-
-
Notifications
You must be signed in to change notification settings - Fork 528
Add questionToken option to transform #1417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import ts from "typescript"; | ||
import { | ||
NEVER, | ||
QUESTION_TOKEN, | ||
addJSDocComment, | ||
tsModifiers, | ||
tsPropertyIndex, | ||
|
@@ -9,6 +10,7 @@ import { createRef, debug, getEntries } from "../lib/utils.js"; | |
import { | ||
ComponentsObject, | ||
GlobalContext, | ||
SchemaObject, | ||
TransformNodeOptions, | ||
} from "../types.js"; | ||
import transformHeaderObject from "./header-object.js"; | ||
|
@@ -51,14 +53,31 @@ export default function transformComponentsObject( | |
const items: ts.TypeElement[] = []; | ||
if (componentsObject[key]) { | ||
for (const [name, item] of getEntries(componentsObject[key], ctx)) { | ||
const subType = transformers[key](item, { | ||
let subType = transformers[key](item, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup I think this will work in all cases I can think of. Just handling keys on |
||
path: createRef(["components", key, name]), | ||
ctx, | ||
}); | ||
|
||
let hasQuestionToken = false; | ||
if (ctx.transform) { | ||
const result = ctx.transform(item as SchemaObject, { | ||
path: createRef(["components", key, name]), | ||
ctx, | ||
}); | ||
if (result) { | ||
if ("schema" in result) { | ||
subType = result.schema; | ||
hasQuestionToken = result.questionToken; | ||
} else { | ||
subType = result; | ||
} | ||
} | ||
} | ||
|
||
const property = ts.factory.createPropertySignature( | ||
/* modifiers */ tsModifiers({ readonly: ctx.immutable }), | ||
/* name */ tsPropertyIndex(name), | ||
/* questionToken */ undefined, | ||
/* questionToken */ hasQuestionToken ? QUESTION_TOKEN : undefined, | ||
/* type */ subType, | ||
); | ||
addJSDocComment(item as unknown as any, property); // eslint-disable-line @typescript-eslint/no-explicit-any | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -467,6 +467,11 @@ export type SchemaObject = { | |
| {} | ||
); | ||
|
||
export interface TransformObject { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 This is great. We can probably extend this pretty far before having to change this API. |
||
schema: ts.TypeNode; | ||
questionToken: boolean; | ||
} | ||
|
||
export interface StringSubtype { | ||
type: "string" | ["string", "null"]; | ||
enum?: (string | ReferenceObject)[]; | ||
|
@@ -646,7 +651,7 @@ export interface OpenAPITSOptions { | |
transform?: ( | ||
schemaObject: SchemaObject, | ||
options: TransformNodeOptions, | ||
) => ts.TypeNode | undefined; | ||
) => ts.TypeNode | TransformObject | undefined; | ||
/** Modify TypeScript types built from Schema Objects */ | ||
postTransform?: ( | ||
type: ts.TypeNode, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,10 @@ import { TestCase } from "./test-helpers.js"; | |
|
||
const EXAMPLES_DIR = new URL("../examples/", import.meta.url); | ||
|
||
const DATE = ts.factory.createTypeReferenceNode( | ||
ts.factory.createIdentifier("Date"), | ||
); | ||
|
||
describe("Node.js API", () => { | ||
const tests: TestCase<any, OpenAPITSOptions>[] = [ | ||
[ | ||
|
@@ -382,9 +386,49 @@ export type operations = Record<string, never>;`, | |
* then use the `typescript` parser and it will tell you the desired | ||
* AST | ||
*/ | ||
return ts.factory.createTypeReferenceNode( | ||
ts.factory.createIdentifier("Date"), | ||
); | ||
return DATE; | ||
} | ||
}, | ||
}, | ||
}, | ||
], | ||
[ | ||
"options > transform with schema object", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💯 Fantastic tests! |
||
{ | ||
given: { | ||
openapi: "3.1", | ||
info: { title: "Test", version: "1.0" }, | ||
components: { | ||
schemas: { | ||
Date: { type: "string", format: "date-time" }, | ||
}, | ||
}, | ||
}, | ||
want: `export type paths = Record<string, never>; | ||
export type webhooks = Record<string, never>; | ||
export interface components { | ||
schemas: { | ||
/** Format: date-time */ | ||
Date?: Date; | ||
}; | ||
responses: never; | ||
parameters: never; | ||
requestBodies: never; | ||
headers: never; | ||
pathItems: never; | ||
} | ||
export type $defs = Record<string, never>; | ||
export type operations = Record<string, never>;`, | ||
options: { | ||
transform(schemaObject) { | ||
if ( | ||
"format" in schemaObject && | ||
schemaObject.format === "date-time" | ||
) { | ||
return { | ||
schema: DATE, | ||
questionToken: true, | ||
}; | ||
} | ||
}, | ||
}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 The docs look great! Thank you.