Skip to content

Commit 790fece

Browse files
authored
feat: add support x-propertyNames, propertyNames for object types (#1302)
1 parent f5b6b2d commit 790fece

File tree

7 files changed

+196
-12
lines changed

7 files changed

+196
-12
lines changed

.changeset/dull-monkeys-help.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"swagger-typescript-api": patch
3+
---
4+
5+
added support x-propertyNames, propertyNames for object types

src/schema-parser/base-schema-parsers/object.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,27 @@ export class ObjectSchemaParser extends MonoSchemaParser {
8282
});
8383

8484
if (additionalProperties) {
85+
const propertyNamesSchema =
86+
this.schemaUtils.getSchemaPropertyNamesSchema(schema);
87+
let interfaceKeysContent: any;
88+
89+
if (propertyNamesSchema) {
90+
interfaceKeysContent = this.schemaParserFabric
91+
.createSchemaParser({
92+
schema: propertyNamesSchema,
93+
schemaPath: this.schemaPath,
94+
})
95+
.getInlineParseContent();
96+
} else {
97+
interfaceKeysContent = this.config.Ts.Keyword.String;
98+
}
99+
85100
propertiesContent.push({
86101
$$raw: { additionalProperties },
87102
description: "",
88103
isRequired: false,
89104
field: this.config.Ts.InterfaceDynamicField(
90-
this.config.Ts.Keyword.String,
105+
interfaceKeysContent,
91106
this.config.Ts.Keyword.Any,
92107
),
93108
});

src/schema-parser/base-schema-parsers/primitive.ts

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,38 @@ export class PrimitiveSchemaParser extends MonoSchemaParser {
88
this.schema || {};
99

1010
if (type === this.config.Ts.Keyword.Object && additionalProperties) {
11-
const fieldType =
12-
typeof additionalProperties === "object"
13-
? this.schemaParserFabric
14-
.createSchemaParser({
15-
schema: additionalProperties,
16-
schemaPath: this.schemaPath,
17-
})
18-
.getInlineParseContent()
19-
: this.config.Ts.Keyword.Any;
11+
const propertyNamesSchema = this.schemaUtils.getSchemaPropertyNamesSchema(
12+
this.schema,
13+
);
14+
15+
let recordKeysContent: any;
16+
let recordValuesContent: any;
17+
18+
if (propertyNamesSchema) {
19+
recordKeysContent = this.schemaParserFabric
20+
.createSchemaParser({
21+
schema: propertyNamesSchema,
22+
schemaPath: this.schemaPath,
23+
})
24+
.getInlineParseContent();
25+
} else {
26+
recordKeysContent = this.config.Ts.Keyword.String;
27+
}
28+
29+
if (typeof additionalProperties === "object") {
30+
recordValuesContent = this.schemaParserFabric
31+
.createSchemaParser({
32+
schema: additionalProperties,
33+
schemaPath: this.schemaPath,
34+
})
35+
.getInlineParseContent();
36+
} else {
37+
recordValuesContent = this.config.Ts.Keyword.Any;
38+
}
39+
2040
contentType = this.config.Ts.RecordType(
21-
this.config.Ts.Keyword.String,
22-
fieldType,
41+
recordKeysContent,
42+
recordValuesContent,
2343
);
2444
}
2545

src/schema-parser/schema-utils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ export class SchemaUtils {
5353
);
5454
};
5555

56+
getSchemaPropertyNamesSchema = (schema) => {
57+
if (!schema) return null;
58+
return schema.propertyNames || schema["x-propertyNames"] || null;
59+
};
60+
5661
getSchemaRefType = (schema) => {
5762
if (!this.isRefSchema(schema)) return null;
5863
return this.schemaComponentsMap.get(schema.$ref);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`basic > propertyNames 1`] = `
4+
"/* eslint-disable */
5+
/* tslint:disable */
6+
// @ts-nocheck
7+
/*
8+
* ---------------------------------------------------------------
9+
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
10+
* ## ##
11+
* ## AUTHOR: acacode ##
12+
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
13+
* ---------------------------------------------------------------
14+
*/
15+
16+
export enum KekEnum {
17+
/** Creating */
18+
Creating = "creating",
19+
/** created */
20+
Created = "created",
21+
/** Starting */
22+
Starting = "starting",
23+
/** Kkeke */
24+
Started = "started",
25+
/** dsafads */
26+
Restarting = "restarting",
27+
/** dasfds */
28+
Stopping = "stopping",
29+
/** dadd */
30+
Stopped = "stopped",
31+
/** xzxzxz */
32+
Deploy = "deploy",
33+
/** axzxe */
34+
WaitDependency = "wait_dependency",
35+
Updating = "updating",
36+
}
37+
38+
export type FooBarBazRoot = Record<KekEnum, number>;
39+
40+
export type FooBarBazNoAdditionalProperties = object;
41+
42+
export type FooBarBazNoAdditionalPropertiesPrimitive = object;
43+
44+
export interface FooBarBazNested {
45+
dataCount?: Record<KekEnum, number>;
46+
}
47+
"
48+
`;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import * as fs from "node:fs/promises";
2+
import * as os from "node:os";
3+
import * as path from "node:path";
4+
5+
import { afterAll, beforeAll, describe, expect, test } from "vitest";
6+
7+
import { generateApi } from "../../../src/index.js";
8+
9+
describe("basic", async () => {
10+
let tmpdir = "";
11+
12+
beforeAll(async () => {
13+
tmpdir = await fs.mkdtemp(path.join(os.tmpdir(), "swagger-typescript-api"));
14+
});
15+
16+
afterAll(async () => {
17+
await fs.rm(tmpdir, { recursive: true });
18+
});
19+
20+
test("propertyNames", async () => {
21+
await generateApi({
22+
fileName: "schema",
23+
input: path.resolve(import.meta.dirname, "schema.yml"),
24+
output: tmpdir,
25+
silent: true,
26+
generateClient: false,
27+
generateRouteTypes: true,
28+
});
29+
30+
const content = await fs.readFile(path.join(tmpdir, "schema.ts"), {
31+
encoding: "utf8",
32+
});
33+
34+
expect(content).toMatchSnapshot();
35+
});
36+
});

tests/spec/propertyNames/schema.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
openapi: 3.0.3
2+
info:
3+
title: teesttt
4+
version: 0.0.0
5+
security:
6+
- registryCookieAuth: []
7+
- cookieAuth: [ ]
8+
components:
9+
schemas:
10+
FooBarBazRoot:
11+
type: object
12+
propertyNames:
13+
$ref: '#/components/schemas/KekEnum'
14+
additionalProperties:
15+
type: number
16+
FooBarBazNoAdditionalProperties:
17+
type: object
18+
propertyNames:
19+
$ref: '#/components/schemas/KekEnum'
20+
FooBarBazNoAdditionalPropertiesPrimitive:
21+
type: object
22+
propertyNames:
23+
type: number
24+
FooBarBazNested:
25+
type: object
26+
properties:
27+
dataCount:
28+
type: object
29+
propertyNames:
30+
$ref: '#/components/schemas/KekEnum'
31+
additionalProperties:
32+
type: number
33+
KekEnum:
34+
type: string
35+
enum:
36+
- creating
37+
- created
38+
- starting
39+
- started
40+
- restarting
41+
- stopping
42+
- stopped
43+
- deploy
44+
- wait_dependency
45+
- updating
46+
x-enum-descriptions:
47+
- Creating
48+
- created
49+
- Starting
50+
- Kkeke
51+
- dsafads
52+
- dasfds
53+
- dadd
54+
- xzxzxz
55+
- axzxe

0 commit comments

Comments
 (0)