refactor: 重构 utils 为 helpers

pull/17/head
954270063@qq.com 2021-05-25 23:17:29 +08:00
parent e171b228d2
commit 5b442d95ce
14 changed files with 229 additions and 228 deletions

View File

@ -6,7 +6,7 @@ import Axios, {
} from './core/Axios'; } from './core/Axios';
import { CancelToken, CancelTokenConstructor, isCancel } from './core/cancel'; import { CancelToken, CancelTokenConstructor, isCancel } from './core/cancel';
import { mergeConfig } from './core/mergeConfig'; import { mergeConfig } from './core/mergeConfig';
import { isString } from './utils'; import { isString } from './helpers/is';
import defaults from './defaults'; import defaults from './defaults';
export interface AxiosInstance extends Axios { export interface AxiosInstance extends Axios {

View File

@ -1,4 +1,4 @@
import { buildURL } from '../utils'; import { buildURL } from '../helpers/url';
import { mergeConfig } from './mergeConfig'; import { mergeConfig } from './mergeConfig';
import { import {
AdapterRequestMethod, AdapterRequestMethod,

View File

@ -1,13 +1,10 @@
import { import {
assert,
isEmptyArray, isEmptyArray,
isFunction, isFunction,
isPlainObject, isPlainObject,
isPlatform,
isUndefined, isUndefined,
revisePlatformApiNames, } from '../helpers/is';
throwError, import { assert, throwError } from '../helpers/utils';
} from '../utils';
import { import {
AxiosProgressCallback, AxiosProgressCallback,
AxiosRequestConfig, AxiosRequestConfig,
@ -86,6 +83,23 @@ export interface AxiosAdapter {
(config: AxiosAdapterRequestConfig): AxiosAdapterTask | void; (config: AxiosAdapterRequestConfig): AxiosAdapterTask | void;
} }
export function isPlatform(value: any): value is AxiosPlatform {
return (
isPlainObject(value) &&
isFunction(value.request) &&
isFunction(value.upload) &&
isFunction(value.download)
);
}
export function revisePlatformApiNames(platform: AnyObject): AxiosPlatform {
return {
request: platform.request ?? platform.httpRequest,
upload: platform.upload ?? platform.uploadFile,
download: platform.download ?? platform.downloadFile,
};
}
export function createAdapter(platform: AxiosPlatform): AxiosAdapter { export function createAdapter(platform: AxiosPlatform): AxiosAdapter {
assert(isPlainObject(platform), 'platform 需要是一个 object'); assert(isPlainObject(platform), 'platform 需要是一个 object');
assert(isFunction(platform.request), 'platform.request 需要是一个 function'); assert(isFunction(platform.request), 'platform.request 需要是一个 function');

View File

@ -1,4 +1,4 @@
import { isPlainObject } from '../utils'; import { isPlainObject } from '../helpers/is';
import { isCancel } from './cancel'; import { isCancel } from './cancel';
import { flattenHeaders } from './flattenHeaders'; import { flattenHeaders } from './flattenHeaders';
import { transformData } from './transformData'; import { transformData } from './transformData';

View File

@ -1,4 +1,5 @@
import { isPlainObject, omit } from '../utils'; import { isPlainObject } from '../helpers/is';
import { omit } from '../helpers/utils';
import { import {
AxiosRequestConfig, AxiosRequestConfig,
AxiosRequestMethodAlias, AxiosRequestMethodAlias,

View File

@ -1,4 +1,5 @@
import { assert, isPlainObject, isString } from '../utils'; import { isPlainObject, isString } from 'src/helpers/is';
import { assert } from '../helpers/utils';
import { AdapterRequestType } from './adapter'; import { AdapterRequestType } from './adapter';
import { AxiosRequestConfig } from './Axios'; import { AxiosRequestConfig } from './Axios';

View File

@ -1,4 +1,5 @@
import { isPlainObject, deepMerge, isUndefined } from '../utils'; import { isUndefined, isPlainObject } from '../helpers/is';
import { deepMerge } from '../helpers/utils';
import { AxiosRequestConfig } from './Axios'; import { AxiosRequestConfig } from './Axios';
type AxiosRequestConfigKey = keyof AxiosRequestConfig; type AxiosRequestConfigKey = keyof AxiosRequestConfig;

View File

@ -1,4 +1,5 @@
import { assert, isFunction, isPlainObject } from '../utils'; import { isFunction, isPlainObject } from '../helpers/is';
import { assert } from '../helpers/utils';
import { import {
AxiosAdapterRequestConfig, AxiosAdapterRequestConfig,
AdapterRequestMethod, AdapterRequestMethod,

View File

@ -1,4 +1,4 @@
import { isArray, isUndefined } from '../utils'; import { isArray, isUndefined } from '../helpers/is';
import { import {
AxiosRequestData, AxiosRequestData,
AxiosRequestFormData, AxiosRequestFormData,

View File

@ -4,7 +4,7 @@ import {
dynamicInterpolation, dynamicInterpolation,
isAbsoluteURL, isAbsoluteURL,
isDynamicURL, isDynamicURL,
} from '../utils'; } from '../helpers/url';
import { AxiosRequestConfig } from './Axios'; import { AxiosRequestConfig } from './Axios';
export function transformURL(config: AxiosRequestConfig): string { export function transformURL(config: AxiosRequestConfig): string {

41
src/helpers/is.ts Normal file
View File

@ -0,0 +1,41 @@
const _toString = Object.prototype.toString;
export function isDate(date: any): date is Date {
return _toString.call(date) === '[object Date]';
}
export function isPlainObject<T = never>(
value: any,
): value is [T] extends never[] ? AnyObject : T {
return _toString.call(value) === '[object Object]';
}
export function isUndefined(value: any): value is undefined {
return typeof value === 'undefined';
}
export function isString(value: any): value is string {
return typeof value === 'string';
}
export function isNull(value: any): value is null {
return value === null;
}
export function isFunction<T extends Function = Function>(
value: any,
): value is T {
return typeof value === 'function';
}
export function isArray<T = any>(value: any): value is T[] {
return Array.isArray(value);
}
export function isEmptyArray<T = any>(value: any): value is [] {
return isArray<T>(value) && value.length === 0;
}
export function isEmptyObject<T = any>(value: any): value is {} {
return isPlainObject<T>(value) && Object.keys(value).length === 0;
}

102
src/helpers/url.ts Normal file
View File

@ -0,0 +1,102 @@
import { isDate, isNull, isPlainObject, isUndefined } from './is';
function encode(str: string): string {
return encodeURIComponent(str)
.replace(/%40/gi, '@')
.replace(/%3A/gi, ':')
.replace(/%24/g, '$')
.replace(/%2C/gi, ',')
.replace(/%20/g, '+')
.replace(/%5B/gi, '[')
.replace(/%5D/gi, ']');
}
function generateURL(url: string, serializedParams: string): string {
const hashIndex = url.indexOf('#');
if (hashIndex !== -1) {
url = url.slice(0, hashIndex);
}
if (serializedParams === '') {
return url;
}
const prefix = url.indexOf('?') === -1 ? '?' : '&';
serializedParams = `${prefix}${serializedParams}`;
return `${url}${serializedParams}`;
}
function paramsSerialization(params?: any): string {
if (!isPlainObject(params)) {
return '';
}
const parts: string[] = [];
Object.keys(params).forEach((key): void => {
const value = params[key];
if (isNull(value) || isUndefined(value) || value !== value) {
return;
}
if (Array.isArray(value)) {
key += '[]';
}
const values = [].concat(value);
values.forEach((val: any): void => {
if (isPlainObject(val)) {
val = JSON.stringify(val);
} else if (isDate(val)) {
val = (val as Date).toISOString();
}
parts.push(`${encode(key)}=${encode(val)}`);
});
});
return parts.join('&');
}
export function buildURL(
url = '',
params?: any,
paramsSerializer = paramsSerialization,
): string {
if (!isPlainObject(params)) {
return url;
}
return generateURL(url, paramsSerializer(params));
}
export const combineREG = /(?<!:)\/{2,}/g;
export function combineURL(baseURL = '', url: string): string {
const separator = '/';
return `${baseURL}${separator}${url}`.replace(combineREG, separator);
}
export const dynamicREG = /\/?(:([a-zA-Z_$][\w-$]*))\/??/g;
export function isDynamicURL(url: string): boolean {
return dynamicREG.test(url);
}
export function dynamicInterpolation(url: string, sourceData?: any): string {
if (!isPlainObject(sourceData)) {
return url;
}
return url.replace(dynamicREG, (key1, key2, key3) =>
key1.replace(key2, sourceData[key3]),
);
}
export const absoluteREG = /^([a-z][a-z\d+\-.]*:)?\/\//i;
export function isAbsoluteURL(url: string): boolean {
return absoluteREG.test(url);
}

54
src/helpers/utils.ts Normal file
View File

@ -0,0 +1,54 @@
import { isPlainObject } from './is';
export function deepMerge<T = any>(...objs: T[]): T {
const result: AnyObject = {};
objs.forEach((obj: AnyObject) =>
Object.keys(obj).forEach((key) => {
const val = obj[key];
const resultVal = result[key];
if (isPlainObject(resultVal) && isPlainObject(val)) {
result[key] = deepMerge(resultVal, val);
} else if (isPlainObject(val)) {
result[key] = deepMerge(val);
} else {
result[key] = val;
}
}),
);
return result as T;
}
export function pick<T extends AnyObject, K extends keyof T>(
obj: T,
...keys: K[]
): Pick<T, K> {
const _pick: Partial<T> = {};
keys.forEach((key: K) => (_pick[key] = obj[key]));
return _pick as Pick<T, K>;
}
export function omit<T extends AnyObject, K extends keyof T>(
obj: T,
...keys: K[]
): Omit<T, K> {
const _omit = Object.assign({}, obj);
keys.forEach((key: K) => delete _omit[key]);
return _omit;
}
export function assert(condition: boolean, msg: string) {
if (!condition) {
throwError(msg);
}
}
export function throwError(msg: string): void {
throw new Error(`[axios-miniprogram]:${msg}`);
}

View File

@ -1,214 +0,0 @@
import { AxiosPlatform } from './core/adapter';
import { AxiosRequestData, AxiosRequestParams } from './core/Axios';
const _toString = Object.prototype.toString;
export function isDate(date: any): date is Date {
return _toString.call(date) === '[object Date]';
}
export function isPlainObject<T = never>(
value: any,
): value is [T] extends never[] ? AnyObject : T {
return _toString.call(value) === '[object Object]';
}
export function isUndefined(value: any): value is undefined {
return typeof value === 'undefined';
}
export function isString(value: any): value is string {
return typeof value === 'string';
}
export function isNull(value: any): value is null {
return value === null;
}
export function isFunction<T extends Function = Function>(
value: any,
): value is T {
return typeof value === 'function';
}
export function isArray<T = any>(value: any): value is T[] {
return Array.isArray(value);
}
export function isEmptyArray<T = any>(value: any): value is [] {
return isArray<T>(value) && value.length === 0;
}
export function isPlatform(value: any): value is AxiosPlatform {
return (
isPlainObject(value) &&
isFunction(value.request) &&
isFunction(value.upload) &&
isFunction(value.download)
);
}
export function deepMerge<T = any>(...objs: T[]): T {
const result: AnyObject = {};
objs.forEach((obj: AnyObject) =>
Object.keys(obj).forEach((key) => {
const val = obj[key];
const resultVal = result[key];
if (isPlainObject(resultVal) && isPlainObject(val)) {
result[key] = deepMerge(resultVal, val);
} else if (isPlainObject(val)) {
result[key] = deepMerge(val);
} else {
result[key] = val;
}
}),
);
return result as T;
}
export function pick<T extends AnyObject, K extends keyof T>(
obj: T,
...keys: K[]
): Pick<T, K> {
const _pick: Partial<T> = {};
keys.forEach((key: K) => (_pick[key] = obj[key]));
return _pick as Pick<T, K>;
}
export function omit<T extends AnyObject, K extends keyof T>(
obj: T,
...keys: K[]
): Omit<T, K> {
const _omit = Object.assign({}, obj);
keys.forEach((key: K) => delete _omit[key]);
return _omit;
}
export function revisePlatformApiNames(platform: AnyObject): AxiosPlatform {
return {
request: platform.request ?? platform.httpRequest,
upload: platform.upload ?? platform.uploadFile,
download: platform.download ?? platform.downloadFile,
};
}
export function assert(condition: boolean, msg: string) {
if (!condition) {
throwError(msg);
}
}
export function throwError(msg: string): void {
throw new Error(`[axios-miniprogram]:${msg}`);
}
function encode(str: string): string {
return encodeURIComponent(str)
.replace(/%40/gi, '@')
.replace(/%3A/gi, ':')
.replace(/%24/g, '$')
.replace(/%2C/gi, ',')
.replace(/%20/g, '+')
.replace(/%5B/gi, '[')
.replace(/%5D/gi, ']');
}
function generateURL(url: string, serializedParams: string): string {
const hashIndex = url.indexOf('#');
if (hashIndex !== -1) {
url = url.slice(0, hashIndex);
}
if (serializedParams === '') {
return url;
}
const prefix = url.indexOf('?') === -1 ? '?' : '&';
serializedParams = `${prefix}${serializedParams}`;
return `${url}${serializedParams}`;
}
function paramsSerialization(params?: AxiosRequestParams): string {
if (!isPlainObject(params)) {
return '';
}
const parts: string[] = [];
Object.keys(params).forEach((key): void => {
const value = params[key];
if (isNull(value) || isUndefined(value) || value !== value) {
return;
}
if (Array.isArray(value)) {
key += '[]';
}
const values = [].concat(value);
values.forEach((val: any): void => {
if (isPlainObject(val)) {
val = JSON.stringify(val);
} else if (isDate(val)) {
val = val.toISOString();
}
parts.push(`${encode(key)}=${encode(val)}`);
});
});
return parts.join('&');
}
export function buildURL(
url = '',
params?: AxiosRequestParams,
paramsSerializer = paramsSerialization,
): string {
if (!isPlainObject(params)) {
return url;
}
return generateURL(url, paramsSerializer(params));
}
export const combineREG = /(?<!:)\/{2,}/g;
export function combineURL(baseURL = '', url: string): string {
const separator = '/';
return `${baseURL}${separator}${url}`.replace(combineREG, separator);
}
export const dynamicREG = /\/?(:([a-zA-Z_$][\w-$]*))\/??/g;
export function isDynamicURL(url: string): boolean {
return dynamicREG.test(url);
}
export function dynamicInterpolation(
url: string,
sourceData?: AxiosRequestParams & AxiosRequestData,
): string {
if (!isPlainObject(sourceData)) {
return url;
}
return url.replace(dynamicREG, (key1, key2, key3) =>
key1.replace(key2, sourceData[key3]),
);
}
export const absoluteREG = /^([a-z][a-z\d+\-.]*:)?\/\//i;
export function isAbsoluteURL(url: string): boolean {
return absoluteREG.test(url);
}