@nocobase/flow-engine 2.0.0-beta.9 → 2.0.0

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 (245) hide show
  1. package/lib/BlockScopedFlowEngine.js +0 -1
  2. package/lib/FlowDefinition.d.ts +2 -0
  3. package/lib/JSRunner.d.ts +6 -0
  4. package/lib/JSRunner.js +32 -2
  5. package/lib/ViewScopedFlowEngine.js +3 -0
  6. package/lib/acl/Acl.js +13 -3
  7. package/lib/components/FlowContextSelector.js +155 -10
  8. package/lib/components/settings/wrappers/component/SwitchWithTitle.js +2 -1
  9. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +76 -15
  10. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +24 -4
  11. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +5 -1
  12. package/lib/components/variables/VariableInput.js +9 -4
  13. package/lib/components/variables/VariableTag.js +46 -39
  14. package/lib/components/variables/utils.d.ts +7 -0
  15. package/lib/components/variables/utils.js +42 -2
  16. package/lib/data-source/index.d.ts +7 -27
  17. package/lib/data-source/index.js +81 -51
  18. package/lib/executor/FlowExecutor.d.ts +2 -1
  19. package/lib/executor/FlowExecutor.js +163 -22
  20. package/lib/flowContext.d.ts +230 -7
  21. package/lib/flowContext.js +2267 -148
  22. package/lib/flowEngine.d.ts +21 -0
  23. package/lib/flowEngine.js +56 -8
  24. package/lib/flowI18n.js +6 -4
  25. package/lib/flowSettings.js +17 -11
  26. package/lib/index.d.ts +7 -1
  27. package/lib/index.js +21 -0
  28. package/lib/locale/en-US.json +9 -2
  29. package/lib/locale/index.d.ts +14 -0
  30. package/lib/locale/zh-CN.json +8 -1
  31. package/lib/models/CollectionFieldModel.d.ts +1 -0
  32. package/lib/models/CollectionFieldModel.js +3 -2
  33. package/lib/models/flowModel.js +12 -1
  34. package/lib/provider.js +5 -5
  35. package/lib/resources/baseRecordResource.d.ts +5 -0
  36. package/lib/resources/baseRecordResource.js +24 -0
  37. package/lib/resources/multiRecordResource.d.ts +1 -0
  38. package/lib/resources/multiRecordResource.js +11 -4
  39. package/lib/resources/singleRecordResource.js +2 -0
  40. package/lib/resources/sqlResource.d.ts +4 -3
  41. package/lib/resources/sqlResource.js +8 -3
  42. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +12 -2
  43. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +2 -2
  44. package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.d.ts +16 -0
  45. package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.js +125 -0
  46. package/lib/runjs-context/contexts/JSItemRunJSContext.js +12 -2
  47. package/lib/runjs-context/contexts/base.js +706 -41
  48. package/lib/runjs-context/contributions.d.ts +33 -0
  49. package/lib/runjs-context/contributions.js +88 -0
  50. package/lib/runjs-context/helpers.js +12 -1
  51. package/lib/runjs-context/setup.js +6 -0
  52. package/lib/runjs-context/snippets/global/api-request.snippet.js +3 -3
  53. package/lib/runjs-context/snippets/global/import-esm.snippet.js +2 -3
  54. package/lib/runjs-context/snippets/global/query-selector.snippet.js +8 -3
  55. package/lib/runjs-context/snippets/global/require-amd.snippet.js +1 -1
  56. package/lib/runjs-context/snippets/index.d.ts +11 -1
  57. package/lib/runjs-context/snippets/index.js +61 -40
  58. package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.js +10 -7
  59. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +3 -3
  60. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +2 -2
  61. package/lib/runjs-context/snippets/scene/block/echarts-init.snippet.js +2 -2
  62. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +2 -2
  63. package/lib/runjs-context/snippets/scene/block/render-react.snippet.js +1 -1
  64. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +1 -1
  65. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +1 -1
  66. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +5 -5
  67. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +6 -6
  68. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +3 -4
  69. package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.js +1 -1
  70. package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.js +20 -3
  71. package/lib/runjs-context/snippets/scene/detail/format-number.snippet.js +1 -1
  72. package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.js +1 -1
  73. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +3 -3
  74. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +3 -3
  75. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +2 -2
  76. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +1 -1
  77. package/lib/runjs-context/snippets/scene/form/render-basic.snippet.js +2 -2
  78. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +6 -3
  79. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +3 -1
  80. package/lib/runjsLibs.d.ts +28 -0
  81. package/lib/runjsLibs.js +532 -0
  82. package/lib/scheduler/ModelOperationScheduler.d.ts +2 -0
  83. package/lib/scheduler/ModelOperationScheduler.js +25 -21
  84. package/lib/types.d.ts +27 -0
  85. package/lib/utils/associationObjectVariable.d.ts +2 -2
  86. package/lib/utils/createCollectionContextMeta.js +1 -0
  87. package/lib/utils/createEphemeralContext.js +2 -2
  88. package/lib/utils/dateVariable.d.ts +16 -0
  89. package/lib/utils/dateVariable.js +380 -0
  90. package/lib/utils/exceptions.d.ts +7 -0
  91. package/lib/utils/exceptions.js +10 -0
  92. package/lib/utils/index.d.ts +8 -3
  93. package/lib/utils/index.js +45 -0
  94. package/lib/utils/params-resolvers.js +16 -9
  95. package/lib/utils/resolveModuleUrl.d.ts +58 -0
  96. package/lib/utils/resolveModuleUrl.js +65 -0
  97. package/lib/utils/resolveRunJSObjectValues.d.ts +16 -0
  98. package/lib/utils/resolveRunJSObjectValues.js +61 -0
  99. package/lib/utils/runjsModuleLoader.d.ts +58 -0
  100. package/lib/utils/runjsModuleLoader.js +422 -0
  101. package/lib/utils/runjsTemplateCompat.d.ts +35 -0
  102. package/lib/utils/runjsTemplateCompat.js +743 -0
  103. package/lib/utils/runjsValue.d.ts +29 -0
  104. package/lib/utils/runjsValue.js +275 -0
  105. package/lib/utils/safeGlobals.d.ts +18 -8
  106. package/lib/utils/safeGlobals.js +164 -17
  107. package/lib/utils/schema-utils.d.ts +10 -0
  108. package/lib/utils/schema-utils.js +61 -0
  109. package/lib/views/createViewMeta.d.ts +0 -7
  110. package/lib/views/createViewMeta.js +19 -70
  111. package/lib/views/index.d.ts +1 -2
  112. package/lib/views/index.js +4 -3
  113. package/lib/views/useDialog.js +7 -2
  114. package/lib/views/useDrawer.js +7 -2
  115. package/lib/views/usePage.d.ts +4 -0
  116. package/lib/views/usePage.js +43 -6
  117. package/lib/views/usePopover.js +4 -1
  118. package/lib/views/viewEvents.d.ts +17 -0
  119. package/lib/views/viewEvents.js +90 -0
  120. package/package.json +4 -4
  121. package/src/BlockScopedFlowEngine.ts +2 -5
  122. package/src/JSRunner.ts +44 -2
  123. package/src/ViewScopedFlowEngine.ts +4 -0
  124. package/src/__tests__/JSRunner.test.ts +64 -0
  125. package/src/__tests__/createViewMeta.popup.test.ts +62 -1
  126. package/src/__tests__/flowContext.test.ts +693 -1
  127. package/src/__tests__/flowEngine.dataSourceDirty.test.ts +63 -0
  128. package/src/__tests__/flowModel.openView.navigation.test.ts +28 -0
  129. package/src/__tests__/flowRunJSContextDefine.test.ts +63 -0
  130. package/src/__tests__/flowRuntimeContext.test.ts +2 -1
  131. package/src/__tests__/flowSettings.open.test.tsx +123 -19
  132. package/src/__tests__/runjsContext.test.ts +10 -7
  133. package/src/__tests__/runjsContextImplementations.test.ts +34 -3
  134. package/src/__tests__/runjsContextRuntime.test.ts +3 -3
  135. package/src/__tests__/runjsContributions.test.ts +89 -0
  136. package/src/__tests__/runjsExternalLibs.test.ts +242 -0
  137. package/src/__tests__/runjsLibsLazyLoading.test.ts +44 -0
  138. package/src/__tests__/runjsLocales.test.ts +4 -1
  139. package/src/__tests__/runjsPreprocessDefault.test.ts +49 -0
  140. package/src/__tests__/runjsRuntimeFeatures.test.ts +166 -0
  141. package/src/__tests__/runjsSnippets.test.ts +40 -3
  142. package/src/acl/Acl.tsx +3 -3
  143. package/src/components/FlowContextSelector.tsx +208 -12
  144. package/src/components/settings/wrappers/component/SwitchWithTitle.tsx +2 -1
  145. package/src/components/settings/wrappers/component/__tests__/InlineControls.test.tsx +74 -0
  146. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +109 -16
  147. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +41 -7
  148. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +13 -2
  149. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +157 -5
  150. package/src/components/variables/VariableInput.tsx +12 -4
  151. package/src/components/variables/VariableTag.tsx +54 -45
  152. package/src/components/variables/__tests__/FlowContextSelector.test.tsx +260 -3
  153. package/src/components/variables/__tests__/VariableTag.test.tsx +50 -0
  154. package/src/components/variables/__tests__/utils.test.ts +81 -3
  155. package/src/components/variables/utils.ts +67 -6
  156. package/src/data-source/index.ts +85 -110
  157. package/src/executor/FlowExecutor.ts +200 -23
  158. package/src/executor/__tests__/flowExecutor.test.ts +66 -0
  159. package/src/flowContext.ts +2986 -211
  160. package/src/flowEngine.ts +59 -8
  161. package/src/flowI18n.ts +7 -5
  162. package/src/flowSettings.ts +18 -12
  163. package/src/index.ts +14 -1
  164. package/src/locale/en-US.json +9 -2
  165. package/src/locale/zh-CN.json +8 -1
  166. package/src/models/CollectionFieldModel.tsx +3 -1
  167. package/src/models/__tests__/dispatchEvent.when.test.ts +554 -0
  168. package/src/models/__tests__/flowModel.test.ts +20 -4
  169. package/src/models/flowModel.tsx +13 -1
  170. package/src/provider.tsx +7 -6
  171. package/src/resources/__tests__/multiRecordResource.test.ts +44 -0
  172. package/src/resources/__tests__/sqlResource.test.ts +60 -0
  173. package/src/resources/baseRecordResource.ts +31 -0
  174. package/src/resources/multiRecordResource.ts +11 -4
  175. package/src/resources/singleRecordResource.ts +3 -0
  176. package/src/resources/sqlResource.ts +11 -6
  177. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +10 -0
  178. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +6 -2
  179. package/src/runjs-context/contexts/JSEditableFieldRunJSContext.ts +106 -0
  180. package/src/runjs-context/contexts/JSItemRunJSContext.ts +10 -0
  181. package/src/runjs-context/contexts/base.ts +715 -44
  182. package/src/runjs-context/contributions.ts +88 -0
  183. package/src/runjs-context/helpers.ts +11 -1
  184. package/src/runjs-context/setup.ts +6 -0
  185. package/src/runjs-context/snippets/global/api-request.snippet.ts +3 -3
  186. package/src/runjs-context/snippets/global/import-esm.snippet.ts +2 -3
  187. package/src/runjs-context/snippets/global/query-selector.snippet.ts +8 -3
  188. package/src/runjs-context/snippets/global/require-amd.snippet.ts +1 -1
  189. package/src/runjs-context/snippets/index.ts +75 -41
  190. package/src/runjs-context/snippets/scene/block/add-event-listener.snippet.ts +11 -13
  191. package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +3 -3
  192. package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +2 -2
  193. package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +2 -2
  194. package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +2 -2
  195. package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +1 -1
  196. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +1 -1
  197. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +1 -1
  198. package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +6 -11
  199. package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +6 -6
  200. package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +3 -4
  201. package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +1 -1
  202. package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +20 -3
  203. package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +1 -1
  204. package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +1 -1
  205. package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +3 -3
  206. package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +3 -3
  207. package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +2 -2
  208. package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +1 -1
  209. package/src/runjs-context/snippets/scene/form/render-basic.snippet.ts +3 -8
  210. package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +6 -3
  211. package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +3 -1
  212. package/src/runjsLibs.ts +622 -0
  213. package/src/scheduler/ModelOperationScheduler.ts +27 -21
  214. package/src/types.ts +38 -1
  215. package/src/utils/__tests__/dateVariable.test.ts +101 -0
  216. package/src/utils/__tests__/params-resolvers.test.ts +40 -0
  217. package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +38 -0
  218. package/src/utils/__tests__/runjsTemplateCompat.test.ts +159 -0
  219. package/src/utils/__tests__/runjsValue.test.ts +44 -0
  220. package/src/utils/__tests__/safeGlobals.test.ts +57 -2
  221. package/src/utils/__tests__/utils.test.ts +95 -0
  222. package/src/utils/associationObjectVariable.ts +2 -2
  223. package/src/utils/createCollectionContextMeta.ts +1 -0
  224. package/src/utils/createEphemeralContext.ts +5 -4
  225. package/src/utils/dateVariable.ts +397 -0
  226. package/src/utils/exceptions.ts +11 -0
  227. package/src/utils/index.ts +37 -3
  228. package/src/utils/params-resolvers.ts +23 -9
  229. package/src/utils/resolveModuleUrl.ts +91 -0
  230. package/src/utils/resolveRunJSObjectValues.ts +46 -0
  231. package/src/utils/runjsModuleLoader.ts +553 -0
  232. package/src/utils/runjsTemplateCompat.ts +828 -0
  233. package/src/utils/runjsValue.ts +287 -0
  234. package/src/utils/safeGlobals.ts +188 -17
  235. package/src/utils/schema-utils.ts +79 -0
  236. package/src/views/__tests__/FlowView.usePage.test.tsx +54 -1
  237. package/src/views/__tests__/useDialog.closeDestroy.test.tsx +35 -8
  238. package/src/views/__tests__/viewEvents.resolveOpenerEngine.test.ts +28 -0
  239. package/src/views/createViewMeta.ts +22 -75
  240. package/src/views/index.tsx +1 -2
  241. package/src/views/useDialog.tsx +8 -1
  242. package/src/views/useDrawer.tsx +8 -1
  243. package/src/views/usePage.tsx +51 -5
  244. package/src/views/usePopover.tsx +4 -1
  245. package/src/views/viewEvents.ts +55 -0
@@ -14,27 +14,276 @@ export function defineBaseContextMeta() {
14
14
  label: 'RunJS base',
15
15
  properties: {
16
16
  logger: 'Pino logger instance for structured logging. Example: `ctx.logger.info({ foo: 1 }, "message")`',
17
- message:
18
- 'Ant Design global message API for displaying temporary messages. Example: `ctx.message.success("Operation completed")`',
19
- notification:
20
- 'Ant Design notification API for displaying notification boxes. Example: `ctx.notification.open({ message: "Title", description: "Content" })`',
21
- resource: 'Data resource accessible based on current user permissions',
17
+ message: {
18
+ description: 'Ant Design global message API for displaying temporary messages.',
19
+ detail: 'MessageInstance',
20
+ hidden: (ctx: any) => !(ctx as any)?.message,
21
+ examples: ['ctx.message.success("Operation completed")'],
22
+ properties: {
23
+ info: {
24
+ type: 'function',
25
+ description: 'Show an info message.',
26
+ detail: '(content: any, duration?: number) => void',
27
+ completion: { insertText: `ctx.message.info('Info')` },
28
+ },
29
+ success: {
30
+ type: 'function',
31
+ description: 'Show a success message.',
32
+ detail: '(content: any, duration?: number) => void',
33
+ completion: { insertText: `ctx.message.success('Success')` },
34
+ },
35
+ error: {
36
+ type: 'function',
37
+ description: 'Show an error message.',
38
+ detail: '(content: any, duration?: number) => void',
39
+ completion: { insertText: `ctx.message.error('Error')` },
40
+ },
41
+ warning: {
42
+ type: 'function',
43
+ description: 'Show a warning message.',
44
+ detail: '(content: any, duration?: number) => void',
45
+ completion: { insertText: `ctx.message.warning('Warning')` },
46
+ },
47
+ loading: {
48
+ type: 'function',
49
+ description: 'Show a loading message.',
50
+ detail: '(content: any, duration?: number) => void',
51
+ completion: { insertText: `ctx.message.loading('Loading...')` },
52
+ },
53
+ open: {
54
+ type: 'function',
55
+ description: 'Open a message with custom config.',
56
+ detail: '(config: any) => void',
57
+ completion: { insertText: `ctx.message.open({ type: 'info', content: 'Hello' })` },
58
+ },
59
+ destroy: {
60
+ type: 'function',
61
+ description: 'Destroy all messages.',
62
+ detail: '() => void',
63
+ completion: { insertText: `ctx.message.destroy()` },
64
+ },
65
+ },
66
+ },
67
+ notification: {
68
+ description: 'Ant Design notification API for displaying notification boxes.',
69
+ detail: 'NotificationInstance',
70
+ hidden: (ctx: any) => !(ctx as any)?.notification,
71
+ examples: ['ctx.notification.open({ message: "Title", description: "Content" })'],
72
+ properties: {
73
+ open: {
74
+ type: 'function',
75
+ description: 'Open a notification with config.',
76
+ detail: '(config: any) => void',
77
+ completion: { insertText: `ctx.notification.open({ message: 'Title', description: 'Content' })` },
78
+ },
79
+ success: {
80
+ type: 'function',
81
+ description: 'Open a success notification.',
82
+ detail: '(config: any) => void',
83
+ completion: { insertText: `ctx.notification.success({ message: 'Success' })` },
84
+ },
85
+ info: {
86
+ type: 'function',
87
+ description: 'Open an info notification.',
88
+ detail: '(config: any) => void',
89
+ completion: { insertText: `ctx.notification.info({ message: 'Info' })` },
90
+ },
91
+ warning: {
92
+ type: 'function',
93
+ description: 'Open a warning notification.',
94
+ detail: '(config: any) => void',
95
+ completion: { insertText: `ctx.notification.warning({ message: 'Warning' })` },
96
+ },
97
+ error: {
98
+ type: 'function',
99
+ description: 'Open an error notification.',
100
+ detail: '(config: any) => void',
101
+ completion: { insertText: `ctx.notification.error({ message: 'Error' })` },
102
+ },
103
+ destroy: {
104
+ type: 'function',
105
+ description: 'Destroy all notifications.',
106
+ detail: '(key?: string) => void',
107
+ completion: { insertText: `ctx.notification.destroy()` },
108
+ },
109
+ },
110
+ },
111
+ modal: {
112
+ description: 'Ant Design modal API (HookAPI) for opening modal dialogs.',
113
+ detail: 'HookAPI',
114
+ hidden: (ctx: any) => !(ctx as any)?.modal,
115
+ examples: [`ctx.modal.confirm({ title: 'Confirm', content: 'Are you sure?' })`],
116
+ properties: {
117
+ info: {
118
+ type: 'function',
119
+ description: 'Open an info modal.',
120
+ detail: '(config: any) => void',
121
+ completion: { insertText: `ctx.modal.info({ title: 'Info', content: '...' })` },
122
+ },
123
+ success: {
124
+ type: 'function',
125
+ description: 'Open a success modal.',
126
+ detail: '(config: any) => void',
127
+ completion: { insertText: `ctx.modal.success({ title: 'Success', content: '...' })` },
128
+ },
129
+ error: {
130
+ type: 'function',
131
+ description: 'Open an error modal.',
132
+ detail: '(config: any) => void',
133
+ completion: { insertText: `ctx.modal.error({ title: 'Error', content: '...' })` },
134
+ },
135
+ warning: {
136
+ type: 'function',
137
+ description: 'Open a warning modal.',
138
+ detail: '(config: any) => void',
139
+ completion: { insertText: `ctx.modal.warning({ title: 'Warning', content: '...' })` },
140
+ },
141
+ confirm: {
142
+ type: 'function',
143
+ description: 'Open a confirm modal.',
144
+ detail: '(config: any) => void',
145
+ completion: { insertText: `ctx.modal.confirm({ title: 'Confirm', content: '...' })` },
146
+ },
147
+ },
148
+ },
149
+ // TODO: context meta
150
+ resource: {
151
+ description:
152
+ 'The current FlowResource instance in this context, used to access and manipulate data. In most block/popup scenarios it is pre-bound by the runtime (no need to call ctx.initResource). In contexts like plain JS blocks where no resource is bound, you can call ctx.initResource(type) first and then use ctx.resource.',
153
+ detail: 'FlowResource',
154
+ examples: ['await ctx.resource.refresh();'],
155
+ properties: {
156
+ // FlowResource
157
+ getData: {
158
+ description: 'Get current resource data.',
159
+ detail: '() => any',
160
+ completion: { insertText: 'ctx.resource.getData()' },
161
+ },
162
+ setData: {
163
+ description: 'Set current resource data (client-side only).',
164
+ detail: '(value: any) => this',
165
+ completion: { insertText: 'ctx.resource.setData(value)' },
166
+ },
167
+ refresh: {
168
+ description: 'Refresh data from server (available on API-backed resources).',
169
+ detail: '() => Promise<any>',
170
+ completion: { insertText: 'await ctx.resource.refresh()' },
171
+ },
172
+ on: {
173
+ description: 'Subscribe resource events (e.g., refresh).',
174
+ detail: '(event: string, callback: (...args) => void) => void',
175
+ completion: { insertText: "ctx.resource.on('refresh', () => {})" },
176
+ },
177
+ off: {
178
+ description: 'Unsubscribe resource events.',
179
+ detail: '(event: string, callback: (...args) => void) => void',
180
+ completion: { insertText: "ctx.resource.off('refresh', handler)" },
181
+ },
182
+ // BaseRecordResource / SingleRecordResource / MultiRecordResource helpers (common)
183
+ setResourceName: {
184
+ description: 'Set resource name (e.g., "users" or "users.profile").',
185
+ detail: '(resourceName: string) => this',
186
+ completion: { insertText: "ctx.resource.setResourceName('users')" },
187
+ },
188
+ setFilterByTk: {
189
+ description: 'Set primary key or filterByTk for record resources.',
190
+ detail: '(filterByTk: any) => this',
191
+ completion: { insertText: 'ctx.resource.setFilterByTk(filterByTk)' },
192
+ },
193
+ runAction: {
194
+ description: 'Run a resource action (create/update/destroy/custom actions).',
195
+ detail: '(action: string, options: any) => Promise<any>',
196
+ completion: { insertText: "await ctx.resource.runAction('create', { data: {} })" },
197
+ },
198
+ selectedRows: {
199
+ description:
200
+ 'Selected rows in table resources (typically for collection/table actions). Availability depends on resource type.',
201
+ detail: 'any[]',
202
+ },
203
+ pagination: {
204
+ description:
205
+ 'Pagination info in list resources. Availability depends on resource type (e.g., MultiRecordResource).',
206
+ detail: 'Record<string, any>',
207
+ },
208
+ },
209
+ },
22
210
  urlSearchParams: 'URLSearchParams object containing query parameters from the current URL',
23
211
  token: 'API authentication token for the current session',
24
212
  role: 'Current user role information',
25
- auth: 'Authentication context containing locale, role, user, and token information',
26
- api: {
27
- description: 'APIClient instance for making HTTP requests.',
28
- detail: 'APIClient',
213
+ auth: {
214
+ description: 'Authentication context containing locale, role, user, and token information.',
215
+ detail: 'AuthContext',
29
216
  properties: {
30
- request: {
31
- description:
32
- 'Make an HTTP request using the APIClient instance. Parameters: (options: RequestOptions) => Promise<any>.',
33
- detail: 'Promise<any>',
34
- completion: {
35
- insertText: `await ctx.api.request({ url: '', method: 'get', params: {} })`,
217
+ locale: 'Current locale code (e.g., "en-US", "zh-CN").',
218
+ roleName: 'Current role name.',
219
+ token: 'Current API token.',
220
+ user: 'Current user info object (if available).',
221
+ },
222
+ },
223
+ viewer: {
224
+ description: 'FlowViewer instance providing view helpers (drawer/dialog/popover/embed). ',
225
+ detail: 'FlowViewer',
226
+ examples: [
227
+ "await ctx.viewer.drawer({ width: '56%', content: <div>Hello</div> });",
228
+ 'await ctx.viewer.dialog({ content: <div>Confirm</div> });',
229
+ ],
230
+ properties: {
231
+ drawer: {
232
+ description: 'Open a drawer view. Parameters: (props: ViewProps) => any',
233
+ detail: '(props) => any',
234
+ completion: { insertText: "await ctx.viewer.drawer({ width: '56%', content: <div /> })" },
235
+ },
236
+ dialog: {
237
+ description: 'Open a dialog/modal view. Parameters: (props: ViewProps) => any',
238
+ detail: '(props) => any',
239
+ completion: { insertText: 'await ctx.viewer.dialog({ content: <div /> })' },
240
+ },
241
+ popover: {
242
+ description: 'Open a popover view. Parameters: (props: PopoverProps) => any',
243
+ detail: '(props) => any',
244
+ completion: { insertText: 'await ctx.viewer.popover({ target: ctx.element?.__el, content: <div /> })' },
245
+ },
246
+ embed: {
247
+ description: 'Open an embed view. Parameters: (props: ViewProps & TargetProps) => any',
248
+ detail: '(props) => any',
249
+ completion: { insertText: 'await ctx.viewer.embed({ target: document.body, content: <div /> })' },
250
+ },
251
+ },
252
+ },
253
+ popup: {
254
+ description:
255
+ 'Popup context when current view is opened as a popup/drawer. Recommended: `const popup = await ctx.getVar("ctx.popup")`.',
256
+ detail: 'Promise<PopupContext | undefined>',
257
+ hidden: async (ctx: any) => {
258
+ try {
259
+ const popup = await (ctx as any)?.popup;
260
+ return !popup?.uid;
261
+ } catch (_) {
262
+ // Fail-open: if we cannot determine, do not hide.
263
+ return false;
264
+ }
265
+ },
266
+ examples: [
267
+ 'const popup = await ctx.getVar("ctx.popup");',
268
+ 'const id = popup?.record?.id;',
269
+ 'const parentId = popup?.parent?.record?.id;',
270
+ ],
271
+ properties: {
272
+ uid: 'Popup view uid (string).',
273
+ record: 'Current popup record (object).',
274
+ sourceRecord: 'Parent/source record inferred from sourceId/associationName (object).',
275
+ resource: {
276
+ description: 'Data source info of the popup record.',
277
+ detail: 'PopupResourceInfo',
278
+ properties: {
279
+ dataSourceKey: 'Data source key (e.g., "main").',
280
+ collectionName: 'Collection name.',
281
+ associationName: 'Association resource name (optional).',
282
+ filterByTk: 'Record primary key / filterByTk.',
283
+ sourceId: 'Source id (optional).',
36
284
  },
37
285
  },
286
+ parent: 'Parent popup info (object). You can access parent.parent... at runtime if available.',
38
287
  },
39
288
  },
40
289
  i18n: {
@@ -44,25 +293,61 @@ export function defineBaseContextMeta() {
44
293
  language: 'Current active language code.',
45
294
  },
46
295
  },
47
- React:
48
- 'React namespace providing React library functions and hooks (available in RunJS environment). Recommended access path: `ctx.libs.React`.',
49
- ReactDOM:
50
- 'ReactDOM client API including createRoot for rendering React components. Also available via `ctx.libs.ReactDOM`.',
51
- antd: 'Ant Design component library. Recommended access path: `ctx.libs.antd`.',
52
296
  libs: {
53
- description: 'Namespace for third-party and shared libraries. Includes React, ReactDOM, Ant Design, and dayjs.',
54
- detail: 'Libraries namespace',
55
297
  properties: {
56
298
  React: 'React namespace (same as ctx.React).',
57
299
  ReactDOM: 'ReactDOM client API (same as ctx.ReactDOM).',
58
300
  antd: 'Ant Design component library (same as ctx.antd).',
59
301
  dayjs: 'dayjs date-time utility library.',
60
302
  antdIcons: 'Ant Design icons library. Example: `ctx.libs.antdIcons.PlusOutlined`.',
303
+ lodash: 'Lodash utility library. Example: `ctx.libs.lodash.get(obj, "a.b")`.',
304
+ formula: 'Formula.js library (spreadsheet-like functions). Example: `ctx.libs.formula.SUM(1, 2, 3)`.',
305
+ math: 'mathjs library. Example: `ctx.libs.math.evaluate("2 + 3")`.',
61
306
  },
62
307
  },
63
308
  },
64
309
  methods: {
65
- t: 'Internationalization function for translating text. Parameters: (key: string, variables?: object) => string. Example: `ctx.t("Hello {name}", { name: "World" })`',
310
+ request: {
311
+ description:
312
+ 'Make an HTTP request using the APIClient instance. Parameters: (options: RequestOptions) => Promise<any>.',
313
+ detail: '(options: RequestOptions) => Promise<any>',
314
+ completion: { insertText: `await ctx.request({ url: '', method: 'get', params: {} })` },
315
+ },
316
+ getModel: {
317
+ description:
318
+ 'Get a model instance by uid. By default, it searches across the current view stack and returns the first matched model.',
319
+ detail: '(uid: string, searchInPreviousEngines?: boolean) => FlowModel | undefined',
320
+ completion: { insertText: `ctx.getModel('block-uid-xxx')` },
321
+ params: [
322
+ {
323
+ name: 'uid',
324
+ type: 'string',
325
+ description: 'Target model uid.',
326
+ },
327
+ {
328
+ name: 'searchInPreviousEngines',
329
+ type: 'boolean',
330
+ description: 'Whether to search in parent engines (default: false).',
331
+ },
332
+ ],
333
+ returns: { type: 'FlowModel | undefined' },
334
+ examples: ["const model = ctx.getModel('block-uid-xxx');"],
335
+ },
336
+ t: 'Internationalization function for translating text. Parameters: (key: string, variables?: object) => string. Example: `ctx.t("Hello {{name}}", { name: "World" })`',
337
+ initResource: {
338
+ description:
339
+ 'Initialize ctx.resource as a FlowResource instance by class name. Common values: "MultiRecordResource", "SingleRecordResource", "SQLResource".',
340
+ detail: '(resourceType: ResourceType) => void',
341
+ completion: { insertText: "ctx.initResource('MultiRecordResource')" },
342
+ examples: ["ctx.initResource('MultiRecordResource'); ctx.resource.setResourceName('users');"],
343
+ },
344
+ makeResource: {
345
+ description:
346
+ 'Create a new resource instance without binding it to ctx.resource. Useful when you need multiple independent or temporary resources. Common values: "MultiRecordResource", "SingleRecordResource", "SQLResource".',
347
+ detail: '(resourceType) => FlowResource',
348
+ completion: { insertText: "const resource = ctx.makeResource('SingleRecordResource')" },
349
+ examples: ["const resource = ctx.makeResource('SingleRecordResource'); resource.setResourceName('users');"],
350
+ },
66
351
  render: {
67
352
  description:
68
353
  'Render into container. Accepts ReactElement, DOM Node/Fragment, or HTML string. Parameters: (vnode: ReactElement | Node | DocumentFragment | string, container?: HTMLElement|ElementProxy) => Root|null. Example: `ctx.render(<div>Hello</div>)` or `ctx.render("<b>hi</b>")`',
@@ -72,11 +357,60 @@ export function defineBaseContextMeta() {
72
357
  },
73
358
  },
74
359
  requireAsync:
75
- 'Asynchronously load external libraries from URL. Parameters: (url: string) => Promise<any>. Example: `const lodash = await ctx.requireAsync("https://cdn.jsdelivr.net/npm/lodash")`',
360
+ 'Load UMD/AMD/global scripts or CSS asynchronously from URL. Accepts shorthand like "echarts@5/dist/echarts.min.js" (resolved via ESM CDN with ?raw) or full URLs, and returns a Promise of the loaded library.',
76
361
  importAsync:
77
- 'Dynamically import ESM module by URL. Parameters: (url: string) => Promise<Module>. Example: `const mod = await ctx.importAsync("https://cdn.jsdelivr.net/npm/lit-html@2/+esm")`',
78
- resolveJsonTemplate:
79
- 'Resolve JSON templates containing variable expressions with {{ }} syntax. Parameters: (template: any, context?: object) => any',
362
+ 'Dynamically import ESM modules or CSS by URL. Accepts shorthand like "vue@3.4.0" or "dayjs@1/plugin/relativeTime.js" (resolved via configured ESM CDN) or full URLs, and returns a Promise of the module namespace.',
363
+ getVar: {
364
+ description: 'Resolve a ctx expression value by path string (expression starts with "ctx.").',
365
+ detail: '(path: string) => Promise<any>',
366
+ completion: { insertText: "await ctx.getVar('ctx.record.id')" },
367
+ params: [
368
+ {
369
+ name: 'path',
370
+ type: 'string',
371
+ description: 'Expression path starts with "ctx." (e.g. "ctx.record.id", "ctx.record.roles[0].id").',
372
+ },
373
+ ],
374
+ returns: { type: 'Promise<any>' },
375
+ examples: ["const id = await ctx.getVar('ctx.record.id');"],
376
+ },
377
+ getApiInfos: {
378
+ description: 'All available APIs under context namespace',
379
+ detail: '(options?: { version?: string }) => Promise<Record<string, any>>',
380
+ completion: { insertText: 'await ctx.getApiInfos()' },
381
+ params: [
382
+ {
383
+ name: 'options',
384
+ type: '{ version?: string }',
385
+ optional: true,
386
+ description: 'Options (e.g. version).',
387
+ },
388
+ ],
389
+ returns: { type: 'Promise<Record<string, any>>' },
390
+ examples: ['const apis = await ctx.getApiInfos();'],
391
+ },
392
+ getVarInfos: {
393
+ description: 'All available variables could be used to get deeper data.',
394
+ detail: '(options?: { path?: string|string[]; maxDepth?: number }) => Promise<Record<string, any>>',
395
+ completion: { insertText: "await ctx.getVarInfos({ path: 'record', maxDepth: 3 })" },
396
+ params: [
397
+ {
398
+ name: 'options',
399
+ type: '{ path?: string|string[]; maxDepth?: number }',
400
+ optional: true,
401
+ description: 'Options for path trimming and maxDepth expansion.',
402
+ },
403
+ ],
404
+ returns: { type: 'Promise<Record<string, any>>' },
405
+ examples: ["const vars = await ctx.getVarInfos({ path: 'record', maxDepth: 3 });"],
406
+ },
407
+ getEnvInfos: {
408
+ description: 'current runtime environment',
409
+ detail: '() => Promise<Record<string, any>>',
410
+ completion: { insertText: 'await ctx.getEnvInfos()' },
411
+ returns: { type: 'Promise<Record<string, any>>' },
412
+ examples: ['const envs = await ctx.getEnvInfos();'],
413
+ },
80
414
  runAction: {
81
415
  description:
82
416
  'Execute a data action on the current resource. Parameters: (actionName: string, params: object) => Promise<any>. Example: `await ctx.runAction("create", { values: { name: "test" } })`',
@@ -114,25 +448,262 @@ export function defineBaseContextMeta() {
114
448
  label: 'RunJS 基础',
115
449
  properties: {
116
450
  logger: 'Pino 日志实例(结构化日志)。示例:`ctx.logger.info({ foo: 1 }, "message")`',
117
- message: 'Ant Design 全局消息 API,用于显示临时提示。示例:`ctx.message.success("操作成功")`',
118
- notification:
119
- 'Ant Design 通知 API,用于显示通知框。示例:`ctx.notification.open({ message: "标题", description: "内容" })`',
120
- resource: '基于当前用户权限可访问的数据资源',
451
+ message: {
452
+ description: 'Ant Design 全局消息 API,用于显示临时提示。',
453
+ detail: 'MessageInstance',
454
+ hidden: (ctx: any) => !(ctx as any)?.message,
455
+ examples: ['ctx.message.success("操作成功")'],
456
+ properties: {
457
+ info: {
458
+ type: 'function',
459
+ description: '显示信息提示。',
460
+ detail: '(content: any, duration?: number) => void',
461
+ completion: { insertText: `ctx.message.info('提示')` },
462
+ },
463
+ success: {
464
+ type: 'function',
465
+ description: '显示成功提示。',
466
+ detail: '(content: any, duration?: number) => void',
467
+ completion: { insertText: `ctx.message.success('成功')` },
468
+ },
469
+ error: {
470
+ type: 'function',
471
+ description: '显示错误提示。',
472
+ detail: '(content: any, duration?: number) => void',
473
+ completion: { insertText: `ctx.message.error('错误')` },
474
+ },
475
+ warning: {
476
+ type: 'function',
477
+ description: '显示警告提示。',
478
+ detail: '(content: any, duration?: number) => void',
479
+ completion: { insertText: `ctx.message.warning('警告')` },
480
+ },
481
+ loading: {
482
+ type: 'function',
483
+ description: '显示加载提示。',
484
+ detail: '(content: any, duration?: number) => void',
485
+ completion: { insertText: `ctx.message.loading('加载中...')` },
486
+ },
487
+ open: {
488
+ type: 'function',
489
+ description: '使用自定义配置打开消息。',
490
+ detail: '(config: any) => void',
491
+ completion: { insertText: `ctx.message.open({ type: 'info', content: 'Hello' })` },
492
+ },
493
+ destroy: {
494
+ type: 'function',
495
+ description: '销毁所有消息。',
496
+ detail: '() => void',
497
+ completion: { insertText: `ctx.message.destroy()` },
498
+ },
499
+ },
500
+ },
501
+ notification: {
502
+ description: 'Ant Design 通知 API,用于显示通知框。',
503
+ detail: 'NotificationInstance',
504
+ hidden: (ctx: any) => !(ctx as any)?.notification,
505
+ examples: ['ctx.notification.open({ message: "标题", description: "内容" })'],
506
+ properties: {
507
+ open: {
508
+ type: 'function',
509
+ description: '打开通知。',
510
+ detail: '(config: any) => void',
511
+ completion: { insertText: `ctx.notification.open({ message: '标题', description: '内容' })` },
512
+ },
513
+ success: {
514
+ type: 'function',
515
+ description: '打开成功通知。',
516
+ detail: '(config: any) => void',
517
+ completion: { insertText: `ctx.notification.success({ message: '成功' })` },
518
+ },
519
+ info: {
520
+ type: 'function',
521
+ description: '打开信息通知。',
522
+ detail: '(config: any) => void',
523
+ completion: { insertText: `ctx.notification.info({ message: '提示' })` },
524
+ },
525
+ warning: {
526
+ type: 'function',
527
+ description: '打开警告通知。',
528
+ detail: '(config: any) => void',
529
+ completion: { insertText: `ctx.notification.warning({ message: '警告' })` },
530
+ },
531
+ error: {
532
+ type: 'function',
533
+ description: '打开错误通知。',
534
+ detail: '(config: any) => void',
535
+ completion: { insertText: `ctx.notification.error({ message: '错误' })` },
536
+ },
537
+ destroy: {
538
+ type: 'function',
539
+ description: '销毁通知。',
540
+ detail: '(key?: string) => void',
541
+ completion: { insertText: `ctx.notification.destroy()` },
542
+ },
543
+ },
544
+ },
545
+ modal: {
546
+ description: 'Ant Design modal API(HookAPI),用于打开对话框。',
547
+ detail: 'HookAPI',
548
+ hidden: (ctx: any) => !(ctx as any)?.modal,
549
+ examples: [`ctx.modal.confirm({ title: '确认', content: '确定继续?' })`],
550
+ properties: {
551
+ info: {
552
+ type: 'function',
553
+ description: '打开信息对话框。',
554
+ detail: '(config: any) => void',
555
+ completion: { insertText: `ctx.modal.info({ title: '提示', content: '...' })` },
556
+ },
557
+ success: {
558
+ type: 'function',
559
+ description: '打开成功对话框。',
560
+ detail: '(config: any) => void',
561
+ completion: { insertText: `ctx.modal.success({ title: '成功', content: '...' })` },
562
+ },
563
+ error: {
564
+ type: 'function',
565
+ description: '打开错误对话框。',
566
+ detail: '(config: any) => void',
567
+ completion: { insertText: `ctx.modal.error({ title: '错误', content: '...' })` },
568
+ },
569
+ warning: {
570
+ type: 'function',
571
+ description: '打开警告对话框。',
572
+ detail: '(config: any) => void',
573
+ completion: { insertText: `ctx.modal.warning({ title: '警告', content: '...' })` },
574
+ },
575
+ confirm: {
576
+ type: 'function',
577
+ description: '打开确认对话框。',
578
+ detail: '(config: any) => void',
579
+ completion: { insertText: `ctx.modal.confirm({ title: '确认', content: '...' })` },
580
+ },
581
+ },
582
+ },
583
+ resource: {
584
+ description:
585
+ '当前上下文中的 resource 实例(FlowResource),用于访问和操作数据。多数区块、弹窗等场景下运行环境会预先绑定 resource(无需手动调用 ctx.initResource)。对于 JS Block 等默认没有 resource 的场景,可通过 ctx.initResource(type) 初始化一个,再通过 ctx.resource 使用。',
586
+ detail: 'FlowResource',
587
+ examples: ['await ctx.resource.refresh();'],
588
+ properties: {
589
+ getData: {
590
+ description: '获取资源当前数据。',
591
+ detail: '() => any',
592
+ completion: { insertText: 'ctx.resource.getData()' },
593
+ },
594
+ setData: {
595
+ description: '设置资源当前数据(仅前端)。',
596
+ detail: '(value: any) => this',
597
+ completion: { insertText: 'ctx.resource.setData(value)' },
598
+ },
599
+ refresh: {
600
+ description: '从后端刷新数据(APIResource/RecordResource 等可用)。',
601
+ detail: '() => Promise<any>',
602
+ completion: { insertText: 'await ctx.resource.refresh()' },
603
+ },
604
+ on: {
605
+ description: '订阅资源事件(例如 refresh)。',
606
+ detail: '(event: string, callback: (...args) => void) => void',
607
+ completion: { insertText: "ctx.resource.on('refresh', () => {})" },
608
+ },
609
+ off: {
610
+ description: '取消订阅资源事件。',
611
+ detail: '(event: string, callback: (...args) => void) => void',
612
+ completion: { insertText: "ctx.resource.off('refresh', handler)" },
613
+ },
614
+ setResourceName: {
615
+ description: '设置资源名称(例如 "users" 或 "users.profile")。',
616
+ detail: '(resourceName: string) => this',
617
+ completion: { insertText: "ctx.resource.setResourceName('users')" },
618
+ },
619
+ setFilterByTk: {
620
+ description: '设置主键/过滤键 filterByTk(记录资源常用)。',
621
+ detail: '(filterByTk: any) => this',
622
+ completion: { insertText: 'ctx.resource.setFilterByTk(filterByTk)' },
623
+ },
624
+ runAction: {
625
+ description: '执行资源动作(create/update/destroy/自定义 action)。',
626
+ detail: '(action: string, options: any) => Promise<any>',
627
+ completion: { insertText: "await ctx.resource.runAction('create', { data: {} })" },
628
+ },
629
+ selectedRows: {
630
+ description: '列表资源的选中行(通常用于表格动作;是否存在取决于资源类型)。',
631
+ detail: 'any[]',
632
+ },
633
+ pagination: {
634
+ description: '列表资源的分页信息(是否存在取决于资源类型)。',
635
+ detail: 'Record<string, any>',
636
+ },
637
+ },
638
+ },
121
639
  urlSearchParams: '当前 URL 的查询参数(URLSearchParams 对象)',
122
640
  token: '当前会话的 API 认证 token',
123
641
  role: '当前用户角色信息',
124
- auth: '认证上下文,包含 locale、role、user、token 等信息',
125
- api: {
126
- description: '用于发起 HTTP 请求的 APIClient 实例',
127
- detail: 'APIClient',
642
+ auth: {
643
+ description: '认证上下文,包含 locale、role、user、token 等信息',
644
+ detail: 'AuthContext',
645
+ properties: {
646
+ locale: '当前 locale(例如 "en-US"、"zh-CN")。',
647
+ roleName: '当前角色名。',
648
+ token: '当前 API token。',
649
+ user: '当前用户信息对象(若可用)。',
650
+ },
651
+ },
652
+ viewer: {
653
+ description: '视图控制器(FlowViewer),提供 drawer/dialog/popover/embed 等交互能力。',
654
+ detail: 'FlowViewer',
655
+ examples: [
656
+ "await ctx.viewer.drawer({ width: '56%', content: <div /> });",
657
+ 'await ctx.viewer.dialog({ content: <div /> });',
658
+ ],
128
659
  properties: {
129
- request: {
130
- description: '通过 ctx.api.request 发起 HTTP 请求,入参为 RequestOptions,返回 Promise。',
131
- detail: 'Promise<any>',
132
- completion: {
133
- insertText: `await ctx.api.request({ url: '', method: 'get', params: {} })`,
660
+ drawer: {
661
+ description: '打开抽屉视图。参数:(props: ViewProps) => any',
662
+ detail: '(props) => any',
663
+ completion: { insertText: "await ctx.viewer.drawer({ width: '56%', content: <div /> })" },
664
+ },
665
+ dialog: {
666
+ description: '打开对话框视图。参数:(props: ViewProps) => any',
667
+ detail: '(props) => any',
668
+ completion: { insertText: 'await ctx.viewer.dialog({ content: <div /> })' },
669
+ },
670
+ popover: {
671
+ description: '打开气泡卡片视图。参数:(props: PopoverProps) => any',
672
+ detail: '(props) => any',
673
+ completion: { insertText: 'await ctx.viewer.popover({ target: ctx.element?.__el, content: <div /> })' },
674
+ },
675
+ embed: {
676
+ description: '打开内嵌视图。参数:(props: ViewProps & TargetProps) => any',
677
+ detail: '(props) => any',
678
+ completion: { insertText: 'await ctx.viewer.embed({ target: document.body, content: <div /> })' },
679
+ },
680
+ },
681
+ },
682
+ popup: {
683
+ description:
684
+ '弹窗上下文(在当前视图以弹窗/抽屉打开时可用)。推荐:`const popup = await ctx.getVar("ctx.popup")`。',
685
+ detail: 'Promise<PopupContext | undefined>',
686
+ examples: [
687
+ 'const popup = await ctx.getVar("ctx.popup");',
688
+ 'const id = popup?.record?.id;',
689
+ 'const parentId = popup?.parent?.record?.id;',
690
+ ],
691
+ properties: {
692
+ uid: '弹窗 view uid(string)',
693
+ record: '当前弹窗记录(object)',
694
+ sourceRecord: '根据 sourceId/associationName 推断的上级记录(object)',
695
+ resource: {
696
+ description: '弹窗记录的数据源信息。',
697
+ detail: 'PopupResourceInfo',
698
+ properties: {
699
+ dataSourceKey: '数据源 key(例如 "main")。',
700
+ collectionName: '集合名称。',
701
+ associationName: '关联资源名(可选)。',
702
+ filterByTk: '记录主键/过滤键 filterByTk。',
703
+ sourceId: 'sourceId(可选)。',
134
704
  },
135
705
  },
706
+ parent: '上级弹窗信息(object)。运行时若存在可访问 parent.parent... 链。',
136
707
  },
137
708
  },
138
709
  i18n: {
@@ -142,12 +713,19 @@ export function defineBaseContextMeta() {
142
713
  language: '当前激活的语言代码',
143
714
  },
144
715
  },
716
+ dayjs: {
717
+ type: 'function',
718
+ description: 'dayjs 日期时间工具库(可调用)。',
719
+ detail: 'dayjs',
720
+ completion: { insertText: 'ctx.dayjs()' },
721
+ examples: ["const now = ctx.dayjs().format('YYYY-MM-DD HH:mm:ss');"],
722
+ },
145
723
  React: 'React 命名空间,提供 React 函数与 hooks(RunJS 环境中可用)。推荐使用 `ctx.libs.React` 访问。',
146
724
  ReactDOM: 'ReactDOM 客户端 API,含 createRoot 等渲染方法。推荐通过 `ctx.libs.ReactDOM` 访问。',
147
725
  antd: 'Ant Design 组件库(RunJS 环境中可用)。推荐使用 `ctx.libs.antd` 访问。',
148
726
  libs: {
149
727
  description:
150
- '第三方/通用库的统一命名空间,包含 React、ReactDOM、Ant Design、dayjs 等。后续新增库会优先挂在此处。',
728
+ '第三方/通用库的统一命名空间,包含 React、ReactDOM、Ant Design、dayjs、icons 等,并可扩展更多工具库(如 lodash、formula、math)。后续新增库会优先挂在此处。',
151
729
  detail: '通用库命名空间',
152
730
  properties: {
153
731
  React: 'React 命名空间(等价于 ctx.React)。',
@@ -155,11 +733,53 @@ export function defineBaseContextMeta() {
155
733
  antd: 'Ant Design 组件库(等价于 ctx.antd)。',
156
734
  dayjs: 'dayjs 日期时间工具库。',
157
735
  antdIcons: 'Ant Design 图标库。 例如:`ctx.libs.antdIcons.PlusOutlined`。',
736
+ lodash: 'Lodash 工具库。示例:`ctx.libs.lodash.get(obj, "a.b")`。',
737
+ formula: 'Formula.js 公式库(类表格函数)。示例:`ctx.libs.formula.SUM(1, 2, 3)`。',
738
+ math: 'mathjs 数学库。示例:`ctx.libs.math.evaluate("2 + 3")`。',
158
739
  },
159
740
  },
160
741
  },
161
742
  methods: {
162
- t: '国际化函数,用于翻译文案。参数:(key: string, variables?: object) => string。示例:`ctx.t("你好 {name}", { name: "世界" })`',
743
+ request: {
744
+ description: '使用 APIClient 实例发起一个 HTTP 请求。参数:(options: RequestOptions) => Promise<any>',
745
+ detail: '(options: RequestOptions) => Promise<any>',
746
+ completion: { insertText: `await ctx.request({ url: '', method: 'get', params: {} })` },
747
+ },
748
+ getModel: {
749
+ description: '根据 uid 获取模型实例。默认会跨当前视图栈查找,并返回第一个命中的模型。',
750
+ detail: '(uid: string, searchInPreviousEngines?: boolean) => FlowModel | undefined',
751
+ completion: { insertText: `ctx.getModel('block-uid-xxx')` },
752
+ params: [
753
+ {
754
+ name: 'uid',
755
+ type: 'string',
756
+ description: '目标模型 uid。',
757
+ },
758
+ {
759
+ name: 'searchInPreviousEngines',
760
+ type: 'boolean',
761
+ optional: true,
762
+ description: '是否在之前的引擎中搜索模型,默认为 false。',
763
+ },
764
+ ],
765
+ returns: { type: 'FlowModel | undefined' },
766
+ examples: ["const model = ctx.getModel('block-uid-xxx');"],
767
+ },
768
+ t: '国际化函数,用于翻译文案。参数:(key: string, variables?: object) => string。示例:`ctx.t("你好 {{name}}", { name: "世界" })`',
769
+ initResource: {
770
+ description:
771
+ '初始化当前上下文的资源:若尚未存在 ctx.resource,则按资源类名创建并绑定;若已存在则直接复用。常用值:"MultiRecordResource"、"SingleRecordResource"、"SQLResource"。',
772
+ detail: '(resourceType: ResourceType) => void',
773
+ completion: { insertText: "ctx.initResource('MultiRecordResource')" },
774
+ examples: ["ctx.initResource('MultiRecordResource'); ctx.resource.setResourceName('users');"],
775
+ },
776
+ makeResource: {
777
+ description:
778
+ '创建一个新的资源实例,不会自动绑定到 ctx.resource。适合需要多个独立资源或临时资源的场景。常用值:"MultiRecordResource"、"SingleRecordResource"、"SQLResource"。',
779
+ detail: '(resourceType) => FlowResource',
780
+ completion: { insertText: "const resource = ctx.makeResource('SingleRecordResource')" },
781
+ examples: ["const resource = ctx.makeResource('SingleRecordResource'); resource.setResourceName('users');"],
782
+ },
163
783
  render: {
164
784
  description:
165
785
  '渲染到容器。vnode 支持 ReactElement、DOM 节点/片段、或 HTML 字符串。参数:(vnode: ReactElement | Node | DocumentFragment | string, container?: HTMLElement|ElementProxy) => Root|null。示例:`ctx.render(<div />)` 或 `ctx.render("<b>hi</b>")`',
@@ -169,9 +789,60 @@ export function defineBaseContextMeta() {
169
789
  },
170
790
  },
171
791
  requireAsync:
172
- '按 URL 异步加载外部库。参数:(url: string) => Promise<any>。示例:`const lodash = await ctx.requireAsync("https://cdn.jsdelivr.net/npm/lodash")`',
792
+ '按 URL 异步加载 UMD/AMD 或挂到全局的脚本,也可加载 CSS。支持简写路径(如 "echarts@5/dist/echarts.min.js",会经由 ESM CDN 加 ?raw 获取原始文件)和完整 URL,返回加载后的库对象或样式注入结果。',
173
793
  importAsync:
174
- '按 URL 动态导入 ESM 模块(开发/生产均可用)。参数:(url: string) => Promise<Module>。示例:`const mod = await ctx.importAsync("https://cdn.jsdelivr.net/npm/lit-html@2/+esm")`',
794
+ '按 URL 动态加载 ESM 模块或 CSS。支持简写(如 "vue@3.4.0"、"dayjs@1/plugin/relativeTime.js",会按配置拼接 ESM CDN 前缀)和完整 URL,返回模块命名空间或样式注入结果。',
795
+ getVar: {
796
+ description: '通过表达式路径字符串获取 ctx 的运行时值(以 "ctx." 开头)。',
797
+ detail: '(path: string) => Promise<any>',
798
+ completion: { insertText: "await ctx.getVar('ctx.record.id')" },
799
+ params: [
800
+ {
801
+ name: 'path',
802
+ type: 'string',
803
+ description: '以 "ctx." 开头的表达式路径(例如 "ctx.record.id" / "ctx.record.roles[0].id")。',
804
+ },
805
+ ],
806
+ returns: { type: 'Promise<any>' },
807
+ examples: ["const id = await ctx.getVar('ctx.record.id');"],
808
+ },
809
+ getApiInfos: {
810
+ description: '上下文命名空间下的所有可用 API',
811
+ detail: '(options?: { version?: string }) => Promise<Record<string, any>>',
812
+ completion: { insertText: 'await ctx.getApiInfos()' },
813
+ params: [
814
+ {
815
+ name: 'options',
816
+ type: '{ version?: string }',
817
+ optional: true,
818
+ description: '可选参数(例如 version)。',
819
+ },
820
+ ],
821
+ returns: { type: 'Promise<Record<string, any>>' },
822
+ examples: ['const apis = await ctx.getApiInfos();'],
823
+ },
824
+ getVarInfos: {
825
+ description: '所有可用变量,可用于获取更深层数据。',
826
+ detail: '(options?: { path?: string|string[]; maxDepth?: number }) => Promise<Record<string, any>>',
827
+ completion: { insertText: "await ctx.getVarInfos({ path: 'record', maxDepth: 3 })" },
828
+ params: [
829
+ {
830
+ name: 'options',
831
+ type: '{ path?: string|string[]; maxDepth?: number }',
832
+ optional: true,
833
+ description: 'path 剪裁与 maxDepth 展开参数。',
834
+ },
835
+ ],
836
+ returns: { type: 'Promise<Record<string, any>>' },
837
+ examples: ["const vars = await ctx.getVarInfos({ path: 'record', maxDepth: 3 });"],
838
+ },
839
+ getEnvInfos: {
840
+ description: '当前运行时环境',
841
+ detail: '() => Promise<Record<string, any>>',
842
+ completion: { insertText: 'await ctx.getEnvInfos()' },
843
+ returns: { type: 'Promise<Record<string, any>>' },
844
+ examples: ['const envs = await ctx.getEnvInfos();'],
845
+ },
175
846
  resolveJsonTemplate: '解析含 {{ }} 变量表达式的 JSON 模板。参数:(template: any, context?: object) => any',
176
847
  runAction: {
177
848
  description: