@umijs/plugins 4.0.0-canary.20220525.2 → 4.0.0-canary.20220608.2

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/dist/access.js CHANGED
@@ -54,7 +54,7 @@ export function accessProvider(container) {
54
54
  api.writeTmpFile({
55
55
  path: 'index.tsx',
56
56
  content: `
57
- import React from 'react';
57
+ import React, { PropsWithChildren } from 'react';
58
58
  import { AccessContext } from './context';
59
59
  import type { IRoute } from 'umi';
60
60
 
@@ -66,7 +66,7 @@ export interface AccessProps {
66
66
  accessible: boolean;
67
67
  fallback?: React.ReactNode;
68
68
  }
69
- export const Access: React.FC<AccessProps> = (props) => {
69
+ export const Access: React.FC<PropsWithChildren<AccessProps>> = (props) => {
70
70
  if (process.env.NODE_ENV === 'development' && typeof props.accessible !== 'boolean') {
71
71
  throw new Error('[access] the \`accessible\` property on <Access /> should be a boolean');
72
72
  }
@@ -85,7 +85,7 @@ export const useAccessMarkedRoutes = (routes: IRoute[]) => {
85
85
 
86
86
  // check access code
87
87
  if (typeof accessCode === 'string') {
88
- const detector = access[route.access];
88
+ const detector = access[accessCode];
89
89
 
90
90
  if (typeof detector === 'function') {
91
91
  route.unaccessible = !detector(route);
@@ -97,8 +97,8 @@ export const useAccessMarkedRoutes = (routes: IRoute[]) => {
97
97
  }
98
98
 
99
99
  // check children access code
100
- if (route.routes) {
101
- const isNoAccessibleChild = !route.routes.reduce((hasAccessibleChild, child) => {
100
+ if (route.children?.length) {
101
+ const isNoAccessibleChild = !route.children.reduce((hasAccessibleChild, child) => {
102
102
  process(child, accessCode);
103
103
 
104
104
  return hasAccessibleChild || !child.unaccessible;
package/dist/analytics.js CHANGED
@@ -20,7 +20,7 @@ exports.default = (api) => {
20
20
  return `
21
21
  (function() {
22
22
  var hm = document.createElement('script');
23
- hm.src = 'https://hm.baidu.com/hm.js?${code}';
23
+ hm.src = '//hm.baidu.com/hm.js?${code}';
24
24
  var s = document.getElementsByTagName('script')[0];
25
25
  s.parentNode.insertBefore(hm, s);
26
26
  })();
package/dist/dva.js CHANGED
@@ -112,7 +112,10 @@ export function RootContainer(props: any) {
112
112
  ${((_d = (_c = api.config.dva) === null || _c === void 0 ? void 0 : _c.immer) === null || _d === void 0 ? void 0 : _d.enableES5) ? `enableES5();` : ''}
113
113
  ${((_f = (_e = api.config.dva) === null || _e === void 0 ? void 0 : _e.immer) === null || _f === void 0 ? void 0 : _f.enableAllPlugins) ? `enableAllPlugins();` : ''}
114
114
  for (const id of Object.keys(models)) {
115
- app.current.model(models[id].model);
115
+ app.current.model({
116
+ namespace: models[id].namespace,
117
+ ...models[id].model,
118
+ });
116
119
  }
117
120
  app.current.start();
118
121
  }
@@ -14,7 +14,12 @@ exports.default = (api) => {
14
14
  });
15
15
  api.register({
16
16
  key: 'addExtraModels',
17
- fn: () => [(0, withTmpPath_1.withTmpPath)({ api, path: '@@initialState.ts' })],
17
+ fn: () => [
18
+ (0, withTmpPath_1.withTmpPath)({
19
+ api,
20
+ path: '@@initialState.ts#{"namespace":"@@initialState"}',
21
+ }),
22
+ ],
18
23
  });
19
24
  api.addRuntimePluginKey(() => ['getInitialState']);
20
25
  api.addRuntimePlugin(() => {
package/dist/request.js CHANGED
@@ -250,7 +250,7 @@ const request: IRequest = (url: string, opts: any = { method: 'GET' }) => {
250
250
  });
251
251
  try {
252
252
  const handler =
253
- config.errorConfig?.errorHandler;
253
+ config?.errorConfig?.errorHandler;
254
254
  if(handler)
255
255
  handler(error, opts, config);
256
256
  } catch (e) {
@@ -7,13 +7,14 @@ interface IOpts {
7
7
  content: string;
8
8
  }) => Boolean;
9
9
  }
10
+ export declare function getNamespace(absFilePath: string, absSrcPath: string): string;
10
11
  export declare class Model {
11
12
  file: string;
12
13
  namespace: string;
13
14
  id: string;
14
15
  exportName: string;
15
16
  deps: string[];
16
- constructor(file: string, sort: {} | undefined, id: number);
17
+ constructor(file: string, absSrcPath: string, sort: {} | undefined, id: number);
17
18
  findDeps(sort: object): string[];
18
19
  }
19
20
  export declare class ModelUtils {
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.ModelUtils = exports.Model = void 0;
29
+ exports.ModelUtils = exports.Model = exports.getNamespace = void 0;
30
30
  const parser = __importStar(require("@umijs/bundler-utils/compiled/babel/parser"));
31
31
  const traverse_1 = __importDefault(require("@umijs/bundler-utils/compiled/babel/traverse"));
32
32
  const t = __importStar(require("@umijs/bundler-utils/compiled/babel/types"));
@@ -35,8 +35,24 @@ const fs_1 = require("fs");
35
35
  const path_1 = require("path");
36
36
  const plugin_utils_1 = require("umi/plugin-utils");
37
37
  const astUtils_1 = require("./astUtils");
38
+ function getNamespace(absFilePath, absSrcPath) {
39
+ const relPath = (0, plugin_utils_1.winPath)((0, path_1.relative)((0, plugin_utils_1.winPath)(absSrcPath), (0, plugin_utils_1.winPath)(absFilePath)));
40
+ const parts = relPath.split('/');
41
+ const dirs = parts.slice(0, -1);
42
+ const file = parts[parts.length - 1];
43
+ // src/pages/foo/models/bar > foo/bar
44
+ const validDirs = dirs.filter((dir) => !['src', 'pages', 'models'].includes(dir));
45
+ let normalizedFile = file;
46
+ normalizedFile = (0, path_1.basename)(file, (0, path_1.extname)(file));
47
+ // foo.model > foo
48
+ if (normalizedFile.endsWith('.model')) {
49
+ normalizedFile = normalizedFile.split('.').slice(0, -1).join('.');
50
+ }
51
+ return [...validDirs, normalizedFile].join('.');
52
+ }
53
+ exports.getNamespace = getNamespace;
38
54
  class Model {
39
- constructor(file, sort, id) {
55
+ constructor(file, absSrcPath, sort, id) {
40
56
  let namespace;
41
57
  let exportName;
42
58
  const [_file, meta] = file.split('#');
@@ -47,7 +63,7 @@ class Model {
47
63
  }
48
64
  this.file = _file;
49
65
  this.id = `model_${id}`;
50
- this.namespace = namespace || (0, path_1.basename)(file, (0, path_1.extname)(file));
66
+ this.namespace = namespace || getNamespace(_file, absSrcPath);
51
67
  this.exportName = exportName || 'default';
52
68
  this.deps = sort ? this.findDeps(sort) : [];
53
69
  }
@@ -107,7 +123,7 @@ class ModelUtils {
107
123
  }),
108
124
  ...opts.extraModels,
109
125
  ].map((file) => {
110
- return new Model(file, opts.sort, this.count++);
126
+ return new Model(file, this.api.paths.absSrcPath, opts.sort, this.count++);
111
127
  });
112
128
  // check duplicate
113
129
  const namespaces = models.map((model) => model.namespace);
@@ -212,11 +228,15 @@ class ModelUtils {
212
228
  const imports = [];
213
229
  const modelProps = [];
214
230
  models.forEach((model) => {
231
+ const fileWithoutExt = (0, plugin_utils_1.winPath)((0, path_1.format)({
232
+ dir: (0, path_1.dirname)(model.file),
233
+ base: (0, path_1.basename)(model.file, (0, path_1.extname)(model.file)),
234
+ }));
215
235
  if (model.exportName !== 'default') {
216
- imports.push(`import { ${model.exportName} as ${model.id} } from '${model.file}';`);
236
+ imports.push(`import { ${model.exportName} as ${model.id} } from '${fileWithoutExt}';`);
217
237
  }
218
238
  else {
219
- imports.push(`import ${model.id} from '${model.file}';`);
239
+ imports.push(`import ${model.id} from '${fileWithoutExt}';`);
220
240
  }
221
241
  modelProps.push(`${model.id}: { namespace: '${model.namespace}', model: ${model.id} },`);
222
242
  });
@@ -225,7 +245,7 @@ ${imports.join('\n')}
225
245
 
226
246
  export const models = {
227
247
  ${modelProps.join('\n')}
228
- }`;
248
+ } as const`;
229
249
  }
230
250
  }
231
251
  exports.ModelUtils = ModelUtils;
package/libs/model.tsx CHANGED
@@ -1,14 +1,25 @@
1
1
  // @ts-ignore
2
+ import type { models as rawModels } from '@@/plugin-model/model';
2
3
  import isEqual from 'fast-deep-equal';
3
4
  import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
4
5
 
6
+ type Models = typeof rawModels;
7
+
8
+ type GetNamespaces<M> = {
9
+ [K in keyof M]: M[K] extends { namespace: string }
10
+ ? M[K]['namespace']
11
+ : never;
12
+ }[keyof M];
13
+
14
+ type Namespaces = GetNamespaces<Models>;
15
+
5
16
  // @ts-ignore
6
17
  const Context = React.createContext<{ dispatcher: Dispatcher }>(null);
7
18
 
8
19
  class Dispatcher {
9
- callbacks: Record<string, Set<Function>> = {};
10
- data: Record<string, unknown> = {};
11
- update = (namespace: string) => {
20
+ callbacks: Record<Namespaces, Set<Function>> = {};
21
+ data: Record<Namespaces, unknown> = {};
22
+ update = (namespace: Namespaces) => {
12
23
  if (this.callbacks[namespace]) {
13
24
  this.callbacks[namespace].forEach((cb) => {
14
25
  try {
@@ -87,7 +98,34 @@ export function Provider(props: {
87
98
  );
88
99
  }
89
100
 
90
- export function useModel(namespace: string, selector?: any) {
101
+ type GetModelByNamespace<M, N> = {
102
+ [K in keyof M]: M[K] extends { namespace: string; model: unknown }
103
+ ? M[K]['namespace'] extends N
104
+ ? M[K]['model'] extends (...args: any) => any
105
+ ? ReturnType<M[K]['model']>
106
+ : never
107
+ : never
108
+ : never;
109
+ }[keyof M];
110
+
111
+ type Model<N> = GetModelByNamespace<Models, N>;
112
+ type Selector<N, S> = (model: Model<N>) => S;
113
+
114
+ type SelectedModel<N, T> = T extends (...args: any) => any
115
+ ? ReturnType<NonNullable<T>>
116
+ : Model<N>;
117
+
118
+ export function useModel<N extends Namespaces>(namespace: N): Model<N>;
119
+
120
+ export function useModel<N extends Namespaces, S>(
121
+ namespace: N,
122
+ selector: Selector<N, S>,
123
+ ): SelectedModel<N, typeof selector>;
124
+
125
+ export function useModel<N extends Namespaces, S>(
126
+ namespace: N,
127
+ selector?: Selector<N, S>,
128
+ ): SelectedModel<N, typeof selector> {
91
129
  const { dispatcher } = useContext<{ dispatcher: Dispatcher }>(Context);
92
130
  const selectorRef = useRef(selector);
93
131
  selectorRef.current = selector;
@@ -127,7 +165,7 @@ export function useModel(namespace: string, selector?: any) {
127
165
  }
128
166
  };
129
167
 
130
- dispatcher.callbacks[namespace] ||= new Set();
168
+ dispatcher.callbacks[namespace] ||= new Set() as any; // rawModels 是 umi 动态生成的文件,导致前面 callback[namespace] 的类型无法推导出来,所以用 as any 来忽略掉
131
169
  dispatcher.callbacks[namespace].add(handler);
132
170
  dispatcher.update(namespace);
133
171
 
@@ -74,11 +74,11 @@ export const MicroApp = forwardRef(
74
74
  apps = [],
75
75
  lifeCycles: globalLifeCycles,
76
76
  prefetch = true,
77
+ appNameKeyAlias = 'name',
77
78
  ...globalSettings
78
79
  } = getMasterOptions() as MasterOptions;
79
80
 
80
81
  const {
81
- name,
82
82
  settings: settingsFromProps = {},
83
83
  loader,
84
84
  errorBoundary,
@@ -88,6 +88,10 @@ export const MicroApp = forwardRef(
88
88
  ...propsFromParams
89
89
  } = componentProps;
90
90
 
91
+ // 优先使用 alias 名匹配,fallback 到 name 匹配
92
+ const name = componentProps[appNameKeyAlias] || componentProps.name;
93
+ const isCurrentApp = (app: any) => app[appNameKeyAlias] === name || app.name === name;
94
+
91
95
  const [loading, setLoading] = useState(true);
92
96
  const [error, setError] = useState<any>(null);
93
97
  // 未配置自定义 errorBoundary 且开启了 autoCaptureError 场景下,使用插件默认的 errorBoundary,否则使用自定义 errorBoundary
@@ -117,7 +121,7 @@ export const MicroApp = forwardRef(
117
121
 
118
122
  useImperativeHandle(componentRef, () => microAppRef.current);
119
123
 
120
- const appConfig = apps.find((app: any) => app.name === name);
124
+ const appConfig = apps.find((app: any) => isCurrentApp(app));
121
125
  useEffect(() => {
122
126
  if (!appConfig) {
123
127
  setComponentError(
@@ -174,13 +178,11 @@ export const MicroApp = forwardRef(
174
178
  if (noneMounted) {
175
179
  if (Array.isArray(prefetch)) {
176
180
  const specialPrefetchApps = apps.filter(
177
- (app) => app.name !== name && prefetch.indexOf(app.name) !== -1,
181
+ (app) => !isCurrentApp(app) && (prefetch.indexOf(app[appNameKeyAlias]) !== -1 || prefetch.indexOf(app.name) !== -1)
178
182
  );
179
183
  prefetchApps(specialPrefetchApps, configuration);
180
184
  } else {
181
- const otherNotMountedApps = apps.filter(
182
- (app) => app.name !== name,
183
- );
185
+ const otherNotMountedApps = apps.filter((app) => !isCurrentApp(app));
184
186
  prefetchApps(otherNotMountedApps, configuration);
185
187
  }
186
188
  noneMounted = false;
@@ -31,6 +31,8 @@ export type MasterOptions = {
31
31
  routeBindingAlias?: string;
32
32
  // 导出的组件别名,默认 MicroApp
33
33
  exportComponentAlias?: string;
34
+ // MicroApp 寻址时使用的应用名唯一键,默认是 name
35
+ appNameKeyAlias?: string;
34
36
  } & FrameworkConfiguration;
35
37
 
36
38
  export type SlaveOptions = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umijs/plugins",
3
- "version": "4.0.0-canary.20220525.2",
3
+ "version": "4.0.0-canary.20220608.2",
4
4
  "description": "@umijs/plugins",
5
5
  "homepage": "https://github.com/umijs/umi-next/tree/master/packages/plugins#readme",
6
6
  "bugs": "https://github.com/umijs/umi-next/issues",
@@ -24,11 +24,11 @@
24
24
  "dependencies": {
25
25
  "@ahooksjs/use-request": "^2.0.0",
26
26
  "@ant-design/icons": "^4.7.0",
27
- "@ant-design/pro-layout": "^6.38.0",
28
- "@umijs/bundler-utils": "4.0.0-canary.20220525.2",
27
+ "@ant-design/pro-layout": "^7.0.1-beta.17",
28
+ "@umijs/bundler-utils": "4.0.0-canary.20220608.2",
29
29
  "antd-dayjs-webpack-plugin": "^1.0.6",
30
30
  "axios": "^0.27.2",
31
- "babel-plugin-import": "^1.13.3",
31
+ "babel-plugin-import": "^1.13.5",
32
32
  "dayjs": "^1.11.2",
33
33
  "dva-core": "^2.0.4",
34
34
  "dva-immer": "^1.0.0",
@@ -39,12 +39,12 @@
39
39
  "moment": "^2.29.3",
40
40
  "qiankun": "^2.7.0",
41
41
  "react-intl": "3.12.1",
42
- "react-redux": "^8.0.1",
42
+ "react-redux": "^8.0.2",
43
43
  "redux": "^4.2.0",
44
44
  "warning": "^4.0.3"
45
45
  },
46
46
  "devDependencies": {
47
- "umi": "4.0.0-canary.20220525.2"
47
+ "umi": "4.0.0-canary.20220608.2"
48
48
  },
49
49
  "publishConfig": {
50
50
  "access": "public"