Skip to content

Commit

Permalink
feat(helpers): 只保留 resolveURL
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudcome committed Apr 15, 2023
1 parent 328f1aa commit e88cb4b
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 97 deletions.
21 changes: 21 additions & 0 deletions src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,24 @@ export const templatesDir = path.join(dirname, '../templates');
export const axiosImportDefault = `import { Axios } from 'axios';
const axios = new Axios();`;
export const helpersImport = `import { formatHeaders, formatBody } from 'openapi-axios/helpers';`;

// 内部类型名称,文档里如果重复了会生成新的唯一值
export const INTERNAL_TYPE_NAMES = [
// @ref ComponentsWriter
'OneOf',
// @ref PathsWriter
'axios',
'request',
'DELETE',
'GET',
'HEAD',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'TRACE',
'resolveURL',
'BASE_URL',
'AxiosPromise',
'AxiosRequestConfig',
];
91 changes: 20 additions & 71 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,21 @@
import { isBoolean, isDate, isNumber, isObject, isString } from './utils/type-is';

export enum ContentKind {
JSON = 'JSON',
URL_ENCODED = 'URL_ENCODED',
FORM_DATA = 'FORM_DATA',
TEXT = 'TEXT',
OTHER = 'OTHER',
}

/**
* 格式化请求头
* @param {ContentKind} contentKind
* @returns {{"content-type": string} | undefined}
*/
export function formatHeaders(contentKind: ContentKind) {
const contentType = {
[ContentKind.JSON]: 'application/json',
[ContentKind.URL_ENCODED]: 'application/x-www-form-urlencoded',
[ContentKind.FORM_DATA]: 'multipart/form-data',
[ContentKind.TEXT]: 'text/plain',
[ContentKind.OTHER]: '',
}[contentKind];
return contentType ? { 'Content-Type': contentType } : undefined;
}

/**
* 判断是否为二进制
* @param value
* @returns {boolean}
*/
export function isBlob(value: unknown): value is Blob {
if (typeof Blob !== 'undefined' && value instanceof Blob) return true;
if (typeof File !== 'undefined' && value instanceof File) return true;

return false;
}

export function toFormDataValue(value: unknown): string | Blob {
if (isString(value) || isNumber(value) || isBoolean(value)) return String(value);
if (isObject(value)) return JSON.stringify(value);
if (isDate(value)) return value.toISOString();
if (isBlob(value)) return value;
return '';
}

/**
* 格式化请求体
* @param {string} contentKind
* @param body
* @returns {FormData | string}
*/
export function formatBody<D>(contentKind: ContentKind, body: D) {
switch (contentKind) {
case ContentKind.URL_ENCODED:
return isObject(body) ? new URLSearchParams(body as Record<string, string>).toString() : '';

case ContentKind.FORM_DATA: {
const fd = new FormData();
if (!isObject(body)) return fd;

return Object.keys(body).reduce((fd, key) => {
const val = body[key as keyof D];
fd.append(key, toFormDataValue(val));
return fd;
}, fd);
}

default:
return JSON.stringify(body);
}
// @ref https://github.com/drwpow/openapi-typescript/blob/bc52343c44f9dab4006e04c27411e405fb67a739/src/index.ts#L215
export type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
export type XOR<T, U> = T | U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;
export type OneOf<T extends any[]> = T extends [infer Only]
? Only
: T extends [infer A, infer B, ...infer Rest]
? OneOf<[XOR<A, B>, ...Rest]>
: never;

export const DELETE = 'DELETE';
export const GET = 'GET';
export const HEAD = 'HEAD';
export const OPTIONS = 'OPTIONS';
export const PATCH = 'PATCH';
export const POST = 'POST';
export const PUT = 'PUT';
export const TRACE = 'TRACE';

export function resolveURL(baseURL: string, url: string) {
return baseURL.replace(/\/+$/, '') + '/' + url.replace(/^\/+/, '');
}
61 changes: 35 additions & 26 deletions test/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
import { ContentKind, formatBody, formatHeaders, isBlob } from '../src/helpers';
// import { ContentKind, formatBody, formatHeaders, isBlob } from '../src/helpers';
//
// test('formatHeaders', () => {
// expect(formatHeaders(ContentKind.JSON)).toEqual({ 'Content-Type': 'application/json' });
// expect(formatHeaders(ContentKind.OTHER)).toBeUndefined();
// });
//
// test('isBlob', () => {
// expect(isBlob('')).toBeFalsy();
// expect(isBlob(new Blob())).toBeTruthy();
// });
//
// test('formatBody', () => {
// const body = {
// a: 1,
// b: '2',
// c: new Blob([]),
// d: [true, null, undefined],
// e: new Date(2000, 1, 1, 1, 1, 1, 1),
// };
//
// expect(formatBody(ContentKind.JSON, body)).toEqual(JSON.stringify(body));
// expect(formatBody(ContentKind.URL_ENCODED, body)).toMatchInlineSnapshot(
// '"a=1&b=2&c=%5Bobject+Blob%5D&d=true%2C%2C&e=Tue+Feb+01+2000+01%3A01%3A01+GMT%2B0800+%28China+Standard+Time%29"'
// );
// expect((formatBody(ContentKind.FORM_DATA, body) as FormData).append).toBeTypeOf('function');
// expect(formatBody(ContentKind.TEXT, body)).toEqual(JSON.stringify(body));
// expect(formatBody(ContentKind.OTHER, body)).toEqual(JSON.stringify(body));
// });

test('formatHeaders', () => {
expect(formatHeaders(ContentKind.JSON)).toEqual({ 'Content-Type': 'application/json' });
expect(formatHeaders(ContentKind.OTHER)).toBeUndefined();
});

test('isBlob', () => {
expect(isBlob('')).toBeFalsy();
expect(isBlob(new Blob())).toBeTruthy();
});

test('formatBody', () => {
const body = {
a: 1,
b: '2',
c: new Blob([]),
d: [true, null, undefined],
e: new Date(2000, 1, 1, 1, 1, 1, 1),
};
import { resolveURL } from '../src/helpers';

expect(formatBody(ContentKind.JSON, body)).toEqual(JSON.stringify(body));
expect(formatBody(ContentKind.URL_ENCODED, body)).toMatchInlineSnapshot(
'"a=1&b=2&c=%5Bobject+Blob%5D&d=true%2C%2C&e=Tue+Feb+01+2000+01%3A01%3A01+GMT%2B0800+%28China+Standard+Time%29"'
);
expect((formatBody(ContentKind.FORM_DATA, body) as FormData).append).toBeTypeOf('function');
expect(formatBody(ContentKind.TEXT, body)).toEqual(JSON.stringify(body));
expect(formatBody(ContentKind.OTHER, body)).toEqual(JSON.stringify(body));
test('resolveBaseURL', () => {
expect(resolveURL('/', '/a/b')).toEqual('/a/b');
expect(resolveURL('/api/v1', '/a/b')).toEqual('/api/v1/a/b');
expect(resolveURL('https//example.com/api/v1', '/a/b')).toEqual('https//example.com/api/v1/a/b');
expect(resolveURL('https//example.com/api/v1/', '/a/b')).toEqual('https//example.com/api/v1/a/b');
});

0 comments on commit e88cb4b

Please sign in to comment.