mirror of
https://github.com/ferdikoomen/openapi-typescript-codegen.git
synced 2025-12-08 20:16:21 +00:00
- Fixed quotes in enums
- Fixed better default operation name - Fixed unittest
This commit is contained in:
parent
ec2c712901
commit
b32c85e4eb
@ -1,6 +1,11 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.20.0] - 2022-02-25
|
||||
### Fixed
|
||||
- Support enums with single quotes in names
|
||||
- Generating better names when `operationId` is not given (breaking change)
|
||||
|
||||
## [0.19.0] - 2022-02-02
|
||||
### Added
|
||||
- Support for Angular client with `--name` option
|
||||
|
||||
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Ferdi Koomen
|
||||
Copyright (c) Ferdi Koomen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@ -2,7 +2,7 @@ import { escapeName } from './escapeName';
|
||||
|
||||
describe('escapeName', () => {
|
||||
it('should escape', () => {
|
||||
expect(escapeName('')).toEqual('');
|
||||
expect(escapeName('')).toEqual("''");
|
||||
expect(escapeName('fooBar')).toEqual('fooBar');
|
||||
expect(escapeName('Foo Bar')).toEqual(`'Foo Bar'`);
|
||||
expect(escapeName('foo bar')).toEqual(`'foo bar'`);
|
||||
|
||||
@ -20,7 +20,7 @@ export const getOperation = (
|
||||
pathParams: OperationParameters
|
||||
): Operation => {
|
||||
const serviceName = getServiceName(tag);
|
||||
const operationName = getOperationName(op.operationId || `${method}`);
|
||||
const operationName = getOperationName(url, method, op.operationId);
|
||||
|
||||
// Create a new operation object for this method.
|
||||
const operation: Operation = {
|
||||
|
||||
@ -2,17 +2,26 @@ import { getOperationName } from './getOperationName';
|
||||
|
||||
describe('getOperationName', () => {
|
||||
it('should produce correct result', () => {
|
||||
expect(getOperationName('')).toEqual('');
|
||||
expect(getOperationName('FooBar')).toEqual('fooBar');
|
||||
expect(getOperationName('Foo Bar')).toEqual('fooBar');
|
||||
expect(getOperationName('foo bar')).toEqual('fooBar');
|
||||
expect(getOperationName('foo-bar')).toEqual('fooBar');
|
||||
expect(getOperationName('foo_bar')).toEqual('fooBar');
|
||||
expect(getOperationName('foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('@foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('$foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('_foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('-foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('123.foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'GetAllUsers')).toEqual('getAllUsers');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', undefined)).toEqual('getApiUsers');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'POST', undefined)).toEqual('postApiUsers');
|
||||
expect(getOperationName('/api/v1/users', 'GET', 'GetAllUsers')).toEqual('getAllUsers');
|
||||
expect(getOperationName('/api/v1/users', 'GET', undefined)).toEqual('getApiV1Users');
|
||||
expect(getOperationName('/api/v1/users', 'POST', undefined)).toEqual('postApiV1Users');
|
||||
expect(getOperationName('/api/v1/users/{id}', 'GET', undefined)).toEqual('getApiV1Users');
|
||||
expect(getOperationName('/api/v1/users/{id}', 'POST', undefined)).toEqual('postApiV1Users');
|
||||
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'fooBar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'FooBar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'Foo Bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo-bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo_bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', '@foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', '$foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', '_foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', '-foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', '123.foo.bar')).toEqual('fooBar');
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,13 +2,23 @@ import camelCase from 'camelcase';
|
||||
|
||||
/**
|
||||
* Convert the input value to a correct operation (method) classname.
|
||||
* This converts the input string to camelCase, so the method name follows
|
||||
* the most popular Javascript and Typescript writing style.
|
||||
* This will use the operation ID - if available - and otherwise fallback
|
||||
* on a generated name from the URL
|
||||
*/
|
||||
export const getOperationName = (value: string): string => {
|
||||
const clean = value
|
||||
.replace(/^[^a-zA-Z]+/g, '')
|
||||
.replace(/[^\w\-]+/g, '-')
|
||||
.trim();
|
||||
return camelCase(clean);
|
||||
export const getOperationName = (url: string, method: string, operationId?: string): string => {
|
||||
if (operationId) {
|
||||
return camelCase(
|
||||
operationId
|
||||
.replace(/^[^a-zA-Z]+/g, '')
|
||||
.replace(/[^\w\-]+/g, '-')
|
||||
.trim()
|
||||
);
|
||||
}
|
||||
|
||||
const urlWithoutPlaceholders = url
|
||||
.replace(/[^/]*?{api-version}.*?\//g, '')
|
||||
.replace(/{(.*?)}/g, '')
|
||||
.replace(/\//g, '-');
|
||||
|
||||
return camelCase(`${method}-${urlWithoutPlaceholders}`);
|
||||
};
|
||||
|
||||
@ -23,7 +23,7 @@ export const getEnum = (values?: (string | number)[]): Enum[] => {
|
||||
.replace(/^(\d+)/g, '_$1')
|
||||
.replace(/([a-z])([A-Z]+)/g, '$1_$2')
|
||||
.toUpperCase(),
|
||||
value: `'${value}'`,
|
||||
value: `'${value.replace(/'/g, "\\'")}'`,
|
||||
type: 'string',
|
||||
description: null,
|
||||
};
|
||||
|
||||
@ -23,7 +23,7 @@ export const getOperation = (
|
||||
pathParams: OperationParameters
|
||||
): Operation => {
|
||||
const serviceName = getServiceName(tag);
|
||||
const operationName = getOperationName(op.operationId || `${method}`);
|
||||
const operationName = getOperationName(url, method, op.operationId);
|
||||
|
||||
// Create a new operation object for this method.
|
||||
const operation: Operation = {
|
||||
|
||||
@ -2,17 +2,26 @@ import { getOperationName } from './getOperationName';
|
||||
|
||||
describe('getOperationName', () => {
|
||||
it('should produce correct result', () => {
|
||||
expect(getOperationName('')).toEqual('');
|
||||
expect(getOperationName('FooBar')).toEqual('fooBar');
|
||||
expect(getOperationName('Foo Bar')).toEqual('fooBar');
|
||||
expect(getOperationName('foo bar')).toEqual('fooBar');
|
||||
expect(getOperationName('foo-bar')).toEqual('fooBar');
|
||||
expect(getOperationName('foo_bar')).toEqual('fooBar');
|
||||
expect(getOperationName('foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('@foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('$foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('_foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('-foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('123.foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'GetAllUsers')).toEqual('getAllUsers');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', undefined)).toEqual('getApiUsers');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'POST', undefined)).toEqual('postApiUsers');
|
||||
expect(getOperationName('/api/v1/users', 'GET', 'GetAllUsers')).toEqual('getAllUsers');
|
||||
expect(getOperationName('/api/v1/users', 'GET', undefined)).toEqual('getApiV1Users');
|
||||
expect(getOperationName('/api/v1/users', 'POST', undefined)).toEqual('postApiV1Users');
|
||||
expect(getOperationName('/api/v1/users/{id}', 'GET', undefined)).toEqual('getApiV1Users');
|
||||
expect(getOperationName('/api/v1/users/{id}', 'POST', undefined)).toEqual('postApiV1Users');
|
||||
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'fooBar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'FooBar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'Foo Bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo-bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo_bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', 'foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', '@foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', '$foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', '_foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', '-foo.bar')).toEqual('fooBar');
|
||||
expect(getOperationName('/api/v{api-version}/users', 'GET', '123.foo.bar')).toEqual('fooBar');
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,13 +2,23 @@ import camelCase from 'camelcase';
|
||||
|
||||
/**
|
||||
* Convert the input value to a correct operation (method) classname.
|
||||
* This converts the input string to camelCase, so the method name follows
|
||||
* the most popular Javascript and Typescript writing style.
|
||||
* This will use the operation ID - if available - and otherwise fallback
|
||||
* on a generated name from the URL
|
||||
*/
|
||||
export const getOperationName = (value: string): string => {
|
||||
const clean = value
|
||||
.replace(/^[^a-zA-Z]+/g, '')
|
||||
.replace(/[^\w\-]+/g, '-')
|
||||
.trim();
|
||||
return camelCase(clean);
|
||||
export const getOperationName = (url: string, method: string, operationId?: string): string => {
|
||||
if (operationId) {
|
||||
return camelCase(
|
||||
operationId
|
||||
.replace(/^[^a-zA-Z]+/g, '')
|
||||
.replace(/[^\w\-]+/g, '-')
|
||||
.trim()
|
||||
);
|
||||
}
|
||||
|
||||
const urlWithoutPlaceholders = url
|
||||
.replace(/[^/]*?{api-version}.*?\//g, '')
|
||||
.replace(/{(.*?)}/g, '')
|
||||
.replace(/\//g, '-');
|
||||
|
||||
return camelCase(`${method}-${urlWithoutPlaceholders}`);
|
||||
};
|
||||
|
||||
@ -1,5 +1,77 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`v2 should generate: ./test/generated/v2/Demo.ts 1`] = `
|
||||
"/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import { NgModule} from '@angular/core';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
import { AngularHttpRequest } from './core/AngularHttpRequest';
|
||||
import { BaseHttpRequest } from './core/BaseHttpRequest';
|
||||
import type { OpenAPIConfig } from './core/OpenAPI';
|
||||
import { OpenAPI } from './core/OpenAPI';
|
||||
|
||||
import { CollectionFormatService } from './services/CollectionFormatService';
|
||||
import { ComplexService } from './services/ComplexService';
|
||||
import { DefaultService } from './services/DefaultService';
|
||||
import { DefaultsService } from './services/DefaultsService';
|
||||
import { DescriptionsService } from './services/DescriptionsService';
|
||||
import { DuplicateService } from './services/DuplicateService';
|
||||
import { ErrorService } from './services/ErrorService';
|
||||
import { HeaderService } from './services/HeaderService';
|
||||
import { MultipleTags1Service } from './services/MultipleTags1Service';
|
||||
import { MultipleTags2Service } from './services/MultipleTags2Service';
|
||||
import { MultipleTags3Service } from './services/MultipleTags3Service';
|
||||
import { NoContentService } from './services/NoContentService';
|
||||
import { ParametersService } from './services/ParametersService';
|
||||
import { ResponseService } from './services/ResponseService';
|
||||
import { SimpleService } from './services/SimpleService';
|
||||
import { TypesService } from './services/TypesService';
|
||||
|
||||
@NgModule({
|
||||
imports: [HttpClientModule],
|
||||
providers: [
|
||||
{
|
||||
provide: OpenAPI,
|
||||
useValue: {
|
||||
BASE: OpenAPI?.BASE ?? 'http://localhost:3000/base',
|
||||
VERSION: OpenAPI?.VERSION ?? '1.0',
|
||||
WITH_CREDENTIALS: OpenAPI?.WITH_CREDENTIALS ?? false,
|
||||
CREDENTIALS: OpenAPI?.CREDENTIALS ?? 'include',
|
||||
TOKEN: OpenAPI?.TOKEN,
|
||||
USERNAME: OpenAPI?.USERNAME,
|
||||
PASSWORD: OpenAPI?.PASSWORD,
|
||||
HEADERS: OpenAPI?.HEADERS,
|
||||
ENCODE_PATH: OpenAPI?.ENCODE_PATH,
|
||||
} as OpenAPIConfig,
|
||||
},
|
||||
{
|
||||
provide: BaseHttpRequest,
|
||||
useClass: AngularHttpRequest,
|
||||
},
|
||||
CollectionFormatService,
|
||||
ComplexService,
|
||||
DefaultService,
|
||||
DefaultsService,
|
||||
DescriptionsService,
|
||||
DuplicateService,
|
||||
ErrorService,
|
||||
HeaderService,
|
||||
MultipleTags1Service,
|
||||
MultipleTags2Service,
|
||||
MultipleTags3Service,
|
||||
NoContentService,
|
||||
ParametersService,
|
||||
ResponseService,
|
||||
SimpleService,
|
||||
TypesService,
|
||||
]
|
||||
})
|
||||
export class Demo {}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`v2 should generate: ./test/generated/v2/core/ApiError.ts 1`] = `
|
||||
"/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
@ -943,6 +1015,8 @@ export enum EnumWithStrings {
|
||||
SUCCESS = 'Success',
|
||||
WARNING = 'Warning',
|
||||
ERROR = 'Error',
|
||||
_SINGLE_QUOTE_ = ''Single Quote'',
|
||||
_DOUBLE_QUOTES_ = '\\"Double Quotes\\"',
|
||||
}"
|
||||
`;
|
||||
|
||||
@ -2949,6 +3023,86 @@ export class TypesService {
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`v3 should generate: ./test/generated/v3/Demo.ts 1`] = `
|
||||
"/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
import { NgModule} from '@angular/core';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
import { AngularHttpRequest } from './core/AngularHttpRequest';
|
||||
import { BaseHttpRequest } from './core/BaseHttpRequest';
|
||||
import type { OpenAPIConfig } from './core/OpenAPI';
|
||||
import { OpenAPI } from './core/OpenAPI';
|
||||
|
||||
import { CollectionFormatService } from './services/CollectionFormatService';
|
||||
import { ComplexService } from './services/ComplexService';
|
||||
import { DefaultService } from './services/DefaultService';
|
||||
import { DefaultsService } from './services/DefaultsService';
|
||||
import { DescriptionsService } from './services/DescriptionsService';
|
||||
import { DuplicateService } from './services/DuplicateService';
|
||||
import { ErrorService } from './services/ErrorService';
|
||||
import { FormDataService } from './services/FormDataService';
|
||||
import { HeaderService } from './services/HeaderService';
|
||||
import { MultipartService } from './services/MultipartService';
|
||||
import { MultipleTags1Service } from './services/MultipleTags1Service';
|
||||
import { MultipleTags2Service } from './services/MultipleTags2Service';
|
||||
import { MultipleTags3Service } from './services/MultipleTags3Service';
|
||||
import { NoContentService } from './services/NoContentService';
|
||||
import { ParametersService } from './services/ParametersService';
|
||||
import { RequestBodyService } from './services/RequestBodyService';
|
||||
import { ResponseService } from './services/ResponseService';
|
||||
import { SimpleService } from './services/SimpleService';
|
||||
import { TypesService } from './services/TypesService';
|
||||
import { UploadService } from './services/UploadService';
|
||||
|
||||
@NgModule({
|
||||
imports: [HttpClientModule],
|
||||
providers: [
|
||||
{
|
||||
provide: OpenAPI,
|
||||
useValue: {
|
||||
BASE: OpenAPI?.BASE ?? 'http://localhost:3000/base',
|
||||
VERSION: OpenAPI?.VERSION ?? '1.0',
|
||||
WITH_CREDENTIALS: OpenAPI?.WITH_CREDENTIALS ?? false,
|
||||
CREDENTIALS: OpenAPI?.CREDENTIALS ?? 'include',
|
||||
TOKEN: OpenAPI?.TOKEN,
|
||||
USERNAME: OpenAPI?.USERNAME,
|
||||
PASSWORD: OpenAPI?.PASSWORD,
|
||||
HEADERS: OpenAPI?.HEADERS,
|
||||
ENCODE_PATH: OpenAPI?.ENCODE_PATH,
|
||||
} as OpenAPIConfig,
|
||||
},
|
||||
{
|
||||
provide: BaseHttpRequest,
|
||||
useClass: AngularHttpRequest,
|
||||
},
|
||||
CollectionFormatService,
|
||||
ComplexService,
|
||||
DefaultService,
|
||||
DefaultsService,
|
||||
DescriptionsService,
|
||||
DuplicateService,
|
||||
ErrorService,
|
||||
FormDataService,
|
||||
HeaderService,
|
||||
MultipartService,
|
||||
MultipleTags1Service,
|
||||
MultipleTags2Service,
|
||||
MultipleTags3Service,
|
||||
NoContentService,
|
||||
ParametersService,
|
||||
RequestBodyService,
|
||||
ResponseService,
|
||||
SimpleService,
|
||||
TypesService,
|
||||
UploadService,
|
||||
]
|
||||
})
|
||||
export class Demo {}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`v3 should generate: ./test/generated/v3/core/ApiError.ts 1`] = `
|
||||
"/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
@ -4089,6 +4243,8 @@ export enum EnumWithStrings {
|
||||
SUCCESS = 'Success',
|
||||
WARNING = 'Warning',
|
||||
ERROR = 'Error',
|
||||
_SINGLE_QUOTE_ = '\\\\'Single Quote\\\\'',
|
||||
_DOUBLE_QUOTES_ = '\\"Double Quotes\\"',
|
||||
}"
|
||||
`;
|
||||
|
||||
@ -6125,7 +6281,7 @@ export class FormDataService {
|
||||
* @param formData A reusable request body
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static post(
|
||||
public static postApiFormData(
|
||||
parameter?: string,
|
||||
formData?: ModelWithString,
|
||||
): CancelablePromise<void> {
|
||||
@ -6502,7 +6658,7 @@ export class RequestBodyService {
|
||||
* @param requestBody A reusable request body
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static post(
|
||||
public static postApiRequestBody(
|
||||
parameter?: string,
|
||||
requestBody?: ModelWithString,
|
||||
): CancelablePromise<void> {
|
||||
|
||||
@ -7,14 +7,14 @@ const generate = async (input, output) => {
|
||||
await OpenAPI.generate({
|
||||
input,
|
||||
output,
|
||||
httpClient: OpenAPI.HttpClient.ANGULAR,
|
||||
httpClient: OpenAPI.HttpClient.FETCH,
|
||||
useOptions: true,
|
||||
useUnionTypes: false,
|
||||
exportCore: true,
|
||||
exportSchemas: true,
|
||||
exportModels: true,
|
||||
exportServices: true,
|
||||
clientName: 'Demo',
|
||||
// clientName: 'Demo',
|
||||
// indent: OpenAPI.Indent.SPACE_2,
|
||||
// postfix: 'Service',
|
||||
// request: './test/custom/request.ts',
|
||||
|
||||
@ -963,7 +963,9 @@
|
||||
"enum": [
|
||||
"Success",
|
||||
"Warning",
|
||||
"Error"
|
||||
"Error",
|
||||
"'Single Quote'",
|
||||
"\"Double Quotes\""
|
||||
]
|
||||
},
|
||||
"EnumWithNumbers": {
|
||||
|
||||
@ -1537,7 +1537,9 @@
|
||||
"enum": [
|
||||
"Success",
|
||||
"Warning",
|
||||
"Error"
|
||||
"Error",
|
||||
"'Single Quote'",
|
||||
"\"Double Quotes\""
|
||||
]
|
||||
},
|
||||
"EnumWithNumbers": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user