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,128 @@
1
+ /**
2
+ * `ekwo login` and `ekwo logout`.
3
+ *
4
+ * Signing in is what turns "every command takes a connection string" into
5
+ * something a person can use twenty times a day. It asks the instance for a
6
+ * session with an address and a password, keeps the session in the person's
7
+ * own configuration directory, and keeps the password nowhere.
8
+ *
9
+ * What it needs comes from a flag, then the environment, then a profile that
10
+ * already exists — so signing in again after a session ended is `ekwo login`
11
+ * and a password — then `ekwo.json` for the instance URL, and a question last,
12
+ * when there is somebody to ask.
13
+ */
14
+ import { IDENTITY_ENV } from '@ekwo-ai/core';
15
+ import { boolFlag, rejectUnknownFlags, stringFlag } from '../args.js';
16
+ import { readConfig } from '../config.js';
17
+ import { fetchOf, profileName, refuseInstallerKey, refuseServiceRole } from '../identity.js';
18
+ import { setContext, setResult } from '../output.js';
19
+ import { FIRST_PROFILE, assertOutsideRepository, configDir, forgetSession, readProfiles, readSession, writeProfiles, writeSession, } from '../profiles.js';
20
+ import { NotInteractiveError, askRequired, askSecret, isInteractive } from '../prompt.js';
21
+ import { signIn, signOut } from '../session.js';
22
+ import { dim, heading, note, pairs, skipped, step } from '../ui.js';
23
+ export const LOGIN_FLAGS = ['profile', 'supabase-url', 'anon-key', 'email', 'password', 'yes'];
24
+ export const LOGOUT_FLAGS = ['profile'];
25
+ export async function loginCommand(args, deps = {}) {
26
+ refuseInstallerKey(args);
27
+ rejectUnknownFlags(args, LOGIN_FLAGS);
28
+ const env = deps.env ?? process.env;
29
+ const interactive = !boolFlag(args, 'yes') && isInteractive();
30
+ const dir = configDir(env);
31
+ // Before anything is asked: a password typed for a session that cannot be
32
+ // kept is a password typed for nothing.
33
+ assertOutsideRepository(dir);
34
+ const file = await readProfiles(dir);
35
+ const name = profileName(args, env) ?? file.current ?? FIRST_PROFILE;
36
+ const known = file.profiles[name];
37
+ const installation = await readConfig(deps.cwd);
38
+ const value = (flag, variable, remembered) => stringFlag(args, flag) ?? (env[variable]?.trim() || undefined) ?? remembered;
39
+ const supabaseUrl = value('supabase-url', IDENTITY_ENV.supabaseUrl, known?.supabase_url ?? installation?.project_url) ??
40
+ (interactive ? await askRequired('URL of the instance (https://<ref>.supabase.co)?') : undefined);
41
+ if (supabaseUrl === undefined)
42
+ throw new NotInteractiveError('the URL of the instance', '--supabase-url');
43
+ const anonKey = value('anon-key', IDENTITY_ENV.anonKey, known?.supabase_url === supabaseUrl ? known.anon_key : undefined) ??
44
+ (interactive ? await askRequired('Publishable (anon) key of the instance (Project Settings → API)?') : undefined);
45
+ if (anonKey === undefined)
46
+ throw new NotInteractiveError('the publishable (anon) key', '--anon-key');
47
+ refuseServiceRole(anonKey, stringFlag(args, 'anon-key') !== undefined ? '--anon-key' : IDENTITY_ENV.anonKey, 'apikey');
48
+ const email = value('email', IDENTITY_ENV.email, known?.email) ??
49
+ (interactive ? await askRequired('E-mail address?') : undefined);
50
+ if (email === undefined)
51
+ throw new NotInteractiveError('the e-mail address', '--email');
52
+ const password = stringFlag(args, 'password') ??
53
+ (env[IDENTITY_ENV.password] || undefined) ??
54
+ (interactive ? await askSecret(`Password for ${email}. It is sent to the instance and never written to disk:`) : undefined);
55
+ if (password === undefined || password.length === 0) {
56
+ throw new NotInteractiveError('the password', `--password, or ${IDENTITY_ENV.password}`);
57
+ }
58
+ heading('Signing in');
59
+ const instance = { supabaseUrl, anonKey };
60
+ const { session, user } = await signIn(fetchOf(deps), instance, email, password);
61
+ step(`signed in to ${supabaseUrl} as ${user.email ?? email}`);
62
+ // The company in use belongs to an instance and to a person. Signing in as
63
+ // somebody else, or somewhere else, is not a reason to keep it.
64
+ const sameBooks = known !== undefined && known.supabase_url === supabaseUrl && known.user_id === user.id;
65
+ const company = sameBooks ? known.company : undefined;
66
+ await writeSession(dir, name, session);
67
+ await writeProfiles(dir, {
68
+ current: name,
69
+ profiles: {
70
+ ...file.profiles,
71
+ [name]: {
72
+ supabase_url: supabaseUrl,
73
+ anon_key: anonKey,
74
+ email: user.email ?? email,
75
+ user_id: user.id,
76
+ ...(company === undefined ? {} : { company }),
77
+ },
78
+ },
79
+ });
80
+ step(`kept the session under the profile ${name}, in ${dir}`);
81
+ if (company === undefined)
82
+ note(dim('No company in use yet: `ekwo whoami` lists them, `ekwo use <company>` picks one.'));
83
+ setContext({ profile: name, instance: supabaseUrl, company: company ?? null });
84
+ setResult({
85
+ profile: name,
86
+ instance: { url: supabaseUrl },
87
+ user: { id: user.id, email: user.email ?? email },
88
+ company: company ?? null,
89
+ expiresAt: new Date(session.expires_at * 1000).toISOString(),
90
+ configDir: dir,
91
+ });
92
+ pairs([
93
+ ['profile', name],
94
+ ['user', user.email ?? email],
95
+ ['company', company?.name ?? dim('none in use')],
96
+ ]);
97
+ return 0;
98
+ }
99
+ export async function logoutCommand(args, deps = {}) {
100
+ rejectUnknownFlags(args, LOGOUT_FLAGS);
101
+ const env = deps.env ?? process.env;
102
+ const dir = configDir(env);
103
+ const file = await readProfiles(dir);
104
+ const name = profileName(args, env) ?? file.current;
105
+ const profile = name === undefined ? undefined : file.profiles[name];
106
+ heading('Signing out');
107
+ if (name === undefined || profile === undefined) {
108
+ skipped('nobody was signed in');
109
+ setResult({ profile: name ?? null, signedOut: false, revoked: false });
110
+ return 0;
111
+ }
112
+ const session = await readSession(dir, name);
113
+ // The instance is told, so the refresh token stops working there too; the
114
+ // local copy goes whether or not the instance could be reached.
115
+ const revoked = session === undefined
116
+ ? false
117
+ : await signOut(fetchOf(deps), { supabaseUrl: profile.supabase_url, anonKey: profile.anon_key }, session.access_token);
118
+ const signedOut = await forgetSession(dir, name);
119
+ if (signedOut)
120
+ step(`forgot the session of the profile ${name}`);
121
+ else
122
+ skipped(`the profile ${name} held no session`);
123
+ if (signedOut && !revoked)
124
+ note(dim('The instance could not be told; the session there ends on its own.'));
125
+ setResult({ profile: name, signedOut, revoked });
126
+ return 0;
127
+ }
128
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * `ekwo migrate` — bring an existing installation up to this release.
3
+ *
4
+ * It shows the gap before it closes it, so an operator sees what is about to
5
+ * run. The reference seeds are re-applied too: they are idempotent, and a new
6
+ * release that adds an account to a chart would otherwise leave every
7
+ * installation one row short.
8
+ *
9
+ * **The modules this release carries are migrated too, by default.** A module
10
+ * is a schema whose tables are empty and whose row level security is on until
11
+ * a company enables it, so there is nothing to ask before creating them — and
12
+ * a module whose schema is half there is the state nobody can reason about.
13
+ * `--no-modules` leaves them alone, which is also what to pass before running
14
+ * `supabase db push`: the Supabase CLI knows the socle's files and not a
15
+ * module's, so it would report them as history it has no file for.
16
+ */
17
+ import { type ParsedArgs } from '../args.js';
18
+ import { type CommandDeps } from '../context.js';
19
+ export declare const MIGRATE_FLAGS: readonly ["db-url", "db-password", "db-region", "project-ref", "supabase-url", "service-role-key", "skip-seeds", "no-modules", "yes"];
20
+ /**
21
+ * The line to print before a migration runs.
22
+ *
23
+ * There is no "down" migration in this repository and there never will be:
24
+ * undoing a schema change on a database holding a year of entries is a
25
+ * restore, not a script. Which makes the snapshot the only way back, and an
26
+ * operator who reads this after the fact has already not taken one.
27
+ */
28
+ export declare function snapshotRecommendation(): void;
29
+ export declare function migrateCommand(args: ParsedArgs, deps?: CommandDeps): Promise<number>;
30
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAgC,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAE3E,OAAO,EAAkC,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAWjF,eAAO,MAAM,aAAa,uIAAoE,CAAC;AAE/F;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAS7C;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2E9F"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * `ekwo migrate` — bring an existing installation up to this release.
3
+ *
4
+ * It shows the gap before it closes it, so an operator sees what is about to
5
+ * run. The reference seeds are re-applied too: they are idempotent, and a new
6
+ * release that adds an account to a chart would otherwise leave every
7
+ * installation one row short.
8
+ *
9
+ * **The modules this release carries are migrated too, by default.** A module
10
+ * is a schema whose tables are empty and whose row level security is on until
11
+ * a company enables it, so there is nothing to ask before creating them — and
12
+ * a module whose schema is half there is the state nobody can reason about.
13
+ * `--no-modules` leaves them alone, which is also what to pass before running
14
+ * `supabase db push`: the Supabase CLI knows the socle's files and not a
15
+ * module's, so it would report them as history it has no file for.
16
+ */
17
+ import { boolFlag, rejectUnknownFlags } from '../args.js';
18
+ import { migrationsDir, seedDir } from '../bundle.js';
19
+ import { CONNECTION_FLAGS, openDatabase } from '../context.js';
20
+ import { applyMigrations, listMigrations, migrationGap } from '../migrations.js';
21
+ import { applyModuleMigrations } from './module.js';
22
+ import { allModuleMigrations, listModules } from '../module/read.js';
23
+ import { isInteractive } from '../prompt.js';
24
+ import { applySeeds } from '../seeds.js';
25
+ import { schemaIsInstalled } from '../bootstrap.js';
26
+ import { syncSchemaVersion } from '../status.js';
27
+ import { setResult } from '../output.js';
28
+ import { bold, dim, heading, line, note, skipped, step, warn } from '../ui.js';
29
+ export const MIGRATE_FLAGS = [...CONNECTION_FLAGS, 'skip-seeds', 'no-modules', 'yes'];
30
+ /**
31
+ * The line to print before a migration runs.
32
+ *
33
+ * There is no "down" migration in this repository and there never will be:
34
+ * undoing a schema change on a database holding a year of entries is a
35
+ * restore, not a script. Which makes the snapshot the only way back, and an
36
+ * operator who reads this after the fact has already not taken one.
37
+ */
38
+ export function snapshotRecommendation() {
39
+ line();
40
+ warn(`Take a snapshot first. Migrations move forward only — there is no ${bold('down')} — so a ` +
41
+ 'restore is the way back.');
42
+ note(dim(' Supabase: Database → Backups, or `supabase db dump -f before-upgrade.sql`.'));
43
+ note(dim(' Self-hosted: `pg_dump` the database this connection points at.'));
44
+ line();
45
+ }
46
+ export async function migrateCommand(args, deps = {}) {
47
+ rejectUnknownFlags(args, MIGRATE_FLAGS);
48
+ const interactive = !boolFlag(args, 'yes') && isInteractive();
49
+ const { db } = await openDatabase(args, { interactive, connect: deps.connect });
50
+ try {
51
+ const migrations = await listMigrations(migrationsDir());
52
+ const modules = boolFlag(args, 'no-modules') ? [] : await listModules();
53
+ // A module's versions live in the same history, so they are not "unknown"
54
+ // — they are simply not the socle's. The gap is computed against both.
55
+ const gap = await migrationGap(db, [...migrations, ...allModuleMigrations(modules)]);
56
+ heading('Migrations');
57
+ note(dim(`${gap.applied.length} applied, ${gap.pending.length} pending`));
58
+ if (gap.unknown.length > 0) {
59
+ warn(`${gap.unknown.length} migration(s) in this database are not in this release — ` +
60
+ 'it was installed by a newer version. Upgrade the CLI before migrating.');
61
+ for (const version of gap.unknown)
62
+ note(dim(` ${version}`));
63
+ setResult({ applied: [], pending: gap.pending.map((m) => m.file), unknown: gap.unknown });
64
+ return 1;
65
+ }
66
+ const applied = [];
67
+ const seeds = [];
68
+ let moduleMigrations = 0;
69
+ let schemaVersion;
70
+ if (gap.pending.length === 0) {
71
+ skipped('nothing to apply');
72
+ }
73
+ else {
74
+ for (const migration of gap.pending)
75
+ note(dim(`pending ${migration.file}`));
76
+ snapshotRecommendation();
77
+ await applyMigrations(db, migrations, (migration) => {
78
+ applied.push(migration.file);
79
+ step(migration.file);
80
+ });
81
+ }
82
+ if (modules.length > 0) {
83
+ moduleMigrations = await applyModuleMigrations(db, modules, { heading: true });
84
+ }
85
+ if (!boolFlag(args, 'skip-seeds')) {
86
+ heading('Reference data');
87
+ await applySeeds(db, seedDir(), (seed) => {
88
+ seeds.push(seed.file);
89
+ step(seed.file);
90
+ });
91
+ note(dim('Seeds are idempotent; re-applying them adds what a new release added.'));
92
+ }
93
+ if (await schemaIsInstalled(db)) {
94
+ const version = await syncSchemaVersion(db);
95
+ schemaVersion = version;
96
+ if (version !== undefined) {
97
+ heading('Version');
98
+ step(`instance.schema_version is now ${version}`);
99
+ }
100
+ }
101
+ setResult({
102
+ alreadyApplied: gap.applied.length,
103
+ applied,
104
+ moduleMigrations,
105
+ seeds,
106
+ schemaVersion: schemaVersion ?? null,
107
+ });
108
+ line();
109
+ return 0;
110
+ }
111
+ finally {
112
+ await db.close();
113
+ }
114
+ }
115
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `ekwo module` — what is beside the socle, and which company holds it.
3
+ *
4
+ * ekwo module list what this release carries, and what the database holds
5
+ * ekwo module migrate [<code>] apply the migrations of the modules, and their pack seeds
6
+ * ekwo module enable <code> --company turn a module on for one company
7
+ * ekwo module disable <code> --company turn it off, unless the module says it holds data
8
+ *
9
+ * `enable` and `disable` go through `enable_module()` / `disable_module()`
10
+ * rather than writing `company_modules`: the guard lives in the function
11
+ * because the table has no write policy, and a CLI that went round it would be
12
+ * a CLI whose rule applies only to clients that respect it. That is the same
13
+ * reason `ekwo register` sets the request claim and calls the function.
14
+ */
15
+ import { type ParsedArgs } from '../args.js';
16
+ import { type CommandDeps } from '../context.js';
17
+ import { type EkwoModule } from '../module/read.js';
18
+ import { type SqlClient } from '../sql.js';
19
+ export declare const MODULE_FLAGS: readonly ["db-url", "db-password", "db-region", "project-ref", "supabase-url", "service-role-key", "company", "as-user", "settings", "yes"];
20
+ export declare function moduleCommand(args: ParsedArgs, deps?: CommandDeps): Promise<number>;
21
+ /**
22
+ * Applies every pending migration of the given modules, then their pack seeds.
23
+ *
24
+ * Shared with `ekwo migrate`, which runs it straight after the socle's — a
25
+ * module's tables existing is not the same as a company holding the module, so
26
+ * there is nothing to ask before creating them, and a schema whose migrations
27
+ * are half applied is the state nobody can reason about.
28
+ */
29
+ export declare function applyModuleMigrations(db: SqlClient, modules: readonly EkwoModule[], options?: {
30
+ heading?: boolean;
31
+ }): Promise<number>;
32
+ //# sourceMappingURL=module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/commands/module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAA8C,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzF,OAAO,EAAkC,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjF,OAAO,EAML,KAAK,UAAU,EAChB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAI1D,eAAO,MAAM,YAAY,6IAA0E,CAAC;AAEpG,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6B7F;AAkID;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,SAAS,EACb,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,OAAO,CAAC,MAAM,CAAC,CAyBjB"}
@@ -0,0 +1,285 @@
1
+ /**
2
+ * `ekwo module` — what is beside the socle, and which company holds it.
3
+ *
4
+ * ekwo module list what this release carries, and what the database holds
5
+ * ekwo module migrate [<code>] apply the migrations of the modules, and their pack seeds
6
+ * ekwo module enable <code> --company turn a module on for one company
7
+ * ekwo module disable <code> --company turn it off, unless the module says it holds data
8
+ *
9
+ * `enable` and `disable` go through `enable_module()` / `disable_module()`
10
+ * rather than writing `company_modules`: the guard lives in the function
11
+ * because the table has no write policy, and a CLI that went round it would be
12
+ * a CLI whose rule applies only to clients that respect it. That is the same
13
+ * reason `ekwo register` sets the request claim and calls the function.
14
+ */
15
+ import { rejectUnknownFlags, stringFlag, UsageError } from '../args.js';
16
+ import { seedDir } from '../bundle.js';
17
+ import { CONNECTION_FLAGS, openDatabase } from '../context.js';
18
+ import { applyMigrations, appliedVersions, ensureHistory } from '../migrations.js';
19
+ import { allModuleMigrations, exposeSchemaNote, listModules, moduleSeeds, readModule, } from '../module/read.js';
20
+ import { isInteractive } from '../prompt.js';
21
+ import { applySeed } from '../seeds.js';
22
+ import { asUser, first } from '../sql.js';
23
+ import { setResult } from '../output.js';
24
+ import { bold, cyan, dim, heading, line, note, skipped, step, table, warn } from '../ui.js';
25
+ export const MODULE_FLAGS = [...CONNECTION_FLAGS, 'company', 'as-user', 'settings', 'yes'];
26
+ export async function moduleCommand(args, deps = {}) {
27
+ rejectUnknownFlags(args, MODULE_FLAGS);
28
+ const action = args.positional[0];
29
+ if (action === undefined)
30
+ throw new UsageError(`name a subcommand\n${usage()}`);
31
+ if (action === 'help') {
32
+ line(usage());
33
+ return 0;
34
+ }
35
+ if (!['list', 'migrate', 'enable', 'disable'].includes(action)) {
36
+ throw new UsageError(`unknown subcommand: module ${action}\n${usage()}`);
37
+ }
38
+ const modules = await listModules();
39
+ const interactive = isInteractive();
40
+ const { db } = await openDatabase(args, { interactive, connect: deps.connect });
41
+ try {
42
+ switch (action) {
43
+ case 'list':
44
+ return await listCommand(db, modules);
45
+ case 'migrate':
46
+ return await migrateCommand(db, modules, args.positional[1]);
47
+ default:
48
+ return await toggleCommand(db, modules, args, action === 'enable');
49
+ }
50
+ }
51
+ finally {
52
+ await db.close();
53
+ }
54
+ }
55
+ async function listCommand(db, modules) {
56
+ const installed = await registry(db);
57
+ const byCode = new Map(installed.map((row) => [row.code, row]));
58
+ const strangers = installed.filter((row) => !modules.some((m) => m.manifest.code === row.code));
59
+ setResult({
60
+ modules: modules.map(({ manifest, migrations }) => {
61
+ const row = byCode.get(manifest.code);
62
+ return {
63
+ code: manifest.code,
64
+ name: manifest.name,
65
+ version: manifest.version,
66
+ schema: manifest.schema,
67
+ description: manifest.description ?? null,
68
+ migrations: migrations.length,
69
+ installed: row !== undefined,
70
+ installedVersion: row?.version ?? null,
71
+ status: row?.status ?? null,
72
+ companies: row?.companies ?? 0,
73
+ };
74
+ }),
75
+ notInThisRelease: strangers.map((row) => ({
76
+ code: row.code,
77
+ name: row.name,
78
+ version: row.version,
79
+ schema: row.schema_name,
80
+ })),
81
+ });
82
+ heading(`Modules (${modules.length} in this release)`);
83
+ if (modules.length === 0) {
84
+ note(dim('none — the socle stands on its own'));
85
+ return 0;
86
+ }
87
+ table([
88
+ { title: 'code' },
89
+ { title: 'name' },
90
+ { title: 'version' },
91
+ { title: 'schema' },
92
+ { title: 'migrations', align: 'right' },
93
+ { title: 'state' },
94
+ ], modules.map(({ manifest, migrations }) => {
95
+ const row = byCode.get(manifest.code);
96
+ return [
97
+ bold(manifest.code),
98
+ manifest.name,
99
+ manifest.version,
100
+ cyan(manifest.schema),
101
+ String(migrations.length),
102
+ row === undefined
103
+ ? dim('not installed — run `ekwo module migrate`')
104
+ : `${row.status}, ${row.companies} compan${row.companies === 1 ? 'y' : 'ies'}`,
105
+ ];
106
+ }));
107
+ line();
108
+ for (const { manifest } of modules) {
109
+ if (manifest.description !== undefined)
110
+ note(dim(`${manifest.code} — ${manifest.description}`));
111
+ }
112
+ for (const { manifest } of modules) {
113
+ const row = byCode.get(manifest.code);
114
+ if (row !== undefined && row.version !== manifest.version) {
115
+ warn(`${manifest.code}: the database holds ${row.version}, this release carries ${manifest.version}`);
116
+ }
117
+ }
118
+ if (strangers.length > 0) {
119
+ heading('Installed here, not in this release');
120
+ for (const row of strangers)
121
+ note(`${bold(row.code)} ${row.name} ${row.version} · schema ${row.schema_name}`);
122
+ }
123
+ line();
124
+ return 0;
125
+ }
126
+ async function registry(db) {
127
+ const exists = await first(db, `select to_regclass('public.modules') is not null as present`);
128
+ if (exists?.present !== true)
129
+ return [];
130
+ return db.query(`select m.code, m.name, m.schema_name, m.version, m.status::text as status,
131
+ (select count(*)::int from company_modules c where c.module_code = m.code) as companies
132
+ from modules m order by m.code`);
133
+ }
134
+ // ---------------------------------------------------------------- migrate
135
+ async function migrateCommand(db, modules, only) {
136
+ const wanted = only === undefined ? modules : [await readModule(only)];
137
+ if (wanted.length === 0) {
138
+ heading('Modules');
139
+ skipped('this release carries none');
140
+ setResult({ modules: [], applied: 0 });
141
+ return 0;
142
+ }
143
+ const applied = await applyModuleMigrations(db, wanted, { heading: true });
144
+ if (applied === 0)
145
+ skipped('nothing to apply');
146
+ setResult({ modules: wanted.map((m) => m.manifest.code), applied });
147
+ for (const module of wanted) {
148
+ heading(`${module.manifest.name}`);
149
+ for (const sentence of exposeSchemaNote(module.manifest.schema))
150
+ note(dim(sentence));
151
+ }
152
+ line();
153
+ return 0;
154
+ }
155
+ /**
156
+ * Applies every pending migration of the given modules, then their pack seeds.
157
+ *
158
+ * Shared with `ekwo migrate`, which runs it straight after the socle's — a
159
+ * module's tables existing is not the same as a company holding the module, so
160
+ * there is nothing to ask before creating them, and a schema whose migrations
161
+ * are half applied is the state nobody can reason about.
162
+ */
163
+ export async function applyModuleMigrations(db, modules, options = {}) {
164
+ const migrations = allModuleMigrations(modules);
165
+ if (migrations.length === 0)
166
+ return 0;
167
+ await ensureHistory(db);
168
+ const known = new Set(await appliedVersions(db));
169
+ const pending = migrations.filter((m) => !known.has(m.version));
170
+ if (options.heading === true) {
171
+ heading('Module migrations');
172
+ note(dim(`${migrations.length - pending.length} applied, ${pending.length} pending`));
173
+ }
174
+ const result = await applyMigrations(db, migrations, (migration) => {
175
+ step(`${migration.name} (${migration.file})`);
176
+ });
177
+ for (const module of modules) {
178
+ for (const path of await moduleSeeds(module.manifest.code, seedDir())) {
179
+ await applySeed(db, { file: path.split('/').at(-1), path });
180
+ step(dim(`${module.manifest.code}: ${path.split('/').at(-1)}`));
181
+ }
182
+ }
183
+ return result.applied.length;
184
+ }
185
+ // ------------------------------------------------------------ enable/disable
186
+ async function toggleCommand(db, modules, args, on) {
187
+ const code = args.positional[1];
188
+ if (code === undefined)
189
+ throw new UsageError(`name a module: ekwo module ${on ? 'enable' : 'disable'} <code>`);
190
+ const module = modules.find((m) => m.manifest.code === code);
191
+ if (module === undefined) {
192
+ throw new UsageError(`unknown module: ${code}. This release carries: ${modules.map((m) => m.manifest.code).join(', ') || 'none'}`);
193
+ }
194
+ const companyId = await resolveCompany(db, stringFlag(args, 'company'));
195
+ const actor = await resolveActor(db, stringFlag(args, 'as-user'), companyId);
196
+ const settings = stringFlag(args, 'settings');
197
+ if (on) {
198
+ await pendingCheck(db, module);
199
+ await asUser(db, actor, async () => {
200
+ await db.query(`select enable_module($1, $2, $3::jsonb)`, [companyId, code, settings ?? null]);
201
+ });
202
+ heading(`${module.manifest.name} enabled`);
203
+ step(`${code} is on for company ${companyId}`);
204
+ line();
205
+ for (const sentence of exposeSchemaNote(module.manifest.schema))
206
+ note(dim(sentence));
207
+ }
208
+ else {
209
+ await asUser(db, actor, async () => {
210
+ await db.query(`select disable_module($1, $2)`, [companyId, code]);
211
+ });
212
+ heading(`${module.manifest.name} disabled`);
213
+ step(`${code} is off for company ${companyId}. Nothing it wrote was deleted.`);
214
+ }
215
+ setResult({ module: code, schema: module.manifest.schema, companyId, actingAs: actor, enabled: on });
216
+ line();
217
+ return 0;
218
+ }
219
+ /**
220
+ * The socle migration a module needs has to have run, and the module's own
221
+ * too. Both are questions about the history, which the CLI holds and the
222
+ * database function deliberately does not — a project restored from a dump has
223
+ * the schema and not necessarily the history, and refusing *that* installation
224
+ * would be refusing the wrong thing.
225
+ */
226
+ async function pendingCheck(db, module) {
227
+ const known = new Set(await appliedVersions(db));
228
+ const min = module.manifest.requires_socle_min;
229
+ if (min !== undefined && known.size > 0 && !known.has(min)) {
230
+ throw new Error(`socle_too_old: ${module.manifest.code} needs socle migration ${min}, which this database has not run. ` +
231
+ 'Run `ekwo migrate` first.');
232
+ }
233
+ const pending = module.migrations.filter((m) => !known.has(m.version));
234
+ if (pending.length > 0 && known.size > 0) {
235
+ throw new Error(`module_not_migrated: ${module.manifest.code} has ${pending.length} migration(s) still to apply. ` +
236
+ 'Run `ekwo module migrate` first.');
237
+ }
238
+ }
239
+ async function resolveCompany(db, given) {
240
+ const companies = await db.query(`select id, name from companies order by name`);
241
+ if (given !== undefined) {
242
+ const match = companies.find((c) => c.id === given || c.name === given);
243
+ if (match === undefined) {
244
+ throw new UsageError(`unknown company: ${given}. This installation holds: ${companies.map((c) => c.name).join(', ') || 'none'}`);
245
+ }
246
+ return match.id;
247
+ }
248
+ const only = companies[0];
249
+ if (companies.length !== 1 || only === undefined) {
250
+ throw new UsageError(`--company is required: this installation holds ${companies.length} companies — ` +
251
+ companies.map((c) => `${c.name} (${c.id})`).join(', '));
252
+ }
253
+ return only.id;
254
+ }
255
+ /**
256
+ * Who the CLI acts for.
257
+ *
258
+ * `enable_module` refuses anyone who is not the owner of the company, and a
259
+ * superuser connection is nobody: `auth.uid()` is null and the guard would
260
+ * refuse the installer. So the claim is set the way PostgREST sets it, for an
261
+ * owner of that company — the rule is satisfied rather than circumvented.
262
+ */
263
+ async function resolveActor(db, given, companyId) {
264
+ if (given !== undefined)
265
+ return given;
266
+ const owner = await first(db, `select user_id from company_members where company_id = $1 and role = 'owner' order by created_at limit 1`, [companyId]);
267
+ if (owner === undefined) {
268
+ throw new Error(`no_company_owner: company ${companyId} has no owner to act for. Pass --as-user <uuid>.`);
269
+ }
270
+ return owner.user_id;
271
+ }
272
+ function usage() {
273
+ return `${bold('ekwo module')} — the modules beside the socle.
274
+
275
+ ekwo module list What this release carries and what the database holds.
276
+ ekwo module migrate [<code>] Apply module migrations and their country seeds.
277
+ ekwo module enable <code> --company X Turn a module on for one company.
278
+ ekwo module disable <code> --company X Turn it off. Nothing it wrote is deleted.
279
+
280
+ --company <id|name> Which company. Required unless the installation holds one.
281
+ --as-user <uuid> Act for this user. Defaults to an owner of the company.
282
+ --settings <json> Settings to store on the company, in the module's own vocabulary.
283
+ `;
284
+ }
285
+ //# sourceMappingURL=module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/commands/module.ts"],"names":[],"mappings":"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"}