@bitstack/ng-query-codegen-openapi 0.0.31-alpha.0 → 0.0.31-alpha.3
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/lib/bin/cli.mjs +43 -36
- package/lib/bin/cli.mjs.map +1 -1
- package/lib/index.d.mts +5 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +101 -86
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +101 -86
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/generators/common-types-generator.ts +2 -2
- package/src/generators/rtk-enhance-endpoints-generator.ts +17 -17
- package/src/generators/rtk-query-generator.ts +4 -4
- package/src/generators/tag-types-generator.ts +37 -21
- package/src/services/api-code-generator.ts +10 -0
- package/src/services/file-writer-service.ts +10 -12
- package/src/services/unified-code-generator.ts +73 -80
- package/src/types.ts +10 -0
package/lib/index.mjs
CHANGED
|
@@ -375,6 +375,9 @@ var FileWriterService = class {
|
|
|
375
375
|
if (sharedFiles.commonTypes) {
|
|
376
376
|
filesToWrite[path3.join(outputDir, "common-types.ts")] = sharedFiles.commonTypes;
|
|
377
377
|
}
|
|
378
|
+
if (sharedFiles.tagTypes) {
|
|
379
|
+
filesToWrite[path3.join(outputDir, "tagTypes.ts")] = sharedFiles.tagTypes;
|
|
380
|
+
}
|
|
378
381
|
if (sharedFiles.doNotModify) {
|
|
379
382
|
filesToWrite[path3.join(outputDir, "DO_NOT_MODIFY.md")] = sharedFiles.doNotModify;
|
|
380
383
|
}
|
|
@@ -476,12 +479,12 @@ export interface QueryConfig {
|
|
|
476
479
|
keepUnusedDataFor?: number,
|
|
477
480
|
}
|
|
478
481
|
|
|
479
|
-
export interface IRequestConfig extends RequestOptions {
|
|
482
|
+
export interface IRequestConfig extends RequestOptions {
|
|
480
483
|
timeout?: number;
|
|
481
484
|
}
|
|
482
485
|
|
|
483
486
|
export type IRestFulEndpointsQueryReturn<TVariables> = TVariables extends void ?
|
|
484
|
-
void | {fetchOptions?: IRequestConfig;}:
|
|
487
|
+
(void | {fetchOptions?: IRequestConfig;}):
|
|
485
488
|
{
|
|
486
489
|
variables: TVariables;
|
|
487
490
|
fetchOptions?: IRequestConfig;
|
|
@@ -911,7 +914,7 @@ function generateRtkQueryFile(endpointInfos, options) {
|
|
|
911
914
|
*/
|
|
912
915
|
${info.operationName}Query(${info.argTypeName !== "VoidApiArg" ? `args: IRestFulEndpointsQueryReturn<${info.argTypeName}>` : ""}): Observable<QueryState<${info.responseTypeName}>> {
|
|
913
916
|
return this.ntkQuery.query<${info.responseTypeName}, ${info.argTypeName !== "VoidApiArg" ? `IRestFulEndpointsQueryReturn<${info.argTypeName}>` : "void"}>({
|
|
914
|
-
queryKey: [
|
|
917
|
+
queryKey: [ECacheTagTypes.${info.queryKeyName}${info.argTypeName !== "VoidApiArg" ? ", args.variables" : ""}],
|
|
915
918
|
queryFn: () => {
|
|
916
919
|
return this.apiService.${info.operationName}(${info.argTypeName !== "VoidApiArg" ? "args" : ""});
|
|
917
920
|
},
|
|
@@ -949,7 +952,7 @@ function generateRtkQueryFile(endpointInfos, options) {
|
|
|
949
952
|
trigger: (${info.argTypeName !== "VoidApiArg" ? "args, " : ""}options = {}) => {
|
|
950
953
|
const { skipCache = true } = options;
|
|
951
954
|
if (!skipCache) {
|
|
952
|
-
const cachedResult = this.ntkQuery.getQueryCache<${info.responseTypeName}>([
|
|
955
|
+
const cachedResult = this.ntkQuery.getQueryCache<${info.responseTypeName}>([ECacheTagTypes.${info.queryKeyName}${info.argTypeName !== "VoidApiArg" ? ", args.variables" : ""}]);
|
|
953
956
|
if (cachedResult) {
|
|
954
957
|
return cachedResult;
|
|
955
958
|
}
|
|
@@ -966,8 +969,8 @@ import {Injectable, inject} from '@angular/core';
|
|
|
966
969
|
import {Observable} from 'rxjs';
|
|
967
970
|
import {HttpErrorResponse} from '@angular/common/http';
|
|
968
971
|
import {NtkQueryService, MutationState, QueryState, MutationResponse} from '@core/ntk-query';
|
|
969
|
-
import {
|
|
970
|
-
import {${apiServiceName}} from './
|
|
972
|
+
import {ECacheTagTypes} from '../tagTypes';
|
|
973
|
+
import {${apiServiceName}} from './enhanceEndpoints';
|
|
971
974
|
import {IRestFulEndpointsQueryReturn, RequestOptions} from '../common-types';
|
|
972
975
|
import {${endpointInfos.map((info) => ` ${info.argTypeName}, ${info.responseTypeName}`).join(",")}} from './types';
|
|
973
976
|
|
|
@@ -990,7 +993,7 @@ function generateRtkEnhanceEndpointsFile(endpointInfos, options) {
|
|
|
990
993
|
return `/* eslint-disable */
|
|
991
994
|
// [Warning] Generated automatically - do not edit manually
|
|
992
995
|
|
|
993
|
-
import { ${httpClient.
|
|
996
|
+
import { ${httpClient.importReturnTypeName} } from '${httpClient.file}';
|
|
994
997
|
import { Injectable, inject } from '@angular/core';
|
|
995
998
|
import { Observable } from 'rxjs';
|
|
996
999
|
import { ${apiConfiguration.importName} } from '${apiConfiguration.file}';
|
|
@@ -1003,7 +1006,7 @@ import {${endpointInfos.map((info) => ` ${info.argTypeName}, ${info.responseType
|
|
|
1003
1006
|
})
|
|
1004
1007
|
export class ${apiServiceClassName} {
|
|
1005
1008
|
private config = inject(${apiConfiguration.importName});
|
|
1006
|
-
private http = inject(${httpClient.
|
|
1009
|
+
private http = inject(${httpClient.importReturnTypeName});
|
|
1007
1010
|
|
|
1008
1011
|
${endpointInfos.map((info) => {
|
|
1009
1012
|
const isGet = info.verb.toUpperCase() === "GET";
|
|
@@ -1021,17 +1024,16 @@ ${endpointInfos.map((info) => {
|
|
|
1021
1024
|
const hasQueryParams = info.queryParams.length > 0;
|
|
1022
1025
|
const hasBody = !isGet && hasArgs;
|
|
1023
1026
|
const generateRequestOptions = () => {
|
|
1024
|
-
|
|
1025
|
-
if (
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
if (hasQueryParams && hasArgs) {
|
|
1029
|
-
options2.push(generateQueryParams(info.queryParams));
|
|
1027
|
+
let paramsSection = "";
|
|
1028
|
+
if (info.queryParams && info.queryParams.length > 0) {
|
|
1029
|
+
const paramsLines = info.queryParams.map((param) => `${param.name}: args.variables.${param.name},`).join("\n");
|
|
1030
|
+
paramsSection = `params: {${paramsLines}},`;
|
|
1030
1031
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1032
|
+
return `{
|
|
1033
|
+
...args.fetchOptions,
|
|
1034
|
+
headers: { 'Content-Type': '${info.contentType}', ...args.fetchOptions?.headers },
|
|
1035
|
+
${paramsSection}${info.hasRequestBody ? `body: args.variables.body,` : ""}
|
|
1036
|
+
}`;
|
|
1035
1037
|
};
|
|
1036
1038
|
return `
|
|
1037
1039
|
/**
|
|
@@ -1047,12 +1049,6 @@ ${endpointInfos.map((info) => {
|
|
|
1047
1049
|
}
|
|
1048
1050
|
`;
|
|
1049
1051
|
}
|
|
1050
|
-
function generateQueryParams(queryParams) {
|
|
1051
|
-
const paramEntries = queryParams.map(
|
|
1052
|
-
(param) => `${param.name}: args.variables.${param.name}`
|
|
1053
|
-
).join(", ");
|
|
1054
|
-
return `params: withoutUndefined({ ${paramEntries} })`;
|
|
1055
|
-
}
|
|
1056
1052
|
|
|
1057
1053
|
// src/services/api-code-generator.ts
|
|
1058
1054
|
var ApiCodeGenerator = class {
|
|
@@ -1078,6 +1074,11 @@ var ApiCodeGenerator = class {
|
|
|
1078
1074
|
const rtkQueryContent = generateRtkQueryFile(endpointInfos, this.options);
|
|
1079
1075
|
const enhanceEndpointsContent = generateRtkEnhanceEndpointsFile(endpointInfos, this.options);
|
|
1080
1076
|
const indexContent = this.generateIndex();
|
|
1077
|
+
const allEndpointCacheKeys = endpointInfos.filter((info) => info.isQuery).map((info) => ({
|
|
1078
|
+
operationName: info.operationName,
|
|
1079
|
+
queryKeyName: info.queryKeyName,
|
|
1080
|
+
groupKey: this.options.groupKey || "_common"
|
|
1081
|
+
}));
|
|
1081
1082
|
const operationNames = endpointInfos.map((info) => info.operationName);
|
|
1082
1083
|
const allTags = /* @__PURE__ */ new Set();
|
|
1083
1084
|
endpointInfos.forEach((info) => {
|
|
@@ -1093,8 +1094,9 @@ var ApiCodeGenerator = class {
|
|
|
1093
1094
|
queryService: rtkQueryContent,
|
|
1094
1095
|
// RTK Query 檔案
|
|
1095
1096
|
index: indexContent,
|
|
1096
|
-
enhanceEndpoints: enhanceEndpointsContent
|
|
1097
|
+
enhanceEndpoints: enhanceEndpointsContent,
|
|
1097
1098
|
// 新增的 enhance endpoints 檔案
|
|
1099
|
+
allEndpointCacheKeys
|
|
1098
1100
|
}
|
|
1099
1101
|
};
|
|
1100
1102
|
}
|
|
@@ -1173,25 +1175,42 @@ export function withoutUndefined(obj?: Record<string, any>) {
|
|
|
1173
1175
|
|
|
1174
1176
|
`;
|
|
1175
1177
|
}
|
|
1178
|
+
function toCamelCase(str) {
|
|
1179
|
+
return str.toLowerCase().replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
1180
|
+
}
|
|
1176
1181
|
|
|
1177
1182
|
// src/generators/tag-types-generator.ts
|
|
1178
1183
|
init_esm_shims();
|
|
1179
|
-
function generateTagTypesFile(
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1184
|
+
function generateTagTypesFile(allEndpointInfos) {
|
|
1185
|
+
const groupedKeys = allEndpointInfos.reduce(
|
|
1186
|
+
(acc, info) => {
|
|
1187
|
+
if (!acc[info.groupKey]) {
|
|
1188
|
+
acc[info.groupKey] = [];
|
|
1189
|
+
}
|
|
1190
|
+
acc[info.groupKey].push({
|
|
1191
|
+
operationName: info.operationName,
|
|
1192
|
+
queryKeyName: info.queryKeyName
|
|
1193
|
+
});
|
|
1194
|
+
return acc;
|
|
1195
|
+
},
|
|
1196
|
+
{}
|
|
1197
|
+
);
|
|
1198
|
+
const enumEntries = Object.entries(groupedKeys).map(([groupKey, keys]) => {
|
|
1199
|
+
const groupComment = ` // ${groupKey.charAt(0).toUpperCase() + groupKey.slice(1)} related cache keys`;
|
|
1200
|
+
const keyEntries = keys.map((key) => ` ${key.queryKeyName} = '${toCamelCase(key.queryKeyName)}',`).join("\n");
|
|
1201
|
+
return `${groupComment}
|
|
1202
|
+
${keyEntries}`;
|
|
1203
|
+
}).join("\n\n");
|
|
1204
|
+
return `// [Warning] Generated automatically - do not edit manually
|
|
1205
|
+
|
|
1206
|
+
/**
|
|
1207
|
+
* Cache keys enum for all API queries
|
|
1208
|
+
*/
|
|
1192
1209
|
export enum ECacheTagTypes {
|
|
1193
1210
|
${enumEntries}
|
|
1194
1211
|
}
|
|
1212
|
+
|
|
1213
|
+
export default ECacheTagTypes;
|
|
1195
1214
|
`;
|
|
1196
1215
|
}
|
|
1197
1216
|
|
|
@@ -1201,6 +1220,7 @@ var UnifiedCodeGenerator = class {
|
|
|
1201
1220
|
openApiService = new OpenApiService();
|
|
1202
1221
|
groupService = new GroupService();
|
|
1203
1222
|
fileWriterService = new FileWriterService();
|
|
1223
|
+
allEndpointCacheKeys = [];
|
|
1204
1224
|
// 內部狀態存儲
|
|
1205
1225
|
openApiDoc = null;
|
|
1206
1226
|
parserService = null;
|
|
@@ -1230,7 +1250,7 @@ var UnifiedCodeGenerator = class {
|
|
|
1230
1250
|
this.generateSchemaContent();
|
|
1231
1251
|
this.generateUtilsContent();
|
|
1232
1252
|
this.generateDoNotModifyContent();
|
|
1233
|
-
this.
|
|
1253
|
+
this.generatECacheTagTypesContent();
|
|
1234
1254
|
return await this.release();
|
|
1235
1255
|
}
|
|
1236
1256
|
/**
|
|
@@ -1244,23 +1264,23 @@ var UnifiedCodeGenerator = class {
|
|
|
1244
1264
|
this._options.schemaFile
|
|
1245
1265
|
);
|
|
1246
1266
|
}
|
|
1247
|
-
this.openApiDoc = await this.openApiService.getDocument(
|
|
1248
|
-
this.actualSchemaFile,
|
|
1249
|
-
this._options.httpResolverOptions
|
|
1250
|
-
);
|
|
1267
|
+
this.openApiDoc = await this.openApiService.getDocument(this.actualSchemaFile, this._options.httpResolverOptions);
|
|
1251
1268
|
this.parserService = new OpenApiParserService(this.openApiDoc, this._options);
|
|
1252
1269
|
this.parserService.initialize();
|
|
1253
1270
|
const apiGen = this.parserService.getApiGenerator();
|
|
1254
|
-
this.schemaInterfaces = apiGen.aliases.reduce(
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1271
|
+
this.schemaInterfaces = apiGen.aliases.reduce(
|
|
1272
|
+
(curr, alias) => {
|
|
1273
|
+
if (ts3.isInterfaceDeclaration(alias) || ts3.isTypeAliasDeclaration(alias)) {
|
|
1274
|
+
const name = alias.name.text;
|
|
1275
|
+
return {
|
|
1276
|
+
...curr,
|
|
1277
|
+
[name]: alias
|
|
1278
|
+
};
|
|
1279
|
+
}
|
|
1280
|
+
return curr;
|
|
1281
|
+
},
|
|
1282
|
+
{}
|
|
1283
|
+
);
|
|
1264
1284
|
}
|
|
1265
1285
|
/**
|
|
1266
1286
|
* 生成階段:產生所有內容但不寫檔
|
|
@@ -1273,10 +1293,7 @@ var UnifiedCodeGenerator = class {
|
|
|
1273
1293
|
const groupInfos = this.groupService.groupPaths(paths, this._options.outputFiles);
|
|
1274
1294
|
for (const groupInfo of Object.values(groupInfos)) {
|
|
1275
1295
|
try {
|
|
1276
|
-
const groupContent = await this.generateApiGroupContent(
|
|
1277
|
-
this._options,
|
|
1278
|
-
groupInfo
|
|
1279
|
-
);
|
|
1296
|
+
const groupContent = await this.generateApiGroupContent(this._options, groupInfo);
|
|
1280
1297
|
if (groupContent.operationNames.length > 0) {
|
|
1281
1298
|
this.generatedContent.groups.push({
|
|
1282
1299
|
groupKey: groupInfo.groupKey,
|
|
@@ -1292,6 +1309,12 @@ var UnifiedCodeGenerator = class {
|
|
|
1292
1309
|
}
|
|
1293
1310
|
}
|
|
1294
1311
|
}
|
|
1312
|
+
/**
|
|
1313
|
+
* 生成 cache keys
|
|
1314
|
+
*/
|
|
1315
|
+
async generatECacheTagTypesContent() {
|
|
1316
|
+
this.generatedContent.tagTypes = generateTagTypesFile(this.allEndpointCacheKeys);
|
|
1317
|
+
}
|
|
1295
1318
|
/**
|
|
1296
1319
|
* 生成 common types
|
|
1297
1320
|
*/
|
|
@@ -1319,10 +1342,10 @@ var UnifiedCodeGenerator = class {
|
|
|
1319
1342
|
/**
|
|
1320
1343
|
* 生成 Tag Types
|
|
1321
1344
|
*/
|
|
1322
|
-
async generateTagTypesContent() {
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
}
|
|
1345
|
+
// private async generateTagTypesContent(): Promise<void> {
|
|
1346
|
+
// const tagsArray = Array.from(this.allTags);
|
|
1347
|
+
// this.generatedContent.tagTypes = generateTagTypesFile(tagsArray);
|
|
1348
|
+
// }
|
|
1326
1349
|
/**
|
|
1327
1350
|
* 發佈階段:統一寫入所有檔案
|
|
1328
1351
|
*/
|
|
@@ -1335,15 +1358,12 @@ var UnifiedCodeGenerator = class {
|
|
|
1335
1358
|
try {
|
|
1336
1359
|
if (group.content?.files) {
|
|
1337
1360
|
const groupOutputDir = path4.dirname(group.outputPath);
|
|
1338
|
-
const groupResults = await this.fileWriterService.writeGroupFiles(
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
index: group.content.files.index
|
|
1345
|
-
}
|
|
1346
|
-
);
|
|
1361
|
+
const groupResults = await this.fileWriterService.writeGroupFiles(groupOutputDir, {
|
|
1362
|
+
types: group.content.files.types,
|
|
1363
|
+
queryService: group.content.files.queryService,
|
|
1364
|
+
enhanceEndpoints: group.content.files.enhanceEndpoints,
|
|
1365
|
+
index: group.content.files.index
|
|
1366
|
+
});
|
|
1347
1367
|
results.push(...groupResults);
|
|
1348
1368
|
generatedGroups.push(group.groupKey);
|
|
1349
1369
|
}
|
|
@@ -1352,24 +1372,15 @@ var UnifiedCodeGenerator = class {
|
|
|
1352
1372
|
}
|
|
1353
1373
|
}
|
|
1354
1374
|
const outputDir = this.generatedContent.groups[0] ? path4.dirname(path4.dirname(this.generatedContent.groups[0].outputPath)) : "./generated";
|
|
1355
|
-
if (this.generatedContent.commonTypes || this.generatedContent.doNotModify || this.generatedContent.utils) {
|
|
1356
|
-
const sharedResults = await this.fileWriterService.writeSharedFiles(
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
}
|
|
1363
|
-
);
|
|
1375
|
+
if (this.generatedContent.tagTypes || this.generatedContent.commonTypes || this.generatedContent.doNotModify || this.generatedContent.utils) {
|
|
1376
|
+
const sharedResults = await this.fileWriterService.writeSharedFiles(outputDir, {
|
|
1377
|
+
tagTypes: this.generatedContent.tagTypes || void 0,
|
|
1378
|
+
commonTypes: this.generatedContent.commonTypes || void 0,
|
|
1379
|
+
doNotModify: this.generatedContent.doNotModify || void 0,
|
|
1380
|
+
utils: this.generatedContent.utils || void 0
|
|
1381
|
+
});
|
|
1364
1382
|
results.push(...sharedResults);
|
|
1365
1383
|
}
|
|
1366
|
-
if (this.generatedContent.tagTypes) {
|
|
1367
|
-
const tagTypesResult = await this.fileWriterService.writeFile(
|
|
1368
|
-
path4.join(outputDir, "tagTypes.ts"),
|
|
1369
|
-
this.generatedContent.tagTypes
|
|
1370
|
-
);
|
|
1371
|
-
results.push(tagTypesResult);
|
|
1372
|
-
}
|
|
1373
1384
|
if (this.generatedContent.componentSchema) {
|
|
1374
1385
|
const schemaResults = await this.fileWriterService.writeSchemaFile(
|
|
1375
1386
|
outputDir,
|
|
@@ -1412,6 +1423,10 @@ var UnifiedCodeGenerator = class {
|
|
|
1412
1423
|
}
|
|
1413
1424
|
const apiGenerator = new ApiCodeGenerator(this.parserService, groupOptions);
|
|
1414
1425
|
const result = await apiGenerator.generate();
|
|
1426
|
+
if (result.files && "allEndpointCacheKeys" in result.files) {
|
|
1427
|
+
const cacheKeys = result.files.allEndpointCacheKeys;
|
|
1428
|
+
this.allEndpointCacheKeys.push(...cacheKeys);
|
|
1429
|
+
}
|
|
1415
1430
|
return result;
|
|
1416
1431
|
}
|
|
1417
1432
|
/**
|