Skip to content

Commit a56ded2

Browse files
committed
feat: add ability to use in paths
1 parent 12f09e2 commit a56ded2

File tree

11 files changed

+621
-10
lines changed

11 files changed

+621
-10
lines changed

.vscode/settings.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"editor.defaultFormatter": "biomejs.biome",
3+
"[typescript]": {
4+
"editor.defaultFormatter": "biomejs.biome"
5+
},
6+
"[typescriptreact]": {
7+
"editor.defaultFormatter": "biomejs.biome"
8+
},
9+
"[javascript]": {
10+
"editor.defaultFormatter": "biomejs.biome"
11+
},
12+
"[javascriptreact]": {
13+
"editor.defaultFormatter": "biomejs.biome"
14+
},
15+
"editor.codeActionsOnSave": {
16+
"source.fixAll.biome": "explicit",
17+
"source.organizeImports.biome": "explicit"
18+
}
19+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"typedoc": "typedoc"
4747
},
4848
"dependencies": {
49+
"@apidevtools/swagger-parser": "12.0.0",
4950
"@biomejs/js-api": "3.0.0",
5051
"@biomejs/wasm-nodejs": "2.2.4",
5152
"@types/lodash": "^4.17.20",

src/code-gen-process.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import SwaggerParser, { type resolve } from "@apidevtools/swagger-parser";
12
import { consola } from "consola";
23
import lodash from "lodash";
34
import * as typescript from "typescript";
@@ -46,9 +47,12 @@ export class CodeGenProcess {
4647
templatesWorker: TemplatesWorker;
4748
schemaWalker: SchemaWalker;
4849
javascriptTranslator: JavascriptTranslator;
50+
swaggerParser: SwaggerParser;
51+
swaggerRefs: Awaited<ReturnType<typeof resolve>> | undefined | null;
4952

5053
constructor(config: Partial<GenerateApiConfiguration["config"]>) {
5154
this.config = new CodeGenConfig(config);
55+
this.swaggerParser = new SwaggerParser();
5256
this.fileSystem = new FileSystem();
5357
this.swaggerSchemaResolver = new SwaggerSchemaResolver(
5458
this.config,
@@ -58,7 +62,7 @@ export class CodeGenProcess {
5862
this.config,
5963
this.swaggerSchemaResolver,
6064
);
61-
this.schemaComponentsMap = new SchemaComponentsMap(this.config);
65+
this.schemaComponentsMap = new SchemaComponentsMap(this.config, this);
6266
this.typeNameFormatter = new TypeNameFormatter(this.config);
6367
this.templatesWorker = new TemplatesWorker(
6468
this.config,
@@ -75,6 +79,7 @@ export class CodeGenProcess {
7579
);
7680
this.schemaRoutes = new SchemaRoutes(
7781
this.config,
82+
this,
7883
this.schemaParserFabric,
7984
this.schemaComponentsMap,
8085
this.templatesWorker,
@@ -98,6 +103,42 @@ export class CodeGenProcess {
98103

99104
this.swaggerSchemaResolver.fixSwaggerSchema(swagger);
100105

106+
try {
107+
this.swaggerRefs = await this.swaggerParser.resolve(
108+
this.config.url || this.config.input || (this.config.spec as any),
109+
{
110+
continueOnError: true,
111+
mutateInputSchema: true,
112+
validate: {
113+
schema: false,
114+
spec: false,
115+
},
116+
resolve: {
117+
external: true,
118+
http: {
119+
...this.config.requestOptions,
120+
headers: Object.assign(
121+
{},
122+
this.config.authorizationToken
123+
? {
124+
Authorization: this.config.authorizationToken,
125+
}
126+
: {},
127+
this.config.requestOptions?.headers ?? {},
128+
),
129+
},
130+
},
131+
},
132+
);
133+
this.swaggerRefs.set("fixed-swagger-schema", swagger.usageSchema as any);
134+
this.swaggerRefs.set(
135+
"original-swagger-schema",
136+
swagger.originalSchema as any,
137+
);
138+
} catch (e) {
139+
consola.error(e);
140+
}
141+
101142
this.config.update({
102143
swaggerSchema: swagger.usageSchema,
103144
originalSchema: swagger.originalSchema,

src/configuration.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { MonoSchemaParser } from "./schema-parser/mono-schema-parser.js";
1313
import type { SchemaParser } from "./schema-parser/schema-parser.js";
1414
import type { Translator } from "./translators/translator.js";
1515
import { objectAssign } from "./util/object-assign.js";
16+
import SwaggerParser from "@apidevtools/swagger-parser";
1617

1718
const TsKeyword = {
1819
Number: "number",
@@ -167,7 +168,7 @@ export class CodeGenConfig {
167168
spec: OpenAPI.Document | null = null;
168169
fileName = "Api.ts";
169170
authorizationToken: string | undefined;
170-
requestOptions = null;
171+
requestOptions: Record<string, any> | null = null;
171172

172173
jsPrimitiveTypes: string[] = [];
173174
jsEmptyTypes: string[] = [];

src/schema-components-map.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1+
import consola from "consola";
12
import type { SchemaComponent } from "../types/index.js";
3+
import type { CodeGenProcess } from "./code-gen-process.js";
24
import type { CodeGenConfig } from "./configuration.js";
35

46
export class SchemaComponentsMap {
57
_data: SchemaComponent[] = [];
68
config: CodeGenConfig;
79

8-
constructor(config: CodeGenConfig) {
10+
constructor(
11+
config: CodeGenConfig,
12+
private codegenProcess: CodeGenProcess,
13+
) {
914
this.config = config;
1015
}
1116

@@ -66,7 +71,20 @@ export class SchemaComponentsMap {
6671
}
6772

6873
get = ($ref: string) => {
69-
return this._data.find((c) => c.$ref === $ref) || null;
74+
const localFound = this._data.find((c) => c.$ref === $ref) || null;
75+
76+
if (localFound != null) {
77+
return localFound;
78+
}
79+
80+
if (this.codegenProcess.swaggerRefs) {
81+
try {
82+
return this.codegenProcess.swaggerRefs.get($ref) as Record<string, any>;
83+
} catch (e) {
84+
consola.error(e);
85+
return null;
86+
}
87+
}
7088
};
7189

7290
// Ensure enums are at the top of components list

src/schema-routes/schema-routes.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type {
44
GenerateApiConfiguration,
55
ParsedRoute,
66
} from "../../types/index.js";
7+
import type { CodeGenProcess } from "../code-gen-process.js";
78
import type { CodeGenConfig } from "../configuration.js";
89
import {
910
DEFAULT_BODY_ARG_NAME,
@@ -32,6 +33,7 @@ const CONTENT_KIND = {
3233

3334
export class SchemaRoutes {
3435
config: CodeGenConfig;
36+
codegenProcess: CodeGenProcess;
3537
schemaParserFabric: SchemaParserFabric;
3638
schemaUtils: SchemaUtils;
3739
typeNameFormatter: TypeNameFormatter;
@@ -47,12 +49,14 @@ export class SchemaRoutes {
4749

4850
constructor(
4951
config: CodeGenConfig,
52+
codegenProcess: CodeGenProcess,
5053
schemaParserFabric: SchemaParserFabric,
5154
schemaComponentsMap: SchemaComponentsMap,
5255
templatesWorker: TemplatesWorker,
5356
typeNameFormatter: TypeNameFormatter,
5457
) {
5558
this.config = config;
59+
this.codegenProcess = codegenProcess;
5660
this.schemaParserFabric = schemaParserFabric;
5761
this.schemaUtils = this.schemaParserFabric.schemaUtils;
5862
this.typeNameFormatter = typeNameFormatter;
@@ -71,10 +75,21 @@ export class SchemaRoutes {
7175
return lodash.reduce(
7276
routeInfoByMethodsMap,
7377
(acc, requestInfo, method) => {
74-
if (
75-
method.startsWith("x-") ||
76-
["parameters", "$ref"].includes(method)
77-
) {
78+
if (method.startsWith("x-") || ["parameters"].includes(method)) {
79+
return acc;
80+
}
81+
82+
if (method === "$ref") {
83+
if (this.codegenProcess.swaggerRefs) {
84+
try {
85+
const resolved = this.codegenProcess.swaggerRefs.get(requestInfo);
86+
Object.assign(acc, this.createRequestsMap(resolved));
87+
return acc;
88+
} catch (e) {
89+
consola.error(e);
90+
return acc;
91+
}
92+
}
7893
return acc;
7994
}
8095

@@ -209,7 +224,11 @@ export class SchemaRoutes {
209224

210225
let routeParam = null;
211226

212-
if (refTypeInfo?.rawTypeData.in && refTypeInfo.rawTypeData) {
227+
if (
228+
!!refTypeInfo?.rawTypeData &&
229+
typeof refTypeInfo === "object" &&
230+
refTypeInfo?.rawTypeData.in
231+
) {
213232
if (!routeParams[refTypeInfo.rawTypeData.in]) {
214233
routeParams[refTypeInfo.rawTypeData.in] = [];
215234
}

0 commit comments

Comments
 (0)