🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

mooljs

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mooljs - npm Package Compare versions

Comparing version
2.0.0-alpha.1
to
2.0.1-beta
+6
index.d.ts
declare module "mooljs" {
export * from "mooljs/dist/hooks/index"
export * from "mooljs/dist/utils/index"
export * from "mooljs/type"
}
import { Router } from "vue-router";
import { DefineComponent, VNode } from "vue";
type GetInitialStateReturnType<T> = T extends () => infer R ? R : never;
export interface RuntimeConfig {
routes?: IMenuRoutes[];
layout?: ILayout | ((option: GetInitialStateReturnType<RuntimeConfig["getInitialState"]>) => LayoutConfig);
getInitialState?: (typeof import("src/app.ts"))["getInitialState"] | (typeof import("src/app.tsx"))["getInitialState"];
}
export type GetInitialState = GetInitialStateReturnType<RuntimeConfig['getInitialState']>;
export interface IMenuRoutes {
path: string;
/**
* 当前页面渲染的组件,must be a absolute path
*/
component?: string;
meta?: RouteMeta;
routes?: IMenuRoutes[];
}
export interface RouteMeta {
/**
* 是否在菜单中隐藏
*/
hideInMenu?: boolean;
/**
* 是否在菜单中隐藏其子节点
*/
hideChildrenInMenu?: boolean;
/**
* 是否渲染菜单
*/
menuRender?: boolean;
/**
* 是否渲染页脚
*/
footerRender?: boolean;
/**
* 是否渲染头部
*/
headerRender?: boolean;
/**
* 当前路由是否使用内置pro layout
*/
layout?: boolean;
/**
* 权限相关设置
*/
access?: string;
/**
* 是否打平菜单
*/
flatMenu?: boolean;
/**
* 当前菜单icon
*/
icon?: string;
/**
* 菜单或当前页面标题
*/
title: string;
}
export interface ILayout {
headerRender?: DefineComponent<{}, {}, any> | (() => VNode);
footerRender?: DefineComponent<{}, {}, any> | (() => VNode);
rightRender?: DefineComponent<{}, {}, any> | (() => VNode);
unAccessible?: DefineComponent<{}, {}, any> | (() => VNode);
noFound?: DefineComponent<{}, {}, any> | (() => VNode);
logout?: DefineComponent<{}, {}, any> | (() => VNode);
}
export interface LayoutConfig extends ILayout {
menu?: {
request?: () => Promise<IMenuRoutes[]>;
};
}
export interface UseProviderOptions {
config: RuntimeConfig;
access?: {
default: (typeof import("src/access"))["default"];
};
router?: Router;
}
+1
-2
export * from './hooks';
export * from './utils';
export * from '../lib/createService.ts';
export * from './utils';

@@ -1,3 +0,2 @@

export * from './createService';
export * from './hooks';
export * from './utils';
{
"name": "mooljs",
"version": "2.0.0-alpha.1",
"version": "2.0.1-beta",
"description": "function tool library for mooljs",

@@ -9,3 +9,2 @@ "main": "dist/index.js",

".": "./dist/index.js",
"./useProvider":"./dist/useProvider.js",
"./hooks":"./dist/hooks/index",

@@ -27,3 +26,5 @@ "./utils":"./dist/utils/index"

"dist",
"lib"
"lib",
"type.d.ts",
"index.d.ts"
],

@@ -30,0 +31,0 @@ "author": "Merlin Hong",

import axios, {
GenericAbortSignal,
AxiosStatic,
AxiosRequestConfig,
AxiosProgressEvent,
ResponseType,
AxiosInstance,
InternalAxiosRequestConfig,
AxiosResponse,
AxiosInterceptorManager,
RawAxiosRequestHeaders,
CreateAxiosDefaults,
CanceledError,
} from "axios";
import qs from "qs";
import { isPlainObject } from "./utils/index";
import { IncomingMessage, ServerResponse } from "http";
export enum StateEnum {
OK = 200,
CREATED = 201,
NO_CONTENT = 204,
INVALID_REQUEST = 400,
UNAUTHORIZED = 401,
FORBIDDEN = 403,
NOT_FOUND = 404,
INTERNAL_SERVER_ERROR = 500,
NOT_AUTH = 820101,
ERR_CANCELED = "ERR_CANCELED",
}
const defaultSettings: DEFAULTSETTING = {
type: "post",
url: "",
data: {},
headers: {},
timeout: 8000,
contentType: "application/json",
withCredentials: true,
baseURL: "",
success: () => {},
error: () => {},
complete: () => {},
};
export interface RespThisType {
req: IncomingMessage;
res: ServerResponse;
parseJson: () => any;
}
// export type MethodType = "get" | "post" | "put" | "delete" | "patch";
export type Recordable<T = any> = Record<string, T>;
interface DEFAULTSETTING<T = any, K = Record<string, any>> {
/**
* mock后端接口数据
*/
mock?: {
/**
* 设置响应时间
*/
timeout?: number;
/**
* 自定义状态码
*/
statusCode?: number;
/**
* @default `'函数类型'`
* ((
this: RespThisType,
opt: { url: Recordable; body: Recordable; query: Recordable; headers: Recordable },
) => any)
*
* @description 自定义返回响应数据
*/
response?:
| ((
this: RespThisType,
opt: {
url: Recordable;
body: Recordable;
query: Recordable;
headers: Recordable;
}
) => any)
| any;
/**
* 可自定义设置响应体
* @param this 响应实例类型
* @param req 请求体
* @param res 响应体
* @returns
*/
rawResponse?: (
this: RespThisType,
req: IncomingMessage,
res: ServerResponse
) => void;
};
/**
* default `'post'`
* 请求类型
* */
type?: keyof HttpMethodMap;
/**请求路径 */
url: string;
/**请求体 */
data?: K;
/**请求超时时间 */
timeout?: number | undefined;
/**请求头 */
headers?: RawAxiosRequestHeaders;
/**项目根路径类别 */
root?: T;
/**
* default `'application/json'`
* 请求体编码类型
*/
contentType?:
| "text/html"
| "text/plain"
| "multipart/form-data"
| "application/json"
| "application/x-www-form-urlencoded"
| "application/octet-stream";
/**返回的响应类型 */
responseType?: ResponseType;
/**跨域成功是否携带cookie */
withCredentials?: boolean;
/**请求根路径,如果遇到跨域问题到vite.config配好代理后在baseURL处修改逻辑 */
baseURL?: string;
/**文件上传的file对象集合 */
files?: Array<{
file?: File;
name?: string;
}>;
/**上传进度 */
uploading?: ((progressEvent: AxiosProgressEvent) => void) | undefined;
/**下载进度 */
downloading?: ((progressEvent: AxiosProgressEvent) => void) | undefined;
onDownloadProgress?:
| ((progressEvent: AxiosProgressEvent) => void)
| undefined;
onUploadProgress?: ((progressEvent: AxiosProgressEvent) => void) | undefined;
/**请求成功回调 */
success?: Function;
/**请求报错回调 */
error?: Function;
/**请求完成回调 */
complete?: Function;
/**
* 取消请求
*/
cancelToken?: AxiosStatic['CancelToken'];
/**
* 信号
*/
signal?: GenericAbortSignal;
}
export type IRootKeys<T extends { env: any; default?: any }> = keyof IViteKeys<
T["env"],
T["default"]
>;
export type IUrlConfig<T = any, K = {}> = Record<string, DEFAULTSETTING<T, K>>;
// 定义一个将以 VITE 开头的属性名转换为小写的映射类型
export type IViteKeys<T, G> = {
[K in keyof T as K extends `VITE_${infer Rest}`
? G extends K
? never
: K
: never]: T[K];
};
// 定义一个将以 VITE 开头的属性名转换为小写的映射类型
export type IEnvKeys<T> = {
[K in keyof T as K extends `VITE_${infer Rest}` ? K : never]: T[K];
};
/**
* 推导接口参数类型
*/
type ApiParams<T, K extends keyof T> = T[K] extends { data: infer D } ? D : undefined;
export type IConfig<T, G = string, L = CommonResponse> = {
env: T;
default?: G & keyof IEnvKeys<T>;
baseURL?: string;
response?: L;
};
// Add this type definition
type ModuleInstance<T, L> = {
[K in keyof T]: {
[P in keyof T[K]]: (data: ApiParams<T[K], P>) => Promise<L>;
};
};
// // 构建服务模块类型
type ServiceModules = {
[K in keyof ServiceTypes]: ServiceTypes[K];
};
// 修改 ApiService 类定义,增加泛型约束
export class CreateService<
T extends Record<string, any>,
G extends string,
H extends IUrlConfig,
L = CommonResponse,
M extends ServiceModules = ServiceModules
> {
private axiosInstance: AxiosInstance;
private defaultSettings: DEFAULTSETTING;
private _env: Record<string, any>;
private _default: string;
private baseURL: string;
private complete: boolean = false;
private Modules: M | ServiceModules;
// 使用更灵活的索引签名
[key: string]: any;
constructor(config?: IConfig<T, G, L>, modules?: M) {
this.defaultSettings = defaultSettings;
this._env = config?.env || {};
this._default = config?.default ?? "";
this.baseURL = config?.baseURL ?? "";
// 如果没有传入modules,则自动加载
this.Modules = modules || this.loadModules();
// 动态添加模块方法
if (this.Modules) {
for (const [name, apis] of Object.entries(this.Modules)) {
const apiInstance = this.setApi(apis);
Object.defineProperty(this, name, {
value: apiInstance,
enumerable: true,
configurable: false,
writable: false,
});
}
}
this.axiosInstance = axios.create(this.getAxiosConfig());
this.init();
}
private loadModules(): ServiceModules {
// 自动导入所有模块
const moduleFiles = import.meta.glob<{ default: IUrlConfig }>(
"/src/service/!(index).ts",
{ eager: true }
);
console.log(3333, moduleFiles);
const modules = {} as Record<string, IUrlConfig>;
for (const path in moduleFiles) {
const moduleName = path.match(/([^/]+)\.ts$/)?.[1];
if (moduleName && moduleName !== "index") {
modules[moduleName] = moduleFiles[path].default;
}
}
return modules as ServiceModules;
}
private setApi(api?: H) {
const apiMap: Record<string, any> = {};
if (!api) return apiMap;
for (const key in api) {
if (Object.prototype.hasOwnProperty.call(api, key)) {
const conf = api[key];
apiMap[key] = (data: any) =>
this.request(
this.mergeConfig({
...conf,
data,
})
);
}
}
return apiMap;
}
private init() {
// 添加请求拦截器
this.axiosInstance.interceptors.request.use(
(config) => {
// 可以在这里添加自定义的请求拦截逻辑
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 添加响应拦截器
this.axiosInstance.interceptors.response.use(
(response) => {
// 可以在这里添加自定义的响应拦截逻辑
return response.data;
},
(error) => {
// 处理错误
return Promise.reject(error);
}
);
}
private getAxiosConfig() {
const config: CreateAxiosDefaults<any> | undefined = {
timeout: this.defaultSettings.timeout,
headers: this.defaultSettings.headers,
};
if (this._default) {
config.baseURL = this._default.startsWith("VITE")
? this._env[this._default]
: this._default;
}
if (this.baseURL) {
config.baseURL = this.baseURL;
}
return config;
}
// 合并配置
private mergeConfig(options: DEFAULTSETTING): DEFAULTSETTING {
return { ...this.defaultSettings, ...options };
}
/**
* 取消当前正在发起的请求
*/
public cancel(msg?: string, confirm?: () => Promise<any>) {
if (this.complete || !this.source) return;
if (confirm) {
confirm().then(() => {
this.source.cancel(msg); // 取消请求
});
} else {
this.source.cancel(msg);
}
}
// 请求方法
async request<K = L>(
options: DEFAULTSETTING<keyof IViteKeys<T, G>>
): Promise<K> {
const config = this.mergeConfig(options);
// // 创建一个 AbortController 实例
// this.controller = new AbortController();
// const signal = this.controller.signal;
this.source = axios.CancelToken.source();
this.complete = false;
const params: AxiosRequestConfig = {
url: config.url,
method: config.type,
data: config.data,
headers: config.headers,
responseType: config.responseType,
withCredentials: config.withCredentials,
onUploadProgress: config.uploading,
onDownloadProgress: config.downloading,
baseURL: this.baseURL,
cancelToken: this.source.token,
};
if (config.root) {
params.baseURL = this._env[config.root] ?? "";
}
if (config.baseURL) {
params.baseURL = config.baseURL;
}
if (params.headers) {
params.headers["Content-Type"] = config.contentType;
if (config.type === "get" && isPlainObject(config.data)) {
params.url += "?" + qs.stringify(config.data);
} else {
params.data = JSON.stringify(config.data);
}
}
return new Promise((resolve, reject) => {
this.axiosInstance(params)
.then((response: AxiosResponse | CanceledError<any>) => {
if (!response.status) {
(response as AxiosResponse).data = { ...response };
response.status = response.code || 200;
}
const { status, data } = response as AxiosResponse;
if (
status !== 200 ||
(response as CanceledError<any>).code == StateEnum.ERR_CANCELED
) {
reject(data);
config.error && config.error(data);
} else {
config.success && config.success(data);
resolve(data);
}
})
.catch((err) => {
config.error && config.error(err);
reject(err);
})
.finally(() => {
config.complete && config.complete();
this.complete = true;
});
});
}
// 自定义请求拦截器
setRequestInterceptor(
...interceptor: Parameters<
AxiosInterceptorManager<InternalAxiosRequestConfig<any>>["use"]
>
) {
this.axiosInstance.interceptors.request.use(...interceptor);
}
// 自定义响应拦截器
setResponseInterceptor(
...interceptor: Parameters<
AxiosInterceptorManager<AxiosResponse<any, any>>["use"]
>
) {
this.axiosInstance.interceptors.response.use(...interceptor);
}
// 添加一个方法来获取模块实例,这将帮助类型推断
getModuleInstance<K extends keyof M>(
moduleName: K
): {
[P in keyof M[K]]: (data: ApiParams<M[K], P>) => Promise<L>;
} {
return this[moduleName] as {
[P in keyof M[K]]: (data: ApiParams<M[K], P>) => Promise<L>;
};
}
}
// 修改 ApiServiceWithModules 类型定义
export type ApiServiceWithModules<
T extends Record<string, any>,
G extends string,
M extends ServiceModules
> = CreateService<T, G, IUrlConfig, CommonResponse, M> & {
[K in keyof M]: {
[P in keyof M[K]]: ApiParams<M[K], P> extends undefined ?(data?: {}) => Promise<CommonResponse>:(data: ApiParams<M[K], P>) => Promise<CommonResponse>;
};
};
// 添加类型转换函数
export function createServiceWithModules<
T extends Record<string, any>,
G extends string,
M extends ServiceModules
>(
apiService: CreateService<T, G, IUrlConfig, CommonResponse, M>
): ApiServiceWithModules<T, G, M> {
return apiService as ApiServiceWithModules<T, G, M>;
}
export const request = new CreateService();