@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/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: [ECacheKeys.${info.queryKeyName}${info.argTypeName !== "VoidApiArg" ? ", args.variables" : ""}],
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}>([ECacheKeys.${info.queryKeyName}${info.argTypeName !== "VoidApiArg" ? ", args.variables" : ""}]);
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 {ECacheKeys} from '../cache-keys';
970
- import {${apiServiceName}} from './api.service';
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.importName} } from '${httpClient.file}';
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.importName});
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
- const options2 = ["...args.fetchOptions"];
1025
- if (hasRequestBody || !isGet) {
1026
- options2.push(`headers: { 'Content-Type': 'application/json', ...args.fetchOptions?.headers }`);
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
- if (hasRequestBody) {
1032
- options2.push("body: args.variables.body");
1033
- }
1034
- return options2.length > 0 ? `{ ${options2.join(", ")} }` : "{}";
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(tags) {
1180
- if (tags.length === 0) {
1181
- return `/* eslint-disable */
1182
- // [Warning] Generated automatically - do not edit manually
1183
-
1184
- export enum ECacheTagTypes {
1185
- }
1186
- `;
1187
- }
1188
- const enumEntries = tags.sort().map((tag) => ` ${tag} = '${tag}',`).join("\n");
1189
- return `/* eslint-disable */
1190
- // [Warning] Generated automatically - do not edit manually
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.generateTagTypesContent();
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((curr, alias) => {
1255
- if (ts3.isInterfaceDeclaration(alias) || ts3.isTypeAliasDeclaration(alias)) {
1256
- const name = alias.name.text;
1257
- return {
1258
- ...curr,
1259
- [name]: alias
1260
- };
1261
- }
1262
- return curr;
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
- const tagsArray = Array.from(this.allTags);
1324
- this.generatedContent.tagTypes = generateTagTypesFile(tagsArray);
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
- groupOutputDir,
1340
- {
1341
- types: group.content.files.types,
1342
- queryService: group.content.files.queryService,
1343
- enhanceEndpoints: group.content.files.enhanceEndpoints,
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
- outputDir,
1358
- {
1359
- commonTypes: this.generatedContent.commonTypes || void 0,
1360
- doNotModify: this.generatedContent.doNotModify || void 0,
1361
- utils: this.generatedContent.utils || void 0
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
  /**