openxiangda 1.0.264 → 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 (537) hide show
  1. package/README.md +11 -666
  2. package/bin/run.js +11 -0
  3. package/dist/browser/AuthoritativeSelector.d.ts +37 -0
  4. package/dist/browser/AuthoritativeSelector.d.ts.map +1 -0
  5. package/dist/browser/AuthoritativeSelector.js +357 -0
  6. package/dist/browser/AuthoritativeSelector.js.map +1 -0
  7. package/dist/browser/FilePreviewPage.d.ts +2 -0
  8. package/dist/browser/FilePreviewPage.d.ts.map +1 -0
  9. package/dist/browser/FilePreviewPage.js +191 -0
  10. package/dist/browser/FilePreviewPage.js.map +1 -0
  11. package/dist/browser/Shell.d.ts +6 -0
  12. package/dist/browser/Shell.d.ts.map +1 -0
  13. package/dist/browser/Shell.js +198 -0
  14. package/dist/browser/Shell.js.map +1 -0
  15. package/dist/browser/appearance.d.ts +12 -0
  16. package/dist/browser/appearance.d.ts.map +1 -0
  17. package/dist/browser/appearance.js +100 -0
  18. package/dist/browser/appearance.js.map +1 -0
  19. package/dist/browser/application.d.ts +8 -0
  20. package/dist/browser/application.d.ts.map +1 -0
  21. package/dist/browser/application.js +42 -0
  22. package/dist/browser/application.js.map +1 -0
  23. package/dist/browser/components/platform-fields/AddressField.d.ts +12 -0
  24. package/dist/browser/components/platform-fields/AddressField.d.ts.map +1 -0
  25. package/dist/browser/components/platform-fields/AddressField.js +179 -0
  26. package/dist/browser/components/platform-fields/AddressField.js.map +1 -0
  27. package/dist/browser/components/platform-fields/AttachmentFileList.d.ts +9 -0
  28. package/dist/browser/components/platform-fields/AttachmentFileList.d.ts.map +1 -0
  29. package/dist/browser/components/platform-fields/AttachmentFileList.js +164 -0
  30. package/dist/browser/components/platform-fields/AttachmentFileList.js.map +1 -0
  31. package/dist/browser/components/platform-fields/CascadeField.d.ts +13 -0
  32. package/dist/browser/components/platform-fields/CascadeField.d.ts.map +1 -0
  33. package/dist/browser/components/platform-fields/CascadeField.js +14 -0
  34. package/dist/browser/components/platform-fields/CascadeField.js.map +1 -0
  35. package/dist/browser/components/platform-fields/DateTimeField.d.ts +16 -0
  36. package/dist/browser/components/platform-fields/DateTimeField.d.ts.map +1 -0
  37. package/dist/browser/components/platform-fields/DateTimeField.js +51 -0
  38. package/dist/browser/components/platform-fields/DateTimeField.js.map +1 -0
  39. package/dist/browser/components/platform-fields/JsonField.d.ts +11 -0
  40. package/dist/browser/components/platform-fields/JsonField.d.ts.map +1 -0
  41. package/dist/browser/components/platform-fields/JsonField.js +40 -0
  42. package/dist/browser/components/platform-fields/JsonField.js.map +1 -0
  43. package/dist/browser/components/platform-fields/LocationField.d.ts +11 -0
  44. package/dist/browser/components/platform-fields/LocationField.d.ts.map +1 -0
  45. package/dist/browser/components/platform-fields/LocationField.js +73 -0
  46. package/dist/browser/components/platform-fields/LocationField.js.map +1 -0
  47. package/dist/browser/components/platform-fields/PlatformDirectoryPicker.d.ts +12 -0
  48. package/dist/browser/components/platform-fields/PlatformDirectoryPicker.d.ts.map +1 -0
  49. package/dist/browser/components/platform-fields/PlatformDirectoryPicker.js +269 -0
  50. package/dist/browser/components/platform-fields/PlatformDirectoryPicker.js.map +1 -0
  51. package/dist/browser/components/platform-fields/ResourceReferenceField.d.ts +12 -0
  52. package/dist/browser/components/platform-fields/ResourceReferenceField.d.ts.map +1 -0
  53. package/dist/browser/components/platform-fields/ResourceReferenceField.js +22 -0
  54. package/dist/browser/components/platform-fields/ResourceReferenceField.js.map +1 -0
  55. package/dist/browser/components/platform-fields/RichTextField.d.ts +14 -0
  56. package/dist/browser/components/platform-fields/RichTextField.d.ts.map +1 -0
  57. package/dist/browser/components/platform-fields/RichTextField.js +214 -0
  58. package/dist/browser/components/platform-fields/RichTextField.js.map +1 -0
  59. package/dist/browser/components/platform-fields/SignatureField.d.ts +15 -0
  60. package/dist/browser/components/platform-fields/SignatureField.d.ts.map +1 -0
  61. package/dist/browser/components/platform-fields/SignatureField.js +179 -0
  62. package/dist/browser/components/platform-fields/SignatureField.js.map +1 -0
  63. package/dist/browser/components/platform-fields/SubtableField.d.ts +18 -0
  64. package/dist/browser/components/platform-fields/SubtableField.d.ts.map +1 -0
  65. package/dist/browser/components/platform-fields/SubtableField.js +236 -0
  66. package/dist/browser/components/platform-fields/SubtableField.js.map +1 -0
  67. package/dist/browser/components/platform-fields/address-value.d.ts +13 -0
  68. package/dist/browser/components/platform-fields/address-value.d.ts.map +1 -0
  69. package/dist/browser/components/platform-fields/address-value.js +70 -0
  70. package/dist/browser/components/platform-fields/address-value.js.map +1 -0
  71. package/dist/browser/components/platform-fields/cascade-value.d.ts +6 -0
  72. package/dist/browser/components/platform-fields/cascade-value.d.ts.map +1 -0
  73. package/dist/browser/components/platform-fields/cascade-value.js +47 -0
  74. package/dist/browser/components/platform-fields/cascade-value.js.map +1 -0
  75. package/dist/browser/components/platform-fields/directory-value.d.ts +7 -0
  76. package/dist/browser/components/platform-fields/directory-value.d.ts.map +1 -0
  77. package/dist/browser/components/platform-fields/directory-value.js +35 -0
  78. package/dist/browser/components/platform-fields/directory-value.js.map +1 -0
  79. package/dist/browser/components/platform-fields/field-form-codec.d.ts +10 -0
  80. package/dist/browser/components/platform-fields/field-form-codec.d.ts.map +1 -0
  81. package/dist/browser/components/platform-fields/field-form-codec.js +82 -0
  82. package/dist/browser/components/platform-fields/field-form-codec.js.map +1 -0
  83. package/dist/browser/components/platform-fields/location-value.d.ts +20 -0
  84. package/dist/browser/components/platform-fields/location-value.d.ts.map +1 -0
  85. package/dist/browser/components/platform-fields/location-value.js +57 -0
  86. package/dist/browser/components/platform-fields/location-value.js.map +1 -0
  87. package/dist/browser/components/platform-fields/resource-query.d.ts +14 -0
  88. package/dist/browser/components/platform-fields/resource-query.d.ts.map +1 -0
  89. package/dist/browser/components/platform-fields/resource-query.js +102 -0
  90. package/dist/browser/components/platform-fields/resource-query.js.map +1 -0
  91. package/dist/browser/components/platform-fields/rich-text-value.d.ts +12 -0
  92. package/dist/browser/components/platform-fields/rich-text-value.d.ts.map +1 -0
  93. package/dist/browser/components/platform-fields/rich-text-value.js +83 -0
  94. package/dist/browser/components/platform-fields/rich-text-value.js.map +1 -0
  95. package/dist/browser/components/platform-fields/subtable-value.d.ts +31 -0
  96. package/dist/browser/components/platform-fields/subtable-value.d.ts.map +1 -0
  97. package/dist/browser/components/platform-fields/subtable-value.js +120 -0
  98. package/dist/browser/components/platform-fields/subtable-value.js.map +1 -0
  99. package/dist/browser/components/resource/GeneratedResourceCrud.d.ts +8 -0
  100. package/dist/browser/components/resource/GeneratedResourceCrud.d.ts.map +1 -0
  101. package/dist/browser/components/resource/GeneratedResourceCrud.js +580 -0
  102. package/dist/browser/components/resource/GeneratedResourceCrud.js.map +1 -0
  103. package/dist/browser/components/resource/ResourceBatchActions.d.ts +25 -0
  104. package/dist/browser/components/resource/ResourceBatchActions.d.ts.map +1 -0
  105. package/dist/browser/components/resource/ResourceBatchActions.js +168 -0
  106. package/dist/browser/components/resource/ResourceBatchActions.js.map +1 -0
  107. package/dist/browser/components/resource/StandardResourcePages.d.ts +57 -0
  108. package/dist/browser/components/resource/StandardResourcePages.d.ts.map +1 -0
  109. package/dist/browser/components/resource/StandardResourcePages.js +89 -0
  110. package/dist/browser/components/resource/StandardResourcePages.js.map +1 -0
  111. package/dist/browser/components/resource/SurfaceFields.d.ts +88 -0
  112. package/dist/browser/components/resource/SurfaceFields.d.ts.map +1 -0
  113. package/dist/browser/components/resource/SurfaceFields.js +497 -0
  114. package/dist/browser/components/resource/SurfaceFields.js.map +1 -0
  115. package/dist/browser/components/resource/generated-resource-definition.d.ts +19 -0
  116. package/dist/browser/components/resource/generated-resource-definition.d.ts.map +1 -0
  117. package/dist/browser/components/resource/generated-resource-definition.js +2 -0
  118. package/dist/browser/components/resource/generated-resource-definition.js.map +1 -0
  119. package/dist/browser/components/resource/resource-import.d.ts +15 -0
  120. package/dist/browser/components/resource/resource-import.d.ts.map +1 -0
  121. package/dist/browser/components/resource/resource-import.js +197 -0
  122. package/dist/browser/components/resource/resource-import.js.map +1 -0
  123. package/dist/browser/data-provider.d.ts +4 -0
  124. package/dist/browser/data-provider.d.ts.map +1 -0
  125. package/dist/browser/data-provider.js +45 -0
  126. package/dist/browser/data-provider.js.map +1 -0
  127. package/dist/browser/platform-client.d.ts +81 -0
  128. package/dist/browser/platform-client.d.ts.map +1 -0
  129. package/dist/browser/platform-client.js +422 -0
  130. package/dist/browser/platform-client.js.map +1 -0
  131. package/dist/browser/resource-definitions.d.ts +8 -0
  132. package/dist/browser/resource-definitions.d.ts.map +1 -0
  133. package/dist/browser/resource-definitions.js +14 -0
  134. package/dist/browser/resource-definitions.js.map +1 -0
  135. package/dist/browser/runtime-meta.d.ts +22 -0
  136. package/dist/browser/runtime-meta.d.ts.map +1 -0
  137. package/dist/browser/runtime-meta.js +79 -0
  138. package/dist/browser/runtime-meta.js.map +1 -0
  139. package/dist/browser/runtime.d.ts +13 -0
  140. package/dist/browser/runtime.d.ts.map +1 -0
  141. package/dist/browser/runtime.js +47 -0
  142. package/dist/browser/runtime.js.map +1 -0
  143. package/dist/browser/styles.css +1941 -0
  144. package/dist/config.d.ts +2 -0
  145. package/dist/config.d.ts.map +1 -0
  146. package/dist/config.js +2 -0
  147. package/dist/config.js.map +1 -0
  148. package/dist/core.d.ts +6 -0
  149. package/dist/core.d.ts.map +1 -0
  150. package/dist/core.js +4 -0
  151. package/dist/core.js.map +1 -0
  152. package/dist/field-kit.d.ts +22 -0
  153. package/dist/field-kit.d.ts.map +1 -0
  154. package/dist/field-kit.js +22 -0
  155. package/dist/field-kit.js.map +1 -0
  156. package/dist/index.d.ts +2 -0
  157. package/dist/index.d.ts.map +1 -0
  158. package/dist/index.js +2 -0
  159. package/dist/index.js.map +1 -0
  160. package/dist/nest.d.ts +10 -0
  161. package/dist/nest.d.ts.map +1 -0
  162. package/dist/nest.js +9 -0
  163. package/dist/nest.js.map +1 -0
  164. package/dist/react.d.ts +12 -0
  165. package/dist/react.d.ts.map +1 -0
  166. package/dist/react.js +11 -0
  167. package/dist/react.js.map +1 -0
  168. package/dist/testing.d.ts +4 -0
  169. package/dist/testing.d.ts.map +1 -0
  170. package/dist/testing.js +4 -0
  171. package/dist/testing.js.map +1 -0
  172. package/package.json +95 -200
  173. package/skills/manifest.json +10 -0
  174. package/skills/openxiangda-v2/SKILL.md +55 -0
  175. package/skills/openxiangda-v2/references/architecture.md +7 -0
  176. package/skills/openxiangda-v2/references/backend.md +116 -0
  177. package/skills/openxiangda-v2/references/data-authz.md +93 -0
  178. package/skills/openxiangda-v2/references/delivery.md +11 -0
  179. package/skills/openxiangda-v2/references/discovery.md +15 -0
  180. package/skills/openxiangda-v2/references/frontend.md +10 -0
  181. package/skills/openxiangda-v2/references/testing.md +16 -0
  182. package/skills/openxiangda-v2/references/workflow-notification.md +69 -0
  183. package/skills/openxiangda-v2/references/workspace.md +21 -0
  184. package/bin/openxiangda.js +0 -26
  185. package/lib/app-function-invoke.js +0 -28
  186. package/lib/application-environments.js +0 -1134
  187. package/lib/change-baseline.js +0 -1359
  188. package/lib/cli.js +0 -31084
  189. package/lib/config.js +0 -450
  190. package/lib/content-cache.js +0 -97
  191. package/lib/delivery-v2-cli.js +0 -329
  192. package/lib/delivery-v2-executor.js +0 -1703
  193. package/lib/delivery-v2-package.js +0 -1176
  194. package/lib/dependency-capsule.js +0 -246
  195. package/lib/design-gates.js +0 -668
  196. package/lib/design-review.js +0 -220
  197. package/lib/developer-center.js +0 -160
  198. package/lib/form-field-contract.js +0 -79
  199. package/lib/form-schema-loader.js +0 -181
  200. package/lib/git-remote-identity.js +0 -89
  201. package/lib/http.js +0 -196
  202. package/lib/integration-bundle.js +0 -225
  203. package/lib/js-code-build.js +0 -175
  204. package/lib/open-api.js +0 -256
  205. package/lib/policy.js +0 -137
  206. package/lib/publish-context.js +0 -98
  207. package/lib/publish-lease-heartbeat.js +0 -182
  208. package/lib/publish-lease.js +0 -221
  209. package/lib/release-error-classification.js +0 -41
  210. package/lib/release-explain.js +0 -75
  211. package/lib/release-mainline.js +0 -654
  212. package/lib/release-plan.js +0 -550
  213. package/lib/release-telemetry.js +0 -182
  214. package/lib/resource-binding-contract.js +0 -210
  215. package/lib/role-resolution.js +0 -57
  216. package/lib/runtime-lineage.js +0 -326
  217. package/lib/sdd.js +0 -3306
  218. package/lib/skills.js +0 -453
  219. package/lib/source-dependencies.js +0 -921
  220. package/lib/task-status.js +0 -330
  221. package/lib/utils.js +0 -178
  222. package/lib/workspace-bootstrap.js +0 -268
  223. package/lib/workspace-init.js +0 -202
  224. package/lib/worktree-cleanup.js +0 -631
  225. package/lib/worktree-owner.js +0 -354
  226. package/openxiangda-skills/SKILL.md +0 -226
  227. package/openxiangda-skills/references/architecture-design.md +0 -409
  228. package/openxiangda-skills/references/architecture-patterns.md +0 -264
  229. package/openxiangda-skills/references/automation-v3.md +0 -349
  230. package/openxiangda-skills/references/best-practices.md +0 -272
  231. package/openxiangda-skills/references/component-guide.md +0 -287
  232. package/openxiangda-skills/references/connector-resources.md +0 -80
  233. package/openxiangda-skills/references/data-views.md +0 -360
  234. package/openxiangda-skills/references/forms/component-registry.md +0 -90
  235. package/openxiangda-skills/references/forms/form-schema.md +0 -146
  236. package/openxiangda-skills/references/forms/layout-and-rules.md +0 -24
  237. package/openxiangda-skills/references/notifications.md +0 -227
  238. package/openxiangda-skills/references/openxiangda-api.md +0 -971
  239. package/openxiangda-skills/references/pages/app-shell.md +0 -66
  240. package/openxiangda-skills/references/pages/page-sdk.md +0 -401
  241. package/openxiangda-skills/references/pages/publish-flow.md +0 -84
  242. package/openxiangda-skills/references/pages/workspace-structure.md +0 -41
  243. package/openxiangda-skills/references/permission-design-patterns.md +0 -313
  244. package/openxiangda-skills/references/permissions-settings.md +0 -468
  245. package/openxiangda-skills/references/platform-data-model.md +0 -340
  246. package/openxiangda-skills/references/resource-manifest-cheatsheet.md +0 -936
  247. package/openxiangda-skills/references/school-contact-relations.md +0 -224
  248. package/openxiangda-skills/references/style-system.md +0 -218
  249. package/openxiangda-skills/references/troubleshooting.md +0 -271
  250. package/openxiangda-skills/references/workflow-v3.md +0 -441
  251. package/openxiangda-skills/references/workspace-state.md +0 -115
  252. package/openxiangda-skills/skills/openxiangda-app/SKILL.md +0 -118
  253. package/openxiangda-skills/skills/openxiangda-architecture-design/SKILL.md +0 -137
  254. package/openxiangda-skills/skills/openxiangda-core/SKILL.md +0 -222
  255. package/openxiangda-skills/skills/openxiangda-form/SKILL.md +0 -184
  256. package/openxiangda-skills/skills/openxiangda-inspect/SKILL.md +0 -63
  257. package/openxiangda-skills/skills/openxiangda-open-api/SKILL.md +0 -57
  258. package/openxiangda-skills/skills/openxiangda-open-api/agents/openai.yaml +0 -4
  259. package/openxiangda-skills/skills/openxiangda-open-api/references/backend-authentication.md +0 -63
  260. package/openxiangda-skills/skills/openxiangda-open-api/references/dingtalk-api.openapi.json +0 -15653
  261. package/openxiangda-skills/skills/openxiangda-page/SKILL.md +0 -154
  262. package/openxiangda-skills/skills/openxiangda-permission-settings/SKILL.md +0 -209
  263. package/openxiangda-skills/skills/openxiangda-workflow-automation/SKILL.md +0 -201
  264. package/packages/sdk/bin/lowcode-workspace.mjs +0 -4
  265. package/packages/sdk/dist/ProcessPreview-DSUIJi5V.d.mts +0 -1292
  266. package/packages/sdk/dist/ProcessPreview-DSUIJi5V.d.ts +0 -1292
  267. package/packages/sdk/dist/build/index.cjs +0 -1
  268. package/packages/sdk/dist/build/index.d.mts +0 -60
  269. package/packages/sdk/dist/build/index.d.ts +0 -60
  270. package/packages/sdk/dist/build/index.mjs +0 -1
  271. package/packages/sdk/dist/components/index.cjs +0 -148
  272. package/packages/sdk/dist/components/index.d.mts +0 -970
  273. package/packages/sdk/dist/components/index.d.ts +0 -970
  274. package/packages/sdk/dist/components/index.mjs +0 -148
  275. package/packages/sdk/dist/dataManagementApi-Ro9itwm8.d.ts +0 -142
  276. package/packages/sdk/dist/dataManagementApi-p_HOhQnA.d.mts +0 -142
  277. package/packages/sdk/dist/runtime/index.cjs +0 -148
  278. package/packages/sdk/dist/runtime/index.d.mts +0 -171
  279. package/packages/sdk/dist/runtime/index.d.ts +0 -171
  280. package/packages/sdk/dist/runtime/index.mjs +0 -148
  281. package/packages/sdk/dist/runtime/react.cjs +0 -148
  282. package/packages/sdk/dist/runtime/react.d.mts +0 -3202
  283. package/packages/sdk/dist/runtime/react.d.ts +0 -3202
  284. package/packages/sdk/dist/runtime/react.mjs +0 -148
  285. package/packages/sdk/dist/styles/antd-theme.cjs +0 -1
  286. package/packages/sdk/dist/styles/antd-theme.d.mts +0 -6
  287. package/packages/sdk/dist/styles/antd-theme.d.ts +0 -6
  288. package/packages/sdk/dist/styles/antd-theme.mjs +0 -1
  289. package/packages/sdk/dist/styles/tailwind-preset.cjs +0 -1
  290. package/packages/sdk/dist/styles/tailwind-preset.d.mts +0 -74
  291. package/packages/sdk/dist/styles/tailwind-preset.d.ts +0 -74
  292. package/packages/sdk/dist/styles/tailwind-preset.mjs +0 -1
  293. package/packages/sdk/dist/styles/tokens.css +0 -74
  294. package/packages/sdk/dist/workflow/index.cjs +0 -3
  295. package/packages/sdk/dist/workflow/index.d.mts +0 -291
  296. package/packages/sdk/dist/workflow/index.d.ts +0 -291
  297. package/packages/sdk/dist/workflow/index.mjs +0 -3
  298. package/packages/sdk/source/admin-list/AdminList.tsx +0 -1734
  299. package/packages/sdk/source/admin-list/README.md +0 -12
  300. package/packages/sdk/source/admin-list/dataSources.ts +0 -345
  301. package/packages/sdk/source/admin-list/index.ts +0 -42
  302. package/packages/sdk/source/admin-list/preferences.ts +0 -174
  303. package/packages/sdk/source/admin-list/types.ts +0 -273
  304. package/packages/sdk/src/build-source/README.md +0 -9
  305. package/packages/sdk/src/build-source/bin/lowcode-workspace.mjs +0 -7
  306. package/packages/sdk/src/build-source/package.json +0 -34
  307. package/packages/sdk/src/build-source/scripts/build-forms.mjs +0 -1129
  308. package/packages/sdk/src/build-source/scripts/build-pages.mjs +0 -897
  309. package/packages/sdk/src/build-source/scripts/build-workspace.mjs +0 -89
  310. package/packages/sdk/src/build-source/scripts/publish-all.mjs +0 -190
  311. package/packages/sdk/src/build-source/scripts/publish-oss.mjs +0 -144
  312. package/packages/sdk/src/build-source/scripts/register-bundle.mjs +0 -1
  313. package/packages/sdk/src/build-source/scripts/register.mjs +0 -362
  314. package/packages/sdk/src/build-source/scripts/sync-schema.mjs +0 -381
  315. package/packages/sdk/src/build-source/scripts/utils/form-api.mjs +0 -1058
  316. package/packages/sdk/src/build-source/scripts/utils/form-runtime-assets.mjs +0 -57
  317. package/packages/sdk/src/build-source/scripts/utils/incremental.mjs +0 -348
  318. package/packages/sdk/src/build-source/scripts/utils/load-config.mjs +0 -331
  319. package/packages/sdk/src/build-source/scripts/utils/mime-types.mjs +0 -70
  320. package/packages/sdk/src/build-source/scripts/utils/namespace-css.mjs +0 -77
  321. package/packages/sdk/src/build-source/scripts/utils/oss-client.mjs +0 -128
  322. package/packages/sdk/src/build-source/scripts/utils/pages.mjs +0 -150
  323. package/packages/sdk/src/build-source/scripts/utils/progress.mjs +0 -57
  324. package/packages/sdk/src/build-source/scripts/utils/publish-oss-patterns.mjs +0 -20
  325. package/packages/sdk/src/build-source/scripts/utils/register-payload.mjs +0 -90
  326. package/packages/sdk/src/build-source/scripts/utils/runtime-css-check.mjs +0 -44
  327. package/packages/sdk/src/build-source/scripts/utils/schema-transform.mjs +0 -142
  328. package/packages/sdk/src/build-source/scripts/utils/static-assets.mjs +0 -165
  329. package/packages/sdk/src/build-source/scripts/utils/tailwind-config.mjs +0 -283
  330. package/packages/sdk/src/build-source/scripts/utils/tailwind-token-warnings.mjs +0 -146
  331. package/packages/sdk/src/build-source/scripts/utils/workspace-style-entry.mjs +0 -29
  332. package/packages/sdk/src/build-source/src/cli.mjs +0 -735
  333. package/policy/openxiangda-policy.json +0 -72
  334. package/templates/openxiangda-react-spa/.cursor/rules/openxiangda-form.mdc +0 -24
  335. package/templates/openxiangda-react-spa/.cursor/rules/openxiangda-page.mdc +0 -25
  336. package/templates/openxiangda-react-spa/.cursor/rules/openxiangda-resources.mdc +0 -32
  337. package/templates/openxiangda-react-spa/.cursor/rules/openxiangda-workflow-automation.mdc +0 -26
  338. package/templates/openxiangda-react-spa/.cursor/rules/openxiangda.mdc +0 -68
  339. package/templates/openxiangda-react-spa/.env.example +0 -4
  340. package/templates/openxiangda-react-spa/.qoder/rules/openxiangda-form.md +0 -37
  341. package/templates/openxiangda-react-spa/.qoder/rules/openxiangda-page.md +0 -29
  342. package/templates/openxiangda-react-spa/.qoder/rules/openxiangda-resources.md +0 -32
  343. package/templates/openxiangda-react-spa/.qoder/rules/openxiangda-workflow-automation.md +0 -34
  344. package/templates/openxiangda-react-spa/.qoder/rules/openxiangda.md +0 -66
  345. package/templates/openxiangda-react-spa/AGENTS.md +0 -192
  346. package/templates/openxiangda-react-spa/DELIVERY.md +0 -43
  347. package/templates/openxiangda-react-spa/app-workspace.config.ts +0 -50
  348. package/templates/openxiangda-react-spa/index.html +0 -12
  349. package/templates/openxiangda-react-spa/package.json +0 -53
  350. package/templates/openxiangda-react-spa/postcss.config.cjs +0 -6
  351. package/templates/openxiangda-react-spa/scripts/build-js-code.mjs +0 -600
  352. package/templates/openxiangda-react-spa/scripts/deploy.mjs +0 -18
  353. package/templates/openxiangda-react-spa/scripts/guard-publish.mjs +0 -21
  354. package/templates/openxiangda-react-spa/src/app/navigation.ts +0 -73
  355. package/templates/openxiangda-react-spa/src/app/router.tsx +0 -146
  356. package/templates/openxiangda-react-spa/src/app/starter-content.ts +0 -144
  357. package/templates/openxiangda-react-spa/src/forms/.gitkeep +0 -1
  358. package/templates/openxiangda-react-spa/src/layouts/AdminShell.tsx +0 -570
  359. package/templates/openxiangda-react-spa/src/main.tsx +0 -21
  360. package/templates/openxiangda-react-spa/src/pages/admin/AdminDashboardPage.tsx +0 -170
  361. package/templates/openxiangda-react-spa/src/pages/admin/LoginLogPage.tsx +0 -425
  362. package/templates/openxiangda-react-spa/src/pages/defaults/DataRoutePage.tsx +0 -36
  363. package/templates/openxiangda-react-spa/src/pages/defaults/FilePreviewRoutePage.tsx +0 -65
  364. package/templates/openxiangda-react-spa/src/pages/defaults/FormRoutePage.tsx +0 -235
  365. package/templates/openxiangda-react-spa/src/pages/public/PublicRegisterPage.tsx +0 -15
  366. package/templates/openxiangda-react-spa/src/pages/states/NotFoundPage.tsx +0 -31
  367. package/templates/openxiangda-react-spa/src/resources/menus/menus.json +0 -22
  368. package/templates/openxiangda-react-spa/src/resources/permissions/page-groups/app-admin.json +0 -8
  369. package/templates/openxiangda-react-spa/src/resources/permissions/page-groups/public-visitor.json +0 -8
  370. package/templates/openxiangda-react-spa/src/resources/public-access/public-register.json +0 -14
  371. package/templates/openxiangda-react-spa/src/resources/roles/roles.json +0 -15
  372. package/templates/openxiangda-react-spa/src/resources/routes/public-register.json +0 -8
  373. package/templates/openxiangda-react-spa/src/runtime/default-page-overrides.tsx +0 -35
  374. package/templates/openxiangda-react-spa/src/runtime/default-routes.ts +0 -16
  375. package/templates/openxiangda-react-spa/src/shared/form-schema.ts +0 -135
  376. package/templates/openxiangda-react-spa/src/shared/mac-admin.tsx +0 -651
  377. package/templates/openxiangda-react-spa/src/shared/ui.tsx +0 -22
  378. package/templates/openxiangda-react-spa/src/styles/index.css +0 -105
  379. package/templates/openxiangda-react-spa/tailwind.config.cjs +0 -37
  380. package/templates/openxiangda-react-spa/tsconfig.app.json +0 -36
  381. package/templates/openxiangda-react-spa/tsconfig.js-code-nodes.json +0 -19
  382. package/templates/openxiangda-react-spa/tsconfig.json +0 -7
  383. package/templates/openxiangda-react-spa/tsconfig.node.json +0 -10
  384. package/templates/openxiangda-react-spa/vite.config.ts +0 -209
  385. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-form.mdc +0 -24
  386. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-page.mdc +0 -21
  387. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-resources.mdc +0 -40
  388. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-workflow-automation.mdc +0 -21
  389. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda.mdc +0 -81
  390. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-form.md +0 -38
  391. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-page.md +0 -39
  392. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-resources.md +0 -59
  393. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-workflow-automation.md +0 -46
  394. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda.md +0 -82
  395. package/templates/sy-lowcode-app-workspace/AGENTS.md +0 -158
  396. package/templates/sy-lowcode-app-workspace/DELIVERY.md +0 -43
  397. package/templates/sy-lowcode-app-workspace/app-workspace.config.ts +0 -51
  398. package/templates/sy-lowcode-app-workspace/examples/best-practices/README.md +0 -43
  399. package/templates/sy-lowcode-app-workspace/examples/best-practices/access-governance.md +0 -239
  400. package/templates/sy-lowcode-app-workspace/examples/best-practices/catalog.json +0 -99
  401. package/templates/sy-lowcode-app-workspace/examples/best-practices/decision-guide.md +0 -94
  402. package/templates/sy-lowcode-app-workspace/examples/best-practices/design-style.md +0 -91
  403. package/templates/sy-lowcode-app-workspace/examples/best-practices/module-structure.md +0 -48
  404. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/role-governance/index.ts +0 -2
  405. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/role-governance/permissions.test.ts +0 -52
  406. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/role-governance/permissions.ts +0 -37
  407. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/role-governance/types.ts +0 -19
  408. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/index.ts +0 -4
  409. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/permissions.test.ts +0 -42
  410. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/permissions.ts +0 -25
  411. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/state-machine.test.ts +0 -63
  412. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/state-machine.ts +0 -73
  413. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/ticket-query.test.ts +0 -34
  414. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/ticket-query.ts +0 -73
  415. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/types.ts +0 -66
  416. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/app-role/page.tsx +0 -1
  417. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/app-role/schema.ts +0 -109
  418. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/customer-profile/page.tsx +0 -1
  419. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/customer-profile/schema.ts +0 -92
  420. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/service-ticket/page.tsx +0 -1
  421. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/service-ticket/schema.ts +0 -153
  422. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/ticket-action-log/page.tsx +0 -1
  423. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/ticket-action-log/schema.ts +0 -65
  424. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/js-code-nodes/daily_ticket_digest/index.ts +0 -44
  425. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/js-code-nodes/sync_roles_to_platform/index.ts +0 -33
  426. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/glass-home-dashboard/App.tsx +0 -8
  427. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/glass-home-dashboard/GlassHomeDashboard.tsx +0 -232
  428. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/glass-home-dashboard/index.tsx +0 -10
  429. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/glass-home-dashboard/page.config.ts +0 -14
  430. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/glass-home-dashboard/styles.css +0 -196
  431. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/App.tsx +0 -7
  432. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/WorkbenchPage.tsx +0 -36
  433. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/components/ConfigPanel.tsx +0 -34
  434. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/components/PreviewPanel.tsx +0 -17
  435. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/index.tsx +0 -10
  436. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/page.config.ts +0 -9
  437. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/reducer.ts +0 -29
  438. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/styles.css +0 -24
  439. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mint-analytics-dashboard/App.tsx +0 -8
  440. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mint-analytics-dashboard/MintAnalyticsDashboard.tsx +0 -279
  441. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mint-analytics-dashboard/index.tsx +0 -10
  442. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mint-analytics-dashboard/page.config.ts +0 -14
  443. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mint-analytics-dashboard/styles.css +0 -163
  444. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/App.tsx +0 -7
  445. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/MobilePortalShell.tsx +0 -31
  446. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/index.tsx +0 -10
  447. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/modules/MobileHome.tsx +0 -13
  448. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/page.config.ts +0 -14
  449. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/routes.ts +0 -13
  450. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/styles.css +0 -11
  451. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/ops-monitor-dashboard/App.tsx +0 -8
  452. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/ops-monitor-dashboard/OpsMonitorDashboard.tsx +0 -306
  453. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/ops-monitor-dashboard/index.tsx +0 -10
  454. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/ops-monitor-dashboard/page.config.ts +0 -14
  455. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/ops-monitor-dashboard/styles.css +0 -248
  456. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/App.tsx +0 -7
  457. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/PcPortalShell.tsx +0 -35
  458. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/components/PortalMetric.tsx +0 -11
  459. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/index.tsx +0 -10
  460. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/modules/HomeModule.tsx +0 -25
  461. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/modules/TicketsModule.tsx +0 -14
  462. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/page.config.ts +0 -14
  463. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/routes.ts +0 -19
  464. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/styles.css +0 -35
  465. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/App.tsx +0 -7
  466. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/TicketOpsPage.tsx +0 -105
  467. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/components/TicketActionTimeline.tsx +0 -22
  468. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/components/TicketDetailDrawer.tsx +0 -44
  469. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/components/TicketTableActions.tsx +0 -57
  470. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/index.tsx +0 -10
  471. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/page.config.ts +0 -9
  472. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/styles.css +0 -35
  473. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/work-order-list-drawer/App.tsx +0 -8
  474. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/work-order-list-drawer/WorkOrderListDrawerPage.tsx +0 -371
  475. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/work-order-list-drawer/index.tsx +0 -10
  476. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/work-order-list-drawer/page.config.ts +0 -14
  477. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/work-order-list-drawer/styles.css +0 -182
  478. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/automations/daily-ticket-digest/automation.json +0 -25
  479. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/automations/daily-ticket-digest/trigger.json +0 -9
  480. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/notifications/daily-ticket-digest.json +0 -24
  481. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/permissions/form-groups/service-ticket-college.json +0 -21
  482. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/permissions/roles.json +0 -17
  483. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/workflows/expense-approval-workflow.json +0 -48
  484. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/ConfirmAction.tsx +0 -22
  485. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/QueryState.tsx +0 -37
  486. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/StatusTag.tsx +0 -20
  487. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/admin-ui-templates/DashboardPrimitives.tsx +0 -832
  488. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/admin-ui-templates/chartOptions.ts +0 -140
  489. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/admin-ui-templates/sampleData.ts +0 -466
  490. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/admin-ui-templates/styles.css +0 -874
  491. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/admin-ui-templates/types.ts +0 -150
  492. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/hooks/useTicketOps.ts +0 -96
  493. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/services/role-governance.ts +0 -48
  494. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/services/service-ticket.ts +0 -113
  495. package/templates/sy-lowcode-app-workspace/examples/forms/customer/page.tsx +0 -1
  496. package/templates/sy-lowcode-app-workspace/examples/forms/customer/schema.ts +0 -36
  497. package/templates/sy-lowcode-app-workspace/index.html +0 -12
  498. package/templates/sy-lowcode-app-workspace/package.json +0 -58
  499. package/templates/sy-lowcode-app-workspace/postcss.config.cjs +0 -9
  500. package/templates/sy-lowcode-app-workspace/scripts/build-js-code.mjs +0 -600
  501. package/templates/sy-lowcode-app-workspace/scripts/guard-publish.mjs +0 -29
  502. package/templates/sy-lowcode-app-workspace/src/dev/App.tsx +0 -820
  503. package/templates/sy-lowcode-app-workspace/src/forms/.gitkeep +0 -1
  504. package/templates/sy-lowcode-app-workspace/src/forms/README.md +0 -52
  505. package/templates/sy-lowcode-app-workspace/src/index.css +0 -26
  506. package/templates/sy-lowcode-app-workspace/src/js-code-nodes/.gitkeep +0 -1
  507. package/templates/sy-lowcode-app-workspace/src/js-code-nodes/types.d.ts +0 -3
  508. package/templates/sy-lowcode-app-workspace/src/main.tsx +0 -29
  509. package/templates/sy-lowcode-app-workspace/src/pages/.gitkeep +0 -1
  510. package/templates/sy-lowcode-app-workspace/src/runtime/builtin-overrides.tsx +0 -8
  511. package/templates/sy-lowcode-app-workspace/src/shared/form-schema.ts +0 -135
  512. package/templates/sy-lowcode-app-workspace/src/types/app-workspace.types.ts +0 -88
  513. package/templates/sy-lowcode-app-workspace/tailwind.config.cjs +0 -31
  514. package/templates/sy-lowcode-app-workspace/tsconfig.app.json +0 -40
  515. package/templates/sy-lowcode-app-workspace/tsconfig.examples.json +0 -24
  516. package/templates/sy-lowcode-app-workspace/tsconfig.js-code-nodes.json +0 -19
  517. package/templates/sy-lowcode-app-workspace/tsconfig.json +0 -7
  518. package/templates/sy-lowcode-app-workspace/tsconfig.node.json +0 -10
  519. package/templates/sy-lowcode-app-workspace/vite.config.ts +0 -85
  520. package/v2/README.md +0 -35
  521. package/v2/skills/manifest.json +0 -45
  522. package/v2/skills/openxiangda-v1-maintenance/SKILL.md +0 -21
  523. package/v2/skills/openxiangda-v1-maintenance/agents/openai.yaml +0 -4
  524. package/v2/skills/openxiangda-v2/SKILL.md +0 -38
  525. package/v2/skills/openxiangda-v2-architecture/SKILL.md +0 -29
  526. package/v2/skills/openxiangda-v2-architecture/agents/openai.yaml +0 -4
  527. package/v2/skills/openxiangda-v2-backend/SKILL.md +0 -28
  528. package/v2/skills/openxiangda-v2-backend/agents/openai.yaml +0 -4
  529. package/v2/skills/openxiangda-v2-data-authz/SKILL.md +0 -28
  530. package/v2/skills/openxiangda-v2-data-authz/agents/openai.yaml +0 -4
  531. package/v2/skills/openxiangda-v2-delivery/SKILL.md +0 -30
  532. package/v2/skills/openxiangda-v2-delivery/agents/openai.yaml +0 -4
  533. package/v2/skills/openxiangda-v2-frontend/SKILL.md +0 -21
  534. package/v2/skills/openxiangda-v2-frontend/agents/openai.yaml +0 -4
  535. package/v2/skills/openxiangda-v2-workflow-events/SKILL.md +0 -28
  536. package/v2/skills/openxiangda-v2-workflow-events/agents/openai.yaml +0 -4
  537. /package/{v2/skills → skills}/openxiangda-v2/agents/openai.yaml +0 -0
@@ -1,1058 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import crypto from "node:crypto";
4
- import { getApiBaseUrl, rootDir } from "./load-config.mjs";
5
-
6
- const PROJECT_STATE_FILE = ".openxiangda/state.json";
7
-
8
- function readJson(filePath, fallback) {
9
- try {
10
- return JSON.parse(fs.readFileSync(filePath, "utf-8"));
11
- } catch {
12
- return fallback;
13
- }
14
- }
15
-
16
- function getWorkspaceRoot(config) {
17
- return config.workspaceRoot || rootDir;
18
- }
19
-
20
- function getProjectStatePath(config) {
21
- return path.join(getWorkspaceRoot(config), PROJECT_STATE_FILE);
22
- }
23
-
24
- function loadProjectState(config) {
25
- return readJson(getProjectStatePath(config), {
26
- version: 1,
27
- profiles: {},
28
- });
29
- }
30
-
31
- function saveProjectState(config, state) {
32
- const statePath = getProjectStatePath(config);
33
- fs.mkdirSync(path.dirname(statePath), { recursive: true });
34
- const normalized = {
35
- version: 1,
36
- ...state,
37
- profiles: state.profiles || {},
38
- };
39
- const tempPath = `${statePath}.${process.pid}.tmp`;
40
- fs.writeFileSync(tempPath, `${JSON.stringify(normalized, null, 2)}\n`, "utf-8");
41
- fs.renameSync(tempPath, statePath);
42
- }
43
-
44
- function normalizeBaseUrl(value) {
45
- return String(value || "").replace(/\/+$/, "");
46
- }
47
-
48
- function ensureResourceBuckets(bound) {
49
- bound.resources = bound.resources || {};
50
- bound.resources.forms = bound.resources.forms || {};
51
- bound.resources.pages = bound.resources.pages || {};
52
- bound.resources.workflows = bound.resources.workflows || {};
53
- bound.resources.automations = bound.resources.automations || {};
54
- bound.resources.menus = bound.resources.menus || {};
55
- bound.resources.roles = bound.resources.roles || {};
56
- bound.resources.dataViews = bound.resources.dataViews || {};
57
- bound.resources.storageConfigs = bound.resources.storageConfigs || {};
58
- bound.resources.pagePermissionGroups = bound.resources.pagePermissionGroups || {};
59
- bound.resources.formPermissionGroups = bound.resources.formPermissionGroups || {};
60
- }
61
-
62
- function resolveProjectProfileName(config, state) {
63
- if (config.openXiangdaProfile) return config.openXiangdaProfile;
64
-
65
- const profiles = Object.entries(state.profiles || {});
66
- const platformUrl = normalizeBaseUrl(config.platformUrl);
67
- const matched = profiles.find(([, bound]) => {
68
- if (bound?.appType !== config.appType) return false;
69
- const boundBaseUrl = normalizeBaseUrl(bound?.baseUrl);
70
- return !platformUrl || !boundBaseUrl || platformUrl === boundBaseUrl;
71
- });
72
- return matched?.[0] || "";
73
- }
74
-
75
- function resolveProjectStateBinding(config, state) {
76
- const targetName = String(config.openXiangdaTarget || "").trim();
77
- if (targetName) {
78
- const bound = state.targets?.[targetName];
79
- if (!bound) {
80
- throw new Error(
81
- `OPENXIANGDA_TARGET_NOT_BOUND: 托管环境 target 不存在: ${targetName}`,
82
- );
83
- }
84
- if (String(bound.appType || "") !== String(config.appType || "")) {
85
- throw new Error(
86
- `OPENXIANGDA_TARGET_APP_MISMATCH: target ${targetName} 绑定 ${bound.appType || "<empty>"},发布目标为 ${config.appType || "<empty>"}`,
87
- );
88
- }
89
- return {
90
- scope: "target",
91
- key: targetName,
92
- bound,
93
- };
94
- }
95
-
96
- const profileName = resolveProjectProfileName(config, state);
97
- if (!profileName) return null;
98
- return {
99
- scope: "profile",
100
- key: profileName,
101
- bound: state.profiles?.[profileName],
102
- };
103
- }
104
-
105
- function readWorkspaceFormBinding(config, formName) {
106
- if (!isOpenXiangdaMode(config)) return null;
107
- const state = loadProjectState(config);
108
- const binding = resolveProjectStateBinding(config, state);
109
- if (!binding) return null;
110
- const bound = binding.bound;
111
- const form = bound?.resources?.forms?.[formName];
112
- if (!form?.formUuid) return null;
113
- return {
114
- profileName:
115
- binding.scope === "profile"
116
- ? binding.key
117
- : String(bound?.profile || config.openXiangdaProfile || ""),
118
- targetName: binding.scope === "target" ? binding.key : "",
119
- bound,
120
- form,
121
- };
122
- }
123
-
124
- function saveWorkspaceFormBinding(config, formName, formUuid, extra = {}) {
125
- if (!isOpenXiangdaMode(config) || !formUuid) return false;
126
-
127
- const state = loadProjectState(config);
128
- const targetName = String(config.openXiangdaTarget || "").trim();
129
- let bound;
130
- if (targetName) {
131
- const binding = resolveProjectStateBinding(config, state);
132
- bound = binding.bound;
133
- } else {
134
- const profileName =
135
- resolveProjectProfileName(config, state) ||
136
- config.openXiangdaProfile ||
137
- config.appType ||
138
- "default";
139
- state.profiles = state.profiles || {};
140
- state.profiles[profileName] = {
141
- ...(state.profiles[profileName] || {}),
142
- baseUrl: config.platformUrl,
143
- appType: config.appType,
144
- updatedAt: new Date().toISOString(),
145
- };
146
- bound = state.profiles[profileName];
147
- }
148
- ensureResourceBuckets(bound);
149
- bound.resources.forms[formName] = {
150
- ...(bound.resources.forms[formName] || {}),
151
- ...extra,
152
- formUuid,
153
- updatedAt: new Date().toISOString(),
154
- };
155
-
156
- saveProjectState(config, state);
157
- return true;
158
- }
159
-
160
- export function markWorkspaceFormSchemaSynced(config, formName, formUuid, extra = {}) {
161
- return saveWorkspaceFormBinding(config, formName, formUuid, {
162
- ...extra,
163
- schemaSyncedAt: new Date().toISOString(),
164
- });
165
- }
166
-
167
- export function markWorkspaceFormBundlePublished(
168
- config,
169
- formName,
170
- formUuid,
171
- extra = {},
172
- ) {
173
- return saveWorkspaceFormBinding(config, formName, formUuid, {
174
- ...extra,
175
- bundlePublishedAt: new Date().toISOString(),
176
- });
177
- }
178
-
179
- export function normalizeFormReleaseExpectation(value) {
180
- const revision = Number(value?.revision);
181
- if (!Number.isSafeInteger(revision) || revision < 1) return null;
182
- const head = value?.activeFormReleaseHead || value?.expectedParent || {};
183
- return {
184
- revision,
185
- etag: String(value?.etag || "").trim() || undefined,
186
- activeFormReleaseHead: {
187
- releaseId: head?.releaseId || null,
188
- releaseHash: head?.releaseHash || null,
189
- revision: Number(head?.revision ?? revision),
190
- },
191
- };
192
- }
193
-
194
- function formReleaseStateFields(value) {
195
- const expectation = normalizeFormReleaseExpectation(value);
196
- return expectation
197
- ? {
198
- revision: expectation.revision,
199
- ...(expectation.etag ? { etag: expectation.etag } : {}),
200
- activeFormReleaseHead: expectation.activeFormReleaseHead,
201
- }
202
- : {};
203
- }
204
-
205
- function readExportedStringConstant(filePath, exportName) {
206
- if (!filePath || !fs.existsSync(filePath)) return "";
207
- const content = fs.readFileSync(filePath, "utf-8");
208
- const escaped = exportName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
209
- const match = content.match(
210
- new RegExp(`export\\s+const\\s+${escaped}\\s*=\\s*(['"])(.*?)\\1`),
211
- );
212
- return match?.[2]?.trim() || "";
213
- }
214
-
215
- function resolveRelativeImportPath(schemaPath, source) {
216
- if (!source.startsWith(".")) return "";
217
- const basePath = path.resolve(path.dirname(schemaPath), source);
218
- const candidates = [
219
- basePath,
220
- `${basePath}.ts`,
221
- `${basePath}.tsx`,
222
- `${basePath}.js`,
223
- `${basePath}.mjs`,
224
- path.join(basePath, "index.ts"),
225
- path.join(basePath, "index.tsx"),
226
- path.join(basePath, "index.js"),
227
- ];
228
- return candidates.find((candidate) => fs.existsSync(candidate)) || "";
229
- }
230
-
231
- function findImportedStringConstantSource(content, schemaPath, identifier) {
232
- if (!schemaPath || !identifier) return "";
233
- const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']([^"']+)["']/g;
234
- let match;
235
- while ((match = importRegex.exec(content))) {
236
- const specifiers = match[1]
237
- .split(",")
238
- .map((item) => item.trim())
239
- .filter(Boolean);
240
- const sourcePath = resolveRelativeImportPath(schemaPath, match[2]);
241
- if (!sourcePath) continue;
242
-
243
- for (const specifier of specifiers) {
244
- const aliasMatch = specifier.match(
245
- /^([A-Za-z_$][\w$]*)(?:\s+as\s+([A-Za-z_$][\w$]*))?$/,
246
- );
247
- if (!aliasMatch) continue;
248
- const exportedName = aliasMatch[1];
249
- const localName = aliasMatch[2] || exportedName;
250
- if (localName !== identifier) continue;
251
- return { sourcePath, exportedName };
252
- }
253
- }
254
- return null;
255
- }
256
-
257
- function readImportedStringConstant(content, schemaPath, identifier) {
258
- const imported = findImportedStringConstantSource(
259
- content,
260
- schemaPath,
261
- identifier,
262
- );
263
- if (!imported) return "";
264
- return readExportedStringConstant(imported.sourcePath, imported.exportedName);
265
- }
266
-
267
- function readPropIdentifier(content, propName) {
268
- const escaped = propName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
269
- const identifierMatch = content.match(
270
- new RegExp(`${escaped}\\s*:\\s*([A-Za-z_$][\\w$]*)`),
271
- );
272
- return identifierMatch?.[1] || "";
273
- }
274
-
275
- function writeStringConstant(filePath, identifier, value) {
276
- const content = fs.readFileSync(filePath, "utf-8");
277
- const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
278
- const nextContent = content.replace(
279
- new RegExp(`((?:export\\s+)?const\\s+${escaped}\\s*=\\s*)([^;]+);`),
280
- (_match, prefix, initializer) => {
281
- const quote = initializer.trim().startsWith("'") ? "'" : '"';
282
- return `${prefix}${quote}${value}${quote};`;
283
- },
284
- );
285
- if (nextContent === content) return false;
286
- fs.writeFileSync(filePath, nextContent, "utf-8");
287
- return true;
288
- }
289
-
290
- export function writeSchemaStringProp(schemaPath, propName, value) {
291
- const content = fs.readFileSync(schemaPath, "utf-8");
292
- const escaped = propName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
293
- const literalRegex = new RegExp(
294
- `(${escaped}\\s*:\\s*)(['"])([^'"]*)\\2`,
295
- );
296
- const literalNextContent = content.replace(
297
- literalRegex,
298
- (_match, prefix, quote) => `${prefix}${quote}${value}${quote}`,
299
- );
300
- if (literalNextContent !== content) {
301
- fs.writeFileSync(schemaPath, literalNextContent, "utf-8");
302
- return;
303
- }
304
-
305
- const identifier = readPropIdentifier(content, propName);
306
- if (!identifier) {
307
- throw new Error(`schema.ts 中未找到 ${propName} 字段,无法回写`);
308
- }
309
-
310
- if (writeStringConstant(schemaPath, identifier, value)) {
311
- return;
312
- }
313
-
314
- const imported = findImportedStringConstantSource(
315
- content,
316
- schemaPath,
317
- identifier,
318
- );
319
- if (
320
- imported &&
321
- writeStringConstant(imported.sourcePath, imported.exportedName, value)
322
- ) {
323
- return;
324
- }
325
-
326
- throw new Error(`schema.ts 中未找到可回写的 ${propName} 字段,无法回写`);
327
- }
328
-
329
- export function writeSchemaFormUuid(schemaPath, formUuid) {
330
- writeSchemaStringProp(schemaPath, "formUuid", formUuid);
331
- }
332
-
333
- export function writeSchemaAppType(schemaPath, appType) {
334
- writeSchemaStringProp(schemaPath, "appType", appType);
335
- }
336
-
337
- function resolveTargetAppType(config, meta) {
338
- if (isOpenXiangdaMode(config)) {
339
- return config.appType;
340
- }
341
- return meta.appType || config.appType;
342
- }
343
-
344
- function isStaleOpenXiangdaBinding(config, meta, targetAppType) {
345
- return Boolean(
346
- isOpenXiangdaMode(config) &&
347
- meta.formUuid &&
348
- meta.appType &&
349
- meta.appType !== targetAppType,
350
- );
351
- }
352
-
353
- function syncSchemaAppTypeIfNeeded(schemaPath, meta, targetAppType) {
354
- if (!targetAppType || meta.appType === targetAppType) return;
355
- if (!meta.appType && !meta.content.includes("appType")) return;
356
- writeSchemaAppType(schemaPath, targetAppType);
357
- }
358
-
359
- function syncCreatedFormMeta(schemaPath, meta, targetAppType, formUuid) {
360
- writeSchemaFormUuid(schemaPath, formUuid);
361
- syncSchemaAppTypeIfNeeded(schemaPath, meta, targetAppType);
362
- }
363
-
364
- function readStringProp(content, propName, schemaPath) {
365
- const escaped = propName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
366
- const literalMatch = content.match(
367
- new RegExp(`${escaped}\\s*:\\s*(['"])(.*?)\\1`),
368
- );
369
- if (literalMatch) return literalMatch[2]?.trim() || "";
370
-
371
- const identifier = readPropIdentifier(content, propName);
372
- if (!identifier) return "";
373
-
374
- const localConstMatch = content.match(
375
- new RegExp(`(?:export\\s+)?const\\s+${identifier}\\s*=\\s*(['"])(.*?)\\1`),
376
- );
377
- if (localConstMatch) return localConstMatch[2]?.trim() || "";
378
-
379
- return readImportedStringConstant(content, schemaPath, identifier);
380
- }
381
-
382
- function hasObjectProp(content, propName) {
383
- const escaped = propName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
384
- return new RegExp(`${escaped}\\s*:`).test(content);
385
- }
386
-
387
- export function readSchemaMeta(schemaPath) {
388
- const content = fs.readFileSync(schemaPath, "utf-8");
389
-
390
- return {
391
- content,
392
- hasFormUuidProp: hasObjectProp(content, "formUuid"),
393
- formUuid: readStringProp(content, "formUuid", schemaPath),
394
- appType: readStringProp(content, "appType", schemaPath),
395
- title: readStringProp(content, "title", schemaPath),
396
- formType: readStringProp(content, "formType", schemaPath) || "receipt",
397
- relateUuid: readStringProp(content, "relateUuid", schemaPath),
398
- };
399
- }
400
-
401
- export function assertRequiredOpenApiConfig(config) {
402
- const missing = [];
403
- if (!config.appType) missing.push("APP_TYPE");
404
- if (!config.platformUrl) missing.push("APP_PLATFORM_URL");
405
-
406
- if (isOpenXiangdaMode(config)) {
407
- if (!config.openXiangdaAccessToken) {
408
- missing.push("OPENXIANGDA_ACCESS_TOKEN");
409
- }
410
- } else {
411
- if (!config.appKey) missing.push("APP_KEY");
412
- if (!config.appSecret) missing.push("APP_SECRET");
413
- if (!config.userId) missing.push("APP_USER_ID");
414
- }
415
-
416
- if (missing.length > 0) {
417
- throw new Error(`缺少必要配置: ${missing.join(", ")}`);
418
- }
419
- }
420
-
421
- export function isOpenXiangdaMode(config) {
422
- return Boolean(config.openXiangdaAccessToken);
423
- }
424
-
425
- export function getOpenXiangdaPublishContextHeaders(env = process.env) {
426
- const values = [
427
- ["x-openxiangda-publish-lease-id", env.OPENXIANGDA_PUBLISH_LEASE_ID],
428
- ["x-openxiangda-change-baseline-id", env.OPENXIANGDA_CHANGE_BASELINE_ID],
429
- ["x-openxiangda-change-id", env.OPENXIANGDA_CHANGE_ID],
430
- ["x-openxiangda-client-session-id", env.OPENXIANGDA_CLIENT_SESSION_ID],
431
- ];
432
- return Object.fromEntries(
433
- values
434
- .map(([name, value]) => [name, String(value || "").trim()])
435
- .filter(([, value]) => Boolean(value)),
436
- );
437
- }
438
-
439
- function getAuthHeaders(config, accessToken) {
440
- if (isOpenXiangdaMode(config)) {
441
- return {
442
- Authorization: `Bearer ${accessToken || config.openXiangdaAccessToken}`,
443
- ...getOpenXiangdaPublishContextHeaders(),
444
- };
445
- }
446
- return {
447
- "x-acs-dingtalk-access-token": accessToken,
448
- };
449
- }
450
-
451
- function canonicalize(value) {
452
- if (Array.isArray(value)) return value.map((item) => canonicalize(item));
453
- if (!value || typeof value !== "object") return value;
454
- return Object.fromEntries(
455
- Object.keys(value)
456
- .sort()
457
- .filter((key) => value[key] !== undefined)
458
- .map((key) => [key, canonicalize(value[key])]),
459
- );
460
- }
461
-
462
- function canonicalJsonSha256(value) {
463
- return crypto
464
- .createHash("sha256")
465
- .update(JSON.stringify(canonicalize(value)))
466
- .digest("hex");
467
- }
468
-
469
- function normalizeFrozenFormSnapshot(value, label = "Form snapshot") {
470
- const expectation = normalizeFormReleaseExpectation(value);
471
- if (!expectation?.etag) {
472
- const error = new Error(
473
- `FORM_REVISION_CONFLICT: ${label} 未返回有效 revision/etag,拒绝配置写入`,
474
- );
475
- error.code = "FORM_REVISION_CONFLICT";
476
- throw error;
477
- }
478
- if (expectation.activeFormReleaseHead.revision !== expectation.revision) {
479
- const error = new Error(
480
- `FORM_REVISION_CONFLICT: ${label} 的 head revision 与 Form revision 不一致`,
481
- );
482
- error.code = "FORM_REVISION_CONFLICT";
483
- throw error;
484
- }
485
- return {
486
- ...value,
487
- ...expectation,
488
- expectedParent: expectation.activeFormReleaseHead,
489
- };
490
- }
491
-
492
- function assertExpectedFormSnapshot(frozen, expected) {
493
- const normalizedExpected = normalizeFormReleaseExpectation(expected);
494
- if (!normalizedExpected) return;
495
- const headMatches =
496
- canonicalJsonSha256(normalizedExpected.activeFormReleaseHead) ===
497
- canonicalJsonSha256(frozen.expectedParent);
498
- const etagMatches =
499
- !normalizedExpected.etag || normalizedExpected.etag === frozen.etag;
500
- if (
501
- normalizedExpected.revision !== frozen.revision ||
502
- !headMatches ||
503
- !etagMatches
504
- ) {
505
- const error = new Error(
506
- `FORM_REVISION_CONFLICT: 工作区冻结 revision=r${normalizedExpected.revision},平台当前 revision=r${frozen.revision};未执行写入,请先合并并重新规划`,
507
- );
508
- error.code = "FORM_REVISION_CONFLICT";
509
- throw error;
510
- }
511
- }
512
-
513
- async function readJsonResponse(response) {
514
- return await response.json().catch(() => null);
515
- }
516
-
517
- export async function getOpenXiangdaFormSnapshot(
518
- config,
519
- accessToken,
520
- { appType, formUuid },
521
- ) {
522
- if (!isOpenXiangdaMode(config)) return null;
523
- const targetAppType = appType || config.appType;
524
- const apiBase = getApiBaseUrl(config);
525
- const response = await fetch(
526
- `${apiBase}/openxiangda-api/v1/apps/${encodeURIComponent(targetAppType)}/forms/${encodeURIComponent(formUuid)}/snapshot`,
527
- {
528
- method: "GET",
529
- headers: {
530
- "Content-Type": "application/json",
531
- ...getAuthHeaders(config, accessToken),
532
- },
533
- },
534
- );
535
- const body = await readJsonResponse(response);
536
- if (!response.ok || body?.code !== 200) {
537
- const message = body?.message || response.statusText || "unknown error";
538
- const error = new Error(
539
- `查询 Form snapshot 失败: HTTP ${response.status} ${message}`,
540
- );
541
- error.code = body?.errorCode || "FORM_REVISION_CONFLICT";
542
- throw error;
543
- }
544
- return normalizeFrozenFormSnapshot(body.data);
545
- }
546
-
547
- export async function mutateOpenXiangdaFormConfig(
548
- config,
549
- accessToken,
550
- {
551
- appType,
552
- formUuid,
553
- endpoint,
554
- operation,
555
- payload,
556
- expected,
557
- artifactId,
558
- },
559
- ) {
560
- if (!isOpenXiangdaMode(config)) {
561
- throw new Error("mutateOpenXiangdaFormConfig 仅用于 OpenXiangda 模式");
562
- }
563
- const targetAppType = appType || config.appType;
564
- const frozen = await getOpenXiangdaFormSnapshot(config, accessToken, {
565
- appType: targetAppType,
566
- formUuid,
567
- });
568
- assertExpectedFormSnapshot(frozen, expected);
569
- const expectedParent = frozen.expectedParent;
570
- const mutationPayload = payload || {};
571
- const stableArtifactId =
572
- artifactId ||
573
- `form:${String(operation || endpoint || "config")
574
- .replace(/[^A-Za-z0-9_.-]+/g, "-")
575
- .slice(0, 48)}:${canonicalJsonSha256({
576
- appType: targetAppType,
577
- formUuid,
578
- operation: operation || endpoint,
579
- expectedParent,
580
- payload: mutationPayload,
581
- }).slice(0, 32)}`;
582
- const apiBase = getApiBaseUrl(config);
583
- const url = `${apiBase}/openxiangda-api/v1/apps/${encodeURIComponent(targetAppType)}/forms/${encodeURIComponent(formUuid)}/${String(endpoint || "").replace(/^\/+/, "")}`;
584
- const response = await fetch(url, {
585
- method: "POST",
586
- headers: {
587
- "Content-Type": "application/json",
588
- ...getAuthHeaders(config, accessToken),
589
- "If-Match": frozen.etag,
590
- },
591
- body: JSON.stringify({
592
- ...mutationPayload,
593
- artifactId: stableArtifactId,
594
- expectedRevision: frozen.revision,
595
- expectedParent,
596
- }),
597
- });
598
- const body = await readJsonResponse(response);
599
- if (!response.ok || body?.code !== 200) {
600
- const message = body?.message || response.statusText || "unknown error";
601
- const error = new Error(
602
- `${body?.errorCode || "FORM_CONFIG_WRITE_FAILED"}: HTTP ${response.status} ${message}`,
603
- );
604
- error.code = body?.errorCode || "FORM_CONFIG_WRITE_FAILED";
605
- error.status = response.status;
606
- error.data = body?.data;
607
- throw error;
608
- }
609
- const resultExpectation = normalizeFormReleaseExpectation(body.data);
610
- if (!resultExpectation) {
611
- const error = new Error(
612
- "FORM_REVISION_CONFLICT: Form 配置写响应未返回 revision/head",
613
- );
614
- error.code = "FORM_REVISION_CONFLICT";
615
- throw error;
616
- }
617
- return { response: body, data: body.data, frozen, url };
618
- }
619
-
620
- export async function getOpenApiAccessToken(config) {
621
- assertRequiredOpenApiConfig(config);
622
- if (isOpenXiangdaMode(config)) {
623
- return config.openXiangdaAccessToken;
624
- }
625
-
626
- const apiBase = getApiBaseUrl(config);
627
- const res = await fetch(`${apiBase}/dingtalk-api/v1.0/oauth2/accessToken`, {
628
- method: "POST",
629
- headers: {
630
- "Content-Type": "application/json",
631
- },
632
- body: JSON.stringify({
633
- appKey: config.appKey,
634
- appSecret: config.appSecret,
635
- }),
636
- });
637
-
638
- let body = null;
639
- try {
640
- body = await res.json();
641
- } catch {
642
- body = null;
643
- }
644
-
645
- if (!res.ok || !body?.accessToken) {
646
- const message = body?.message || res.statusText || "unknown error";
647
- throw new Error(`获取 accessToken 失败: HTTP ${res.status} ${message}`);
648
- }
649
-
650
- return body.accessToken;
651
- }
652
-
653
- export async function createOpenApiForm(config, accessToken, formOptions) {
654
- assertRequiredOpenApiConfig(config);
655
-
656
- const apiBase = getApiBaseUrl(config);
657
- const targetAppType = formOptions.appType || config.appType;
658
- const payload = {
659
- name: formOptions.name,
660
- formType: formOptions.formType || "receipt",
661
- relateUuid: formOptions.relateUuid || "",
662
- };
663
- const builderVersion =
664
- formOptions.builderVersion || config.defaults?.formBuilderVersion || "2.0";
665
- if (
666
- builderVersion === "2.0" &&
667
- ["receipt", "process"].includes(String(payload.formType || ""))
668
- ) {
669
- payload.builderVersion = "2.0";
670
- }
671
- if (formOptions.formUuid) {
672
- payload.formUuid = formOptions.formUuid;
673
- }
674
-
675
- if (isOpenXiangdaMode(config)) {
676
- payload.createMenu = formOptions.createMenu !== false;
677
- payload.menuParentId = config.menu?.parentId || "";
678
- payload.menuIcon = config.menu?.icon || "";
679
- payload.expectedRevision = 0;
680
- } else {
681
- payload.userId = config.userId;
682
- payload.appType = targetAppType;
683
- }
684
-
685
- const url = isOpenXiangdaMode(config)
686
- ? `${apiBase}/openxiangda-api/v1/apps/${encodeURIComponent(targetAppType)}/forms`
687
- : `${apiBase}/dingtalk-api/v1.0/forms/createForm`;
688
-
689
- const res = await fetch(url, {
690
- method: "POST",
691
- headers: {
692
- "Content-Type": "application/json",
693
- ...getAuthHeaders(config, accessToken),
694
- ...(isOpenXiangdaMode(config) ? { "If-Match": "0" } : {}),
695
- },
696
- body: JSON.stringify(payload),
697
- });
698
-
699
- let body = null;
700
- try {
701
- body = await res.json();
702
- } catch {
703
- body = null;
704
- }
705
-
706
- if (!res.ok || body?.code !== 200) {
707
- const message = body?.message || res.statusText || "unknown error";
708
- throw new Error(`创建表单失败: HTTP ${res.status} ${message}`);
709
- }
710
-
711
- const responseData = body?.data || body;
712
- const data = responseData?.form || responseData;
713
- const formUuid = data?.formUuid;
714
- if (!formUuid) {
715
- throw new Error("创建表单成功但响应中没有 formUuid");
716
- }
717
-
718
- return {
719
- ...data,
720
- formUuid,
721
- revision: data?.revision ?? responseData?.revision,
722
- etag: data?.etag ?? responseData?.etag,
723
- activeFormReleaseHead:
724
- responseData?.activeFormReleaseHead || data?.activeFormReleaseHead,
725
- };
726
- }
727
-
728
- export async function listOpenApiForms(config, accessToken, appType) {
729
- assertRequiredOpenApiConfig(config);
730
-
731
- const apiBase = getApiBaseUrl(config);
732
- const targetAppType = appType || config.appType;
733
- const url = isOpenXiangdaMode(config)
734
- ? `${apiBase}/openxiangda-api/v1/apps/${encodeURIComponent(targetAppType)}/forms`
735
- : `${apiBase}/dingtalk-api/v1.0/forms/getFormList`;
736
- const res = await fetch(url, {
737
- method: isOpenXiangdaMode(config) ? "GET" : "POST",
738
- headers: {
739
- "Content-Type": "application/json",
740
- ...getAuthHeaders(config, accessToken),
741
- },
742
- body: isOpenXiangdaMode(config)
743
- ? undefined
744
- : JSON.stringify({
745
- userId: config.userId,
746
- appType: targetAppType,
747
- }),
748
- });
749
-
750
- let body = null;
751
- try {
752
- body = await res.json();
753
- } catch {
754
- body = null;
755
- }
756
-
757
- if (!res.ok || body?.code !== 200) {
758
- const message = body?.message || res.statusText || "unknown error";
759
- throw new Error(`查询表单失败: HTTP ${res.status} ${message}`);
760
- }
761
-
762
- return Array.isArray(body?.data) ? body.data : Array.isArray(body) ? body : [];
763
- }
764
-
765
- export async function getOpenApiForm(
766
- config,
767
- accessToken,
768
- { appType, formUuid },
769
- ) {
770
- if (!formUuid) return null;
771
- const forms = await listOpenApiForms(
772
- config,
773
- accessToken,
774
- appType || config.appType,
775
- );
776
- return (
777
- forms.find(
778
- (item) =>
779
- item?.formUuid === formUuid &&
780
- (!appType || !item?.appType || item.appType === appType),
781
- ) || null
782
- );
783
- }
784
-
785
- export async function listOpenApiMenus(config, accessToken, appType) {
786
- assertRequiredOpenApiConfig(config);
787
-
788
- const apiBase = getApiBaseUrl(config);
789
- const targetAppType = appType || config.appType;
790
- const url = isOpenXiangdaMode(config)
791
- ? `${apiBase}/openxiangda-api/v1/apps/${encodeURIComponent(targetAppType)}/menus`
792
- : `${apiBase}/dingtalk-api/v1.0/forms/getMenusByAppType`;
793
- const res = await fetch(url, {
794
- method: isOpenXiangdaMode(config) ? "GET" : "POST",
795
- headers: {
796
- "Content-Type": "application/json",
797
- ...getAuthHeaders(config, accessToken),
798
- },
799
- body: isOpenXiangdaMode(config)
800
- ? undefined
801
- : JSON.stringify({
802
- userId: config.userId,
803
- appType: targetAppType,
804
- }),
805
- });
806
-
807
- let body = null;
808
- try {
809
- body = await res.json();
810
- } catch {
811
- body = null;
812
- }
813
-
814
- if (!res.ok || body?.code !== 200) {
815
- const message = body?.message || res.statusText || "unknown error";
816
- throw new Error(`查询菜单失败: HTTP ${res.status} ${message}`);
817
- }
818
-
819
- return Array.isArray(body?.data) ? body.data : Array.isArray(body) ? body : [];
820
- }
821
-
822
- function flattenMenus(menus) {
823
- const result = [];
824
- const visit = (menu) => {
825
- result.push(menu);
826
- if (Array.isArray(menu.children)) {
827
- for (const child of menu.children) {
828
- visit(child);
829
- }
830
- }
831
- };
832
-
833
- for (const menu of menus) {
834
- visit(menu);
835
- }
836
-
837
- return result;
838
- }
839
-
840
- export async function ensureOpenApiMenuForForm(
841
- config,
842
- accessToken,
843
- { appType, formUuid, name, formType = "receipt", parentId = "", icon = "" },
844
- ) {
845
- assertRequiredOpenApiConfig(config);
846
-
847
- const targetAppType = appType || config.appType;
848
- const menus = flattenMenus(
849
- await listOpenApiMenus(config, accessToken, targetAppType),
850
- );
851
- const existing = menus.find((menu) => menu.formUuid === formUuid);
852
- if (existing) {
853
- return {
854
- created: false,
855
- menu: existing,
856
- };
857
- }
858
-
859
- if (isOpenXiangdaMode(config)) {
860
- return {
861
- created: false,
862
- menu: null,
863
- };
864
- }
865
-
866
- const apiBase = getApiBaseUrl(config);
867
- const payload = {
868
- userId: config.userId,
869
- appType: targetAppType,
870
- name,
871
- type: formType || "receipt",
872
- formUuid,
873
- parentId: parentId || null,
874
- icon: icon || null,
875
- };
876
-
877
- const res = await fetch(`${apiBase}/dingtalk-api/v1.0/forms/menu/create`, {
878
- method: "POST",
879
- headers: {
880
- "Content-Type": "application/json",
881
- "x-acs-dingtalk-access-token": accessToken,
882
- },
883
- body: JSON.stringify(payload),
884
- });
885
-
886
- let body = null;
887
- try {
888
- body = await res.json();
889
- } catch {
890
- body = null;
891
- }
892
-
893
- if (!res.ok || body?.code !== 200) {
894
- const message = body?.message || res.statusText || "unknown error";
895
- throw new Error(`创建菜单失败: HTTP ${res.status} ${message}`);
896
- }
897
-
898
- return {
899
- created: true,
900
- menu: body.data,
901
- };
902
- }
903
-
904
- export async function ensureSchemaFormUuid({
905
- config,
906
- schemaPath,
907
- formName,
908
- accessToken,
909
- dryRun = false,
910
- ensureMenu = false,
911
- }) {
912
- const meta = readSchemaMeta(schemaPath);
913
- const targetAppType = resolveTargetAppType(config, meta);
914
- const workspaceBinding = readWorkspaceFormBinding(config, formName);
915
- const workspaceReleaseExpectation = normalizeFormReleaseExpectation(
916
- workspaceBinding?.form,
917
- );
918
- const effectiveMeta = workspaceBinding?.form?.formUuid
919
- ? {
920
- ...meta,
921
- formUuid: workspaceBinding.form.formUuid,
922
- appType: targetAppType,
923
- }
924
- : meta;
925
- const staleOpenXiangdaBinding = isStaleOpenXiangdaBinding(
926
- config,
927
- effectiveMeta,
928
- targetAppType,
929
- );
930
-
931
- if (effectiveMeta.formUuid && !staleOpenXiangdaBinding) {
932
- let created = false;
933
- let createdForm = null;
934
- if (!dryRun) {
935
- const token = accessToken || (await getOpenApiAccessToken(config));
936
- const existingForm = await getOpenApiForm(config, token, {
937
- appType: targetAppType,
938
- formUuid: effectiveMeta.formUuid,
939
- });
940
-
941
- if (!existingForm) {
942
- createdForm = await createOpenApiForm(config, token, {
943
- name: effectiveMeta.title || formName,
944
- appType: targetAppType,
945
- formType: effectiveMeta.formType || "receipt",
946
- relateUuid: effectiveMeta.relateUuid,
947
- formUuid: effectiveMeta.formUuid,
948
- builderVersion: config.defaults?.formBuilderVersion || "2.0",
949
- });
950
- created = true;
951
- console.log(
952
- ` ✓ ${formName}: 已按已有 formUuid 创建表单 ${effectiveMeta.formUuid}`,
953
- );
954
- }
955
-
956
- if ((created || ensureMenu) && !isOpenXiangdaMode(config)) {
957
- const menuResult = await ensureOpenApiMenuForForm(config, token, {
958
- appType: targetAppType,
959
- formUuid: effectiveMeta.formUuid,
960
- name: effectiveMeta.title || formName,
961
- formType: effectiveMeta.formType || "receipt",
962
- parentId: config.menu?.parentId,
963
- icon: config.menu?.icon,
964
- });
965
-
966
- if (menuResult.created) {
967
- console.log(
968
- ` ✓ ${formName}: 已创建菜单 ${menuResult.menu?.id || ""}`,
969
- );
970
- }
971
- }
972
-
973
- saveWorkspaceFormBinding(config, formName, effectiveMeta.formUuid, {
974
- title: effectiveMeta.title || formName,
975
- ...formReleaseStateFields(createdForm),
976
- });
977
- }
978
-
979
- return {
980
- ...effectiveMeta,
981
- appType: targetAppType,
982
- created,
983
- dryRunCreated: false,
984
- releaseExpectation:
985
- normalizeFormReleaseExpectation(createdForm) ||
986
- workspaceReleaseExpectation,
987
- };
988
- }
989
-
990
- if (!meta.hasFormUuidProp && !isOpenXiangdaMode(config)) {
991
- throw new Error(
992
- `${formName}: schema.ts 中未找到 formUuid 字段,无法自动创建并回写`,
993
- );
994
- }
995
-
996
- const createOptions = {
997
- name: meta.title || formName,
998
- appType: targetAppType,
999
- formType: meta.formType || "receipt",
1000
- relateUuid: meta.relateUuid,
1001
- formUuid: staleOpenXiangdaBinding ? undefined : meta.formUuid || undefined,
1002
- builderVersion: config.defaults?.formBuilderVersion || "2.0",
1003
- };
1004
-
1005
- if (dryRun) {
1006
- console.log(
1007
- ` [dry-run] ${formName}: ${
1008
- staleOpenXiangdaBinding ? "检测到旧 appType 绑定" : "formUuid 为空"
1009
- },将创建表单和菜单 "${createOptions.name}"`,
1010
- );
1011
- return {
1012
- ...meta,
1013
- ...createOptions,
1014
- formUuid: "<auto-created-formUuid>",
1015
- created: false,
1016
- dryRunCreated: true,
1017
- };
1018
- }
1019
-
1020
- const token = accessToken || (await getOpenApiAccessToken(config));
1021
- const createdForm = await createOpenApiForm(config, token, createOptions);
1022
- if (isOpenXiangdaMode(config)) {
1023
- saveWorkspaceFormBinding(config, formName, createdForm.formUuid, {
1024
- title: createOptions.name,
1025
- ...formReleaseStateFields(createdForm),
1026
- });
1027
- } else {
1028
- syncCreatedFormMeta(schemaPath, meta, targetAppType, createdForm.formUuid);
1029
- }
1030
- console.log(` ✓ ${formName}: 已创建表单 ${createdForm.formUuid}`);
1031
-
1032
- let menuResult = { created: false, menu: null };
1033
- if (!isOpenXiangdaMode(config)) {
1034
- menuResult = await ensureOpenApiMenuForForm(config, token, {
1035
- appType: createOptions.appType,
1036
- formUuid: createdForm.formUuid,
1037
- name: createOptions.name,
1038
- formType: createOptions.formType,
1039
- parentId: config.menu?.parentId,
1040
- icon: config.menu?.icon,
1041
- });
1042
- if (menuResult.created) {
1043
- console.log(` ✓ ${formName}: 已创建菜单 ${menuResult.menu?.id || ""}`);
1044
- } else {
1045
- console.log(` ✓ ${formName}: 菜单已存在 ${menuResult.menu?.id || ""}`);
1046
- }
1047
- }
1048
-
1049
- return {
1050
- ...meta,
1051
- ...createOptions,
1052
- formUuid: createdForm.formUuid,
1053
- created: true,
1054
- menuCreated: menuResult.created,
1055
- dryRunCreated: false,
1056
- releaseExpectation: normalizeFormReleaseExpectation(createdForm),
1057
- };
1058
- }