@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.
@@ -1,7 +1,6 @@
1
1
  {
2
- "name": "@joystick.js/cli",
3
- "version": "1.0.0-beta.71",
4
- "developmentVersion": "1.0.0-beta.1695",
2
+ "name": "@joystick.js/cli-canary",
3
+ "version": "0.0.0-canary.203",
5
4
  "type": "module",
6
5
  "description": "CLI for the Joystick JavaScript framework.",
7
6
  "main": "development.js",
@@ -221,21 +221,26 @@ var functions_default = {
221
221
  set: !!rawArgs.includes("test"),
222
222
  description: "Start an existing Joystick app and run its tests.",
223
223
  args: {
224
- w: {
225
- set: !!rawArgs.includes("w") && !!rawArgs[rawArgs.indexOf("w") + 1],
226
- parent: "w",
227
- value: !!rawArgs.includes("w") && rawArgs[rawArgs.indexOf("w") + 1],
228
- description: "Run joystick test in watch mode."
229
- },
230
224
  watch: {
231
- set: !!rawArgs.includes("watch") && !!rawArgs[rawArgs.indexOf("watch") + 1],
232
- parent: "watch",
233
- value: !!rawArgs.includes("watch") && rawArgs[rawArgs.indexOf("watch") + 1],
225
+ set: !!rawArgs.includes("watch"),
226
+ parent: "test",
227
+ value: !!rawArgs.includes("watch"),
234
228
  description: "Run joystick test in watch mode."
235
229
  }
236
230
  },
237
- options: {},
238
- function: test()
231
+ options: {
232
+ watch: {
233
+ flags: {
234
+ "--watch": {
235
+ set: !!rawArgs.includes("--watch"),
236
+ value: !!rawArgs.includes("--watch"),
237
+ parent: "test"
238
+ }
239
+ },
240
+ description: "Environment to set for process.env.NODE_ENV."
241
+ }
242
+ },
243
+ function: test
239
244
  },
240
245
  update: {
241
246
  set: !!rawArgs.includes("update"),
@@ -1,23 +1,4 @@
1
1
  import dev from "../../lib/dev/index.js";
2
- const startHMRProcess = () => {
3
- const execArgv = ["--no-warnings"];
4
- if (majorVersion < 19) {
5
- execArgv.push("--experimental-specifier-resolution=node");
6
- }
7
- const hmrProcess = child_process.fork(
8
- path.resolve(`${__dirname}/hmrServer.js`),
9
- [],
10
- {
11
- execArgv,
12
- // NOTE: Pipe stdin, stdout, and stderr. IPC establishes a message channel so we
13
- // communicate with the child_process.
14
- silent: true
15
- }
16
- );
17
- process.hmrProcess = hmrProcess;
18
- handleHMRProcessSTDIO();
19
- handleHMRProcessMessages();
20
- };
21
2
  var start_default = async (args = {}, options = {}) => {
22
3
  await dev({
23
4
  environment: args?.environment || "development",
@@ -3,7 +3,8 @@ var test_default = async (args = {}, options = {}) => {
3
3
  await dev({
4
4
  environment: "test",
5
5
  process,
6
- port: 1977
6
+ port: 1977,
7
+ watch: options?.watch
7
8
  });
8
9
  };
9
10
  export {
@@ -1,6 +1,7 @@
1
1
  import getPlatformSafePath from "../getPlatformSafePath.js";
2
2
  var browserPathExclusions_default = [
3
- getPlatformSafePath("lib/node")
3
+ getPlatformSafePath("lib/node"),
4
+ getPlatformSafePath("tests/")
4
5
  ];
5
6
  export {
6
7
  browserPathExclusions_default as default
@@ -46,8 +46,10 @@ const handleBuildForNode = (nodePaths2 = [], options = {}) => {
46
46
  format: "esm",
47
47
  bundle: false,
48
48
  entryPoints: nodePaths2?.map((file) => file.path),
49
+ entryNames: "[dir]/[name]",
49
50
  // TODO: Make sure we don't need outbase here so the paths map correctly.
50
51
  outdir: options?.outputPath || "./.joystick/build",
52
+ outbase: "./",
51
53
  define: {
52
54
  "process.env.NODE_ENV": `'${options?.environment}'`
53
55
  },
@@ -69,6 +71,8 @@ const handleBuildForBrowser = (browserPaths2 = [], options = {}) => {
69
71
  format: "esm",
70
72
  bundle: true,
71
73
  entryPoints: browserPaths2?.map((file) => file.path),
74
+ entryNames: "[dir]/[name]",
75
+ outbase: "./",
72
76
  // TODO: Make sure we don't need outbase here so the paths map correctly.
73
77
  outdir: options?.outputPath || "./.joystick/build",
74
78
  define: {
@@ -197,7 +201,6 @@ const buildFiles = async (options, { resolve, reject }) => {
197
201
  return { success: true };
198
202
  }).catch((exception) => {
199
203
  const file = handleParseFilePathFromException(exception);
200
- console.log(file, exception);
201
204
  const snippet = handleBuildException(exception, file);
202
205
  return {
203
206
  success: false,
@@ -4,6 +4,7 @@ var nodePaths_default = [
4
4
  getPlatformSafePath("routes/"),
5
5
  getPlatformSafePath("fixtures/"),
6
6
  getPlatformSafePath("lib/node"),
7
+ getPlatformSafePath("tests/"),
7
8
  "index.server.js"
8
9
  ];
9
10
  export {
@@ -0,0 +1,66 @@
1
+ import fs from "fs";
2
+ import { WebSocketServer } from "ws";
3
+ import generateId from "../generateId.js";
4
+ var hmrServer_default = (() => {
5
+ const websocketServer = new WebSocketServer({
6
+ port: parseInt(process.env.PORT, 10) + 1,
7
+ path: "/_joystick/hmr"
8
+ });
9
+ process.on("message", (message) => {
10
+ if (typeof process.HMR_CONNECTIONS === "object") {
11
+ const parsedMessage = JSON.parse(message);
12
+ const connections = Object.values(process.HMR_CONNECTIONS);
13
+ for (let i = 0; i < connections?.length; i += 1) {
14
+ const connection = connections[i];
15
+ if (connection?.connection?.send) {
16
+ connection.connection.send(
17
+ JSON.stringify({
18
+ type: "FILE_CHANGE",
19
+ settings: {
20
+ global: parsedMessage?.settings?.global,
21
+ public: parsedMessage?.settings?.public
22
+ },
23
+ indexHTMLChanged: parsedMessage?.indexHTMLChanged
24
+ })
25
+ );
26
+ }
27
+ }
28
+ }
29
+ });
30
+ websocketServer.on("connection", function connection(websocketConnection) {
31
+ const connectionId = generateId();
32
+ process.HMR_CONNECTIONS = {
33
+ ...process.HMR_CONNECTIONS || {},
34
+ [connectionId]: {
35
+ connection: websocketConnection,
36
+ watchlist: []
37
+ }
38
+ };
39
+ if (Object.keys(process.HMR_CONNECTIONS || {})?.length > 0) {
40
+ process.send({ type: "HAS_HMR_CONNECTIONS" });
41
+ }
42
+ websocketConnection.on("message", (message) => {
43
+ const parsedMessage = JSON.parse(message);
44
+ if (parsedMessage?.type === "HMR_UPDATE_COMPLETE") {
45
+ process.send({ type: "HMR_UPDATE_COMPLETED", sessions: parsedMessage?.sessions });
46
+ }
47
+ if (parsedMessage?.type === "HMR_WATCHLIST") {
48
+ process.HMR_CONNECTIONS[connectionId]?.watchlist?.push(
49
+ ...parsedMessage?.tags || []
50
+ );
51
+ }
52
+ });
53
+ websocketConnection.on("close", () => {
54
+ if (process.HMR_CONNECTIONS[connectionId]) {
55
+ delete process.HMR_CONNECTIONS[connectionId];
56
+ if (Object.keys(process.HMR_CONNECTIONS || {})?.length === 0) {
57
+ process.send({ type: "HAS_NO_HMR_CONNECTIONS" });
58
+ }
59
+ }
60
+ });
61
+ });
62
+ return true;
63
+ })();
64
+ export {
65
+ hmrServer_default as default
66
+ };
@@ -19,6 +19,7 @@ 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
+ const processIds = [];
22
23
  const getDatabaseProcessIds = () => {
23
24
  try {
24
25
  const databaseProcessIds = [];
@@ -43,7 +44,7 @@ const getDatabaseProcessIds = () => {
43
44
  throw new Error(`[dev.getDatabaseProcessIds] ${exception.message}`);
44
45
  }
45
46
  };
46
- const handleSignalEvents = (processIds = [], nodeMajorVersion = 0, __dirname = "") => {
47
+ const handleSignalEvents = (processIds2 = [], nodeMajorVersion = 0, __dirname = "") => {
47
48
  try {
48
49
  const execArgv = ["--no-warnings"];
49
50
  if (nodeMajorVersion < 19) {
@@ -62,14 +63,15 @@ const handleSignalEvents = (processIds = [], nodeMajorVersion = 0, __dirname = "
62
63
  silent: true
63
64
  }
64
65
  );
66
+ process.cleanupProcess = cleanupProcess;
65
67
  process.on("SIGINT", async () => {
66
68
  const databaseProcessIds = getDatabaseProcessIds();
67
- cleanupProcess.send(JSON.stringify({ processIds: [...processIds, ...databaseProcessIds] }));
69
+ cleanupProcess.send(JSON.stringify({ processIds: [...processIds2, ...databaseProcessIds] }));
68
70
  process.exit();
69
71
  });
70
72
  process.on("SIGTERM", async () => {
71
73
  const databaseProcessIds = getDatabaseProcessIds();
72
- cleanupProcess.send(JSON.stringify({ processIds: [...processIds, ...databaseProcessIds] }));
74
+ cleanupProcess.send(JSON.stringify({ processIds: [...processIds2, ...databaseProcessIds] }));
73
75
  process.exit();
74
76
  });
75
77
  } catch (exception) {
@@ -143,7 +145,7 @@ const handleServerProcessMessages = () => {
143
145
  throw new Error(`[dev.handleServerProcessMessages] ${exception.message}`);
144
146
  }
145
147
  };
146
- const handleServerProcessSTDIO = () => {
148
+ const handleServerProcessSTDIO = (options = {}) => {
147
149
  try {
148
150
  if (process.serverProcess) {
149
151
  process.serverProcess.on("error", (error) => {
@@ -151,7 +153,7 @@ const handleServerProcessSTDIO = () => {
151
153
  });
152
154
  process.serverProcess.stdout.on("data", (data) => {
153
155
  const message = data.toString();
154
- if (message && message.includes("App running at:")) {
156
+ if (message && message.includes("App running at:") && !options?.watch) {
155
157
  process.loader.stable(message);
156
158
  } else {
157
159
  if (message && !message.includes("BUILD_ERROR")) {
@@ -175,11 +177,10 @@ const handleAddOrChangeFile = async (context = {}, path2 = "", options = {}) =>
175
177
  try {
176
178
  if (context.isAddingOrChangingFile) {
177
179
  const codependencies = await getCodependenciesForFile(path2);
178
- const fileResults = await buildFiles(
179
- [path2, ...codependencies?.existing || []],
180
- null,
181
- process.env.NODE_ENV
182
- );
180
+ const fileResults = await buildFiles({
181
+ files: [path2, ...codependencies?.existing || []],
182
+ environment: process.env.NODE_ENV
183
+ });
183
184
  const fileResultsHaveErrors = fileResults.filter((result) => !!result).map(({ success }) => success).includes(false);
184
185
  removeDeletedDependenciesFromMap(codependencies.deleted);
185
186
  if (process.serverProcess && fileResultsHaveErrors) {
@@ -252,17 +253,11 @@ const handleCopyDirectory = (context = {}, path2 = "", options = {}) => {
252
253
  const handleRestartApplicationProcess = async (options = {}) => {
253
254
  try {
254
255
  if (process.serverProcess && process.serverProcess.pid) {
255
- process.loader.text("Restarting app...");
256
256
  process.serverProcess.kill();
257
- await startApp({
258
- nodeMajorVersion: options?.nodeMajorVersion,
259
- port: options?.port,
260
- sessionsBeforeHMRUpdate: options?.sessionsBeforeHMRUpdate
261
- });
257
+ await handleStartAppServer(options);
262
258
  return Promise.resolve();
263
259
  }
264
- process.loader.text("Starting app...");
265
- startApplicationProcess();
260
+ await handleStartAppServer(options);
266
261
  if (!process.hmrProcess) {
267
262
  startHMR();
268
263
  }
@@ -270,19 +265,39 @@ const handleRestartApplicationProcess = async (options = {}) => {
270
265
  throw new Error(`[dev.handleRestartApplicationProcess] ${exception.message}`);
271
266
  }
272
267
  };
273
- const handleNotifyHMRClients = (indexHTMLChanged = false) => {
268
+ const handleStartAppServer = async (options = {}) => {
269
+ try {
270
+ const serverProcess = await startApp({
271
+ watch: options?.watch,
272
+ nodeMajorVersion: options?.nodeMajorVersion,
273
+ port: options?.port,
274
+ sessionsBeforeHMRUpdate: options?.sessionsBeforeHMRUpdate
275
+ });
276
+ if (serverProcess) {
277
+ processIds.push(serverProcess.pid);
278
+ process.serverProcess = serverProcess;
279
+ handleServerProcessSTDIO(options);
280
+ handleServerProcessMessages(options);
281
+ }
282
+ } catch (exception) {
283
+ console.warn(exception);
284
+ throw new Error(`[dev.handleStartAppServer] ${exception.message}`);
285
+ }
286
+ };
287
+ const handleNotifyHMRClients = async (indexHTMLChanged = false) => {
274
288
  try {
275
289
  if (process.hmrProcess) {
276
- const settings = loadSettings(process.env.NODE_ENV);
290
+ const settings = await loadSettings({ environment: process.env.NODE_ENV });
277
291
  process.hmrProcess.send(
278
292
  JSON.stringify({
279
293
  type: "RESTART_SERVER",
280
- settings,
294
+ settings: settings.parsed,
281
295
  indexHTMLChanged
282
296
  })
283
297
  );
284
298
  }
285
299
  } catch (exception) {
300
+ console.warn(exception);
286
301
  throw new Error(`[dev.handleNotifyHMRClients] ${exception.message}`);
287
302
  }
288
303
  };
@@ -299,7 +314,7 @@ const getWatchChangeContext = (event = "", path2 = "") => {
299
314
  const isAddDirectory = event === "addDir" && isExistingDirectoryInSource && !isExistingDirectoryInBuild;
300
315
  const isFileToCopy = !!filesToCopy.find((fileToCopy) => fileToCopy.path === path2);
301
316
  const isExistingFileInSource = isFile && fs.existsSync(path2);
302
- const isAddingOrChangingFile = event === "add" && isExistingFileInSource;
317
+ const isAddingOrChangingFile = ["add", "change"].includes(event) && isExistingFileInSource;
303
318
  return {
304
319
  isHTMLUpdate,
305
320
  isUIPath,
@@ -326,7 +341,9 @@ const startFileWatcher = (options = {}) => {
326
341
  );
327
342
  watcher.on("all", async (event, path2) => {
328
343
  checkForRequiredFiles();
329
- process.loader.text("Rebuilding app...");
344
+ if (!options?.watch) {
345
+ process.loader.text("Rebuilding app...");
346
+ }
330
347
  const watchChangeContext = getWatchChangeContext(event, path2);
331
348
  handleCopyDirectory(watchChangeContext, path2, options);
332
349
  handleCopyFile(watchChangeContext, path2, options);
@@ -484,18 +501,14 @@ const dev = async (options, { resolve, reject }) => {
484
501
  settings: settings.parsed
485
502
  });
486
503
  await runInitialBuild(settings?.parsed?.config?.build);
487
- await startFileWatcher(options);
488
- const processIds = [];
489
- const serverProcess = await startApp({
490
- nodeMajorVersion,
491
- port: options?.port
504
+ await startFileWatcher({
505
+ ...options,
506
+ nodeMajorVersion
507
+ });
508
+ await handleStartAppServer({
509
+ ...options,
510
+ nodeMajorVersion
492
511
  });
493
- if (serverProcess) {
494
- processIds.push(serverProcess.pid);
495
- process.serverProcess = serverProcess;
496
- handleServerProcessSTDIO();
497
- handleServerProcessMessages();
498
- }
499
512
  if (options?.environment !== "test") {
500
513
  const hmrProcess = await startHMR({
501
514
  nodeMajorVersion,
@@ -504,7 +517,10 @@ const dev = async (options, { resolve, reject }) => {
504
517
  processIds.push(hmrProcess.pid);
505
518
  process.hmrProcess = hmrProcess;
506
519
  handleHMRProcessSTDIO();
507
- handleHMRProcessMessages(options);
520
+ handleHMRProcessMessages({
521
+ ...options,
522
+ nodeMajorVersion
523
+ });
508
524
  }
509
525
  handleSignalEvents(
510
526
  processIds,
@@ -512,10 +528,20 @@ const dev = async (options, { resolve, reject }) => {
512
528
  __dirname
513
529
  );
514
530
  if (options?.environment === "test") {
515
- process.loader.text("Running tests...");
531
+ process.loader.stop();
532
+ const databaseProcessIds = getDatabaseProcessIds();
516
533
  await runTests({
517
- __dirname
534
+ watch: options?.watch,
535
+ __dirname,
536
+ processIds: [
537
+ ...processIds,
538
+ ...databaseProcessIds
539
+ ],
540
+ cleanupProcess: process.cleanupProcess
518
541
  });
542
+ if (!options?.watch) {
543
+ process.exit(0);
544
+ }
519
545
  }
520
546
  resolve();
521
547
  } catch (exception) {
@@ -1,39 +1,71 @@
1
1
  import child_process from "child_process";
2
- const handleAvaSTDIO = (ava = {}) => {
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
- if (!string?.includes("ava")) {
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
- if (!string?.includes("ava")) {
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 = (__dirname = "") => {
48
+ const runAva = (options = {}) => {
21
49
  try {
22
- console.log(`node_modules/.bin/ava --config ${__dirname}/tests.config.js`);
50
+ const avaPath = `${process.cwd()}/node_modules/.bin/ava`;
23
51
  return new Promise((resolve, reject) => {
24
- const ava = child_process.exec(`node_modules/.bin/ava --config ${__dirname}/tests.config.js`, {
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
- return reject();
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?.__dirname);
87
+ await runAva(options);
56
88
  resolve();
57
89
  } catch (exception) {
58
90
  reject(`[runTests] ${exception.message}`);
@@ -1,8 +1,10 @@
1
1
  import child_process from "child_process";
2
2
  import path from "path";
3
- const handleStartServerProcess = (execArgv = {}, sessionsBeforeHMRUpdate = {}) => {
3
+ const handleStartServerProcess = (execArgv = {}, options = {}) => {
4
4
  try {
5
- process.loader.text("Starting app...");
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: JSON.stringify(sessionsBeforeHMRUpdate)
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?.sessionsBeforeHMRUpdate);
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joystick.js/cli-canary",
3
- "version": "0.0.0-canary.99",
3
+ "version": "1.0.0-beta.74",
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",
@@ -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
- w: {
228
- set: !!rawArgs.includes('w') && !!rawArgs[rawArgs.indexOf('w') + 1],
229
- parent: 'w',
230
- value: !!rawArgs.includes('w') && rawArgs[rawArgs.indexOf('w') + 1],
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
- set: !!rawArgs.includes('watch') && !!rawArgs[rawArgs.indexOf('watch') + 1],
235
- parent: 'watch',
236
- value: !!rawArgs.includes('watch') && rawArgs[rawArgs.indexOf('watch') + 1],
237
- description: 'Run joystick test in watch mode.',
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
- options: {},
241
- function: test(),
246
+ function: test,
242
247
  },
243
248
  update: {
244
249
  set: !!rawArgs.includes('update'),