@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
@@ -57,7 +57,6 @@ __export(flowContext_exports, {
57
57
  module.exports = __toCommonJS(flowContext_exports);
58
58
  var import_reactive = require("@formily/reactive");
59
59
  var antd = __toESM(require("antd"));
60
- var antdIcons = __toESM(require("@ant-design/icons"));
61
60
  var import_lodash = __toESM(require("lodash"));
62
61
  var import_qs = __toESM(require("qs"));
63
62
  var import_react = __toESM(require("react"));
@@ -74,9 +73,12 @@ var import_utils = require("./utils");
74
73
  var import_exceptions = require("./utils/exceptions");
75
74
  var import_params_resolvers = require("./utils/params-resolvers");
76
75
  var import_serverContextParams = require("./utils/serverContextParams");
76
+ var import_variablesParams = require("./utils/variablesParams");
77
77
  var import_registry = require("./runjs-context/registry");
78
78
  var import_createEphemeralContext = require("./utils/createEphemeralContext");
79
79
  var import_dayjs = __toESM(require("dayjs"));
80
+ var import_runjsLibs = require("./runjsLibs");
81
+ var import_runjsModuleLoader = require("./utils/runjsModuleLoader");
80
82
  var _proxy, _FlowContext_instances, createChildNodes_fn, findMetaByPath_fn, findMetaInDelegatesDeep_fn, findMetaInProperty_fn, resolvePathInMeta_fn, resolvePathInMetaAsync_fn, buildParentTitles_fn, toTreeNode_fn;
81
83
  function isRecordRefLike(val) {
82
84
  return !!(val && typeof val === "object" && "collection" in val && "filterByTk" in val);
@@ -96,6 +98,50 @@ function filterBuilderOutputByPaths(built, neededPaths) {
96
98
  return void 0;
97
99
  }
98
100
  __name(filterBuilderOutputByPaths, "filterBuilderOutputByPaths");
101
+ function topLevelOf(subPath) {
102
+ if (!subPath) return void 0;
103
+ const m = String(subPath).match(/^([^.[]+)/);
104
+ return m == null ? void 0 : m[1];
105
+ }
106
+ __name(topLevelOf, "topLevelOf");
107
+ function inferSelectsFromUsage(paths = []) {
108
+ if (!Array.isArray(paths) || paths.length === 0) {
109
+ return { generatedAppends: void 0, generatedFields: void 0 };
110
+ }
111
+ const appendSet = /* @__PURE__ */ new Set();
112
+ const fieldSet = /* @__PURE__ */ new Set();
113
+ const normalizePath = /* @__PURE__ */ __name((raw) => {
114
+ if (!raw) return "";
115
+ let s = String(raw);
116
+ s = s.replace(/\[(?:\d+)\]/g, "");
117
+ s = s.replace(/\[(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)')\]/g, (_m, g1, g2) => `.${g1 || g2}`);
118
+ s = s.replace(/\.\.+/g, ".");
119
+ s = s.replace(/^\./, "").replace(/\.$/, "");
120
+ return s;
121
+ }, "normalizePath");
122
+ for (let path of paths) {
123
+ if (!path) continue;
124
+ while (/^\[(\d+)\](\.|$)/.test(path)) {
125
+ path = path.replace(/^\[(\d+)\]\.?/, "");
126
+ }
127
+ const norm = normalizePath(path);
128
+ if (!norm) continue;
129
+ const segments = norm.split(".").filter(Boolean);
130
+ if (segments.length === 0) continue;
131
+ if (segments.length === 1) {
132
+ fieldSet.add(segments[0]);
133
+ continue;
134
+ }
135
+ for (let i = 0; i < segments.length - 1; i++) {
136
+ appendSet.add(segments.slice(0, i + 1).join("."));
137
+ }
138
+ fieldSet.add(segments.join("."));
139
+ }
140
+ const generatedAppends = appendSet.size ? Array.from(appendSet) : void 0;
141
+ const generatedFields = fieldSet.size ? Array.from(fieldSet) : void 0;
142
+ return { generatedAppends, generatedFields };
143
+ }
144
+ __name(inferSelectsFromUsage, "inferSelectsFromUsage");
99
145
  const _FlowContext = class _FlowContext {
100
146
  constructor() {
101
147
  __privateAdd(this, _FlowContext_instances);
@@ -607,6 +653,7 @@ toTreeNode_fn = /* @__PURE__ */ __name(function(name, metaOrFactory, paths = [na
607
653
  type: "object",
608
654
  // 初始类型
609
655
  interface: void 0,
656
+ options: void 0,
610
657
  uiSchema: void 0,
611
658
  paths,
612
659
  parentTitles: parentTitles.length > 0 ? parentTitles : void 0,
@@ -635,6 +682,7 @@ toTreeNode_fn = /* @__PURE__ */ __name(function(name, metaOrFactory, paths = [na
635
682
  node.title = finalTitle;
636
683
  node.type = meta == null ? void 0 : meta.type;
637
684
  node.interface = meta == null ? void 0 : meta.interface;
685
+ node.options = meta == null ? void 0 : meta.options;
638
686
  node.uiSchema = meta == null ? void 0 : meta.uiSchema;
639
687
  if (!(meta == null ? void 0 : meta.properties)) return [];
640
688
  const childNodes = __privateMethod(this, _FlowContext_instances, createChildNodes_fn).call(this, meta.properties, paths, [...parentTitles, finalTitle], meta);
@@ -655,6 +703,7 @@ toTreeNode_fn = /* @__PURE__ */ __name(function(name, metaOrFactory, paths = [na
655
703
  title: nodeTitle,
656
704
  type: metaOrFactory.type,
657
705
  interface: metaOrFactory.interface,
706
+ options: metaOrFactory.options,
658
707
  uiSchema: metaOrFactory.uiSchema,
659
708
  paths,
660
709
  parentTitles: parentTitles.length > 0 ? parentTitles : void 0,
@@ -670,6 +719,23 @@ toTreeNode_fn = /* @__PURE__ */ __name(function(name, metaOrFactory, paths = [na
670
719
  __name(_FlowContext, "FlowContext");
671
720
  let FlowContext = _FlowContext;
672
721
  const _BaseFlowEngineContext = class _BaseFlowEngineContext extends FlowContext {
722
+ constructor() {
723
+ super();
724
+ this.defineMethod(
725
+ "runjs",
726
+ async function(code, variables, options) {
727
+ const { preprocessTemplates, ...runnerOptions } = options || {};
728
+ const mergedGlobals = { ...(runnerOptions == null ? void 0 : runnerOptions.globals) || {}, ...variables || {} };
729
+ const runner = await this.createJSRunner({
730
+ ...runnerOptions || {},
731
+ globals: mergedGlobals
732
+ });
733
+ const shouldPreprocessTemplates = preprocessTemplates !== false;
734
+ const jsCode = await (0, import_utils.prepareRunJsCode)(String(code ?? ""), { preprocessTemplates: shouldPreprocessTemplates });
735
+ return runner.run(jsCode);
736
+ }
737
+ );
738
+ }
673
739
  };
674
740
  __name(_BaseFlowEngineContext, "BaseFlowEngineContext");
675
741
  let BaseFlowEngineContext = _BaseFlowEngineContext;
@@ -706,14 +772,6 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
706
772
  this.defineMethod("t", (keyOrTemplate, options) => {
707
773
  return i18n.translate(keyOrTemplate, options);
708
774
  });
709
- this.defineMethod("runjs", async (code, variables, options) => {
710
- const mergedGlobals = { ...(options == null ? void 0 : options.globals) || {}, ...variables || {} };
711
- const runner = await this.createJSRunner({
712
- ...options || {},
713
- globals: mergedGlobals
714
- });
715
- return runner.run(code);
716
- });
717
775
  this.defineMethod("renderJson", function(template) {
718
776
  return this.resolveJsonTemplate(template);
719
777
  });
@@ -745,6 +803,21 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
745
803
  const needServer = Object.keys(serverVarPaths).length > 0;
746
804
  let serverResolved = template;
747
805
  if (needServer) {
806
+ const inferRecordRefWithMeta = /* @__PURE__ */ __name((ctx) => {
807
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
808
+ const ref = (0, import_variablesParams.inferRecordRef)(ctx);
809
+ if (ref) return ref;
810
+ try {
811
+ const tk = (_b2 = (_a2 = ctx == null ? void 0 : ctx.resource) == null ? void 0 : _a2.getMeta) == null ? void 0 : _b2.call(_a2, "currentFilterByTk");
812
+ if (typeof tk === "undefined" || tk === null) return void 0;
813
+ const collection = ((_c = ctx == null ? void 0 : ctx.collection) == null ? void 0 : _c.name) || ((_j = (_i = (_h = (_g = (_f = (_e = (_d = ctx == null ? void 0 : ctx.resource) == null ? void 0 : _d.getResourceName) == null ? void 0 : _e.call(_d)) == null ? void 0 : _f.split) == null ? void 0 : _g.call(_f, ".")) == null ? void 0 : _h.slice) == null ? void 0 : _i.call(_h, -1)) == null ? void 0 : _j[0]);
814
+ if (!collection) return void 0;
815
+ const dataSourceKey = ((_k = ctx == null ? void 0 : ctx.collection) == null ? void 0 : _k.dataSourceKey) || ((_m = (_l = ctx == null ? void 0 : ctx.resource) == null ? void 0 : _l.getDataSourceKey) == null ? void 0 : _m.call(_l));
816
+ return { collection, dataSourceKey, filterByTk: tk };
817
+ } catch (_2) {
818
+ return void 0;
819
+ }
820
+ }, "inferRecordRefWithMeta");
748
821
  const collectFromMeta = /* @__PURE__ */ __name(async () => {
749
822
  var _a2;
750
823
  const out = {};
@@ -780,6 +853,43 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
780
853
  }, "collectFromMeta");
781
854
  const inputFromMeta = await collectFromMeta();
782
855
  const autoInput = { ...inputFromMeta };
856
+ try {
857
+ const varName = "formValues";
858
+ const neededPaths = serverVarPaths[varName] || [];
859
+ if (neededPaths.length) {
860
+ const requiredTop = /* @__PURE__ */ new Set();
861
+ for (const p of neededPaths) {
862
+ const top = topLevelOf(p);
863
+ if (top) requiredTop.add(top);
864
+ }
865
+ const metaOut = inputFromMeta == null ? void 0 : inputFromMeta[varName];
866
+ const builtTop = /* @__PURE__ */ new Set();
867
+ if (metaOut && typeof metaOut === "object" && !Array.isArray(metaOut) && !isRecordRefLike(metaOut)) {
868
+ Object.keys(metaOut).forEach((k) => builtTop.add(k));
869
+ }
870
+ const missing = [...requiredTop].filter((k) => !builtTop.has(k));
871
+ if (missing.length) {
872
+ const ref = inferRecordRefWithMeta(this);
873
+ if (ref) {
874
+ const { generatedFields, generatedAppends } = inferSelectsFromUsage(neededPaths);
875
+ const recordRef = {
876
+ ...ref,
877
+ fields: generatedFields,
878
+ appends: generatedAppends
879
+ };
880
+ const existing = autoInput[varName];
881
+ if (existing && typeof existing === "object" && !Array.isArray(existing) && !isRecordRefLike(existing)) {
882
+ for (const [k, v] of Object.entries(existing)) {
883
+ autoInput[`${varName}.${k}`] = v;
884
+ }
885
+ delete autoInput[varName];
886
+ }
887
+ autoInput[varName] = recordRef;
888
+ }
889
+ }
890
+ }
891
+ } catch (_2) {
892
+ }
783
893
  const autoContextParams = Object.keys(autoInput).length ? (0, import_serverContextParams.buildServerContextParams)(this, autoInput) : void 0;
784
894
  if (!autoContextParams) {
785
895
  const keys = Object.keys(serverVarPaths);
@@ -894,7 +1004,8 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
894
1004
  user: this.user
895
1005
  }), "get")
896
1006
  });
897
- this.defineMethod("loadCSS", async (url) => {
1007
+ this.defineMethod("loadCSS", async (href) => {
1008
+ const url = (0, import_utils.resolveModuleUrl)(href);
898
1009
  return new Promise((resolve, reject) => {
899
1010
  const existingLink = document.querySelector(`link[href="${url}"]`);
900
1011
  if (existingLink) {
@@ -910,51 +1021,14 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
910
1021
  });
911
1022
  });
912
1023
  this.defineMethod("requireAsync", async (url) => {
913
- return new Promise((resolve, reject) => {
914
- if (!this.requirejs) {
915
- reject(new Error("requirejs is not available"));
916
- return;
917
- }
918
- this.requirejs(
919
- [url],
920
- (...args) => {
921
- resolve(args[0]);
922
- },
923
- reject
924
- );
925
- });
1024
+ const u = (0, import_utils.resolveModuleUrl)(url, { raw: true });
1025
+ return await (0, import_runjsModuleLoader.runjsRequireAsync)(this.requirejs, u);
926
1026
  });
927
- this.defineMethod("importAsync", async (url) => {
928
- if (!url || typeof url !== "string") {
929
- throw new Error("invalid url");
1027
+ this.defineMethod("importAsync", async function(url) {
1028
+ if ((0, import_utils.isCssFile)(url)) {
1029
+ return this.loadCSS(url);
930
1030
  }
931
- const u = url.trim();
932
- const g = globalThis;
933
- g.__nocobaseImportAsyncCache = g.__nocobaseImportAsyncCache || /* @__PURE__ */ new Map();
934
- const cache = g.__nocobaseImportAsyncCache;
935
- if (cache.has(u)) return cache.get(u);
936
- const nativeImport = /* @__PURE__ */ __name(() => import(
937
- /* @vite-ignore */
938
- /* webpackIgnore: true */
939
- u
940
- ), "nativeImport");
941
- const evalImport = /* @__PURE__ */ __name(() => {
942
- const importer = (0, eval)("u => import(u)");
943
- return importer(u);
944
- }, "evalImport");
945
- const p = (async () => {
946
- try {
947
- return await nativeImport();
948
- } catch (err) {
949
- try {
950
- return await evalImport();
951
- } catch (err2) {
952
- throw err2 || err;
953
- }
954
- }
955
- })();
956
- cache.set(u, p);
957
- return p;
1031
+ return await (0, import_runjsModuleLoader.runjsImportModule)(this, url, { importer: import_runjsModuleLoader.runjsImportAsync });
958
1032
  });
959
1033
  this.defineMethod("createJSRunner", async function(options) {
960
1034
  try {
@@ -964,11 +1038,8 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
964
1038
  }
965
1039
  const version = (options == null ? void 0 : options.version) || "v1";
966
1040
  const modelClass = (0, import_registry.getModelClassName)(this);
967
- const Ctor = import_registry.RunJSContextRegistry.resolve(version, modelClass) || import_registry.RunJSContextRegistry.resolve(version, "*") || FlowRunJSContext;
968
- let runCtx;
969
- if (Ctor) {
970
- runCtx = new Ctor(this);
971
- }
1041
+ const Ctor = import_registry.RunJSContextRegistry.resolve(version, modelClass) || FlowRunJSContext;
1042
+ const runCtx = new Ctor(this);
972
1043
  const globals = { ctx: runCtx, ...(options == null ? void 0 : options.globals) || {} };
973
1044
  const { timeoutMs } = options || {};
974
1045
  return new import_JSRunner.JSRunner({ globals, timeoutMs });
@@ -1045,13 +1116,6 @@ const _FlowModelContext = class _FlowModelContext extends BaseFlowModelContext {
1045
1116
  this.defineMethod("onRefReady", (ref, cb, timeout) => {
1046
1117
  this.engine.reactView.onRefReady(ref, cb, timeout);
1047
1118
  });
1048
- this.defineMethod("runjs", async (code, variables, options) => {
1049
- const runner = await this.createJSRunner({
1050
- globals: variables,
1051
- version: options == null ? void 0 : options.version
1052
- });
1053
- return runner.run(code);
1054
- });
1055
1119
  this.defineProperty("model", {
1056
1120
  value: model
1057
1121
  });
@@ -1183,13 +1247,6 @@ const _FlowForkModelContext = class _FlowForkModelContext extends BaseFlowModelC
1183
1247
  return stableRef;
1184
1248
  }, "get")
1185
1249
  });
1186
- this.defineMethod("runjs", async (code, variables, options) => {
1187
- const runner = await this.createJSRunner({
1188
- globals: variables,
1189
- version: options == null ? void 0 : options.version
1190
- });
1191
- return runner.run(code);
1192
- });
1193
1250
  }
1194
1251
  };
1195
1252
  __name(_FlowForkModelContext, "FlowForkModelContext");
@@ -1234,13 +1291,6 @@ const _FlowRuntimeContext = class _FlowRuntimeContext extends BaseFlowModelConte
1234
1291
  this.defineMethod("onRefReady", (ref, cb, timeout) => {
1235
1292
  this.engine.reactView.onRefReady(ref, cb, timeout);
1236
1293
  });
1237
- this.defineMethod("runjs", async (code, variables, options) => {
1238
- const runner = await this.createJSRunner({
1239
- globals: variables,
1240
- version: options == null ? void 0 : options.version
1241
- });
1242
- return runner.run(code);
1243
- });
1244
1294
  }
1245
1295
  stepResults = {};
1246
1296
  _getOwnProperty(key) {
@@ -1307,15 +1357,9 @@ const _FlowRunJSContext = class _FlowRunJSContext extends FlowContext {
1307
1357
  return this.engine.reactView.createRoot(realContainer, options);
1308
1358
  }, "createRoot")
1309
1359
  };
1360
+ ReactDOMShim.__nbRunjsInternalShim = true;
1310
1361
  this.defineProperty("ReactDOM", { value: ReactDOMShim });
1311
- const libs = Object.freeze({
1312
- React: import_react.default,
1313
- ReactDOM: ReactDOMShim,
1314
- antd,
1315
- dayjs: import_dayjs.default,
1316
- antdIcons
1317
- });
1318
- this.defineProperty("libs", { value: libs });
1362
+ (0, import_runjsLibs.setupRunJSLibs)(this);
1319
1363
  this.defineMethod(
1320
1364
  "render",
1321
1365
  function(vnode, container) {
@@ -1325,39 +1369,64 @@ const _FlowRunJSContext = class _FlowRunJSContext extends FlowContext {
1325
1369
  const globalRef = globalThis;
1326
1370
  globalRef.__nbRunjsRoots = globalRef.__nbRunjsRoots || /* @__PURE__ */ new WeakMap();
1327
1371
  const rootMap = globalRef.__nbRunjsRoots;
1328
- if (typeof vnode === "string") {
1329
- const existingRoot = rootMap.get(containerEl);
1330
- if (existingRoot && typeof existingRoot.unmount === "function") {
1372
+ const disposeEntry = /* @__PURE__ */ __name((entry2) => {
1373
+ if (!entry2) return;
1374
+ if (entry2.disposeTheme && typeof entry2.disposeTheme === "function") {
1331
1375
  try {
1332
- existingRoot.unmount();
1333
- } finally {
1334
- rootMap.delete(containerEl);
1376
+ entry2.disposeTheme();
1377
+ } catch (_2) {
1378
+ }
1379
+ entry2.disposeTheme = void 0;
1380
+ }
1381
+ const root = entry2.root || entry2;
1382
+ if (root && typeof root.unmount === "function") {
1383
+ try {
1384
+ root.unmount();
1385
+ } catch (_2) {
1335
1386
  }
1336
1387
  }
1388
+ }, "disposeEntry");
1389
+ const unmountContainerRoot = /* @__PURE__ */ __name(() => {
1390
+ const existing = rootMap.get(containerEl);
1391
+ if (existing) {
1392
+ disposeEntry(existing);
1393
+ rootMap.delete(containerEl);
1394
+ }
1395
+ }, "unmountContainerRoot");
1396
+ if (typeof vnode === "string") {
1397
+ unmountContainerRoot();
1337
1398
  const proxy = new import_ElementProxy.ElementProxy(containerEl);
1338
1399
  proxy.innerHTML = String(vnode ?? "");
1339
1400
  return null;
1340
1401
  }
1341
1402
  if (vnode && vnode.nodeType && (vnode.nodeType === 1 || vnode.nodeType === 3 || vnode.nodeType === 11)) {
1342
- const existingRoot = rootMap.get(containerEl);
1343
- if (existingRoot && typeof existingRoot.unmount === "function") {
1344
- try {
1345
- existingRoot.unmount();
1346
- } finally {
1347
- rootMap.delete(containerEl);
1348
- }
1349
- }
1403
+ unmountContainerRoot();
1350
1404
  while (containerEl.firstChild) containerEl.removeChild(containerEl.firstChild);
1351
1405
  containerEl.appendChild(vnode);
1352
1406
  return null;
1353
1407
  }
1354
- let root = rootMap.get(containerEl);
1355
- if (!root) {
1356
- root = this.ReactDOM.createRoot(containerEl);
1357
- rootMap.set(containerEl, root);
1408
+ const rendererKey = this.ReactDOM;
1409
+ const ownerKey = this;
1410
+ let entry = rootMap.get(containerEl);
1411
+ if (!entry || entry.rendererKey !== rendererKey || entry.ownerKey !== ownerKey) {
1412
+ if (entry) {
1413
+ disposeEntry(entry);
1414
+ rootMap.delete(containerEl);
1415
+ }
1416
+ const root = this.ReactDOM.createRoot(containerEl);
1417
+ entry = { rendererKey, ownerKey, root, disposeTheme: void 0, lastVnode: void 0 };
1418
+ rootMap.set(containerEl, entry);
1358
1419
  }
1359
- root.render(vnode);
1360
- return root;
1420
+ return (0, import_runjsLibs.externalReactRender)({
1421
+ ctx: this,
1422
+ entry,
1423
+ vnode,
1424
+ containerEl,
1425
+ rootMap,
1426
+ unmountContainerRoot,
1427
+ internalReact: import_react.default,
1428
+ internalAntd: antd
1429
+ });
1361
1430
  }
1362
1431
  );
1363
1432
  }
@@ -84,6 +84,17 @@ export declare class FlowEngine {
84
84
  private _previousEngine?;
85
85
  private _nextEngine?;
86
86
  private _resources;
87
+ /**
88
+ * Data change registry used to coordinate "refresh on active" across view-scoped engines.
89
+ *
90
+ * Keyed by: dataSourceKey -> resourceName -> version.
91
+ * - mark: increments version
92
+ * - get: returns current version (default 0)
93
+ *
94
+ * NOTE: ViewScopedFlowEngine proxies delegate non-local fields/methods to parents, so this
95
+ * registry naturally lives on the root engine instance and is shared across the whole view stack.
96
+ */
97
+ private _dataSourceDirtyVersions;
87
98
  /**
88
99
  * 引擎事件总线(目前用于模型生命周期等事件)。
89
100
  * ViewScopedFlowEngine 持有自己的实例,实现作用域隔离。
@@ -116,6 +127,16 @@ export declare class FlowEngine {
116
127
  getScheduler(): ModelOperationScheduler;
117
128
  /** 释放并清理当前引擎本地调度器(若存在) */
118
129
  disposeScheduler(): void;
130
+ /**
131
+ * Mark a data source resource as "dirty" (changed).
132
+ * This is used by data blocks to decide whether to refresh when a view becomes active.
133
+ */
134
+ markDataSourceDirty(dataSourceKey: string, resourceName: string): number;
135
+ /**
136
+ * Get current dirty version for a data source resource.
137
+ * Returns 0 when no writes have been recorded.
138
+ */
139
+ getDataSourceDirtyVersion(dataSourceKey: string, resourceName: string): number;
119
140
  /** 在目标模型生命周期达成时执行操作(仅在 View 引擎本地存储计划) */
120
141
  scheduleModelOperation(fromModelOrUid: FlowModel | string, toUid: string, fn: (model: FlowModel) => Promise<void> | void, options?: ScheduleOptions): ScheduledCancel;
121
142
  /** 上一个引擎(根引擎为 undefined) */
package/lib/flowEngine.js CHANGED
@@ -120,6 +120,17 @@ const _FlowEngine = class _FlowEngine {
120
120
  __publicField(this, "_previousEngine");
121
121
  __publicField(this, "_nextEngine");
122
122
  __publicField(this, "_resources", /* @__PURE__ */ new Map());
123
+ /**
124
+ * Data change registry used to coordinate "refresh on active" across view-scoped engines.
125
+ *
126
+ * Keyed by: dataSourceKey -> resourceName -> version.
127
+ * - mark: increments version
128
+ * - get: returns current version (default 0)
129
+ *
130
+ * NOTE: ViewScopedFlowEngine proxies delegate non-local fields/methods to parents, so this
131
+ * registry naturally lives on the root engine instance and is shared across the whole view stack.
132
+ */
133
+ __publicField(this, "_dataSourceDirtyVersions", /* @__PURE__ */ new Map());
123
134
  /**
124
135
  * 引擎事件总线(目前用于模型生命周期等事件)。
125
136
  * ViewScopedFlowEngine 持有自己的实例,实现作用域隔离。
@@ -187,6 +198,33 @@ const _FlowEngine = class _FlowEngine {
187
198
  }
188
199
  }
189
200
  }
201
+ /**
202
+ * Mark a data source resource as "dirty" (changed).
203
+ * This is used by data blocks to decide whether to refresh when a view becomes active.
204
+ */
205
+ markDataSourceDirty(dataSourceKey, resourceName) {
206
+ const dsKey = String(dataSourceKey || "main");
207
+ const resName = String(resourceName || "");
208
+ if (!resName) return this.getDataSourceDirtyVersion(dsKey, resName);
209
+ const ds = this._dataSourceDirtyVersions.get(dsKey) || /* @__PURE__ */ new Map();
210
+ if (!this._dataSourceDirtyVersions.has(dsKey)) {
211
+ this._dataSourceDirtyVersions.set(dsKey, ds);
212
+ }
213
+ const next = (ds.get(resName) || 0) + 1;
214
+ ds.set(resName, next);
215
+ return next;
216
+ }
217
+ /**
218
+ * Get current dirty version for a data source resource.
219
+ * Returns 0 when no writes have been recorded.
220
+ */
221
+ getDataSourceDirtyVersion(dataSourceKey, resourceName) {
222
+ var _a;
223
+ const dsKey = String(dataSourceKey || "main");
224
+ const resName = String(resourceName || "");
225
+ if (!resName) return 0;
226
+ return ((_a = this._dataSourceDirtyVersions.get(dsKey)) == null ? void 0 : _a.get(resName)) || 0;
227
+ }
190
228
  /** 在目标模型生命周期达成时执行操作(仅在 View 引擎本地存储计划) */
191
229
  scheduleModelOperation(fromModelOrUid, toUid, fn, options) {
192
230
  return this.getScheduler().schedule(fromModelOrUid, toUid, fn, options);
@@ -63,6 +63,7 @@ var import__ = require(".");
63
63
  var import_useFlowSettingsContext = require("./hooks/useFlowSettingsContext");
64
64
  var import_utils = require("./utils");
65
65
  var import_useFlowStep = require("./hooks/useFlowStep");
66
+ var import_views = require("./views");
66
67
  var _forceEnabled, _emitter;
67
68
  const Panel = import_antd.Collapse.Panel;
68
69
  const _FlowSettings = class _FlowSettings {
@@ -536,12 +537,9 @@ const _FlowSettings = class _FlowSettings {
536
537
  };
537
538
  let modeProps = typeof resolvedUiMode === "object" && resolvedUiMode ? resolvedUiMode.props || {} : {};
538
539
  if (modeType === "embed") {
539
- const target = document.querySelector("#nocobase-embed-container");
540
+ const target = document.querySelector(`#${import_views.GLOBAL_EMBED_CONTAINER_ID}`);
540
541
  const onOpen = modeProps.onOpen;
541
542
  const onClose = modeProps.onClose;
542
- if (target) {
543
- target.innerHTML = "";
544
- }
545
543
  modeProps = {
546
544
  target,
547
545
  styles: {
@@ -551,15 +549,19 @@ const _FlowSettings = class _FlowSettings {
551
549
  },
552
550
  ...modeProps,
553
551
  onOpen() {
554
- target.style.width = modeProps.width || "33.3%";
555
- target.style.maxWidth = modeProps.maxWidth || "800px";
556
- target.style.minWidth = modeProps.minWidth || "0px";
552
+ if (target) {
553
+ target.style.width = modeProps.width || "33.3%";
554
+ target.style.maxWidth = modeProps.maxWidth || "800px";
555
+ target.style.minWidth = modeProps.minWidth || "0px";
556
+ }
557
557
  onOpen == null ? void 0 : onOpen();
558
558
  },
559
559
  onClose() {
560
- target.style.width = "auto";
561
- target.style.maxWidth = "none";
562
- target.style.minWidth = "auto";
560
+ if (target && target.dataset[import_views.EMBED_REPLACING_DATA_KEY] !== "1") {
561
+ target.style.width = "auto";
562
+ target.style.maxWidth = "none";
563
+ target.style.minWidth = "auto";
564
+ }
563
565
  onClose == null ? void 0 : onClose();
564
566
  }
565
567
  };
package/lib/index.d.ts CHANGED
@@ -9,6 +9,8 @@
9
9
  export * from './types';
10
10
  export * from './utils';
11
11
  export { compileRunJs } from './utils/jsxTransform';
12
+ export { registerRunJSLib } from './runjsLibs';
13
+ export type { RunJSLibCache, RunJSLibLoader } from './runjsLibs';
12
14
  export * from './resources';
13
15
  export * from './flowEngine';
14
16
  export * from './hooks';
@@ -27,6 +29,7 @@ export { RunJSContextRegistry, getModelClassName } from './runjs-context/registr
27
29
  export { setupRunJSContexts } from './runjs-context/setup';
28
30
  export { getSnippetBody, listSnippetsForContext } from './runjs-context/snippets';
29
31
  export * from './views';
32
+ export { DATA_SOURCE_DIRTY_EVENT, ENGINE_SCOPE_KEY, getEmitterViewActivatedVersion, VIEW_ACTIVATED_EVENT, VIEW_ACTIVATED_VERSION, VIEW_ENGINE_SCOPE, } from './views/viewEvents';
30
33
  export * from './FlowDefinition';
31
34
  export { createViewScopedEngine } from './ViewScopedFlowEngine';
32
35
  export { createBlockScopedEngine } from './BlockScopedFlowEngine';
package/lib/index.js CHANGED
@@ -27,23 +27,31 @@ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "defau
27
27
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
28
  var src_exports = {};
29
29
  __export(src_exports, {
30
+ DATA_SOURCE_DIRTY_EVENT: () => import_viewEvents.DATA_SOURCE_DIRTY_EVENT,
31
+ ENGINE_SCOPE_KEY: () => import_viewEvents.ENGINE_SCOPE_KEY,
30
32
  RunJSContextRegistry: () => import_registry.RunJSContextRegistry,
33
+ VIEW_ACTIVATED_EVENT: () => import_viewEvents.VIEW_ACTIVATED_EVENT,
34
+ VIEW_ACTIVATED_VERSION: () => import_viewEvents.VIEW_ACTIVATED_VERSION,
35
+ VIEW_ENGINE_SCOPE: () => import_viewEvents.VIEW_ENGINE_SCOPE,
31
36
  compileRunJs: () => import_jsxTransform.compileRunJs,
32
37
  createBlockScopedEngine: () => import_BlockScopedFlowEngine.createBlockScopedEngine,
33
38
  createJSRunnerWithVersion: () => import_helpers.createJSRunnerWithVersion,
34
39
  createViewScopedEngine: () => import_ViewScopedFlowEngine.createViewScopedEngine,
40
+ getEmitterViewActivatedVersion: () => import_viewEvents.getEmitterViewActivatedVersion,
35
41
  getModelClassName: () => import_registry.getModelClassName,
36
42
  getRunJSDocFor: () => import_helpers.getRunJSDocFor,
37
43
  getRunJSScenesForContext: () => import_helpers.getRunJSScenesForContext,
38
44
  getRunJSScenesForModel: () => import_helpers.getRunJSScenesForModel,
39
45
  getSnippetBody: () => import_snippets.getSnippetBody,
40
46
  listSnippetsForContext: () => import_snippets.listSnippetsForContext,
47
+ registerRunJSLib: () => import_runjsLibs.registerRunJSLib,
41
48
  setupRunJSContexts: () => import_setup.setupRunJSContexts
42
49
  });
43
50
  module.exports = __toCommonJS(src_exports);
44
51
  __reExport(src_exports, require("./types"), module.exports);
45
52
  __reExport(src_exports, require("./utils"), module.exports);
46
53
  var import_jsxTransform = require("./utils/jsxTransform");
54
+ var import_runjsLibs = require("./runjsLibs");
47
55
  __reExport(src_exports, require("./resources"), module.exports);
48
56
  __reExport(src_exports, require("./flowEngine"), module.exports);
49
57
  __reExport(src_exports, require("./hooks"), module.exports);
@@ -62,22 +70,30 @@ var import_registry = require("./runjs-context/registry");
62
70
  var import_setup = require("./runjs-context/setup");
63
71
  var import_snippets = require("./runjs-context/snippets");
64
72
  __reExport(src_exports, require("./views"), module.exports);
73
+ var import_viewEvents = require("./views/viewEvents");
65
74
  __reExport(src_exports, require("./FlowDefinition"), module.exports);
66
75
  var import_ViewScopedFlowEngine = require("./ViewScopedFlowEngine");
67
76
  var import_BlockScopedFlowEngine = require("./BlockScopedFlowEngine");
68
77
  // Annotate the CommonJS export names for ESM import in node:
69
78
  0 && (module.exports = {
79
+ DATA_SOURCE_DIRTY_EVENT,
80
+ ENGINE_SCOPE_KEY,
70
81
  RunJSContextRegistry,
82
+ VIEW_ACTIVATED_EVENT,
83
+ VIEW_ACTIVATED_VERSION,
84
+ VIEW_ENGINE_SCOPE,
71
85
  compileRunJs,
72
86
  createBlockScopedEngine,
73
87
  createJSRunnerWithVersion,
74
88
  createViewScopedEngine,
89
+ getEmitterViewActivatedVersion,
75
90
  getModelClassName,
76
91
  getRunJSDocFor,
77
92
  getRunJSScenesForContext,
78
93
  getRunJSScenesForModel,
79
94
  getSnippetBody,
80
95
  listSnippetsForContext,
96
+ registerRunJSLib,
81
97
  setupRunJSContexts,
82
98
  ...require("./types"),
83
99
  ...require("./utils"),
@@ -45,6 +45,7 @@ export declare class CollectionFieldModel<T extends DefaultStructure = DefaultSt
45
45
  }): BindingOptions | null;
46
46
  static bindModelToInterface(modelName: string, interfaceName: string | string[], options?: {
47
47
  isDefault?: boolean;
48
+ order?: number;
48
49
  defaultProps?: object | ((ctx: FlowEngineContext, fieldInstance: CollectionField) => object);
49
50
  when?: (ctx: FlowEngineContext, fieldInstance: CollectionField) => boolean;
50
51
  }): void;
@@ -182,7 +182,7 @@ const _CollectionFieldModel = class _CollectionFieldModel extends import_flowMod
182
182
  if (!this.bindings.has(interfaceName)) {
183
183
  return [];
184
184
  }
185
- const bindings = this.bindings.get(interfaceName);
185
+ const bindings = this.bindings.get(interfaceName).sort((a, b) => a.order - b.order);
186
186
  return bindings.filter(
187
187
  (binding) => ctx.engine.getModelClass(binding.modelName) && binding.when(ctx, collectionField)
188
188
  );
@@ -245,7 +245,8 @@ const _CollectionFieldModel = class _CollectionFieldModel extends import_flowMod
245
245
  modelName,
246
246
  isDefault: options.isDefault || false,
247
247
  defaultProps: options.defaultProps || null,
248
- when: options.when || defaultWhen
248
+ when: options.when || defaultWhen,
249
+ order: options.order
249
250
  });
250
251
  this.currentBindings.set(interfaceName, bindings);
251
252
  }