New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

openapi-typescript

Package Overview
Dependencies
Maintainers
1
Versions
145
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

openapi-typescript - npm Package Compare versions

Comparing version 7.0.0-next.9 to 7.0.0-next.10

biome.json

52

bin/cli.js

@@ -7,13 +7,4 @@ #!/usr/bin/env node

import parser from "yargs-parser";
import openapiTS, {
astToString,
c,
COMMENT_HEADER,
error,
formatTime,
warn,
} from "../dist/index.js";
import openapiTS, { astToString, c, COMMENT_HEADER, error, formatTime, warn } from "../dist/index.js";
/* eslint-disable no-console */
const HELP = `Usage

@@ -33,2 +24,4 @@ $ openapi-typescript [input] [options]

--default-non-nullable Set to \`false\` to ignore default values when generating non-nullable types
--properties-required-by-default
Treat schema objects as if \`required\` is set to all properties by default
--array-length Generate tuples using array minItems / maxItems

@@ -49,5 +42,3 @@ --path-params-as-types Convert paths to template literal types

if (args.includes("-ap")) {
errorAndExit(
`The -ap alias has been deprecated. Use "--additional-properties" instead.`,
);
errorAndExit(`The -ap alias has been deprecated. Use "--additional-properties" instead.`);
}

@@ -58,10 +49,6 @@ if (args.includes("--immutable-types")) {

if (args.includes("--support-array-length")) {
errorAndExit(
`The --support-array-length flag has been renamed to "--array-length".`,
);
errorAndExit(`The --support-array-length flag has been renamed to "--array-length".`);
}
if (args.includes("-it")) {
errorAndExit(
`The -it alias has been deprecated. Use "--immutable-types" instead.`,
);
errorAndExit(`The -it alias has been deprecated. Use "--immutable-types" instead.`);
}

@@ -76,2 +63,3 @@

"defaultNonNullable",
"propertiesRequiredByDefault",
"emptyObjectsUnknown",

@@ -104,2 +92,3 @@ "enum",

contentNever: flags.contentNever,
propertiesRequired: flags.propertiesRequired,
defaultNonNullable: flags.defaultNonNullable,

@@ -126,7 +115,4 @@ emptyObjectsUnknown: flags.emptyObjectsUnknown,

// final console output
console.log(
`🚀 ${c.green(`${input} → ${c.bold(output)}`)} ${c.dim(
`[${formatTime(time)}]`,
)}`,
);
// biome-ignore lint/suspicious/noConsoleLog: this is a CLI and is expected to show output
console.log(`🚀 ${c.green(`${input} → ${c.bold(output)}`)} ${c.dim(`[${formatTime(time)}]`)}`);
}

@@ -139,5 +125,3 @@

}
const packageJSON = JSON.parse(
fs.readFileSync(new URL("../package.json", import.meta.url), "utf8"),
);
const packageJSON = JSON.parse(fs.readFileSync(new URL("../package.json", import.meta.url), "utf8"));
if ("version" in flags) {

@@ -156,5 +140,3 @@ console.info(`v${packageJSON.version}`);

// load Redocly config
const maybeRedoc = findConfig(
flags.redoc ? path.dirname(flags.redoc) : undefined,
);
const maybeRedoc = findConfig(flags.redoc ? path.dirname(flags.redoc) : undefined);
const redoc = maybeRedoc

@@ -168,5 +150,3 @@ ? await loadConfig({ configPath: maybeRedoc })

if (input) {
warn(
"APIs are specified both in Redocly Config and CLI argument. Only using Redocly config.",
);
warn("APIs are specified both in Redocly Config and CLI argument. Only using Redocly config.");
}

@@ -185,5 +165,3 @@ await Promise.all(

if (api["openapi-ts"]) {
errorAndExit(
`Please rename "openapi-ts" to "x-openapi-ts" in your Redoc config.`,
);
errorAndExit(`Please rename "openapi-ts" to "x-openapi-ts" in your Redoc config.`);
}

@@ -228,3 +206,3 @@

errorAndExit(
`Globbing has been deprecated in favor of redocly.yaml’s \`apis\` keys. See https://openapi-ts.pages.dev/cli/#multiple-schemas`,
"Globbing has been deprecated in favor of redocly.yaml’s `apis` keys. See https://openapi-ts.pages.dev/cli/#multiple-schemas",
);

@@ -231,0 +209,0 @@ }

@@ -122,3 +122,3 @@ # Contributing

To run ESLint on the project:
Linting is handled via [Biome](https://biomejs.dev), a faster ESLint replacement. It was installed with `pnpm i` and can be run with:

@@ -125,0 +125,0 @@ ```bash

@@ -38,5 +38,3 @@ import { createConfig } from "@redocly/openapi-core";

redoc,
cwd: options.cwd instanceof URL
? options.cwd
: new URL(`file://${options.cwd ?? process.cwd()}/`),
cwd: options.cwd instanceof URL ? options.cwd : new URL(`file://${options.cwd ?? process.cwd()}/`),
silent: options.silent ?? false,

@@ -47,2 +45,3 @@ });

alphabetize: options.alphabetize ?? false,
arrayLength: options.arrayLength ?? false,
defaultNonNullable: options.defaultNonNullable ?? true,

@@ -57,8 +56,6 @@ discriminators: scanDiscriminators(schema, options),

pathParamsAsTypes: options.pathParamsAsTypes ?? false,
postTransform: typeof options.postTransform === "function"
? options.postTransform
: undefined,
postTransform: typeof options.postTransform === "function" ? options.postTransform : undefined,
propertiesRequiredByDefault: options.propertiesRequiredByDefault ?? false,
redoc,
silent: options.silent ?? false,
arrayLength: options.arrayLength ?? false,
transform: typeof options.transform === "function" ? options.transform : undefined,

@@ -65,0 +62,0 @@ resolve($ref) {

@@ -7,3 +7,3 @@ import { BaseResolver, bundle, makeDocumentFromString, Source, lintDocument, } from "@redocly/openapi-core";

if (!schema) {
throw new Error(`Can’t parse empty schema`);
throw new Error("Can’t parse empty schema");
}

@@ -35,5 +35,3 @@ if (schema instanceof URL) {

if (typeof schema === "string") {
if (schema.startsWith("http://") ||
schema.startsWith("https://") ||
schema.startsWith("file://")) {
if (schema.startsWith("http://") || schema.startsWith("https://") || schema.startsWith("file://")) {
const url = new URL(schema);

@@ -67,4 +65,3 @@ return parseSchema(url, {

if (source instanceof URL) {
absoluteRef =
source.protocol === "file:" ? fileURLToPath(source) : source.href;
absoluteRef = source.protocol === "file:" ? fileURLToPath(source) : source.href;
}

@@ -77,3 +74,3 @@ const resolver = new BaseResolver(options.redoc.resolve);

debug("Parsed schema", "redoc", performance.now() - redocParseT);
const openapiVersion = parseFloat(document.parsed.openapi);
const openapiVersion = Number.parseFloat(document.parsed.openapi);
if (document.parsed.swagger ||

@@ -87,5 +84,3 @@ !document.parsed.openapi ||

}
else if (document.parsed.openapi ||
openapiVersion < 3 ||
openapiVersion >= 4) {
if (document.parsed.openapi || openapiVersion < 3 || openapiVersion >= 4) {
throw new Error(`Unsupported OpenAPI version: ${document.parsed.openapi}`);

@@ -92,0 +87,0 @@ }

@@ -19,5 +19,3 @@ import { parseRef } from "@redocly/openapi-core/lib/ref-utils.js";

export function addJSDocComment(schemaObject, node) {
if (!schemaObject ||
typeof schemaObject !== "object" ||
Array.isArray(schemaObject)) {
if (!schemaObject || typeof schemaObject !== "object" || Array.isArray(schemaObject)) {
return;

@@ -47,5 +45,3 @@ }

}
const serialized = typeof schemaObject[field] === "object"
? JSON.stringify(schemaObject[field], null, 2)
: schemaObject[field];
const serialized = typeof schemaObject[field] === "object" ? JSON.stringify(schemaObject[field], null, 2) : schemaObject[field];
output.push(`@${field} ${String(serialized).replace(LB_RE, "\n * ")}`);

@@ -64,3 +60,3 @@ }

}
output.push(`@enum {${type}${schemaObject.nullable ? `|null` : ""}}`);
output.push(`@enum {${type}${schemaObject.nullable ? "|null" : ""}}`);
}

@@ -124,5 +120,3 @@ if (output.length) {

const last = c[c.length - 1];
return JS_PROPERTY_INDEX_INVALID_CHARS_RE.test(last)
? ""
: last.toUpperCase();
return JS_PROPERTY_INDEX_INVALID_CHARS_RE.test(last) ? "" : last.toUpperCase();
});

@@ -133,5 +127,3 @@ if (Number(name[0]) >= 0) {

enumName = `${enumName[0].toUpperCase()}${enumName.substring(1)}`;
return ts.factory.createEnumDeclaration(options
? tsModifiers({ export: options.export ?? false })
: undefined, enumName, members.map((value, i) => tsEnumMember(value, metadata?.[i])));
return ts.factory.createEnumDeclaration(options ? tsModifiers({ export: options.export ?? false }) : undefined, enumName, members.map((value, i) => tsEnumMember(value, metadata?.[i])));
}

@@ -159,3 +151,3 @@ export function tsEnumMember(value, metadata = {}) {

}
if (metadata.description == undefined) {
if (metadata.description === undefined) {
return member;

@@ -210,5 +202,3 @@ }

}
return keys.length
? ts.factory.createTypeLiteralNode(keys)
: tsRecord(STRING, NEVER);
return keys.length ? ts.factory.createTypeLiteralNode(keys) : tsRecord(STRING, NEVER);
}

@@ -231,3 +221,6 @@ return UNKNOWN;

export function tsOmit(type, keys) {
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Omit"), [type, ts.factory.createUnionTypeNode(keys.map((k) => tsLiteral(k)))]);
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Omit"), [
type,
ts.factory.createUnionTypeNode(keys.map((k) => tsLiteral(k))),
]);
}

@@ -239,5 +232,3 @@ export function tsRecord(key, value) {

if ((typeof index === "number" && !(index < 0)) ||
(typeof index === "string" &&
String(Number(index)) === index &&
index[0] !== "-")) {
(typeof index === "string" && String(Number(index)) === index && index[0] !== "-")) {
return ts.factory.createNumericLiteral(index);

@@ -262,9 +253,11 @@ }

}
if (!injectFooter.some((node) => ts.isTypeAliasDeclaration(node) &&
node?.name?.escapedText === "WithRequired")) {
const helper = stringToAST(`type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };`)[0];
if (!injectFooter.some((node) => ts.isTypeAliasDeclaration(node) && node?.name?.escapedText === "WithRequired")) {
const helper = stringToAST("type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };")[0];
injectFooter.push(helper);
}
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("WithRequired"), [type, tsUnion(keys.map((k) => tsLiteral(k)))]);
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("WithRequired"), [
type,
tsUnion(keys.map((k) => tsLiteral(k))),
]);
}
//# sourceMappingURL=ts.js.map

@@ -9,3 +9,3 @@ import c from "ansi-colors";

}): ts.TypeElement;
export declare function createRef(parts: (number | string)[]): string;
export declare function createRef(parts: (number | string | undefined | null)[]): string;
export declare function debug(msg: string, group?: string, time?: number): void;

@@ -12,0 +12,0 @@ export declare function error(msg: string): void;

@@ -1,2 +0,2 @@

import { escapePointer, parseRef, } from "@redocly/openapi-core/lib/ref-utils.js";
import { escapePointer, parseRef } from "@redocly/openapi-core/lib/ref-utils.js";
import c from "ansi-colors";

@@ -19,4 +19,3 @@ import supportsColor from "supports-color";

if (discriminator.mapping) {
const matchedValue = Object.entries(discriminator.mapping).find(([, v]) => (!v.startsWith("#") && v === value) ||
(v.startsWith("#") && parseRef(v).pointer.pop() === value));
const matchedValue = Object.entries(discriminator.mapping).find(([, v]) => (!v.startsWith("#") && v === value) || (v.startsWith("#") && parseRef(v).pointer.pop() === value));
if (matchedValue) {

@@ -33,3 +32,3 @@ value = matchedValue[0];

for (const part of parts) {
if (!part) {
if (part === undefined || part === null || part === "") {
continue;

@@ -54,4 +53,3 @@ }

process.env.DEBUG === "openapi-ts:*" ||
process.env.DEBUG.toLocaleLowerCase() ===
`openapi-ts:${group.toLocaleLowerCase()}`)) {
process.env.DEBUG.toLocaleLowerCase() === `openapi-ts:${group.toLocaleLowerCase()}`)) {
const groupColor = (group && DEBUG_GROUPS[group]) || c.whiteBright;

@@ -74,3 +72,3 @@ const groupName = groupColor(`openapi-ts:${group ?? "info"}`);

}
else if (t < 60000) {
if (t < 60000) {
return `${Math.round(t / 100) / 10}s`;

@@ -125,3 +123,3 @@ }

? `${prevSchema.description} (enum property replaced by openapi-typescript)`
: `discriminator enum property added by openapi-typescript`,
: "discriminator enum property added by openapi-typescript",
};

@@ -143,5 +141,3 @@ }

}
else if (typeof resolvedSchema === "object" &&
"type" in resolvedSchema &&
resolvedSchema.type === "object") {
else if (typeof resolvedSchema === "object" && "type" in resolvedSchema && resolvedSchema.type === "object") {
if (!resolvedSchema.properties) {

@@ -156,4 +152,3 @@ resolvedSchema.properties = {};

}
resolvedSchema.properties[discriminator.propertyName] =
createDiscriminatorEnum(values, resolvedSchema.properties[discriminator.propertyName]);
resolvedSchema.properties[discriminator.propertyName] = createDiscriminatorEnum(values, resolvedSchema.properties[discriminator.propertyName]);
return true;

@@ -160,0 +155,0 @@ }

import ts from "typescript";
import { NEVER, QUESTION_TOKEN, addJSDocComment, tsModifiers, tsPropertyIndex, } from "../lib/ts.js";
import { NEVER, QUESTION_TOKEN, addJSDocComment, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef, debug, getEntries } from "../lib/utils.js";

@@ -50,5 +50,3 @@ import transformHeaderObject from "./header-object.js";

}
type.push(ts.factory.createPropertySignature(undefined, tsPropertyIndex(key), undefined, items.length
? ts.factory.createTypeLiteralNode(items)
: NEVER));
type.push(ts.factory.createPropertySignature(undefined, tsPropertyIndex(key), undefined, items.length ? ts.factory.createTypeLiteralNode(items) : NEVER));
debug(`Transformed components → ${key}`, "ts", performance.now() - componentT);

@@ -55,0 +53,0 @@ }

import { escapePointer } from "@redocly/openapi-core/lib/ref-utils.js";
import ts from "typescript";
import { addJSDocComment, tsModifiers, tsPropertyIndex, UNKNOWN, } from "../lib/ts.js";
import { addJSDocComment, tsModifiers, tsPropertyIndex, UNKNOWN } from "../lib/ts.js";
import { getEntries } from "../lib/utils.js";

@@ -5,0 +5,0 @@ import transformMediaTypeObject from "./media-type-object.js";

@@ -39,4 +39,3 @@ import ts from "typescript";

for (const injectedType of ctx.injectFooter) {
if (!hasOperations &&
injectedType?.name?.escapedText === "operations") {
if (!hasOperations && injectedType?.name?.escapedText === "operations") {
hasOperations = true;

@@ -43,0 +42,0 @@ }

import ts from "typescript";
import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex, } from "../lib/ts.js";
import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef } from "../lib/utils.js";

@@ -31,4 +31,3 @@ import { transformParametersArray } from "./parameters-array.js";

export function injectOperationObject(operationId, operationObject, options) {
let operations = options.ctx.injectFooter.find((node) => ts.isInterfaceDeclaration(node) &&
node.name.text === "operations");
let operations = options.ctx.injectFooter.find((node) => ts.isInterfaceDeclaration(node) && node.name.text === "operations");
if (!operations) {

@@ -35,0 +34,0 @@ operations = ts.factory.createInterfaceDeclaration(tsModifiers({

import { STRING } from "../lib/ts.js";
import transformSchemaObject from "./schema-object.js";
export default function transformParameterObject(parameterObject, options) {
return parameterObject.schema
? transformSchemaObject(parameterObject.schema, options)
: STRING;
return parameterObject.schema ? transformSchemaObject(parameterObject.schema, options) : STRING;
}
//# sourceMappingURL=parameter-object.js.map
import ts from "typescript";
import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex, } from "../lib/ts.js";
import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef } from "../lib/utils.js";

@@ -8,14 +8,7 @@ import transformParameterObject from "./parameter-object.js";

const paramType = [];
for (const paramIn of [
"query",
"header",
"path",
"cookie",
]) {
for (const paramIn of ["query", "header", "path", "cookie"]) {
const paramLocType = [];
let operationParameters = parametersArray.map((param) => ({
original: param,
resolved: "$ref" in param
? options.ctx.resolve(param.$ref)
: param,
resolved: "$ref" in param ? options.ctx.resolve(param.$ref) : param,
}));

@@ -40,8 +33,3 @@ if (options.ctx.alphabetize) {

...options,
path: createRef([
options.path ?? "",
"parameters",
resolved.in,
resolved.name,
]),
path: createRef([options.path, "parameters", resolved.in, resolved.name]),
});

@@ -53,13 +41,7 @@ const property = ts.factory.createPropertySignature(tsModifiers({ readonly: options.ctx.immutable }), tsPropertyIndex(resolved?.name), optional, subType);

const allOptional = paramLocType.every((node) => !!node.questionToken);
paramType.push(ts.factory.createPropertySignature(tsModifiers({ readonly: options.ctx.immutable }), tsPropertyIndex(paramIn), allOptional || !paramLocType.length
? QUESTION_TOKEN
: undefined, paramLocType.length
? ts.factory.createTypeLiteralNode(paramLocType)
: NEVER));
paramType.push(ts.factory.createPropertySignature(tsModifiers({ readonly: options.ctx.immutable }), tsPropertyIndex(paramIn), allOptional || !paramLocType.length ? QUESTION_TOKEN : undefined, paramLocType.length ? ts.factory.createTypeLiteralNode(paramLocType) : NEVER));
}
type.push(ts.factory.createPropertySignature(tsModifiers({ readonly: options.ctx.immutable }), tsPropertyIndex("parameters"), !paramType.length ? QUESTION_TOKEN : undefined, paramType.length
? ts.factory.createTypeLiteralNode(paramType)
: NEVER));
type.push(ts.factory.createPropertySignature(tsModifiers({ readonly: options.ctx.immutable }), tsPropertyIndex("parameters"), !paramType.length ? QUESTION_TOKEN : undefined, paramType.length ? ts.factory.createTypeLiteralNode(paramType) : NEVER));
return type;
}
//# sourceMappingURL=parameters-array.js.map
import ts from "typescript";
import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex, } from "../lib/ts.js";
import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef } from "../lib/utils.js";
import transformOperationObject, { injectOperationObject, } from "./operation-object.js";
import transformOperationObject, { injectOperationObject } from "./operation-object.js";
import { transformParametersArray } from "./parameters-array.js";

@@ -12,18 +12,8 @@ export default function transformPathItemObject(pathItem, options) {

}));
for (const method of [
"get",
"put",
"post",
"delete",
"options",
"head",
"patch",
"trace",
]) {
for (const method of ["get", "put", "post", "delete", "options", "head", "patch", "trace"]) {
const operationObject = pathItem[method];
if (!operationObject ||
(options.ctx.excludeDeprecated &&
("$ref" in operationObject
? options.ctx.resolve(operationObject.$ref)
: operationObject)?.deprecated)) {
("$ref" in operationObject ? options.ctx.resolve(operationObject.$ref) : operationObject)
?.deprecated)) {
type.push(ts.factory.createPropertySignature(tsModifiers({ readonly: options.ctx.immutable }), tsPropertyIndex(method), QUESTION_TOKEN, NEVER));

@@ -34,9 +24,4 @@ continue;

if (!("$ref" in operationObject)) {
for (const parameter of [
...(pathItem.parameters ?? []),
...(operationObject.parameters ?? []),
]) {
const name = "$ref" in parameter
? options.ctx.resolve(parameter.$ref)?.name
: parameter.name;
for (const parameter of [...(pathItem.parameters ?? []), ...(operationObject.parameters ?? [])]) {
const name = "$ref" in parameter ? options.ctx.resolve(parameter.$ref)?.name : parameter.name;
if (name) {

@@ -43,0 +28,0 @@ keyedParameters[name] = parameter;

import ts from "typescript";
import { addJSDocComment, oapiRef, stringToAST, tsModifiers, tsPropertyIndex, } from "../lib/ts.js";
import { addJSDocComment, oapiRef, stringToAST, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef, debug, getEntries } from "../lib/utils.js";

@@ -55,5 +55,3 @@ import transformPathItemObject from "./path-item-object.js";

for (const p of pathItemObject.parameters ?? []) {
const resolved = "$ref" in p && p.$ref
? ctx.resolve(p.$ref)
: p;
const resolved = "$ref" in p && p.$ref ? ctx.resolve(p.$ref) : p;
if (resolved && resolved.in === "path") {

@@ -63,12 +61,3 @@ params[resolved.name] = resolved;

}
for (const method of [
"get",
"put",
"post",
"delete",
"options",
"head",
"patch",
"trace",
]) {
for (const method of ["get", "put", "post", "delete", "options", "head", "patch", "trace"]) {
if (!(method in pathItemObject)) {

@@ -82,5 +71,3 @@ continue;

for (const p of resolvedMethod.parameters) {
const resolvedParam = "$ref" in p && p.$ref
? ctx.resolve(p.$ref)
: p;
const resolvedParam = "$ref" in p && p.$ref ? ctx.resolve(p.$ref) : p;
if (resolvedParam && resolvedParam.in === "path") {

@@ -87,0 +74,0 @@ params[resolvedParam.name] = resolvedParam;

import ts from "typescript";
import { NEVER, QUESTION_TOKEN, addJSDocComment, tsModifiers, tsPropertyIndex, } from "../lib/ts.js";
import { NEVER, QUESTION_TOKEN, addJSDocComment, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef, getEntries } from "../lib/utils.js";

@@ -4,0 +4,0 @@ import transformMediaTypeObject from "./media-type-object.js";

@@ -11,5 +11,3 @@ import ts from "typescript";

for (const [name, headerObject] of getEntries(responseObject.headers, options.ctx)) {
const optional = "$ref" in headerObject || headerObject.required
? undefined
: QUESTION_TOKEN;
const optional = "$ref" in headerObject || headerObject.required ? undefined : QUESTION_TOKEN;
const subType = "$ref" in headerObject

@@ -19,3 +17,3 @@ ? oapiRef(headerObject.$ref)

...options,
path: createRef([options.path ?? "", "headers", name]),
path: createRef([options.path, "headers", name]),
});

@@ -36,3 +34,3 @@ const property = ts.factory.createPropertySignature(tsModifiers({ readonly: options.ctx.immutable }), tsPropertyIndex(name), optional, subType);

...options,
path: createRef([options.path ?? "", "content", contentType]),
path: createRef([options.path, "content", contentType]),
}));

@@ -39,0 +37,0 @@ contentObject.push(property);

import ts from "typescript";
import { NEVER, addJSDocComment, tsModifiers, oapiRef, tsPropertyIndex, } from "../lib/ts.js";
import { NEVER, addJSDocComment, tsModifiers, oapiRef, tsPropertyIndex } from "../lib/ts.js";
import { createRef, getEntries } from "../lib/utils.js";

@@ -12,3 +12,3 @@ import transformResponseObject from "./response-object.js";

...options,
path: createRef([options.path ?? "", "responses", responseCode]),
path: createRef([options.path, "responses", responseCode]),
});

@@ -15,0 +15,0 @@ const property = ts.factory.createPropertySignature(tsModifiers({ readonly: options.ctx.immutable }), tsPropertyIndex(responseCode), undefined, responseType);

import { parseRef } from "@redocly/openapi-core/lib/ref-utils.js";
import ts from "typescript";
import { BOOLEAN, NEVER, NULL, NUMBER, QUESTION_TOKEN, STRING, UNDEFINED, UNKNOWN, addJSDocComment, oapiRef, tsEnum, tsIntersection, tsIsPrimitive, tsLiteral, tsModifiers, tsNullable, tsOmit, tsPropertyIndex, tsRecord, tsUnion, tsWithRequired, } from "../lib/ts.js";
import { createDiscriminatorProperty, createRef, getEntries, } from "../lib/utils.js";
import { createDiscriminatorProperty, createRef, getEntries } from "../lib/utils.js";
export default function transformSchemaObject(schemaObject, options) {

@@ -35,11 +35,8 @@ const type = transformSchemaObjectWithComposition(schemaObject, options);

!("additionalProperties" in schemaObject)) {
if (options.ctx.enum &&
schemaObject.enum.every((v) => typeof v === "string" || typeof v === "number")) {
if (options.ctx.enum && schemaObject.enum.every((v) => typeof v === "string" || typeof v === "number")) {
let enumName = parseRef(options.path ?? "").pointer.join("/");
enumName = enumName.replace("components/schemas", "");
const metadata = schemaObject.enum.map((_, i) => ({
name: schemaObject["x-enum-varnames"]?.[i] ??
schemaObject["x-enumNames"]?.[i],
description: schemaObject["x-enum-descriptions"]?.[i] ??
schemaObject["x-enumDescriptions"]?.[i],
name: schemaObject["x-enum-varnames"]?.[i] ?? schemaObject["x-enumNames"]?.[i],
description: schemaObject["x-enum-descriptions"]?.[i] ?? schemaObject["x-enumDescriptions"]?.[i],
}));

@@ -72,3 +69,3 @@ const enumType = tsEnum(enumName, schemaObject.enum, metadata, {

!options.ctx.discriminators.refsHandled.includes(item.$ref)) {
const validRequired = (required ?? []).filter((key) => !!resolved.properties[key]);
const validRequired = (required ?? []).filter((key) => !!resolved.properties?.[key]);
if (validRequired.length) {

@@ -86,4 +83,3 @@ itemType = tsWithRequired(itemType, validRequired, options.ctx.injectFooter);

}
const discriminator = ("$ref" in item && options.ctx.discriminators.objects[item.$ref]) ||
item.discriminator;
const discriminator = ("$ref" in item && options.ctx.discriminators.objects[item.$ref]) || item.discriminator;
if (discriminator) {

@@ -102,9 +98,4 @@ output.push(tsOmit(itemType, [discriminator.propertyName]));

if (coreObjectType || allOfType.length) {
const allOf = allOfType.length
? tsIntersection(allOfType)
: undefined;
finalType = tsIntersection([
...(coreObjectType ? [coreObjectType] : []),
...(allOf ? [allOf] : []),
]);
const allOf = allOfType.length ? tsIntersection(allOfType) : undefined;
finalType = tsIntersection([...(coreObjectType ? [coreObjectType] : []), ...(allOf ? [allOf] : [])]);
}

@@ -125,6 +116,3 @@ const anyOfType = collectUnionCompositions(schemaObject.anyOf ?? []);

else {
finalType = tsIntersection([
...(finalType ? [finalType] : []),
tsUnion(oneOfType),
]);
finalType = tsIntersection([...(finalType ? [finalType] : []), tsUnion(oneOfType)]);
}

@@ -147,2 +135,18 @@ }

if ("type" in schemaObject && schemaObject.type) {
if (typeof options.ctx.transform === "function") {
const result = options.ctx.transform(schemaObject, options);
if (result) {
if ("schema" in result) {
if (result.questionToken) {
return ts.factory.createUnionTypeNode([result.schema, UNDEFINED]);
}
else {
return result.schema;
}
}
else {
return result;
}
}
}
if (schemaObject.type === "null") {

@@ -163,9 +167,7 @@ return NULL;

if (schemaObject.prefixItems || Array.isArray(schemaObject.items)) {
const prefixItems = schemaObject.prefixItems ??
schemaObject.items;
const prefixItems = schemaObject.prefixItems ?? schemaObject.items;
itemType = ts.factory.createTupleTypeNode(prefixItems.map((item) => transformSchemaObject(item, options)));
}
else if (schemaObject.items) {
if ("type" in schemaObject.items &&
schemaObject.items.type === "array") {
if ("type" in schemaObject.items && schemaObject.items.type === "array") {
itemType = ts.factory.createArrayTypeNode(transformSchemaObject(schemaObject.items, options));

@@ -177,8 +179,4 @@ }

}
const min = typeof schemaObject.minItems === "number" && schemaObject.minItems >= 0
? schemaObject.minItems
: 0;
const max = typeof schemaObject.maxItems === "number" &&
schemaObject.maxItems >= 0 &&
min <= schemaObject.maxItems
const min = typeof schemaObject.minItems === "number" && schemaObject.minItems >= 0 ? schemaObject.minItems : 0;
const max = typeof schemaObject.maxItems === "number" && schemaObject.maxItems >= 0 && min <= schemaObject.maxItems
? schemaObject.maxItems

@@ -218,7 +216,3 @@ : undefined;

for (const t of schemaObject.type) {
if ((t === "boolean" ||
t === "string" ||
t === "number" ||
t === "integer" ||
t === "null") &&
if ((t === "boolean" || t === "string" || t === "number" || t === "integer" || t === "null") &&
schemaObject.oneOf.find((o) => typeof o === "object" && "type" in o && o.type === t)) {

@@ -246,7 +240,7 @@ continue;

const discriminator = !schemaObject.discriminator &&
!options.ctx.discriminators.refsHandled.includes(options.path) &&
options.ctx.discriminators.objects[options.path];
!options.ctx.discriminators.refsHandled.includes(options.path ?? "") &&
options.ctx.discriminators.objects[options.path ?? ""];
if (discriminator) {
coreObjectType.unshift(createDiscriminatorProperty(discriminator, {
path: options.path,
path: options.path ?? "",
readonly: options.ctx.immutable,

@@ -257,7 +251,4 @@ }));

}
if (("properties" in schemaObject &&
schemaObject.properties &&
Object.keys(schemaObject.properties).length) ||
("additionalProperties" in schemaObject &&
schemaObject.additionalProperties) ||
if (("properties" in schemaObject && schemaObject.properties && Object.keys(schemaObject.properties).length) ||
("additionalProperties" in schemaObject && schemaObject.additionalProperties) ||
("$defs" in schemaObject && schemaObject.$defs)) {

@@ -276,5 +267,4 @@ if (Object.keys(schemaObject.properties ?? {}).length) {

let optional = schemaObject.required?.includes(k) ||
("default" in v &&
options.ctx.defaultNonNullable &&
!options.path?.includes("parameters"))
(schemaObject.required === undefined && options.ctx.propertiesRequiredByDefault) ||
("default" in v && options.ctx.defaultNonNullable && !options.path?.includes("parameters"))
? undefined

@@ -286,3 +276,3 @@ : QUESTION_TOKEN;

...options,
path: createRef([options.path ?? "", k]),
path: createRef([options.path, k]),
});

@@ -308,5 +298,3 @@ if (typeof options.ctx.transform === "function") {

}
if (schemaObject.$defs &&
typeof schemaObject.$defs === "object" &&
Object.keys(schemaObject.$defs).length) {
if (schemaObject.$defs && typeof schemaObject.$defs === "object" && Object.keys(schemaObject.$defs).length) {
const defKeys = [];

@@ -318,3 +306,3 @@ for (const [k, v] of Object.entries(schemaObject.$defs)) {

...options,
path: createRef([options.path ?? "", "$defs", k]),
path: createRef([options.path, "$defs", k]),
}));

@@ -327,4 +315,3 @@ addJSDocComment(v, property);

if (schemaObject.additionalProperties || options.ctx.additionalProperties) {
const hasExplicitAdditionalProperties = typeof schemaObject.additionalProperties === "object" &&
Object.keys(schemaObject.additionalProperties).length;
const hasExplicitAdditionalProperties = typeof schemaObject.additionalProperties === "object" && Object.keys(schemaObject.additionalProperties).length;
let addlType = hasExplicitAdditionalProperties

@@ -343,6 +330,4 @@ ? transformSchemaObject(schemaObject.additionalProperties, options)

}
return coreObjectType.length
? ts.factory.createTypeLiteralNode(coreObjectType)
: undefined;
return coreObjectType.length ? ts.factory.createTypeLiteralNode(coreObjectType) : undefined;
}
//# sourceMappingURL=schema-object.js.map

@@ -215,3 +215,3 @@ /// <reference types="node" />

type: ("string" | "number" | "integer" | "array" | "boolean" | "null" | "object")[];
} | {});
});
export interface TransformObject {

@@ -314,5 +314,7 @@ schema: ts.TypeNode;

alphabetize?: boolean;
arrayLength?: boolean;
emptyObjectsUnknown?: boolean;
cwd?: PathLike;
defaultNonNullable?: boolean;
excludeDeprecated?: boolean;
transform?: (schemaObject: SchemaObject, options: TransformNodeOptions) => ts.TypeNode | TransformObject | undefined;

@@ -325,5 +327,4 @@ postTransform?: (type: ts.TypeNode, options: TransformNodeOptions) => ts.TypeNode | undefined;

enum?: boolean;
arrayLength?: boolean;
pathParamsAsTypes?: boolean;
excludeDeprecated?: boolean;
propertiesRequiredByDefault?: boolean;
redocly?: RedoclyConfig;

@@ -334,2 +335,3 @@ }

alphabetize: boolean;
arrayLength: boolean;
defaultNonNullable: boolean;

@@ -348,5 +350,5 @@ discriminators: {

postTransform: OpenAPITSOptions["postTransform"];
propertiesRequiredByDefault: boolean;
redoc: RedoclyConfig;
silent: boolean;
arrayLength: boolean;
transform: OpenAPITSOptions["transform"];

@@ -353,0 +355,0 @@ resolve<T>($ref: string): T | undefined;

{
"name": "openapi-typescript",
"description": "Convert OpenAPI 3.0 & 3.1 schemas to TypeScript",
"version": "7.0.0-next.9",
"version": "7.0.0-next.10",
"author": {

@@ -49,6 +49,4 @@ "name": "Drew Powers",

"download:schemas": "vite-node ./scripts/download-schemas.ts",
"format": "prettier --write \"src/**/*\"",
"lint": "pnpm run \"/^lint:/\"",
"lint:js": "eslint \"{src,test}/**/*.{js,ts}\"",
"lint:prettier": "prettier --check \"src/**/*\"",
"format": "biome format . --write",
"lint": "biome check .",
"test": "pnpm run \"/^test:/\"",

@@ -55,0 +53,0 @@ "test:examples": "tsc -p tsconfig.examples.json --noEmit",

@@ -45,5 +45,3 @@ import { createConfig } from "@redocly/openapi-core";

if (!source) {
throw new Error(
"Empty schema. Please specify a URL, file path, or Redocly Config",
);
throw new Error("Empty schema. Please specify a URL, file path, or Redocly Config");
}

@@ -64,6 +62,3 @@

redoc,
cwd:
options.cwd instanceof URL
? options.cwd
: new URL(`file://${options.cwd ?? process.cwd()}/`),
cwd: options.cwd instanceof URL ? options.cwd : new URL(`file://${options.cwd ?? process.cwd()}/`),
silent: options.silent ?? false,

@@ -75,2 +70,3 @@ });

alphabetize: options.alphabetize ?? false,
arrayLength: options.arrayLength ?? false,
defaultNonNullable: options.defaultNonNullable ?? true,

@@ -85,11 +81,7 @@ discriminators: scanDiscriminators(schema, options),

pathParamsAsTypes: options.pathParamsAsTypes ?? false,
postTransform:
typeof options.postTransform === "function"
? options.postTransform
: undefined,
postTransform: typeof options.postTransform === "function" ? options.postTransform : undefined,
propertiesRequiredByDefault: options.propertiesRequiredByDefault ?? false,
redoc,
silent: options.silent ?? false,
arrayLength: options.arrayLength ?? false,
transform:
typeof options.transform === "function" ? options.transform : undefined,
transform: typeof options.transform === "function" ? options.transform : undefined,
resolve($ref) {

@@ -102,9 +94,5 @@ return resolveRef(schema, $ref, { silent: options.silent ?? false });

const result = transformSchema(schema, ctx);
debug(
"Completed AST transformation for entire document",
"ts",
performance.now() - transformT,
);
debug("Completed AST transformation for entire document", "ts", performance.now() - transformT);
return result;
}

@@ -26,8 +26,5 @@ import {

export async function parseSchema(
schema: unknown,
{ absoluteRef, resolver }: ParseSchemaOptions,
): Promise<Document> {
export async function parseSchema(schema: unknown, { absoluteRef, resolver }: ParseSchemaOptions): Promise<Document> {
if (!schema) {
throw new Error(`Can’t parse empty schema`);
throw new Error("Can’t parse empty schema");
}

@@ -60,7 +57,3 @@ if (schema instanceof URL) {

// URL
if (
schema.startsWith("http://") ||
schema.startsWith("https://") ||
schema.startsWith("file://")
) {
if (schema.startsWith("http://") || schema.startsWith("https://") || schema.startsWith("file://")) {
const url = new URL(schema);

@@ -84,15 +77,7 @@ return parseSchema(url, {

return {
source: new Source(
absoluteRef,
JSON.stringify(schema),
"application/json",
),
source: new Source(absoluteRef, JSON.stringify(schema), "application/json"),
parsed: schema,
};
}
throw new Error(
`Expected string, object, or Buffer. Got ${
Array.isArray(schema) ? "Array" : typeof schema
}`,
);
throw new Error(`Expected string, object, or Buffer. Got ${Array.isArray(schema) ? "Array" : typeof schema}`);
}

@@ -110,8 +95,5 @@

const redocParseT = performance.now();
let absoluteRef = fileURLToPath(
new URL(options?.cwd ?? `file://${process.cwd()}/`),
);
let absoluteRef = fileURLToPath(new URL(options?.cwd ?? `file://${process.cwd()}/`));
if (source instanceof URL) {
absoluteRef =
source.protocol === "file:" ? fileURLToPath(source) : source.href;
absoluteRef = source.protocol === "file:" ? fileURLToPath(source) : source.href;
}

@@ -126,3 +108,3 @@ const resolver = new BaseResolver(options.redoc.resolve);

// 1. check for OpenAPI 3 or greater
const openapiVersion = parseFloat(document.parsed.openapi);
const openapiVersion = Number.parseFloat(document.parsed.openapi);
if (

@@ -136,14 +118,7 @@ document.parsed.swagger ||

if (document.parsed.swagger) {
throw new Error(
"Unsupported Swagger version: 2.x. Use OpenAPI 3.x instead.",
);
} else if (
document.parsed.openapi ||
openapiVersion < 3 ||
openapiVersion >= 4
) {
throw new Error(
`Unsupported OpenAPI version: ${document.parsed.openapi}`,
);
throw new Error("Unsupported Swagger version: 2.x. Use OpenAPI 3.x instead.");
}
if (document.parsed.openapi || openapiVersion < 3 || openapiVersion >= 4) {
throw new Error(`Unsupported OpenAPI version: ${document.parsed.openapi}`);
}
throw new Error("Unsupported schema format, expected `openapi: 3.x`");

@@ -150,0 +125,0 @@ }

@@ -8,26 +8,12 @@ import { parseRef } from "@redocly/openapi-core/lib/ref-utils.js";

export const BOOLEAN = ts.factory.createKeywordTypeNode(
ts.SyntaxKind.BooleanKeyword,
);
export const BOOLEAN = ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
export const FALSE = ts.factory.createLiteralTypeNode(ts.factory.createFalse());
export const NEVER = ts.factory.createKeywordTypeNode(
ts.SyntaxKind.NeverKeyword,
);
export const NEVER = ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword);
export const NULL = ts.factory.createLiteralTypeNode(ts.factory.createNull());
export const NUMBER = ts.factory.createKeywordTypeNode(
ts.SyntaxKind.NumberKeyword,
);
export const QUESTION_TOKEN = ts.factory.createToken(
ts.SyntaxKind.QuestionToken,
);
export const STRING = ts.factory.createKeywordTypeNode(
ts.SyntaxKind.StringKeyword,
);
export const NUMBER = ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
export const QUESTION_TOKEN = ts.factory.createToken(ts.SyntaxKind.QuestionToken);
export const STRING = ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
export const TRUE = ts.factory.createLiteralTypeNode(ts.factory.createTrue());
export const UNDEFINED = ts.factory.createKeywordTypeNode(
ts.SyntaxKind.UndefinedKeyword,
);
export const UNKNOWN = ts.factory.createKeywordTypeNode(
ts.SyntaxKind.UnknownKeyword,
);
export const UNDEFINED = ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword);
export const UNKNOWN = ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword);

@@ -56,11 +42,4 @@ const LB_RE = /\r?\n/g;

*/
export function addJSDocComment(
schemaObject: AnnotatedSchemaObject,
node: ts.PropertySignature,
): void {
if (
!schemaObject ||
typeof schemaObject !== "object" ||
Array.isArray(schemaObject)
) {
export function addJSDocComment(schemaObject: AnnotatedSchemaObject, node: ts.PropertySignature): void {
if (!schemaObject || typeof schemaObject !== "object" || Array.isArray(schemaObject)) {
return;

@@ -98,5 +77,3 @@ }

const serialized =
typeof schemaObject[field] === "object"
? JSON.stringify(schemaObject[field], null, 2)
: schemaObject[field];
typeof schemaObject[field] === "object" ? JSON.stringify(schemaObject[field], null, 2) : schemaObject[field];
output.push(`@${field} ${String(serialized).replace(LB_RE, "\n * ")}`);

@@ -118,3 +95,3 @@ }

}
output.push(`@enum {${type}${schemaObject.nullable ? `|null` : ""}}`);
output.push(`@enum {${type}${schemaObject.nullable ? "|null" : ""}}`);
}

@@ -147,6 +124,5 @@

}
let t: ts.TypeReferenceNode | ts.IndexedAccessTypeNode =
ts.factory.createTypeReferenceNode(
ts.factory.createIdentifier(String(pointer[0])),
);
let t: ts.TypeReferenceNode | ts.IndexedAccessTypeNode = ts.factory.createTypeReferenceNode(
ts.factory.createIdentifier(String(pointer[0])),
);
if (pointer.length > 1) {

@@ -157,5 +133,5 @@ for (let i = 1; i < pointer.length; i++) {

ts.factory.createLiteralTypeNode(
typeof pointer[i]! === "number"
? ts.factory.createNumericLiteral(pointer[i]!)
: ts.factory.createStringLiteral(pointer[i]! as string),
typeof pointer[i] === "number"
? ts.factory.createNumericLiteral(pointer[i])
: ts.factory.createStringLiteral(pointer[i] as string),
),

@@ -188,5 +164,3 @@ );

// @ts-expect-error it’s OK to overwrite statements once
sourceFile.statements = ts.factory.createNodeArray(
Array.isArray(ast) ? ast : [ast],
);
sourceFile.statements = ts.factory.createNodeArray(Array.isArray(ast) ? ast : [ast]);

@@ -209,3 +183,3 @@ const printer = ts.createPrinter({

/* scriptKind */ undefined,
).statements as any; // eslint-disable-line @typescript-eslint/no-explicit-any
).statements as any;
}

@@ -245,5 +219,3 @@

const last = c[c.length - 1];
return JS_PROPERTY_INDEX_INVALID_CHARS_RE.test(last)
? ""
: last.toUpperCase();
return JS_PROPERTY_INDEX_INVALID_CHARS_RE.test(last) ? "" : last.toUpperCase();
});

@@ -255,9 +227,5 @@ if (Number(name[0]) >= 0) {

return ts.factory.createEnumDeclaration(
/* modifiers */ options
? tsModifiers({ export: options.export ?? false })
: undefined,
/* modifiers */ options ? tsModifiers({ export: options.export ?? false }) : undefined,
/* name */ enumName,
/* members */ members.map((value, i) =>
tsEnumMember(value, metadata?.[i]),
),
/* members */ members.map((value, i) => tsEnumMember(value, metadata?.[i])),
);

@@ -267,6 +235,3 @@ }

/** Sanitize TS enum member expression */
export function tsEnumMember(
value: string | number,
metadata: { name?: string; description?: string } = {},
) {
export function tsEnumMember(value: string | number, metadata: { name?: string; description?: string } = {}) {
let name = metadata.name ?? String(value);

@@ -282,3 +247,3 @@ if (!JS_PROPERTY_INDEX_RE.test(name)) {

let member;
let member: ts.EnumMember;
if (typeof value === "number") {

@@ -295,9 +260,6 @@ const literal =

} else {
member = ts.factory.createEnumMember(
name,
ts.factory.createStringLiteral(value),
);
member = ts.factory.createEnumMember(name, ts.factory.createStringLiteral(value));
}
if (metadata.description == undefined) {
if (metadata.description === undefined) {
return member;

@@ -345,10 +307,6 @@ }

// workaround for UTF-8: https://github.com/microsoft/TypeScript/issues/36174
return ts.factory.createIdentifier(
JSON.stringify(value),
) as unknown as ts.TypeNode;
return ts.factory.createIdentifier(JSON.stringify(value)) as unknown as ts.TypeNode;
}
if (typeof value === "number") {
return ts.factory.createLiteralTypeNode(
ts.factory.createNumericLiteral(value),
);
return ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(value));
}

@@ -365,5 +323,3 @@ if (typeof value === "boolean") {

}
return ts.factory.createTupleTypeNode(
value.map((v: unknown) => tsLiteral(v)),
);
return ts.factory.createTupleTypeNode(value.map((v: unknown) => tsLiteral(v)));
}

@@ -382,5 +338,3 @@ if (typeof value === "object") {

}
return keys.length
? ts.factory.createTypeLiteralNode(keys)
: tsRecord(STRING, NEVER);
return keys.length ? ts.factory.createTypeLiteralNode(keys) : tsRecord(STRING, NEVER);
}

@@ -412,6 +366,6 @@ return UNKNOWN;

export function tsOmit(type: ts.TypeNode, keys: string[]): ts.TypeNode {
return ts.factory.createTypeReferenceNode(
ts.factory.createIdentifier("Omit"),
[type, ts.factory.createUnionTypeNode(keys.map((k) => tsLiteral(k)))],
);
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Omit"), [
type,
ts.factory.createUnionTypeNode(keys.map((k) => tsLiteral(k))),
]);
}

@@ -421,6 +375,3 @@

export function tsRecord(key: ts.TypeNode, value: ts.TypeNode) {
return ts.factory.createTypeReferenceNode(
ts.factory.createIdentifier("Record"),
[key, value],
);
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("Record"), [key, value]);
}

@@ -432,5 +383,3 @@

(typeof index === "number" && !(index < 0)) ||
(typeof index === "string" &&
String(Number(index)) === index &&
index[0] !== "-")
(typeof index === "string" && String(Number(index)) === index && index[0] !== "-")
) {

@@ -466,19 +415,11 @@ return ts.factory.createNumericLiteral(index);

// inject helper, if needed
if (
!injectFooter.some(
(node) =>
ts.isTypeAliasDeclaration(node) &&
node?.name?.escapedText === "WithRequired",
)
) {
const helper = stringToAST(
`type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };`,
)[0] as any; // eslint-disable-line @typescript-eslint/no-explicit-any
if (!injectFooter.some((node) => ts.isTypeAliasDeclaration(node) && node?.name?.escapedText === "WithRequired")) {
const helper = stringToAST("type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };")[0] as any;
injectFooter.push(helper);
}
return ts.factory.createTypeReferenceNode(
ts.factory.createIdentifier("WithRequired"),
[type, tsUnion(keys.map((k) => tsLiteral(k)))],
);
return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("WithRequired"), [
type,
tsUnion(keys.map((k) => tsLiteral(k))),
]);
}

@@ -1,15 +0,6 @@

import {
escapePointer,
parseRef,
} from "@redocly/openapi-core/lib/ref-utils.js";
import { escapePointer, parseRef } from "@redocly/openapi-core/lib/ref-utils.js";
import c from "ansi-colors";
import supportsColor from "supports-color";
import ts from "typescript";
import type {
DiscriminatorObject,
OpenAPI3,
OpenAPITSOptions,
ReferenceObject,
SchemaObject,
} from "../types.js";
import type { DiscriminatorObject, OpenAPI3, OpenAPITSOptions, ReferenceObject, SchemaObject } from "../types.js";
import { tsLiteral, tsModifiers, tsPropertyIndex } from "./ts.js";

@@ -36,3 +27,3 @@

// get the inferred propertyName value from the last section of the path (as the spec suggests to do)
let value = parseRef(path).pointer.pop()!;
let value = parseRef(path).pointer.pop();
// if mapping, and there’s a match, use this rather than the inferred name

@@ -42,5 +33,3 @@ if (discriminator.mapping) {

const matchedValue = Object.entries(discriminator.mapping).find(
([, v]) =>
(!v.startsWith("#") && v === value) ||
(v.startsWith("#") && parseRef(v).pointer.pop() === value),
([, v]) => (!v.startsWith("#") && v === value) || (v.startsWith("#") && parseRef(v).pointer.pop() === value),
);

@@ -62,6 +51,6 @@ if (matchedValue) {

/** Create a $ref pointer (even from other $refs) */
export function createRef(parts: (number | string)[]): string {
export function createRef(parts: (number | string | undefined | null)[]): string {
let pointer = "#";
for (const part of parts) {
if (!part) {
if (part === undefined || part === null || part === "") {
continue;

@@ -88,4 +77,3 @@ }

process.env.DEBUG === "openapi-ts:*" ||
process.env.DEBUG.toLocaleLowerCase() ===
`openapi-ts:${group.toLocaleLowerCase()}`)
process.env.DEBUG.toLocaleLowerCase() === `openapi-ts:${group.toLocaleLowerCase()}`)
) {

@@ -98,3 +86,2 @@ const groupColor = (group && DEBUG_GROUPS[group]) || c.whiteBright;

}
// eslint-disable-next-line no-console
console.debug(` ${c.bold(groupName)}${timeFormatted}${msg}`);

@@ -106,3 +93,3 @@ }

export function error(msg: string) {
console.error(c.red(` ✘ ${msg}`)); // eslint-disable-line no-console
console.error(c.red(` ✘ ${msg}`));
}

@@ -115,3 +102,4 @@

return `${Math.round(10 * t) / 10}ms`;
} else if (t < 60000) {
}
if (t < 60000) {
return `${Math.round(t / 100) / 10}s`;

@@ -137,6 +125,3 @@ }

if (options?.excludeDeprecated) {
entries = entries.filter(
([, v]) =>
!(v && typeof v === "object" && "deprecated" in v && v.deprecated),
);
entries = entries.filter(([, v]) => !(v && typeof v === "object" && "deprecated" in v && v.deprecated));
}

@@ -146,3 +131,2 @@ return entries;

/* eslint-disable @typescript-eslint/no-explicit-any */
/** resolve a $ref in a schema */

@@ -183,6 +167,3 @@ export function resolveRef<T>(

function createDiscriminatorEnum(
values: string[],
prevSchema?: SchemaObject,
): SchemaObject {
function createDiscriminatorEnum(values: string[], prevSchema?: SchemaObject): SchemaObject {
return {

@@ -193,3 +174,3 @@ type: "string",

? `${prevSchema.description} (enum property replaced by openapi-typescript)`
: `discriminator enum property added by openapi-typescript`,
: "discriminator enum property added by openapi-typescript",
};

@@ -223,7 +204,3 @@ }

return true;
} else if (
typeof resolvedSchema === "object" &&
"type" in resolvedSchema &&
resolvedSchema.type === "object"
) {
} else if (typeof resolvedSchema === "object" && "type" in resolvedSchema && resolvedSchema.type === "object") {
// if the schema is an object, we can apply the discriminator enums to its properties

@@ -242,7 +219,6 @@ if (!resolvedSchema.properties) {

// add/replace the discriminator enum property
resolvedSchema.properties[discriminator.propertyName] =
createDiscriminatorEnum(
values,
resolvedSchema.properties[discriminator.propertyName],
);
resolvedSchema.properties[discriminator.propertyName] = createDiscriminatorEnum(
values,
resolvedSchema.properties[discriminator.propertyName] as SchemaObject,
);

@@ -262,12 +238,6 @@ return true;

type InternalDiscriminatorMapping = Record<
string,
{ inferred?: string; defined?: string[] }
>;
type InternalDiscriminatorMapping = Record<string, { inferred?: string; defined?: string[] }>;
/** Return a key–value map of discriminator objects found in a schema */
export function scanDiscriminators(
schema: OpenAPI3,
options: OpenAPITSOptions,
) {
export function scanDiscriminators(schema: OpenAPI3, options: OpenAPITSOptions) {
// all discriminator objects found in the schema

@@ -345,13 +315,7 @@ const objects: Record<string, DiscriminatorObject> = {};

// so if we have defined values, use them instead
// biome-ignore lint/style/noNonNullAssertion: we just checked for this
const mappedValues = defined ?? [inferred!];
if (
patchDiscriminatorEnum(
schema,
mappedRef,
mappedValues,
discriminator,
ref,
options,
)
patchDiscriminatorEnum(schema as unknown as SchemaObject, mappedRef, mappedValues, discriminator, ref, options)
) {

@@ -391,3 +355,3 @@ refsHandled.push(mappedRef);

patchDiscriminatorEnum(
schema,
schema as unknown as SchemaObject,
ref,

@@ -441,4 +405,4 @@ mappedValues,

if (!silent) {
console.warn(c.yellow(` ⚠ ${msg}`)); // eslint-disable-line no-console
console.warn(c.yellow(` ⚠ ${msg}`));
}
}
import ts from "typescript";
import {
NEVER,
QUESTION_TOKEN,
addJSDocComment,
tsModifiers,
tsPropertyIndex,
} from "../lib/ts.js";
import { NEVER, QUESTION_TOKEN, addJSDocComment, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef, debug, getEntries } from "../lib/utils.js";
import type {
ComponentsObject,
GlobalContext,
SchemaObject,
TransformNodeOptions,
} from "../types.js";
import type { ComponentsObject, GlobalContext, SchemaObject, TransformNodeOptions } from "../types.js";
import transformHeaderObject from "./header-object.js";

@@ -23,11 +12,5 @@ import transformParameterObject from "./parameter-object.js";

type ComponentTransforms = keyof Omit<
ComponentsObject,
"examples" | "securitySchemes" | "links" | "callbacks"
>;
type ComponentTransforms = keyof Omit<ComponentsObject, "examples" | "securitySchemes" | "links" | "callbacks">;
const transformers: Record<
ComponentTransforms,
(node: any, options: TransformNodeOptions) => ts.TypeNode // eslint-disable-line @typescript-eslint/no-explicit-any
> = {
const transformers: Record<ComponentTransforms, (node: any, options: TransformNodeOptions) => ts.TypeNode> = {
schemas: transformSchemaObject,

@@ -45,6 +28,3 @@ responses: transformResponseObject,

*/
export default function transformComponentsObject(
componentsObject: ComponentsObject,
ctx: GlobalContext,
): ts.TypeNode {
export default function transformComponentsObject(componentsObject: ComponentsObject, ctx: GlobalContext): ts.TypeNode {
const type: ts.TypeElement[] = [];

@@ -85,3 +65,3 @@

);
addJSDocComment(item as unknown as any, property); // eslint-disable-line @typescript-eslint/no-explicit-any
addJSDocComment(item as unknown as any, property);
items.push(property);

@@ -95,13 +75,7 @@ }

/* questionToken */ undefined,
/* type */ items.length
? ts.factory.createTypeLiteralNode(items)
: NEVER,
/* type */ items.length ? ts.factory.createTypeLiteralNode(items) : NEVER,
),
);
debug(
`Transformed components → ${key}`,
"ts",
performance.now() - componentT,
);
debug(`Transformed components → ${key}`, "ts", performance.now() - componentT);
}

@@ -108,0 +82,0 @@

import { escapePointer } from "@redocly/openapi-core/lib/ref-utils.js";
import ts from "typescript";
import {
addJSDocComment,
tsModifiers,
tsPropertyIndex,
UNKNOWN,
} from "../lib/ts.js";
import { addJSDocComment, tsModifiers, tsPropertyIndex, UNKNOWN } from "../lib/ts.js";
import { getEntries } from "../lib/utils.js";

@@ -18,6 +13,3 @@ import type { HeaderObject, TransformNodeOptions } from "../types.js";

*/
export default function transformHeaderObject(
headerObject: HeaderObject,
options: TransformNodeOptions,
): ts.TypeNode {
export default function transformHeaderObject(headerObject: HeaderObject, options: TransformNodeOptions): ts.TypeNode {
if (headerObject.schema) {

@@ -29,6 +21,3 @@ return transformSchemaObject(headerObject.schema, options);

const type: ts.TypeElement[] = [];
for (const [contentType, mediaTypeObject] of getEntries(
headerObject.content,
options.ctx,
)) {
for (const [contentType, mediaTypeObject] of getEntries(headerObject.content, options.ctx)) {
const nextPath = `${options.path ?? "#"}/${escapePointer(contentType)}`;

@@ -35,0 +24,0 @@ const mediaType =

@@ -1,5 +0,2 @@

import ts, {
type InterfaceDeclaration,
type TypeLiteralNode,
} from "typescript";
import ts, { type InterfaceDeclaration, type TypeLiteralNode } from "typescript";
import { NEVER, STRING, tsModifiers, tsRecord } from "../lib/ts.js";

@@ -13,16 +10,9 @@ import { createRef, debug } from "../lib/utils.js";

type SchemaTransforms = keyof Pick<
OpenAPI3,
"paths" | "webhooks" | "components" | "$defs"
>;
type SchemaTransforms = keyof Pick<OpenAPI3, "paths" | "webhooks" | "components" | "$defs">;
const transformers: Record<
SchemaTransforms,
(node: any, options: GlobalContext) => ts.TypeNode // eslint-disable-line @typescript-eslint/no-explicit-any
> = {
const transformers: Record<SchemaTransforms, (node: any, options: GlobalContext) => ts.TypeNode> = {
paths: transformPathsObject,
webhooks: transformWebhooksObject,
components: transformComponentsObject,
$defs: (node, options) =>
transformSchemaObject(node, { path: createRef(["$defs"]), ctx: options }),
$defs: (node, options) => transformSchemaObject(node, { path: createRef(["$defs"]), ctx: options }),
};

@@ -75,6 +65,3 @@

for (const injectedType of ctx.injectFooter) {
if (
!hasOperations &&
(injectedType as InterfaceDeclaration)?.name?.escapedText === "operations"
) {
if (!hasOperations && (injectedType as InterfaceDeclaration)?.name?.escapedText === "operations") {
hasOperations = true;

@@ -81,0 +68,0 @@ }

import ts from "typescript";
import {
NEVER,
QUESTION_TOKEN,
addJSDocComment,
oapiRef,
tsModifiers,
tsPropertyIndex,
} from "../lib/ts.js";
import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef } from "../lib/utils.js";
import type {
OperationObject,
RequestBodyObject,
TransformNodeOptions,
} from "../types.js";
import type { OperationObject, RequestBodyObject, TransformNodeOptions } from "../types.js";
import { transformParametersArray } from "./parameters-array.js";

@@ -31,5 +20,3 @@ import transformRequestBodyObject from "./request-body-object.js";

// parameters
type.push(
...transformParametersArray(operationObject.parameters ?? [], options),
);
type.push(...transformParametersArray(operationObject.parameters ?? [], options));

@@ -43,9 +30,7 @@ // requestBody

...options,
path: createRef([options.path!, "requestBody"]),
path: createRef([options.path, "requestBody"]),
});
const required = !!(
"$ref" in operationObject.requestBody
? options.ctx.resolve<RequestBodyObject>(
operationObject.requestBody.$ref,
)
? options.ctx.resolve<RequestBodyObject>(operationObject.requestBody.$ref)
: operationObject.requestBody

@@ -78,6 +63,3 @@ )?.required;

/* questionToken */ undefined,
/* type */ transformResponsesObject(
operationObject.responses ?? {},
options,
),
/* type */ transformResponsesObject(operationObject.responses ?? {}, options),
),

@@ -97,5 +79,3 @@ );

let operations = options.ctx.injectFooter.find(
(node) =>
ts.isInterfaceDeclaration(node) &&
(node as ts.InterfaceDeclaration).name.text === "operations",
(node) => ts.isInterfaceDeclaration(node) && (node as ts.InterfaceDeclaration).name.text === "operations",
) as unknown as ts.InterfaceDeclaration;

@@ -102,0 +82,0 @@ if (!operations) {

@@ -14,5 +14,3 @@ import type ts from "typescript";

): ts.TypeNode {
return parameterObject.schema
? transformSchemaObject(parameterObject.schema, options)
: STRING; // assume a parameter is a string by default rather than "unknown"
return parameterObject.schema ? transformSchemaObject(parameterObject.schema, options) : STRING; // assume a parameter is a string by default rather than "unknown"
}
import ts from "typescript";
import {
NEVER,
QUESTION_TOKEN,
addJSDocComment,
oapiRef,
tsModifiers,
tsPropertyIndex,
} from "../lib/ts.js";
import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef } from "../lib/utils.js";
import type {
ParameterObject,
ReferenceObject,
TransformNodeOptions,
} from "../types.js";
import type { ParameterObject, ReferenceObject, TransformNodeOptions } from "../types.js";
import transformParameterObject from "./parameter-object.js";

@@ -29,26 +18,15 @@

const paramType: ts.TypeElement[] = [];
for (const paramIn of [
"query",
"header",
"path",
"cookie",
] as ParameterObject["in"][]) {
for (const paramIn of ["query", "header", "path", "cookie"] as ParameterObject["in"][]) {
const paramLocType: ts.TypeElement[] = [];
let operationParameters = parametersArray.map((param) => ({
original: param,
resolved:
"$ref" in param
? options.ctx.resolve<ParameterObject>(param.$ref)
: param,
resolved: "$ref" in param ? options.ctx.resolve<ParameterObject>(param.$ref) : param,
}));
// this is the only array type in the spec, so we have to one-off sort here
if (options.ctx.alphabetize) {
operationParameters.sort((a, b) =>
(a.resolved?.name ?? "").localeCompare(b.resolved?.name ?? ""),
);
operationParameters.sort((a, b) => (a.resolved?.name ?? "").localeCompare(b.resolved?.name ?? ""));
}
if (options.ctx.excludeDeprecated) {
operationParameters = operationParameters.filter(
({ resolved }) =>
!resolved?.deprecated && !resolved?.schema?.deprecated,
({ resolved }) => !resolved?.deprecated && !resolved?.schema?.deprecated,
);

@@ -69,8 +47,3 @@ }

...options,
path: createRef([
options.path ?? "",
"parameters",
resolved.in,
resolved.name,
]),
path: createRef([options.path, "parameters", resolved.in, resolved.name]),
});

@@ -91,8 +64,4 @@ const property = ts.factory.createPropertySignature(

/* name */ tsPropertyIndex(paramIn),
/* questionToken */ allOptional || !paramLocType.length
? QUESTION_TOKEN
: undefined,
/* type */ paramLocType.length
? ts.factory.createTypeLiteralNode(paramLocType)
: NEVER,
/* questionToken */ allOptional || !paramLocType.length ? QUESTION_TOKEN : undefined,
/* type */ paramLocType.length ? ts.factory.createTypeLiteralNode(paramLocType) : NEVER,
),

@@ -106,5 +75,3 @@ );

/* questionToken */ !paramType.length ? QUESTION_TOKEN : undefined,
/* type */ paramType.length
? ts.factory.createTypeLiteralNode(paramType)
: NEVER,
/* type */ paramType.length ? ts.factory.createTypeLiteralNode(paramType) : NEVER,
),

@@ -111,0 +78,0 @@ );

import ts from "typescript";
import {
NEVER,
QUESTION_TOKEN,
addJSDocComment,
oapiRef,
tsModifiers,
tsPropertyIndex,
} from "../lib/ts.js";
import { NEVER, QUESTION_TOKEN, addJSDocComment, oapiRef, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef } from "../lib/utils.js";

@@ -18,16 +11,6 @@ import type {

} from "../types.js";
import transformOperationObject, {
injectOperationObject,
} from "./operation-object.js";
import transformOperationObject, { injectOperationObject } from "./operation-object.js";
import { transformParametersArray } from "./parameters-array.js";
export type Method =
| "get"
| "put"
| "post"
| "delete"
| "options"
| "head"
| "patch"
| "trace";
export type Method = "get" | "put" | "post" | "delete" | "options" | "head" | "patch" | "trace";

@@ -38,6 +21,3 @@ /**

*/
export default function transformPathItemObject(
pathItem: PathItemObject,
options: TransformNodeOptions,
): ts.TypeNode {
export default function transformPathItemObject(pathItem: PathItemObject, options: TransformNodeOptions): ts.TypeNode {
const type: ts.TypeElement[] = [];

@@ -49,3 +29,3 @@

...options,
path: createRef([options.path!, "parameters"]),
path: createRef([options.path, "parameters"]),
}),

@@ -55,12 +35,3 @@ );

// methods
for (const method of [
"get",
"put",
"post",
"delete",
"options",
"head",
"patch",
"trace",
] as Method[]) {
for (const method of ["get", "put", "post", "delete", "options", "head", "patch", "trace"] as Method[]) {
const operationObject = pathItem[method];

@@ -70,6 +41,4 @@ if (

(options.ctx.excludeDeprecated &&
("$ref" in operationObject
? options.ctx.resolve<OperationObject>(operationObject.$ref)
: operationObject
)?.deprecated)
("$ref" in operationObject ? options.ctx.resolve<OperationObject>(operationObject.$ref) : operationObject)
?.deprecated)
) {

@@ -88,14 +57,7 @@ type.push(

// fold top-level PathItem parameters into method-level, with the latter overriding the former
const keyedParameters: Record<string, ParameterObject | ReferenceObject> =
{};
const keyedParameters: Record<string, ParameterObject | ReferenceObject> = {};
if (!("$ref" in operationObject)) {
// important: OperationObject parameters come last, and will override any conflicts with PathItem parameters
for (const parameter of [
...(pathItem.parameters ?? []),
...(operationObject.parameters ?? []),
]) {
const name =
"$ref" in parameter
? options.ctx.resolve<ParameterObject>(parameter.$ref)?.name
: parameter.name;
for (const parameter of [...(pathItem.parameters ?? []), ...(operationObject.parameters ?? [])]) {
const name = "$ref" in parameter ? options.ctx.resolve<ParameterObject>(parameter.$ref)?.name : parameter.name;
if (name) {

@@ -119,3 +81,3 @@ keyedParameters[name] = parameter;

{ ...operationObject, parameters: Object.values(keyedParameters) },
{ ...options, path: createRef([options.path!, method]) },
{ ...options, path: createRef([options.path, method]) },
);

@@ -126,3 +88,3 @@ } else {

{ ...operationObject, parameters: Object.values(keyedParameters) },
{ ...options, path: createRef([options.path!, method]) },
{ ...options, path: createRef([options.path, method]) },
),

@@ -129,0 +91,0 @@ );

import ts from "typescript";
import {
addJSDocComment,
oapiRef,
stringToAST,
tsModifiers,
tsPropertyIndex,
} from "../lib/ts.js";
import { addJSDocComment, oapiRef, stringToAST, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef, debug, getEntries } from "../lib/utils.js";

@@ -26,6 +20,3 @@ import type {

*/
export default function transformPathsObject(
pathsObject: PathsObject,
ctx: GlobalContext,
): ts.TypeNode {
export default function transformPathsObject(pathsObject: PathsObject, ctx: GlobalContext): ts.TypeNode {
const type: ts.TypeElement[] = [];

@@ -60,3 +51,2 @@ for (const [url, pathItemObject] of getEntries(pathsObject, ctx)) {

if (matches) {
/* eslint-disable @typescript-eslint/no-explicit-any */
for (const match of matches) {

@@ -68,6 +58,3 @@ const paramName = match.slice(1, -1);

} else {
rawPath = rawPath.replace(
match,
`$\{${(param.schema as any)?.type ?? "string"}}`,
);
rawPath = rawPath.replace(match, `$\{${(param.schema as any)?.type ?? "string"}}`);
}

@@ -97,3 +84,2 @@ }

}
/* eslint-enable @typescript-eslint/no-explicit-any */
}

@@ -121,6 +107,3 @@ }

for (const p of pathItemObject.parameters ?? []) {
const resolved =
"$ref" in p && p.$ref
? ctx.resolve<ParameterObject>(p.$ref)
: (p as ParameterObject);
const resolved = "$ref" in p && p.$ref ? ctx.resolve<ParameterObject>(p.$ref) : (p as ParameterObject);
if (resolved && resolved.in === "path") {

@@ -130,12 +113,3 @@ params[resolved.name] = resolved;

}
for (const method of [
"get",
"put",
"post",
"delete",
"options",
"head",
"patch",
"trace",
] as Method[]) {
for (const method of ["get", "put", "post", "delete", "options", "head", "patch", "trace"] as Method[]) {
if (!(method in pathItemObject)) {

@@ -145,12 +119,7 @@ continue;

const resolvedMethod = (pathItemObject[method] as ReferenceObject).$ref
? ctx.resolve<OperationObject>(
(pathItemObject[method] as ReferenceObject).$ref,
)
? ctx.resolve<OperationObject>((pathItemObject[method] as ReferenceObject).$ref)
: (pathItemObject[method] as OperationObject);
if (resolvedMethod?.parameters) {
for (const p of resolvedMethod.parameters) {
const resolvedParam =
"$ref" in p && p.$ref
? ctx.resolve<ParameterObject>(p.$ref)
: (p as ParameterObject);
const resolvedParam = "$ref" in p && p.$ref ? ctx.resolve<ParameterObject>(p.$ref) : (p as ParameterObject);
if (resolvedParam && resolvedParam.in === "path") {

@@ -157,0 +126,0 @@ params[resolvedParam.name] = resolvedParam;

import ts from "typescript";
import {
NEVER,
QUESTION_TOKEN,
addJSDocComment,
tsModifiers,
tsPropertyIndex,
} from "../lib/ts.js";
import { NEVER, QUESTION_TOKEN, addJSDocComment, tsModifiers, tsPropertyIndex } from "../lib/ts.js";
import { createRef, getEntries } from "../lib/utils.js";

@@ -23,7 +17,4 @@ import type { RequestBodyObject, TransformNodeOptions } from "../types.js";

const type: ts.TypeElement[] = [];
for (const [contentType, mediaTypeObject] of getEntries(
requestBodyObject.content,
options.ctx,
)) {
const nextPath = createRef([options.path!, contentType]);
for (const [contentType, mediaTypeObject] of getEntries(requestBodyObject.content, options.ctx)) {
const nextPath = createRef([options.path, contentType]);
const mediaType =

@@ -30,0 +21,0 @@ "$ref" in mediaTypeObject

@@ -30,10 +30,4 @@ import ts from "typescript";

if (responseObject.headers) {
for (const [name, headerObject] of getEntries(
responseObject.headers,
options.ctx,
)) {
const optional =
"$ref" in headerObject || headerObject.required
? undefined
: QUESTION_TOKEN;
for (const [name, headerObject] of getEntries(responseObject.headers, options.ctx)) {
const optional = "$ref" in headerObject || headerObject.required ? undefined : QUESTION_TOKEN;
const subType =

@@ -44,3 +38,3 @@ "$ref" in headerObject

...options,
path: createRef([options.path ?? "", "headers", name]),
path: createRef([options.path, "headers", name]),
});

@@ -85,6 +79,3 @@ const property = ts.factory.createPropertySignature(

if (responseObject.content) {
for (const [contentType, mediaTypeObject] of getEntries(
responseObject.content,
options.ctx,
)) {
for (const [contentType, mediaTypeObject] of getEntries(responseObject.content, options.ctx)) {
const property = ts.factory.createPropertySignature(

@@ -96,3 +87,3 @@ /* modifiers */ tsModifiers({ readonly: options.ctx.immutable }),

...options,
path: createRef([options.path ?? "", "content", contentType]),
path: createRef([options.path, "content", contentType]),
}),

@@ -99,0 +90,0 @@ );

import ts from "typescript";
import {
NEVER,
addJSDocComment,
tsModifiers,
oapiRef,
tsPropertyIndex,
} from "../lib/ts.js";
import { NEVER, addJSDocComment, tsModifiers, oapiRef, tsPropertyIndex } from "../lib/ts.js";
import { createRef, getEntries } from "../lib/utils.js";

@@ -23,6 +17,3 @@ import type { ResponsesObject, TransformNodeOptions } from "../types.js";

for (const [responseCode, responseObject] of getEntries(
responsesObject,
options.ctx,
)) {
for (const [responseCode, responseObject] of getEntries(responsesObject, options.ctx)) {
const responseType =

@@ -33,3 +24,3 @@ "$ref" in responseObject

...options,
path: createRef([options.path ?? "", "responses", responseCode]),
path: createRef([options.path, "responses", responseCode]),
});

@@ -36,0 +27,0 @@ const property = ts.factory.createPropertySignature(

@@ -26,12 +26,4 @@ import { parseRef } from "@redocly/openapi-core/lib/ref-utils.js";

} from "../lib/ts.js";
import {
createDiscriminatorProperty,
createRef,
getEntries,
} from "../lib/utils.js";
import type {
ReferenceObject,
SchemaObject,
TransformNodeOptions,
} from "../types.js";
import { createDiscriminatorProperty, createRef, getEntries } from "../lib/utils.js";
import type { ReferenceObject, SchemaObject, TransformNodeOptions } from "../types.js";

@@ -77,7 +69,3 @@ /**

if (Array.isArray(schemaObject) || typeof schemaObject !== "object") {
throw new Error(
`Expected SchemaObject, received ${
Array.isArray(schemaObject) ? "Array" : typeof schemaObject
}`,
);
throw new Error(`Expected SchemaObject, received ${Array.isArray(schemaObject) ? "Array" : typeof schemaObject}`);
}

@@ -110,8 +98,3 @@

// hoist enum to top level if string/number enum and option is enabled
if (
options.ctx.enum &&
schemaObject.enum.every(
(v) => typeof v === "string" || typeof v === "number",
)
) {
if (options.ctx.enum && schemaObject.enum.every((v) => typeof v === "string" || typeof v === "number")) {
let enumName = parseRef(options.path ?? "").pointer.join("/");

@@ -121,8 +104,4 @@ // allow #/components/schemas to have simpler names

const metadata = schemaObject.enum.map((_, i) => ({
name:
schemaObject["x-enum-varnames"]?.[i] ??
schemaObject["x-enumNames"]?.[i],
description:
schemaObject["x-enum-descriptions"]?.[i] ??
schemaObject["x-enumDescriptions"]?.[i],
name: schemaObject["x-enum-varnames"]?.[i] ?? schemaObject["x-enumNames"]?.[i],
description: schemaObject["x-enum-descriptions"]?.[i] ?? schemaObject["x-enumDescriptions"]?.[i],
}));

@@ -160,6 +139,3 @@ const enumType = tsEnum(

/** Collect allOf with Omit<> for discriminators */
function collectAllOfCompositions(
items: (SchemaObject | ReferenceObject)[],
required?: string[],
): ts.TypeNode[] {
function collectAllOfCompositions(items: (SchemaObject | ReferenceObject)[], required?: string[]): ts.TypeNode[] {
const output: ts.TypeNode[] = [];

@@ -184,11 +160,5 @@ for (const item of items) {

// add WithRequired<X, Y> if necessary
const validRequired = (required ?? []).filter(
(key) => !!resolved.properties![key],
);
const validRequired = (required ?? []).filter((key) => !!resolved.properties?.[key]);
if (validRequired.length) {
itemType = tsWithRequired(
itemType,
validRequired,
options.ctx.injectFooter,
);
itemType = tsWithRequired(itemType, validRequired, options.ctx.injectFooter);
}

@@ -203,11 +173,7 @@ }

}
itemType = transformSchemaObject(
{ ...item, required: itemRequired },
options,
);
itemType = transformSchemaObject({ ...item, required: itemRequired }, options);
}
const discriminator =
("$ref" in item && options.ctx.discriminators.objects[item.$ref]) ||
(item as any).discriminator; // eslint-disable-line @typescript-eslint/no-explicit-any
("$ref" in item && options.ctx.discriminators.objects[item.$ref]) || (item as any).discriminator;
if (discriminator) {

@@ -227,14 +193,6 @@ output.push(tsOmit(itemType, [discriminator.propertyName]));

const coreObjectType = transformSchemaObjectCore(schemaObject, options);
const allOfType = collectAllOfCompositions(
schemaObject.allOf ?? [],
schemaObject.required,
);
const allOfType = collectAllOfCompositions(schemaObject.allOf ?? [], schemaObject.required);
if (coreObjectType || allOfType.length) {
const allOf: ts.TypeNode | undefined = allOfType.length
? tsIntersection(allOfType)
: undefined;
finalType = tsIntersection([
...(coreObjectType ? [coreObjectType] : []),
...(allOf ? [allOf] : []),
]);
const allOf: ts.TypeNode | undefined = allOfType.length ? tsIntersection(allOfType) : undefined;
finalType = tsIntersection([...(coreObjectType ? [coreObjectType] : []), ...(allOf ? [allOf] : [])]);
}

@@ -260,6 +218,3 @@ // anyOf: union

} else {
finalType = tsIntersection([
...(finalType ? [finalType] : []),
tsUnion(oneOfType),
]);
finalType = tsIntersection([...(finalType ? [finalType] : []), tsUnion(oneOfType)]);
}

@@ -291,7 +246,19 @@ }

*/
function transformSchemaObjectCore(
schemaObject: SchemaObject,
options: TransformNodeOptions,
): ts.TypeNode | undefined {
function transformSchemaObjectCore(schemaObject: SchemaObject, options: TransformNodeOptions): ts.TypeNode | undefined {
if ("type" in schemaObject && schemaObject.type) {
if (typeof options.ctx.transform === "function") {
const result = options.ctx.transform(schemaObject, options);
if (result) {
if ("schema" in result) {
if (result.questionToken) {
return ts.factory.createUnionTypeNode([result.schema, UNDEFINED]);
} else {
return result.schema;
}
} else {
return result;
}
}
}
// primitives

@@ -321,18 +288,9 @@ // type: null

if (schemaObject.prefixItems || Array.isArray(schemaObject.items)) {
const prefixItems =
schemaObject.prefixItems ??
(schemaObject.items as (SchemaObject | ReferenceObject)[]);
itemType = ts.factory.createTupleTypeNode(
prefixItems.map((item) => transformSchemaObject(item, options)),
);
const prefixItems = schemaObject.prefixItems ?? (schemaObject.items as (SchemaObject | ReferenceObject)[]);
itemType = ts.factory.createTupleTypeNode(prefixItems.map((item) => transformSchemaObject(item, options)));
}
// standard array type
else if (schemaObject.items) {
if (
"type" in schemaObject.items &&
schemaObject.items.type === "array"
) {
itemType = ts.factory.createArrayTypeNode(
transformSchemaObject(schemaObject.items, options),
);
if ("type" in schemaObject.items && schemaObject.items.type === "array") {
itemType = ts.factory.createArrayTypeNode(transformSchemaObject(schemaObject.items, options));
} else {

@@ -344,13 +302,8 @@ itemType = transformSchemaObject(schemaObject.items, options);

const min: number =
typeof schemaObject.minItems === "number" && schemaObject.minItems >= 0
? schemaObject.minItems
: 0;
typeof schemaObject.minItems === "number" && schemaObject.minItems >= 0 ? schemaObject.minItems : 0;
const max: number | undefined =
typeof schemaObject.maxItems === "number" &&
schemaObject.maxItems >= 0 &&
min <= schemaObject.maxItems
typeof schemaObject.maxItems === "number" && schemaObject.maxItems >= 0 && min <= schemaObject.maxItems
? schemaObject.maxItems
: undefined;
const estimateCodeSize =
typeof max !== "number" ? min : (max * (max + 1) - min * (min - 1)) / 2;
const estimateCodeSize = typeof max !== "number" ? min : (max * (max + 1) - min * (min - 1)) / 2;
if (

@@ -380,7 +333,3 @@ options.ctx.arrayLength &&

}
elements.push(
ts.factory.createRestTypeNode(
ts.factory.createArrayTypeNode(itemType),
),
);
elements.push(ts.factory.createRestTypeNode(ts.factory.createArrayTypeNode(itemType)));
return ts.factory.createTupleTypeNode(elements);

@@ -402,10 +351,4 @@ }

if (
(t === "boolean" ||
t === "string" ||
t === "number" ||
t === "integer" ||
t === "null") &&
schemaObject.oneOf.find(
(o) => typeof o === "object" && "type" in o && o.type === t,
)
(t === "boolean" || t === "string" || t === "number" || t === "integer" || t === "null") &&
schemaObject.oneOf.find((o) => typeof o === "object" && "type" in o && o.type === t)
) {

@@ -418,3 +361,3 @@ continue;

: transformSchemaObject(
{ ...schemaObject, type: t, oneOf: undefined }, // don’t stack oneOf transforms
{ ...schemaObject, type: t, oneOf: undefined } as SchemaObject, // don’t stack oneOf transforms
options,

@@ -428,3 +371,3 @@ ),

? NULL
: transformSchemaObject({ ...schemaObject, type: t }, options),
: transformSchemaObject({ ...schemaObject, type: t } as SchemaObject, options),
);

@@ -451,8 +394,8 @@ }

!schemaObject.discriminator &&
!options.ctx.discriminators.refsHandled.includes(options.path!) &&
options.ctx.discriminators.objects[options.path!];
!options.ctx.discriminators.refsHandled.includes(options.path ?? "") &&
options.ctx.discriminators.objects[options.path ?? ""];
if (discriminator) {
coreObjectType.unshift(
createDiscriminatorProperty(discriminator, {
path: options.path!,
path: options.path ?? "",
readonly: options.ctx.immutable,

@@ -466,7 +409,4 @@ }),

if (
("properties" in schemaObject &&
schemaObject.properties &&
Object.keys(schemaObject.properties).length) ||
("additionalProperties" in schemaObject &&
schemaObject.additionalProperties) ||
("properties" in schemaObject && schemaObject.properties && Object.keys(schemaObject.properties).length) ||
("additionalProperties" in schemaObject && schemaObject.additionalProperties) ||
("$defs" in schemaObject && schemaObject.$defs)

@@ -476,11 +416,6 @@ ) {

if (Object.keys(schemaObject.properties ?? {}).length) {
for (const [k, v] of getEntries(
schemaObject.properties ?? {},
options.ctx,
)) {
for (const [k, v] of getEntries(schemaObject.properties ?? {}, options.ctx)) {
if (typeof v !== "object" || Array.isArray(v)) {
throw new Error(
`${
options.path
}: invalid property ${k}. Expected Schema Object, got ${
`${options.path}: invalid property ${k}. Expected Schema Object, got ${
Array.isArray(v) ? "Array" : typeof v

@@ -493,4 +428,3 @@ }`,

if (options.ctx.excludeDeprecated) {
const resolved =
"$ref" in v ? options.ctx.resolve<SchemaObject>(v.$ref) : v;
const resolved = "$ref" in v ? options.ctx.resolve<SchemaObject>(v.$ref) : v;
if (resolved?.deprecated) {

@@ -502,5 +436,4 @@ continue;

schemaObject.required?.includes(k) ||
("default" in v &&
options.ctx.defaultNonNullable &&
!options.path?.includes("parameters")) // parameters can’t be required, even with defaults
(schemaObject.required === undefined && options.ctx.propertiesRequiredByDefault) ||
("default" in v && options.ctx.defaultNonNullable && !options.path?.includes("parameters")) // parameters can’t be required, even with defaults
? undefined

@@ -513,7 +446,7 @@ : QUESTION_TOKEN;

...options,
path: createRef([options.path ?? "", k]),
path: createRef([options.path, k]),
});
if (typeof options.ctx.transform === "function") {
const result = options.ctx.transform(v, options);
const result = options.ctx.transform(v as SchemaObject, options);
if (result) {

@@ -531,4 +464,3 @@ if ("schema" in result) {

/* modifiers */ tsModifiers({
readonly:
options.ctx.immutable || ("readOnly" in v && !!v.readOnly),
readonly: options.ctx.immutable || ("readOnly" in v && !!v.readOnly),
}),

@@ -545,7 +477,3 @@ /* name */ tsPropertyIndex(k),

// $defs
if (
schemaObject.$defs &&
typeof schemaObject.$defs === "object" &&
Object.keys(schemaObject.$defs).length
) {
if (schemaObject.$defs && typeof schemaObject.$defs === "object" && Object.keys(schemaObject.$defs).length) {
const defKeys: ts.TypeElement[] = [];

@@ -555,4 +483,3 @@ for (const [k, v] of Object.entries(schemaObject.$defs)) {

/* modifiers */ tsModifiers({
readonly:
options.ctx.immutable || ("readonly" in v && !!v.readOnly),
readonly: options.ctx.immutable || ("readonly" in v && !!v.readOnly),
}),

@@ -563,3 +490,3 @@ /* name */ tsPropertyIndex(k),

...options,
path: createRef([options.path ?? "", "$defs", k]),
path: createRef([options.path, "$defs", k]),
}),

@@ -583,9 +510,5 @@ );

const hasExplicitAdditionalProperties =
typeof schemaObject.additionalProperties === "object" &&
Object.keys(schemaObject.additionalProperties).length;
typeof schemaObject.additionalProperties === "object" && Object.keys(schemaObject.additionalProperties).length;
let addlType = hasExplicitAdditionalProperties
? transformSchemaObject(
schemaObject.additionalProperties as SchemaObject,
options,
)
? transformSchemaObject(schemaObject.additionalProperties as SchemaObject, options)
: UNKNOWN;

@@ -616,5 +539,3 @@ // allow for `| undefined`, at least until https://github.com/microsoft/TypeScript/issues/4196 is resolved

return coreObjectType.length
? ts.factory.createTypeLiteralNode(coreObjectType)
: undefined;
return coreObjectType.length ? ts.factory.createTypeLiteralNode(coreObjectType) : undefined;
}

@@ -7,6 +7,3 @@ import ts from "typescript";

export default function transformWebhooksObject(
webhooksObject: WebhooksObject,
options: GlobalContext,
): ts.TypeNode {
export default function transformWebhooksObject(webhooksObject: WebhooksObject, options: GlobalContext): ts.TypeNode {
const type: ts.TypeElement[] = [];

@@ -13,0 +10,0 @@

@@ -6,3 +6,2 @@ import type { Config as RedoclyConfig } from "@redocly/openapi-core";

// Many types allow for true “any” for inheritance to work
/* eslint-disable @typescript-eslint/no-explicit-any */

@@ -457,14 +456,4 @@ export interface Extensable {

| {
type: (
| "string"
| "number"
| "integer"
| "array"
| "boolean"
| "null"
| "object"
)[];
type: ("string" | "number" | "integer" | "array" | "boolean" | "null" | "object")[];
}
// eslint-disable-next-line @typescript-eslint/ban-types
| {}
);

@@ -517,7 +506,3 @@

properties?: { [name: string]: SchemaObject | ReferenceObject };
additionalProperties?:
| boolean
| Record<string, never>
| SchemaObject
| ReferenceObject;
additionalProperties?: boolean | Record<string, never> | SchemaObject | ReferenceObject;
required?: string[];

@@ -637,6 +622,3 @@ allOf?: (SchemaObject | ReferenceObject)[];

*/
export type SecurityRequirementObject = Record<
keyof ComponentsObject["securitySchemes"],
string[]
>;
export type SecurityRequirementObject = Record<keyof ComponentsObject["securitySchemes"], string[]>;

@@ -648,2 +630,4 @@ export interface OpenAPITSOptions {

alphabetize?: boolean;
/** (optional) Generate tuples using array minItems / maxItems */
arrayLength?: boolean;
/** Allow schema objects with no specified properties to have additional properties if not expressly forbidden? (default: false) */

@@ -655,12 +639,8 @@ emptyObjectsUnknown?: boolean;

defaultNonNullable?: boolean;
/** Exclude deprecated fields from types? (default: false) */
excludeDeprecated?: boolean;
/** Manually transform certain Schema Objects with a custom TypeScript type */
transform?: (
schemaObject: SchemaObject,
options: TransformNodeOptions,
) => ts.TypeNode | TransformObject | undefined;
transform?: (schemaObject: SchemaObject, options: TransformNodeOptions) => ts.TypeNode | TransformObject | undefined;
/** Modify TypeScript types built from Schema Objects */
postTransform?: (
type: ts.TypeNode,
options: TransformNodeOptions,
) => ts.TypeNode | undefined;
postTransform?: (type: ts.TypeNode, options: TransformNodeOptions) => ts.TypeNode | undefined;
/** Add readonly properties and readonly arrays? (default: false) */

@@ -676,8 +656,6 @@ immutable?: boolean;

enum?: boolean;
/** (optional) Generate tuples using array minItems / maxItems */
arrayLength?: boolean;
/** (optional) Substitute path parameter names with their respective types */
pathParamsAsTypes?: boolean;
/** Exclude deprecated fields from types? (default: false) */
excludeDeprecated?: boolean;
/** Treat all objects as if they have \`required\` set to all properties by default (default: false) */
propertiesRequiredByDefault?: boolean;
/**

@@ -695,2 +673,3 @@ * Configure Redocly for validation, schema fetching, and bundling

alphabetize: boolean;
arrayLength: boolean;
defaultNonNullable: boolean;

@@ -709,5 +688,5 @@ discriminators: {

postTransform: OpenAPITSOptions["postTransform"];
propertiesRequiredByDefault: boolean;
redoc: RedoclyConfig;
silent: boolean;
arrayLength: boolean;
transform: OpenAPITSOptions["transform"];

@@ -714,0 +693,0 @@ /** retrieve a node by $ref */

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc