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,1703 +0,0 @@
1
- const crypto = require('crypto');
2
- const fs = require('fs');
3
- const os = require('os');
4
- const path = require('path');
5
- const {
6
- collectConfigurationManifestCodes,
7
- collectManifestCodes,
8
- compileAppPackage,
9
- sha256,
10
- sha256Canonical,
11
- } = require('./delivery-v2-package');
12
- const {
13
- buildWorkspaceReleaseSteps,
14
- commandFromArgs,
15
- } = require('./release-plan');
16
-
17
- const CONFIG_TARGET_BY_RESOURCE_TYPE = Object.freeze({
18
- role: 'roles',
19
- connector: 'connectors',
20
- notification: 'notifications',
21
- menu: 'menus',
22
- 'data-view': 'dataViews',
23
- storage: 'storageConfigs',
24
- 'auth-config': 'authConfigs',
25
- route: 'routes',
26
- 'public-access': 'publicAccessPolicies',
27
- 'page-permission-group': 'pagePermissionGroups',
28
- 'form-permission-group': 'formPermissionGroups',
29
- 'scope-dimension': 'scopeDimensions',
30
- 'scope-grant-source': 'scopeGrantSources',
31
- 'data-scope-policy': 'dataScopePolicies',
32
- });
33
-
34
- function createDeliveryV2Executor(dependencies) {
35
- const deps = assertDependencies(dependencies);
36
-
37
- async function inspect(input) {
38
- const previous = await latestSuccessfulRun(input.config, input.target);
39
- const compiled = await compileAppPackage({
40
- workspaceRoot: input.workspaceRoot,
41
- previousManifest: previous?.packageManifest || null,
42
- skipBuild: input.skipBuild === true,
43
- buildCommand: input.buildCommand,
44
- distDir: input.distDir,
45
- onBuildOutput: input.onBuildOutput,
46
- });
47
- const targets = releaseTargets(
48
- compiled.packageManifest,
49
- previous?.packageManifest || null
50
- );
51
- return {
52
- compiled,
53
- previous,
54
- targets,
55
- plan: describeExecutionPlan(
56
- targets,
57
- compiled.packageManifest.runtimeMode,
58
- input.target.profileName
59
- ),
60
- };
61
- }
62
-
63
- async function deploy(input) {
64
- const previous = await latestSuccessfulRun(input.config, input.target);
65
- let compiled;
66
- let executionRoot = path.resolve(input.workspaceRoot || process.cwd());
67
- let materialized = false;
68
-
69
- if (input.packageDigest) {
70
- const packageManifest = await downloadPackageManifest(
71
- input.config,
72
- input.target,
73
- input.packageDigest
74
- );
75
- executionRoot = await materializePackageWorkspace({
76
- config: input.config,
77
- target: input.target,
78
- packageDigest: input.packageDigest,
79
- packageManifest,
80
- sourceWorkspaceRoot: executionRoot,
81
- });
82
- compiled = {
83
- workspaceRoot: executionRoot,
84
- packageDigest: input.packageDigest,
85
- packageManifest,
86
- artifacts: [],
87
- summary: packageSummary(packageManifest, previous?.packageManifest),
88
- };
89
- materialized = true;
90
- } else {
91
- compiled = await compileAppPackage({
92
- workspaceRoot: executionRoot,
93
- previousManifest: previous?.packageManifest || null,
94
- buildCommand: input.buildCommand,
95
- distDir: input.distDir,
96
- onBuildOutput: input.onBuildOutput,
97
- });
98
- }
99
-
100
- const targets = releaseTargets(
101
- compiled.packageManifest,
102
- previous?.packageManifest || null,
103
- { forceAll: input.forceAll === true }
104
- );
105
- const plan = describeExecutionPlan(
106
- targets,
107
- compiled.packageManifest.runtimeMode,
108
- input.target.profileName
109
- );
110
- if (!input.packageDigest) {
111
- await uploadArtifacts(input.config, input.target, compiled.artifacts);
112
- }
113
- let run = await createRun({
114
- config: input.config,
115
- target: input.target,
116
- packageDigest: compiled.packageDigest,
117
- packageManifest: compiled.packageManifest,
118
- kind: input.kind || 'deploy',
119
- idempotencyKey:
120
- input.idempotencyKey ||
121
- defaultIdempotencyKey(
122
- input.kind || 'deploy',
123
- input.target,
124
- compiled.packageDigest
125
- ),
126
- clientSessionId: input.clientSessionId,
127
- });
128
- if (run.status === 'succeeded') {
129
- return {
130
- run,
131
- packageDigest: compiled.packageDigest,
132
- packageManifest: compiled.packageManifest,
133
- summary: compiled.summary,
134
- targets,
135
- plan,
136
- materialized,
137
- idempotent: true,
138
- };
139
- }
140
- if (run.status !== 'packaged') {
141
- if (run.status === 'failed') {
142
- run = await requestRunRetry(input.config, input.target, run);
143
- } else {
144
- throw runNotExecutableError(run, input.target);
145
- }
146
- }
147
-
148
- const result = await executeRun({
149
- config: input.config,
150
- target: input.target,
151
- run,
152
- packageDigest: compiled.packageDigest,
153
- packageManifest: compiled.packageManifest,
154
- targets,
155
- plan,
156
- executionRoot,
157
- skipCompleted: true,
158
- });
159
- return {
160
- ...result,
161
- summary: compiled.summary,
162
- targets,
163
- plan,
164
- materialized,
165
- idempotent: false,
166
- };
167
- }
168
-
169
- async function retry(input) {
170
- const current = await runDetail(
171
- input.config,
172
- input.target,
173
- input.runId
174
- );
175
- if (current.status === 'succeeded') {
176
- return { run: current, idempotent: true };
177
- }
178
- const run = await requestRunRetry(
179
- input.config,
180
- input.target,
181
- current
182
- );
183
- if (run.status !== 'packaged') {
184
- throw deliveryError(
185
- 'DELIVERY_RUN_NOT_EXECUTABLE',
186
- `ReleaseRun ${run.id} 当前状态为 ${run.status}`,
187
- false
188
- );
189
- }
190
- const executionRoot = await materializePackageWorkspace({
191
- config: input.config,
192
- target: input.target,
193
- packageDigest: run.packageDigest,
194
- packageManifest: run.packageManifest,
195
- sourceWorkspaceRoot: input.workspaceRoot,
196
- });
197
- const previous = await latestSuccessfulRun(input.config, input.target, {
198
- excludeRunId: run.id,
199
- });
200
- const targets = releaseTargets(
201
- run.packageManifest,
202
- previous?.packageManifest || null
203
- );
204
- return await executeRun({
205
- config: input.config,
206
- target: input.target,
207
- run,
208
- packageDigest: run.packageDigest,
209
- packageManifest: run.packageManifest,
210
- targets,
211
- executionRoot,
212
- skipCompleted: true,
213
- });
214
- }
215
-
216
- async function rollback(input) {
217
- const targetRun = await findSuccessfulRunByRelease(
218
- input.config,
219
- input.target,
220
- input.releaseId
221
- );
222
- if (!targetRun) {
223
- throw deliveryError(
224
- 'DELIVERY_ROLLBACK_RELEASE_NOT_FOUND',
225
- `未找到 App Release ${input.releaseId} 对应的成功 Delivery V2 记录`,
226
- false
227
- );
228
- }
229
- return await deploy({
230
- ...input,
231
- kind: 'rollback',
232
- packageDigest: targetRun.packageDigest,
233
- forceAll: true,
234
- idempotencyKey:
235
- input.idempotencyKey ||
236
- `rollback:${targetRun.id}:${Date.now().toString(36)}`,
237
- });
238
- }
239
-
240
- async function status(input) {
241
- return await runDetail(input.config, input.target, input.runId);
242
- }
243
-
244
- async function executeRun(input) {
245
- const originalCwd = process.cwd();
246
- const executionTarget = {
247
- ...input.target,
248
- deploymentId:
249
- input.run?.deploymentId ||
250
- input.run?.control?.deploymentId ||
251
- input.target.deploymentId ||
252
- null,
253
- };
254
- let activeRun = input.run;
255
- let currentStep = 'preparing';
256
- let currentComponent = 'delivery-v2';
257
- try {
258
- process.chdir(input.executionRoot);
259
- const executionTargets = normalizeLegacyPackageTargetsForExecution(
260
- input.targets,
261
- input.executionRoot
262
- );
263
- deps.installDeliveryContext(
264
- executionTarget,
265
- activeRun,
266
- executionTargets
267
- );
268
- restoreDeliveryCheckpointFiles(
269
- input.executionRoot,
270
- activeRun,
271
- executionTarget
272
- );
273
- const recordCheckpoint = async body => {
274
- const expectedAttempt = Number(activeRun?.attempt || 1);
275
- const updated = await checkpoint(
276
- input.config,
277
- executionTarget,
278
- activeRun.id,
279
- { ...body, expectedAttempt }
280
- );
281
- if (
282
- updated?.attempt !== undefined &&
283
- Number(updated.attempt) !== expectedAttempt
284
- ) {
285
- throw deliveryError(
286
- 'DELIVERY_ATTEMPT_FENCED',
287
- `ReleaseRun ${activeRun.id} attempt ${expectedAttempt} 已被 attempt ${updated?.attempt || 'unknown'} 接管`,
288
- false
289
- );
290
- }
291
- return updated;
292
- };
293
- activeRun = await recordCheckpoint({
294
- stage: lifecycleStage('preparing', activeRun.attempt),
295
- status: 'preparing',
296
- component: 'package',
297
- progress: {
298
- packageDigest: input.packageDigest,
299
- },
300
- });
301
- const steps = decorateSteps(
302
- buildWorkspaceReleaseSteps(
303
- executionTargets,
304
- input.packageManifest.runtimeMode,
305
- executionTarget.profileName,
306
- activeRun.control?.changeId
307
- ),
308
- executionTarget,
309
- activeRun,
310
- input.packageManifest,
311
- input.executionRoot
312
- );
313
-
314
- const stepResults = {};
315
- for (const [index, step] of steps.entries()) {
316
- const doneStage = checkpointName('done', step.id);
317
- if (input.skipCompleted && activeRun.checkpoints?.[doneStage]) {
318
- const completedResult =
319
- activeRun.result?.[doneStage] || { resumed: true };
320
- if (step.resumeMode === 'replay-local') {
321
- currentStep = `${step.id}-replay-local`;
322
- currentComponent = step.stagedKind || step.id;
323
- const replayResult = await deps.runOpenXiangdaInProcess(
324
- [...step.args, '--replay-local'],
325
- { quiet: true }
326
- );
327
- stepResults[step.id] = {
328
- ...completedResult,
329
- resumed: true,
330
- localReplay: compactLocalReplayResult(replayResult),
331
- };
332
- activeRun = await recordCheckpoint({
333
- stage: lifecycleStage(
334
- `replay-${step.id}`,
335
- activeRun.attempt
336
- ),
337
- status: 'preparing',
338
- component: currentComponent,
339
- result: {
340
- mode: 'replay-local',
341
- ...compactLocalReplayResult(replayResult),
342
- },
343
- });
344
- } else {
345
- stepResults[step.id] = completedResult;
346
- }
347
- continue;
348
- }
349
- currentStep = step.id;
350
- currentComponent = step.stagedKind || step.id;
351
- if (step.id === 'app-finalize') {
352
- prepareAppFinalizeStep(step, {
353
- executionRoot: input.executionRoot,
354
- run: activeRun,
355
- target: executionTarget,
356
- steps,
357
- });
358
- activeRun = await recordCheckpoint({
359
- stage: lifecycleStage('activating', activeRun.attempt),
360
- status: 'activating',
361
- component: 'app-release',
362
- progress: {
363
- completed: index,
364
- total: steps.length,
365
- },
366
- });
367
- }
368
- const result = await deps.runOpenXiangdaInProcess(step.args, {
369
- quiet: true,
370
- });
371
- stepResults[step.id] = result;
372
- activeRun = await recordCheckpoint({
373
- stage: doneStage,
374
- component: currentComponent,
375
- progress: {
376
- completed: index + 1,
377
- total: steps.length,
378
- },
379
- result: compactStepResult(step.id, result, {
380
- executionRoot: input.executionRoot,
381
- run: activeRun,
382
- target: executionTarget,
383
- }),
384
- });
385
- }
386
-
387
- if (activeRun.status !== 'verifying') {
388
- if (activeRun.status !== 'activating') {
389
- activeRun = await recordCheckpoint({
390
- stage: lifecycleStage('activating', activeRun.attempt),
391
- status: 'activating',
392
- component: 'activation',
393
- });
394
- }
395
- activeRun = await recordCheckpoint({
396
- stage: lifecycleStage('verifying', activeRun.attempt),
397
- status: 'verifying',
398
- component: 'readback',
399
- });
400
- }
401
- const verification = await verifyActivation(
402
- input.config,
403
- executionTarget,
404
- stepResults
405
- );
406
- activeRun = await recordCheckpoint({
407
- stage: 'succeeded',
408
- status: 'succeeded',
409
- component: 'delivery-v2',
410
- progress: {
411
- completed: steps.length,
412
- total: steps.length,
413
- },
414
- result: {
415
- packageDigest: input.packageDigest,
416
- appReleaseId: verification.appReleaseId,
417
- runtimeReleaseId: verification.runtimeReleaseId,
418
- },
419
- });
420
- return {
421
- run: activeRun,
422
- packageDigest: input.packageDigest,
423
- packageManifest: input.packageManifest,
424
- steps: steps.map(step => ({
425
- id: step.id,
426
- command: step.command,
427
- })),
428
- verification,
429
- };
430
- } catch (error) {
431
- const failure = structuredFailure(
432
- error,
433
- activeRun?.id,
434
- currentStep,
435
- currentComponent
436
- );
437
- if (activeRun?.id) {
438
- try {
439
- await deps.requestWithAuth(
440
- input.config,
441
- executionTarget.profileName,
442
- runPath(
443
- executionTarget,
444
- `/${encodeURIComponent(activeRun.id)}/fail`
445
- ),
446
- {
447
- method: 'POST',
448
- retryTransient: true,
449
- body: {
450
- expectedAttempt: Number(activeRun?.attempt || 1),
451
- stage: failure.stage,
452
- component: failure.component,
453
- code: failure.code,
454
- message: failure.message,
455
- retryable: failure.retryable,
456
- details: {
457
- progressPreserved: true,
458
- },
459
- },
460
- }
461
- );
462
- } catch {
463
- // The original execution failure remains authoritative.
464
- }
465
- }
466
- error.deliveryFailure = failure;
467
- error.data = failure;
468
- error.code = failure.code;
469
- throw error;
470
- } finally {
471
- try {
472
- deps.clearDeliveryContext(executionTarget, activeRun);
473
- } finally {
474
- process.chdir(originalCwd);
475
- }
476
- }
477
- }
478
-
479
- async function uploadArtifacts(config, target, artifacts) {
480
- for (const artifact of artifacts || []) {
481
- if (await artifactExists(config, target, artifact.digest)) continue;
482
- const query = new URLSearchParams({
483
- kind: artifact.kind,
484
- contentType: artifact.contentType || 'application/octet-stream',
485
- metadata: JSON.stringify(cleanObject(artifact.metadata)),
486
- });
487
- await deps.requestFormWithAuth(
488
- config,
489
- target.profileName,
490
- `${artifactPath(target, artifact.digest)}?${query.toString()}`,
491
- () => {
492
- const form = new FormData();
493
- form.append(
494
- 'file',
495
- new Blob([artifact.buffer], {
496
- type: artifact.contentType || 'application/octet-stream',
497
- }),
498
- artifact.metadata?.path || artifact.digest
499
- );
500
- return form;
501
- },
502
- { retryTransient: true, retries: 2 }
503
- );
504
- }
505
- }
506
-
507
- async function artifactExists(config, target, digest) {
508
- try {
509
- await deps.requestWithAuth(
510
- config,
511
- target.profileName,
512
- artifactPath(target, digest),
513
- { retryTransient: true }
514
- );
515
- return true;
516
- } catch (error) {
517
- if (isNotFound(error)) return false;
518
- throw error;
519
- }
520
- }
521
-
522
- async function downloadPackageManifest(config, target, digestInput) {
523
- const digest = normalizeDigest(digestInput);
524
- const downloaded = await deps.downloadWithAuth(
525
- config,
526
- target.profileName,
527
- `${artifactPath(target, digest)}/content`,
528
- { retries: 2 }
529
- );
530
- if (sha256(downloaded.buffer) !== digest) {
531
- throw deliveryError(
532
- 'DELIVERY_PACKAGE_DOWNLOAD_DIGEST_MISMATCH',
533
- `下载的 package manifest 与 ${digest} 不一致`,
534
- true
535
- );
536
- }
537
- let manifest;
538
- try {
539
- manifest = JSON.parse(downloaded.buffer.toString('utf8'));
540
- } catch {
541
- throw deliveryError(
542
- 'DELIVERY_PACKAGE_MANIFEST_INVALID',
543
- 'package manifest 不是合法 JSON',
544
- false
545
- );
546
- }
547
- if (
548
- manifest.schemaVersion !== 'openxiangda-app-package-v2' ||
549
- sha256Canonical(manifest) !== digest
550
- ) {
551
- throw deliveryError(
552
- 'DELIVERY_PACKAGE_MANIFEST_INVALID',
553
- 'package manifest schema 或摘要无效',
554
- false
555
- );
556
- }
557
- return manifest;
558
- }
559
-
560
- async function materializePackageWorkspace(input) {
561
- const root = packageWorkspaceRoot(
562
- input.sourceWorkspaceRoot,
563
- input.packageDigest
564
- );
565
- fs.mkdirSync(root, { recursive: true });
566
- const sourceLayer = layerByKind(input.packageManifest, 'source');
567
- if (!sourceLayer) {
568
- throw deliveryError(
569
- 'DELIVERY_PACKAGE_SOURCE_LAYER_MISSING',
570
- 'package manifest 缺少 source layer',
571
- false
572
- );
573
- }
574
- await materializeFiles(
575
- input.config,
576
- input.target,
577
- root,
578
- sourceLayer.files || []
579
- );
580
- const stateSource = path.join(
581
- path.resolve(input.sourceWorkspaceRoot || process.cwd()),
582
- '.openxiangda',
583
- 'state.json'
584
- );
585
- const stateTarget = path.join(root, '.openxiangda', 'state.json');
586
- if (fs.existsSync(stateSource)) {
587
- fs.mkdirSync(path.dirname(stateTarget), { recursive: true });
588
- fs.copyFileSync(stateSource, stateTarget);
589
- } else if (fs.existsSync(stateTarget)) {
590
- fs.unlinkSync(stateTarget);
591
- }
592
- const nodeModulesTarget = path.join(root, 'node_modules');
593
- const sealedBuild =
594
- input.packageManifest?.buildRequirements?.workspaceNodeModules ===
595
- 'forbidden';
596
- if (sealedBuild) {
597
- materializeBundledBuildClosure(root);
598
- } else {
599
- const nodeModulesSource = path.join(
600
- path.resolve(input.sourceWorkspaceRoot || process.cwd()),
601
- 'node_modules'
602
- );
603
- if (
604
- fs.existsSync(nodeModulesSource) &&
605
- !fs.existsSync(nodeModulesTarget)
606
- ) {
607
- fs.symlinkSync(nodeModulesSource, nodeModulesTarget, 'dir');
608
- }
609
- }
610
- const runtimeLayer = layerByKind(input.packageManifest, 'runtime');
611
- if (runtimeLayer) {
612
- await materializeFiles(
613
- input.config,
614
- input.target,
615
- path.join(root, 'dist'),
616
- runtimeLayer.files || []
617
- );
618
- }
619
- return root;
620
- }
621
-
622
- async function materializeFiles(config, target, root, files) {
623
- for (const descriptor of files) {
624
- const relative = safeRelativePath(descriptor.path);
625
- const destination = path.join(root, relative);
626
- if (fs.existsSync(destination)) {
627
- const existing = fs.readFileSync(destination);
628
- if (sha256(existing) === descriptor.digest) continue;
629
- }
630
- const downloaded = await deps.downloadWithAuth(
631
- config,
632
- target.profileName,
633
- `${artifactPath(target, descriptor.digest)}/content`,
634
- { retries: 2 }
635
- );
636
- if (sha256(downloaded.buffer) !== descriptor.digest) {
637
- throw deliveryError(
638
- 'DELIVERY_ARTIFACT_DOWNLOAD_DIGEST_MISMATCH',
639
- `制品 ${descriptor.digest} 下载校验失败`,
640
- true
641
- );
642
- }
643
- fs.mkdirSync(path.dirname(destination), { recursive: true });
644
- const temporary = `${destination}.${process.pid}.tmp`;
645
- fs.writeFileSync(temporary, downloaded.buffer, { mode: 0o600 });
646
- fs.renameSync(temporary, destination);
647
- }
648
- }
649
-
650
- async function latestSuccessfulRun(config, target, options = {}) {
651
- const list = await deps.requestWithAuth(
652
- config,
653
- target.profileName,
654
- `${runPath(target)}?limit=100`,
655
- { retryTransient: true }
656
- );
657
- const candidate = (list?.items || []).find(
658
- item =>
659
- item.status === 'succeeded' &&
660
- item.id !== options.excludeRunId &&
661
- sameEnvironment(item, target)
662
- );
663
- return candidate
664
- ? await runDetail(config, target, candidate.id)
665
- : null;
666
- }
667
-
668
- async function findSuccessfulRunByRelease(config, target, releaseId) {
669
- const list = await deps.requestWithAuth(
670
- config,
671
- target.profileName,
672
- `${runPath(target)}?limit=100`,
673
- { retryTransient: true }
674
- );
675
- for (const item of list?.items || []) {
676
- if (item.status !== 'succeeded' || !sameEnvironment(item, target)) {
677
- continue;
678
- }
679
- const detail = await runDetail(config, target, item.id);
680
- if (
681
- detail.result?.succeeded?.appReleaseId === releaseId ||
682
- detail.result?.activation?.appReleaseId === releaseId
683
- ) {
684
- return detail;
685
- }
686
- }
687
- return null;
688
- }
689
-
690
- async function runDetail(config, target, runId) {
691
- return await deps.requestWithAuth(
692
- config,
693
- target.profileName,
694
- runPath(target, `/${encodeURIComponent(runId)}`),
695
- { retryTransient: true }
696
- );
697
- }
698
-
699
- async function createRun(input) {
700
- return await deps.requestWithAuth(
701
- input.config,
702
- input.target.profileName,
703
- runPath(input.target),
704
- {
705
- method: 'POST',
706
- retryTransient: true,
707
- retries: 2,
708
- body: {
709
- environmentId: input.target.environmentId || null,
710
- environmentKind: input.target.environmentKind || null,
711
- kind: input.kind,
712
- packageDigest: input.packageDigest,
713
- packageManifest: input.packageManifest,
714
- idempotencyKey: input.idempotencyKey,
715
- clientSessionId: input.clientSessionId,
716
- },
717
- }
718
- );
719
- }
720
-
721
- async function requestRunRetry(config, target, run) {
722
- return await deps.requestWithAuth(
723
- config,
724
- target.profileName,
725
- runPath(target, `/${encodeURIComponent(run.id)}/retry`),
726
- {
727
- method: 'POST',
728
- retryTransient: true,
729
- body: { expectedAttempt: Number(run.attempt || 1) },
730
- }
731
- );
732
- }
733
-
734
- async function checkpoint(config, target, runId, body) {
735
- return await deps.requestWithAuth(
736
- config,
737
- target.profileName,
738
- runPath(target, `/${encodeURIComponent(runId)}/checkpoints`),
739
- {
740
- method: 'POST',
741
- retryTransient: true,
742
- retries: 2,
743
- body,
744
- }
745
- );
746
- }
747
-
748
- async function verifyActivation(config, target, stepResults) {
749
- const [appHead, runtimeHead] = await Promise.all([
750
- deps.requestWithAuth(
751
- config,
752
- target.profileName,
753
- appApiPath(target, '/app-releases/head'),
754
- { retryTransient: true }
755
- ),
756
- deps.requestWithAuth(
757
- config,
758
- target.profileName,
759
- appApiPath(target, '/runtime/releases/head'),
760
- { retryTransient: true }
761
- ),
762
- ]);
763
- const finalized = stepResults['app-finalize'];
764
- const expectedAppReleaseId =
765
- finalized?.activated?.id ||
766
- finalized?.verified?.id ||
767
- finalized?.prepared?.id ||
768
- null;
769
- const activeAppReleaseId =
770
- appHead?.activeAppReleaseId || appHead?.release?.id || null;
771
- if (
772
- expectedAppReleaseId &&
773
- activeAppReleaseId &&
774
- expectedAppReleaseId !== activeAppReleaseId
775
- ) {
776
- throw deliveryError(
777
- 'DELIVERY_ACTIVATION_READBACK_MISMATCH',
778
- `App Release 激活读回不一致: expected=${expectedAppReleaseId} actual=${activeAppReleaseId}`,
779
- true
780
- );
781
- }
782
- return {
783
- appReleaseId: activeAppReleaseId || expectedAppReleaseId,
784
- runtimeReleaseId: runtimeHead?.activeRuntimeReleaseId || null,
785
- runtimeBuildId: runtimeHead?.activeRuntimeBuildId || null,
786
- };
787
- }
788
-
789
- return {
790
- deploy,
791
- inspect,
792
- retry,
793
- rollback,
794
- status,
795
- };
796
- }
797
-
798
- function packageWorkspaceRoot(sourceWorkspaceRoot, digestInput) {
799
- const sourceWorkspace = path.resolve(
800
- sourceWorkspaceRoot || process.cwd()
801
- );
802
- const workspaceKey = sha256(Buffer.from(sourceWorkspace)).slice(0, 20);
803
- return path.join(
804
- fs.realpathSync(os.tmpdir()),
805
- 'openxiangda-delivery-v2',
806
- workspaceKey,
807
- normalizeDigest(digestInput)
808
- );
809
- }
810
-
811
- function materializeBundledBuildClosure(root) {
812
- const nodeModulesRoot = path.join(root, 'node_modules');
813
- if (
814
- fs.existsSync(nodeModulesRoot) &&
815
- fs.lstatSync(nodeModulesRoot).isSymbolicLink()
816
- ) {
817
- throw deliveryError(
818
- 'DELIVERY_BUILD_CLOSURE_CONTAMINATED',
819
- `密封构建 node_modules 不能是软链接: ${nodeModulesRoot}`,
820
- false
821
- );
822
- }
823
- fs.mkdirSync(nodeModulesRoot, { recursive: true });
824
- ensureBuildClosureLink(
825
- path.join(nodeModulesRoot, 'openxiangda'),
826
- path.resolve(__dirname, '..')
827
- );
828
- const nodeTypesRoot = path.dirname(
829
- require.resolve('@types/node/package.json')
830
- );
831
- const scopedTypesRoot = path.join(nodeModulesRoot, '@types');
832
- fs.mkdirSync(scopedTypesRoot, { recursive: true });
833
- ensureBuildClosureLink(path.join(scopedTypesRoot, 'node'), nodeTypesRoot);
834
- }
835
-
836
- function ensureBuildClosureLink(target, source) {
837
- const resolvedSource = fs.realpathSync(source);
838
- if (fs.existsSync(target)) {
839
- const stat = fs.lstatSync(target);
840
- if (
841
- !stat.isSymbolicLink() ||
842
- fs.realpathSync(target) !== resolvedSource
843
- ) {
844
- throw deliveryError(
845
- 'DELIVERY_BUILD_CLOSURE_CONTAMINATED',
846
- `密封构建依赖槽位被非预期内容占用: ${target}`,
847
- false
848
- );
849
- }
850
- return;
851
- }
852
- fs.symlinkSync(resolvedSource, target, 'dir');
853
- }
854
-
855
- function releaseTargets(manifest, previousManifest, options = {}) {
856
- const layerChanged = kind =>
857
- options.forceAll === true ||
858
- layerByKind(manifest, kind)?.digest !==
859
- layerByKind(previousManifest, kind)?.digest;
860
- const resources = manifest?.resources || {};
861
- const previousResources = previousManifest?.resources || {};
862
- const fingerprints = resources.resourceFingerprints || {};
863
- const previousFingerprints =
864
- previousResources.resourceFingerprints || {};
865
- const diffBucket = (kind, layerKind, currentCodes, previousCodes) =>
866
- diffResourceFingerprintBucket({
867
- current: fingerprints[kind],
868
- previous: previousFingerprints[kind],
869
- currentCodes,
870
- previousCodes,
871
- changed:
872
- layerChanged(layerKind) ||
873
- fingerprintBucketChanged(
874
- fingerprints[kind],
875
- previousFingerprints[kind]
876
- ),
877
- forceAll: options.forceAll === true,
878
- sharedChanged:
879
- fingerprints.shared?.[layerKind] !==
880
- previousFingerprints.shared?.[layerKind],
881
- });
882
- const formDiff = diffBucket(
883
- 'forms',
884
- 'form',
885
- resources.forms,
886
- previousResources.forms
887
- );
888
- const functionDiff = diffBucket(
889
- 'functions',
890
- 'backend',
891
- resources.functions,
892
- previousResources.functions
893
- );
894
- const automationDiff = diffBucket(
895
- 'automations',
896
- 'backend',
897
- resources.automations,
898
- previousResources.automations
899
- );
900
- const workflowDiff = diffBucket(
901
- 'workflows',
902
- 'workflow',
903
- resources.workflows,
904
- previousResources.workflows
905
- );
906
- const resourceSelectors = {};
907
- const resourceDeletes = {};
908
- const selectedConfigurationOwners = [];
909
- if (
910
- layerChanged('configuration') ||
911
- fingerprintBucketChanged(
912
- fingerprints.configuration,
913
- previousFingerprints.configuration
914
- )
915
- ) {
916
- const types = new Set([
917
- ...Object.keys(resources.configuration || {}),
918
- ...Object.keys(previousResources.configuration || {}),
919
- ]);
920
- for (const type of [...types].sort()) {
921
- const key = CONFIG_TARGET_BY_RESOURCE_TYPE[type];
922
- if (!key) continue;
923
- const diff = diffResourceFingerprintBucket({
924
- current: fingerprints.configuration?.[type],
925
- previous: previousFingerprints.configuration?.[type],
926
- currentCodes: resources.configuration?.[type],
927
- previousCodes: previousResources.configuration?.[type],
928
- changed: true,
929
- forceAll: options.forceAll === true,
930
- sharedChanged:
931
- fingerprints.shared?.configuration !==
932
- previousFingerprints.shared?.configuration,
933
- });
934
- if (diff.changed.length > 0) {
935
- resourceSelectors[key] = diff.changed;
936
- selectedConfigurationOwners.push(
937
- ...diff.changed.map(code => `${type}:${code}`)
938
- );
939
- }
940
- if (diff.removed.length > 0) {
941
- resourceDeletes[key] = diff.removed;
942
- }
943
- }
944
- }
945
- const permissionAffectedForms = uniqueStrings(
946
- (resourceSelectors.formPermissionGroups || []).flatMap(
947
- code => resources.formPermissionGroupForms?.[code] || []
948
- )
949
- );
950
- const forms = uniqueStrings([
951
- ...formDiff.changed,
952
- ...permissionAffectedForms,
953
- ]);
954
- const dependencyForms = new Set();
955
- const dependenciesByResource =
956
- resources.formDependenciesByResource || {};
957
- for (const owner of [
958
- ...functionDiff.changed.map(code => `function:${code}`),
959
- ...automationDiff.changed.map(code => `automation:${code}`),
960
- ]) {
961
- for (const code of dependenciesByResource.backend?.[owner] || []) {
962
- dependencyForms.add(String(code));
963
- }
964
- }
965
- for (const owner of workflowDiff.changed.map(code => `workflow:${code}`)) {
966
- for (const code of dependenciesByResource.workflow?.[owner] || []) {
967
- dependencyForms.add(String(code));
968
- }
969
- }
970
- for (const owner of selectedConfigurationOwners) {
971
- for (const code of
972
- dependenciesByResource.configuration?.[owner] || []) {
973
- dependencyForms.add(String(code));
974
- }
975
- }
976
- const hasResourceDependencyIndex =
977
- dependenciesByResource &&
978
- Object.keys(dependenciesByResource).length > 0;
979
- if (
980
- !hasResourceDependencyIndex &&
981
- (functionDiff.changed.length > 0 ||
982
- automationDiff.changed.length > 0 ||
983
- workflowDiff.changed.length > 0 ||
984
- selectedConfigurationOwners.length > 0)
985
- ) {
986
- for (const code of resources.formDependencies || []) {
987
- dependencyForms.add(String(code));
988
- }
989
- }
990
- for (const code of forms) dependencyForms.delete(code);
991
- if (formDiff.removed.length > 0) {
992
- resourceDeletes.forms = formDiff.removed;
993
- }
994
- if (functionDiff.removed.length > 0) {
995
- resourceDeletes.functions = functionDiff.removed;
996
- }
997
- if (automationDiff.removed.length > 0) {
998
- resourceDeletes.automations = automationDiff.removed;
999
- }
1000
- if (workflowDiff.removed.length > 0) {
1001
- resourceDeletes.workflows = workflowDiff.removed;
1002
- }
1003
- return {
1004
- forms,
1005
- formDependencies: uniqueStrings([...dependencyForms]),
1006
- pages: [],
1007
- functions: functionDiff.changed,
1008
- automations: automationDiff.changed,
1009
- workflows: workflowDiff.changed,
1010
- jsCodeNodes: [],
1011
- resources: false,
1012
- resourceSelectors,
1013
- resourceDeletes,
1014
- runtime: Boolean(
1015
- layerByKind(manifest, 'runtime') && layerChanged('runtime')
1016
- ),
1017
- other: [],
1018
- };
1019
- }
1020
-
1021
- function describeExecutionPlan(targets, runtimeMode, profileName) {
1022
- const steps = buildWorkspaceReleaseSteps(
1023
- targets,
1024
- runtimeMode,
1025
- profileName,
1026
- 'delivery-v2-plan'
1027
- );
1028
- return {
1029
- stepCount: steps.length,
1030
- steps: steps.map(step => ({
1031
- id: step.id,
1032
- command: step.command,
1033
- resumeMode: step.resumeMode,
1034
- stagedKind: step.stagedKind,
1035
- })),
1036
- };
1037
- }
1038
-
1039
- function diffResourceFingerprintBucket(options = {}) {
1040
- const currentCodes = uniqueStrings(options.currentCodes);
1041
- const previousCodes = uniqueStrings(options.previousCodes);
1042
- if (!options.changed) return { changed: [], removed: [] };
1043
- const current = isPlainObject(options.current) ? options.current : null;
1044
- const previous = isPlainObject(options.previous) ? options.previous : null;
1045
- const removed = previousCodes.filter(code => !currentCodes.includes(code));
1046
- if (
1047
- options.forceAll ||
1048
- options.sharedChanged ||
1049
- !current ||
1050
- !previous
1051
- ) {
1052
- return { changed: currentCodes, removed };
1053
- }
1054
- return {
1055
- changed: currentCodes.filter(
1056
- code => !previous[code] || previous[code] !== current[code]
1057
- ),
1058
- removed,
1059
- };
1060
- }
1061
-
1062
- function isPlainObject(value) {
1063
- return Boolean(
1064
- value && typeof value === 'object' && !Array.isArray(value)
1065
- );
1066
- }
1067
-
1068
- function fingerprintBucketChanged(current, previous) {
1069
- if (!isPlainObject(current) && !isPlainObject(previous)) return false;
1070
- return sha256Canonical(current || {}) !== sha256Canonical(previous || {});
1071
- }
1072
-
1073
- function decorateSteps(
1074
- steps,
1075
- target,
1076
- run,
1077
- packageManifest,
1078
- executionRoot
1079
- ) {
1080
- const result = [];
1081
- for (const original of steps) {
1082
- const step = {
1083
- ...original,
1084
- args: [...original.args],
1085
- };
1086
- if (target.targetName) {
1087
- step.args.push('--environment', target.targetName);
1088
- }
1089
- if (target.deploymentId) {
1090
- step.args.push('--deployment-id', target.deploymentId);
1091
- }
1092
- if (step.id === 'runtime-stage') {
1093
- const runtime = layerByKind(packageManifest, 'runtime');
1094
- step.args.push(
1095
- '--no-build',
1096
- '--dist',
1097
- path.join(executionRoot, 'dist'),
1098
- '--build-id',
1099
- deliveryV2RuntimeBuildId(runtime?.digest, run?.packageDigest),
1100
- '--upload-mode',
1101
- 'staged',
1102
- '--recover-stale-source-mismatch'
1103
- );
1104
- }
1105
- if (step.id === 'app-finalize') {
1106
- if (target.environmentId) {
1107
- step.args.push('--environment-id', target.environmentId);
1108
- }
1109
- step.args.push('--delivery-run-id', run.id);
1110
- const stagedIndex = step.args.indexOf('--staged-resources-json');
1111
- if (stagedIndex >= 0 && target.deploymentId) {
1112
- step.args[stagedIndex + 1] = path
1113
- .relative(
1114
- executionRoot,
1115
- path.join(
1116
- deliveryReleaseDirectory(
1117
- executionRoot,
1118
- run.control?.changeId,
1119
- target.deploymentId
1120
- ),
1121
- 'staged-resources.json'
1122
- )
1123
- )
1124
- .replace(/\\/g, '/');
1125
- }
1126
- }
1127
- step.command = commandFromArgs(step.args);
1128
- result.push(step);
1129
- }
1130
- return result;
1131
- }
1132
-
1133
- function deliveryV2RuntimeBuildId(runtimeDigest, packageDigest) {
1134
- const normalizedRuntimeDigest = String(runtimeDigest || '')
1135
- .trim()
1136
- .toLowerCase();
1137
- const normalizedPackageDigest = String(packageDigest || '')
1138
- .trim()
1139
- .toLowerCase();
1140
- if (!/^[a-f0-9]{64}$/.test(normalizedRuntimeDigest)) {
1141
- throw deliveryError(
1142
- 'DELIVERY_RUNTIME_LAYER_DIGEST_INVALID',
1143
- 'Runtime layer digest 必须是 64 位 SHA-256',
1144
- false
1145
- );
1146
- }
1147
- if (!/^[a-f0-9]{64}$/.test(normalizedPackageDigest)) {
1148
- throw deliveryError(
1149
- 'DELIVERY_PACKAGE_DIGEST_INVALID',
1150
- 'package digest 必须是 64 位 SHA-256',
1151
- false
1152
- );
1153
- }
1154
- return `pkg-${normalizedRuntimeDigest.slice(0, 20)}-${normalizedPackageDigest.slice(0, 12)}`;
1155
- }
1156
-
1157
- function packageSummary(manifest, previousManifest) {
1158
- return {
1159
- sourceFileCount: layerByKind(manifest, 'source')?.fileCount || 0,
1160
- artifactUploadCount: 0,
1161
- layers: (manifest.layers || []).map(layer => ({
1162
- kind: layer.kind,
1163
- digest: layer.digest,
1164
- sourceHash: layer.sourceHash,
1165
- reused:
1166
- layer.digest === layerByKind(previousManifest, layer.kind)?.digest,
1167
- built: false,
1168
- fileCount: layer.fileCount,
1169
- size: layer.size,
1170
- })),
1171
- };
1172
- }
1173
-
1174
- function compactStepResult(stepId, result, context = {}) {
1175
- if (!result || typeof result !== 'object') return { ok: true };
1176
- if (stepId === 'app-finalize') {
1177
- return {
1178
- appReleaseId:
1179
- result.activated?.id ||
1180
- result.verified?.id ||
1181
- result.prepared?.id ||
1182
- null,
1183
- };
1184
- }
1185
- const compact = {
1186
- ok: true,
1187
- id: result.id || result.release?.id || null,
1188
- };
1189
- const stagedResources = normalizeCheckpointStagedResources(
1190
- Array.isArray(result.stagedResources)
1191
- ? result.stagedResources
1192
- : result.stagedResource
1193
- ? [result.stagedResource]
1194
- : []
1195
- );
1196
- if (stagedResources.length > 0) {
1197
- compact.stagedResources = stagedResources;
1198
- }
1199
- const satisfiedSelectors = uniqueStrings(result.satisfiedSelectors);
1200
- if (satisfiedSelectors.length > 0) {
1201
- compact.satisfiedSelectors = satisfiedSelectors;
1202
- }
1203
- if (stepId === 'form-ensure') {
1204
- const replay = compactLocalReplayResult(result);
1205
- if (replay.forms) compact.formBindings = replay.forms;
1206
- }
1207
- if (stepId === 'backend-stage') {
1208
- const bindingContracts = readDeliverySupportFile(
1209
- context.executionRoot,
1210
- context.run,
1211
- context.target,
1212
- 'backend-binding-contracts.json'
1213
- );
1214
- if (bindingContracts) {
1215
- compact.backendBindingContracts = bindingContracts;
1216
- }
1217
- if (result.deliveryV2BackendManifestReplacement) {
1218
- compact.backendManifestReplacement =
1219
- result.deliveryV2BackendManifestReplacement;
1220
- }
1221
- }
1222
- return compact;
1223
- }
1224
-
1225
- function prepareAppFinalizeStep(step, context = {}) {
1226
- const stagedIndex = step.args.indexOf('--staged-resources-json');
1227
- if (stagedIndex < 0) {
1228
- return {
1229
- mode: 'frozen-capture',
1230
- stagedResourceCount: 0,
1231
- };
1232
- }
1233
-
1234
- const stagedStepIds = (context.steps || [])
1235
- .filter(candidate => Boolean(candidate.stagedKind))
1236
- .map(candidate => candidate.id);
1237
- const incompleteStagedCheckpoints = stagedStepIds.filter(stepId => {
1238
- const checkpointResult =
1239
- context.run?.result?.[checkpointName('done', stepId)];
1240
- if (!checkpointResult?.id) return false;
1241
- return (
1242
- normalizeCheckpointStagedResources(
1243
- checkpointResult.stagedResources || []
1244
- ).length === 0
1245
- );
1246
- });
1247
- if (incompleteStagedCheckpoints.length > 0) {
1248
- throw deliveryError(
1249
- 'DELIVERY_CHECKPOINT_STAGED_RESOURCES_MISSING',
1250
- `服务端检查点 ${incompleteStagedCheckpoints.join(
1251
- ', '
1252
- )} 已记录子 Release,但缺少可恢复 stagedResources`,
1253
- false
1254
- );
1255
- }
1256
-
1257
- const restored = restoreDeliveryCheckpointFiles(
1258
- context.executionRoot,
1259
- context.run,
1260
- context.target
1261
- );
1262
- if (restored.stagedResourceCount === 0) {
1263
- step.args.splice(stagedIndex, 2);
1264
- step.command = commandFromArgs(step.args);
1265
- return {
1266
- mode: 'frozen-capture',
1267
- stagedResourceCount: 0,
1268
- };
1269
- }
1270
-
1271
- const stagedResourcesPath = path.resolve(
1272
- context.executionRoot,
1273
- step.args[stagedIndex + 1]
1274
- );
1275
- if (!fs.existsSync(stagedResourcesPath)) {
1276
- throw deliveryError(
1277
- 'DELIVERY_CHECKPOINT_FILE_MISSING',
1278
- '服务端 stagedResources 检查点已恢复,但 app-finalize 暂存资源文件缺失',
1279
- false
1280
- );
1281
- }
1282
- step.command = commandFromArgs(step.args);
1283
- return {
1284
- mode: 'staged-children',
1285
- stagedResourceCount: restored.stagedResourceCount,
1286
- };
1287
- }
1288
-
1289
- function restoreDeliveryCheckpointFiles(executionRoot, run, target) {
1290
- const changeId = String(run?.control?.changeId || '').trim();
1291
- if (!changeId) return { stagedResourceCount: 0, restored: false };
1292
- const checkpointResults = Object.values(run?.result || {});
1293
- const staged = new Map();
1294
- const satisfiedSelectors = [];
1295
- let backendBindingContracts = null;
1296
- for (const result of checkpointResults) {
1297
- for (const resource of normalizeCheckpointStagedResources(
1298
- result?.stagedResources || []
1299
- )) {
1300
- staged.set(checkpointStagedResourceKey(resource), resource);
1301
- }
1302
- satisfiedSelectors.push(...uniqueStrings(result?.satisfiedSelectors));
1303
- if (result?.backendBindingContracts) {
1304
- backendBindingContracts = cloneJson(result.backendBindingContracts);
1305
- }
1306
- }
1307
- if (staged.size === 0 && !backendBindingContracts) {
1308
- return { stagedResourceCount: 0, restored: false };
1309
- }
1310
- const releaseDir = deliveryReleaseDirectory(
1311
- executionRoot,
1312
- changeId,
1313
- target?.deploymentId
1314
- );
1315
- fs.mkdirSync(releaseDir, { recursive: true });
1316
- const resources = Array.from(staged.values()).sort((left, right) =>
1317
- checkpointStagedResourceKey(left).localeCompare(
1318
- checkpointStagedResourceKey(right)
1319
- )
1320
- );
1321
- if (resources.length > 0) {
1322
- writeJsonAtomic(
1323
- path.join(releaseDir, 'staged-resources.json'),
1324
- resources
1325
- );
1326
- writeJsonAtomic(
1327
- path.join(releaseDir, 'staged-resources.context.json'),
1328
- {
1329
- contractVersion: 'staged_resources_context_v1',
1330
- appType: target.appType,
1331
- profile: target.profileName,
1332
- changeId,
1333
- deploymentId: target.deploymentId || null,
1334
- baselineId: run.control?.baselineId || null,
1335
- clientSessionId: run.control?.clientSessionId || null,
1336
- initializedAt: new Date().toISOString(),
1337
- restoredFromDeliveryRunId: run.id,
1338
- ...(uniqueStrings(satisfiedSelectors).length > 0
1339
- ? { satisfiedSelectors: uniqueStrings(satisfiedSelectors) }
1340
- : {}),
1341
- }
1342
- );
1343
- }
1344
- if (backendBindingContracts) {
1345
- writeJsonAtomic(
1346
- path.join(releaseDir, 'backend-binding-contracts.json'),
1347
- backendBindingContracts
1348
- );
1349
- }
1350
- return {
1351
- stagedResourceCount: resources.length,
1352
- restored: true,
1353
- backendBindingContracts: Boolean(backendBindingContracts),
1354
- };
1355
- }
1356
-
1357
- function readDeliverySupportFile(
1358
- executionRoot,
1359
- run,
1360
- target,
1361
- fileName
1362
- ) {
1363
- const changeId = String(run?.control?.changeId || '').trim();
1364
- if (!changeId || !executionRoot) return null;
1365
- const file = path.join(
1366
- deliveryReleaseDirectory(
1367
- executionRoot,
1368
- changeId,
1369
- target?.deploymentId
1370
- ),
1371
- fileName
1372
- );
1373
- if (!fs.existsSync(file)) return null;
1374
- try {
1375
- return cloneJson(JSON.parse(fs.readFileSync(file, 'utf8')));
1376
- } catch {
1377
- throw deliveryError(
1378
- 'DELIVERY_CHECKPOINT_FILE_INVALID',
1379
- `${fileName} 不是合法 JSON,不能创建可恢复检查点`,
1380
- false
1381
- );
1382
- }
1383
- }
1384
-
1385
- function deliveryReleaseDirectory(executionRoot, changeId, deploymentId) {
1386
- const normalizedChangeId = String(changeId || '').trim();
1387
- if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(normalizedChangeId)) {
1388
- throw deliveryError(
1389
- 'DELIVERY_CONTROL_INVALID',
1390
- 'ReleaseRun changeId 不能用于恢复暂存资源',
1391
- false
1392
- );
1393
- }
1394
- const base = path.join(
1395
- path.resolve(executionRoot),
1396
- '.openxiangda',
1397
- 'releases',
1398
- normalizedChangeId
1399
- );
1400
- return deploymentId ? path.join(base, String(deploymentId)) : base;
1401
- }
1402
-
1403
- function normalizeCheckpointStagedResources(values) {
1404
- if (!Array.isArray(values)) return [];
1405
- const supportedKinds = new Set([
1406
- 'RuntimeRelease',
1407
- 'PageRelease',
1408
- 'BackendRelease',
1409
- 'WorkflowRelease',
1410
- 'FormRelease',
1411
- ]);
1412
- return values
1413
- .filter(value => value && typeof value === 'object' && !Array.isArray(value))
1414
- .filter(value => supportedKinds.has(String(value.kind || '').trim()))
1415
- .filter(value => {
1416
- const releaseId = String(
1417
- value.identity?.releaseId || value.releaseId || ''
1418
- ).trim();
1419
- const hash = String(value.hash || value.resourceHash || '')
1420
- .trim()
1421
- .toLowerCase();
1422
- const formUuid = String(
1423
- value.identity?.formUuid || value.formUuid || ''
1424
- ).trim();
1425
- return (
1426
- Boolean(releaseId) &&
1427
- /^[a-f0-9]{64}$/.test(hash) &&
1428
- (value.kind !== 'FormRelease' || Boolean(formUuid))
1429
- );
1430
- })
1431
- .map(cloneJson);
1432
- }
1433
-
1434
- function checkpointStagedResourceKey(resource) {
1435
- if (resource.kind === 'FormRelease') {
1436
- return `FormRelease:${
1437
- resource.identity?.formUuid || resource.formUuid
1438
- }`;
1439
- }
1440
- return String(resource.kind);
1441
- }
1442
-
1443
- function uniqueStrings(values) {
1444
- return Array.from(
1445
- new Set(
1446
- (Array.isArray(values) ? values : [])
1447
- .map(value => String(value || '').trim())
1448
- .filter(Boolean)
1449
- )
1450
- ).sort();
1451
- }
1452
-
1453
- function writeJsonAtomic(file, value) {
1454
- const temporary = `${file}.${process.pid}.tmp`;
1455
- fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, {
1456
- mode: 0o600,
1457
- });
1458
- fs.renameSync(temporary, file);
1459
- }
1460
-
1461
- function cloneJson(value) {
1462
- return JSON.parse(JSON.stringify(value));
1463
- }
1464
-
1465
- function structuredFailure(error, runId, stage, component) {
1466
- const code =
1467
- error?.code ||
1468
- error?.payload?.errorCode ||
1469
- error?.payload?.data?.code ||
1470
- 'DELIVERY_EXECUTION_FAILED';
1471
- return {
1472
- runId: runId || null,
1473
- stage: stage || 'unknown',
1474
- component: component || 'unknown',
1475
- code: String(code),
1476
- message: String(error?.message || 'Delivery V2 执行失败'),
1477
- retryable: error?.retryable !== false,
1478
- progressPreserved: true,
1479
- };
1480
- }
1481
-
1482
- function compactLocalReplayResult(result) {
1483
- const forms = Array.isArray(result?.forms)
1484
- ? result.forms
1485
- .map(item => ({
1486
- code: String(item?.code || '').trim(),
1487
- formUuid: String(item?.formUuid || '').trim(),
1488
- action: String(item?.action || '').trim(),
1489
- }))
1490
- .filter(item => item.code && item.formUuid)
1491
- .sort((left, right) => left.code.localeCompare(right.code))
1492
- : [];
1493
- return {
1494
- ok: true,
1495
- ...(forms.length > 0 ? { forms } : {}),
1496
- };
1497
- }
1498
-
1499
- function runNotExecutableError(run, target) {
1500
- const environment =
1501
- target?.targetName || target?.environmentKind || '当前环境';
1502
- const retryCommand = `openxiangda retry ${run?.id} --environment ${environment}`;
1503
- const code =
1504
- run?.status === 'cancelled'
1505
- ? 'DELIVERY_RUN_CANCELLED'
1506
- : 'DELIVERY_RUN_ALREADY_EXECUTING';
1507
- const error = deliveryError(
1508
- code,
1509
- `ReleaseRun ${run?.id || 'unknown'} 当前状态为 ${run?.status || 'unknown'};如确认原执行器已停止,请运行 ${retryCommand}`,
1510
- false
1511
- );
1512
- error.runId = run?.id || null;
1513
- error.runStatus = run?.status || null;
1514
- error.nextAction = retryCommand;
1515
- return error;
1516
- }
1517
-
1518
- function layerByKind(manifest, kind) {
1519
- return (manifest?.layers || []).find(layer => layer.kind === kind) || null;
1520
- }
1521
-
1522
- function runPath(target, suffix = '') {
1523
- return `${appApiPath(target, '/delivery/runs')}${suffix}`;
1524
- }
1525
-
1526
- function artifactPath(target, digest) {
1527
- return appApiPath(
1528
- target,
1529
- `/delivery/artifacts/${encodeURIComponent(digest)}`
1530
- );
1531
- }
1532
-
1533
- function appApiPath(target, suffix) {
1534
- return `/openxiangda-api/v1/apps/${encodeURIComponent(
1535
- target.appType
1536
- )}${suffix}`;
1537
- }
1538
-
1539
- function checkpointName(prefix, value) {
1540
- return `${prefix}-${String(value || 'step')
1541
- .replace(/[^a-z0-9-]+/gi, '-')
1542
- .toLowerCase()}`.slice(0, 64);
1543
- }
1544
-
1545
- function lifecycleStage(name, attempt) {
1546
- return `${name}-attempt-${Math.max(Number(attempt) || 1, 1)}`;
1547
- }
1548
-
1549
- function sameEnvironment(run, target) {
1550
- return String(run.environmentId || '') === String(target.environmentId || '');
1551
- }
1552
-
1553
- function defaultIdempotencyKey(kind, target, digest) {
1554
- return [
1555
- 'delivery-v2',
1556
- kind,
1557
- target.appType,
1558
- target.environmentId || 'direct',
1559
- digest,
1560
- ].join(':');
1561
- }
1562
-
1563
- function normalizeLegacyPackageTargetsForExecution(targets, executionRoot) {
1564
- const selectors = targets?.resourceSelectors?.dataViews;
1565
- if (!Array.isArray(selectors) || selectors.length === 0) return targets;
1566
- const dataViewDir = path.join(
1567
- path.resolve(executionRoot),
1568
- 'src',
1569
- 'resources',
1570
- 'data-views'
1571
- );
1572
- if (!fs.existsSync(dataViewDir)) return targets;
1573
-
1574
- const actualCodes = new Set();
1575
- const legacyNestedCodes = new Set();
1576
- const visit = directory => {
1577
- for (const entry of fs
1578
- .readdirSync(directory, { withFileTypes: true })
1579
- .sort((left, right) => left.name.localeCompare(right.name))) {
1580
- const absolute = path.join(directory, entry.name);
1581
- if (entry.isDirectory()) {
1582
- visit(absolute);
1583
- continue;
1584
- }
1585
- if (!entry.isFile() || !entry.name.endsWith('.json')) continue;
1586
- let value;
1587
- try {
1588
- value = JSON.parse(fs.readFileSync(absolute, 'utf8'));
1589
- } catch {
1590
- // The resource command remains responsible for reporting malformed
1591
- // manifests. This compatibility normalization only narrows selectors.
1592
- continue;
1593
- }
1594
- const topLevelCodes = collectConfigurationManifestCodes(
1595
- 'data-view',
1596
- value
1597
- );
1598
- for (const code of topLevelCodes) {
1599
- actualCodes.add(code);
1600
- }
1601
- const topLevelSet = new Set(topLevelCodes);
1602
- for (const code of collectManifestCodes(value)) {
1603
- if (!topLevelSet.has(code)) legacyNestedCodes.add(code);
1604
- }
1605
- }
1606
- };
1607
- visit(dataViewDir);
1608
- if (actualCodes.size === 0 || legacyNestedCodes.size === 0) return targets;
1609
-
1610
- const filtered = selectors.filter(
1611
- code => !legacyNestedCodes.has(String(code)) || actualCodes.has(String(code))
1612
- );
1613
- if (filtered.length === selectors.length) return targets;
1614
- return {
1615
- ...targets,
1616
- resourceSelectors: {
1617
- ...(targets.resourceSelectors || {}),
1618
- dataViews: filtered,
1619
- },
1620
- };
1621
- }
1622
-
1623
- function normalizeDigest(value) {
1624
- const digest = String(value || '')
1625
- .trim()
1626
- .toLowerCase();
1627
- if (!/^[a-f0-9]{64}$/.test(digest)) {
1628
- throw deliveryError(
1629
- 'DELIVERY_PACKAGE_DIGEST_INVALID',
1630
- 'package digest 必须是 64 位 SHA-256',
1631
- false
1632
- );
1633
- }
1634
- return digest;
1635
- }
1636
-
1637
- function safeRelativePath(value) {
1638
- const normalized = String(value || '').replace(/\\/g, '/');
1639
- if (
1640
- !normalized ||
1641
- normalized.startsWith('/') ||
1642
- normalized.includes('../') ||
1643
- normalized === '..'
1644
- ) {
1645
- throw deliveryError(
1646
- 'DELIVERY_ARTIFACT_PATH_INVALID',
1647
- `制品路径无效: ${value}`,
1648
- false
1649
- );
1650
- }
1651
- return normalized;
1652
- }
1653
-
1654
- function isNotFound(error) {
1655
- return (
1656
- Number(error?.status || error?.statusCode) === 404 ||
1657
- /\bHTTP 404\b|NOT_FOUND/i.test(String(error?.message || ''))
1658
- );
1659
- }
1660
-
1661
- function cleanObject(value) {
1662
- return Object.fromEntries(
1663
- Object.entries(value || {}).filter(([, item]) => item !== undefined)
1664
- );
1665
- }
1666
-
1667
- function deliveryError(code, message, retryable) {
1668
- const error = new Error(`${code}: ${message}`);
1669
- error.code = code;
1670
- error.retryable = retryable;
1671
- return error;
1672
- }
1673
-
1674
- function assertDependencies(value) {
1675
- const required = [
1676
- 'clearDeliveryContext',
1677
- 'downloadWithAuth',
1678
- 'installDeliveryContext',
1679
- 'requestFormWithAuth',
1680
- 'requestWithAuth',
1681
- 'runOpenXiangdaInProcess',
1682
- ];
1683
- for (const key of required) {
1684
- if (typeof value?.[key] !== 'function') {
1685
- throw new Error(`Delivery V2 executor dependency 缺失: ${key}`);
1686
- }
1687
- }
1688
- return value;
1689
- }
1690
-
1691
- module.exports = {
1692
- CONFIG_TARGET_BY_RESOURCE_TYPE,
1693
- compactStepResult,
1694
- createDeliveryV2Executor,
1695
- decorateSteps,
1696
- deliveryV2RuntimeBuildId,
1697
- normalizeLegacyPackageTargetsForExecution,
1698
- packageWorkspaceRoot,
1699
- prepareAppFinalizeStep,
1700
- releaseTargets,
1701
- restoreDeliveryCheckpointFiles,
1702
- structuredFailure,
1703
- };