Skip to content

Commit 39f9b2f

Browse files
Add schema to postTransform options (#2049)
* Add schema to postTransform options Closes #2013 * fixup! Add schema to postTransform options Closes #2013 * fixup! Add schema to postTransform options Closes #2013 * fixup! Add schema to postTransform options
1 parent 5bb2e15 commit 39f9b2f

File tree

6 files changed

+57
-6
lines changed

6 files changed

+57
-6
lines changed

Diff for: .changeset/four-worms-leave.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"openapi-typescript": patch
3+
---
4+
5+
Add schema to postTransform options

Diff for: docs/6.x/node.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,16 @@ Resultant diff with correctly-typed `file` property:
122122
+ file?: Blob;
123123
```
124124
125-
Any [Schema Object](https://spec.openapis.org/oas/latest.html#schema-object) present in your schema will be run through this formatter (even remote ones!). Also be sure to check the `metadata` parameter for additional context that may be helpful.
125+
#### transform / postTransform metadata
126126
127-
There are many other uses for this besides checking `format`. Because this must return a **string** you can produce any arbitrary TypeScript code you’d like (even your own custom types).
127+
Any [Schema Object](https://spec.openapis.org/oas/latest.html#schema-object) present in your schema will be run through `transform`, prior to its conversion to a TypeScript AST node, and `postTransform` after its conversion, including remote schemas!
128+
129+
The `metadata` parameter present on both `transform` and `postTransform` has additional context that may be helpful.
130+
131+
| Property | Description |
132+
|-|-|
133+
| `metadata.path` | A [`$ref`](https://json-schema.org/understanding-json-schema/structuring#dollarref) URI string, pointing to the current schema object |
134+
| `metadata.schema` | The schema object being transformed (only present for `postTransform`) |
135+
| `metadata.ctx` | The GlobalContext object, containing
136+
137+
There are many other uses for this besides checking `format`. Because `tranform` may return a **string** you can produce any arbitrary TypeScript code you’d like (even your own custom types).

Diff for: packages/openapi-typescript/src/transform/components-object.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,18 @@ export default function transformComponentsObject(componentsObject: ComponentsOb
3434

3535
const items: ts.TypeElement[] = [];
3636
if (componentsObject[key]) {
37-
for (const [name, item] of getEntries(componentsObject[key], ctx)) {
37+
for (const [name, item] of getEntries<SchemaObject>(componentsObject[key], ctx)) {
3838
let subType = transformers[key](item, {
3939
path: createRef(["components", key, name]),
40+
schema: item,
4041
ctx,
4142
});
4243

4344
let hasQuestionToken = false;
4445
if (ctx.transform) {
45-
const result = ctx.transform(item as SchemaObject, {
46+
const result = ctx.transform(item, {
4647
path: createRef(["components", key, name]),
48+
schema: item,
4749
ctx,
4850
});
4951
if (result) {

Diff for: packages/openapi-typescript/src/transform/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const transformers: Record<SchemaTransforms, (node: any, options: GlobalContext)
1515
paths: transformPathsObject,
1616
webhooks: transformWebhooksObject,
1717
components: transformComponentsObject,
18-
$defs: (node, options) => transformSchemaObject(node, { path: createRef(["$defs"]), ctx: options }),
18+
$defs: (node, options) => transformSchemaObject(node, { path: createRef(["$defs"]), ctx: options, schema: node }),
1919
};
2020

2121
export default function transformSchema(schema: OpenAPI3, ctx: GlobalContext) {

Diff for: packages/openapi-typescript/src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -710,5 +710,6 @@ export type $defs = Record<string, SchemaObject>;
710710
/** generic options for most internal transform* functions */
711711
export interface TransformNodeOptions {
712712
path?: string;
713+
schema?: SchemaObject | ReferenceObject;
713714
ctx: GlobalContext;
714715
}

Diff for: packages/openapi-typescript/test/node-api.test.ts

+34-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { fileURLToPath } from "node:url";
22
import ts from "typescript";
33
import openapiTS, { COMMENT_HEADER, astToString } from "../src/index.js";
4-
import type { OpenAPITSOptions } from "../src/types.js";
4+
import type { OpenAPITSOptions, ReferenceObject, SchemaObject } from "../src/types.js";
55
import type { TestCase } from "./test-helpers.js";
66

77
const EXAMPLES_DIR = new URL("../examples/", import.meta.url);
@@ -537,6 +537,11 @@ export type operations = Record<string, never>;`,
537537
components: {
538538
schemas: {
539539
Date: { type: "string", format: "date-time" },
540+
Set: {
541+
"x-string-enum-to-set": true,
542+
type: "string",
543+
enum: ["low", "medium", "high"],
544+
},
540545
},
541546
},
542547
},
@@ -546,6 +551,8 @@ export interface components {
546551
schemas: {
547552
/** Format: date-time */
548553
Date: DateOrTime;
554+
/** @enum {string} */
555+
Set: Set<"low" | "medium" | "high">;
549556
};
550557
responses: never;
551558
parameters: never;
@@ -565,6 +572,32 @@ export type operations = Record<string, never>;`,
565572
*/
566573
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("DateOrTime"));
567574
}
575+
576+
// Previously, in order to access the schema in postTransform,
577+
// you could resolve the schema using the path.
578+
// Now, the schema is made available directly on the options.
579+
// const schema = options.path
580+
// ? options.ctx.resolve<ReferenceObject | SchemaObject>(options.path)
581+
// : undefined;
582+
const schema = options.schema;
583+
584+
if (
585+
schema &&
586+
!("$ref" in schema) &&
587+
Object.hasOwn(schema, "x-string-enum-to-set") &&
588+
schema.type === "string" &&
589+
schema.enum?.every((enumMember) => {
590+
return typeof enumMember === "string";
591+
})
592+
) {
593+
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Set"), [
594+
ts.factory.createUnionTypeNode(
595+
schema.enum.map((value) => {
596+
return ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(value));
597+
}),
598+
),
599+
]);
600+
}
568601
},
569602
},
570603
},

0 commit comments

Comments
 (0)