@nocobase/flow-engine 2.0.0-beta.2 → 2.0.0-beta.20

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 (124) hide show
  1. package/lib/BlockScopedFlowEngine.js +0 -1
  2. package/lib/JSRunner.d.ts +6 -0
  3. package/lib/JSRunner.js +2 -1
  4. package/lib/ViewScopedFlowEngine.js +3 -0
  5. package/lib/acl/Acl.js +13 -3
  6. package/lib/components/dnd/gridDragPlanner.d.ts +1 -0
  7. package/lib/components/dnd/gridDragPlanner.js +53 -1
  8. package/lib/components/settings/wrappers/component/SwitchWithTitle.js +2 -1
  9. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +11 -3
  10. package/lib/components/variables/VariableInput.js +8 -2
  11. package/lib/data-source/index.js +6 -0
  12. package/lib/executor/FlowExecutor.d.ts +2 -1
  13. package/lib/executor/FlowExecutor.js +156 -22
  14. package/lib/flowContext.d.ts +4 -1
  15. package/lib/flowContext.js +176 -107
  16. package/lib/flowEngine.d.ts +21 -0
  17. package/lib/flowEngine.js +38 -0
  18. package/lib/flowSettings.js +12 -10
  19. package/lib/index.d.ts +3 -0
  20. package/lib/index.js +16 -0
  21. package/lib/models/CollectionFieldModel.d.ts +1 -0
  22. package/lib/models/CollectionFieldModel.js +3 -2
  23. package/lib/models/flowModel.d.ts +7 -0
  24. package/lib/models/flowModel.js +66 -1
  25. package/lib/provider.js +7 -6
  26. package/lib/resources/baseRecordResource.d.ts +5 -0
  27. package/lib/resources/baseRecordResource.js +24 -0
  28. package/lib/resources/multiRecordResource.d.ts +1 -0
  29. package/lib/resources/multiRecordResource.js +11 -4
  30. package/lib/resources/singleRecordResource.js +2 -0
  31. package/lib/resources/sqlResource.d.ts +1 -0
  32. package/lib/resources/sqlResource.js +8 -3
  33. package/lib/runjs-context/contexts/base.js +10 -4
  34. package/lib/runjsLibs.d.ts +28 -0
  35. package/lib/runjsLibs.js +532 -0
  36. package/lib/scheduler/ModelOperationScheduler.d.ts +2 -0
  37. package/lib/scheduler/ModelOperationScheduler.js +21 -21
  38. package/lib/types.d.ts +15 -0
  39. package/lib/utils/createCollectionContextMeta.js +1 -0
  40. package/lib/utils/index.d.ts +2 -0
  41. package/lib/utils/index.js +10 -0
  42. package/lib/utils/params-resolvers.js +16 -9
  43. package/lib/utils/resolveModuleUrl.d.ts +58 -0
  44. package/lib/utils/resolveModuleUrl.js +65 -0
  45. package/lib/utils/runjsModuleLoader.d.ts +58 -0
  46. package/lib/utils/runjsModuleLoader.js +422 -0
  47. package/lib/utils/runjsTemplateCompat.d.ts +35 -0
  48. package/lib/utils/runjsTemplateCompat.js +743 -0
  49. package/lib/utils/safeGlobals.d.ts +5 -9
  50. package/lib/utils/safeGlobals.js +129 -17
  51. package/lib/views/createViewMeta.d.ts +0 -7
  52. package/lib/views/createViewMeta.js +19 -70
  53. package/lib/views/index.d.ts +1 -2
  54. package/lib/views/index.js +4 -3
  55. package/lib/views/useDialog.js +8 -3
  56. package/lib/views/useDrawer.js +7 -2
  57. package/lib/views/usePage.d.ts +4 -0
  58. package/lib/views/usePage.js +43 -6
  59. package/lib/views/usePopover.js +4 -1
  60. package/lib/views/viewEvents.d.ts +17 -0
  61. package/lib/views/viewEvents.js +90 -0
  62. package/package.json +4 -4
  63. package/src/BlockScopedFlowEngine.ts +2 -5
  64. package/src/JSRunner.ts +8 -1
  65. package/src/ViewScopedFlowEngine.ts +4 -0
  66. package/src/__tests__/createViewMeta.popup.test.ts +62 -1
  67. package/src/__tests__/flowEngine.dataSourceDirty.test.ts +63 -0
  68. package/src/__tests__/flowSettings.open.test.tsx +69 -15
  69. package/src/__tests__/provider.test.tsx +0 -5
  70. package/src/__tests__/runjsExternalLibs.test.ts +242 -0
  71. package/src/__tests__/runjsLibsLazyLoading.test.ts +44 -0
  72. package/src/__tests__/runjsPreprocessDefault.test.ts +49 -0
  73. package/src/acl/Acl.tsx +3 -3
  74. package/src/components/__tests__/gridDragPlanner.test.ts +141 -1
  75. package/src/components/dnd/gridDragPlanner.ts +60 -0
  76. package/src/components/settings/wrappers/component/SwitchWithTitle.tsx +2 -1
  77. package/src/components/settings/wrappers/component/__tests__/InlineControls.test.tsx +74 -0
  78. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +11 -3
  79. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +63 -4
  80. package/src/components/variables/VariableInput.tsx +8 -2
  81. package/src/data-source/index.ts +6 -0
  82. package/src/executor/FlowExecutor.ts +193 -23
  83. package/src/executor/__tests__/flowExecutor.test.ts +66 -0
  84. package/src/flowContext.ts +234 -118
  85. package/src/flowEngine.ts +41 -0
  86. package/src/flowSettings.ts +12 -11
  87. package/src/index.ts +10 -0
  88. package/src/models/CollectionFieldModel.tsx +3 -1
  89. package/src/models/__tests__/dispatchEvent.when.test.ts +356 -0
  90. package/src/models/__tests__/flowModel.clone.test.ts +416 -0
  91. package/src/models/__tests__/flowModel.test.ts +16 -0
  92. package/src/models/flowModel.tsx +94 -1
  93. package/src/provider.tsx +9 -7
  94. package/src/resources/__tests__/multiRecordResource.test.ts +44 -0
  95. package/src/resources/__tests__/sqlResource.test.ts +60 -0
  96. package/src/resources/baseRecordResource.ts +31 -0
  97. package/src/resources/multiRecordResource.ts +11 -4
  98. package/src/resources/singleRecordResource.ts +3 -0
  99. package/src/resources/sqlResource.ts +8 -3
  100. package/src/runjs-context/contexts/base.ts +9 -2
  101. package/src/runjsLibs.ts +622 -0
  102. package/src/scheduler/ModelOperationScheduler.ts +23 -21
  103. package/src/types.ts +26 -1
  104. package/src/utils/__tests__/params-resolvers.test.ts +40 -0
  105. package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +38 -0
  106. package/src/utils/__tests__/runjsTemplateCompat.test.ts +159 -0
  107. package/src/utils/__tests__/safeGlobals.test.ts +49 -2
  108. package/src/utils/createCollectionContextMeta.ts +1 -0
  109. package/src/utils/index.ts +6 -0
  110. package/src/utils/params-resolvers.ts +23 -9
  111. package/src/utils/resolveModuleUrl.ts +91 -0
  112. package/src/utils/runjsModuleLoader.ts +553 -0
  113. package/src/utils/runjsTemplateCompat.ts +828 -0
  114. package/src/utils/safeGlobals.ts +133 -16
  115. package/src/views/__tests__/FlowView.usePage.test.tsx +54 -1
  116. package/src/views/__tests__/useDialog.closeDestroy.test.tsx +35 -8
  117. package/src/views/__tests__/viewEvents.resolveOpenerEngine.test.ts +28 -0
  118. package/src/views/createViewMeta.ts +22 -75
  119. package/src/views/index.tsx +1 -2
  120. package/src/views/useDialog.tsx +9 -2
  121. package/src/views/useDrawer.tsx +8 -1
  122. package/src/views/usePage.tsx +51 -5
  123. package/src/views/usePopover.tsx +4 -1
  124. package/src/views/viewEvents.ts +55 -0
@@ -361,6 +361,13 @@ export declare class FlowModel<Structure extends DefaultStructure = DefaultStruc
361
361
  }): Promise<void>;
362
362
  get translate(): any;
363
363
  serialize(): Record<string, any>;
364
+ /**
365
+ * 复制当前模型实例为一个新的实例。
366
+ * 新实例及其所有子模型都会有新的 uid,且不保留 root model 的 parent 关系。
367
+ * 内部所有引用旧 uid 的地方(如 parentId, parentUid 等)都会被替换为对应的新 uid。
368
+ * @returns {FlowModel} 复制后的新模型实例
369
+ */
370
+ clone<T extends FlowModel = this>(): T;
364
371
  /**
365
372
  * Opens the flow settings dialog for this flow model.
366
373
  * @param options - Configuration options for opening flow settings, excluding the model property
@@ -353,7 +353,18 @@ const _FlowModel = class _FlowModel {
353
353
  const meta = Cls.meta;
354
354
  const metaCreate = meta == null ? void 0 : meta.createModelOptions;
355
355
  if (metaCreate && typeof metaCreate === "object" && metaCreate.subModels) {
356
- mergedSubModels = import_lodash.default.merge({}, import_lodash.default.cloneDeep(metaCreate.subModels || {}), import_lodash.default.cloneDeep(subModels || {}));
356
+ const replaceArrays = /* @__PURE__ */ __name((objValue, srcValue) => {
357
+ if (Array.isArray(objValue) && Array.isArray(srcValue)) {
358
+ return srcValue;
359
+ }
360
+ return void 0;
361
+ }, "replaceArrays");
362
+ mergedSubModels = import_lodash.default.mergeWith(
363
+ {},
364
+ import_lodash.default.cloneDeep(metaCreate.subModels || {}),
365
+ import_lodash.default.cloneDeep(subModels || {}),
366
+ replaceArrays
367
+ );
357
368
  }
358
369
  } catch (e) {
359
370
  }
@@ -1119,6 +1130,60 @@ const _FlowModel = class _FlowModel {
1119
1130
  }
1120
1131
  return data;
1121
1132
  }
1133
+ /**
1134
+ * 复制当前模型实例为一个新的实例。
1135
+ * 新实例及其所有子模型都会有新的 uid,且不保留 root model 的 parent 关系。
1136
+ * 内部所有引用旧 uid 的地方(如 parentId, parentUid 等)都会被替换为对应的新 uid。
1137
+ * @returns {FlowModel} 复制后的新模型实例
1138
+ */
1139
+ clone() {
1140
+ if (!this.flowEngine) {
1141
+ throw new Error("FlowEngine is not set on this model. Please set flowEngine before cloning.");
1142
+ }
1143
+ const serialized = this.serialize();
1144
+ const uidMap = /* @__PURE__ */ new Map();
1145
+ const collectUids = /* @__PURE__ */ __name((data) => {
1146
+ if (data.uid && typeof data.uid === "string") {
1147
+ uidMap.set(data.uid, (0, import_secure.uid)());
1148
+ }
1149
+ if (data.subModels) {
1150
+ for (const key in data.subModels) {
1151
+ const subModel = data.subModels[key];
1152
+ if (Array.isArray(subModel)) {
1153
+ subModel.forEach((item) => collectUids(item));
1154
+ } else if (subModel && typeof subModel === "object") {
1155
+ collectUids(subModel);
1156
+ }
1157
+ }
1158
+ }
1159
+ }, "collectUids");
1160
+ collectUids(serialized);
1161
+ const replaceUidReferences = /* @__PURE__ */ __name((data, isRoot = false) => {
1162
+ if (data === null || data === void 0) {
1163
+ return data;
1164
+ }
1165
+ if (typeof data === "string") {
1166
+ return uidMap.get(data) ?? data;
1167
+ }
1168
+ if (Array.isArray(data)) {
1169
+ return data.map((item) => replaceUidReferences(item, false));
1170
+ }
1171
+ if (typeof data === "object") {
1172
+ const result = {};
1173
+ for (const key in data) {
1174
+ if (!Object.prototype.hasOwnProperty.call(data, key)) continue;
1175
+ if (isRoot && key === "parentId") {
1176
+ continue;
1177
+ }
1178
+ result[key] = replaceUidReferences(data[key], false);
1179
+ }
1180
+ return result;
1181
+ }
1182
+ return data;
1183
+ }, "replaceUidReferences");
1184
+ const clonedData = replaceUidReferences(serialized, true);
1185
+ return this.flowEngine.createModel(clonedData);
1186
+ }
1122
1187
  /**
1123
1188
  * Opens the flow settings dialog for this flow model.
1124
1189
  * @param options - Configuration options for opening flow settings, excluding the model property
package/lib/provider.js CHANGED
@@ -79,17 +79,17 @@ const FlowEngineGlobalsContextProvider = /* @__PURE__ */ __name(({ children }) =
79
79
  cache: false,
80
80
  get: /* @__PURE__ */ __name((ctx) => new import_FlowView.FlowViewer(ctx, { drawer, embed, popover, dialog }), "get")
81
81
  });
82
- engine.context.defineProperty("themeToken", {
83
- get: /* @__PURE__ */ __name(() => token, "get"),
84
- observable: true,
85
- cache: true
86
- });
87
82
  for (const item of Object.entries(context)) {
88
83
  const [key, value] = item;
89
84
  if (value) {
90
85
  engine.context.defineProperty(key, { value });
91
86
  }
92
87
  }
88
+ engine.context.defineProperty("themeToken", {
89
+ get: /* @__PURE__ */ __name(() => token, "get"),
90
+ observable: true,
91
+ cache: true
92
+ });
93
93
  engine.reactView.refresh();
94
94
  }, [engine, drawer, modal, message, notification, config, popover, token, dialog, embed]);
95
95
  return /* @__PURE__ */ import_react.default.createElement(import_antd.ConfigProvider, { ...config, locale: (_a = engine.context.locales) == null ? void 0 : _a.antd, popupMatchSelectWidth: false }, children, contextHolder, popoverContextHolder, pageContextHolder, dialogContextHolder);
@@ -97,9 +97,10 @@ const FlowEngineGlobalsContextProvider = /* @__PURE__ */ __name(({ children }) =
97
97
  const useFlowEngine = /* @__PURE__ */ __name(({ throwError = true } = {}) => {
98
98
  const context = (0, import_react.useContext)(FlowEngineReactContext);
99
99
  if (!context && throwError) {
100
- throw new Error(
100
+ console.warn(
101
101
  "useFlowEngine must be used within a FlowEngineProvider, and FlowEngineProvider must be supplied with an engine."
102
102
  );
103
+ return;
103
104
  }
104
105
  return context;
105
106
  }, "useFlowEngine");
@@ -30,6 +30,11 @@ export declare abstract class BaseRecordResource<TData = any> extends APIResourc
30
30
  runAction<TData = any, TMeta = any>(action: string, options: any): Promise<any>;
31
31
  setResourceName(resourceName: string): this;
32
32
  getResourceName(): string;
33
+ /**
34
+ * Mark current resource as dirty on the root FlowEngine.
35
+ * Used to coordinate "refresh on active" across view stacks.
36
+ */
37
+ protected markDataSourceDirty(resourceName?: string): void;
33
38
  setSourceId(sourceId: string | number): this;
34
39
  getSourceId(): string | number;
35
40
  setDataSourceKey(dataSourceKey: string): this;
@@ -44,6 +44,7 @@ var import_lodash = __toESM(require("lodash"));
44
44
  var import_apiResource = require("./apiResource");
45
45
  var import_filterItem = require("./filterItem");
46
46
  var import_flowResource = require("./flowResource");
47
+ var import_viewEvents = require("../views/viewEvents");
47
48
  const _BaseRecordResource = class _BaseRecordResource extends import_apiResource.APIResource {
48
49
  resourceName;
49
50
  sourceId = null;
@@ -145,6 +146,29 @@ const _BaseRecordResource = class _BaseRecordResource extends import_apiResource
145
146
  getResourceName() {
146
147
  return this.resourceName;
147
148
  }
149
+ /**
150
+ * Mark current resource as dirty on the root FlowEngine.
151
+ * Used to coordinate "refresh on active" across view stacks.
152
+ */
153
+ markDataSourceDirty(resourceName) {
154
+ var _a, _b;
155
+ const engine = this.context.engine;
156
+ if (!engine) return;
157
+ const dataSourceKey = this.getDataSourceKey() || "main";
158
+ const resName = resourceName || this.getResourceName();
159
+ if (!resName) return;
160
+ const affectedResourceNames = /* @__PURE__ */ new Set([String(resName)]);
161
+ if (typeof resName === "string" && resName.includes(".")) {
162
+ affectedResourceNames.add(resName.split(".")[0]);
163
+ }
164
+ for (const name of affectedResourceNames) {
165
+ engine.markDataSourceDirty(dataSourceKey, name);
166
+ }
167
+ (_b = (_a = engine.emitter) == null ? void 0 : _a.emit) == null ? void 0 : _b.call(_a, import_viewEvents.DATA_SOURCE_DIRTY_EVENT, {
168
+ dataSourceKey,
169
+ resourceNames: Array.from(affectedResourceNames)
170
+ });
171
+ }
148
172
  setSourceId(sourceId) {
149
173
  this.sourceId = sourceId;
150
174
  return this;
@@ -16,6 +16,7 @@ export declare class MultiRecordResource<TDataItem = any> extends BaseRecordReso
16
16
  value: Record<string, any>;
17
17
  };
18
18
  private refreshTimer;
19
+ private refreshWaiters;
19
20
  protected createActionOptions: {};
20
21
  protected updateActionOptions: {};
21
22
  protected _refreshActionName: string;
@@ -47,6 +47,7 @@ const _MultiRecordResource = class _MultiRecordResource extends import_baseRecor
47
47
  _data = import_reactive.observable.ref([]);
48
48
  _meta = import_reactive.observable.ref({});
49
49
  refreshTimer = null;
50
+ refreshWaiters = [];
50
51
  createActionOptions = {};
51
52
  updateActionOptions = {};
52
53
  _refreshActionName = "list";
@@ -130,6 +131,7 @@ const _MultiRecordResource = class _MultiRecordResource extends import_baseRecor
130
131
  async create(data, options) {
131
132
  const config = this.mergeRequestConfig({ data }, this.createActionOptions, options);
132
133
  const res = await this.runAction("create", config);
134
+ this.markDataSourceDirty();
133
135
  this.emit("saved", data);
134
136
  if ((options == null ? void 0 : options.refresh) !== false) {
135
137
  await this.refresh();
@@ -160,6 +162,7 @@ const _MultiRecordResource = class _MultiRecordResource extends import_baseRecor
160
162
  options
161
163
  );
162
164
  await this.runAction("update", config);
165
+ this.markDataSourceDirty();
163
166
  this.emit("saved", data);
164
167
  await this.refresh();
165
168
  }
@@ -180,6 +183,7 @@ const _MultiRecordResource = class _MultiRecordResource extends import_baseRecor
180
183
  options
181
184
  );
182
185
  await this.runAction("destroy", config);
186
+ this.markDataSourceDirty();
183
187
  const currentPage = this.getPage();
184
188
  const lastPage = Math.ceil((this.getCount() - import_lodash.default.castArray(filterByTk).length) / this.getPageSize());
185
189
  if (currentPage > lastPage) {
@@ -202,7 +206,11 @@ const _MultiRecordResource = class _MultiRecordResource extends import_baseRecor
202
206
  clearTimeout(this.refreshTimer);
203
207
  }
204
208
  return new Promise((resolve, reject) => {
209
+ this.refreshWaiters.push({ resolve, reject });
205
210
  this.refreshTimer = setTimeout(async () => {
211
+ const waiters = this.refreshWaiters;
212
+ this.refreshWaiters = [];
213
+ this.refreshTimer = null;
206
214
  try {
207
215
  this.clearError();
208
216
  this.loading = true;
@@ -218,13 +226,12 @@ const _MultiRecordResource = class _MultiRecordResource extends import_baseRecor
218
226
  this.setPageSize(meta.pageSize);
219
227
  }
220
228
  this.emit("refresh");
221
- this.loading = false;
222
- resolve();
229
+ waiters.forEach((w) => w.resolve());
223
230
  } catch (error) {
224
231
  this.setError(error);
225
- reject(error instanceof Error ? error : new Error(String(error)));
232
+ const err = error instanceof Error ? error : new Error(String(error));
233
+ waiters.forEach((w) => w.reject(err));
226
234
  } finally {
227
- this.refreshTimer = null;
228
235
  this.loading = false;
229
236
  }
230
237
  });
@@ -70,6 +70,7 @@ const _SingleRecordResource = class _SingleRecordResource extends import_baseRec
70
70
  ...config,
71
71
  data: result
72
72
  });
73
+ this.markDataSourceDirty();
73
74
  this.emit("saved", data);
74
75
  if ((options == null ? void 0 : options.refresh) !== false) {
75
76
  await this.refresh();
@@ -86,6 +87,7 @@ const _SingleRecordResource = class _SingleRecordResource extends import_baseRec
86
87
  options
87
88
  );
88
89
  await this.runAction("destroy", config);
90
+ this.markDataSourceDirty();
89
91
  this.setData(null);
90
92
  }
91
93
  async refresh() {
@@ -35,6 +35,7 @@ export declare class SQLResource<TData = any> extends BaseRecordResource<TData>
35
35
  value: Record<string, any>;
36
36
  };
37
37
  private refreshTimer;
38
+ private refreshWaiters;
38
39
  private _debugEnabled;
39
40
  private _sql;
40
41
  protected request: {
@@ -126,6 +126,7 @@ const _SQLResource = class _SQLResource extends import_baseRecordResource.BaseRe
126
126
  _data = import_reactive.observable.ref(null);
127
127
  _meta = import_reactive.observable.ref({});
128
128
  refreshTimer = null;
129
+ refreshWaiters = [];
129
130
  _debugEnabled = false;
130
131
  _sql;
131
132
  // 请求配置 - 与 APIClient 接口保持一致
@@ -261,7 +262,11 @@ const _SQLResource = class _SQLResource extends import_baseRecordResource.BaseRe
261
262
  clearTimeout(this.refreshTimer);
262
263
  }
263
264
  return new Promise((resolve, reject) => {
265
+ this.refreshWaiters.push({ resolve, reject });
264
266
  this.refreshTimer = setTimeout(async () => {
267
+ const waiters = this.refreshWaiters;
268
+ this.refreshWaiters = [];
269
+ this.refreshTimer = null;
265
270
  try {
266
271
  this.clearError();
267
272
  this.loading = true;
@@ -270,12 +275,12 @@ const _SQLResource = class _SQLResource extends import_baseRecordResource.BaseRe
270
275
  this.setData(data).setMeta(meta);
271
276
  this.loading = false;
272
277
  this.emit("refresh");
273
- resolve();
278
+ waiters.forEach((w) => w.resolve());
274
279
  } catch (error) {
275
280
  this.setError(error);
276
- reject(error instanceof Error ? error : new Error(String(error)));
281
+ const err = error instanceof Error ? error : new Error(String(error));
282
+ waiters.forEach((w) => w.reject(err));
277
283
  } finally {
278
- this.refreshTimer = null;
279
284
  this.loading = false;
280
285
  }
281
286
  });
@@ -67,14 +67,17 @@ function defineBaseContextMeta() {
67
67
  ReactDOM: "ReactDOM client API including createRoot for rendering React components. Also available via `ctx.libs.ReactDOM`.",
68
68
  antd: "Ant Design component library. Recommended access path: `ctx.libs.antd`.",
69
69
  libs: {
70
- description: "Namespace for third-party and shared libraries. Includes React, ReactDOM, Ant Design, and dayjs.",
70
+ description: "Namespace for third-party and shared libraries. Includes React, ReactDOM, Ant Design, dayjs, lodash, math.js, and formula.js.",
71
71
  detail: "Libraries namespace",
72
72
  properties: {
73
73
  React: "React namespace (same as ctx.React).",
74
74
  ReactDOM: "ReactDOM client API (same as ctx.ReactDOM).",
75
75
  antd: "Ant Design component library (same as ctx.antd).",
76
76
  dayjs: "dayjs date-time utility library.",
77
- antdIcons: "Ant Design icons library. Example: `ctx.libs.antdIcons.PlusOutlined`."
77
+ antdIcons: "Ant Design icons library. Example: `ctx.libs.antdIcons.PlusOutlined`.",
78
+ lodash: 'Lodash utility library. Example: `ctx.libs.lodash.get(obj, "a.b.c")`.',
79
+ math: 'Math.js library for mathematical operations. Example: `ctx.libs.math.evaluate("2 + 3 * 4")`.',
80
+ formula: "Formula.js library for spreadsheet-like formulas. Example: `ctx.libs.formula.SUM([1, 2, 3])`."
78
81
  }
79
82
  }
80
83
  },
@@ -156,14 +159,17 @@ function defineBaseContextMeta() {
156
159
  ReactDOM: "ReactDOM \u5BA2\u6237\u7AEF API\uFF0C\u542B createRoot \u7B49\u6E32\u67D3\u65B9\u6CD5\u3002\u63A8\u8350\u901A\u8FC7 `ctx.libs.ReactDOM` \u8BBF\u95EE\u3002",
157
160
  antd: "Ant Design \u7EC4\u4EF6\u5E93\uFF08RunJS \u73AF\u5883\u4E2D\u53EF\u7528\uFF09\u3002\u63A8\u8350\u4F7F\u7528 `ctx.libs.antd` \u8BBF\u95EE\u3002",
158
161
  libs: {
159
- description: "\u7B2C\u4E09\u65B9/\u901A\u7528\u5E93\u7684\u7EDF\u4E00\u547D\u540D\u7A7A\u95F4\uFF0C\u5305\u542B React\u3001ReactDOM\u3001Ant Design\u3001dayjs \u7B49\u3002\u540E\u7EED\u65B0\u589E\u5E93\u4F1A\u4F18\u5148\u6302\u5728\u6B64\u5904\u3002",
162
+ description: "\u7B2C\u4E09\u65B9/\u901A\u7528\u5E93\u7684\u7EDF\u4E00\u547D\u540D\u7A7A\u95F4\uFF0C\u5305\u542B React\u3001ReactDOM\u3001Ant Design\u3001dayjs\u3001lodash\u3001math.js\u3001formula.js \u7B49\u3002\u540E\u7EED\u65B0\u589E\u5E93\u4F1A\u4F18\u5148\u6302\u5728\u6B64\u5904\u3002",
160
163
  detail: "\u901A\u7528\u5E93\u547D\u540D\u7A7A\u95F4",
161
164
  properties: {
162
165
  React: "React \u547D\u540D\u7A7A\u95F4\uFF08\u7B49\u4EF7\u4E8E ctx.React\uFF09\u3002",
163
166
  ReactDOM: "ReactDOM \u5BA2\u6237\u7AEF API\uFF08\u7B49\u4EF7\u4E8E ctx.ReactDOM\uFF09\u3002",
164
167
  antd: "Ant Design \u7EC4\u4EF6\u5E93\uFF08\u7B49\u4EF7\u4E8E ctx.antd\uFF09\u3002",
165
168
  dayjs: "dayjs \u65E5\u671F\u65F6\u95F4\u5DE5\u5177\u5E93\u3002",
166
- antdIcons: "Ant Design \u56FE\u6807\u5E93\u3002 \u4F8B\u5982\uFF1A`ctx.libs.antdIcons.PlusOutlined`\u3002"
169
+ antdIcons: "Ant Design \u56FE\u6807\u5E93\u3002 \u4F8B\u5982\uFF1A`ctx.libs.antdIcons.PlusOutlined`\u3002",
170
+ lodash: 'Lodash \u5DE5\u5177\u5E93\u3002\u4F8B\u5982\uFF1A`ctx.libs.lodash.get(obj, "a.b.c")`\u3002',
171
+ math: 'Math.js \u6570\u5B66\u8FD0\u7B97\u5E93\u3002\u4F8B\u5982\uFF1A`ctx.libs.math.evaluate("2 + 3 * 4")`\u3002',
172
+ formula: "Formula.js \u7535\u5B50\u8868\u683C\u516C\u5F0F\u5E93\u3002\u4F8B\u5982\uFF1A`ctx.libs.formula.SUM([1, 2, 3])`\u3002"
167
173
  }
168
174
  }
169
175
  },
@@ -0,0 +1,28 @@
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
+ import type { FlowContext } from './flowContext';
10
+ export type RunJSLibCache = 'global' | 'context';
11
+ export type RunJSLibLoader<T = any> = (ctx: FlowContext) => T | Promise<T>;
12
+ export declare function registerRunJSLib(name: string, loader: RunJSLibLoader, options?: {
13
+ cache?: RunJSLibCache;
14
+ }): void;
15
+ export declare function setupRunJSLibs(ctx: FlowContext): void;
16
+ export declare function setRunJSLibOverride(ctx: FlowContext, name: string, value: unknown, options?: {
17
+ topLevelKey?: string | false;
18
+ }): void;
19
+ export declare function externalReactRender(options: {
20
+ ctx: any;
21
+ entry: any;
22
+ vnode: any;
23
+ containerEl: any;
24
+ rootMap: WeakMap<any, any>;
25
+ unmountContainerRoot: () => void;
26
+ internalReact: any;
27
+ internalAntd: any;
28
+ }): any;