ng-openapi 0.0.40-pr-8-feature-url-support.0 → 0.0.40
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 +44 -184
- package/index.d.ts +2 -7
- package/index.js +32 -162
- package/package.json +1 -1
package/cli.cjs
CHANGED
|
@@ -33,18 +33,14 @@ var fs4 = __toESM(require("fs"));
|
|
|
33
33
|
var fs = __toESM(require("fs"));
|
|
34
34
|
var path = __toESM(require("path"));
|
|
35
35
|
var yaml = __toESM(require("js-yaml"));
|
|
36
|
-
var SwaggerParser = class
|
|
36
|
+
var SwaggerParser = class {
|
|
37
37
|
static {
|
|
38
38
|
__name(this, "SwaggerParser");
|
|
39
39
|
}
|
|
40
40
|
spec;
|
|
41
|
-
constructor(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
static async create(swaggerPathOrUrl) {
|
|
45
|
-
const swaggerContent = await _SwaggerParser.loadContent(swaggerPathOrUrl);
|
|
46
|
-
const spec = _SwaggerParser.parseSpecContent(swaggerContent, swaggerPathOrUrl);
|
|
47
|
-
return new _SwaggerParser(spec);
|
|
41
|
+
constructor(swaggerPath) {
|
|
42
|
+
const swaggerContent = fs.readFileSync(swaggerPath, "utf8");
|
|
43
|
+
this.spec = this.parseSpecFile(swaggerContent, swaggerPath);
|
|
48
44
|
}
|
|
49
45
|
getDefinitions() {
|
|
50
46
|
return this.spec.definitions || this.spec.components?.schemas || {};
|
|
@@ -85,100 +81,17 @@ var SwaggerParser = class _SwaggerParser {
|
|
|
85
81
|
}
|
|
86
82
|
return null;
|
|
87
83
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return true;
|
|
99
|
-
} catch {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
static async fetchUrlContent(url) {
|
|
104
|
-
try {
|
|
105
|
-
const response = await fetch(url, {
|
|
106
|
-
method: "GET",
|
|
107
|
-
headers: {
|
|
108
|
-
"Accept": "application/json, application/yaml, text/yaml, text/plain, */*",
|
|
109
|
-
"User-Agent": "ng-openapi"
|
|
110
|
-
},
|
|
111
|
-
// 30 second timeout
|
|
112
|
-
signal: AbortSignal.timeout(3e4)
|
|
113
|
-
});
|
|
114
|
-
if (!response.ok) {
|
|
115
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
116
|
-
}
|
|
117
|
-
const content = await response.text();
|
|
118
|
-
if (!content || content.trim() === "") {
|
|
119
|
-
throw new Error(`Empty response from URL: ${url}`);
|
|
120
|
-
}
|
|
121
|
-
return content;
|
|
122
|
-
} catch (error) {
|
|
123
|
-
let errorMessage = `Failed to fetch content from URL: ${url}`;
|
|
124
|
-
if (error.name === "AbortError") {
|
|
125
|
-
errorMessage += " - Request timeout (30s)";
|
|
126
|
-
} else if (error.message) {
|
|
127
|
-
errorMessage += ` - ${error.message}`;
|
|
128
|
-
}
|
|
129
|
-
throw new Error(errorMessage);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
static parseSpecContent(content, pathOrUrl) {
|
|
133
|
-
let format;
|
|
134
|
-
if (_SwaggerParser.isUrl(pathOrUrl)) {
|
|
135
|
-
const urlPath = new URL(pathOrUrl).pathname.toLowerCase();
|
|
136
|
-
if (urlPath.endsWith(".json")) {
|
|
137
|
-
format = "json";
|
|
138
|
-
} else if (urlPath.endsWith(".yaml") || urlPath.endsWith(".yml")) {
|
|
139
|
-
format = "yaml";
|
|
140
|
-
} else {
|
|
141
|
-
format = _SwaggerParser.detectFormat(content);
|
|
142
|
-
}
|
|
143
|
-
} else {
|
|
144
|
-
const extension = path.extname(pathOrUrl).toLowerCase();
|
|
145
|
-
switch (extension) {
|
|
146
|
-
case ".json":
|
|
147
|
-
format = "json";
|
|
148
|
-
break;
|
|
149
|
-
case ".yaml":
|
|
150
|
-
format = "yaml";
|
|
151
|
-
break;
|
|
152
|
-
case ".yml":
|
|
153
|
-
format = "yml";
|
|
154
|
-
break;
|
|
155
|
-
default:
|
|
156
|
-
format = _SwaggerParser.detectFormat(content);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
try {
|
|
160
|
-
switch (format) {
|
|
161
|
-
case "json":
|
|
162
|
-
return JSON.parse(content);
|
|
163
|
-
case "yaml":
|
|
164
|
-
case "yml":
|
|
165
|
-
return yaml.load(content);
|
|
166
|
-
default:
|
|
167
|
-
throw new Error(`Unable to determine format for: ${pathOrUrl}`);
|
|
168
|
-
}
|
|
169
|
-
} catch (error) {
|
|
170
|
-
throw new Error(`Failed to parse ${format.toUpperCase()} content from: ${pathOrUrl}. Error: ${error instanceof Error ? error.message : error}`);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
static detectFormat(content) {
|
|
174
|
-
const trimmed = content.trim();
|
|
175
|
-
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
176
|
-
return "json";
|
|
177
|
-
}
|
|
178
|
-
if (trimmed.includes("openapi:") || trimmed.includes("swagger:") || trimmed.includes("---") || /^[a-zA-Z][a-zA-Z0-9_]*\s*:/.test(trimmed)) {
|
|
179
|
-
return "yaml";
|
|
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.`);
|
|
180
94
|
}
|
|
181
|
-
return "json";
|
|
182
95
|
}
|
|
183
96
|
};
|
|
184
97
|
|
|
@@ -224,7 +137,7 @@ var BASE_INTERCEPTOR_HEADER_COMMENT = /* @__PURE__ */ __name((clientName) => def
|
|
|
224
137
|
`, "BASE_INTERCEPTOR_HEADER_COMMENT");
|
|
225
138
|
|
|
226
139
|
// src/lib/generators/type/type.generator.ts
|
|
227
|
-
var TypeGenerator = class
|
|
140
|
+
var TypeGenerator = class {
|
|
228
141
|
static {
|
|
229
142
|
__name(this, "TypeGenerator");
|
|
230
143
|
}
|
|
@@ -233,7 +146,7 @@ var TypeGenerator = class _TypeGenerator {
|
|
|
233
146
|
sourceFile;
|
|
234
147
|
generatedTypes = /* @__PURE__ */ new Set();
|
|
235
148
|
config;
|
|
236
|
-
constructor(
|
|
149
|
+
constructor(swaggerPath, outputRoot, config) {
|
|
237
150
|
this.config = config;
|
|
238
151
|
const outputPath = outputRoot + "/models/index.ts";
|
|
239
152
|
this.project = new import_ts_morph.Project({
|
|
@@ -245,14 +158,15 @@ var TypeGenerator = class _TypeGenerator {
|
|
|
245
158
|
...this.config.compilerOptions
|
|
246
159
|
}
|
|
247
160
|
});
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
161
|
+
try {
|
|
162
|
+
this.parser = new SwaggerParser(swaggerPath);
|
|
163
|
+
this.sourceFile = this.project.createSourceFile(outputPath, "", {
|
|
164
|
+
overwrite: true
|
|
165
|
+
});
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.error("Error initializing TypeGenerator:", error);
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
256
170
|
}
|
|
257
171
|
generate() {
|
|
258
172
|
try {
|
|
@@ -2094,7 +2008,7 @@ var ServiceMethodGenerator = class {
|
|
|
2094
2008
|
};
|
|
2095
2009
|
|
|
2096
2010
|
// src/lib/generators/service/service.generator.ts
|
|
2097
|
-
var ServiceGenerator = class
|
|
2011
|
+
var ServiceGenerator = class {
|
|
2098
2012
|
static {
|
|
2099
2013
|
__name(this, "ServiceGenerator");
|
|
2100
2014
|
}
|
|
@@ -2103,10 +2017,10 @@ var ServiceGenerator = class _ServiceGenerator {
|
|
|
2103
2017
|
spec;
|
|
2104
2018
|
config;
|
|
2105
2019
|
methodGenerator;
|
|
2106
|
-
constructor(
|
|
2020
|
+
constructor(swaggerPath, project, config) {
|
|
2107
2021
|
this.config = config;
|
|
2108
2022
|
this.project = project;
|
|
2109
|
-
this.parser =
|
|
2023
|
+
this.parser = new SwaggerParser(swaggerPath);
|
|
2110
2024
|
this.spec = this.parser.getSpec();
|
|
2111
2025
|
if (!this.parser.isValidSpec()) {
|
|
2112
2026
|
const versionInfo = this.parser.getSpecVersion();
|
|
@@ -2114,10 +2028,6 @@ var ServiceGenerator = class _ServiceGenerator {
|
|
|
2114
2028
|
}
|
|
2115
2029
|
this.methodGenerator = new ServiceMethodGenerator(config);
|
|
2116
2030
|
}
|
|
2117
|
-
static async create(swaggerPathOrUrl, project, config) {
|
|
2118
|
-
const parser = await SwaggerParser.create(swaggerPathOrUrl);
|
|
2119
|
-
return new _ServiceGenerator(parser, project, config);
|
|
2120
|
-
}
|
|
2121
2031
|
generate(outputRoot) {
|
|
2122
2032
|
const outputDir = path8.join(outputRoot, "services");
|
|
2123
2033
|
const paths = this.extractPaths();
|
|
@@ -2425,36 +2335,12 @@ var ServiceIndexGenerator = class {
|
|
|
2425
2335
|
|
|
2426
2336
|
// src/lib/core/generator.ts
|
|
2427
2337
|
var fs3 = __toESM(require("fs"));
|
|
2428
|
-
function isUrl(input) {
|
|
2429
|
-
try {
|
|
2430
|
-
new URL(input);
|
|
2431
|
-
return true;
|
|
2432
|
-
} catch {
|
|
2433
|
-
return false;
|
|
2434
|
-
}
|
|
2435
|
-
}
|
|
2436
|
-
__name(isUrl, "isUrl");
|
|
2437
|
-
function validateInput(input) {
|
|
2438
|
-
if (isUrl(input)) {
|
|
2439
|
-
const url = new URL(input);
|
|
2440
|
-
if (![
|
|
2441
|
-
"http:",
|
|
2442
|
-
"https:"
|
|
2443
|
-
].includes(url.protocol)) {
|
|
2444
|
-
throw new Error(`Unsupported URL protocol: ${url.protocol}. Only HTTP and HTTPS are supported.`);
|
|
2445
|
-
}
|
|
2446
|
-
} else {
|
|
2447
|
-
if (!fs3.existsSync(input)) {
|
|
2448
|
-
throw new Error(`Input file not found: ${input}`);
|
|
2449
|
-
}
|
|
2450
|
-
}
|
|
2451
|
-
}
|
|
2452
|
-
__name(validateInput, "validateInput");
|
|
2453
2338
|
async function generateFromConfig(config) {
|
|
2454
|
-
|
|
2339
|
+
if (!fs3.existsSync(config.input)) {
|
|
2340
|
+
throw new Error(`Input file not found: ${config.input}`);
|
|
2341
|
+
}
|
|
2455
2342
|
const outputPath = config.output;
|
|
2456
2343
|
const generateServices = config.options.generateServices ?? true;
|
|
2457
|
-
const inputType = isUrl(config.input) ? "URL" : "file";
|
|
2458
2344
|
if (!fs3.existsSync(outputPath)) {
|
|
2459
2345
|
fs3.mkdirSync(outputPath, {
|
|
2460
2346
|
recursive: true
|
|
@@ -2470,8 +2356,7 @@ async function generateFromConfig(config) {
|
|
|
2470
2356
|
...config.compilerOptions
|
|
2471
2357
|
}
|
|
2472
2358
|
});
|
|
2473
|
-
|
|
2474
|
-
const typeGenerator = await TypeGenerator.create(config.input, outputPath, config);
|
|
2359
|
+
const typeGenerator = new TypeGenerator(config.input, outputPath, config);
|
|
2475
2360
|
typeGenerator.generate();
|
|
2476
2361
|
console.log(`\u2705 TypeScript interfaces generated`);
|
|
2477
2362
|
if (generateServices) {
|
|
@@ -2483,7 +2368,7 @@ async function generateFromConfig(config) {
|
|
|
2483
2368
|
}
|
|
2484
2369
|
const fileDownloadHelper = new FileDownloadGenerator(project);
|
|
2485
2370
|
fileDownloadHelper.generate(outputPath);
|
|
2486
|
-
const serviceGenerator =
|
|
2371
|
+
const serviceGenerator = new ServiceGenerator(config.input, project, config);
|
|
2487
2372
|
serviceGenerator.generate(outputPath);
|
|
2488
2373
|
const indexGenerator = new ServiceIndexGenerator(project);
|
|
2489
2374
|
indexGenerator.generateIndex(outputPath);
|
|
@@ -2495,19 +2380,14 @@ async function generateFromConfig(config) {
|
|
|
2495
2380
|
}
|
|
2496
2381
|
const mainIndexGenerator = new MainIndexGenerator(project, config);
|
|
2497
2382
|
mainIndexGenerator.generateMainIndex(outputPath);
|
|
2498
|
-
const sourceInfo = `from ${inputType}: ${config.input}`;
|
|
2499
2383
|
if (config.clientName) {
|
|
2500
|
-
console.log(`\u{1F389} ${config.clientName} Generation completed successfully
|
|
2384
|
+
console.log(`\u{1F389} ${config.clientName} Generation completed successfully at: ${outputPath}`);
|
|
2501
2385
|
} else {
|
|
2502
|
-
console.log(
|
|
2386
|
+
console.log("\u{1F389} Generation completed successfully at:", outputPath);
|
|
2503
2387
|
}
|
|
2504
2388
|
} catch (error) {
|
|
2505
2389
|
if (error instanceof Error) {
|
|
2506
2390
|
console.error("\u274C Error during generation:", error.message);
|
|
2507
|
-
if (error.message.includes("fetch") || error.message.includes("Failed to fetch")) {
|
|
2508
|
-
console.error("\u{1F4A1} Tip: Make sure the URL is accessible and returns a valid OpenAPI/Swagger specification");
|
|
2509
|
-
console.error("\u{1F4A1} Alternative: Download the specification file locally and use the file path instead");
|
|
2510
|
-
}
|
|
2511
2391
|
} else {
|
|
2512
2392
|
console.error("\u274C Unknown error during generation:", error);
|
|
2513
2393
|
}
|
|
@@ -2542,26 +2422,7 @@ async function loadConfigFile(configPath) {
|
|
|
2542
2422
|
}
|
|
2543
2423
|
}
|
|
2544
2424
|
__name(loadConfigFile, "loadConfigFile");
|
|
2545
|
-
function
|
|
2546
|
-
try {
|
|
2547
|
-
new URL(input);
|
|
2548
|
-
return true;
|
|
2549
|
-
} catch {
|
|
2550
|
-
return false;
|
|
2551
|
-
}
|
|
2552
|
-
}
|
|
2553
|
-
__name(isUrl2, "isUrl");
|
|
2554
|
-
function validateInput2(inputPath) {
|
|
2555
|
-
if (isUrl2(inputPath)) {
|
|
2556
|
-
const url = new URL(inputPath);
|
|
2557
|
-
if (![
|
|
2558
|
-
"http:",
|
|
2559
|
-
"https:"
|
|
2560
|
-
].includes(url.protocol)) {
|
|
2561
|
-
throw new Error(`Unsupported URL protocol: ${url.protocol}. Only HTTP and HTTPS are supported.`);
|
|
2562
|
-
}
|
|
2563
|
-
return;
|
|
2564
|
-
}
|
|
2425
|
+
function validateInputFile(inputPath) {
|
|
2565
2426
|
if (!fs4.existsSync(inputPath)) {
|
|
2566
2427
|
throw new Error(`Input file not found: ${inputPath}`);
|
|
2567
2428
|
}
|
|
@@ -2575,17 +2436,18 @@ function validateInput2(inputPath) {
|
|
|
2575
2436
|
throw new Error(`Failed to parse ${extension || "specification"}. Supported formats are .json, .yaml, and .yml.`);
|
|
2576
2437
|
}
|
|
2577
2438
|
}
|
|
2578
|
-
__name(
|
|
2439
|
+
__name(validateInputFile, "validateInputFile");
|
|
2579
2440
|
async function generateFromOptions(options) {
|
|
2580
2441
|
try {
|
|
2581
2442
|
if (options.config) {
|
|
2582
2443
|
const config = await loadConfigFile(options.config);
|
|
2583
|
-
|
|
2444
|
+
validateInputFile(path10.resolve(config.input));
|
|
2584
2445
|
await generateFromConfig(config);
|
|
2585
2446
|
} else if (options.input) {
|
|
2586
|
-
|
|
2447
|
+
const inputPath = path10.resolve(options.input);
|
|
2448
|
+
validateInputFile(inputPath);
|
|
2587
2449
|
const config = {
|
|
2588
|
-
input:
|
|
2450
|
+
input: inputPath,
|
|
2589
2451
|
output: options.output || "./src/generated",
|
|
2590
2452
|
options: {
|
|
2591
2453
|
dateType: options.dateType || "Date",
|
|
@@ -2607,10 +2469,10 @@ async function generateFromOptions(options) {
|
|
|
2607
2469
|
}
|
|
2608
2470
|
}
|
|
2609
2471
|
__name(generateFromOptions, "generateFromOptions");
|
|
2610
|
-
program.name("ng-openapi").description("Generate Angular services and types from OpenAPI/Swagger specifications (JSON, YAML, YML)
|
|
2472
|
+
program.name("ng-openapi").description("Generate Angular services and types from OpenAPI/Swagger specifications (JSON, YAML, YML)").version(version).option("-c, --config <path>", "Path to configuration file").option("-i, --input <path>", "Path to OpenAPI/Swagger specification file (.json, .yaml, .yml)").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) => {
|
|
2611
2473
|
await generateFromOptions(options);
|
|
2612
2474
|
});
|
|
2613
|
-
program.command("generate").alias("gen").description("Generate code from OpenAPI/Swagger specification").option("-c, --config <path>", "Path to configuration file").option("-i, --input <path>", "Path
|
|
2475
|
+
program.command("generate").alias("gen").description("Generate code from OpenAPI/Swagger specification").option("-c, --config <path>", "Path to configuration file").option("-i, --input <path>", "Path to OpenAPI/Swagger specification file (.json, .yaml, .yml)").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) => {
|
|
2614
2476
|
await generateFromOptions(options);
|
|
2615
2477
|
});
|
|
2616
2478
|
program.on("--help", () => {
|
|
@@ -2620,10 +2482,8 @@ program.on("--help", () => {
|
|
|
2620
2482
|
console.log(" $ ng-openapi -i ./swagger.json -o ./src/api");
|
|
2621
2483
|
console.log(" $ ng-openapi -i ./openapi.yaml -o ./src/api");
|
|
2622
2484
|
console.log(" $ ng-openapi -i ./api-spec.yml -o ./src/api");
|
|
2623
|
-
console.log(" $ ng-openapi -i https://api.example.com/openapi.json -o ./src/api");
|
|
2624
|
-
console.log(" $ ng-openapi -i https://petstore.swagger.io/v2/swagger.json -o ./src/api");
|
|
2625
2485
|
console.log(" $ ng-openapi generate -c ./openapi.config.ts");
|
|
2626
|
-
console.log(" $ ng-openapi generate -i
|
|
2486
|
+
console.log(" $ ng-openapi generate -i ./api.yaml --types-only");
|
|
2627
2487
|
});
|
|
2628
2488
|
program.parse();
|
|
2629
2489
|
//# sourceMappingURL=cli.cjs.map
|
package/index.d.ts
CHANGED
|
@@ -164,8 +164,7 @@ type EnumValueObject = {
|
|
|
164
164
|
|
|
165
165
|
declare class SwaggerParser {
|
|
166
166
|
private readonly spec;
|
|
167
|
-
|
|
168
|
-
static create(swaggerPathOrUrl: string): Promise<SwaggerParser>;
|
|
167
|
+
constructor(swaggerPath: string);
|
|
169
168
|
getDefinitions(): Record<string, SwaggerDefinition>;
|
|
170
169
|
getDefinition(name: string): SwaggerDefinition | undefined;
|
|
171
170
|
resolveReference(ref: string): SwaggerDefinition | undefined;
|
|
@@ -177,11 +176,7 @@ declare class SwaggerParser {
|
|
|
177
176
|
type: "swagger" | "openapi";
|
|
178
177
|
version: string;
|
|
179
178
|
} | null;
|
|
180
|
-
private
|
|
181
|
-
private static isUrl;
|
|
182
|
-
private static fetchUrlContent;
|
|
183
|
-
private static parseSpecContent;
|
|
184
|
-
private static detectFormat;
|
|
179
|
+
private parseSpecFile;
|
|
185
180
|
}
|
|
186
181
|
|
|
187
182
|
/**
|
package/index.js
CHANGED
|
@@ -83,16 +83,10 @@ var fs = __toESM(require("fs"));
|
|
|
83
83
|
var path = __toESM(require("path"));
|
|
84
84
|
var yaml = __toESM(require("js-yaml"));
|
|
85
85
|
var _SwaggerParser = class _SwaggerParser {
|
|
86
|
-
constructor(
|
|
86
|
+
constructor(swaggerPath) {
|
|
87
87
|
__publicField(this, "spec");
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
static create(swaggerPathOrUrl) {
|
|
91
|
-
return __async(this, null, function* () {
|
|
92
|
-
const swaggerContent = yield _SwaggerParser.loadContent(swaggerPathOrUrl);
|
|
93
|
-
const spec = _SwaggerParser.parseSpecContent(swaggerContent, swaggerPathOrUrl);
|
|
94
|
-
return new _SwaggerParser(spec);
|
|
95
|
-
});
|
|
88
|
+
const swaggerContent = fs.readFileSync(swaggerPath, "utf8");
|
|
89
|
+
this.spec = this.parseSpecFile(swaggerContent, swaggerPath);
|
|
96
90
|
}
|
|
97
91
|
getDefinitions() {
|
|
98
92
|
var _a;
|
|
@@ -134,104 +128,17 @@ var _SwaggerParser = class _SwaggerParser {
|
|
|
134
128
|
}
|
|
135
129
|
return null;
|
|
136
130
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
new URL(input);
|
|
149
|
-
return true;
|
|
150
|
-
} catch (e) {
|
|
151
|
-
return false;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
static fetchUrlContent(url) {
|
|
155
|
-
return __async(this, null, function* () {
|
|
156
|
-
try {
|
|
157
|
-
const response = yield fetch(url, {
|
|
158
|
-
method: "GET",
|
|
159
|
-
headers: {
|
|
160
|
-
"Accept": "application/json, application/yaml, text/yaml, text/plain, */*",
|
|
161
|
-
"User-Agent": "ng-openapi"
|
|
162
|
-
},
|
|
163
|
-
// 30 second timeout
|
|
164
|
-
signal: AbortSignal.timeout(3e4)
|
|
165
|
-
});
|
|
166
|
-
if (!response.ok) {
|
|
167
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
168
|
-
}
|
|
169
|
-
const content = yield response.text();
|
|
170
|
-
if (!content || content.trim() === "") {
|
|
171
|
-
throw new Error(`Empty response from URL: ${url}`);
|
|
172
|
-
}
|
|
173
|
-
return content;
|
|
174
|
-
} catch (error) {
|
|
175
|
-
let errorMessage = `Failed to fetch content from URL: ${url}`;
|
|
176
|
-
if (error.name === "AbortError") {
|
|
177
|
-
errorMessage += " - Request timeout (30s)";
|
|
178
|
-
} else if (error.message) {
|
|
179
|
-
errorMessage += ` - ${error.message}`;
|
|
180
|
-
}
|
|
181
|
-
throw new Error(errorMessage);
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
static parseSpecContent(content, pathOrUrl) {
|
|
186
|
-
let format;
|
|
187
|
-
if (_SwaggerParser.isUrl(pathOrUrl)) {
|
|
188
|
-
const urlPath = new URL(pathOrUrl).pathname.toLowerCase();
|
|
189
|
-
if (urlPath.endsWith(".json")) {
|
|
190
|
-
format = "json";
|
|
191
|
-
} else if (urlPath.endsWith(".yaml") || urlPath.endsWith(".yml")) {
|
|
192
|
-
format = "yaml";
|
|
193
|
-
} else {
|
|
194
|
-
format = _SwaggerParser.detectFormat(content);
|
|
195
|
-
}
|
|
196
|
-
} else {
|
|
197
|
-
const extension = path.extname(pathOrUrl).toLowerCase();
|
|
198
|
-
switch (extension) {
|
|
199
|
-
case ".json":
|
|
200
|
-
format = "json";
|
|
201
|
-
break;
|
|
202
|
-
case ".yaml":
|
|
203
|
-
format = "yaml";
|
|
204
|
-
break;
|
|
205
|
-
case ".yml":
|
|
206
|
-
format = "yml";
|
|
207
|
-
break;
|
|
208
|
-
default:
|
|
209
|
-
format = _SwaggerParser.detectFormat(content);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
try {
|
|
213
|
-
switch (format) {
|
|
214
|
-
case "json":
|
|
215
|
-
return JSON.parse(content);
|
|
216
|
-
case "yaml":
|
|
217
|
-
case "yml":
|
|
218
|
-
return yaml.load(content);
|
|
219
|
-
default:
|
|
220
|
-
throw new Error(`Unable to determine format for: ${pathOrUrl}`);
|
|
221
|
-
}
|
|
222
|
-
} catch (error) {
|
|
223
|
-
throw new Error(`Failed to parse ${format.toUpperCase()} content from: ${pathOrUrl}. Error: ${error instanceof Error ? error.message : error}`);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
static detectFormat(content) {
|
|
227
|
-
const trimmed = content.trim();
|
|
228
|
-
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
229
|
-
return "json";
|
|
230
|
-
}
|
|
231
|
-
if (trimmed.includes("openapi:") || trimmed.includes("swagger:") || trimmed.includes("---") || /^[a-zA-Z][a-zA-Z0-9_]*\s*:/.test(trimmed)) {
|
|
232
|
-
return "yaml";
|
|
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.`);
|
|
233
141
|
}
|
|
234
|
-
return "json";
|
|
235
142
|
}
|
|
236
143
|
};
|
|
237
144
|
__name(_SwaggerParser, "SwaggerParser");
|
|
@@ -280,7 +187,7 @@ var BASE_INTERCEPTOR_HEADER_COMMENT = /* @__PURE__ */ __name((clientName) => def
|
|
|
280
187
|
|
|
281
188
|
// src/lib/generators/type/type.generator.ts
|
|
282
189
|
var _TypeGenerator = class _TypeGenerator {
|
|
283
|
-
constructor(
|
|
190
|
+
constructor(swaggerPath, outputRoot, config) {
|
|
284
191
|
__publicField(this, "project");
|
|
285
192
|
__publicField(this, "parser");
|
|
286
193
|
__publicField(this, "sourceFile");
|
|
@@ -296,16 +203,15 @@ var _TypeGenerator = class _TypeGenerator {
|
|
|
296
203
|
strict: true
|
|
297
204
|
}, this.config.compilerOptions)
|
|
298
205
|
});
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
});
|
|
206
|
+
try {
|
|
207
|
+
this.parser = new SwaggerParser(swaggerPath);
|
|
208
|
+
this.sourceFile = this.project.createSourceFile(outputPath, "", {
|
|
209
|
+
overwrite: true
|
|
210
|
+
});
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.error("Error initializing TypeGenerator:", error);
|
|
213
|
+
throw error;
|
|
214
|
+
}
|
|
309
215
|
}
|
|
310
216
|
generate() {
|
|
311
217
|
try {
|
|
@@ -2157,7 +2063,7 @@ var ServiceMethodGenerator = _ServiceMethodGenerator;
|
|
|
2157
2063
|
|
|
2158
2064
|
// src/lib/generators/service/service.generator.ts
|
|
2159
2065
|
var _ServiceGenerator = class _ServiceGenerator {
|
|
2160
|
-
constructor(
|
|
2066
|
+
constructor(swaggerPath, project, config) {
|
|
2161
2067
|
__publicField(this, "project");
|
|
2162
2068
|
__publicField(this, "parser");
|
|
2163
2069
|
__publicField(this, "spec");
|
|
@@ -2165,7 +2071,7 @@ var _ServiceGenerator = class _ServiceGenerator {
|
|
|
2165
2071
|
__publicField(this, "methodGenerator");
|
|
2166
2072
|
this.config = config;
|
|
2167
2073
|
this.project = project;
|
|
2168
|
-
this.parser =
|
|
2074
|
+
this.parser = new SwaggerParser(swaggerPath);
|
|
2169
2075
|
this.spec = this.parser.getSpec();
|
|
2170
2076
|
if (!this.parser.isValidSpec()) {
|
|
2171
2077
|
const versionInfo = this.parser.getSpecVersion();
|
|
@@ -2173,12 +2079,6 @@ var _ServiceGenerator = class _ServiceGenerator {
|
|
|
2173
2079
|
}
|
|
2174
2080
|
this.methodGenerator = new ServiceMethodGenerator(config);
|
|
2175
2081
|
}
|
|
2176
|
-
static create(swaggerPathOrUrl, project, config) {
|
|
2177
|
-
return __async(this, null, function* () {
|
|
2178
|
-
const parser = yield SwaggerParser.create(swaggerPathOrUrl);
|
|
2179
|
-
return new _ServiceGenerator(parser, project, config);
|
|
2180
|
-
});
|
|
2181
|
-
}
|
|
2182
2082
|
generate(outputRoot) {
|
|
2183
2083
|
const outputDir = path8.join(outputRoot, "services");
|
|
2184
2084
|
const paths = this.extractPaths();
|
|
@@ -2488,38 +2388,14 @@ var ServiceIndexGenerator = _ServiceIndexGenerator;
|
|
|
2488
2388
|
|
|
2489
2389
|
// src/lib/core/generator.ts
|
|
2490
2390
|
var fs3 = __toESM(require("fs"));
|
|
2491
|
-
function isUrl(input) {
|
|
2492
|
-
try {
|
|
2493
|
-
new URL(input);
|
|
2494
|
-
return true;
|
|
2495
|
-
} catch (e) {
|
|
2496
|
-
return false;
|
|
2497
|
-
}
|
|
2498
|
-
}
|
|
2499
|
-
__name(isUrl, "isUrl");
|
|
2500
|
-
function validateInput(input) {
|
|
2501
|
-
if (isUrl(input)) {
|
|
2502
|
-
const url = new URL(input);
|
|
2503
|
-
if (![
|
|
2504
|
-
"http:",
|
|
2505
|
-
"https:"
|
|
2506
|
-
].includes(url.protocol)) {
|
|
2507
|
-
throw new Error(`Unsupported URL protocol: ${url.protocol}. Only HTTP and HTTPS are supported.`);
|
|
2508
|
-
}
|
|
2509
|
-
} else {
|
|
2510
|
-
if (!fs3.existsSync(input)) {
|
|
2511
|
-
throw new Error(`Input file not found: ${input}`);
|
|
2512
|
-
}
|
|
2513
|
-
}
|
|
2514
|
-
}
|
|
2515
|
-
__name(validateInput, "validateInput");
|
|
2516
2391
|
function generateFromConfig(config) {
|
|
2517
2392
|
return __async(this, null, function* () {
|
|
2518
2393
|
var _a;
|
|
2519
|
-
|
|
2394
|
+
if (!fs3.existsSync(config.input)) {
|
|
2395
|
+
throw new Error(`Input file not found: ${config.input}`);
|
|
2396
|
+
}
|
|
2520
2397
|
const outputPath = config.output;
|
|
2521
2398
|
const generateServices = (_a = config.options.generateServices) != null ? _a : true;
|
|
2522
|
-
const inputType = isUrl(config.input) ? "URL" : "file";
|
|
2523
2399
|
if (!fs3.existsSync(outputPath)) {
|
|
2524
2400
|
fs3.mkdirSync(outputPath, {
|
|
2525
2401
|
recursive: true
|
|
@@ -2534,8 +2410,7 @@ function generateFromConfig(config) {
|
|
|
2534
2410
|
strict: true
|
|
2535
2411
|
}, config.compilerOptions)
|
|
2536
2412
|
});
|
|
2537
|
-
|
|
2538
|
-
const typeGenerator = yield TypeGenerator.create(config.input, outputPath, config);
|
|
2413
|
+
const typeGenerator = new TypeGenerator(config.input, outputPath, config);
|
|
2539
2414
|
typeGenerator.generate();
|
|
2540
2415
|
console.log(`\u2705 TypeScript interfaces generated`);
|
|
2541
2416
|
if (generateServices) {
|
|
@@ -2547,7 +2422,7 @@ function generateFromConfig(config) {
|
|
|
2547
2422
|
}
|
|
2548
2423
|
const fileDownloadHelper = new FileDownloadGenerator(project);
|
|
2549
2424
|
fileDownloadHelper.generate(outputPath);
|
|
2550
|
-
const serviceGenerator =
|
|
2425
|
+
const serviceGenerator = new ServiceGenerator(config.input, project, config);
|
|
2551
2426
|
serviceGenerator.generate(outputPath);
|
|
2552
2427
|
const indexGenerator = new ServiceIndexGenerator(project);
|
|
2553
2428
|
indexGenerator.generateIndex(outputPath);
|
|
@@ -2559,19 +2434,14 @@ function generateFromConfig(config) {
|
|
|
2559
2434
|
}
|
|
2560
2435
|
const mainIndexGenerator = new MainIndexGenerator(project, config);
|
|
2561
2436
|
mainIndexGenerator.generateMainIndex(outputPath);
|
|
2562
|
-
const sourceInfo = `from ${inputType}: ${config.input}`;
|
|
2563
2437
|
if (config.clientName) {
|
|
2564
|
-
console.log(`\u{1F389} ${config.clientName} Generation completed successfully
|
|
2438
|
+
console.log(`\u{1F389} ${config.clientName} Generation completed successfully at: ${outputPath}`);
|
|
2565
2439
|
} else {
|
|
2566
|
-
console.log(
|
|
2440
|
+
console.log("\u{1F389} Generation completed successfully at:", outputPath);
|
|
2567
2441
|
}
|
|
2568
2442
|
} catch (error) {
|
|
2569
2443
|
if (error instanceof Error) {
|
|
2570
2444
|
console.error("\u274C Error during generation:", error.message);
|
|
2571
|
-
if (error.message.includes("fetch") || error.message.includes("Failed to fetch")) {
|
|
2572
|
-
console.error("\u{1F4A1} Tip: Make sure the URL is accessible and returns a valid OpenAPI/Swagger specification");
|
|
2573
|
-
console.error("\u{1F4A1} Alternative: Download the specification file locally and use the file path instead");
|
|
2574
|
-
}
|
|
2575
2445
|
} else {
|
|
2576
2446
|
console.error("\u274C Unknown error during generation:", error);
|
|
2577
2447
|
}
|