@umijs/plugins 4.0.0-beta.12 → 4.0.0-beta.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/access.js +73 -1
- package/dist/{dayjs.d.ts → analytics.d.ts} +0 -0
- package/dist/analytics.js +67 -0
- package/dist/antd.js +0 -25
- package/dist/dva.d.ts +3 -9
- package/dist/dva.js +59 -107
- package/dist/initial-state.js +112 -1
- package/dist/layout.js +479 -1
- package/dist/locale.d.ts +1 -0
- package/dist/locale.js +199 -1
- package/dist/model.d.ts +0 -9
- package/dist/model.js +71 -74
- package/dist/moment2dayjs.d.ts +3 -0
- package/dist/moment2dayjs.js +96 -0
- package/dist/qiankun/constants.d.ts +5 -0
- package/dist/qiankun/constants.js +8 -0
- package/dist/qiankun/master.d.ts +6 -0
- package/dist/qiankun/master.js +114 -0
- package/dist/qiankun/slave.d.ts +3 -0
- package/dist/qiankun/slave.js +141 -0
- package/dist/qiankun.js +15 -1
- package/dist/request.js +297 -1
- package/dist/utils/{getIdentifierDeclaration.d.ts → astUtils.d.ts} +0 -0
- package/dist/utils/{getIdentifierDeclaration.js → astUtils.js} +0 -0
- package/dist/utils/localeUtils.d.ts +33 -0
- package/dist/utils/localeUtils.js +135 -0
- package/dist/utils/modelUtils.d.ts +35 -0
- package/dist/utils/modelUtils.js +145 -0
- package/libs/dva.ts +10 -0
- package/libs/locale/SelectLang.tpl +478 -0
- package/libs/locale/locale.tpl +82 -0
- package/libs/locale/localeExports.tpl +271 -0
- package/libs/locale/runtime.tpl +33 -0
- package/libs/model.tsx +140 -0
- package/libs/qiankun/master/AntdErrorBoundary.tsx +34 -0
- package/libs/qiankun/master/AntdLoader.tsx +15 -0
- package/libs/qiankun/master/ErrorBoundary.tsx +7 -0
- package/libs/qiankun/master/MicroApp.tsx +262 -0
- package/libs/qiankun/master/MicroAppWithMemoHistory.tsx +43 -0
- package/libs/qiankun/master/common.ts +133 -0
- package/libs/qiankun/master/constants.ts +7 -0
- package/libs/qiankun/master/getMicroAppRouteComponent.tsx.tpl +45 -0
- package/libs/qiankun/master/masterRuntimePlugin.tsx +130 -0
- package/libs/qiankun/master/types.ts +44 -0
- package/libs/qiankun/slave/connectMaster.tsx +15 -0
- package/libs/qiankun/slave/lifecycles.ts +149 -0
- package/libs/qiankun/slave/qiankunModel.ts +19 -0
- package/libs/qiankun/slave/slaveRuntimePlugin.ts +21 -0
- package/package.json +20 -6
- package/dist/dayjs.js +0 -5
package/dist/request.js
CHANGED
|
@@ -1,5 +1,301 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("@umijs/utils");
|
|
4
|
+
const path_1 = require("path");
|
|
3
5
|
exports.default = (api) => {
|
|
4
|
-
api
|
|
6
|
+
api.describe({
|
|
7
|
+
key: 'request',
|
|
8
|
+
config: {
|
|
9
|
+
schema: (joi) => {
|
|
10
|
+
return joi.object();
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
enableBy: api.EnableBy.config,
|
|
14
|
+
});
|
|
15
|
+
api.addRuntimePluginKey(() => ['request']);
|
|
16
|
+
const requestTpl = `
|
|
17
|
+
import axios, {
|
|
18
|
+
type AxiosInstance,
|
|
19
|
+
type AxiosRequestConfig,
|
|
20
|
+
type AxiosResponse,
|
|
21
|
+
} from '{{{axiosPath}}}';
|
|
22
|
+
import useUmiRequest, { UseRequestProvider } from '{{{umiRequestPath}}}';
|
|
23
|
+
import { message, notification } from '{{{antdPkg}}}';
|
|
24
|
+
import { ApplyPluginsType } from 'umi';
|
|
25
|
+
import { getPluginManager } from '../core/plugin';
|
|
26
|
+
|
|
27
|
+
import {
|
|
28
|
+
BaseOptions,
|
|
29
|
+
BasePaginatedOptions,
|
|
30
|
+
BaseResult,
|
|
31
|
+
CombineService,
|
|
32
|
+
LoadMoreFormatReturn,
|
|
33
|
+
LoadMoreOptions,
|
|
34
|
+
LoadMoreOptionsWithFormat,
|
|
35
|
+
LoadMoreParams,
|
|
36
|
+
LoadMoreResult,
|
|
37
|
+
OptionsWithFormat,
|
|
38
|
+
PaginatedFormatReturn,
|
|
39
|
+
PaginatedOptionsWithFormat,
|
|
40
|
+
PaginatedParams,
|
|
41
|
+
PaginatedResult,
|
|
42
|
+
} from '{{{umiRequestPath}}}/es/types';
|
|
43
|
+
|
|
44
|
+
type ResultWithData< T = any > = { data?: T; [key: string]: any };
|
|
45
|
+
|
|
46
|
+
function useRequest<
|
|
47
|
+
R = any,
|
|
48
|
+
P extends any[] = any,
|
|
49
|
+
U = any,
|
|
50
|
+
UU extends U = any,
|
|
51
|
+
>(
|
|
52
|
+
service: CombineService<R, P>,
|
|
53
|
+
options: OptionsWithFormat<R, P, U, UU>,
|
|
54
|
+
): BaseResult<U, P>;
|
|
55
|
+
function useRequest<R extends ResultWithData = any, P extends any[] = any>(
|
|
56
|
+
service: CombineService<R, P>,
|
|
57
|
+
options?: BaseOptions<R['data'], P>,
|
|
58
|
+
): BaseResult<R['data'], P>;
|
|
59
|
+
function useRequest<R extends LoadMoreFormatReturn = any, RR = any>(
|
|
60
|
+
service: CombineService<RR, LoadMoreParams<R>>,
|
|
61
|
+
options: LoadMoreOptionsWithFormat<R, RR>,
|
|
62
|
+
): LoadMoreResult<R>;
|
|
63
|
+
function useRequest<
|
|
64
|
+
R extends ResultWithData<LoadMoreFormatReturn | any> = any,
|
|
65
|
+
RR extends R = any,
|
|
66
|
+
>(
|
|
67
|
+
service: CombineService<R, LoadMoreParams<R['data']>>,
|
|
68
|
+
options: LoadMoreOptions<RR['data']>,
|
|
69
|
+
): LoadMoreResult<R['data']>;
|
|
70
|
+
|
|
71
|
+
function useRequest<R = any, Item = any, U extends Item = any>(
|
|
72
|
+
service: CombineService<R, PaginatedParams>,
|
|
73
|
+
options: PaginatedOptionsWithFormat<R, Item, U>,
|
|
74
|
+
): PaginatedResult<Item>;
|
|
75
|
+
function useRequest<Item = any, U extends Item = any>(
|
|
76
|
+
service: CombineService<
|
|
77
|
+
ResultWithData<PaginatedFormatReturn<Item>>,
|
|
78
|
+
PaginatedParams
|
|
79
|
+
>,
|
|
80
|
+
options: BasePaginatedOptions<U>,
|
|
81
|
+
): PaginatedResult<Item>;
|
|
82
|
+
function useRequest(service: any, options: any = {}) {
|
|
83
|
+
return useUmiRequest(service, {
|
|
84
|
+
formatResult: result => result?.data,
|
|
85
|
+
requestMethod: (requestOptions: any) => {
|
|
86
|
+
if (typeof requestOptions === 'string') {
|
|
87
|
+
return request(requestOptions);
|
|
88
|
+
}
|
|
89
|
+
if (typeof requestOptions === 'object') {
|
|
90
|
+
const { url, ...rest } = requestOptions;
|
|
91
|
+
return request(url, rest);
|
|
92
|
+
}
|
|
93
|
+
throw new Error('request options error');
|
|
94
|
+
},
|
|
95
|
+
...options,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface RequestConfig extends AxiosRequestConfig {
|
|
100
|
+
errorConfig?: {
|
|
101
|
+
errorPage?: string;
|
|
102
|
+
adaptor?: IAdaptor; // adaptor 用以用户将不满足接口的后端数据修改成 errorInfo
|
|
103
|
+
errorHandler?: IErrorHandler;
|
|
104
|
+
defaultNoneResponseErrorMessage?: string;
|
|
105
|
+
defaultRequestErrorMessage?: string;
|
|
106
|
+
};
|
|
107
|
+
formatResultAdaptor?: IFormatResultAdaptor;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export enum ErrorShowType {
|
|
111
|
+
SILENT = 0,
|
|
112
|
+
WARN_MESSAGE = 1,
|
|
113
|
+
ERROR_MESSAGE = 2,
|
|
114
|
+
NOTIFICATION = 3,
|
|
115
|
+
REDIRECT = 9,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface IErrorInfo {
|
|
119
|
+
success: boolean;
|
|
120
|
+
data?: any;
|
|
121
|
+
errorCode?: string;
|
|
122
|
+
errorMessage?: string;
|
|
123
|
+
showType?: ErrorShowType;
|
|
124
|
+
traceId?: string;
|
|
125
|
+
host?: string;
|
|
126
|
+
[key: string]: any;
|
|
127
|
+
}
|
|
128
|
+
// resData 其实就是 response.data, response 则是 axios 的响应对象
|
|
129
|
+
interface IAdaptor {
|
|
130
|
+
(resData: any, response: AxiosResponse): IErrorInfo;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface RequestError extends Error {
|
|
134
|
+
data?: any;
|
|
135
|
+
info?: IErrorInfo;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
interface IRequest {
|
|
139
|
+
(
|
|
140
|
+
url: string,
|
|
141
|
+
opts: AxiosRequestConfig & { skipErrorHandler?: boolean },
|
|
142
|
+
): Promise<AxiosResponse<any, any>>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
interface IErrorHandler {
|
|
146
|
+
(error: RequestError, opts: AxiosRequestConfig & { skipErrorHandler?: boolean }, config: RequestConfig): void;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
interface IFormatResultAdaptor {
|
|
150
|
+
(res: AxiosResponse): any;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const defaultErrorHandler: IErrorHandler = (error, opts, config) => {
|
|
154
|
+
if (opts?.skipErrorHandler) throw error;
|
|
155
|
+
const { errorConfig } = config;
|
|
156
|
+
if (error.response) {
|
|
157
|
+
// 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围 或者 成功响应,success字段为false 由我们抛出的错误
|
|
158
|
+
let errorInfo: IErrorInfo | undefined;
|
|
159
|
+
// 不是我们的错误
|
|
160
|
+
if(error.name === 'ResponseError'){
|
|
161
|
+
const adaptor: IAdaptor =
|
|
162
|
+
errorConfig?.adaptor || ((errorData) => errorData);
|
|
163
|
+
errorInfo = adaptor(error.response.data, error.response);
|
|
164
|
+
error.info = errorInfo;
|
|
165
|
+
error.data = error.response.data;
|
|
166
|
+
}
|
|
167
|
+
errorInfo = error.info;
|
|
168
|
+
if (errorInfo) {
|
|
169
|
+
const { errorMessage, errorCode } = errorInfo;
|
|
170
|
+
switch (errorInfo.showType) {
|
|
171
|
+
case ErrorShowType.SILENT:
|
|
172
|
+
// do nothong
|
|
173
|
+
break;
|
|
174
|
+
case ErrorShowType.WARN_MESSAGE:
|
|
175
|
+
message.warn(errorMessage);
|
|
176
|
+
break;
|
|
177
|
+
case ErrorShowType.ERROR_MESSAGE:
|
|
178
|
+
message.error(errorMessage);
|
|
179
|
+
break;
|
|
180
|
+
case ErrorShowType.NOTIFICATION:
|
|
181
|
+
notification.open({ description: errorMessage, message: errorCode });
|
|
182
|
+
break;
|
|
183
|
+
case ErrorShowType.REDIRECT:
|
|
184
|
+
// TODO: redirect
|
|
185
|
+
break;
|
|
186
|
+
default:
|
|
187
|
+
message.error(errorMessage);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
} else if (error.request) {
|
|
191
|
+
// 请求已经成功发起,但没有收到响应
|
|
192
|
+
// \`error.request\` 在浏览器中是 XMLHttpRequest 的实例,
|
|
193
|
+
// 而在node.js中是 http.ClientRequest 的实例
|
|
194
|
+
message.error(
|
|
195
|
+
errorConfig?.defaultNoneResponseErrorMessage ||
|
|
196
|
+
'None response! Please retry.',
|
|
197
|
+
);
|
|
198
|
+
} else {
|
|
199
|
+
// 发送请求时出了点问题
|
|
200
|
+
message.error(
|
|
201
|
+
errorConfig?.defaultRequestErrorMessage || 'Request error, please retry.',
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
throw error;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
let requestInstance: AxiosInstance;
|
|
208
|
+
let config: RequestConfig;
|
|
209
|
+
const getConfig = (): RequestConfig => {
|
|
210
|
+
if (config) return config;
|
|
211
|
+
config = getPluginManager().applyPlugins({
|
|
212
|
+
key: 'request',
|
|
213
|
+
type: ApplyPluginsType.modify,
|
|
214
|
+
initialValue: {},
|
|
215
|
+
});
|
|
216
|
+
return config;
|
|
217
|
+
};
|
|
218
|
+
const getRequestInstance = (): AxiosInstance => {
|
|
219
|
+
if (requestInstance) return requestInstance;
|
|
220
|
+
const config = getConfig();
|
|
221
|
+
requestInstance = axios.create(config);
|
|
222
|
+
|
|
223
|
+
// 当响应的数据 success 是 false 的时候,抛出 error 以供 errorHandler 处理。
|
|
224
|
+
requestInstance.interceptors.response.use((response)=>{
|
|
225
|
+
const {data} = response;
|
|
226
|
+
const adaptor = config?.errorConfig?.adaptor || ((resData) => resData);
|
|
227
|
+
const errorInfo = adaptor(data,response);
|
|
228
|
+
if(errorInfo.success === false){
|
|
229
|
+
const error: RequestError = new Error(errorInfo.errorMessage);
|
|
230
|
+
error.name = 'BizError';
|
|
231
|
+
error.data = data;
|
|
232
|
+
error.info = errorInfo;
|
|
233
|
+
error.response = response;
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
return response;
|
|
237
|
+
})
|
|
238
|
+
return requestInstance;
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const request: IRequest = (url, opts) => {
|
|
242
|
+
const requestInstance = getRequestInstance();
|
|
243
|
+
const config = getConfig();
|
|
244
|
+
return new Promise((resolve, reject) => {
|
|
245
|
+
requestInstance
|
|
246
|
+
.request({ ...opts, url })
|
|
247
|
+
.then((res) => {
|
|
248
|
+
const formatResultAdaptor =
|
|
249
|
+
config?.formatResultAdaptor || ((res) => res.data);
|
|
250
|
+
resolve(formatResultAdaptor(res));
|
|
251
|
+
})
|
|
252
|
+
.catch((error) => {
|
|
253
|
+
try {
|
|
254
|
+
const handler =
|
|
255
|
+
config.errorConfig?.errorHandler || defaultErrorHandler;
|
|
256
|
+
handler(error, opts, config);
|
|
257
|
+
} catch (e) {
|
|
258
|
+
reject(e);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
export {
|
|
265
|
+
useRequest,
|
|
266
|
+
UseRequestProvider,
|
|
267
|
+
AxiosRequestConfig,
|
|
268
|
+
request,
|
|
269
|
+
AxiosInstance,
|
|
270
|
+
AxiosResponse,
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
`;
|
|
274
|
+
api.onGenerateFiles(() => {
|
|
275
|
+
var _a;
|
|
276
|
+
const umiRequestPath = (0, path_1.dirname)(require.resolve('@ahooksjs/use-request/package.json'));
|
|
277
|
+
const axiosPath = (0, path_1.dirname)(require.resolve('axios/package.json'));
|
|
278
|
+
const antdPkg =
|
|
279
|
+
// use path from antd plugin first
|
|
280
|
+
((_a = api.appData.antd) === null || _a === void 0 ? void 0 : _a.pkgPath) ||
|
|
281
|
+
(0, path_1.dirname)(require.resolve('antd/package.json'));
|
|
282
|
+
api.writeTmpFile({
|
|
283
|
+
path: 'request.ts',
|
|
284
|
+
content: utils_1.Mustache.render(requestTpl, {
|
|
285
|
+
umiRequestPath,
|
|
286
|
+
axiosPath,
|
|
287
|
+
antdPkg,
|
|
288
|
+
}),
|
|
289
|
+
});
|
|
290
|
+
api.writeTmpFile({
|
|
291
|
+
path: 'index.ts',
|
|
292
|
+
content: `
|
|
293
|
+
export {
|
|
294
|
+
useRequest,
|
|
295
|
+
UseRequestProvider,
|
|
296
|
+
request,
|
|
297
|
+
} from './request';
|
|
298
|
+
`,
|
|
299
|
+
});
|
|
300
|
+
});
|
|
5
301
|
};
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare type IAddAntdLocales = (args: {
|
|
2
|
+
lang: string;
|
|
3
|
+
country: string;
|
|
4
|
+
}) => Promise<string[]>;
|
|
5
|
+
export interface IGetLocaleFileListOpts {
|
|
6
|
+
localeFolder: string;
|
|
7
|
+
separator?: string;
|
|
8
|
+
absSrcPath?: string;
|
|
9
|
+
absPagesPath?: string;
|
|
10
|
+
addAntdLocales: IAddAntdLocales;
|
|
11
|
+
resolveKey: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 获取 moment 包的 locale 名称
|
|
15
|
+
* @param lang 语言
|
|
16
|
+
* @param country 国家
|
|
17
|
+
* @param resolveKey 用来resolve的key,moment 或者 dayjs,为了使 dayjs 可以替换 moment
|
|
18
|
+
*/
|
|
19
|
+
export declare const getMomentLocale: (lang: string, country: string, resolveKey: string) => {
|
|
20
|
+
momentLocale: string;
|
|
21
|
+
};
|
|
22
|
+
export declare const getAntdLocale: (lang: string, country: string) => string;
|
|
23
|
+
export interface IGetLocaleFileListResult {
|
|
24
|
+
lang: string;
|
|
25
|
+
country: string;
|
|
26
|
+
name: string;
|
|
27
|
+
paths: string[];
|
|
28
|
+
antdLocale: string[];
|
|
29
|
+
momentLocale: string;
|
|
30
|
+
}
|
|
31
|
+
export declare const getLocaleList: (opts: IGetLocaleFileListOpts) => Promise<IGetLocaleFileListResult[]>;
|
|
32
|
+
export declare const exactLocalePaths: (data: IGetLocaleFileListResult[]) => string[];
|
|
33
|
+
export declare function isNeedPolyfill(targets?: {}): boolean;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.isNeedPolyfill = exports.exactLocalePaths = exports.getLocaleList = exports.getAntdLocale = exports.getMomentLocale = void 0;
|
|
13
|
+
const utils_1 = require("@umijs/utils");
|
|
14
|
+
const fs_1 = require("fs");
|
|
15
|
+
const path_1 = require("path");
|
|
16
|
+
/**
|
|
17
|
+
* 获取 moment 包的 locale 名称
|
|
18
|
+
* @param lang 语言
|
|
19
|
+
* @param country 国家
|
|
20
|
+
* @param resolveKey 用来resolve的key,moment 或者 dayjs,为了使 dayjs 可以替换 moment
|
|
21
|
+
*/
|
|
22
|
+
const getMomentLocale = (lang, country, resolveKey) => {
|
|
23
|
+
var _a, _b;
|
|
24
|
+
const momentLocation = require
|
|
25
|
+
.resolve(`${resolveKey}/locale/zh-cn`)
|
|
26
|
+
.replace(/zh\-cn\.js$/, '');
|
|
27
|
+
if ((0, fs_1.existsSync)((0, path_1.join)(momentLocation, `${lang}-${(_a = country === null || country === void 0 ? void 0 : country.toLocaleLowerCase) === null || _a === void 0 ? void 0 : _a.call(country)}.js`))) {
|
|
28
|
+
const momentLocale = `${lang}-${(_b = country === null || country === void 0 ? void 0 : country.toLocaleLowerCase) === null || _b === void 0 ? void 0 : _b.call(country)}`;
|
|
29
|
+
return {
|
|
30
|
+
momentLocale,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if ((0, fs_1.existsSync)((0, path_1.join)(momentLocation, `${lang}.js`))) {
|
|
34
|
+
return {
|
|
35
|
+
momentLocale: lang,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return { momentLocale: '' };
|
|
39
|
+
};
|
|
40
|
+
exports.getMomentLocale = getMomentLocale;
|
|
41
|
+
const getAntdLocale = (lang, country) => `${lang}_${(country || lang).toLocaleUpperCase()}`;
|
|
42
|
+
exports.getAntdLocale = getAntdLocale;
|
|
43
|
+
/**
|
|
44
|
+
* 有些情况下可能项目包含的locale和antd的不匹配
|
|
45
|
+
* 这个方法用于检测
|
|
46
|
+
* @param localePath
|
|
47
|
+
* @returns
|
|
48
|
+
*/
|
|
49
|
+
const modulesHasLocale = (localePath) => {
|
|
50
|
+
try {
|
|
51
|
+
require.resolve(localePath);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const getLocaleList = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
59
|
+
const { localeFolder, separator = '-', absSrcPath = '', absPagesPath = '', addAntdLocales, resolveKey = 'moment', } = opts;
|
|
60
|
+
const localeFileMath = new RegExp(`^([a-z]{2})${separator}?([A-Z]{2})?\.(js|json|ts)$`);
|
|
61
|
+
const localeFiles = utils_1.glob
|
|
62
|
+
.sync('*.{ts,js,json}', {
|
|
63
|
+
cwd: (0, utils_1.winPath)((0, path_1.join)(absSrcPath, localeFolder)),
|
|
64
|
+
})
|
|
65
|
+
.map((name) => (0, utils_1.winPath)((0, path_1.join)(absSrcPath, localeFolder, name)))
|
|
66
|
+
.concat(utils_1.glob
|
|
67
|
+
.sync(`**/${localeFolder}/*.{ts,js,json}`, {
|
|
68
|
+
cwd: absPagesPath,
|
|
69
|
+
})
|
|
70
|
+
.map((name) => (0, utils_1.winPath)((0, path_1.join)(absPagesPath, name))))
|
|
71
|
+
.filter((p) => localeFileMath.test((0, path_1.basename)(p)) && (0, fs_1.existsSync)(p))
|
|
72
|
+
.map((fullName) => {
|
|
73
|
+
var _a, _b;
|
|
74
|
+
const fileName = (0, path_1.basename)(fullName);
|
|
75
|
+
const fileInfo = (_b = (_a = localeFileMath
|
|
76
|
+
.exec(fileName)) === null || _a === void 0 ? void 0 : _a.slice(1, 3)) === null || _b === void 0 ? void 0 : _b.filter(Boolean);
|
|
77
|
+
return {
|
|
78
|
+
name: (fileInfo || []).join(separator),
|
|
79
|
+
path: fullName,
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
const groups = utils_1.lodash.groupBy(localeFiles, 'name');
|
|
83
|
+
const promises = Object.keys(groups).map((name) => __awaiter(void 0, void 0, void 0, function* () {
|
|
84
|
+
const [lang, country = ''] = name.split(separator);
|
|
85
|
+
const { momentLocale } = (0, exports.getMomentLocale)(lang, country, resolveKey);
|
|
86
|
+
const antdLocale = utils_1.lodash
|
|
87
|
+
.uniq(yield addAntdLocales({ lang, country }))
|
|
88
|
+
.filter((localePath) => modulesHasLocale(localePath));
|
|
89
|
+
return {
|
|
90
|
+
lang,
|
|
91
|
+
name,
|
|
92
|
+
// react-intl Function.supportedLocalesOf
|
|
93
|
+
// Uncaught RangeError: Incorrect locale information provided
|
|
94
|
+
locale: name.split(separator).join('-'),
|
|
95
|
+
country,
|
|
96
|
+
antdLocale,
|
|
97
|
+
paths: groups[name].map((item) => (0, utils_1.winPath)(item.path)),
|
|
98
|
+
momentLocale,
|
|
99
|
+
};
|
|
100
|
+
}));
|
|
101
|
+
return Promise.all(promises);
|
|
102
|
+
});
|
|
103
|
+
exports.getLocaleList = getLocaleList;
|
|
104
|
+
const exactLocalePaths = (data) => {
|
|
105
|
+
return utils_1.lodash.flatten(data.map((item) => item.paths));
|
|
106
|
+
};
|
|
107
|
+
exports.exactLocalePaths = exactLocalePaths;
|
|
108
|
+
function isNeedPolyfill(targets = {}) {
|
|
109
|
+
// data come from https://caniuse.com/#search=intl
|
|
110
|
+
// you can find all browsers in https://github.com/browserslist/browserslist#browsers
|
|
111
|
+
const polyfillTargets = {
|
|
112
|
+
ie: 10,
|
|
113
|
+
firefox: 28,
|
|
114
|
+
chrome: 23,
|
|
115
|
+
safari: 9.1,
|
|
116
|
+
opera: 12.1,
|
|
117
|
+
ios: 9.3,
|
|
118
|
+
ios_saf: 9.3,
|
|
119
|
+
operamini: Infinity,
|
|
120
|
+
op_mini: Infinity,
|
|
121
|
+
android: 4.3,
|
|
122
|
+
blackberry: Infinity,
|
|
123
|
+
operamobile: 12.1,
|
|
124
|
+
op_mob: 12.1,
|
|
125
|
+
explorermobil: 10,
|
|
126
|
+
ie_mob: 10,
|
|
127
|
+
ucandroid: Infinity,
|
|
128
|
+
};
|
|
129
|
+
return (Object.keys(targets).find((key) => {
|
|
130
|
+
const lowKey = key.toLocaleLowerCase();
|
|
131
|
+
// @ts-ignore
|
|
132
|
+
return polyfillTargets[lowKey] && polyfillTargets[lowKey] >= targets[key];
|
|
133
|
+
}) !== undefined);
|
|
134
|
+
}
|
|
135
|
+
exports.isNeedPolyfill = isNeedPolyfill;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as t from '@umijs/bundler-utils/compiled/babel/types';
|
|
2
|
+
import { IApi } from 'umi';
|
|
3
|
+
interface IOpts {
|
|
4
|
+
contentTest?: (content: string) => Boolean;
|
|
5
|
+
astTest?: (opts: {
|
|
6
|
+
node: t.Node;
|
|
7
|
+
content: string;
|
|
8
|
+
}) => Boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare class Model {
|
|
11
|
+
file: string;
|
|
12
|
+
namespace: string;
|
|
13
|
+
id: string;
|
|
14
|
+
exportName: string;
|
|
15
|
+
constructor(file: string, id: number);
|
|
16
|
+
}
|
|
17
|
+
export declare class ModelUtils {
|
|
18
|
+
api: IApi;
|
|
19
|
+
opts: IOpts;
|
|
20
|
+
count: number;
|
|
21
|
+
constructor(api: IApi | null, opts: IOpts);
|
|
22
|
+
getAllModels(opts: {
|
|
23
|
+
extraModels: string[];
|
|
24
|
+
}): Model[];
|
|
25
|
+
getModels(opts: {
|
|
26
|
+
base: string;
|
|
27
|
+
pattern?: string;
|
|
28
|
+
}): string[];
|
|
29
|
+
isModelValid(opts: {
|
|
30
|
+
content: string;
|
|
31
|
+
file: string;
|
|
32
|
+
}): boolean;
|
|
33
|
+
static getModelsContent(models: Model[]): string;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.ModelUtils = exports.Model = void 0;
|
|
26
|
+
const parser = __importStar(require("@umijs/bundler-utils/compiled/babel/parser"));
|
|
27
|
+
const traverse_1 = __importDefault(require("@umijs/bundler-utils/compiled/babel/traverse"));
|
|
28
|
+
const esbuild_1 = require("@umijs/bundler-utils/compiled/esbuild");
|
|
29
|
+
const utils_1 = require("@umijs/utils");
|
|
30
|
+
const fs_1 = require("fs");
|
|
31
|
+
const path_1 = require("path");
|
|
32
|
+
const astUtils_1 = require("./astUtils");
|
|
33
|
+
class Model {
|
|
34
|
+
constructor(file, id) {
|
|
35
|
+
let namespace;
|
|
36
|
+
let exportName;
|
|
37
|
+
const [_file, meta] = file.split('#');
|
|
38
|
+
if (meta) {
|
|
39
|
+
const metaObj = JSON.parse(meta);
|
|
40
|
+
namespace = metaObj.namespace;
|
|
41
|
+
exportName = metaObj.exportName;
|
|
42
|
+
}
|
|
43
|
+
this.file = _file;
|
|
44
|
+
this.id = `model_${id}`;
|
|
45
|
+
this.namespace = namespace || (0, path_1.basename)(file, (0, path_1.extname)(file));
|
|
46
|
+
this.exportName = exportName || 'default';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.Model = Model;
|
|
50
|
+
class ModelUtils {
|
|
51
|
+
constructor(api, opts) {
|
|
52
|
+
this.opts = {};
|
|
53
|
+
this.count = 1;
|
|
54
|
+
this.api = api;
|
|
55
|
+
this.opts = opts;
|
|
56
|
+
}
|
|
57
|
+
getAllModels(opts) {
|
|
58
|
+
// reset count
|
|
59
|
+
this.count = 1;
|
|
60
|
+
return [
|
|
61
|
+
...this.getModels({
|
|
62
|
+
base: (0, path_1.join)(this.api.paths.absSrcPath, 'models'),
|
|
63
|
+
pattern: '**/*.{ts,tsx,js,jsx}',
|
|
64
|
+
}),
|
|
65
|
+
...this.getModels({
|
|
66
|
+
base: (0, path_1.join)(this.api.paths.absPagesPath),
|
|
67
|
+
pattern: '**/models/**/*.{ts,tsx,js,jsx}',
|
|
68
|
+
}),
|
|
69
|
+
...this.getModels({
|
|
70
|
+
base: (0, path_1.join)(this.api.paths.absPagesPath),
|
|
71
|
+
pattern: '**/model.{ts,tsx,js,jsx}',
|
|
72
|
+
}),
|
|
73
|
+
...opts.extraModels,
|
|
74
|
+
].map((file) => {
|
|
75
|
+
return new Model(file, this.count++);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
getModels(opts) {
|
|
79
|
+
return utils_1.glob
|
|
80
|
+
.sync(opts.pattern || '**/*.{ts,js}', {
|
|
81
|
+
cwd: opts.base,
|
|
82
|
+
absolute: true,
|
|
83
|
+
})
|
|
84
|
+
.map(utils_1.winPath)
|
|
85
|
+
.filter((file) => {
|
|
86
|
+
if (/\.d.ts$/.test(file))
|
|
87
|
+
return false;
|
|
88
|
+
if (/\.(test|e2e|spec).([jt])sx?$/.test(file))
|
|
89
|
+
return false;
|
|
90
|
+
const content = (0, fs_1.readFileSync)(file, 'utf-8');
|
|
91
|
+
return this.isModelValid({ content, file });
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
isModelValid(opts) {
|
|
95
|
+
const { file, content } = opts;
|
|
96
|
+
if (this.opts.contentTest && this.opts.contentTest(content)) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
// transform with esbuild first
|
|
100
|
+
// to reduce unexpected ast problem
|
|
101
|
+
const loader = (0, path_1.extname)(file).slice(1);
|
|
102
|
+
const result = (0, esbuild_1.transformSync)(content, {
|
|
103
|
+
loader,
|
|
104
|
+
sourcemap: false,
|
|
105
|
+
minify: false,
|
|
106
|
+
});
|
|
107
|
+
// transform with babel
|
|
108
|
+
let ret = false;
|
|
109
|
+
const ast = parser.parse(result.code, {
|
|
110
|
+
sourceType: 'module',
|
|
111
|
+
sourceFilename: file,
|
|
112
|
+
plugins: [],
|
|
113
|
+
});
|
|
114
|
+
(0, traverse_1.default)(ast, {
|
|
115
|
+
ExportDefaultDeclaration: (path) => {
|
|
116
|
+
let node = path.node.declaration;
|
|
117
|
+
node = (0, astUtils_1.getIdentifierDeclaration)(node, path);
|
|
118
|
+
if (this.opts.astTest && this.opts.astTest({ node, content })) {
|
|
119
|
+
ret = true;
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
return ret;
|
|
124
|
+
}
|
|
125
|
+
static getModelsContent(models) {
|
|
126
|
+
const imports = [];
|
|
127
|
+
const modelProps = [];
|
|
128
|
+
models.forEach((model) => {
|
|
129
|
+
if (model.exportName !== 'default') {
|
|
130
|
+
imports.push(`import { ${model.exportName} as ${model.id} } from '${model.file}';`);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
imports.push(`import ${model.id} from '${model.file}';`);
|
|
134
|
+
}
|
|
135
|
+
modelProps.push(`${model.id}: { namespace: '${model.namespace}', model: ${model.id} },`);
|
|
136
|
+
});
|
|
137
|
+
return `
|
|
138
|
+
${imports.join('\n')}
|
|
139
|
+
|
|
140
|
+
export const models = {
|
|
141
|
+
${modelProps.join('\n')}
|
|
142
|
+
}`;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
exports.ModelUtils = ModelUtils;
|