@joystick.js/cli-canary 1.0.0-beta.74 → 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/canary.json +1 -1
- package/dist/lib/build/buildFiles.js +8 -3
- package/dist/lib/build/buildPlugins.js +19 -5
- 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/index.js +70 -12
- package/dist/lib/dev/loadSettings.js +10 -4
- package/dist/lib/regexes.js +2 -0
- package/package.json +1 -1
- package/src/lib/build/buildFiles.js +9 -3
- package/src/lib/build/buildPlugins.js +31 -14
- 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/index.js +82 -31
- package/src/lib/dev/loadSettings.js +12 -4
- package/src/lib/regexes.js +1 -0
package/canary.json
CHANGED
|
@@ -12,6 +12,10 @@ import getCodeFrame from "./getCodeFrame.js";
|
|
|
12
12
|
import onWarn from "./onWarn.js";
|
|
13
13
|
const handleBuildException = (exception = {}, file = "") => {
|
|
14
14
|
try {
|
|
15
|
+
console.warn({
|
|
16
|
+
exception,
|
|
17
|
+
file
|
|
18
|
+
});
|
|
15
19
|
const error = exception?.errors && exception?.errors[0];
|
|
16
20
|
const snippet = fs.existsSync(file) ? getCodeFrame(file, {
|
|
17
21
|
line: error?.location?.line,
|
|
@@ -28,7 +32,7 @@ const handleBuildException = (exception = {}, file = "") => {
|
|
|
28
32
|
});
|
|
29
33
|
return snippet;
|
|
30
34
|
} catch (exception2) {
|
|
31
|
-
throw new Error(`[
|
|
35
|
+
throw new Error(`[buildFiles.handleBuildException] ${exception2.message}`);
|
|
32
36
|
}
|
|
33
37
|
};
|
|
34
38
|
const handleParseFilePathFromException = (exception = {}) => {
|
|
@@ -36,18 +40,18 @@ const handleParseFilePathFromException = (exception = {}) => {
|
|
|
36
40
|
const rawErrorMessage = exception?.message?.split(":");
|
|
37
41
|
return rawErrorMessage[1] && rawErrorMessage[1]?.replace("\n", "") || "";
|
|
38
42
|
} catch (exception2) {
|
|
39
|
-
throw new Error(`[
|
|
43
|
+
throw new Error(`[buildFiles.handleParseFilePathFromException] ${exception2.message}`);
|
|
40
44
|
}
|
|
41
45
|
};
|
|
42
46
|
const handleBuildForNode = (nodePaths2 = [], options = {}) => {
|
|
43
47
|
try {
|
|
44
48
|
return esbuild.build({
|
|
49
|
+
allowOverwrite: true,
|
|
45
50
|
platform: "node",
|
|
46
51
|
format: "esm",
|
|
47
52
|
bundle: false,
|
|
48
53
|
entryPoints: nodePaths2?.map((file) => file.path),
|
|
49
54
|
entryNames: "[dir]/[name]",
|
|
50
|
-
// TODO: Make sure we don't need outbase here so the paths map correctly.
|
|
51
55
|
outdir: options?.outputPath || "./.joystick/build",
|
|
52
56
|
outbase: "./",
|
|
53
57
|
define: {
|
|
@@ -66,6 +70,7 @@ const handleBuildForNode = (nodePaths2 = [], options = {}) => {
|
|
|
66
70
|
const handleBuildForBrowser = (browserPaths2 = [], options = {}) => {
|
|
67
71
|
try {
|
|
68
72
|
return esbuild.build({
|
|
73
|
+
allowOverwrite: true,
|
|
69
74
|
target: "es2020",
|
|
70
75
|
platform: "browser",
|
|
71
76
|
format: "esm",
|
|
@@ -5,11 +5,13 @@ import {
|
|
|
5
5
|
JOYSTICK_UI_REGEX,
|
|
6
6
|
EXPORT_DEFAULT_REGEX,
|
|
7
7
|
JOYSTICK_COMPONENT_REGEX,
|
|
8
|
-
JOYSTICK_COMMENT_REGEX
|
|
8
|
+
JOYSTICK_COMMENT_REGEX,
|
|
9
|
+
EXAMPLE_CODE_REGEX
|
|
9
10
|
} from "../regexes.js";
|
|
10
11
|
import generateId from "../generateId.js";
|
|
11
12
|
import getPlatformSafePath from "../getPlatformSafePath.js";
|
|
12
13
|
import setComponentId from "./setComponentId.js";
|
|
14
|
+
import replaceExamples from "./replaceExamples.js";
|
|
13
15
|
var buildPlugins_default = {
|
|
14
16
|
bootstrapComponent: {
|
|
15
17
|
name: "bootstrapComponent",
|
|
@@ -17,7 +19,7 @@ var buildPlugins_default = {
|
|
|
17
19
|
const ssrId = generateId();
|
|
18
20
|
build.onLoad({ filter: /\.js$/ }, (args = {}) => {
|
|
19
21
|
try {
|
|
20
|
-
const
|
|
22
|
+
const shouldSetComponentId = [getPlatformSafePath("ui/")].some(
|
|
21
23
|
(bootstrapTarget) => {
|
|
22
24
|
return args.path.includes(bootstrapTarget);
|
|
23
25
|
}
|
|
@@ -37,7 +39,7 @@ var buildPlugins_default = {
|
|
|
37
39
|
return args.path.includes(bootstrapTarget);
|
|
38
40
|
}
|
|
39
41
|
);
|
|
40
|
-
if (
|
|
42
|
+
if (shouldSetComponentId || isLayoutComponent || isPageComponent || isEmailComponent) {
|
|
41
43
|
const code = fs.readFileSync(
|
|
42
44
|
getPlatformSafePath(args.path),
|
|
43
45
|
"utf-8"
|
|
@@ -56,7 +58,9 @@ var buildPlugins_default = {
|
|
|
56
58
|
console.log(" ");
|
|
57
59
|
return;
|
|
58
60
|
}
|
|
59
|
-
|
|
61
|
+
const examples = code.match(EXAMPLE_CODE_REGEX) || [];
|
|
62
|
+
let contents = replaceExamples(code);
|
|
63
|
+
contents = contents?.replace(
|
|
60
64
|
/\.component\(\/\*\*\//g,
|
|
61
65
|
".component("
|
|
62
66
|
);
|
|
@@ -103,6 +107,10 @@ var buildPlugins_default = {
|
|
|
103
107
|
`
|
|
104
108
|
);
|
|
105
109
|
}
|
|
110
|
+
for (let i = 0; i < examples?.length; i += 1) {
|
|
111
|
+
const exampleToRestore = examples[i];
|
|
112
|
+
contents = contents.replace(`%example:${i}%`, exampleToRestore);
|
|
113
|
+
}
|
|
106
114
|
return {
|
|
107
115
|
contents,
|
|
108
116
|
loader: "js"
|
|
@@ -125,11 +133,17 @@ var buildPlugins_default = {
|
|
|
125
133
|
if (shouldSetComponentId) {
|
|
126
134
|
const file = fs.readFileSync(`${build?.initialOptions?.outdir}/${entryPoint}`, "utf-8");
|
|
127
135
|
const joystickUIMatches = file?.match(JOYSTICK_COMPONENT_REGEX) || [];
|
|
136
|
+
const examples = file.match(EXAMPLE_CODE_REGEX) || [];
|
|
137
|
+
let contents = replaceExamples(file);
|
|
128
138
|
if (joystickUIMatches?.length > 0) {
|
|
129
|
-
|
|
139
|
+
contents = setComponentId(contents)?.replace(
|
|
130
140
|
/\.component\(\/\*\*\//g,
|
|
131
141
|
".component("
|
|
132
142
|
);
|
|
143
|
+
for (let i2 = 0; i2 < examples?.length; i2 += 1) {
|
|
144
|
+
const exampleToRestore = examples[i2];
|
|
145
|
+
contents = contents.replace(`%example:${i2}%`, exampleToRestore);
|
|
146
|
+
}
|
|
133
147
|
fs.writeFileSync(`${build?.initialOptions?.outdir}/${entryPoint}`, contents);
|
|
134
148
|
}
|
|
135
149
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EXAMPLE_CODE_REGEX } from "../regexes.js";
|
|
2
|
+
var replaceExamples_default = (code = "") => {
|
|
3
|
+
let exampleIndex = 0;
|
|
4
|
+
return code.replace(
|
|
5
|
+
EXAMPLE_CODE_REGEX,
|
|
6
|
+
() => {
|
|
7
|
+
return `%example:${exampleIndex++}%`;
|
|
8
|
+
}
|
|
9
|
+
);
|
|
10
|
+
};
|
|
11
|
+
export {
|
|
12
|
+
replaceExamples_default as default
|
|
13
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import net from "net";
|
|
2
|
+
const resetClient = (client = {}) => {
|
|
3
|
+
client.end();
|
|
4
|
+
client.destroy();
|
|
5
|
+
client.unref();
|
|
6
|
+
};
|
|
7
|
+
var checkIfPortOccupied_default = (port = 2600) => {
|
|
8
|
+
return new Promise((resolve) => {
|
|
9
|
+
const client = new net.Socket();
|
|
10
|
+
client.once("connect", () => {
|
|
11
|
+
resetClient(client);
|
|
12
|
+
resolve(true);
|
|
13
|
+
});
|
|
14
|
+
client.once("error", () => {
|
|
15
|
+
resetClient(client);
|
|
16
|
+
resolve(false);
|
|
17
|
+
});
|
|
18
|
+
client.connect({
|
|
19
|
+
port,
|
|
20
|
+
host: "127.0.0.1"
|
|
21
|
+
}, function() {
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
export {
|
|
26
|
+
checkIfPortOccupied_default as default
|
|
27
|
+
};
|
|
@@ -30,7 +30,7 @@ var getFilesToBuild_default = (excludedPaths = [], context = null) => {
|
|
|
30
30
|
return path.includes(excludedPath);
|
|
31
31
|
});
|
|
32
32
|
}).filter((path) => {
|
|
33
|
-
return !fs.lstatSync(path).isDirectory();
|
|
33
|
+
return fs.existsSync(path) && !fs.lstatSync(path).isDirectory();
|
|
34
34
|
});
|
|
35
35
|
};
|
|
36
36
|
export {
|
package/dist/lib/dev/index.js
CHANGED
|
@@ -19,6 +19,8 @@ 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";
|
|
22
24
|
const processIds = [];
|
|
23
25
|
const getDatabaseProcessIds = () => {
|
|
24
26
|
try {
|
|
@@ -173,6 +175,29 @@ const handleServerProcessSTDIO = (options = {}) => {
|
|
|
173
175
|
throw new Error(`[dev.handleServerProcessSTDIO] ${exception.message}`);
|
|
174
176
|
}
|
|
175
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
|
+
};
|
|
176
201
|
const handleAddOrChangeFile = async (context = {}, path2 = "", options = {}) => {
|
|
177
202
|
try {
|
|
178
203
|
if (context.isAddingOrChangingFile) {
|
|
@@ -205,6 +230,7 @@ const handleAddOrChangeFile = async (context = {}, path2 = "", options = {}) =>
|
|
|
205
230
|
}
|
|
206
231
|
}
|
|
207
232
|
} catch (exception) {
|
|
233
|
+
console.warn(exception);
|
|
208
234
|
throw new Error(`[dev.handleAddOrChangeFile] ${exception.message}`);
|
|
209
235
|
}
|
|
210
236
|
};
|
|
@@ -238,7 +264,7 @@ const handleCopyFile = (context = {}, path2 = "", options = {}) => {
|
|
|
238
264
|
};
|
|
239
265
|
const handleCopyDirectory = (context = {}, path2 = "", options = {}) => {
|
|
240
266
|
try {
|
|
241
|
-
if (context.isFileToCopy && context.isDirectory && !context.
|
|
267
|
+
if (context.isFileToCopy && context.isDirectory && !context.isExistingPathInBuild) {
|
|
242
268
|
fs.mkdirSync(`./.joystick/build/${path2}`);
|
|
243
269
|
if (context.isUIUpdate) {
|
|
244
270
|
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
@@ -287,7 +313,11 @@ const handleStartAppServer = async (options = {}) => {
|
|
|
287
313
|
const handleNotifyHMRClients = async (indexHTMLChanged = false) => {
|
|
288
314
|
try {
|
|
289
315
|
if (process.hmrProcess) {
|
|
290
|
-
const
|
|
316
|
+
const databaseProcessIds = getDatabaseProcessIds();
|
|
317
|
+
const settings = await loadSettings({
|
|
318
|
+
environment: process.env.NODE_ENV,
|
|
319
|
+
processIds: [...processIds, ...databaseProcessIds]
|
|
320
|
+
});
|
|
291
321
|
process.hmrProcess.send(
|
|
292
322
|
JSON.stringify({
|
|
293
323
|
type: "RESTART_SERVER",
|
|
@@ -307,27 +337,31 @@ const getWatchChangeContext = (event = "", path2 = "") => {
|
|
|
307
337
|
const isUIPath = path2?.includes("ui/") || path2 === "index.css" || isHTMLUpdate;
|
|
308
338
|
const isUIUpdate = process.hmrProcess && process.hmrProcess.hasConnections && isUIPath || false;
|
|
309
339
|
const isSettingsUpdate = path2?.match(SETTINGS_FILE_NAME_REGEX)?.length > 0;
|
|
310
|
-
const
|
|
311
|
-
const
|
|
312
|
-
const
|
|
313
|
-
const
|
|
314
|
-
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;
|
|
315
346
|
const isFileToCopy = !!filesToCopy.find((fileToCopy) => fileToCopy.path === path2);
|
|
316
|
-
const isExistingFileInSource = isFile &&
|
|
347
|
+
const isExistingFileInSource = isFile && pathExists;
|
|
317
348
|
const isAddingOrChangingFile = ["add", "change"].includes(event) && isExistingFileInSource;
|
|
349
|
+
const isDeletingPath = ["unlink", "unlinkDir"].includes(event);
|
|
318
350
|
return {
|
|
351
|
+
pathExists,
|
|
319
352
|
isHTMLUpdate,
|
|
320
353
|
isUIPath,
|
|
321
354
|
isUIUpdate,
|
|
322
355
|
isSettingsUpdate,
|
|
323
356
|
isDirectory,
|
|
324
357
|
isFile,
|
|
325
|
-
|
|
326
|
-
|
|
358
|
+
isExistingPathInSource,
|
|
359
|
+
isExistingPathInBuild,
|
|
327
360
|
isAddDirectory,
|
|
328
361
|
isFileToCopy,
|
|
329
362
|
isExistingFileInSource,
|
|
330
|
-
isAddingOrChangingFile
|
|
363
|
+
isAddingOrChangingFile,
|
|
364
|
+
isDeletingPath
|
|
331
365
|
};
|
|
332
366
|
} catch (exception) {
|
|
333
367
|
throw new Error(`[dev.getWatchChangeContext] ${exception.message}`);
|
|
@@ -349,10 +383,12 @@ const startFileWatcher = (options = {}) => {
|
|
|
349
383
|
handleCopyFile(watchChangeContext, path2, options);
|
|
350
384
|
handleAddDirectory(watchChangeContext, path2, options);
|
|
351
385
|
await handleAddOrChangeFile(watchChangeContext, path2, options);
|
|
386
|
+
await handleDeletePath(watchChangeContext, path2, options);
|
|
352
387
|
if (watchChangeContext?.isSettingsUpdate) {
|
|
388
|
+
const databaseProcessIds = getDatabaseProcessIds();
|
|
353
389
|
await loadSettings({
|
|
354
390
|
environment: options.environment,
|
|
355
|
-
|
|
391
|
+
processIds: [...processIds, ...databaseProcessIds]
|
|
356
392
|
});
|
|
357
393
|
}
|
|
358
394
|
});
|
|
@@ -470,6 +506,16 @@ const warnInvalidJoystickEnvironment = () => {
|
|
|
470
506
|
throw new Error(`[dev.warnInvalidJoystickEnvironment] ${exception.message}`);
|
|
471
507
|
}
|
|
472
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
|
+
};
|
|
473
519
|
const validateOptions = (options) => {
|
|
474
520
|
try {
|
|
475
521
|
if (!options)
|
|
@@ -483,6 +529,18 @@ const validateOptions = (options) => {
|
|
|
483
529
|
const dev = async (options, { resolve, reject }) => {
|
|
484
530
|
try {
|
|
485
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
|
+
}
|
|
486
544
|
initProcess(options);
|
|
487
545
|
const nodeMajorVersion = parseInt(
|
|
488
546
|
process?.version?.split(".")[0]?.replace("v", ""),
|
|
@@ -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/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
|
@@ -13,6 +13,11 @@ import onWarn from "./onWarn.js";
|
|
|
13
13
|
|
|
14
14
|
const handleBuildException = (exception = {}, file = '') => {
|
|
15
15
|
try {
|
|
16
|
+
console.warn({
|
|
17
|
+
exception,
|
|
18
|
+
file,
|
|
19
|
+
});
|
|
20
|
+
|
|
16
21
|
const error = exception?.errors && exception?.errors[0];
|
|
17
22
|
const snippet = fs.existsSync(file)
|
|
18
23
|
? getCodeFrame(file, {
|
|
@@ -33,7 +38,7 @@ const handleBuildException = (exception = {}, file = '') => {
|
|
|
33
38
|
|
|
34
39
|
return snippet;
|
|
35
40
|
} catch (exception) {
|
|
36
|
-
throw new Error(`[
|
|
41
|
+
throw new Error(`[buildFiles.handleBuildException] ${exception.message}`);
|
|
37
42
|
}
|
|
38
43
|
};
|
|
39
44
|
|
|
@@ -42,19 +47,19 @@ const handleParseFilePathFromException = (exception = {}) => {
|
|
|
42
47
|
const rawErrorMessage = exception?.message?.split(':');
|
|
43
48
|
return rawErrorMessage[1] && rawErrorMessage[1]?.replace('\n', '') || '';
|
|
44
49
|
} catch (exception) {
|
|
45
|
-
throw new Error(`[
|
|
50
|
+
throw new Error(`[buildFiles.handleParseFilePathFromException] ${exception.message}`);
|
|
46
51
|
}
|
|
47
52
|
};
|
|
48
53
|
|
|
49
54
|
const handleBuildForNode = (nodePaths = [], options = {}) => {
|
|
50
55
|
try {
|
|
51
56
|
return esbuild.build({
|
|
57
|
+
allowOverwrite: true,
|
|
52
58
|
platform: "node",
|
|
53
59
|
format: "esm",
|
|
54
60
|
bundle: false,
|
|
55
61
|
entryPoints: nodePaths?.map((file) => file.path),
|
|
56
62
|
entryNames: '[dir]/[name]',
|
|
57
|
-
// TODO: Make sure we don't need outbase here so the paths map correctly.
|
|
58
63
|
outdir: options?.outputPath || "./.joystick/build",
|
|
59
64
|
outbase: './',
|
|
60
65
|
define: {
|
|
@@ -74,6 +79,7 @@ const handleBuildForNode = (nodePaths = [], options = {}) => {
|
|
|
74
79
|
const handleBuildForBrowser = (browserPaths = [], options = {}) => {
|
|
75
80
|
try {
|
|
76
81
|
return esbuild.build({
|
|
82
|
+
allowOverwrite: true,
|
|
77
83
|
target: "es2020",
|
|
78
84
|
platform: "browser",
|
|
79
85
|
format: "esm",
|
|
@@ -5,11 +5,12 @@ import {
|
|
|
5
5
|
JOYSTICK_UI_REGEX,
|
|
6
6
|
EXPORT_DEFAULT_REGEX,
|
|
7
7
|
JOYSTICK_COMPONENT_REGEX,
|
|
8
|
-
JOYSTICK_COMMENT_REGEX,
|
|
8
|
+
JOYSTICK_COMMENT_REGEX, EXAMPLE_CODE_REGEX,
|
|
9
9
|
} from "../regexes.js";
|
|
10
10
|
import generateId from "../generateId.js";
|
|
11
11
|
import getPlatformSafePath from "../getPlatformSafePath.js";
|
|
12
12
|
import setComponentId from "./setComponentId.js";
|
|
13
|
+
import replaceExamples from "./replaceExamples.js";
|
|
13
14
|
|
|
14
15
|
export default {
|
|
15
16
|
bootstrapComponent: {
|
|
@@ -21,7 +22,7 @@ export default {
|
|
|
21
22
|
|
|
22
23
|
build.onLoad({ filter: /\.js$/ }, (args = {}) => {
|
|
23
24
|
try {
|
|
24
|
-
const
|
|
25
|
+
const shouldSetComponentId = [getPlatformSafePath("ui/")].some(
|
|
25
26
|
(bootstrapTarget) => {
|
|
26
27
|
return args.path.includes(bootstrapTarget);
|
|
27
28
|
}
|
|
@@ -46,7 +47,7 @@ export default {
|
|
|
46
47
|
);
|
|
47
48
|
|
|
48
49
|
if (
|
|
49
|
-
|
|
50
|
+
shouldSetComponentId ||
|
|
50
51
|
isLayoutComponent ||
|
|
51
52
|
isPageComponent ||
|
|
52
53
|
isEmailComponent
|
|
@@ -74,20 +75,20 @@ export default {
|
|
|
74
75
|
return;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
|
|
78
|
+
// NOTE: Replace any <example> bracketed code with a placeholder. This ensures
|
|
79
|
+
// that we don't accidentally include any mounting code in example code included
|
|
80
|
+
// as content on the page.
|
|
81
|
+
const examples = code.match(EXAMPLE_CODE_REGEX) || [];
|
|
82
|
+
let contents = replaceExamples(code);
|
|
83
|
+
|
|
84
|
+
contents = contents?.replace(
|
|
78
85
|
/\.component\(\/\*\*\//g,
|
|
79
86
|
".component("
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// contents = contents.replace(
|
|
83
|
-
// "ui.component({",
|
|
84
|
-
// `ui.component({\n _ssrId: '${ssrId}',`
|
|
85
|
-
// );
|
|
87
|
+
);
|
|
86
88
|
|
|
87
89
|
// NOTE: Remove any commented code inside of render() so it doesn't get rendered during SSR
|
|
88
90
|
// or in the browser.
|
|
89
91
|
contents = contents.replace(JOYSTICK_COMMENT_REGEX, "");
|
|
90
|
-
|
|
91
92
|
const exportDefaultMatchParts =
|
|
92
93
|
(exportDefaultMatch && exportDefaultMatch.split(" ")) || [];
|
|
93
94
|
const componentName = exportDefaultMatchParts.pop();
|
|
@@ -134,6 +135,11 @@ export default {
|
|
|
134
135
|
);
|
|
135
136
|
}
|
|
136
137
|
|
|
138
|
+
for (let i = 0; i < examples?.length; i += 1) {
|
|
139
|
+
const exampleToRestore = examples[i];
|
|
140
|
+
contents = contents.replace(`%example:${i}%`, exampleToRestore);
|
|
141
|
+
}
|
|
142
|
+
|
|
137
143
|
return {
|
|
138
144
|
contents,
|
|
139
145
|
loader: "js",
|
|
@@ -160,21 +166,32 @@ export default {
|
|
|
160
166
|
const joystickUIMatches =
|
|
161
167
|
file?.match(JOYSTICK_COMPONENT_REGEX) || [];
|
|
162
168
|
|
|
169
|
+
// NOTE: Replace any <example> bracketed code with a placeholder. This ensures
|
|
170
|
+
// that we don't accidentally add a componentId to any example code included
|
|
171
|
+
// as content on the page.
|
|
172
|
+
const examples = file.match(EXAMPLE_CODE_REGEX) || [];
|
|
173
|
+
let contents = replaceExamples(file);
|
|
174
|
+
|
|
163
175
|
if (joystickUIMatches?.length > 0) {
|
|
164
|
-
|
|
176
|
+
contents = setComponentId(contents)?.replace(
|
|
165
177
|
/\.component\(\/\*\*\//g,
|
|
166
178
|
".component("
|
|
167
179
|
);
|
|
180
|
+
|
|
181
|
+
for (let i = 0; i < examples?.length; i += 1) {
|
|
182
|
+
const exampleToRestore = examples[i];
|
|
183
|
+
contents = contents.replace(`%example:${i}%`, exampleToRestore);
|
|
184
|
+
}
|
|
168
185
|
|
|
169
186
|
fs.writeFileSync(`${build?.initialOptions?.outdir}/${entryPoint}`, contents);
|
|
170
187
|
}
|
|
171
|
-
}
|
|
188
|
+
}
|
|
172
189
|
}
|
|
173
190
|
|
|
174
191
|
resolve();
|
|
175
192
|
});
|
|
176
193
|
});
|
|
177
|
-
|
|
194
|
+
},
|
|
178
195
|
},
|
|
179
196
|
generateFileDependencyMap: {
|
|
180
197
|
name: "generateFileDependencyMap",
|
|
@@ -27,7 +27,7 @@ export default (file = "") => {
|
|
|
27
27
|
source: file.substring(
|
|
28
28
|
part.index,
|
|
29
29
|
nextPart ? nextPart.index : file.length
|
|
30
|
-
|
|
30
|
+
),
|
|
31
31
|
};
|
|
32
32
|
});
|
|
33
33
|
|
|
@@ -45,7 +45,7 @@ export default (file = "") => {
|
|
|
45
45
|
() => {
|
|
46
46
|
return `.component({\n _componentId: '${componentId}',`;
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
);
|
|
49
49
|
|
|
50
50
|
file = file.replace(component.source, tainted);
|
|
51
51
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import net from 'net';
|
|
2
|
+
|
|
3
|
+
const resetClient = (client = {}) => {
|
|
4
|
+
client.end();
|
|
5
|
+
client.destroy();
|
|
6
|
+
client.unref();
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default (port = 2600) => {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
const client = new net.Socket();
|
|
12
|
+
|
|
13
|
+
// NOTE: This is inverted. If we can connect, the port is occupied. If we can't, the port is free.
|
|
14
|
+
client.once('connect', () => {
|
|
15
|
+
resetClient(client);
|
|
16
|
+
resolve(true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
client.once('error', () => {
|
|
20
|
+
resetClient(client);
|
|
21
|
+
resolve(false);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
client.connect({
|
|
25
|
+
port,
|
|
26
|
+
host: '127.0.0.1',
|
|
27
|
+
}, function() {});
|
|
28
|
+
});
|
|
29
|
+
};
|
package/src/lib/dev/index.js
CHANGED
|
@@ -21,6 +21,8 @@ import { SETTINGS_FILE_NAME_REGEX } from "../regexes.js";
|
|
|
21
21
|
import getCodependenciesForFile from "./getCodependenciesForFile.js";
|
|
22
22
|
import removeDeletedDependenciesFromMap from "../build/removeDeletedDependenciesFromMap.js";
|
|
23
23
|
import chalk from "chalk";
|
|
24
|
+
import checkIfPortOccupied from "../checkIfPortOccupied.js";
|
|
25
|
+
import {killPortProcess} from "kill-port-process";
|
|
24
26
|
|
|
25
27
|
const processIds = [];
|
|
26
28
|
|
|
@@ -208,6 +210,33 @@ const handleServerProcessSTDIO = (options = {}) => {
|
|
|
208
210
|
}
|
|
209
211
|
};
|
|
210
212
|
|
|
213
|
+
const handleDeletePath = (context = {}, path = '', options = {}) => {
|
|
214
|
+
try {
|
|
215
|
+
if (context?.isDeletingPath) {
|
|
216
|
+
if (context.isExistingPathInBuild) {
|
|
217
|
+
const pathToUnlink = `./.joystick/build/${path}`;
|
|
218
|
+
const stats = fs.lstatSync(pathToUnlink);
|
|
219
|
+
|
|
220
|
+
if (stats.isDirectory()) {
|
|
221
|
+
fs.rmdirSync(pathToUnlink, { recursive: true });
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (stats.isFile()) {
|
|
225
|
+
fs.unlinkSync(pathToUnlink);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (context.isUIUpdate) {
|
|
230
|
+
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
231
|
+
} else {
|
|
232
|
+
handleRestartApplicationProcess(options);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} catch (exception) {
|
|
236
|
+
throw new Error(`[dev.handleDeletePath] ${exception.message}`);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
211
240
|
const handleAddOrChangeFile = async (context = {}, path = '', options = {}) => {
|
|
212
241
|
try {
|
|
213
242
|
if (context.isAddingOrChangingFile) {
|
|
@@ -253,6 +282,7 @@ const handleAddOrChangeFile = async (context = {}, path = '', options = {}) => {
|
|
|
253
282
|
}
|
|
254
283
|
}
|
|
255
284
|
} catch (exception) {
|
|
285
|
+
console.warn(exception);
|
|
256
286
|
throw new Error(`[dev.handleAddOrChangeFile] ${exception.message}`);
|
|
257
287
|
}
|
|
258
288
|
};
|
|
@@ -291,7 +321,7 @@ const handleCopyFile = (context = {}, path = '', options = {}) => {
|
|
|
291
321
|
|
|
292
322
|
const handleCopyDirectory = (context = {}, path = '', options = {}) => {
|
|
293
323
|
try {
|
|
294
|
-
if (context.isFileToCopy && context.isDirectory && !context.
|
|
324
|
+
if (context.isFileToCopy && context.isDirectory && !context.isExistingPathInBuild) {
|
|
295
325
|
fs.mkdirSync(`./.joystick/build/${path}`);
|
|
296
326
|
|
|
297
327
|
if (context.isUIUpdate) {
|
|
@@ -350,7 +380,12 @@ const handleStartAppServer = async (options = {}) => {
|
|
|
350
380
|
const handleNotifyHMRClients = async (indexHTMLChanged = false) => {
|
|
351
381
|
try {
|
|
352
382
|
if (process.hmrProcess) {
|
|
353
|
-
const
|
|
383
|
+
const databaseProcessIds = getDatabaseProcessIds();
|
|
384
|
+
const settings = await loadSettings({
|
|
385
|
+
environment: process.env.NODE_ENV,
|
|
386
|
+
processIds: [...processIds, ...databaseProcessIds],
|
|
387
|
+
});
|
|
388
|
+
|
|
354
389
|
process.hmrProcess.send(
|
|
355
390
|
JSON.stringify({
|
|
356
391
|
type: "RESTART_SERVER",
|
|
@@ -371,28 +406,32 @@ const getWatchChangeContext = (event = '', path = '') => {
|
|
|
371
406
|
const isUIPath = path?.includes("ui/") || path === 'index.css' || isHTMLUpdate;
|
|
372
407
|
const isUIUpdate = (process.hmrProcess && process.hmrProcess.hasConnections && isUIPath) || false;
|
|
373
408
|
const isSettingsUpdate = path?.match(SETTINGS_FILE_NAME_REGEX)?.length > 0;
|
|
374
|
-
const
|
|
375
|
-
const
|
|
376
|
-
const
|
|
377
|
-
const
|
|
378
|
-
const
|
|
409
|
+
const pathExists = fs.existsSync(path);
|
|
410
|
+
const isDirectory = pathExists && fs.statSync(path).isDirectory();
|
|
411
|
+
const isFile = pathExists && fs.statSync(path).isFile();
|
|
412
|
+
const isExistingPathInSource = isDirectory && pathExists;
|
|
413
|
+
const isExistingPathInBuild = !!fs.existsSync(`./.joystick/build/${path}`);
|
|
414
|
+
const isAddDirectory = event === 'addDir' && isExistingPathInSource && !isExistingPathInBuild;
|
|
379
415
|
const isFileToCopy = !!filesToCopy.find((fileToCopy) => fileToCopy.path === path);
|
|
380
|
-
const isExistingFileInSource = isFile &&
|
|
416
|
+
const isExistingFileInSource = isFile && pathExists;
|
|
381
417
|
const isAddingOrChangingFile = ["add", "change"].includes(event) && isExistingFileInSource;
|
|
418
|
+
const isDeletingPath = ["unlink", "unlinkDir"].includes(event);
|
|
382
419
|
|
|
383
420
|
return {
|
|
421
|
+
pathExists,
|
|
384
422
|
isHTMLUpdate,
|
|
385
423
|
isUIPath,
|
|
386
424
|
isUIUpdate,
|
|
387
425
|
isSettingsUpdate,
|
|
388
426
|
isDirectory,
|
|
389
427
|
isFile,
|
|
390
|
-
|
|
391
|
-
|
|
428
|
+
isExistingPathInSource,
|
|
429
|
+
isExistingPathInBuild,
|
|
392
430
|
isAddDirectory,
|
|
393
431
|
isFileToCopy,
|
|
394
432
|
isExistingFileInSource,
|
|
395
433
|
isAddingOrChangingFile,
|
|
434
|
+
isDeletingPath,
|
|
396
435
|
};
|
|
397
436
|
} catch (exception) {
|
|
398
437
|
throw new Error(`[dev.getWatchChangeContext] ${exception.message}`);
|
|
@@ -415,20 +454,19 @@ const startFileWatcher = (options = {}) => {
|
|
|
415
454
|
}
|
|
416
455
|
|
|
417
456
|
const watchChangeContext = getWatchChangeContext(event, path);
|
|
418
|
-
|
|
419
|
-
// console.log({
|
|
420
|
-
// watchChangeContext,
|
|
421
|
-
// });
|
|
422
|
-
//
|
|
457
|
+
|
|
423
458
|
handleCopyDirectory(watchChangeContext, path, options);
|
|
424
459
|
handleCopyFile(watchChangeContext, path, options);
|
|
425
460
|
handleAddDirectory(watchChangeContext, path, options);
|
|
461
|
+
|
|
426
462
|
await handleAddOrChangeFile(watchChangeContext, path, options);
|
|
463
|
+
await handleDeletePath(watchChangeContext, path, options);
|
|
427
464
|
|
|
428
465
|
if (watchChangeContext?.isSettingsUpdate) {
|
|
466
|
+
const databaseProcessIds = getDatabaseProcessIds();
|
|
429
467
|
await loadSettings({
|
|
430
468
|
environment: options.environment,
|
|
431
|
-
|
|
469
|
+
processIds: [...processIds, ...databaseProcessIds],
|
|
432
470
|
});
|
|
433
471
|
}
|
|
434
472
|
});
|
|
@@ -567,6 +605,17 @@ const warnInvalidJoystickEnvironment = () => {
|
|
|
567
605
|
}
|
|
568
606
|
};
|
|
569
607
|
|
|
608
|
+
const handleCleanup = () => {
|
|
609
|
+
try {
|
|
610
|
+
if (process.cleanupProcess) {
|
|
611
|
+
const databaseProcessIds = getDatabaseProcessIds();
|
|
612
|
+
process.cleanupProcess.send(JSON.stringify(({ processIds: [...processIds, ...databaseProcessIds] })));
|
|
613
|
+
}
|
|
614
|
+
} catch (exception) {
|
|
615
|
+
throw new Error(`[actionName.handleCleanup] ${exception.message}`);
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
|
|
570
619
|
const validateOptions = (options) => {
|
|
571
620
|
try {
|
|
572
621
|
if (!options) throw new Error('options object is required.');
|
|
@@ -579,6 +628,23 @@ const validateOptions = (options) => {
|
|
|
579
628
|
const dev = async (options, { resolve, reject }) => {
|
|
580
629
|
try {
|
|
581
630
|
validateOptions(options);
|
|
631
|
+
|
|
632
|
+
const port = parseInt(options?.port || 2600, 10);
|
|
633
|
+
const appPortOccupied = await checkIfPortOccupied(port);
|
|
634
|
+
const hmrPortOccupied = await checkIfPortOccupied(port + 1);
|
|
635
|
+
|
|
636
|
+
if (appPortOccupied) {
|
|
637
|
+
CLILog(`Port ${options?.port} is already occupied. To start Joystick on this port, clear it and try again.`, {
|
|
638
|
+
level: 'danger',
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
process.exit(0);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (hmrPortOccupied) {
|
|
645
|
+
await killPortProcess(port + 1);
|
|
646
|
+
}
|
|
647
|
+
|
|
582
648
|
initProcess(options);
|
|
583
649
|
|
|
584
650
|
const nodeMajorVersion = parseInt(
|
|
@@ -655,21 +721,6 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
655
721
|
process.exit(0);
|
|
656
722
|
}
|
|
657
723
|
}
|
|
658
|
-
|
|
659
|
-
/*
|
|
660
|
-
TODO:
|
|
661
|
-
|
|
662
|
-
- [x] Make sure we're in a Joystick project.
|
|
663
|
-
- [x] If environment === 'test', check that both a .joystick fo lder exists AND a /tests folder
|
|
664
|
-
exists. If no /tests, log out docs on how to scaffold your tests.
|
|
665
|
-
- [x] Load settings.<environment>.json.
|
|
666
|
-
- [x] Start databases relative to options.environment (development|test) from settings.<environment>.json.
|
|
667
|
-
- [x] Run the initial build
|
|
668
|
-
- [x] Start the file watcher
|
|
669
|
-
- [x] Start the app as normal from the build directory.
|
|
670
|
-
- [ ] If environment === 'test', run the tests.
|
|
671
|
-
- [ ] If environment === 'test', after tests, run process.exit(0).
|
|
672
|
-
*/
|
|
673
724
|
|
|
674
725
|
resolve();
|
|
675
726
|
} catch (exception) {
|
|
@@ -4,7 +4,7 @@ import fs from 'fs';
|
|
|
4
4
|
import CLILog from "../CLILog.js";
|
|
5
5
|
import isValidJSONString from "../isValidJSONString.js";
|
|
6
6
|
|
|
7
|
-
const warnIfInvalidJSONInSettings = (settings = '') => {
|
|
7
|
+
const warnIfInvalidJSONInSettings = (settings = '', processIds = []) => {
|
|
8
8
|
try {
|
|
9
9
|
const isValidJSON = isValidJSONString(settings);
|
|
10
10
|
const context = process.env.NODE_ENV === 'test' ? 'test' : 'start';
|
|
@@ -19,6 +19,10 @@ const warnIfInvalidJSONInSettings = (settings = '') => {
|
|
|
19
19
|
}
|
|
20
20
|
);
|
|
21
21
|
|
|
22
|
+
if (process.cleanupProcess) {
|
|
23
|
+
process.cleanupProcess.send(JSON.stringify(({ processIds })));
|
|
24
|
+
}
|
|
25
|
+
|
|
22
26
|
process.exit(0);
|
|
23
27
|
}
|
|
24
28
|
} catch (exception) {
|
|
@@ -34,7 +38,7 @@ const getSettings = (settingsPath = '') => {
|
|
|
34
38
|
}
|
|
35
39
|
};
|
|
36
40
|
|
|
37
|
-
const warnIfSettingsNotFound = (settingsPath = '') => {
|
|
41
|
+
const warnIfSettingsNotFound = (settingsPath = '', processIds = []) => {
|
|
38
42
|
try {
|
|
39
43
|
const hasSettingsFile = fs.existsSync(settingsPath);
|
|
40
44
|
const context = process.env.NODE_ENV === 'test' ? 'test' : 'start';
|
|
@@ -48,6 +52,10 @@ const warnIfSettingsNotFound = (settingsPath = '') => {
|
|
|
48
52
|
}
|
|
49
53
|
);
|
|
50
54
|
|
|
55
|
+
if (process.cleanupProcess) {
|
|
56
|
+
process.cleanupProcess.send(JSON.stringify(({ processIds })));
|
|
57
|
+
}
|
|
58
|
+
|
|
51
59
|
process.exit(0);
|
|
52
60
|
}
|
|
53
61
|
} catch (exception) {
|
|
@@ -69,9 +77,9 @@ const loadSettings = (options, { resolve, reject }) => {
|
|
|
69
77
|
validateOptions(options);
|
|
70
78
|
|
|
71
79
|
const settingsPath = `${process.cwd()}/settings.${options.environment}.json`;
|
|
72
|
-
warnIfSettingsNotFound(settingsPath);
|
|
80
|
+
warnIfSettingsNotFound(settingsPath, options.processIds);
|
|
73
81
|
const settings = getSettings(settingsPath);
|
|
74
|
-
warnIfInvalidJSONInSettings(settings);
|
|
82
|
+
warnIfInvalidJSONInSettings(settings, options.processIds);
|
|
75
83
|
|
|
76
84
|
process.env.JOYSTICK_SETTINGS = settings;
|
|
77
85
|
|
package/src/lib/regexes.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export const EXAMPLE_CODE_REGEX = new RegExp(/\<example\>[^%]+\<\/example\>/g);
|
|
1
2
|
export const EXPORT_DEFAULT_REGEX = new RegExp(/export default [a-zA-Z0-9]+/g);
|
|
2
3
|
export const JOYSTICK_COMMENT_REGEX = new RegExp(/\<\!\-\-(.|\n|\r)*?-->/g);
|
|
3
4
|
export const JOYSTICK_COMPONENT_REGEX = new RegExp(/\.component\(\{/g);
|