ekwo-os 0.4.1

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 (361) hide show
  1. package/README.md +873 -0
  2. package/dist/args.d.ts +57 -0
  3. package/dist/args.d.ts.map +1 -0
  4. package/dist/args.js +134 -0
  5. package/dist/args.js.map +1 -0
  6. package/dist/assets/expected-objects.json +9432 -0
  7. package/dist/assets/migrations/20260911120000_core_companies.sql +260 -0
  8. package/dist/assets/migrations/20260911120100_accounts_journals.sql +211 -0
  9. package/dist/assets/migrations/20260911120200_contacts.sql +90 -0
  10. package/dist/assets/migrations/20260911120300_taxes.sql +146 -0
  11. package/dist/assets/migrations/20260911120400_entries.sql +338 -0
  12. package/dist/assets/migrations/20260911120500_documents.sql +279 -0
  13. package/dist/assets/migrations/20260911120600_payments_reconciliation.sql +251 -0
  14. package/dist/assets/migrations/20260911120700_bank.sql +178 -0
  15. package/dist/assets/migrations/20260911120800_analytics_attachments.sql +128 -0
  16. package/dist/assets/migrations/20260911120900_post_document.sql +279 -0
  17. package/dist/assets/migrations/20260911121000_reporting.sql +235 -0
  18. package/dist/assets/migrations/20260911121100_country_templates.sql +226 -0
  19. package/dist/assets/migrations/20260911121200_fec.sql +71 -0
  20. package/dist/assets/migrations/20260911130000_instance.sql +77 -0
  21. package/dist/assets/migrations/20260911130100_instance_members.sql +224 -0
  22. package/dist/assets/migrations/20260911140000_instance_admins.sql +112 -0
  23. package/dist/assets/migrations/20260911160000_tax_posting_templates_unique.sql +17 -0
  24. package/dist/assets/migrations/20260911170000_document_amount_paid.sql +82 -0
  25. package/dist/assets/migrations/20260911173000_post_payment.sql +122 -0
  26. package/dist/assets/migrations/20260911173100_sequence_counters_under_rls.sql +84 -0
  27. package/dist/assets/migrations/20260911183000_country_journal_defaults.sql +143 -0
  28. package/dist/assets/migrations/20260911193853_line_account_defaults.sql +274 -0
  29. package/dist/assets/migrations/20260911195054_products.sql +221 -0
  30. package/dist/assets/migrations/20260911210131_anon_surface.sql +85 -0
  31. package/dist/assets/migrations/20260912074712_country_packs.sql +318 -0
  32. package/dist/assets/migrations/20260912080311_report_code_and_region.sql +198 -0
  33. package/dist/assets/migrations/20260912081014_pack_certification_maintained.sql +31 -0
  34. package/dist/assets/migrations/20260912081015_pack_certification_backfill.sql +16 -0
  35. package/dist/assets/migrations/20260912090407_tax_report_boxes.sql +329 -0
  36. package/dist/assets/migrations/20260912091917_tax_on_base_value.sql +25 -0
  37. package/dist/assets/migrations/20260912091918_tax_engine_columns.sql +776 -0
  38. package/dist/assets/migrations/20260912094412_opening_and_closing.sql +759 -0
  39. package/dist/assets/migrations/20260912095825_charts_of_accounts.sql +326 -0
  40. package/dist/assets/migrations/20260912100412_financial_statements.sql +632 -0
  41. package/dist/assets/migrations/20260912104719_one_formula_evaluator.sql +209 -0
  42. package/dist/assets/migrations/20260912105720_entry_kind_appropriation.sql +26 -0
  43. package/dist/assets/migrations/20260912105721_appropriation_entry_kind.sql +444 -0
  44. package/dist/assets/migrations/20260912111751_document_rules.sql +274 -0
  45. package/dist/assets/migrations/20260912112132_cash_basis_vat_and_fx.sql +1189 -0
  46. package/dist/assets/migrations/20260913074512_modules.sql +493 -0
  47. package/dist/assets/migrations/20260913075903_asset_disposal_roles.sql +47 -0
  48. package/dist/assets/migrations/20260913083216_capabilities.sql +637 -0
  49. package/dist/assets/migrations/20260913083901_company_invitations.sql +262 -0
  50. package/dist/assets/migrations/20260913084402_user_preferences.sql +376 -0
  51. package/dist/assets/migrations/20260913084847_company_profile.sql +261 -0
  52. package/dist/assets/migrations/20260913085436_numbering_reads_the_pack.sql +235 -0
  53. package/dist/assets/migrations/20260913085932_api_keys.sql +303 -0
  54. package/dist/assets/migrations/20260913090216_fiscal_year_bounds.sql +159 -0
  55. package/dist/assets/migrations/20260913092527_entries_import.sql +219 -0
  56. package/dist/assets/migrations/20260913101536_null_safe_guards.sql +188 -0
  57. package/dist/assets/migrations/20260913102115_installer_is_named.sql +462 -0
  58. package/dist/assets/migrations/20260913102758_no_currency_default.sql +138 -0
  59. package/dist/assets/migrations/20260913103355_cash_basis_needs_a_box.sql +453 -0
  60. package/dist/assets/migrations/20260913104014_aged_balance_named_group.sql +79 -0
  61. package/dist/assets/migrations/20260913104232_foreign_key_indexes.sql +144 -0
  62. package/dist/assets/migrations/20260913105120_declared_no_reader.sql +41 -0
  63. package/dist/assets/migrations/20260913111407_pack_languages.sql +223 -0
  64. package/dist/assets/migrations/20260913112233_schema_comments_for_a_reader.sql +27 -0
  65. package/dist/assets/migrations/20260913114535_fec_opening_balances.sql +307 -0
  66. package/dist/assets/migrations/20260914103412_audit_log.sql +509 -0
  67. package/dist/assets/migrations/20260914111907_pack_upgrade.sql +428 -0
  68. package/dist/assets/migrations/20260914120500_rounding_reads_the_currency.sql +206 -0
  69. package/dist/assets/migrations/20260914121200_amounts_round_at_the_currency.sql +2403 -0
  70. package/dist/assets/migrations/20260914134325_schema_version_0_2_0.sql +36 -0
  71. package/dist/assets/migrations/20260914143915_accounts_in_use.sql +428 -0
  72. package/dist/assets/migrations/20260914144731_account_code_frozen.sql +99 -0
  73. package/dist/assets/migrations/20260914151207_schema_grants_its_own_rights.sql +284 -0
  74. package/dist/assets/migrations/20260914152840_pack_upgrade_records_its_own_line.sql +237 -0
  75. package/dist/assets/migrations/20260914163943_declaration_periodicity.sql +349 -0
  76. package/dist/assets/migrations/20260915094000_foreign_services_received.sql +37 -0
  77. package/dist/assets/migrations/20260915094500_mentions_read_a_foreign_service.sql +72 -0
  78. package/dist/assets/migrations/20260915153000_document_shares.sql +568 -0
  79. package/dist/assets/migrations/20260915160000_ec_sales_list.sql +181 -0
  80. package/dist/assets/migrations/20260915161842_pack_sources.sql +56 -0
  81. package/dist/assets/migrations/20260915170500_schema_version_0_3_0.sql +45 -0
  82. package/dist/assets/migrations/20260915174500_a_vat_category_is_a_code.sql +177 -0
  83. package/dist/assets/migrations/20260915180000_document_rule_references.sql +85 -0
  84. package/dist/assets/migrations/20260915181000_territories.sql +342 -0
  85. package/dist/assets/migrations/20260915181500_ec_sales_list_reads_the_territories.sql +222 -0
  86. package/dist/assets/migrations/20260915182000_intracom_triangular.sql +53 -0
  87. package/dist/assets/migrations/20260915182500_a_triangular_supply_says_reverse_charge.sql +99 -0
  88. package/dist/assets/migrations/20260915191200_a_document_knows_its_language.sql +633 -0
  89. package/dist/assets/migrations/20260915195000_a_price_that_holds_its_tax.sql +649 -0
  90. package/dist/assets/migrations/20260915200000_a_posting_names_its_boxes.sql +1004 -0
  91. package/dist/assets/migrations/20260916094500_a_company_files_more_than_one_declaration.sql +795 -0
  92. package/dist/assets/migrations/20260916103000_a_ledger_line_names_its_posting.sql +902 -0
  93. package/dist/assets/migrations/20260916123000_a_vocabulary_for_a_tax_that_is_not_a_vat.sql +144 -0
  94. package/dist/assets/migrations/20260916124000_a_box_can_be_a_rate_of_a_box.sql +525 -0
  95. package/dist/assets/migrations/20260916125000_a_tax_follows_the_territory.sql +1318 -0
  96. package/dist/assets/migrations/20260916126000_a_tax_point_and_its_exception.sql +1211 -0
  97. package/dist/assets/migrations/20260917090000_a_counterparty_that_learns.sql +561 -0
  98. package/dist/assets/migrations/20260917120000_what_the_money_pays.sql +545 -0
  99. package/dist/assets/migrations/20260917150000_a_filing_is_a_row.sql +488 -0
  100. package/dist/assets/migrations/20260917170000_when_it_is_due.sql +194 -0
  101. package/dist/assets/migrations/20260917180000_a_box_is_a_number_and_a_kind.sql +213 -0
  102. package/dist/assets/migrations/20260917190000_what_a_declaration_owes.sql +486 -0
  103. package/dist/assets/migrations/20260917200000_what_moved_after_it_went.sql +227 -0
  104. package/dist/assets/migrations/20260918090000_a_form_names_its_file.sql +27 -0
  105. package/dist/assets/migrations/20260918110000_a_deposit_and_what_came_back.sql +286 -0
  106. package/dist/assets/migrations/20260918113741_a_fourth_preset_is_named.sql +9 -0
  107. package/dist/assets/migrations/20260918113807_a_client_reads_and_hands_over.sql +96 -0
  108. package/dist/assets/migrations/20260918114322_two_definer_functions_check_their_caller.sql +75 -0
  109. package/dist/assets/migrations/20260918130000_every_company_somebody_keeps.sql +177 -0
  110. package/dist/assets/migrations/20260918140000_a_session_nobody_prepared.sql +40 -0
  111. package/dist/assets/migrations/20260918141107_a_line_keeps_the_tax_it_was_posted_with.sql +256 -0
  112. package/dist/assets/migrations/20260918141342_a_company_has_an_electronic_address.sql +66 -0
  113. package/dist/assets/migrations/20260918141605_an_invoice_reads_whole_from_the_views.sql +313 -0
  114. package/dist/assets/migrations/20260918141627_a_policy_asks_once.sql +132 -0
  115. package/dist/assets/migrations/20260918143352_a_suggestion_reads_the_words_once.sql +204 -0
  116. package/dist/assets/migrations/20260918143417_a_reference_of_the_caller_and_a_rehearsal.sql +115 -0
  117. package/dist/assets/migrations/20260918150712_a_company_leaves_with_its_books.sql +1119 -0
  118. package/dist/assets/migrations/20260918150931_a_statement_is_imported_once.sql +654 -0
  119. package/dist/assets/migrations/20260918161204_a_posted_document_does_not_move.sql +437 -0
  120. package/dist/assets/migrations/20260918161538_a_posted_entry_does_not_move.sql +252 -0
  121. package/dist/assets/migrations/20260918171946_an_entry_is_posted_by_post_entry.sql +289 -0
  122. package/dist/assets/migrations/20260918174312_schema_version_0_4_0.sql +53 -0
  123. package/dist/assets/modules/assets/module.json +13 -0
  124. package/dist/assets/modules/assets/supabase/migrations/20260913081447_assets.sql +1190 -0
  125. package/dist/assets/modules/assets/supabase/migrations/20260913104234_foreign_key_indexes.sql +47 -0
  126. package/dist/assets/modules/assets/supabase/migrations/20260913104500_assets_capabilities.sql +145 -0
  127. package/dist/assets/modules/assets/supabase/migrations/20260914122100_assets_round_at_the_currency.sql +564 -0
  128. package/dist/assets/modules/assets/supabase/migrations/20260914145012_assets_accounts_in_use.sql +37 -0
  129. package/dist/assets/modules/assets/supabase/migrations/20260914151530_assets_grants_its_own_rights.sql +63 -0
  130. package/dist/assets/modules/assets/supabase/migrations/20260918113912_assets_client_reads.sql +20 -0
  131. package/dist/assets/modules/assets/supabase/migrations/20260918150801_assets_leave_with_the_company.sql +41 -0
  132. package/dist/assets/modules/budgets/module.json +12 -0
  133. package/dist/assets/modules/budgets/supabase/migrations/20260913083012_budgets.sql +210 -0
  134. package/dist/assets/modules/budgets/supabase/migrations/20260913104233_foreign_key_indexes.sql +37 -0
  135. package/dist/assets/modules/budgets/supabase/migrations/20260913104501_budgets_capabilities.sql +72 -0
  136. package/dist/assets/modules/budgets/supabase/migrations/20260914122400_budgets_round_at_the_currency.sql +68 -0
  137. package/dist/assets/modules/budgets/supabase/migrations/20260914145048_budgets_accounts_in_use.sql +30 -0
  138. package/dist/assets/modules/budgets/supabase/migrations/20260914151812_budgets_grants_its_own_rights.sql +31 -0
  139. package/dist/assets/modules/budgets/supabase/migrations/20260918113954_budgets_client_reads.sql +20 -0
  140. package/dist/assets/modules/budgets/supabase/migrations/20260918150823_budgets_leave_with_the_company.sql +37 -0
  141. package/dist/assets/modules/schema/module.1.json +69 -0
  142. package/dist/assets/seed/00_currencies.sql +15 -0
  143. package/dist/assets/seed/00_territories.sql +280 -0
  144. package/dist/assets/seed/05_framework_generic.sql +110 -0
  145. package/dist/assets/seed/10_pack_be.sql +1284 -0
  146. package/dist/assets/seed/11_pack_fr.sql +1112 -0
  147. package/dist/assets/seed/12_pack_lu.sql +2484 -0
  148. package/dist/assets/seed/13_pack_ee.sql +733 -0
  149. package/dist/assets/seed/14_pack_gb.sql +796 -0
  150. package/dist/assets/seed/15_pack_us.sql +751 -0
  151. package/dist/assets/seed/90_demo_company.sql +368 -0
  152. package/dist/assets/seed/modules/assets/10_pack_be.sql +58 -0
  153. package/dist/assets/seed/modules/assets/11_pack_fr.sql +57 -0
  154. package/dist/assets/seed/modules/assets/14_pack_gb.sql +58 -0
  155. package/dist/assets/seed/modules/assets/15_pack_us.sql +60 -0
  156. package/dist/auth.d.ts +59 -0
  157. package/dist/auth.d.ts.map +1 -0
  158. package/dist/auth.js +134 -0
  159. package/dist/auth.js.map +1 -0
  160. package/dist/bin.d.ts +6 -0
  161. package/dist/bin.d.ts.map +1 -0
  162. package/dist/bin.js +8 -0
  163. package/dist/bin.js.map +1 -0
  164. package/dist/books.d.ts +60 -0
  165. package/dist/books.d.ts.map +1 -0
  166. package/dist/books.js +168 -0
  167. package/dist/books.js.map +1 -0
  168. package/dist/bootstrap.d.ts +236 -0
  169. package/dist/bootstrap.d.ts.map +1 -0
  170. package/dist/bootstrap.js +459 -0
  171. package/dist/bootstrap.js.map +1 -0
  172. package/dist/bundle.d.ts +27 -0
  173. package/dist/bundle.d.ts.map +1 -0
  174. package/dist/bundle.js +47 -0
  175. package/dist/bundle.js.map +1 -0
  176. package/dist/checklist.d.ts +35 -0
  177. package/dist/checklist.d.ts.map +1 -0
  178. package/dist/checklist.js +64 -0
  179. package/dist/checklist.js.map +1 -0
  180. package/dist/cli.d.ts +14 -0
  181. package/dist/cli.d.ts.map +1 -0
  182. package/dist/cli.js +318 -0
  183. package/dist/cli.js.map +1 -0
  184. package/dist/commands/company.d.ts +59 -0
  185. package/dist/commands/company.d.ts.map +1 -0
  186. package/dist/commands/company.js +287 -0
  187. package/dist/commands/company.js.map +1 -0
  188. package/dist/commands/contact.d.ts +9 -0
  189. package/dist/commands/contact.d.ts.map +1 -0
  190. package/dist/commands/contact.js +82 -0
  191. package/dist/commands/contact.js.map +1 -0
  192. package/dist/commands/demo.d.ts +19 -0
  193. package/dist/commands/demo.d.ts.map +1 -0
  194. package/dist/commands/demo.js +72 -0
  195. package/dist/commands/demo.js.map +1 -0
  196. package/dist/commands/doctor.d.ts +12 -0
  197. package/dist/commands/doctor.d.ts.map +1 -0
  198. package/dist/commands/doctor.js +68 -0
  199. package/dist/commands/doctor.js.map +1 -0
  200. package/dist/commands/document.d.ts +17 -0
  201. package/dist/commands/document.d.ts.map +1 -0
  202. package/dist/commands/document.js +217 -0
  203. package/dist/commands/document.js.map +1 -0
  204. package/dist/commands/init.d.ts +31 -0
  205. package/dist/commands/init.d.ts.map +1 -0
  206. package/dist/commands/init.js +535 -0
  207. package/dist/commands/init.js.map +1 -0
  208. package/dist/commands/login.d.ts +24 -0
  209. package/dist/commands/login.d.ts.map +1 -0
  210. package/dist/commands/login.js +128 -0
  211. package/dist/commands/login.js.map +1 -0
  212. package/dist/commands/migrate.d.ts +30 -0
  213. package/dist/commands/migrate.d.ts.map +1 -0
  214. package/dist/commands/migrate.js +115 -0
  215. package/dist/commands/migrate.js.map +1 -0
  216. package/dist/commands/module.d.ts +32 -0
  217. package/dist/commands/module.d.ts.map +1 -0
  218. package/dist/commands/module.js +285 -0
  219. package/dist/commands/module.js.map +1 -0
  220. package/dist/commands/pack.d.ts +22 -0
  221. package/dist/commands/pack.d.ts.map +1 -0
  222. package/dist/commands/pack.js +481 -0
  223. package/dist/commands/pack.js.map +1 -0
  224. package/dist/commands/payment.d.ts +15 -0
  225. package/dist/commands/payment.d.ts.map +1 -0
  226. package/dist/commands/payment.js +97 -0
  227. package/dist/commands/payment.js.map +1 -0
  228. package/dist/commands/register.d.ts +20 -0
  229. package/dist/commands/register.d.ts.map +1 -0
  230. package/dist/commands/register.js +134 -0
  231. package/dist/commands/register.js.map +1 -0
  232. package/dist/commands/status.d.ts +8 -0
  233. package/dist/commands/status.d.ts.map +1 -0
  234. package/dist/commands/status.js +134 -0
  235. package/dist/commands/status.js.map +1 -0
  236. package/dist/commands/whoami.d.ts +21 -0
  237. package/dist/commands/whoami.d.ts.map +1 -0
  238. package/dist/commands/whoami.js +133 -0
  239. package/dist/commands/whoami.js.map +1 -0
  240. package/dist/company.d.ts +16 -0
  241. package/dist/company.d.ts.map +1 -0
  242. package/dist/company.js +26 -0
  243. package/dist/company.js.map +1 -0
  244. package/dist/config.d.ts +24 -0
  245. package/dist/config.d.ts.map +1 -0
  246. package/dist/config.js +50 -0
  247. package/dist/config.js.map +1 -0
  248. package/dist/connection.d.ts +79 -0
  249. package/dist/connection.d.ts.map +1 -0
  250. package/dist/connection.js +116 -0
  251. package/dist/connection.js.map +1 -0
  252. package/dist/context.d.ts +47 -0
  253. package/dist/context.d.ts.map +1 -0
  254. package/dist/context.js +93 -0
  255. package/dist/context.js.map +1 -0
  256. package/dist/doctor.d.ts +45 -0
  257. package/dist/doctor.d.ts.map +1 -0
  258. package/dist/doctor.js +448 -0
  259. package/dist/doctor.js.map +1 -0
  260. package/dist/grants.d.ts +88 -0
  261. package/dist/grants.d.ts.map +1 -0
  262. package/dist/grants.js +174 -0
  263. package/dist/grants.js.map +1 -0
  264. package/dist/identity.d.ts +54 -0
  265. package/dist/identity.d.ts.map +1 -0
  266. package/dist/identity.js +132 -0
  267. package/dist/identity.js.map +1 -0
  268. package/dist/index.d.ts +44 -0
  269. package/dist/index.d.ts.map +1 -0
  270. package/dist/index.js +43 -0
  271. package/dist/index.js.map +1 -0
  272. package/dist/inventory.d.ts +155 -0
  273. package/dist/inventory.d.ts.map +1 -0
  274. package/dist/inventory.js +303 -0
  275. package/dist/inventory.js.map +1 -0
  276. package/dist/migrations.d.ts +76 -0
  277. package/dist/migrations.d.ts.map +1 -0
  278. package/dist/migrations.js +226 -0
  279. package/dist/migrations.js.map +1 -0
  280. package/dist/module/read.d.ts +91 -0
  281. package/dist/module/read.d.ts.map +1 -0
  282. package/dist/module/read.js +172 -0
  283. package/dist/module/read.js.map +1 -0
  284. package/dist/output.d.ts +110 -0
  285. package/dist/output.d.ts.map +1 -0
  286. package/dist/output.js +173 -0
  287. package/dist/output.js.map +1 -0
  288. package/dist/pack/certification.d.ts +27 -0
  289. package/dist/pack/certification.d.ts.map +1 -0
  290. package/dist/pack/certification.js +38 -0
  291. package/dist/pack/certification.js.map +1 -0
  292. package/dist/pack/compile.d.ts +75 -0
  293. package/dist/pack/compile.d.ts.map +1 -0
  294. package/dist/pack/compile.js +801 -0
  295. package/dist/pack/compile.js.map +1 -0
  296. package/dist/pack/filing.d.ts +48 -0
  297. package/dist/pack/filing.d.ts.map +1 -0
  298. package/dist/pack/filing.js +56 -0
  299. package/dist/pack/filing.js.map +1 -0
  300. package/dist/pack/read.d.ts +766 -0
  301. package/dist/pack/read.d.ts.map +1 -0
  302. package/dist/pack/read.js +2336 -0
  303. package/dist/pack/read.js.map +1 -0
  304. package/dist/pack/schema.d.ts +26 -0
  305. package/dist/pack/schema.d.ts.map +1 -0
  306. package/dist/pack/schema.js +181 -0
  307. package/dist/pack/schema.js.map +1 -0
  308. package/dist/pack/territories.d.ts +98 -0
  309. package/dist/pack/territories.d.ts.map +1 -0
  310. package/dist/pack/territories.js +0 -0
  311. package/dist/pack/territories.js.map +1 -0
  312. package/dist/pack/upgrade.d.ts +86 -0
  313. package/dist/pack/upgrade.d.ts.map +1 -0
  314. package/dist/pack/upgrade.js +76 -0
  315. package/dist/pack/upgrade.js.map +1 -0
  316. package/dist/pack/vat-codes.d.ts +273 -0
  317. package/dist/pack/vat-codes.d.ts.map +1 -0
  318. package/dist/pack/vat-codes.js +513 -0
  319. package/dist/pack/vat-codes.js.map +1 -0
  320. package/dist/profiles.d.ts +67 -0
  321. package/dist/profiles.d.ts.map +1 -0
  322. package/dist/profiles.js +187 -0
  323. package/dist/profiles.js.map +1 -0
  324. package/dist/prompt.d.ts +40 -0
  325. package/dist/prompt.d.ts.map +1 -0
  326. package/dist/prompt.js +120 -0
  327. package/dist/prompt.js.map +1 -0
  328. package/dist/registry.d.ts +84 -0
  329. package/dist/registry.d.ts.map +1 -0
  330. package/dist/registry.js +104 -0
  331. package/dist/registry.js.map +1 -0
  332. package/dist/rest.d.ts +81 -0
  333. package/dist/rest.d.ts.map +1 -0
  334. package/dist/rest.js +245 -0
  335. package/dist/rest.js.map +1 -0
  336. package/dist/schema.d.ts +15 -0
  337. package/dist/schema.d.ts.map +1 -0
  338. package/dist/schema.js +15 -0
  339. package/dist/schema.js.map +1 -0
  340. package/dist/seeds.d.ts +27 -0
  341. package/dist/seeds.d.ts.map +1 -0
  342. package/dist/seeds.js +47 -0
  343. package/dist/seeds.js.map +1 -0
  344. package/dist/session.d.ts +39 -0
  345. package/dist/session.d.ts.map +1 -0
  346. package/dist/session.js +92 -0
  347. package/dist/session.js.map +1 -0
  348. package/dist/sql.d.ts +48 -0
  349. package/dist/sql.d.ts.map +1 -0
  350. package/dist/sql.js +112 -0
  351. package/dist/sql.js.map +1 -0
  352. package/dist/status.d.ts +94 -0
  353. package/dist/status.d.ts.map +1 -0
  354. package/dist/status.js +120 -0
  355. package/dist/status.js.map +1 -0
  356. package/dist/ui.d.ts +55 -0
  357. package/dist/ui.d.ts.map +1 -0
  358. package/dist/ui.js +114 -0
  359. package/dist/ui.js.map +1 -0
  360. package/package.json +29 -0
  361. package/schema/output.1.json +613 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The company a name or an id refers to, among those a caller can see.
3
+ *
4
+ * A name is what a person types and a uuid is what a script passes, so both
5
+ * are accepted; an ambiguous name is refused rather than resolved to the first
6
+ * match, because working on the wrong company is not a mistake anybody
7
+ * notices the same day. The list is whatever the caller was allowed to read —
8
+ * every company for the installer's connection, the ones row level security
9
+ * lets through for a person — so a company somebody was never invited to is
10
+ * simply unknown, which is also all they should learn about it.
11
+ */
12
+ import { UsageError } from './args.js';
13
+ export function matchCompany(companies, wanted) {
14
+ const asked = wanted.toLowerCase();
15
+ const matches = companies.filter((c) => c.id === asked || c.name.toLowerCase() === asked);
16
+ if (matches.length === 0) {
17
+ throw new UsageError(`unknown_company: no company called ${wanted}. This installation has: ${companies.length === 0 ? 'none' : companies.map((c) => c.name).join(', ')}`);
18
+ }
19
+ if (matches.length > 1) {
20
+ throw new UsageError(`ambiguous_company: ${matches.length} companies are called ${wanted}. Name one by its id: ${matches
21
+ .map((c) => c.id)
22
+ .join(', ')}`);
23
+ }
24
+ return matches[0];
25
+ }
26
+ //# sourceMappingURL=company.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"company.js","sourceRoot":"","sources":["../src/company.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,UAAU,YAAY,CAAyC,SAAuB,EAAE,MAAc;IAC1G,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,CAAC;IAC1F,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,UAAU,CAClB,sCAAsC,MAAM,4BAC1C,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAC1E,EAAE,CACH,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,UAAU,CAClB,sBAAsB,OAAO,CAAC,MAAM,yBAAyB,MAAM,yBAAyB,OAAO;aAChG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChB,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAAM,CAAC;AACzB,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * `ekwo.json` — the one file the CLI writes, and what is deliberately not in it.
3
+ *
4
+ * It holds three things: which Supabase project this installation is on, which
5
+ * country's rules it was set up for, and which schema version it was at. That
6
+ * is enough for the next `ekwo status` or `ekwo migrate` to know where it is
7
+ * pointed without being told again.
8
+ *
9
+ * It holds no password, no service_role key and no connection string with
10
+ * credentials in it. Those are given per invocation, by flag, environment
11
+ * variable or prompt, and they are never written down here. A file that is
12
+ * safe to commit is a file that stays useful; a file with a key in it becomes
13
+ * a leak the first time somebody commits it.
14
+ */
15
+ export declare const CONFIG_FILE = "ekwo.json";
16
+ export interface EkwoConfig {
17
+ project_url?: string;
18
+ country?: string;
19
+ schema_version?: string;
20
+ }
21
+ export declare function configPath(cwd?: string): string;
22
+ export declare function readConfig(cwd?: string): Promise<EkwoConfig | undefined>;
23
+ export declare function writeConfig(config: EkwoConfig, cwd?: string): Promise<string>;
24
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,eAAO,MAAM,WAAW,cAAc,CAAC;AAEvC,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAMD,wBAAgB,UAAU,CAAC,GAAG,SAAgB,GAAG,MAAM,CAEtD;AAED,wBAAsB,UAAU,CAAC,GAAG,SAAgB,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAcrF;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAU1F"}
package/dist/config.js ADDED
@@ -0,0 +1,50 @@
1
+ /**
2
+ * `ekwo.json` — the one file the CLI writes, and what is deliberately not in it.
3
+ *
4
+ * It holds three things: which Supabase project this installation is on, which
5
+ * country's rules it was set up for, and which schema version it was at. That
6
+ * is enough for the next `ekwo status` or `ekwo migrate` to know where it is
7
+ * pointed without being told again.
8
+ *
9
+ * It holds no password, no service_role key and no connection string with
10
+ * credentials in it. Those are given per invocation, by flag, environment
11
+ * variable or prompt, and they are never written down here. A file that is
12
+ * safe to commit is a file that stays useful; a file with a key in it becomes
13
+ * a leak the first time somebody commits it.
14
+ */
15
+ import { readFile, writeFile } from 'node:fs/promises';
16
+ import { join } from 'node:path';
17
+ export const CONFIG_FILE = 'ekwo.json';
18
+ const HEADER = 'No secrets live here. The database password and the service_role key are ' +
19
+ 'given per command, through --flags, the environment or a prompt.';
20
+ export function configPath(cwd = process.cwd()) {
21
+ return join(cwd, CONFIG_FILE);
22
+ }
23
+ export async function readConfig(cwd = process.cwd()) {
24
+ try {
25
+ const text = await readFile(configPath(cwd), 'utf8');
26
+ const parsed = JSON.parse(text);
27
+ return {
28
+ ...(typeof parsed['project_url'] === 'string' ? { project_url: parsed['project_url'] } : {}),
29
+ ...(typeof parsed['country'] === 'string' ? { country: parsed['country'] } : {}),
30
+ ...(typeof parsed['schema_version'] === 'string'
31
+ ? { schema_version: parsed['schema_version'] }
32
+ : {}),
33
+ };
34
+ }
35
+ catch {
36
+ return undefined;
37
+ }
38
+ }
39
+ export async function writeConfig(config, cwd = process.cwd()) {
40
+ const path = configPath(cwd);
41
+ const body = {
42
+ $comment: HEADER,
43
+ ...(config.project_url !== undefined ? { project_url: config.project_url } : {}),
44
+ ...(config.country !== undefined ? { country: config.country } : {}),
45
+ ...(config.schema_version !== undefined ? { schema_version: config.schema_version } : {}),
46
+ };
47
+ await writeFile(path, `${JSON.stringify(body, null, 2)}\n`, 'utf8');
48
+ return path;
49
+ }
50
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AAQvC,MAAM,MAAM,GACV,2EAA2E;IAC3E,kEAAkE,CAAC;AAErE,MAAM,UAAU,UAAU,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC5C,OAAO,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAClD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;QAC3D,OAAO;YACL,GAAG,CAAC,OAAO,MAAM,CAAC,aAAa,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5F,GAAG,CAAC,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChF,GAAG,CAAC,OAAO,MAAM,CAAC,gBAAgB,CAAC,KAAK,QAAQ;gBAC9C,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,gBAAgB,CAAC,EAAE;gBAC9C,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAkB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACvE,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG;QACX,QAAQ,EAAE,MAAM;QAChB,GAAG,CAAC,MAAM,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,GAAG,CAAC,MAAM,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1F,CAAC;IACF,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpE,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Where the connection details come from, and where they do not go.
3
+ *
4
+ * Three sources, in this order: a flag, an environment variable, a prompt.
5
+ * Nothing else. In particular the CLI never reads a secret out of a file it
6
+ * wrote and never writes one into a file — not into `ekwo.json`, not into a
7
+ * dotfile in the home directory, not into a cache. A service_role key can do
8
+ * anything to the project it belongs to; leaving a copy of it on disk because
9
+ * it saved a paste is not a trade worth making. `.env.example` documents the
10
+ * variables so an operator can put them somewhere *they* chose.
11
+ *
12
+ * The reliable way to give the CLI a database is `--db-url`, copied from the
13
+ * Supabase dashboard under Connect → Session pooler. `--project-ref` with
14
+ * `--db-password` and `--db-region` is the convenience, and it no longer
15
+ * guesses: the pooler hostname carries a generation prefix as well as a
16
+ * region, so both `aws-0-<region>` and `aws-1-<region>` are tried and the one
17
+ * that answers is kept and printed. There is deliberately no helper that
18
+ * builds the direct host `db.<ref>.supabase.co`: it resolves to an IPv6
19
+ * address only on projects created since 2024, so deriving it on the
20
+ * operator's behalf produces a hang rather than an error. Someone who wants it
21
+ * passes it as `--db-url`.
22
+ */
23
+ export interface Connection {
24
+ /** Postgres connection string. Always present once resolved. */
25
+ dbUrl: string;
26
+ /** `https://<ref>.supabase.co`, when known. Needed to create the first user. */
27
+ supabaseUrl?: string | undefined;
28
+ /** Needed to create the first user, and never stored. */
29
+ serviceRoleKey?: string | undefined;
30
+ projectRef?: string | undefined;
31
+ }
32
+ export declare const ENV_DB_URL = "EKWO_DB_URL";
33
+ export declare const ENV_DB_URL_FALLBACK = "SUPABASE_DB_URL";
34
+ export declare const ENV_SUPABASE_URL = "SUPABASE_URL";
35
+ export declare const ENV_SERVICE_ROLE_KEY = "SUPABASE_SERVICE_ROLE_KEY";
36
+ /** The project ref out of whatever we were given, or `undefined`. */
37
+ export declare function projectRefFrom(value: string | undefined): string | undefined;
38
+ export declare function supabaseUrlFor(projectRef: string): string;
39
+ /**
40
+ * The two pooler generations Supabase issues today. Both are tried, so the
41
+ * order is only which one costs a round trip when it is the wrong one.
42
+ */
43
+ export declare const POOLER_GENERATIONS: readonly ["aws-0", "aws-1"];
44
+ /**
45
+ * The session pooler, on port 5432, for one generation prefix.
46
+ *
47
+ * Session mode — not the transaction pooler on 6543 — because a migration
48
+ * needs a session: advisory locks, `set local`, and a multi-statement file
49
+ * applied as one command.
50
+ */
51
+ export declare function poolerUrl(projectRef: string, password: string, region: string, generation: string): string;
52
+ /**
53
+ * Every pooler host worth trying for a ref and a region.
54
+ *
55
+ * The generation prefix is not derivable. A project created in `eu-west-3` in
56
+ * September 2026 answered on `aws-1-eu-west-3` and returned "Tenant or user
57
+ * not found" on `aws-0-eu-west-3`; older projects are the other way round.
58
+ * Building one of them and calling it the answer is the bug this replaces.
59
+ */
60
+ export declare function poolerCandidates(projectRef: string, password: string, region: string): string[];
61
+ /** The host of a connection string, for a message that names what answered. */
62
+ export declare function hostOf(dbUrl: string): string;
63
+ /** Answers whether a connection string reaches a database. */
64
+ export type Probe = (dbUrl: string) => Promise<boolean>;
65
+ export declare class NoPoolerHostError extends Error {
66
+ readonly tried: string[];
67
+ constructor(tried: string[]);
68
+ }
69
+ /**
70
+ * Picks the pooler host that answers, trying each generation in turn.
71
+ *
72
+ * Returns the string that worked, so the caller can print the host and the
73
+ * operator learns which one their project is on.
74
+ */
75
+ export declare function pickPoolerUrl(projectRef: string, password: string, region: string, probe: Probe): Promise<string>;
76
+ export declare function looksLikeConnectionString(value: string): boolean;
77
+ /** A connection string with `sslmode=require` added when it says nothing. */
78
+ export declare function withSsl(dbUrl: string): string;
79
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,WAAW,UAAU;IACzB,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,eAAO,MAAM,UAAU,gBAAgB,CAAC;AACxC,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AACrD,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAC/C,eAAO,MAAM,oBAAoB,8BAA8B,CAAC;AAEhE,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAmB5E;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,6BAA8B,CAAC;AAE9D;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,MAAM,CAER;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,EAAE,CAIV;AAED,+EAA+E;AAC/E,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAG5C;AAED,8DAA8D;AAC9D,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAExD,qBAAa,iBAAkB,SAAQ,KAAK;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE;gBAAf,KAAK,EAAE,MAAM,EAAE;CAOrC;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,MAAM,CAAC,CAMjB;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI7C"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Where the connection details come from, and where they do not go.
3
+ *
4
+ * Three sources, in this order: a flag, an environment variable, a prompt.
5
+ * Nothing else. In particular the CLI never reads a secret out of a file it
6
+ * wrote and never writes one into a file — not into `ekwo.json`, not into a
7
+ * dotfile in the home directory, not into a cache. A service_role key can do
8
+ * anything to the project it belongs to; leaving a copy of it on disk because
9
+ * it saved a paste is not a trade worth making. `.env.example` documents the
10
+ * variables so an operator can put them somewhere *they* chose.
11
+ *
12
+ * The reliable way to give the CLI a database is `--db-url`, copied from the
13
+ * Supabase dashboard under Connect → Session pooler. `--project-ref` with
14
+ * `--db-password` and `--db-region` is the convenience, and it no longer
15
+ * guesses: the pooler hostname carries a generation prefix as well as a
16
+ * region, so both `aws-0-<region>` and `aws-1-<region>` are tried and the one
17
+ * that answers is kept and printed. There is deliberately no helper that
18
+ * builds the direct host `db.<ref>.supabase.co`: it resolves to an IPv6
19
+ * address only on projects created since 2024, so deriving it on the
20
+ * operator's behalf produces a hang rather than an error. Someone who wants it
21
+ * passes it as `--db-url`.
22
+ */
23
+ export const ENV_DB_URL = 'EKWO_DB_URL';
24
+ export const ENV_DB_URL_FALLBACK = 'SUPABASE_DB_URL';
25
+ export const ENV_SUPABASE_URL = 'SUPABASE_URL';
26
+ export const ENV_SERVICE_ROLE_KEY = 'SUPABASE_SERVICE_ROLE_KEY';
27
+ /** The project ref out of whatever we were given, or `undefined`. */
28
+ export function projectRefFrom(value) {
29
+ if (value === undefined || value.length === 0)
30
+ return undefined;
31
+ // https://abcdefghijklmnopqrst.supabase.co
32
+ const host = /^https?:\/\/([a-z0-9-]+)\.supabase\.(co|in|red)/i.exec(value);
33
+ if (host !== null)
34
+ return host[1];
35
+ // postgresql://postgres.<ref>:password@aws-0-eu-central-1.pooler.supabase.com:5432/postgres
36
+ const pooler = /\/\/postgres\.([a-z0-9]+):/i.exec(value);
37
+ if (pooler !== null)
38
+ return pooler[1];
39
+ // postgresql://postgres:password@db.<ref>.supabase.co:5432/postgres
40
+ const direct = /@db\.([a-z0-9]+)\.supabase\./i.exec(value);
41
+ if (direct !== null)
42
+ return direct[1];
43
+ // A bare ref: twenty lowercase letters is what Supabase issues.
44
+ if (/^[a-z]{20}$/.test(value))
45
+ return value;
46
+ return undefined;
47
+ }
48
+ export function supabaseUrlFor(projectRef) {
49
+ return `https://${projectRef}.supabase.co`;
50
+ }
51
+ /**
52
+ * The two pooler generations Supabase issues today. Both are tried, so the
53
+ * order is only which one costs a round trip when it is the wrong one.
54
+ */
55
+ export const POOLER_GENERATIONS = ['aws-0', 'aws-1'];
56
+ /**
57
+ * The session pooler, on port 5432, for one generation prefix.
58
+ *
59
+ * Session mode — not the transaction pooler on 6543 — because a migration
60
+ * needs a session: advisory locks, `set local`, and a multi-statement file
61
+ * applied as one command.
62
+ */
63
+ export function poolerUrl(projectRef, password, region, generation) {
64
+ return `postgresql://postgres.${projectRef}:${encodeURIComponent(password)}@${generation}-${region}.pooler.supabase.com:5432/postgres`;
65
+ }
66
+ /**
67
+ * Every pooler host worth trying for a ref and a region.
68
+ *
69
+ * The generation prefix is not derivable. A project created in `eu-west-3` in
70
+ * September 2026 answered on `aws-1-eu-west-3` and returned "Tenant or user
71
+ * not found" on `aws-0-eu-west-3`; older projects are the other way round.
72
+ * Building one of them and calling it the answer is the bug this replaces.
73
+ */
74
+ export function poolerCandidates(projectRef, password, region) {
75
+ return POOLER_GENERATIONS.map((generation) => poolerUrl(projectRef, password, region, generation));
76
+ }
77
+ /** The host of a connection string, for a message that names what answered. */
78
+ export function hostOf(dbUrl) {
79
+ const match = /@([^/:?]+)/.exec(dbUrl);
80
+ return match?.[1] ?? dbUrl;
81
+ }
82
+ export class NoPoolerHostError extends Error {
83
+ tried;
84
+ constructor(tried) {
85
+ super(`no_pooler_host: none of ${tried.join(', ')} answered. ` +
86
+ 'Copy the connection string from your Supabase dashboard — Connect → Session pooler — ' +
87
+ 'and pass it as --db-url. That string is the only form that is not derived.');
88
+ this.tried = tried;
89
+ }
90
+ }
91
+ /**
92
+ * Picks the pooler host that answers, trying each generation in turn.
93
+ *
94
+ * Returns the string that worked, so the caller can print the host and the
95
+ * operator learns which one their project is on.
96
+ */
97
+ export async function pickPoolerUrl(projectRef, password, region, probe) {
98
+ const candidates = poolerCandidates(projectRef, password, region);
99
+ for (const candidate of candidates) {
100
+ if (await probe(withSsl(candidate)))
101
+ return candidate;
102
+ }
103
+ throw new NoPoolerHostError(candidates.map(hostOf));
104
+ }
105
+ export function looksLikeConnectionString(value) {
106
+ return /^postgres(ql)?:\/\//i.test(value);
107
+ }
108
+ /** A connection string with `sslmode=require` added when it says nothing. */
109
+ export function withSsl(dbUrl) {
110
+ if (/[?&]sslmode=/i.test(dbUrl))
111
+ return dbUrl;
112
+ if (/localhost|127\.0\.0\.1/.test(dbUrl))
113
+ return dbUrl;
114
+ return `${dbUrl}${dbUrl.includes('?') ? '&' : '?'}sslmode=require`;
115
+ }
116
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Turning flags, environment variables and questions into a connection.
3
+ *
4
+ * Every command starts here, so the rules about where a secret may come from
5
+ * are written once. See `connection.ts` for why none of them is a file.
6
+ */
7
+ import type { ParsedArgs } from './args.js';
8
+ import { type Connection, type Probe } from './connection.js';
9
+ import { type SqlClient } from './sql.js';
10
+ export declare const CONNECTION_FLAGS: readonly ["db-url", "db-password", "db-region", "project-ref", "supabase-url", "service-role-key"];
11
+ export interface ResolveOptions {
12
+ /** Ask for what is missing. False in `--yes` runs and when stdin is not a terminal. */
13
+ interactive: boolean;
14
+ env?: NodeJS.ProcessEnv;
15
+ /**
16
+ * How a candidate pooler host is tried. Injected so the resolution can be
17
+ * tested without a network, and so nothing else in this file knows a driver
18
+ * exists.
19
+ */
20
+ probe?: Probe;
21
+ /** How the database is opened. See `CommandDeps`. */
22
+ connect?: Connector | undefined;
23
+ }
24
+ /** Opens a connection string. The network driver, unless a test says otherwise. */
25
+ export type Connector = (dbUrl: string) => Promise<SqlClient>;
26
+ /**
27
+ * What a command may be handed instead of reaching for it.
28
+ *
29
+ * One thing: the way a database is opened. The tests plug PGlite in here and
30
+ * then run the commands themselves — flags, output, exit code — rather than
31
+ * the functions underneath them, which is the only way to hold every command
32
+ * to the same output contract.
33
+ */
34
+ export interface CommandDeps {
35
+ connect?: Connector | undefined;
36
+ }
37
+ /** Opens the connection, closes it, and answers whether that worked. */
38
+ export declare const connectProbe: Probe;
39
+ /** Works out how to reach the database, without connecting yet. */
40
+ export declare function resolveConnection(args: ParsedArgs, options: ResolveOptions): Promise<Connection>;
41
+ export interface Context {
42
+ db: SqlClient;
43
+ connection: Connection;
44
+ }
45
+ /** Resolves and opens. The caller closes. */
46
+ export declare function openDatabase(args: ParsedArgs, options: ResolveOptions): Promise<Context>;
47
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EAWL,KAAK,UAAU,EACf,KAAK,KAAK,EACX,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAGnD,eAAO,MAAM,gBAAgB,oGAOnB,CAAC;AAEX,MAAM,WAAW,cAAc;IAC7B,uFAAuF;IACvF,WAAW,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB;;;;OAIG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,qDAAqD;IACrD,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC;AAED,mFAAmF;AACnF,MAAM,MAAM,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;AAE9D;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC;AAED,wEAAwE;AACxE,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC;AAEF,mEAAmE;AACnE,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,UAAU,CAAC,CAmErB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,SAAS,CAAC;IACd,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,6CAA6C;AAC7C,wBAAsB,YAAY,CAChC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC,CASlB"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Turning flags, environment variables and questions into a connection.
3
+ *
4
+ * Every command starts here, so the rules about where a secret may come from
5
+ * are written once. See `connection.ts` for why none of them is a file.
6
+ */
7
+ import { UsageError, stringFlag } from './args.js';
8
+ import { ENV_DB_URL, ENV_DB_URL_FALLBACK, ENV_SERVICE_ROLE_KEY, ENV_SUPABASE_URL, hostOf, looksLikeConnectionString, pickPoolerUrl, projectRefFrom, supabaseUrlFor, withSsl, } from './connection.js';
9
+ import { NotInteractiveError, askSecret, isInteractive } from './prompt.js';
10
+ import { connect } from './sql.js';
11
+ import { dim, note } from './ui.js';
12
+ export const CONNECTION_FLAGS = [
13
+ 'db-url',
14
+ 'db-password',
15
+ 'db-region',
16
+ 'project-ref',
17
+ 'supabase-url',
18
+ 'service-role-key',
19
+ ];
20
+ /** Opens the connection, closes it, and answers whether that worked. */
21
+ export const connectProbe = async (dbUrl) => {
22
+ try {
23
+ const db = await connect(dbUrl);
24
+ await db.close();
25
+ return true;
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ };
31
+ /** Works out how to reach the database, without connecting yet. */
32
+ export async function resolveConnection(args, options) {
33
+ const env = options.env ?? process.env;
34
+ const interactive = options.interactive && isInteractive();
35
+ const supabaseUrlGiven = stringFlag(args, 'supabase-url') ?? env[ENV_SUPABASE_URL];
36
+ const serviceRoleKey = stringFlag(args, 'service-role-key') ?? env[ENV_SERVICE_ROLE_KEY];
37
+ let dbUrl = stringFlag(args, 'db-url') ?? env[ENV_DB_URL] ?? env[ENV_DB_URL_FALLBACK];
38
+ let projectRef = projectRefFrom(stringFlag(args, 'project-ref')) ??
39
+ projectRefFrom(supabaseUrlGiven) ??
40
+ projectRefFrom(dbUrl);
41
+ const region = stringFlag(args, 'db-region');
42
+ if (dbUrl === undefined && projectRef !== undefined && region !== undefined) {
43
+ const password = stringFlag(args, 'db-password') ??
44
+ env['EKWO_DB_PASSWORD'] ??
45
+ (interactive
46
+ ? await askSecret(`Database password for project ${projectRef}:`)
47
+ : undefined);
48
+ if (password === undefined || password.length === 0) {
49
+ throw new NotInteractiveError('the database password', '--db-password or --db-url');
50
+ }
51
+ // Both pooler generations are tried and the one that answers is kept. The
52
+ // prefix is not derivable from the region, and building one of the two and
53
+ // calling it the host is how `--db-region` used to fail: the connection
54
+ // was refused with "Tenant or user not found", which reads like a wrong
55
+ // password rather than a wrong hostname.
56
+ dbUrl = await pickPoolerUrl(projectRef, password, region, options.probe ?? connectProbe);
57
+ note(dim(`Session pooler: ${hostOf(dbUrl)}`));
58
+ }
59
+ // No `--db-region`, or no ref at all: ask for the string the dashboard
60
+ // prints. The direct host `db.<ref>.supabase.co` is not built here on the
61
+ // operator's behalf — it resolves to IPv6 only on any recent project, so
62
+ // deriving it silently produces a hang rather than an answer.
63
+ if (dbUrl === undefined) {
64
+ if (!interactive) {
65
+ throw new NotInteractiveError('the database connection string', '--db-url (or --project-ref with --db-password and --db-region)');
66
+ }
67
+ const answer = await askSecret('Postgres connection string (Supabase dashboard → Connect → Session pooler):');
68
+ if (!looksLikeConnectionString(answer)) {
69
+ throw new UsageError(`bad_connection_string: expected something starting with postgresql://, got "${answer.slice(0, 24)}…"`);
70
+ }
71
+ dbUrl = answer;
72
+ projectRef = projectRef ?? projectRefFrom(dbUrl);
73
+ }
74
+ const supabaseUrl = supabaseUrlGiven ?? (projectRef !== undefined ? supabaseUrlFor(projectRef) : undefined);
75
+ return {
76
+ dbUrl: withSsl(dbUrl),
77
+ ...(supabaseUrl !== undefined ? { supabaseUrl } : {}),
78
+ ...(serviceRoleKey !== undefined ? { serviceRoleKey } : {}),
79
+ ...(projectRef !== undefined ? { projectRef } : {}),
80
+ };
81
+ }
82
+ /** Resolves and opens. The caller closes. */
83
+ export async function openDatabase(args, options) {
84
+ const connection = await resolveConnection(args, options);
85
+ const db = await (options.connect ?? connect)(connection.dbUrl);
86
+ // The exception, announced. Everything that keeps books signs in as a
87
+ // person; what installs and operates connects as the owner of the database,
88
+ // to whom no policy applies, and a reader of the log should not have to
89
+ // know which commands are which.
90
+ note(dim('Connected as the owner of the database: installing and operating, not keeping books. Row level security does not apply to this connection.'));
91
+ return { db, connection };
92
+ }
93
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * `ekwo doctor` — the checks worth running on a live installation.
3
+ *
4
+ * Each one is something that is true of a healthy database and that nothing
5
+ * in the schema can enforce on its own: a table someone added without row
6
+ * level security, a migration that never landed, a membership row pointing at
7
+ * a user who has since been deleted, a bank statement whose declared closing
8
+ * balance does not match its lines.
9
+ *
10
+ * The doctor reads and reports. It never repairs: the fix for a missing
11
+ * policy is a migration, and the fix for an orphaned membership is a decision
12
+ * about who should have access, not a delete the installer guesses at.
13
+ */
14
+ import { type ExpectedObjects } from './inventory.js';
15
+ import type { Migration } from './migrations.js';
16
+ import type { SqlClient } from './sql.js';
17
+ export type Severity = 'ok' | 'warning' | 'problem';
18
+ export interface Check {
19
+ name: string;
20
+ severity: Severity;
21
+ summary: string;
22
+ /** Lines of evidence, printed under the summary. */
23
+ details?: string[];
24
+ /**
25
+ * The check's own findings, whole, for `--json`. The printed form is a
26
+ * summary of this and a machine reading the report should not have to parse
27
+ * English back into a list.
28
+ */
29
+ data?: Record<string, unknown>;
30
+ }
31
+ export interface DoctorReport {
32
+ checks: Check[];
33
+ problems: number;
34
+ warnings: number;
35
+ }
36
+ export interface DoctorOptions {
37
+ /**
38
+ * The inventory to compare the catalogue against. Defaults to the one this
39
+ * CLI ships; a test passes its own to describe a schema that is not this
40
+ * release's.
41
+ */
42
+ expected?: ExpectedObjects;
43
+ }
44
+ export declare function doctor(db: SqlClient, migrations: Migration[], options?: DoctorOptions): Promise<DoctorReport>;
45
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAOL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG1C,MAAM,MAAM,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpD,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,wBAAsB,MAAM,CAC1B,EAAE,EAAE,SAAS,EACb,UAAU,EAAE,SAAS,EAAE,EACvB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CA0BvB"}