ng-openapi 0.0.24 → 0.0.25-alpha.1

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.
Files changed (4) hide show
  1. package/cli.cjs +417 -226
  2. package/index.d.ts +9 -1
  3. package/index.js +422 -222
  4. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
 
27
27
  // src/lib/cli.ts
28
28
  var import_commander = require("commander");
29
- var path8 = __toESM(require("path"));
29
+ var path9 = __toESM(require("path"));
30
30
  var fs4 = __toESM(require("fs"));
31
31
 
32
32
  // src/lib/core/swagger-parser.ts
@@ -58,7 +58,7 @@ var SwaggerParser = class {
58
58
  };
59
59
 
60
60
  // src/lib/core/generator.ts
61
- var import_ts_morph4 = require("ts-morph");
61
+ var import_ts_morph5 = require("ts-morph");
62
62
 
63
63
  // src/lib/generators/type/type.generator.ts
64
64
  var import_ts_morph = require("ts-morph");
@@ -93,6 +93,10 @@ var PROVIDER_GENERATOR_HEADER_COMMENT = defaultHeaderComment + `* Generated prov
93
93
  * Do not edit this file manually
94
94
  */
95
95
  `;
96
+ var BASE_INTERCEPTOR_HEADER_COMMENT = /* @__PURE__ */ __name((clientName) => defaultHeaderComment + `* Generated Base Interceptor for client ${clientName}
97
+ * Do not edit this file manually
98
+ */
99
+ `, "BASE_INTERCEPTOR_HEADER_COMMENT");
96
100
 
97
101
  // src/lib/generators/type/type.generator.ts
98
102
  var TypeGenerator = class {
@@ -402,8 +406,10 @@ var TokenGenerator = class {
402
406
  __name(this, "TokenGenerator");
403
407
  }
404
408
  project;
405
- constructor(project) {
409
+ clientName;
410
+ constructor(project, clientName = "default") {
406
411
  this.project = project;
412
+ this.clientName = clientName;
407
413
  }
408
414
  generate(outputDir) {
409
415
  const tokensDir = path.join(outputDir, "tokens");
@@ -413,29 +419,73 @@ var TokenGenerator = class {
413
419
  });
414
420
  sourceFile.addImportDeclaration({
415
421
  namedImports: [
416
- "InjectionToken"
422
+ "InjectionToken",
423
+ "HttpInterceptor"
417
424
  ],
418
425
  moduleSpecifier: "@angular/core"
419
426
  });
427
+ const basePathTokenName = this.getBasePathTokenName();
428
+ const interceptorsTokenName = this.getInterceptorsTokenName();
420
429
  sourceFile.addVariableStatement({
421
430
  isExported: true,
422
431
  declarationKind: import_ts_morph2.VariableDeclarationKind.Const,
423
432
  declarations: [
424
433
  {
425
- name: "BASE_PATH",
426
- initializer: `new InjectionToken<string>('BASE_PATH', {
434
+ name: basePathTokenName,
435
+ initializer: `new InjectionToken<string>('${basePathTokenName}', {
427
436
  providedIn: 'root',
428
437
  factory: () => '/api', // Default fallback
429
438
  })`
430
439
  }
431
440
  ],
432
441
  leadingTrivia: `/**
433
- * Injection token for the base API path
442
+ * Injection token for the ${this.clientName} client base API path
443
+ */
444
+ `
445
+ });
446
+ sourceFile.addVariableStatement({
447
+ isExported: true,
448
+ declarationKind: import_ts_morph2.VariableDeclarationKind.Const,
449
+ declarations: [
450
+ {
451
+ name: interceptorsTokenName,
452
+ initializer: `new InjectionToken<HttpInterceptor[]>('${interceptorsTokenName}', {
453
+ providedIn: 'root',
454
+ factory: () => [], // Default empty array
455
+ })`
456
+ }
457
+ ],
458
+ leadingTrivia: `/**
459
+ * Injection token for the ${this.clientName} client HTTP interceptors
434
460
  */
435
461
  `
436
462
  });
463
+ if (this.clientName === "default") {
464
+ sourceFile.addVariableStatement({
465
+ isExported: true,
466
+ declarationKind: import_ts_morph2.VariableDeclarationKind.Const,
467
+ declarations: [
468
+ {
469
+ name: "BASE_PATH",
470
+ initializer: basePathTokenName
471
+ }
472
+ ],
473
+ leadingTrivia: `/**
474
+ * @deprecated Use ${basePathTokenName} instead
475
+ */
476
+ `
477
+ });
478
+ }
437
479
  sourceFile.saveSync();
438
480
  }
481
+ getBasePathTokenName() {
482
+ const clientSuffix = this.clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
483
+ return `BASE_PATH_${clientSuffix}`;
484
+ }
485
+ getInterceptorsTokenName() {
486
+ const clientSuffix = this.clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
487
+ return `HTTP_INTERCEPTORS_${clientSuffix}`;
488
+ }
439
489
  };
440
490
 
441
491
  // src/lib/generators/utility/file-download.generator.ts
@@ -757,9 +807,332 @@ var MainIndexGenerator = class {
757
807
  }
758
808
  };
759
809
 
760
- // src/lib/generators/service/service.generator.ts
761
- var import_ts_morph3 = require("ts-morph");
810
+ // src/lib/generators/utility/provider.generator.ts
762
811
  var path5 = __toESM(require("path"));
812
+ var ProviderGenerator = class {
813
+ static {
814
+ __name(this, "ProviderGenerator");
815
+ }
816
+ project;
817
+ config;
818
+ clientName;
819
+ constructor(project, config) {
820
+ this.project = project;
821
+ this.config = config;
822
+ this.clientName = config.clientName || "default";
823
+ }
824
+ generate(outputDir) {
825
+ const filePath = path5.join(outputDir, "providers.ts");
826
+ const sourceFile = this.project.createSourceFile(filePath, "", {
827
+ overwrite: true
828
+ });
829
+ sourceFile.insertText(0, PROVIDER_GENERATOR_HEADER_COMMENT);
830
+ const basePathTokenName = this.getBasePathTokenName();
831
+ const interceptorsTokenName = this.getInterceptorsTokenName();
832
+ const baseInterceptorClassName = `${this.capitalizeFirst(this.clientName)}BaseInterceptor`;
833
+ sourceFile.addImportDeclarations([
834
+ {
835
+ namedImports: [
836
+ "EnvironmentProviders",
837
+ "Provider",
838
+ "makeEnvironmentProviders"
839
+ ],
840
+ moduleSpecifier: "@angular/core"
841
+ },
842
+ {
843
+ namedImports: [
844
+ "HTTP_INTERCEPTORS",
845
+ "HttpInterceptor"
846
+ ],
847
+ moduleSpecifier: "@angular/common/http"
848
+ },
849
+ {
850
+ namedImports: [
851
+ basePathTokenName,
852
+ interceptorsTokenName
853
+ ],
854
+ moduleSpecifier: "./tokens"
855
+ },
856
+ {
857
+ namedImports: [
858
+ baseInterceptorClassName
859
+ ],
860
+ moduleSpecifier: "./utils/base-interceptor"
861
+ }
862
+ ]);
863
+ if (this.config.options.dateType === "Date") {
864
+ sourceFile.addImportDeclaration({
865
+ namedImports: [
866
+ "DateInterceptor"
867
+ ],
868
+ moduleSpecifier: "./utils/date-transformer"
869
+ });
870
+ }
871
+ sourceFile.addInterface({
872
+ name: `${this.capitalizeFirst(this.clientName)}Config`,
873
+ isExported: true,
874
+ docs: [
875
+ `Configuration options for ${this.clientName} client`
876
+ ],
877
+ properties: [
878
+ {
879
+ name: "basePath",
880
+ type: "string",
881
+ docs: [
882
+ "Base API URL"
883
+ ]
884
+ },
885
+ {
886
+ name: "enableDateTransform",
887
+ type: "boolean",
888
+ hasQuestionToken: true,
889
+ docs: [
890
+ "Enable automatic date transformation (default: true)"
891
+ ]
892
+ },
893
+ {
894
+ name: "interceptors",
895
+ type: "HttpInterceptor[]",
896
+ hasQuestionToken: true,
897
+ docs: [
898
+ "Array of HTTP interceptors to apply to this client"
899
+ ]
900
+ }
901
+ ]
902
+ });
903
+ this.addMainProviderFunction(sourceFile, basePathTokenName, interceptorsTokenName, baseInterceptorClassName);
904
+ sourceFile.saveSync();
905
+ }
906
+ addMainProviderFunction(sourceFile, basePathTokenName, interceptorsTokenName, baseInterceptorClassName) {
907
+ const hasDateInterceptor = this.config.options.dateType === "Date";
908
+ const functionName = `provide${this.capitalizeFirst(this.clientName)}Client`;
909
+ const configTypeName = `${this.capitalizeFirst(this.clientName)}Config`;
910
+ const functionBody = `
911
+ const providers: Provider[] = [
912
+ // Base path token for this client
913
+ {
914
+ provide: ${basePathTokenName},
915
+ useValue: config.basePath
916
+ },
917
+ // Client-specific interceptors token
918
+ {
919
+ provide: ${interceptorsTokenName},
920
+ useValue: config.interceptors || []
921
+ },
922
+ // Base interceptor that handles client-specific interceptors
923
+ {
924
+ provide: HTTP_INTERCEPTORS,
925
+ useClass: ${baseInterceptorClassName},
926
+ multi: true
927
+ }
928
+ ];
929
+
930
+ ${hasDateInterceptor ? `// Add date interceptor to client-specific interceptors if enabled
931
+ if (config.enableDateTransform !== false) {
932
+ const currentInterceptors = config.interceptors || [];
933
+ providers.push({
934
+ provide: ${interceptorsTokenName},
935
+ useValue: [new DateInterceptor(), ...currentInterceptors]
936
+ });
937
+ }` : `// Date transformation not available (dateType: 'string' was used in generation)`}
938
+
939
+ return makeEnvironmentProviders(providers);`;
940
+ sourceFile.addFunction({
941
+ name: functionName,
942
+ isExported: true,
943
+ docs: [
944
+ `Provides configuration for ${this.clientName} client`,
945
+ "",
946
+ "@example",
947
+ "```typescript",
948
+ "// In your app.config.ts",
949
+ `import { ${functionName} } from './api/providers';`,
950
+ "",
951
+ "export const appConfig: ApplicationConfig = {",
952
+ " providers: [",
953
+ ` ${functionName}({`,
954
+ " basePath: 'https://api.example.com',",
955
+ " interceptors: [new LoggingInterceptor(), new AuthInterceptor()]",
956
+ " }),",
957
+ " // other providers...",
958
+ " ]",
959
+ "};",
960
+ "```"
961
+ ],
962
+ parameters: [
963
+ {
964
+ name: "config",
965
+ type: configTypeName
966
+ }
967
+ ],
968
+ returnType: "EnvironmentProviders",
969
+ statements: functionBody
970
+ });
971
+ if (this.clientName === "default") {
972
+ sourceFile.addFunction({
973
+ name: "provideNgOpenapi",
974
+ isExported: true,
975
+ docs: [
976
+ "@deprecated Use provideDefaultClient instead for better clarity",
977
+ "Provides configuration for the default client"
978
+ ],
979
+ parameters: [
980
+ {
981
+ name: "config",
982
+ type: configTypeName
983
+ }
984
+ ],
985
+ returnType: "EnvironmentProviders",
986
+ statements: `return ${functionName}(config);`
987
+ });
988
+ }
989
+ }
990
+ getBasePathTokenName() {
991
+ const clientSuffix = this.clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
992
+ return `BASE_PATH_${clientSuffix}`;
993
+ }
994
+ getInterceptorsTokenName() {
995
+ const clientSuffix = this.clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
996
+ return `HTTP_INTERCEPTORS_${clientSuffix}`;
997
+ }
998
+ capitalizeFirst(str) {
999
+ return str.charAt(0).toUpperCase() + str.slice(1);
1000
+ }
1001
+ };
1002
+
1003
+ // src/lib/generators/utility/base-interceptor.generator.ts
1004
+ var import_ts_morph3 = require("ts-morph");
1005
+ var path6 = __toESM(require("path"));
1006
+ var BaseInterceptorGenerator = class {
1007
+ static {
1008
+ __name(this, "BaseInterceptorGenerator");
1009
+ }
1010
+ #project;
1011
+ #clientName;
1012
+ constructor(project, clientName = "default") {
1013
+ this.#project = project;
1014
+ this.#clientName = clientName;
1015
+ }
1016
+ generate(outputDir) {
1017
+ const utilsDir = path6.join(outputDir, "utils");
1018
+ const filePath = path6.join(utilsDir, "base-interceptor.ts");
1019
+ const sourceFile = this.#project.createSourceFile(filePath, "", {
1020
+ overwrite: true
1021
+ });
1022
+ sourceFile.insertText(0, BASE_INTERCEPTOR_HEADER_COMMENT(this.#clientName));
1023
+ const basePathTokenName = this.getBasePathTokenName();
1024
+ const interceptorsTokenName = this.getInterceptorsTokenName();
1025
+ sourceFile.addImportDeclarations([
1026
+ {
1027
+ namedImports: [
1028
+ "HttpEvent",
1029
+ "HttpHandler",
1030
+ "HttpInterceptor",
1031
+ "HttpRequest"
1032
+ ],
1033
+ moduleSpecifier: "@angular/common/http"
1034
+ },
1035
+ {
1036
+ namedImports: [
1037
+ "inject",
1038
+ "Injectable"
1039
+ ],
1040
+ moduleSpecifier: "@angular/core"
1041
+ },
1042
+ {
1043
+ namedImports: [
1044
+ "Observable"
1045
+ ],
1046
+ moduleSpecifier: "rxjs"
1047
+ },
1048
+ {
1049
+ namedImports: [
1050
+ basePathTokenName,
1051
+ interceptorsTokenName
1052
+ ],
1053
+ moduleSpecifier: "../tokens"
1054
+ }
1055
+ ]);
1056
+ sourceFile.addClass({
1057
+ name: `${this.capitalizeFirst(this.#clientName)}BaseInterceptor`,
1058
+ isExported: true,
1059
+ decorators: [
1060
+ {
1061
+ name: "Injectable",
1062
+ arguments: []
1063
+ }
1064
+ ],
1065
+ implements: [
1066
+ "HttpInterceptor"
1067
+ ],
1068
+ properties: [
1069
+ {
1070
+ name: "basePath",
1071
+ type: "string",
1072
+ scope: import_ts_morph3.Scope.Private,
1073
+ isReadonly: true,
1074
+ initializer: `inject(${basePathTokenName})`
1075
+ },
1076
+ {
1077
+ name: "httpInterceptors",
1078
+ type: "HttpInterceptor[]",
1079
+ scope: import_ts_morph3.Scope.Private,
1080
+ isReadonly: true,
1081
+ initializer: `inject(${interceptorsTokenName})`
1082
+ }
1083
+ ],
1084
+ methods: [
1085
+ {
1086
+ name: "intercept",
1087
+ parameters: [
1088
+ {
1089
+ name: "req",
1090
+ type: "HttpRequest<any>"
1091
+ },
1092
+ {
1093
+ name: "next",
1094
+ type: "HttpHandler"
1095
+ }
1096
+ ],
1097
+ returnType: "Observable<HttpEvent<any>>",
1098
+ statements: `
1099
+ // Only intercept requests to this client's base path
1100
+ if (!req.url.startsWith(this.#basePath)) {
1101
+ return next.handle(req);
1102
+ }
1103
+
1104
+ // Apply client-specific interceptors in reverse order
1105
+ let handler = next;
1106
+
1107
+ handler = this.#httpInterceptors.reduceRight(
1108
+ (next, interceptor) => ({
1109
+ handle: (request: HttpRequest<any>) => interceptor.intercept(request, next)
1110
+ }),
1111
+ handler
1112
+ );
1113
+
1114
+ return handler.handle(req);`
1115
+ }
1116
+ ]
1117
+ });
1118
+ sourceFile.saveSync();
1119
+ }
1120
+ getBasePathTokenName() {
1121
+ const clientSuffix = this.#clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
1122
+ return `BASE_PATH_${clientSuffix}`;
1123
+ }
1124
+ getInterceptorsTokenName() {
1125
+ const clientSuffix = this.#clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
1126
+ return `HTTP_INTERCEPTORS_${clientSuffix}`;
1127
+ }
1128
+ capitalizeFirst(str) {
1129
+ return str.charAt(0).toUpperCase() + str.slice(1);
1130
+ }
1131
+ };
1132
+
1133
+ // src/lib/generators/service/service.generator.ts
1134
+ var import_ts_morph4 = require("ts-morph");
1135
+ var path7 = __toESM(require("path"));
763
1136
 
764
1137
  // src/lib/utils/string.utils.ts
765
1138
  function camelCase(str) {
@@ -1551,7 +1924,7 @@ var ServiceGenerator = class {
1551
1924
  this.methodGenerator = new ServiceMethodGenerator(config);
1552
1925
  }
1553
1926
  generate(outputRoot) {
1554
- const outputDir = path5.join(outputRoot, "services");
1927
+ const outputDir = path7.join(outputRoot, "services");
1555
1928
  const paths = this.extractPaths();
1556
1929
  const controllerGroups = this.groupPathsByController(paths);
1557
1930
  Object.entries(controllerGroups).forEach(([controllerName, operations]) => {
@@ -1561,7 +1934,7 @@ var ServiceGenerator = class {
1561
1934
  extractPaths() {
1562
1935
  const paths = [];
1563
1936
  const swaggerPaths = this.spec.paths || {};
1564
- Object.entries(swaggerPaths).forEach(([path9, pathItem]) => {
1937
+ Object.entries(swaggerPaths).forEach(([path10, pathItem]) => {
1565
1938
  const methods = [
1566
1939
  "get",
1567
1940
  "post",
@@ -1575,7 +1948,7 @@ var ServiceGenerator = class {
1575
1948
  if (pathItem[method]) {
1576
1949
  const operation = pathItem[method];
1577
1950
  paths.push({
1578
- path: path9,
1951
+ path: path10,
1579
1952
  method: method.toUpperCase(),
1580
1953
  operationId: operation.operationId,
1581
1954
  summary: operation.summary,
@@ -1607,12 +1980,12 @@ var ServiceGenerator = class {
1607
1980
  }
1608
1981
  groupPathsByController(paths) {
1609
1982
  const groups = {};
1610
- paths.forEach((path9) => {
1983
+ paths.forEach((path10) => {
1611
1984
  let controllerName = "Default";
1612
- if (path9.tags && path9.tags.length > 0) {
1613
- controllerName = path9.tags[0];
1985
+ if (path10.tags && path10.tags.length > 0) {
1986
+ controllerName = path10.tags[0];
1614
1987
  } else {
1615
- const pathParts = path9.path.split("/").filter((p) => p && !p.startsWith("{"));
1988
+ const pathParts = path10.path.split("/").filter((p) => p && !p.startsWith("{"));
1616
1989
  if (pathParts.length > 1) {
1617
1990
  controllerName = pascalCase(pathParts[1]);
1618
1991
  }
@@ -1621,13 +1994,13 @@ var ServiceGenerator = class {
1621
1994
  if (!groups[controllerName]) {
1622
1995
  groups[controllerName] = [];
1623
1996
  }
1624
- groups[controllerName].push(path9);
1997
+ groups[controllerName].push(path10);
1625
1998
  });
1626
1999
  return groups;
1627
2000
  }
1628
2001
  generateServiceFile(controllerName, operations, outputDir) {
1629
2002
  const fileName = `${camelCase(controllerName)}.service.ts`;
1630
- const filePath = path5.join(outputDir, fileName);
2003
+ const filePath = path7.join(outputDir, fileName);
1631
2004
  const sourceFile = this.project.createSourceFile(filePath, "", {
1632
2005
  overwrite: true
1633
2006
  });
@@ -1702,6 +2075,7 @@ var ServiceGenerator = class {
1702
2075
  });
1703
2076
  }
1704
2077
  addImports(sourceFile, usedTypes) {
2078
+ const basePathTokenName = this.getBasePathTokenName();
1705
2079
  sourceFile.addImportDeclarations([
1706
2080
  {
1707
2081
  namedImports: [
@@ -1729,7 +2103,7 @@ var ServiceGenerator = class {
1729
2103
  },
1730
2104
  {
1731
2105
  namedImports: [
1732
- "BASE_PATH"
2106
+ basePathTokenName
1733
2107
  ],
1734
2108
  moduleSpecifier: "../tokens"
1735
2109
  }
@@ -1743,6 +2117,7 @@ var ServiceGenerator = class {
1743
2117
  }
1744
2118
  addServiceClass(sourceFile, controllerName, operations) {
1745
2119
  const className = `${controllerName}Service`;
2120
+ const basePathTokenName = this.getBasePathTokenName();
1746
2121
  sourceFile.insertText(0, SERVICE_GENERATOR_HEADER_COMMENT(controllerName));
1747
2122
  const serviceClass = sourceFile.addClass({
1748
2123
  name: className,
@@ -1759,16 +2134,16 @@ var ServiceGenerator = class {
1759
2134
  serviceClass.addProperty({
1760
2135
  name: "httpClient",
1761
2136
  type: "HttpClient",
1762
- scope: import_ts_morph3.Scope.Private,
2137
+ scope: import_ts_morph4.Scope.Private,
1763
2138
  isReadonly: true,
1764
2139
  initializer: "inject(HttpClient)"
1765
2140
  });
1766
2141
  serviceClass.addProperty({
1767
2142
  name: "basePath",
1768
2143
  type: "string",
1769
- scope: import_ts_morph3.Scope.Private,
2144
+ scope: import_ts_morph4.Scope.Private,
1770
2145
  isReadonly: true,
1771
- initializer: "inject(BASE_PATH)"
2146
+ initializer: `inject(${basePathTokenName})`
1772
2147
  });
1773
2148
  operations.forEach((operation) => {
1774
2149
  this.methodGenerator.addServiceMethod(serviceClass, operation);
@@ -1777,6 +2152,11 @@ var ServiceGenerator = class {
1777
2152
  throw new Error(`Duplicate method names found in service class ${className}. Please ensure unique method names for each operation.`);
1778
2153
  }
1779
2154
  }
2155
+ getBasePathTokenName() {
2156
+ const clientName = this.config.clientName || "default";
2157
+ const clientSuffix = clientName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
2158
+ return `BASE_PATH_${clientSuffix}`;
2159
+ }
1780
2160
  hasDuplicateMethodNames(arr) {
1781
2161
  return new Set(arr.map((method) => method.getName())).size !== arr.length;
1782
2162
  }
@@ -1784,7 +2164,7 @@ var ServiceGenerator = class {
1784
2164
 
1785
2165
  // src/lib/generators/service/service-index.generator.ts
1786
2166
  var fs2 = __toESM(require("fs"));
1787
- var path6 = __toESM(require("path"));
2167
+ var path8 = __toESM(require("path"));
1788
2168
  var ServiceIndexGenerator = class {
1789
2169
  static {
1790
2170
  __name(this, "ServiceIndexGenerator");
@@ -1794,8 +2174,8 @@ var ServiceIndexGenerator = class {
1794
2174
  this.project = project;
1795
2175
  }
1796
2176
  generateIndex(outputRoot) {
1797
- const servicesDir = path6.join(outputRoot, "services");
1798
- const indexPath = path6.join(servicesDir, "index.ts");
2177
+ const servicesDir = path8.join(outputRoot, "services");
2178
+ const indexPath = path8.join(servicesDir, "index.ts");
1799
2179
  const sourceFile = this.project.createSourceFile(indexPath, "", {
1800
2180
  overwrite: true
1801
2181
  });
@@ -1814,198 +2194,6 @@ var ServiceIndexGenerator = class {
1814
2194
  }
1815
2195
  };
1816
2196
 
1817
- // src/lib/generators/utility/provider.generator.ts
1818
- var path7 = __toESM(require("path"));
1819
- var ProviderGenerator = class {
1820
- static {
1821
- __name(this, "ProviderGenerator");
1822
- }
1823
- project;
1824
- config;
1825
- constructor(project, config) {
1826
- this.project = project;
1827
- this.config = config;
1828
- }
1829
- generate(outputDir) {
1830
- const filePath = path7.join(outputDir, "providers.ts");
1831
- const sourceFile = this.project.createSourceFile(filePath, "", {
1832
- overwrite: true
1833
- });
1834
- sourceFile.insertText(0, PROVIDER_GENERATOR_HEADER_COMMENT);
1835
- sourceFile.addImportDeclarations([
1836
- {
1837
- namedImports: [
1838
- "EnvironmentProviders",
1839
- "Provider",
1840
- "makeEnvironmentProviders"
1841
- ],
1842
- moduleSpecifier: "@angular/core"
1843
- },
1844
- {
1845
- namedImports: [
1846
- "HTTP_INTERCEPTORS"
1847
- ],
1848
- moduleSpecifier: "@angular/common/http"
1849
- },
1850
- {
1851
- namedImports: [
1852
- "BASE_PATH"
1853
- ],
1854
- moduleSpecifier: "./tokens"
1855
- }
1856
- ]);
1857
- if (this.config.options.dateType === "Date") {
1858
- sourceFile.addImportDeclaration({
1859
- namedImports: [
1860
- "DateInterceptor"
1861
- ],
1862
- moduleSpecifier: "./utils/date-transformer"
1863
- });
1864
- }
1865
- sourceFile.addInterface({
1866
- name: "NgOpenapiConfig",
1867
- isExported: true,
1868
- docs: [
1869
- "Configuration options for ng-openapi providers"
1870
- ],
1871
- properties: [
1872
- {
1873
- name: "basePath",
1874
- type: "string",
1875
- docs: [
1876
- "Base API URL"
1877
- ]
1878
- },
1879
- {
1880
- name: "enableDateTransform",
1881
- type: "boolean",
1882
- hasQuestionToken: true,
1883
- docs: [
1884
- "Enable automatic date transformation (default: true)"
1885
- ]
1886
- }
1887
- ]
1888
- });
1889
- this.addMainProviderFunction(sourceFile);
1890
- this.addAsyncProviderFunction(sourceFile);
1891
- sourceFile.saveSync();
1892
- }
1893
- addMainProviderFunction(sourceFile) {
1894
- const hasDateInterceptor = this.config.options.dateType === "Date";
1895
- const functionBody = `
1896
- const providers: Provider[] = [
1897
- // Base path token
1898
- {
1899
- provide: BASE_PATH,
1900
- useValue: config.basePath
1901
- }
1902
- ];
1903
-
1904
- ${hasDateInterceptor ? `// Add date interceptor if enabled (default: true)
1905
- if (config.enableDateTransform !== false) {
1906
- providers.push({
1907
- provide: HTTP_INTERCEPTORS,
1908
- useClass: DateInterceptor,
1909
- multi: true
1910
- });
1911
- }` : `// Date transformation not available (dateType: 'string' was used in generation)`}
1912
-
1913
- return makeEnvironmentProviders(providers);`;
1914
- sourceFile.addFunction({
1915
- name: "provideNgOpenapi",
1916
- isExported: true,
1917
- docs: [
1918
- "Provides all necessary configuration for ng-openapi generated services",
1919
- "",
1920
- "@example",
1921
- "```typescript",
1922
- "// In your app.config.ts",
1923
- "import { provideNgOpenapi } from './api/providers';",
1924
- "",
1925
- "export const appConfig: ApplicationConfig = {",
1926
- " providers: [",
1927
- " provideNgOpenapi({",
1928
- " basePath: 'https://api.example.com'",
1929
- " }),",
1930
- " // other providers...",
1931
- " ]",
1932
- "};",
1933
- "```"
1934
- ],
1935
- parameters: [
1936
- {
1937
- name: "config",
1938
- type: "NgOpenapiConfig"
1939
- }
1940
- ],
1941
- returnType: "EnvironmentProviders",
1942
- statements: functionBody
1943
- });
1944
- }
1945
- addAsyncProviderFunction(sourceFile) {
1946
- const hasDateInterceptor = this.config.options.dateType === "Date";
1947
- const functionBody = `
1948
- const providers: Provider[] = [];
1949
-
1950
- // Handle async base path
1951
- if (typeof config.basePath === 'string') {
1952
- providers.push({
1953
- provide: BASE_PATH,
1954
- useValue: config.basePath
1955
- });
1956
- } else {
1957
- providers.push({
1958
- provide: BASE_PATH,
1959
- useFactory: config.basePath
1960
- });
1961
- }
1962
-
1963
- ${hasDateInterceptor ? `// Add date interceptor if enabled (default: true)
1964
- if (config.enableDateTransform !== false) {
1965
- providers.push({
1966
- provide: HTTP_INTERCEPTORS,
1967
- useClass: DateInterceptor,
1968
- multi: true
1969
- });
1970
- }` : `// Date transformation not available (dateType: 'string' was used in generation)`}
1971
-
1972
- return makeEnvironmentProviders(providers);`;
1973
- sourceFile.addFunction({
1974
- name: "provideNgOpenapiAsync",
1975
- isExported: true,
1976
- docs: [
1977
- "Alternative function for cases where you need to handle async configuration",
1978
- "",
1979
- "@example",
1980
- "```typescript",
1981
- "// In your app.config.ts",
1982
- "import { provideNgOpenapiAsync } from './api/providers';",
1983
- "",
1984
- "export const appConfig: ApplicationConfig = {",
1985
- " providers: [",
1986
- " provideNgOpenapiAsync({",
1987
- " basePath: () => import('./config').then(c => c.apiConfig.baseUrl)",
1988
- " }),",
1989
- " // other providers...",
1990
- " ]",
1991
- "};",
1992
- "```"
1993
- ],
1994
- parameters: [
1995
- {
1996
- name: "config",
1997
- type: `{
1998
- basePath: string | (() => Promise<string>);
1999
- enableDateTransform?: boolean;
2000
- }`
2001
- }
2002
- ],
2003
- returnType: "EnvironmentProviders",
2004
- statements: functionBody
2005
- });
2006
- }
2007
- };
2008
-
2009
2197
  // src/lib/core/generator.ts
2010
2198
  var fs3 = __toESM(require("fs"));
2011
2199
  async function generateFromConfig(config) {
@@ -2020,11 +2208,11 @@ async function generateFromConfig(config) {
2020
2208
  });
2021
2209
  }
2022
2210
  try {
2023
- const project = new import_ts_morph4.Project({
2211
+ const project = new import_ts_morph5.Project({
2024
2212
  compilerOptions: {
2025
2213
  declaration: true,
2026
- target: import_ts_morph4.ScriptTarget.ES2022,
2027
- module: import_ts_morph4.ModuleKind.Preserve,
2214
+ target: import_ts_morph5.ScriptTarget.ES2022,
2215
+ module: import_ts_morph5.ModuleKind.Preserve,
2028
2216
  strict: true,
2029
2217
  ...config.compilerOptions
2030
2218
  }
@@ -2038,11 +2226,9 @@ async function generateFromConfig(config) {
2038
2226
  if (config.options.dateType === "Date") {
2039
2227
  const dateTransformer = new DateTransformerGenerator(project);
2040
2228
  dateTransformer.generate(outputPath);
2041
- console.log(`\u2705 Date transformer generated`);
2042
2229
  }
2043
2230
  const fileDownloadHelper = new FileDownloadGenerator(project);
2044
2231
  fileDownloadHelper.generate(outputPath);
2045
- console.log(`\u2705 File download helper generated`);
2046
2232
  const serviceGenerator = new ServiceGenerator(config.input, project, config);
2047
2233
  serviceGenerator.generate(outputPath);
2048
2234
  const indexGenerator = new ServiceIndexGenerator(project);
@@ -2050,11 +2236,16 @@ async function generateFromConfig(config) {
2050
2236
  console.log(`\u2705 Angular services generated`);
2051
2237
  const providerGenerator = new ProviderGenerator(project, config);
2052
2238
  providerGenerator.generate(outputPath);
2053
- console.log(`\u2705 Provider functions generated`);
2239
+ const baseInterceptorGenerator = new BaseInterceptorGenerator(project, config.clientName);
2240
+ baseInterceptorGenerator.generate(outputPath);
2054
2241
  }
2055
2242
  const mainIndexGenerator = new MainIndexGenerator(project, config);
2056
2243
  mainIndexGenerator.generateMainIndex(outputPath);
2057
- console.log("\u{1F389} Generation completed successfully at:", outputPath);
2244
+ if (config.clientName) {
2245
+ console.log(`\u{1F389} ${config.clientName} Generation completed successfully at: ${outputPath}`);
2246
+ } else {
2247
+ console.log("\u{1F389} Generation completed successfully at:", outputPath);
2248
+ }
2058
2249
  } catch (error) {
2059
2250
  if (error instanceof Error) {
2060
2251
  console.error("\u274C Error during generation:", error.message);
@@ -2069,7 +2260,7 @@ __name(generateFromConfig, "generateFromConfig");
2069
2260
  // src/lib/cli.ts
2070
2261
  var program = new import_commander.Command();
2071
2262
  async function loadConfigFile(configPath) {
2072
- const resolvedPath = path8.resolve(configPath);
2263
+ const resolvedPath = path9.resolve(configPath);
2073
2264
  if (!fs4.existsSync(resolvedPath)) {
2074
2265
  throw new Error(`Configuration file not found: ${resolvedPath}`);
2075
2266
  }
@@ -2095,7 +2286,7 @@ async function generateFromOptions(options) {
2095
2286
  const config = await loadConfigFile(options.config);
2096
2287
  await generateFromConfig(config);
2097
2288
  } else if (options.input) {
2098
- const inputPath = path8.resolve(options.input);
2289
+ const inputPath = path9.resolve(options.input);
2099
2290
  if (!fs4.existsSync(inputPath)) {
2100
2291
  console.error(`Error: Input file not found: ${inputPath}`);
2101
2292
  process.exit(1);