Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/silent-beds-greet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"swagger-typescript-api": minor
---

partial support external paths by ref (#447)
5 changes: 5 additions & 0 deletions .changeset/some-clowns-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"swagger-typescript-api": minor
---

added partial support links property (jsdoc ref only)
19 changes: 19 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"editor.defaultFormatter": "biomejs.biome",
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[javascriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}
152 changes: 109 additions & 43 deletions bun.lock

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@
"lint": "biome check",
"prepack": "tsdown",
"test": "vitest run",
"test:update": "vitest run --update",
"typedoc": "typedoc"
},
"dependencies": {
"@apidevtools/swagger-parser": "12.1.0",
"@biomejs/js-api": "4.0.0",
"@biomejs/wasm-nodejs": "2.4.5",
"@types/swagger-schema-official": "^2.0.25",
Expand All @@ -57,7 +59,8 @@
"swagger2openapi": "^7.0.8",
"type-fest": "^5.4.4",
"typescript": "~5.9.3",
"yaml": "^2.8.2"
"yaml": "^2.8.2",
"yummies": "7.9.0"
},
"devDependencies": {
"@biomejs/biome": "2.4.5",
Expand Down
38 changes: 13 additions & 25 deletions src/code-gen-process.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { resolve } from "@apidevtools/swagger-parser";
import { consola } from "consola";
import { compact, merge } from "es-toolkit";
import { camelCase } from "es-toolkit/compat";
Expand All @@ -11,7 +12,6 @@ import { CodeGenConfig } from "./configuration.js";
import { SchemaComponentsMap } from "./schema-components-map.js";
import { SchemaParserFabric } from "./schema-parser/schema-parser-fabric.js";
import { SchemaRoutes } from "./schema-routes/schema-routes.js";
import { SchemaWalker } from "./schema-walker.js";
import { SwaggerSchemaResolver } from "./swagger-schema-resolver.js";
import { TemplatesWorker } from "./templates-worker.js";
import { JavascriptTranslator } from "./translators/javascript.js";
Expand Down Expand Up @@ -45,8 +45,8 @@ export class CodeGenProcess {
fileSystem: FileSystem;
codeFormatter: CodeFormatter;
templatesWorker: TemplatesWorker;
schemaWalker: SchemaWalker;
javascriptTranslator: JavascriptTranslator;
swaggerRefs: Awaited<ReturnType<typeof resolve>> | undefined | null;

constructor(config: Partial<GenerateApiConfiguration["config"]>) {
this.config = new CodeGenConfig(config);
Expand All @@ -55,10 +55,6 @@ export class CodeGenProcess {
this.config,
this.fileSystem,
);
this.schemaWalker = new SchemaWalker(
this.config,
this.swaggerSchemaResolver,
);
this.schemaComponentsMap = new SchemaComponentsMap(this.config);
this.typeNameFormatter = new TypeNameFormatter(this.config);
this.templatesWorker = new TemplatesWorker(
Expand All @@ -72,7 +68,6 @@ export class CodeGenProcess {
this.templatesWorker,
this.schemaComponentsMap,
this.typeNameFormatter,
this.schemaWalker,
);
this.schemaRoutes = new SchemaRoutes(
this.config,
Expand All @@ -95,35 +90,31 @@ export class CodeGenProcess {
templatesToRender: this.templatesWorker.getTemplates(this.config),
});

const swagger = await this.swaggerSchemaResolver.create();

this.swaggerSchemaResolver.fixSwaggerSchema(swagger);
const resolvedSwaggerSchema = await this.swaggerSchemaResolver.create();

this.config.update({
swaggerSchema: swagger.usageSchema,
originalSchema: swagger.originalSchema,
resolvedSwaggerSchema: resolvedSwaggerSchema,
swaggerSchema: resolvedSwaggerSchema.usageSchema,
originalSchema: resolvedSwaggerSchema.originalSchema,
});

this.schemaWalker.addSchema("$usage", swagger.usageSchema);
this.schemaWalker.addSchema("$original", swagger.originalSchema);

consola.info("start generating your typescript api");

this.config.update(
this.config.hooks.onInit(this.config, this) || this.config,
this.config.hooks.onInit?.(this.config, this) || this.config,
);

if (this.config.swaggerSchema) {
swagger.usageSchema = this.config.swaggerSchema;
resolvedSwaggerSchema.usageSchema = this.config.swaggerSchema;
}
if (this.config.originalSchema) {
swagger.originalSchema = this.config.originalSchema;
resolvedSwaggerSchema.originalSchema = this.config.originalSchema;
}

this.schemaComponentsMap.clear();

for (const [componentName, component] of Object.entries(
swagger.usageSchema.components || {},
resolvedSwaggerSchema.usageSchema.components || {},
)) {
for (const [typeName, rawTypeData] of Object.entries(
component as Record<string, unknown>,
Expand Down Expand Up @@ -158,13 +149,10 @@ export class CodeGenProcess {
return parsed;
});

this.schemaRoutes.attachSchema({
usageSchema: swagger.usageSchema,
parsedSchemas,
});
this.schemaRoutes.attachSchema(resolvedSwaggerSchema, parsedSchemas);

const rawConfiguration = {
apiConfig: this.createApiConfig(swagger.usageSchema),
apiConfig: this.createApiConfig(resolvedSwaggerSchema.usageSchema),
config: this.config,
modelTypes: this.collectModelTypes(),
hasSecurityRoutes: this.schemaRoutes.hasSecurityRoutes,
Expand All @@ -182,7 +170,7 @@ export class CodeGenProcess {
};

const configuration =
this.config.hooks.onPrepareConfig(rawConfiguration) || rawConfiguration;
this.config.hooks.onPrepareConfig?.(rawConfiguration) || rawConfiguration;

if (this.fileSystem.pathIsExist(this.config.output)) {
if (this.config.cleanOutput) {
Expand Down
12 changes: 10 additions & 2 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
} from "../types/index.js";
import { ComponentTypeNameResolver } from "./component-type-name-resolver.js";
import * as CONSTANTS from "./constants.js";
import type { ResolvedSwaggerSchema } from "./resolved-swagger-schema.js";
import type { MonoSchemaParser } from "./schema-parser/mono-schema-parser.js";
import type { SchemaParser } from "./schema-parser/schema-parser.js";
import type { Translator } from "./translators/translator.js";
Expand Down Expand Up @@ -110,6 +111,7 @@ export class CodeGenConfig {
) => {},
onFormatRouteName: (_routeInfo: unknown, _templateRouteName: unknown) => {},
};
resolvedSwaggerSchema!: ResolvedSwaggerSchema;
defaultResponseType;
singleHttpClient = false;
httpClientType = CONSTANTS.HTTP_CLIENT.FETCH;
Expand Down Expand Up @@ -167,7 +169,7 @@ export class CodeGenConfig {
spec: OpenAPI.Document | null = null;
fileName = "Api.ts";
authorizationToken: string | undefined;
requestOptions = null;
requestOptions: Record<string, any> | null = null;

jsPrimitiveTypes: string[] = [];
jsEmptyTypes: string[] = [];
Expand Down Expand Up @@ -441,7 +443,13 @@ export class CodeGenConfig {
this.componentTypeNameResolver = new ComponentTypeNameResolver(this, []);
}

update = (update: Partial<GenerateApiConfiguration["config"]>) => {
update = (
update: Partial<
GenerateApiConfiguration["config"] & {
resolvedSwaggerSchema: ResolvedSwaggerSchema;
}
>,
) => {
objectAssign(this, update);
if (this.enumNamesAsValues) {
this.extractEnums = true;
Expand Down
Loading