@fluojs/cli 1.0.6 → 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 +31 -10
- package/README.md +31 -10
- 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 +16 -7
- 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 +43 -8
- 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 +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- 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/run-cli.d.ts +16 -0
- package/dist/run-cli.d.ts.map +1 -0
- package/dist/run-cli.js +16 -0
- package/dist/studio/sidecar.d.ts.map +1 -1
- package/dist/studio/sidecar.js +113 -27
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/update-check.d.ts.map +1 -1
- package/dist/update-check.js +21 -4
- 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/studio/sidecar.js
CHANGED
|
@@ -21,16 +21,60 @@ const DEFAULT_HOST = '127.0.0.1';
|
|
|
21
21
|
const DEFAULT_HEARTBEAT_MS = 15_000;
|
|
22
22
|
const MAX_EVENT_REPLAY = 1_000;
|
|
23
23
|
const MAX_REQUEST_BYTES = 1_048_576;
|
|
24
|
+
const BODY_LIKE_PAYLOAD_FIELDS = new Set(['body', 'headers', 'payload', 'rawBody', 'requestBody', 'responseBody']);
|
|
24
25
|
const require = createRequire(import.meta.url);
|
|
25
26
|
function isRecord(value) {
|
|
26
27
|
return typeof value === 'object' && value !== null;
|
|
27
28
|
}
|
|
29
|
+
function findBodyLikePayloadField(value, path = 'payload') {
|
|
30
|
+
if (Array.isArray(value)) {
|
|
31
|
+
for (const [index, item] of value.entries()) {
|
|
32
|
+
const match = findBodyLikePayloadField(item, `${path}[${String(index)}]`);
|
|
33
|
+
if (match) {
|
|
34
|
+
return match;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
if (!isRecord(value)) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
43
|
+
const nestedPath = `${path}.${key}`;
|
|
44
|
+
if (BODY_LIKE_PAYLOAD_FIELDS.has(key)) {
|
|
45
|
+
return nestedPath;
|
|
46
|
+
}
|
|
47
|
+
const match = findBodyLikePayloadField(nestedValue, nestedPath);
|
|
48
|
+
if (match) {
|
|
49
|
+
return match;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
28
54
|
function isRestartEpochBoundary(incoming) {
|
|
29
55
|
if (incoming.type !== 'restart' || !isRecord(incoming.payload)) {
|
|
30
56
|
return false;
|
|
31
57
|
}
|
|
32
58
|
return incoming.payload.phase === 'scheduled' || incoming.payload.phase === 'starting';
|
|
33
59
|
}
|
|
60
|
+
function resolveRestartEpoch(incoming) {
|
|
61
|
+
if (!isRestartEpochBoundary(incoming)) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
const payload = isRecord(incoming.payload) ? incoming.payload : undefined;
|
|
65
|
+
const requestedEpoch = payload?.epoch;
|
|
66
|
+
return typeof requestedEpoch === 'string' && requestedEpoch.length > 0 ? requestedEpoch : createEpoch();
|
|
67
|
+
}
|
|
68
|
+
function createStudioSidecarEnv(options) {
|
|
69
|
+
return {
|
|
70
|
+
FLUO_STUDIO: '1',
|
|
71
|
+
FLUO_STUDIO_APP_ID: options.appId,
|
|
72
|
+
FLUO_STUDIO_EPOCH: options.epoch,
|
|
73
|
+
FLUO_STUDIO_RUNTIME: options.runtime,
|
|
74
|
+
FLUO_STUDIO_TOKEN: options.token,
|
|
75
|
+
FLUO_STUDIO_URL: options.url
|
|
76
|
+
};
|
|
77
|
+
}
|
|
34
78
|
function createToken() {
|
|
35
79
|
return randomBytes(24).toString('base64url');
|
|
36
80
|
}
|
|
@@ -42,20 +86,53 @@ function createDefaultAppId() {
|
|
|
42
86
|
}
|
|
43
87
|
function readBody(request) {
|
|
44
88
|
return new Promise((resolve, reject) => {
|
|
89
|
+
let settled = false;
|
|
45
90
|
let body = '';
|
|
46
91
|
request.setEncoding('utf8');
|
|
47
|
-
|
|
92
|
+
const settle = (action, value) => {
|
|
93
|
+
if (settled) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
settled = true;
|
|
97
|
+
request.off('data', onData);
|
|
98
|
+
request.off('end', onEnd);
|
|
99
|
+
request.off('error', onError);
|
|
100
|
+
request.off('close', onClose);
|
|
101
|
+
if (action === 'resolve') {
|
|
102
|
+
resolve(value);
|
|
103
|
+
} else {
|
|
104
|
+
reject(value);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const onData = chunk => {
|
|
48
108
|
body += chunk;
|
|
49
109
|
if (body.length > MAX_REQUEST_BYTES) {
|
|
50
|
-
reject
|
|
110
|
+
settle('reject', new Error('Studio event payload is too large.'));
|
|
51
111
|
request.destroy();
|
|
52
112
|
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
113
|
+
};
|
|
114
|
+
const onEnd = () => settle('resolve', body);
|
|
115
|
+
const onError = error => settle('reject', error);
|
|
116
|
+
// A client that closes the socket after sending only a partial request body
|
|
117
|
+
// may never emit `end` or `error`. Bind `close` to body-reader cancellation
|
|
118
|
+
// so the sidecar cannot hang on a malformed local client indefinitely.
|
|
119
|
+
const onClose = () => {
|
|
120
|
+
if (body.length === 0) {
|
|
121
|
+
settle('reject', new Error('Studio sidecar request closed before any body was received.'));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
settle('reject', new Error('Studio sidecar request closed before the full body was received.'));
|
|
125
|
+
};
|
|
126
|
+
request.on('data', onData);
|
|
127
|
+
request.on('end', onEnd);
|
|
128
|
+
request.on('error', onError);
|
|
129
|
+
request.on('close', onClose);
|
|
56
130
|
});
|
|
57
131
|
}
|
|
58
132
|
function writeJson(response, statusCode, payload) {
|
|
133
|
+
if (response.writableEnded) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
59
136
|
response.writeHead(statusCode, {
|
|
60
137
|
'cache-control': 'no-store',
|
|
61
138
|
'content-type': 'application/json; charset=utf-8'
|
|
@@ -222,8 +299,9 @@ export async function startStudioSidecar(options = {}) {
|
|
|
222
299
|
let sequence = 0;
|
|
223
300
|
const startedAt = performance.now();
|
|
224
301
|
const publish = incoming => {
|
|
225
|
-
|
|
226
|
-
|
|
302
|
+
const restartEpoch = resolveRestartEpoch(incoming);
|
|
303
|
+
if (restartEpoch) {
|
|
304
|
+
epoch = restartEpoch;
|
|
227
305
|
}
|
|
228
306
|
sequence += 1;
|
|
229
307
|
const source = isRecord(incoming.source) ? incoming.source : undefined;
|
|
@@ -316,6 +394,13 @@ export async function startStudioSidecar(options = {}) {
|
|
|
316
394
|
});
|
|
317
395
|
return;
|
|
318
396
|
}
|
|
397
|
+
const bodyLikeField = findBodyLikePayloadField(parsed.payload);
|
|
398
|
+
if (bodyLikeField) {
|
|
399
|
+
writeJson(response, 400, {
|
|
400
|
+
error: `Studio runtime event payload must not include body-like field ${bodyLikeField}.`
|
|
401
|
+
});
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
319
404
|
const event = publish(parsed);
|
|
320
405
|
writeJson(response, 202, {
|
|
321
406
|
accepted: true,
|
|
@@ -333,6 +418,19 @@ export async function startStudioSidecar(options = {}) {
|
|
|
333
418
|
error: 'Unknown Studio sidecar route.'
|
|
334
419
|
});
|
|
335
420
|
});
|
|
421
|
+
await new Promise((resolve, reject) => {
|
|
422
|
+
server.once('error', reject);
|
|
423
|
+
server.listen(options.port ?? 0, host, () => {
|
|
424
|
+
server.off('error', reject);
|
|
425
|
+
resolve();
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
const address = server.address();
|
|
429
|
+
if (!address || typeof address === 'string') {
|
|
430
|
+
await closeServer(server, clients, undefined);
|
|
431
|
+
throw new Error('Failed to resolve Studio sidecar address.');
|
|
432
|
+
}
|
|
433
|
+
const url = `http://${host}:${String(address.port)}`;
|
|
336
434
|
const heartbeat = options.heartbeatMs === 0 ? undefined : setInterval(() => {
|
|
337
435
|
publish({
|
|
338
436
|
payload: {
|
|
@@ -346,31 +444,19 @@ export async function startStudioSidecar(options = {}) {
|
|
|
346
444
|
});
|
|
347
445
|
}, options.heartbeatMs ?? DEFAULT_HEARTBEAT_MS);
|
|
348
446
|
heartbeat?.unref();
|
|
349
|
-
await new Promise((resolve, reject) => {
|
|
350
|
-
server.once('error', reject);
|
|
351
|
-
server.listen(options.port ?? 0, host, () => {
|
|
352
|
-
server.off('error', reject);
|
|
353
|
-
resolve();
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
const address = server.address();
|
|
357
|
-
if (!address || typeof address === 'string') {
|
|
358
|
-
await closeServer(server, clients, heartbeat);
|
|
359
|
-
throw new Error('Failed to resolve Studio sidecar address.');
|
|
360
|
-
}
|
|
361
|
-
const url = `http://${host}:${String(address.port)}`;
|
|
362
447
|
return {
|
|
363
448
|
appId,
|
|
364
449
|
get epoch() {
|
|
365
450
|
return epoch;
|
|
366
451
|
},
|
|
367
|
-
env
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
452
|
+
get env() {
|
|
453
|
+
return createStudioSidecarEnv({
|
|
454
|
+
appId,
|
|
455
|
+
epoch,
|
|
456
|
+
runtime,
|
|
457
|
+
token,
|
|
458
|
+
url
|
|
459
|
+
});
|
|
374
460
|
},
|
|
375
461
|
host,
|
|
376
462
|
port: address.port,
|
package/dist/types.d.ts
CHANGED
|
@@ -4,9 +4,14 @@ export type { GenerateOptions, GeneratedFile } from './generator-types.js';
|
|
|
4
4
|
export type GeneratorKind = ManifestGeneratorKind;
|
|
5
5
|
/**
|
|
6
6
|
* Minimal registration metadata used by tests and helper utilities that reason about module wiring.
|
|
7
|
+
*
|
|
8
|
+
* @remarks Middleware registrations target the module `middleware` array; controllers and providers
|
|
9
|
+
* target their matching module metadata arrays.
|
|
7
10
|
*/
|
|
8
11
|
export interface ModuleRegistration {
|
|
12
|
+
/** Class name inserted into the target module metadata array. */
|
|
9
13
|
className: string;
|
|
10
|
-
kind
|
|
14
|
+
/** Module metadata kind used by the generated class. */
|
|
15
|
+
kind: 'controller' | 'provider' | 'middleware';
|
|
11
16
|
}
|
|
12
17
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,IAAI,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEvF,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,0EAA0E;AAC1E,MAAM,MAAM,aAAa,GAAG,qBAAqB,CAAC;AAElD
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,IAAI,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEvF,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,0EAA0E;AAC1E,MAAM,MAAM,aAAa,GAAG,qBAAqB,CAAC;AAElD;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,YAAY,CAAC;CAChD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"AAQA,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;AAieD;;;;;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
|
@@ -35,6 +35,20 @@ const UPDATE_PACKAGE_MANAGERS = new Set(['bun', 'npm', 'pnpm', 'yarn']);
|
|
|
35
35
|
function isRecord(value) {
|
|
36
36
|
return typeof value === 'object' && value !== null;
|
|
37
37
|
}
|
|
38
|
+
function isReadableStream(value) {
|
|
39
|
+
if (!value || !isRecord(value)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
const candidate = value;
|
|
43
|
+
return typeof candidate.on === 'function' && typeof candidate.pause === 'function' && typeof candidate.resume === 'function';
|
|
44
|
+
}
|
|
45
|
+
function isWritableStream(value) {
|
|
46
|
+
if (!value || !isRecord(value)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
const candidate = value;
|
|
50
|
+
return typeof candidate.write === 'function' && typeof candidate.on === 'function' && typeof candidate.once === 'function' && typeof candidate.emit === 'function' && typeof candidate.removeListener === 'function';
|
|
51
|
+
}
|
|
38
52
|
function isTruthyEnvValue(value) {
|
|
39
53
|
if (!value) {
|
|
40
54
|
return false;
|
|
@@ -325,11 +339,11 @@ function resolveInstallCommand(packageName, latestVersion, packageManager) {
|
|
|
325
339
|
display: `npm install -g ${packageSpecifier}`
|
|
326
340
|
};
|
|
327
341
|
}
|
|
328
|
-
async function defaultPromptConfirm(message, defaultValue) {
|
|
342
|
+
async function defaultPromptConfirm(message, defaultValue, io = {}) {
|
|
329
343
|
const promptSuffix = defaultValue ? 'Y/n' : 'y/N';
|
|
330
344
|
const readline = createInterface({
|
|
331
|
-
input: process.stdin,
|
|
332
|
-
output: process.stdout
|
|
345
|
+
input: isReadableStream(io.stdin) ? io.stdin : process.stdin,
|
|
346
|
+
output: isWritableStream(io.stdout) ? io.stdout : process.stdout
|
|
333
347
|
});
|
|
334
348
|
try {
|
|
335
349
|
const answer = (await readline.question(`${message} (${promptSuffix}) `)).trim().toLowerCase();
|
|
@@ -439,7 +453,10 @@ export async function runCliUpdateCheck(argv, options = {}) {
|
|
|
439
453
|
}
|
|
440
454
|
stderr.write(`A newer ${packageName} version is available: ${currentVersion} -> ${latestVersion}.\n`);
|
|
441
455
|
const prompt = options.prompt ?? {
|
|
442
|
-
confirm: defaultPromptConfirm
|
|
456
|
+
confirm: (message, defaultValue) => defaultPromptConfirm(message, defaultValue, {
|
|
457
|
+
stdin: options.stdin,
|
|
458
|
+
stdout
|
|
459
|
+
})
|
|
443
460
|
};
|
|
444
461
|
const shouldInstall = await prompt.confirm(`Install ${packageName}@${latestVersion} now and restart this command?`, false);
|
|
445
462
|
if (!shouldInstall) {
|
package/dist/usage.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders CLI help text for `fluo new` without importing the scaffold implementation.
|
|
3
|
+
*
|
|
4
|
+
* @returns Stable help output for the scaffolding command.
|
|
5
|
+
*/
|
|
6
|
+
export declare function newUsage(): string;
|
|
7
|
+
/**
|
|
8
|
+
* Returns the usage information string for the inspect command without importing runtime inspection logic.
|
|
9
|
+
*
|
|
10
|
+
* @returns Formatted help text including usage and options.
|
|
11
|
+
*/
|
|
12
|
+
export declare function inspectUsage(): string;
|
|
13
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"AAiIA;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,MAAM,CA0BjC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAarC"}
|
package/dist/usage.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { renderAliasList, renderHelpTable } from './help.js';
|
|
2
|
+
const NEW_OPTION_HELP = [{
|
|
3
|
+
aliases: [],
|
|
4
|
+
description: 'Provide the project name without using the positional argument.',
|
|
5
|
+
option: '--name <project-name>'
|
|
6
|
+
}, {
|
|
7
|
+
aliases: [],
|
|
8
|
+
description: 'Select the scaffold shape explicitly (application for HTTP, microservice for the transport-driven starter path, mixed for the API + microservice starter).',
|
|
9
|
+
option: '--shape <application|microservice|mixed>'
|
|
10
|
+
}, {
|
|
11
|
+
aliases: [],
|
|
12
|
+
description: 'Select the transport path explicitly (http for applications, tcp for the runnable microservice starter, plus shipped microservice starter transports).',
|
|
13
|
+
option: '--transport <http|tcp|redis-streams|nats|kafka|rabbitmq|mqtt|grpc>'
|
|
14
|
+
}, {
|
|
15
|
+
aliases: [],
|
|
16
|
+
description: 'Select the runtime explicitly (node, bun, deno, or cloudflare-workers for application starters; node for microservice and mixed starters).',
|
|
17
|
+
option: '--runtime <node|bun|deno|cloudflare-workers>'
|
|
18
|
+
}, {
|
|
19
|
+
aliases: [],
|
|
20
|
+
description: 'Select the platform adapter explicitly (fastify, express, or nodejs on node; bun/deno/cloudflare-workers on their native runtimes; none for microservices).',
|
|
21
|
+
option: '--platform <fastify|express|nodejs|bun|deno|cloudflare-workers|none>'
|
|
22
|
+
}, {
|
|
23
|
+
aliases: [],
|
|
24
|
+
description: 'Select the starter tooling preset explicitly (currently only standard).',
|
|
25
|
+
option: '--tooling <standard>'
|
|
26
|
+
}, {
|
|
27
|
+
aliases: [],
|
|
28
|
+
description: 'Select the starter topology mode explicitly (currently only single-package).',
|
|
29
|
+
option: '--topology <single-package>'
|
|
30
|
+
}, {
|
|
31
|
+
aliases: [],
|
|
32
|
+
description: 'Choose which package manager installs the starter dependencies.',
|
|
33
|
+
option: '--package-manager <pnpm|npm|yarn|bun>'
|
|
34
|
+
}, {
|
|
35
|
+
aliases: [],
|
|
36
|
+
description: 'Write the new app to a custom target directory (always overrides positional name path).',
|
|
37
|
+
option: '--target-directory <path>'
|
|
38
|
+
}, {
|
|
39
|
+
aliases: [],
|
|
40
|
+
description: 'Overwrite files in a non-empty target directory without prompting.',
|
|
41
|
+
option: '--force'
|
|
42
|
+
}, {
|
|
43
|
+
aliases: [],
|
|
44
|
+
description: 'Install starter dependencies after writing files.',
|
|
45
|
+
option: '--install'
|
|
46
|
+
}, {
|
|
47
|
+
aliases: [],
|
|
48
|
+
description: 'Skip starter dependency installation.',
|
|
49
|
+
option: '--no-install'
|
|
50
|
+
}, {
|
|
51
|
+
aliases: [],
|
|
52
|
+
description: 'Initialize a git repository in the generated starter.',
|
|
53
|
+
option: '--git'
|
|
54
|
+
}, {
|
|
55
|
+
aliases: [],
|
|
56
|
+
description: 'Skip git repository initialization in the generated starter.',
|
|
57
|
+
option: '--no-git'
|
|
58
|
+
}, {
|
|
59
|
+
aliases: [],
|
|
60
|
+
description: 'Print the resolved scaffold plan without writing files, installing dependencies, or initializing git.',
|
|
61
|
+
option: '--print-plan'
|
|
62
|
+
}, {
|
|
63
|
+
aliases: ['-h'],
|
|
64
|
+
description: 'Show help for the new command.',
|
|
65
|
+
option: '--help'
|
|
66
|
+
}];
|
|
67
|
+
const INSPECT_OPTION_HELP = [{
|
|
68
|
+
aliases: [],
|
|
69
|
+
description: 'Emit the runtime platform snapshot/diagnostics payload as JSON (default when no output mode is selected).',
|
|
70
|
+
option: '--json'
|
|
71
|
+
}, {
|
|
72
|
+
aliases: [],
|
|
73
|
+
description: 'Emit a Mermaid graph through the optional @fluojs/studio rendering contract.',
|
|
74
|
+
option: '--mermaid'
|
|
75
|
+
}, {
|
|
76
|
+
aliases: [],
|
|
77
|
+
description: 'Include bootstrap timing diagnostics next to JSON inspect output.',
|
|
78
|
+
option: '--timing'
|
|
79
|
+
}, {
|
|
80
|
+
aliases: [],
|
|
81
|
+
description: 'Emit a CI-friendly JSON report with summary, snapshot, diagnostics, and timing.',
|
|
82
|
+
option: '--report'
|
|
83
|
+
}, {
|
|
84
|
+
aliases: [],
|
|
85
|
+
description: 'Write the selected inspect payload to a file instead of stdout.',
|
|
86
|
+
option: '--output <path>'
|
|
87
|
+
}, {
|
|
88
|
+
aliases: [],
|
|
89
|
+
description: 'Select the exported module symbol name (default: AppModule).',
|
|
90
|
+
option: '--export <name>'
|
|
91
|
+
}, {
|
|
92
|
+
aliases: ['-h'],
|
|
93
|
+
description: 'Show help for the inspect command.',
|
|
94
|
+
option: '--help'
|
|
95
|
+
}];
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Renders CLI help text for `fluo new` without importing the scaffold implementation.
|
|
99
|
+
*
|
|
100
|
+
* @returns Stable help output for the scaffolding command.
|
|
101
|
+
*/
|
|
102
|
+
export function newUsage() {
|
|
103
|
+
return ['Usage: fluo new|create [project-name] [options]', '', 'Options', renderHelpTable(NEW_OPTION_HELP, [{
|
|
104
|
+
header: 'Option',
|
|
105
|
+
render: entry => entry.option
|
|
106
|
+
}, {
|
|
107
|
+
header: 'Aliases',
|
|
108
|
+
render: entry => renderAliasList(entry.aliases)
|
|
109
|
+
}, {
|
|
110
|
+
header: 'Description',
|
|
111
|
+
render: entry => entry.description
|
|
112
|
+
}]), '', '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');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Returns the usage information string for the inspect command without importing runtime inspection logic.
|
|
117
|
+
*
|
|
118
|
+
* @returns Formatted help text including usage and options.
|
|
119
|
+
*/
|
|
120
|
+
export function inspectUsage() {
|
|
121
|
+
return ['Usage: fluo inspect <module-path> [options]', '', 'Options', renderHelpTable(INSPECT_OPTION_HELP, [{
|
|
122
|
+
header: 'Option',
|
|
123
|
+
render: entry => entry.option
|
|
124
|
+
}, {
|
|
125
|
+
header: 'Aliases',
|
|
126
|
+
render: entry => renderAliasList(entry.aliases)
|
|
127
|
+
}, {
|
|
128
|
+
header: 'Description',
|
|
129
|
+
render: entry => entry.description
|
|
130
|
+
}]), '', 'Docs: https://github.com/fluojs/fluo/tree/main/docs/getting-started/quick-start.md'].join('\n');
|
|
131
|
+
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"migration",
|
|
10
10
|
"diagnostics"
|
|
11
11
|
],
|
|
12
|
-
"version": "
|
|
12
|
+
"version": "2.0.1",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"ejs": "^3.1.10",
|
|
45
45
|
"tsx": "^4.20.4",
|
|
46
46
|
"typescript": "^6.0.2",
|
|
47
|
-
"@fluojs/runtime": "^
|
|
47
|
+
"@fluojs/runtime": "^2.0.1"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@fluojs/studio": "^1.0.
|
|
50
|
+
"@fluojs/studio": "^1.0.8"
|
|
51
51
|
},
|
|
52
52
|
"peerDependenciesMeta": {
|
|
53
53
|
"@fluojs/studio": {
|