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,1359 +0,0 @@
1
- const { spawnSync } = require('child_process');
2
- const {
3
- legacyRemoteIdentity,
4
- remoteRepositoryHashes,
5
- } = require('./git-remote-identity');
6
- const crypto = require('crypto');
7
- const fs = require('fs');
8
- const os = require('os');
9
- const path = require('path');
10
-
11
- const { saveProjectState } = require('./config');
12
- const { runWorkspaceJsCodeBuildBatch } = require('./js-code-build');
13
- const { version: OPENXIANGDA_VERSION } = require('../package.json');
14
-
15
- const SOURCE_KIND_BY_RESOURCE_KIND = Object.freeze({
16
- Function: 'functions',
17
- Automation: 'automations',
18
- });
19
-
20
- function getStoredChangeBaseline(target, options = {}) {
21
- const baseline = target?.bound?.promotion?.changeBaseline;
22
- if (!baseline || typeof baseline !== 'object' || Array.isArray(baseline)) return null;
23
- assertStoredChangeBaseline(target, baseline, options);
24
- return baseline;
25
- }
26
-
27
- function saveChangeBaseline(target, input, options = {}) {
28
- const identity = assertTargetIdentity(target);
29
- if (!input || typeof input !== 'object' || Array.isArray(input)) {
30
- throw changeBaselineError(
31
- 'CHANGE_BASELINE_INVALID',
32
- 'change baseline 必须是对象'
33
- );
34
- }
35
-
36
- const existing = target.bound?.promotion?.changeBaseline;
37
- if (existing && typeof existing === 'object' && !Array.isArray(existing)) {
38
- assertStoredChangeBaseline(target, existing, options);
39
- }
40
- assertInputIdentity(input, identity);
41
-
42
- const env = options.env || process.env;
43
- const currentThreadId = currentCodexThreadId(env);
44
- const inputOwnerThreadId = getChangeBaselineOwnerThreadId(input);
45
- if (inputOwnerThreadId && inputOwnerThreadId !== currentThreadId) {
46
- throw ownershipError(inputOwnerThreadId, currentThreadId);
47
- }
48
-
49
- const merged = {
50
- ...(existing ? cloneJson(existing) : {}),
51
- ...cloneJson(input),
52
- };
53
- const workspace = {
54
- ...(existing?.workspace && typeof existing.workspace === 'object'
55
- ? cloneJson(existing.workspace)
56
- : {}),
57
- ...(input.workspace && typeof input.workspace === 'object'
58
- ? cloneJson(input.workspace)
59
- : {}),
60
- };
61
- const ownerThreadId = currentThreadId || inputOwnerThreadId;
62
- if (ownerThreadId) workspace.threadId = ownerThreadId;
63
- else delete workspace.threadId;
64
-
65
- const baseline = {
66
- ...merged,
67
- appType: identity.appType,
68
- profile: identity.profile,
69
- resourceHeads: clonePreservedField(input, existing, 'resourceHeads', {}),
70
- sourceBase: clonePreservedField(input, existing, 'sourceBase', null),
71
- clientSessionId: normalizeOptionalString(
72
- preservedField(input, existing, 'clientSessionId', null)
73
- ),
74
- localBaseArtifactHashes: clonePreservedField(
75
- input,
76
- existing,
77
- 'localBaseArtifactHashes',
78
- {}
79
- ),
80
- workspace,
81
- updatedAt: normalizeNow(options.now),
82
- };
83
-
84
- target.bound.promotion = {
85
- ...(target.bound.promotion || {}),
86
- changeBaseline: baseline,
87
- };
88
- persistTargetState(target, options);
89
- return baseline;
90
- }
91
-
92
- function clearChangeBaseline(target, baselineIdOrOptions, maybeOptions = {}) {
93
- const hasOptionsAsSecondArgument =
94
- baselineIdOrOptions &&
95
- typeof baselineIdOrOptions === 'object' &&
96
- !Array.isArray(baselineIdOrOptions);
97
- const options = hasOptionsAsSecondArgument
98
- ? baselineIdOrOptions
99
- : maybeOptions;
100
- const baselineId = hasOptionsAsSecondArgument
101
- ? null
102
- : normalizeOptionalString(baselineIdOrOptions);
103
-
104
- const baseline = target?.bound?.promotion?.changeBaseline;
105
- if (!baseline || typeof baseline !== 'object' || Array.isArray(baseline)) return false;
106
- assertStoredChangeBaseline(target, baseline, options);
107
-
108
- const storedId = normalizeOptionalString(baseline.baselineId || baseline.id);
109
- if (baselineId && storedId !== baselineId) return false;
110
-
111
- target.bound.promotion = { ...(target.bound.promotion || {}) };
112
- delete target.bound.promotion.changeBaseline;
113
- if (Object.keys(target.bound.promotion).length === 0) {
114
- delete target.bound.promotion;
115
- }
116
- persistTargetState(target, options);
117
- return true;
118
- }
119
-
120
- function clearChangeBaselineForReconciliation(target, expected = {}, options = {}) {
121
- const baseline = target?.bound?.promotion?.changeBaseline;
122
- if (!baseline || typeof baseline !== 'object' || Array.isArray(baseline)) return false;
123
- assertStoredChangeBaseline(target, baseline, {
124
- ...options,
125
- access: 'reconciliation-read',
126
- });
127
-
128
- const expectedBaselineId = normalizeOptionalString(expected.baselineId || expected.id);
129
- const expectedChangeId = normalizeOptionalString(expected.changeId);
130
- const expectedClientSessionId = normalizeOptionalString(expected.clientSessionId);
131
- const expectedSourceCommit = normalizeOptionalString(
132
- expected.releaseSourceRevision?.baseCommit || expected.sourceCommit
133
- );
134
- const hasExpectedLeaseId = Object.prototype.hasOwnProperty.call(
135
- expected,
136
- 'leaseId'
137
- );
138
- const expectedLeaseId = normalizeOptionalString(expected.leaseId);
139
- if (
140
- !expectedBaselineId ||
141
- !expectedChangeId ||
142
- !expectedClientSessionId ||
143
- !expectedSourceCommit ||
144
- !hasExpectedLeaseId
145
- ) {
146
- throw changeBaselineError(
147
- 'CHANGE_BASELINE_RECONCILIATION_INVALID',
148
- 'reconciliation 清理必须提供精确 baselineId/changeId/clientSessionId/sourceCommit/leaseId(无 lease 时显式传 null)'
149
- );
150
- }
151
-
152
- if (
153
- normalizeOptionalString(baseline.baselineId || baseline.id) !== expectedBaselineId ||
154
- normalizeOptionalString(baseline.changeId) !== expectedChangeId ||
155
- normalizeOptionalString(baseline.clientSessionId) !== expectedClientSessionId ||
156
- normalizeOptionalString(baseline.releaseSourceRevision?.baseCommit) !== expectedSourceCommit
157
- ) {
158
- return false;
159
- }
160
-
161
- const lease = target?.bound?.promotion?.publishLease;
162
- if (expectedLeaseId) {
163
- if (
164
- !lease ||
165
- normalizeOptionalString(lease.leaseId) !== expectedLeaseId ||
166
- normalizeOptionalString(lease.changeId) !== expectedChangeId ||
167
- normalizeOptionalString(lease.clientSessionId) !== expectedClientSessionId ||
168
- normalizeOptionalString(lease.workspace?.commit) !== expectedSourceCommit
169
- ) {
170
- return false;
171
- }
172
- } else if (lease) {
173
- return false;
174
- }
175
-
176
- // Validate both pieces of release evidence before mutating either one, then
177
- // persist once so a failed baseline CAS can never leave a lease-only partial
178
- // cleanup behind.
179
- target.bound.promotion = { ...(target.bound.promotion || {}) };
180
- delete target.bound.promotion.publishLease;
181
- delete target.bound.promotion.changeBaseline;
182
- if (Object.keys(target.bound.promotion).length === 0) {
183
- delete target.bound.promotion;
184
- }
185
- persistTargetState(target, options);
186
- return true;
187
- }
188
-
189
- function isChangeBaselineOwnedByCurrentSession(baseline, env = process.env) {
190
- const ownerThreadId = getChangeBaselineOwnerThreadId(baseline);
191
- if (!ownerThreadId) return true;
192
- const threadId = currentCodexThreadId(env);
193
- return Boolean(threadId) && ownerThreadId === threadId;
194
- }
195
-
196
- function readGitSourceBase(cwd = process.cwd(), baseRef = 'HEAD') {
197
- const repository = resolveGitRepository(cwd);
198
- const normalizedBaseRef = normalizeBaseRef(baseRef);
199
- const baseCommit = resolveExactCommit(repository.root, normalizedBaseRef);
200
- const treeHash = runGit(repository.root, [
201
- 'rev-parse',
202
- '--verify',
203
- `${baseCommit}^{tree}`,
204
- ]).trim();
205
- assertGitObjectId(treeHash, 'treeHash');
206
-
207
- let remote = tryRunGit(repository.root, [
208
- 'config',
209
- '--get',
210
- 'remote.origin.url',
211
- ]).trim();
212
- if (!remote) {
213
- const remotes = tryRunGit(repository.root, ['remote'])
214
- .split(/\r?\n/)
215
- .map(item => item.trim())
216
- .filter(Boolean);
217
- if (remotes.length === 1) {
218
- remote = tryRunGit(repository.root, [
219
- 'config',
220
- '--get',
221
- `remote.${remotes[0]}.url`,
222
- ]).trim();
223
- }
224
- }
225
- const commonGitDirValue = tryRunGit(repository.root, [
226
- 'rev-parse',
227
- '--path-format=absolute',
228
- '--git-common-dir',
229
- ]).trim() || tryRunGit(repository.root, [
230
- 'rev-parse',
231
- '--git-common-dir',
232
- ]).trim();
233
- const commonGitDir = commonGitDirValue
234
- ? fs.realpathSync(
235
- path.isAbsolute(commonGitDirValue)
236
- ? commonGitDirValue
237
- : path.resolve(repository.root, commonGitDirValue)
238
- )
239
- : repository.root;
240
- const repositoryIds = remote
241
- ? remoteRepositoryHashes(remote)
242
- : [];
243
- const identitySeed = remote
244
- ? `remote:${legacyRemoteIdentity(remote)}`
245
- : `local:${commonGitDir}`;
246
- const repositoryId = `sha256:${sha256Buffer(Buffer.from(identitySeed, 'utf8'))}`;
247
-
248
- return {
249
- repo: repositoryId,
250
- repositoryId,
251
- repoAliases: Array.from(new Set([repositoryId, ...repositoryIds])),
252
- baseCommit,
253
- treeHash,
254
- };
255
- }
256
-
257
- function buildGitBaseSourceArtifacts({
258
- cwd = process.cwd(),
259
- baseCommit,
260
- targets,
261
- env = process.env,
262
- packageManager = 'pnpm',
263
- } = {}) {
264
- const normalizedTargets = normalizeArtifactTargets(targets);
265
- const cacheFile =
266
- env?.FAKE_BATCH_FAIL || env?.OPENXIANGDA_DISABLE_ARTIFACT_CACHE === '1'
267
- ? null
268
- : resolveGitArtifactCacheFile({
269
- cwd,
270
- baseCommit,
271
- targets: normalizedTargets,
272
- packageManager,
273
- });
274
- const cached = cacheFile
275
- ? readGitArtifactCache(cacheFile, baseCommit, normalizedTargets)
276
- : null;
277
- if (cached) return { ...cached, cacheHit: true };
278
- const built = withGitBaseWorkspace({ cwd, baseCommit, env }, context => {
279
- const {
280
- buildRoot,
281
- buildEnv,
282
- resolvedCommit,
283
- } = context;
284
- prepareExactArtifactBuild(buildRoot, normalizedTargets);
285
- const specs = normalizedTargets
286
- .map(target => `${target.sourceKind}:${target.code}`)
287
- .join(',');
288
- const batchProcess = runWorkspaceJsCodeBuildBatch(
289
- buildRoot,
290
- normalizedTargets.map(target => ({
291
- sourceKind: target.sourceKind,
292
- scriptCode: target.code,
293
- })),
294
- {
295
- packageManager,
296
- spawnOptions: {
297
- env: buildEnv,
298
- maxBuffer: 16 * 1024 * 1024,
299
- },
300
- }
301
- );
302
- const batch = normalizeBuildProcessResult(batchProcess, [
303
- packageManager,
304
- 'build-js-code',
305
- '--scripts',
306
- specs,
307
- ]);
308
-
309
- let buildMode =
310
- batchProcess.openxiangdaBuildMode === 'canonical-scoped'
311
- ? 'canonical-scoped'
312
- : 'batch';
313
- if (!batch.ok) {
314
- if (batchProcess.openxiangdaBuildMode === 'canonical-scoped') {
315
- throw buildFailureError(normalizedTargets[0], batch);
316
- }
317
- buildMode = 'legacy-fallback';
318
- for (const target of normalizedTargets) {
319
- const legacy = runBuildCommand(
320
- packageManager,
321
- [
322
- 'build-js-code',
323
- '--script',
324
- target.code,
325
- '--source',
326
- target.sourceKind,
327
- ],
328
- buildRoot,
329
- buildEnv
330
- );
331
- if (!legacy.ok) {
332
- throw buildFailureError(target, batch, legacy);
333
- }
334
- }
335
- }
336
-
337
- const artifacts = {};
338
- const localBaseArtifactHashes = {};
339
- for (const target of normalizedTargets) {
340
- const relativePath = path.posix.join(
341
- 'dist',
342
- target.sourceKind,
343
- target.code,
344
- 'index.cjs'
345
- );
346
- const artifactPath = path.resolve(buildRoot, ...relativePath.split('/'));
347
- assertArtifactFileSafe(buildRoot, artifactPath, target);
348
- const artifactHash = sha256File(artifactPath);
349
- const sourceHash = readBuiltSourceHash(
350
- buildRoot,
351
- target.sourceKind,
352
- target.code
353
- );
354
- const key = `${target.kind}:${target.code}`;
355
- artifacts[key] = {
356
- kind: target.kind,
357
- code: target.code,
358
- sourceKind: target.sourceKind,
359
- relativePath,
360
- artifactHash,
361
- sha256: artifactHash,
362
- ...(sourceHash ? { sourceHash } : {}),
363
- };
364
- localBaseArtifactHashes[key] = artifactHash;
365
- }
366
-
367
- return {
368
- baseCommit: resolvedCommit,
369
- buildMode,
370
- artifacts,
371
- localBaseArtifactHashes,
372
- };
373
- });
374
- if (cacheFile) writeGitArtifactCache(cacheFile, built);
375
- return { ...built, cacheHit: false };
376
- }
377
-
378
- function resolveGitArtifactCacheFile({
379
- cwd,
380
- baseCommit,
381
- targets,
382
- packageManager,
383
- }) {
384
- const commit = String(baseCommit || '').trim().toLowerCase();
385
- if (!/^[0-9a-f]{40,64}$/.test(commit)) return null;
386
- const repository = resolveGitRepository(cwd);
387
- const commonDirValue =
388
- tryRunGit(repository.root, [
389
- 'rev-parse',
390
- '--path-format=absolute',
391
- '--git-common-dir',
392
- ]).trim() ||
393
- tryRunGit(repository.root, ['rev-parse', '--git-common-dir']).trim();
394
- if (!commonDirValue) return null;
395
- const commonDir = path.resolve(repository.root, commonDirValue);
396
- const key = canonicalJsonSha256({
397
- schemaVersion: 'git_base_artifacts_v2',
398
- openxiangdaVersion: OPENXIANGDA_VERSION,
399
- baseCommit: commit,
400
- packageManager,
401
- targets,
402
- });
403
- return path.join(
404
- commonDir,
405
- 'openxiangda-cache',
406
- 'git-base-artifacts-v2',
407
- `${key}.json`
408
- );
409
- }
410
-
411
- function readGitArtifactCache(file, baseCommit, targets) {
412
- if (!fs.existsSync(file)) return null;
413
- let value;
414
- try {
415
- value = JSON.parse(fs.readFileSync(file, 'utf8'));
416
- } catch {
417
- return null;
418
- }
419
- if (
420
- value?.schemaVersion !== 'git_base_artifacts_v2' ||
421
- value?.openxiangdaVersion !== OPENXIANGDA_VERSION ||
422
- value?.result?.baseCommit !== String(baseCommit).toLowerCase()
423
- ) {
424
- return null;
425
- }
426
- const expectedKeys = targets
427
- .map(target => `${target.kind}:${target.code}`)
428
- .sort();
429
- const artifactKeys = Object.keys(value.result.artifacts || {}).sort();
430
- if (
431
- expectedKeys.length !== artifactKeys.length ||
432
- expectedKeys.some((key, index) => key !== artifactKeys[index])
433
- ) {
434
- return null;
435
- }
436
- if (
437
- artifactKeys.some(
438
- key =>
439
- !/^[a-f0-9]{64}$/.test(
440
- String(value.result.artifacts[key]?.artifactHash || '')
441
- )
442
- )
443
- ) {
444
- return null;
445
- }
446
- return cloneJson(value.result);
447
- }
448
-
449
- function writeGitArtifactCache(file, result) {
450
- fs.mkdirSync(path.dirname(file), { recursive: true });
451
- const tempFile = `${file}.${process.pid}.${Date.now()}.tmp`;
452
- fs.writeFileSync(
453
- tempFile,
454
- `${JSON.stringify(
455
- {
456
- schemaVersion: 'git_base_artifacts_v2',
457
- openxiangdaVersion: OPENXIANGDA_VERSION,
458
- createdAt: new Date().toISOString(),
459
- result,
460
- },
461
- null,
462
- 2
463
- )}\n`,
464
- { mode: 0o600 }
465
- );
466
- fs.renameSync(tempFile, file);
467
- }
468
-
469
- function readBuiltSourceHash(buildRoot, sourceKind, code) {
470
- const key = `${sourceKind}/${code}`;
471
- for (const filename of [
472
- 'build-cache.json',
473
- 'build-cache.cli-v4.json',
474
- 'build-cache.cli-v3.json',
475
- ]) {
476
- try {
477
- const cache = JSON.parse(
478
- fs.readFileSync(
479
- path.join(buildRoot, '.openxiangda', filename),
480
- 'utf8'
481
- )
482
- );
483
- const sourceHash = String(
484
- cache?.targets?.[key]?.sourceHash || ''
485
- ).toLowerCase();
486
- if (/^[a-f0-9]{64}$/.test(sourceHash)) return sourceHash;
487
- } catch {
488
- // Custom builders are allowed to omit the optional lineage cache.
489
- }
490
- }
491
- return null;
492
- }
493
-
494
- function withGitBaseWorkspace(
495
- {
496
- cwd = process.cwd(),
497
- baseCommit,
498
- env = process.env,
499
- copyProjectState = false,
500
- } = {},
501
- callback
502
- ) {
503
- if (typeof callback !== 'function') {
504
- throw changeBaselineError(
505
- 'CHANGE_BASELINE_CALLBACK_REQUIRED',
506
- 'Git 基线工作区必须提供同步 callback'
507
- );
508
- }
509
- const workspace = createGitBaseWorkspace({
510
- cwd,
511
- baseCommit,
512
- env,
513
- copyProjectState,
514
- });
515
- let callbackError = null;
516
- try {
517
- return callback(workspace);
518
- } catch (error) {
519
- callbackError = error;
520
- throw error;
521
- } finally {
522
- try {
523
- assertCopiedProjectStateUnchanged(workspace);
524
- } catch (stateError) {
525
- if (!callbackError) throw stateError;
526
- } finally {
527
- fs.rmSync(workspace.tempRoot, { recursive: true, force: true });
528
- }
529
- }
530
- }
531
-
532
- function createGitBaseWorkspace({
533
- cwd,
534
- baseCommit,
535
- env,
536
- copyProjectState,
537
- }) {
538
- const repository = resolveGitRepository(cwd);
539
- const immutableCommit = normalizeImmutableCommit(baseCommit);
540
- const resolvedCommit = resolveExactCommit(repository.root, immutableCommit);
541
- if (resolvedCommit.toLowerCase() !== immutableCommit.toLowerCase()) {
542
- throw changeBaselineError(
543
- 'CHANGE_BASELINE_COMMIT_NOT_EXACT',
544
- `baseCommit 必须是完整且不可变的 commit id: ${baseCommit}`
545
- );
546
- }
547
-
548
- const currentWorkspaceRoot = fs.realpathSync(path.resolve(cwd));
549
- const workspaceRelative = path.relative(repository.root, currentWorkspaceRoot);
550
- if (isOutsidePath(workspaceRelative)) {
551
- throw changeBaselineError(
552
- 'CHANGE_BASELINE_WORKSPACE_OUTSIDE_REPOSITORY',
553
- 'cwd 必须位于 Git 仓库内'
554
- );
555
- }
556
-
557
- const currentNodeModules = path.join(currentWorkspaceRoot, 'node_modules');
558
- let currentNodeModulesRealPath;
559
- try {
560
- currentNodeModulesRealPath = fs.realpathSync(currentNodeModules);
561
- } catch {
562
- throw changeBaselineError(
563
- 'CHANGE_BASELINE_NODE_MODULES_MISSING',
564
- '构建 Git 基线前必须先在当前工作区安装 node_modules'
565
- );
566
- }
567
- if (!fs.statSync(currentNodeModulesRealPath).isDirectory()) {
568
- throw changeBaselineError(
569
- 'CHANGE_BASELINE_NODE_MODULES_INVALID',
570
- '当前工作区 node_modules 不是目录'
571
- );
572
- }
573
-
574
- const tempRoot = fs.realpathSync(
575
- fs.mkdtempSync(path.join(os.tmpdir(), 'openxiangda-change-baseline-'))
576
- );
577
- const archivePath = path.join(tempRoot, 'source.tar');
578
- const extractRoot = path.join(tempRoot, 'source');
579
-
580
- try {
581
- fs.mkdirSync(extractRoot, { recursive: true });
582
- validateGitTreeForSafeArchive(repository.root, resolvedCommit);
583
- runGit(repository.root, [
584
- 'archive',
585
- '--format=tar',
586
- `--output=${archivePath}`,
587
- resolvedCommit,
588
- ]);
589
- validateTarEntryNames(archivePath);
590
- runCommand('tar', ['-xf', archivePath, '-C', extractRoot], {
591
- code: 'CHANGE_BASELINE_ARCHIVE_EXTRACT_FAILED',
592
- message: '无法安全解包 Git 基线归档',
593
- });
594
- assertExtractedTreeSafe(extractRoot);
595
-
596
- const buildRoot = path.resolve(extractRoot, workspaceRelative || '.');
597
- if (!isPathInside(extractRoot, buildRoot) || !isDirectory(buildRoot)) {
598
- throw changeBaselineError(
599
- 'CHANGE_BASELINE_WORKSPACE_NOT_IN_COMMIT',
600
- 'baseCommit 中不存在当前工作区目录'
601
- );
602
- }
603
- if (!fs.existsSync(path.join(buildRoot, 'package.json'))) {
604
- throw changeBaselineError(
605
- 'CHANGE_BASELINE_PACKAGE_MISSING',
606
- 'baseCommit 工作区缺少 package.json,不能执行基线校验'
607
- );
608
- }
609
-
610
- const archivedNodeModules = path.join(buildRoot, 'node_modules');
611
- if (fs.existsSync(archivedNodeModules)) {
612
- throw changeBaselineError(
613
- 'CHANGE_BASELINE_ARCHIVE_NODE_MODULES_CONFLICT',
614
- 'baseCommit 不应包含 node_modules'
615
- );
616
- }
617
- fs.symlinkSync(
618
- currentNodeModulesRealPath,
619
- archivedNodeModules,
620
- process.platform === 'win32' ? 'junction' : 'dir'
621
- );
622
-
623
- const stateSnapshot = copyProjectState
624
- ? copyReadonlyProjectState(currentWorkspaceRoot, buildRoot)
625
- : null;
626
- return {
627
- tempRoot,
628
- extractRoot,
629
- buildRoot,
630
- currentWorkspaceRoot,
631
- repositoryRoot: repository.root,
632
- resolvedCommit,
633
- stateSnapshot,
634
- buildEnv: buildIsolatedEnvironment(env, {
635
- currentWorkspaceRoot,
636
- buildRoot,
637
- repositoryRoot: repository.root,
638
- extractRoot,
639
- }),
640
- };
641
- } catch (error) {
642
- fs.rmSync(tempRoot, { recursive: true, force: true });
643
- throw error;
644
- }
645
- }
646
-
647
- function copyReadonlyProjectState(currentWorkspaceRoot, buildRoot) {
648
- const sourcePath = path.join(
649
- currentWorkspaceRoot,
650
- '.openxiangda',
651
- 'state.json'
652
- );
653
- if (!fs.existsSync(sourcePath)) {
654
- throw changeBaselineError(
655
- 'CHANGE_BASELINE_PROJECT_STATE_MISSING',
656
- '当前工作区缺少 .openxiangda/state.json,不能在 Git 基线中解析应用绑定'
657
- );
658
- }
659
- const destinationDir = path.join(buildRoot, '.openxiangda');
660
- const destinationPath = path.join(destinationDir, 'state.json');
661
- fs.mkdirSync(destinationDir, { recursive: true });
662
- const content = fs.readFileSync(sourcePath);
663
- fs.writeFileSync(destinationPath, content, { mode: 0o444 });
664
- try {
665
- fs.chmodSync(destinationPath, 0o444);
666
- } catch {
667
- // chmod is best-effort on non-POSIX filesystems; the before/after hash below
668
- // still proves that the read-only child plan did not mutate project state.
669
- }
670
- return {
671
- path: destinationPath,
672
- sha256: sha256Buffer(content),
673
- };
674
- }
675
-
676
- function assertCopiedProjectStateUnchanged(workspace) {
677
- const snapshot = workspace?.stateSnapshot;
678
- if (!snapshot) return;
679
- let currentHash = null;
680
- try {
681
- currentHash = sha256File(snapshot.path);
682
- } catch {
683
- // Missing/renamed state is also a mutation.
684
- }
685
- if (currentHash !== snapshot.sha256) {
686
- throw changeBaselineError(
687
- 'CHANGE_BASELINE_PROJECT_STATE_MUTATED',
688
- 'Git 基线 resource plan 修改了只读 .openxiangda/state.json,已中止发布'
689
- );
690
- }
691
- }
692
-
693
- function canonicalJsonSha256(value) {
694
- const canonical = canonicalizeJson(value, new Set(), '$');
695
- return sha256Buffer(Buffer.from(JSON.stringify(canonical), 'utf8'));
696
- }
697
-
698
- function sha256File(filePath) {
699
- return sha256Buffer(fs.readFileSync(filePath));
700
- }
701
-
702
- function canonicalizeJson(value, ancestors, pathLabel) {
703
- if (value === null || typeof value === 'string' || typeof value === 'boolean') {
704
- return value;
705
- }
706
- if (typeof value === 'number') {
707
- if (!Number.isFinite(value)) {
708
- throw changeBaselineError(
709
- 'CHANGE_BASELINE_CANONICAL_JSON_INVALID',
710
- `${pathLabel} 包含非有限数字`
711
- );
712
- }
713
- return Object.is(value, -0) ? 0 : value;
714
- }
715
- if (Array.isArray(value)) {
716
- if (ancestors.has(value)) return throwCircularJson(pathLabel);
717
- ancestors.add(value);
718
- const result = value.map((item, index) =>
719
- canonicalizeJson(item, ancestors, `${pathLabel}[${index}]`)
720
- );
721
- ancestors.delete(value);
722
- return result;
723
- }
724
- if (value && typeof value === 'object') {
725
- const prototype = Object.getPrototypeOf(value);
726
- if (prototype !== Object.prototype && prototype !== null) {
727
- throw changeBaselineError(
728
- 'CHANGE_BASELINE_CANONICAL_JSON_INVALID',
729
- `${pathLabel} 不是普通 JSON 对象`
730
- );
731
- }
732
- if (ancestors.has(value)) return throwCircularJson(pathLabel);
733
- ancestors.add(value);
734
- const result = {};
735
- for (const key of Object.keys(value).sort()) {
736
- const item = value[key];
737
- if (
738
- item === undefined ||
739
- typeof item === 'function' ||
740
- typeof item === 'symbol' ||
741
- typeof item === 'bigint'
742
- ) {
743
- throw changeBaselineError(
744
- 'CHANGE_BASELINE_CANONICAL_JSON_INVALID',
745
- `${pathLabel}.${key} 不是有效 JSON 值`
746
- );
747
- }
748
- result[key] = canonicalizeJson(item, ancestors, `${pathLabel}.${key}`);
749
- }
750
- ancestors.delete(value);
751
- return result;
752
- }
753
- throw changeBaselineError(
754
- 'CHANGE_BASELINE_CANONICAL_JSON_INVALID',
755
- `${pathLabel} 不是有效 JSON 值`
756
- );
757
- }
758
-
759
- function throwCircularJson(pathLabel) {
760
- throw changeBaselineError(
761
- 'CHANGE_BASELINE_CANONICAL_JSON_INVALID',
762
- `${pathLabel} 包含循环引用`
763
- );
764
- }
765
-
766
- function assertStoredChangeBaseline(target, baseline, options = {}) {
767
- const identity = assertTargetIdentity(target);
768
- const baselineAppType = normalizeOptionalString(baseline.appType);
769
- const baselineProfile = normalizeOptionalString(baseline.profile);
770
- if (baselineAppType !== identity.appType) {
771
- throw changeBaselineError(
772
- 'CHANGE_BASELINE_APP_MISMATCH',
773
- `change baseline 属于应用 ${baselineAppType || '<missing>'},不能用于 ${identity.appType}`
774
- );
775
- }
776
- if (baselineProfile !== identity.profile) {
777
- throw changeBaselineError(
778
- 'CHANGE_BASELINE_PROFILE_MISMATCH',
779
- `change baseline 属于 profile ${baselineProfile || '<missing>'},不能用于 ${identity.profile}`
780
- );
781
- }
782
- if (
783
- options.access !== 'reconciliation-read' &&
784
- !isChangeBaselineOwnedByCurrentSession(baseline, options.env || process.env)
785
- ) {
786
- throw ownershipError(
787
- getChangeBaselineOwnerThreadId(baseline),
788
- currentCodexThreadId(options.env || process.env)
789
- );
790
- }
791
- }
792
-
793
- function assertTargetIdentity(target) {
794
- if (!target?.state || !target?.bound || !target?.profileName) {
795
- throw changeBaselineError(
796
- 'CHANGE_BASELINE_TARGET_INVALID',
797
- 'change baseline target 缺少 state、bound 或 profileName'
798
- );
799
- }
800
- const profile = String(target.profileName).trim();
801
- const appType = String(target.appType || target.bound.appType || '').trim();
802
- if (!profile || !appType) {
803
- throw changeBaselineError(
804
- 'CHANGE_BASELINE_TARGET_INVALID',
805
- 'change baseline target 缺少 appType 或 profileName'
806
- );
807
- }
808
- const boundAppType = normalizeOptionalString(target.bound.appType);
809
- const managedStateBound = resolveManagedStateBinding(target, appType);
810
- const stateBound = managedStateBound || target.state.profiles?.[profile];
811
- const stateAppType = normalizeOptionalString(stateBound?.appType);
812
- if (
813
- (boundAppType && boundAppType !== appType) ||
814
- (stateAppType && stateAppType !== appType)
815
- ) {
816
- throw changeBaselineError(
817
- 'CHANGE_BASELINE_TARGET_INVALID',
818
- 'change baseline target 的 appType 与 profile binding 不一致'
819
- );
820
- }
821
- return { appType, profile };
822
- }
823
-
824
- function resolveManagedStateBinding(target, appType) {
825
- const targetName = normalizeOptionalString(target?.targetName);
826
- if (!targetName) return null;
827
- const binding = target.state?.targets?.[targetName];
828
- const bindingAppType = normalizeOptionalString(binding?.appType);
829
- const environmentId = normalizeOptionalString(target.environmentId);
830
- const bindingEnvironmentId = normalizeOptionalString(binding?.environmentId);
831
- if (
832
- !binding ||
833
- bindingAppType !== appType ||
834
- (environmentId && bindingEnvironmentId !== environmentId)
835
- ) {
836
- throw changeBaselineError(
837
- 'CHANGE_BASELINE_TARGET_INVALID',
838
- `change baseline managed target ${targetName} 与 state.targets binding 不一致`
839
- );
840
- }
841
- return binding;
842
- }
843
-
844
- function assertInputIdentity(input, identity) {
845
- const appType = normalizeOptionalString(input.appType);
846
- const profile = normalizeOptionalString(input.profile);
847
- if (appType && appType !== identity.appType) {
848
- throw changeBaselineError(
849
- 'CHANGE_BASELINE_APP_MISMATCH',
850
- `不能把应用 ${appType} 的 baseline 保存到 ${identity.appType}`
851
- );
852
- }
853
- if (profile && profile !== identity.profile) {
854
- throw changeBaselineError(
855
- 'CHANGE_BASELINE_PROFILE_MISMATCH',
856
- `不能把 profile ${profile} 的 baseline 保存到 ${identity.profile}`
857
- );
858
- }
859
- }
860
-
861
- function persistTargetState(target, options) {
862
- target.bound.updatedAt = normalizeNow(options.now);
863
- const targetName = normalizeOptionalString(target.targetName);
864
- if (targetName) {
865
- target.state.targets ||= {};
866
- target.state.targets[targetName] = target.bound;
867
- } else if (target.state.profiles?.[target.profileName]) {
868
- target.state.profiles[target.profileName] = target.bound;
869
- }
870
- (options.saveState || saveProjectState)(
871
- target.state,
872
- options.cwd || target.cwd || process.cwd()
873
- );
874
- }
875
-
876
- function normalizeArtifactTargets(targets) {
877
- if (!Array.isArray(targets) || targets.length === 0) {
878
- throw changeBaselineError(
879
- 'CHANGE_BASELINE_TARGETS_REQUIRED',
880
- 'Git 基线构建至少需要一个精确 Function/Automation target'
881
- );
882
- }
883
- const normalized = [];
884
- const seen = new Set();
885
- for (const target of targets) {
886
- const kind = String(target?.kind || '').trim();
887
- const code = String(target?.code || '').trim();
888
- const expectedSourceKind = SOURCE_KIND_BY_RESOURCE_KIND[kind];
889
- if (!expectedSourceKind) {
890
- throw changeBaselineError(
891
- 'CHANGE_BASELINE_TARGET_INVALID',
892
- `不支持的 Git 基线资源类型: ${kind || '<empty>'}`
893
- );
894
- }
895
- if (!isSafeCode(code)) {
896
- throw changeBaselineError(
897
- 'CHANGE_BASELINE_TARGET_INVALID',
898
- `无效的 Git 基线资源 code: ${code || '<empty>'}`
899
- );
900
- }
901
- const sourceKind = String(target.sourceKind || expectedSourceKind).trim();
902
- if (sourceKind !== expectedSourceKind) {
903
- throw changeBaselineError(
904
- 'CHANGE_BASELINE_TARGET_INVALID',
905
- `${kind}:${code} 的 sourceKind 必须是 ${expectedSourceKind}`
906
- );
907
- }
908
- const key = `${kind}:${code}`;
909
- if (seen.has(key)) continue;
910
- seen.add(key);
911
- normalized.push({ kind, code, sourceKind });
912
- }
913
- return normalized;
914
- }
915
-
916
- function prepareExactArtifactBuild(buildRoot, targets) {
917
- for (const target of targets) {
918
- const outputDir = path.join(buildRoot, 'dist', target.sourceKind, target.code);
919
- fs.rmSync(outputDir, { recursive: true, force: true });
920
- }
921
- fs.rmSync(path.join(buildRoot, '.openxiangda', 'build-cache.json'), {
922
- force: true,
923
- });
924
- fs.rmSync(path.join(buildRoot, '.openxiangda', 'build-cache.json.lock'), {
925
- force: true,
926
- });
927
- }
928
-
929
- function runBuildCommand(packageManager, args, cwd, env) {
930
- const result = spawnSync(packageManager, args, {
931
- cwd,
932
- env,
933
- encoding: 'utf8',
934
- maxBuffer: 16 * 1024 * 1024,
935
- });
936
- return {
937
- ok: !result.error && result.status === 0,
938
- status: result.status,
939
- error: result.error || null,
940
- stdout: String(result.stdout || ''),
941
- stderr: String(result.stderr || ''),
942
- command: [packageManager, ...args],
943
- };
944
- }
945
-
946
- function normalizeBuildProcessResult(result, fallbackCommand) {
947
- return {
948
- ok: !result.error && result.status === 0,
949
- status: result.status,
950
- error: result.error || null,
951
- stdout: String(result.stdout || ''),
952
- stderr: String(result.stderr || ''),
953
- command:
954
- Array.isArray(result.spawnargs) && result.spawnargs.length > 0
955
- ? result.spawnargs
956
- : fallbackCommand,
957
- };
958
- }
959
-
960
- function buildIsolatedEnvironment(
961
- env,
962
- { currentWorkspaceRoot, buildRoot, repositoryRoot, extractRoot }
963
- ) {
964
- const replacements = [
965
- [currentWorkspaceRoot, buildRoot],
966
- [repositoryRoot, extractRoot],
967
- ].sort((left, right) => right[0].length - left[0].length);
968
- const isolated = {};
969
- for (const [key, rawValue] of Object.entries(env || {})) {
970
- if (rawValue === undefined || rawValue === null) continue;
971
- let value = String(rawValue);
972
- for (const [currentPath, archivedPath] of replacements) {
973
- value = value.split(currentPath).join(archivedPath);
974
- }
975
- isolated[key] = value;
976
- }
977
- return {
978
- ...isolated,
979
- // Git-base builds are always non-interactive. Force CI even when the
980
- // parent shell explicitly carries CI=false so pnpm never prompts to purge
981
- // a linked node_modules directory and then aborts because no TTY exists.
982
- CI: 'true',
983
- INIT_CWD: buildRoot,
984
- LOWCODE_WORKSPACE_ROOT: buildRoot,
985
- OPENXIANGDA_WORKSPACE_ROOT: buildRoot,
986
- PWD: buildRoot,
987
- npm_config_local_prefix: buildRoot,
988
- npm_package_json: path.join(buildRoot, 'package.json'),
989
- };
990
- }
991
-
992
- function buildFailureError(target, batch, legacy) {
993
- const output = [
994
- summarizeCommandFailure('batch', batch),
995
- ...(legacy
996
- ? [summarizeCommandFailure(`legacy ${target.kind}:${target.code}`, legacy)]
997
- : []),
998
- ].join('\n');
999
- return changeBaselineError(
1000
- 'CHANGE_BASELINE_BUILD_FAILED',
1001
- `无法从 Git baseCommit 构建精确源码产物\n${output}`
1002
- );
1003
- }
1004
-
1005
- function summarizeCommandFailure(label, result) {
1006
- const detail = [result.error?.message, result.stdout, result.stderr]
1007
- .filter(Boolean)
1008
- .join('\n')
1009
- .trim()
1010
- .slice(-4000);
1011
- return `${label} (${result.command.join(' ')}) status=${result.status ?? 'spawn-error'}${
1012
- detail ? `\n${detail}` : ''
1013
- }`;
1014
- }
1015
-
1016
- function assertArtifactFileSafe(buildRoot, artifactPath, target) {
1017
- if (!isPathInside(buildRoot, artifactPath)) {
1018
- throw changeBaselineError(
1019
- 'CHANGE_BASELINE_ARTIFACT_UNSAFE',
1020
- `${target.kind}:${target.code} 产物路径越界`
1021
- );
1022
- }
1023
- let stat;
1024
- try {
1025
- stat = fs.lstatSync(artifactPath);
1026
- } catch {
1027
- throw changeBaselineError(
1028
- 'CHANGE_BASELINE_ARTIFACT_MISSING',
1029
- `Git baseCommit 构建未生成 ${target.kind}:${target.code} 的 index.cjs`
1030
- );
1031
- }
1032
- if (!stat.isFile() || stat.isSymbolicLink()) {
1033
- throw changeBaselineError(
1034
- 'CHANGE_BASELINE_ARTIFACT_UNSAFE',
1035
- `${target.kind}:${target.code} 产物必须是普通文件`
1036
- );
1037
- }
1038
- const realPath = fs.realpathSync(artifactPath);
1039
- if (!isPathInside(buildRoot, realPath)) {
1040
- throw changeBaselineError(
1041
- 'CHANGE_BASELINE_ARTIFACT_UNSAFE',
1042
- `${target.kind}:${target.code} 产物指向临时 Git 基线之外`
1043
- );
1044
- }
1045
- }
1046
-
1047
- function validateGitTreeForSafeArchive(repoRoot, commit) {
1048
- const result = runGitBuffer(repoRoot, [
1049
- 'ls-tree',
1050
- '-r',
1051
- '-z',
1052
- '--full-tree',
1053
- commit,
1054
- ]);
1055
- for (const recordBuffer of splitNullBuffer(result)) {
1056
- const record = recordBuffer.toString('utf8');
1057
- const tab = record.indexOf('\t');
1058
- if (tab < 0) {
1059
- throw changeBaselineError(
1060
- 'CHANGE_BASELINE_ARCHIVE_UNSAFE',
1061
- 'Git tree 包含无法解析的条目'
1062
- );
1063
- }
1064
- const metadata = record.slice(0, tab).split(' ');
1065
- const entryPath = record.slice(tab + 1);
1066
- const mode = metadata[0];
1067
- const type = metadata[1];
1068
- if (type !== 'blob' || mode === '120000') {
1069
- throw changeBaselineError(
1070
- 'CHANGE_BASELINE_ARCHIVE_UNSAFE',
1071
- `Git baseCommit 包含不允许归档的 ${type || 'unknown'} 条目`
1072
- );
1073
- }
1074
- assertSafeArchivePath(entryPath);
1075
- }
1076
- }
1077
-
1078
- function validateTarEntryNames(archivePath) {
1079
- const result = runCommand('tar', ['-tf', archivePath], {
1080
- code: 'CHANGE_BASELINE_ARCHIVE_LIST_FAILED',
1081
- message: '无法检查 Git 基线归档',
1082
- encoding: 'utf8',
1083
- });
1084
- for (const entry of String(result.stdout || '').split(/\r?\n/).filter(Boolean)) {
1085
- assertSafeArchivePath(entry.replace(/\/$/, ''));
1086
- }
1087
- }
1088
-
1089
- function assertSafeArchivePath(value) {
1090
- const entry = String(value || '');
1091
- const normalized = path.posix.normalize(entry);
1092
- const segments = entry.split('/');
1093
- if (
1094
- !entry ||
1095
- entry.includes('\\') ||
1096
- /[\0\r\n]/.test(entry) ||
1097
- path.posix.isAbsolute(entry) ||
1098
- normalized === '..' ||
1099
- normalized.startsWith('../') ||
1100
- normalized !== entry.replace(/\/$/, '') ||
1101
- segments.some(segment => segment === '..' || segment === '.git')
1102
- ) {
1103
- throw changeBaselineError(
1104
- 'CHANGE_BASELINE_ARCHIVE_UNSAFE',
1105
- 'Git baseCommit 归档包含不安全路径'
1106
- );
1107
- }
1108
- }
1109
-
1110
- function assertExtractedTreeSafe(root) {
1111
- const visit = directory => {
1112
- for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
1113
- const entryPath = path.join(directory, entry.name);
1114
- const stat = fs.lstatSync(entryPath);
1115
- if (stat.isSymbolicLink()) {
1116
- throw changeBaselineError(
1117
- 'CHANGE_BASELINE_ARCHIVE_UNSAFE',
1118
- 'Git baseCommit 归档不能包含符号链接'
1119
- );
1120
- }
1121
- if (!isPathInside(root, fs.realpathSync(entryPath))) {
1122
- throw changeBaselineError(
1123
- 'CHANGE_BASELINE_ARCHIVE_UNSAFE',
1124
- 'Git baseCommit 解包路径越界'
1125
- );
1126
- }
1127
- if (entry.isDirectory()) visit(entryPath);
1128
- }
1129
- };
1130
- visit(root);
1131
- }
1132
-
1133
- function resolveGitRepository(cwd) {
1134
- const resolvedCwd = path.resolve(cwd || process.cwd());
1135
- if (!isDirectory(resolvedCwd)) {
1136
- throw changeBaselineError(
1137
- 'CHANGE_BASELINE_GIT_REQUIRED',
1138
- 'cwd 不是可用目录'
1139
- );
1140
- }
1141
- const root = runGit(resolvedCwd, ['rev-parse', '--show-toplevel']).trim();
1142
- if (!root) {
1143
- throw changeBaselineError(
1144
- 'CHANGE_BASELINE_GIT_REQUIRED',
1145
- '当前工作区不是 Git 仓库'
1146
- );
1147
- }
1148
- return { root: fs.realpathSync(path.resolve(root)) };
1149
- }
1150
-
1151
- function resolveExactCommit(repoRoot, ref) {
1152
- const commit = runGit(repoRoot, [
1153
- 'rev-parse',
1154
- '--verify',
1155
- `${ref}^{commit}`,
1156
- ]).trim();
1157
- assertGitObjectId(commit, 'baseCommit');
1158
- return commit;
1159
- }
1160
-
1161
- function normalizeBaseRef(value) {
1162
- const ref = String(value || 'HEAD').trim();
1163
- if (!ref || ref.startsWith('-') || /[\0\r\n]/.test(ref)) {
1164
- throw changeBaselineError(
1165
- 'CHANGE_BASELINE_REF_INVALID',
1166
- 'Git baseRef 无效'
1167
- );
1168
- }
1169
- return ref;
1170
- }
1171
-
1172
- function normalizeImmutableCommit(value) {
1173
- const commit = String(value || '').trim();
1174
- if (!/^[0-9a-f]{40,64}$/i.test(commit)) {
1175
- throw changeBaselineError(
1176
- 'CHANGE_BASELINE_COMMIT_NOT_EXACT',
1177
- 'baseCommit 必须是完整的 Git commit id,不能使用 HEAD、branch 或短 hash'
1178
- );
1179
- }
1180
- return commit;
1181
- }
1182
-
1183
- function assertGitObjectId(value, label) {
1184
- if (!/^[0-9a-f]{40,64}$/i.test(String(value || ''))) {
1185
- throw changeBaselineError(
1186
- 'CHANGE_BASELINE_GIT_OBJECT_INVALID',
1187
- `Git ${label} 无效`
1188
- );
1189
- }
1190
- }
1191
-
1192
- function runGit(cwd, args) {
1193
- const result = runCommand('git', ['-C', cwd, ...args], {
1194
- code: 'CHANGE_BASELINE_GIT_FAILED',
1195
- message: `Git 命令失败: git ${args.join(' ')}`,
1196
- encoding: 'utf8',
1197
- });
1198
- return String(result.stdout || '');
1199
- }
1200
-
1201
- function tryRunGit(cwd, args) {
1202
- const result = spawnSync('git', ['-C', cwd, ...args], {
1203
- encoding: 'utf8',
1204
- maxBuffer: 16 * 1024 * 1024,
1205
- });
1206
- return result.status === 0 && !result.error ? String(result.stdout || '') : '';
1207
- }
1208
-
1209
- function runGitBuffer(cwd, args) {
1210
- const result = runCommand('git', ['-C', cwd, ...args], {
1211
- code: 'CHANGE_BASELINE_GIT_FAILED',
1212
- message: `Git 命令失败: git ${args.join(' ')}`,
1213
- });
1214
- return Buffer.isBuffer(result.stdout) ? result.stdout : Buffer.from(result.stdout || '');
1215
- }
1216
-
1217
- function runCommand(command, args, options = {}) {
1218
- const result = spawnSync(command, args, {
1219
- encoding: options.encoding,
1220
- maxBuffer: 16 * 1024 * 1024,
1221
- });
1222
- if (result.error || result.status !== 0) {
1223
- const detail = [
1224
- result.error?.message,
1225
- Buffer.isBuffer(result.stderr)
1226
- ? result.stderr.toString('utf8')
1227
- : result.stderr,
1228
- Buffer.isBuffer(result.stdout)
1229
- ? result.stdout.toString('utf8')
1230
- : result.stdout,
1231
- ]
1232
- .filter(Boolean)
1233
- .join('\n')
1234
- .trim()
1235
- .slice(-4000);
1236
- throw changeBaselineError(
1237
- options.code || 'CHANGE_BASELINE_COMMAND_FAILED',
1238
- `${options.message || `${command} 执行失败`}${detail ? `\n${detail}` : ''}`
1239
- );
1240
- }
1241
- return result;
1242
- }
1243
-
1244
- function splitNullBuffer(buffer) {
1245
- const records = [];
1246
- let start = 0;
1247
- for (let index = 0; index < buffer.length; index += 1) {
1248
- if (buffer[index] !== 0) continue;
1249
- if (index > start) records.push(buffer.subarray(start, index));
1250
- start = index + 1;
1251
- }
1252
- if (start < buffer.length) records.push(buffer.subarray(start));
1253
- return records;
1254
- }
1255
-
1256
- function getChangeBaselineOwnerThreadId(baseline) {
1257
- return String(
1258
- baseline?.workspace?.threadId || baseline?.ownerThreadId || ''
1259
- ).trim();
1260
- }
1261
-
1262
- function currentCodexThreadId(env = process.env) {
1263
- return String(env?.CODEX_THREAD_ID || '').trim();
1264
- }
1265
-
1266
- function ownershipError(ownerThreadId, currentThreadId) {
1267
- return changeBaselineError(
1268
- 'CHANGE_BASELINE_OWNED_BY_ANOTHER_TASK',
1269
- `change baseline 由另一个任务持有 (${ownerThreadId || 'unknown'});当前任务 ${
1270
- currentThreadId || '<none>'
1271
- } 不能复用、覆盖或清除`
1272
- );
1273
- }
1274
-
1275
- function preservedField(input, existing, key, fallback) {
1276
- if (Object.prototype.hasOwnProperty.call(input, key)) return input[key];
1277
- if (existing && Object.prototype.hasOwnProperty.call(existing, key)) {
1278
- return existing[key];
1279
- }
1280
- return fallback;
1281
- }
1282
-
1283
- function clonePreservedField(input, existing, key, fallback) {
1284
- return cloneJson(preservedField(input, existing, key, fallback));
1285
- }
1286
-
1287
- function cloneJson(value) {
1288
- if (value === undefined) return undefined;
1289
- return JSON.parse(JSON.stringify(value));
1290
- }
1291
-
1292
- function normalizeOptionalString(value) {
1293
- const text = String(value === undefined || value === null ? '' : value).trim();
1294
- return text || null;
1295
- }
1296
-
1297
- function normalizeNow(value) {
1298
- const date = value === undefined ? new Date() : new Date(value);
1299
- if (Number.isNaN(date.getTime())) {
1300
- throw changeBaselineError(
1301
- 'CHANGE_BASELINE_INVALID',
1302
- 'change baseline updatedAt 无效'
1303
- );
1304
- }
1305
- return date.toISOString();
1306
- }
1307
-
1308
- function isSafeCode(code) {
1309
- return Boolean(
1310
- code &&
1311
- code !== '.' &&
1312
- code !== '..' &&
1313
- !/[\\/,:\0\r\n]/.test(code)
1314
- );
1315
- }
1316
-
1317
- function isDirectory(value) {
1318
- try {
1319
- return fs.statSync(value).isDirectory();
1320
- } catch {
1321
- return false;
1322
- }
1323
- }
1324
-
1325
- function isOutsidePath(relativePath) {
1326
- return (
1327
- relativePath === '..' ||
1328
- relativePath.startsWith(`..${path.sep}`) ||
1329
- path.isAbsolute(relativePath)
1330
- );
1331
- }
1332
-
1333
- function isPathInside(root, candidate) {
1334
- const relative = path.relative(path.resolve(root), path.resolve(candidate));
1335
- return !isOutsidePath(relative);
1336
- }
1337
-
1338
- function sha256Buffer(buffer) {
1339
- return crypto.createHash('sha256').update(buffer).digest('hex');
1340
- }
1341
-
1342
- function changeBaselineError(code, message) {
1343
- const error = new Error(message);
1344
- error.code = code;
1345
- return error;
1346
- }
1347
-
1348
- module.exports = {
1349
- buildGitBaseSourceArtifacts,
1350
- canonicalJsonSha256,
1351
- clearChangeBaseline,
1352
- clearChangeBaselineForReconciliation,
1353
- getStoredChangeBaseline,
1354
- isChangeBaselineOwnedByCurrentSession,
1355
- readGitSourceBase,
1356
- saveChangeBaseline,
1357
- sha256File,
1358
- withGitBaseWorkspace,
1359
- };