@fluojs/cli 1.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +183 -22
- package/README.md +186 -22
- package/dist/cli.d.ts +5 -4
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +128 -35
- package/dist/commands/diagnostics.d.ts +35 -0
- package/dist/commands/diagnostics.d.ts.map +1 -1
- package/dist/commands/diagnostics.js +60 -0
- 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 +5 -7
- package/dist/commands/inspect.d.ts.map +1 -1
- package/dist/commands/inspect.js +85 -65
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +27 -15
- package/dist/commands/migration-transform-tokens.d.ts +15 -0
- package/dist/commands/migration-transform-tokens.d.ts.map +1 -0
- package/dist/commands/migration-transform-tokens.js +41 -0
- package/dist/commands/new.d.ts +0 -6
- package/dist/commands/new.d.ts.map +1 -1
- package/dist/commands/new.js +42 -96
- package/dist/commands/output-path-safety.d.ts +14 -0
- package/dist/commands/output-path-safety.d.ts.map +1 -0
- package/dist/commands/output-path-safety.js +34 -0
- package/dist/commands/scripts.d.ts +1 -1
- package/dist/commands/scripts.d.ts.map +1 -1
- package/dist/commands/scripts.js +13 -7
- package/dist/commands/typegen-artifact.d.ts +54 -0
- package/dist/commands/typegen-artifact.d.ts.map +1 -0
- package/dist/commands/typegen-artifact.js +117 -0
- package/dist/commands/typegen-generation-child.d.ts +2 -0
- package/dist/commands/typegen-generation-child.d.ts.map +1 -0
- package/dist/commands/typegen-generation-child.js +59 -0
- package/dist/commands/typegen-generation-process.d.ts +46 -0
- package/dist/commands/typegen-generation-process.d.ts.map +1 -0
- package/dist/commands/typegen-generation-process.js +131 -0
- package/dist/commands/typegen-generation-protocol.d.ts +16 -0
- package/dist/commands/typegen-generation-protocol.d.ts.map +1 -0
- package/dist/commands/typegen-generation-protocol.js +35 -0
- package/dist/commands/typegen-isolated-source.d.ts +10 -0
- package/dist/commands/typegen-isolated-source.d.ts.map +1 -0
- package/dist/commands/typegen-isolated-source.js +75 -0
- package/dist/commands/typegen-options.d.ts +20 -0
- package/dist/commands/typegen-options.d.ts.map +1 -0
- package/dist/commands/typegen-options.js +71 -0
- package/dist/commands/typegen-source.d.ts +59 -0
- package/dist/commands/typegen-source.d.ts.map +1 -0
- package/dist/commands/typegen-source.js +183 -0
- package/dist/commands/typegen-watch.d.ts +46 -0
- package/dist/commands/typegen-watch.d.ts.map +1 -0
- package/dist/commands/typegen-watch.js +212 -0
- package/dist/commands/typegen.d.ts +29 -0
- package/dist/commands/typegen.d.ts.map +1 -0
- package/dist/commands/typegen.js +119 -0
- 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 +64 -13
- package/dist/fixtures/inspect-react-app.module.d.ts +4 -0
- package/dist/fixtures/inspect-react-app.module.d.ts.map +1 -0
- package/dist/fixtures/inspect-react-app.module.js +32 -0
- package/dist/fixtures/typegen-react-app.module.d.ts +4 -0
- package/dist/fixtures/typegen-react-app.module.d.ts.map +1 -0
- package/dist/fixtures/typegen-react-app.module.js +33 -0
- 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 +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -5
- package/dist/new/install.js +1 -1
- package/dist/new/package-spec-resolver.d.ts.map +1 -1
- package/dist/new/package-spec-resolver.js +50 -59
- package/dist/new/prompt.d.ts +1 -0
- package/dist/new/prompt.d.ts.map +1 -1
- package/dist/new/prompt.js +40 -12
- package/dist/new/published-internal-dependencies.d.ts +20 -0
- package/dist/new/published-internal-dependencies.d.ts.map +1 -0
- package/dist/new/published-internal-dependencies.js +20 -0
- package/dist/new/react-vite-ssr-scaffold.d.ts +19 -0
- package/dist/new/react-vite-ssr-scaffold.d.ts.map +1 -0
- package/dist/new/react-vite-ssr-scaffold.js +108 -0
- package/dist/new/resolver.d.ts +2 -2
- package/dist/new/resolver.d.ts.map +1 -1
- package/dist/new/resolver.js +5 -1
- package/dist/new/scaffold.d.ts.map +1 -1
- package/dist/new/scaffold.js +177 -54
- package/dist/new/starter-profiles.d.ts +8 -4
- package/dist/new/starter-profiles.d.ts.map +1 -1
- package/dist/new/starter-profiles.js +52 -18
- package/dist/new/templates/react-vite-ssr/README.md.ejs +74 -0
- package/dist/new/templates/react-vite-ssr/playwright.config.ts.ejs +26 -0
- package/dist/new/templates/react-vite-ssr/src/app.test.ts.ejs +82 -0
- package/dist/new/templates/react-vite-ssr/src/app.ts.ejs +91 -0
- package/dist/new/templates/react-vite-ssr/src/entry-client.tsx.ejs +29 -0
- package/dist/new/templates/react-vite-ssr/src/entry-server.tsx.ejs +52 -0
- package/dist/new/templates/react-vite-ssr/src/load-manifest.test.ts.ejs +55 -0
- package/dist/new/templates/react-vite-ssr/src/load-manifest.ts.ejs +53 -0
- package/dist/new/templates/react-vite-ssr/src/main.ts.ejs +18 -0
- package/dist/new/templates/react-vite-ssr/src/page.tsx.ejs +43 -0
- package/dist/new/templates/react-vite-ssr/src/react-app.test.tsx.ejs +67 -0
- package/dist/new/templates/react-vite-ssr/src/react-app.tsx.ejs +46 -0
- package/dist/new/templates/react-vite-ssr/src/styles.css.ejs +25 -0
- package/dist/new/templates/react-vite-ssr/src/styles.d.ts.ejs +1 -0
- package/dist/new/templates/react-vite-ssr/tests/production-hydration.spec.ts.ejs +54 -0
- package/dist/new/templates/react-vite-ssr/tsconfig.json.ejs +16 -0
- package/dist/new/templates/react-vite-ssr/vite.client.config.ts.ejs +24 -0
- package/dist/new/templates/react-vite-ssr/vite.server.config.ts.ejs +17 -0
- package/dist/new/templates/react-vite-ssr/vitest.config.ts.ejs +10 -0
- package/dist/new/types.d.ts +4 -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/public-typegen.d.ts +14 -0
- package/dist/public-typegen.d.ts.map +1 -0
- package/dist/public-typegen.js +17 -0
- package/dist/run-cli.d.ts +2 -1
- package/dist/run-cli.d.ts.map +1 -1
- package/dist/studio/sidecar.d.ts.map +1 -1
- package/dist/studio/sidecar.js +106 -14
- package/dist/transforms/nestjs-migrate.d.ts +4 -1
- package/dist/transforms/nestjs-migrate.d.ts.map +1 -1
- package/dist/transforms/nestjs-migrate.js +625 -65
- package/dist/typegen-contract.d.ts +10 -0
- package/dist/typegen-contract.d.ts.map +1 -0
- package/dist/typegen-contract.js +9 -0
- package/dist/usage.d.ts +19 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +178 -0
- package/package.json +19 -10
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
type TypegenGenerationRequest = {
|
|
2
|
+
readonly cwd: string;
|
|
3
|
+
readonly exportName: string;
|
|
4
|
+
readonly modulePath: string;
|
|
5
|
+
};
|
|
6
|
+
/** Listener boundary for one short-lived typegen generation child. */
|
|
7
|
+
export type TypegenGenerationChild = {
|
|
8
|
+
readonly kill: (signal: NodeJS.Signals) => boolean;
|
|
9
|
+
readonly offError: (listener: (error: Error) => void) => void;
|
|
10
|
+
readonly offExit: (listener: (code: number | null, signal: NodeJS.Signals | null) => void) => void;
|
|
11
|
+
readonly offMessage: (listener: (message: unknown) => void) => void;
|
|
12
|
+
readonly onError: (listener: (error: Error) => void) => void;
|
|
13
|
+
readonly onExit: (listener: (code: number | null, signal: NodeJS.Signals | null) => void) => void;
|
|
14
|
+
readonly onMessage: (listener: (message: unknown) => void) => void;
|
|
15
|
+
};
|
|
16
|
+
type TypegenGenerationSpawner = (request: TypegenGenerationRequest) => TypegenGenerationChild;
|
|
17
|
+
/** One short-lived typegen generation process controlled by its watch coordinator. */
|
|
18
|
+
export type TypegenGenerationProcess = {
|
|
19
|
+
cancel(): void;
|
|
20
|
+
readonly result: Promise<string>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Waits for a generation child to return source and exit, then removes every completion listener.
|
|
24
|
+
*
|
|
25
|
+
* @param child Generation child listener boundary.
|
|
26
|
+
* @returns Generated source after successful process exit.
|
|
27
|
+
*/
|
|
28
|
+
export declare function waitForTypegenGenerationChild(child: TypegenGenerationChild): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Starts one default typegen generation child for a coordinator to complete or cancel.
|
|
31
|
+
*
|
|
32
|
+
* @param request Consumer directory, application module path, and selected export.
|
|
33
|
+
* @param spawnGeneration Child-process factory used by the default runtime and lifecycle tests.
|
|
34
|
+
* @returns A cancellable child process whose result settles only after a clean process exit.
|
|
35
|
+
*/
|
|
36
|
+
export declare function startTypegenGenerationProcess(request: TypegenGenerationRequest, spawnGeneration?: TypegenGenerationSpawner): TypegenGenerationProcess;
|
|
37
|
+
/**
|
|
38
|
+
* Runs one default typegen generation in a short-lived child process.
|
|
39
|
+
*
|
|
40
|
+
* @param request Consumer directory, application module path, and selected export.
|
|
41
|
+
* @param spawnGeneration Child-process factory used by the default runtime and lifecycle tests.
|
|
42
|
+
* @returns Generated source after the child process has exited.
|
|
43
|
+
*/
|
|
44
|
+
export declare function runTypegenGenerationProcess(request: TypegenGenerationRequest, spawnGeneration?: TypegenGenerationSpawner): Promise<string>;
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=typegen-generation-process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typegen-generation-process.d.ts","sourceRoot":"","sources":["../../src/commands/typegen-generation-process.ts"],"names":[],"mappings":"AAQA,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,sEAAsE;AACtE,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,OAAO,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;IAC9D,QAAQ,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC;IACnG,QAAQ,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;IACpE,QAAQ,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;IAC7D,QAAQ,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC;IAClG,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;CACpE,CAAC;AAEF,KAAK,wBAAwB,GAAG,CAAC,OAAO,EAAE,wBAAwB,KAAK,sBAAsB,CAAC;AA2B9F,sFAAsF;AACtF,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,IAAI,IAAI,CAAC;IACf,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CAClC,CAAC;AASF;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsC5F;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,wBAAwB,EACjC,eAAe,GAAE,wBAAgD,GAChE,wBAAwB,CA0B1B;AAED;;;;;;GAMG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,wBAAwB,EACjC,eAAe,GAAE,wBAAgD,GAChE,OAAO,CAAC,MAAM,CAAC,CAEjB"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { fork } from 'node:child_process';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { dirname, extname, join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { parseTypegenGenerationMessage } from './typegen-generation-protocol.js';
|
|
6
|
+
import { TypegenCommandError } from './typegen-options.js';
|
|
7
|
+
|
|
8
|
+
/** Listener boundary for one short-lived typegen generation child. */
|
|
9
|
+
|
|
10
|
+
const CHILD_TERMINATION_GRACE_MS = 500;
|
|
11
|
+
function createGenerationChild(request) {
|
|
12
|
+
const currentPath = fileURLToPath(import.meta.url);
|
|
13
|
+
const extension = extname(currentPath);
|
|
14
|
+
const childPath = join(dirname(currentPath), `typegen-generation-child${extension}`);
|
|
15
|
+
const execArgv = extension === '.ts' ? ['--experimental-import-meta-resolve', '--import', createRequire(import.meta.url).resolve('tsx')] : ['--experimental-import-meta-resolve'];
|
|
16
|
+
const child = fork(childPath, [request.cwd, request.modulePath, request.exportName], {
|
|
17
|
+
cwd: request.cwd,
|
|
18
|
+
execArgv,
|
|
19
|
+
stdio: ['ignore', 'ignore', 'ignore', 'ipc']
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
kill: signal => child.kill(signal),
|
|
23
|
+
offError: listener => child.off('error', listener),
|
|
24
|
+
offExit: listener => child.off('exit', listener),
|
|
25
|
+
offMessage: listener => child.off('message', listener),
|
|
26
|
+
onError: listener => child.once('error', listener),
|
|
27
|
+
onExit: listener => child.once('exit', listener),
|
|
28
|
+
onMessage: listener => child.on('message', listener)
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** One short-lived typegen generation process controlled by its watch coordinator. */
|
|
33
|
+
|
|
34
|
+
function describeExit(code, signal) {
|
|
35
|
+
if (signal !== null) {
|
|
36
|
+
return `signal ${signal}`;
|
|
37
|
+
}
|
|
38
|
+
return code === null ? 'without an exit code' : `with exit code ${String(code)}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Waits for a generation child to return source and exit, then removes every completion listener.
|
|
43
|
+
*
|
|
44
|
+
* @param child Generation child listener boundary.
|
|
45
|
+
* @returns Generated source after successful process exit.
|
|
46
|
+
*/
|
|
47
|
+
export function waitForTypegenGenerationChild(child) {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
let message;
|
|
50
|
+
const cleanup = () => {
|
|
51
|
+
child.offError(onError);
|
|
52
|
+
child.offExit(onExit);
|
|
53
|
+
child.offMessage(onMessage);
|
|
54
|
+
};
|
|
55
|
+
const onError = error => {
|
|
56
|
+
cleanup();
|
|
57
|
+
reject(error);
|
|
58
|
+
};
|
|
59
|
+
const onMessage = value => {
|
|
60
|
+
try {
|
|
61
|
+
message = parseTypegenGenerationMessage(value);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
message = {
|
|
64
|
+
kind: 'error',
|
|
65
|
+
message: error instanceof Error ? error.message : String(error)
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const onExit = (code, signal) => {
|
|
70
|
+
cleanup();
|
|
71
|
+
if (message?.kind === 'error') {
|
|
72
|
+
reject(new TypegenCommandError(message.message));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (message?.kind === 'source' && code === 0) {
|
|
76
|
+
resolve(message.source);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
reject(new TypegenCommandError(`Typegen generation process exited ${describeExit(code, signal)} before returning source.`));
|
|
80
|
+
};
|
|
81
|
+
child.onError(onError);
|
|
82
|
+
child.onExit(onExit);
|
|
83
|
+
child.onMessage(onMessage);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Starts one default typegen generation child for a coordinator to complete or cancel.
|
|
89
|
+
*
|
|
90
|
+
* @param request Consumer directory, application module path, and selected export.
|
|
91
|
+
* @param spawnGeneration Child-process factory used by the default runtime and lifecycle tests.
|
|
92
|
+
* @returns A cancellable child process whose result settles only after a clean process exit.
|
|
93
|
+
*/
|
|
94
|
+
export function startTypegenGenerationProcess(request, spawnGeneration = createGenerationChild) {
|
|
95
|
+
const child = spawnGeneration(request);
|
|
96
|
+
let cancelled = false;
|
|
97
|
+
let forcedKillTimer;
|
|
98
|
+
const result = waitForTypegenGenerationChild(child).finally(() => {
|
|
99
|
+
if (forcedKillTimer !== undefined) {
|
|
100
|
+
clearTimeout(forcedKillTimer);
|
|
101
|
+
forcedKillTimer = undefined;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
return {
|
|
105
|
+
cancel() {
|
|
106
|
+
if (cancelled) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
cancelled = true;
|
|
110
|
+
if (!child.kill('SIGTERM')) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
forcedKillTimer = setTimeout(() => {
|
|
114
|
+
forcedKillTimer = undefined;
|
|
115
|
+
child.kill('SIGKILL');
|
|
116
|
+
}, CHILD_TERMINATION_GRACE_MS);
|
|
117
|
+
},
|
|
118
|
+
result
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Runs one default typegen generation in a short-lived child process.
|
|
124
|
+
*
|
|
125
|
+
* @param request Consumer directory, application module path, and selected export.
|
|
126
|
+
* @param spawnGeneration Child-process factory used by the default runtime and lifecycle tests.
|
|
127
|
+
* @returns Generated source after the child process has exited.
|
|
128
|
+
*/
|
|
129
|
+
export async function runTypegenGenerationProcess(request, spawnGeneration = createGenerationChild) {
|
|
130
|
+
return startTypegenGenerationProcess(request, spawnGeneration).result;
|
|
131
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** IPC outcome emitted by one isolated typegen generation child. */
|
|
2
|
+
export type TypegenGenerationMessage = {
|
|
3
|
+
readonly kind: 'error';
|
|
4
|
+
readonly message: string;
|
|
5
|
+
} | {
|
|
6
|
+
readonly kind: 'source';
|
|
7
|
+
readonly source: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Parses an untrusted generation child IPC payload.
|
|
11
|
+
*
|
|
12
|
+
* @param value IPC payload received from the child process.
|
|
13
|
+
* @returns A validated source or error message.
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseTypegenGenerationMessage(value: unknown): TypegenGenerationMessage;
|
|
16
|
+
//# sourceMappingURL=typegen-generation-protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typegen-generation-protocol.d.ts","sourceRoot":"","sources":["../../src/commands/typegen-generation-protocol.ts"],"names":[],"mappings":"AAEA,oEAAoE;AACpE,MAAM,MAAM,wBAAwB,GAChC;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAkBtF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { TypegenCommandError } from './typegen-options.js';
|
|
2
|
+
|
|
3
|
+
/** IPC outcome emitted by one isolated typegen generation child. */
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parses an untrusted generation child IPC payload.
|
|
7
|
+
*
|
|
8
|
+
* @param value IPC payload received from the child process.
|
|
9
|
+
* @returns A validated source or error message.
|
|
10
|
+
*/
|
|
11
|
+
export function parseTypegenGenerationMessage(value) {
|
|
12
|
+
if (typeof value !== 'object' || value === null) {
|
|
13
|
+
throw new TypegenCommandError('Typegen generation process returned an invalid IPC message.');
|
|
14
|
+
}
|
|
15
|
+
const kind = Reflect.get(value, 'kind');
|
|
16
|
+
if (kind === 'error') {
|
|
17
|
+
const message = Reflect.get(value, 'message');
|
|
18
|
+
if (typeof message === 'string') {
|
|
19
|
+
return {
|
|
20
|
+
kind,
|
|
21
|
+
message
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (kind === 'source') {
|
|
26
|
+
const source = Reflect.get(value, 'source');
|
|
27
|
+
if (typeof source === 'string') {
|
|
28
|
+
return {
|
|
29
|
+
kind,
|
|
30
|
+
source
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
throw new TypegenCommandError('Typegen generation process returned an invalid IPC message.');
|
|
35
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ParsedTypegenArgs } from './typegen-options.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generates source inside the default short-lived process while preserving one native module graph.
|
|
4
|
+
*
|
|
5
|
+
* @param parsed Parsed typegen command options.
|
|
6
|
+
* @param cwd Consumer project directory.
|
|
7
|
+
* @returns Complete deterministic generated source.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createProcessIsolatedTypegenSource(parsed: ParsedTypegenArgs, cwd: string): Promise<string>;
|
|
10
|
+
//# sourceMappingURL=typegen-isolated-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typegen-isolated-source.d.ts","sourceRoot":"","sources":["../../src/commands/typegen-isolated-source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAkE9D;;;;;;GAMG;AACH,wBAAsB,kCAAkC,CACtD,MAAM,EAAE,iBAAiB,EACzB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CAcjB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { dirname, extname, resolve } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { TypegenCommandError } from './typegen-options.js';
|
|
5
|
+
import { createTypegenSource, generateTypegenSource, loadReactTypegenModules } from './typegen-source.js';
|
|
6
|
+
const TYPESCRIPT_MODULE_EXTENSIONS = new Set(['.ts', '.tsx', '.mts', '.cts']);
|
|
7
|
+
const TYPEGEN_MODULE_IDS = ['@fluojs/react', '@fluojs/react/typegen', '@fluojs/runtime'];
|
|
8
|
+
function isModuleNotFoundError(error) {
|
|
9
|
+
return typeof error === 'object' && error !== null && 'code' in error && (error.code === 'MODULE_NOT_FOUND' || error.code === 'ERR_MODULE_NOT_FOUND');
|
|
10
|
+
}
|
|
11
|
+
function resolveProjectModuleUrl(moduleId, cwd) {
|
|
12
|
+
const parentUrls = [pathToFileURL(resolve(cwd, 'package.json')).href, import.meta.url];
|
|
13
|
+
for (const parentUrl of parentUrls) {
|
|
14
|
+
try {
|
|
15
|
+
return import.meta.resolve(moduleId, parentUrl);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
if (!isModuleNotFoundError(error)) {
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
throw new TypegenCommandError(`Unable to resolve ${moduleId} from the inspected project.`);
|
|
23
|
+
}
|
|
24
|
+
function requireNamespace(owner, name) {
|
|
25
|
+
const value = Reflect.get(owner, name);
|
|
26
|
+
if (typeof value !== 'object' || value === null) {
|
|
27
|
+
throw new TypegenCommandError(`Required typegen namespace ${name} is unavailable.`);
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
async function importNativeTypegenGraph(modulePath, cwd) {
|
|
32
|
+
const imports = {
|
|
33
|
+
application: pathToFileURL(modulePath).href,
|
|
34
|
+
react: resolveProjectModuleUrl(TYPEGEN_MODULE_IDS[0], cwd),
|
|
35
|
+
typegen: resolveProjectModuleUrl(TYPEGEN_MODULE_IDS[1], cwd),
|
|
36
|
+
runtime: resolveProjectModuleUrl(TYPEGEN_MODULE_IDS[2], cwd)
|
|
37
|
+
};
|
|
38
|
+
const source = `${Object.entries(imports).map(([name, url]) => `import * as ${name} from ${JSON.stringify(url)};`).join('\n')}\nexport { application, react, runtime, typegen };\n`;
|
|
39
|
+
const graphUrl = `data:text/javascript;charset=utf-8,${encodeURIComponent(source)}`;
|
|
40
|
+
const graph = await import(graphUrl);
|
|
41
|
+
return {
|
|
42
|
+
application: requireNamespace(graph, 'application'),
|
|
43
|
+
modules: {
|
|
44
|
+
react: requireNamespace(graph, 'react'),
|
|
45
|
+
runtime: requireNamespace(graph, 'runtime'),
|
|
46
|
+
typegen: requireNamespace(graph, 'typegen')
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Generates source inside the default short-lived process while preserving one native module graph.
|
|
53
|
+
*
|
|
54
|
+
* @param parsed Parsed typegen command options.
|
|
55
|
+
* @param cwd Consumer project directory.
|
|
56
|
+
* @returns Complete deterministic generated source.
|
|
57
|
+
*/
|
|
58
|
+
export async function createProcessIsolatedTypegenSource(parsed, cwd) {
|
|
59
|
+
const modulePath = resolve(cwd, parsed.modulePath);
|
|
60
|
+
if (TYPESCRIPT_MODULE_EXTENSIONS.has(extname(modulePath))) {
|
|
61
|
+
const tsconfigPath = resolve(dirname(modulePath), 'tsconfig.json');
|
|
62
|
+
const modules = await loadReactTypegenModules(cwd, existsSync(tsconfigPath) ? tsconfigPath : false);
|
|
63
|
+
return createTypegenSource({
|
|
64
|
+
cwd,
|
|
65
|
+
modules,
|
|
66
|
+
parsed
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const imported = await importNativeTypegenGraph(modulePath, cwd);
|
|
70
|
+
return generateTypegenSource({
|
|
71
|
+
application: imported.application,
|
|
72
|
+
modules: imported.modules,
|
|
73
|
+
parsed
|
|
74
|
+
});
|
|
75
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Parsed lifecycle and path options for one typegen invocation. */
|
|
2
|
+
export type ParsedTypegenArgs = {
|
|
3
|
+
readonly check: boolean;
|
|
4
|
+
readonly exportName: string;
|
|
5
|
+
readonly modulePath: string;
|
|
6
|
+
readonly outputPath: string;
|
|
7
|
+
readonly watch: boolean;
|
|
8
|
+
};
|
|
9
|
+
/** Invalid typegen command arguments or unavailable runtime tooling. */
|
|
10
|
+
export declare class TypegenCommandError extends Error {
|
|
11
|
+
readonly name = "TypegenCommandError";
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parses command arguments after `fluo typegen`.
|
|
15
|
+
*
|
|
16
|
+
* @param argv Raw typegen command arguments.
|
|
17
|
+
* @returns Parsed module, output, export, and lifecycle options.
|
|
18
|
+
*/
|
|
19
|
+
export declare function parseTypegenArgs(argv: readonly string[]): ParsedTypegenArgs;
|
|
20
|
+
//# sourceMappingURL=typegen-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typegen-options.d.ts","sourceRoot":"","sources":["../../src/commands/typegen-options.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,wEAAwE;AACxE,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,yBAAyB;CACvC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CAsD3E"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/** Parsed lifecycle and path options for one typegen invocation. */
|
|
2
|
+
|
|
3
|
+
/** Invalid typegen command arguments or unavailable runtime tooling. */
|
|
4
|
+
export class TypegenCommandError extends Error {
|
|
5
|
+
name = 'TypegenCommandError';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Parses command arguments after `fluo typegen`.
|
|
10
|
+
*
|
|
11
|
+
* @param argv Raw typegen command arguments.
|
|
12
|
+
* @returns Parsed module, output, export, and lifecycle options.
|
|
13
|
+
*/
|
|
14
|
+
export function parseTypegenArgs(argv) {
|
|
15
|
+
let check = false;
|
|
16
|
+
let exportName = 'AppModule';
|
|
17
|
+
let modulePath;
|
|
18
|
+
let outputPath;
|
|
19
|
+
let watch = false;
|
|
20
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
21
|
+
const option = argv[index];
|
|
22
|
+
if (option === '--check') {
|
|
23
|
+
check = true;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (option === '--watch') {
|
|
27
|
+
watch = true;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (option === '--output') {
|
|
31
|
+
const next = argv[index + 1];
|
|
32
|
+
if (next === undefined || next.startsWith('-')) {
|
|
33
|
+
throw new TypegenCommandError('Expected --output to have a file path value.');
|
|
34
|
+
}
|
|
35
|
+
outputPath = next;
|
|
36
|
+
index += 1;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (option === '--export') {
|
|
40
|
+
const next = argv[index + 1];
|
|
41
|
+
if (next === undefined || next.startsWith('-')) {
|
|
42
|
+
throw new TypegenCommandError('Expected --export to have a symbol name value.');
|
|
43
|
+
}
|
|
44
|
+
exportName = next;
|
|
45
|
+
index += 1;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (option?.startsWith('-')) {
|
|
49
|
+
throw new TypegenCommandError(`Unknown option for typegen command: ${option}`);
|
|
50
|
+
}
|
|
51
|
+
if (option !== undefined) {
|
|
52
|
+
if (modulePath !== undefined) {
|
|
53
|
+
throw new TypegenCommandError(`Unexpected extra positional argument: ${option}`);
|
|
54
|
+
}
|
|
55
|
+
modulePath = option;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (modulePath === undefined || outputPath === undefined) {
|
|
59
|
+
throw new TypegenCommandError('Usage: fluo typegen <module-path> --output <path> [--export <name>] [--check|--watch]');
|
|
60
|
+
}
|
|
61
|
+
if (check && watch) {
|
|
62
|
+
throw new TypegenCommandError('fluo typegen accepts only one of --check or --watch.');
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
check,
|
|
66
|
+
exportName,
|
|
67
|
+
modulePath,
|
|
68
|
+
outputPath,
|
|
69
|
+
watch
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ParsedTypegenArgs } from './typegen-options.js';
|
|
2
|
+
/** Dynamically loaded package surfaces required by typegen. */
|
|
3
|
+
export type ReactTypegenModules = {
|
|
4
|
+
readonly react: object;
|
|
5
|
+
readonly runtime: object;
|
|
6
|
+
readonly typegen: object;
|
|
7
|
+
};
|
|
8
|
+
/** Structural artifact result returned by the React typegen package. */
|
|
9
|
+
export type ReactTypegenArtifactInspection = {
|
|
10
|
+
readonly status: 'malformed';
|
|
11
|
+
} | {
|
|
12
|
+
readonly status: 'unsupported-version';
|
|
13
|
+
readonly version: number;
|
|
14
|
+
} | {
|
|
15
|
+
readonly status: 'valid';
|
|
16
|
+
readonly version: number;
|
|
17
|
+
};
|
|
18
|
+
type CreateTypegenSourceOptions = {
|
|
19
|
+
readonly cwd: string;
|
|
20
|
+
readonly modules: ReactTypegenModules;
|
|
21
|
+
readonly parsed: ParsedTypegenArgs;
|
|
22
|
+
};
|
|
23
|
+
type GenerateTypegenSourceOptions = {
|
|
24
|
+
readonly application: object;
|
|
25
|
+
readonly modules: ReactTypegenModules;
|
|
26
|
+
readonly parsed: ParsedTypegenArgs;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Loads typegen package entrypoints from the consumer project or CLI installation.
|
|
30
|
+
*
|
|
31
|
+
* @param cwd Consumer project directory used for package resolution.
|
|
32
|
+
* @param tsconfig TypeScript configuration path, or `false` for native package resolution.
|
|
33
|
+
* @returns React, React typegen, and runtime module namespaces.
|
|
34
|
+
*/
|
|
35
|
+
export declare function loadReactTypegenModules(cwd: string, tsconfig?: string | false): Promise<ReactTypegenModules>;
|
|
36
|
+
/**
|
|
37
|
+
* Bootstraps the selected module and generates source from authoritative route descriptors.
|
|
38
|
+
*
|
|
39
|
+
* @param options Parsed command, consumer directory, module namespaces, and native import boundary.
|
|
40
|
+
* @returns Complete deterministic generated source.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createTypegenSource(options: CreateTypegenSourceOptions): Promise<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Generates source from one already-imported application and its matching tooling namespaces.
|
|
45
|
+
*
|
|
46
|
+
* @param options Application namespace, generation modules, and parsed command selection.
|
|
47
|
+
* @returns Complete deterministic generated source.
|
|
48
|
+
*/
|
|
49
|
+
export declare function generateTypegenSource(options: GenerateTypegenSourceOptions): Promise<string>;
|
|
50
|
+
/**
|
|
51
|
+
* Inspects an existing generated source value through the loaded React typegen package.
|
|
52
|
+
*
|
|
53
|
+
* @param modules Loaded React typegen module namespace.
|
|
54
|
+
* @param source Existing artifact source.
|
|
55
|
+
* @returns Parsed current, malformed, or unsupported-version status.
|
|
56
|
+
*/
|
|
57
|
+
export declare function inspectReactTypegenArtifact(modules: ReactTypegenModules, source: string): ReactTypegenArtifactInspection;
|
|
58
|
+
export {};
|
|
59
|
+
//# sourceMappingURL=typegen-source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typegen-source.d.ts","sourceRoot":"","sources":["../../src/commands/typegen-source.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAG9D,+DAA+D;AAC/D,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,wEAAwE;AACxE,MAAM,MAAM,8BAA8B,GACtC;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAChC;IAAE,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,KAAK,0BAA0B,GAAG;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;CACpC,CAAC;AAEF,KAAK,4BAA4B,GAAG;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;CACpC,CAAC;AAwEF;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAM,GAAG,KAAa,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAKzH;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAU9F;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,OAAO,CAAC,MAAM,CAAC,CAqClG;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,mBAAmB,EAC5B,MAAM,EAAE,MAAM,GACb,8BAA8B,CAmBhC"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { dirname, extname, resolve } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { tsImport } from 'tsx/esm/api';
|
|
5
|
+
import { TypegenCommandError } from './typegen-options.js';
|
|
6
|
+
|
|
7
|
+
/** Dynamically loaded package surfaces required by typegen. */
|
|
8
|
+
|
|
9
|
+
/** Structural artifact result returned by the React typegen package. */
|
|
10
|
+
|
|
11
|
+
const TYPESCRIPT_MODULE_EXTENSIONS = new Set(['.ts', '.tsx', '.mts', '.cts']);
|
|
12
|
+
const TYPEGEN_MODULE_IDS = ['@fluojs/react', '@fluojs/react/typegen', '@fluojs/runtime'];
|
|
13
|
+
const SILENT_APPLICATION_LOGGER = Object.freeze({
|
|
14
|
+
debug() {},
|
|
15
|
+
error() {},
|
|
16
|
+
log() {},
|
|
17
|
+
warn() {}
|
|
18
|
+
});
|
|
19
|
+
let applicationImportSequence = 0;
|
|
20
|
+
function isModuleNotFoundError(error) {
|
|
21
|
+
return typeof error === 'object' && error !== null && 'code' in error && (error.code === 'MODULE_NOT_FOUND' || error.code === 'ERR_MODULE_NOT_FOUND');
|
|
22
|
+
}
|
|
23
|
+
async function importProjectModule(moduleId, cwd, tsconfig) {
|
|
24
|
+
const importOptions = [{
|
|
25
|
+
parentURL: pathToFileURL(resolve(cwd, 'package.json')).href,
|
|
26
|
+
tsconfig
|
|
27
|
+
}, {
|
|
28
|
+
parentURL: import.meta.url,
|
|
29
|
+
tsconfig: false
|
|
30
|
+
}];
|
|
31
|
+
for (const options of importOptions) {
|
|
32
|
+
try {
|
|
33
|
+
const imported = await tsImport(moduleId, options);
|
|
34
|
+
if (typeof imported !== 'object' || imported === null) {
|
|
35
|
+
throw new TypegenCommandError(`Resolved ${moduleId} to an invalid module namespace.`);
|
|
36
|
+
}
|
|
37
|
+
return imported;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (!isModuleNotFoundError(error)) {
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
throw new TypegenCommandError(`Unable to resolve ${moduleId} from the inspected project.`);
|
|
45
|
+
}
|
|
46
|
+
async function importTypeScriptApplicationModule(modulePath) {
|
|
47
|
+
const moduleUrl = pathToFileURL(modulePath).href;
|
|
48
|
+
const tsconfigPath = resolve(dirname(modulePath), 'tsconfig.json');
|
|
49
|
+
return existsSync(tsconfigPath) ? tsImport(moduleUrl, {
|
|
50
|
+
parentURL: import.meta.url,
|
|
51
|
+
tsconfig: tsconfigPath
|
|
52
|
+
}) : tsImport(moduleUrl, {
|
|
53
|
+
parentURL: import.meta.url,
|
|
54
|
+
tsconfig: false
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function requireNamespace(owner, name) {
|
|
58
|
+
const value = Reflect.get(owner, name);
|
|
59
|
+
if (typeof value !== 'object' || value === null) {
|
|
60
|
+
throw new TypegenCommandError(`Required typegen namespace ${name} is unavailable.`);
|
|
61
|
+
}
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
async function importNativeApplicationModule(modulePath) {
|
|
65
|
+
applicationImportSequence += 1;
|
|
66
|
+
const source = `import * as application from ${JSON.stringify(pathToFileURL(modulePath).href)};\nexport { application };\n`;
|
|
67
|
+
const graphUrl = `data:text/javascript;charset=utf-8,${encodeURIComponent(source)}#fluo-typegen-${String(applicationImportSequence)}`;
|
|
68
|
+
const graph = await tsImport(graphUrl, import.meta.url);
|
|
69
|
+
return requireNamespace(graph, 'application');
|
|
70
|
+
}
|
|
71
|
+
function requireFunction(owner, name) {
|
|
72
|
+
const value = Reflect.get(owner, name);
|
|
73
|
+
if (typeof value !== 'function') {
|
|
74
|
+
throw new TypegenCommandError(`Required typegen function ${name} is unavailable.`);
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Loads typegen package entrypoints from the consumer project or CLI installation.
|
|
81
|
+
*
|
|
82
|
+
* @param cwd Consumer project directory used for package resolution.
|
|
83
|
+
* @param tsconfig TypeScript configuration path, or `false` for native package resolution.
|
|
84
|
+
* @returns React, React typegen, and runtime module namespaces.
|
|
85
|
+
*/
|
|
86
|
+
export async function loadReactTypegenModules(cwd, tsconfig = false) {
|
|
87
|
+
const [react, typegen, runtime] = await Promise.all(TYPEGEN_MODULE_IDS.map(moduleId => importProjectModule(moduleId, cwd, tsconfig)));
|
|
88
|
+
return {
|
|
89
|
+
react,
|
|
90
|
+
runtime,
|
|
91
|
+
typegen
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Bootstraps the selected module and generates source from authoritative route descriptors.
|
|
97
|
+
*
|
|
98
|
+
* @param options Parsed command, consumer directory, module namespaces, and native import boundary.
|
|
99
|
+
* @returns Complete deterministic generated source.
|
|
100
|
+
*/
|
|
101
|
+
export async function createTypegenSource(options) {
|
|
102
|
+
const modulePath = resolve(options.cwd, options.parsed.modulePath);
|
|
103
|
+
const importedApplication = TYPESCRIPT_MODULE_EXTENSIONS.has(extname(modulePath)) ? await importTypeScriptApplicationModule(modulePath) : await importNativeApplicationModule(modulePath);
|
|
104
|
+
return generateTypegenSource({
|
|
105
|
+
application: importedApplication,
|
|
106
|
+
modules: options.modules,
|
|
107
|
+
parsed: options.parsed
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Generates source from one already-imported application and its matching tooling namespaces.
|
|
113
|
+
*
|
|
114
|
+
* @param options Application namespace, generation modules, and parsed command selection.
|
|
115
|
+
* @returns Complete deterministic generated source.
|
|
116
|
+
*/
|
|
117
|
+
export async function generateTypegenSource(options) {
|
|
118
|
+
const rootModule = Reflect.get(options.application, options.parsed.exportName);
|
|
119
|
+
if (typeof rootModule !== 'function') {
|
|
120
|
+
throw new TypegenCommandError(`Export "${options.parsed.exportName}" is not a module class constructor.`);
|
|
121
|
+
}
|
|
122
|
+
const factory = Reflect.get(options.modules.runtime, 'FluoFactory');
|
|
123
|
+
if (typeof factory !== 'function') {
|
|
124
|
+
throw new TypegenCommandError('Required runtime FluoFactory is unavailable.');
|
|
125
|
+
}
|
|
126
|
+
const application = await Reflect.apply(requireFunction(factory, 'create'), factory, [rootModule, {
|
|
127
|
+
logger: SILENT_APPLICATION_LOGGER
|
|
128
|
+
}]);
|
|
129
|
+
if (typeof application !== 'object' || application === null) {
|
|
130
|
+
throw new TypegenCommandError('Runtime application bootstrap returned an invalid value.');
|
|
131
|
+
}
|
|
132
|
+
const close = requireFunction(application, 'close');
|
|
133
|
+
try {
|
|
134
|
+
const dispatcher = Reflect.get(application, 'dispatcher');
|
|
135
|
+
if (typeof dispatcher !== 'object' || dispatcher === null) {
|
|
136
|
+
throw new TypegenCommandError('Runtime application dispatcher is unavailable.');
|
|
137
|
+
}
|
|
138
|
+
const descriptors = Reflect.apply(requireFunction(dispatcher, 'describeRoutes'), dispatcher, []);
|
|
139
|
+
if (!Array.isArray(descriptors)) {
|
|
140
|
+
throw new TypegenCommandError('Runtime route descriptors are unavailable.');
|
|
141
|
+
}
|
|
142
|
+
const catalog = Reflect.apply(requireFunction(options.modules.react, 'createReactPageCatalog'), undefined, [descriptors]);
|
|
143
|
+
const source = Reflect.apply(requireFunction(options.modules.typegen, 'generateReactPageTypes'), undefined, [catalog]);
|
|
144
|
+
if (typeof source !== 'string') {
|
|
145
|
+
throw new TypegenCommandError('React page typegen returned an invalid artifact.');
|
|
146
|
+
}
|
|
147
|
+
return source;
|
|
148
|
+
} finally {
|
|
149
|
+
await Reflect.apply(close, application, []);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Inspects an existing generated source value through the loaded React typegen package.
|
|
155
|
+
*
|
|
156
|
+
* @param modules Loaded React typegen module namespace.
|
|
157
|
+
* @param source Existing artifact source.
|
|
158
|
+
* @returns Parsed current, malformed, or unsupported-version status.
|
|
159
|
+
*/
|
|
160
|
+
export function inspectReactTypegenArtifact(modules, source) {
|
|
161
|
+
const inspection = Reflect.apply(requireFunction(modules.typegen, 'inspectReactPageTypeArtifact'), undefined, [source]);
|
|
162
|
+
if (typeof inspection !== 'object' || inspection === null || !('status' in inspection)) {
|
|
163
|
+
throw new TypegenCommandError('React page typegen artifact inspection returned an invalid result.');
|
|
164
|
+
}
|
|
165
|
+
if (inspection.status === 'malformed') {
|
|
166
|
+
return {
|
|
167
|
+
status: 'malformed'
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
if (inspection.status === 'unsupported-version' && 'version' in inspection && typeof inspection.version === 'number') {
|
|
171
|
+
return {
|
|
172
|
+
status: 'unsupported-version',
|
|
173
|
+
version: inspection.version
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
if (inspection.status === 'valid' && 'version' in inspection && typeof inspection.version === 'number') {
|
|
177
|
+
return {
|
|
178
|
+
status: 'valid',
|
|
179
|
+
version: inspection.version
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
throw new TypegenCommandError('React page typegen artifact inspection returned an invalid result.');
|
|
183
|
+
}
|