@nanoforge-dev/cli 1.0.0
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/LICENSE +21 -0
- package/README.md +111 -0
- package/dist/command.loader.d.ts +8 -0
- package/dist/command.loader.js +1435 -0
- package/dist/command.loader.js.map +1 -0
- package/dist/nf.js +1597 -0
- package/package.json +97 -0
package/dist/nf.js
ADDED
|
@@ -0,0 +1,1597 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
29
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
30
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
31
|
+
if (decorator = decorators[i])
|
|
32
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
33
|
+
if (kind && result) __defProp(target, key, result);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// package.json
|
|
38
|
+
var require_package = __commonJS({
|
|
39
|
+
"package.json"(exports, module2) {
|
|
40
|
+
module2.exports = {
|
|
41
|
+
$schema: "https://json.schemastore.org/package.json",
|
|
42
|
+
name: "@nanoforge-dev/cli",
|
|
43
|
+
version: "1.0.0",
|
|
44
|
+
description: "NanoForge CLI",
|
|
45
|
+
keywords: [
|
|
46
|
+
"nanoforge",
|
|
47
|
+
"game",
|
|
48
|
+
"cli"
|
|
49
|
+
],
|
|
50
|
+
homepage: "https://github.com/NanoForge-dev/CLI#readme",
|
|
51
|
+
bugs: "https://github.com/NanoForge-dev/cli/issues",
|
|
52
|
+
license: "MIT",
|
|
53
|
+
contributors: [
|
|
54
|
+
"Bill <timothe.jacquot@epitech.eu>",
|
|
55
|
+
"Exelo <exelo.corp@gmail.com>",
|
|
56
|
+
"Fexkoser <martin.fillon@epitech.eu>",
|
|
57
|
+
"Tchips <leo.outmizguine@epitech.eu>"
|
|
58
|
+
],
|
|
59
|
+
files: [
|
|
60
|
+
"dist"
|
|
61
|
+
],
|
|
62
|
+
bin: {
|
|
63
|
+
nf: "dist/nf.js"
|
|
64
|
+
},
|
|
65
|
+
type: "module",
|
|
66
|
+
directories: {
|
|
67
|
+
lib: "src"
|
|
68
|
+
},
|
|
69
|
+
repository: {
|
|
70
|
+
type: "git",
|
|
71
|
+
url: "git+https://github.com/NanoForge-dev/CLI.git"
|
|
72
|
+
},
|
|
73
|
+
funding: "",
|
|
74
|
+
scripts: {
|
|
75
|
+
build: "tsc --noEmit && tsup",
|
|
76
|
+
start: "node dist/nf.js",
|
|
77
|
+
lint: "prettier --check . && eslint --format=pretty src",
|
|
78
|
+
format: "prettier --write . && eslint --fix --format=pretty src",
|
|
79
|
+
prepack: "pnpm run build && pnpm run lint",
|
|
80
|
+
changelog: "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r . --include-path '.'",
|
|
81
|
+
release: "cliff-jumper",
|
|
82
|
+
prepare: "husky"
|
|
83
|
+
},
|
|
84
|
+
dependencies: {
|
|
85
|
+
"@angular-devkit/schematics": "^21.0.1",
|
|
86
|
+
"@angular-devkit/schematics-cli": "^21.0.1",
|
|
87
|
+
"@inquirer/prompts": "^7.9.0",
|
|
88
|
+
"@nanoforge-dev/loader-client": "^1.0.1",
|
|
89
|
+
"@nanoforge-dev/loader-server": "^1.0.1",
|
|
90
|
+
"@nanoforge-dev/schematics": "^1.0.2",
|
|
91
|
+
ansis: "^4.2.0",
|
|
92
|
+
chokidar: "^4.0.3",
|
|
93
|
+
"class-transformer": "^0.5.1",
|
|
94
|
+
"class-validator": "^0.14.2",
|
|
95
|
+
"cli-table3": "^0.6.5",
|
|
96
|
+
commander: "^14.0.2",
|
|
97
|
+
"node-emoji": "^2.2.0",
|
|
98
|
+
ora: "^9.0.0",
|
|
99
|
+
"reflect-metadata": "^0.2.2"
|
|
100
|
+
},
|
|
101
|
+
devDependencies: {
|
|
102
|
+
"@commitlint/cli": "^20.1.0",
|
|
103
|
+
"@commitlint/config-conventional": "^20.0.0",
|
|
104
|
+
"@eslint/js": "^9.39.0",
|
|
105
|
+
"@favware/cliff-jumper": "^6.0.0",
|
|
106
|
+
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
|
107
|
+
"@types/inquirer": "^9.0.9",
|
|
108
|
+
"@types/node": "^24.10.1",
|
|
109
|
+
"@typescript-eslint/eslint-plugin": "^8.46.2",
|
|
110
|
+
"@typescript-eslint/parser": "^8.46.2",
|
|
111
|
+
eslint: "^9.39.0",
|
|
112
|
+
"eslint-config-prettier": "^10.1.8",
|
|
113
|
+
"eslint-formatter-pretty": "^7.0.0",
|
|
114
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
115
|
+
globals: "^16.5.0",
|
|
116
|
+
husky: "^9.1.7",
|
|
117
|
+
"lint-staged": "^16.2.6",
|
|
118
|
+
prettier: "^3.6.2",
|
|
119
|
+
taze: "^19.9.0",
|
|
120
|
+
tsup: "^8.5.1",
|
|
121
|
+
typescript: "^5.9.3",
|
|
122
|
+
"typescript-eslint": "^8.46.2"
|
|
123
|
+
},
|
|
124
|
+
packageManager: "pnpm@10.24.0",
|
|
125
|
+
engines: {
|
|
126
|
+
node: "24.11.1"
|
|
127
|
+
},
|
|
128
|
+
publishConfig: {
|
|
129
|
+
access: "public"
|
|
130
|
+
},
|
|
131
|
+
"lint-staged": {
|
|
132
|
+
"**/*.ts": [
|
|
133
|
+
"prettier --write"
|
|
134
|
+
],
|
|
135
|
+
"src/**/*.ts": [
|
|
136
|
+
"eslint --fix"
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// src/bin/nf.ts
|
|
144
|
+
import { program } from "commander";
|
|
145
|
+
import "reflect-metadata";
|
|
146
|
+
|
|
147
|
+
// src/lib/utils/local-binaries.ts
|
|
148
|
+
import { existsSync } from "fs";
|
|
149
|
+
import { join, posix } from "path";
|
|
150
|
+
var localBinPathSegments = [process.cwd(), "node_modules", "@nanoforge-dev", "cli", "dist"];
|
|
151
|
+
var localBinExists = /* @__PURE__ */ __name(() => {
|
|
152
|
+
return existsSync(join(...localBinPathSegments));
|
|
153
|
+
}, "localBinExists");
|
|
154
|
+
var loadLocalBinCommandLoader = /* @__PURE__ */ __name(async () => {
|
|
155
|
+
const commandsFile = await import(posix.join(...localBinPathSegments, "command.loader.js"));
|
|
156
|
+
return commandsFile.CommandLoader;
|
|
157
|
+
}, "loadLocalBinCommandLoader");
|
|
158
|
+
|
|
159
|
+
// src/command/command.loader.ts
|
|
160
|
+
import { red as red6 } from "ansis";
|
|
161
|
+
|
|
162
|
+
// src/lib/ui/messages.ts
|
|
163
|
+
import { green } from "ansis";
|
|
164
|
+
|
|
165
|
+
// src/lib/ui/emojis.ts
|
|
166
|
+
import { get } from "node-emoji";
|
|
167
|
+
var Emojis = {
|
|
168
|
+
HEART: get("heart"),
|
|
169
|
+
COFFEE: get("coffee"),
|
|
170
|
+
BEER: get("beer"),
|
|
171
|
+
BROKEN_HEART: get("broken_heart"),
|
|
172
|
+
CRYING: get("crying_cat_face"),
|
|
173
|
+
HEART_EYES: get("heart_eyes_cat"),
|
|
174
|
+
JOY: get("joy_cat"),
|
|
175
|
+
KISSING: get("kissing_cat"),
|
|
176
|
+
SCREAM: get("scream_cat"),
|
|
177
|
+
ROCKET: get("rocket"),
|
|
178
|
+
SMIRK: get("smirk_cat"),
|
|
179
|
+
RAISED_HANDS: get("raised_hands"),
|
|
180
|
+
POINT_RIGHT: get("point_right"),
|
|
181
|
+
SPARKLES: get("sparkles"),
|
|
182
|
+
BOOM: get("boom"),
|
|
183
|
+
PRAY: get("pray"),
|
|
184
|
+
WINE: get("wine_glass")
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// src/lib/ui/messages.ts
|
|
188
|
+
var Messages = {
|
|
189
|
+
BUILD_START: "NanoForge Build",
|
|
190
|
+
BUILD_PART_IN_PROGRESS: /* @__PURE__ */ __name((part) => `Building ${part}...`, "BUILD_PART_IN_PROGRESS"),
|
|
191
|
+
BUILD_NOTHING: "Nothing to build, terminated.",
|
|
192
|
+
BUILD_SUCCESS: `${Emojis.ROCKET} Build succeeded !`,
|
|
193
|
+
BUILD_PART_FAILED: /* @__PURE__ */ __name((part, commandToRunManually) => `${Emojis.SCREAM} Build of ${part} failed !
|
|
194
|
+
In case you don't see any errors above, consider manually running the failed command ${commandToRunManually} to see more details on why it errored out.`, "BUILD_PART_FAILED"),
|
|
195
|
+
BUILD_FAILED: `${Emojis.SCREAM} Build failed !`,
|
|
196
|
+
INSTALL_START: "NanoForge Installation",
|
|
197
|
+
INSTALL_NAMES_QUESTION: "Witch libraries do you want to install ?",
|
|
198
|
+
NEW_START: "NanoForge Project Creation",
|
|
199
|
+
NEW_SUCCESS: `${Emojis.ROCKET} Project successfully created !`,
|
|
200
|
+
NEW_FAILED: `${Emojis.SCREAM} Project creation failed !`,
|
|
201
|
+
NEW_NAME_QUESTION: "What is the name of your project ?",
|
|
202
|
+
NEW_PACKAGE_MANAGER_QUESTION: "Which package manager do you want to use ?",
|
|
203
|
+
NEW_LANGUAGE_QUESTION: "Which language do you want to use ?",
|
|
204
|
+
NEW_STRICT_QUESTION: "Do you want to use types strict mode ?",
|
|
205
|
+
NEW_SERVER_QUESTION: "Do you want generate a server to create a multiplayer game ?",
|
|
206
|
+
NEW_SKIP_INSTALL_QUESTION: "Do you want to skip installation ?",
|
|
207
|
+
SCHEMATICS_START: "Schematics execution",
|
|
208
|
+
SCHEMATIC_IN_PROGRESS: /* @__PURE__ */ __name((name) => `Executing schematic ${name}...`, "SCHEMATIC_IN_PROGRESS"),
|
|
209
|
+
SCHEMATIC_SUCCESS: /* @__PURE__ */ __name((name) => `${Emojis.ROCKET} Schematic ${name} executed successfully !`, "SCHEMATIC_SUCCESS"),
|
|
210
|
+
SCHEMATIC_FAILED: /* @__PURE__ */ __name((name) => `${Emojis.SCREAM} Schematic ${name} execution failed. See error below for more details.`, "SCHEMATIC_FAILED"),
|
|
211
|
+
PACKAGE_MANAGER_INSTALLATION_IN_PROGRESS: `Installation in progress... ${Emojis.COFFEE}`,
|
|
212
|
+
PACKAGE_MANAGER_INSTALLATION_NOTHING: "Nothing to install, terminated.",
|
|
213
|
+
PACKAGE_MANAGER_INSTALLATION_SUCCEED: /* @__PURE__ */ __name((names) => names ? `${Emojis.ROCKET} Packages successfully installed : ${names.map((name) => green(name)).join(", ")} !` : `${Emojis.ROCKET} Packages successfully installed !`, "PACKAGE_MANAGER_INSTALLATION_SUCCEED"),
|
|
214
|
+
PACKAGE_MANAGER_INSTALLATION_FAILED: /* @__PURE__ */ __name((commandToRunManually) => `${Emojis.SCREAM} Packages installation failed !
|
|
215
|
+
In case you don't see any errors above, consider manually running the failed command ${commandToRunManually} to see more details on why it errored out.`, "PACKAGE_MANAGER_INSTALLATION_FAILED"),
|
|
216
|
+
RUN_START: "NanoForge Run",
|
|
217
|
+
RUN_PART_IN_PROGRESS: /* @__PURE__ */ __name((part) => `Running ${part}...`, "RUN_PART_IN_PROGRESS"),
|
|
218
|
+
RUN_PART_SUCCESS: /* @__PURE__ */ __name((part) => `${Emojis.ROCKET} Run of ${part} terminated.`, "RUN_PART_SUCCESS"),
|
|
219
|
+
RUN_PART_FAILED: /* @__PURE__ */ __name((part) => `${Emojis.SCREAM} Run of ${part} failed !`, "RUN_PART_FAILED"),
|
|
220
|
+
RUNNER_EXECUTION_ERROR: /* @__PURE__ */ __name((command) => `
|
|
221
|
+
Failed to execute command: ${command}`, "RUNNER_EXECUTION_ERROR")
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// src/lib/ui/prefixes.ts
|
|
225
|
+
import { bgRgb } from "ansis";
|
|
226
|
+
var Prefixes = {
|
|
227
|
+
INFO: bgRgb(60, 190, 100).bold.rgb(0, 0, 0)(" Info "),
|
|
228
|
+
ERROR: bgRgb(210, 0, 75).bold.rgb(0, 0, 0)(" Error ")
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// src/action/actions/build.action.ts
|
|
232
|
+
import * as ansis from "ansis";
|
|
233
|
+
import * as process3 from "process";
|
|
234
|
+
|
|
235
|
+
// src/lib/input/base-inputs.ts
|
|
236
|
+
var getStringInput = /* @__PURE__ */ __name((input2, field) => {
|
|
237
|
+
const value = input2.get(field)?.value;
|
|
238
|
+
if (value === void 0) return void 0;
|
|
239
|
+
if (typeof value === "string") return value;
|
|
240
|
+
throw new Error(`Invalid type for ${field}`);
|
|
241
|
+
}, "getStringInput");
|
|
242
|
+
var getStringInputWithDefault = /* @__PURE__ */ __name((input2, field, defaultValue) => {
|
|
243
|
+
return getStringInput(input2, field) ?? defaultValue;
|
|
244
|
+
}, "getStringInputWithDefault");
|
|
245
|
+
var getBooleanInput = /* @__PURE__ */ __name((input2, field) => {
|
|
246
|
+
const value = input2.get(field)?.value;
|
|
247
|
+
if (value === void 0) return void 0;
|
|
248
|
+
if (typeof value === "boolean") return value;
|
|
249
|
+
throw new Error(`Invalid type for ${field}`);
|
|
250
|
+
}, "getBooleanInput");
|
|
251
|
+
var getBooleanInputWithDefault = /* @__PURE__ */ __name((input2, field, defaultValue) => {
|
|
252
|
+
return getBooleanInput(input2, field) ?? defaultValue;
|
|
253
|
+
}, "getBooleanInputWithDefault");
|
|
254
|
+
var getArrayInput = /* @__PURE__ */ __name((input2, field) => {
|
|
255
|
+
const value = input2.get(field)?.value;
|
|
256
|
+
if (value === void 0) return void 0;
|
|
257
|
+
if (typeof value === "object" && Array.isArray(value)) return value;
|
|
258
|
+
throw new Error(`Invalid type for ${field}`);
|
|
259
|
+
}, "getArrayInput");
|
|
260
|
+
|
|
261
|
+
// src/lib/input/ask-inputs.ts
|
|
262
|
+
var getInputOrAsk = /* @__PURE__ */ __name(async (baseInput, askCb, defaultValue) => {
|
|
263
|
+
if (baseInput !== void 0) return baseInput;
|
|
264
|
+
const res = await askCb();
|
|
265
|
+
if (res !== void 0) return res;
|
|
266
|
+
if (defaultValue !== void 0) return defaultValue;
|
|
267
|
+
throw new Error("No input provided");
|
|
268
|
+
}, "getInputOrAsk");
|
|
269
|
+
|
|
270
|
+
// src/lib/input/inputs/directory.input.ts
|
|
271
|
+
function getDirectoryInput(inputs, withDefault = true) {
|
|
272
|
+
if (withDefault) return getStringInputWithDefault(inputs, "directory", ".");
|
|
273
|
+
return getStringInput(inputs, "directory");
|
|
274
|
+
}
|
|
275
|
+
__name(getDirectoryInput, "getDirectoryInput");
|
|
276
|
+
|
|
277
|
+
// src/lib/input/inputs/config.input.ts
|
|
278
|
+
var getConfigInput = /* @__PURE__ */ __name((inputs) => {
|
|
279
|
+
return getStringInputWithDefault(inputs, "config", ".");
|
|
280
|
+
}, "getConfigInput");
|
|
281
|
+
|
|
282
|
+
// src/lib/question/questions/confirm.question.ts
|
|
283
|
+
import { confirm } from "@inquirer/prompts";
|
|
284
|
+
|
|
285
|
+
// src/lib/utils/errors.ts
|
|
286
|
+
var promptError = /* @__PURE__ */ __name((err) => {
|
|
287
|
+
if (err.name === "ExitPromptError") {
|
|
288
|
+
process.exit(1);
|
|
289
|
+
} else {
|
|
290
|
+
throw err;
|
|
291
|
+
}
|
|
292
|
+
}, "promptError");
|
|
293
|
+
|
|
294
|
+
// src/lib/question/questions/confirm.question.ts
|
|
295
|
+
var askConfirm = /* @__PURE__ */ __name(async (question, baseOptions) => {
|
|
296
|
+
const options = {
|
|
297
|
+
default: false,
|
|
298
|
+
...baseOptions ?? {}
|
|
299
|
+
};
|
|
300
|
+
return await confirm({
|
|
301
|
+
message: question,
|
|
302
|
+
default: options.default
|
|
303
|
+
}).catch(promptError);
|
|
304
|
+
}, "askConfirm");
|
|
305
|
+
|
|
306
|
+
// src/lib/question/questions/input.question.ts
|
|
307
|
+
import { input } from "@inquirer/prompts";
|
|
308
|
+
var askInput = /* @__PURE__ */ __name(async (question, baseOptions) => {
|
|
309
|
+
const options = {
|
|
310
|
+
required: false,
|
|
311
|
+
...baseOptions ?? {}
|
|
312
|
+
};
|
|
313
|
+
return await input({
|
|
314
|
+
message: question,
|
|
315
|
+
required: options.required,
|
|
316
|
+
default: options.default
|
|
317
|
+
}).catch(promptError);
|
|
318
|
+
}, "askInput");
|
|
319
|
+
var askInputArray = /* @__PURE__ */ __name(async (question, baseOptions) => {
|
|
320
|
+
const options = {
|
|
321
|
+
required: false,
|
|
322
|
+
split: " ",
|
|
323
|
+
filter: true,
|
|
324
|
+
...baseOptions ?? {}
|
|
325
|
+
};
|
|
326
|
+
const res = (await input({
|
|
327
|
+
message: question,
|
|
328
|
+
required: options.required,
|
|
329
|
+
default: options.default
|
|
330
|
+
}).catch(promptError)).split(options.split);
|
|
331
|
+
return options.filter ? res.filter((r) => r.length) : res;
|
|
332
|
+
}, "askInputArray");
|
|
333
|
+
|
|
334
|
+
// src/lib/question/questions/number.question.ts
|
|
335
|
+
import { number } from "@inquirer/prompts";
|
|
336
|
+
|
|
337
|
+
// src/lib/question/questions/select.question.ts
|
|
338
|
+
import { checkbox, select } from "@inquirer/prompts";
|
|
339
|
+
var askSelect = /* @__PURE__ */ __name(async (question, choices, baseOptions) => {
|
|
340
|
+
const options = {
|
|
341
|
+
loop: true,
|
|
342
|
+
...baseOptions ?? {}
|
|
343
|
+
};
|
|
344
|
+
return await select({
|
|
345
|
+
message: question,
|
|
346
|
+
choices,
|
|
347
|
+
loop: options.loop,
|
|
348
|
+
default: options.default
|
|
349
|
+
}).catch(promptError);
|
|
350
|
+
}, "askSelect");
|
|
351
|
+
|
|
352
|
+
// src/lib/input/inputs/install/names.input.ts
|
|
353
|
+
var getNamesInput = /* @__PURE__ */ __name((inputs) => {
|
|
354
|
+
return getArrayInput(inputs, "names");
|
|
355
|
+
}, "getNamesInput");
|
|
356
|
+
var getInstallNamesInputOrAsk = /* @__PURE__ */ __name((inputs) => {
|
|
357
|
+
return getInputOrAsk(
|
|
358
|
+
getNamesInput(inputs),
|
|
359
|
+
() => askInputArray(Messages.INSTALL_NAMES_QUESTION, { required: true })
|
|
360
|
+
);
|
|
361
|
+
}, "getInstallNamesInputOrAsk");
|
|
362
|
+
|
|
363
|
+
// src/lib/runner/runner.factory.ts
|
|
364
|
+
import { yellow } from "ansis";
|
|
365
|
+
|
|
366
|
+
// src/lib/runner/abstract.runner.ts
|
|
367
|
+
import { red } from "ansis";
|
|
368
|
+
import { spawn } from "child_process";
|
|
369
|
+
import * as process2 from "process";
|
|
370
|
+
var AbstractRunner = class {
|
|
371
|
+
constructor(binary, args = []) {
|
|
372
|
+
this.binary = binary;
|
|
373
|
+
this.args = args;
|
|
374
|
+
}
|
|
375
|
+
static {
|
|
376
|
+
__name(this, "AbstractRunner");
|
|
377
|
+
}
|
|
378
|
+
async run(args, collect = false, cwd2 = process2.cwd(), env2, listeners, failSpinner) {
|
|
379
|
+
const options = {
|
|
380
|
+
cwd: cwd2,
|
|
381
|
+
stdio: collect ? "pipe" : "inherit",
|
|
382
|
+
shell: true,
|
|
383
|
+
env: { ...process2.env, ...env2 }
|
|
384
|
+
};
|
|
385
|
+
return new Promise((resolve, reject) => {
|
|
386
|
+
const child = spawn(
|
|
387
|
+
`${this.binary} ${[...this.args, ...args].join(" ")}`,
|
|
388
|
+
options
|
|
389
|
+
);
|
|
390
|
+
const res = [];
|
|
391
|
+
child.stdout?.on(
|
|
392
|
+
"data",
|
|
393
|
+
listeners?.onStdout ?? ((data) => res.push(data.toString().replace(/\r\n|\n/, "")))
|
|
394
|
+
);
|
|
395
|
+
child.stderr?.on(
|
|
396
|
+
"data",
|
|
397
|
+
listeners?.onStderr ?? ((data) => res.push(data.toString().replace(/\r\n|\n/, "")))
|
|
398
|
+
);
|
|
399
|
+
child.on("close", (code) => {
|
|
400
|
+
if (code === 0) {
|
|
401
|
+
resolve(collect && res.length ? res.join("\n") : null);
|
|
402
|
+
} else {
|
|
403
|
+
if (failSpinner) failSpinner();
|
|
404
|
+
console.error(
|
|
405
|
+
red(Messages.RUNNER_EXECUTION_ERROR([this.binary, ...this.args, ...args].join(" ")))
|
|
406
|
+
);
|
|
407
|
+
if (res.length) {
|
|
408
|
+
console.error();
|
|
409
|
+
console.error(res.join("\n"));
|
|
410
|
+
console.error();
|
|
411
|
+
}
|
|
412
|
+
reject();
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
rawFullCommand(args) {
|
|
418
|
+
const commandArgs = [...this.args, ...args];
|
|
419
|
+
return `${this.binary} ${commandArgs.join(" ")}`;
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
// src/lib/runner/runners/bun.runner.ts
|
|
424
|
+
var BunRunner = class extends AbstractRunner {
|
|
425
|
+
static {
|
|
426
|
+
__name(this, "BunRunner");
|
|
427
|
+
}
|
|
428
|
+
constructor() {
|
|
429
|
+
super("bun");
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
// src/lib/utils/path.ts
|
|
434
|
+
import { join as join2 } from "path";
|
|
435
|
+
var getCwd = /* @__PURE__ */ __name((directory) => {
|
|
436
|
+
return directory.startsWith("/") ? directory : join2(process.cwd(), directory);
|
|
437
|
+
}, "getCwd");
|
|
438
|
+
var getModulePath = /* @__PURE__ */ __name((name, removeLast = false) => {
|
|
439
|
+
const path = import.meta.resolve(name).replace(/^file:\/\//, "");
|
|
440
|
+
if (removeLast) return path.split("/").slice(0, -1).join("/");
|
|
441
|
+
return path;
|
|
442
|
+
}, "getModulePath");
|
|
443
|
+
|
|
444
|
+
// src/lib/runner/runners/schematic.runner.ts
|
|
445
|
+
var SchematicRunner = class _SchematicRunner extends AbstractRunner {
|
|
446
|
+
static {
|
|
447
|
+
__name(this, "SchematicRunner");
|
|
448
|
+
}
|
|
449
|
+
static getModulePaths() {
|
|
450
|
+
return module.paths;
|
|
451
|
+
}
|
|
452
|
+
static findClosestSchematicsBinary() {
|
|
453
|
+
try {
|
|
454
|
+
return getModulePath("@angular-devkit/schematics-cli/bin/schematics.js");
|
|
455
|
+
} catch (e) {
|
|
456
|
+
console.error(e);
|
|
457
|
+
throw new Error("'schematics' binary path could not be found!");
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
constructor() {
|
|
461
|
+
super(`node`, [`"${_SchematicRunner.findClosestSchematicsBinary()}"`]);
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
// src/lib/runner/runner.factory.ts
|
|
466
|
+
var RunnerFactory = class {
|
|
467
|
+
static {
|
|
468
|
+
__name(this, "RunnerFactory");
|
|
469
|
+
}
|
|
470
|
+
static create(runner) {
|
|
471
|
+
switch (runner) {
|
|
472
|
+
case 0 /* BUN */:
|
|
473
|
+
return new BunRunner();
|
|
474
|
+
case 1 /* SCHEMATIC */:
|
|
475
|
+
return new SchematicRunner();
|
|
476
|
+
default:
|
|
477
|
+
console.info(yellow`[WARN] Unsupported runner: ${runner}`);
|
|
478
|
+
throw Error(`Unsupported runner: ${runner}`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
// src/lib/package-manager/abstract.package-manager.ts
|
|
484
|
+
import { bold, green as green2, red as red2, yellow as yellow2 } from "ansis";
|
|
485
|
+
import ora from "ora";
|
|
486
|
+
var SPINNER = /* @__PURE__ */ __name((message) => ora({
|
|
487
|
+
text: message
|
|
488
|
+
}), "SPINNER");
|
|
489
|
+
var FAIL_SPINNER = /* @__PURE__ */ __name((spinner) => () => spinner.fail(), "FAIL_SPINNER");
|
|
490
|
+
var AbstractPackageManager = class {
|
|
491
|
+
constructor(runner) {
|
|
492
|
+
this.runner = runner;
|
|
493
|
+
}
|
|
494
|
+
static {
|
|
495
|
+
__name(this, "AbstractPackageManager");
|
|
496
|
+
}
|
|
497
|
+
async install(directory) {
|
|
498
|
+
const spinner = SPINNER(Messages.PACKAGE_MANAGER_INSTALLATION_IN_PROGRESS);
|
|
499
|
+
spinner.start();
|
|
500
|
+
try {
|
|
501
|
+
const commandArgs = [this.cli.install, this.cli.silentFlag];
|
|
502
|
+
const collect = true;
|
|
503
|
+
await this.runner.run(
|
|
504
|
+
commandArgs,
|
|
505
|
+
collect,
|
|
506
|
+
getCwd(directory),
|
|
507
|
+
void 0,
|
|
508
|
+
void 0,
|
|
509
|
+
() => spinner.fail()
|
|
510
|
+
);
|
|
511
|
+
spinner.succeed();
|
|
512
|
+
this.printInstallSuccess();
|
|
513
|
+
} catch {
|
|
514
|
+
const commandArgs = [this.cli.install];
|
|
515
|
+
const commandToRun = this.runner.rawFullCommand(commandArgs);
|
|
516
|
+
this.printInstallFailure(commandToRun);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
version() {
|
|
520
|
+
const commandArguments = ["--version"];
|
|
521
|
+
const collect = true;
|
|
522
|
+
return this.runner.run(commandArguments, collect);
|
|
523
|
+
}
|
|
524
|
+
addProduction(directory, dependencies) {
|
|
525
|
+
const command = [this.cli.add, this.cli.saveFlag];
|
|
526
|
+
return this.add(command, directory, dependencies);
|
|
527
|
+
}
|
|
528
|
+
addDevelopment(directory, dependencies) {
|
|
529
|
+
const command = [this.cli.add, this.cli.saveDevFlag];
|
|
530
|
+
return this.add(command, directory, dependencies);
|
|
531
|
+
}
|
|
532
|
+
async build(name, directory, entry, output, flags) {
|
|
533
|
+
if (!this.cli.build) throw new Error(`Package manager ${this.name} does not support building`);
|
|
534
|
+
const spinner = SPINNER(Messages.BUILD_PART_IN_PROGRESS(name));
|
|
535
|
+
spinner.start();
|
|
536
|
+
try {
|
|
537
|
+
const commandArgs = [
|
|
538
|
+
this.cli.build,
|
|
539
|
+
this.cli.silentFlag,
|
|
540
|
+
entry,
|
|
541
|
+
"--outdir",
|
|
542
|
+
output,
|
|
543
|
+
...flags ?? []
|
|
544
|
+
];
|
|
545
|
+
const collect = true;
|
|
546
|
+
await this.runner.run(
|
|
547
|
+
commandArgs,
|
|
548
|
+
collect,
|
|
549
|
+
getCwd(directory),
|
|
550
|
+
void 0,
|
|
551
|
+
void 0,
|
|
552
|
+
FAIL_SPINNER(spinner)
|
|
553
|
+
);
|
|
554
|
+
spinner.succeed();
|
|
555
|
+
return true;
|
|
556
|
+
} catch {
|
|
557
|
+
const commandArgs = [this.cli.install];
|
|
558
|
+
const commandToRun = this.runner.rawFullCommand(commandArgs);
|
|
559
|
+
console.error(red2(Messages.BUILD_PART_FAILED(name, bold(commandToRun))));
|
|
560
|
+
return false;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
async run(name, directory, file, env2 = {}, flags = [], silent = false) {
|
|
564
|
+
if (!this.cli.run) throw new Error(`Package manager ${this.name} does not support running`);
|
|
565
|
+
try {
|
|
566
|
+
console.info(Messages.RUN_PART_IN_PROGRESS(name));
|
|
567
|
+
const commandArgs = [...flags, this.cli.run];
|
|
568
|
+
if (silent) commandArgs.push(this.cli.silentFlag);
|
|
569
|
+
commandArgs.push(file);
|
|
570
|
+
await this.runner.run(commandArgs, true, getCwd(directory), env2, {
|
|
571
|
+
onStdout: this.onRunStdout(name),
|
|
572
|
+
onStderr: this.onRunStderr(name)
|
|
573
|
+
});
|
|
574
|
+
console.info(Messages.RUN_PART_SUCCESS(name));
|
|
575
|
+
return true;
|
|
576
|
+
} catch {
|
|
577
|
+
console.error(red2(Messages.RUN_PART_FAILED(name)));
|
|
578
|
+
return false;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
async add(args, directory, dependencies) {
|
|
582
|
+
if (!dependencies.length) {
|
|
583
|
+
console.info();
|
|
584
|
+
console.info(Messages.PACKAGE_MANAGER_INSTALLATION_NOTHING);
|
|
585
|
+
console.info();
|
|
586
|
+
return true;
|
|
587
|
+
}
|
|
588
|
+
const commandArguments = [...args, ...dependencies];
|
|
589
|
+
const spinner = SPINNER(Messages.PACKAGE_MANAGER_INSTALLATION_IN_PROGRESS);
|
|
590
|
+
spinner.start();
|
|
591
|
+
try {
|
|
592
|
+
const collect = true;
|
|
593
|
+
await this.runner.run(
|
|
594
|
+
commandArguments,
|
|
595
|
+
collect,
|
|
596
|
+
getCwd(directory),
|
|
597
|
+
void 0,
|
|
598
|
+
void 0,
|
|
599
|
+
FAIL_SPINNER(spinner)
|
|
600
|
+
);
|
|
601
|
+
spinner.succeed();
|
|
602
|
+
this.printInstallSuccess(dependencies);
|
|
603
|
+
return true;
|
|
604
|
+
} catch {
|
|
605
|
+
spinner.fail();
|
|
606
|
+
const commandToRun = this.runner.rawFullCommand(commandArguments);
|
|
607
|
+
this.printInstallFailure(commandToRun);
|
|
608
|
+
return false;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
printInstallSuccess(dependencies) {
|
|
612
|
+
console.info();
|
|
613
|
+
console.info(Messages.PACKAGE_MANAGER_INSTALLATION_SUCCEED(dependencies));
|
|
614
|
+
console.info();
|
|
615
|
+
}
|
|
616
|
+
printInstallFailure(command) {
|
|
617
|
+
console.error(red2(Messages.PACKAGE_MANAGER_INSTALLATION_FAILED(bold(command))));
|
|
618
|
+
}
|
|
619
|
+
onRunStdout = /* @__PURE__ */ __name((name) => (chunk) => {
|
|
620
|
+
chunk.toString().replace(/\r\n|\n/g, "\n").replace(/^\n+|\n+$/g, "").split("\n").forEach((line) => {
|
|
621
|
+
const date = yellow2(`[${(/* @__PURE__ */ new Date()).toISOString()}]`);
|
|
622
|
+
const prompt = green2(`(${name}) INFO -`);
|
|
623
|
+
console.info(`${date} ${prompt} ${line}`);
|
|
624
|
+
});
|
|
625
|
+
}, "onRunStdout");
|
|
626
|
+
onRunStderr = /* @__PURE__ */ __name((name) => (chunk) => {
|
|
627
|
+
chunk.toString().replace(/\r\n|\n/g, "\n").replace(/^\n+|\n+$/g, "").split("\n").forEach((line) => {
|
|
628
|
+
const date = yellow2(`[${(/* @__PURE__ */ new Date()).toISOString()}]`);
|
|
629
|
+
const prompt = red2(`(${name}) ERROR -`);
|
|
630
|
+
console.error(`${date} ${prompt} ${line}`);
|
|
631
|
+
});
|
|
632
|
+
}, "onRunStderr");
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
// src/lib/package-manager/package-managers/bun.package-manager.ts
|
|
636
|
+
var BunPackageManager = class extends AbstractPackageManager {
|
|
637
|
+
static {
|
|
638
|
+
__name(this, "BunPackageManager");
|
|
639
|
+
}
|
|
640
|
+
constructor() {
|
|
641
|
+
super(RunnerFactory.create(0 /* BUN */));
|
|
642
|
+
}
|
|
643
|
+
get name() {
|
|
644
|
+
return "bun" /* BUN */.toUpperCase();
|
|
645
|
+
}
|
|
646
|
+
get cli() {
|
|
647
|
+
return {
|
|
648
|
+
install: "install",
|
|
649
|
+
add: "add",
|
|
650
|
+
update: "update",
|
|
651
|
+
remove: "remove",
|
|
652
|
+
build: "build",
|
|
653
|
+
run: "run",
|
|
654
|
+
saveFlag: "--save",
|
|
655
|
+
saveDevFlag: "--dev",
|
|
656
|
+
silentFlag: "--silent"
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
// src/lib/package-manager/package-manager.factory.ts
|
|
662
|
+
var PackageManagerFactory = class {
|
|
663
|
+
static {
|
|
664
|
+
__name(this, "PackageManagerFactory");
|
|
665
|
+
}
|
|
666
|
+
static create(name) {
|
|
667
|
+
switch (name) {
|
|
668
|
+
case "bun" /* BUN */:
|
|
669
|
+
return new BunPackageManager();
|
|
670
|
+
default:
|
|
671
|
+
throw new Error(`Package manager ${name} is not managed.`);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
// src/lib/config/config.type.ts
|
|
677
|
+
import { Expose, Type } from "class-transformer";
|
|
678
|
+
import { IsBoolean, IsEnum, IsNotEmpty, IsPort, IsString, ValidateNested } from "class-validator";
|
|
679
|
+
var BuildConfig = class {
|
|
680
|
+
static {
|
|
681
|
+
__name(this, "BuildConfig");
|
|
682
|
+
}
|
|
683
|
+
entryFile;
|
|
684
|
+
outDir;
|
|
685
|
+
};
|
|
686
|
+
__decorateClass([
|
|
687
|
+
Expose(),
|
|
688
|
+
IsString(),
|
|
689
|
+
IsNotEmpty()
|
|
690
|
+
], BuildConfig.prototype, "entryFile", 2);
|
|
691
|
+
__decorateClass([
|
|
692
|
+
Expose(),
|
|
693
|
+
IsString(),
|
|
694
|
+
IsNotEmpty()
|
|
695
|
+
], BuildConfig.prototype, "outDir", 2);
|
|
696
|
+
var RunConfig = class {
|
|
697
|
+
static {
|
|
698
|
+
__name(this, "RunConfig");
|
|
699
|
+
}
|
|
700
|
+
dir;
|
|
701
|
+
};
|
|
702
|
+
__decorateClass([
|
|
703
|
+
Expose(),
|
|
704
|
+
IsString(),
|
|
705
|
+
IsNotEmpty()
|
|
706
|
+
], RunConfig.prototype, "dir", 2);
|
|
707
|
+
var ClientConfig = class {
|
|
708
|
+
static {
|
|
709
|
+
__name(this, "ClientConfig");
|
|
710
|
+
}
|
|
711
|
+
port;
|
|
712
|
+
gameExposurePort;
|
|
713
|
+
build;
|
|
714
|
+
runtime;
|
|
715
|
+
};
|
|
716
|
+
__decorateClass([
|
|
717
|
+
Expose(),
|
|
718
|
+
IsPort()
|
|
719
|
+
], ClientConfig.prototype, "port", 2);
|
|
720
|
+
__decorateClass([
|
|
721
|
+
Expose(),
|
|
722
|
+
IsPort()
|
|
723
|
+
], ClientConfig.prototype, "gameExposurePort", 2);
|
|
724
|
+
__decorateClass([
|
|
725
|
+
Expose(),
|
|
726
|
+
Type(() => BuildConfig),
|
|
727
|
+
ValidateNested()
|
|
728
|
+
], ClientConfig.prototype, "build", 2);
|
|
729
|
+
__decorateClass([
|
|
730
|
+
Expose(),
|
|
731
|
+
Type(() => RunConfig),
|
|
732
|
+
ValidateNested()
|
|
733
|
+
], ClientConfig.prototype, "runtime", 2);
|
|
734
|
+
var ServerConfig = class {
|
|
735
|
+
static {
|
|
736
|
+
__name(this, "ServerConfig");
|
|
737
|
+
}
|
|
738
|
+
enable;
|
|
739
|
+
port;
|
|
740
|
+
build;
|
|
741
|
+
runtime;
|
|
742
|
+
};
|
|
743
|
+
__decorateClass([
|
|
744
|
+
Expose(),
|
|
745
|
+
IsBoolean()
|
|
746
|
+
], ServerConfig.prototype, "enable", 2);
|
|
747
|
+
__decorateClass([
|
|
748
|
+
Expose(),
|
|
749
|
+
IsPort()
|
|
750
|
+
], ServerConfig.prototype, "port", 2);
|
|
751
|
+
__decorateClass([
|
|
752
|
+
Expose(),
|
|
753
|
+
Type(() => BuildConfig),
|
|
754
|
+
ValidateNested()
|
|
755
|
+
], ServerConfig.prototype, "build", 2);
|
|
756
|
+
__decorateClass([
|
|
757
|
+
Expose(),
|
|
758
|
+
Type(() => RunConfig),
|
|
759
|
+
ValidateNested()
|
|
760
|
+
], ServerConfig.prototype, "runtime", 2);
|
|
761
|
+
var Config = class {
|
|
762
|
+
static {
|
|
763
|
+
__name(this, "Config");
|
|
764
|
+
}
|
|
765
|
+
name;
|
|
766
|
+
language;
|
|
767
|
+
initFunctions;
|
|
768
|
+
client;
|
|
769
|
+
server;
|
|
770
|
+
};
|
|
771
|
+
__decorateClass([
|
|
772
|
+
Expose(),
|
|
773
|
+
IsString(),
|
|
774
|
+
IsNotEmpty()
|
|
775
|
+
], Config.prototype, "name", 2);
|
|
776
|
+
__decorateClass([
|
|
777
|
+
Expose(),
|
|
778
|
+
IsEnum(["ts", "js"])
|
|
779
|
+
], Config.prototype, "language", 2);
|
|
780
|
+
__decorateClass([
|
|
781
|
+
Expose(),
|
|
782
|
+
IsBoolean()
|
|
783
|
+
], Config.prototype, "initFunctions", 2);
|
|
784
|
+
__decorateClass([
|
|
785
|
+
Expose(),
|
|
786
|
+
Type(() => ClientConfig),
|
|
787
|
+
ValidateNested()
|
|
788
|
+
], Config.prototype, "client", 2);
|
|
789
|
+
__decorateClass([
|
|
790
|
+
Expose(),
|
|
791
|
+
Type(() => ServerConfig),
|
|
792
|
+
ValidateNested()
|
|
793
|
+
], Config.prototype, "server", 2);
|
|
794
|
+
|
|
795
|
+
// src/lib/config/config-loader.ts
|
|
796
|
+
import { plainToInstance } from "class-transformer";
|
|
797
|
+
import { validate } from "class-validator";
|
|
798
|
+
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
799
|
+
import { join as join3 } from "path";
|
|
800
|
+
|
|
801
|
+
// src/lib/utils/object.ts
|
|
802
|
+
var isObject = /* @__PURE__ */ __name((item) => {
|
|
803
|
+
return item && typeof item === "object" && !Array.isArray(item);
|
|
804
|
+
}, "isObject");
|
|
805
|
+
var deepMerge = /* @__PURE__ */ __name((target, ...sources) => {
|
|
806
|
+
if (!sources.length) return target;
|
|
807
|
+
const source = sources.shift();
|
|
808
|
+
if (isObject(target) && isObject(source)) {
|
|
809
|
+
for (const key in source) {
|
|
810
|
+
if (isObject(source[key])) {
|
|
811
|
+
if (!target[key]) Object.assign(target, { [key]: {} });
|
|
812
|
+
deepMerge(target[key], source[key]);
|
|
813
|
+
} else {
|
|
814
|
+
Object.assign(target, { [key]: source[key] });
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
return deepMerge(target, ...sources);
|
|
819
|
+
}, "deepMerge");
|
|
820
|
+
|
|
821
|
+
// src/lib/config/config-defaults.ts
|
|
822
|
+
var CONFIG_DEFAULTS = {
|
|
823
|
+
name: "nanoforge-app",
|
|
824
|
+
language: "ts",
|
|
825
|
+
initFunctions: true,
|
|
826
|
+
client: {
|
|
827
|
+
port: "3000",
|
|
828
|
+
gameExposurePort: "3001",
|
|
829
|
+
build: {
|
|
830
|
+
entryFile: "client/main.ts",
|
|
831
|
+
outDir: ".nanoforge/client"
|
|
832
|
+
},
|
|
833
|
+
runtime: {
|
|
834
|
+
dir: ".nanoforge/client"
|
|
835
|
+
}
|
|
836
|
+
},
|
|
837
|
+
server: {
|
|
838
|
+
enable: false,
|
|
839
|
+
port: "3002",
|
|
840
|
+
build: {
|
|
841
|
+
entryFile: "server/main.ts",
|
|
842
|
+
outDir: ".nanoforge/server"
|
|
843
|
+
},
|
|
844
|
+
runtime: {
|
|
845
|
+
dir: ".nanoforge/server"
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
};
|
|
849
|
+
|
|
850
|
+
// src/lib/config/config-loader.ts
|
|
851
|
+
var config;
|
|
852
|
+
var getConfigPath = /* @__PURE__ */ __name((directory, name) => {
|
|
853
|
+
if (name) {
|
|
854
|
+
return join3(directory, name);
|
|
855
|
+
} else {
|
|
856
|
+
for (const n of ["nanoforge.config.json"]) {
|
|
857
|
+
const path = join3(directory, n);
|
|
858
|
+
if (existsSync2(path)) return path;
|
|
859
|
+
}
|
|
860
|
+
throw new Error(`Unsupported config: ${name}`);
|
|
861
|
+
}
|
|
862
|
+
}, "getConfigPath");
|
|
863
|
+
var loadConfig = /* @__PURE__ */ __name(async (directory, name) => {
|
|
864
|
+
if (config) return config;
|
|
865
|
+
let rawData;
|
|
866
|
+
const path = getConfigPath(directory, name);
|
|
867
|
+
if (!path) throw new Error("No config file found");
|
|
868
|
+
try {
|
|
869
|
+
rawData = deepMerge(CONFIG_DEFAULTS, JSON.parse(readFileSync(path, "utf-8")));
|
|
870
|
+
} catch {
|
|
871
|
+
rawData = null;
|
|
872
|
+
}
|
|
873
|
+
if (!rawData) throw new Error(`Not able to read config file : ${path}`);
|
|
874
|
+
const data = plainToInstance(Config, rawData, {
|
|
875
|
+
excludeExtraneousValues: true
|
|
876
|
+
});
|
|
877
|
+
const errors = await validate(data);
|
|
878
|
+
if (errors.length > 0)
|
|
879
|
+
throw new Error(`Invalid config :
|
|
880
|
+
${errors.toString().replace(/,/g, "\n")}`);
|
|
881
|
+
config = data;
|
|
882
|
+
return config;
|
|
883
|
+
}, "loadConfig");
|
|
884
|
+
|
|
885
|
+
// src/action/common/config.ts
|
|
886
|
+
var getConfig = /* @__PURE__ */ __name((inputs, dir) => {
|
|
887
|
+
return loadConfig(dir, getConfigInput(inputs));
|
|
888
|
+
}, "getConfig");
|
|
889
|
+
|
|
890
|
+
// src/action/abstract.action.ts
|
|
891
|
+
var AbstractAction = class {
|
|
892
|
+
static {
|
|
893
|
+
__name(this, "AbstractAction");
|
|
894
|
+
}
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
// src/action/actions/build.action.ts
|
|
898
|
+
var BuildAction = class extends AbstractAction {
|
|
899
|
+
static {
|
|
900
|
+
__name(this, "BuildAction");
|
|
901
|
+
}
|
|
902
|
+
async handle(_args, options) {
|
|
903
|
+
console.info(Messages.BUILD_START);
|
|
904
|
+
console.info();
|
|
905
|
+
try {
|
|
906
|
+
const directory = getDirectoryInput(options);
|
|
907
|
+
const config2 = await getConfig(options, directory);
|
|
908
|
+
const client = getPart(
|
|
909
|
+
config2.client.build,
|
|
910
|
+
options.get("clientDirectory")?.value,
|
|
911
|
+
"client"
|
|
912
|
+
);
|
|
913
|
+
let res = await buildPart("Client", client, directory);
|
|
914
|
+
if (config2.server.enable) {
|
|
915
|
+
const server = getPart(
|
|
916
|
+
config2.server.build,
|
|
917
|
+
options.get("serverDirectory")?.value,
|
|
918
|
+
"server"
|
|
919
|
+
);
|
|
920
|
+
res = await buildPart("Server", server, directory) ? res : false;
|
|
921
|
+
}
|
|
922
|
+
console.info();
|
|
923
|
+
if (!res) console.info(Messages.BUILD_FAILED);
|
|
924
|
+
else console.info(Messages.BUILD_SUCCESS);
|
|
925
|
+
process3.exit(0);
|
|
926
|
+
} catch (e) {
|
|
927
|
+
console.error(e);
|
|
928
|
+
process3.exit(1);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
var getPart = /* @__PURE__ */ __name((config2, directoryOption, target) => {
|
|
933
|
+
return {
|
|
934
|
+
entry: config2.entryFile,
|
|
935
|
+
output: directoryOption || config2.outDir,
|
|
936
|
+
target
|
|
937
|
+
};
|
|
938
|
+
}, "getPart");
|
|
939
|
+
var buildPart = /* @__PURE__ */ __name(async (name, part, directory) => {
|
|
940
|
+
const packageManagerName = "bun" /* BUN */;
|
|
941
|
+
try {
|
|
942
|
+
const packageManager = PackageManagerFactory.create(packageManagerName);
|
|
943
|
+
return await packageManager.build(name, directory, part.entry, part.output, [
|
|
944
|
+
"--asset-naming",
|
|
945
|
+
"[name].[ext]",
|
|
946
|
+
"--target",
|
|
947
|
+
part.target === "client" ? "browser" : "node"
|
|
948
|
+
]);
|
|
949
|
+
} catch (error3) {
|
|
950
|
+
if (error3 && error3.message) {
|
|
951
|
+
console.error(ansis.red(error3.message));
|
|
952
|
+
}
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
955
|
+
}, "buildPart");
|
|
956
|
+
|
|
957
|
+
// src/action/actions/generate.action.ts
|
|
958
|
+
import * as console2 from "console";
|
|
959
|
+
|
|
960
|
+
// src/lib/schematics/abstract.collection.ts
|
|
961
|
+
var AbstractCollection = class {
|
|
962
|
+
constructor(collection, runner, cwd2) {
|
|
963
|
+
this.collection = collection;
|
|
964
|
+
this.runner = runner;
|
|
965
|
+
this.cwd = cwd2;
|
|
966
|
+
}
|
|
967
|
+
static {
|
|
968
|
+
__name(this, "AbstractCollection");
|
|
969
|
+
}
|
|
970
|
+
async execute(name, options, flags, failSpinner) {
|
|
971
|
+
const command = this.buildCommandLine(name, options, flags);
|
|
972
|
+
await this.runner.run(
|
|
973
|
+
command,
|
|
974
|
+
true,
|
|
975
|
+
this.cwd ? getCwd(this.cwd) : void 0,
|
|
976
|
+
void 0,
|
|
977
|
+
void 0,
|
|
978
|
+
failSpinner
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
buildCommandLine(name, options, flags = []) {
|
|
982
|
+
return [`${this.collection}:${name}`, ...flags, ...this.buildOptions(options)];
|
|
983
|
+
}
|
|
984
|
+
buildOptions(options) {
|
|
985
|
+
return options.reduce(
|
|
986
|
+
(old, option) => [...old, ...option.toCommandString()],
|
|
987
|
+
[]
|
|
988
|
+
);
|
|
989
|
+
}
|
|
990
|
+
};
|
|
991
|
+
|
|
992
|
+
// src/lib/schematics/nanoforge.collection.ts
|
|
993
|
+
var NanoforgeCollection = class _NanoforgeCollection extends AbstractCollection {
|
|
994
|
+
static {
|
|
995
|
+
__name(this, "NanoforgeCollection");
|
|
996
|
+
}
|
|
997
|
+
static schematics = [
|
|
998
|
+
{
|
|
999
|
+
name: "application",
|
|
1000
|
+
alias: "application",
|
|
1001
|
+
description: "Generate a new application"
|
|
1002
|
+
},
|
|
1003
|
+
{
|
|
1004
|
+
name: "configuration",
|
|
1005
|
+
alias: "config",
|
|
1006
|
+
description: "Generate a CLI configuration file"
|
|
1007
|
+
},
|
|
1008
|
+
{
|
|
1009
|
+
name: "part-base",
|
|
1010
|
+
alias: "base",
|
|
1011
|
+
description: "Generate a NanoForge Part Base"
|
|
1012
|
+
},
|
|
1013
|
+
{
|
|
1014
|
+
name: "part-main",
|
|
1015
|
+
alias: "main",
|
|
1016
|
+
description: "Generate a NanoForge Part Main file"
|
|
1017
|
+
}
|
|
1018
|
+
];
|
|
1019
|
+
constructor(runner, cwd2) {
|
|
1020
|
+
super("@nanoforge-dev/schematics", runner, cwd2);
|
|
1021
|
+
}
|
|
1022
|
+
async execute(name, options, flags, failSpinner) {
|
|
1023
|
+
const schematic = this.validate(name);
|
|
1024
|
+
await super.execute(schematic, options, flags, failSpinner);
|
|
1025
|
+
}
|
|
1026
|
+
getSchematics() {
|
|
1027
|
+
return _NanoforgeCollection.schematics;
|
|
1028
|
+
}
|
|
1029
|
+
validate(name) {
|
|
1030
|
+
const schematic = _NanoforgeCollection.schematics.find(
|
|
1031
|
+
(s) => s.name === name || s.alias === name
|
|
1032
|
+
);
|
|
1033
|
+
if (schematic === void 0 || schematic === null) {
|
|
1034
|
+
throw new Error(
|
|
1035
|
+
`Invalid schematic "${name}". Please, ensure that "${name}" exists in this collection.`
|
|
1036
|
+
);
|
|
1037
|
+
}
|
|
1038
|
+
return schematic.name;
|
|
1039
|
+
}
|
|
1040
|
+
};
|
|
1041
|
+
|
|
1042
|
+
// src/lib/schematics/collection.factory.ts
|
|
1043
|
+
var CollectionFactory = class {
|
|
1044
|
+
static {
|
|
1045
|
+
__name(this, "CollectionFactory");
|
|
1046
|
+
}
|
|
1047
|
+
static create(collection, directory) {
|
|
1048
|
+
const schematicRunner = RunnerFactory.create(1 /* SCHEMATIC */);
|
|
1049
|
+
if (collection === "@nanoforge-dev/schematics" /* NANOFORGE */) {
|
|
1050
|
+
return new NanoforgeCollection(schematicRunner, directory);
|
|
1051
|
+
} else {
|
|
1052
|
+
return new NanoforgeCollection(schematicRunner, directory);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
};
|
|
1056
|
+
|
|
1057
|
+
// src/lib/utils/formatting.ts
|
|
1058
|
+
var toKebabCase = /* @__PURE__ */ __name((str) => {
|
|
1059
|
+
return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
1060
|
+
}, "toKebabCase");
|
|
1061
|
+
|
|
1062
|
+
// src/lib/schematics/schematic.option.ts
|
|
1063
|
+
var SchematicOption = class {
|
|
1064
|
+
constructor(name, value) {
|
|
1065
|
+
this.name = name;
|
|
1066
|
+
this.value = value;
|
|
1067
|
+
}
|
|
1068
|
+
static {
|
|
1069
|
+
__name(this, "SchematicOption");
|
|
1070
|
+
}
|
|
1071
|
+
get normalizedName() {
|
|
1072
|
+
return toKebabCase(this.name);
|
|
1073
|
+
}
|
|
1074
|
+
toCommandString(prefix) {
|
|
1075
|
+
const normalizedName = `${prefix ? `${prefix}.` : ""}${this.normalizedName}`;
|
|
1076
|
+
if (typeof this.value === "string") {
|
|
1077
|
+
if (this.name === "name") {
|
|
1078
|
+
return [`--${normalizedName}=${this.format()}`];
|
|
1079
|
+
} else if (this.name === "version" || this.name === "path") {
|
|
1080
|
+
return [`--${normalizedName}=${this.value}`];
|
|
1081
|
+
} else {
|
|
1082
|
+
return [`--${normalizedName}="${this.value}"`];
|
|
1083
|
+
}
|
|
1084
|
+
} else if (typeof this.value === "boolean") {
|
|
1085
|
+
const str = normalizedName;
|
|
1086
|
+
return this.value ? [`--${str}`] : [`--no-${str}`];
|
|
1087
|
+
} else if (Array.isArray(this.value)) {
|
|
1088
|
+
return this.value.reduce(
|
|
1089
|
+
(old, option) => [
|
|
1090
|
+
...old,
|
|
1091
|
+
...option.toCommandString(normalizedName)
|
|
1092
|
+
],
|
|
1093
|
+
[]
|
|
1094
|
+
);
|
|
1095
|
+
} else {
|
|
1096
|
+
return [`--${normalizedName}=${this.value}`];
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
format() {
|
|
1100
|
+
return toKebabCase(this.value).split("").reduce((content, char) => {
|
|
1101
|
+
if (char === "(" || char === ")" || char === "[" || char === "]") {
|
|
1102
|
+
return `${content}\\${char}`;
|
|
1103
|
+
}
|
|
1104
|
+
return `${content}${char}`;
|
|
1105
|
+
}, "");
|
|
1106
|
+
}
|
|
1107
|
+
};
|
|
1108
|
+
|
|
1109
|
+
// src/action/common/spinner.ts
|
|
1110
|
+
import ora2 from "ora";
|
|
1111
|
+
var getSpinner = /* @__PURE__ */ __name((message) => ora2({
|
|
1112
|
+
text: message
|
|
1113
|
+
}), "getSpinner");
|
|
1114
|
+
|
|
1115
|
+
// src/action/common/schematics.ts
|
|
1116
|
+
var executeSchematic = /* @__PURE__ */ __name(async (name, collection, schematicName, options) => {
|
|
1117
|
+
const spinner = getSpinner(Messages.SCHEMATIC_IN_PROGRESS(name));
|
|
1118
|
+
spinner.start();
|
|
1119
|
+
await collection.execute(
|
|
1120
|
+
schematicName,
|
|
1121
|
+
mapSchematicOptions(options),
|
|
1122
|
+
void 0,
|
|
1123
|
+
() => spinner.fail(Messages.SCHEMATIC_FAILED(name))
|
|
1124
|
+
);
|
|
1125
|
+
spinner.succeed(Messages.SCHEMATIC_SUCCESS(name));
|
|
1126
|
+
}, "executeSchematic");
|
|
1127
|
+
var mapSchematicOptions = /* @__PURE__ */ __name((inputs) => {
|
|
1128
|
+
return Object.entries(inputs).reduce((old, [key, value]) => {
|
|
1129
|
+
if (value === void 0) return old;
|
|
1130
|
+
return [
|
|
1131
|
+
...old,
|
|
1132
|
+
new SchematicOption(key, typeof value === "object" ? mapSchematicOptions(value) : value)
|
|
1133
|
+
];
|
|
1134
|
+
}, []);
|
|
1135
|
+
}, "mapSchematicOptions");
|
|
1136
|
+
|
|
1137
|
+
// src/action/actions/generate.action.ts
|
|
1138
|
+
var GenerateAction = class extends AbstractAction {
|
|
1139
|
+
static {
|
|
1140
|
+
__name(this, "GenerateAction");
|
|
1141
|
+
}
|
|
1142
|
+
async handle(_args, options) {
|
|
1143
|
+
console2.info(Messages.NEW_START);
|
|
1144
|
+
try {
|
|
1145
|
+
const directory = getDirectoryInput(options);
|
|
1146
|
+
const config2 = await getConfig(options, directory);
|
|
1147
|
+
const values = await getSchemaValues(config2);
|
|
1148
|
+
await generateFiles(values, directory);
|
|
1149
|
+
console2.info();
|
|
1150
|
+
console2.info(Messages.NEW_SUCCESS);
|
|
1151
|
+
process.exit(0);
|
|
1152
|
+
} catch (e) {
|
|
1153
|
+
console2.error(Messages.NEW_FAILED);
|
|
1154
|
+
console2.error(e);
|
|
1155
|
+
process.exit(1);
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
};
|
|
1159
|
+
var getSchemaValues = /* @__PURE__ */ __name(async (config2) => {
|
|
1160
|
+
return {
|
|
1161
|
+
name: config2.name,
|
|
1162
|
+
directory: ".",
|
|
1163
|
+
language: config2.language,
|
|
1164
|
+
server: config2.server.enable,
|
|
1165
|
+
initFunctions: config2.initFunctions
|
|
1166
|
+
};
|
|
1167
|
+
}, "getSchemaValues");
|
|
1168
|
+
var generateFiles = /* @__PURE__ */ __name(async (values, directory) => {
|
|
1169
|
+
console2.info();
|
|
1170
|
+
const collection = CollectionFactory.create("@nanoforge-dev/schematics" /* NANOFORGE */, directory);
|
|
1171
|
+
console2.info();
|
|
1172
|
+
console2.info(Messages.SCHEMATICS_START);
|
|
1173
|
+
console2.info();
|
|
1174
|
+
await executeSchematic("Client main file", collection, "part-main", {
|
|
1175
|
+
name: values.name,
|
|
1176
|
+
part: "client",
|
|
1177
|
+
directory: values.directory,
|
|
1178
|
+
language: values.language,
|
|
1179
|
+
initFunctions: values.initFunctions
|
|
1180
|
+
});
|
|
1181
|
+
if (values.server) {
|
|
1182
|
+
await executeSchematic("Server main file", collection, "part-main", {
|
|
1183
|
+
name: values.name,
|
|
1184
|
+
part: "server",
|
|
1185
|
+
directory: values.directory,
|
|
1186
|
+
language: values.language,
|
|
1187
|
+
initFunctions: values.initFunctions
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
}, "generateFiles");
|
|
1191
|
+
|
|
1192
|
+
// src/action/actions/install.action.ts
|
|
1193
|
+
import * as ansis2 from "ansis";
|
|
1194
|
+
import * as process4 from "process";
|
|
1195
|
+
var InstallAction = class extends AbstractAction {
|
|
1196
|
+
static {
|
|
1197
|
+
__name(this, "InstallAction");
|
|
1198
|
+
}
|
|
1199
|
+
async handle(args, options) {
|
|
1200
|
+
console.info(Messages.INSTALL_START);
|
|
1201
|
+
console.info();
|
|
1202
|
+
try {
|
|
1203
|
+
const names = await getInstallNamesInputOrAsk(args);
|
|
1204
|
+
const directory = getDirectoryInput(options);
|
|
1205
|
+
await installPackages(names, directory);
|
|
1206
|
+
process4.exit(0);
|
|
1207
|
+
} catch (e) {
|
|
1208
|
+
console.error(e);
|
|
1209
|
+
process4.exit(1);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
var installPackages = /* @__PURE__ */ __name(async (names, directory) => {
|
|
1214
|
+
const packageManagerName = "bun" /* BUN */;
|
|
1215
|
+
try {
|
|
1216
|
+
const packageManager = PackageManagerFactory.create(packageManagerName);
|
|
1217
|
+
await packageManager.addProduction(directory, names);
|
|
1218
|
+
} catch (error3) {
|
|
1219
|
+
if (error3 && error3.message) {
|
|
1220
|
+
console.error(ansis2.red(error3.message));
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
}, "installPackages");
|
|
1224
|
+
|
|
1225
|
+
// src/lib/input/inputs/new/init-functions.input.ts
|
|
1226
|
+
var getNewInitFunctionsWithDefault = /* @__PURE__ */ __name((inputs) => {
|
|
1227
|
+
return getBooleanInputWithDefault(inputs, "initFunctions", false);
|
|
1228
|
+
}, "getNewInitFunctionsWithDefault");
|
|
1229
|
+
|
|
1230
|
+
// src/lib/input/inputs/new/language.input.ts
|
|
1231
|
+
var getLanguageInput = /* @__PURE__ */ __name((inputs) => {
|
|
1232
|
+
return getStringInput(inputs, "language");
|
|
1233
|
+
}, "getLanguageInput");
|
|
1234
|
+
var getNewLanguageInputOrAsk = /* @__PURE__ */ __name((inputs) => {
|
|
1235
|
+
return getInputOrAsk(
|
|
1236
|
+
getLanguageInput(inputs),
|
|
1237
|
+
() => askSelect(Messages.NEW_LANGUAGE_QUESTION, [{ value: "ts" }, { value: "js" }], {
|
|
1238
|
+
default: "ts"
|
|
1239
|
+
})
|
|
1240
|
+
);
|
|
1241
|
+
}, "getNewLanguageInputOrAsk");
|
|
1242
|
+
|
|
1243
|
+
// src/lib/input/inputs/new/name.input.ts
|
|
1244
|
+
var getNameInput = /* @__PURE__ */ __name((inputs) => {
|
|
1245
|
+
return getStringInput(inputs, "name");
|
|
1246
|
+
}, "getNameInput");
|
|
1247
|
+
var getNewNameInputOrAsk = /* @__PURE__ */ __name((inputs) => {
|
|
1248
|
+
return getInputOrAsk(
|
|
1249
|
+
getNameInput(inputs),
|
|
1250
|
+
() => askInput(Messages.NEW_NAME_QUESTION, {
|
|
1251
|
+
required: true,
|
|
1252
|
+
default: "nanoforge-app"
|
|
1253
|
+
})
|
|
1254
|
+
);
|
|
1255
|
+
}, "getNewNameInputOrAsk");
|
|
1256
|
+
|
|
1257
|
+
// src/lib/input/inputs/new/package-manager.input.ts
|
|
1258
|
+
var getPackageManagerInput = /* @__PURE__ */ __name((inputs) => {
|
|
1259
|
+
return getStringInput(inputs, "packageManager");
|
|
1260
|
+
}, "getPackageManagerInput");
|
|
1261
|
+
var getNewPackageManagerInputOrAsk = /* @__PURE__ */ __name((inputs) => {
|
|
1262
|
+
return getInputOrAsk(
|
|
1263
|
+
getPackageManagerInput(inputs),
|
|
1264
|
+
() => askSelect(
|
|
1265
|
+
Messages.NEW_PACKAGE_MANAGER_QUESTION,
|
|
1266
|
+
[{ value: "npm" }, { value: "yarn" }, { value: "pnpm" }, { value: "bun" }],
|
|
1267
|
+
{
|
|
1268
|
+
default: "npm"
|
|
1269
|
+
}
|
|
1270
|
+
)
|
|
1271
|
+
);
|
|
1272
|
+
}, "getNewPackageManagerInputOrAsk");
|
|
1273
|
+
|
|
1274
|
+
// src/lib/input/inputs/new/path.input.ts
|
|
1275
|
+
var getNewPathInput = /* @__PURE__ */ __name((inputs) => {
|
|
1276
|
+
return getStringInput(inputs, "path");
|
|
1277
|
+
}, "getNewPathInput");
|
|
1278
|
+
|
|
1279
|
+
// src/lib/input/inputs/new/server.input.ts
|
|
1280
|
+
var getNewServerInput = /* @__PURE__ */ __name((inputs) => {
|
|
1281
|
+
return getBooleanInput(inputs, "server");
|
|
1282
|
+
}, "getNewServerInput");
|
|
1283
|
+
var getNewServerOrAsk = /* @__PURE__ */ __name((inputs) => {
|
|
1284
|
+
return getInputOrAsk(
|
|
1285
|
+
getNewServerInput(inputs),
|
|
1286
|
+
() => askConfirm(Messages.NEW_SERVER_QUESTION, { default: false })
|
|
1287
|
+
);
|
|
1288
|
+
}, "getNewServerOrAsk");
|
|
1289
|
+
|
|
1290
|
+
// src/lib/input/inputs/new/skip-install.input.ts
|
|
1291
|
+
var getNewSkipInstallInput = /* @__PURE__ */ __name((inputs) => {
|
|
1292
|
+
return getBooleanInput(inputs, "skipInstall");
|
|
1293
|
+
}, "getNewSkipInstallInput");
|
|
1294
|
+
var getNewSkipInstallOrAsk = /* @__PURE__ */ __name((inputs) => {
|
|
1295
|
+
return getInputOrAsk(
|
|
1296
|
+
getNewSkipInstallInput(inputs),
|
|
1297
|
+
() => askConfirm(Messages.NEW_SKIP_INSTALL_QUESTION, { default: false })
|
|
1298
|
+
);
|
|
1299
|
+
}, "getNewSkipInstallOrAsk");
|
|
1300
|
+
|
|
1301
|
+
// src/lib/input/inputs/new/strict.input.ts
|
|
1302
|
+
var getNewStrictInput = /* @__PURE__ */ __name((inputs) => {
|
|
1303
|
+
return getBooleanInput(inputs, "strict");
|
|
1304
|
+
}, "getNewStrictInput");
|
|
1305
|
+
var getNewStrictOrAsk = /* @__PURE__ */ __name((inputs) => {
|
|
1306
|
+
return getInputOrAsk(
|
|
1307
|
+
getNewStrictInput(inputs),
|
|
1308
|
+
() => askConfirm(Messages.NEW_STRICT_QUESTION, { default: true })
|
|
1309
|
+
);
|
|
1310
|
+
}, "getNewStrictOrAsk");
|
|
1311
|
+
|
|
1312
|
+
// src/action/actions/new.action.ts
|
|
1313
|
+
var NewAction = class extends AbstractAction {
|
|
1314
|
+
static {
|
|
1315
|
+
__name(this, "NewAction");
|
|
1316
|
+
}
|
|
1317
|
+
async handle(_args, options) {
|
|
1318
|
+
console.info(Messages.NEW_START);
|
|
1319
|
+
try {
|
|
1320
|
+
const directory = getDirectoryInput(options);
|
|
1321
|
+
const values = await getSchemaValues2(options);
|
|
1322
|
+
await generateApplicationFiles(values, directory);
|
|
1323
|
+
console.info();
|
|
1324
|
+
console.info(Messages.NEW_SUCCESS);
|
|
1325
|
+
process.exit(0);
|
|
1326
|
+
} catch {
|
|
1327
|
+
console.error(Messages.NEW_FAILED);
|
|
1328
|
+
process.exit(1);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
var getSchemaValues2 = /* @__PURE__ */ __name(async (inputs) => {
|
|
1333
|
+
return {
|
|
1334
|
+
name: await getNewNameInputOrAsk(inputs),
|
|
1335
|
+
directory: getNewPathInput(inputs),
|
|
1336
|
+
packageManager: await getNewPackageManagerInputOrAsk(inputs),
|
|
1337
|
+
language: await getNewLanguageInputOrAsk(inputs),
|
|
1338
|
+
strict: await getNewStrictOrAsk(inputs),
|
|
1339
|
+
server: await getNewServerOrAsk(inputs),
|
|
1340
|
+
initFunctions: getNewInitFunctionsWithDefault(inputs),
|
|
1341
|
+
skipInstall: await getNewSkipInstallOrAsk(inputs)
|
|
1342
|
+
};
|
|
1343
|
+
}, "getSchemaValues");
|
|
1344
|
+
var generateApplicationFiles = /* @__PURE__ */ __name(async (values, directory) => {
|
|
1345
|
+
console.info();
|
|
1346
|
+
const collection = CollectionFactory.create("@nanoforge-dev/schematics" /* NANOFORGE */, directory);
|
|
1347
|
+
console.info();
|
|
1348
|
+
console.info(Messages.SCHEMATICS_START);
|
|
1349
|
+
console.info();
|
|
1350
|
+
await executeSchematic("Application", collection, "application", {
|
|
1351
|
+
name: values.name,
|
|
1352
|
+
directory: values.directory,
|
|
1353
|
+
packageManager: values.packageManager,
|
|
1354
|
+
language: values.language,
|
|
1355
|
+
strict: values.strict,
|
|
1356
|
+
server: values.server
|
|
1357
|
+
});
|
|
1358
|
+
await executeSchematic("Configuration", collection, "configuration", {
|
|
1359
|
+
name: values.name,
|
|
1360
|
+
directory: values.directory,
|
|
1361
|
+
server: values.server
|
|
1362
|
+
});
|
|
1363
|
+
await executeSchematic("Base Client", collection, "part-base", {
|
|
1364
|
+
name: values.name,
|
|
1365
|
+
part: "client",
|
|
1366
|
+
directory: values.directory,
|
|
1367
|
+
language: values.language,
|
|
1368
|
+
initFunctions: values.initFunctions
|
|
1369
|
+
});
|
|
1370
|
+
await executeSchematic("Client main file", collection, "part-main", {
|
|
1371
|
+
name: values.name,
|
|
1372
|
+
part: "client",
|
|
1373
|
+
directory: values.directory,
|
|
1374
|
+
language: values.language,
|
|
1375
|
+
initFunctions: values.initFunctions
|
|
1376
|
+
});
|
|
1377
|
+
if (values.server) {
|
|
1378
|
+
await executeSchematic("Base server", collection, "part-base", {
|
|
1379
|
+
name: values.name,
|
|
1380
|
+
part: "server",
|
|
1381
|
+
directory: values.directory,
|
|
1382
|
+
language: values.language,
|
|
1383
|
+
initFunctions: values.initFunctions
|
|
1384
|
+
});
|
|
1385
|
+
await executeSchematic("Server main file", collection, "part-main", {
|
|
1386
|
+
name: values.name,
|
|
1387
|
+
part: "server",
|
|
1388
|
+
directory: values.directory,
|
|
1389
|
+
language: values.language,
|
|
1390
|
+
initFunctions: values.initFunctions
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
}, "generateApplicationFiles");
|
|
1394
|
+
|
|
1395
|
+
// src/action/actions/start.action.ts
|
|
1396
|
+
import * as ansis3 from "ansis";
|
|
1397
|
+
import * as console3 from "console";
|
|
1398
|
+
import { join as join4 } from "path";
|
|
1399
|
+
var StartAction = class extends AbstractAction {
|
|
1400
|
+
static {
|
|
1401
|
+
__name(this, "StartAction");
|
|
1402
|
+
}
|
|
1403
|
+
async handle(_args, options) {
|
|
1404
|
+
console3.info(Messages.RUN_START);
|
|
1405
|
+
console3.info();
|
|
1406
|
+
try {
|
|
1407
|
+
const directory = getDirectoryInput(options);
|
|
1408
|
+
const config2 = await getConfig(options, directory);
|
|
1409
|
+
const clientDir = config2.client.runtime.dir;
|
|
1410
|
+
const serverDir = config2.server.runtime.dir;
|
|
1411
|
+
const clientPort = getStringInputWithDefault(options, "clientPort", config2.client.port);
|
|
1412
|
+
await Promise.all([
|
|
1413
|
+
config2.server.enable ? this.startServer(directory, serverDir) : void 0,
|
|
1414
|
+
this.startClient(clientPort, directory, clientDir)
|
|
1415
|
+
]);
|
|
1416
|
+
process.exit(0);
|
|
1417
|
+
} catch (e) {
|
|
1418
|
+
console3.error(e);
|
|
1419
|
+
process.exit(1);
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
async startClient(port, directory, gameDir) {
|
|
1423
|
+
const path = getModulePath("@nanoforge-dev/loader-client/package.json", true);
|
|
1424
|
+
return runPart("Client", path, {
|
|
1425
|
+
PORT: port,
|
|
1426
|
+
GAME_DIR: getCwd(join4(directory, gameDir))
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
startServer(directory, gameDir) {
|
|
1430
|
+
const path = getModulePath("@nanoforge-dev/loader-server/package.json", true);
|
|
1431
|
+
return runPart("Server", path, {
|
|
1432
|
+
GAME_DIR: getCwd(join4(directory, gameDir))
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
};
|
|
1436
|
+
var runPart = /* @__PURE__ */ __name(async (part, directory, env2, flags) => {
|
|
1437
|
+
const packageManagerName = "bun" /* BUN */;
|
|
1438
|
+
try {
|
|
1439
|
+
const packageManager = PackageManagerFactory.create(packageManagerName);
|
|
1440
|
+
await packageManager.run(part, directory, "start", env2, flags, true);
|
|
1441
|
+
} catch (error3) {
|
|
1442
|
+
if (error3 && error3.message) {
|
|
1443
|
+
console3.error(ansis3.red(error3.message));
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
}, "runPart");
|
|
1447
|
+
|
|
1448
|
+
// src/command/abstract.command.ts
|
|
1449
|
+
var AbstractCommand = class {
|
|
1450
|
+
constructor(action) {
|
|
1451
|
+
this.action = action;
|
|
1452
|
+
}
|
|
1453
|
+
static {
|
|
1454
|
+
__name(this, "AbstractCommand");
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1458
|
+
// src/command/commands/build.command.ts
|
|
1459
|
+
var BuildCommand = class extends AbstractCommand {
|
|
1460
|
+
static {
|
|
1461
|
+
__name(this, "BuildCommand");
|
|
1462
|
+
}
|
|
1463
|
+
load(program2) {
|
|
1464
|
+
program2.command("build").description("build your game").option("-d, --directory [directory]", "specify the directory of your project").option("-c, --config [config]", "path to the config file", "nanoforge.config.json").option("--client-outDir [clientDirectory]", "specify the output directory of the client").option("--server-outDir [serverDirectory]", "specify the output directory of the server").action(async (rawOptions) => {
|
|
1465
|
+
const options = /* @__PURE__ */ new Map();
|
|
1466
|
+
options.set("directory", { value: rawOptions.directory });
|
|
1467
|
+
options.set("config", { value: rawOptions.config });
|
|
1468
|
+
options.set("clientDirectory", { value: rawOptions.clientOutDir });
|
|
1469
|
+
options.set("serverDirectory", { value: rawOptions.serverOutDir });
|
|
1470
|
+
const args = /* @__PURE__ */ new Map();
|
|
1471
|
+
await this.action.handle(args, options);
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
};
|
|
1475
|
+
|
|
1476
|
+
// src/command/commands/generate.command.ts
|
|
1477
|
+
var GenerateCommand = class extends AbstractCommand {
|
|
1478
|
+
static {
|
|
1479
|
+
__name(this, "GenerateCommand");
|
|
1480
|
+
}
|
|
1481
|
+
load(program2) {
|
|
1482
|
+
program2.command("generate").description("generate nanoforge files from config").option("-d, --directory [directory]", "specify the directory of your project").option("-c, --config [config]", "path to the config file", "nanoforge.config.json").action(async (rawOptions) => {
|
|
1483
|
+
const options = /* @__PURE__ */ new Map();
|
|
1484
|
+
options.set("directory", { value: rawOptions.directory });
|
|
1485
|
+
options.set("config", { value: rawOptions.config });
|
|
1486
|
+
const args = /* @__PURE__ */ new Map();
|
|
1487
|
+
await this.action.handle(args, options);
|
|
1488
|
+
});
|
|
1489
|
+
}
|
|
1490
|
+
};
|
|
1491
|
+
|
|
1492
|
+
// src/command/commands/install.command.ts
|
|
1493
|
+
var InstallCommand = class extends AbstractCommand {
|
|
1494
|
+
static {
|
|
1495
|
+
__name(this, "InstallCommand");
|
|
1496
|
+
}
|
|
1497
|
+
load(program2) {
|
|
1498
|
+
program2.command("install [names...]").alias("add").description("add NanoForge library to your project").option("-d, --directory [directory]", "specify the directory of your project").action(async (names, rawOptions) => {
|
|
1499
|
+
const options = /* @__PURE__ */ new Map();
|
|
1500
|
+
options.set("directory", { value: rawOptions.directory });
|
|
1501
|
+
const args = /* @__PURE__ */ new Map();
|
|
1502
|
+
args.set("names", { value: names.length ? names : void 0 });
|
|
1503
|
+
await this.action.handle(args, options);
|
|
1504
|
+
});
|
|
1505
|
+
}
|
|
1506
|
+
};
|
|
1507
|
+
|
|
1508
|
+
// src/command/commands/new.command.ts
|
|
1509
|
+
var NewCommand = class extends AbstractCommand {
|
|
1510
|
+
static {
|
|
1511
|
+
__name(this, "NewCommand");
|
|
1512
|
+
}
|
|
1513
|
+
load(program2) {
|
|
1514
|
+
program2.command("new").description("create a new nanoforge project").option("-d, --directory [directory]", "specify the directory of your project").option("--name [name]", "specify the name of your project").option("--path [path]", "specify the path of your project").option("--package-manager [packageManager]", "specify the package manager of your project").option("--language [language]", "specify the language of your project").option("--strict", "use strict mode").option("--no-strict", "do not use strict mode").option("--server", "create a server").option("--no-server", "do not create a server").option("--init-functions", "initialize functions").option("--no-init-functions", "do not initialize functions").option("--skip-install", "skip installing dependencies").option("--no-skip-install", "do not skip installing dependencies").action(async (rawOptions) => {
|
|
1515
|
+
const options = /* @__PURE__ */ new Map();
|
|
1516
|
+
options.set("directory", { value: rawOptions.directory });
|
|
1517
|
+
options.set("name", { value: rawOptions.name });
|
|
1518
|
+
options.set("path", { value: rawOptions.path });
|
|
1519
|
+
options.set("packageManager", { value: rawOptions.packageManager });
|
|
1520
|
+
options.set("language", { value: rawOptions.language });
|
|
1521
|
+
options.set("strict", { value: rawOptions.strict });
|
|
1522
|
+
options.set("server", { value: rawOptions.server });
|
|
1523
|
+
options.set("initFunctions", { value: rawOptions.initFunctions });
|
|
1524
|
+
options.set("skipInstall", { value: rawOptions.skipInstall });
|
|
1525
|
+
const args = /* @__PURE__ */ new Map();
|
|
1526
|
+
await this.action.handle(args, options);
|
|
1527
|
+
});
|
|
1528
|
+
}
|
|
1529
|
+
};
|
|
1530
|
+
|
|
1531
|
+
// src/command/commands/start.command.ts
|
|
1532
|
+
var StartCommand = class extends AbstractCommand {
|
|
1533
|
+
static {
|
|
1534
|
+
__name(this, "StartCommand");
|
|
1535
|
+
}
|
|
1536
|
+
load(program2) {
|
|
1537
|
+
program2.command("start").description("start your game").option("-d, --directory [directory]", "specify the directory of your project").option("-c, --config [config]", "path to the config file", "nanoforge.config.json").option(
|
|
1538
|
+
"-p, --client-port [clientPort]",
|
|
1539
|
+
"specify the port of the loader (the website to load the game)"
|
|
1540
|
+
).option("--game-exposure-port [gameExposurePort]", "specify the port of the game exposure").option("--server-port [serverPort]", "specify the port of the server").action(async (rawOptions) => {
|
|
1541
|
+
const options = /* @__PURE__ */ new Map();
|
|
1542
|
+
options.set("directory", { value: rawOptions.directory });
|
|
1543
|
+
options.set("config", { value: rawOptions.config });
|
|
1544
|
+
options.set("clientPort", { value: rawOptions.clientPort });
|
|
1545
|
+
options.set("gameExposurePort", {
|
|
1546
|
+
value: rawOptions.gameExposurePort
|
|
1547
|
+
});
|
|
1548
|
+
options.set("serverPort", { value: rawOptions.serverPort });
|
|
1549
|
+
const args = /* @__PURE__ */ new Map();
|
|
1550
|
+
await this.action.handle(args, options);
|
|
1551
|
+
});
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
// src/command/command.loader.ts
|
|
1556
|
+
var CommandLoader = class {
|
|
1557
|
+
static {
|
|
1558
|
+
__name(this, "CommandLoader");
|
|
1559
|
+
}
|
|
1560
|
+
static async load(program2) {
|
|
1561
|
+
new BuildCommand(new BuildAction()).load(program2);
|
|
1562
|
+
new GenerateCommand(new GenerateAction()).load(program2);
|
|
1563
|
+
new InstallCommand(new InstallAction()).load(program2);
|
|
1564
|
+
new NewCommand(new NewAction()).load(program2);
|
|
1565
|
+
new StartCommand(new StartAction()).load(program2);
|
|
1566
|
+
this.handleInvalidCommand(program2);
|
|
1567
|
+
}
|
|
1568
|
+
static handleInvalidCommand(program2) {
|
|
1569
|
+
program2.on("command:*", () => {
|
|
1570
|
+
console.error(`
|
|
1571
|
+
${Prefixes.ERROR} Invalid command: ${red6`%s`}`, program2.args.join(" "));
|
|
1572
|
+
console.log(`See ${red6`--help`} for a list of available commands.
|
|
1573
|
+
`);
|
|
1574
|
+
process.exit(1);
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
};
|
|
1578
|
+
|
|
1579
|
+
// src/bin/nf.ts
|
|
1580
|
+
var bootstrap = /* @__PURE__ */ __name(async () => {
|
|
1581
|
+
program.version(
|
|
1582
|
+
(await Promise.resolve().then(() => __toESM(require_package(), 1))).version ?? "unknown",
|
|
1583
|
+
"-v, --version",
|
|
1584
|
+
"output the current version"
|
|
1585
|
+
).usage("<command> [options]").helpOption("-h, --help", "output usage information");
|
|
1586
|
+
if (localBinExists()) {
|
|
1587
|
+
const localCommandLoader = await loadLocalBinCommandLoader();
|
|
1588
|
+
await localCommandLoader.load(program);
|
|
1589
|
+
} else {
|
|
1590
|
+
await CommandLoader.load(program);
|
|
1591
|
+
}
|
|
1592
|
+
await program.parseAsync(process.argv);
|
|
1593
|
+
if (!process.argv.slice(2).length) {
|
|
1594
|
+
program.outputHelp();
|
|
1595
|
+
}
|
|
1596
|
+
}, "bootstrap");
|
|
1597
|
+
bootstrap().then();
|