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.
- package/README.md +873 -0
- package/dist/args.d.ts +57 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +134 -0
- package/dist/args.js.map +1 -0
- package/dist/assets/expected-objects.json +9432 -0
- package/dist/assets/migrations/20260911120000_core_companies.sql +260 -0
- package/dist/assets/migrations/20260911120100_accounts_journals.sql +211 -0
- package/dist/assets/migrations/20260911120200_contacts.sql +90 -0
- package/dist/assets/migrations/20260911120300_taxes.sql +146 -0
- package/dist/assets/migrations/20260911120400_entries.sql +338 -0
- package/dist/assets/migrations/20260911120500_documents.sql +279 -0
- package/dist/assets/migrations/20260911120600_payments_reconciliation.sql +251 -0
- package/dist/assets/migrations/20260911120700_bank.sql +178 -0
- package/dist/assets/migrations/20260911120800_analytics_attachments.sql +128 -0
- package/dist/assets/migrations/20260911120900_post_document.sql +279 -0
- package/dist/assets/migrations/20260911121000_reporting.sql +235 -0
- package/dist/assets/migrations/20260911121100_country_templates.sql +226 -0
- package/dist/assets/migrations/20260911121200_fec.sql +71 -0
- package/dist/assets/migrations/20260911130000_instance.sql +77 -0
- package/dist/assets/migrations/20260911130100_instance_members.sql +224 -0
- package/dist/assets/migrations/20260911140000_instance_admins.sql +112 -0
- package/dist/assets/migrations/20260911160000_tax_posting_templates_unique.sql +17 -0
- package/dist/assets/migrations/20260911170000_document_amount_paid.sql +82 -0
- package/dist/assets/migrations/20260911173000_post_payment.sql +122 -0
- package/dist/assets/migrations/20260911173100_sequence_counters_under_rls.sql +84 -0
- package/dist/assets/migrations/20260911183000_country_journal_defaults.sql +143 -0
- package/dist/assets/migrations/20260911193853_line_account_defaults.sql +274 -0
- package/dist/assets/migrations/20260911195054_products.sql +221 -0
- package/dist/assets/migrations/20260911210131_anon_surface.sql +85 -0
- package/dist/assets/migrations/20260912074712_country_packs.sql +318 -0
- package/dist/assets/migrations/20260912080311_report_code_and_region.sql +198 -0
- package/dist/assets/migrations/20260912081014_pack_certification_maintained.sql +31 -0
- package/dist/assets/migrations/20260912081015_pack_certification_backfill.sql +16 -0
- package/dist/assets/migrations/20260912090407_tax_report_boxes.sql +329 -0
- package/dist/assets/migrations/20260912091917_tax_on_base_value.sql +25 -0
- package/dist/assets/migrations/20260912091918_tax_engine_columns.sql +776 -0
- package/dist/assets/migrations/20260912094412_opening_and_closing.sql +759 -0
- package/dist/assets/migrations/20260912095825_charts_of_accounts.sql +326 -0
- package/dist/assets/migrations/20260912100412_financial_statements.sql +632 -0
- package/dist/assets/migrations/20260912104719_one_formula_evaluator.sql +209 -0
- package/dist/assets/migrations/20260912105720_entry_kind_appropriation.sql +26 -0
- package/dist/assets/migrations/20260912105721_appropriation_entry_kind.sql +444 -0
- package/dist/assets/migrations/20260912111751_document_rules.sql +274 -0
- package/dist/assets/migrations/20260912112132_cash_basis_vat_and_fx.sql +1189 -0
- package/dist/assets/migrations/20260913074512_modules.sql +493 -0
- package/dist/assets/migrations/20260913075903_asset_disposal_roles.sql +47 -0
- package/dist/assets/migrations/20260913083216_capabilities.sql +637 -0
- package/dist/assets/migrations/20260913083901_company_invitations.sql +262 -0
- package/dist/assets/migrations/20260913084402_user_preferences.sql +376 -0
- package/dist/assets/migrations/20260913084847_company_profile.sql +261 -0
- package/dist/assets/migrations/20260913085436_numbering_reads_the_pack.sql +235 -0
- package/dist/assets/migrations/20260913085932_api_keys.sql +303 -0
- package/dist/assets/migrations/20260913090216_fiscal_year_bounds.sql +159 -0
- package/dist/assets/migrations/20260913092527_entries_import.sql +219 -0
- package/dist/assets/migrations/20260913101536_null_safe_guards.sql +188 -0
- package/dist/assets/migrations/20260913102115_installer_is_named.sql +462 -0
- package/dist/assets/migrations/20260913102758_no_currency_default.sql +138 -0
- package/dist/assets/migrations/20260913103355_cash_basis_needs_a_box.sql +453 -0
- package/dist/assets/migrations/20260913104014_aged_balance_named_group.sql +79 -0
- package/dist/assets/migrations/20260913104232_foreign_key_indexes.sql +144 -0
- package/dist/assets/migrations/20260913105120_declared_no_reader.sql +41 -0
- package/dist/assets/migrations/20260913111407_pack_languages.sql +223 -0
- package/dist/assets/migrations/20260913112233_schema_comments_for_a_reader.sql +27 -0
- package/dist/assets/migrations/20260913114535_fec_opening_balances.sql +307 -0
- package/dist/assets/migrations/20260914103412_audit_log.sql +509 -0
- package/dist/assets/migrations/20260914111907_pack_upgrade.sql +428 -0
- package/dist/assets/migrations/20260914120500_rounding_reads_the_currency.sql +206 -0
- package/dist/assets/migrations/20260914121200_amounts_round_at_the_currency.sql +2403 -0
- package/dist/assets/migrations/20260914134325_schema_version_0_2_0.sql +36 -0
- package/dist/assets/migrations/20260914143915_accounts_in_use.sql +428 -0
- package/dist/assets/migrations/20260914144731_account_code_frozen.sql +99 -0
- package/dist/assets/migrations/20260914151207_schema_grants_its_own_rights.sql +284 -0
- package/dist/assets/migrations/20260914152840_pack_upgrade_records_its_own_line.sql +237 -0
- package/dist/assets/migrations/20260914163943_declaration_periodicity.sql +349 -0
- package/dist/assets/migrations/20260915094000_foreign_services_received.sql +37 -0
- package/dist/assets/migrations/20260915094500_mentions_read_a_foreign_service.sql +72 -0
- package/dist/assets/migrations/20260915153000_document_shares.sql +568 -0
- package/dist/assets/migrations/20260915160000_ec_sales_list.sql +181 -0
- package/dist/assets/migrations/20260915161842_pack_sources.sql +56 -0
- package/dist/assets/migrations/20260915170500_schema_version_0_3_0.sql +45 -0
- package/dist/assets/migrations/20260915174500_a_vat_category_is_a_code.sql +177 -0
- package/dist/assets/migrations/20260915180000_document_rule_references.sql +85 -0
- package/dist/assets/migrations/20260915181000_territories.sql +342 -0
- package/dist/assets/migrations/20260915181500_ec_sales_list_reads_the_territories.sql +222 -0
- package/dist/assets/migrations/20260915182000_intracom_triangular.sql +53 -0
- package/dist/assets/migrations/20260915182500_a_triangular_supply_says_reverse_charge.sql +99 -0
- package/dist/assets/migrations/20260915191200_a_document_knows_its_language.sql +633 -0
- package/dist/assets/migrations/20260915195000_a_price_that_holds_its_tax.sql +649 -0
- package/dist/assets/migrations/20260915200000_a_posting_names_its_boxes.sql +1004 -0
- package/dist/assets/migrations/20260916094500_a_company_files_more_than_one_declaration.sql +795 -0
- package/dist/assets/migrations/20260916103000_a_ledger_line_names_its_posting.sql +902 -0
- package/dist/assets/migrations/20260916123000_a_vocabulary_for_a_tax_that_is_not_a_vat.sql +144 -0
- package/dist/assets/migrations/20260916124000_a_box_can_be_a_rate_of_a_box.sql +525 -0
- package/dist/assets/migrations/20260916125000_a_tax_follows_the_territory.sql +1318 -0
- package/dist/assets/migrations/20260916126000_a_tax_point_and_its_exception.sql +1211 -0
- package/dist/assets/migrations/20260917090000_a_counterparty_that_learns.sql +561 -0
- package/dist/assets/migrations/20260917120000_what_the_money_pays.sql +545 -0
- package/dist/assets/migrations/20260917150000_a_filing_is_a_row.sql +488 -0
- package/dist/assets/migrations/20260917170000_when_it_is_due.sql +194 -0
- package/dist/assets/migrations/20260917180000_a_box_is_a_number_and_a_kind.sql +213 -0
- package/dist/assets/migrations/20260917190000_what_a_declaration_owes.sql +486 -0
- package/dist/assets/migrations/20260917200000_what_moved_after_it_went.sql +227 -0
- package/dist/assets/migrations/20260918090000_a_form_names_its_file.sql +27 -0
- package/dist/assets/migrations/20260918110000_a_deposit_and_what_came_back.sql +286 -0
- package/dist/assets/migrations/20260918113741_a_fourth_preset_is_named.sql +9 -0
- package/dist/assets/migrations/20260918113807_a_client_reads_and_hands_over.sql +96 -0
- package/dist/assets/migrations/20260918114322_two_definer_functions_check_their_caller.sql +75 -0
- package/dist/assets/migrations/20260918130000_every_company_somebody_keeps.sql +177 -0
- package/dist/assets/migrations/20260918140000_a_session_nobody_prepared.sql +40 -0
- package/dist/assets/migrations/20260918141107_a_line_keeps_the_tax_it_was_posted_with.sql +256 -0
- package/dist/assets/migrations/20260918141342_a_company_has_an_electronic_address.sql +66 -0
- package/dist/assets/migrations/20260918141605_an_invoice_reads_whole_from_the_views.sql +313 -0
- package/dist/assets/migrations/20260918141627_a_policy_asks_once.sql +132 -0
- package/dist/assets/migrations/20260918143352_a_suggestion_reads_the_words_once.sql +204 -0
- package/dist/assets/migrations/20260918143417_a_reference_of_the_caller_and_a_rehearsal.sql +115 -0
- package/dist/assets/migrations/20260918150712_a_company_leaves_with_its_books.sql +1119 -0
- package/dist/assets/migrations/20260918150931_a_statement_is_imported_once.sql +654 -0
- package/dist/assets/migrations/20260918161204_a_posted_document_does_not_move.sql +437 -0
- package/dist/assets/migrations/20260918161538_a_posted_entry_does_not_move.sql +252 -0
- package/dist/assets/migrations/20260918171946_an_entry_is_posted_by_post_entry.sql +289 -0
- package/dist/assets/migrations/20260918174312_schema_version_0_4_0.sql +53 -0
- package/dist/assets/modules/assets/module.json +13 -0
- package/dist/assets/modules/assets/supabase/migrations/20260913081447_assets.sql +1190 -0
- package/dist/assets/modules/assets/supabase/migrations/20260913104234_foreign_key_indexes.sql +47 -0
- package/dist/assets/modules/assets/supabase/migrations/20260913104500_assets_capabilities.sql +145 -0
- package/dist/assets/modules/assets/supabase/migrations/20260914122100_assets_round_at_the_currency.sql +564 -0
- package/dist/assets/modules/assets/supabase/migrations/20260914145012_assets_accounts_in_use.sql +37 -0
- package/dist/assets/modules/assets/supabase/migrations/20260914151530_assets_grants_its_own_rights.sql +63 -0
- package/dist/assets/modules/assets/supabase/migrations/20260918113912_assets_client_reads.sql +20 -0
- package/dist/assets/modules/assets/supabase/migrations/20260918150801_assets_leave_with_the_company.sql +41 -0
- package/dist/assets/modules/budgets/module.json +12 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260913083012_budgets.sql +210 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260913104233_foreign_key_indexes.sql +37 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260913104501_budgets_capabilities.sql +72 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260914122400_budgets_round_at_the_currency.sql +68 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260914145048_budgets_accounts_in_use.sql +30 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260914151812_budgets_grants_its_own_rights.sql +31 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260918113954_budgets_client_reads.sql +20 -0
- package/dist/assets/modules/budgets/supabase/migrations/20260918150823_budgets_leave_with_the_company.sql +37 -0
- package/dist/assets/modules/schema/module.1.json +69 -0
- package/dist/assets/seed/00_currencies.sql +15 -0
- package/dist/assets/seed/00_territories.sql +280 -0
- package/dist/assets/seed/05_framework_generic.sql +110 -0
- package/dist/assets/seed/10_pack_be.sql +1284 -0
- package/dist/assets/seed/11_pack_fr.sql +1112 -0
- package/dist/assets/seed/12_pack_lu.sql +2484 -0
- package/dist/assets/seed/13_pack_ee.sql +733 -0
- package/dist/assets/seed/14_pack_gb.sql +796 -0
- package/dist/assets/seed/15_pack_us.sql +751 -0
- package/dist/assets/seed/90_demo_company.sql +368 -0
- package/dist/assets/seed/modules/assets/10_pack_be.sql +58 -0
- package/dist/assets/seed/modules/assets/11_pack_fr.sql +57 -0
- package/dist/assets/seed/modules/assets/14_pack_gb.sql +58 -0
- package/dist/assets/seed/modules/assets/15_pack_us.sql +60 -0
- package/dist/auth.d.ts +59 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +134 -0
- package/dist/auth.js.map +1 -0
- package/dist/bin.d.ts +6 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +8 -0
- package/dist/bin.js.map +1 -0
- package/dist/books.d.ts +60 -0
- package/dist/books.d.ts.map +1 -0
- package/dist/books.js +168 -0
- package/dist/books.js.map +1 -0
- package/dist/bootstrap.d.ts +236 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +459 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/bundle.d.ts +27 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +47 -0
- package/dist/bundle.js.map +1 -0
- package/dist/checklist.d.ts +35 -0
- package/dist/checklist.d.ts.map +1 -0
- package/dist/checklist.js +64 -0
- package/dist/checklist.js.map +1 -0
- package/dist/cli.d.ts +14 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +318 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/company.d.ts +59 -0
- package/dist/commands/company.d.ts.map +1 -0
- package/dist/commands/company.js +287 -0
- package/dist/commands/company.js.map +1 -0
- package/dist/commands/contact.d.ts +9 -0
- package/dist/commands/contact.d.ts.map +1 -0
- package/dist/commands/contact.js +82 -0
- package/dist/commands/contact.js.map +1 -0
- package/dist/commands/demo.d.ts +19 -0
- package/dist/commands/demo.d.ts.map +1 -0
- package/dist/commands/demo.js +72 -0
- package/dist/commands/demo.js.map +1 -0
- package/dist/commands/doctor.d.ts +12 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +68 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/document.d.ts +17 -0
- package/dist/commands/document.d.ts.map +1 -0
- package/dist/commands/document.js +217 -0
- package/dist/commands/document.js.map +1 -0
- package/dist/commands/init.d.ts +31 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +535 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +24 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +128 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/migrate.d.ts +30 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +115 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/module.d.ts +32 -0
- package/dist/commands/module.d.ts.map +1 -0
- package/dist/commands/module.js +285 -0
- package/dist/commands/module.js.map +1 -0
- package/dist/commands/pack.d.ts +22 -0
- package/dist/commands/pack.d.ts.map +1 -0
- package/dist/commands/pack.js +481 -0
- package/dist/commands/pack.js.map +1 -0
- package/dist/commands/payment.d.ts +15 -0
- package/dist/commands/payment.d.ts.map +1 -0
- package/dist/commands/payment.js +97 -0
- package/dist/commands/payment.js.map +1 -0
- package/dist/commands/register.d.ts +20 -0
- package/dist/commands/register.d.ts.map +1 -0
- package/dist/commands/register.js +134 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/status.d.ts +8 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +134 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/whoami.d.ts +21 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +133 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/company.d.ts +16 -0
- package/dist/company.d.ts.map +1 -0
- package/dist/company.js +26 -0
- package/dist/company.js.map +1 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +50 -0
- package/dist/config.js.map +1 -0
- package/dist/connection.d.ts +79 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/connection.js +116 -0
- package/dist/connection.js.map +1 -0
- package/dist/context.d.ts +47 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +93 -0
- package/dist/context.js.map +1 -0
- package/dist/doctor.d.ts +45 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +448 -0
- package/dist/doctor.js.map +1 -0
- package/dist/grants.d.ts +88 -0
- package/dist/grants.d.ts.map +1 -0
- package/dist/grants.js +174 -0
- package/dist/grants.js.map +1 -0
- package/dist/identity.d.ts +54 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +132 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/inventory.d.ts +155 -0
- package/dist/inventory.d.ts.map +1 -0
- package/dist/inventory.js +303 -0
- package/dist/inventory.js.map +1 -0
- package/dist/migrations.d.ts +76 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +226 -0
- package/dist/migrations.js.map +1 -0
- package/dist/module/read.d.ts +91 -0
- package/dist/module/read.d.ts.map +1 -0
- package/dist/module/read.js +172 -0
- package/dist/module/read.js.map +1 -0
- package/dist/output.d.ts +110 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +173 -0
- package/dist/output.js.map +1 -0
- package/dist/pack/certification.d.ts +27 -0
- package/dist/pack/certification.d.ts.map +1 -0
- package/dist/pack/certification.js +38 -0
- package/dist/pack/certification.js.map +1 -0
- package/dist/pack/compile.d.ts +75 -0
- package/dist/pack/compile.d.ts.map +1 -0
- package/dist/pack/compile.js +801 -0
- package/dist/pack/compile.js.map +1 -0
- package/dist/pack/filing.d.ts +48 -0
- package/dist/pack/filing.d.ts.map +1 -0
- package/dist/pack/filing.js +56 -0
- package/dist/pack/filing.js.map +1 -0
- package/dist/pack/read.d.ts +766 -0
- package/dist/pack/read.d.ts.map +1 -0
- package/dist/pack/read.js +2336 -0
- package/dist/pack/read.js.map +1 -0
- package/dist/pack/schema.d.ts +26 -0
- package/dist/pack/schema.d.ts.map +1 -0
- package/dist/pack/schema.js +181 -0
- package/dist/pack/schema.js.map +1 -0
- package/dist/pack/territories.d.ts +98 -0
- package/dist/pack/territories.d.ts.map +1 -0
- package/dist/pack/territories.js +0 -0
- package/dist/pack/territories.js.map +1 -0
- package/dist/pack/upgrade.d.ts +86 -0
- package/dist/pack/upgrade.d.ts.map +1 -0
- package/dist/pack/upgrade.js +76 -0
- package/dist/pack/upgrade.js.map +1 -0
- package/dist/pack/vat-codes.d.ts +273 -0
- package/dist/pack/vat-codes.d.ts.map +1 -0
- package/dist/pack/vat-codes.js +513 -0
- package/dist/pack/vat-codes.js.map +1 -0
- package/dist/profiles.d.ts +67 -0
- package/dist/profiles.d.ts.map +1 -0
- package/dist/profiles.js +187 -0
- package/dist/profiles.js.map +1 -0
- package/dist/prompt.d.ts +40 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +120 -0
- package/dist/prompt.js.map +1 -0
- package/dist/registry.d.ts +84 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +104 -0
- package/dist/registry.js.map +1 -0
- package/dist/rest.d.ts +81 -0
- package/dist/rest.d.ts.map +1 -0
- package/dist/rest.js +245 -0
- package/dist/rest.js.map +1 -0
- package/dist/schema.d.ts +15 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +15 -0
- package/dist/schema.js.map +1 -0
- package/dist/seeds.d.ts +27 -0
- package/dist/seeds.d.ts.map +1 -0
- package/dist/seeds.js +47 -0
- package/dist/seeds.js.map +1 -0
- package/dist/session.d.ts +39 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +92 -0
- package/dist/session.js.map +1 -0
- package/dist/sql.d.ts +48 -0
- package/dist/sql.d.ts.map +1 -0
- package/dist/sql.js +112 -0
- package/dist/sql.js.map +1 -0
- package/dist/status.d.ts +94 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +120 -0
- package/dist/status.js.map +1 -0
- package/dist/ui.d.ts +55 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +114 -0
- package/dist/ui.js.map +1 -0
- package/package.json +29 -0
- package/schema/output.1.json +613 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The migration runner.
|
|
3
|
+
*
|
|
4
|
+
* It applies `supabase/migrations/*.sql` in filename order and records what
|
|
5
|
+
* it did in `supabase_migrations.schema_migrations`, **in the format the
|
|
6
|
+
* Supabase CLI uses** — same schema, same table, same three columns, version
|
|
7
|
+
* being the timestamp prefix of the filename. That is the whole point: an
|
|
8
|
+
* installation set up with `ekwo init` can later be pushed to with
|
|
9
|
+
* `supabase db push`, and one set up with `supabase db push` can be brought
|
|
10
|
+
* forward with `ekwo migrate`. The two are interchangeable because they read
|
|
11
|
+
* and write the same history.
|
|
12
|
+
*
|
|
13
|
+
* Each file is applied inside one transaction together with its history row,
|
|
14
|
+
* so a migration that fails halfway leaves neither half-applied schema nor a
|
|
15
|
+
* history row that lies. Re-running resumes at the file that failed.
|
|
16
|
+
*/
|
|
17
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
18
|
+
import { join } from 'node:path';
|
|
19
|
+
const FILE_PATTERN = /^(\d{14})_(.+)\.sql$/;
|
|
20
|
+
/** Parses a migration filename, or returns `undefined` if it is not one. */
|
|
21
|
+
export function parseMigrationFile(file) {
|
|
22
|
+
const match = FILE_PATTERN.exec(file);
|
|
23
|
+
if (match === null)
|
|
24
|
+
return undefined;
|
|
25
|
+
const [, version, name] = match;
|
|
26
|
+
if (version === undefined || name === undefined)
|
|
27
|
+
return undefined;
|
|
28
|
+
return { version, name, file };
|
|
29
|
+
}
|
|
30
|
+
/** Every migration in `dir`, in the order they must be applied. */
|
|
31
|
+
export async function listMigrations(dir) {
|
|
32
|
+
const files = (await readdir(dir)).filter((f) => f.endsWith('.sql')).sort();
|
|
33
|
+
const migrations = [];
|
|
34
|
+
for (const file of files) {
|
|
35
|
+
const parsed = parseMigrationFile(file);
|
|
36
|
+
if (parsed === undefined) {
|
|
37
|
+
throw new Error(`migration_name_invalid: ${file} — expected YYYYMMDDHHMMSS_subject.sql`);
|
|
38
|
+
}
|
|
39
|
+
migrations.push({ ...parsed, path: join(dir, file) });
|
|
40
|
+
}
|
|
41
|
+
return migrations;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The history table, created exactly as the Supabase CLI creates it.
|
|
45
|
+
*
|
|
46
|
+
* The columns are added one by one with `if not exists`, so this is safe on a
|
|
47
|
+
* project the Supabase CLI has already touched, whichever version of it.
|
|
48
|
+
*/
|
|
49
|
+
export async function ensureHistory(db) {
|
|
50
|
+
await db.exec(`
|
|
51
|
+
create schema if not exists supabase_migrations;
|
|
52
|
+
create table if not exists supabase_migrations.schema_migrations (
|
|
53
|
+
version text not null primary key
|
|
54
|
+
);
|
|
55
|
+
alter table supabase_migrations.schema_migrations
|
|
56
|
+
add column if not exists statements text[];
|
|
57
|
+
alter table supabase_migrations.schema_migrations
|
|
58
|
+
add column if not exists name text;
|
|
59
|
+
`);
|
|
60
|
+
}
|
|
61
|
+
/** Versions already recorded, oldest first. */
|
|
62
|
+
export async function appliedVersions(db) {
|
|
63
|
+
const rows = await db.query('select version from supabase_migrations.schema_migrations order by version');
|
|
64
|
+
return rows.map((r) => r.version);
|
|
65
|
+
}
|
|
66
|
+
/** What separates the database from the migrations this CLI carries. */
|
|
67
|
+
export async function migrationGap(db, all) {
|
|
68
|
+
await ensureHistory(db);
|
|
69
|
+
const applied = await appliedVersions(db);
|
|
70
|
+
const appliedSet = new Set(applied);
|
|
71
|
+
const shipped = new Set(all.map((m) => m.version));
|
|
72
|
+
return {
|
|
73
|
+
applied,
|
|
74
|
+
pending: all.filter((m) => !appliedSet.has(m.version)),
|
|
75
|
+
unknown: applied.filter((v) => !shipped.has(v)),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Applies one migration and records it, atomically.
|
|
80
|
+
*
|
|
81
|
+
* The file is sent as a single command string, so Postgres runs it as one
|
|
82
|
+
* unit inside the transaction we opened. No file in this repository opens a
|
|
83
|
+
* transaction of its own, and none may: the runner owns that.
|
|
84
|
+
*/
|
|
85
|
+
export async function applyMigration(db, migration) {
|
|
86
|
+
const sql = await readFile(migration.path, 'utf8');
|
|
87
|
+
const statements = splitStatements(sql);
|
|
88
|
+
await db.transaction(async (tx) => {
|
|
89
|
+
await tx.exec(sql);
|
|
90
|
+
await tx.query(`insert into supabase_migrations.schema_migrations (version, name, statements)
|
|
91
|
+
values ($1, $2, $3)
|
|
92
|
+
on conflict (version) do nothing`, [migration.version, migration.name, statements]);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/** Applies every pending migration, in order, reporting each one as it lands. */
|
|
96
|
+
export async function applyMigrations(db, all, onApplied) {
|
|
97
|
+
const gap = await migrationGap(db, all);
|
|
98
|
+
for (const migration of gap.pending) {
|
|
99
|
+
await applyMigration(db, migration);
|
|
100
|
+
onApplied?.(migration);
|
|
101
|
+
}
|
|
102
|
+
return { applied: gap.pending, alreadyApplied: gap.applied.length };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Splits a SQL file into statements, for the `statements` column only.
|
|
106
|
+
*
|
|
107
|
+
* Execution never goes through this: the file is handed to Postgres whole.
|
|
108
|
+
* The column is what `supabase migration repair` and `supabase db diff` read
|
|
109
|
+
* back, so it should hold statements rather than one blob — but a mistake
|
|
110
|
+
* here can only make that column less pretty, never break an installation.
|
|
111
|
+
*
|
|
112
|
+
* Handles line and block comments, single- and double-quoted literals,
|
|
113
|
+
* `E''` backslash escapes and dollar quoting with tags, which is what the
|
|
114
|
+
* function bodies in this schema are made of.
|
|
115
|
+
*/
|
|
116
|
+
export function splitStatements(sql) {
|
|
117
|
+
const statements = [];
|
|
118
|
+
let current = '';
|
|
119
|
+
let index = 0;
|
|
120
|
+
const push = () => {
|
|
121
|
+
const trimmed = current.trim();
|
|
122
|
+
if (trimmed.length > 0)
|
|
123
|
+
statements.push(trimmed);
|
|
124
|
+
current = '';
|
|
125
|
+
};
|
|
126
|
+
while (index < sql.length) {
|
|
127
|
+
const char = sql[index];
|
|
128
|
+
const next = sql[index + 1];
|
|
129
|
+
// Line comment.
|
|
130
|
+
if (char === '-' && next === '-') {
|
|
131
|
+
const end = sql.indexOf('\n', index);
|
|
132
|
+
const stop = end === -1 ? sql.length : end;
|
|
133
|
+
current += sql.slice(index, stop);
|
|
134
|
+
index = stop;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
// Block comment, which nests in Postgres.
|
|
138
|
+
if (char === '/' && next === '*') {
|
|
139
|
+
let depth = 0;
|
|
140
|
+
const start = index;
|
|
141
|
+
while (index < sql.length) {
|
|
142
|
+
if (sql[index] === '/' && sql[index + 1] === '*') {
|
|
143
|
+
depth += 1;
|
|
144
|
+
index += 2;
|
|
145
|
+
}
|
|
146
|
+
else if (sql[index] === '*' && sql[index + 1] === '/') {
|
|
147
|
+
depth -= 1;
|
|
148
|
+
index += 2;
|
|
149
|
+
if (depth === 0)
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
index += 1;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
current += sql.slice(start, index);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
// Dollar-quoted string: $$ … $$ or $tag$ … $tag$.
|
|
160
|
+
if (char === '$') {
|
|
161
|
+
const tag = DOLLAR_TAG.exec(sql.slice(index));
|
|
162
|
+
if (tag !== null) {
|
|
163
|
+
const marker = tag[0];
|
|
164
|
+
const end = sql.indexOf(marker, index + marker.length);
|
|
165
|
+
const stop = end === -1 ? sql.length : end + marker.length;
|
|
166
|
+
current += sql.slice(index, stop);
|
|
167
|
+
index = stop;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Single-quoted literal. Backslash escapes only after E''.
|
|
172
|
+
if (char === "'") {
|
|
173
|
+
const escaped = /[eE]$/.test(current);
|
|
174
|
+
const start = index;
|
|
175
|
+
index += 1;
|
|
176
|
+
while (index < sql.length) {
|
|
177
|
+
if (escaped && sql[index] === BACKSLASH) {
|
|
178
|
+
index += 2;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (sql[index] === "'") {
|
|
182
|
+
if (sql[index + 1] === "'") {
|
|
183
|
+
index += 2;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
index += 1;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
index += 1;
|
|
190
|
+
}
|
|
191
|
+
current += sql.slice(start, index);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
// Quoted identifier.
|
|
195
|
+
if (char === '"') {
|
|
196
|
+
const start = index;
|
|
197
|
+
index += 1;
|
|
198
|
+
while (index < sql.length) {
|
|
199
|
+
if (sql[index] === '"') {
|
|
200
|
+
if (sql[index + 1] === '"') {
|
|
201
|
+
index += 2;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
index += 1;
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
index += 1;
|
|
208
|
+
}
|
|
209
|
+
current += sql.slice(start, index);
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
if (char === ';') {
|
|
213
|
+
current += char;
|
|
214
|
+
push();
|
|
215
|
+
index += 1;
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
current += char;
|
|
219
|
+
index += 1;
|
|
220
|
+
}
|
|
221
|
+
push();
|
|
222
|
+
return statements;
|
|
223
|
+
}
|
|
224
|
+
const DOLLAR_TAG = /^\$[A-Za-z_][A-Za-z0-9_]*\$|^\$\$/;
|
|
225
|
+
const BACKSLASH = String.fromCharCode(92);
|
|
226
|
+
//# sourceMappingURL=migrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The modules this checkout — or this published package — carries.
|
|
3
|
+
*
|
|
4
|
+
* A module is a folder: a manifest, a `supabase/migrations/` of its own, a
|
|
5
|
+
* README and its tests. There is no registry in code here either: the folders
|
|
6
|
+
* are the list, `module.json` is what each one says about itself, and
|
|
7
|
+
* `public.modules` is what the database holds once its migrations have run.
|
|
8
|
+
*
|
|
9
|
+
* Nothing in this file talks to a database. Reading and validating a manifest
|
|
10
|
+
* is the same work whether the next step is `ekwo module list` in a checkout
|
|
11
|
+
* or `ekwo migrate` against a Supabase project, so it is done once, here.
|
|
12
|
+
*/
|
|
13
|
+
import { type Migration } from '../migrations.js';
|
|
14
|
+
export declare class ModuleError extends Error {
|
|
15
|
+
}
|
|
16
|
+
export interface ModuleMcp {
|
|
17
|
+
prefix: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ModulePack {
|
|
20
|
+
/** `assets` → a country pack may carry `packs/<cc>/assets.json`. */
|
|
21
|
+
section: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ModuleManifest {
|
|
24
|
+
code: string;
|
|
25
|
+
name: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
schema: string;
|
|
28
|
+
version: string;
|
|
29
|
+
status: 'draft' | 'available' | 'deprecated';
|
|
30
|
+
requires_socle_min?: string;
|
|
31
|
+
posts?: boolean;
|
|
32
|
+
mcp?: ModuleMcp;
|
|
33
|
+
pack?: ModulePack;
|
|
34
|
+
}
|
|
35
|
+
export interface EkwoModule {
|
|
36
|
+
manifest: ModuleManifest;
|
|
37
|
+
/** Absolute path of `modules/<code>/`. */
|
|
38
|
+
dir: string;
|
|
39
|
+
/** Its own migrations, in the order they must be applied. */
|
|
40
|
+
migrations: Migration[];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Where the modules live.
|
|
44
|
+
*
|
|
45
|
+
* Published package: `dist/assets/modules/`, put there at build time by
|
|
46
|
+
* `scripts/copy-assets.mjs`, because `npx ekwo-os migrate` has no clone. Checkout:
|
|
47
|
+
* `<repo>/modules/`. The two candidates mirror `resolveBundleDir()`.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveModulesDir(): string | undefined;
|
|
50
|
+
/** `modules/schema/module.1.json`, the published shape of a manifest. */
|
|
51
|
+
export declare function readModuleSchema(dir: string): Promise<Record<string, unknown>>;
|
|
52
|
+
/** The module folders of `dir`, by code, in the order they are applied. */
|
|
53
|
+
export declare function listModules(dir?: string | undefined): Promise<EkwoModule[]>;
|
|
54
|
+
/** One module, with its manifest validated and its migrations listed. */
|
|
55
|
+
export declare function readModule(code: string, dir?: string | undefined, schema?: Record<string, unknown>): Promise<EkwoModule>;
|
|
56
|
+
/**
|
|
57
|
+
* A module's migrations, recorded under the same history the socle uses.
|
|
58
|
+
*
|
|
59
|
+
* `version` stays the plain timestamp, because that is the column Supabase
|
|
60
|
+
* keys its history on and the whole point of that choice is that `ekwo
|
|
61
|
+
* migrate` and `supabase db push` read and write the same table. What carries
|
|
62
|
+
* the module is `name`: `assets/initial` rather than `initial`, so a human
|
|
63
|
+
* reading `supabase migration list` sees which module a version belongs to.
|
|
64
|
+
*
|
|
65
|
+
* The consequence, which is a rule and a test: a module's timestamps sort
|
|
66
|
+
* after every socle migration it depends on, and no two migrations anywhere in
|
|
67
|
+
* this repository share a version.
|
|
68
|
+
*/
|
|
69
|
+
export declare function moduleMigrations(manifest: ModuleManifest, folder: string): Promise<Migration[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Every module migration, in one list, ordered by version.
|
|
72
|
+
*
|
|
73
|
+
* Concatenated with the socle's and sorted, this is what `ekwo migrate`
|
|
74
|
+
* applies. A duplicate version is a bug in whoever wrote the second one and is
|
|
75
|
+
* refused here rather than silently dropping a file, which is exactly what the
|
|
76
|
+
* Supabase history does when two files share a timestamp prefix.
|
|
77
|
+
*/
|
|
78
|
+
export declare function allModuleMigrations(modules: readonly EkwoModule[]): Migration[];
|
|
79
|
+
/**
|
|
80
|
+
* The seeds compiled from the `<section>.json` of a country pack, for one
|
|
81
|
+
* module: `supabase/seed/modules/<code>/*.sql`.
|
|
82
|
+
*
|
|
83
|
+
* They are not reference data of the socle and are deliberately not in
|
|
84
|
+
* `supabase/seed/` itself, where `ekwo migrate` and the test harness read a
|
|
85
|
+
* flat directory: a module's country data has no business landing on an
|
|
86
|
+
* installation that does not carry the module.
|
|
87
|
+
*/
|
|
88
|
+
export declare function moduleSeeds(code: string, seedDir: string): Promise<string[]>;
|
|
89
|
+
/** The line an operator has to add by hand, because no migration can. */
|
|
90
|
+
export declare function exposeSchemaNote(schemaName: string): string[];
|
|
91
|
+
//# sourceMappingURL=read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/module/read.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGtE,qBAAa,WAAY,SAAQ,KAAK;CAAG;AAEzC,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,YAAY,CAAC;IAC7C,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAUtD;AAED,yEAAyE;AACzE,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAMpF;AAED,2EAA2E;AAC3E,wBAAsB,WAAW,CAAC,GAAG,qBAAsB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAalF;AAED,yEAAyE;AACzE,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,GAAG,qBAAsB,EACzB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,UAAU,CAAC,CA6BrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,SAAS,EAAE,CAAC,CAkBtB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,EAAE,CAgB/E;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOlF;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAO7D"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The modules this checkout — or this published package — carries.
|
|
3
|
+
*
|
|
4
|
+
* A module is a folder: a manifest, a `supabase/migrations/` of its own, a
|
|
5
|
+
* README and its tests. There is no registry in code here either: the folders
|
|
6
|
+
* are the list, `module.json` is what each one says about itself, and
|
|
7
|
+
* `public.modules` is what the database holds once its migrations have run.
|
|
8
|
+
*
|
|
9
|
+
* Nothing in this file talks to a database. Reading and validating a manifest
|
|
10
|
+
* is the same work whether the next step is `ekwo module list` in a checkout
|
|
11
|
+
* or `ekwo migrate` against a Supabase project, so it is done once, here.
|
|
12
|
+
*/
|
|
13
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
14
|
+
import { existsSync } from 'node:fs';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
import { fileURLToPath } from 'node:url';
|
|
17
|
+
import { parseMigrationFile } from '../migrations.js';
|
|
18
|
+
import { validate } from '../pack/schema.js';
|
|
19
|
+
export class ModuleError extends Error {
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Where the modules live.
|
|
23
|
+
*
|
|
24
|
+
* Published package: `dist/assets/modules/`, put there at build time by
|
|
25
|
+
* `scripts/copy-assets.mjs`, because `npx ekwo-os migrate` has no clone. Checkout:
|
|
26
|
+
* `<repo>/modules/`. The two candidates mirror `resolveBundleDir()`.
|
|
27
|
+
*/
|
|
28
|
+
export function resolveModulesDir() {
|
|
29
|
+
const candidates = [
|
|
30
|
+
new URL('../assets/modules/', import.meta.url),
|
|
31
|
+
new URL('../../../../modules/', import.meta.url),
|
|
32
|
+
];
|
|
33
|
+
for (const candidate of candidates) {
|
|
34
|
+
const dir = fileURLToPath(candidate).replace(/\/$/, '');
|
|
35
|
+
if (existsSync(dir))
|
|
36
|
+
return dir;
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
/** `modules/schema/module.1.json`, the published shape of a manifest. */
|
|
41
|
+
export async function readModuleSchema(dir) {
|
|
42
|
+
const path = join(dir, 'schema', 'module.1.json');
|
|
43
|
+
const raw = await readFile(path, 'utf8').catch(() => {
|
|
44
|
+
throw new ModuleError(`module_schema_missing: ${path}`);
|
|
45
|
+
});
|
|
46
|
+
return JSON.parse(raw);
|
|
47
|
+
}
|
|
48
|
+
/** The module folders of `dir`, by code, in the order they are applied. */
|
|
49
|
+
export async function listModules(dir = resolveModulesDir()) {
|
|
50
|
+
if (dir === undefined)
|
|
51
|
+
return [];
|
|
52
|
+
const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
53
|
+
const schema = await readModuleSchema(dir);
|
|
54
|
+
const modules = [];
|
|
55
|
+
for (const entry of [...entries].sort((a, b) => a.name.localeCompare(b.name))) {
|
|
56
|
+
if (!entry.isDirectory() || entry.name === 'schema')
|
|
57
|
+
continue;
|
|
58
|
+
const folder = join(dir, entry.name);
|
|
59
|
+
if (!existsSync(join(folder, 'module.json')))
|
|
60
|
+
continue;
|
|
61
|
+
modules.push(await readModule(entry.name, dir, schema));
|
|
62
|
+
}
|
|
63
|
+
return modules;
|
|
64
|
+
}
|
|
65
|
+
/** One module, with its manifest validated and its migrations listed. */
|
|
66
|
+
export async function readModule(code, dir = resolveModulesDir(), schema) {
|
|
67
|
+
if (dir === undefined)
|
|
68
|
+
throw new ModuleError('modules_missing: this installation carries no modules folder');
|
|
69
|
+
const folder = join(dir, code);
|
|
70
|
+
const manifestPath = join(folder, 'module.json');
|
|
71
|
+
const raw = await readFile(manifestPath, 'utf8').catch(() => {
|
|
72
|
+
throw new ModuleError(`unknown_module: ${manifestPath} does not exist`);
|
|
73
|
+
});
|
|
74
|
+
let manifest;
|
|
75
|
+
try {
|
|
76
|
+
manifest = JSON.parse(raw);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
throw new ModuleError(`module_manifest_invalid: ${code}/module.json — ${error.message}`);
|
|
80
|
+
}
|
|
81
|
+
const issues = validate(manifest, schema ?? (await readModuleSchema(dir)));
|
|
82
|
+
if (issues.length > 0) {
|
|
83
|
+
throw new ModuleError(`module_manifest_invalid: ${code}/module.json\n` +
|
|
84
|
+
issues.map((issue) => ` ${issue.path}: ${issue.message}`).join('\n'));
|
|
85
|
+
}
|
|
86
|
+
if (manifest.code !== code) {
|
|
87
|
+
throw new ModuleError(`module_code_mismatch: modules/${code}/module.json calls itself "${manifest.code}"`);
|
|
88
|
+
}
|
|
89
|
+
return { manifest, dir: folder, migrations: await moduleMigrations(manifest, folder) };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A module's migrations, recorded under the same history the socle uses.
|
|
93
|
+
*
|
|
94
|
+
* `version` stays the plain timestamp, because that is the column Supabase
|
|
95
|
+
* keys its history on and the whole point of that choice is that `ekwo
|
|
96
|
+
* migrate` and `supabase db push` read and write the same table. What carries
|
|
97
|
+
* the module is `name`: `assets/initial` rather than `initial`, so a human
|
|
98
|
+
* reading `supabase migration list` sees which module a version belongs to.
|
|
99
|
+
*
|
|
100
|
+
* The consequence, which is a rule and a test: a module's timestamps sort
|
|
101
|
+
* after every socle migration it depends on, and no two migrations anywhere in
|
|
102
|
+
* this repository share a version.
|
|
103
|
+
*/
|
|
104
|
+
export async function moduleMigrations(manifest, folder) {
|
|
105
|
+
const dir = join(folder, 'supabase', 'migrations');
|
|
106
|
+
if (!existsSync(dir))
|
|
107
|
+
return [];
|
|
108
|
+
const files = (await readdir(dir)).filter((f) => f.endsWith('.sql')).sort();
|
|
109
|
+
return files.map((file) => {
|
|
110
|
+
const parsed = parseMigrationFile(file);
|
|
111
|
+
if (parsed === undefined) {
|
|
112
|
+
throw new ModuleError(`migration_name_invalid: modules/${manifest.code}/supabase/migrations/${file} — expected YYYYMMDDHHMMSS_subject.sql`);
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
version: parsed.version,
|
|
116
|
+
name: `${manifest.code}/${parsed.name}`,
|
|
117
|
+
file: parsed.file,
|
|
118
|
+
path: join(dir, file),
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Every module migration, in one list, ordered by version.
|
|
124
|
+
*
|
|
125
|
+
* Concatenated with the socle's and sorted, this is what `ekwo migrate`
|
|
126
|
+
* applies. A duplicate version is a bug in whoever wrote the second one and is
|
|
127
|
+
* refused here rather than silently dropping a file, which is exactly what the
|
|
128
|
+
* Supabase history does when two files share a timestamp prefix.
|
|
129
|
+
*/
|
|
130
|
+
export function allModuleMigrations(modules) {
|
|
131
|
+
const seen = new Map();
|
|
132
|
+
const all = [];
|
|
133
|
+
for (const module of modules) {
|
|
134
|
+
for (const migration of module.migrations) {
|
|
135
|
+
const previous = seen.get(migration.version);
|
|
136
|
+
if (previous !== undefined) {
|
|
137
|
+
throw new ModuleError(`migration_version_duplicate: ${migration.version} is used by ${previous} and by ${migration.name}`);
|
|
138
|
+
}
|
|
139
|
+
seen.set(migration.version, migration.name);
|
|
140
|
+
all.push(migration);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return all.sort((a, b) => a.version.localeCompare(b.version));
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The seeds compiled from the `<section>.json` of a country pack, for one
|
|
147
|
+
* module: `supabase/seed/modules/<code>/*.sql`.
|
|
148
|
+
*
|
|
149
|
+
* They are not reference data of the socle and are deliberately not in
|
|
150
|
+
* `supabase/seed/` itself, where `ekwo migrate` and the test harness read a
|
|
151
|
+
* flat directory: a module's country data has no business landing on an
|
|
152
|
+
* installation that does not carry the module.
|
|
153
|
+
*/
|
|
154
|
+
export async function moduleSeeds(code, seedDir) {
|
|
155
|
+
const dir = join(seedDir, 'modules', code);
|
|
156
|
+
if (!existsSync(dir))
|
|
157
|
+
return [];
|
|
158
|
+
return (await readdir(dir))
|
|
159
|
+
.filter((f) => f.endsWith('.sql'))
|
|
160
|
+
.sort()
|
|
161
|
+
.map((file) => join(dir, file));
|
|
162
|
+
}
|
|
163
|
+
/** The line an operator has to add by hand, because no migration can. */
|
|
164
|
+
export function exposeSchemaNote(schemaName) {
|
|
165
|
+
return [
|
|
166
|
+
`PostgREST does not serve \`${schemaName}\` until the project exposes it.`,
|
|
167
|
+
` Supabase dashboard → Project Settings → API → Exposed schemas: add \`${schemaName}\`.`,
|
|
168
|
+
` Self-hosted: add it to \`[api] schemas\` in supabase/config.toml and restart.`,
|
|
169
|
+
'No migration can do this: it is a setting of the API, not of the database.',
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/module/read.ts"],"names":[],"mappings":"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"}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The output contract: what a command answers, and with which exit code.
|
|
3
|
+
*
|
|
4
|
+
* Every command of this CLI is run through `execute()`, so the contract is
|
|
5
|
+
* written once and a command cannot opt out of it by forgetting.
|
|
6
|
+
*
|
|
7
|
+
* 0 done.
|
|
8
|
+
* 1 it did not end well and the books were not asked: the network, a
|
|
9
|
+
* database that does not answer, a bug — and a check that found
|
|
10
|
+
* something (`doctor`, `pack check`, a pending migration), which is how
|
|
11
|
+
* a CI job goes red.
|
|
12
|
+
* 2 the command was called wrong: an unknown option, a missing argument,
|
|
13
|
+
* a question that needed an answer and no terminal to ask it on.
|
|
14
|
+
* 3 the database refused. A locked period, a capability the caller does
|
|
15
|
+
* not hold, a tax that does not apply here. The command was well formed
|
|
16
|
+
* and everything worked; the accounting said no.
|
|
17
|
+
*
|
|
18
|
+
* A caller — an agent with a shell, a Makefile — has to tell 2 from 3 without
|
|
19
|
+
* reading a sentence, and that is the reason 3 exists.
|
|
20
|
+
*
|
|
21
|
+
* The refusal itself is printed as the database wrote it. Its name
|
|
22
|
+
* (`period_locked`) is the part a program matches on and its sentence is the
|
|
23
|
+
* part a person reads; neither is rephrased here, and nothing in this file
|
|
24
|
+
* knows what any of the names mean. Which SQLSTATEs count as a refusal and
|
|
25
|
+
* how a name is read out of a message are in `@ekwo-ai/core`, where the MCP
|
|
26
|
+
* server reads them too.
|
|
27
|
+
*/
|
|
28
|
+
import { type ParsedArgs } from './args.js';
|
|
29
|
+
export declare const EXIT_OK = 0;
|
|
30
|
+
export declare const EXIT_ERROR = 1;
|
|
31
|
+
export declare const EXIT_USAGE = 2;
|
|
32
|
+
export declare const EXIT_REFUSED = 3;
|
|
33
|
+
export type ErrorKind = 'refusal' | 'usage' | 'technical';
|
|
34
|
+
export interface OutputError {
|
|
35
|
+
kind: ErrorKind;
|
|
36
|
+
/** `period_locked`, when the message carries a name. Never invented. */
|
|
37
|
+
name?: string;
|
|
38
|
+
/** What was said, word for word. */
|
|
39
|
+
message: string;
|
|
40
|
+
/** What Postgres called it, when the error came from the database. */
|
|
41
|
+
sqlstate?: string;
|
|
42
|
+
/** The DETAIL and HINT of the raise, when the database gave them. */
|
|
43
|
+
detail?: string;
|
|
44
|
+
hint?: string;
|
|
45
|
+
}
|
|
46
|
+
/** The one JSON document a command writes under `--json`. */
|
|
47
|
+
export interface OutputDocument {
|
|
48
|
+
ok: boolean;
|
|
49
|
+
command: string;
|
|
50
|
+
exitCode: number;
|
|
51
|
+
/** What the command has to say. Absent when it failed before having any. */
|
|
52
|
+
data?: unknown;
|
|
53
|
+
/**
|
|
54
|
+
* On whose behalf, where, and for which company the answer was rendered.
|
|
55
|
+
* Present on every command that acts as a person; absent on the commands
|
|
56
|
+
* that install and operate, which act as nobody.
|
|
57
|
+
*/
|
|
58
|
+
context?: OutputContext;
|
|
59
|
+
/** Every warning the command printed, without the colours. */
|
|
60
|
+
warnings: string[];
|
|
61
|
+
error?: OutputError;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* What a caller checks before it believes the rest.
|
|
65
|
+
*
|
|
66
|
+
* An agent that keeps the books of two companies and answers for the wrong
|
|
67
|
+
* one has made the one mistake no total will reveal. So the company is in the
|
|
68
|
+
* document itself — `null` when none is in use — on success and on a refusal
|
|
69
|
+
* alike, as soon as it is known.
|
|
70
|
+
*/
|
|
71
|
+
export interface OutputContext {
|
|
72
|
+
/** `null` when the environment said who, and no profile was read. */
|
|
73
|
+
profile: string | null;
|
|
74
|
+
instance: string;
|
|
75
|
+
company: {
|
|
76
|
+
id: string;
|
|
77
|
+
name: string;
|
|
78
|
+
} | null;
|
|
79
|
+
}
|
|
80
|
+
/** Called by a command that acts as a person, as soon as it knows for which company. */
|
|
81
|
+
export declare function setContext(value: OutputContext): void;
|
|
82
|
+
/**
|
|
83
|
+
* What the command answers under `--json`.
|
|
84
|
+
*
|
|
85
|
+
* Called by the command with the same values it prints, never with values of
|
|
86
|
+
* its own: a figure that exists in one of the two forms only is a bug.
|
|
87
|
+
*/
|
|
88
|
+
export declare function setResult(data: unknown): void;
|
|
89
|
+
/** `module list`, `pack upgrade`, `status`: the words that named the command. */
|
|
90
|
+
export declare function commandLabel(args: ParsedArgs): string;
|
|
91
|
+
/** Which of the three an error is, and with it the exit code. */
|
|
92
|
+
export declare function classify(error: unknown): {
|
|
93
|
+
exitCode: number;
|
|
94
|
+
error: OutputError;
|
|
95
|
+
};
|
|
96
|
+
/** `--json` as it was typed, for the errors that happen before flags are read. */
|
|
97
|
+
export declare function askedForJson(argv: readonly string[]): boolean;
|
|
98
|
+
/** An error met before any command ran: a bad option, an unknown command. */
|
|
99
|
+
export declare function reportFailure(command: string, json: boolean, error: unknown): number;
|
|
100
|
+
/**
|
|
101
|
+
* Runs one command under the contract.
|
|
102
|
+
*
|
|
103
|
+
* The handler prints for a person as it goes and hands `setResult()` what a
|
|
104
|
+
* program should read. Here the two are kept apart: under `--json` the prose
|
|
105
|
+
* has already gone to the standard error, and the standard output receives
|
|
106
|
+
* exactly one document — on success, on a finding, and on a refusal alike, so
|
|
107
|
+
* a caller parses the same shape whatever happened.
|
|
108
|
+
*/
|
|
109
|
+
export declare function execute(args: ParsedArgs, json: boolean, handler: () => Promise<number>): Promise<number>;
|
|
110
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAIxD,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,WAAW,CAAC;AAE1D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,6DAA6D;AAC7D,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC9C;AAKD,wFAAwF;AACxF,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAE7C;AAID,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAWrD;AAQD,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CA8BjF;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAM7D;AAQD,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAcpF;AAED;;;;;;;;GAQG;AACH,wBAAsB,OAAO,CAC3B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAC7B,OAAO,CAAC,MAAM,CAAC,CA6BjB"}
|