11import browserifyDependencies from "@userfrosting/browserify-dependencies" ;
22import Bundler , { MergeRawConfigs , ValidateRawConfig } from "@userfrosting/gulp-bundle-assets" ;
33import { bower as mergeBowerDeps , npm as mergeNpmDeps } from "@userfrosting/merge-package-dependencies" ;
4- import { execSync } from "child_process" ;
4+ import childProcess , { exec as _exec } from "child_process" ;
55import { sync as deleteSync } from "del" ;
66import { config as envConfig } from "dotenv" ;
77import { existsSync , readFileSync , writeFileSync } from "fs" ;
@@ -13,36 +13,86 @@ import prune from "gulp-prune";
1313import rev from "gulp-rev" ;
1414import minifyJs from "gulp-uglify-es" ;
1515import { info } from "gulplog" ;
16- import { normalize as normalisePath , resolve as resolvePath } from "path" ;
16+ import { resolve as resolvePath } from "path" ;
17+ import stripAnsi from "strip-ansi" ;
18+ import { promisify } from "util" ;
19+
20+ // Promisify exec
21+ const exec = promisify ( _exec ) ;
22+
23+ // Path constants
24+ const rootDir = ".." ;
25+ const sprinklesDir = `${ rootDir } /app/sprinkles/` ;
26+ const sprinklesSchemaPath = `${ rootDir } /app/sprinkles.json` ;
27+ const publicAssetsDir = `${ rootDir } /public/assets/` ;
28+ const legacyVendorAssetsGlob = `${ rootDir } /sprinkles/*/assets/vendor/**` ;
29+ const sprinkleBundleFile = "asset-bundles.json" ;
30+ const vendorAssetsDir = `${ rootDir } /app/assets/` ;
31+ const logFile = `${ rootDir } /app/logs/build.log` ;
1732
1833// Load environment variables
1934envConfig ( { path : "../app/.env" } ) ;
2035
2136// Set up logging
22- const doILog = ( process . env . UF_MODE === "dev" ) ;
37+
38+ // Write starting command to log
39+ writeFileSync ( logFile , "\n\n" + process . argv . join ( " " ) + "\n\n" , {
40+ flag : 'a'
41+ } ) ;
42+
43+ // Verbosity
44+ const debug = ( process . env . UF_MODE === "debug" ) ;
45+
46+ // Catch stdout and write to build log
47+ const write = process . stdout . write ;
48+ const w = ( ...args ) => {
49+ process . stdout . write = write ;
50+ process . stdout . write ( ...args ) ;
51+
52+ writeFileSync ( logFile , stripAnsi ( args [ 0 ] ) , {
53+ flag : 'a'
54+ } ) ;
55+
56+ process . stdout . write = w ;
57+ } ;
58+ process . stdout . write = w ;
2359
2460/**
2561 * Prints to stdout with newline when UF_MODE is dev.
26- * @param {any } message Message to log.
62+ * @param {string } message Message to log. If source specified, must be string.
63+ * @param {string } source Message source.
2764 */
2865function Logger ( message , source ) {
29- if ( doILog ) {
66+ const messageLines = message . split ( "\n" ) ;
67+ messageLines . forEach ( msg => {
3068 if ( source )
31- info ( `${ source } : ${ message } ` ) ;
69+ info ( `${ source } : ${ msg } ` ) ;
3270 else
33- info ( message ) ;
34- }
71+ info ( msg ) ;
72+ } ) ;
3573}
3674
37- // Path constants
38- const rootDir = "../" ;
39- const sprinklesDir = rootDir + "app/sprinkles/" ;
40- const sprinklesSchemaPath = rootDir + "app/sprinkles.json" ;
41- const publicAssetsDir = rootDir + "public/assets/" ;
42- const legacyVendorAssetsGlob = rootDir + "sprinkles/*/assets/vendor/**" ;
43- const sprinkleBundleFile = "asset-bundles.json" ;
44- const vendorAssetsDir = rootDir + "app/assets/" ;
45- const buildDirFromVendorAssetsDir = "../../build/" ;
75+ /**
76+ * Runs the provided command and captures output.
77+ * @param {string } cmd Command to execute.
78+ * @param {childProcess.ExecOptions } options Options to pass to `exec`.
79+ */
80+ async function RunCommand ( cmd , options ) {
81+ Logger ( `Running command "${ cmd } "` , "CMD" ) ;
82+
83+ try {
84+ const result = await exec ( cmd , options ) ;
85+ if ( result . stdout ) Logger ( result . stdout , `CMD> ${ cmd } ` ) ;
86+ if ( result . stderr ) Logger ( result . stderr , `CMD> ${ cmd } ` ) ;
87+ } catch ( e ) {
88+ if ( e . stdout ) Logger ( e . stdout , `CMD> ${ cmd } ` ) ;
89+ if ( e . stderr ) Logger ( e . stderr , `CMD> ${ cmd } ` ) ;
90+ Logger ( `Command "${ cmd } " has completed with an error` , "CMD" ) ;
91+ throw e ;
92+ }
93+
94+ Logger ( `Command "${ cmd } " has completed successfully` , "CMD" ) ;
95+ }
4696
4797// Load sprinkles
4898let sprinkles ;
@@ -84,29 +134,28 @@ export async function assetsInstall() {
84134 private : true
85135 } ;
86136 Logger ( "Collating dependencies..." ) ;
87- const pkg = mergeNpmDeps ( npmTemplate , npmPaths , vendorAssetsDir , doILog ) ;
137+ const pkg = mergeNpmDeps ( npmTemplate , npmPaths , vendorAssetsDir , true ) ;
88138 Logger ( "Dependency collation complete." ) ;
89139
140+ Logger ( "Using npm from PATH variable" ) ;
141+
90142 // Remove any existing unneeded dependencies
91- Logger ( "Running npm prune (using npm from PATH)" ) ;
92- execSync ( "npm prune" , {
93- cwd : vendorAssetsDir ,
94- stdio : doILog ? "inherit" : ""
143+ Logger ( "Removing extraneous dependencies" ) ;
144+ await RunCommand ( "npm prune" , {
145+ cwd : vendorAssetsDir
95146 } ) ;
96147
97148 // Perform installation
98- Logger ( "Running npm install (using npm from PATH)" ) ;
99- execSync ( "npm install" , {
100- cwd : vendorAssetsDir ,
101- stdio : doILog ? "inherit" : ""
149+ Logger ( "Installing dependencies" ) ;
150+ await RunCommand ( "npm install" , {
151+ cwd : vendorAssetsDir
102152 } ) ;
103153
104154 // Conduct audit
105- Logger ( "Running npm audit (using npm from PATH) " ) ;
155+ Logger ( "Running audit" ) ;
106156 try {
107- execSync ( "npm audit" , {
108- cwd : vendorAssetsDir ,
109- stdio : doILog ? "inherit" : ""
157+ await RunCommand ( "npm audit" , {
158+ cwd : vendorAssetsDir
110159 } ) ;
111160 }
112161 catch {
@@ -156,23 +205,22 @@ export async function assetsInstall() {
156205 name : "uf-vendor-assets"
157206 } ;
158207 Logger ( "Collating dependencies..." ) ;
159- mergeBowerDeps ( bowerTemplate , bowerPaths , vendorAssetsDir , doILog ) ;
208+ mergeBowerDeps ( bowerTemplate , bowerPaths , vendorAssetsDir , true ) ;
160209 Logger ( "Dependency collation complete." ) ;
161210
162211 // Perform installation
163- Logger ( "Running bower install -q --allow-root " ) ;
212+ Logger ( "Installed dependencies " ) ;
164213 // --allow-root stops bower from complaining about being in 'sudo' in various situations
165- execSync ( normalisePath ( buildDirFromVendorAssetsDir + "node_modules/.bin/bower" ) + " install -q --allow-root" , {
166- cwd : vendorAssetsDir ,
167- stdio : doILog ? "inherit" : ""
214+ await RunCommand ( "bower install -q --allow-root" , {
215+ cwd : vendorAssetsDir
168216 } ) ;
217+
169218
170219 // Prune any unnecessary dependencies
171- Logger ( "Running bower prune -q --allow-root " ) ;
220+ Logger ( "Removing extraneous dependencies " ) ;
172221 // --allow-root stops bower from complaining about being in 'sudo' in various situations
173- execSync ( "bower prune -q --allow-root" , {
174- cwd : vendorAssetsDir ,
175- stdio : doILog ? "inherit" : ""
222+ await RunCommand ( "bower prune -q --allow-root" , {
223+ cwd : vendorAssetsDir
176224 } ) ;
177225 }
178226 else {
@@ -222,10 +270,10 @@ export function bundle() {
222270 let fileContent ;
223271 try {
224272 fileContent = readFileSync ( sprinklesDir + sprinkle + "/" + sprinkleBundleFile ) ;
225- Logger ( ` Read '${ sprinkleBundleFile } '.` ) ;
273+ Logger ( `Read '${ sprinkleBundleFile } '.` , sprinkle ) ;
226274 }
227275 catch ( error ) {
228- Logger ( ` No '${ sprinkleBundleFile } ' detected, or can't be read.` ) ;
276+ Logger ( `No '${ sprinkleBundleFile } ' detected, or can't be read.` , sprinkle ) ;
229277 continue ;
230278 }
231279
@@ -235,10 +283,10 @@ export function bundle() {
235283 rawConfig = JSON . parse ( fileContent ) ;
236284 ValidateRawConfig ( rawConfig ) ;
237285 rawConfigs . push ( rawConfig ) ;
238- Logger ( " Asset bundles validated and loaded." ) ;
286+ Logger ( "Asset bundles validated and loaded." , sprinkle ) ;
239287 }
240288 catch ( error ) {
241- Logger ( " Asset bundle is invalid." ) ;
289+ Logger ( "Asset bundle is invalid." , sprinkle ) ;
242290 throw error ;
243291 }
244292 }
@@ -260,9 +308,8 @@ export function bundle() {
260308 // Set base path for bundle resources to align with virtual paths
261309 rawConfig . BundlesVirtualBasePath = "./assets/" ;
262310
263- // Bundle results callback
264311 /**
265- *
312+ * Bundle results callback.
266313 * @param {Map<string, any[] } results
267314 */
268315 function bundleResults ( results ) {
@@ -321,7 +368,7 @@ export function bundle() {
321368 // Logger adapter
322369 function LoggerAdapter ( message , loglevel ) {
323370 // Normal level and above
324- if ( loglevel > 0 ) {
371+ if ( loglevel > 0 || debug ) {
325372 Logger ( message , "gulp-bundle-assets" ) ;
326373 }
327374 }
0 commit comments