spine-framework 0.3.145 → 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/.env.example +76 -0
- package/.framework/.spine-manifest.json +19 -0
- package/.framework/cli/commands/agents.ts +61 -33
- package/.framework/cli/commands/auth.ts +60 -28
- package/.framework/cli/commands/create-app.ts +212 -80
- package/.framework/cli/commands/dev.ts +184 -68
- package/.framework/cli/commands/doctor.ts +324 -152
- package/.framework/cli/commands/generate.ts +119 -68
- package/.framework/cli/commands/init.ts +141 -242
- package/.framework/cli/commands/install-app.ts +1336 -314
- package/.framework/cli/commands/items.ts +31 -29
- package/.framework/cli/commands/migrate.ts +299 -156
- package/.framework/cli/commands/migrations.ts +62 -30
- package/.framework/cli/commands/pipelines.ts +31 -29
- package/.framework/cli/commands/status.ts +105 -45
- package/.framework/cli/commands/system.ts +47 -42
- package/.framework/cli/commands/test.ts +161 -102
- package/.framework/cli/commands/upgrade.ts +260 -0
- package/.framework/cli/commands/validate-app.ts +517 -161
- package/.framework/cli/context.ts +117 -85
- package/.framework/cli/env-loader.ts +74 -43
- package/.framework/cli/index.ts +70 -46
- package/.framework/cli/lib/project-files.ts +404 -0
- package/.framework/docs/guides/testing-guide.md +1 -1
- package/.framework/docs/runtime-types.md +72 -72
- package/.framework/functions/_shared/access.ts +84 -0
- package/.framework/functions/_shared/agent-runner.ts +5067 -1026
- package/.framework/functions/_shared/app-manifest.ts +214 -94
- package/.framework/functions/_shared/ast.ts +214 -0
- package/.framework/functions/_shared/audit.ts +91 -55
- package/.framework/functions/_shared/cil.ts +368 -127
- package/.framework/functions/_shared/db.ts +337 -68
- package/.framework/functions/_shared/funnel.ts +228 -0
- package/.framework/functions/_shared/geo.ts +105 -0
- package/.framework/functions/_shared/hash-api-key.ts +94 -17
- package/.framework/functions/_shared/index.ts +22 -224
- package/.framework/functions/_shared/kb.ts +832 -58
- package/.framework/functions/_shared/llm.ts +118 -18
- package/.framework/functions/_shared/logging.ts +317 -19
- package/.framework/functions/_shared/middleware.ts +701 -131
- package/.framework/functions/_shared/notify.ts +70 -0
- package/.framework/functions/_shared/outcomes.ts +34 -19
- package/.framework/functions/_shared/permissions.ts +501 -315
- package/.framework/functions/_shared/pipeline-runner.ts +704 -155
- package/.framework/functions/_shared/principal.ts +436 -263
- package/.framework/functions/_shared/rate-limit.ts +233 -0
- package/.framework/functions/_shared/resolve-credentials.ts +86 -19
- package/.framework/functions/_shared/resolve-ids.ts +203 -139
- package/.framework/functions/_shared/retry-deliveries.ts +51 -16
- package/.framework/functions/_shared/schema-utils.ts +602 -521
- package/.framework/functions/_shared/security.ts +345 -0
- package/.framework/functions/_shared/testing.ts +197 -172
- package/.framework/functions/_shared/tracing.ts +351 -21
- package/.framework/functions/_shared/trigger-engine.ts +425 -136
- package/.framework/functions/_shared/webhook-registration.ts +71 -70
- package/.framework/functions/_shared/webhook-registry.ts +126 -83
- package/.framework/functions/account-nodes.ts +30 -30
- package/.framework/functions/adapters/generic-webhook-inbound.ts +49 -16
- package/.framework/functions/adapters/generic-webhook-outbound.ts +17 -17
- package/.framework/functions/adapters/openai-outbound.ts +15 -16
- package/.framework/functions/admin-data.ts +596 -173
- package/.framework/functions/admin-funnel.ts +64 -60
- package/.framework/functions/admin-install-funnel.ts +84 -66
- package/.framework/functions/admin-signals.ts +69 -51
- package/.framework/functions/ai-agents.ts +431 -106
- package/.framework/functions/ai-interactions.ts +186 -112
- package/.framework/functions/api-keys.ts +107 -107
- package/.framework/functions/apps.ts +154 -136
- package/.framework/functions/auth.ts +83 -65
- package/.framework/functions/cil-agent-ingest.ts +189 -232
- package/.framework/functions/cil-agent.ts +433 -177
- package/.framework/functions/cil-callmap.ts +642 -430
- package/.framework/functions/cil-config.ts +139 -135
- package/.framework/functions/cil-context.ts +214 -127
- package/.framework/functions/cil-doc.ts +587 -458
- package/.framework/functions/cil-embeddings.ts +453 -364
- package/.framework/functions/cil-graph.ts +427 -142
- package/.framework/functions/cil-ingest.ts +1418 -1154
- package/.framework/functions/cil-pipeline.ts +276 -21
- package/.framework/functions/cil-project.ts +659 -132
- package/.framework/functions/cil-validate.ts +198 -164
- package/.framework/functions/debug-auth.ts +57 -55
- package/.framework/functions/deliveries.ts +80 -21
- package/.framework/functions/embeddings.ts +1023 -318
- package/.framework/functions/eval-harness.ts +146 -108
- package/.framework/functions/integration-outbound.ts +205 -75
- package/.framework/functions/integration-routes.ts +128 -23
- package/.framework/functions/integrations.ts +125 -100
- package/.framework/functions/invites.ts +1095 -460
- package/.framework/functions/item-progress.ts +158 -102
- package/.framework/functions/kb.ts +34 -10
- package/.framework/functions/logs.ts +133 -133
- package/.framework/functions/observability.ts +152 -122
- package/.framework/functions/pipeline-executions.ts +147 -132
- package/.framework/functions/pipelines.ts +134 -119
- package/.framework/functions/prompt-configs.ts +96 -80
- package/.framework/functions/roles.ts +112 -82
- package/.framework/functions/security.ts +450 -0
- package/.framework/functions/system-cron.ts +117 -80
- package/.framework/functions/system.ts +158 -98
- package/.framework/functions/tests.ts +29 -29
- package/.framework/functions/timers.ts +94 -95
- package/.framework/functions/trigger-scheduler.ts +10 -0
- package/.framework/functions/triggers.ts +179 -149
- package/.framework/functions/types.ts +137 -125
- package/.framework/mcp/index.ts +133 -0
- package/.framework/mcp/load-env.ts +60 -0
- package/.framework/mcp/shared/app-manifest.ts +275 -0
- package/.framework/mcp/shared/db.ts +477 -0
- package/.framework/mcp/shared/kb.ts +118 -0
- package/.framework/mcp/tools/architect.ts +431 -0
- package/.framework/mcp/tools/cil/context.ts +345 -0
- package/.framework/mcp/tools/cil/graph.ts +242 -0
- package/.framework/mcp/tools/cil/ingest.ts +1217 -0
- package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +693 -0
- package/.framework/mcp/tools/cil/pipeline.ts +767 -0
- package/.framework/mcp/tools/cil/project.ts +791 -0
- package/.framework/mcp/tools/cil/retrieval.ts +336 -0
- package/.framework/mcp/tools/cil/search-core.ts +454 -0
- package/.framework/mcp/tools/cil/search.ts +97 -0
- package/.framework/mcp/tools/cil/suggest.ts +186 -0
- package/.framework/mcp/tools/cil/validate.ts +1369 -0
- package/.framework/mcp/tools/kb/delete.ts +139 -0
- package/.framework/mcp/tools/kb/index.ts +52 -0
- package/.framework/mcp/tools/kb/ingest.ts +84 -0
- package/.framework/mcp/tools/kb/list-types.ts +102 -0
- package/.framework/mcp/tools/kb/publish.ts +100 -0
- package/.framework/mcp/tools/kb/reindex.ts +86 -0
- package/.framework/mcp/tools/kb/revoke.ts +85 -0
- package/.framework/mcp/tools/kb/search.ts +101 -0
- package/.framework/mcp/tools/kb/upsert.ts +125 -0
- package/.framework/mcp/tools/observability.ts +510 -0
- package/.framework/migrations/001_core_schema.sql +15 -0
- package/.framework/migrations/002_core_rls_and_functions.sql +15 -0
- package/.framework/migrations/003_core_system_data.sql +16 -1
- package/.framework/migrations/004_core_rpc_and_broker.sql +17 -1
- package/.framework/migrations/005_core_observability.sql +17 -1
- package/.framework/migrations/006_security_hardening_rls.sql +15 -0
- package/.framework/migrations/007_kb_article_list.sql +17 -1
- package/.framework/migrations/008_items_target.sql +15 -0
- package/.framework/migrations/009_roles_slug_unique.sql +15 -0
- package/.framework/migrations/010_auth_user_trigger.sql +15 -0
- package/.framework/migrations/011_spine_system_account.sql +16 -0
- package/.framework/migrations/012_service_role_grants.sql +16 -0
- package/.framework/migrations/013_get_account_apps_role_filter.sql +15 -0
- package/.framework/migrations/014_apps_required_roles.sql +16 -0
- package/.framework/migrations/015_types_kind_slug_unique.sql +15 -0
- package/.framework/migrations/016_cil_types.sql +281 -0
- package/.framework/migrations/017_cil_stable_ids.sql +37 -0
- package/.framework/migrations/018_runtime_tables.sql +129 -0
- package/.framework/migrations/019_agent_prompt_columns.sql +56 -0
- package/.framework/migrations/020_schema_reconciliation.sql +67 -0
- package/.framework/migrations/021_kb_embedding_lifecycle.sql +31 -0
- package/.framework/migrations/032_cil_status_migration.sql +73 -0
- package/.framework/migrations/033_cil_versioning.sql +73 -0
- package/.framework/migrations/034_match_embeddings_knn.sql +115 -0
- package/.framework/migrations/035_rate_limits.sql +55 -0
- package/.framework/migrations/036_demo_record_flags.sql +72 -0
- package/.framework/migrations/037_kb_types_canonical.sql +244 -0
- package/.framework/migrations/038_drop_demo_record_flags.sql +38 -0
- package/.framework/migrations/042_registration_hierarchy.sql +309 -0
- package/.framework/migrations/043_policy_actor_cleanup.sql +39 -0
- package/.framework/migrations/044_match_embeddings_filtered_knn.sql +151 -0
- package/.framework/migrations/045_security_critical_rls.sql +139 -0
- package/.framework/migrations/046_security_missing_rls.sql +79 -0
- package/.framework/migrations/047_people_updated_by.sql +27 -0
- package/.framework/migrations/048_watcher_last_seen_at.sql +24 -0
- package/.framework/migrations/049_security_blocklist.sql +148 -0
- package/.framework/migrations/050_notifications.sql +49 -0
- package/.framework/migrations/051_message_agent_fields.sql +74 -0
- package/.framework/migrations/052_registration_security.sql +421 -0
- package/.framework/migrations/053_builtin_action_seeds.sql +66 -0
- package/.framework/migrations/054_kb_ingest_lease.sql +157 -0
- package/.framework/migrations/055_type_id_drift_reconciliation.sql +33 -0
- package/.framework/migrations/056_slug_column_reconciliation.sql +38 -0
- package/.framework/migrations/057_pipelines_slug_identity.sql +14 -0
- package/.framework/migrations/058_account_data_field_declarations.sql +53 -0
- package/.framework/migrations/059_registration_placement_fixes.sql +269 -0
- package/.framework/migrations/060_account_person_record_permissions.sql +38 -0
- package/.framework/migrations/061_fk_dedup.sql +32 -0
- package/.framework/public/spine-logo.svg +10 -3
- package/.framework/scripts/app-install-cli.ts +190 -93
- package/.framework/scripts/assemble-frontend.sh +127 -44
- package/.framework/scripts/assemble-functions.sh +128 -30
- package/.framework/scripts/boundary-check.sh +6 -2
- package/.framework/scripts/build-manifest.sh +24 -68
- package/.framework/scripts/check-core-integrity.sh +15 -76
- package/.framework/scripts/checksum-manifest.mts +343 -0
- package/.framework/scripts/cil-migrate-markers.ts +403 -0
- package/.framework/scripts/fix-cil-markers.mjs +176 -0
- package/.framework/scripts/verify-integrity.sh +21 -57
- package/.framework/scripts/verify-manifest.mts +305 -0
- package/.framework/seeds/types/funnel_signal_use.json +74 -21
- package/.framework/seeds/types/spine_instance.json +73 -21
- package/.framework/src/App.tsx +118 -72
- package/.framework/src/apps/admin/index.tsx +855 -58
- package/.framework/src/components/AppWrapper.tsx +43 -45
- package/.framework/src/components/CustomAppLoader.tsx +160 -116
- package/.framework/src/components/admin/AdminListPage.tsx +46 -44
- package/.framework/src/components/admin/AdminSidebar.tsx +57 -47
- package/.framework/src/components/admin/AdminStatsCard.tsx +46 -44
- package/.framework/src/components/admin/PageInstructions.tsx +98 -2
- package/.framework/src/components/admin/SortableTableHeader.tsx +44 -45
- package/.framework/src/components/app-shell/GenericAppShell.tsx +64 -65
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +44 -47
- package/.framework/src/components/app-shell/GenericListPage.tsx +45 -49
- package/.framework/src/components/app-sidebar.tsx +42 -45
- package/.framework/src/components/auth/ProtectedRoute.tsx +48 -41
- package/.framework/src/components/auth/TurnstileWidget.tsx +27 -0
- package/.framework/src/components/kb/KBArticleEditor.tsx +231 -22
- package/.framework/src/components/kb/KBArticleList.tsx +251 -10
- package/.framework/src/components/layout/AppShell.tsx +51 -45
- package/.framework/src/components/layout/Header.tsx +42 -43
- package/.framework/src/components/layout/Layout.tsx +46 -46
- package/.framework/src/components/layout/Sidebar.tsx +196 -96
- package/.framework/src/components/runtime/DataDetailHeader.tsx +55 -30
- package/.framework/src/components/runtime/DataDetailPage.tsx +31 -269
- package/.framework/src/components/runtime/DataFilters.tsx +49 -74
- package/.framework/src/components/runtime/DataHeader.tsx +53 -32
- package/.framework/src/components/runtime/DataListPage.tsx +51 -155
- package/.framework/src/components/runtime/DataStats.tsx +66 -44
- package/.framework/src/components/runtime/DataTable.tsx +49 -149
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +45 -75
- package/.framework/src/components/runtime/index.ts +119 -16
- package/.framework/src/components/search-form.tsx +46 -29
- package/.framework/src/components/shared/AgentView.tsx +65 -48
- package/.framework/src/components/shared/FieldRenderer.tsx +144 -50
- package/.framework/src/components/shared/InviteManager.tsx +207 -97
- package/.framework/src/components/shared/MemberList.tsx +97 -0
- package/.framework/src/components/shared/SchemaFields.tsx +107 -86
- package/.framework/src/components/ui/DataTable.tsx +80 -68
- package/.framework/src/components/ui/Form.tsx +157 -146
- package/.framework/src/components/ui/ItemCard.tsx +74 -67
- package/.framework/src/components/ui/ItemListView.tsx +73 -68
- package/.framework/src/components/ui/LoadingSpinner.tsx +43 -48
- package/.framework/src/components/ui/Modal.tsx +78 -68
- package/.framework/src/components/ui/RichTextEditor.tsx +89 -69
- package/.framework/src/components/ui/accordion.tsx +85 -86
- package/.framework/src/components/ui/alert-dialog.tsx +197 -184
- package/.framework/src/components/ui/alert.tsx +105 -94
- package/.framework/src/components/ui/aspect-ratio.tsx +57 -43
- package/.framework/src/components/ui/avatar.tsx +122 -107
- package/.framework/src/components/ui/badge.tsx +60 -55
- package/.framework/src/components/ui/breadcrumb.tsx +127 -128
- package/.framework/src/components/ui/button-group.tsx +86 -72
- package/.framework/src/components/ui/button.tsx +71 -50
- package/.framework/src/components/ui/calendar.tsx +72 -57
- package/.framework/src/components/ui/card.tsx +136 -129
- package/.framework/src/components/ui/carousel.tsx +226 -107
- package/.framework/src/components/ui/chart.tsx +252 -147
- package/.framework/src/components/ui/checkbox.tsx +43 -44
- package/.framework/src/components/ui/collapsible.tsx +86 -71
- package/.framework/src/components/ui/combobox.tsx +282 -249
- package/.framework/src/components/ui/command.tsx +158 -146
- package/.framework/src/components/ui/context-menu.tsx +239 -240
- package/.framework/src/components/ui/dialog.tsx +174 -157
- package/.framework/src/components/ui/direction.tsx +72 -56
- package/.framework/src/components/ui/drawer.tsx +168 -169
- package/.framework/src/components/ui/dropdown-menu.tsx +254 -223
- package/.framework/src/components/ui/empty.tsx +131 -120
- package/.framework/src/components/ui/field.tsx +205 -173
- package/.framework/src/components/ui/hover-card.tsx +71 -72
- package/.framework/src/components/ui/input-group.tsx +148 -133
- package/.framework/src/components/ui/input-otp.tsx +99 -86
- package/.framework/src/components/ui/input.tsx +43 -41
- package/.framework/src/components/ui/item.tsx +207 -185
- package/.framework/src/components/ui/kbd.tsx +57 -56
- package/.framework/src/components/ui/label.tsx +45 -41
- package/.framework/src/components/ui/menubar.tsx +268 -236
- package/.framework/src/components/ui/native-select.tsx +85 -86
- package/.framework/src/components/ui/navigation-menu.tsx +166 -156
- package/.framework/src/components/ui/pagination.tsx +131 -141
- package/.framework/src/components/ui/popover.tsx +125 -128
- package/.framework/src/components/ui/progress.tsx +47 -44
- package/.framework/src/components/ui/radio-group.tsx +60 -55
- package/.framework/src/components/ui/resizable.tsx +85 -72
- package/.framework/src/components/ui/scroll-area.tsx +57 -58
- package/.framework/src/components/ui/select.tsx +182 -169
- package/.framework/src/components/ui/separator.tsx +42 -43
- package/.framework/src/components/ui/sheet.tsx +170 -159
- package/.framework/src/components/ui/sidebar.tsx +395 -398
- package/.framework/src/components/ui/skeleton.tsx +42 -43
- package/.framework/src/components/ui/slider.tsx +61 -44
- package/.framework/src/components/ui/sonner.tsx +44 -44
- package/.framework/src/components/ui/spinner.tsx +47 -42
- package/.framework/src/components/ui/switch.tsx +56 -42
- package/.framework/src/components/ui/table-primitives.tsx +272 -132
- package/.framework/src/components/ui/table.tsx +140 -142
- package/.framework/src/components/ui/tabs.tsx +110 -93
- package/.framework/src/components/ui/textarea.tsx +43 -44
- package/.framework/src/components/ui/toggle-group.tsx +87 -71
- package/.framework/src/components/ui/toggle.tsx +56 -56
- package/.framework/src/components/ui/tooltip.tsx +99 -85
- package/.framework/src/contexts/AppContext.tsx +166 -114
- package/.framework/src/contexts/AuthContext.tsx +232 -137
- package/.framework/src/hooks/use-mobile.ts +43 -44
- package/.framework/src/hooks/useApi.ts +185 -172
- package/.framework/src/hooks/useAppPath.ts +31 -29
- package/.framework/src/hooks/useApps.ts +77 -42
- package/.framework/src/hooks/useEntityList.ts +66 -29
- package/.framework/src/hooks/useEntityRecord.ts +76 -32
- package/.framework/src/hooks/useForm.ts +62 -30
- package/.framework/src/hooks/useListSchema.ts +60 -43
- package/.framework/src/hooks/useSchemaRecord.ts +115 -95
- package/.framework/src/lib/api.ts +258 -134
- package/.framework/src/lib/registration.ts +181 -0
- package/.framework/src/lib/supabase.ts +118 -81
- package/.framework/src/lib/utils.ts +266 -266
- package/.framework/src/main.tsx +43 -44
- package/.framework/src/pages/DashboardPage.tsx +44 -43
- package/.framework/src/pages/NoAppPage.tsx +50 -0
- package/.framework/src/pages/NotFoundPage.tsx +32 -29
- package/.framework/src/pages/SetupPage.tsx +34 -33
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +69 -58
- package/.framework/src/pages/admin/AIAgentsPage.tsx +43 -40
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +63 -55
- package/.framework/src/pages/admin/APIKeysPage.tsx +44 -42
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +117 -94
- package/.framework/src/pages/admin/AppDetailPage.tsx +48 -42
- package/.framework/src/pages/admin/AppsPage.tsx +45 -42
- package/.framework/src/pages/admin/DeliveriesPage.tsx +49 -17
- package/.framework/src/pages/admin/DesignedPage.tsx +31 -30
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +58 -0
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +49 -0
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +31 -29
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +46 -29
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -29
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +68 -55
- package/.framework/src/pages/admin/IntegrationsPage.tsx +45 -42
- package/.framework/src/pages/admin/InvitesPage.tsx +60 -44
- package/.framework/src/pages/admin/LogsPage.tsx +87 -137
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +31 -29
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +150 -89
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +77 -104
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +44 -43
- package/.framework/src/pages/admin/PipelinesPage.tsx +59 -145
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +53 -42
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +47 -117
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +31 -44
- package/.framework/src/pages/admin/RoleDetailPage.tsx +49 -92
- package/.framework/src/pages/admin/RolesPage.tsx +47 -164
- package/.framework/src/pages/admin/SecurityPage.tsx +310 -0
- package/.framework/src/pages/admin/SelectTestPage.tsx +30 -32
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +37 -44
- package/.framework/src/pages/admin/SimpleDashboard.tsx +32 -44
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +97 -44
- package/.framework/src/pages/admin/TestingDashboard.tsx +126 -71
- package/.framework/src/pages/admin/TimerDetailPage.tsx +67 -55
- package/.framework/src/pages/admin/TimersPage.tsx +44 -42
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +47 -42
- package/.framework/src/pages/admin/TriggersPage.tsx +58 -57
- package/.framework/src/pages/admin/TypeDetailPage.tsx +91 -55
- package/.framework/src/pages/admin/TypesPage.tsx +45 -42
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +258 -128
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +127 -123
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +308 -235
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +159 -110
- package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +432 -0
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +200 -178
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +286 -239
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +211 -90
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +156 -143
- package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +379 -0
- package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +337 -0
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +219 -214
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +135 -65
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +39 -31
- package/.framework/src/pages/auth/LoginPage.tsx +38 -32
- package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -28
- package/.framework/src/pages/auth/RegisterPage.tsx +429 -155
- package/.framework/src/pages/spine-framework/APIPage.tsx +33 -30
- package/.framework/src/pages/spine-framework/CLIPage.tsx +32 -30
- package/.framework/src/types/auth.ts +101 -93
- package/.framework/src/types/types.ts +283 -262
- package/.framework/templates/project.json +87 -0
- package/.framework/templates/spine.config.neutral.json +7 -0
- package/.framework/tests/api/api-surface.test.ts +381 -0
- package/.framework/tests/fixtures/seed.ts +427 -0
- package/.framework/tests/fixtures/teardown.ts +228 -0
- package/.framework/tests/reporter.ts +351 -0
- package/.framework/tests/setup.ts +135 -0
- package/.framework/tests/ui/ui-sweep.ts +278 -0
- package/.framework/tests/unit/admin-data-logger.test.ts +310 -0
- package/.framework/tests/unit/agent-runner.test.ts +2389 -0
- package/.framework/tests/unit/ai-interactions.test.ts +81 -0
- package/.framework/tests/unit/app-manifest.test.ts +359 -0
- package/.framework/tests/unit/assembly-scripts.test.ts +172 -0
- package/.framework/tests/unit/cil-determinism.test.ts +85 -0
- package/.framework/tests/unit/core-isolation.test.ts +153 -0
- package/.framework/tests/unit/funnel-signals.test.ts +135 -0
- package/.framework/tests/unit/install-app.test.ts +1759 -0
- package/.framework/tests/unit/invites-security.test.ts +572 -0
- package/.framework/tests/unit/kb-ingest-lease.test.ts +287 -0
- package/.framework/tests/unit/kb-search.test.ts +119 -0
- package/.framework/tests/unit/migrate.test.ts +509 -0
- package/.framework/tests/unit/notify.test.ts +136 -0
- package/.framework/tests/unit/permissions.test.ts +269 -0
- package/.framework/tests/unit/pipeline-runner.test.ts +755 -0
- package/.framework/tests/unit/principal-cache.test.ts +138 -0
- package/.framework/tests/unit/retrieval-golden.test.ts +520 -0
- package/.framework/tests/unit/runtime-isolation.test.ts +642 -0
- package/.framework/tests/unit/schema-utils.test.ts +225 -0
- package/.framework/tests/unit/trigger-engine.test.ts +513 -0
- package/.framework/tests/unit/validate-app.test.ts +527 -0
- package/README.md +34 -3
- package/bin/spine-framework.cjs +1 -0
- package/config/tailwind.config.cjs +7 -0
- package/config/tsconfig.functions.json +42 -0
- package/config/tsconfig.json +37 -9
- package/config/vite.config.ts +31 -2
- package/netlify.toml +31 -3
- package/package.json +46 -29
- package/scripts/assemble-frontend.sh +127 -44
- package/scripts/assemble-functions.sh +127 -29
- package/scripts/boundary-check.sh +6 -2
- package/scripts/build-manifest.sh +24 -68
- package/scripts/checksum-manifest.mts +345 -0
- package/scripts/dev-clean.sh +86 -0
- package/scripts/dev-netlify.sh +49 -0
- package/scripts/netlify-dev-wrapper.sh +2 -0
- package/scripts/verify-install.ts +358 -0
- package/scripts/verify-integrity.sh +21 -57
- package/scripts/verify-manifest.mts +305 -0
- package/templates/project/gitignore +45 -0
- package/{config → templates/project}/package-lock.json +22335 -9366
- package/vitest.config.ts +46 -0
- package/.framework/public/spine.config.json +0 -91
- package/config/deno.lock +0 -108
- package/config/tsconfig.node.tsbuildinfo +0 -1
- package/config/tsconfig.tsbuildinfo +0 -1
- package/config/vite.config.d.ts +0 -2
- package/custom/.devin/AGENT.md +0 -357
- package/custom/.devin/skills/install-app/SKILL.md +0 -39
- package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +0 -39
- package/custom/.devin/skills/spine-workbench-idea/SKILL.md +0 -36
- package/custom/.devin/skills/spine-workbench-implement/SKILL.md +0 -46
- package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +0 -28
- package/custom/.devin/skills/spine-workbench-plan/SKILL.md +0 -38
- package/custom/.devin/workflows/app-install.yaml +0 -83
- package/custom/README.md +0 -79
- package/docs/README.md +0 -15
- package/scripts/app-install-cli.ts +0 -286
- package/scripts/check-core-integrity.sh +0 -82
- package/scripts/ingest-chunks.cjs +0 -202
- package/scripts/kb-chunk-parser.cjs +0 -312
- package/scripts/kb-chunk-parser.ts +0 -330
- package/scripts/kb-ingest-docs.ts +0 -203
- package/scripts/load-test-app-install.ts +0 -484
- package/scripts/test-login.js +0 -33
- package/spine.config.json +0 -91
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/cli/commands/migrate.ts"]
|
|
2
|
+
// CIL[DOC-MACRO purpose="Provides the migrate command for applying database migrations to a Supabase project."]
|
|
3
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Bootstraps imports and module context for the migrate CLI command."]
|
|
4
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
|
|
5
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
6
|
+
// CIL[DOC-MICRO logic_summary="Imports Commander type, fs, path, and url helpers and defines package and project root constants." notable_decisions="Package root is resolved relative to the installed package; project root is the current working directory."]
|
|
7
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
8
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
9
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
10
|
+
|
|
1
11
|
|
|
2
12
|
|
|
3
13
|
|
|
@@ -8,51 +18,120 @@
|
|
|
8
18
|
|
|
9
19
|
|
|
10
20
|
|
|
11
|
-
// CIL[BEGIN chunk_id="migrate_moduleheader_1784069813" type="module_header" identity="module_header" parent="none"]
|
|
12
|
-
// CIL[DOC-MACRO purpose="Module imports and types for migration CLI"]
|
|
13
|
-
// CIL[DOC-RESPONSIBILITY responsibility="Provide filesystem utilities and migration interfaces"]
|
|
14
|
-
// CIL[DOC-CONTEXT module="cli.commands.migrate" layer="cli" related_files="[\".framework/migrations/015_simplify_apps_table.sql\",\"custom/apps/cortex/pages/operations/OperationsDashboard.tsx\",\"custom/apps/portal/pages/ContentPage.tsx\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\".framework/functions/_shared/principal.ts\",\"\\\"]"]
|
|
15
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="imports and types" errors="none" side_effects="none"]
|
|
16
|
-
// CIL[DOC-MICRO logic_summary="Imports Node.js modules and defines MigrateOptions interface" notable_decisions="[]"]
|
|
17
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
18
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
19
|
-
// CIL[DOC-AUDIENCE audience="developer"]
|
|
20
|
-
// CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: .framework/migrations/015_simplify_apps_table.sql, custom/apps/cortex/pages/operations/OperationsDashboard.tsx, custom/apps/portal/pages/ContentPage.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, .framework/functions/_shared/principal.ts, \."]
|
|
21
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
22
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
23
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
24
|
-
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
25
|
-
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
26
21
|
import type { Command } from 'commander'
|
|
27
22
|
import { existsSync, readdirSync, readFileSync } from 'fs'
|
|
28
23
|
import { resolve, dirname, join } from 'path'
|
|
29
24
|
import { fileURLToPath } from 'url'
|
|
30
|
-
|
|
25
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Provides the migrate command for applying database migrations to a Supabase project.'; No verified external callers; imports: none"]
|
|
26
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
27
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
28
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
29
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
30
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
31
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:module_header:module_header"]
|
|
32
|
+
|
|
33
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:__filename:constant" type="constant" identity="__filename" parent="~/.framework/cli/commands/migrate.ts"]
|
|
34
|
+
// CIL[DOC-MACRO purpose="Defines the current module file path."]
|
|
35
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Derives __filename from the module import meta URL."]
|
|
36
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
|
|
37
|
+
// CIL[DOC-STABILITY stability="internal"]
|
|
38
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
39
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
40
|
+
// CIL[DOC-MICRO logic_summary="Converts import.meta.url to a file path and assigns to __filename." notable_decisions="none"]
|
|
41
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
31
42
|
const __filename = fileURLToPath(import.meta.url)
|
|
43
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:__filename:constant"]
|
|
44
|
+
// CIL[DOC-CONTEXT module="unknown" layer="unknown" related_files=".framework/cli/commands/migrate.ts"]
|
|
45
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Defines the current module file path.'; No verified external callers; imports: none"]
|
|
46
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
47
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
48
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
49
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
50
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
51
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:__dirname:constant" type="constant" identity="__dirname" parent="~/.framework/cli/commands/migrate.ts"]
|
|
52
|
+
// CIL[DOC-MACRO purpose="Defines the current module directory."]
|
|
53
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Derives __dirname from __filename."]
|
|
54
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
|
|
55
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
56
|
+
// CIL[DOC-STABILITY stability="internal"]
|
|
57
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
58
|
+
// CIL[DOC-MICRO logic_summary="Computes the directory of the current file and assigns to __dirname." notable_decisions="none"]
|
|
59
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
32
60
|
const __dirname = dirname(__filename)
|
|
61
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:__dirname:constant"]
|
|
62
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:PACKAGE_ROOT:constant" type="constant" identity="PACKAGE_ROOT" parent="~/.framework/cli/commands/migrate.ts"]
|
|
63
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Defines the current module directory.'; No verified external callers; imports: none"]
|
|
64
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
65
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
66
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
67
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
68
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
69
|
+
// CIL[DOC-CONTEXT module="migrate" layer="cli" related_files=".framework/cli/commands/migrate.ts"]
|
|
70
|
+
// CIL[DOC-MACRO purpose="Defines the package root path."]
|
|
71
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Resolves the package root by walking up from the CLI directory."]
|
|
72
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
73
|
+
// CIL[DOC-MICRO logic_summary="Resolves the package root three levels above the current module." notable_decisions="none"]
|
|
74
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
75
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
76
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
33
77
|
const PACKAGE_ROOT = resolve(__dirname, '../../../')
|
|
78
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:PACKAGE_ROOT:constant"]
|
|
79
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Defines the package root path.'; No verified external callers; imports: none"]
|
|
80
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
81
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
82
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
83
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
84
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
85
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:PROJECT_ROOT:constant" type="constant" identity="PROJECT_ROOT" parent="~/.framework/cli/commands/migrate.ts"]
|
|
86
|
+
// CIL[DOC-MACRO purpose="Defines the project root path."]
|
|
87
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Uses the current working directory as the project root."]
|
|
88
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
|
|
89
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
90
|
+
// CIL[DOC-MICRO logic_summary="Sets PROJECT_ROOT to process.cwd()." notable_decisions="none"]
|
|
91
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
92
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
93
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
34
94
|
const PROJECT_ROOT = process.cwd()
|
|
95
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Defines the project root path.'; No verified external callers; imports: none"]
|
|
96
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
97
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
98
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
99
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
100
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
101
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:PROJECT_ROOT:constant"]
|
|
102
|
+
|
|
35
103
|
|
|
104
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:MigrateOptions:interface" type="interface" identity="MigrateOptions" parent="~/.framework/cli/commands/migrate.ts"]
|
|
105
|
+
// CIL[DOC-MACRO purpose="Declares the migrate command options."]
|
|
106
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Types the CLI flags and optional db password."]
|
|
107
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
|
|
108
|
+
// CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
|
|
109
|
+
// CIL[DOC-MICRO logic_summary="Defines dbPassword, dryRun, and frameworkOnly fields." notable_decisions="none"]
|
|
110
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
111
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
112
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
36
113
|
interface MigrateOptions {
|
|
37
114
|
dbPassword?: string
|
|
38
115
|
dryRun: boolean
|
|
39
116
|
frameworkOnly: boolean
|
|
40
117
|
}
|
|
41
|
-
// CIL[
|
|
42
|
-
// CIL[
|
|
43
|
-
// CIL[DOC-
|
|
44
|
-
// CIL[DOC-
|
|
45
|
-
// CIL[DOC-CONTEXT module="cli.commands.migrate" layer="cli" related_files="[\".framework/migrations/015_simplify_apps_table.sql\",\".framework/src/pages/admin/RolesPage.tsx\",\"\\\"]"]
|
|
46
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="migration results" errors="database errors" side_effects="database writes"]
|
|
47
|
-
// CIL[DOC-MICRO logic_summary="Connects to PostgreSQL, creates migration tracking table, applies SQL files" notable_decisions="[]"]
|
|
48
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
49
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
50
|
-
// CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: .framework/migrations/015_simplify_apps_table.sql, .framework/src/pages/admin/RolesPage.tsx, \."]
|
|
51
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
52
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
53
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
118
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Declares the migrate command options.'; No verified external callers; imports: none"]
|
|
119
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
120
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
121
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
54
122
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
55
123
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
124
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:MigrateOptions:interface"]
|
|
125
|
+
|
|
126
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:runMigrations:function" type="function" identity="runMigrations" parent="~/.framework/cli/commands/migrate.ts"]
|
|
127
|
+
// CIL[DOC-MACRO purpose="Applies pending SQL migration files to the Supabase database and tracks which have been applied."]
|
|
128
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Executes migrations safely in transactions and records them in the tracking table."]
|
|
129
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
|
|
130
|
+
// CIL[DOC-CONTRACT inputs="opts: { frameworkOnly?: boolean }" outputs="Promise<{ applied: number; skipped: number; failed: number } | null>" errors="Returns null if credentials missing; throws on invalid SUPABASE_URL, tracking-table failures, and file read errors; logs per migration statement errors to stderr, rolls back, increments failed once, and stops." side_effects="Connects to Postgres, creates _spine_migrations table, executes SQL, inserts migration records, writes to stdout/stderr."]
|
|
131
|
+
// CIL[DOC-MICRO logic_summary="Reads env, validates SUPABASE_URL is a credential-free hosted https://<project-ref>.supabase.co URL, derives the db host, builds a pg.Client config object, collects migration files, filters already applied, splits and runs SQL statements, updates _spine_migrations, and returns counts." notable_decisions="Skips missing or placeholder credentials; non-HTTPS, credential-bearing, non-supabase.co, ported, pathed, or query/hash URLs are rejected before any client exists; uses a SET to track applied files; runs each migration in a transaction; tracking CREATE and SELECT propagate so migrations never run against unknown tracking state; first file error rolls back and breaks; the connected client always ends via finally."]
|
|
132
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
133
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
134
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
56
135
|
export async function runMigrations(opts: { frameworkOnly?: boolean } = {}): Promise<{ applied: number; skipped: number; failed: number } | null> {
|
|
57
136
|
const supabaseUrl = process.env.SUPABASE_URL
|
|
58
137
|
if (!supabaseUrl || supabaseUrl.includes('placeholder') || supabaseUrl.includes('your-project')) {
|
|
@@ -64,16 +143,41 @@ export async function runMigrations(opts: { frameworkOnly?: boolean } = {}): Pro
|
|
|
64
143
|
return null
|
|
65
144
|
}
|
|
66
145
|
|
|
67
|
-
|
|
68
|
-
|
|
146
|
+
let projectRef: string
|
|
147
|
+
try {
|
|
148
|
+
const parsed = new URL(supabaseUrl)
|
|
149
|
+
if (
|
|
150
|
+
parsed.protocol !== 'https:' ||
|
|
151
|
+
parsed.username !== '' ||
|
|
152
|
+
parsed.password !== '' ||
|
|
153
|
+
parsed.port !== '' ||
|
|
154
|
+
parsed.search !== '' ||
|
|
155
|
+
parsed.hash !== '' ||
|
|
156
|
+
(parsed.pathname !== '/' && parsed.pathname !== '') ||
|
|
157
|
+
!/^[a-z0-9-]+\.supabase\.co$/.test(parsed.hostname)
|
|
158
|
+
) {
|
|
159
|
+
throw new Error('not a hosted Supabase URL')
|
|
160
|
+
}
|
|
161
|
+
projectRef = parsed.hostname.split('.')[0]
|
|
162
|
+
} catch {
|
|
163
|
+
throw new Error('Invalid SUPABASE_URL — expected a URL like https://<project-ref>.supabase.co')
|
|
164
|
+
}
|
|
69
165
|
|
|
70
166
|
const migrationFiles = collectMigrations(opts.frameworkOnly ?? false)
|
|
71
167
|
if (migrationFiles.length === 0) return { applied: 0, skipped: 0, failed: 0 }
|
|
72
168
|
|
|
73
169
|
const { default: pg } = await import('pg')
|
|
74
|
-
const client = new pg.Client({
|
|
170
|
+
const client = new pg.Client({
|
|
171
|
+
user: 'postgres',
|
|
172
|
+
password: dbPassword,
|
|
173
|
+
host: `db.${projectRef}.supabase.co`,
|
|
174
|
+
port: 5432,
|
|
175
|
+
database: 'postgres',
|
|
176
|
+
})
|
|
75
177
|
await client.connect()
|
|
76
178
|
|
|
179
|
+
let applied = 0, skipped = 0, failed = 0
|
|
180
|
+
|
|
77
181
|
try {
|
|
78
182
|
await client.query(`
|
|
79
183
|
CREATE TABLE IF NOT EXISTS _spine_migrations (
|
|
@@ -82,62 +186,61 @@ export async function runMigrations(opts: { frameworkOnly?: boolean } = {}): Pro
|
|
|
82
186
|
applied_at TIMESTAMPTZ DEFAULT NOW()
|
|
83
187
|
)
|
|
84
188
|
`)
|
|
85
|
-
} catch { /* non-fatal */ }
|
|
86
189
|
|
|
87
|
-
let appliedMigrations = new Set<string>()
|
|
88
|
-
try {
|
|
89
190
|
const { rows } = await client.query('SELECT filename FROM _spine_migrations')
|
|
90
|
-
appliedMigrations = new Set(rows.map((r: { filename: string }) => r.filename))
|
|
91
|
-
} catch { /* non-fatal */ }
|
|
191
|
+
const appliedMigrations = new Set<string>(rows.map((r: { filename: string }) => r.filename))
|
|
92
192
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
continue
|
|
99
|
-
}
|
|
193
|
+
for (const { name, path } of migrationFiles) {
|
|
194
|
+
if (appliedMigrations.has(name)) {
|
|
195
|
+
skipped++
|
|
196
|
+
continue
|
|
197
|
+
}
|
|
100
198
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
199
|
+
const sql = readFileSync(path, 'utf8')
|
|
200
|
+
process.stdout.write(` Applying ${name}... `)
|
|
201
|
+
const statements = splitSqlStatements(sql)
|
|
104
202
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
203
|
+
try {
|
|
204
|
+
await client.query('BEGIN')
|
|
205
|
+
for (const stmt of statements) await client.query(stmt)
|
|
206
|
+
await client.query(
|
|
207
|
+
`INSERT INTO _spine_migrations (filename) VALUES ($1) ON CONFLICT (filename) DO NOTHING`,
|
|
208
|
+
[name]
|
|
209
|
+
)
|
|
210
|
+
await client.query('COMMIT')
|
|
211
|
+
console.log('✓')
|
|
212
|
+
applied++
|
|
213
|
+
} catch (err: any) {
|
|
214
|
+
await client.query('ROLLBACK').catch(() => { /* non-fatal */ })
|
|
215
|
+
console.log('✗')
|
|
216
|
+
console.error(` ${err.message}`)
|
|
217
|
+
failed++
|
|
218
|
+
break
|
|
219
|
+
}
|
|
120
220
|
}
|
|
221
|
+
} finally {
|
|
222
|
+
await client.end().catch(() => { /* non-fatal */ })
|
|
121
223
|
}
|
|
122
224
|
|
|
123
|
-
await client.end()
|
|
124
225
|
return { applied, skipped, failed }
|
|
125
226
|
}
|
|
126
|
-
// CIL[
|
|
127
|
-
// CIL[
|
|
128
|
-
// CIL[DOC-
|
|
129
|
-
// CIL[DOC-
|
|
130
|
-
// CIL[DOC-CONTEXT module="cli.commands.migrate" layer="cli" related_files="[\".framework/functions/_shared/schema-utils.ts\",\".framework/migrations/015_simplify_apps_table.sql\",\".framework/src/pages/admin/TypeDetailPage.tsx\",\"\\\"]"]
|
|
131
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="migration execution" errors="validation errors" side_effects="process exit"]
|
|
132
|
-
// CIL[DOC-MICRO logic_summary="Validates env vars, loads migrations, handles dry-run and execution" notable_decisions="[]"]
|
|
133
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
134
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
135
|
-
// CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/migrations/015_simplify_apps_table.sql, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
|
|
136
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
137
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
138
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
227
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Applies pending SQL migration files to the Supabase database and tracks which have been applied.'; No verified external callers; imports: none"]
|
|
228
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
229
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
230
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
139
231
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
140
232
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
233
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:runMigrations:function"]
|
|
234
|
+
|
|
235
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:migrateCommand:function" type="function" identity="migrateCommand" parent="~/.framework/cli/commands/migrate.ts"]
|
|
236
|
+
// CIL[DOC-MACRO purpose="CLI action that collects, optionally dry-runs, and applies framework migrations."]
|
|
237
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Validates environment, loads .env, handles dry run, and prints result."]
|
|
238
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
|
|
239
|
+
// CIL[DOC-CONTRACT inputs="options: MigrateOptions" outputs="Promise<void>" errors="Exits process with status 1 on missing credentials or failed migrations." side_effects="Reads .env, writes to stdout/stderr, may set process.env, calls process.exit."]
|
|
240
|
+
// CIL[DOC-MICRO logic_summary="Loads .env, verifies SUPABASE_URL and password, collects migration files, dry-run lists them or calls runMigrations, reports counts, and exits." notable_decisions="Supports --db-password, --dry-run, and --framework-only; sets process.env.SUPABASE_DB_PASSWORD if passed; hard exits on missing env or failed migrations."]
|
|
241
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
242
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
243
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
141
244
|
async function migrateCommand(options: MigrateOptions): Promise<void> {
|
|
142
245
|
console.log('\nRunning Spine Framework migrations...\n')
|
|
143
246
|
|
|
@@ -210,24 +313,26 @@ async function migrateCommand(options: MigrateOptions): Promise<void> {
|
|
|
210
313
|
|
|
211
314
|
console.log('\n✅ All migrations applied successfully!\n')
|
|
212
315
|
console.log('Next steps:')
|
|
213
|
-
console.log(' npx spine-framework install-app
|
|
316
|
+
console.log(' npx spine-framework install-app <app-package>')
|
|
214
317
|
console.log(' npm install && npm run assemble && netlify dev\n')
|
|
215
318
|
}
|
|
216
|
-
// CIL[END
|
|
217
|
-
|
|
218
|
-
// CIL[
|
|
219
|
-
// CIL[DOC-
|
|
220
|
-
// CIL[DOC-
|
|
221
|
-
// CIL[DOC-
|
|
222
|
-
// CIL[DOC-
|
|
223
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
224
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
225
|
-
// CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: .framework/functions/_shared/schema-utils.ts, .framework/src/components/ui/dialog.tsx, .framework/functions/_shared/principal.ts, .framework/src/components/ui/table-primitives.tsx, .framework/src/pages/admin/TypeDetailPage.tsx, \."]
|
|
226
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
227
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
228
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
319
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:migrateCommand:function"]
|
|
320
|
+
|
|
321
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:registerMigrateCommands:function" type="function" identity="registerMigrateCommands" parent="~/.framework/cli/commands/migrate.ts"]
|
|
322
|
+
// CIL[DOC-VECTOR type="context" content="purpose='CLI action that collects, optionally dry-runs, and applies framework migrations.'; No verified external callers; imports: none"]
|
|
323
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
324
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
325
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
229
326
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
230
327
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
328
|
+
// CIL[DOC-MACRO purpose="Registers the migrate command with the Commander program."]
|
|
329
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Defines CLI command options and delegates to migrateCommand."]
|
|
330
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
|
|
331
|
+
// CIL[DOC-CONTRACT inputs="program: Command" outputs="void" errors="Logs error and exits on action failure." side_effects="Mutates the Commander program with a new command."]
|
|
332
|
+
// CIL[DOC-MICRO logic_summary="Adds the migrate command with --db-password, --dry-run, and --framework-only options and an async action." notable_decisions="Catches action errors, prints messages, and exits on failure; logs stack if SPINE_CLI_DEBUG."]
|
|
333
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
334
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
335
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
231
336
|
export function registerMigrateCommands(program: Command) {
|
|
232
337
|
program
|
|
233
338
|
.command('migrate')
|
|
@@ -245,21 +350,23 @@ export function registerMigrateCommands(program: Command) {
|
|
|
245
350
|
}
|
|
246
351
|
})
|
|
247
352
|
}
|
|
248
|
-
// CIL[
|
|
249
|
-
// CIL[
|
|
250
|
-
// CIL[DOC-
|
|
251
|
-
// CIL[DOC-
|
|
252
|
-
// CIL[DOC-CONTEXT module="cli.commands.migrate" layer="cli" related_files="[\"\\\"]"]
|
|
253
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="process.env updates" errors="file read errors" side_effects="process.env mutation"]
|
|
254
|
-
// CIL[DOC-MICRO logic_summary="Reads .env file, parses key=value pairs, sets process.env" notable_decisions="[]"]
|
|
255
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
256
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
257
|
-
// CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: \."]
|
|
258
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
259
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
260
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
353
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Registers the migrate command with the Commander program.'; No verified external callers; imports: none"]
|
|
354
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
355
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
356
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
261
357
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
262
358
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
359
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:registerMigrateCommands:function"]
|
|
360
|
+
|
|
361
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:loadEnv:function" type="function" identity="loadEnv" parent="~/.framework/cli/commands/migrate.ts"]
|
|
362
|
+
// CIL[DOC-MACRO purpose="Loads key=value pairs from the project .env file into process.env."]
|
|
363
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Reads .env without overwriting existing environment variables."]
|
|
364
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
|
|
365
|
+
// CIL[DOC-CONTRACT inputs="none (reads PROJECT_ROOT/.env)" outputs="void" errors="silently returns if .env is missing" side_effects="Mutates process.env."]
|
|
366
|
+
// CIL[DOC-MICRO logic_summary="Reads .env lines, skips comments and blank lines, parses the first = into key and value, and sets process.env if absent." notable_decisions="Ignores malformed lines; does not overwrite existing environment variables."]
|
|
367
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
368
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
369
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
263
370
|
function loadEnv() {
|
|
264
371
|
const envPath = join(PROJECT_ROOT, '.env')
|
|
265
372
|
if (!existsSync(envPath)) return
|
|
@@ -274,22 +381,24 @@ function loadEnv() {
|
|
|
274
381
|
if (key && !(key in process.env)) process.env[key] = val
|
|
275
382
|
}
|
|
276
383
|
}
|
|
277
|
-
// CIL[
|
|
278
|
-
// CIL[
|
|
279
|
-
// CIL[DOC-
|
|
280
|
-
// CIL[DOC-
|
|
281
|
-
// CIL[DOC-CONTEXT module="cli.commands.migrate" layer="cli" related_files="[]"]
|
|
282
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="migration file list" errors="filesystem errors" side_effects="none"]
|
|
283
|
-
// CIL[DOC-MICRO logic_summary="Scans .framework/migrations and custom/migrations for .sql files" notable_decisions="[]"]
|
|
284
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="none"]
|
|
285
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
286
|
-
// CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
287
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
288
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
289
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
384
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Loads key=value pairs from the project .env file into process.env.'; No verified external callers; imports: none"]
|
|
385
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
386
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
387
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
290
388
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
291
389
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
292
|
-
|
|
390
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:loadEnv:function"]
|
|
391
|
+
|
|
392
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:collectMigrations:function" type="function" identity="collectMigrations" parent="~/.framework/cli/commands/migrate.ts"]
|
|
393
|
+
// CIL[DOC-MACRO purpose="Collects SQL migration files from framework and custom directories."]
|
|
394
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Sorts and returns file paths for pending migrations, optionally including custom migrations."]
|
|
395
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
|
|
396
|
+
// CIL[DOC-CONTRACT inputs="frameworkOnly: boolean" outputs="Array<{ name: string; path: string }>" errors="none" side_effects="Reads directories via readdirSync."]
|
|
397
|
+
// CIL[DOC-MICRO logic_summary="Resolves the framework migrations directory, optionally adds custom/migrations, and returns sorted .sql entries." notable_decisions="Prefers PROJECT_ROOT/.framework/migrations over PACKAGE_ROOT; filters dotfiles and non-.sql files."]
|
|
398
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
399
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
400
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
401
|
+
export function collectMigrations(frameworkOnly: boolean): { name: string; path: string }[] {
|
|
293
402
|
const files: { name: string; path: string }[] = []
|
|
294
403
|
|
|
295
404
|
|
|
@@ -317,47 +426,81 @@ function collectMigrations(frameworkOnly: boolean): { name: string; path: string
|
|
|
317
426
|
|
|
318
427
|
return files
|
|
319
428
|
}
|
|
320
|
-
// CIL[
|
|
321
|
-
// CIL[
|
|
322
|
-
// CIL[DOC-
|
|
323
|
-
// CIL[DOC-
|
|
324
|
-
// CIL[DOC-CONTEXT module="cli.commands.migrate" layer="cli" related_files="[]"]
|
|
325
|
-
// CIL[DOC-CONTRACT inputs="none" outputs="statement array" errors="parsing errors" side_effects="none"]
|
|
326
|
-
// CIL[DOC-MICRO logic_summary="Handles dollar-quoted blocks, removes comments, splits on semicolons" notable_decisions="[]"]
|
|
327
|
-
// CIL[DOC-CONFIDENCE pass="second" score="0.95" flags="complex_sql_parsing"]
|
|
328
|
-
// CIL[DOC-STABILITY stability="stable"]
|
|
329
|
-
// CIL[DOC-VECTOR type="context" content="Layer: cli. Direct callers: 0. Direct calls: 0. Related files: none."]
|
|
330
|
-
// CIL[DOC-VECTOR type="blast_radius" content="Direct callers: 0. Total affected: 0."]
|
|
331
|
-
// CIL[DOC-VECTOR type="configuration" content="No configuration dependencies."]
|
|
332
|
-
// CIL[DOC-VECTOR type="constraint" content="No test paths identified."]
|
|
429
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Collects SQL migration files from framework and custom directories.'; No verified external callers; imports: none"]
|
|
430
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
431
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
432
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
333
433
|
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
334
434
|
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
435
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:collectMigrations:function"]
|
|
436
|
+
|
|
437
|
+
// CIL[BEGIN stable_id="~/.framework/cli/commands/migrate.ts:splitSqlStatements:function" type="function" identity="splitSqlStatements" parent="~/.framework/cli/commands/migrate.ts"]
|
|
438
|
+
// CIL[DOC-MACRO purpose="Splits SQL into executable statements while preserving dollar-quoted blocks."]
|
|
439
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Removes single-line comments, splits on semicolons, restores protected dollar-quoted blocks, and returns trimmed statements."]
|
|
440
|
+
// CIL[DOC-CONTEXT module="cli" layer="framework" related_files=".framework/cli/commands/migrate.ts"]
|
|
441
|
+
// CIL[DOC-CONTRACT inputs="sql: string" outputs="Array<string>" errors="none" side_effects="none"]
|
|
442
|
+
// CIL[DOC-MICRO logic_summary="Single-pass scanner tracking --, /* */, single-quote, double-quote, and dollar-tag state so ; only splits statements in normal state" notable_decisions="Regex layering was abandoned — apostrophes inside comments and semicolons inside literals broke both orderings; a state machine is the only correct approach."]
|
|
443
|
+
// CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
|
|
444
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
445
|
+
// CIL[DOC-AUDIENCE audience="engineers"]
|
|
446
|
+
export function splitSqlStatements(sql: string): string[] {
|
|
447
|
+
// Single-pass scanner: a ; only ends a statement in normal state. Comments
|
|
448
|
+
// are dropped; string literals, quoted identifiers, and dollar-quoted blocks
|
|
449
|
+
// are preserved verbatim.
|
|
450
|
+
const statements: string[] = []
|
|
451
|
+
let buf = ''
|
|
452
|
+
let i = 0
|
|
453
|
+
let inLine = false, inBlock = false, inSingle = false, inDouble = false
|
|
454
|
+
let dollarTag: string | null = null
|
|
455
|
+
|
|
456
|
+
while (i < sql.length) {
|
|
457
|
+
const ch = sql[i], next = sql[i + 1]
|
|
458
|
+
|
|
459
|
+
if (inLine) { if (ch === '\n') inLine = false; i++; continue }
|
|
460
|
+
if (inBlock) { if (ch === '*' && next === '/') { inBlock = false; i += 2 } else i++; continue }
|
|
461
|
+
|
|
462
|
+
if (dollarTag) {
|
|
463
|
+
if (sql.startsWith(dollarTag, i)) { buf += dollarTag; i += dollarTag.length; dollarTag = null }
|
|
464
|
+
else { buf += ch; i++ }
|
|
465
|
+
continue
|
|
466
|
+
}
|
|
467
|
+
if (inSingle) {
|
|
468
|
+
buf += ch
|
|
469
|
+
if (ch === "'") { if (next === "'") { buf += next; i++ } else inSingle = false }
|
|
470
|
+
i++; continue
|
|
471
|
+
}
|
|
472
|
+
if (inDouble) {
|
|
473
|
+
buf += ch
|
|
474
|
+
if (ch === '"') inDouble = false
|
|
475
|
+
i++; continue
|
|
476
|
+
}
|
|
346
477
|
|
|
347
|
-
|
|
348
|
-
|
|
478
|
+
if (ch === '-' && next === '-') { inLine = true; i += 2; continue }
|
|
479
|
+
if (ch === '/' && next === '*') { inBlock = true; i += 2; continue }
|
|
480
|
+
if (ch === "'") { inSingle = true; buf += ch; i++; continue }
|
|
481
|
+
if (ch === '"') { inDouble = true; buf += ch; i++; continue }
|
|
482
|
+
if (ch === '$') {
|
|
483
|
+
const m = sql.slice(i).match(/^\$[A-Za-z_]*\$/)
|
|
484
|
+
if (m) { dollarTag = m[0]; buf += m[0]; i += m[0].length; continue }
|
|
485
|
+
}
|
|
486
|
+
if (ch === ';') {
|
|
487
|
+
const s = buf.trim()
|
|
488
|
+
if (s) statements.push(s + ';')
|
|
489
|
+
buf = ''
|
|
490
|
+
i++
|
|
491
|
+
continue
|
|
492
|
+
}
|
|
493
|
+
buf += ch; i++
|
|
494
|
+
}
|
|
349
495
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
.map(s => {
|
|
354
|
-
let restored = s.trim()
|
|
355
|
-
dollarBlocks.forEach((block, idx) => {
|
|
356
|
-
restored = restored.replace(`__DOLLAR_BLOCK_${idx}__`, () => block)
|
|
357
|
-
})
|
|
358
|
-
return restored
|
|
359
|
-
})
|
|
360
|
-
.filter(s => s.length > 0)
|
|
361
|
-
.map(s => s + ';')
|
|
496
|
+
const tail = buf.trim()
|
|
497
|
+
if (tail) statements.push(tail + ';')
|
|
498
|
+
return statements
|
|
362
499
|
}
|
|
363
|
-
// CIL[
|
|
500
|
+
// CIL[DOC-VECTOR type="context" content="purpose='Splits SQL into executable statements while preserving dollar-quoted blocks.'; No verified external callers; imports: none"]
|
|
501
|
+
// CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
|
|
502
|
+
// CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
|
|
503
|
+
// CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
|
|
504
|
+
// CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
|
|
505
|
+
// CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
|
|
506
|
+
// CIL[END stable_id="~/.framework/cli/commands/migrate.ts:splitSqlStatements:function"]
|