nurjs-cli 0.1.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 +114 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +48 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/doctor.command.d.ts +2 -0
- package/dist/commands/doctor.command.d.ts.map +1 -0
- package/dist/commands/doctor.command.js +32 -0
- package/dist/commands/doctor.command.js.map +1 -0
- package/dist/commands/init.command.d.ts +6 -0
- package/dist/commands/init.command.d.ts.map +1 -0
- package/dist/commands/init.command.js +117 -0
- package/dist/commands/init.command.js.map +1 -0
- package/dist/commands/install.command.d.ts +8 -0
- package/dist/commands/install.command.d.ts.map +1 -0
- package/dist/commands/install.command.js +86 -0
- package/dist/commands/install.command.js.map +1 -0
- package/dist/commands/list.command.d.ts +2 -0
- package/dist/commands/list.command.d.ts.map +1 -0
- package/dist/commands/list.command.js +14 -0
- package/dist/commands/list.command.js.map +1 -0
- package/dist/commands/start.command.d.ts +6 -0
- package/dist/commands/start.command.d.ts.map +1 -0
- package/dist/commands/start.command.js +64 -0
- package/dist/commands/start.command.js.map +1 -0
- package/dist/config/loadNurConfig.d.ts +3 -0
- package/dist/config/loadNurConfig.d.ts.map +1 -0
- package/dist/config/loadNurConfig.js +38 -0
- package/dist/config/loadNurConfig.js.map +1 -0
- package/dist/config/projectDetector.d.ts +3 -0
- package/dist/config/projectDetector.d.ts.map +1 -0
- package/dist/config/projectDetector.js +11 -0
- package/dist/config/projectDetector.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/envFile.d.ts +2 -0
- package/dist/utils/envFile.d.ts.map +1 -0
- package/dist/utils/envFile.js +21 -0
- package/dist/utils/envFile.js.map +1 -0
- package/dist/utils/fileSystem.d.ts +11 -0
- package/dist/utils/fileSystem.d.ts.map +1 -0
- package/dist/utils/fileSystem.js +45 -0
- package/dist/utils/fileSystem.js.map +1 -0
- package/dist/utils/markers.d.ts +7 -0
- package/dist/utils/markers.d.ts.map +1 -0
- package/dist/utils/markers.js +22 -0
- package/dist/utils/markers.js.map +1 -0
- package/dist/utils/packageJson.d.ts +9 -0
- package/dist/utils/packageJson.d.ts.map +1 -0
- package/dist/utils/packageJson.js +21 -0
- package/dist/utils/packageJson.js.map +1 -0
- package/dist/utils/packageMetadata.d.ts +2 -0
- package/dist/utils/packageMetadata.d.ts.map +1 -0
- package/dist/utils/packageMetadata.js +8 -0
- package/dist/utils/packageMetadata.js.map +1 -0
- package/dist/utils/paths.d.ts +3 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +10 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/runCommand.d.ts +2 -0
- package/dist/utils/runCommand.d.ts.map +1 -0
- package/dist/utils/runCommand.js +19 -0
- package/dist/utils/runCommand.js.map +1 -0
- package/package.json +49 -0
- package/templates/app/.env.example.tpl +11 -0
- package/templates/app/.env.tpl +11 -0
- package/templates/app/.gitignore.tpl +5 -0
- package/templates/app/README.md.tpl +43 -0
- package/templates/app/nur.config.ts.tpl +29 -0
- package/templates/app/package.json.tpl +33 -0
- package/templates/app/pnpm-workspace.yaml.tpl +2 -0
- package/templates/app/src/app.ts.tpl +23 -0
- package/templates/app/src/config/app.config.ts.tpl +17 -0
- package/templates/app/src/config/env.ts.tpl +22 -0
- package/templates/app/src/main.ts.tpl +6 -0
- package/templates/app/src/middlewares/errorHandler.middleware.ts.tpl +23 -0
- package/templates/app/src/middlewares/notFound.middleware.ts.tpl +6 -0
- package/templates/app/src/middlewares/requestLogger.middleware.ts.tpl +17 -0
- package/templates/app/src/modules/health/health.controller.ts.tpl +12 -0
- package/templates/app/src/modules/health/health.module.ts.tpl +12 -0
- package/templates/app/src/modules/health/health.routes.ts.tpl +10 -0
- package/templates/app/src/modules/index.ts.tpl +12 -0
- package/templates/app/src/shared/errors/.gitkeep.tpl +0 -0
- package/templates/app/src/shared/logger/logger.ts.tpl +43 -0
- package/templates/app/src/shared/response/.gitkeep.tpl +0 -0
- package/templates/app/src/shared/validation/.gitkeep.tpl +0 -0
- package/templates/app/tsconfig.json.tpl +24 -0
- package/templates/modules/auth/files/src/modules/auth/auth.controller.ts.tpl +60 -0
- package/templates/modules/auth/files/src/modules/auth/auth.module.ts.tpl +22 -0
- package/templates/modules/auth/files/src/modules/auth/auth.repository.ts.tpl +22 -0
- package/templates/modules/auth/files/src/modules/auth/auth.routes.ts.tpl +21 -0
- package/templates/modules/auth/files/src/modules/auth/auth.schema.ts.tpl +19 -0
- package/templates/modules/auth/files/src/modules/auth/auth.service.ts.tpl +92 -0
- package/templates/modules/auth/files/src/modules/auth/auth.types.ts.tpl +14 -0
- package/templates/modules/auth/files/src/modules/auth/index.ts.tpl +1 -0
- package/templates/modules/auth/files/src/shared/security/jwt.ts.tpl +49 -0
- package/templates/modules/auth/files/src/shared/security/password.ts.tpl +11 -0
- package/templates/modules/auth/manifest.json +29 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
function matchString(content, key, fallback) {
|
|
4
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5
|
+
const match = content.match(new RegExp(`${escaped}\\s*:\\s*[\"']([^\"']+)[\"']`));
|
|
6
|
+
return match?.[1] ?? fallback;
|
|
7
|
+
}
|
|
8
|
+
function matchNumber(content, key, fallback) {
|
|
9
|
+
const escaped = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
10
|
+
const match = content.match(new RegExp(`${escaped}\\s*:\\s*(\\d+)`));
|
|
11
|
+
return match?.[1] ? Number(match[1]) : fallback;
|
|
12
|
+
}
|
|
13
|
+
export async function loadNurConfig(cwd = process.cwd()) {
|
|
14
|
+
const configPath = resolve(cwd, "nur.config.ts");
|
|
15
|
+
const content = await readFile(configPath, "utf8");
|
|
16
|
+
return {
|
|
17
|
+
projectName: matchString(content, "projectName", "nur-api"),
|
|
18
|
+
runtime: {
|
|
19
|
+
entry: matchString(content, "entry", "src/main.ts"),
|
|
20
|
+
distEntry: matchString(content, "distEntry", "dist/main.js"),
|
|
21
|
+
tsconfig: matchString(content, "tsconfig", "tsconfig.json"),
|
|
22
|
+
},
|
|
23
|
+
server: {
|
|
24
|
+
host: matchString(content, "host", "127.0.0.1"),
|
|
25
|
+
port: matchNumber(content, "port", 5000),
|
|
26
|
+
apiPrefix: matchString(content, "apiPrefix", "/api/v1"),
|
|
27
|
+
},
|
|
28
|
+
paths: {
|
|
29
|
+
srcDir: matchString(content, "srcDir", "src"),
|
|
30
|
+
modulesDir: matchString(content, "modulesDir", "src/modules"),
|
|
31
|
+
moduleRegistryFile: matchString(content, "moduleRegistryFile", "src/modules/index.ts"),
|
|
32
|
+
envFile: matchString(content, "envFile", ".env"),
|
|
33
|
+
envExampleFile: matchString(content, "envExampleFile", ".env.example"),
|
|
34
|
+
},
|
|
35
|
+
packageManager: matchString(content, "packageManager", "pnpm"),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=loadNurConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadNurConfig.js","sourceRoot":"","sources":["../../src/config/loadNurConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,SAAS,WAAW,CAAC,OAAe,EAAE,GAAW,EAAE,QAAgB;IACjE,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,8BAA8B,CAAC,CAAC,CAAC;IAClF,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC;AAChC,CAAC;AAED,SAAS,WAAW,CAAC,OAAe,EAAE,GAAW,EAAE,QAAgB;IACjE,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,iBAAiB,CAAC,CAAC,CAAC;IACrE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAEnD,OAAO;QACL,WAAW,EAAE,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC;QAC3D,OAAO,EAAE;YACP,KAAK,EAAE,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC;YACnD,SAAS,EAAE,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,cAAc,CAAC;YAC5D,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC;SAC5D;QACD,MAAM,EAAE;YACN,IAAI,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC;YAC/C,IAAI,EAAE,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC;YACxC,SAAS,EAAE,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,CAAC;SACxD;QACD,KAAK,EAAE;YACL,MAAM,EAAE,WAAW,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC;YAC7C,UAAU,EAAE,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,aAAa,CAAC;YAC7D,kBAAkB,EAAE,WAAW,CAAC,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,CAAC;YACtF,OAAO,EAAE,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC;YAChD,cAAc,EAAE,WAAW,CAAC,OAAO,EAAE,gBAAgB,EAAE,cAAc,CAAC;SACvE;QACD,cAAc,EAAE,WAAW,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAuC;KACrG,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectDetector.d.ts","sourceRoot":"","sources":["../../src/config/projectDetector.ts"],"names":[],"mappings":"AAGA,wBAAgB,YAAY,CAAC,GAAG,SAAgB,GAAG,OAAO,CAEzD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,SAAgB,GAAG,IAAI,CAI1D"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
export function isNurProject(cwd = process.cwd()) {
|
|
4
|
+
return existsSync(resolve(cwd, "nur.config.ts")) && existsSync(resolve(cwd, "package.json"));
|
|
5
|
+
}
|
|
6
|
+
export function assertNurProject(cwd = process.cwd()) {
|
|
7
|
+
if (!isNurProject(cwd)) {
|
|
8
|
+
throw new Error("This directory does not look like a NurJS project. Missing nur.config.ts or package.json.");
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=projectDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectDetector.js","sourceRoot":"","sources":["../../src/config/projectDetector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,UAAU,YAAY,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC9C,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAClD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,2FAA2F,CAAC,CAAC;IAC/G,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envFile.d.ts","sourceRoot":"","sources":["../../src/utils/envFile.ts"],"names":[],"mappings":"AAGA,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
export async function appendEnvEntries(path, entries) {
|
|
4
|
+
const current = existsSync(path) ? await readFile(path, "utf8") : "";
|
|
5
|
+
const lines = current.split(/\r?\n/);
|
|
6
|
+
const existingKeys = new Set(lines
|
|
7
|
+
.map((line) => line.trim())
|
|
8
|
+
.filter((line) => line && !line.startsWith("#"))
|
|
9
|
+
.map((line) => line.split("=")[0])
|
|
10
|
+
.filter(Boolean));
|
|
11
|
+
const missing = entries.filter((entry) => {
|
|
12
|
+
const key = entry.split("=")[0];
|
|
13
|
+
return key && !existingKeys.has(key);
|
|
14
|
+
});
|
|
15
|
+
if (missing.length === 0) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const prefix = current.endsWith("\n") || current.length === 0 ? "" : "\n";
|
|
19
|
+
await writeFile(path, `${current}${prefix}\n# NurJS module env\n${missing.join("\n")}\n`, "utf8");
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=envFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envFile.js","sourceRoot":"","sources":["../../src/utils/envFile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,OAAiB;IACpE,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,YAAY,GAAG,IAAI,GAAG,CAC1B,KAAK;SACF,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;SAC/C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SACjC,MAAM,CAAC,OAAO,CAAC,CACnB,CAAC;IAEF,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QACvC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,OAAO,GAAG,MAAM,yBAAyB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACpG,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type TemplateVariables = Record<string, string | number | boolean>;
|
|
2
|
+
export declare function interpolate(content: string, variables: TemplateVariables): string;
|
|
3
|
+
export declare function copyTemplateDirectory(options: {
|
|
4
|
+
from: string;
|
|
5
|
+
to: string;
|
|
6
|
+
variables: TemplateVariables;
|
|
7
|
+
dryRun?: boolean;
|
|
8
|
+
force?: boolean;
|
|
9
|
+
}): Promise<string[]>;
|
|
10
|
+
export declare function pathExists(path: string): boolean;
|
|
11
|
+
//# sourceMappingURL=fileSystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileSystem.d.ts","sourceRoot":"","sources":["../../src/utils/fileSystem.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAE1E,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,GAAG,MAAM,CAQjF;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAuCpB;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { basename, join } from "node:path";
|
|
4
|
+
export function interpolate(content, variables) {
|
|
5
|
+
let next = content;
|
|
6
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
7
|
+
next = next.replaceAll(`__${key}__`, String(value));
|
|
8
|
+
}
|
|
9
|
+
return next;
|
|
10
|
+
}
|
|
11
|
+
export async function copyTemplateDirectory(options) {
|
|
12
|
+
const created = [];
|
|
13
|
+
async function walk(sourceDir, targetDir) {
|
|
14
|
+
const entries = await readdir(sourceDir);
|
|
15
|
+
for (const entry of entries) {
|
|
16
|
+
const sourcePath = join(sourceDir, entry);
|
|
17
|
+
const sourceStat = await stat(sourcePath);
|
|
18
|
+
const cleanEntry = entry.endsWith(".tpl") ? entry.slice(0, -4) : entry;
|
|
19
|
+
const targetPath = join(targetDir, cleanEntry);
|
|
20
|
+
if (sourceStat.isDirectory()) {
|
|
21
|
+
if (!options.dryRun) {
|
|
22
|
+
await mkdir(targetPath, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
await walk(sourcePath, targetPath);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (existsSync(targetPath) && !options.force) {
|
|
28
|
+
throw new Error(`File already exists: ${targetPath}. Use --force to overwrite generated files.`);
|
|
29
|
+
}
|
|
30
|
+
const raw = await readFile(sourcePath, "utf8");
|
|
31
|
+
const rendered = interpolate(raw, options.variables);
|
|
32
|
+
if (!options.dryRun) {
|
|
33
|
+
await mkdir(targetDir, { recursive: true });
|
|
34
|
+
await writeFile(targetPath, rendered, "utf8");
|
|
35
|
+
}
|
|
36
|
+
created.push(targetPath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
await walk(options.from, options.to);
|
|
40
|
+
return created.map((file) => basename(file) === file ? file : file);
|
|
41
|
+
}
|
|
42
|
+
export function pathExists(path) {
|
|
43
|
+
return existsSync(path);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=fileSystem.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileSystem.js","sourceRoot":"","sources":["../../src/utils/fileSystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAI3C,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,SAA4B;IACvE,IAAI,IAAI,GAAG,OAAO,CAAC;IAEnB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAM3C;IACC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,UAAU,IAAI,CAAC,SAAiB,EAAE,SAAiB;QACtD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;QAEzC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC1C,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC;YAC1C,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YACvE,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YAE/C,IAAI,UAAU,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC7B,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;oBACpB,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/C,CAAC;gBACD,MAAM,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;gBACnC,SAAS;YACX,CAAC;YAED,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC7C,MAAM,IAAI,KAAK,CAAC,wBAAwB,UAAU,6CAA6C,CAAC,CAAC;YACnG,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC/C,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;YAErD,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBACpB,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC5C,MAAM,SAAS,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;YAChD,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IAErC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function insertBetweenMarkers(content: string, startMarker: string, endMarker: string, lineToInsert: string): string;
|
|
2
|
+
export declare function updateModuleRegistry(options: {
|
|
3
|
+
filePath: string;
|
|
4
|
+
moduleImport: string;
|
|
5
|
+
moduleExportName: string;
|
|
6
|
+
}): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=markers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markers.d.ts","sourceRoot":"","sources":["../../src/utils/markers.ts"],"names":[],"mappings":"AAEA,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAiB1H;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
export function insertBetweenMarkers(content, startMarker, endMarker, lineToInsert) {
|
|
3
|
+
if (content.includes(lineToInsert)) {
|
|
4
|
+
return content;
|
|
5
|
+
}
|
|
6
|
+
const startIndex = content.indexOf(startMarker);
|
|
7
|
+
const endIndex = content.indexOf(endMarker);
|
|
8
|
+
if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
|
|
9
|
+
throw new Error(`Could not find marker zone: ${startMarker} ... ${endMarker}`);
|
|
10
|
+
}
|
|
11
|
+
const beforeEndMarker = content.slice(0, endIndex);
|
|
12
|
+
const afterEndMarker = content.slice(endIndex);
|
|
13
|
+
const linePrefix = beforeEndMarker.endsWith("\n") ? "" : "\n";
|
|
14
|
+
return `${beforeEndMarker}${linePrefix}${lineToInsert}\n${afterEndMarker}`;
|
|
15
|
+
}
|
|
16
|
+
export async function updateModuleRegistry(options) {
|
|
17
|
+
const current = await readFile(options.filePath, "utf8");
|
|
18
|
+
const withImport = insertBetweenMarkers(current, "// nur:imports:start", "// nur:imports:end", options.moduleImport);
|
|
19
|
+
const withModule = insertBetweenMarkers(withImport, "// nur:modules:start", "// nur:modules:end", ` ${options.moduleExportName},`);
|
|
20
|
+
await writeFile(options.filePath, withModule, "utf8");
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=markers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markers.js","sourceRoot":"","sources":["../../src/utils/markers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,WAAmB,EAAE,SAAiB,EAAE,YAAoB;IAChH,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACnC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAE5C,IAAI,UAAU,KAAK,CAAC,CAAC,IAAI,QAAQ,KAAK,CAAC,CAAC,IAAI,QAAQ,GAAG,UAAU,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,+BAA+B,WAAW,QAAQ,SAAS,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAE9D,OAAO,GAAG,eAAe,GAAG,UAAU,GAAG,YAAY,KAAK,cAAc,EAAE,CAAC;AAC7E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAI1C;IACC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEzD,MAAM,UAAU,GAAG,oBAAoB,CACrC,OAAO,EACP,sBAAsB,EACtB,oBAAoB,EACpB,OAAO,CAAC,YAAY,CACrB,CAAC;IAEF,MAAM,UAAU,GAAG,oBAAoB,CACrC,UAAU,EACV,sBAAsB,EACtB,oBAAoB,EACpB,KAAK,OAAO,CAAC,gBAAgB,GAAG,CACjC,CAAC;IAEF,MAAM,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type PackageJson = {
|
|
2
|
+
dependencies?: Record<string, string>;
|
|
3
|
+
devDependencies?: Record<string, string>;
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
};
|
|
6
|
+
export declare function readPackageJson(path: string): Promise<PackageJson>;
|
|
7
|
+
export declare function writePackageJson(path: string, pkg: PackageJson): Promise<void>;
|
|
8
|
+
export declare function mergeDependencies(pkg: PackageJson, dependencies?: Record<string, string>, devDependencies?: Record<string, string>): PackageJson;
|
|
9
|
+
//# sourceMappingURL=packageJson.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageJson.d.ts","sourceRoot":"","sources":["../../src/utils/packageJson.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAExE;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAEpF;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,WAAW,EAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACvC,WAAW,CAYb"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
export async function readPackageJson(path) {
|
|
3
|
+
return JSON.parse(await readFile(path, "utf8"));
|
|
4
|
+
}
|
|
5
|
+
export async function writePackageJson(path, pkg) {
|
|
6
|
+
await writeFile(path, `${JSON.stringify(pkg, null, 2)}\n`, "utf8");
|
|
7
|
+
}
|
|
8
|
+
export function mergeDependencies(pkg, dependencies, devDependencies) {
|
|
9
|
+
return {
|
|
10
|
+
...pkg,
|
|
11
|
+
dependencies: {
|
|
12
|
+
...(pkg.dependencies ?? {}),
|
|
13
|
+
...(dependencies ?? {}),
|
|
14
|
+
},
|
|
15
|
+
devDependencies: {
|
|
16
|
+
...(pkg.devDependencies ?? {}),
|
|
17
|
+
...(devDependencies ?? {}),
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=packageJson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageJson.js","sourceRoot":"","sources":["../../src/utils/packageJson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAQvD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY;IAChD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAgB,CAAC;AACjE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,GAAgB;IACnE,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,GAAgB,EAChB,YAAqC,EACrC,eAAwC;IAExC,OAAO;QACL,GAAG,GAAG;QACN,YAAY,EAAE;YACZ,GAAG,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;YAC3B,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;SACxB;QACD,eAAe,EAAE;YACf,GAAG,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;YAC9B,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;SAC3B;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageMetadata.d.ts","sourceRoot":"","sources":["../../src/utils/packageMetadata.ts"],"names":[],"mappings":"AAOA,wBAAgB,oBAAoB,IAAI,MAAM,CAK7C"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
export function getCliPackageVersion() {
|
|
4
|
+
const packageJsonPath = fileURLToPath(new URL("../../package.json", import.meta.url));
|
|
5
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
6
|
+
return packageJson.version;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=packageMetadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageMetadata.js","sourceRoot":"","sources":["../../src/utils/packageMetadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAMzC,MAAM,UAAU,oBAAoB;IAClC,MAAM,eAAe,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACtF,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAmB,CAAC;IAExF,OAAO,WAAW,CAAC,OAAO,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAGA,wBAAgB,cAAc,IAAI,MAAM,CAGvC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { dirname, resolve } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
export function getPackageRoot() {
|
|
4
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
5
|
+
return resolve(dirname(currentFile), "../..");
|
|
6
|
+
}
|
|
7
|
+
export function getTemplatesDir() {
|
|
8
|
+
return resolve(getPackageRoot(), "templates");
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,cAAc;IAC5B,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;IACnD,OAAO,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,OAAO,CAAC,cAAc,EAAE,EAAE,WAAW,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runCommand.d.ts","sourceRoot":"","sources":["../../src/utils/runCommand.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBtF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
export function runCommand(command, args, cwd) {
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
const child = spawn(command, args, {
|
|
5
|
+
cwd,
|
|
6
|
+
stdio: "inherit",
|
|
7
|
+
shell: process.platform === "win32",
|
|
8
|
+
});
|
|
9
|
+
child.on("error", reject);
|
|
10
|
+
child.on("close", (code) => {
|
|
11
|
+
if (code === 0) {
|
|
12
|
+
resolve();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
reject(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=runCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runCommand.js","sourceRoot":"","sources":["../../src/utils/runCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,IAAc,EAAE,GAAW;IACrE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACjC,GAAG;YACH,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;SACpC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAE1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YAED,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nurjs-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for NurJS backend projects.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"nur": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"templates",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc -p tsconfig.json",
|
|
18
|
+
"check": "tsc --noEmit -p tsconfig.json",
|
|
19
|
+
"dev": "tsx src/cli.ts",
|
|
20
|
+
"prepack": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@inquirer/prompts": "^8.7.2",
|
|
24
|
+
"commander": "^15.0.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^24.13.4",
|
|
28
|
+
"nurjs-core": "workspace:*",
|
|
29
|
+
"tsx": "^4.23.13",
|
|
30
|
+
"typescript": "^7.0.2"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"author": "WebDigiTech",
|
|
34
|
+
"keywords": [
|
|
35
|
+
"nurjs",
|
|
36
|
+
"cli",
|
|
37
|
+
"express",
|
|
38
|
+
"typescript",
|
|
39
|
+
"backend",
|
|
40
|
+
"scaffold",
|
|
41
|
+
"generator"
|
|
42
|
+
],
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=24.0.0"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# __PROJECT_NAME__
|
|
2
|
+
|
|
3
|
+
Generated with NurJS.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
Node.js 24 LTS or newer.
|
|
8
|
+
|
|
9
|
+
## Development
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
__PACKAGE_MANAGER__ install
|
|
13
|
+
nur start
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Default health endpoint:
|
|
17
|
+
|
|
18
|
+
```txt
|
|
19
|
+
GET __API_PREFIX__/health
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Project checks
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
__PACKAGE_MANAGER__ run check
|
|
26
|
+
__PACKAGE_MANAGER__ run build
|
|
27
|
+
nur doctor
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Add the auth starter module
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
nur install auth
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The v0.1.0 auth repository is in-memory. Before production use, replace it with persistent storage and set a strong `JWT_SECRET`.
|
|
37
|
+
|
|
38
|
+
## Production build
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
__PACKAGE_MANAGER__ run build
|
|
42
|
+
__PACKAGE_MANAGER__ run start:prod
|
|
43
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { NurProjectConfig } from "nurjs-core";
|
|
2
|
+
|
|
3
|
+
const config: NurProjectConfig = {
|
|
4
|
+
projectName: "__PROJECT_NAME__",
|
|
5
|
+
|
|
6
|
+
runtime: {
|
|
7
|
+
entry: "src/main.ts",
|
|
8
|
+
distEntry: "dist/main.js",
|
|
9
|
+
tsconfig: "tsconfig.json",
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
server: {
|
|
13
|
+
host: "__APP_HOST__",
|
|
14
|
+
port: __APP_PORT__,
|
|
15
|
+
apiPrefix: "__API_PREFIX__",
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
paths: {
|
|
19
|
+
srcDir: "src",
|
|
20
|
+
modulesDir: "src/modules",
|
|
21
|
+
moduleRegistryFile: "src/modules/index.ts",
|
|
22
|
+
envFile: ".env",
|
|
23
|
+
envExampleFile: ".env.example",
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
packageManager: "__PACKAGE_MANAGER__",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default config;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__PROJECT_NAME__",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "__DESCRIPTION__",
|
|
5
|
+
"private": true,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "tsx watch src/main.ts",
|
|
9
|
+
"start": "tsx watch src/main.ts",
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"start:prod": "node dist/main.js",
|
|
12
|
+
"check": "tsc --noEmit"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"nurjs-core": "__NUR_CORE_DEP__",
|
|
16
|
+
"cors": "^2.8.6",
|
|
17
|
+
"dotenv": "^17.4.2",
|
|
18
|
+
"express": "^5.2.1",
|
|
19
|
+
"helmet": "^8.3.0",
|
|
20
|
+
"pino": "^10.3.1",
|
|
21
|
+
"zod": "^4.6.5"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/cors": "^2.8.19",
|
|
25
|
+
"@types/express": "^5.0.6",
|
|
26
|
+
"@types/node": "^24.13.4",
|
|
27
|
+
"tsx": "^4.23.13",
|
|
28
|
+
"typescript": "^7.0.2"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=24.0.0"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createNurApp, registerNurModules, startNurServer } from "nurjs-core";
|
|
2
|
+
import { appConfig } from "./config/app.config.js";
|
|
3
|
+
import { modules } from "./modules/index.js";
|
|
4
|
+
import { logger } from "./shared/logger/logger.js";
|
|
5
|
+
import { requestLoggerMiddleware } from "./middlewares/requestLogger.middleware.js";
|
|
6
|
+
import { notFoundMiddleware } from "./middlewares/notFound.middleware.js";
|
|
7
|
+
import { errorHandlerMiddleware } from "./middlewares/errorHandler.middleware.js";
|
|
8
|
+
|
|
9
|
+
export async function bootstrap(): Promise<void> {
|
|
10
|
+
const ctx = createNurApp({
|
|
11
|
+
config: appConfig,
|
|
12
|
+
logger,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
ctx.app.use(requestLoggerMiddleware);
|
|
16
|
+
|
|
17
|
+
await registerNurModules(ctx, modules);
|
|
18
|
+
|
|
19
|
+
ctx.app.use(notFoundMiddleware);
|
|
20
|
+
ctx.app.use(errorHandlerMiddleware);
|
|
21
|
+
|
|
22
|
+
await startNurServer(ctx);
|
|
23
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { NurAppConfig } from "nurjs-core";
|
|
2
|
+
import { env } from "./env.js";
|
|
3
|
+
|
|
4
|
+
export const appConfig: NurAppConfig = {
|
|
5
|
+
appName: env.APP_NAME,
|
|
6
|
+
nodeEnv: env.NODE_ENV,
|
|
7
|
+
host: env.APP_HOST,
|
|
8
|
+
port: env.APP_PORT,
|
|
9
|
+
apiPrefix: env.API_PREFIX,
|
|
10
|
+
cors: {
|
|
11
|
+
enabled: env.CORS_ENABLED,
|
|
12
|
+
origin: env.CORS_ORIGIN,
|
|
13
|
+
},
|
|
14
|
+
logger: {
|
|
15
|
+
level: env.LOG_LEVEL,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { config as loadEnv } from "dotenv";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
loadEnv({ quiet: true });
|
|
5
|
+
|
|
6
|
+
const envSchema = z.object({
|
|
7
|
+
NODE_ENV: z.enum(["development", "test", "production"]).default("development"),
|
|
8
|
+
APP_NAME: z.string().default("nur-api"),
|
|
9
|
+
APP_HOST: z.string().default("127.0.0.1"),
|
|
10
|
+
APP_PORT: z.coerce.number().int().positive().default(5000),
|
|
11
|
+
API_PREFIX: z.string().default("/api/v1"),
|
|
12
|
+
CORS_ENABLED: z
|
|
13
|
+
.enum(["true", "false"])
|
|
14
|
+
.default("true")
|
|
15
|
+
.transform((value) => value === "true"),
|
|
16
|
+
CORS_ORIGIN: z.string().default("http://localhost:3000"),
|
|
17
|
+
LOG_LEVEL: z
|
|
18
|
+
.enum(["trace", "debug", "info", "warn", "error", "fatal"])
|
|
19
|
+
.default("info"),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const env = envSchema.parse(process.env);
|