@nocobase/flow-engine 2.1.0-alpha.4 → 2.1.0-alpha.40

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 (194) hide show
  1. package/LICENSE +201 -661
  2. package/README.md +79 -10
  3. package/lib/JSRunner.d.ts +10 -1
  4. package/lib/JSRunner.js +50 -5
  5. package/lib/ViewScopedFlowEngine.js +5 -1
  6. package/lib/components/FieldModelRenderer.js +2 -2
  7. package/lib/components/FlowModelRenderer.d.ts +3 -1
  8. package/lib/components/FlowModelRenderer.js +12 -6
  9. package/lib/components/FormItem.d.ts +6 -0
  10. package/lib/components/FormItem.js +11 -3
  11. package/lib/components/MobilePopup.js +6 -5
  12. package/lib/components/dnd/gridDragPlanner.d.ts +59 -2
  13. package/lib/components/dnd/gridDragPlanner.js +613 -21
  14. package/lib/components/dnd/index.d.ts +31 -2
  15. package/lib/components/dnd/index.js +244 -23
  16. package/lib/components/settings/wrappers/component/SelectWithTitle.d.ts +2 -1
  17. package/lib/components/settings/wrappers/component/SelectWithTitle.js +14 -12
  18. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.d.ts +3 -0
  19. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +68 -10
  20. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +23 -43
  21. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +352 -295
  22. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +16 -2
  23. package/lib/components/settings/wrappers/contextual/useFloatToolbarPortal.d.ts +36 -0
  24. package/lib/components/settings/wrappers/contextual/useFloatToolbarPortal.js +274 -0
  25. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.d.ts +30 -0
  26. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.js +315 -0
  27. package/lib/components/subModel/AddSubModelButton.js +27 -1
  28. package/lib/components/subModel/LazyDropdown.js +96 -39
  29. package/lib/components/subModel/index.d.ts +1 -0
  30. package/lib/components/subModel/index.js +19 -0
  31. package/lib/components/subModel/utils.d.ts +1 -1
  32. package/lib/components/subModel/utils.js +9 -3
  33. package/lib/components/variables/VariableHybridInput.d.ts +27 -0
  34. package/lib/components/variables/VariableHybridInput.js +499 -0
  35. package/lib/components/variables/index.d.ts +2 -0
  36. package/lib/components/variables/index.js +3 -0
  37. package/lib/data-source/index.d.ts +75 -0
  38. package/lib/data-source/index.js +247 -5
  39. package/lib/executor/FlowExecutor.js +32 -9
  40. package/lib/flow-registry/DetachedFlowRegistry.d.ts +21 -0
  41. package/lib/flow-registry/DetachedFlowRegistry.js +80 -0
  42. package/lib/flow-registry/index.d.ts +1 -0
  43. package/lib/flow-registry/index.js +3 -1
  44. package/lib/flowContext.d.ts +3 -0
  45. package/lib/flowContext.js +43 -1
  46. package/lib/flowEngine.d.ts +151 -1
  47. package/lib/flowEngine.js +389 -15
  48. package/lib/flowI18n.js +2 -1
  49. package/lib/flowSettings.d.ts +14 -6
  50. package/lib/flowSettings.js +34 -6
  51. package/lib/index.d.ts +2 -0
  52. package/lib/index.js +7 -0
  53. package/lib/lazy-helper.d.ts +14 -0
  54. package/lib/lazy-helper.js +71 -0
  55. package/lib/locale/en-US.json +1 -0
  56. package/lib/locale/index.d.ts +2 -0
  57. package/lib/locale/zh-CN.json +1 -0
  58. package/lib/models/DisplayItemModel.d.ts +1 -1
  59. package/lib/models/EditableItemModel.d.ts +1 -1
  60. package/lib/models/FilterableItemModel.d.ts +1 -1
  61. package/lib/models/flowModel.d.ts +13 -10
  62. package/lib/models/flowModel.js +78 -18
  63. package/lib/provider.js +38 -23
  64. package/lib/reactive/observer.js +46 -16
  65. package/lib/runjs-context/registry.d.ts +1 -1
  66. package/lib/runjs-context/setup.js +20 -12
  67. package/lib/runjs-context/snippets/index.js +13 -2
  68. package/lib/runjs-context/snippets/scene/detail/set-field-style.snippet.d.ts +11 -0
  69. package/lib/runjs-context/snippets/scene/detail/set-field-style.snippet.js +50 -0
  70. package/lib/runjs-context/snippets/scene/table/set-cell-style.snippet.d.ts +11 -0
  71. package/lib/runjs-context/snippets/scene/table/set-cell-style.snippet.js +54 -0
  72. package/lib/scheduler/ModelOperationScheduler.d.ts +5 -1
  73. package/lib/scheduler/ModelOperationScheduler.js +3 -2
  74. package/lib/types.d.ts +50 -2
  75. package/lib/types.js +1 -0
  76. package/lib/utils/createCollectionContextMeta.js +6 -2
  77. package/lib/utils/index.d.ts +3 -2
  78. package/lib/utils/index.js +7 -0
  79. package/lib/utils/parsePathnameToViewParams.js +1 -1
  80. package/lib/utils/randomId.d.ts +39 -0
  81. package/lib/utils/randomId.js +45 -0
  82. package/lib/utils/runjsTemplateCompat.js +1 -1
  83. package/lib/utils/runjsValue.js +41 -11
  84. package/lib/utils/schema-utils.d.ts +7 -1
  85. package/lib/utils/schema-utils.js +19 -0
  86. package/lib/views/FlowView.d.ts +7 -1
  87. package/lib/views/FlowView.js +11 -1
  88. package/lib/views/PageComponent.js +8 -6
  89. package/lib/views/ViewNavigation.js +6 -2
  90. package/lib/views/runViewBeforeClose.d.ts +10 -0
  91. package/lib/views/runViewBeforeClose.js +45 -0
  92. package/lib/views/useDialog.d.ts +2 -1
  93. package/lib/views/useDialog.js +20 -3
  94. package/lib/views/useDrawer.d.ts +2 -1
  95. package/lib/views/useDrawer.js +20 -3
  96. package/lib/views/usePage.d.ts +5 -11
  97. package/lib/views/usePage.js +302 -144
  98. package/package.json +6 -5
  99. package/src/JSRunner.ts +68 -4
  100. package/src/ViewScopedFlowEngine.ts +4 -0
  101. package/src/__tests__/JSRunner.test.ts +27 -1
  102. package/src/__tests__/flow-engine.test.ts +166 -0
  103. package/src/__tests__/flowContext.test.ts +82 -1
  104. package/src/__tests__/flowEngine.modelLoaders.test.ts +245 -0
  105. package/src/__tests__/flowSettings.test.ts +94 -15
  106. package/src/__tests__/objectVariable.test.ts +24 -0
  107. package/src/__tests__/provider.test.tsx +24 -2
  108. package/src/__tests__/renderHiddenInConfig.test.tsx +6 -6
  109. package/src/__tests__/runjsContext.test.ts +16 -0
  110. package/src/__tests__/runjsContextRuntime.test.ts +2 -0
  111. package/src/__tests__/runjsPreprocessDefault.test.ts +23 -0
  112. package/src/__tests__/runjsSnippets.test.ts +21 -0
  113. package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
  114. package/src/components/FieldModelRenderer.tsx +2 -1
  115. package/src/components/FlowModelRenderer.tsx +18 -6
  116. package/src/components/FormItem.tsx +7 -1
  117. package/src/components/MobilePopup.tsx +4 -2
  118. package/src/components/__tests__/FlowModelRenderer.test.tsx +65 -2
  119. package/src/components/__tests__/FormItem.test.tsx +25 -0
  120. package/src/components/__tests__/dnd.test.ts +44 -0
  121. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +20 -10
  122. package/src/components/__tests__/gridDragPlanner.test.ts +558 -3
  123. package/src/components/dnd/__tests__/DndProvider.test.tsx +98 -0
  124. package/src/components/dnd/gridDragPlanner.ts +758 -19
  125. package/src/components/dnd/index.tsx +305 -28
  126. package/src/components/settings/wrappers/component/SelectWithTitle.tsx +21 -9
  127. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +88 -10
  128. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +487 -440
  129. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +18 -2
  130. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +189 -3
  131. package/src/components/settings/wrappers/contextual/__tests__/FlowsFloatContextMenu.test.tsx +778 -0
  132. package/src/components/settings/wrappers/contextual/useFloatToolbarPortal.ts +360 -0
  133. package/src/components/settings/wrappers/contextual/useFloatToolbarVisibility.ts +361 -0
  134. package/src/components/subModel/AddSubModelButton.tsx +32 -2
  135. package/src/components/subModel/LazyDropdown.tsx +107 -43
  136. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +319 -36
  137. package/src/components/subModel/__tests__/utils.test.ts +24 -0
  138. package/src/components/subModel/index.ts +1 -0
  139. package/src/components/subModel/utils.ts +7 -1
  140. package/src/components/variables/VariableHybridInput.tsx +531 -0
  141. package/src/components/variables/index.ts +2 -0
  142. package/src/data-source/__tests__/collection.test.ts +41 -2
  143. package/src/data-source/__tests__/index.test.ts +68 -1
  144. package/src/data-source/index.ts +304 -6
  145. package/src/executor/FlowExecutor.ts +35 -10
  146. package/src/executor/__tests__/flowExecutor.test.ts +57 -0
  147. package/src/flow-registry/DetachedFlowRegistry.ts +46 -0
  148. package/src/flow-registry/__tests__/detachedFlowRegistry.test.ts +47 -0
  149. package/src/flow-registry/index.ts +1 -0
  150. package/src/flowContext.ts +47 -3
  151. package/src/flowEngine.ts +445 -11
  152. package/src/flowI18n.ts +2 -1
  153. package/src/flowSettings.ts +40 -6
  154. package/src/index.ts +2 -0
  155. package/src/lazy-helper.tsx +57 -0
  156. package/src/locale/en-US.json +1 -0
  157. package/src/locale/zh-CN.json +1 -0
  158. package/src/models/DisplayItemModel.tsx +1 -1
  159. package/src/models/EditableItemModel.tsx +1 -1
  160. package/src/models/FilterableItemModel.tsx +1 -1
  161. package/src/models/__tests__/dispatchEvent.when.test.ts +214 -0
  162. package/src/models/__tests__/flowModel.test.ts +47 -3
  163. package/src/models/flowModel.tsx +119 -33
  164. package/src/provider.tsx +41 -25
  165. package/src/reactive/__tests__/observer.test.tsx +82 -0
  166. package/src/reactive/observer.tsx +87 -25
  167. package/src/runjs-context/registry.ts +1 -1
  168. package/src/runjs-context/setup.ts +22 -12
  169. package/src/runjs-context/snippets/index.ts +12 -1
  170. package/src/runjs-context/snippets/scene/detail/set-field-style.snippet.ts +30 -0
  171. package/src/runjs-context/snippets/scene/table/set-cell-style.snippet.ts +34 -0
  172. package/src/scheduler/ModelOperationScheduler.ts +14 -3
  173. package/src/types.ts +62 -0
  174. package/src/utils/__tests__/createCollectionContextMeta.test.ts +48 -0
  175. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +7 -0
  176. package/src/utils/__tests__/runjsValue.test.ts +11 -0
  177. package/src/utils/__tests__/utils.test.ts +62 -0
  178. package/src/utils/createCollectionContextMeta.ts +6 -2
  179. package/src/utils/index.ts +5 -1
  180. package/src/utils/parsePathnameToViewParams.ts +2 -2
  181. package/src/utils/randomId.ts +48 -0
  182. package/src/utils/runjsTemplateCompat.ts +1 -1
  183. package/src/utils/runjsValue.ts +50 -11
  184. package/src/utils/schema-utils.ts +30 -1
  185. package/src/views/FlowView.tsx +22 -2
  186. package/src/views/PageComponent.tsx +7 -4
  187. package/src/views/ViewNavigation.ts +6 -2
  188. package/src/views/__tests__/FlowView.usePage.test.tsx +243 -3
  189. package/src/views/__tests__/runViewBeforeClose.test.ts +30 -0
  190. package/src/views/__tests__/useDialog.closeDestroy.test.tsx +13 -12
  191. package/src/views/runViewBeforeClose.ts +19 -0
  192. package/src/views/useDialog.tsx +25 -3
  193. package/src/views/useDrawer.tsx +25 -3
  194. package/src/views/usePage.tsx +365 -179
@@ -0,0 +1,47 @@
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 { describe, expect, test } from 'vitest';
11
+ import { DetachedFlowRegistry, replaceFlowRegistry, serializeFlowRegistry } from '../DetachedFlowRegistry';
12
+
13
+ describe('DetachedFlowRegistry', () => {
14
+ test('keeps flow edits detached and can replace another registry', () => {
15
+ const source = {
16
+ flow1: {
17
+ title: 'Flow 1',
18
+ steps: {
19
+ step1: { title: 'Step 1' } as any,
20
+ },
21
+ },
22
+ };
23
+ const registry = new DetachedFlowRegistry(source);
24
+
25
+ source.flow1.title = 'Changed outside';
26
+ expect(registry.getFlow('flow1')?.title).toBe('Flow 1');
27
+
28
+ const flow = registry.getFlow('flow1');
29
+ expect(flow).toBeDefined();
30
+ if (!flow) {
31
+ throw new Error('flow1 should exist');
32
+ }
33
+ flow.title = 'Draft title';
34
+ const serialized = serializeFlowRegistry(registry);
35
+ serialized.flow1.title = 'Changed serialized';
36
+ expect(registry.getFlow('flow1')?.title).toBe('Draft title');
37
+
38
+ const target = new DetachedFlowRegistry({ stale: { title: 'Stale', steps: {} } });
39
+ replaceFlowRegistry(target, serializeFlowRegistry(registry));
40
+
41
+ expect(target.hasFlow('stale')).toBe(false);
42
+ expect(target.getFlow('flow1')?.title).toBe('Draft title');
43
+
44
+ target.destroyFlow('flow1');
45
+ expect(target.hasFlow('flow1')).toBe(false);
46
+ });
47
+ });
@@ -10,3 +10,4 @@
10
10
  export * from './BaseFlowRegistry';
11
11
  export * from './InstanceFlowRegistry';
12
12
  export * from './GlobalFlowRegistry';
13
+ export * from './DetachedFlowRegistry';
@@ -11,6 +11,7 @@ import { ISchema } from '@formily/json-schema';
11
11
  import { observable } from '@formily/reactive';
12
12
  import { APIClient, RequestOptions } from '@nocobase/sdk';
13
13
  import type { Router } from '@remix-run/router';
14
+ import axios from 'axios';
14
15
  import { MessageInstance } from 'antd/es/message/interface';
15
16
  import * as antd from 'antd';
16
17
  import type { HookAPI } from 'antd/es/modal/useModal';
@@ -27,7 +28,7 @@ import { ContextPathProxy } from './ContextPathProxy';
27
28
  import { DataSource, DataSourceManager } from './data-source';
28
29
  import { FlowEngine } from './flowEngine';
29
30
  import { FlowI18n } from './flowI18n';
30
- import { JSRunner, JSRunnerOptions } from './JSRunner';
31
+ import { JSRunner, JSRunnerOptions, shouldPreprocessRunJSTemplates } from './JSRunner';
31
32
  import type { FlowModel } from './models/flowModel';
32
33
  import type { ForkFlowModel } from './models/forkFlowModel';
33
34
  import { FlowResource, FlowSQLRepository } from './resources';
@@ -58,6 +59,31 @@ import dayjs from 'dayjs';
58
59
  import { externalReactRender, setupRunJSLibs } from './runjsLibs';
59
60
  import { runjsImportAsync, runjsImportModule, runjsRequireAsync } from './utils/runjsModuleLoader';
60
61
 
62
+ function normalizePathname(pathname: string) {
63
+ return pathname.endsWith('/') ? pathname : `${pathname}/`;
64
+ }
65
+
66
+ function shouldBypassApiClient(url: string, app?: { getApiUrl?: (pathname?: string) => string }) {
67
+ try {
68
+ const requestUrl = new URL(url);
69
+ if (!['http:', 'https:'].includes(requestUrl.protocol)) {
70
+ return false;
71
+ }
72
+
73
+ if (!app?.getApiUrl) {
74
+ return true;
75
+ }
76
+
77
+ const apiUrl = new URL(app.getApiUrl());
78
+ const apiPath = normalizePathname(apiUrl.pathname);
79
+ const requestPath = normalizePathname(requestUrl.pathname);
80
+
81
+ return requestUrl.origin !== apiUrl.origin || !requestPath.startsWith(apiPath);
82
+ } catch {
83
+ return false;
84
+ }
85
+ }
86
+
61
87
  // Helper: detect a RecordRef-like object
62
88
  function isRecordRefLike(val: any): boolean {
63
89
  return !!(val && typeof val === 'object' && 'collection' in val && 'filterByTk' in val);
@@ -2980,8 +3006,10 @@ export class FlowContext {
2980
3006
  }
2981
3007
 
2982
3008
  class BaseFlowEngineContext extends FlowContext {
3009
+ declare t: (key: any, options?: any) => string;
2983
3010
  declare router: Router;
2984
3011
  declare dataSourceManager: DataSourceManager;
3012
+ declare isDarkTheme: boolean;
2985
3013
  declare requireAsync: (url: string) => Promise<any>;
2986
3014
  declare importAsync: (url: string) => Promise<any>;
2987
3015
  declare createJSRunner: (options?: JSRunnerOptions) => Promise<JSRunner>;
@@ -3008,6 +3036,7 @@ class BaseFlowEngineContext extends FlowContext {
3008
3036
  declare runAction: (actionName: string, params?: Record<string, any>) => Promise<any> | any;
3009
3037
  declare engine: FlowEngine;
3010
3038
  declare api: APIClient;
3039
+ declare locale: string;
3011
3040
  declare viewer: FlowViewer;
3012
3041
  declare view: FlowView;
3013
3042
  declare modal: HookAPI;
@@ -3024,6 +3053,10 @@ class BaseFlowEngineContext extends FlowContext {
3024
3053
  return this.engine.getModel(modelName, searchInPreviousEngines);
3025
3054
  });
3026
3055
  this.defineMethod('request', (options: RequestOptions) => {
3056
+ const app = this.app as { getApiUrl?: (pathname?: string) => string } | undefined;
3057
+ if (typeof options?.url === 'string' && shouldBypassApiClient(options.url, app)) {
3058
+ return axios.request(options);
3059
+ }
3027
3060
  return this.api.request(options);
3028
3061
  });
3029
3062
  this.defineMethod(
@@ -3035,8 +3068,10 @@ class BaseFlowEngineContext extends FlowContext {
3035
3068
  ...(runnerOptions || {}),
3036
3069
  globals: mergedGlobals,
3037
3070
  });
3038
- // Enable by default; use `preprocessTemplates: false` to explicitly disable.
3039
- const shouldPreprocessTemplates = preprocessTemplates !== false;
3071
+ const shouldPreprocessTemplates = shouldPreprocessRunJSTemplates({
3072
+ version: runnerOptions?.version,
3073
+ preprocessTemplates,
3074
+ });
3040
3075
  const jsCode = await prepareRunJsCode(String(code ?? ''), { preprocessTemplates: shouldPreprocessTemplates });
3041
3076
  return runner.run(jsCode);
3042
3077
  },
@@ -3112,6 +3147,15 @@ export class FlowEngineContext extends BaseFlowEngineContext {
3112
3147
  this.defineMethod('t', (keyOrTemplate: string, options?: any) => {
3113
3148
  return i18n.translate(keyOrTemplate, options);
3114
3149
  });
3150
+ this.defineProperty('locale', {
3151
+ get: () => this.api?.auth?.locale || this.i18n?.language,
3152
+ cache: false,
3153
+ meta: Object.assign(() => ({ type: 'string', title: this.t('Current language'), sort: 970 }), {
3154
+ title: escapeT('Current language'),
3155
+ sort: 970,
3156
+ hasChildren: false,
3157
+ }),
3158
+ });
3115
3159
  this.defineMethod('renderJson', function (template: any) {
3116
3160
  return this.resolveJsonTemplate(template);
3117
3161
  });