From a9c764e318f7f358e7662b5cb94f97c5dd65f981 Mon Sep 17 00:00:00 2001 From: Lubos Date: Sun, 5 May 2024 07:39:44 +0100 Subject: [PATCH] fix: broken encoding --- .changeset/dry-socks-thank.md | 5 ++ packages/openapi-ts/src/compiler/classes.ts | 63 ++-------------- packages/openapi-ts/src/compiler/index.ts | 14 ++-- packages/openapi-ts/src/compiler/module.ts | 57 +++++++------- packages/openapi-ts/src/compiler/typedef.ts | 2 +- packages/openapi-ts/src/compiler/types.ts | 58 +++++++++++++- packages/openapi-ts/src/compiler/utils.ts | 75 +++++++++++++------ packages/openapi-ts/src/utils/escape.ts | 3 - .../openapi-ts/src/utils/write/services.ts | 8 +- packages/openapi-ts/src/utils/write/type.ts | 4 +- .../test/generated/v2/schemas.gen.ts.snap | 6 +- .../test/generated/v3/schemas.gen.ts.snap | 6 +- .../test/generated/v3/services.gen.ts.snap | 2 +- .../generated/v3_angular/services.gen.ts.snap | 2 +- .../generated/v3_client/services.gen.ts.snap | 2 +- .../v3_enums_typescript/services.gen.ts.snap | 2 +- .../v3_schemas_form/schemas.gen.ts.snap | 4 +- .../v3_schemas_json/schemas.gen.ts.snap | 6 +- 18 files changed, 181 insertions(+), 138 deletions(-) create mode 100644 .changeset/dry-socks-thank.md diff --git a/.changeset/dry-socks-thank.md b/.changeset/dry-socks-thank.md new file mode 100644 index 00000000..a7af8fb4 --- /dev/null +++ b/.changeset/dry-socks-thank.md @@ -0,0 +1,5 @@ +--- +"@hey-api/openapi-ts": patch +--- + +fix: broken encoding diff --git a/packages/openapi-ts/src/compiler/classes.ts b/packages/openapi-ts/src/compiler/classes.ts index 9a083e21..754df592 100644 --- a/packages/openapi-ts/src/compiler/classes.ts +++ b/packages/openapi-ts/src/compiler/classes.ts @@ -1,64 +1,15 @@ import ts from 'typescript'; import { createTypeNode } from './typedef'; -import { toExpression } from './types'; +import { + type AccessLevel, + type FunctionParameter, + toAccessLevelModifiers, + toExpression, + toParameterDeclarations, +} from './types'; import { addLeadingJSDocComment, Comments, isType } from './utils'; -type AccessLevel = 'public' | 'protected' | 'private'; - -export type FunctionParameter = { - accessLevel?: AccessLevel; - default?: any; - isReadOnly?: boolean; - isRequired?: boolean; - name: string; - type: any | ts.TypeNode; -}; - -/** - * Convert AccessLevel to proper TypeScript compiler API modifier. - * @param access - the access level. - * @returns ts.ModifierLike[] - */ -const toAccessLevelModifiers = (access?: AccessLevel): ts.ModifierLike[] => { - const keyword = - access === 'public' - ? ts.SyntaxKind.PublicKeyword - : access === 'protected' - ? ts.SyntaxKind.ProtectedKeyword - : access === 'private' - ? ts.SyntaxKind.PrivateKeyword - : undefined; - const modifiers: ts.ModifierLike[] = []; - if (keyword) { - modifiers.push(ts.factory.createModifier(keyword)); - } - return modifiers; -}; - -/** - * Convert parameters to the declaration array expected by compiler API. - * @param parameters - the parameters to conver to declarations - * @returns ts.ParameterDeclaration[] - */ -export const toParameterDeclarations = (parameters: FunctionParameter[]) => - parameters.map((p) => { - const modifiers = toAccessLevelModifiers(p.accessLevel); - if (p.isReadOnly) { - modifiers.push(ts.factory.createModifier(ts.SyntaxKind.ReadonlyKeyword)); - } - return ts.factory.createParameterDeclaration( - modifiers, - undefined, - ts.factory.createIdentifier(p.name), - p.isRequired !== undefined && !p.isRequired - ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) - : undefined, - p.type !== undefined ? createTypeNode(p.type) : undefined, - p.default !== undefined ? toExpression({ value: p.default }) : undefined, - ); - }); - /** * Create a class constructor declaration. * @param accessLevel - the access level of the constructor. diff --git a/packages/openapi-ts/src/compiler/index.ts b/packages/openapi-ts/src/compiler/index.ts index a993ed5f..eea5cded 100644 --- a/packages/openapi-ts/src/compiler/index.ts +++ b/packages/openapi-ts/src/compiler/index.ts @@ -10,8 +10,8 @@ import * as typedef from './typedef'; import * as types from './types'; import { stringToTsNodes, tsNodeToString } from './utils'; -export type { FunctionParameter } from './classes'; export type { Property } from './typedef'; +export type { FunctionParameter } from './types'; export type { Comments } from './utils'; export type { ClassElement, Node, TypeNode } from 'typescript'; @@ -52,11 +52,11 @@ export class TypeScriptFile { } } - public add(...nodes: Array): void { + public add(...nodes: Array) { this._items = [...this._items, ...nodes]; } - public addImport(...params: Parameters): void { + public addImport(...params: Parameters) { this._imports = [...this._imports, compiler.import.named(...params)]; } @@ -94,13 +94,15 @@ export class TypeScriptFile { if (this._imports.length) { output = [ ...output, - this._imports.map((v) => tsNodeToString(v)).join('\n'), + this._imports.map((node) => tsNodeToString({ node })).join('\n'), ]; } output = [ ...output, - ...this._items.map((v) => - typeof v === 'string' ? v : tsNodeToString(v), + ...this._items.map((node) => + typeof node === 'string' + ? node + : tsNodeToString({ node, unescape: true }), ), ]; return output.join(seperator); diff --git a/packages/openapi-ts/src/compiler/module.ts b/packages/openapi-ts/src/compiler/module.ts index f59e5f6a..ab97d933 100644 --- a/packages/openapi-ts/src/compiler/module.ts +++ b/packages/openapi-ts/src/compiler/module.ts @@ -1,6 +1,11 @@ import ts from 'typescript'; -import { addLeadingJSDocComment, type Comments, ots } from './utils'; +import { + addLeadingJSDocComment, + type Comments, + type ImportItemObject, + ots, +} from './utils'; /** * Create export all declaration. Example: `export * from './y'`. @@ -15,9 +20,7 @@ export const createExportAllDeclaration = (module: string) => ots.string(module), ); -type ImportItem = - | { name: string; isTypeOnly?: boolean; alias?: string } - | string; +type ImportItem = ImportItemObject | string; /** * Create a named export declaration. Example: `export { X } from './y'`. @@ -103,28 +106,30 @@ export const createNamedImportDeclarations = ( items: Array | ImportItem, module: string, ): ts.ImportDeclaration => { - items = Array.isArray(items) ? items : [items]; - const isAllTypes = items.every((i) => typeof i === 'object' && i.isTypeOnly); - return ts.factory.createImportDeclaration( + const importedTypes = Array.isArray(items) ? items : [items]; + const isTypeOnly = !importedTypes.some( + (item) => typeof item !== 'object' || !item.isTypeOnly, + ); + const elements = importedTypes.map((item) => { + const importedType: ImportItemObject = + typeof item === 'string' ? { name: item } : item; + return ots.import({ + alias: importedType.alias, + isTypeOnly: isTypeOnly ? false : Boolean(importedType.isTypeOnly), + name: importedType.name, + }); + }); + const namedBindings = ts.factory.createNamedImports(elements); + const importClause = ts.factory.createImportClause( + isTypeOnly, undefined, - ts.factory.createImportClause( - isAllTypes, - undefined, - ts.factory.createNamedImports( - items.map((item) => { - const { - name, - isTypeOnly = undefined, - alias = undefined, - } = typeof item === 'string' ? { name: item } : item; - return ots.import( - name, - isAllTypes ? false : Boolean(isTypeOnly), - alias, - ); - }), - ), - ), - ots.string(module), + namedBindings, + ); + const moduleSpecifier = ots.string(module); + const statement = ts.factory.createImportDeclaration( + undefined, + importClause, + moduleSpecifier, ); + return statement; }; diff --git a/packages/openapi-ts/src/compiler/typedef.ts b/packages/openapi-ts/src/compiler/typedef.ts index 9aad19bf..23bbc77d 100644 --- a/packages/openapi-ts/src/compiler/typedef.ts +++ b/packages/openapi-ts/src/compiler/typedef.ts @@ -170,7 +170,7 @@ export const createTypeRecordNode = ( const node = createTypeInterfaceNode([ { isRequired: true, - name: `[key: ${tsNodeToString(keyNode)}]`, + name: `[key: ${tsNodeToString({ node: keyNode, unescape: true })}]`, type: valueNode, }, ]); diff --git a/packages/openapi-ts/src/compiler/types.ts b/packages/openapi-ts/src/compiler/types.ts index 50cb514c..86d13a0c 100644 --- a/packages/openapi-ts/src/compiler/types.ts +++ b/packages/openapi-ts/src/compiler/types.ts @@ -1,9 +1,19 @@ import ts from 'typescript'; -import { type FunctionParameter, toParameterDeclarations } from './classes'; import { createTypeNode } from './typedef'; import { addLeadingJSDocComment, type Comments, isType, ots } from './utils'; +export type AccessLevel = 'public' | 'protected' | 'private'; + +export type FunctionParameter = { + accessLevel?: AccessLevel; + default?: any; + isReadOnly?: boolean; + isRequired?: boolean; + name: string; + type: any | ts.TypeNode; +}; + /** * Convert an unknown value to an expression. * @param identifiers - list of keys that are treated as identifiers. @@ -48,6 +58,52 @@ export const toExpression = ({ } }; +/** + * Convert AccessLevel to proper TypeScript compiler API modifier. + * @param access - the access level. + * @returns ts.ModifierLike[] + */ +export const toAccessLevelModifiers = ( + access?: AccessLevel, +): ts.ModifierLike[] => { + const keyword = + access === 'public' + ? ts.SyntaxKind.PublicKeyword + : access === 'protected' + ? ts.SyntaxKind.ProtectedKeyword + : access === 'private' + ? ts.SyntaxKind.PrivateKeyword + : undefined; + const modifiers: ts.ModifierLike[] = []; + if (keyword) { + modifiers.push(ts.factory.createModifier(keyword)); + } + return modifiers; +}; + +/** + * Convert parameters to the declaration array expected by compiler API. + * @param parameters - the parameters to conver to declarations + * @returns ts.ParameterDeclaration[] + */ +export const toParameterDeclarations = (parameters: FunctionParameter[]) => + parameters.map((p) => { + const modifiers = toAccessLevelModifiers(p.accessLevel); + if (p.isReadOnly) { + modifiers.push(ts.factory.createModifier(ts.SyntaxKind.ReadonlyKeyword)); + } + return ts.factory.createParameterDeclaration( + modifiers, + undefined, + ts.factory.createIdentifier(p.name), + p.isRequired !== undefined && !p.isRequired + ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) + : undefined, + p.type !== undefined ? createTypeNode(p.type) : undefined, + p.default !== undefined ? toExpression({ value: p.default }) : undefined, + ); + }); + /** * Create Function type expression. */ diff --git a/packages/openapi-ts/src/compiler/utils.ts b/packages/openapi-ts/src/compiler/utils.ts index a33e2ada..958300e7 100644 --- a/packages/openapi-ts/src/compiler/utils.ts +++ b/packages/openapi-ts/src/compiler/utils.ts @@ -3,6 +3,12 @@ import ts from 'typescript'; import { getConfig } from '../utils/config'; import { unescapeName } from '../utils/escape'; +export interface ImportItemObject { + alias?: string; + isTypeOnly?: boolean; + name: string; +} + export const CONFIG = { newLine: ts.NewLineKind.LineFeed, scriptKind: ts.ScriptKind.TS, @@ -23,19 +29,40 @@ export const createSourceFile = (sourceText: string) => const blankSourceFile = createSourceFile(''); +const unescapeUnicode = (value: string) => + value.replace(/\\u([0-9a-fA-F]{4})/g, (_, hex: string) => + String.fromCharCode(Number.parseInt(hex, 16)), + ); + /** - * Print a typescript node to a string. - * @param node - the node to print. + * Print a TypeScript node to a string. + * @param node the node to print * @returns string */ -export function tsNodeToString(node: ts.Node): string { +export function tsNodeToString({ + node, + unescape = false, +}: { + node: ts.Node; + unescape?: boolean; +}): string { const result = printer.printNode( ts.EmitHint.Unspecified, node, blankSourceFile, ); + + if (!unescape) { + return result; + } + try { - return decodeURIComponent(result); + /** + * TypeScript Compiler API escapes unicode characters by default and there + * is no way to disable this behavior + * {@link https://github.com/microsoft/TypeScript/issues/36174} + */ + return unescapeUnicode(result); } catch { if (getConfig().debug) { console.warn('Could not decode value:', result); @@ -46,11 +73,11 @@ export function tsNodeToString(node: ts.Node): string { /** * Convert a string to a TypeScript Node - * @param s - the string to convert. + * @param value the string to convert. * @returns ts.Node */ -export function stringToTsNodes(s: string): ts.Node { - const file = createSourceFile(s); +export function stringToTsNodes(value: string): ts.Node { + const file = createSourceFile(value); return file.statements[0]; } @@ -67,13 +94,13 @@ export const ots = { alias ? ts.factory.createIdentifier(encodeURIComponent(alias)) : n, ); }, - import: (name: string, isTypeOnly?: boolean, alias?: string) => { - const n = ts.factory.createIdentifier(encodeURIComponent(name)); - return ts.factory.createImportSpecifier( - isTypeOnly ?? false, - alias ? n : undefined, - alias ? ts.factory.createIdentifier(encodeURIComponent(alias)) : n, - ); + import: ({ alias, isTypeOnly = false, name }: ImportItemObject) => { + const nameNode = ts.factory.createIdentifier(name); + if (alias) { + const aliasNode = ts.factory.createIdentifier(alias); + return ts.factory.createImportSpecifier(isTypeOnly, nameNode, aliasNode); + } + return ts.factory.createImportSpecifier(isTypeOnly, undefined, nameNode); }, // Create a numeric expression, handling negative numbers. number: (value: number) => { @@ -87,26 +114,26 @@ export const ots = { }, // Create a string literal. This handles strings that start with '`' or "'". string: (value: string, unescape = false) => { + let text = value; if (unescape) { - value = unescapeName(value); + text = unescapeName(text); } - const hasBothQuotes = value.includes("'") && value.includes('"'); - const hasNewlines = value.includes('\n'); - const hasUnescapedBackticks = value.startsWith('`'); - const isBacktickEscaped = value.startsWith('\\`') && value.endsWith('\\`'); + const hasBothQuotes = text.includes("'") && text.includes('"'); + const hasNewlines = text.includes('\n'); + const hasUnescapedBackticks = text.startsWith('`'); + const isBacktickEscaped = text.startsWith('\\`') && text.endsWith('\\`'); if ( (hasNewlines || hasBothQuotes || hasUnescapedBackticks) && !isBacktickEscaped ) { - value = `\`${value.replace(/(? { const jsdoc = ts.factory.createJSDocComment( ts.factory.createNodeArray(jsdocTexts), ); - const cleanedJsdoc = tsNodeToString(jsdoc) + const cleanedJsdoc = tsNodeToString({ node: jsdoc, unescape: true }) .replace('/*', '') .replace('* */', ''); diff --git a/packages/openapi-ts/src/utils/escape.ts b/packages/openapi-ts/src/utils/escape.ts index 6746cf31..c7153b0e 100644 --- a/packages/openapi-ts/src/utils/escape.ts +++ b/packages/openapi-ts/src/utils/escape.ts @@ -29,6 +29,3 @@ export const escapeComment = (value: string) => .replace(/\*\//g, '*') .replace(/\/\*/g, '*') .replace(/\r?\n(.*)/g, (_l, w) => EOL + w.trim()); - -export const escapeDescription = (value: string) => - value.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\${/g, '\\${'); diff --git a/packages/openapi-ts/src/utils/write/services.ts b/packages/openapi-ts/src/utils/write/services.ts index 80225b86..44ea1ab6 100644 --- a/packages/openapi-ts/src/utils/write/services.ts +++ b/packages/openapi-ts/src/utils/write/services.ts @@ -11,7 +11,7 @@ import type { ObjectValue } from '../../compiler/types'; import type { Operation, OperationParameter, Service } from '../../openApi'; import type { Client } from '../../types/client'; import { getConfig } from '../config'; -import { escapeComment, escapeDescription, escapeName } from '../escape'; +import { escapeComment, escapeName } from '../escape'; import { modelIsRequired } from '../required'; import { transformServiceName } from '../transform'; import { unique } from '../unique'; @@ -205,7 +205,7 @@ const toRequestOptions = (operation: Operation) => { if (operation.errors.length) { const errors: Record = {}; operation.errors.forEach((err) => { - errors[err.code] = escapeDescription(err.description ?? ''); + errors[err.code] = err.description ?? ''; }); obj.errors = errors; } @@ -423,9 +423,9 @@ export const processServices = async ({ // Import all models required by the services. if (files.types && !files.types.isEmpty()) { - const models = imports + const importedTypes = imports .filter(unique) .map((name) => ({ isTypeOnly: true, name })); - files.services?.addImport(models, `./${files.types.getName(false)}`); + files.services?.addImport(importedTypes, `./${files.types.getName(false)}`); } }; diff --git a/packages/openapi-ts/src/utils/write/type.ts b/packages/openapi-ts/src/utils/write/type.ts index 33edbe1a..68a6a596 100644 --- a/packages/openapi-ts/src/utils/write/type.ts +++ b/packages/openapi-ts/src/utils/write/type.ts @@ -62,14 +62,14 @@ const typeDict = (model: Model) => { const typeUnion = (model: Model) => { const models = model.properties; const types = models - .map((m) => compiler.utils.toString(toType(m))) + .map((m) => compiler.utils.toString({ node: toType(m), unescape: true })) .filter(unique); return compiler.typedef.union(types, model.isNullable); }; const typeIntersect = (model: Model) => { const types = model.properties - .map((m) => compiler.utils.toString(toType(m))) + .map((m) => compiler.utils.toString({ node: toType(m), unescape: true })) .filter(unique); return compiler.typedef.intersect(types, model.isNullable); }; diff --git a/packages/openapi-ts/test/__snapshots__/test/generated/v2/schemas.gen.ts.snap b/packages/openapi-ts/test/__snapshots__/test/generated/v2/schemas.gen.ts.snap index 50e7f544..38e5e435 100644 --- a/packages/openapi-ts/test/__snapshots__/test/generated/v2/schemas.gen.ts.snap +++ b/packages/openapi-ts/test/__snapshots__/test/generated/v2/schemas.gen.ts.snap @@ -19,7 +19,7 @@ export const $CommentWithBackticksAndQuotes = { } as const; export const $CommentWithSlashes = { - description: 'Testing slashes in string: \backwards\\\ and /forwards/// should work', + description: 'Testing slashes in string: \\backwards\\\\\\ and /forwards/// should work', type: 'integer' } as const; @@ -590,11 +590,11 @@ export const $ModelWithPattern = { }, id: { type: 'string', - pattern: '^\d{2}-\d{3}-\d{4}$' + pattern: '^\\d{2}-\\d{3}-\\d{4}$' }, text: { type: 'string', - pattern: '^\w+$' + pattern: '^\\w+$' }, patternWithSingleQuotes: { type: 'string', diff --git a/packages/openapi-ts/test/__snapshots__/test/generated/v3/schemas.gen.ts.snap b/packages/openapi-ts/test/__snapshots__/test/generated/v3/schemas.gen.ts.snap index 90c72931..c32eebbf 100644 --- a/packages/openapi-ts/test/__snapshots__/test/generated/v3/schemas.gen.ts.snap +++ b/packages/openapi-ts/test/__snapshots__/test/generated/v3/schemas.gen.ts.snap @@ -27,7 +27,7 @@ export const $CommentWithBackticksAndQuotes = { } as const; export const $CommentWithSlashes = { - description: 'Testing slashes in string: \backwards\\\ and /forwards/// should work', + description: 'Testing slashes in string: \\backwards\\\\\\ and /forwards/// should work', type: 'integer' } as const; @@ -1184,11 +1184,11 @@ export const $ModelWithPattern = { }, id: { type: 'string', - pattern: '^\d{2}-\d{3}-\d{4}$' + pattern: '^\\d{2}-\\d{3}-\\d{4}$' }, text: { type: 'string', - pattern: '^\w+$' + pattern: '^\\w+$' }, patternWithSingleQuotes: { type: 'string', diff --git a/packages/openapi-ts/test/__snapshots__/test/generated/v3/services.gen.ts.snap b/packages/openapi-ts/test/__snapshots__/test/generated/v3/services.gen.ts.snap index c5d58d31..19842250 100644 --- a/packages/openapi-ts/test/__snapshots__/test/generated/v3/services.gen.ts.snap +++ b/packages/openapi-ts/test/__snapshots__/test/generated/v3/services.gen.ts.snap @@ -736,7 +736,7 @@ export class ComplexService { parameterReference: data.parameterReference }, errors: { - 400: '400 \`server\` error', + 400: '400 `server` error', 500: '500 server error' } }); diff --git a/packages/openapi-ts/test/__snapshots__/test/generated/v3_angular/services.gen.ts.snap b/packages/openapi-ts/test/__snapshots__/test/generated/v3_angular/services.gen.ts.snap index 3a90d042..73b29dfe 100644 --- a/packages/openapi-ts/test/__snapshots__/test/generated/v3_angular/services.gen.ts.snap +++ b/packages/openapi-ts/test/__snapshots__/test/generated/v3_angular/services.gen.ts.snap @@ -833,7 +833,7 @@ export class ComplexService { parameterReference: data.parameterReference }, errors: { - 400: '400 \`server\` error', + 400: '400 `server` error', 500: '500 server error' } }); diff --git a/packages/openapi-ts/test/__snapshots__/test/generated/v3_client/services.gen.ts.snap b/packages/openapi-ts/test/__snapshots__/test/generated/v3_client/services.gen.ts.snap index fdb12aed..8e050efe 100644 --- a/packages/openapi-ts/test/__snapshots__/test/generated/v3_client/services.gen.ts.snap +++ b/packages/openapi-ts/test/__snapshots__/test/generated/v3_client/services.gen.ts.snap @@ -773,7 +773,7 @@ export class ComplexService { parameterReference: data.parameterReference }, errors: { - 400: '400 \`server\` error', + 400: '400 `server` error', 500: '500 server error' } }); diff --git a/packages/openapi-ts/test/__snapshots__/test/generated/v3_enums_typescript/services.gen.ts.snap b/packages/openapi-ts/test/__snapshots__/test/generated/v3_enums_typescript/services.gen.ts.snap index c5d58d31..19842250 100644 --- a/packages/openapi-ts/test/__snapshots__/test/generated/v3_enums_typescript/services.gen.ts.snap +++ b/packages/openapi-ts/test/__snapshots__/test/generated/v3_enums_typescript/services.gen.ts.snap @@ -736,7 +736,7 @@ export class ComplexService { parameterReference: data.parameterReference }, errors: { - 400: '400 \`server\` error', + 400: '400 `server` error', 500: '500 server error' } }); diff --git a/packages/openapi-ts/test/__snapshots__/test/generated/v3_schemas_form/schemas.gen.ts.snap b/packages/openapi-ts/test/__snapshots__/test/generated/v3_schemas_form/schemas.gen.ts.snap index b05ad344..9fdcd20b 100644 --- a/packages/openapi-ts/test/__snapshots__/test/generated/v3_schemas_form/schemas.gen.ts.snap +++ b/packages/openapi-ts/test/__snapshots__/test/generated/v3_schemas_form/schemas.gen.ts.snap @@ -1079,11 +1079,11 @@ export const $ModelWithPattern = { }, id: { type: 'string', - pattern: '^\d{2}-\d{3}-\d{4}$' + pattern: '^\\d{2}-\\d{3}-\\d{4}$' }, text: { type: 'string', - pattern: '^\w+$' + pattern: '^\\w+$' }, patternWithSingleQuotes: { type: 'string', diff --git a/packages/openapi-ts/test/__snapshots__/test/generated/v3_schemas_json/schemas.gen.ts.snap b/packages/openapi-ts/test/__snapshots__/test/generated/v3_schemas_json/schemas.gen.ts.snap index 90c72931..c32eebbf 100644 --- a/packages/openapi-ts/test/__snapshots__/test/generated/v3_schemas_json/schemas.gen.ts.snap +++ b/packages/openapi-ts/test/__snapshots__/test/generated/v3_schemas_json/schemas.gen.ts.snap @@ -27,7 +27,7 @@ export const $CommentWithBackticksAndQuotes = { } as const; export const $CommentWithSlashes = { - description: 'Testing slashes in string: \backwards\\\ and /forwards/// should work', + description: 'Testing slashes in string: \\backwards\\\\\\ and /forwards/// should work', type: 'integer' } as const; @@ -1184,11 +1184,11 @@ export const $ModelWithPattern = { }, id: { type: 'string', - pattern: '^\d{2}-\d{3}-\d{4}$' + pattern: '^\\d{2}-\\d{3}-\\d{4}$' }, text: { type: 'string', - pattern: '^\w+$' + pattern: '^\\w+$' }, patternWithSingleQuotes: { type: 'string',