@nocobase/flow-engine 2.0.0-beta.8 → 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
@@ -36,26 +36,273 @@ function defineBaseContextMeta() {
36
36
  label: "RunJS base",
37
37
  properties: {
38
38
  logger: 'Pino logger instance for structured logging. Example: `ctx.logger.info({ foo: 1 }, "message")`',
39
- message: 'Ant Design global message API for displaying temporary messages. Example: `ctx.message.success("Operation completed")`',
40
- notification: 'Ant Design notification API for displaying notification boxes. Example: `ctx.notification.open({ message: "Title", description: "Content" })`',
41
- resource: "Data resource accessible based on current user permissions",
39
+ message: {
40
+ description: "Ant Design global message API for displaying temporary messages.",
41
+ detail: "MessageInstance",
42
+ hidden: /* @__PURE__ */ __name((ctx) => !(ctx == null ? void 0 : ctx.message), "hidden"),
43
+ examples: ['ctx.message.success("Operation completed")'],
44
+ properties: {
45
+ info: {
46
+ type: "function",
47
+ description: "Show an info message.",
48
+ detail: "(content: any, duration?: number) => void",
49
+ completion: { insertText: `ctx.message.info('Info')` }
50
+ },
51
+ success: {
52
+ type: "function",
53
+ description: "Show a success message.",
54
+ detail: "(content: any, duration?: number) => void",
55
+ completion: { insertText: `ctx.message.success('Success')` }
56
+ },
57
+ error: {
58
+ type: "function",
59
+ description: "Show an error message.",
60
+ detail: "(content: any, duration?: number) => void",
61
+ completion: { insertText: `ctx.message.error('Error')` }
62
+ },
63
+ warning: {
64
+ type: "function",
65
+ description: "Show a warning message.",
66
+ detail: "(content: any, duration?: number) => void",
67
+ completion: { insertText: `ctx.message.warning('Warning')` }
68
+ },
69
+ loading: {
70
+ type: "function",
71
+ description: "Show a loading message.",
72
+ detail: "(content: any, duration?: number) => void",
73
+ completion: { insertText: `ctx.message.loading('Loading...')` }
74
+ },
75
+ open: {
76
+ type: "function",
77
+ description: "Open a message with custom config.",
78
+ detail: "(config: any) => void",
79
+ completion: { insertText: `ctx.message.open({ type: 'info', content: 'Hello' })` }
80
+ },
81
+ destroy: {
82
+ type: "function",
83
+ description: "Destroy all messages.",
84
+ detail: "() => void",
85
+ completion: { insertText: `ctx.message.destroy()` }
86
+ }
87
+ }
88
+ },
89
+ notification: {
90
+ description: "Ant Design notification API for displaying notification boxes.",
91
+ detail: "NotificationInstance",
92
+ hidden: /* @__PURE__ */ __name((ctx) => !(ctx == null ? void 0 : ctx.notification), "hidden"),
93
+ examples: ['ctx.notification.open({ message: "Title", description: "Content" })'],
94
+ properties: {
95
+ open: {
96
+ type: "function",
97
+ description: "Open a notification with config.",
98
+ detail: "(config: any) => void",
99
+ completion: { insertText: `ctx.notification.open({ message: 'Title', description: 'Content' })` }
100
+ },
101
+ success: {
102
+ type: "function",
103
+ description: "Open a success notification.",
104
+ detail: "(config: any) => void",
105
+ completion: { insertText: `ctx.notification.success({ message: 'Success' })` }
106
+ },
107
+ info: {
108
+ type: "function",
109
+ description: "Open an info notification.",
110
+ detail: "(config: any) => void",
111
+ completion: { insertText: `ctx.notification.info({ message: 'Info' })` }
112
+ },
113
+ warning: {
114
+ type: "function",
115
+ description: "Open a warning notification.",
116
+ detail: "(config: any) => void",
117
+ completion: { insertText: `ctx.notification.warning({ message: 'Warning' })` }
118
+ },
119
+ error: {
120
+ type: "function",
121
+ description: "Open an error notification.",
122
+ detail: "(config: any) => void",
123
+ completion: { insertText: `ctx.notification.error({ message: 'Error' })` }
124
+ },
125
+ destroy: {
126
+ type: "function",
127
+ description: "Destroy all notifications.",
128
+ detail: "(key?: string) => void",
129
+ completion: { insertText: `ctx.notification.destroy()` }
130
+ }
131
+ }
132
+ },
133
+ modal: {
134
+ description: "Ant Design modal API (HookAPI) for opening modal dialogs.",
135
+ detail: "HookAPI",
136
+ hidden: /* @__PURE__ */ __name((ctx) => !(ctx == null ? void 0 : ctx.modal), "hidden"),
137
+ examples: [`ctx.modal.confirm({ title: 'Confirm', content: 'Are you sure?' })`],
138
+ properties: {
139
+ info: {
140
+ type: "function",
141
+ description: "Open an info modal.",
142
+ detail: "(config: any) => void",
143
+ completion: { insertText: `ctx.modal.info({ title: 'Info', content: '...' })` }
144
+ },
145
+ success: {
146
+ type: "function",
147
+ description: "Open a success modal.",
148
+ detail: "(config: any) => void",
149
+ completion: { insertText: `ctx.modal.success({ title: 'Success', content: '...' })` }
150
+ },
151
+ error: {
152
+ type: "function",
153
+ description: "Open an error modal.",
154
+ detail: "(config: any) => void",
155
+ completion: { insertText: `ctx.modal.error({ title: 'Error', content: '...' })` }
156
+ },
157
+ warning: {
158
+ type: "function",
159
+ description: "Open a warning modal.",
160
+ detail: "(config: any) => void",
161
+ completion: { insertText: `ctx.modal.warning({ title: 'Warning', content: '...' })` }
162
+ },
163
+ confirm: {
164
+ type: "function",
165
+ description: "Open a confirm modal.",
166
+ detail: "(config: any) => void",
167
+ completion: { insertText: `ctx.modal.confirm({ title: 'Confirm', content: '...' })` }
168
+ }
169
+ }
170
+ },
171
+ // TODO: context meta
172
+ resource: {
173
+ description: "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.",
174
+ detail: "FlowResource",
175
+ examples: ["await ctx.resource.refresh();"],
176
+ properties: {
177
+ // FlowResource
178
+ getData: {
179
+ description: "Get current resource data.",
180
+ detail: "() => any",
181
+ completion: { insertText: "ctx.resource.getData()" }
182
+ },
183
+ setData: {
184
+ description: "Set current resource data (client-side only).",
185
+ detail: "(value: any) => this",
186
+ completion: { insertText: "ctx.resource.setData(value)" }
187
+ },
188
+ refresh: {
189
+ description: "Refresh data from server (available on API-backed resources).",
190
+ detail: "() => Promise<any>",
191
+ completion: { insertText: "await ctx.resource.refresh()" }
192
+ },
193
+ on: {
194
+ description: "Subscribe resource events (e.g., refresh).",
195
+ detail: "(event: string, callback: (...args) => void) => void",
196
+ completion: { insertText: "ctx.resource.on('refresh', () => {})" }
197
+ },
198
+ off: {
199
+ description: "Unsubscribe resource events.",
200
+ detail: "(event: string, callback: (...args) => void) => void",
201
+ completion: { insertText: "ctx.resource.off('refresh', handler)" }
202
+ },
203
+ // BaseRecordResource / SingleRecordResource / MultiRecordResource helpers (common)
204
+ setResourceName: {
205
+ description: 'Set resource name (e.g., "users" or "users.profile").',
206
+ detail: "(resourceName: string) => this",
207
+ completion: { insertText: "ctx.resource.setResourceName('users')" }
208
+ },
209
+ setFilterByTk: {
210
+ description: "Set primary key or filterByTk for record resources.",
211
+ detail: "(filterByTk: any) => this",
212
+ completion: { insertText: "ctx.resource.setFilterByTk(filterByTk)" }
213
+ },
214
+ runAction: {
215
+ description: "Run a resource action (create/update/destroy/custom actions).",
216
+ detail: "(action: string, options: any) => Promise<any>",
217
+ completion: { insertText: "await ctx.resource.runAction('create', { data: {} })" }
218
+ },
219
+ selectedRows: {
220
+ description: "Selected rows in table resources (typically for collection/table actions). Availability depends on resource type.",
221
+ detail: "any[]"
222
+ },
223
+ pagination: {
224
+ description: "Pagination info in list resources. Availability depends on resource type (e.g., MultiRecordResource).",
225
+ detail: "Record<string, any>"
226
+ }
227
+ }
228
+ },
42
229
  urlSearchParams: "URLSearchParams object containing query parameters from the current URL",
43
230
  token: "API authentication token for the current session",
44
231
  role: "Current user role information",
45
- auth: "Authentication context containing locale, role, user, and token information",
46
- api: {
47
- description: "APIClient instance for making HTTP requests.",
48
- detail: "APIClient",
232
+ auth: {
233
+ description: "Authentication context containing locale, role, user, and token information.",
234
+ detail: "AuthContext",
49
235
  properties: {
50
- request: {
51
- description: "Make an HTTP request using the APIClient instance. Parameters: (options: RequestOptions) => Promise<any>.",
52
- detail: "Promise<any>",
53
- completion: {
54
- insertText: `await ctx.api.request({ url: '', method: 'get', params: {} })`
55
- }
236
+ locale: 'Current locale code (e.g., "en-US", "zh-CN").',
237
+ roleName: "Current role name.",
238
+ token: "Current API token.",
239
+ user: "Current user info object (if available)."
240
+ }
241
+ },
242
+ viewer: {
243
+ description: "FlowViewer instance providing view helpers (drawer/dialog/popover/embed). ",
244
+ detail: "FlowViewer",
245
+ examples: [
246
+ "await ctx.viewer.drawer({ width: '56%', content: <div>Hello</div> });",
247
+ "await ctx.viewer.dialog({ content: <div>Confirm</div> });"
248
+ ],
249
+ properties: {
250
+ drawer: {
251
+ description: "Open a drawer view. Parameters: (props: ViewProps) => any",
252
+ detail: "(props) => any",
253
+ completion: { insertText: "await ctx.viewer.drawer({ width: '56%', content: <div /> })" }
254
+ },
255
+ dialog: {
256
+ description: "Open a dialog/modal view. Parameters: (props: ViewProps) => any",
257
+ detail: "(props) => any",
258
+ completion: { insertText: "await ctx.viewer.dialog({ content: <div /> })" }
259
+ },
260
+ popover: {
261
+ description: "Open a popover view. Parameters: (props: PopoverProps) => any",
262
+ detail: "(props) => any",
263
+ completion: { insertText: "await ctx.viewer.popover({ target: ctx.element?.__el, content: <div /> })" }
264
+ },
265
+ embed: {
266
+ description: "Open an embed view. Parameters: (props: ViewProps & TargetProps) => any",
267
+ detail: "(props) => any",
268
+ completion: { insertText: "await ctx.viewer.embed({ target: document.body, content: <div /> })" }
56
269
  }
57
270
  }
58
271
  },
272
+ popup: {
273
+ description: 'Popup context when current view is opened as a popup/drawer. Recommended: `const popup = await ctx.getVar("ctx.popup")`.',
274
+ detail: "Promise<PopupContext | undefined>",
275
+ hidden: /* @__PURE__ */ __name(async (ctx) => {
276
+ try {
277
+ const popup = await (ctx == null ? void 0 : ctx.popup);
278
+ return !(popup == null ? void 0 : popup.uid);
279
+ } catch (_) {
280
+ return false;
281
+ }
282
+ }, "hidden"),
283
+ examples: [
284
+ 'const popup = await ctx.getVar("ctx.popup");',
285
+ "const id = popup?.record?.id;",
286
+ "const parentId = popup?.parent?.record?.id;"
287
+ ],
288
+ properties: {
289
+ uid: "Popup view uid (string).",
290
+ record: "Current popup record (object).",
291
+ sourceRecord: "Parent/source record inferred from sourceId/associationName (object).",
292
+ resource: {
293
+ description: "Data source info of the popup record.",
294
+ detail: "PopupResourceInfo",
295
+ properties: {
296
+ dataSourceKey: 'Data source key (e.g., "main").',
297
+ collectionName: "Collection name.",
298
+ associationName: "Association resource name (optional).",
299
+ filterByTk: "Record primary key / filterByTk.",
300
+ sourceId: "Source id (optional)."
301
+ }
302
+ },
303
+ parent: "Parent popup info (object). You can access parent.parent... at runtime if available."
304
+ }
305
+ },
59
306
  i18n: {
60
307
  description: "An instance of i18next for managing internationalization.",
61
308
  detail: "i18next",
@@ -63,23 +310,57 @@ function defineBaseContextMeta() {
63
310
  language: "Current active language code."
64
311
  }
65
312
  },
66
- React: "React namespace providing React library functions and hooks (available in RunJS environment). Recommended access path: `ctx.libs.React`.",
67
- ReactDOM: "ReactDOM client API including createRoot for rendering React components. Also available via `ctx.libs.ReactDOM`.",
68
- antd: "Ant Design component library. Recommended access path: `ctx.libs.antd`.",
69
313
  libs: {
70
- description: "Namespace for third-party and shared libraries. Includes React, ReactDOM, Ant Design, and dayjs.",
71
- detail: "Libraries namespace",
72
314
  properties: {
73
315
  React: "React namespace (same as ctx.React).",
74
316
  ReactDOM: "ReactDOM client API (same as ctx.ReactDOM).",
75
317
  antd: "Ant Design component library (same as ctx.antd).",
76
318
  dayjs: "dayjs date-time utility library.",
77
- antdIcons: "Ant Design icons library. Example: `ctx.libs.antdIcons.PlusOutlined`."
319
+ antdIcons: "Ant Design icons library. Example: `ctx.libs.antdIcons.PlusOutlined`.",
320
+ lodash: 'Lodash utility library. Example: `ctx.libs.lodash.get(obj, "a.b")`.',
321
+ formula: "Formula.js library (spreadsheet-like functions). Example: `ctx.libs.formula.SUM(1, 2, 3)`.",
322
+ math: 'mathjs library. Example: `ctx.libs.math.evaluate("2 + 3")`.'
78
323
  }
79
324
  }
80
325
  },
81
326
  methods: {
82
- t: 'Internationalization function for translating text. Parameters: (key: string, variables?: object) => string. Example: `ctx.t("Hello {name}", { name: "World" })`',
327
+ request: {
328
+ description: "Make an HTTP request using the APIClient instance. Parameters: (options: RequestOptions) => Promise<any>.",
329
+ detail: "(options: RequestOptions) => Promise<any>",
330
+ completion: { insertText: `await ctx.request({ url: '', method: 'get', params: {} })` }
331
+ },
332
+ getModel: {
333
+ description: "Get a model instance by uid. By default, it searches across the current view stack and returns the first matched model.",
334
+ detail: "(uid: string, searchInPreviousEngines?: boolean) => FlowModel | undefined",
335
+ completion: { insertText: `ctx.getModel('block-uid-xxx')` },
336
+ params: [
337
+ {
338
+ name: "uid",
339
+ type: "string",
340
+ description: "Target model uid."
341
+ },
342
+ {
343
+ name: "searchInPreviousEngines",
344
+ type: "boolean",
345
+ description: "Whether to search in parent engines (default: false)."
346
+ }
347
+ ],
348
+ returns: { type: "FlowModel | undefined" },
349
+ examples: ["const model = ctx.getModel('block-uid-xxx');"]
350
+ },
351
+ t: 'Internationalization function for translating text. Parameters: (key: string, variables?: object) => string. Example: `ctx.t("Hello {{name}}", { name: "World" })`',
352
+ initResource: {
353
+ description: 'Initialize ctx.resource as a FlowResource instance by class name. Common values: "MultiRecordResource", "SingleRecordResource", "SQLResource".',
354
+ detail: "(resourceType: ResourceType) => void",
355
+ completion: { insertText: "ctx.initResource('MultiRecordResource')" },
356
+ examples: ["ctx.initResource('MultiRecordResource'); ctx.resource.setResourceName('users');"]
357
+ },
358
+ makeResource: {
359
+ description: '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".',
360
+ detail: "(resourceType) => FlowResource",
361
+ completion: { insertText: "const resource = ctx.makeResource('SingleRecordResource')" },
362
+ examples: ["const resource = ctx.makeResource('SingleRecordResource'); resource.setResourceName('users');"]
363
+ },
83
364
  render: {
84
365
  description: '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>")`',
85
366
  detail: "ReactDOM Root",
@@ -87,9 +368,59 @@ function defineBaseContextMeta() {
87
368
  insertText: `ctx.render(<div />)`
88
369
  }
89
370
  },
90
- requireAsync: 'Asynchronously load external libraries from URL. Parameters: (url: string) => Promise<any>. Example: `const lodash = await ctx.requireAsync("https://cdn.jsdelivr.net/npm/lodash")`',
91
- importAsync: '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")`',
92
- resolveJsonTemplate: "Resolve JSON templates containing variable expressions with {{ }} syntax. Parameters: (template: any, context?: object) => any",
371
+ requireAsync: '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.',
372
+ importAsync: '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.',
373
+ getVar: {
374
+ description: 'Resolve a ctx expression value by path string (expression starts with "ctx.").',
375
+ detail: "(path: string) => Promise<any>",
376
+ completion: { insertText: "await ctx.getVar('ctx.record.id')" },
377
+ params: [
378
+ {
379
+ name: "path",
380
+ type: "string",
381
+ description: 'Expression path starts with "ctx." (e.g. "ctx.record.id", "ctx.record.roles[0].id").'
382
+ }
383
+ ],
384
+ returns: { type: "Promise<any>" },
385
+ examples: ["const id = await ctx.getVar('ctx.record.id');"]
386
+ },
387
+ getApiInfos: {
388
+ description: "All available APIs under context namespace",
389
+ detail: "(options?: { version?: string }) => Promise<Record<string, any>>",
390
+ completion: { insertText: "await ctx.getApiInfos()" },
391
+ params: [
392
+ {
393
+ name: "options",
394
+ type: "{ version?: string }",
395
+ optional: true,
396
+ description: "Options (e.g. version)."
397
+ }
398
+ ],
399
+ returns: { type: "Promise<Record<string, any>>" },
400
+ examples: ["const apis = await ctx.getApiInfos();"]
401
+ },
402
+ getVarInfos: {
403
+ description: "All available variables could be used to get deeper data.",
404
+ detail: "(options?: { path?: string|string[]; maxDepth?: number }) => Promise<Record<string, any>>",
405
+ completion: { insertText: "await ctx.getVarInfos({ path: 'record', maxDepth: 3 })" },
406
+ params: [
407
+ {
408
+ name: "options",
409
+ type: "{ path?: string|string[]; maxDepth?: number }",
410
+ optional: true,
411
+ description: "Options for path trimming and maxDepth expansion."
412
+ }
413
+ ],
414
+ returns: { type: "Promise<Record<string, any>>" },
415
+ examples: ["const vars = await ctx.getVarInfos({ path: 'record', maxDepth: 3 });"]
416
+ },
417
+ getEnvInfos: {
418
+ description: "current runtime environment",
419
+ detail: "() => Promise<Record<string, any>>",
420
+ completion: { insertText: "await ctx.getEnvInfos()" },
421
+ returns: { type: "Promise<Record<string, any>>" },
422
+ examples: ["const envs = await ctx.getEnvInfos();"]
423
+ },
93
424
  runAction: {
94
425
  description: 'Execute a data action on the current resource. Parameters: (actionName: string, params: object) => Promise<any>. Example: `await ctx.runAction("create", { values: { name: "test" } })`',
95
426
  detail: "Promise<any>",
@@ -125,26 +456,262 @@ function defineBaseContextMeta() {
125
456
  label: "RunJS \u57FA\u7840",
126
457
  properties: {
127
458
  logger: 'Pino \u65E5\u5FD7\u5B9E\u4F8B\uFF08\u7ED3\u6784\u5316\u65E5\u5FD7\uFF09\u3002\u793A\u4F8B\uFF1A`ctx.logger.info({ foo: 1 }, "message")`',
128
- message: 'Ant Design \u5168\u5C40\u6D88\u606F API\uFF0C\u7528\u4E8E\u663E\u793A\u4E34\u65F6\u63D0\u793A\u3002\u793A\u4F8B\uFF1A`ctx.message.success("\u64CD\u4F5C\u6210\u529F")`',
129
- notification: 'Ant Design \u901A\u77E5 API\uFF0C\u7528\u4E8E\u663E\u793A\u901A\u77E5\u6846\u3002\u793A\u4F8B\uFF1A`ctx.notification.open({ message: "\u6807\u9898", description: "\u5185\u5BB9" })`',
130
- resource: "\u57FA\u4E8E\u5F53\u524D\u7528\u6237\u6743\u9650\u53EF\u8BBF\u95EE\u7684\u6570\u636E\u8D44\u6E90",
459
+ message: {
460
+ description: "Ant Design \u5168\u5C40\u6D88\u606F API\uFF0C\u7528\u4E8E\u663E\u793A\u4E34\u65F6\u63D0\u793A\u3002",
461
+ detail: "MessageInstance",
462
+ hidden: /* @__PURE__ */ __name((ctx) => !(ctx == null ? void 0 : ctx.message), "hidden"),
463
+ examples: ['ctx.message.success("\u64CD\u4F5C\u6210\u529F")'],
464
+ properties: {
465
+ info: {
466
+ type: "function",
467
+ description: "\u663E\u793A\u4FE1\u606F\u63D0\u793A\u3002",
468
+ detail: "(content: any, duration?: number) => void",
469
+ completion: { insertText: `ctx.message.info('\u63D0\u793A')` }
470
+ },
471
+ success: {
472
+ type: "function",
473
+ description: "\u663E\u793A\u6210\u529F\u63D0\u793A\u3002",
474
+ detail: "(content: any, duration?: number) => void",
475
+ completion: { insertText: `ctx.message.success('\u6210\u529F')` }
476
+ },
477
+ error: {
478
+ type: "function",
479
+ description: "\u663E\u793A\u9519\u8BEF\u63D0\u793A\u3002",
480
+ detail: "(content: any, duration?: number) => void",
481
+ completion: { insertText: `ctx.message.error('\u9519\u8BEF')` }
482
+ },
483
+ warning: {
484
+ type: "function",
485
+ description: "\u663E\u793A\u8B66\u544A\u63D0\u793A\u3002",
486
+ detail: "(content: any, duration?: number) => void",
487
+ completion: { insertText: `ctx.message.warning('\u8B66\u544A')` }
488
+ },
489
+ loading: {
490
+ type: "function",
491
+ description: "\u663E\u793A\u52A0\u8F7D\u63D0\u793A\u3002",
492
+ detail: "(content: any, duration?: number) => void",
493
+ completion: { insertText: `ctx.message.loading('\u52A0\u8F7D\u4E2D...')` }
494
+ },
495
+ open: {
496
+ type: "function",
497
+ description: "\u4F7F\u7528\u81EA\u5B9A\u4E49\u914D\u7F6E\u6253\u5F00\u6D88\u606F\u3002",
498
+ detail: "(config: any) => void",
499
+ completion: { insertText: `ctx.message.open({ type: 'info', content: 'Hello' })` }
500
+ },
501
+ destroy: {
502
+ type: "function",
503
+ description: "\u9500\u6BC1\u6240\u6709\u6D88\u606F\u3002",
504
+ detail: "() => void",
505
+ completion: { insertText: `ctx.message.destroy()` }
506
+ }
507
+ }
508
+ },
509
+ notification: {
510
+ description: "Ant Design \u901A\u77E5 API\uFF0C\u7528\u4E8E\u663E\u793A\u901A\u77E5\u6846\u3002",
511
+ detail: "NotificationInstance",
512
+ hidden: /* @__PURE__ */ __name((ctx) => !(ctx == null ? void 0 : ctx.notification), "hidden"),
513
+ examples: ['ctx.notification.open({ message: "\u6807\u9898", description: "\u5185\u5BB9" })'],
514
+ properties: {
515
+ open: {
516
+ type: "function",
517
+ description: "\u6253\u5F00\u901A\u77E5\u3002",
518
+ detail: "(config: any) => void",
519
+ completion: { insertText: `ctx.notification.open({ message: '\u6807\u9898', description: '\u5185\u5BB9' })` }
520
+ },
521
+ success: {
522
+ type: "function",
523
+ description: "\u6253\u5F00\u6210\u529F\u901A\u77E5\u3002",
524
+ detail: "(config: any) => void",
525
+ completion: { insertText: `ctx.notification.success({ message: '\u6210\u529F' })` }
526
+ },
527
+ info: {
528
+ type: "function",
529
+ description: "\u6253\u5F00\u4FE1\u606F\u901A\u77E5\u3002",
530
+ detail: "(config: any) => void",
531
+ completion: { insertText: `ctx.notification.info({ message: '\u63D0\u793A' })` }
532
+ },
533
+ warning: {
534
+ type: "function",
535
+ description: "\u6253\u5F00\u8B66\u544A\u901A\u77E5\u3002",
536
+ detail: "(config: any) => void",
537
+ completion: { insertText: `ctx.notification.warning({ message: '\u8B66\u544A' })` }
538
+ },
539
+ error: {
540
+ type: "function",
541
+ description: "\u6253\u5F00\u9519\u8BEF\u901A\u77E5\u3002",
542
+ detail: "(config: any) => void",
543
+ completion: { insertText: `ctx.notification.error({ message: '\u9519\u8BEF' })` }
544
+ },
545
+ destroy: {
546
+ type: "function",
547
+ description: "\u9500\u6BC1\u901A\u77E5\u3002",
548
+ detail: "(key?: string) => void",
549
+ completion: { insertText: `ctx.notification.destroy()` }
550
+ }
551
+ }
552
+ },
553
+ modal: {
554
+ description: "Ant Design modal API\uFF08HookAPI\uFF09\uFF0C\u7528\u4E8E\u6253\u5F00\u5BF9\u8BDD\u6846\u3002",
555
+ detail: "HookAPI",
556
+ hidden: /* @__PURE__ */ __name((ctx) => !(ctx == null ? void 0 : ctx.modal), "hidden"),
557
+ examples: [`ctx.modal.confirm({ title: '\u786E\u8BA4', content: '\u786E\u5B9A\u7EE7\u7EED\uFF1F' })`],
558
+ properties: {
559
+ info: {
560
+ type: "function",
561
+ description: "\u6253\u5F00\u4FE1\u606F\u5BF9\u8BDD\u6846\u3002",
562
+ detail: "(config: any) => void",
563
+ completion: { insertText: `ctx.modal.info({ title: '\u63D0\u793A', content: '...' })` }
564
+ },
565
+ success: {
566
+ type: "function",
567
+ description: "\u6253\u5F00\u6210\u529F\u5BF9\u8BDD\u6846\u3002",
568
+ detail: "(config: any) => void",
569
+ completion: { insertText: `ctx.modal.success({ title: '\u6210\u529F', content: '...' })` }
570
+ },
571
+ error: {
572
+ type: "function",
573
+ description: "\u6253\u5F00\u9519\u8BEF\u5BF9\u8BDD\u6846\u3002",
574
+ detail: "(config: any) => void",
575
+ completion: { insertText: `ctx.modal.error({ title: '\u9519\u8BEF', content: '...' })` }
576
+ },
577
+ warning: {
578
+ type: "function",
579
+ description: "\u6253\u5F00\u8B66\u544A\u5BF9\u8BDD\u6846\u3002",
580
+ detail: "(config: any) => void",
581
+ completion: { insertText: `ctx.modal.warning({ title: '\u8B66\u544A', content: '...' })` }
582
+ },
583
+ confirm: {
584
+ type: "function",
585
+ description: "\u6253\u5F00\u786E\u8BA4\u5BF9\u8BDD\u6846\u3002",
586
+ detail: "(config: any) => void",
587
+ completion: { insertText: `ctx.modal.confirm({ title: '\u786E\u8BA4', content: '...' })` }
588
+ }
589
+ }
590
+ },
591
+ resource: {
592
+ description: "\u5F53\u524D\u4E0A\u4E0B\u6587\u4E2D\u7684 resource \u5B9E\u4F8B\uFF08FlowResource\uFF09\uFF0C\u7528\u4E8E\u8BBF\u95EE\u548C\u64CD\u4F5C\u6570\u636E\u3002\u591A\u6570\u533A\u5757\u3001\u5F39\u7A97\u7B49\u573A\u666F\u4E0B\u8FD0\u884C\u73AF\u5883\u4F1A\u9884\u5148\u7ED1\u5B9A resource\uFF08\u65E0\u9700\u624B\u52A8\u8C03\u7528 ctx.initResource\uFF09\u3002\u5BF9\u4E8E JS Block \u7B49\u9ED8\u8BA4\u6CA1\u6709 resource \u7684\u573A\u666F\uFF0C\u53EF\u901A\u8FC7 ctx.initResource(type) \u521D\u59CB\u5316\u4E00\u4E2A\uFF0C\u518D\u901A\u8FC7 ctx.resource \u4F7F\u7528\u3002",
593
+ detail: "FlowResource",
594
+ examples: ["await ctx.resource.refresh();"],
595
+ properties: {
596
+ getData: {
597
+ description: "\u83B7\u53D6\u8D44\u6E90\u5F53\u524D\u6570\u636E\u3002",
598
+ detail: "() => any",
599
+ completion: { insertText: "ctx.resource.getData()" }
600
+ },
601
+ setData: {
602
+ description: "\u8BBE\u7F6E\u8D44\u6E90\u5F53\u524D\u6570\u636E\uFF08\u4EC5\u524D\u7AEF\uFF09\u3002",
603
+ detail: "(value: any) => this",
604
+ completion: { insertText: "ctx.resource.setData(value)" }
605
+ },
606
+ refresh: {
607
+ description: "\u4ECE\u540E\u7AEF\u5237\u65B0\u6570\u636E\uFF08APIResource/RecordResource \u7B49\u53EF\u7528\uFF09\u3002",
608
+ detail: "() => Promise<any>",
609
+ completion: { insertText: "await ctx.resource.refresh()" }
610
+ },
611
+ on: {
612
+ description: "\u8BA2\u9605\u8D44\u6E90\u4E8B\u4EF6\uFF08\u4F8B\u5982 refresh\uFF09\u3002",
613
+ detail: "(event: string, callback: (...args) => void) => void",
614
+ completion: { insertText: "ctx.resource.on('refresh', () => {})" }
615
+ },
616
+ off: {
617
+ description: "\u53D6\u6D88\u8BA2\u9605\u8D44\u6E90\u4E8B\u4EF6\u3002",
618
+ detail: "(event: string, callback: (...args) => void) => void",
619
+ completion: { insertText: "ctx.resource.off('refresh', handler)" }
620
+ },
621
+ setResourceName: {
622
+ description: '\u8BBE\u7F6E\u8D44\u6E90\u540D\u79F0\uFF08\u4F8B\u5982 "users" \u6216 "users.profile"\uFF09\u3002',
623
+ detail: "(resourceName: string) => this",
624
+ completion: { insertText: "ctx.resource.setResourceName('users')" }
625
+ },
626
+ setFilterByTk: {
627
+ description: "\u8BBE\u7F6E\u4E3B\u952E/\u8FC7\u6EE4\u952E filterByTk\uFF08\u8BB0\u5F55\u8D44\u6E90\u5E38\u7528\uFF09\u3002",
628
+ detail: "(filterByTk: any) => this",
629
+ completion: { insertText: "ctx.resource.setFilterByTk(filterByTk)" }
630
+ },
631
+ runAction: {
632
+ description: "\u6267\u884C\u8D44\u6E90\u52A8\u4F5C\uFF08create/update/destroy/\u81EA\u5B9A\u4E49 action\uFF09\u3002",
633
+ detail: "(action: string, options: any) => Promise<any>",
634
+ completion: { insertText: "await ctx.resource.runAction('create', { data: {} })" }
635
+ },
636
+ selectedRows: {
637
+ description: "\u5217\u8868\u8D44\u6E90\u7684\u9009\u4E2D\u884C\uFF08\u901A\u5E38\u7528\u4E8E\u8868\u683C\u52A8\u4F5C\uFF1B\u662F\u5426\u5B58\u5728\u53D6\u51B3\u4E8E\u8D44\u6E90\u7C7B\u578B\uFF09\u3002",
638
+ detail: "any[]"
639
+ },
640
+ pagination: {
641
+ description: "\u5217\u8868\u8D44\u6E90\u7684\u5206\u9875\u4FE1\u606F\uFF08\u662F\u5426\u5B58\u5728\u53D6\u51B3\u4E8E\u8D44\u6E90\u7C7B\u578B\uFF09\u3002",
642
+ detail: "Record<string, any>"
643
+ }
644
+ }
645
+ },
131
646
  urlSearchParams: "\u5F53\u524D URL \u7684\u67E5\u8BE2\u53C2\u6570\uFF08URLSearchParams \u5BF9\u8C61\uFF09",
132
647
  token: "\u5F53\u524D\u4F1A\u8BDD\u7684 API \u8BA4\u8BC1 token",
133
648
  role: "\u5F53\u524D\u7528\u6237\u89D2\u8272\u4FE1\u606F",
134
- auth: "\u8BA4\u8BC1\u4E0A\u4E0B\u6587\uFF0C\u5305\u542B locale\u3001role\u3001user\u3001token \u7B49\u4FE1\u606F",
135
- api: {
136
- description: "\u7528\u4E8E\u53D1\u8D77 HTTP \u8BF7\u6C42\u7684 APIClient \u5B9E\u4F8B",
137
- detail: "APIClient",
649
+ auth: {
650
+ description: "\u8BA4\u8BC1\u4E0A\u4E0B\u6587\uFF0C\u5305\u542B locale\u3001role\u3001user\u3001token \u7B49\u4FE1\u606F",
651
+ detail: "AuthContext",
138
652
  properties: {
139
- request: {
140
- description: "\u901A\u8FC7 ctx.api.request \u53D1\u8D77 HTTP \u8BF7\u6C42\uFF0C\u5165\u53C2\u4E3A RequestOptions\uFF0C\u8FD4\u56DE Promise\u3002",
141
- detail: "Promise<any>",
142
- completion: {
143
- insertText: `await ctx.api.request({ url: '', method: 'get', params: {} })`
144
- }
653
+ locale: '\u5F53\u524D locale\uFF08\u4F8B\u5982 "en-US"\u3001"zh-CN"\uFF09\u3002',
654
+ roleName: "\u5F53\u524D\u89D2\u8272\u540D\u3002",
655
+ token: "\u5F53\u524D API token\u3002",
656
+ user: "\u5F53\u524D\u7528\u6237\u4FE1\u606F\u5BF9\u8C61\uFF08\u82E5\u53EF\u7528\uFF09\u3002"
657
+ }
658
+ },
659
+ viewer: {
660
+ description: "\u89C6\u56FE\u63A7\u5236\u5668\uFF08FlowViewer\uFF09\uFF0C\u63D0\u4F9B drawer/dialog/popover/embed \u7B49\u4EA4\u4E92\u80FD\u529B\u3002",
661
+ detail: "FlowViewer",
662
+ examples: [
663
+ "await ctx.viewer.drawer({ width: '56%', content: <div /> });",
664
+ "await ctx.viewer.dialog({ content: <div /> });"
665
+ ],
666
+ properties: {
667
+ drawer: {
668
+ description: "\u6253\u5F00\u62BD\u5C49\u89C6\u56FE\u3002\u53C2\u6570\uFF1A(props: ViewProps) => any",
669
+ detail: "(props) => any",
670
+ completion: { insertText: "await ctx.viewer.drawer({ width: '56%', content: <div /> })" }
671
+ },
672
+ dialog: {
673
+ description: "\u6253\u5F00\u5BF9\u8BDD\u6846\u89C6\u56FE\u3002\u53C2\u6570\uFF1A(props: ViewProps) => any",
674
+ detail: "(props) => any",
675
+ completion: { insertText: "await ctx.viewer.dialog({ content: <div /> })" }
676
+ },
677
+ popover: {
678
+ description: "\u6253\u5F00\u6C14\u6CE1\u5361\u7247\u89C6\u56FE\u3002\u53C2\u6570\uFF1A(props: PopoverProps) => any",
679
+ detail: "(props) => any",
680
+ completion: { insertText: "await ctx.viewer.popover({ target: ctx.element?.__el, content: <div /> })" }
681
+ },
682
+ embed: {
683
+ description: "\u6253\u5F00\u5185\u5D4C\u89C6\u56FE\u3002\u53C2\u6570\uFF1A(props: ViewProps & TargetProps) => any",
684
+ detail: "(props) => any",
685
+ completion: { insertText: "await ctx.viewer.embed({ target: document.body, content: <div /> })" }
145
686
  }
146
687
  }
147
688
  },
689
+ popup: {
690
+ description: '\u5F39\u7A97\u4E0A\u4E0B\u6587\uFF08\u5728\u5F53\u524D\u89C6\u56FE\u4EE5\u5F39\u7A97/\u62BD\u5C49\u6253\u5F00\u65F6\u53EF\u7528\uFF09\u3002\u63A8\u8350\uFF1A`const popup = await ctx.getVar("ctx.popup")`\u3002',
691
+ detail: "Promise<PopupContext | undefined>",
692
+ examples: [
693
+ 'const popup = await ctx.getVar("ctx.popup");',
694
+ "const id = popup?.record?.id;",
695
+ "const parentId = popup?.parent?.record?.id;"
696
+ ],
697
+ properties: {
698
+ uid: "\u5F39\u7A97 view uid\uFF08string\uFF09",
699
+ record: "\u5F53\u524D\u5F39\u7A97\u8BB0\u5F55\uFF08object\uFF09",
700
+ sourceRecord: "\u6839\u636E sourceId/associationName \u63A8\u65AD\u7684\u4E0A\u7EA7\u8BB0\u5F55\uFF08object\uFF09",
701
+ resource: {
702
+ description: "\u5F39\u7A97\u8BB0\u5F55\u7684\u6570\u636E\u6E90\u4FE1\u606F\u3002",
703
+ detail: "PopupResourceInfo",
704
+ properties: {
705
+ dataSourceKey: '\u6570\u636E\u6E90 key\uFF08\u4F8B\u5982 "main"\uFF09\u3002',
706
+ collectionName: "\u96C6\u5408\u540D\u79F0\u3002",
707
+ associationName: "\u5173\u8054\u8D44\u6E90\u540D\uFF08\u53EF\u9009\uFF09\u3002",
708
+ filterByTk: "\u8BB0\u5F55\u4E3B\u952E/\u8FC7\u6EE4\u952E filterByTk\u3002",
709
+ sourceId: "sourceId\uFF08\u53EF\u9009\uFF09\u3002"
710
+ }
711
+ },
712
+ parent: "\u4E0A\u7EA7\u5F39\u7A97\u4FE1\u606F\uFF08object\uFF09\u3002\u8FD0\u884C\u65F6\u82E5\u5B58\u5728\u53EF\u8BBF\u95EE parent.parent... \u94FE\u3002"
713
+ }
714
+ },
148
715
  i18n: {
149
716
  description: "i18next \u5B9E\u4F8B\uFF0C\u53EF\u7528\u4E8E\u7BA1\u7406\u56FD\u9645\u5316",
150
717
  detail: "i18next",
@@ -152,23 +719,70 @@ function defineBaseContextMeta() {
152
719
  language: "\u5F53\u524D\u6FC0\u6D3B\u7684\u8BED\u8A00\u4EE3\u7801"
153
720
  }
154
721
  },
722
+ dayjs: {
723
+ type: "function",
724
+ description: "dayjs \u65E5\u671F\u65F6\u95F4\u5DE5\u5177\u5E93\uFF08\u53EF\u8C03\u7528\uFF09\u3002",
725
+ detail: "dayjs",
726
+ completion: { insertText: "ctx.dayjs()" },
727
+ examples: ["const now = ctx.dayjs().format('YYYY-MM-DD HH:mm:ss');"]
728
+ },
155
729
  React: "React \u547D\u540D\u7A7A\u95F4\uFF0C\u63D0\u4F9B React \u51FD\u6570\u4E0E hooks\uFF08RunJS \u73AF\u5883\u4E2D\u53EF\u7528\uFF09\u3002\u63A8\u8350\u4F7F\u7528 `ctx.libs.React` \u8BBF\u95EE\u3002",
156
730
  ReactDOM: "ReactDOM \u5BA2\u6237\u7AEF API\uFF0C\u542B createRoot \u7B49\u6E32\u67D3\u65B9\u6CD5\u3002\u63A8\u8350\u901A\u8FC7 `ctx.libs.ReactDOM` \u8BBF\u95EE\u3002",
157
731
  antd: "Ant Design \u7EC4\u4EF6\u5E93\uFF08RunJS \u73AF\u5883\u4E2D\u53EF\u7528\uFF09\u3002\u63A8\u8350\u4F7F\u7528 `ctx.libs.antd` \u8BBF\u95EE\u3002",
158
732
  libs: {
159
- description: "\u7B2C\u4E09\u65B9/\u901A\u7528\u5E93\u7684\u7EDF\u4E00\u547D\u540D\u7A7A\u95F4\uFF0C\u5305\u542B React\u3001ReactDOM\u3001Ant Design\u3001dayjs \u7B49\u3002\u540E\u7EED\u65B0\u589E\u5E93\u4F1A\u4F18\u5148\u6302\u5728\u6B64\u5904\u3002",
733
+ description: "\u7B2C\u4E09\u65B9/\u901A\u7528\u5E93\u7684\u7EDF\u4E00\u547D\u540D\u7A7A\u95F4\uFF0C\u5305\u542B React\u3001ReactDOM\u3001Ant Design\u3001dayjs\u3001icons \u7B49\uFF0C\u5E76\u53EF\u6269\u5C55\u66F4\u591A\u5DE5\u5177\u5E93\uFF08\u5982 lodash\u3001formula\u3001math\uFF09\u3002\u540E\u7EED\u65B0\u589E\u5E93\u4F1A\u4F18\u5148\u6302\u5728\u6B64\u5904\u3002",
160
734
  detail: "\u901A\u7528\u5E93\u547D\u540D\u7A7A\u95F4",
161
735
  properties: {
162
736
  React: "React \u547D\u540D\u7A7A\u95F4\uFF08\u7B49\u4EF7\u4E8E ctx.React\uFF09\u3002",
163
737
  ReactDOM: "ReactDOM \u5BA2\u6237\u7AEF API\uFF08\u7B49\u4EF7\u4E8E ctx.ReactDOM\uFF09\u3002",
164
738
  antd: "Ant Design \u7EC4\u4EF6\u5E93\uFF08\u7B49\u4EF7\u4E8E ctx.antd\uFF09\u3002",
165
739
  dayjs: "dayjs \u65E5\u671F\u65F6\u95F4\u5DE5\u5177\u5E93\u3002",
166
- antdIcons: "Ant Design \u56FE\u6807\u5E93\u3002 \u4F8B\u5982\uFF1A`ctx.libs.antdIcons.PlusOutlined`\u3002"
740
+ antdIcons: "Ant Design \u56FE\u6807\u5E93\u3002 \u4F8B\u5982\uFF1A`ctx.libs.antdIcons.PlusOutlined`\u3002",
741
+ lodash: 'Lodash \u5DE5\u5177\u5E93\u3002\u793A\u4F8B\uFF1A`ctx.libs.lodash.get(obj, "a.b")`\u3002',
742
+ formula: "Formula.js \u516C\u5F0F\u5E93\uFF08\u7C7B\u8868\u683C\u51FD\u6570\uFF09\u3002\u793A\u4F8B\uFF1A`ctx.libs.formula.SUM(1, 2, 3)`\u3002",
743
+ math: 'mathjs \u6570\u5B66\u5E93\u3002\u793A\u4F8B\uFF1A`ctx.libs.math.evaluate("2 + 3")`\u3002'
167
744
  }
168
745
  }
169
746
  },
170
747
  methods: {
171
- t: '\u56FD\u9645\u5316\u51FD\u6570\uFF0C\u7528\u4E8E\u7FFB\u8BD1\u6587\u6848\u3002\u53C2\u6570\uFF1A(key: string, variables?: object) => string\u3002\u793A\u4F8B\uFF1A`ctx.t("\u4F60\u597D {name}", { name: "\u4E16\u754C" })`',
748
+ request: {
749
+ description: "\u4F7F\u7528 APIClient \u5B9E\u4F8B\u53D1\u8D77\u4E00\u4E2A HTTP \u8BF7\u6C42\u3002\u53C2\u6570\uFF1A(options: RequestOptions) => Promise<any>",
750
+ detail: "(options: RequestOptions) => Promise<any>",
751
+ completion: { insertText: `await ctx.request({ url: '', method: 'get', params: {} })` }
752
+ },
753
+ getModel: {
754
+ description: "\u6839\u636E uid \u83B7\u53D6\u6A21\u578B\u5B9E\u4F8B\u3002\u9ED8\u8BA4\u4F1A\u8DE8\u5F53\u524D\u89C6\u56FE\u6808\u67E5\u627E\uFF0C\u5E76\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u547D\u4E2D\u7684\u6A21\u578B\u3002",
755
+ detail: "(uid: string, searchInPreviousEngines?: boolean) => FlowModel | undefined",
756
+ completion: { insertText: `ctx.getModel('block-uid-xxx')` },
757
+ params: [
758
+ {
759
+ name: "uid",
760
+ type: "string",
761
+ description: "\u76EE\u6807\u6A21\u578B uid\u3002"
762
+ },
763
+ {
764
+ name: "searchInPreviousEngines",
765
+ type: "boolean",
766
+ optional: true,
767
+ description: "\u662F\u5426\u5728\u4E4B\u524D\u7684\u5F15\u64CE\u4E2D\u641C\u7D22\u6A21\u578B\uFF0C\u9ED8\u8BA4\u4E3A false\u3002"
768
+ }
769
+ ],
770
+ returns: { type: "FlowModel | undefined" },
771
+ examples: ["const model = ctx.getModel('block-uid-xxx');"]
772
+ },
773
+ t: '\u56FD\u9645\u5316\u51FD\u6570\uFF0C\u7528\u4E8E\u7FFB\u8BD1\u6587\u6848\u3002\u53C2\u6570\uFF1A(key: string, variables?: object) => string\u3002\u793A\u4F8B\uFF1A`ctx.t("\u4F60\u597D {{name}}", { name: "\u4E16\u754C" })`',
774
+ initResource: {
775
+ description: '\u521D\u59CB\u5316\u5F53\u524D\u4E0A\u4E0B\u6587\u7684\u8D44\u6E90\uFF1A\u82E5\u5C1A\u672A\u5B58\u5728 ctx.resource\uFF0C\u5219\u6309\u8D44\u6E90\u7C7B\u540D\u521B\u5EFA\u5E76\u7ED1\u5B9A\uFF1B\u82E5\u5DF2\u5B58\u5728\u5219\u76F4\u63A5\u590D\u7528\u3002\u5E38\u7528\u503C\uFF1A"MultiRecordResource"\u3001"SingleRecordResource"\u3001"SQLResource"\u3002',
776
+ detail: "(resourceType: ResourceType) => void",
777
+ completion: { insertText: "ctx.initResource('MultiRecordResource')" },
778
+ examples: ["ctx.initResource('MultiRecordResource'); ctx.resource.setResourceName('users');"]
779
+ },
780
+ makeResource: {
781
+ description: '\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684\u8D44\u6E90\u5B9E\u4F8B\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u7ED1\u5B9A\u5230 ctx.resource\u3002\u9002\u5408\u9700\u8981\u591A\u4E2A\u72EC\u7ACB\u8D44\u6E90\u6216\u4E34\u65F6\u8D44\u6E90\u7684\u573A\u666F\u3002\u5E38\u7528\u503C\uFF1A"MultiRecordResource"\u3001"SingleRecordResource"\u3001"SQLResource"\u3002',
782
+ detail: "(resourceType) => FlowResource",
783
+ completion: { insertText: "const resource = ctx.makeResource('SingleRecordResource')" },
784
+ examples: ["const resource = ctx.makeResource('SingleRecordResource'); resource.setResourceName('users');"]
785
+ },
172
786
  render: {
173
787
  description: '\u6E32\u67D3\u5230\u5BB9\u5668\u3002vnode \u652F\u6301 ReactElement\u3001DOM \u8282\u70B9/\u7247\u6BB5\u3001\u6216 HTML \u5B57\u7B26\u4E32\u3002\u53C2\u6570\uFF1A(vnode: ReactElement | Node | DocumentFragment | string, container?: HTMLElement|ElementProxy) => Root|null\u3002\u793A\u4F8B\uFF1A`ctx.render(<div />)` \u6216 `ctx.render("<b>hi</b>")`',
174
788
  detail: "ReactDOM Root",
@@ -176,8 +790,59 @@ function defineBaseContextMeta() {
176
790
  insertText: `ctx.render(<div />)`
177
791
  }
178
792
  },
179
- requireAsync: '\u6309 URL \u5F02\u6B65\u52A0\u8F7D\u5916\u90E8\u5E93\u3002\u53C2\u6570\uFF1A(url: string) => Promise<any>\u3002\u793A\u4F8B\uFF1A`const lodash = await ctx.requireAsync("https://cdn.jsdelivr.net/npm/lodash")`',
180
- importAsync: '\u6309 URL \u52A8\u6001\u5BFC\u5165 ESM \u6A21\u5757\uFF08\u5F00\u53D1/\u751F\u4EA7\u5747\u53EF\u7528\uFF09\u3002\u53C2\u6570\uFF1A(url: string) => Promise<Module>\u3002\u793A\u4F8B\uFF1A`const mod = await ctx.importAsync("https://cdn.jsdelivr.net/npm/lit-html@2/+esm")`',
793
+ requireAsync: '\u6309 URL \u5F02\u6B65\u52A0\u8F7D UMD/AMD \u6216\u6302\u5230\u5168\u5C40\u7684\u811A\u672C\uFF0C\u4E5F\u53EF\u52A0\u8F7D CSS\u3002\u652F\u6301\u7B80\u5199\u8DEF\u5F84\uFF08\u5982 "echarts@5/dist/echarts.min.js"\uFF0C\u4F1A\u7ECF\u7531 ESM CDN \u52A0 ?raw \u83B7\u53D6\u539F\u59CB\u6587\u4EF6\uFF09\u548C\u5B8C\u6574 URL\uFF0C\u8FD4\u56DE\u52A0\u8F7D\u540E\u7684\u5E93\u5BF9\u8C61\u6216\u6837\u5F0F\u6CE8\u5165\u7ED3\u679C\u3002',
794
+ importAsync: '\u6309 URL \u52A8\u6001\u52A0\u8F7D ESM \u6A21\u5757\u6216 CSS\u3002\u652F\u6301\u7B80\u5199\uFF08\u5982 "vue@3.4.0"\u3001"dayjs@1/plugin/relativeTime.js"\uFF0C\u4F1A\u6309\u914D\u7F6E\u62FC\u63A5 ESM CDN \u524D\u7F00\uFF09\u548C\u5B8C\u6574 URL\uFF0C\u8FD4\u56DE\u6A21\u5757\u547D\u540D\u7A7A\u95F4\u6216\u6837\u5F0F\u6CE8\u5165\u7ED3\u679C\u3002',
795
+ getVar: {
796
+ description: '\u901A\u8FC7\u8868\u8FBE\u5F0F\u8DEF\u5F84\u5B57\u7B26\u4E32\u83B7\u53D6 ctx \u7684\u8FD0\u884C\u65F6\u503C\uFF08\u4EE5 "ctx." \u5F00\u5934\uFF09\u3002',
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: '\u4EE5 "ctx." \u5F00\u5934\u7684\u8868\u8FBE\u5F0F\u8DEF\u5F84\uFF08\u4F8B\u5982 "ctx.record.id" / "ctx.record.roles[0].id"\uFF09\u3002'
804
+ }
805
+ ],
806
+ returns: { type: "Promise<any>" },
807
+ examples: ["const id = await ctx.getVar('ctx.record.id');"]
808
+ },
809
+ getApiInfos: {
810
+ description: "\u4E0A\u4E0B\u6587\u547D\u540D\u7A7A\u95F4\u4E0B\u7684\u6240\u6709\u53EF\u7528 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: "\u53EF\u9009\u53C2\u6570\uFF08\u4F8B\u5982 version\uFF09\u3002"
819
+ }
820
+ ],
821
+ returns: { type: "Promise<Record<string, any>>" },
822
+ examples: ["const apis = await ctx.getApiInfos();"]
823
+ },
824
+ getVarInfos: {
825
+ description: "\u6240\u6709\u53EF\u7528\u53D8\u91CF\uFF0C\u53EF\u7528\u4E8E\u83B7\u53D6\u66F4\u6DF1\u5C42\u6570\u636E\u3002",
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 \u526A\u88C1\u4E0E maxDepth \u5C55\u5F00\u53C2\u6570\u3002"
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: "\u5F53\u524D\u8FD0\u884C\u65F6\u73AF\u5883",
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
+ },
181
846
  resolveJsonTemplate: "\u89E3\u6790\u542B {{ }} \u53D8\u91CF\u8868\u8FBE\u5F0F\u7684 JSON \u6A21\u677F\u3002\u53C2\u6570\uFF1A(template: any, context?: object) => any",
182
847
  runAction: {
183
848
  description: '\u5BF9\u5F53\u524D\u8D44\u6E90\u6267\u884C\u6570\u636E\u52A8\u4F5C\u3002\u53C2\u6570\uFF1A(actionName: string, params: object) => Promise<any>\u3002\u793A\u4F8B\uFF1A`await ctx.runAction("create", { values: { name: "test" } })`',