@joystick.js/cli-canary 0.0.0-canary.92 → 0.0.0-canary.94
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 +41 -0
- package/dist/lib/dev/index.js +91 -17
- package/dist/lib/dev/startApp.js +1 -1
- package/package.json +1 -1
- package/src/functions/start/index.js +656 -0
- package/src/lib/dev/index.js +111 -21
- package/src/lib/dev/startApp.js +1 -1
|
@@ -1,4 +1,45 @@
|
|
|
1
1
|
import dev from "../../lib/dev/index.js";
|
|
2
|
+
process.hmrProcess.on("message", (message) => {
|
|
3
|
+
const processMessages = [
|
|
4
|
+
"SERVER_CLOSED",
|
|
5
|
+
"HAS_HMR_CONNECTIONS",
|
|
6
|
+
"HAS_NO_HMR_CONNECTIONS",
|
|
7
|
+
"HMR_UPDATE_COMPLETED"
|
|
8
|
+
];
|
|
9
|
+
if (!processMessages.includes(message?.type)) {
|
|
10
|
+
process.loader.stable(message);
|
|
11
|
+
}
|
|
12
|
+
if (message?.type === "HAS_HMR_CONNECTIONS") {
|
|
13
|
+
process.hmrProcess.hasConnections = true;
|
|
14
|
+
}
|
|
15
|
+
if (message?.type === "HAS_NO_HMR_CONNECTIONS") {
|
|
16
|
+
process.hmrProcess.hasConnections = false;
|
|
17
|
+
}
|
|
18
|
+
if (message?.type === "HMR_UPDATE_COMPLETED") {
|
|
19
|
+
setTimeout(() => {
|
|
20
|
+
restartApplicationProcess(message?.sessions);
|
|
21
|
+
}, 500);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
const startHMRProcess = () => {
|
|
25
|
+
const execArgv = ["--no-warnings"];
|
|
26
|
+
if (majorVersion < 19) {
|
|
27
|
+
execArgv.push("--experimental-specifier-resolution=node");
|
|
28
|
+
}
|
|
29
|
+
const hmrProcess = child_process.fork(
|
|
30
|
+
path.resolve(`${__dirname}/hmrServer.js`),
|
|
31
|
+
[],
|
|
32
|
+
{
|
|
33
|
+
execArgv,
|
|
34
|
+
// NOTE: Pipe stdin, stdout, and stderr. IPC establishes a message channel so we
|
|
35
|
+
// communicate with the child_process.
|
|
36
|
+
silent: true
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
process.hmrProcess = hmrProcess;
|
|
40
|
+
handleHMRProcessSTDIO();
|
|
41
|
+
handleHMRProcessMessages();
|
|
42
|
+
};
|
|
2
43
|
var start_default = async (args = {}, options = {}) => {
|
|
3
44
|
await dev({
|
|
4
45
|
environment: args?.environment || "development",
|
package/dist/lib/dev/index.js
CHANGED
|
@@ -76,6 +76,61 @@ const handleSignalEvents = (processIds = [], nodeMajorVersion = 0, __dirname = "
|
|
|
76
76
|
throw new Error(`[dev.handleSignalEvents] ${exception.message}`);
|
|
77
77
|
}
|
|
78
78
|
};
|
|
79
|
+
const handleHMRProcessMessages = (options = {}) => {
|
|
80
|
+
try {
|
|
81
|
+
process.hmrProcess.on("message", (message) => {
|
|
82
|
+
const processMessages = [
|
|
83
|
+
"SERVER_CLOSED",
|
|
84
|
+
"HAS_HMR_CONNECTIONS",
|
|
85
|
+
"HAS_NO_HMR_CONNECTIONS",
|
|
86
|
+
"HMR_UPDATE_COMPLETED"
|
|
87
|
+
];
|
|
88
|
+
if (!processMessages.includes(message?.type)) {
|
|
89
|
+
process.loader.stable(message);
|
|
90
|
+
}
|
|
91
|
+
if (message?.type === "HAS_HMR_CONNECTIONS") {
|
|
92
|
+
process.hmrProcess.hasConnections = true;
|
|
93
|
+
}
|
|
94
|
+
if (message?.type === "HAS_NO_HMR_CONNECTIONS") {
|
|
95
|
+
process.hmrProcess.hasConnections = false;
|
|
96
|
+
}
|
|
97
|
+
if (message?.type === "HMR_UPDATE_COMPLETED") {
|
|
98
|
+
setTimeout(() => {
|
|
99
|
+
handleRestartApplicationProcess({
|
|
100
|
+
...options,
|
|
101
|
+
sessionsBeforeHMRUpdate: message?.sessions
|
|
102
|
+
});
|
|
103
|
+
}, 500);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
} catch (exception) {
|
|
107
|
+
throw new Error(`[dev.handleHMRProcessMessages] ${exception.message}`);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const handleHMRProcessSTDIO = () => {
|
|
111
|
+
try {
|
|
112
|
+
if (process.hmrProcess) {
|
|
113
|
+
process.hmrProcess.on("error", (error) => {
|
|
114
|
+
CLILog(error.toString(), {
|
|
115
|
+
level: "danger",
|
|
116
|
+
docs: "https://github.com/cheatcode/joystick"
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
process.hmrProcess.stdout.on("data", (data) => {
|
|
120
|
+
console.log(data.toString());
|
|
121
|
+
});
|
|
122
|
+
process.hmrProcess.stderr.on("data", (data) => {
|
|
123
|
+
process.loader.stop();
|
|
124
|
+
CLILog(data.toString(), {
|
|
125
|
+
level: "danger",
|
|
126
|
+
docs: "https://github.com/cheatcode/joystick"
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
} catch (exception) {
|
|
131
|
+
throw new Error(`[dev.handleHMRProcessSTDIO] ${exception.message}`);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
79
134
|
const handleServerProcessMessages = () => {
|
|
80
135
|
try {
|
|
81
136
|
process.serverProcess.on("message", (message) => {
|
|
@@ -116,7 +171,7 @@ const handleServerProcessSTDIO = () => {
|
|
|
116
171
|
throw new Error(`[dev.handleServerProcessSTDIO] ${exception.message}`);
|
|
117
172
|
}
|
|
118
173
|
};
|
|
119
|
-
const handleAddOrChangeFile = async (context = {}, path2 = "") => {
|
|
174
|
+
const handleAddOrChangeFile = async (context = {}, path2 = "", options = {}) => {
|
|
120
175
|
try {
|
|
121
176
|
if (context.isAddingOrChangingFile) {
|
|
122
177
|
const codependencies = await getCodependenciesForFile(path2);
|
|
@@ -144,59 +199,73 @@ const handleAddOrChangeFile = async (context = {}, path2 = "") => {
|
|
|
144
199
|
if (context.isUIUpdate) {
|
|
145
200
|
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
146
201
|
} else {
|
|
147
|
-
handleRestartApplicationProcess();
|
|
202
|
+
handleRestartApplicationProcess(options);
|
|
148
203
|
}
|
|
149
|
-
return;
|
|
150
204
|
}
|
|
151
205
|
}
|
|
152
206
|
} catch (exception) {
|
|
153
207
|
throw new Error(`[dev.handleAddOrChangeFile] ${exception.message}`);
|
|
154
208
|
}
|
|
155
209
|
};
|
|
156
|
-
const handleAddDirectory = (context = {}, path2 = "") => {
|
|
210
|
+
const handleAddDirectory = (context = {}, path2 = "", options = {}) => {
|
|
157
211
|
try {
|
|
158
212
|
if (context.isAddDirectory) {
|
|
159
213
|
fs.mkdirSync(`./.joystick/build/${path2}`);
|
|
160
214
|
if (context.isUIUpdate) {
|
|
161
215
|
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
162
216
|
} else {
|
|
163
|
-
handleRestartApplicationProcess();
|
|
217
|
+
handleRestartApplicationProcess(options);
|
|
164
218
|
}
|
|
165
219
|
}
|
|
166
220
|
} catch (exception) {
|
|
167
221
|
throw new Error(`[dev.handleAddDirectory] ${exception.message}`);
|
|
168
222
|
}
|
|
169
223
|
};
|
|
170
|
-
const handleCopyFile = (context = {}, path2 = "") => {
|
|
224
|
+
const handleCopyFile = (context = {}, path2 = "", options = {}) => {
|
|
171
225
|
try {
|
|
172
226
|
if (context.isFileToCopy && !context.isDirectory) {
|
|
173
227
|
fs.writeFileSync(`./.joystick/build/${path2}`, fs.readFileSync(path2));
|
|
174
228
|
if (context.isUIUpdate) {
|
|
175
229
|
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
176
230
|
} else {
|
|
177
|
-
handleRestartApplicationProcess();
|
|
231
|
+
handleRestartApplicationProcess(options);
|
|
178
232
|
}
|
|
179
233
|
}
|
|
180
234
|
} catch (exception) {
|
|
181
235
|
throw new Error(`[dev.handleCopyFile] ${exception.message}`);
|
|
182
236
|
}
|
|
183
237
|
};
|
|
184
|
-
const handleCopyDirectory = (context = {}, path2 = "") => {
|
|
238
|
+
const handleCopyDirectory = (context = {}, path2 = "", options = {}) => {
|
|
185
239
|
try {
|
|
186
240
|
if (context.isFileToCopy && context.isDirectory && !context.isExistingDirectoryInBuild) {
|
|
187
241
|
fs.mkdirSync(`./.joystick/build/${path2}`);
|
|
188
242
|
if (context.isUIUpdate) {
|
|
189
243
|
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
190
244
|
} else {
|
|
191
|
-
handleRestartApplicationProcess();
|
|
245
|
+
handleRestartApplicationProcess(options);
|
|
192
246
|
}
|
|
193
247
|
}
|
|
194
248
|
} catch (exception) {
|
|
195
249
|
throw new Error(`[dev.handleCopyDirectory] ${exception.message}`);
|
|
196
250
|
}
|
|
197
251
|
};
|
|
198
|
-
const handleRestartApplicationProcess = () => {
|
|
252
|
+
const handleRestartApplicationProcess = async (options = {}) => {
|
|
199
253
|
try {
|
|
254
|
+
if (process.serverProcess && process.serverProcess.pid) {
|
|
255
|
+
process.loader.text("Restarting app...");
|
|
256
|
+
process.serverProcess.kill();
|
|
257
|
+
await startApp({
|
|
258
|
+
nodeMajorVersion: options?.nodeMajorVersion,
|
|
259
|
+
port: options?.port,
|
|
260
|
+
sessionsBeforeHMRUpdate: options?.sessionsBeforeHMRUpdate
|
|
261
|
+
});
|
|
262
|
+
return Promise.resolve();
|
|
263
|
+
}
|
|
264
|
+
process.loader.text("Starting app...");
|
|
265
|
+
startApplicationProcess();
|
|
266
|
+
if (!process.hmrProcess) {
|
|
267
|
+
startHMR();
|
|
268
|
+
}
|
|
200
269
|
} catch (exception) {
|
|
201
270
|
throw new Error(`[dev.handleRestartApplicationProcess] ${exception.message}`);
|
|
202
271
|
}
|
|
@@ -259,10 +328,10 @@ const startFileWatcher = (options = {}) => {
|
|
|
259
328
|
checkForRequiredFiles();
|
|
260
329
|
process.loader.text("Rebuilding app...");
|
|
261
330
|
const watchChangeContext = getWatchChangeContext(event, path2);
|
|
262
|
-
handleCopyDirectory(watchChangeContext, path2);
|
|
263
|
-
handleCopyFile(watchChangeContext, path2);
|
|
264
|
-
handleAddDirectory(watchChangeContext, path2);
|
|
265
|
-
await handleAddOrChangeFile(watchChangeContext, path2);
|
|
331
|
+
handleCopyDirectory(watchChangeContext, path2, options);
|
|
332
|
+
handleCopyFile(watchChangeContext, path2, options);
|
|
333
|
+
handleAddDirectory(watchChangeContext, path2, options);
|
|
334
|
+
await handleAddOrChangeFile(watchChangeContext, path2, options);
|
|
266
335
|
if (watchChangeContext?.isSettingsUpdate) {
|
|
267
336
|
await loadSettings({
|
|
268
337
|
environment: options.environment,
|
|
@@ -416,24 +485,29 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
416
485
|
});
|
|
417
486
|
await runInitialBuild(settings?.parsed?.config?.build);
|
|
418
487
|
await startFileWatcher(options);
|
|
488
|
+
const processIds = [];
|
|
419
489
|
const serverProcess = await startApp({
|
|
420
490
|
nodeMajorVersion,
|
|
421
491
|
port: options?.port
|
|
422
492
|
});
|
|
423
493
|
if (serverProcess) {
|
|
494
|
+
processIds.push(serverProcess.pid);
|
|
424
495
|
process.serverProcess = serverProcess;
|
|
425
496
|
handleServerProcessSTDIO();
|
|
426
497
|
handleServerProcessMessages();
|
|
427
498
|
}
|
|
428
|
-
let hmrProcess;
|
|
429
499
|
if (options?.environment !== "test") {
|
|
430
|
-
hmrProcess = await startHMR({
|
|
500
|
+
const hmrProcess = await startHMR({
|
|
431
501
|
nodeMajorVersion,
|
|
432
502
|
__dirname
|
|
433
503
|
});
|
|
504
|
+
processIds.push(hmrProcess.pid);
|
|
505
|
+
process.hmrProcess = hmrProcess;
|
|
506
|
+
handleHMRProcessSTDIO();
|
|
507
|
+
handleHMRProcessMessages(options);
|
|
434
508
|
}
|
|
435
509
|
handleSignalEvents(
|
|
436
|
-
|
|
510
|
+
processIds,
|
|
437
511
|
nodeMajorVersion,
|
|
438
512
|
__dirname
|
|
439
513
|
);
|
package/dist/lib/dev/startApp.js
CHANGED
|
@@ -56,7 +56,7 @@ const startApp = (options, { resolve, reject }) => {
|
|
|
56
56
|
try {
|
|
57
57
|
validateOptions(options);
|
|
58
58
|
const execArgv = getExecArgs(options?.nodeMajorVersion);
|
|
59
|
-
const serverProcess = handleStartServerProcess(execArgv);
|
|
59
|
+
const serverProcess = handleStartServerProcess(execArgv, options?.sessionsBeforeHMRUpdate);
|
|
60
60
|
return resolve(serverProcess);
|
|
61
61
|
} catch (exception) {
|
|
62
62
|
reject(`[startApp] ${exception.message}`);
|
package/package.json
CHANGED
|
@@ -1,5 +1,661 @@
|
|
|
1
|
+
/* eslint-disable consistent-return */
|
|
2
|
+
|
|
3
|
+
//import child_process from "child_process";
|
|
4
|
+
//import path, { dirname } from "path";
|
|
5
|
+
//import { fileURLToPath } from "url";
|
|
6
|
+
//import ps from "ps-node";
|
|
7
|
+
//import { killPortProcess } from "kill-port-process";
|
|
8
|
+
//import fs from "fs";
|
|
9
|
+
//import chokidar from "chokidar";
|
|
10
|
+
//import Loader from "../../lib/loader.js";
|
|
11
|
+
//import getFilesToBuild from "./getFilesToBuild.js";
|
|
12
|
+
//import buildFiles from "./buildFiles.js";
|
|
13
|
+
//import filesToCopy from "./filesToCopy.js";
|
|
14
|
+
//import checkIfPortAvailable from "./checkIfPortAvailable.js";
|
|
15
|
+
//import getCodependenciesForFile from "./getCodependenciesForFile.js";
|
|
16
|
+
//import isValidJSONString from "../../lib/isValidJSONString.js";
|
|
17
|
+
//import startDatabaseProvider from "./databases/startProvider.js";
|
|
18
|
+
//import CLILog from "../../lib/CLILog.js";
|
|
19
|
+
//import removeDeletedDependenciesFromMap from "./removeDeletedDependenciesFromMap.js";
|
|
20
|
+
//import validateDatabasesFromSettings from "../../lib/validateDatabasesFromSettings.js";
|
|
21
|
+
//import wait from "../../lib/wait.js";
|
|
1
22
|
import dev from "../../lib/dev/index.js";
|
|
2
23
|
|
|
24
|
+
//const majorVersion = parseInt(
|
|
25
|
+
// process?.version?.split(".")[0]?.replace("v", ""),
|
|
26
|
+
// 10
|
|
27
|
+
//);
|
|
28
|
+
//
|
|
29
|
+
//const __filename = fileURLToPath(import.meta.url);
|
|
30
|
+
//const __dirname = dirname(__filename);
|
|
31
|
+
//
|
|
32
|
+
//const killProcess = (pid = 0) => {
|
|
33
|
+
// return new Promise((resolve) => {
|
|
34
|
+
// ps.kill(pid, () => {
|
|
35
|
+
// resolve();
|
|
36
|
+
// });
|
|
37
|
+
// });
|
|
38
|
+
//};
|
|
39
|
+
//
|
|
40
|
+
//const watchlist = [
|
|
41
|
+
// { path: "ui" },
|
|
42
|
+
// { path: "lib" },
|
|
43
|
+
// { path: "i18n" },
|
|
44
|
+
// { path: "api" },
|
|
45
|
+
// { path: "email" },
|
|
46
|
+
// { path: "fixtures" },
|
|
47
|
+
// { path: "routes" },
|
|
48
|
+
// { path: "index.client.js" },
|
|
49
|
+
// { path: "index.server.js" },
|
|
50
|
+
// ...filesToCopy,
|
|
51
|
+
//];
|
|
52
|
+
//
|
|
53
|
+
//const requiredFileCheck = () => {
|
|
54
|
+
// return new Promise((resolve) => {
|
|
55
|
+
// const requiredFiles = [
|
|
56
|
+
// { path: "index.server.js", type: "file" },
|
|
57
|
+
// { path: "index.html", type: "file" },
|
|
58
|
+
// { path: "index.client.js", type: "file" },
|
|
59
|
+
// { path: "api", type: "directory" },
|
|
60
|
+
// { path: "i18n", type: "directory" },
|
|
61
|
+
// { path: "lib", type: "directory" },
|
|
62
|
+
// { path: "public", type: "directory" },
|
|
63
|
+
// { path: "ui", type: "directory" },
|
|
64
|
+
// { path: "ui/components", type: "directory" },
|
|
65
|
+
// { path: "ui/layouts", type: "directory" },
|
|
66
|
+
// { path: "ui/pages", type: "directory" },
|
|
67
|
+
// ];
|
|
68
|
+
//
|
|
69
|
+
// requiredFiles.forEach((requiredFile) => {
|
|
70
|
+
// const exists = fs.existsSync(`${process.cwd()}/${requiredFile.path}`);
|
|
71
|
+
// const stats =
|
|
72
|
+
// exists && fs.statSync(`${process.cwd()}/${requiredFile.path}`);
|
|
73
|
+
// const isFile = stats && stats.isFile();
|
|
74
|
+
// const isDirectory = stats && stats.isDirectory();
|
|
75
|
+
//
|
|
76
|
+
// if (requiredFile && requiredFile.type === "file") {
|
|
77
|
+
// if (!exists || (exists && !isFile)) {
|
|
78
|
+
// CLILog(
|
|
79
|
+
// `The path ${requiredFile.path} must exist in your project and must be a file (not a directory).`,
|
|
80
|
+
// {
|
|
81
|
+
// level: "danger",
|
|
82
|
+
// docs: "https://github.com/cheatcode/joystick#folder-and-file-structure",
|
|
83
|
+
// }
|
|
84
|
+
// );
|
|
85
|
+
// process.exit(0);
|
|
86
|
+
// }
|
|
87
|
+
// }
|
|
88
|
+
//
|
|
89
|
+
// if (requiredFile && requiredFile.type === "directory") {
|
|
90
|
+
// if (!exists || (exists && !isDirectory)) {
|
|
91
|
+
// CLILog(
|
|
92
|
+
// `The path ${requiredFile.path} must exist in your project and must be a directory (not a file).`,
|
|
93
|
+
// {
|
|
94
|
+
// level: "danger",
|
|
95
|
+
// docs: "https://github.com/cheatcode/joystick#folder-and-file-structure",
|
|
96
|
+
// }
|
|
97
|
+
// );
|
|
98
|
+
// process.exit(0);
|
|
99
|
+
// }
|
|
100
|
+
// }
|
|
101
|
+
// });
|
|
102
|
+
//
|
|
103
|
+
// resolve();
|
|
104
|
+
// });
|
|
105
|
+
//};
|
|
106
|
+
//
|
|
107
|
+
//const handleCleanup = async (
|
|
108
|
+
// processIds = [process?.serverProcess?.pid, process?.hmrProcess?.pid]
|
|
109
|
+
//) => {
|
|
110
|
+
// for (let i = 0; i < processIds?.length; i += 1) {
|
|
111
|
+
// const processId = processIds[i];
|
|
112
|
+
//
|
|
113
|
+
// if (processId) {
|
|
114
|
+
// await killProcess(processId);
|
|
115
|
+
// }
|
|
116
|
+
// }
|
|
117
|
+
//
|
|
118
|
+
// const databases = Object.entries(process._databases || {});
|
|
119
|
+
//
|
|
120
|
+
// for (let i = 0; i < databases?.length; i += 1) {
|
|
121
|
+
// const [provider, providerConnection] = databases[i];
|
|
122
|
+
//
|
|
123
|
+
// if (providerConnection?.pid) {
|
|
124
|
+
// await killProcess(providerConnection.pid);
|
|
125
|
+
// }
|
|
126
|
+
//
|
|
127
|
+
// if (!providerConnection?.pid) {
|
|
128
|
+
// const providerConnections = Object.entries(providerConnection);
|
|
129
|
+
//
|
|
130
|
+
// for (let pc = 0; pc < providerConnections?.length; pc += 1) {
|
|
131
|
+
// const [_connectionName, connection] = providerConnections[pc];
|
|
132
|
+
//
|
|
133
|
+
// if (connection?.pid) {
|
|
134
|
+
// await killProcess(connection?.pid);
|
|
135
|
+
// }
|
|
136
|
+
// }
|
|
137
|
+
// }
|
|
138
|
+
// }
|
|
139
|
+
//};
|
|
140
|
+
//
|
|
141
|
+
//const getDatabaseProcessIds = () => {
|
|
142
|
+
// const databaseProcessIds = [];
|
|
143
|
+
// const databases = Object.entries(process._databases || {});
|
|
144
|
+
//
|
|
145
|
+
// for (let i = 0; i < databases?.length; i += 1) {
|
|
146
|
+
// const [_provider, providerConnection] = databases[i];
|
|
147
|
+
//
|
|
148
|
+
// if (providerConnection?.pid) {
|
|
149
|
+
// databaseProcessIds.push(providerConnection.pid);
|
|
150
|
+
// }
|
|
151
|
+
//
|
|
152
|
+
// if (!providerConnection?.pid) {
|
|
153
|
+
// const providerConnections = Object.entries(providerConnection);
|
|
154
|
+
//
|
|
155
|
+
// for (let pc = 0; pc < providerConnections?.length; pc += 1) {
|
|
156
|
+
// const [_connectionName, connection] = providerConnections[pc];
|
|
157
|
+
//
|
|
158
|
+
// if (connection?.pid) {
|
|
159
|
+
// databaseProcessIds.push(connection.pid);
|
|
160
|
+
// }
|
|
161
|
+
// }
|
|
162
|
+
// }
|
|
163
|
+
// }
|
|
164
|
+
//
|
|
165
|
+
// return databaseProcessIds;
|
|
166
|
+
//};
|
|
167
|
+
//
|
|
168
|
+
//const handleSignalEvents = (processIds = []) => {
|
|
169
|
+
// const execArgv = ["--no-warnings"];
|
|
170
|
+
//
|
|
171
|
+
// if (majorVersion < 19) {
|
|
172
|
+
// execArgv.push("--experimental-specifier-resolution=node");
|
|
173
|
+
// }
|
|
174
|
+
//
|
|
175
|
+
// const cleanupProcess = child_process.fork(
|
|
176
|
+
// path.resolve(`${__dirname}/cleanup/index.js`),
|
|
177
|
+
// [],
|
|
178
|
+
// {
|
|
179
|
+
// // NOTE: Run in detached mode so when parent process dies, the child still runs
|
|
180
|
+
// // and cleanup completes.
|
|
181
|
+
// detached: true,
|
|
182
|
+
// execArgv,
|
|
183
|
+
// // NOTE: Pipe stdin, stdout, and stderr. IPC establishes a message channel so we
|
|
184
|
+
// // communicate with the child_process.
|
|
185
|
+
// silent: true,
|
|
186
|
+
// }
|
|
187
|
+
// );
|
|
188
|
+
//
|
|
189
|
+
// process.on("SIGINT", async () => {
|
|
190
|
+
// const databaseProcessIds = getDatabaseProcessIds();
|
|
191
|
+
// cleanupProcess.send(JSON.stringify(({ processIds: [...processIds, ...databaseProcessIds] })));
|
|
192
|
+
// process.exit();
|
|
193
|
+
// });
|
|
194
|
+
//
|
|
195
|
+
// process.on("SIGTERM", async () => {
|
|
196
|
+
// const databaseProcessIds = getDatabaseProcessIds();
|
|
197
|
+
// cleanupProcess.send(JSON.stringify(({ processIds: [...processIds, ...databaseProcessIds] })));
|
|
198
|
+
// process.exit();
|
|
199
|
+
// });
|
|
200
|
+
//};
|
|
201
|
+
//
|
|
202
|
+
//const handleHMRProcessMessages = () => {
|
|
203
|
+
process.hmrProcess.on("message", (message) => {
|
|
204
|
+
const processMessages = [
|
|
205
|
+
"SERVER_CLOSED",
|
|
206
|
+
"HAS_HMR_CONNECTIONS",
|
|
207
|
+
"HAS_NO_HMR_CONNECTIONS",
|
|
208
|
+
"HMR_UPDATE_COMPLETED",
|
|
209
|
+
];
|
|
210
|
+
|
|
211
|
+
if (!processMessages.includes(message?.type)) {
|
|
212
|
+
process.loader.stable(message);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (message?.type === "HAS_HMR_CONNECTIONS") {
|
|
216
|
+
process.hmrProcess.hasConnections = true;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (message?.type === "HAS_NO_HMR_CONNECTIONS") {
|
|
220
|
+
process.hmrProcess.hasConnections = false;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (message?.type === "HMR_UPDATE_COMPLETED") {
|
|
224
|
+
// NOTE: Do a setTimeout to ensure that server is still available while the HMR update completes.
|
|
225
|
+
// Necessary because some updates are instance, but others might mount a UI that needs a server
|
|
226
|
+
// available (e.g., runs API requests).
|
|
227
|
+
setTimeout(() => {
|
|
228
|
+
restartApplicationProcess(message?.sessions);
|
|
229
|
+
}, 500);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
//};
|
|
233
|
+
//
|
|
234
|
+
//const handleHMRProcessSTDIO = () => {
|
|
235
|
+
// try {
|
|
236
|
+
// if (process.hmrProcess) {
|
|
237
|
+
// process.hmrProcess.on("error", (error) => {
|
|
238
|
+
// CLILog(error.toString(), {
|
|
239
|
+
// level: "danger",
|
|
240
|
+
// docs: "https://github.com/cheatcode/joystick",
|
|
241
|
+
// });
|
|
242
|
+
// });
|
|
243
|
+
//
|
|
244
|
+
// process.hmrProcess.stdout.on("data", (data) => {
|
|
245
|
+
// console.log(data.toString());
|
|
246
|
+
// });
|
|
247
|
+
//
|
|
248
|
+
// process.hmrProcess.stderr.on("data", (data) => {
|
|
249
|
+
// process.loader.stop();
|
|
250
|
+
// CLILog(data.toString(), {
|
|
251
|
+
// level: "danger",
|
|
252
|
+
// docs: "https://github.com/cheatcode/joystick",
|
|
253
|
+
// });
|
|
254
|
+
// });
|
|
255
|
+
// }
|
|
256
|
+
// } catch (exception) {
|
|
257
|
+
// throw new Error(`[dev.handleHMRProcessSTDIO] ${exception.message}`);
|
|
258
|
+
// }
|
|
259
|
+
//};
|
|
260
|
+
//
|
|
261
|
+
const startHMRProcess = () => {
|
|
262
|
+
const execArgv = ["--no-warnings"];
|
|
263
|
+
|
|
264
|
+
if (majorVersion < 19) {
|
|
265
|
+
execArgv.push("--experimental-specifier-resolution=node");
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const hmrProcess = child_process.fork(
|
|
269
|
+
path.resolve(`${__dirname}/hmrServer.js`),
|
|
270
|
+
[],
|
|
271
|
+
{
|
|
272
|
+
execArgv,
|
|
273
|
+
// NOTE: Pipe stdin, stdout, and stderr. IPC establishes a message channel so we
|
|
274
|
+
// communicate with the child_process.
|
|
275
|
+
silent: true,
|
|
276
|
+
}
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
process.hmrProcess = hmrProcess;
|
|
280
|
+
|
|
281
|
+
handleHMRProcessSTDIO();
|
|
282
|
+
handleHMRProcessMessages();
|
|
283
|
+
};
|
|
284
|
+
//
|
|
285
|
+
//const notifyHMRClients = (indexHTMLChanged = false) => {
|
|
286
|
+
// const settings = loadSettings(process.env.NODE_ENV);
|
|
287
|
+
// process.hmrProcess.send(
|
|
288
|
+
// JSON.stringify({
|
|
289
|
+
// type: "RESTART_SERVER",
|
|
290
|
+
// settings,
|
|
291
|
+
// indexHTMLChanged,
|
|
292
|
+
// })
|
|
293
|
+
// );
|
|
294
|
+
//};
|
|
295
|
+
//
|
|
296
|
+
//const handleServerProcessMessages = () => {
|
|
297
|
+
// process.serverProcess.on("message", (message) => {
|
|
298
|
+
// const processMessages = ["SERVER_CLOSED"];
|
|
299
|
+
//
|
|
300
|
+
// if (!processMessages.includes(message)) {
|
|
301
|
+
// process.loader.stable(message);
|
|
302
|
+
// }
|
|
303
|
+
// });
|
|
304
|
+
//};
|
|
305
|
+
//
|
|
306
|
+
//const handleServerProcessSTDIO = () => {
|
|
307
|
+
// try {
|
|
308
|
+
// if (process.serverProcess) {
|
|
309
|
+
// process.serverProcess.on("error", (error) => {
|
|
310
|
+
// console.log(error);
|
|
311
|
+
// });
|
|
312
|
+
//
|
|
313
|
+
// process.serverProcess.stdout.on("data", (data) => {
|
|
314
|
+
// const message = data.toString();
|
|
315
|
+
//
|
|
316
|
+
// if (message && message.includes("App running at:")) {
|
|
317
|
+
// process.loader.stable(message);
|
|
318
|
+
// } else {
|
|
319
|
+
// if (message && !message.includes("BUILD_ERROR")) {
|
|
320
|
+
// console.log(message);
|
|
321
|
+
// }
|
|
322
|
+
// }
|
|
323
|
+
// });
|
|
324
|
+
//
|
|
325
|
+
// process.serverProcess.stderr.on("data", (data) => {
|
|
326
|
+
// process.loader.stop();
|
|
327
|
+
// CLILog(data.toString(), {
|
|
328
|
+
// level: "danger",
|
|
329
|
+
// docs: "https://github.com/cheatcode/joystick",
|
|
330
|
+
// });
|
|
331
|
+
// });
|
|
332
|
+
// }
|
|
333
|
+
// } catch (exception) {
|
|
334
|
+
// throw new Error(`[dev.handleServerProcessSTDIO] ${exception.message}`);
|
|
335
|
+
// }
|
|
336
|
+
//};
|
|
337
|
+
//
|
|
338
|
+
//const startApplicationProcess = (sessionsBeforeHMRUpdate = null) => {
|
|
339
|
+
// const execArgv = ["--no-warnings"];
|
|
340
|
+
//
|
|
341
|
+
// if (majorVersion < 19) {
|
|
342
|
+
// execArgv.push("--experimental-specifier-resolution=node");
|
|
343
|
+
// }
|
|
344
|
+
//
|
|
345
|
+
// if (
|
|
346
|
+
// process.env.NODE_ENV === "development" &&
|
|
347
|
+
// process.env.IS_DEBUG_MODE === "true"
|
|
348
|
+
// ) {
|
|
349
|
+
// execArgv.push("--inspect");
|
|
350
|
+
// }
|
|
351
|
+
//
|
|
352
|
+
// const serverProcess = child_process.fork(
|
|
353
|
+
// path.resolve(".joystick/build/index.server.js"),
|
|
354
|
+
// [],
|
|
355
|
+
// {
|
|
356
|
+
// execArgv,
|
|
357
|
+
// // NOTE: Pipe stdin, stdout, and stderr. IPC establishes a message channel so we
|
|
358
|
+
// // communicate with the child_process.
|
|
359
|
+
// silent: true,
|
|
360
|
+
// env: {
|
|
361
|
+
// FORCE_COLOR: "1",
|
|
362
|
+
// LOGS_PATH: process.env.LOGS_PATH,
|
|
363
|
+
// NODE_ENV: process.env.NODE_ENV,
|
|
364
|
+
// ROOT_URL: process.env.ROOT_URL,
|
|
365
|
+
// PORT: process.env.PORT,
|
|
366
|
+
// JOYSTICK_SETTINGS: process.env.JOYSTICK_SETTINGS,
|
|
367
|
+
// HMR_SESSIONS: sessionsBeforeHMRUpdate,
|
|
368
|
+
// },
|
|
369
|
+
// }
|
|
370
|
+
// );
|
|
371
|
+
//
|
|
372
|
+
// process.serverProcess = serverProcess;
|
|
373
|
+
//
|
|
374
|
+
// handleServerProcessSTDIO();
|
|
375
|
+
// handleServerProcessMessages();
|
|
376
|
+
//
|
|
377
|
+
// return serverProcess;
|
|
378
|
+
//};
|
|
379
|
+
//
|
|
380
|
+
//const restartApplicationProcess = async (sessionsBeforeHMRUpdate = null) => {
|
|
381
|
+
// if (process.serverProcess && process.serverProcess.pid) {
|
|
382
|
+
// process.loader.text("Restarting app...");
|
|
383
|
+
// process.serverProcess.kill();
|
|
384
|
+
// startApplicationProcess(sessionsBeforeHMRUpdate);
|
|
385
|
+
// return Promise.resolve();
|
|
386
|
+
// }
|
|
387
|
+
//
|
|
388
|
+
// // NOTE: Original process was never initialized due to an error.
|
|
389
|
+
// process.loader.text("Starting app...");
|
|
390
|
+
// startApplicationProcess();
|
|
391
|
+
//
|
|
392
|
+
// if (!process.hmrProcess) {
|
|
393
|
+
// startHMRProcess();
|
|
394
|
+
// }
|
|
395
|
+
//};
|
|
396
|
+
//
|
|
397
|
+
//const initialBuild = async (buildSettings = {}) => {
|
|
398
|
+
// const buildPath = `.joystick/build`;
|
|
399
|
+
// const fileMapPath = `.joystick/build/fileMap.json`;
|
|
400
|
+
//
|
|
401
|
+
// if (!fs.existsSync(buildPath)) {
|
|
402
|
+
// fs.mkdirSync(".joystick/build");
|
|
403
|
+
// }
|
|
404
|
+
//
|
|
405
|
+
// if (fs.existsSync(fileMapPath)) {
|
|
406
|
+
// fs.unlinkSync(fileMapPath);
|
|
407
|
+
// }
|
|
408
|
+
//
|
|
409
|
+
// process.loader.text("Building app...");
|
|
410
|
+
//
|
|
411
|
+
// await requiredFileCheck();
|
|
412
|
+
//
|
|
413
|
+
// const filesToBuild = getFilesToBuild(buildSettings?.excludedPaths, "start");
|
|
414
|
+
// const fileResults = await buildFiles(
|
|
415
|
+
// filesToBuild,
|
|
416
|
+
// null,
|
|
417
|
+
// process.env.NODE_ENV
|
|
418
|
+
// );
|
|
419
|
+
//
|
|
420
|
+
// const hasErrors = [...fileResults]
|
|
421
|
+
// .filter((result) => !!result)
|
|
422
|
+
// .map(({ success }) => success)
|
|
423
|
+
// .includes(false);
|
|
424
|
+
//
|
|
425
|
+
// if (!hasErrors) {
|
|
426
|
+
// startApplicationProcess();
|
|
427
|
+
// startHMRProcess();
|
|
428
|
+
// // If the file has errors on startup, no way to trigger a restart w/o a watcher.
|
|
429
|
+
// }
|
|
430
|
+
//};
|
|
431
|
+
//
|
|
432
|
+
//const startWatcher = async (buildSettings = {}) => {
|
|
433
|
+
// await initialBuild(buildSettings);
|
|
434
|
+
//
|
|
435
|
+
// const watcher = chokidar.watch(
|
|
436
|
+
// watchlist.map(({ path }) => path),
|
|
437
|
+
// {
|
|
438
|
+
// ignoreInitial: true,
|
|
439
|
+
// }
|
|
440
|
+
// );
|
|
441
|
+
//
|
|
442
|
+
// watcher.on("all", async (event, path) => {
|
|
443
|
+
// await requiredFileCheck();
|
|
444
|
+
// process.loader.text("Rebuilding app...");
|
|
445
|
+
// const isHTMLUpdate = path === "index.html";
|
|
446
|
+
// const isUIPath = path?.includes("ui/") || path === 'index.css' || isHTMLUpdate;
|
|
447
|
+
// const isUIUpdate =
|
|
448
|
+
// (process.hmrProcess.hasConnections && isUIPath) || false;
|
|
449
|
+
//
|
|
450
|
+
// if (
|
|
451
|
+
// ["addDir"].includes(event) &&
|
|
452
|
+
// fs.existsSync(path) &&
|
|
453
|
+
// fs.lstatSync(path).isDirectory() &&
|
|
454
|
+
// !fs.existsSync(`./.joystick/build/${path}`)
|
|
455
|
+
// ) {
|
|
456
|
+
// fs.mkdirSync(`./.joystick/build/${path}`);
|
|
457
|
+
//
|
|
458
|
+
// if (isUIUpdate) {
|
|
459
|
+
// notifyHMRClients(isHTMLUpdate);
|
|
460
|
+
// } else {
|
|
461
|
+
// restartApplicationProcess();
|
|
462
|
+
// }
|
|
463
|
+
//
|
|
464
|
+
// return;
|
|
465
|
+
// }
|
|
466
|
+
//
|
|
467
|
+
// // If path is file to copy...
|
|
468
|
+
// if (!!filesToCopy.find((fileToCopy) => fileToCopy.path === path)) {
|
|
469
|
+
// const isDirectory = fs.statSync(path).isDirectory();
|
|
470
|
+
//
|
|
471
|
+
// // If path to copy is a directory and doesn't exist in the build...
|
|
472
|
+
// if (isDirectory && !fs.existsSync(`./.joystick/build/${path}`)) {
|
|
473
|
+
// fs.mkdirSync(`./.joystick/build/${path}`);
|
|
474
|
+
// }
|
|
475
|
+
//
|
|
476
|
+
// // If path to copy is not a directory...
|
|
477
|
+
// if (!isDirectory) {
|
|
478
|
+
// fs.writeFileSync(`./.joystick/build/${path}`, fs.readFileSync(path));
|
|
479
|
+
// }
|
|
480
|
+
//
|
|
481
|
+
// // Load settings in case we copied new values over...
|
|
482
|
+
// loadSettings(process.env.NODE_ENV);
|
|
483
|
+
//
|
|
484
|
+
// if (isUIUpdate) {
|
|
485
|
+
// notifyHMRClients(isHTMLUpdate);
|
|
486
|
+
// } else {
|
|
487
|
+
// restartApplicationProcess();
|
|
488
|
+
// }
|
|
489
|
+
//
|
|
490
|
+
// return;
|
|
491
|
+
// }
|
|
492
|
+
//
|
|
493
|
+
// if (["add", "change"].includes(event) && fs.existsSync(path)) {
|
|
494
|
+
// const codependencies = getCodependenciesForFile(path);
|
|
495
|
+
// const fileResults = await buildFiles(
|
|
496
|
+
// [path, ...(codependencies?.existing || [])],
|
|
497
|
+
// null,
|
|
498
|
+
// process.env.NODE_ENV
|
|
499
|
+
// );
|
|
500
|
+
// const fileResultsHaveErrors = fileResults
|
|
501
|
+
// .filter((result) => !!result)
|
|
502
|
+
// .map(({ success }) => success)
|
|
503
|
+
// .includes(false);
|
|
504
|
+
//
|
|
505
|
+
// removeDeletedDependenciesFromMap(codependencies.deleted);
|
|
506
|
+
//
|
|
507
|
+
// const hasErrors = fileResultsHaveErrors;
|
|
508
|
+
//
|
|
509
|
+
// if (process.serverProcess && hasErrors) {
|
|
510
|
+
// process.serverProcess.send(
|
|
511
|
+
// JSON.stringify({
|
|
512
|
+
// error: "BUILD_ERROR",
|
|
513
|
+
// paths: fileResults
|
|
514
|
+
// .filter(({ success }) => !success)
|
|
515
|
+
// .map(({ path: pathWithError, error }) => ({
|
|
516
|
+
// path: pathWithError,
|
|
517
|
+
// error,
|
|
518
|
+
// })),
|
|
519
|
+
// })
|
|
520
|
+
// );
|
|
521
|
+
//
|
|
522
|
+
// return;
|
|
523
|
+
// }
|
|
524
|
+
//
|
|
525
|
+
// if (!hasErrors) {
|
|
526
|
+
// process.initialBuildComplete = true;
|
|
527
|
+
//
|
|
528
|
+
// if (isUIUpdate) {
|
|
529
|
+
// notifyHMRClients(isHTMLUpdate);
|
|
530
|
+
// } else {
|
|
531
|
+
// restartApplicationProcess();
|
|
532
|
+
// }
|
|
533
|
+
//
|
|
534
|
+
// return;
|
|
535
|
+
// }
|
|
536
|
+
// }
|
|
537
|
+
//
|
|
538
|
+
// if (
|
|
539
|
+
// ["unlink", "unlinkDir"].includes(event) &&
|
|
540
|
+
// !fs.existsSync(`./.joystick/build/${path}`)
|
|
541
|
+
// ) {
|
|
542
|
+
// if (isUIUpdate) {
|
|
543
|
+
// notifyHMRClients(isHTMLUpdate);
|
|
544
|
+
// } else {
|
|
545
|
+
// restartApplicationProcess();
|
|
546
|
+
// }
|
|
547
|
+
//
|
|
548
|
+
// return;
|
|
549
|
+
// }
|
|
550
|
+
//
|
|
551
|
+
// if (
|
|
552
|
+
// ["unlink", "unlinkDir"].includes(event) &&
|
|
553
|
+
// fs.existsSync(`./.joystick/build/${path}`)
|
|
554
|
+
// ) {
|
|
555
|
+
// const pathToUnlink = `./.joystick/build/${path}`;
|
|
556
|
+
// const stats = fs.lstatSync(pathToUnlink);
|
|
557
|
+
//
|
|
558
|
+
// if (stats.isDirectory()) {
|
|
559
|
+
// fs.rmdirSync(pathToUnlink, { recursive: true });
|
|
560
|
+
// }
|
|
561
|
+
//
|
|
562
|
+
// if (stats.isFile()) {
|
|
563
|
+
// fs.unlinkSync(pathToUnlink);
|
|
564
|
+
// }
|
|
565
|
+
//
|
|
566
|
+
// if (isUIUpdate) {
|
|
567
|
+
// notifyHMRClients(isHTMLUpdate);
|
|
568
|
+
// } else {
|
|
569
|
+
// restartApplicationProcess();
|
|
570
|
+
// }
|
|
571
|
+
//
|
|
572
|
+
// return;
|
|
573
|
+
// }
|
|
574
|
+
// });
|
|
575
|
+
//};
|
|
576
|
+
//
|
|
577
|
+
//const startDatabase = async (database = {}, databasePort = 2610, hasMultipleOfProvider = false) => {
|
|
578
|
+
// process._databases = {
|
|
579
|
+
// ...(process._databases || {}),
|
|
580
|
+
// [database.provider]: !hasMultipleOfProvider ? await startDatabaseProvider(database, databasePort) : {
|
|
581
|
+
// ...((process._databases && process._databases[database.provider]) || {}),
|
|
582
|
+
// [database?.name || `${database.provider}_${databasePort}`]: await startDatabaseProvider(database, databasePort)
|
|
583
|
+
// },
|
|
584
|
+
// };
|
|
585
|
+
//
|
|
586
|
+
// return Promise.resolve(process._databases);
|
|
587
|
+
//};
|
|
588
|
+
//
|
|
589
|
+
//const startDatabases = async (databasePortStart = 2610) => {
|
|
590
|
+
// try {
|
|
591
|
+
// const hasSettings = !!process.env.JOYSTICK_SETTINGS;
|
|
592
|
+
// const settings = hasSettings && JSON.parse(process.env.JOYSTICK_SETTINGS);
|
|
593
|
+
// const databases = settings?.config?.databases || [];
|
|
594
|
+
//
|
|
595
|
+
// if (databases && Array.isArray(databases) && databases.length > 0) {
|
|
596
|
+
// validateDatabasesFromSettings(databases);
|
|
597
|
+
//
|
|
598
|
+
// for (let i = 0; i < databases?.length; i += 1) {
|
|
599
|
+
// const database = databases[i];
|
|
600
|
+
// const hasMultipleOfProvider = (databases?.filter((database) => database?.provider === database?.provider))?.length > 1;
|
|
601
|
+
//
|
|
602
|
+
// // NOTE: Increment each database port using index in the databases array from settings.
|
|
603
|
+
// await startDatabase(database, databasePortStart + i, hasMultipleOfProvider);
|
|
604
|
+
// }
|
|
605
|
+
//
|
|
606
|
+
// return Promise.resolve();
|
|
607
|
+
// }
|
|
608
|
+
//
|
|
609
|
+
// return Promise.resolve();
|
|
610
|
+
// } catch (exception) {
|
|
611
|
+
// console.warn(exception);
|
|
612
|
+
// }
|
|
613
|
+
//};
|
|
614
|
+
//
|
|
615
|
+
//const loadSettings = () => {
|
|
616
|
+
// const environment = process.env.NODE_ENV;
|
|
617
|
+
// const settingsFilePath = `${process.cwd()}/settings.${environment}.json`;
|
|
618
|
+
// const hasSettingsFile = fs.existsSync(settingsFilePath);
|
|
619
|
+
//
|
|
620
|
+
// if (!hasSettingsFile) {
|
|
621
|
+
// CLILog(
|
|
622
|
+
// `A settings file could not be found for this environment (${environment}). Create a settings.${environment}.json file at the root of your project and restart Joystick.`,
|
|
623
|
+
// {
|
|
624
|
+
// level: "danger",
|
|
625
|
+
// docs: "https://github.com/cheatcode/joystick#settings",
|
|
626
|
+
// }
|
|
627
|
+
// );
|
|
628
|
+
// process.exit(0);
|
|
629
|
+
// }
|
|
630
|
+
//
|
|
631
|
+
// const rawSettingsFile = fs.readFileSync(settingsFilePath, "utf-8");
|
|
632
|
+
// const isValidJSON = isValidJSONString(rawSettingsFile);
|
|
633
|
+
//
|
|
634
|
+
// if (!isValidJSON) {
|
|
635
|
+
// CLILog(
|
|
636
|
+
// `Failed to parse settings file. Double-check the syntax in your settings.${environment}.json file at the root of your project and restart Joystick.`,
|
|
637
|
+
// {
|
|
638
|
+
// level: "danger",
|
|
639
|
+
// docs: "https://github.com/cheatcode/joystick#settings",
|
|
640
|
+
// tools: [{ title: "JSON Linter", url: "https://jsonlint.com/" }],
|
|
641
|
+
// }
|
|
642
|
+
// );
|
|
643
|
+
//
|
|
644
|
+
// process.exit(0);
|
|
645
|
+
// }
|
|
646
|
+
//
|
|
647
|
+
// const settingsFile = isValidJSON ? rawSettingsFile : "{}";
|
|
648
|
+
//
|
|
649
|
+
// // NOTE: Child process will inherit this env var from this parent process.
|
|
650
|
+
// process.env.JOYSTICK_SETTINGS = settingsFile;
|
|
651
|
+
//
|
|
652
|
+
// return JSON.parse(settingsFile);
|
|
653
|
+
//};
|
|
654
|
+
//
|
|
655
|
+
//const checkIfJoystickProject = () => {
|
|
656
|
+
// return fs.existsSync(`${process.cwd()}/.joystick`);
|
|
657
|
+
//};
|
|
658
|
+
|
|
3
659
|
export default async (args = {}, options = {}) => {
|
|
4
660
|
await dev({
|
|
5
661
|
environment: args?.environment || 'development',
|
package/src/lib/dev/index.js
CHANGED
|
@@ -91,6 +91,72 @@ const handleSignalEvents = (processIds = [], nodeMajorVersion = 0, __dirname = '
|
|
|
91
91
|
}
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
+
const handleHMRProcessMessages = (options = {}) => {
|
|
95
|
+
try {
|
|
96
|
+
process.hmrProcess.on("message", (message) => {
|
|
97
|
+
const processMessages = [
|
|
98
|
+
"SERVER_CLOSED",
|
|
99
|
+
"HAS_HMR_CONNECTIONS",
|
|
100
|
+
"HAS_NO_HMR_CONNECTIONS",
|
|
101
|
+
"HMR_UPDATE_COMPLETED",
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
if (!processMessages.includes(message?.type)) {
|
|
105
|
+
process.loader.stable(message);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (message?.type === "HAS_HMR_CONNECTIONS") {
|
|
109
|
+
process.hmrProcess.hasConnections = true;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (message?.type === "HAS_NO_HMR_CONNECTIONS") {
|
|
113
|
+
process.hmrProcess.hasConnections = false;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (message?.type === "HMR_UPDATE_COMPLETED") {
|
|
117
|
+
// NOTE: Do a setTimeout to ensure that server is still available while the HMR update completes.
|
|
118
|
+
// Necessary because some updates are instance, but others might mount a UI that needs a server
|
|
119
|
+
// available (e.g., runs API requests).
|
|
120
|
+
setTimeout(() => {
|
|
121
|
+
handleRestartApplicationProcess({
|
|
122
|
+
...options,
|
|
123
|
+
sessionsBeforeHMRUpdate: message?.sessions,
|
|
124
|
+
});
|
|
125
|
+
}, 500);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
} catch (exception) {
|
|
129
|
+
throw new Error(`[dev.handleHMRProcessMessages] ${exception.message}`);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const handleHMRProcessSTDIO = () => {
|
|
134
|
+
try {
|
|
135
|
+
if (process.hmrProcess) {
|
|
136
|
+
process.hmrProcess.on("error", (error) => {
|
|
137
|
+
CLILog(error.toString(), {
|
|
138
|
+
level: "danger",
|
|
139
|
+
docs: "https://github.com/cheatcode/joystick",
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
process.hmrProcess.stdout.on("data", (data) => {
|
|
144
|
+
console.log(data.toString());
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
process.hmrProcess.stderr.on("data", (data) => {
|
|
148
|
+
process.loader.stop();
|
|
149
|
+
CLILog(data.toString(), {
|
|
150
|
+
level: "danger",
|
|
151
|
+
docs: "https://github.com/cheatcode/joystick",
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
} catch (exception) {
|
|
156
|
+
throw new Error(`[dev.handleHMRProcessSTDIO] ${exception.message}`);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
94
160
|
const handleServerProcessMessages = () => {
|
|
95
161
|
try {
|
|
96
162
|
process.serverProcess.on("message", (message) => {
|
|
@@ -138,7 +204,7 @@ const handleServerProcessSTDIO = () => {
|
|
|
138
204
|
}
|
|
139
205
|
};
|
|
140
206
|
|
|
141
|
-
const handleAddOrChangeFile = async (context = {}, path = '') => {
|
|
207
|
+
const handleAddOrChangeFile = async (context = {}, path = '', options = {}) => {
|
|
142
208
|
try {
|
|
143
209
|
if (context.isAddingOrChangingFile) {
|
|
144
210
|
const codependencies = await getCodependenciesForFile(path);
|
|
@@ -179,10 +245,8 @@ const handleAddOrChangeFile = async (context = {}, path = '') => {
|
|
|
179
245
|
if (context.isUIUpdate) {
|
|
180
246
|
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
181
247
|
} else {
|
|
182
|
-
handleRestartApplicationProcess();
|
|
248
|
+
handleRestartApplicationProcess(options);
|
|
183
249
|
}
|
|
184
|
-
|
|
185
|
-
return;
|
|
186
250
|
}
|
|
187
251
|
}
|
|
188
252
|
} catch (exception) {
|
|
@@ -190,7 +254,7 @@ const handleAddOrChangeFile = async (context = {}, path = '') => {
|
|
|
190
254
|
}
|
|
191
255
|
};
|
|
192
256
|
|
|
193
|
-
const handleAddDirectory = (context = {}, path = '') => {
|
|
257
|
+
const handleAddDirectory = (context = {}, path = '', options = {}) => {
|
|
194
258
|
try {
|
|
195
259
|
if (context.isAddDirectory) {
|
|
196
260
|
fs.mkdirSync(`./.joystick/build/${path}`);
|
|
@@ -198,7 +262,7 @@ const handleAddDirectory = (context = {}, path = '') => {
|
|
|
198
262
|
if (context.isUIUpdate) {
|
|
199
263
|
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
200
264
|
} else {
|
|
201
|
-
handleRestartApplicationProcess();
|
|
265
|
+
handleRestartApplicationProcess(options);
|
|
202
266
|
}
|
|
203
267
|
}
|
|
204
268
|
} catch (exception) {
|
|
@@ -206,7 +270,7 @@ const handleAddDirectory = (context = {}, path = '') => {
|
|
|
206
270
|
}
|
|
207
271
|
};
|
|
208
272
|
|
|
209
|
-
const handleCopyFile = (context = {}, path = '') => {
|
|
273
|
+
const handleCopyFile = (context = {}, path = '', options = {}) => {
|
|
210
274
|
try {
|
|
211
275
|
if (context.isFileToCopy && !context.isDirectory) {
|
|
212
276
|
fs.writeFileSync(`./.joystick/build/${path}`, fs.readFileSync(path));
|
|
@@ -214,7 +278,7 @@ const handleCopyFile = (context = {}, path = '') => {
|
|
|
214
278
|
if (context.isUIUpdate) {
|
|
215
279
|
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
216
280
|
} else {
|
|
217
|
-
handleRestartApplicationProcess();
|
|
281
|
+
handleRestartApplicationProcess(options);
|
|
218
282
|
}
|
|
219
283
|
}
|
|
220
284
|
} catch (exception) {
|
|
@@ -222,7 +286,7 @@ const handleCopyFile = (context = {}, path = '') => {
|
|
|
222
286
|
}
|
|
223
287
|
};
|
|
224
288
|
|
|
225
|
-
const handleCopyDirectory = (context = {}, path = '') => {
|
|
289
|
+
const handleCopyDirectory = (context = {}, path = '', options = {}) => {
|
|
226
290
|
try {
|
|
227
291
|
if (context.isFileToCopy && context.isDirectory && !context.isExistingDirectoryInBuild) {
|
|
228
292
|
fs.mkdirSync(`./.joystick/build/${path}`);
|
|
@@ -230,7 +294,7 @@ const handleCopyDirectory = (context = {}, path = '') => {
|
|
|
230
294
|
if (context.isUIUpdate) {
|
|
231
295
|
handleNotifyHMRClients(context.isHTMLUpdate);
|
|
232
296
|
} else {
|
|
233
|
-
handleRestartApplicationProcess();
|
|
297
|
+
handleRestartApplicationProcess(options);
|
|
234
298
|
}
|
|
235
299
|
}
|
|
236
300
|
} catch (exception) {
|
|
@@ -238,9 +302,28 @@ const handleCopyDirectory = (context = {}, path = '') => {
|
|
|
238
302
|
}
|
|
239
303
|
};
|
|
240
304
|
|
|
241
|
-
const handleRestartApplicationProcess = () => {
|
|
305
|
+
const handleRestartApplicationProcess = async (options = {}) => {
|
|
242
306
|
try {
|
|
243
|
-
|
|
307
|
+
if (process.serverProcess && process.serverProcess.pid) {
|
|
308
|
+
process.loader.text("Restarting app...");
|
|
309
|
+
process.serverProcess.kill();
|
|
310
|
+
|
|
311
|
+
await startApp({
|
|
312
|
+
nodeMajorVersion: options?.nodeMajorVersion,
|
|
313
|
+
port: options?.port,
|
|
314
|
+
sessionsBeforeHMRUpdate: options?.sessionsBeforeHMRUpdate,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
return Promise.resolve();
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// NOTE: Original process was never initialized due to an error.
|
|
321
|
+
process.loader.text("Starting app...");
|
|
322
|
+
startApplicationProcess();
|
|
323
|
+
|
|
324
|
+
if (!process.hmrProcess) {
|
|
325
|
+
startHMR();
|
|
326
|
+
}
|
|
244
327
|
} catch (exception) {
|
|
245
328
|
throw new Error(`[dev.handleRestartApplicationProcess] ${exception.message}`);
|
|
246
329
|
}
|
|
@@ -312,10 +395,10 @@ const startFileWatcher = (options = {}) => {
|
|
|
312
395
|
|
|
313
396
|
const watchChangeContext = getWatchChangeContext(event, path);
|
|
314
397
|
|
|
315
|
-
handleCopyDirectory(watchChangeContext, path);
|
|
316
|
-
handleCopyFile(watchChangeContext, path);
|
|
317
|
-
handleAddDirectory(watchChangeContext, path);
|
|
318
|
-
await handleAddOrChangeFile(watchChangeContext, path);
|
|
398
|
+
handleCopyDirectory(watchChangeContext, path, options);
|
|
399
|
+
handleCopyFile(watchChangeContext, path, options);
|
|
400
|
+
handleAddDirectory(watchChangeContext, path, options);
|
|
401
|
+
await handleAddOrChangeFile(watchChangeContext, path, options);
|
|
319
402
|
|
|
320
403
|
if (watchChangeContext?.isSettingsUpdate) {
|
|
321
404
|
await loadSettings({
|
|
@@ -497,29 +580,36 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
497
580
|
await runInitialBuild(settings?.parsed?.config?.build);
|
|
498
581
|
await startFileWatcher(options);
|
|
499
582
|
|
|
583
|
+
const processIds = [];
|
|
584
|
+
|
|
500
585
|
const serverProcess = await startApp({
|
|
501
586
|
nodeMajorVersion,
|
|
502
587
|
port: options?.port,
|
|
503
588
|
});
|
|
504
589
|
|
|
505
590
|
if (serverProcess) {
|
|
591
|
+
processIds.push(serverProcess.pid);
|
|
506
592
|
process.serverProcess = serverProcess;
|
|
507
593
|
handleServerProcessSTDIO();
|
|
508
594
|
handleServerProcessMessages();
|
|
509
595
|
}
|
|
510
596
|
|
|
511
|
-
// NOTE: Scope this out here so we can reference the processId below.
|
|
512
|
-
let hmrProcess;
|
|
513
|
-
|
|
514
597
|
if (options?.environment !== 'test') {
|
|
515
|
-
hmrProcess = await startHMR({
|
|
598
|
+
const hmrProcess = await startHMR({
|
|
516
599
|
nodeMajorVersion,
|
|
517
600
|
__dirname,
|
|
518
601
|
});
|
|
602
|
+
|
|
603
|
+
processIds.push(hmrProcess.pid);
|
|
604
|
+
process.hmrProcess = hmrProcess;
|
|
605
|
+
|
|
606
|
+
handleHMRProcessSTDIO();
|
|
607
|
+
handleHMRProcessMessages(options);
|
|
519
608
|
}
|
|
520
609
|
|
|
610
|
+
|
|
521
611
|
handleSignalEvents(
|
|
522
|
-
|
|
612
|
+
processIds,
|
|
523
613
|
nodeMajorVersion,
|
|
524
614
|
__dirname
|
|
525
615
|
);
|
package/src/lib/dev/startApp.js
CHANGED
|
@@ -65,7 +65,7 @@ const startApp = (options, { resolve, reject }) => {
|
|
|
65
65
|
validateOptions(options);
|
|
66
66
|
|
|
67
67
|
const execArgv = getExecArgs(options?.nodeMajorVersion);
|
|
68
|
-
const serverProcess = handleStartServerProcess(execArgv);
|
|
68
|
+
const serverProcess = handleStartServerProcess(execArgv, options?.sessionsBeforeHMRUpdate);
|
|
69
69
|
|
|
70
70
|
return resolve(serverProcess);
|
|
71
71
|
} catch (exception) {
|