fastnode-cli 0.6.0 → 0.6.2
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/index.js +284 -99
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7,160 +7,265 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
const child_process_1 = require("child_process");
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const [, , command, resource, name] = process.argv;
|
|
10
|
+
const [, , command, resource, name, moduleName] = process.argv;
|
|
11
11
|
if (command === "create" && resource) {
|
|
12
12
|
createProject(resource);
|
|
13
13
|
}
|
|
14
14
|
else if (command === "serve" && resource) {
|
|
15
15
|
serveProject(resource);
|
|
16
16
|
}
|
|
17
|
+
else if (command === "build") {
|
|
18
|
+
buildProject();
|
|
19
|
+
}
|
|
17
20
|
else if (command === "generate" && resource === "controller" && name) {
|
|
18
|
-
generateController(name);
|
|
21
|
+
generateController(name, moduleName);
|
|
19
22
|
}
|
|
20
23
|
else {
|
|
21
24
|
printUsage();
|
|
22
25
|
}
|
|
23
26
|
function createProject(projectName) {
|
|
24
27
|
const projectDir = path_1.default.resolve(projectName);
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
const srcDir = path_1.default.join(projectDir, "src");
|
|
29
|
+
const constantsDir = path_1.default.join(srcDir, "constants");
|
|
30
|
+
const controllersDir = path_1.default.join(srcDir, "controllers");
|
|
31
|
+
const servicesDir = path_1.default.join(srcDir, "services");
|
|
32
|
+
const helpersDir = path_1.default.join(srcDir, "helpers");
|
|
33
|
+
fs_1.default.mkdirSync(constantsDir, { recursive: true });
|
|
34
|
+
fs_1.default.mkdirSync(controllersDir, { recursive: true });
|
|
35
|
+
fs_1.default.mkdirSync(servicesDir, { recursive: true });
|
|
36
|
+
fs_1.default.mkdirSync(helpersDir, { recursive: true });
|
|
37
|
+
fs_1.default.writeFileSync(path_1.default.join(srcDir, "main.ts"), buildMainTemplate());
|
|
38
|
+
fs_1.default.writeFileSync(path_1.default.join(srcDir, "app.module.ts"), buildAppModuleTemplate(projectName));
|
|
39
|
+
fs_1.default.writeFileSync(path_1.default.join(controllersDir, "app.controller.ts"), buildAppControllerTemplate(projectName));
|
|
40
|
+
fs_1.default.writeFileSync(path_1.default.join(constantsDir, "config.ts"), buildConfigTemplate());
|
|
28
41
|
fs_1.default.writeFileSync(path_1.default.join(projectDir, "tsconfig.json"), `{
|
|
29
42
|
"compilerOptions": {
|
|
30
|
-
"target": "
|
|
31
|
-
"module": "
|
|
32
|
-
"
|
|
33
|
-
"
|
|
43
|
+
"target": "ES2022",
|
|
44
|
+
"module": "es2022",
|
|
45
|
+
"moduleResolution": "bundler",
|
|
46
|
+
"rootDir": "src",
|
|
47
|
+
"outDir": "dist",
|
|
34
48
|
"strict": true,
|
|
35
49
|
"esModuleInterop": true,
|
|
36
50
|
"experimentalDecorators": true,
|
|
37
51
|
"emitDecoratorMetadata": true,
|
|
38
|
-
"
|
|
52
|
+
"skipLibCheck": true,
|
|
53
|
+
"resolveJsonModule": true,
|
|
54
|
+
"types": ["node"]
|
|
39
55
|
},
|
|
40
|
-
"include": ["src"]
|
|
56
|
+
"include": ["src/**/*.ts"],
|
|
57
|
+
"exclude": ["dist", "node_modules"]
|
|
41
58
|
}
|
|
42
59
|
`);
|
|
43
60
|
fs_1.default.writeFileSync(path_1.default.join(projectDir, "package.json"), `{
|
|
44
61
|
"name": "${projectName}",
|
|
45
62
|
"version": "1.0.0",
|
|
46
|
-
"type": "
|
|
47
|
-
"main": "dist/index.js",
|
|
63
|
+
"type": "module",
|
|
48
64
|
"scripts": {
|
|
49
|
-
"dev": "tsx src
|
|
50
|
-
"build": "tsc",
|
|
51
|
-
"start": "node dist
|
|
65
|
+
"dev": "tsx watch src/main.ts",
|
|
66
|
+
"build": "tsc -p tsconfig.json",
|
|
67
|
+
"start": "node dist/main.js"
|
|
52
68
|
},
|
|
53
69
|
"dependencies": {
|
|
54
|
-
"fastnode-core": "
|
|
55
|
-
"reflect-metadata": "^0.
|
|
70
|
+
"fastnode-core": "^0.6.1",
|
|
71
|
+
"reflect-metadata": "^0.2.2"
|
|
56
72
|
},
|
|
57
73
|
"devDependencies": {
|
|
58
|
-
"
|
|
59
|
-
"
|
|
74
|
+
"@types/node": "^24.12.0",
|
|
75
|
+
"tsx": "^4.21.0",
|
|
76
|
+
"typescript": "^5.9.3"
|
|
60
77
|
}
|
|
61
78
|
}
|
|
62
79
|
`);
|
|
63
|
-
console.log(
|
|
80
|
+
console.log(`Project '${projectName}' created at ${projectDir}`);
|
|
64
81
|
}
|
|
65
82
|
function serveProject(projectName) {
|
|
66
|
-
const entry = path_1.default.resolve(process.cwd(),
|
|
83
|
+
const entry = path_1.default.resolve(process.cwd(), "src", "main.ts");
|
|
67
84
|
if (!fs_1.default.existsSync(entry)) {
|
|
68
|
-
|
|
69
|
-
process.exit(1);
|
|
85
|
+
fail(`Cannot find module at ${entry}`);
|
|
70
86
|
}
|
|
71
87
|
(0, child_process_1.execSync)(`npx tsx ${entry}`, { stdio: "inherit" });
|
|
72
88
|
}
|
|
73
|
-
function
|
|
89
|
+
function buildProject() {
|
|
90
|
+
const errors = validateProjectConfiguration();
|
|
91
|
+
if (errors.length > 0) {
|
|
92
|
+
printValidationErrors(errors);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
clearBuildOutput();
|
|
97
|
+
(0, child_process_1.execSync)("npx tsc -p tsconfig.json", { stdio: "inherit" });
|
|
98
|
+
console.log("Build completed successfully.");
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error("Build failed.");
|
|
102
|
+
if (error instanceof Error && error.message) {
|
|
103
|
+
console.error(error.message);
|
|
104
|
+
}
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function clearBuildOutput() {
|
|
109
|
+
const distDir = path_1.default.resolve(process.cwd(), "dist");
|
|
110
|
+
if (!fs_1.default.existsSync(distDir)) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
fs_1.default.rmSync(distDir, { recursive: true, force: true });
|
|
114
|
+
}
|
|
115
|
+
function generateController(controllerName, moduleName) {
|
|
74
116
|
const normalizedName = toKebabCase(controllerName);
|
|
75
117
|
const className = `${toPascalCase(controllerName)}Controller`;
|
|
76
|
-
const
|
|
118
|
+
const moduleFile = resolveModuleFile(moduleName);
|
|
119
|
+
const controllerDir = path_1.default.resolve(process.cwd(), "src", "controllers");
|
|
77
120
|
const controllerFile = path_1.default.join(controllerDir, `${normalizedName}.controller.ts`);
|
|
78
121
|
fs_1.default.mkdirSync(controllerDir, { recursive: true });
|
|
79
122
|
if (fs_1.default.existsSync(controllerFile)) {
|
|
80
|
-
|
|
81
|
-
process.exit(1);
|
|
123
|
+
fail(`Controller already exists at ${controllerFile}`);
|
|
82
124
|
}
|
|
83
125
|
fs_1.default.writeFileSync(controllerFile, buildControllerTemplate(normalizedName));
|
|
84
|
-
|
|
85
|
-
console.log(
|
|
126
|
+
updateModuleControllers(moduleFile, className, normalizedName);
|
|
127
|
+
console.log(`Controller '${normalizedName}' created at ${controllerFile}`);
|
|
128
|
+
console.log(`Added ${className} to ${path_1.default.basename(moduleFile)}.`);
|
|
86
129
|
}
|
|
87
|
-
function
|
|
88
|
-
const
|
|
89
|
-
const
|
|
130
|
+
function validateProjectConfiguration() {
|
|
131
|
+
const errors = [];
|
|
132
|
+
const packageJsonPath = path_1.default.resolve(process.cwd(), "package.json");
|
|
133
|
+
const tsconfigPath = path_1.default.resolve(process.cwd(), "tsconfig.json");
|
|
134
|
+
const mainFilePath = path_1.default.resolve(process.cwd(), "src", "main.ts");
|
|
135
|
+
const packageJson = readJsonFile(packageJsonPath, "package.json", errors);
|
|
136
|
+
const tsconfig = readJsonFile(tsconfigPath, "tsconfig.json", errors);
|
|
137
|
+
if (!fs_1.default.existsSync(mainFilePath)) {
|
|
138
|
+
errors.push(`Missing entry file: ${mainFilePath}`);
|
|
139
|
+
}
|
|
140
|
+
validatePackageJson(packageJson, errors);
|
|
141
|
+
validateTsconfig(tsconfig, errors);
|
|
142
|
+
return errors;
|
|
143
|
+
}
|
|
144
|
+
function validatePackageJson(packageJson, errors) {
|
|
145
|
+
if (!packageJson) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const scripts = asRecord(packageJson.scripts);
|
|
149
|
+
const dependencies = asRecord(packageJson.dependencies);
|
|
150
|
+
const devDependencies = asRecord(packageJson.devDependencies);
|
|
151
|
+
if (packageJson.type !== "module") {
|
|
152
|
+
errors.push(`package.json: expected "type" to be "module".`);
|
|
153
|
+
}
|
|
154
|
+
if (typeof scripts?.build !== "string" || !scripts.build.includes("tsc")) {
|
|
155
|
+
errors.push(`package.json: expected scripts.build to run TypeScript, for example "tsc -p tsconfig.json".`);
|
|
156
|
+
}
|
|
157
|
+
if (typeof dependencies?.["fastnode-core"] !== "string") {
|
|
158
|
+
errors.push(`package.json: missing dependency "fastnode-core".`);
|
|
159
|
+
}
|
|
160
|
+
else if (!hasLocalInstalledPackage("fastnode-core")) {
|
|
161
|
+
errors.push(`package.json: dependency "fastnode-core" is not installed. Run npm install.`);
|
|
162
|
+
}
|
|
163
|
+
if (typeof dependencies?.["reflect-metadata"] !== "string") {
|
|
164
|
+
errors.push(`package.json: missing dependency "reflect-metadata".`);
|
|
165
|
+
}
|
|
166
|
+
else if (!hasLocalInstalledPackage("reflect-metadata")) {
|
|
167
|
+
errors.push(`package.json: dependency "reflect-metadata" is not installed. Run npm install.`);
|
|
168
|
+
}
|
|
169
|
+
if (typeof devDependencies?.typescript !== "string") {
|
|
170
|
+
errors.push(`package.json: missing devDependency "typescript".`);
|
|
171
|
+
}
|
|
172
|
+
else if (!hasLocalInstalledPackage("typescript")) {
|
|
173
|
+
errors.push(`package.json: devDependency "typescript" is not installed. Run npm install.`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function validateTsconfig(tsconfig, errors) {
|
|
177
|
+
if (!tsconfig) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const compilerOptions = asRecord(tsconfig.compilerOptions);
|
|
181
|
+
if (!compilerOptions) {
|
|
182
|
+
errors.push(`tsconfig.json: missing compilerOptions.`);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (compilerOptions.rootDir !== "src") {
|
|
186
|
+
errors.push(`tsconfig.json: expected compilerOptions.rootDir to be "src".`);
|
|
187
|
+
}
|
|
188
|
+
if (compilerOptions.outDir !== "dist") {
|
|
189
|
+
errors.push(`tsconfig.json: expected compilerOptions.outDir to be "dist".`);
|
|
190
|
+
}
|
|
191
|
+
if (compilerOptions.moduleResolution !== "bundler") {
|
|
192
|
+
errors.push(`tsconfig.json: expected compilerOptions.moduleResolution to be "bundler".`);
|
|
193
|
+
}
|
|
194
|
+
if (compilerOptions.experimentalDecorators !== true) {
|
|
195
|
+
errors.push(`tsconfig.json: expected compilerOptions.experimentalDecorators to be true.`);
|
|
196
|
+
}
|
|
197
|
+
if (compilerOptions.emitDecoratorMetadata !== true) {
|
|
198
|
+
errors.push(`tsconfig.json: expected compilerOptions.emitDecoratorMetadata to be true.`);
|
|
199
|
+
}
|
|
200
|
+
if (compilerOptions.module !== "es2022" &&
|
|
201
|
+
compilerOptions.module !== "ES2022") {
|
|
202
|
+
errors.push(`tsconfig.json: expected compilerOptions.module to be "es2022".`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function readJsonFile(filePath, label, errors) {
|
|
206
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
207
|
+
errors.push(`Missing ${label} at ${filePath}`);
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
try {
|
|
211
|
+
const content = fs_1.default.readFileSync(filePath, "utf8");
|
|
212
|
+
return JSON.parse(content);
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
const message = error instanceof Error ? error.message : "Unknown JSON parsing error.";
|
|
216
|
+
errors.push(`Invalid ${label}: ${message}`);
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function printValidationErrors(errors) {
|
|
221
|
+
console.error("FastNode build validation failed.");
|
|
222
|
+
console.error("");
|
|
223
|
+
for (const error of errors) {
|
|
224
|
+
console.error(`- ${error}`);
|
|
225
|
+
}
|
|
226
|
+
console.error("");
|
|
227
|
+
console.error("Update your package.json and tsconfig.json, then run `fastnode build` again.");
|
|
228
|
+
}
|
|
229
|
+
function buildMainTemplate() {
|
|
90
230
|
return `import "reflect-metadata";
|
|
91
|
-
import {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
Controller,
|
|
95
|
-
EmitToClient,
|
|
96
|
-
ExecutionPolicy,
|
|
97
|
-
Get,
|
|
98
|
-
Module,
|
|
99
|
-
Param,
|
|
100
|
-
Post,
|
|
101
|
-
Query,
|
|
102
|
-
SocketController,
|
|
103
|
-
Subscribe,
|
|
104
|
-
createApp,
|
|
105
|
-
} from "fastnode-core";
|
|
106
|
-
|
|
107
|
-
@Controller("/${projectName}")
|
|
108
|
-
@ExecutionPolicy({ timeout: 5000 })
|
|
109
|
-
class ${className} {
|
|
110
|
-
@Get("/")
|
|
111
|
-
async hello(
|
|
112
|
-
@Query("name") name?: string,
|
|
113
|
-
@Context() ctx?: any
|
|
114
|
-
) {
|
|
115
|
-
await ctx?.sleep(25);
|
|
231
|
+
import { createApp } from "fastnode-core";
|
|
232
|
+
import { AppModule } from "./app.module.js";
|
|
233
|
+
import { API_CONFIG } from "./constants/config.js";
|
|
116
234
|
|
|
117
|
-
|
|
118
|
-
message: \`Hello from ${projectName}\${name ? \`, \${name}\` : ""}\`,
|
|
119
|
-
deadline: ctx?.snapshot?.().deadline,
|
|
120
|
-
};
|
|
121
|
-
}
|
|
235
|
+
export const app = createApp([AppModule], {
|
|
122
236
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
|
|
130
|
-
include,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
237
|
+
}).listen({ port: API_CONFIG.port, host: API_CONFIG.host });
|
|
238
|
+
`;
|
|
239
|
+
}
|
|
240
|
+
function buildAppModuleTemplate(projectName) {
|
|
241
|
+
const controllerName = `${toPascalCase(projectName)}Controller`;
|
|
242
|
+
return `import { Module } from "fastnode-core";
|
|
243
|
+
import { ${controllerName} } from "./controllers/app.controller.js";
|
|
133
244
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
created: true,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
245
|
+
@Module({ controllers: [${controllerName}] })
|
|
246
|
+
export class AppModule {}
|
|
247
|
+
`;
|
|
140
248
|
}
|
|
249
|
+
function buildAppControllerTemplate(projectName) {
|
|
250
|
+
const className = `${toPascalCase(projectName)}Controller`;
|
|
251
|
+
return `import { Controller, Get } from "fastnode-core";
|
|
141
252
|
|
|
142
|
-
@
|
|
143
|
-
class ${
|
|
144
|
-
@
|
|
145
|
-
|
|
146
|
-
ping(@Body("message") message?: string) {
|
|
253
|
+
@Controller("/")
|
|
254
|
+
export class ${className} {
|
|
255
|
+
@Get("/")
|
|
256
|
+
getHello() {
|
|
147
257
|
return {
|
|
148
|
-
message:
|
|
258
|
+
message: "Hello from ${projectName}",
|
|
149
259
|
};
|
|
150
260
|
}
|
|
151
261
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
executionPolicy: {
|
|
160
|
-
timeout: 30000,
|
|
161
|
-
mode: "inline",
|
|
162
|
-
},
|
|
163
|
-
}).listen(3000);
|
|
262
|
+
`;
|
|
263
|
+
}
|
|
264
|
+
function buildConfigTemplate() {
|
|
265
|
+
return `export const API_CONFIG = {
|
|
266
|
+
host: "0.0.0.0",
|
|
267
|
+
port: 3000,
|
|
268
|
+
};
|
|
164
269
|
`;
|
|
165
270
|
}
|
|
166
271
|
function buildControllerTemplate(controllerName) {
|
|
@@ -169,8 +274,8 @@ function buildControllerTemplate(controllerName) {
|
|
|
169
274
|
Body,
|
|
170
275
|
Controller,
|
|
171
276
|
Get,
|
|
172
|
-
Post,
|
|
173
277
|
Param,
|
|
278
|
+
Post,
|
|
174
279
|
Query,
|
|
175
280
|
} from "fastnode-core";
|
|
176
281
|
|
|
@@ -212,6 +317,85 @@ export class ${className} {
|
|
|
212
317
|
}
|
|
213
318
|
`;
|
|
214
319
|
}
|
|
320
|
+
function resolveModuleFile(moduleName) {
|
|
321
|
+
const srcDir = path_1.default.resolve(process.cwd(), "src");
|
|
322
|
+
if (!fs_1.default.existsSync(srcDir)) {
|
|
323
|
+
fail(`Cannot find src directory at ${srcDir}`);
|
|
324
|
+
}
|
|
325
|
+
if (!moduleName) {
|
|
326
|
+
const defaultModuleFile = path_1.default.join(srcDir, "app.module.ts");
|
|
327
|
+
if (!fs_1.default.existsSync(defaultModuleFile)) {
|
|
328
|
+
fail(`Cannot find default module at ${defaultModuleFile}`);
|
|
329
|
+
}
|
|
330
|
+
return defaultModuleFile;
|
|
331
|
+
}
|
|
332
|
+
const expectedFileName = `${toKebabCase(moduleName)}.module.ts`;
|
|
333
|
+
const moduleFile = findFileRecursive(srcDir, expectedFileName);
|
|
334
|
+
if (!moduleFile) {
|
|
335
|
+
fail(`Cannot find module '${moduleName}'. Expected ${expectedFileName} under ${srcDir}`);
|
|
336
|
+
}
|
|
337
|
+
return moduleFile;
|
|
338
|
+
}
|
|
339
|
+
function findFileRecursive(dir, fileName) {
|
|
340
|
+
const entries = fs_1.default.readdirSync(dir, { withFileTypes: true });
|
|
341
|
+
for (const entry of entries) {
|
|
342
|
+
const fullPath = path_1.default.join(dir, entry.name);
|
|
343
|
+
if (entry.isDirectory()) {
|
|
344
|
+
const match = findFileRecursive(fullPath, fileName);
|
|
345
|
+
if (match) {
|
|
346
|
+
return match;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
else if (entry.isFile() && entry.name === fileName) {
|
|
350
|
+
return fullPath;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return undefined;
|
|
354
|
+
}
|
|
355
|
+
function updateModuleControllers(moduleFile, controllerClassName, controllerName) {
|
|
356
|
+
const controllerFile = path_1.default.resolve(process.cwd(), "src", "controllers", `${controllerName}.controller.ts`);
|
|
357
|
+
const importStatement = `import { ${controllerClassName} } from "${buildRelativeImportPath(moduleFile, controllerFile)}";`;
|
|
358
|
+
let moduleSource = fs_1.default.readFileSync(moduleFile, "utf8");
|
|
359
|
+
if (!moduleSource.includes(importStatement)) {
|
|
360
|
+
moduleSource = `${importStatement}\n${moduleSource}`;
|
|
361
|
+
}
|
|
362
|
+
const controllersMatch = moduleSource.match(/controllers\s*:\s*\[([\s\S]*?)\]/);
|
|
363
|
+
if (!controllersMatch) {
|
|
364
|
+
fail(`Could not find a controllers array inside ${moduleFile}`);
|
|
365
|
+
}
|
|
366
|
+
const existingControllers = controllersMatch[1]
|
|
367
|
+
.split(",")
|
|
368
|
+
.map((value) => value.trim())
|
|
369
|
+
.filter(Boolean);
|
|
370
|
+
if (!existingControllers.includes(controllerClassName)) {
|
|
371
|
+
existingControllers.push(controllerClassName);
|
|
372
|
+
}
|
|
373
|
+
moduleSource = moduleSource.replace(/controllers\s*:\s*\[[\s\S]*?\]/, `controllers: [${existingControllers.join(", ")}]`);
|
|
374
|
+
fs_1.default.writeFileSync(moduleFile, moduleSource);
|
|
375
|
+
}
|
|
376
|
+
function buildRelativeImportPath(fromFile, toFile) {
|
|
377
|
+
const relativePath = path_1.default
|
|
378
|
+
.relative(path_1.default.dirname(fromFile), toFile)
|
|
379
|
+
.replace(/\\/g, "/")
|
|
380
|
+
.replace(/\.ts$/, ".js");
|
|
381
|
+
if (relativePath.startsWith(".")) {
|
|
382
|
+
return relativePath;
|
|
383
|
+
}
|
|
384
|
+
return `./${relativePath}`;
|
|
385
|
+
}
|
|
386
|
+
function asRecord(value) {
|
|
387
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
388
|
+
return undefined;
|
|
389
|
+
}
|
|
390
|
+
return value;
|
|
391
|
+
}
|
|
392
|
+
function hasLocalInstalledPackage(packageName) {
|
|
393
|
+
return fs_1.default.existsSync(path_1.default.resolve(process.cwd(), "node_modules", packageName));
|
|
394
|
+
}
|
|
395
|
+
function fail(message) {
|
|
396
|
+
console.error(message);
|
|
397
|
+
process.exit(1);
|
|
398
|
+
}
|
|
215
399
|
function capitalize(value) {
|
|
216
400
|
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
217
401
|
}
|
|
@@ -234,6 +418,7 @@ function printUsage() {
|
|
|
234
418
|
Usage:
|
|
235
419
|
fastnode create <project-name>
|
|
236
420
|
fastnode serve <project-name>
|
|
237
|
-
fastnode
|
|
421
|
+
fastnode build
|
|
422
|
+
fastnode generate controller <controller-name> [module-name]
|
|
238
423
|
`);
|
|
239
424
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastnode-cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "The official CLI for scaffolding and serving FastNode applications.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"fastnode": "dist/index.js"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"chalk": "^5.3.0",
|
|
27
27
|
"commander": "^11.0.0",
|
|
28
|
-
"fastnode-core": "^0.6.
|
|
28
|
+
"fastnode-core": "^0.6.1",
|
|
29
29
|
"reflect-metadata": "^0.1.13"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|