@treeseed/sdk 0.12.62 → 0.13.0-rc.10

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 (1108) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +33 -359
  3. package/dist/accounts/account-contracts.d.ts +170 -0
  4. package/dist/accounts/account-contracts.js +33 -0
  5. package/dist/agent-capacity/allocation.d.ts +186 -0
  6. package/dist/agent-capacity/allocation.js +226 -0
  7. package/dist/agent-capacity/artifact-mutation-receipt.d.ts +49 -0
  8. package/dist/agent-capacity/artifact-mutation-receipt.js +36 -0
  9. package/dist/agent-capacity/artifacts.d.ts +107 -0
  10. package/dist/agent-capacity/artifacts.js +39 -0
  11. package/dist/agent-capacity/authority/agent-authority-presets.d.ts +13 -0
  12. package/dist/agent-capacity/authority/agent-authority-presets.js +106 -0
  13. package/dist/agent-capacity/contracts/capacity/assignments/assignment-records.d.ts +269 -0
  14. package/dist/agent-capacity/contracts/capacity/assignments/assignment-records.js +10 -0
  15. package/dist/agent-capacity/contracts/capacity/communication/communication-records.d.ts +101 -0
  16. package/dist/agent-capacity/contracts/capacity/communication/communication-records.js +9 -0
  17. package/dist/agent-capacity/contracts/capacity/providers/supply-policy.d.ts +36 -0
  18. package/dist/agent-capacity/contracts/capacity/providers/supply-policy.js +4 -0
  19. package/dist/agent-capacity/contracts/capacity/workdays/workday-records.d.ts +188 -0
  20. package/dist/agent-capacity/contracts/configuration/configuration.d.ts +11 -0
  21. package/dist/agent-capacity/contracts/configuration/configuration.js +20 -0
  22. package/dist/agent-capacity/contracts/operations/research-workflow.d.ts +59 -0
  23. package/dist/agent-capacity/contracts/operations/research-workflow.js +16 -0
  24. package/dist/agent-capacity/contracts/operations/workflow-promotion.d.ts +24 -0
  25. package/dist/agent-capacity/contracts/projects/agents/project-agent-class.d.ts +37 -0
  26. package/dist/agent-capacity/contracts/runtime/runtime-observability.d.ts +335 -0
  27. package/dist/agent-capacity/contracts/support/agent-atlas.d.ts +185 -0
  28. package/dist/agent-capacity/contracts/support/agent-atlas.js +47 -0
  29. package/dist/agent-capacity/contracts/support/agent-lab-monitoring.d.ts +96 -0
  30. package/dist/agent-capacity/contracts/support/agent-lab-monitoring.js +14 -0
  31. package/dist/agent-capacity/contracts/support/authority/execution-mode.d.ts +10 -0
  32. package/dist/agent-capacity/contracts/support/authority/execution-mode.js +17 -0
  33. package/dist/agent-capacity/contracts/support/decision-work.d.ts +251 -0
  34. package/dist/agent-capacity/contracts/support/failure-records.d.ts +9 -0
  35. package/dist/agent-capacity/contracts/support/failure-records.js +0 -0
  36. package/dist/agent-capacity/contracts/support/financial-records.d.ts +124 -0
  37. package/dist/agent-capacity/contracts/support/financial-records.js +0 -0
  38. package/dist/agent-capacity/contracts/support/planning-records.d.ts +121 -0
  39. package/dist/agent-capacity/contracts/support/planning-records.js +0 -0
  40. package/dist/agent-capacity/contracts/support/research-citation.d.ts +15 -0
  41. package/dist/agent-capacity/contracts/support/research-citation.js +0 -0
  42. package/dist/agent-capacity/contracts/support/research-source-policy.d.ts +8 -0
  43. package/dist/agent-capacity/contracts/support/research-source-policy.js +0 -0
  44. package/dist/agent-capacity/contracts/support/time-capacity.d.ts +163 -0
  45. package/dist/agent-capacity/contracts/support/time-capacity.js +63 -0
  46. package/dist/agent-capacity/policy/capacity/allocations/allocation-hierarchy.d.ts +29 -0
  47. package/dist/agent-capacity/policy/capacity/allocations/allocation-hierarchy.js +110 -0
  48. package/dist/agent-capacity/validation/activity-profile.d.ts +12 -0
  49. package/dist/agent-capacity/validation/activity-profile.js +264 -0
  50. package/dist/agent-capacity/validation/agent-definition-schema.d.ts +9140 -0
  51. package/dist/agent-capacity/validation/agent-definition-schema.js +198 -0
  52. package/dist/agent-capacity/validation/agent-lab-forensics-schema.d.ts +234 -0
  53. package/dist/agent-capacity/validation/agent-lab-forensics-schema.js +104 -0
  54. package/dist/agent-capacity/validation/agent-signal.d.ts +30 -0
  55. package/dist/agent-capacity/validation/agent-signal.js +31 -0
  56. package/dist/agent-capacity/validation/allocation.d.ts +12 -0
  57. package/dist/agent-capacity/validation/allocation.js +115 -0
  58. package/dist/agent-capacity/validation/assignment-records.d.ts +16 -0
  59. package/dist/agent-capacity/validation/assignment-records.js +92 -0
  60. package/dist/agent-capacity/validation/configuration.d.ts +14 -0
  61. package/dist/agent-capacity/validation/configuration.js +23 -0
  62. package/dist/agent-capacity/validation/index.d.ts +11 -0
  63. package/dist/agent-capacity/validation/index.js +11 -0
  64. package/dist/agent-capacity/validation/proposal-type.d.ts +22 -0
  65. package/dist/agent-capacity/validation/proposal-type.js +21 -0
  66. package/dist/agent-capacity/validation/research/citation.d.ts +16 -0
  67. package/dist/agent-capacity/validation/research/citation.js +47 -0
  68. package/dist/agent-capacity/validation/research/source-policy.d.ts +11 -0
  69. package/dist/agent-capacity/validation/research/source-policy.js +26 -0
  70. package/dist/agent-capacity/validation/research/workflow.d.ts +10 -0
  71. package/dist/agent-capacity/validation/research/workflow.js +31 -0
  72. package/dist/agent-capacity/validation/workflow-promotion.d.ts +2 -0
  73. package/dist/agent-capacity/validation/workflow-promotion.js +34 -0
  74. package/dist/agent-capacity/workday.d.ts +52 -0
  75. package/dist/agent-capacity/workday.js +105 -0
  76. package/dist/ai-appliance/contracts.d.ts +90 -0
  77. package/dist/ai-appliance/contracts.js +16 -0
  78. package/dist/ai-appliance/validation.d.ts +4 -0
  79. package/dist/ai-appliance/validation.js +62 -0
  80. package/dist/capacity/agents/agent-capacity.d.ts +21 -0
  81. package/dist/capacity/agents/agent-capacity.js +20 -0
  82. package/dist/capacity/capacity-core/capacity-pagination.d.ts +18 -0
  83. package/dist/capacity/capacity-core/capacity-pagination.js +33 -0
  84. package/dist/capacity/providers/capacity-provider.d.ts +1 -0
  85. package/dist/capacity/providers/capacity-provider.js +1 -0
  86. package/dist/capacity-provider/client.d.ts +56 -0
  87. package/dist/capacity-provider/client.js +163 -0
  88. package/dist/capacity-provider/contracts/capacity-facts.d.ts +64 -0
  89. package/dist/capacity-provider/contracts/capacity-facts.js +0 -0
  90. package/dist/capacity-provider/contracts/governance.d.ts +399 -0
  91. package/dist/capacity-provider/contracts/governance.js +18 -0
  92. package/dist/capacity-provider/contracts/index.d.ts +2 -0
  93. package/dist/capacity-provider/contracts/index.js +2 -0
  94. package/dist/capacity-provider/index.d.ts +3 -0
  95. package/dist/capacity-provider/index.js +3 -0
  96. package/dist/capacity-provider/validation.d.ts +27 -0
  97. package/dist/capacity-provider/validation.js +184 -0
  98. package/dist/configuration/secrets-capability.d.ts +4 -0
  99. package/dist/configuration/secrets-capability.js +4 -0
  100. package/dist/content/contracts.d.ts +12 -0
  101. package/dist/content/contracts.js +0 -0
  102. package/dist/content/validation/agent-operational-content-schemas.d.ts +1351 -0
  103. package/dist/content/validation/agent-operational-content-schemas.js +146 -0
  104. package/dist/content/validation/auxiliary-content-schemas.d.ts +1715 -0
  105. package/dist/content/validation/auxiliary-content-schemas.js +173 -0
  106. package/dist/content/validation/content-model-schemas.d.ts +21728 -0
  107. package/dist/content/validation/content-model-schemas.js +271 -0
  108. package/dist/content/validation/index.d.ts +3 -0
  109. package/dist/content/validation/index.js +3 -0
  110. package/dist/content/validation/portable-content-data.d.ts +2101 -0
  111. package/dist/content/validation/portable-content-data.js +49 -0
  112. package/dist/entrypoints/clients/control-plane-client.d.ts +112 -0
  113. package/dist/entrypoints/clients/control-plane-client.js +180 -0
  114. package/dist/entrypoints/models/field-aliases.d.ts +11 -0
  115. package/dist/entrypoints/models/model-registry.d.ts +3 -0
  116. package/dist/entrypoints/models/model-registry.js +3 -0
  117. package/dist/entrypoints/models/sdk-fields.d.ts +11 -0
  118. package/dist/entrypoints/models/sdk-types.d.ts +10 -0
  119. package/dist/entrypoints/models/sdk-types.js +10 -0
  120. package/dist/feedback/contracts.d.ts +142 -0
  121. package/dist/feedback/contracts.js +18 -0
  122. package/dist/feedback/index.d.ts +1 -0
  123. package/dist/feedback/index.js +1 -0
  124. package/dist/governance/groups/contracts.d.ts +102 -0
  125. package/dist/governance/groups/contracts.js +6 -0
  126. package/dist/graph/context-query-contracts.d.ts +19 -1
  127. package/dist/graph/context-query-contracts.js +49 -8
  128. package/dist/knowledge/contracts.d.ts +173 -0
  129. package/dist/knowledge/contracts.js +16 -0
  130. package/dist/knowledge/index.d.ts +1 -0
  131. package/dist/knowledge/index.js +1 -0
  132. package/dist/model-registry/agent-operational-models.d.ts +4 -0
  133. package/dist/model-registry/agent-operational-models.js +38 -0
  134. package/dist/model-registry/build-builtin-model-registry.d.ts +2 -0
  135. package/dist/model-registry/build-builtin-model-registry.js +426 -0
  136. package/dist/model-registry/content-root.d.ts +9 -0
  137. package/dist/model-registry/content-root.js +33 -0
  138. package/dist/model-registry/discussion-models.d.ts +4 -0
  139. package/dist/model-registry/discussion-models.js +84 -0
  140. package/dist/model-registry/group-models.d.ts +2 -0
  141. package/dist/model-registry/group-models.js +52 -0
  142. package/dist/model-registry/knowledge-models.d.ts +2 -0
  143. package/dist/model-registry/knowledge-models.js +89 -0
  144. package/dist/model-registry/normalize-definition.d.ts +8 -0
  145. package/dist/model-registry/normalize-definition.js +69 -0
  146. package/dist/operator-contracts/canonical-command-tree.d.ts +3 -0
  147. package/dist/operator-contracts/canonical-command-tree.js +81 -0
  148. package/dist/operator-contracts/command-tree.d.ts +79 -0
  149. package/dist/operator-contracts/command-tree.js +53 -0
  150. package/dist/operator-contracts/control-plane-operation.d.ts +80 -0
  151. package/dist/operator-contracts/control-plane-operation.js +75 -0
  152. package/dist/operator-contracts/control-plane-operations.d.ts +546 -0
  153. package/dist/operator-contracts/control-plane-operations.js +352 -0
  154. package/dist/operator-contracts/index.d.ts +8 -0
  155. package/dist/operator-contracts/index.js +8 -0
  156. package/dist/operator-contracts/mcp.d.ts +78 -0
  157. package/dist/operator-contracts/mcp.js +23 -0
  158. package/dist/operator-contracts/oauth.d.ts +46 -0
  159. package/dist/operator-contracts/oauth.js +0 -0
  160. package/dist/operator-contracts/workday-lifecycle.d.ts +157 -0
  161. package/dist/operator-contracts/workday-lifecycle.js +65 -0
  162. package/dist/operator-contracts/workday-profile.d.ts +72 -0
  163. package/dist/operator-contracts/workday-profile.js +106 -0
  164. package/dist/projects/projects-core/project-workflow.d.ts +179 -0
  165. package/dist/projects/projects-core/project-workflow.js +66 -0
  166. package/dist/sdk-types/configuration/sdk-dispatch-credential-source.d.ts +201 -0
  167. package/dist/sdk-types/configuration/sdk-dispatch-credential-source.js +0 -0
  168. package/dist/sdk-types/control-plane/resource-requests.d.ts +124 -0
  169. package/dist/sdk-types/control-plane/resource-requests.js +0 -0
  170. package/dist/sdk-types/governance/commons/commons-question-input.d.ts +61 -0
  171. package/dist/sdk-types/governance/commons/commons-question-input.js +0 -0
  172. package/dist/sdk-types/support/planning-policy.d.ts +210 -0
  173. package/dist/sdk-types/support/planning-policy.js +0 -0
  174. package/dist/sdk-types/support/platform-contracts.d.ts +178 -0
  175. package/dist/sdk-types/support/platform-contracts.js +15 -0
  176. package/dist/sdk-types/support/sdk-model-names.d.ts +44 -0
  177. package/dist/sdk-types/support/sdk-model-names.js +80 -0
  178. package/dist/sdk-types/support/sdk-search-request.d.ts +182 -0
  179. package/dist/sdk-types/support/sdk-search-request.js +0 -0
  180. package/dist/sdk-types/support/task-planning.d.ts +189 -0
  181. package/dist/sdk-types/support/task-planning.js +0 -0
  182. package/dist/sdk-types/treedx/graph/sdk-graph-query-request.d.ts +157 -0
  183. package/dist/sdk-types/treedx/graph/sdk-graph-query-request.js +0 -0
  184. package/dist/secrets-capability/provider-operation-contracts.d.ts +90 -0
  185. package/dist/secrets-capability/provider-operation-contracts.js +10 -0
  186. package/dist/secrets-capability/service-provider-contracts.d.ts +92 -0
  187. package/dist/secrets-capability/service-provider-contracts.js +183 -0
  188. package/dist/secrets-capability/service-vault-contracts.d.ts +61 -0
  189. package/dist/secrets-capability/service-vault-contracts.js +39 -0
  190. package/dist/secrets-capability/workflow-operation-contracts.d.ts +95 -0
  191. package/dist/secrets-capability/workflow-operation-contracts.js +0 -0
  192. package/dist/standards/canonicalize.d.ts +10 -0
  193. package/dist/standards/canonicalize.js +43 -0
  194. package/dist/standards/compatibility-attestation.d.ts +23 -0
  195. package/dist/standards/compatibility-attestation.js +40 -0
  196. package/dist/standards/composition.d.ts +15 -0
  197. package/dist/standards/composition.js +14 -0
  198. package/dist/standards/contract-bundle.d.ts +8 -0
  199. package/dist/standards/contract-bundle.js +23 -0
  200. package/dist/standards/contracts.d.ts +39 -0
  201. package/dist/standards/contracts.js +0 -0
  202. package/dist/standards/errors.d.ts +6 -0
  203. package/dist/standards/errors.js +13 -0
  204. package/dist/standards/index.d.ts +8 -0
  205. package/dist/standards/index.js +8 -0
  206. package/dist/standards/mcp/compare.d.ts +2 -0
  207. package/dist/standards/mcp/compare.js +38 -0
  208. package/dist/standards/mcp/contracts.d.ts +34 -0
  209. package/dist/standards/mcp/contracts.js +0 -0
  210. package/dist/standards/mcp/index.d.ts +3 -0
  211. package/dist/standards/mcp/index.js +3 -0
  212. package/dist/standards/mcp/normalize.d.ts +4 -0
  213. package/dist/standards/mcp/normalize.js +30 -0
  214. package/dist/standards/openapi/compare.d.ts +2 -0
  215. package/dist/standards/openapi/compare.js +112 -0
  216. package/dist/standards/openapi/contracts.d.ts +24 -0
  217. package/dist/standards/openapi/contracts.js +0 -0
  218. package/dist/standards/openapi/index.d.ts +3 -0
  219. package/dist/standards/openapi/index.js +3 -0
  220. package/dist/standards/openapi/normalize.d.ts +2 -0
  221. package/dist/standards/openapi/normalize.js +57 -0
  222. package/dist/standards/package-manifest.d.ts +37 -0
  223. package/dist/standards/package-manifest.js +89 -0
  224. package/dist/standards/portfolio-entry.d.ts +12 -0
  225. package/dist/standards/portfolio-entry.js +11 -0
  226. package/dist/standards/typescript/compare.d.ts +2 -0
  227. package/dist/standards/typescript/compare.js +88 -0
  228. package/dist/standards/typescript/contracts.d.ts +44 -0
  229. package/dist/standards/typescript/contracts.js +0 -0
  230. package/dist/standards/typescript/extract.d.ts +10 -0
  231. package/dist/standards/typescript/extract.js +244 -0
  232. package/dist/standards/typescript/index.d.ts +3 -0
  233. package/dist/standards/typescript/index.js +3 -0
  234. package/dist/treedx/accounts/auth.d.ts +17 -0
  235. package/dist/treedx/accounts/auth.js +48 -0
  236. package/dist/treedx/client/accounts/contracts/auth-mode.d.ts +3 -0
  237. package/dist/treedx/client/accounts/contracts/auth-mode.js +6 -0
  238. package/dist/treedx/client/build/creation/build-context.d.ts +3 -0
  239. package/dist/treedx/client/build/creation/build-context.js +7 -0
  240. package/dist/treedx/client/build/creation/build-snapshot.d.ts +3 -0
  241. package/dist/treedx/client/build/creation/build-snapshot.js +8 -0
  242. package/dist/treedx/client/capacity/allocations/contracts/put-capability-grant.d.ts +3 -0
  243. package/dist/treedx/client/capacity/allocations/contracts/put-capability-grant.js +7 -0
  244. package/dist/treedx/client/capacity/allocations/queries/list-capability-grants.d.ts +6 -0
  245. package/dist/treedx/client/capacity/allocations/queries/list-capability-grants.js +10 -0
  246. package/dist/treedx/client/methods.d.ts +102 -0
  247. package/dist/treedx/client/methods.js +209 -0
  248. package/dist/treedx/client/persistence/contracts/restore-storage.d.ts +3 -0
  249. package/dist/treedx/client/persistence/contracts/restore-storage.js +6 -0
  250. package/dist/treedx/client/persistence/lifecycle/verify-storage-restore.d.ts +3 -0
  251. package/dist/treedx/client/persistence/lifecycle/verify-storage-restore.js +6 -0
  252. package/dist/treedx/client/repositories/creation/register-repository.d.ts +3 -0
  253. package/dist/treedx/client/repositories/creation/register-repository.js +7 -0
  254. package/dist/treedx/client/repositories/queries/get-repository.d.ts +3 -0
  255. package/dist/treedx/client/repositories/queries/get-repository.js +7 -0
  256. package/dist/treedx/client/repositories/queries/list-repository-paths.d.ts +3 -0
  257. package/dist/treedx/client/repositories/queries/list-repository-paths.js +7 -0
  258. package/dist/treedx/client/repositories/queries/list-repository-refs.d.ts +3 -0
  259. package/dist/treedx/client/repositories/queries/list-repository-refs.js +12 -0
  260. package/dist/treedx/client/repositories/queries/query-repository.d.ts +3 -0
  261. package/dist/treedx/client/repositories/queries/query-repository.js +7 -0
  262. package/dist/treedx/client/repositories/queries/read-repository-file.d.ts +3 -0
  263. package/dist/treedx/client/repositories/queries/read-repository-file.js +6 -0
  264. package/dist/treedx/client/repositories/queries/read-repository-files.d.ts +3 -0
  265. package/dist/treedx/client/repositories/queries/read-repository-files.js +7 -0
  266. package/dist/treedx/client/repositories/queries/search-repository-files.d.ts +3 -0
  267. package/dist/treedx/client/repositories/queries/search-repository-files.js +7 -0
  268. package/dist/treedx/client/support/contracts/treedx/artifacts/contracts/download-artifact.d.ts +3 -0
  269. package/dist/treedx/client/support/contracts/treedx/artifacts/contracts/download-artifact.js +9 -0
  270. package/dist/treedx/client/support/contracts/treedx/authorization/contracts/whoami.d.ts +3 -0
  271. package/dist/treedx/client/support/contracts/treedx/authorization/contracts/whoami.js +6 -0
  272. package/dist/treedx/client/support/contracts/treedx/graph/contracts/parse-context-dsl.d.ts +3 -0
  273. package/dist/treedx/client/support/contracts/treedx/graph/contracts/parse-context-dsl.js +7 -0
  274. package/dist/treedx/client/support/contracts/treedx/health/contracts/deep-health.d.ts +5 -0
  275. package/dist/treedx/client/support/contracts/treedx/health/contracts/deep-health.js +7 -0
  276. package/dist/treedx/client/support/contracts/treedx/health/contracts/health.d.ts +3 -0
  277. package/dist/treedx/client/support/contracts/treedx/health/contracts/health.js +6 -0
  278. package/dist/treedx/client/support/contracts/treedx/health/contracts/metrics.d.ts +3 -0
  279. package/dist/treedx/client/support/contracts/treedx/health/contracts/metrics.js +7 -0
  280. package/dist/treedx/client/support/contracts/treedx/health/contracts/prometheus-metrics.d.ts +2 -0
  281. package/dist/treedx/client/support/contracts/treedx/health/contracts/prometheus-metrics.js +19 -0
  282. package/dist/treedx/client/support/contracts/treedx/health/contracts/ready.d.ts +3 -0
  283. package/dist/treedx/client/support/contracts/treedx/health/contracts/ready.js +7 -0
  284. package/dist/treedx/client/support/contracts/treedx/health/contracts/status.d.ts +3 -0
  285. package/dist/treedx/client/support/contracts/treedx/health/contracts/status.js +6 -0
  286. package/dist/treedx/client/support/contracts/treedx/repositories/contracts/commit.d.ts +3 -0
  287. package/dist/treedx/client/support/contracts/treedx/repositories/contracts/commit.js +7 -0
  288. package/dist/treedx/client/support/contracts/treedx/repositories/contracts/diff.d.ts +3 -0
  289. package/dist/treedx/client/support/contracts/treedx/repositories/contracts/diff.js +6 -0
  290. package/dist/treedx/client/support/contracts/treedx/repositories/contracts/fetch-remote.d.ts +3 -0
  291. package/dist/treedx/client/support/contracts/treedx/repositories/contracts/fetch-remote.js +7 -0
  292. package/dist/treedx/client/support/contracts/treedx/repositories/contracts/push.d.ts +6 -0
  293. package/dist/treedx/client/support/contracts/treedx/repositories/contracts/push.js +23 -0
  294. package/dist/treedx/client/support/contracts/treedx/search/contracts/compact-search-index.d.ts +3 -0
  295. package/dist/treedx/client/support/contracts/treedx/search/contracts/compact-search-index.js +8 -0
  296. package/dist/treedx/client/support/contracts/treedx/search/contracts/search.d.ts +3 -0
  297. package/dist/treedx/client/support/contracts/treedx/search/contracts/search.js +7 -0
  298. package/dist/treedx/client/support/contracts/treedx/storage/contracts/backup-storage.d.ts +3 -0
  299. package/dist/treedx/client/support/contracts/treedx/storage/contracts/backup-storage.js +8 -0
  300. package/dist/treedx/client/support/contracts/treedx/storage/contracts/compact-storage.d.ts +3 -0
  301. package/dist/treedx/client/support/contracts/treedx/storage/contracts/compact-storage.js +8 -0
  302. package/dist/treedx/client/support/contracts/treedx/transport/contracts/assert-binary-ok.d.ts +2 -0
  303. package/dist/treedx/client/support/contracts/treedx/transport/contracts/assert-binary-ok.js +15 -0
  304. package/dist/treedx/client/support/contracts/treedx/transport/contracts/fetch-with-timeout.d.ts +2 -0
  305. package/dist/treedx/client/support/contracts/treedx/transport/contracts/fetch-with-timeout.js +38 -0
  306. package/dist/treedx/client/support/contracts/treedx/transport/contracts/headers.d.ts +2 -0
  307. package/dist/treedx/client/support/contracts/treedx/transport/contracts/headers.js +15 -0
  308. package/dist/treedx/client/support/contracts/treedx/transport/contracts/parse-json-response.d.ts +2 -0
  309. package/dist/treedx/client/support/contracts/treedx/transport/contracts/parse-json-response.js +15 -0
  310. package/dist/treedx/client/support/contracts/treedx/transport/contracts/query.d.ts +2 -0
  311. package/dist/treedx/client/support/contracts/treedx/transport/contracts/query.js +14 -0
  312. package/dist/treedx/client/support/contracts/treedx/transport/contracts/repo-id.d.ts +2 -0
  313. package/dist/treedx/client/support/contracts/treedx/transport/contracts/repo-id.js +14 -0
  314. package/dist/treedx/client/support/contracts/treedx/transport/contracts/request.d.ts +6 -0
  315. package/dist/treedx/client/support/contracts/treedx/transport/contracts/request.js +41 -0
  316. package/dist/treedx/client/support/contracts/treedx/transport/contracts/throw-api-error.d.ts +2 -0
  317. package/dist/treedx/client/support/contracts/treedx/transport/contracts/throw-api-error.js +14 -0
  318. package/dist/treedx/client/support/contracts/treedx/workspaces/contracts/exec.d.ts +3 -0
  319. package/dist/treedx/client/support/contracts/treedx/workspaces/contracts/exec.js +7 -0
  320. package/dist/treedx/client/support/creation/apply-changeset.d.ts +3 -0
  321. package/dist/treedx/client/support/creation/apply-changeset.js +10 -0
  322. package/dist/treedx/client/support/creation/apply-storage-migration.d.ts +3 -0
  323. package/dist/treedx/client/support/creation/apply-storage-migration.js +7 -0
  324. package/dist/treedx/client/support/creation/create-migration.d.ts +6 -0
  325. package/dist/treedx/client/support/creation/create-migration.js +7 -0
  326. package/dist/treedx/client/support/creation/export-artifact.d.ts +3 -0
  327. package/dist/treedx/client/support/creation/export-artifact.js +8 -0
  328. package/dist/treedx/client/support/creation/plan-storage-migration.d.ts +3 -0
  329. package/dist/treedx/client/support/creation/plan-storage-migration.js +7 -0
  330. package/dist/treedx/client/support/creation/request-binary.d.ts +6 -0
  331. package/dist/treedx/client/support/creation/request-binary.js +42 -0
  332. package/dist/treedx/client/support/creation/write-file.d.ts +3 -0
  333. package/dist/treedx/client/support/creation/write-file.js +10 -0
  334. package/dist/treedx/client/support/creation/write-files.d.ts +3 -0
  335. package/dist/treedx/client/support/creation/write-files.js +12 -0
  336. package/dist/treedx/client/support/queries/treedx/artifacts/queries/get-artifact.d.ts +3 -0
  337. package/dist/treedx/client/support/queries/treedx/artifacts/queries/get-artifact.js +7 -0
  338. package/dist/treedx/client/support/queries/treedx/artifacts/queries/list-artifacts.d.ts +3 -0
  339. package/dist/treedx/client/support/queries/treedx/artifacts/queries/list-artifacts.js +7 -0
  340. package/dist/treedx/client/support/queries/treedx/authorization/queries/effective-scope.d.ts +3 -0
  341. package/dist/treedx/client/support/queries/treedx/authorization/queries/effective-scope.js +9 -0
  342. package/dist/treedx/client/support/queries/treedx/authorization/queries/list-capabilities.d.ts +4 -0
  343. package/dist/treedx/client/support/queries/treedx/authorization/queries/list-capabilities.js +6 -0
  344. package/dist/treedx/client/support/queries/treedx/federation/queries/get-placement.d.ts +3 -0
  345. package/dist/treedx/client/support/queries/treedx/federation/queries/get-placement.js +7 -0
  346. package/dist/treedx/client/support/queries/treedx/graph/queries/get-node.d.ts +3 -0
  347. package/dist/treedx/client/support/queries/treedx/graph/queries/get-node.js +7 -0
  348. package/dist/treedx/client/support/queries/treedx/graph/queries/get-related.d.ts +3 -0
  349. package/dist/treedx/client/support/queries/treedx/graph/queries/get-related.js +7 -0
  350. package/dist/treedx/client/support/queries/treedx/graph/queries/list-nodes.d.ts +3 -0
  351. package/dist/treedx/client/support/queries/treedx/graph/queries/list-nodes.js +7 -0
  352. package/dist/treedx/client/support/queries/treedx/repositories/queries/list-tree.d.ts +3 -0
  353. package/dist/treedx/client/support/queries/treedx/repositories/queries/list-tree.js +10 -0
  354. package/dist/treedx/client/support/queries/treedx/repositories/queries/read-file.d.ts +3 -0
  355. package/dist/treedx/client/support/queries/treedx/repositories/queries/read-file.js +9 -0
  356. package/dist/treedx/client/support/queries/treedx/search/queries/get-search-index-status.d.ts +3 -0
  357. package/dist/treedx/client/support/queries/treedx/search/queries/get-search-index-status.js +7 -0
  358. package/dist/treedx/client/support/queries/treedx/storage/queries/get-migration.d.ts +6 -0
  359. package/dist/treedx/client/support/queries/treedx/storage/queries/get-migration.js +7 -0
  360. package/dist/treedx/client/support/queries/treedx/storage/queries/get-snapshot.d.ts +6 -0
  361. package/dist/treedx/client/support/queries/treedx/storage/queries/get-snapshot.js +7 -0
  362. package/dist/treedx/client/support/queries/treedx/storage/queries/list-storage-migrations.d.ts +6 -0
  363. package/dist/treedx/client/support/queries/treedx/storage/queries/list-storage-migrations.js +6 -0
  364. package/dist/treedx/client/support/queries/treedx/transport/queries/list-audit-events.d.ts +15 -0
  365. package/dist/treedx/client/support/queries/treedx/transport/queries/list-audit-events.js +6 -0
  366. package/dist/treedx/client/support/queries/treedx/transport/queries/list-repositories.d.ts +3 -0
  367. package/dist/treedx/client/support/queries/treedx/transport/queries/list-repositories.js +7 -0
  368. package/dist/treedx/client/support/retirement/cleanup-artifacts.d.ts +3 -0
  369. package/dist/treedx/client/support/retirement/cleanup-artifacts.js +7 -0
  370. package/dist/treedx/client/support/retirement/delete-artifact.d.ts +3 -0
  371. package/dist/treedx/client/support/retirement/delete-artifact.js +7 -0
  372. package/dist/treedx/client/support/retirement/delete-file.d.ts +3 -0
  373. package/dist/treedx/client/support/retirement/delete-file.js +10 -0
  374. package/dist/treedx/client/support/retirement/rollback-storage-migration.d.ts +3 -0
  375. package/dist/treedx/client/support/retirement/rollback-storage-migration.js +7 -0
  376. package/dist/treedx/client/support/updates/patch-file.d.ts +3 -0
  377. package/dist/treedx/client/support/updates/patch-file.js +10 -0
  378. package/dist/treedx/client/support/updates/refresh-search-index.d.ts +3 -0
  379. package/dist/treedx/client/support/updates/refresh-search-index.js +8 -0
  380. package/dist/treedx/client/treedx/blobs/contracts/download-blob.d.ts +3 -0
  381. package/dist/treedx/client/treedx/blobs/contracts/download-blob.js +6 -0
  382. package/dist/treedx/client/treedx/blobs/creation/create-blob-upload.d.ts +3 -0
  383. package/dist/treedx/client/treedx/blobs/creation/create-blob-upload.js +8 -0
  384. package/dist/treedx/client/treedx/blobs/creation/request-blob-download.d.ts +3 -0
  385. package/dist/treedx/client/treedx/blobs/creation/request-blob-download.js +27 -0
  386. package/dist/treedx/client/treedx/blobs/creation/request-blob-upload.d.ts +3 -0
  387. package/dist/treedx/client/treedx/blobs/creation/request-blob-upload.js +41 -0
  388. package/dist/treedx/client/treedx/blobs/creation/upload-blob-part.d.ts +3 -0
  389. package/dist/treedx/client/treedx/blobs/creation/upload-blob-part.js +27 -0
  390. package/dist/treedx/client/treedx/blobs/creation/upload-blob.d.ts +3 -0
  391. package/dist/treedx/client/treedx/blobs/creation/upload-blob.js +6 -0
  392. package/dist/treedx/client/treedx/blobs/creation/write-blob.d.ts +3 -0
  393. package/dist/treedx/client/treedx/blobs/creation/write-blob.js +8 -0
  394. package/dist/treedx/client/treedx/blobs/lifecycle/complete-blob-upload.d.ts +3 -0
  395. package/dist/treedx/client/treedx/blobs/lifecycle/complete-blob-upload.js +8 -0
  396. package/dist/treedx/client/treedx/blobs/queries/read-blob.d.ts +3 -0
  397. package/dist/treedx/client/treedx/blobs/queries/read-blob.js +10 -0
  398. package/dist/treedx/client/treedx/blobs/retirement/abort-blob-upload.d.ts +3 -0
  399. package/dist/treedx/client/treedx/blobs/retirement/abort-blob-upload.js +7 -0
  400. package/dist/treedx/client/treedx/blobs/retirement/delete-blob.d.ts +3 -0
  401. package/dist/treedx/client/treedx/blobs/retirement/delete-blob.js +8 -0
  402. package/dist/treedx/client/treedx/federation/contracts/federated-query.d.ts +3 -0
  403. package/dist/treedx/client/treedx/federation/contracts/federated-query.js +7 -0
  404. package/dist/treedx/client/treedx/federation/creation/plan-federated-query.d.ts +3 -0
  405. package/dist/treedx/client/treedx/federation/creation/plan-federated-query.js +6 -0
  406. package/dist/treedx/client/treedx/federation/queries/check-mirror-health.d.ts +3 -0
  407. package/dist/treedx/client/treedx/federation/queries/check-mirror-health.js +7 -0
  408. package/dist/treedx/client/treedx/federation/updates/promote-mirror.d.ts +3 -0
  409. package/dist/treedx/client/treedx/federation/updates/promote-mirror.js +7 -0
  410. package/dist/treedx/client/treedx/federation/updates/sync-mirror.d.ts +3 -0
  411. package/dist/treedx/client/treedx/federation/updates/sync-mirror.js +7 -0
  412. package/dist/treedx/client/treedx/graph/contracts/federated-context.d.ts +3 -0
  413. package/dist/treedx/client/treedx/graph/contracts/federated-context.js +7 -0
  414. package/dist/treedx/client/treedx/graph/contracts/federated-graph.d.ts +3 -0
  415. package/dist/treedx/client/treedx/graph/contracts/federated-graph.js +7 -0
  416. package/dist/treedx/client/treedx/graph/contracts/graph-search.d.ts +3 -0
  417. package/dist/treedx/client/treedx/graph/contracts/graph-search.js +8 -0
  418. package/dist/treedx/client/treedx/graph/queries/get-graph-node.d.ts +3 -0
  419. package/dist/treedx/client/treedx/graph/queries/get-graph-node.js +10 -0
  420. package/dist/treedx/client/treedx/graph/queries/get-graph-refresh-job.d.ts +3 -0
  421. package/dist/treedx/client/treedx/graph/queries/get-graph-refresh-job.js +7 -0
  422. package/dist/treedx/client/treedx/graph/queries/get-subgraph.d.ts +3 -0
  423. package/dist/treedx/client/treedx/graph/queries/get-subgraph.js +7 -0
  424. package/dist/treedx/client/treedx/graph/queries/query-graph.d.ts +3 -0
  425. package/dist/treedx/client/treedx/graph/queries/query-graph.js +7 -0
  426. package/dist/treedx/client/treedx/graph/queries/search-graph-entities.d.ts +3 -0
  427. package/dist/treedx/client/treedx/graph/queries/search-graph-entities.js +6 -0
  428. package/dist/treedx/client/treedx/graph/queries/search-graph-files.d.ts +3 -0
  429. package/dist/treedx/client/treedx/graph/queries/search-graph-files.js +6 -0
  430. package/dist/treedx/client/treedx/graph/queries/search-graph-sections.d.ts +3 -0
  431. package/dist/treedx/client/treedx/graph/queries/search-graph-sections.js +6 -0
  432. package/dist/treedx/client/treedx/graph/updates/refresh-graph.d.ts +3 -0
  433. package/dist/treedx/client/treedx/graph/updates/refresh-graph.js +7 -0
  434. package/dist/treedx/client/treedx/search/contracts/federated-search.d.ts +3 -0
  435. package/dist/treedx/client/treedx/search/contracts/federated-search.js +7 -0
  436. package/dist/treedx/client/treedx/workspaces/creation/create-workspace.d.ts +3 -0
  437. package/dist/treedx/client/treedx/workspaces/creation/create-workspace.js +7 -0
  438. package/dist/treedx/client/treedx/workspaces/retirement/abandon-workspace.d.ts +3 -0
  439. package/dist/treedx/client/treedx/workspaces/retirement/abandon-workspace.js +12 -0
  440. package/dist/treedx/client/treedx/workspaces/retirement/close-workspace.d.ts +2 -0
  441. package/dist/treedx/client/treedx/workspaces/retirement/close-workspace.js +6 -0
  442. package/dist/treedx/generated/openapi-types.d.ts +104 -0
  443. package/dist/treedx/support/client.d.ts +251 -0
  444. package/dist/treedx/support/client.js +252 -0
  445. package/dist/treedx/support/errors.d.ts +13 -0
  446. package/dist/treedx/types/tree-dx-actor.d.ts +209 -0
  447. package/dist/treedx/types/tree-dx-actor.js +8 -0
  448. package/dist/treedx/types/tree-dx-artifact-list-response.d.ts +13 -0
  449. package/dist/treedx/types/tree-dx-artifact-list-response.js +0 -0
  450. package/dist/treedx/types/tree-dx-changeset.d.ts +51 -0
  451. package/dist/treedx/types/tree-dx-changeset.js +6 -0
  452. package/dist/treedx/types/tree-dx-context-request.d.ts +245 -0
  453. package/dist/treedx/types/tree-dx-context-request.js +0 -0
  454. package/dist/treedx/types/tree-dx-exec-result.d.ts +249 -0
  455. package/dist/treedx/types/tree-dx-exec-result.js +0 -0
  456. package/dist/treedx/types/tree-dx-list-tree-request.d.ts +222 -0
  457. package/dist/treedx/types/tree-dx-list-tree-request.js +0 -0
  458. package/dist/treedx/types/tree-dx-push-request.d.ts +229 -0
  459. package/dist/treedx/types/tree-dx-push-request.js +0 -0
  460. package/dist/treedx/types.d.ts +7 -1084
  461. package/dist/treedx/types.js +7 -8
  462. package/dist/types/agents/agent-activity-profile.d.ts +267 -0
  463. package/dist/types/agents/agent-activity-profile.js +0 -0
  464. package/dist/types/agents/agent-trigger-kinds.d.ts +189 -0
  465. package/dist/types/agents/agent-trigger-kinds.js +107 -0
  466. package/dist/types/agents/execution-run-ref.d.ts +136 -0
  467. package/dist/types/agents/execution-run-ref.js +0 -0
  468. package/dist/types/agents.d.ts +3 -493
  469. package/dist/types/agents.js +3 -95
  470. package/package.json +77 -362
  471. package/dist/agent-capacity.d.ts +0 -1100
  472. package/dist/agent-capacity.js +0 -1822
  473. package/dist/agent-tools.d.ts +0 -37
  474. package/dist/agent-tools.js +0 -301
  475. package/dist/api/app.d.ts +0 -8
  476. package/dist/api/app.js +0 -404
  477. package/dist/api/auth/d1-database.d.ts +0 -3
  478. package/dist/api/auth/d1-database.js +0 -20
  479. package/dist/api/auth/d1-provider.d.ts +0 -85
  480. package/dist/api/auth/d1-provider.js +0 -95
  481. package/dist/api/auth/d1-store.d.ts +0 -121
  482. package/dist/api/auth/d1-store.js +0 -990
  483. package/dist/api/auth/memory-provider.d.ts +0 -82
  484. package/dist/api/auth/memory-provider.js +0 -297
  485. package/dist/api/auth/rbac.d.ts +0 -22
  486. package/dist/api/auth/rbac.js +0 -162
  487. package/dist/api/auth/tokens.d.ts +0 -18
  488. package/dist/api/auth/tokens.js +0 -56
  489. package/dist/api/config.d.ts +0 -4
  490. package/dist/api/config.js +0 -149
  491. package/dist/api/http.d.ts +0 -28
  492. package/dist/api/http.js +0 -51
  493. package/dist/api/index.d.ts +0 -10
  494. package/dist/api/index.js +0 -29
  495. package/dist/api/operations-routes.d.ts +0 -11
  496. package/dist/api/operations-routes.js +0 -39
  497. package/dist/api/operations.d.ts +0 -3
  498. package/dist/api/operations.js +0 -26
  499. package/dist/api/providers.d.ts +0 -2
  500. package/dist/api/providers.js +0 -85
  501. package/dist/api/railway.d.ts +0 -53
  502. package/dist/api/railway.js +0 -71
  503. package/dist/api/sdk-dispatch.d.ts +0 -6
  504. package/dist/api/sdk-dispatch.js +0 -14
  505. package/dist/api/sdk-routes.d.ts +0 -11
  506. package/dist/api/sdk-routes.js +0 -29
  507. package/dist/api/templates.d.ts +0 -3
  508. package/dist/api/templates.js +0 -31
  509. package/dist/api/types.d.ts +0 -238
  510. package/dist/capacity-provider.d.ts +0 -494
  511. package/dist/capacity-provider.js +0 -727
  512. package/dist/capacity.d.ts +0 -483
  513. package/dist/capacity.js +0 -2331
  514. package/dist/cli-tools.d.ts +0 -3
  515. package/dist/cli-tools.js +0 -46
  516. package/dist/content-operations.d.ts +0 -97
  517. package/dist/content-operations.js +0 -250
  518. package/dist/content-store.d.ts +0 -25
  519. package/dist/content-store.js +0 -269
  520. package/dist/control-plane-client.d.ts +0 -203
  521. package/dist/control-plane-client.js +0 -540
  522. package/dist/control-plane.d.ts +0 -101
  523. package/dist/control-plane.js +0 -201
  524. package/dist/copilot.d.ts +0 -18
  525. package/dist/copilot.js +0 -90
  526. package/dist/d1-http.d.ts +0 -38
  527. package/dist/d1-http.js +0 -95
  528. package/dist/d1-store.d.ts +0 -336
  529. package/dist/d1-store.js +0 -1431
  530. package/dist/db/d1.d.ts +0 -246
  531. package/dist/db/d1.js +0 -8
  532. package/dist/db/index.d.ts +0 -3
  533. package/dist/db/index.js +0 -3
  534. package/dist/db/market-schema.d.ts +0 -83651
  535. package/dist/db/market-schema.js +0 -3725
  536. package/dist/db/node-sqlite.d.ts +0 -297
  537. package/dist/db/node-sqlite.js +0 -133
  538. package/dist/db/schema.d.ts +0 -483
  539. package/dist/db/schema.js +0 -29
  540. package/dist/dispatch.d.ts +0 -4
  541. package/dist/dispatch.js +0 -174
  542. package/dist/field-aliases.d.ts +0 -11
  543. package/dist/fixture-support.d.ts +0 -24
  544. package/dist/fixture-support.js +0 -385
  545. package/dist/frontmatter.d.ts +0 -6
  546. package/dist/frontmatter.js +0 -33
  547. package/dist/git-runtime.d.ts +0 -16
  548. package/dist/git-runtime.js +0 -69
  549. package/dist/governance.d.ts +0 -133
  550. package/dist/governance.js +0 -285
  551. package/dist/graph/build.d.ts +0 -19
  552. package/dist/graph/build.js +0 -949
  553. package/dist/graph/dsl.d.ts +0 -2
  554. package/dist/graph/dsl.js +0 -243
  555. package/dist/graph/query.d.ts +0 -47
  556. package/dist/graph/query.js +0 -447
  557. package/dist/graph/ranking.d.ts +0 -3
  558. package/dist/graph/ranking.js +0 -483
  559. package/dist/graph/schema.d.ts +0 -142
  560. package/dist/graph/schema.js +0 -137
  561. package/dist/graph.d.ts +0 -52
  562. package/dist/graph.js +0 -133
  563. package/dist/guarantees/index.d.ts +0 -512
  564. package/dist/guarantees/index.js +0 -1782
  565. package/dist/hosting/apps.d.ts +0 -12
  566. package/dist/hosting/apps.js +0 -107
  567. package/dist/hosting/builtins.d.ts +0 -25
  568. package/dist/hosting/builtins.js +0 -685
  569. package/dist/hosting/contracts.d.ts +0 -190
  570. package/dist/hosting/graph.d.ts +0 -110
  571. package/dist/hosting/graph.js +0 -993
  572. package/dist/hosting/index.d.ts +0 -4
  573. package/dist/hosting/index.js +0 -4
  574. package/dist/index.d.ts +0 -88
  575. package/dist/index.js +0 -757
  576. package/dist/local-dev/managed-dev.d.ts +0 -85
  577. package/dist/local-dev/managed-dev.js +0 -431
  578. package/dist/managed-dependencies.d.ts +0 -91
  579. package/dist/managed-dependencies.js +0 -1186
  580. package/dist/market-client.d.ts +0 -831
  581. package/dist/market-client.js +0 -1219
  582. package/dist/model-registry.d.ts +0 -8
  583. package/dist/model-registry.js +0 -674
  584. package/dist/operations/agent-tools.d.ts +0 -105
  585. package/dist/operations/agent-tools.js +0 -171
  586. package/dist/operations/providers/default.d.ts +0 -10
  587. package/dist/operations/providers/default.js +0 -1245
  588. package/dist/operations/repository-operations.d.ts +0 -158
  589. package/dist/operations/repository-operations.js +0 -851
  590. package/dist/operations/runtime.d.ts +0 -7
  591. package/dist/operations/runtime.js +0 -61
  592. package/dist/operations/services/bootstrap-runner.d.ts +0 -39
  593. package/dist/operations/services/bootstrap-runner.js +0 -191
  594. package/dist/operations/services/build-warning-policy.d.ts +0 -34
  595. package/dist/operations/services/build-warning-policy.js +0 -91
  596. package/dist/operations/services/commit-message-provider.d.ts +0 -65
  597. package/dist/operations/services/commit-message-provider.js +0 -496
  598. package/dist/operations/services/config-runtime.d.ts +0 -558
  599. package/dist/operations/services/config-runtime.js +0 -3494
  600. package/dist/operations/services/d1-migration.d.ts +0 -6
  601. package/dist/operations/services/d1-migration.js +0 -120
  602. package/dist/operations/services/deploy.d.ts +0 -645
  603. package/dist/operations/services/deploy.js +0 -3826
  604. package/dist/operations/services/deployment-readiness.d.ts +0 -30
  605. package/dist/operations/services/deployment-readiness.js +0 -217
  606. package/dist/operations/services/export-runtime.d.ts +0 -18
  607. package/dist/operations/services/export-runtime.js +0 -140
  608. package/dist/operations/services/git-remote-policy.d.ts +0 -9
  609. package/dist/operations/services/git-remote-policy.js +0 -63
  610. package/dist/operations/services/git-runner.d.ts +0 -68
  611. package/dist/operations/services/git-runner.js +0 -500
  612. package/dist/operations/services/git-workflow.d.ts +0 -255
  613. package/dist/operations/services/git-workflow.js +0 -845
  614. package/dist/operations/services/github-actions-verification.d.ts +0 -148
  615. package/dist/operations/services/github-actions-verification.js +0 -589
  616. package/dist/operations/services/github-api.d.ts +0 -279
  617. package/dist/operations/services/github-api.js +0 -936
  618. package/dist/operations/services/github-automation.d.ts +0 -230
  619. package/dist/operations/services/github-automation.js +0 -520
  620. package/dist/operations/services/github-credentials.d.ts +0 -13
  621. package/dist/operations/services/github-credentials.js +0 -59
  622. package/dist/operations/services/hosted-service-checks.d.ts +0 -82
  623. package/dist/operations/services/hosted-service-checks.js +0 -527
  624. package/dist/operations/services/hosting-audit.d.ts +0 -69
  625. package/dist/operations/services/hosting-audit.js +0 -638
  626. package/dist/operations/services/hub-launch.d.ts +0 -182
  627. package/dist/operations/services/hub-launch.js +0 -309
  628. package/dist/operations/services/hub-provider-launch.d.ts +0 -160
  629. package/dist/operations/services/hub-provider-launch.js +0 -1056
  630. package/dist/operations/services/key-agent.d.ts +0 -137
  631. package/dist/operations/services/key-agent.js +0 -641
  632. package/dist/operations/services/live-hosted-service-checks.d.ts +0 -30
  633. package/dist/operations/services/live-hosted-service-checks.js +0 -611
  634. package/dist/operations/services/local-cleanup.d.ts +0 -30
  635. package/dist/operations/services/local-cleanup.js +0 -77
  636. package/dist/operations/services/local-dev.d.ts +0 -8
  637. package/dist/operations/services/local-dev.js +0 -97
  638. package/dist/operations/services/managed-host-security.d.ts +0 -13
  639. package/dist/operations/services/managed-host-security.js +0 -56
  640. package/dist/operations/services/managed-repositories.d.ts +0 -37
  641. package/dist/operations/services/managed-repositories.js +0 -177
  642. package/dist/operations/services/market-packaging.d.ts +0 -59
  643. package/dist/operations/services/market-packaging.js +0 -234
  644. package/dist/operations/services/operations-runner-smoke.d.ts +0 -31
  645. package/dist/operations/services/operations-runner-smoke.js +0 -212
  646. package/dist/operations/services/package-adapters.d.ts +0 -184
  647. package/dist/operations/services/package-adapters.js +0 -912
  648. package/dist/operations/services/package-artifacts.d.ts +0 -37
  649. package/dist/operations/services/package-artifacts.js +0 -99
  650. package/dist/operations/services/package-reference-policy.d.ts +0 -64
  651. package/dist/operations/services/package-reference-policy.js +0 -364
  652. package/dist/operations/services/project-host-operations.d.ts +0 -153
  653. package/dist/operations/services/project-host-operations.js +0 -365
  654. package/dist/operations/services/project-platform.d.ts +0 -727
  655. package/dist/operations/services/project-platform.js +0 -1603
  656. package/dist/operations/services/project-web-monitor.d.ts +0 -15
  657. package/dist/operations/services/project-web-monitor.js +0 -377
  658. package/dist/operations/services/railway-api.d.ts +0 -494
  659. package/dist/operations/services/railway-api.js +0 -1874
  660. package/dist/operations/services/railway-cli.d.ts +0 -47
  661. package/dist/operations/services/railway-cli.js +0 -142
  662. package/dist/operations/services/railway-deploy.d.ts +0 -161
  663. package/dist/operations/services/railway-deploy.js +0 -1808
  664. package/dist/operations/services/railway-source-policy.d.ts +0 -25
  665. package/dist/operations/services/railway-source-policy.js +0 -111
  666. package/dist/operations/services/release-history.d.ts +0 -59
  667. package/dist/operations/services/release-history.js +0 -158
  668. package/dist/operations/services/release-proof-ledger.d.ts +0 -13
  669. package/dist/operations/services/release-proof-ledger.js +0 -81
  670. package/dist/operations/services/release-proof-planner.d.ts +0 -48
  671. package/dist/operations/services/release-proof-planner.js +0 -195
  672. package/dist/operations/services/release-proof-runner.d.ts +0 -16
  673. package/dist/operations/services/release-proof-runner.js +0 -169
  674. package/dist/operations/services/release-proof.d.ts +0 -81
  675. package/dist/operations/services/release-proof.js +0 -79
  676. package/dist/operations/services/repository-save-orchestrator.d.ts +0 -193
  677. package/dist/operations/services/repository-save-orchestrator.js +0 -2110
  678. package/dist/operations/services/runtime-paths.d.ts +0 -19
  679. package/dist/operations/services/runtime-paths.js +0 -54
  680. package/dist/operations/services/runtime-tools.d.ts +0 -35
  681. package/dist/operations/services/runtime-tools.js +0 -212
  682. package/dist/operations/services/save-deploy-preflight.d.ts +0 -32
  683. package/dist/operations/services/save-deploy-preflight.js +0 -82
  684. package/dist/operations/services/template-host-bindings.d.ts +0 -68
  685. package/dist/operations/services/template-host-bindings.js +0 -401
  686. package/dist/operations/services/template-registry.d.ts +0 -110
  687. package/dist/operations/services/template-registry.js +0 -595
  688. package/dist/operations/services/template-secret-sync.d.ts +0 -97
  689. package/dist/operations/services/template-secret-sync.js +0 -292
  690. package/dist/operations/services/verification-cache.d.ts +0 -25
  691. package/dist/operations/services/verification-cache.js +0 -71
  692. package/dist/operations/services/watch-dev.d.ts +0 -21
  693. package/dist/operations/services/watch-dev.js +0 -282
  694. package/dist/operations/services/workflow-timing.d.ts +0 -25
  695. package/dist/operations/services/workflow-timing.js +0 -79
  696. package/dist/operations/services/workspace-dependency-mode.d.ts +0 -74
  697. package/dist/operations/services/workspace-dependency-mode.js +0 -478
  698. package/dist/operations/services/workspace-preflight.d.ts +0 -40
  699. package/dist/operations/services/workspace-preflight.js +0 -172
  700. package/dist/operations/services/workspace-save-script.d.ts +0 -26
  701. package/dist/operations/services/workspace-save-script.js +0 -50
  702. package/dist/operations/services/workspace-save.d.ts +0 -76
  703. package/dist/operations/services/workspace-save.js +0 -453
  704. package/dist/operations/services/workspace-tools.d.ts +0 -17
  705. package/dist/operations/services/workspace-tools.js +0 -320
  706. package/dist/operations-registry.d.ts +0 -5
  707. package/dist/operations-registry.js +0 -98
  708. package/dist/operations-types.d.ts +0 -75
  709. package/dist/operations-types.js +0 -17
  710. package/dist/operations.d.ts +0 -17
  711. package/dist/operations.js +0 -114
  712. package/dist/platform/book-export.d.ts +0 -78
  713. package/dist/platform/book-export.js +0 -451
  714. package/dist/platform/books-data.d.ts +0 -28
  715. package/dist/platform/books-data.js +0 -111
  716. package/dist/platform/config.d.ts +0 -27
  717. package/dist/platform/config.js +0 -100
  718. package/dist/platform/content-runtime-source.d.ts +0 -54
  719. package/dist/platform/content-runtime-source.js +0 -169
  720. package/dist/platform/contracts.d.ts +0 -361
  721. package/dist/platform/deploy-config.d.ts +0 -17
  722. package/dist/platform/deploy-config.js +0 -731
  723. package/dist/platform/deploy-runtime.d.ts +0 -22
  724. package/dist/platform/deploy-runtime.js +0 -93
  725. package/dist/platform/desired-state.d.ts +0 -66
  726. package/dist/platform/desired-state.js +0 -1071
  727. package/dist/platform/env.yaml +0 -1126
  728. package/dist/platform/environment.d.ts +0 -159
  729. package/dist/platform/environment.js +0 -778
  730. package/dist/platform/local-content-materialization.d.ts +0 -9
  731. package/dist/platform/local-content-materialization.js +0 -212
  732. package/dist/platform/plugin.d.ts +0 -103
  733. package/dist/platform/plugin.js +0 -6
  734. package/dist/platform/plugins/constants.d.ts +0 -26
  735. package/dist/platform/plugins/constants.js +0 -33
  736. package/dist/platform/plugins/runtime.d.ts +0 -41
  737. package/dist/platform/plugins/runtime.js +0 -257
  738. package/dist/platform/plugins.d.ts +0 -6
  739. package/dist/platform/plugins.js +0 -42
  740. package/dist/platform/published-content-pipeline.d.ts +0 -84
  741. package/dist/platform/published-content-pipeline.js +0 -547
  742. package/dist/platform/published-content.d.ts +0 -224
  743. package/dist/platform/published-content.js +0 -611
  744. package/dist/platform/site-config-schema.d.ts +0 -1
  745. package/dist/platform/site-config-schema.js +0 -4
  746. package/dist/platform/tenant/runtime-config.d.ts +0 -154
  747. package/dist/platform/tenant/runtime-config.js +0 -69
  748. package/dist/platform/tenant-config.d.ts +0 -8
  749. package/dist/platform/tenant-config.js +0 -207
  750. package/dist/platform/utils/site-config-schema.d.ts +0 -154
  751. package/dist/platform/utils/site-config-schema.js +0 -450
  752. package/dist/platform-operation-store.d.ts +0 -94
  753. package/dist/platform-operation-store.js +0 -531
  754. package/dist/platform-operations.d.ts +0 -273
  755. package/dist/platform-operations.js +0 -440
  756. package/dist/plugin-default.d.ts +0 -28
  757. package/dist/plugin-default.js +0 -55
  758. package/dist/project-import.d.ts +0 -91
  759. package/dist/project-import.js +0 -257
  760. package/dist/project-workflow.d.ts +0 -233
  761. package/dist/project-workflow.js +0 -82
  762. package/dist/reconcile/bootstrap-systems.d.ts +0 -32
  763. package/dist/reconcile/bootstrap-systems.js +0 -175
  764. package/dist/reconcile/builtin-adapters.d.ts +0 -9
  765. package/dist/reconcile/builtin-adapters.js +0 -5545
  766. package/dist/reconcile/contracts.d.ts +0 -172
  767. package/dist/reconcile/desired-state.d.ts +0 -10
  768. package/dist/reconcile/desired-state.js +0 -322
  769. package/dist/reconcile/engine.d.ts +0 -118
  770. package/dist/reconcile/engine.js +0 -645
  771. package/dist/reconcile/errors.d.ts +0 -5
  772. package/dist/reconcile/errors.js +0 -13
  773. package/dist/reconcile/index.d.ts +0 -10
  774. package/dist/reconcile/index.js +0 -10
  775. package/dist/reconcile/live-acceptance.d.ts +0 -100
  776. package/dist/reconcile/live-acceptance.js +0 -2018
  777. package/dist/reconcile/platform.d.ts +0 -104
  778. package/dist/reconcile/platform.js +0 -100
  779. package/dist/reconcile/providers/docker-private.d.ts +0 -54
  780. package/dist/reconcile/providers/docker-private.js +0 -101
  781. package/dist/reconcile/providers/github-private.d.ts +0 -69
  782. package/dist/reconcile/providers/github-private.js +0 -145
  783. package/dist/reconcile/providers/local-private.d.ts +0 -28
  784. package/dist/reconcile/providers/local-private.js +0 -75
  785. package/dist/reconcile/providers/railway-iac.d.ts +0 -220
  786. package/dist/reconcile/providers/railway-iac.js +0 -621
  787. package/dist/reconcile/providers/release-private.d.ts +0 -89
  788. package/dist/reconcile/providers/release-private.js +0 -140
  789. package/dist/reconcile/registry.d.ts +0 -7
  790. package/dist/reconcile/registry.js +0 -79
  791. package/dist/reconcile/state.d.ts +0 -7
  792. package/dist/reconcile/state.js +0 -270
  793. package/dist/reconcile/units.d.ts +0 -6
  794. package/dist/reconcile/units.js +0 -72
  795. package/dist/remote.d.ts +0 -244
  796. package/dist/remote.js +0 -284
  797. package/dist/scenes/artifacts.d.ts +0 -16
  798. package/dist/scenes/artifacts.js +0 -61
  799. package/dist/scenes/auth.d.ts +0 -2
  800. package/dist/scenes/auth.js +0 -28
  801. package/dist/scenes/base-url.d.ts +0 -12
  802. package/dist/scenes/base-url.js +0 -123
  803. package/dist/scenes/builtin-plugins.d.ts +0 -2
  804. package/dist/scenes/builtin-plugins.js +0 -499
  805. package/dist/scenes/checkpoints.d.ts +0 -14
  806. package/dist/scenes/checkpoints.js +0 -33
  807. package/dist/scenes/device-matrix.d.ts +0 -2
  808. package/dist/scenes/device-matrix.js +0 -100
  809. package/dist/scenes/devices.d.ts +0 -11
  810. package/dist/scenes/devices.js +0 -40
  811. package/dist/scenes/diagnostics.d.ts +0 -5
  812. package/dist/scenes/diagnostics.js +0 -22
  813. package/dist/scenes/diagram-providers.d.ts +0 -2
  814. package/dist/scenes/diagram-providers.js +0 -181
  815. package/dist/scenes/diagram-validation.d.ts +0 -22
  816. package/dist/scenes/diagram-validation.js +0 -74
  817. package/dist/scenes/environment.d.ts +0 -2
  818. package/dist/scenes/environment.js +0 -65
  819. package/dist/scenes/evidence-bundle.d.ts +0 -5
  820. package/dist/scenes/evidence-bundle.js +0 -42
  821. package/dist/scenes/evidence-report.d.ts +0 -10
  822. package/dist/scenes/evidence-report.js +0 -73
  823. package/dist/scenes/evidence.d.ts +0 -16
  824. package/dist/scenes/evidence.js +0 -277
  825. package/dist/scenes/index.d.ts +0 -48
  826. package/dist/scenes/index.js +0 -312
  827. package/dist/scenes/inspect.d.ts +0 -9
  828. package/dist/scenes/inspect.js +0 -64
  829. package/dist/scenes/loader.d.ts +0 -3
  830. package/dist/scenes/loader.js +0 -38
  831. package/dist/scenes/logs.d.ts +0 -2
  832. package/dist/scenes/logs.js +0 -47
  833. package/dist/scenes/operations.d.ts +0 -3
  834. package/dist/scenes/operations.js +0 -128
  835. package/dist/scenes/phase0.d.ts +0 -9
  836. package/dist/scenes/phase0.js +0 -637
  837. package/dist/scenes/planner.d.ts +0 -12
  838. package/dist/scenes/planner.js +0 -166
  839. package/dist/scenes/playwright-adapter.d.ts +0 -2
  840. package/dist/scenes/playwright-adapter.js +0 -63
  841. package/dist/scenes/plugins.d.ts +0 -5
  842. package/dist/scenes/plugins.js +0 -115
  843. package/dist/scenes/progress.d.ts +0 -17
  844. package/dist/scenes/progress.js +0 -24
  845. package/dist/scenes/publish-destinations.d.ts +0 -12
  846. package/dist/scenes/publish-destinations.js +0 -99
  847. package/dist/scenes/publish-plan-report.d.ts +0 -10
  848. package/dist/scenes/publish-plan-report.js +0 -70
  849. package/dist/scenes/publish-plan.d.ts +0 -15
  850. package/dist/scenes/publish-plan.js +0 -248
  851. package/dist/scenes/publish-redaction.d.ts +0 -16
  852. package/dist/scenes/publish-redaction.js +0 -148
  853. package/dist/scenes/publish-release-record.d.ts +0 -13
  854. package/dist/scenes/publish-release-record.js +0 -34
  855. package/dist/scenes/publish-report.d.ts +0 -10
  856. package/dist/scenes/publish-report.js +0 -67
  857. package/dist/scenes/publish.d.ts +0 -16
  858. package/dist/scenes/publish.js +0 -298
  859. package/dist/scenes/registry.d.ts +0 -12
  860. package/dist/scenes/registry.js +0 -65
  861. package/dist/scenes/remotion-adapter.d.ts +0 -3
  862. package/dist/scenes/remotion-adapter.js +0 -94
  863. package/dist/scenes/remotion-composition-registry.d.ts +0 -2
  864. package/dist/scenes/remotion-composition-registry.js +0 -12
  865. package/dist/scenes/remotion-compositions.d.ts +0 -15
  866. package/dist/scenes/remotion-compositions.js +0 -464
  867. package/dist/scenes/remotion-diagrams.d.ts +0 -9
  868. package/dist/scenes/remotion-diagrams.js +0 -188
  869. package/dist/scenes/remotion-input.d.ts +0 -13
  870. package/dist/scenes/remotion-input.js +0 -291
  871. package/dist/scenes/remotion-visuals.d.ts +0 -29
  872. package/dist/scenes/remotion-visuals.js +0 -198
  873. package/dist/scenes/render-media-assets.d.ts +0 -9
  874. package/dist/scenes/render-media-assets.js +0 -117
  875. package/dist/scenes/render-report.d.ts +0 -10
  876. package/dist/scenes/render-report.js +0 -27
  877. package/dist/scenes/render.d.ts +0 -2
  878. package/dist/scenes/render.js +0 -218
  879. package/dist/scenes/reporter.d.ts +0 -3
  880. package/dist/scenes/reporter.js +0 -101
  881. package/dist/scenes/resume.d.ts +0 -2
  882. package/dist/scenes/resume.js +0 -79
  883. package/dist/scenes/runner.d.ts +0 -2
  884. package/dist/scenes/runner.js +0 -687
  885. package/dist/scenes/schema.d.ts +0 -6
  886. package/dist/scenes/schema.js +0 -1023
  887. package/dist/scenes/seed.d.ts +0 -2
  888. package/dist/scenes/seed.js +0 -83
  889. package/dist/scenes/segments.d.ts +0 -15
  890. package/dist/scenes/segments.js +0 -79
  891. package/dist/scenes/selectors.d.ts +0 -3
  892. package/dist/scenes/selectors.js +0 -21
  893. package/dist/scenes/timeline.d.ts +0 -11
  894. package/dist/scenes/timeline.js +0 -26
  895. package/dist/scenes/timeouts.d.ts +0 -6
  896. package/dist/scenes/timeouts.js +0 -17
  897. package/dist/scenes/training-captions.d.ts +0 -14
  898. package/dist/scenes/training-captions.js +0 -98
  899. package/dist/scenes/training-report.d.ts +0 -10
  900. package/dist/scenes/training-report.js +0 -78
  901. package/dist/scenes/training-transcript.d.ts +0 -24
  902. package/dist/scenes/training-transcript.js +0 -204
  903. package/dist/scenes/training.d.ts +0 -10
  904. package/dist/scenes/training.js +0 -134
  905. package/dist/scenes/types.d.ts +0 -1900
  906. package/dist/scenes/types.js +0 -8
  907. package/dist/scenes/visual-audit-contact-sheets.d.ts +0 -6
  908. package/dist/scenes/visual-audit-contact-sheets.js +0 -119
  909. package/dist/scenes/visual-audit-fixtures.d.ts +0 -25
  910. package/dist/scenes/visual-audit-fixtures.js +0 -247
  911. package/dist/scenes/visual-audit-report.d.ts +0 -11
  912. package/dist/scenes/visual-audit-report.js +0 -85
  913. package/dist/scenes/visual-audit-review.d.ts +0 -23
  914. package/dist/scenes/visual-audit-review.js +0 -829
  915. package/dist/scenes/visual-audit-routes.d.ts +0 -13
  916. package/dist/scenes/visual-audit-routes.js +0 -308
  917. package/dist/scenes/visual-audit.d.ts +0 -3
  918. package/dist/scenes/visual-audit.js +0 -596
  919. package/dist/scripts/aggregate-book.js +0 -16
  920. package/dist/scripts/assert-release-tag-version.js +0 -23
  921. package/dist/scripts/build-dist.js +0 -294
  922. package/dist/scripts/build-tenant-worker.js +0 -36
  923. package/dist/scripts/check-build-warnings.js +0 -51
  924. package/dist/scripts/cleanup-markdown.js +0 -377
  925. package/dist/scripts/cli-test-fixtures.js +0 -44
  926. package/dist/scripts/config-treeseed.js +0 -131
  927. package/dist/scripts/deployment-readiness.js +0 -20
  928. package/dist/scripts/generate-treedx-openapi-types.js +0 -186
  929. package/dist/scripts/install-managed-dependencies.js +0 -12
  930. package/dist/scripts/key-agent.js +0 -165
  931. package/dist/scripts/local-dev.js +0 -129
  932. package/dist/scripts/migrate-journey-csv-to-guarantees.js +0 -140
  933. package/dist/scripts/operations-runner-smoke.js +0 -16
  934. package/dist/scripts/package-tools.js +0 -85
  935. package/dist/scripts/patch-starlight-content-path.js +0 -173
  936. package/dist/scripts/prepare.js +0 -10
  937. package/dist/scripts/publish-package.js +0 -29
  938. package/dist/scripts/release-verify.js +0 -105
  939. package/dist/scripts/run-fixture-astro-command.js +0 -18
  940. package/dist/scripts/scaffold-site.js +0 -66
  941. package/dist/scripts/sync-template.js +0 -20
  942. package/dist/scripts/template-catalog.test.js +0 -86
  943. package/dist/scripts/template-command.js +0 -31
  944. package/dist/scripts/tenant-astro-command.js +0 -3
  945. package/dist/scripts/tenant-build.js +0 -48
  946. package/dist/scripts/tenant-check.js +0 -10
  947. package/dist/scripts/tenant-d1-migrate-local.js +0 -15
  948. package/dist/scripts/tenant-deploy.js +0 -220
  949. package/dist/scripts/tenant-destroy.js +0 -112
  950. package/dist/scripts/tenant-dev.js +0 -160
  951. package/dist/scripts/tenant-lint.js +0 -4
  952. package/dist/scripts/tenant-test.js +0 -4
  953. package/dist/scripts/tenant-workflow-action.js +0 -101
  954. package/dist/scripts/test-cloudflare-local.js +0 -209
  955. package/dist/scripts/test-scaffold.js +0 -300
  956. package/dist/scripts/test-smoke.js +0 -137
  957. package/dist/scripts/treeseed-assert-release-tag-version.js +0 -21
  958. package/dist/scripts/treeseed-build-dist.js +0 -131
  959. package/dist/scripts/treeseed-publish-package.js +0 -19
  960. package/dist/scripts/treeseed-release-verify.js +0 -131
  961. package/dist/scripts/validate-templates.js +0 -6
  962. package/dist/scripts/verify-driver.js +0 -45
  963. package/dist/scripts/workflow-commands.test.js +0 -31
  964. package/dist/scripts/workspace-command-e2e.js +0 -718
  965. package/dist/scripts/workspace-lint.js +0 -15
  966. package/dist/scripts/workspace-preflight.js +0 -22
  967. package/dist/scripts/workspace-publish-changed-packages.js +0 -16
  968. package/dist/scripts/workspace-release-test.js +0 -104
  969. package/dist/scripts/workspace-release-verify.js +0 -81
  970. package/dist/scripts/workspace-save.js +0 -64
  971. package/dist/scripts/workspace-start-warning.js +0 -3
  972. package/dist/scripts/workspace-test-unit.js +0 -4
  973. package/dist/scripts/workspace-test.js +0 -17
  974. package/dist/sdk-dispatch.d.ts +0 -12
  975. package/dist/sdk-dispatch.js +0 -126
  976. package/dist/sdk-fields.d.ts +0 -11
  977. package/dist/sdk-filters.d.ts +0 -4
  978. package/dist/sdk-filters.js +0 -74
  979. package/dist/sdk-types.d.ts +0 -3868
  980. package/dist/sdk-types.js +0 -542
  981. package/dist/sdk-version.d.ts +0 -2
  982. package/dist/sdk-version.js +0 -42
  983. package/dist/sdk.d.ts +0 -266
  984. package/dist/sdk.js +0 -825
  985. package/dist/secrets-capability.d.ts +0 -421
  986. package/dist/secrets-capability.js +0 -530
  987. package/dist/seeds/errors.d.ts +0 -5
  988. package/dist/seeds/errors.js +0 -22
  989. package/dist/seeds/index.d.ts +0 -20
  990. package/dist/seeds/index.js +0 -53
  991. package/dist/seeds/loader.d.ts +0 -8
  992. package/dist/seeds/loader.js +0 -32
  993. package/dist/seeds/normalize.d.ts +0 -13
  994. package/dist/seeds/normalize.js +0 -282
  995. package/dist/seeds/planner.d.ts +0 -10
  996. package/dist/seeds/planner.js +0 -149
  997. package/dist/seeds/schema.d.ts +0 -2
  998. package/dist/seeds/schema.js +0 -893
  999. package/dist/seeds/types.d.ts +0 -312
  1000. package/dist/seeds/types.js +0 -12
  1001. package/dist/service-credentials.d.ts +0 -54
  1002. package/dist/service-credentials.js +0 -112
  1003. package/dist/stores/cursor-store.d.ts +0 -10
  1004. package/dist/stores/cursor-store.js +0 -164
  1005. package/dist/stores/envelopes.d.ts +0 -116
  1006. package/dist/stores/envelopes.js +0 -219
  1007. package/dist/stores/helpers.d.ts +0 -12
  1008. package/dist/stores/helpers.js +0 -42
  1009. package/dist/stores/lease-store.d.ts +0 -18
  1010. package/dist/stores/lease-store.js +0 -189
  1011. package/dist/stores/message-store.d.ts +0 -12
  1012. package/dist/stores/message-store.js +0 -273
  1013. package/dist/stores/operational-store.d.ts +0 -55
  1014. package/dist/stores/operational-store.js +0 -861
  1015. package/dist/stores/project-workflow-store.d.ts +0 -56
  1016. package/dist/stores/project-workflow-store.js +0 -482
  1017. package/dist/stores/run-store.d.ts +0 -9
  1018. package/dist/stores/run-store.js +0 -75
  1019. package/dist/stores/subscription-store.d.ts +0 -8
  1020. package/dist/stores/subscription-store.js +0 -73
  1021. package/dist/template-catalog.d.ts +0 -13
  1022. package/dist/template-catalog.js +0 -151
  1023. package/dist/template-launch-requirements.d.ts +0 -118
  1024. package/dist/template-launch-requirements.js +0 -768
  1025. package/dist/template-launch-ui.d.ts +0 -85
  1026. package/dist/template-launch-ui.js +0 -189
  1027. package/dist/timing.d.ts +0 -20
  1028. package/dist/timing.js +0 -73
  1029. package/dist/treedx/adapters.d.ts +0 -6
  1030. package/dist/treedx/adapters.js +0 -36
  1031. package/dist/treedx/client.d.ts +0 -222
  1032. package/dist/treedx/client.js +0 -871
  1033. package/dist/treedx/errors.d.ts +0 -13
  1034. package/dist/treedx/federated-client.d.ts +0 -27
  1035. package/dist/treedx/federated-client.js +0 -158
  1036. package/dist/treedx/graph-adapter.d.ts +0 -33
  1037. package/dist/treedx/graph-adapter.js +0 -156
  1038. package/dist/treedx/index.d.ts +0 -14
  1039. package/dist/treedx/index.js +0 -48
  1040. package/dist/treedx/market-integration.d.ts +0 -27
  1041. package/dist/treedx/market-integration.js +0 -131
  1042. package/dist/treedx/ports.d.ts +0 -166
  1043. package/dist/treedx/ports.js +0 -231
  1044. package/dist/treedx/query-adapter.d.ts +0 -19
  1045. package/dist/treedx/query-adapter.js +0 -62
  1046. package/dist/treedx/registry-client.d.ts +0 -11
  1047. package/dist/treedx/registry-client.js +0 -19
  1048. package/dist/treedx/repository-adapter.d.ts +0 -45
  1049. package/dist/treedx/repository-adapter.js +0 -319
  1050. package/dist/treedx/sdk-integration.d.ts +0 -27
  1051. package/dist/treedx/sdk-integration.js +0 -63
  1052. package/dist/treedx/workspace-adapter.d.ts +0 -27
  1053. package/dist/treedx/workspace-adapter.js +0 -65
  1054. package/dist/treedx-backends.d.ts +0 -220
  1055. package/dist/treedx-backends.js +0 -634
  1056. package/dist/treedx-client.d.ts +0 -89
  1057. package/dist/treedx-client.js +0 -184
  1058. package/dist/treeseed/services/compose.yml +0 -6
  1059. package/dist/treeseed/template-catalog/catalog.fixture.json +0 -707
  1060. package/dist/types/cloudflare.d.ts +0 -54
  1061. package/dist/verification.d.ts +0 -31
  1062. package/dist/verification.js +0 -430
  1063. package/dist/workflow/operations.d.ts +0 -1516
  1064. package/dist/workflow/operations.js +0 -7001
  1065. package/dist/workflow/policy.d.ts +0 -12
  1066. package/dist/workflow/policy.js +0 -70
  1067. package/dist/workflow/runs.d.ts +0 -143
  1068. package/dist/workflow/runs.js +0 -720
  1069. package/dist/workflow/session.d.ts +0 -34
  1070. package/dist/workflow/session.js +0 -160
  1071. package/dist/workflow/worktrees.d.ts +0 -43
  1072. package/dist/workflow/worktrees.js +0 -307
  1073. package/dist/workflow-state.d.ts +0 -250
  1074. package/dist/workflow-state.js +0 -844
  1075. package/dist/workflow-support.d.ts +0 -28
  1076. package/dist/workflow-support.js +0 -390
  1077. package/dist/workflow.d.ts +0 -327
  1078. package/dist/workflow.js +0 -140
  1079. package/drizzle/d1/0000_treeseed_d1.sql +0 -19
  1080. package/drizzle/market/0000_market_control_plane.sql +0 -3223
  1081. package/drizzle/market/0001_capacity_budget_mode_default.sql +0 -4
  1082. package/drizzle/market/0002_user_email_addresses.sql +0 -26
  1083. package/drizzle/market/0003_project_team_slug_unique.sql +0 -4
  1084. package/drizzle/market/0004_treedx_market_integration.sql +0 -99
  1085. package/drizzle/market/0005_agent_capacity_coordination.sql +0 -145
  1086. package/drizzle/market/0006_provider_assignment_lifecycle.sql +0 -9
  1087. package/drizzle/market/0007_agent_architecture_gap_closure.sql +0 -157
  1088. package/drizzle/market/0008_agent_capacity_operational_closure.sql +0 -27
  1089. package/drizzle/market/0009_agent_capacity_runtime_hardening.sql +0 -29
  1090. package/drizzle/market/0010_secrets_capability_persistence.sql +0 -130
  1091. package/drizzle/market/0011_github_app_adapter.sql +0 -47
  1092. package/drizzle/market/0012_workday_test_runs.sql +0 -44
  1093. package/drizzle/market/0013_runtime_task_lifecycle.sql +0 -39
  1094. package/drizzle/market/0014_governance_pipeline.sql +0 -189
  1095. package/drizzle/market/0015_agent_decision_assignment_graphs.sql +0 -60
  1096. package/scripts/verify-driver.ts +0 -51
  1097. package/templates/github/deploy-web.workflow.yml +0 -168
  1098. package/templates/github/hosted-project.workflow.yml +0 -76
  1099. /package/dist/{api/types.js → agent-capacity/contracts/capacity/workdays/workday-records.js} +0 -0
  1100. /package/dist/{hosting/contracts.js → agent-capacity/contracts/operations/workflow-promotion.js} +0 -0
  1101. /package/dist/{platform/contracts.js → agent-capacity/contracts/projects/agents/project-agent-class.js} +0 -0
  1102. /package/dist/{reconcile/contracts.js → agent-capacity/contracts/runtime/runtime-observability.js} +0 -0
  1103. /package/dist/{types/cloudflare.js → agent-capacity/contracts/support/decision-work.js} +0 -0
  1104. /package/dist/{field-aliases.js → entrypoints/models/field-aliases.js} +0 -0
  1105. /package/dist/{sdk-fields.js → entrypoints/models/sdk-fields.js} +0 -0
  1106. /package/dist/{runtime.d.ts → runtime/runtime.d.ts} +0 -0
  1107. /package/dist/{runtime.js → runtime/runtime.js} +0 -0
  1108. /package/dist/treedx/{errors.js → support/errors.js} +0 -0
@@ -1,3826 +0,0 @@
1
- import { createHash, randomBytes } from "node:crypto";
2
- import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
3
- import { dirname, relative, resolve } from "node:path";
4
- import { spawnSync } from "node:child_process";
5
- import { createInterface } from "node:readline/promises";
6
- import { resolveTreeseedWebCachePolicy } from "../../platform/deploy-config.js";
7
- import {
8
- deleteRailwayCustomDomain,
9
- deleteRailwayEnvironment,
10
- deleteRailwayVolume,
11
- getRailwayServiceInstance,
12
- listRailwayCustomDomains,
13
- listRailwayProjects,
14
- listRailwayVariables,
15
- listRailwayVolumes,
16
- normalizeRailwayEnvironmentName,
17
- resolveRailwayApiToken,
18
- resolveRailwayWorkspace,
19
- resolveRailwayWorkspaceContext
20
- } from "./railway-api.js";
21
- import { loadCliDeployConfig, resolveWranglerBin } from "./runtime-tools.js";
22
- import { sdkD1MigrationsRoot } from "./runtime-paths.js";
23
- const DEFAULT_COMPATIBILITY_DATE = "2026-04-05";
24
- const DEFAULT_COMPATIBILITY_FLAGS = ["nodejs_compat"];
25
- const DEFAULT_TREESEED_MARKET_BASE_URL = "https://api.treeseed.dev";
26
- const GENERATED_ROOT = ".treeseed/generated";
27
- const STATE_ROOT = ".treeseed/state";
28
- const WORKTREE_METADATA_RELATIVE_PATH = ".treeseed/worktree.json";
29
- const PERSISTENT_SCOPES = /* @__PURE__ */ new Set(["local", "staging", "prod"]);
30
- const MANAGED_SERVICE_KEYS = ["api"];
31
- const TRESEED_ENVELOPE_SCHEMA_GENERATION = "runtime-envelopes-v1";
32
- const TRESEED_MIGRATION_WAVE_ID = "0005_runtime_envelopes";
33
- const TRESEED_SUPPORTED_PAYLOAD_RANGE = { min: 1, max: 1 };
34
- function sleepSync(milliseconds) {
35
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);
36
- }
37
- function ensureParent(filePath) {
38
- mkdirSync(dirname(filePath), { recursive: true });
39
- }
40
- function stableHash(value) {
41
- return createHash("sha256").update(value).digest("hex");
42
- }
43
- function compactDeploymentKey(input) {
44
- const rawKey = sanitizeResourceKey(input.rawKey ?? "");
45
- if (rawKey && rawKey.length <= 40) return rawKey;
46
- const base = sanitizeSegment(input.slug ?? input.projectSegment ?? "project").slice(0, 27) || "project";
47
- const hash = stableHash(`${input.teamId ?? ""}:${input.projectId ?? ""}:${input.slug ?? ""}`).slice(0, 8);
48
- return `${base}-${hash}`;
49
- }
50
- function readJson(filePath, fallback) {
51
- if (!existsSync(filePath)) {
52
- return fallback;
53
- }
54
- try {
55
- return JSON.parse(readFileSync(filePath, "utf8"));
56
- } catch {
57
- return fallback;
58
- }
59
- }
60
- function writeJson(filePath, value) {
61
- ensureParent(filePath);
62
- writeFileSync(filePath, `${JSON.stringify(value, null, 2)}
63
- `, "utf8");
64
- }
65
- function renderTomlString(value) {
66
- return JSON.stringify(String(value));
67
- }
68
- function envOrNull(key) {
69
- const value = process.env[key];
70
- return typeof value === "string" && value.length ? value : null;
71
- }
72
- function loadTenantDeployConfig(tenantRoot) {
73
- return loadCliDeployConfig(tenantRoot);
74
- }
75
- function sanitizeSegment(value) {
76
- return String(value).trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-").slice(0, 36) || "default";
77
- }
78
- function sanitizeResourceKey(value) {
79
- return String(value).trim().toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "");
80
- }
81
- function requireConfiguredIdentityValue(value, label) {
82
- const normalized = typeof value === "string" && value.trim() ? value.trim() : "";
83
- if (!normalized) {
84
- throw new Error(`Configure ${label} before reconciling multi-tenant resources.`);
85
- }
86
- return normalized;
87
- }
88
- function resolveTreeseedResourceIdentity(deployConfig, target) {
89
- const teamId = requireConfiguredIdentityValue(
90
- envOrNull("TREESEED_HOSTING_TEAM_ID") ?? deployConfig.runtime?.teamId ?? deployConfig.hosting?.teamId,
91
- "hosting.teamId or runtime.teamId in treeseed.site.yaml"
92
- );
93
- const projectId = requireConfiguredIdentityValue(
94
- envOrNull("TREESEED_PROJECT_ID") ?? deployConfig.runtime?.projectId ?? deployConfig.hosting?.projectId,
95
- "hosting.projectId or runtime.projectId in treeseed.site.yaml"
96
- );
97
- const teamSegment = sanitizeSegment(teamId);
98
- const projectSegment = sanitizeSegment(projectId);
99
- const deploymentKey = compactDeploymentKey({
100
- rawKey: `${teamSegment}-${projectSegment}`,
101
- teamId,
102
- projectId,
103
- projectSegment,
104
- slug: deployConfig.slug
105
- });
106
- const environment = target.kind === "persistent" ? target.scope : target.branchName;
107
- const environmentSegment = target.kind === "persistent" ? target.scope : sanitizeSegment(target.branchName);
108
- return {
109
- teamId,
110
- projectId,
111
- slug: deployConfig.slug,
112
- environment,
113
- deploymentKey,
114
- environmentKey: `${deploymentKey}-${environmentSegment}`
115
- };
116
- }
117
- function primaryHost(value) {
118
- return safeUrl(value)?.hostname ?? null;
119
- }
120
- function domainZoneFromConfiguredWebDomain(domain) {
121
- if (typeof domain !== "string" || !domain.trim()) {
122
- return null;
123
- }
124
- return domain.trim().replace(/^api\./u, "");
125
- }
126
- function resolveSurfaceDomainZone(deployConfig) {
127
- return domainZoneFromConfiguredWebDomain(
128
- deployConfig.surfaces?.web?.environments?.prod?.domain ?? primaryHost(deployConfig.surfaces?.web?.publicBaseUrl ?? deployConfig.siteUrl)
129
- );
130
- }
131
- function deriveStagingDomainHash(identity, surface) {
132
- return stableHash(`${identity.teamId}:${identity.projectId}:${identity.slug}:${surface}:staging`).slice(0, 8);
133
- }
134
- function deriveTreeseedStagingSurfaceDomain(deployConfig, identity, surface) {
135
- const zone = resolveSurfaceDomainZone(deployConfig);
136
- if (!zone) {
137
- return null;
138
- }
139
- const hash = deriveStagingDomainHash(identity, surface);
140
- return surface === "web" ? `${identity.deploymentKey}-staging-${hash}.${zone}` : `api-${identity.deploymentKey}-staging-${hash}.${zone}`;
141
- }
142
- function deriveApiDomainFromWebDomain(domain) {
143
- if (!domain) {
144
- return null;
145
- }
146
- return domain.startsWith("api.") ? domain : `api.${domain}`;
147
- }
148
- function configuredApiConnectionDomain(deployConfig, scope) {
149
- const apiConnection = deployConfig.connections?.api?.environments?.[scope];
150
- const domain = apiConnection?.domain?.trim();
151
- if (domain) {
152
- return domain;
153
- }
154
- const connectionBaseUrl = primaryHost(apiConnection?.baseUrl);
155
- if (connectionBaseUrl) {
156
- return connectionBaseUrl;
157
- }
158
- const serviceDomain = deployConfig.services?.api?.environments?.[scope]?.domain?.trim();
159
- if (serviceDomain) {
160
- return serviceDomain;
161
- }
162
- return primaryHost(
163
- deployConfig.services?.api?.environments?.[scope]?.baseUrl ?? deployConfig.services?.api?.publicBaseUrl
164
- );
165
- }
166
- function resolveConfiguredSurfaceDomain(deployConfig, target, surface) {
167
- if (target.kind !== "persistent") {
168
- return null;
169
- }
170
- const scope = target.scope;
171
- const configured = deployConfig.surfaces?.[surface]?.environments?.[scope]?.domain?.trim();
172
- if (configured) {
173
- return configured;
174
- }
175
- if (surface === "api") {
176
- const apiConnectionDomain = configuredApiConnectionDomain(deployConfig, scope);
177
- if (apiConnectionDomain) {
178
- return apiConnectionDomain;
179
- }
180
- }
181
- if (scope === "staging") {
182
- return deriveTreeseedStagingSurfaceDomain(
183
- deployConfig,
184
- resolveTreeseedResourceIdentity(deployConfig, target),
185
- surface
186
- );
187
- }
188
- if (scope !== "prod") {
189
- return null;
190
- }
191
- if (surface === "web") {
192
- return primaryHost(deployConfig.surfaces?.web?.publicBaseUrl ?? deployConfig.siteUrl);
193
- }
194
- return deriveApiDomainFromWebDomain(resolveConfiguredSurfaceDomain(deployConfig, target, "web"));
195
- }
196
- function resolveConfiguredSurfaceBaseUrl(deployConfig, target, surface) {
197
- if (surface === "api") {
198
- const scope = scopeFromTarget(target);
199
- const apiConnection = deployConfig.connections?.api?.environments?.[scope];
200
- const connectionBaseUrl = apiConnection?.baseUrl ?? (apiConnection?.domain ? `https://${apiConnection.domain}` : null);
201
- if (connectionBaseUrl) {
202
- return connectionBaseUrl;
203
- }
204
- }
205
- const configuredDomain = resolveConfiguredSurfaceDomain(deployConfig, target, surface);
206
- if (configuredDomain) {
207
- return `https://${configuredDomain}`;
208
- }
209
- if (surface === "web") {
210
- return deployConfig.surfaces?.web?.publicBaseUrl ?? deployConfig.siteUrl ?? null;
211
- }
212
- if (surface === "api") {
213
- const scope = scopeFromTarget(target);
214
- return deployConfig.services?.api?.environments?.[scope]?.baseUrl ?? deployConfig.services?.api?.publicBaseUrl ?? null;
215
- }
216
- return null;
217
- }
218
- function configuredSurfaceHosts(deployConfig, target, surface) {
219
- const hosts = [
220
- resolveConfiguredSurfaceDomain(deployConfig, target, surface),
221
- surface === "web" && target.kind === "persistent" && target.scope === "prod" ? primaryHost(deployConfig.surfaces?.web?.publicBaseUrl ?? deployConfig.siteUrl) : null
222
- ].filter(Boolean);
223
- return [...new Set(hosts)];
224
- }
225
- function sharedDeploymentName(identity, role = "") {
226
- const roleSegment = role === "workdayManager" ? "workday-manager" : role === "workerRunner" ? "worker-runner-01" : role;
227
- return role ? `${identity.deploymentKey}-${sanitizeSegment(roleSegment)}` : identity.deploymentKey;
228
- }
229
- function environmentScopedIdentityName(identity, role, target) {
230
- const environmentSegment = target.kind === "persistent" ? target.scope : sanitizeSegment(target.branchName);
231
- return `${identity.deploymentKey}-${sanitizeSegment(role)}-${environmentSegment}`;
232
- }
233
- function normalizePersistentScope(scope = "prod") {
234
- if (!PERSISTENT_SCOPES.has(scope)) {
235
- throw new Error(`Unsupported Treeseed environment "${scope}". Expected one of local, staging, prod.`);
236
- }
237
- return scope;
238
- }
239
- function createPersistentDeployTarget(scope = "prod") {
240
- return {
241
- kind: "persistent",
242
- scope: normalizePersistentScope(scope)
243
- };
244
- }
245
- function createBranchPreviewDeployTarget(branchName) {
246
- const normalized = String(branchName ?? "").trim();
247
- if (!normalized) {
248
- throw new Error("Branch preview target requires a branch name.");
249
- }
250
- return {
251
- kind: "branch",
252
- branchName: normalized
253
- };
254
- }
255
- function normalizeTarget(scopeOrTarget = "prod") {
256
- if (!scopeOrTarget || typeof scopeOrTarget === "string") {
257
- return createPersistentDeployTarget(scopeOrTarget ?? "prod");
258
- }
259
- if (scopeOrTarget.kind === "persistent") {
260
- return createPersistentDeployTarget(scopeOrTarget.scope);
261
- }
262
- if (scopeOrTarget.kind === "branch") {
263
- return createBranchPreviewDeployTarget(scopeOrTarget.branchName);
264
- }
265
- throw new Error("Unsupported Treeseed deployment target.");
266
- }
267
- function scopeFromTarget(target) {
268
- return target.kind === "persistent" ? target.scope : "staging";
269
- }
270
- function targetDirectoryParts(target) {
271
- if (target.kind === "persistent") {
272
- return ["environments", target.scope];
273
- }
274
- return ["branches", sanitizeSegment(target.branchName)];
275
- }
276
- function targetKey(target) {
277
- return target.kind === "persistent" ? target.scope : `branch:${target.branchName}`;
278
- }
279
- function resolveManagedWorktreeStateRoot(tenantRoot) {
280
- const metadataPath = resolve(tenantRoot, WORKTREE_METADATA_RELATIVE_PATH);
281
- if (!existsSync(metadataPath)) return tenantRoot;
282
- try {
283
- const metadata = JSON.parse(readFileSync(metadataPath, "utf8")) ?? {};
284
- const primaryRoot = metadata.kind === "treeseed.workflow.worktree" && typeof metadata.primaryRoot === "string" ? metadata.primaryRoot : null;
285
- return primaryRoot && existsSync(resolve(primaryRoot, STATE_ROOT)) ? primaryRoot : tenantRoot;
286
- } catch {
287
- return tenantRoot;
288
- }
289
- }
290
- function resolveTargetPaths(tenantRoot, scopeOrTarget = "prod") {
291
- const target = normalizeTarget(scopeOrTarget);
292
- const pathParts = targetDirectoryParts(target);
293
- const stateRoot = resolveManagedWorktreeStateRoot(tenantRoot);
294
- const generatedRoot = resolve(tenantRoot, GENERATED_ROOT, ...pathParts);
295
- const statePath = resolve(stateRoot, STATE_ROOT, ...pathParts, "deploy.json");
296
- return {
297
- target,
298
- generatedRoot,
299
- wranglerPath: resolve(generatedRoot, "wrangler.toml"),
300
- workerEntryPath: resolve(tenantRoot, "dist/_worker.js/index.js"),
301
- statePath
302
- };
303
- }
304
- function deployTargetLabel(scopeOrTarget = "prod") {
305
- const target = normalizeTarget(scopeOrTarget);
306
- return target.kind === "persistent" ? target.scope : `branch:${target.branchName}`;
307
- }
308
- function targetWorkerName(deployConfig, target) {
309
- const identity = resolveTreeseedResourceIdentity(deployConfig, target);
310
- const configuredBaseName = deployConfig.cloudflare.workerName?.trim();
311
- const baseName = configuredBaseName && configuredBaseName === deployConfig.slug ? identity.deploymentKey : configuredBaseName || `${identity.deploymentKey}-edge`;
312
- if (target.kind === "persistent") {
313
- return `${sanitizeSegment(baseName)}-${target.scope}`;
314
- }
315
- return `${sanitizeSegment(baseName)}-${sanitizeSegment(target.branchName)}`;
316
- }
317
- function targetWorkersDevUrl(workerName) {
318
- return `https://${workerName}.workers.dev`;
319
- }
320
- function relativeFromGeneratedRoot(targetPath, generatedRoot) {
321
- return relative(generatedRoot, targetPath).replaceAll("\\", "/");
322
- }
323
- function resolveContentServingMode(deployConfig, options = {}) {
324
- const override = envOrNull("TREESEED_CONTENT_SERVING_MODE");
325
- if (override) {
326
- return override;
327
- }
328
- const target = options.target ? normalizeTarget(options.target) : null;
329
- if (target?.kind === "persistent" && target.scope !== "local") {
330
- return "published_runtime";
331
- }
332
- return deployConfig.providers?.content?.serving ?? "local_collections";
333
- }
334
- function buildPublicVars(deployConfig, options = {}) {
335
- const target = options.target ? normalizeTarget(options.target) : createPersistentDeployTarget("prod");
336
- const identity = resolveTreeseedResourceIdentity(deployConfig, createPersistentDeployTarget("prod"));
337
- const contentRuntimeProvider = deployConfig.providers?.content?.runtime ?? "team_scoped_r2_overlay";
338
- const contentPublishProvider = deployConfig.providers?.content?.publish ?? contentRuntimeProvider;
339
- const contentServingMode = resolveContentServingMode(deployConfig, options);
340
- const contentDefaultTeamId = identity.teamId;
341
- const contentManifestKeyTemplate = deployConfig.cloudflare.r2?.manifestKeyTemplate ?? "teams/{teamId}/published/common.json";
342
- const contentPreviewRootTemplate = deployConfig.cloudflare.r2?.previewRootTemplate ?? "teams/{teamId}/previews";
343
- const contentManifestKey = contentManifestKeyTemplate.replaceAll("{teamId}", contentDefaultTeamId);
344
- const managedRuntime = deployConfig.runtime?.mode === "treeseed_managed";
345
- const workerRailway = deployConfig.services?.worker?.railway ?? {};
346
- const webCachePolicy = resolveTreeseedWebCachePolicy(deployConfig);
347
- const projectDomain = target.kind === "persistent" ? resolveConfiguredSurfaceDomain(deployConfig, target, "web") : primaryHost(deployConfig.surfaces?.web?.publicBaseUrl ?? deployConfig.siteUrl);
348
- return {
349
- TREESEED_HOSTING_KIND: deployConfig.hosting?.kind ?? "self_hosted_project",
350
- TREESEED_HOSTING_REGISTRATION: deployConfig.hosting?.registration ?? "none",
351
- TREESEED_HUB_MODE: deployConfig.hub?.mode ?? "treeseed_hosted",
352
- TREESEED_RUNTIME_MODE: deployConfig.runtime?.mode ?? "none",
353
- TREESEED_RUNTIME_REGISTRATION: deployConfig.runtime?.registration ?? "none",
354
- TREESEED_CENTRAL_MARKET_API_BASE_URL: resolveConfiguredCentralMarketBaseUrl(deployConfig, target),
355
- TREESEED_MARKET_API_BASE_URL: resolveConfiguredMarketBaseUrl(deployConfig, target),
356
- TREESEED_API_BASE_URL: resolveConfiguredMarketBaseUrl(deployConfig, target),
357
- TREESEED_CATALOG_MARKET_API_BASE_URLS: resolveConfiguredMarketBaseUrl(deployConfig, target) ?? envOrNull("TREESEED_CATALOG_MARKET_API_BASE_URLS"),
358
- TREESEED_HOSTING_TEAM_ID: contentDefaultTeamId,
359
- TREESEED_PROJECT_DOMAINS: projectDomain ?? "",
360
- TREESEED_PROJECT_ID: identity.projectId,
361
- TREESEED_AGENT_EXECUTION_PROVIDER: deployConfig.providers?.agents?.execution ?? "codex",
362
- TREESEED_AGENT_REPOSITORY_PROVIDER: deployConfig.providers?.agents?.repository ?? "git",
363
- TREESEED_AGENT_VERIFICATION_PROVIDER: deployConfig.providers?.agents?.verification ?? "local",
364
- TREESEED_CONTENT_RUNTIME_PROVIDER: contentRuntimeProvider,
365
- TREESEED_CONTENT_PUBLISH_PROVIDER: contentPublishProvider,
366
- TREESEED_CONTENT_SERVING_MODE: contentServingMode,
367
- TREESEED_CONTENT_DEFAULT_TEAM_ID: contentDefaultTeamId,
368
- TREESEED_CONTENT_MANIFEST_KEY: contentManifestKey,
369
- TREESEED_CONTENT_MANIFEST_KEY_TEMPLATE: contentManifestKeyTemplate,
370
- TREESEED_CONTENT_PREVIEW_ROOT_TEMPLATE: contentPreviewRootTemplate,
371
- TREESEED_EDITORIAL_PREVIEW_ROOT: contentPreviewRootTemplate.replaceAll("{teamId}", contentDefaultTeamId),
372
- TREESEED_EDITORIAL_PREVIEW_TTL_HOURS: String(deployConfig.cloudflare.r2?.previewTtlHours ?? 168),
373
- TREESEED_CONTENT_BUCKET_NAME: resolveConfiguredContentBucketName(deployConfig),
374
- TREESEED_CONTENT_PUBLIC_BASE_URL: resolveConfiguredContentPublicBaseUrl(deployConfig),
375
- TREESEED_WORKER_POOL_SCALER: envOrNull("TREESEED_WORKER_POOL_SCALER") ?? (managedRuntime ? "railway" : ""),
376
- TREESEED_WORKDAY_TIMEZONE: envOrNull("TREESEED_WORKDAY_TIMEZONE") ?? "",
377
- TREESEED_WORKDAY_WINDOWS_JSON: envOrNull("TREESEED_WORKDAY_WINDOWS_JSON") ?? "",
378
- TREESEED_WORKDAY_TASK_CREDIT_BUDGET: envOrNull("TREESEED_WORKDAY_TASK_CREDIT_BUDGET") ?? "",
379
- TREESEED_MANAGER_MAX_QUEUED_TASKS: envOrNull("TREESEED_MANAGER_MAX_QUEUED_TASKS") ?? "",
380
- TREESEED_MANAGER_MAX_QUEUED_CREDITS: envOrNull("TREESEED_MANAGER_MAX_QUEUED_CREDITS") ?? "",
381
- TREESEED_MANAGER_PRIORITY_MODELS: envOrNull("TREESEED_MANAGER_PRIORITY_MODELS") ?? "",
382
- TREESEED_TASK_CREDIT_WEIGHTS_JSON: envOrNull("TREESEED_TASK_CREDIT_WEIGHTS_JSON") ?? "",
383
- TREESEED_AGENT_POOL_MIN_WORKERS: envOrNull("TREESEED_AGENT_POOL_MIN_WORKERS") ?? "",
384
- TREESEED_AGENT_POOL_MAX_WORKERS: envOrNull("TREESEED_AGENT_POOL_MAX_WORKERS") ?? "",
385
- TREESEED_AGENT_POOL_TARGET_QUEUE_DEPTH: envOrNull("TREESEED_AGENT_POOL_TARGET_QUEUE_DEPTH") ?? "",
386
- TREESEED_AGENT_POOL_COOLDOWN_SECONDS: envOrNull("TREESEED_AGENT_POOL_COOLDOWN_SECONDS") ?? "",
387
- TREESEED_RAILWAY_PROJECT_ID: envOrNull("TREESEED_RAILWAY_PROJECT_ID") ?? workerRailway.projectId ?? "",
388
- TREESEED_RAILWAY_ENVIRONMENT_ID: envOrNull("TREESEED_RAILWAY_ENVIRONMENT_ID") ?? "",
389
- TREESEED_RAILWAY_WORKER_SERVICE_ID: envOrNull("TREESEED_RAILWAY_WORKER_SERVICE_ID") ?? workerRailway.serviceId ?? "",
390
- TREESEED_PUBLIC_TURNSTILE_SITE_KEY: envOrNull("TREESEED_PUBLIC_TURNSTILE_SITE_KEY") ?? "",
391
- TREESEED_AUTH_EMAIL_FROM: envOrNull("TREESEED_AUTH_EMAIL_FROM") ?? "",
392
- TREESEED_AUTH_EMAIL_REPLY_TO: envOrNull("TREESEED_AUTH_EMAIL_REPLY_TO") ?? "",
393
- TREESEED_SMTP_HOST: envOrNull("TREESEED_SMTP_HOST") ?? "",
394
- TREESEED_SMTP_PORT: envOrNull("TREESEED_SMTP_PORT") ?? "",
395
- TREESEED_SMTP_USERNAME: envOrNull("TREESEED_SMTP_USERNAME") ?? "",
396
- TREESEED_SMTP_FROM: envOrNull("TREESEED_SMTP_FROM") ?? "",
397
- TREESEED_SMTP_REPLY_TO: envOrNull("TREESEED_SMTP_REPLY_TO") ?? "",
398
- TREESEED_SMTP_SECURE: envOrNull("TREESEED_SMTP_SECURE") ?? "",
399
- TREESEED_WEB_CACHE_SOURCE_BROWSER_TTL_SECONDS: String(webCachePolicy.sourcePages.browserTtlSeconds),
400
- TREESEED_WEB_CACHE_SOURCE_EDGE_TTL_SECONDS: String(webCachePolicy.sourcePages.edgeTtlSeconds),
401
- TREESEED_WEB_CACHE_SOURCE_STALE_WHILE_REVALIDATE_SECONDS: String(webCachePolicy.sourcePages.staleWhileRevalidateSeconds),
402
- TREESEED_WEB_CACHE_SOURCE_STALE_IF_ERROR_SECONDS: String(webCachePolicy.sourcePages.staleIfErrorSeconds),
403
- TREESEED_WEB_CACHE_CONTENT_BROWSER_TTL_SECONDS: String(webCachePolicy.contentPages.browserTtlSeconds),
404
- TREESEED_WEB_CACHE_CONTENT_EDGE_TTL_SECONDS: String(webCachePolicy.contentPages.edgeTtlSeconds),
405
- TREESEED_WEB_CACHE_CONTENT_STALE_WHILE_REVALIDATE_SECONDS: String(webCachePolicy.contentPages.staleWhileRevalidateSeconds),
406
- TREESEED_WEB_CACHE_CONTENT_STALE_IF_ERROR_SECONDS: String(webCachePolicy.contentPages.staleIfErrorSeconds),
407
- TREESEED_WEB_CACHE_R2_BROWSER_TTL_SECONDS: String(webCachePolicy.r2PublishedObjects.browserTtlSeconds),
408
- TREESEED_WEB_CACHE_R2_EDGE_TTL_SECONDS: String(webCachePolicy.r2PublishedObjects.edgeTtlSeconds),
409
- TREESEED_WEB_CACHE_R2_STALE_WHILE_REVALIDATE_SECONDS: String(webCachePolicy.r2PublishedObjects.staleWhileRevalidateSeconds),
410
- TREESEED_WEB_CACHE_R2_STALE_IF_ERROR_SECONDS: String(webCachePolicy.r2PublishedObjects.staleIfErrorSeconds)
411
- };
412
- }
413
- function envValue(env, key) {
414
- const value = env?.[key] ?? process.env[key];
415
- return typeof value === "string" && value.trim() ? value.trim() : null;
416
- }
417
- const LOCAL_RUNTIME_AUTH_ENV_KEYS = [
418
- "TREESEED_BETTER_AUTH_URL",
419
- "TREESEED_SITE_URL",
420
- "TREESEED_AUTH_MODE",
421
- "TREESEED_AUTH_INTERNAL_SIGNUP",
422
- "TREESEED_AUTH_EMAIL_LINKING",
423
- "TREESEED_AUTH_ALLOW_MEMORY_DB",
424
- "TREESEED_AUTH_EMAIL_FROM",
425
- "TREESEED_WEB_SESSION_TTL",
426
- "TREESEED_API_BOOTSTRAP_ADMIN_ALLOWLIST",
427
- "TREESEED_API_AUTH_SECRET",
428
- "TREESEED_API_ISSUER",
429
- "TREESEED_API_ACCESS_TOKEN_TTL",
430
- "TREESEED_API_REFRESH_TOKEN_TTL",
431
- "TREESEED_API_DEVICE_CODE_TTL",
432
- "TREESEED_API_DEVICE_ACCESS_TOKEN_TTL",
433
- "TREESEED_API_DEVICE_POLL_INTERVAL",
434
- "TREESEED_API_WEB_SERVICE_ID",
435
- "TREESEED_API_WEB_SERVICE_SECRET",
436
- "TREESEED_API_WEB_EXCHANGE_TTL",
437
- "TREESEED_PLATFORM_RUNNER_SECRET",
438
- "TREESEED_AUTH_GITHUB_CLIENT_ID",
439
- "TREESEED_AUTH_GITHUB_CLIENT_SECRET",
440
- "TREESEED_AUTH_GOOGLE_CLIENT_ID",
441
- "TREESEED_AUTH_GOOGLE_CLIENT_SECRET",
442
- "TREESEED_AUTH_MICROSOFT_CLIENT_ID",
443
- "TREESEED_AUTH_MICROSOFT_CLIENT_SECRET",
444
- "TREESEED_AUTH_APPLE_CLIENT_ID",
445
- "TREESEED_AUTH_APPLE_CLIENT_SECRET"
446
- ];
447
- function localAuthRuntimeVars(env) {
448
- return Object.fromEntries(
449
- LOCAL_RUNTIME_AUTH_ENV_KEYS.map((key) => [key, envValue(env, key)]).filter(([, value]) => value != null)
450
- );
451
- }
452
- function buildLocalRuntimeVars(deployConfig, state, target, env) {
453
- if (target.kind !== "persistent" || target.scope !== "local") {
454
- return {};
455
- }
456
- const localDevAuthTtlSeconds = String(365 * 24 * 60 * 60);
457
- return {
458
- ...localAuthRuntimeVars(env),
459
- TREESEED_LOCAL_DEV_MODE: envValue(env, "TREESEED_LOCAL_DEV_MODE") ?? "cloudflare",
460
- TREESEED_API_ACCESS_TOKEN_TTL: envValue(env, "TREESEED_API_ACCESS_TOKEN_TTL") ?? localDevAuthTtlSeconds,
461
- TREESEED_API_REFRESH_TOKEN_TTL: envValue(env, "TREESEED_API_REFRESH_TOKEN_TTL") ?? localDevAuthTtlSeconds,
462
- TREESEED_FORM_TOKEN_SECRET: envValue(env, "TREESEED_FORM_TOKEN_SECRET") ?? state.generatedSecrets?.TREESEED_FORM_TOKEN_SECRET ?? "treeseed-local-form-token-secret",
463
- TREESEED_BETTER_AUTH_SECRET: envValue(env, "TREESEED_BETTER_AUTH_SECRET") ?? state.generatedSecrets?.TREESEED_BETTER_AUTH_SECRET ?? state.generatedSecrets?.TREESEED_FORM_TOKEN_SECRET ?? "treeseed-local-better-auth-secret-minimum-32-characters",
464
- TREESEED_EDITORIAL_PREVIEW_SECRET: envValue(env, "TREESEED_EDITORIAL_PREVIEW_SECRET") ?? state.generatedSecrets?.TREESEED_EDITORIAL_PREVIEW_SECRET ?? "treeseed-local-editorial-preview-secret",
465
- TREESEED_FORMS_LOCAL_BYPASS_CLOUDFLARE_GUARDS: envValue(env, "TREESEED_FORMS_LOCAL_BYPASS_CLOUDFLARE_GUARDS") ?? "",
466
- TREESEED_MAILPIT_SMTP_HOST: "127.0.0.1",
467
- TREESEED_MAILPIT_SMTP_PORT: "1025",
468
- TREESEED_SMTP_HOST: "127.0.0.1",
469
- TREESEED_SMTP_PORT: "1025",
470
- TREESEED_SMTP_USERNAME: "",
471
- TREESEED_SMTP_PASSWORD: ""
472
- };
473
- }
474
- function buildSecretMap(deployConfig, state) {
475
- const generatedSecret = state.generatedSecrets?.TREESEED_FORM_TOKEN_SECRET ?? randomBytes(24).toString("hex");
476
- const previewSecret = state.generatedSecrets?.TREESEED_EDITORIAL_PREVIEW_SECRET ?? randomBytes(24).toString("hex");
477
- return {
478
- TREESEED_FORM_TOKEN_SECRET: envOrNull("TREESEED_FORM_TOKEN_SECRET") ?? generatedSecret,
479
- TREESEED_EDITORIAL_PREVIEW_SECRET: envOrNull("TREESEED_EDITORIAL_PREVIEW_SECRET") ?? previewSecret,
480
- TREESEED_TURNSTILE_SECRET_KEY: state.turnstileWidgets?.formGuard?.secret ?? envOrNull("TREESEED_TURNSTILE_SECRET_KEY"),
481
- TREESEED_SMTP_PASSWORD: envOrNull("TREESEED_SMTP_PASSWORD")
482
- };
483
- }
484
- function defaultStateFromConfig(deployConfig, target) {
485
- const identity = resolveTreeseedResourceIdentity(deployConfig, target);
486
- const workerName = targetWorkerName(deployConfig, target);
487
- const suffix = target.kind === "persistent" ? target.scope : sanitizeSegment(target.branchName);
488
- const contentManifestKeyTemplate = deployConfig.cloudflare.r2?.manifestKeyTemplate ?? "teams/{teamId}/published/common.json";
489
- const contentPreviewRootTemplate = deployConfig.cloudflare.r2?.previewRootTemplate ?? "teams/{teamId}/previews";
490
- const contentDefaultTeamId = identity.teamId;
491
- const contentManifestKey = contentManifestKeyTemplate.replaceAll("{teamId}", contentDefaultTeamId);
492
- const turnstileName = environmentScopedIdentityName(identity, "turnstile", target);
493
- const turnstileDomains = configuredSurfaceHosts(deployConfig, target, "web");
494
- return {
495
- version: 2,
496
- target,
497
- identity,
498
- previewEnabled: target.kind === "branch",
499
- workerName,
500
- kvNamespaces: {
501
- FORM_GUARD_KV: {
502
- name: environmentScopedIdentityName(identity, "form-guard", target),
503
- binding: "FORM_GUARD_KV",
504
- id: `plan-${suffix}-form-guard`,
505
- previewId: `plan-${suffix}-form-guard-preview`
506
- }
507
- },
508
- d1Databases: {
509
- SITE_DATA_DB: {
510
- databaseName: environmentScopedIdentityName(identity, "site-data", target),
511
- binding: "SITE_DATA_DB",
512
- databaseId: `plan-${suffix}-site-data`,
513
- previewDatabaseId: `plan-${suffix}-site-data-preview`
514
- }
515
- },
516
- queues: {},
517
- pages: {
518
- projectName: resolveConfiguredPagesProjectName(deployConfig),
519
- productionBranch: deployConfig.cloudflare.pages?.productionBranch ?? "main",
520
- stagingBranch: deployConfig.cloudflare.pages?.stagingBranch ?? "staging",
521
- buildOutputDir: deployConfig.cloudflare.pages?.buildOutputDir ?? "dist",
522
- url: resolveConfiguredSurfaceBaseUrl(deployConfig, target, "web")
523
- },
524
- turnstileWidgets: {
525
- formGuard: {
526
- name: turnstileName,
527
- sitekey: null,
528
- secret: null,
529
- mode: "managed",
530
- domains: turnstileDomains,
531
- managed: true,
532
- lastSyncedAt: null
533
- }
534
- },
535
- content: {
536
- runtimeProvider: deployConfig.providers?.content?.runtime ?? "team_scoped_r2_overlay",
537
- publishProvider: deployConfig.providers?.content?.publish ?? deployConfig.providers?.content?.runtime ?? "team_scoped_r2_overlay",
538
- defaultTeamId: contentDefaultTeamId,
539
- r2Binding: resolveConfiguredContentBucketBinding(deployConfig),
540
- bucketName: resolveConfiguredContentBucketName(deployConfig),
541
- publicBaseUrl: resolveConfiguredContentPublicBaseUrl(deployConfig) || null,
542
- manifestKeyTemplate: contentManifestKeyTemplate,
543
- previewRootTemplate: contentPreviewRootTemplate,
544
- previewTtlHours: deployConfig.cloudflare.r2?.previewTtlHours ?? 168,
545
- manifestKey: contentManifestKey,
546
- lastPublishedManifestRevision: null,
547
- lastPublishedManifestSha256: null
548
- },
549
- hosting: {
550
- kind: deployConfig.hosting?.kind ?? "self_hosted_project",
551
- registration: deployConfig.hosting?.registration ?? "none",
552
- marketBaseUrl: resolveConfiguredMarketBaseUrl(deployConfig) || null,
553
- teamId: identity.teamId,
554
- projectId: identity.projectId
555
- },
556
- hub: {
557
- mode: deployConfig.hub?.mode ?? "treeseed_hosted"
558
- },
559
- runtime: {
560
- mode: deployConfig.runtime?.mode ?? "none",
561
- registration: deployConfig.runtime?.registration ?? "none",
562
- marketBaseUrl: resolveConfiguredMarketBaseUrl(deployConfig) || null,
563
- teamId: identity.teamId,
564
- projectId: identity.projectId
565
- },
566
- webCache: {
567
- webHost: null,
568
- contentHost: null,
569
- webZoneId: null,
570
- contentZoneId: null,
571
- webRulesetId: null,
572
- contentRulesetId: null,
573
- rulesManaged: false,
574
- lastSyncedAt: null,
575
- lastVerifiedAt: null,
576
- lastError: null,
577
- deployPurge: {
578
- lastPurgedAt: null,
579
- purgeCount: 0,
580
- lastError: null
581
- },
582
- contentPurge: {
583
- lastPurgedAt: null,
584
- purgeCount: 0,
585
- lastError: null
586
- }
587
- },
588
- generatedSecrets: {},
589
- readiness: {
590
- phase: "pending",
591
- configured: false,
592
- provisioned: false,
593
- deployable: false,
594
- initialized: false,
595
- initializedAt: null,
596
- lastValidatedAt: null,
597
- lastConfigFingerprint: null,
598
- blockers: [],
599
- warnings: [],
600
- lastValidationSummary: null
601
- },
602
- lastDeployedUrl: target.kind === "branch" ? targetWorkersDevUrl(workerName) : resolveConfiguredSurfaceBaseUrl(deployConfig, target, "web"),
603
- lastManifestFingerprint: null,
604
- lastDeploymentTimestamp: null,
605
- lastDeployedCommit: null,
606
- services: Object.fromEntries(
607
- MANAGED_SERVICE_KEYS.map((serviceKey) => {
608
- const serviceConfig = deployConfig.services?.[serviceKey];
609
- const scope = scopeFromTarget(target);
610
- const baseUrl = serviceKey === "api" ? resolveConfiguredSurfaceBaseUrl(deployConfig, target, "api") ?? serviceConfig?.environments?.[scope]?.baseUrl ?? serviceConfig?.publicBaseUrl ?? null : serviceConfig?.environments?.[scope]?.baseUrl ?? serviceConfig?.publicBaseUrl ?? null;
611
- return [
612
- serviceKey,
613
- {
614
- enabled: serviceConfig?.enabled !== false && Boolean(serviceConfig),
615
- provider: serviceConfig?.provider ?? (serviceConfig ? "railway" : "none"),
616
- projectId: serviceConfig?.railway?.projectId ?? null,
617
- projectName: serviceConfig?.railway?.projectName ?? sharedDeploymentName(identity),
618
- serviceId: serviceConfig?.railway?.serviceId ?? null,
619
- serviceName: serviceConfig?.environments?.[scope]?.serviceName ?? serviceConfig?.railway?.serviceName ?? sharedDeploymentName(identity, serviceKey),
620
- workerName: serviceConfig?.cloudflare?.workerName ?? null,
621
- rootDir: serviceConfig?.railway?.rootDir ?? serviceConfig?.rootDir ?? null,
622
- environment: normalizeRailwayEnvironmentName(serviceConfig?.environments?.[scope]?.railwayEnvironment ?? scope),
623
- schedule: serviceConfig?.railway?.schedule ?? null,
624
- publicBaseUrl: baseUrl,
625
- initialized: false,
626
- lastDeploymentTimestamp: null,
627
- lastDeployedUrl: baseUrl,
628
- lastDeploymentCommand: null,
629
- lastScheduleSyncAt: null
630
- }
631
- ];
632
- })
633
- ),
634
- railwaySchedules: {},
635
- runtimeCompatibility: {
636
- envelopeSchemaGeneration: TRESEED_ENVELOPE_SCHEMA_GENERATION,
637
- migrationWaveId: TRESEED_MIGRATION_WAVE_ID,
638
- supportedPayloadVersionRange: TRESEED_SUPPORTED_PAYLOAD_RANGE
639
- },
640
- deploymentHistory: []
641
- };
642
- }
643
- function loadDeployState(tenantRoot, deployConfig, options = {}) {
644
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
645
- const defaults = defaultStateFromConfig(deployConfig, target);
646
- const { statePath } = resolveTargetPaths(tenantRoot, target);
647
- const persisted = readJson(statePath, {});
648
- const persistedSiteDataDb = persisted.d1Databases?.SITE_DATA_DB ?? persisted.d1Databases?.SUBSCRIBERS_DB ?? {};
649
- const merged = {
650
- ...defaults,
651
- ...persisted,
652
- target,
653
- identity: {
654
- ...defaults.identity ?? {},
655
- ...persisted.identity ?? {},
656
- teamId: defaults.identity?.teamId,
657
- projectId: defaults.identity?.projectId,
658
- slug: defaults.identity?.slug,
659
- environment: defaults.identity?.environment,
660
- deploymentKey: defaults.identity?.deploymentKey,
661
- environmentKey: defaults.identity?.environmentKey
662
- },
663
- previewEnabled: persisted.previewEnabled ?? defaults.previewEnabled,
664
- workerName: defaults.workerName,
665
- kvNamespaces: {
666
- ...defaults.kvNamespaces,
667
- FORM_GUARD_KV: {
668
- ...defaults.kvNamespaces.FORM_GUARD_KV,
669
- ...persisted.kvNamespaces?.FORM_GUARD_KV ?? {},
670
- name: defaults.kvNamespaces.FORM_GUARD_KV.name,
671
- binding: defaults.kvNamespaces.FORM_GUARD_KV.binding
672
- },
673
- ...persisted.kvNamespaces?.SESSION ? { SESSION: persisted.kvNamespaces.SESSION } : {}
674
- },
675
- d1Databases: {
676
- ...defaults.d1Databases,
677
- ...persisted.d1Databases ?? {},
678
- SITE_DATA_DB: {
679
- ...defaults.d1Databases.SITE_DATA_DB,
680
- ...persistedSiteDataDb,
681
- databaseName: defaults.d1Databases.SITE_DATA_DB.databaseName,
682
- binding: defaults.d1Databases.SITE_DATA_DB.binding
683
- }
684
- },
685
- queues: {},
686
- generatedSecrets: {
687
- ...defaults.generatedSecrets ?? {},
688
- ...persisted.generatedSecrets ?? {}
689
- },
690
- turnstileWidgets: {
691
- ...defaults.turnstileWidgets ?? {},
692
- ...persisted.turnstileWidgets ?? {},
693
- formGuard: {
694
- ...defaults.turnstileWidgets?.formGuard ?? {},
695
- ...persisted.turnstileWidgets?.formGuard ?? {},
696
- name: defaults.turnstileWidgets?.formGuard?.name ?? persisted.turnstileWidgets?.formGuard?.name ?? null,
697
- mode: "managed",
698
- managed: true,
699
- domains: [
700
- ...new Set([
701
- ...Array.isArray(defaults.turnstileWidgets?.formGuard?.domains) ? defaults.turnstileWidgets.formGuard.domains : [],
702
- ...Array.isArray(persisted.turnstileWidgets?.formGuard?.domains) ? persisted.turnstileWidgets.formGuard.domains : []
703
- ].filter(Boolean))
704
- ]
705
- }
706
- },
707
- content: {
708
- ...defaults.content ?? {},
709
- ...persisted.content ?? {},
710
- runtimeProvider: defaults.content?.runtimeProvider ?? persisted.content?.runtimeProvider ?? "team_scoped_r2_overlay",
711
- publishProvider: defaults.content?.publishProvider ?? persisted.content?.publishProvider ?? "team_scoped_r2_overlay",
712
- defaultTeamId: defaults.content?.defaultTeamId ?? persisted.content?.defaultTeamId ?? defaults.identity?.teamId,
713
- r2Binding: defaults.content?.r2Binding ?? persisted.content?.r2Binding ?? null,
714
- bucketName: defaults.content?.bucketName ?? persisted.content?.bucketName ?? null,
715
- publicBaseUrl: defaults.content?.publicBaseUrl ?? persisted.content?.publicBaseUrl ?? null,
716
- manifestKeyTemplate: defaults.content?.manifestKeyTemplate ?? persisted.content?.manifestKeyTemplate ?? "teams/{teamId}/published/common.json",
717
- previewRootTemplate: defaults.content?.previewRootTemplate ?? persisted.content?.previewRootTemplate ?? "teams/{teamId}/previews",
718
- previewTtlHours: defaults.content?.previewTtlHours ?? persisted.content?.previewTtlHours ?? 168,
719
- manifestKey: defaults.content?.manifestKey ?? persisted.content?.manifestKey ?? `teams/${defaults.identity?.teamId}/published/common.json`,
720
- lastPublishedManifestRevision: persisted.content?.lastPublishedManifestRevision ?? defaults.content?.lastPublishedManifestRevision ?? null,
721
- lastPublishedManifestSha256: persisted.content?.lastPublishedManifestSha256 ?? defaults.content?.lastPublishedManifestSha256 ?? null
722
- },
723
- hosting: {
724
- ...defaults.hosting ?? {},
725
- ...persisted.hosting ?? {},
726
- kind: defaults.hosting?.kind ?? persisted.hosting?.kind ?? "self_hosted_project",
727
- registration: defaults.hosting?.registration ?? persisted.hosting?.registration ?? "none",
728
- marketBaseUrl: defaults.hosting?.marketBaseUrl ?? persisted.hosting?.marketBaseUrl ?? null,
729
- teamId: defaults.hosting?.teamId ?? persisted.hosting?.teamId ?? defaults.identity?.teamId,
730
- projectId: defaults.hosting?.projectId ?? persisted.hosting?.projectId ?? defaults.identity?.projectId
731
- },
732
- hub: {
733
- ...defaults.hub ?? {},
734
- ...persisted.hub ?? {},
735
- mode: defaults.hub?.mode ?? persisted.hub?.mode ?? "treeseed_hosted"
736
- },
737
- runtime: {
738
- ...defaults.runtime ?? {},
739
- ...persisted.runtime ?? {},
740
- mode: defaults.runtime?.mode ?? persisted.runtime?.mode ?? "none",
741
- registration: defaults.runtime?.registration ?? persisted.runtime?.registration ?? "none",
742
- marketBaseUrl: defaults.runtime?.marketBaseUrl ?? persisted.runtime?.marketBaseUrl ?? null,
743
- teamId: defaults.runtime?.teamId ?? persisted.runtime?.teamId ?? defaults.identity?.teamId,
744
- projectId: defaults.runtime?.projectId ?? persisted.runtime?.projectId ?? defaults.identity?.projectId
745
- },
746
- webCache: {
747
- ...defaults.webCache ?? {},
748
- ...persisted.webCache ?? {},
749
- webHost: persisted.webCache?.webHost ?? persisted.webCache?.publicHost ?? defaults.webCache?.webHost ?? null,
750
- contentHost: persisted.webCache?.contentHost ?? defaults.webCache?.contentHost ?? null,
751
- webZoneId: persisted.webCache?.webZoneId ?? persisted.webCache?.zoneId ?? defaults.webCache?.webZoneId ?? null,
752
- contentZoneId: persisted.webCache?.contentZoneId ?? defaults.webCache?.contentZoneId ?? null,
753
- webRulesetId: persisted.webCache?.webRulesetId ?? persisted.webCache?.rulesetId ?? defaults.webCache?.webRulesetId ?? null,
754
- contentRulesetId: persisted.webCache?.contentRulesetId ?? defaults.webCache?.contentRulesetId ?? null,
755
- rulesManaged: persisted.webCache?.rulesManaged ?? defaults.webCache?.rulesManaged ?? false,
756
- lastSyncedAt: persisted.webCache?.lastSyncedAt ?? defaults.webCache?.lastSyncedAt ?? null,
757
- lastVerifiedAt: persisted.webCache?.lastVerifiedAt ?? defaults.webCache?.lastVerifiedAt ?? null,
758
- lastError: persisted.webCache?.lastError ?? defaults.webCache?.lastError ?? null,
759
- deployPurge: {
760
- ...defaults.webCache?.deployPurge ?? {},
761
- ...persisted.webCache?.deployPurge ?? {},
762
- lastPurgedAt: persisted.webCache?.deployPurge?.lastPurgedAt ?? defaults.webCache?.deployPurge?.lastPurgedAt ?? null,
763
- purgeCount: persisted.webCache?.deployPurge?.purgeCount ?? defaults.webCache?.deployPurge?.purgeCount ?? 0,
764
- lastError: persisted.webCache?.deployPurge?.lastError ?? defaults.webCache?.deployPurge?.lastError ?? null
765
- },
766
- contentPurge: {
767
- ...defaults.webCache?.contentPurge ?? {},
768
- ...persisted.webCache?.contentPurge ?? {},
769
- lastPurgedAt: persisted.webCache?.contentPurge?.lastPurgedAt ?? defaults.webCache?.contentPurge?.lastPurgedAt ?? null,
770
- purgeCount: persisted.webCache?.contentPurge?.purgeCount ?? defaults.webCache?.contentPurge?.purgeCount ?? 0,
771
- lastError: persisted.webCache?.contentPurge?.lastError ?? defaults.webCache?.contentPurge?.lastError ?? null
772
- }
773
- },
774
- pages: {
775
- ...defaults.pages ?? {},
776
- ...persisted.pages ?? {},
777
- projectName: defaults.pages?.projectName ?? persisted.pages?.projectName ?? null,
778
- productionBranch: defaults.pages?.productionBranch ?? persisted.pages?.productionBranch ?? "main",
779
- stagingBranch: defaults.pages?.stagingBranch ?? persisted.pages?.stagingBranch ?? "staging",
780
- buildOutputDir: defaults.pages?.buildOutputDir ?? persisted.pages?.buildOutputDir ?? "dist",
781
- url: defaults.pages?.url ?? persisted.pages?.url ?? null
782
- },
783
- readiness: {
784
- ...defaults.readiness,
785
- ...persisted.readiness ?? {}
786
- },
787
- services: Object.fromEntries(
788
- MANAGED_SERVICE_KEYS.map((serviceKey) => {
789
- const defaultService = defaults.services?.[serviceKey] ?? {};
790
- const persistedService = persisted.services?.[serviceKey] ?? {};
791
- const effectiveDeploymentTimestamp = persistedService.lastDeploymentTimestamp ?? defaultService.lastDeploymentTimestamp ?? null;
792
- return [
793
- serviceKey,
794
- {
795
- ...defaultService,
796
- ...persistedService,
797
- enabled: defaultService.enabled,
798
- initialized: persistedService.initialized === true && Boolean(effectiveDeploymentTimestamp),
799
- provider: defaultService.provider,
800
- projectId: defaultService.projectId ?? persistedService.projectId ?? null,
801
- projectName: defaultService.projectName ?? persistedService.projectName ?? null,
802
- serviceId: defaultService.serviceId ?? persistedService.serviceId ?? null,
803
- serviceName: defaultService.serviceName ?? persistedService.serviceName ?? null,
804
- workerName: defaultService.workerName ?? persistedService.workerName ?? null,
805
- rootDir: defaultService.rootDir ?? persistedService.rootDir ?? null,
806
- environment: defaultService.environment ?? persistedService.environment ?? null,
807
- schedule: defaultService.schedule ?? persistedService.schedule ?? null,
808
- publicBaseUrl: defaultService.publicBaseUrl ?? persistedService.publicBaseUrl ?? null,
809
- lastDeploymentTimestamp: effectiveDeploymentTimestamp,
810
- lastDeployedUrl: defaultService.publicBaseUrl ?? persistedService.lastDeployedUrl ?? null,
811
- lastScheduleSyncAt: persistedService.lastScheduleSyncAt ?? defaultService.lastScheduleSyncAt ?? null
812
- }
813
- ];
814
- })
815
- ),
816
- railwaySchedules: {
817
- ...persisted.railwaySchedules ?? {}
818
- }
819
- };
820
- if (target.kind === "persistent") {
821
- merged.lastDeployedUrl = resolveConfiguredSurfaceBaseUrl(deployConfig, target, "web") ?? merged.lastDeployedUrl ?? null;
822
- }
823
- if (target.kind === "branch" && !merged.lastDeployedUrl) {
824
- merged.lastDeployedUrl = targetWorkersDevUrl(merged.workerName);
825
- }
826
- return merged;
827
- }
828
- function writeDeployState(tenantRoot, state, options = {}) {
829
- const target = normalizeTarget(options.scope ?? options.target ?? state.target ?? "prod");
830
- const { statePath } = resolveTargetPaths(tenantRoot, target);
831
- writeJson(statePath, {
832
- ...state,
833
- target
834
- });
835
- }
836
- function resolveGeneratedWranglerPath(tenantRoot, options = {}) {
837
- return resolveTargetPaths(tenantRoot, options.scope ?? options.target ?? "prod").wranglerPath;
838
- }
839
- function buildWranglerConfigContents(tenantRoot, deployConfig, state, options = {}) {
840
- const target = normalizeTarget(options.scope ?? options.target ?? state.target ?? "prod");
841
- const { generatedRoot } = resolveTargetPaths(tenantRoot, target);
842
- const workerName = state.workerName ?? targetWorkerName(deployConfig, target);
843
- const mainPath = relativeFromGeneratedRoot(resolve(tenantRoot, "dist/_worker.js/index.js"), generatedRoot);
844
- const assetsDirectory = relativeFromGeneratedRoot(resolve(tenantRoot, "dist"), generatedRoot);
845
- const migrationsDir = relativeFromGeneratedRoot(sdkD1MigrationsRoot, generatedRoot);
846
- const vars = {
847
- ...buildPublicVars(deployConfig, { target }),
848
- ...buildLocalRuntimeVars(deployConfig, state, target, options.env)
849
- };
850
- const r2Config = deployConfig.cloudflare.r2;
851
- const r2Binding = resolveConfiguredContentBucketBinding(deployConfig);
852
- const r2BucketName = resolveConfiguredContentBucketName(deployConfig);
853
- return [
854
- `name = ${renderTomlString(workerName)}`,
855
- `compatibility_date = ${renderTomlString(DEFAULT_COMPATIBILITY_DATE)}`,
856
- `compatibility_flags = [${DEFAULT_COMPATIBILITY_FLAGS.map((flag) => renderTomlString(flag)).join(", ")}]`,
857
- `main = ${renderTomlString(mainPath)}`,
858
- "workers_dev = true",
859
- "preview_urls = true",
860
- "",
861
- "[assets]",
862
- `directory = ${renderTomlString(assetsDirectory)}`,
863
- "",
864
- "[vars]",
865
- ...Object.entries(vars).map(([key, value]) => `${key} = ${renderTomlString(value)}`),
866
- "",
867
- "[[kv_namespaces]]",
868
- 'binding = "FORM_GUARD_KV"',
869
- `id = ${renderTomlString(state.kvNamespaces.FORM_GUARD_KV.id)}`,
870
- `preview_id = ${renderTomlString(state.kvNamespaces.FORM_GUARD_KV.previewId ?? state.kvNamespaces.FORM_GUARD_KV.id)}`,
871
- "",
872
- "[[d1_databases]]",
873
- 'binding = "SITE_DATA_DB"',
874
- `database_name = ${renderTomlString(state.d1Databases.SITE_DATA_DB.databaseName)}`,
875
- `database_id = ${renderTomlString(state.d1Databases.SITE_DATA_DB.databaseId)}`,
876
- `preview_database_id = ${renderTomlString(state.d1Databases.SITE_DATA_DB.previewDatabaseId ?? state.d1Databases.SITE_DATA_DB.databaseId)}`,
877
- `migrations_dir = ${renderTomlString(migrationsDir)}`,
878
- "",
879
- ...r2Config ? [
880
- "[[r2_buckets]]",
881
- `binding = ${renderTomlString(r2Binding)}`,
882
- `bucket_name = ${renderTomlString(r2BucketName)}`,
883
- ""
884
- ] : []
885
- ].join("\n");
886
- }
887
- function ensureGeneratedWranglerConfig(tenantRoot, options = {}) {
888
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
889
- const deployConfig = loadTenantDeployConfig(tenantRoot);
890
- const state = loadDeployState(tenantRoot, deployConfig, { target });
891
- const { wranglerPath } = resolveTargetPaths(tenantRoot, target);
892
- const manifestFingerprint = stableHash(JSON.stringify({ deployConfig, targetKey: targetKey(target) }));
893
- const contents = buildWranglerConfigContents(tenantRoot, deployConfig, state, { target, env: options.env });
894
- ensureParent(wranglerPath);
895
- writeFileSync(wranglerPath, contents, "utf8");
896
- state.lastManifestFingerprint = manifestFingerprint;
897
- state.readiness.lastConfigFingerprint = manifestFingerprint;
898
- if (!state.generatedSecrets) {
899
- state.generatedSecrets = {};
900
- }
901
- const secretMap = buildSecretMap(deployConfig, state);
902
- state.generatedSecrets.TREESEED_FORM_TOKEN_SECRET = secretMap.TREESEED_FORM_TOKEN_SECRET;
903
- state.generatedSecrets.TREESEED_EDITORIAL_PREVIEW_SECRET = secretMap.TREESEED_EDITORIAL_PREVIEW_SECRET;
904
- writeDeployState(tenantRoot, state, { target });
905
- return { wranglerPath, deployConfig, state, manifestFingerprint, target };
906
- }
907
- function runWrangler(args, { cwd, allowFailure = false, json = false, capture = false, env = {}, input } = {}) {
908
- const result = spawnSync(process.execPath, [resolveWranglerBin(), ...args], {
909
- stdio: json || capture || input !== void 0 ? ["pipe", "pipe", "pipe"] : "inherit",
910
- cwd,
911
- env: { ...process.env, ...env },
912
- encoding: "utf8",
913
- input
914
- });
915
- if (result.status !== 0 && !allowFailure) {
916
- const stderr = result.stderr?.trim();
917
- const stdout = result.stdout?.trim();
918
- const output = [stderr, stdout].filter(Boolean).join("\n");
919
- if (/Authentication error/i.test(output) || /\[code:\s*10000\]/i.test(output)) {
920
- throw new Error([
921
- output || `Wrangler command failed: ${args.join(" ")}`,
922
- "",
923
- "Treeseed Cloudflare authentication failed. Check that CLOUDFLARE_API_TOKEN is an account-level token scoped to the target account and domain.",
924
- "Required Cloudflare permissions: account Pages Write, Workers Scripts Write, Workers KV Storage Write, Workers R2 Storage Write, D1 Write, Queues Write, Turnstile Sites Write, Account Rulesets Write, and Account Rule Lists Write; target zone Zone Read, DNS Write, Cache Settings Write, and SSL and Certificates Write."
925
- ].join("\n"));
926
- }
927
- throw new Error(output || `Wrangler command failed: ${args.join(" ")}`);
928
- }
929
- return result;
930
- }
931
- function parseWranglerJsonOutput(result, label) {
932
- const source = `${result.stdout ?? ""}`.trim();
933
- if (!source) {
934
- throw new Error(`Expected JSON output from ${label}.`);
935
- }
936
- return JSON.parse(source);
937
- }
938
- function isWranglerAlreadyExistsError(error, matchers) {
939
- const message = error instanceof Error ? error.message : String(error);
940
- return matchers.some((matcher) => matcher.test(message));
941
- }
942
- function listKvNamespaces(tenantRoot, env) {
943
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
944
- if (!accountId) {
945
- return [];
946
- }
947
- const payload = cloudflareApiRequest(`/accounts/${encodeURIComponent(accountId)}/storage/kv/namespaces?per_page=1000&order=title&direction=asc`, {
948
- env,
949
- allowFailure: true
950
- });
951
- return Array.isArray(payload?.result) ? payload.result : [];
952
- }
953
- function listD1Databases(tenantRoot, env) {
954
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
955
- if (!accountId) {
956
- return [];
957
- }
958
- const payload = cloudflareApiRequest(`/accounts/${encodeURIComponent(accountId)}/d1/database`, {
959
- env,
960
- allowFailure: true
961
- });
962
- return Array.isArray(payload?.result) ? payload.result : [];
963
- }
964
- function listQueues(tenantRoot, env) {
965
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
966
- if (!accountId) {
967
- return [];
968
- }
969
- const payload = cloudflareApiRequest(`/accounts/${encodeURIComponent(accountId)}/queues`, {
970
- env,
971
- allowFailure: true
972
- });
973
- return Array.isArray(payload?.result) ? payload.result : [];
974
- }
975
- function listR2Buckets(tenantRoot, env) {
976
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
977
- if (!accountId) {
978
- return [];
979
- }
980
- const payload = cloudflareApiRequest(`/accounts/${encodeURIComponent(accountId)}/r2/buckets`, {
981
- env,
982
- allowFailure: true
983
- });
984
- return Array.isArray(payload?.result?.buckets) ? payload.result.buckets : [];
985
- }
986
- function listPagesProjects(tenantRoot, env) {
987
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
988
- if (!accountId) {
989
- return [];
990
- }
991
- const payload = cloudflareApiRequest(`/accounts/${encodeURIComponent(accountId)}/pages/projects`, {
992
- env,
993
- allowFailure: true
994
- });
995
- return Array.isArray(payload?.result) ? payload.result : [];
996
- }
997
- function listTurnstileWidgets(tenantRoot, env) {
998
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
999
- if (!accountId) {
1000
- return [];
1001
- }
1002
- const payload = cloudflareApiRequest(`/accounts/${encodeURIComponent(accountId)}/challenges/widgets?per_page=100`, {
1003
- env,
1004
- allowFailure: true
1005
- });
1006
- return Array.isArray(payload?.result) ? payload.result : [];
1007
- }
1008
- function listWorkers(tenantRoot, env) {
1009
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
1010
- if (!accountId) {
1011
- return [];
1012
- }
1013
- const payload = cloudflareApiRequest(`/accounts/${encodeURIComponent(accountId)}/workers/services?per_page=100`, {
1014
- env,
1015
- allowFailure: true
1016
- });
1017
- return Array.isArray(payload?.result) ? payload.result : [];
1018
- }
1019
- function listDnsZones(env) {
1020
- const payload = cloudflareApiRequest("/zones?per_page=100", {
1021
- env,
1022
- allowFailure: true
1023
- });
1024
- return Array.isArray(payload?.result) ? payload.result : [];
1025
- }
1026
- function listDnsRecords(zoneId, env) {
1027
- if (!zoneId) {
1028
- return [];
1029
- }
1030
- const records = [];
1031
- let page = 1;
1032
- let totalPages = 1;
1033
- while (page <= totalPages && page <= 50) {
1034
- const payload = cloudflareApiRequest(
1035
- `/zones/${encodeURIComponent(zoneId)}/dns_records?per_page=100&page=${page}`,
1036
- { env, allowFailure: true }
1037
- );
1038
- if (payload?.success === false) {
1039
- break;
1040
- }
1041
- if (Array.isArray(payload?.result)) {
1042
- records.push(...payload.result);
1043
- }
1044
- const reportedTotal = Number(payload?.result_info?.total_pages);
1045
- totalPages = Number.isFinite(reportedTotal) && reportedTotal > 0 ? reportedTotal : page;
1046
- page += 1;
1047
- }
1048
- return records;
1049
- }
1050
- function getTurnstileWidget(env, sitekey) {
1051
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
1052
- if (!accountId || !sitekey) {
1053
- return null;
1054
- }
1055
- const payload = cloudflareApiRequest(
1056
- `/accounts/${encodeURIComponent(accountId)}/challenges/widgets/${encodeURIComponent(sitekey)}`,
1057
- { env, allowFailure: true }
1058
- );
1059
- return payload?.result ?? null;
1060
- }
1061
- function createTurnstileWidget(env, input) {
1062
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
1063
- if (!accountId) {
1064
- throw new Error("Configure CLOUDFLARE_ACCOUNT_ID before creating Turnstile widgets.");
1065
- }
1066
- try {
1067
- return cloudflareApiRequest(`/accounts/${encodeURIComponent(accountId)}/challenges/widgets`, {
1068
- method: "POST",
1069
- env,
1070
- body: {
1071
- name: input.name,
1072
- domains: input.domains ?? [],
1073
- mode: input.mode ?? "managed"
1074
- }
1075
- })?.result ?? null;
1076
- } catch (error) {
1077
- const detail = error instanceof Error ? error.message : String(error);
1078
- throw new Error(`Cloudflare Turnstile widget creation failed. Ensure the API token has Turnstile Sites Write permission: ${detail}`);
1079
- }
1080
- }
1081
- function updateTurnstileWidget(env, sitekey, input) {
1082
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
1083
- if (!accountId || !sitekey) {
1084
- throw new Error("Configure CLOUDFLARE_ACCOUNT_ID and sitekey before updating Turnstile widgets.");
1085
- }
1086
- try {
1087
- return cloudflareApiRequest(`/accounts/${encodeURIComponent(accountId)}/challenges/widgets/${encodeURIComponent(sitekey)}`, {
1088
- method: "PUT",
1089
- env,
1090
- body: {
1091
- name: input.name,
1092
- domains: input.domains ?? [],
1093
- mode: input.mode ?? "managed"
1094
- }
1095
- })?.result ?? null;
1096
- } catch (error) {
1097
- const detail = error instanceof Error ? error.message : String(error);
1098
- throw new Error(`Cloudflare Turnstile widget update failed. Ensure the API token has Turnstile Sites Write permission: ${detail}`);
1099
- }
1100
- }
1101
- function buildCloudflarePagesFunctionBindings(state) {
1102
- const kvNamespaces = Object.fromEntries(
1103
- Object.entries(state.kvNamespaces ?? {}).map(([key, namespace]) => {
1104
- const binding = namespace?.binding ?? key;
1105
- const namespaceId = namespace?.id;
1106
- return binding && namespaceId && !isPlaceholderResourceId(namespaceId) ? [binding, { namespace_id: namespaceId }] : null;
1107
- }).filter(Boolean)
1108
- );
1109
- const database = state.d1Databases?.SITE_DATA_DB;
1110
- const d1Databases = database?.binding && database?.databaseId && !isPlaceholderResourceId(database.databaseId) ? { [database.binding]: { id: database.databaseId } } : {};
1111
- const contentBinding = state.content?.r2Binding;
1112
- const contentBucketName = state.content?.bucketName;
1113
- const r2Buckets = contentBinding && contentBucketName ? { [contentBinding]: { name: contentBucketName } } : {};
1114
- return {
1115
- ...Object.keys(kvNamespaces).length ? { kv_namespaces: kvNamespaces } : {},
1116
- ...Object.keys(d1Databases).length ? { d1_databases: d1Databases } : {},
1117
- ...Object.keys(r2Buckets).length ? { r2_buckets: r2Buckets } : {}
1118
- };
1119
- }
1120
- function mergeCloudflarePagesDeploymentConfig(config = {}, bindings = {}) {
1121
- return Object.entries(bindings).reduce((merged, [key, value]) => ({
1122
- ...merged,
1123
- [key]: {
1124
- ...merged[key] ?? {},
1125
- ...value
1126
- }
1127
- }), { ...config });
1128
- }
1129
- function ensurePagesProjectCompatibility(accountId, projectName, env, currentProject = null, options = {}) {
1130
- if (!accountId || !projectName) {
1131
- return;
1132
- }
1133
- const projectPath = `/accounts/${encodeURIComponent(accountId)}/pages/projects/${encodeURIComponent(projectName)}`;
1134
- const latestProject = cloudflareApiRequest(projectPath, { env, allowFailure: true })?.result ?? currentProject;
1135
- const currentConfigs = latestProject?.deployment_configs ?? {};
1136
- const target = options.target;
1137
- const targetConfigKey = target?.kind === "persistent" && target.scope === "prod" ? "production" : "preview";
1138
- const bindings = options.state ? buildCloudflarePagesFunctionBindings(options.state) : {};
1139
- const mergeCompatibility = (config = {}) => ({
1140
- ...config,
1141
- compatibility_date: config.compatibility_date ?? DEFAULT_COMPATIBILITY_DATE,
1142
- compatibility_flags: [.../* @__PURE__ */ new Set([...config.compatibility_flags ?? [], ...DEFAULT_COMPATIBILITY_FLAGS])]
1143
- });
1144
- const mergeTarget = (key, config = {}) => {
1145
- const compatible = mergeCompatibility(config);
1146
- return key === targetConfigKey && Object.keys(bindings).length ? mergeCloudflarePagesDeploymentConfig(compatible, bindings) : compatible;
1147
- };
1148
- cloudflareApiRequest(
1149
- projectPath,
1150
- {
1151
- method: "PATCH",
1152
- env,
1153
- body: {
1154
- deployment_configs: {
1155
- ...currentConfigs,
1156
- preview: mergeTarget("preview", currentConfigs.preview),
1157
- production: mergeTarget("production", currentConfigs.production)
1158
- }
1159
- }
1160
- }
1161
- );
1162
- }
1163
- function isPlaceholderResourceId(value) {
1164
- if (!value || typeof value !== "string") {
1165
- return true;
1166
- }
1167
- return value.startsWith("local-") || value.startsWith("plan-") || value.endsWith("-id") || value.endsWith("-preview-id");
1168
- }
1169
- function buildProvisioningSummary(deployConfig, state, target) {
1170
- const webCachePolicy = resolveTreeseedWebCachePolicy(deployConfig);
1171
- const identity = state.identity ?? resolveTreeseedResourceIdentity(deployConfig, target);
1172
- const configuredWebDomain = resolveConfiguredSurfaceDomain(deployConfig, target, "web");
1173
- const configuredApiDomain = resolveConfiguredSurfaceDomain(deployConfig, target, "api");
1174
- return {
1175
- target: deployTargetLabel(target),
1176
- identity,
1177
- workerName: state.workerName ?? targetWorkerName(deployConfig, target),
1178
- siteUrl: target.kind === "branch" ? targetWorkersDevUrl(state.workerName) : deployConfig.siteUrl,
1179
- accountId: resolveConfiguredCloudflareAccountId(deployConfig),
1180
- pages: state.pages ?? null,
1181
- turnstileWidget: state.turnstileWidgets?.formGuard ?? null,
1182
- formGuardKv: state.kvNamespaces.FORM_GUARD_KV,
1183
- sessionKv: state.kvNamespaces.SESSION ?? null,
1184
- siteDataDb: state.d1Databases.SITE_DATA_DB,
1185
- content: state.content ?? null,
1186
- resources: {
1187
- pagesProject: state.pages?.projectName ?? null,
1188
- contentBucket: state.content?.bucketName ?? null,
1189
- database: state.d1Databases?.SITE_DATA_DB?.databaseName ?? null,
1190
- turnstileWidget: state.turnstileWidgets?.formGuard?.name ?? null,
1191
- formGuardKv: state.kvNamespaces?.FORM_GUARD_KV?.name ?? null,
1192
- railwayProject: state.services?.worker?.projectName ?? state.services?.api?.projectName ?? null,
1193
- webDomain: configuredWebDomain,
1194
- apiDomain: configuredApiDomain,
1195
- railwayServices: Object.fromEntries(
1196
- Object.entries(state.services ?? {}).filter(([, service]) => service?.enabled === true).map(([serviceKey, service]) => [serviceKey, service?.serviceName ?? null])
1197
- )
1198
- },
1199
- webCache: {
1200
- webHost: state.webCache?.webHost ?? null,
1201
- contentHost: state.webCache?.contentHost ?? null,
1202
- rulesManaged: state.webCache?.rulesManaged === true,
1203
- lastSyncedAt: state.webCache?.lastSyncedAt ?? null,
1204
- lastError: state.webCache?.lastError ?? null,
1205
- policy: webCachePolicy,
1206
- deployPurge: state.webCache?.deployPurge ?? null,
1207
- contentPurge: state.webCache?.contentPurge ?? null
1208
- }
1209
- };
1210
- }
1211
- function safeUrl(value) {
1212
- try {
1213
- return new URL(value);
1214
- } catch {
1215
- return null;
1216
- }
1217
- }
1218
- function normalizePathPrefix(pathname) {
1219
- const normalized = String(pathname ?? "").replace(/\/+$/u, "");
1220
- if (!normalized || normalized === "/") {
1221
- return "";
1222
- }
1223
- return normalized.startsWith("/") ? normalized : `/${normalized}`;
1224
- }
1225
- function resolvePublicWebCacheTarget(deployConfig) {
1226
- const parsed = safeUrl(deployConfig.surfaces?.web?.publicBaseUrl ?? deployConfig.siteUrl);
1227
- if (!parsed) {
1228
- return null;
1229
- }
1230
- return {
1231
- host: parsed.hostname,
1232
- pathPrefix: normalizePathPrefix(parsed.pathname)
1233
- };
1234
- }
1235
- function resolvePublicContentCacheTarget(deployConfig) {
1236
- const parsed = safeUrl(resolveConfiguredContentPublicBaseUrl(deployConfig));
1237
- if (!parsed) {
1238
- return null;
1239
- }
1240
- return {
1241
- host: parsed.hostname,
1242
- pathPrefix: normalizePathPrefix(parsed.pathname)
1243
- };
1244
- }
1245
- function shouldManageCloudflareWebCacheRules(deployConfig, target) {
1246
- if (target.kind !== "persistent" || target.scope !== "prod") {
1247
- return false;
1248
- }
1249
- if ((deployConfig.surfaces?.web?.provider ?? deployConfig.providers?.deploy) !== "cloudflare") {
1250
- return false;
1251
- }
1252
- const webTarget = resolvePublicWebCacheTarget(deployConfig);
1253
- return Boolean(webTarget?.host && !webTarget.host.endsWith(".workers.dev") && !webTarget.host.endsWith(".pages.dev"));
1254
- }
1255
- function cloudflareApiRequest(path, { method = "GET", body, env, allowFailure = false } = {}) {
1256
- const token = env?.TREESEED_CLOUDFLARE_API_TOKEN ?? env?.CLOUDFLARE_API_TOKEN ?? process.env.TREESEED_CLOUDFLARE_API_TOKEN ?? "";
1257
- if (!token) {
1258
- if (allowFailure) {
1259
- return null;
1260
- }
1261
- throw new Error(`Cloudflare API token is required: ${method} ${path}`);
1262
- }
1263
- const requestScript = `import { readFileSync } from 'node:fs';
1264
- import { request } from 'node:https';
1265
- const input = JSON.parse(readFileSync(0, 'utf8') || '{}');
1266
- function errorMessage(error) {
1267
- const parts = [];
1268
- if (error && typeof error.message === 'string') parts.push(error.message);
1269
- const cause = error?.cause;
1270
- if (cause && typeof cause.message === 'string') parts.push(cause.message);
1271
- if (cause && typeof cause.code === 'string') parts.push(cause.code);
1272
- if (Array.isArray(cause?.errors)) {
1273
- for (const entry of cause.errors) {
1274
- if (entry && typeof entry.message === 'string') parts.push(entry.message);
1275
- if (entry && typeof entry.code === 'string') parts.push(entry.code);
1276
- }
1277
- }
1278
- return [...new Set(parts.filter(Boolean))].join('; ') || String(error);
1279
- }
1280
- try {
1281
- const body = input.body ? JSON.stringify(input.body) : undefined;
1282
- const response = await new Promise((resolve, reject) => {
1283
- const req = request(input.url, {
1284
- method: input.method,
1285
- headers: {
1286
- authorization: 'Bearer ' + input.token,
1287
- 'content-type': 'application/json',
1288
- },
1289
- timeout: input.timeoutMs ?? 12000,
1290
- }, (res) => {
1291
- const chunks = [];
1292
- res.setEncoding('utf8');
1293
- res.on('data', (chunk) => chunks.push(chunk));
1294
- res.on('end', () => resolve({
1295
- ok: typeof res.statusCode === 'number' && res.statusCode >= 200 && res.statusCode < 300,
1296
- text: chunks.join(''),
1297
- }));
1298
- });
1299
- req.on('timeout', () => {
1300
- req.destroy(new Error('Cloudflare API request timed out'));
1301
- });
1302
- req.on('error', reject);
1303
- if (body) req.write(body);
1304
- req.end();
1305
- });
1306
- const rawBody = response.text;
1307
- let payload;
1308
- try {
1309
- payload = rawBody ? JSON.parse(rawBody) : {};
1310
- } catch {
1311
- payload = { success: false, errors: [{ message: rawBody || 'empty response' }] };
1312
- }
1313
- process.stdout.write(JSON.stringify({ ok: response.ok, payload }));
1314
- } catch (error) {
1315
- process.stdout.write(JSON.stringify({
1316
- ok: false,
1317
- transient: true,
1318
- payload: { success: false, errors: [{ message: errorMessage(error) }] },
1319
- }));
1320
- }`;
1321
- const requestInput = JSON.stringify({
1322
- url: `https://api.cloudflare.com/client/v4${path}`,
1323
- method,
1324
- body,
1325
- timeoutMs: 12e3,
1326
- token
1327
- });
1328
- const isTransient = (text) => /fetch failed|timed out|etimedout|econnreset|enetunreach|temporarily unavailable|aborted|rate limit|too many requests|throttl|please wait/iu.test(text || "");
1329
- const retryDelay = (text, currentAttempt) => {
1330
- const base = /rate limit|too many requests|throttl|please wait/iu.test(text || "") ? 2500 : 500;
1331
- return base * (currentAttempt + 1);
1332
- };
1333
- const formatPayloadErrors = (payload) => Array.isArray(payload?.errors) ? payload.errors.map((entry) => entry?.message ?? JSON.stringify(entry)).join("; ") : "";
1334
- const summarizeChildError = (text) => {
1335
- const lines = String(text || "").split("\n").map((line) => line.trim()).filter(Boolean);
1336
- return lines.find((line) => /fetch failed|timed out|etimedout|econnreset|enetunreach|temporarily unavailable|aborted|typeerror|error/iu.test(line)) ?? lines[0] ?? "";
1337
- };
1338
- let attempt = 0;
1339
- for (; ; ) {
1340
- const response = spawnSync(
1341
- process.execPath,
1342
- [
1343
- "--input-type=module",
1344
- "-e",
1345
- requestScript
1346
- ],
1347
- {
1348
- stdio: ["pipe", "pipe", "pipe"],
1349
- encoding: "utf8",
1350
- env: { ...process.env, ...env ?? {} },
1351
- input: requestInput,
1352
- timeout: 15e3
1353
- }
1354
- );
1355
- if (response.error?.code === "ETIMEDOUT") {
1356
- if (attempt < 7) {
1357
- attempt += 1;
1358
- sleepSync(retryDelay("timed out", attempt));
1359
- continue;
1360
- }
1361
- if (!allowFailure) {
1362
- throw new Error(`Cloudflare API request timed out after ${attempt + 1} attempts: ${method} ${path}`);
1363
- }
1364
- return null;
1365
- }
1366
- const stderr = response.stderr?.trim() || "";
1367
- if (response.status !== 0) {
1368
- if (attempt < 7 && isTransient(stderr)) {
1369
- attempt += 1;
1370
- sleepSync(retryDelay(stderr, attempt));
1371
- continue;
1372
- }
1373
- if (!allowFailure) {
1374
- const detail = summarizeChildError(stderr);
1375
- throw new Error(detail ? `Cloudflare API request failed after ${attempt + 1} attempts: ${method} ${path}: ${detail}` : `Cloudflare API request failed after ${attempt + 1} attempts: ${method} ${path}`);
1376
- }
1377
- }
1378
- let parsed;
1379
- try {
1380
- parsed = JSON.parse(response.stdout?.trim() || '{"ok":false,"payload":{"success":false,"errors":[{"message":"empty response"}]}}');
1381
- } catch {
1382
- parsed = {
1383
- ok: false,
1384
- payload: {
1385
- success: false,
1386
- errors: [{ message: response.stdout?.trim() || stderr || "empty response" }]
1387
- }
1388
- };
1389
- }
1390
- const details = formatPayloadErrors(parsed.payload);
1391
- if (!parsed.ok && isTransient(details) && attempt < 7) {
1392
- attempt += 1;
1393
- sleepSync(retryDelay(details, attempt));
1394
- continue;
1395
- }
1396
- if (!parsed.ok && !allowFailure) {
1397
- throw new Error(details ? `Cloudflare API request failed after ${attempt + 1} attempts: ${method} ${path}: ${details}` : `Cloudflare API request failed after ${attempt + 1} attempts: ${method} ${path}`);
1398
- }
1399
- return parsed.payload;
1400
- }
1401
- }
1402
- function resolveCloudflareZoneIdForHost(deployConfig, host, env) {
1403
- if (deployConfig.cloudflare.zoneId) {
1404
- return deployConfig.cloudflare.zoneId;
1405
- }
1406
- const result = cloudflareApiRequest(`/zones?name=${encodeURIComponent(host)}`, { env, allowFailure: true });
1407
- const exact = Array.isArray(result?.result) ? result.result.find((zone) => zone?.name === host) : null;
1408
- if (exact?.id) {
1409
- return exact.id;
1410
- }
1411
- const fallback = cloudflareApiRequest("/zones", { env, allowFailure: true });
1412
- const zones = Array.isArray(fallback?.result) ? fallback.result : [];
1413
- const matched = zones.filter((zone) => typeof zone?.name === "string" && (host === zone.name || host.endsWith(`.${zone.name}`))).sort((left, right) => String(right.name).length - String(left.name).length)[0];
1414
- return matched?.id ?? null;
1415
- }
1416
- function listCloudflareZoneRulesets(zoneId, env) {
1417
- const result = cloudflareApiRequest(`/zones/${zoneId}/rulesets`, { env, allowFailure: true });
1418
- return Array.isArray(result?.result) ? result.result : [];
1419
- }
1420
- function joinCloudflareAndExpression(clauses) {
1421
- const parts = clauses.map((clause) => typeof clause === "string" ? clause.trim() : "").filter((clause) => clause.length > 0).map((clause) => clause.startsWith("(") && clause.endsWith(")") ? clause : `(${clause})`);
1422
- if (parts.length === 0) {
1423
- throw new Error("Cannot build a Cloudflare expression without predicates.");
1424
- }
1425
- return `(${parts.join(" and ")})`;
1426
- }
1427
- function buildTreeseedManagedCloudflareCacheRules(deployConfig, cacheTarget, kind) {
1428
- if (!cacheTarget?.host) {
1429
- return [];
1430
- }
1431
- const policy = resolveTreeseedWebCachePolicy(deployConfig);
1432
- const cachePolicy = kind === "web" ? policy.contentPages : policy.r2PublishedObjects;
1433
- const hostExpression = `(http.host eq "${cacheTarget.host}")`;
1434
- const pathExpression = cacheTarget.pathPrefix ? `(starts_with(http.request.uri.path, "${cacheTarget.pathPrefix}/") or (http.request.uri.path eq "${cacheTarget.pathPrefix}"))` : null;
1435
- if (kind === "content") {
1436
- return [
1437
- {
1438
- description: "treeseed-managed: cache public r2 objects",
1439
- expression: joinCloudflareAndExpression([
1440
- hostExpression,
1441
- pathExpression,
1442
- '(http.request.method in {"GET" "HEAD"})'
1443
- ]),
1444
- action: "set_cache_settings",
1445
- action_parameters: {
1446
- cache: true,
1447
- edge_ttl: {
1448
- mode: "override_origin",
1449
- default: cachePolicy.edgeTtlSeconds
1450
- },
1451
- browser_ttl: {
1452
- mode: "override_origin",
1453
- default: cachePolicy.browserTtlSeconds
1454
- }
1455
- },
1456
- enabled: true
1457
- }
1458
- ];
1459
- }
1460
- const sourcePaths = policy.sourcePages.paths.map((path) => path === "/" ? "/" : path.replace(/\/+$/u, ""));
1461
- const sourcePathExpression = sourcePaths.length > 0 ? `(${sourcePaths.map((path) => `(http.request.uri.path eq "${path}")`).join(" or ")})` : null;
1462
- const notSourcePathExpression = sourcePaths.length > 0 ? `not ${sourcePathExpression}` : null;
1463
- const rules = [
1464
- {
1465
- description: "treeseed-managed: bypass preview and dynamic routes",
1466
- expression: joinCloudflareAndExpression([
1467
- hostExpression,
1468
- '((starts_with(http.request.uri.path, "/api/")) or (http.request.uri.path eq "/api") or (starts_with(http.request.uri.path, "/auth")) or (starts_with(http.request.uri.path, "/admin")) or (starts_with(http.request.uri.path, "/app")) or (starts_with(http.request.uri.path, "/internal")) or (http.request.uri.query contains "preview=") or (http.cookie contains "treeseed-content-preview="))'
1469
- ]),
1470
- action: "set_cache_settings",
1471
- action_parameters: {
1472
- cache: false
1473
- },
1474
- enabled: true
1475
- }
1476
- ];
1477
- if (sourcePathExpression) {
1478
- rules.push({
1479
- description: "treeseed-managed: bypass source html routes",
1480
- expression: joinCloudflareAndExpression([
1481
- hostExpression,
1482
- pathExpression,
1483
- sourcePathExpression,
1484
- '(http.request.method in {"GET" "HEAD"})'
1485
- ]),
1486
- action: "set_cache_settings",
1487
- action_parameters: {
1488
- cache: false
1489
- },
1490
- enabled: true
1491
- });
1492
- }
1493
- rules.push(
1494
- {
1495
- description: "treeseed-managed: cache content html routes",
1496
- expression: joinCloudflareAndExpression([
1497
- hostExpression,
1498
- pathExpression,
1499
- notSourcePathExpression,
1500
- '(http.request.method in {"GET" "HEAD"})',
1501
- '(http.request.uri.path.extension eq "")',
1502
- 'not (starts_with(http.request.uri.path, "/api/"))',
1503
- 'not (http.request.uri.path eq "/api")',
1504
- 'not (starts_with(http.request.uri.path, "/auth"))',
1505
- 'not (starts_with(http.request.uri.path, "/admin"))',
1506
- 'not (starts_with(http.request.uri.path, "/app"))',
1507
- 'not (starts_with(http.request.uri.path, "/internal"))',
1508
- 'not (http.request.uri.query contains "preview=")',
1509
- 'not (http.cookie contains "treeseed-content-preview=")'
1510
- ]),
1511
- action: "set_cache_settings",
1512
- action_parameters: {
1513
- cache: true,
1514
- edge_ttl: {
1515
- mode: "override_origin",
1516
- default: cachePolicy.edgeTtlSeconds
1517
- },
1518
- browser_ttl: {
1519
- mode: "override_origin",
1520
- default: cachePolicy.browserTtlSeconds
1521
- }
1522
- },
1523
- enabled: true
1524
- }
1525
- );
1526
- return rules;
1527
- }
1528
- function reconcileCloudflareCacheRulesForTarget(role, deployConfig, state, cacheTarget, env, { planOnly = false } = {}) {
1529
- const roleKey = role === "web" ? "Web" : "Content";
1530
- if (!cacheTarget?.host) {
1531
- return { managed: false, skipped: true, reason: "missing_host" };
1532
- }
1533
- const zoneId = resolveCloudflareZoneIdForHost(deployConfig, cacheTarget.host, env);
1534
- if (!zoneId) {
1535
- return { managed: false, skipped: true, reason: "zone_unresolved" };
1536
- }
1537
- const desiredRules = buildTreeseedManagedCloudflareCacheRules(deployConfig, cacheTarget, role);
1538
- state.webCache[role === "web" ? "webHost" : "contentHost"] = cacheTarget.host;
1539
- state.webCache[role === "web" ? "webZoneId" : "contentZoneId"] = zoneId;
1540
- if (planOnly) {
1541
- return { managed: true, planOnly: true, zoneId, host: cacheTarget.host, rules: desiredRules };
1542
- }
1543
- const rulesets = listCloudflareZoneRulesets(zoneId, env);
1544
- const existing = rulesets.find((ruleset) => ruleset?.phase === "http_request_cache_settings") ?? null;
1545
- const prefix = `treeseed-managed:${roleKey.toLowerCase()}:`;
1546
- const unmanagedRules = Array.isArray(existing?.rules) ? existing.rules.filter((rule) => typeof rule?.description !== "string" || !rule.description.startsWith(prefix)) : [];
1547
- const rules = [
1548
- ...unmanagedRules,
1549
- ...desiredRules.map((rule) => ({ ...rule, description: `${prefix} ${rule.description}` }))
1550
- ];
1551
- const payload = existing ? cloudflareApiRequest(`/zones/${zoneId}/rulesets/${existing.id}`, {
1552
- method: "PUT",
1553
- body: { rules },
1554
- env
1555
- }) : cloudflareApiRequest(`/zones/${zoneId}/rulesets`, {
1556
- method: "POST",
1557
- body: {
1558
- name: `Treeseed Managed ${roleKey} Cache Rules`,
1559
- kind: "zone",
1560
- phase: "http_request_cache_settings",
1561
- rules
1562
- },
1563
- env
1564
- });
1565
- const rulesetId = payload?.result?.id ?? existing?.id ?? null;
1566
- state.webCache[role === "web" ? "webRulesetId" : "contentRulesetId"] = rulesetId;
1567
- return { managed: true, zoneId, host: cacheTarget.host, rulesetId };
1568
- }
1569
- function reconcileCloudflareWebCacheRules(tenantRoot, deployConfig, state, target, { planOnly = false, env: providedEnv } = {}) {
1570
- if (!shouldManageCloudflareWebCacheRules(deployConfig, target)) {
1571
- const webTarget2 = resolvePublicWebCacheTarget(deployConfig);
1572
- const contentTarget2 = resolvePublicContentCacheTarget(deployConfig);
1573
- state.webCache.webHost = webTarget2?.host ?? null;
1574
- state.webCache.contentHost = contentTarget2?.host ?? null;
1575
- state.webCache.rulesManaged = false;
1576
- state.webCache.lastError = null;
1577
- return { managed: false, skipped: true, reason: "unsupported_target_or_host" };
1578
- }
1579
- const env = {
1580
- CLOUDFLARE_API_TOKEN: providedEnv?.CLOUDFLARE_API_TOKEN ?? process.env.TREESEED_CLOUDFLARE_API_TOKEN ?? ""
1581
- };
1582
- if (!env.CLOUDFLARE_API_TOKEN) {
1583
- state.webCache.webHost = resolvePublicWebCacheTarget(deployConfig)?.host ?? null;
1584
- state.webCache.contentHost = resolvePublicContentCacheTarget(deployConfig)?.host ?? null;
1585
- state.webCache.rulesManaged = false;
1586
- state.webCache.lastError = "CLOUDFLARE_API_TOKEN is required to manage Cloudflare Cache Rules.";
1587
- return { managed: false, skipped: true, reason: "missing_api_token" };
1588
- }
1589
- const webTarget = resolvePublicWebCacheTarget(deployConfig);
1590
- const contentTarget = resolvePublicContentCacheTarget(deployConfig);
1591
- try {
1592
- const results = [];
1593
- if (webTarget?.host) {
1594
- results.push(reconcileCloudflareCacheRulesForTarget("web", deployConfig, state, webTarget, env, { planOnly }));
1595
- }
1596
- if (contentTarget?.host) {
1597
- results.push(reconcileCloudflareCacheRulesForTarget("content", deployConfig, state, contentTarget, env, { planOnly }));
1598
- }
1599
- state.webCache.rulesManaged = true;
1600
- state.webCache.lastSyncedAt = (/* @__PURE__ */ new Date()).toISOString();
1601
- state.webCache.lastError = null;
1602
- return { managed: true, results };
1603
- } catch (error) {
1604
- const message = error instanceof Error ? error.message : String(error ?? "");
1605
- if (/Authentication error|permission/i.test(message)) {
1606
- state.webCache.rulesManaged = false;
1607
- state.webCache.lastError = message;
1608
- return { managed: false, skipped: true, reason: "auth_error", error: message };
1609
- }
1610
- throw error;
1611
- }
1612
- }
1613
- function purgeCloudflareCacheByUrls(urls, deployConfig, { env } = {}) {
1614
- const uniqueUrls = [...new Set((urls ?? []).filter(Boolean))];
1615
- if (uniqueUrls.length === 0) {
1616
- return [];
1617
- }
1618
- const grouped = /* @__PURE__ */ new Map();
1619
- for (const urlValue of uniqueUrls) {
1620
- const parsed = safeUrl(urlValue);
1621
- if (!parsed) {
1622
- continue;
1623
- }
1624
- const zoneId = resolveCloudflareZoneIdForHost(deployConfig, parsed.hostname, env);
1625
- if (!zoneId) {
1626
- continue;
1627
- }
1628
- const current = grouped.get(zoneId) ?? [];
1629
- current.push(parsed.toString());
1630
- grouped.set(zoneId, current);
1631
- }
1632
- return [...grouped.entries()].map(([zoneId, files]) => {
1633
- const payload = cloudflareApiRequest(`/zones/${zoneId}/purge_cache`, {
1634
- method: "POST",
1635
- body: { files: [...new Set(files)] },
1636
- env
1637
- });
1638
- const errors = Array.isArray(payload?.errors) ? payload.errors.map((entry) => entry?.message ?? JSON.stringify(entry)).filter(Boolean) : [];
1639
- return {
1640
- zoneId,
1641
- count: [...new Set(files)].length,
1642
- success: payload?.success === true,
1643
- errors
1644
- };
1645
- });
1646
- }
1647
- function purgeCloudflareCacheEverythingByHosts(hosts, deployConfig, { env } = {}) {
1648
- const zoneIds = [...new Set((hosts ?? []).map((host) => typeof host === "string" ? host.trim() : "").filter(Boolean).map((host) => resolveCloudflareZoneIdForHost(deployConfig, host, env)).filter(Boolean))];
1649
- return zoneIds.map((zoneId) => {
1650
- const payload = cloudflareApiRequest(`/zones/${zoneId}/purge_cache`, {
1651
- method: "POST",
1652
- body: { purge_everything: true },
1653
- env
1654
- });
1655
- const errors = Array.isArray(payload?.errors) ? payload.errors.map((entry) => entry?.message ?? JSON.stringify(entry)).filter(Boolean) : [];
1656
- return {
1657
- zoneId,
1658
- count: "everything",
1659
- success: payload?.success === true,
1660
- errors
1661
- };
1662
- });
1663
- }
1664
- function assertCloudflareCachePurgeSucceeded(results) {
1665
- const failures = (results ?? []).filter((result) => result?.success !== true);
1666
- if (failures.length === 0) return;
1667
- const detail = failures.map((result) => {
1668
- const errors = Array.isArray(result?.errors) && result.errors.length > 0 ? `: ${result.errors.join("; ")}` : "";
1669
- return `${result?.zoneId ?? "unknown-zone"} (${result?.count ?? 0} urls)${errors}`;
1670
- }).join(", ");
1671
- throw new Error(`Cloudflare cache purge did not succeed for ${detail}.`);
1672
- }
1673
- function queueName(entry) {
1674
- return entry?.queue_name ?? entry?.queueName ?? entry?.name ?? null;
1675
- }
1676
- function queueId(entry) {
1677
- return entry?.queue_id ?? entry?.queueId ?? entry?.id ?? entry?.uuid ?? null;
1678
- }
1679
- function hasProvisionedCloudflareResources(state) {
1680
- return Boolean(
1681
- state?.pages?.projectName && state?.pages?.url && state?.d1Databases?.SITE_DATA_DB?.databaseId && state?.kvNamespaces?.FORM_GUARD_KV?.id && state?.content?.bucketName
1682
- );
1683
- }
1684
- function absoluteUrlForPath(baseUrl, path) {
1685
- const parsed = safeUrl(baseUrl);
1686
- if (!parsed) {
1687
- return null;
1688
- }
1689
- const normalizedPath = String(path ?? "").startsWith("/") ? String(path) : `/${String(path ?? "")}`;
1690
- return new URL(normalizedPath, parsed).toString();
1691
- }
1692
- function resolveSourcePagePurgeUrls(deployConfig) {
1693
- const webBaseUrl = deployConfig.surfaces?.web?.publicBaseUrl ?? deployConfig.siteUrl;
1694
- const paths = resolveTreeseedWebCachePolicy(deployConfig).sourcePages.paths;
1695
- return paths.map((path) => absoluteUrlForPath(webBaseUrl, path)).filter(Boolean);
1696
- }
1697
- function recordCachePurgeResult(targetState, results, error = null) {
1698
- if (error) {
1699
- targetState.lastError = error instanceof Error ? error.message : String(error);
1700
- return;
1701
- }
1702
- targetState.lastPurgedAt = (/* @__PURE__ */ new Date()).toISOString();
1703
- targetState.purgeCount = Array.isArray(results) ? results.reduce((sum, result) => sum + (typeof result?.count === "number" ? result.count : 0), 0) : 0;
1704
- targetState.lastError = null;
1705
- }
1706
- function resolveCloudflareCachePurgeEnv(options = {}) {
1707
- const env = options.env ?? {};
1708
- const token = env.TREESEED_CLOUDFLARE_API_TOKEN ?? env.CLOUDFLARE_API_TOKEN ?? process.env.TREESEED_CLOUDFLARE_API_TOKEN ?? process.env.CLOUDFLARE_API_TOKEN;
1709
- return token ? { ...env, TREESEED_CLOUDFLARE_API_TOKEN: token, CLOUDFLARE_API_TOKEN: token } : null;
1710
- }
1711
- function purgeSourcePageCaches(tenantRoot, options = {}) {
1712
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
1713
- const deployConfig = loadTenantDeployConfig(tenantRoot);
1714
- const state = loadDeployState(tenantRoot, deployConfig, { target });
1715
- const urls = resolveSourcePagePurgeUrls(deployConfig);
1716
- const env = resolveCloudflareCachePurgeEnv(options);
1717
- if ((options.planOnly ?? false) || urls.length === 0 || !env) {
1718
- recordCachePurgeResult(state.webCache.deployPurge, urls.map((url) => ({ count: url ? 1 : 0 })));
1719
- writeDeployState(tenantRoot, state, { target });
1720
- return {
1721
- skipped: true,
1722
- reason: options.planOnly ? "plan" : urls.length === 0 ? "no_urls" : "missing_cloudflare_token",
1723
- urls,
1724
- results: []
1725
- };
1726
- }
1727
- try {
1728
- const results = purgeCloudflareCacheByUrls(urls, deployConfig, {
1729
- env
1730
- });
1731
- const hosts = [...new Set(urls.map((url) => safeUrl(url)?.hostname).filter(Boolean))];
1732
- const allResults = target.scope === "prod" ? purgeCloudflareCacheEverythingByHosts(hosts, deployConfig, { env }) : [];
1733
- assertCloudflareCachePurgeSucceeded([...results, ...allResults]);
1734
- recordCachePurgeResult(state.webCache.deployPurge, [...results, ...allResults]);
1735
- writeDeployState(tenantRoot, state, { target });
1736
- return { urls, results: [...results, ...allResults] };
1737
- } catch (error) {
1738
- recordCachePurgeResult(state.webCache.deployPurge, [], error);
1739
- writeDeployState(tenantRoot, state, { target });
1740
- throw error;
1741
- }
1742
- }
1743
- function purgePublishedContentCaches(tenantRoot, urls, options = {}) {
1744
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
1745
- const deployConfig = loadTenantDeployConfig(tenantRoot);
1746
- const state = loadDeployState(tenantRoot, deployConfig, { target });
1747
- const env = resolveCloudflareCachePurgeEnv(options);
1748
- if ((options.planOnly ?? false) || !urls?.length || !env) {
1749
- recordCachePurgeResult(state.webCache.contentPurge, (urls ?? []).map((url) => ({ count: url ? 1 : 0 })));
1750
- writeDeployState(tenantRoot, state, { target });
1751
- return {
1752
- skipped: true,
1753
- reason: options.planOnly ? "plan" : !urls?.length ? "no_urls" : "missing_cloudflare_token",
1754
- urls: urls ?? [],
1755
- results: []
1756
- };
1757
- }
1758
- try {
1759
- const results = purgeCloudflareCacheByUrls(urls, deployConfig, {
1760
- env
1761
- });
1762
- assertCloudflareCachePurgeSucceeded(results);
1763
- recordCachePurgeResult(state.webCache.contentPurge, results);
1764
- writeDeployState(tenantRoot, state, { target });
1765
- return { urls, results };
1766
- } catch (error) {
1767
- recordCachePurgeResult(state.webCache.contentPurge, [], error);
1768
- writeDeployState(tenantRoot, state, { target });
1769
- throw error;
1770
- }
1771
- }
1772
- function buildDestroySummary(deployConfig, state, target) {
1773
- return buildProvisioningSummary(deployConfig, state, target);
1774
- }
1775
- function isPlaceholderAccountId(value) {
1776
- return !value || value === "replace-with-cloudflare-account-id";
1777
- }
1778
- function resolveConfiguredCloudflareAccountId(deployConfig) {
1779
- return envOrNull("CLOUDFLARE_ACCOUNT_ID") ?? deployConfig.cloudflare.accountId;
1780
- }
1781
- function normalizeConfiguredBaseUrl(value) {
1782
- const raw = typeof value === "string" ? value.trim() : "";
1783
- if (!raw) {
1784
- return null;
1785
- }
1786
- return raw.replace(/\/+$/u, "");
1787
- }
1788
- function domainBaseUrl(domain) {
1789
- const raw = typeof domain === "string" ? domain.trim() : "";
1790
- if (!raw) {
1791
- return null;
1792
- }
1793
- if (/^https?:\/\//iu.test(raw)) {
1794
- return normalizeConfiguredBaseUrl(raw);
1795
- }
1796
- return `https://${raw.replace(/^\/+|\/+$/gu, "")}`;
1797
- }
1798
- function targetEnvironmentKey(target) {
1799
- if (target?.kind === "persistent") {
1800
- return target.scope;
1801
- }
1802
- return "staging";
1803
- }
1804
- function resolveConfiguredApiConnectionBaseUrl(deployConfig, target) {
1805
- const scope = targetEnvironmentKey(target);
1806
- if (scope === "local") {
1807
- return normalizeConfiguredBaseUrl(deployConfig.connections?.api?.localBaseUrl) ?? normalizeConfiguredBaseUrl(deployConfig.connections?.api?.environments?.local?.baseUrl) ?? domainBaseUrl(deployConfig.connections?.api?.environments?.local?.domain);
1808
- }
1809
- return normalizeConfiguredBaseUrl(deployConfig.connections?.api?.environments?.[scope]?.baseUrl) ?? domainBaseUrl(deployConfig.connections?.api?.environments?.[scope]?.domain);
1810
- }
1811
- function resolveConfiguredMarketBaseUrl(deployConfig, target) {
1812
- return resolveConfiguredApiConnectionBaseUrl(deployConfig, target) ?? envOrNull("TREESEED_API_BASE_URL") ?? deployConfig.runtime?.marketBaseUrl ?? deployConfig.hosting?.marketBaseUrl ?? envOrNull("TREESEED_CENTRAL_MARKET_API_BASE_URL") ?? DEFAULT_TREESEED_MARKET_BASE_URL;
1813
- }
1814
- function resolveConfiguredCentralMarketBaseUrl(deployConfig, target) {
1815
- return resolveConfiguredApiConnectionBaseUrl(deployConfig, target) ?? envOrNull("TREESEED_CENTRAL_MARKET_API_BASE_URL") ?? DEFAULT_TREESEED_MARKET_BASE_URL;
1816
- }
1817
- function resolveConfiguredPagesProjectName(deployConfig) {
1818
- return sharedDeploymentName(resolveTreeseedResourceIdentity(deployConfig, createPersistentDeployTarget("prod")));
1819
- }
1820
- function resolveConfiguredContentBucketBinding(deployConfig) {
1821
- return envOrNull("TREESEED_CONTENT_BUCKET_BINDING") ?? deployConfig.cloudflare.r2?.binding ?? "TREESEED_CONTENT_BUCKET";
1822
- }
1823
- function resolveConfiguredContentBucketName(deployConfig) {
1824
- return sharedDeploymentName(resolveTreeseedResourceIdentity(deployConfig, createPersistentDeployTarget("prod")), "content");
1825
- }
1826
- function resolveConfiguredContentPublicBaseUrl(deployConfig) {
1827
- return envOrNull("TREESEED_CONTENT_PUBLIC_BASE_URL") ?? deployConfig.cloudflare.r2?.publicBaseUrl ?? "";
1828
- }
1829
- function missingTurnstileRequirements() {
1830
- return [];
1831
- }
1832
- function missingContentRuntimeRequirements(deployConfig) {
1833
- const issues = [];
1834
- if (deployConfig.providers?.content?.runtime === "team_scoped_r2_overlay") {
1835
- if (!resolveConfiguredContentBucketName(deployConfig)) {
1836
- issues.push("Set TREESEED_CONTENT_BUCKET_NAME before deploying team-scoped hosted content.");
1837
- }
1838
- if (!envOrNull("TREESEED_EDITORIAL_PREVIEW_SECRET")) {
1839
- issues.push("Set TREESEED_EDITORIAL_PREVIEW_SECRET before deploying team-scoped hosted content.");
1840
- }
1841
- }
1842
- return issues;
1843
- }
1844
- function collectMissingDeployInputs(tenantRoot) {
1845
- const deployConfig = loadTenantDeployConfig(tenantRoot);
1846
- const missing = [];
1847
- if (isPlaceholderAccountId(deployConfig.cloudflare.accountId)) {
1848
- missing.push({
1849
- key: "CLOUDFLARE_ACCOUNT_ID",
1850
- label: "Cloudflare account ID",
1851
- message: "Cloudflare account ID is missing. Set CLOUDFLARE_ACCOUNT_ID with treeseed config or provide it now."
1852
- });
1853
- }
1854
- if (deployConfig.providers?.content?.runtime === "team_scoped_r2_overlay" && !envOrNull("TREESEED_EDITORIAL_PREVIEW_SECRET")) {
1855
- missing.push({
1856
- key: "TREESEED_EDITORIAL_PREVIEW_SECRET",
1857
- label: "Editorial preview signing secret",
1858
- message: "Editorial preview signing secret is missing for deploy."
1859
- });
1860
- }
1861
- return missing;
1862
- }
1863
- async function promptForMissingDeployInputs(tenantRoot) {
1864
- const missing = collectMissingDeployInputs(tenantRoot);
1865
- if (!missing.length || !process.stdin.isTTY || !process.stdout.isTTY) {
1866
- return { prompted: false, provided: [] };
1867
- }
1868
- const rl = createInterface({
1869
- input: process.stdin,
1870
- output: process.stdout
1871
- });
1872
- const provided = [];
1873
- try {
1874
- console.log("Treeseed deploy needs a few missing values before it can continue.");
1875
- console.log("These values will be used for this deploy process only. Persist them in your env files or CI secrets afterward.");
1876
- for (const item of missing) {
1877
- console.log(`- ${item.message}`);
1878
- const answer = (await rl.question(`${item.label}: `)).trim();
1879
- if (!answer) {
1880
- continue;
1881
- }
1882
- process.env[item.key] = answer;
1883
- provided.push(item.key);
1884
- }
1885
- } finally {
1886
- rl.close();
1887
- }
1888
- return { prompted: true, provided };
1889
- }
1890
- function validateDeployPrerequisites(tenantRoot, { requireRemote = true } = {}) {
1891
- const deployConfig = loadTenantDeployConfig(tenantRoot);
1892
- const issues = [];
1893
- if (isPlaceholderAccountId(deployConfig.cloudflare.accountId)) {
1894
- issues.push(
1895
- "Set CLOUDFLARE_ACCOUNT_ID with treeseed config or export it before deploying."
1896
- );
1897
- }
1898
- if (requireRemote) {
1899
- issues.push(...missingTurnstileRequirements());
1900
- issues.push(...missingContentRuntimeRequirements(deployConfig));
1901
- const result = runWrangler(["whoami"], {
1902
- cwd: tenantRoot,
1903
- allowFailure: true,
1904
- capture: true
1905
- });
1906
- const output = `${result.stdout ?? ""}
1907
- ${result.stderr ?? ""}`;
1908
- if (/You are not authenticated/i.test(output) || /wrangler login/i.test(output)) {
1909
- issues.push("Authenticate Wrangler first with `wrangler login`.");
1910
- }
1911
- }
1912
- if (issues.length > 0) {
1913
- throw new Error(`Treeseed deploy prerequisites are not satisfied:
1914
- - ${issues.join("\n- ")}`);
1915
- }
1916
- return deployConfig;
1917
- }
1918
- function validateDestroyPrerequisites(tenantRoot, { requireRemote = true } = {}) {
1919
- const deployConfig = loadTenantDeployConfig(tenantRoot);
1920
- const issues = [];
1921
- if (requireRemote && isPlaceholderAccountId(deployConfig.cloudflare.accountId)) {
1922
- issues.push(
1923
- "Set CLOUDFLARE_ACCOUNT_ID with treeseed config or export it before destroying infrastructure."
1924
- );
1925
- }
1926
- if (requireRemote) {
1927
- const result = runWrangler(["whoami"], {
1928
- cwd: tenantRoot,
1929
- allowFailure: true,
1930
- capture: true
1931
- });
1932
- const output = `${result.stdout ?? ""}
1933
- ${result.stderr ?? ""}`;
1934
- if (/You are not authenticated/i.test(output) || /wrangler login/i.test(output)) {
1935
- issues.push("Authenticate Wrangler first with `wrangler login`.");
1936
- }
1937
- }
1938
- if (issues.length > 0) {
1939
- throw new Error(`Treeseed destroy prerequisites are not satisfied:
1940
- - ${issues.join("\n- ")}`);
1941
- }
1942
- return deployConfig;
1943
- }
1944
- function resolveExistingKvIdByName(kvNamespaces, expectedName, fallbackId) {
1945
- if (fallbackId && !isPlaceholderResourceId(fallbackId)) {
1946
- return fallbackId;
1947
- }
1948
- return kvNamespaces.find((entry) => entry?.title === expectedName)?.id ?? null;
1949
- }
1950
- function resolveExistingTurnstileWidget(widgets, current) {
1951
- if (!current?.name && !current?.sitekey) {
1952
- return current;
1953
- }
1954
- const existing = widgets.find(
1955
- (entry) => current.sitekey && entry?.sitekey === current.sitekey || current.name && entry?.name === current.name
1956
- );
1957
- if (!existing?.sitekey) {
1958
- return current;
1959
- }
1960
- return {
1961
- ...current,
1962
- sitekey: existing.sitekey,
1963
- secret: existing.secret ?? current.secret ?? null,
1964
- domains: Array.isArray(existing.domains) ? existing.domains : current.domains ?? [],
1965
- mode: existing.mode ?? current.mode ?? "managed"
1966
- };
1967
- }
1968
- function resolveExistingD1ByName(d1Databases, expectedName, current) {
1969
- if (current?.databaseId && !isPlaceholderResourceId(current.databaseId)) {
1970
- return current;
1971
- }
1972
- const existing = d1Databases.find((entry) => entry?.name === expectedName);
1973
- if (!existing?.uuid) {
1974
- return current;
1975
- }
1976
- return {
1977
- ...current,
1978
- databaseId: existing.uuid,
1979
- previewDatabaseId: existing.previewDatabaseUuid ?? existing.uuid
1980
- };
1981
- }
1982
- function looksLikeMissingResource(output) {
1983
- return /not found|does not exist|could(?: not|n't) find|couldnt find|already deleted|deleted widget|access a deleted/i.test(output);
1984
- }
1985
- function deleteKvNamespace(tenantRoot, namespaceId, { env, planOnly, preview = false }) {
1986
- if (!namespaceId || isPlaceholderResourceId(namespaceId)) {
1987
- return { status: "missing", id: namespaceId };
1988
- }
1989
- if (planOnly) {
1990
- return { status: "planned", id: namespaceId, preview };
1991
- }
1992
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
1993
- const path = accountId ? `/accounts/${encodeURIComponent(accountId)}/storage/kv/namespaces/${encodeURIComponent(namespaceId)}` : null;
1994
- const deleted = deleteCloudflareApiResource(path, { env, planOnly: false, name: namespaceId, type: "kv-namespace" });
1995
- return { status: deleted.status, id: namespaceId, preview };
1996
- }
1997
- function deleteTurnstileWidget(sitekey, { env, planOnly, name = null }) {
1998
- if (!sitekey || isPlaceholderResourceId(sitekey)) {
1999
- return { status: "missing", sitekey, name };
2000
- }
2001
- if (planOnly) {
2002
- return { status: "planned", sitekey, name };
2003
- }
2004
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2005
- const path = accountId ? `/accounts/${encodeURIComponent(accountId)}/challenges/widgets/${encodeURIComponent(sitekey)}` : null;
2006
- let deleted;
2007
- try {
2008
- deleted = deleteCloudflareApiResource(path, { env, planOnly: false, name: name ?? sitekey, type: "turnstile-widget" });
2009
- } catch (error) {
2010
- const detail = error instanceof Error ? error.message : String(error);
2011
- throw new Error(`Cloudflare Turnstile widget deletion failed. Ensure the API token has Turnstile Sites Write permission: ${detail}`);
2012
- }
2013
- return { status: deleted.status, sitekey, name };
2014
- }
2015
- function deleteD1Database(tenantRoot, databaseName, { env, planOnly }) {
2016
- if (!databaseName) {
2017
- return { status: "missing", name: databaseName };
2018
- }
2019
- if (planOnly) {
2020
- return { status: "planned", name: databaseName };
2021
- }
2022
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2023
- const database = accountId ? listD1Databases(tenantRoot, env).find((entry) => entry?.name === databaseName) : null;
2024
- const databaseId = database?.uuid ?? database?.id ?? null;
2025
- const path = accountId && databaseId ? `/accounts/${encodeURIComponent(accountId)}/d1/database/${encodeURIComponent(databaseId)}` : null;
2026
- const deleted = deleteCloudflareApiResource(path, { env, planOnly: false, name: databaseName, type: "d1-database" });
2027
- return { status: deleted.status, name: databaseName, id: databaseId };
2028
- }
2029
- function deleteWorker(tenantRoot, workerName, { env, planOnly, force = false }) {
2030
- if (!workerName) {
2031
- return { status: "missing", name: workerName };
2032
- }
2033
- if (planOnly) {
2034
- return { status: "planned", name: workerName };
2035
- }
2036
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2037
- const path = accountId ? `/accounts/${encodeURIComponent(accountId)}/workers/services/${encodeURIComponent(workerName)}` : null;
2038
- const deleted = deleteCloudflareApiResource(path, { env, planOnly: false, name: workerName, type: "worker" });
2039
- return { status: deleted.status, name: workerName };
2040
- }
2041
- function resourceOperation(provider, type, name, status, extra = {}) {
2042
- return {
2043
- provider,
2044
- type,
2045
- name: name ?? null,
2046
- status,
2047
- ...extra
2048
- };
2049
- }
2050
- function deleteCloudflareApiResource(path, { env, planOnly, name, type }) {
2051
- if (!path) {
2052
- return resourceOperation("cloudflare", type, name, "missing");
2053
- }
2054
- if (planOnly) {
2055
- return resourceOperation("cloudflare", type, name, "planned", { path });
2056
- }
2057
- const result = cloudflareApiRequest(path, { method: "DELETE", env, allowFailure: true });
2058
- if (result?.success === false && !looksLikeMissingResource(formatCloudflareErrors(result))) {
2059
- throw new Error(formatCloudflareErrors(result) || `Failed to delete Cloudflare ${type} ${name}.`);
2060
- }
2061
- return resourceOperation("cloudflare", type, name, result?.success === false ? "missing" : "deleted", { path });
2062
- }
2063
- function formatCloudflareErrors(payload) {
2064
- return Array.isArray(payload?.errors) ? payload.errors.map((entry) => entry?.message ?? JSON.stringify(entry)).filter(Boolean).join("; ") : "";
2065
- }
2066
- function deleteQueueByName(tenantRoot, queue, { env, planOnly }) {
2067
- const name = queueName(queue) ?? queue?.name ?? null;
2068
- let id = queueId(queue);
2069
- if (!name) {
2070
- return resourceOperation("cloudflare", "queue", name, "missing");
2071
- }
2072
- if (planOnly) {
2073
- return resourceOperation("cloudflare", "queue", name, "planned", { id });
2074
- }
2075
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2076
- if (!id && accountId) {
2077
- const live = listQueues(tenantRoot, env).find((entry) => queueName(entry) === name);
2078
- id = queueId(live);
2079
- }
2080
- const path = id ? `/accounts/${encodeURIComponent(accountId)}/queues/${encodeURIComponent(id)}` : null;
2081
- if (path) {
2082
- const deleted = deleteCloudflareApiResource(path, { env, planOnly: false, name, type: "queue" });
2083
- if (deleted.status === "deleted" || deleted.status === "missing") {
2084
- return { ...deleted, id };
2085
- }
2086
- }
2087
- if (accountId) {
2088
- return resourceOperation("cloudflare", "queue", name, "missing", { id });
2089
- }
2090
- throw new Error(`Failed to delete queue ${name}: CLOUDFLARE_ACCOUNT_ID is not configured.`);
2091
- }
2092
- function deleteR2Bucket(tenantRoot, bucketName, { env, planOnly, deleteData }) {
2093
- if (!bucketName) {
2094
- return resourceOperation("cloudflare", "r2-bucket", bucketName, "missing");
2095
- }
2096
- if (!deleteData) {
2097
- return resourceOperation("cloudflare", "r2-bucket", bucketName, "skipped", { reason: "data_preserved" });
2098
- }
2099
- if (planOnly) {
2100
- return resourceOperation("cloudflare", "r2-bucket", bucketName, "planned");
2101
- }
2102
- const drained = drainR2Bucket(bucketName, { env });
2103
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2104
- const path = accountId ? `/accounts/${encodeURIComponent(accountId)}/r2/buckets/${encodeURIComponent(bucketName)}` : null;
2105
- const deleted = deleteCloudflareApiResource(path, { env, planOnly: false, name: bucketName, type: "r2-bucket" });
2106
- return resourceOperation("cloudflare", "r2-bucket", bucketName, deleted.status, drained);
2107
- }
2108
- function r2ObjectKey(entry) {
2109
- return typeof entry?.key === "string" ? entry.key : typeof entry?.name === "string" ? entry.name : "";
2110
- }
2111
- function listR2Objects(bucketName, { env }) {
2112
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2113
- if (!accountId || !bucketName) {
2114
- return [];
2115
- }
2116
- const objects = [];
2117
- let cursor = "";
2118
- for (let page = 0; page < 20; page += 1) {
2119
- const payload = cloudflareApiRequest(
2120
- `/accounts/${encodeURIComponent(accountId)}/r2/buckets/${encodeURIComponent(bucketName)}/objects?per_page=200${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}`,
2121
- { env, allowFailure: true }
2122
- );
2123
- if (payload?.success === false) {
2124
- break;
2125
- }
2126
- const pageObjects = Array.isArray(payload?.result) ? payload.result : Array.isArray(payload?.result?.objects) ? payload.result.objects : [];
2127
- objects.push(...pageObjects);
2128
- const nextCursor = typeof payload?.result_info?.cursor === "string" ? payload.result_info.cursor : typeof payload?.result?.cursor === "string" ? payload.result.cursor : "";
2129
- if (!nextCursor || nextCursor === cursor || pageObjects.length === 0) {
2130
- break;
2131
- }
2132
- cursor = nextCursor;
2133
- if (objects.length >= 200) {
2134
- break;
2135
- }
2136
- }
2137
- return objects;
2138
- }
2139
- function drainR2Bucket(bucketName, { env }) {
2140
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2141
- if (!accountId || !bucketName) {
2142
- return { objectsDeleted: 0, objectsMissing: 0, objectsDeferred: 0 };
2143
- }
2144
- let objectsDeleted = 0;
2145
- let objectsMissing = 0;
2146
- let objectsDeferred = 0;
2147
- for (let batch = 0; batch < 100; batch += 1) {
2148
- const objects = listR2Objects(bucketName, { env });
2149
- if (objects.length === 0) {
2150
- break;
2151
- }
2152
- const keys = objects.map((object) => r2ObjectKey(object)).filter(Boolean);
2153
- const deleted = deleteR2ObjectsBatch(bucketName, keys, { env });
2154
- objectsDeleted += deleted.objectsDeleted;
2155
- objectsMissing += deleted.objectsMissing;
2156
- objectsDeferred += deleted.objectsDeferred;
2157
- const batchDeleted = deleted.objectsDeleted + deleted.objectsMissing;
2158
- if (batchDeleted === 0) {
2159
- if (deleted.objectsDeferred > 0) {
2160
- sleepSync(3e3);
2161
- continue;
2162
- }
2163
- break;
2164
- }
2165
- if (deleted.objectsDeferred > 0) {
2166
- sleepSync(1500);
2167
- }
2168
- }
2169
- return { objectsDeleted, objectsMissing, objectsDeferred };
2170
- }
2171
- function deleteR2ObjectsBatch(bucketName, keys, { env }) {
2172
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2173
- const token = env?.CLOUDFLARE_API_TOKEN ?? process.env.TREESEED_CLOUDFLARE_API_TOKEN ?? "";
2174
- const uniqueKeys = [...new Set((keys ?? []).filter(Boolean))];
2175
- if (!accountId || !bucketName || uniqueKeys.length === 0) {
2176
- return { objectsDeleted: 0, objectsMissing: 0, objectsDeferred: 0 };
2177
- }
2178
- const script = `
2179
- const input = JSON.parse(await new Promise((resolve) => {
2180
- let body = '';
2181
- process.stdin.setEncoding('utf8');
2182
- process.stdin.on('data', (chunk) => { body += chunk; });
2183
- process.stdin.on('end', () => resolve(body || '{}'));
2184
- }));
2185
- let index = 0;
2186
- let deleted = 0;
2187
- let missing = 0;
2188
- let deferred = 0;
2189
- const failed = [];
2190
- async function removeKey(key) {
2191
- function encodeObjectKey(value) {
2192
- return String(value).split('/').map((part) => encodeURIComponent(part)).join('/');
2193
- }
2194
- const url = 'https://api.cloudflare.com/client/v4/accounts/'
2195
- + encodeURIComponent(input.accountId)
2196
- + '/r2/buckets/'
2197
- + encodeURIComponent(input.bucketName)
2198
- + '/objects/'
2199
- + encodeObjectKey(key);
2200
- for (let attempt = 0; attempt < 6; attempt += 1) {
2201
- const controller = new AbortController();
2202
- const timeout = setTimeout(() => controller.abort(), input.timeoutMs || 15000);
2203
- try {
2204
- const response = await fetch(url, {
2205
- method: 'DELETE',
2206
- headers: { authorization: 'Bearer ' + input.token },
2207
- signal: controller.signal,
2208
- });
2209
- const text = await response.text();
2210
- let payload = {};
2211
- try { payload = text ? JSON.parse(text) : {}; } catch { payload = { errors: [{ message: text }] }; }
2212
- if (response.ok && payload.success !== false) {
2213
- deleted += 1;
2214
- return;
2215
- }
2216
- const message = Array.isArray(payload.errors) ? payload.errors.map((entry) => entry?.message || JSON.stringify(entry)).join('; ') : text;
2217
- if (/not found|does not exist|deleted|missing/i.test(message || '')) {
2218
- missing += 1;
2219
- return;
2220
- }
2221
- if (response.status === 429 || /rate limit|too many requests/i.test(message || '')) {
2222
- await new Promise((resolve) => setTimeout(resolve, 750 * (attempt + 1)));
2223
- continue;
2224
- }
2225
- failed.push({ key, message: message || \`delete failed with status \${response.status}\` });
2226
- return;
2227
- } catch (error) {
2228
- if (attempt < 5 && /aborted|timed out|fetch failed|econnreset/i.test(error instanceof Error ? error.message : String(error))) {
2229
- await new Promise((resolve) => setTimeout(resolve, 750 * (attempt + 1)));
2230
- continue;
2231
- }
2232
- failed.push({ key, message: error instanceof Error ? error.message : String(error) });
2233
- return;
2234
- } finally {
2235
- clearTimeout(timeout);
2236
- }
2237
- }
2238
- deferred += 1;
2239
- }
2240
- async function worker() {
2241
- for (;;) {
2242
- const current = index;
2243
- index += 1;
2244
- if (current >= input.keys.length) return;
2245
- await removeKey(input.keys[current]);
2246
- }
2247
- }
2248
- await Promise.all(Array.from({ length: Math.min(input.concurrency || 4, input.keys.length) }, () => worker()));
2249
- process.stdout.write(JSON.stringify({ deleted, missing, deferred, failed }));
2250
- `.trim();
2251
- const result = spawnSync(process.execPath, ["--input-type=module", "-e", script], {
2252
- stdio: ["pipe", "pipe", "pipe"],
2253
- encoding: "utf8",
2254
- env: { ...process.env, ...env ?? {} },
2255
- input: JSON.stringify({
2256
- accountId,
2257
- bucketName,
2258
- keys: uniqueKeys,
2259
- token,
2260
- concurrency: 4,
2261
- timeoutMs: 12e3
2262
- }),
2263
- timeout: 12e4
2264
- });
2265
- if (result.status !== 0 || result.error) {
2266
- throw new Error(result.stderr?.trim() || result.error?.message || `Failed to delete R2 object batch for ${bucketName}.`);
2267
- }
2268
- let parsed;
2269
- try {
2270
- parsed = JSON.parse(result.stdout || "{}");
2271
- } catch {
2272
- throw new Error(`R2 object batch delete returned invalid JSON for ${bucketName}.`);
2273
- }
2274
- if (Array.isArray(parsed.failed) && parsed.failed.length > 0) {
2275
- const first = parsed.failed[0];
2276
- throw new Error(`Failed to delete ${parsed.failed.length} R2 objects from ${bucketName}: ${first?.message ?? first?.key ?? "unknown error"}`);
2277
- }
2278
- return {
2279
- objectsDeleted: Number(parsed.deleted) || 0,
2280
- objectsMissing: Number(parsed.missing) || 0,
2281
- objectsDeferred: Number(parsed.deferred) || 0
2282
- };
2283
- }
2284
- function deleteD1DatabaseForDestroy(tenantRoot, databaseName, { env, planOnly, deleteData }) {
2285
- if (!deleteData) {
2286
- return resourceOperation("cloudflare", "d1-database", databaseName, "skipped", { reason: "data_preserved" });
2287
- }
2288
- const result = deleteD1Database(tenantRoot, databaseName, { env, planOnly });
2289
- return resourceOperation("cloudflare", "d1-database", databaseName, result.status, result);
2290
- }
2291
- function pagesDomainName(domain) {
2292
- return typeof domain?.name === "string" ? domain.name : typeof domain?.domain === "string" ? domain.domain : typeof domain?.hostname === "string" ? domain.hostname : "";
2293
- }
2294
- function listPagesCustomDomains(projectName, { env }) {
2295
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2296
- if (!projectName || !accountId) {
2297
- return [];
2298
- }
2299
- const domains = [];
2300
- let page = 1;
2301
- let totalPages = 1;
2302
- while (page <= totalPages && page <= 50) {
2303
- const payload = cloudflareApiRequest(
2304
- `/accounts/${encodeURIComponent(accountId)}/pages/projects/${encodeURIComponent(projectName)}/domains?per_page=100&page=${page}`,
2305
- { env, allowFailure: true }
2306
- );
2307
- if (payload?.success === false) {
2308
- break;
2309
- }
2310
- if (Array.isArray(payload?.result)) {
2311
- domains.push(...payload.result);
2312
- }
2313
- const reportedTotal = Number(payload?.result_info?.total_pages);
2314
- totalPages = Number.isFinite(reportedTotal) && reportedTotal > 0 ? reportedTotal : page;
2315
- page += 1;
2316
- }
2317
- return domains;
2318
- }
2319
- function listPagesCustomDomainsWithWrangler(tenantRoot, projectName, { env }) {
2320
- const result = runWrangler(["pages", "project", "list", "--json"], {
2321
- cwd: tenantRoot,
2322
- allowFailure: true,
2323
- capture: true,
2324
- env
2325
- });
2326
- if (result.status !== 0) {
2327
- return [];
2328
- }
2329
- try {
2330
- const projects = JSON.parse(result.stdout || "[]");
2331
- const project = (Array.isArray(projects) ? projects : []).find((entry) => entry?.name === projectName || entry?.projectName === projectName || entry?.["Project Name"] === projectName);
2332
- const domains = typeof project?.["Project Domains"] === "string" ? project["Project Domains"] : typeof project?.domains === "string" ? project.domains : "";
2333
- return domains.split(",").map((entry) => entry.trim()).filter((entry) => entry && !entry.endsWith(".pages.dev"));
2334
- } catch {
2335
- return [];
2336
- }
2337
- }
2338
- function deletePagesCustomDomains(tenantRoot, projectName, knownNames, { env, planOnly, knownOnly = false }) {
2339
- if (!projectName) {
2340
- return [resourceOperation("cloudflare", "pages-custom-domain", projectName, "missing")];
2341
- }
2342
- const desiredNames = [...new Set((knownNames ?? []).filter(Boolean))];
2343
- if (planOnly) {
2344
- return desiredNames.length > 0 ? desiredNames.map((name) => resourceOperation("cloudflare", "pages-custom-domain", name, "planned", { projectName, knownOnly })) : [resourceOperation("cloudflare", "pages-custom-domain", projectName, knownOnly ? "skipped" : "planned", { reason: knownOnly ? "no_target_scoped_domain" : "project_delete_prerequisite" })];
2345
- }
2346
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2347
- if (!accountId) {
2348
- return desiredNames.length > 0 ? desiredNames.map((name) => resourceOperation("cloudflare", "pages-custom-domain", name, "blocked", { projectName, reason: "missing_cloudflare_account_id" })) : [resourceOperation("cloudflare", "pages-custom-domain", projectName, "blocked", { reason: "missing_cloudflare_account_id" })];
2349
- }
2350
- const listedNames = knownOnly ? [] : listPagesCustomDomains(projectName, { env }).map(pagesDomainName).filter(Boolean);
2351
- const wranglerNames = knownOnly ? [] : listPagesCustomDomainsWithWrangler(tenantRoot, projectName, { env });
2352
- const domainNames = [.../* @__PURE__ */ new Set([...desiredNames, ...listedNames, ...wranglerNames])];
2353
- if (domainNames.length === 0) {
2354
- return [resourceOperation("cloudflare", "pages-custom-domain", projectName, "missing", { projectName })];
2355
- }
2356
- return domainNames.map((name) => deleteCloudflareApiResource(
2357
- `/accounts/${encodeURIComponent(accountId)}/pages/projects/${encodeURIComponent(projectName)}/domains/${encodeURIComponent(name)}`,
2358
- { env, planOnly: false, name, type: "pages-custom-domain" }
2359
- ));
2360
- }
2361
- function normalizePagesDeploymentId(deployment) {
2362
- return typeof deployment?.id === "string" ? deployment.id : typeof deployment?.Id === "string" ? deployment.Id : "";
2363
- }
2364
- function normalizePagesDeployments(value) {
2365
- return (Array.isArray(value) ? value : Array.isArray(value?.result) ? value.result : []).filter((entry) => normalizePagesDeploymentId(entry));
2366
- }
2367
- function pagesDeploymentEnvironments(environment = "all") {
2368
- return environment === "preview" ? ["preview"] : environment === "production" ? ["production"] : ["preview", "production"];
2369
- }
2370
- function listPagesDeploymentsWithApi(projectName, { env, environment = "all" }) {
2371
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2372
- if (!projectName || !accountId) {
2373
- return [];
2374
- }
2375
- const deployments = [];
2376
- for (const pagesEnvironment of pagesDeploymentEnvironments(environment)) {
2377
- let page = 1;
2378
- let totalPages = 1;
2379
- while (page <= totalPages && page <= 50) {
2380
- const payload = cloudflareApiRequest(
2381
- `/accounts/${encodeURIComponent(accountId)}/pages/projects/${encodeURIComponent(projectName)}/deployments?per_page=100&page=${page}&env=${pagesEnvironment}`,
2382
- { env, allowFailure: true }
2383
- );
2384
- if (payload?.success === false) {
2385
- break;
2386
- }
2387
- deployments.push(...normalizePagesDeployments(payload));
2388
- const reportedTotal = Number(payload?.result_info?.total_pages);
2389
- totalPages = Number.isFinite(reportedTotal) && reportedTotal > 0 ? reportedTotal : page;
2390
- page += 1;
2391
- }
2392
- }
2393
- return deployments;
2394
- }
2395
- function listPagesDeployments(tenantRoot, projectName, { env, environment = "all" }) {
2396
- const deployments = [];
2397
- for (const pagesEnvironment of pagesDeploymentEnvironments(environment)) {
2398
- const result = runWrangler(["pages", "deployment", "list", "--project-name", projectName, "--environment", pagesEnvironment, "--json"], {
2399
- cwd: tenantRoot,
2400
- allowFailure: true,
2401
- capture: true,
2402
- env
2403
- });
2404
- if (result.status !== 0) {
2405
- continue;
2406
- }
2407
- try {
2408
- deployments.push(...normalizePagesDeployments(JSON.parse(result.stdout || "[]")));
2409
- } catch {
2410
- }
2411
- }
2412
- if (deployments.length > 0) {
2413
- const byId = new Map(deployments.map((deployment) => [normalizePagesDeploymentId(deployment), deployment]));
2414
- return [...byId.values()];
2415
- }
2416
- return listPagesDeploymentsWithApi(projectName, { env, environment });
2417
- }
2418
- function deletePagesDeployments(tenantRoot, projectName, { env, planOnly, environment = "all" }) {
2419
- if (!projectName) {
2420
- return resourceOperation("cloudflare", "pages-deployments", projectName, "missing");
2421
- }
2422
- if (planOnly) {
2423
- return resourceOperation("cloudflare", "pages-deployments", projectName, "planned", { reason: "project_delete_prerequisite", environment });
2424
- }
2425
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2426
- if (!accountId) {
2427
- return resourceOperation("cloudflare", "pages-deployments", projectName, "blocked", { reason: "missing_cloudflare_account_id" });
2428
- }
2429
- let deleted = 0;
2430
- let skipped = 0;
2431
- let total = 0;
2432
- for (let batch = 0; batch < 100; batch += 1) {
2433
- const deployments = listPagesDeployments(tenantRoot, projectName, { env, environment });
2434
- if (deployments.length === 0) {
2435
- return resourceOperation("cloudflare", "pages-deployments", projectName, deleted > 0 ? "deleted" : "missing", {
2436
- deleted,
2437
- skipped,
2438
- total
2439
- });
2440
- }
2441
- total += deployments.length;
2442
- let batchDeleted = 0;
2443
- let batchSkipped = 0;
2444
- for (const deployment of deployments) {
2445
- const deploymentId = normalizePagesDeploymentId(deployment);
2446
- if (!deploymentId) {
2447
- continue;
2448
- }
2449
- const result = cloudflareApiRequest(
2450
- `/accounts/${encodeURIComponent(accountId)}/pages/projects/${encodeURIComponent(projectName)}/deployments/${encodeURIComponent(deploymentId)}`,
2451
- { method: "DELETE", env, allowFailure: true }
2452
- );
2453
- if (result?.success === false) {
2454
- const message = formatCloudflareErrors(result);
2455
- if (/active production deployment|production deployment|deployment is aliased|aliased deployment/iu.test(message)) {
2456
- skipped += 1;
2457
- batchSkipped += 1;
2458
- continue;
2459
- }
2460
- if (looksLikeMissingResource(message)) {
2461
- continue;
2462
- }
2463
- throw new Error(message || `Failed to delete Pages deployment ${deploymentId}.`);
2464
- }
2465
- deleted += 1;
2466
- batchDeleted += 1;
2467
- }
2468
- if (batchDeleted === 0 && batchSkipped >= deployments.length) {
2469
- break;
2470
- }
2471
- }
2472
- return resourceOperation("cloudflare", "pages-deployments", projectName, deleted > 0 ? "deleted" : "skipped", {
2473
- deleted,
2474
- skipped,
2475
- total
2476
- });
2477
- }
2478
- function deletePagesProject(projectName, { env, planOnly }) {
2479
- const accountId = env?.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "";
2480
- if (!projectName || !accountId) {
2481
- return resourceOperation("cloudflare", "pages-project", projectName, "missing");
2482
- }
2483
- return deleteCloudflareApiResource(
2484
- `/accounts/${encodeURIComponent(accountId)}/pages/projects/${encodeURIComponent(projectName)}`,
2485
- { env, planOnly, name: projectName, type: "pages-project" }
2486
- );
2487
- }
2488
- function listDnsRecordsForName(zoneId, name, env) {
2489
- if (!zoneId || !name) {
2490
- return [];
2491
- }
2492
- const result = cloudflareApiRequest(`/zones/${encodeURIComponent(zoneId)}/dns_records?name=${encodeURIComponent(name)}&per_page=100`, { env, allowFailure: true });
2493
- return Array.isArray(result?.result) ? result.result : [];
2494
- }
2495
- function deleteDnsRecordsForName(deployConfig, name, { env, planOnly }) {
2496
- if (!name) {
2497
- return [resourceOperation("cloudflare", "dns-record", name, "missing")];
2498
- }
2499
- if (planOnly) {
2500
- return [resourceOperation("cloudflare", "dns-record", name, "planned")];
2501
- }
2502
- const zoneId = resolveCloudflareZoneIdForHost(deployConfig, name, env);
2503
- if (!zoneId) {
2504
- return [resourceOperation("cloudflare", "dns-record", name, "blocked", { reason: "zone_unresolved" })];
2505
- }
2506
- const records = listDnsRecordsForName(zoneId, name, env);
2507
- if (records.length === 0) {
2508
- return [resourceOperation("cloudflare", "dns-record", name, "missing", { zoneId })];
2509
- }
2510
- return records.map((record) => {
2511
- const recordName = record?.name ?? name;
2512
- return deleteCloudflareApiResource(
2513
- `/zones/${encodeURIComponent(zoneId)}/dns_records/${encodeURIComponent(record.id)}`,
2514
- { env, planOnly: false, name: recordName, type: "dns-record" }
2515
- );
2516
- });
2517
- }
2518
- function deleteTreeseedCacheRules(deployConfig, state, { env, planOnly }) {
2519
- const targets = [
2520
- { role: "web", zoneId: state.webCache?.webZoneId, host: state.webCache?.webHost },
2521
- { role: "content", zoneId: state.webCache?.contentZoneId, host: state.webCache?.contentHost }
2522
- ].filter((entry) => entry.host || entry.zoneId);
2523
- if (targets.length === 0) {
2524
- return [resourceOperation("cloudflare", "cache-rules", null, "missing")];
2525
- }
2526
- return targets.map((target) => {
2527
- const zoneId = target.zoneId ?? resolveCloudflareZoneIdForHost(deployConfig, target.host, env);
2528
- if (!zoneId) {
2529
- return resourceOperation("cloudflare", "cache-rules", target.host, "blocked", { reason: "zone_unresolved" });
2530
- }
2531
- if (planOnly) {
2532
- return resourceOperation("cloudflare", "cache-rules", target.host, "planned", { zoneId });
2533
- }
2534
- const rulesets = listCloudflareZoneRulesets(zoneId, env);
2535
- const ruleset = rulesets.find((entry) => entry?.phase === "http_request_cache_settings") ?? null;
2536
- const rules = Array.isArray(ruleset?.rules) ? ruleset.rules : [];
2537
- const kept = rules.filter((rule) => typeof rule?.description !== "string" || !rule.description.startsWith("treeseed-managed:"));
2538
- if (!ruleset || kept.length === rules.length) {
2539
- return resourceOperation("cloudflare", "cache-rules", target.host, "missing", { zoneId });
2540
- }
2541
- cloudflareApiRequest(`/zones/${encodeURIComponent(zoneId)}/rulesets/${encodeURIComponent(ruleset.id)}`, {
2542
- method: "PUT",
2543
- body: { rules: kept },
2544
- env
2545
- });
2546
- return resourceOperation("cloudflare", "cache-rules", target.host, "deleted", { zoneId, rulesetId: ruleset.id, removed: rules.length - kept.length });
2547
- });
2548
- }
2549
- function configuredRailwayDestroyTargets(tenantRoot, deployConfig, scope) {
2550
- const normalizedScope = scope === "prod" ? "prod" : scope === "staging" ? "staging" : "local";
2551
- if (normalizedScope === "local" || deployConfig.runtime?.mode !== "treeseed_managed") {
2552
- return [];
2553
- }
2554
- let identity;
2555
- try {
2556
- identity = resolveTreeseedResourceIdentity(deployConfig, createPersistentDeployTarget(normalizedScope));
2557
- } catch {
2558
- identity = { deploymentKey: deployConfig.slug ?? deployConfig.name ?? "treeseed" };
2559
- }
2560
- const services = [];
2561
- for (const serviceKey of ["api", "operationsRunner"]) {
2562
- const service = deployConfig.services?.[serviceKey];
2563
- if (!service || service.enabled === false || (service.provider ?? "railway") !== "railway") {
2564
- continue;
2565
- }
2566
- const baseServiceName = service.environments?.[normalizedScope]?.serviceName ?? service.railway?.serviceName ?? `${identity.deploymentKey}-${serviceKey === "operationsRunner" ? "operations-runner" : serviceKey}`;
2567
- const runnerPool = serviceKey === "operationsRunner" && service.railway?.runnerPool && typeof service.railway.runnerPool === "object" ? service.railway.runnerPool : null;
2568
- const count = serviceKey === "operationsRunner" ? Math.max(1, Number.parseInt(String(runnerPool?.bootstrapCount ?? 1), 10) || 1) : 1;
2569
- for (let index = 1; index <= count; index += 1) {
2570
- const serviceName = serviceKey === "operationsRunner" ? `${String(baseServiceName).replace(/-\d+$/u, "").replace(/-\d{2}$/u, "")}-${String(index).padStart(2, "0")}` : baseServiceName;
2571
- services.push({
2572
- key: serviceKey,
2573
- projectName: service.railway?.projectName ?? identity.deploymentKey,
2574
- serviceName,
2575
- railwayEnvironment: normalizeRailwayEnvironmentName(service.environments?.[normalizedScope]?.railwayEnvironment ?? normalizedScope),
2576
- domain: service.environments?.[normalizedScope]?.domain ?? null,
2577
- volumeMountPath: serviceKey === "operationsRunner" ? service.railway?.volumeMountPath ?? runnerPool?.volumeMountPath ?? "/data" : null
2578
- });
2579
- }
2580
- }
2581
- const treeseedDatabase = deployConfig.services?.treeseedDatabase;
2582
- if (treeseedDatabase?.enabled !== false && treeseedDatabase?.provider === "railway" && treeseedDatabase?.railway?.resourceType === "postgres") {
2583
- const baseName = typeof treeseedDatabase.railway?.serviceName === "string" && treeseedDatabase.railway.serviceName.trim() ? treeseedDatabase.railway.serviceName.trim() : `${deployConfig.slug ?? "treeseed-market"}-postgres`;
2584
- services.push({
2585
- key: "treeseedDatabase",
2586
- projectName: deployConfig.services?.api?.railway?.projectName ?? identity.deploymentKey,
2587
- serviceName: baseName.replace(/-(staging|prod|production)$/u, ""),
2588
- railwayEnvironment: normalizeRailwayEnvironmentName(normalizedScope),
2589
- domain: null,
2590
- volumeMountPath: null,
2591
- dataStore: true
2592
- });
2593
- }
2594
- return services;
2595
- }
2596
- async function destroyRailwayResources(tenantRoot, deployConfig, target, { planOnly = false, deleteData = false, env = process.env } = {}) {
2597
- const scope = target.kind === "persistent" ? target.scope : target.branchName;
2598
- const services = configuredRailwayDestroyTargets(tenantRoot, deployConfig, scope);
2599
- if (services.length === 0) {
2600
- return { operations: [resourceOperation("railway", "environment", scope, "skipped", { reason: "not_applicable" })] };
2601
- }
2602
- const operations = [];
2603
- if (!resolveRailwayApiToken(env)) {
2604
- return {
2605
- operations: services.map((service) => resourceOperation("railway", "service", service.serviceName, "blocked", { reason: "missing_railway_api_token" }))
2606
- };
2607
- }
2608
- const workspace = await resolveRailwayWorkspaceContext({ env, workspace: resolveRailwayWorkspace(env) });
2609
- const projects = await listRailwayProjects({ env, workspaceId: workspace.id });
2610
- const projectNames = [...new Set(services.map((service) => service.projectName).filter(Boolean))];
2611
- for (const projectName of projectNames) {
2612
- const project = projects.find((entry) => !entry.deletedAt && (entry.name === projectName || entry.id === projectName)) ?? null;
2613
- if (!project) {
2614
- operations.push(resourceOperation("railway", "project", projectName, "missing"));
2615
- continue;
2616
- }
2617
- const serviceTargets = services.filter((service) => service.projectName === projectName);
2618
- const environmentName = normalizeRailwayEnvironmentName(scope);
2619
- const environment = project.environments.find((entry) => entry.name === environmentName || entry.id === environmentName) ?? null;
2620
- if (!environment) {
2621
- operations.push(resourceOperation("railway", "environment", environmentName, "missing", { projectId: project.id }));
2622
- }
2623
- for (const service of serviceTargets) {
2624
- const railwayService = project.services.find((entry) => entry.name === service.serviceName || entry.id === service.serviceName) ?? null;
2625
- const shouldDeleteData = service.dataStore ? deleteData : true;
2626
- operations.push(resourceOperation("railway", service.dataStore ? "postgres-service" : "service", service.serviceName, railwayService ? planOnly ? "planned" : "planned" : "missing", {
2627
- projectId: project.id,
2628
- serviceId: railwayService?.id ?? null,
2629
- ...service.dataStore && !shouldDeleteData ? { status: "skipped", reason: "data_preserved" } : {}
2630
- }));
2631
- if (!railwayService || !environment) {
2632
- continue;
2633
- }
2634
- if (shouldDeleteData) {
2635
- const variables = await listRailwayVariables({
2636
- projectId: project.id,
2637
- environmentId: environment.id,
2638
- serviceId: railwayService.id,
2639
- env
2640
- });
2641
- for (const variableName of Object.keys(variables).sort()) {
2642
- operations.push(resourceOperation("railway", "variable", `${service.serviceName}:${variableName}`, planOnly ? "planned" : "deleted", {
2643
- projectId: project.id,
2644
- serviceId: railwayService.id,
2645
- environmentId: environment.id,
2646
- reason: scope === "prod" && deleteData ? "project_delete" : "environment_delete"
2647
- }));
2648
- }
2649
- }
2650
- const instance = await getRailwayServiceInstance({ serviceId: railwayService.id, environmentId: environment.id, env });
2651
- if (instance.cronSchedule) {
2652
- operations.push(resourceOperation("railway", "schedule", `${service.serviceName}:${instance.cronSchedule}`, planOnly ? "planned" : "deleted", {
2653
- projectId: project.id,
2654
- serviceId: railwayService.id,
2655
- environmentId: environment.id,
2656
- reason: scope === "prod" && deleteData ? "project_delete" : "environment_delete"
2657
- }));
2658
- }
2659
- if (!service.dataStore && service.domain) {
2660
- const domains = await listRailwayCustomDomains({ projectId: project.id, environmentId: environment.id, serviceId: railwayService.id, env });
2661
- for (const domain of domains.filter((entry) => entry.domain === service.domain)) {
2662
- if (planOnly) {
2663
- operations.push(resourceOperation("railway", "custom-domain", domain.domain, "planned", { id: domain.id }));
2664
- } else {
2665
- const result = await deleteRailwayCustomDomain({ projectId: project.id, environmentId: environment.id, serviceId: railwayService.id, domainId: domain.id, env });
2666
- operations.push(resourceOperation("railway", "custom-domain", domain.domain, result.status, { id: domain.id }));
2667
- }
2668
- }
2669
- }
2670
- }
2671
- if (deleteData) {
2672
- const volumes = await listRailwayVolumes({ projectId: project.id, env });
2673
- for (const volume of volumes) {
2674
- const matchingInstance = volume.instances.find((instance) => instance.environmentId === environment?.id);
2675
- if (!matchingInstance) {
2676
- continue;
2677
- }
2678
- if (planOnly) {
2679
- operations.push(resourceOperation("railway", "volume", volume.name, "planned", { id: volume.id, projectId: project.id }));
2680
- } else {
2681
- const result = await deleteRailwayVolume({ projectId: project.id, environmentId: environment.id, volumeId: volume.id, env });
2682
- operations.push(resourceOperation("railway", "volume", volume.name, result.status, { id: volume.id, projectId: project.id }));
2683
- }
2684
- }
2685
- }
2686
- const shouldDeleteProject = shouldDeleteRailwayProjectAfterEnvironmentDestroy(project, scope, deleteData, environment?.id ?? null);
2687
- if (scope === "prod" && deleteData || shouldDeleteProject) {
2688
- if (planOnly) {
2689
- operations.push(resourceOperation("railway", "project", project.name, "planned", {
2690
- id: project.id,
2691
- reason: scope === "prod" ? "prod_delete_data_cleanup" : "no_managed_persistent_environments"
2692
- }));
2693
- } else {
2694
- throw new Error("Railway project deletion is reconciler-owned. Use trsd reconcile destroy or live acceptance cleanup for project-scoped deletion.");
2695
- }
2696
- } else if (environment) {
2697
- if (planOnly) {
2698
- operations.push(resourceOperation("railway", "environment", environment.name, "planned", { id: environment.id, projectId: project.id }));
2699
- } else {
2700
- const result = await deleteRailwayEnvironment({ projectId: project.id, environmentId: environment.id, env });
2701
- operations.push(resourceOperation("railway", "environment", environment.name, result.status, { id: environment.id, projectId: project.id }));
2702
- }
2703
- }
2704
- }
2705
- return { operations };
2706
- }
2707
- function shouldDeleteRailwayProjectAfterEnvironmentDestroy(project, scope, deleteData, deletedEnvironmentId = null) {
2708
- if (!deleteData || scope === "prod") {
2709
- return false;
2710
- }
2711
- const managedPersistentNames = /* @__PURE__ */ new Set(["staging", "production", "prod"]);
2712
- const targetEnvironmentName = normalizeRailwayEnvironmentName(scope);
2713
- const remainingManagedEnvironments = (project?.environments ?? []).filter((environment) => environment?.id !== deletedEnvironmentId).filter((environment) => environment?.name !== targetEnvironmentName).filter((environment) => managedPersistentNames.has(environment?.name));
2714
- return remainingManagedEnvironments.length === 0;
2715
- }
2716
- function killPidFromFile(filePath, { planOnly }) {
2717
- const pid = Number.parseInt(readFileSync(filePath, "utf8").trim(), 10);
2718
- if (!Number.isFinite(pid) || pid <= 0) {
2719
- return resourceOperation("local", "dev-process", filePath, "missing");
2720
- }
2721
- if (planOnly) {
2722
- return resourceOperation("local", "dev-process", String(pid), "planned", { pidFile: filePath });
2723
- }
2724
- try {
2725
- process.kill(-pid, "SIGTERM");
2726
- } catch {
2727
- try {
2728
- process.kill(pid, "SIGTERM");
2729
- } catch {
2730
- }
2731
- }
2732
- try {
2733
- unlinkSync(filePath);
2734
- } catch {
2735
- }
2736
- return resourceOperation("local", "dev-process", String(pid), "deleted", { pidFile: filePath });
2737
- }
2738
- const LOCAL_DOCKER_RESOURCE_PATTERN = /(?:^|[-_.])(?:treeseed|treedx|treedb)(?:[-_.]|$)|(?:treeseed|treedx|treedb)/iu;
2739
- let destroyDockerRunnerForTests = null;
2740
- function setDestroyDockerRunnerForTests(runner) {
2741
- destroyDockerRunnerForTests = runner;
2742
- }
2743
- function runDestroyDocker(args) {
2744
- if (destroyDockerRunnerForTests) {
2745
- return destroyDockerRunnerForTests(args);
2746
- }
2747
- return spawnSync("docker", args, { encoding: "utf8", stdio: "pipe" });
2748
- }
2749
- function dockerAvailable() {
2750
- const result = runDestroyDocker(["info"]);
2751
- return result.status === 0;
2752
- }
2753
- function dockerList(formatArgs) {
2754
- const result = runDestroyDocker(formatArgs);
2755
- if (result.status !== 0) {
2756
- return [];
2757
- }
2758
- return result.stdout.split("\n").map((line) => line.trim()).filter(Boolean);
2759
- }
2760
- function matchingDockerEntries(lines, parser) {
2761
- return lines.map(parser).filter((entry) => entry && LOCAL_DOCKER_RESOURCE_PATTERN.test(`${entry.name} ${entry.image ?? ""}`));
2762
- }
2763
- function removeDockerResource(kind, id, name) {
2764
- const args = kind === "container" ? ["rm", "-f", id] : kind === "volume" ? ["volume", "rm", "-f", id] : ["network", "rm", id];
2765
- const result = runDestroyDocker(args);
2766
- if (result.status === 0) {
2767
- return resourceOperation("local", `docker-${kind}`, name, "deleted", { id });
2768
- }
2769
- return resourceOperation("local", `docker-${kind}`, name, "blocked", {
2770
- id,
2771
- reason: result.stderr?.trim() || result.stdout?.trim() || "docker_remove_failed"
2772
- });
2773
- }
2774
- function dockerLocalRuntimeResourceOperations({ planOnly = false } = {}) {
2775
- if (!dockerAvailable()) {
2776
- return [resourceOperation("local", "docker-cleanup", "docker", "skipped", { reason: "docker_unavailable" })];
2777
- }
2778
- const containers = matchingDockerEntries(
2779
- dockerList(["ps", "-a", "--format", "{{.ID}} {{.Names}} {{.Image}}"]),
2780
- (line) => {
2781
- const [id, name, image] = line.split(" ");
2782
- return id && name ? { id, name, image } : null;
2783
- }
2784
- );
2785
- const volumes = matchingDockerEntries(
2786
- dockerList(["volume", "ls", "--format", "{{.Name}}"]),
2787
- (line) => ({ id: line, name: line })
2788
- );
2789
- const networks = matchingDockerEntries(
2790
- dockerList(["network", "ls", "--format", "{{.ID}} {{.Name}}"]),
2791
- (line) => {
2792
- const [id, name] = line.split(" ");
2793
- return id && name ? { id, name } : null;
2794
- }
2795
- ).filter((entry) => !["bridge", "host", "none"].includes(entry.name));
2796
- if (planOnly) {
2797
- return [
2798
- ...containers.map((entry) => resourceOperation("local", "docker-container", entry.name, "planned", { id: entry.id })),
2799
- ...volumes.map((entry) => resourceOperation("local", "docker-volume", entry.name, "planned", { id: entry.id })),
2800
- ...networks.map((entry) => resourceOperation("local", "docker-network", entry.name, "planned", { id: entry.id })),
2801
- ...containers.length || volumes.length || networks.length ? [] : [resourceOperation("local", "docker-cleanup", "docker", "missing", { reason: "no_matching_resources" })]
2802
- ];
2803
- }
2804
- const operations = [];
2805
- for (const entry of containers) {
2806
- operations.push(removeDockerResource("container", entry.id, entry.name));
2807
- }
2808
- for (const entry of volumes) {
2809
- operations.push(removeDockerResource("volume", entry.id, entry.name));
2810
- }
2811
- for (const entry of networks) {
2812
- operations.push(removeDockerResource("network", entry.id, entry.name));
2813
- }
2814
- if (!operations.length) {
2815
- operations.push(resourceOperation("local", "docker-cleanup", "docker", "missing", { reason: "no_matching_resources" }));
2816
- }
2817
- return operations;
2818
- }
2819
- function destroyLocalRuntimeResources(tenantRoot, { planOnly = false, deleteData = false } = {}) {
2820
- const operations = [];
2821
- const pidDir = resolve(tenantRoot, ".treeseed/dev-pids");
2822
- if (existsSync(pidDir)) {
2823
- for (const entry of readdirSync(pidDir)) {
2824
- if (entry.endsWith(".pid")) {
2825
- operations.push(killPidFromFile(resolve(pidDir, entry), { planOnly }));
2826
- }
2827
- }
2828
- } else {
2829
- operations.push(resourceOperation("local", "dev-pids", pidDir, "missing"));
2830
- }
2831
- if (deleteData) {
2832
- for (const relativePath of [
2833
- ".treeseed/generated/environments/local",
2834
- ".treeseed/generated/dev",
2835
- ".treeseed/operations-runner",
2836
- ".treeseed/local-capacity-provider/data"
2837
- ]) {
2838
- const absolutePath = resolve(tenantRoot, relativePath);
2839
- if (!existsSync(absolutePath)) {
2840
- operations.push(resourceOperation("local", "data-path", relativePath, "missing"));
2841
- continue;
2842
- }
2843
- if (planOnly) {
2844
- operations.push(resourceOperation("local", "data-path", relativePath, "planned"));
2845
- continue;
2846
- }
2847
- rmSync(absolutePath, { recursive: true, force: true });
2848
- operations.push(resourceOperation("local", "data-path", relativePath, "deleted"));
2849
- }
2850
- operations.push(...dockerLocalRuntimeResourceOperations({ planOnly }));
2851
- } else {
2852
- operations.push(resourceOperation("local", "data-path", ".treeseed/generated/environments/local", "skipped", { reason: "data_preserved" }));
2853
- }
2854
- return { operations };
2855
- }
2856
- function treeSeedSweepTokens(deployConfig, state) {
2857
- const configuredHosts = [
2858
- deployConfig.siteUrl,
2859
- deployConfig.surfaces?.web?.publicBaseUrl,
2860
- deployConfig.surfaces?.web?.environments?.staging?.domain,
2861
- deployConfig.surfaces?.web?.environments?.prod?.domain,
2862
- deployConfig.surfaces?.api?.environments?.staging?.domain,
2863
- deployConfig.surfaces?.api?.environments?.prod?.domain,
2864
- deployConfig.services?.api?.environments?.staging?.domain,
2865
- deployConfig.services?.api?.environments?.prod?.domain
2866
- ].map((value) => primaryHost(value) ?? value);
2867
- return [...new Set([
2868
- "treeseed",
2869
- deployConfig.slug,
2870
- deployConfig.name,
2871
- state.identity?.deploymentKey,
2872
- state.identity?.environmentKey,
2873
- state.pages?.projectName,
2874
- state.workerName,
2875
- state.content?.bucketName,
2876
- state.kvNamespaces?.FORM_GUARD_KV?.name,
2877
- state.kvNamespaces?.SESSION?.name,
2878
- state.d1Databases?.SITE_DATA_DB?.databaseName,
2879
- ...configuredHosts
2880
- ].map((value) => String(value ?? "").trim().toLowerCase()).filter((value) => value.length >= 4))];
2881
- }
2882
- function isProtectedAiIntegrationResource(value) {
2883
- return /(?:^|[-_.])(?:ai-gateway|workers-ai|ai-integration|openai|anthropic)(?:[-_.]|$)/iu.test(String(value ?? ""));
2884
- }
2885
- function matchesTreeSeedSweep(value, tokens) {
2886
- const normalized = String(value ?? "").trim().toLowerCase();
2887
- if (!normalized || isProtectedAiIntegrationResource(normalized)) {
2888
- return false;
2889
- }
2890
- return tokens.some((token) => normalized === token || normalized.includes(token));
2891
- }
2892
- function cloudflareNameCandidates(entry) {
2893
- return [
2894
- entry?.name,
2895
- entry?.title,
2896
- entry?.id,
2897
- entry?.queue_name,
2898
- entry?.script,
2899
- entry?.domain,
2900
- entry?.hostname,
2901
- entry?.content,
2902
- entry?.comment,
2903
- ...Array.isArray(entry?.domains) ? entry.domains : [],
2904
- ...Array.isArray(entry?.tags) ? entry.tags : []
2905
- ].filter(Boolean);
2906
- }
2907
- function cloudflareEntryMatchesTreeSeed(entry, tokens) {
2908
- return cloudflareNameCandidates(entry).some((candidate) => matchesTreeSeedSweep(candidate, tokens));
2909
- }
2910
- function deleteDnsRecord(zoneId, record, { env, planOnly }) {
2911
- const name = record?.name ?? record?.content ?? record?.id ?? null;
2912
- if (!zoneId || !record?.id) {
2913
- return resourceOperation("cloudflare", "dns-record", name, "missing", { zoneId });
2914
- }
2915
- if (planOnly) {
2916
- return resourceOperation("cloudflare", "dns-record", name, "planned", {
2917
- zoneId,
2918
- id: record.id,
2919
- content: record.content ?? null,
2920
- recordType: record.type ?? null
2921
- });
2922
- }
2923
- return deleteCloudflareApiResource(
2924
- `/zones/${encodeURIComponent(zoneId)}/dns_records/${encodeURIComponent(record.id)}`,
2925
- { env, planOnly: false, name, type: "dns-record" }
2926
- );
2927
- }
2928
- function sweepTreeSeedCloudflareResources(tenantRoot, deployConfig, state, { env, planOnly, deleteData }) {
2929
- const tokens = treeSeedSweepTokens(deployConfig, state);
2930
- const operations = [];
2931
- const pagesProjects = listPagesProjects(tenantRoot, env).filter((entry) => cloudflareEntryMatchesTreeSeed(entry, tokens));
2932
- for (const project of pagesProjects) {
2933
- const projectName = project?.name ?? project?.id ?? null;
2934
- operations.push(...deletePagesCustomDomains(tenantRoot, projectName, [], { env, planOnly, knownOnly: false }));
2935
- operations.push(deletePagesDeployments(tenantRoot, projectName, { env, planOnly, environment: "all" }));
2936
- operations.push(deletePagesProject(projectName, { env, planOnly }));
2937
- }
2938
- for (const worker of listWorkers(tenantRoot, env).filter((entry) => cloudflareEntryMatchesTreeSeed(entry, tokens))) {
2939
- const name = worker?.id ?? worker?.name ?? worker?.script ?? null;
2940
- const deleted = deleteWorker(tenantRoot, name, { env, planOnly, force: true });
2941
- operations.push(resourceOperation("cloudflare", "worker", name, deleted.status, { ...deleted, sweep: true }));
2942
- }
2943
- for (const namespace of listKvNamespaces(tenantRoot, env).filter((entry) => cloudflareEntryMatchesTreeSeed(entry, tokens))) {
2944
- const deleted = deleteKvNamespace(tenantRoot, namespace.id, { env, planOnly });
2945
- operations.push(resourceOperation("cloudflare", "kv-namespace", namespace.title ?? namespace.id, deleted.status, { ...deleted, sweep: true }));
2946
- }
2947
- for (const queue of listQueues(tenantRoot, env).filter((entry) => cloudflareEntryMatchesTreeSeed(entry, tokens))) {
2948
- operations.push({ ...deleteQueueByName(tenantRoot, queue, { env, planOnly }), sweep: true });
2949
- }
2950
- for (const database of listD1Databases(tenantRoot, env).filter((entry) => cloudflareEntryMatchesTreeSeed(entry, tokens))) {
2951
- const name = database?.name ?? database?.uuid ?? database?.id ?? null;
2952
- const deleted = deleteData ? deleteD1Database(tenantRoot, name, { env, planOnly }) : null;
2953
- operations.push(resourceOperation("cloudflare", "d1-database", name, deleteData ? deleted?.status : "skipped", {
2954
- ...deleteData ? deleted : { reason: "data_preserved" },
2955
- sweep: true
2956
- }));
2957
- }
2958
- for (const bucket of listR2Buckets(tenantRoot, env).filter((entry) => cloudflareEntryMatchesTreeSeed(entry, tokens))) {
2959
- operations.push({ ...deleteR2Bucket(tenantRoot, bucket.name, { env, planOnly, deleteData }), sweep: true });
2960
- }
2961
- for (const widget of listTurnstileWidgets(tenantRoot, env).filter((entry) => cloudflareEntryMatchesTreeSeed(entry, tokens))) {
2962
- const deleted = deleteTurnstileWidget(widget.sitekey, { env, planOnly, name: widget.name });
2963
- operations.push(resourceOperation("cloudflare", "turnstile-widget", widget.name ?? widget.sitekey, deleted.status, { ...deleted, sweep: true }));
2964
- }
2965
- for (const zone of listDnsZones(env)) {
2966
- const zoneId = zone?.id ?? null;
2967
- for (const record of listDnsRecords(zoneId, env)) {
2968
- if (record?.type === "SOA" || record?.type === "NS") {
2969
- continue;
2970
- }
2971
- if (!cloudflareEntryMatchesTreeSeed(record, tokens)) {
2972
- continue;
2973
- }
2974
- operations.push({ ...deleteDnsRecord(zoneId, record, { env, planOnly }), zoneName: zone?.name ?? null, sweep: true });
2975
- }
2976
- }
2977
- return operations.length > 0 ? operations : [resourceOperation("cloudflare", "treeseed-sweep", "cloudflare", "missing", { reason: "no_matching_resources" })];
2978
- }
2979
- function countMatchingCloudflareEntries(entries, tokens) {
2980
- return entries.filter((entry) => cloudflareEntryMatchesTreeSeed(entry, tokens)).length;
2981
- }
2982
- function cloudflareDestroyVerification(tenantRoot, deployConfig, state, env) {
2983
- const tokens = treeSeedSweepTokens(deployConfig, state);
2984
- const zoneIds = /* @__PURE__ */ new Set([
2985
- deployConfig.cloudflare?.zoneId,
2986
- state.webCache?.webZoneId,
2987
- state.webCache?.contentZoneId
2988
- ]);
2989
- for (const zone of listDnsZones(env)) {
2990
- if (zone?.id) {
2991
- zoneIds.add(zone.id);
2992
- }
2993
- }
2994
- const dnsRecords = [];
2995
- for (const zoneId of [...zoneIds].filter(Boolean)) {
2996
- dnsRecords.push(...listDnsRecords(zoneId, env));
2997
- }
2998
- const remaining = {
2999
- pages: countMatchingCloudflareEntries(listPagesProjects(tenantRoot, env), tokens),
3000
- workers: countMatchingCloudflareEntries(listWorkers(tenantRoot, env), tokens),
3001
- kvNamespaces: countMatchingCloudflareEntries(listKvNamespaces(tenantRoot, env), tokens),
3002
- queues: countMatchingCloudflareEntries(listQueues(tenantRoot, env), tokens),
3003
- d1Databases: countMatchingCloudflareEntries(listD1Databases(tenantRoot, env), tokens),
3004
- r2Buckets: countMatchingCloudflareEntries(listR2Buckets(tenantRoot, env), tokens),
3005
- turnstileWidgets: countMatchingCloudflareEntries(listTurnstileWidgets(tenantRoot, env), tokens),
3006
- dnsRecords: countMatchingCloudflareEntries(
3007
- dnsRecords.filter((record) => record?.type !== "SOA" && record?.type !== "NS"),
3008
- tokens
3009
- )
3010
- };
3011
- const totalRemaining = Object.values(remaining).reduce((sum, value) => sum + value, 0);
3012
- return {
3013
- provider: "cloudflare",
3014
- method: "cloudflare-api",
3015
- status: totalRemaining === 0 ? "clean" : "remaining",
3016
- remaining,
3017
- totalRemaining
3018
- };
3019
- }
3020
- function localDockerDestroyVerification() {
3021
- if (!dockerAvailable()) {
3022
- return {
3023
- provider: "local-docker",
3024
- method: "docker-cli",
3025
- status: "skipped",
3026
- reason: "docker_unavailable",
3027
- remaining: {
3028
- containers: 0,
3029
- volumes: 0,
3030
- networks: 0
3031
- },
3032
- totalRemaining: 0
3033
- };
3034
- }
3035
- const containers = matchingDockerEntries(
3036
- dockerList(["ps", "-a", "--format", "{{.ID}} {{.Names}} {{.Image}}"]),
3037
- (line) => {
3038
- const [id, name, image] = line.split(" ");
3039
- return id && name ? { id, name, image } : null;
3040
- }
3041
- ).length;
3042
- const volumes = matchingDockerEntries(
3043
- dockerList(["volume", "ls", "--format", "{{.Name}}"]),
3044
- (line) => ({ id: line, name: line })
3045
- ).length;
3046
- const networks = matchingDockerEntries(
3047
- dockerList(["network", "ls", "--format", "{{.ID}} {{.Name}}"]),
3048
- (line) => {
3049
- const [id, name] = line.split(" ");
3050
- return id && name ? { id, name } : null;
3051
- }
3052
- ).filter((entry) => !["bridge", "host", "none"].includes(entry.name)).length;
3053
- const remaining = { containers, volumes, networks };
3054
- const totalRemaining = containers + volumes + networks;
3055
- return {
3056
- provider: "local-docker",
3057
- method: "docker-cli",
3058
- status: totalRemaining === 0 ? "clean" : "remaining",
3059
- remaining,
3060
- totalRemaining
3061
- };
3062
- }
3063
- async function sweepTreeSeedRailwayResources(deployConfig, state, { env, planOnly }) {
3064
- if (!resolveRailwayApiToken(env)) {
3065
- return [resourceOperation("railway", "treeseed-sweep", "railway", "blocked", { reason: "missing_railway_api_token" })];
3066
- }
3067
- const tokens = treeSeedSweepTokens(deployConfig, state);
3068
- const workspace = await resolveRailwayWorkspaceContext({ env, workspace: resolveRailwayWorkspace(env) });
3069
- const projects = await listRailwayProjects({ env, workspaceId: workspace.id });
3070
- const operations = [];
3071
- for (const project of projects) {
3072
- if (project.deletedAt || !matchesTreeSeedSweep(project.name, tokens)) {
3073
- continue;
3074
- }
3075
- if (planOnly) {
3076
- operations.push(resourceOperation("railway", "project", project.name, "planned", {
3077
- id: project.id,
3078
- workspaceId: workspace.id,
3079
- sweep: true
3080
- }));
3081
- } else {
3082
- throw new Error("Railway project sweep deletion is reconciler-owned. Use trsd reconcile test-live --mode cleanup for isolated cleanup.");
3083
- }
3084
- }
3085
- return operations.length > 0 ? operations : [resourceOperation("railway", "treeseed-sweep", "railway", "missing", { reason: "no_matching_projects" })];
3086
- }
3087
- async function destroyTreeseedEnvironmentResources(tenantRoot, options = {}) {
3088
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
3089
- const deployConfig = loadTenantDeployConfig(tenantRoot);
3090
- const state = loadDeployState(tenantRoot, deployConfig, { target });
3091
- state.workerName = targetWorkerName(deployConfig, target);
3092
- const env = {
3093
- CLOUDFLARE_ACCOUNT_ID: resolveConfiguredCloudflareAccountId(deployConfig)
3094
- };
3095
- const planOnly = options.planOnly ?? false;
3096
- const deleteData = options.deleteData === true;
3097
- const force = options.force ?? false;
3098
- const sweepTreeseed = options.sweepTreeseed === true;
3099
- const destroysSharedWebSurface = target.kind === "persistent" && target.scope === "prod" && deleteData;
3100
- const kvNamespaces = planOnly ? [] : listKvNamespaces(tenantRoot, env);
3101
- const d1Databases = planOnly ? [] : listD1Databases(tenantRoot, env);
3102
- const queues = planOnly ? [] : listQueues(tenantRoot, env);
3103
- const buckets = planOnly ? [] : listR2Buckets(tenantRoot, env);
3104
- const pagesProjects = planOnly ? [] : listPagesProjects(tenantRoot, env);
3105
- const turnstileWidgets = planOnly ? [] : listTurnstileWidgets(tenantRoot, env);
3106
- state.kvNamespaces.FORM_GUARD_KV.id = resolveExistingKvIdByName(
3107
- kvNamespaces,
3108
- state.kvNamespaces.FORM_GUARD_KV.name,
3109
- state.kvNamespaces.FORM_GUARD_KV.id
3110
- );
3111
- if (state.kvNamespaces.SESSION?.name) {
3112
- state.kvNamespaces.SESSION.id = resolveExistingKvIdByName(
3113
- kvNamespaces,
3114
- state.kvNamespaces.SESSION.name,
3115
- state.kvNamespaces.SESSION.id
3116
- );
3117
- }
3118
- state.d1Databases.SITE_DATA_DB = resolveExistingD1ByName(
3119
- d1Databases,
3120
- state.d1Databases.SITE_DATA_DB.databaseName,
3121
- state.d1Databases.SITE_DATA_DB
3122
- );
3123
- state.turnstileWidgets.formGuard = resolveExistingTurnstileWidget(turnstileWidgets, state.turnstileWidgets?.formGuard);
3124
- const pagesProject = pagesProjects.find((entry) => entry?.name === state.pages?.projectName);
3125
- const bucket = buckets.find((entry) => entry?.name === state.content?.bucketName);
3126
- const workerResult = deleteWorker(tenantRoot, state.workerName, { env, planOnly, force });
3127
- const turnstileWidget = deleteTurnstileWidget(state.turnstileWidgets?.formGuard?.sitekey, {
3128
- env,
3129
- planOnly,
3130
- name: state.turnstileWidgets?.formGuard?.name
3131
- });
3132
- const formGuard = deleteKvNamespace(tenantRoot, state.kvNamespaces.FORM_GUARD_KV.id, { env, planOnly });
3133
- const formGuardPreview = state.kvNamespaces.FORM_GUARD_KV.previewId && state.kvNamespaces.FORM_GUARD_KV.previewId !== state.kvNamespaces.FORM_GUARD_KV.id ? deleteKvNamespace(tenantRoot, state.kvNamespaces.FORM_GUARD_KV.previewId, { env, planOnly, preview: true }) : null;
3134
- const session = state.kvNamespaces.SESSION?.id ? deleteKvNamespace(tenantRoot, state.kvNamespaces.SESSION.id, { env, planOnly }) : null;
3135
- const sessionPreview = state.kvNamespaces.SESSION?.previewId && state.kvNamespaces.SESSION.previewId !== state.kvNamespaces.SESSION.id ? deleteKvNamespace(tenantRoot, state.kvNamespaces.SESSION.previewId, { env, planOnly, preview: true }) : null;
3136
- const knownKvIds = new Set([
3137
- state.kvNamespaces.FORM_GUARD_KV.id,
3138
- state.kvNamespaces.FORM_GUARD_KV.previewId,
3139
- state.kvNamespaces.SESSION?.id,
3140
- state.kvNamespaces.SESSION?.previewId
3141
- ].filter(Boolean));
3142
- const legacyKvPrefix = state.identity?.deploymentKey ?? state.pages?.projectName ?? "";
3143
- const legacyKvNamespaces = planOnly ? [] : kvNamespaces.filter((namespace) => {
3144
- const title = typeof namespace?.title === "string" ? namespace.title : "";
3145
- const id = typeof namespace?.id === "string" ? namespace.id : "";
3146
- return title && id && !knownKvIds.has(id) && legacyKvPrefix && title.includes(legacyKvPrefix) && title.includes(target.scope);
3147
- }).map((namespace) => {
3148
- const result = deleteKvNamespace(tenantRoot, namespace.id, { env, planOnly: false });
3149
- return resourceOperation("cloudflare", "kv-namespace", namespace.title, result.status, { ...result, legacy: true });
3150
- });
3151
- const database = deleteD1DatabaseForDestroy(tenantRoot, state.d1Databases.SITE_DATA_DB.databaseName, { env, planOnly, deleteData });
3152
- const r2Bucket = bucket || planOnly ? deleteR2Bucket(tenantRoot, state.content?.bucketName, { env, planOnly, deleteData }) : resourceOperation("cloudflare", "r2-bucket", state.content?.bucketName, "missing");
3153
- const pageDnsNames = [
3154
- state.pages?.customDomain,
3155
- deployConfig.surfaces?.web?.environments?.[target.scope]?.domain,
3156
- target.scope === "prod" ? primaryHost(deployConfig.surfaces?.web?.publicBaseUrl ?? deployConfig.siteUrl) : null
3157
- ].filter(Boolean);
3158
- const apiDnsNames = [
3159
- deployConfig.services?.api?.environments?.[target.scope]?.domain,
3160
- deployConfig.surfaces?.api?.environments?.[target.scope]?.domain
3161
- ].filter(Boolean);
3162
- const dnsRecords = [.../* @__PURE__ */ new Set([...pageDnsNames, ...apiDnsNames])].flatMap((name) => deleteDnsRecordsForName(deployConfig, name, { env, planOnly }));
3163
- const cacheRules = deleteTreeseedCacheRules(deployConfig, state, { env, planOnly });
3164
- const pageCustomDomains = pagesProject || planOnly ? deletePagesCustomDomains(tenantRoot, state.pages?.projectName, pageDnsNames, { env, planOnly, knownOnly: !destroysSharedWebSurface }) : [resourceOperation("cloudflare", "pages-custom-domain", state.pages?.projectName, "missing")];
3165
- const pageDeployments = pagesProject || planOnly ? deletePagesDeployments(tenantRoot, state.pages?.projectName, {
3166
- env,
3167
- planOnly,
3168
- environment: destroysSharedWebSurface ? "all" : "preview"
3169
- }) : resourceOperation("cloudflare", "pages-deployments", state.pages?.projectName, "missing");
3170
- const pages = destroysSharedWebSurface && (pagesProject || planOnly) ? deletePagesProject(state.pages?.projectName, { env, planOnly }) : resourceOperation("cloudflare", "pages-project", state.pages?.projectName, "skipped", {
3171
- reason: target.scope === "prod" ? "delete_data_required" : "shared_web_surface"
3172
- });
3173
- const local = target.kind === "persistent" && target.scope === "local" ? destroyLocalRuntimeResources(tenantRoot, { planOnly, deleteData }) : { operations: [] };
3174
- const railway = await destroyRailwayResources(tenantRoot, deployConfig, target, { planOnly, deleteData, env: process.env });
3175
- const sweep = sweepTreeseed ? {
3176
- cloudflare: sweepTreeSeedCloudflareResources(tenantRoot, deployConfig, state, { env, planOnly, deleteData }),
3177
- railway: await sweepTreeSeedRailwayResources(deployConfig, state, { env: process.env, planOnly })
3178
- } : { cloudflare: [], railway: [] };
3179
- const operations = {
3180
- cloudflare: [
3181
- resourceOperation("cloudflare", "worker", state.workerName, workerResult.status, workerResult),
3182
- resourceOperation("cloudflare", "turnstile-widget", state.turnstileWidgets?.formGuard?.name, turnstileWidget.status, turnstileWidget),
3183
- resourceOperation("cloudflare", "kv-namespace", state.kvNamespaces.FORM_GUARD_KV.name, formGuard.status, formGuard),
3184
- ...formGuardPreview ? [resourceOperation("cloudflare", "kv-namespace-preview", state.kvNamespaces.FORM_GUARD_KV.name, formGuardPreview.status, formGuardPreview)] : [],
3185
- ...session ? [resourceOperation("cloudflare", "kv-namespace", state.kvNamespaces.SESSION.name, session.status, session)] : [],
3186
- ...sessionPreview ? [resourceOperation("cloudflare", "kv-namespace-preview", state.kvNamespaces.SESSION.name, sessionPreview.status, sessionPreview)] : [],
3187
- ...legacyKvNamespaces,
3188
- database,
3189
- r2Bucket,
3190
- ...pageCustomDomains,
3191
- pageDeployments,
3192
- pages,
3193
- ...dnsRecords,
3194
- ...cacheRules,
3195
- ...sweep.cloudflare
3196
- ],
3197
- railway: [
3198
- ...railway.operations,
3199
- ...sweep.railway
3200
- ],
3201
- local: local.operations
3202
- };
3203
- const verification = planOnly ? null : {
3204
- cloudflare: cloudflareDestroyVerification(tenantRoot, deployConfig, state, env),
3205
- ...target.kind === "persistent" && target.scope === "local" ? { localDocker: localDockerDestroyVerification() } : {}
3206
- };
3207
- return {
3208
- target,
3209
- deleteData,
3210
- sweepTreeseed,
3211
- summary: buildDestroySummary(deployConfig, state, target),
3212
- operations,
3213
- verification
3214
- };
3215
- }
3216
- function destroyCloudflareResources(tenantRoot, options = {}) {
3217
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
3218
- const deployConfig = loadTenantDeployConfig(tenantRoot);
3219
- const state = loadDeployState(tenantRoot, deployConfig, { target });
3220
- state.workerName = targetWorkerName(deployConfig, target);
3221
- const env = {
3222
- CLOUDFLARE_ACCOUNT_ID: resolveConfiguredCloudflareAccountId(deployConfig)
3223
- };
3224
- const planOnly = options.planOnly ?? false;
3225
- const deleteData = options.deleteData === true;
3226
- const force = options.force ?? false;
3227
- const kvNamespaces = planOnly ? [] : listKvNamespaces(tenantRoot, env);
3228
- const d1Databases = planOnly ? [] : listD1Databases(tenantRoot, env);
3229
- const queues = listQueues(tenantRoot, env);
3230
- const buckets = planOnly ? [] : listR2Buckets(tenantRoot, env);
3231
- const pagesProjects = planOnly ? [] : listPagesProjects(tenantRoot, env);
3232
- const turnstileWidgets = planOnly ? [] : listTurnstileWidgets(tenantRoot, env);
3233
- state.kvNamespaces.FORM_GUARD_KV.id = resolveExistingKvIdByName(
3234
- kvNamespaces,
3235
- state.kvNamespaces.FORM_GUARD_KV.name,
3236
- state.kvNamespaces.FORM_GUARD_KV.id
3237
- );
3238
- state.d1Databases.SITE_DATA_DB = resolveExistingD1ByName(
3239
- d1Databases,
3240
- state.d1Databases.SITE_DATA_DB.databaseName,
3241
- state.d1Databases.SITE_DATA_DB
3242
- );
3243
- state.turnstileWidgets.formGuard = resolveExistingTurnstileWidget(turnstileWidgets, state.turnstileWidgets?.formGuard);
3244
- const bucket = buckets.find((entry) => entry?.name === state.content?.bucketName);
3245
- const pagesProject = pagesProjects.find((entry) => entry?.name === state.pages?.projectName);
3246
- const worker = deleteWorker(tenantRoot, state.workerName, { env, planOnly, force });
3247
- const turnstileWidget = deleteTurnstileWidget(state.turnstileWidgets?.formGuard?.sitekey, {
3248
- env,
3249
- planOnly,
3250
- name: state.turnstileWidgets?.formGuard?.name
3251
- });
3252
- const formGuard = deleteKvNamespace(tenantRoot, state.kvNamespaces.FORM_GUARD_KV.id, { env, planOnly });
3253
- const database = deleteD1DatabaseForDestroy(tenantRoot, state.d1Databases.SITE_DATA_DB.databaseName, { env, planOnly, deleteData });
3254
- const r2Bucket = bucket || planOnly ? deleteR2Bucket(tenantRoot, state.content?.bucketName, { env, planOnly, deleteData }) : resourceOperation("cloudflare", "r2-bucket", state.content?.bucketName, "missing");
3255
- const pages = pagesProject || planOnly ? deletePagesProject(state.pages?.projectName, { env, planOnly }) : resourceOperation("cloudflare", "pages-project", state.pages?.projectName, "missing");
3256
- const operations = {
3257
- worker,
3258
- turnstileWidget,
3259
- formGuard,
3260
- database,
3261
- r2Bucket,
3262
- pages
3263
- };
3264
- return {
3265
- target,
3266
- deleteData,
3267
- summary: buildDestroySummary(deployConfig, state, target),
3268
- operations
3269
- };
3270
- }
3271
- function cleanupDestroyedState(tenantRoot, options = {}) {
3272
- const target = options.scope || options.target ? normalizeTarget(options.scope ?? options.target) : null;
3273
- if (target) {
3274
- const { statePath, generatedRoot } = resolveTargetPaths(tenantRoot, target);
3275
- rmSync(statePath, { force: true });
3276
- rmSync(generatedRoot, { recursive: true, force: true });
3277
- if (options.removeBuildArtifacts) {
3278
- rmSync(resolve(tenantRoot, "dist"), { recursive: true, force: true });
3279
- }
3280
- return;
3281
- }
3282
- rmSync(resolve(tenantRoot, STATE_ROOT), { recursive: true, force: true });
3283
- rmSync(resolve(tenantRoot, GENERATED_ROOT), { recursive: true, force: true });
3284
- if (options.removeBuildArtifacts) {
3285
- rmSync(resolve(tenantRoot, "dist"), { recursive: true, force: true });
3286
- }
3287
- }
3288
- function provisionCloudflareResources(tenantRoot, options = {}) {
3289
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
3290
- const deployConfig = loadTenantDeployConfig(tenantRoot);
3291
- const state = loadDeployState(tenantRoot, deployConfig, { target });
3292
- state.workerName = targetWorkerName(deployConfig, target);
3293
- const env = {
3294
- CLOUDFLARE_ACCOUNT_ID: resolveConfiguredCloudflareAccountId(deployConfig)
3295
- };
3296
- const planOnly = options.planOnly ?? false;
3297
- const kvNamespaces = planOnly ? [] : listKvNamespaces(tenantRoot, env);
3298
- const d1Databases = planOnly ? [] : listD1Databases(tenantRoot, env);
3299
- const queues = planOnly ? [] : listQueues(tenantRoot, env);
3300
- const buckets = planOnly ? [] : listR2Buckets(tenantRoot, env);
3301
- const pagesProjects = planOnly ? [] : listPagesProjects(tenantRoot, env);
3302
- const ensureKv = (binding) => {
3303
- const current = state.kvNamespaces[binding];
3304
- if (current?.id && !isPlaceholderResourceId(current.id)) {
3305
- state.kvNamespaces[binding].previewId = current.previewId ?? current.id;
3306
- return;
3307
- }
3308
- const existing = kvNamespaces.find((entry) => entry?.title === current.name);
3309
- if (existing?.id) {
3310
- state.kvNamespaces[binding].id = existing.id;
3311
- state.kvNamespaces[binding].previewId = existing.id;
3312
- return;
3313
- }
3314
- if (planOnly) {
3315
- state.kvNamespaces[binding].id = `plan-${current.name}`;
3316
- state.kvNamespaces[binding].previewId = `plan-${current.name}-preview`;
3317
- return;
3318
- }
3319
- runWrangler(["kv", "namespace", "create", current.name], { cwd: tenantRoot, capture: true, env });
3320
- const refreshed = listKvNamespaces(tenantRoot, env);
3321
- const created = refreshed.find((entry) => entry?.title === current.name);
3322
- if (!created?.id) {
3323
- throw new Error(`Unable to resolve created KV namespace id for ${current.name}.`);
3324
- }
3325
- state.kvNamespaces[binding].id = created.id;
3326
- state.kvNamespaces[binding].previewId = created.id;
3327
- };
3328
- const ensureD1 = () => {
3329
- const current = state.d1Databases.SITE_DATA_DB;
3330
- if (current?.databaseId && !isPlaceholderResourceId(current.databaseId)) {
3331
- return;
3332
- }
3333
- const existing = d1Databases.find((entry) => entry?.name === current.databaseName);
3334
- if (existing?.uuid) {
3335
- current.databaseId = existing.uuid;
3336
- current.previewDatabaseId = existing.previewDatabaseUuid ?? existing.uuid;
3337
- return;
3338
- }
3339
- if (planOnly) {
3340
- current.databaseId = `plan-${current.databaseName}`;
3341
- current.previewDatabaseId = `plan-${current.databaseName}-preview`;
3342
- return;
3343
- }
3344
- runWrangler(["d1", "create", current.databaseName], {
3345
- cwd: tenantRoot,
3346
- capture: true,
3347
- env
3348
- });
3349
- const refreshed = listD1Databases(tenantRoot, env);
3350
- const created = refreshed.find((entry) => entry?.name === current.databaseName);
3351
- if (!created?.uuid) {
3352
- throw new Error(`Unable to resolve created D1 database id for ${current.databaseName}.`);
3353
- }
3354
- current.databaseId = created.uuid;
3355
- current.previewDatabaseId = created.previewDatabaseUuid ?? created.uuid;
3356
- };
3357
- const ensureR2Bucket = () => {
3358
- const bucketName = state.content?.bucketName;
3359
- if (!bucketName) {
3360
- return;
3361
- }
3362
- let refreshedBuckets = buckets;
3363
- const exists = refreshedBuckets.find((entry) => entry?.name === bucketName);
3364
- if (exists) {
3365
- return;
3366
- }
3367
- if (planOnly) {
3368
- return;
3369
- }
3370
- try {
3371
- runWrangler(["r2", "bucket", "create", bucketName], {
3372
- cwd: tenantRoot,
3373
- capture: true,
3374
- env
3375
- });
3376
- } catch (error) {
3377
- if (!isWranglerAlreadyExistsError(error, [/bucket you tried to create already exists, and you own it/i, /\[code:\s*10004\]/i])) {
3378
- throw error;
3379
- }
3380
- }
3381
- refreshedBuckets = listR2Buckets(tenantRoot, env);
3382
- if (!refreshedBuckets.find((entry) => entry?.name === bucketName)) {
3383
- throw new Error(`Unable to resolve Cloudflare R2 bucket ${bucketName} after reconciliation.`);
3384
- }
3385
- };
3386
- const ensurePagesProject = () => {
3387
- const current = state.pages;
3388
- if (!current?.projectName) {
3389
- return;
3390
- }
3391
- const exists = pagesProjects.find((entry) => entry?.name === current.projectName);
3392
- if (exists) {
3393
- current.url = exists.subdomain ? `https://${exists.subdomain}` : current.url ?? `https://${current.projectName}.pages.dev`;
3394
- ensurePagesProjectCompatibility(env.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "", current.projectName, env, exists, { state, target });
3395
- return;
3396
- }
3397
- if (planOnly) {
3398
- current.url = `https://${current.projectName}.pages.dev`;
3399
- return;
3400
- }
3401
- runWrangler([
3402
- "pages",
3403
- "project",
3404
- "create",
3405
- current.projectName,
3406
- "--production-branch",
3407
- target.kind === "persistent" && target.scope === "prod" ? current.productionBranch ?? "main" : current.stagingBranch ?? "staging"
3408
- ], {
3409
- cwd: tenantRoot,
3410
- capture: true,
3411
- env
3412
- });
3413
- ensurePagesProjectCompatibility(env.CLOUDFLARE_ACCOUNT_ID ?? process.env.TREESEED_CLOUDFLARE_ACCOUNT_ID ?? "", current.projectName, env, null, { state, target });
3414
- current.url = `https://${current.projectName}.pages.dev`;
3415
- };
3416
- ensureKv("FORM_GUARD_KV");
3417
- ensureD1();
3418
- ensureR2Bucket();
3419
- ensurePagesProject();
3420
- reconcileCloudflareWebCacheRules(tenantRoot, deployConfig, state, target, { planOnly });
3421
- state.readiness.configured = true;
3422
- state.readiness.provisioned = hasProvisionedCloudflareResources(state);
3423
- state.readiness.deployable = state.readiness.provisioned === true;
3424
- state.readiness.phase = state.readiness.provisioned === true ? "provisioned" : "config_complete";
3425
- state.readiness.initialized = true;
3426
- state.readiness.initializedAt = (/* @__PURE__ */ new Date()).toISOString();
3427
- state.readiness.lastValidatedAt = state.readiness.initializedAt;
3428
- state.readiness.blockers = [];
3429
- state.readiness.warnings = [];
3430
- state.readiness.lastValidationSummary = {
3431
- cloudflare: state.readiness.provisioned === true ? "ready" : "incomplete",
3432
- railway: "configured"
3433
- };
3434
- writeDeployState(tenantRoot, state, { target });
3435
- return buildProvisioningSummary(deployConfig, state, target);
3436
- }
3437
- function syncCloudflareSecrets(tenantRoot, options = {}) {
3438
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
3439
- const deployConfig = loadTenantDeployConfig(tenantRoot);
3440
- const state = loadDeployState(tenantRoot, deployConfig, { target });
3441
- const env = {
3442
- CLOUDFLARE_ACCOUNT_ID: resolveConfiguredCloudflareAccountId(deployConfig)
3443
- };
3444
- const entryFilter = Array.isArray(options.entryIds) && options.entryIds.length > 0 ? new Set(options.entryIds) : null;
3445
- const extraSecrets = options.extraSecrets && typeof options.extraSecrets === "object" ? Object.fromEntries(Object.entries(options.extraSecrets).filter(([key, value]) => (!entryFilter || entryFilter.has(key)) && typeof value === "string" && value.length > 0)) : {};
3446
- const secrets = {
3447
- ...buildSecretMap(deployConfig, state),
3448
- ...extraSecrets
3449
- };
3450
- const synced = [];
3451
- const planOnly = options.planOnly ?? false;
3452
- for (const [key, value] of Object.entries(secrets)) {
3453
- if (!value) {
3454
- continue;
3455
- }
3456
- synced.push(key);
3457
- if (planOnly) {
3458
- continue;
3459
- }
3460
- const command = state.pages?.projectName && target.kind === "persistent" ? [resolveWranglerBin(), "pages", "secret", "put", key, "--project-name", state.pages.projectName] : [resolveWranglerBin(), "secret", "put", key, "--config", resolveGeneratedWranglerPath(tenantRoot, { target })];
3461
- const result = spawnSync(process.execPath, command, {
3462
- cwd: tenantRoot,
3463
- input: `${value}
3464
- `,
3465
- stdio: ["pipe", "inherit", "inherit"],
3466
- env: { ...process.env, ...env },
3467
- encoding: "utf8"
3468
- });
3469
- if (result.status !== 0) {
3470
- throw new Error(`Failed to sync secret ${key}.`);
3471
- }
3472
- }
3473
- state.generatedSecrets = {
3474
- ...state.generatedSecrets ?? {},
3475
- TREESEED_FORM_TOKEN_SECRET: secrets.TREESEED_FORM_TOKEN_SECRET ?? state.generatedSecrets?.TREESEED_FORM_TOKEN_SECRET,
3476
- TREESEED_EDITORIAL_PREVIEW_SECRET: secrets.TREESEED_EDITORIAL_PREVIEW_SECRET ?? state.generatedSecrets?.TREESEED_EDITORIAL_PREVIEW_SECRET
3477
- };
3478
- writeDeployState(tenantRoot, state, { target });
3479
- return synced;
3480
- }
3481
- function verifyProvisionedCloudflareResources(tenantRoot, options = {}) {
3482
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
3483
- const deployConfig = loadTenantDeployConfig(tenantRoot);
3484
- const state = loadDeployState(tenantRoot, deployConfig, { target });
3485
- const env = {
3486
- CLOUDFLARE_ACCOUNT_ID: resolveConfiguredCloudflareAccountId(deployConfig)
3487
- };
3488
- const planOnly = options.planOnly ?? false;
3489
- const kvNamespaces = planOnly ? [] : listKvNamespaces(tenantRoot, env);
3490
- const d1Databases = planOnly ? [] : listD1Databases(tenantRoot, env);
3491
- const queues = planOnly ? [] : listQueues(tenantRoot, env);
3492
- const buckets = planOnly ? [] : listR2Buckets(tenantRoot, env);
3493
- const pagesProjects = planOnly ? [] : listPagesProjects(tenantRoot, env);
3494
- const livePages = pagesProjects.find((entry) => entry?.name === state.pages?.projectName);
3495
- const pagesProject = planOnly || !env.CLOUDFLARE_ACCOUNT_ID || !state.pages?.projectName ? livePages : cloudflareApiRequest(
3496
- `/accounts/${encodeURIComponent(env.CLOUDFLARE_ACCOUNT_ID)}/pages/projects/${encodeURIComponent(state.pages.projectName)}`,
3497
- { env, allowFailure: true }
3498
- )?.result ?? livePages;
3499
- const pagesConfigKey = target.kind === "persistent" && target.scope === "prod" ? "production" : "preview";
3500
- const pagesConfig = pagesProject?.deployment_configs?.[pagesConfigKey] ?? {};
3501
- const pagesBindings = buildCloudflarePagesFunctionBindings(state);
3502
- const pageBindingConfigured = (configKey, binding, expected) => pagesConfig?.[configKey]?.[binding] && Object.entries(expected).every(([key, value]) => pagesConfig[configKey][binding]?.[key] === value);
3503
- const checks = {
3504
- pages: Boolean(state.pages?.projectName && (livePages || pagesProject?.name === state.pages.projectName)),
3505
- formGuardKv: Boolean(state.kvNamespaces?.FORM_GUARD_KV?.name && kvNamespaces.find((entry) => entry?.title === state.kvNamespaces.FORM_GUARD_KV.name)),
3506
- d1: Boolean(state.d1Databases?.SITE_DATA_DB?.databaseName && d1Databases.find((entry) => entry?.name === state.d1Databases.SITE_DATA_DB.databaseName)),
3507
- r2: Boolean(state.content?.bucketName && buckets.find((entry) => entry?.name === state.content.bucketName)),
3508
- pagesFormGuardKvBinding: !pagesBindings.kv_namespaces?.FORM_GUARD_KV || pageBindingConfigured("kv_namespaces", "FORM_GUARD_KV", pagesBindings.kv_namespaces.FORM_GUARD_KV),
3509
- pagesD1Binding: !pagesBindings.d1_databases?.SITE_DATA_DB || pageBindingConfigured("d1_databases", "SITE_DATA_DB", pagesBindings.d1_databases.SITE_DATA_DB),
3510
- pagesR2Binding: !state.content?.r2Binding || !pagesBindings.r2_buckets?.[state.content.r2Binding] || pageBindingConfigured("r2_buckets", state.content.r2Binding, pagesBindings.r2_buckets[state.content.r2Binding]),
3511
- webCache: !shouldManageCloudflareWebCacheRules(deployConfig, target) || state.webCache?.rulesManaged === true
3512
- };
3513
- const ok = planOnly ? true : Object.values(checks).every(Boolean);
3514
- state.readiness.configured = true;
3515
- state.readiness.provisioned = ok;
3516
- state.readiness.deployable = ok;
3517
- state.readiness.phase = ok ? "provisioned" : "config_complete";
3518
- state.readiness.lastValidatedAt = (/* @__PURE__ */ new Date()).toISOString();
3519
- state.readiness.blockers = [];
3520
- state.readiness.warnings = [];
3521
- state.readiness.lastValidationSummary = checks;
3522
- if (state.pages) {
3523
- const configuredWebUrl = resolveConfiguredSurfaceBaseUrl(deployConfig, target, "web");
3524
- if (configuredWebUrl) {
3525
- state.pages.url = configuredWebUrl;
3526
- } else if (livePages?.subdomain) {
3527
- state.pages.url = target.kind === "persistent" && target.scope === "staging" ? `https://${state.pages.stagingBranch ?? "staging"}.${livePages.subdomain}` : `https://${livePages.subdomain}`;
3528
- }
3529
- }
3530
- if (!planOnly) {
3531
- try {
3532
- reconcileCloudflareWebCacheRules(tenantRoot, deployConfig, state, target, { planOnly: false });
3533
- } catch (error) {
3534
- state.webCache.rulesManaged = false;
3535
- state.webCache.lastError = error instanceof Error ? error.message : String(error);
3536
- }
3537
- }
3538
- state.webCache.lastVerifiedAt = (/* @__PURE__ */ new Date()).toISOString();
3539
- writeDeployState(tenantRoot, state, { target });
3540
- return {
3541
- ok,
3542
- target: deployTargetLabel(target),
3543
- checks,
3544
- state
3545
- };
3546
- }
3547
- function runRemoteD1Migrations(tenantRoot, options = {}) {
3548
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
3549
- const { wranglerPath, deployConfig, state } = ensureGeneratedWranglerConfig(tenantRoot, { target });
3550
- if (options.planOnly) {
3551
- return { databaseName: state.d1Databases.SITE_DATA_DB.databaseName, planOnly: true };
3552
- }
3553
- const args = ["d1", "migrations", "apply", state.d1Databases.SITE_DATA_DB.databaseName, "--remote", "--config", wranglerPath];
3554
- const env = { CLOUDFLARE_ACCOUNT_ID: resolveConfiguredCloudflareAccountId(deployConfig) };
3555
- const isTransient = (output) => /fetch failed|timed out|etimedout|econnreset|enetunreach|temporarily unavailable|aborted|internal error/i.test(output || "");
3556
- let lastOutput = "";
3557
- for (let attempt = 1; attempt <= 3; attempt += 1) {
3558
- const result = runWrangler(args, {
3559
- cwd: tenantRoot,
3560
- env,
3561
- capture: true,
3562
- allowFailure: true
3563
- });
3564
- if (result.status === 0) {
3565
- return { databaseName: state.d1Databases.SITE_DATA_DB.databaseName, planOnly: false };
3566
- }
3567
- lastOutput = [result.stderr?.trim(), result.stdout?.trim()].filter(Boolean).join("\n");
3568
- if (!isTransient(lastOutput) || attempt === 3) {
3569
- throw new Error(lastOutput || `Wrangler command failed: ${args.join(" ")}`);
3570
- }
3571
- sleepSync(2e3 * attempt);
3572
- }
3573
- throw new Error(lastOutput || `Wrangler command failed: ${args.join(" ")}`);
3574
- }
3575
- function markDeploymentInitialized(tenantRoot, options = {}) {
3576
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
3577
- const deployConfig = loadTenantDeployConfig(tenantRoot);
3578
- const state = loadDeployState(tenantRoot, deployConfig, { target });
3579
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
3580
- state.readiness.initialized = true;
3581
- state.readiness.configured = true;
3582
- state.readiness.provisioned = hasProvisionedCloudflareResources(state);
3583
- state.readiness.deployable = state.readiness.provisioned === true;
3584
- state.readiness.phase = state.readiness.provisioned === true ? "provisioned" : "config_complete";
3585
- state.readiness.initializedAt = state.readiness.initializedAt ?? timestamp;
3586
- state.readiness.lastValidatedAt = timestamp;
3587
- state.readiness.lastConfigFingerprint = state.lastManifestFingerprint ?? state.readiness.lastConfigFingerprint;
3588
- state.readiness.blockers = [];
3589
- state.readiness.warnings = [];
3590
- writeDeployState(tenantRoot, state, { target });
3591
- return state;
3592
- }
3593
- function markManagedServicesInitialized(tenantRoot, options = {}) {
3594
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
3595
- const deployConfig = loadTenantDeployConfig(tenantRoot);
3596
- const state = loadDeployState(tenantRoot, deployConfig, { target });
3597
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
3598
- for (const serviceKey of MANAGED_SERVICE_KEYS) {
3599
- if (!state.services?.[serviceKey]?.enabled) {
3600
- continue;
3601
- }
3602
- state.services[serviceKey].initialized = true;
3603
- state.services[serviceKey].lastDeploymentTimestamp = state.services[serviceKey].lastDeploymentTimestamp ?? timestamp;
3604
- state.services[serviceKey].lastDeployedUrl = state.services[serviceKey].lastDeployedUrl ?? state.services[serviceKey].publicBaseUrl ?? null;
3605
- }
3606
- writeDeployState(tenantRoot, state, { target });
3607
- return state;
3608
- }
3609
- function recordHostedDeploymentState(tenantRoot, options = {}) {
3610
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
3611
- const deployConfig = loadTenantDeployConfig(tenantRoot);
3612
- const state = loadDeployState(tenantRoot, deployConfig, { target });
3613
- const timestamp = typeof options.timestamp === "string" && options.timestamp.trim() ? options.timestamp.trim() : (/* @__PURE__ */ new Date()).toISOString();
3614
- const deployedUrl = typeof options.url === "string" && options.url.trim() ? options.url.trim() : state.lastDeployedUrl ?? resolveConfiguredSurfaceBaseUrl(deployConfig, target, "web");
3615
- const commit = typeof options.commit === "string" && options.commit.trim() ? options.commit.trim() : null;
3616
- state.lastDeployedUrl = deployedUrl;
3617
- state.lastDeploymentTimestamp = timestamp;
3618
- state.lastDeployedCommit = commit;
3619
- state.readiness = {
3620
- ...state.readiness ?? {},
3621
- initialized: true,
3622
- configured: true,
3623
- provisioned: true,
3624
- deployable: true,
3625
- phase: "provisioned",
3626
- initializedAt: state.readiness?.initializedAt ?? timestamp,
3627
- lastValidatedAt: timestamp,
3628
- blockers: [],
3629
- warnings: state.readiness?.warnings ?? []
3630
- };
3631
- const nextHistoryEntry = {
3632
- commit,
3633
- timestamp,
3634
- url: deployedUrl,
3635
- target: deployTargetLabel(target),
3636
- source: options.source ?? "hosted-github-workflow",
3637
- workflow: options.workflow ?? null,
3638
- runId: options.runId ?? null
3639
- };
3640
- const history = Array.isArray(state.deploymentHistory) ? state.deploymentHistory : [];
3641
- state.deploymentHistory = [...history, nextHistoryEntry].slice(-20);
3642
- writeDeployState(tenantRoot, state, { target });
3643
- return state;
3644
- }
3645
- function assertDeploymentInitialized(tenantRoot, options = {}) {
3646
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
3647
- const deployConfig = loadTenantDeployConfig(tenantRoot);
3648
- const state = loadDeployState(tenantRoot, deployConfig, { target });
3649
- if (state.readiness?.initialized) {
3650
- return state;
3651
- }
3652
- throw new Error(
3653
- `Treeseed environment ${deployTargetLabel(target)} has not been initialized. Run \`treeseed config --environment ${scopeFromTarget(target)}\` first.`
3654
- );
3655
- }
3656
- function finalizeDeploymentState(tenantRoot, options = {}) {
3657
- const target = normalizeTarget(options.scope ?? options.target ?? "prod");
3658
- const deployConfig = loadTenantDeployConfig(tenantRoot);
3659
- const state = loadDeployState(tenantRoot, deployConfig, { target });
3660
- state.lastManifestFingerprint = stableHash(JSON.stringify({ deployConfig, targetKey: targetKey(target) }));
3661
- state.lastDeployedUrl = target.kind === "branch" ? targetWorkersDevUrl(state.workerName) : resolveConfiguredSurfaceBaseUrl(deployConfig, target, "web");
3662
- state.lastDeploymentTimestamp = (/* @__PURE__ */ new Date()).toISOString();
3663
- state.lastDeployedCommit = envOrNull("GITHUB_SHA") ?? envOrNull("TREESEED_DEPLOY_COMMIT") ?? null;
3664
- state.runtimeCompatibility = {
3665
- envelopeSchemaGeneration: TRESEED_ENVELOPE_SCHEMA_GENERATION,
3666
- migrationWaveId: TRESEED_MIGRATION_WAVE_ID,
3667
- supportedPayloadVersionRange: TRESEED_SUPPORTED_PAYLOAD_RANGE
3668
- };
3669
- const nextHistoryEntry = {
3670
- commit: state.lastDeployedCommit,
3671
- timestamp: state.lastDeploymentTimestamp,
3672
- url: state.lastDeployedUrl,
3673
- target: deployTargetLabel(target),
3674
- appVersion: envOrNull("npm_package_version") ?? envOrNull("TREESEED_APP_VERSION") ?? null,
3675
- envelopeSchemaGeneration: TRESEED_ENVELOPE_SCHEMA_GENERATION,
3676
- migrationWaveId: TRESEED_MIGRATION_WAVE_ID,
3677
- supportedPayloadVersionRange: TRESEED_SUPPORTED_PAYLOAD_RANGE
3678
- };
3679
- const history = Array.isArray(state.deploymentHistory) ? state.deploymentHistory : [];
3680
- state.deploymentHistory = [...history, nextHistoryEntry].slice(-20);
3681
- state.readiness.initialized = true;
3682
- state.readiness.configured = true;
3683
- state.readiness.provisioned = hasProvisionedCloudflareResources(state);
3684
- state.readiness.deployable = state.readiness.provisioned === true;
3685
- state.readiness.phase = state.readiness.provisioned === true ? "provisioned" : "config_complete";
3686
- state.readiness.lastValidatedAt = state.lastDeploymentTimestamp;
3687
- state.readiness.blockers = [];
3688
- state.readiness.warnings = [];
3689
- for (const result of options.serviceResults ?? []) {
3690
- if (!result?.service || !state.services?.[result.service]) {
3691
- continue;
3692
- }
3693
- state.services[result.service].initialized = true;
3694
- state.services[result.service].lastDeploymentTimestamp = state.lastDeploymentTimestamp;
3695
- state.services[result.service].lastDeployedUrl = result.publicBaseUrl ?? state.services[result.service].publicBaseUrl ?? state.services[result.service].lastDeployedUrl ?? null;
3696
- state.services[result.service].lastDeploymentCommand = result.command ?? null;
3697
- }
3698
- writeDeployState(tenantRoot, state, { target });
3699
- if (target.kind === "persistent") {
3700
- try {
3701
- const purgeResult = purgeSourcePageCaches(tenantRoot, { target, env: options.env });
3702
- if (target.scope === "prod" && purgeResult?.skipped) {
3703
- throw new Error(`Production source-page cache purge was skipped: ${purgeResult.reason ?? "unknown"}.`);
3704
- }
3705
- } catch (error) {
3706
- if (target.scope === "prod") {
3707
- throw error;
3708
- }
3709
- }
3710
- return loadDeployState(tenantRoot, deployConfig, { target });
3711
- }
3712
- return state;
3713
- }
3714
- function printDeploySummary(summary) {
3715
- console.log("Treeseed deployment summary");
3716
- console.log(` Target: ${summary.target}`);
3717
- console.log(` Worker: ${summary.workerName}`);
3718
- console.log(` Site URL: ${summary.siteUrl}`);
3719
- console.log(` Account ID: ${summary.accountId}`);
3720
- console.log(` D1: ${summary.siteDataDb.databaseName} (${summary.siteDataDb.databaseId})`);
3721
- console.log(` KV FORM_GUARD_KV: ${summary.formGuardKv.id}`);
3722
- }
3723
- function printDestroySummary(result) {
3724
- const { summary, operations } = result;
3725
- const cloudflare = Array.isArray(operations?.cloudflare) ? operations.cloudflare : null;
3726
- const legacy = cloudflare ? {
3727
- worker: cloudflare.find((entry) => entry.type === "worker"),
3728
- database: cloudflare.find((entry) => entry.type === "d1-database"),
3729
- formGuard: cloudflare.find((entry) => entry.type === "kv-namespace"),
3730
- formGuardPreview: cloudflare.find((entry) => entry.type === "kv-namespace-preview"),
3731
- session: cloudflare.find((entry) => entry.type === "kv-namespace" && entry.name === summary.sessionKv?.name),
3732
- sessionPreview: cloudflare.find((entry) => entry.type === "kv-namespace-preview" && entry.name === summary.sessionKv?.name)
3733
- } : operations;
3734
- console.log("Treeseed destroy summary");
3735
- console.log(` Target: ${summary.target}`);
3736
- console.log(` Worker: ${summary.workerName} -> ${legacy.worker?.status ?? "unknown"}`);
3737
- console.log(` Site URL: ${summary.siteUrl}`);
3738
- console.log(` Account ID: ${summary.accountId}`);
3739
- console.log(` D1: ${summary.siteDataDb.databaseName} -> ${legacy.database?.status ?? "unknown"}`);
3740
- console.log(` KV FORM_GUARD_KV: ${summary.formGuardKv.name} -> ${legacy.formGuard?.status ?? "unknown"}`);
3741
- if (legacy.formGuardPreview) {
3742
- console.log(` KV FORM_GUARD_KV preview -> ${legacy.formGuardPreview.status}`);
3743
- }
3744
- if (summary.sessionKv && legacy.session) {
3745
- console.log(` KV SESSION (deprecated): ${summary.sessionKv.name} -> ${legacy.session.status}`);
3746
- }
3747
- if (legacy.sessionPreview) {
3748
- console.log(` KV SESSION preview -> ${legacy.sessionPreview.status}`);
3749
- }
3750
- if (cloudflare) {
3751
- for (const entry of [
3752
- ...cloudflare.filter((item) => !["worker", "d1-database", "kv-namespace", "kv-namespace-preview"].includes(item.type)),
3753
- ...Array.isArray(operations?.railway) ? operations.railway : [],
3754
- ...Array.isArray(operations?.local) ? operations.local : []
3755
- ]) {
3756
- console.log(` ${entry.provider} ${entry.type} ${entry.name ?? "(none)"} -> ${entry.status}`);
3757
- }
3758
- }
3759
- }
3760
- export {
3761
- assertDeploymentInitialized,
3762
- buildCloudflarePagesFunctionBindings,
3763
- buildProvisioningSummary,
3764
- buildPublicVars,
3765
- buildSecretMap,
3766
- buildTreeseedManagedCloudflareCacheRules,
3767
- buildWranglerConfigContents,
3768
- cleanupDestroyedState,
3769
- cloudflareApiRequest,
3770
- cloudflareDestroyVerification,
3771
- collectMissingDeployInputs,
3772
- createBranchPreviewDeployTarget,
3773
- createPersistentDeployTarget,
3774
- createTurnstileWidget,
3775
- deployTargetLabel,
3776
- deriveTreeseedStagingSurfaceDomain,
3777
- destroyCloudflareResources,
3778
- destroyTreeseedEnvironmentResources,
3779
- dockerLocalRuntimeResourceOperations,
3780
- ensureGeneratedWranglerConfig,
3781
- finalizeDeploymentState,
3782
- getTurnstileWidget,
3783
- hasProvisionedCloudflareResources,
3784
- isWranglerAlreadyExistsError,
3785
- listD1Databases,
3786
- listDnsRecords,
3787
- listDnsZones,
3788
- listKvNamespaces,
3789
- listPagesProjects,
3790
- listQueues,
3791
- listR2Buckets,
3792
- listTurnstileWidgets,
3793
- listWorkers,
3794
- loadDeployState,
3795
- markDeploymentInitialized,
3796
- markManagedServicesInitialized,
3797
- mergeCloudflarePagesDeploymentConfig,
3798
- normalizePersistentScope,
3799
- printDeploySummary,
3800
- printDestroySummary,
3801
- promptForMissingDeployInputs,
3802
- provisionCloudflareResources,
3803
- purgePublishedContentCaches,
3804
- purgeSourcePageCaches,
3805
- queueId,
3806
- queueName,
3807
- reconcileCloudflareWebCacheRules,
3808
- recordHostedDeploymentState,
3809
- resolveCloudflareZoneIdForHost,
3810
- resolveConfiguredCloudflareAccountId,
3811
- resolveConfiguredSurfaceBaseUrl,
3812
- resolveConfiguredSurfaceDomain,
3813
- resolveGeneratedWranglerPath,
3814
- resolveTreeseedResourceIdentity,
3815
- runRemoteD1Migrations,
3816
- runWrangler,
3817
- scopeFromTarget,
3818
- setDestroyDockerRunnerForTests,
3819
- shouldDeleteRailwayProjectAfterEnvironmentDestroy,
3820
- syncCloudflareSecrets,
3821
- updateTurnstileWidget,
3822
- validateDeployPrerequisites,
3823
- validateDestroyPrerequisites,
3824
- verifyProvisionedCloudflareResources,
3825
- writeDeployState
3826
- };