@joystick.js/cli-canary 0.0.0-canary.9 → 0.0.0-canary.91
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/cli.js +7 -0
- package/dist/functions/index.js +21 -0
- package/dist/functions/start/index.js +3 -489
- package/dist/functions/start/onWarn.js +1 -1
- package/dist/functions/start/setComponentId.js +1 -1
- package/dist/functions/test/index.js +7 -26
- package/dist/lib/build/buildFiles.js +63 -7
- 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/dev/cleanup.js +15 -27
- 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 +104 -28
- 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/cli.js +9 -0
- package/src/functions/index.js +21 -0
- package/src/functions/start/index.js +2 -691
- package/src/functions/start/onWarn.js +1 -1
- package/src/functions/start/setComponentId.js +1 -1
- package/src/functions/test/index.js +7 -32
- package/src/lib/build/buildFiles.js +74 -8
- 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/dev/cleanup.js +20 -28
- 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 +124 -41
- 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
|
@@ -8,6 +8,37 @@ 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
|
+
const handleBuildException = (exception = {}, file = "") => {
|
|
14
|
+
try {
|
|
15
|
+
const error = exception?.errors && exception?.errors[0];
|
|
16
|
+
const snippet = fs.existsSync(file) ? getCodeFrame(file, {
|
|
17
|
+
line: error?.location?.line,
|
|
18
|
+
column: error?.location?.column
|
|
19
|
+
}) : null;
|
|
20
|
+
onWarn({
|
|
21
|
+
file,
|
|
22
|
+
stack: exception?.stack,
|
|
23
|
+
line: error?.location?.line,
|
|
24
|
+
column: error?.location?.column,
|
|
25
|
+
snippet,
|
|
26
|
+
lineWithError: error?.location?.lineText?.trim(),
|
|
27
|
+
message: error?.text
|
|
28
|
+
});
|
|
29
|
+
return snippet;
|
|
30
|
+
} catch (exception2) {
|
|
31
|
+
throw new Error(`[actionName.handleBuildException] ${exception2.message}`);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const handleParseFilePathFromException = (exception = {}) => {
|
|
35
|
+
try {
|
|
36
|
+
const rawErrorMessage = exception?.message?.split(":");
|
|
37
|
+
return rawErrorMessage[1] && rawErrorMessage[1]?.replace("\n", "") || "";
|
|
38
|
+
} catch (exception2) {
|
|
39
|
+
throw new Error(`[actionName.handleParseFilePathFromException] ${exception2.message}`);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
11
42
|
const handleBuildForNode = (nodePaths2 = [], options = {}) => {
|
|
12
43
|
try {
|
|
13
44
|
return esbuild.build({
|
|
@@ -60,7 +91,7 @@ const handleCopyFiles = (files = [], outputPath = "") => {
|
|
|
60
91
|
for (let i = 0; i < files?.length; i += 1) {
|
|
61
92
|
const file = files[i];
|
|
62
93
|
const fileContents = fs.readFileSync(file.path);
|
|
63
|
-
fs.
|
|
94
|
+
fs.outputFileSync(
|
|
64
95
|
`${outputPath || "./.joystick/build"}/${file.path}`,
|
|
65
96
|
fileContents
|
|
66
97
|
);
|
|
@@ -71,7 +102,7 @@ const handleCopyFiles = (files = [], outputPath = "") => {
|
|
|
71
102
|
};
|
|
72
103
|
const isNodePath = (path = "") => {
|
|
73
104
|
try {
|
|
74
|
-
return nodePaths.some((nodePath) => {
|
|
105
|
+
return !isNotJavaScript(path) && nodePaths.some((nodePath) => {
|
|
75
106
|
return path.includes(nodePath);
|
|
76
107
|
}) && !nodePathExclusions.some((nodeExclusionPath) => {
|
|
77
108
|
return path.includes(nodeExclusionPath);
|
|
@@ -82,7 +113,7 @@ const isNodePath = (path = "") => {
|
|
|
82
113
|
};
|
|
83
114
|
const isBrowserPath = (path = "") => {
|
|
84
115
|
try {
|
|
85
|
-
return browserPaths.some((browserPath) => {
|
|
116
|
+
return !isNotJavaScript(path) && browserPaths.some((browserPath) => {
|
|
86
117
|
return path.includes(browserPath);
|
|
87
118
|
}) && !browserPathExclusions.some((browserExclusionPath) => {
|
|
88
119
|
return path.includes(browserExclusionPath);
|
|
@@ -161,16 +192,41 @@ const buildFiles = async (options, { resolve, reject }) => {
|
|
|
161
192
|
const browserFiles = filesWithPlatform?.filter((file) => file?.platform === "browser");
|
|
162
193
|
const nodeFiles = filesWithPlatform?.filter((file) => file?.platform === "node");
|
|
163
194
|
handleCopyFiles(copyFiles, options?.outputPath);
|
|
164
|
-
await Promise.all([
|
|
165
|
-
handleBuildForBrowser(browserFiles, options)
|
|
166
|
-
|
|
195
|
+
const fileResults = await Promise.all([
|
|
196
|
+
handleBuildForBrowser(browserFiles, options).then(() => {
|
|
197
|
+
return { success: true };
|
|
198
|
+
}).catch((exception) => {
|
|
199
|
+
const file = handleParseFilePathFromException(exception);
|
|
200
|
+
console.log(file, exception);
|
|
201
|
+
const snippet = handleBuildException(exception, file);
|
|
202
|
+
return {
|
|
203
|
+
success: false,
|
|
204
|
+
path: file,
|
|
205
|
+
error: {
|
|
206
|
+
stack: exception?.stack,
|
|
207
|
+
snippet
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
}),
|
|
211
|
+
handleBuildForNode(nodeFiles, options).catch((exception) => {
|
|
212
|
+
const file = handleParseFilePathFromException(exception);
|
|
213
|
+
const snippet = handleBuildException(exception, file);
|
|
214
|
+
return {
|
|
215
|
+
success: false,
|
|
216
|
+
path: file,
|
|
217
|
+
error: {
|
|
218
|
+
stack: exception?.stack,
|
|
219
|
+
snippet
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
})
|
|
167
223
|
]);
|
|
168
224
|
if (options?.environment !== "development") {
|
|
169
225
|
await Promise.all([browserFiles, nodeFiles].map((file) => {
|
|
170
226
|
return minifyFile(`${options?.outputPath || "./.joystick/build"}/${file.path}`);
|
|
171
227
|
}));
|
|
172
228
|
}
|
|
173
|
-
resolve();
|
|
229
|
+
resolve(fileResults);
|
|
174
230
|
} catch (exception) {
|
|
175
231
|
reject(`[buildFiles] ${exception.message}`);
|
|
176
232
|
}
|
|
@@ -114,21 +114,24 @@ var buildPlugins_default = {
|
|
|
114
114
|
});
|
|
115
115
|
build.onEnd(() => {
|
|
116
116
|
return new Promise((resolve) => {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
117
|
+
for (let i = 0; i < build?.initialOptions?.entryPoints?.length; i += 1) {
|
|
118
|
+
const entryPoint = build?.initialOptions?.entryPoints[i];
|
|
119
|
+
const shouldSetComponentId = [
|
|
120
|
+
getPlatformSafePath("ui/"),
|
|
121
|
+
getPlatformSafePath("email/")
|
|
122
|
+
].some((bootstrapTarget) => {
|
|
123
|
+
return entryPoint.includes(bootstrapTarget);
|
|
124
|
+
});
|
|
125
|
+
if (shouldSetComponentId) {
|
|
126
|
+
const file = fs.readFileSync(`${build?.initialOptions?.outdir}/${entryPoint}`, "utf-8");
|
|
127
|
+
const joystickUIMatches = file?.match(JOYSTICK_COMPONENT_REGEX) || [];
|
|
128
|
+
if (joystickUIMatches?.length > 0) {
|
|
129
|
+
let contents = setComponentId(file)?.replace(
|
|
130
|
+
/\.component\(\/\*\*\//g,
|
|
131
|
+
".component("
|
|
132
|
+
);
|
|
133
|
+
fs.writeFileSync(`${build?.initialOptions?.outdir}/${entryPoint}`, contents);
|
|
134
|
+
}
|
|
132
135
|
}
|
|
133
136
|
}
|
|
134
137
|
resolve();
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import { codeFrameColumns } from "@babel/code-frame";
|
|
3
|
-
var getCodeFrame_default = (
|
|
4
|
-
const file = fs.readFileSync(
|
|
5
|
-
|
|
6
|
-
return frame;
|
|
3
|
+
var getCodeFrame_default = (path = "", location = {}) => {
|
|
4
|
+
const file = fs.readFileSync(path, "utf-8");
|
|
5
|
+
return codeFrameColumns(file, { start: location });
|
|
7
6
|
};
|
|
8
7
|
export {
|
|
9
8
|
getCodeFrame_default as default
|
package/dist/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
|
const removeLocationDataFromStackTrace = (stackTrace = "") => {
|
|
6
6
|
return stackTrace.replace(OBJECT_REGEX, "");
|
|
7
7
|
};
|
package/dist/lib/dev/cleanup.js
CHANGED
|
@@ -1,30 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (!options)
|
|
10
|
-
throw new Error("options object is required.");
|
|
11
|
-
if (!options.someOption)
|
|
12
|
-
throw new Error("options.someOption is required.");
|
|
13
|
-
} catch (exception) {
|
|
14
|
-
throw new Error(`[cleanup.validateOptions] ${exception.message}`);
|
|
15
|
-
}
|
|
1
|
+
import ps from "ps-node";
|
|
2
|
+
process.title = "joystick_cleanup";
|
|
3
|
+
const killProcess = (pid = 0) => {
|
|
4
|
+
return new Promise((resolve) => {
|
|
5
|
+
ps.kill(pid, () => {
|
|
6
|
+
resolve();
|
|
7
|
+
});
|
|
8
|
+
});
|
|
16
9
|
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
process.on("message", async (message) => {
|
|
11
|
+
const parsedMessage = JSON.parse(message);
|
|
12
|
+
const processIds = parsedMessage?.processIds;
|
|
13
|
+
for (let i = 0; i < processIds?.length; i += 1) {
|
|
14
|
+
const processId = processIds[i];
|
|
15
|
+
await killProcess(processId);
|
|
23
16
|
}
|
|
24
|
-
|
|
25
|
-
var cleanup_default = (options) => new Promise((resolve, reject) => {
|
|
26
|
-
cleanup(options, { resolve, reject });
|
|
17
|
+
process.exit();
|
|
27
18
|
});
|
|
28
|
-
export {
|
|
29
|
-
cleanup_default as default
|
|
30
|
-
};
|
|
@@ -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
|
const getMongoProcessId = async (port = 2601) => {
|
|
9
9
|
const pids = await getProcessIdFromPort(port);
|
|
10
10
|
return pids.tcp && pids.tcp[0];
|
|
@@ -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
|
const exec = util.promisify(child_process.exec);
|
|
10
10
|
const getPostgreSQLProcessId = async (port = 2610) => {
|
|
11
11
|
const pids = await getProcessIdFromPort(port);
|
package/dist/lib/dev/index.js
CHANGED
|
@@ -8,7 +8,6 @@ import loadSettings from "./loadSettings.js";
|
|
|
8
8
|
import Loader from "../loader.js";
|
|
9
9
|
import startDatabases from "./startDatabases.js";
|
|
10
10
|
import runTests from "./runTests.js";
|
|
11
|
-
import cleanup from "./cleanup.js";
|
|
12
11
|
import startHMR from "./startHMR.js";
|
|
13
12
|
import startApp from "./startApp.js";
|
|
14
13
|
import requiredFiles from "./requiredFiles.js";
|
|
@@ -19,12 +18,7 @@ import filesToCopy from "../filesToCopy.js";
|
|
|
19
18
|
import { SETTINGS_FILE_NAME_REGEX } from "../regexes.js";
|
|
20
19
|
import getCodependenciesForFile from "./getCodependenciesForFile.js";
|
|
21
20
|
import removeDeletedDependenciesFromMap from "../build/removeDeletedDependenciesFromMap.js";
|
|
22
|
-
|
|
23
|
-
process?.version?.split(".")[0]?.replace("v", ""),
|
|
24
|
-
10
|
|
25
|
-
);
|
|
26
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
27
|
-
const __dirname = dirname(__filename);
|
|
21
|
+
import chalk from "chalk";
|
|
28
22
|
const getDatabaseProcessIds = () => {
|
|
29
23
|
try {
|
|
30
24
|
const databaseProcessIds = [];
|
|
@@ -49,14 +43,14 @@ const getDatabaseProcessIds = () => {
|
|
|
49
43
|
throw new Error(`[dev.getDatabaseProcessIds] ${exception.message}`);
|
|
50
44
|
}
|
|
51
45
|
};
|
|
52
|
-
const handleSignalEvents = (processIds = []) => {
|
|
46
|
+
const handleSignalEvents = (processIds = [], nodeMajorVersion = 0, __dirname = "") => {
|
|
53
47
|
try {
|
|
54
48
|
const execArgv = ["--no-warnings"];
|
|
55
49
|
if (nodeMajorVersion < 19) {
|
|
56
50
|
execArgv.push("--experimental-specifier-resolution=node");
|
|
57
51
|
}
|
|
58
52
|
const cleanupProcess = child_process.fork(
|
|
59
|
-
path.resolve(`${__dirname}/cleanup
|
|
53
|
+
path.resolve(`${__dirname}/cleanup.js`),
|
|
60
54
|
[],
|
|
61
55
|
{
|
|
62
56
|
// NOTE: Run in detached mode so when parent process dies, the child still runs
|
|
@@ -82,6 +76,46 @@ const handleSignalEvents = (processIds = []) => {
|
|
|
82
76
|
throw new Error(`[dev.handleSignalEvents] ${exception.message}`);
|
|
83
77
|
}
|
|
84
78
|
};
|
|
79
|
+
const handleServerProcessMessages = () => {
|
|
80
|
+
try {
|
|
81
|
+
process.serverProcess.on("message", (message) => {
|
|
82
|
+
const processMessages = ["SERVER_CLOSED"];
|
|
83
|
+
if (!processMessages.includes(message)) {
|
|
84
|
+
process.loader.stable(message);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
} catch (exception) {
|
|
88
|
+
throw new Error(`[dev.handleServerProcessMessages] ${exception.message}`);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const handleServerProcessSTDIO = () => {
|
|
92
|
+
try {
|
|
93
|
+
if (process.serverProcess) {
|
|
94
|
+
process.serverProcess.on("error", (error) => {
|
|
95
|
+
console.log(error);
|
|
96
|
+
});
|
|
97
|
+
process.serverProcess.stdout.on("data", (data) => {
|
|
98
|
+
const message = data.toString();
|
|
99
|
+
if (message && message.includes("App running at:")) {
|
|
100
|
+
process.loader.stable(message);
|
|
101
|
+
} else {
|
|
102
|
+
if (message && !message.includes("BUILD_ERROR")) {
|
|
103
|
+
console.log(message);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
process.serverProcess.stderr.on("data", (data) => {
|
|
108
|
+
process.loader.stop();
|
|
109
|
+
CLILog(data.toString(), {
|
|
110
|
+
level: "danger",
|
|
111
|
+
docs: "https://cheatcode.co/docs/joystick"
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
} catch (exception) {
|
|
116
|
+
throw new Error(`[dev.handleServerProcessSTDIO] ${exception.message}`);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
85
119
|
const handleAddOrChangeFile = async (context = {}, path2 = "") => {
|
|
86
120
|
try {
|
|
87
121
|
if (context.isAddingOrChangingFile) {
|
|
@@ -187,7 +221,7 @@ const getWatchChangeContext = (event = "", path2 = "") => {
|
|
|
187
221
|
try {
|
|
188
222
|
const isHTMLUpdate = path2 === "index.html";
|
|
189
223
|
const isUIPath = path2?.includes("ui/") || path2 === "index.css" || isHTMLUpdate;
|
|
190
|
-
const isUIUpdate = process.hmrProcess.hasConnections && isUIPath || false;
|
|
224
|
+
const isUIUpdate = process.hmrProcess && process.hmrProcess.hasConnections && isUIPath || false;
|
|
191
225
|
const isSettingsUpdate = path2?.match(SETTINGS_FILE_NAME_REGEX)?.length > 0;
|
|
192
226
|
const isDirectory = fs.statSync(path2).isDirectory();
|
|
193
227
|
const isFile = fs.statSync(path2).isFile();
|
|
@@ -242,14 +276,19 @@ const startFileWatcher = (options = {}) => {
|
|
|
242
276
|
};
|
|
243
277
|
const runInitialBuild = async (buildSettings = {}) => {
|
|
244
278
|
try {
|
|
279
|
+
process.loader.text("Building app...");
|
|
245
280
|
const filesToBuild = getFilesToBuild(buildSettings?.excludedPaths, "start");
|
|
246
|
-
const fileResults = await buildFiles(
|
|
247
|
-
filesToBuild,
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
);
|
|
281
|
+
const fileResults = await buildFiles({
|
|
282
|
+
files: filesToBuild,
|
|
283
|
+
environment: process.env.NODE_ENV
|
|
284
|
+
});
|
|
251
285
|
const hasErrors = [...fileResults].filter((result) => !!result).map(({ success }) => success).includes(false);
|
|
286
|
+
if (hasErrors) {
|
|
287
|
+
console.log(chalk.redBright("Failed to start app. Correct the errors above and run joystick start again.\n"));
|
|
288
|
+
process.exit(1);
|
|
289
|
+
}
|
|
252
290
|
} catch (exception) {
|
|
291
|
+
console.warn(exception);
|
|
253
292
|
throw new Error(`[dev.runInitialBuild] ${exception.message}`);
|
|
254
293
|
}
|
|
255
294
|
};
|
|
@@ -287,21 +326,25 @@ const checkForRequiredFiles = () => {
|
|
|
287
326
|
let error = `The following paths are missing and required in a Joystick project:
|
|
288
327
|
|
|
289
328
|
`;
|
|
290
|
-
|
|
329
|
+
if (files?.length > 0) {
|
|
330
|
+
error += ` > Required Files:
|
|
291
331
|
|
|
292
332
|
`;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
333
|
+
for (let i = 0; i < files?.length; i += 1) {
|
|
334
|
+
const file = files[i];
|
|
335
|
+
error += ` /${file.path}
|
|
297
336
|
`;
|
|
337
|
+
}
|
|
298
338
|
}
|
|
299
|
-
|
|
339
|
+
if (directories?.length > 0) {
|
|
340
|
+
error += ` > Required Directories:
|
|
300
341
|
|
|
301
342
|
`;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
343
|
+
for (let i = 0; i < directories?.length; i += 1) {
|
|
344
|
+
const file = directories[i];
|
|
345
|
+
error += ` /${file.path}
|
|
346
|
+
`;
|
|
347
|
+
}
|
|
305
348
|
}
|
|
306
349
|
CLILog(error, {
|
|
307
350
|
level: "danger",
|
|
@@ -327,7 +370,7 @@ const warnInvalidJoystickEnvironment = () => {
|
|
|
327
370
|
);
|
|
328
371
|
process.exit(0);
|
|
329
372
|
}
|
|
330
|
-
if (process.env.NODE_ENV !== "test" &&
|
|
373
|
+
if (process.env.NODE_ENV !== "test" && !hasJoystickFolder) {
|
|
331
374
|
CLILog(
|
|
332
375
|
"joystick start must be run in a directory with a .joystick folder.",
|
|
333
376
|
{
|
|
@@ -355,18 +398,51 @@ const dev = async (options, { resolve, reject }) => {
|
|
|
355
398
|
try {
|
|
356
399
|
validateOptions(options);
|
|
357
400
|
initProcess(options);
|
|
401
|
+
const nodeMajorVersion = parseInt(
|
|
402
|
+
process?.version?.split(".")[0]?.replace("v", ""),
|
|
403
|
+
10
|
|
404
|
+
);
|
|
405
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
406
|
+
const __dirname = dirname(__filename);
|
|
358
407
|
warnInvalidJoystickEnvironment();
|
|
359
408
|
checkForRequiredFiles();
|
|
360
409
|
const settings = await loadSettings({
|
|
410
|
+
environment: options.environment
|
|
411
|
+
});
|
|
412
|
+
await startDatabases({
|
|
361
413
|
environment: options.environment,
|
|
362
|
-
|
|
414
|
+
port: options.port,
|
|
415
|
+
settings: settings.parsed
|
|
363
416
|
});
|
|
364
|
-
await startDatabases(settings.parsed);
|
|
365
417
|
await runInitialBuild(settings?.parsed?.config?.build);
|
|
366
418
|
await startFileWatcher(options);
|
|
367
|
-
|
|
419
|
+
const serverProcess = await startApp({
|
|
420
|
+
nodeMajorVersion,
|
|
421
|
+
port: options?.port
|
|
422
|
+
});
|
|
423
|
+
if (serverProcess) {
|
|
424
|
+
process.serverProcess = serverProcess;
|
|
425
|
+
handleServerProcessSTDIO();
|
|
426
|
+
handleServerProcessMessages();
|
|
427
|
+
}
|
|
428
|
+
let hmrProcess;
|
|
429
|
+
if (options?.environment !== "test") {
|
|
430
|
+
hmrProcess = await startHMR({
|
|
431
|
+
nodeMajorVersion,
|
|
432
|
+
__dirname
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
handleSignalEvents(
|
|
436
|
+
[serverProcess.pid, hmrProcess.pid],
|
|
437
|
+
nodeMajorVersion,
|
|
438
|
+
__dirname
|
|
439
|
+
);
|
|
440
|
+
if (options?.environment === "test") {
|
|
441
|
+
process.loader.text("Running tests...");
|
|
442
|
+
}
|
|
368
443
|
resolve();
|
|
369
444
|
} catch (exception) {
|
|
445
|
+
console.warn(exception);
|
|
370
446
|
reject(`[dev] ${exception.message}`);
|
|
371
447
|
}
|
|
372
448
|
};
|
|
@@ -62,9 +62,7 @@ const loadSettings = (options, { resolve, reject }) => {
|
|
|
62
62
|
warnIfSettingsNotFound(settingsPath);
|
|
63
63
|
const settings = getSettings(settingsPath);
|
|
64
64
|
warnIfInvalidJSONInSettings(settings);
|
|
65
|
-
|
|
66
|
-
options.process.env.JOYSTICK_SETTINGS = settings;
|
|
67
|
-
}
|
|
65
|
+
process.env.JOYSTICK_SETTINGS = settings;
|
|
68
66
|
resolve({
|
|
69
67
|
parsed: JSON.parse(settings),
|
|
70
68
|
unparsed: settings
|
package/dist/lib/dev/startApp.js
CHANGED
|
@@ -1,13 +1,51 @@
|
|
|
1
|
-
|
|
1
|
+
import child_process from "child_process";
|
|
2
|
+
import path from "path";
|
|
3
|
+
const handleStartServerProcess = (execArgv = {}, sessionsBeforeHMRUpdate = {}) => {
|
|
2
4
|
try {
|
|
5
|
+
process.loader.text("Starting app...");
|
|
6
|
+
return child_process.fork(
|
|
7
|
+
path.resolve(".joystick/build/index.server.js"),
|
|
8
|
+
[],
|
|
9
|
+
{
|
|
10
|
+
execArgv,
|
|
11
|
+
// NOTE: Pipe stdin, stdout, and stderr. IPC establishes a message channel so we
|
|
12
|
+
// communicate with the child_process.
|
|
13
|
+
silent: true,
|
|
14
|
+
env: {
|
|
15
|
+
FORCE_COLOR: "1",
|
|
16
|
+
LOGS_PATH: process.env.LOGS_PATH,
|
|
17
|
+
NODE_ENV: process.env.NODE_ENV,
|
|
18
|
+
ROOT_URL: process.env.ROOT_URL,
|
|
19
|
+
PORT: process.env.PORT,
|
|
20
|
+
JOYSTICK_SETTINGS: process.env.JOYSTICK_SETTINGS,
|
|
21
|
+
HMR_SESSIONS: JSON.stringify(sessionsBeforeHMRUpdate)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
);
|
|
3
25
|
} catch (exception) {
|
|
4
|
-
throw new Error(`[startApp.
|
|
26
|
+
throw new Error(`[startApp.handleStartServerProcess] ${exception.message}`);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const getExecArgs = (nodeMajorVersion = 0) => {
|
|
30
|
+
try {
|
|
31
|
+
const execArgv = ["--no-warnings"];
|
|
32
|
+
if (nodeMajorVersion < 19) {
|
|
33
|
+
execArgv.push("--experimental-specifier-resolution=node");
|
|
34
|
+
}
|
|
35
|
+
if (process.env.NODE_ENV === "development" && process.env.IS_DEBUG_MODE === "true") {
|
|
36
|
+
execArgv.push("--inspect");
|
|
37
|
+
}
|
|
38
|
+
return execArgv;
|
|
39
|
+
} catch (exception) {
|
|
40
|
+
throw new Error(`[startApp.getExecArgs] ${exception.message}`);
|
|
5
41
|
}
|
|
6
42
|
};
|
|
7
43
|
const validateOptions = (options) => {
|
|
8
44
|
try {
|
|
9
45
|
if (!options)
|
|
10
46
|
throw new Error("options object is required.");
|
|
47
|
+
if (!options.nodeMajorVersion)
|
|
48
|
+
throw new Error("options.nodeMajorVersion is required.");
|
|
11
49
|
if (!options.port)
|
|
12
50
|
throw new Error("options.port is required.");
|
|
13
51
|
} catch (exception) {
|
|
@@ -17,7 +55,9 @@ const validateOptions = (options) => {
|
|
|
17
55
|
const startApp = (options, { resolve, reject }) => {
|
|
18
56
|
try {
|
|
19
57
|
validateOptions(options);
|
|
20
|
-
|
|
58
|
+
const execArgv = getExecArgs(options?.nodeMajorVersion);
|
|
59
|
+
const serverProcess = handleStartServerProcess(execArgv);
|
|
60
|
+
return resolve(serverProcess);
|
|
21
61
|
} catch (exception) {
|
|
22
62
|
reject(`[startApp] ${exception.message}`);
|
|
23
63
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import util from "util";
|
|
2
1
|
import CLILog from "../CLILog.js";
|
|
3
2
|
import providerMap from "./databases/providerMap.js";
|
|
3
|
+
import { isObject } from "../types.js";
|
|
4
4
|
const startDatabaseProvider = async (environment = "development", database = {}, port = 2610, hasMultipleOfProvider = false) => {
|
|
5
5
|
try {
|
|
6
6
|
const provider = providerMap[database?.provider];
|
|
@@ -19,12 +19,13 @@ const startDatabaseProvider = async (environment = "development", database = {},
|
|
|
19
19
|
throw new Error(`[startDatabases.startDatabaseProvider] ${exception.message}`);
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
|
-
const startDatabaseProviders = async (databases = [], databasePortStart = 2610) => {
|
|
22
|
+
const startDatabaseProviders = async (databases = [], databasePortStart = 2610, environment = "") => {
|
|
23
23
|
try {
|
|
24
24
|
for (let i = 0; i < databases?.length; i += 1) {
|
|
25
25
|
const database = databases[i];
|
|
26
26
|
const hasMultipleOfProvider = databases?.filter((database2) => database2?.provider === database2?.provider)?.length > 1;
|
|
27
27
|
await startDatabaseProvider(
|
|
28
|
+
environment,
|
|
28
29
|
database,
|
|
29
30
|
// NOTE: Increment each database port using index in the databases array from settings if no port
|
|
30
31
|
// is assigned in the settings.
|
|
@@ -39,7 +40,7 @@ const startDatabaseProviders = async (databases = [], databasePortStart = 2610)
|
|
|
39
40
|
const validateDatabasesFromSettings = (databases = []) => {
|
|
40
41
|
try {
|
|
41
42
|
const databasesNotAsObjects = databases.filter(
|
|
42
|
-
(database) => !
|
|
43
|
+
(database) => !isObject(database)
|
|
43
44
|
);
|
|
44
45
|
const userDatabases = databases.filter((database) => !!database.users);
|
|
45
46
|
const queueDatabases = databases.filter((database) => !!database.queues);
|
|
@@ -73,6 +74,8 @@ const validateOptions = (options) => {
|
|
|
73
74
|
try {
|
|
74
75
|
if (!options)
|
|
75
76
|
throw new Error("options object is required.");
|
|
77
|
+
if (!options.environment)
|
|
78
|
+
throw new Error("options.environment is required.");
|
|
76
79
|
if (!options.port)
|
|
77
80
|
throw new Error("options.port is required.");
|
|
78
81
|
if (!options.settings)
|
|
@@ -84,10 +87,14 @@ const validateOptions = (options) => {
|
|
|
84
87
|
const startDatabases = async (options, { resolve, reject }) => {
|
|
85
88
|
try {
|
|
86
89
|
validateOptions(options);
|
|
87
|
-
const databases = options?.settings?.databases || [];
|
|
90
|
+
const databases = options?.settings?.config?.databases || [];
|
|
88
91
|
if (databases?.length > 0) {
|
|
89
92
|
validateDatabasesFromSettings(databases);
|
|
90
|
-
await startDatabaseProviders(
|
|
93
|
+
await startDatabaseProviders(
|
|
94
|
+
databases,
|
|
95
|
+
options?.port + 10,
|
|
96
|
+
options?.environment
|
|
97
|
+
);
|
|
91
98
|
}
|
|
92
99
|
resolve();
|
|
93
100
|
} catch (exception) {
|
package/dist/lib/dev/startHMR.js
CHANGED
|
@@ -1,15 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
import child_process from "child_process";
|
|
2
|
+
import path from "path";
|
|
3
|
+
const handleStartHMRProcess = (execArgv = {}, __dirname = "") => {
|
|
2
4
|
try {
|
|
5
|
+
return child_process.fork(
|
|
6
|
+
path.resolve(`${__dirname}/hmrServer.js`),
|
|
7
|
+
[],
|
|
8
|
+
{
|
|
9
|
+
execArgv,
|
|
10
|
+
// NOTE: Pipe stdin, stdout, and stderr. IPC establishes a message channel so we
|
|
11
|
+
// communicate with the child_process.
|
|
12
|
+
silent: true
|
|
13
|
+
}
|
|
14
|
+
);
|
|
3
15
|
} catch (exception) {
|
|
4
|
-
throw new Error(`[startHMR.
|
|
16
|
+
throw new Error(`[startHMR.handleStartHMRProcess] ${exception.message}`);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const getExecArgs = (nodeMajorVersion = 0) => {
|
|
20
|
+
try {
|
|
21
|
+
const execArgv = ["--no-warnings"];
|
|
22
|
+
if (nodeMajorVersion < 19) {
|
|
23
|
+
execArgv.push("--experimental-specifier-resolution=node");
|
|
24
|
+
}
|
|
25
|
+
return execArgv;
|
|
26
|
+
} catch (exception) {
|
|
27
|
+
throw new Error(`[startHMR.getExecArgs] ${exception.message}`);
|
|
5
28
|
}
|
|
6
29
|
};
|
|
7
30
|
const validateOptions = (options) => {
|
|
8
31
|
try {
|
|
9
32
|
if (!options)
|
|
10
33
|
throw new Error("options object is required.");
|
|
11
|
-
if (!options.
|
|
12
|
-
throw new Error("options.
|
|
34
|
+
if (!options.nodeMajorVersion)
|
|
35
|
+
throw new Error("options.nodeMajorVersion is required.");
|
|
13
36
|
} catch (exception) {
|
|
14
37
|
throw new Error(`[startHMR.validateOptions] ${exception.message}`);
|
|
15
38
|
}
|
|
@@ -17,7 +40,9 @@ const validateOptions = (options) => {
|
|
|
17
40
|
const startHMR = (options, { resolve, reject }) => {
|
|
18
41
|
try {
|
|
19
42
|
validateOptions(options);
|
|
20
|
-
|
|
43
|
+
const execArgv = getExecArgs(options?.nodeMajorVersion);
|
|
44
|
+
const hmrProcess = handleStartHMRProcess(execArgv, options?.__dirname);
|
|
45
|
+
return resolve(hmrProcess);
|
|
21
46
|
} catch (exception) {
|
|
22
47
|
reject(`[startHMR] ${exception.message}`);
|
|
23
48
|
}
|