@fluojs/cli 1.1.0 → 2.0.1
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.ko.md +16 -3
- package/README.md +16 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -3
- package/dist/commands/generate.d.ts +1 -49
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +1 -214
- package/dist/commands/inspect.d.ts +0 -6
- package/dist/commands/inspect.d.ts.map +1 -1
- package/dist/commands/inspect.js +1 -48
- package/dist/commands/new.d.ts +0 -6
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +14 -88
- package/dist/commands/scripts.d.ts +1 -1
- package/dist/commands/scripts.d.ts.map +1 -1
- package/dist/commands/scripts.js +11 -5
- package/dist/dev-runner/node-restart-runner.d.ts +6 -0
- package/dist/dev-runner/node-restart-runner.d.ts.map +1 -1
- package/dist/dev-runner/node-restart-runner.js +10 -6
- package/dist/generate-command.d.ts +50 -0
- package/dist/generate-command.d.ts.map +1 -0
- package/dist/generate-command.js +214 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/new/scaffold.d.ts.map +1 -1
- package/dist/new/scaffold.js +115 -23
- package/dist/new/types.d.ts +0 -2
- package/dist/new/types.d.ts.map +1 -1
- package/dist/public-generate.d.ts +2 -0
- package/dist/public-generate.d.ts.map +1 -0
- package/dist/public-generate.js +1 -0
- package/dist/public-inspect.d.ts +13 -0
- package/dist/public-inspect.d.ts.map +1 -0
- package/dist/public-inspect.js +16 -0
- package/dist/public-new.d.ts +13 -0
- package/dist/public-new.d.ts.map +1 -0
- package/dist/public-new.js +16 -0
- package/dist/studio/sidecar.d.ts.map +1 -1
- package/dist/studio/sidecar.js +71 -5
- package/dist/usage.d.ts +13 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +131 -0
- package/package.json +3 -3
package/dist/commands/new.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
|
-
import {
|
|
3
|
-
import { renderAliasList, renderHelpTable } from '../help.js';
|
|
4
|
-
import { isCliPromptCancelledError } from '../prompt-cancel.js';
|
|
2
|
+
import { log as clackLog, spinner as clackSpinner } from '@clack/prompts';
|
|
5
3
|
import { installDependencies } from '../new/install.js';
|
|
6
4
|
import { collectBootstrapAnswers } from '../new/prompt.js';
|
|
7
5
|
import { resolveBootstrapPlan } from '../new/resolver.js';
|
|
8
6
|
import { scaffoldBootstrapApp } from '../new/scaffold.js';
|
|
9
7
|
import { SUPPORTED_BOOTSTRAP_PLATFORMS, SUPPORTED_BOOTSTRAP_RUNTIMES, SUPPORTED_BOOTSTRAP_SHAPES, SUPPORTED_BOOTSTRAP_TOOLING_PRESETS, SUPPORTED_BOOTSTRAP_TOPOLOGY_MODES, SUPPORTED_BOOTSTRAP_TRANSPORTS } from '../new/starter-profiles.js';
|
|
8
|
+
import { isCliPromptCancelledError } from '../prompt-cancel.js';
|
|
9
|
+
import { newUsage } from '../usage.js';
|
|
10
10
|
function shouldUseInteractiveShell(runtime) {
|
|
11
11
|
return runtime.prompt === undefined && runtime.stdout === undefined && runtime.stderr === undefined && (runtime.interactive ?? true) && Boolean(runtime.stdin?.isTTY ?? process.stdin.isTTY);
|
|
12
12
|
}
|
|
@@ -20,76 +20,19 @@ function extractDependencyInstallationOutput(error) {
|
|
|
20
20
|
function isHelpFlag(value) {
|
|
21
21
|
return value === '--help' || value === '-h';
|
|
22
22
|
}
|
|
23
|
+
function readInternalScaffoldOverrides(runtime) {
|
|
24
|
+
const dependencySource = 'dependencySource' in runtime ? runtime.dependencySource : undefined;
|
|
25
|
+
const repoRoot = 'repoRoot' in runtime ? runtime.repoRoot : undefined;
|
|
26
|
+
return {
|
|
27
|
+
dependencySource: dependencySource === 'local' || dependencySource === 'published' ? dependencySource : undefined,
|
|
28
|
+
repoRoot: typeof repoRoot === 'string' ? repoRoot : undefined
|
|
29
|
+
};
|
|
30
|
+
}
|
|
23
31
|
|
|
24
32
|
/**
|
|
25
33
|
* Runtime dependency overrides for the programmatic `fluo new` entry point.
|
|
26
34
|
*/
|
|
27
35
|
|
|
28
|
-
const NEW_OPTION_HELP = [{
|
|
29
|
-
aliases: [],
|
|
30
|
-
description: 'Provide the project name without using the positional argument.',
|
|
31
|
-
option: '--name <project-name>'
|
|
32
|
-
}, {
|
|
33
|
-
aliases: [],
|
|
34
|
-
description: 'Select the scaffold shape explicitly (application for HTTP, microservice for the transport-driven starter path, mixed for the API + microservice starter).',
|
|
35
|
-
option: '--shape <application|microservice|mixed>'
|
|
36
|
-
}, {
|
|
37
|
-
aliases: [],
|
|
38
|
-
description: 'Select the transport path explicitly (http for applications, tcp for the runnable microservice starter, plus shipped microservice starter transports).',
|
|
39
|
-
option: '--transport <http|tcp|redis-streams|nats|kafka|rabbitmq|mqtt|grpc>'
|
|
40
|
-
}, {
|
|
41
|
-
aliases: [],
|
|
42
|
-
description: 'Select the runtime explicitly (node, bun, deno, or cloudflare-workers for application starters; node for microservice and mixed starters).',
|
|
43
|
-
option: '--runtime <node|bun|deno|cloudflare-workers>'
|
|
44
|
-
}, {
|
|
45
|
-
aliases: [],
|
|
46
|
-
description: 'Select the platform adapter explicitly (fastify, express, or nodejs on node; bun/deno/cloudflare-workers on their native runtimes; none for microservices).',
|
|
47
|
-
option: '--platform <fastify|express|nodejs|bun|deno|cloudflare-workers|none>'
|
|
48
|
-
}, {
|
|
49
|
-
aliases: [],
|
|
50
|
-
description: 'Select the starter tooling preset explicitly (currently only standard).',
|
|
51
|
-
option: '--tooling <standard>'
|
|
52
|
-
}, {
|
|
53
|
-
aliases: [],
|
|
54
|
-
description: 'Select the starter topology mode explicitly (currently only single-package).',
|
|
55
|
-
option: '--topology <single-package>'
|
|
56
|
-
}, {
|
|
57
|
-
aliases: [],
|
|
58
|
-
description: 'Choose which package manager installs the starter dependencies.',
|
|
59
|
-
option: '--package-manager <pnpm|npm|yarn|bun>'
|
|
60
|
-
}, {
|
|
61
|
-
aliases: [],
|
|
62
|
-
description: 'Write the new app to a custom target directory (always overrides positional name path).',
|
|
63
|
-
option: '--target-directory <path>'
|
|
64
|
-
}, {
|
|
65
|
-
aliases: [],
|
|
66
|
-
description: 'Overwrite files in a non-empty target directory without prompting.',
|
|
67
|
-
option: '--force'
|
|
68
|
-
}, {
|
|
69
|
-
aliases: [],
|
|
70
|
-
description: 'Install starter dependencies after writing files.',
|
|
71
|
-
option: '--install'
|
|
72
|
-
}, {
|
|
73
|
-
aliases: [],
|
|
74
|
-
description: 'Skip starter dependency installation.',
|
|
75
|
-
option: '--no-install'
|
|
76
|
-
}, {
|
|
77
|
-
aliases: [],
|
|
78
|
-
description: 'Initialize a git repository in the generated starter.',
|
|
79
|
-
option: '--git'
|
|
80
|
-
}, {
|
|
81
|
-
aliases: [],
|
|
82
|
-
description: 'Skip git repository initialization in the generated starter.',
|
|
83
|
-
option: '--no-git'
|
|
84
|
-
}, {
|
|
85
|
-
aliases: [],
|
|
86
|
-
description: 'Print the resolved scaffold plan without writing files, installing dependencies, or initializing git.',
|
|
87
|
-
option: '--print-plan'
|
|
88
|
-
}, {
|
|
89
|
-
aliases: ['-h'],
|
|
90
|
-
description: 'Show help for the new command.',
|
|
91
|
-
option: '--help'
|
|
92
|
-
}];
|
|
93
36
|
const SUPPORTED_PACKAGE_MANAGERS = new Set(['bun', 'npm', 'pnpm', 'yarn']);
|
|
94
37
|
const SUPPORTED_SHAPES = new Set(SUPPORTED_BOOTSTRAP_SHAPES);
|
|
95
38
|
const SUPPORTED_TRANSPORTS = new Set(SUPPORTED_BOOTSTRAP_TRANSPORTS);
|
|
@@ -249,24 +192,6 @@ function renderScaffoldPlanPreview(answers, resolvedTargetDirectory) {
|
|
|
249
192
|
return ['fluo new scaffold plan', '', `Project name: ${answers.projectName}`, `Target directory: ${answers.targetDirectory}`, `Resolved target: ${resolvedTargetDirectory}`, `Shape: ${answers.shape}`, `Runtime: ${answers.runtime}`, `Platform: ${answers.platform}`, `Transport: ${answers.transport}`, `Tooling preset: ${answers.tooling}`, `Topology: ${answers.topology.mode}${answers.topology.deferred ? ' (deferred)' : ''}`, `Starter recipe: ${bootstrapPlan.profile.id}`, `Emitter: ${bootstrapPlan.emitter.type}`, `Package manager: ${answers.packageManager}`, `Install dependencies: ${answers.installDependencies ? 'yes' : 'no'}`, `Initialize git: ${answers.initializeGit ? 'yes' : 'no'}`, '', 'Dependencies:', ` runtime: ${renderDependencyList(bootstrapPlan.dependencies.dependencies)}`, ` dev: ${renderDependencyList(bootstrapPlan.dependencies.devDependencies)}`, '', 'Side effects: none. Preview mode does not create files, install dependencies, or initialize git.'].join('\n');
|
|
250
193
|
}
|
|
251
194
|
|
|
252
|
-
/**
|
|
253
|
-
* Renders CLI help text for `fluo new`.
|
|
254
|
-
*
|
|
255
|
-
* @returns Stable help output for the scaffolding command.
|
|
256
|
-
*/
|
|
257
|
-
export function newUsage() {
|
|
258
|
-
return ['Usage: fluo new|create [project-name] [options]', '', 'Options', renderHelpTable(NEW_OPTION_HELP, [{
|
|
259
|
-
header: 'Option',
|
|
260
|
-
render: entry => entry.option
|
|
261
|
-
}, {
|
|
262
|
-
header: 'Aliases',
|
|
263
|
-
render: entry => renderAliasList(entry.aliases)
|
|
264
|
-
}, {
|
|
265
|
-
header: 'Description',
|
|
266
|
-
render: entry => entry.description
|
|
267
|
-
}]), '', 'Next steps:', ' cd <app-name>', ' pnpm dev # runs fluo dev from the generated package.json script', '', 'Docs: https://github.com/fluojs/fluo/tree/main/docs/getting-started/quick-start.md'].join('\n');
|
|
268
|
-
}
|
|
269
|
-
|
|
270
195
|
/**
|
|
271
196
|
* Executes `fluo new` with parsed arguments and scaffold options.
|
|
272
197
|
*
|
|
@@ -313,13 +238,14 @@ export async function runNewCommand(argv, runtime = {}) {
|
|
|
313
238
|
stdout.write(`${renderScaffoldPlanPreview(answers, targetDirectory)}\n`);
|
|
314
239
|
return 0;
|
|
315
240
|
}
|
|
241
|
+
const internalScaffoldOverrides = readInternalScaffoldOverrides(runtime);
|
|
316
242
|
const options = {
|
|
317
243
|
...answers,
|
|
318
|
-
dependencySource:
|
|
244
|
+
dependencySource: internalScaffoldOverrides.dependencySource,
|
|
319
245
|
force: parsed.force ?? runtime.force,
|
|
320
246
|
initializeGit: answers.initializeGit,
|
|
321
247
|
installDependencies: false,
|
|
322
|
-
repoRoot:
|
|
248
|
+
repoRoot: internalScaffoldOverrides.repoRoot,
|
|
323
249
|
skipInstall: true,
|
|
324
250
|
targetDirectory
|
|
325
251
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../../src/commands/scripts.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../../src/commands/scripts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAuC,MAAM,sBAAsB,CAAC;AAGpG,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAMF,KAAK,mBAAmB,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClG,kBAAkB,CAAC,EAAE,OAAO,kBAAkB,CAAC;IAC/C,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB,CAAC;AAKF,KAAK,aAAa,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;AAkmB/C;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAqB1D;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsFlI"}
|
package/dist/commands/scripts.js
CHANGED
|
@@ -3,7 +3,6 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
3
3
|
import { delimiter, dirname, join, resolve } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { createStudioDevtoolsNodeImport } from '../studio/runtime-config.js';
|
|
6
|
-
import { startStudioSidecar } from '../studio/sidecar.js';
|
|
7
6
|
import { SUPPORTED_PACKAGE_MANAGERS } from './package-manager.js';
|
|
8
7
|
const EMPTY_ENV = {};
|
|
9
8
|
const FAILURE_STDOUT_BUFFER_LIMIT = 16_384;
|
|
@@ -119,6 +118,12 @@ function defaultSpawnCommand(command, args, options) {
|
|
|
119
118
|
child.on('close', code => resolveExitCode(code ?? 1));
|
|
120
119
|
});
|
|
121
120
|
}
|
|
121
|
+
async function loadDefaultStudioSidecarFactory() {
|
|
122
|
+
const {
|
|
123
|
+
startStudioSidecar: startStudioSidecarImplementation
|
|
124
|
+
} = await import('../studio/sidecar.js');
|
|
125
|
+
return startStudioSidecarImplementation;
|
|
126
|
+
}
|
|
122
127
|
function buildNativeNodeWatchStep(passThrough) {
|
|
123
128
|
return {
|
|
124
129
|
command: 'node',
|
|
@@ -404,7 +409,8 @@ function assertStudioSupport(command, studio, projectRuntime, devRunner, rawWatc
|
|
|
404
409
|
throw new Error('fluo dev --studio requires the fluo-owned Node restart runner. Remove --raw-watch and use --runner fluo so Studio lifecycle events stay attached to the CLI restart boundary.');
|
|
405
410
|
}
|
|
406
411
|
}
|
|
407
|
-
function withStudioDryRunEnv(env, project, projectRuntime) {
|
|
412
|
+
function withStudioDryRunEnv(env, project, projectRuntime, studioPort) {
|
|
413
|
+
const portLabel = studioPort === undefined ? '<auto>' : String(studioPort);
|
|
408
414
|
return {
|
|
409
415
|
...env,
|
|
410
416
|
FLUO_STUDIO: '1',
|
|
@@ -412,7 +418,7 @@ function withStudioDryRunEnv(env, project, projectRuntime) {
|
|
|
412
418
|
FLUO_STUDIO_EPOCH: '<generated-at-runtime>',
|
|
413
419
|
FLUO_STUDIO_RUNTIME: projectRuntimeToStudioRuntime(projectRuntime),
|
|
414
420
|
FLUO_STUDIO_TOKEN: '<generated-at-runtime>',
|
|
415
|
-
FLUO_STUDIO_URL:
|
|
421
|
+
FLUO_STUDIO_URL: `http://127.0.0.1:${portLabel}`
|
|
416
422
|
};
|
|
417
423
|
}
|
|
418
424
|
function renderStep(step) {
|
|
@@ -635,10 +641,10 @@ export async function runScriptCommand(command, argv, runtime = {}) {
|
|
|
635
641
|
const verbose = parsed.verbose || isEnabledEnvironmentFlag(env.FLUO_VERBOSE);
|
|
636
642
|
let childEnv = withPipedReporterColorEnv(withProjectLocalBin(withDefaultNodeEnv(env, defaultNodeEnv), project.directory), reporterMode, stdout, stderr);
|
|
637
643
|
if (parsed.studio && parsed.dryRun) {
|
|
638
|
-
childEnv = withStudioDryRunEnv(childEnv, project, projectRuntime);
|
|
644
|
+
childEnv = withStudioDryRunEnv(childEnv, project, projectRuntime, parsed.studioPort);
|
|
639
645
|
}
|
|
640
646
|
if (command === 'dev' && parsed.studio && !parsed.dryRun) {
|
|
641
|
-
const studioSidecarFactory = runtime.startStudioSidecar ??
|
|
647
|
+
const studioSidecarFactory = runtime.startStudioSidecar ?? (await loadDefaultStudioSidecarFactory());
|
|
642
648
|
const studioSidecar = await studioSidecarFactory({
|
|
643
649
|
appId: projectDisplayName(project),
|
|
644
650
|
port: parsed.studioPort,
|
|
@@ -19,6 +19,11 @@ type RestartSignalTarget = {
|
|
|
19
19
|
type RestartWatcherFactory = (target: string, optionsOrListener: {
|
|
20
20
|
recursive: boolean;
|
|
21
21
|
} | ((event: string, filename: string | Buffer | null) => void), listener?: (event: string, filename: string | Buffer | null) => void) => FSWatcher;
|
|
22
|
+
type RestartSchedulerHandle = ReturnType<typeof setTimeout> | number;
|
|
23
|
+
type RestartScheduler = {
|
|
24
|
+
clear(handle: RestartSchedulerHandle): void;
|
|
25
|
+
set(callback: () => void, delayMs: number): RestartSchedulerHandle;
|
|
26
|
+
};
|
|
22
27
|
type ContentChangeGate = {
|
|
23
28
|
commitBaseline(paths: Iterable<string>): void;
|
|
24
29
|
hasMeaningfulChange(paths: Iterable<string>): boolean;
|
|
@@ -33,6 +38,7 @@ export type NodeRestartRunnerOptions = {
|
|
|
33
38
|
signalTarget?: RestartSignalTarget;
|
|
34
39
|
spawnChild?: RestartChildSpawner;
|
|
35
40
|
stderr?: RestartRunnerStream;
|
|
41
|
+
restartScheduler?: RestartScheduler;
|
|
36
42
|
stdout?: RestartRunnerStream;
|
|
37
43
|
watchTarget?: RestartWatcherFactory;
|
|
38
44
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-restart-runner.d.ts","sourceRoot":"","sources":["../../src/dev-runner/node-restart-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE9D,OAAO,EAA0D,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAKjG,KAAK,mBAAmB,GAAG;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,KAAK,mBAAmB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,KAAK,YAAY,CAAC;AACjJ,2EAA2E;AAC3E,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,oBAAoB,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9E,KAAK,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1C,KAAK,mBAAmB,GAAG;IACzB,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;IAC1D,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;CAC5D,CAAC;AAEF,KAAK,qBAAqB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,KAAK,SAAS,CAAC;AAE1O,KAAK,iBAAiB,GAAG;IACvB,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC9C,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;CACvD,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC,CAAC;AA6NF;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,gBAAgB,EAAE,MAAM,EAAE,cAAc,GAAE,MAAM,EAAoB,GAAG,iBAAiB,CAuB/H;AAkFD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"node-restart-runner.d.ts","sourceRoot":"","sources":["../../src/dev-runner/node-restart-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE9D,OAAO,EAA0D,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAKjG,KAAK,mBAAmB,GAAG;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,KAAK,mBAAmB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,KAAK,YAAY,CAAC;AACjJ,2EAA2E;AAC3E,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,oBAAoB,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9E,KAAK,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1C,KAAK,mBAAmB,GAAG;IACzB,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;IAC1D,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;CAC5D,CAAC;AAEF,KAAK,qBAAqB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,KAAK,SAAS,CAAC;AAE1O,KAAK,sBAAsB,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,MAAM,CAAC;AAErE,KAAK,gBAAgB,GAAG;IACtB,KAAK,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC5C,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,sBAAsB,CAAC;CACpE,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC9C,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;CACvD,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC,CAAC;AA6NF;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,gBAAgB,EAAE,MAAM,EAAE,cAAc,GAAE,MAAM,EAAoB,GAAG,iBAAiB,CAuB/H;AAkFD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAoP7F"}
|
|
@@ -100,7 +100,7 @@ function parseIgnorePatterns(env) {
|
|
|
100
100
|
return normalizeIgnorePatterns([...DEFAULT_IGNORES, ...configured]);
|
|
101
101
|
}
|
|
102
102
|
function matchesSegmentPattern(segment, pattern) {
|
|
103
|
-
if (pattern.startsWith('
|
|
103
|
+
if (pattern.startsWith('*')) {
|
|
104
104
|
return segment.endsWith(pattern.slice(1));
|
|
105
105
|
}
|
|
106
106
|
if (pattern.endsWith('*')) {
|
|
@@ -293,6 +293,10 @@ export async function runNodeRestartRunner(options) {
|
|
|
293
293
|
const spawnChild = options.spawnChild ?? spawn;
|
|
294
294
|
const stdout = options.stdout ?? process.stdout;
|
|
295
295
|
const stderr = options.stderr ?? process.stderr;
|
|
296
|
+
const restartScheduler = options.restartScheduler ?? {
|
|
297
|
+
clear: clearTimeout,
|
|
298
|
+
set: setTimeout
|
|
299
|
+
};
|
|
296
300
|
const watchTarget = options.watchTarget ?? watch;
|
|
297
301
|
const appArgs = options.appArgs ?? [];
|
|
298
302
|
const debounceMs = options.debounceMs ?? Number(env.FLUO_DEV_RELOAD_DEBOUNCE_MS ?? DEFAULT_DEBOUNCE_MS);
|
|
@@ -358,10 +362,10 @@ export async function runNodeRestartRunner(options) {
|
|
|
358
362
|
};
|
|
359
363
|
const scheduleRestart = (filePath, resolveExitCode, cleanup) => {
|
|
360
364
|
pendingRestartPaths.add(filePath);
|
|
361
|
-
if (restartTimer) {
|
|
362
|
-
|
|
365
|
+
if (restartTimer !== undefined) {
|
|
366
|
+
restartScheduler.clear(restartTimer);
|
|
363
367
|
}
|
|
364
|
-
restartTimer =
|
|
368
|
+
restartTimer = restartScheduler.set(() => {
|
|
365
369
|
const restartPaths = [...pendingRestartPaths];
|
|
366
370
|
pendingRestartPaths.clear();
|
|
367
371
|
restartTimer = undefined;
|
|
@@ -445,8 +449,8 @@ export async function runNodeRestartRunner(options) {
|
|
|
445
449
|
return;
|
|
446
450
|
}
|
|
447
451
|
cleanedUp = true;
|
|
448
|
-
if (restartTimer) {
|
|
449
|
-
|
|
452
|
+
if (restartTimer !== undefined) {
|
|
453
|
+
restartScheduler.clear(restartTimer);
|
|
450
454
|
restartTimer = undefined;
|
|
451
455
|
}
|
|
452
456
|
pendingRestartPaths.clear();
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { GeneratorManifestEntry } from './generators/manifest.js';
|
|
2
|
+
import type { GenerateOptions, GeneratorKind } from './types.js';
|
|
3
|
+
/** Describes how one generated artifact would interact with the workspace. */
|
|
4
|
+
export type GeneratePlanAction = 'create' | 'module-create' | 'module-unchanged' | 'module-update' | 'overwrite' | 'skip' | 'unchanged';
|
|
5
|
+
/** One path-level action reported by generate dry-run previews and structured results. */
|
|
6
|
+
export type GeneratePlanEntry = {
|
|
7
|
+
/** Planned action for this path. */
|
|
8
|
+
action: GeneratePlanAction;
|
|
9
|
+
/** Absolute path affected by the plan entry. */
|
|
10
|
+
path: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Structured result returned by {@link runGenerateCommand} for tooling-friendly automation.
|
|
14
|
+
*
|
|
15
|
+
* `generatedFiles` only includes files whose on-disk content changed during the command.
|
|
16
|
+
* `moduleRegistered` reports whether the target schematic participates in automatic module wiring,
|
|
17
|
+
* even when the target module file was already up to date.
|
|
18
|
+
*/
|
|
19
|
+
export type GenerateResult = {
|
|
20
|
+
generatedFiles: string[];
|
|
21
|
+
moduleRegistered: boolean;
|
|
22
|
+
modulePath: string | undefined;
|
|
23
|
+
nextStepHint: string;
|
|
24
|
+
plannedFiles: GeneratePlanEntry[];
|
|
25
|
+
wiringBehavior: GeneratorManifestEntry['wiringBehavior'];
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Generates one CLI schematic into a source directory and returns structured wiring metadata.
|
|
29
|
+
*
|
|
30
|
+
* The command keeps generation idempotent where possible: unchanged files are not rewritten, and
|
|
31
|
+
* auto-registered schematics reuse an existing module file when it already contains the required import
|
|
32
|
+
* and registration entry.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const result = runGenerateCommand('service', 'Post', './src');
|
|
37
|
+
*
|
|
38
|
+
* console.log(result.wiringBehavior);
|
|
39
|
+
* console.log(result.nextStepHint);
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @param kind Generator kind to execute.
|
|
43
|
+
* @param name Resource name supplied by the caller before normalization.
|
|
44
|
+
* @param baseDirectory Source directory that should receive the generated domain folder.
|
|
45
|
+
* @param options Optional generation flags that control overwrites, request DTO feature placement, and sibling-aware templates.
|
|
46
|
+
* @returns Structured file and wiring metadata for the completed generation run.
|
|
47
|
+
* @throws {Error} When the resource name is invalid, the generator kind is unknown, or the target module source cannot be updated safely.
|
|
48
|
+
*/
|
|
49
|
+
export declare function runGenerateCommand(kind: GeneratorKind, name: string, baseDirectory: string, options?: GenerateOptions): GenerateResult;
|
|
50
|
+
//# sourceMappingURL=generate-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-command.d.ts","sourceRoot":"","sources":["../src/generate-command.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAkB,MAAM,0BAA0B,CAAC;AAIvF,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAWjE,8EAA8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,eAAe,GAAG,kBAAkB,GAAG,eAAe,GAAG,WAAW,GAAG,MAAM,GAAG,WAAW,CAAC;AAExI,0FAA0F;AAC1F,MAAM,MAAM,iBAAiB,GAAG;IAC9B,oCAAoC;IACpC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAyIF;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC,cAAc,EAAE,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;CAC1D,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,cAAc,CAgE1I"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { basename, dirname, join, normalize, relative, resolve, sep } from 'node:path';
|
|
3
|
+
import { findGeneratorDefinition } from './generators/manifest.js';
|
|
4
|
+
import { ensureModuleImport, generateModuleFiles, registerInModule } from './generators/module.js';
|
|
5
|
+
import { toKebabCase, toPascalCase, toPlural } from './generators/utils.js';
|
|
6
|
+
function writeFileIfChanged(filePath, content) {
|
|
7
|
+
if (existsSync(filePath) && readFileSync(filePath, 'utf8') === content) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
writeFileSync(filePath, content, 'utf8');
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Describes how one generated artifact would interact with the workspace. */
|
|
15
|
+
|
|
16
|
+
/** One path-level action reported by generate dry-run previews and structured results. */
|
|
17
|
+
|
|
18
|
+
function planFileWrite(filePath, content, options) {
|
|
19
|
+
if (!existsSync(filePath)) {
|
|
20
|
+
return {
|
|
21
|
+
action: 'create',
|
|
22
|
+
path: filePath
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (!options.force) {
|
|
26
|
+
return {
|
|
27
|
+
action: 'skip',
|
|
28
|
+
path: filePath
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (readFileSync(filePath, 'utf8') === content) {
|
|
32
|
+
return {
|
|
33
|
+
action: 'unchanged',
|
|
34
|
+
path: filePath
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
action: 'overwrite',
|
|
39
|
+
path: filePath
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function planModuleWrite(modulePath, content) {
|
|
43
|
+
if (!existsSync(modulePath)) {
|
|
44
|
+
return {
|
|
45
|
+
action: 'module-create',
|
|
46
|
+
path: modulePath
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (readFileSync(modulePath, 'utf8') === content) {
|
|
50
|
+
return {
|
|
51
|
+
action: 'module-unchanged',
|
|
52
|
+
path: modulePath
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
action: 'module-update',
|
|
57
|
+
path: modulePath
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function createGeneratorOptions(kind, domainDirectory, kebab, options, resolvedBase) {
|
|
61
|
+
return {
|
|
62
|
+
...options,
|
|
63
|
+
e2eRootModuleImport: options.e2eRootModuleImport ?? (kind === 'e2e' ? resolveE2eRootModuleImport(domainDirectory, resolvedBase) : undefined),
|
|
64
|
+
hasRepo: options.hasRepo ?? (kind === 'service' ? existsSync(join(domainDirectory, `${kebab}.repo.ts`)) : undefined),
|
|
65
|
+
hasService: options.hasService ?? (kind === 'controller' ? existsSync(join(domainDirectory, `${kebab}.service.ts`)) : undefined)
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function toImportSpecifier(path) {
|
|
69
|
+
const normalized = path.split(sep).join('/');
|
|
70
|
+
return normalized.startsWith('.') ? normalized : `./${normalized}`;
|
|
71
|
+
}
|
|
72
|
+
function resolveE2eRootModuleImport(domainDirectory, resolvedBase) {
|
|
73
|
+
return toImportSpecifier(relative(domainDirectory, join(resolvedBase, 'app')));
|
|
74
|
+
}
|
|
75
|
+
function resolveDomainDirectory(kind, resolvedBase, kebab, options) {
|
|
76
|
+
if (kind === 'e2e') {
|
|
77
|
+
return basename(resolvedBase) === 'src' ? join(dirname(resolvedBase), 'test') : join(resolvedBase, 'test');
|
|
78
|
+
}
|
|
79
|
+
if (kind === 'request-dto' && options.targetFeature !== undefined) {
|
|
80
|
+
const normalizedFeature = options.targetFeature.trim();
|
|
81
|
+
const featureKebab = assertValidResourceName(normalizedFeature);
|
|
82
|
+
const featureDirectory = /^[A-Z]/u.test(normalizedFeature) ? toPlural(featureKebab) : featureKebab;
|
|
83
|
+
return join(resolvedBase, featureDirectory);
|
|
84
|
+
}
|
|
85
|
+
return join(resolvedBase, toPlural(kebab));
|
|
86
|
+
}
|
|
87
|
+
function assertValidResourceName(name) {
|
|
88
|
+
const kebab = toKebabCase(name);
|
|
89
|
+
if (name.trim().length === 0) {
|
|
90
|
+
throw new Error('Invalid resource name: name must not be empty.');
|
|
91
|
+
}
|
|
92
|
+
if (kebab !== normalize(kebab) || kebab.includes('/') || kebab.includes('\\') || kebab.includes('..')) {
|
|
93
|
+
throw new Error(`Invalid resource name "${name}": must not contain path separators or traversal sequences.`);
|
|
94
|
+
}
|
|
95
|
+
if (!/^[a-z0-9][a-z0-9-]*$/.test(kebab)) {
|
|
96
|
+
throw new Error(`Invalid resource name "${name}": use letters, numbers, spaces, underscores, or hyphens only.`);
|
|
97
|
+
}
|
|
98
|
+
return kebab;
|
|
99
|
+
}
|
|
100
|
+
function resolveModulePath(domainDirectory, name) {
|
|
101
|
+
const kebab = toKebabCase(name);
|
|
102
|
+
return join(domainDirectory, `${kebab}.module.ts`);
|
|
103
|
+
}
|
|
104
|
+
function readOrCreateModuleSource(modulePath, name) {
|
|
105
|
+
if (existsSync(modulePath)) {
|
|
106
|
+
return readFileSync(modulePath, 'utf8');
|
|
107
|
+
}
|
|
108
|
+
const [moduleFile] = generateModuleFiles(name);
|
|
109
|
+
if (!moduleFile) {
|
|
110
|
+
throw new Error(`Unable to generate module file for resource "${name}".`);
|
|
111
|
+
}
|
|
112
|
+
return moduleFile.content;
|
|
113
|
+
}
|
|
114
|
+
function buildUpdatedModuleSource(moduleSource, arrayKey, className, importPath) {
|
|
115
|
+
let source = moduleSource;
|
|
116
|
+
source = ensureModuleImport(source, className, importPath);
|
|
117
|
+
source = registerInModule(source, arrayKey, className);
|
|
118
|
+
return source;
|
|
119
|
+
}
|
|
120
|
+
function prepareModuleUpdate(domainDirectory, normalizedName, kind, classSuffix, arrayKey) {
|
|
121
|
+
const kebab = toKebabCase(normalizedName);
|
|
122
|
+
const modulePath = resolveModulePath(domainDirectory, normalizedName);
|
|
123
|
+
const className = `${toPascalCase(normalizedName)}${classSuffix}`;
|
|
124
|
+
const importPath = `${kebab}.${kind}`;
|
|
125
|
+
const moduleSource = readOrCreateModuleSource(modulePath, normalizedName);
|
|
126
|
+
return {
|
|
127
|
+
modulePath,
|
|
128
|
+
source: buildUpdatedModuleSource(moduleSource, arrayKey, className, importPath)
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Structured result returned by {@link runGenerateCommand} for tooling-friendly automation.
|
|
134
|
+
*
|
|
135
|
+
* `generatedFiles` only includes files whose on-disk content changed during the command.
|
|
136
|
+
* `moduleRegistered` reports whether the target schematic participates in automatic module wiring,
|
|
137
|
+
* even when the target module file was already up to date.
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Generates one CLI schematic into a source directory and returns structured wiring metadata.
|
|
142
|
+
*
|
|
143
|
+
* The command keeps generation idempotent where possible: unchanged files are not rewritten, and
|
|
144
|
+
* auto-registered schematics reuse an existing module file when it already contains the required import
|
|
145
|
+
* and registration entry.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* const result = runGenerateCommand('service', 'Post', './src');
|
|
150
|
+
*
|
|
151
|
+
* console.log(result.wiringBehavior);
|
|
152
|
+
* console.log(result.nextStepHint);
|
|
153
|
+
* ```
|
|
154
|
+
*
|
|
155
|
+
* @param kind Generator kind to execute.
|
|
156
|
+
* @param name Resource name supplied by the caller before normalization.
|
|
157
|
+
* @param baseDirectory Source directory that should receive the generated domain folder.
|
|
158
|
+
* @param options Optional generation flags that control overwrites, request DTO feature placement, and sibling-aware templates.
|
|
159
|
+
* @returns Structured file and wiring metadata for the completed generation run.
|
|
160
|
+
* @throws {Error} When the resource name is invalid, the generator kind is unknown, or the target module source cannot be updated safely.
|
|
161
|
+
*/
|
|
162
|
+
export function runGenerateCommand(kind, name, baseDirectory, options = {}) {
|
|
163
|
+
const normalizedName = name.trim();
|
|
164
|
+
const kebab = assertValidResourceName(normalizedName);
|
|
165
|
+
const generator = findGeneratorDefinition(kind);
|
|
166
|
+
const resolvedBase = resolve(baseDirectory);
|
|
167
|
+
const domainDirectory = resolveDomainDirectory(kind, resolvedBase, kebab, options);
|
|
168
|
+
const generatorOptions = createGeneratorOptions(kind, domainDirectory, kebab, options, resolvedBase);
|
|
169
|
+
const files = generator.factory(normalizedName, generatorOptions);
|
|
170
|
+
const moduleRegistration = 'moduleRegistration' in generator ? generator.moduleRegistration : undefined;
|
|
171
|
+
const moduleUpdate = moduleRegistration ? prepareModuleUpdate(domainDirectory, normalizedName, kind, moduleRegistration.classSuffix, moduleRegistration.arrayKey) : undefined;
|
|
172
|
+
const plannedFiles = files.map(file => planFileWrite(join(domainDirectory, file.path), file.content, options));
|
|
173
|
+
const modulePlan = moduleUpdate ? planModuleWrite(moduleUpdate.modulePath, moduleUpdate.source) : undefined;
|
|
174
|
+
if (options.dryRun) {
|
|
175
|
+
return {
|
|
176
|
+
generatedFiles: [],
|
|
177
|
+
moduleRegistered: moduleUpdate !== undefined,
|
|
178
|
+
modulePath: moduleUpdate?.modulePath,
|
|
179
|
+
nextStepHint: generator.nextStepHint,
|
|
180
|
+
plannedFiles: modulePlan ? [...plannedFiles, modulePlan] : plannedFiles,
|
|
181
|
+
wiringBehavior: generator.wiringBehavior
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
mkdirSync(domainDirectory, {
|
|
185
|
+
recursive: true
|
|
186
|
+
});
|
|
187
|
+
const writtenPaths = files.map(file => {
|
|
188
|
+
const filePath = join(domainDirectory, file.path);
|
|
189
|
+
if (!options.force && existsSync(filePath)) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
return writeFileIfChanged(filePath, file.content) ? filePath : null;
|
|
193
|
+
}).filter(filePath => filePath !== null);
|
|
194
|
+
let moduleRegistered = false;
|
|
195
|
+
let resolvedModulePath;
|
|
196
|
+
if (moduleUpdate && writeFileIfChanged(moduleUpdate.modulePath, moduleUpdate.source)) {
|
|
197
|
+
moduleRegistered = true;
|
|
198
|
+
resolvedModulePath = moduleUpdate.modulePath;
|
|
199
|
+
if (!writtenPaths.includes(moduleUpdate.modulePath)) {
|
|
200
|
+
writtenPaths.push(moduleUpdate.modulePath);
|
|
201
|
+
}
|
|
202
|
+
} else if (moduleUpdate) {
|
|
203
|
+
moduleRegistered = true;
|
|
204
|
+
resolvedModulePath = moduleUpdate.modulePath;
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
generatedFiles: writtenPaths,
|
|
208
|
+
moduleRegistered: moduleRegistered,
|
|
209
|
+
modulePath: resolvedModulePath,
|
|
210
|
+
nextStepHint: generator.nextStepHint,
|
|
211
|
+
plannedFiles: modulePlan ? [...plannedFiles, modulePlan] : plannedFiles,
|
|
212
|
+
wiringBehavior: generator.wiringBehavior
|
|
213
|
+
};
|
|
214
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { runCli, type CliRuntimeOptions } from './run-cli.js';
|
|
2
|
-
export { runGenerateCommand, type GeneratePlanAction, type GeneratePlanEntry, type GenerateResult } from './
|
|
3
|
-
export { inspectUsage, runInspectCommand, type InspectCommandRuntimeOptions } from './
|
|
4
|
-
export { newUsage, runNewCommand, type NewCommandRuntimeOptions } from './
|
|
2
|
+
export { runGenerateCommand, type GeneratePlanAction, type GeneratePlanEntry, type GenerateResult } from './public-generate.js';
|
|
3
|
+
export { inspectUsage, runInspectCommand, type InspectCommandRuntimeOptions } from './public-inspect.js';
|
|
4
|
+
export { newUsage, runNewCommand, type NewCommandRuntimeOptions } from './public-new.js';
|
|
5
5
|
export { CliPromptCancelledError } from './prompt-cancel.js';
|
|
6
6
|
export type { GenerateOptions, GeneratedFile, GeneratorKind, ModuleRegistration } from './types.js';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAChI,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,KAAK,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AACzG,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AACzF,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { runCli } from './run-cli.js';
|
|
2
|
-
export { runGenerateCommand } from './
|
|
3
|
-
export { inspectUsage, runInspectCommand } from './
|
|
4
|
-
export { newUsage, runNewCommand } from './
|
|
2
|
+
export { runGenerateCommand } from './public-generate.js';
|
|
3
|
+
export { inspectUsage, runInspectCommand } from './public-inspect.js';
|
|
4
|
+
export { newUsage, runNewCommand } from './public-new.js';
|
|
5
5
|
export { CliPromptCancelledError } from './prompt-cancel.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/new/scaffold.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/new/scaffold.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,YAAY,CAAC;AA03EnE;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,gBAAgB,EACzB,aAAa,SAAkB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,6BAAuB,CAAC"}
|