nestforge-generator 0.4.1 → 0.6.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/README.md CHANGED
@@ -16,6 +16,44 @@ Run the locally installed CLI:
16
16
  npx nestforge
17
17
  ```
18
18
 
19
+ ## Command-line usage
20
+
21
+ Running `npx nestforge` without arguments starts the complete interactive flow. You can also provide part of the configuration and answer only the remaining prompts:
22
+
23
+ ```bash
24
+ npx nestforge my-api --orm prisma --database postgres
25
+ ```
26
+
27
+ Use `--yes` or `--non-interactive` to generate without prompts. Omitted options use the documented defaults: TypeScript, Prisma, PostgreSQL, JWT, all optional features enabled, access control enabled, and automatic `.env` creation.
28
+
29
+ ```bash
30
+ npx nestforge my-api --yes
31
+ npx nestforge my-api --non-interactive --orm drizzle --database sqlite --no-redis
32
+ ```
33
+
34
+ Available utility commands:
35
+
36
+ ```bash
37
+ npx nestforge --help
38
+ npx nestforge --version
39
+ npx nestforge --list
40
+ npx nestforge --doctor
41
+ ```
42
+
43
+ Generation flags include `--language`, `--orm`, `--database`, `--auth`, `--docker`, `--swagger`, `--validation`, `--redis`, `--access-control`, and `--env`. Boolean features also accept the corresponding `--no-*` form. Use `--no-update-check` to skip the registry check and `--no-banner` to hide the banner.
44
+
45
+ Invalid values, contradictory toggles, and unsupported combinations terminate with an error instead of silently changing the requested configuration.
46
+
47
+ ## Automatic update check
48
+
49
+ When the CLI starts, it checks the npm registry for a newer stable version. If an update is available, you can:
50
+
51
+ - download the latest version with `npx` and restart the CLI;
52
+ - continue with the currently installed version;
53
+ - hide the reminder until the next local day.
54
+
55
+ Registry metadata is cached for six hours in `~/.nestforge/update-check.json`. Network and cache failures are ignored so that the generator remains available offline.
56
+
19
57
  For the testing guide, CLI prompts, and complete checklist, see [`TESTING.md`](TESTING.md).
20
58
 
21
59
  ## What already works
package/README.pt-BR.md CHANGED
@@ -16,6 +16,44 @@ Execute a CLI instalada localmente:
16
16
  npx nestforge
17
17
  ```
18
18
 
19
+ ## Uso pela linha de comando
20
+
21
+ Executar `npx nestforge` sem argumentos inicia o fluxo interativo completo. Também é possível informar parte da configuração e responder apenas às perguntas restantes:
22
+
23
+ ```bash
24
+ npx nestforge minha-api --orm prisma --database postgres
25
+ ```
26
+
27
+ Use `--yes` ou `--non-interactive` para gerar sem prompts. As opções omitidas usam os padrões documentados: TypeScript, Prisma, PostgreSQL, JWT, todos os recursos opcionais habilitados, controle de acesso habilitado e criação automática do `.env`.
28
+
29
+ ```bash
30
+ npx nestforge minha-api --yes
31
+ npx nestforge minha-api --non-interactive --orm drizzle --database sqlite --no-redis
32
+ ```
33
+
34
+ Comandos utilitários disponíveis:
35
+
36
+ ```bash
37
+ npx nestforge --help
38
+ npx nestforge --version
39
+ npx nestforge --list
40
+ npx nestforge --doctor
41
+ ```
42
+
43
+ As flags de geração incluem `--language`, `--orm`, `--database`, `--auth`, `--docker`, `--swagger`, `--validation`, `--redis`, `--access-control` e `--env`. Recursos booleanos também aceitam a forma `--no-*` correspondente. Use `--no-update-check` para não consultar o registro e `--no-banner` para ocultar o banner.
44
+
45
+ Valores inválidos, toggles contraditórios e combinações não suportadas encerram a execução com erro, sem modificar silenciosamente a configuração solicitada.
46
+
47
+ ## Verificação automática de atualizações
48
+
49
+ Quando a CLI inicia, ela consulta o registro do npm em busca de uma versão estável mais recente. Se houver uma atualização, você pode:
50
+
51
+ * baixar a versão mais recente com `npx` e reiniciar a CLI;
52
+ * continuar com a versão instalada atualmente;
53
+ * ocultar o lembrete até o próximo dia no horário local.
54
+
55
+ Os metadados do registro ficam em cache durante seis horas em `~/.nestforge/update-check.json`. Falhas de rede ou de cache são ignoradas para que o gerador continue disponível offline.
56
+
19
57
  Para o guia de testes, perguntas da CLI e checklist completo, consulte [`TESTING.pt-BR.md`](TESTING.pt-BR.md).
20
58
 
21
59
  ## O que já funciona
@@ -0,0 +1,19 @@
1
+ export const CAPABILITIES = `
2
+ Supported NestForge combinations
3
+
4
+ Languages:
5
+ typescript, javascript
6
+
7
+ ORMs and databases:
8
+ prisma postgres, mysql, sqlite, mongodb
9
+ typeorm postgres, mysql, sqlite
10
+ drizzle postgres, mysql, sqlite
11
+ none no database
12
+
13
+ Authentication:
14
+ jwt, session, oauth, none
15
+
16
+ Projects without an ORM currently support only authentication "none".
17
+ MongoDB is currently available only with Prisma.
18
+ `.trim();
19
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;CAiB3B,CAAC,IAAI,EAAE,CAAC"}
@@ -0,0 +1,109 @@
1
+ import { parseArgs } from 'node:util';
2
+ import { AUTH_STRATEGY_CHOICES, DATABASE_CHOICES, LANGUAGE_CHOICES, ORM_CHOICES, } from './options.js';
3
+ export function parseCliArguments(args) {
4
+ const { values, positionals } = parseArgs({
5
+ args,
6
+ allowPositionals: true,
7
+ strict: true,
8
+ options: {
9
+ help: { type: 'boolean', short: 'h' },
10
+ version: { type: 'boolean', short: 'V' },
11
+ list: { type: 'boolean' },
12
+ doctor: { type: 'boolean' },
13
+ name: { type: 'string' },
14
+ language: { type: 'string' },
15
+ orm: { type: 'string' },
16
+ database: { type: 'string' },
17
+ auth: { type: 'string' },
18
+ 'non-interactive': { type: 'boolean' },
19
+ yes: { type: 'boolean', short: 'y' },
20
+ docker: { type: 'boolean' },
21
+ 'no-docker': { type: 'boolean' },
22
+ swagger: { type: 'boolean' },
23
+ 'no-swagger': { type: 'boolean' },
24
+ validation: { type: 'boolean' },
25
+ 'no-validation': { type: 'boolean' },
26
+ redis: { type: 'boolean' },
27
+ 'no-redis': { type: 'boolean' },
28
+ 'access-control': { type: 'boolean' },
29
+ 'no-access-control': { type: 'boolean' },
30
+ env: { type: 'boolean' },
31
+ 'no-env': { type: 'boolean' },
32
+ 'no-update-check': { type: 'boolean' },
33
+ 'no-banner': { type: 'boolean' },
34
+ },
35
+ });
36
+ const commands = [
37
+ values.help && 'help',
38
+ values.version && 'version',
39
+ values.list && 'list',
40
+ values.doctor && 'doctor',
41
+ ].filter(Boolean);
42
+ if (commands.length > 1) {
43
+ throw new Error('Use only one command at a time: --help, --version, --list, or --doctor.');
44
+ }
45
+ if (positionals.length > 1) {
46
+ throw new Error('Only one positional project name is allowed.');
47
+ }
48
+ if (values.name && positionals[0] && values.name !== positionals[0]) {
49
+ throw new Error('The positional project name and --name must match when both are provided.');
50
+ }
51
+ const projectName = values.name ?? positionals[0];
52
+ return {
53
+ command: commands[0] ?? 'generate',
54
+ options: {
55
+ projectName,
56
+ language: parseChoice(values.language, LANGUAGE_CHOICES, '--language'),
57
+ orm: parseChoice(values.orm, ORM_CHOICES, '--orm'),
58
+ database: parseChoice(values.database, DATABASE_CHOICES, '--database'),
59
+ authStrategy: parseChoice(values.auth, AUTH_STRATEGY_CHOICES, '--auth'),
60
+ docker: readToggle(values, 'docker'),
61
+ swagger: readToggle(values, 'swagger'),
62
+ validation: readToggle(values, 'validation'),
63
+ redis: readToggle(values, 'redis'),
64
+ accessControl: readToggle(values, 'access-control'),
65
+ createEnv: readToggle(values, 'env'),
66
+ },
67
+ nonInteractive: Boolean(values['non-interactive'] || values.yes),
68
+ checkUpdates: values['no-update-check'] !== true,
69
+ showBanner: values['no-banner'] !== true,
70
+ };
71
+ }
72
+ export function readCliArgumentVector(args = process.argv.slice(2), restartedArgs = process.env.NESTFORGE_RESTART_ARGS) {
73
+ if (!restartedArgs) {
74
+ return args;
75
+ }
76
+ try {
77
+ const parsed = JSON.parse(restartedArgs);
78
+ if (Array.isArray(parsed) &&
79
+ parsed.every((argument) => typeof argument === 'string')) {
80
+ return parsed;
81
+ }
82
+ }
83
+ catch {
84
+ // Ignore malformed external environment values.
85
+ }
86
+ return args;
87
+ }
88
+ function readToggle(values, name) {
89
+ const enabled = values[name] === true;
90
+ const disabled = values[`no-${name}`] === true;
91
+ if (enabled && disabled) {
92
+ throw new Error(`Options --${name} and --no-${name} cannot be used together.`);
93
+ }
94
+ if (enabled)
95
+ return true;
96
+ if (disabled)
97
+ return false;
98
+ return undefined;
99
+ }
100
+ function parseChoice(value, choices, flag) {
101
+ if (value === undefined) {
102
+ return undefined;
103
+ }
104
+ if (!choices.includes(value)) {
105
+ throw new Error(`Invalid value for ${flag}: "${value}". Available values: ${choices.join(', ')}.`);
106
+ }
107
+ return value;
108
+ }
109
+ //# sourceMappingURL=cli-arguments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-arguments.js","sourceRoot":"","sources":["../src/cli-arguments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ export const CLI_HELP = `
2
+ NestForge — generate production-ready NestJS projects
3
+
4
+ Usage:
5
+ nestforge [project-name] [options]
6
+ nestforge --name <project-name> [options]
7
+
8
+ Commands:
9
+ -h, --help Show this help
10
+ -V, --version Show the installed version
11
+ --list List supported combinations
12
+ --doctor Check the local environment
13
+
14
+ Generation:
15
+ --language <value> typescript | javascript
16
+ --orm <value> prisma | typeorm | drizzle | none
17
+ --database <value> postgres | mysql | sqlite | mongodb | none
18
+ --auth <value> jwt | session | oauth | none
19
+ -y, --yes Generate non-interactively with defaults
20
+ --non-interactive Never open configuration prompts
21
+
22
+ Feature toggles:
23
+ --docker / --no-docker
24
+ --swagger / --no-swagger
25
+ --validation / --no-validation
26
+ --redis / --no-redis
27
+ --access-control / --no-access-control
28
+ --env / --no-env
29
+
30
+ Output and updates:
31
+ --no-banner Hide the NestForge banner
32
+ --no-update-check Skip the automatic update check
33
+
34
+ Examples:
35
+ nestforge
36
+ nestforge my-api --orm prisma
37
+ nestforge my-api --yes
38
+ nestforge my-api --non-interactive --orm drizzle --database sqlite
39
+ `.trim();
40
+ //# sourceMappingURL=cli-help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCvB,CAAC,IAAI,EAAE,CAAC"}
package/dist/doctor.js ADDED
@@ -0,0 +1,88 @@
1
+ export async function runDoctorChecks() {
2
+ const nodeMajor = Number(process.versions.node.split('.')[0]);
3
+ const checks = [
4
+ {
5
+ label: 'Node.js',
6
+ status: nodeMajor >= 20 ? 'pass' : 'fail',
7
+ detail: `v${process.versions.node} (NestForge requires Node.js 20 or newer)`,
8
+ },
9
+ ];
10
+ try {
11
+ await access(process.cwd(), constants.W_OK);
12
+ checks.push({
13
+ label: 'Current directory',
14
+ status: 'pass',
15
+ detail: 'Writable',
16
+ });
17
+ }
18
+ catch {
19
+ checks.push({
20
+ label: 'Current directory',
21
+ status: 'fail',
22
+ detail: 'Not writable',
23
+ });
24
+ }
25
+ checks.push(checkCommand('npm', ['--version'], false));
26
+ checks.push(checkCommand('Git', ['--version'], false, 'git'));
27
+ checks.push(checkCommand('Docker', ['--version'], true, 'docker'));
28
+ return {
29
+ checks,
30
+ healthy: checks.every((check) => check.status !== 'fail'),
31
+ };
32
+ }
33
+ export function formatDoctorReport(report) {
34
+ const symbols = {
35
+ pass: '✓',
36
+ warning: '!',
37
+ fail: '✗',
38
+ };
39
+ return [
40
+ 'NestForge doctor',
41
+ '',
42
+ ...report.checks.map((check) => `${symbols[check.status]} ${check.label}: ${check.detail}`),
43
+ '',
44
+ report.healthy
45
+ ? 'Environment ready.'
46
+ : 'Resolve the failed checks before generating a project.',
47
+ ].join('\n');
48
+ }
49
+ function checkCommand(label, args, optional, command = label) {
50
+ if (process.platform === 'win32') {
51
+ const lookup = spawnSync('where.exe', [command], {
52
+ encoding: 'utf8',
53
+ windowsHide: true,
54
+ });
55
+ if (lookup.status === 0) {
56
+ return {
57
+ label,
58
+ status: 'pass',
59
+ detail: lookup.stdout.trim().split(/\r?\n/)[0],
60
+ };
61
+ }
62
+ return {
63
+ label,
64
+ status: optional ? 'warning' : 'fail',
65
+ detail: optional ? 'Not found (optional)' : 'Not found',
66
+ };
67
+ }
68
+ const result = spawnSync(command, args, {
69
+ encoding: 'utf8',
70
+ windowsHide: true,
71
+ });
72
+ if (result.status === 0) {
73
+ return {
74
+ label,
75
+ status: 'pass',
76
+ detail: (result.stdout || result.stderr).trim(),
77
+ };
78
+ }
79
+ return {
80
+ label,
81
+ status: optional ? 'warning' : 'fail',
82
+ detail: optional ? 'Not found (optional)' : 'Not found',
83
+ };
84
+ }
85
+ import { constants } from 'node:fs';
86
+ import { access } from 'node:fs/promises';
87
+ import { spawnSync } from 'node:child_process';
88
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4,8 +4,56 @@ import pc from 'picocolors';
4
4
  import path from 'node:path';
5
5
  import { runPrompts } from './prompts.js';
6
6
  import { generateProject } from './generator.js';
7
+ import { handleUpdateNotification } from './update-notifier.js';
8
+ import { parseCliArguments, readCliArgumentVector } from './cli-arguments.js';
9
+ import { CLI_HELP } from './cli-help.js';
10
+ import { readPackageInfo } from './package-info.js';
11
+ import { CAPABILITIES } from './capabilities.js';
12
+ import { formatDoctorReport, runDoctorChecks } from './doctor.js';
13
+ import { resolveNonInteractiveOptions } from './project-options.js';
7
14
  async function main() {
8
- const options = await runPrompts();
15
+ try {
16
+ await run();
17
+ }
18
+ catch (error) {
19
+ log.error(error instanceof Error ? error.message : String(error));
20
+ process.exitCode = 1;
21
+ }
22
+ }
23
+ async function run() {
24
+ const cli = parseCliArguments(readCliArgumentVector());
25
+ if (cli.command === 'help') {
26
+ console.log(CLI_HELP);
27
+ return;
28
+ }
29
+ if (cli.command === 'version') {
30
+ const packageInfo = await readPackageInfo();
31
+ console.log(packageInfo.version);
32
+ return;
33
+ }
34
+ if (cli.command === 'list') {
35
+ console.log(CAPABILITIES);
36
+ return;
37
+ }
38
+ if (cli.command === 'doctor') {
39
+ const report = await runDoctorChecks();
40
+ console.log(formatDoctorReport(report));
41
+ if (!report.healthy) {
42
+ process.exitCode = 1;
43
+ }
44
+ return;
45
+ }
46
+ const updateResult = cli.checkUpdates
47
+ ? await handleUpdateNotification()
48
+ : 'continue';
49
+ if (updateResult === 'restarted') {
50
+ return;
51
+ }
52
+ const options = cli.nonInteractive
53
+ ? resolveNonInteractiveOptions(cli.options)
54
+ : await runPrompts(cli.options, {
55
+ showBanner: cli.showBanner,
56
+ });
9
57
  try {
10
58
  const targetDir = await generateProject(options);
11
59
  const relativeDir = path.relative(process.cwd(), targetDir) || '.';
@@ -67,7 +115,7 @@ async function main() {
67
115
  }
68
116
  catch (error) {
69
117
  log.error(error instanceof Error ? error.message : String(error));
70
- process.exit(1);
118
+ process.exitCode = 1;
71
119
  }
72
120
  }
73
121
  main();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export const LANGUAGE_CHOICES = ['typescript', 'javascript'];
2
+ export const ORM_CHOICES = ['prisma', 'typeorm', 'drizzle', 'none'];
3
+ export const DATABASE_CHOICES = ['postgres', 'mysql', 'sqlite', 'mongodb', 'none'];
4
+ export const AUTH_STRATEGY_CHOICES = ['jwt', 'session', 'oauth', 'none'];
5
+ export const FEATURE_NAMES = ['docker', 'swagger', 'validation', 'redis'];
6
+ export const DEFAULT_PROJECT_OPTIONS = {
7
+ language: 'typescript',
8
+ orm: 'prisma',
9
+ database: 'postgres',
10
+ docker: true,
11
+ swagger: true,
12
+ validation: true,
13
+ redis: true,
14
+ authStrategy: 'jwt',
15
+ accessControl: true,
16
+ createEnv: true,
17
+ };
18
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AA8BA,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,YAAY,EAAE,YAAY,CAAU,CAAC;AACtE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAU,CAAC;AAC7E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAU,CAAC;AAC5F,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;AAElF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,CAAU,CAAC;AAGnF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACnC,QAAQ,EAAE,YAAY;IACtB,GAAG,EAAE,QAAQ;IACb,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,IAAI;IACb,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,IAAI;IACX,YAAY,EAAE,KAAK;IACnB,aAAa,EAAE,IAAI;IACnB,SAAS,EAAE,IAAI;CACyC,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import fs from 'fs-extra';
3
+ const packageJsonPath = fileURLToPath(new URL('../package.json', import.meta.url));
4
+ export async function readPackageInfo() {
5
+ const manifest = (await fs.readJson(packageJsonPath));
6
+ if (typeof manifest.name !== 'string' ||
7
+ typeof manifest.version !== 'string') {
8
+ throw new Error('Unable to read the NestForge package information.');
9
+ }
10
+ return {
11
+ name: manifest.name,
12
+ version: manifest.version,
13
+ };
14
+ }
15
+ //# sourceMappingURL=package-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-info.js","sourceRoot":"","sources":["../src/package-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,MAAM,UAAU,CAAC;AAO1B,MAAM,eAAe,GAAG,aAAa,CACjC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAC9C,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,eAAe;IAIjC,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,CAC/B,eAAe,CAClB,CAAoB,CAAC;IAEtB,IACI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ;QACjC,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,EACtC,CAAC;QACC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACzE,CAAC;IAED,OAAO;QACH,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,OAAO,EAAE,QAAQ,CAAC,OAAO;KAC5B,CAAC;AACN,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { DEFAULT_PROJECT_OPTIONS, } from './options.js';
2
+ export function buildFeatureList(options) {
3
+ return [
4
+ options.docker && 'docker',
5
+ options.swagger && 'swagger',
6
+ options.validation && 'validation',
7
+ options.redis && 'redis',
8
+ ].filter((feature) => Boolean(feature));
9
+ }
10
+ export function assertCompatibleOptionInput(input) {
11
+ if (input.orm === 'none' && input.database && input.database !== 'none') {
12
+ throw new Error('Projects without an ORM must use "none" as their database option.');
13
+ }
14
+ if (input.orm === 'none' && input.authStrategy && input.authStrategy !== 'none') {
15
+ throw new Error('Projects without an ORM currently support only the "none" authentication strategy.');
16
+ }
17
+ if (input.orm === 'none' && input.accessControl === true) {
18
+ throw new Error('Access control is not available without an ORM.');
19
+ }
20
+ if (input.database === 'mongodb' && input.orm && input.orm !== 'prisma') {
21
+ throw new Error('MongoDB is currently available only with Prisma.');
22
+ }
23
+ if (input.authStrategy === 'none' && input.accessControl === true) {
24
+ throw new Error('Access control requires an authentication strategy.');
25
+ }
26
+ }
27
+ export function resolveNonInteractiveOptions(input) {
28
+ assertCompatibleOptionInput(input);
29
+ if (!input.projectName) {
30
+ throw new Error('A project name is required in non-interactive mode.');
31
+ }
32
+ const orm = input.orm ?? DEFAULT_PROJECT_OPTIONS.orm;
33
+ const database = orm === 'none'
34
+ ? 'none'
35
+ : input.database ?? DEFAULT_PROJECT_OPTIONS.database;
36
+ const authStrategy = orm === 'none'
37
+ ? 'none'
38
+ : input.authStrategy ?? DEFAULT_PROJECT_OPTIONS.authStrategy;
39
+ const accessControl = authStrategy === 'none'
40
+ ? false
41
+ : input.accessControl ?? DEFAULT_PROJECT_OPTIONS.accessControl;
42
+ const featureInput = {
43
+ docker: input.docker ?? DEFAULT_PROJECT_OPTIONS.docker,
44
+ swagger: input.swagger ?? DEFAULT_PROJECT_OPTIONS.swagger,
45
+ validation: input.validation ?? DEFAULT_PROJECT_OPTIONS.validation,
46
+ redis: input.redis ?? DEFAULT_PROJECT_OPTIONS.redis,
47
+ };
48
+ const resolved = {
49
+ projectName: input.projectName,
50
+ language: input.language ?? DEFAULT_PROJECT_OPTIONS.language,
51
+ orm,
52
+ database,
53
+ features: buildFeatureList(featureInput),
54
+ authStrategy,
55
+ accessControl,
56
+ createEnv: input.createEnv ?? DEFAULT_PROJECT_OPTIONS.createEnv,
57
+ };
58
+ assertCompatibleOptionInput({
59
+ ...input,
60
+ orm: resolved.orm,
61
+ database: resolved.database,
62
+ authStrategy: resolved.authStrategy,
63
+ accessControl: resolved.accessControl,
64
+ });
65
+ return resolved;
66
+ }
67
+ //# sourceMappingURL=project-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-options.js","sourceRoot":"","sources":["../src/project-options.ts"],"names":[],"mappings":"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"}
package/dist/prompts.js CHANGED
@@ -2,6 +2,7 @@ import { intro, outro, text, select, confirm, isCancel, cancel } from '@clack/pr
2
2
  import gradient from 'gradient-string';
3
3
  import pc from 'picocolors';
4
4
  import { validateProjectName } from './project-name.js';
5
+ import { assertCompatibleOptionInput } from './project-options.js';
5
6
  // red -> orange, the NestJS colors
6
7
  const nestforgeGradient = gradient(['#e0234e', '#ff8a65']);
7
8
  const logo = [
@@ -25,11 +26,14 @@ function handleCancel(value) {
25
26
  process.exit(0);
26
27
  }
27
28
  }
28
- export async function runPrompts() {
29
- showBanner();
29
+ export async function runPrompts(initial = {}, settings = {}) {
30
+ assertCompatibleOptionInput(initial);
31
+ if (settings.showBanner !== false) {
32
+ showBanner();
33
+ }
30
34
  intro(pc.bgMagenta(pc.black(' NestForge ')));
31
35
  // 1. Project name
32
- const projectName = await text({
36
+ const projectName = initial.projectName ?? await text({
33
37
  message: 'What is your project name?',
34
38
  placeholder: 'my-nest-api',
35
39
  defaultValue: 'my-nest-api',
@@ -37,7 +41,7 @@ export async function runPrompts() {
37
41
  });
38
42
  handleCancel(projectName);
39
43
  // 2. Language
40
- const language = await select({
44
+ const language = initial.language ?? await select({
41
45
  message: 'TypeScript or JavaScript?',
42
46
  options: [
43
47
  { value: 'typescript', label: 'TypeScript', hint: 'Recommended' },
@@ -46,7 +50,7 @@ export async function runPrompts() {
46
50
  });
47
51
  handleCancel(language);
48
52
  // 3. ORM selection
49
- const orm = await select({
53
+ const orm = initial.orm ?? await select({
50
54
  message: 'Choose the ORM/Query Builder:',
51
55
  options: [
52
56
  { value: 'prisma', label: 'Prisma', hint: 'Recommended' },
@@ -57,8 +61,8 @@ export async function runPrompts() {
57
61
  });
58
62
  handleCancel(orm);
59
63
  // 4. Database
60
- let database = 'none';
61
- if (orm !== 'none') {
64
+ let database = initial.database ?? 'none';
65
+ if (orm !== 'none' && initial.database === undefined) {
62
66
  const databaseSelection = await select({
63
67
  message: 'Which database do you want to use?',
64
68
  options: [
@@ -75,28 +79,28 @@ export async function runPrompts() {
75
79
  }
76
80
  // 5. Additional features (one yes/no prompt at a time)
77
81
  const features = [];
78
- const wantsDocker = await confirm({
82
+ const wantsDocker = initial.docker ?? await confirm({
79
83
  message: 'Do you want to add Docker?',
80
84
  initialValue: true,
81
85
  });
82
86
  handleCancel(wantsDocker);
83
87
  if (wantsDocker)
84
88
  features.push('docker');
85
- const wantsSwagger = await confirm({
89
+ const wantsSwagger = initial.swagger ?? await confirm({
86
90
  message: 'Do you want to include Swagger/OpenAPI documentation?',
87
91
  initialValue: true,
88
92
  });
89
93
  handleCancel(wantsSwagger);
90
94
  if (wantsSwagger)
91
95
  features.push('swagger');
92
- const wantsValidation = await confirm({
96
+ const wantsValidation = initial.validation ?? await confirm({
93
97
  message: 'Do you want to enable global validation with Zod?',
94
98
  initialValue: true,
95
99
  });
96
100
  handleCancel(wantsValidation);
97
101
  if (wantsValidation)
98
102
  features.push('validation');
99
- const wantsRedis = await confirm({
103
+ const wantsRedis = initial.redis ?? await confirm({
100
104
  message: 'Do you want to include Redis (cache/queues + email through BullMQ)?',
101
105
  initialValue: true,
102
106
  });
@@ -104,8 +108,8 @@ export async function runPrompts() {
104
108
  if (wantsRedis)
105
109
  features.push('redis');
106
110
  // 6. Authentication strategy
107
- let authStrategy = 'none';
108
- if (orm !== 'none') {
111
+ let authStrategy = initial.authStrategy ?? 'none';
112
+ if (orm !== 'none' && initial.authStrategy === undefined) {
109
113
  const authStrategySelection = await select({
110
114
  message: 'Which authentication strategy do you want to use?',
111
115
  options: [
@@ -119,8 +123,8 @@ export async function runPrompts() {
119
123
  authStrategy = authStrategySelection;
120
124
  }
121
125
  // 7. Access control (only applicable when authentication is enabled)
122
- let accessControl = false;
123
- if (authStrategy !== 'none') {
126
+ let accessControl = initial.accessControl ?? false;
127
+ if (authStrategy !== 'none' && initial.accessControl === undefined) {
124
128
  const wantsAccessControl = await confirm({
125
129
  message: '🛡️ Do you want to include access control (RBAC + Permissions)?',
126
130
  initialValue: true,
@@ -129,7 +133,7 @@ export async function runPrompts() {
129
133
  accessControl = wantsAccessControl;
130
134
  }
131
135
  // 8. Automatic .env creation
132
- const createEnv = await confirm({
136
+ const createEnv = initial.createEnv ?? await confirm({
133
137
  message: 'Do you want to create the .env file automatically (from .env.example)?',
134
138
  initialValue: true,
135
139
  });
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import os from 'node:os';
2
+ import path from 'node:path';
3
+ import fs from 'fs-extra';
4
+ import semver from 'semver';
5
+ const REGISTRY_URL = 'https://registry.npmjs.org/nestforge-generator/latest';
6
+ const CHECK_INTERVAL_MS = 6 * 60 * 60 * 1000;
7
+ const REQUEST_TIMEOUT_MS = 2_000;
8
+ export function getUpdateCachePath() {
9
+ return path.join(os.homedir(), '.nestforge', 'update-check.json');
10
+ }
11
+ async function readCache(cachePath) {
12
+ try {
13
+ const cache = (await fs.readJson(cachePath));
14
+ return cache && typeof cache === 'object' ? cache : {};
15
+ }
16
+ catch {
17
+ return {};
18
+ }
19
+ }
20
+ async function writeCache(cachePath, cache) {
21
+ await fs.outputJson(cachePath, cache, { spaces: 2 });
22
+ }
23
+ async function fetchLatestVersion(fetchImplementation) {
24
+ const controller = new AbortController();
25
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
26
+ try {
27
+ const response = await fetchImplementation(REGISTRY_URL, {
28
+ headers: {
29
+ accept: 'application/json',
30
+ },
31
+ signal: controller.signal,
32
+ });
33
+ if (!response.ok) {
34
+ throw new Error(`The npm registry returned ${response.status}.`);
35
+ }
36
+ const metadata = (await response.json());
37
+ if (typeof metadata.version !== 'string' ||
38
+ !semver.valid(metadata.version)) {
39
+ throw new Error('The npm registry returned an invalid version.');
40
+ }
41
+ return metadata.version;
42
+ }
43
+ finally {
44
+ clearTimeout(timeout);
45
+ }
46
+ }
47
+ export async function checkForUpdate(currentVersion, options = {}) {
48
+ if (!semver.valid(currentVersion)) {
49
+ return null;
50
+ }
51
+ const now = options.now ?? Date.now();
52
+ const cachePath = options.cachePath ?? getUpdateCachePath();
53
+ try {
54
+ const cache = await readCache(cachePath);
55
+ if (typeof cache.dismissedUntil === 'number' &&
56
+ cache.dismissedUntil > now) {
57
+ return null;
58
+ }
59
+ const hasFreshCache = typeof cache.checkedAt === 'number' &&
60
+ typeof cache.latestVersion === 'string' &&
61
+ now - cache.checkedAt < CHECK_INTERVAL_MS &&
62
+ semver.valid(cache.latestVersion);
63
+ const latestVersion = hasFreshCache
64
+ ? cache.latestVersion
65
+ : await fetchLatestVersion(options.fetchImplementation ?? fetch);
66
+ if (!hasFreshCache) {
67
+ try {
68
+ await writeCache(cachePath, {
69
+ ...cache,
70
+ checkedAt: now,
71
+ latestVersion,
72
+ });
73
+ }
74
+ catch {
75
+ // The update can still be offered without a writable cache.
76
+ }
77
+ }
78
+ return semver.gt(latestVersion, currentVersion)
79
+ ? { currentVersion, latestVersion }
80
+ : null;
81
+ }
82
+ catch {
83
+ return null;
84
+ }
85
+ }
86
+ export async function dismissUpdatesForToday(options = {}) {
87
+ const now = options.now ?? Date.now();
88
+ const cachePath = options.cachePath ?? getUpdateCachePath();
89
+ const tomorrow = new Date(now);
90
+ tomorrow.setHours(24, 0, 0, 0);
91
+ try {
92
+ const cache = await readCache(cachePath);
93
+ await writeCache(cachePath, {
94
+ ...cache,
95
+ dismissedUntil: tomorrow.getTime(),
96
+ });
97
+ }
98
+ catch {
99
+ // A cache failure must never prevent the CLI from starting.
100
+ }
101
+ }
102
+ //# sourceMappingURL=update-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-check.js","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { isCancel, log, note, select } from '@clack/prompts';
3
+ import pc from 'picocolors';
4
+ import { readPackageInfo } from './package-info.js';
5
+ import { checkForUpdate, dismissUpdatesForToday, } from './update-check.js';
6
+ export function getUpdateProcess(platform = process.platform) {
7
+ if (platform === 'win32') {
8
+ return {
9
+ command: process.env.ComSpec ?? 'cmd.exe',
10
+ args: [
11
+ '/d',
12
+ '/s',
13
+ '/c',
14
+ 'npx --yes nestforge-generator@latest',
15
+ ],
16
+ };
17
+ }
18
+ return {
19
+ command: 'npx',
20
+ args: ['--yes', 'nestforge-generator@latest'],
21
+ };
22
+ }
23
+ export async function runLatestVersion() {
24
+ return new Promise((resolve) => {
25
+ const updateProcess = getUpdateProcess();
26
+ const child = spawn(updateProcess.command, updateProcess.args, {
27
+ stdio: 'inherit',
28
+ shell: false,
29
+ env: {
30
+ ...process.env,
31
+ NESTFORGE_RESTART_ARGS: JSON.stringify(process.argv.slice(2)),
32
+ },
33
+ });
34
+ let settled = false;
35
+ const finish = (success) => {
36
+ if (settled) {
37
+ return;
38
+ }
39
+ settled = true;
40
+ resolve(success);
41
+ };
42
+ child.once('error', () => finish(false));
43
+ child.once('exit', (code) => finish(code === 0));
44
+ });
45
+ }
46
+ async function promptForUpdate(update) {
47
+ note(`${pc.dim(update.currentVersion)} ${pc.dim('→')} ${pc.green(update.latestVersion)}`, 'NestForge update available');
48
+ const choice = await select({
49
+ message: 'How would you like to continue?',
50
+ options: [
51
+ {
52
+ value: 'update',
53
+ label: 'Update and restart',
54
+ hint: 'Recommended',
55
+ },
56
+ {
57
+ value: 'continue',
58
+ label: `Continue with version ${update.currentVersion}`,
59
+ },
60
+ {
61
+ value: 'dismiss-today',
62
+ label: "Don't remind me today",
63
+ },
64
+ ],
65
+ });
66
+ return isCancel(choice) ? 'continue' : choice;
67
+ }
68
+ export async function handleUpdateNotification(options = {}) {
69
+ try {
70
+ const packageInfo = await (options.readCurrentPackage ?? readPackageInfo)();
71
+ const update = await (options.check ?? checkForUpdate)(packageInfo.version);
72
+ if (!update) {
73
+ return 'continue';
74
+ }
75
+ const choice = await (options.prompt ?? promptForUpdate)(update);
76
+ if (choice === 'dismiss-today') {
77
+ await (options.dismiss ?? dismissUpdatesForToday)();
78
+ return 'continue';
79
+ }
80
+ if (choice === 'continue') {
81
+ return 'continue';
82
+ }
83
+ log.info('Downloading the latest NestForge version...');
84
+ const updated = await (options.runLatest ?? runLatestVersion)();
85
+ if (updated) {
86
+ return 'restarted';
87
+ }
88
+ log.warn('The update could not be started. Continuing with the current version.');
89
+ return 'continue';
90
+ }
91
+ catch {
92
+ return 'continue';
93
+ }
94
+ }
95
+ //# sourceMappingURL=update-notifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-notifier.js","sourceRoot":"","sources":["../src/update-notifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EACH,cAAc,EACd,sBAAsB,GAEzB,MAAM,mBAAmB,CAAC;AAa3B,MAAM,UAAU,gBAAgB,CAC5B,WAA4B,OAAO,CAAC,QAAQ;IAE5C,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACvB,OAAO;YACH,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,SAAS;YACzC,IAAI,EAAE;gBACF,IAAI;gBACJ,IAAI;gBACJ,IAAI;gBACJ,sCAAsC;aACzC;SACJ,CAAC;IACN,CAAC;IAED,OAAO;QACH,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,CAAC,OAAO,EAAE,4BAA4B,CAAC;KAChD,CAAC;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IAClC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,KAAK,CACf,aAAa,CAAC,OAAO,EACrB,aAAa,CAAC,IAAI,EAClB;YACI,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,KAAK;YACZ,GAAG,EAAE;gBACD,GAAG,OAAO,CAAC,GAAG;gBACd,sBAAsB,EAAE,IAAI,CAAC,SAAS,CAClC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CACxB;aACJ;SACJ,CACJ,CAAC;QAEF,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,MAAM,GAAG,CAAC,OAAgB,EAAE,EAAE;YAChC,IAAI,OAAO,EAAE,CAAC;gBACV,OAAO;YACX,CAAC;YAED,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC,CAAC;QAEF,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACP,CAAC;AAED,KAAK,UAAU,eAAe,CAC1B,MAAkB;IAElB,IAAI,CACA,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,EACnF,4BAA4B,CAC/B,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAe;QACtC,OAAO,EAAE,iCAAiC;QAC1C,OAAO,EAAE;YACL;gBACI,KAAK,EAAE,QAAQ;gBACf,KAAK,EAAE,oBAAoB;gBAC3B,IAAI,EAAE,aAAa;aACtB;YACD;gBACI,KAAK,EAAE,UAAU;gBACjB,KAAK,EAAE,yBAAyB,MAAM,CAAC,cAAc,EAAE;aAC1D;YACD;gBACI,KAAK,EAAE,eAAe;gBACtB,KAAK,EAAE,uBAAuB;aACjC;SACJ;KACJ,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC1C,UAAiC,EAAE;IAEnC,IAAI,CAAC;QACD,MAAM,WAAW,GAAG,MAAM,CACtB,OAAO,CAAC,kBAAkB,IAAI,eAAe,CAChD,EAAE,CAAC;QACJ,MAAM,MAAM,GAAG,MAAM,CACjB,OAAO,CAAC,KAAK,IAAI,cAAc,CAClC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAEvB,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,OAAO,UAAU,CAAC;QACtB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CACjB,OAAO,CAAC,MAAM,IAAI,eAAe,CACpC,CAAC,MAAM,CAAC,CAAC;QAEV,IAAI,MAAM,KAAK,eAAe,EAAE,CAAC;YAC7B,MAAM,CACF,OAAO,CAAC,OAAO,IAAI,sBAAsB,CAC5C,EAAE,CAAC;YACJ,OAAO,UAAU,CAAC;QACtB,CAAC;QAED,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;YACxB,OAAO,UAAU,CAAC;QACtB,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,MAAM,CAClB,OAAO,CAAC,SAAS,IAAI,gBAAgB,CACxC,EAAE,CAAC;QAEJ,IAAI,OAAO,EAAE,CAAC;YACV,OAAO,WAAW,CAAC;QACvB,CAAC;QAED,GAAG,CAAC,IAAI,CACJ,uEAAuE,CAC1E,CAAC;QACF,OAAO,UAAU,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,UAAU,CAAC;IACtB,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nestforge-generator",
3
- "version": "0.4.1",
3
+ "version": "0.6.0",
4
4
  "description": "Interactive CLI for generating a NestJS project from a NestForge starter template",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -19,7 +19,7 @@
19
19
  "build": "tsc -p tsconfig.json && npm run copy:templates",
20
20
  "copy:templates": "node scripts/copy-templates.mjs",
21
21
  "dev": "tsx src/index.ts",
22
- "test": "tsx --test test/generator.test.ts",
22
+ "test": "tsx --test test/generator.test.ts test/update-check.test.ts test/cli-arguments.test.ts test/project-options.test.ts",
23
23
  "lint": "eslint \"src/**/*.ts\" --fix",
24
24
  "prepack": "npm run build",
25
25
  "prepublishOnly": "npm test"
@@ -48,15 +48,17 @@
48
48
  ],
49
49
  "dependencies": {
50
50
  "@clack/prompts": "^0.9.0",
51
- "picocolors": "^1.1.0",
52
51
  "fs-extra": "^11.2.0",
53
52
  "gradient-string": "^2.0.2",
53
+ "picocolors": "^1.1.0",
54
+ "semver": "^7.8.5",
54
55
  "typescript": "^5.6.0"
55
56
  },
56
57
  "devDependencies": {
57
58
  "@types/fs-extra": "^11.0.4",
58
- "@types/node": "^22.0.0",
59
59
  "@types/gradient-string": "^1.1.6",
60
+ "@types/node": "^22.0.0",
61
+ "@types/semver": "^7.8.0",
60
62
  "tsx": "^4.19.0"
61
63
  },
62
64
  "engines": {