@nocobase/flow-engine 2.1.0-beta.9 → 2.2.0-beta.1

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 (215) hide show
  1. package/lib/FlowContextProvider.d.ts +5 -1
  2. package/lib/FlowContextProvider.js +9 -2
  3. package/lib/components/FieldModelRenderer.js +2 -2
  4. package/lib/components/FlowModelRenderer.d.ts +3 -1
  5. package/lib/components/FlowModelRenderer.js +12 -6
  6. package/lib/components/FormItem.d.ts +6 -0
  7. package/lib/components/FormItem.js +11 -3
  8. package/lib/components/MobilePopup.js +6 -5
  9. package/lib/components/dnd/gridDragPlanner.d.ts +59 -2
  10. package/lib/components/dnd/gridDragPlanner.js +607 -19
  11. package/lib/components/dnd/index.d.ts +31 -2
  12. package/lib/components/dnd/index.js +244 -23
  13. package/lib/components/settings/wrappers/component/SelectWithTitle.d.ts +2 -1
  14. package/lib/components/settings/wrappers/component/SelectWithTitle.js +14 -12
  15. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.d.ts +3 -0
  16. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +152 -42
  17. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +23 -43
  18. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +352 -295
  19. package/lib/components/settings/wrappers/contextual/useFloatToolbarPortal.d.ts +36 -0
  20. package/lib/components/settings/wrappers/contextual/useFloatToolbarPortal.js +274 -0
  21. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.d.ts +30 -0
  22. package/lib/components/settings/wrappers/contextual/useFloatToolbarVisibility.js +315 -0
  23. package/lib/components/subModel/AddSubModelButton.js +12 -1
  24. package/lib/components/subModel/LazyDropdown.js +301 -52
  25. package/lib/components/subModel/index.d.ts +1 -0
  26. package/lib/components/subModel/index.js +19 -0
  27. package/lib/components/subModel/utils.d.ts +2 -1
  28. package/lib/components/subModel/utils.js +15 -5
  29. package/lib/components/variables/VariableHybridInput.d.ts +27 -0
  30. package/lib/components/variables/VariableHybridInput.js +499 -0
  31. package/lib/components/variables/index.d.ts +2 -0
  32. package/lib/components/variables/index.js +3 -0
  33. package/lib/data-source/index.d.ts +84 -0
  34. package/lib/data-source/index.js +269 -7
  35. package/lib/executor/FlowExecutor.js +6 -3
  36. package/lib/flow-registry/DetachedFlowRegistry.d.ts +21 -0
  37. package/lib/flow-registry/DetachedFlowRegistry.js +80 -0
  38. package/lib/flow-registry/index.d.ts +1 -0
  39. package/lib/flow-registry/index.js +3 -1
  40. package/lib/flowContext.d.ts +9 -1
  41. package/lib/flowContext.js +77 -6
  42. package/lib/flowEngine.d.ts +136 -4
  43. package/lib/flowEngine.js +429 -51
  44. package/lib/flowI18n.js +2 -1
  45. package/lib/flowSettings.d.ts +14 -6
  46. package/lib/flowSettings.js +34 -6
  47. package/lib/index.d.ts +2 -0
  48. package/lib/index.js +7 -0
  49. package/lib/lazy-helper.d.ts +14 -0
  50. package/lib/lazy-helper.js +71 -0
  51. package/lib/locale/en-US.json +1 -0
  52. package/lib/locale/index.d.ts +2 -0
  53. package/lib/locale/zh-CN.json +1 -0
  54. package/lib/models/DisplayItemModel.d.ts +1 -1
  55. package/lib/models/EditableItemModel.d.ts +1 -1
  56. package/lib/models/FilterableItemModel.d.ts +1 -1
  57. package/lib/models/flowModel.d.ts +13 -10
  58. package/lib/models/flowModel.js +126 -34
  59. package/lib/provider.js +38 -23
  60. package/lib/reactive/observer.js +46 -16
  61. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +4 -3
  62. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +4 -15
  63. package/lib/runjs-context/contexts/JSColumnRunJSContext.js +5 -2
  64. package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.js +5 -8
  65. package/lib/runjs-context/contexts/JSFieldRunJSContext.js +4 -3
  66. package/lib/runjs-context/contexts/JSItemRunJSContext.js +4 -3
  67. package/lib/runjs-context/contexts/base.js +464 -29
  68. package/lib/runjs-context/contexts/elementDoc.d.ts +11 -0
  69. package/lib/runjs-context/contexts/elementDoc.js +152 -0
  70. package/lib/runjs-context/setup.js +1 -0
  71. package/lib/runjs-context/snippets/index.js +13 -2
  72. package/lib/runjs-context/snippets/scene/detail/set-field-style.snippet.d.ts +11 -0
  73. package/lib/runjs-context/snippets/scene/detail/set-field-style.snippet.js +50 -0
  74. package/lib/runjs-context/snippets/scene/table/set-cell-style.snippet.d.ts +11 -0
  75. package/lib/runjs-context/snippets/scene/table/set-cell-style.snippet.js +54 -0
  76. package/lib/types.d.ts +50 -2
  77. package/lib/types.js +1 -0
  78. package/lib/utils/createCollectionContextMeta.js +6 -2
  79. package/lib/utils/index.d.ts +3 -2
  80. package/lib/utils/index.js +7 -0
  81. package/lib/utils/loadedPageCache.d.ts +24 -0
  82. package/lib/utils/loadedPageCache.js +139 -0
  83. package/lib/utils/parsePathnameToViewParams.d.ts +5 -1
  84. package/lib/utils/parsePathnameToViewParams.js +28 -4
  85. package/lib/utils/randomId.d.ts +39 -0
  86. package/lib/utils/randomId.js +45 -0
  87. package/lib/utils/runjsTemplateCompat.js +1 -1
  88. package/lib/utils/runjsValue.js +41 -11
  89. package/lib/utils/schema-utils.d.ts +7 -1
  90. package/lib/utils/schema-utils.js +19 -0
  91. package/lib/views/FlowView.d.ts +7 -1
  92. package/lib/views/FlowView.js +11 -1
  93. package/lib/views/PageComponent.js +8 -6
  94. package/lib/views/ViewNavigation.d.ts +12 -2
  95. package/lib/views/ViewNavigation.js +28 -9
  96. package/lib/views/createViewMeta.js +114 -50
  97. package/lib/views/inheritLayoutContext.d.ts +10 -0
  98. package/lib/views/inheritLayoutContext.js +50 -0
  99. package/lib/views/runViewBeforeClose.d.ts +10 -0
  100. package/lib/views/runViewBeforeClose.js +45 -0
  101. package/lib/views/useDialog.d.ts +2 -1
  102. package/lib/views/useDialog.js +12 -3
  103. package/lib/views/useDrawer.d.ts +2 -1
  104. package/lib/views/useDrawer.js +12 -3
  105. package/lib/views/usePage.d.ts +5 -11
  106. package/lib/views/usePage.js +304 -144
  107. package/package.json +5 -4
  108. package/src/FlowContextProvider.tsx +9 -1
  109. package/src/__tests__/createViewMeta.popup.test.ts +115 -1
  110. package/src/__tests__/flow-engine.test.ts +166 -0
  111. package/src/__tests__/flowContext.test.ts +105 -1
  112. package/src/__tests__/flowEngine.modelLoaders.test.ts +245 -0
  113. package/src/__tests__/flowEngine.moveModel.test.ts +81 -1
  114. package/src/__tests__/flowEngine.removeModel.test.ts +47 -3
  115. package/src/__tests__/flowSettings.test.ts +94 -15
  116. package/src/__tests__/objectVariable.test.ts +24 -0
  117. package/src/__tests__/provider.test.tsx +24 -2
  118. package/src/__tests__/renderHiddenInConfig.test.tsx +6 -6
  119. package/src/__tests__/runjsContext.test.ts +21 -0
  120. package/src/__tests__/runjsContextImplementations.test.ts +9 -2
  121. package/src/__tests__/runjsContextRuntime.test.ts +2 -0
  122. package/src/__tests__/runjsLocales.test.ts +6 -5
  123. package/src/__tests__/runjsSnippets.test.ts +21 -0
  124. package/src/__tests__/viewScopedFlowEngine.test.ts +136 -3
  125. package/src/components/FieldModelRenderer.tsx +2 -1
  126. package/src/components/FlowModelRenderer.tsx +18 -6
  127. package/src/components/FormItem.tsx +7 -1
  128. package/src/components/MobilePopup.tsx +4 -2
  129. package/src/components/__tests__/FlowModelRenderer.test.tsx +65 -2
  130. package/src/components/__tests__/FormItem.test.tsx +25 -0
  131. package/src/components/__tests__/dnd.test.ts +44 -0
  132. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +20 -10
  133. package/src/components/__tests__/gridDragPlanner.test.ts +472 -5
  134. package/src/components/dnd/__tests__/DndProvider.test.tsx +98 -0
  135. package/src/components/dnd/gridDragPlanner.ts +750 -17
  136. package/src/components/dnd/index.tsx +305 -28
  137. package/src/components/settings/wrappers/component/SelectWithTitle.tsx +21 -9
  138. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +178 -48
  139. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +487 -440
  140. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +344 -8
  141. package/src/components/settings/wrappers/contextual/__tests__/FlowsFloatContextMenu.test.tsx +778 -0
  142. package/src/components/settings/wrappers/contextual/useFloatToolbarPortal.ts +360 -0
  143. package/src/components/settings/wrappers/contextual/useFloatToolbarVisibility.ts +361 -0
  144. package/src/components/subModel/AddSubModelButton.tsx +16 -2
  145. package/src/components/subModel/LazyDropdown.tsx +341 -56
  146. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +524 -38
  147. package/src/components/subModel/__tests__/utils.test.ts +24 -0
  148. package/src/components/subModel/index.ts +1 -0
  149. package/src/components/subModel/utils.ts +13 -2
  150. package/src/components/variables/VariableHybridInput.tsx +531 -0
  151. package/src/components/variables/index.ts +2 -0
  152. package/src/data-source/__tests__/collection.test.ts +41 -2
  153. package/src/data-source/__tests__/index.test.ts +69 -2
  154. package/src/data-source/index.ts +332 -8
  155. package/src/executor/FlowExecutor.ts +6 -3
  156. package/src/executor/__tests__/flowExecutor.test.ts +57 -0
  157. package/src/flow-registry/DetachedFlowRegistry.ts +46 -0
  158. package/src/flow-registry/__tests__/detachedFlowRegistry.test.ts +47 -0
  159. package/src/flow-registry/index.ts +1 -0
  160. package/src/flowContext.ts +85 -6
  161. package/src/flowEngine.ts +484 -45
  162. package/src/flowI18n.ts +2 -1
  163. package/src/flowSettings.ts +40 -6
  164. package/src/index.ts +2 -0
  165. package/src/lazy-helper.tsx +57 -0
  166. package/src/locale/en-US.json +1 -0
  167. package/src/locale/zh-CN.json +1 -0
  168. package/src/models/DisplayItemModel.tsx +1 -1
  169. package/src/models/EditableItemModel.tsx +1 -1
  170. package/src/models/FilterableItemModel.tsx +1 -1
  171. package/src/models/__tests__/flowEngine.resolveUse.test.ts +0 -15
  172. package/src/models/__tests__/flowModel.test.ts +65 -37
  173. package/src/models/flowModel.tsx +184 -65
  174. package/src/provider.tsx +41 -25
  175. package/src/reactive/__tests__/observer.test.tsx +82 -0
  176. package/src/reactive/observer.tsx +87 -25
  177. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +4 -3
  178. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +4 -15
  179. package/src/runjs-context/contexts/JSColumnRunJSContext.ts +4 -2
  180. package/src/runjs-context/contexts/JSEditableFieldRunJSContext.ts +5 -9
  181. package/src/runjs-context/contexts/JSFieldRunJSContext.ts +4 -3
  182. package/src/runjs-context/contexts/JSItemRunJSContext.ts +4 -3
  183. package/src/runjs-context/contexts/base.ts +467 -31
  184. package/src/runjs-context/contexts/elementDoc.ts +130 -0
  185. package/src/runjs-context/setup.ts +1 -0
  186. package/src/runjs-context/snippets/index.ts +12 -1
  187. package/src/runjs-context/snippets/scene/detail/set-field-style.snippet.ts +30 -0
  188. package/src/runjs-context/snippets/scene/table/set-cell-style.snippet.ts +34 -0
  189. package/src/types.ts +62 -0
  190. package/src/utils/__tests__/createCollectionContextMeta.test.ts +48 -0
  191. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +21 -0
  192. package/src/utils/__tests__/runjsValue.test.ts +11 -0
  193. package/src/utils/__tests__/utils.test.ts +62 -0
  194. package/src/utils/createCollectionContextMeta.ts +6 -2
  195. package/src/utils/index.ts +5 -1
  196. package/src/utils/loadedPageCache.ts +147 -0
  197. package/src/utils/parsePathnameToViewParams.ts +45 -5
  198. package/src/utils/randomId.ts +48 -0
  199. package/src/utils/runjsTemplateCompat.ts +1 -1
  200. package/src/utils/runjsValue.ts +50 -11
  201. package/src/utils/schema-utils.ts +30 -1
  202. package/src/views/FlowView.tsx +22 -2
  203. package/src/views/PageComponent.tsx +7 -4
  204. package/src/views/ViewNavigation.ts +46 -9
  205. package/src/views/__tests__/FlowView.usePage.test.tsx +243 -3
  206. package/src/views/__tests__/ViewNavigation.test.ts +52 -0
  207. package/src/views/__tests__/inheritLayoutContext.test.ts +53 -0
  208. package/src/views/__tests__/runViewBeforeClose.test.ts +30 -0
  209. package/src/views/__tests__/useDialog.closeDestroy.test.tsx +12 -12
  210. package/src/views/createViewMeta.ts +106 -34
  211. package/src/views/inheritLayoutContext.ts +26 -0
  212. package/src/views/runViewBeforeClose.ts +19 -0
  213. package/src/views/useDialog.tsx +13 -3
  214. package/src/views/useDrawer.tsx +13 -3
  215. package/src/views/usePage.tsx +367 -180
@@ -0,0 +1,46 @@
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 _ from 'lodash';
11
+ import { FlowDefinition } from '../FlowDefinition';
12
+ import { FlowDefinitionOptions } from '../types';
13
+ import { BaseFlowRegistry, IFlowRepository } from './BaseFlowRegistry';
14
+
15
+ export type FlowRegistryData = Record<string, Omit<FlowDefinitionOptions, 'key'> & { key?: string }>;
16
+
17
+ export class DetachedFlowRegistry extends BaseFlowRegistry {
18
+ constructor(flows: FlowRegistryData = {}) {
19
+ super();
20
+ this.addFlows(_.cloneDeep(flows));
21
+ }
22
+
23
+ saveFlow(_flow: FlowDefinition): void {}
24
+
25
+ destroyFlow(flowKey: string): void {
26
+ this.removeFlow(flowKey);
27
+ }
28
+ }
29
+
30
+ export function serializeFlowRegistry(registry: Pick<IFlowRepository, 'getFlows'>): FlowRegistryData {
31
+ const flows: FlowRegistryData = {};
32
+ for (const [key, flow] of registry.getFlows()) {
33
+ flows[key] = _.cloneDeep(flow.toData());
34
+ }
35
+ return flows;
36
+ }
37
+
38
+ export function replaceFlowRegistry(
39
+ registry: Pick<IFlowRepository, 'getFlows' | 'removeFlow' | 'addFlows'>,
40
+ flows: FlowRegistryData,
41
+ ) {
42
+ for (const key of Array.from(registry.getFlows().keys())) {
43
+ registry.removeFlow(key);
44
+ }
45
+ registry.addFlows(_.cloneDeep(flows));
46
+ }
@@ -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';
@@ -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);
@@ -374,6 +400,10 @@ export type FlowContextGetApiInfosOptions = {
374
400
  * RunJS 文档版本(默认 v1)。
375
401
  */
376
402
  version?: RunJSVersion;
403
+ /**
404
+ * Include editor completion metadata. Defaults to false so API-doc callers keep the compact public shape.
405
+ */
406
+ includeCompletion?: boolean;
377
407
  };
378
408
 
379
409
  export type FlowContextGetVarInfosOptions = {
@@ -678,10 +708,11 @@ export class FlowContext {
678
708
  * - 输出仅来自 RunJS doc 与 defineProperty/defineMethod 的 info
679
709
  * - 不读取/展开 PropertyMeta(变量结构)
680
710
  * - 不自动展开深层 properties
681
- * - 不返回自动补全字段(例如 completion
711
+ * - 默认不返回自动补全字段(例如 completion),传入 includeCompletion=true 时返回
682
712
  */
683
713
  async getApiInfos(options: FlowContextGetApiInfosOptions = {}): Promise<Record<string, FlowContextApiInfo>> {
684
714
  const version = (options.version as RunJSVersion) || ('v1' as RunJSVersion);
715
+ const includeCompletion = !!options.includeCompletion;
685
716
  const evalCtx = this.createProxy();
686
717
 
687
718
  const isPrivateKey = (key: string) => typeof key === 'string' && key.startsWith('_');
@@ -733,7 +764,14 @@ export class FlowContext {
733
764
  const src = toDocObject(obj);
734
765
  if (!src) return {};
735
766
  const out: any = {};
736
- for (const k of ['description', 'examples', 'ref', 'params', 'returns']) {
767
+ for (const k of [
768
+ 'description',
769
+ 'examples',
770
+ ...(includeCompletion ? ['completion'] : []),
771
+ 'ref',
772
+ 'params',
773
+ 'returns',
774
+ ]) {
737
775
  const v = (src as any)[k];
738
776
  if (typeof v !== 'undefined') out[k] = v;
739
777
  }
@@ -747,7 +785,17 @@ export class FlowContext {
747
785
  const src = toDocObject(obj);
748
786
  if (!src) return {};
749
787
  const out: any = {};
750
- for (const k of ['title', 'type', 'interface', 'description', 'examples', 'ref', 'params', 'returns']) {
788
+ for (const k of [
789
+ 'title',
790
+ 'type',
791
+ 'interface',
792
+ 'description',
793
+ 'examples',
794
+ ...(includeCompletion ? ['completion'] : []),
795
+ 'ref',
796
+ 'params',
797
+ 'returns',
798
+ ]) {
751
799
  const v = (src as any)[k];
752
800
  if (typeof v !== 'undefined') out[k] = v;
753
801
  }
@@ -846,7 +894,7 @@ export class FlowContext {
846
894
  node = { ...node, ...pickPropertyInfo(docObj) };
847
895
  node = { ...node, ...pickPropertyInfo(infoObj) };
848
896
  delete (node as any).properties;
849
- delete (node as any).completion;
897
+ if (!includeCompletion) delete (node as any).completion;
850
898
  if (!Object.keys(node).length) continue;
851
899
  const outKey = mapDocKeyToApiKey(key, docNode);
852
900
  // Avoid exposing ctx.React/ctx.ReactDOM/ctx.antd in api docs when mapping to ctx.libs.*.
@@ -864,7 +912,7 @@ export class FlowContext {
864
912
  node = { ...node, ...pickMethodInfo(docObj) };
865
913
  node = { ...node, ...pickMethodInfo(info) };
866
914
  delete (node as any).properties;
867
- delete (node as any).completion;
915
+ if (!includeCompletion) delete (node as any).completion;
868
916
  if (!Object.keys(node).length) continue;
869
917
  node.type = 'function';
870
918
 
@@ -887,7 +935,7 @@ export class FlowContext {
887
935
  let node: FlowContextApiInfo = {};
888
936
  node = { ...node, ...pickPropertyInfo(childObj) };
889
937
  delete (node as any).properties;
890
- delete (node as any).completion;
938
+ if (!includeCompletion) delete (node as any).completion;
891
939
  if (!node.description || !String(node.description).trim()) continue;
892
940
  out[outKey] = node;
893
941
  }
@@ -2980,8 +3028,10 @@ export class FlowContext {
2980
3028
  }
2981
3029
 
2982
3030
  class BaseFlowEngineContext extends FlowContext {
3031
+ declare t: (key: any, options?: any) => string;
2983
3032
  declare router: Router;
2984
3033
  declare dataSourceManager: DataSourceManager;
3034
+ declare isDarkTheme: boolean;
2985
3035
  declare requireAsync: (url: string) => Promise<any>;
2986
3036
  declare importAsync: (url: string) => Promise<any>;
2987
3037
  declare createJSRunner: (options?: JSRunnerOptions) => Promise<JSRunner>;
@@ -3008,6 +3058,7 @@ class BaseFlowEngineContext extends FlowContext {
3008
3058
  declare runAction: (actionName: string, params?: Record<string, any>) => Promise<any> | any;
3009
3059
  declare engine: FlowEngine;
3010
3060
  declare api: APIClient;
3061
+ declare locale: string;
3011
3062
  declare viewer: FlowViewer;
3012
3063
  declare view: FlowView;
3013
3064
  declare modal: HookAPI;
@@ -3024,6 +3075,10 @@ class BaseFlowEngineContext extends FlowContext {
3024
3075
  return this.engine.getModel(modelName, searchInPreviousEngines);
3025
3076
  });
3026
3077
  this.defineMethod('request', (options: RequestOptions) => {
3078
+ const app = this.app as { getApiUrl?: (pathname?: string) => string } | undefined;
3079
+ if (typeof options?.url === 'string' && shouldBypassApiClient(options.url, app)) {
3080
+ return axios.request(options);
3081
+ }
3027
3082
  return this.api.request(options);
3028
3083
  });
3029
3084
  this.defineMethod(
@@ -3042,6 +3097,17 @@ class BaseFlowEngineContext extends FlowContext {
3042
3097
  const jsCode = await prepareRunJsCode(String(code ?? ''), { preprocessTemplates: shouldPreprocessTemplates });
3043
3098
  return runner.run(jsCode);
3044
3099
  },
3100
+ {
3101
+ description: 'Execute a RunJS code string in the current Flow context.',
3102
+ detail: '(code: string, variables?: Record<string, any>, options?: JSRunnerOptions) => Promise<RunJSResult>',
3103
+ params: [
3104
+ { name: 'code', type: 'string', description: 'RunJS code to execute.' },
3105
+ { name: 'variables', type: 'Record<string, any>', optional: true, description: 'Additional globals.' },
3106
+ { name: 'options', type: 'JSRunnerOptions', optional: true, description: 'Runner options.' },
3107
+ ],
3108
+ returns: { type: 'Promise<{ success: boolean; value?: any; error?: any; timeout?: boolean }>' },
3109
+ completion: { insertText: `await ctx.runjs('return 1')` },
3110
+ },
3045
3111
  );
3046
3112
  }
3047
3113
  }
@@ -3114,6 +3180,15 @@ export class FlowEngineContext extends BaseFlowEngineContext {
3114
3180
  this.defineMethod('t', (keyOrTemplate: string, options?: any) => {
3115
3181
  return i18n.translate(keyOrTemplate, options);
3116
3182
  });
3183
+ this.defineProperty('locale', {
3184
+ get: () => this.api?.auth?.locale || this.i18n?.language,
3185
+ cache: false,
3186
+ meta: Object.assign(() => ({ type: 'string', title: this.t('Current language'), sort: 970 }), {
3187
+ title: escapeT('Current language'),
3188
+ sort: 970,
3189
+ hasChildren: false,
3190
+ }),
3191
+ });
3117
3192
  this.defineMethod('renderJson', function (template: any) {
3118
3193
  return this.resolveJsonTemplate(template);
3119
3194
  });
@@ -3539,6 +3614,9 @@ export class FlowEngineContext extends BaseFlowEngineContext {
3539
3614
  },
3540
3615
  });
3541
3616
  this.defineMethod('aclCheck', function (params) {
3617
+ if (this.skipAclCheck) {
3618
+ return true;
3619
+ }
3542
3620
  return this.acl.aclCheck(params);
3543
3621
  });
3544
3622
  this.defineMethod('createResource', function (this: BaseFlowEngineContext, resourceType) {
@@ -3882,6 +3960,7 @@ export type FlowSettingsContext<TModel extends FlowModel = FlowModel> = FlowRunt
3882
3960
 
3883
3961
  export type RunJSDocCompletionDoc = {
3884
3962
  insertText?: string;
3963
+ requires?: Array<'element'>;
3885
3964
  };
3886
3965
 
3887
3966
  export type RunJSDocHiddenDoc = boolean | ((ctx: any) => boolean | Promise<boolean>);