@fluojs/cli 1.0.0-beta.3 → 1.0.0-beta.5
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 +63 -0
- package/README.md +63 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +171 -4
- package/dist/commands/diagnostics.d.ts +15 -0
- package/dist/commands/diagnostics.d.ts.map +1 -0
- package/dist/commands/diagnostics.js +163 -0
- package/dist/commands/new.js +2 -2
- package/dist/commands/package-manager.d.ts +9 -0
- package/dist/commands/package-manager.d.ts.map +1 -0
- package/dist/commands/package-manager.js +63 -0
- package/dist/commands/package-workflow.d.ts +20 -0
- package/dist/commands/package-workflow.d.ts.map +1 -0
- package/dist/commands/package-workflow.js +137 -0
- package/dist/commands/scripts.d.ts +38 -0
- package/dist/commands/scripts.d.ts.map +1 -0
- package/dist/commands/scripts.js +418 -0
- package/dist/dev-runner/node-restart-runner.d.ts +50 -0
- package/dist/dev-runner/node-restart-runner.d.ts.map +1 -0
- package/dist/dev-runner/node-restart-runner.js +248 -0
- package/dist/generators/manifest.d.ts +24 -0
- package/dist/generators/manifest.d.ts.map +1 -1
- package/dist/generators/manifest.js +9 -0
- package/dist/generators/resource.d.ts +10 -0
- package/dist/generators/resource.d.ts.map +1 -0
- package/dist/generators/resource.js +23 -0
- package/dist/generators/templates/controller.ts.ejs +5 -1
- package/dist/generators/templates/request-dto.ts.ejs +3 -0
- package/dist/new/scaffold.d.ts.map +1 -1
- package/dist/new/scaffold.js +77 -27
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.d.ts.map +1 -1
- package/dist/update-check.js +7 -5
- package/package.json +2 -2
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { existsSync, readdirSync, readFileSync, statSync, watch } from 'node:fs';
|
|
4
|
+
import { basename, join, relative, sep } from 'node:path';
|
|
5
|
+
const DEFAULT_DEBOUNCE_MS = 100;
|
|
6
|
+
const DEFAULT_IGNORES = ['.cache', '.fluo', '.git', '.turbo', 'coverage', 'dist', 'node_modules', '*.swp', '*.swo', '*~', '.#*'];
|
|
7
|
+
const WATCH_FILES = ['.env', 'package.json', 'tsconfig.json', 'tsconfig.build.json'];
|
|
8
|
+
function normalizeIgnorePatterns(patterns) {
|
|
9
|
+
return patterns.map(pattern => pattern.trim()).filter(pattern => pattern.length > 0);
|
|
10
|
+
}
|
|
11
|
+
function parseIgnorePatterns(env) {
|
|
12
|
+
const configured = env.FLUO_DEV_WATCH_IGNORE?.split(',') ?? [];
|
|
13
|
+
return normalizeIgnorePatterns([...DEFAULT_IGNORES, ...configured]);
|
|
14
|
+
}
|
|
15
|
+
function matchesSegmentPattern(segment, pattern) {
|
|
16
|
+
if (pattern.startsWith('*.')) {
|
|
17
|
+
return segment.endsWith(pattern.slice(1));
|
|
18
|
+
}
|
|
19
|
+
if (pattern.endsWith('*')) {
|
|
20
|
+
return segment.startsWith(pattern.slice(0, -1));
|
|
21
|
+
}
|
|
22
|
+
return segment === pattern;
|
|
23
|
+
}
|
|
24
|
+
function shouldIgnorePath(filePath, projectDirectory, ignorePatterns) {
|
|
25
|
+
const relativePath = relative(projectDirectory, filePath);
|
|
26
|
+
if (relativePath.startsWith('..')) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
const segments = relativePath.split(sep).filter(Boolean);
|
|
30
|
+
return segments.some(segment => ignorePatterns.some(pattern => matchesSegmentPattern(segment, pattern)));
|
|
31
|
+
}
|
|
32
|
+
function hashFileContent(filePath) {
|
|
33
|
+
try {
|
|
34
|
+
const stats = statSync(filePath);
|
|
35
|
+
if (!stats.isFile()) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
return createHash('sha256').update(readFileSync(filePath)).digest('hex');
|
|
39
|
+
} catch (_error) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function collectContentPaths(filePath, projectDirectory, ignorePatterns, paths) {
|
|
44
|
+
if (shouldIgnorePath(filePath, projectDirectory, ignorePatterns)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const stats = statSync(filePath);
|
|
49
|
+
if (stats.isDirectory()) {
|
|
50
|
+
for (const entry of readdirSync(filePath)) {
|
|
51
|
+
collectContentPaths(join(filePath, entry), projectDirectory, ignorePatterns, paths);
|
|
52
|
+
}
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (stats.isFile()) {
|
|
56
|
+
paths.add(filePath);
|
|
57
|
+
}
|
|
58
|
+
} catch (_error) {
|
|
59
|
+
paths.add(filePath);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function collectWatchedContentPaths(paths, projectDirectory, ignorePatterns) {
|
|
63
|
+
const collected = new Set();
|
|
64
|
+
for (const filePath of paths) {
|
|
65
|
+
collectContentPaths(filePath, projectDirectory, ignorePatterns, collected);
|
|
66
|
+
}
|
|
67
|
+
return collected;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Creates a content-diff gate for fluo-owned dev restarts.
|
|
72
|
+
*
|
|
73
|
+
* @param projectDirectory Project root used for ignore matching.
|
|
74
|
+
* @param ignorePatterns Additional or default ignore patterns to apply before hashing.
|
|
75
|
+
* @returns A gate that reports whether watched paths changed by content rather than by filesystem event alone.
|
|
76
|
+
*/
|
|
77
|
+
export function createContentChangeGate(projectDirectory, ignorePatterns = DEFAULT_IGNORES) {
|
|
78
|
+
const normalizedIgnores = normalizeIgnorePatterns(ignorePatterns);
|
|
79
|
+
const hashes = new Map();
|
|
80
|
+
return {
|
|
81
|
+
commitBaseline(paths) {
|
|
82
|
+
for (const filePath of collectWatchedContentPaths(paths, projectDirectory, normalizedIgnores)) {
|
|
83
|
+
hashes.set(filePath, hashFileContent(filePath));
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
hasMeaningfulChange(paths) {
|
|
87
|
+
for (const filePath of collectWatchedContentPaths(paths, projectDirectory, normalizedIgnores)) {
|
|
88
|
+
const nextHash = hashFileContent(filePath);
|
|
89
|
+
const previousHash = hashes.get(filePath);
|
|
90
|
+
if (previousHash !== nextHash) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function getWatchTargets(projectDirectory) {
|
|
99
|
+
return [join(projectDirectory, 'src'), ...WATCH_FILES.map(fileName => join(projectDirectory, fileName))].filter(target => existsSync(target));
|
|
100
|
+
}
|
|
101
|
+
function stopChild(child) {
|
|
102
|
+
if (child && child.exitCode === null && !child.killed) {
|
|
103
|
+
child.kill('SIGTERM');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Runs the Node.js development lifecycle through fluo-owned restart supervision.
|
|
109
|
+
*
|
|
110
|
+
* @param options Runner dependencies and project settings.
|
|
111
|
+
* @returns A promise that resolves with the final child exit code when the runner stops.
|
|
112
|
+
*/
|
|
113
|
+
export async function runNodeRestartRunner(options) {
|
|
114
|
+
const projectDirectory = options.projectDirectory ?? process.cwd();
|
|
115
|
+
const env = options.env;
|
|
116
|
+
const signalTarget = options.signalTarget ?? process;
|
|
117
|
+
const spawnChild = options.spawnChild ?? spawn;
|
|
118
|
+
const stdout = options.stdout ?? process.stdout;
|
|
119
|
+
const stderr = options.stderr ?? process.stderr;
|
|
120
|
+
const watchTarget = options.watchTarget ?? watch;
|
|
121
|
+
const appArgs = options.appArgs ?? [];
|
|
122
|
+
const debounceMs = options.debounceMs ?? Number(env.FLUO_DEV_RELOAD_DEBOUNCE_MS ?? DEFAULT_DEBOUNCE_MS);
|
|
123
|
+
const gate = createContentChangeGate(projectDirectory, parseIgnorePatterns(env));
|
|
124
|
+
const watchTargets = getWatchTargets(projectDirectory);
|
|
125
|
+
let child;
|
|
126
|
+
const pendingRestartPaths = new Set();
|
|
127
|
+
const restartAfterClosePaths = new Set();
|
|
128
|
+
let restartTimer;
|
|
129
|
+
let restarting = false;
|
|
130
|
+
let stopping = false;
|
|
131
|
+
const startChild = (resolveExitCode, cleanup) => {
|
|
132
|
+
child = spawnChild(process.execPath, ['--env-file=.env', '--import', 'tsx', 'src/main.ts', ...appArgs], {
|
|
133
|
+
cwd: projectDirectory,
|
|
134
|
+
env,
|
|
135
|
+
stdio: 'inherit'
|
|
136
|
+
});
|
|
137
|
+
child.once('close', code => {
|
|
138
|
+
if (restarting) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (stopping) {
|
|
142
|
+
cleanup();
|
|
143
|
+
resolveExitCode(code ?? 0);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
cleanup();
|
|
147
|
+
resolveExitCode(code ?? 1);
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
const scheduleRestart = (filePath, resolveExitCode, cleanup) => {
|
|
151
|
+
pendingRestartPaths.add(filePath);
|
|
152
|
+
if (restartTimer) {
|
|
153
|
+
clearTimeout(restartTimer);
|
|
154
|
+
}
|
|
155
|
+
restartTimer = setTimeout(() => {
|
|
156
|
+
const restartPaths = [...pendingRestartPaths];
|
|
157
|
+
pendingRestartPaths.clear();
|
|
158
|
+
restartTimer = undefined;
|
|
159
|
+
if (!gate.hasMeaningfulChange(restartPaths)) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
stdout.write(`[fluo] restarting after content change: ${relative(projectDirectory, restartPaths[restartPaths.length - 1] ?? projectDirectory)}\n`);
|
|
163
|
+
const previousChild = child;
|
|
164
|
+
const startReplacementChild = () => {
|
|
165
|
+
startChild(resolveExitCode, cleanup);
|
|
166
|
+
gate.commitBaseline(restartPaths);
|
|
167
|
+
};
|
|
168
|
+
if (previousChild) {
|
|
169
|
+
for (const restartPath of restartPaths) {
|
|
170
|
+
restartAfterClosePaths.add(restartPath);
|
|
171
|
+
}
|
|
172
|
+
if (restarting) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
restarting = true;
|
|
176
|
+
previousChild.once('close', () => {
|
|
177
|
+
const committedRestartPaths = [...restartAfterClosePaths];
|
|
178
|
+
restartAfterClosePaths.clear();
|
|
179
|
+
restarting = false;
|
|
180
|
+
if (stopping) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
startChild(resolveExitCode, cleanup);
|
|
184
|
+
gate.commitBaseline(committedRestartPaths);
|
|
185
|
+
});
|
|
186
|
+
stopChild(previousChild);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
startReplacementChild();
|
|
191
|
+
} finally {
|
|
192
|
+
restarting = false;
|
|
193
|
+
}
|
|
194
|
+
}, debounceMs);
|
|
195
|
+
};
|
|
196
|
+
gate.commitBaseline(watchTargets);
|
|
197
|
+
return new Promise(resolveExitCode => {
|
|
198
|
+
const watchers = [];
|
|
199
|
+
let cleanedUp = false;
|
|
200
|
+
const stop = () => {
|
|
201
|
+
stopping = true;
|
|
202
|
+
cleanup();
|
|
203
|
+
stopChild(child);
|
|
204
|
+
};
|
|
205
|
+
const cleanup = () => {
|
|
206
|
+
if (cleanedUp) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
cleanedUp = true;
|
|
210
|
+
if (restartTimer) {
|
|
211
|
+
clearTimeout(restartTimer);
|
|
212
|
+
restartTimer = undefined;
|
|
213
|
+
}
|
|
214
|
+
pendingRestartPaths.clear();
|
|
215
|
+
restartAfterClosePaths.clear();
|
|
216
|
+
for (const watcher of watchers.splice(0)) {
|
|
217
|
+
watcher.close();
|
|
218
|
+
}
|
|
219
|
+
signalTarget.off('SIGINT', stop);
|
|
220
|
+
signalTarget.off('SIGTERM', stop);
|
|
221
|
+
};
|
|
222
|
+
startChild(resolveExitCode, cleanup);
|
|
223
|
+
for (const target of watchTargets) {
|
|
224
|
+
try {
|
|
225
|
+
const stats = statSync(target);
|
|
226
|
+
const watchOptions = {
|
|
227
|
+
recursive: stats.isDirectory()
|
|
228
|
+
};
|
|
229
|
+
const listener = (_event, filename) => {
|
|
230
|
+
const fileName = filename ? String(filename) : basename(target);
|
|
231
|
+
scheduleRestart(stats.isDirectory() ? join(target, fileName) : target, resolveExitCode, cleanup);
|
|
232
|
+
};
|
|
233
|
+
try {
|
|
234
|
+
watchers.push(watchTarget(target, watchOptions, listener));
|
|
235
|
+
} catch (error) {
|
|
236
|
+
if (!stats.isDirectory()) {
|
|
237
|
+
throw error;
|
|
238
|
+
}
|
|
239
|
+
watchers.push(watchTarget(target, listener));
|
|
240
|
+
}
|
|
241
|
+
} catch (error) {
|
|
242
|
+
stderr.write(`[fluo] unable to watch ${target}: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
signalTarget.once('SIGINT', stop);
|
|
246
|
+
signalTarget.once('SIGTERM', stop);
|
|
247
|
+
});
|
|
248
|
+
}
|
|
@@ -126,6 +126,14 @@ export declare const builtInGeneratorCollection: {
|
|
|
126
126
|
readonly nextStepHint: "Import the DTO in a controller and add it as a parameter with @FromBody or @FromQuery.";
|
|
127
127
|
readonly schematic: "request-dto";
|
|
128
128
|
readonly wiringBehavior: "files-only";
|
|
129
|
+
}, {
|
|
130
|
+
readonly aliases: readonly ["resrc"];
|
|
131
|
+
readonly description: "Generate a full resource slice with module, controller, service, repository, and DTO stubs.";
|
|
132
|
+
readonly factory: (name: string, options: import("../generator-types.js").GenerateOptions | undefined) => import("../generator-types.js").GeneratedFile[];
|
|
133
|
+
readonly kind: "resource";
|
|
134
|
+
readonly nextStepHint: "Run 'pnpm typecheck' and wire the resource module into a parent module when ready.";
|
|
135
|
+
readonly schematic: "resource";
|
|
136
|
+
readonly wiringBehavior: "files-only";
|
|
129
137
|
}, {
|
|
130
138
|
readonly aliases: readonly ["res"];
|
|
131
139
|
readonly description: "Generate a response DTO for typed response payloads (files only — use it as a controller return type).";
|
|
@@ -230,6 +238,14 @@ export declare const generatorCollections: readonly [{
|
|
|
230
238
|
readonly nextStepHint: "Import the DTO in a controller and add it as a parameter with @FromBody or @FromQuery.";
|
|
231
239
|
readonly schematic: "request-dto";
|
|
232
240
|
readonly wiringBehavior: "files-only";
|
|
241
|
+
}, {
|
|
242
|
+
readonly aliases: readonly ["resrc"];
|
|
243
|
+
readonly description: "Generate a full resource slice with module, controller, service, repository, and DTO stubs.";
|
|
244
|
+
readonly factory: (name: string, options: import("../generator-types.js").GenerateOptions | undefined) => import("../generator-types.js").GeneratedFile[];
|
|
245
|
+
readonly kind: "resource";
|
|
246
|
+
readonly nextStepHint: "Run 'pnpm typecheck' and wire the resource module into a parent module when ready.";
|
|
247
|
+
readonly schematic: "resource";
|
|
248
|
+
readonly wiringBehavior: "files-only";
|
|
233
249
|
}, {
|
|
234
250
|
readonly aliases: readonly ["res"];
|
|
235
251
|
readonly description: "Generate a response DTO for typed response payloads (files only — use it as a controller return type).";
|
|
@@ -332,6 +348,14 @@ export declare const generatorManifest: readonly [{
|
|
|
332
348
|
readonly nextStepHint: "Import the DTO in a controller and add it as a parameter with @FromBody or @FromQuery.";
|
|
333
349
|
readonly schematic: "request-dto";
|
|
334
350
|
readonly wiringBehavior: "files-only";
|
|
351
|
+
}, {
|
|
352
|
+
readonly aliases: readonly ["resrc"];
|
|
353
|
+
readonly description: "Generate a full resource slice with module, controller, service, repository, and DTO stubs.";
|
|
354
|
+
readonly factory: (name: string, options: import("../generator-types.js").GenerateOptions | undefined) => import("../generator-types.js").GeneratedFile[];
|
|
355
|
+
readonly kind: "resource";
|
|
356
|
+
readonly nextStepHint: "Run 'pnpm typecheck' and wire the resource module into a parent module when ready.";
|
|
357
|
+
readonly schematic: "resource";
|
|
358
|
+
readonly wiringBehavior: "files-only";
|
|
335
359
|
}, {
|
|
336
360
|
readonly aliases: readonly ["res"];
|
|
337
361
|
readonly description: "Generate a response DTO for typed response payloads (files only — use it as a controller return type).";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/generators/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAyB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/generators/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAyB,MAAM,uBAAuB,CAAC;AAarF,yFAAyF;AACzF,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,WAAW,GAAG,YAAY,CAAC;AAExE,KAAK,4BAA4B,GAAG;IAClC,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,8EAA8E;AAC9E,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,4BAA4B,CAAC;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,iBAAiB,GAAG,YAAY,CAAC;CAClD,CAAC;AAEF,4FAA4F;AAC5F,MAAM,MAAM,mBAAmB,GAAG;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC9C,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;EAKkB,CAAC;AAsGtD,6EAA6E;AAC7E,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKC,CAAC;AAEzC,2FAA2F;AAC3F,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAiF,CAAC;AAEnH,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAwC,CAAC;AAEvE,kFAAkF;AAClF,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAcrE;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,aAAa,GAAG,mBAAmB,CAOhF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,SAAS,mBAAmB,EAAE,CAEzE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,GAAE,MAAsC,GAAG,SAAS,mBAAmB,EAAE,CAO7H;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAMzF"}
|
|
@@ -5,6 +5,7 @@ import { generateMiddlewareFiles } from './middleware.js';
|
|
|
5
5
|
import { generateModuleFiles } from './module.js';
|
|
6
6
|
import { generateRepoFiles } from './repository.js';
|
|
7
7
|
import { generateRequestDtoFiles } from './request-dto.js';
|
|
8
|
+
import { generateResourceFiles } from './resource.js';
|
|
8
9
|
import { generateResponseDtoFiles } from './response-dto.js';
|
|
9
10
|
import { generateServiceFiles } from './service.js';
|
|
10
11
|
|
|
@@ -113,6 +114,14 @@ const builtInGeneratorDefinitions = [{
|
|
|
113
114
|
nextStepHint: 'Import the DTO in a controller and add it as a parameter with @FromBody or @FromQuery.',
|
|
114
115
|
schematic: 'request-dto',
|
|
115
116
|
wiringBehavior: 'files-only'
|
|
117
|
+
}, {
|
|
118
|
+
aliases: ['resrc'],
|
|
119
|
+
description: 'Generate a full resource slice with module, controller, service, repository, and DTO stubs.',
|
|
120
|
+
factory: (name, options) => generateResourceFiles(name, options),
|
|
121
|
+
kind: 'resource',
|
|
122
|
+
nextStepHint: "Run 'pnpm typecheck' and wire the resource module into a parent module when ready.",
|
|
123
|
+
schematic: 'resource',
|
|
124
|
+
wiringBehavior: 'files-only'
|
|
116
125
|
}, {
|
|
117
126
|
aliases: ['res'],
|
|
118
127
|
description: 'Generate a response DTO for typed response payloads (files only — use it as a controller return type).',
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { GenerateOptions, GeneratedFile } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generate a complete feature resource slice.
|
|
4
|
+
*
|
|
5
|
+
* @param name The resource name.
|
|
6
|
+
* @param options The generation options.
|
|
7
|
+
* @returns The generated resource files.
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateResourceFiles(name: string, options?: GenerateOptions): GeneratedFile[];
|
|
10
|
+
//# sourceMappingURL=resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/generators/resource.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AASlE;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,aAAa,EAAE,CASlG"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { generateControllerFiles } from './controller.js';
|
|
2
|
+
import { generateModuleFiles } from './module.js';
|
|
3
|
+
import { generateRepoFiles } from './repository.js';
|
|
4
|
+
import { generateRequestDtoFiles } from './request-dto.js';
|
|
5
|
+
import { generateResponseDtoFiles } from './response-dto.js';
|
|
6
|
+
import { generateServiceFiles } from './service.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Generate a complete feature resource slice.
|
|
10
|
+
*
|
|
11
|
+
* @param name The resource name.
|
|
12
|
+
* @param options The generation options.
|
|
13
|
+
* @returns The generated resource files.
|
|
14
|
+
*/
|
|
15
|
+
export function generateResourceFiles(name, options = {}) {
|
|
16
|
+
return [...generateModuleFiles(name), ...generateRepoFiles(name, options), ...generateServiceFiles(name, {
|
|
17
|
+
...options,
|
|
18
|
+
hasRepo: true
|
|
19
|
+
}), ...generateControllerFiles(name, {
|
|
20
|
+
...options,
|
|
21
|
+
hasService: true
|
|
22
|
+
}), ...generateRequestDtoFiles(`Create ${name}`), ...generateResponseDtoFiles(name)];
|
|
23
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<% if (hasService) { %>
|
|
2
|
-
import { Inject } from '@fluojs/core';
|
|
2
|
+
import { ensureMetadataSymbol, Inject } from '@fluojs/core';
|
|
3
|
+
<% } else { %>
|
|
4
|
+
import { ensureMetadataSymbol } from '@fluojs/core';
|
|
3
5
|
<% } %>
|
|
4
6
|
import { Controller, Get } from '@fluojs/http';
|
|
5
7
|
|
|
@@ -7,6 +9,8 @@ import { Controller, Get } from '@fluojs/http';
|
|
|
7
9
|
import { <%- service %> } from './<%- kebab %>.service';
|
|
8
10
|
<% } %>
|
|
9
11
|
|
|
12
|
+
ensureMetadataSymbol();
|
|
13
|
+
|
|
10
14
|
@Controller('/<%- kebab %>')
|
|
11
15
|
<% if (hasService) { %>
|
|
12
16
|
@Inject(<%- service %>)
|
|
@@ -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;AAqnEnE;;;;;;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"}
|
package/dist/new/scaffold.js
CHANGED
|
@@ -27,20 +27,21 @@ const PUBLISHED_RUNTIME_DEPENDENCIES = {
|
|
|
27
27
|
nats: '^2.29.3'
|
|
28
28
|
};
|
|
29
29
|
const PUBLISHED_INTERNAL_DEPENDENCIES = {
|
|
30
|
-
'@fluojs/cli': '^1.0.0-beta.
|
|
31
|
-
'@fluojs/config': '^1.0.0-beta.
|
|
32
|
-
'@fluojs/core': '^1.0.0-beta.
|
|
33
|
-
'@fluojs/di': '^1.0.0-beta.
|
|
34
|
-
'@fluojs/http': '^1.0.0-beta.
|
|
35
|
-
'@fluojs/microservices': '^1.0.0-beta.
|
|
36
|
-
'@fluojs/platform-bun': '^1.0.0-beta.
|
|
37
|
-
'@fluojs/platform-cloudflare-workers': '^1.0.0-beta.
|
|
38
|
-
'@fluojs/platform-deno': '^1.0.0-beta.
|
|
39
|
-
'@fluojs/platform-express': '^1.0.0-beta.
|
|
40
|
-
'@fluojs/platform-fastify': '^1.0.0-beta.
|
|
41
|
-
'@fluojs/platform-nodejs': '^1.0.0-beta.
|
|
42
|
-
'@fluojs/runtime': '^1.0.0-beta.
|
|
43
|
-
'@fluojs/testing': '^1.0.0-beta.
|
|
30
|
+
'@fluojs/cli': '^1.0.0-beta.3',
|
|
31
|
+
'@fluojs/config': '^1.0.0-beta.5',
|
|
32
|
+
'@fluojs/core': '^1.0.0-beta.3',
|
|
33
|
+
'@fluojs/di': '^1.0.0-beta.6',
|
|
34
|
+
'@fluojs/http': '^1.0.0-beta.9',
|
|
35
|
+
'@fluojs/microservices': '^1.0.0-beta.3',
|
|
36
|
+
'@fluojs/platform-bun': '^1.0.0-beta.6',
|
|
37
|
+
'@fluojs/platform-cloudflare-workers': '^1.0.0-beta.2',
|
|
38
|
+
'@fluojs/platform-deno': '^1.0.0-beta.3',
|
|
39
|
+
'@fluojs/platform-express': '^1.0.0-beta.6',
|
|
40
|
+
'@fluojs/platform-fastify': '^1.0.0-beta.8',
|
|
41
|
+
'@fluojs/platform-nodejs': '^1.0.0-beta.4',
|
|
42
|
+
'@fluojs/runtime': '^1.0.0-beta.9',
|
|
43
|
+
'@fluojs/testing': '^1.0.0-beta.2',
|
|
44
|
+
'@fluojs/validation': '^1.0.0-beta.2'
|
|
44
45
|
};
|
|
45
46
|
function describeApplicationStarter(options) {
|
|
46
47
|
if (options.runtime === 'bun') {
|
|
@@ -146,32 +147,36 @@ function createProjectScripts(bootstrapPlan) {
|
|
|
146
147
|
switch (bootstrapPlan.profile.id) {
|
|
147
148
|
case 'application-bun-bun-http':
|
|
148
149
|
return {
|
|
149
|
-
build: '
|
|
150
|
-
dev: '
|
|
150
|
+
build: 'fluo build',
|
|
151
|
+
dev: 'fluo dev',
|
|
152
|
+
start: 'fluo start',
|
|
151
153
|
test: 'vitest run',
|
|
152
154
|
'test:watch': 'vitest',
|
|
153
155
|
typecheck: 'tsc -p tsconfig.json --noEmit'
|
|
154
156
|
};
|
|
155
157
|
case 'application-deno-deno-http':
|
|
156
158
|
return {
|
|
157
|
-
build: '
|
|
158
|
-
dev: '
|
|
159
|
+
build: 'fluo build',
|
|
160
|
+
dev: 'fluo dev',
|
|
161
|
+
start: 'fluo start',
|
|
159
162
|
test: 'deno test --allow-env --allow-net',
|
|
160
163
|
'test:watch': 'deno test --allow-env --allow-net --watch',
|
|
161
164
|
typecheck: 'deno check src/main.ts src/app.test.ts'
|
|
162
165
|
};
|
|
163
166
|
case 'application-cloudflare-workers-cloudflare-workers-http':
|
|
164
167
|
return {
|
|
165
|
-
build: '
|
|
166
|
-
dev: '
|
|
168
|
+
build: 'fluo build',
|
|
169
|
+
dev: 'fluo dev',
|
|
170
|
+
start: 'fluo start',
|
|
167
171
|
test: 'vitest run',
|
|
168
172
|
'test:watch': 'vitest',
|
|
169
173
|
typecheck: 'tsc -p tsconfig.json --noEmit'
|
|
170
174
|
};
|
|
171
175
|
default:
|
|
172
176
|
return {
|
|
173
|
-
build: '
|
|
174
|
-
dev: '
|
|
177
|
+
build: 'fluo build',
|
|
178
|
+
dev: 'fluo dev',
|
|
179
|
+
start: 'fluo start',
|
|
175
180
|
test: 'vitest run',
|
|
176
181
|
'test:watch': 'vitest',
|
|
177
182
|
typecheck: 'tsc -p tsconfig.json --noEmit'
|
|
@@ -280,9 +285,49 @@ function createBabelConfig() {
|
|
|
280
285
|
`;
|
|
281
286
|
}
|
|
282
287
|
function createViteConfig() {
|
|
283
|
-
return `import {
|
|
288
|
+
return `import { transformAsync } from '@babel/core';
|
|
289
|
+
import type { Plugin } from 'vite';
|
|
290
|
+
import { defineConfig } from 'vite';
|
|
291
|
+
|
|
292
|
+
function fluoDecoratorsPlugin(): Plugin {
|
|
293
|
+
return {
|
|
294
|
+
name: 'fluo-babel-decorators',
|
|
295
|
+
async transform(code: string, id: string) {
|
|
296
|
+
if (!id.endsWith('.ts') || id.includes('.test.')) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const result = await transformAsync(code, {
|
|
301
|
+
babelrc: false,
|
|
302
|
+
configFile: false,
|
|
303
|
+
filename: id,
|
|
304
|
+
plugins: [['@babel/plugin-proposal-decorators', { version: '2023-11' }]],
|
|
305
|
+
presets: [['@babel/preset-typescript', { allowDeclareFields: true }]],
|
|
306
|
+
sourceMaps: true,
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
if (!result?.code) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return { code: result.code, map: result.map };
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
}
|
|
284
317
|
|
|
285
318
|
export default defineConfig({
|
|
319
|
+
plugins: [fluoDecoratorsPlugin()],
|
|
320
|
+
build: {
|
|
321
|
+
emptyOutDir: true,
|
|
322
|
+
outDir: 'dist',
|
|
323
|
+
rollupOptions: {
|
|
324
|
+
output: {
|
|
325
|
+
entryFileNames: 'main.js',
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
ssr: 'src/main.ts',
|
|
329
|
+
target: 'node20',
|
|
330
|
+
},
|
|
286
331
|
server: {
|
|
287
332
|
port: 5173,
|
|
288
333
|
},
|
|
@@ -327,7 +372,7 @@ Generated by @fluojs/cli.
|
|
|
327
372
|
- Starter contract: ${starterContract}
|
|
328
373
|
- Default baseline: when you omit \`--platform\`, \`fluo new\` still generates the Node.js + Fastify HTTP starter by default
|
|
329
374
|
- Broader runtime/adapter package coverage is documented in the fluo docs and package READMEs; this generated starter intentionally describes only the wired starter path above
|
|
330
|
-
- Package manager: install/run commands can use ${options.packageManager};
|
|
375
|
+
- Package manager: install/run commands can use ${options.packageManager}; ${createRunCommand(options.packageManager, 'dev')}, ${createRunCommand(options.packageManager, 'build')}, and ${createRunCommand(options.packageManager, 'start')} delegate to \`fluo dev\`, \`fluo build\`, and \`fluo start\`, which own the generated runtime lifecycle and default \`NODE_ENV\` when unset
|
|
331
376
|
- Runtime dependency set: generated manifest entries match the selected runtime contract instead of inheriting the Node-only starter recipe
|
|
332
377
|
${corsLine}
|
|
333
378
|
- Observability: /health and /ready endpoints are included by default
|
|
@@ -337,6 +382,7 @@ ${corsLine}
|
|
|
337
382
|
## Commands
|
|
338
383
|
|
|
339
384
|
- Dev: ${createRunCommand(options.packageManager, 'dev')}
|
|
385
|
+
- Start: ${createRunCommand(options.packageManager, 'start')}
|
|
340
386
|
- Build: ${createRunCommand(options.packageManager, 'build')}
|
|
341
387
|
- Typecheck: ${createRunCommand(options.packageManager, 'typecheck')}
|
|
342
388
|
- Test: ${createRunCommand(options.packageManager, 'test')}
|
|
@@ -451,7 +497,7 @@ Generated by @fluojs/cli.
|
|
|
451
497
|
- Transport: \`${starter.readmeTransportLabel}\` is the generated runnable starter contract for this project
|
|
452
498
|
- Runtime: \`node\`
|
|
453
499
|
- Platform: \`none\` because the microservice starter boots through \`@fluojs/microservices\`, not an HTTP adapter
|
|
454
|
-
- Package manager: install/run commands can use ${options.packageManager}; ${starter.packageManagerNote}
|
|
500
|
+
- Package manager: install/run commands can use ${options.packageManager}; ${createRunCommand(options.packageManager, 'dev')}, ${createRunCommand(options.packageManager, 'build')}, and ${createRunCommand(options.packageManager, 'start')} delegate to \`fluo dev\`, \`fluo build\`, and \`fluo start\`, which own the generated runtime lifecycle and default \`NODE_ENV\` when unset; ${starter.packageManagerNote}
|
|
455
501
|
- Messaging contract: \`src/math/math.handler.ts\` exposes a \`${starter.pattern}\` message pattern and the generated tests verify it through an in-memory transport so the starter stays testable without external brokers
|
|
456
502
|
- Entrypoint contract: ${starter.entrypointNote}
|
|
457
503
|
- Starter contract note: ${starter.starterNote}
|
|
@@ -460,6 +506,7 @@ Generated by @fluojs/cli.
|
|
|
460
506
|
## Commands
|
|
461
507
|
|
|
462
508
|
- Dev: ${createRunCommand(options.packageManager, 'dev')}
|
|
509
|
+
- Start: ${createRunCommand(options.packageManager, 'start')}
|
|
463
510
|
- Build: ${createRunCommand(options.packageManager, 'build')}
|
|
464
511
|
- Typecheck: ${createRunCommand(options.packageManager, 'typecheck')}
|
|
465
512
|
- Test: ${createRunCommand(options.packageManager, 'test')}
|
|
@@ -610,12 +657,14 @@ describe('HealthService', () => {
|
|
|
610
657
|
`;
|
|
611
658
|
}
|
|
612
659
|
function createHealthControllerFile(importSuffix = '') {
|
|
613
|
-
return `import { Inject } from '@fluojs/core';
|
|
660
|
+
return `import { ensureMetadataSymbol, Inject } from '@fluojs/core';
|
|
614
661
|
import { Controller, Get } from '@fluojs/http';
|
|
615
662
|
|
|
616
663
|
import { HealthService } from './health.service${importSuffix}';
|
|
617
664
|
import { HealthResponseDto } from './health.response.dto${importSuffix}';
|
|
618
665
|
|
|
666
|
+
ensureMetadataSymbol();
|
|
667
|
+
|
|
619
668
|
@Inject(HealthService)
|
|
620
669
|
@Controller('/health-info')
|
|
621
670
|
export class HealthController {
|
|
@@ -1364,12 +1413,13 @@ Generated by @fluojs/cli.
|
|
|
1364
1413
|
|
|
1365
1414
|
- Shape: \`mixed\`
|
|
1366
1415
|
- Supported topology: \`single-package\` generates one shared Node.js package where the Fastify HTTP application also starts an attached TCP microservice from the same \`src/main.ts\`
|
|
1367
|
-
- Runtime contract: \`src/app.ts\` owns one shared module graph, and \`src/main.ts\` bootstraps the HTTP API before calling \`connectMicroservice()\` and \`startAllMicroservices()\`
|
|
1416
|
+
- Runtime contract: \`src/app.ts\` owns one shared module graph, and \`src/main.ts\` bootstraps the HTTP API before calling \`connectMicroservice()\` and \`startAllMicroservices()\`; ${createRunCommand(options.packageManager, 'dev')}, ${createRunCommand(options.packageManager, 'build')}, and ${createRunCommand(options.packageManager, 'start')} delegate to \`fluo dev\`, \`fluo build\`, and \`fluo start\`, which default \`NODE_ENV\` when unset
|
|
1368
1417
|
- Intentional limitation: the first mixed release supports only the explicit Fastify HTTP + attached TCP microservice contract; other mixed transports or separate multi-entrypoint layouts fail validation instead of generating partial scaffolds
|
|
1369
1418
|
|
|
1370
1419
|
## Commands
|
|
1371
1420
|
|
|
1372
1421
|
- Dev: ${createRunCommand(options.packageManager, 'dev')}
|
|
1422
|
+
- Start: ${createRunCommand(options.packageManager, 'start')}
|
|
1373
1423
|
- Build: ${createRunCommand(options.packageManager, 'build')}
|
|
1374
1424
|
- Typecheck: ${createRunCommand(options.packageManager, 'typecheck')}
|
|
1375
1425
|
- Test: ${createRunCommand(options.packageManager, 'test')}
|
package/dist/update-check.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"AAOA,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAcF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAC5B;IACE,MAAM,EAAE,UAAU,CAAC;CACpB,GACD;IACE,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEN;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,yDAAyD;AACzD,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,MAAM,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,kBAAkB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC1E,cAAc,CAAC,EAAE,CAAC,cAAc,EAAE,oBAAoB,EAAE,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1G,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"AAOA,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAcF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAC5B;IACE,MAAM,EAAE,UAAU,CAAC;CACpB,GACD;IACE,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEN;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,yDAAyD;AACzD,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,MAAM,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,kBAAkB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC1E,cAAc,CAAC,EAAE,CAAC,cAAc,EAAE,oBAAoB,EAAE,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1G,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAycD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAcnG;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,4BAAiC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAmEjI"}
|
package/dist/update-check.js
CHANGED
|
@@ -204,10 +204,12 @@ async function fetchLatestDistTag(packageName) {
|
|
|
204
204
|
clearTimeout(timeout);
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
|
-
async function resolveLatestVersion(packageName, cacheFile, cacheTtlMs, nowMs, fetchLatestVersion) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
207
|
+
async function resolveLatestVersion(packageName, cacheFile, cacheTtlMs, nowMs, fetchLatestVersion, bypassCache) {
|
|
208
|
+
if (!bypassCache) {
|
|
209
|
+
const cachedLatestVersion = await readCachedLatestVersion(cacheFile, nowMs, cacheTtlMs);
|
|
210
|
+
if (cachedLatestVersion) {
|
|
211
|
+
return cachedLatestVersion;
|
|
212
|
+
}
|
|
211
213
|
}
|
|
212
214
|
let latestVersion;
|
|
213
215
|
try {
|
|
@@ -429,7 +431,7 @@ export async function runCliUpdateCheck(argv, options = {}) {
|
|
|
429
431
|
action: 'continue'
|
|
430
432
|
};
|
|
431
433
|
}
|
|
432
|
-
const latestVersion = await resolveLatestVersion(packageName, cacheFile, cacheTtlMs, nowMs, options.fetchLatestVersion ?? fetchLatestDistTag);
|
|
434
|
+
const latestVersion = await resolveLatestVersion(packageName, cacheFile, cacheTtlMs, nowMs, options.fetchLatestVersion ?? fetchLatestDistTag, options.bypassCache === true);
|
|
433
435
|
if (!latestVersion || !isNewerVersion(latestVersion, currentVersion)) {
|
|
434
436
|
return {
|
|
435
437
|
action: 'continue'
|