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.
Files changed (101) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +114 -0
  3. package/dist/cli.d.ts +4 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +48 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/doctor.command.d.ts +2 -0
  8. package/dist/commands/doctor.command.d.ts.map +1 -0
  9. package/dist/commands/doctor.command.js +32 -0
  10. package/dist/commands/doctor.command.js.map +1 -0
  11. package/dist/commands/init.command.d.ts +6 -0
  12. package/dist/commands/init.command.d.ts.map +1 -0
  13. package/dist/commands/init.command.js +117 -0
  14. package/dist/commands/init.command.js.map +1 -0
  15. package/dist/commands/install.command.d.ts +8 -0
  16. package/dist/commands/install.command.d.ts.map +1 -0
  17. package/dist/commands/install.command.js +86 -0
  18. package/dist/commands/install.command.js.map +1 -0
  19. package/dist/commands/list.command.d.ts +2 -0
  20. package/dist/commands/list.command.d.ts.map +1 -0
  21. package/dist/commands/list.command.js +14 -0
  22. package/dist/commands/list.command.js.map +1 -0
  23. package/dist/commands/start.command.d.ts +6 -0
  24. package/dist/commands/start.command.d.ts.map +1 -0
  25. package/dist/commands/start.command.js +64 -0
  26. package/dist/commands/start.command.js.map +1 -0
  27. package/dist/config/loadNurConfig.d.ts +3 -0
  28. package/dist/config/loadNurConfig.d.ts.map +1 -0
  29. package/dist/config/loadNurConfig.js +38 -0
  30. package/dist/config/loadNurConfig.js.map +1 -0
  31. package/dist/config/projectDetector.d.ts +3 -0
  32. package/dist/config/projectDetector.d.ts.map +1 -0
  33. package/dist/config/projectDetector.js +11 -0
  34. package/dist/config/projectDetector.js.map +1 -0
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +2 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/utils/envFile.d.ts +2 -0
  40. package/dist/utils/envFile.d.ts.map +1 -0
  41. package/dist/utils/envFile.js +21 -0
  42. package/dist/utils/envFile.js.map +1 -0
  43. package/dist/utils/fileSystem.d.ts +11 -0
  44. package/dist/utils/fileSystem.d.ts.map +1 -0
  45. package/dist/utils/fileSystem.js +45 -0
  46. package/dist/utils/fileSystem.js.map +1 -0
  47. package/dist/utils/markers.d.ts +7 -0
  48. package/dist/utils/markers.d.ts.map +1 -0
  49. package/dist/utils/markers.js +22 -0
  50. package/dist/utils/markers.js.map +1 -0
  51. package/dist/utils/packageJson.d.ts +9 -0
  52. package/dist/utils/packageJson.d.ts.map +1 -0
  53. package/dist/utils/packageJson.js +21 -0
  54. package/dist/utils/packageJson.js.map +1 -0
  55. package/dist/utils/packageMetadata.d.ts +2 -0
  56. package/dist/utils/packageMetadata.d.ts.map +1 -0
  57. package/dist/utils/packageMetadata.js +8 -0
  58. package/dist/utils/packageMetadata.js.map +1 -0
  59. package/dist/utils/paths.d.ts +3 -0
  60. package/dist/utils/paths.d.ts.map +1 -0
  61. package/dist/utils/paths.js +10 -0
  62. package/dist/utils/paths.js.map +1 -0
  63. package/dist/utils/runCommand.d.ts +2 -0
  64. package/dist/utils/runCommand.d.ts.map +1 -0
  65. package/dist/utils/runCommand.js +19 -0
  66. package/dist/utils/runCommand.js.map +1 -0
  67. package/package.json +49 -0
  68. package/templates/app/.env.example.tpl +11 -0
  69. package/templates/app/.env.tpl +11 -0
  70. package/templates/app/.gitignore.tpl +5 -0
  71. package/templates/app/README.md.tpl +43 -0
  72. package/templates/app/nur.config.ts.tpl +29 -0
  73. package/templates/app/package.json.tpl +33 -0
  74. package/templates/app/pnpm-workspace.yaml.tpl +2 -0
  75. package/templates/app/src/app.ts.tpl +23 -0
  76. package/templates/app/src/config/app.config.ts.tpl +17 -0
  77. package/templates/app/src/config/env.ts.tpl +22 -0
  78. package/templates/app/src/main.ts.tpl +6 -0
  79. package/templates/app/src/middlewares/errorHandler.middleware.ts.tpl +23 -0
  80. package/templates/app/src/middlewares/notFound.middleware.ts.tpl +6 -0
  81. package/templates/app/src/middlewares/requestLogger.middleware.ts.tpl +17 -0
  82. package/templates/app/src/modules/health/health.controller.ts.tpl +12 -0
  83. package/templates/app/src/modules/health/health.module.ts.tpl +12 -0
  84. package/templates/app/src/modules/health/health.routes.ts.tpl +10 -0
  85. package/templates/app/src/modules/index.ts.tpl +12 -0
  86. package/templates/app/src/shared/errors/.gitkeep.tpl +0 -0
  87. package/templates/app/src/shared/logger/logger.ts.tpl +43 -0
  88. package/templates/app/src/shared/response/.gitkeep.tpl +0 -0
  89. package/templates/app/src/shared/validation/.gitkeep.tpl +0 -0
  90. package/templates/app/tsconfig.json.tpl +24 -0
  91. package/templates/modules/auth/files/src/modules/auth/auth.controller.ts.tpl +60 -0
  92. package/templates/modules/auth/files/src/modules/auth/auth.module.ts.tpl +22 -0
  93. package/templates/modules/auth/files/src/modules/auth/auth.repository.ts.tpl +22 -0
  94. package/templates/modules/auth/files/src/modules/auth/auth.routes.ts.tpl +21 -0
  95. package/templates/modules/auth/files/src/modules/auth/auth.schema.ts.tpl +19 -0
  96. package/templates/modules/auth/files/src/modules/auth/auth.service.ts.tpl +92 -0
  97. package/templates/modules/auth/files/src/modules/auth/auth.types.ts.tpl +14 -0
  98. package/templates/modules/auth/files/src/modules/auth/index.ts.tpl +1 -0
  99. package/templates/modules/auth/files/src/shared/security/jwt.ts.tpl +49 -0
  100. package/templates/modules/auth/files/src/shared/security/password.ts.tpl +11 -0
  101. package/templates/modules/auth/manifest.json +29 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 WebDigiTech / Ventsislav Kolev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # nurjs-cli
2
+
3
+ Command-line interface for NurJS.
4
+
5
+ The package installs the `nur` executable used to create, run, inspect, and extend NurJS backend projects.
6
+
7
+ ## Requirements
8
+
9
+ Node.js 24 LTS or newer.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pnpm add -g nurjs-cli
15
+ ```
16
+
17
+ or:
18
+
19
+ ```bash
20
+ npm install -g nurjs-cli
21
+ ```
22
+
23
+ Verify the installation:
24
+
25
+ ```bash
26
+ nur --version
27
+ ```
28
+
29
+ ## Quick start
30
+
31
+ ```bash
32
+ nur init my-api
33
+ cd my-api
34
+ nur start
35
+ ```
36
+
37
+ The generated application includes a health endpoint at `/api/v1/health` by default.
38
+
39
+ ## Commands
40
+
41
+ ### `nur init [projectName]`
42
+
43
+ Creates a new Express + TypeScript NurJS project using an interactive setup.
44
+
45
+ ```bash
46
+ nur init my-api
47
+ nur init my-api --no-install
48
+ ```
49
+
50
+ The wizard supports pnpm, npm, and Yarn.
51
+
52
+ ### `nur start`
53
+
54
+ Runs the current project through its configured package manager and local `tsx` installation.
55
+
56
+ ```bash
57
+ nur start
58
+ nur start --no-watch
59
+ ```
60
+
61
+ ### `nur install <moduleName>`
62
+
63
+ Installs a module template, updates the module registry, updates environment examples and package dependencies, and installs the declared dependencies by default.
64
+
65
+ ```bash
66
+ nur install auth
67
+ nur install auth --dry-run
68
+ nur install auth --no-install
69
+ nur install auth --force
70
+ ```
71
+
72
+ In v0.1.0 the available installable template is:
73
+
74
+ ```txt
75
+ auth Authentication module skeleton
76
+ ```
77
+
78
+ The auth template is a starter implementation with an in-memory repository. Replace persistence and configure a strong `JWT_SECRET` before production use.
79
+
80
+ ### `nur list`
81
+
82
+ Lists module templates included in the installed CLI version.
83
+
84
+ ```bash
85
+ nur list
86
+ ```
87
+
88
+ ### `nur doctor`
89
+
90
+ Checks the expected NurJS project files, registry markers, environment files, and health module registration.
91
+
92
+ ```bash
93
+ nur doctor
94
+ ```
95
+
96
+ ## Generated project
97
+
98
+ A generated project uses `nurjs` as its core dependency and includes scripts for development, type checking, building, and production startup.
99
+
100
+ Default API prefix:
101
+
102
+ ```txt
103
+ /api/v1
104
+ ```
105
+
106
+ Default health endpoint:
107
+
108
+ ```txt
109
+ GET /api/v1/health
110
+ ```
111
+
112
+ ## License
113
+
114
+ MIT.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ export declare function createCliProgram(): Command;
4
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,gBAAgB,IAAI,OAAO,CAyC1C"}
package/dist/cli.js ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { initCommand } from "./commands/init.command.js";
4
+ import { startCommand } from "./commands/start.command.js";
5
+ import { installCommand } from "./commands/install.command.js";
6
+ import { listCommand } from "./commands/list.command.js";
7
+ import { doctorCommand } from "./commands/doctor.command.js";
8
+ import { getCliPackageVersion } from "./utils/packageMetadata.js";
9
+ export function createCliProgram() {
10
+ const program = new Command();
11
+ program
12
+ .name("nur")
13
+ .description("NurJS CLI - lightweight modular backend engine for Express + TypeScript")
14
+ .version(getCliPackageVersion());
15
+ program
16
+ .command("init")
17
+ .description("Create a new NurJS project")
18
+ .argument("[projectName]", "Project name")
19
+ .option("--no-install", "Do not install dependencies")
20
+ .action(initCommand);
21
+ program
22
+ .command("start")
23
+ .description("Start the current NurJS project in development mode")
24
+ .option("--no-watch", "Run without watch mode")
25
+ .action(startCommand);
26
+ program
27
+ .command("install")
28
+ .description("Install a NurJS module template")
29
+ .argument("<moduleName>", "Module name")
30
+ .option("--dry-run", "Show planned changes without writing files")
31
+ .option("--force", "Overwrite generated files when they already exist")
32
+ .option("--no-install", "Do not install module dependencies")
33
+ .action(installCommand);
34
+ program
35
+ .command("list")
36
+ .description("List available NurJS module templates")
37
+ .action(listCommand);
38
+ program
39
+ .command("doctor")
40
+ .description("Check whether the current project is a valid NurJS project")
41
+ .action(doctorCommand);
42
+ return program;
43
+ }
44
+ createCliProgram().parseAsync(process.argv).catch((error) => {
45
+ console.error(error instanceof Error ? error.message : error);
46
+ process.exit(1);
47
+ });
48
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAElE,MAAM,UAAU,gBAAgB;IAC9B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,KAAK,CAAC;SACX,WAAW,CAAC,yEAAyE,CAAC;SACtF,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IAEnC,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,4BAA4B,CAAC;SACzC,QAAQ,CAAC,eAAe,EAAE,cAAc,CAAC;SACzC,MAAM,CAAC,cAAc,EAAE,6BAA6B,CAAC;SACrD,MAAM,CAAC,WAAW,CAAC,CAAC;IAEvB,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,qDAAqD,CAAC;SAClE,MAAM,CAAC,YAAY,EAAE,wBAAwB,CAAC;SAC9C,MAAM,CAAC,YAAY,CAAC,CAAC;IAExB,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,iCAAiC,CAAC;SAC9C,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC;SACvC,MAAM,CAAC,WAAW,EAAE,4CAA4C,CAAC;SACjE,MAAM,CAAC,SAAS,EAAE,mDAAmD,CAAC;SACtE,MAAM,CAAC,cAAc,EAAE,oCAAoC,CAAC;SAC5D,MAAM,CAAC,cAAc,CAAC,CAAC;IAE1B,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,uCAAuC,CAAC;SACpD,MAAM,CAAC,WAAW,CAAC,CAAC;IAEvB,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,4DAA4D,CAAC;SACzE,MAAM,CAAC,aAAa,CAAC,CAAC;IAEzB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,gBAAgB,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IACnE,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function doctorCommand(): Promise<void>;
2
+ //# sourceMappingURL=doctor.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.command.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.command.ts"],"names":[],"mappings":"AAQA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA8BnD"}
@@ -0,0 +1,32 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ function check(label, passed) {
4
+ console.log(`${passed ? "✓" : "✗"} ${label}`);
5
+ return passed;
6
+ }
7
+ export async function doctorCommand() {
8
+ const cwd = process.cwd();
9
+ console.log("NurJS Doctor\n");
10
+ const checks = [];
11
+ checks.push(check("nur.config.ts found", existsSync(resolve(cwd, "nur.config.ts"))));
12
+ checks.push(check("package.json found", existsSync(resolve(cwd, "package.json"))));
13
+ checks.push(check("tsconfig.json found", existsSync(resolve(cwd, "tsconfig.json"))));
14
+ checks.push(check("src/main.ts found", existsSync(resolve(cwd, "src/main.ts"))));
15
+ checks.push(check("src/app.ts found", existsSync(resolve(cwd, "src/app.ts"))));
16
+ checks.push(check("src/modules/index.ts found", existsSync(resolve(cwd, "src/modules/index.ts"))));
17
+ checks.push(check(".env found", existsSync(resolve(cwd, ".env"))));
18
+ checks.push(check(".env.example found", existsSync(resolve(cwd, ".env.example"))));
19
+ const modulesIndexPath = resolve(cwd, "src/modules/index.ts");
20
+ if (existsSync(modulesIndexPath)) {
21
+ const content = readFileSync(modulesIndexPath, "utf8");
22
+ checks.push(check("module import marker found", content.includes("// nur:imports:start")));
23
+ checks.push(check("module registry marker found", content.includes("// nur:modules:start")));
24
+ checks.push(check("health module registered", content.includes("healthModule")));
25
+ }
26
+ const passed = checks.every(Boolean);
27
+ console.log(passed ? "\nProject looks healthy." : "\nProject has issues. Review the failed checks above.");
28
+ if (!passed) {
29
+ process.exitCode = 1;
30
+ }
31
+ }
32
+ //# sourceMappingURL=doctor.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.command.js","sourceRoot":"","sources":["../../src/commands/doctor.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,SAAS,KAAK,CAAC,KAAa,EAAE,MAAe;IAC3C,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;IAC9C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAE9B,MAAM,MAAM,GAAc,EAAE,CAAC;IAE7B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,qBAAqB,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IACrF,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,qBAAqB,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IACrF,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IACjF,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,4BAA4B,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;IACnG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,oBAAoB,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnF,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;IAC9D,IAAI,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,4BAA4B,EAAE,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC3F,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,8BAA8B,EAAE,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,EAAE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAErC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,uDAAuD,CAAC,CAAC;IAE3G,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ type InitOptions = {
2
+ install?: boolean;
3
+ };
4
+ export declare function initCommand(projectNameArg: string | undefined, options: InitOptions): Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=init.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.command.d.ts","sourceRoot":"","sources":["../../src/commands/init.command.ts"],"names":[],"mappings":"AAQA,KAAK,WAAW,GAAG;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAiCF,wBAAsB,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuGzG"}
@@ -0,0 +1,117 @@
1
+ import { confirm, input, select } from "@inquirer/prompts";
2
+ import { existsSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ import { copyTemplateDirectory } from "../utils/fileSystem.js";
5
+ import { getCliPackageVersion } from "../utils/packageMetadata.js";
6
+ import { runCommand } from "../utils/runCommand.js";
7
+ import { getPackageRoot, getTemplatesDir } from "../utils/paths.js";
8
+ function normalizeProjectName(value) {
9
+ return value
10
+ .trim()
11
+ .toLowerCase()
12
+ .replace(/\s+/g, "-")
13
+ .replace(/[^a-z0-9._-]/g, "-")
14
+ .replace(/-+/g, "-")
15
+ .replace(/^[._-]+|[._-]+$/g, "");
16
+ }
17
+ function validateProjectName(value) {
18
+ if (!value) {
19
+ return "Project name cannot be empty";
20
+ }
21
+ if (!/^[a-z0-9][a-z0-9._-]*$/.test(value)) {
22
+ return "Project name may contain only lowercase letters, numbers, dots, underscores and hyphens";
23
+ }
24
+ return true;
25
+ }
26
+ function validatePort(value) {
27
+ if (!/^\d+$/.test(value)) {
28
+ return "Port must be a number";
29
+ }
30
+ const port = Number(value);
31
+ return port >= 1 && port <= 65535 ? true : "Port must be between 1 and 65535";
32
+ }
33
+ export async function initCommand(projectNameArg, options) {
34
+ const requestedProjectName = projectNameArg ||
35
+ (await input({
36
+ message: "Project name:",
37
+ default: "nur-api",
38
+ }));
39
+ const projectName = normalizeProjectName(requestedProjectName);
40
+ const projectNameValidation = validateProjectName(projectName);
41
+ if (projectNameValidation !== true) {
42
+ throw new Error(projectNameValidation);
43
+ }
44
+ const description = await input({
45
+ message: "Description:",
46
+ default: "Modular backend API",
47
+ });
48
+ const packageManager = await select({
49
+ message: "Package manager:",
50
+ default: "pnpm",
51
+ choices: [
52
+ { name: "pnpm", value: "pnpm" },
53
+ { name: "npm", value: "npm" },
54
+ { name: "yarn", value: "yarn" },
55
+ ],
56
+ });
57
+ const port = await input({
58
+ message: "Server port:",
59
+ default: "5000",
60
+ validate: validatePort,
61
+ });
62
+ const host = await input({
63
+ message: "Server host:",
64
+ default: "127.0.0.1",
65
+ });
66
+ const apiPrefix = await input({
67
+ message: "API prefix:",
68
+ default: "/api/v1",
69
+ });
70
+ const corsOrigin = await input({
71
+ message: "CORS origin:",
72
+ default: "http://localhost:3000",
73
+ });
74
+ const shouldInstall = options.install === false
75
+ ? false
76
+ : await confirm({
77
+ message: "Install dependencies now?",
78
+ default: true,
79
+ });
80
+ const targetDir = resolve(process.cwd(), projectName);
81
+ if (existsSync(targetDir)) {
82
+ throw new Error(`Target directory already exists: ${targetDir}`);
83
+ }
84
+ const templatesDir = getTemplatesDir();
85
+ const appTemplateDir = resolve(templatesDir, "app");
86
+ const cliPackageRoot = getPackageRoot();
87
+ const workspaceRoot = resolve(cliPackageRoot, "../..");
88
+ const corePackageRoot = resolve(workspaceRoot, "packages/nur");
89
+ const isLocalMonorepo = existsSync(resolve(workspaceRoot, "pnpm-workspace.yaml")) &&
90
+ existsSync(resolve(corePackageRoot, "package.json"));
91
+ const nurCoreDependency = isLocalMonorepo
92
+ ? `file:${corePackageRoot}`
93
+ : `^${getCliPackageVersion()}`;
94
+ console.log("\nCreating NurJS project...\n");
95
+ await copyTemplateDirectory({
96
+ from: appTemplateDir,
97
+ to: targetDir,
98
+ variables: {
99
+ PROJECT_NAME: projectName,
100
+ DESCRIPTION: description,
101
+ PACKAGE_MANAGER: packageManager,
102
+ APP_PORT: port,
103
+ APP_HOST: host,
104
+ API_PREFIX: apiPrefix,
105
+ CORS_ORIGIN: corsOrigin,
106
+ NUR_CORE_DEP: nurCoreDependency,
107
+ },
108
+ });
109
+ if (shouldInstall) {
110
+ await runCommand(packageManager, ["install"], targetDir);
111
+ }
112
+ console.log(`\nNurJS project created: ${projectName}`);
113
+ console.log("\nNext steps:");
114
+ console.log(`cd ${projectName}`);
115
+ console.log("nur start");
116
+ }
117
+ //# sourceMappingURL=init.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.command.js","sourceRoot":"","sources":["../../src/commands/init.command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ type InstallOptions = {
2
+ dryRun?: boolean;
3
+ force?: boolean;
4
+ install?: boolean;
5
+ };
6
+ export declare function installCommand(moduleName: string, options: InstallOptions): Promise<void>;
7
+ export {};
8
+ //# sourceMappingURL=install.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.command.d.ts","sourceRoot":"","sources":["../../src/commands/install.command.ts"],"names":[],"mappings":"AAYA,KAAK,cAAc,GAAG;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAwBF,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA+E/F"}
@@ -0,0 +1,86 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readFile } from "node:fs/promises";
3
+ import { resolve } from "node:path";
4
+ import { assertNurProject } from "../config/projectDetector.js";
5
+ import { loadNurConfig } from "../config/loadNurConfig.js";
6
+ import { appendEnvEntries } from "../utils/envFile.js";
7
+ import { copyTemplateDirectory } from "../utils/fileSystem.js";
8
+ import { updateModuleRegistry } from "../utils/markers.js";
9
+ import { mergeDependencies, readPackageJson, writePackageJson } from "../utils/packageJson.js";
10
+ import { getTemplatesDir } from "../utils/paths.js";
11
+ import { runCommand } from "../utils/runCommand.js";
12
+ function printDependencyGroup(label, dependencies) {
13
+ if (!dependencies || Object.keys(dependencies).length === 0) {
14
+ return;
15
+ }
16
+ console.log(`\n${label}:`);
17
+ for (const [name, version] of Object.entries(dependencies)) {
18
+ console.log(`- ${name}@${version}`);
19
+ }
20
+ }
21
+ export async function installCommand(moduleName, options) {
22
+ const cwd = process.cwd();
23
+ assertNurProject(cwd);
24
+ const config = await loadNurConfig(cwd);
25
+ const templatesDir = getTemplatesDir();
26
+ const moduleTemplateDir = resolve(templatesDir, "modules", moduleName);
27
+ const manifestPath = resolve(moduleTemplateDir, "manifest.json");
28
+ if (!existsSync(manifestPath)) {
29
+ throw new Error(`Unknown NurJS module: ${moduleName}. Run "nur list" to see available modules.`);
30
+ }
31
+ const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
32
+ const filesDir = resolve(moduleTemplateDir, "files");
33
+ console.log(`${options.dryRun ? "Dry run:" : "Installing:"} ${manifest.name}`);
34
+ console.log(manifest.description);
35
+ for (const file of manifest.creates) {
36
+ const targetPath = resolve(cwd, file);
37
+ if (existsSync(targetPath) && !options.force) {
38
+ throw new Error(`File already exists: ${file}. Use --force to overwrite generated files.`);
39
+ }
40
+ }
41
+ if (options.dryRun) {
42
+ console.log("\nFiles to create:");
43
+ for (const file of manifest.creates) {
44
+ console.log(`- ${file}`);
45
+ }
46
+ printDependencyGroup("Dependencies", manifest.dependencies);
47
+ printDependencyGroup("Dev dependencies", manifest.devDependencies);
48
+ if (manifest.env?.length) {
49
+ console.log("\n.env.example entries:");
50
+ for (const entry of manifest.env) {
51
+ console.log(`- ${entry}`);
52
+ }
53
+ }
54
+ console.log("\nModule registry will be updated.");
55
+ console.log(options.install === false ? "Dependency install will be skipped." : "Dependencies will be installed.");
56
+ return;
57
+ }
58
+ await copyTemplateDirectory({
59
+ from: filesDir,
60
+ to: cwd,
61
+ variables: {
62
+ MODULE_NAME: manifest.name,
63
+ },
64
+ force: options.force ?? false,
65
+ });
66
+ await updateModuleRegistry({
67
+ filePath: resolve(cwd, config.paths.moduleRegistryFile),
68
+ moduleImport: manifest.moduleImport,
69
+ moduleExportName: manifest.moduleExportName,
70
+ });
71
+ if (manifest.env?.length) {
72
+ await appendEnvEntries(resolve(cwd, config.paths.envExampleFile), manifest.env);
73
+ }
74
+ const packageJsonPath = resolve(cwd, "package.json");
75
+ const pkg = await readPackageJson(packageJsonPath);
76
+ const merged = mergeDependencies(pkg, manifest.dependencies, manifest.devDependencies);
77
+ await writePackageJson(packageJsonPath, merged);
78
+ if (options.install !== false && (manifest.dependencies || manifest.devDependencies)) {
79
+ console.log("\nInstalling module dependencies...");
80
+ await runCommand(config.packageManager, ["install"], cwd);
81
+ }
82
+ console.log(`\nInstalled NurJS module: ${manifest.name}`);
83
+ console.log("Run:");
84
+ console.log("nur start");
85
+ }
86
+ //# sourceMappingURL=install.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.command.js","sourceRoot":"","sources":["../../src/commands/install.command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function listCommand(): Promise<void>;
2
+ //# sourceMappingURL=list.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.command.d.ts","sourceRoot":"","sources":["../../src/commands/list.command.ts"],"names":[],"mappings":"AASA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAWjD"}
@@ -0,0 +1,14 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { resolve } from "node:path";
3
+ import { getTemplatesDir } from "../utils/paths.js";
4
+ export async function listCommand() {
5
+ const modulesDir = resolve(getTemplatesDir(), "modules");
6
+ const moduleNames = await readdir(modulesDir);
7
+ console.log("Available NurJS modules:\n");
8
+ for (const moduleName of moduleNames) {
9
+ const manifestPath = resolve(modulesDir, moduleName, "manifest.json");
10
+ const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
11
+ console.log(`${manifest.name.padEnd(10)} ${manifest.description}`);
12
+ }
13
+ }
14
+ //# sourceMappingURL=list.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.command.js","sourceRoot":"","sources":["../../src/commands/list.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAOpD,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,UAAU,GAAG,OAAO,CAAC,eAAe,EAAE,EAAE,SAAS,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;IAE9C,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAE1C,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;QACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAmB,CAAC;QACpF,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IACrE,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ type StartOptions = {
2
+ watch?: boolean;
3
+ };
4
+ export declare function startCommand(options: StartOptions): Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=start.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.command.d.ts","sourceRoot":"","sources":["../../src/commands/start.command.ts"],"names":[],"mappings":"AAMA,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AA6BF,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA6CvE"}
@@ -0,0 +1,64 @@
1
+ import { existsSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { spawn } from "node:child_process";
4
+ import { assertNurProject } from "../config/projectDetector.js";
5
+ import { loadNurConfig } from "../config/loadNurConfig.js";
6
+ function createTsxCommand(packageManager, entry, watch) {
7
+ const tsxArgs = watch ? ["watch", entry] : [entry];
8
+ if (packageManager === "pnpm") {
9
+ return {
10
+ command: "pnpm",
11
+ args: ["exec", "tsx", ...tsxArgs],
12
+ };
13
+ }
14
+ if (packageManager === "npm") {
15
+ return {
16
+ command: "npm",
17
+ args: ["exec", "--", "tsx", ...tsxArgs],
18
+ };
19
+ }
20
+ return {
21
+ command: "yarn",
22
+ args: ["tsx", ...tsxArgs],
23
+ };
24
+ }
25
+ export async function startCommand(options) {
26
+ const cwd = process.cwd();
27
+ assertNurProject(cwd);
28
+ const config = await loadNurConfig(cwd);
29
+ const entryPath = resolve(cwd, config.runtime.entry);
30
+ if (!existsSync(entryPath)) {
31
+ throw new Error(`Entry file not found: ${config.runtime.entry}`);
32
+ }
33
+ console.log("NurJS starting...\n");
34
+ console.log(`Project: ${config.projectName}`);
35
+ console.log(`Entry: ${config.runtime.entry}`);
36
+ console.log(`Host: ${config.server.host}`);
37
+ console.log(`Port: ${config.server.port}`);
38
+ console.log(`API prefix: ${config.server.apiPrefix}`);
39
+ console.log(`Health: http://${config.server.host}:${config.server.port}${config.server.apiPrefix}/health\n`);
40
+ const runner = createTsxCommand(config.packageManager, config.runtime.entry, options.watch !== false);
41
+ const child = spawn(runner.command, runner.args, {
42
+ cwd,
43
+ stdio: "inherit",
44
+ shell: process.platform === "win32",
45
+ env: {
46
+ ...process.env,
47
+ NUR_PROJECT_NAME: config.projectName,
48
+ },
49
+ });
50
+ child.on("error", (error) => {
51
+ console.error(`Failed to start ${runner.command}: ${error.message}`);
52
+ process.exitCode = 1;
53
+ });
54
+ child.on("close", (code) => {
55
+ if (code !== null) {
56
+ process.exitCode = code;
57
+ return;
58
+ }
59
+ if (process.exitCode === undefined) {
60
+ process.exitCode = 1;
61
+ }
62
+ });
63
+ }
64
+ //# sourceMappingURL=start.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.command.js","sourceRoot":"","sources":["../../src/commands/start.command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { NurProjectConfig } from "nurjs-core";
2
+ export declare function loadNurConfig(cwd?: string): Promise<NurProjectConfig>;
3
+ //# sourceMappingURL=loadNurConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadNurConfig.d.ts","sourceRoot":"","sources":["../../src/config/loadNurConfig.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAcnD,wBAAsB,aAAa,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyBlF"}