openapi-typescript
Version:
Convert OpenAPI 3.0 & 3.1 schemas to TypeScript
1 lines • 8.6 kB
Source Map (JSON)
{"version":3,"file":"components-object.cjs","sources":["../../src/transform/components-object.ts"],"sourcesContent":["import ts from \"typescript\";\nimport * as changeCase from \"change-case\";\nimport { performance } from \"node:perf_hooks\";\nimport { NEVER, QUESTION_TOKEN, addJSDocComment, tsModifiers, tsPropertyIndex } from \"../lib/ts.js\";\nimport { createRef, debug, getEntries } from \"../lib/utils.js\";\nimport type { ComponentsObject, GlobalContext, SchemaObject, TransformNodeOptions } from \"../types.js\";\nimport transformHeaderObject from \"./header-object.js\";\nimport transformParameterObject from \"./parameter-object.js\";\nimport transformPathItemObject from \"./path-item-object.js\";\nimport transformRequestBodyObject from \"./request-body-object.js\";\nimport transformResponseObject from \"./response-object.js\";\nimport transformSchemaObject from \"./schema-object.js\";\n\ntype ComponentTransforms = keyof Omit<ComponentsObject, \"examples\" | \"securitySchemes\" | \"links\" | \"callbacks\">;\n\nconst transformers: Record<ComponentTransforms, (node: any, options: TransformNodeOptions) => ts.TypeNode> = {\n schemas: transformSchemaObject,\n responses: transformResponseObject,\n parameters: transformParameterObject,\n requestBodies: transformRequestBodyObject,\n headers: transformHeaderObject,\n pathItems: transformPathItemObject,\n};\n\n/**\n * Transform the ComponentsObject (4.8.7)\n * @see https://spec.openapis.org/oas/latest.html#components-object\n */\nexport default function transformComponentsObject(componentsObject: ComponentsObject, ctx: GlobalContext): ts.Node[] {\n const type: ts.TypeElement[] = [];\n const rootTypeAliases: { [key: string]: ts.TypeAliasDeclaration } = {};\n for (const key of Object.keys(transformers) as ComponentTransforms[]) {\n const componentT = performance.now();\n\n const items: ts.TypeElement[] = [];\n if (componentsObject[key]) {\n for (const [name, item] of getEntries<SchemaObject>(componentsObject[key], ctx)) {\n let subType = transformers[key](item, {\n path: createRef([\"components\", key, name]),\n schema: item,\n ctx,\n });\n\n let hasQuestionToken = false;\n if (ctx.transform) {\n const result = ctx.transform(item, {\n path: createRef([\"components\", key, name]),\n schema: item,\n ctx,\n });\n if (result) {\n if (\"schema\" in result) {\n subType = result.schema;\n hasQuestionToken = result.questionToken;\n } else {\n subType = result;\n }\n }\n }\n\n const property = ts.factory.createPropertySignature(\n /* modifiers */ tsModifiers({ readonly: ctx.immutable }),\n /* name */ tsPropertyIndex(name),\n /* questionToken */ hasQuestionToken ? QUESTION_TOKEN : undefined,\n /* type */ subType,\n );\n addJSDocComment(item as unknown as any, property);\n items.push(property);\n\n if (ctx.rootTypes) {\n const componentKey = changeCase.pascalCase(singularizeComponentKey(key));\n let aliasName = `${componentKey}${changeCase.pascalCase(name)}`;\n\n // Add counter suffix (e.g. \"_2\") if conflict in name\n let conflictCounter = 1;\n\n while (rootTypeAliases[aliasName] !== undefined) {\n conflictCounter++;\n aliasName = `${componentKey}${changeCase.pascalCase(name)}_${conflictCounter}`;\n }\n const ref = ts.factory.createTypeReferenceNode(`components['${key}']['${name}']`);\n if (ctx.rootTypesNoSchemaPrefix && key === \"schemas\") {\n aliasName = aliasName.replace(componentKey, \"\");\n }\n const typeAlias = ts.factory.createTypeAliasDeclaration(\n /* modifiers */ tsModifiers({ export: true }),\n /* name */ aliasName,\n /* typeParameters */ undefined,\n /* type */ ref,\n );\n rootTypeAliases[aliasName] = typeAlias;\n }\n }\n }\n type.push(\n ts.factory.createPropertySignature(\n /* modifiers */ undefined,\n /* name */ tsPropertyIndex(key),\n /* questionToken */ undefined,\n /* type */ items.length ? ts.factory.createTypeLiteralNode(items) : NEVER,\n ),\n );\n\n debug(`Transformed components → ${key}`, \"ts\", performance.now() - componentT);\n }\n\n // Extract root types\n let rootTypes: ts.TypeAliasDeclaration[] = [];\n if (ctx.rootTypes) {\n rootTypes = Object.keys(rootTypeAliases).map((k) => rootTypeAliases[k]);\n }\n\n return [ts.factory.createTypeLiteralNode(type), ...rootTypes];\n}\n\nexport function singularizeComponentKey(\n key: `x-${string}` | \"schemas\" | \"responses\" | \"parameters\" | \"requestBodies\" | \"headers\" | \"pathItems\",\n): string {\n switch (key) {\n // Handle special singular case\n case \"requestBodies\":\n return \"requestBody\";\n // Default to removing the \"s\"\n default:\n return key.slice(0, -1);\n }\n}\n"],"names":["transformSchemaObject","transformResponseObject","transformParameterObject","transformRequestBodyObject","transformHeaderObject","transformPathItemObject","performance","getEntries","createRef","ts","tsModifiers","tsPropertyIndex","QUESTION_TOKEN","addJSDocComment","changeCase","NEVER","debug"],"mappings":"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"}