@agent-native/core 0.85.7 → 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 +124 -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/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/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/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/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 +50 -12
- 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 +10 -2
- package/corpus/templates/design/actions/apply-fusion-edits.ts +161 -0
- package/corpus/templates/design/actions/apply-visual-edit.ts +34 -1
- 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/get-fusion-deploy-status.ts +86 -0
- 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/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/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 +115 -14
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +12 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +379 -0
- package/corpus/templates/design/app/components/design/EditPanel.tsx +149 -73
- package/corpus/templates/design/app/components/design/FusionAppBanner.tsx +328 -0
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +148 -30
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +1 -1
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +567 -6
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +7 -98
- 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/DesignColorPicker.tsx +127 -10
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +52 -29
- package/corpus/templates/design/app/components/design/inspector/index.ts +9 -0
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +56 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +80 -1
- package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +6 -16
- package/corpus/templates/design/app/i18n/zh-TW.ts +2 -1
- package/corpus/templates/design/app/i18n-data.ts +31 -18
- package/corpus/templates/design/app/pages/DesignEditor.tsx +1474 -175
- package/corpus/templates/design/app/pages/Index.tsx +90 -17
- 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/package.json +4 -3
- package/corpus/templates/design/server/db/schema.ts +31 -0
- 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/collab-selection.ts +52 -0
- package/corpus/templates/design/shared/full-app.ts +126 -0
- package/corpus/templates/design/shared/pen-path.ts +296 -0
- 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/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 +12 -1
- 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/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/routes.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- 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 +2 -2
- 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/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- 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/server/transcribe-voice.d.ts +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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-get-db.js","sourceRoot":"","sources":["../../src/db/create-get-db.ts"],"names":[],"mappings":"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","sourcesContent":["import { drizzle as drizzleD1 } from \"drizzle-orm/d1\";\nimport type { LibSQLDatabase } from \"drizzle-orm/libsql\";\n\nimport {\n getDialect,\n getDatabaseUrl,\n getDatabaseAuthToken,\n isLocalSqliteUrl,\n isPgliteUrl,\n isConnectionError,\n getPgliteClient,\n loadPgliteDrizzle,\n prepareLocalSqliteUrl,\n sqliteFilenameFromUrl,\n pgPoolOptions,\n neonPoolMax,\n attachNeonPoolErrorLogger,\n withDbTimeout,\n retryOnConnectionError,\n dbOpTimeoutMs,\n} from \"./client.js\";\n\n// Lazy driver loaders — cached promises so dynamic import only runs once.\nlet _pgDrizzle: Promise<{ drizzle: any; postgres: any }> | undefined;\nfunction getPgDrizzle() {\n if (!_pgDrizzle) {\n _pgDrizzle = Promise.all([\n import(\"drizzle-orm/postgres-js\"),\n import(\"postgres\"),\n ]).then(([drizzleMod, pgMod]) => ({\n drizzle: drizzleMod.drizzle,\n postgres: pgMod.default,\n }));\n }\n return _pgDrizzle;\n}\n\nlet _neonServerlessDrizzle: Promise<{ drizzle: any; Pool: any }> | undefined;\nfunction getNeonServerlessDrizzle() {\n if (!_neonServerlessDrizzle) {\n _neonServerlessDrizzle = Promise.all([\n import(\"drizzle-orm/neon-serverless\"),\n import(\"@neondatabase/serverless\"),\n ]).then(([drizzleMod, neonMod]) => ({\n drizzle: drizzleMod.drizzle,\n Pool: neonMod.Pool,\n }));\n }\n return _neonServerlessDrizzle;\n}\n\n/**\n * Returns true when a SQL string starts with a SELECT-class verb.\n * Used by the Neon resilience wrapper to decide retry safety:\n * - reads (SELECT) → retryable on any connection-class error\n * - writes (INSERT/UPDATE/DELETE/…) → only retryable on errors that\n * provably occurred BEFORE the statement was sent (e.g. an acquire /\n * connect timeout). Post-send write failures must propagate to the caller\n * to avoid double-execution.\n */\nexport function isSqlRead(sql: string): boolean {\n return /^\\s*(SELECT|WITH\\s)/i.test(sql);\n}\n\n/**\n * Wraps a @neondatabase/serverless Pool so every query goes through\n * the same withDbTimeout + retryOnConnectionError resilience that the\n * raw DbExec path in client.ts uses. This protects Drizzle queries\n * (which bypass DbExec) from the frozen-WebSocket failure mode documented\n * in client.ts (~lines 378–408).\n *\n * Retry-safety rule (prevents double-execution on writes):\n * - Reads (SELECT / WITH …): retry freely on any connection-class error.\n * - Writes: only retry when the error occurred during connection acquire\n * (i.e. withDbTimeout \"connect\" timed out before the statement was ever\n * sent). Post-send failures on writes are rethrown immediately.\n *\n * Transactions: we do NOT wrap individual queries inside a drizzle\n * transaction — drizzle-neon-serverless manages the session itself, so\n * interposing a per-query client acquire/release would break the sticky\n * connection the transaction needs. The pool-level error logger still fires\n * on idle-client drops inside transactions.\n */\nexport function buildResilientNeonPool(pool: {\n connect(): Promise<any>;\n query(\n sql: string,\n args?: any[],\n ): Promise<{ rows: unknown[]; rowCount?: number }>;\n end(): Promise<void>;\n on(event: string, listener: (...args: any[]) => void): unknown;\n}): typeof pool {\n // Preserve all original pool methods and properties; only override `connect`\n // and `query` at the Pool level (used by drizzle's neon-serverless adapter\n // when it calls pool.query() directly, e.g. outside a transaction).\n const resilientQuery = async (\n sql: string,\n args?: any[],\n ): Promise<{ rows: unknown[]; rowCount?: number }> => {\n const isRead = isSqlRead(sql);\n\n const runAttempt = async (): Promise<{\n rows: unknown[];\n rowCount?: number;\n }> => {\n // Bound the pool.connect() acquire — a frozen Neon WebSocket stalls here\n // before the query ever starts, so a query-level timeout alone won't help.\n let acquireTimedOut = false;\n const client = await withDbTimeout(\n \"connect\",\n () =>\n pool.connect().then((c: any) => {\n // If we already gave up on this slot, immediately release it so\n // the scarce pool connection isn't leaked.\n if (acquireTimedOut) c.release();\n return c;\n }),\n dbOpTimeoutMs(),\n () => {\n acquireTimedOut = true;\n },\n );\n\n let released = false;\n const releaseClient = (err?: Error | boolean) => {\n if (released) return;\n released = true;\n client.release(err);\n };\n\n try {\n const result = await withDbTimeout(\n \"query\",\n () =>\n client.query(sql, args ?? []) as Promise<{\n rows: unknown[];\n rowCount?: number;\n }>,\n dbOpTimeoutMs(),\n () => releaseClient(true),\n );\n releaseClient();\n return result;\n } catch (err) {\n releaseClient(isConnectionError(err) ? true : undefined);\n throw err;\n }\n };\n\n if (isRead) {\n // Reads: retry on any connection-class error (safe — no side effects).\n return retryOnConnectionError(runAttempt);\n }\n\n // Writes: attempt once. If the acquire itself times out (error occurs\n // before the statement was sent), that produces a CONNECT_TIMEOUT which\n // isConnectionError() recognises → retry is safe. Any error that surfaces\n // AFTER the statement was sent must propagate immediately to avoid\n // double-execution.\n try {\n return await runAttempt();\n } catch (err) {\n // acquire-timeout fires before the statement → safe to retry once.\n if (isConnectionError(err) && (err as any)?.code === \"CONNECT_TIMEOUT\") {\n return runAttempt();\n }\n throw err;\n }\n };\n\n // Return a proxy so every pool property/method is forwarded as-is, but\n // pool.query() goes through the resilient wrapper. drizzle-neon-serverless\n // calls pool.connect() for transactions and pool.query() for simple queries.\n return new Proxy(pool, {\n get(target, prop) {\n if (prop === \"query\") return resilientQuery;\n const val = (target as any)[prop];\n return typeof val === \"function\" ? val.bind(target) : val;\n },\n });\n}\n\n/**\n * Neon's pooler endpoints cold-start in 5–10s. Serverless environments\n * (Netlify Functions, Vercel Edge, CF Workers) have short cold-start\n * budgets of their own, and `postgres-js` opens a raw TCP connection on\n * port 5432 that can't negotiate around Neon's wake-up window — every\n * request after an idle period 502s. `@neondatabase/serverless` rides\n * over WebSockets (HTTP/443 upgrade) and handles Neon wake-up\n * transparently, supports transactions, and works in every serverless\n * runtime we deploy to, so we prefer it whenever the URL points at Neon.\n */\nexport function isNeonUrl(url: string): boolean {\n // Must match neon.tech followed by port/path/query/end — include `?` so\n // URLs like `postgres://…@ep.neon.tech?sslmode=require` (no explicit port\n // or path) still route through the serverless driver.\n return /\\.neon\\.tech([:/?]|$)/.test(url);\n}\n\nlet _libsqlWebDrizzle: Promise<{ drizzle: any }> | undefined;\nfunction getLibsqlWebDrizzle() {\n if (!_libsqlWebDrizzle) {\n _libsqlWebDrizzle = import(\"drizzle-orm/libsql/web\").then((mod) => ({\n drizzle: mod.drizzle,\n }));\n }\n return _libsqlWebDrizzle;\n}\n\nlet _betterSqliteDrizzle: Promise<{ drizzle: any; Database: any }> | undefined;\nfunction getBetterSqliteDrizzle() {\n if (!_betterSqliteDrizzle) {\n _betterSqliteDrizzle = Promise.all([\n import(\"drizzle-orm/better-sqlite3\"),\n import(\"better-sqlite3\"),\n ]).then(([drizzleMod, sqliteMod]) => ({\n drizzle: drizzleMod.drizzle,\n Database: sqliteMod.default,\n }));\n }\n return _betterSqliteDrizzle;\n}\n\n/**\n * Patch a drizzle-orm/better-sqlite3 instance so that db.transaction(async …)\n * works. The native better-sqlite3 Transaction wrapper is sync-only — passing\n * an async callback throws \"Transaction function cannot return a promise\".\n *\n * This wrapper bypasses the native path by issuing raw SQL control statements\n * on the single better-sqlite3 connection, which is safe because:\n * - better-sqlite3 is single-connection (no concurrency inside one process)\n * - the framework serialises all async work through one Database instance\n *\n * Nesting: if a transaction is already open (sqlite.inTransaction === true),\n * SAVEPOINT / RELEASE / ROLLBACK TO is used instead of BEGIN / COMMIT /\n * ROLLBACK, matching drizzle's own BetterSQLiteTransaction.transaction().\n *\n * The patched transaction also patches the tx object it passes to the callback\n * so that nested async calls (tx.transaction(async …)) work recursively.\n */\nfunction patchBetterSqliteTransactions<\n DB extends { transaction: (...args: any[]) => any; session: any },\n>(db: DB, sqlite: { inTransaction: boolean; exec: (sql: string) => void }): DB {\n let savepointSeq = 0;\n\n function makeAsyncTransaction(\n originalTransaction: (...args: any[]) => any,\n ): (...args: any[]) => Promise<unknown> {\n return async function asyncTransaction(\n cb: (tx: unknown) => unknown,\n ): Promise<unknown> {\n // Extract the drizzle tx proxy synchronously — call the original with a\n // stub that captures the tx arg then immediately throws a sentinel so\n // better-sqlite3's native wrapper rolls back the stub and re-throws.\n // The sentinel is caught here and never propagates further.\n let capturedTx: unknown;\n try {\n originalTransaction((tx: unknown) => {\n capturedTx = tx;\n throw _EXTRACT_TX;\n });\n } catch (e) {\n if (e !== _EXTRACT_TX) throw e;\n }\n\n // Recursively patch the nested tx so tx.transaction(async …) also works.\n const tx = capturedTx as { transaction: (...a: any[]) => any };\n if (tx && typeof tx.transaction === \"function\") {\n tx.transaction = makeAsyncTransaction(tx.transaction.bind(tx));\n }\n\n const nested = sqlite.inTransaction;\n if (nested) {\n const sp = `sp_async_${++savepointSeq}`;\n sqlite.exec(`SAVEPOINT ${sp}`);\n let released = false;\n try {\n const result = await cb(tx);\n sqlite.exec(`RELEASE SAVEPOINT ${sp}`);\n released = true;\n return result;\n } catch (err) {\n if (!released) {\n try {\n sqlite.exec(`ROLLBACK TO SAVEPOINT ${sp}`);\n sqlite.exec(`RELEASE SAVEPOINT ${sp}`);\n } catch {\n /* ignore: connection may already be in an error state */\n }\n }\n throw err;\n }\n }\n\n // Top-level: BEGIN IMMEDIATE … COMMIT / ROLLBACK.\n sqlite.exec(\"BEGIN IMMEDIATE\");\n let committed = false;\n try {\n const result = await cb(tx);\n sqlite.exec(\"COMMIT\");\n committed = true;\n return result;\n } catch (err) {\n if (!committed) {\n try {\n sqlite.exec(\"ROLLBACK\");\n } catch {\n /* swallow: connection may already be unusable */\n }\n }\n throw err;\n }\n };\n }\n\n db.transaction = makeAsyncTransaction(db.transaction.bind(db));\n return db;\n}\n\n/** Sentinel thrown inside the tx-extraction stub — never escapes the catch. */\nconst _EXTRACT_TX = Symbol(\"extract-tx\");\n\nexport function createGetDb<T extends Record<string, unknown>>(schema: T) {\n let _db: any;\n let _dbReady: Promise<any> | undefined;\n\n function startInit(): Promise<any> {\n if (_dbReady) return _dbReady;\n\n const url = getDatabaseUrl(\"file:./data/app.db\");\n const dialect = getDialect();\n\n // D1 only if dialect detected it (DATABASE_URL takes priority)\n if (dialect === \"d1\") {\n const d1 = globalThis.__cf_env?.DB;\n if (d1) {\n _db = drizzleD1(d1, { schema }) as unknown as LibSQLDatabase<T>;\n _dbReady = Promise.resolve(_db);\n return _dbReady;\n }\n }\n\n if (isPgliteUrl(url)) {\n _dbReady = loadPgliteDrizzle().then(async ({ drizzle }) => {\n const client = await getPgliteClient(url);\n _db = drizzle({ client, schema });\n });\n return _dbReady;\n }\n\n if (dialect === \"postgres\") {\n if (isNeonUrl(url)) {\n _dbReady = getNeonServerlessDrizzle().then(({ drizzle, Pool }) => {\n const rawPool = new Pool({\n connectionString: url,\n max: neonPoolMax(),\n });\n attachNeonPoolErrorLogger(rawPool);\n // Wrap the pool with the resilience layer so Drizzle queries get the\n // same withDbTimeout + retryOnConnectionError protection as the raw\n // DbExec path in client.ts. Reads retry freely; writes only retry on\n // acquire-timeout (pre-send) errors to avoid double-execution.\n const pool = buildResilientNeonPool(rawPool);\n _db = drizzle(pool, { schema });\n });\n } else {\n _dbReady = getPgDrizzle().then(({ drizzle, postgres }) => {\n // pgPoolOptions caps the pool to a small size on serverless so\n // concurrent frozen instances don't exhaust Neon/Postgres'\n // connection limit (\"Max client connections reached\").\n const client = postgres(url, pgPoolOptions(url));\n _db = drizzle(client, { schema });\n });\n }\n } else if (isLocalSqliteUrl(url)) {\n _dbReady = Promise.all([\n prepareLocalSqliteUrl(url.startsWith(\"file:\") ? url : `file:${url}`),\n getBetterSqliteDrizzle(),\n ]).then(([sqliteUrl, { drizzle, Database }]) => {\n const sqlite = new Database(sqliteFilenameFromUrl(sqliteUrl));\n sqlite.pragma(\"journal_mode = WAL\");\n const db = drizzle(sqlite, { schema });\n _db = patchBetterSqliteTransactions(db, sqlite);\n });\n } else {\n _dbReady = getLibsqlWebDrizzle().then(({ drizzle }) => {\n _db = drizzle({\n connection: { url, authToken: getDatabaseAuthToken() },\n schema,\n });\n });\n }\n return _dbReady;\n }\n\n /**\n * Create a lazy proxy that records property accesses and method calls,\n * then replays them on the real DB once init completes. Supports\n * Drizzle's chained API: db.select().from(table).where(...).\n *\n * When `.then()` is called (i.e. the chain is awaited), the proxy\n * awaits _dbReady and replays the recorded chain on the real _db.\n */\n function createLazyProxy(\n ready: Promise<any>,\n chain: Array<{ prop: string | symbol; args?: any[] }>,\n ): any {\n return new Proxy(function () {} as any, {\n get(_target, prop) {\n // When awaited, replay the chain on the real db\n if (prop === \"then\" || prop === \"catch\" || prop === \"finally\") {\n const promise = ready.then(() => {\n let result: any = _db;\n for (const step of chain) {\n const val = result[step.prop];\n result =\n typeof val === \"function\" ? val.apply(result, step.args) : val;\n }\n return result;\n });\n return (promise as any)[prop].bind(promise);\n }\n // Symbol.toStringTag, Symbol.iterator, etc. — return another proxy\n // Property access (e.g. db.query) — record and return another proxy\n return createLazyProxy(ready, [...chain, { prop }]);\n },\n apply(_target, _thisArg, args) {\n // Method call (e.g. .from(table)) — record args and return another proxy\n if (chain.length === 0) return createLazyProxy(ready, []);\n const last = chain[chain.length - 1];\n const newChain = chain.slice(0, -1);\n newChain.push({ prop: last.prop, args });\n return createLazyProxy(ready, newChain);\n },\n });\n }\n\n /**\n * Get the Drizzle DB instance. Kicks off lazy init on first call.\n * If the async init hasn't completed yet, returns a lazy Proxy that\n * records the Drizzle chain (select/from/where/etc.) and replays it\n * once the DB driver finishes loading. Since callers always `await`\n * the final result, the proxy is transparent.\n */\n function getDb(): LibSQLDatabase<T> {\n if (_db) return _db;\n startInit();\n if (_db) return _db;\n\n return createLazyProxy(_dbReady!, []) as LibSQLDatabase<T>;\n }\n\n return getDb;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"create-get-db.js","sourceRoot":"","sources":["../../src/db/create-get-db.ts"],"names":[],"mappings":"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","sourcesContent":["import { drizzle as drizzleD1 } from \"drizzle-orm/d1\";\nimport type { LibSQLDatabase } from \"drizzle-orm/libsql\";\n\nimport {\n getDialect,\n getDatabaseUrl,\n getDatabaseAuthToken,\n isLocalSqliteUrl,\n isPgliteUrl,\n isConnectionError,\n getPgliteClient,\n loadPgliteDrizzle,\n prepareLocalSqliteUrl,\n sqliteFilenameFromUrl,\n pgPoolOptions,\n neonPoolMax,\n attachNeonPoolErrorLogger,\n withDbTimeout,\n retryOnConnectionError,\n dbOpTimeoutMs,\n} from \"./client.js\";\n\n// Lazy driver loaders — cached promises so dynamic import only runs once.\nlet _pgDrizzle: Promise<{ drizzle: any; postgres: any }> | undefined;\nfunction getPgDrizzle() {\n if (!_pgDrizzle) {\n _pgDrizzle = Promise.all([\n import(\"drizzle-orm/postgres-js\"),\n import(\"postgres\"),\n ]).then(([drizzleMod, pgMod]) => ({\n drizzle: drizzleMod.drizzle,\n postgres: pgMod.default,\n }));\n }\n return _pgDrizzle;\n}\n\nlet _neonServerlessDrizzle: Promise<{ drizzle: any; Pool: any }> | undefined;\nfunction getNeonServerlessDrizzle() {\n if (!_neonServerlessDrizzle) {\n _neonServerlessDrizzle = Promise.all([\n import(\"drizzle-orm/neon-serverless\"),\n import(\"@neondatabase/serverless\"),\n ]).then(([drizzleMod, neonMod]) => ({\n drizzle: drizzleMod.drizzle,\n Pool: neonMod.Pool,\n }));\n }\n return _neonServerlessDrizzle;\n}\n\n/**\n * Returns true when a SQL string starts with a SELECT-class verb.\n * Used by the Neon resilience wrapper to decide retry safety:\n * - reads (SELECT) → retryable on any connection-class error\n * - writes (INSERT/UPDATE/DELETE/…) → only retryable on errors that\n * provably occurred BEFORE the statement was sent (e.g. an acquire /\n * connect timeout). Post-send write failures must propagate to the caller\n * to avoid double-execution.\n */\nexport function isSqlRead(sql: string): boolean {\n return /^\\s*(SELECT|WITH\\s)/i.test(sql);\n}\n\n/**\n * Wraps a @neondatabase/serverless Pool so every query goes through\n * the same withDbTimeout + retryOnConnectionError resilience that the\n * raw DbExec path in client.ts uses. This protects Drizzle queries\n * (which bypass DbExec) from the frozen-WebSocket failure mode documented\n * in client.ts (~lines 378–408).\n *\n * Retry-safety rule (prevents double-execution on writes):\n * - Reads (SELECT / WITH …): retry freely on any connection-class error.\n * - Writes: only retry when the error occurred during connection acquire\n * (i.e. withDbTimeout \"connect\" timed out before the statement was ever\n * sent). Post-send failures on writes are rethrown immediately.\n *\n * Transactions: we do NOT wrap individual queries inside a drizzle\n * transaction — drizzle-neon-serverless manages the session itself, so\n * interposing a per-query client acquire/release would break the sticky\n * connection the transaction needs. The pool-level error logger still fires\n * on idle-client drops inside transactions.\n */\nexport function buildResilientNeonPool(pool: {\n connect(): Promise<any>;\n query(\n sql: string,\n args?: any[],\n ): Promise<{ rows: unknown[]; rowCount?: number }>;\n end(): Promise<void>;\n on(event: string, listener: (...args: any[]) => void): unknown;\n}): typeof pool {\n // Preserve all original pool methods and properties; only override `connect`\n // and `query` at the Pool level (used by drizzle's neon-serverless adapter\n // when it calls pool.query() directly, e.g. outside a transaction).\n const resilientQuery = async (\n sql: string,\n args?: any[],\n ): Promise<{ rows: unknown[]; rowCount?: number }> => {\n const isRead = isSqlRead(sql);\n\n const runAttempt = async (): Promise<{\n rows: unknown[];\n rowCount?: number;\n }> => {\n // Bound the pool.connect() acquire — a frozen Neon WebSocket stalls here\n // before the query ever starts, so a query-level timeout alone won't help.\n let acquireTimedOut = false;\n const client = await withDbTimeout(\n \"connect\",\n () =>\n pool.connect().then((c: any) => {\n // If we already gave up on this slot, immediately release it so\n // the scarce pool connection isn't leaked.\n if (acquireTimedOut) c.release();\n return c;\n }),\n dbOpTimeoutMs(),\n () => {\n acquireTimedOut = true;\n },\n );\n\n let released = false;\n const releaseClient = (err?: Error | boolean) => {\n if (released) return;\n released = true;\n client.release(err);\n };\n\n try {\n const result = await withDbTimeout(\n \"query\",\n () =>\n client.query(sql, args ?? []) as Promise<{\n rows: unknown[];\n rowCount?: number;\n }>,\n dbOpTimeoutMs(),\n () => releaseClient(true),\n );\n releaseClient();\n return result;\n } catch (err) {\n releaseClient(isConnectionError(err) ? true : undefined);\n throw err;\n }\n };\n\n if (isRead) {\n // Reads: retry on any connection-class error (safe — no side effects).\n return retryOnConnectionError(runAttempt);\n }\n\n // Writes: attempt once. If the acquire itself times out (error occurs\n // before the statement was sent), that produces a CONNECT_TIMEOUT which\n // isConnectionError() recognises → retry is safe. Any error that surfaces\n // AFTER the statement was sent must propagate immediately to avoid\n // double-execution.\n try {\n return await runAttempt();\n } catch (err) {\n // acquire-timeout fires before the statement → safe to retry once.\n if (isConnectionError(err) && (err as any)?.code === \"CONNECT_TIMEOUT\") {\n return runAttempt();\n }\n throw err;\n }\n };\n\n // Return a proxy so every pool property/method is forwarded as-is, but\n // pool.query() goes through the resilient wrapper. drizzle-neon-serverless\n // calls pool.connect() for transactions and pool.query() for simple queries.\n return new Proxy(pool, {\n get(target, prop) {\n if (prop === \"query\") return resilientQuery;\n const val = (target as any)[prop];\n return typeof val === \"function\" ? val.bind(target) : val;\n },\n });\n}\n\n/**\n * Wraps a postgres.js client so Drizzle queries on the non-Neon Postgres\n * path get the same withDbTimeout + retryOnConnectionError protection as\n * every other Postgres path (raw DbExec postgres.js, raw DbExec Neon, and\n * the Drizzle Neon pool above). Without this, one hung query on a BYO\n * Postgres deployment stalls its request forever.\n *\n * Drizzle's postgres-js session only calls `client.unsafe(query, params)` —\n * awaited directly for row-object results or via `.values()` for row-array\n * results — plus `client.begin(...)` for transactions. We interpose on\n * `unsafe` with a lazy thenable that re-issues the query per retry attempt,\n * and leave transactions unwrapped (same rule as the Neon wrapper: the\n * driver manages the sticky connection inside `begin`).\n *\n * Retry-safety mirrors buildResilientNeonPool: reads retry freely on\n * connection-class errors; writes retry only on CONNECT_TIMEOUT (postgres.js\n * raises it before the statement is ever sent), so writes can't\n * double-execute.\n */\nexport function buildResilientPostgresJsClient<\n T extends {\n unsafe(query: string, params?: any[], options?: any): any;\n },\n>(client: T): T {\n const wrapUnsafe = (query: string, params?: any[], options?: any) => {\n const isRead = isSqlRead(query);\n\n const runAttempt = (mode: \"rows\" | \"values\") => async (): Promise<any> => {\n const pending = client.unsafe(query, params, options);\n return withDbTimeout(\n \"query\",\n async () => (mode === \"values\" ? pending.values() : pending),\n dbOpTimeoutMs(),\n () => {\n // Best-effort cancel so the timed-out statement doesn't keep\n // occupying one of the (small, serverless-capped) pool slots.\n try {\n pending.cancel?.();\n } catch {\n // ignore — cancellation is advisory\n }\n },\n );\n };\n\n const execute = async (mode: \"rows\" | \"values\"): Promise<any> => {\n if (isRead) return retryOnConnectionError(runAttempt(mode));\n try {\n return await runAttempt(mode)();\n } catch (err) {\n // Connect timeout fires before the statement is sent → one retry is\n // safe even for writes.\n if (\n isConnectionError(err) &&\n (err as any)?.code === \"CONNECT_TIMEOUT\"\n ) {\n return runAttempt(mode)();\n }\n throw err;\n }\n };\n\n // Lazy thenable mirroring the slice of postgres.js's PendingQuery\n // surface that Drizzle uses: `await q` or `await q.values()`.\n return {\n then: (onFulfilled?: any, onRejected?: any) =>\n execute(\"rows\").then(onFulfilled, onRejected),\n catch: (onRejected?: any) => execute(\"rows\").catch(onRejected),\n finally: (onFinally?: any) => execute(\"rows\").finally(onFinally),\n values: () => execute(\"values\"),\n };\n };\n\n return new Proxy(client as any, {\n get(target, prop) {\n if (prop === \"unsafe\") return wrapUnsafe;\n const val = target[prop];\n return typeof val === \"function\" ? val.bind(target) : val;\n },\n }) as T;\n}\n\n/**\n * Neon's pooler endpoints cold-start in 5–10s. Serverless environments\n * (Netlify Functions, Vercel Edge, CF Workers) have short cold-start\n * budgets of their own, and `postgres-js` opens a raw TCP connection on\n * port 5432 that can't negotiate around Neon's wake-up window — every\n * request after an idle period 502s. `@neondatabase/serverless` rides\n * over WebSockets (HTTP/443 upgrade) and handles Neon wake-up\n * transparently, supports transactions, and works in every serverless\n * runtime we deploy to, so we prefer it whenever the URL points at Neon.\n */\nexport function isNeonUrl(url: string): boolean {\n // Must match neon.tech followed by port/path/query/end — include `?` so\n // URLs like `postgres://…@ep.neon.tech?sslmode=require` (no explicit port\n // or path) still route through the serverless driver.\n return /\\.neon\\.tech([:/?]|$)/.test(url);\n}\n\nlet _libsqlWebDrizzle: Promise<{ drizzle: any }> | undefined;\nfunction getLibsqlWebDrizzle() {\n if (!_libsqlWebDrizzle) {\n _libsqlWebDrizzle = import(\"drizzle-orm/libsql/web\").then((mod) => ({\n drizzle: mod.drizzle,\n }));\n }\n return _libsqlWebDrizzle;\n}\n\nlet _betterSqliteDrizzle: Promise<{ drizzle: any; Database: any }> | undefined;\nfunction getBetterSqliteDrizzle() {\n if (!_betterSqliteDrizzle) {\n _betterSqliteDrizzle = Promise.all([\n import(\"drizzle-orm/better-sqlite3\"),\n import(\"better-sqlite3\"),\n ]).then(([drizzleMod, sqliteMod]) => ({\n drizzle: drizzleMod.drizzle,\n Database: sqliteMod.default,\n }));\n }\n return _betterSqliteDrizzle;\n}\n\n/**\n * Patch a drizzle-orm/better-sqlite3 instance so that db.transaction(async …)\n * works. The native better-sqlite3 Transaction wrapper is sync-only — passing\n * an async callback throws \"Transaction function cannot return a promise\".\n *\n * This wrapper bypasses the native path by issuing raw SQL control statements\n * on the single better-sqlite3 connection, which is safe because:\n * - better-sqlite3 is single-connection (no concurrency inside one process)\n * - the framework serialises all async work through one Database instance\n *\n * Nesting: if a transaction is already open (sqlite.inTransaction === true),\n * SAVEPOINT / RELEASE / ROLLBACK TO is used instead of BEGIN / COMMIT /\n * ROLLBACK, matching drizzle's own BetterSQLiteTransaction.transaction().\n *\n * The patched transaction also patches the tx object it passes to the callback\n * so that nested async calls (tx.transaction(async …)) work recursively.\n */\nfunction patchBetterSqliteTransactions<\n DB extends { transaction: (...args: any[]) => any; session: any },\n>(db: DB, sqlite: { inTransaction: boolean; exec: (sql: string) => void }): DB {\n let savepointSeq = 0;\n\n function makeAsyncTransaction(\n originalTransaction: (...args: any[]) => any,\n ): (...args: any[]) => Promise<unknown> {\n return async function asyncTransaction(\n cb: (tx: unknown) => unknown,\n ): Promise<unknown> {\n // Extract the drizzle tx proxy synchronously — call the original with a\n // stub that captures the tx arg then immediately throws a sentinel so\n // better-sqlite3's native wrapper rolls back the stub and re-throws.\n // The sentinel is caught here and never propagates further.\n let capturedTx: unknown;\n try {\n originalTransaction((tx: unknown) => {\n capturedTx = tx;\n throw _EXTRACT_TX;\n });\n } catch (e) {\n if (e !== _EXTRACT_TX) throw e;\n }\n\n // Recursively patch the nested tx so tx.transaction(async …) also works.\n const tx = capturedTx as { transaction: (...a: any[]) => any };\n if (tx && typeof tx.transaction === \"function\") {\n tx.transaction = makeAsyncTransaction(tx.transaction.bind(tx));\n }\n\n const nested = sqlite.inTransaction;\n if (nested) {\n const sp = `sp_async_${++savepointSeq}`;\n sqlite.exec(`SAVEPOINT ${sp}`);\n let released = false;\n try {\n const result = await cb(tx);\n sqlite.exec(`RELEASE SAVEPOINT ${sp}`);\n released = true;\n return result;\n } catch (err) {\n if (!released) {\n try {\n sqlite.exec(`ROLLBACK TO SAVEPOINT ${sp}`);\n sqlite.exec(`RELEASE SAVEPOINT ${sp}`);\n } catch {\n /* ignore: connection may already be in an error state */\n }\n }\n throw err;\n }\n }\n\n // Top-level: BEGIN IMMEDIATE … COMMIT / ROLLBACK.\n sqlite.exec(\"BEGIN IMMEDIATE\");\n let committed = false;\n try {\n const result = await cb(tx);\n sqlite.exec(\"COMMIT\");\n committed = true;\n return result;\n } catch (err) {\n if (!committed) {\n try {\n sqlite.exec(\"ROLLBACK\");\n } catch {\n /* swallow: connection may already be unusable */\n }\n }\n throw err;\n }\n };\n }\n\n db.transaction = makeAsyncTransaction(db.transaction.bind(db));\n return db;\n}\n\n/** Sentinel thrown inside the tx-extraction stub — never escapes the catch. */\nconst _EXTRACT_TX = Symbol(\"extract-tx\");\n\nexport function createGetDb<T extends Record<string, unknown>>(schema: T) {\n let _db: any;\n let _dbReady: Promise<any> | undefined;\n\n function startInit(): Promise<any> {\n if (_dbReady) return _dbReady;\n\n const url = getDatabaseUrl(\"file:./data/app.db\");\n const dialect = getDialect();\n\n // D1 only if dialect detected it (DATABASE_URL takes priority)\n if (dialect === \"d1\") {\n const d1 = globalThis.__cf_env?.DB;\n if (d1) {\n _db = drizzleD1(d1, { schema }) as unknown as LibSQLDatabase<T>;\n _dbReady = Promise.resolve(_db);\n return _dbReady;\n }\n }\n\n if (isPgliteUrl(url)) {\n _dbReady = loadPgliteDrizzle().then(async ({ drizzle }) => {\n const client = await getPgliteClient(url);\n _db = drizzle({ client, schema });\n });\n return _dbReady;\n }\n\n if (dialect === \"postgres\") {\n if (isNeonUrl(url)) {\n _dbReady = getNeonServerlessDrizzle().then(({ drizzle, Pool }) => {\n const rawPool = new Pool({\n connectionString: url,\n max: neonPoolMax(),\n });\n attachNeonPoolErrorLogger(rawPool);\n // Wrap the pool with the resilience layer so Drizzle queries get the\n // same withDbTimeout + retryOnConnectionError protection as the raw\n // DbExec path in client.ts. Reads retry freely; writes only retry on\n // acquire-timeout (pre-send) errors to avoid double-execution.\n const pool = buildResilientNeonPool(rawPool);\n _db = drizzle(pool, { schema });\n });\n } else {\n _dbReady = getPgDrizzle().then(({ drizzle, postgres }) => {\n // pgPoolOptions caps the pool to a small size on serverless so\n // concurrent frozen instances don't exhaust Neon/Postgres'\n // connection limit (\"Max client connections reached\").\n const client = postgres(url, pgPoolOptions(url));\n _db = drizzle(buildResilientPostgresJsClient(client), { schema });\n });\n }\n } else if (isLocalSqliteUrl(url)) {\n _dbReady = Promise.all([\n prepareLocalSqliteUrl(url.startsWith(\"file:\") ? url : `file:${url}`),\n getBetterSqliteDrizzle(),\n ]).then(([sqliteUrl, { drizzle, Database }]) => {\n const sqlite = new Database(sqliteFilenameFromUrl(sqliteUrl));\n // Wait up to 10s for a concurrent writer instead of failing fast\n // with SQLITE_BUSY — mirrors the raw DbExec SQLite path in client.ts.\n sqlite.pragma(\"busy_timeout = 10000\");\n sqlite.pragma(\"journal_mode = WAL\");\n const db = drizzle(sqlite, { schema });\n _db = patchBetterSqliteTransactions(db, sqlite);\n });\n } else {\n _dbReady = getLibsqlWebDrizzle().then(({ drizzle }) => {\n _db = drizzle({\n connection: { url, authToken: getDatabaseAuthToken() },\n schema,\n });\n });\n }\n return _dbReady;\n }\n\n /**\n * Create a lazy proxy that records property accesses and method calls,\n * then replays them on the real DB once init completes. Supports\n * Drizzle's chained API: db.select().from(table).where(...).\n *\n * When `.then()` is called (i.e. the chain is awaited), the proxy\n * awaits _dbReady and replays the recorded chain on the real _db.\n */\n function createLazyProxy(\n ready: Promise<any>,\n chain: Array<{ prop: string | symbol; args?: any[] }>,\n ): any {\n return new Proxy(function () {} as any, {\n get(_target, prop) {\n // When awaited, replay the chain on the real db\n if (prop === \"then\" || prop === \"catch\" || prop === \"finally\") {\n const promise = ready.then(() => {\n let result: any = _db;\n for (const step of chain) {\n const val = result[step.prop];\n result =\n typeof val === \"function\" ? val.apply(result, step.args) : val;\n }\n return result;\n });\n return (promise as any)[prop].bind(promise);\n }\n // Symbol.toStringTag, Symbol.iterator, etc. — return another proxy\n // Property access (e.g. db.query) — record and return another proxy\n return createLazyProxy(ready, [...chain, { prop }]);\n },\n apply(_target, _thisArg, args) {\n // Method call (e.g. .from(table)) — record args and return another proxy\n if (chain.length === 0) return createLazyProxy(ready, []);\n const last = chain[chain.length - 1];\n const newChain = chain.slice(0, -1);\n newChain.push({ prop: last.prop, args });\n return createLazyProxy(ready, newChain);\n },\n });\n }\n\n /**\n * Get the Drizzle DB instance. Kicks off lazy init on first call.\n * If the async init hasn't completed yet, returns a lazy Proxy that\n * records the Drizzle chain (select/from/where/etc.) and replays it\n * once the DB driver finishes loading. Since callers always `await`\n * the final result, the proxy is transparent.\n */\n function getDb(): LibSQLDatabase<T> {\n if (_db) return _db;\n startInit();\n if (_db) return _db;\n\n return createLazyProxy(_dbReady!, []) as LibSQLDatabase<T>;\n }\n\n return getDb;\n}\n"]}
|
|
@@ -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
|