ng-openapi 0.0.38-pr-7-feature-yaml-support.0 → 0.0.38
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/cli.cjs +40 -103
- package/index.d.ts +1 -10
- package/index.js +31 -78
- package/package.json +2 -3
package/cli.cjs
CHANGED
|
@@ -26,13 +26,11 @@ 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
|
|
29
|
+
var path9 = __toESM(require("path"));
|
|
30
30
|
var fs4 = __toESM(require("fs"));
|
|
31
31
|
|
|
32
32
|
// src/lib/core/swagger-parser.ts
|
|
33
33
|
var fs = __toESM(require("fs"));
|
|
34
|
-
var path = __toESM(require("path"));
|
|
35
|
-
var yaml = __toESM(require("js-yaml"));
|
|
36
34
|
var SwaggerParser = class {
|
|
37
35
|
static {
|
|
38
36
|
__name(this, "SwaggerParser");
|
|
@@ -40,7 +38,7 @@ var SwaggerParser = class {
|
|
|
40
38
|
spec;
|
|
41
39
|
constructor(swaggerPath) {
|
|
42
40
|
const swaggerContent = fs.readFileSync(swaggerPath, "utf8");
|
|
43
|
-
this.spec =
|
|
41
|
+
this.spec = JSON.parse(swaggerContent);
|
|
44
42
|
}
|
|
45
43
|
getDefinitions() {
|
|
46
44
|
return this.spec.definitions || this.spec.components?.schemas || {};
|
|
@@ -57,42 +55,6 @@ var SwaggerParser = class {
|
|
|
57
55
|
getAllDefinitionNames() {
|
|
58
56
|
return Object.keys(this.getDefinitions());
|
|
59
57
|
}
|
|
60
|
-
getSpec() {
|
|
61
|
-
return this.spec;
|
|
62
|
-
}
|
|
63
|
-
getPaths() {
|
|
64
|
-
return this.spec.paths || {};
|
|
65
|
-
}
|
|
66
|
-
isValidSpec() {
|
|
67
|
-
return !!(this.spec.swagger && this.spec.swagger.startsWith("2.") || this.spec.openapi && this.spec.openapi.startsWith("3."));
|
|
68
|
-
}
|
|
69
|
-
getSpecVersion() {
|
|
70
|
-
if (this.spec.swagger) {
|
|
71
|
-
return {
|
|
72
|
-
type: "swagger",
|
|
73
|
-
version: this.spec.swagger
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
if (this.spec.openapi) {
|
|
77
|
-
return {
|
|
78
|
-
type: "openapi",
|
|
79
|
-
version: this.spec.openapi
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
parseSpecFile(content, filePath) {
|
|
85
|
-
const extension = path.extname(filePath).toLowerCase();
|
|
86
|
-
switch (extension) {
|
|
87
|
-
case ".json":
|
|
88
|
-
return JSON.parse(content);
|
|
89
|
-
case ".yaml":
|
|
90
|
-
case ".yml":
|
|
91
|
-
return yaml.load(content);
|
|
92
|
-
default:
|
|
93
|
-
throw new Error(`Failed to parse ${extension || "specification"} file: ${filePath}. Supported formats are .json, .yaml, and .yml.`);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
58
|
};
|
|
97
59
|
|
|
98
60
|
// src/lib/core/generator.ts
|
|
@@ -438,7 +400,7 @@ var TypeGenerator = class {
|
|
|
438
400
|
|
|
439
401
|
// src/lib/generators/utility/token.generator.ts
|
|
440
402
|
var import_ts_morph2 = require("ts-morph");
|
|
441
|
-
var
|
|
403
|
+
var path = __toESM(require("path"));
|
|
442
404
|
var TokenGenerator = class {
|
|
443
405
|
static {
|
|
444
406
|
__name(this, "TokenGenerator");
|
|
@@ -450,8 +412,8 @@ var TokenGenerator = class {
|
|
|
450
412
|
this.clientName = clientName;
|
|
451
413
|
}
|
|
452
414
|
generate(outputDir) {
|
|
453
|
-
const tokensDir =
|
|
454
|
-
const filePath =
|
|
415
|
+
const tokensDir = path.join(outputDir, "tokens");
|
|
416
|
+
const filePath = path.join(tokensDir, "index.ts");
|
|
455
417
|
const sourceFile = this.project.createSourceFile(filePath, "", {
|
|
456
418
|
overwrite: true
|
|
457
419
|
});
|
|
@@ -566,7 +528,7 @@ var TokenGenerator = class {
|
|
|
566
528
|
};
|
|
567
529
|
|
|
568
530
|
// src/lib/generators/utility/file-download.generator.ts
|
|
569
|
-
var
|
|
531
|
+
var path2 = __toESM(require("path"));
|
|
570
532
|
var FileDownloadGenerator = class {
|
|
571
533
|
static {
|
|
572
534
|
__name(this, "FileDownloadGenerator");
|
|
@@ -576,8 +538,8 @@ var FileDownloadGenerator = class {
|
|
|
576
538
|
this.project = project;
|
|
577
539
|
}
|
|
578
540
|
generate(outputDir) {
|
|
579
|
-
const utilsDir =
|
|
580
|
-
const filePath =
|
|
541
|
+
const utilsDir = path2.join(outputDir, "utils");
|
|
542
|
+
const filePath = path2.join(utilsDir, "file-download.ts");
|
|
581
543
|
const sourceFile = this.project.createSourceFile(filePath, "", {
|
|
582
544
|
overwrite: true
|
|
583
545
|
});
|
|
@@ -708,7 +670,7 @@ var FileDownloadGenerator = class {
|
|
|
708
670
|
|
|
709
671
|
// src/lib/generators/utility/date-transformer.generator.ts
|
|
710
672
|
var import_ts_morph3 = require("ts-morph");
|
|
711
|
-
var
|
|
673
|
+
var path3 = __toESM(require("path"));
|
|
712
674
|
var DateTransformerGenerator = class {
|
|
713
675
|
static {
|
|
714
676
|
__name(this, "DateTransformerGenerator");
|
|
@@ -718,8 +680,8 @@ var DateTransformerGenerator = class {
|
|
|
718
680
|
this.project = project;
|
|
719
681
|
}
|
|
720
682
|
generate(outputDir) {
|
|
721
|
-
const utilsDir =
|
|
722
|
-
const filePath =
|
|
683
|
+
const utilsDir = path3.join(outputDir, "utils");
|
|
684
|
+
const filePath = path3.join(utilsDir, "date-transformer.ts");
|
|
723
685
|
const sourceFile = this.project.createSourceFile(filePath, "", {
|
|
724
686
|
overwrite: true
|
|
725
687
|
});
|
|
@@ -842,7 +804,7 @@ var DateTransformerGenerator = class {
|
|
|
842
804
|
};
|
|
843
805
|
|
|
844
806
|
// src/lib/generators/utility/main-index.generator.ts
|
|
845
|
-
var
|
|
807
|
+
var path4 = __toESM(require("path"));
|
|
846
808
|
var MainIndexGenerator = class {
|
|
847
809
|
static {
|
|
848
810
|
__name(this, "MainIndexGenerator");
|
|
@@ -854,7 +816,7 @@ var MainIndexGenerator = class {
|
|
|
854
816
|
this.config = config;
|
|
855
817
|
}
|
|
856
818
|
generateMainIndex(outputRoot) {
|
|
857
|
-
const indexPath =
|
|
819
|
+
const indexPath = path4.join(outputRoot, "index.ts");
|
|
858
820
|
const sourceFile = this.project.createSourceFile(indexPath, "", {
|
|
859
821
|
overwrite: true
|
|
860
822
|
});
|
|
@@ -886,7 +848,7 @@ var MainIndexGenerator = class {
|
|
|
886
848
|
};
|
|
887
849
|
|
|
888
850
|
// src/lib/generators/utility/provider.generator.ts
|
|
889
|
-
var
|
|
851
|
+
var path5 = __toESM(require("path"));
|
|
890
852
|
var ProviderGenerator = class {
|
|
891
853
|
static {
|
|
892
854
|
__name(this, "ProviderGenerator");
|
|
@@ -900,7 +862,7 @@ var ProviderGenerator = class {
|
|
|
900
862
|
this.clientName = config.clientName || "default";
|
|
901
863
|
}
|
|
902
864
|
generate(outputDir) {
|
|
903
|
-
const filePath =
|
|
865
|
+
const filePath = path5.join(outputDir, "providers.ts");
|
|
904
866
|
const sourceFile = this.project.createSourceFile(filePath, "", {
|
|
905
867
|
overwrite: true
|
|
906
868
|
});
|
|
@@ -1093,7 +1055,7 @@ return makeEnvironmentProviders(providers);`;
|
|
|
1093
1055
|
|
|
1094
1056
|
// src/lib/generators/utility/base-interceptor.generator.ts
|
|
1095
1057
|
var import_ts_morph4 = require("ts-morph");
|
|
1096
|
-
var
|
|
1058
|
+
var path6 = __toESM(require("path"));
|
|
1097
1059
|
var BaseInterceptorGenerator = class {
|
|
1098
1060
|
static {
|
|
1099
1061
|
__name(this, "BaseInterceptorGenerator");
|
|
@@ -1105,8 +1067,8 @@ var BaseInterceptorGenerator = class {
|
|
|
1105
1067
|
this.#clientName = clientName;
|
|
1106
1068
|
}
|
|
1107
1069
|
generate(outputDir) {
|
|
1108
|
-
const utilsDir =
|
|
1109
|
-
const filePath =
|
|
1070
|
+
const utilsDir = path6.join(outputDir, "utils");
|
|
1071
|
+
const filePath = path6.join(utilsDir, "base-interceptor.ts");
|
|
1110
1072
|
const sourceFile = this.#project.createSourceFile(filePath, "", {
|
|
1111
1073
|
overwrite: true
|
|
1112
1074
|
});
|
|
@@ -1225,7 +1187,7 @@ var BaseInterceptorGenerator = class {
|
|
|
1225
1187
|
|
|
1226
1188
|
// src/lib/generators/service/service.generator.ts
|
|
1227
1189
|
var import_ts_morph5 = require("ts-morph");
|
|
1228
|
-
var
|
|
1190
|
+
var path7 = __toESM(require("path"));
|
|
1229
1191
|
|
|
1230
1192
|
// src/lib/utils/string.utils.ts
|
|
1231
1193
|
function camelCase(str) {
|
|
@@ -2021,30 +1983,21 @@ var ServiceGenerator = class {
|
|
|
2021
1983
|
this.config = config;
|
|
2022
1984
|
this.project = project;
|
|
2023
1985
|
this.parser = new SwaggerParser(swaggerPath);
|
|
2024
|
-
this.spec =
|
|
2025
|
-
if (!this.parser.isValidSpec()) {
|
|
2026
|
-
const versionInfo = this.parser.getSpecVersion();
|
|
2027
|
-
throw new Error(`Invalid or unsupported specification format. Expected OpenAPI 3.x or Swagger 2.x. ${versionInfo ? `Found: ${versionInfo.type} ${versionInfo.version}` : "No version info found"}`);
|
|
2028
|
-
}
|
|
1986
|
+
this.spec = JSON.parse(require("fs").readFileSync(swaggerPath, "utf8"));
|
|
2029
1987
|
this.methodGenerator = new ServiceMethodGenerator(config);
|
|
2030
1988
|
}
|
|
2031
1989
|
generate(outputRoot) {
|
|
2032
|
-
const outputDir =
|
|
1990
|
+
const outputDir = path7.join(outputRoot, "services");
|
|
2033
1991
|
const paths = this.extractPaths();
|
|
2034
|
-
if (paths.length === 0) {
|
|
2035
|
-
console.warn("No API paths found in the specification");
|
|
2036
|
-
return;
|
|
2037
|
-
}
|
|
2038
1992
|
const controllerGroups = this.groupPathsByController(paths);
|
|
2039
1993
|
Object.entries(controllerGroups).forEach(([controllerName, operations]) => {
|
|
2040
1994
|
this.generateServiceFile(controllerName, operations, outputDir);
|
|
2041
1995
|
});
|
|
2042
|
-
console.log(`Generated ${Object.keys(controllerGroups).length} service(s) from ${paths.length} path(s)`);
|
|
2043
1996
|
}
|
|
2044
1997
|
extractPaths() {
|
|
2045
1998
|
const paths = [];
|
|
2046
1999
|
const swaggerPaths = this.spec.paths || {};
|
|
2047
|
-
Object.entries(swaggerPaths).forEach(([
|
|
2000
|
+
Object.entries(swaggerPaths).forEach(([path10, pathItem]) => {
|
|
2048
2001
|
const methods = [
|
|
2049
2002
|
"get",
|
|
2050
2003
|
"post",
|
|
@@ -2058,7 +2011,7 @@ var ServiceGenerator = class {
|
|
|
2058
2011
|
if (pathItem[method]) {
|
|
2059
2012
|
const operation = pathItem[method];
|
|
2060
2013
|
paths.push({
|
|
2061
|
-
path:
|
|
2014
|
+
path: path10,
|
|
2062
2015
|
method: method.toUpperCase(),
|
|
2063
2016
|
operationId: operation.operationId,
|
|
2064
2017
|
summary: operation.summary,
|
|
@@ -2090,12 +2043,12 @@ var ServiceGenerator = class {
|
|
|
2090
2043
|
}
|
|
2091
2044
|
groupPathsByController(paths) {
|
|
2092
2045
|
const groups = {};
|
|
2093
|
-
paths.forEach((
|
|
2046
|
+
paths.forEach((path10) => {
|
|
2094
2047
|
let controllerName = "Default";
|
|
2095
|
-
if (
|
|
2096
|
-
controllerName =
|
|
2048
|
+
if (path10.tags && path10.tags.length > 0) {
|
|
2049
|
+
controllerName = path10.tags[0];
|
|
2097
2050
|
} else {
|
|
2098
|
-
const pathParts =
|
|
2051
|
+
const pathParts = path10.path.split("/").filter((p) => p && !p.startsWith("{"));
|
|
2099
2052
|
if (pathParts.length > 1) {
|
|
2100
2053
|
controllerName = pascalCase(pathParts[1]);
|
|
2101
2054
|
}
|
|
@@ -2104,13 +2057,13 @@ var ServiceGenerator = class {
|
|
|
2104
2057
|
if (!groups[controllerName]) {
|
|
2105
2058
|
groups[controllerName] = [];
|
|
2106
2059
|
}
|
|
2107
|
-
groups[controllerName].push(
|
|
2060
|
+
groups[controllerName].push(path10);
|
|
2108
2061
|
});
|
|
2109
2062
|
return groups;
|
|
2110
2063
|
}
|
|
2111
2064
|
generateServiceFile(controllerName, operations, outputDir) {
|
|
2112
2065
|
const fileName = `${camelCase(controllerName)}.service.ts`;
|
|
2113
|
-
const filePath =
|
|
2066
|
+
const filePath = path7.join(outputDir, fileName);
|
|
2114
2067
|
const sourceFile = this.project.createSourceFile(filePath, "", {
|
|
2115
2068
|
overwrite: true
|
|
2116
2069
|
});
|
|
@@ -2304,7 +2257,7 @@ return context.set(this.clientContextToken, '${this.config.clientName || "defaul
|
|
|
2304
2257
|
|
|
2305
2258
|
// src/lib/generators/service/service-index.generator.ts
|
|
2306
2259
|
var fs2 = __toESM(require("fs"));
|
|
2307
|
-
var
|
|
2260
|
+
var path8 = __toESM(require("path"));
|
|
2308
2261
|
var ServiceIndexGenerator = class {
|
|
2309
2262
|
static {
|
|
2310
2263
|
__name(this, "ServiceIndexGenerator");
|
|
@@ -2314,8 +2267,8 @@ var ServiceIndexGenerator = class {
|
|
|
2314
2267
|
this.project = project;
|
|
2315
2268
|
}
|
|
2316
2269
|
generateIndex(outputRoot) {
|
|
2317
|
-
const servicesDir =
|
|
2318
|
-
const indexPath =
|
|
2270
|
+
const servicesDir = path8.join(outputRoot, "services");
|
|
2271
|
+
const indexPath = path8.join(servicesDir, "index.ts");
|
|
2319
2272
|
const sourceFile = this.project.createSourceFile(indexPath, "", {
|
|
2320
2273
|
overwrite: true
|
|
2321
2274
|
});
|
|
@@ -2403,7 +2356,7 @@ var version = "0.0.37";
|
|
|
2403
2356
|
// src/lib/cli.ts
|
|
2404
2357
|
var program = new import_commander.Command();
|
|
2405
2358
|
async function loadConfigFile(configPath) {
|
|
2406
|
-
const resolvedPath =
|
|
2359
|
+
const resolvedPath = path9.resolve(configPath);
|
|
2407
2360
|
if (!fs4.existsSync(resolvedPath)) {
|
|
2408
2361
|
throw new Error(`Configuration file not found: ${resolvedPath}`);
|
|
2409
2362
|
}
|
|
@@ -2423,31 +2376,17 @@ async function loadConfigFile(configPath) {
|
|
|
2423
2376
|
}
|
|
2424
2377
|
}
|
|
2425
2378
|
__name(loadConfigFile, "loadConfigFile");
|
|
2426
|
-
function validateInputFile(inputPath) {
|
|
2427
|
-
if (!fs4.existsSync(inputPath)) {
|
|
2428
|
-
throw new Error(`Input file not found: ${inputPath}`);
|
|
2429
|
-
}
|
|
2430
|
-
const extension = path10.extname(inputPath).toLowerCase();
|
|
2431
|
-
const supportedExtensions = [
|
|
2432
|
-
".json",
|
|
2433
|
-
".yaml",
|
|
2434
|
-
".yml"
|
|
2435
|
-
];
|
|
2436
|
-
if (!supportedExtensions.includes(extension)) {
|
|
2437
|
-
console.warn(`Warning: File extension '${extension}' is not explicitly supported. Supported extensions: ${supportedExtensions.join(", ")}`);
|
|
2438
|
-
console.warn("The parser will attempt to auto-detect the format.");
|
|
2439
|
-
}
|
|
2440
|
-
}
|
|
2441
|
-
__name(validateInputFile, "validateInputFile");
|
|
2442
2379
|
async function generateFromOptions(options) {
|
|
2443
2380
|
try {
|
|
2444
2381
|
if (options.config) {
|
|
2445
2382
|
const config = await loadConfigFile(options.config);
|
|
2446
|
-
validateInputFile(path10.resolve(config.input));
|
|
2447
2383
|
await generateFromConfig(config);
|
|
2448
2384
|
} else if (options.input) {
|
|
2449
|
-
const inputPath =
|
|
2450
|
-
|
|
2385
|
+
const inputPath = path9.resolve(options.input);
|
|
2386
|
+
if (!fs4.existsSync(inputPath)) {
|
|
2387
|
+
console.error(`Error: Input file not found: ${inputPath}`);
|
|
2388
|
+
process.exit(1);
|
|
2389
|
+
}
|
|
2451
2390
|
const config = {
|
|
2452
2391
|
input: inputPath,
|
|
2453
2392
|
output: options.output || "./src/generated",
|
|
@@ -2471,10 +2410,10 @@ async function generateFromOptions(options) {
|
|
|
2471
2410
|
}
|
|
2472
2411
|
}
|
|
2473
2412
|
__name(generateFromOptions, "generateFromOptions");
|
|
2474
|
-
program.name("ng-openapi").description("Generate Angular services and types from OpenAPI
|
|
2413
|
+
program.name("ng-openapi").description("Generate Angular services and types from Swagger/OpenAPI spec").version(version).option("-c, --config <path>", "Path to configuration file").option("-i, --input <path>", "Path to Swagger/OpenAPI specification file").option("-o, --output <path>", "Output directory", "./src/generated").option("--types-only", "Generate only TypeScript interfaces").option("--date-type <type>", "Date type to use (string | Date)", "Date").action(async (options) => {
|
|
2475
2414
|
await generateFromOptions(options);
|
|
2476
2415
|
});
|
|
2477
|
-
program.command("generate").alias("gen").description("Generate code from
|
|
2416
|
+
program.command("generate").alias("gen").description("Generate code from Swagger specification").option("-c, --config <path>", "Path to configuration file").option("-i, --input <path>", "Path to Swagger/OpenAPI specification file").option("-o, --output <path>", "Output directory", "./src/generated").option("--types-only", "Generate only TypeScript interfaces").option("--date-type <type>", "Date type to use (string | Date)", "Date").action(async (options) => {
|
|
2478
2417
|
await generateFromOptions(options);
|
|
2479
2418
|
});
|
|
2480
2419
|
program.on("--help", () => {
|
|
@@ -2482,8 +2421,6 @@ program.on("--help", () => {
|
|
|
2482
2421
|
console.log("Examples:");
|
|
2483
2422
|
console.log(" $ ng-openapi -c ./openapi.config.ts");
|
|
2484
2423
|
console.log(" $ ng-openapi -i ./swagger.json -o ./src/api");
|
|
2485
|
-
console.log(" $ ng-openapi -i ./openapi.yaml -o ./src/api");
|
|
2486
|
-
console.log(" $ ng-openapi -i ./api-spec.yml -o ./src/api");
|
|
2487
2424
|
console.log(" $ ng-openapi generate -c ./openapi.config.ts");
|
|
2488
2425
|
console.log(" $ ng-openapi generate -i ./api.yaml --types-only");
|
|
2489
2426
|
});
|
package/index.d.ts
CHANGED
|
@@ -125,7 +125,6 @@ interface SwaggerDefinition {
|
|
|
125
125
|
anyOf?: SwaggerDefinition[];
|
|
126
126
|
}
|
|
127
127
|
interface SwaggerSpec {
|
|
128
|
-
openapi: string;
|
|
129
128
|
swagger: string;
|
|
130
129
|
info: Info;
|
|
131
130
|
externalDocs?: ExternalDocs | undefined;
|
|
@@ -163,20 +162,12 @@ type EnumValueObject = {
|
|
|
163
162
|
};
|
|
164
163
|
|
|
165
164
|
declare class SwaggerParser {
|
|
166
|
-
private
|
|
165
|
+
private spec;
|
|
167
166
|
constructor(swaggerPath: string);
|
|
168
167
|
getDefinitions(): Record<string, SwaggerDefinition>;
|
|
169
168
|
getDefinition(name: string): SwaggerDefinition | undefined;
|
|
170
169
|
resolveReference(ref: string): SwaggerDefinition | undefined;
|
|
171
170
|
getAllDefinitionNames(): string[];
|
|
172
|
-
getSpec(): SwaggerSpec;
|
|
173
|
-
getPaths(): Record<string, any>;
|
|
174
|
-
isValidSpec(): boolean;
|
|
175
|
-
getSpecVersion(): {
|
|
176
|
-
type: "swagger" | "openapi";
|
|
177
|
-
version: string;
|
|
178
|
-
} | null;
|
|
179
|
-
private parseSpecFile;
|
|
180
171
|
}
|
|
181
172
|
|
|
182
173
|
/**
|
package/index.js
CHANGED
|
@@ -80,13 +80,11 @@ module.exports = __toCommonJS(index_exports);
|
|
|
80
80
|
|
|
81
81
|
// src/lib/core/swagger-parser.ts
|
|
82
82
|
var fs = __toESM(require("fs"));
|
|
83
|
-
var path = __toESM(require("path"));
|
|
84
|
-
var yaml = __toESM(require("js-yaml"));
|
|
85
83
|
var _SwaggerParser = class _SwaggerParser {
|
|
86
84
|
constructor(swaggerPath) {
|
|
87
85
|
__publicField(this, "spec");
|
|
88
86
|
const swaggerContent = fs.readFileSync(swaggerPath, "utf8");
|
|
89
|
-
this.spec =
|
|
87
|
+
this.spec = JSON.parse(swaggerContent);
|
|
90
88
|
}
|
|
91
89
|
getDefinitions() {
|
|
92
90
|
var _a;
|
|
@@ -104,42 +102,6 @@ var _SwaggerParser = class _SwaggerParser {
|
|
|
104
102
|
getAllDefinitionNames() {
|
|
105
103
|
return Object.keys(this.getDefinitions());
|
|
106
104
|
}
|
|
107
|
-
getSpec() {
|
|
108
|
-
return this.spec;
|
|
109
|
-
}
|
|
110
|
-
getPaths() {
|
|
111
|
-
return this.spec.paths || {};
|
|
112
|
-
}
|
|
113
|
-
isValidSpec() {
|
|
114
|
-
return !!(this.spec.swagger && this.spec.swagger.startsWith("2.") || this.spec.openapi && this.spec.openapi.startsWith("3."));
|
|
115
|
-
}
|
|
116
|
-
getSpecVersion() {
|
|
117
|
-
if (this.spec.swagger) {
|
|
118
|
-
return {
|
|
119
|
-
type: "swagger",
|
|
120
|
-
version: this.spec.swagger
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
if (this.spec.openapi) {
|
|
124
|
-
return {
|
|
125
|
-
type: "openapi",
|
|
126
|
-
version: this.spec.openapi
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
parseSpecFile(content, filePath) {
|
|
132
|
-
const extension = path.extname(filePath).toLowerCase();
|
|
133
|
-
switch (extension) {
|
|
134
|
-
case ".json":
|
|
135
|
-
return JSON.parse(content);
|
|
136
|
-
case ".yaml":
|
|
137
|
-
case ".yml":
|
|
138
|
-
return yaml.load(content);
|
|
139
|
-
default:
|
|
140
|
-
throw new Error(`Failed to parse ${extension || "specification"} file: ${filePath}. Supported formats are .json, .yaml, and .yml.`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
105
|
};
|
|
144
106
|
__name(_SwaggerParser, "SwaggerParser");
|
|
145
107
|
var SwaggerParser = _SwaggerParser;
|
|
@@ -488,7 +450,7 @@ var TypeGenerator = _TypeGenerator;
|
|
|
488
450
|
|
|
489
451
|
// src/lib/generators/utility/token.generator.ts
|
|
490
452
|
var import_ts_morph2 = require("ts-morph");
|
|
491
|
-
var
|
|
453
|
+
var path = __toESM(require("path"));
|
|
492
454
|
var _TokenGenerator = class _TokenGenerator {
|
|
493
455
|
constructor(project, clientName = "default") {
|
|
494
456
|
__publicField(this, "project");
|
|
@@ -497,8 +459,8 @@ var _TokenGenerator = class _TokenGenerator {
|
|
|
497
459
|
this.clientName = clientName;
|
|
498
460
|
}
|
|
499
461
|
generate(outputDir) {
|
|
500
|
-
const tokensDir =
|
|
501
|
-
const filePath =
|
|
462
|
+
const tokensDir = path.join(outputDir, "tokens");
|
|
463
|
+
const filePath = path.join(tokensDir, "index.ts");
|
|
502
464
|
const sourceFile = this.project.createSourceFile(filePath, "", {
|
|
503
465
|
overwrite: true
|
|
504
466
|
});
|
|
@@ -615,15 +577,15 @@ __name(_TokenGenerator, "TokenGenerator");
|
|
|
615
577
|
var TokenGenerator = _TokenGenerator;
|
|
616
578
|
|
|
617
579
|
// src/lib/generators/utility/file-download.generator.ts
|
|
618
|
-
var
|
|
580
|
+
var path2 = __toESM(require("path"));
|
|
619
581
|
var _FileDownloadGenerator = class _FileDownloadGenerator {
|
|
620
582
|
constructor(project) {
|
|
621
583
|
__publicField(this, "project");
|
|
622
584
|
this.project = project;
|
|
623
585
|
}
|
|
624
586
|
generate(outputDir) {
|
|
625
|
-
const utilsDir =
|
|
626
|
-
const filePath =
|
|
587
|
+
const utilsDir = path2.join(outputDir, "utils");
|
|
588
|
+
const filePath = path2.join(utilsDir, "file-download.ts");
|
|
627
589
|
const sourceFile = this.project.createSourceFile(filePath, "", {
|
|
628
590
|
overwrite: true
|
|
629
591
|
});
|
|
@@ -756,15 +718,15 @@ var FileDownloadGenerator = _FileDownloadGenerator;
|
|
|
756
718
|
|
|
757
719
|
// src/lib/generators/utility/date-transformer.generator.ts
|
|
758
720
|
var import_ts_morph3 = require("ts-morph");
|
|
759
|
-
var
|
|
721
|
+
var path3 = __toESM(require("path"));
|
|
760
722
|
var _DateTransformerGenerator = class _DateTransformerGenerator {
|
|
761
723
|
constructor(project) {
|
|
762
724
|
__publicField(this, "project");
|
|
763
725
|
this.project = project;
|
|
764
726
|
}
|
|
765
727
|
generate(outputDir) {
|
|
766
|
-
const utilsDir =
|
|
767
|
-
const filePath =
|
|
728
|
+
const utilsDir = path3.join(outputDir, "utils");
|
|
729
|
+
const filePath = path3.join(utilsDir, "date-transformer.ts");
|
|
768
730
|
const sourceFile = this.project.createSourceFile(filePath, "", {
|
|
769
731
|
overwrite: true
|
|
770
732
|
});
|
|
@@ -889,7 +851,7 @@ __name(_DateTransformerGenerator, "DateTransformerGenerator");
|
|
|
889
851
|
var DateTransformerGenerator = _DateTransformerGenerator;
|
|
890
852
|
|
|
891
853
|
// src/lib/generators/utility/main-index.generator.ts
|
|
892
|
-
var
|
|
854
|
+
var path4 = __toESM(require("path"));
|
|
893
855
|
var _MainIndexGenerator = class _MainIndexGenerator {
|
|
894
856
|
constructor(project, config) {
|
|
895
857
|
__publicField(this, "project");
|
|
@@ -898,7 +860,7 @@ var _MainIndexGenerator = class _MainIndexGenerator {
|
|
|
898
860
|
this.config = config;
|
|
899
861
|
}
|
|
900
862
|
generateMainIndex(outputRoot) {
|
|
901
|
-
const indexPath =
|
|
863
|
+
const indexPath = path4.join(outputRoot, "index.ts");
|
|
902
864
|
const sourceFile = this.project.createSourceFile(indexPath, "", {
|
|
903
865
|
overwrite: true
|
|
904
866
|
});
|
|
@@ -932,7 +894,7 @@ __name(_MainIndexGenerator, "MainIndexGenerator");
|
|
|
932
894
|
var MainIndexGenerator = _MainIndexGenerator;
|
|
933
895
|
|
|
934
896
|
// src/lib/generators/utility/provider.generator.ts
|
|
935
|
-
var
|
|
897
|
+
var path5 = __toESM(require("path"));
|
|
936
898
|
var _ProviderGenerator = class _ProviderGenerator {
|
|
937
899
|
constructor(project, config) {
|
|
938
900
|
__publicField(this, "project");
|
|
@@ -943,7 +905,7 @@ var _ProviderGenerator = class _ProviderGenerator {
|
|
|
943
905
|
this.clientName = config.clientName || "default";
|
|
944
906
|
}
|
|
945
907
|
generate(outputDir) {
|
|
946
|
-
const filePath =
|
|
908
|
+
const filePath = path5.join(outputDir, "providers.ts");
|
|
947
909
|
const sourceFile = this.project.createSourceFile(filePath, "", {
|
|
948
910
|
overwrite: true
|
|
949
911
|
});
|
|
@@ -1138,7 +1100,7 @@ var ProviderGenerator = _ProviderGenerator;
|
|
|
1138
1100
|
|
|
1139
1101
|
// src/lib/generators/utility/base-interceptor.generator.ts
|
|
1140
1102
|
var import_ts_morph4 = require("ts-morph");
|
|
1141
|
-
var
|
|
1103
|
+
var path6 = __toESM(require("path"));
|
|
1142
1104
|
var _project, _clientName;
|
|
1143
1105
|
var _BaseInterceptorGenerator = class _BaseInterceptorGenerator {
|
|
1144
1106
|
constructor(project, clientName = "default") {
|
|
@@ -1148,8 +1110,8 @@ var _BaseInterceptorGenerator = class _BaseInterceptorGenerator {
|
|
|
1148
1110
|
__privateSet(this, _clientName, clientName);
|
|
1149
1111
|
}
|
|
1150
1112
|
generate(outputDir) {
|
|
1151
|
-
const utilsDir =
|
|
1152
|
-
const filePath =
|
|
1113
|
+
const utilsDir = path6.join(outputDir, "utils");
|
|
1114
|
+
const filePath = path6.join(utilsDir, "base-interceptor.ts");
|
|
1153
1115
|
const sourceFile = __privateGet(this, _project).createSourceFile(filePath, "", {
|
|
1154
1116
|
overwrite: true
|
|
1155
1117
|
});
|
|
@@ -1272,7 +1234,7 @@ var BaseInterceptorGenerator = _BaseInterceptorGenerator;
|
|
|
1272
1234
|
|
|
1273
1235
|
// src/lib/generators/service/service.generator.ts
|
|
1274
1236
|
var import_ts_morph5 = require("ts-morph");
|
|
1275
|
-
var
|
|
1237
|
+
var path7 = __toESM(require("path"));
|
|
1276
1238
|
|
|
1277
1239
|
// src/lib/utils/string.utils.ts
|
|
1278
1240
|
function camelCase(str) {
|
|
@@ -2072,30 +2034,21 @@ var _ServiceGenerator = class _ServiceGenerator {
|
|
|
2072
2034
|
this.config = config;
|
|
2073
2035
|
this.project = project;
|
|
2074
2036
|
this.parser = new SwaggerParser(swaggerPath);
|
|
2075
|
-
this.spec =
|
|
2076
|
-
if (!this.parser.isValidSpec()) {
|
|
2077
|
-
const versionInfo = this.parser.getSpecVersion();
|
|
2078
|
-
throw new Error(`Invalid or unsupported specification format. Expected OpenAPI 3.x or Swagger 2.x. ${versionInfo ? `Found: ${versionInfo.type} ${versionInfo.version}` : "No version info found"}`);
|
|
2079
|
-
}
|
|
2037
|
+
this.spec = JSON.parse(require("fs").readFileSync(swaggerPath, "utf8"));
|
|
2080
2038
|
this.methodGenerator = new ServiceMethodGenerator(config);
|
|
2081
2039
|
}
|
|
2082
2040
|
generate(outputRoot) {
|
|
2083
|
-
const outputDir =
|
|
2041
|
+
const outputDir = path7.join(outputRoot, "services");
|
|
2084
2042
|
const paths = this.extractPaths();
|
|
2085
|
-
if (paths.length === 0) {
|
|
2086
|
-
console.warn("No API paths found in the specification");
|
|
2087
|
-
return;
|
|
2088
|
-
}
|
|
2089
2043
|
const controllerGroups = this.groupPathsByController(paths);
|
|
2090
2044
|
Object.entries(controllerGroups).forEach(([controllerName, operations]) => {
|
|
2091
2045
|
this.generateServiceFile(controllerName, operations, outputDir);
|
|
2092
2046
|
});
|
|
2093
|
-
console.log(`Generated ${Object.keys(controllerGroups).length} service(s) from ${paths.length} path(s)`);
|
|
2094
2047
|
}
|
|
2095
2048
|
extractPaths() {
|
|
2096
2049
|
const paths = [];
|
|
2097
2050
|
const swaggerPaths = this.spec.paths || {};
|
|
2098
|
-
Object.entries(swaggerPaths).forEach(([
|
|
2051
|
+
Object.entries(swaggerPaths).forEach(([path9, pathItem]) => {
|
|
2099
2052
|
const methods = [
|
|
2100
2053
|
"get",
|
|
2101
2054
|
"post",
|
|
@@ -2109,7 +2062,7 @@ var _ServiceGenerator = class _ServiceGenerator {
|
|
|
2109
2062
|
if (pathItem[method]) {
|
|
2110
2063
|
const operation = pathItem[method];
|
|
2111
2064
|
paths.push({
|
|
2112
|
-
path:
|
|
2065
|
+
path: path9,
|
|
2113
2066
|
method: method.toUpperCase(),
|
|
2114
2067
|
operationId: operation.operationId,
|
|
2115
2068
|
summary: operation.summary,
|
|
@@ -2141,12 +2094,12 @@ var _ServiceGenerator = class _ServiceGenerator {
|
|
|
2141
2094
|
}
|
|
2142
2095
|
groupPathsByController(paths) {
|
|
2143
2096
|
const groups = {};
|
|
2144
|
-
paths.forEach((
|
|
2097
|
+
paths.forEach((path9) => {
|
|
2145
2098
|
let controllerName = "Default";
|
|
2146
|
-
if (
|
|
2147
|
-
controllerName =
|
|
2099
|
+
if (path9.tags && path9.tags.length > 0) {
|
|
2100
|
+
controllerName = path9.tags[0];
|
|
2148
2101
|
} else {
|
|
2149
|
-
const pathParts =
|
|
2102
|
+
const pathParts = path9.path.split("/").filter((p) => p && !p.startsWith("{"));
|
|
2150
2103
|
if (pathParts.length > 1) {
|
|
2151
2104
|
controllerName = pascalCase(pathParts[1]);
|
|
2152
2105
|
}
|
|
@@ -2155,13 +2108,13 @@ var _ServiceGenerator = class _ServiceGenerator {
|
|
|
2155
2108
|
if (!groups[controllerName]) {
|
|
2156
2109
|
groups[controllerName] = [];
|
|
2157
2110
|
}
|
|
2158
|
-
groups[controllerName].push(
|
|
2111
|
+
groups[controllerName].push(path9);
|
|
2159
2112
|
});
|
|
2160
2113
|
return groups;
|
|
2161
2114
|
}
|
|
2162
2115
|
generateServiceFile(controllerName, operations, outputDir) {
|
|
2163
2116
|
const fileName = `${camelCase(controllerName)}.service.ts`;
|
|
2164
|
-
const filePath =
|
|
2117
|
+
const filePath = path7.join(outputDir, fileName);
|
|
2165
2118
|
const sourceFile = this.project.createSourceFile(filePath, "", {
|
|
2166
2119
|
overwrite: true
|
|
2167
2120
|
});
|
|
@@ -2358,15 +2311,15 @@ var ServiceGenerator = _ServiceGenerator;
|
|
|
2358
2311
|
|
|
2359
2312
|
// src/lib/generators/service/service-index.generator.ts
|
|
2360
2313
|
var fs2 = __toESM(require("fs"));
|
|
2361
|
-
var
|
|
2314
|
+
var path8 = __toESM(require("path"));
|
|
2362
2315
|
var _ServiceIndexGenerator = class _ServiceIndexGenerator {
|
|
2363
2316
|
constructor(project) {
|
|
2364
2317
|
__publicField(this, "project");
|
|
2365
2318
|
this.project = project;
|
|
2366
2319
|
}
|
|
2367
2320
|
generateIndex(outputRoot) {
|
|
2368
|
-
const servicesDir =
|
|
2369
|
-
const indexPath =
|
|
2321
|
+
const servicesDir = path8.join(outputRoot, "services");
|
|
2322
|
+
const indexPath = path8.join(servicesDir, "index.ts");
|
|
2370
2323
|
const sourceFile = this.project.createSourceFile(indexPath, "", {
|
|
2371
2324
|
overwrite: true
|
|
2372
2325
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ng-openapi",
|
|
3
|
-
"version": "0.0.38
|
|
3
|
+
"version": "0.0.38",
|
|
4
4
|
"description": "Generate Angular services and TypeScript types from OpenAPI/Swagger specifications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -61,8 +61,7 @@
|
|
|
61
61
|
"ts-morph": "^26.0.0",
|
|
62
62
|
"ts-node": "^10.9.2",
|
|
63
63
|
"typescript": "^5.8.3",
|
|
64
|
-
"@types/swagger-schema-official": "^2.0.25"
|
|
65
|
-
"js-yaml": "^4.1.0"
|
|
64
|
+
"@types/swagger-schema-official": "^2.0.25"
|
|
66
65
|
},
|
|
67
66
|
"peerDependencies": {
|
|
68
67
|
"@angular/core": ">=15",
|