@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.
Files changed (296) 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 +9 -9
  7. package/templates/docker/bin/atlas.ts +108 -44
  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 +2 -39
  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 +37 -39
  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 +103 -0
  90. package/templates/docker/src/lib/plugins/registry.ts +12 -6
  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-sidecar.test.ts +5 -3
  101. package/templates/docker/src/lib/tools/__tests__/python-nsjail.test.ts +515 -0
  102. package/templates/docker/src/lib/tools/__tests__/python-sandbox.test.ts +397 -0
  103. package/templates/docker/src/lib/tools/__tests__/python-sidecar.test.ts +365 -0
  104. package/templates/docker/src/lib/tools/__tests__/python.test.ts +331 -0
  105. package/templates/docker/src/lib/tools/__tests__/registry-actions.test.ts +1 -13
  106. package/templates/docker/src/lib/tools/__tests__/registry.test.ts +38 -31
  107. package/templates/docker/src/lib/tools/__tests__/sql-audit.test.ts +2 -0
  108. package/templates/docker/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +2 -0
  109. package/templates/docker/src/lib/tools/__tests__/sql-ratelimit.test.ts +2 -0
  110. package/templates/docker/src/lib/tools/__tests__/sql.test.ts +5 -308
  111. package/templates/docker/src/lib/tools/explore-nsjail.ts +17 -12
  112. package/templates/docker/src/lib/tools/explore-sidecar.ts +25 -0
  113. package/templates/docker/src/lib/tools/explore.ts +28 -32
  114. package/templates/docker/src/lib/tools/python-nsjail.ts +396 -0
  115. package/templates/docker/src/lib/tools/python-sandbox.ts +476 -0
  116. package/templates/docker/src/lib/tools/python-sidecar.ts +150 -0
  117. package/templates/docker/src/lib/tools/python.ts +367 -0
  118. package/templates/docker/src/lib/tools/registry.ts +49 -22
  119. package/templates/docker/src/lib/tools/sql.ts +88 -88
  120. package/templates/docker/src/types/vercel-sandbox.d.ts +7 -0
  121. package/templates/docker/src/ui/components/admin/admin-layout.tsx +77 -8
  122. package/templates/docker/src/ui/components/admin/admin-sidebar.tsx +25 -17
  123. package/templates/docker/src/ui/components/admin/change-password-dialog.tsx +128 -0
  124. package/templates/docker/src/ui/components/admin/entity-detail.tsx +3 -3
  125. package/templates/docker/src/ui/components/admin/semantic-file-tree.tsx +159 -0
  126. package/templates/docker/src/ui/components/atlas-chat.tsx +64 -12
  127. package/templates/docker/src/ui/components/chart/result-chart.tsx +25 -15
  128. package/templates/docker/src/ui/components/chat/markdown.tsx +88 -42
  129. package/templates/docker/src/ui/components/chat/python-result-card.tsx +244 -0
  130. package/templates/docker/src/ui/components/chat/sql-block.tsx +39 -15
  131. package/templates/docker/src/ui/components/chat/sql-result-card.tsx +6 -1
  132. package/templates/docker/src/ui/components/chat/tool-part.tsx +12 -3
  133. package/templates/docker/src/ui/components/chat/typing-indicator.tsx +5 -2
  134. package/templates/docker/src/ui/components/conversations/conversation-item.tsx +25 -20
  135. package/templates/docker/src/ui/context.tsx +1 -1
  136. package/templates/docker/src/ui/hooks/use-conversations.ts +3 -3
  137. package/templates/docker/src/ui/hooks/use-dark-mode.ts +17 -10
  138. package/templates/docker/tsconfig.json +2 -2
  139. package/templates/nextjs-standalone/.env.example +1 -1
  140. package/templates/nextjs-standalone/bin/__tests__/plugin-cli.test.ts +9 -9
  141. package/templates/nextjs-standalone/bin/atlas.ts +108 -44
  142. package/templates/nextjs-standalone/data/demo-semantic/catalog.yml +51 -27
  143. package/templates/nextjs-standalone/data/demo-semantic/entities/accounts.yml +95 -103
  144. package/templates/nextjs-standalone/data/demo-semantic/entities/companies.yml +88 -152
  145. package/templates/nextjs-standalone/data/demo-semantic/entities/people.yml +82 -95
  146. package/templates/nextjs-standalone/data/demo-semantic/glossary.yml +104 -8
  147. package/templates/nextjs-standalone/data/demo-semantic/metrics/accounts.yml +62 -23
  148. package/templates/nextjs-standalone/data/demo-semantic/metrics/companies.yml +52 -78
  149. package/templates/nextjs-standalone/docs/deploy.md +2 -39
  150. package/templates/nextjs-standalone/package.json +11 -2
  151. package/templates/nextjs-standalone/scripts/migrate-auth.ts +25 -0
  152. package/templates/nextjs-standalone/scripts/seed-demo.ts +94 -0
  153. package/templates/nextjs-standalone/semantic/catalog.yml +62 -3
  154. package/templates/nextjs-standalone/semantic/entities/accounts.yml +162 -0
  155. package/templates/nextjs-standalone/semantic/entities/companies.yml +143 -0
  156. package/templates/nextjs-standalone/semantic/entities/people.yml +132 -0
  157. package/templates/nextjs-standalone/semantic/glossary.yml +116 -4
  158. package/templates/nextjs-standalone/semantic/metrics/accounts.yml +77 -0
  159. package/templates/nextjs-standalone/semantic/metrics/companies.yml +63 -0
  160. package/templates/nextjs-standalone/src/api/__tests__/admin.test.ts +7 -7
  161. package/templates/nextjs-standalone/src/api/__tests__/health-plugin.test.ts +7 -0
  162. package/templates/nextjs-standalone/src/api/__tests__/health.test.ts +30 -8
  163. package/templates/nextjs-standalone/src/api/routes/admin.ts +549 -8
  164. package/templates/nextjs-standalone/src/api/routes/chat.ts +5 -20
  165. package/templates/nextjs-standalone/src/api/routes/health.ts +39 -27
  166. package/templates/nextjs-standalone/src/api/routes/openapi.ts +1329 -74
  167. package/templates/nextjs-standalone/src/api/routes/query.ts +2 -1
  168. package/templates/nextjs-standalone/src/api/server.ts +27 -0
  169. package/templates/nextjs-standalone/src/app/api/[...route]/route.ts +2 -2
  170. package/templates/nextjs-standalone/src/app/globals.css +13 -12
  171. package/templates/nextjs-standalone/src/app/layout.tsx +9 -2
  172. package/templates/nextjs-standalone/src/components/ui/alert-dialog.tsx +196 -0
  173. package/templates/nextjs-standalone/src/components/ui/badge.tsx +48 -0
  174. package/templates/nextjs-standalone/src/components/ui/button.tsx +64 -0
  175. package/templates/nextjs-standalone/src/components/ui/card.tsx +92 -0
  176. package/templates/nextjs-standalone/src/components/ui/collapsible.tsx +33 -0
  177. package/templates/nextjs-standalone/src/components/ui/command.tsx +184 -0
  178. package/templates/nextjs-standalone/src/components/ui/dialog.tsx +158 -0
  179. package/templates/nextjs-standalone/src/components/ui/dropdown-menu.tsx +257 -0
  180. package/templates/nextjs-standalone/src/components/ui/input.tsx +21 -0
  181. package/templates/nextjs-standalone/src/components/ui/scroll-area.tsx +58 -0
  182. package/templates/nextjs-standalone/src/components/ui/select.tsx +190 -0
  183. package/templates/nextjs-standalone/src/components/ui/separator.tsx +28 -0
  184. package/templates/nextjs-standalone/src/components/ui/sheet.tsx +143 -0
  185. package/templates/nextjs-standalone/src/components/ui/sidebar.tsx +726 -0
  186. package/templates/nextjs-standalone/src/components/ui/skeleton.tsx +13 -0
  187. package/templates/nextjs-standalone/src/components/ui/table.tsx +116 -0
  188. package/templates/nextjs-standalone/src/components/ui/tabs.tsx +91 -0
  189. package/templates/nextjs-standalone/src/components/ui/toggle-group.tsx +83 -0
  190. package/templates/nextjs-standalone/src/components/ui/toggle.tsx +47 -0
  191. package/templates/nextjs-standalone/src/components/ui/tooltip.tsx +57 -0
  192. package/templates/nextjs-standalone/src/hooks/use-mobile.ts +19 -0
  193. package/templates/nextjs-standalone/src/lib/__tests__/agent-cache.test.ts +2 -0
  194. package/templates/nextjs-standalone/src/lib/__tests__/agent-dialect.test.ts +17 -0
  195. package/templates/nextjs-standalone/src/lib/__tests__/agent-health-annotations.test.ts +2 -0
  196. package/templates/nextjs-standalone/src/lib/__tests__/agent-integration.test.ts +2 -0
  197. package/templates/nextjs-standalone/src/lib/__tests__/config.test.ts +69 -19
  198. package/templates/nextjs-standalone/src/lib/__tests__/plugin-aware-validation.test.ts +321 -0
  199. package/templates/nextjs-standalone/src/lib/__tests__/providers.test.ts +32 -1
  200. package/templates/nextjs-standalone/src/lib/__tests__/startup-actions.test.ts +9 -0
  201. package/templates/nextjs-standalone/src/lib/__tests__/startup-first-run.test.ts +429 -0
  202. package/templates/nextjs-standalone/src/lib/__tests__/startup.test.ts +5 -0
  203. package/templates/nextjs-standalone/src/lib/agent-query.ts +5 -23
  204. package/templates/nextjs-standalone/src/lib/agent.ts +32 -112
  205. package/templates/nextjs-standalone/src/lib/auth/__tests__/migrate.test.ts +5 -3
  206. package/templates/nextjs-standalone/src/lib/auth/middleware.ts +30 -4
  207. package/templates/nextjs-standalone/src/lib/auth/migrate.ts +97 -0
  208. package/templates/nextjs-standalone/src/lib/auth/server.ts +12 -1
  209. package/templates/nextjs-standalone/src/lib/config.ts +37 -39
  210. package/templates/nextjs-standalone/src/lib/db/__tests__/connection.test.ts +89 -14
  211. package/templates/nextjs-standalone/src/lib/db/__tests__/registry-health.test.ts +1 -18
  212. package/templates/nextjs-standalone/src/lib/db/__tests__/registry-pool-limits.test.ts +0 -19
  213. package/templates/nextjs-standalone/src/lib/db/__tests__/registry.test.ts +11 -208
  214. package/templates/nextjs-standalone/src/lib/db/connection.ts +87 -265
  215. package/templates/nextjs-standalone/src/lib/db/internal.ts +6 -1
  216. package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks-integration.test.ts +3 -1
  217. package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks.test.ts +2 -2
  218. package/templates/nextjs-standalone/src/lib/plugins/__tests__/migrate.test.ts +355 -1
  219. package/templates/nextjs-standalone/src/lib/plugins/__tests__/registry.test.ts +32 -5
  220. package/templates/nextjs-standalone/src/lib/plugins/__tests__/wiring.test.ts +228 -14
  221. package/templates/nextjs-standalone/src/lib/plugins/index.ts +4 -1
  222. package/templates/nextjs-standalone/src/lib/plugins/migrate.ts +103 -0
  223. package/templates/nextjs-standalone/src/lib/plugins/registry.ts +12 -6
  224. package/templates/nextjs-standalone/src/lib/plugins/wiring.ts +113 -4
  225. package/templates/nextjs-standalone/src/lib/providers.ts +6 -1
  226. package/templates/nextjs-standalone/src/lib/security.ts +24 -0
  227. package/templates/nextjs-standalone/src/lib/semantic.ts +2 -0
  228. package/templates/nextjs-standalone/src/lib/sidecar-types.ts +12 -1
  229. package/templates/nextjs-standalone/src/lib/startup.ts +71 -101
  230. package/templates/nextjs-standalone/src/lib/tools/__tests__/custom-validation.test.ts +2 -0
  231. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-nsjail.test.ts +32 -18
  232. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-plugin.test.ts +14 -14
  233. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sidecar.test.ts +5 -3
  234. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-nsjail.test.ts +515 -0
  235. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sandbox.test.ts +397 -0
  236. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sidecar.test.ts +365 -0
  237. package/templates/nextjs-standalone/src/lib/tools/__tests__/python.test.ts +331 -0
  238. package/templates/nextjs-standalone/src/lib/tools/__tests__/registry-actions.test.ts +1 -13
  239. package/templates/nextjs-standalone/src/lib/tools/__tests__/registry.test.ts +38 -31
  240. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-audit.test.ts +2 -0
  241. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +2 -0
  242. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-ratelimit.test.ts +2 -0
  243. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql.test.ts +5 -308
  244. package/templates/nextjs-standalone/src/lib/tools/explore-nsjail.ts +17 -12
  245. package/templates/nextjs-standalone/src/lib/tools/explore-sidecar.ts +25 -0
  246. package/templates/nextjs-standalone/src/lib/tools/explore.ts +28 -32
  247. package/templates/nextjs-standalone/src/lib/tools/python-nsjail.ts +396 -0
  248. package/templates/nextjs-standalone/src/lib/tools/python-sandbox.ts +476 -0
  249. package/templates/nextjs-standalone/src/lib/tools/python-sidecar.ts +150 -0
  250. package/templates/nextjs-standalone/src/lib/tools/python.ts +367 -0
  251. package/templates/nextjs-standalone/src/lib/tools/registry.ts +49 -22
  252. package/templates/nextjs-standalone/src/lib/tools/sql.ts +88 -88
  253. package/templates/nextjs-standalone/src/ui/components/admin/admin-layout.tsx +77 -8
  254. package/templates/nextjs-standalone/src/ui/components/admin/admin-sidebar.tsx +25 -17
  255. package/templates/nextjs-standalone/src/ui/components/admin/change-password-dialog.tsx +128 -0
  256. package/templates/nextjs-standalone/src/ui/components/admin/entity-detail.tsx +3 -3
  257. package/templates/nextjs-standalone/src/ui/components/admin/semantic-file-tree.tsx +159 -0
  258. package/templates/nextjs-standalone/src/ui/components/atlas-chat.tsx +64 -12
  259. package/templates/nextjs-standalone/src/ui/components/chart/result-chart.tsx +25 -15
  260. package/templates/nextjs-standalone/src/ui/components/chat/markdown.tsx +88 -42
  261. package/templates/nextjs-standalone/src/ui/components/chat/python-result-card.tsx +244 -0
  262. package/templates/nextjs-standalone/src/ui/components/chat/sql-block.tsx +39 -15
  263. package/templates/nextjs-standalone/src/ui/components/chat/sql-result-card.tsx +6 -1
  264. package/templates/nextjs-standalone/src/ui/components/chat/tool-part.tsx +12 -3
  265. package/templates/nextjs-standalone/src/ui/components/chat/typing-indicator.tsx +5 -2
  266. package/templates/nextjs-standalone/src/ui/components/conversations/conversation-item.tsx +25 -20
  267. package/templates/nextjs-standalone/src/ui/context.tsx +1 -1
  268. package/templates/nextjs-standalone/src/ui/hooks/use-conversations.ts +3 -3
  269. package/templates/nextjs-standalone/src/ui/hooks/use-dark-mode.ts +17 -10
  270. package/templates/nextjs-standalone/tsconfig.json +0 -1
  271. package/templates/nextjs-standalone/vercel.json +4 -1
  272. package/templates/docker/render.yaml +0 -34
  273. package/templates/docker/semantic/entities/.gitkeep +0 -0
  274. package/templates/docker/semantic/metrics/.gitkeep +0 -0
  275. package/templates/docker/src/lib/db/__tests__/duckdb.test.ts +0 -141
  276. package/templates/docker/src/lib/db/__tests__/salesforce.test.ts +0 -339
  277. package/templates/docker/src/lib/db/__tests__/snowflake.test.ts +0 -217
  278. package/templates/docker/src/lib/db/duckdb.ts +0 -122
  279. package/templates/docker/src/lib/db/salesforce.ts +0 -342
  280. package/templates/docker/src/lib/tools/__tests__/salesforce-tool.test.ts +0 -154
  281. package/templates/docker/src/lib/tools/__tests__/soql-validation.test.ts +0 -303
  282. package/templates/docker/src/lib/tools/__tests__/sql-duckdb.test.ts +0 -233
  283. package/templates/docker/src/lib/tools/salesforce.ts +0 -138
  284. package/templates/docker/src/lib/tools/soql-validation.ts +0 -172
  285. package/templates/nextjs-standalone/semantic/entities/.gitkeep +0 -0
  286. package/templates/nextjs-standalone/semantic/metrics/.gitkeep +0 -0
  287. package/templates/nextjs-standalone/src/lib/db/__tests__/duckdb.test.ts +0 -141
  288. package/templates/nextjs-standalone/src/lib/db/__tests__/salesforce.test.ts +0 -339
  289. package/templates/nextjs-standalone/src/lib/db/__tests__/snowflake.test.ts +0 -217
  290. package/templates/nextjs-standalone/src/lib/db/duckdb.ts +0 -122
  291. package/templates/nextjs-standalone/src/lib/db/salesforce.ts +0 -342
  292. package/templates/nextjs-standalone/src/lib/tools/__tests__/salesforce-tool.test.ts +0 -154
  293. package/templates/nextjs-standalone/src/lib/tools/__tests__/soql-validation.test.ts +0 -303
  294. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-duckdb.test.ts +0 -233
  295. package/templates/nextjs-standalone/src/lib/tools/salesforce.ts +0 -138
  296. package/templates/nextjs-standalone/src/lib/tools/soql-validation.ts +0 -172
@@ -19,19 +19,24 @@
19
19
  "@ai-sdk/react": "^3.0.99",
20
20
  "ai": "^6.0.97",
21
21
  "@better-auth/api-key": "^1.5.1",
22
- "clsx": "^2.1.1",
23
22
  "better-auth": "^1.5.1",
23
+ "class-variance-authority": "^0.7.1",
24
+ "clsx": "^2.1.1",
25
+ "cmdk": "^1.1.1",
26
+ "croner": "^9.0.0",
24
27
  "hono": "^4.12.3",
25
28
  "jose": "^6.1.3",
26
29
  "js-yaml": "^4.1.1",
27
30
  "just-bash": "^2.10.2",
28
- "lucide-react": "^0.576.0",
31
+ "lucide-react": "^0.577.0",
29
32
  "mysql2": "^3.18.0",
30
33
  "next": "^16.1.6",
31
34
  "node-sql-parser": "^5.4.0",
35
+ "nuqs": "^2.8.9",
32
36
  "pg": "^8.18.0",
33
37
  "pino": "^10.3.1",
34
38
  "pino-pretty": "^13.1.3",
39
+ "radix-ui": "^1.4.3",
35
40
  "react": "^19.2.4",
36
41
  "react-dom": "^19.2.4",
37
42
  "react-markdown": "^10.1.0",
@@ -45,6 +50,7 @@
45
50
  "@vercel/sandbox": "^1"
46
51
  },
47
52
  "devDependencies": {
53
+ "@clack/prompts": "^0.10.0",
48
54
  "@eslint/js": "^10.0.1",
49
55
  "@next/eslint-plugin-next": "^16.1.6",
50
56
  "@tailwindcss/postcss": "^4.2.1",
@@ -54,9 +60,12 @@
54
60
  "@types/react": "^19.2.14",
55
61
  "@types/react-dom": "^19.2.3",
56
62
  "@types/react-syntax-highlighter": "^15.5.13",
63
+ "@types/bun": "^1.3.9",
57
64
  "@typescript/native-preview": "^7.0.0-dev.20260226.1",
58
65
  "eslint": "^10.0.2",
59
66
  "tailwindcss": "^4.2.1",
67
+ "shadcn": "^3.8.5",
68
+ "picocolors": "^1.1.0",
60
69
  "typescript": "^5.9.3",
61
70
  "typescript-eslint": "^8.56.1"
62
71
  }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Build-time auth migration for Vercel deployments.
3
+ *
4
+ * On Vercel, there is no persistent server boot — the Hono app runs inside
5
+ * a serverless catch-all route. The standalone server (server.ts) normally
6
+ * calls migrateAuthTables() at boot, but that code path is never hit on
7
+ * Vercel. This script bridges the gap by running the same migration at
8
+ * build time, right after seed-demo.ts.
9
+ *
10
+ * Creates Better Auth tables (user, session, account, etc.), the audit_log
11
+ * table, and seeds a dev admin account when ATLAS_ADMIN_EMAIL is set.
12
+ */
13
+
14
+ import { migrateAuthTables } from "@atlas/api/lib/auth/migrate";
15
+
16
+ try {
17
+ await migrateAuthTables();
18
+ console.log("migrate-auth: complete");
19
+ } catch (err) {
20
+ console.error(
21
+ "migrate-auth: failed —",
22
+ err instanceof Error ? err.stack : err,
23
+ );
24
+ process.exit(1);
25
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Build-time demo data seeder for Vercel deployments.
3
+ *
4
+ * When ATLAS_DEMO_DATA=true, seeds the Neon-provisioned database with demo
5
+ * data (companies, people, accounts — ~30KB). Idempotent: skips if data
6
+ * already exists. Runs during `next build` on Vercel.
7
+ *
8
+ * Resolves the database URL from DATABASE_URL_UNPOOLED or DATABASE_URL
9
+ * (set automatically by Neon's Vercel integration).
10
+ */
11
+
12
+ import { readFileSync } from "fs";
13
+ import { resolve } from "path";
14
+ import pg from "pg";
15
+
16
+ if (process.env.ATLAS_DEMO_DATA !== "true") {
17
+ console.log("seed-demo: ATLAS_DEMO_DATA is not 'true' — skipping");
18
+ process.exit(0);
19
+ }
20
+
21
+ // Prefer unpooled for DDL/migrations (PgBouncer can interfere with multi-statement transactions)
22
+ const url = process.env.DATABASE_URL_UNPOOLED || process.env.DATABASE_URL;
23
+ if (!url) {
24
+ console.error("seed-demo: no DATABASE_URL or DATABASE_URL_UNPOOLED — cannot seed");
25
+ process.exit(1);
26
+ }
27
+
28
+ // Normalize sslmode: pg v8 treats 'require' as 'verify-full' but warns about it.
29
+ const connString = url.replace(
30
+ /([?&])sslmode=require(?=&|$)/,
31
+ "$1sslmode=verify-full",
32
+ );
33
+
34
+ const client = new pg.Client({
35
+ connectionString: connString,
36
+ connectionTimeoutMillis: 10_000,
37
+ });
38
+
39
+ try {
40
+ await client.connect();
41
+
42
+ // Check if demo data already exists
43
+ const result = await client.query(`
44
+ SELECT EXISTS (
45
+ SELECT 1 FROM information_schema.tables
46
+ WHERE table_schema = 'public' AND table_name = 'companies'
47
+ ) AS table_exists
48
+ `);
49
+
50
+ if (result.rows[0]?.table_exists) {
51
+ const count = await client.query("SELECT count(*) AS n FROM companies");
52
+ if (parseInt(count.rows[0]?.n ?? "0", 10) > 0) {
53
+ console.log("seed-demo: demo data already exists, skipping");
54
+ await client.end();
55
+ process.exit(0);
56
+ }
57
+ console.log("seed-demo: companies table exists but is empty, re-seeding...");
58
+ }
59
+
60
+ // Read the seed SQL
61
+ const sqlPath = resolve(import.meta.dirname, "../data/demo.sql");
62
+ let sql: string;
63
+ try {
64
+ sql = readFileSync(sqlPath, "utf-8");
65
+ } catch (err) {
66
+ throw new Error(
67
+ `Failed to read ${sqlPath}: ${err instanceof Error ? err.message : err}`
68
+ );
69
+ }
70
+
71
+ // Execute inside a transaction
72
+ await client.query("BEGIN");
73
+ try {
74
+ await client.query(sql);
75
+ await client.query("COMMIT");
76
+ } catch (err) {
77
+ try { await client.query("ROLLBACK"); } catch (rollbackErr) {
78
+ console.warn("seed-demo: ROLLBACK failed —", rollbackErr instanceof Error ? rollbackErr.message : rollbackErr);
79
+ }
80
+ throw err;
81
+ }
82
+
83
+ const verify = await client.query("SELECT count(*) AS n FROM companies");
84
+ console.log(`seed-demo: seeded ${verify.rows[0]?.n ?? 0} companies successfully`);
85
+
86
+ await client.end();
87
+ process.exit(0);
88
+ } catch (err) {
89
+ console.error("seed-demo: failed —", err instanceof Error ? err.stack : err);
90
+ try { await client.end(); } catch (cleanupErr) {
91
+ console.warn("seed-demo: cleanup failed —", cleanupErr instanceof Error ? cleanupErr.message : cleanupErr);
92
+ }
93
+ process.exit(1);
94
+ }
@@ -1,5 +1,64 @@
1
- # Atlas Semantic Layer — Catalog
2
- # Run `bun run atlas -- init` to auto-generate from your database.
3
1
  version: "1.0"
4
- entities: []
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
+
9
+ entities:
10
+ - name: Companies
11
+ file: entities/companies.yml
12
+ grain: one row per customer company
13
+ description: >
14
+ Customer companies with firmographic data — industry, headcount,
15
+ geography, revenue, and valuation.
16
+ use_for:
17
+ - Firmographic segmentation (industry, country, company size)
18
+ - Revenue and valuation analysis
19
+ - Customer base composition
20
+ common_questions:
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
+
26
+ - name: People
27
+ file: entities/people.yml
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.
48
+ use_for:
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
53
+ common_questions:
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
+
5
59
  glossary: glossary.yml
60
+ metrics:
61
+ - file: metrics/accounts.yml
62
+ description: Subscription and revenue metrics (MRR, churn rate, ARPA)
63
+ - file: metrics/companies.yml
64
+ description: Customer base metrics (count, avg revenue, industry breakdown)
@@ -0,0 +1,162 @@
1
+ name: Accounts
2
+ type: fact_table
3
+ table: accounts
4
+ grain: one row per subscription account
5
+ description: |
6
+ Subscription accounts representing our billing relationship with each customer.
7
+ Each account belongs to one company and has a plan tier (Free, Starter, Pro,
8
+ Enterprise), a billing status (Active, Inactive, Suspended, Churned), and a
9
+ monthly_value representing MRR contribution. Contract dates track the lifecycle.
10
+ A company can have multiple accounts (e.g. separate subscriptions for different teams).
11
+
12
+ dimensions:
13
+ - name: id
14
+ sql: id
15
+ type: number
16
+ description: Primary key — unique account identifier
17
+ primary_key: true
18
+
19
+ - name: company_id
20
+ sql: company_id
21
+ type: number
22
+ description: Foreign key to companies — which customer owns this account
23
+
24
+ - name: plan
25
+ sql: plan
26
+ type: string
27
+ description: |
28
+ Subscription tier. Determines pricing and feature access.
29
+ Free = $0, Starter = ~$49-89, Pro = ~$299-500, Enterprise = ~$5K-15K.
30
+ sample_values: [Enterprise, Pro, Starter, Free]
31
+
32
+ - name: status
33
+ sql: status
34
+ type: string
35
+ description: |
36
+ Current billing status. Active = paying, Inactive = paused,
37
+ Suspended = payment issue, Churned = cancelled.
38
+ sample_values: [Active, Churned, Inactive, Suspended]
39
+
40
+ - name: monthly_value
41
+ sql: monthly_value
42
+ type: number
43
+ description: |
44
+ Monthly Recurring Revenue (MRR) from this account in dollars.
45
+ Free accounts have $0. This is the core revenue metric.
46
+
47
+ - name: contract_start
48
+ sql: contract_start
49
+ type: date
50
+ description: Date the subscription began
51
+
52
+ - name: contract_end
53
+ sql: contract_end
54
+ type: date
55
+ description: |
56
+ Date the subscription ended. NULL means the account is still under contract.
57
+ Set when an account churns or is terminated.
58
+
59
+ - name: monthly_value_bucket
60
+ sql: |-
61
+ CASE
62
+ WHEN monthly_value = 0 THEN 'Free'
63
+ WHEN monthly_value < 100 THEN 'Low'
64
+ WHEN monthly_value < 1000 THEN 'Mid'
65
+ ELSE 'High'
66
+ END
67
+ type: string
68
+ description: MRR tier bucket — Free / Low / Mid / High
69
+ virtual: true
70
+ sample_values: [Free, Low, Mid, High]
71
+
72
+ - name: contract_start_year
73
+ sql: EXTRACT(YEAR FROM contract_start)
74
+ type: number
75
+ description: Year the contract started — useful for cohort analysis
76
+ virtual: true
77
+
78
+ - name: contract_start_month
79
+ sql: TO_CHAR(contract_start, 'YYYY-MM')
80
+ type: string
81
+ description: Year-month the contract started
82
+ virtual: true
83
+
84
+ - name: is_churned
85
+ sql: CASE WHEN status = 'Churned' THEN true ELSE false END
86
+ type: boolean
87
+ description: Whether this account has churned
88
+ virtual: true
89
+
90
+ measures:
91
+ - name: account_count
92
+ sql: id
93
+ type: count_distinct
94
+ description: Number of unique accounts
95
+
96
+ - name: total_mrr
97
+ sql: monthly_value
98
+ type: sum
99
+ description: Total Monthly Recurring Revenue
100
+
101
+ - name: avg_mrr
102
+ sql: monthly_value
103
+ type: avg
104
+ description: Average MRR per account
105
+
106
+ joins:
107
+ - target_entity: Companies
108
+ relationship: many_to_one
109
+ join_columns:
110
+ from: company_id
111
+ to: id
112
+ description: Each account belongs to one company (customer)
113
+
114
+ use_cases:
115
+ - MRR analysis — total, by plan, by status, over time
116
+ - Churn analysis — churned vs active accounts, churn rate by plan
117
+ - Revenue segmentation — which plans drive the most revenue
118
+ - Contract lifecycle — average duration, upcoming renewals
119
+ - Cross-entity joins to companies for firmographic revenue analysis
120
+
121
+ query_patterns:
122
+ - name: mrr_by_plan
123
+ description: Total MRR and account count by plan tier
124
+ sql: |-
125
+ SELECT plan,
126
+ SUM(monthly_value) AS total_mrr,
127
+ COUNT(*) AS account_count,
128
+ AVG(monthly_value) AS avg_mrr
129
+ FROM accounts
130
+ WHERE status = 'Active'
131
+ GROUP BY plan
132
+ ORDER BY total_mrr DESC
133
+
134
+ - name: churn_rate_by_plan
135
+ description: Churn rate by plan type
136
+ sql: |-
137
+ SELECT plan,
138
+ COUNT(*) FILTER (WHERE status = 'Churned') AS churned,
139
+ COUNT(*) AS total,
140
+ ROUND(100.0 * COUNT(*) FILTER (WHERE status = 'Churned') / COUNT(*), 1) AS churn_pct
141
+ FROM accounts
142
+ GROUP BY plan
143
+ ORDER BY churn_pct DESC
144
+
145
+ - name: accounts_by_status
146
+ description: Account distribution by billing status
147
+ sql: |-
148
+ SELECT status, COUNT(*) AS count
149
+ FROM accounts
150
+ GROUP BY status
151
+ ORDER BY count DESC
152
+
153
+ - name: mrr_by_contract_year
154
+ description: MRR cohort analysis by contract start year
155
+ sql: |-
156
+ SELECT EXTRACT(YEAR FROM contract_start) AS cohort_year,
157
+ SUM(monthly_value) AS total_mrr,
158
+ COUNT(*) AS accounts
159
+ FROM accounts
160
+ WHERE status = 'Active'
161
+ GROUP BY cohort_year
162
+ ORDER BY cohort_year
@@ -0,0 +1,143 @@
1
+ name: Companies
2
+ type: dimension_table
3
+ table: companies
4
+ grain: one row per customer company
5
+ description: |
6
+ Customer companies (our B2B clients). Contains firmographic data including
7
+ industry vertical, headcount, founding year, HQ country, annual revenue,
8
+ and valuation. Each company can have multiple accounts (subscriptions)
9
+ and multiple people (contacts). This is the central dimension table for
10
+ customer-level analysis.
11
+
12
+ dimensions:
13
+ - name: id
14
+ sql: id
15
+ type: number
16
+ description: Primary key — unique company identifier
17
+ primary_key: true
18
+
19
+ - name: name
20
+ sql: name
21
+ type: string
22
+ description: Company name
23
+ sample_values: [Acme Corp, DataFlow Inc, CloudSync, RetailHub]
24
+
25
+ - name: industry
26
+ sql: industry
27
+ type: string
28
+ description: Business sector / vertical
29
+ sample_values: [Education, Energy, Finance, Healthcare, Manufacturing, Media, Retail, Technology]
30
+
31
+ - name: employee_count
32
+ sql: employee_count
33
+ type: number
34
+ description: Total headcount at the company
35
+
36
+ - name: founded_year
37
+ sql: founded_year
38
+ type: number
39
+ description: Year the company was founded
40
+
41
+ - name: country
42
+ sql: country
43
+ type: string
44
+ description: ISO 2-letter code for company HQ location
45
+ sample_values: [AU, BR, CA, DE, FR, IN, JP, SG, UK, US]
46
+
47
+ - name: revenue
48
+ sql: revenue
49
+ type: number
50
+ description: Annual revenue in dollars (the company's own revenue, not what they pay us)
51
+
52
+ - name: valuation
53
+ sql: valuation
54
+ type: number
55
+ description: Company valuation in dollars
56
+
57
+ - name: company_size
58
+ sql: |-
59
+ CASE
60
+ WHEN employee_count < 100 THEN 'Small'
61
+ WHEN employee_count < 300 THEN 'Mid-Market'
62
+ ELSE 'Enterprise'
63
+ END
64
+ type: string
65
+ description: Company size segment based on headcount
66
+ virtual: true
67
+ sample_values: [Small, Mid-Market, Enterprise]
68
+
69
+ - name: revenue_tier
70
+ sql: |-
71
+ CASE
72
+ WHEN revenue < 10000000 THEN 'Under $10M'
73
+ WHEN revenue < 50000000 THEN '$10M-$50M'
74
+ WHEN revenue < 100000000 THEN '$50M-$100M'
75
+ ELSE '$100M+'
76
+ END
77
+ type: string
78
+ description: Revenue tier for segmentation
79
+ virtual: true
80
+ sample_values: [Under $10M, $10M-$50M, $50M-$100M, $100M+]
81
+
82
+ measures:
83
+ - name: company_count
84
+ sql: id
85
+ type: count_distinct
86
+ description: Number of unique companies
87
+
88
+ - name: avg_employee_count
89
+ sql: employee_count
90
+ type: avg
91
+ description: Average headcount per company
92
+
93
+ - name: total_revenue
94
+ sql: revenue
95
+ type: sum
96
+ description: Combined annual revenue of all companies
97
+
98
+ - name: avg_revenue
99
+ sql: revenue
100
+ type: avg
101
+ description: Average annual revenue per company
102
+
103
+ - name: avg_valuation
104
+ sql: valuation
105
+ type: avg
106
+ description: Average company valuation
107
+
108
+ use_cases:
109
+ - Customer segmentation by industry, country, company size
110
+ - Revenue and valuation analysis across the customer base
111
+ - Firmographic profiling for ICP (ideal customer profile) analysis
112
+ - Join to accounts for revenue-per-company analysis
113
+ - Join to people for stakeholder density per company
114
+
115
+ query_patterns:
116
+ - name: companies_by_industry
117
+ description: Customer count and avg revenue by industry
118
+ sql: |-
119
+ SELECT industry,
120
+ COUNT(*) AS company_count,
121
+ AVG(revenue) AS avg_revenue,
122
+ AVG(employee_count) AS avg_headcount
123
+ FROM companies
124
+ GROUP BY industry
125
+ ORDER BY company_count DESC
126
+
127
+ - name: companies_by_country
128
+ description: Customer distribution by country
129
+ sql: |-
130
+ SELECT country,
131
+ COUNT(*) AS company_count,
132
+ SUM(revenue) AS total_revenue
133
+ FROM companies
134
+ GROUP BY country
135
+ ORDER BY company_count DESC
136
+
137
+ - name: top_companies_by_revenue
138
+ description: Largest customers by annual revenue
139
+ sql: |-
140
+ SELECT name, industry, country, revenue, employee_count
141
+ FROM companies
142
+ ORDER BY revenue DESC
143
+ LIMIT 10
@@ -0,0 +1,132 @@
1
+ name: People
2
+ type: dimension_table
3
+ table: people
4
+ grain: one row per contact
5
+ description: |
6
+ Contacts at customer companies. Each person has a department, seniority level,
7
+ job title, and start date. Linked to companies via company_id. Use for
8
+ stakeholder mapping, org analysis, and understanding who we're selling to
9
+ and supporting at each company.
10
+
11
+ dimensions:
12
+ - name: id
13
+ sql: id
14
+ type: number
15
+ description: Primary key — unique contact identifier
16
+ primary_key: true
17
+
18
+ - name: name
19
+ sql: name
20
+ type: string
21
+ description: Full name of the contact
22
+
23
+ - name: email
24
+ sql: email
25
+ type: string
26
+ description: Work email address
27
+
28
+ - name: company_id
29
+ sql: company_id
30
+ type: number
31
+ description: Foreign key to companies — which company this person works at
32
+
33
+ - name: department
34
+ sql: department
35
+ type: string
36
+ description: Functional department within the company
37
+ sample_values: [Engineering, Finance, Marketing, Operations, Product, Sales]
38
+
39
+ - name: seniority
40
+ sql: seniority
41
+ type: string
42
+ description: Career level — indicates decision-making authority
43
+ sample_values: [Executive, Senior, Mid, Junior]
44
+
45
+ - name: title
46
+ sql: title
47
+ type: string
48
+ description: Job title (e.g. CFO, Backend Engineer, Account Executive)
49
+
50
+ - name: start_date
51
+ sql: start_date
52
+ type: date
53
+ description: Date the person started at their company
54
+
55
+ - name: start_date_year
56
+ sql: EXTRACT(YEAR FROM start_date)
57
+ type: number
58
+ description: Year the person started — useful for tenure analysis
59
+ virtual: true
60
+
61
+ - name: tenure_years
62
+ sql: EXTRACT(YEAR FROM AGE(CURRENT_DATE, start_date))
63
+ type: number
64
+ description: Approximate years of tenure at the company
65
+ virtual: true
66
+
67
+ measures:
68
+ - name: contact_count
69
+ sql: id
70
+ type: count_distinct
71
+ description: Number of unique contacts
72
+
73
+ - name: avg_tenure
74
+ sql: EXTRACT(YEAR FROM AGE(CURRENT_DATE, start_date))
75
+ type: avg
76
+ description: Average tenure in years
77
+
78
+ joins:
79
+ - target_entity: Companies
80
+ relationship: many_to_one
81
+ join_columns:
82
+ from: company_id
83
+ to: id
84
+ description: Each contact belongs to one company
85
+
86
+ use_cases:
87
+ - Stakeholder mapping — who are the key contacts at each company
88
+ - Department breakdown — what functions are represented
89
+ - Seniority analysis — how many executives vs individual contributors
90
+ - Hiring trends — when were contacts added, by year
91
+ - Join to companies + accounts for full customer intelligence
92
+
93
+ query_patterns:
94
+ - name: contacts_by_department
95
+ description: Contact count by department
96
+ sql: |-
97
+ SELECT department,
98
+ COUNT(*) AS contact_count
99
+ FROM people
100
+ GROUP BY department
101
+ ORDER BY contact_count DESC
102
+
103
+ - name: contacts_by_seniority
104
+ description: Contact distribution by seniority level
105
+ sql: |-
106
+ SELECT seniority,
107
+ COUNT(*) AS contact_count
108
+ FROM people
109
+ GROUP BY seniority
110
+ ORDER BY contact_count DESC
111
+
112
+ - name: executives_by_company
113
+ description: Executive contacts per company
114
+ sql: |-
115
+ SELECT c.name AS company,
116
+ COUNT(*) AS executive_count
117
+ FROM people p
118
+ JOIN companies c ON p.company_id = c.id
119
+ WHERE p.seniority = 'Executive'
120
+ GROUP BY c.name
121
+ ORDER BY executive_count DESC
122
+
123
+ - name: contacts_per_company
124
+ description: Contact density per company
125
+ sql: |-
126
+ SELECT c.name AS company,
127
+ COUNT(*) AS contact_count,
128
+ c.employee_count AS total_employees
129
+ FROM people p
130
+ JOIN companies c ON p.company_id = c.id
131
+ GROUP BY c.name, c.employee_count
132
+ ORDER BY contact_count DESC