@useatlas/create 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +231 -0
- package/index.ts +829 -0
- package/package.json +38 -0
- package/templates/docker/.env.example +67 -0
- package/templates/docker/Dockerfile +52 -0
- package/templates/docker/bin/__tests__/benchmark.test.ts +598 -0
- package/templates/docker/bin/__tests__/duckdb-ingest.test.ts +171 -0
- package/templates/docker/bin/__tests__/eval.test.ts +434 -0
- package/templates/docker/bin/__tests__/matview-partition.test.ts +615 -0
- package/templates/docker/bin/__tests__/multi-source.test.ts +113 -0
- package/templates/docker/bin/__tests__/plugin-cli.test.ts +322 -0
- package/templates/docker/bin/__tests__/profiler-heuristics.test.ts +608 -0
- package/templates/docker/bin/__tests__/query.test.ts +240 -0
- package/templates/docker/bin/__tests__/schema-drift.test.ts +542 -0
- package/templates/docker/bin/__tests__/view-yaml-generation.test.ts +146 -0
- package/templates/docker/bin/atlas.ts +5044 -0
- package/templates/docker/bin/benchmark.ts +695 -0
- package/templates/docker/bin/enrich.ts +559 -0
- package/templates/docker/bin/eval.ts +770 -0
- package/templates/docker/bin/smoke.ts +438 -0
- package/templates/docker/data/.gitkeep +0 -0
- package/templates/docker/data/cybersec.sql +1961 -0
- package/templates/docker/data/demo-semantic/catalog.yml +40 -0
- package/templates/docker/data/demo-semantic/entities/accounts.yml +170 -0
- package/templates/docker/data/demo-semantic/entities/companies.yml +207 -0
- package/templates/docker/data/demo-semantic/entities/people.yml +145 -0
- package/templates/docker/data/demo-semantic/glossary.yml +22 -0
- package/templates/docker/data/demo-semantic/metrics/accounts.yml +38 -0
- package/templates/docker/data/demo-semantic/metrics/companies.yml +89 -0
- package/templates/docker/data/demo.sql +373 -0
- package/templates/docker/data/ecommerce.sql +1690 -0
- package/templates/docker/data/init-demo-db.sql +8 -0
- package/templates/docker/docker-compose.yml +34 -0
- package/templates/docker/docs/deploy.md +390 -0
- package/templates/docker/eslint.config.mjs +18 -0
- package/templates/docker/gitignore +5 -0
- package/templates/docker/next.config.ts +9 -0
- package/templates/docker/package.json +59 -0
- package/templates/docker/postcss.config.mjs +8 -0
- package/templates/docker/public/.gitkeep +0 -0
- package/templates/docker/public/favicon.svg +4 -0
- package/templates/docker/railway.json +13 -0
- package/templates/docker/render.yaml +34 -0
- package/templates/docker/semantic/catalog.yml +5 -0
- package/templates/docker/semantic/entities/.gitkeep +0 -0
- package/templates/docker/semantic/glossary.yml +6 -0
- package/templates/docker/semantic/metrics/.gitkeep +0 -0
- package/templates/docker/sidecar/Dockerfile +28 -0
- package/templates/docker/sidecar/railway.json +14 -0
- package/templates/docker/sidecar/server.ts +188 -0
- package/templates/docker/src/api/__tests__/actions.test.ts +683 -0
- package/templates/docker/src/api/__tests__/admin.test.ts +820 -0
- package/templates/docker/src/api/__tests__/auth.test.ts +165 -0
- package/templates/docker/src/api/__tests__/chat.test.ts +376 -0
- package/templates/docker/src/api/__tests__/conversations.test.ts +555 -0
- package/templates/docker/src/api/__tests__/cors.test.ts +135 -0
- package/templates/docker/src/api/__tests__/health-plugin.test.ts +169 -0
- package/templates/docker/src/api/__tests__/health.test.ts +261 -0
- package/templates/docker/src/api/__tests__/query.test.ts +891 -0
- package/templates/docker/src/api/__tests__/scheduled-tasks.test.ts +601 -0
- package/templates/docker/src/api/__tests__/slack.test.ts +847 -0
- package/templates/docker/src/api/index.ts +117 -0
- package/templates/docker/src/api/routes/actions.ts +274 -0
- package/templates/docker/src/api/routes/admin.ts +757 -0
- package/templates/docker/src/api/routes/auth.ts +48 -0
- package/templates/docker/src/api/routes/chat.ts +465 -0
- package/templates/docker/src/api/routes/conversations.ts +266 -0
- package/templates/docker/src/api/routes/health.ts +287 -0
- package/templates/docker/src/api/routes/openapi.ts +390 -0
- package/templates/docker/src/api/routes/query.ts +318 -0
- package/templates/docker/src/api/routes/scheduled-tasks.ts +467 -0
- package/templates/docker/src/api/routes/slack.ts +611 -0
- package/templates/docker/src/api/server.ts +226 -0
- package/templates/docker/src/app/api/[...route]/route.ts +33 -0
- package/templates/docker/src/app/error.tsx +24 -0
- package/templates/docker/src/app/globals.css +126 -0
- package/templates/docker/src/app/layout.tsx +19 -0
- package/templates/docker/src/app/page.tsx +14 -0
- package/templates/docker/src/global.d.ts +1 -0
- package/templates/docker/src/lib/__tests__/agent-cache.test.ts +437 -0
- package/templates/docker/src/lib/__tests__/agent-dialect.test.ts +114 -0
- package/templates/docker/src/lib/__tests__/agent-health-annotations.test.ts +164 -0
- package/templates/docker/src/lib/__tests__/agent-integration.test.ts +514 -0
- package/templates/docker/src/lib/__tests__/config-actions.test.ts +166 -0
- package/templates/docker/src/lib/__tests__/config.test.ts +1063 -0
- package/templates/docker/src/lib/__tests__/conversations.test.ts +589 -0
- package/templates/docker/src/lib/__tests__/errors.test.ts +256 -0
- package/templates/docker/src/lib/__tests__/logger.test.ts +200 -0
- package/templates/docker/src/lib/__tests__/providers.test.ts +99 -0
- package/templates/docker/src/lib/__tests__/rls.test.ts +435 -0
- package/templates/docker/src/lib/__tests__/scheduled-task-types.test.ts +124 -0
- package/templates/docker/src/lib/__tests__/scheduled-tasks.test.ts +550 -0
- package/templates/docker/src/lib/__tests__/semantic-index.test.ts +547 -0
- package/templates/docker/src/lib/__tests__/semantic-multisource.test.ts +544 -0
- package/templates/docker/src/lib/__tests__/semantic.test.ts +363 -0
- package/templates/docker/src/lib/__tests__/startup-actions.test.ts +452 -0
- package/templates/docker/src/lib/__tests__/startup.test.ts +465 -0
- package/templates/docker/src/lib/__tests__/tracing.test.ts +28 -0
- package/templates/docker/src/lib/action-types.ts +95 -0
- package/templates/docker/src/lib/agent-query.ts +178 -0
- package/templates/docker/src/lib/agent.ts +505 -0
- package/templates/docker/src/lib/api-url.ts +2 -0
- package/templates/docker/src/lib/auth/__tests__/audit.test.ts +418 -0
- package/templates/docker/src/lib/auth/__tests__/byot-integration.test.ts +222 -0
- package/templates/docker/src/lib/auth/__tests__/byot.test.ts +366 -0
- package/templates/docker/src/lib/auth/__tests__/detect.test.ts +190 -0
- package/templates/docker/src/lib/auth/__tests__/managed.test.ts +173 -0
- package/templates/docker/src/lib/auth/__tests__/middleware.test.ts +456 -0
- package/templates/docker/src/lib/auth/__tests__/migrate.test.ts +201 -0
- package/templates/docker/src/lib/auth/__tests__/permissions.test.ts +225 -0
- package/templates/docker/src/lib/auth/__tests__/server.test.ts +34 -0
- package/templates/docker/src/lib/auth/__tests__/simple-key.test.ts +176 -0
- package/templates/docker/src/lib/auth/__tests__/types.test.ts +44 -0
- package/templates/docker/src/lib/auth/audit.ts +89 -0
- package/templates/docker/src/lib/auth/byot.ts +158 -0
- package/templates/docker/src/lib/auth/client.ts +35 -0
- package/templates/docker/src/lib/auth/detect.ts +83 -0
- package/templates/docker/src/lib/auth/managed.ts +73 -0
- package/templates/docker/src/lib/auth/middleware.ts +208 -0
- package/templates/docker/src/lib/auth/migrate.ts +111 -0
- package/templates/docker/src/lib/auth/permissions.ts +156 -0
- package/templates/docker/src/lib/auth/server.ts +142 -0
- package/templates/docker/src/lib/auth/simple-key.ts +92 -0
- package/templates/docker/src/lib/auth/types.ts +49 -0
- package/templates/docker/src/lib/config.ts +704 -0
- package/templates/docker/src/lib/conversation-types.ts +29 -0
- package/templates/docker/src/lib/conversations.ts +270 -0
- package/templates/docker/src/lib/db/__tests__/connection.test.ts +69 -0
- package/templates/docker/src/lib/db/__tests__/duckdb.test.ts +141 -0
- package/templates/docker/src/lib/db/__tests__/internal.test.ts +387 -0
- package/templates/docker/src/lib/db/__tests__/registry-health.test.ts +207 -0
- package/templates/docker/src/lib/db/__tests__/registry-pool-limits.test.ts +156 -0
- package/templates/docker/src/lib/db/__tests__/registry.test.ts +595 -0
- package/templates/docker/src/lib/db/__tests__/salesforce.test.ts +339 -0
- package/templates/docker/src/lib/db/__tests__/snowflake.test.ts +217 -0
- package/templates/docker/src/lib/db/__tests__/source-rate-limit.test.ts +130 -0
- package/templates/docker/src/lib/db/connection.ts +753 -0
- package/templates/docker/src/lib/db/duckdb.ts +122 -0
- package/templates/docker/src/lib/db/internal.ts +273 -0
- package/templates/docker/src/lib/db/salesforce.ts +342 -0
- package/templates/docker/src/lib/db/source-rate-limit.ts +191 -0
- package/templates/docker/src/lib/errors.ts +154 -0
- package/templates/docker/src/lib/logger.ts +98 -0
- package/templates/docker/src/lib/plugins/__tests__/hooks-integration.test.ts +202 -0
- package/templates/docker/src/lib/plugins/__tests__/hooks.test.ts +529 -0
- package/templates/docker/src/lib/plugins/__tests__/migrate.test.ts +521 -0
- package/templates/docker/src/lib/plugins/__tests__/registry.test.ts +346 -0
- package/templates/docker/src/lib/plugins/__tests__/tools.test.ts +49 -0
- package/templates/docker/src/lib/plugins/__tests__/wiring.test.ts +585 -0
- package/templates/docker/src/lib/plugins/hooks.ts +162 -0
- package/templates/docker/src/lib/plugins/index.ts +9 -0
- package/templates/docker/src/lib/plugins/migrate.ts +309 -0
- package/templates/docker/src/lib/plugins/registry.ts +231 -0
- package/templates/docker/src/lib/plugins/tools.ts +39 -0
- package/templates/docker/src/lib/plugins/wiring.ts +291 -0
- package/templates/docker/src/lib/providers.ts +102 -0
- package/templates/docker/src/lib/rls.ts +321 -0
- package/templates/docker/src/lib/scheduled-task-types.ts +132 -0
- package/templates/docker/src/lib/scheduled-tasks.ts +475 -0
- package/templates/docker/src/lib/scheduler/__tests__/delivery.test.ts +192 -0
- package/templates/docker/src/lib/scheduler/__tests__/engine.test.ts +248 -0
- package/templates/docker/src/lib/scheduler/__tests__/format-email.test.ts +96 -0
- package/templates/docker/src/lib/scheduler/__tests__/format-slack.test.ts +78 -0
- package/templates/docker/src/lib/scheduler/__tests__/format-webhook.test.ts +78 -0
- package/templates/docker/src/lib/scheduler/delivery.ts +248 -0
- package/templates/docker/src/lib/scheduler/engine.ts +317 -0
- package/templates/docker/src/lib/scheduler/executor.ts +73 -0
- package/templates/docker/src/lib/scheduler/format-email.ts +109 -0
- package/templates/docker/src/lib/scheduler/format-slack.ts +35 -0
- package/templates/docker/src/lib/scheduler/format-webhook.ts +37 -0
- package/templates/docker/src/lib/scheduler/index.ts +7 -0
- package/templates/docker/src/lib/security.ts +11 -0
- package/templates/docker/src/lib/semantic-index.ts +503 -0
- package/templates/docker/src/lib/semantic.ts +387 -0
- package/templates/docker/src/lib/sidecar-types.ts +16 -0
- package/templates/docker/src/lib/slack/__tests__/api.test.ts +160 -0
- package/templates/docker/src/lib/slack/__tests__/format.test.ts +237 -0
- package/templates/docker/src/lib/slack/__tests__/store.test.ts +188 -0
- package/templates/docker/src/lib/slack/__tests__/threads.test.ts +112 -0
- package/templates/docker/src/lib/slack/__tests__/verify.test.ts +111 -0
- package/templates/docker/src/lib/slack/api.ts +102 -0
- package/templates/docker/src/lib/slack/format.ts +209 -0
- package/templates/docker/src/lib/slack/store.ts +107 -0
- package/templates/docker/src/lib/slack/threads.ts +64 -0
- package/templates/docker/src/lib/slack/verify.ts +71 -0
- package/templates/docker/src/lib/startup.ts +730 -0
- package/templates/docker/src/lib/tools/__tests__/action-permissions.test.ts +594 -0
- package/templates/docker/src/lib/tools/__tests__/custom-validation.test.ts +238 -0
- package/templates/docker/src/lib/tools/__tests__/explore-backend.test.ts +267 -0
- package/templates/docker/src/lib/tools/__tests__/explore-nsjail.test.ts +492 -0
- package/templates/docker/src/lib/tools/__tests__/explore-plugin.test.ts +374 -0
- package/templates/docker/src/lib/tools/__tests__/explore-sdk-compat.test.ts +82 -0
- package/templates/docker/src/lib/tools/__tests__/explore-sidecar.test.ts +208 -0
- package/templates/docker/src/lib/tools/__tests__/registry-actions.test.ts +144 -0
- package/templates/docker/src/lib/tools/__tests__/registry.test.ts +235 -0
- package/templates/docker/src/lib/tools/__tests__/salesforce-tool.test.ts +154 -0
- package/templates/docker/src/lib/tools/__tests__/soql-validation.test.ts +303 -0
- package/templates/docker/src/lib/tools/__tests__/sql-audit.test.ts +225 -0
- package/templates/docker/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +98 -0
- package/templates/docker/src/lib/tools/__tests__/sql-duckdb.test.ts +233 -0
- package/templates/docker/src/lib/tools/__tests__/sql-ratelimit.test.ts +225 -0
- package/templates/docker/src/lib/tools/__tests__/sql.test.ts +1012 -0
- package/templates/docker/src/lib/tools/actions/__tests__/audit.test.ts +211 -0
- package/templates/docker/src/lib/tools/actions/__tests__/email.test.ts +378 -0
- package/templates/docker/src/lib/tools/actions/__tests__/handler.test.ts +681 -0
- package/templates/docker/src/lib/tools/actions/__tests__/jira.test.ts +427 -0
- package/templates/docker/src/lib/tools/actions/audit.ts +47 -0
- package/templates/docker/src/lib/tools/actions/email.ts +191 -0
- package/templates/docker/src/lib/tools/actions/handler.ts +591 -0
- package/templates/docker/src/lib/tools/actions/index.ts +23 -0
- package/templates/docker/src/lib/tools/actions/jira.ts +220 -0
- package/templates/docker/src/lib/tools/explore-nsjail.ts +343 -0
- package/templates/docker/src/lib/tools/explore-sandbox.ts +264 -0
- package/templates/docker/src/lib/tools/explore-sidecar.ts +163 -0
- package/templates/docker/src/lib/tools/explore.ts +379 -0
- package/templates/docker/src/lib/tools/registry.ts +221 -0
- package/templates/docker/src/lib/tools/salesforce.ts +138 -0
- package/templates/docker/src/lib/tools/soql-validation.ts +172 -0
- package/templates/docker/src/lib/tools/sql.ts +680 -0
- package/templates/docker/src/lib/tracing.ts +40 -0
- package/templates/docker/src/lib/utils.ts +6 -0
- package/templates/docker/src/test-setup.ts +38 -0
- package/templates/docker/src/types/vercel-sandbox.d.ts +54 -0
- package/templates/docker/src/ui/components/actions/action-approval-card.tsx +295 -0
- package/templates/docker/src/ui/components/actions/action-status-badge.tsx +50 -0
- package/templates/docker/src/ui/components/admin/admin-layout.tsx +26 -0
- package/templates/docker/src/ui/components/admin/admin-sidebar.tsx +96 -0
- package/templates/docker/src/ui/components/admin/empty-state.tsx +24 -0
- package/templates/docker/src/ui/components/admin/entity-detail.tsx +233 -0
- package/templates/docker/src/ui/components/admin/entity-list.tsx +96 -0
- package/templates/docker/src/ui/components/admin/error-banner.tsx +22 -0
- package/templates/docker/src/ui/components/admin/feature-disabled.tsx +44 -0
- package/templates/docker/src/ui/components/admin/health-badge.tsx +30 -0
- package/templates/docker/src/ui/components/admin/loading-state.tsx +14 -0
- package/templates/docker/src/ui/components/admin/stat-card.tsx +32 -0
- package/templates/docker/src/ui/components/atlas-chat.tsx +370 -0
- package/templates/docker/src/ui/components/chart/chart-detection.ts +261 -0
- package/templates/docker/src/ui/components/chart/result-chart.tsx +375 -0
- package/templates/docker/src/ui/components/chat/api-key-bar.tsx +66 -0
- package/templates/docker/src/ui/components/chat/copy-button.tsx +25 -0
- package/templates/docker/src/ui/components/chat/data-table.tsx +102 -0
- package/templates/docker/src/ui/components/chat/error-banner.tsx +32 -0
- package/templates/docker/src/ui/components/chat/explore-card.tsx +41 -0
- package/templates/docker/src/ui/components/chat/loading-card.tsx +10 -0
- package/templates/docker/src/ui/components/chat/managed-auth-card.tsx +116 -0
- package/templates/docker/src/ui/components/chat/markdown.tsx +72 -0
- package/templates/docker/src/ui/components/chat/sql-block.tsx +30 -0
- package/templates/docker/src/ui/components/chat/sql-result-card.tsx +144 -0
- package/templates/docker/src/ui/components/chat/starter-prompts.ts +6 -0
- package/templates/docker/src/ui/components/chat/tool-part.tsx +40 -0
- package/templates/docker/src/ui/components/chat/typing-indicator.tsx +19 -0
- package/templates/docker/src/ui/components/conversations/conversation-item.tsx +120 -0
- package/templates/docker/src/ui/components/conversations/conversation-list.tsx +66 -0
- package/templates/docker/src/ui/components/conversations/conversation-sidebar.tsx +78 -0
- package/templates/docker/src/ui/components/conversations/delete-confirmation.tsx +27 -0
- package/templates/docker/src/ui/context.tsx +78 -0
- package/templates/docker/src/ui/hooks/use-admin-fetch.ts +104 -0
- package/templates/docker/src/ui/hooks/use-conversations.ts +184 -0
- package/templates/docker/src/ui/hooks/use-dark-mode.ts +17 -0
- package/templates/docker/src/ui/lib/action-types.ts +63 -0
- package/templates/docker/src/ui/lib/helpers.ts +104 -0
- package/templates/docker/src/ui/lib/types.ts +145 -0
- package/templates/docker/tsconfig.json +41 -0
- package/templates/docker/vercel.json +3 -0
- package/templates/nextjs-standalone/.env.example +68 -0
- package/templates/nextjs-standalone/bin/__tests__/benchmark.test.ts +598 -0
- package/templates/nextjs-standalone/bin/__tests__/duckdb-ingest.test.ts +171 -0
- package/templates/nextjs-standalone/bin/__tests__/eval.test.ts +434 -0
- package/templates/nextjs-standalone/bin/__tests__/matview-partition.test.ts +615 -0
- package/templates/nextjs-standalone/bin/__tests__/multi-source.test.ts +113 -0
- package/templates/nextjs-standalone/bin/__tests__/plugin-cli.test.ts +322 -0
- package/templates/nextjs-standalone/bin/__tests__/profiler-heuristics.test.ts +608 -0
- package/templates/nextjs-standalone/bin/__tests__/query.test.ts +240 -0
- package/templates/nextjs-standalone/bin/__tests__/schema-drift.test.ts +542 -0
- package/templates/nextjs-standalone/bin/__tests__/view-yaml-generation.test.ts +146 -0
- package/templates/nextjs-standalone/bin/atlas.ts +5044 -0
- package/templates/nextjs-standalone/bin/benchmark.ts +695 -0
- package/templates/nextjs-standalone/bin/enrich.ts +559 -0
- package/templates/nextjs-standalone/bin/eval.ts +770 -0
- package/templates/nextjs-standalone/bin/smoke.ts +438 -0
- package/templates/nextjs-standalone/data/.gitkeep +0 -0
- package/templates/nextjs-standalone/data/cybersec.sql +1961 -0
- package/templates/nextjs-standalone/data/demo-semantic/catalog.yml +40 -0
- package/templates/nextjs-standalone/data/demo-semantic/entities/accounts.yml +170 -0
- package/templates/nextjs-standalone/data/demo-semantic/entities/companies.yml +207 -0
- package/templates/nextjs-standalone/data/demo-semantic/entities/people.yml +145 -0
- package/templates/nextjs-standalone/data/demo-semantic/glossary.yml +22 -0
- package/templates/nextjs-standalone/data/demo-semantic/metrics/accounts.yml +38 -0
- package/templates/nextjs-standalone/data/demo-semantic/metrics/companies.yml +89 -0
- package/templates/nextjs-standalone/data/demo.sql +373 -0
- package/templates/nextjs-standalone/data/ecommerce.sql +1690 -0
- package/templates/nextjs-standalone/data/init-demo-db.sql +8 -0
- package/templates/nextjs-standalone/docs/deploy.md +390 -0
- package/templates/nextjs-standalone/eslint.config.mjs +18 -0
- package/templates/nextjs-standalone/gitignore +5 -0
- package/templates/nextjs-standalone/next.config.ts +10 -0
- package/templates/nextjs-standalone/package.json +63 -0
- package/templates/nextjs-standalone/postcss.config.mjs +8 -0
- package/templates/nextjs-standalone/semantic/catalog.yml +5 -0
- package/templates/nextjs-standalone/semantic/entities/.gitkeep +0 -0
- package/templates/nextjs-standalone/semantic/glossary.yml +6 -0
- package/templates/nextjs-standalone/semantic/metrics/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/api/__tests__/actions.test.ts +683 -0
- package/templates/nextjs-standalone/src/api/__tests__/admin.test.ts +820 -0
- package/templates/nextjs-standalone/src/api/__tests__/auth.test.ts +165 -0
- package/templates/nextjs-standalone/src/api/__tests__/chat.test.ts +376 -0
- package/templates/nextjs-standalone/src/api/__tests__/conversations.test.ts +555 -0
- package/templates/nextjs-standalone/src/api/__tests__/cors.test.ts +135 -0
- package/templates/nextjs-standalone/src/api/__tests__/health-plugin.test.ts +169 -0
- package/templates/nextjs-standalone/src/api/__tests__/health.test.ts +261 -0
- package/templates/nextjs-standalone/src/api/__tests__/query.test.ts +891 -0
- package/templates/nextjs-standalone/src/api/__tests__/scheduled-tasks.test.ts +601 -0
- package/templates/nextjs-standalone/src/api/__tests__/slack.test.ts +847 -0
- package/templates/nextjs-standalone/src/api/index.ts +117 -0
- package/templates/nextjs-standalone/src/api/routes/actions.ts +274 -0
- package/templates/nextjs-standalone/src/api/routes/admin.ts +757 -0
- package/templates/nextjs-standalone/src/api/routes/auth.ts +48 -0
- package/templates/nextjs-standalone/src/api/routes/chat.ts +465 -0
- package/templates/nextjs-standalone/src/api/routes/conversations.ts +266 -0
- package/templates/nextjs-standalone/src/api/routes/health.ts +287 -0
- package/templates/nextjs-standalone/src/api/routes/openapi.ts +390 -0
- package/templates/nextjs-standalone/src/api/routes/query.ts +318 -0
- package/templates/nextjs-standalone/src/api/routes/scheduled-tasks.ts +467 -0
- package/templates/nextjs-standalone/src/api/routes/slack.ts +611 -0
- package/templates/nextjs-standalone/src/api/server.ts +226 -0
- package/templates/nextjs-standalone/src/app/api/[...route]/route.ts +33 -0
- package/templates/nextjs-standalone/src/app/error.tsx +24 -0
- package/templates/nextjs-standalone/src/app/global-error.tsx +68 -0
- package/templates/nextjs-standalone/src/app/globals.css +126 -0
- package/templates/nextjs-standalone/src/app/layout.tsx +19 -0
- package/templates/nextjs-standalone/src/app/page.tsx +14 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-cache.test.ts +437 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-dialect.test.ts +114 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-health-annotations.test.ts +164 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-integration.test.ts +514 -0
- package/templates/nextjs-standalone/src/lib/__tests__/config-actions.test.ts +166 -0
- package/templates/nextjs-standalone/src/lib/__tests__/config.test.ts +1063 -0
- package/templates/nextjs-standalone/src/lib/__tests__/conversations.test.ts +589 -0
- package/templates/nextjs-standalone/src/lib/__tests__/errors.test.ts +256 -0
- package/templates/nextjs-standalone/src/lib/__tests__/logger.test.ts +200 -0
- package/templates/nextjs-standalone/src/lib/__tests__/providers.test.ts +99 -0
- package/templates/nextjs-standalone/src/lib/__tests__/rls.test.ts +435 -0
- package/templates/nextjs-standalone/src/lib/__tests__/scheduled-task-types.test.ts +124 -0
- package/templates/nextjs-standalone/src/lib/__tests__/scheduled-tasks.test.ts +550 -0
- package/templates/nextjs-standalone/src/lib/__tests__/semantic-index.test.ts +547 -0
- package/templates/nextjs-standalone/src/lib/__tests__/semantic-multisource.test.ts +544 -0
- package/templates/nextjs-standalone/src/lib/__tests__/semantic.test.ts +363 -0
- package/templates/nextjs-standalone/src/lib/__tests__/startup-actions.test.ts +452 -0
- package/templates/nextjs-standalone/src/lib/__tests__/startup.test.ts +465 -0
- package/templates/nextjs-standalone/src/lib/__tests__/tracing.test.ts +28 -0
- package/templates/nextjs-standalone/src/lib/action-types.ts +95 -0
- package/templates/nextjs-standalone/src/lib/agent-query.ts +178 -0
- package/templates/nextjs-standalone/src/lib/agent.ts +505 -0
- package/templates/nextjs-standalone/src/lib/api-url.ts +3 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/audit.test.ts +418 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/byot-integration.test.ts +222 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/byot.test.ts +366 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/detect.test.ts +190 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/managed.test.ts +173 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/middleware.test.ts +456 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/migrate.test.ts +201 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/permissions.test.ts +225 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/server.test.ts +34 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/simple-key.test.ts +176 -0
- package/templates/nextjs-standalone/src/lib/auth/__tests__/types.test.ts +44 -0
- package/templates/nextjs-standalone/src/lib/auth/audit.ts +89 -0
- package/templates/nextjs-standalone/src/lib/auth/byot.ts +158 -0
- package/templates/nextjs-standalone/src/lib/auth/client.ts +23 -0
- package/templates/nextjs-standalone/src/lib/auth/detect.ts +83 -0
- package/templates/nextjs-standalone/src/lib/auth/managed.ts +73 -0
- package/templates/nextjs-standalone/src/lib/auth/middleware.ts +208 -0
- package/templates/nextjs-standalone/src/lib/auth/migrate.ts +111 -0
- package/templates/nextjs-standalone/src/lib/auth/permissions.ts +156 -0
- package/templates/nextjs-standalone/src/lib/auth/server.ts +142 -0
- package/templates/nextjs-standalone/src/lib/auth/simple-key.ts +92 -0
- package/templates/nextjs-standalone/src/lib/auth/types.ts +49 -0
- package/templates/nextjs-standalone/src/lib/config.ts +704 -0
- package/templates/nextjs-standalone/src/lib/conversation-types.ts +29 -0
- package/templates/nextjs-standalone/src/lib/conversations.ts +270 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/connection.test.ts +69 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/duckdb.test.ts +141 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/internal.test.ts +387 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry-health.test.ts +207 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry-pool-limits.test.ts +156 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry.test.ts +595 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/salesforce.test.ts +339 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/snowflake.test.ts +217 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/source-rate-limit.test.ts +130 -0
- package/templates/nextjs-standalone/src/lib/db/connection.ts +753 -0
- package/templates/nextjs-standalone/src/lib/db/duckdb.ts +122 -0
- package/templates/nextjs-standalone/src/lib/db/internal.ts +273 -0
- package/templates/nextjs-standalone/src/lib/db/salesforce.ts +342 -0
- package/templates/nextjs-standalone/src/lib/db/source-rate-limit.ts +191 -0
- package/templates/nextjs-standalone/src/lib/errors.ts +154 -0
- package/templates/nextjs-standalone/src/lib/logger.ts +98 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks-integration.test.ts +202 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks.test.ts +529 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/migrate.test.ts +521 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/registry.test.ts +346 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/tools.test.ts +49 -0
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/wiring.test.ts +585 -0
- package/templates/nextjs-standalone/src/lib/plugins/hooks.ts +162 -0
- package/templates/nextjs-standalone/src/lib/plugins/index.ts +9 -0
- package/templates/nextjs-standalone/src/lib/plugins/migrate.ts +309 -0
- package/templates/nextjs-standalone/src/lib/plugins/registry.ts +231 -0
- package/templates/nextjs-standalone/src/lib/plugins/tools.ts +39 -0
- package/templates/nextjs-standalone/src/lib/plugins/wiring.ts +291 -0
- package/templates/nextjs-standalone/src/lib/providers.ts +102 -0
- package/templates/nextjs-standalone/src/lib/rls.ts +321 -0
- package/templates/nextjs-standalone/src/lib/scheduled-task-types.ts +132 -0
- package/templates/nextjs-standalone/src/lib/scheduled-tasks.ts +475 -0
- package/templates/nextjs-standalone/src/lib/scheduler/__tests__/delivery.test.ts +192 -0
- package/templates/nextjs-standalone/src/lib/scheduler/__tests__/engine.test.ts +248 -0
- package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-email.test.ts +96 -0
- package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-slack.test.ts +78 -0
- package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-webhook.test.ts +78 -0
- package/templates/nextjs-standalone/src/lib/scheduler/delivery.ts +248 -0
- package/templates/nextjs-standalone/src/lib/scheduler/engine.ts +317 -0
- package/templates/nextjs-standalone/src/lib/scheduler/executor.ts +73 -0
- package/templates/nextjs-standalone/src/lib/scheduler/format-email.ts +109 -0
- package/templates/nextjs-standalone/src/lib/scheduler/format-slack.ts +35 -0
- package/templates/nextjs-standalone/src/lib/scheduler/format-webhook.ts +37 -0
- package/templates/nextjs-standalone/src/lib/scheduler/index.ts +7 -0
- package/templates/nextjs-standalone/src/lib/security.ts +11 -0
- package/templates/nextjs-standalone/src/lib/semantic-index.ts +503 -0
- package/templates/nextjs-standalone/src/lib/semantic.ts +387 -0
- package/templates/nextjs-standalone/src/lib/sidecar-types.ts +16 -0
- package/templates/nextjs-standalone/src/lib/slack/__tests__/api.test.ts +160 -0
- package/templates/nextjs-standalone/src/lib/slack/__tests__/format.test.ts +237 -0
- package/templates/nextjs-standalone/src/lib/slack/__tests__/store.test.ts +188 -0
- package/templates/nextjs-standalone/src/lib/slack/__tests__/threads.test.ts +112 -0
- package/templates/nextjs-standalone/src/lib/slack/__tests__/verify.test.ts +111 -0
- package/templates/nextjs-standalone/src/lib/slack/api.ts +102 -0
- package/templates/nextjs-standalone/src/lib/slack/format.ts +209 -0
- package/templates/nextjs-standalone/src/lib/slack/store.ts +107 -0
- package/templates/nextjs-standalone/src/lib/slack/threads.ts +64 -0
- package/templates/nextjs-standalone/src/lib/slack/verify.ts +71 -0
- package/templates/nextjs-standalone/src/lib/startup.ts +730 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/action-permissions.test.ts +594 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/custom-validation.test.ts +238 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-backend.test.ts +267 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-nsjail.test.ts +492 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-plugin.test.ts +374 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sdk-compat.test.ts +82 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sidecar.test.ts +208 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/registry-actions.test.ts +144 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/registry.test.ts +235 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/salesforce-tool.test.ts +154 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/soql-validation.test.ts +303 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-audit.test.ts +225 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +98 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-duckdb.test.ts +233 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-ratelimit.test.ts +225 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql.test.ts +1012 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/audit.test.ts +211 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/email.test.ts +378 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/handler.test.ts +681 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/jira.test.ts +427 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/audit.ts +47 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/email.ts +191 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/handler.ts +591 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/index.ts +23 -0
- package/templates/nextjs-standalone/src/lib/tools/actions/jira.ts +220 -0
- package/templates/nextjs-standalone/src/lib/tools/explore-nsjail.ts +343 -0
- package/templates/nextjs-standalone/src/lib/tools/explore-sandbox.ts +264 -0
- package/templates/nextjs-standalone/src/lib/tools/explore-sidecar.ts +163 -0
- package/templates/nextjs-standalone/src/lib/tools/explore.ts +379 -0
- package/templates/nextjs-standalone/src/lib/tools/registry.ts +221 -0
- package/templates/nextjs-standalone/src/lib/tools/salesforce.ts +138 -0
- package/templates/nextjs-standalone/src/lib/tools/soql-validation.ts +172 -0
- package/templates/nextjs-standalone/src/lib/tools/sql.ts +680 -0
- package/templates/nextjs-standalone/src/lib/tracing.ts +40 -0
- package/templates/nextjs-standalone/src/lib/utils.ts +6 -0
- package/templates/nextjs-standalone/src/test-setup.ts +38 -0
- package/templates/nextjs-standalone/src/ui/components/actions/action-approval-card.tsx +295 -0
- package/templates/nextjs-standalone/src/ui/components/actions/action-status-badge.tsx +50 -0
- package/templates/nextjs-standalone/src/ui/components/admin/admin-layout.tsx +26 -0
- package/templates/nextjs-standalone/src/ui/components/admin/admin-sidebar.tsx +96 -0
- package/templates/nextjs-standalone/src/ui/components/admin/empty-state.tsx +24 -0
- package/templates/nextjs-standalone/src/ui/components/admin/entity-detail.tsx +233 -0
- package/templates/nextjs-standalone/src/ui/components/admin/entity-list.tsx +96 -0
- package/templates/nextjs-standalone/src/ui/components/admin/error-banner.tsx +22 -0
- package/templates/nextjs-standalone/src/ui/components/admin/feature-disabled.tsx +44 -0
- package/templates/nextjs-standalone/src/ui/components/admin/health-badge.tsx +30 -0
- package/templates/nextjs-standalone/src/ui/components/admin/loading-state.tsx +14 -0
- package/templates/nextjs-standalone/src/ui/components/admin/stat-card.tsx +32 -0
- package/templates/nextjs-standalone/src/ui/components/atlas-chat.tsx +370 -0
- package/templates/nextjs-standalone/src/ui/components/chart/chart-detection.ts +261 -0
- package/templates/nextjs-standalone/src/ui/components/chart/result-chart.tsx +375 -0
- package/templates/nextjs-standalone/src/ui/components/chat/api-key-bar.tsx +66 -0
- package/templates/nextjs-standalone/src/ui/components/chat/copy-button.tsx +25 -0
- package/templates/nextjs-standalone/src/ui/components/chat/data-table.tsx +102 -0
- package/templates/nextjs-standalone/src/ui/components/chat/error-banner.tsx +32 -0
- package/templates/nextjs-standalone/src/ui/components/chat/explore-card.tsx +41 -0
- package/templates/nextjs-standalone/src/ui/components/chat/loading-card.tsx +10 -0
- package/templates/nextjs-standalone/src/ui/components/chat/managed-auth-card.tsx +116 -0
- package/templates/nextjs-standalone/src/ui/components/chat/markdown.tsx +72 -0
- package/templates/nextjs-standalone/src/ui/components/chat/sql-block.tsx +30 -0
- package/templates/nextjs-standalone/src/ui/components/chat/sql-result-card.tsx +144 -0
- package/templates/nextjs-standalone/src/ui/components/chat/starter-prompts.ts +6 -0
- package/templates/nextjs-standalone/src/ui/components/chat/tool-part.tsx +40 -0
- package/templates/nextjs-standalone/src/ui/components/chat/typing-indicator.tsx +19 -0
- package/templates/nextjs-standalone/src/ui/components/conversations/conversation-item.tsx +120 -0
- package/templates/nextjs-standalone/src/ui/components/conversations/conversation-list.tsx +66 -0
- package/templates/nextjs-standalone/src/ui/components/conversations/conversation-sidebar.tsx +78 -0
- package/templates/nextjs-standalone/src/ui/components/conversations/delete-confirmation.tsx +27 -0
- package/templates/nextjs-standalone/src/ui/context.tsx +78 -0
- package/templates/nextjs-standalone/src/ui/hooks/use-admin-fetch.ts +104 -0
- package/templates/nextjs-standalone/src/ui/hooks/use-conversations.ts +184 -0
- package/templates/nextjs-standalone/src/ui/hooks/use-dark-mode.ts +17 -0
- package/templates/nextjs-standalone/src/ui/lib/action-types.ts +63 -0
- package/templates/nextjs-standalone/src/ui/lib/helpers.ts +104 -0
- package/templates/nextjs-standalone/src/ui/lib/types.ts +145 -0
- package/templates/nextjs-standalone/tsconfig.json +32 -0
- package/templates/nextjs-standalone/vercel.json +4 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DuckDB adapter implementing the DBConnection interface.
|
|
3
|
+
*
|
|
4
|
+
* Uses @duckdb/node-api (the "Neo" API) for in-process analytical queries
|
|
5
|
+
* on CSV, Parquet, and persistent DuckDB database files. DuckDB runs fully
|
|
6
|
+
* in-process — no external server required.
|
|
7
|
+
*
|
|
8
|
+
* Connection URL formats:
|
|
9
|
+
* - `duckdb://path/to/file.duckdb` — persistent database file
|
|
10
|
+
* - `duckdb://:memory:` — in-memory database
|
|
11
|
+
* - `duckdb://` — in-memory (shorthand)
|
|
12
|
+
*
|
|
13
|
+
* Read-only enforcement: the database is opened with `access_mode: 'READ_ONLY'`
|
|
14
|
+
* when the file already exists. For newly-created databases (e.g. during CLI
|
|
15
|
+
* ingestion), the caller is responsible for opening in read-write mode first,
|
|
16
|
+
* then re-opening as read-only for runtime use.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type { DBConnection, QueryResult } from "./connection";
|
|
20
|
+
import { createLogger } from "@atlas/api/lib/logger";
|
|
21
|
+
|
|
22
|
+
const log = createLogger("duckdb");
|
|
23
|
+
|
|
24
|
+
export interface DuckDBConfig {
|
|
25
|
+
/** Path to the .duckdb file, or ":memory:" for in-memory. */
|
|
26
|
+
path: string;
|
|
27
|
+
/** Open in read-only mode (default: true for runtime). */
|
|
28
|
+
readOnly?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Parse a duckdb:// URL into a DuckDBConfig.
|
|
33
|
+
*
|
|
34
|
+
* - `duckdb://` or `duckdb://:memory:` → in-memory
|
|
35
|
+
* - `duckdb:///absolute/path.duckdb` → absolute path
|
|
36
|
+
* - `duckdb://relative/path.duckdb` → relative path
|
|
37
|
+
*/
|
|
38
|
+
export function parseDuckDBUrl(url: string): DuckDBConfig {
|
|
39
|
+
if (!url.startsWith("duckdb://")) {
|
|
40
|
+
throw new Error(`Invalid DuckDB URL: expected duckdb:// scheme, got "${url.slice(0, 20)}..."`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const rest = url.slice("duckdb://".length);
|
|
44
|
+
|
|
45
|
+
if (!rest || rest === ":memory:") {
|
|
46
|
+
return { path: ":memory:" };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// duckdb:///absolute/path → /absolute/path
|
|
50
|
+
// duckdb://relative/path → relative/path
|
|
51
|
+
return { path: rest };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function createDuckDBConnection(config: DuckDBConfig): DBConnection {
|
|
55
|
+
// Lazy-load to avoid requiring @duckdb/node-api when not needed
|
|
56
|
+
let instancePromise: Promise<{ instance: unknown; connection: unknown }> | null = null;
|
|
57
|
+
|
|
58
|
+
async function getConnection() {
|
|
59
|
+
if (!instancePromise) {
|
|
60
|
+
instancePromise = (async () => {
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
62
|
+
const { DuckDBInstance } = require("@duckdb/node-api");
|
|
63
|
+
|
|
64
|
+
const options: Record<string, string> = {};
|
|
65
|
+
if (config.readOnly !== false && config.path !== ":memory:") {
|
|
66
|
+
options.access_mode = "READ_ONLY";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const instance = await DuckDBInstance.create(config.path, options);
|
|
70
|
+
const connection = await instance.connect();
|
|
71
|
+
return { instance, connection };
|
|
72
|
+
})();
|
|
73
|
+
// Allow retry on transient failures — don't cache rejected promises
|
|
74
|
+
instancePromise.catch(() => { instancePromise = null; });
|
|
75
|
+
}
|
|
76
|
+
return instancePromise;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
async query(sql: string, timeoutMs?: number): Promise<QueryResult> {
|
|
81
|
+
const { connection } = await getConnection();
|
|
82
|
+
|
|
83
|
+
const runQuery = async () => {
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
|
+
const reader = await (connection as any).runAndReadAll(sql);
|
|
86
|
+
const columns: string[] = reader.columnNames();
|
|
87
|
+
const rowObjects: Record<string, unknown>[] = reader.getRowObjects();
|
|
88
|
+
return { columns, rows: rowObjects };
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
if (timeoutMs && timeoutMs > 0) {
|
|
92
|
+
const timeout = new Promise<never>((_, reject) =>
|
|
93
|
+
setTimeout(() => reject(new Error(
|
|
94
|
+
`DuckDB query timed out after ${timeoutMs}ms`
|
|
95
|
+
)), timeoutMs)
|
|
96
|
+
);
|
|
97
|
+
return Promise.race([runQuery(), timeout]);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return runQuery();
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
async close(): Promise<void> {
|
|
104
|
+
if (instancePromise) {
|
|
105
|
+
try {
|
|
106
|
+
const { connection, instance } = await instancePromise;
|
|
107
|
+
// DuckDB Neo API uses synchronous cleanup methods
|
|
108
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
109
|
+
(connection as any).disconnectSync();
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
111
|
+
(instance as any).closeSync();
|
|
112
|
+
} catch (err) {
|
|
113
|
+
log.warn(
|
|
114
|
+
{ err: err instanceof Error ? err.message : String(err) },
|
|
115
|
+
"Failed to close DuckDB connection"
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
instancePromise = null;
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atlas internal database connection.
|
|
3
|
+
*
|
|
4
|
+
* Read-write Postgres connection for Atlas's own state (auth, audit, settings).
|
|
5
|
+
* Completely separate from the analytics datasource in connection.ts.
|
|
6
|
+
* Configured via DATABASE_URL.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createLogger } from "@atlas/api/lib/logger";
|
|
10
|
+
|
|
11
|
+
const log = createLogger("internal-db");
|
|
12
|
+
|
|
13
|
+
/** Typed interface for the internal pg.Pool — avoids importing pg at module level. */
|
|
14
|
+
export interface InternalPool {
|
|
15
|
+
query(sql: string, params?: unknown[]): Promise<{ rows: Record<string, unknown>[] }>;
|
|
16
|
+
end(): Promise<void>;
|
|
17
|
+
on(event: "error", listener: (err: Error) => void): void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let _pool: InternalPool | null = null;
|
|
21
|
+
|
|
22
|
+
/** Returns true if DATABASE_URL is configured. */
|
|
23
|
+
export function hasInternalDB(): boolean {
|
|
24
|
+
return !!process.env.DATABASE_URL;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Returns the singleton pg.Pool for the internal database. Throws if DATABASE_URL is not set. */
|
|
28
|
+
export function getInternalDB(): InternalPool {
|
|
29
|
+
if (!_pool) {
|
|
30
|
+
if (!process.env.DATABASE_URL) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
"DATABASE_URL is not set. Atlas internal database requires a PostgreSQL connection string."
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
36
|
+
const { Pool } = require("pg");
|
|
37
|
+
_pool = new Pool({
|
|
38
|
+
connectionString: process.env.DATABASE_URL,
|
|
39
|
+
max: 5,
|
|
40
|
+
idleTimeoutMillis: 30000,
|
|
41
|
+
}) as InternalPool;
|
|
42
|
+
_pool.on("error", (err: unknown) => {
|
|
43
|
+
log.error(
|
|
44
|
+
{ err: err instanceof Error ? err : new Error(String(err)) },
|
|
45
|
+
"Internal DB pool idle client error",
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return _pool;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Gracefully close the internal DB pool. */
|
|
53
|
+
export async function closeInternalDB(): Promise<void> {
|
|
54
|
+
if (_pool) {
|
|
55
|
+
const pool = _pool;
|
|
56
|
+
_pool = null;
|
|
57
|
+
try {
|
|
58
|
+
await pool.end();
|
|
59
|
+
} catch (err: unknown) {
|
|
60
|
+
log.warn(
|
|
61
|
+
{ err: err instanceof Error ? err.message : String(err) },
|
|
62
|
+
"Error closing internal DB pool",
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Reset singleton for testing. Optionally inject a mock pool. */
|
|
69
|
+
export function _resetPool(mockPool?: InternalPool | null): void {
|
|
70
|
+
_pool = mockPool ?? null;
|
|
71
|
+
_consecutiveFailures = 0;
|
|
72
|
+
_circuitOpen = false;
|
|
73
|
+
_droppedCount = 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Parameterized query that returns typed rows. */
|
|
77
|
+
export async function internalQuery<T extends Record<string, unknown>>(
|
|
78
|
+
sql: string,
|
|
79
|
+
params?: unknown[],
|
|
80
|
+
): Promise<T[]> {
|
|
81
|
+
const pool = getInternalDB();
|
|
82
|
+
const result = await pool.query(sql, params);
|
|
83
|
+
return result.rows as T[];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let _consecutiveFailures = 0;
|
|
87
|
+
const MAX_CONSECUTIVE_FAILURES = 5;
|
|
88
|
+
let _circuitOpen = false;
|
|
89
|
+
let _droppedCount = 0;
|
|
90
|
+
|
|
91
|
+
/** Fire-and-forget query — async errors are logged, never thrown.
|
|
92
|
+
* After 5 consecutive failures, a circuit breaker trips and silently
|
|
93
|
+
* drops all calls for 60s before retrying. Throws synchronously if
|
|
94
|
+
* DATABASE_URL is not set (callers should check hasInternalDB() first). */
|
|
95
|
+
export function internalExecute(sql: string, params?: unknown[]): void {
|
|
96
|
+
if (_circuitOpen) {
|
|
97
|
+
_droppedCount++;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const pool = getInternalDB();
|
|
101
|
+
void pool.query(sql, params)
|
|
102
|
+
.then(() => { _consecutiveFailures = 0; })
|
|
103
|
+
.catch((err: unknown) => {
|
|
104
|
+
_consecutiveFailures++;
|
|
105
|
+
if (_consecutiveFailures >= MAX_CONSECUTIVE_FAILURES && !_circuitOpen) {
|
|
106
|
+
_circuitOpen = true;
|
|
107
|
+
log.error("Internal DB circuit breaker open — fire-and-forget writes disabled until recovery");
|
|
108
|
+
// Try to recover every 60s
|
|
109
|
+
setTimeout(() => {
|
|
110
|
+
const dropped = _droppedCount;
|
|
111
|
+
_circuitOpen = false;
|
|
112
|
+
_consecutiveFailures = 0;
|
|
113
|
+
_droppedCount = 0;
|
|
114
|
+
log.info({ droppedCount: dropped }, "Internal DB circuit breaker recovered — fire-and-forget writes resumed");
|
|
115
|
+
}, 60_000).unref();
|
|
116
|
+
}
|
|
117
|
+
if (!_circuitOpen) {
|
|
118
|
+
log.error(
|
|
119
|
+
{
|
|
120
|
+
err: err instanceof Error ? err.message : String(err),
|
|
121
|
+
sql: sql.slice(0, 200),
|
|
122
|
+
paramCount: params?.length ?? 0,
|
|
123
|
+
},
|
|
124
|
+
"Internal DB fire-and-forget write failed — row lost",
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Reset circuit breaker state. For testing only. */
|
|
131
|
+
export function _resetCircuitBreaker(): void {
|
|
132
|
+
_consecutiveFailures = 0;
|
|
133
|
+
_circuitOpen = false;
|
|
134
|
+
_droppedCount = 0;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Idempotent migration: creates audit_log, conversations, and messages tables. */
|
|
138
|
+
export async function migrateInternalDB(): Promise<void> {
|
|
139
|
+
const pool = getInternalDB();
|
|
140
|
+
await pool.query(`
|
|
141
|
+
CREATE TABLE IF NOT EXISTS audit_log (
|
|
142
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
143
|
+
timestamp TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
144
|
+
user_id TEXT,
|
|
145
|
+
user_label TEXT,
|
|
146
|
+
auth_mode TEXT NOT NULL,
|
|
147
|
+
sql TEXT NOT NULL,
|
|
148
|
+
duration_ms INTEGER NOT NULL,
|
|
149
|
+
row_count INTEGER,
|
|
150
|
+
success BOOLEAN NOT NULL,
|
|
151
|
+
error TEXT
|
|
152
|
+
);
|
|
153
|
+
`);
|
|
154
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_audit_log_timestamp ON audit_log(timestamp);`);
|
|
155
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_audit_log_user_id ON audit_log(user_id);`);
|
|
156
|
+
await pool.query(`
|
|
157
|
+
CREATE TABLE IF NOT EXISTS conversations (
|
|
158
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
159
|
+
user_id TEXT,
|
|
160
|
+
title TEXT,
|
|
161
|
+
surface TEXT DEFAULT 'web',
|
|
162
|
+
connection_id TEXT,
|
|
163
|
+
created_at TIMESTAMPTZ DEFAULT now(),
|
|
164
|
+
updated_at TIMESTAMPTZ DEFAULT now()
|
|
165
|
+
);
|
|
166
|
+
`);
|
|
167
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_conversations_user ON conversations(user_id);`);
|
|
168
|
+
await pool.query(`
|
|
169
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
170
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
171
|
+
conversation_id UUID REFERENCES conversations(id) ON DELETE CASCADE,
|
|
172
|
+
role TEXT NOT NULL,
|
|
173
|
+
content JSONB NOT NULL,
|
|
174
|
+
created_at TIMESTAMPTZ DEFAULT now()
|
|
175
|
+
);
|
|
176
|
+
`);
|
|
177
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_messages_conversation ON messages(conversation_id);`);
|
|
178
|
+
|
|
179
|
+
// Slack integration tables
|
|
180
|
+
await pool.query(`
|
|
181
|
+
CREATE TABLE IF NOT EXISTS slack_installations (
|
|
182
|
+
team_id TEXT PRIMARY KEY,
|
|
183
|
+
bot_token TEXT NOT NULL,
|
|
184
|
+
installed_at TIMESTAMPTZ DEFAULT now()
|
|
185
|
+
);
|
|
186
|
+
`);
|
|
187
|
+
await pool.query(`
|
|
188
|
+
CREATE TABLE IF NOT EXISTS slack_threads (
|
|
189
|
+
thread_ts TEXT NOT NULL,
|
|
190
|
+
channel_id TEXT NOT NULL,
|
|
191
|
+
conversation_id UUID NOT NULL,
|
|
192
|
+
PRIMARY KEY (thread_ts, channel_id)
|
|
193
|
+
);
|
|
194
|
+
`);
|
|
195
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_slack_threads_conversation ON slack_threads(conversation_id);`);
|
|
196
|
+
|
|
197
|
+
// Action framework tables
|
|
198
|
+
await pool.query(`
|
|
199
|
+
CREATE TABLE IF NOT EXISTS action_log (
|
|
200
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
201
|
+
requested_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
202
|
+
resolved_at TIMESTAMPTZ,
|
|
203
|
+
executed_at TIMESTAMPTZ,
|
|
204
|
+
requested_by TEXT,
|
|
205
|
+
approved_by TEXT,
|
|
206
|
+
auth_mode TEXT NOT NULL,
|
|
207
|
+
action_type TEXT NOT NULL,
|
|
208
|
+
target TEXT NOT NULL,
|
|
209
|
+
summary TEXT NOT NULL,
|
|
210
|
+
payload JSONB NOT NULL,
|
|
211
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
212
|
+
result JSONB,
|
|
213
|
+
error TEXT,
|
|
214
|
+
rollback_info JSONB,
|
|
215
|
+
conversation_id UUID,
|
|
216
|
+
request_id TEXT
|
|
217
|
+
);
|
|
218
|
+
`);
|
|
219
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_action_log_requested_by ON action_log(requested_by);`);
|
|
220
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_action_log_status ON action_log(status);`);
|
|
221
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_action_log_action_type ON action_log(action_type);`);
|
|
222
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_action_log_conversation ON action_log(conversation_id);`);
|
|
223
|
+
|
|
224
|
+
// Multi-database production hardening: add source tracking columns to audit_log
|
|
225
|
+
await pool.query(`ALTER TABLE audit_log ADD COLUMN IF NOT EXISTS source_id TEXT, ADD COLUMN IF NOT EXISTS source_type TEXT, ADD COLUMN IF NOT EXISTS target_host TEXT;`);
|
|
226
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_audit_log_source_id ON audit_log(source_id);`);
|
|
227
|
+
|
|
228
|
+
// Saved/starred conversations
|
|
229
|
+
await pool.query(`ALTER TABLE conversations ADD COLUMN IF NOT EXISTS starred BOOLEAN NOT NULL DEFAULT false;`);
|
|
230
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_conversations_starred ON conversations(user_id, starred) WHERE starred = true;`);
|
|
231
|
+
|
|
232
|
+
// Scheduled tasks
|
|
233
|
+
await pool.query(`
|
|
234
|
+
CREATE TABLE IF NOT EXISTS scheduled_tasks (
|
|
235
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
236
|
+
owner_id TEXT NOT NULL,
|
|
237
|
+
name TEXT NOT NULL,
|
|
238
|
+
question TEXT NOT NULL,
|
|
239
|
+
cron_expression TEXT NOT NULL,
|
|
240
|
+
delivery_channel TEXT NOT NULL DEFAULT 'webhook',
|
|
241
|
+
recipients JSONB NOT NULL DEFAULT '[]',
|
|
242
|
+
connection_id TEXT,
|
|
243
|
+
approval_mode TEXT NOT NULL DEFAULT 'auto',
|
|
244
|
+
enabled BOOLEAN NOT NULL DEFAULT true,
|
|
245
|
+
last_run_at TIMESTAMPTZ,
|
|
246
|
+
next_run_at TIMESTAMPTZ,
|
|
247
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
248
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
249
|
+
);
|
|
250
|
+
`);
|
|
251
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_owner ON scheduled_tasks(owner_id);`);
|
|
252
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_enabled ON scheduled_tasks(enabled) WHERE enabled = true;`);
|
|
253
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_scheduled_tasks_next_run ON scheduled_tasks(next_run_at) WHERE enabled = true;`);
|
|
254
|
+
|
|
255
|
+
await pool.query(`
|
|
256
|
+
CREATE TABLE IF NOT EXISTS scheduled_task_runs (
|
|
257
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
258
|
+
task_id UUID NOT NULL REFERENCES scheduled_tasks(id) ON DELETE CASCADE,
|
|
259
|
+
started_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
260
|
+
completed_at TIMESTAMPTZ,
|
|
261
|
+
status TEXT NOT NULL DEFAULT 'running',
|
|
262
|
+
conversation_id UUID,
|
|
263
|
+
action_id UUID,
|
|
264
|
+
error TEXT,
|
|
265
|
+
tokens_used INTEGER,
|
|
266
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
267
|
+
);
|
|
268
|
+
`);
|
|
269
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_scheduled_task_runs_task ON scheduled_task_runs(task_id);`);
|
|
270
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_scheduled_task_runs_status ON scheduled_task_runs(status);`);
|
|
271
|
+
|
|
272
|
+
log.info("Internal DB migration complete (audit_log, conversations, messages, slack, action_log, scheduled_tasks)");
|
|
273
|
+
}
|