@nocobase/client-v2 2.1.0-beta.33 → 2.1.0-beta.35

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 (76) hide show
  1. package/es/APIClient.d.ts +16 -0
  2. package/es/Application.d.ts +2 -1
  3. package/es/BaseApplication.d.ts +6 -0
  4. package/es/PluginManager.d.ts +2 -0
  5. package/es/authRedirect.d.ts +9 -16
  6. package/es/components/form/EnvVariableInput.d.ts +8 -6
  7. package/es/components/form/VariableInput.d.ts +73 -0
  8. package/es/components/form/index.d.ts +1 -0
  9. package/es/components/form/table/RowOverlayPreview.d.ts +27 -0
  10. package/es/components/form/table/SelectionCell.d.ts +36 -0
  11. package/es/components/form/table/Table.d.ts +82 -0
  12. package/es/components/form/table/constants.d.ts +15 -0
  13. package/es/components/form/table/dnd/SortableRow.d.ts +40 -0
  14. package/es/components/form/table/dnd/index.d.ts +9 -0
  15. package/es/components/form/table/index.d.ts +9 -0
  16. package/es/components/form/table/styles.d.ts +41 -0
  17. package/es/components/form/table/utils.d.ts +44 -0
  18. package/es/components/index.d.ts +2 -0
  19. package/es/flow/components/TextAreaWithContextSelector.d.ts +15 -0
  20. package/es/flow/models/blocks/filter-form/FilterFormBlockModel.d.ts +9 -1
  21. package/es/flow/models/blocks/table/dragSort/dragSortComponents.d.ts +1 -6
  22. package/es/flow/models/blocks/table/dragSort/dragSortHooks.d.ts +5 -1
  23. package/es/flow-compat/passwordUtils.d.ts +1 -1
  24. package/es/index.d.ts +1 -0
  25. package/es/index.mjs +166 -99
  26. package/es/json-logic/globalOperators.d.ts +11 -0
  27. package/es/theme/globalStyles.d.ts +9 -0
  28. package/es/theme/index.d.ts +1 -0
  29. package/es/utils/globalDeps.d.ts +7 -0
  30. package/lib/index.js +173 -106
  31. package/package.json +9 -6
  32. package/src/APIClient.ts +68 -0
  33. package/src/Application.tsx +6 -2
  34. package/src/BaseApplication.tsx +8 -0
  35. package/src/PluginManager.ts +2 -0
  36. package/src/__tests__/app.test.tsx +8 -0
  37. package/src/__tests__/authRedirect.test.ts +170 -64
  38. package/src/__tests__/globalDeps.test.ts +2 -0
  39. package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +6 -6
  40. package/src/__tests__/remotePlugins.test.ts +148 -0
  41. package/src/authRedirect.ts +23 -84
  42. package/src/components/form/EnvVariableInput.tsx +11 -46
  43. package/src/components/form/VariableInput.tsx +177 -0
  44. package/src/components/form/__tests__/EnvVariableInput.test.tsx +175 -0
  45. package/src/components/form/index.tsx +1 -0
  46. package/src/components/form/table/RowOverlayPreview.tsx +51 -0
  47. package/src/components/form/table/SelectionCell.tsx +72 -0
  48. package/src/components/form/table/Table.tsx +279 -0
  49. package/src/components/form/table/__tests__/Table.pagination.test.tsx +80 -0
  50. package/src/components/form/table/constants.ts +16 -0
  51. package/src/components/form/table/dnd/SortableRow.tsx +106 -0
  52. package/src/components/form/table/dnd/index.ts +10 -0
  53. package/src/components/form/table/index.tsx +13 -0
  54. package/src/components/form/table/styles.ts +110 -0
  55. package/src/components/form/table/utils.ts +75 -0
  56. package/src/components/index.ts +2 -0
  57. package/src/css-variable/CSSVariableProvider.tsx +1 -1
  58. package/src/flow/actions/filterFormDefaultValues.tsx +1 -2
  59. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuModels.tsx +2 -0
  60. package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.test.ts +111 -0
  61. package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.ts +2 -1
  62. package/src/flow/components/TextAreaWithContextSelector.tsx +30 -6
  63. package/src/flow/components/code-editor/__tests__/useCodeRunner.test.tsx +81 -0
  64. package/src/flow/components/code-editor/hooks/useCodeRunner.ts +34 -2
  65. package/src/flow/models/blocks/filter-form/FilterFormBlockModel.tsx +329 -5
  66. package/src/flow/models/blocks/filter-form/__tests__/defaultValues.wiring.test.ts +337 -0
  67. package/src/flow/models/blocks/table/dragSort/dragSortComponents.tsx +1 -81
  68. package/src/flow/models/fields/JSEditableFieldModel.tsx +107 -7
  69. package/src/flow/models/fields/__tests__/JSEditableFieldModel.test.tsx +97 -0
  70. package/src/index.ts +1 -0
  71. package/src/json-logic/globalOperators.js +731 -0
  72. package/src/nocobase-buildin-plugin/index.tsx +4 -4
  73. package/src/theme/globalStyles.ts +21 -0
  74. package/src/theme/index.tsx +1 -0
  75. package/src/utils/globalDeps.ts +50 -30
  76. package/src/utils/remotePlugins.ts +107 -6
@@ -11,7 +11,7 @@ import { createCollectionContextMeta } from '@nocobase/flow-engine';
11
11
  import React, { createContext, type FC, useEffect, useRef, useState } from 'react';
12
12
  import { Navigate, Outlet, useLocation } from 'react-router-dom';
13
13
  import type { Application } from '../Application';
14
- import { getCurrentV2RedirectPath, getDefaultV2AdminRedirectPath, redirectToLegacySignin } from '../authRedirect';
14
+ import { getCurrentV2RedirectPath, getDefaultV2AdminRedirectPath, redirectToV2Signin } from '../authRedirect';
15
15
  import { AppNotFound } from '../components';
16
16
  import { PluginFlowEngine } from '../flow';
17
17
  import { AdminLayoutMenuItemModel, AdminLayoutModel } from '../flow/admin-shell/admin-layout';
@@ -144,7 +144,7 @@ const CurrentUserProvider: FC = ({ children }) => {
144
144
 
145
145
  const user = res?.data?.data;
146
146
  if (user?.id == null) {
147
- redirectToLegacySignin(app, getCurrentV2RedirectPath(app, locationRef.current), { replace: true });
147
+ redirectToV2Signin(app, getCurrentV2RedirectPath(app, locationRef.current), { replace: true });
148
148
  return;
149
149
  }
150
150
 
@@ -169,7 +169,7 @@ const CurrentUserProvider: FC = ({ children }) => {
169
169
  } catch (error: any) {
170
170
  const isAuthError = error?.response?.status === 401 || error?.status === 401;
171
171
  if (isAuthError) {
172
- redirectToLegacySignin(app, getCurrentV2RedirectPath(app, locationRef.current), { replace: true });
172
+ redirectToV2Signin(app, getCurrentV2RedirectPath(app, locationRef.current), { replace: true });
173
173
  return;
174
174
  }
175
175
  if (mounted) {
@@ -199,7 +199,7 @@ const RootRedirect: FC = () => {
199
199
 
200
200
  useEffect(() => {
201
201
  if (!hasToken) {
202
- redirectToLegacySignin(app, getDefaultV2AdminRedirectPath(app), { replace: true });
202
+ redirectToV2Signin(app, getDefaultV2AdminRedirectPath(app), { replace: true });
203
203
  }
204
204
  }, [app, hasToken]);
205
205
 
@@ -0,0 +1,21 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import { injectGlobal } from '@emotion/css';
11
+
12
+ // Antd v5 has no labelFontWeight token, so a descendant selector on the
13
+ // stable Form structure is the lowest-risk implementation for the bolder
14
+ // form label default. Injected globally because v1's GlobalThemeProvider
15
+ // re-exports v2's, so any v1 app served from this codebase goes through
16
+ // the same provider and should get the same defaults.
17
+ injectGlobal`
18
+ .ant-form-item-label > label {
19
+ font-weight: 600;
20
+ }
21
+ `;
@@ -13,6 +13,7 @@ import React, { createContext, FC, useCallback, useMemo, useRef } from 'react';
13
13
  import compatOldTheme from './compatOldTheme';
14
14
  import { addCustomAlgorithmToTheme } from './customAlgorithm';
15
15
  import defaultTheme from './defaultTheme';
16
+ import './globalStyles';
16
17
  import { ThemeConfig } from './type';
17
18
 
18
19
  interface ThemeItem {
@@ -33,53 +33,73 @@ import * as ReactRouter from 'react-router';
33
33
  import * as ReactRouterDom from 'react-router-dom';
34
34
  import jsxRuntime from 'react/jsx-runtime';
35
35
  import * as nocobaseClientV2 from '../index';
36
-
36
+ import * as dndKitCore from '@dnd-kit/core';
37
+ import * as dndKitSortable from '@dnd-kit/sortable';
37
38
  import type { RequireJS } from './requirejs';
38
39
 
40
+ declare global {
41
+ interface Window {
42
+ __nocobase_app_dev__?: boolean;
43
+ __nocobase_app_dev_deps__?: Record<string, unknown>;
44
+ __nocobase_app_dev_plugins__?: Record<string, unknown>;
45
+ }
46
+ }
47
+
48
+ function defineGlobalDep(requirejs: RequireJS, name: string, value: unknown) {
49
+ requirejs.define(name, () => value);
50
+ if (window.__nocobase_app_dev__) {
51
+ window.__nocobase_app_dev_deps__ = window.__nocobase_app_dev_deps__ || {};
52
+ window.__nocobase_app_dev_deps__[name] = value;
53
+ }
54
+ }
55
+
39
56
  /**
40
57
  * @internal
41
58
  */
42
59
  export function defineGlobalDeps(requirejs: RequireJS) {
43
60
  // react
44
- requirejs.define('react', () => React);
45
- requirejs.define('react-dom', () => ReactDOM);
46
- requirejs.define('react/jsx-runtime', () => jsxRuntime);
61
+ defineGlobalDep(requirejs, 'react', React);
62
+ defineGlobalDep(requirejs, 'react-dom', ReactDOM);
63
+ defineGlobalDep(requirejs, 'react/jsx-runtime', jsxRuntime);
47
64
 
48
65
  // react-router
49
- requirejs.define('react-router', () => ReactRouter);
50
- requirejs.define('react-router-dom', () => ReactRouterDom);
66
+ defineGlobalDep(requirejs, 'react-router', ReactRouter);
67
+ defineGlobalDep(requirejs, 'react-router-dom', ReactRouterDom);
51
68
 
52
69
  // antd
53
- requirejs.define('antd', () => antd);
54
- requirejs.define('@ant-design/icons', () => antdIcons);
55
- requirejs.define('@ant-design/cssinjs', () => antdCssinjs);
56
- requirejs.define('antd-style', () => antdStyle);
70
+ defineGlobalDep(requirejs, 'antd', antd);
71
+ defineGlobalDep(requirejs, '@ant-design/icons', antdIcons);
72
+ defineGlobalDep(requirejs, '@ant-design/cssinjs', antdCssinjs);
73
+ defineGlobalDep(requirejs, 'antd-style', antdStyle);
57
74
 
58
75
  // i18next
59
- requirejs.define('i18next', () => i18next);
60
- requirejs.define('react-i18next', () => reactI18next);
76
+ defineGlobalDep(requirejs, 'i18next', i18next);
77
+ defineGlobalDep(requirejs, 'react-i18next', reactI18next);
61
78
 
62
79
  // formily
63
- requirejs.define('@formily/antd-v5', () => formilyAntdV5);
64
- requirejs.define('@formily/core', () => formilyCore);
65
- requirejs.define('@formily/react', () => formilyReact);
66
- requirejs.define('@formily/reactive', () => formilyReactive);
67
- requirejs.define('@formily/shared', () => formilyShared);
80
+ defineGlobalDep(requirejs, '@formily/antd-v5', formilyAntdV5);
81
+ defineGlobalDep(requirejs, '@formily/core', formilyCore);
82
+ defineGlobalDep(requirejs, '@formily/react', formilyReact);
83
+ defineGlobalDep(requirejs, '@formily/reactive', formilyReactive);
84
+ defineGlobalDep(requirejs, '@formily/shared', formilyShared);
68
85
 
69
86
  // nocobase
70
- requirejs.define('@nocobase/utils', () => nocobaseClientUtils);
71
- requirejs.define('@nocobase/utils/client', () => nocobaseClientUtils);
72
- requirejs.define('@nocobase/client-v2', () => nocobaseClientV2);
73
- requirejs.define('@nocobase/client-v2/client-v2', () => nocobaseClientV2);
74
- requirejs.define('@nocobase/flow-engine', () => nocobaseFlowEngine);
75
- requirejs.define('@nocobase/evaluators', () => nocobaseEvaluators);
76
- requirejs.define('@nocobase/evaluators/client', () => nocobaseEvaluators);
87
+ defineGlobalDep(requirejs, '@nocobase/utils', nocobaseClientUtils);
88
+ defineGlobalDep(requirejs, '@nocobase/utils/client', nocobaseClientUtils);
89
+ defineGlobalDep(requirejs, '@nocobase/client-v2', nocobaseClientV2);
90
+ defineGlobalDep(requirejs, '@nocobase/client-v2/client-v2', nocobaseClientV2);
91
+ defineGlobalDep(requirejs, '@nocobase/flow-engine', nocobaseFlowEngine);
92
+ defineGlobalDep(requirejs, '@nocobase/evaluators', nocobaseEvaluators);
93
+ defineGlobalDep(requirejs, '@nocobase/evaluators/client', nocobaseEvaluators);
94
+
95
+ requirejs.define('@dnd-kit/core', () => dndKitCore);
96
+ requirejs.define('@dnd-kit/sortable', () => dndKitSortable);
77
97
 
78
98
  // utils
79
- requirejs.define('ahooks', () => ahooks);
80
- requirejs.define('axios', () => axios);
81
- requirejs.define('dayjs', () => dayjs);
82
- requirejs.define('lodash', () => lodash);
83
- requirejs.define('@emotion/css', () => emotionCss);
84
- requirejs.define('file-saver', () => FileSaver);
99
+ defineGlobalDep(requirejs, 'ahooks', ahooks);
100
+ defineGlobalDep(requirejs, 'axios', axios);
101
+ defineGlobalDep(requirejs, 'dayjs', dayjs);
102
+ defineGlobalDep(requirejs, 'lodash', lodash);
103
+ defineGlobalDep(requirejs, '@emotion/css', emotionCss);
104
+ defineGlobalDep(requirejs, 'file-saver', FileSaver);
85
105
  }
@@ -12,10 +12,22 @@ import type { PluginClass } from '../PluginManager';
12
12
  import type { PluginData } from '../PluginManager';
13
13
  import type { RequireJS } from './requirejs';
14
14
 
15
+ type RemotePluginModule = PluginClass | ({ default?: PluginClass } & Record<string, unknown>);
16
+
15
17
  function getClientV2ModuleId(packageName: string) {
16
18
  return `${packageName}/client-v2`;
17
19
  }
18
20
 
21
+ function getPluginClass(pluginModule: RemotePluginModule): PluginClass {
22
+ const defaultPlugin = 'default' in pluginModule ? pluginModule.default : undefined;
23
+ return defaultPlugin || (pluginModule as PluginClass);
24
+ }
25
+
26
+ function defineAppDevPluginModule(moduleId: string, pluginModule: RemotePluginModule) {
27
+ window.__nocobase_app_dev_plugins__ = window.__nocobase_app_dev_plugins__ || {};
28
+ window.__nocobase_app_dev_plugins__[moduleId] = pluginModule;
29
+ }
30
+
19
31
  /**
20
32
  * @internal
21
33
  */
@@ -25,6 +37,14 @@ export function defineDevPlugins(plugins: Record<string, PluginClass>) {
25
37
  });
26
38
  }
27
39
 
40
+ function defineDevPluginModules(plugins: Record<string, RemotePluginModule>) {
41
+ Object.entries(plugins).forEach(([packageName, pluginModule]) => {
42
+ const moduleId = getClientV2ModuleId(packageName);
43
+ window.define(moduleId, () => pluginModule);
44
+ defineAppDevPluginModule(moduleId, pluginModule);
45
+ });
46
+ }
47
+
28
48
  /**
29
49
  * @internal
30
50
  */
@@ -43,6 +63,12 @@ export function configRequirejs(requirejs: any, pluginData: PluginData[]) {
43
63
  */
44
64
  export function processRemotePlugins(pluginData: PluginData[], resolve: (plugins: [string, PluginClass][]) => void) {
45
65
  return (...pluginModules: (PluginClass & { default?: PluginClass })[]) => {
66
+ pluginModules.forEach((item, index) => {
67
+ if (item) {
68
+ defineAppDevPluginModule(getClientV2ModuleId(pluginData[index].packageName), item);
69
+ }
70
+ });
71
+
46
72
  const res: [string, PluginClass][] = pluginModules
47
73
  .map<[string, PluginClass]>((item, index) => [pluginData[index].name, item?.default || item])
48
74
  .filter((item) => item[1]);
@@ -75,6 +101,77 @@ export function getRemotePlugins(requirejs: any, pluginData: PluginData[] = []):
75
101
  });
76
102
  }
77
103
 
104
+ async function getEsmDevPlugins(pluginData: PluginData[] = []): Promise<Array<[string, PluginClass]>> {
105
+ const plugins: Array<[string, PluginClass]> = [];
106
+ for (const plugin of sortPluginsByAppDevDependencies(pluginData)) {
107
+ const pluginModule: RemotePluginModule = await import(/* webpackIgnore: true */ plugin.url);
108
+ const pluginClass = getPluginClass(pluginModule);
109
+ if (pluginClass) {
110
+ plugins.push([plugin.name, pluginClass]);
111
+ defineDevPluginModules({ [plugin.packageName]: pluginModule });
112
+ }
113
+ }
114
+ return plugins;
115
+ }
116
+
117
+ function sortPluginsByAppDevDependencies(pluginData: PluginData[] = []) {
118
+ const pluginMap = new Map(pluginData.map((plugin) => [plugin.packageName, plugin]));
119
+ const sorted: PluginData[] = [];
120
+ const visiting = new Set<string>();
121
+ const visited = new Set<string>();
122
+
123
+ const visit = (plugin: PluginData) => {
124
+ if (visited.has(plugin.packageName)) {
125
+ return;
126
+ }
127
+ if (visiting.has(plugin.packageName)) {
128
+ return;
129
+ }
130
+ visiting.add(plugin.packageName);
131
+ for (const dep of plugin.appDevDependencies || []) {
132
+ const depPlugin = pluginMap.get(dep);
133
+ if (depPlugin) {
134
+ visit(depPlugin);
135
+ }
136
+ }
137
+ visiting.delete(plugin.packageName);
138
+ visited.add(plugin.packageName);
139
+ sorted.push(plugin);
140
+ };
141
+
142
+ pluginData.forEach(visit);
143
+ return sorted;
144
+ }
145
+
146
+ async function getMixedRemotePluginsInOrder(
147
+ requirejs: RequireJS,
148
+ pluginData: PluginData[] = [],
149
+ ): Promise<Array<[string, PluginClass]>> {
150
+ const plugins: Array<[string, PluginClass]> = [];
151
+ let requirejsPlugins: PluginData[] = [];
152
+ const flushRequirejsPlugins = async () => {
153
+ if (requirejsPlugins.length === 0) {
154
+ return;
155
+ }
156
+ const remotePluginList = await getRemotePlugins(requirejs, requirejsPlugins);
157
+ plugins.push(...remotePluginList);
158
+ requirejsPlugins = [];
159
+ };
160
+
161
+ for (const plugin of sortPluginsByAppDevDependencies(pluginData)) {
162
+ if (plugin.devMode === 'esm') {
163
+ await flushRequirejsPlugins();
164
+ const esmPluginList = await getEsmDevPlugins([plugin]);
165
+ plugins.push(...esmPluginList);
166
+ continue;
167
+ }
168
+ requirejsPlugins.push(plugin);
169
+ }
170
+
171
+ await flushRequirejsPlugins();
172
+ return plugins;
173
+ }
174
+
78
175
  interface GetPluginsOption {
79
176
  requirejs: RequireJS;
80
177
  pluginData: PluginData[];
@@ -103,15 +200,19 @@ export async function getPlugins(options: GetPluginsOption): Promise<Array<[stri
103
200
  }
104
201
 
105
202
  const remotePlugins = pluginData.filter((item) => !resolveDevPlugins[item.packageName]);
203
+ const esmDevPlugins = remotePlugins.filter((item) => item.devMode === 'esm');
204
+ const requirejsPlugins = remotePlugins.filter((item) => item.devMode !== 'esm');
106
205
 
107
- if (remotePlugins.length === 0) {
108
- return res;
109
- }
110
-
111
- if (res.length === 0) {
112
- const remotePluginList = await getRemotePlugins(requirejs, remotePlugins);
206
+ if (esmDevPlugins.length === 0) {
207
+ if (requirejsPlugins.length === 0) {
208
+ return res;
209
+ }
210
+ const remotePluginList = await getRemotePlugins(requirejs, requirejsPlugins);
113
211
  res.push(...remotePluginList);
212
+ return res;
114
213
  }
115
214
 
215
+ const mixedPluginList = await getMixedRemotePluginsInOrder(requirejs, remotePlugins);
216
+ res.push(...mixedPluginList);
116
217
  return res;
117
218
  }