@joystick.js/cli-canary 0.0.0-canary.99 → 1.0.0-beta.74
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 +4 -1
- package/dist/lib/build/nodePaths.js +1 -0
- package/dist/lib/dev/hmrServer.js +66 -0
- package/dist/lib/dev/index.js +63 -37
- 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/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 +4 -1
- package/src/lib/build/nodePaths.js +1 -0
- package/src/lib/dev/hmrServer.js +78 -0
- package/src/lib/dev/index.js +71 -36
- 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
|
@@ -53,8 +53,10 @@ const handleBuildForNode = (nodePaths = [], options = {}) => {
|
|
|
53
53
|
format: "esm",
|
|
54
54
|
bundle: false,
|
|
55
55
|
entryPoints: nodePaths?.map((file) => file.path),
|
|
56
|
+
entryNames: '[dir]/[name]',
|
|
56
57
|
// TODO: Make sure we don't need outbase here so the paths map correctly.
|
|
57
58
|
outdir: options?.outputPath || "./.joystick/build",
|
|
59
|
+
outbase: './',
|
|
58
60
|
define: {
|
|
59
61
|
"process.env.NODE_ENV": `'${options?.environment}'`,
|
|
60
62
|
},
|
|
@@ -77,6 +79,8 @@ const handleBuildForBrowser = (browserPaths = [], options = {}) => {
|
|
|
77
79
|
format: "esm",
|
|
78
80
|
bundle: true,
|
|
79
81
|
entryPoints: browserPaths?.map((file) => file.path),
|
|
82
|
+
entryNames: '[dir]/[name]',
|
|
83
|
+
outbase: './',
|
|
80
84
|
// TODO: Make sure we don't need outbase here so the paths map correctly.
|
|
81
85
|
outdir: options?.outputPath || "./.joystick/build",
|
|
82
86
|
define: {
|
|
@@ -225,7 +229,6 @@ const buildFiles = async (options, { resolve, reject }) => {
|
|
|
225
229
|
return { success: true };
|
|
226
230
|
}).catch((exception) => {
|
|
227
231
|
const file = handleParseFilePathFromException(exception);
|
|
228
|
-
console.log(file, exception);
|
|
229
232
|
const snippet = handleBuildException(exception, file);
|
|
230
233
|
|
|
231
234
|
return {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import { WebSocketServer } from "ws";
|
|
3
|
+
import generateId from "../generateId.js";
|
|
4
|
+
|
|
5
|
+
// NOTE: This doesn't run on the app server (in node). This runs on your local computer
|
|
6
|
+
// as a totally separate process that's forked on joystick start.
|
|
7
|
+
|
|
8
|
+
export default (() => {
|
|
9
|
+
const websocketServer = new WebSocketServer({
|
|
10
|
+
port: parseInt(process.env.PORT, 10) + 1,
|
|
11
|
+
path: "/_joystick/hmr",
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
process.on("message", (message) => {
|
|
15
|
+
if (typeof process.HMR_CONNECTIONS === "object") {
|
|
16
|
+
const parsedMessage = JSON.parse(message);
|
|
17
|
+
const connections = Object.values(process.HMR_CONNECTIONS);
|
|
18
|
+
for (let i = 0; i < connections?.length; i += 1) {
|
|
19
|
+
const connection = connections[i];
|
|
20
|
+
if (connection?.connection?.send) {
|
|
21
|
+
connection.connection.send(
|
|
22
|
+
JSON.stringify({
|
|
23
|
+
type: "FILE_CHANGE",
|
|
24
|
+
settings: {
|
|
25
|
+
global: parsedMessage?.settings?.global,
|
|
26
|
+
public: parsedMessage?.settings?.public,
|
|
27
|
+
},
|
|
28
|
+
indexHTMLChanged: parsedMessage?.indexHTMLChanged,
|
|
29
|
+
})
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
websocketServer.on("connection", function connection(websocketConnection) {
|
|
37
|
+
const connectionId = generateId();
|
|
38
|
+
|
|
39
|
+
process.HMR_CONNECTIONS = {
|
|
40
|
+
...(process.HMR_CONNECTIONS || {}),
|
|
41
|
+
[connectionId]: {
|
|
42
|
+
connection: websocketConnection,
|
|
43
|
+
watchlist: [],
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
if (Object.keys(process.HMR_CONNECTIONS || {})?.length > 0) {
|
|
48
|
+
process.send({ type: "HAS_HMR_CONNECTIONS" });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
websocketConnection.on("message", (message) => {
|
|
52
|
+
const parsedMessage = JSON.parse(message);
|
|
53
|
+
|
|
54
|
+
if (parsedMessage?.type === "HMR_UPDATE_COMPLETE") {
|
|
55
|
+
process.send({ type: "HMR_UPDATE_COMPLETED", sessions: parsedMessage?.sessions });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (parsedMessage?.type === "HMR_WATCHLIST") {
|
|
59
|
+
process.HMR_CONNECTIONS[connectionId]?.watchlist?.push(
|
|
60
|
+
...(parsedMessage?.tags || [])
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
websocketConnection.on("close", () => {
|
|
66
|
+
if (process.HMR_CONNECTIONS[connectionId]) {
|
|
67
|
+
delete process.HMR_CONNECTIONS[connectionId];
|
|
68
|
+
|
|
69
|
+
if (Object.keys(process.HMR_CONNECTIONS || {})?.length === 0) {
|
|
70
|
+
process.send({ type: "HAS_NO_HMR_CONNECTIONS" });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return true;
|
|
78
|
+
})();
|
package/src/lib/dev/index.js
CHANGED
|
@@ -22,6 +22,8 @@ import getCodependenciesForFile from "./getCodependenciesForFile.js";
|
|
|
22
22
|
import removeDeletedDependenciesFromMap from "../build/removeDeletedDependenciesFromMap.js";
|
|
23
23
|
import chalk from "chalk";
|
|
24
24
|
|
|
25
|
+
const processIds = [];
|
|
26
|
+
|
|
25
27
|
const getDatabaseProcessIds = () => {
|
|
26
28
|
try {
|
|
27
29
|
const databaseProcessIds = [];
|
|
@@ -75,6 +77,8 @@ const handleSignalEvents = (processIds = [], nodeMajorVersion = 0, __dirname = '
|
|
|
75
77
|
}
|
|
76
78
|
);
|
|
77
79
|
|
|
80
|
+
process.cleanupProcess = cleanupProcess;
|
|
81
|
+
|
|
78
82
|
process.on("SIGINT", async () => {
|
|
79
83
|
const databaseProcessIds = getDatabaseProcessIds();
|
|
80
84
|
cleanupProcess.send(JSON.stringify(({ processIds: [...processIds, ...databaseProcessIds] })));
|
|
@@ -115,7 +119,7 @@ const handleHMRProcessMessages = (options = {}) => {
|
|
|
115
119
|
|
|
116
120
|
if (message?.type === "HMR_UPDATE_COMPLETED") {
|
|
117
121
|
// NOTE: Do a setTimeout to ensure that server is still available while the HMR update completes.
|
|
118
|
-
// Necessary because some updates are
|
|
122
|
+
// Necessary because some updates are instant, but others might mount a UI that needs a server
|
|
119
123
|
// available (e.g., runs API requests).
|
|
120
124
|
setTimeout(() => {
|
|
121
125
|
handleRestartApplicationProcess({
|
|
@@ -171,7 +175,7 @@ const handleServerProcessMessages = () => {
|
|
|
171
175
|
}
|
|
172
176
|
};
|
|
173
177
|
|
|
174
|
-
const handleServerProcessSTDIO = () => {
|
|
178
|
+
const handleServerProcessSTDIO = (options = {}) => {
|
|
175
179
|
try {
|
|
176
180
|
if (process.serverProcess) {
|
|
177
181
|
process.serverProcess.on("error", (error) => {
|
|
@@ -181,7 +185,7 @@ const handleServerProcessSTDIO = () => {
|
|
|
181
185
|
process.serverProcess.stdout.on("data", (data) => {
|
|
182
186
|
const message = data.toString();
|
|
183
187
|
|
|
184
|
-
if (message && message.includes("App running at:")) {
|
|
188
|
+
if (message && message.includes("App running at:") && !options?.watch) {
|
|
185
189
|
process.loader.stable(message);
|
|
186
190
|
} else {
|
|
187
191
|
if (message && !message.includes("BUILD_ERROR")) {
|
|
@@ -208,11 +212,10 @@ const handleAddOrChangeFile = async (context = {}, path = '', options = {}) => {
|
|
|
208
212
|
try {
|
|
209
213
|
if (context.isAddingOrChangingFile) {
|
|
210
214
|
const codependencies = await getCodependenciesForFile(path);
|
|
211
|
-
const fileResults = await buildFiles(
|
|
212
|
-
[path, ...(codependencies?.existing || [])],
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
);
|
|
215
|
+
const fileResults = await buildFiles({
|
|
216
|
+
files: [path, ...(codependencies?.existing || [])],
|
|
217
|
+
environment: process.env.NODE_ENV,
|
|
218
|
+
});
|
|
216
219
|
|
|
217
220
|
const fileResultsHaveErrors = fileResults
|
|
218
221
|
.filter((result) => !!result)
|
|
@@ -305,21 +308,15 @@ const handleCopyDirectory = (context = {}, path = '', options = {}) => {
|
|
|
305
308
|
const handleRestartApplicationProcess = async (options = {}) => {
|
|
306
309
|
try {
|
|
307
310
|
if (process.serverProcess && process.serverProcess.pid) {
|
|
308
|
-
process.loader.text("Restarting app...");
|
|
309
311
|
process.serverProcess.kill();
|
|
310
312
|
|
|
311
|
-
await
|
|
312
|
-
nodeMajorVersion: options?.nodeMajorVersion,
|
|
313
|
-
port: options?.port,
|
|
314
|
-
sessionsBeforeHMRUpdate: options?.sessionsBeforeHMRUpdate,
|
|
315
|
-
});
|
|
313
|
+
await handleStartAppServer(options);
|
|
316
314
|
|
|
317
315
|
return Promise.resolve();
|
|
318
316
|
}
|
|
319
317
|
|
|
320
318
|
// NOTE: Original process was never initialized due to an error.
|
|
321
|
-
|
|
322
|
-
startApplicationProcess();
|
|
319
|
+
await handleStartAppServer(options);
|
|
323
320
|
|
|
324
321
|
if (!process.hmrProcess) {
|
|
325
322
|
startHMR();
|
|
@@ -329,19 +326,41 @@ const handleRestartApplicationProcess = async (options = {}) => {
|
|
|
329
326
|
}
|
|
330
327
|
};
|
|
331
328
|
|
|
332
|
-
const
|
|
329
|
+
const handleStartAppServer = async (options = {}) => {
|
|
330
|
+
try {
|
|
331
|
+
const serverProcess = await startApp({
|
|
332
|
+
watch: options?.watch,
|
|
333
|
+
nodeMajorVersion: options?.nodeMajorVersion,
|
|
334
|
+
port: options?.port,
|
|
335
|
+
sessionsBeforeHMRUpdate: options?.sessionsBeforeHMRUpdate,
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
if (serverProcess) {
|
|
339
|
+
processIds.push(serverProcess.pid);
|
|
340
|
+
process.serverProcess = serverProcess;
|
|
341
|
+
handleServerProcessSTDIO(options);
|
|
342
|
+
handleServerProcessMessages(options);
|
|
343
|
+
}
|
|
344
|
+
} catch (exception) {
|
|
345
|
+
console.warn(exception);
|
|
346
|
+
throw new Error(`[dev.handleStartAppServer] ${exception.message}`);
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const handleNotifyHMRClients = async (indexHTMLChanged = false) => {
|
|
333
351
|
try {
|
|
334
352
|
if (process.hmrProcess) {
|
|
335
|
-
const settings = loadSettings(process.env.NODE_ENV);
|
|
353
|
+
const settings = await loadSettings({ environment: process.env.NODE_ENV });
|
|
336
354
|
process.hmrProcess.send(
|
|
337
355
|
JSON.stringify({
|
|
338
356
|
type: "RESTART_SERVER",
|
|
339
|
-
settings,
|
|
357
|
+
settings: settings.parsed,
|
|
340
358
|
indexHTMLChanged,
|
|
341
359
|
})
|
|
342
360
|
);
|
|
343
361
|
}
|
|
344
362
|
} catch (exception) {
|
|
363
|
+
console.warn(exception);
|
|
345
364
|
throw new Error(`[dev.handleNotifyHMRClients] ${exception.message}`);
|
|
346
365
|
}
|
|
347
366
|
};
|
|
@@ -359,7 +378,7 @@ const getWatchChangeContext = (event = '', path = '') => {
|
|
|
359
378
|
const isAddDirectory = event === 'addDir' && isExistingDirectoryInSource && !isExistingDirectoryInBuild;
|
|
360
379
|
const isFileToCopy = !!filesToCopy.find((fileToCopy) => fileToCopy.path === path);
|
|
361
380
|
const isExistingFileInSource = isFile && fs.existsSync(path);
|
|
362
|
-
const isAddingOrChangingFile = event
|
|
381
|
+
const isAddingOrChangingFile = ["add", "change"].includes(event) && isExistingFileInSource;
|
|
363
382
|
|
|
364
383
|
return {
|
|
365
384
|
isHTMLUpdate,
|
|
@@ -391,10 +410,16 @@ const startFileWatcher = (options = {}) => {
|
|
|
391
410
|
// NOTE: Do this here in case a required file/folder goes missing inbetween builds.
|
|
392
411
|
checkForRequiredFiles();
|
|
393
412
|
|
|
394
|
-
|
|
413
|
+
if (!options?.watch) {
|
|
414
|
+
process.loader.text("Rebuilding app...");
|
|
415
|
+
}
|
|
395
416
|
|
|
396
417
|
const watchChangeContext = getWatchChangeContext(event, path);
|
|
397
|
-
|
|
418
|
+
//
|
|
419
|
+
// console.log({
|
|
420
|
+
// watchChangeContext,
|
|
421
|
+
// });
|
|
422
|
+
//
|
|
398
423
|
handleCopyDirectory(watchChangeContext, path, options);
|
|
399
424
|
handleCopyFile(watchChangeContext, path, options);
|
|
400
425
|
handleAddDirectory(watchChangeContext, path, options);
|
|
@@ -578,21 +603,15 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
578
603
|
});
|
|
579
604
|
|
|
580
605
|
await runInitialBuild(settings?.parsed?.config?.build);
|
|
581
|
-
await startFileWatcher(
|
|
582
|
-
|
|
583
|
-
const processIds = [];
|
|
584
|
-
|
|
585
|
-
const serverProcess = await startApp({
|
|
606
|
+
await startFileWatcher({
|
|
607
|
+
...options,
|
|
586
608
|
nodeMajorVersion,
|
|
587
|
-
port: options?.port,
|
|
588
609
|
});
|
|
589
610
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
handleServerProcessMessages();
|
|
595
|
-
}
|
|
611
|
+
await handleStartAppServer({
|
|
612
|
+
...options,
|
|
613
|
+
nodeMajorVersion,
|
|
614
|
+
});
|
|
596
615
|
|
|
597
616
|
if (options?.environment !== 'test') {
|
|
598
617
|
const hmrProcess = await startHMR({
|
|
@@ -604,7 +623,10 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
604
623
|
process.hmrProcess = hmrProcess;
|
|
605
624
|
|
|
606
625
|
handleHMRProcessSTDIO();
|
|
607
|
-
handleHMRProcessMessages(
|
|
626
|
+
handleHMRProcessMessages({
|
|
627
|
+
...options,
|
|
628
|
+
nodeMajorVersion,
|
|
629
|
+
});
|
|
608
630
|
}
|
|
609
631
|
|
|
610
632
|
|
|
@@ -615,10 +637,23 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
615
637
|
);
|
|
616
638
|
|
|
617
639
|
if (options?.environment === 'test') {
|
|
618
|
-
process.loader.
|
|
640
|
+
process.loader.stop();
|
|
641
|
+
const databaseProcessIds = getDatabaseProcessIds();
|
|
642
|
+
|
|
619
643
|
await runTests({
|
|
644
|
+
watch: options?.watch,
|
|
620
645
|
__dirname,
|
|
646
|
+
processIds: [
|
|
647
|
+
...processIds,
|
|
648
|
+
...databaseProcessIds,
|
|
649
|
+
],
|
|
650
|
+
cleanupProcess: process.cleanupProcess,
|
|
621
651
|
});
|
|
652
|
+
|
|
653
|
+
if (!options?.watch) {
|
|
654
|
+
// NOTE: Kick out of the process after tests run if we're not in watch mode.
|
|
655
|
+
process.exit(0);
|
|
656
|
+
}
|
|
622
657
|
}
|
|
623
658
|
|
|
624
659
|
/*
|
package/src/lib/dev/runTests.js
CHANGED
|
@@ -1,46 +1,95 @@
|
|
|
1
1
|
import child_process from "child_process";
|
|
2
|
+
import CLILog from "../CLILog.js";
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
+
const handleAvaSTDERR = (stderr = '', options = {}) => {
|
|
5
|
+
try {
|
|
6
|
+
// NOTE: Squash output about using a configuration file (we always do in the framework).
|
|
7
|
+
if (stderr?.includes('Using configuration')) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (stderr?.includes('No tests found')) {
|
|
12
|
+
return CLILog('No tests found. Add tests in the /tests folder at the root of your Joystick app.', {
|
|
13
|
+
level: 'danger',
|
|
14
|
+
docs: 'https://cheatcode.co/docs/joystick/test/setup',
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
console.log(stderr);
|
|
19
|
+
} catch (exception) {
|
|
20
|
+
throw new Error(`[runTests.handleAvaSTDERR] ${exception.message}`);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const handleAvaSTDOUT = (stdout = '', options = {}) => {
|
|
25
|
+
try {
|
|
26
|
+
// NOTE: Squash output about using a configuration file (we always do in the framework).
|
|
27
|
+
if (stdout?.includes('Using configuration')) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (stdout?.includes('No tests found in')) {
|
|
32
|
+
const [message] = stdout?.split(',');
|
|
33
|
+
return console.log(`${message}\n`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
console.log(stdout);
|
|
37
|
+
} catch (exception) {
|
|
38
|
+
throw new Error(`[runTests.handleAvaSTDOUT] ${exception.message}`);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const handleAvaSTDIO = (ava = {}, options = {}) => {
|
|
4
43
|
try {
|
|
5
44
|
ava.stdout.on('data', function (data) {
|
|
6
45
|
const string = data.toString();
|
|
7
|
-
|
|
8
|
-
if (!string?.includes('ava')) {
|
|
9
|
-
console.log(string);
|
|
10
|
-
}
|
|
46
|
+
handleAvaSTDOUT(string, options);
|
|
11
47
|
});
|
|
12
48
|
|
|
13
49
|
ava.stderr.on('data', function (data) {
|
|
14
50
|
const string = data.toString();
|
|
15
|
-
|
|
16
|
-
if (!string?.includes('ava')) {
|
|
17
|
-
console.log(string);
|
|
18
|
-
}
|
|
51
|
+
handleAvaSTDERR(string, options);
|
|
19
52
|
});
|
|
20
53
|
} catch (exception) {
|
|
21
54
|
throw new Error(`[runTests.handleAvaSTDIO] ${exception.message}`);
|
|
22
55
|
}
|
|
23
56
|
};
|
|
24
57
|
|
|
25
|
-
const runAva = (
|
|
58
|
+
const runAva = (options = {}) => {
|
|
26
59
|
try {
|
|
27
|
-
|
|
60
|
+
// NOTE: A little bananas to reason through this. In order for Ava to run w/o errors,
|
|
61
|
+
// the Ava binary being run here has to be identical to the one used in @joystick.js/test.
|
|
62
|
+
// That would equal the copy of Ava that's installed in a Joystick app's node_modules
|
|
63
|
+
// directory, not the node_modules directory of the CLI here. We can guarantee that will
|
|
64
|
+
// exist for the CLI here because a developer has to install @joystick.js/test which will
|
|
65
|
+
// add Ava as a dependency to their app in order to write tests.
|
|
66
|
+
const avaPath = `${process.cwd()}/node_modules/.bin/ava`;
|
|
67
|
+
|
|
28
68
|
return new Promise((resolve, reject) => {
|
|
29
|
-
|
|
69
|
+
// NOTE: Despite using the app's node_modules path to reference Ava, we still want to reference
|
|
70
|
+
// the internal path here for the default test config in /lib/dev/tests.config.js.
|
|
71
|
+
const ava = child_process.exec(`${avaPath} --config ${options?.__dirname}/tests.config.js ${options?.watch ? '--watch' : ''}`, {
|
|
30
72
|
stdio: 'inherit',
|
|
31
73
|
env: {
|
|
32
74
|
...(process.env),
|
|
75
|
+
databases: process.databases,
|
|
33
76
|
FORCE_COLOR: "1"
|
|
34
77
|
}
|
|
35
78
|
}, (error) => {
|
|
36
|
-
if (error) {
|
|
37
|
-
|
|
79
|
+
if (!error) {
|
|
80
|
+
// NOTE: Do this here because the standard SIGINT and SIGTERM hooks the dev process
|
|
81
|
+
// listens for don't catch a clean exit (and the process.exit() hook fires after exit).
|
|
82
|
+
options.cleanupProcess.send(JSON.stringify(({ processIds: options?.processIds })));
|
|
83
|
+
resolve();
|
|
84
|
+
} else {
|
|
85
|
+
// NOTE: Do not report any Ava errors here because they're picked up by the handleAvaSTDIO();
|
|
86
|
+
// hook below. Just do a clean exit here so Node doesn't hang.
|
|
87
|
+
options.cleanupProcess.send(JSON.stringify(({ processIds: options?.processIds })));
|
|
88
|
+
resolve();
|
|
38
89
|
}
|
|
39
|
-
|
|
40
|
-
return resolve();
|
|
41
90
|
});
|
|
42
91
|
|
|
43
|
-
handleAvaSTDIO(ava);
|
|
92
|
+
handleAvaSTDIO(ava, options);
|
|
44
93
|
});
|
|
45
94
|
} catch (exception) {
|
|
46
95
|
throw new Error(`[runTests.runAva] ${exception.message}`);
|
|
@@ -60,7 +109,7 @@ const runTests = async (options, { resolve, reject }) => {
|
|
|
60
109
|
try {
|
|
61
110
|
validateOptions(options);
|
|
62
111
|
|
|
63
|
-
await runAva(options
|
|
112
|
+
await runAva(options);
|
|
64
113
|
|
|
65
114
|
resolve();
|
|
66
115
|
} catch (exception) {
|
package/src/lib/dev/startApp.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import child_process from "child_process";
|
|
2
2
|
import path from "path";
|
|
3
3
|
|
|
4
|
-
const handleStartServerProcess = (execArgv = {},
|
|
4
|
+
const handleStartServerProcess = (execArgv = {}, options = {}) => {
|
|
5
5
|
try {
|
|
6
|
-
|
|
6
|
+
if (!options?.watch) {
|
|
7
|
+
process.loader.text('Starting app...');
|
|
8
|
+
}
|
|
7
9
|
|
|
8
10
|
return child_process.fork(
|
|
9
11
|
path.resolve(".joystick/build/index.server.js"),
|
|
@@ -20,7 +22,7 @@ const handleStartServerProcess = (execArgv = {}, sessionsBeforeHMRUpdate = {}) =
|
|
|
20
22
|
ROOT_URL: process.env.ROOT_URL,
|
|
21
23
|
PORT: process.env.PORT,
|
|
22
24
|
JOYSTICK_SETTINGS: process.env.JOYSTICK_SETTINGS,
|
|
23
|
-
HMR_SESSIONS:
|
|
25
|
+
HMR_SESSIONS: options?.sessionsBeforeHMRUpdate || '{}',
|
|
24
26
|
},
|
|
25
27
|
}
|
|
26
28
|
);
|
|
@@ -65,7 +67,7 @@ const startApp = (options, { resolve, reject }) => {
|
|
|
65
67
|
validateOptions(options);
|
|
66
68
|
|
|
67
69
|
const execArgv = getExecArgs(options?.nodeMajorVersion);
|
|
68
|
-
const serverProcess = handleStartServerProcess(execArgv, options
|
|
70
|
+
const serverProcess = handleStartServerProcess(execArgv, options);
|
|
69
71
|
|
|
70
72
|
return resolve(serverProcess);
|
|
71
73
|
} catch (exception) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export 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
|
+
};
|