Skip to content

Commit c267ea4

Browse files
committed
Add schema to postTransform options
Closes openapi-ts#2013
1 parent c9ba9dc commit c267ea4

File tree

5 files changed

+60
-7
lines changed

5 files changed

+60
-7
lines changed

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).

packages/openapi-typescript/src/transform/components-object.ts

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

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

4445
let hasQuestionToken = false;
4546
if (ctx.transform) {
46-
const result = ctx.transform(item as SchemaObject, {
47+
const result = ctx.transform(item, {
4748
path: createRef(["components", key, name]),
49+
schema: item,
4850
ctx,
4951
});
5052
if (result) {

packages/openapi-typescript/src/transform/index.ts

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

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

packages/openapi-typescript/src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -704,5 +704,6 @@ export type $defs = Record<string, SchemaObject>;
704704
/** generic options for most internal transform* functions */
705705
export interface TransformNodeOptions {
706706
path?: string;
707+
schema?: SchemaObject | ReferenceObject;
707708
ctx: GlobalContext;
708709
}

packages/openapi-typescript/test/node-api.test.ts

+42-2
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;
@@ -563,7 +570,40 @@ export type operations = Record<string, never>;`,
563570
* then use the `typescript` parser and it will tell you the desired
564571
* AST
565572
*/
566-
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("DateOrTime"));
573+
return ts.factory.createTypeReferenceNode(
574+
ts.factory.createIdentifier("DateOrTime")
575+
);
576+
}
577+
578+
// Previously, in order to access the schema in postTransform,
579+
// you could resolve the schema using the path.
580+
// Now, the schema is made available directly on the options.
581+
// const schema = options.path
582+
// ? options.ctx.resolve<ReferenceObject | SchemaObject>(options.path)
583+
// : undefined;
584+
const schema = options.schema;
585+
586+
if (
587+
schema &&
588+
!("$ref" in schema) &&
589+
Object.hasOwn(schema, "x-string-enum-to-set") &&
590+
schema.type === "string" &&
591+
schema.enum?.every((enumMember) => {
592+
return typeof enumMember === "string";
593+
})
594+
) {
595+
return ts.factory.createTypeReferenceNode(
596+
ts.factory.createIdentifier("Set"),
597+
[
598+
ts.factory.createUnionTypeNode(
599+
schema.enum.map((value) => {
600+
return ts.factory.createLiteralTypeNode(
601+
ts.factory.createStringLiteral(value)
602+
);
603+
})
604+
),
605+
]
606+
);
567607
}
568608
},
569609
},

0 commit comments

Comments
 (0)