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,1134 +0,0 @@
1
- const crypto = require('crypto');
2
- const fs = require('fs');
3
- const path = require('path');
4
-
5
- const ENVIRONMENT_KINDS = new Set(['preproduction', 'production']);
6
- const SIDE_EFFECT_POLICY_ENUMS = Object.freeze({
7
- notifications: ['disabled', 'tester_allowlist', 'enabled', 'real'],
8
- organizationWrites: ['deny', 'explicit_capability_only'],
9
- scheduledAutomations: ['disabled', 'enabled'],
10
- externalWrites: ['deny', 'allowlist', 'configured', 'sandbox'],
11
- payments: ['deny', 'configured', 'sandbox'],
12
- publicIndexing: ['deny', 'configured', 'enabled'],
13
- });
14
- const SIDE_EFFECT_POLICY_FIELDS = new Set([
15
- ...Object.keys(SIDE_EFFECT_POLICY_ENUMS),
16
- 'notificationAllowlist',
17
- 'environmentBanner',
18
- 'externalDingTalkDepartmentRootId',
19
- ]);
20
- const CANDIDATE_STATE_HASH_POLICY_V1 =
21
- 'openxiangda-state-without-runtime-promotion-v1';
22
- const CANDIDATE_STATE_HASH_POLICY =
23
- 'openxiangda-state-stable-managed-bindings-v2';
24
- const CANDIDATE_STATE_HASH_POLICIES = new Set([
25
- CANDIDATE_STATE_HASH_POLICY_V1,
26
- CANDIDATE_STATE_HASH_POLICY,
27
- ]);
28
- const CANDIDATE_RESOURCE_OBSERVATION_FIELDS = new Set([
29
- 'createdAt',
30
- 'updatedAt',
31
- 'syncedAt',
32
- 'schemaSyncedAt',
33
- 'bundlePublishedAt',
34
- ]);
35
-
36
- function isCandidateResourceObservationField(pathParts, key) {
37
- if (CANDIDATE_RESOURCE_OBSERVATION_FIELDS.has(key)) return true;
38
- return (
39
- key === 'status' &&
40
- pathParts.length === 2 &&
41
- pathParts[0] === 'dataViews'
42
- );
43
- }
44
-
45
- function canonicalJson(value) {
46
- if (Array.isArray(value)) {
47
- return `[${value.map(item => canonicalJson(item)).join(',')}]`;
48
- }
49
- if (value && typeof value === 'object') {
50
- return `{${Object.keys(value)
51
- .sort()
52
- .map(key => `${JSON.stringify(key)}:${canonicalJson(value[key])}`)
53
- .join(',')}}`;
54
- }
55
- return JSON.stringify(value);
56
- }
57
-
58
- function sha256Canonical(value) {
59
- return crypto.createHash('sha256').update(canonicalJson(value)).digest('hex');
60
- }
61
-
62
- function normalizeEnvironmentKind(value, label = 'environment') {
63
- const kind = String(value || '').trim().toLowerCase();
64
- if (!ENVIRONMENT_KINDS.has(kind)) {
65
- throw new Error(`${label} 必须是 preproduction 或 production`);
66
- }
67
- return kind;
68
- }
69
-
70
- function normalizeTargetName(value, kind) {
71
- const targetName = String(value || kind || '').trim();
72
- if (!/^[a-z][a-z0-9-]*$/.test(targetName)) {
73
- throw new Error(
74
- 'target 名称必须以小写字母开头,且只包含小写字母、数字和连字符'
75
- );
76
- }
77
- return targetName;
78
- }
79
-
80
- function cloneJsonValue(value) {
81
- return value === undefined
82
- ? undefined
83
- : JSON.parse(JSON.stringify(value));
84
- }
85
-
86
- function normalizeSideEffectPolicyInput(value, label = 'sideEffectPolicy') {
87
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
88
- throw new Error(`${label} 必须是对象`);
89
- }
90
- for (const key of Object.keys(value)) {
91
- if (!SIDE_EFFECT_POLICY_FIELDS.has(key)) {
92
- throw new Error(`${label}.${key} 不是允许的副作用策略字段`);
93
- }
94
- }
95
- const result = {};
96
- for (const [key, allowed] of Object.entries(SIDE_EFFECT_POLICY_ENUMS)) {
97
- if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
98
- const normalized = String(value[key] || '').trim();
99
- if (!allowed.includes(normalized)) {
100
- throw new Error(`${label}.${key} 必须是 ${allowed.join('、')} 之一`);
101
- }
102
- result[key] = normalized;
103
- }
104
- if (Object.prototype.hasOwnProperty.call(value, 'notificationAllowlist')) {
105
- if (!Array.isArray(value.notificationAllowlist)) {
106
- throw new Error(`${label}.notificationAllowlist 必须是数组`);
107
- }
108
- if (value.notificationAllowlist.length > 500) {
109
- throw new Error(`${label}.notificationAllowlist 最多包含 500 项`);
110
- }
111
- result.notificationAllowlist = Array.from(
112
- new Set(
113
- value.notificationAllowlist.map((item, index) => {
114
- const normalized = String(item ?? '').trim();
115
- if (!normalized || normalized.length > 255) {
116
- throw new Error(
117
- `${label}.notificationAllowlist[${index}] 必须是 1-255 字符的字符串`,
118
- );
119
- }
120
- return normalized;
121
- }),
122
- ),
123
- );
124
- }
125
- if (Object.prototype.hasOwnProperty.call(value, 'environmentBanner')) {
126
- if (typeof value.environmentBanner !== 'boolean') {
127
- throw new Error(`${label}.environmentBanner 必须是布尔值`);
128
- }
129
- result.environmentBanner = value.environmentBanner;
130
- }
131
- if (
132
- Object.prototype.hasOwnProperty.call(
133
- value,
134
- 'externalDingTalkDepartmentRootId',
135
- )
136
- ) {
137
- const raw = value.externalDingTalkDepartmentRootId;
138
- if (
139
- !['string', 'number'].includes(typeof raw) ||
140
- (typeof raw === 'number' && !Number.isSafeInteger(raw))
141
- ) {
142
- throw new Error(
143
- `${label}.externalDingTalkDepartmentRootId 必须是字符串或安全整数`,
144
- );
145
- }
146
- const normalized = String(raw).trim();
147
- if (!/^\d{1,64}$/.test(normalized)) {
148
- throw new Error(
149
- `${label}.externalDingTalkDepartmentRootId 必须是数字型钉钉部门 ID`,
150
- );
151
- }
152
- result.externalDingTalkDepartmentRootId = normalized;
153
- }
154
- return result;
155
- }
156
-
157
- function cloneExistingSideEffectPolicy(value, label = 'currentSideEffectPolicy') {
158
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
159
- throw new Error(`${label} 必须是对象`);
160
- }
161
- return cloneJsonValue(value);
162
- }
163
-
164
- function buildSideEffectPolicyDiff(beforeInput, updateInput, options = {}) {
165
- // Existing policies are durable protocol data and may contain fields written
166
- // by an older/newer platform version. Patch validation must apply only to the
167
- // caller's update; revalidating the stored object would make a harmless read
168
- // incompatible with newly introduced policy fields.
169
- const before = cloneExistingSideEffectPolicy(
170
- beforeInput || {},
171
- 'currentSideEffectPolicy',
172
- );
173
- const update = normalizeSideEffectPolicyInput(
174
- updateInput,
175
- 'sideEffectPolicy',
176
- );
177
- const fullReplace = options.fullReplace === true;
178
- const after = fullReplace
179
- ? cloneJsonValue(update)
180
- : { ...before, ...update };
181
- const fields = Array.from(
182
- new Set([...Object.keys(before), ...Object.keys(after)]),
183
- ).sort();
184
- const changes = fields
185
- .filter(key => canonicalJson(before[key]) !== canonicalJson(after[key]))
186
- .map(key => ({
187
- field: key,
188
- before: Object.prototype.hasOwnProperty.call(before, key)
189
- ? cloneJsonValue(before[key])
190
- : null,
191
- after: Object.prototype.hasOwnProperty.call(after, key)
192
- ? cloneJsonValue(after[key])
193
- : null,
194
- }));
195
- return {
196
- fullReplace,
197
- changed: changes.length > 0,
198
- before,
199
- after,
200
- changes,
201
- };
202
- }
203
-
204
- function normalizeIdentityList(values) {
205
- return Array.from(
206
- new Set(
207
- values
208
- .map(value => String(value || '').trim().toLowerCase())
209
- .filter(value => /^sha256:[0-9a-f]{64}$/.test(value))
210
- )
211
- ).sort();
212
- }
213
-
214
- function normalizeManagedReleaseSourceRevision(
215
- target,
216
- sourceRevision,
217
- options = {}
218
- ) {
219
- const logicalApp = target?.logicalApp || target?.state?.logicalApp;
220
- const expectedRepositoryId = String(
221
- logicalApp?.sourceRepositoryId || ''
222
- )
223
- .trim()
224
- .toLowerCase();
225
- if (!expectedRepositoryId) return cloneJsonValue(sourceRevision);
226
- const revision =
227
- sourceRevision &&
228
- typeof sourceRevision === 'object' &&
229
- !Array.isArray(sourceRevision)
230
- ? cloneJsonValue(sourceRevision)
231
- : {};
232
- const repositoryAliases = normalizeIdentityList([
233
- revision.repo,
234
- revision.repositoryId,
235
- ...(Array.isArray(revision.repoAliases) ? revision.repoAliases : []),
236
- ]);
237
- if (!repositoryAliases.includes(expectedRepositoryId)) {
238
- const code =
239
- String(options.errorCode || '').trim() ||
240
- 'MANAGED_SOURCE_REPOSITORY_MISMATCH';
241
- const error = new Error(
242
- `${code}: 当前 Git 仓库与 logical app 权威仓库不一致`
243
- );
244
- error.code = code;
245
- error.details = {
246
- expectedRepositoryId,
247
- repositoryAliases,
248
- };
249
- throw error;
250
- }
251
- const {
252
- capturedAt: _capturedAt,
253
- worktreeRoot: _worktreeRoot,
254
- ...stableRevision
255
- } = revision;
256
- return {
257
- ...stableRevision,
258
- repo: expectedRepositoryId,
259
- repositoryId: expectedRepositoryId,
260
- repoAliases: normalizeIdentityList([
261
- expectedRepositoryId,
262
- ...repositoryAliases,
263
- ]),
264
- ...(Array.isArray(revision.remoteUrlHashAliases)
265
- ? {
266
- remoteUrlHashAliases: normalizeIdentityList(
267
- revision.remoteUrlHashAliases
268
- ),
269
- }
270
- : {}),
271
- };
272
- }
273
-
274
- function normalizeReleaseSourceRevisionForBaseline(
275
- target,
276
- sourceBase,
277
- sourceRevision,
278
- options = {}
279
- ) {
280
- const revision = normalizeManagedReleaseSourceRevision(
281
- target,
282
- sourceRevision,
283
- options
284
- );
285
- const expectedRepositoryId = String(
286
- sourceBase?.repo || sourceBase?.repositoryId || ''
287
- )
288
- .trim()
289
- .toLowerCase();
290
- if (!expectedRepositoryId) return revision;
291
- const repositoryAliases = normalizeIdentityList([
292
- revision?.repo,
293
- revision?.repositoryId,
294
- ...(Array.isArray(revision?.repoAliases) ? revision.repoAliases : []),
295
- ]);
296
- if (!repositoryAliases.includes(expectedRepositoryId)) {
297
- const code =
298
- String(options.errorCode || '').trim() ||
299
- 'RELEASE_SOURCE_REPOSITORY_MISMATCH';
300
- const error = new Error(
301
- `${code}: 当前 Git 仓库与冻结 change baseline 仓库不一致`
302
- );
303
- error.code = code;
304
- error.details = {
305
- expectedRepositoryId,
306
- repositoryAliases,
307
- };
308
- throw error;
309
- }
310
- return {
311
- ...revision,
312
- repo: expectedRepositoryId,
313
- repositoryId: expectedRepositoryId,
314
- repoAliases: normalizeIdentityList([
315
- expectedRepositoryId,
316
- ...repositoryAliases,
317
- ]),
318
- };
319
- }
320
-
321
- function normalizeManagedChangeSourceBase(
322
- target,
323
- sourceBase,
324
- releaseSourceRevision
325
- ) {
326
- const logicalApp = target?.logicalApp || target?.state?.logicalApp;
327
- if (!logicalApp?.sourceRepositoryId) {
328
- return cloneJsonValue(sourceBase);
329
- }
330
- return normalizeManagedReleaseSourceRevision(
331
- target,
332
- {
333
- ...(sourceBase || {}),
334
- repositoryId: sourceBase?.repo,
335
- repoAliases: [
336
- sourceBase?.repo,
337
- releaseSourceRevision?.repo,
338
- releaseSourceRevision?.repositoryId,
339
- ...(Array.isArray(releaseSourceRevision?.repoAliases)
340
- ? releaseSourceRevision.repoAliases
341
- : []),
342
- ],
343
- },
344
- { errorCode: 'RELEASE_SOURCE_BASE_REPOSITORY_MISMATCH' }
345
- );
346
- }
347
-
348
- function hasStateResourceMappings(value) {
349
- if (Array.isArray(value)) return value.length > 0;
350
- if (!value || typeof value !== 'object') {
351
- return value !== undefined && value !== null && value !== '';
352
- }
353
- return Object.values(value).some(item => hasStateResourceMappings(item));
354
- }
355
-
356
- function resolveEnvironmentTarget(state, selector) {
357
- const targets = state?.targets || {};
358
- const requested = String(selector || state?.currentTarget || '').trim();
359
- if (!requested) {
360
- throw new Error(
361
- '当前工作区已启用应用环境,请显式使用 --environment <target|preproduction|production>'
362
- );
363
- }
364
- if (targets[requested]) {
365
- return { targetName: requested, binding: targets[requested] };
366
- }
367
- const matches = Object.entries(targets).filter(
368
- ([, binding]) => binding?.kind === requested
369
- );
370
- if (matches.length !== 1) {
371
- throw new Error(`应用环境 target 不存在或不唯一: ${requested}`);
372
- }
373
- return { targetName: matches[0][0], binding: matches[0][1] };
374
- }
375
-
376
- function bindEnvironmentTarget(state, input) {
377
- const kind = normalizeEnvironmentKind(input.kind);
378
- const targetName = normalizeTargetName(input.targetName, kind);
379
- const appType = String(input.appType || '').trim();
380
- const profile = String(input.profile || '').trim();
381
- const environmentId = String(input.environmentId || '').trim();
382
- if (!appType || !profile || !environmentId) {
383
- throw new Error('环境 target 缺少 appType、profile 或 environmentId');
384
- }
385
- state.targets = state.targets || {};
386
- const previous = state.targets[targetName] || {};
387
- const previousResources = previous.resources || {};
388
- const resources = input.replaceResources
389
- ? cloneJsonValue(input.seedResources || {}) || {}
390
- : hasStateResourceMappings(previousResources)
391
- ? previousResources
392
- : cloneJsonValue(input.seedResources || previousResources) || {};
393
- state.targets[targetName] = {
394
- ...previous,
395
- targetName,
396
- profile,
397
- environmentId,
398
- kind,
399
- appType,
400
- displayName: input.displayName || previous.displayName || kind,
401
- publicOrigin:
402
- input.publicOrigin === undefined
403
- ? previous.publicOrigin || null
404
- : input.publicOrigin,
405
- sideEffectPolicy:
406
- input.sideEffectPolicy === undefined
407
- ? previous.sideEffectPolicy || {}
408
- : input.sideEffectPolicy,
409
- revision:
410
- input.revision === undefined
411
- ? previous.revision || null
412
- : Number(input.revision),
413
- resources,
414
- updatedAt: new Date().toISOString(),
415
- };
416
- if (input.replaceAppScopedState) {
417
- const seedAppScopedState = input.seedAppScopedState || {};
418
- for (const key of [
419
- 'lastDeploymentId',
420
- 'lastCandidateId',
421
- 'lastDeploymentStatus',
422
- 'runtime',
423
- ]) {
424
- delete state.targets[targetName][key];
425
- if (
426
- Object.prototype.hasOwnProperty.call(seedAppScopedState, key) &&
427
- seedAppScopedState[key] !== undefined
428
- ) {
429
- state.targets[targetName][key] = cloneJsonValue(
430
- seedAppScopedState[key]
431
- );
432
- }
433
- }
434
- }
435
- if (!state.currentTarget || kind === 'preproduction') {
436
- state.currentTarget = targetName;
437
- }
438
- return state.targets[targetName];
439
- }
440
-
441
- function resolveManagedStateBinding(target) {
442
- if (!target?.targetName) return null;
443
- const binding = target.state?.targets?.[target.targetName];
444
- if (!binding) {
445
- throw new Error(`环境 target 状态不存在: ${target.targetName}`);
446
- }
447
- if (
448
- binding.appType !== target.appType ||
449
- (target.environmentId &&
450
- binding.environmentId !== target.environmentId)
451
- ) {
452
- throw new Error(
453
- `环境 target 状态与当前写入目标不一致: ${target.targetName}`
454
- );
455
- }
456
- return binding;
457
- }
458
-
459
- function candidateDirectory(cwd = process.cwd()) {
460
- return path.join(cwd, '.openxiangda', 'candidates');
461
- }
462
-
463
- function candidateFile(candidateId, cwd = process.cwd()) {
464
- const normalized = String(candidateId || '').trim();
465
- if (!/^[0-9a-f-]{36}$/i.test(normalized)) {
466
- throw new Error('candidateId 必须是 UUID');
467
- }
468
- return path.join(candidateDirectory(cwd), `${normalized}.json`);
469
- }
470
-
471
- function writePrivateJsonAtomic(file, value) {
472
- fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
473
- const temp = `${file}.${process.pid}.${Date.now()}.tmp`;
474
- fs.writeFileSync(temp, `${JSON.stringify(value, null, 2)}\n`, {
475
- mode: 0o600,
476
- });
477
- fs.renameSync(temp, file);
478
- }
479
-
480
- function saveCandidate(candidate, cwd = process.cwd()) {
481
- if (!candidate?.id) throw new Error('候选版本缺少 id');
482
- const file = candidateFile(candidate.id, cwd);
483
- writePrivateJsonAtomic(file, candidate);
484
- return file;
485
- }
486
-
487
- function readCandidate(candidateId, cwd = process.cwd()) {
488
- const file = candidateFile(candidateId, cwd);
489
- if (!fs.existsSync(file)) {
490
- throw new Error(
491
- `本地候选版本不存在: ${path.relative(cwd, file)};请先执行 release candidate`
492
- );
493
- }
494
- try {
495
- return JSON.parse(fs.readFileSync(file, 'utf8'));
496
- } catch (error) {
497
- throw new Error(`候选版本文件无效: ${error.message}`);
498
- }
499
- }
500
-
501
- function managedTargetDeploymentFile(target, cwd = process.cwd()) {
502
- const safeSegment = (value, fallback) =>
503
- String(value || fallback)
504
- .trim()
505
- .replace(/[^A-Za-z0-9._-]+/g, '_')
506
- .slice(0, 128);
507
- return path.join(
508
- cwd,
509
- '.openxiangda',
510
- 'releases',
511
- 'targets',
512
- safeSegment(target.logicalApp?.code, 'unmanaged'),
513
- `${safeSegment(
514
- target.targetName || target.environmentId || target.appType,
515
- 'default'
516
- )}.json`
517
- );
518
- }
519
-
520
- function readRememberedTargetDeployment(target, cwd = process.cwd()) {
521
- const file = managedTargetDeploymentFile(target, cwd);
522
- if (fs.existsSync(file)) {
523
- try {
524
- return JSON.parse(fs.readFileSync(file, 'utf8'));
525
- } catch (error) {
526
- throw new Error(
527
- `MANAGED_TARGET_DEPLOYMENT_STATE_INVALID: ${path.relative(
528
- cwd,
529
- file
530
- )} 无法读取: ${error.message}`
531
- );
532
- }
533
- }
534
- if (
535
- target.bound?.lastDeploymentId ||
536
- target.bound?.lastCandidateId ||
537
- target.bound?.lastDeploymentStatus
538
- ) {
539
- return {
540
- schemaVersion: 'openxiangda_target_deployment_v1',
541
- deploymentId: target.bound.lastDeploymentId || null,
542
- candidateId: target.bound.lastCandidateId || null,
543
- status: target.bound.lastDeploymentStatus || null,
544
- migratedFromProjectState: true,
545
- };
546
- }
547
- return null;
548
- }
549
-
550
- function rememberTargetDeployment(
551
- target,
552
- deployment,
553
- cwd = process.cwd()
554
- ) {
555
- const record = {
556
- schemaVersion: 'openxiangda_target_deployment_v1',
557
- logicalAppCode: target.logicalApp?.code || null,
558
- targetName: target.targetName || null,
559
- environmentId: target.environmentId || null,
560
- appType: target.appType,
561
- deploymentId: deployment.id,
562
- candidateId: deployment.candidateId || null,
563
- status: deployment.status,
564
- updatedAt: new Date().toISOString(),
565
- };
566
- const file = managedTargetDeploymentFile(target, cwd);
567
- writePrivateJsonAtomic(file, record);
568
- return { record, file };
569
- }
570
-
571
- function readJsonInput(value, label, cwd = process.cwd()) {
572
- const input = String(value || '').trim();
573
- if (!input) throw new Error(`${label} 不能为空`);
574
- const possibleFile = path.resolve(cwd, input);
575
- const text = fs.existsSync(possibleFile)
576
- ? fs.readFileSync(possibleFile, 'utf8')
577
- : input;
578
- let parsed;
579
- try {
580
- parsed = JSON.parse(text);
581
- } catch (error) {
582
- throw new Error(`${label} 必须是 JSON 或 JSON 文件: ${error.message}`);
583
- }
584
- if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
585
- throw new Error(`${label} 必须是 JSON 对象`);
586
- }
587
- return parsed;
588
- }
589
-
590
- function hashWorkspaceFile(cwd, relativePath) {
591
- const normalized = String(relativePath || '').replace(/\\/g, '/');
592
- const absolute = path.resolve(cwd, normalized);
593
- const relative = path.relative(cwd, absolute);
594
- if (
595
- !normalized ||
596
- relative.startsWith('..') ||
597
- path.isAbsolute(relative)
598
- ) {
599
- return null;
600
- }
601
- if (!fs.existsSync(absolute)) {
602
- return {
603
- path: normalized,
604
- exists: false,
605
- size: 0,
606
- sha256: null,
607
- };
608
- }
609
- if (!fs.statSync(absolute).isFile()) return null;
610
- const buffer = fs.readFileSync(absolute);
611
- return {
612
- path: normalized,
613
- exists: true,
614
- size: buffer.length,
615
- sha256: crypto.createHash('sha256').update(buffer).digest('hex'),
616
- };
617
- }
618
-
619
- function candidateFileHashPolicy(relativePath) {
620
- return String(relativePath || '').replace(/\\/g, '/') ===
621
- '.openxiangda/state.json'
622
- ? CANDIDATE_STATE_HASH_POLICY
623
- : null;
624
- }
625
-
626
- function hashCandidateWorkspaceFile(cwd, relativePath, options = {}) {
627
- const normalized = String(relativePath || '').replace(/\\/g, '/');
628
- const hasExplicitPolicy = Object.prototype.hasOwnProperty.call(
629
- options,
630
- 'hashPolicy'
631
- );
632
- const hashPolicy = hasExplicitPolicy
633
- ? options.hashPolicy
634
- : candidateFileHashPolicy(normalized);
635
- if (!hashPolicy) return hashWorkspaceFile(cwd, normalized);
636
- if (!CANDIDATE_STATE_HASH_POLICIES.has(hashPolicy)) {
637
- const error = new Error(
638
- `不支持的 candidate 文件哈希策略: ${hashPolicy}`
639
- );
640
- error.code = 'CANDIDATE_FILE_HASH_POLICY_UNSUPPORTED';
641
- throw error;
642
- }
643
-
644
- const raw = hashWorkspaceFile(cwd, normalized);
645
- if (!raw || raw.exists === false) {
646
- return raw ? { ...raw, hashPolicy } : raw;
647
- }
648
-
649
- let state;
650
- try {
651
- state = JSON.parse(
652
- fs.readFileSync(path.resolve(cwd, normalized), 'utf8')
653
- );
654
- } catch (error) {
655
- const invalid = new Error(
656
- `${normalized} 不是有效 JSON,不能生成稳定 candidate 输入哈希: ${error.message}`
657
- );
658
- invalid.code = 'CANDIDATE_STATE_INPUT_INVALID';
659
- throw invalid;
660
- }
661
- const normalizedState = normalizeCandidateProjectStateForHash(
662
- state,
663
- hashPolicy
664
- );
665
- const buffer = Buffer.from(canonicalJson(normalizedState), 'utf8');
666
- return {
667
- path: normalized,
668
- exists: true,
669
- size: buffer.length,
670
- sha256: crypto.createHash('sha256').update(buffer).digest('hex'),
671
- hashPolicy,
672
- };
673
- }
674
-
675
- function normalizeCandidateProjectStateForHash(input, hashPolicy) {
676
- const state = cloneJsonValue(input);
677
- if (!state || typeof state !== 'object' || Array.isArray(state)) {
678
- const error = new Error(
679
- '.openxiangda/state.json 顶层必须是 JSON 对象'
680
- );
681
- error.code = 'CANDIDATE_STATE_INPUT_INVALID';
682
- throw error;
683
- }
684
- for (const collectionName of ['profiles', 'targets']) {
685
- const collection = state[collectionName];
686
- if (
687
- !collection ||
688
- typeof collection !== 'object' ||
689
- Array.isArray(collection)
690
- ) {
691
- continue;
692
- }
693
- for (const binding of Object.values(collection)) {
694
- if (!binding || typeof binding !== 'object' || Array.isArray(binding)) {
695
- continue;
696
- }
697
- // publish lease / change baseline are local execution state written by
698
- // release begin/end. Their persistence must not invalidate the candidate
699
- // that caused the release, while all durable binding fields remain hashed.
700
- delete binding.promotion;
701
- delete binding.updatedAt;
702
- if (
703
- collectionName === 'targets' &&
704
- hashPolicy === CANDIDATE_STATE_HASH_POLICY
705
- ) {
706
- // Managed release stages persist discovered/created resource IDs and
707
- // the activated runtime head as their durable local execution result.
708
- // The sealed environmentBindings manifest independently protects every
709
- // resource identity that existed before sealing, while intentionally
710
- // allowing additive bindings created by the candidate itself.
711
- delete binding.resources;
712
- delete binding.runtime;
713
- }
714
- }
715
- }
716
- return state;
717
- }
718
-
719
- function normalizeCandidateResourceBindings(value, pathParts = []) {
720
- if (Array.isArray(value)) {
721
- return value.map((item, index) =>
722
- normalizeCandidateResourceBindings(item, [...pathParts, String(index)])
723
- );
724
- }
725
- if (!value || typeof value !== 'object') return value;
726
- return Object.fromEntries(
727
- Object.entries(value)
728
- .filter(
729
- ([key]) => !isCandidateResourceObservationField(pathParts, key)
730
- )
731
- .sort(([left], [right]) => left.localeCompare(right))
732
- .map(([key, item]) => [
733
- key,
734
- normalizeCandidateResourceBindings(item, [...pathParts, key]),
735
- ])
736
- );
737
- }
738
-
739
- function buildCandidateEnvironmentBindings(state) {
740
- const targets =
741
- state?.targets && typeof state.targets === 'object'
742
- ? state.targets
743
- : {};
744
- return Object.fromEntries(
745
- Object.entries(targets)
746
- .sort(([left], [right]) => left.localeCompare(right))
747
- .map(([targetName, binding]) => [
748
- targetName,
749
- {
750
- targetName,
751
- profile: binding?.profile || null,
752
- environmentId: binding?.environmentId || null,
753
- kind: binding?.kind || null,
754
- appType: binding?.appType || null,
755
- publicOrigin: binding?.publicOrigin || null,
756
- sideEffectPolicy:
757
- cloneJsonValue(binding?.sideEffectPolicy || {}) || {},
758
- revision:
759
- binding?.revision === undefined
760
- ? null
761
- : binding.revision,
762
- resources:
763
- normalizeCandidateResourceBindings(binding?.resources || {}) ||
764
- {},
765
- },
766
- ])
767
- );
768
- }
769
-
770
- function candidateBindingValueContains(expected, current) {
771
- if (Array.isArray(expected)) {
772
- return (
773
- Array.isArray(current) &&
774
- expected.length === current.length &&
775
- expected.every((item, index) =>
776
- candidateBindingValueContains(item, current[index])
777
- )
778
- );
779
- }
780
- if (expected && typeof expected === 'object') {
781
- if (!current || typeof current !== 'object' || Array.isArray(current)) {
782
- return false;
783
- }
784
- return Object.entries(expected).every(([key, value]) =>
785
- candidateBindingValueContains(value, current[key])
786
- );
787
- }
788
- return expected === current;
789
- }
790
-
791
- function inspectCandidateEnvironmentBindings(candidate, state) {
792
- const expected =
793
- candidate?.sourceBundleManifest?.environmentBindings ||
794
- candidate?.environmentBindings ||
795
- {};
796
- const current = buildCandidateEnvironmentBindings(state);
797
- const mismatches = [];
798
- const expectedNames = Object.keys(expected).sort();
799
- const currentNames = Object.keys(current).sort();
800
- if (canonicalJson(expectedNames) !== canonicalJson(currentNames)) {
801
- mismatches.push({
802
- targetName: '(targets)',
803
- reason: 'target-set-changed',
804
- expected: expectedNames,
805
- current: currentNames,
806
- });
807
- }
808
- for (const targetName of expectedNames) {
809
- const expectedBinding = expected[targetName];
810
- const currentBinding = current[targetName];
811
- if (!currentBinding) continue;
812
- for (const field of [
813
- 'targetName',
814
- 'profile',
815
- 'environmentId',
816
- 'kind',
817
- 'appType',
818
- 'publicOrigin',
819
- 'sideEffectPolicy',
820
- 'revision',
821
- ]) {
822
- if (
823
- canonicalJson(expectedBinding?.[field]) !==
824
- canonicalJson(currentBinding?.[field])
825
- ) {
826
- mismatches.push({
827
- targetName,
828
- field,
829
- reason: 'changed',
830
- expected: expectedBinding?.[field],
831
- current: currentBinding?.[field],
832
- });
833
- }
834
- }
835
- const expectedResources = normalizeCandidateResourceBindings(
836
- expectedBinding?.resources || {}
837
- );
838
- const currentResources = normalizeCandidateResourceBindings(
839
- currentBinding.resources || {}
840
- );
841
- if (!candidateBindingValueContains(expectedResources, currentResources)) {
842
- mismatches.push({
843
- targetName,
844
- field: 'resources',
845
- reason: 'sealed-resource-binding-changed',
846
- expected: expectedResources,
847
- current: currentResources,
848
- });
849
- }
850
- }
851
- return {
852
- valid: mismatches.length === 0,
853
- checked: expectedNames.length,
854
- mismatches,
855
- };
856
- }
857
-
858
- function assertCandidateEnvironmentBindingsCurrent(candidate, state) {
859
- const inspection = inspectCandidateEnvironmentBindings(candidate, state);
860
- if (inspection.valid) return inspection;
861
- const error = new Error(
862
- `CANDIDATE_ENVIRONMENT_BINDINGS_CHANGED: sealed candidate 的环境或资源绑定已变化: ${inspection.mismatches
863
- .slice(0, 8)
864
- .map(
865
- item =>
866
- `${item.targetName}${
867
- item.field ? `.${item.field}` : ''
868
- }(${item.reason})`
869
- )
870
- .join(', ')}`
871
- );
872
- error.code = 'CANDIDATE_ENVIRONMENT_BINDINGS_CHANGED';
873
- error.details = inspection;
874
- throw error;
875
- }
876
-
877
- function buildCandidateBundle(input) {
878
- const cwd = path.resolve(input.cwd || process.cwd());
879
- const files = Array.from(new Set(input.files || []))
880
- .sort()
881
- .map(file => hashCandidateWorkspaceFile(cwd, file))
882
- .filter(Boolean);
883
- const testPlan = input.testPlan || {
884
- schemaVersion: 1,
885
- requiredGates: [
886
- 'static',
887
- 'schema',
888
- 'appFunctions',
889
- 'roles',
890
- 'browser',
891
- 'lifecycle',
892
- 'cleanup',
893
- ],
894
- maximumEvidenceAgeHours: 24,
895
- };
896
- const sourceBundleManifest = {
897
- schemaVersion: 1,
898
- logicalAppCode: input.logicalAppCode,
899
- changeId: input.changeId,
900
- sourceRevision: input.sourceRevision,
901
- runtimeMode: input.runtimeMode,
902
- targets: input.targets,
903
- inputPolicy: 'candidate-inputs-v2',
904
- files,
905
- environmentBindings:
906
- cloneJsonValue(input.environmentBindings || {}) || {},
907
- runtimeArtifacts:
908
- cloneJsonValue(input.runtimeArtifacts || []) || [],
909
- testPlanHash: sha256Canonical(testPlan),
910
- prepublishVerificationHash:
911
- input.prepublishVerificationHash || null,
912
- candidatePreflightHash:
913
- input.candidatePreflightHash || null,
914
- openxiangdaVersion: input.openxiangdaVersion,
915
- };
916
- return {
917
- sourceBundleManifest,
918
- candidateHash: sha256Canonical(sourceBundleManifest),
919
- testPlan,
920
- testPlanHash: sourceBundleManifest.testPlanHash,
921
- };
922
- }
923
-
924
- function inspectCandidateBundleFiles(candidate, cwd = process.cwd()) {
925
- const manifest =
926
- candidate?.sourceBundleManifest &&
927
- typeof candidate.sourceBundleManifest === 'object'
928
- ? candidate.sourceBundleManifest
929
- : candidate;
930
- const expectedFiles = Array.isArray(manifest?.files)
931
- ? manifest.files
932
- : [];
933
- const mismatches = [];
934
- const seen = new Set();
935
- for (const expected of expectedFiles) {
936
- const file = String(expected?.path || '').replace(/\\/g, '/');
937
- if (!file || seen.has(file)) {
938
- mismatches.push({
939
- path: file || '(missing path)',
940
- reason: seen.has(file) ? 'duplicate' : 'invalid',
941
- });
942
- continue;
943
- }
944
- seen.add(file);
945
- const hashPolicy = expected.hashPolicy || null;
946
- if (hashPolicy && !CANDIDATE_STATE_HASH_POLICIES.has(hashPolicy)) {
947
- mismatches.push({
948
- path: file,
949
- reason: 'unsupported-hash-policy',
950
- hashPolicy,
951
- });
952
- continue;
953
- }
954
- let current;
955
- try {
956
- current = hashCandidateWorkspaceFile(path.resolve(cwd), file, {
957
- hashPolicy,
958
- });
959
- } catch (error) {
960
- mismatches.push({
961
- path: file,
962
- reason: 'invalid',
963
- errorCode: error.code || null,
964
- });
965
- continue;
966
- }
967
- const expectedExists = expected.exists !== false;
968
- if (!current || (expectedExists && current.exists === false)) {
969
- mismatches.push({ path: file, reason: 'missing' });
970
- continue;
971
- }
972
- if (!expectedExists) {
973
- if (current.exists !== false) {
974
- mismatches.push({ path: file, reason: 'reappeared', current });
975
- }
976
- continue;
977
- }
978
- if (
979
- current.size !== Number(expected.size) ||
980
- current.sha256 !== String(expected.sha256 || '').toLowerCase()
981
- ) {
982
- mismatches.push({
983
- path: file,
984
- reason: 'changed',
985
- expected: {
986
- size: Number(expected.size),
987
- sha256: String(expected.sha256 || '').toLowerCase(),
988
- },
989
- current,
990
- });
991
- }
992
- }
993
- return {
994
- valid: mismatches.length === 0,
995
- checked: expectedFiles.length,
996
- mismatches,
997
- };
998
- }
999
-
1000
- function assertCandidateBundleFilesCurrent(candidate, cwd = process.cwd()) {
1001
- const inspection = inspectCandidateBundleFiles(candidate, cwd);
1002
- if (inspection.valid) return inspection;
1003
- const error = new Error(
1004
- `CANDIDATE_INPUTS_CHANGED: sealed candidate 的发布输入已变化: ${inspection.mismatches
1005
- .slice(0, 8)
1006
- .map(item => `${item.path}(${item.reason})`)
1007
- .join(', ')}`
1008
- );
1009
- error.code = 'CANDIDATE_INPUTS_CHANGED';
1010
- error.details = inspection;
1011
- throw error;
1012
- }
1013
-
1014
- function releaseExecutionPath(changeId, deploymentId, cwd = process.cwd()) {
1015
- const base = path.join(
1016
- cwd,
1017
- '.openxiangda',
1018
- 'releases',
1019
- String(changeId || '').trim()
1020
- );
1021
- const deployment = String(deploymentId || '').trim();
1022
- return deployment
1023
- ? path.join(base, deployment, 'execution.json')
1024
- : path.join(base, 'execution.json');
1025
- }
1026
-
1027
- function withManagedReleaseForwardedFlags(stepId, args = [], flags = {}) {
1028
- const forwarded = [...args];
1029
- if (stepId === 'runtime-stage' && flags['allow-runtime-rollback']) {
1030
- forwarded.push('--allow-runtime-rollback');
1031
- const rollbackReason = String(flags.reason || '').trim();
1032
- if (rollbackReason) {
1033
- forwarded.push('--reason', rollbackReason);
1034
- }
1035
- return forwarded;
1036
- }
1037
- const immutableResourceStages = new Set([
1038
- 'backend-stage',
1039
- 'workflow-stage',
1040
- ]);
1041
- if (
1042
- immutableResourceStages.has(stepId) &&
1043
- !forwarded.includes('--include-noop')
1044
- ) {
1045
- forwarded.push('--include-noop');
1046
- }
1047
- const isExactResourcePublish =
1048
- forwarded[0] === 'resource' &&
1049
- forwarded[1] === 'publish' &&
1050
- (forwarded.includes('--only') || forwarded.includes('--code'));
1051
- if (!isExactResourcePublish) {
1052
- return forwarded;
1053
- }
1054
- if (stepId === 'backend-stage' && flags['replace-manifest']) {
1055
- forwarded.push('--replace-manifest');
1056
- const replacementReason = String(flags.reason || '').trim();
1057
- if (replacementReason) {
1058
- forwarded.push('--reason', replacementReason);
1059
- }
1060
- }
1061
- if (flags['adopt-online-baseline']) {
1062
- forwarded.push('--adopt-online-baseline');
1063
- const adoptionReason = String(
1064
- flags['adoption-reason'] || flags.reason || ''
1065
- ).trim();
1066
- if (adoptionReason) {
1067
- forwarded.push('--adoption-reason', adoptionReason);
1068
- }
1069
- }
1070
- return forwarded;
1071
- }
1072
-
1073
- function withReleaseClientSessionArgs(args = [], flags = {}) {
1074
- const clientSessionId = String(flags['client-session-id'] || '').trim();
1075
- return clientSessionId
1076
- ? [...args, '--client-session-id', clientSessionId]
1077
- : [...args];
1078
- }
1079
-
1080
- function isRecoverablePostActivationDeploymentError(error, deployment) {
1081
- if (
1082
- deployment?.status !== 'deployed' ||
1083
- !String(deployment?.targetAppReleaseId || '').trim()
1084
- ) {
1085
- return false;
1086
- }
1087
- const detail = [
1088
- error?.code,
1089
- error?.message,
1090
- error?.publishLeaseCleanupError?.code,
1091
- error?.publishLeaseCleanupError?.message,
1092
- ]
1093
- .filter(Boolean)
1094
- .join(' ');
1095
- return (
1096
- /(publish[\s_-]*lease|publishLease|发布租约)/i.test(detail) &&
1097
- /(concurr|conflict|cleanup|release[\s_-]*end|并发冲突|清理|释放)/i.test(
1098
- detail
1099
- )
1100
- );
1101
- }
1102
-
1103
- module.exports = {
1104
- assertCandidateBundleFilesCurrent,
1105
- assertCandidateEnvironmentBindingsCurrent,
1106
- bindEnvironmentTarget,
1107
- buildCandidateEnvironmentBindings,
1108
- buildSideEffectPolicyDiff,
1109
- buildCandidateBundle,
1110
- canonicalJson,
1111
- isRecoverablePostActivationDeploymentError,
1112
- normalizeEnvironmentKind,
1113
- normalizeManagedChangeSourceBase,
1114
- normalizeManagedReleaseSourceRevision,
1115
- normalizeReleaseSourceRevisionForBaseline,
1116
- normalizeSideEffectPolicyInput,
1117
- normalizeTargetName,
1118
- hasStateResourceMappings,
1119
- inspectCandidateBundleFiles,
1120
- inspectCandidateEnvironmentBindings,
1121
- managedTargetDeploymentFile,
1122
- readCandidate,
1123
- readJsonInput,
1124
- readRememberedTargetDeployment,
1125
- releaseExecutionPath,
1126
- rememberTargetDeployment,
1127
- resolveManagedStateBinding,
1128
- resolveEnvironmentTarget,
1129
- saveCandidate,
1130
- sha256Canonical,
1131
- withManagedReleaseForwardedFlags,
1132
- withReleaseClientSessionArgs,
1133
- writePrivateJsonAtomic,
1134
- };