@useatlas/create 0.0.2 → 0.0.4
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 +4 -18
- package/index.ts +191 -31
- package/package.json +1 -1
- package/templates/docker/.env.example +3 -3
- package/templates/docker/Dockerfile.sidecar +28 -0
- package/templates/docker/bin/__tests__/plugin-cli.test.ts +9 -9
- package/templates/docker/bin/atlas.ts +108 -44
- package/templates/docker/data/demo-semantic/catalog.yml +51 -27
- package/templates/docker/data/demo-semantic/entities/accounts.yml +95 -103
- package/templates/docker/data/demo-semantic/entities/companies.yml +88 -152
- package/templates/docker/data/demo-semantic/entities/people.yml +82 -95
- package/templates/docker/data/demo-semantic/glossary.yml +104 -8
- package/templates/docker/data/demo-semantic/metrics/accounts.yml +62 -23
- package/templates/docker/data/demo-semantic/metrics/companies.yml +52 -78
- package/templates/docker/docker-compose.yml +1 -1
- package/templates/docker/docs/deploy.md +2 -39
- package/templates/docker/package.json +17 -1
- package/templates/docker/semantic/catalog.yml +62 -3
- package/templates/docker/semantic/entities/accounts.yml +162 -0
- package/templates/docker/semantic/entities/companies.yml +143 -0
- package/templates/docker/semantic/entities/people.yml +132 -0
- package/templates/docker/semantic/glossary.yml +116 -4
- package/templates/docker/semantic/metrics/accounts.yml +77 -0
- package/templates/docker/semantic/metrics/companies.yml +63 -0
- package/templates/docker/sidecar/Dockerfile +5 -6
- package/templates/docker/sidecar/railway.json +1 -2
- package/templates/docker/src/api/__tests__/admin.test.ts +7 -7
- package/templates/docker/src/api/__tests__/health-plugin.test.ts +7 -0
- package/templates/docker/src/api/__tests__/health.test.ts +30 -8
- package/templates/docker/src/api/routes/admin.ts +549 -8
- package/templates/docker/src/api/routes/chat.ts +5 -20
- package/templates/docker/src/api/routes/health.ts +39 -27
- package/templates/docker/src/api/routes/openapi.ts +1329 -74
- package/templates/docker/src/api/routes/query.ts +2 -1
- package/templates/docker/src/api/server.ts +27 -0
- package/templates/docker/src/app/api/[...route]/route.ts +2 -2
- package/templates/docker/src/app/globals.css +13 -12
- package/templates/docker/src/app/layout.tsx +9 -2
- package/templates/docker/src/components/ui/alert-dialog.tsx +196 -0
- package/templates/docker/src/components/ui/badge.tsx +48 -0
- package/templates/docker/src/components/ui/button.tsx +64 -0
- package/templates/docker/src/components/ui/card.tsx +92 -0
- package/templates/docker/src/components/ui/collapsible.tsx +33 -0
- package/templates/docker/src/components/ui/command.tsx +184 -0
- package/templates/docker/src/components/ui/dialog.tsx +158 -0
- package/templates/docker/src/components/ui/dropdown-menu.tsx +257 -0
- package/templates/docker/src/components/ui/input.tsx +21 -0
- package/templates/docker/src/components/ui/scroll-area.tsx +58 -0
- package/templates/docker/src/components/ui/select.tsx +190 -0
- package/templates/docker/src/components/ui/separator.tsx +28 -0
- package/templates/docker/src/components/ui/sheet.tsx +143 -0
- package/templates/docker/src/components/ui/sidebar.tsx +726 -0
- package/templates/docker/src/components/ui/skeleton.tsx +13 -0
- package/templates/docker/src/components/ui/table.tsx +116 -0
- package/templates/docker/src/components/ui/tabs.tsx +91 -0
- package/templates/docker/src/components/ui/toggle-group.tsx +83 -0
- package/templates/docker/src/components/ui/toggle.tsx +47 -0
- package/templates/docker/src/components/ui/tooltip.tsx +57 -0
- package/templates/docker/src/hooks/use-mobile.ts +19 -0
- package/templates/docker/src/lib/__tests__/agent-cache.test.ts +2 -0
- package/templates/docker/src/lib/__tests__/agent-dialect.test.ts +17 -0
- package/templates/docker/src/lib/__tests__/agent-health-annotations.test.ts +2 -0
- package/templates/docker/src/lib/__tests__/agent-integration.test.ts +2 -0
- package/templates/docker/src/lib/__tests__/config.test.ts +69 -19
- package/templates/docker/src/lib/__tests__/plugin-aware-validation.test.ts +321 -0
- package/templates/docker/src/lib/__tests__/providers.test.ts +32 -1
- package/templates/docker/src/lib/__tests__/startup-actions.test.ts +9 -0
- package/templates/docker/src/lib/__tests__/startup-first-run.test.ts +429 -0
- package/templates/docker/src/lib/__tests__/startup.test.ts +5 -0
- package/templates/docker/src/lib/agent-query.ts +5 -23
- package/templates/docker/src/lib/agent.ts +32 -112
- package/templates/docker/src/lib/auth/__tests__/migrate.test.ts +5 -3
- package/templates/docker/src/lib/auth/middleware.ts +30 -4
- package/templates/docker/src/lib/auth/migrate.ts +97 -0
- package/templates/docker/src/lib/auth/server.ts +12 -1
- package/templates/docker/src/lib/config.ts +37 -39
- package/templates/docker/src/lib/db/__tests__/connection.test.ts +89 -14
- package/templates/docker/src/lib/db/__tests__/registry-health.test.ts +1 -18
- package/templates/docker/src/lib/db/__tests__/registry-pool-limits.test.ts +0 -19
- package/templates/docker/src/lib/db/__tests__/registry.test.ts +11 -208
- package/templates/docker/src/lib/db/connection.ts +87 -265
- package/templates/docker/src/lib/db/internal.ts +6 -1
- package/templates/docker/src/lib/plugins/__tests__/hooks-integration.test.ts +3 -1
- package/templates/docker/src/lib/plugins/__tests__/hooks.test.ts +2 -2
- package/templates/docker/src/lib/plugins/__tests__/migrate.test.ts +355 -1
- package/templates/docker/src/lib/plugins/__tests__/registry.test.ts +32 -5
- package/templates/docker/src/lib/plugins/__tests__/wiring.test.ts +228 -14
- package/templates/docker/src/lib/plugins/index.ts +4 -1
- package/templates/docker/src/lib/plugins/migrate.ts +103 -0
- package/templates/docker/src/lib/plugins/registry.ts +12 -6
- package/templates/docker/src/lib/plugins/wiring.ts +113 -4
- package/templates/docker/src/lib/providers.ts +6 -1
- package/templates/docker/src/lib/security.ts +24 -0
- package/templates/docker/src/lib/semantic.ts +2 -0
- package/templates/docker/src/lib/sidecar-types.ts +12 -1
- package/templates/docker/src/lib/startup.ts +71 -101
- package/templates/docker/src/lib/tools/__tests__/custom-validation.test.ts +2 -0
- package/templates/docker/src/lib/tools/__tests__/explore-nsjail.test.ts +32 -18
- package/templates/docker/src/lib/tools/__tests__/explore-plugin.test.ts +14 -14
- package/templates/docker/src/lib/tools/__tests__/explore-sidecar.test.ts +5 -3
- package/templates/docker/src/lib/tools/__tests__/python-nsjail.test.ts +515 -0
- package/templates/docker/src/lib/tools/__tests__/python-sandbox.test.ts +397 -0
- package/templates/docker/src/lib/tools/__tests__/python-sidecar.test.ts +365 -0
- package/templates/docker/src/lib/tools/__tests__/python.test.ts +331 -0
- package/templates/docker/src/lib/tools/__tests__/registry-actions.test.ts +1 -13
- package/templates/docker/src/lib/tools/__tests__/registry.test.ts +38 -31
- package/templates/docker/src/lib/tools/__tests__/sql-audit.test.ts +2 -0
- package/templates/docker/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +2 -0
- package/templates/docker/src/lib/tools/__tests__/sql-ratelimit.test.ts +2 -0
- package/templates/docker/src/lib/tools/__tests__/sql.test.ts +5 -308
- package/templates/docker/src/lib/tools/explore-nsjail.ts +17 -12
- package/templates/docker/src/lib/tools/explore-sidecar.ts +25 -0
- package/templates/docker/src/lib/tools/explore.ts +28 -32
- package/templates/docker/src/lib/tools/python-nsjail.ts +396 -0
- package/templates/docker/src/lib/tools/python-sandbox.ts +476 -0
- package/templates/docker/src/lib/tools/python-sidecar.ts +150 -0
- package/templates/docker/src/lib/tools/python.ts +367 -0
- package/templates/docker/src/lib/tools/registry.ts +49 -22
- package/templates/docker/src/lib/tools/sql.ts +88 -88
- package/templates/docker/src/types/vercel-sandbox.d.ts +7 -0
- package/templates/docker/src/ui/components/admin/admin-layout.tsx +77 -8
- package/templates/docker/src/ui/components/admin/admin-sidebar.tsx +25 -17
- package/templates/docker/src/ui/components/admin/change-password-dialog.tsx +128 -0
- package/templates/docker/src/ui/components/admin/entity-detail.tsx +3 -3
- package/templates/docker/src/ui/components/admin/semantic-file-tree.tsx +159 -0
- package/templates/docker/src/ui/components/atlas-chat.tsx +64 -12
- package/templates/docker/src/ui/components/chart/result-chart.tsx +25 -15
- package/templates/docker/src/ui/components/chat/markdown.tsx +88 -42
- package/templates/docker/src/ui/components/chat/python-result-card.tsx +244 -0
- package/templates/docker/src/ui/components/chat/sql-block.tsx +39 -15
- package/templates/docker/src/ui/components/chat/sql-result-card.tsx +6 -1
- package/templates/docker/src/ui/components/chat/tool-part.tsx +12 -3
- package/templates/docker/src/ui/components/chat/typing-indicator.tsx +5 -2
- package/templates/docker/src/ui/components/conversations/conversation-item.tsx +25 -20
- package/templates/docker/src/ui/context.tsx +1 -1
- package/templates/docker/src/ui/hooks/use-conversations.ts +3 -3
- package/templates/docker/src/ui/hooks/use-dark-mode.ts +17 -10
- package/templates/docker/tsconfig.json +2 -2
- package/templates/nextjs-standalone/.env.example +1 -1
- package/templates/nextjs-standalone/bin/__tests__/plugin-cli.test.ts +9 -9
- package/templates/nextjs-standalone/bin/atlas.ts +108 -44
- package/templates/nextjs-standalone/data/demo-semantic/catalog.yml +51 -27
- package/templates/nextjs-standalone/data/demo-semantic/entities/accounts.yml +95 -103
- package/templates/nextjs-standalone/data/demo-semantic/entities/companies.yml +88 -152
- package/templates/nextjs-standalone/data/demo-semantic/entities/people.yml +82 -95
- package/templates/nextjs-standalone/data/demo-semantic/glossary.yml +104 -8
- package/templates/nextjs-standalone/data/demo-semantic/metrics/accounts.yml +62 -23
- package/templates/nextjs-standalone/data/demo-semantic/metrics/companies.yml +52 -78
- package/templates/nextjs-standalone/docs/deploy.md +2 -39
- package/templates/nextjs-standalone/package.json +11 -2
- package/templates/nextjs-standalone/scripts/migrate-auth.ts +25 -0
- package/templates/nextjs-standalone/scripts/seed-demo.ts +94 -0
- package/templates/nextjs-standalone/semantic/catalog.yml +62 -3
- package/templates/nextjs-standalone/semantic/entities/accounts.yml +162 -0
- package/templates/nextjs-standalone/semantic/entities/companies.yml +143 -0
- package/templates/nextjs-standalone/semantic/entities/people.yml +132 -0
- package/templates/nextjs-standalone/semantic/glossary.yml +116 -4
- package/templates/nextjs-standalone/semantic/metrics/accounts.yml +77 -0
- package/templates/nextjs-standalone/semantic/metrics/companies.yml +63 -0
- package/templates/nextjs-standalone/src/api/__tests__/admin.test.ts +7 -7
- package/templates/nextjs-standalone/src/api/__tests__/health-plugin.test.ts +7 -0
- package/templates/nextjs-standalone/src/api/__tests__/health.test.ts +30 -8
- package/templates/nextjs-standalone/src/api/routes/admin.ts +549 -8
- package/templates/nextjs-standalone/src/api/routes/chat.ts +5 -20
- package/templates/nextjs-standalone/src/api/routes/health.ts +39 -27
- package/templates/nextjs-standalone/src/api/routes/openapi.ts +1329 -74
- package/templates/nextjs-standalone/src/api/routes/query.ts +2 -1
- package/templates/nextjs-standalone/src/api/server.ts +27 -0
- package/templates/nextjs-standalone/src/app/api/[...route]/route.ts +2 -2
- package/templates/nextjs-standalone/src/app/globals.css +13 -12
- package/templates/nextjs-standalone/src/app/layout.tsx +9 -2
- package/templates/nextjs-standalone/src/components/ui/alert-dialog.tsx +196 -0
- package/templates/nextjs-standalone/src/components/ui/badge.tsx +48 -0
- package/templates/nextjs-standalone/src/components/ui/button.tsx +64 -0
- package/templates/nextjs-standalone/src/components/ui/card.tsx +92 -0
- package/templates/nextjs-standalone/src/components/ui/collapsible.tsx +33 -0
- package/templates/nextjs-standalone/src/components/ui/command.tsx +184 -0
- package/templates/nextjs-standalone/src/components/ui/dialog.tsx +158 -0
- package/templates/nextjs-standalone/src/components/ui/dropdown-menu.tsx +257 -0
- package/templates/nextjs-standalone/src/components/ui/input.tsx +21 -0
- package/templates/nextjs-standalone/src/components/ui/scroll-area.tsx +58 -0
- package/templates/nextjs-standalone/src/components/ui/select.tsx +190 -0
- package/templates/nextjs-standalone/src/components/ui/separator.tsx +28 -0
- package/templates/nextjs-standalone/src/components/ui/sheet.tsx +143 -0
- package/templates/nextjs-standalone/src/components/ui/sidebar.tsx +726 -0
- package/templates/nextjs-standalone/src/components/ui/skeleton.tsx +13 -0
- package/templates/nextjs-standalone/src/components/ui/table.tsx +116 -0
- package/templates/nextjs-standalone/src/components/ui/tabs.tsx +91 -0
- package/templates/nextjs-standalone/src/components/ui/toggle-group.tsx +83 -0
- package/templates/nextjs-standalone/src/components/ui/toggle.tsx +47 -0
- package/templates/nextjs-standalone/src/components/ui/tooltip.tsx +57 -0
- package/templates/nextjs-standalone/src/hooks/use-mobile.ts +19 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-cache.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-dialect.test.ts +17 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-health-annotations.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-integration.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/__tests__/config.test.ts +69 -19
- package/templates/nextjs-standalone/src/lib/__tests__/plugin-aware-validation.test.ts +321 -0
- package/templates/nextjs-standalone/src/lib/__tests__/providers.test.ts +32 -1
- package/templates/nextjs-standalone/src/lib/__tests__/startup-actions.test.ts +9 -0
- package/templates/nextjs-standalone/src/lib/__tests__/startup-first-run.test.ts +429 -0
- package/templates/nextjs-standalone/src/lib/__tests__/startup.test.ts +5 -0
- package/templates/nextjs-standalone/src/lib/agent-query.ts +5 -23
- package/templates/nextjs-standalone/src/lib/agent.ts +32 -112
- package/templates/nextjs-standalone/src/lib/auth/__tests__/migrate.test.ts +5 -3
- package/templates/nextjs-standalone/src/lib/auth/middleware.ts +30 -4
- package/templates/nextjs-standalone/src/lib/auth/migrate.ts +97 -0
- package/templates/nextjs-standalone/src/lib/auth/server.ts +12 -1
- package/templates/nextjs-standalone/src/lib/config.ts +37 -39
- package/templates/nextjs-standalone/src/lib/db/__tests__/connection.test.ts +89 -14
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry-health.test.ts +1 -18
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry-pool-limits.test.ts +0 -19
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry.test.ts +11 -208
- package/templates/nextjs-standalone/src/lib/db/connection.ts +87 -265
- package/templates/nextjs-standalone/src/lib/db/internal.ts +6 -1
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks-integration.test.ts +3 -1
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks.test.ts +2 -2
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/migrate.test.ts +355 -1
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/registry.test.ts +32 -5
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/wiring.test.ts +228 -14
- package/templates/nextjs-standalone/src/lib/plugins/index.ts +4 -1
- package/templates/nextjs-standalone/src/lib/plugins/migrate.ts +103 -0
- package/templates/nextjs-standalone/src/lib/plugins/registry.ts +12 -6
- package/templates/nextjs-standalone/src/lib/plugins/wiring.ts +113 -4
- package/templates/nextjs-standalone/src/lib/providers.ts +6 -1
- package/templates/nextjs-standalone/src/lib/security.ts +24 -0
- package/templates/nextjs-standalone/src/lib/semantic.ts +2 -0
- package/templates/nextjs-standalone/src/lib/sidecar-types.ts +12 -1
- package/templates/nextjs-standalone/src/lib/startup.ts +71 -101
- package/templates/nextjs-standalone/src/lib/tools/__tests__/custom-validation.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-nsjail.test.ts +32 -18
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-plugin.test.ts +14 -14
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sidecar.test.ts +5 -3
- package/templates/nextjs-standalone/src/lib/tools/__tests__/python-nsjail.test.ts +515 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sandbox.test.ts +397 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sidecar.test.ts +365 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/python.test.ts +331 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/registry-actions.test.ts +1 -13
- package/templates/nextjs-standalone/src/lib/tools/__tests__/registry.test.ts +38 -31
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-audit.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-ratelimit.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql.test.ts +5 -308
- package/templates/nextjs-standalone/src/lib/tools/explore-nsjail.ts +17 -12
- package/templates/nextjs-standalone/src/lib/tools/explore-sidecar.ts +25 -0
- package/templates/nextjs-standalone/src/lib/tools/explore.ts +28 -32
- package/templates/nextjs-standalone/src/lib/tools/python-nsjail.ts +396 -0
- package/templates/nextjs-standalone/src/lib/tools/python-sandbox.ts +476 -0
- package/templates/nextjs-standalone/src/lib/tools/python-sidecar.ts +150 -0
- package/templates/nextjs-standalone/src/lib/tools/python.ts +367 -0
- package/templates/nextjs-standalone/src/lib/tools/registry.ts +49 -22
- package/templates/nextjs-standalone/src/lib/tools/sql.ts +88 -88
- package/templates/nextjs-standalone/src/ui/components/admin/admin-layout.tsx +77 -8
- package/templates/nextjs-standalone/src/ui/components/admin/admin-sidebar.tsx +25 -17
- package/templates/nextjs-standalone/src/ui/components/admin/change-password-dialog.tsx +128 -0
- package/templates/nextjs-standalone/src/ui/components/admin/entity-detail.tsx +3 -3
- package/templates/nextjs-standalone/src/ui/components/admin/semantic-file-tree.tsx +159 -0
- package/templates/nextjs-standalone/src/ui/components/atlas-chat.tsx +64 -12
- package/templates/nextjs-standalone/src/ui/components/chart/result-chart.tsx +25 -15
- package/templates/nextjs-standalone/src/ui/components/chat/markdown.tsx +88 -42
- package/templates/nextjs-standalone/src/ui/components/chat/python-result-card.tsx +244 -0
- package/templates/nextjs-standalone/src/ui/components/chat/sql-block.tsx +39 -15
- package/templates/nextjs-standalone/src/ui/components/chat/sql-result-card.tsx +6 -1
- package/templates/nextjs-standalone/src/ui/components/chat/tool-part.tsx +12 -3
- package/templates/nextjs-standalone/src/ui/components/chat/typing-indicator.tsx +5 -2
- package/templates/nextjs-standalone/src/ui/components/conversations/conversation-item.tsx +25 -20
- package/templates/nextjs-standalone/src/ui/context.tsx +1 -1
- package/templates/nextjs-standalone/src/ui/hooks/use-conversations.ts +3 -3
- package/templates/nextjs-standalone/src/ui/hooks/use-dark-mode.ts +17 -10
- package/templates/nextjs-standalone/tsconfig.json +0 -1
- package/templates/nextjs-standalone/vercel.json +4 -1
- package/templates/docker/render.yaml +0 -34
- package/templates/docker/semantic/entities/.gitkeep +0 -0
- package/templates/docker/semantic/metrics/.gitkeep +0 -0
- package/templates/docker/src/lib/db/__tests__/duckdb.test.ts +0 -141
- package/templates/docker/src/lib/db/__tests__/salesforce.test.ts +0 -339
- package/templates/docker/src/lib/db/__tests__/snowflake.test.ts +0 -217
- package/templates/docker/src/lib/db/duckdb.ts +0 -122
- package/templates/docker/src/lib/db/salesforce.ts +0 -342
- package/templates/docker/src/lib/tools/__tests__/salesforce-tool.test.ts +0 -154
- package/templates/docker/src/lib/tools/__tests__/soql-validation.test.ts +0 -303
- package/templates/docker/src/lib/tools/__tests__/sql-duckdb.test.ts +0 -233
- package/templates/docker/src/lib/tools/salesforce.ts +0 -138
- package/templates/docker/src/lib/tools/soql-validation.ts +0 -172
- package/templates/nextjs-standalone/semantic/entities/.gitkeep +0 -0
- package/templates/nextjs-standalone/semantic/metrics/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/duckdb.test.ts +0 -141
- package/templates/nextjs-standalone/src/lib/db/__tests__/salesforce.test.ts +0 -339
- package/templates/nextjs-standalone/src/lib/db/__tests__/snowflake.test.ts +0 -217
- package/templates/nextjs-standalone/src/lib/db/duckdb.ts +0 -122
- package/templates/nextjs-standalone/src/lib/db/salesforce.ts +0 -342
- package/templates/nextjs-standalone/src/lib/tools/__tests__/salesforce-tool.test.ts +0 -154
- package/templates/nextjs-standalone/src/lib/tools/__tests__/soql-validation.test.ts +0 -303
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-duckdb.test.ts +0 -233
- package/templates/nextjs-standalone/src/lib/tools/salesforce.ts +0 -138
- package/templates/nextjs-standalone/src/lib/tools/soql-validation.ts +0 -172
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
* bun run atlas -- diff --tables t1,t2 # Diff only specific tables/views
|
|
29
29
|
* bun run atlas -- diff --schema analytics # Diff a non-public PostgreSQL schema
|
|
30
30
|
* bun run atlas -- diff --source warehouse # Diff from semantic/warehouse/ subdirectory
|
|
31
|
+
* bun run atlas -- doctor # Validate environment and connectivity
|
|
31
32
|
*
|
|
32
33
|
* When run in a TTY without --tables or --demo, an interactive multiselect picker
|
|
33
34
|
* lets you choose which tables and views to profile. --demo skips the picker since
|
|
@@ -44,7 +45,22 @@ import * as path from "path";
|
|
|
44
45
|
import * as yaml from "js-yaml";
|
|
45
46
|
import * as p from "@clack/prompts";
|
|
46
47
|
import pc from "picocolors";
|
|
47
|
-
import {
|
|
48
|
+
import { type DBType } from "@atlas/api/lib/db/connection";
|
|
49
|
+
|
|
50
|
+
/** CLI-local DB type detection — supports all URL schemes (core + plugin databases). */
|
|
51
|
+
function detectDBType(url: string): DBType {
|
|
52
|
+
if (url.startsWith("postgresql://") || url.startsWith("postgres://")) return "postgres";
|
|
53
|
+
if (url.startsWith("mysql://") || url.startsWith("mysql2://")) return "mysql";
|
|
54
|
+
if (url.startsWith("clickhouse://") || url.startsWith("clickhouses://")) return "clickhouse";
|
|
55
|
+
if (url.startsWith("snowflake://")) return "snowflake";
|
|
56
|
+
if (url.startsWith("duckdb://")) return "duckdb";
|
|
57
|
+
if (url.startsWith("salesforce://")) return "salesforce";
|
|
58
|
+
const scheme = url.split("://")[0] || "(empty)";
|
|
59
|
+
throw new Error(
|
|
60
|
+
`Unsupported database URL scheme "${scheme}://". ` +
|
|
61
|
+
"Supported: postgresql://, mysql://, clickhouse://, snowflake://, duckdb://, salesforce://."
|
|
62
|
+
);
|
|
63
|
+
}
|
|
48
64
|
// Lazy-loaded to avoid requiring native bindings at type-check time
|
|
49
65
|
async function loadDuckDB() {
|
|
50
66
|
const { DuckDBInstance } = await import("@duckdb/node-api");
|
|
@@ -1051,7 +1067,7 @@ async function createSnowflakePool(connectionString: string, max = 1) {
|
|
|
1051
1067
|
const snowflake = require("snowflake-sdk") as typeof import("snowflake-sdk");
|
|
1052
1068
|
snowflake.configure({ logLevel: "ERROR" });
|
|
1053
1069
|
|
|
1054
|
-
const { parseSnowflakeURL } = await import("
|
|
1070
|
+
const { parseSnowflakeURL } = await import("../../../plugins/snowflake/src/connection");
|
|
1055
1071
|
const opts = parseSnowflakeURL(connectionString);
|
|
1056
1072
|
|
|
1057
1073
|
const pool = snowflake.createPool(
|
|
@@ -1386,12 +1402,13 @@ function mapSalesforceFieldType(sfType: string): string {
|
|
|
1386
1402
|
}
|
|
1387
1403
|
|
|
1388
1404
|
export async function listSalesforceObjects(connectionString: string): Promise<DatabaseObject[]> {
|
|
1389
|
-
const { parseSalesforceURL,
|
|
1405
|
+
const { parseSalesforceURL, createSalesforceConnection } = await import("../../../plugins/salesforce/src/connection");
|
|
1390
1406
|
const config = parseSalesforceURL(connectionString);
|
|
1391
|
-
|
|
1407
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1408
|
+
const source: any = createSalesforceConnection(config);
|
|
1392
1409
|
try {
|
|
1393
1410
|
const objects = await source.listObjects();
|
|
1394
|
-
return objects.map((obj) => ({
|
|
1411
|
+
return objects.map((obj: { name: string }) => ({
|
|
1395
1412
|
name: obj.name,
|
|
1396
1413
|
type: "table" as const,
|
|
1397
1414
|
}));
|
|
@@ -1405,9 +1422,10 @@ export async function profileSalesforce(
|
|
|
1405
1422
|
filterTables?: string[],
|
|
1406
1423
|
prefetchedObjects?: DatabaseObject[],
|
|
1407
1424
|
): Promise<TableProfile[]> {
|
|
1408
|
-
const { parseSalesforceURL,
|
|
1425
|
+
const { parseSalesforceURL, createSalesforceConnection } = await import("../../../plugins/salesforce/src/connection");
|
|
1409
1426
|
const config = parseSalesforceURL(connectionString);
|
|
1410
|
-
|
|
1427
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1428
|
+
const source: any = createSalesforceConnection(config);
|
|
1411
1429
|
|
|
1412
1430
|
const profiles: TableProfile[] = [];
|
|
1413
1431
|
const errors: { table: string; error: string }[] = [];
|
|
@@ -1418,7 +1436,7 @@ export async function profileSalesforce(
|
|
|
1418
1436
|
allObjects = prefetchedObjects;
|
|
1419
1437
|
} else {
|
|
1420
1438
|
const objects = await source.listObjects();
|
|
1421
|
-
allObjects = objects.map((obj) => ({
|
|
1439
|
+
allObjects = objects.map((obj: { name: string }) => ({
|
|
1422
1440
|
name: obj.name,
|
|
1423
1441
|
type: "table" as const,
|
|
1424
1442
|
}));
|
|
@@ -1452,7 +1470,8 @@ export async function profileSalesforce(
|
|
|
1452
1470
|
const foreignKeys: ForeignKey[] = [];
|
|
1453
1471
|
const primaryKeyColumns: string[] = [];
|
|
1454
1472
|
|
|
1455
|
-
|
|
1473
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1474
|
+
const columns: ColumnProfile[] = desc.fields.map((field: any) => {
|
|
1456
1475
|
const isPK = field.name === "Id";
|
|
1457
1476
|
if (isPK) primaryKeyColumns.push(field.name);
|
|
1458
1477
|
|
|
@@ -1470,7 +1489,8 @@ export async function profileSalesforce(
|
|
|
1470
1489
|
|
|
1471
1490
|
// For picklist fields, extract active values as sample_values
|
|
1472
1491
|
const sampleValues = isEnumLike
|
|
1473
|
-
|
|
1492
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1493
|
+
? field.picklistValues.filter((pv: any) => pv.active).map((pv: any) => pv.value)
|
|
1474
1494
|
: [];
|
|
1475
1495
|
|
|
1476
1496
|
return {
|
|
@@ -2684,6 +2704,21 @@ function parseDemoArg(args: string[]): DemoDataset | null {
|
|
|
2684
2704
|
throw new Error(`Unknown demo dataset "${next}". Available: ${Object.keys(DEMO_DATASETS).join(", ")}`);
|
|
2685
2705
|
}
|
|
2686
2706
|
|
|
2707
|
+
/** Recursively copy a directory, overwriting existing files. */
|
|
2708
|
+
function copyDirRecursive(src: string, dest: string): void {
|
|
2709
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
2710
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
2711
|
+
const srcPath = path.join(src, entry.name);
|
|
2712
|
+
const destPath = path.join(dest, entry.name);
|
|
2713
|
+
if (entry.isDirectory()) {
|
|
2714
|
+
copyDirRecursive(srcPath, destPath);
|
|
2715
|
+
} else {
|
|
2716
|
+
fs.copyFileSync(srcPath, destPath);
|
|
2717
|
+
console.log(` wrote ${destPath}`);
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
|
|
2687
2722
|
// --- Demo data seeding ---
|
|
2688
2723
|
|
|
2689
2724
|
export async function seedDemoPostgres(
|
|
@@ -3134,7 +3169,7 @@ export async function handleActionApproval(
|
|
|
3134
3169
|
|
|
3135
3170
|
interface PluginInfo {
|
|
3136
3171
|
id: string;
|
|
3137
|
-
|
|
3172
|
+
types: string[];
|
|
3138
3173
|
version: string;
|
|
3139
3174
|
name?: string;
|
|
3140
3175
|
healthy?: boolean;
|
|
@@ -3169,7 +3204,7 @@ export async function handlePluginList(): Promise<void> {
|
|
|
3169
3204
|
for (const p of plugins) {
|
|
3170
3205
|
const info: PluginInfo = {
|
|
3171
3206
|
id: String(p.id ?? "unknown"),
|
|
3172
|
-
|
|
3207
|
+
types: Array.isArray(p.types) ? (p.types as string[]).map(String) : ["unknown"],
|
|
3173
3208
|
version: String(p.version ?? "unknown"),
|
|
3174
3209
|
name: p.name ? String(p.name) : undefined,
|
|
3175
3210
|
};
|
|
@@ -3194,7 +3229,7 @@ export async function handlePluginList(): Promise<void> {
|
|
|
3194
3229
|
const rows = infos.map((info) => ({
|
|
3195
3230
|
Name: info.name ?? info.id,
|
|
3196
3231
|
ID: info.id,
|
|
3197
|
-
Type: info.
|
|
3232
|
+
Type: info.types.join(", "),
|
|
3198
3233
|
Version: info.version,
|
|
3199
3234
|
Health:
|
|
3200
3235
|
info.healthy === undefined
|
|
@@ -3230,7 +3265,7 @@ import type { AtlasDatasourcePlugin, PluginDBConnection } from "@useatlas/plugin
|
|
|
3230
3265
|
|
|
3231
3266
|
export default definePlugin({
|
|
3232
3267
|
id: "${id}",
|
|
3233
|
-
|
|
3268
|
+
types: ["datasource"],
|
|
3234
3269
|
version: "0.1.0",
|
|
3235
3270
|
name: "${pascalName}",
|
|
3236
3271
|
|
|
@@ -3259,7 +3294,7 @@ import type { AtlasContextPlugin } from "@useatlas/plugin-sdk";
|
|
|
3259
3294
|
|
|
3260
3295
|
export default definePlugin({
|
|
3261
3296
|
id: "${id}",
|
|
3262
|
-
|
|
3297
|
+
types: ["context"],
|
|
3263
3298
|
version: "0.1.0",
|
|
3264
3299
|
name: "${pascalName}",
|
|
3265
3300
|
|
|
@@ -3290,7 +3325,7 @@ import type { Hono } from "hono";
|
|
|
3290
3325
|
|
|
3291
3326
|
export default definePlugin({
|
|
3292
3327
|
id: "${id}",
|
|
3293
|
-
|
|
3328
|
+
types: ["interaction"],
|
|
3294
3329
|
version: "0.1.0",
|
|
3295
3330
|
name: "${pascalName}",
|
|
3296
3331
|
|
|
@@ -3317,7 +3352,7 @@ import { z } from "zod";
|
|
|
3317
3352
|
|
|
3318
3353
|
export default definePlugin({
|
|
3319
3354
|
id: "${id}",
|
|
3320
|
-
|
|
3355
|
+
types: ["action"],
|
|
3321
3356
|
version: "0.1.0",
|
|
3322
3357
|
name: "${pascalName}",
|
|
3323
3358
|
|
|
@@ -3358,7 +3393,7 @@ import type { AtlasSandboxPlugin, PluginExploreBackend, PluginExecResult } from
|
|
|
3358
3393
|
|
|
3359
3394
|
export default definePlugin({
|
|
3360
3395
|
id: "${id}",
|
|
3361
|
-
|
|
3396
|
+
types: ["sandbox"],
|
|
3362
3397
|
version: "0.1.0",
|
|
3363
3398
|
name: "${pascalName}",
|
|
3364
3399
|
|
|
@@ -3398,7 +3433,7 @@ import plugin from "./index";
|
|
|
3398
3433
|
describe("${name} plugin", () => {
|
|
3399
3434
|
test("has correct id and type", () => {
|
|
3400
3435
|
expect(plugin.id).toBe("${name}");
|
|
3401
|
-
expect(plugin.
|
|
3436
|
+
expect(plugin.types).toContain("${pluginType}");
|
|
3402
3437
|
});
|
|
3403
3438
|
|
|
3404
3439
|
test("has a version string", () => {
|
|
@@ -3890,9 +3925,10 @@ async function handleDiff(args: string[]): Promise<void> {
|
|
|
3890
3925
|
}
|
|
3891
3926
|
}
|
|
3892
3927
|
} else if (dbType === "salesforce") {
|
|
3893
|
-
const { parseSalesforceURL,
|
|
3928
|
+
const { parseSalesforceURL, createSalesforceConnection } = await import("../../../plugins/salesforce/src/connection");
|
|
3894
3929
|
const config = parseSalesforceURL(connStr);
|
|
3895
|
-
|
|
3930
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3931
|
+
const source: any = createSalesforceConnection(config);
|
|
3896
3932
|
try {
|
|
3897
3933
|
const objects = await source.listObjects();
|
|
3898
3934
|
console.log(`Connected: Salesforce (${objects.length} queryable objects)`);
|
|
@@ -3949,7 +3985,7 @@ async function handleDiff(args: string[]): Promise<void> {
|
|
|
3949
3985
|
profiles = await profileSnowflake(connStr, filterTables);
|
|
3950
3986
|
break;
|
|
3951
3987
|
case "duckdb": {
|
|
3952
|
-
const { parseDuckDBUrl } = await import("
|
|
3988
|
+
const { parseDuckDBUrl } = await import("../../../plugins/duckdb/src/connection");
|
|
3953
3989
|
const duckConfig = parseDuckDBUrl(connStr);
|
|
3954
3990
|
profiles = await profileDuckDB(duckConfig.path, filterTables);
|
|
3955
3991
|
break;
|
|
@@ -3958,8 +3994,7 @@ async function handleDiff(args: string[]): Promise<void> {
|
|
|
3958
3994
|
profiles = await profileSalesforce(connStr, filterTables);
|
|
3959
3995
|
break;
|
|
3960
3996
|
default: {
|
|
3961
|
-
|
|
3962
|
-
throw new Error(`Unknown database type: ${_exhaustive}`);
|
|
3997
|
+
throw new Error(`Unknown database type: ${dbType}`);
|
|
3963
3998
|
}
|
|
3964
3999
|
}
|
|
3965
4000
|
} catch (err) {
|
|
@@ -4136,7 +4171,7 @@ async function profileDatasource(opts: ProfileDatasourceOpts): Promise<void> {
|
|
|
4136
4171
|
}
|
|
4137
4172
|
} else if (dbType === "duckdb") {
|
|
4138
4173
|
try {
|
|
4139
|
-
const { parseDuckDBUrl } = await import("
|
|
4174
|
+
const { parseDuckDBUrl } = await import("../../../plugins/duckdb/src/connection");
|
|
4140
4175
|
const duckConfig = parseDuckDBUrl(connStr);
|
|
4141
4176
|
const DuckDBInstance = await loadDuckDB();
|
|
4142
4177
|
const testInstance = await DuckDBInstance.create(duckConfig.path, { access_mode: "READ_ONLY" });
|
|
@@ -4156,9 +4191,10 @@ async function profileDatasource(opts: ProfileDatasourceOpts): Promise<void> {
|
|
|
4156
4191
|
process.exit(1);
|
|
4157
4192
|
}
|
|
4158
4193
|
} else if (dbType === "salesforce") {
|
|
4159
|
-
const { parseSalesforceURL,
|
|
4194
|
+
const { parseSalesforceURL, createSalesforceConnection } = await import("../../../plugins/salesforce/src/connection");
|
|
4160
4195
|
const config = parseSalesforceURL(connStr);
|
|
4161
|
-
|
|
4196
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4197
|
+
const source: any = createSalesforceConnection(config);
|
|
4162
4198
|
try {
|
|
4163
4199
|
const objects = await source.listObjects();
|
|
4164
4200
|
console.log(`Connected: Salesforce (${objects.length} queryable objects)`);
|
|
@@ -4208,7 +4244,7 @@ async function profileDatasource(opts: ProfileDatasourceOpts): Promise<void> {
|
|
|
4208
4244
|
allObjects = await listSnowflakeObjects(connStr);
|
|
4209
4245
|
break;
|
|
4210
4246
|
case "duckdb": {
|
|
4211
|
-
const { parseDuckDBUrl } = await import("
|
|
4247
|
+
const { parseDuckDBUrl } = await import("../../../plugins/duckdb/src/connection");
|
|
4212
4248
|
const duckConfig = parseDuckDBUrl(connStr);
|
|
4213
4249
|
allObjects = await listDuckDBObjects(duckConfig.path);
|
|
4214
4250
|
break;
|
|
@@ -4217,8 +4253,7 @@ async function profileDatasource(opts: ProfileDatasourceOpts): Promise<void> {
|
|
|
4217
4253
|
allObjects = await listSalesforceObjects(connStr);
|
|
4218
4254
|
break;
|
|
4219
4255
|
default: {
|
|
4220
|
-
|
|
4221
|
-
throw new Error(`Unknown database type: ${_exhaustive}`);
|
|
4256
|
+
throw new Error(`Unknown database type: ${dbType}`);
|
|
4222
4257
|
}
|
|
4223
4258
|
}
|
|
4224
4259
|
} catch (err) {
|
|
@@ -4278,7 +4313,7 @@ async function profileDatasource(opts: ProfileDatasourceOpts): Promise<void> {
|
|
|
4278
4313
|
profiles = await profileSnowflake(connStr, selectedTables, prefetchedObjects);
|
|
4279
4314
|
break;
|
|
4280
4315
|
case "duckdb": {
|
|
4281
|
-
const { parseDuckDBUrl } = await import("
|
|
4316
|
+
const { parseDuckDBUrl } = await import("../../../plugins/duckdb/src/connection");
|
|
4282
4317
|
const duckConfig = parseDuckDBUrl(connStr);
|
|
4283
4318
|
profiles = await profileDuckDB(duckConfig.path, selectedTables, prefetchedObjects);
|
|
4284
4319
|
break;
|
|
@@ -4287,8 +4322,7 @@ async function profileDatasource(opts: ProfileDatasourceOpts): Promise<void> {
|
|
|
4287
4322
|
profiles = await profileSalesforce(connStr, selectedTables, prefetchedObjects);
|
|
4288
4323
|
break;
|
|
4289
4324
|
default: {
|
|
4290
|
-
|
|
4291
|
-
throw new Error(`Unknown database type: ${_exhaustive}`);
|
|
4325
|
+
throw new Error(`Unknown database type: ${dbType}`);
|
|
4292
4326
|
}
|
|
4293
4327
|
}
|
|
4294
4328
|
|
|
@@ -4374,6 +4408,15 @@ async function profileDatasource(opts: ProfileDatasourceOpts): Promise<void> {
|
|
|
4374
4408
|
}
|
|
4375
4409
|
}
|
|
4376
4410
|
|
|
4411
|
+
// For --demo simple, overlay hand-crafted semantic files with richer descriptions
|
|
4412
|
+
if (demoDataset === "simple") {
|
|
4413
|
+
const demoSemanticDir = path.resolve(import.meta.dir, "..", "data", "demo-semantic");
|
|
4414
|
+
if (fs.existsSync(demoSemanticDir)) {
|
|
4415
|
+
console.log(`\nApplying curated demo semantic layer...\n`);
|
|
4416
|
+
copyDirRecursive(demoSemanticDir, outputBase);
|
|
4417
|
+
}
|
|
4418
|
+
}
|
|
4419
|
+
|
|
4377
4420
|
// LLM enrichment (optional)
|
|
4378
4421
|
let enrichmentSucceeded = false;
|
|
4379
4422
|
if (shouldEnrich) {
|
|
@@ -4551,6 +4594,24 @@ async function main() {
|
|
|
4551
4594
|
return handleSmoke(args);
|
|
4552
4595
|
}
|
|
4553
4596
|
|
|
4597
|
+
if (command === "completions") {
|
|
4598
|
+
const { handleCompletions } = await import("../src/completions");
|
|
4599
|
+
handleCompletions(args);
|
|
4600
|
+
return;
|
|
4601
|
+
}
|
|
4602
|
+
|
|
4603
|
+
if (command === "doctor") {
|
|
4604
|
+
const { runDoctor } = await import("../src/doctor");
|
|
4605
|
+
const exitCode = await runDoctor();
|
|
4606
|
+
process.exit(exitCode);
|
|
4607
|
+
}
|
|
4608
|
+
|
|
4609
|
+
if (command === "validate") {
|
|
4610
|
+
const { runValidate } = await import("../src/validate");
|
|
4611
|
+
const exitCode = await runValidate();
|
|
4612
|
+
process.exit(exitCode);
|
|
4613
|
+
}
|
|
4614
|
+
|
|
4554
4615
|
if (command === "diff") {
|
|
4555
4616
|
return handleDiff(args);
|
|
4556
4617
|
}
|
|
@@ -4625,17 +4686,20 @@ async function main() {
|
|
|
4625
4686
|
|
|
4626
4687
|
if (command !== "init") {
|
|
4627
4688
|
console.log(
|
|
4628
|
-
"Usage: bun run atlas -- <init|diff|query|eval|smoke|migrate|plugin|benchmark|mcp> [options]\n\n" +
|
|
4689
|
+
"Usage: bun run atlas -- <init|diff|query|doctor|validate|eval|smoke|migrate|plugin|benchmark|mcp|completions> [options]\n\n" +
|
|
4629
4690
|
"Commands:\n" +
|
|
4630
|
-
" init
|
|
4631
|
-
" diff
|
|
4632
|
-
" query
|
|
4633
|
-
"
|
|
4634
|
-
"
|
|
4635
|
-
"
|
|
4636
|
-
"
|
|
4637
|
-
"
|
|
4638
|
-
"
|
|
4691
|
+
" init Profile DB and generate semantic layer\n" +
|
|
4692
|
+
" diff Compare DB schema against existing semantic layer\n" +
|
|
4693
|
+
" query Ask a question via the Atlas API\n" +
|
|
4694
|
+
" doctor Validate environment, connectivity, and configuration\n" +
|
|
4695
|
+
" validate Check config and semantic layer YAML files (offline)\n" +
|
|
4696
|
+
" eval Run eval pipeline against demo schemas\n" +
|
|
4697
|
+
" smoke Run E2E smoke tests against a running Atlas deployment\n" +
|
|
4698
|
+
" migrate Generate/apply plugin schema migrations\n" +
|
|
4699
|
+
" plugin Manage plugins (list, create, add)\n" +
|
|
4700
|
+
" benchmark Run BIRD benchmark for text-to-SQL accuracy\n" +
|
|
4701
|
+
" mcp Start MCP server (stdio default, --transport sse --port N for SSE)\n" +
|
|
4702
|
+
" completions Output shell completion script (bash, zsh, fish)\n\n" +
|
|
4639
4703
|
"Options (init):\n" +
|
|
4640
4704
|
" --tables t1,t2 Only specific tables/views\n" +
|
|
4641
4705
|
" --schema <name> PostgreSQL schema (default: public)\n" +
|
|
@@ -4645,7 +4709,7 @@ async function main() {
|
|
|
4645
4709
|
" --parquet f1.parquet[,...] Load Parquet files via DuckDB\n" +
|
|
4646
4710
|
" --enrich Profile + LLM enrichment (needs API key)\n" +
|
|
4647
4711
|
" --no-enrich Explicitly skip LLM enrichment\n" +
|
|
4648
|
-
" --demo [simple|cybersec] Load demo dataset then profile\n\n" +
|
|
4712
|
+
" --demo [simple|cybersec|ecommerce] Load demo dataset then profile\n\n" +
|
|
4649
4713
|
"Options (diff):\n" +
|
|
4650
4714
|
" --tables t1,t2 Only diff specific tables/views\n" +
|
|
4651
4715
|
" --schema <name> PostgreSQL schema (default: public)\n" +
|
|
@@ -1,40 +1,64 @@
|
|
|
1
|
-
version:
|
|
1
|
+
version: "1.0"
|
|
2
|
+
name: Atlas Demo — SaaS CRM
|
|
3
|
+
description: |
|
|
4
|
+
B2B SaaS company CRM dataset. Tracks companies (customers), the people who work
|
|
5
|
+
there (contacts), and subscription accounts with plan tiers and MRR.
|
|
6
|
+
Use this dataset to explore revenue analysis, customer segmentation,
|
|
7
|
+
churn patterns, and org-level reporting.
|
|
8
|
+
|
|
2
9
|
entities:
|
|
3
|
-
- name: Accounts
|
|
4
|
-
file: entities/accounts.yml
|
|
5
|
-
grain: one row per account record
|
|
6
|
-
description: accounts (80 rows, 7 columns)
|
|
7
|
-
use_for:
|
|
8
|
-
- Segmentation by plan, status
|
|
9
|
-
- Aggregation on monthly_value
|
|
10
|
-
- Cross-entity analysis via companies
|
|
11
|
-
common_questions:
|
|
12
|
-
- How many accounts by plan?
|
|
13
|
-
- How many accounts by status?
|
|
14
|
-
- What is the average monthly_value across accounts?
|
|
15
|
-
- How are accounts distributed across companies?
|
|
16
10
|
- name: Companies
|
|
17
11
|
file: entities/companies.yml
|
|
18
|
-
grain: one row per company
|
|
19
|
-
description:
|
|
12
|
+
grain: one row per customer company
|
|
13
|
+
description: >
|
|
14
|
+
Customer companies with firmographic data — industry, headcount,
|
|
15
|
+
geography, revenue, and valuation.
|
|
20
16
|
use_for:
|
|
21
|
-
-
|
|
17
|
+
- Firmographic segmentation (industry, country, company size)
|
|
18
|
+
- Revenue and valuation analysis
|
|
19
|
+
- Customer base composition
|
|
22
20
|
common_questions:
|
|
23
|
-
- What
|
|
21
|
+
- What industries make up our customer base?
|
|
22
|
+
- Which countries have the most customers?
|
|
23
|
+
- What is the average company revenue by industry?
|
|
24
|
+
- How many enterprise-size companies (500+ employees) do we have?
|
|
25
|
+
|
|
24
26
|
- name: People
|
|
25
27
|
file: entities/people.yml
|
|
26
|
-
grain: one row per
|
|
27
|
-
description:
|
|
28
|
+
grain: one row per contact
|
|
29
|
+
description: >
|
|
30
|
+
Contacts at customer companies — department, seniority, title,
|
|
31
|
+
and start date. Linked to companies via company_id.
|
|
32
|
+
use_for:
|
|
33
|
+
- Stakeholder mapping by department and seniority
|
|
34
|
+
- Org chart analysis per company
|
|
35
|
+
- Tenure and hiring trend analysis
|
|
36
|
+
common_questions:
|
|
37
|
+
- How many contacts do we have per company?
|
|
38
|
+
- What is the department breakdown across all contacts?
|
|
39
|
+
- Which companies have the most executive-level contacts?
|
|
40
|
+
- What seniority levels are most common?
|
|
41
|
+
|
|
42
|
+
- name: Accounts
|
|
43
|
+
file: entities/accounts.yml
|
|
44
|
+
grain: one row per subscription account
|
|
45
|
+
description: >
|
|
46
|
+
Subscription accounts with plan tier, billing status, MRR
|
|
47
|
+
(monthly_value), and contract dates. Linked to companies via company_id.
|
|
28
48
|
use_for:
|
|
29
|
-
-
|
|
30
|
-
-
|
|
49
|
+
- MRR and revenue analysis by plan
|
|
50
|
+
- Churn and retention analysis
|
|
51
|
+
- Contract lifecycle tracking
|
|
52
|
+
- Cross-entity analysis joining to companies and people
|
|
31
53
|
common_questions:
|
|
32
|
-
-
|
|
33
|
-
- How many
|
|
34
|
-
-
|
|
54
|
+
- What is total MRR by plan type?
|
|
55
|
+
- How many accounts are churned vs active?
|
|
56
|
+
- What is the average contract length?
|
|
57
|
+
- Which companies have the highest MRR?
|
|
58
|
+
|
|
35
59
|
glossary: glossary.yml
|
|
36
60
|
metrics:
|
|
37
61
|
- file: metrics/accounts.yml
|
|
38
|
-
description:
|
|
62
|
+
description: Subscription and revenue metrics (MRR, churn rate, ARPA)
|
|
39
63
|
- file: metrics/companies.yml
|
|
40
|
-
description:
|
|
64
|
+
description: Customer base metrics (count, avg revenue, industry breakdown)
|