这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/nice-lemons-care.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hey-api/openapi-ts": patch
---

fix: escape schema names
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { describe, expect, it } from 'vitest';

import { sanitizeNamespaceIdentifier, sanitizeOperationParameterName, sanitizeTypeName } from '../sanitize';
import {
ensureValidTypeScriptJavaScriptIdentifier,
sanitizeNamespaceIdentifier,
sanitizeOperationParameterName,
} from '../sanitize';

describe('sanitizeOperationParameterName', () => {
it.each([
Expand All @@ -26,13 +30,13 @@ describe('sanitizeNamespaceIdentifier', () => {
});
});

describe('sanitizeTypeName', () => {
describe('ensureValidTypeScriptJavaScriptIdentifier', () => {
it.each([
{ expected: 'abc', input: 'abc' },
{ expected: 'æbc', input: 'æbc' },
{ expected: 'æb_c', input: 'æb.c' },
{ expected: 'æb_c', input: '1æb.c' },
])('sanitizeTypeName($input) -> $expected', ({ input, expected }) => {
expect(sanitizeTypeName(input)).toEqual(expected);
])('ensureValidTypeScriptJavaScriptIdentifier($input) -> $expected', ({ input, expected }) => {
expect(ensureValidTypeScriptJavaScriptIdentifier(input)).toEqual(expected);
});
});
8 changes: 4 additions & 4 deletions packages/openapi-ts/src/openApi/common/parser/sanitize.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/**
* Sanitizes names of types, so they are valid typescript identifiers of a certain form.
* 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.
* 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/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers
* JavaScript identifier regexp pattern retrieved from https://developer.mozilla.org/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers
*/
export const sanitizeTypeName = (name: string) =>
export const ensureValidTypeScriptJavaScriptIdentifier = (name: string) =>
name.replace(/^[^$_\p{ID_Start}]+/u, '').replace(/[^$\u200c\u200d\p{ID_Continue}]/gu, '_');

/**
Expand Down
8 changes: 4 additions & 4 deletions packages/openapi-ts/src/openApi/common/parser/type.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Type } from '../interfaces/Type';
import { sanitizeTypeName } from './sanitize';
import { ensureValidTypeScriptJavaScriptIdentifier } from './sanitize';
import { stripNamespace } from './stripNamespace';

/**
Expand Down Expand Up @@ -82,8 +82,8 @@ export const getType = (type: string | string[] = 'unknown', format?: string): T
if (/\[.*\]$/g.test(typeWithoutNamespace)) {
const matches = typeWithoutNamespace.match(/(.*?)\[(.*)\]$/);
if (matches?.length) {
const match1 = getType(sanitizeTypeName(matches[1]));
const match2 = getType(sanitizeTypeName(matches[2]));
const match1 = getType(ensureValidTypeScriptJavaScriptIdentifier(matches[1]));
const match2 = getType(ensureValidTypeScriptJavaScriptIdentifier(matches[2]));

if (match1.type === 'unknown[]') {
result.type = `${match2.type}[]`;
Expand All @@ -107,7 +107,7 @@ export const getType = (type: string | string[] = 'unknown', format?: string): T
}

if (typeWithoutNamespace) {
const encodedType = sanitizeTypeName(typeWithoutNamespace);
const encodedType = ensureValidTypeScriptJavaScriptIdentifier(typeWithoutNamespace);
result.type = encodedType;
result.base = encodedType;
if (type.startsWith('#')) {
Expand Down
10 changes: 6 additions & 4 deletions packages/openapi-ts/src/utils/write/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import path from 'node:path';

import { compiler, TypeScriptFile } from '../../compiler';
import type { OpenApi } from '../../openApi';
import { ensureValidTypeScriptJavaScriptIdentifier } from '../../openApi/common/parser/sanitize';

/**
* Generate Schemas using the Handlebar template and write to disk.
Expand All @@ -12,8 +13,9 @@ export const writeClientSchemas = async (openApi: OpenApi, outputPath: string):
const file = new TypeScriptFile();

const addSchema = (name: string, obj: any) => {
const validName = `$${ensureValidTypeScriptJavaScriptIdentifier(name)}`;
const expression = compiler.types.object(obj);
const statement = compiler.export.asConst(name, expression);
const statement = compiler.export.asConst(validName, expression);
file.add(statement);
};

Expand All @@ -22,7 +24,7 @@ export const writeClientSchemas = async (openApi: OpenApi, outputPath: string):
for (const name in openApi.definitions) {
if (openApi.definitions.hasOwnProperty(name)) {
const definition = openApi.definitions[name];
addSchema(`$${name}`, definition);
addSchema(name, definition);
}
}
}
Expand All @@ -33,13 +35,13 @@ export const writeClientSchemas = async (openApi: OpenApi, outputPath: string):
for (const name in openApi.components.schemas) {
if (openApi.components.schemas.hasOwnProperty(name)) {
const schema = openApi.components.schemas[name];
addSchema(`$${name}`, schema);
addSchema(name, schema);
}
}
for (const name in openApi.components.parameters) {
if (openApi.components.parameters.hasOwnProperty(name)) {
const parameter = openApi.components.parameters[name];
addSchema(`$${name}`, parameter);
addSchema(name, parameter);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export type ModelWithString = {
/**
* `Comment` or `VoiceComment`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)
*/
export type ModelFromZendesk = string;
export type Model_From_Zendesk = string;

/**
* This is a model with one string property
Expand Down Expand Up @@ -840,7 +840,7 @@ export type DefaultData = {

export type SimpleData = {
responses: {
ApiVversionOdataControllerCount: ModelFromZendesk;
ApiVversionOdataControllerCount: Model_From_Zendesk;
GetCallWithoutParametersAndResponse: void;
PutCallWithoutParametersAndResponse: void;
PostCallWithoutParametersAndResponse: void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ export const $ModelWithString = {
},
} as const;

export const $ModelFromZendesk = {
export const $Model_From_Zendesk = {
description: `\`Comment\` or \`VoiceComment\`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)`,
type: 'string',
} as const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class DefaultService {

export class SimpleService {
/**
* @returns ModelFromZendesk Success
* @returns Model_From_Zendesk Success
* @throws ApiError
*/
public static apiVVersionOdataControllerCount(): CancelablePromise<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export type ModelWithString = {
/**
* `Comment` or `VoiceComment`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)
*/
export type ModelFromZendesk = string;
export type Model_From_Zendesk = string;

/**
* This is a model with one string property
Expand Down Expand Up @@ -737,7 +737,7 @@ export type DefaultData = {

export type SimpleData = {
responses: {
ApiVversionOdataControllerCount: ModelFromZendesk;
ApiVversionOdataControllerCount: Model_From_Zendesk;
GetCallWithoutParametersAndResponse: void;
PutCallWithoutParametersAndResponse: void;
PostCallWithoutParametersAndResponse: void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ export const $ModelWithString = {
},
} as const;

export const $ModelFromZendesk = {
export const $Model_From_Zendesk = {
description: `\`Comment\` or \`VoiceComment\`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)`,
type: 'string',
} as const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class SimpleService {
constructor(public readonly http: HttpClient) {}

/**
* @returns ModelFromZendesk Success
* @returns Model_From_Zendesk Success
* @throws ApiError
*/
public apiVVersionOdataControllerCount(): Observable<SimpleData['responses']['ApiVversionOdataControllerCount']> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export type ModelWithString = {
/**
* `Comment` or `VoiceComment`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)
*/
export type ModelFromZendesk = string;
export type Model_From_Zendesk = string;

/**
* This is a model with one string property
Expand Down Expand Up @@ -840,7 +840,7 @@ export type DefaultData = {

export type SimpleData = {
responses: {
ApiVversionOdataControllerCount: ModelFromZendesk;
ApiVversionOdataControllerCount: Model_From_Zendesk;
GetCallWithoutParametersAndResponse: void;
PutCallWithoutParametersAndResponse: void;
PostCallWithoutParametersAndResponse: void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class SimpleService {
constructor(public readonly httpRequest: BaseHttpRequest) {}

/**
* @returns ModelFromZendesk Success
* @returns Model_From_Zendesk Success
* @throws ApiError
*/
public apiVVersionOdataControllerCount(): CancelablePromise<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export type DefaultData = {

export type SimpleData = {
responses: {
ApiVversionOdataControllerCount: ModelFromZendesk;
ApiVversionOdataControllerCount: Model_From_Zendesk;
GetCallWithoutParametersAndResponse: void;
PutCallWithoutParametersAndResponse: void;
PostCallWithoutParametersAndResponse: void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ export const $ModelWithString = {
},
} as const;

export const $ModelFromZendesk = {
export const $Model_From_Zendesk = {
description: `\`Comment\` or \`VoiceComment\`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)`,
type: 'string',
} as const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ export type ModelWithString = {
/**
* `Comment` or `VoiceComment`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)
*/
export type ModelFromZendesk = string;
export type Model_From_Zendesk = string;

/**
* This is a model with one string property
Expand Down Expand Up @@ -782,7 +782,7 @@ export type DefaultData = {

export type SimpleData = {
responses: {
ApiVversionOdataControllerCount: ModelFromZendesk;
ApiVversionOdataControllerCount: Model_From_Zendesk;
GetCallWithoutParametersAndResponse: void;
PutCallWithoutParametersAndResponse: void;
PostCallWithoutParametersAndResponse: void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ export const $ModelWithString = {
},
} as const;

export const $ModelFromZendesk = {
export const $Model_From_Zendesk = {
description: `\`Comment\` or \`VoiceComment\`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)`,
type: 'string',
} as const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class DefaultService {

export class SimpleService {
/**
* @returns ModelFromZendesk Success
* @returns Model_From_Zendesk Success
* @throws ApiError
*/
public static apiVVersionOdataControllerCount(): CancelablePromise<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export type ModelWithString = {
/**
* `Comment` or `VoiceComment`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)
*/
export type ModelFromZendesk = string;
export type Model_From_Zendesk = string;

/**
* This is a model with one string property
Expand Down Expand Up @@ -739,7 +739,7 @@ export type DefaultData = {

export type SimpleData = {
responses: {
ApiVversionOdataControllerCount: ModelFromZendesk;
ApiVversionOdataControllerCount: Model_From_Zendesk;
GetCallWithoutParametersAndResponse: void;
PutCallWithoutParametersAndResponse: void;
PostCallWithoutParametersAndResponse: void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ export const $ModelWithString = {
},
} as const;

export const $ModelFromZendesk = {
export const $Model_From_Zendesk = {
description: `\`Comment\` or \`VoiceComment\`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)`,
type: 'string',
} as const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class DefaultService {

export class SimpleService {
/**
* @returns ModelFromZendesk Success
* @returns Model_From_Zendesk Success
* @throws ApiError
*/
public static apiVVersionOdataControllerCount(): CancelablePromise<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export type ModelWithString = {
/**
* `Comment` or `VoiceComment`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)
*/
export type ModelFromZendesk = string;
export type Model_From_Zendesk = string;

/**
* This is a model with one string property
Expand Down Expand Up @@ -737,7 +737,7 @@ export type DefaultData = {

export type SimpleData = {
responses: {
ApiVversionOdataControllerCount: ModelFromZendesk;
ApiVversionOdataControllerCount: Model_From_Zendesk;
GetCallWithoutParametersAndResponse: void;
PutCallWithoutParametersAndResponse: void;
PostCallWithoutParametersAndResponse: void;
Expand Down
4 changes: 2 additions & 2 deletions packages/openapi-ts/test/spec/v3.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"content": {
"application/json; type=collection": {
"schema": {
"$ref": "#/components/schemas/ModelFromZendesk"
"$ref": "#/components/schemas/Model-From.Zendesk"
}
}
}
Expand Down Expand Up @@ -2048,7 +2048,7 @@
}
}
},
"ModelFromZendesk": {
"Model-From.Zendesk": {
"description": "`Comment` or `VoiceComment`. The JSON object for adding voice comments to tickets is different. See [Adding voice comments to tickets](/documentation/ticketing/managing-tickets/adding-voice-comments-to-tickets)",
"type": "string"
},
Expand Down