@joystick.js/cli-canary 0.0.0-canary.99 → 1.0.0-beta.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{_package.json → canary.json} +2 -3
- package/dist/functions/index.js +16 -11
- package/dist/functions/start/index.js +0 -19
- package/dist/functions/test/index.js +2 -1
- package/dist/lib/build/browserPathExclusions.js +2 -1
- package/dist/lib/build/buildFiles.js +12 -4
- package/dist/lib/build/buildPlugins.js +19 -5
- package/dist/lib/build/nodePaths.js +1 -0
- package/dist/lib/build/replaceExamples.js +13 -0
- package/dist/lib/checkIfPortOccupied.js +27 -0
- package/dist/lib/dev/getFilesToBuild.js +1 -1
- package/dist/lib/dev/hmrServer.js +66 -0
- package/dist/lib/dev/index.js +132 -48
- package/dist/lib/dev/loadSettings.js +10 -4
- package/dist/lib/dev/runTests.js +47 -15
- package/dist/lib/dev/startApp.js +6 -4
- package/dist/lib/dev/tests.config.js +12 -0
- package/dist/lib/regexes.js +2 -0
- package/package.json +2 -1
- package/src/functions/index.js +15 -10
- package/src/functions/start/index.js +0 -656
- package/src/functions/test/index.js +1 -0
- package/src/lib/build/browserPathExclusions.js +2 -1
- package/src/lib/build/buildFiles.js +13 -4
- package/src/lib/build/buildPlugins.js +31 -14
- package/src/lib/build/nodePaths.js +1 -0
- package/src/lib/build/replaceExamples.js +11 -0
- package/src/lib/build/setComponentId.js +2 -2
- package/src/lib/checkIfPortOccupied.js +29 -0
- package/src/lib/dev/getFilesToBuild.js +1 -1
- package/src/lib/dev/hmrServer.js +78 -0
- package/src/lib/dev/index.js +146 -60
- package/src/lib/dev/loadSettings.js +12 -4
- package/src/lib/dev/runTests.js +67 -18
- package/src/lib/dev/startApp.js +6 -4
- package/src/lib/dev/tests.config.js +9 -0
- package/src/lib/regexes.js +1 -0
package/dist/lib/dev/index.js
CHANGED
|
@@ -19,6 +19,9 @@ import { SETTINGS_FILE_NAME_REGEX } from "../regexes.js";
|
|
|
19
19
|
import getCodependenciesForFile from "./getCodependenciesForFile.js";
|
|
20
20
|
import removeDeletedDependenciesFromMap from "../build/removeDeletedDependenciesFromMap.js";
|
|
21
21
|
import chalk from "chalk";
|
|
22
|
+
import checkIfPortOccupied from "../checkIfPortOccupied.js";
|
|
23
|
+
import { killPortProcess } from "kill-port-process";
|
|
24
|
+
const processIds = [];
|
|
22
25
|
const getDatabaseProcessIds = () => {
|
|
23
26
|
try {
|
|
24
27
|
const databaseProcessIds = [];
|
|
@@ -43,7 +46,7 @@ const getDatabaseProcessIds = () => {
|
|
|
43
46
|
throw new Error(`[dev.getDatabaseProcessIds] ${exception.message}`);
|
|
44
47
|
}
|
|
45
48
|
};
|
|
46
|
-
const handleSignalEvents = (
|
|
49
|
+
const handleSignalEvents = (processIds2 = [], nodeMajorVersion = 0, __dirname = "") => {
|
|
47
50
|
try {
|
|
48
51
|
const execArgv = ["--no-warnings"];
|
|
49
52
|
if (nodeMajorVersion < 19) {
|
|
@@ -62,14 +65,15 @@ const handleSignalEvents = (processIds = [], nodeMajorVersion = 0, __dirname = "
|
|
|
62
65
|
silent: true
|
|
63
66
|
}
|
|
64
67
|
);
|
|
68
|
+
process.cleanupProcess = cleanupProcess;
|
|
65
69
|
process.on("SIGINT", async () => {
|
|
66
70
|
const databaseProcessIds = getDatabaseProcessIds();
|
|
67
|
-
cleanupProcess.send(JSON.stringify({ processIds: [...
|
|
71
|
+
cleanupProcess.send(JSON.stringify({ processIds: [...processIds2, ...databaseProcessIds] }));
|
|
68
72
|
process.exit();
|
|
69
73
|
});
|
|
70
74
|
process.on("SIGTERM", async () => {
|
|
71
75
|
const databaseProcessIds = getDatabaseProcessIds();
|
|
72
|
-
cleanupProcess.send(JSON.stringify({ processIds: [...
|
|
76
|
+
cleanupProcess.send(JSON.stringify({ processIds: [...processIds2, ...databaseProcessIds] }));
|
|
73
77
|
process.exit();
|
|
74
78
|
});
|
|
75
79
|
} catch (exception) {
|
|
@@ -143,7 +147,7 @@ const handleServerProcessMessages = () => {
|
|
|
143
147
|
throw new Error(`[dev.handleServerProcessMessages] ${exception.message}`);
|
|
144
148
|
}
|
|
145
149
|
};
|
|
146
|
-
const handleServerProcessSTDIO = () => {
|
|
150
|
+
const handleServerProcessSTDIO = (options = {}) => {
|
|
147
151
|
try {
|
|
148
152
|
if (process.serverProcess) {
|
|
149
153
|
process.serverProcess.on("error", (error) => {
|
|
@@ -151,7 +155,7 @@ const handleServerProcessSTDIO = () => {
|
|
|
151
155
|
});
|
|
152
156
|
process.serverProcess.stdout.on("data", (data) => {
|
|
153
157
|
const message = data.toString();
|
|
154
|
-
if (message && message.includes("App running at:")) {
|
|
158
|
+
if (message && message.includes("App running at:") && !options?.watch) {
|
|
155
159
|
process.loader.stable(message);
|
|
156
160
|
} else {
|
|
157
161
|
if (message && !message.includes("BUILD_ERROR")) {
|
|
@@ -171,15 +175,37 @@ const handleServerProcessSTDIO = () => {
|
|
|
171
175
|
throw new Error(`[dev.handleServerProcessSTDIO] ${exception.message}`);
|
|
172
176
|
}
|
|
173
177
|
};
|
|
178
|
+
const handleDeletePath = (context = {}, path2 = "", options = {}) => {
|
|
179
|
+
try {
|
|
180
|
+
if (context?.isDeletingPath) {
|
|
181
|
+
if (context.isExistingPathInBuild) {
|
|
182
|
+
const pathToUnlink = `./.joystick/build/${path2}`;
|
|
183
|
+
const stats = fs.lstatSync(pathToUnlink);
|
|
184
|
+
if (stats.isDirectory()) {
|
|
185
|
+
fs.rmdirSync(pathToUnlink, { recursive: true });
|
|
186
|
+
}
|
|
187
|
+
if (stats.isFile()) {
|
|
188
|
+
fs.unlinkSync(pathToUnlink);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (context.isUIUpdate) {
|
|
192
|
+
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
193
|
+
} else {
|
|
194
|
+
handleRestartApplicationProcess(options);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
} catch (exception) {
|
|
198
|
+
throw new Error(`[dev.handleDeletePath] ${exception.message}`);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
174
201
|
const handleAddOrChangeFile = async (context = {}, path2 = "", options = {}) => {
|
|
175
202
|
try {
|
|
176
203
|
if (context.isAddingOrChangingFile) {
|
|
177
204
|
const codependencies = await getCodependenciesForFile(path2);
|
|
178
|
-
const fileResults = await buildFiles(
|
|
179
|
-
[path2, ...codependencies?.existing || []],
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
);
|
|
205
|
+
const fileResults = await buildFiles({
|
|
206
|
+
files: [path2, ...codependencies?.existing || []],
|
|
207
|
+
environment: process.env.NODE_ENV
|
|
208
|
+
});
|
|
183
209
|
const fileResultsHaveErrors = fileResults.filter((result) => !!result).map(({ success }) => success).includes(false);
|
|
184
210
|
removeDeletedDependenciesFromMap(codependencies.deleted);
|
|
185
211
|
if (process.serverProcess && fileResultsHaveErrors) {
|
|
@@ -204,6 +230,7 @@ const handleAddOrChangeFile = async (context = {}, path2 = "", options = {}) =>
|
|
|
204
230
|
}
|
|
205
231
|
}
|
|
206
232
|
} catch (exception) {
|
|
233
|
+
console.warn(exception);
|
|
207
234
|
throw new Error(`[dev.handleAddOrChangeFile] ${exception.message}`);
|
|
208
235
|
}
|
|
209
236
|
};
|
|
@@ -237,7 +264,7 @@ const handleCopyFile = (context = {}, path2 = "", options = {}) => {
|
|
|
237
264
|
};
|
|
238
265
|
const handleCopyDirectory = (context = {}, path2 = "", options = {}) => {
|
|
239
266
|
try {
|
|
240
|
-
if (context.isFileToCopy && context.isDirectory && !context.
|
|
267
|
+
if (context.isFileToCopy && context.isDirectory && !context.isExistingPathInBuild) {
|
|
241
268
|
fs.mkdirSync(`./.joystick/build/${path2}`);
|
|
242
269
|
if (context.isUIUpdate) {
|
|
243
270
|
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
@@ -252,17 +279,11 @@ const handleCopyDirectory = (context = {}, path2 = "", options = {}) => {
|
|
|
252
279
|
const handleRestartApplicationProcess = async (options = {}) => {
|
|
253
280
|
try {
|
|
254
281
|
if (process.serverProcess && process.serverProcess.pid) {
|
|
255
|
-
process.loader.text("Restarting app...");
|
|
256
282
|
process.serverProcess.kill();
|
|
257
|
-
await
|
|
258
|
-
nodeMajorVersion: options?.nodeMajorVersion,
|
|
259
|
-
port: options?.port,
|
|
260
|
-
sessionsBeforeHMRUpdate: options?.sessionsBeforeHMRUpdate
|
|
261
|
-
});
|
|
283
|
+
await handleStartAppServer(options);
|
|
262
284
|
return Promise.resolve();
|
|
263
285
|
}
|
|
264
|
-
|
|
265
|
-
startApplicationProcess();
|
|
286
|
+
await handleStartAppServer(options);
|
|
266
287
|
if (!process.hmrProcess) {
|
|
267
288
|
startHMR();
|
|
268
289
|
}
|
|
@@ -270,19 +291,43 @@ const handleRestartApplicationProcess = async (options = {}) => {
|
|
|
270
291
|
throw new Error(`[dev.handleRestartApplicationProcess] ${exception.message}`);
|
|
271
292
|
}
|
|
272
293
|
};
|
|
273
|
-
const
|
|
294
|
+
const handleStartAppServer = async (options = {}) => {
|
|
295
|
+
try {
|
|
296
|
+
const serverProcess = await startApp({
|
|
297
|
+
watch: options?.watch,
|
|
298
|
+
nodeMajorVersion: options?.nodeMajorVersion,
|
|
299
|
+
port: options?.port,
|
|
300
|
+
sessionsBeforeHMRUpdate: options?.sessionsBeforeHMRUpdate
|
|
301
|
+
});
|
|
302
|
+
if (serverProcess) {
|
|
303
|
+
processIds.push(serverProcess.pid);
|
|
304
|
+
process.serverProcess = serverProcess;
|
|
305
|
+
handleServerProcessSTDIO(options);
|
|
306
|
+
handleServerProcessMessages(options);
|
|
307
|
+
}
|
|
308
|
+
} catch (exception) {
|
|
309
|
+
console.warn(exception);
|
|
310
|
+
throw new Error(`[dev.handleStartAppServer] ${exception.message}`);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
const handleNotifyHMRClients = async (indexHTMLChanged = false) => {
|
|
274
314
|
try {
|
|
275
315
|
if (process.hmrProcess) {
|
|
276
|
-
const
|
|
316
|
+
const databaseProcessIds = getDatabaseProcessIds();
|
|
317
|
+
const settings = await loadSettings({
|
|
318
|
+
environment: process.env.NODE_ENV,
|
|
319
|
+
processIds: [...processIds, ...databaseProcessIds]
|
|
320
|
+
});
|
|
277
321
|
process.hmrProcess.send(
|
|
278
322
|
JSON.stringify({
|
|
279
323
|
type: "RESTART_SERVER",
|
|
280
|
-
settings,
|
|
324
|
+
settings: settings.parsed,
|
|
281
325
|
indexHTMLChanged
|
|
282
326
|
})
|
|
283
327
|
);
|
|
284
328
|
}
|
|
285
329
|
} catch (exception) {
|
|
330
|
+
console.warn(exception);
|
|
286
331
|
throw new Error(`[dev.handleNotifyHMRClients] ${exception.message}`);
|
|
287
332
|
}
|
|
288
333
|
};
|
|
@@ -292,27 +337,31 @@ const getWatchChangeContext = (event = "", path2 = "") => {
|
|
|
292
337
|
const isUIPath = path2?.includes("ui/") || path2 === "index.css" || isHTMLUpdate;
|
|
293
338
|
const isUIUpdate = process.hmrProcess && process.hmrProcess.hasConnections && isUIPath || false;
|
|
294
339
|
const isSettingsUpdate = path2?.match(SETTINGS_FILE_NAME_REGEX)?.length > 0;
|
|
295
|
-
const
|
|
296
|
-
const
|
|
297
|
-
const
|
|
298
|
-
const
|
|
299
|
-
const
|
|
340
|
+
const pathExists = fs.existsSync(path2);
|
|
341
|
+
const isDirectory = pathExists && fs.statSync(path2).isDirectory();
|
|
342
|
+
const isFile = pathExists && fs.statSync(path2).isFile();
|
|
343
|
+
const isExistingPathInSource = isDirectory && pathExists;
|
|
344
|
+
const isExistingPathInBuild = !!fs.existsSync(`./.joystick/build/${path2}`);
|
|
345
|
+
const isAddDirectory = event === "addDir" && isExistingPathInSource && !isExistingPathInBuild;
|
|
300
346
|
const isFileToCopy = !!filesToCopy.find((fileToCopy) => fileToCopy.path === path2);
|
|
301
|
-
const isExistingFileInSource = isFile &&
|
|
302
|
-
const isAddingOrChangingFile =
|
|
347
|
+
const isExistingFileInSource = isFile && pathExists;
|
|
348
|
+
const isAddingOrChangingFile = ["add", "change"].includes(event) && isExistingFileInSource;
|
|
349
|
+
const isDeletingPath = ["unlink", "unlinkDir"].includes(event);
|
|
303
350
|
return {
|
|
351
|
+
pathExists,
|
|
304
352
|
isHTMLUpdate,
|
|
305
353
|
isUIPath,
|
|
306
354
|
isUIUpdate,
|
|
307
355
|
isSettingsUpdate,
|
|
308
356
|
isDirectory,
|
|
309
357
|
isFile,
|
|
310
|
-
|
|
311
|
-
|
|
358
|
+
isExistingPathInSource,
|
|
359
|
+
isExistingPathInBuild,
|
|
312
360
|
isAddDirectory,
|
|
313
361
|
isFileToCopy,
|
|
314
362
|
isExistingFileInSource,
|
|
315
|
-
isAddingOrChangingFile
|
|
363
|
+
isAddingOrChangingFile,
|
|
364
|
+
isDeletingPath
|
|
316
365
|
};
|
|
317
366
|
} catch (exception) {
|
|
318
367
|
throw new Error(`[dev.getWatchChangeContext] ${exception.message}`);
|
|
@@ -326,16 +375,20 @@ const startFileWatcher = (options = {}) => {
|
|
|
326
375
|
);
|
|
327
376
|
watcher.on("all", async (event, path2) => {
|
|
328
377
|
checkForRequiredFiles();
|
|
329
|
-
|
|
378
|
+
if (!options?.watch) {
|
|
379
|
+
process.loader.text("Rebuilding app...");
|
|
380
|
+
}
|
|
330
381
|
const watchChangeContext = getWatchChangeContext(event, path2);
|
|
331
382
|
handleCopyDirectory(watchChangeContext, path2, options);
|
|
332
383
|
handleCopyFile(watchChangeContext, path2, options);
|
|
333
384
|
handleAddDirectory(watchChangeContext, path2, options);
|
|
334
385
|
await handleAddOrChangeFile(watchChangeContext, path2, options);
|
|
386
|
+
await handleDeletePath(watchChangeContext, path2, options);
|
|
335
387
|
if (watchChangeContext?.isSettingsUpdate) {
|
|
388
|
+
const databaseProcessIds = getDatabaseProcessIds();
|
|
336
389
|
await loadSettings({
|
|
337
390
|
environment: options.environment,
|
|
338
|
-
|
|
391
|
+
processIds: [...processIds, ...databaseProcessIds]
|
|
339
392
|
});
|
|
340
393
|
}
|
|
341
394
|
});
|
|
@@ -453,6 +506,16 @@ const warnInvalidJoystickEnvironment = () => {
|
|
|
453
506
|
throw new Error(`[dev.warnInvalidJoystickEnvironment] ${exception.message}`);
|
|
454
507
|
}
|
|
455
508
|
};
|
|
509
|
+
const handleCleanup = () => {
|
|
510
|
+
try {
|
|
511
|
+
if (process.cleanupProcess) {
|
|
512
|
+
const databaseProcessIds = getDatabaseProcessIds();
|
|
513
|
+
process.cleanupProcess.send(JSON.stringify({ processIds: [...processIds, ...databaseProcessIds] }));
|
|
514
|
+
}
|
|
515
|
+
} catch (exception) {
|
|
516
|
+
throw new Error(`[actionName.handleCleanup] ${exception.message}`);
|
|
517
|
+
}
|
|
518
|
+
};
|
|
456
519
|
const validateOptions = (options) => {
|
|
457
520
|
try {
|
|
458
521
|
if (!options)
|
|
@@ -466,6 +529,18 @@ const validateOptions = (options) => {
|
|
|
466
529
|
const dev = async (options, { resolve, reject }) => {
|
|
467
530
|
try {
|
|
468
531
|
validateOptions(options);
|
|
532
|
+
const port = parseInt(options?.port || 2600, 10);
|
|
533
|
+
const appPortOccupied = await checkIfPortOccupied(port);
|
|
534
|
+
const hmrPortOccupied = await checkIfPortOccupied(port + 1);
|
|
535
|
+
if (appPortOccupied) {
|
|
536
|
+
CLILog(`Port ${options?.port} is already occupied. To start Joystick on this port, clear it and try again.`, {
|
|
537
|
+
level: "danger"
|
|
538
|
+
});
|
|
539
|
+
process.exit(0);
|
|
540
|
+
}
|
|
541
|
+
if (hmrPortOccupied) {
|
|
542
|
+
await killPortProcess(port + 1);
|
|
543
|
+
}
|
|
469
544
|
initProcess(options);
|
|
470
545
|
const nodeMajorVersion = parseInt(
|
|
471
546
|
process?.version?.split(".")[0]?.replace("v", ""),
|
|
@@ -484,18 +559,14 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
484
559
|
settings: settings.parsed
|
|
485
560
|
});
|
|
486
561
|
await runInitialBuild(settings?.parsed?.config?.build);
|
|
487
|
-
await startFileWatcher(
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
562
|
+
await startFileWatcher({
|
|
563
|
+
...options,
|
|
564
|
+
nodeMajorVersion
|
|
565
|
+
});
|
|
566
|
+
await handleStartAppServer({
|
|
567
|
+
...options,
|
|
568
|
+
nodeMajorVersion
|
|
492
569
|
});
|
|
493
|
-
if (serverProcess) {
|
|
494
|
-
processIds.push(serverProcess.pid);
|
|
495
|
-
process.serverProcess = serverProcess;
|
|
496
|
-
handleServerProcessSTDIO();
|
|
497
|
-
handleServerProcessMessages();
|
|
498
|
-
}
|
|
499
570
|
if (options?.environment !== "test") {
|
|
500
571
|
const hmrProcess = await startHMR({
|
|
501
572
|
nodeMajorVersion,
|
|
@@ -504,7 +575,10 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
504
575
|
processIds.push(hmrProcess.pid);
|
|
505
576
|
process.hmrProcess = hmrProcess;
|
|
506
577
|
handleHMRProcessSTDIO();
|
|
507
|
-
handleHMRProcessMessages(
|
|
578
|
+
handleHMRProcessMessages({
|
|
579
|
+
...options,
|
|
580
|
+
nodeMajorVersion
|
|
581
|
+
});
|
|
508
582
|
}
|
|
509
583
|
handleSignalEvents(
|
|
510
584
|
processIds,
|
|
@@ -512,10 +586,20 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
512
586
|
__dirname
|
|
513
587
|
);
|
|
514
588
|
if (options?.environment === "test") {
|
|
515
|
-
process.loader.
|
|
589
|
+
process.loader.stop();
|
|
590
|
+
const databaseProcessIds = getDatabaseProcessIds();
|
|
516
591
|
await runTests({
|
|
517
|
-
|
|
592
|
+
watch: options?.watch,
|
|
593
|
+
__dirname,
|
|
594
|
+
processIds: [
|
|
595
|
+
...processIds,
|
|
596
|
+
...databaseProcessIds
|
|
597
|
+
],
|
|
598
|
+
cleanupProcess: process.cleanupProcess
|
|
518
599
|
});
|
|
600
|
+
if (!options?.watch) {
|
|
601
|
+
process.exit(0);
|
|
602
|
+
}
|
|
519
603
|
}
|
|
520
604
|
resolve();
|
|
521
605
|
} catch (exception) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import CLILog from "../CLILog.js";
|
|
3
3
|
import isValidJSONString from "../isValidJSONString.js";
|
|
4
|
-
const warnIfInvalidJSONInSettings = (settings = "") => {
|
|
4
|
+
const warnIfInvalidJSONInSettings = (settings = "", processIds = []) => {
|
|
5
5
|
try {
|
|
6
6
|
const isValidJSON = isValidJSONString(settings);
|
|
7
7
|
const context = process.env.NODE_ENV === "test" ? "test" : "start";
|
|
@@ -14,6 +14,9 @@ const warnIfInvalidJSONInSettings = (settings = "") => {
|
|
|
14
14
|
tools: [{ title: "JSON Linter", url: "https://jsonlint.com/" }]
|
|
15
15
|
}
|
|
16
16
|
);
|
|
17
|
+
if (process.cleanupProcess) {
|
|
18
|
+
process.cleanupProcess.send(JSON.stringify({ processIds }));
|
|
19
|
+
}
|
|
17
20
|
process.exit(0);
|
|
18
21
|
}
|
|
19
22
|
} catch (exception) {
|
|
@@ -27,7 +30,7 @@ const getSettings = (settingsPath = "") => {
|
|
|
27
30
|
throw new Error(`[loadSettings.getSettings] ${exception.message}`);
|
|
28
31
|
}
|
|
29
32
|
};
|
|
30
|
-
const warnIfSettingsNotFound = (settingsPath = "") => {
|
|
33
|
+
const warnIfSettingsNotFound = (settingsPath = "", processIds = []) => {
|
|
31
34
|
try {
|
|
32
35
|
const hasSettingsFile = fs.existsSync(settingsPath);
|
|
33
36
|
const context = process.env.NODE_ENV === "test" ? "test" : "start";
|
|
@@ -39,6 +42,9 @@ const warnIfSettingsNotFound = (settingsPath = "") => {
|
|
|
39
42
|
docs: `https://cheatcode.co/docs/joystick/cli/${context}`
|
|
40
43
|
}
|
|
41
44
|
);
|
|
45
|
+
if (process.cleanupProcess) {
|
|
46
|
+
process.cleanupProcess.send(JSON.stringify({ processIds }));
|
|
47
|
+
}
|
|
42
48
|
process.exit(0);
|
|
43
49
|
}
|
|
44
50
|
} catch (exception) {
|
|
@@ -59,9 +65,9 @@ const loadSettings = (options, { resolve, reject }) => {
|
|
|
59
65
|
try {
|
|
60
66
|
validateOptions(options);
|
|
61
67
|
const settingsPath = `${process.cwd()}/settings.${options.environment}.json`;
|
|
62
|
-
warnIfSettingsNotFound(settingsPath);
|
|
68
|
+
warnIfSettingsNotFound(settingsPath, options.processIds);
|
|
63
69
|
const settings = getSettings(settingsPath);
|
|
64
|
-
warnIfInvalidJSONInSettings(settings);
|
|
70
|
+
warnIfInvalidJSONInSettings(settings, options.processIds);
|
|
65
71
|
process.env.JOYSTICK_SETTINGS = settings;
|
|
66
72
|
resolve({
|
|
67
73
|
parsed: JSON.parse(settings),
|
package/dist/lib/dev/runTests.js
CHANGED
|
@@ -1,39 +1,71 @@
|
|
|
1
1
|
import child_process from "child_process";
|
|
2
|
-
|
|
2
|
+
import CLILog from "../CLILog.js";
|
|
3
|
+
const handleAvaSTDERR = (stderr = "", options = {}) => {
|
|
4
|
+
try {
|
|
5
|
+
if (stderr?.includes("Using configuration")) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
if (stderr?.includes("No tests found")) {
|
|
9
|
+
return CLILog("No tests found. Add tests in the /tests folder at the root of your Joystick app.", {
|
|
10
|
+
level: "danger",
|
|
11
|
+
docs: "https://cheatcode.co/docs/joystick/test/setup"
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
console.log(stderr);
|
|
15
|
+
} catch (exception) {
|
|
16
|
+
throw new Error(`[runTests.handleAvaSTDERR] ${exception.message}`);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const handleAvaSTDOUT = (stdout = "", options = {}) => {
|
|
20
|
+
try {
|
|
21
|
+
if (stdout?.includes("Using configuration")) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
if (stdout?.includes("No tests found in")) {
|
|
25
|
+
const [message] = stdout?.split(",");
|
|
26
|
+
return console.log(`${message}
|
|
27
|
+
`);
|
|
28
|
+
}
|
|
29
|
+
console.log(stdout);
|
|
30
|
+
} catch (exception) {
|
|
31
|
+
throw new Error(`[runTests.handleAvaSTDOUT] ${exception.message}`);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const handleAvaSTDIO = (ava = {}, options = {}) => {
|
|
3
35
|
try {
|
|
4
36
|
ava.stdout.on("data", function(data) {
|
|
5
37
|
const string = data.toString();
|
|
6
|
-
|
|
7
|
-
console.log(string);
|
|
8
|
-
}
|
|
38
|
+
handleAvaSTDOUT(string, options);
|
|
9
39
|
});
|
|
10
40
|
ava.stderr.on("data", function(data) {
|
|
11
41
|
const string = data.toString();
|
|
12
|
-
|
|
13
|
-
console.log(string);
|
|
14
|
-
}
|
|
42
|
+
handleAvaSTDERR(string, options);
|
|
15
43
|
});
|
|
16
44
|
} catch (exception) {
|
|
17
45
|
throw new Error(`[runTests.handleAvaSTDIO] ${exception.message}`);
|
|
18
46
|
}
|
|
19
47
|
};
|
|
20
|
-
const runAva = (
|
|
48
|
+
const runAva = (options = {}) => {
|
|
21
49
|
try {
|
|
22
|
-
|
|
50
|
+
const avaPath = `${process.cwd()}/node_modules/.bin/ava`;
|
|
23
51
|
return new Promise((resolve, reject) => {
|
|
24
|
-
const ava = child_process.exec(
|
|
52
|
+
const ava = child_process.exec(`${avaPath} --config ${options?.__dirname}/tests.config.js ${options?.watch ? "--watch" : ""}`, {
|
|
25
53
|
stdio: "inherit",
|
|
26
54
|
env: {
|
|
27
55
|
...process.env,
|
|
56
|
+
databases: process.databases,
|
|
28
57
|
FORCE_COLOR: "1"
|
|
29
58
|
}
|
|
30
59
|
}, (error) => {
|
|
31
|
-
if (error) {
|
|
32
|
-
|
|
60
|
+
if (!error) {
|
|
61
|
+
options.cleanupProcess.send(JSON.stringify({ processIds: options?.processIds }));
|
|
62
|
+
resolve();
|
|
63
|
+
} else {
|
|
64
|
+
options.cleanupProcess.send(JSON.stringify({ processIds: options?.processIds }));
|
|
65
|
+
resolve();
|
|
33
66
|
}
|
|
34
|
-
return resolve();
|
|
35
67
|
});
|
|
36
|
-
handleAvaSTDIO(ava);
|
|
68
|
+
handleAvaSTDIO(ava, options);
|
|
37
69
|
});
|
|
38
70
|
} catch (exception) {
|
|
39
71
|
throw new Error(`[runTests.runAva] ${exception.message}`);
|
|
@@ -52,7 +84,7 @@ const validateOptions = (options) => {
|
|
|
52
84
|
const runTests = async (options, { resolve, reject }) => {
|
|
53
85
|
try {
|
|
54
86
|
validateOptions(options);
|
|
55
|
-
await runAva(options
|
|
87
|
+
await runAva(options);
|
|
56
88
|
resolve();
|
|
57
89
|
} catch (exception) {
|
|
58
90
|
reject(`[runTests] ${exception.message}`);
|
package/dist/lib/dev/startApp.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import child_process from "child_process";
|
|
2
2
|
import path from "path";
|
|
3
|
-
const handleStartServerProcess = (execArgv = {},
|
|
3
|
+
const handleStartServerProcess = (execArgv = {}, options = {}) => {
|
|
4
4
|
try {
|
|
5
|
-
|
|
5
|
+
if (!options?.watch) {
|
|
6
|
+
process.loader.text("Starting app...");
|
|
7
|
+
}
|
|
6
8
|
return child_process.fork(
|
|
7
9
|
path.resolve(".joystick/build/index.server.js"),
|
|
8
10
|
[],
|
|
@@ -18,7 +20,7 @@ const handleStartServerProcess = (execArgv = {}, sessionsBeforeHMRUpdate = {}) =
|
|
|
18
20
|
ROOT_URL: process.env.ROOT_URL,
|
|
19
21
|
PORT: process.env.PORT,
|
|
20
22
|
JOYSTICK_SETTINGS: process.env.JOYSTICK_SETTINGS,
|
|
21
|
-
HMR_SESSIONS:
|
|
23
|
+
HMR_SESSIONS: options?.sessionsBeforeHMRUpdate || "{}"
|
|
22
24
|
}
|
|
23
25
|
}
|
|
24
26
|
);
|
|
@@ -56,7 +58,7 @@ const startApp = (options, { resolve, reject }) => {
|
|
|
56
58
|
try {
|
|
57
59
|
validateOptions(options);
|
|
58
60
|
const execArgv = getExecArgs(options?.nodeMajorVersion);
|
|
59
|
-
const serverProcess = handleStartServerProcess(execArgv, options
|
|
61
|
+
const serverProcess = handleStartServerProcess(execArgv, options);
|
|
60
62
|
return resolve(serverProcess);
|
|
61
63
|
} catch (exception) {
|
|
62
64
|
reject(`[startApp] ${exception.message}`);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
var tests_config_default = {
|
|
2
|
+
files: [`tests/**/*.test.js`],
|
|
3
|
+
// NOTE: Intentionally limit to 1 test at a time to avoid concurrency creating
|
|
4
|
+
// race conditions in tests that have users or other "global" data that needs
|
|
5
|
+
// to be cleaned up. The extra time needed is worth it to guarantee that tests
|
|
6
|
+
// don't step on each other's toes and our code is properly verified.
|
|
7
|
+
concurrency: 1,
|
|
8
|
+
cache: false
|
|
9
|
+
};
|
|
10
|
+
export {
|
|
11
|
+
tests_config_default as default
|
|
12
|
+
};
|
package/dist/lib/regexes.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const EXAMPLE_CODE_REGEX = new RegExp(/\<example\>[^%]+\<\/example\>/g);
|
|
1
2
|
const EXPORT_DEFAULT_REGEX = new RegExp(/export default [a-zA-Z0-9]+/g);
|
|
2
3
|
const JOYSTICK_COMMENT_REGEX = new RegExp(/\<\!\-\-(.|\n|\r)*?-->/g);
|
|
3
4
|
const JOYSTICK_COMPONENT_REGEX = new RegExp(/\.component\(\{/g);
|
|
@@ -5,6 +6,7 @@ const JOYSTICK_UI_REGEX = new RegExp(/@joystick.js\/ui/g);
|
|
|
5
6
|
const OBJECT_REGEX = new RegExp(/{([^;]*)}/g);
|
|
6
7
|
const SETTINGS_FILE_NAME_REGEX = new RegExp(/settings.[a-zA-Z0-9]+.json/g);
|
|
7
8
|
export {
|
|
9
|
+
EXAMPLE_CODE_REGEX,
|
|
8
10
|
EXPORT_DEFAULT_REGEX,
|
|
9
11
|
JOYSTICK_COMMENT_REGEX,
|
|
10
12
|
JOYSTICK_COMPONENT_REGEX,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@joystick.js/cli-canary",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0-beta.75",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for the Joystick JavaScript framework.",
|
|
6
6
|
"main": "development.js",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"@babel/code-frame": "^7.15.8",
|
|
26
26
|
"acorn": "^8.5.0",
|
|
27
27
|
"ascii-table": "^0.0.9",
|
|
28
|
+
"ava": "^5.3.1",
|
|
28
29
|
"chalk": "^4.1.2",
|
|
29
30
|
"chokidar": "^3.5.2",
|
|
30
31
|
"command-exists": "^1.2.9",
|
package/src/functions/index.js
CHANGED
|
@@ -224,21 +224,26 @@ export default {
|
|
|
224
224
|
set: !!rawArgs.includes('test'),
|
|
225
225
|
description: 'Start an existing Joystick app and run its tests.',
|
|
226
226
|
args: {
|
|
227
|
-
|
|
228
|
-
set: !!rawArgs.includes('
|
|
229
|
-
parent: '
|
|
230
|
-
value: !!rawArgs.includes('
|
|
227
|
+
watch: {
|
|
228
|
+
set: !!rawArgs.includes('watch'),
|
|
229
|
+
parent: 'test',
|
|
230
|
+
value: !!rawArgs.includes('watch'),
|
|
231
231
|
description: 'Run joystick test in watch mode.',
|
|
232
232
|
},
|
|
233
|
+
},
|
|
234
|
+
options: {
|
|
233
235
|
watch: {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
236
|
+
flags: {
|
|
237
|
+
'--watch': {
|
|
238
|
+
set: !!rawArgs.includes('--watch'),
|
|
239
|
+
value: !!rawArgs.includes('--watch'),
|
|
240
|
+
parent: 'test'
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
description: 'Environment to set for process.env.NODE_ENV.',
|
|
238
244
|
},
|
|
239
245
|
},
|
|
240
|
-
|
|
241
|
-
function: test(),
|
|
246
|
+
function: test,
|
|
242
247
|
},
|
|
243
248
|
update: {
|
|
244
249
|
set: !!rawArgs.includes('update'),
|