@acrool/rtk-query-codegen-openapi 0.0.2-test.4 → 0.0.2-test.6
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.md +1 -0
- package/lib/index.d.mts +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +114 -30
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +114 -30
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/generate.ts +131 -32
- package/src/types.ts +1 -0
package/src/generate.ts
CHANGED
|
@@ -117,6 +117,7 @@ export async function generateApi(
|
|
|
117
117
|
useEnumType = false,
|
|
118
118
|
mergeReadWriteOnly = false,
|
|
119
119
|
httpResolverOptions,
|
|
120
|
+
sharedTypesFile,
|
|
120
121
|
}: GenerationOptions
|
|
121
122
|
) {
|
|
122
123
|
const v3Doc = (v3DocCache[spec] ??= await getV3Doc(spec, httpResolverOptions));
|
|
@@ -127,6 +128,48 @@ export async function generateApi(
|
|
|
127
128
|
mergeReadWriteOnly,
|
|
128
129
|
});
|
|
129
130
|
|
|
131
|
+
// 如果提供了 sharedTypesFile,則將 components 輸出到該文件
|
|
132
|
+
if (sharedTypesFile) {
|
|
133
|
+
const components = v3Doc.components;
|
|
134
|
+
if (components) {
|
|
135
|
+
const resultFile = ts.createSourceFile(
|
|
136
|
+
'sharedTypes.ts',
|
|
137
|
+
'',
|
|
138
|
+
ts.ScriptTarget.Latest,
|
|
139
|
+
/*setParentNodes*/ false,
|
|
140
|
+
ts.ScriptKind.TS
|
|
141
|
+
);
|
|
142
|
+
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
|
|
143
|
+
|
|
144
|
+
// 將 components 轉換為 TypeScript 類型定義
|
|
145
|
+
const typeDefinitions = Object.entries(components).flatMap(([_, componentDefs]) => {
|
|
146
|
+
return Object.entries(componentDefs as Record<string, unknown>).map(([name, def]) => {
|
|
147
|
+
const typeNode = apiGen.getTypeFromSchema(def as OpenAPIV3.SchemaObject);
|
|
148
|
+
return factory.createTypeAliasDeclaration(
|
|
149
|
+
[factory.createModifier(ts.SyntaxKind.ExportKeyword)],
|
|
150
|
+
factory.createIdentifier(name),
|
|
151
|
+
undefined,
|
|
152
|
+
typeNode
|
|
153
|
+
);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const output = printer.printNode(
|
|
158
|
+
ts.EmitHint.Unspecified,
|
|
159
|
+
factory.createSourceFile(
|
|
160
|
+
typeDefinitions,
|
|
161
|
+
factory.createToken(ts.SyntaxKind.EndOfFileToken),
|
|
162
|
+
ts.NodeFlags.None
|
|
163
|
+
),
|
|
164
|
+
resultFile
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
// 寫入文件
|
|
168
|
+
const fs = await import('node:fs/promises');
|
|
169
|
+
await fs.writeFile(sharedTypesFile, output, 'utf-8');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
130
173
|
// temporary workaround for https://github.com/oazapfts/oazapfts/issues/491
|
|
131
174
|
if (apiGen.spec.components?.schemas) {
|
|
132
175
|
apiGen.preprocessComponents(apiGen.spec.components.schemas);
|
|
@@ -160,8 +203,17 @@ export async function generateApi(
|
|
|
160
203
|
apiFile = apiFile.replace(/\\/g, '/');
|
|
161
204
|
if (!apiFile.startsWith('.')) apiFile = `./${apiFile}`;
|
|
162
205
|
}
|
|
206
|
+
// 處理 sharedTypesFile 的路徑
|
|
207
|
+
if (sharedTypesFile && sharedTypesFile.startsWith('.')) {
|
|
208
|
+
sharedTypesFile = path.relative(path.dirname(outputFile), sharedTypesFile);
|
|
209
|
+
sharedTypesFile = sharedTypesFile.replace(/\\/g, '/');
|
|
210
|
+
if (!sharedTypesFile.startsWith('.')) sharedTypesFile = `./${sharedTypesFile}`;
|
|
211
|
+
}
|
|
163
212
|
}
|
|
164
213
|
apiFile = apiFile.replace(/\.[jt]sx?$/, '');
|
|
214
|
+
if (sharedTypesFile) {
|
|
215
|
+
sharedTypesFile = sharedTypesFile.replace(/\.[jt]sx?$/, '');
|
|
216
|
+
}
|
|
165
217
|
|
|
166
218
|
return printer.printNode(
|
|
167
219
|
ts.EmitHint.Unspecified,
|
|
@@ -169,6 +221,18 @@ export async function generateApi(
|
|
|
169
221
|
[
|
|
170
222
|
generateImportNode(apiFile, { [apiImport]: 'api' }),
|
|
171
223
|
generateImportNode('@acrool/react-fetcher', { IRestFulEndpointsQueryReturn: 'IRestFulEndpointsQueryReturn' }),
|
|
224
|
+
...(sharedTypesFile ? [
|
|
225
|
+
factory.createImportDeclaration(
|
|
226
|
+
undefined,
|
|
227
|
+
factory.createImportClause(
|
|
228
|
+
false,
|
|
229
|
+
undefined,
|
|
230
|
+
factory.createNamespaceImport(factory.createIdentifier('SharedTypes'))
|
|
231
|
+
),
|
|
232
|
+
factory.createStringLiteral(sharedTypesFile),
|
|
233
|
+
undefined
|
|
234
|
+
)
|
|
235
|
+
] : []),
|
|
172
236
|
...(tag ? [generateTagTypes({ addTagTypes: extractAllTagTypes({ operationDefinitions }) })] : []),
|
|
173
237
|
generateCreateApiCall({
|
|
174
238
|
tag,
|
|
@@ -182,20 +246,13 @@ export async function generateApi(
|
|
|
182
246
|
true
|
|
183
247
|
),
|
|
184
248
|
}),
|
|
185
|
-
factory.
|
|
249
|
+
factory.createExportAssignment(
|
|
186
250
|
undefined,
|
|
187
|
-
|
|
188
|
-
factory.
|
|
189
|
-
factory.createExportSpecifier(
|
|
190
|
-
factory.createIdentifier(generatedApiName),
|
|
191
|
-
factory.createIdentifier(exportName)
|
|
192
|
-
),
|
|
193
|
-
]),
|
|
194
|
-
undefined
|
|
251
|
+
undefined,
|
|
252
|
+
factory.createIdentifier(generatedApiName)
|
|
195
253
|
),
|
|
196
254
|
...Object.values(interfaces),
|
|
197
|
-
...apiGen.aliases,
|
|
198
|
-
...apiGen.enumAliases,
|
|
255
|
+
...(sharedTypesFile ? [] : [...apiGen.aliases, ...apiGen.enumAliases]),
|
|
199
256
|
...(hooks
|
|
200
257
|
? [
|
|
201
258
|
generateReactHooks({
|
|
@@ -245,16 +302,54 @@ export async function generateApi(
|
|
|
245
302
|
|
|
246
303
|
const returnsJson = apiGen.getResponseType(responses) === 'json';
|
|
247
304
|
let ResponseType: ts.TypeNode = factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
|
|
305
|
+
|
|
306
|
+
function replaceReferences(schema: any): ts.TypeNode {
|
|
307
|
+
if (!schema) return factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);
|
|
308
|
+
|
|
309
|
+
const refName = getReferenceName(schema);
|
|
310
|
+
if (refName && sharedTypesFile) {
|
|
311
|
+
return factory.createTypeReferenceNode(
|
|
312
|
+
factory.createQualifiedName(
|
|
313
|
+
factory.createIdentifier('SharedTypes'),
|
|
314
|
+
factory.createIdentifier(refName)
|
|
315
|
+
),
|
|
316
|
+
undefined
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (schema.type === 'object' && schema.properties) {
|
|
321
|
+
const members = Object.entries(schema.properties).map(([key, value]: [string, any]) => {
|
|
322
|
+
return factory.createPropertySignature(
|
|
323
|
+
undefined,
|
|
324
|
+
factory.createIdentifier(key),
|
|
325
|
+
schema.required?.includes(key) ? undefined : factory.createToken(ts.SyntaxKind.QuestionToken),
|
|
326
|
+
replaceReferences(value)
|
|
327
|
+
);
|
|
328
|
+
});
|
|
329
|
+
return factory.createTypeLiteralNode(members);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (schema.type === 'array' && schema.items) {
|
|
333
|
+
return factory.createArrayTypeNode(replaceReferences(schema.items));
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return apiGen.getTypeFromSchema(schema);
|
|
337
|
+
}
|
|
338
|
+
|
|
248
339
|
if (returnsJson) {
|
|
249
340
|
const returnTypes = Object.entries(responses || {})
|
|
250
341
|
.map(
|
|
251
|
-
([code, response]) =>
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
342
|
+
([code, response]) => {
|
|
343
|
+
const resolvedResponse = apiGen.resolve(response);
|
|
344
|
+
if (!resolvedResponse.content?.['application/json']?.schema) {
|
|
345
|
+
return [code, resolvedResponse, factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)] as const;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const schema = resolvedResponse.content['application/json'].schema;
|
|
349
|
+
const type = replaceReferences(schema);
|
|
350
|
+
|
|
351
|
+
return [code, resolvedResponse, type] as const;
|
|
352
|
+
}
|
|
258
353
|
)
|
|
259
354
|
.filter(([status, response]) =>
|
|
260
355
|
isDataResponse(status, includeDefault, apiGen.resolve(response), responses || {})
|
|
@@ -314,22 +409,11 @@ export async function generateApi(
|
|
|
314
409
|
return name;
|
|
315
410
|
}
|
|
316
411
|
|
|
317
|
-
for (const param of parameters) {
|
|
318
|
-
const name = generateName(param.name, param.in);
|
|
319
|
-
queryArg[name] = {
|
|
320
|
-
origin: 'param',
|
|
321
|
-
name,
|
|
322
|
-
originalName: param.name,
|
|
323
|
-
type: apiGen.getTypeFromSchema(isReference(param) ? param : param.schema, undefined, 'writeOnly'),
|
|
324
|
-
required: param.required,
|
|
325
|
-
param,
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
|
|
329
412
|
if (requestBody) {
|
|
330
413
|
const body = apiGen.resolve(requestBody);
|
|
331
414
|
const schema = apiGen.getSchemaFromContent(body.content);
|
|
332
|
-
const type =
|
|
415
|
+
const type = replaceReferences(schema);
|
|
416
|
+
|
|
333
417
|
const schemaName = camelCase(
|
|
334
418
|
(type as any).name ||
|
|
335
419
|
getReferenceName(schema) ||
|
|
@@ -342,12 +426,27 @@ export async function generateApi(
|
|
|
342
426
|
origin: 'body',
|
|
343
427
|
name,
|
|
344
428
|
originalName: schemaName,
|
|
345
|
-
type
|
|
429
|
+
type,
|
|
346
430
|
required: true,
|
|
347
431
|
body,
|
|
348
432
|
};
|
|
349
433
|
}
|
|
350
434
|
|
|
435
|
+
for (const param of parameters) {
|
|
436
|
+
const name = generateName(param.name, param.in);
|
|
437
|
+
const paramSchema = isReference(param) ? param : param.schema;
|
|
438
|
+
const type = replaceReferences(paramSchema);
|
|
439
|
+
|
|
440
|
+
queryArg[name] = {
|
|
441
|
+
origin: 'param',
|
|
442
|
+
name,
|
|
443
|
+
originalName: param.name,
|
|
444
|
+
type,
|
|
445
|
+
required: param.required,
|
|
446
|
+
param,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
|
|
351
450
|
const propertyName = (name: string | ts.PropertyName): ts.PropertyName => {
|
|
352
451
|
if (typeof name === 'string') {
|
|
353
452
|
return isValidIdentifier(name) ? factory.createIdentifier(name) : factory.createStringLiteral(name);
|
package/src/types.ts
CHANGED
|
@@ -132,6 +132,7 @@ export interface OutputFileOptions extends Partial<CommonOptions> {
|
|
|
132
132
|
* If passed as true it will generate TS enums instead of union of strings
|
|
133
133
|
*/
|
|
134
134
|
useEnumType?: boolean;
|
|
135
|
+
sharedTypesFile?: string;
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
export type EndpointOverrides = {
|