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.11 to 7.0.0-rc.0

7

bin/cli.js
#!/usr/bin/env node
import { loadConfig, findConfig, createConfig } from "@redocly/openapi-core";
import { createConfig, findConfig, loadConfig } from "@redocly/openapi-core";
import fs from "node:fs";
import path from "node:path";
import parser from "yargs-parser";
import openapiTS, { astToString, c, COMMENT_HEADER, error, formatTime, warn } from "../dist/index.js";
import openapiTS, { COMMENT_HEADER, astToString, c, error, formatTime, warn } from "../dist/index.js";

@@ -18,2 +18,3 @@ const HELP = `Usage

--enum Export true TS enums instead of unions
--enum-values Export enum values as arrays
--export-type, -t Export top-level \`type\` instead of \`interface\`

@@ -66,2 +67,3 @@ --immutable Generate readonly types

"enum",
"enumValues",
"excludeDeprecated",

@@ -96,2 +98,3 @@ "exportType",

enum: flags.enum,
enumValues: flags.enumValues,
excludeDeprecated: flags.excludeDeprecated,

@@ -98,0 +101,0 @@ exportType: flags.exportType,

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

enum: options.enum ?? false,
enumValues: options.enumValues ?? false,
excludeDeprecated: options.excludeDeprecated ?? false,

@@ -51,0 +52,0 @@ exportType: options.exportType ?? false,

@@ -44,2 +44,6 @@ import ts from "typescript";

}): ts.EnumDeclaration;
export declare function tsArrayLiteralExpression(name: string, elementType: ts.TypeNode, values: (string | number)[], options?: {
export?: boolean;
readonly?: boolean;
}): ts.VariableStatement;
export declare function tsEnumMember(value: string | number, metadata?: {

@@ -46,0 +50,0 @@ name?: string;

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

export function tsEnum(name, members, metadata, options) {
let enumName = name.replace(JS_ENUM_INVALID_CHARS_RE, (c) => {
let enumName = sanitizeMemberName(name);
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])));
}
export function tsArrayLiteralExpression(name, elementType, values, options) {
let variableName = sanitizeMemberName(name);
variableName = `${variableName[0].toLowerCase()}${variableName.substring(1)}`;
const arrayType = options?.readonly
? ts.factory.createTypeReferenceNode("ReadonlyArray", [elementType])
: ts.factory.createArrayTypeNode(elementType);
return ts.factory.createVariableStatement(options ? tsModifiers({ export: options.export ?? false }) : undefined, ts.factory.createVariableDeclarationList([
ts.factory.createVariableDeclaration(variableName, undefined, arrayType, ts.factory.createArrayLiteralExpression(values.map((value) => {
if (typeof value === "number") {
if (value < 0) {
return ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral(Math.abs(value)));
}
else {
return ts.factory.createNumericLiteral(value);
}
}
else {
return ts.factory.createStringLiteral(value);
}
}))),
], ts.NodeFlags.Const));
}
function sanitizeMemberName(name) {
let sanitizedName = name.replace(JS_ENUM_INVALID_CHARS_RE, (c) => {
const last = c[c.length - 1];

@@ -121,6 +148,5 @@ return JS_PROPERTY_INDEX_INVALID_CHARS_RE.test(last) ? "" : last.toUpperCase();

if (Number(name[0]) >= 0) {
enumName = `Value${name}`;
sanitizedName = `Value${name}`;
}
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 sanitizedName;
}

@@ -179,3 +205,6 @@ export function tsEnumMember(value, metadata = {}) {

if (typeof value === "number") {
return ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(value));
const literal = value < 0
? ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral(Math.abs(value)))
: ts.factory.createNumericLiteral(value);
return ts.factory.createLiteralTypeNode(literal);
}

@@ -182,0 +211,0 @@ if (typeof value === "boolean") {

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 { BOOLEAN, NEVER, NULL, NUMBER, QUESTION_TOKEN, STRING, UNDEFINED, UNKNOWN, addJSDocComment, oapiRef, tsArrayLiteralExpression, tsEnum, tsIntersection, tsIsPrimitive, tsLiteral, tsModifiers, tsNullable, tsOmit, tsPropertyIndex, tsRecord, tsUnion, tsWithRequired, } from "../lib/ts.js";
import { createDiscriminatorProperty, createRef, getEntries } from "../lib/utils.js";

@@ -49,6 +49,18 @@ export default function transformSchemaObject(schemaObject, options) {

const enumType = schemaObject.enum.map(tsLiteral);
if ((Array.isArray(schemaObject.type) && schemaObject.type.includes("null")) || schemaObject.nullable) {
if (((Array.isArray(schemaObject.type) && schemaObject.type.includes("null")) || schemaObject.nullable) &&
!schemaObject.default) {
enumType.push(NULL);
}
return tsUnion(enumType);
const unionType = tsUnion(enumType);
if (options.ctx.enumValues && schemaObject.enum.every((v) => typeof v === "string" || typeof v === "number")) {
let enumValuesVariableName = parseRef(options.path ?? "").pointer.join("/");
enumValuesVariableName = enumValuesVariableName.replace("components/schemas", "");
enumValuesVariableName = `${enumValuesVariableName}Values`;
const enumValuesArray = tsArrayLiteralExpression(enumValuesVariableName, oapiRef(options.path ?? ""), schemaObject.enum, {
export: true,
readonly: true,
});
options.ctx.injectFooter.push(enumValuesArray);
}
return unionType;
}

@@ -121,3 +133,3 @@ function collectUnionCompositions(items) {

if (finalType) {
if (schemaObject.nullable) {
if (schemaObject.nullable && !schemaObject.default) {
return tsNullable([finalType]);

@@ -214,3 +226,3 @@ }

if (Array.isArray(schemaObject.type) && !Array.isArray(schemaObject)) {
let uniqueTypes = [];
const uniqueTypes = [];
if (Array.isArray(schemaObject.oneOf)) {

@@ -228,5 +240,12 @@ for (const t of schemaObject.type) {

else {
uniqueTypes = schemaObject.type.map((t) => t === "null" || t === null
? NULL
: transformSchemaObject({ ...schemaObject, type: t }, options));
for (const t of schemaObject.type) {
if (t === "null" || t === null) {
if (!schemaObject.default) {
uniqueTypes.push(NULL);
}
}
else {
uniqueTypes.push(transformSchemaObject({ ...schemaObject, type: t }, options));
}
}
}

@@ -233,0 +252,0 @@ return tsUnion(uniqueTypes);

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

}
export type SecurityRequirementObject = Record<keyof ComponentsObject["securitySchemes"], string[]>;
export type SecurityRequirementObject = {
[P in keyof ComponentsObject["securitySchemes"]]?: string[];
};
export interface OpenAPITSOptions {

@@ -326,2 +328,3 @@ additionalProperties?: boolean;

enum?: boolean;
enumValues?: boolean;
pathParamsAsTypes?: boolean;

@@ -342,2 +345,3 @@ propertiesRequiredByDefault?: boolean;

enum: boolean;
enumValues: boolean;
excludeDeprecated: boolean;

@@ -344,0 +348,0 @@ exportType: boolean;

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

@@ -46,3 +46,3 @@ "name": "Drew Powers",

"dependencies": {
"@redocly/openapi-core": "^1.12.0",
"@redocly/openapi-core": "^1.12.2",
"ansi-colors": "^4.1.3",

@@ -56,3 +56,3 @@ "parse-json": "^8.1.0",

"@types/js-yaml": "^4.0.9",
"@types/node": "^20.12.7",
"@types/node": "^20.12.12",
"degit": "^2.8.4",

@@ -64,4 +64,4 @@ "del-cli": "^5.1.0",

"typescript": "^5.4.5",
"vite-node": "^1.5.2",
"vitest": "^1.5.2"
"vite-node": "^1.6.0",
"vitest": "^1.6.0"
},

@@ -68,0 +68,0 @@ "scripts": {

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

enum: options.enum ?? false,
enumValues: options.enumValues ?? false,
excludeDeprecated: options.excludeDeprecated ?? false,

@@ -75,0 +76,0 @@ exportType: options.exportType ?? false,

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

) {
let enumName = name.replace(JS_ENUM_INVALID_CHARS_RE, (c) => {
const last = c[c.length - 1];
return JS_PROPERTY_INDEX_INVALID_CHARS_RE.test(last) ? "" : last.toUpperCase();
});
if (Number(name[0]) >= 0) {
enumName = `Value${name}`;
}
let enumName = sanitizeMemberName(name);
enumName = `${enumName[0].toUpperCase()}${enumName.substring(1)}`;

@@ -225,2 +219,58 @@ return ts.factory.createEnumDeclaration(

/** Create an exported TS array literal expression */
export function tsArrayLiteralExpression(
name: string,
elementType: ts.TypeNode,
values: (string | number)[],
options?: { export?: boolean; readonly?: boolean },
) {
let variableName = sanitizeMemberName(name);
variableName = `${variableName[0].toLowerCase()}${variableName.substring(1)}`;
const arrayType = options?.readonly
? ts.factory.createTypeReferenceNode("ReadonlyArray", [elementType])
: ts.factory.createArrayTypeNode(elementType);
return ts.factory.createVariableStatement(
options ? tsModifiers({ export: options.export ?? false }) : undefined,
ts.factory.createVariableDeclarationList(
[
ts.factory.createVariableDeclaration(
variableName,
undefined,
arrayType,
ts.factory.createArrayLiteralExpression(
values.map((value) => {
if (typeof value === "number") {
if (value < 0) {
return ts.factory.createPrefixUnaryExpression(
ts.SyntaxKind.MinusToken,
ts.factory.createNumericLiteral(Math.abs(value)),
);
} else {
return ts.factory.createNumericLiteral(value);
}
} else {
return ts.factory.createStringLiteral(value);
}
}),
),
),
],
ts.NodeFlags.Const,
),
);
}
function sanitizeMemberName(name: string) {
let sanitizedName = name.replace(JS_ENUM_INVALID_CHARS_RE, (c) => {
const last = c[c.length - 1];
return JS_PROPERTY_INDEX_INVALID_CHARS_RE.test(last) ? "" : last.toUpperCase();
});
if (Number(name[0]) >= 0) {
sanitizedName = `Value${name}`;
}
return sanitizedName;
}
/** Sanitize TS enum member expression */

@@ -299,3 +349,10 @@ export function tsEnumMember(value: string | number, metadata: { name?: string; description?: string } = {}) {

if (typeof value === "number") {
return ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(value));
const literal =
value < 0
? ts.factory.createPrefixUnaryExpression(
ts.SyntaxKind.MinusToken,
ts.factory.createNumericLiteral(Math.abs(value)),
)
: ts.factory.createNumericLiteral(value);
return ts.factory.createLiteralTypeNode(literal);
}

@@ -302,0 +359,0 @@ if (typeof value === "boolean") {

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

oapiRef,
tsArrayLiteralExpression,
tsEnum,

@@ -119,6 +120,32 @@ tsIntersection,

const enumType = schemaObject.enum.map(tsLiteral);
if ((Array.isArray(schemaObject.type) && schemaObject.type.includes("null")) || schemaObject.nullable) {
if (
((Array.isArray(schemaObject.type) && schemaObject.type.includes("null")) || schemaObject.nullable) &&
!schemaObject.default
) {
enumType.push(NULL);
}
return tsUnion(enumType);
const unionType = tsUnion(enumType);
// hoist array with valid enum values to top level if string/number enum and option is enabled
if (options.ctx.enumValues && schemaObject.enum.every((v) => typeof v === "string" || typeof v === "number")) {
let enumValuesVariableName = parseRef(options.path ?? "").pointer.join("/");
// allow #/components/schemas to have simpler names
enumValuesVariableName = enumValuesVariableName.replace("components/schemas", "");
enumValuesVariableName = `${enumValuesVariableName}Values`;
const enumValuesArray = tsArrayLiteralExpression(
enumValuesVariableName,
oapiRef(options.path ?? ""),
schemaObject.enum as (string | number)[],
{
export: true,
readonly: true,
},
);
options.ctx.injectFooter.push(enumValuesArray);
}
return unionType;
}

@@ -223,3 +250,3 @@

// deprecated nullable
if (schemaObject.nullable) {
if (schemaObject.nullable && !schemaObject.default) {
return tsNullable([finalType]);

@@ -346,3 +373,3 @@ }

// skip any primitive types that appear in oneOf as well
let uniqueTypes: ts.TypeNode[] = [];
const uniqueTypes: ts.TypeNode[] = [];
if (Array.isArray(schemaObject.oneOf)) {

@@ -366,7 +393,11 @@ for (const t of schemaObject.type) {

} else {
uniqueTypes = schemaObject.type.map((t) =>
t === "null" || t === null
? NULL
: transformSchemaObject({ ...schemaObject, type: t } as SchemaObject, options),
);
for (const t of schemaObject.type) {
if (t === "null" || t === null) {
if (!schemaObject.default) {
uniqueTypes.push(NULL);
}
} else {
uniqueTypes.push(transformSchemaObject({ ...schemaObject, type: t } as SchemaObject, options));
}
}
}

@@ -373,0 +404,0 @@ return tsUnion(uniqueTypes);

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

*/
export type SecurityRequirementObject = Record<keyof ComponentsObject["securitySchemes"], string[]>;
export type SecurityRequirementObject = {
[P in keyof ComponentsObject["securitySchemes"]]?: string[];
};

@@ -651,2 +653,4 @@ export interface OpenAPITSOptions {

enum?: boolean;
/** Export union values as arrays */
enumValues?: boolean;
/** (optional) Substitute path parameter names with their respective types */

@@ -676,2 +680,3 @@ pathParamsAsTypes?: boolean;

enum: boolean;
enumValues: boolean;
excludeDeprecated: boolean;

@@ -678,0 +683,0 @@ exportType: boolean;

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