@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
@@ -0,0 +1,397 @@
1
+ import { describe, expect, it, beforeEach, afterEach, mock } from "bun:test";
2
+
3
+ // ---------------------------------------------------------------------------
4
+ // Mocks
5
+ // ---------------------------------------------------------------------------
6
+
7
+ mock.module("@atlas/api/lib/logger", () => ({
8
+ createLogger: () => ({
9
+ debug: () => {},
10
+ info: () => {},
11
+ warn: () => {},
12
+ error: () => {},
13
+ }),
14
+ }));
15
+
16
+ mock.module("@atlas/api/lib/tracing", () => ({
17
+ withSpan: async (_name: string, _attrs: unknown, fn: () => Promise<unknown>) => fn(),
18
+ }));
19
+
20
+ mock.module("@atlas/api/lib/security", () => ({
21
+ SENSITIVE_PATTERNS: /postgresql:\/\/|mysql:\/\/|sk-ant-/,
22
+ }));
23
+
24
+ // --- @vercel/sandbox mock infrastructure ---
25
+
26
+ type RunCommandParams = {
27
+ cmd: string;
28
+ args?: string[];
29
+ cwd?: string;
30
+ env?: Record<string, string>;
31
+ sudo?: boolean;
32
+ };
33
+
34
+ interface MockSandboxOverrides {
35
+ createError?: string;
36
+ pipExitCode?: number;
37
+ pipStderr?: string;
38
+ pipThrows?: string;
39
+ updateNetworkPolicyThrows?: string;
40
+ mkDirThrows?: string;
41
+ writeFilesThrows?: string;
42
+ runCommandThrows?: string;
43
+ runCommandResult?: {
44
+ exitCode: number;
45
+ stdout: string;
46
+ stderr: string;
47
+ };
48
+ /** If true, dynamically inject the result marker into stdout */
49
+ injectMarker?: boolean;
50
+ /** Custom stdout builder given the marker */
51
+ stdoutForMarker?: (marker: string) => string;
52
+ }
53
+
54
+ let mockCreateCalls: unknown[] = [];
55
+ let mockRunCommandCalls: RunCommandParams[] = [];
56
+ let mockWriteFilesCalls: { path: string; content: Buffer }[][] = [];
57
+ let mockMkDirCalls: string[] = [];
58
+ let mockStopCalls = 0;
59
+ let mockUpdateNetworkPolicyCalls: unknown[] = [];
60
+
61
+ function setupSandboxMock(overrides: MockSandboxOverrides = {}) {
62
+ mockCreateCalls = [];
63
+ mockRunCommandCalls = [];
64
+ mockWriteFilesCalls = [];
65
+ mockMkDirCalls = [];
66
+ mockStopCalls = 0;
67
+ mockUpdateNetworkPolicyCalls = [];
68
+
69
+ mock.module("@vercel/sandbox", () => ({
70
+ Sandbox: {
71
+ create: async (opts: unknown) => {
72
+ mockCreateCalls.push(opts);
73
+ if (overrides.createError) throw new Error(overrides.createError);
74
+ return {
75
+ runCommand: async (params: RunCommandParams) => {
76
+ if (params.cmd === "pip") {
77
+ if (overrides.pipThrows) throw new Error(overrides.pipThrows);
78
+ return {
79
+ exitCode: overrides.pipExitCode ?? 0,
80
+ stdout: async () => "",
81
+ stderr: async () => overrides.pipStderr ?? "",
82
+ };
83
+ }
84
+ mockRunCommandCalls.push(params);
85
+ if (overrides.runCommandThrows) throw new Error(overrides.runCommandThrows);
86
+
87
+ const marker = params.env?.ATLAS_RESULT_MARKER ?? "";
88
+ if (overrides.stdoutForMarker) {
89
+ return {
90
+ exitCode: overrides.runCommandResult?.exitCode ?? 0,
91
+ stdout: async () => overrides.stdoutForMarker!(marker),
92
+ stderr: async () => overrides.runCommandResult?.stderr ?? "",
93
+ };
94
+ }
95
+ if (overrides.injectMarker !== false && !overrides.runCommandResult) {
96
+ return {
97
+ exitCode: 0,
98
+ stdout: async () => `${marker}{"success":true}\n`,
99
+ stderr: async () => "",
100
+ };
101
+ }
102
+ return {
103
+ exitCode: overrides.runCommandResult?.exitCode ?? 0,
104
+ stdout: async () => overrides.runCommandResult?.stdout ?? "",
105
+ stderr: async () => overrides.runCommandResult?.stderr ?? "",
106
+ };
107
+ },
108
+ writeFiles: async (files: { path: string; content: Buffer }[]) => {
109
+ mockWriteFilesCalls.push(files);
110
+ if (overrides.writeFilesThrows) throw new Error(overrides.writeFilesThrows);
111
+ },
112
+ mkDir: async (dir: string) => {
113
+ mockMkDirCalls.push(dir);
114
+ if (overrides.mkDirThrows) throw new Error(overrides.mkDirThrows);
115
+ },
116
+ updateNetworkPolicy: async (policy: unknown) => {
117
+ mockUpdateNetworkPolicyCalls.push(policy);
118
+ if (overrides.updateNetworkPolicyThrows) throw new Error(overrides.updateNetworkPolicyThrows);
119
+ },
120
+ stop: async () => { mockStopCalls++; },
121
+ };
122
+ },
123
+ },
124
+ }));
125
+ }
126
+
127
+ async function freshBackend() {
128
+ const mod = await import("@atlas/api/lib/tools/python-sandbox");
129
+ return mod.createPythonSandboxBackend();
130
+ }
131
+
132
+ // ---------------------------------------------------------------------------
133
+ // Tests
134
+ // ---------------------------------------------------------------------------
135
+
136
+ describe("createPythonSandboxBackend", () => {
137
+ const originalEnv = { ...process.env };
138
+
139
+ beforeEach(() => {
140
+ setupSandboxMock();
141
+ });
142
+
143
+ afterEach(() => {
144
+ process.env = { ...originalEnv };
145
+ });
146
+
147
+ it("creates sandbox with python3.13 runtime, installs packages, then locks to deny-all", async () => {
148
+ setupSandboxMock({
149
+ stdoutForMarker: (m) => `${m}{"success":true,"output":"hello"}\n`,
150
+ });
151
+
152
+ const backend = await freshBackend();
153
+ const result = await backend.exec('print("hello")');
154
+
155
+ // Sandbox created with allow-all (for pip)
156
+ expect(mockCreateCalls.length).toBe(1);
157
+ const createOpts = mockCreateCalls[0] as { runtime: string; networkPolicy: string };
158
+ expect(createOpts.runtime).toBe("python3.13");
159
+ expect(createOpts.networkPolicy).toBe("allow-all");
160
+
161
+ // Network locked down to deny-all after pip install
162
+ expect(mockUpdateNetworkPolicyCalls).toEqual(["deny-all"]);
163
+
164
+ expect(result.success).toBe(true);
165
+ if (result.success) {
166
+ expect(result.output).toBe("hello");
167
+ }
168
+ });
169
+
170
+ it("writes wrapper, user code, and data files to sandbox", async () => {
171
+ setupSandboxMock();
172
+ const backend = await freshBackend();
173
+
174
+ const data = { columns: ["a", "b"], rows: [[1, 2], [3, 4]] };
175
+ await backend.exec("print(df.head())", data);
176
+
177
+ expect(mockWriteFilesCalls.length).toBe(1);
178
+ const files = mockWriteFilesCalls[0];
179
+ expect(files.length).toBe(3);
180
+
181
+ const paths = files.map((f) => f.path);
182
+ expect(paths.some((p) => p.includes("wrapper.py"))).toBe(true);
183
+ expect(paths.some((p) => p.includes("user_code.py"))).toBe(true);
184
+ expect(paths.some((p) => p.includes("data.json"))).toBe(true);
185
+
186
+ const dataFile = files.find((f) => f.path.includes("data.json"))!;
187
+ const parsed = JSON.parse(dataFile.content.toString());
188
+ expect(parsed.columns).toEqual(["a", "b"]);
189
+ expect(parsed.rows).toEqual([[1, 2], [3, 4]]);
190
+ });
191
+
192
+ it("omits data file when no data provided", async () => {
193
+ setupSandboxMock();
194
+ const backend = await freshBackend();
195
+ await backend.exec("print(1)");
196
+
197
+ expect(mockWriteFilesCalls.length).toBe(1);
198
+ const files = mockWriteFilesCalls[0];
199
+ expect(files.length).toBe(2);
200
+ expect(files.some((f) => f.path.includes("data.json"))).toBe(false);
201
+ });
202
+
203
+ it("passes correct env vars to runCommand with no secrets", async () => {
204
+ setupSandboxMock();
205
+ const backend = await freshBackend();
206
+ await backend.exec("print(1)");
207
+
208
+ expect(mockRunCommandCalls.length).toBe(1);
209
+ const params = mockRunCommandCalls[0];
210
+
211
+ expect(params.cmd).toBe("python3");
212
+ expect(params.env?.MPLBACKEND).toBe("Agg");
213
+ expect(params.env?.ATLAS_RESULT_MARKER).toBeDefined();
214
+ expect(params.env?.ATLAS_CHART_DIR).toContain("charts");
215
+
216
+ // No secrets
217
+ expect(params.env).not.toHaveProperty("ATLAS_DATASOURCE_URL");
218
+ expect(params.env).not.toHaveProperty("ANTHROPIC_API_KEY");
219
+ expect(params.env).not.toHaveProperty("DATABASE_URL");
220
+ });
221
+
222
+ it("reuses sandbox across multiple exec calls", async () => {
223
+ setupSandboxMock();
224
+ const backend = await freshBackend();
225
+
226
+ await backend.exec("print(1)");
227
+ await backend.exec("print(2)");
228
+
229
+ // Sandbox.create called only once
230
+ expect(mockCreateCalls.length).toBe(1);
231
+ // But runCommand called twice
232
+ expect(mockRunCommandCalls.length).toBe(2);
233
+ });
234
+
235
+ it("invalidation stops old sandbox and creates fresh one on next call", async () => {
236
+ // First call uses a sandbox that errors on runCommand
237
+ setupSandboxMock({ runCommandThrows: "VM crashed" });
238
+ const backend = await freshBackend();
239
+
240
+ const result1 = await backend.exec("print(1)");
241
+ expect(result1.success).toBe(false);
242
+
243
+ // Invalidation should have stopped the old sandbox
244
+ // Give the async stop a tick to complete
245
+ await new Promise((r) => setTimeout(r, 10));
246
+ expect(mockStopCalls).toBeGreaterThanOrEqual(1);
247
+
248
+ // Next call should create a fresh sandbox
249
+ setupSandboxMock(); // Reset to working sandbox
250
+ await backend.exec("print(2)");
251
+ expect(mockCreateCalls.length).toBe(1); // New sandbox created
252
+ });
253
+
254
+ it("returns error when sandbox creation fails", async () => {
255
+ setupSandboxMock({ createError: "quota exceeded" });
256
+ const backend = await freshBackend();
257
+ const result = await backend.exec("print(1)");
258
+
259
+ expect(result.success).toBe(false);
260
+ if (!result.success) {
261
+ expect(result.error).toContain("quota exceeded");
262
+ }
263
+ });
264
+
265
+ it("returns error when mkDir fails and invalidates sandbox", async () => {
266
+ setupSandboxMock({ mkDirThrows: "permission denied" });
267
+ const backend = await freshBackend();
268
+ const result = await backend.exec("print(1)");
269
+
270
+ expect(result.success).toBe(false);
271
+ if (!result.success) {
272
+ expect(result.error).toContain("permission denied");
273
+ }
274
+ });
275
+
276
+ it("returns error when writeFiles fails", async () => {
277
+ setupSandboxMock({ writeFilesThrows: "disk full" });
278
+ const backend = await freshBackend();
279
+ const result = await backend.exec("print(1)");
280
+
281
+ expect(result.success).toBe(false);
282
+ if (!result.success) {
283
+ expect(result.error).toContain("disk full");
284
+ }
285
+ });
286
+
287
+ it("returns error when runCommand fails", async () => {
288
+ setupSandboxMock({ runCommandThrows: "VM crashed" });
289
+ const backend = await freshBackend();
290
+ const result = await backend.exec("print(1)");
291
+
292
+ expect(result.success).toBe(false);
293
+ if (!result.success) {
294
+ expect(result.error).toContain("VM crashed");
295
+ }
296
+ });
297
+
298
+ it("returns error when updateNetworkPolicy fails and stops sandbox", async () => {
299
+ setupSandboxMock({ updateNetworkPolicyThrows: "policy update failed" });
300
+ const backend = await freshBackend();
301
+ const result = await backend.exec("print(1)");
302
+
303
+ expect(result.success).toBe(false);
304
+ if (!result.success) {
305
+ expect(result.error).toContain("lock down sandbox network");
306
+ }
307
+ // Should have stopped the sandbox on failure
308
+ expect(mockStopCalls).toBeGreaterThanOrEqual(1);
309
+ });
310
+
311
+ it("handles SIGKILL exit code", async () => {
312
+ setupSandboxMock({
313
+ injectMarker: false,
314
+ runCommandResult: { exitCode: 137, stdout: "", stderr: "" },
315
+ });
316
+ const backend = await freshBackend();
317
+ const result = await backend.exec("while True: pass");
318
+
319
+ expect(result.success).toBe(false);
320
+ if (!result.success) {
321
+ expect(result.error).toContain("killed");
322
+ }
323
+ });
324
+
325
+ it("handles SIGSEGV exit code with stderr", async () => {
326
+ setupSandboxMock({
327
+ injectMarker: false,
328
+ runCommandResult: { exitCode: 139, stdout: "", stderr: "Segfault in numpy" },
329
+ });
330
+ const backend = await freshBackend();
331
+ const result = await backend.exec("bad code");
332
+
333
+ expect(result.success).toBe(false);
334
+ if (!result.success) {
335
+ expect(result.error).toContain("SIGSEGV");
336
+ expect(result.error).toContain("Segfault in numpy");
337
+ }
338
+ });
339
+
340
+ it("returns stderr as error when no result marker and non-zero exit", async () => {
341
+ setupSandboxMock({
342
+ injectMarker: false,
343
+ runCommandResult: { exitCode: 1, stdout: "some output", stderr: "NameError: name 'foo' is not defined" },
344
+ });
345
+ const backend = await freshBackend();
346
+ const result = await backend.exec("print(foo)");
347
+
348
+ expect(result.success).toBe(false);
349
+ if (!result.success) {
350
+ expect(result.error).toContain("NameError");
351
+ }
352
+ });
353
+
354
+ it("rejects output exceeding 1 MB", async () => {
355
+ const bigOutput = "x".repeat(1024 * 1024 + 1);
356
+ setupSandboxMock({
357
+ injectMarker: false,
358
+ runCommandResult: { exitCode: 0, stdout: bigOutput, stderr: "" },
359
+ });
360
+ const backend = await freshBackend();
361
+ const result = await backend.exec("print('a' * 10000000)");
362
+
363
+ expect(result.success).toBe(false);
364
+ if (!result.success) {
365
+ expect(result.error).toContain("exceeded 1 MB");
366
+ }
367
+ });
368
+
369
+ it("scrubs sensitive data from error messages", async () => {
370
+ setupSandboxMock({ mkDirThrows: "Error connecting to postgresql://user:pass@host/db" });
371
+ const backend = await freshBackend();
372
+ const result = await backend.exec("print(1)");
373
+
374
+ expect(result.success).toBe(false);
375
+ if (!result.success) {
376
+ expect(result.error).not.toContain("postgresql://");
377
+ expect(result.error).toContain("details in server logs");
378
+ }
379
+ });
380
+
381
+ it("continues without packages when pip install fails", async () => {
382
+ setupSandboxMock({ pipExitCode: 1, pipStderr: "network error" });
383
+ const backend = await freshBackend();
384
+ const result = await backend.exec("print(1)");
385
+
386
+ // Should still succeed — pip failure is non-fatal
387
+ expect(result.success).toBe(true);
388
+ });
389
+
390
+ it("continues without packages when pip install throws", async () => {
391
+ setupSandboxMock({ pipThrows: "command not found" });
392
+ const backend = await freshBackend();
393
+ const result = await backend.exec("print(1)");
394
+
395
+ expect(result.success).toBe(true);
396
+ });
397
+ });