@constructive-io/graphql-codegen 4.12.2 → 4.13.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/core/codegen/cli/command-map-generator.d.ts +1 -0
- package/core/codegen/cli/command-map-generator.js +4 -0
- package/core/codegen/cli/config-command-generator.d.ts +11 -0
- package/core/codegen/cli/config-command-generator.js +458 -0
- package/core/codegen/cli/helpers-generator.d.ts +15 -0
- package/core/codegen/cli/helpers-generator.js +119 -0
- package/core/codegen/cli/index.d.ts +4 -0
- package/core/codegen/cli/index.js +21 -3
- package/core/codegen/orm/index.js +3 -2
- package/core/codegen/orm/input-types-generator.d.ts +3 -1
- package/core/codegen/orm/input-types-generator.js +14 -6
- package/core/codegen/orm/model-generator.d.ts +6 -2
- package/core/codegen/orm/model-generator.js +59 -37
- package/core/codegen/templates/query-builder.ts +2 -2
- package/core/codegen/templates/select-types.ts +2 -2
- package/esm/core/codegen/cli/command-map-generator.d.ts +1 -0
- package/esm/core/codegen/cli/command-map-generator.js +4 -0
- package/esm/core/codegen/cli/config-command-generator.d.ts +11 -0
- package/esm/core/codegen/cli/config-command-generator.js +422 -0
- package/esm/core/codegen/cli/helpers-generator.d.ts +15 -0
- package/esm/core/codegen/cli/helpers-generator.js +83 -0
- package/esm/core/codegen/cli/index.d.ts +4 -0
- package/esm/core/codegen/cli/index.js +18 -2
- package/esm/core/codegen/orm/index.js +3 -2
- package/esm/core/codegen/orm/input-types-generator.d.ts +3 -1
- package/esm/core/codegen/orm/input-types-generator.js +14 -6
- package/esm/core/codegen/orm/model-generator.d.ts +6 -2
- package/esm/core/codegen/orm/model-generator.js +59 -37
- package/esm/types/config.d.ts +9 -0
- package/esm/types/config.js +1 -0
- package/package.json +4 -4
- package/types/config.d.ts +9 -0
- package/types/config.js +1 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
import * as t from '@babel/types';
|
|
2
|
+
import { generateCode } from '../babel-ast';
|
|
3
|
+
import { getGeneratedFileHeader } from '../utils';
|
|
4
|
+
function createImportDeclaration(moduleSpecifier, namedImports, typeOnly = false) {
|
|
5
|
+
const specifiers = namedImports.map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
|
|
6
|
+
const decl = t.importDeclaration(specifiers, t.stringLiteral(moduleSpecifier));
|
|
7
|
+
decl.importKind = typeOnly ? 'type' : 'value';
|
|
8
|
+
return decl;
|
|
9
|
+
}
|
|
10
|
+
function buildSwitchCase(testValue, handlerName, args) {
|
|
11
|
+
return t.switchCase(t.stringLiteral(testValue), [
|
|
12
|
+
t.returnStatement(t.callExpression(t.identifier(handlerName), args)),
|
|
13
|
+
]);
|
|
14
|
+
}
|
|
15
|
+
function buildDefaultSwitchCase(usageVarName) {
|
|
16
|
+
return t.switchCase(null, [
|
|
17
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('log')), [t.identifier(usageVarName)])),
|
|
18
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('process'), t.identifier('exit')), [t.numericLiteral(1)])),
|
|
19
|
+
]);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generate the config command file (get/set/list/delete for per-context vars).
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* <tool> config get <key>
|
|
26
|
+
* <tool> config set <key> <value>
|
|
27
|
+
* <tool> config list
|
|
28
|
+
* <tool> config delete <key>
|
|
29
|
+
*/
|
|
30
|
+
export function generateConfigCommand(toolName, commandName) {
|
|
31
|
+
const statements = [];
|
|
32
|
+
statements.push(createImportDeclaration('inquirerer', [
|
|
33
|
+
'CLIOptions',
|
|
34
|
+
'Inquirerer',
|
|
35
|
+
'extractFirst',
|
|
36
|
+
]));
|
|
37
|
+
statements.push(createImportDeclaration('../executor', ['getStore']));
|
|
38
|
+
const usageStr = `
|
|
39
|
+
${toolName} ${commandName} <command>
|
|
40
|
+
|
|
41
|
+
Commands:
|
|
42
|
+
get <key> Get a config value
|
|
43
|
+
set <key> <value> Set a config value
|
|
44
|
+
list List all config values
|
|
45
|
+
delete <key> Delete a config value
|
|
46
|
+
|
|
47
|
+
--help, -h Show this help message
|
|
48
|
+
`;
|
|
49
|
+
statements.push(t.variableDeclaration('const', [
|
|
50
|
+
t.variableDeclarator(t.identifier('usage'), t.stringLiteral(usageStr)),
|
|
51
|
+
]));
|
|
52
|
+
// Main export: default async (argv, prompter, _options) => { ... }
|
|
53
|
+
const argvParam = t.identifier('argv');
|
|
54
|
+
argvParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Partial'), t.tsTypeParameterInstantiation([
|
|
55
|
+
t.tsTypeReference(t.identifier('Record'), t.tsTypeParameterInstantiation([
|
|
56
|
+
t.tsStringKeyword(),
|
|
57
|
+
t.tsUnknownKeyword(),
|
|
58
|
+
])),
|
|
59
|
+
])));
|
|
60
|
+
const prompterParam = t.identifier('prompter');
|
|
61
|
+
prompterParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Inquirerer')));
|
|
62
|
+
const optionsParam = t.identifier('_options');
|
|
63
|
+
optionsParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('CLIOptions')));
|
|
64
|
+
const mainBody = [
|
|
65
|
+
// Help check
|
|
66
|
+
t.ifStatement(t.logicalExpression('||', t.memberExpression(t.identifier('argv'), t.identifier('help')), t.memberExpression(t.identifier('argv'), t.identifier('h'))), t.blockStatement([
|
|
67
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('log')), [t.identifier('usage')])),
|
|
68
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('process'), t.identifier('exit')), [t.numericLiteral(0)])),
|
|
69
|
+
])),
|
|
70
|
+
// const store = getStore();
|
|
71
|
+
t.variableDeclaration('const', [
|
|
72
|
+
t.variableDeclarator(t.identifier('store'), t.callExpression(t.identifier('getStore'), [])),
|
|
73
|
+
]),
|
|
74
|
+
// const { first: subcommand, newArgv } = extractFirst(argv);
|
|
75
|
+
t.variableDeclaration('const', [
|
|
76
|
+
t.variableDeclarator(t.objectPattern([
|
|
77
|
+
t.objectProperty(t.identifier('first'), t.identifier('subcommand')),
|
|
78
|
+
t.objectProperty(t.identifier('newArgv'), t.identifier('newArgv'), false, true),
|
|
79
|
+
]), t.callExpression(t.identifier('extractFirst'), [
|
|
80
|
+
t.identifier('argv'),
|
|
81
|
+
])),
|
|
82
|
+
]),
|
|
83
|
+
// If no subcommand, prompt
|
|
84
|
+
t.ifStatement(t.unaryExpression('!', t.identifier('subcommand')), t.blockStatement([
|
|
85
|
+
t.variableDeclaration('const', [
|
|
86
|
+
t.variableDeclarator(t.identifier('answer'), t.awaitExpression(t.callExpression(t.memberExpression(t.identifier('prompter'), t.identifier('prompt')), [
|
|
87
|
+
t.identifier('argv'),
|
|
88
|
+
t.arrayExpression([
|
|
89
|
+
t.objectExpression([
|
|
90
|
+
t.objectProperty(t.identifier('type'), t.stringLiteral('autocomplete')),
|
|
91
|
+
t.objectProperty(t.identifier('name'), t.stringLiteral('subcommand')),
|
|
92
|
+
t.objectProperty(t.identifier('message'), t.stringLiteral('What do you want to do?')),
|
|
93
|
+
t.objectProperty(t.identifier('options'), t.arrayExpression([
|
|
94
|
+
t.stringLiteral('get'),
|
|
95
|
+
t.stringLiteral('set'),
|
|
96
|
+
t.stringLiteral('list'),
|
|
97
|
+
t.stringLiteral('delete'),
|
|
98
|
+
])),
|
|
99
|
+
]),
|
|
100
|
+
]),
|
|
101
|
+
]))),
|
|
102
|
+
]),
|
|
103
|
+
t.returnStatement(t.callExpression(t.identifier('handleSubcommand'), [
|
|
104
|
+
t.memberExpression(t.identifier('answer'), t.identifier('subcommand')),
|
|
105
|
+
t.identifier('newArgv'),
|
|
106
|
+
t.identifier('prompter'),
|
|
107
|
+
t.identifier('store'),
|
|
108
|
+
])),
|
|
109
|
+
])),
|
|
110
|
+
t.returnStatement(t.callExpression(t.identifier('handleSubcommand'), [
|
|
111
|
+
t.identifier('subcommand'),
|
|
112
|
+
t.identifier('newArgv'),
|
|
113
|
+
t.identifier('prompter'),
|
|
114
|
+
t.identifier('store'),
|
|
115
|
+
])),
|
|
116
|
+
];
|
|
117
|
+
const mainExport = t.exportDefaultDeclaration(t.arrowFunctionExpression([argvParam, prompterParam, optionsParam], t.blockStatement(mainBody), true));
|
|
118
|
+
statements.push(mainExport);
|
|
119
|
+
// handleSubcommand function
|
|
120
|
+
const subcmdParam = t.identifier('subcommand');
|
|
121
|
+
subcmdParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword());
|
|
122
|
+
const argvParam2 = t.identifier('argv');
|
|
123
|
+
argvParam2.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Partial'), t.tsTypeParameterInstantiation([
|
|
124
|
+
t.tsTypeReference(t.identifier('Record'), t.tsTypeParameterInstantiation([
|
|
125
|
+
t.tsStringKeyword(),
|
|
126
|
+
t.tsUnknownKeyword(),
|
|
127
|
+
])),
|
|
128
|
+
])));
|
|
129
|
+
const prompterParam2 = t.identifier('prompter');
|
|
130
|
+
prompterParam2.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Inquirerer')));
|
|
131
|
+
const storeParam = t.identifier('store');
|
|
132
|
+
storeParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('ReturnType'), t.tsTypeParameterInstantiation([
|
|
133
|
+
t.tsTypeQuery(t.identifier('getStore')),
|
|
134
|
+
])));
|
|
135
|
+
const handleSubcommandFunc = t.functionDeclaration(t.identifier('handleSubcommand'), [subcmdParam, argvParam2, prompterParam2, storeParam], t.blockStatement([
|
|
136
|
+
t.switchStatement(t.identifier('subcommand'), [
|
|
137
|
+
buildSwitchCase('get', 'handleGet', [
|
|
138
|
+
t.identifier('argv'),
|
|
139
|
+
t.identifier('prompter'),
|
|
140
|
+
t.identifier('store'),
|
|
141
|
+
]),
|
|
142
|
+
buildSwitchCase('set', 'handleSet', [
|
|
143
|
+
t.identifier('argv'),
|
|
144
|
+
t.identifier('prompter'),
|
|
145
|
+
t.identifier('store'),
|
|
146
|
+
]),
|
|
147
|
+
buildSwitchCase('list', 'handleList', [t.identifier('store')]),
|
|
148
|
+
buildSwitchCase('delete', 'handleDelete', [
|
|
149
|
+
t.identifier('argv'),
|
|
150
|
+
t.identifier('prompter'),
|
|
151
|
+
t.identifier('store'),
|
|
152
|
+
]),
|
|
153
|
+
buildDefaultSwitchCase('usage'),
|
|
154
|
+
]),
|
|
155
|
+
]), false, true);
|
|
156
|
+
statements.push(handleSubcommandFunc);
|
|
157
|
+
// handleGet
|
|
158
|
+
statements.push(buildGetHandler());
|
|
159
|
+
// handleSet
|
|
160
|
+
statements.push(buildSetHandler());
|
|
161
|
+
// handleList
|
|
162
|
+
statements.push(buildListHandler());
|
|
163
|
+
// handleDelete
|
|
164
|
+
statements.push(buildDeleteHandler());
|
|
165
|
+
const header = getGeneratedFileHeader('Config key-value store commands');
|
|
166
|
+
const code = generateCode(statements);
|
|
167
|
+
return {
|
|
168
|
+
fileName: `commands/${commandName}.ts`,
|
|
169
|
+
content: header + '\n' + code,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function buildGetHandler() {
|
|
173
|
+
const argvParam = t.identifier('argv');
|
|
174
|
+
argvParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Partial'), t.tsTypeParameterInstantiation([
|
|
175
|
+
t.tsTypeReference(t.identifier('Record'), t.tsTypeParameterInstantiation([
|
|
176
|
+
t.tsStringKeyword(),
|
|
177
|
+
t.tsUnknownKeyword(),
|
|
178
|
+
])),
|
|
179
|
+
])));
|
|
180
|
+
const prompterParam = t.identifier('prompter');
|
|
181
|
+
prompterParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Inquirerer')));
|
|
182
|
+
const storeParam = t.identifier('store');
|
|
183
|
+
storeParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('ReturnType'), t.tsTypeParameterInstantiation([
|
|
184
|
+
t.tsTypeQuery(t.identifier('getStore')),
|
|
185
|
+
])));
|
|
186
|
+
const body = [
|
|
187
|
+
// const { first: key } = extractFirst(argv);
|
|
188
|
+
t.variableDeclaration('const', [
|
|
189
|
+
t.variableDeclarator(t.objectPattern([
|
|
190
|
+
t.objectProperty(t.identifier('first'), t.identifier('key')),
|
|
191
|
+
]), t.callExpression(t.identifier('extractFirst'), [
|
|
192
|
+
t.identifier('argv'),
|
|
193
|
+
])),
|
|
194
|
+
]),
|
|
195
|
+
// Prompt if no key
|
|
196
|
+
t.ifStatement(t.unaryExpression('!', t.identifier('key')), t.blockStatement([
|
|
197
|
+
t.variableDeclaration('const', [
|
|
198
|
+
t.variableDeclarator(t.identifier('answers'), t.awaitExpression(t.callExpression(t.memberExpression(t.identifier('prompter'), t.identifier('prompt')), [
|
|
199
|
+
t.identifier('argv'),
|
|
200
|
+
t.arrayExpression([
|
|
201
|
+
t.objectExpression([
|
|
202
|
+
t.objectProperty(t.identifier('type'), t.stringLiteral('text')),
|
|
203
|
+
t.objectProperty(t.identifier('name'), t.stringLiteral('key')),
|
|
204
|
+
t.objectProperty(t.identifier('message'), t.stringLiteral('Config key')),
|
|
205
|
+
t.objectProperty(t.identifier('required'), t.booleanLiteral(true)),
|
|
206
|
+
]),
|
|
207
|
+
]),
|
|
208
|
+
]))),
|
|
209
|
+
]),
|
|
210
|
+
t.variableDeclaration('const', [
|
|
211
|
+
t.variableDeclarator(t.identifier('value'), t.callExpression(t.memberExpression(t.identifier('store'), t.identifier('getVar')), [t.memberExpression(t.identifier('answers'), t.identifier('key'))])),
|
|
212
|
+
]),
|
|
213
|
+
t.ifStatement(t.binaryExpression('===', t.identifier('value'), t.identifier('undefined')), t.blockStatement([
|
|
214
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('error')), [
|
|
215
|
+
t.templateLiteral([
|
|
216
|
+
t.templateElement({ raw: 'Key "', cooked: 'Key "' }),
|
|
217
|
+
t.templateElement({ raw: '" not found.', cooked: '" not found.' }, true),
|
|
218
|
+
], [t.memberExpression(t.identifier('answers'), t.identifier('key'))]),
|
|
219
|
+
])),
|
|
220
|
+
]), t.blockStatement([
|
|
221
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('log')), [t.identifier('value')])),
|
|
222
|
+
])),
|
|
223
|
+
t.returnStatement(),
|
|
224
|
+
])),
|
|
225
|
+
// const value = store.getVar(key);
|
|
226
|
+
t.variableDeclaration('const', [
|
|
227
|
+
t.variableDeclarator(t.identifier('value'), t.callExpression(t.memberExpression(t.identifier('store'), t.identifier('getVar')), [t.identifier('key')])),
|
|
228
|
+
]),
|
|
229
|
+
t.ifStatement(t.binaryExpression('===', t.identifier('value'), t.identifier('undefined')), t.blockStatement([
|
|
230
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('error')), [
|
|
231
|
+
t.templateLiteral([
|
|
232
|
+
t.templateElement({ raw: 'Key "', cooked: 'Key "' }),
|
|
233
|
+
t.templateElement({ raw: '" not found.', cooked: '" not found.' }, true),
|
|
234
|
+
], [t.identifier('key')]),
|
|
235
|
+
])),
|
|
236
|
+
]), t.blockStatement([
|
|
237
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('log')), [t.identifier('value')])),
|
|
238
|
+
])),
|
|
239
|
+
];
|
|
240
|
+
return t.functionDeclaration(t.identifier('handleGet'), [argvParam, prompterParam, storeParam], t.blockStatement(body), false, true);
|
|
241
|
+
}
|
|
242
|
+
function buildSetHandler() {
|
|
243
|
+
const argvParam = t.identifier('argv');
|
|
244
|
+
argvParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Partial'), t.tsTypeParameterInstantiation([
|
|
245
|
+
t.tsTypeReference(t.identifier('Record'), t.tsTypeParameterInstantiation([
|
|
246
|
+
t.tsStringKeyword(),
|
|
247
|
+
t.tsUnknownKeyword(),
|
|
248
|
+
])),
|
|
249
|
+
])));
|
|
250
|
+
const prompterParam = t.identifier('prompter');
|
|
251
|
+
prompterParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Inquirerer')));
|
|
252
|
+
const storeParam = t.identifier('store');
|
|
253
|
+
storeParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('ReturnType'), t.tsTypeParameterInstantiation([
|
|
254
|
+
t.tsTypeQuery(t.identifier('getStore')),
|
|
255
|
+
])));
|
|
256
|
+
const body = [
|
|
257
|
+
// const { first: key, newArgv: restArgv } = extractFirst(argv);
|
|
258
|
+
t.variableDeclaration('const', [
|
|
259
|
+
t.variableDeclarator(t.objectPattern([
|
|
260
|
+
t.objectProperty(t.identifier('first'), t.identifier('key')),
|
|
261
|
+
t.objectProperty(t.identifier('newArgv'), t.identifier('restArgv')),
|
|
262
|
+
]), t.callExpression(t.identifier('extractFirst'), [
|
|
263
|
+
t.identifier('argv'),
|
|
264
|
+
])),
|
|
265
|
+
]),
|
|
266
|
+
// const { first: value } = extractFirst(restArgv);
|
|
267
|
+
t.variableDeclaration('const', [
|
|
268
|
+
t.variableDeclarator(t.objectPattern([
|
|
269
|
+
t.objectProperty(t.identifier('first'), t.identifier('value')),
|
|
270
|
+
]), t.callExpression(t.identifier('extractFirst'), [
|
|
271
|
+
t.identifier('restArgv'),
|
|
272
|
+
])),
|
|
273
|
+
]),
|
|
274
|
+
// Prompt if missing key or value
|
|
275
|
+
t.ifStatement(t.logicalExpression('||', t.unaryExpression('!', t.identifier('key')), t.unaryExpression('!', t.identifier('value'))), t.blockStatement([
|
|
276
|
+
t.variableDeclaration('const', [
|
|
277
|
+
t.variableDeclarator(t.identifier('answers'), t.awaitExpression(t.callExpression(t.memberExpression(t.identifier('prompter'), t.identifier('prompt')), [
|
|
278
|
+
t.objectExpression([
|
|
279
|
+
t.objectProperty(t.identifier('key'), t.identifier('key'), false, true),
|
|
280
|
+
t.objectProperty(t.identifier('value'), t.identifier('value'), false, true),
|
|
281
|
+
]),
|
|
282
|
+
t.arrayExpression([
|
|
283
|
+
t.objectExpression([
|
|
284
|
+
t.objectProperty(t.identifier('type'), t.stringLiteral('text')),
|
|
285
|
+
t.objectProperty(t.identifier('name'), t.stringLiteral('key')),
|
|
286
|
+
t.objectProperty(t.identifier('message'), t.stringLiteral('Config key')),
|
|
287
|
+
t.objectProperty(t.identifier('required'), t.booleanLiteral(true)),
|
|
288
|
+
]),
|
|
289
|
+
t.objectExpression([
|
|
290
|
+
t.objectProperty(t.identifier('type'), t.stringLiteral('text')),
|
|
291
|
+
t.objectProperty(t.identifier('name'), t.stringLiteral('value')),
|
|
292
|
+
t.objectProperty(t.identifier('message'), t.stringLiteral('Config value')),
|
|
293
|
+
t.objectProperty(t.identifier('required'), t.booleanLiteral(true)),
|
|
294
|
+
]),
|
|
295
|
+
]),
|
|
296
|
+
]))),
|
|
297
|
+
]),
|
|
298
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('store'), t.identifier('setVar')), [
|
|
299
|
+
t.memberExpression(t.identifier('answers'), t.identifier('key')),
|
|
300
|
+
t.callExpression(t.memberExpression(t.identifier('String'), t.identifier('call')), [
|
|
301
|
+
t.identifier('undefined'),
|
|
302
|
+
t.memberExpression(t.identifier('answers'), t.identifier('value')),
|
|
303
|
+
]),
|
|
304
|
+
])),
|
|
305
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('log')), [
|
|
306
|
+
t.templateLiteral([
|
|
307
|
+
t.templateElement({ raw: 'Set ', cooked: 'Set ' }),
|
|
308
|
+
t.templateElement({ raw: ' = ', cooked: ' = ' }),
|
|
309
|
+
t.templateElement({ raw: '', cooked: '' }, true),
|
|
310
|
+
], [
|
|
311
|
+
t.memberExpression(t.identifier('answers'), t.identifier('key')),
|
|
312
|
+
t.memberExpression(t.identifier('answers'), t.identifier('value')),
|
|
313
|
+
]),
|
|
314
|
+
])),
|
|
315
|
+
t.returnStatement(),
|
|
316
|
+
])),
|
|
317
|
+
// store.setVar(key, String(value));
|
|
318
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('store'), t.identifier('setVar')), [
|
|
319
|
+
t.identifier('key'),
|
|
320
|
+
t.callExpression(t.identifier('String'), [t.identifier('value')]),
|
|
321
|
+
])),
|
|
322
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('log')), [
|
|
323
|
+
t.templateLiteral([
|
|
324
|
+
t.templateElement({ raw: 'Set ', cooked: 'Set ' }),
|
|
325
|
+
t.templateElement({ raw: ' = ', cooked: ' = ' }),
|
|
326
|
+
t.templateElement({ raw: '', cooked: '' }, true),
|
|
327
|
+
], [t.identifier('key'), t.identifier('value')]),
|
|
328
|
+
])),
|
|
329
|
+
];
|
|
330
|
+
return t.functionDeclaration(t.identifier('handleSet'), [argvParam, prompterParam, storeParam], t.blockStatement(body), false, true);
|
|
331
|
+
}
|
|
332
|
+
function buildListHandler() {
|
|
333
|
+
const storeParam = t.identifier('store');
|
|
334
|
+
storeParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('ReturnType'), t.tsTypeParameterInstantiation([
|
|
335
|
+
t.tsTypeQuery(t.identifier('getStore')),
|
|
336
|
+
])));
|
|
337
|
+
const body = [
|
|
338
|
+
// const vars = store.listVars();
|
|
339
|
+
t.variableDeclaration('const', [
|
|
340
|
+
t.variableDeclarator(t.identifier('vars'), t.callExpression(t.memberExpression(t.identifier('store'), t.identifier('listVars')), [])),
|
|
341
|
+
]),
|
|
342
|
+
// const entries = Object.entries(vars);
|
|
343
|
+
t.variableDeclaration('const', [
|
|
344
|
+
t.variableDeclarator(t.identifier('entries'), t.callExpression(t.memberExpression(t.identifier('Object'), t.identifier('entries')), [t.identifier('vars')])),
|
|
345
|
+
]),
|
|
346
|
+
t.ifStatement(t.binaryExpression('===', t.memberExpression(t.identifier('entries'), t.identifier('length')), t.numericLiteral(0)), t.blockStatement([
|
|
347
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('log')), [t.stringLiteral('No config values set.')])),
|
|
348
|
+
t.returnStatement(),
|
|
349
|
+
])),
|
|
350
|
+
// for (const [key, value] of entries) { console.log(`${key} = ${value}`); }
|
|
351
|
+
t.forOfStatement(t.variableDeclaration('const', [
|
|
352
|
+
t.variableDeclarator(t.arrayPattern([t.identifier('key'), t.identifier('value')])),
|
|
353
|
+
]), t.identifier('entries'), t.blockStatement([
|
|
354
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('log')), [
|
|
355
|
+
t.templateLiteral([
|
|
356
|
+
t.templateElement({ raw: '', cooked: '' }),
|
|
357
|
+
t.templateElement({ raw: ' = ', cooked: ' = ' }),
|
|
358
|
+
t.templateElement({ raw: '', cooked: '' }, true),
|
|
359
|
+
], [t.identifier('key'), t.identifier('value')]),
|
|
360
|
+
])),
|
|
361
|
+
])),
|
|
362
|
+
];
|
|
363
|
+
return t.functionDeclaration(t.identifier('handleList'), [storeParam], t.blockStatement(body));
|
|
364
|
+
}
|
|
365
|
+
function buildDeleteHandler() {
|
|
366
|
+
const argvParam = t.identifier('argv');
|
|
367
|
+
argvParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Partial'), t.tsTypeParameterInstantiation([
|
|
368
|
+
t.tsTypeReference(t.identifier('Record'), t.tsTypeParameterInstantiation([
|
|
369
|
+
t.tsStringKeyword(),
|
|
370
|
+
t.tsUnknownKeyword(),
|
|
371
|
+
])),
|
|
372
|
+
])));
|
|
373
|
+
const prompterParam = t.identifier('prompter');
|
|
374
|
+
prompterParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('Inquirerer')));
|
|
375
|
+
const storeParam = t.identifier('store');
|
|
376
|
+
storeParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('ReturnType'), t.tsTypeParameterInstantiation([
|
|
377
|
+
t.tsTypeQuery(t.identifier('getStore')),
|
|
378
|
+
])));
|
|
379
|
+
const body = [
|
|
380
|
+
// const { first: key } = extractFirst(argv);
|
|
381
|
+
t.variableDeclaration('const', [
|
|
382
|
+
t.variableDeclarator(t.objectPattern([
|
|
383
|
+
t.objectProperty(t.identifier('first'), t.identifier('key')),
|
|
384
|
+
]), t.callExpression(t.identifier('extractFirst'), [
|
|
385
|
+
t.identifier('argv'),
|
|
386
|
+
])),
|
|
387
|
+
]),
|
|
388
|
+
// Prompt if no key
|
|
389
|
+
t.ifStatement(t.unaryExpression('!', t.identifier('key')), t.blockStatement([
|
|
390
|
+
t.variableDeclaration('const', [
|
|
391
|
+
t.variableDeclarator(t.identifier('answers'), t.awaitExpression(t.callExpression(t.memberExpression(t.identifier('prompter'), t.identifier('prompt')), [
|
|
392
|
+
t.identifier('argv'),
|
|
393
|
+
t.arrayExpression([
|
|
394
|
+
t.objectExpression([
|
|
395
|
+
t.objectProperty(t.identifier('type'), t.stringLiteral('text')),
|
|
396
|
+
t.objectProperty(t.identifier('name'), t.stringLiteral('key')),
|
|
397
|
+
t.objectProperty(t.identifier('message'), t.stringLiteral('Config key to delete')),
|
|
398
|
+
t.objectProperty(t.identifier('required'), t.booleanLiteral(true)),
|
|
399
|
+
]),
|
|
400
|
+
]),
|
|
401
|
+
]))),
|
|
402
|
+
]),
|
|
403
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('store'), t.identifier('deleteVar')), [t.memberExpression(t.identifier('answers'), t.identifier('key'))])),
|
|
404
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('log')), [
|
|
405
|
+
t.templateLiteral([
|
|
406
|
+
t.templateElement({ raw: 'Deleted key: ', cooked: 'Deleted key: ' }),
|
|
407
|
+
t.templateElement({ raw: '', cooked: '' }, true),
|
|
408
|
+
], [t.memberExpression(t.identifier('answers'), t.identifier('key'))]),
|
|
409
|
+
])),
|
|
410
|
+
t.returnStatement(),
|
|
411
|
+
])),
|
|
412
|
+
// store.deleteVar(key);
|
|
413
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('store'), t.identifier('deleteVar')), [t.identifier('key')])),
|
|
414
|
+
t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('console'), t.identifier('log')), [
|
|
415
|
+
t.templateLiteral([
|
|
416
|
+
t.templateElement({ raw: 'Deleted key: ', cooked: 'Deleted key: ' }),
|
|
417
|
+
t.templateElement({ raw: '', cooked: '' }, true),
|
|
418
|
+
], [t.identifier('key')]),
|
|
419
|
+
])),
|
|
420
|
+
];
|
|
421
|
+
return t.functionDeclaration(t.identifier('handleDelete'), [argvParam, prompterParam, storeParam], t.blockStatement(body), false, true);
|
|
422
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { GeneratedFile } from './executor-generator';
|
|
2
|
+
export interface HelpersGeneratorInput {
|
|
3
|
+
name: string;
|
|
4
|
+
ormImportPath: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Generate helpers.ts with typed per-target client factories.
|
|
8
|
+
*
|
|
9
|
+
* Each target gets a `createXxxClient(contextName?)` function that uses
|
|
10
|
+
* `store.getClientConfig(targetName, contextName)` under the hood with
|
|
11
|
+
* 3-tier resolution: appstash store -> env vars -> throw.
|
|
12
|
+
*
|
|
13
|
+
* Also re-exports the store for direct config/var access.
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateHelpersFile(toolName: string, targets: HelpersGeneratorInput[]): GeneratedFile;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import * as t from '@babel/types';
|
|
2
|
+
import { generateCode } from '../babel-ast';
|
|
3
|
+
import { getGeneratedFileHeader } from '../utils';
|
|
4
|
+
function createImportDeclaration(moduleSpecifier, namedImports, typeOnly = false) {
|
|
5
|
+
const specifiers = namedImports.map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
|
|
6
|
+
const decl = t.importDeclaration(specifiers, t.stringLiteral(moduleSpecifier));
|
|
7
|
+
decl.importKind = typeOnly ? 'type' : 'value';
|
|
8
|
+
return decl;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Generate helpers.ts with typed per-target client factories.
|
|
12
|
+
*
|
|
13
|
+
* Each target gets a `createXxxClient(contextName?)` function that uses
|
|
14
|
+
* `store.getClientConfig(targetName, contextName)` under the hood with
|
|
15
|
+
* 3-tier resolution: appstash store -> env vars -> throw.
|
|
16
|
+
*
|
|
17
|
+
* Also re-exports the store for direct config/var access.
|
|
18
|
+
*/
|
|
19
|
+
export function generateHelpersFile(toolName, targets) {
|
|
20
|
+
const statements = [];
|
|
21
|
+
// import { createConfigStore } from 'appstash';
|
|
22
|
+
statements.push(createImportDeclaration('appstash', ['createConfigStore']));
|
|
23
|
+
// import type { ClientConfig } from 'appstash';
|
|
24
|
+
statements.push(createImportDeclaration('appstash', ['ClientConfig'], true));
|
|
25
|
+
// Import createClient from each target's ORM
|
|
26
|
+
for (const target of targets) {
|
|
27
|
+
const aliasName = `create${target.name[0].toUpperCase()}${target.name.slice(1)}OrmClient`;
|
|
28
|
+
const specifier = t.importSpecifier(t.identifier(aliasName), t.identifier('createClient'));
|
|
29
|
+
statements.push(t.importDeclaration([specifier], t.stringLiteral(target.ormImportPath)));
|
|
30
|
+
}
|
|
31
|
+
// const store = createConfigStore('toolName');
|
|
32
|
+
statements.push(t.variableDeclaration('const', [
|
|
33
|
+
t.variableDeclarator(t.identifier('store'), t.callExpression(t.identifier('createConfigStore'), [
|
|
34
|
+
t.stringLiteral(toolName),
|
|
35
|
+
])),
|
|
36
|
+
]));
|
|
37
|
+
// export const getStore = () => store;
|
|
38
|
+
const getStoreExport = t.variableDeclaration('const', [
|
|
39
|
+
t.variableDeclarator(t.identifier('getStore'), t.arrowFunctionExpression([], t.identifier('store'))),
|
|
40
|
+
]);
|
|
41
|
+
statements.push(t.exportNamedDeclaration(getStoreExport));
|
|
42
|
+
// export function getClientConfig(targetName: string, contextName?: string): ClientConfig
|
|
43
|
+
const targetNameParam = t.identifier('targetName');
|
|
44
|
+
targetNameParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword());
|
|
45
|
+
const contextNameParam = t.identifier('contextName');
|
|
46
|
+
contextNameParam.optional = true;
|
|
47
|
+
contextNameParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword());
|
|
48
|
+
const getClientConfigBody = t.blockStatement([
|
|
49
|
+
t.returnStatement(t.callExpression(t.memberExpression(t.identifier('store'), t.identifier('getClientConfig')), [t.identifier('targetName'), t.identifier('contextName')])),
|
|
50
|
+
]);
|
|
51
|
+
const getClientConfigFunc = t.functionDeclaration(t.identifier('getClientConfig'), [targetNameParam, contextNameParam], getClientConfigBody);
|
|
52
|
+
// Add return type annotation
|
|
53
|
+
const returnTypeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier('ClientConfig')));
|
|
54
|
+
getClientConfigFunc.returnType = returnTypeAnnotation;
|
|
55
|
+
statements.push(t.exportNamedDeclaration(getClientConfigFunc));
|
|
56
|
+
// Generate typed factory for each target
|
|
57
|
+
for (const target of targets) {
|
|
58
|
+
const factoryName = `create${target.name[0].toUpperCase()}${target.name.slice(1)}Client`;
|
|
59
|
+
const ormAliasName = `create${target.name[0].toUpperCase()}${target.name.slice(1)}OrmClient`;
|
|
60
|
+
const ctxParam = t.identifier('contextName');
|
|
61
|
+
ctxParam.optional = true;
|
|
62
|
+
ctxParam.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword());
|
|
63
|
+
const factoryBody = t.blockStatement([
|
|
64
|
+
t.variableDeclaration('const', [
|
|
65
|
+
t.variableDeclarator(t.identifier('config'), t.callExpression(t.memberExpression(t.identifier('store'), t.identifier('getClientConfig')), [t.stringLiteral(target.name), t.identifier('contextName')])),
|
|
66
|
+
]),
|
|
67
|
+
t.returnStatement(t.callExpression(t.identifier(ormAliasName), [
|
|
68
|
+
t.objectExpression([
|
|
69
|
+
t.objectProperty(t.identifier('endpoint'), t.memberExpression(t.identifier('config'), t.identifier('endpoint'))),
|
|
70
|
+
t.objectProperty(t.identifier('headers'), t.memberExpression(t.identifier('config'), t.identifier('headers'))),
|
|
71
|
+
]),
|
|
72
|
+
])),
|
|
73
|
+
]);
|
|
74
|
+
const factoryFunc = t.functionDeclaration(t.identifier(factoryName), [ctxParam], factoryBody);
|
|
75
|
+
statements.push(t.exportNamedDeclaration(factoryFunc));
|
|
76
|
+
}
|
|
77
|
+
const header = getGeneratedFileHeader('SDK helpers — typed per-target client factories with 3-tier credential resolution');
|
|
78
|
+
const code = generateCode(statements);
|
|
79
|
+
return {
|
|
80
|
+
fileName: 'helpers.ts',
|
|
81
|
+
content: header + '\n' + code,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -47,12 +47,16 @@ export interface GenerateMultiTargetCliOptions {
|
|
|
47
47
|
export declare function resolveBuiltinNames(targetNames: string[], userOverrides?: BuiltinNames): {
|
|
48
48
|
auth: string;
|
|
49
49
|
context: string;
|
|
50
|
+
config: string;
|
|
50
51
|
};
|
|
51
52
|
export declare function generateMultiTargetCli(options: GenerateMultiTargetCliOptions): GenerateCliResult;
|
|
52
53
|
export { generateExecutorFile, generateMultiTargetExecutorFile } from './executor-generator';
|
|
53
54
|
export { generateTableCommand } from './table-command-generator';
|
|
54
55
|
export { generateCustomCommand } from './custom-command-generator';
|
|
55
56
|
export { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator';
|
|
57
|
+
export { generateConfigCommand } from './config-command-generator';
|
|
58
|
+
export { generateHelpersFile } from './helpers-generator';
|
|
59
|
+
export type { HelpersGeneratorInput } from './helpers-generator';
|
|
56
60
|
export { generateContextCommand, generateAuthCommand, generateMultiTargetContextCommand, generateAuthCommandWithName, } from './infra-generator';
|
|
57
61
|
export { generateReadme, generateAgentsDocs, getCliMcpTools, generateSkills, generateMultiTargetReadme, generateMultiTargetAgentsDocs, getMultiTargetCliMcpTools, generateMultiTargetSkills, } from './docs-generator';
|
|
58
62
|
export type { MultiTargetDocsInput } from './docs-generator';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator';
|
|
2
|
+
import { generateConfigCommand } from './config-command-generator';
|
|
2
3
|
import { generateCustomCommand } from './custom-command-generator';
|
|
3
4
|
import { generateExecutorFile, generateMultiTargetExecutorFile } from './executor-generator';
|
|
5
|
+
import { generateHelpersFile } from './helpers-generator';
|
|
4
6
|
import { generateAuthCommand, generateAuthCommandWithName, generateContextCommand, generateMultiTargetContextCommand, } from './infra-generator';
|
|
5
7
|
import { generateTableCommand } from './table-command-generator';
|
|
6
8
|
import { generateUtilsFile, generateNodeFetchFile, generateEntryPointFile } from './utils-generator';
|
|
@@ -62,13 +64,17 @@ export function generateCli(options) {
|
|
|
62
64
|
export function resolveBuiltinNames(targetNames, userOverrides) {
|
|
63
65
|
let authName = userOverrides?.auth ?? 'auth';
|
|
64
66
|
let contextName = userOverrides?.context ?? 'context';
|
|
67
|
+
let configName = userOverrides?.config ?? 'config';
|
|
65
68
|
if (targetNames.includes(authName) && !userOverrides?.auth) {
|
|
66
69
|
authName = 'credentials';
|
|
67
70
|
}
|
|
68
71
|
if (targetNames.includes(contextName) && !userOverrides?.context) {
|
|
69
72
|
contextName = 'env';
|
|
70
73
|
}
|
|
71
|
-
|
|
74
|
+
if (targetNames.includes(configName) && !userOverrides?.config) {
|
|
75
|
+
configName = 'vars';
|
|
76
|
+
}
|
|
77
|
+
return { auth: authName, context: contextName, config: configName };
|
|
72
78
|
}
|
|
73
79
|
export function generateMultiTargetCli(options) {
|
|
74
80
|
const { toolName, targets } = options;
|
|
@@ -94,6 +100,14 @@ export function generateMultiTargetCli(options) {
|
|
|
94
100
|
files.push(contextFile);
|
|
95
101
|
const authFile = generateAuthCommandWithName(toolName, builtinNames.auth);
|
|
96
102
|
files.push(authFile);
|
|
103
|
+
const configFile = generateConfigCommand(toolName, builtinNames.config);
|
|
104
|
+
files.push(configFile);
|
|
105
|
+
const helpersInputs = targets.map((t) => ({
|
|
106
|
+
name: t.name,
|
|
107
|
+
ormImportPath: t.ormImportPath,
|
|
108
|
+
}));
|
|
109
|
+
const helpersFile = generateHelpersFile(toolName, helpersInputs);
|
|
110
|
+
files.push(helpersFile);
|
|
97
111
|
let totalTables = 0;
|
|
98
112
|
let totalQueries = 0;
|
|
99
113
|
let totalMutations = 0;
|
|
@@ -145,7 +159,7 @@ export function generateMultiTargetCli(options) {
|
|
|
145
159
|
tables: totalTables,
|
|
146
160
|
customQueries: totalQueries,
|
|
147
161
|
customMutations: totalMutations,
|
|
148
|
-
infraFiles:
|
|
162
|
+
infraFiles: 6,
|
|
149
163
|
totalFiles: files.length,
|
|
150
164
|
},
|
|
151
165
|
};
|
|
@@ -154,6 +168,8 @@ export { generateExecutorFile, generateMultiTargetExecutorFile } from './executo
|
|
|
154
168
|
export { generateTableCommand } from './table-command-generator';
|
|
155
169
|
export { generateCustomCommand } from './custom-command-generator';
|
|
156
170
|
export { generateCommandMap, generateMultiTargetCommandMap } from './command-map-generator';
|
|
171
|
+
export { generateConfigCommand } from './config-command-generator';
|
|
172
|
+
export { generateHelpersFile } from './helpers-generator';
|
|
157
173
|
export { generateContextCommand, generateAuthCommand, generateMultiTargetContextCommand, generateAuthCommandWithName, } from './infra-generator';
|
|
158
174
|
export { generateReadme, generateAgentsDocs, getCliMcpTools, generateSkills, generateMultiTargetReadme, generateMultiTargetAgentsDocs, getMultiTargetCliMcpTools, generateMultiTargetSkills, } from './docs-generator';
|
|
159
175
|
export { resolveDocsConfig } from '../docs-utils';
|
|
@@ -9,6 +9,7 @@ import { generateAllModelFiles } from './model-generator';
|
|
|
9
9
|
export function generateOrm(options) {
|
|
10
10
|
const { tables, customOperations, sharedTypesPath } = options;
|
|
11
11
|
const commentsEnabled = options.config.codegen?.comments !== false;
|
|
12
|
+
const conditionEnabled = options.config.codegen?.condition !== false;
|
|
12
13
|
const files = [];
|
|
13
14
|
// Use shared types when a sharedTypesPath is provided (unified output mode)
|
|
14
15
|
const useSharedTypes = !!sharedTypesPath;
|
|
@@ -29,7 +30,7 @@ export function generateOrm(options) {
|
|
|
29
30
|
content: selectTypesFile.content,
|
|
30
31
|
});
|
|
31
32
|
// 2. Generate model files
|
|
32
|
-
const modelFiles = generateAllModelFiles(tables, useSharedTypes);
|
|
33
|
+
const modelFiles = generateAllModelFiles(tables, useSharedTypes, { condition: conditionEnabled });
|
|
33
34
|
for (const modelFile of modelFiles) {
|
|
34
35
|
files.push({
|
|
35
36
|
path: `models/${modelFile.fileName}`,
|
|
@@ -66,7 +67,7 @@ export function generateOrm(options) {
|
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
|
-
const inputTypesFile = generateInputTypesFile(typeRegistry ?? new Map(), usedInputTypes, tables, usedPayloadTypes, commentsEnabled);
|
|
70
|
+
const inputTypesFile = generateInputTypesFile(typeRegistry ?? new Map(), usedInputTypes, tables, usedPayloadTypes, commentsEnabled, { condition: conditionEnabled });
|
|
70
71
|
files.push({
|
|
71
72
|
path: inputTypesFile.fileName,
|
|
72
73
|
content: inputTypesFile.content,
|
|
@@ -18,4 +18,6 @@ export declare function collectPayloadTypeNames(operations: Array<{
|
|
|
18
18
|
/**
|
|
19
19
|
* Generate comprehensive input-types.ts file using Babel AST
|
|
20
20
|
*/
|
|
21
|
-
export declare function generateInputTypesFile(typeRegistry: TypeRegistry, usedInputTypes: Set<string>, tables?: CleanTable[], usedPayloadTypes?: Set<string>, comments?: boolean
|
|
21
|
+
export declare function generateInputTypesFile(typeRegistry: TypeRegistry, usedInputTypes: Set<string>, tables?: CleanTable[], usedPayloadTypes?: Set<string>, comments?: boolean, options?: {
|
|
22
|
+
condition?: boolean;
|
|
23
|
+
}): GeneratedInputTypesFile;
|