@useatlas/create 0.0.1 → 0.0.3

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.
Files changed (298) hide show
  1. package/README.md +4 -18
  2. package/index.ts +191 -31
  3. package/package.json +1 -1
  4. package/templates/docker/.env.example +3 -3
  5. package/templates/docker/Dockerfile.sidecar +28 -0
  6. package/templates/docker/bin/__tests__/plugin-cli.test.ts +11 -11
  7. package/templates/docker/bin/atlas.ts +120 -56
  8. package/templates/docker/data/demo-semantic/catalog.yml +51 -27
  9. package/templates/docker/data/demo-semantic/entities/accounts.yml +95 -103
  10. package/templates/docker/data/demo-semantic/entities/companies.yml +88 -152
  11. package/templates/docker/data/demo-semantic/entities/people.yml +82 -95
  12. package/templates/docker/data/demo-semantic/glossary.yml +104 -8
  13. package/templates/docker/data/demo-semantic/metrics/accounts.yml +62 -23
  14. package/templates/docker/data/demo-semantic/metrics/companies.yml +52 -78
  15. package/templates/docker/docker-compose.yml +1 -1
  16. package/templates/docker/docs/deploy.md +4 -41
  17. package/templates/docker/package.json +17 -1
  18. package/templates/docker/semantic/catalog.yml +62 -3
  19. package/templates/docker/semantic/entities/accounts.yml +162 -0
  20. package/templates/docker/semantic/entities/companies.yml +143 -0
  21. package/templates/docker/semantic/entities/people.yml +132 -0
  22. package/templates/docker/semantic/glossary.yml +116 -4
  23. package/templates/docker/semantic/metrics/accounts.yml +77 -0
  24. package/templates/docker/semantic/metrics/companies.yml +63 -0
  25. package/templates/docker/sidecar/Dockerfile +5 -6
  26. package/templates/docker/sidecar/railway.json +1 -2
  27. package/templates/docker/src/api/__tests__/admin.test.ts +7 -7
  28. package/templates/docker/src/api/__tests__/health-plugin.test.ts +7 -0
  29. package/templates/docker/src/api/__tests__/health.test.ts +30 -8
  30. package/templates/docker/src/api/routes/admin.ts +549 -8
  31. package/templates/docker/src/api/routes/chat.ts +5 -20
  32. package/templates/docker/src/api/routes/health.ts +39 -27
  33. package/templates/docker/src/api/routes/openapi.ts +1329 -74
  34. package/templates/docker/src/api/routes/query.ts +2 -1
  35. package/templates/docker/src/api/server.ts +27 -0
  36. package/templates/docker/src/app/api/[...route]/route.ts +2 -2
  37. package/templates/docker/src/app/globals.css +13 -12
  38. package/templates/docker/src/app/layout.tsx +9 -2
  39. package/templates/docker/src/components/ui/alert-dialog.tsx +196 -0
  40. package/templates/docker/src/components/ui/badge.tsx +48 -0
  41. package/templates/docker/src/components/ui/button.tsx +64 -0
  42. package/templates/docker/src/components/ui/card.tsx +92 -0
  43. package/templates/docker/src/components/ui/collapsible.tsx +33 -0
  44. package/templates/docker/src/components/ui/command.tsx +184 -0
  45. package/templates/docker/src/components/ui/dialog.tsx +158 -0
  46. package/templates/docker/src/components/ui/dropdown-menu.tsx +257 -0
  47. package/templates/docker/src/components/ui/input.tsx +21 -0
  48. package/templates/docker/src/components/ui/scroll-area.tsx +58 -0
  49. package/templates/docker/src/components/ui/select.tsx +190 -0
  50. package/templates/docker/src/components/ui/separator.tsx +28 -0
  51. package/templates/docker/src/components/ui/sheet.tsx +143 -0
  52. package/templates/docker/src/components/ui/sidebar.tsx +726 -0
  53. package/templates/docker/src/components/ui/skeleton.tsx +13 -0
  54. package/templates/docker/src/components/ui/table.tsx +116 -0
  55. package/templates/docker/src/components/ui/tabs.tsx +91 -0
  56. package/templates/docker/src/components/ui/toggle-group.tsx +83 -0
  57. package/templates/docker/src/components/ui/toggle.tsx +47 -0
  58. package/templates/docker/src/components/ui/tooltip.tsx +57 -0
  59. package/templates/docker/src/hooks/use-mobile.ts +19 -0
  60. package/templates/docker/src/lib/__tests__/agent-cache.test.ts +2 -0
  61. package/templates/docker/src/lib/__tests__/agent-dialect.test.ts +17 -0
  62. package/templates/docker/src/lib/__tests__/agent-health-annotations.test.ts +2 -0
  63. package/templates/docker/src/lib/__tests__/agent-integration.test.ts +2 -0
  64. package/templates/docker/src/lib/__tests__/config.test.ts +69 -19
  65. package/templates/docker/src/lib/__tests__/plugin-aware-validation.test.ts +321 -0
  66. package/templates/docker/src/lib/__tests__/providers.test.ts +32 -1
  67. package/templates/docker/src/lib/__tests__/startup-actions.test.ts +9 -0
  68. package/templates/docker/src/lib/__tests__/startup-first-run.test.ts +429 -0
  69. package/templates/docker/src/lib/__tests__/startup.test.ts +5 -0
  70. package/templates/docker/src/lib/agent-query.ts +5 -23
  71. package/templates/docker/src/lib/agent.ts +32 -112
  72. package/templates/docker/src/lib/auth/__tests__/migrate.test.ts +5 -3
  73. package/templates/docker/src/lib/auth/middleware.ts +30 -4
  74. package/templates/docker/src/lib/auth/migrate.ts +97 -0
  75. package/templates/docker/src/lib/auth/server.ts +12 -1
  76. package/templates/docker/src/lib/config.ts +38 -40
  77. package/templates/docker/src/lib/db/__tests__/connection.test.ts +89 -14
  78. package/templates/docker/src/lib/db/__tests__/registry-health.test.ts +1 -18
  79. package/templates/docker/src/lib/db/__tests__/registry-pool-limits.test.ts +0 -19
  80. package/templates/docker/src/lib/db/__tests__/registry.test.ts +11 -208
  81. package/templates/docker/src/lib/db/connection.ts +87 -265
  82. package/templates/docker/src/lib/db/internal.ts +6 -1
  83. package/templates/docker/src/lib/plugins/__tests__/hooks-integration.test.ts +3 -1
  84. package/templates/docker/src/lib/plugins/__tests__/hooks.test.ts +2 -2
  85. package/templates/docker/src/lib/plugins/__tests__/migrate.test.ts +355 -1
  86. package/templates/docker/src/lib/plugins/__tests__/registry.test.ts +32 -5
  87. package/templates/docker/src/lib/plugins/__tests__/wiring.test.ts +228 -14
  88. package/templates/docker/src/lib/plugins/index.ts +4 -1
  89. package/templates/docker/src/lib/plugins/migrate.ts +104 -1
  90. package/templates/docker/src/lib/plugins/registry.ts +14 -8
  91. package/templates/docker/src/lib/plugins/wiring.ts +113 -4
  92. package/templates/docker/src/lib/providers.ts +6 -1
  93. package/templates/docker/src/lib/security.ts +24 -0
  94. package/templates/docker/src/lib/semantic.ts +2 -0
  95. package/templates/docker/src/lib/sidecar-types.ts +12 -1
  96. package/templates/docker/src/lib/startup.ts +71 -101
  97. package/templates/docker/src/lib/tools/__tests__/custom-validation.test.ts +2 -0
  98. package/templates/docker/src/lib/tools/__tests__/explore-nsjail.test.ts +32 -18
  99. package/templates/docker/src/lib/tools/__tests__/explore-plugin.test.ts +14 -14
  100. package/templates/docker/src/lib/tools/__tests__/explore-sdk-compat.test.ts +1 -1
  101. package/templates/docker/src/lib/tools/__tests__/explore-sidecar.test.ts +5 -3
  102. package/templates/docker/src/lib/tools/__tests__/python-nsjail.test.ts +515 -0
  103. package/templates/docker/src/lib/tools/__tests__/python-sandbox.test.ts +397 -0
  104. package/templates/docker/src/lib/tools/__tests__/python-sidecar.test.ts +365 -0
  105. package/templates/docker/src/lib/tools/__tests__/python.test.ts +331 -0
  106. package/templates/docker/src/lib/tools/__tests__/registry-actions.test.ts +1 -13
  107. package/templates/docker/src/lib/tools/__tests__/registry.test.ts +38 -31
  108. package/templates/docker/src/lib/tools/__tests__/sql-audit.test.ts +2 -0
  109. package/templates/docker/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +2 -0
  110. package/templates/docker/src/lib/tools/__tests__/sql-ratelimit.test.ts +2 -0
  111. package/templates/docker/src/lib/tools/__tests__/sql.test.ts +5 -308
  112. package/templates/docker/src/lib/tools/explore-nsjail.ts +17 -12
  113. package/templates/docker/src/lib/tools/explore-sidecar.ts +25 -0
  114. package/templates/docker/src/lib/tools/explore.ts +28 -32
  115. package/templates/docker/src/lib/tools/python-nsjail.ts +396 -0
  116. package/templates/docker/src/lib/tools/python-sandbox.ts +476 -0
  117. package/templates/docker/src/lib/tools/python-sidecar.ts +150 -0
  118. package/templates/docker/src/lib/tools/python.ts +367 -0
  119. package/templates/docker/src/lib/tools/registry.ts +49 -22
  120. package/templates/docker/src/lib/tools/sql.ts +88 -88
  121. package/templates/docker/src/types/vercel-sandbox.d.ts +7 -0
  122. package/templates/docker/src/ui/components/admin/admin-layout.tsx +77 -8
  123. package/templates/docker/src/ui/components/admin/admin-sidebar.tsx +25 -17
  124. package/templates/docker/src/ui/components/admin/change-password-dialog.tsx +128 -0
  125. package/templates/docker/src/ui/components/admin/entity-detail.tsx +3 -3
  126. package/templates/docker/src/ui/components/admin/semantic-file-tree.tsx +159 -0
  127. package/templates/docker/src/ui/components/atlas-chat.tsx +64 -12
  128. package/templates/docker/src/ui/components/chart/result-chart.tsx +25 -15
  129. package/templates/docker/src/ui/components/chat/markdown.tsx +88 -42
  130. package/templates/docker/src/ui/components/chat/python-result-card.tsx +244 -0
  131. package/templates/docker/src/ui/components/chat/sql-block.tsx +39 -15
  132. package/templates/docker/src/ui/components/chat/sql-result-card.tsx +6 -1
  133. package/templates/docker/src/ui/components/chat/tool-part.tsx +12 -3
  134. package/templates/docker/src/ui/components/chat/typing-indicator.tsx +5 -2
  135. package/templates/docker/src/ui/components/conversations/conversation-item.tsx +25 -20
  136. package/templates/docker/src/ui/context.tsx +1 -1
  137. package/templates/docker/src/ui/hooks/use-conversations.ts +3 -3
  138. package/templates/docker/src/ui/hooks/use-dark-mode.ts +17 -10
  139. package/templates/docker/tsconfig.json +2 -2
  140. package/templates/nextjs-standalone/.env.example +1 -1
  141. package/templates/nextjs-standalone/bin/__tests__/plugin-cli.test.ts +11 -11
  142. package/templates/nextjs-standalone/bin/atlas.ts +120 -56
  143. package/templates/nextjs-standalone/data/demo-semantic/catalog.yml +51 -27
  144. package/templates/nextjs-standalone/data/demo-semantic/entities/accounts.yml +95 -103
  145. package/templates/nextjs-standalone/data/demo-semantic/entities/companies.yml +88 -152
  146. package/templates/nextjs-standalone/data/demo-semantic/entities/people.yml +82 -95
  147. package/templates/nextjs-standalone/data/demo-semantic/glossary.yml +104 -8
  148. package/templates/nextjs-standalone/data/demo-semantic/metrics/accounts.yml +62 -23
  149. package/templates/nextjs-standalone/data/demo-semantic/metrics/companies.yml +52 -78
  150. package/templates/nextjs-standalone/docs/deploy.md +4 -41
  151. package/templates/nextjs-standalone/package.json +11 -2
  152. package/templates/nextjs-standalone/scripts/migrate-auth.ts +25 -0
  153. package/templates/nextjs-standalone/scripts/seed-demo.ts +94 -0
  154. package/templates/nextjs-standalone/semantic/catalog.yml +62 -3
  155. package/templates/nextjs-standalone/semantic/entities/accounts.yml +162 -0
  156. package/templates/nextjs-standalone/semantic/entities/companies.yml +143 -0
  157. package/templates/nextjs-standalone/semantic/entities/people.yml +132 -0
  158. package/templates/nextjs-standalone/semantic/glossary.yml +116 -4
  159. package/templates/nextjs-standalone/semantic/metrics/accounts.yml +77 -0
  160. package/templates/nextjs-standalone/semantic/metrics/companies.yml +63 -0
  161. package/templates/nextjs-standalone/src/api/__tests__/admin.test.ts +7 -7
  162. package/templates/nextjs-standalone/src/api/__tests__/health-plugin.test.ts +7 -0
  163. package/templates/nextjs-standalone/src/api/__tests__/health.test.ts +30 -8
  164. package/templates/nextjs-standalone/src/api/routes/admin.ts +549 -8
  165. package/templates/nextjs-standalone/src/api/routes/chat.ts +5 -20
  166. package/templates/nextjs-standalone/src/api/routes/health.ts +39 -27
  167. package/templates/nextjs-standalone/src/api/routes/openapi.ts +1329 -74
  168. package/templates/nextjs-standalone/src/api/routes/query.ts +2 -1
  169. package/templates/nextjs-standalone/src/api/server.ts +27 -0
  170. package/templates/nextjs-standalone/src/app/api/[...route]/route.ts +2 -2
  171. package/templates/nextjs-standalone/src/app/globals.css +13 -12
  172. package/templates/nextjs-standalone/src/app/layout.tsx +9 -2
  173. package/templates/nextjs-standalone/src/components/ui/alert-dialog.tsx +196 -0
  174. package/templates/nextjs-standalone/src/components/ui/badge.tsx +48 -0
  175. package/templates/nextjs-standalone/src/components/ui/button.tsx +64 -0
  176. package/templates/nextjs-standalone/src/components/ui/card.tsx +92 -0
  177. package/templates/nextjs-standalone/src/components/ui/collapsible.tsx +33 -0
  178. package/templates/nextjs-standalone/src/components/ui/command.tsx +184 -0
  179. package/templates/nextjs-standalone/src/components/ui/dialog.tsx +158 -0
  180. package/templates/nextjs-standalone/src/components/ui/dropdown-menu.tsx +257 -0
  181. package/templates/nextjs-standalone/src/components/ui/input.tsx +21 -0
  182. package/templates/nextjs-standalone/src/components/ui/scroll-area.tsx +58 -0
  183. package/templates/nextjs-standalone/src/components/ui/select.tsx +190 -0
  184. package/templates/nextjs-standalone/src/components/ui/separator.tsx +28 -0
  185. package/templates/nextjs-standalone/src/components/ui/sheet.tsx +143 -0
  186. package/templates/nextjs-standalone/src/components/ui/sidebar.tsx +726 -0
  187. package/templates/nextjs-standalone/src/components/ui/skeleton.tsx +13 -0
  188. package/templates/nextjs-standalone/src/components/ui/table.tsx +116 -0
  189. package/templates/nextjs-standalone/src/components/ui/tabs.tsx +91 -0
  190. package/templates/nextjs-standalone/src/components/ui/toggle-group.tsx +83 -0
  191. package/templates/nextjs-standalone/src/components/ui/toggle.tsx +47 -0
  192. package/templates/nextjs-standalone/src/components/ui/tooltip.tsx +57 -0
  193. package/templates/nextjs-standalone/src/hooks/use-mobile.ts +19 -0
  194. package/templates/nextjs-standalone/src/lib/__tests__/agent-cache.test.ts +2 -0
  195. package/templates/nextjs-standalone/src/lib/__tests__/agent-dialect.test.ts +17 -0
  196. package/templates/nextjs-standalone/src/lib/__tests__/agent-health-annotations.test.ts +2 -0
  197. package/templates/nextjs-standalone/src/lib/__tests__/agent-integration.test.ts +2 -0
  198. package/templates/nextjs-standalone/src/lib/__tests__/config.test.ts +69 -19
  199. package/templates/nextjs-standalone/src/lib/__tests__/plugin-aware-validation.test.ts +321 -0
  200. package/templates/nextjs-standalone/src/lib/__tests__/providers.test.ts +32 -1
  201. package/templates/nextjs-standalone/src/lib/__tests__/startup-actions.test.ts +9 -0
  202. package/templates/nextjs-standalone/src/lib/__tests__/startup-first-run.test.ts +429 -0
  203. package/templates/nextjs-standalone/src/lib/__tests__/startup.test.ts +5 -0
  204. package/templates/nextjs-standalone/src/lib/agent-query.ts +5 -23
  205. package/templates/nextjs-standalone/src/lib/agent.ts +32 -112
  206. package/templates/nextjs-standalone/src/lib/auth/__tests__/migrate.test.ts +5 -3
  207. package/templates/nextjs-standalone/src/lib/auth/middleware.ts +30 -4
  208. package/templates/nextjs-standalone/src/lib/auth/migrate.ts +97 -0
  209. package/templates/nextjs-standalone/src/lib/auth/server.ts +12 -1
  210. package/templates/nextjs-standalone/src/lib/config.ts +38 -40
  211. package/templates/nextjs-standalone/src/lib/db/__tests__/connection.test.ts +89 -14
  212. package/templates/nextjs-standalone/src/lib/db/__tests__/registry-health.test.ts +1 -18
  213. package/templates/nextjs-standalone/src/lib/db/__tests__/registry-pool-limits.test.ts +0 -19
  214. package/templates/nextjs-standalone/src/lib/db/__tests__/registry.test.ts +11 -208
  215. package/templates/nextjs-standalone/src/lib/db/connection.ts +87 -265
  216. package/templates/nextjs-standalone/src/lib/db/internal.ts +6 -1
  217. package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks-integration.test.ts +3 -1
  218. package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks.test.ts +2 -2
  219. package/templates/nextjs-standalone/src/lib/plugins/__tests__/migrate.test.ts +355 -1
  220. package/templates/nextjs-standalone/src/lib/plugins/__tests__/registry.test.ts +32 -5
  221. package/templates/nextjs-standalone/src/lib/plugins/__tests__/wiring.test.ts +228 -14
  222. package/templates/nextjs-standalone/src/lib/plugins/index.ts +4 -1
  223. package/templates/nextjs-standalone/src/lib/plugins/migrate.ts +104 -1
  224. package/templates/nextjs-standalone/src/lib/plugins/registry.ts +14 -8
  225. package/templates/nextjs-standalone/src/lib/plugins/wiring.ts +113 -4
  226. package/templates/nextjs-standalone/src/lib/providers.ts +6 -1
  227. package/templates/nextjs-standalone/src/lib/security.ts +24 -0
  228. package/templates/nextjs-standalone/src/lib/semantic.ts +2 -0
  229. package/templates/nextjs-standalone/src/lib/sidecar-types.ts +12 -1
  230. package/templates/nextjs-standalone/src/lib/startup.ts +71 -101
  231. package/templates/nextjs-standalone/src/lib/tools/__tests__/custom-validation.test.ts +2 -0
  232. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-nsjail.test.ts +32 -18
  233. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-plugin.test.ts +14 -14
  234. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sdk-compat.test.ts +1 -1
  235. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sidecar.test.ts +5 -3
  236. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-nsjail.test.ts +515 -0
  237. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sandbox.test.ts +397 -0
  238. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sidecar.test.ts +365 -0
  239. package/templates/nextjs-standalone/src/lib/tools/__tests__/python.test.ts +331 -0
  240. package/templates/nextjs-standalone/src/lib/tools/__tests__/registry-actions.test.ts +1 -13
  241. package/templates/nextjs-standalone/src/lib/tools/__tests__/registry.test.ts +38 -31
  242. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-audit.test.ts +2 -0
  243. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +2 -0
  244. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-ratelimit.test.ts +2 -0
  245. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql.test.ts +5 -308
  246. package/templates/nextjs-standalone/src/lib/tools/explore-nsjail.ts +17 -12
  247. package/templates/nextjs-standalone/src/lib/tools/explore-sidecar.ts +25 -0
  248. package/templates/nextjs-standalone/src/lib/tools/explore.ts +28 -32
  249. package/templates/nextjs-standalone/src/lib/tools/python-nsjail.ts +396 -0
  250. package/templates/nextjs-standalone/src/lib/tools/python-sandbox.ts +476 -0
  251. package/templates/nextjs-standalone/src/lib/tools/python-sidecar.ts +150 -0
  252. package/templates/nextjs-standalone/src/lib/tools/python.ts +367 -0
  253. package/templates/nextjs-standalone/src/lib/tools/registry.ts +49 -22
  254. package/templates/nextjs-standalone/src/lib/tools/sql.ts +88 -88
  255. package/templates/nextjs-standalone/src/ui/components/admin/admin-layout.tsx +77 -8
  256. package/templates/nextjs-standalone/src/ui/components/admin/admin-sidebar.tsx +25 -17
  257. package/templates/nextjs-standalone/src/ui/components/admin/change-password-dialog.tsx +128 -0
  258. package/templates/nextjs-standalone/src/ui/components/admin/entity-detail.tsx +3 -3
  259. package/templates/nextjs-standalone/src/ui/components/admin/semantic-file-tree.tsx +159 -0
  260. package/templates/nextjs-standalone/src/ui/components/atlas-chat.tsx +64 -12
  261. package/templates/nextjs-standalone/src/ui/components/chart/result-chart.tsx +25 -15
  262. package/templates/nextjs-standalone/src/ui/components/chat/markdown.tsx +88 -42
  263. package/templates/nextjs-standalone/src/ui/components/chat/python-result-card.tsx +244 -0
  264. package/templates/nextjs-standalone/src/ui/components/chat/sql-block.tsx +39 -15
  265. package/templates/nextjs-standalone/src/ui/components/chat/sql-result-card.tsx +6 -1
  266. package/templates/nextjs-standalone/src/ui/components/chat/tool-part.tsx +12 -3
  267. package/templates/nextjs-standalone/src/ui/components/chat/typing-indicator.tsx +5 -2
  268. package/templates/nextjs-standalone/src/ui/components/conversations/conversation-item.tsx +25 -20
  269. package/templates/nextjs-standalone/src/ui/context.tsx +1 -1
  270. package/templates/nextjs-standalone/src/ui/hooks/use-conversations.ts +3 -3
  271. package/templates/nextjs-standalone/src/ui/hooks/use-dark-mode.ts +17 -10
  272. package/templates/nextjs-standalone/tsconfig.json +0 -1
  273. package/templates/nextjs-standalone/vercel.json +4 -1
  274. package/templates/docker/render.yaml +0 -34
  275. package/templates/docker/semantic/entities/.gitkeep +0 -0
  276. package/templates/docker/semantic/metrics/.gitkeep +0 -0
  277. package/templates/docker/src/lib/db/__tests__/duckdb.test.ts +0 -141
  278. package/templates/docker/src/lib/db/__tests__/salesforce.test.ts +0 -339
  279. package/templates/docker/src/lib/db/__tests__/snowflake.test.ts +0 -217
  280. package/templates/docker/src/lib/db/duckdb.ts +0 -122
  281. package/templates/docker/src/lib/db/salesforce.ts +0 -342
  282. package/templates/docker/src/lib/tools/__tests__/salesforce-tool.test.ts +0 -154
  283. package/templates/docker/src/lib/tools/__tests__/soql-validation.test.ts +0 -303
  284. package/templates/docker/src/lib/tools/__tests__/sql-duckdb.test.ts +0 -233
  285. package/templates/docker/src/lib/tools/salesforce.ts +0 -138
  286. package/templates/docker/src/lib/tools/soql-validation.ts +0 -172
  287. package/templates/nextjs-standalone/semantic/entities/.gitkeep +0 -0
  288. package/templates/nextjs-standalone/semantic/metrics/.gitkeep +0 -0
  289. package/templates/nextjs-standalone/src/lib/db/__tests__/duckdb.test.ts +0 -141
  290. package/templates/nextjs-standalone/src/lib/db/__tests__/salesforce.test.ts +0 -339
  291. package/templates/nextjs-standalone/src/lib/db/__tests__/snowflake.test.ts +0 -217
  292. package/templates/nextjs-standalone/src/lib/db/duckdb.ts +0 -122
  293. package/templates/nextjs-standalone/src/lib/db/salesforce.ts +0 -342
  294. package/templates/nextjs-standalone/src/lib/tools/__tests__/salesforce-tool.test.ts +0 -154
  295. package/templates/nextjs-standalone/src/lib/tools/__tests__/soql-validation.test.ts +0 -303
  296. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-duckdb.test.ts +0 -233
  297. package/templates/nextjs-standalone/src/lib/tools/salesforce.ts +0 -138
  298. 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 { detectDBType, type DBType } from "@atlas/api/lib/db/connection";
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("@atlas/api/lib/db/connection");
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, createSalesforceDataSource } = await import("@atlas/api/lib/db/salesforce");
1405
+ const { parseSalesforceURL, createSalesforceConnection } = await import("../../../plugins/salesforce/src/connection");
1390
1406
  const config = parseSalesforceURL(connectionString);
1391
- const source = createSalesforceDataSource(config);
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, createSalesforceDataSource } = await import("@atlas/api/lib/db/salesforce");
1425
+ const { parseSalesforceURL, createSalesforceConnection } = await import("../../../plugins/salesforce/src/connection");
1409
1426
  const config = parseSalesforceURL(connectionString);
1410
- const source = createSalesforceDataSource(config);
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
- const columns: ColumnProfile[] = desc.fields.map((field) => {
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
- ? field.picklistValues.filter((pv) => pv.active).map((pv) => pv.value)
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
- type: string;
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
- type: String(p.type ?? "unknown"),
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.type,
3232
+ Type: info.types.join(", "),
3198
3233
  Version: info.version,
3199
3234
  Health:
3200
3235
  info.healthy === undefined
@@ -3225,12 +3260,12 @@ export function pluginTemplate(name: string, pluginType: ScaffoldPluginType): st
3225
3260
 
3226
3261
  switch (pluginType) {
3227
3262
  case "datasource":
3228
- return `import { definePlugin } from "@atlas/plugin-sdk";
3229
- import type { AtlasDatasourcePlugin, PluginDBConnection } from "@atlas/plugin-sdk";
3263
+ return `import { definePlugin } from "@useatlas/plugin-sdk";
3264
+ import type { AtlasDatasourcePlugin, PluginDBConnection } from "@useatlas/plugin-sdk";
3230
3265
 
3231
3266
  export default definePlugin({
3232
3267
  id: "${id}",
3233
- type: "datasource",
3268
+ types: ["datasource"],
3234
3269
  version: "0.1.0",
3235
3270
  name: "${pascalName}",
3236
3271
 
@@ -3254,12 +3289,12 @@ export default definePlugin({
3254
3289
  `;
3255
3290
 
3256
3291
  case "context":
3257
- return `import { definePlugin } from "@atlas/plugin-sdk";
3258
- import type { AtlasContextPlugin } from "@atlas/plugin-sdk";
3292
+ return `import { definePlugin } from "@useatlas/plugin-sdk";
3293
+ import type { AtlasContextPlugin } from "@useatlas/plugin-sdk";
3259
3294
 
3260
3295
  export default definePlugin({
3261
3296
  id: "${id}",
3262
- type: "context",
3297
+ types: ["context"],
3263
3298
  version: "0.1.0",
3264
3299
  name: "${pascalName}",
3265
3300
 
@@ -3284,13 +3319,13 @@ export default definePlugin({
3284
3319
  `;
3285
3320
 
3286
3321
  case "interaction":
3287
- return `import { definePlugin } from "@atlas/plugin-sdk";
3288
- import type { AtlasInteractionPlugin } from "@atlas/plugin-sdk";
3322
+ return `import { definePlugin } from "@useatlas/plugin-sdk";
3323
+ import type { AtlasInteractionPlugin } from "@useatlas/plugin-sdk";
3289
3324
  import type { Hono } from "hono";
3290
3325
 
3291
3326
  export default definePlugin({
3292
3327
  id: "${id}",
3293
- type: "interaction",
3328
+ types: ["interaction"],
3294
3329
  version: "0.1.0",
3295
3330
  name: "${pascalName}",
3296
3331
 
@@ -3310,14 +3345,14 @@ export default definePlugin({
3310
3345
  `;
3311
3346
 
3312
3347
  case "action":
3313
- return `import { definePlugin } from "@atlas/plugin-sdk";
3314
- import type { AtlasActionPlugin } from "@atlas/plugin-sdk";
3348
+ return `import { definePlugin } from "@useatlas/plugin-sdk";
3349
+ import type { AtlasActionPlugin } from "@useatlas/plugin-sdk";
3315
3350
  import { tool } from "ai";
3316
3351
  import { z } from "zod";
3317
3352
 
3318
3353
  export default definePlugin({
3319
3354
  id: "${id}",
3320
- type: "action",
3355
+ types: ["action"],
3321
3356
  version: "0.1.0",
3322
3357
  name: "${pascalName}",
3323
3358
 
@@ -3353,12 +3388,12 @@ export default definePlugin({
3353
3388
  `;
3354
3389
 
3355
3390
  case "sandbox":
3356
- return `import { definePlugin } from "@atlas/plugin-sdk";
3357
- import type { AtlasSandboxPlugin, PluginExploreBackend, PluginExecResult } from "@atlas/plugin-sdk";
3391
+ return `import { definePlugin } from "@useatlas/plugin-sdk";
3392
+ import type { AtlasSandboxPlugin, PluginExploreBackend, PluginExecResult } from "@useatlas/plugin-sdk";
3358
3393
 
3359
3394
  export default definePlugin({
3360
3395
  id: "${id}",
3361
- type: "sandbox",
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.type).toBe("${pluginType}");
3436
+ expect(plugin.types).toContain("${pluginType}");
3402
3437
  });
3403
3438
 
3404
3439
  test("has a version string", () => {
@@ -3426,10 +3461,10 @@ export function pluginPackageJsonTemplate(name: string): string {
3426
3461
  test: "bun test src/index.test.ts",
3427
3462
  },
3428
3463
  peerDependencies: {
3429
- "@atlas/plugin-sdk": "workspace:*",
3464
+ "@useatlas/plugin-sdk": "workspace:*",
3430
3465
  },
3431
3466
  devDependencies: {
3432
- "@atlas/plugin-sdk": "workspace:*",
3467
+ "@useatlas/plugin-sdk": "workspace:*",
3433
3468
  },
3434
3469
  },
3435
3470
  null,
@@ -3890,9 +3925,10 @@ async function handleDiff(args: string[]): Promise<void> {
3890
3925
  }
3891
3926
  }
3892
3927
  } else if (dbType === "salesforce") {
3893
- const { parseSalesforceURL, createSalesforceDataSource } = await import("@atlas/api/lib/db/salesforce");
3928
+ const { parseSalesforceURL, createSalesforceConnection } = await import("../../../plugins/salesforce/src/connection");
3894
3929
  const config = parseSalesforceURL(connStr);
3895
- const source = createSalesforceDataSource(config);
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("@atlas/api/lib/db/duckdb");
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
- const _exhaustive: never = dbType;
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("@atlas/api/lib/db/duckdb");
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, createSalesforceDataSource } = await import("@atlas/api/lib/db/salesforce");
4194
+ const { parseSalesforceURL, createSalesforceConnection } = await import("../../../plugins/salesforce/src/connection");
4160
4195
  const config = parseSalesforceURL(connStr);
4161
- const source = createSalesforceDataSource(config);
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("@atlas/api/lib/db/duckdb");
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
- const _exhaustive: never = dbType;
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("@atlas/api/lib/db/duckdb");
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
- const _exhaustive: never = dbType;
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 Profile DB and generate semantic layer\n" +
4631
- " diff Compare DB schema against existing semantic layer\n" +
4632
- " query Ask a question via the Atlas API\n" +
4633
- " eval Run eval pipeline against demo schemas\n" +
4634
- " smoke Run E2E smoke tests against a running Atlas deployment\n" +
4635
- " migrate Generate/apply plugin schema migrations\n" +
4636
- " plugin Manage plugins (list, create, add)\n" +
4637
- " benchmark Run BIRD benchmark for text-to-SQL accuracy\n" +
4638
- " mcp Start MCP server (stdio default, --transport sse --port N for SSE)\n\n" +
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.0'
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 record
19
- description: companies (50 rows, 8 columns)
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
- - Aggregation on employee_count, founded_year, revenue, valuation
17
+ - Firmographic segmentation (industry, country, company size)
18
+ - Revenue and valuation analysis
19
+ - Customer base composition
22
20
  common_questions:
23
- - What is the average employee_count across companies?
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 person record
27
- description: people (198 rows, 8 columns)
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
- - Segmentation by department, seniority
30
- - Cross-entity analysis via companies
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
- - How many people by department?
33
- - How many people by seniority?
34
- - How are people distributed across companies?
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: Auto-generated metrics for accounts
62
+ description: Subscription and revenue metrics (MRR, churn rate, ARPA)
39
63
  - file: metrics/companies.yml
40
- description: Auto-generated metrics for companies
64
+ description: Customer base metrics (count, avg revenue, industry breakdown)