@agent-native/core 0.85.6 → 0.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +130 -1
- package/corpus/core/README.md +0 -11
- package/corpus/core/docs/content/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/ar-SA/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/ar-SA/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/ar-SA/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/ar-SA/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/ar-SA/workspace-connections.mdx +11 -11
- package/corpus/core/docs/content/locales/de-DE/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/de-DE/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/de-DE/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/de-DE/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/es-ES/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/es-ES/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/es-ES/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/fr-FR/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/fr-FR/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/fr-FR/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/hi-IN/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/hi-IN/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/hi-IN/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/ja-JP/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/ja-JP/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/ja-JP/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/ko-KR/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/ko-KR/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/ko-KR/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/pt-BR/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/pt-BR/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/pt-BR/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/zh-CN/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/zh-CN/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/zh-CN/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/cloneable-saas.mdx +0 -1
- package/corpus/core/docs/content/locales/zh-TW/plan-plugin.mdx +10 -9
- package/corpus/core/docs/content/locales/zh-TW/sharing.mdx +1 -2
- package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +2 -3
- package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +23 -7
- package/corpus/core/docs/content/locales/zh-TW/tracking.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/workspace-connections.mdx +1 -1
- package/corpus/core/docs/content/plan-plugin.mdx +12 -11
- package/corpus/core/docs/content/sharing.mdx +1 -2
- package/corpus/core/docs/content/skills-guide.mdx +4 -3
- package/corpus/core/docs/content/template-plan.mdx +37 -6
- package/corpus/core/docs/content/tracking.mdx +1 -1
- package/corpus/core/docs/content/workspace-connections.mdx +1 -1
- package/corpus/core/package.json +6 -6
- package/corpus/core/src/agent/run-store.ts +1 -1
- package/corpus/core/src/chat-threads/store.ts +73 -11
- package/corpus/core/src/checkpoints/store.ts +13 -2
- package/corpus/core/src/cli/create.ts +3 -4
- package/corpus/core/src/cli/design-connect.ts +469 -9
- package/corpus/core/src/cli/index.ts +13 -0
- package/corpus/core/src/cli/plan-local.ts +281 -24
- package/corpus/core/src/cli/skills.ts +177 -21
- package/corpus/core/src/cli/templates-meta.ts +0 -13
- package/corpus/core/src/cli/visualize-repo.ts +715 -0
- package/corpus/core/src/client/AssistantChat.tsx +126 -17
- package/corpus/core/src/client/agent-chat-adapter.ts +6 -5
- package/corpus/core/src/client/app-providers.tsx +2 -2
- package/corpus/core/src/client/collab/index.ts +31 -0
- package/corpus/core/src/client/components/LiveCursorOverlay.tsx +16 -1
- package/corpus/core/src/client/components/PresenceBar.tsx +14 -1
- package/corpus/core/src/client/components/RecentEditHighlights.tsx +219 -0
- package/corpus/core/src/client/components/RemoteSelectionRings.tsx +40 -6
- package/corpus/core/src/client/index.ts +48 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +0 -4
- package/corpus/core/src/client/rich-markdown-editor/SharedRichEditor.tsx +49 -32
- package/corpus/core/src/client/rich-markdown-editor/index.ts +6 -0
- package/corpus/core/src/client/rich-markdown-editor/surgical-apply.ts +192 -0
- package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +59 -8
- package/corpus/core/src/client/session-replay.ts +181 -15
- package/corpus/core/src/client/sse-event-processor.ts +90 -1
- package/corpus/core/src/client/use-action.ts +123 -25
- package/corpus/core/src/client/use-agent-engine-configured.ts +7 -1
- package/corpus/core/src/client/use-chat-threads.ts +18 -7
- package/corpus/core/src/client/use-db-sync.ts +104 -19
- package/corpus/core/src/client/use-pinch-zoom.ts +76 -11
- package/corpus/core/src/client/visual-style-controls.tsx +475 -0
- package/corpus/core/src/collab/agent-presence.ts +191 -62
- package/corpus/core/src/collab/awareness.ts +83 -6
- package/corpus/core/src/collab/client.ts +89 -146
- package/corpus/core/src/collab/index.ts +34 -0
- package/corpus/core/src/collab/presence.ts +63 -3
- package/corpus/core/src/collab/recent-edits.ts +171 -0
- package/corpus/core/src/collab/undo.ts +432 -0
- package/corpus/core/src/collab/ydoc-manager.ts +68 -0
- package/corpus/core/src/connections/catalog.ts +2 -3
- package/corpus/core/src/db/create-get-db.ts +86 -1
- package/corpus/core/src/db/ensure-additive-columns.ts +430 -0
- package/corpus/core/src/db/index.ts +6 -0
- package/corpus/core/src/db/migrations.ts +236 -35
- package/corpus/core/src/jobs/scheduler.ts +17 -14
- package/corpus/core/src/observability/traces.ts +182 -1
- package/corpus/core/src/org/context.ts +79 -2
- package/corpus/core/src/server/agent-chat-plugin.ts +10 -6
- package/corpus/core/src/server/auth-marketing.ts +0 -11
- package/corpus/core/src/server/auth.ts +11 -4
- package/corpus/core/src/server/collab-plugin.ts +56 -13
- package/corpus/core/src/server/design-token-utils.ts +1 -1
- package/corpus/core/src/server/fusion-app.ts +447 -0
- package/corpus/core/src/server/index.ts +13 -0
- package/corpus/core/src/server/onboarding-html.ts +3 -4
- package/corpus/core/src/server/poll-events.ts +14 -2
- package/corpus/core/src/server/poll.ts +219 -12
- package/corpus/core/src/server/schema-prompt.ts +28 -9
- package/corpus/core/src/settings/store.ts +33 -2
- package/corpus/core/src/sharing/actions/set-resource-visibility.ts +2 -0
- package/corpus/core/src/sharing/actions/share-resource.ts +3 -0
- package/corpus/core/src/sharing/actions/unshare-resource.ts +2 -0
- package/corpus/core/src/styles/agent-native.css +0 -5
- package/corpus/core/src/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/core/src/templates/default/package.json +3 -3
- package/corpus/core/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
- package/corpus/core/src/tracking/providers.ts +22 -1
- package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/analytics/.agents/skills/session-replay/SKILL.md +20 -5
- package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/analytics/AGENTS.md +33 -6
- package/corpus/templates/analytics/actions/navigate.ts +14 -4
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
- package/corpus/templates/analytics/actions/view-screen.ts +57 -0
- package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +23 -1
- package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +21 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +7 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +15 -1
- package/corpus/templates/analytics/app/i18n-data.ts +151 -10
- package/corpus/templates/analytics/app/pages/Agents.tsx +118 -0
- package/corpus/templates/analytics/app/pages/DataSources.tsx +11 -1
- package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +76 -40
- package/corpus/templates/analytics/app/pages/sessions/session-replay-devtools.ts +5 -0
- package/corpus/templates/analytics/app/routes/agents.tsx +10 -0
- package/corpus/templates/analytics/changelog/2026-07-03-agent-admin-tools-page.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-03-agent-llm-observability-dashboard.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-03-session-recordings-now-include-response-bodies-for-5xx-error.md +6 -0
- package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +34 -0
- package/corpus/templates/analytics/docs/schemas/tracked-events.md +6 -0
- package/corpus/templates/analytics/package.json +3 -3
- package/corpus/templates/analytics/seeds/dashboards/agent-observability-llm.json +173 -0
- package/corpus/templates/analytics/server/jobs/analytics-alerts.ts +23 -5
- package/corpus/templates/analytics/server/lib/analytics-alerts.ts +58 -13
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +23 -0
- package/corpus/templates/analytics/server/lib/dashboard-seeds.ts +5 -0
- package/corpus/templates/analytics/server/lib/session-replay-agent-context.ts +120 -8
- package/corpus/templates/analytics/server/lib/session-replay.ts +3 -2
- package/corpus/templates/analytics/server/plugins/db.ts +93 -2
- package/corpus/templates/analytics/server/routes/api/session-replay/agent-diagnostics.json.get.ts +45 -1
- package/corpus/templates/analytics/shared/session-replay-diagnostics.ts +10 -0
- package/corpus/templates/assets/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/assets/package.json +3 -3
- package/corpus/templates/assets/server/plugins/db.ts +63 -2
- package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/brain/package.json +3 -3
- package/corpus/templates/brain/server/plugins/db.ts +75 -2
- package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/calendar/package.json +3 -3
- package/corpus/templates/calendar/server/plugins/db.ts +64 -2
- package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/chat/package.json +3 -3
- package/corpus/templates/clips/actions/finalize-recording.ts +50 -40
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +8 -6
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +3 -3
- package/corpus/templates/clips/changelog/2026-07-03-mobile-recording-pages-keep-videos-in-a-16-9-player-with-act.md +6 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +245 -77
- package/corpus/templates/clips/package.json +3 -3
- package/corpus/templates/clips/server/lib/recording-upload-state.ts +56 -0
- package/corpus/templates/clips/server/plugins/db.ts +68 -1
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +27 -3
- package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/content/actions/edit-document.ts +48 -1
- package/corpus/templates/content/actions/list-documents.ts +101 -94
- package/corpus/templates/content/actions/search-documents.ts +19 -3
- package/corpus/templates/content/actions/update-document.ts +54 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +127 -7
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +97 -2
- package/corpus/templates/content/changelog/2026-07-03-agent-document-edits-now-appear-as-a-live-collaborator-prese.md +6 -0
- package/corpus/templates/content/changelog/2026-07-03-document-search-and-list-views-load-faster-on-large-workspac.md +6 -0
- package/corpus/templates/content/package.json +3 -3
- package/corpus/templates/content/server/plugins/db.ts +57 -1
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +190 -13
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +16 -4
- package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +46 -3
- package/corpus/templates/design/.agents/skills/full-app-build/SKILL.md +140 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +20 -0
- package/corpus/templates/design/AGENTS.md +83 -13
- package/corpus/templates/design/actions/add-fusion-screens.ts +91 -0
- package/corpus/templates/design/actions/apply-a11y-fix.ts +5 -1
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +24 -69
- package/corpus/templates/design/actions/apply-fusion-edits.ts +161 -0
- package/corpus/templates/design/actions/apply-motion-edit.ts +29 -2
- package/corpus/templates/design/actions/apply-visual-edit.ts +38 -3
- package/corpus/templates/design/actions/connect-localhost.ts +25 -18
- package/corpus/templates/design/actions/create-component.ts +5 -1
- package/corpus/templates/design/actions/create-fusion-app.ts +202 -0
- package/corpus/templates/design/actions/deploy-fusion-app.ts +123 -0
- package/corpus/templates/design/actions/edit-design.ts +13 -16
- package/corpus/templates/design/actions/export-pdf.ts +8 -1
- package/corpus/templates/design/actions/export-zip.ts +10 -1
- package/corpus/templates/design/actions/get-fusion-deploy-status.ts +86 -0
- package/corpus/templates/design/actions/get-motion-timeline.ts +26 -20
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +10 -0
- package/corpus/templates/design/actions/insert-asset.ts +190 -7
- package/corpus/templates/design/actions/list-fusion-edits.ts +96 -0
- package/corpus/templates/design/actions/list-local-files.ts +133 -0
- package/corpus/templates/design/actions/open-visual-edit.ts +27 -5
- package/corpus/templates/design/actions/present-design-variants.ts +2 -2
- package/corpus/templates/design/actions/push-fusion-app.ts +62 -0
- package/corpus/templates/design/actions/queue-fusion-edit.ts +112 -0
- package/corpus/templates/design/actions/read-local-file.ts +139 -0
- package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +18 -14
- package/corpus/templates/design/actions/run-design-audit.ts +7 -4
- package/corpus/templates/design/actions/send-fusion-message.ts +69 -0
- package/corpus/templates/design/actions/sync-fusion-app.ts +196 -0
- package/corpus/templates/design/actions/write-local-file.ts +162 -36
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +12 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +600 -66
- package/corpus/templates/design/app/components/design/EditPanel.tsx +793 -304
- package/corpus/templates/design/app/components/design/FusionAppBanner.tsx +328 -0
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +671 -154
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +1 -1
- package/corpus/templates/design/app/components/design/MotionDock.tsx +234 -46
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +2070 -420
- package/corpus/templates/design/app/components/design/StatesPanel.tsx +25 -2
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +7 -98
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +640 -72
- package/corpus/templates/design/app/components/design/bridge/motion-preview.bridge.ts +605 -0
- package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +50 -26
- package/corpus/templates/design/app/components/design/code-workbench/ActivityBar.tsx +85 -0
- package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +466 -0
- package/corpus/templates/design/app/components/design/code-workbench/SideBar.tsx +53 -0
- package/corpus/templates/design/app/components/design/code-workbench/commands.ts +339 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/Breadcrumbs.tsx +42 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/BufferSync.tsx +128 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/EditorTabs.tsx +363 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +268 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/StatusBar.tsx +208 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-setup.ts +61 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-theme-palette.ts +191 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/monaco-theme.ts +29 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/status-bar-lang.ts +21 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/tab-drag.ts +27 -0
- package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +155 -0
- package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +551 -0
- package/corpus/templates/design/app/components/design/code-workbench/explorer/file-icons.tsx +115 -0
- package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open.ts +65 -0
- package/corpus/templates/design/app/components/design/code-workbench/format/prettier-format.ts +182 -0
- package/corpus/templates/design/app/components/design/code-workbench/model-registry.ts +133 -0
- package/corpus/templates/design/app/components/design/code-workbench/quickinput/QuickInput.tsx +563 -0
- package/corpus/templates/design/app/components/design/code-workbench/quickinput/fuzzy.ts +170 -0
- package/corpus/templates/design/app/components/design/code-workbench/search/SearchView.tsx +508 -0
- package/corpus/templates/design/app/components/design/code-workbench/search/search-engine.ts +280 -0
- package/corpus/templates/design/app/components/design/code-workbench/store.tsx +734 -0
- package/corpus/templates/design/app/components/design/code-workbench/workspace/create-providers.ts +39 -0
- package/corpus/templates/design/app/components/design/code-workbench/workspace/inline-provider.ts +196 -0
- package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +177 -0
- package/corpus/templates/design/app/components/design/code-workbench/workspace/tree.ts +110 -0
- package/corpus/templates/design/app/components/design/code-workbench/workspace/types.ts +103 -0
- package/corpus/templates/design/app/components/design/code-workbench-theme.ts +68 -0
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +16 -4
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +217 -113
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +111 -5
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +13 -2
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +79 -16
- package/corpus/templates/design/app/components/design/inspector/index.ts +9 -0
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +67 -2
- package/corpus/templates/design/app/components/design/types.ts +16 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +80 -1
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +24 -6
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +15 -1
- package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +6 -16
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +77 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +2 -0
- package/corpus/templates/design/app/i18n-data.ts +31 -0
- package/corpus/templates/design/app/lib/design-import.ts +95 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +5586 -1112
- package/corpus/templates/design/app/pages/Index.tsx +90 -17
- package/corpus/templates/design/changelog/2026-07-03-canvas-interactions-now-match-figma-rotation-aware-resizing-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-inspector-fixes-mixed-selections-show-mixed-instead-of-wrong.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-keyframe-timeline-works-reliably-drag-keyframes-smoothly-pic.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-layers-panel-matches-figma-top-layer-on-top-drag-with-auto-s.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-much-faster-editor-smooth-dragging-zooming-and-panel-updates.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-pen-tool-refinements-click-the-first-point-to-close-with-a-d.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-text-editing-enter-adds-a-line-break-international-ime-typin.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-the-ai-now-edits-like-a-collaborator-on-canvas-its-cursor-gl.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-the-code-panel-is-now-a-full-vs-code-style-editor-with-a-fil.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-undo-and-redo-are-dependable-across-agent-edits-screen-switc.md +6 -0
- package/corpus/templates/design/package.json +4 -3
- package/corpus/templates/design/server/db/schema.ts +31 -0
- package/corpus/templates/design/server/lib/design-export.ts +43 -1
- package/corpus/templates/design/server/lib/fusion-screens.ts +246 -0
- package/corpus/templates/design/server/plugins/db.ts +89 -2
- package/corpus/templates/design/shared/board-file.ts +25 -5
- package/corpus/templates/design/shared/canvas-math.ts +754 -9
- package/corpus/templates/design/shared/code-layer.ts +304 -26
- package/corpus/templates/design/shared/collab-selection.ts +52 -0
- package/corpus/templates/design/shared/color-utils.ts +84 -0
- package/corpus/templates/design/shared/design-source-capabilities.ts +16 -7
- package/corpus/templates/design/shared/full-app.ts +126 -0
- package/corpus/templates/design/shared/motion-compiler.ts +75 -31
- package/corpus/templates/design/shared/motion-timeline.ts +335 -0
- package/corpus/templates/design/shared/pen-path.ts +496 -23
- package/corpus/templates/dispatch/package.json +3 -3
- package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/forms/package.json +3 -3
- package/corpus/templates/forms/server/plugins/db.ts +62 -2
- package/corpus/templates/macros/package.json +3 -3
- package/corpus/templates/macros/server/plugins/db.ts +63 -2
- package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +8 -0
- package/corpus/templates/mail/package.json +3 -3
- package/corpus/templates/mail/server/lib/contact-frequency.ts +42 -15
- package/corpus/templates/mail/server/plugins/db.ts +63 -2
- package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +9 -3
- package/corpus/templates/plan/.agents/skills/visualize-repo/SKILL.md +92 -0
- package/corpus/templates/plan/actions/export-visual-plan.ts +5 -0
- package/corpus/templates/plan/actions/get-local-plan-folder.ts +4 -22
- package/corpus/templates/plan/actions/get-plan-version.ts +6 -16
- package/corpus/templates/plan/actions/list-plan-versions.ts +48 -20
- package/corpus/templates/plan/actions/patch-visual-plan-source.ts +41 -1
- package/corpus/templates/plan/actions/promote-local-plan-folder.ts +4 -22
- package/corpus/templates/plan/actions/update-local-plan-comments.ts +4 -2
- package/corpus/templates/plan/actions/update-local-plan-folder.ts +4 -22
- package/corpus/templates/plan/actions/update-visual-plan.ts +60 -1
- package/corpus/templates/plan/agent-native.app-skill.json +10 -0
- package/corpus/templates/plan/app/components/editor/PlanDocumentEditor.tsx +138 -39
- package/corpus/templates/plan/app/components/editor/usePlanUndoStack.ts +165 -23
- package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +80 -4
- package/corpus/templates/plan/app/global.css +11 -9
- package/corpus/templates/plan/app/hooks/use-navigation-state.ts +10 -1
- package/corpus/templates/plan/app/hooks/use-plan-presence.ts +66 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +215 -63
- package/corpus/templates/plan/changelog/2026-07-03-local-visual-plans-and-recaps-can-save-comments-without-sign.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-03-plan-tabs-render-nested-text-instead-of-raw-json.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-03-plans-are-now-fully-real-time-collaborative-multiple-people-.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-03-plans-open-and-refresh-faster-especially-long-lived-plans-wi.md +6 -0
- package/corpus/templates/plan/changelog/2026-07-03-undo-now-survives-agent-edits-cmd-z-keeps-working-on-your-ow.md +6 -0
- package/corpus/templates/plan/package.json +5 -3
- package/corpus/templates/plan/server/db/schema.ts +12 -0
- package/corpus/templates/plan/server/lib/local-plan-kind.ts +25 -0
- package/corpus/templates/plan/server/lib/plan-versions.ts +83 -1
- package/corpus/templates/plan/server/lib/public-action-paths.ts +0 -2
- package/corpus/templates/plan/server/plans.ts +26 -3
- package/corpus/templates/plan/server/plugins/db.ts +105 -2
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +8 -4
- package/corpus/templates/slides/AGENTS.md +4 -0
- package/corpus/templates/slides/actions/_agent-presence.ts +48 -0
- package/corpus/templates/slides/actions/add-slide.ts +16 -18
- package/corpus/templates/slides/actions/patch-deck.ts +4 -2
- package/corpus/templates/slides/actions/update-slide.ts +114 -77
- package/corpus/templates/slides/actions/view-screen.ts +39 -0
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +47 -3
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +32 -35
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +625 -199
- package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +342 -0
- package/corpus/templates/slides/app/components/editor/TweaksPanel.tsx +46 -96
- package/corpus/templates/slides/app/components/visual-editor/SaveStatusIndicator.tsx +8 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +589 -176
- package/corpus/templates/slides/app/hooks/use-deck-presence.ts +84 -42
- package/corpus/templates/slides/app/i18n/ar-SA.ts +46 -0
- package/corpus/templates/slides/app/i18n/de-DE.ts +46 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +46 -0
- package/corpus/templates/slides/app/i18n/es-ES.ts +46 -0
- package/corpus/templates/slides/app/i18n/fr-FR.ts +46 -0
- package/corpus/templates/slides/app/i18n/hi-IN.ts +46 -0
- package/corpus/templates/slides/app/i18n/ja-JP.ts +46 -0
- package/corpus/templates/slides/app/i18n/ko-KR.ts +46 -0
- package/corpus/templates/slides/app/i18n/pt-BR.ts +46 -0
- package/corpus/templates/slides/app/i18n/zh-CN.ts +46 -0
- package/corpus/templates/slides/app/i18n/zh-TW.ts +46 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +25 -13
- package/corpus/templates/slides/changelog/2026-07-03-figma-style-slide-editing.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-03-see-the-ai-working-with-you-when-the-agent-edits-a-slide-it-.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-03-undo-redo-is-now-precise-and-safe-with-collaborators-it-only.md +6 -0
- package/corpus/templates/slides/package.json +3 -3
- package/corpus/templates/slides/server/handlers/decks.ts +31 -3
- package/corpus/templates/slides/server/plugins/db.ts +65 -2
- package/corpus/templates/videos/netlify.toml +1 -12
- package/dist/agent/run-store.js +1 -1
- package/dist/agent/run-store.js.map +1 -1
- package/dist/chat-threads/store.d.ts +9 -1
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +63 -11
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/checkpoints/store.d.ts.map +1 -1
- package/dist/checkpoints/store.js +10 -2
- package/dist/checkpoints/store.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +3 -5
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/design-connect.d.ts +49 -1
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +414 -9
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/index.js +12 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plan-local.d.ts +24 -0
- package/dist/cli/plan-local.d.ts.map +1 -1
- package/dist/cli/plan-local.js +188 -20
- package/dist/cli/plan-local.js.map +1 -1
- package/dist/cli/skills.d.ts +3 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +173 -21
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/templates-meta.d.ts.map +1 -1
- package/dist/cli/templates-meta.js +0 -14
- package/dist/cli/templates-meta.js.map +1 -1
- package/dist/cli/visualize-repo.d.ts +49 -0
- package/dist/cli/visualize-repo.d.ts.map +1 -0
- package/dist/cli/visualize-repo.js +561 -0
- package/dist/cli/visualize-repo.js.map +1 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +120 -15
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +6 -5
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/app-providers.d.ts +2 -2
- package/dist/client/app-providers.js.map +1 -1
- package/dist/client/collab/index.d.ts +4 -1
- package/dist/client/collab/index.d.ts.map +1 -1
- package/dist/client/collab/index.js +3 -0
- package/dist/client/collab/index.js.map +1 -1
- package/dist/client/components/LiveCursorOverlay.d.ts.map +1 -1
- package/dist/client/components/LiveCursorOverlay.js +11 -3
- package/dist/client/components/LiveCursorOverlay.js.map +1 -1
- package/dist/client/components/PresenceBar.d.ts.map +1 -1
- package/dist/client/components/PresenceBar.js +6 -1
- package/dist/client/components/PresenceBar.js.map +1 -1
- package/dist/client/components/RecentEditHighlights.d.ts +43 -0
- package/dist/client/components/RecentEditHighlights.d.ts.map +1 -0
- package/dist/client/components/RecentEditHighlights.js +146 -0
- package/dist/client/components/RecentEditHighlights.js.map +1 -0
- package/dist/client/components/RemoteSelectionRings.d.ts +9 -0
- package/dist/client/components/RemoteSelectionRings.d.ts.map +1 -1
- package/dist/client/components/RemoteSelectionRings.js +22 -8
- package/dist/client/components/RemoteSelectionRings.js.map +1 -1
- package/dist/client/index.d.ts +6 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +1 -3
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +8 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/SharedRichEditor.js +8 -2
- package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
- package/dist/client/rich-markdown-editor/index.d.ts +1 -0
- package/dist/client/rich-markdown-editor/index.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/index.js +1 -0
- package/dist/client/rich-markdown-editor/index.js.map +1 -1
- package/dist/client/rich-markdown-editor/surgical-apply.d.ts +66 -0
- package/dist/client/rich-markdown-editor/surgical-apply.d.ts.map +1 -0
- package/dist/client/rich-markdown-editor/surgical-apply.js +147 -0
- package/dist/client/rich-markdown-editor/surgical-apply.js.map +1 -0
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts +18 -2
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +39 -8
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
- package/dist/client/session-replay.d.ts +10 -1
- package/dist/client/session-replay.d.ts.map +1 -1
- package/dist/client/session-replay.js +134 -7
- package/dist/client/session-replay.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +81 -1
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/client/use-action.d.ts +24 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +109 -27
- package/dist/client/use-action.js.map +1 -1
- package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
- package/dist/client/use-agent-engine-configured.js +7 -1
- package/dist/client/use-agent-engine-configured.js.map +1 -1
- package/dist/client/use-chat-threads.d.ts.map +1 -1
- package/dist/client/use-chat-threads.js +11 -3
- package/dist/client/use-chat-threads.js.map +1 -1
- package/dist/client/use-db-sync.d.ts +36 -0
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +68 -12
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/client/use-pinch-zoom.d.ts.map +1 -1
- package/dist/client/use-pinch-zoom.js +76 -11
- package/dist/client/use-pinch-zoom.js.map +1 -1
- package/dist/client/visual-style-controls.d.ts +79 -0
- package/dist/client/visual-style-controls.d.ts.map +1 -0
- package/dist/client/visual-style-controls.js +150 -0
- package/dist/client/visual-style-controls.js.map +1 -0
- package/dist/collab/agent-presence.d.ts +51 -5
- package/dist/collab/agent-presence.d.ts.map +1 -1
- package/dist/collab/agent-presence.js +144 -58
- package/dist/collab/agent-presence.js.map +1 -1
- package/dist/collab/awareness-store.d.ts +32 -0
- package/dist/collab/awareness-store.d.ts.map +1 -0
- package/dist/collab/awareness-store.js +0 -0
- package/dist/collab/awareness-store.js.map +1 -0
- package/dist/collab/awareness.d.ts +14 -3
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/awareness.js +53 -5
- package/dist/collab/awareness.js.map +1 -1
- package/dist/collab/client.d.ts +2 -0
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +79 -119
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/index.d.ts +3 -1
- package/dist/collab/index.d.ts.map +1 -1
- package/dist/collab/index.js +5 -1
- package/dist/collab/index.js.map +1 -1
- package/dist/collab/presence.d.ts.map +1 -1
- package/dist/collab/presence.js +54 -3
- package/dist/collab/presence.js.map +1 -1
- package/dist/collab/recent-edits.d.ts +87 -0
- package/dist/collab/recent-edits.d.ts.map +1 -0
- package/dist/collab/recent-edits.js +116 -0
- package/dist/collab/recent-edits.js.map +1 -0
- package/dist/collab/undo.d.ts +121 -0
- package/dist/collab/undo.d.ts.map +1 -0
- package/dist/collab/undo.js +244 -0
- package/dist/collab/undo.js.map +1 -0
- package/dist/collab/ydoc-manager.d.ts +10 -0
- package/dist/collab/ydoc-manager.d.ts.map +1 -1
- package/dist/collab/ydoc-manager.js +57 -0
- package/dist/collab/ydoc-manager.js.map +1 -1
- package/dist/connections/catalog.d.ts +2 -2
- package/dist/connections/catalog.d.ts.map +1 -1
- package/dist/connections/catalog.js +1 -1
- package/dist/connections/catalog.js.map +1 -1
- package/dist/db/create-get-db.d.ts +22 -0
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +73 -1
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/db/ensure-additive-columns.d.ts +93 -0
- package/dist/db/ensure-additive-columns.d.ts.map +1 -0
- package/dist/db/ensure-additive-columns.js +355 -0
- package/dist/db/ensure-additive-columns.js.map +1 -0
- package/dist/db/index.d.ts +1 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -0
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts +70 -0
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +196 -33
- package/dist/db/migrations.js.map +1 -1
- package/dist/jobs/scheduler.js +17 -10
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +5 -5
- package/dist/observability/traces.d.ts.map +1 -1
- package/dist/observability/traces.js +155 -1
- package/dist/observability/traces.js.map +1 -1
- package/dist/org/context.d.ts +7 -0
- package/dist/org/context.d.ts.map +1 -1
- package/dist/org/context.js +54 -2
- package/dist/org/context.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +10 -6
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth-marketing.d.ts.map +1 -1
- package/dist/server/auth-marketing.js +0 -10
- package/dist/server/auth-marketing.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +6 -4
- package/dist/server/auth.js.map +1 -1
- package/dist/server/collab-plugin.d.ts.map +1 -1
- package/dist/server/collab-plugin.js +45 -13
- package/dist/server/collab-plugin.js.map +1 -1
- package/dist/server/design-token-utils.d.ts +1 -1
- package/dist/server/design-token-utils.js +1 -1
- package/dist/server/design-token-utils.js.map +1 -1
- package/dist/server/fusion-app.d.ts +107 -0
- package/dist/server/fusion-app.d.ts.map +1 -0
- package/dist/server/fusion-app.js +371 -0
- package/dist/server/fusion-app.js.map +1 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +3 -4
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/poll-events.d.ts +2 -0
- package/dist/server/poll-events.d.ts.map +1 -1
- package/dist/server/poll-events.js +7 -2
- package/dist/server/poll-events.js.map +1 -1
- package/dist/server/poll.d.ts +47 -3
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +176 -10
- package/dist/server/poll.js.map +1 -1
- package/dist/server/schema-prompt.d.ts.map +1 -1
- package/dist/server/schema-prompt.js +24 -7
- package/dist/server/schema-prompt.js.map +1 -1
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +32 -3
- package/dist/settings/store.js.map +1 -1
- package/dist/sharing/actions/set-resource-visibility.js +2 -0
- package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
- package/dist/sharing/actions/share-resource.d.ts.map +1 -1
- package/dist/sharing/actions/share-resource.js +3 -0
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/sharing/actions/unshare-resource.js +2 -0
- package/dist/sharing/actions/unshare-resource.js.map +1 -1
- package/dist/styles/agent-native.css +0 -5
- package/dist/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
- package/dist/templates/default/package.json +3 -3
- package/dist/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
- package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
- package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
- package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
- package/dist/tracking/providers.d.ts.map +1 -1
- package/dist/tracking/providers.js +17 -1
- package/dist/tracking/providers.js.map +1 -1
- package/docs/content/cloneable-saas.mdx +0 -1
- package/docs/content/locales/ar-SA/cloneable-saas.mdx +0 -1
- package/docs/content/locales/ar-SA/plan-plugin.mdx +10 -9
- package/docs/content/locales/ar-SA/sharing.mdx +1 -2
- package/docs/content/locales/ar-SA/skills-guide.mdx +2 -3
- package/docs/content/locales/ar-SA/template-plan.mdx +23 -7
- package/docs/content/locales/ar-SA/tracking.mdx +1 -1
- package/docs/content/locales/ar-SA/workspace-connections.mdx +11 -11
- package/docs/content/locales/de-DE/cloneable-saas.mdx +0 -1
- package/docs/content/locales/de-DE/plan-plugin.mdx +10 -9
- package/docs/content/locales/de-DE/sharing.mdx +1 -2
- package/docs/content/locales/de-DE/skills-guide.mdx +2 -3
- package/docs/content/locales/de-DE/template-plan.mdx +23 -7
- package/docs/content/locales/de-DE/tracking.mdx +1 -1
- package/docs/content/locales/de-DE/workspace-connections.mdx +1 -1
- package/docs/content/locales/es-ES/cloneable-saas.mdx +0 -1
- package/docs/content/locales/es-ES/plan-plugin.mdx +10 -9
- package/docs/content/locales/es-ES/sharing.mdx +1 -2
- package/docs/content/locales/es-ES/skills-guide.mdx +2 -3
- package/docs/content/locales/es-ES/template-plan.mdx +23 -7
- package/docs/content/locales/es-ES/tracking.mdx +1 -1
- package/docs/content/locales/es-ES/workspace-connections.mdx +1 -1
- package/docs/content/locales/fr-FR/cloneable-saas.mdx +0 -1
- package/docs/content/locales/fr-FR/plan-plugin.mdx +10 -9
- package/docs/content/locales/fr-FR/sharing.mdx +1 -2
- package/docs/content/locales/fr-FR/skills-guide.mdx +2 -3
- package/docs/content/locales/fr-FR/template-plan.mdx +23 -7
- package/docs/content/locales/fr-FR/tracking.mdx +1 -1
- package/docs/content/locales/fr-FR/workspace-connections.mdx +1 -1
- package/docs/content/locales/hi-IN/cloneable-saas.mdx +0 -1
- package/docs/content/locales/hi-IN/plan-plugin.mdx +10 -9
- package/docs/content/locales/hi-IN/sharing.mdx +1 -2
- package/docs/content/locales/hi-IN/skills-guide.mdx +2 -3
- package/docs/content/locales/hi-IN/template-plan.mdx +23 -7
- package/docs/content/locales/hi-IN/tracking.mdx +1 -1
- package/docs/content/locales/hi-IN/workspace-connections.mdx +1 -1
- package/docs/content/locales/ja-JP/cloneable-saas.mdx +0 -1
- package/docs/content/locales/ja-JP/plan-plugin.mdx +10 -9
- package/docs/content/locales/ja-JP/sharing.mdx +1 -2
- package/docs/content/locales/ja-JP/skills-guide.mdx +2 -3
- package/docs/content/locales/ja-JP/template-plan.mdx +23 -7
- package/docs/content/locales/ja-JP/tracking.mdx +1 -1
- package/docs/content/locales/ja-JP/workspace-connections.mdx +1 -1
- package/docs/content/locales/ko-KR/cloneable-saas.mdx +0 -1
- package/docs/content/locales/ko-KR/plan-plugin.mdx +10 -9
- package/docs/content/locales/ko-KR/sharing.mdx +1 -2
- package/docs/content/locales/ko-KR/skills-guide.mdx +2 -3
- package/docs/content/locales/ko-KR/template-plan.mdx +23 -7
- package/docs/content/locales/ko-KR/tracking.mdx +1 -1
- package/docs/content/locales/ko-KR/workspace-connections.mdx +1 -1
- package/docs/content/locales/pt-BR/cloneable-saas.mdx +0 -1
- package/docs/content/locales/pt-BR/plan-plugin.mdx +10 -9
- package/docs/content/locales/pt-BR/sharing.mdx +1 -2
- package/docs/content/locales/pt-BR/skills-guide.mdx +2 -3
- package/docs/content/locales/pt-BR/template-plan.mdx +23 -7
- package/docs/content/locales/pt-BR/tracking.mdx +1 -1
- package/docs/content/locales/pt-BR/workspace-connections.mdx +1 -1
- package/docs/content/locales/zh-CN/cloneable-saas.mdx +0 -1
- package/docs/content/locales/zh-CN/plan-plugin.mdx +10 -9
- package/docs/content/locales/zh-CN/sharing.mdx +1 -2
- package/docs/content/locales/zh-CN/skills-guide.mdx +2 -3
- package/docs/content/locales/zh-CN/template-plan.mdx +23 -7
- package/docs/content/locales/zh-CN/tracking.mdx +1 -1
- package/docs/content/locales/zh-CN/workspace-connections.mdx +1 -1
- package/docs/content/locales/zh-TW/cloneable-saas.mdx +0 -1
- package/docs/content/locales/zh-TW/plan-plugin.mdx +10 -9
- package/docs/content/locales/zh-TW/sharing.mdx +1 -2
- package/docs/content/locales/zh-TW/skills-guide.mdx +2 -3
- package/docs/content/locales/zh-TW/template-plan.mdx +23 -7
- package/docs/content/locales/zh-TW/tracking.mdx +1 -1
- package/docs/content/locales/zh-TW/workspace-connections.mdx +1 -1
- package/docs/content/plan-plugin.mdx +12 -11
- package/docs/content/sharing.mdx +1 -2
- package/docs/content/skills-guide.mdx +4 -3
- package/docs/content/template-plan.mdx +37 -6
- package/docs/content/tracking.mdx +1 -1
- package/docs/content/workspace-connections.mdx +1 -1
- package/package.json +6 -6
- package/src/templates/default/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +8 -0
- package/src/templates/default/package.json +3 -3
- package/src/templates/workspace-core/.agents/skills/client-methods/SKILL.md +8 -0
- package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +22 -0
- package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +82 -19
- package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +15 -0
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +8 -0
- package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -0
- package/corpus/core/docs/content/locales/ar-SA/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/de-DE/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/es-ES/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/fr-FR/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/hi-IN/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/ja-JP/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/ko-KR/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/pt-BR/template-videos.mdx +0 -336
- package/corpus/core/docs/content/locales/zh-CN/template-videos.mdx +0 -334
- package/corpus/core/docs/content/locales/zh-TW/template-videos.mdx +0 -334
- package/corpus/core/docs/content/template-videos.mdx +0 -332
- package/corpus/templates/design/app/components/design/CodeWorkbenchHost.tsx +0 -697
- package/corpus/templates/slides/app/components/editor/CodeEditor.tsx +0 -49
- package/corpus/templates/videos/.agents/skills/actions/SKILL.md +0 -432
- package/corpus/templates/videos/.agents/skills/animation-tracks/SKILL.md +0 -99
- package/corpus/templates/videos/.agents/skills/capture-learnings/SKILL.md +0 -76
- package/corpus/templates/videos/.agents/skills/composition-management/SKILL.md +0 -106
- package/corpus/templates/videos/.agents/skills/create-skill/SKILL.md +0 -221
- package/corpus/templates/videos/.agents/skills/delegate-to-agent/SKILL.md +0 -263
- package/corpus/templates/videos/.agents/skills/frontend-design/SKILL.md +0 -112
- package/corpus/templates/videos/.agents/skills/security/SKILL.md +0 -263
- package/corpus/templates/videos/.agents/skills/self-modifying-code/SKILL.md +0 -88
- package/corpus/templates/videos/.agents/skills/shadcn-ui/SKILL.md +0 -95
- package/corpus/templates/videos/.builder/ANIMATED_PROPERTIES.md +0 -335
- package/corpus/templates/videos/.builder/KEYFRAME_SYNC.md +0 -166
- package/corpus/templates/videos/.builder/SEAMLESS_SYNC.md +0 -211
- package/corpus/templates/videos/.builder/rules/deploy-app.mdc +0 -22
- package/corpus/templates/videos/.builder/rules/organize-ui.mdc +0 -9
- package/corpus/templates/videos/.builder/skills/remotion/SKILL.md +0 -29
- package/corpus/templates/videos/.builder/skills/remotion/rules/animations.md +0 -27
- package/corpus/templates/videos/.builder/skills/remotion/rules/assets.md +0 -43
- package/corpus/templates/videos/.builder/skills/remotion/rules/audio.md +0 -58
- package/corpus/templates/videos/.builder/skills/remotion/rules/compositions.md +0 -129
- package/corpus/templates/videos/.builder/skills/remotion/rules/fonts.md +0 -47
- package/corpus/templates/videos/.builder/skills/remotion/rules/images.md +0 -41
- package/corpus/templates/videos/.builder/skills/remotion/rules/parameters.md +0 -59
- package/corpus/templates/videos/.builder/skills/remotion/rules/sequencing.md +0 -54
- package/corpus/templates/videos/.builder/skills/remotion/rules/tailwind.md +0 -11
- package/corpus/templates/videos/.builder/skills/remotion/rules/text-animations.md +0 -18
- package/corpus/templates/videos/.builder/skills/remotion/rules/timing.md +0 -103
- package/corpus/templates/videos/.builder/skills/remotion/rules/transparent-videos.md +0 -35
- package/corpus/templates/videos/.builder/skills/remotion/rules/trimming.md +0 -38
- package/corpus/templates/videos/.builder/skills/remotion/rules/videos.md +0 -54
- package/corpus/templates/videos/.dockerignore +0 -62
- package/corpus/templates/videos/.env.example +0 -4
- package/corpus/templates/videos/.oxfmtrc.json +0 -8
- package/corpus/templates/videos/AGENTS.md +0 -46
- package/corpus/templates/videos/CHANGELOG.md +0 -10
- package/corpus/templates/videos/DEVELOPING.md +0 -143
- package/corpus/templates/videos/README.md +0 -33
- package/corpus/templates/videos/actions/analyze-brand-assets.ts +0 -151
- package/corpus/templates/videos/actions/apply-design-system.ts +0 -35
- package/corpus/templates/videos/actions/create-design-system.ts +0 -84
- package/corpus/templates/videos/actions/create-folder.ts +0 -48
- package/corpus/templates/videos/actions/db-connect.ts +0 -45
- package/corpus/templates/videos/actions/db-health.ts +0 -24
- package/corpus/templates/videos/actions/db-status.ts +0 -28
- package/corpus/templates/videos/actions/delete-composition.ts +0 -272
- package/corpus/templates/videos/actions/delete-folder.ts +0 -27
- package/corpus/templates/videos/actions/generate-animated-component.ts +0 -470
- package/corpus/templates/videos/actions/get-composition.ts +0 -36
- package/corpus/templates/videos/actions/get-design-system.ts +0 -35
- package/corpus/templates/videos/actions/import-code.ts +0 -67
- package/corpus/templates/videos/actions/import-design-project.ts +0 -42
- package/corpus/templates/videos/actions/import-document.ts +0 -125
- package/corpus/templates/videos/actions/import-from-url.ts +0 -18
- package/corpus/templates/videos/actions/import-github.ts +0 -182
- package/corpus/templates/videos/actions/list-compositions.ts +0 -32
- package/corpus/templates/videos/actions/list-design-systems.ts +0 -66
- package/corpus/templates/videos/actions/list-folders.ts +0 -61
- package/corpus/templates/videos/actions/move-composition-to-folder.ts +0 -59
- package/corpus/templates/videos/actions/navigate.ts +0 -40
- package/corpus/templates/videos/actions/rename-folder.ts +0 -41
- package/corpus/templates/videos/actions/run.ts +0 -2
- package/corpus/templates/videos/actions/save-composition.ts +0 -114
- package/corpus/templates/videos/actions/set-default-design-system.ts +0 -40
- package/corpus/templates/videos/actions/update-composition.ts +0 -81
- package/corpus/templates/videos/actions/update-design-system.ts +0 -68
- package/corpus/templates/videos/actions/validate-compositions.ts +0 -502
- package/corpus/templates/videos/actions/view-screen.ts +0 -48
- package/corpus/templates/videos/app/components/CameraControls.tsx +0 -442
- package/corpus/templates/videos/app/components/CameraToolbar.tsx +0 -437
- package/corpus/templates/videos/app/components/CloudUpgrade.tsx +0 -287
- package/corpus/templates/videos/app/components/CollabPresenceBar.tsx +0 -81
- package/corpus/templates/videos/app/components/CompSettingsEditor.tsx +0 -107
- package/corpus/templates/videos/app/components/ComponentLibrarySidebar.tsx +0 -457
- package/corpus/templates/videos/app/components/ComponentPropsPanel.tsx +0 -227
- package/corpus/templates/videos/app/components/ComponentsSidebar.tsx +0 -70
- package/corpus/templates/videos/app/components/CompositionCard.tsx +0 -147
- package/corpus/templates/videos/app/components/CurrentElementPanel.tsx +0 -835
- package/corpus/templates/videos/app/components/CursorControls.tsx +0 -664
- package/corpus/templates/videos/app/components/CursorPositioningOverlay.tsx +0 -238
- package/corpus/templates/videos/app/components/LibraryFolderRow.tsx +0 -235
- package/corpus/templates/videos/app/components/MotionCurveSelect.tsx +0 -61
- package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +0 -192
- package/corpus/templates/videos/app/components/PropsEditor.tsx +0 -210
- package/corpus/templates/videos/app/components/QuestionFlow.tsx +0 -40
- package/corpus/templates/videos/app/components/Sidebar.tsx +0 -609
- package/corpus/templates/videos/app/components/StudioHeader.tsx +0 -109
- package/corpus/templates/videos/app/components/Timeline.tsx +0 -2067
- package/corpus/templates/videos/app/components/TrackPropertiesPanel.tsx +0 -922
- package/corpus/templates/videos/app/components/TweaksPanel.tsx +0 -277
- package/corpus/templates/videos/app/components/VideoPlayer.tsx +0 -487
- package/corpus/templates/videos/app/components/design-system/DesignSystemCard.tsx +0 -134
- package/corpus/templates/videos/app/components/design-system/DesignSystemPreview.tsx +0 -176
- package/corpus/templates/videos/app/components/design-system/DesignSystemSetup.tsx +0 -707
- package/corpus/templates/videos/app/components/keyframes/KeyframeActionButtons.tsx +0 -78
- package/corpus/templates/videos/app/components/keyframes/KeyframeNavigation.tsx +0 -59
- package/corpus/templates/videos/app/components/keyframes/PropertyNumberInput.tsx +0 -56
- package/corpus/templates/videos/app/components/layout/Header.tsx +0 -64
- package/corpus/templates/videos/app/components/layout/HeaderActions.tsx +0 -84
- package/corpus/templates/videos/app/components/layout/Layout.tsx +0 -132
- package/corpus/templates/videos/app/components/layout/NavSidebar.tsx +0 -180
- package/corpus/templates/videos/app/components/ui/accordion.tsx +0 -56
- package/corpus/templates/videos/app/components/ui/alert-dialog.tsx +0 -139
- package/corpus/templates/videos/app/components/ui/alert.tsx +0 -59
- package/corpus/templates/videos/app/components/ui/aspect-ratio.tsx +0 -5
- package/corpus/templates/videos/app/components/ui/avatar.tsx +0 -48
- package/corpus/templates/videos/app/components/ui/badge.tsx +0 -37
- package/corpus/templates/videos/app/components/ui/breadcrumb.tsx +0 -115
- package/corpus/templates/videos/app/components/ui/button.tsx +0 -57
- package/corpus/templates/videos/app/components/ui/calendar.tsx +0 -68
- package/corpus/templates/videos/app/components/ui/card.tsx +0 -86
- package/corpus/templates/videos/app/components/ui/carousel.tsx +0 -260
- package/corpus/templates/videos/app/components/ui/chart.tsx +0 -375
- package/corpus/templates/videos/app/components/ui/checkbox.tsx +0 -28
- package/corpus/templates/videos/app/components/ui/collapsible.tsx +0 -9
- package/corpus/templates/videos/app/components/ui/command.tsx +0 -154
- package/corpus/templates/videos/app/components/ui/context-menu.tsx +0 -202
- package/corpus/templates/videos/app/components/ui/dialog.tsx +0 -130
- package/corpus/templates/videos/app/components/ui/drawer.tsx +0 -116
- package/corpus/templates/videos/app/components/ui/dropdown-menu.tsx +0 -212
- package/corpus/templates/videos/app/components/ui/form.tsx +0 -177
- package/corpus/templates/videos/app/components/ui/hover-card.tsx +0 -27
- package/corpus/templates/videos/app/components/ui/input-otp.tsx +0 -69
- package/corpus/templates/videos/app/components/ui/input.tsx +0 -22
- package/corpus/templates/videos/app/components/ui/label.tsx +0 -24
- package/corpus/templates/videos/app/components/ui/menubar.tsx +0 -234
- package/corpus/templates/videos/app/components/ui/navigation-menu.tsx +0 -128
- package/corpus/templates/videos/app/components/ui/pagination.tsx +0 -121
- package/corpus/templates/videos/app/components/ui/popover.tsx +0 -44
- package/corpus/templates/videos/app/components/ui/progress.tsx +0 -26
- package/corpus/templates/videos/app/components/ui/radio-group.tsx +0 -42
- package/corpus/templates/videos/app/components/ui/resizable.tsx +0 -43
- package/corpus/templates/videos/app/components/ui/scroll-area.tsx +0 -46
- package/corpus/templates/videos/app/components/ui/select.tsx +0 -158
- package/corpus/templates/videos/app/components/ui/separator.tsx +0 -29
- package/corpus/templates/videos/app/components/ui/sheet.tsx +0 -160
- package/corpus/templates/videos/app/components/ui/sidebar.tsx +0 -782
- package/corpus/templates/videos/app/components/ui/skeleton.tsx +0 -15
- package/corpus/templates/videos/app/components/ui/slider.tsx +0 -26
- package/corpus/templates/videos/app/components/ui/sonner.tsx +0 -58
- package/corpus/templates/videos/app/components/ui/spinner.tsx +0 -17
- package/corpus/templates/videos/app/components/ui/switch.tsx +0 -27
- package/corpus/templates/videos/app/components/ui/table.tsx +0 -117
- package/corpus/templates/videos/app/components/ui/tabs.tsx +0 -53
- package/corpus/templates/videos/app/components/ui/textarea.tsx +0 -23
- package/corpus/templates/videos/app/components/ui/toast.tsx +0 -127
- package/corpus/templates/videos/app/components/ui/toaster.tsx +0 -33
- package/corpus/templates/videos/app/components/ui/toggle-group.tsx +0 -59
- package/corpus/templates/videos/app/components/ui/toggle.tsx +0 -43
- package/corpus/templates/videos/app/components/ui/tooltip.tsx +0 -30
- package/corpus/templates/videos/app/components/ui/use-toast.ts +0 -3
- package/corpus/templates/videos/app/config/constants.ts +0 -204
- package/corpus/templates/videos/app/contexts/CompositionContext.tsx +0 -437
- package/corpus/templates/videos/app/contexts/CurrentElementContext.tsx +0 -247
- package/corpus/templates/videos/app/contexts/PlaybackContext.tsx +0 -65
- package/corpus/templates/videos/app/contexts/TimelineContext.tsx +0 -433
- package/corpus/templates/videos/app/entry.client.tsx +0 -19
- package/corpus/templates/videos/app/entry.server.tsx +0 -10
- package/corpus/templates/videos/app/global.css +0 -171
- package/corpus/templates/videos/app/hooks/use-composition-collab.ts +0 -269
- package/corpus/templates/videos/app/hooks/use-composition-design-system.ts +0 -47
- package/corpus/templates/videos/app/hooks/use-database-compositions.ts +0 -144
- package/corpus/templates/videos/app/hooks/use-db-status.ts +0 -30
- package/corpus/templates/videos/app/hooks/use-design-systems.ts +0 -21
- package/corpus/templates/videos/app/hooks/use-folders.ts +0 -199
- package/corpus/templates/videos/app/hooks/use-mobile.tsx +0 -21
- package/corpus/templates/videos/app/hooks/use-navigation-state.ts +0 -52
- package/corpus/templates/videos/app/hooks/use-question-flow.ts +0 -14
- package/corpus/templates/videos/app/hooks/use-toast.ts +0 -188
- package/corpus/templates/videos/app/hooks/useUnsavedChanges.ts +0 -48
- package/corpus/templates/videos/app/i18n/ar-SA.ts +0 -446
- package/corpus/templates/videos/app/i18n/de-DE.ts +0 -470
- package/corpus/templates/videos/app/i18n/en-US.ts +0 -452
- package/corpus/templates/videos/app/i18n/es-ES.ts +0 -468
- package/corpus/templates/videos/app/i18n/fr-FR.ts +0 -469
- package/corpus/templates/videos/app/i18n/hi-IN.ts +0 -446
- package/corpus/templates/videos/app/i18n/index.ts +0 -34
- package/corpus/templates/videos/app/i18n/ja-JP.ts +0 -460
- package/corpus/templates/videos/app/i18n/ko-KR.ts +0 -453
- package/corpus/templates/videos/app/i18n/pt-BR.ts +0 -461
- package/corpus/templates/videos/app/i18n/zh-CN.ts +0 -437
- package/corpus/templates/videos/app/i18n/zh-TW.ts +0 -437
- package/corpus/templates/videos/app/lib/database-compositions.ts +0 -67
- package/corpus/templates/videos/app/lib/design-systems.ts +0 -234
- package/corpus/templates/videos/app/lib/tab-id.ts +0 -1
- package/corpus/templates/videos/app/lib/utils.ts +0 -1
- package/corpus/templates/videos/app/pages/ComponentLibrary.tsx +0 -134
- package/corpus/templates/videos/app/pages/ComponentLibraryView.tsx +0 -362
- package/corpus/templates/videos/app/pages/CompositionView.tsx +0 -715
- package/corpus/templates/videos/app/pages/DesignSystems.tsx +0 -180
- package/corpus/templates/videos/app/pages/Index.tsx +0 -258
- package/corpus/templates/videos/app/pages/NewComposition.tsx +0 -95
- package/corpus/templates/videos/app/pages/NotFound.tsx +0 -36
- package/corpus/templates/videos/app/remotion/CameraHost.tsx +0 -223
- package/corpus/templates/videos/app/remotion/animations/useElementAnimations.ts +0 -231
- package/corpus/templates/videos/app/remotion/componentRegistry.ts +0 -473
- package/corpus/templates/videos/app/remotion/components/AnimatedElement.tsx +0 -436
- package/corpus/templates/videos/app/remotion/components/InteractiveElement.tsx +0 -159
- package/corpus/templates/videos/app/remotion/components/InteractiveZoneEditor.tsx +0 -273
- package/corpus/templates/videos/app/remotion/compositions/BlankComposition.tsx +0 -204
- package/corpus/templates/videos/app/remotion/compositions/index.ts +0 -2
- package/corpus/templates/videos/app/remotion/createComponentCursorTrack.ts +0 -132
- package/corpus/templates/videos/app/remotion/docs/CURSOR_TRACKS.md +0 -285
- package/corpus/templates/videos/app/remotion/easingFunctions.ts +0 -255
- package/corpus/templates/videos/app/remotion/hooks/createInteractiveComposition.tsx +0 -283
- package/corpus/templates/videos/app/remotion/hooks/useCursorHistory.ts +0 -72
- package/corpus/templates/videos/app/remotion/hooks/useCursorTypeFromHover.ts +0 -35
- package/corpus/templates/videos/app/remotion/hooks/useEditableZones.tsx +0 -267
- package/corpus/templates/videos/app/remotion/hooks/useHoverAnimation.ts +0 -90
- package/corpus/templates/videos/app/remotion/hooks/useHoverAnimationSmooth.ts +0 -146
- package/corpus/templates/videos/app/remotion/hooks/useInteractiveComponent.ts +0 -711
- package/corpus/templates/videos/app/remotion/hooks/useRegisterInteractiveElement.ts +0 -56
- package/corpus/templates/videos/app/remotion/library-components/Button.tsx +0 -252
- package/corpus/templates/videos/app/remotion/library-components/Card.tsx +0 -241
- package/corpus/templates/videos/app/remotion/library-components/CodePanel.tsx +0 -1005
- package/corpus/templates/videos/app/remotion/library-components/FileItem.tsx +0 -196
- package/corpus/templates/videos/app/remotion/library-components/FolderItem.tsx +0 -199
- package/corpus/templates/videos/app/remotion/library-components/PrimaryButton.tsx +0 -177
- package/corpus/templates/videos/app/remotion/library-components/SecondaryButton.tsx +0 -167
- package/corpus/templates/videos/app/remotion/library-components/SectionHeader.tsx +0 -108
- package/corpus/templates/videos/app/remotion/library-components/TEMPLATE.tsx +0 -211
- package/corpus/templates/videos/app/remotion/library-components/index.ts +0 -10
- package/corpus/templates/videos/app/remotion/registry.ts +0 -91
- package/corpus/templates/videos/app/remotion/testing/animationTestUtils.ts +0 -366
- package/corpus/templates/videos/app/remotion/trackAnimation.ts +0 -179
- package/corpus/templates/videos/app/remotion/trackHelpers.ts +0 -110
- package/corpus/templates/videos/app/remotion/ui-components/Cursor.tsx +0 -182
- package/corpus/templates/videos/app/remotion/ui-components/InteractiveButton.tsx +0 -116
- package/corpus/templates/videos/app/remotion/ui-components/InteractiveCard.tsx +0 -126
- package/corpus/templates/videos/app/remotion/ui-components/index.ts +0 -16
- package/corpus/templates/videos/app/remotion/utils/animationHelpers.ts +0 -444
- package/corpus/templates/videos/app/remotion/utils/interactiveElements.ts +0 -235
- package/corpus/templates/videos/app/remotion/utils/springAnimation.ts +0 -76
- package/corpus/templates/videos/app/root.tsx +0 -165
- package/corpus/templates/videos/app/routes/$.tsx +0 -10
- package/corpus/templates/videos/app/routes/_index.tsx +0 -25
- package/corpus/templates/videos/app/routes/c.$compositionId.tsx +0 -10
- package/corpus/templates/videos/app/routes/components.tsx +0 -10
- package/corpus/templates/videos/app/routes/design-systems.tsx +0 -10
- package/corpus/templates/videos/app/routes/extensions.$id.$slug.tsx +0 -2
- package/corpus/templates/videos/app/routes/extensions.$id.tsx +0 -5
- package/corpus/templates/videos/app/routes/extensions._index.tsx +0 -5
- package/corpus/templates/videos/app/routes/extensions.tsx +0 -5
- package/corpus/templates/videos/app/routes/settings.tsx +0 -88
- package/corpus/templates/videos/app/routes/team.tsx +0 -11
- package/corpus/templates/videos/app/routes.ts +0 -4
- package/corpus/templates/videos/app/state.ts +0 -77
- package/corpus/templates/videos/app/types/elementAnimations.ts +0 -121
- package/corpus/templates/videos/app/types.ts +0 -200
- package/corpus/templates/videos/app/utils/compositionHelpers.ts +0 -445
- package/corpus/templates/videos/app/utils/debug.ts +0 -63
- package/corpus/templates/videos/app/utils/keyframeUtils.ts +0 -331
- package/corpus/templates/videos/app/utils/timelineCoordinates.ts +0 -79
- package/corpus/templates/videos/app/vite-env.d.ts +0 -6
- package/corpus/templates/videos/changelog/2026-06-24-a-new-settings-page-gives-quick-access-to-language-workspace.md +0 -6
- package/corpus/templates/videos/changelog/2026-06-24-added-a-language-picker-and-localized-app-chrome-for-support.md +0 -6
- package/corpus/templates/videos/changelog/2026-06-27-traditional-chinese-copy-uses-taiwan-terminology.md +0 -6
- package/corpus/templates/videos/changelog/2026-06-28-left-sidebar-collapses-into-an-animated-icon-rail.md +0 -6
- package/corpus/templates/videos/changelog/2026-06-29-video-layouts-adapt-when-the-agent-sidebar-is-open.md +0 -6
- package/corpus/templates/videos/components.json +0 -20
- package/corpus/templates/videos/data/sync-config.json +0 -3
- package/corpus/templates/videos/docs/examples/create-composition.example.ts +0 -128
- package/corpus/templates/videos/drizzle.config.ts +0 -3
- package/corpus/templates/videos/learnings.defaults.md +0 -5
- package/corpus/templates/videos/package.json +0 -114
- package/corpus/templates/videos/public/agent-native-icon-dark.svg +0 -10
- package/corpus/templates/videos/public/agent-native-icon-light.svg +0 -10
- package/corpus/templates/videos/public/agent-native-logo-dark.svg +0 -21
- package/corpus/templates/videos/public/agent-native-logo-light.svg +0 -21
- package/corpus/templates/videos/public/favicon.svg +0 -1
- package/corpus/templates/videos/public/icon-180.svg +0 -1
- package/corpus/templates/videos/public/icon-192.svg +0 -1
- package/corpus/templates/videos/public/icon-512.svg +0 -1
- package/corpus/templates/videos/public/manifest.json +0 -21
- package/corpus/templates/videos/public/placeholder.svg +0 -1
- package/corpus/templates/videos/public/robots.txt +0 -14
- package/corpus/templates/videos/react-router.config.ts +0 -7
- package/corpus/templates/videos/server/db/index.ts +0 -37
- package/corpus/templates/videos/server/db/schema.ts +0 -55
- package/corpus/templates/videos/server/middleware/auth.ts +0 -15
- package/corpus/templates/videos/server/plugins/agent-chat.ts +0 -29
- package/corpus/templates/videos/server/plugins/auth.ts +0 -14
- package/corpus/templates/videos/server/plugins/collab.ts +0 -11
- package/corpus/templates/videos/server/plugins/core-routes.ts +0 -22
- package/corpus/templates/videos/server/plugins/db.ts +0 -160
- package/corpus/templates/videos/server/routes/[...page].get.ts +0 -5
- package/corpus/templates/videos/server/routes/[...page].head.ts +0 -1
- package/corpus/templates/videos/server/routes/api/save-composition-defaults.post.ts +0 -274
- package/corpus/templates/videos/shared/api.ts +0 -75
- package/corpus/templates/videos/ssr-entry.ts +0 -15
- package/corpus/templates/videos/tsconfig.json +0 -21
- package/corpus/templates/videos/vite.config.ts +0 -19
- package/corpus/templates/videos/vitest.config.ts +0 -16
- package/docs/content/locales/ar-SA/template-videos.mdx +0 -336
- package/docs/content/locales/de-DE/template-videos.mdx +0 -336
- package/docs/content/locales/es-ES/template-videos.mdx +0 -336
- package/docs/content/locales/fr-FR/template-videos.mdx +0 -336
- package/docs/content/locales/hi-IN/template-videos.mdx +0 -336
- package/docs/content/locales/ja-JP/template-videos.mdx +0 -336
- package/docs/content/locales/ko-KR/template-videos.mdx +0 -336
- package/docs/content/locales/pt-BR/template-videos.mdx +0 -336
- package/docs/content/locales/zh-CN/template-videos.mdx +0 -334
- package/docs/content/locales/zh-TW/template-videos.mdx +0 -334
- package/docs/content/template-videos.mdx +0 -332
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boot-time convergence for columns Drizzle's schema declares but a
|
|
3
|
+
* pre-existing table is missing.
|
|
4
|
+
*
|
|
5
|
+
* Lives in its own module (like `./widen-columns.js`) so stores/plugins can
|
|
6
|
+
* import it without every `vi.mock("../db/client.js")` test needing to stub
|
|
7
|
+
* it: the helper resolves `isPostgres()` / `getDbExec()` through `client.js`,
|
|
8
|
+
* so a test that mocks the client to SQLite makes the Postgres introspection
|
|
9
|
+
* path a no-op automatically.
|
|
10
|
+
*
|
|
11
|
+
* ## Why
|
|
12
|
+
*
|
|
13
|
+
* `CREATE TABLE IF NOT EXISTS` only runs the CREATE the first time a table is
|
|
14
|
+
* created — once it exists, adding a column to the Drizzle schema (e.g.
|
|
15
|
+
* `schema.ts`) does nothing to already-existing rows unless a hand-written
|
|
16
|
+
* `ALTER TABLE ... ADD COLUMN` migration ships alongside it. Fresh dev
|
|
17
|
+
* databases mask this because the CREATE always includes every declared
|
|
18
|
+
* column; only long-lived, pre-existing production tables are missing the
|
|
19
|
+
* new column. Forgetting the migration turns every query that references the
|
|
20
|
+
* column into a Postgres `42703 (undefined_column)` — e.g.
|
|
21
|
+
* `session_recordings.network_error_count`, which 500'd every
|
|
22
|
+
* `list-session-recordings` call.
|
|
23
|
+
*
|
|
24
|
+
* `ensureAdditiveColumns()` is belt-and-braces for that failure mode: after
|
|
25
|
+
* the authoritative hand-written migrations run, diff each Drizzle table's
|
|
26
|
+
* declared columns against the live table and additively patch any gap. It
|
|
27
|
+
* is NOT a replacement for migrations — it never touches indexes, data
|
|
28
|
+
* transforms, or existing columns, and a hand-written migration should still
|
|
29
|
+
* ship for every schema change. This is a safety net for the case where one
|
|
30
|
+
* doesn't.
|
|
31
|
+
*
|
|
32
|
+
* ## Safety rules (hard)
|
|
33
|
+
*
|
|
34
|
+
* - Additive only: never drops, renames, retypes, or otherwise touches a
|
|
35
|
+
* column that already exists on the live table.
|
|
36
|
+
* - A `NOT NULL` column is only ever added when it has a renderable default
|
|
37
|
+
* (so existing rows get a valid value in the same statement). If it has no
|
|
38
|
+
* renderable default, it is added as nullable when the Drizzle declaration
|
|
39
|
+
* allows null, else the column is SKIPPED entirely with a loud log line
|
|
40
|
+
* naming the column and the reason.
|
|
41
|
+
* - Only simple literal defaults are rendered: numbers, strings, booleans,
|
|
42
|
+
* and `sql` template defaults that stringify to one of a small allow-listed
|
|
43
|
+
* set of safe constants (see `renderDefaultLiteral`). Any other `sql`
|
|
44
|
+
* default is NOT rendered — the column is added without a `DEFAULT` (and
|
|
45
|
+
* without `NOT NULL`, per the rule above) rather than risk interpolating
|
|
46
|
+
* unsafe SQL.
|
|
47
|
+
* - All identifiers (table/column names) are validated against a strict
|
|
48
|
+
* `[A-Za-z_][A-Za-z0-9_]*` pattern and double-quoted; no value from a row or
|
|
49
|
+
* from user data is ever interpolated into the generated SQL.
|
|
50
|
+
* - If the table itself does not exist yet, this is a no-op — table creation
|
|
51
|
+
* owns bringing every declared column into existence for a brand-new table.
|
|
52
|
+
* - Idempotent and best-effort: a failure on one column is logged and does
|
|
53
|
+
* not abort the rest, and a total failure (e.g. `information_schema`
|
|
54
|
+
* unreadable) must never crash boot — the caller decides whether/how to
|
|
55
|
+
* surface `errors` in the returned summary.
|
|
56
|
+
*/
|
|
57
|
+
import { type DbExec } from "./client.js";
|
|
58
|
+
export interface EnsureAdditiveColumnsLogger {
|
|
59
|
+
info: (message: string) => void;
|
|
60
|
+
warn: (message: string) => void;
|
|
61
|
+
error: (message: string) => void;
|
|
62
|
+
}
|
|
63
|
+
export interface EnsureAdditiveColumnsOptions {
|
|
64
|
+
db: DbExec;
|
|
65
|
+
/** Drizzle table objects (from `pgTable`/`sqliteTable`, or the dialect-agnostic `table()` helper). */
|
|
66
|
+
tables: unknown[];
|
|
67
|
+
logger?: EnsureAdditiveColumnsLogger;
|
|
68
|
+
}
|
|
69
|
+
export interface EnsureAdditiveColumnsResult {
|
|
70
|
+
/** `"table.column"` entries that were successfully added. */
|
|
71
|
+
applied: string[];
|
|
72
|
+
/** Declared columns that were intentionally left unpatched, with why. */
|
|
73
|
+
skipped: Array<{
|
|
74
|
+
column: string;
|
|
75
|
+
reason: string;
|
|
76
|
+
}>;
|
|
77
|
+
/** `"table.column"` entries whose ALTER failed unexpectedly (logged, non-fatal). */
|
|
78
|
+
errors: Array<{
|
|
79
|
+
column: string;
|
|
80
|
+
error: string;
|
|
81
|
+
}>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Diff each declared Drizzle table's columns against the live database and
|
|
85
|
+
* additively `ALTER TABLE ... ADD COLUMN` any that are missing. See the
|
|
86
|
+
* module docstring for the full safety-rule contract.
|
|
87
|
+
*
|
|
88
|
+
* Call this once at boot, immediately after the authoritative hand-written
|
|
89
|
+
* migrations have run. Never throws — every failure path is captured in the
|
|
90
|
+
* returned summary instead so a boot-time caller can log-and-continue.
|
|
91
|
+
*/
|
|
92
|
+
export declare function ensureAdditiveColumns(options: EnsureAdditiveColumnsOptions): Promise<EnsureAdditiveColumnsResult>;
|
|
93
|
+
//# sourceMappingURL=ensure-additive-columns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensure-additive-columns.d.ts","sourceRoot":"","sources":["../../src/db/ensure-additive-columns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAItD,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AA4BD,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,sGAAsG;IACtG,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,2BAA2B,CAAC;CACtC;AAED,MAAM,WAAW,2BAA2B;IAC1C,6DAA6D;IAC7D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,yEAAyE;IACzE,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,oFAAoF;IACpF,MAAM,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;AAiLD;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,2BAA2B,CAAC,CAgHtC"}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boot-time convergence for columns Drizzle's schema declares but a
|
|
3
|
+
* pre-existing table is missing.
|
|
4
|
+
*
|
|
5
|
+
* Lives in its own module (like `./widen-columns.js`) so stores/plugins can
|
|
6
|
+
* import it without every `vi.mock("../db/client.js")` test needing to stub
|
|
7
|
+
* it: the helper resolves `isPostgres()` / `getDbExec()` through `client.js`,
|
|
8
|
+
* so a test that mocks the client to SQLite makes the Postgres introspection
|
|
9
|
+
* path a no-op automatically.
|
|
10
|
+
*
|
|
11
|
+
* ## Why
|
|
12
|
+
*
|
|
13
|
+
* `CREATE TABLE IF NOT EXISTS` only runs the CREATE the first time a table is
|
|
14
|
+
* created — once it exists, adding a column to the Drizzle schema (e.g.
|
|
15
|
+
* `schema.ts`) does nothing to already-existing rows unless a hand-written
|
|
16
|
+
* `ALTER TABLE ... ADD COLUMN` migration ships alongside it. Fresh dev
|
|
17
|
+
* databases mask this because the CREATE always includes every declared
|
|
18
|
+
* column; only long-lived, pre-existing production tables are missing the
|
|
19
|
+
* new column. Forgetting the migration turns every query that references the
|
|
20
|
+
* column into a Postgres `42703 (undefined_column)` — e.g.
|
|
21
|
+
* `session_recordings.network_error_count`, which 500'd every
|
|
22
|
+
* `list-session-recordings` call.
|
|
23
|
+
*
|
|
24
|
+
* `ensureAdditiveColumns()` is belt-and-braces for that failure mode: after
|
|
25
|
+
* the authoritative hand-written migrations run, diff each Drizzle table's
|
|
26
|
+
* declared columns against the live table and additively patch any gap. It
|
|
27
|
+
* is NOT a replacement for migrations — it never touches indexes, data
|
|
28
|
+
* transforms, or existing columns, and a hand-written migration should still
|
|
29
|
+
* ship for every schema change. This is a safety net for the case where one
|
|
30
|
+
* doesn't.
|
|
31
|
+
*
|
|
32
|
+
* ## Safety rules (hard)
|
|
33
|
+
*
|
|
34
|
+
* - Additive only: never drops, renames, retypes, or otherwise touches a
|
|
35
|
+
* column that already exists on the live table.
|
|
36
|
+
* - A `NOT NULL` column is only ever added when it has a renderable default
|
|
37
|
+
* (so existing rows get a valid value in the same statement). If it has no
|
|
38
|
+
* renderable default, it is added as nullable when the Drizzle declaration
|
|
39
|
+
* allows null, else the column is SKIPPED entirely with a loud log line
|
|
40
|
+
* naming the column and the reason.
|
|
41
|
+
* - Only simple literal defaults are rendered: numbers, strings, booleans,
|
|
42
|
+
* and `sql` template defaults that stringify to one of a small allow-listed
|
|
43
|
+
* set of safe constants (see `renderDefaultLiteral`). Any other `sql`
|
|
44
|
+
* default is NOT rendered — the column is added without a `DEFAULT` (and
|
|
45
|
+
* without `NOT NULL`, per the rule above) rather than risk interpolating
|
|
46
|
+
* unsafe SQL.
|
|
47
|
+
* - All identifiers (table/column names) are validated against a strict
|
|
48
|
+
* `[A-Za-z_][A-Za-z0-9_]*` pattern and double-quoted; no value from a row or
|
|
49
|
+
* from user data is ever interpolated into the generated SQL.
|
|
50
|
+
* - If the table itself does not exist yet, this is a no-op — table creation
|
|
51
|
+
* owns bringing every declared column into existence for a brand-new table.
|
|
52
|
+
* - Idempotent and best-effort: a failure on one column is logged and does
|
|
53
|
+
* not abort the rest, and a total failure (e.g. `information_schema`
|
|
54
|
+
* unreadable) must never crash boot — the caller decides whether/how to
|
|
55
|
+
* surface `errors` in the returned summary.
|
|
56
|
+
*/
|
|
57
|
+
import { isPostgres } from "./client.js";
|
|
58
|
+
const PLAIN_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
59
|
+
const defaultLogger = {
|
|
60
|
+
info: (message) => console.log(message),
|
|
61
|
+
warn: (message) => console.warn(message),
|
|
62
|
+
error: (message) => console.error(message),
|
|
63
|
+
};
|
|
64
|
+
function emptyResult() {
|
|
65
|
+
return { applied: [], skipped: [], errors: [] };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Resolve `getTableConfig` for the dialect currently in effect. Both
|
|
69
|
+
* `drizzle-orm/pg-core` and `drizzle-orm/sqlite-core` export a function with
|
|
70
|
+
* this name and a compatible-enough shape (`{ columns, name, schema? }`), but
|
|
71
|
+
* each only understands its own table class — calling the wrong one throws.
|
|
72
|
+
* `table()` from `./schema.js` builds a `pgTable` on Postgres and a
|
|
73
|
+
* `sqliteTable` everywhere else, so the same dialect switch used there
|
|
74
|
+
* decides which `getTableConfig` to load here.
|
|
75
|
+
*/
|
|
76
|
+
async function loadGetTableConfig() {
|
|
77
|
+
if (isPostgres()) {
|
|
78
|
+
const { getTableConfig } = await import("drizzle-orm/pg-core");
|
|
79
|
+
return getTableConfig;
|
|
80
|
+
}
|
|
81
|
+
const { getTableConfig } = await import("drizzle-orm/sqlite-core");
|
|
82
|
+
return getTableConfig;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Live columns already present on `table`, keyed by column name.
|
|
86
|
+
* Postgres: `information_schema.columns` scoped to the table's schema
|
|
87
|
+
* (default `public`). SQLite: `PRAGMA table_info(table)`.
|
|
88
|
+
*
|
|
89
|
+
* Returns `null` when the table itself does not exist (caller no-ops —
|
|
90
|
+
* table creation owns that path) or when introspection fails outright.
|
|
91
|
+
*/
|
|
92
|
+
async function introspectLiveColumns(db, table, schema) {
|
|
93
|
+
if (isPostgres()) {
|
|
94
|
+
try {
|
|
95
|
+
const tableSchema = schema || "public";
|
|
96
|
+
const { rows: existsRows } = await db.execute({
|
|
97
|
+
sql: `SELECT 1 FROM information_schema.tables
|
|
98
|
+
WHERE table_schema = ? AND table_name = ? LIMIT 1`,
|
|
99
|
+
args: [tableSchema, table],
|
|
100
|
+
});
|
|
101
|
+
if (existsRows.length === 0)
|
|
102
|
+
return null;
|
|
103
|
+
const { rows } = await db.execute({
|
|
104
|
+
sql: `SELECT column_name FROM information_schema.columns
|
|
105
|
+
WHERE table_schema = ? AND table_name = ?`,
|
|
106
|
+
args: [tableSchema, table],
|
|
107
|
+
});
|
|
108
|
+
return new Set(rows.map((r) => String(r.column_name)));
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// SQLite: PRAGMA table_info returns zero rows for a non-existent table
|
|
115
|
+
// (no error), so we can't distinguish "missing table" from "no columns"
|
|
116
|
+
// that way — probe sqlite_master first.
|
|
117
|
+
try {
|
|
118
|
+
const { rows: existsRows } = await db.execute({
|
|
119
|
+
sql: `SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1`,
|
|
120
|
+
args: [table],
|
|
121
|
+
});
|
|
122
|
+
if (existsRows.length === 0)
|
|
123
|
+
return null;
|
|
124
|
+
// PRAGMA doesn't support bound parameters; the table name is already
|
|
125
|
+
// validated against PLAIN_IDENTIFIER by the caller before we get here.
|
|
126
|
+
const { rows } = await db.execute(`PRAGMA table_info("${table}")`);
|
|
127
|
+
return new Set(rows.map((r) => String(r.name)));
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Quote a validated identifier for use in generated SQL. */
|
|
134
|
+
function quoteIdent(name) {
|
|
135
|
+
return `"${name}"`;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Render a column's declared default as a SQL literal, or `undefined` if it
|
|
139
|
+
* can't be rendered safely. Only numbers, strings, booleans, and a small
|
|
140
|
+
* allow-list of `sql` template defaults that stringify to a known-safe
|
|
141
|
+
* constant are supported — anything else is deliberately left unrendered so
|
|
142
|
+
* we never interpolate arbitrary SQL.
|
|
143
|
+
*/
|
|
144
|
+
function renderDefaultLiteral(column) {
|
|
145
|
+
if (!column.hasDefault)
|
|
146
|
+
return undefined;
|
|
147
|
+
const value = column.default;
|
|
148
|
+
if (value == null)
|
|
149
|
+
return undefined;
|
|
150
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
151
|
+
return String(value);
|
|
152
|
+
}
|
|
153
|
+
if (typeof value === "boolean") {
|
|
154
|
+
return isPostgres() ? (value ? "true" : "false") : value ? "1" : "0";
|
|
155
|
+
}
|
|
156
|
+
if (typeof value === "string") {
|
|
157
|
+
// Escape single quotes for a plain string literal.
|
|
158
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
159
|
+
}
|
|
160
|
+
// Drizzle `sql` template defaults (e.g. `now()`, `(datetime('now'))`) carry
|
|
161
|
+
// a `queryChunks`/`toQuery`-style object rather than a plain scalar. Only
|
|
162
|
+
// render the handful of known-safe constants used by this codebase's
|
|
163
|
+
// `now()` helper (see ./schema.ts) — never stringify arbitrary SQL.
|
|
164
|
+
const raw = sqlDefaultText(value);
|
|
165
|
+
if (raw == null)
|
|
166
|
+
return undefined;
|
|
167
|
+
const normalized = raw.trim().toLowerCase();
|
|
168
|
+
const SAFE_SQL_DEFAULTS = new Set([
|
|
169
|
+
"now()",
|
|
170
|
+
"(datetime('now'))",
|
|
171
|
+
"current_timestamp",
|
|
172
|
+
"current_date",
|
|
173
|
+
"current_time",
|
|
174
|
+
]);
|
|
175
|
+
if (SAFE_SQL_DEFAULTS.has(normalized)) {
|
|
176
|
+
return raw.trim();
|
|
177
|
+
}
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Best-effort extraction of the raw SQL text from a drizzle `SQL` default
|
|
182
|
+
* object (e.g. the value produced by `` sql`now()` ``). Drizzle's `SQL`
|
|
183
|
+
* class publicly exposes `readonly queryChunks: SQLChunk[]`, where a plain
|
|
184
|
+
* literal chunk is a `StringChunk` with a `.value: string[]`. Only accept the
|
|
185
|
+
* text when EVERY chunk is a plain string literal — if the default embeds any
|
|
186
|
+
* dynamic piece (a bound param, column reference, nested table, etc.) we
|
|
187
|
+
* refuse to stringify it, since that could contain unsafe or unbounded SQL.
|
|
188
|
+
*/
|
|
189
|
+
function sqlDefaultText(value) {
|
|
190
|
+
if (typeof value === "string")
|
|
191
|
+
return value;
|
|
192
|
+
const chunks = value?.queryChunks;
|
|
193
|
+
if (!Array.isArray(chunks))
|
|
194
|
+
return undefined;
|
|
195
|
+
const parts = [];
|
|
196
|
+
for (const chunk of chunks) {
|
|
197
|
+
const stringValues = chunk?.value;
|
|
198
|
+
if (!Array.isArray(stringValues) ||
|
|
199
|
+
!stringValues.every((v) => typeof v === "string")) {
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
parts.push(...stringValues);
|
|
203
|
+
}
|
|
204
|
+
const text = parts.join("");
|
|
205
|
+
return text || undefined;
|
|
206
|
+
}
|
|
207
|
+
/** True when an ALTER ... ADD COLUMN failure indicates the column already exists (race with a concurrent boot). */
|
|
208
|
+
function isDuplicateColumnError(err) {
|
|
209
|
+
const msg = err?.message ?? "";
|
|
210
|
+
return (/duplicate column name/i.test(msg) ||
|
|
211
|
+
/column .* already exists/i.test(msg) ||
|
|
212
|
+
err?.code === "42701");
|
|
213
|
+
}
|
|
214
|
+
/** Annotate a schema-drift-shaped Postgres error (42703/42P01) so logs read plainly. */
|
|
215
|
+
function describeSchemaDriftError(err) {
|
|
216
|
+
const code = err?.code;
|
|
217
|
+
const message = err?.message ?? String(err);
|
|
218
|
+
if (code === "42703") {
|
|
219
|
+
return `schema drift (42703 undefined_column): ${message}`;
|
|
220
|
+
}
|
|
221
|
+
if (code === "42P01") {
|
|
222
|
+
return `schema drift (42P01 undefined_table): ${message}`;
|
|
223
|
+
}
|
|
224
|
+
return message;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Diff each declared Drizzle table's columns against the live database and
|
|
228
|
+
* additively `ALTER TABLE ... ADD COLUMN` any that are missing. See the
|
|
229
|
+
* module docstring for the full safety-rule contract.
|
|
230
|
+
*
|
|
231
|
+
* Call this once at boot, immediately after the authoritative hand-written
|
|
232
|
+
* migrations have run. Never throws — every failure path is captured in the
|
|
233
|
+
* returned summary instead so a boot-time caller can log-and-continue.
|
|
234
|
+
*/
|
|
235
|
+
export async function ensureAdditiveColumns(options) {
|
|
236
|
+
const { db, tables, logger = defaultLogger } = options;
|
|
237
|
+
const result = emptyResult();
|
|
238
|
+
let getTableConfig;
|
|
239
|
+
try {
|
|
240
|
+
getTableConfig = await loadGetTableConfig();
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
result.errors.push({
|
|
244
|
+
column: "*",
|
|
245
|
+
error: `failed to load drizzle-orm table config helper: ${err instanceof Error ? err.message : String(err)}`,
|
|
246
|
+
});
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
for (const tableObj of tables) {
|
|
250
|
+
let config;
|
|
251
|
+
try {
|
|
252
|
+
config = getTableConfig(tableObj);
|
|
253
|
+
}
|
|
254
|
+
catch (err) {
|
|
255
|
+
// Not a table this dialect's getTableConfig understands (e.g. a stray
|
|
256
|
+
// export that isn't a Drizzle table) — skip quietly rather than
|
|
257
|
+
// erroring the whole run over one bad entry.
|
|
258
|
+
logger.warn(`[ensure-additive-columns] skipping non-table export: ${err instanceof Error ? err.message : String(err)}`);
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
const tableName = config.name;
|
|
262
|
+
if (!tableName || !PLAIN_IDENTIFIER.test(tableName))
|
|
263
|
+
continue;
|
|
264
|
+
let liveColumns;
|
|
265
|
+
try {
|
|
266
|
+
liveColumns = await introspectLiveColumns(db, tableName, config.schema);
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
269
|
+
result.errors.push({
|
|
270
|
+
column: `${tableName}.*`,
|
|
271
|
+
error: describeSchemaDriftError(err),
|
|
272
|
+
});
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
// Table doesn't exist yet — the creation path (CREATE TABLE IF NOT
|
|
276
|
+
// EXISTS / a real migration) owns bringing every declared column into
|
|
277
|
+
// existence. Nothing to do here.
|
|
278
|
+
if (liveColumns == null)
|
|
279
|
+
continue;
|
|
280
|
+
for (const column of config.columns) {
|
|
281
|
+
const columnName = column.name;
|
|
282
|
+
if (!columnName || !PLAIN_IDENTIFIER.test(columnName))
|
|
283
|
+
continue;
|
|
284
|
+
if (liveColumns.has(columnName))
|
|
285
|
+
continue; // untouched — already present
|
|
286
|
+
const label = `${tableName}.${columnName}`;
|
|
287
|
+
const sqlType = safeSQLType(column, label, logger);
|
|
288
|
+
if (!sqlType) {
|
|
289
|
+
result.skipped.push({
|
|
290
|
+
column: label,
|
|
291
|
+
reason: "could not determine a safe SQL type for the column",
|
|
292
|
+
});
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
const defaultLiteral = renderDefaultLiteral(column);
|
|
296
|
+
let notNullClause = "";
|
|
297
|
+
if (column.notNull) {
|
|
298
|
+
if (defaultLiteral != null) {
|
|
299
|
+
notNullClause = " NOT NULL";
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
// Can't safely backfill existing rows — adding NOT NULL without a
|
|
303
|
+
// default would fail immediately on any existing row. Skip the
|
|
304
|
+
// whole column rather than add a nullable column that silently
|
|
305
|
+
// disagrees with the Drizzle declaration's NOT NULL contract in
|
|
306
|
+
// a way that could surprise a future safe-default addition.
|
|
307
|
+
result.skipped.push({
|
|
308
|
+
column: label,
|
|
309
|
+
reason: "declared NOT NULL with no renderable default — cannot backfill existing rows safely",
|
|
310
|
+
});
|
|
311
|
+
logger.warn(`[ensure-additive-columns] SKIPPING ${label}: declared NOT NULL with no renderable default (existing rows have no safe backfill value)`);
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const defaultClause = defaultLiteral != null ? ` DEFAULT ${defaultLiteral}` : "";
|
|
316
|
+
const ddl = `ALTER TABLE ${quoteIdent(tableName)} ADD COLUMN ${quoteIdent(columnName)} ${sqlType}${defaultClause}${notNullClause}`;
|
|
317
|
+
try {
|
|
318
|
+
await db.execute(ddl);
|
|
319
|
+
result.applied.push(label);
|
|
320
|
+
logger.info(`[ensure-additive-columns] added ${label}`);
|
|
321
|
+
}
|
|
322
|
+
catch (err) {
|
|
323
|
+
if (isDuplicateColumnError(err)) {
|
|
324
|
+
// A concurrent boot already added it — treat as success.
|
|
325
|
+
result.applied.push(label);
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
const message = describeSchemaDriftError(err);
|
|
329
|
+
result.errors.push({ column: label, error: message });
|
|
330
|
+
logger.error(`[ensure-additive-columns] failed to add ${label}: ${message}`);
|
|
331
|
+
// Continue with the remaining columns/tables — one failure must not
|
|
332
|
+
// abort the rest.
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return result;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Resolve the SQL type to use for a new column. Prefers the column's own
|
|
340
|
+
* `getSQLType()` (the exact type Drizzle would have used in a fresh CREATE
|
|
341
|
+
* TABLE); falls back to skipping (returns `undefined`) if it throws or
|
|
342
|
+
* returns something empty.
|
|
343
|
+
*/
|
|
344
|
+
function safeSQLType(column, label, logger) {
|
|
345
|
+
try {
|
|
346
|
+
const sqlType = column.getSQLType();
|
|
347
|
+
if (typeof sqlType === "string" && sqlType.trim())
|
|
348
|
+
return sqlType.trim();
|
|
349
|
+
}
|
|
350
|
+
catch (err) {
|
|
351
|
+
logger.warn(`[ensure-additive-columns] getSQLType() threw for ${label}: ${err instanceof Error ? err.message : String(err)}`);
|
|
352
|
+
}
|
|
353
|
+
return undefined;
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=ensure-additive-columns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensure-additive-columns.js","sourceRoot":"","sources":["../../src/db/ensure-additive-columns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,OAAO,EAAE,UAAU,EAAe,MAAM,aAAa,CAAC;AAEtD,MAAM,gBAAgB,GAAG,0BAA0B,CAAC;AAQpD,MAAM,aAAa,GAAgC;IACjD,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;IACvC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;IACxC,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;CAC3C,CAAC;AAsCF,SAAS,WAAW;IAClB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AAClD,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,kBAAkB;IAG/B,IAAI,UAAU,EAAE,EAAE,CAAC;QACjB,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;QAC/D,OAAO,cAAkE,CAAC;IAC5E,CAAC;IACD,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;IACnE,OAAO,cAAkE,CAAC;AAC5E,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,qBAAqB,CAClC,EAAU,EACV,KAAa,EACb,MAA0B;IAE1B,IAAI,UAAU,EAAE,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,IAAI,QAAQ,CAAC;YACvC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC;gBAC5C,GAAG,EAAE;gEACmD;gBACxD,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC;aAC3B,CAAC,CAAC;YACH,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YACzC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC;gBAChC,GAAG,EAAE;wDAC2C;gBAChD,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC;aAC3B,CAAC,CAAC;YACH,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,wEAAwE;IACxE,wCAAwC;IACxC,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC;YAC5C,GAAG,EAAE,uEAAuE;YAC5E,IAAI,EAAE,CAAC,KAAK,CAAC;SACd,CAAC,CAAC;QACH,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,qEAAqE;QACrE,uEAAuE;QACvE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,sBAAsB,KAAK,IAAI,CAAC,CAAC;QACnE,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,6DAA6D;AAC7D,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,IAAI,GAAG,CAAC;AACrB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,oBAAoB,CAAC,MAA0B;IACtD,IAAI,CAAC,MAAM,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IACzC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;IAC7B,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC;IAEpC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACvE,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,mDAAmD;QACnD,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;IAC1C,CAAC;IAED,4EAA4E;IAC5E,0EAA0E;IAC1E,qEAAqE;IACrE,oEAAoE;IACpE,MAAM,GAAG,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC;IAClC,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;QAChC,OAAO;QACP,mBAAmB;QACnB,mBAAmB;QACnB,cAAc;QACd,cAAc;KACf,CAAC,CAAC;IACH,IAAI,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACtC,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,MAAM,GAAI,KAA0C,EAAE,WAAW,CAAC;IACxE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,YAAY,GAAI,KAAoC,EAAE,KAAK,CAAC;QAClE,IACE,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;YAC5B,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EACjD,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,GAAI,YAAyB,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5B,OAAO,IAAI,IAAI,SAAS,CAAC;AAC3B,CAAC;AAED,mHAAmH;AACnH,SAAS,sBAAsB,CAAC,GAAY;IAC1C,MAAM,GAAG,GAAI,GAAwC,EAAE,OAAO,IAAI,EAAE,CAAC;IACrE,OAAO,CACL,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC;QAClC,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC;QACpC,GAAqC,EAAE,IAAI,KAAK,OAAO,CACzD,CAAC;AACJ,CAAC;AAED,wFAAwF;AACxF,SAAS,wBAAwB,CAAC,GAAY;IAC5C,MAAM,IAAI,GAAI,GAAqC,EAAE,IAAI,CAAC;IAC1D,MAAM,OAAO,GACV,GAAwC,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;IACpE,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,0CAA0C,OAAO,EAAE,CAAC;IAC7D,CAAC;IACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,yCAAyC,OAAO,EAAE,CAAC;IAC5D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAqC;IAErC,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC;IACvD,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,IAAI,cAAqD,CAAC;IAC1D,IAAI,CAAC;QACH,cAAc,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;YACjB,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,mDAAmD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SAC7G,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,MAAM,QAAQ,IAAI,MAAM,EAAE,CAAC;QAC9B,IAAI,MAAyB,CAAC;QAC9B,IAAI,CAAC;YACH,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,sEAAsE;YACtE,gEAAgE;YAChE,6CAA6C;YAC7C,MAAM,CAAC,IAAI,CACT,wDAAwD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC3G,CAAC;YACF,SAAS;QACX,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC;QAC9B,IAAI,CAAC,SAAS,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,SAAS;QAE9D,IAAI,WAA+B,CAAC;QACpC,IAAI,CAAC;YACH,WAAW,GAAG,MAAM,qBAAqB,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;gBACjB,MAAM,EAAE,GAAG,SAAS,IAAI;gBACxB,KAAK,EAAE,wBAAwB,CAAC,GAAG,CAAC;aACrC,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,mEAAmE;QACnE,sEAAsE;QACtE,iCAAiC;QACjC,IAAI,WAAW,IAAI,IAAI;YAAE,SAAS;QAElC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC;YAC/B,IAAI,CAAC,UAAU,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC;gBAAE,SAAS;YAChE,IAAI,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC;gBAAE,SAAS,CAAC,8BAA8B;YAEzE,MAAM,KAAK,GAAG,GAAG,SAAS,IAAI,UAAU,EAAE,CAAC;YAC3C,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YACnD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;oBAClB,MAAM,EAAE,KAAK;oBACb,MAAM,EAAE,oDAAoD;iBAC7D,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YAED,MAAM,cAAc,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;YACpD,IAAI,aAAa,GAAG,EAAE,CAAC;YACvB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;oBAC3B,aAAa,GAAG,WAAW,CAAC;gBAC9B,CAAC;qBAAM,CAAC;oBACN,kEAAkE;oBAClE,+DAA+D;oBAC/D,+DAA+D;oBAC/D,gEAAgE;oBAChE,4DAA4D;oBAC5D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;wBAClB,MAAM,EAAE,KAAK;wBACb,MAAM,EACJ,qFAAqF;qBACxF,CAAC,CAAC;oBACH,MAAM,CAAC,IAAI,CACT,sCAAsC,KAAK,4FAA4F,CACxI,CAAC;oBACF,SAAS;gBACX,CAAC;YACH,CAAC;YAED,MAAM,aAAa,GACjB,cAAc,IAAI,IAAI,CAAC,CAAC,CAAC,YAAY,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,MAAM,GAAG,GAAG,eAAe,UAAU,CAAC,SAAS,CAAC,eAAe,UAAU,CAAC,UAAU,CAAC,IAAI,OAAO,GAAG,aAAa,GAAG,aAAa,EAAE,CAAC;YAEnI,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBACtB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC,mCAAmC,KAAK,EAAE,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAChC,yDAAyD;oBACzD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBAC3B,SAAS;gBACX,CAAC;gBACD,MAAM,OAAO,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;gBAC9C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;gBACtD,MAAM,CAAC,KAAK,CACV,2CAA2C,KAAK,KAAK,OAAO,EAAE,CAC/D,CAAC;gBACF,oEAAoE;gBACpE,kBAAkB;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAClB,MAA0B,EAC1B,KAAa,EACb,MAAmC;IAEnC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QACpC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE;YAAE,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;IAC3E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CACT,oDAAoD,KAAK,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACjH,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["/**\n * Boot-time convergence for columns Drizzle's schema declares but a\n * pre-existing table is missing.\n *\n * Lives in its own module (like `./widen-columns.js`) so stores/plugins can\n * import it without every `vi.mock(\"../db/client.js\")` test needing to stub\n * it: the helper resolves `isPostgres()` / `getDbExec()` through `client.js`,\n * so a test that mocks the client to SQLite makes the Postgres introspection\n * path a no-op automatically.\n *\n * ## Why\n *\n * `CREATE TABLE IF NOT EXISTS` only runs the CREATE the first time a table is\n * created — once it exists, adding a column to the Drizzle schema (e.g.\n * `schema.ts`) does nothing to already-existing rows unless a hand-written\n * `ALTER TABLE ... ADD COLUMN` migration ships alongside it. Fresh dev\n * databases mask this because the CREATE always includes every declared\n * column; only long-lived, pre-existing production tables are missing the\n * new column. Forgetting the migration turns every query that references the\n * column into a Postgres `42703 (undefined_column)` — e.g.\n * `session_recordings.network_error_count`, which 500'd every\n * `list-session-recordings` call.\n *\n * `ensureAdditiveColumns()` is belt-and-braces for that failure mode: after\n * the authoritative hand-written migrations run, diff each Drizzle table's\n * declared columns against the live table and additively patch any gap. It\n * is NOT a replacement for migrations — it never touches indexes, data\n * transforms, or existing columns, and a hand-written migration should still\n * ship for every schema change. This is a safety net for the case where one\n * doesn't.\n *\n * ## Safety rules (hard)\n *\n * - Additive only: never drops, renames, retypes, or otherwise touches a\n * column that already exists on the live table.\n * - A `NOT NULL` column is only ever added when it has a renderable default\n * (so existing rows get a valid value in the same statement). If it has no\n * renderable default, it is added as nullable when the Drizzle declaration\n * allows null, else the column is SKIPPED entirely with a loud log line\n * naming the column and the reason.\n * - Only simple literal defaults are rendered: numbers, strings, booleans,\n * and `sql` template defaults that stringify to one of a small allow-listed\n * set of safe constants (see `renderDefaultLiteral`). Any other `sql`\n * default is NOT rendered — the column is added without a `DEFAULT` (and\n * without `NOT NULL`, per the rule above) rather than risk interpolating\n * unsafe SQL.\n * - All identifiers (table/column names) are validated against a strict\n * `[A-Za-z_][A-Za-z0-9_]*` pattern and double-quoted; no value from a row or\n * from user data is ever interpolated into the generated SQL.\n * - If the table itself does not exist yet, this is a no-op — table creation\n * owns bringing every declared column into existence for a brand-new table.\n * - Idempotent and best-effort: a failure on one column is logged and does\n * not abort the rest, and a total failure (e.g. `information_schema`\n * unreadable) must never crash boot — the caller decides whether/how to\n * surface `errors` in the returned summary.\n */\n\nimport { isPostgres, type DbExec } from \"./client.js\";\n\nconst PLAIN_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport interface EnsureAdditiveColumnsLogger {\n info: (message: string) => void;\n warn: (message: string) => void;\n error: (message: string) => void;\n}\n\nconst defaultLogger: EnsureAdditiveColumnsLogger = {\n info: (message) => console.log(message),\n warn: (message) => console.warn(message),\n error: (message) => console.error(message),\n};\n\n/**\n * Minimal shape this module needs from a Drizzle column — matches both\n * `drizzle-orm/pg-core` and `drizzle-orm/sqlite-core` column instances (and\n * the dialect-agnostic wrappers in `./schema.js`, which delegate to one or\n * the other at runtime).\n */\ninterface DeclaredColumnLike {\n name: string;\n notNull: boolean;\n hasDefault: boolean;\n default: unknown;\n getSQLType(): string;\n}\n\ninterface DeclaredTableLike {\n columns: DeclaredColumnLike[];\n name: string;\n schema?: string;\n}\n\nexport interface EnsureAdditiveColumnsOptions {\n db: DbExec;\n /** Drizzle table objects (from `pgTable`/`sqliteTable`, or the dialect-agnostic `table()` helper). */\n tables: unknown[];\n logger?: EnsureAdditiveColumnsLogger;\n}\n\nexport interface EnsureAdditiveColumnsResult {\n /** `\"table.column\"` entries that were successfully added. */\n applied: string[];\n /** Declared columns that were intentionally left unpatched, with why. */\n skipped: Array<{ column: string; reason: string }>;\n /** `\"table.column\"` entries whose ALTER failed unexpectedly (logged, non-fatal). */\n errors: Array<{ column: string; error: string }>;\n}\n\nfunction emptyResult(): EnsureAdditiveColumnsResult {\n return { applied: [], skipped: [], errors: [] };\n}\n\n/**\n * Resolve `getTableConfig` for the dialect currently in effect. Both\n * `drizzle-orm/pg-core` and `drizzle-orm/sqlite-core` export a function with\n * this name and a compatible-enough shape (`{ columns, name, schema? }`), but\n * each only understands its own table class — calling the wrong one throws.\n * `table()` from `./schema.js` builds a `pgTable` on Postgres and a\n * `sqliteTable` everywhere else, so the same dialect switch used there\n * decides which `getTableConfig` to load here.\n */\nasync function loadGetTableConfig(): Promise<\n (table: unknown) => DeclaredTableLike\n> {\n if (isPostgres()) {\n const { getTableConfig } = await import(\"drizzle-orm/pg-core\");\n return getTableConfig as unknown as (table: unknown) => DeclaredTableLike;\n }\n const { getTableConfig } = await import(\"drizzle-orm/sqlite-core\");\n return getTableConfig as unknown as (table: unknown) => DeclaredTableLike;\n}\n\n/**\n * Live columns already present on `table`, keyed by column name.\n * Postgres: `information_schema.columns` scoped to the table's schema\n * (default `public`). SQLite: `PRAGMA table_info(table)`.\n *\n * Returns `null` when the table itself does not exist (caller no-ops —\n * table creation owns that path) or when introspection fails outright.\n */\nasync function introspectLiveColumns(\n db: DbExec,\n table: string,\n schema: string | undefined,\n): Promise<Set<string> | null> {\n if (isPostgres()) {\n try {\n const tableSchema = schema || \"public\";\n const { rows: existsRows } = await db.execute({\n sql: `SELECT 1 FROM information_schema.tables\n WHERE table_schema = ? AND table_name = ? LIMIT 1`,\n args: [tableSchema, table],\n });\n if (existsRows.length === 0) return null;\n const { rows } = await db.execute({\n sql: `SELECT column_name FROM information_schema.columns\n WHERE table_schema = ? AND table_name = ?`,\n args: [tableSchema, table],\n });\n return new Set(rows.map((r) => String(r.column_name)));\n } catch {\n return null;\n }\n }\n\n // SQLite: PRAGMA table_info returns zero rows for a non-existent table\n // (no error), so we can't distinguish \"missing table\" from \"no columns\"\n // that way — probe sqlite_master first.\n try {\n const { rows: existsRows } = await db.execute({\n sql: `SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1`,\n args: [table],\n });\n if (existsRows.length === 0) return null;\n // PRAGMA doesn't support bound parameters; the table name is already\n // validated against PLAIN_IDENTIFIER by the caller before we get here.\n const { rows } = await db.execute(`PRAGMA table_info(\"${table}\")`);\n return new Set(rows.map((r) => String(r.name)));\n } catch {\n return null;\n }\n}\n\n/** Quote a validated identifier for use in generated SQL. */\nfunction quoteIdent(name: string): string {\n return `\"${name}\"`;\n}\n\n/**\n * Render a column's declared default as a SQL literal, or `undefined` if it\n * can't be rendered safely. Only numbers, strings, booleans, and a small\n * allow-list of `sql` template defaults that stringify to a known-safe\n * constant are supported — anything else is deliberately left unrendered so\n * we never interpolate arbitrary SQL.\n */\nfunction renderDefaultLiteral(column: DeclaredColumnLike): string | undefined {\n if (!column.hasDefault) return undefined;\n const value = column.default;\n if (value == null) return undefined;\n\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value);\n }\n if (typeof value === \"boolean\") {\n return isPostgres() ? (value ? \"true\" : \"false\") : value ? \"1\" : \"0\";\n }\n if (typeof value === \"string\") {\n // Escape single quotes for a plain string literal.\n return `'${value.replace(/'/g, \"''\")}'`;\n }\n\n // Drizzle `sql` template defaults (e.g. `now()`, `(datetime('now'))`) carry\n // a `queryChunks`/`toQuery`-style object rather than a plain scalar. Only\n // render the handful of known-safe constants used by this codebase's\n // `now()` helper (see ./schema.ts) — never stringify arbitrary SQL.\n const raw = sqlDefaultText(value);\n if (raw == null) return undefined;\n const normalized = raw.trim().toLowerCase();\n const SAFE_SQL_DEFAULTS = new Set([\n \"now()\",\n \"(datetime('now'))\",\n \"current_timestamp\",\n \"current_date\",\n \"current_time\",\n ]);\n if (SAFE_SQL_DEFAULTS.has(normalized)) {\n return raw.trim();\n }\n return undefined;\n}\n\n/**\n * Best-effort extraction of the raw SQL text from a drizzle `SQL` default\n * object (e.g. the value produced by `` sql`now()` ``). Drizzle's `SQL`\n * class publicly exposes `readonly queryChunks: SQLChunk[]`, where a plain\n * literal chunk is a `StringChunk` with a `.value: string[]`. Only accept the\n * text when EVERY chunk is a plain string literal — if the default embeds any\n * dynamic piece (a bound param, column reference, nested table, etc.) we\n * refuse to stringify it, since that could contain unsafe or unbounded SQL.\n */\nfunction sqlDefaultText(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n const chunks = (value as { queryChunks?: unknown } | null)?.queryChunks;\n if (!Array.isArray(chunks)) return undefined;\n const parts: string[] = [];\n for (const chunk of chunks) {\n const stringValues = (chunk as { value?: unknown } | null)?.value;\n if (\n !Array.isArray(stringValues) ||\n !stringValues.every((v) => typeof v === \"string\")\n ) {\n return undefined;\n }\n parts.push(...(stringValues as string[]));\n }\n const text = parts.join(\"\");\n return text || undefined;\n}\n\n/** True when an ALTER ... ADD COLUMN failure indicates the column already exists (race with a concurrent boot). */\nfunction isDuplicateColumnError(err: unknown): boolean {\n const msg = (err as { message?: string } | undefined)?.message ?? \"\";\n return (\n /duplicate column name/i.test(msg) ||\n /column .* already exists/i.test(msg) ||\n (err as { code?: string } | undefined)?.code === \"42701\"\n );\n}\n\n/** Annotate a schema-drift-shaped Postgres error (42703/42P01) so logs read plainly. */\nfunction describeSchemaDriftError(err: unknown): string {\n const code = (err as { code?: string } | undefined)?.code;\n const message =\n (err as { message?: string } | undefined)?.message ?? String(err);\n if (code === \"42703\") {\n return `schema drift (42703 undefined_column): ${message}`;\n }\n if (code === \"42P01\") {\n return `schema drift (42P01 undefined_table): ${message}`;\n }\n return message;\n}\n\n/**\n * Diff each declared Drizzle table's columns against the live database and\n * additively `ALTER TABLE ... ADD COLUMN` any that are missing. See the\n * module docstring for the full safety-rule contract.\n *\n * Call this once at boot, immediately after the authoritative hand-written\n * migrations have run. Never throws — every failure path is captured in the\n * returned summary instead so a boot-time caller can log-and-continue.\n */\nexport async function ensureAdditiveColumns(\n options: EnsureAdditiveColumnsOptions,\n): Promise<EnsureAdditiveColumnsResult> {\n const { db, tables, logger = defaultLogger } = options;\n const result = emptyResult();\n\n let getTableConfig: (table: unknown) => DeclaredTableLike;\n try {\n getTableConfig = await loadGetTableConfig();\n } catch (err) {\n result.errors.push({\n column: \"*\",\n error: `failed to load drizzle-orm table config helper: ${err instanceof Error ? err.message : String(err)}`,\n });\n return result;\n }\n\n for (const tableObj of tables) {\n let config: DeclaredTableLike;\n try {\n config = getTableConfig(tableObj);\n } catch (err) {\n // Not a table this dialect's getTableConfig understands (e.g. a stray\n // export that isn't a Drizzle table) — skip quietly rather than\n // erroring the whole run over one bad entry.\n logger.warn(\n `[ensure-additive-columns] skipping non-table export: ${err instanceof Error ? err.message : String(err)}`,\n );\n continue;\n }\n\n const tableName = config.name;\n if (!tableName || !PLAIN_IDENTIFIER.test(tableName)) continue;\n\n let liveColumns: Set<string> | null;\n try {\n liveColumns = await introspectLiveColumns(db, tableName, config.schema);\n } catch (err) {\n result.errors.push({\n column: `${tableName}.*`,\n error: describeSchemaDriftError(err),\n });\n continue;\n }\n\n // Table doesn't exist yet — the creation path (CREATE TABLE IF NOT\n // EXISTS / a real migration) owns bringing every declared column into\n // existence. Nothing to do here.\n if (liveColumns == null) continue;\n\n for (const column of config.columns) {\n const columnName = column.name;\n if (!columnName || !PLAIN_IDENTIFIER.test(columnName)) continue;\n if (liveColumns.has(columnName)) continue; // untouched — already present\n\n const label = `${tableName}.${columnName}`;\n const sqlType = safeSQLType(column, label, logger);\n if (!sqlType) {\n result.skipped.push({\n column: label,\n reason: \"could not determine a safe SQL type for the column\",\n });\n continue;\n }\n\n const defaultLiteral = renderDefaultLiteral(column);\n let notNullClause = \"\";\n if (column.notNull) {\n if (defaultLiteral != null) {\n notNullClause = \" NOT NULL\";\n } else {\n // Can't safely backfill existing rows — adding NOT NULL without a\n // default would fail immediately on any existing row. Skip the\n // whole column rather than add a nullable column that silently\n // disagrees with the Drizzle declaration's NOT NULL contract in\n // a way that could surprise a future safe-default addition.\n result.skipped.push({\n column: label,\n reason:\n \"declared NOT NULL with no renderable default — cannot backfill existing rows safely\",\n });\n logger.warn(\n `[ensure-additive-columns] SKIPPING ${label}: declared NOT NULL with no renderable default (existing rows have no safe backfill value)`,\n );\n continue;\n }\n }\n\n const defaultClause =\n defaultLiteral != null ? ` DEFAULT ${defaultLiteral}` : \"\";\n const ddl = `ALTER TABLE ${quoteIdent(tableName)} ADD COLUMN ${quoteIdent(columnName)} ${sqlType}${defaultClause}${notNullClause}`;\n\n try {\n await db.execute(ddl);\n result.applied.push(label);\n logger.info(`[ensure-additive-columns] added ${label}`);\n } catch (err) {\n if (isDuplicateColumnError(err)) {\n // A concurrent boot already added it — treat as success.\n result.applied.push(label);\n continue;\n }\n const message = describeSchemaDriftError(err);\n result.errors.push({ column: label, error: message });\n logger.error(\n `[ensure-additive-columns] failed to add ${label}: ${message}`,\n );\n // Continue with the remaining columns/tables — one failure must not\n // abort the rest.\n }\n }\n }\n\n return result;\n}\n\n/**\n * Resolve the SQL type to use for a new column. Prefers the column's own\n * `getSQLType()` (the exact type Drizzle would have used in a fresh CREATE\n * TABLE); falls back to skipping (returns `undefined`) if it throws or\n * returns something empty.\n */\nfunction safeSQLType(\n column: DeclaredColumnLike,\n label: string,\n logger: EnsureAdditiveColumnsLogger,\n): string | undefined {\n try {\n const sqlType = column.getSQLType();\n if (typeof sqlType === \"string\" && sqlType.trim()) return sqlType.trim();\n } catch (err) {\n logger.warn(\n `[ensure-additive-columns] getSQLType() threw for ${label}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n return undefined;\n}\n"]}
|
package/dist/db/index.d.ts
CHANGED
|
@@ -24,4 +24,5 @@ export { createGetDb } from "./create-get-db.js";
|
|
|
24
24
|
export { runMigrations } from "./migrations.js";
|
|
25
25
|
export { getDbExec, createDbExec, getDialect, isPostgres, intType, closeDbExec, type DbExec, type DbExecConfig, type Dialect, } from "./client.js";
|
|
26
26
|
export { table, text, integer, now } from "./schema.js";
|
|
27
|
+
export { ensureAdditiveColumns, type EnsureAdditiveColumnsOptions, type EnsureAdditiveColumnsResult, type EnsureAdditiveColumnsLogger, } from "./ensure-additive-columns.js";
|
|
27
28
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/db/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAGtC,MAAM,MAAM,QAAQ,GAChB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,GAC9B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,QAAQ;;;;IAe9C;AAED,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACL,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,EACV,OAAO,EACP,WAAW,EACX,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,OAAO,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAGtC,MAAM,MAAM,QAAQ,GAChB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,GAC9B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,QAAQ;;;;IAe9C;AAED,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACL,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,EACV,OAAO,EACP,WAAW,EACX,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,OAAO,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,KAAK,4BAA4B,EACjC,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,GACjC,MAAM,8BAA8B,CAAC"}
|
package/dist/db/index.js
CHANGED
|
@@ -23,4 +23,5 @@ export { createGetDb } from "./create-get-db.js";
|
|
|
23
23
|
export { runMigrations } from "./migrations.js";
|
|
24
24
|
export { getDbExec, createDbExec, getDialect, isPostgres, intType, closeDbExec, } from "./client.js";
|
|
25
25
|
export { table, text, integer, now } from "./schema.js";
|
|
26
|
+
export { ensureAdditiveColumns, } from "./ensure-additive-columns.js";
|
|
26
27
|
//# sourceMappingURL=index.js.map
|
package/dist/db/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAOrD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAgB;IAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;QACvE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QACjD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACtD,OAAO,SAAS,CACd,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,aAAa,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CACpE,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACpC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uBAAwB,MAAc,CAAC,MAAM,EAAE,CAAC,CAAC;AACnE,CAAC;AAID,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACL,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,EACV,OAAO,EACP,WAAW,GAIZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC","sourcesContent":["import Database from \"better-sqlite3\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\n\nexport type DbConfig =\n | { driver: \"sqlite\"; filename: string }\n | { driver: \"d1\"; binding: any }\n | { driver: \"postgres\"; connectionString: string };\n\n/**\n * Create a Drizzle ORM database instance.\n * Supports SQLite via better-sqlite3 and Postgres via postgres-js.\n * Postgres driver is loaded dynamically to avoid bundling in edge runtimes.\n */\nexport async function createDb(config: DbConfig) {\n if (config.driver === \"postgres\") {\n const { drizzle: drizzlePg } = await import(\"drizzle-orm/postgres-js\");\n const { default: pg } = await import(\"postgres\");\n const { pgPoolOptions } = await import(\"./client.js\");\n return drizzlePg(\n pg(config.connectionString, pgPoolOptions(config.connectionString)),\n );\n }\n if (config.driver === \"sqlite\") {\n const sqlite = new Database(config.filename);\n sqlite.pragma(\"journal_mode = WAL\");\n return drizzle(sqlite);\n }\n throw new Error(`Unsupported driver: ${(config as any).driver}`);\n}\n\nexport type DrizzleDb = Awaited<ReturnType<typeof createDb>>;\n\nexport { createGetDb } from \"./create-get-db.js\";\nexport { runMigrations } from \"./migrations.js\";\nexport {\n getDbExec,\n createDbExec,\n getDialect,\n isPostgres,\n intType,\n closeDbExec,\n type DbExec,\n type DbExecConfig,\n type Dialect,\n} from \"./client.js\";\nexport { table, text, integer, now } from \"./schema.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAOrD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAgB;IAC7C,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;QACvE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QACjD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACtD,OAAO,SAAS,CACd,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,aAAa,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CACpE,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACpC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,uBAAwB,MAAc,CAAC,MAAM,EAAE,CAAC,CAAC;AACnE,CAAC;AAID,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EACL,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,EACV,OAAO,EACP,WAAW,GAIZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EACL,qBAAqB,GAItB,MAAM,8BAA8B,CAAC","sourcesContent":["import Database from \"better-sqlite3\";\nimport { drizzle } from \"drizzle-orm/better-sqlite3\";\n\nexport type DbConfig =\n | { driver: \"sqlite\"; filename: string }\n | { driver: \"d1\"; binding: any }\n | { driver: \"postgres\"; connectionString: string };\n\n/**\n * Create a Drizzle ORM database instance.\n * Supports SQLite via better-sqlite3 and Postgres via postgres-js.\n * Postgres driver is loaded dynamically to avoid bundling in edge runtimes.\n */\nexport async function createDb(config: DbConfig) {\n if (config.driver === \"postgres\") {\n const { drizzle: drizzlePg } = await import(\"drizzle-orm/postgres-js\");\n const { default: pg } = await import(\"postgres\");\n const { pgPoolOptions } = await import(\"./client.js\");\n return drizzlePg(\n pg(config.connectionString, pgPoolOptions(config.connectionString)),\n );\n }\n if (config.driver === \"sqlite\") {\n const sqlite = new Database(config.filename);\n sqlite.pragma(\"journal_mode = WAL\");\n return drizzle(sqlite);\n }\n throw new Error(`Unsupported driver: ${(config as any).driver}`);\n}\n\nexport type DrizzleDb = Awaited<ReturnType<typeof createDb>>;\n\nexport { createGetDb } from \"./create-get-db.js\";\nexport { runMigrations } from \"./migrations.js\";\nexport {\n getDbExec,\n createDbExec,\n getDialect,\n isPostgres,\n intType,\n closeDbExec,\n type DbExec,\n type DbExecConfig,\n type Dialect,\n} from \"./client.js\";\nexport { table, text, integer, now } from \"./schema.js\";\nexport {\n ensureAdditiveColumns,\n type EnsureAdditiveColumnsOptions,\n type EnsureAdditiveColumnsResult,\n type EnsureAdditiveColumnsLogger,\n} from \"./ensure-additive-columns.js\";\n"]}
|
package/dist/db/migrations.d.ts
CHANGED
|
@@ -43,6 +43,11 @@ export interface RunMigrationsOptions {
|
|
|
43
43
|
*
|
|
44
44
|
* { version: 14, sql: { postgres: "ALTER TABLE …" } } // no-op on sqlite
|
|
45
45
|
* { version: 15, sql: { sqlite: "…", postgres: "…" } } // both dialects
|
|
46
|
+
*
|
|
47
|
+
* `name` is an optional stable, unique slug that opts a migration into
|
|
48
|
+
* **name-based tracking** instead of the legacy version-number gate. See the
|
|
49
|
+
* "Name-based tracking" section on `runMigrations` for why this exists and
|
|
50
|
+
* exactly how the two gating strategies interact.
|
|
46
51
|
*/
|
|
47
52
|
export type MigrationSql = string | {
|
|
48
53
|
postgres?: string;
|
|
@@ -51,7 +56,72 @@ export type MigrationSql = string | {
|
|
|
51
56
|
export interface MigrationEntry {
|
|
52
57
|
version: number;
|
|
53
58
|
sql: MigrationSql;
|
|
59
|
+
/**
|
|
60
|
+
* Stable, unique slug for this migration (e.g. `"analytics-alert-rules-table"`).
|
|
61
|
+
* When present, this migration is tracked by NAME instead of by version
|
|
62
|
+
* number — see the `runMigrations` doc comment for the full rationale and
|
|
63
|
+
* gating rules. Must be unique across the migration list; a duplicate name
|
|
64
|
+
* throws at startup (programmer error, not a runtime data problem).
|
|
65
|
+
*/
|
|
66
|
+
name?: string;
|
|
54
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Runs a list of migrations against the configured database, gated by a
|
|
70
|
+
* per-table bookkeeping row (`options.table`) so repeated boots only apply
|
|
71
|
+
* new migrations.
|
|
72
|
+
*
|
|
73
|
+
* ## Name-based tracking (why it exists)
|
|
74
|
+
*
|
|
75
|
+
* The legacy gate is purely numeric: `SELECT MAX(version)` from the
|
|
76
|
+
* bookkeeping table, then apply every entry whose `version` is greater. That
|
|
77
|
+
* scheme silently breaks down when **two independent branches each extend the
|
|
78
|
+
* same migration list with different DDL under the same version numbers** —
|
|
79
|
+
* exactly what happened to the analytics template's v75-v83 range. Branch A
|
|
80
|
+
* shipped alert-rule tables as v75-v78; branch B shipped unrelated DDL as its
|
|
81
|
+
* own v75-v83. Whichever branch deployed first recorded "v75..v83 applied"
|
|
82
|
+
* in the bookkeeping table. When the other branch merged and deployed, its
|
|
83
|
+
* migrations at those same version numbers were never applied — `MAX(version)`
|
|
84
|
+
* was already ≥ their version, so the gate treated them as done even though
|
|
85
|
+
* their actual DDL had never run. The result: `analytics_migrations` showed
|
|
86
|
+
* rows for 1..83 with no gaps, yet `analytics_alert_rules`,
|
|
87
|
+
* `analytics_alert_incidents`, and `session_recordings.network_error_count`
|
|
88
|
+
* did not exist in production. Version numbers are not a stable identity —
|
|
89
|
+
* they're just sequence position, and sequence position collides across
|
|
90
|
+
* branches.
|
|
91
|
+
*
|
|
92
|
+
* Name-based tracking fixes this by keying application on a stable, unique
|
|
93
|
+
* **string slug** instead of a position in a shared integer sequence:
|
|
94
|
+
*
|
|
95
|
+
* - Entries with a `name` are recorded in a companion table,
|
|
96
|
+
* `${table}_named` (`name TEXT PRIMARY KEY`), and APPLY IFF their name is
|
|
97
|
+
* absent from that table — completely independent of version numbers or
|
|
98
|
+
* the legacy `MAX(version)` gate. Two branches can both ship a migration
|
|
99
|
+
* named `"analytics-alert-rules-table"` at version 75, or one at version 75
|
|
100
|
+
* and the other at version 90 after a rebase — either way it applies
|
|
101
|
+
* exactly once per database, keyed on the name.
|
|
102
|
+
* - Entries WITHOUT a `name` keep the exact legacy behavior
|
|
103
|
+
* (`version > MAX(recorded version)`), so nothing changes for existing
|
|
104
|
+
* unnamed migrations.
|
|
105
|
+
* - Named migrations still execute in list order, interleaved with unnamed
|
|
106
|
+
* ones exactly as written.
|
|
107
|
+
* - When a named migration's DDL runs, we record BOTH the named row (always)
|
|
108
|
+
* and — if its `version` is greater than the current legacy max — the
|
|
109
|
+
* legacy version row too, in the SAME atomic batch/transaction as the DDL.
|
|
110
|
+
* This keeps the legacy `MAX(version)` gate monotonically advancing for
|
|
111
|
+
* any unnamed migrations that come after it in the list, while ensuring a
|
|
112
|
+
* named migration is never "double recorded" in a way that would let it
|
|
113
|
+
* re-apply.
|
|
114
|
+
* - A duplicate `name` across the migration list throws at startup — that's
|
|
115
|
+
* a programmer error (copy-paste or merge mistake), not a runtime data
|
|
116
|
+
* problem, and failing loud beats silently tracking the wrong row.
|
|
117
|
+
*
|
|
118
|
+
* New migrations should always set a `name`. Legacy unnamed migrations don't
|
|
119
|
+
* need to be renamed retroactively — the two gating strategies coexist in the
|
|
120
|
+
* same list — but if a table is EVER at risk of being shared across parallel
|
|
121
|
+
* branches (any template's own migrations qualify, since branches routinely
|
|
122
|
+
* extend the same list concurrently), giving new entries a name is what makes
|
|
123
|
+
* them immune to the collision class described above.
|
|
124
|
+
*/
|
|
55
125
|
export declare function runMigrations(migrations: Array<MigrationEntry>, options: RunMigrationsOptions): NitroPluginDef;
|
|
56
126
|
export {};
|
|
57
127
|
//# sourceMappingURL=migrations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/db/migrations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/db/migrations.ts"],"names":[],"mappings":"AA8DA,KAAK,cAAc,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AA4B9D;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAK5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CASvD;AAmDD,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;;;;;OAYG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,YAAY,CAAC;IAClB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,KAAK,CAAC,cAAc,CAAC,EACjC,OAAO,EAAE,oBAAoB,GAC5B,cAAc,CAmYhB"}
|