@nocobase/flow-engine 2.2.0-alpha.1 → 2.2.0-alpha.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.
Files changed (84) hide show
  1. package/lib/JSRunner.d.ts +1 -0
  2. package/lib/JSRunner.js +110 -20
  3. package/lib/components/FieldModelRenderer.js +44 -31
  4. package/lib/components/FlowContextSelector.js +24 -3
  5. package/lib/components/dnd/index.js +9 -2
  6. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +86 -32
  7. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.js +20 -0
  8. package/lib/components/variables/VariableHybridInput.d.ts +8 -0
  9. package/lib/components/variables/VariableHybridInput.js +128 -12
  10. package/lib/components/variables/types.d.ts +8 -0
  11. package/lib/flowContext.d.ts +1 -1
  12. package/lib/flowContext.js +87 -36
  13. package/lib/flowI18n.js +3 -3
  14. package/lib/flowSettings.d.ts +5 -1
  15. package/lib/flowSettings.js +70 -0
  16. package/lib/locale/en-US.json +1 -0
  17. package/lib/locale/index.d.ts +2 -0
  18. package/lib/locale/zh-CN.json +1 -0
  19. package/lib/resources/apiResource.js +2 -1
  20. package/lib/resources/baseRecordResource.js +6 -17
  21. package/lib/resources/multiRecordResource.js +13 -3
  22. package/lib/resources/singleRecordResource.js +7 -2
  23. package/lib/runjs-context/helpers.js +12 -5
  24. package/lib/types.d.ts +12 -0
  25. package/lib/utils/dataSourceDirty.d.ts +20 -0
  26. package/lib/utils/dataSourceDirty.js +139 -0
  27. package/lib/utils/dirtyAwareApiClient.d.ts +11 -0
  28. package/lib/utils/dirtyAwareApiClient.js +378 -0
  29. package/lib/utils/index.d.ts +1 -1
  30. package/lib/utils/index.js +11 -11
  31. package/lib/utils/openViewRouteState.d.ts +28 -0
  32. package/lib/utils/openViewRouteState.js +125 -0
  33. package/lib/utils/parsePathnameToViewParams.d.ts +3 -0
  34. package/lib/utils/parsePathnameToViewParams.js +18 -1
  35. package/lib/utils/resolveRunJSObjectValues.js +3 -2
  36. package/lib/utils/runjsModuleLoader.js +0 -30
  37. package/lib/views/ViewNavigation.js +5 -0
  38. package/package.json +4 -4
  39. package/src/JSRunner.ts +112 -25
  40. package/src/__tests__/JSRunner.test.ts +4 -5
  41. package/src/__tests__/flowContext.test.ts +131 -0
  42. package/src/__tests__/flowEngine.dataSourceDirty.test.ts +51 -0
  43. package/src/__tests__/flowI18n.test.ts +11 -0
  44. package/src/__tests__/flowModel.openView.navigation.test.ts +28 -0
  45. package/src/__tests__/flowSettings.test.ts +72 -0
  46. package/src/__tests__/runjsRuntimeFeatures.test.ts +15 -2
  47. package/src/components/FieldModelRenderer.tsx +50 -36
  48. package/src/components/FlowContextSelector.tsx +33 -2
  49. package/src/components/__tests__/FieldModelRenderer.test.tsx +165 -0
  50. package/src/components/dnd/index.tsx +11 -2
  51. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +105 -35
  52. package/src/components/settings/wrappers/contextual/__tests__/FlowsFloatContextMenu.test.tsx +381 -12
  53. package/src/components/settings/wrappers/contextual/useFloatToolbarVisibility.ts +28 -0
  54. package/src/components/variables/VariableHybridInput.tsx +166 -9
  55. package/src/components/variables/__tests__/VariableHybridInput.test.tsx +178 -0
  56. package/src/components/variables/types.ts +8 -0
  57. package/src/flowContext.ts +100 -33
  58. package/src/flowI18n.ts +8 -3
  59. package/src/flowSettings.ts +85 -1
  60. package/src/locale/en-US.json +1 -0
  61. package/src/locale/zh-CN.json +1 -0
  62. package/src/resources/apiResource.ts +2 -1
  63. package/src/resources/baseRecordResource.ts +6 -23
  64. package/src/resources/multiRecordResource.ts +13 -3
  65. package/src/resources/singleRecordResource.ts +6 -1
  66. package/src/runjs-context/helpers.ts +12 -6
  67. package/src/types.ts +14 -0
  68. package/src/utils/__tests__/dirtyAwareApiClient.test.ts +392 -0
  69. package/src/utils/__tests__/openViewRouteState.test.ts +40 -0
  70. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +36 -0
  71. package/src/utils/dataSourceDirty.ts +126 -0
  72. package/src/utils/dirtyAwareApiClient.ts +430 -0
  73. package/src/utils/index.ts +10 -9
  74. package/src/utils/openViewRouteState.ts +107 -0
  75. package/src/utils/parsePathnameToViewParams.ts +23 -1
  76. package/src/utils/resolveRunJSObjectValues.ts +5 -2
  77. package/src/utils/runjsModuleLoader.ts +0 -32
  78. package/src/views/ViewNavigation.ts +6 -1
  79. package/src/views/__tests__/ViewNavigation.test.ts +15 -0
  80. package/lib/utils/safeGlobals.d.ts +0 -28
  81. package/lib/utils/safeGlobals.js +0 -367
  82. package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +0 -38
  83. package/src/utils/__tests__/safeGlobals.test.ts +0 -106
  84. package/src/utils/safeGlobals.ts +0 -406
@@ -44,7 +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
+ var import_dataSourceDirty = require("../utils/dataSourceDirty");
48
48
  const _BaseRecordResource = class _BaseRecordResource extends import_apiResource.APIResource {
49
49
  resourceName;
50
50
  sourceId = null;
@@ -151,22 +151,11 @@ const _BaseRecordResource = class _BaseRecordResource extends import_apiResource
151
151
  * Used to coordinate "refresh on active" across view stacks.
152
152
  */
153
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)
154
+ (0, import_dataSourceDirty.markDataSourceDirty)({
155
+ engine: this.context.engine,
156
+ dataSourceKey: this.getDataSourceKey(),
157
+ resourceName: resourceName || this.getResourceName(),
158
+ includePreviousEngines: true
170
159
  });
171
160
  }
172
161
  setSourceId(sourceId) {
@@ -42,6 +42,7 @@ __export(multiRecordResource_exports, {
42
42
  module.exports = __toCommonJS(multiRecordResource_exports);
43
43
  var import_reactive = require("@formily/reactive");
44
44
  var import_lodash = __toESM(require("lodash"));
45
+ var import_dirtyAwareApiClient = require("../utils/dirtyAwareApiClient");
45
46
  var import_baseRecordResource = require("./baseRecordResource");
46
47
  const _MultiRecordResource = class _MultiRecordResource extends import_baseRecordResource.BaseRecordResource {
47
48
  _data = import_reactive.observable.ref([]);
@@ -130,7 +131,10 @@ const _MultiRecordResource = class _MultiRecordResource extends import_baseRecor
130
131
  }
131
132
  async create(data, options) {
132
133
  const config = this.mergeRequestConfig({ data }, this.createActionOptions, options);
133
- const res = await this.runAction("create", config);
134
+ const res = await this.runAction("create", {
135
+ ...config,
136
+ [import_dirtyAwareApiClient.SKIP_DATA_SOURCE_DIRTY]: true
137
+ });
134
138
  this.markDataSourceDirty();
135
139
  this.emit("saved", data);
136
140
  if ((options == null ? void 0 : options.refresh) !== false) {
@@ -161,7 +165,10 @@ const _MultiRecordResource = class _MultiRecordResource extends import_baseRecor
161
165
  this.updateActionOptions,
162
166
  options
163
167
  );
164
- await this.runAction("update", config);
168
+ await this.runAction("update", {
169
+ ...config,
170
+ [import_dirtyAwareApiClient.SKIP_DATA_SOURCE_DIRTY]: true
171
+ });
165
172
  this.markDataSourceDirty();
166
173
  this.emit("saved", data);
167
174
  await this.refresh();
@@ -182,7 +189,10 @@ const _MultiRecordResource = class _MultiRecordResource extends import_baseRecor
182
189
  },
183
190
  options
184
191
  );
185
- await this.runAction("destroy", config);
192
+ await this.runAction("destroy", {
193
+ ...config,
194
+ [import_dirtyAwareApiClient.SKIP_DATA_SOURCE_DIRTY]: true
195
+ });
186
196
  this.markDataSourceDirty();
187
197
  const currentPage = this.getPage();
188
198
  const lastPage = Math.ceil((this.getCount() - import_lodash.default.castArray(filterByTk).length) / this.getPageSize());
@@ -41,6 +41,7 @@ __export(singleRecordResource_exports, {
41
41
  });
42
42
  module.exports = __toCommonJS(singleRecordResource_exports);
43
43
  var import_lodash = __toESM(require("lodash"));
44
+ var import_dirtyAwareApiClient = require("../utils/dirtyAwareApiClient");
44
45
  var import_baseRecordResource = require("./baseRecordResource");
45
46
  const _SingleRecordResource = class _SingleRecordResource extends import_baseRecordResource.BaseRecordResource {
46
47
  isNewRecord = false;
@@ -68,7 +69,8 @@ const _SingleRecordResource = class _SingleRecordResource extends import_baseRec
68
69
  }
69
70
  const res = await this.runAction(actionName, {
70
71
  ...config,
71
- data: result
72
+ data: result,
73
+ [import_dirtyAwareApiClient.SKIP_DATA_SOURCE_DIRTY]: true
72
74
  });
73
75
  this.markDataSourceDirty();
74
76
  this.emit("saved", data);
@@ -86,7 +88,10 @@ const _SingleRecordResource = class _SingleRecordResource extends import_baseRec
86
88
  },
87
89
  options
88
90
  );
89
- await this.runAction("destroy", config);
91
+ await this.runAction("destroy", {
92
+ ...config,
93
+ [import_dirtyAwareApiClient.SKIP_DATA_SOURCE_DIRTY]: true
94
+ });
90
95
  this.markDataSourceDirty();
91
96
  this.setData(null);
92
97
  }
@@ -71,18 +71,25 @@ function createJSRunnerWithVersion(options) {
71
71
  doc = {};
72
72
  }
73
73
  const deprecatedCtx = (0, import_flowContext.createRunJSDeprecationProxy)(runCtx, { doc });
74
- const globals = { ctx: deprecatedCtx, ...(options == null ? void 0 : options.globals) || {} };
75
- if (modelClass === "JSFieldModel" || modelClass === "JSBlockModel") {
76
- if (typeof window !== "undefined") globals.window = window;
77
- if (typeof document !== "undefined") globals.document = document;
74
+ const browserGlobals = {};
75
+ if (typeof window !== "undefined") {
76
+ browserGlobals.window = window;
77
+ if (typeof navigator !== "undefined") {
78
+ browserGlobals.navigator = navigator;
79
+ }
78
80
  }
81
+ if (typeof document !== "undefined") {
82
+ browserGlobals.document = document;
83
+ }
84
+ const globals = { ctx: deprecatedCtx, ...browserGlobals, ...(options == null ? void 0 : options.globals) || {} };
79
85
  const { timeoutMs } = options || {};
80
86
  return new import_JSRunner.JSRunner({ globals, timeoutMs });
81
87
  }
82
88
  __name(createJSRunnerWithVersion, "createJSRunnerWithVersion");
83
89
  function getRunJSScenesForModel(modelClass, version = "v1") {
84
90
  const meta = import_registry.RunJSContextRegistry.getMeta(version, modelClass);
85
- return Array.isArray(meta == null ? void 0 : meta.scenes) ? [...meta.scenes] : [];
91
+ const scenes = meta == null ? void 0 : meta.scenes;
92
+ return Array.isArray(scenes) ? [...scenes] : [];
86
93
  }
87
94
  __name(getRunJSScenesForModel, "getRunJSScenesForModel");
88
95
  function getRunJSScenesForContext(ctx, { version = "v1" } = {}) {
package/lib/types.d.ts CHANGED
@@ -500,6 +500,18 @@ export interface ToolbarItemConfig {
500
500
  /** 排序权重,数字越小越靠右(先添加的在右边) */
501
501
  sort?: number;
502
502
  }
503
+ export interface DynamicFlowSource {
504
+ key: string;
505
+ label: React.ReactNode;
506
+ model: FlowModel;
507
+ sort?: number;
508
+ }
509
+ export interface DynamicFlowSourceProvider {
510
+ key: string;
511
+ sort?: number;
512
+ visible?: (model: FlowModel) => boolean;
513
+ getSources: (model: FlowModel) => DynamicFlowSource[] | Promise<DynamicFlowSource[]>;
514
+ }
503
515
  export interface ApplyFlowCacheEntry {
504
516
  status: 'pending' | 'resolved' | 'rejected';
505
517
  promise: Promise<any>;
@@ -0,0 +1,20 @@
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 { FlowEngine } from '../flowEngine';
10
+ type MarkDataSourceDirtyOptions = {
11
+ engine?: FlowEngine;
12
+ dataSourceKey?: unknown;
13
+ resourceName?: unknown;
14
+ includePreviousEngines?: boolean;
15
+ };
16
+ export declare function getHeaderValue(headers: unknown, name: string): unknown;
17
+ export declare function getDataSourceKeyFromHeaders(headers: unknown): string;
18
+ export declare function getAffectedResourceNames(resourceName: unknown): string[];
19
+ export declare function markDataSourceDirty(options: MarkDataSourceDirtyOptions): string[];
20
+ export {};
@@ -0,0 +1,139 @@
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
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
15
+ var __export = (target, all) => {
16
+ for (var name in all)
17
+ __defProp(target, name, { get: all[name], enumerable: true });
18
+ };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (let key of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key) && key !== except)
23
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
24
+ }
25
+ return to;
26
+ };
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var dataSourceDirty_exports = {};
29
+ __export(dataSourceDirty_exports, {
30
+ getAffectedResourceNames: () => getAffectedResourceNames,
31
+ getDataSourceKeyFromHeaders: () => getDataSourceKeyFromHeaders,
32
+ getHeaderValue: () => getHeaderValue,
33
+ markDataSourceDirty: () => markDataSourceDirty
34
+ });
35
+ module.exports = __toCommonJS(dataSourceDirty_exports);
36
+ var import_viewEvents = require("../views/viewEvents");
37
+ function getHeaderValue(headers, name) {
38
+ if (!headers || typeof headers !== "object") {
39
+ return void 0;
40
+ }
41
+ const maybeHeaders = headers;
42
+ if (typeof maybeHeaders.get === "function") {
43
+ const value = maybeHeaders.get(name);
44
+ if (value != null && value !== "") {
45
+ return value;
46
+ }
47
+ }
48
+ const lowerName = name.toLowerCase();
49
+ for (const [key, value] of Object.entries(headers)) {
50
+ if (key.toLowerCase() === lowerName) {
51
+ return value;
52
+ }
53
+ }
54
+ return void 0;
55
+ }
56
+ __name(getHeaderValue, "getHeaderValue");
57
+ function getDataSourceKeyFromHeaders(headers) {
58
+ const value = getHeaderValue(headers, "x-data-source");
59
+ if (Array.isArray(value)) {
60
+ return String(value[0] || "main");
61
+ }
62
+ return value == null || value === "" ? "main" : String(value);
63
+ }
64
+ __name(getDataSourceKeyFromHeaders, "getDataSourceKeyFromHeaders");
65
+ function getAffectedResourceNames(resourceName) {
66
+ const name = String(resourceName || "").trim();
67
+ if (!name) {
68
+ return [];
69
+ }
70
+ const names = /* @__PURE__ */ new Set([name]);
71
+ if (name.includes(".")) {
72
+ names.add(name.split(".")[0]);
73
+ }
74
+ return Array.from(names);
75
+ }
76
+ __name(getAffectedResourceNames, "getAffectedResourceNames");
77
+ function getDirtyTargetEngines(engine, includePreviousEngines) {
78
+ if (!includePreviousEngines) {
79
+ return [engine];
80
+ }
81
+ const engines = [];
82
+ const seen = /* @__PURE__ */ new Set();
83
+ let current = engine;
84
+ let guard = 0;
85
+ while (current && guard++ < 50) {
86
+ if (!seen.has(current)) {
87
+ engines.push(current);
88
+ seen.add(current);
89
+ }
90
+ current = current.previousEngine;
91
+ }
92
+ return engines;
93
+ }
94
+ __name(getDirtyTargetEngines, "getDirtyTargetEngines");
95
+ function markDataSourceDirty(options) {
96
+ var _a, _b, _c, _d;
97
+ const { engine, resourceName, includePreviousEngines } = options;
98
+ if (!(engine == null ? void 0 : engine.markDataSourceDirty)) {
99
+ return [];
100
+ }
101
+ const resourceNames = getAffectedResourceNames(resourceName);
102
+ if (!resourceNames.length) {
103
+ return [];
104
+ }
105
+ const dataSourceKey = String(options.dataSourceKey || "main");
106
+ const targetEngines = getDirtyTargetEngines(engine, includePreviousEngines);
107
+ const beforeVersions = /* @__PURE__ */ new Map();
108
+ for (const targetEngine of targetEngines) {
109
+ const versions = /* @__PURE__ */ new Map();
110
+ beforeVersions.set(targetEngine, versions);
111
+ for (const name of resourceNames) {
112
+ versions.set(name, ((_a = targetEngine.getDataSourceDirtyVersion) == null ? void 0 : _a.call(targetEngine, dataSourceKey, name)) || 0);
113
+ }
114
+ }
115
+ for (const targetEngine of targetEngines) {
116
+ const versions = beforeVersions.get(targetEngine);
117
+ for (const name of resourceNames) {
118
+ const before = (versions == null ? void 0 : versions.get(name)) || 0;
119
+ const current = ((_b = targetEngine.getDataSourceDirtyVersion) == null ? void 0 : _b.call(targetEngine, dataSourceKey, name)) || 0;
120
+ if (current !== before) {
121
+ continue;
122
+ }
123
+ targetEngine.markDataSourceDirty(dataSourceKey, name);
124
+ }
125
+ }
126
+ (_d = (_c = engine.emitter) == null ? void 0 : _c.emit) == null ? void 0 : _d.call(_c, import_viewEvents.DATA_SOURCE_DIRTY_EVENT, {
127
+ dataSourceKey,
128
+ resourceNames
129
+ });
130
+ return resourceNames;
131
+ }
132
+ __name(markDataSourceDirty, "markDataSourceDirty");
133
+ // Annotate the CommonJS export names for ESM import in node:
134
+ 0 && (module.exports = {
135
+ getAffectedResourceNames,
136
+ getDataSourceKeyFromHeaders,
137
+ getHeaderValue,
138
+ markDataSourceDirty
139
+ });
@@ -0,0 +1,11 @@
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 declare const SKIP_DATA_SOURCE_DIRTY = "__nocobaseSkipDataSourceDirty";
11
+ export declare function getDirtyAwareApiClient(value: unknown, context: FlowContext): unknown;