Skip to content

Commit 64144f5

Browse files
committed
added multiple script targets and require loading for .js files.
1 parent 0735b72 commit 64144f5

File tree

4 files changed

+313
-13
lines changed

4 files changed

+313
-13
lines changed

src/runner.js

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,69 @@ var stripJsonComments = require('strip-json-comments');
1010
*
1111
* Two command line arguments must be supplied:
1212
* ```
13-
* (string) filePath - The path to a JSON formatted file.
13+
* (string|string[]) filePathOrArray - The path or array of paths to a JSON or JS CJS formatted file.
1414
* (string) scriptEntry - A entry path separated by `.` relative to the root of the JSON file that is an `Array`.
1515
* (string) messagePrepend - An optional message to prepend instead of the default: `typhonjs-npm-scripts-runner`.
1616
* ```
1717
*/
18-
module.exports.run = function(filePath, scriptEntry, messagePrepend)
18+
module.exports.run = function(filePathOrArray, scriptEntry, messagePrepend)
1919
{
2020
messagePrepend = typeof messagePrepend === 'string' ? messagePrepend : 'typhonjs-npm-scripts-runner';
2121

22-
if (typeof filePath !== 'string')
22+
if (typeof filePathOrArray !== 'string' && !Array.isArray(filePathOrArray))
2323
{
24-
throw new TypeError(messagePrepend + ' error: filePath is not a `string`.');
24+
throw new TypeError(messagePrepend + " error: 'filePathOrArray' is not a 'string' or an 'array'.");
2525
}
2626

2727
if (typeof scriptEntry !== 'string')
2828
{
29-
throw new TypeError(messagePrepend + ' error: scriptEntry is not a `string`.');
29+
throw new TypeError(messagePrepend + " error: 'scriptEntry' is not a 'string'.");
30+
}
31+
32+
if (Array.isArray(filePathOrArray))
33+
{
34+
var errMessages = '';
35+
36+
for (var cntr = 0; cntr < filePathOrArray.length; cntr++)
37+
{
38+
if (typeof filePathOrArray[cntr] !== 'string')
39+
{
40+
throw new TypeError(messagePrepend + " error: 'filePathOrArray[" + cntr + "]: '" + filePathOrArray[cntr] +
41+
"' is not a 'string'.");
42+
}
43+
44+
try
45+
{
46+
// If running scripts completes successfully quit early.
47+
if (runImpl(filePathOrArray[cntr], scriptEntry, messagePrepend)) { return; }
48+
}
49+
catch (err)
50+
{
51+
errMessages += err.message +'\n';
52+
}
53+
}
54+
55+
// Script runner failed to execute.
56+
throw new Error(messagePrepend + " failed to execute any scripts: \n" + errMessages);
57+
}
58+
else
59+
{
60+
runImpl(filePathOrArray, scriptEntry, messagePrepend);
3061
}
62+
};
3163

64+
/**
65+
* run -- Provides a NPM module to run commands / scripts defined in an indexed JSON file via `child_process->execSync`.
66+
*
67+
* Two command line arguments must be supplied:
68+
* ```
69+
* (string) filePath - The path to a JSON formatted file.
70+
* (string) scriptEntry - A entry path separated by `.` relative to the root of the JSON file that is an `Array`.
71+
* (string) messagePrepend - An optional message to prepend instead of the default: `typhonjs-npm-scripts-runner`.
72+
* ```
73+
*/
74+
function runImpl(filePath, scriptEntry, messagePrepend)
75+
{
3276
var relativeFilePath = path.resolve(process.cwd(), filePath);
3377

3478
// Verify that `fileName` exists.
@@ -45,17 +89,30 @@ module.exports.run = function(filePath, scriptEntry, messagePrepend)
4589
throw new Error(messagePrepend + ' error: ' + err);
4690
}
4791

48-
// Load `filePath` as JSON stripping any comments.
4992
var configInfo;
5093

51-
/* istanbul ignore next */
52-
try
94+
// Load `filePath` by requiring if extension name ends in `.js` or as a JSON object stripping any comments.
95+
if (path.extname(relativeFilePath) === '.js')
5396
{
54-
configInfo = JSON.parse(stripJsonComments(fs.readFileSync(relativeFilePath, 'utf-8')));
97+
try
98+
{
99+
configInfo = require(relativeFilePath);
100+
}
101+
catch (err)
102+
{
103+
throw new Error(messagePrepend + ' error: ' + err);
104+
}
55105
}
56-
catch (err)
106+
else
57107
{
58-
throw new Error(messagePrepend + ' error: ' + err);
108+
try
109+
{
110+
configInfo = JSON.parse(stripJsonComments(fs.readFileSync(relativeFilePath, 'utf-8')));
111+
}
112+
catch (err)
113+
{
114+
throw new Error(messagePrepend + ' error: ' + err);
115+
}
59116
}
60117

61118
var entries = scriptEntry.split('.');
@@ -109,5 +166,7 @@ module.exports.run = function(filePath, scriptEntry, messagePrepend)
109166
process.stdout.write(messagePrepend + ' executing: ' + exec + '\n');
110167
cp.execSync(exec, { stdio: 'inherit' });
111168
}
112-
};
169+
170+
return true;
171+
}
113172

test/data/.scriptrc.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Script runner config file can be CJS formatted.
3+
*
4+
* You can provide comments in script runner data files.
5+
*
6+
* The entry below is used in testing and used in `./test/scripts/test.js`.
7+
*/
8+
module.exports =
9+
{
10+
"test":
11+
{
12+
"data":
13+
{
14+
"scripts":
15+
[
16+
"cp ./test/data/empty.js ./test/fixture/empty2.js",
17+
"cp ./test/data/empty.js ./test/fixture/empty3.js"
18+
]
19+
}
20+
}
21+
};

test/data/.scriptrc2

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Script runner config file should be JSON formatted.
3+
*
4+
* You can provide comments in script runner data files.
5+
*
6+
* The entry below is used in testing and used in `./test/scripts/test.js` to determine file array execution. This
7+
* config file should never be reached as part of a file array where a previous file satisfies running the script.
8+
*/
9+
{
10+
"test":
11+
{
12+
"data":
13+
{
14+
"scripts":
15+
[
16+
"cp ./test/data/empty.js ./test/fixture/SHOULD_NOT_EXIST.js"
17+
]
18+
}
19+
}
20+
}

test/scripts/test.js

Lines changed: 201 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,23 @@ try { runner.run('./test/data/.scriptrc', 'bogus.data'); }
4040
catch(err) { thrown = true; }
4141
if (!thrown) { throw new Error('typhonjs-npm-scripts-runner test error: bad entries did not throw exception'); }
4242

43+
// Verify that runner throws exception with bad file array.
44+
thrown = false;
45+
try { runner.run([false, './test/data/.scriptrc'], 'test.data.scripts'); }
46+
catch(err) { thrown = true; }
47+
if (!thrown) { throw new Error('typhonjs-npm-scripts-runner test error: bad file array did not throw exception'); }
48+
49+
// Verify that runner throws exception with bad file array paths.
50+
thrown = false;
51+
try { runner.run(['./test/data/.badfile1', './test/data/.badfile2'], 'test.data.scripts'); }
52+
catch(err) { thrown = true; }
53+
if (!thrown) { throw new Error('typhonjs-npm-scripts-runner test error: bad file array did not throw exception'); }
54+
55+
// ------------------------------------------------------------------------------------------------------------------
56+
57+
// Bare script treated as JSON.
58+
console.log('Testing bare script treated as JSON:');
59+
4360
// Actually run the test of copying files.
4461
runner.run('./test/data/.scriptrc', 'test.data.scripts');
4562

@@ -63,7 +80,190 @@ catch (err)
6380
throw new Error('typhonjs-npm-scripts-runner test error: ' + err);
6481
}
6582

83+
// -------------------------
84+
85+
// Test the message prepend
86+
console.log('\nTesting bare script message prepend:');
87+
88+
runner.run('./test/data/.scriptrc', 'test.data.scripts', 'A custom message -');
89+
90+
fs.emptyDirSync('./test/fixture');
91+
92+
// -------------------------
93+
94+
// Run again with file array with bad first entry
95+
console.log('\nTesting bad file array first entry:');
96+
97+
// Actually run the test of copying files.
98+
runner.run(['./test/data/.badfile1', './test/data/.scriptrc', './test/data/.badfile2'], 'test.data.scripts');
99+
100+
// Verify that two files were copied.
101+
try
102+
{
103+
// Verify that `./test/fixture/empty2.json` exists.
104+
if (!fs.statSync('./test/fixture/empty2.js').isFile())
105+
{
106+
throw new Error('`./test/fixture/empty2.js` is not a file.');
107+
}
108+
109+
// Verify that `./test/fixture/empty3.json` exists.
110+
if (!fs.statSync('./test/fixture/empty2.js').isFile())
111+
{
112+
throw new Error('`./test/fixture/empty2.js` is not a file.');
113+
}
114+
}
115+
catch (err)
116+
{
117+
throw new Error('typhonjs-npm-scripts-runner test error: ' + err);
118+
}
119+
120+
// -------------------------
121+
66122
// Test the message prepend
123+
console.log('\nTesting message prepend:');
124+
67125
runner.run('./test/data/.scriptrc', 'test.data.scripts', 'A custom message -');
68126

69-
fs.emptyDirSync('./test/fixture');
127+
fs.emptyDirSync('./test/fixture');
128+
129+
// ------------------------------------------------------------------------------------------------------------------
130+
131+
// CJS JS script required.
132+
console.log('\nTesting CJS scriptrc.js require:');
133+
134+
// Actually run the test of copying files.
135+
runner.run('./test/data/.scriptrc.js', 'test.data.scripts');
136+
137+
// Verify that two files were copied.
138+
try
139+
{
140+
// Verify that `./test/fixture/empty2.json` exists.
141+
if (!fs.statSync('./test/fixture/empty2.js').isFile())
142+
{
143+
throw new Error('`./test/fixture/empty2.js` is not a file.');
144+
}
145+
146+
// Verify that `./test/fixture/empty3.json` exists.
147+
if (!fs.statSync('./test/fixture/empty2.js').isFile())
148+
{
149+
throw new Error('`./test/fixture/empty2.js` is not a file.');
150+
}
151+
}
152+
catch (err)
153+
{
154+
throw new Error('typhonjs-npm-scripts-runner test error: ' + err);
155+
}
156+
157+
// -------------------------
158+
159+
// Test the message prepend
160+
console.log('\nTesting CJS scriptrc.js require - message prepend:');
161+
162+
runner.run('./test/data/.scriptrc.js', 'test.data.scripts', 'A custom message -');
163+
164+
fs.emptyDirSync('./test/fixture');
165+
166+
// -------------------------
167+
168+
// Run again with file array with bad first entry
169+
console.log('\nTesting CJS bad first entry for file array:');
170+
171+
// Actually run the test of copying files.
172+
runner.run(['./test/data/.badfile1.js', './test/data/.scriptrc.js', './test/data/.badfile2.js'], 'test.data.scripts');
173+
174+
// Verify that two files were copied.
175+
try
176+
{
177+
// Verify that `./test/fixture/empty2.json` exists.
178+
if (!fs.statSync('./test/fixture/empty2.js').isFile())
179+
{
180+
throw new Error('`./test/fixture/empty2.js` is not a file.');
181+
}
182+
183+
// Verify that `./test/fixture/empty3.json` exists.
184+
if (!fs.statSync('./test/fixture/empty2.js').isFile())
185+
{
186+
throw new Error('`./test/fixture/empty2.js` is not a file.');
187+
}
188+
}
189+
catch (err)
190+
{
191+
throw new Error('typhonjs-npm-scripts-runner test error: ' + err);
192+
}
193+
194+
// -------------------------
195+
196+
// Test the message prepend
197+
console.log('\nTesting CJS prepend message:');
198+
199+
runner.run('./test/data/.scriptrc.js', 'test.data.scripts', 'A custom message -');
200+
201+
fs.emptyDirSync('./test/fixture');
202+
203+
// -------------------------
204+
205+
// Test that multiple file array only executes first matching file.
206+
console.log('\nTesting JSON file array only executes first matching script:');
207+
208+
// Actually run the test of copying files.
209+
runner.run(['./test/data/.scriptrc', './test/data/.scriptrc2'], 'test.data.scripts');
210+
211+
// Verify that two files were copied and that 'scriptrc2' is not executed.
212+
try
213+
{
214+
// Verify that `./test/fixture/empty2.json` exists.
215+
if (!fs.statSync('./test/fixture/empty2.js').isFile())
216+
{
217+
throw new Error('`./test/fixture/empty2.js` is not a file.');
218+
}
219+
220+
// Verify that `./test/fixture/empty3.json` exists.
221+
if (!fs.statSync('./test/fixture/empty2.js').isFile())
222+
{
223+
throw new Error('`./test/fixture/empty2.js` is not a file.');
224+
}
225+
226+
// Verify that `./test/fixture/empty3.json` exists.
227+
if (fs.existsSync('./test/fixture/SHOULD_NOT_EXIST.js'))
228+
{
229+
throw new Error('`./test/fixture/SHOULD_NOT_EXIST.js` is was copied / scriptrc2 was incorrectly executed.');
230+
}
231+
}
232+
catch (err)
233+
{
234+
throw new Error('typhonjs-npm-scripts-runner test error: ' + err);
235+
}
236+
237+
// -------------------------
238+
239+
// Test that multiple file array only executes first matching file.
240+
console.log('\nTesting CJS file array only executes first matching script:');
241+
242+
// Actually run the test of copying files.
243+
runner.run(['./test/data/.scriptrc.js', './test/data/.scriptrc2'], 'test.data.scripts');
244+
245+
// Verify that two files were copied and that 'scriptrc2' is not executed.
246+
try
247+
{
248+
// Verify that `./test/fixture/empty2.json` exists.
249+
if (!fs.statSync('./test/fixture/empty2.js').isFile())
250+
{
251+
throw new Error('`./test/fixture/empty2.js` is not a file.');
252+
}
253+
254+
// Verify that `./test/fixture/empty3.json` exists.
255+
if (!fs.statSync('./test/fixture/empty2.js').isFile())
256+
{
257+
throw new Error('`./test/fixture/empty2.js` is not a file.');
258+
}
259+
260+
// Verify that `./test/fixture/empty3.json` exists.
261+
if (fs.existsSync('./test/fixture/SHOULD_NOT_EXIST.js'))
262+
{
263+
throw new Error('`./test/fixture/SHOULD_NOT_EXIST.js` is was copied / scriptrc2 was incorrectly executed.');
264+
}
265+
}
266+
catch (err)
267+
{
268+
throw new Error('typhonjs-npm-scripts-runner test error: ' + err);
269+
}

0 commit comments

Comments
 (0)