@t4h.framework/cli 0.0.0-experimental-c0d4325
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/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/bin/bin.js +57 -0
- package/dist/bin/bin.js.map +1 -0
- package/dist/commands/build/build.js +49 -0
- package/dist/commands/build/build.js.map +1 -0
- package/dist/commands/dev/dev.js +109 -0
- package/dist/commands/dev/dev.js.map +1 -0
- package/dist/commands/dev-server-up-app-process.js +84 -0
- package/dist/commands/dev-server-up-app-process.js.map +1 -0
- package/dist/commands/publish/publish.js +149 -0
- package/dist/commands/publish/publish.js.map +1 -0
- package/dist/models/CliFileSystemClaim.js +30 -0
- package/dist/models/CliFileSystemClaim.js.map +1 -0
- package/dist/models/CliHttpClientRequestClaim.js +21 -0
- package/dist/models/CliHttpClientRequestClaim.js.map +1 -0
- package/dist/models/CliORMClaim.js +37 -0
- package/dist/models/CliORMClaim.js.map +1 -0
- package/dist/models/DevServer.js +77 -0
- package/dist/models/DevServer.js.map +1 -0
- package/dist/models/DevServerFileBinary.js +27 -0
- package/dist/models/DevServerFileBinary.js.map +1 -0
- package/dist/models/DevServerFileSystemClaim.js +30 -0
- package/dist/models/DevServerFileSystemClaim.js.map +1 -0
- package/dist/models/DevServerHttpClientRequestClaim.js +21 -0
- package/dist/models/DevServerHttpClientRequestClaim.js.map +1 -0
- package/dist/models/DevServerORMClaim.js +37 -0
- package/dist/models/DevServerORMClaim.js.map +1 -0
- package/dist/models/DevServerSmtpSendEmailClaim.js +32 -0
- package/dist/models/DevServerSmtpSendEmailClaim.js.map +1 -0
- package/dist/models/FileBinary.js +28 -0
- package/dist/models/FileBinary.js.map +1 -0
- package/dist/models/InMemoryDatabase.js +86 -0
- package/dist/models/InMemoryDatabase.js.map +1 -0
- package/dist/models/JSONCodec.js +110 -0
- package/dist/models/JSONCodec.js.map +1 -0
- package/dist/models/JSONCodecKindFrameworkSerializableClass.js +7 -0
- package/dist/models/JSONCodecKindFrameworkSerializableClass.js.map +1 -0
- package/dist/models/JSONRPCClient.js +50 -0
- package/dist/models/JSONRPCClient.js.map +1 -0
- package/dist/models/JSONRPCServer.js +61 -0
- package/dist/models/JSONRPCServer.js.map +1 -0
- package/dist/models/__tests__/DevServerFileBinary.spec.js +44 -0
- package/dist/models/__tests__/DevServerFileBinary.spec.js.map +1 -0
- package/dist/models/__tests__/InMemoryDatabase.spec.js +189 -0
- package/dist/models/__tests__/InMemoryDatabase.spec.js.map +1 -0
- package/dist/models/__tests__/JSONCodec.spec.js +135 -0
- package/dist/models/__tests__/JSONCodec.spec.js.map +1 -0
- package/dist/models/__tests__/JSONCodecKindFrameworkSerializableClass.spec.js +51 -0
- package/dist/models/__tests__/JSONCodecKindFrameworkSerializableClass.spec.js.map +1 -0
- package/dist/models/__tests__/JSONRPCClient.spec.js +133 -0
- package/dist/models/__tests__/JSONRPCClient.spec.js.map +1 -0
- package/dist/models/__tests__/JSONRPCServer.spec.js +160 -0
- package/dist/models/__tests__/JSONRPCServer.spec.js.map +1 -0
- package/dist/tools/__tests__/up-app.spec.js +24 -0
- package/dist/tools/__tests__/up-app.spec.js.map +1 -0
- package/dist/tools/a.js +53 -0
- package/dist/tools/a.js.map +1 -0
- package/dist/tools/extract-workflow-jsx.js +206 -0
- package/dist/tools/extract-workflow-jsx.js.map +1 -0
- package/dist/tools/generate-rsc-entries.js +105 -0
- package/dist/tools/generate-rsc-entries.js.map +1 -0
- package/dist/tools/json-codec.js +17 -0
- package/dist/tools/json-codec.js.map +1 -0
- package/dist/tools/json-schema-to-inquirer-question.js +33 -0
- package/dist/tools/json-schema-to-inquirer-question.js.map +1 -0
- package/dist/tools/mkdir-out-dir-project-from-ts-config-path-and-json-package-path.js +11 -0
- package/dist/tools/mkdir-out-dir-project-from-ts-config-path-and-json-package-path.js.map +1 -0
- package/dist/tools/resolve-package-json-path.js +21 -0
- package/dist/tools/resolve-package-json-path.js.map +1 -0
- package/dist/tools/resolve-tsconfig-path-from-package-json-path.js +14 -0
- package/dist/tools/resolve-tsconfig-path-from-package-json-path.js.map +1 -0
- package/dist/tools/test.js +32 -0
- package/dist/tools/test.js.map +1 -0
- package/dist/tools/ts-build-watch.js +46 -0
- package/dist/tools/ts-build-watch.js.map +1 -0
- package/dist/tools/ts-build.js +37 -0
- package/dist/tools/ts-build.js.map +1 -0
- package/dist/tools/up-app.js +10 -0
- package/dist/tools/up-app.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import Type from 'typebox';
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { JSONRPCServer, JSONRPCServerMethod } from '../JSONRPCServer.js';
|
|
4
|
+
describe('JSONRPCServerMethod', () => {
|
|
5
|
+
describe('constructor', () => {
|
|
6
|
+
it('creates with name and function', () => {
|
|
7
|
+
const method = new JSONRPCServerMethod('add', (a, b) => a + b);
|
|
8
|
+
expect(method.name).toBe('add');
|
|
9
|
+
expect(method.schema).toEqual([]);
|
|
10
|
+
});
|
|
11
|
+
it('creates with name, config, and function', () => {
|
|
12
|
+
const method = new JSONRPCServerMethod('add', { schema: [Type.Number(), Type.Number()] }, (a, b) => a + b);
|
|
13
|
+
expect(method.name).toBe('add');
|
|
14
|
+
expect(method.schema).toHaveLength(2);
|
|
15
|
+
expect(method.validate).toHaveLength(2);
|
|
16
|
+
});
|
|
17
|
+
it('defaults schema to empty array when config has no schema', () => {
|
|
18
|
+
const method = new JSONRPCServerMethod('echo', {}, (v) => v);
|
|
19
|
+
expect(method.schema).toEqual([]);
|
|
20
|
+
});
|
|
21
|
+
it('throws on invalid constructor arguments', () => {
|
|
22
|
+
expect(() => new JSONRPCServerMethod('bad', {}, undefined)).toThrow('Invalid constructor arguments');
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe('call', () => {
|
|
26
|
+
it('calls the function with array params', async () => {
|
|
27
|
+
const method = new JSONRPCServerMethod('add', (a, b) => a + b);
|
|
28
|
+
const result = await method.call([2, 3]);
|
|
29
|
+
expect(result).toBe(5);
|
|
30
|
+
});
|
|
31
|
+
it('wraps non-array params in an array', async () => {
|
|
32
|
+
const method = new JSONRPCServerMethod('echo', (v) => v);
|
|
33
|
+
const result = await method.call('hello');
|
|
34
|
+
expect(result).toBe('hello');
|
|
35
|
+
});
|
|
36
|
+
it('validates params against schema and throws on invalid', async () => {
|
|
37
|
+
const method = new JSONRPCServerMethod('typed', { schema: [Type.Number()] }, (n) => n * 2);
|
|
38
|
+
await expect(method.call(['not-a-number'])).rejects.toThrow('Invalid parameters');
|
|
39
|
+
});
|
|
40
|
+
it('passes validation and calls function with valid params', async () => {
|
|
41
|
+
const method = new JSONRPCServerMethod('double', { schema: [Type.Number()] }, (n) => n * 2);
|
|
42
|
+
const result = await method.call([5]);
|
|
43
|
+
expect(result).toBe(10);
|
|
44
|
+
});
|
|
45
|
+
it('handles async functions', async () => {
|
|
46
|
+
const method = new JSONRPCServerMethod('async', async (n) => {
|
|
47
|
+
return n + 1;
|
|
48
|
+
});
|
|
49
|
+
const result = await method.call([10]);
|
|
50
|
+
expect(result).toBe(11);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe('JSONRPCServer', () => {
|
|
55
|
+
describe('handle', () => {
|
|
56
|
+
it('dispatches to the correct method and sends response', async () => {
|
|
57
|
+
const send = vi.fn();
|
|
58
|
+
const addMethod = new JSONRPCServerMethod('add', (a, b) => a + b);
|
|
59
|
+
const server = new JSONRPCServer([addMethod], send);
|
|
60
|
+
await server.handle({
|
|
61
|
+
jsonrpc: '2.0',
|
|
62
|
+
id: 'req-1',
|
|
63
|
+
method: 'add',
|
|
64
|
+
params: [2, 3],
|
|
65
|
+
});
|
|
66
|
+
expect(send).toHaveBeenCalledOnce();
|
|
67
|
+
const response = JSON.parse(send.mock.calls[0][0]);
|
|
68
|
+
expect(response).toEqual({
|
|
69
|
+
jsonrpc: '2.0',
|
|
70
|
+
id: 'req-1',
|
|
71
|
+
result: 5,
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
it('handles string messages by parsing JSON', async () => {
|
|
75
|
+
const send = vi.fn();
|
|
76
|
+
const echoMethod = new JSONRPCServerMethod('echo', (v) => v);
|
|
77
|
+
const server = new JSONRPCServer([echoMethod], send);
|
|
78
|
+
await server.handle(JSON.stringify({
|
|
79
|
+
jsonrpc: '2.0',
|
|
80
|
+
id: 'req-2',
|
|
81
|
+
method: 'echo',
|
|
82
|
+
params: ['hello'],
|
|
83
|
+
}));
|
|
84
|
+
const response = JSON.parse(send.mock.calls[0][0]);
|
|
85
|
+
expect(response.result).toBe('hello');
|
|
86
|
+
});
|
|
87
|
+
it('handles Buffer messages', async () => {
|
|
88
|
+
const send = vi.fn();
|
|
89
|
+
const echoMethod = new JSONRPCServerMethod('echo', (v) => v);
|
|
90
|
+
const server = new JSONRPCServer([echoMethod], send);
|
|
91
|
+
const msg = Buffer.from(JSON.stringify({
|
|
92
|
+
jsonrpc: '2.0',
|
|
93
|
+
id: 'req-3',
|
|
94
|
+
method: 'echo',
|
|
95
|
+
params: [42],
|
|
96
|
+
}));
|
|
97
|
+
await server.handle(msg);
|
|
98
|
+
const response = JSON.parse(send.mock.calls[0][0]);
|
|
99
|
+
expect(response.result).toBe(42);
|
|
100
|
+
});
|
|
101
|
+
it('throws for unknown method', async () => {
|
|
102
|
+
const send = vi.fn();
|
|
103
|
+
const server = new JSONRPCServer([], send);
|
|
104
|
+
await expect(server.handle({
|
|
105
|
+
jsonrpc: '2.0',
|
|
106
|
+
id: 'req-4',
|
|
107
|
+
method: 'nonexistent',
|
|
108
|
+
params: [],
|
|
109
|
+
})).rejects.toThrow('Method nonexistent not found');
|
|
110
|
+
});
|
|
111
|
+
it('returns early for non-object messages', async () => {
|
|
112
|
+
const send = vi.fn();
|
|
113
|
+
const server = new JSONRPCServer([], send);
|
|
114
|
+
const result = await server.handle(42);
|
|
115
|
+
expect(result).toBeUndefined();
|
|
116
|
+
expect(send).not.toHaveBeenCalled();
|
|
117
|
+
});
|
|
118
|
+
it('returns early for null messages', async () => {
|
|
119
|
+
const send = vi.fn();
|
|
120
|
+
const server = new JSONRPCServer([], send);
|
|
121
|
+
const result = await server.handle(null);
|
|
122
|
+
expect(result).toBeUndefined();
|
|
123
|
+
expect(send).not.toHaveBeenCalled();
|
|
124
|
+
});
|
|
125
|
+
it('returns early for messages without method', async () => {
|
|
126
|
+
const send = vi.fn();
|
|
127
|
+
const server = new JSONRPCServer([], send);
|
|
128
|
+
const result = await server.handle({ jsonrpc: '2.0', id: 'req-5' });
|
|
129
|
+
expect(result).toBeUndefined();
|
|
130
|
+
expect(send).not.toHaveBeenCalled();
|
|
131
|
+
});
|
|
132
|
+
it('sends null result when method returns undefined', async () => {
|
|
133
|
+
const send = vi.fn();
|
|
134
|
+
const voidMethod = new JSONRPCServerMethod('noop', () => { });
|
|
135
|
+
const server = new JSONRPCServer([voidMethod], send);
|
|
136
|
+
await server.handle({
|
|
137
|
+
jsonrpc: '2.0',
|
|
138
|
+
id: 'req-6',
|
|
139
|
+
method: 'noop',
|
|
140
|
+
params: [],
|
|
141
|
+
});
|
|
142
|
+
const response = JSON.parse(send.mock.calls[0][0]);
|
|
143
|
+
expect(response.result).toBeNull();
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
describe('notify', () => {
|
|
147
|
+
it('sends a notification message without id', async () => {
|
|
148
|
+
const send = vi.fn();
|
|
149
|
+
const server = new JSONRPCServer([], send);
|
|
150
|
+
await server.notify('update', { data: 'test' });
|
|
151
|
+
const message = JSON.parse(send.mock.calls[0][0]);
|
|
152
|
+
expect(message).toEqual({
|
|
153
|
+
jsonrpc: '2.0',
|
|
154
|
+
method: 'update',
|
|
155
|
+
params: [{ data: 'test' }],
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
//# sourceMappingURL=JSONRPCServer.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JSONRPCServer.spec.js","sourceRoot":"","sources":["../../../src/models/__tests__/JSONRPCServer.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
5
|
+
import { upApp } from '../up-app.js';
|
|
6
|
+
let tmpDir;
|
|
7
|
+
beforeAll(async () => {
|
|
8
|
+
tmpDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'up-app-test-'));
|
|
9
|
+
});
|
|
10
|
+
afterAll(async () => {
|
|
11
|
+
await fs.promises.rm(tmpDir, { recursive: true, force: true });
|
|
12
|
+
});
|
|
13
|
+
describe('upApp', () => {
|
|
14
|
+
it('throws when module does not export an App', async () => {
|
|
15
|
+
const modulePath = path.join(tmpDir, 'no-app.mjs');
|
|
16
|
+
await fs.promises.writeFile(modulePath, 'export const foo = 42;');
|
|
17
|
+
await expect(upApp(modulePath)).rejects.toThrow('App not found');
|
|
18
|
+
});
|
|
19
|
+
it('throws when module path does not exist', async () => {
|
|
20
|
+
const modulePath = path.join(tmpDir, 'nonexistent.mjs');
|
|
21
|
+
await expect(upApp(modulePath)).rejects.toThrow();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
//# sourceMappingURL=up-app.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"up-app.spec.js","sourceRoot":"","sources":["../../../src/tools/__tests__/up-app.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAElE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAEpC,IAAI,MAAc,CAAA;AAElB,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,CAAA;AAC5E,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,KAAK,IAAI,EAAE;IAClB,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AAChE,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;IACrB,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;QAClD,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,EAAE,wBAAwB,CAAC,CAAA;QAEjE,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;IAClE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;QAEvD,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAA;IACnD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
package/dist/tools/a.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import ts from 'typescript';
|
|
4
|
+
export async function generateRscEntrypointFile(opts) {
|
|
5
|
+
const { outFileAbs, extracted } = opts;
|
|
6
|
+
if (!extracted.length)
|
|
7
|
+
return;
|
|
8
|
+
// 1) printer para transformar AST em texto
|
|
9
|
+
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
|
10
|
+
// 2) Coleta imports (v1: copia TODOS os imports de cada sourceFile envolvido)
|
|
11
|
+
// Dedup por texto exato pra evitar repetição
|
|
12
|
+
const importLines = new Set();
|
|
13
|
+
// Para evitar que "import type" vire algo estranho, a gente só imprime o node em si.
|
|
14
|
+
for (const item of extracted) {
|
|
15
|
+
for (const st of item.sourceFile.statements) {
|
|
16
|
+
if (ts.isImportDeclaration(st) || ts.isImportEqualsDeclaration(st)) {
|
|
17
|
+
const txt = printer.printNode(ts.EmitHint.Unspecified, st, item.sourceFile);
|
|
18
|
+
importLines.add(txt.endsWith(';') ? txt : `${txt};`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// 3) Gera as factories
|
|
23
|
+
const factoryLines = [];
|
|
24
|
+
for (const item of extracted) {
|
|
25
|
+
// imprime o JSX como aparece no arquivo original
|
|
26
|
+
const jsxText = printer.printNode(ts.EmitHint.Unspecified, item.jsx, item.sourceFile);
|
|
27
|
+
// garante que vira expression única dentro de arrow fn
|
|
28
|
+
// (se for fragment/element ok; se for algo esquisito, envolve em parênteses)
|
|
29
|
+
const body = jsxText.startsWith('<') ? `(${jsxText})` : jsxText;
|
|
30
|
+
factoryLines.push(` ${JSON.stringify(item.id)}: () => ${body},`);
|
|
31
|
+
}
|
|
32
|
+
const content = `/* eslint-disable */
|
|
33
|
+
// Auto-generated by t4h CLI. Do not edit by hand.
|
|
34
|
+
|
|
35
|
+
${Array.from(importLines).join('\n')}
|
|
36
|
+
|
|
37
|
+
export const __RSC_FACTORIES__ = {
|
|
38
|
+
${factoryLines.join('\n')}
|
|
39
|
+
} as const;
|
|
40
|
+
|
|
41
|
+
export type RscFactoryId = keyof typeof __RSC_FACTORIES__;
|
|
42
|
+
|
|
43
|
+
export function __getRscElement__(id: RscFactoryId) {
|
|
44
|
+
const fn = __RSC_FACTORIES__[id];
|
|
45
|
+
if (!fn) throw new Error("RSC factory not found: " + id);
|
|
46
|
+
return fn();
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
49
|
+
// 4) garante pasta e escreve o arquivo
|
|
50
|
+
await fs.mkdir(path.dirname(outFileAbs), { recursive: true });
|
|
51
|
+
await fs.writeFile(outFileAbs, content, 'utf8');
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=a.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a.js","sourceRoot":"","sources":["../../src/tools/a.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjC,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,MAAM,YAAY,CAAA;AAI3B,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,IAI/C;IACC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,CAAA;IAEtC,IAAI,CAAC,SAAS,CAAC,MAAM;QAAE,OAAM;IAE7B,2CAA2C;IAC3C,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAA;IAEtE,8EAA8E;IAC9E,gDAAgD;IAChD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;IAErC,qFAAqF;IACrF,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;YAC5C,IAAI,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,yBAAyB,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnE,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAC3B,EAAE,CAAC,QAAQ,CAAC,WAAW,EACvB,EAAE,EACF,IAAI,CAAC,UAAU,CAChB,CAAA;gBACD,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAA;YACtD,CAAC;QACH,CAAC;IACH,CAAC;IAED,uBAAuB;IACvB,MAAM,YAAY,GAAa,EAAE,CAAA;IAEjC,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,iDAAiD;QACjD,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAC/B,EAAE,CAAC,QAAQ,CAAC,WAAW,EACvB,IAAI,CAAC,GAAG,EACR,IAAI,CAAC,UAAU,CAChB,CAAA;QAED,uDAAuD;QACvD,6EAA6E;QAC7E,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,OAAO,CAAA;QAE/D,YAAY,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,IAAI,GAAG,CAAC,CAAA;IACnE,CAAC;IAED,MAAM,OAAO,GAAG;;;EAGhB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;EAGlC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;;CAUxB,CAAA;IAEC,uCAAuC;IACvC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7D,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;AACjD,CAAC"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
function resolveJsxTagName(node) {
|
|
3
|
+
const tagName = node.tagName;
|
|
4
|
+
if (ts.isIdentifier(tagName))
|
|
5
|
+
return tagName.text;
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
function findImportForIdentifier(sf, name) {
|
|
9
|
+
for (const stmt of sf.statements) {
|
|
10
|
+
if (!ts.isImportDeclaration(stmt))
|
|
11
|
+
continue;
|
|
12
|
+
const specifier = ts.isStringLiteral(stmt.moduleSpecifier)
|
|
13
|
+
? stmt.moduleSpecifier.text
|
|
14
|
+
: null;
|
|
15
|
+
if (!specifier)
|
|
16
|
+
continue;
|
|
17
|
+
const clause = stmt.importClause;
|
|
18
|
+
if (!clause)
|
|
19
|
+
continue;
|
|
20
|
+
if (clause.name && clause.name.text === name) {
|
|
21
|
+
return { moduleSpecifier: specifier, isDefault: true };
|
|
22
|
+
}
|
|
23
|
+
const namedBindings = clause.namedBindings;
|
|
24
|
+
if (namedBindings && ts.isNamedImports(namedBindings)) {
|
|
25
|
+
for (const element of namedBindings.elements) {
|
|
26
|
+
if (element.name.text === name) {
|
|
27
|
+
return { moduleSpecifier: specifier, isDefault: false };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
function jsxAttributesToObjectLiteral(attrs) {
|
|
35
|
+
const properties = [];
|
|
36
|
+
for (const attr of attrs.properties) {
|
|
37
|
+
if (ts.isJsxAttribute(attr)) {
|
|
38
|
+
const propName = ts.isIdentifier(attr.name) ? attr.name.text : attr.name.getText();
|
|
39
|
+
let value;
|
|
40
|
+
if (!attr.initializer) {
|
|
41
|
+
value = ts.factory.createTrue();
|
|
42
|
+
}
|
|
43
|
+
else if (ts.isStringLiteral(attr.initializer)) {
|
|
44
|
+
value = ts.factory.createStringLiteral(attr.initializer.text);
|
|
45
|
+
}
|
|
46
|
+
else if (ts.isJsxExpression(attr.initializer)) {
|
|
47
|
+
value =
|
|
48
|
+
attr.initializer.expression ??
|
|
49
|
+
ts.factory.createIdentifier('undefined');
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
value = attr.initializer;
|
|
53
|
+
}
|
|
54
|
+
properties.push(ts.factory.createPropertyAssignment(ts.factory.createIdentifier(propName), value));
|
|
55
|
+
}
|
|
56
|
+
else if (ts.isJsxSpreadAttribute(attr)) {
|
|
57
|
+
properties.push(ts.factory.createSpreadAssignment(attr.expression));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return ts.factory.createObjectLiteralExpression(properties, properties.length > 0);
|
|
61
|
+
}
|
|
62
|
+
function getJsxRootInfo(node) {
|
|
63
|
+
if (ts.isJsxSelfClosingElement(node)) {
|
|
64
|
+
const name = resolveJsxTagName(node);
|
|
65
|
+
if (!name)
|
|
66
|
+
return null;
|
|
67
|
+
return { tagName: name, attributes: node.attributes };
|
|
68
|
+
}
|
|
69
|
+
if (ts.isJsxElement(node)) {
|
|
70
|
+
const name = resolveJsxTagName(node.openingElement);
|
|
71
|
+
if (!name)
|
|
72
|
+
return null;
|
|
73
|
+
return { tagName: name, attributes: node.openingElement.attributes };
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
function findEnclosingWorkflow(node) {
|
|
78
|
+
let current = node.parent;
|
|
79
|
+
while (current) {
|
|
80
|
+
if ((ts.isArrowFunction(current) || ts.isFunctionExpression(current)) &&
|
|
81
|
+
current.parent &&
|
|
82
|
+
ts.isNewExpression(current.parent)) {
|
|
83
|
+
const newExpr = current.parent;
|
|
84
|
+
if (ts.isIdentifier(newExpr.expression) &&
|
|
85
|
+
newExpr.expression.text === 'Workflow') {
|
|
86
|
+
return { workflowId: extractWorkflowId(newExpr) };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
current = current.parent;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
function extractWorkflowId(newExpr) {
|
|
94
|
+
const args = newExpr.arguments;
|
|
95
|
+
if (!args || args.length < 2)
|
|
96
|
+
return null;
|
|
97
|
+
const optionsArg = args[0];
|
|
98
|
+
if (!optionsArg || !ts.isObjectLiteralExpression(optionsArg))
|
|
99
|
+
return null;
|
|
100
|
+
for (const prop of optionsArg.properties) {
|
|
101
|
+
if (ts.isPropertyAssignment(prop) &&
|
|
102
|
+
ts.isIdentifier(prop.name) &&
|
|
103
|
+
prop.name.text === 'id' &&
|
|
104
|
+
ts.isStringLiteral(prop.initializer)) {
|
|
105
|
+
return prop.initializer.text;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
function isJsxNode(node) {
|
|
111
|
+
return (ts.isJsxElement(node) ||
|
|
112
|
+
ts.isJsxSelfClosingElement(node) ||
|
|
113
|
+
ts.isJsxFragment(node));
|
|
114
|
+
}
|
|
115
|
+
function isNestedInsideJsx(node) {
|
|
116
|
+
let current = node.parent;
|
|
117
|
+
while (current) {
|
|
118
|
+
if (ts.isJsxElement(current) || ts.isJsxFragment(current))
|
|
119
|
+
return true;
|
|
120
|
+
current = current.parent;
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
const RENDER_FUNCTION_NAMES = new Set(['render', 'renderForm']);
|
|
125
|
+
function isRenderCallWithJsx(node) {
|
|
126
|
+
if (!ts.isCallExpression(node))
|
|
127
|
+
return false;
|
|
128
|
+
const callee = node.expression;
|
|
129
|
+
if (!ts.isIdentifier(callee))
|
|
130
|
+
return false;
|
|
131
|
+
if (!RENDER_FUNCTION_NAMES.has(callee.text))
|
|
132
|
+
return false;
|
|
133
|
+
if (node.arguments.length < 1)
|
|
134
|
+
return false;
|
|
135
|
+
const firstArg = node.arguments[0];
|
|
136
|
+
return isJsxNode(firstArg);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Walks `new Workflow(...)` callbacks and:
|
|
140
|
+
*
|
|
141
|
+
* 1. `render(<Comp x={v} />)` / `renderForm(<Comp x={v} />)`
|
|
142
|
+
* -> `render("component-id", { x: v })` / `renderForm("component-id", { x: v })`
|
|
143
|
+
*
|
|
144
|
+
* 2. Standalone JSX (variable assignment, return, etc.)
|
|
145
|
+
* -> `__rscRef("component-id", { x: v })`
|
|
146
|
+
*
|
|
147
|
+
* Nested JSX children are left untouched; only the top-level JSX
|
|
148
|
+
* expressions inside the workflow callback are transformed.
|
|
149
|
+
*/
|
|
150
|
+
export function extractWorkflowJsxTransformer(result, makeId) {
|
|
151
|
+
return (ctx) => {
|
|
152
|
+
let componentIndex = 0;
|
|
153
|
+
return (sf) => {
|
|
154
|
+
const processedCallExpressions = new WeakSet();
|
|
155
|
+
function tryExtract(jsxNode, sourceFile, workflowId) {
|
|
156
|
+
const rootInfo = getJsxRootInfo(jsxNode);
|
|
157
|
+
if (!rootInfo)
|
|
158
|
+
return null;
|
|
159
|
+
const importInfo = findImportForIdentifier(sourceFile, rootInfo.tagName);
|
|
160
|
+
if (!importInfo)
|
|
161
|
+
return null;
|
|
162
|
+
const id = makeId(sourceFile, rootInfo.tagName, componentIndex++);
|
|
163
|
+
result.components.push({
|
|
164
|
+
id,
|
|
165
|
+
workflowId,
|
|
166
|
+
componentName: rootInfo.tagName,
|
|
167
|
+
importModuleSpecifier: importInfo.moduleSpecifier,
|
|
168
|
+
importIsDefault: importInfo.isDefault,
|
|
169
|
+
sourceFile,
|
|
170
|
+
});
|
|
171
|
+
return { id, propsObj: jsxAttributesToObjectLiteral(rootInfo.attributes) };
|
|
172
|
+
}
|
|
173
|
+
const visitor = (node) => {
|
|
174
|
+
const renderWorkflow = isRenderCallWithJsx(node)
|
|
175
|
+
? findEnclosingWorkflow(node)
|
|
176
|
+
: null;
|
|
177
|
+
if (isRenderCallWithJsx(node) && renderWorkflow) {
|
|
178
|
+
const jsxArg = node.arguments[0];
|
|
179
|
+
const extracted = tryExtract(jsxArg, sf, renderWorkflow.workflowId);
|
|
180
|
+
if (extracted) {
|
|
181
|
+
processedCallExpressions.add(jsxArg);
|
|
182
|
+
return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [
|
|
183
|
+
ts.factory.createStringLiteral(extracted.id),
|
|
184
|
+
extracted.propsObj,
|
|
185
|
+
]);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (isJsxNode(node) && !processedCallExpressions.has(node) && !isNestedInsideJsx(node)) {
|
|
189
|
+
const standaloneWorkflow = findEnclosingWorkflow(node);
|
|
190
|
+
if (!standaloneWorkflow)
|
|
191
|
+
return ts.visitEachChild(node, visitor, ctx);
|
|
192
|
+
const extracted = tryExtract(node, sf, standaloneWorkflow.workflowId);
|
|
193
|
+
if (extracted) {
|
|
194
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('__rscRef'), undefined, [
|
|
195
|
+
ts.factory.createStringLiteral(extracted.id),
|
|
196
|
+
extracted.propsObj,
|
|
197
|
+
]);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return ts.visitEachChild(node, visitor, ctx);
|
|
201
|
+
};
|
|
202
|
+
return ts.visitNode(sf, visitor);
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=extract-workflow-jsx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-workflow-jsx.js","sourceRoot":"","sources":["../../src/tools/extract-workflow-jsx.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export function componentKey(comp) {
|
|
4
|
+
return `${comp.importModuleSpecifier}::${comp.componentName}`;
|
|
5
|
+
}
|
|
6
|
+
export async function generateRscEntries(opts) {
|
|
7
|
+
const { outDir, components } = opts;
|
|
8
|
+
if (components.length === 0)
|
|
9
|
+
return null;
|
|
10
|
+
await fs.mkdir(outDir, { recursive: true });
|
|
11
|
+
const unique = new Map();
|
|
12
|
+
for (const c of components) {
|
|
13
|
+
const key = componentKey(c);
|
|
14
|
+
if (!unique.has(key))
|
|
15
|
+
unique.set(key, c);
|
|
16
|
+
}
|
|
17
|
+
const rscEntry = path.join(outDir, 'rsc-entry.tsx');
|
|
18
|
+
const ssrEntry = path.join(outDir, 'ssr-entry.tsx');
|
|
19
|
+
const browserEntry = path.join(outDir, 'browser-entry.tsx');
|
|
20
|
+
const importLines = [];
|
|
21
|
+
const registryEntries = [];
|
|
22
|
+
let i = 0;
|
|
23
|
+
for (const [, comp] of unique) {
|
|
24
|
+
const alias = `__Comp${i}__`;
|
|
25
|
+
const importSpecifier = resolveComponentImport(rscEntry, comp);
|
|
26
|
+
importLines.push(comp.importIsDefault
|
|
27
|
+
? `import ${alias} from '${importSpecifier}'`
|
|
28
|
+
: `import { ${comp.componentName} as ${alias} } from '${importSpecifier}'`);
|
|
29
|
+
registryEntries.push(` '${comp.componentName}': ${alias},`);
|
|
30
|
+
i++;
|
|
31
|
+
}
|
|
32
|
+
const rscContent = `/* Auto-generated RSC entry — do not edit */
|
|
33
|
+
${importLines.join('\n')}
|
|
34
|
+
|
|
35
|
+
const registry: Record<string, React.ComponentType<any>> = {
|
|
36
|
+
${registryEntries.join('\n')}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default function RscEntry(props: { componentId: string; componentProps: Record<string, unknown> }) {
|
|
40
|
+
const Component = registry[props.componentId]
|
|
41
|
+
if (!Component) throw new Error('RSC component not found: ' + props.componentId)
|
|
42
|
+
return <Component {...props.componentProps} />
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
45
|
+
await fs.writeFile(rscEntry, rscContent, 'utf8');
|
|
46
|
+
const ssrContent = `/* Auto-generated SSR entry — do not edit */
|
|
47
|
+
import { createFromReadableStream } from '@vitejs/plugin-rsc/ssr'
|
|
48
|
+
import { renderToReadableStream } from 'react-dom/server.edge'
|
|
49
|
+
|
|
50
|
+
export async function handleSsr(
|
|
51
|
+
rscStream: ReadableStream,
|
|
52
|
+
bootstrapScriptContent?: string,
|
|
53
|
+
) {
|
|
54
|
+
const root = await createFromReadableStream(rscStream)
|
|
55
|
+
|
|
56
|
+
const htmlStream = await renderToReadableStream(root, {
|
|
57
|
+
bootstrapScriptContent,
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
return htmlStream
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
await fs.writeFile(ssrEntry, ssrContent, 'utf8');
|
|
64
|
+
const browserContent = `/* Auto-generated browser entry — do not edit */
|
|
65
|
+
import { createFromReadableStream } from '@vitejs/plugin-rsc/browser'
|
|
66
|
+
import { hydrateRoot } from 'react-dom/client'
|
|
67
|
+
|
|
68
|
+
declare const __RSC_STREAM_URL__: string
|
|
69
|
+
|
|
70
|
+
async function main() {
|
|
71
|
+
const response = await fetch(__RSC_STREAM_URL__)
|
|
72
|
+
|
|
73
|
+
if (!response.body) throw new Error('No RSC stream body')
|
|
74
|
+
|
|
75
|
+
const root = await createFromReadableStream(response.body)
|
|
76
|
+
const container = document.getElementById('root')
|
|
77
|
+
|
|
78
|
+
if (!container) throw new Error('No #root element found')
|
|
79
|
+
|
|
80
|
+
hydrateRoot(container, root)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
main()
|
|
84
|
+
`;
|
|
85
|
+
await fs.writeFile(browserEntry, browserContent, 'utf8');
|
|
86
|
+
return {
|
|
87
|
+
componentMap: unique,
|
|
88
|
+
rscEntry,
|
|
89
|
+
ssrEntry,
|
|
90
|
+
browserEntry,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function resolveComponentImport(entryFile, comp) {
|
|
94
|
+
const specifier = comp.importModuleSpecifier;
|
|
95
|
+
if (!specifier.startsWith('.') && !specifier.startsWith('/')) {
|
|
96
|
+
return specifier;
|
|
97
|
+
}
|
|
98
|
+
const sourceFileDir = path.dirname(comp.sourceFile.fileName);
|
|
99
|
+
const absoluteImport = path.resolve(sourceFileDir, specifier);
|
|
100
|
+
const relativeFromEntry = path.relative(path.dirname(entryFile), absoluteImport);
|
|
101
|
+
return relativeFromEntry.startsWith('.')
|
|
102
|
+
? relativeFromEntry
|
|
103
|
+
: `./${relativeFromEntry}`;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=generate-rsc-entries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-rsc-entries.js","sourceRoot":"","sources":["../../src/tools/generate-rsc-entries.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Binary } from '@t4h.framework/core';
|
|
2
|
+
import { Body, OAuth2ClientCredentials, OAuth2GrantResourceOwnerPassword, } from '@t4h.framework/http';
|
|
3
|
+
import { ORM } from '@t4h.framework/orm';
|
|
4
|
+
import { DevServerFileBinary } from '../models/DevServerFileBinary.js';
|
|
5
|
+
import { JSONCodec, JSONCodecKind } from '../models/JSONCodec.js';
|
|
6
|
+
import { JSONCodecKindFrameworkSerializableClass as Kind } from '../models/JSONCodecKindFrameworkSerializableClass.js';
|
|
7
|
+
// interface FileBinaryParseOptions {
|
|
8
|
+
// fileBinaryToStream: (fileBinary: FileBinary) => Readable | Promise<Readable>
|
|
9
|
+
// }
|
|
10
|
+
const jsonDateKind = new JSONCodecKind('date', value => value instanceof Date, (date) => date.toISOString(), (date) => new Date(date));
|
|
11
|
+
const jsonBinaryKind = new JSONCodecKind('binary', value => value instanceof Binary, (binary) => {
|
|
12
|
+
if (!(binary instanceof DevServerFileBinary))
|
|
13
|
+
throw new TypeError('Unsupported binary instance');
|
|
14
|
+
return binary.toJSON();
|
|
15
|
+
}, json => DevServerFileBinary.from(json));
|
|
16
|
+
export const jsonCodec = new JSONCodec(jsonDateKind, jsonBinaryKind, new Kind('orm', ORM), new Kind('http:body', Body), new Kind('oauth2:client-credentials-grant', OAuth2ClientCredentials), new Kind('oauth2:grant-resource-owner-password', OAuth2GrantResourceOwnerPassword));
|
|
17
|
+
//# sourceMappingURL=json-codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-codec.js","sourceRoot":"","sources":["../../src/tools/json-codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EACL,IAAI,EACJ,uBAAuB,EACvB,gCAAgC,GACjC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AAExC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AACtE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,uCAAuC,IAAI,IAAI,EAAE,MAAM,sDAAsD,CAAA;AAEtH,qCAAqC;AACrC,iFAAiF;AACjF,IAAI;AAEJ,MAAM,YAAY,GAAG,IAAI,aAAa,CACpC,MAAM,EACN,KAAK,CAAC,EAAE,CAAC,KAAK,YAAY,IAAI,EAC9B,CAAC,IAAU,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAClC,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CACjC,CAAA;AAED,MAAM,cAAc,GAAG,IAAI,aAAa,CACtC,QAAQ,EACR,KAAK,CAAC,EAAE,CAAC,KAAK,YAAY,MAAM,EAChC,CAAC,MAAc,EAAE,EAAE;IACjB,IAAI,CAAC,CAAC,MAAM,YAAY,mBAAmB,CAAC;QAC1C,MAAM,IAAI,SAAS,CAAC,6BAA6B,CAAC,CAAA;IAEpD,OAAO,MAAM,CAAC,MAAM,EAAE,CAAA;AACxB,CAAC,EACD,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CACvC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,SAAS,CACpC,YAAY,EACZ,cAAc,EACd,IAAI,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,EACpB,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,EAC3B,IAAI,IAAI,CAAC,iCAAiC,EAAE,uBAAuB,CAAC,EACpE,IAAI,IAAI,CACN,sCAAsC,EACtC,gCAAgC,CACjC,CACF,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { input, number } from '@inquirer/prompts';
|
|
2
|
+
export async function jsonSchemaToInquirerQuestion(schema, context = {}) {
|
|
3
|
+
if (typeof schema === 'boolean')
|
|
4
|
+
return;
|
|
5
|
+
if (schema.type === 'object')
|
|
6
|
+
return jsonSchemaObjectToInquirerQuestion(schema, context);
|
|
7
|
+
if (schema.type === 'string')
|
|
8
|
+
return jsonSchemaStringToInquirerQuestion(schema, context);
|
|
9
|
+
if (schema.type === 'number')
|
|
10
|
+
return jsonSchemaNumberToInquirerQuestion(schema, context);
|
|
11
|
+
}
|
|
12
|
+
export async function jsonSchemaObjectToInquirerQuestion(schema, context) {
|
|
13
|
+
const result = {};
|
|
14
|
+
for (const [key, property] of Object.entries(schema.properties ?? {})) {
|
|
15
|
+
const isRequired = schema.required?.includes(key);
|
|
16
|
+
result[key] = await jsonSchemaToInquirerQuestion(property, {
|
|
17
|
+
key: context.key ? `${context.key}.${key}` : key,
|
|
18
|
+
isOptional: !isRequired,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
export async function jsonSchemaStringToInquirerQuestion(schema, context) {
|
|
24
|
+
return input({
|
|
25
|
+
message: `${context.key ? context.key : ''}${context.key && schema.description ? ': ' : ''}${schema.description ?? ''}`,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
export async function jsonSchemaNumberToInquirerQuestion(schema, context) {
|
|
29
|
+
return number({
|
|
30
|
+
message: `${context.key ? context.key : ''}${context.key && schema.description ? ': ' : ''}${schema.description ?? ''}`,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=json-schema-to-inquirer-question.js.map
|