@umijs/plugins 4.0.0-beta.9 → 4.0.0-rc.1

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.
Files changed (58) hide show
  1. package/README.md +4 -1
  2. package/dist/access.js +73 -1
  3. package/dist/{sass.d.ts → analytics.d.ts} +0 -0
  4. package/dist/analytics.js +67 -0
  5. package/dist/antd.js +89 -145
  6. package/dist/dva.d.ts +3 -0
  7. package/dist/dva.js +168 -4
  8. package/dist/initial-state.js +112 -1
  9. package/dist/layout.js +479 -1
  10. package/dist/locale.d.ts +1 -0
  11. package/dist/locale.js +199 -1
  12. package/dist/model.js +112 -1
  13. package/dist/moment2dayjs.d.ts +3 -0
  14. package/dist/moment2dayjs.js +96 -0
  15. package/dist/qiankun/constants.d.ts +5 -0
  16. package/dist/qiankun/constants.js +8 -0
  17. package/dist/qiankun/master.d.ts +6 -0
  18. package/dist/qiankun/master.js +114 -0
  19. package/dist/qiankun/slave.d.ts +3 -0
  20. package/dist/qiankun/slave.js +141 -0
  21. package/dist/qiankun.js +15 -1
  22. package/dist/request.js +300 -1
  23. package/dist/tailwindcss.d.ts +3 -0
  24. package/dist/tailwindcss.js +38 -0
  25. package/dist/unocss.d.ts +3 -0
  26. package/dist/unocss.js +57 -0
  27. package/dist/utils/astUtils.d.ts +3 -0
  28. package/dist/utils/astUtils.js +34 -0
  29. package/dist/utils/localeUtils.d.ts +33 -0
  30. package/dist/utils/localeUtils.js +135 -0
  31. package/dist/utils/modelUtils.d.ts +35 -0
  32. package/dist/utils/modelUtils.js +145 -0
  33. package/dist/utils/resolveProjectDep.d.ts +5 -0
  34. package/dist/utils/resolveProjectDep.js +15 -0
  35. package/dist/utils/withTmpPath.d.ts +6 -0
  36. package/dist/utils/withTmpPath.js +11 -0
  37. package/libs/dva.ts +10 -0
  38. package/libs/locale/SelectLang.tpl +478 -0
  39. package/libs/locale/locale.tpl +82 -0
  40. package/libs/locale/localeExports.tpl +271 -0
  41. package/libs/locale/runtime.tpl +33 -0
  42. package/libs/model.tsx +140 -0
  43. package/libs/qiankun/master/AntdErrorBoundary.tsx +34 -0
  44. package/libs/qiankun/master/AntdLoader.tsx +15 -0
  45. package/libs/qiankun/master/ErrorBoundary.tsx +7 -0
  46. package/libs/qiankun/master/MicroApp.tsx +262 -0
  47. package/libs/qiankun/master/MicroAppWithMemoHistory.tsx +43 -0
  48. package/libs/qiankun/master/common.ts +133 -0
  49. package/libs/qiankun/master/constants.ts +7 -0
  50. package/libs/qiankun/master/getMicroAppRouteComponent.tsx.tpl +45 -0
  51. package/libs/qiankun/master/masterRuntimePlugin.tsx +130 -0
  52. package/libs/qiankun/master/types.ts +44 -0
  53. package/libs/qiankun/slave/connectMaster.tsx +15 -0
  54. package/libs/qiankun/slave/lifecycles.ts +149 -0
  55. package/libs/qiankun/slave/qiankunModel.ts +19 -0
  56. package/libs/qiankun/slave/slaveRuntimePlugin.ts +21 -0
  57. package/package.json +21 -5
  58. package/dist/sass.js +0 -5
@@ -0,0 +1,271 @@
1
+ import {
2
+ createIntl,
3
+ IntlShape,
4
+ MessageDescriptor,
5
+ } from '{{{ reactIntlPkgPath }}}';
6
+ import { ApplyPluginsType } from 'umi';
7
+ import { getPluginManager } from '../core/plugin';
8
+ import EventEmitter from '{{{EventEmitterPkg}}}';
9
+ // @ts-ignore
10
+ import warning from '{{{ warningPkgPath }}}';
11
+
12
+ export {
13
+ createIntl,
14
+ };
15
+ export {
16
+ FormattedDate,
17
+ FormattedDateParts,
18
+ FormattedDisplayName,
19
+ FormattedHTMLMessage,
20
+ FormattedList,
21
+ FormattedMessage,
22
+ FormattedNumber,
23
+ FormattedNumberParts,
24
+ FormattedPlural,
25
+ FormattedRelativeTime,
26
+ FormattedTime,
27
+ FormattedTimeParts,
28
+ IntlContext,
29
+ IntlProvider,
30
+ RawIntlProvider,
31
+ createIntlCache,
32
+ defineMessages,
33
+ injectIntl,
34
+ useIntl,
35
+ } from '{{{ reactIntlPkgPath }}}';
36
+
37
+ let g_intl: IntlShape;
38
+
39
+ const useLocalStorage = {{{UseLocalStorage}}};
40
+
41
+ // @ts-ignore
42
+ export const event = new EventEmitter();
43
+
44
+ export const LANG_CHANGE_EVENT = Symbol('LANG_CHANGE');
45
+
46
+ {{#LocaleList}}
47
+ {{#antdLocale}}
48
+ import {{lang}}{{country}}{{index}} from '{{{locale}}}';
49
+ {{/antdLocale}}
50
+ {{#paths}}
51
+ import lang_{{lang}}{{country}}{{index}} from "{{{path}}}";
52
+ {{/paths}}
53
+ {{/LocaleList}}
54
+
55
+ export const localeInfo: {[key: string]: any} = {
56
+ {{#LocaleList}}
57
+ '{{name}}': {
58
+ messages: {
59
+ {{#paths}}...lang_{{lang}}{{country}}{{index}},{{/paths}}
60
+ },
61
+ locale: '{{locale}}',
62
+ {{#Antd}}antd: {
63
+ {{#antdLocale}}
64
+ ...{{lang}}{{country}}{{index}},
65
+ {{/antdLocale}}
66
+ },{{/Antd}}
67
+ momentLocale: '{{momentLocale}}',
68
+ },
69
+ {{/LocaleList}}
70
+ };
71
+
72
+ /**
73
+ * 增加一个新的国际化语言
74
+ * @param name 语言的 key
75
+ * @param messages 对应的枚举对象
76
+ * @param extraLocales momentLocale, antd 国际化
77
+ */
78
+ export const addLocale = (
79
+ name: string,
80
+ messages: Object,
81
+ extraLocales: {
82
+ momentLocale:string;
83
+ antd:string
84
+ },
85
+ ) => {
86
+ if (!name) {
87
+ return;
88
+ }
89
+ // 可以合并
90
+ const mergeMessages = localeInfo[name]?.messages
91
+ ? Object.assign({}, localeInfo[name].messages, messages)
92
+ : messages;
93
+
94
+
95
+ const { momentLocale, antd } = extraLocales || {};
96
+ const locale = name.split('{{BaseSeparator}}')?.join('-')
97
+ localeInfo[name] = {
98
+ messages: mergeMessages,
99
+ locale,
100
+ momentLocale: momentLocale,
101
+ {{#Antd}}antd,{{/Antd}}
102
+ };
103
+ // 如果这是的 name 和当前的locale 相同需要重新设置一下,不然更新不了
104
+ if (locale === getLocale()) {
105
+ event.emit(LANG_CHANGE_EVENT, locale);
106
+ }
107
+ };
108
+
109
+ /**
110
+ * 获取当前的 intl 对象,可以在 node 中使用
111
+ * @param locale 需要切换的语言类型
112
+ * @param changeIntl 是否不使用 g_intl
113
+ * @returns IntlShape
114
+ */
115
+ export const getIntl = (locale?: string, changeIntl?: boolean) => {
116
+ // 如果全局的 g_intl 存在,且不是 setIntl 调用
117
+ if (g_intl && !changeIntl && !locale) {
118
+ return g_intl;
119
+ }
120
+ // 如果存在于 localeInfo 中
121
+ if (locale&&localeInfo[locale]) {
122
+ return createIntl(localeInfo[locale]);
123
+ }
124
+ {{#ExistLocaleDir}}
125
+ // 不存在需要一个报错提醒
126
+ warning(
127
+ !locale||!!localeInfo[locale],
128
+ `The current popular language does not exist, please check the {{{LocaleDir}}} folder!`,
129
+ );
130
+ {{/ExistLocaleDir}}
131
+ // 使用 zh-CN
132
+ if (localeInfo[{{{ DefaultLocale }}}]) return createIntl(localeInfo[{{{ DefaultLocale }}}]);
133
+
134
+ // 如果还没有,返回一个空的
135
+ return createIntl({
136
+ locale: {{{ DefaultLocale }}},
137
+ messages: {},
138
+ });
139
+ };
140
+
141
+ /**
142
+ * 切换全局的 intl 的设置
143
+ * @param locale 语言的key
144
+ */
145
+ export const setIntl = (locale: string) => {
146
+ g_intl = getIntl(locale, true);
147
+ };
148
+
149
+ /**
150
+ * 获取当前选择的语言
151
+ * @returns string
152
+ */
153
+ export const getLocale = () => {
154
+ const runtimeLocale = getPluginManager().applyPlugins({
155
+ key: 'locale',
156
+ type: ApplyPluginsType.modify,
157
+ initialValue: {},
158
+ });
159
+ // runtime getLocale for user define
160
+ if (typeof runtimeLocale?.getLocale === 'function') {
161
+ return runtimeLocale.getLocale();
162
+ }
163
+ // please clear localStorage if you change the baseSeparator config
164
+ // because changing will break the app
165
+ const lang =
166
+ typeof localStorage !== 'undefined' && useLocalStorage
167
+ ? window.localStorage.getItem('umi_locale')
168
+ : '';
169
+ // support baseNavigator, default true
170
+ let browserLang;
171
+ {{#BaseNavigator}}
172
+ const isNavigatorLanguageValid =
173
+ typeof navigator !== 'undefined' && typeof navigator.language === 'string';
174
+ browserLang = isNavigatorLanguageValid
175
+ ? navigator.language.split('-').join('{{BaseSeparator}}')
176
+ : '';
177
+ {{/BaseNavigator}}
178
+ return lang || browserLang || {{{DefaultLocale}}};
179
+ };
180
+
181
+
182
+ /**
183
+ * 获取当前选择的方向
184
+ * @returns string
185
+ */
186
+ export const getDirection = () => {
187
+ const lang = getLocale();
188
+ // array with all prefixs for rtl langueges ex: ar-EG , he-IL
189
+ const rtlLangs = ['he', 'ar', 'fa', 'ku']
190
+ const direction = rtlLangs.filter(lng => lang.startsWith(lng)).length ? 'rtl' : 'ltr';
191
+ return direction;
192
+ };
193
+
194
+ /**
195
+ * 切换语言
196
+ * @param lang 语言的 key
197
+ * @param realReload 是否刷新页面,默认刷新
198
+ * @returns string
199
+ */
200
+ export const setLocale = (lang: string, realReload: boolean = true) => {
201
+ //const { pluginManager } = useAppContext();
202
+ //const runtimeLocale = pluginManagerapplyPlugins({
203
+ // key: 'locale',
204
+ // type: ApplyPluginsType.modify,
205
+ // initialValue: {},
206
+ //});
207
+
208
+ const updater = () => {
209
+ if (getLocale() !== lang) {
210
+ if (typeof window.localStorage !== 'undefined' && useLocalStorage) {
211
+ window.localStorage.setItem('umi_locale', lang || '');
212
+ }
213
+ setIntl(lang);
214
+ if (realReload) {
215
+ window.location.reload();
216
+ } else {
217
+ event.emit(LANG_CHANGE_EVENT, lang);
218
+ // chrome 不支持这个事件。所以人肉触发一下
219
+ if (window.dispatchEvent) {
220
+ const event = new Event('languagechange');
221
+ window.dispatchEvent(event);
222
+ }
223
+ }
224
+ }
225
+ }
226
+
227
+ //if (typeof runtimeLocale?.setLocale === 'function') {
228
+ // runtimeLocale.setLocale({
229
+ // lang,
230
+ // realReload,
231
+ // updater: updater,
232
+ // });
233
+ // return;
234
+ //}
235
+
236
+ updater();
237
+ };
238
+
239
+ let firstWaring = true;
240
+
241
+ /**
242
+ * intl.formatMessage 的语法糖
243
+ * @deprecated 使用此 api 会造成切换语言的时候无法自动刷新,请使用 useIntl 或 injectIntl
244
+ * @param descriptor { id : string, defaultMessage : string }
245
+ * @param values { [key:string] : string }
246
+ * @returns string
247
+ */
248
+ export const formatMessage: IntlShape['formatMessage'] = (
249
+ descriptor: MessageDescriptor,
250
+ values: any,
251
+ ) => {
252
+ if (firstWaring) {
253
+ warning(
254
+ false,
255
+ `Using this API will cause automatic refresh when switching languages, please use useIntl or injectIntl.
256
+
257
+ 使用此 api 会造成切换语言的时候无法自动刷新,请使用 useIntl 或 injectIntl。
258
+
259
+ http://j.mp/37Fkd5Q
260
+ `,
261
+ );
262
+ firstWaring = false;
263
+ }
264
+ return g_intl.formatMessage(descriptor, values);
265
+ };
266
+
267
+ /**
268
+ * 获取语言列表
269
+ * @returns string[]
270
+ */
271
+ export const getAllLocales = () => Object.keys(localeInfo);
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ // @ts-ignore
3
+ import { _LocaleContainer } from './locale';
4
+ {{#Title}}
5
+ import { getIntl, getLocale } from './localeExports';
6
+ {{/Title}}
7
+ export function i18nProvider(container: Element) {
8
+ return React.createElement(_LocaleContainer, null, container);
9
+ }
10
+
11
+ {{#Title}}
12
+ export function patchRoutes({ routes }) {
13
+ // loop all route for patch title field
14
+ const intl = getIntl(getLocale());
15
+ const traverseRoute = (routes) => {
16
+ Object.keys(routes).forEach((key) => {
17
+ const route = routes[key];
18
+ if (route.title) {
19
+ const newTitle = intl.messages[route.title] ? intl.formatMessage({ id: route.title }, {}) : route.title;
20
+ route.name = intl.messages[route.title] ? intl.formatMessage({ id: route.title }, {}) : route.name;
21
+ route.title = newTitle;
22
+ }
23
+ if (route.routes) {
24
+ traverseRoute(route.routes);
25
+ }
26
+ if (route.routes) {
27
+ traverseRoute(route.routes);
28
+ }
29
+ })
30
+ }
31
+ traverseRoute(routes);
32
+ }
33
+ {{/Title}}
package/libs/model.tsx ADDED
@@ -0,0 +1,140 @@
1
+ // @ts-ignore
2
+ import isEqual from 'fast-deep-equal';
3
+ import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
4
+
5
+ // @ts-ignore
6
+ const Context = React.createContext<{ dispatcher: Dispatcher }>(null);
7
+
8
+ class Dispatcher {
9
+ callbacks: Record<string, Set<Function>> = {};
10
+ data: Record<string, unknown> = {};
11
+ update = (namespace: string) => {
12
+ if (this.callbacks[namespace]) {
13
+ this.callbacks[namespace].forEach((cb) => {
14
+ try {
15
+ const data = this.data[namespace];
16
+ cb(data);
17
+ } catch (e) {
18
+ cb(undefined);
19
+ }
20
+ });
21
+ }
22
+ };
23
+ }
24
+
25
+ interface ExecutorProps {
26
+ hook: () => any;
27
+ onUpdate: (val: any) => void;
28
+ namespace: string;
29
+ }
30
+
31
+ function Executor(props: ExecutorProps) {
32
+ const { hook, onUpdate, namespace } = props;
33
+
34
+ const updateRef = useRef(onUpdate);
35
+ const initialLoad = useRef(false);
36
+
37
+ let data: any;
38
+ try {
39
+ data = hook();
40
+ } catch (e) {
41
+ console.error(
42
+ `plugin-model: Invoking '${namespace || 'unknown'}' model failed:`,
43
+ e,
44
+ );
45
+ }
46
+
47
+ // 首次执行时立刻返回初始值
48
+ useMemo(() => {
49
+ updateRef.current(data);
50
+ }, []);
51
+
52
+ // React 16.13 后 update 函数用 useEffect 包裹
53
+ useEffect(() => {
54
+ if (initialLoad.current) {
55
+ updateRef.current(data);
56
+ } else {
57
+ initialLoad.current = true;
58
+ }
59
+ });
60
+
61
+ return null;
62
+ }
63
+
64
+ const dispatcher = new Dispatcher();
65
+
66
+ export function Provider(props: {
67
+ models: Record<string, any>;
68
+ children: React.ReactNode;
69
+ }) {
70
+ return (
71
+ <Context.Provider value={{ dispatcher }}>
72
+ {Object.keys(props.models).map((namespace) => {
73
+ return (
74
+ <Executor
75
+ key={namespace}
76
+ hook={props.models[namespace]}
77
+ namespace={namespace}
78
+ onUpdate={(val) => {
79
+ dispatcher.data[namespace] = val;
80
+ dispatcher.update(namespace);
81
+ }}
82
+ />
83
+ );
84
+ })}
85
+ {props.children}
86
+ </Context.Provider>
87
+ );
88
+ }
89
+
90
+ export function useModel(namespace: string, selector?: any) {
91
+ const { dispatcher } = useContext<{ dispatcher: Dispatcher }>(Context);
92
+ const selectorRef = useRef(selector);
93
+ selectorRef.current = selector;
94
+ const [state, setState] = useState(() =>
95
+ selectorRef.current
96
+ ? selectorRef.current(dispatcher.data[namespace])
97
+ : dispatcher.data[namespace],
98
+ );
99
+ const stateRef = useRef<any>(state);
100
+ stateRef.current = state;
101
+
102
+ const isMount = useRef(false);
103
+ useEffect(() => {
104
+ isMount.current = true;
105
+ return () => {
106
+ isMount.current = false;
107
+ };
108
+ }, []);
109
+
110
+ useEffect(() => {
111
+ const handler = (data: any) => {
112
+ if (!isMount.current) {
113
+ // 如果 handler 执行过程中,组件被卸载了,则强制更新全局 data
114
+ // TODO: 需要加个 example 测试
115
+ setTimeout(() => {
116
+ dispatcher.data[namespace] = data;
117
+ dispatcher.update(namespace);
118
+ });
119
+ } else {
120
+ const currentState = selectorRef.current
121
+ ? selectorRef.current(data)
122
+ : data;
123
+ const previousState = stateRef.current;
124
+ if (!isEqual(currentState, previousState)) {
125
+ setState(currentState);
126
+ }
127
+ }
128
+ };
129
+
130
+ dispatcher.callbacks[namespace] ||= new Set();
131
+ dispatcher.callbacks[namespace].add(handler);
132
+ dispatcher.update(namespace);
133
+
134
+ return () => {
135
+ dispatcher.callbacks[namespace].delete(handler);
136
+ };
137
+ }, [namespace]);
138
+
139
+ return state;
140
+ }
@@ -0,0 +1,34 @@
1
+ // @ts-nocheck
2
+ /* eslint-disable */
3
+ import { Button, Result } from 'antd';
4
+ import React from 'react';
5
+ import { getLocale } from 'umi';
6
+
7
+ const defaultLocale = 'en-US';
8
+
9
+ export const ErrorBoundary = ({ error }: { error: any }) => {
10
+ console.error(error);
11
+
12
+ const currentLocale = getLocale ? getLocale() : defaultLocale;
13
+
14
+ return (
15
+ <Result
16
+ status="500"
17
+ title={
18
+ currentLocale === defaultLocale
19
+ ? 'Whoops, something went wrong'
20
+ : '出错了'
21
+ }
22
+ subTitle={
23
+ currentLocale === defaultLocale
24
+ ? 'This page failed to load, please try again later'
25
+ : '页面加载失败,请稍后重试'
26
+ }
27
+ extra={
28
+ <Button type="primary" onClick={() => window.location.reload()}>
29
+ {currentLocale === defaultLocale ? 'Reload' : '再试一次'}
30
+ </Button>
31
+ }
32
+ />
33
+ );
34
+ };
@@ -0,0 +1,15 @@
1
+ // @ts-nocheck
2
+ /* eslint-disable */
3
+ import { Spin } from 'antd';
4
+ import React from 'react';
5
+
6
+ export default function AntdLoader(props: { loading: boolean }) {
7
+ const { loading } = props;
8
+ const style = {
9
+ position: 'absolute',
10
+ top: '50%',
11
+ left: '50%',
12
+ transform: 'translate(-50%, -50%)',
13
+ };
14
+ return <Spin spinning={loading} size="large" style={style} />;
15
+ }
@@ -0,0 +1,7 @@
1
+ // @ts-nocheck
2
+ /* eslint-disable */
3
+ import React from 'react';
4
+
5
+ export const ErrorBoundary = ({ error }: { error: any }) => (
6
+ <div>{error?.message}</div>
7
+ );