@joystick.js/cli-canary 0.0.0-canary.7 → 0.0.0-canary.71
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/dist/functions/start/index.js +4 -470
- package/dist/functions/start/onWarn.js +1 -1
- package/dist/lib/build/buildFiles.js +67 -5
- package/dist/lib/build/buildPlugins.js +18 -15
- package/dist/lib/build/getCodeFrame.js +3 -4
- package/dist/lib/build/onWarn.js +1 -1
- package/dist/lib/build/removeDeletedDependenciesFromMap.js +1 -1
- package/dist/lib/dev/databases/mongodb/index.js +1 -1
- package/dist/lib/dev/databases/postgresql/index.js +2 -2
- package/dist/lib/dev/databases/providerMap.js +1 -1
- package/dist/lib/dev/index.js +100 -26
- package/dist/lib/dev/isWindows.js +5 -0
- package/dist/lib/dev/loadSettings.js +1 -3
- package/dist/lib/dev/startApp.js +43 -3
- package/dist/lib/dev/startDatabases.js +12 -5
- package/dist/lib/dev/startHMR.js +30 -5
- package/dist/lib/getProcessIdFromPort.js +60 -0
- package/dist/lib/types.js +6 -0
- package/package.json +1 -1
- package/src/functions/start/index.js +615 -612
- package/src/functions/start/onWarn.js +1 -1
- package/src/lib/build/buildFiles.js +79 -6
- package/src/lib/build/buildPlugins.js +29 -22
- package/src/lib/build/getCodeFrame.js +3 -4
- package/src/lib/build/onWarn.js +1 -1
- package/src/lib/build/removeDeletedDependenciesFromMap.js +1 -1
- package/src/lib/dev/databases/mongodb/index.js +1 -1
- package/src/lib/dev/databases/postgresql/index.js +2 -2
- package/src/lib/dev/databases/providerMap.js +1 -1
- package/src/lib/dev/index.js +118 -33
- package/src/lib/dev/isWindows.js +3 -0
- package/src/lib/dev/loadSettings.js +1 -3
- package/src/lib/dev/startApp.js +52 -6
- package/src/lib/dev/startDatabases.js +12 -6
- package/src/lib/dev/startHMR.js +36 -7
- package/src/lib/getProcessIdFromPort.js +92 -0
- package/src/lib/types.js +3 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { OBJECT_REGEX } from "../../lib/regexes.js";
|
|
3
3
|
import rainbowRoad from '../../lib/rainbowRoad.js';
|
|
4
|
-
import getCodeFrame from "../../lib/getCodeFrame.js";
|
|
4
|
+
import getCodeFrame from "../../lib/build/getCodeFrame.js";
|
|
5
5
|
|
|
6
6
|
const removeLocationDataFromStackTrace = (stackTrace = "") => {
|
|
7
7
|
return stackTrace.replace(OBJECT_REGEX, "");
|
|
@@ -8,6 +8,43 @@ import browserPathExclusions from "./browserPathExclusions.js";
|
|
|
8
8
|
import nodePaths from "./nodePaths.js";
|
|
9
9
|
import nodePathExclusions from "./nodePathExclusions.js";
|
|
10
10
|
import buildPlugins from "./buildPlugins.js";
|
|
11
|
+
import getCodeFrame from "./getCodeFrame.js";
|
|
12
|
+
import onWarn from "./onWarn.js";
|
|
13
|
+
|
|
14
|
+
const handleBuildException = (exception = {}, file = '') => {
|
|
15
|
+
try {
|
|
16
|
+
const error = exception?.errors && exception?.errors[0];
|
|
17
|
+
const snippet = fs.existsSync(file)
|
|
18
|
+
? getCodeFrame(file, {
|
|
19
|
+
line: error?.location?.line,
|
|
20
|
+
column: error?.location?.column,
|
|
21
|
+
})
|
|
22
|
+
: null;
|
|
23
|
+
|
|
24
|
+
onWarn({
|
|
25
|
+
file,
|
|
26
|
+
stack: exception?.stack,
|
|
27
|
+
line: error?.location?.line,
|
|
28
|
+
column: error?.location?.column,
|
|
29
|
+
snippet,
|
|
30
|
+
lineWithError: error?.location?.lineText?.trim(),
|
|
31
|
+
message: error?.text,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return snippet;
|
|
35
|
+
} catch (exception) {
|
|
36
|
+
throw new Error(`[actionName.handleBuildException] ${exception.message}`);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const handleParseFilePathFromException = (exception = {}) => {
|
|
41
|
+
try {
|
|
42
|
+
const rawErrorMessage = exception?.message?.split(':');
|
|
43
|
+
return rawErrorMessage[1] && rawErrorMessage[1]?.replace('\n', '') || '';
|
|
44
|
+
} catch (exception) {
|
|
45
|
+
throw new Error(`[actionName.handleParseFilePathFromException] ${exception.message}`);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
11
48
|
|
|
12
49
|
const handleBuildForNode = (nodePaths = [], options = {}) => {
|
|
13
50
|
try {
|
|
@@ -63,8 +100,10 @@ const handleCopyFiles = (files = [], outputPath = '') => {
|
|
|
63
100
|
for (let i = 0; i < files?.length; i += 1) {
|
|
64
101
|
const file = files[i];
|
|
65
102
|
const fileContents = fs.readFileSync(file.path);
|
|
66
|
-
|
|
67
|
-
fs.
|
|
103
|
+
|
|
104
|
+
// NOTE: Using fs.outputFileSync() from fs-extra to ensure parent path is created
|
|
105
|
+
// if it doesn't exist (avoids need for separate fs.mkdirSync()).
|
|
106
|
+
fs.outputFileSync(
|
|
68
107
|
`${outputPath || "./.joystick/build"}/${file.path}`,
|
|
69
108
|
fileContents
|
|
70
109
|
);
|
|
@@ -129,6 +168,13 @@ const getFilePlatform = (path = '') => {
|
|
|
129
168
|
const isBrowser = isBrowserPath(path);
|
|
130
169
|
const isNode = isNodePath(path);
|
|
131
170
|
|
|
171
|
+
console.log({
|
|
172
|
+
path,
|
|
173
|
+
isCopy,
|
|
174
|
+
isBrowser,
|
|
175
|
+
isNode,
|
|
176
|
+
});
|
|
177
|
+
|
|
132
178
|
if (isCopy) {
|
|
133
179
|
platform = "copy";
|
|
134
180
|
}
|
|
@@ -181,9 +227,36 @@ const buildFiles = async (options, { resolve, reject }) => {
|
|
|
181
227
|
|
|
182
228
|
handleCopyFiles(copyFiles, options?.outputPath);
|
|
183
229
|
|
|
184
|
-
await Promise.all([
|
|
185
|
-
handleBuildForBrowser(browserFiles, options)
|
|
186
|
-
|
|
230
|
+
const fileResults = await Promise.all([
|
|
231
|
+
handleBuildForBrowser(browserFiles, options).then(() => {
|
|
232
|
+
return { success: true };
|
|
233
|
+
}).catch((exception) => {
|
|
234
|
+
const file = handleParseFilePathFromException(exception);
|
|
235
|
+
console.log(file, exception);
|
|
236
|
+
const snippet = handleBuildException(exception, file);
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
success: false,
|
|
240
|
+
path: file,
|
|
241
|
+
error: {
|
|
242
|
+
stack: exception?.stack,
|
|
243
|
+
snippet,
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
}),
|
|
247
|
+
handleBuildForNode(nodeFiles, options).catch((exception) => {
|
|
248
|
+
const file = handleParseFilePathFromException(exception);
|
|
249
|
+
const snippet = handleBuildException(exception, file);
|
|
250
|
+
|
|
251
|
+
return {
|
|
252
|
+
success: false,
|
|
253
|
+
path: file,
|
|
254
|
+
error: {
|
|
255
|
+
stack: exception?.stack,
|
|
256
|
+
snippet,
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
}),
|
|
187
260
|
]);
|
|
188
261
|
|
|
189
262
|
if (options?.environment !== 'development') {
|
|
@@ -192,7 +265,7 @@ const buildFiles = async (options, { resolve, reject }) => {
|
|
|
192
265
|
}));
|
|
193
266
|
}
|
|
194
267
|
|
|
195
|
-
resolve();
|
|
268
|
+
resolve(fileResults);
|
|
196
269
|
} catch (exception) {
|
|
197
270
|
reject(`[buildFiles] ${exception.message}`);
|
|
198
271
|
}
|
|
@@ -25,22 +25,25 @@ export default {
|
|
|
25
25
|
(bootstrapTarget) => {
|
|
26
26
|
return args.path.includes(bootstrapTarget);
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
);
|
|
29
|
+
|
|
29
30
|
const isLayoutComponent = [getPlatformSafePath("ui/layouts")].some(
|
|
30
31
|
(bootstrapTarget) => {
|
|
31
32
|
return args.path.includes(bootstrapTarget);
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
+
);
|
|
35
|
+
|
|
34
36
|
const isPageComponent = [getPlatformSafePath("ui/pages")].some(
|
|
35
37
|
(bootstrapTarget) => {
|
|
36
38
|
return args.path.includes(bootstrapTarget);
|
|
37
39
|
}
|
|
38
|
-
|
|
40
|
+
);
|
|
41
|
+
|
|
39
42
|
const isEmailComponent = [getPlatformSafePath("email/")].some(
|
|
40
43
|
(bootstrapTarget) => {
|
|
41
44
|
return args.path.includes(bootstrapTarget);
|
|
42
45
|
}
|
|
43
|
-
|
|
46
|
+
);
|
|
44
47
|
|
|
45
48
|
if (
|
|
46
49
|
shouldSetSSRId ||
|
|
@@ -51,7 +54,7 @@ export default {
|
|
|
51
54
|
const code = fs.readFileSync(
|
|
52
55
|
getPlatformSafePath(args.path),
|
|
53
56
|
"utf-8"
|
|
54
|
-
|
|
57
|
+
);
|
|
55
58
|
|
|
56
59
|
// NOTE: Check to see if we have a valid component file.
|
|
57
60
|
const joystickUIMatches = code.match(JOYSTICK_UI_REGEX) || [];
|
|
@@ -65,8 +68,8 @@ export default {
|
|
|
65
68
|
console.warn(
|
|
66
69
|
chalk.yellowBright(
|
|
67
70
|
`All Joystick components in the ui directory must have an export default statement (e.g., export default MyComponent, export default MyLayout, or export default MyPage). Please check the file at ${args.path}.`
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
)
|
|
72
|
+
);
|
|
70
73
|
console.log(" ");
|
|
71
74
|
return;
|
|
72
75
|
}
|
|
@@ -110,7 +113,7 @@ export default {
|
|
|
110
113
|
|
|
111
114
|
export default ${componentName};
|
|
112
115
|
`
|
|
113
|
-
|
|
116
|
+
);
|
|
114
117
|
}
|
|
115
118
|
|
|
116
119
|
if (componentName && isPageComponent) {
|
|
@@ -128,7 +131,7 @@ export default {
|
|
|
128
131
|
|
|
129
132
|
export default ${componentName};
|
|
130
133
|
`
|
|
131
|
-
|
|
134
|
+
);
|
|
132
135
|
}
|
|
133
136
|
|
|
134
137
|
return {
|
|
@@ -143,25 +146,29 @@ export default {
|
|
|
143
146
|
|
|
144
147
|
build.onEnd(() => {
|
|
145
148
|
return new Promise((resolve) => {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
+
for (let i = 0; i < build?.initialOptions?.entryPoints?.length; i += 1) {
|
|
150
|
+
const entryPoint = build?.initialOptions?.entryPoints[i];
|
|
151
|
+
const shouldSetComponentId = [
|
|
152
|
+
getPlatformSafePath("ui/"),
|
|
153
|
+
getPlatformSafePath("email/"),
|
|
149
154
|
].some((bootstrapTarget) => {
|
|
150
|
-
return
|
|
155
|
+
return entryPoint.includes(bootstrapTarget);
|
|
151
156
|
});
|
|
152
157
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
158
|
+
if (shouldSetComponentId) {
|
|
159
|
+
const file = fs.readFileSync(`${build?.initialOptions?.outdir}/${entryPoint}`, "utf-8");
|
|
160
|
+
const joystickUIMatches =
|
|
156
161
|
file?.match(JOYSTICK_COMPONENT_REGEX) || [];
|
|
157
162
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
163
|
+
if (joystickUIMatches?.length > 0) {
|
|
164
|
+
let contents = setComponentId(file)?.replace(
|
|
165
|
+
/\.component\(\/\*\*\//g,
|
|
166
|
+
".component("
|
|
162
167
|
);
|
|
163
|
-
|
|
164
|
-
|
|
168
|
+
|
|
169
|
+
fs.writeFileSync(`${build?.initialOptions?.outdir}/${entryPoint}`, contents);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
165
172
|
}
|
|
166
173
|
|
|
167
174
|
resolve();
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import { codeFrameColumns } from "@babel/code-frame";
|
|
3
3
|
|
|
4
|
-
export default (
|
|
5
|
-
const file = fs.readFileSync(
|
|
6
|
-
|
|
7
|
-
return frame;
|
|
4
|
+
export default (path = "", location = {}) => {
|
|
5
|
+
const file = fs.readFileSync(path, "utf-8");
|
|
6
|
+
return codeFrameColumns(file, { start: location });
|
|
8
7
|
};
|
package/src/lib/build/onWarn.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { OBJECT_REGEX } from "../regexes.js";
|
|
3
3
|
import rainbowRoad from '../rainbowRoad.js';
|
|
4
|
-
import getCodeFrame from "
|
|
4
|
+
import getCodeFrame from "./getCodeFrame.js";
|
|
5
5
|
|
|
6
6
|
const removeLocationDataFromStackTrace = (stackTrace = "") => {
|
|
7
7
|
return stackTrace.replace(OBJECT_REGEX, "");
|
|
@@ -4,7 +4,7 @@ import child_process from "child_process";
|
|
|
4
4
|
import { kill as killPortProcess } from 'cross-port-killer';
|
|
5
5
|
import isWindows from "../../isWindows.js";
|
|
6
6
|
import CLILog from "../../../../lib/CLILog.js";
|
|
7
|
-
import getProcessIdFromPort from "
|
|
7
|
+
import getProcessIdFromPort from "../../../getProcessIdFromPort.js";
|
|
8
8
|
|
|
9
9
|
const getMongoProcessId = async (port = 2601) => {
|
|
10
10
|
const pids = await getProcessIdFromPort(port);
|
|
@@ -4,8 +4,8 @@ import util from "util";
|
|
|
4
4
|
import commandExists from "command-exists";
|
|
5
5
|
import child_process from "child_process";
|
|
6
6
|
import { kill as killPortProcess } from 'cross-port-killer';
|
|
7
|
-
import getProcessIdFromPort from "
|
|
8
|
-
import CLILog from "
|
|
7
|
+
import getProcessIdFromPort from "../../../getProcessIdFromPort.js";
|
|
8
|
+
import CLILog from "../../../CLILog.js";
|
|
9
9
|
|
|
10
10
|
const exec = util.promisify(child_process.exec);
|
|
11
11
|
|
package/src/lib/dev/index.js
CHANGED
|
@@ -21,14 +21,7 @@ import filesToCopy from "../filesToCopy.js";
|
|
|
21
21
|
import { SETTINGS_FILE_NAME_REGEX } from "../regexes.js";
|
|
22
22
|
import getCodependenciesForFile from "./getCodependenciesForFile.js";
|
|
23
23
|
import removeDeletedDependenciesFromMap from "../build/removeDeletedDependenciesFromMap.js";
|
|
24
|
-
|
|
25
|
-
const nodeMajorVersion = parseInt(
|
|
26
|
-
process?.version?.split(".")[0]?.replace("v", ""),
|
|
27
|
-
10
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
31
|
-
const __dirname = dirname(__filename);
|
|
24
|
+
import chalk from "chalk";
|
|
32
25
|
|
|
33
26
|
const getDatabaseProcessIds = () => {
|
|
34
27
|
try {
|
|
@@ -61,7 +54,7 @@ const getDatabaseProcessIds = () => {
|
|
|
61
54
|
}
|
|
62
55
|
};
|
|
63
56
|
|
|
64
|
-
const handleSignalEvents = (processIds = []) => {
|
|
57
|
+
const handleSignalEvents = (processIds = [], nodeMajorVersion = 0, __dirname = '') => {
|
|
65
58
|
try {
|
|
66
59
|
const execArgv = ["--no-warnings"];
|
|
67
60
|
|
|
@@ -99,6 +92,53 @@ const handleSignalEvents = (processIds = []) => {
|
|
|
99
92
|
}
|
|
100
93
|
};
|
|
101
94
|
|
|
95
|
+
const handleServerProcessMessages = () => {
|
|
96
|
+
try {
|
|
97
|
+
process.serverProcess.on("message", (message) => {
|
|
98
|
+
const processMessages = ["SERVER_CLOSED"];
|
|
99
|
+
|
|
100
|
+
if (!processMessages.includes(message)) {
|
|
101
|
+
process.loader.stable(message);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
} catch (exception) {
|
|
105
|
+
throw new Error(`[dev.handleServerProcessMessages] ${exception.message}`);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const handleServerProcessSTDIO = () => {
|
|
110
|
+
try {
|
|
111
|
+
if (process.serverProcess) {
|
|
112
|
+
process.serverProcess.on("error", (error) => {
|
|
113
|
+
console.log(error);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
process.serverProcess.stdout.on("data", (data) => {
|
|
117
|
+
const message = data.toString();
|
|
118
|
+
|
|
119
|
+
if (message && message.includes("App running at:")) {
|
|
120
|
+
process.loader.stable(message);
|
|
121
|
+
} else {
|
|
122
|
+
if (message && !message.includes("BUILD_ERROR")) {
|
|
123
|
+
console.log(message);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
process.serverProcess.stderr.on("data", (data) => {
|
|
129
|
+
process.loader.stop();
|
|
130
|
+
|
|
131
|
+
CLILog(data.toString(), {
|
|
132
|
+
level: "danger",
|
|
133
|
+
docs: "https://cheatcode.co/docs/joystick",
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
} catch (exception) {
|
|
138
|
+
throw new Error(`[dev.handleServerProcessSTDIO] ${exception.message}`);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
|
|
102
142
|
const handleAddOrChangeFile = async (context = {}, path = '') => {
|
|
103
143
|
try {
|
|
104
144
|
if (context.isAddingOrChangingFile) {
|
|
@@ -228,7 +268,8 @@ const getWatchChangeContext = (event = '', path = '') => {
|
|
|
228
268
|
try {
|
|
229
269
|
const isHTMLUpdate = path === "index.html";
|
|
230
270
|
const isUIPath = path?.includes("ui/") || path === 'index.css' || isHTMLUpdate;
|
|
231
|
-
|
|
271
|
+
// TODO: Flimsy. May want to wait until HMR and server are up to do the builds/watching.
|
|
272
|
+
const isUIUpdate = (process.hmrProcess && process.hmrProcess.hasConnections && isUIPath) || false;
|
|
232
273
|
const isSettingsUpdate = path?.match(SETTINGS_FILE_NAME_REGEX)?.length > 0;
|
|
233
274
|
const isDirectory = fs.statSync(path).isDirectory();
|
|
234
275
|
const isFile = fs.statSync(path).isFile();
|
|
@@ -292,21 +333,26 @@ const startFileWatcher = (options = {}) => {
|
|
|
292
333
|
|
|
293
334
|
const runInitialBuild = async (buildSettings = {}) => {
|
|
294
335
|
try {
|
|
336
|
+
process.loader.text('Building app...');
|
|
337
|
+
|
|
295
338
|
const filesToBuild = getFilesToBuild(buildSettings?.excludedPaths, "start");
|
|
296
|
-
const fileResults = await buildFiles(
|
|
297
|
-
filesToBuild,
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
);
|
|
339
|
+
const fileResults = await buildFiles({
|
|
340
|
+
files: filesToBuild,
|
|
341
|
+
environment: process.env.NODE_ENV
|
|
342
|
+
});
|
|
301
343
|
|
|
302
344
|
const hasErrors = [...fileResults]
|
|
303
345
|
.filter((result) => !!result)
|
|
304
346
|
.map(({ success }) => success)
|
|
305
347
|
.includes(false);
|
|
306
348
|
|
|
307
|
-
//
|
|
308
|
-
|
|
349
|
+
// NOTE: If the initial build fails, exit the startup process.
|
|
350
|
+
if (hasErrors) {
|
|
351
|
+
console.log(chalk.redBright('Failed to start app. Correct the errors above and run joystick start again.\n'));
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|
|
309
354
|
} catch (exception) {
|
|
355
|
+
console.warn(exception);
|
|
310
356
|
throw new Error(`[dev.runInitialBuild] ${exception.message}`);
|
|
311
357
|
}
|
|
312
358
|
};
|
|
@@ -352,18 +398,22 @@ const checkForRequiredFiles = () => {
|
|
|
352
398
|
|
|
353
399
|
let error = `The following paths are missing and required in a Joystick project:\n\n`;
|
|
354
400
|
|
|
355
|
-
|
|
401
|
+
if (files?.length > 0) {
|
|
402
|
+
error += ` > Required Files:\n\n`;
|
|
356
403
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
404
|
+
for (let i = 0; i < files?.length; i += 1) {
|
|
405
|
+
const file = files[i];
|
|
406
|
+
error += ` /${file.path}\n`;
|
|
407
|
+
}
|
|
360
408
|
}
|
|
361
409
|
|
|
362
|
-
|
|
410
|
+
if (directories?.length > 0) {
|
|
411
|
+
error += ` > Required Directories:\n\n`;
|
|
363
412
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
413
|
+
for (let i = 0; i < directories?.length; i += 1) {
|
|
414
|
+
const file = directories[i];
|
|
415
|
+
error += ` /${file.path}\n`;
|
|
416
|
+
}
|
|
367
417
|
}
|
|
368
418
|
|
|
369
419
|
CLILog(error, {
|
|
@@ -395,7 +445,7 @@ const warnInvalidJoystickEnvironment = () => {
|
|
|
395
445
|
process.exit(0);
|
|
396
446
|
}
|
|
397
447
|
|
|
398
|
-
if (process.env.NODE_ENV !== 'test' &&
|
|
448
|
+
if (process.env.NODE_ENV !== 'test' && !hasJoystickFolder) {
|
|
399
449
|
CLILog(
|
|
400
450
|
"joystick start must be run in a directory with a .joystick folder.",
|
|
401
451
|
{
|
|
@@ -425,24 +475,56 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
425
475
|
validateOptions(options);
|
|
426
476
|
initProcess(options);
|
|
427
477
|
|
|
478
|
+
const nodeMajorVersion = parseInt(
|
|
479
|
+
process?.version?.split(".")[0]?.replace("v", ""),
|
|
480
|
+
10
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
484
|
+
const __dirname = dirname(__filename);
|
|
485
|
+
|
|
428
486
|
warnInvalidJoystickEnvironment();
|
|
429
487
|
checkForRequiredFiles();
|
|
430
488
|
|
|
431
489
|
const settings = await loadSettings({
|
|
432
490
|
environment: options.environment,
|
|
433
|
-
process: options.process,
|
|
434
491
|
});
|
|
435
492
|
|
|
436
|
-
await startDatabases(
|
|
493
|
+
await startDatabases({
|
|
494
|
+
environment: options.environment,
|
|
495
|
+
port: options.port,
|
|
496
|
+
settings: settings.parsed
|
|
497
|
+
});
|
|
437
498
|
|
|
438
499
|
await runInitialBuild(settings?.parsed?.config?.build);
|
|
439
500
|
await startFileWatcher(options);
|
|
440
501
|
|
|
441
|
-
|
|
502
|
+
const serverProcess = await startApp({
|
|
503
|
+
nodeMajorVersion,
|
|
504
|
+
port: options?.port,
|
|
505
|
+
});
|
|
442
506
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
507
|
+
if (serverProcess) {
|
|
508
|
+
process.serverProcess = serverProcess;
|
|
509
|
+
handleServerProcessSTDIO();
|
|
510
|
+
handleServerProcessMessages();
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// NOTE: Scope this out here so we can reference the processId below.
|
|
514
|
+
let hmrProcess;
|
|
515
|
+
|
|
516
|
+
if (options?.environment !== 'test') {
|
|
517
|
+
hmrProcess = await startHMR({
|
|
518
|
+
nodeMajorVersion,
|
|
519
|
+
__dirname,
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
handleSignalEvents(
|
|
524
|
+
[serverProcess.pid, hmrProcess.pid],
|
|
525
|
+
nodeMajorVersion,
|
|
526
|
+
__dirname
|
|
527
|
+
);
|
|
446
528
|
//
|
|
447
529
|
// if (options?.environment === 'test') {
|
|
448
530
|
// await runTests(options);
|
|
@@ -456,7 +538,9 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
456
538
|
- [x] If environment === 'test', check that both a .joystick fo lder exists AND a /tests folder
|
|
457
539
|
exists. If no /tests, log out docs on how to scaffold your tests.
|
|
458
540
|
- [x] Load settings.<environment>.json.
|
|
459
|
-
- [
|
|
541
|
+
- [x] Start databases relative to options.environment (development|test) from settings.<environment>.json.
|
|
542
|
+
- [x] Run the initial build
|
|
543
|
+
- [x] Start the file watcher
|
|
460
544
|
- [ ] Start the app as normal from the build directory.
|
|
461
545
|
- [ ] If environment === 'test', run the tests.
|
|
462
546
|
- [ ] If environment === 'test', after tests, run process.exit(0).
|
|
@@ -464,6 +548,7 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
464
548
|
|
|
465
549
|
resolve();
|
|
466
550
|
} catch (exception) {
|
|
551
|
+
console.warn(exception);
|
|
467
552
|
reject(`[dev] ${exception.message}`);
|
|
468
553
|
}
|
|
469
554
|
};
|
|
@@ -73,9 +73,7 @@ const loadSettings = (options, { resolve, reject }) => {
|
|
|
73
73
|
const settings = getSettings(settingsPath);
|
|
74
74
|
warnIfInvalidJSONInSettings(settings);
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
options.process.env.JOYSTICK_SETTINGS = settings;
|
|
78
|
-
}
|
|
76
|
+
process.env.JOYSTICK_SETTINGS = settings;
|
|
79
77
|
|
|
80
78
|
resolve({
|
|
81
79
|
parsed: JSON.parse(settings),
|
package/src/lib/dev/startApp.js
CHANGED
|
@@ -1,16 +1,59 @@
|
|
|
1
|
-
|
|
1
|
+
import child_process from "child_process";
|
|
2
|
+
import path from "path";
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
+
const handleStartServerProcess = (execArgv = {}, sessionsBeforeHMRUpdate = {}) => {
|
|
4
5
|
try {
|
|
5
|
-
|
|
6
|
+
process.loader.text('Starting app...');
|
|
7
|
+
|
|
8
|
+
return child_process.fork(
|
|
9
|
+
path.resolve(".joystick/build/index.server.js"),
|
|
10
|
+
[],
|
|
11
|
+
{
|
|
12
|
+
execArgv,
|
|
13
|
+
// NOTE: Pipe stdin, stdout, and stderr. IPC establishes a message channel so we
|
|
14
|
+
// communicate with the child_process.
|
|
15
|
+
silent: true,
|
|
16
|
+
env: {
|
|
17
|
+
FORCE_COLOR: "1",
|
|
18
|
+
LOGS_PATH: process.env.LOGS_PATH,
|
|
19
|
+
NODE_ENV: process.env.NODE_ENV,
|
|
20
|
+
ROOT_URL: process.env.ROOT_URL,
|
|
21
|
+
PORT: process.env.PORT,
|
|
22
|
+
JOYSTICK_SETTINGS: process.env.JOYSTICK_SETTINGS,
|
|
23
|
+
HMR_SESSIONS: JSON.stringify(sessionsBeforeHMRUpdate),
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
);
|
|
6
27
|
} catch (exception) {
|
|
7
|
-
throw new Error(`[startApp.
|
|
28
|
+
throw new Error(`[startApp.handleStartServerProcess] ${exception.message}`);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const getExecArgs = (nodeMajorVersion = 0) => {
|
|
33
|
+
try {
|
|
34
|
+
const execArgv = ["--no-warnings"];
|
|
35
|
+
|
|
36
|
+
if (nodeMajorVersion < 19) {
|
|
37
|
+
execArgv.push("--experimental-specifier-resolution=node");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (
|
|
41
|
+
process.env.NODE_ENV === "development" &&
|
|
42
|
+
process.env.IS_DEBUG_MODE === "true"
|
|
43
|
+
) {
|
|
44
|
+
execArgv.push("--inspect");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return execArgv;
|
|
48
|
+
} catch (exception) {
|
|
49
|
+
throw new Error(`[startApp.getExecArgs] ${exception.message}`);
|
|
8
50
|
}
|
|
9
51
|
};
|
|
10
52
|
|
|
11
53
|
const validateOptions = (options) => {
|
|
12
54
|
try {
|
|
13
55
|
if (!options) throw new Error('options object is required.');
|
|
56
|
+
if (!options.nodeMajorVersion) throw new Error('options.nodeMajorVersion is required.');
|
|
14
57
|
if (!options.port) throw new Error('options.port is required.');
|
|
15
58
|
} catch (exception) {
|
|
16
59
|
throw new Error(`[startApp.validateOptions] ${exception.message}`);
|
|
@@ -20,8 +63,11 @@ const validateOptions = (options) => {
|
|
|
20
63
|
const startApp = (options, { resolve, reject }) => {
|
|
21
64
|
try {
|
|
22
65
|
validateOptions(options);
|
|
23
|
-
|
|
24
|
-
|
|
66
|
+
|
|
67
|
+
const execArgv = getExecArgs(options?.nodeMajorVersion);
|
|
68
|
+
const serverProcess = handleStartServerProcess(execArgv);
|
|
69
|
+
|
|
70
|
+
return resolve(serverProcess);
|
|
25
71
|
} catch (exception) {
|
|
26
72
|
reject(`[startApp] ${exception.message}`);
|
|
27
73
|
}
|