@nocobase/flow-engine 2.0.0-alpha.2

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 (597) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +30 -0
  3. package/lib/ContextPathProxy.d.ts +17 -0
  4. package/lib/ContextPathProxy.js +65 -0
  5. package/lib/ElementProxy.d.ts +17 -0
  6. package/lib/ElementProxy.js +93 -0
  7. package/lib/FlowContextProvider.d.ts +24 -0
  8. package/lib/FlowContextProvider.js +82 -0
  9. package/lib/FlowDefinition.d.ts +423 -0
  10. package/lib/FlowDefinition.js +257 -0
  11. package/lib/JSRunner.d.ts +32 -0
  12. package/lib/JSRunner.js +95 -0
  13. package/lib/ReactView.d.ts +20 -0
  14. package/lib/ReactView.js +120 -0
  15. package/lib/ViewScopedFlowEngine.d.ts +23 -0
  16. package/lib/ViewScopedFlowEngine.js +81 -0
  17. package/lib/acl/Acl.d.ts +31 -0
  18. package/lib/acl/Acl.js +115 -0
  19. package/lib/action-registry/BaseActionRegistry.d.ts +23 -0
  20. package/lib/action-registry/BaseActionRegistry.js +57 -0
  21. package/lib/action-registry/EngineActionRegistry.d.ts +20 -0
  22. package/lib/action-registry/EngineActionRegistry.js +47 -0
  23. package/lib/action-registry/ModelActionRegistry.d.ts +34 -0
  24. package/lib/action-registry/ModelActionRegistry.js +79 -0
  25. package/lib/components/DynamicFlowsEditor.d.ts +17 -0
  26. package/lib/components/DynamicFlowsEditor.js +49 -0
  27. package/lib/components/FieldModelRenderer.d.ts +10 -0
  28. package/lib/components/FieldModelRenderer.js +94 -0
  29. package/lib/components/FlowContextSelector.d.ts +11 -0
  30. package/lib/components/FlowContextSelector.js +221 -0
  31. package/lib/components/FlowErrorFallback.d.ts +25 -0
  32. package/lib/components/FlowErrorFallback.js +264 -0
  33. package/lib/components/FlowModelRenderer.d.ts +64 -0
  34. package/lib/components/FlowModelRenderer.js +254 -0
  35. package/lib/components/FormItem.d.ts +18 -0
  36. package/lib/components/FormItem.js +147 -0
  37. package/lib/components/common/FlowSettingsButton.d.ts +11 -0
  38. package/lib/components/common/FlowSettingsButton.js +66 -0
  39. package/lib/components/common/index.d.ts +9 -0
  40. package/lib/components/common/index.js +30 -0
  41. package/lib/components/common/withFlowDesignMode.d.ts +26 -0
  42. package/lib/components/common/withFlowDesignMode.js +61 -0
  43. package/lib/components/dnd/getMousePositionOnElement.d.ts +50 -0
  44. package/lib/components/dnd/getMousePositionOnElement.js +95 -0
  45. package/lib/components/dnd/index.d.ts +24 -0
  46. package/lib/components/dnd/index.js +164 -0
  47. package/lib/components/dnd/moveBlock.d.ts +33 -0
  48. package/lib/components/dnd/moveBlock.js +302 -0
  49. package/lib/components/index.d.ts +18 -0
  50. package/lib/components/index.js +48 -0
  51. package/lib/components/settings/independents/dropdown/FlowsDropdownButton.d.ts +46 -0
  52. package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +225 -0
  53. package/lib/components/settings/independents/dropdown/index.d.ts +9 -0
  54. package/lib/components/settings/independents/dropdown/index.js +30 -0
  55. package/lib/components/settings/independents/index.d.ts +1 -0
  56. package/lib/components/settings/independents/index.js +30 -0
  57. package/lib/components/settings/index.d.ts +10 -0
  58. package/lib/components/settings/index.js +32 -0
  59. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.d.ts +24 -0
  60. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +501 -0
  61. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.d.ts +45 -0
  62. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +231 -0
  63. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +111 -0
  64. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +484 -0
  65. package/lib/components/settings/wrappers/contextual/StepRequiredSettingsDialog.d.ts +26 -0
  66. package/lib/components/settings/wrappers/contextual/StepRequiredSettingsDialog.js +342 -0
  67. package/lib/components/settings/wrappers/contextual/StepSettings.d.ts +23 -0
  68. package/lib/components/settings/wrappers/contextual/StepSettings.js +110 -0
  69. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.d.ts +20 -0
  70. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +206 -0
  71. package/lib/components/settings/wrappers/contextual/StepSettingsDrawer.d.ts +20 -0
  72. package/lib/components/settings/wrappers/contextual/StepSettingsDrawer.js +47 -0
  73. package/lib/components/settings/wrappers/contextual/index.d.ts +14 -0
  74. package/lib/components/settings/wrappers/contextual/index.js +40 -0
  75. package/lib/components/settings/wrappers/embedded/FlowSettings.d.ts +33 -0
  76. package/lib/components/settings/wrappers/embedded/FlowSettings.js +207 -0
  77. package/lib/components/settings/wrappers/embedded/FlowsSettings.d.ts +41 -0
  78. package/lib/components/settings/wrappers/embedded/FlowsSettings.js +84 -0
  79. package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.d.ts +16 -0
  80. package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.js +88 -0
  81. package/lib/components/settings/wrappers/embedded/index.d.ts +10 -0
  82. package/lib/components/settings/wrappers/embedded/index.js +32 -0
  83. package/lib/components/settings/wrappers/index.d.ts +2 -0
  84. package/lib/components/settings/wrappers/index.js +32 -0
  85. package/lib/components/subModel/AddSubModelButton.d.ts +62 -0
  86. package/lib/components/subModel/AddSubModelButton.js +415 -0
  87. package/lib/components/subModel/LazyDropdown.d.ts +55 -0
  88. package/lib/components/subModel/LazyDropdown.js +524 -0
  89. package/lib/components/subModel/index.d.ts +10 -0
  90. package/lib/components/subModel/index.js +32 -0
  91. package/lib/components/subModel/utils.d.ts +34 -0
  92. package/lib/components/subModel/utils.js +287 -0
  93. package/lib/components/variables/InlineVariableTag.d.ts +21 -0
  94. package/lib/components/variables/InlineVariableTag.js +123 -0
  95. package/lib/components/variables/SlateVariableEditor.d.ts +46 -0
  96. package/lib/components/variables/SlateVariableEditor.js +302 -0
  97. package/lib/components/variables/VariableInput.d.ts +11 -0
  98. package/lib/components/variables/VariableInput.js +322 -0
  99. package/lib/components/variables/VariableTag.d.ts +11 -0
  100. package/lib/components/variables/VariableTag.js +148 -0
  101. package/lib/components/variables/VariableTrigger.d.ts +20 -0
  102. package/lib/components/variables/VariableTrigger.js +136 -0
  103. package/lib/components/variables/index.d.ts +15 -0
  104. package/lib/components/variables/index.js +53 -0
  105. package/lib/components/variables/types.d.ts +93 -0
  106. package/lib/components/variables/types.js +24 -0
  107. package/lib/components/variables/useResolvedMetaTree.d.ts +19 -0
  108. package/lib/components/variables/useResolvedMetaTree.js +91 -0
  109. package/lib/components/variables/utils.d.ts +22 -0
  110. package/lib/components/variables/utils.js +177 -0
  111. package/lib/data-source/index.d.ts +180 -0
  112. package/lib/data-source/index.js +733 -0
  113. package/lib/data-source/jioToJoiSchema.d.ts +19 -0
  114. package/lib/data-source/jioToJoiSchema.js +114 -0
  115. package/lib/decorators/index.d.ts +9 -0
  116. package/lib/decorators/index.js +36 -0
  117. package/lib/decorators/largeField.d.ts +9 -0
  118. package/lib/decorators/largeField.js +42 -0
  119. package/lib/emitter.d.ts +16 -0
  120. package/lib/emitter.js +58 -0
  121. package/lib/event-registry/BaseEventRegistry.d.ts +22 -0
  122. package/lib/event-registry/BaseEventRegistry.js +57 -0
  123. package/lib/event-registry/EngineEventRegistry.d.ts +19 -0
  124. package/lib/event-registry/EngineEventRegistry.js +47 -0
  125. package/lib/event-registry/ModelEventRegistry.d.ts +33 -0
  126. package/lib/event-registry/ModelEventRegistry.js +79 -0
  127. package/lib/executor/FlowExecutor.d.ts +26 -0
  128. package/lib/executor/FlowExecutor.js +262 -0
  129. package/lib/flow-registry/BaseFlowRegistry.d.ts +46 -0
  130. package/lib/flow-registry/BaseFlowRegistry.js +86 -0
  131. package/lib/flow-registry/GlobalFlowRegistry.d.ts +22 -0
  132. package/lib/flow-registry/GlobalFlowRegistry.js +95 -0
  133. package/lib/flow-registry/InstanceFlowRegistry.d.ts +21 -0
  134. package/lib/flow-registry/InstanceFlowRegistry.js +59 -0
  135. package/lib/flow-registry/index.d.ts +11 -0
  136. package/lib/flow-registry/index.js +34 -0
  137. package/lib/flowContext.d.ts +215 -0
  138. package/lib/flowContext.js +1266 -0
  139. package/lib/flowEngine.d.ts +340 -0
  140. package/lib/flowEngine.js +781 -0
  141. package/lib/flowI18n.d.ts +46 -0
  142. package/lib/flowI18n.js +117 -0
  143. package/lib/flowSettings.d.ts +266 -0
  144. package/lib/flowSettings.js +850 -0
  145. package/lib/hooks/index.d.ts +14 -0
  146. package/lib/hooks/index.js +40 -0
  147. package/lib/hooks/useApplyAutoFlows.d.ts +21 -0
  148. package/lib/hooks/useApplyAutoFlows.js +62 -0
  149. package/lib/hooks/useFlowModel.d.ts +29 -0
  150. package/lib/hooks/useFlowModel.js +72 -0
  151. package/lib/hooks/useFlowModelById.d.ts +11 -0
  152. package/lib/hooks/useFlowModelById.js +61 -0
  153. package/lib/hooks/useFlowSettingsContext.d.ts +20 -0
  154. package/lib/hooks/useFlowSettingsContext.js +61 -0
  155. package/lib/hooks/useFlowStep.d.ts +17 -0
  156. package/lib/hooks/useFlowStep.js +56 -0
  157. package/lib/hooks/useNiceDropdownMaxHeight.d.ts +13 -0
  158. package/lib/hooks/useNiceDropdownMaxHeight.js +52 -0
  159. package/lib/index.d.ts +27 -0
  160. package/lib/index.js +73 -0
  161. package/lib/locale/en-US.json +61 -0
  162. package/lib/locale/index.d.ts +141 -0
  163. package/lib/locale/index.js +70 -0
  164. package/lib/locale/zh-CN.json +61 -0
  165. package/lib/models/CollectionFieldModel.d.ts +50 -0
  166. package/lib/models/CollectionFieldModel.js +242 -0
  167. package/lib/models/DisplayItemModel.d.ts +12 -0
  168. package/lib/models/DisplayItemModel.js +41 -0
  169. package/lib/models/EditableItemModel.d.ts +12 -0
  170. package/lib/models/EditableItemModel.js +41 -0
  171. package/lib/models/FilterableItemModel.d.ts +12 -0
  172. package/lib/models/FilterableItemModel.js +41 -0
  173. package/lib/models/flowModel.d.ts +344 -0
  174. package/lib/models/flowModel.js +1133 -0
  175. package/lib/models/forkFlowModel.d.ts +83 -0
  176. package/lib/models/forkFlowModel.js +257 -0
  177. package/lib/models/index.d.ts +14 -0
  178. package/lib/models/index.js +40 -0
  179. package/lib/provider.d.ts +22 -0
  180. package/lib/provider.js +114 -0
  181. package/lib/resources/apiResource.d.ts +34 -0
  182. package/lib/resources/apiResource.js +153 -0
  183. package/lib/resources/baseRecordResource.d.ts +61 -0
  184. package/lib/resources/baseRecordResource.js +264 -0
  185. package/lib/resources/filterItem.d.ts +33 -0
  186. package/lib/resources/filterItem.js +93 -0
  187. package/lib/resources/flowResource.d.ts +45 -0
  188. package/lib/resources/flowResource.js +146 -0
  189. package/lib/resources/index.d.ts +15 -0
  190. package/lib/resources/index.js +42 -0
  191. package/lib/resources/multiRecordResource.d.ts +53 -0
  192. package/lib/resources/multiRecordResource.js +230 -0
  193. package/lib/resources/singleRecordResource.d.ts +23 -0
  194. package/lib/resources/singleRecordResource.js +111 -0
  195. package/lib/resources/sqlResource.d.ts +73 -0
  196. package/lib/resources/sqlResource.js +294 -0
  197. package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +38 -0
  198. package/lib/runjs-context/contexts/FlowRunJSContext.js +217 -0
  199. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +16 -0
  200. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +66 -0
  201. package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +16 -0
  202. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +78 -0
  203. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +12 -0
  204. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +59 -0
  205. package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +16 -0
  206. package/lib/runjs-context/contexts/JSFieldRunJSContext.js +70 -0
  207. package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +16 -0
  208. package/lib/runjs-context/contexts/JSItemRunJSContext.js +66 -0
  209. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +12 -0
  210. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +61 -0
  211. package/lib/runjs-context/contexts/LinkageRunJSContext.d.ts +12 -0
  212. package/lib/runjs-context/contexts/LinkageRunJSContext.js +62 -0
  213. package/lib/runjs-context/helpers.d.ts +17 -0
  214. package/lib/runjs-context/helpers.js +79 -0
  215. package/lib/runjs-context/index.d.ts +19 -0
  216. package/lib/runjs-context/index.js +57 -0
  217. package/lib/runjs-context/registry.d.ts +17 -0
  218. package/lib/runjs-context/registry.js +93 -0
  219. package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +16 -0
  220. package/lib/runjs-context/snippets/global/api-request-get.snippet.js +42 -0
  221. package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +16 -0
  222. package/lib/runjs-context/snippets/global/api-request-post.snippet.js +42 -0
  223. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +16 -0
  224. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +41 -0
  225. package/lib/runjs-context/snippets/global/copy-record-json.snippet.d.ts +11 -0
  226. package/lib/runjs-context/snippets/global/copy-record-json.snippet.js +42 -0
  227. package/lib/runjs-context/snippets/global/copy-to-clipboard.snippet.d.ts +11 -0
  228. package/lib/runjs-context/snippets/global/copy-to-clipboard.snippet.js +42 -0
  229. package/lib/runjs-context/snippets/global/log-json-record.snippet.d.ts +11 -0
  230. package/lib/runjs-context/snippets/global/log-json-record.snippet.js +42 -0
  231. package/lib/runjs-context/snippets/global/message-error.snippet.d.ts +11 -0
  232. package/lib/runjs-context/snippets/global/message-error.snippet.js +41 -0
  233. package/lib/runjs-context/snippets/global/message-success.snippet.d.ts +11 -0
  234. package/lib/runjs-context/snippets/global/message-success.snippet.js +41 -0
  235. package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +16 -0
  236. package/lib/runjs-context/snippets/global/notification-open.snippet.js +43 -0
  237. package/lib/runjs-context/snippets/global/open-view-dialog.snippet.d.ts +11 -0
  238. package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +47 -0
  239. package/lib/runjs-context/snippets/global/open-view-drawer.snippet.d.ts +11 -0
  240. package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +47 -0
  241. package/lib/runjs-context/snippets/global/requireAsync.snippet.d.ts +16 -0
  242. package/lib/runjs-context/snippets/global/requireAsync.snippet.js +46 -0
  243. package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +16 -0
  244. package/lib/runjs-context/snippets/global/sleep.snippet.js +43 -0
  245. package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +16 -0
  246. package/lib/runjs-context/snippets/global/try-catch-async.snippet.js +44 -0
  247. package/lib/runjs-context/snippets/global/view-navigation-push.snippet.d.ts +11 -0
  248. package/lib/runjs-context/snippets/global/view-navigation-push.snippet.js +44 -0
  249. package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +16 -0
  250. package/lib/runjs-context/snippets/global/window-open.snippet.js +41 -0
  251. package/lib/runjs-context/snippets/index.d.ts +11 -0
  252. package/lib/runjs-context/snippets/index.js +94 -0
  253. package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +15 -0
  254. package/lib/runjs-context/snippets/libs/echarts-init.snippet.js +46 -0
  255. package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +15 -0
  256. package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.js +44 -0
  257. package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +15 -0
  258. package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.js +43 -0
  259. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +15 -0
  260. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +43 -0
  261. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +15 -0
  262. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +40 -0
  263. package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +15 -0
  264. package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.js +46 -0
  265. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +15 -0
  266. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +42 -0
  267. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +15 -0
  268. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js +46 -0
  269. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +15 -0
  270. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +41 -0
  271. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +15 -0
  272. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +41 -0
  273. package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +15 -0
  274. package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.js +46 -0
  275. package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.d.ts +11 -0
  276. package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.js +45 -0
  277. package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +15 -0
  278. package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.js +56 -0
  279. package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +15 -0
  280. package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.js +42 -0
  281. package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +15 -0
  282. package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.js +41 -0
  283. package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +15 -0
  284. package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.js +40 -0
  285. package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +15 -0
  286. package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.js +44 -0
  287. package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +15 -0
  288. package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.js +60 -0
  289. package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +15 -0
  290. package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.js +59 -0
  291. package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +15 -0
  292. package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.js +60 -0
  293. package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +15 -0
  294. package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.js +60 -0
  295. package/lib/runjs-context/snippets/types.d.ts +16 -0
  296. package/lib/runjs-context/snippets/types.js +24 -0
  297. package/lib/types.d.ts +398 -0
  298. package/lib/types.js +43 -0
  299. package/lib/utils/autoFlowError.d.ts +16 -0
  300. package/lib/utils/autoFlowError.js +53 -0
  301. package/lib/utils/constants.d.ts +29 -0
  302. package/lib/utils/constants.js +77 -0
  303. package/lib/utils/context.d.ts +40 -0
  304. package/lib/utils/context.js +63 -0
  305. package/lib/utils/createCollectionContextMeta.d.ts +11 -0
  306. package/lib/utils/createCollectionContextMeta.js +117 -0
  307. package/lib/utils/exceptions.d.ts +22 -0
  308. package/lib/utils/exceptions.js +62 -0
  309. package/lib/utils/flow-definitions.d.ts +11 -0
  310. package/lib/utils/flow-definitions.js +40 -0
  311. package/lib/utils/index.d.ts +22 -0
  312. package/lib/utils/index.js +117 -0
  313. package/lib/utils/inheritance.d.ts +16 -0
  314. package/lib/utils/inheritance.js +53 -0
  315. package/lib/utils/params-resolvers.d.ts +51 -0
  316. package/lib/utils/params-resolvers.js +309 -0
  317. package/lib/utils/parsePathnameToViewParams.d.ts +34 -0
  318. package/lib/utils/parsePathnameToViewParams.js +84 -0
  319. package/lib/utils/safeGlobals.d.ts +16 -0
  320. package/lib/utils/safeGlobals.js +179 -0
  321. package/lib/utils/schema-utils.d.ts +40 -0
  322. package/lib/utils/schema-utils.js +161 -0
  323. package/lib/utils/serverContextParams.d.ts +28 -0
  324. package/lib/utils/serverContextParams.js +106 -0
  325. package/lib/utils/setupRuntimeContextSteps.d.ts +19 -0
  326. package/lib/utils/setupRuntimeContextSteps.js +88 -0
  327. package/lib/utils/translation.d.ts +18 -0
  328. package/lib/utils/translation.js +58 -0
  329. package/lib/utils/variablesParams.d.ts +51 -0
  330. package/lib/utils/variablesParams.js +150 -0
  331. package/lib/views/DialogComponent.d.ts +22 -0
  332. package/lib/views/DialogComponent.js +98 -0
  333. package/lib/views/DrawerComponent.d.ts +11 -0
  334. package/lib/views/DrawerComponent.js +101 -0
  335. package/lib/views/FlowView.d.ts +76 -0
  336. package/lib/views/FlowView.js +81 -0
  337. package/lib/views/PageComponent.d.ts +10 -0
  338. package/lib/views/PageComponent.js +167 -0
  339. package/lib/views/ViewNavigation.d.ts +45 -0
  340. package/lib/views/ViewNavigation.js +97 -0
  341. package/lib/views/createViewMeta.d.ts +16 -0
  342. package/lib/views/createViewMeta.js +171 -0
  343. package/lib/views/index.d.ts +13 -0
  344. package/lib/views/index.js +48 -0
  345. package/lib/views/useDialog.d.ts +32 -0
  346. package/lib/views/useDialog.js +199 -0
  347. package/lib/views/useDrawer.d.ts +33 -0
  348. package/lib/views/useDrawer.js +206 -0
  349. package/lib/views/usePage.d.ts +32 -0
  350. package/lib/views/usePage.js +193 -0
  351. package/lib/views/usePatchElement.d.ts +10 -0
  352. package/lib/views/usePatchElement.js +54 -0
  353. package/lib/views/usePopover.d.ts +17 -0
  354. package/lib/views/usePopover.js +159 -0
  355. package/package.json +37 -0
  356. package/src/ContextPathProxy.ts +45 -0
  357. package/src/ElementProxy.ts +69 -0
  358. package/src/FlowContextProvider.tsx +40 -0
  359. package/src/FlowDefinition.ts +275 -0
  360. package/src/JSRunner.ts +84 -0
  361. package/src/ReactView.tsx +104 -0
  362. package/src/ViewScopedFlowEngine.ts +75 -0
  363. package/src/__tests__/ElementProxy.test.ts +51 -0
  364. package/src/__tests__/JSRunner.test.ts +92 -0
  365. package/src/__tests__/ReactView.test.tsx +63 -0
  366. package/src/__tests__/context-path-proxy.test.ts +35 -0
  367. package/src/__tests__/flow-engine.test.ts +189 -0
  368. package/src/__tests__/flowContext.test.ts +2012 -0
  369. package/src/__tests__/flowEngine.saveModel.test.ts +171 -0
  370. package/src/__tests__/flowI18n.test.ts +28 -0
  371. package/src/__tests__/flowModel.getFlows.test.ts +61 -0
  372. package/src/__tests__/flowModel.openView.navigation.test.ts +78 -0
  373. package/src/__tests__/flowRuntimeContext.test.ts +187 -0
  374. package/src/__tests__/flowSettings.open.test.tsx +1920 -0
  375. package/src/__tests__/flowSettings.test.ts +566 -0
  376. package/src/__tests__/globalFlowRegistry.test.ts +77 -0
  377. package/src/__tests__/isFieldInterfaceMatch.test.ts +51 -0
  378. package/src/__tests__/metaTreeNodeCache.test.ts +234 -0
  379. package/src/__tests__/path-aggregation.test.ts +85 -0
  380. package/src/__tests__/provider.test.tsx +28 -0
  381. package/src/__tests__/renderHiddenInConfig.test.tsx +91 -0
  382. package/src/__tests__/runjsContext.test.ts +60 -0
  383. package/src/__tests__/viewScopedFlowEngine.test.ts +212 -0
  384. package/src/acl/Acl.tsx +109 -0
  385. package/src/acl/__tests__/Acl.test.tsx +72 -0
  386. package/src/action-registry/BaseActionRegistry.ts +46 -0
  387. package/src/action-registry/EngineActionRegistry.ts +32 -0
  388. package/src/action-registry/ModelActionRegistry.ts +75 -0
  389. package/src/action-registry/__tests__/engineActionRegistry.test.ts +43 -0
  390. package/src/action-registry/__tests__/modelActionRegistry.test.ts +107 -0
  391. package/src/components/DynamicFlowsEditor.tsx +318 -0
  392. package/src/components/FieldModelRenderer.tsx +62 -0
  393. package/src/components/FlowContextSelector.tsx +255 -0
  394. package/src/components/FlowErrorFallback.tsx +316 -0
  395. package/src/components/FlowModelRenderer.tsx +428 -0
  396. package/src/components/FormItem.tsx +130 -0
  397. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +226 -0
  398. package/src/components/common/FlowSettingsButton.tsx +30 -0
  399. package/src/components/common/index.ts +10 -0
  400. package/src/components/common/withFlowDesignMode.tsx +49 -0
  401. package/src/components/dnd/getMousePositionOnElement.ts +115 -0
  402. package/src/components/dnd/index.tsx +128 -0
  403. package/src/components/dnd/moveBlock.ts +379 -0
  404. package/src/components/index.ts +20 -0
  405. package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +279 -0
  406. package/src/components/settings/independents/dropdown/index.ts +10 -0
  407. package/src/components/settings/independents/index.ts +2 -0
  408. package/src/components/settings/index.ts +11 -0
  409. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +617 -0
  410. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +292 -0
  411. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +655 -0
  412. package/src/components/settings/wrappers/contextual/StepRequiredSettingsDialog.tsx +446 -0
  413. package/src/components/settings/wrappers/contextual/StepSettings.tsx +109 -0
  414. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +217 -0
  415. package/src/components/settings/wrappers/contextual/StepSettingsDrawer.tsx +32 -0
  416. package/src/components/settings/wrappers/contextual/index.ts +15 -0
  417. package/src/components/settings/wrappers/embedded/FlowSettings.tsx +258 -0
  418. package/src/components/settings/wrappers/embedded/FlowsSettings.tsx +111 -0
  419. package/src/components/settings/wrappers/embedded/FlowsSettingsContent.tsx +96 -0
  420. package/src/components/settings/wrappers/embedded/index.ts +11 -0
  421. package/src/components/settings/wrappers/index.ts +5 -0
  422. package/src/components/subModel/AddSubModelButton.tsx +575 -0
  423. package/src/components/subModel/LazyDropdown.tsx +714 -0
  424. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +1185 -0
  425. package/src/components/subModel/__tests__/buildWrapperFieldChildren.test.ts +192 -0
  426. package/src/components/subModel/__tests__/utils.test.ts +425 -0
  427. package/src/components/subModel/index.ts +12 -0
  428. package/src/components/subModel/utils.ts +278 -0
  429. package/src/components/variables/InlineVariableTag.tsx +97 -0
  430. package/src/components/variables/SlateVariableEditor.tsx +384 -0
  431. package/src/components/variables/VariableInput.tsx +342 -0
  432. package/src/components/variables/VariableTag.tsx +123 -0
  433. package/src/components/variables/VariableTrigger.tsx +116 -0
  434. package/src/components/variables/__tests__/FlowContextSelector.test.tsx +553 -0
  435. package/src/components/variables/__tests__/VariableInput.test.tsx +550 -0
  436. package/src/components/variables/__tests__/VariableTag.test.tsx +347 -0
  437. package/src/components/variables/__tests__/test-utils.tsx +62 -0
  438. package/src/components/variables/__tests__/utils.test.ts +310 -0
  439. package/src/components/variables/index.ts +16 -0
  440. package/src/components/variables/types.ts +100 -0
  441. package/src/components/variables/useResolvedMetaTree.ts +76 -0
  442. package/src/components/variables/utils.ts +192 -0
  443. package/src/data-source/__tests__/collection.test.ts +58 -0
  444. package/src/data-source/__tests__/index.test.ts +82 -0
  445. package/src/data-source/__tests__/jioToJoiSchema.test.ts +56 -0
  446. package/src/data-source/index.ts +812 -0
  447. package/src/data-source/jioToJoiSchema.ts +103 -0
  448. package/src/decorators/index.ts +10 -0
  449. package/src/decorators/largeField.ts +14 -0
  450. package/src/emitter.ts +33 -0
  451. package/src/event-registry/BaseEventRegistry.ts +40 -0
  452. package/src/event-registry/EngineEventRegistry.ts +26 -0
  453. package/src/event-registry/ModelEventRegistry.ts +69 -0
  454. package/src/event-registry/__tests__/engineEventRegistry.test.ts +48 -0
  455. package/src/executor/FlowExecutor.ts +256 -0
  456. package/src/executor/__tests__/eventStep.test.ts +157 -0
  457. package/src/executor/__tests__/flowExecutor.test.ts +163 -0
  458. package/src/flow-registry/BaseFlowRegistry.ts +91 -0
  459. package/src/flow-registry/GlobalFlowRegistry.ts +82 -0
  460. package/src/flow-registry/InstanceFlowRegistry.ts +39 -0
  461. package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +141 -0
  462. package/src/flow-registry/__tests__/instance-and-global-registry.test.ts +67 -0
  463. package/src/flow-registry/__tests__/instanceFlowRegistry.test.ts +83 -0
  464. package/src/flow-registry/index.ts +12 -0
  465. package/src/flowContext.ts +1639 -0
  466. package/src/flowEngine.ts +905 -0
  467. package/src/flowI18n.ts +96 -0
  468. package/src/flowSettings.ts +1045 -0
  469. package/src/hooks/index.ts +15 -0
  470. package/src/hooks/useApplyAutoFlows.ts +51 -0
  471. package/src/hooks/useFlowModel.tsx +59 -0
  472. package/src/hooks/useFlowModelById.ts +37 -0
  473. package/src/hooks/useFlowSettingsContext.tsx +37 -0
  474. package/src/hooks/useFlowStep.tsx +19 -0
  475. package/src/hooks/useNiceDropdownMaxHeight.ts +34 -0
  476. package/src/index.ts +38 -0
  477. package/src/locale/en-US.json +61 -0
  478. package/src/locale/index.ts +38 -0
  479. package/src/locale/zh-CN.json +61 -0
  480. package/src/models/CollectionFieldModel.tsx +269 -0
  481. package/src/models/DisplayItemModel.tsx +13 -0
  482. package/src/models/EditableItemModel.tsx +13 -0
  483. package/src/models/FilterableItemModel.tsx +13 -0
  484. package/src/models/__tests__/CollectionFieldModel.test.ts +122 -0
  485. package/src/models/__tests__/defaultParams-on-create.test.ts +83 -0
  486. package/src/models/__tests__/flow-model-oninit.test.ts +44 -0
  487. package/src/models/__tests__/flowModel.actions.integration.test.ts +100 -0
  488. package/src/models/__tests__/flowModel.getFlows.sort.test.ts +100 -0
  489. package/src/models/__tests__/flowModel.test.ts +2746 -0
  490. package/src/models/__tests__/flowRegistry.test.ts +512 -0
  491. package/src/models/__tests__/forkFlowModel.test.ts +1047 -0
  492. package/src/models/__tests__/model-actions.test.ts +70 -0
  493. package/src/models/__tests__/model-events.test.ts +69 -0
  494. package/src/models/flowModel.tsx +1398 -0
  495. package/src/models/forkFlowModel.ts +287 -0
  496. package/src/models/index.ts +17 -0
  497. package/src/provider.tsx +101 -0
  498. package/src/resources/__tests__/apiResource.test.ts +201 -0
  499. package/src/resources/__tests__/baseRecordResource.test.ts +262 -0
  500. package/src/resources/__tests__/filterItem.test.ts +260 -0
  501. package/src/resources/__tests__/flowResource.test.ts +127 -0
  502. package/src/resources/apiResource.ts +148 -0
  503. package/src/resources/baseRecordResource.ts +279 -0
  504. package/src/resources/filterItem.ts +74 -0
  505. package/src/resources/flowResource.ts +143 -0
  506. package/src/resources/index.ts +17 -0
  507. package/src/resources/multiRecordResource.ts +219 -0
  508. package/src/resources/singleRecordResource.ts +83 -0
  509. package/src/resources/sqlResource.ts +299 -0
  510. package/src/runjs-context/contexts/FlowRunJSContext.ts +190 -0
  511. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +39 -0
  512. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +52 -0
  513. package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +32 -0
  514. package/src/runjs-context/contexts/JSFieldRunJSContext.ts +43 -0
  515. package/src/runjs-context/contexts/JSItemRunJSContext.ts +39 -0
  516. package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +34 -0
  517. package/src/runjs-context/contexts/LinkageRunJSContext.ts +35 -0
  518. package/src/runjs-context/helpers.ts +56 -0
  519. package/src/runjs-context/index.ts +20 -0
  520. package/src/runjs-context/registry.ts +65 -0
  521. package/src/runjs-context/snippets/global/api-request-get.snippet.ts +20 -0
  522. package/src/runjs-context/snippets/global/api-request-post.snippet.ts +20 -0
  523. package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +19 -0
  524. package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +21 -0
  525. package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +21 -0
  526. package/src/runjs-context/snippets/global/log-json-record.snippet.ts +21 -0
  527. package/src/runjs-context/snippets/global/message-error.snippet.ts +20 -0
  528. package/src/runjs-context/snippets/global/message-success.snippet.ts +20 -0
  529. package/src/runjs-context/snippets/global/notification-open.snippet.ts +21 -0
  530. package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +26 -0
  531. package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +26 -0
  532. package/src/runjs-context/snippets/global/requireAsync.snippet.ts +24 -0
  533. package/src/runjs-context/snippets/global/sleep.snippet.ts +21 -0
  534. package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +22 -0
  535. package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +23 -0
  536. package/src/runjs-context/snippets/global/window-open.snippet.ts +19 -0
  537. package/src/runjs-context/snippets/index.ts +59 -0
  538. package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +24 -0
  539. package/src/runjs-context/snippets/scene/actions/collection-selected-count.snippet.ts +22 -0
  540. package/src/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.ts +21 -0
  541. package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +21 -0
  542. package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +18 -0
  543. package/src/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.ts +29 -0
  544. package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +20 -0
  545. package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +24 -0
  546. package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +19 -0
  547. package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +24 -0
  548. package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +24 -0
  549. package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +30 -0
  550. package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +34 -0
  551. package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +20 -0
  552. package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +19 -0
  553. package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +18 -0
  554. package/src/runjs-context/snippets/scene/jsitem/render-basic.snippet.ts +27 -0
  555. package/src/runjs-context/snippets/scene/linkage/set-disabled.snippet.ts +38 -0
  556. package/src/runjs-context/snippets/scene/linkage/set-field-value.snippet.ts +37 -0
  557. package/src/runjs-context/snippets/scene/linkage/set-required.snippet.ts +38 -0
  558. package/src/runjs-context/snippets/scene/linkage/toggle-visible.snippet.ts +38 -0
  559. package/src/runjs-context/snippets/types.ts +17 -0
  560. package/src/types.ts +474 -0
  561. package/src/utils/__tests__/context.test.ts +93 -0
  562. package/src/utils/__tests__/params-resolvers.test.ts +652 -0
  563. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +104 -0
  564. package/src/utils/__tests__/safeGlobals.test.ts +29 -0
  565. package/src/utils/__tests__/utils.test.ts +1021 -0
  566. package/src/utils/__tests__/variablesParams.test.ts +52 -0
  567. package/src/utils/autoFlowError.ts +29 -0
  568. package/src/utils/constants.ts +60 -0
  569. package/src/utils/context.ts +70 -0
  570. package/src/utils/createCollectionContextMeta.ts +122 -0
  571. package/src/utils/exceptions.ts +36 -0
  572. package/src/utils/flow-definitions.ts +16 -0
  573. package/src/utils/index.ts +63 -0
  574. package/src/utils/inheritance.ts +39 -0
  575. package/src/utils/params-resolvers.ts +482 -0
  576. package/src/utils/parsePathnameToViewParams.ts +103 -0
  577. package/src/utils/safeGlobals.ts +188 -0
  578. package/src/utils/schema-utils.ts +201 -0
  579. package/src/utils/serverContextParams.ts +111 -0
  580. package/src/utils/setupRuntimeContextSteps.ts +89 -0
  581. package/src/utils/translation.ts +37 -0
  582. package/src/utils/variablesParams.ts +175 -0
  583. package/src/views/DialogComponent.tsx +79 -0
  584. package/src/views/DrawerComponent.tsx +72 -0
  585. package/src/views/FlowView.tsx +103 -0
  586. package/src/views/PageComponent.tsx +150 -0
  587. package/src/views/ViewNavigation.ts +122 -0
  588. package/src/views/__tests__/FlowView.test.ts +31 -0
  589. package/src/views/__tests__/ViewNavigation.test.ts +191 -0
  590. package/src/views/__tests__/usePatchElement.test.tsx +28 -0
  591. package/src/views/createViewMeta.ts +157 -0
  592. package/src/views/index.tsx +14 -0
  593. package/src/views/useDialog.tsx +192 -0
  594. package/src/views/useDrawer.tsx +205 -0
  595. package/src/views/usePage.tsx +182 -0
  596. package/src/views/usePatchElement.tsx +27 -0
  597. package/src/views/usePopover.tsx +131 -0
@@ -0,0 +1,1047 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import { vi } from 'vitest';
11
+ import { FlowEngine } from '../../flowEngine';
12
+ import type { FlowModelOptions, IModelComponentProps } from '../../types';
13
+ import { FlowModel } from '../flowModel';
14
+ import { ForkFlowModel } from '../forkFlowModel';
15
+
16
+ // Helper functions
17
+ const createMockFlowEngine = (): FlowEngine => {
18
+ return new FlowEngine();
19
+ };
20
+
21
+ const createMockFlowModel = (overrides: Partial<FlowModelOptions> = {}): FlowModel => {
22
+ const flowEngine = createMockFlowEngine();
23
+ const options = {
24
+ uid: 'test-master-uid',
25
+ flowEngine,
26
+ props: { masterProp: 'masterValue' },
27
+ stepParams: { testFlow: { step1: { param1: 'value1' } } },
28
+ sortIndex: 0,
29
+ subModels: {},
30
+ async: false,
31
+ ...overrides,
32
+ };
33
+
34
+ const model = new FlowModel(options);
35
+ return model;
36
+ };
37
+
38
+ // Test setup
39
+ let mockMaster: FlowModel;
40
+ let initialProps: IModelComponentProps;
41
+
42
+ beforeEach(() => {
43
+ mockMaster = createMockFlowModel();
44
+ initialProps = { forkProp: 'forkValue' };
45
+ vi.clearAllMocks();
46
+ });
47
+
48
+ describe('ForkFlowModel', () => {
49
+ // ==================== CONSTRUCTOR & INITIALIZATION ====================
50
+ describe('Constructor & Initialization', () => {
51
+ test('should create fork with basic parameters', () => {
52
+ const fork = new ForkFlowModel(mockMaster, initialProps, 1);
53
+
54
+ expect(fork.uid).toBe(mockMaster.uid);
55
+ expect(fork.forkId).toBe(1);
56
+ expect(fork.localProps).toEqual(initialProps);
57
+ expect(fork.isFork).toBe(true);
58
+ expect((fork as any).master).toBe(mockMaster);
59
+ expect((fork as any).disposed).toBe(false);
60
+ });
61
+
62
+ test('should create fork with default parameters', () => {
63
+ const fork = new ForkFlowModel(mockMaster);
64
+
65
+ expect(fork.uid).toBe(mockMaster.uid);
66
+ expect(fork.forkId).toBe(0);
67
+ expect(fork.localProps).toEqual({});
68
+ expect(fork.isFork).toBe(true);
69
+ });
70
+
71
+ test('should return Proxy object', () => {
72
+ const fork = new ForkFlowModel(mockMaster, initialProps);
73
+
74
+ // Verify it's a Proxy by checking transparent property access
75
+ expect(typeof fork).toBe('object');
76
+ expect(fork.constructor).toBe(mockMaster.constructor);
77
+ });
78
+ });
79
+
80
+ // ==================== HIDDEN STATE ====================
81
+ describe('Hidden State', () => {
82
+ test('should initialize hidden from master', () => {
83
+ mockMaster.hidden = true;
84
+ const fork = new ForkFlowModel(mockMaster);
85
+
86
+ expect(fork.hidden).toBe(true);
87
+ });
88
+
89
+ test('should keep hidden independent between master and fork', () => {
90
+ mockMaster.hidden = true;
91
+ const fork = new ForkFlowModel(mockMaster);
92
+
93
+ // initial copy from master
94
+ expect(fork.hidden).toBe(true);
95
+
96
+ // change fork.hidden should not affect master
97
+ fork.hidden = false;
98
+ expect(fork.hidden).toBe(false);
99
+ expect(mockMaster.hidden).toBe(true);
100
+
101
+ // change master.hidden should not affect existing fork
102
+ mockMaster.hidden = false;
103
+ expect(mockMaster.hidden).toBe(false);
104
+ expect(fork.hidden).toBe(false);
105
+
106
+ // toggle master again; fork remains unchanged
107
+ mockMaster.hidden = true;
108
+ expect(mockMaster.hidden).toBe(true);
109
+ expect(fork.hidden).toBe(false);
110
+ });
111
+ });
112
+
113
+ // ==================== PROXY GET MECHANISM ====================
114
+ describe('Proxy Get Mechanism', () => {
115
+ let fork: ForkFlowModel;
116
+
117
+ beforeEach(() => {
118
+ fork = new ForkFlowModel(mockMaster, initialProps, 1);
119
+ });
120
+
121
+ test('should return disposed status correctly', () => {
122
+ expect(fork['disposed']).toBe(false);
123
+
124
+ fork.dispose();
125
+
126
+ expect(fork['disposed']).toBe(true);
127
+ });
128
+
129
+ test('should return master constructor for constructor property', () => {
130
+ expect(fork.constructor).toBe(mockMaster.constructor);
131
+ expect(fork.constructor).toBe(FlowModel);
132
+ });
133
+
134
+ test('should merge props from master and local', () => {
135
+ const masterProps = { masterProp: 'masterValue', shared: 'master' };
136
+ const localProps = { localProp: 'localValue', shared: 'local' };
137
+
138
+ mockMaster.getProps = vi.fn(() => masterProps);
139
+ fork.localProps = localProps;
140
+
141
+ const mergedProps = fork.props;
142
+
143
+ expect(mergedProps).toEqual({
144
+ masterProp: 'masterValue',
145
+ localProp: 'localValue',
146
+ shared: 'local', // Local should override master
147
+ });
148
+ });
149
+
150
+ test('should return fork own properties first', () => {
151
+ expect(fork.uid).toBe(mockMaster.uid);
152
+ expect(fork.forkId).toBe(1);
153
+ expect(fork.isFork).toBe(true);
154
+ expect(fork.localProps).toEqual(initialProps);
155
+ });
156
+
157
+ test('should access local properties storage', () => {
158
+ // Set a local property directly
159
+ (fork as any).localCustomProp = 'localValue';
160
+
161
+ expect((fork as any).localCustomProp).toBe('localValue');
162
+ });
163
+
164
+ test('should fallback to master properties', () => {
165
+ // Access master property that doesn\'t exist on fork
166
+ const masterStepParams = mockMaster.stepParams;
167
+
168
+ expect((fork as any).stepParams).toBe(masterStepParams);
169
+ });
170
+
171
+ test('should bind functions to fork instance', () => {
172
+ const testMethod = vi.fn(function (this: any) {
173
+ return this.uid;
174
+ });
175
+
176
+ (mockMaster as any).testMethod = testMethod;
177
+
178
+ const result = (fork as any).testMethod();
179
+
180
+ expect(testMethod).toHaveBeenCalled();
181
+ expect(result).toBe(fork.uid);
182
+ });
183
+
184
+ test('should preserve master constructor in function context', () => {
185
+ const testMethod = vi.fn(function (this: any) {
186
+ return this.constructor;
187
+ });
188
+
189
+ (mockMaster as any).testMethod = testMethod;
190
+
191
+ const result = (fork as any).testMethod();
192
+
193
+ expect(result).toBe(mockMaster.constructor);
194
+ });
195
+
196
+ test('should pass arguments to bound functions', () => {
197
+ const testMethod = vi.fn((arg1: string, arg2: number) => `${arg1}-${arg2}`);
198
+
199
+ (mockMaster as any).testMethod = testMethod;
200
+
201
+ const result = (fork as any).testMethod('test', 123);
202
+
203
+ expect(testMethod).toHaveBeenCalledWith('test', 123);
204
+ expect(result).toBe('test-123');
205
+ });
206
+
207
+ test('should handle non-function master properties', () => {
208
+ (mockMaster as any).masterData = { key: 'value' };
209
+
210
+ expect((fork as any).masterData).toEqual({ key: 'value' });
211
+ });
212
+
213
+ test('should handle undefined master properties', () => {
214
+ expect((fork as any).nonExistentProperty).toBeUndefined();
215
+ });
216
+
217
+ test('should create correct context object for functions', () => {
218
+ const contextChecker = vi.fn(function (this: any) {
219
+ return {
220
+ hasConstructor: 'constructor' in this,
221
+ constructorValue: this.constructor,
222
+ isConfigurable: Object.getOwnPropertyDescriptor(this, 'constructor')?.configurable,
223
+ isEnumerable: Object.getOwnPropertyDescriptor(this, 'constructor')?.enumerable,
224
+ isWritable: Object.getOwnPropertyDescriptor(this, 'constructor')?.writable,
225
+ };
226
+ });
227
+
228
+ (mockMaster as any).contextChecker = contextChecker;
229
+
230
+ const result = (fork as any).contextChecker();
231
+
232
+ expect(result.hasConstructor).toBe(true);
233
+ expect(result.constructorValue).toBe(mockMaster.constructor);
234
+ expect(result.isConfigurable).toBe(true);
235
+ expect(result.isEnumerable).toBe(false);
236
+ expect(result.isWritable).toBe(false);
237
+ });
238
+ });
239
+
240
+ // ==================== PROXY SET MECHANISM ====================
241
+ describe('Proxy Set Mechanism', () => {
242
+ let fork: ForkFlowModel;
243
+
244
+ beforeEach(() => {
245
+ fork = new ForkFlowModel(mockMaster, initialProps);
246
+ });
247
+
248
+ test('should ignore setting props property', () => {
249
+ const originalProps = fork.props;
250
+
251
+ (fork as any).props = { newProp: 'newValue' };
252
+
253
+ // Props should remain unchanged since set returns true but doesn't actually set
254
+ expect(fork.props).toEqual(originalProps);
255
+ });
256
+
257
+ test('should set fork own properties directly', () => {
258
+ fork.localProps = { newLocal: 'value' };
259
+
260
+ expect(fork.localProps).toEqual({ newLocal: 'value' });
261
+ });
262
+
263
+ test('should sync shared properties to master', () => {
264
+ const newStepParams = { newFlow: { newStep: { param: 'value' } } };
265
+
266
+ (fork as any).stepParams = newStepParams;
267
+
268
+ expect((mockMaster as any).stepParams).toEqual(newStepParams);
269
+ });
270
+
271
+ test('should store non-shared properties locally', () => {
272
+ const customValue = { data: 'localData' };
273
+
274
+ (fork as any).customProperty = customValue;
275
+
276
+ expect((fork as any).customProperty).toBe(customValue);
277
+ expect((mockMaster as any).customProperty).toBeUndefined();
278
+ });
279
+
280
+ test('should call master setter for shared properties', () => {
281
+ const setterSpy = vi.fn();
282
+
283
+ // Mock a setter on master
284
+ Object.defineProperty(mockMaster, 'sortIndex', {
285
+ get: () => 0,
286
+ set: setterSpy,
287
+ configurable: true,
288
+ });
289
+
290
+ (fork as any).sortIndex = 5;
291
+
292
+ expect(setterSpy).toHaveBeenCalledWith(5);
293
+ });
294
+
295
+ test('should handle shared property without setter', () => {
296
+ // stepParams should be a shared property without custom setter
297
+ const newParams = { flow: { step: { param: 'test' } } };
298
+
299
+ (fork as any).stepParams = newParams;
300
+
301
+ expect((mockMaster as any).stepParams).toEqual(newParams);
302
+ });
303
+
304
+ test('should identify shared properties correctly', () => {
305
+ const originalSharedProps = ForkFlowModel.getSharedProperties();
306
+
307
+ expect(originalSharedProps).toContain('stepParams');
308
+ expect(originalSharedProps).toContain('sortIndex');
309
+ });
310
+
311
+ test('should handle property descriptor lookup', () => {
312
+ // Create a property with descriptor on master
313
+ Object.defineProperty(mockMaster, 'testDescriptor', {
314
+ get: () => 'test',
315
+ set: vi.fn(),
316
+ configurable: true,
317
+ });
318
+
319
+ const fork = new ForkFlowModel(mockMaster, initialProps);
320
+
321
+ // Since testDescriptor is not a shared property, our fix now makes
322
+ // non-shared properties also check for setters and call them if they exist
323
+ (fork as any).testDescriptor = 'newValue';
324
+
325
+ // With our fix, the setter should be called even for non-shared properties
326
+ const descriptor = Object.getOwnPropertyDescriptor(mockMaster, 'testDescriptor');
327
+ expect(descriptor?.set).toHaveBeenCalledWith('newValue');
328
+ });
329
+
330
+ test('should handle non-existent property descriptors', () => {
331
+ ForkFlowModel.setSharedProperties(['nonExistentProp']);
332
+
333
+ // Should not throw when setting property without descriptor
334
+ expect(() => {
335
+ (fork as any).nonExistentProp = 'value';
336
+ }).not.toThrow();
337
+
338
+ expect((mockMaster as any).nonExistentProp).toBe('value');
339
+ });
340
+ });
341
+
342
+ // ==================== SHARED PROPERTIES MANAGEMENT ====================
343
+ describe('Shared Properties Management', () => {
344
+ test('should set shared properties configuration', () => {
345
+ const newSharedProps = ['customProp1', 'customProp2'];
346
+
347
+ ForkFlowModel.setSharedProperties(newSharedProps);
348
+
349
+ expect(ForkFlowModel.getSharedProperties()).toEqual(newSharedProps);
350
+ });
351
+
352
+ test('should get current shared properties', () => {
353
+ const currentProps = ForkFlowModel.getSharedProperties();
354
+
355
+ expect(Array.isArray(currentProps)).toBe(true);
356
+ expect(currentProps.length).toBeGreaterThan(0);
357
+ });
358
+
359
+ test('should have default shared properties', () => {
360
+ // Reset to defaults
361
+ ForkFlowModel.setSharedProperties(['stepParams', 'sortIndex']);
362
+
363
+ const defaultProps = ForkFlowModel.getSharedProperties();
364
+
365
+ expect(defaultProps).toContain('stepParams');
366
+ expect(defaultProps).toContain('sortIndex');
367
+ });
368
+
369
+ test('should identify shared property correctly', () => {
370
+ ForkFlowModel.setSharedProperties(['testProp']);
371
+ const fork = new ForkFlowModel(mockMaster, initialProps);
372
+
373
+ // Use private method indirectly through property setting behavior
374
+ (fork as any).testProp = 'value';
375
+
376
+ expect((mockMaster as any).testProp).toBe('value');
377
+ });
378
+
379
+ test('should identify non-shared property correctly', () => {
380
+ ForkFlowModel.setSharedProperties(['onlyThisProp']);
381
+ const fork = new ForkFlowModel(mockMaster, initialProps);
382
+
383
+ (fork as any).nonSharedProp = 'value';
384
+
385
+ expect((fork as any).nonSharedProp).toBe('value');
386
+ expect((mockMaster as any).nonSharedProp).toBeUndefined();
387
+ });
388
+ });
389
+
390
+ // ==================== PROPS MANAGEMENT ====================
391
+ describe('Props Management', () => {
392
+ let fork: ForkFlowModel;
393
+
394
+ beforeEach(() => {
395
+ fork = new ForkFlowModel(mockMaster, { initial: 'value' });
396
+ });
397
+
398
+ test('should set props with string key-value', () => {
399
+ fork.setProps('newKey', 'newValue');
400
+
401
+ expect(fork.localProps.newKey).toBe('newValue');
402
+ expect(fork.localProps.initial).toBe('value'); // Should preserve existing
403
+ });
404
+
405
+ test('should set props with object', () => {
406
+ const newProps = { prop1: 'value1', prop2: 'value2' };
407
+
408
+ fork.setProps(newProps);
409
+
410
+ expect(fork.localProps).toEqual({
411
+ initial: 'value',
412
+ prop1: 'value1',
413
+ prop2: 'value2',
414
+ });
415
+ });
416
+
417
+ test('should merge props correctly', () => {
418
+ fork.setProps({ existing: 'updated', new: 'added' });
419
+
420
+ expect(fork.localProps).toEqual({
421
+ initial: 'value',
422
+ existing: 'updated',
423
+ new: 'added',
424
+ });
425
+ });
426
+
427
+ test('should get merged props from master and local', () => {
428
+ const masterProps = { master: 'value', shared: 'master' };
429
+ const localProps = { local: 'value', shared: 'local' };
430
+
431
+ mockMaster.getProps = vi.fn(() => masterProps);
432
+ fork.localProps = localProps;
433
+
434
+ const result = fork.getProps();
435
+
436
+ expect(result).toEqual({
437
+ master: 'value',
438
+ local: 'value',
439
+ shared: 'local', // Local should override
440
+ });
441
+ });
442
+
443
+ test('should maintain local props independence', () => {
444
+ const originalProps = { ...fork.localProps };
445
+
446
+ fork.setProps('newKey', 'newValue');
447
+
448
+ expect(fork.localProps.newKey).toBe('newValue');
449
+ expect(originalProps).not.toHaveProperty('newKey');
450
+ });
451
+
452
+ test('should ignore setProps when disposed', () => {
453
+ fork.dispose();
454
+ const originalProps = { ...fork.localProps };
455
+
456
+ fork.setProps('shouldIgnore', 'value');
457
+
458
+ expect(fork.localProps).toEqual(originalProps);
459
+ });
460
+
461
+ test('should handle props priority in getter', () => {
462
+ mockMaster.getProps = vi.fn(() => ({
463
+ masterOnly: 'master',
464
+ conflict: 'master',
465
+ }));
466
+
467
+ fork.localProps = {
468
+ localOnly: 'local',
469
+ conflict: 'local',
470
+ };
471
+
472
+ const merged = fork.props;
473
+
474
+ expect(merged.masterOnly).toBe('master');
475
+ expect(merged.localOnly).toBe('local');
476
+ expect(merged.conflict).toBe('local'); // Local wins
477
+ });
478
+
479
+ test('should handle nested object props', () => {
480
+ const nestedProps = {
481
+ user: { name: 'John', settings: { theme: 'dark' } },
482
+ config: { debug: true },
483
+ };
484
+
485
+ fork.setProps(nestedProps);
486
+
487
+ expect(fork.localProps.user).toEqual(nestedProps.user);
488
+ expect(fork.localProps.config).toEqual(nestedProps.config);
489
+ });
490
+ });
491
+
492
+ // ==================== CONTEXT AND SHARED STATE ====================
493
+ describe('Context and Shared State', () => {
494
+ let fork: ForkFlowModel;
495
+
496
+ beforeEach(() => {
497
+ fork = new ForkFlowModel(mockMaster, initialProps);
498
+ });
499
+
500
+ test('should set shared context', () => {
501
+ const contextData = { key1: 'value1', key2: 'value2' };
502
+
503
+ // Set context properties on the master model first
504
+ mockMaster.context.defineProperty('key1', { value: contextData.key1 });
505
+ mockMaster.context.defineProperty('key2', { value: contextData.key2 });
506
+
507
+ // Check that the context properties are accessible through fork
508
+ expect(fork.context.key1).toEqual('value1');
509
+ expect(fork.context.key2).toEqual('value2');
510
+ });
511
+
512
+ test('should merge shared context', () => {
513
+ // Set initial context properties on master
514
+ mockMaster.context.defineProperty('initial', { value: 'original' });
515
+
516
+ // Update the property on master
517
+ mockMaster.context.defineProperty('initial', { value: 'updated' });
518
+ mockMaster.context.defineProperty('additional', { value: 'data' });
519
+
520
+ // Check that context properties are merged correctly
521
+ expect(fork.context.initial).toEqual('updated');
522
+ expect(fork.context.additional).toEqual('data');
523
+ });
524
+
525
+ test('should get ctx with globals and shared', () => {
526
+ // Set shared property on master
527
+ mockMaster.context.defineProperty('shared', { value: 'data' });
528
+
529
+ const ctx = fork.context;
530
+
531
+ // Check that shared properties are accessible through ctx
532
+ expect(ctx.shared).toEqual('data');
533
+
534
+ // Verify that fork has its own context instance
535
+ expect(ctx).toBeDefined();
536
+ expect(ctx).toBeInstanceOf(Object);
537
+ });
538
+ });
539
+
540
+ // ==================== RENDER MECHANISM ====================
541
+ describe('Render Mechanism', () => {
542
+ let fork: ForkFlowModel;
543
+
544
+ beforeEach(() => {
545
+ fork = new ForkFlowModel(mockMaster, { localStyle: 'local' });
546
+ });
547
+
548
+ test('should render with merged props', () => {
549
+ const masterProps = { masterStyle: 'master', shared: 'master' };
550
+ const expectedMerged = {
551
+ masterStyle: 'master',
552
+ localStyle: 'local',
553
+ shared: 'local',
554
+ };
555
+
556
+ mockMaster.getProps = vi.fn(() => masterProps);
557
+ fork.localProps = { localStyle: 'local', shared: 'local' };
558
+
559
+ mockMaster.render = vi.fn(function (this: any) {
560
+ return { type: 'div', props: this.props };
561
+ });
562
+
563
+ const result = fork.render();
564
+
565
+ expect(mockMaster.render).toHaveBeenCalled();
566
+ expect(result.props).toEqual(expectedMerged);
567
+ });
568
+
569
+ test('should call master render with fork as this', () => {
570
+ let renderThis: any;
571
+
572
+ mockMaster.render = vi.fn(function (this: any) {
573
+ renderThis = this;
574
+ return { type: 'span', props: this.props };
575
+ });
576
+
577
+ fork.render();
578
+
579
+ expect(renderThis).toBe(fork);
580
+ expect(renderThis.isFork).toBe(true);
581
+ });
582
+
583
+ // TODO: This test case indicates a bug? even it is passing... we should not restore!
584
+ // test('should restore original props after render', () => {
585
+ // const originalProps = fork.props;
586
+
587
+ // mockMaster.render = vi.fn(function(this: any) {
588
+ // // Modify props during render
589
+ // this.props = { modified: 'during-render' };
590
+ // return { type: 'div', props: this.props };
591
+ // });
592
+
593
+ // fork.render();
594
+
595
+ // // Props should be restored
596
+ // expect(fork.props).toEqual(originalProps);
597
+ // });
598
+
599
+ test('should return null when disposed', () => {
600
+ mockMaster.render = vi.fn();
601
+ fork.dispose();
602
+
603
+ const result = fork.render();
604
+
605
+ expect(result).toBeNull();
606
+ expect(mockMaster.render).not.toHaveBeenCalled();
607
+ });
608
+
609
+ test('should handle render exceptions gracefully', () => {
610
+ mockMaster.render = vi.fn(() => {
611
+ throw new Error('Render error');
612
+ });
613
+
614
+ expect(() => fork.render()).toThrow('Render error');
615
+ });
616
+ });
617
+
618
+ // ==================== LIFECYCLE MANAGEMENT ====================
619
+ describe('Lifecycle Management', () => {
620
+ let fork: ForkFlowModel;
621
+
622
+ beforeEach(() => {
623
+ mockMaster = createMockFlowModel();
624
+ (mockMaster as any).forks = new Set();
625
+ (mockMaster as any).forkCache = new Map();
626
+
627
+ fork = new ForkFlowModel(mockMaster, initialProps);
628
+ (mockMaster as any).forks.add(fork);
629
+ });
630
+
631
+ test('should dispose and change status', () => {
632
+ expect(fork['disposed']).toBe(false);
633
+
634
+ fork.dispose();
635
+
636
+ expect(fork['disposed']).toBe(true);
637
+ });
638
+
639
+ test('should remove from master forks collection', () => {
640
+ expect((mockMaster as any).forks.has(fork)).toBe(true);
641
+
642
+ fork.dispose();
643
+
644
+ expect((mockMaster as any).forks.has(fork)).toBe(false);
645
+ });
646
+
647
+ test('should remove from master fork cache', () => {
648
+ const cacheKey = 'testKey';
649
+ (mockMaster as any).forkCache.set(cacheKey, fork);
650
+
651
+ fork.dispose();
652
+
653
+ expect((mockMaster as any).forkCache.has(cacheKey)).toBe(false);
654
+ });
655
+
656
+ test('should handle dispose when already disposed', () => {
657
+ fork.dispose();
658
+
659
+ // Should not throw on second dispose
660
+ expect(() => fork.dispose()).not.toThrow();
661
+ expect(fork['disposed']).toBe(true);
662
+ });
663
+
664
+ test('should find and remove correct fork from cache', () => {
665
+ const fork1 = new ForkFlowModel(mockMaster, {}, 1);
666
+ const fork2 = new ForkFlowModel(mockMaster, {}, 2);
667
+
668
+ (mockMaster as any).forkCache.set('key1', fork1);
669
+ (mockMaster as any).forkCache.set('key2', fork2);
670
+
671
+ fork1.dispose();
672
+
673
+ expect((mockMaster as any).forkCache.has('key1')).toBe(false);
674
+ expect((mockMaster as any).forkCache.has('key2')).toBe(true);
675
+ });
676
+ });
677
+
678
+ // ==================== FUNCTION BINDING AND CONTEXT ====================
679
+ describe('Function Binding and Context', () => {
680
+ let fork: ForkFlowModel;
681
+
682
+ beforeEach(() => {
683
+ fork = new ForkFlowModel(mockMaster, initialProps);
684
+ });
685
+
686
+ test('should bind master methods to fork instance', () => {
687
+ const boundMethod = vi.fn(function (this: any) {
688
+ return {
689
+ uid: this.uid,
690
+ isFork: this.isFork,
691
+ forkId: this.forkId,
692
+ };
693
+ });
694
+
695
+ (mockMaster as any).boundMethod = boundMethod;
696
+
697
+ const result = (fork as any).boundMethod();
698
+
699
+ expect(result.uid).toBe(fork.uid);
700
+ expect(result.isFork).toBe(true);
701
+ expect(result.forkId).toBe(fork.forkId);
702
+ });
703
+
704
+ test('should preserve constructor in bound method context', () => {
705
+ const constructorChecker = vi.fn(function (this: any) {
706
+ return this.constructor === mockMaster.constructor;
707
+ });
708
+
709
+ (mockMaster as any).constructorChecker = constructorChecker;
710
+
711
+ const result = (fork as any).constructorChecker();
712
+
713
+ expect(result).toBe(true);
714
+ });
715
+
716
+ test('should handle async methods correctly', async () => {
717
+ const asyncMethod = vi.fn(async function (this: any) {
718
+ return new Promise((resolve) => {
719
+ setTimeout(() => {
720
+ resolve({
721
+ uid: this.uid,
722
+ constructor: this.constructor,
723
+ });
724
+ }, 0);
725
+ });
726
+ });
727
+
728
+ (mockMaster as any).asyncMethod = asyncMethod;
729
+
730
+ const result = await (fork as any).asyncMethod();
731
+
732
+ expect(result.uid).toBe(fork.uid);
733
+ expect(result.constructor).toBe(mockMaster.constructor);
734
+ });
735
+
736
+ test('should pass method arguments correctly', () => {
737
+ const methodWithArgs = vi.fn(function (arg1: string, arg2: number, arg3: object) {
738
+ return { arg1, arg2, arg3 };
739
+ });
740
+
741
+ (mockMaster as any).methodWithArgs = methodWithArgs;
742
+
743
+ const testObj = { test: 'object' };
744
+ const result = (fork as any).methodWithArgs('test', 123, testObj);
745
+
746
+ expect(methodWithArgs).toHaveBeenCalledWith('test', 123, testObj);
747
+ expect(result).toEqual({ arg1: 'test', arg2: 123, arg3: testObj });
748
+ });
749
+
750
+ test('should handle method return values correctly', () => {
751
+ const methodWithReturn = vi.fn(() => ({ success: true, data: 'result' }));
752
+
753
+ (mockMaster as any).methodWithReturn = methodWithReturn;
754
+
755
+ const result = (fork as any).methodWithReturn();
756
+
757
+ expect(result).toEqual({ success: true, data: 'result' });
758
+ });
759
+
760
+ test('should create correct context object properties', () => {
761
+ const contextInspector = vi.fn(function (this: any) {
762
+ const descriptor = Object.getOwnPropertyDescriptor(this, 'constructor');
763
+ return {
764
+ hasOwnConstructor: Object.prototype.hasOwnProperty.call(this, 'constructor'),
765
+ constructorValue: this.constructor,
766
+ descriptorExists: !!descriptor,
767
+ configurable: descriptor?.configurable,
768
+ enumerable: descriptor?.enumerable,
769
+ writable: descriptor?.writable,
770
+ };
771
+ });
772
+
773
+ (mockMaster as any).contextInspector = contextInspector;
774
+
775
+ const result = (fork as any).contextInspector();
776
+
777
+ expect(result.hasOwnConstructor).toBe(true);
778
+ expect(result.constructorValue).toBe(mockMaster.constructor);
779
+ expect(result.descriptorExists).toBe(true);
780
+ expect(result.configurable).toBe(true);
781
+ expect(result.enumerable).toBe(false);
782
+ expect(result.writable).toBe(false);
783
+ });
784
+
785
+ test('should handle closure constructor capture', () => {
786
+ // Create a method that captures constructor in closure
787
+ let capturedConstructor: any;
788
+
789
+ const closureMethod = function (this: any) {
790
+ capturedConstructor = this.constructor;
791
+ return this.constructor;
792
+ };
793
+
794
+ (mockMaster as any).closureMethod = closureMethod;
795
+
796
+ const result = (fork as any).closureMethod();
797
+
798
+ expect(capturedConstructor).toBe(mockMaster.constructor);
799
+ expect(result).toBe(mockMaster.constructor);
800
+ });
801
+
802
+ test('should maintain correct this binding in nested calls', () => {
803
+ const nestedMethod = vi.fn(function (this: any) {
804
+ return this.uid;
805
+ });
806
+
807
+ const callerMethod = vi.fn(function (this: any) {
808
+ return {
809
+ directUid: this.uid,
810
+ nestedUid: nestedMethod.call(this),
811
+ };
812
+ });
813
+
814
+ (mockMaster as any).nestedMethod = nestedMethod;
815
+ (mockMaster as any).callerMethod = callerMethod;
816
+
817
+ const result = (fork as any).callerMethod();
818
+
819
+ expect(result.directUid).toBe(fork.uid);
820
+ expect(result.nestedUid).toBe(fork.uid);
821
+ });
822
+ });
823
+
824
+ // ==================== EDGE CASES AND ERROR HANDLING ====================
825
+ describe('Edge Cases and Error Handling', () => {
826
+ let fork: ForkFlowModel;
827
+
828
+ beforeEach(() => {
829
+ fork = new ForkFlowModel(mockMaster, initialProps);
830
+ });
831
+
832
+ test('should handle accessing non-existent properties', () => {
833
+ const value = (fork as any).totallyNonExistentProperty;
834
+
835
+ expect(value).toBeUndefined();
836
+ });
837
+
838
+ test('should handle setting props property directly', () => {
839
+ const originalProps = fork.props;
840
+
841
+ // This should be ignored by the proxy
842
+ (fork as any).props = { ignored: 'value' };
843
+
844
+ // Props should be accessed through the getter mechanism
845
+ expect(fork.props).toEqual(originalProps);
846
+ });
847
+
848
+ test('should handle setProps with null/undefined values', () => {
849
+ fork.setProps('nullProp', null);
850
+ fork.setProps('undefinedProp', undefined);
851
+
852
+ expect(fork.localProps.nullProp).toBeNull();
853
+ expect(fork.localProps.undefinedProp).toBeUndefined();
854
+ });
855
+
856
+ test('should handle complex nested property access patterns', () => {
857
+ // Set up complex nested structure
858
+ (mockMaster as any).nested = {
859
+ deep: {
860
+ property: {
861
+ value: 'deep value',
862
+ },
863
+ },
864
+ };
865
+
866
+ expect((fork as any).nested.deep.property.value).toBe('deep value');
867
+ });
868
+ });
869
+
870
+ // ==================== SETTER BEHAVIOR ====================
871
+ describe('Setter Behavior', () => {
872
+ let fork: ForkFlowModel;
873
+
874
+ beforeEach(() => {
875
+ fork = new ForkFlowModel(mockMaster, initialProps);
876
+ });
877
+
878
+ describe('non-shared properties with setters', () => {
879
+ test('should call master setter methods in fork instances', () => {
880
+ // 直接在 master 上定义 setter
881
+ let testValue = '';
882
+ Object.defineProperty(mockMaster, 'customProperty', {
883
+ get() {
884
+ return testValue;
885
+ },
886
+ set(value: string) {
887
+ testValue = `processed_${value}`;
888
+ },
889
+ configurable: true,
890
+ enumerable: true,
891
+ });
892
+
893
+ // 在 fork 上设置属性应该调用 master 的 setter
894
+ (fork as any).customProperty = 'test_value';
895
+
896
+ // 验证 setter 被正确调用(值被处理)
897
+ expect((fork as any).customProperty).toBe('processed_test_value');
898
+ expect((mockMaster as any).customProperty).toBe('processed_test_value');
899
+ });
900
+
901
+ test('should preserve this context in fork setter calls', () => {
902
+ let setterContext: any = null;
903
+ let testValue = '';
904
+
905
+ Object.defineProperty(mockMaster, 'testProperty', {
906
+ get() {
907
+ return testValue;
908
+ },
909
+ set(value: string) {
910
+ setterContext = this;
911
+ testValue = value;
912
+ // 验证 this 指向 fork 实例,而不是 master
913
+ expect(this.isFork).toBe(true);
914
+ },
915
+ configurable: true,
916
+ enumerable: true,
917
+ });
918
+
919
+ // 在 fork 上设置属性
920
+ (fork as any).testProperty = 'context_test';
921
+
922
+ // 验证 setter 中的 this 指向 fork
923
+ expect(setterContext).toBe(fork);
924
+ expect(setterContext.isFork).toBe(true);
925
+ expect((fork as any).testProperty).toBe('context_test');
926
+ });
927
+
928
+ test('should handle non-shared properties with setters correctly', () => {
929
+ let nonSharedValue = 0;
930
+
931
+ Object.defineProperty(mockMaster, 'nonSharedProperty', {
932
+ get() {
933
+ return nonSharedValue;
934
+ },
935
+ set(value: number) {
936
+ nonSharedValue = value * 2;
937
+ },
938
+ configurable: true,
939
+ enumerable: true,
940
+ });
941
+
942
+ // 设置非共享属性应该调用 setter
943
+ (fork as any).nonSharedProperty = 5;
944
+
945
+ // 验证 setter 被调用且 this 指向正确
946
+ expect((fork as any).nonSharedProperty).toBe(10); // 5 * 2
947
+ // master 也应该受到影响,因为我们共享同一个变量
948
+ expect((mockMaster as any).nonSharedProperty).toBe(10);
949
+ });
950
+
951
+ test('should fallback to local storage when no setter exists', () => {
952
+ // 设置一个没有 setter 的属性
953
+ (fork as any).customNonSetterProperty = 'local_value';
954
+
955
+ // 应该存储在 fork 的本地属性中
956
+ expect((fork as any).customNonSetterProperty).toBe('local_value');
957
+ // master 不应该有这个属性
958
+ expect((mockMaster as any).customNonSetterProperty).toBeUndefined();
959
+ });
960
+ });
961
+
962
+ describe('shared properties with setters', () => {
963
+ test('should handle shared properties with setters', () => {
964
+ // 临时修改 SHARED_PROPERTIES 来包含我们的测试属性
965
+ const originalSharedProps = ForkFlowModel.getSharedProperties();
966
+ ForkFlowModel.setSharedProperties([...originalSharedProps, 'sharedTestProperty']);
967
+
968
+ try {
969
+ let sharedValue = '';
970
+ Object.defineProperty(mockMaster, 'sharedTestProperty', {
971
+ get() {
972
+ return sharedValue;
973
+ },
974
+ set(value: string) {
975
+ sharedValue = `shared_${value}`;
976
+ },
977
+ configurable: true,
978
+ enumerable: true,
979
+ });
980
+
981
+ // 设置共享属性应该调用 setter
982
+ (fork as any).sharedTestProperty = 'test';
983
+
984
+ // 验证 setter 被调用
985
+ expect((fork as any).sharedTestProperty).toBe('shared_test');
986
+ expect((mockMaster as any).sharedTestProperty).toBe('shared_test');
987
+ } finally {
988
+ // 恢复原始的共享属性
989
+ ForkFlowModel.setSharedProperties(originalSharedProps);
990
+ }
991
+ });
992
+
993
+ test('should handle shared properties without setters', () => {
994
+ // 临时修改 SHARED_PROPERTIES 来包含我们的测试属性
995
+ const originalSharedProps = ForkFlowModel.getSharedProperties();
996
+ ForkFlowModel.setSharedProperties([...originalSharedProps, 'plainSharedProperty']);
997
+
998
+ try {
999
+ // 设置共享属性(没有 setter)
1000
+ (fork as any).plainSharedProperty = 'shared_value';
1001
+
1002
+ // 应该直接设置在 master 上
1003
+ expect((mockMaster as any).plainSharedProperty).toBe('shared_value');
1004
+ expect((fork as any).plainSharedProperty).toBe('shared_value');
1005
+ } finally {
1006
+ // 恢复原始的共享属性
1007
+ ForkFlowModel.setSharedProperties(originalSharedProps);
1008
+ }
1009
+ });
1010
+ });
1011
+
1012
+ describe('UploadEditableFieldModel scenario', () => {
1013
+ test('should handle customRequest setter like in UploadEditableFieldModel', () => {
1014
+ // 模拟 UploadEditableFieldModel 的 customRequest setter
1015
+ let customRequestValue: any = null;
1016
+
1017
+ Object.defineProperty(mockMaster, 'customRequest', {
1018
+ set(fn: any) {
1019
+ customRequestValue = fn;
1020
+ // 模拟实际的 setter 逻辑
1021
+ console.log('customRequest setter called');
1022
+ },
1023
+ get() {
1024
+ return customRequestValue;
1025
+ },
1026
+ configurable: true,
1027
+ enumerable: true,
1028
+ });
1029
+
1030
+ const testFunction = (fileData: any) => {
1031
+ console.log('custom request executed', fileData);
1032
+ };
1033
+
1034
+ // 在 fork 上设置 customRequest 应该调用 master 的 setter
1035
+ (fork as any).customRequest = testFunction;
1036
+
1037
+ // 验证 setter 被调用,值被正确存储
1038
+ expect((mockMaster as any).customRequest).toBe(testFunction);
1039
+ expect(customRequestValue).toBe(testFunction);
1040
+
1041
+ // 注意:由于 ForkFlowModel 的 get proxy 会重新绑定函数,
1042
+ // fork.customRequest 返回的是一个绑定的版本,但原始值正确存储了
1043
+ expect(typeof (fork as any).customRequest).toBe('function');
1044
+ });
1045
+ });
1046
+ });
1047
+ });