diff --git a/src/openApi/v2/parser/escapeName.ts b/src/openApi/v2/parser/escapeName.ts index 9d6816c10..1fb196c63 100644 --- a/src/openApi/v2/parser/escapeName.ts +++ b/src/openApi/v2/parser/escapeName.ts @@ -1,6 +1,8 @@ +import validTypescriptIdentifierRegex from '../../../utils/validTypescriptIdentifierRegex'; + export const escapeName = (value: string): string => { if (value || value === '') { - const validName = /^[a-zA-Z_$][\w$]+$/g.test(value); + const validName = validTypescriptIdentifierRegex.test(value); if (!validName) { return `'${value}'`; } diff --git a/src/openApi/v2/parser/getEnum.ts b/src/openApi/v2/parser/getEnum.ts index 64c7ca8b5..eb671f679 100644 --- a/src/openApi/v2/parser/getEnum.ts +++ b/src/openApi/v2/parser/getEnum.ts @@ -1,4 +1,5 @@ import type { Enum } from '../../../client/interfaces/Enum'; +import sanitizeEnumName from '../../../utils/sanitizeEnumName'; export const getEnum = (values?: (string | number)[]): Enum[] => { if (Array.isArray(values)) { @@ -19,11 +20,7 @@ export const getEnum = (values?: (string | number)[]): Enum[] => { }; } return { - name: String(value) - .replace(/\W+/g, '_') - .replace(/^(\d+)/g, '_$1') - .replace(/([a-z])([A-Z]+)/g, '$1_$2') - .toUpperCase(), + name: sanitizeEnumName(String(value)), value: `'${value.replace(/'/g, "\\'")}'`, type: 'string', description: null, diff --git a/src/openApi/v2/parser/getOperationName.ts b/src/openApi/v2/parser/getOperationName.ts index 124bf66bd..4734bfbc9 100644 --- a/src/openApi/v2/parser/getOperationName.ts +++ b/src/openApi/v2/parser/getOperationName.ts @@ -1,5 +1,7 @@ import camelCase from 'camelcase'; +import sanitizeOperationName from '../../../utils/sanitizeOperationName'; + /** * Convert the input value to a correct operation (method) classname. * This will use the operation ID - if available - and otherwise fallback @@ -7,12 +9,7 @@ import camelCase from 'camelcase'; */ export const getOperationName = (url: string, method: string, operationId?: string): string => { if (operationId) { - return camelCase( - operationId - .replace(/^[^a-zA-Z]+/g, '') - .replace(/[^\w\-]+/g, '-') - .trim() - ); + return camelCase(sanitizeOperationName(operationId).trim()); } const urlWithoutPlaceholders = url diff --git a/src/openApi/v2/parser/getOperationParameterName.ts b/src/openApi/v2/parser/getOperationParameterName.ts index 3a7fb408b..fc7f21594 100644 --- a/src/openApi/v2/parser/getOperationParameterName.ts +++ b/src/openApi/v2/parser/getOperationParameterName.ts @@ -1,15 +1,13 @@ import camelCase from 'camelcase'; import { reservedWords } from '../../../utils/reservedWords'; +import sanitizeOperationParameterName from '../../../utils/sanitizeOperationParameterName'; /** * Replaces any invalid characters from a parameter name. * For example: 'filter.someProperty' becomes 'filterSomeProperty'. */ export const getOperationParameterName = (value: string): string => { - const clean = value - .replace(/^[^a-zA-Z]+/g, '') - .replace(/[^\w\-]+/g, '-') - .trim(); + const clean = sanitizeOperationParameterName(value).trim(); return camelCase(clean).replace(reservedWords, '_$1'); }; diff --git a/src/openApi/v2/parser/getServiceName.ts b/src/openApi/v2/parser/getServiceName.ts index b5b1718f2..2dfff844e 100644 --- a/src/openApi/v2/parser/getServiceName.ts +++ b/src/openApi/v2/parser/getServiceName.ts @@ -1,13 +1,12 @@ import camelCase from 'camelcase'; +import sanitizeServiceName from '../../../utils/sanitizeServiceName'; + /** * Convert the input value to a correct service name. This converts * the input string to PascalCase. */ export const getServiceName = (value: string): string => { - const clean = value - .replace(/^[^a-zA-Z]+/g, '') - .replace(/[^\w\-]+/g, '-') - .trim(); + const clean = sanitizeServiceName(value).trim(); return camelCase(clean, { pascalCase: true }); }; diff --git a/src/openApi/v2/parser/getType.ts b/src/openApi/v2/parser/getType.ts index 6caa1e015..594fa6106 100644 --- a/src/openApi/v2/parser/getType.ts +++ b/src/openApi/v2/parser/getType.ts @@ -1,10 +1,9 @@ import type { Type } from '../../../client/interfaces/Type'; +import sanitizeTypeName from '../../../utils/sanitizeTypeName'; import { getMappedType } from './getMappedType'; import { stripNamespace } from './stripNamespace'; -const encode = (value: string): string => { - return value.replace(/^[^a-zA-Z_$]+/g, '').replace(/[^\w$]+/g, '_'); -}; +const encode = (value: string): string => sanitizeTypeName(value); /** * Parse any string value into a type object. diff --git a/src/openApi/v3/parser/escapeName.ts b/src/openApi/v3/parser/escapeName.ts index 9d6816c10..1fb196c63 100644 --- a/src/openApi/v3/parser/escapeName.ts +++ b/src/openApi/v3/parser/escapeName.ts @@ -1,6 +1,8 @@ +import validTypescriptIdentifierRegex from '../../../utils/validTypescriptIdentifierRegex'; + export const escapeName = (value: string): string => { if (value || value === '') { - const validName = /^[a-zA-Z_$][\w$]+$/g.test(value); + const validName = validTypescriptIdentifierRegex.test(value); if (!validName) { return `'${value}'`; } diff --git a/src/openApi/v3/parser/getEnum.ts b/src/openApi/v3/parser/getEnum.ts index 64c7ca8b5..eb671f679 100644 --- a/src/openApi/v3/parser/getEnum.ts +++ b/src/openApi/v3/parser/getEnum.ts @@ -1,4 +1,5 @@ import type { Enum } from '../../../client/interfaces/Enum'; +import sanitizeEnumName from '../../../utils/sanitizeEnumName'; export const getEnum = (values?: (string | number)[]): Enum[] => { if (Array.isArray(values)) { @@ -19,11 +20,7 @@ export const getEnum = (values?: (string | number)[]): Enum[] => { }; } return { - name: String(value) - .replace(/\W+/g, '_') - .replace(/^(\d+)/g, '_$1') - .replace(/([a-z])([A-Z]+)/g, '$1_$2') - .toUpperCase(), + name: sanitizeEnumName(String(value)), value: `'${value.replace(/'/g, "\\'")}'`, type: 'string', description: null, diff --git a/src/openApi/v3/parser/getOperationName.ts b/src/openApi/v3/parser/getOperationName.ts index 124bf66bd..4734bfbc9 100644 --- a/src/openApi/v3/parser/getOperationName.ts +++ b/src/openApi/v3/parser/getOperationName.ts @@ -1,5 +1,7 @@ import camelCase from 'camelcase'; +import sanitizeOperationName from '../../../utils/sanitizeOperationName'; + /** * Convert the input value to a correct operation (method) classname. * This will use the operation ID - if available - and otherwise fallback @@ -7,12 +9,7 @@ import camelCase from 'camelcase'; */ export const getOperationName = (url: string, method: string, operationId?: string): string => { if (operationId) { - return camelCase( - operationId - .replace(/^[^a-zA-Z]+/g, '') - .replace(/[^\w\-]+/g, '-') - .trim() - ); + return camelCase(sanitizeOperationName(operationId).trim()); } const urlWithoutPlaceholders = url diff --git a/src/openApi/v3/parser/getOperationParameterName.ts b/src/openApi/v3/parser/getOperationParameterName.ts index a3caa291c..fc7f21594 100644 --- a/src/openApi/v3/parser/getOperationParameterName.ts +++ b/src/openApi/v3/parser/getOperationParameterName.ts @@ -1,16 +1,13 @@ import camelCase from 'camelcase'; import { reservedWords } from '../../../utils/reservedWords'; +import sanitizeOperationParameterName from '../../../utils/sanitizeOperationParameterName'; /** * Replaces any invalid characters from a parameter name. * For example: 'filter.someProperty' becomes 'filterSomeProperty'. */ export const getOperationParameterName = (value: string): string => { - const clean = value - .replace(/^[^a-zA-Z]+/g, '') - .replace('[]', 'Array') - .replace(/[^\w\-]+/g, '-') - .trim(); + const clean = sanitizeOperationParameterName(value).trim(); return camelCase(clean).replace(reservedWords, '_$1'); }; diff --git a/src/openApi/v3/parser/getServiceName.spec.ts b/src/openApi/v3/parser/getServiceName.spec.ts index 77c420d3b..c1de86020 100644 --- a/src/openApi/v3/parser/getServiceName.spec.ts +++ b/src/openApi/v3/parser/getServiceName.spec.ts @@ -9,5 +9,6 @@ describe('getServiceName', () => { expect(getServiceName('@fooBar')).toEqual('FooBar'); expect(getServiceName('$fooBar')).toEqual('FooBar'); expect(getServiceName('123fooBar')).toEqual('FooBar'); + expect(getServiceName('non-ascii-æøåÆØÅöôêÊ字符串')).toEqual('NonAsciiÆøåÆøÅöôêÊ字符串'); }); }); diff --git a/src/openApi/v3/parser/getServiceName.ts b/src/openApi/v3/parser/getServiceName.ts index b5b1718f2..2dfff844e 100644 --- a/src/openApi/v3/parser/getServiceName.ts +++ b/src/openApi/v3/parser/getServiceName.ts @@ -1,13 +1,12 @@ import camelCase from 'camelcase'; +import sanitizeServiceName from '../../../utils/sanitizeServiceName'; + /** * Convert the input value to a correct service name. This converts * the input string to PascalCase. */ export const getServiceName = (value: string): string => { - const clean = value - .replace(/^[^a-zA-Z]+/g, '') - .replace(/[^\w\-]+/g, '-') - .trim(); + const clean = sanitizeServiceName(value).trim(); return camelCase(clean, { pascalCase: true }); }; diff --git a/src/openApi/v3/parser/getType.ts b/src/openApi/v3/parser/getType.ts index e8ef4733d..4cb82d367 100644 --- a/src/openApi/v3/parser/getType.ts +++ b/src/openApi/v3/parser/getType.ts @@ -1,11 +1,10 @@ import type { Type } from '../../../client/interfaces/Type'; import { isDefined } from '../../../utils/isDefined'; +import sanitizeTypeName from '../../../utils/sanitizeTypeName'; import { getMappedType } from './getMappedType'; import { stripNamespace } from './stripNamespace'; -const encode = (value: string): string => { - return value.replace(/^[^a-zA-Z_$]+/g, '').replace(/[^\w$]+/g, '_'); -}; +const encode = (value: string): string => sanitizeTypeName(value); /** * Parse any string value into a type object. diff --git a/src/utils/sanitizeEnumName.spec.ts b/src/utils/sanitizeEnumName.spec.ts new file mode 100644 index 000000000..36db89743 --- /dev/null +++ b/src/utils/sanitizeEnumName.spec.ts @@ -0,0 +1,11 @@ +import sanitizeEnumName from './sanitizeEnumName'; + +describe('sanitizeEnumName', () => { + it('should replace illegal characters', () => { + expect(sanitizeEnumName('abc')).toEqual('ABC'); + expect(sanitizeEnumName('æbc')).toEqual('ÆBC'); + expect(sanitizeEnumName('æb.c')).toEqual('ÆB_C'); + expect(sanitizeEnumName('1æb.c')).toEqual('_1ÆB_C'); + expect(sanitizeEnumName("'quoted'")).toEqual('_QUOTED_'); + }); +}); diff --git a/src/utils/sanitizeEnumName.ts b/src/utils/sanitizeEnumName.ts new file mode 100644 index 000000000..1f1a6080c --- /dev/null +++ b/src/utils/sanitizeEnumName.ts @@ -0,0 +1,18 @@ +/** + * Sanitizes names of enums, so they are valid typescript identifiers of a certain form. + * + * 1: Replace all characters not legal as part of identifier with '_' + * 2: Add '_' prefix if first character of enum name has character not legal for start of identifier + * 3: Add '_' where the string transitions from lowercase to uppercase + * 4: Transform the whole string to uppercase + * + * Javascript identifier regexp pattern retrieved from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers + */ +const sanitizeEnumName = (name: string) => + name + .replace(/[^$\u200c\u200d\p{ID_Continue}]/gu, '_') + .replace(/^([^$_\p{ID_Start}])/u, '_$1') + .replace(/(\p{Lowercase})(\p{Uppercase}+)/gu, '$1_$2') + .toUpperCase(); + +export default sanitizeEnumName; diff --git a/src/utils/sanitizeOperationName.ts b/src/utils/sanitizeOperationName.ts new file mode 100644 index 000000000..512b0d5a4 --- /dev/null +++ b/src/utils/sanitizeOperationName.ts @@ -0,0 +1,7 @@ +import sanitizeServiceName from './sanitizeServiceName'; + +/** + * sanitizeOperationName does the same as sanitizeServiceName. + */ +const sanitizeOperationName = sanitizeServiceName; +export default sanitizeOperationName; diff --git a/src/utils/sanitizeOperationParameterName.ts b/src/utils/sanitizeOperationParameterName.ts new file mode 100644 index 000000000..8c157ecf9 --- /dev/null +++ b/src/utils/sanitizeOperationParameterName.ts @@ -0,0 +1,7 @@ +import sanitizeOperationName from './sanitizeOperationName'; + +const sanitizeOperationParameterName = (name: string): string => { + const withoutBrackets = name.replace('[]', 'Array'); + return sanitizeOperationName(withoutBrackets); +}; +export default sanitizeOperationParameterName; diff --git a/src/utils/sanitizeServiceName.ts b/src/utils/sanitizeServiceName.ts new file mode 100644 index 000000000..92c7e116b --- /dev/null +++ b/src/utils/sanitizeServiceName.ts @@ -0,0 +1,18 @@ +/** + * Sanitizes service names, so they are valid typescript identifiers of a certain form. + * + * 1: Remove any leading characters that are illegal as starting character of a typescript identifier. + * 2: Replace illegal characters in remaining part of type name with underscore (-). + * + * Step 1 should perhaps instead also replace illegal characters with underscore, or prefix with it, like sanitizeEnumName + * does. The way this is now one could perhaps end up removing all characters, if all are illegal start characters. It + * would be sort of a breaking change to do so, though, previously generated code might change then. + * + * Javascript identifier regexp pattern retrieved from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers + * + * The output of this is expected to be converted to PascalCase + */ +const sanitizeServiceName = (name: string) => + name.replace(/^[^\p{ID_Start}]+/u, '').replace(/[^$\u200c\u200d\p{ID_Continue}]/gu, '-'); + +export default sanitizeServiceName; diff --git a/src/utils/sanitizeTypeName.spec.ts b/src/utils/sanitizeTypeName.spec.ts new file mode 100644 index 000000000..d01c52cb7 --- /dev/null +++ b/src/utils/sanitizeTypeName.spec.ts @@ -0,0 +1,10 @@ +import sanitizeTypeName from './sanitizeTypeName'; + +describe('sanitizeTypeName', () => { + it('should remove/replace illegal characters', () => { + expect(sanitizeTypeName('abc')).toEqual('abc'); + expect(sanitizeTypeName('æbc')).toEqual('æbc'); + expect(sanitizeTypeName('æb.c')).toEqual('æb_c'); + expect(sanitizeTypeName('1æb.c')).toEqual('æb_c'); + }); +}); diff --git a/src/utils/sanitizeTypeName.ts b/src/utils/sanitizeTypeName.ts new file mode 100644 index 000000000..3c0a2079c --- /dev/null +++ b/src/utils/sanitizeTypeName.ts @@ -0,0 +1,16 @@ +/** + * Sanitizes names of types, so they are valid typescript identifiers of a certain form. + * + * 1: Remove any leading characters that are illegal as starting character of a typescript identifier. + * 2: Replace illegal characters in remaining part of type name with underscore (_). + * + * Step 1 should perhaps instead also replace illegal characters with underscore, or prefix with it, like sanitizeEnumName + * does. The way this is now one could perhaps end up removing all characters, if all are illegal start characters. It + * would be sort of a breaking change to do so, though, previously generated code might change then. + * + * Javascript identifier regexp pattern retrieved from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers + */ +const sanitizeTypeName = (name: string) => + name.replace(/^[^$_\p{ID_Start}]+/u, '').replace(/[^$\u200c\u200d\p{ID_Continue}]/gu, '_'); + +export default sanitizeTypeName; diff --git a/src/utils/validTypescriptIdentifierRegex.ts b/src/utils/validTypescriptIdentifierRegex.ts new file mode 100644 index 000000000..80501679b --- /dev/null +++ b/src/utils/validTypescriptIdentifierRegex.ts @@ -0,0 +1,4 @@ +// Javascript identifier regexp pattern retrieved from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers +const validTypescriptIdentifierRegex = /^[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*$/u; + +export default validTypescriptIdentifierRegex; diff --git a/test/__snapshots__/index.spec.ts.snap b/test/__snapshots__/index.spec.ts.snap index e1c221495..c17c8317b 100644 --- a/test/__snapshots__/index.spec.ts.snap +++ b/test/__snapshots__/index.spec.ts.snap @@ -614,6 +614,7 @@ export type { ModelWithPattern } from './models/ModelWithPattern'; export type { ModelWithProperties } from './models/ModelWithProperties'; export type { ModelWithReference } from './models/ModelWithReference'; export type { ModelWithString } from './models/ModelWithString'; +export type { NonAsciiStringæøåÆØÅöôêÊ字符串 } from './models/NonAsciiStringæøåÆØÅöôêÊ字符串'; export type { SimpleBoolean } from './models/SimpleBoolean'; export type { SimpleFile } from './models/SimpleFile'; export type { SimpleInteger } from './models/SimpleInteger'; @@ -663,6 +664,7 @@ export { $ModelWithPattern } from './schemas/$ModelWithPattern'; export { $ModelWithProperties } from './schemas/$ModelWithProperties'; export { $ModelWithReference } from './schemas/$ModelWithReference'; export { $ModelWithString } from './schemas/$ModelWithString'; +export { $NonAsciiStringæøåÆØÅöôêÊ字符串 } from './schemas/$NonAsciiStringæøåÆØÅöôêÊ字符串'; export { $SimpleBoolean } from './schemas/$SimpleBoolean'; export { $SimpleFile } from './schemas/$SimpleFile'; export { $SimpleInteger } from './schemas/$SimpleInteger'; @@ -682,6 +684,7 @@ export { MultipleTags1Service } from './services/MultipleTags1Service'; export { MultipleTags2Service } from './services/MultipleTags2Service'; export { MultipleTags3Service } from './services/MultipleTags3Service'; export { NoContentService } from './services/NoContentService'; +export { NonAsciiÆøåÆøÅöôêÊService } from './services/NonAsciiÆøåÆøÅöôêÊService'; export { ParametersService } from './services/ParametersService'; export { ResponseService } from './services/ResponseService'; export { SimpleService } from './services/SimpleService'; @@ -1009,6 +1012,7 @@ export enum EnumWithStrings { ERROR = 'Error', _SINGLE_QUOTE_ = '\\'Single Quote\\'', _DOUBLE_QUOTES_ = '"Double Quotes"', + NON_ASCII__ØÆÅÔÖ_ØÆÅÔÖ字符串 = 'Non-ascii: øæåôöØÆÅÔÖ字符串', } " `; @@ -1178,6 +1182,7 @@ export namespace ModelWithEnum { SUCCESS = 'Success', WARNING = 'Warning', ERROR = 'Error', + ØÆÅ字符串 = 'ØÆÅ字符串', } /** * These are the HTTP error code enums @@ -1388,6 +1393,18 @@ export type ModelWithString = { " `; +exports[`v2 should generate: test/generated/v2/models/NonAsciiStringæøåÆØÅöôêÊ字符串.ts 1`] = ` +"/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +/** + * A string with non-ascii (unicode) characters valid in typescript identifiers (æøåÆØÅöÔèÈ字符串) + */ +export type NonAsciiStringæøåÆØÅöôêÊ字符串 = string; +" +`; + exports[`v2 should generate: test/generated/v2/models/SimpleBoolean.ts 1`] = ` "/* generated using openapi-typescript-codegen -- do no edit */ /* istanbul ignore file */ @@ -2256,6 +2273,18 @@ export const $ModelWithString = { " `; +exports[`v2 should generate: test/generated/v2/schemas/$NonAsciiStringæøåÆØÅöôêÊ字符串.ts 1`] = ` +"/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export const $NonAsciiStringæøåÆØÅöôêÊ字符串 = { + type: 'string', + description: \`A string with non-ascii (unicode) characters valid in typescript identifiers (æøåÆØÅöÔèÈ字符串)\`, +} as const; +" +`; + exports[`v2 should generate: test/generated/v2/schemas/$SimpleBoolean.ts 1`] = ` "/* generated using openapi-typescript-codegen -- do no edit */ /* istanbul ignore file */ @@ -2813,6 +2842,36 @@ export class NoContentService { " `; +exports[`v2 should generate: test/generated/v2/services/NonAsciiÆøåÆøÅöôêÊService.ts 1`] = ` +"/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { NonAsciiStringæøåÆØÅöôêÊ字符串 } from '../models/NonAsciiStringæøåÆØÅöôêÊ字符串'; +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; +export class NonAsciiÆøåÆøÅöôêÊService { + /** + * @param nonAsciiParamæøåÆøÅöôêÊ Dummy input param + * @returns NonAsciiStringæøåÆØÅöôêÊ字符串 Successful response + * @throws ApiError + */ + public static nonAsciiæøåÆøÅöôêÊ字符串( + nonAsciiParamæøåÆøÅöôêÊ: number, + ): CancelablePromise { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v{api-version}/non-ascii-æøåÆØÅöôêÊ字符串', + query: { + 'nonAsciiParamæøåÆØÅöôêÊ': nonAsciiParamæøåÆøÅöôêÊ, + }, + }); + } +} +" +`; + exports[`v2 should generate: test/generated/v2/services/ParametersService.ts 1`] = ` "/* generated using openapi-typescript-codegen -- do no edit */ /* istanbul ignore file */ @@ -3728,6 +3787,7 @@ export type { ModelWithPattern } from './models/ModelWithPattern'; export type { ModelWithProperties } from './models/ModelWithProperties'; export type { ModelWithReference } from './models/ModelWithReference'; export type { ModelWithString } from './models/ModelWithString'; +export type { NonAsciiStringæøåÆØÅöôêÊ字符串 } from './models/NonAsciiStringæøåÆØÅöôêÊ字符串'; export type { Pageable } from './models/Pageable'; export type { SimpleBoolean } from './models/SimpleBoolean'; export type { SimpleFile } from './models/SimpleFile'; @@ -3798,6 +3858,7 @@ export { $ModelWithPattern } from './schemas/$ModelWithPattern'; export { $ModelWithProperties } from './schemas/$ModelWithProperties'; export { $ModelWithReference } from './schemas/$ModelWithReference'; export { $ModelWithString } from './schemas/$ModelWithString'; +export { $NonAsciiStringæøåÆØÅöôêÊ字符串 } from './schemas/$NonAsciiStringæøåÆØÅöôêÊ字符串'; export { $Pageable } from './schemas/$Pageable'; export { $SimpleBoolean } from './schemas/$SimpleBoolean'; export { $SimpleFile } from './schemas/$SimpleFile'; @@ -3822,6 +3883,7 @@ export { MultipleTags1Service } from './services/MultipleTags1Service'; export { MultipleTags2Service } from './services/MultipleTags2Service'; export { MultipleTags3Service } from './services/MultipleTags3Service'; export { NoContentService } from './services/NoContentService'; +export { NonAsciiÆøåÆøÅöôêÊService } from './services/NonAsciiÆøåÆøÅöôêÊService'; export { ParametersService } from './services/ParametersService'; export { RequestBodyService } from './services/RequestBodyService'; export { ResponseService } from './services/ResponseService'; @@ -4385,6 +4447,7 @@ export enum EnumWithStrings { ERROR = 'Error', _SINGLE_QUOTE_ = '\\'Single Quote\\'', _DOUBLE_QUOTES_ = '"Double Quotes"', + NON_ASCII__ØÆÅÔÖ_ØÆÅÔÖ字符串 = 'Non-ascii: øæåôöØÆÅÔÖ字符串', } " `; @@ -4638,6 +4701,7 @@ export namespace ModelWithEnum { SUCCESS = 'Success', WARNING = 'Warning', ERROR = 'Error', + ØÆÅ字符串 = 'ØÆÅ字符串', } /** * These are the HTTP error code enums @@ -4857,6 +4921,18 @@ export type ModelWithString = { " `; +exports[`v3 should generate: test/generated/v3/models/NonAsciiStringæøåÆØÅöôêÊ字符串.ts 1`] = ` +"/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +/** + * A string with non-ascii (unicode) characters valid in typescript identifiers (æøåÆØÅöÔèÈ字符串) + */ +export type NonAsciiStringæøåÆØÅöôêÊ字符串 = string; +" +`; + exports[`v3 should generate: test/generated/v3/models/Pageable.ts 1`] = ` "/* generated using openapi-typescript-codegen -- do no edit */ /* istanbul ignore file */ @@ -6247,6 +6323,18 @@ export const $ModelWithString = { " `; +exports[`v3 should generate: test/generated/v3/schemas/$NonAsciiStringæøåÆØÅöôêÊ字符串.ts 1`] = ` +"/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export const $NonAsciiStringæøåÆØÅöôêÊ字符串 = { + type: 'string', + description: \`A string with non-ascii (unicode) characters valid in typescript identifiers (æøåÆØÅöÔèÈ字符串)\`, +} as const; +" +`; + exports[`v3 should generate: test/generated/v3/schemas/$Pageable.ts 1`] = ` "/* generated using openapi-typescript-codegen -- do no edit */ /* istanbul ignore file */ @@ -6989,6 +7077,36 @@ export class NoContentService { " `; +exports[`v3 should generate: test/generated/v3/services/NonAsciiÆøåÆøÅöôêÊService.ts 1`] = ` +"/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { NonAsciiStringæøåÆØÅöôêÊ字符串 } from '../models/NonAsciiStringæøåÆØÅöôêÊ字符串'; +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; +export class NonAsciiÆøåÆøÅöôêÊService { + /** + * @param nonAsciiParamæøåÆøÅöôêÊ Dummy input param + * @returns NonAsciiStringæøåÆØÅöôêÊ字符串 Successful response + * @throws ApiError + */ + public static nonAsciiæøåÆøÅöôêÊ字符串( + nonAsciiParamæøåÆøÅöôêÊ: number, + ): CancelablePromise> { + return __request(OpenAPI, { + method: 'POST', + url: '/api/v{api-version}/non-ascii-æøåÆØÅöôêÊ字符串', + query: { + 'nonAsciiParamæøåÆØÅöôêÊ': nonAsciiParamæøåÆøÅöôêÊ, + }, + }); + } +} +" +`; + exports[`v3 should generate: test/generated/v3/services/ParametersService.ts 1`] = ` "/* generated using openapi-typescript-codegen -- do no edit */ /* istanbul ignore file */ diff --git a/test/spec/v2.json b/test/spec/v2.json index e8eb19b51..eceaf5134 100644 --- a/test/spec/v2.json +++ b/test/spec/v2.json @@ -905,6 +905,33 @@ } } } + }, + "/api/v{api-version}/non-ascii-æøåÆØÅöôêÊ字符串": { + "post": { + "tags": [ + "Non-Ascii-æøåÆØÅöôêÊ" + ], + "operationId": "nonAsciiæøåÆØÅöôêÊ字符串", + "parameters": [ + { + "description": "Dummy input param", + "name": "nonAsciiParamæøåÆØÅöôêÊ", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/NonAsciiStringæøåÆØÅöôêÊ字符串" + } + } + } + } } }, "definitions": { @@ -944,6 +971,10 @@ "description": "This is a simple string", "type": "string" }, + "NonAsciiStringæøåÆØÅöôêÊ字符串": { + "description": "A string with non-ascii (unicode) characters valid in typescript identifiers (æøåÆØÅöÔèÈ字符串)", + "type": "string" + }, "SimpleFile": { "description": "This is a simple file", "type": "file" @@ -965,7 +996,8 @@ "Warning", "Error", "'Single Quote'", - "\"Double Quotes\"" + "\"Double Quotes\"", + "Non-ascii: øæåôöØÆÅÔÖ字符串" ] }, "EnumWithNumbers": { @@ -1174,7 +1206,8 @@ "enum": [ "Success", "Warning", - "Error" + "Error", + "ØÆÅ字符串" ] }, "statusCode": { diff --git a/test/spec/v3.json b/test/spec/v3.json index cb590d0b7..9a3f429bc 100644 --- a/test/spec/v3.json +++ b/test/spec/v3.json @@ -1464,6 +1464,40 @@ } } } + }, + "/api/v{api-version}/non-ascii-æøåÆØÅöôêÊ字符串": { + "post": { + "tags": [ + "Non-Ascii-æøåÆØÅöôêÊ" + ], + "operationId": "nonAsciiæøåÆØÅöôêÊ字符串", + "parameters": [ + { + "description": "Dummy input param", + "name": "nonAsciiParamæøåÆØÅöôêÊ", + "in": "query", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/NonAsciiStringæøåÆØÅöôêÊ字符串" + } + } + } + } + } + } + } } }, "components": { @@ -1539,6 +1573,10 @@ "description": "This is a simple string", "type": "string" }, + "NonAsciiStringæøåÆØÅöôêÊ字符串": { + "description": "A string with non-ascii (unicode) characters valid in typescript identifiers (æøåÆØÅöÔèÈ字符串)", + "type": "string" + }, "SimpleFile": { "description": "This is a simple file", "type": "file" @@ -1561,7 +1599,8 @@ "Warning", "Error", "'Single Quote'", - "\"Double Quotes\"" + "\"Double Quotes\"", + "Non-ascii: øæåôöØÆÅÔÖ字符串" ] }, "EnumWithNumbers": { @@ -1781,7 +1820,8 @@ "enum": [ "Success", "Warning", - "Error" + "Error", + "ØÆÅ字符串" ] }, "statusCode": {