@slaw-ai/db 2026.611.0

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 (590) hide show
  1. package/LICENSE +26 -0
  2. package/dist/backup-lib.d.ts +42 -0
  3. package/dist/backup-lib.d.ts.map +1 -0
  4. package/dist/backup-lib.js +862 -0
  5. package/dist/backup-lib.js.map +1 -0
  6. package/dist/backup-lib.test.d.ts +2 -0
  7. package/dist/backup-lib.test.d.ts.map +1 -0
  8. package/dist/backup-lib.test.js +376 -0
  9. package/dist/backup-lib.test.js.map +1 -0
  10. package/dist/backup.d.ts +2 -0
  11. package/dist/backup.d.ts.map +1 -0
  12. package/dist/backup.js +77 -0
  13. package/dist/backup.js.map +1 -0
  14. package/dist/check-migration-numbering.d.ts +2 -0
  15. package/dist/check-migration-numbering.d.ts.map +1 -0
  16. package/dist/check-migration-numbering.js +64 -0
  17. package/dist/check-migration-numbering.js.map +1 -0
  18. package/dist/client.d.ts +43 -0
  19. package/dist/client.d.ts.map +1 -0
  20. package/dist/client.js +586 -0
  21. package/dist/client.js.map +1 -0
  22. package/dist/client.test.d.ts +2 -0
  23. package/dist/client.test.d.ts.map +1 -0
  24. package/dist/client.test.js +400 -0
  25. package/dist/client.test.js.map +1 -0
  26. package/dist/embedded-postgres-error.d.ts +9 -0
  27. package/dist/embedded-postgres-error.d.ts.map +1 -0
  28. package/dist/embedded-postgres-error.js +73 -0
  29. package/dist/embedded-postgres-error.js.map +1 -0
  30. package/dist/embedded-postgres-error.test.d.ts +2 -0
  31. package/dist/embedded-postgres-error.test.d.ts.map +1 -0
  32. package/dist/embedded-postgres-error.test.js +25 -0
  33. package/dist/embedded-postgres-error.test.js.map +1 -0
  34. package/dist/embedded-postgres-native.d.ts +3 -0
  35. package/dist/embedded-postgres-native.d.ts.map +1 -0
  36. package/dist/embedded-postgres-native.js +83 -0
  37. package/dist/embedded-postgres-native.js.map +1 -0
  38. package/dist/embedded-postgres-native.test.d.ts +2 -0
  39. package/dist/embedded-postgres-native.test.d.ts.map +1 -0
  40. package/dist/embedded-postgres-native.test.js +36 -0
  41. package/dist/embedded-postgres-native.test.js.map +1 -0
  42. package/dist/index.d.ts +9 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +9 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/migrate.d.ts +2 -0
  47. package/dist/migrate.d.ts.map +1 -0
  48. package/dist/migrate.js +25 -0
  49. package/dist/migrate.js.map +1 -0
  50. package/dist/migration-runtime.d.ts +7 -0
  51. package/dist/migration-runtime.d.ts.map +1 -0
  52. package/dist/migration-runtime.js +159 -0
  53. package/dist/migration-runtime.js.map +1 -0
  54. package/dist/migration-status.d.ts +2 -0
  55. package/dist/migration-status.d.ts.map +1 -0
  56. package/dist/migration-status.js +55 -0
  57. package/dist/migration-status.js.map +1 -0
  58. package/dist/migrations/0000_mature_masked_marvel.sql +208 -0
  59. package/dist/migrations/0001_fast_northstar.sql +87 -0
  60. package/dist/migrations/0002_big_zaladane.sql +1 -0
  61. package/dist/migrations/0003_shallow_quentin_quire.sql +5 -0
  62. package/dist/migrations/0004_issue_identifiers.sql +28 -0
  63. package/dist/migrations/0005_chief_luke_cage.sql +19 -0
  64. package/dist/migrations/0006_overjoyed_mister_sinister.sql +36 -0
  65. package/dist/migrations/0007_new_quentin_quire.sql +20 -0
  66. package/dist/migrations/0008_amused_zzzax.sql +1 -0
  67. package/dist/migrations/0009_fast_jackal.sql +36 -0
  68. package/dist/migrations/0010_stale_justin_hammer.sql +37 -0
  69. package/dist/migrations/0011_windy_corsair.sql +18 -0
  70. package/dist/migrations/0012_perpetual_ser_duncan.sql +2 -0
  71. package/dist/migrations/0013_dashing_wasp.sql +4 -0
  72. package/dist/migrations/0014_many_mikhail_rasputin.sql +135 -0
  73. package/dist/migrations/0015_project_color_archived.sql +2 -0
  74. package/dist/migrations/0016_agent_icon.sql +1 -0
  75. package/dist/migrations/0017_tiresome_gabe_jones.sql +51 -0
  76. package/dist/migrations/0018_flat_sleepwalker.sql +26 -0
  77. package/dist/migrations/0019_public_victor_mancha.sql +18 -0
  78. package/dist/migrations/0020_white_anita_blake.sql +1 -0
  79. package/dist/migrations/0021_chief_vindicator.sql +1 -0
  80. package/dist/migrations/0022_squad_brand_color.sql +1 -0
  81. package/dist/migrations/0023_fair_lethal_legion.sql +3 -0
  82. package/dist/migrations/0024_far_beast.sql +2 -0
  83. package/dist/migrations/0025_nasty_salo.sql +15 -0
  84. package/dist/migrations/0026_lying_pete_wisdom.sql +39 -0
  85. package/dist/migrations/0027_tranquil_tenebrous.sql +2 -0
  86. package/dist/migrations/0028_harsh_goliath.sql +54 -0
  87. package/dist/migrations/0029_plugin_tables.sql +177 -0
  88. package/dist/migrations/0030_rich_magneto.sql +12 -0
  89. package/dist/migrations/0031_zippy_magma.sql +51 -0
  90. package/dist/migrations/0032_pretty_doctor_octopus.sql +102 -0
  91. package/dist/migrations/0033_shiny_black_tarantula.sql +2 -0
  92. package/dist/migrations/0034_fat_dormammu.sql +2 -0
  93. package/dist/migrations/0035_marvelous_satana.sql +91 -0
  94. package/dist/migrations/0036_cheerful_nitro.sql +9 -0
  95. package/dist/migrations/0037_friendly_eddie_brock.sql +29 -0
  96. package/dist/migrations/0038_careless_iron_monger.sql +5 -0
  97. package/dist/migrations/0039_fat_magneto.sql +161 -0
  98. package/dist/migrations/0040_eager_shotgun.sql +5 -0
  99. package/dist/migrations/0041_curly_maria_hill.sql +1 -0
  100. package/dist/migrations/0042_spotty_the_renegades.sql +26 -0
  101. package/dist/migrations/0043_reflective_captain_universe.sql +6 -0
  102. package/dist/migrations/0044_illegal_toad.sql +56 -0
  103. package/dist/migrations/0045_workable_shockwave.sql +17 -0
  104. package/dist/migrations/0046_smooth_sentinels.sql +11 -0
  105. package/dist/migrations/0047_overjoyed_groot.sql +102 -0
  106. package/dist/migrations/0048_flashy_marrow.sql +1 -0
  107. package/dist/migrations/0049_flawless_abomination.sql +21 -0
  108. package/dist/migrations/0050_stiff_luckman.sql +1 -0
  109. package/dist/migrations/0051_young_korg.sql +5 -0
  110. package/dist/migrations/0052_mushy_trauma.sql +26 -0
  111. package/dist/migrations/0053_sharp_wild_child.sql +18 -0
  112. package/dist/migrations/0054_draft_routines.sql +2 -0
  113. package/dist/migrations/0055_kind_weapon_omega.sql +1 -0
  114. package/dist/migrations/0056_spooky_ultragirl.sql +22 -0
  115. package/dist/migrations/0057_tidy_join_requests.sql +57 -0
  116. package/dist/migrations/0058_wealthy_starbolt.sql +6 -0
  117. package/dist/migrations/0059_plugin_database_namespaces.sql +41 -0
  118. package/dist/migrations/0060_orange_annihilus.sql +50 -0
  119. package/dist/migrations/0061_lively_thor_girl.sql +3 -0
  120. package/dist/migrations/0062_routine_run_dispatch_fingerprint.sql +9 -0
  121. package/dist/migrations/0063_issue_thread_interactions.sql +65 -0
  122. package/dist/migrations/0064_issue_thread_interaction_idempotency.sql +4 -0
  123. package/dist/migrations/0065_environments.sql +50 -0
  124. package/dist/migrations/0066_issue_tree_holds.sql +107 -0
  125. package/dist/migrations/0067_agent_default_environment.sql +3 -0
  126. package/dist/migrations/0068_environment_local_driver_unique.sql +2 -0
  127. package/dist/migrations/0069_liveness_recovery_dedupe.sql +13 -0
  128. package/dist/migrations/0070_active_run_output_watchdog.sql +70 -0
  129. package/dist/migrations/0071_default_hire_approval_off.sql +1 -0
  130. package/dist/migrations/0072_large_sandman.sql +6 -0
  131. package/dist/migrations/0073_shiny_salo.sql +1 -0
  132. package/dist/migrations/0074_striped_genesis.sql +4 -0
  133. package/dist/migrations/0075_cultured_sebastian_shaw.sql +7 -0
  134. package/dist/migrations/0076_useful_elektra.sql +29 -0
  135. package/dist/migrations/0077_unusual_karnak.sql +140 -0
  136. package/dist/migrations/0078_white_darwin.sql +3 -0
  137. package/dist/migrations/0079_squad_search_document_indexes.sql +2 -0
  138. package/dist/migrations/0080_squad_search_fuzzystrmatch.sql +1 -0
  139. package/dist/migrations/0081_optimal_dormammu.sql +1 -0
  140. package/dist/migrations/0082_dry_vision.sql +124 -0
  141. package/dist/migrations/0083_squad_secret_provider_configs.sql +51 -0
  142. package/dist/migrations/0084_issue_recovery_actions.sql +64 -0
  143. package/dist/migrations/0085_tranquil_the_executioner.sql +8 -0
  144. package/dist/migrations/0086_routine_env_runtime_contract.sql +8 -0
  145. package/dist/migrations/0087_backfill_environment_manage_human_defaults.sql +29 -0
  146. package/dist/migrations/0088_backfill_principal_access_compatibility.sql +75 -0
  147. package/dist/migrations/0089_cloud_upstreams.sql +71 -0
  148. package/dist/migrations/0090_resource_memberships.sql +55 -0
  149. package/dist/migrations/0091_old_swarm.sql +189 -0
  150. package/dist/migrations/0092_mighty_puma.sql +28 -0
  151. package/dist/migrations/0093_giant_green_goblin.sql +6 -0
  152. package/dist/migrations/0094_botfather_sync_state.sql +7 -0
  153. package/dist/migrations/0095_instance_limits.sql +10 -0
  154. package/dist/migrations/0096_squad_skills_tower_managed.sql +4 -0
  155. package/dist/migrations/0097_board_to_operator.sql +52 -0
  156. package/dist/migrations/0098_roles_to_leads.sql +13 -0
  157. package/dist/migrations/meta/0000_snapshot.json +1743 -0
  158. package/dist/migrations/meta/0001_snapshot.json +2441 -0
  159. package/dist/migrations/meta/0002_snapshot.json +2454 -0
  160. package/dist/migrations/meta/0003_snapshot.json +2502 -0
  161. package/dist/migrations/meta/0005_snapshot.json +2719 -0
  162. package/dist/migrations/meta/0006_snapshot.json +3048 -0
  163. package/dist/migrations/meta/0007_snapshot.json +3258 -0
  164. package/dist/migrations/meta/0008_snapshot.json +3264 -0
  165. package/dist/migrations/meta/0009_snapshot.json +3587 -0
  166. package/dist/migrations/meta/0010_snapshot.json +3929 -0
  167. package/dist/migrations/meta/0011_snapshot.json +4068 -0
  168. package/dist/migrations/meta/0012_snapshot.json +4087 -0
  169. package/dist/migrations/meta/0013_snapshot.json +4118 -0
  170. package/dist/migrations/meta/0014_snapshot.json +5187 -0
  171. package/dist/migrations/meta/0017_snapshot.json +5215 -0
  172. package/dist/migrations/meta/0018_snapshot.json +5450 -0
  173. package/dist/migrations/meta/0019_snapshot.json +5603 -0
  174. package/dist/migrations/meta/0020_snapshot.json +5603 -0
  175. package/dist/migrations/meta/0021_snapshot.json +5609 -0
  176. package/dist/migrations/meta/0023_snapshot.json +5633 -0
  177. package/dist/migrations/meta/0024_snapshot.json +5693 -0
  178. package/dist/migrations/meta/0025_snapshot.json +5849 -0
  179. package/dist/migrations/meta/0027_snapshot.json +6205 -0
  180. package/dist/migrations/meta/0028_snapshot.json +6710 -0
  181. package/dist/migrations/meta/0029_snapshot.json +7899 -0
  182. package/dist/migrations/meta/0030_snapshot.json +8003 -0
  183. package/dist/migrations/meta/0031_snapshot.json +7242 -0
  184. package/dist/migrations/meta/0032_snapshot.json +7733 -0
  185. package/dist/migrations/meta/0033_snapshot.json +9038 -0
  186. package/dist/migrations/meta/0034_snapshot.json +9039 -0
  187. package/dist/migrations/meta/0035_snapshot.json +9959 -0
  188. package/dist/migrations/meta/0036_snapshot.json +10023 -0
  189. package/dist/migrations/meta/0037_snapshot.json +10263 -0
  190. package/dist/migrations/meta/0038_snapshot.json +11350 -0
  191. package/dist/migrations/meta/0039_snapshot.json +10308 -0
  192. package/dist/migrations/meta/0040_snapshot.json +10481 -0
  193. package/dist/migrations/meta/0041_snapshot.json +11393 -0
  194. package/dist/migrations/meta/0044_snapshot.json +11701 -0
  195. package/dist/migrations/meta/0045_snapshot.json +11857 -0
  196. package/dist/migrations/meta/0046_snapshot.json +11870 -0
  197. package/dist/migrations/meta/0047_snapshot.json +12539 -0
  198. package/dist/migrations/meta/0048_snapshot.json +12546 -0
  199. package/dist/migrations/meta/0049_snapshot.json +12766 -0
  200. package/dist/migrations/meta/0050_snapshot.json +12772 -0
  201. package/dist/migrations/meta/0051_snapshot.json +12836 -0
  202. package/dist/migrations/meta/0052_snapshot.json +13057 -0
  203. package/dist/migrations/meta/0053_snapshot.json +12979 -0
  204. package/dist/migrations/meta/0055_snapshot.json +13206 -0
  205. package/dist/migrations/meta/0056_snapshot.json +13388 -0
  206. package/dist/migrations/meta/0057_snapshot.json +13432 -0
  207. package/dist/migrations/meta/0058_snapshot.json +13490 -0
  208. package/dist/migrations/meta/0060_snapshot.json +14023 -0
  209. package/dist/migrations/meta/0061_snapshot.json +14042 -0
  210. package/dist/migrations/meta/0072_snapshot.json +15852 -0
  211. package/dist/migrations/meta/0073_snapshot.json +15859 -0
  212. package/dist/migrations/meta/0074_snapshot.json +15887 -0
  213. package/dist/migrations/meta/0075_snapshot.json +15945 -0
  214. package/dist/migrations/meta/0077_snapshot.json +16355 -0
  215. package/dist/migrations/meta/0078_snapshot.json +16373 -0
  216. package/dist/migrations/meta/0081_snapshot.json +16380 -0
  217. package/dist/migrations/meta/0090_snapshot.json +17974 -0
  218. package/dist/migrations/meta/0091_snapshot.json +18843 -0
  219. package/dist/migrations/meta/0092_snapshot.json +19543 -0
  220. package/dist/migrations/meta/0093_snapshot.json +19543 -0
  221. package/dist/migrations/meta/_journal.json +699 -0
  222. package/dist/runtime-config.d.ts +16 -0
  223. package/dist/runtime-config.d.ts.map +1 -0
  224. package/dist/runtime-config.js +168 -0
  225. package/dist/runtime-config.js.map +1 -0
  226. package/dist/runtime-config.test.d.ts +2 -0
  227. package/dist/runtime-config.test.d.ts.map +1 -0
  228. package/dist/runtime-config.test.js +111 -0
  229. package/dist/runtime-config.test.js.map +1 -0
  230. package/dist/schema/activity_log.d.ts +197 -0
  231. package/dist/schema/activity_log.d.ts.map +1 -0
  232. package/dist/schema/activity_log.js +22 -0
  233. package/dist/schema/activity_log.js.map +1 -0
  234. package/dist/schema/agent_api_keys.d.ts +144 -0
  235. package/dist/schema/agent_api_keys.d.ts.map +1 -0
  236. package/dist/schema/agent_api_keys.js +17 -0
  237. package/dist/schema/agent_api_keys.js.map +1 -0
  238. package/dist/schema/agent_config_revisions.d.ts +201 -0
  239. package/dist/schema/agent_config_revisions.d.ts.map +1 -0
  240. package/dist/schema/agent_config_revisions.js +20 -0
  241. package/dist/schema/agent_config_revisions.js.map +1 -0
  242. package/dist/schema/agent_memberships.d.ts +127 -0
  243. package/dist/schema/agent_memberships.d.ts.map +1 -0
  244. package/dist/schema/agent_memberships.js +17 -0
  245. package/dist/schema/agent_memberships.js.map +1 -0
  246. package/dist/schema/agent_runtime_state.d.ts +248 -0
  247. package/dist/schema/agent_runtime_state.d.ts.map +1 -0
  248. package/dist/schema/agent_runtime_state.js +23 -0
  249. package/dist/schema/agent_runtime_state.js.map +1 -0
  250. package/dist/schema/agent_task_sessions.d.ts +197 -0
  251. package/dist/schema/agent_task_sessions.d.ts.map +1 -0
  252. package/dist/schema/agent_task_sessions.js +22 -0
  253. package/dist/schema/agent_task_sessions.js.map +1 -0
  254. package/dist/schema/agent_wakeup_requests.d.ts +333 -0
  255. package/dist/schema/agent_wakeup_requests.d.ts.map +1 -0
  256. package/dist/schema/agent_wakeup_requests.js +29 -0
  257. package/dist/schema/agent_wakeup_requests.js.map +1 -0
  258. package/dist/schema/agents.d.ts +390 -0
  259. package/dist/schema/agents.d.ts.map +1 -0
  260. package/dist/schema/agents.js +32 -0
  261. package/dist/schema/agents.js.map +1 -0
  262. package/dist/schema/approval_comments.d.ts +144 -0
  263. package/dist/schema/approval_comments.d.ts.map +1 -0
  264. package/dist/schema/approval_comments.js +19 -0
  265. package/dist/schema/approval_comments.js.map +1 -0
  266. package/dist/schema/approvals.d.ts +214 -0
  267. package/dist/schema/approvals.d.ts.map +1 -0
  268. package/dist/schema/approvals.js +20 -0
  269. package/dist/schema/approvals.js.map +1 -0
  270. package/dist/schema/assets.d.ts +212 -0
  271. package/dist/schema/assets.d.ts.map +1 -0
  272. package/dist/schema/assets.js +22 -0
  273. package/dist/schema/assets.js.map +1 -0
  274. package/dist/schema/auth.d.ts +607 -0
  275. package/dist/schema/auth.d.ts.map +1 -0
  276. package/dist/schema/auth.js +44 -0
  277. package/dist/schema/auth.js.map +1 -0
  278. package/dist/schema/botfather_sync_state.d.ts +103 -0
  279. package/dist/schema/botfather_sync_state.d.ts.map +1 -0
  280. package/dist/schema/botfather_sync_state.js +22 -0
  281. package/dist/schema/botfather_sync_state.js.map +1 -0
  282. package/dist/schema/budget_incidents.d.ts +297 -0
  283. package/dist/schema/budget_incidents.d.ts.map +1 -0
  284. package/dist/schema/budget_incidents.js +29 -0
  285. package/dist/schema/budget_incidents.js.map +1 -0
  286. package/dist/schema/budget_policies.d.ts +263 -0
  287. package/dist/schema/budget_policies.d.ts.map +1 -0
  288. package/dist/schema/budget_policies.js +24 -0
  289. package/dist/schema/budget_policies.js.map +1 -0
  290. package/dist/schema/cli_auth_challenges.d.ts +263 -0
  291. package/dist/schema/cli_auth_challenges.d.ts.map +1 -0
  292. package/dist/schema/cli_auth_challenges.js +26 -0
  293. package/dist/schema/cli_auth_challenges.js.map +1 -0
  294. package/dist/schema/cloud_upstreams.d.ts +884 -0
  295. package/dist/schema/cloud_upstreams.d.ts.map +1 -0
  296. package/dist/schema/cloud_upstreams.js +63 -0
  297. package/dist/schema/cloud_upstreams.js.map +1 -0
  298. package/dist/schema/cost_events.d.ts +314 -0
  299. package/dist/schema/cost_events.d.ts.map +1 -0
  300. package/dist/schema/cost_events.js +34 -0
  301. package/dist/schema/cost_events.js.map +1 -0
  302. package/dist/schema/document_annotation_anchor_snapshots.d.ts +255 -0
  303. package/dist/schema/document_annotation_anchor_snapshots.d.ts.map +1 -0
  304. package/dist/schema/document_annotation_anchor_snapshots.js +25 -0
  305. package/dist/schema/document_annotation_anchor_snapshots.js.map +1 -0
  306. package/dist/schema/document_annotation_comments.d.ts +214 -0
  307. package/dist/schema/document_annotation_comments.d.ts.map +1 -0
  308. package/dist/schema/document_annotation_comments.js +27 -0
  309. package/dist/schema/document_annotation_comments.js.map +1 -0
  310. package/dist/schema/document_annotation_threads.d.ts +476 -0
  311. package/dist/schema/document_annotation_threads.d.ts.map +1 -0
  312. package/dist/schema/document_annotation_threads.js +44 -0
  313. package/dist/schema/document_annotation_threads.js.map +1 -0
  314. package/dist/schema/document_revisions.d.ts +212 -0
  315. package/dist/schema/document_revisions.d.ts.map +1 -0
  316. package/dist/schema/document_revisions.js +23 -0
  317. package/dist/schema/document_revisions.js.map +1 -0
  318. package/dist/schema/documents.d.ts +280 -0
  319. package/dist/schema/documents.d.ts.map +1 -0
  320. package/dist/schema/documents.js +27 -0
  321. package/dist/schema/documents.js.map +1 -0
  322. package/dist/schema/environment_leases.d.ts +333 -0
  323. package/dist/schema/environment_leases.d.ts.map +1 -0
  324. package/dist/schema/environment_leases.js +35 -0
  325. package/dist/schema/environment_leases.js.map +1 -0
  326. package/dist/schema/environments.d.ts +182 -0
  327. package/dist/schema/environments.d.ts.map +1 -0
  328. package/dist/schema/environments.js +22 -0
  329. package/dist/schema/environments.js.map +1 -0
  330. package/dist/schema/execution_workspaces.d.ts +418 -0
  331. package/dist/schema/execution_workspaces.d.ts.map +1 -0
  332. package/dist/schema/execution_workspaces.js +39 -0
  333. package/dist/schema/execution_workspaces.js.map +1 -0
  334. package/dist/schema/feedback_exports.d.ts +450 -0
  335. package/dist/schema/feedback_exports.d.ts.map +1 -0
  336. package/dist/schema/feedback_exports.js +41 -0
  337. package/dist/schema/feedback_exports.js.map +1 -0
  338. package/dist/schema/feedback_votes.d.ts +246 -0
  339. package/dist/schema/feedback_votes.d.ts.map +1 -0
  340. package/dist/schema/feedback_votes.js +25 -0
  341. package/dist/schema/feedback_votes.js.map +1 -0
  342. package/dist/schema/finance_events.d.ts +469 -0
  343. package/dist/schema/finance_events.d.ts.map +1 -0
  344. package/dist/schema/finance_events.js +45 -0
  345. package/dist/schema/finance_events.js.map +1 -0
  346. package/dist/schema/goals.d.ts +178 -0
  347. package/dist/schema/goals.d.ts.map +1 -0
  348. package/dist/schema/goals.js +18 -0
  349. package/dist/schema/goals.js.map +1 -0
  350. package/dist/schema/heartbeat_run_events.d.ts +214 -0
  351. package/dist/schema/heartbeat_run_events.d.ts.map +1 -0
  352. package/dist/schema/heartbeat_run_events.js +23 -0
  353. package/dist/schema/heartbeat_run_events.js.map +1 -0
  354. package/dist/schema/heartbeat_run_watchdog_decisions.d.ts +195 -0
  355. package/dist/schema/heartbeat_run_watchdog_decisions.d.ts.map +1 -0
  356. package/dist/schema/heartbeat_run_watchdog_decisions.js +22 -0
  357. package/dist/schema/heartbeat_run_watchdog_decisions.js.map +1 -0
  358. package/dist/schema/heartbeat_runs.d.ts +830 -0
  359. package/dist/schema/heartbeat_runs.d.ts.map +1 -0
  360. package/dist/schema/heartbeat_runs.js +62 -0
  361. package/dist/schema/heartbeat_runs.js.map +1 -0
  362. package/dist/schema/inbox_dismissals.d.ts +127 -0
  363. package/dist/schema/inbox_dismissals.d.ts.map +1 -0
  364. package/dist/schema/inbox_dismissals.js +16 -0
  365. package/dist/schema/inbox_dismissals.js.map +1 -0
  366. package/dist/schema/index.d.ts +88 -0
  367. package/dist/schema/index.d.ts.map +1 -0
  368. package/dist/schema/index.js +88 -0
  369. package/dist/schema/index.js.map +1 -0
  370. package/dist/schema/instance_limits.d.ts +155 -0
  371. package/dist/schema/instance_limits.d.ts.map +1 -0
  372. package/dist/schema/instance_limits.js +26 -0
  373. package/dist/schema/instance_limits.js.map +1 -0
  374. package/dist/schema/instance_settings.d.ts +114 -0
  375. package/dist/schema/instance_settings.d.ts.map +1 -0
  376. package/dist/schema/instance_settings.js +12 -0
  377. package/dist/schema/instance_settings.js.map +1 -0
  378. package/dist/schema/instance_user_roles.d.ts +93 -0
  379. package/dist/schema/instance_user_roles.d.ts.map +1 -0
  380. package/dist/schema/instance_user_roles.js +12 -0
  381. package/dist/schema/instance_user_roles.js.map +1 -0
  382. package/dist/schema/invites.d.ts +214 -0
  383. package/dist/schema/invites.d.ts.map +1 -0
  384. package/dist/schema/invites.js +20 -0
  385. package/dist/schema/invites.js.map +1 -0
  386. package/dist/schema/issue_approvals.d.ts +110 -0
  387. package/dist/schema/issue_approvals.d.ts.map +1 -0
  388. package/dist/schema/issue_approvals.js +19 -0
  389. package/dist/schema/issue_approvals.js.map +1 -0
  390. package/dist/schema/issue_attachments.d.ts +127 -0
  391. package/dist/schema/issue_attachments.d.ts.map +1 -0
  392. package/dist/schema/issue_attachments.js +19 -0
  393. package/dist/schema/issue_attachments.js.map +1 -0
  394. package/dist/schema/issue_comments.d.ts +219 -0
  395. package/dist/schema/issue_comments.d.ts.map +1 -0
  396. package/dist/schema/issue_comments.js +26 -0
  397. package/dist/schema/issue_comments.js.map +1 -0
  398. package/dist/schema/issue_documents.d.ts +127 -0
  399. package/dist/schema/issue_documents.d.ts.map +1 -0
  400. package/dist/schema/issue_documents.js +18 -0
  401. package/dist/schema/issue_documents.js.map +1 -0
  402. package/dist/schema/issue_execution_decisions.d.ts +212 -0
  403. package/dist/schema/issue_execution_decisions.d.ts.map +1 -0
  404. package/dist/schema/issue_execution_decisions.js +23 -0
  405. package/dist/schema/issue_execution_decisions.js.map +1 -0
  406. package/dist/schema/issue_inbox_archives.d.ts +127 -0
  407. package/dist/schema/issue_inbox_archives.d.ts.map +1 -0
  408. package/dist/schema/issue_inbox_archives.js +17 -0
  409. package/dist/schema/issue_inbox_archives.js.map +1 -0
  410. package/dist/schema/issue_labels.d.ts +76 -0
  411. package/dist/schema/issue_labels.d.ts.map +1 -0
  412. package/dist/schema/issue_labels.js +16 -0
  413. package/dist/schema/issue_labels.js.map +1 -0
  414. package/dist/schema/issue_plan_decompositions.d.ts +284 -0
  415. package/dist/schema/issue_plan_decompositions.d.ts.map +1 -0
  416. package/dist/schema/issue_plan_decompositions.js +36 -0
  417. package/dist/schema/issue_plan_decompositions.js.map +1 -0
  418. package/dist/schema/issue_read_states.d.ts +127 -0
  419. package/dist/schema/issue_read_states.d.ts.map +1 -0
  420. package/dist/schema/issue_read_states.js +17 -0
  421. package/dist/schema/issue_read_states.js.map +1 -0
  422. package/dist/schema/issue_recovery_actions.d.ts +456 -0
  423. package/dist/schema/issue_recovery_actions.d.ts.map +1 -0
  424. package/dist/schema/issue_recovery_actions.js +44 -0
  425. package/dist/schema/issue_recovery_actions.js.map +1 -0
  426. package/dist/schema/issue_reference_mentions.d.ts +180 -0
  427. package/dist/schema/issue_reference_mentions.d.ts.map +1 -0
  428. package/dist/schema/issue_reference_mentions.js +23 -0
  429. package/dist/schema/issue_reference_mentions.js.map +1 -0
  430. package/dist/schema/issue_relations.d.ts +163 -0
  431. package/dist/schema/issue_relations.d.ts.map +1 -0
  432. package/dist/schema/issue_relations.js +21 -0
  433. package/dist/schema/issue_relations.js.map +1 -0
  434. package/dist/schema/issue_thread_interactions.d.ts +353 -0
  435. package/dist/schema/issue_thread_interactions.d.ts.map +1 -0
  436. package/dist/schema/issue_thread_interactions.js +38 -0
  437. package/dist/schema/issue_thread_interactions.js.map +1 -0
  438. package/dist/schema/issue_tree_hold_members.d.ts +280 -0
  439. package/dist/schema/issue_tree_hold_members.d.ts.map +1 -0
  440. package/dist/schema/issue_tree_hold_members.js +29 -0
  441. package/dist/schema/issue_tree_hold_members.js.map +1 -0
  442. package/dist/schema/issue_tree_holds.d.ts +352 -0
  443. package/dist/schema/issue_tree_holds.d.ts.map +1 -0
  444. package/dist/schema/issue_tree_holds.js +31 -0
  445. package/dist/schema/issue_tree_holds.js.map +1 -0
  446. package/dist/schema/issue_work_products.d.ts +350 -0
  447. package/dist/schema/issue_work_products.d.ts.map +1 -0
  448. package/dist/schema/issue_work_products.js +37 -0
  449. package/dist/schema/issue_work_products.js.map +1 -0
  450. package/dist/schema/issues.d.ts +781 -0
  451. package/dist/schema/issues.d.ts.map +1 -0
  452. package/dist/schema/issues.js +109 -0
  453. package/dist/schema/issues.js.map +1 -0
  454. package/dist/schema/join_requests.d.ts +384 -0
  455. package/dist/schema/join_requests.d.ts.map +1 -0
  456. package/dist/schema/join_requests.js +39 -0
  457. package/dist/schema/join_requests.js.map +1 -0
  458. package/dist/schema/labels.d.ts +110 -0
  459. package/dist/schema/labels.d.ts.map +1 -0
  460. package/dist/schema/labels.js +14 -0
  461. package/dist/schema/labels.js.map +1 -0
  462. package/dist/schema/operator_api_keys.d.ts +144 -0
  463. package/dist/schema/operator_api_keys.d.ts.map +1 -0
  464. package/dist/schema/operator_api_keys.js +16 -0
  465. package/dist/schema/operator_api_keys.js.map +1 -0
  466. package/dist/schema/plugin_config.d.ts +123 -0
  467. package/dist/schema/plugin_config.d.ts.map +1 -0
  468. package/dist/schema/plugin_config.js +26 -0
  469. package/dist/schema/plugin_config.js.map +1 -0
  470. package/dist/schema/plugin_database.d.ts +357 -0
  471. package/dist/schema/plugin_database.d.ts.map +1 -0
  472. package/dist/schema/plugin_database.js +51 -0
  473. package/dist/schema/plugin_database.js.map +1 -0
  474. package/dist/schema/plugin_entities.d.ts +213 -0
  475. package/dist/schema/plugin_entities.d.ts.map +1 -0
  476. package/dist/schema/plugin_entities.js +37 -0
  477. package/dist/schema/plugin_entities.js.map +1 -0
  478. package/dist/schema/plugin_jobs.d.ts +392 -0
  479. package/dist/schema/plugin_jobs.d.ts.map +1 -0
  480. package/dist/schema/plugin_jobs.js +83 -0
  481. package/dist/schema/plugin_jobs.js.map +1 -0
  482. package/dist/schema/plugin_logs.d.ts +125 -0
  483. package/dist/schema/plugin_logs.d.ts.map +1 -0
  484. package/dist/schema/plugin_logs.js +29 -0
  485. package/dist/schema/plugin_logs.js.map +1 -0
  486. package/dist/schema/plugin_managed_resources.d.ts +180 -0
  487. package/dist/schema/plugin_managed_resources.d.ts.map +1 -0
  488. package/dist/schema/plugin_managed_resources.js +25 -0
  489. package/dist/schema/plugin_managed_resources.js.map +1 -0
  490. package/dist/schema/plugin_squad_settings.d.ts +158 -0
  491. package/dist/schema/plugin_squad_settings.d.ts.map +1 -0
  492. package/dist/schema/plugin_squad_settings.js +34 -0
  493. package/dist/schema/plugin_squad_settings.js.map +1 -0
  494. package/dist/schema/plugin_state.d.ts +169 -0
  495. package/dist/schema/plugin_state.d.ts.map +1 -0
  496. package/dist/schema/plugin_state.js +68 -0
  497. package/dist/schema/plugin_state.js.map +1 -0
  498. package/dist/schema/plugin_webhooks.d.ts +239 -0
  499. package/dist/schema/plugin_webhooks.d.ts.map +1 -0
  500. package/dist/schema/plugin_webhooks.js +52 -0
  501. package/dist/schema/plugin_webhooks.js.map +1 -0
  502. package/dist/schema/plugins.d.ts +246 -0
  503. package/dist/schema/plugins.d.ts.map +1 -0
  504. package/dist/schema/plugins.js +31 -0
  505. package/dist/schema/plugins.js.map +1 -0
  506. package/dist/schema/principal_permission_grants.d.ts +163 -0
  507. package/dist/schema/principal_permission_grants.d.ts.map +1 -0
  508. package/dist/schema/principal_permission_grants.js +17 -0
  509. package/dist/schema/principal_permission_grants.js.map +1 -0
  510. package/dist/schema/project_goals.d.ts +93 -0
  511. package/dist/schema/project_goals.d.ts.map +1 -0
  512. package/dist/schema/project_goals.js +17 -0
  513. package/dist/schema/project_goals.js.map +1 -0
  514. package/dist/schema/project_memberships.d.ts +127 -0
  515. package/dist/schema/project_memberships.d.ts.map +1 -0
  516. package/dist/schema/project_memberships.js +17 -0
  517. package/dist/schema/project_memberships.js.map +1 -0
  518. package/dist/schema/project_workspaces.d.ts +333 -0
  519. package/dist/schema/project_workspaces.d.ts.map +1 -0
  520. package/dist/schema/project_workspaces.js +32 -0
  521. package/dist/schema/project_workspaces.js.map +1 -0
  522. package/dist/schema/projects.d.ts +285 -0
  523. package/dist/schema/projects.d.ts.map +1 -0
  524. package/dist/schema/projects.js +25 -0
  525. package/dist/schema/projects.js.map +1 -0
  526. package/dist/schema/routines.d.ts +1330 -0
  527. package/dist/schema/routines.d.ts.map +1 -0
  528. package/dist/schema/routines.js +113 -0
  529. package/dist/schema/routines.js.map +1 -0
  530. package/dist/schema/secret_access_events.d.ts +280 -0
  531. package/dist/schema/secret_access_events.d.ts.map +1 -0
  532. package/dist/schema/secret_access_events.js +30 -0
  533. package/dist/schema/secret_access_events.js.map +1 -0
  534. package/dist/schema/squad_logos.d.ts +93 -0
  535. package/dist/schema/squad_logos.d.ts.map +1 -0
  536. package/dist/schema/squad_logos.js +14 -0
  537. package/dist/schema/squad_logos.js.map +1 -0
  538. package/dist/schema/squad_memberships.d.ts +144 -0
  539. package/dist/schema/squad_memberships.d.ts.map +1 -0
  540. package/dist/schema/squad_memberships.js +17 -0
  541. package/dist/schema/squad_memberships.js.map +1 -0
  542. package/dist/schema/squad_secret_bindings.d.ts +195 -0
  543. package/dist/schema/squad_secret_bindings.d.ts.map +1 -0
  544. package/dist/schema/squad_secret_bindings.js +22 -0
  545. package/dist/schema/squad_secret_bindings.js.map +1 -0
  546. package/dist/schema/squad_secret_provider_configs.d.ts +284 -0
  547. package/dist/schema/squad_secret_provider_configs.d.ts.map +1 -0
  548. package/dist/schema/squad_secret_provider_configs.js +29 -0
  549. package/dist/schema/squad_secret_provider_configs.js.map +1 -0
  550. package/dist/schema/squad_secret_versions.d.ts +231 -0
  551. package/dist/schema/squad_secret_versions.d.ts.map +1 -0
  552. package/dist/schema/squad_secret_versions.js +24 -0
  553. package/dist/schema/squad_secret_versions.js.map +1 -0
  554. package/dist/schema/squad_secrets.d.ts +333 -0
  555. package/dist/schema/squad_secrets.d.ts.map +1 -0
  556. package/dist/schema/squad_secrets.js +32 -0
  557. package/dist/schema/squad_secrets.js.map +1 -0
  558. package/dist/schema/squad_skills.d.ts +335 -0
  559. package/dist/schema/squad_skills.d.ts.map +1 -0
  560. package/dist/schema/squad_skills.js +32 -0
  561. package/dist/schema/squad_skills.js.map +1 -0
  562. package/dist/schema/squad_user_sidebar_preferences.d.ts +112 -0
  563. package/dist/schema/squad_user_sidebar_preferences.d.ts.map +1 -0
  564. package/dist/schema/squad_user_sidebar_preferences.js +15 -0
  565. package/dist/schema/squad_user_sidebar_preferences.js.map +1 -0
  566. package/dist/schema/squads.d.ts +331 -0
  567. package/dist/schema/squads.d.ts.map +1 -0
  568. package/dist/schema/squads.js +31 -0
  569. package/dist/schema/squads.js.map +1 -0
  570. package/dist/schema/user_sidebar_preferences.d.ts +95 -0
  571. package/dist/schema/user_sidebar_preferences.d.ts.map +1 -0
  572. package/dist/schema/user_sidebar_preferences.js +11 -0
  573. package/dist/schema/user_sidebar_preferences.js.map +1 -0
  574. package/dist/schema/workspace_operations.d.ts +367 -0
  575. package/dist/schema/workspace_operations.d.ts.map +1 -0
  576. package/dist/schema/workspace_operations.js +35 -0
  577. package/dist/schema/workspace_operations.js.map +1 -0
  578. package/dist/schema/workspace_runtime_services.d.ts +469 -0
  579. package/dist/schema/workspace_runtime_services.d.ts.map +1 -0
  580. package/dist/schema/workspace_runtime_services.js +44 -0
  581. package/dist/schema/workspace_runtime_services.js.map +1 -0
  582. package/dist/seed.d.ts +2 -0
  583. package/dist/seed.d.ts.map +1 -0
  584. package/dist/seed.js +91 -0
  585. package/dist/seed.js.map +1 -0
  586. package/dist/test-embedded-postgres.d.ts +11 -0
  587. package/dist/test-embedded-postgres.d.ts.map +1 -0
  588. package/dist/test-embedded-postgres.js +138 -0
  589. package/dist/test-embedded-postgres.js.map +1 -0
  590. package/package.json +55 -0
@@ -0,0 +1,862 @@
1
+ import { createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, statSync, unlinkSync } from "node:fs";
2
+ import { basename, resolve } from "node:path";
3
+ import { createInterface } from "node:readline";
4
+ import { spawn } from "node:child_process";
5
+ import { open as openFile } from "node:fs/promises";
6
+ import { pipeline } from "node:stream/promises";
7
+ import { createGunzip, createGzip } from "node:zlib";
8
+ import postgres from "postgres";
9
+ const DEFAULT_BACKUP_WRITE_BUFFER_BYTES = 1024 * 1024;
10
+ const BACKUP_DATA_CURSOR_ROWS = 100;
11
+ const BACKUP_CLI_STDERR_BYTES = 64 * 1024;
12
+ const BACKUP_BREAKPOINT_DETECT_BYTES = 64 * 1024;
13
+ const STATEMENT_BREAKPOINT = "-- slaw statement breakpoint 69f6f3f1-42fd-46a6-bf17-d1d85f8f3900";
14
+ function sanitizeRestoreErrorMessage(error) {
15
+ if (error && typeof error === "object") {
16
+ const record = error;
17
+ const firstLine = typeof record.message === "string"
18
+ ? record.message.split(/\r?\n/, 1)[0]?.trim()
19
+ : "";
20
+ const detail = typeof record.detail === "string" ? record.detail.trim() : "";
21
+ const severity = typeof record.severity === "string" ? record.severity.trim() : "";
22
+ const message = firstLine || detail || (error instanceof Error ? error.message : String(error));
23
+ return severity ? `${severity}: ${message}` : message;
24
+ }
25
+ return error instanceof Error ? error.message : String(error);
26
+ }
27
+ function timestamp(date = new Date()) {
28
+ const pad = (n) => String(n).padStart(2, "0");
29
+ return `${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}-${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`;
30
+ }
31
+ /**
32
+ * ISO week key for grouping backups by calendar week (ISO 8601).
33
+ */
34
+ function isoWeekKey(date) {
35
+ const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
36
+ d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));
37
+ const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
38
+ const weekNo = Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7);
39
+ return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, "0")}`;
40
+ }
41
+ function monthKey(date) {
42
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}`;
43
+ }
44
+ /**
45
+ * Tiered backup pruning:
46
+ * - Daily tier: keep ALL backups from the last `dailyDays` days
47
+ * - Weekly tier: keep the NEWEST backup per calendar week for `weeklyWeeks` weeks
48
+ * - Monthly tier: keep the NEWEST backup per calendar month for `monthlyMonths` months
49
+ * - Everything else is deleted
50
+ */
51
+ function pruneOldBackups(backupDir, retention, filenamePrefix) {
52
+ if (!existsSync(backupDir))
53
+ return 0;
54
+ const now = Date.now();
55
+ const dailyCutoff = now - Math.max(1, retention.dailyDays) * 24 * 60 * 60 * 1000;
56
+ const weeklyCutoff = now - Math.max(1, retention.weeklyWeeks) * 7 * 24 * 60 * 60 * 1000;
57
+ const monthlyCutoff = now - Math.max(1, retention.monthlyMonths) * 30 * 24 * 60 * 60 * 1000;
58
+ const entries = [];
59
+ for (const name of readdirSync(backupDir)) {
60
+ if (!name.startsWith(`${filenamePrefix}-`))
61
+ continue;
62
+ if (!name.endsWith(".sql") && !name.endsWith(".sql.gz"))
63
+ continue;
64
+ const fullPath = resolve(backupDir, name);
65
+ const stat = statSync(fullPath);
66
+ entries.push({ name, fullPath, mtimeMs: stat.mtimeMs });
67
+ }
68
+ // Sort newest first so the first entry per week/month bucket is the one we keep
69
+ entries.sort((a, b) => b.mtimeMs - a.mtimeMs);
70
+ const keepWeekBuckets = new Set();
71
+ const keepMonthBuckets = new Set();
72
+ const toDelete = [];
73
+ for (const entry of entries) {
74
+ // Daily tier — keep everything within dailyDays
75
+ if (entry.mtimeMs >= dailyCutoff)
76
+ continue;
77
+ const date = new Date(entry.mtimeMs);
78
+ const week = isoWeekKey(date);
79
+ const month = monthKey(date);
80
+ // Weekly tier — keep newest per calendar week
81
+ if (entry.mtimeMs >= weeklyCutoff) {
82
+ if (keepWeekBuckets.has(week)) {
83
+ toDelete.push(entry.fullPath);
84
+ }
85
+ else {
86
+ keepWeekBuckets.add(week);
87
+ }
88
+ continue;
89
+ }
90
+ // Monthly tier — keep newest per calendar month
91
+ if (entry.mtimeMs >= monthlyCutoff) {
92
+ if (keepMonthBuckets.has(month)) {
93
+ toDelete.push(entry.fullPath);
94
+ }
95
+ else {
96
+ keepMonthBuckets.add(month);
97
+ }
98
+ continue;
99
+ }
100
+ // Beyond all retention tiers — delete
101
+ toDelete.push(entry.fullPath);
102
+ }
103
+ for (const filePath of toDelete) {
104
+ unlinkSync(filePath);
105
+ }
106
+ return toDelete.length;
107
+ }
108
+ function formatBackupSize(sizeBytes) {
109
+ if (sizeBytes < 1024)
110
+ return `${sizeBytes}B`;
111
+ if (sizeBytes < 1024 * 1024)
112
+ return `${(sizeBytes / 1024).toFixed(1)}K`;
113
+ return `${(sizeBytes / (1024 * 1024)).toFixed(1)}M`;
114
+ }
115
+ function formatSqlLiteral(value) {
116
+ const sanitized = value.replace(/\u0000/g, "");
117
+ let tag = "$slaw$";
118
+ while (sanitized.includes(tag)) {
119
+ tag = `$slaw_${Math.random().toString(36).slice(2, 8)}$`;
120
+ }
121
+ return `${tag}${sanitized}${tag}`;
122
+ }
123
+ function normalizeTableNameSet(values) {
124
+ return new Set((values ?? [])
125
+ .map(normalizeTableSelector)
126
+ .filter((value) => value.length > 0));
127
+ }
128
+ function normalizeTableSelector(value) {
129
+ const trimmed = value.trim();
130
+ if (trimmed.length === 0)
131
+ return "";
132
+ return trimmed.includes(".") ? trimmed : tableKey("public", trimmed);
133
+ }
134
+ function normalizeNullifyColumnMap(values) {
135
+ const out = new Map();
136
+ if (!values)
137
+ return out;
138
+ for (const [tableName, columns] of Object.entries(values)) {
139
+ const normalizedTable = normalizeTableSelector(tableName);
140
+ if (normalizedTable.length === 0)
141
+ continue;
142
+ const normalizedColumns = new Set(columns
143
+ .map((column) => column.trim())
144
+ .filter((column) => column.length > 0));
145
+ if (normalizedColumns.size > 0) {
146
+ out.set(normalizedTable, normalizedColumns);
147
+ }
148
+ }
149
+ return out;
150
+ }
151
+ function quoteIdentifier(value) {
152
+ return `"${value.replaceAll("\"", "\"\"")}"`;
153
+ }
154
+ function quoteQualifiedName(schemaName, objectName) {
155
+ return `${quoteIdentifier(schemaName)}.${quoteIdentifier(objectName)}`;
156
+ }
157
+ function tableKey(schemaName, tableName) {
158
+ return `${schemaName}.${tableName}`;
159
+ }
160
+ function nonSystemSchemaPredicate(identifier) {
161
+ // PostgreSQL reserves pg_ prefixes for system schemas, including temp/toast variants.
162
+ return `${identifier} <> 'information_schema'
163
+ AND ${identifier} NOT LIKE 'pg\\_%' ESCAPE '\\'`;
164
+ }
165
+ function hasBackupTransforms(opts) {
166
+ return (opts.excludeTables?.length ?? 0) > 0 ||
167
+ Object.keys(opts.nullifyColumns ?? {}).length > 0;
168
+ }
169
+ function formatPostgresArrayElement(value) {
170
+ if (value === null || value === undefined)
171
+ return "NULL";
172
+ if (Array.isArray(value))
173
+ return formatPostgresArrayLiteral(value);
174
+ const raw = value instanceof Date
175
+ ? value.toISOString()
176
+ : typeof value === "object"
177
+ ? JSON.stringify(value)
178
+ : String(value);
179
+ if (raw.length === 0 || /^null$/i.test(raw) || /[{}\s,"\\]/.test(raw)) {
180
+ return `"${raw.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
181
+ }
182
+ return raw;
183
+ }
184
+ function formatPostgresArrayLiteral(value) {
185
+ return `{${value.map(formatPostgresArrayElement).join(",")}}`;
186
+ }
187
+ function formatSqlValue(rawValue, columnName, nullifiedColumns, dataType) {
188
+ const val = columnName && nullifiedColumns.has(columnName) ? null : rawValue;
189
+ if (val === null || val === undefined)
190
+ return "NULL";
191
+ if (dataType === "json" || dataType === "jsonb") {
192
+ return formatSqlLiteral(JSON.stringify(val));
193
+ }
194
+ if (typeof val === "boolean")
195
+ return val ? "true" : "false";
196
+ if (typeof val === "number")
197
+ return String(val);
198
+ if (val instanceof Date)
199
+ return formatSqlLiteral(val.toISOString());
200
+ if (Array.isArray(val))
201
+ return formatSqlLiteral(formatPostgresArrayLiteral(val));
202
+ if (typeof val === "object")
203
+ return formatSqlLiteral(JSON.stringify(val));
204
+ return formatSqlLiteral(String(val));
205
+ }
206
+ function appendCapturedStderr(previous, chunk) {
207
+ const next = previous + (Buffer.isBuffer(chunk) ? chunk.toString("utf8") : chunk);
208
+ if (Buffer.byteLength(next, "utf8") <= BACKUP_CLI_STDERR_BYTES)
209
+ return next;
210
+ return Buffer.from(next, "utf8").subarray(-BACKUP_CLI_STDERR_BYTES).toString("utf8");
211
+ }
212
+ async function waitForChildExit(child, label) {
213
+ let stderr = "";
214
+ child.stderr?.on("data", (chunk) => {
215
+ stderr = appendCapturedStderr(stderr, chunk);
216
+ });
217
+ const result = await new Promise((resolve, reject) => {
218
+ child.once("error", reject);
219
+ child.once("exit", (code, signal) => resolve({ code, signal }));
220
+ });
221
+ if (result.signal) {
222
+ throw new Error(`${label} exited via ${result.signal}${stderr.trim() ? `: ${stderr.trim()}` : ""}`);
223
+ }
224
+ if (result.code !== 0) {
225
+ throw new Error(`${label} failed with exit code ${result.code ?? "unknown"}${stderr.trim() ? `: ${stderr.trim()}` : ""}`);
226
+ }
227
+ }
228
+ async function runPgDumpBackup(opts) {
229
+ const pgDumpBin = process.env.SLAW_PG_DUMP_PATH || "pg_dump";
230
+ const child = spawn(pgDumpBin, [
231
+ `--dbname=${opts.connectionString}`,
232
+ "--format=plain",
233
+ "--clean",
234
+ "--if-exists",
235
+ "--no-owner",
236
+ "--no-privileges",
237
+ ], {
238
+ stdio: ["ignore", "pipe", "pipe"],
239
+ env: {
240
+ ...process.env,
241
+ PGCONNECT_TIMEOUT: String(opts.connectTimeout),
242
+ },
243
+ });
244
+ if (!child.stdout) {
245
+ throw new Error("pg_dump did not expose stdout");
246
+ }
247
+ await Promise.all([
248
+ pipeline(child.stdout, createGzip(), createWriteStream(opts.backupFile)),
249
+ waitForChildExit(child, pgDumpBin),
250
+ ]);
251
+ }
252
+ async function restoreWithPsql(opts, connectTimeout) {
253
+ const psqlBin = process.env.SLAW_PSQL_PATH || "psql";
254
+ const child = spawn(psqlBin, [
255
+ `--dbname=${opts.connectionString}`,
256
+ "--set=ON_ERROR_STOP=1",
257
+ "--quiet",
258
+ "--no-psqlrc",
259
+ ], {
260
+ stdio: ["pipe", "ignore", "pipe"],
261
+ env: {
262
+ ...process.env,
263
+ PGCONNECT_TIMEOUT: String(connectTimeout),
264
+ },
265
+ });
266
+ if (!child.stdin) {
267
+ throw new Error("psql did not expose stdin");
268
+ }
269
+ const input = opts.backupFile.endsWith(".gz")
270
+ ? createReadStream(opts.backupFile).pipe(createGunzip())
271
+ : createReadStream(opts.backupFile);
272
+ await Promise.all([
273
+ pipeline(input, child.stdin),
274
+ waitForChildExit(child, psqlBin),
275
+ ]);
276
+ }
277
+ async function hasStatementBreakpoints(backupFile) {
278
+ const raw = createReadStream(backupFile);
279
+ const stream = backupFile.endsWith(".gz") ? raw.pipe(createGunzip()) : raw;
280
+ let text = "";
281
+ try {
282
+ for await (const chunk of stream) {
283
+ text += Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk);
284
+ if (text.includes(STATEMENT_BREAKPOINT))
285
+ return true;
286
+ if (Buffer.byteLength(text, "utf8") >= BACKUP_BREAKPOINT_DETECT_BYTES)
287
+ return false;
288
+ }
289
+ return text.includes(STATEMENT_BREAKPOINT);
290
+ }
291
+ finally {
292
+ stream.destroy();
293
+ raw.destroy();
294
+ }
295
+ }
296
+ async function* readRestoreStatements(backupFile) {
297
+ const raw = createReadStream(backupFile);
298
+ const stream = backupFile.endsWith(".gz") ? raw.pipe(createGunzip()) : raw;
299
+ stream.setEncoding("utf8");
300
+ const reader = createInterface({
301
+ input: stream,
302
+ crlfDelay: Infinity,
303
+ });
304
+ let statementLines = [];
305
+ const flushStatement = () => {
306
+ const statement = statementLines.join("\n").trim();
307
+ statementLines = [];
308
+ return statement;
309
+ };
310
+ try {
311
+ for await (const line of reader) {
312
+ if (line === STATEMENT_BREAKPOINT) {
313
+ const statement = flushStatement();
314
+ if (statement.length > 0) {
315
+ yield statement;
316
+ }
317
+ continue;
318
+ }
319
+ statementLines.push(line);
320
+ }
321
+ const trailingStatement = flushStatement();
322
+ if (trailingStatement.length > 0) {
323
+ yield trailingStatement;
324
+ }
325
+ }
326
+ finally {
327
+ reader.close();
328
+ stream.destroy();
329
+ raw.destroy();
330
+ }
331
+ }
332
+ export function createBufferedTextFileWriter(filePath, maxBufferedBytes = DEFAULT_BACKUP_WRITE_BUFFER_BYTES) {
333
+ const filePromise = openFile(filePath, "w");
334
+ const flushThreshold = Math.max(1, Math.trunc(maxBufferedBytes));
335
+ let bufferedLines = [];
336
+ let bufferedBytes = 0;
337
+ let firstChunk = true;
338
+ let closed = false;
339
+ let pendingWrite = Promise.resolve();
340
+ const writeChunk = async (chunk) => {
341
+ const file = await filePromise;
342
+ if (typeof chunk === "string") {
343
+ await file.write(chunk, null, "utf8");
344
+ }
345
+ else {
346
+ await file.write(chunk);
347
+ }
348
+ };
349
+ const flushBufferedLines = () => {
350
+ if (bufferedLines.length === 0)
351
+ return;
352
+ const linesToWrite = bufferedLines;
353
+ bufferedLines = [];
354
+ bufferedBytes = 0;
355
+ const chunkBody = linesToWrite.join("\n");
356
+ const chunk = firstChunk ? chunkBody : `\n${chunkBody}`;
357
+ firstChunk = false;
358
+ pendingWrite = pendingWrite.then(() => writeChunk(chunk));
359
+ };
360
+ return {
361
+ emit(line) {
362
+ if (closed) {
363
+ throw new Error(`Cannot write to closed backup file: ${filePath}`);
364
+ }
365
+ bufferedLines.push(line);
366
+ bufferedBytes += Buffer.byteLength(line, "utf8") + 1;
367
+ if (bufferedBytes >= flushThreshold) {
368
+ flushBufferedLines();
369
+ }
370
+ },
371
+ async drain() {
372
+ if (closed) {
373
+ throw new Error(`Cannot drain closed backup file: ${filePath}`);
374
+ }
375
+ flushBufferedLines();
376
+ await pendingWrite;
377
+ },
378
+ async writeRaw(chunk) {
379
+ if (closed) {
380
+ throw new Error(`Cannot write to closed backup file: ${filePath}`);
381
+ }
382
+ flushBufferedLines();
383
+ firstChunk = false;
384
+ pendingWrite = pendingWrite.then(() => writeChunk(chunk));
385
+ await pendingWrite;
386
+ },
387
+ async close() {
388
+ if (closed)
389
+ return;
390
+ closed = true;
391
+ flushBufferedLines();
392
+ await pendingWrite;
393
+ const file = await filePromise;
394
+ await file.close();
395
+ },
396
+ async abort() {
397
+ if (closed)
398
+ return;
399
+ closed = true;
400
+ bufferedLines = [];
401
+ bufferedBytes = 0;
402
+ await pendingWrite.catch(() => { });
403
+ await filePromise.then((file) => file.close()).catch(() => { });
404
+ if (existsSync(filePath)) {
405
+ try {
406
+ unlinkSync(filePath);
407
+ }
408
+ catch {
409
+ // Preserve the original backup failure if temporary file cleanup also fails.
410
+ }
411
+ }
412
+ },
413
+ };
414
+ }
415
+ export async function runDatabaseBackup(opts) {
416
+ const filenamePrefix = opts.filenamePrefix ?? "slaw";
417
+ const retention = opts.retention;
418
+ const connectTimeout = Math.max(1, Math.trunc(opts.connectTimeoutSeconds ?? 5));
419
+ const backupEngine = opts.backupEngine ?? "auto";
420
+ const canUsePgDump = !hasBackupTransforms(opts);
421
+ const excludedTableNames = normalizeTableNameSet(opts.excludeTables);
422
+ const nullifiedColumnsByTable = normalizeNullifyColumnMap(opts.nullifyColumns);
423
+ let sql = postgres(opts.connectionString, { max: 1, connect_timeout: connectTimeout });
424
+ let sqlClosed = false;
425
+ const closeSql = async () => {
426
+ if (sqlClosed)
427
+ return;
428
+ sqlClosed = true;
429
+ await sql.end();
430
+ };
431
+ mkdirSync(opts.backupDir, { recursive: true });
432
+ const sqlFile = resolve(opts.backupDir, `${filenamePrefix}-${timestamp()}.sql`);
433
+ const backupFile = `${sqlFile}.gz`;
434
+ const writer = createBufferedTextFileWriter(sqlFile);
435
+ try {
436
+ if (backupEngine === "pg_dump" || (backupEngine === "auto" && canUsePgDump)) {
437
+ await sql `SELECT 1`;
438
+ try {
439
+ await closeSql();
440
+ await runPgDumpBackup({
441
+ connectionString: opts.connectionString,
442
+ backupFile,
443
+ connectTimeout,
444
+ });
445
+ await writer.abort();
446
+ const sizeBytes = statSync(backupFile).size;
447
+ const prunedCount = pruneOldBackups(opts.backupDir, retention, filenamePrefix);
448
+ return {
449
+ backupFile,
450
+ sizeBytes,
451
+ prunedCount,
452
+ };
453
+ }
454
+ catch (error) {
455
+ if (existsSync(backupFile)) {
456
+ try {
457
+ unlinkSync(backupFile);
458
+ }
459
+ catch { /* ignore */ }
460
+ }
461
+ if (backupEngine === "pg_dump") {
462
+ throw error;
463
+ }
464
+ sql = postgres(opts.connectionString, { max: 1, connect_timeout: connectTimeout });
465
+ sqlClosed = false;
466
+ }
467
+ }
468
+ await sql `SELECT 1`;
469
+ const emit = (line) => writer.emit(line);
470
+ const emitStatement = (statement) => {
471
+ emit(statement);
472
+ emit(STATEMENT_BREAKPOINT);
473
+ };
474
+ const emitStatementBoundary = () => {
475
+ emit(STATEMENT_BREAKPOINT);
476
+ };
477
+ emit("-- Slaw database backup");
478
+ emit(`-- Created: ${new Date().toISOString()}`);
479
+ emit("");
480
+ emitStatement("BEGIN;");
481
+ emitStatement("SET LOCAL session_replication_role = replica;");
482
+ emitStatement("SET LOCAL client_min_messages = warning;");
483
+ emit("");
484
+ const allTables = await sql `
485
+ SELECT table_schema AS schema_name, table_name AS tablename
486
+ FROM information_schema.tables
487
+ WHERE table_type = 'BASE TABLE'
488
+ AND ${sql.unsafe(nonSystemSchemaPredicate("table_schema"))}
489
+ ORDER BY table_schema, table_name
490
+ `;
491
+ const tables = allTables;
492
+ const includedTableNames = new Set(tables.map(({ schema_name, tablename }) => tableKey(schema_name, tablename)));
493
+ const includedSchemas = new Set(tables.map(({ schema_name }) => schema_name));
494
+ // Get all enums
495
+ const enums = await sql `
496
+ SELECT n.nspname AS schema_name, t.typname, array_agg(e.enumlabel ORDER BY e.enumsortorder) AS labels
497
+ FROM pg_type t
498
+ JOIN pg_enum e ON t.oid = e.enumtypid
499
+ JOIN pg_namespace n ON t.typnamespace = n.oid
500
+ WHERE ${sql.unsafe(nonSystemSchemaPredicate("n.nspname"))}
501
+ GROUP BY n.nspname, t.typname
502
+ ORDER BY n.nspname, t.typname
503
+ `;
504
+ for (const e of enums)
505
+ includedSchemas.add(e.schema_name);
506
+ const allSequences = await sql `
507
+ SELECT
508
+ s.sequence_schema,
509
+ s.sequence_name,
510
+ s.data_type,
511
+ s.start_value,
512
+ s.minimum_value,
513
+ s.maximum_value,
514
+ s.increment,
515
+ s.cycle_option,
516
+ tblns.nspname AS owner_schema,
517
+ tbl.relname AS owner_table,
518
+ attr.attname AS owner_column
519
+ FROM information_schema.sequences s
520
+ JOIN pg_class seq ON seq.relname = s.sequence_name
521
+ JOIN pg_namespace n ON n.oid = seq.relnamespace AND n.nspname = s.sequence_schema
522
+ LEFT JOIN pg_depend dep ON dep.objid = seq.oid AND dep.deptype = 'a'
523
+ LEFT JOIN pg_class tbl ON tbl.oid = dep.refobjid
524
+ LEFT JOIN pg_namespace tblns ON tblns.oid = tbl.relnamespace
525
+ LEFT JOIN pg_attribute attr ON attr.attrelid = tbl.oid AND attr.attnum = dep.refobjsubid
526
+ WHERE ${sql.unsafe(nonSystemSchemaPredicate("s.sequence_schema"))}
527
+ ORDER BY s.sequence_schema, s.sequence_name
528
+ `;
529
+ const sequences = allSequences.filter((seq) => !seq.owner_table || includedTableNames.has(tableKey(seq.owner_schema ?? "public", seq.owner_table)));
530
+ const schemas = new Set(includedSchemas);
531
+ for (const seq of sequences)
532
+ schemas.add(seq.sequence_schema);
533
+ const extraSchemas = [...schemas].filter((schemaName) => schemaName !== "public");
534
+ if (extraSchemas.length > 0) {
535
+ emit("-- Schemas");
536
+ for (const schemaName of extraSchemas) {
537
+ emitStatement(`CREATE SCHEMA IF NOT EXISTS ${quoteIdentifier(schemaName)};`);
538
+ }
539
+ emit("");
540
+ }
541
+ for (const e of enums) {
542
+ const labels = e.labels.map((l) => `'${l.replace(/'/g, "''")}'`).join(", ");
543
+ emitStatement(`CREATE TYPE ${quoteQualifiedName(e.schema_name, e.typname)} AS ENUM (${labels});`);
544
+ }
545
+ if (enums.length > 0)
546
+ emit("");
547
+ const extensions = await sql `
548
+ SELECT
549
+ e.extname AS extension_name,
550
+ n.nspname AS schema_name
551
+ FROM pg_extension e
552
+ JOIN pg_namespace n ON n.oid = e.extnamespace
553
+ WHERE e.extname <> 'plpgsql'
554
+ ORDER BY e.extname
555
+ `;
556
+ if (extensions.length > 0) {
557
+ emit("-- Extensions");
558
+ for (const extension of extensions) {
559
+ emitStatement(`CREATE EXTENSION IF NOT EXISTS ${quoteIdentifier(extension.extension_name)} WITH SCHEMA ${quoteIdentifier(extension.schema_name)};`);
560
+ }
561
+ emit("");
562
+ }
563
+ if (sequences.length > 0) {
564
+ emit("-- Sequences");
565
+ for (const seq of sequences) {
566
+ const qualifiedSequenceName = quoteQualifiedName(seq.sequence_schema, seq.sequence_name);
567
+ emitStatement(`DROP SEQUENCE IF EXISTS ${qualifiedSequenceName} CASCADE;`);
568
+ emitStatement(`CREATE SEQUENCE ${qualifiedSequenceName} AS ${seq.data_type} INCREMENT BY ${seq.increment} MINVALUE ${seq.minimum_value} MAXVALUE ${seq.maximum_value} START WITH ${seq.start_value}${seq.cycle_option === "YES" ? " CYCLE" : " NO CYCLE"};`);
569
+ }
570
+ emit("");
571
+ }
572
+ // Get full CREATE TABLE DDL via column info
573
+ for (const { schema_name, tablename } of tables) {
574
+ const qualifiedTableName = quoteQualifiedName(schema_name, tablename);
575
+ const columns = await sql `
576
+ SELECT column_name, data_type, udt_schema, udt_name, is_nullable, column_default,
577
+ character_maximum_length, numeric_precision, numeric_scale
578
+ FROM information_schema.columns
579
+ WHERE table_schema = ${schema_name} AND table_name = ${tablename}
580
+ ORDER BY ordinal_position
581
+ `;
582
+ emit(`-- Table: ${schema_name}.${tablename}`);
583
+ emitStatement(`DROP TABLE IF EXISTS ${qualifiedTableName} CASCADE;`);
584
+ const colDefs = [];
585
+ for (const col of columns) {
586
+ let typeStr;
587
+ if (col.data_type === "USER-DEFINED") {
588
+ typeStr = quoteQualifiedName(col.udt_schema, col.udt_name);
589
+ }
590
+ else if (col.data_type === "ARRAY") {
591
+ const elementType = col.udt_name.replace(/^_/, "");
592
+ typeStr = col.udt_schema === "pg_catalog"
593
+ ? `${elementType}[]`
594
+ : `${quoteQualifiedName(col.udt_schema, elementType)}[]`;
595
+ }
596
+ else if (col.data_type === "character varying") {
597
+ typeStr = col.character_maximum_length
598
+ ? `varchar(${col.character_maximum_length})`
599
+ : "varchar";
600
+ }
601
+ else if (col.data_type === "numeric" && col.numeric_precision != null) {
602
+ typeStr =
603
+ col.numeric_scale != null
604
+ ? `numeric(${col.numeric_precision}, ${col.numeric_scale})`
605
+ : `numeric(${col.numeric_precision})`;
606
+ }
607
+ else {
608
+ typeStr = col.data_type;
609
+ }
610
+ let def = ` "${col.column_name}" ${typeStr}`;
611
+ if (col.column_default != null)
612
+ def += ` DEFAULT ${col.column_default}`;
613
+ if (col.is_nullable === "NO")
614
+ def += " NOT NULL";
615
+ colDefs.push(def);
616
+ }
617
+ // Primary key
618
+ const pk = await sql `
619
+ SELECT c.conname AS constraint_name,
620
+ array_agg(a.attname ORDER BY array_position(c.conkey, a.attnum)) AS column_names
621
+ FROM pg_constraint c
622
+ JOIN pg_class t ON t.oid = c.conrelid
623
+ JOIN pg_namespace n ON n.oid = t.relnamespace
624
+ JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey)
625
+ WHERE n.nspname = ${schema_name} AND t.relname = ${tablename} AND c.contype = 'p'
626
+ GROUP BY c.conname
627
+ `;
628
+ for (const p of pk) {
629
+ const cols = p.column_names.map((c) => `"${c}"`).join(", ");
630
+ colDefs.push(` CONSTRAINT "${p.constraint_name}" PRIMARY KEY (${cols})`);
631
+ }
632
+ emit(`CREATE TABLE ${qualifiedTableName} (`);
633
+ emit(colDefs.join(",\n"));
634
+ emit(");");
635
+ emitStatementBoundary();
636
+ emit("");
637
+ }
638
+ const ownedSequences = sequences.filter((seq) => seq.owner_table && seq.owner_column);
639
+ if (ownedSequences.length > 0) {
640
+ emit("-- Sequence ownership");
641
+ for (const seq of ownedSequences) {
642
+ emitStatement(`ALTER SEQUENCE ${quoteQualifiedName(seq.sequence_schema, seq.sequence_name)} OWNED BY ${quoteQualifiedName(seq.owner_schema ?? "public", seq.owner_table)}.${quoteIdentifier(seq.owner_column)};`);
643
+ }
644
+ emit("");
645
+ }
646
+ // Unique constraints must exist before foreign keys that reference them.
647
+ const allUniqueConstraints = await sql `
648
+ SELECT c.conname AS constraint_name,
649
+ n.nspname AS schema_name,
650
+ t.relname AS tablename,
651
+ array_agg(a.attname ORDER BY array_position(c.conkey, a.attnum)) AS column_names
652
+ FROM pg_constraint c
653
+ JOIN pg_class t ON t.oid = c.conrelid
654
+ JOIN pg_namespace n ON n.oid = t.relnamespace
655
+ JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey)
656
+ WHERE c.contype = 'u'
657
+ AND ${sql.unsafe(nonSystemSchemaPredicate("n.nspname"))}
658
+ GROUP BY c.conname, n.nspname, t.relname
659
+ ORDER BY n.nspname, t.relname, c.conname
660
+ `;
661
+ const uniques = allUniqueConstraints.filter((entry) => includedTableNames.has(tableKey(entry.schema_name, entry.tablename)));
662
+ if (uniques.length > 0) {
663
+ emit("-- Unique constraints");
664
+ for (const u of uniques) {
665
+ const cols = u.column_names.map((c) => `"${c}"`).join(", ");
666
+ emitStatement(`ALTER TABLE ${quoteQualifiedName(u.schema_name, u.tablename)} ADD CONSTRAINT "${u.constraint_name}" UNIQUE (${cols});`);
667
+ }
668
+ emit("");
669
+ }
670
+ // Foreign keys (after all tables and referenced unique constraints are created)
671
+ const allForeignKeys = await sql `
672
+ SELECT
673
+ c.conname AS constraint_name,
674
+ srcn.nspname AS source_schema,
675
+ src.relname AS source_table,
676
+ array_agg(sa.attname ORDER BY key_columns.ordinal_position) AS source_columns,
677
+ tgtn.nspname AS target_schema,
678
+ tgt.relname AS target_table,
679
+ array_agg(ta.attname ORDER BY key_columns.ordinal_position) AS target_columns,
680
+ CASE c.confupdtype WHEN 'a' THEN 'NO ACTION' WHEN 'r' THEN 'RESTRICT' WHEN 'c' THEN 'CASCADE' WHEN 'n' THEN 'SET NULL' WHEN 'd' THEN 'SET DEFAULT' END AS update_rule,
681
+ CASE c.confdeltype WHEN 'a' THEN 'NO ACTION' WHEN 'r' THEN 'RESTRICT' WHEN 'c' THEN 'CASCADE' WHEN 'n' THEN 'SET NULL' WHEN 'd' THEN 'SET DEFAULT' END AS delete_rule
682
+ FROM pg_constraint c
683
+ JOIN pg_class src ON src.oid = c.conrelid
684
+ JOIN pg_namespace srcn ON srcn.oid = src.relnamespace
685
+ JOIN pg_class tgt ON tgt.oid = c.confrelid
686
+ JOIN pg_namespace tgtn ON tgtn.oid = tgt.relnamespace
687
+ JOIN LATERAL unnest(c.conkey, c.confkey) WITH ORDINALITY AS key_columns(source_attnum, target_attnum, ordinal_position) ON true
688
+ JOIN pg_attribute sa ON sa.attrelid = src.oid AND sa.attnum = key_columns.source_attnum
689
+ JOIN pg_attribute ta ON ta.attrelid = tgt.oid AND ta.attnum = key_columns.target_attnum
690
+ WHERE c.contype = 'f'
691
+ AND ${sql.unsafe(nonSystemSchemaPredicate("srcn.nspname"))}
692
+ GROUP BY c.conname, srcn.nspname, src.relname, tgtn.nspname, tgt.relname, c.confupdtype, c.confdeltype
693
+ ORDER BY srcn.nspname, src.relname, c.conname
694
+ `;
695
+ const fks = allForeignKeys.filter((fk) => includedTableNames.has(tableKey(fk.source_schema, fk.source_table))
696
+ && includedTableNames.has(tableKey(fk.target_schema, fk.target_table)));
697
+ if (fks.length > 0) {
698
+ emit("-- Foreign keys");
699
+ for (const fk of fks) {
700
+ const srcCols = fk.source_columns.map((c) => `"${c}"`).join(", ");
701
+ const tgtCols = fk.target_columns.map((c) => `"${c}"`).join(", ");
702
+ emitStatement(`ALTER TABLE ${quoteQualifiedName(fk.source_schema, fk.source_table)} ADD CONSTRAINT "${fk.constraint_name}" FOREIGN KEY (${srcCols}) REFERENCES ${quoteQualifiedName(fk.target_schema, fk.target_table)} (${tgtCols}) ON UPDATE ${fk.update_rule} ON DELETE ${fk.delete_rule};`);
703
+ }
704
+ emit("");
705
+ }
706
+ // Indexes (non-primary, non-unique-constraint)
707
+ const allIndexes = await sql `
708
+ SELECT schemaname AS schema_name, tablename, indexdef
709
+ FROM pg_indexes
710
+ WHERE ${sql.unsafe(nonSystemSchemaPredicate("schemaname"))}
711
+ AND indexname NOT IN (
712
+ SELECT conname FROM pg_constraint c
713
+ JOIN pg_namespace n ON n.oid = c.connamespace
714
+ WHERE n.nspname = pg_indexes.schemaname
715
+ )
716
+ ORDER BY schemaname, tablename, indexname
717
+ `;
718
+ const indexes = allIndexes.filter((entry) => includedTableNames.has(tableKey(entry.schema_name, entry.tablename)));
719
+ if (indexes.length > 0) {
720
+ emit("-- Indexes");
721
+ for (const idx of indexes) {
722
+ emitStatement(`${idx.indexdef};`);
723
+ }
724
+ emit("");
725
+ }
726
+ // Dump data for each table
727
+ for (const { schema_name, tablename } of tables) {
728
+ const currentTableKey = tableKey(schema_name, tablename);
729
+ const qualifiedTableName = quoteQualifiedName(schema_name, tablename);
730
+ const count = await sql.unsafe(`SELECT count(*)::int AS n FROM ${qualifiedTableName}`);
731
+ if (excludedTableNames.has(currentTableKey) || (count[0]?.n ?? 0) === 0)
732
+ continue;
733
+ // Get column info for this table
734
+ const cols = await sql `
735
+ SELECT column_name, data_type
736
+ FROM information_schema.columns
737
+ WHERE table_schema = ${schema_name} AND table_name = ${tablename}
738
+ ORDER BY ordinal_position
739
+ `;
740
+ const colNames = cols.map((c) => `"${c.column_name}"`).join(", ");
741
+ emit(`-- Data for: ${schema_name}.${tablename} (${count[0].n} rows)`);
742
+ const nullifiedColumns = nullifiedColumnsByTable.get(currentTableKey) ?? new Set();
743
+ if (backupEngine !== "javascript" && nullifiedColumns.size === 0) {
744
+ emit(`COPY ${qualifiedTableName} (${colNames}) FROM stdin;`);
745
+ await writer.writeRaw("\n");
746
+ const copySql = postgres(opts.connectionString, { max: 1, connect_timeout: connectTimeout });
747
+ try {
748
+ const copyStream = await copySql
749
+ .unsafe(`COPY ${qualifiedTableName} (${colNames}) TO STDOUT`)
750
+ .readable();
751
+ for await (const chunk of copyStream) {
752
+ await writer.writeRaw(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
753
+ }
754
+ }
755
+ finally {
756
+ await copySql.end();
757
+ }
758
+ await writer.writeRaw("\\.\n");
759
+ emitStatementBoundary();
760
+ emit("");
761
+ continue;
762
+ }
763
+ const rowCursor = sql
764
+ .unsafe(`SELECT * FROM ${qualifiedTableName}`)
765
+ .values()
766
+ .cursor(BACKUP_DATA_CURSOR_ROWS);
767
+ for await (const rows of rowCursor) {
768
+ for (const row of rows) {
769
+ const values = row.map((rawValue, index) => formatSqlValue(rawValue, cols[index]?.column_name, nullifiedColumns, cols[index]?.data_type));
770
+ emitStatement(`INSERT INTO ${qualifiedTableName} (${colNames}) VALUES (${values.join(", ")});`);
771
+ }
772
+ await writer.drain();
773
+ }
774
+ emit("");
775
+ }
776
+ // Sequence values
777
+ if (sequences.length > 0) {
778
+ emit("-- Sequence values");
779
+ for (const seq of sequences) {
780
+ const qualifiedSequenceName = quoteQualifiedName(seq.sequence_schema, seq.sequence_name);
781
+ const val = await sql.unsafe(`SELECT last_value::text, is_called FROM ${qualifiedSequenceName}`);
782
+ const skipSequenceValue = seq.owner_table !== null
783
+ && excludedTableNames.has(seq.owner_table);
784
+ if (val[0] && !skipSequenceValue) {
785
+ emitStatement(`SELECT setval('${qualifiedSequenceName.replaceAll("'", "''")}', ${val[0].last_value}, ${val[0].is_called ? "true" : "false"});`);
786
+ }
787
+ }
788
+ emit("");
789
+ }
790
+ emitStatement("COMMIT;");
791
+ emit("");
792
+ await writer.close();
793
+ // Compress the SQL file with gzip
794
+ const sqlReadStream = createReadStream(sqlFile);
795
+ const gzWriteStream = createWriteStream(backupFile);
796
+ await pipeline(sqlReadStream, createGzip(), gzWriteStream);
797
+ unlinkSync(sqlFile);
798
+ const sizeBytes = statSync(backupFile).size;
799
+ const prunedCount = pruneOldBackups(opts.backupDir, retention, filenamePrefix);
800
+ return {
801
+ backupFile,
802
+ sizeBytes,
803
+ prunedCount,
804
+ };
805
+ }
806
+ catch (error) {
807
+ await writer.abort();
808
+ if (existsSync(backupFile)) {
809
+ try {
810
+ unlinkSync(backupFile);
811
+ }
812
+ catch { /* ignore */ }
813
+ }
814
+ if (existsSync(sqlFile)) {
815
+ try {
816
+ unlinkSync(sqlFile);
817
+ }
818
+ catch { /* ignore */ }
819
+ }
820
+ throw error;
821
+ }
822
+ finally {
823
+ await closeSql();
824
+ }
825
+ }
826
+ export async function runDatabaseRestore(opts) {
827
+ const connectTimeout = Math.max(1, Math.trunc(opts.connectTimeoutSeconds ?? 5));
828
+ try {
829
+ await restoreWithPsql(opts, connectTimeout);
830
+ return;
831
+ }
832
+ catch (error) {
833
+ if (!(await hasStatementBreakpoints(opts.backupFile))) {
834
+ throw new Error(`Failed to restore ${basename(opts.backupFile)} with psql: ${sanitizeRestoreErrorMessage(error)}`);
835
+ }
836
+ }
837
+ const sql = postgres(opts.connectionString, { max: 1, connect_timeout: connectTimeout });
838
+ try {
839
+ await sql `SELECT 1`;
840
+ for await (const statement of readRestoreStatements(opts.backupFile)) {
841
+ await sql.unsafe(statement).execute();
842
+ }
843
+ }
844
+ catch (error) {
845
+ const statementPreview = typeof error === "object" && error !== null && typeof error.query === "string"
846
+ ? String(error.query)
847
+ .split(/\r?\n/)
848
+ .map((line) => line.trim())
849
+ .find((line) => line.length > 0 && !line.startsWith("--"))
850
+ : null;
851
+ throw new Error(`Failed to restore ${basename(opts.backupFile)}: ${sanitizeRestoreErrorMessage(error)}${statementPreview ? ` [statement: ${statementPreview.slice(0, 120)}]` : ""}`);
852
+ }
853
+ finally {
854
+ await sql.end();
855
+ }
856
+ }
857
+ export function formatDatabaseBackupResult(result) {
858
+ const size = formatBackupSize(result.sizeBytes);
859
+ const pruned = result.prunedCount > 0 ? `; pruned ${result.prunedCount} old backup(s)` : "";
860
+ return `${result.backupFile} (${size}${pruned})`;
861
+ }
862
+ //# sourceMappingURL=backup-lib.js.map