@tscircuit/fake-snippets 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/.github/CODEOWNERS +1 -0
  2. package/.github/workflows/bun-formatcheck.yml +26 -0
  3. package/.github/workflows/bun-test.yml +28 -0
  4. package/.github/workflows/bun-typecheck.yml +26 -0
  5. package/.github/workflows/bundle-size-analysis.yml +79 -0
  6. package/.github/workflows/playwright-test.yml +37 -0
  7. package/.github/workflows/stale.yml +40 -0
  8. package/.github/workflows/update-snapshots.yml +49 -0
  9. package/CONTRIBUTING.md +59 -0
  10. package/LICENSE +21 -0
  11. package/README.md +113 -0
  12. package/biome.json +60 -0
  13. package/bun-tests/fake-snippets-api/fixtures/get-circuit-json.ts +148 -0
  14. package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +96 -0
  15. package/bun-tests/fake-snippets-api/fixtures/start-server.ts +44 -0
  16. package/bun-tests/fake-snippets-api/routes/accounts/get_account_balance.test.ts +18 -0
  17. package/bun-tests/fake-snippets-api/routes/health.test.ts +9 -0
  18. package/bun-tests/fake-snippets-api/routes/order_files/get.test.ts +48 -0
  19. package/bun-tests/fake-snippets-api/routes/order_files/upload.test.ts +77 -0
  20. package/bun-tests/fake-snippets-api/routes/orders/create.test.ts +19 -0
  21. package/bun-tests/fake-snippets-api/routes/orders/get.test.ts +38 -0
  22. package/bun-tests/fake-snippets-api/routes/orders/list.test.ts +30 -0
  23. package/bun-tests/fake-snippets-api/routes/orders/update.test.ts +46 -0
  24. package/bun-tests/fake-snippets-api/routes/snippets/add_star.test.ts +114 -0
  25. package/bun-tests/fake-snippets-api/routes/snippets/create.test.ts +28 -0
  26. package/bun-tests/fake-snippets-api/routes/snippets/delete.test.ts +106 -0
  27. package/bun-tests/fake-snippets-api/routes/snippets/download.test.ts +90 -0
  28. package/bun-tests/fake-snippets-api/routes/snippets/generate_from_jlcpcb.test.ts +25 -0
  29. package/bun-tests/fake-snippets-api/routes/snippets/get_image.test.ts +113 -0
  30. package/bun-tests/fake-snippets-api/routes/snippets/images.test.ts +112 -0
  31. package/bun-tests/fake-snippets-api/routes/snippets/list.test.ts +62 -0
  32. package/bun-tests/fake-snippets-api/routes/snippets/list_newest.test.ts +48 -0
  33. package/bun-tests/fake-snippets-api/routes/snippets/list_trending.test.ts +69 -0
  34. package/bun-tests/fake-snippets-api/routes/snippets/remove_star.test.ts +110 -0
  35. package/bun-tests/fake-snippets-api/routes/snippets/search.test.ts +75 -0
  36. package/bun-tests/fake-snippets-api/routes/snippets/star-count.test.ts +44 -0
  37. package/bun-tests/fake-snippets-api/routes/snippets/update.test.ts +116 -0
  38. package/bun-tests/parts-engine.test.ts +18 -0
  39. package/bun.lockb +0 -0
  40. package/bunfig.toml +2 -0
  41. package/components.json +20 -0
  42. package/dist/assets/editor_example_1-1000w.webp +0 -0
  43. package/dist/assets/editor_example_1-1200w.webp +0 -0
  44. package/dist/assets/editor_example_1-1600w.webp +0 -0
  45. package/dist/assets/editor_example_1-2000w.webp +0 -0
  46. package/dist/assets/editor_example_1-400w.webp +0 -0
  47. package/dist/assets/editor_example_1-600w.webp +0 -0
  48. package/dist/assets/editor_example_1-800w.webp +0 -0
  49. package/dist/assets/editor_example_1_more_square-1000w.webp +0 -0
  50. package/dist/assets/editor_example_1_more_square-1200w.webp +0 -0
  51. package/dist/assets/editor_example_1_more_square-1600w.webp +0 -0
  52. package/dist/assets/editor_example_1_more_square-2000w.webp +0 -0
  53. package/dist/assets/editor_example_1_more_square-400w.webp +0 -0
  54. package/dist/assets/editor_example_1_more_square-600w.webp +0 -0
  55. package/dist/assets/editor_example_1_more_square-800w.webp +0 -0
  56. package/dist/assets/editor_example_2-1000w.webp +0 -0
  57. package/dist/assets/editor_example_2-1200w.webp +0 -0
  58. package/dist/assets/editor_example_2-1600w.webp +0 -0
  59. package/dist/assets/editor_example_2-2000w.webp +0 -0
  60. package/dist/assets/editor_example_2-400w.webp +0 -0
  61. package/dist/assets/editor_example_2-600w.webp +0 -0
  62. package/dist/assets/editor_example_2-800w.webp +0 -0
  63. package/dist/assets/example_schematic-1000w.webp +0 -0
  64. package/dist/assets/example_schematic-1200w.webp +0 -0
  65. package/dist/assets/example_schematic-1600w.webp +0 -0
  66. package/dist/assets/example_schematic-2000w.webp +0 -0
  67. package/dist/assets/example_schematic-400w.webp +0 -0
  68. package/dist/assets/example_schematic-600w.webp +0 -0
  69. package/dist/assets/example_schematic-800w.webp +0 -0
  70. package/dist/bundle.js +3270 -0
  71. package/dist/robots.txt +9 -0
  72. package/dist/sitemap.xml +118 -0
  73. package/docs/CIRCUIT_JSON_SOURCE_COMPONENT_OVERVIEW.md +151 -0
  74. package/fake-snippets-api/README.md +6 -0
  75. package/fake-snippets-api/biome.json +47 -0
  76. package/fake-snippets-api/bun.lockb +0 -0
  77. package/fake-snippets-api/lib/db/autoload-dev-snippets.ts +84 -0
  78. package/fake-snippets-api/lib/db/autoload-snippets.json +24 -0
  79. package/fake-snippets-api/lib/db/db-client.ts +343 -0
  80. package/fake-snippets-api/lib/db/schema.ts +112 -0
  81. package/fake-snippets-api/lib/db/seed.ts +1608 -0
  82. package/fake-snippets-api/lib/middleware/with-ctx-error.ts +26 -0
  83. package/fake-snippets-api/lib/middleware/with-db.ts +15 -0
  84. package/fake-snippets-api/lib/middleware/with-error-handling.ts +24 -0
  85. package/fake-snippets-api/lib/middleware/with-optional-session-auth.ts +34 -0
  86. package/fake-snippets-api/lib/middleware/with-request-logging.ts +54 -0
  87. package/fake-snippets-api/lib/middleware/with-session-auth.ts +39 -0
  88. package/fake-snippets-api/lib/middleware/with-winter-spec.ts +24 -0
  89. package/fake-snippets-api/next-env.d.ts +5 -0
  90. package/fake-snippets-api/routes/api/accounts/get.ts +21 -0
  91. package/fake-snippets-api/routes/api/accounts/get_account_balance.ts +22 -0
  92. package/fake-snippets-api/routes/api/accounts/update.ts +32 -0
  93. package/fake-snippets-api/routes/api/ai/[...anyroute].ts +31 -0
  94. package/fake-snippets-api/routes/api/ai.ts +2 -0
  95. package/fake-snippets-api/routes/api/aistream/[...anyroute].ts +65 -0
  96. package/fake-snippets-api/routes/api/health.ts +9 -0
  97. package/fake-snippets-api/routes/api/internal/sessions/create_without_auth.ts +63 -0
  98. package/fake-snippets-api/routes/api/order_files/get.ts +28 -0
  99. package/fake-snippets-api/routes/api/order_files/upload.ts +43 -0
  100. package/fake-snippets-api/routes/api/orders/create.ts +41 -0
  101. package/fake-snippets-api/routes/api/orders/get.ts +28 -0
  102. package/fake-snippets-api/routes/api/orders/list.ts +15 -0
  103. package/fake-snippets-api/routes/api/orders/update.ts +50 -0
  104. package/fake-snippets-api/routes/api/snippets/add_star.ts +42 -0
  105. package/fake-snippets-api/routes/api/snippets/create.ts +55 -0
  106. package/fake-snippets-api/routes/api/snippets/delete.ts +41 -0
  107. package/fake-snippets-api/routes/api/snippets/download.ts +148 -0
  108. package/fake-snippets-api/routes/api/snippets/generate_from_jlcpcb.ts +55 -0
  109. package/fake-snippets-api/routes/api/snippets/get.ts +50 -0
  110. package/fake-snippets-api/routes/api/snippets/get_image.ts +65 -0
  111. package/fake-snippets-api/routes/api/snippets/images/[author]/[snippet_name]/[typeFormat].ts +74 -0
  112. package/fake-snippets-api/routes/api/snippets/list.ts +28 -0
  113. package/fake-snippets-api/routes/api/snippets/list_newest.ts +13 -0
  114. package/fake-snippets-api/routes/api/snippets/list_trending.ts +21 -0
  115. package/fake-snippets-api/routes/api/snippets/remove_star.ts +42 -0
  116. package/fake-snippets-api/routes/api/snippets/search.ts +18 -0
  117. package/fake-snippets-api/routes/api/snippets/update.ts +86 -0
  118. package/favicon.ico +0 -0
  119. package/index.html +23 -0
  120. package/landing.html +23 -0
  121. package/package.json +164 -0
  122. package/playwright-tests/ai-page.spec.ts +19 -0
  123. package/playwright-tests/cmd-click.spec.ts +43 -0
  124. package/playwright-tests/dashboard-page.spec.ts +10 -0
  125. package/playwright-tests/editor-page.spec.ts +15 -0
  126. package/playwright-tests/files-dialog.spec.ts +19 -0
  127. package/playwright-tests/footprint-dialog/footprint-dialog.spec.ts +27 -0
  128. package/playwright-tests/footprint-dialog/footprint-insertion.spec.ts +38 -0
  129. package/playwright-tests/footprint-dialog/footprint-preview.spec.ts +34 -0
  130. package/playwright-tests/footprint-dialog/footprint-selection.spec.ts +29 -0
  131. package/playwright-tests/handle-manual-edits.spec.ts +55 -0
  132. package/playwright-tests/home-page.spec.ts +10 -0
  133. package/playwright-tests/images.spec.ts +17 -0
  134. package/playwright-tests/manual-edits.spec.ts +89 -0
  135. package/playwright-tests/preview-page.spec.ts +14 -0
  136. package/playwright-tests/quickstart-page.spec.ts +10 -0
  137. package/playwright-tests/search-links.spec.ts +21 -0
  138. package/playwright-tests/search.spec.ts +27 -0
  139. package/playwright-tests/snapshots/ai-page.spec.ts-AI-Page-lg.png +0 -0
  140. package/playwright-tests/snapshots/ai-page.spec.ts-AI-Page-md.png +0 -0
  141. package/playwright-tests/snapshots/ai-page.spec.ts-AI-Page-xs.png +0 -0
  142. package/playwright-tests/snapshots/cmd-click.spec.ts-underlined-imports.png +0 -0
  143. package/playwright-tests/snapshots/dashboard-page.spec.ts-Dashboard-page-lg.png +0 -0
  144. package/playwright-tests/snapshots/dashboard-page.spec.ts-Dashboard-page-md.png +0 -0
  145. package/playwright-tests/snapshots/dashboard-page.spec.ts-Dashboard-page-xs.png +0 -0
  146. package/playwright-tests/snapshots/editor-page.spec.ts-editor-with-snippet.png +0 -0
  147. package/playwright-tests/snapshots/error-fallback.spec.ts-error-fallback-lg.png +0 -0
  148. package/playwright-tests/snapshots/error-fallback.spec.ts-error-fallback-md.png +0 -0
  149. package/playwright-tests/snapshots/error-fallback.spec.ts-error-fallback-xs.png +0 -0
  150. package/playwright-tests/snapshots/files-dialog.spec.ts-view-snippet-files.png +0 -0
  151. package/playwright-tests/snapshots/footprint-dialog/footprint-dialog.spec.ts-footprint-preview-lg.png +0 -0
  152. package/playwright-tests/snapshots/footprint-dialog/footprint-dialog.spec.ts-footprint-preview-md.png +0 -0
  153. package/playwright-tests/snapshots/footprint-dialog/footprint-dialog.spec.ts-footprint-preview-xs.png +0 -0
  154. package/playwright-tests/snapshots/footprint-dialog/footprint-insertion.spec.ts-footprint-insertion-lg.png +0 -0
  155. package/playwright-tests/snapshots/footprint-dialog/footprint-insertion.spec.ts-footprint-insertion-md.png +0 -0
  156. package/playwright-tests/snapshots/footprint-dialog/footprint-insertion.spec.ts-footprint-insertion-xs.png +0 -0
  157. package/playwright-tests/snapshots/footprint-dialog/footprint-preview.spec.ts-footprint-preview-lg.png +0 -0
  158. package/playwright-tests/snapshots/footprint-dialog/footprint-preview.spec.ts-footprint-preview-md.png +0 -0
  159. package/playwright-tests/snapshots/footprint-dialog/footprint-preview.spec.ts-footprint-preview-xs.png +0 -0
  160. package/playwright-tests/snapshots/footprint-dialog/footprint-selection.spec.ts-footprint-preview-lg.png +0 -0
  161. package/playwright-tests/snapshots/footprint-dialog/footprint-selection.spec.ts-footprint-preview-md.png +0 -0
  162. package/playwright-tests/snapshots/footprint-dialog/footprint-selection.spec.ts-footprint-preview-xs.png +0 -0
  163. package/playwright-tests/snapshots/handle-manual-edits.spec.ts-handle-manual-edits.png +0 -0
  164. package/playwright-tests/snapshots/home-page.spec.ts-Home-page-lg.png +0 -0
  165. package/playwright-tests/snapshots/home-page.spec.ts-Home-page-md.png +0 -0
  166. package/playwright-tests/snapshots/home-page.spec.ts-Home-page-xs.png +0 -0
  167. package/playwright-tests/snapshots/images.spec.ts-pcb-image.png +0 -0
  168. package/playwright-tests/snapshots/images.spec.ts-schematic-image.png +0 -0
  169. package/playwright-tests/snapshots/manual-edits.spec.ts-editor-manual-edits.png +0 -0
  170. package/playwright-tests/snapshots/manual-edits.spec.ts-manual-edits-view.png +0 -0
  171. package/playwright-tests/snapshots/preview-page.spec.ts-preview-snippet-pcb.png +0 -0
  172. package/playwright-tests/snapshots/preview-page.spec.ts-preview-snippet-schematic.png +0 -0
  173. package/playwright-tests/snapshots/quickstart-page.spec.ts-Quickstart-Pagelg.png +0 -0
  174. package/playwright-tests/snapshots/quickstart-page.spec.ts-Quickstart-Pagemd.png +0 -0
  175. package/playwright-tests/snapshots/quickstart-page.spec.ts-Quickstart-Pagexs.png +0 -0
  176. package/playwright-tests/snapshots/search-links.spec.ts-search-links.png +0 -0
  177. package/playwright-tests/snapshots/search.spec.ts-search-lg.png +0 -0
  178. package/playwright-tests/snapshots/search.spec.ts-search-md.png +0 -0
  179. package/playwright-tests/snapshots/search.spec.ts-search-xs.png +0 -0
  180. package/playwright-tests/snapshots/star.spec.ts-remove-star-button.png +0 -0
  181. package/playwright-tests/snapshots/star.spec.ts-star-button.png +0 -0
  182. package/playwright-tests/snapshots/update-description.spec.ts-update-description.png +0 -0
  183. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-after-lg.png +0 -0
  184. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-after-md.png +0 -0
  185. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-after-xs.png +0 -0
  186. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-before-lg.png +0 -0
  187. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-before-md.png +0 -0
  188. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-before-xs.png +0 -0
  189. package/playwright-tests/snapshots/view-snippet.spec.ts-view-snippet-files.png +0 -0
  190. package/playwright-tests/star.spec.ts +40 -0
  191. package/playwright-tests/update-description.spec.ts +18 -0
  192. package/playwright-tests/view-snippet.spec.ts +35 -0
  193. package/playwright-tests/viewports.ts +5 -0
  194. package/playwright.config.ts +27 -0
  195. package/postcss.config.js +6 -0
  196. package/public/robots.txt +9 -0
  197. package/renovate.json +24 -0
  198. package/scripts/generate-image-sizes.ts +58 -0
  199. package/scripts/generate-sitemap.ts +103 -0
  200. package/scripts/generate_bundle_stats.js +192 -0
  201. package/scripts/snapshot.ts +35 -0
  202. package/src/App.tsx +113 -0
  203. package/src/ContextProviders.tsx +9 -0
  204. package/src/assets/originals/editor_example_1.webp +0 -0
  205. package/src/assets/originals/editor_example_1_more_square.webp +0 -0
  206. package/src/assets/originals/editor_example_2.webp +0 -0
  207. package/src/assets/originals/example_schematic.webp +0 -0
  208. package/src/components/AiChatInterface.tsx +221 -0
  209. package/src/components/AiChatMessage.tsx +86 -0
  210. package/src/components/Analytics.tsx +30 -0
  211. package/src/components/BomTable.tsx +69 -0
  212. package/src/components/ChatInput.tsx +53 -0
  213. package/src/components/CircuitToSvgWithMouseControl.tsx +78 -0
  214. package/src/components/CmdKMenu.tsx +301 -0
  215. package/src/components/CodeAndPreview.tsx +258 -0
  216. package/src/components/CodeEditor.tsx +460 -0
  217. package/src/components/CodeEditorHeader.tsx +160 -0
  218. package/src/components/CreateNewSnippetWithAiHero.tsx +77 -0
  219. package/src/components/DownloadButtonAndMenu.tsx +212 -0
  220. package/src/components/EditorNav.tsx +428 -0
  221. package/src/components/ErrorFallback.tsx +25 -0
  222. package/src/components/ErrorTabContent.tsx +122 -0
  223. package/src/components/FAQ.tsx +113 -0
  224. package/src/components/Footer.tsx +134 -0
  225. package/src/components/Footer2.tsx +100 -0
  226. package/src/components/FootprintDialog.tsx +342 -0
  227. package/src/components/Header.tsx +187 -0
  228. package/src/components/Header2.tsx +135 -0
  229. package/src/components/HeaderDropdown.tsx +83 -0
  230. package/src/components/HeaderLogin.tsx +94 -0
  231. package/src/components/JLCPCBImportDialog.tsx +155 -0
  232. package/src/components/LandingHero.tsx +175 -0
  233. package/src/components/LatestSnippets.tsx +39 -0
  234. package/src/components/OptimizedImage.tsx +96 -0
  235. package/src/components/OrderPreviewContent.tsx +61 -0
  236. package/src/components/ParametersEditor.tsx +140 -0
  237. package/src/components/PcbViewerWithContainerHeight.tsx +47 -0
  238. package/src/components/PrefetchPageLink.tsx +45 -0
  239. package/src/components/PreviewContent.tsx +375 -0
  240. package/src/components/PreviewEmptyState.tsx +16 -0
  241. package/src/components/RunButton.tsx +27 -0
  242. package/src/components/SearchComponent.tsx +163 -0
  243. package/src/components/ShippingInformationForm.tsx +423 -0
  244. package/src/components/SnippetLink.tsx +37 -0
  245. package/src/components/StaticPreviewContent.tsx +89 -0
  246. package/src/components/StaticViewSnippetHeader.tsx +70 -0
  247. package/src/components/StaticViewSnippetSidebar.tsx +100 -0
  248. package/src/components/TableViewer/CircuitJsonTableViewer.tsx +316 -0
  249. package/src/components/TableViewer/ClickableText.tsx +21 -0
  250. package/src/components/TableViewer/HeaderCell.tsx +27 -0
  251. package/src/components/TableViewer/Modal.tsx +39 -0
  252. package/src/components/TrendingSnippetCarousel.tsx +77 -0
  253. package/src/components/TypeBadge.tsx +31 -0
  254. package/src/components/ViewSnippetHeader.tsx +144 -0
  255. package/src/components/ViewSnippetSidebar.tsx +162 -0
  256. package/src/components/dialogs/confirm-delete-snippet-dialog.tsx +80 -0
  257. package/src/components/dialogs/create-order-dialog.tsx +146 -0
  258. package/src/components/dialogs/create-use-dialog.tsx +34 -0
  259. package/src/components/dialogs/edit-description-dialog.tsx +96 -0
  260. package/src/components/dialogs/files-dialog.tsx +70 -0
  261. package/src/components/dialogs/import-snippet-dialog.tsx +84 -0
  262. package/src/components/dialogs/rename-snippet-dialog.tsx +81 -0
  263. package/src/components/dialogs/view-ts-files-dialog.tsx +89 -0
  264. package/src/components/ui/accordion.tsx +55 -0
  265. package/src/components/ui/alert-dialog.tsx +139 -0
  266. package/src/components/ui/alert.tsx +59 -0
  267. package/src/components/ui/aspect-ratio.tsx +5 -0
  268. package/src/components/ui/avatar.tsx +48 -0
  269. package/src/components/ui/badge.tsx +36 -0
  270. package/src/components/ui/breadcrumb.tsx +118 -0
  271. package/src/components/ui/button.tsx +58 -0
  272. package/src/components/ui/calendar.tsx +73 -0
  273. package/src/components/ui/card.tsx +76 -0
  274. package/src/components/ui/carousel.tsx +260 -0
  275. package/src/components/ui/chart.tsx +363 -0
  276. package/src/components/ui/checkbox.tsx +28 -0
  277. package/src/components/ui/collapsible.tsx +9 -0
  278. package/src/components/ui/combobox.tsx +178 -0
  279. package/src/components/ui/command.tsx +151 -0
  280. package/src/components/ui/context-menu.tsx +202 -0
  281. package/src/components/ui/dialog.tsx +120 -0
  282. package/src/components/ui/drawer.tsx +116 -0
  283. package/src/components/ui/dropdown-menu.tsx +203 -0
  284. package/src/components/ui/form.tsx +182 -0
  285. package/src/components/ui/hover-card.tsx +27 -0
  286. package/src/components/ui/input-otp.tsx +69 -0
  287. package/src/components/ui/input.tsx +25 -0
  288. package/src/components/ui/label.tsx +24 -0
  289. package/src/components/ui/menubar.tsx +238 -0
  290. package/src/components/ui/navigation-menu.tsx +129 -0
  291. package/src/components/ui/pagination.tsx +121 -0
  292. package/src/components/ui/popover.tsx +31 -0
  293. package/src/components/ui/progress.tsx +26 -0
  294. package/src/components/ui/radio-group.tsx +42 -0
  295. package/src/components/ui/resizable.tsx +43 -0
  296. package/src/components/ui/scroll-area.tsx +46 -0
  297. package/src/components/ui/searchable-select.tsx +94 -0
  298. package/src/components/ui/select.tsx +162 -0
  299. package/src/components/ui/separator.tsx +29 -0
  300. package/src/components/ui/sheet.tsx +141 -0
  301. package/src/components/ui/skeleton.tsx +18 -0
  302. package/src/components/ui/slider.tsx +26 -0
  303. package/src/components/ui/sonner.tsx +30 -0
  304. package/src/components/ui/switch.tsx +27 -0
  305. package/src/components/ui/table.tsx +120 -0
  306. package/src/components/ui/tabs.tsx +53 -0
  307. package/src/components/ui/textarea.tsx +24 -0
  308. package/src/components/ui/toast.tsx +128 -0
  309. package/src/components/ui/toaster.tsx +33 -0
  310. package/src/components/ui/toggle-group.tsx +59 -0
  311. package/src/components/ui/toggle.tsx +43 -0
  312. package/src/components/ui/tooltip.tsx +28 -0
  313. package/src/entry-server.tsx +12 -0
  314. package/src/hooks/use-account-balance.ts +24 -0
  315. package/src/hooks/use-ai-api.ts +35 -0
  316. package/src/hooks/use-axios.ts +20 -0
  317. package/src/hooks/use-code-completion-ai-api.ts +11 -0
  318. package/src/hooks/use-compiled-tsx.ts +37 -0
  319. package/src/hooks/use-copy-to-clipboard.ts +26 -0
  320. package/src/hooks/use-create-snippet-mutation.ts +62 -0
  321. package/src/hooks/use-current-snippet-id.ts +75 -0
  322. package/src/hooks/use-current-snippet.ts +24 -0
  323. package/src/hooks/use-global-store.ts +33 -0
  324. package/src/hooks/use-is-using-fake-api.ts +3 -0
  325. package/src/hooks/use-run-tsx/construct-circuit.tsx +64 -0
  326. package/src/hooks/use-run-tsx/eval-compiled-js.ts +9 -0
  327. package/src/hooks/use-run-tsx/index.tsx +251 -0
  328. package/src/hooks/use-save-snippet.ts +66 -0
  329. package/src/hooks/use-sign-in.ts +22 -0
  330. package/src/hooks/use-snippet-by-name.ts +25 -0
  331. package/src/hooks/use-snippet.ts +23 -0
  332. package/src/hooks/use-snippets-base-api-url.ts +3 -0
  333. package/src/hooks/use-toast.tsx +208 -0
  334. package/src/hooks/use-typecheck.ts +54 -0
  335. package/src/hooks/use-url-params.ts +31 -0
  336. package/src/hooks/use-warn-user-on-page-change.ts +23 -0
  337. package/src/hooks/useForkSnippetMutation.ts +52 -0
  338. package/src/index.css +21 -0
  339. package/src/lib/__tests__/constants.test.ts +66 -0
  340. package/src/lib/base64ToBytes.ts +5 -0
  341. package/src/lib/bytesToBase64.ts +4 -0
  342. package/src/lib/codemirror/basic-setup.ts +51 -0
  343. package/src/lib/constants.ts +12 -0
  344. package/src/lib/decodeUrlHashToText.ts +15 -0
  345. package/src/lib/defaultCodeForBlankCode.tsx +7 -0
  346. package/src/lib/download-fns/createBlobURL.ts +4 -0
  347. package/src/lib/download-fns/download-assembly-svg.ts +12 -0
  348. package/src/lib/download-fns/download-circuit-json-fn.ts +12 -0
  349. package/src/lib/download-fns/download-dsn-file-fn.ts +12 -0
  350. package/src/lib/download-fns/download-fabrication-files.ts +233 -0
  351. package/src/lib/download-fns/download-gltf.ts +49 -0
  352. package/src/lib/download-fns/download-kicad-files.ts +27 -0
  353. package/src/lib/download-fns/download-readable-netlist.ts +12 -0
  354. package/src/lib/download-fns/download-schematic-svg.ts +12 -0
  355. package/src/lib/download-fns/download-simple-route-json.ts +17 -0
  356. package/src/lib/encodeTextToUrlHash.ts +17 -0
  357. package/src/lib/get-snippet-template.ts +26 -0
  358. package/src/lib/handleManualEditsImport.tsx +65 -0
  359. package/src/lib/jlc-parts-engine.ts +69 -0
  360. package/src/lib/templates/blank-3d-model-template.ts +12 -0
  361. package/src/lib/templates/blank-circuit-board-template.ts +24 -0
  362. package/src/lib/templates/blank-footprint-template.ts +29 -0
  363. package/src/lib/templates/blank-package-template.ts +22 -0
  364. package/src/lib/templates/blinking-led-board-template.ts +63 -0
  365. package/src/lib/templates/manual-edits-template.ts +5 -0
  366. package/src/lib/templates/usb-c-led-flashlight-template.ts +22 -0
  367. package/src/lib/utils/checkIfManualEditsImported.ts +6 -0
  368. package/src/lib/utils/getSyntaxError.ts +13 -0
  369. package/src/lib/utils/index.ts +6 -0
  370. package/src/lib/utils/load-prettier.ts +18 -0
  371. package/src/lib/utils/parseFootprintParams.ts +52 -0
  372. package/src/lib/utils/parseJsonOrNull.ts +8 -0
  373. package/src/lib/utils/pcbManualEditEventHandler.ts +156 -0
  374. package/src/main.tsx +10 -0
  375. package/src/pages/ai.tsx +92 -0
  376. package/src/pages/authorize.tsx +54 -0
  377. package/src/pages/dashboard.tsx +165 -0
  378. package/src/pages/dev-login.tsx +68 -0
  379. package/src/pages/editor.tsx +28 -0
  380. package/src/pages/landing.tsx +236 -0
  381. package/src/pages/my-orders.tsx +54 -0
  382. package/src/pages/newest.tsx +16 -0
  383. package/src/pages/preview.tsx +70 -0
  384. package/src/pages/quickstart.tsx +198 -0
  385. package/src/pages/search.tsx +26 -0
  386. package/src/pages/settings.tsx +25 -0
  387. package/src/pages/user-profile.tsx +97 -0
  388. package/src/pages/view-order.tsx +123 -0
  389. package/src/pages/view-snippet.tsx +149 -0
  390. package/src/prettier.ts +9 -0
  391. package/src/vite-env.d.ts +1 -0
  392. package/tailwind.config.js +47 -0
  393. package/tsconfig.json +30 -0
  394. package/vercel.json +50 -0
  395. package/vite.config.ts +146 -0
  396. package/winterspec.config.ts +6 -0
@@ -0,0 +1,148 @@
1
+ import * as React from "react"
2
+ import { getImportsFromCode } from "@tscircuit/prompt-benchmarks/code-runner-utils"
3
+ import * as tscircuitCore from "@tscircuit/core"
4
+ import * as jscadFiber from "jscad-fiber"
5
+ import type { AnyCircuitElement } from "circuit-json"
6
+ import { safeCompileTsx } from "@/hooks/use-compiled-tsx"
7
+ import { evalCompiledJs } from "@/hooks/use-run-tsx/eval-compiled-js"
8
+ import { constructCircuit } from "@/hooks/use-run-tsx/construct-circuit"
9
+
10
+ type GenerateCircuitJson = {
11
+ code: string
12
+ type: "board" | "footprint" | "package" | "model"
13
+ compiled_js: string
14
+ }
15
+
16
+ // Keeping track of processed imports to avoid circular dependencies
17
+ const processedImports = new Set<string>()
18
+
19
+ async function processImport(
20
+ importName: string,
21
+ preSuppliedImports: Record<string, any>,
22
+ depth = 0,
23
+ code: string,
24
+ compiled_js: string,
25
+ ): Promise<void> {
26
+ if (!importName.startsWith("@tsci/")) return
27
+ if (preSuppliedImports[importName]) return
28
+ if (processedImports.has(importName)) return
29
+ if (depth > 5) {
30
+ throw new Error(
31
+ `Max depth for imports reached when processing ${importName}`,
32
+ )
33
+ }
34
+
35
+ processedImports.add(importName)
36
+
37
+ try {
38
+ // Process nested imports first
39
+ const nestedImports = getImportsFromCode(code)
40
+
41
+ // Filter out already processed imports and non-@tsci imports
42
+ const validNestedImports = nestedImports.filter(
43
+ (imp) =>
44
+ imp.startsWith("@tsci/") &&
45
+ !processedImports.has(imp) &&
46
+ !preSuppliedImports[imp],
47
+ )
48
+
49
+ // Process each valid nested import
50
+ for (const nestedImport of validNestedImports) {
51
+ await processImport(
52
+ nestedImport,
53
+ preSuppliedImports,
54
+ depth + 1,
55
+ code,
56
+ compiled_js,
57
+ )
58
+ }
59
+ // Set React in the global scope before evaluation
60
+ ;(globalThis as any).React = React
61
+ const exports = evalCompiledJs(compiled_js).exports
62
+
63
+ // Only set the import if we successfully evaluated it
64
+ if (exports) {
65
+ preSuppliedImports[importName] = exports
66
+ }
67
+ } catch (e) {
68
+ processedImports.delete(importName) // Clean up on error
69
+ }
70
+ }
71
+
72
+ export const generateCircuitJson = async ({
73
+ code,
74
+ type,
75
+ compiled_js,
76
+ }: GenerateCircuitJson): Promise<AnyCircuitElement[]> => {
77
+ // Clear the processed imports set at the start of each generation
78
+ processedImports.clear()
79
+
80
+ // Set up pre-supplied imports
81
+ const preSuppliedImports: Record<string, any> = {
82
+ "@tscircuit/core": tscircuitCore,
83
+ react: React,
84
+ "jscad-fiber": jscadFiber,
85
+ }
86
+ ;(globalThis as any).React = React
87
+ ;(globalThis as any).createElement = React.createElement
88
+
89
+ try {
90
+ // Process all @tsci imports
91
+ const tsciImports = getImportsFromCode(code).filter((imp) =>
92
+ imp.startsWith("@tsci/"),
93
+ )
94
+ for (const importName of tsciImports) {
95
+ await processImport(importName, preSuppliedImports, 0, code, compiled_js)
96
+ }
97
+
98
+ // Create require function for imports
99
+ const __tscircuit_require = (name: string) => {
100
+ if (!preSuppliedImports[name]) {
101
+ throw new Error(
102
+ `Import "${name}" not found (available imports: ${Object.keys(preSuppliedImports).join(", ")})`,
103
+ )
104
+ }
105
+ return preSuppliedImports[name]
106
+ }
107
+ ;(globalThis as any).__tscircuit_require = __tscircuit_require
108
+
109
+ // Add a custom JSX runtime
110
+ ;(globalThis as any).jsx = React.createElement
111
+ ;(globalThis as any).jsxs = React.createElement
112
+
113
+ const { success, compiledTsx, error } = safeCompileTsx(code)
114
+ if (!success || !compiledTsx) {
115
+ throw new Error(
116
+ `Compile Error: ${error?.message || "Unknown compilation error"}`,
117
+ )
118
+ }
119
+
120
+ const module = evalCompiledJs(compiledTsx)
121
+ const componentExportKeys = Object.keys(module.exports).filter(
122
+ (key) => !key.startsWith("use"),
123
+ )
124
+
125
+ if (componentExportKeys.length > 1) {
126
+ throw new Error(
127
+ `Too many exports, only export one component. Exports: ${JSON.stringify(componentExportKeys)}`,
128
+ )
129
+ }
130
+
131
+ const primaryKey = componentExportKeys[0]
132
+
133
+ // Create the user element with explicit React scope
134
+ const UserElm = function (props: any) {
135
+ return React.createElement(module.exports[primaryKey], props)
136
+ }
137
+
138
+ // Construct and render the circuit
139
+ const circuit = constructCircuit({ UserElm, type })
140
+
141
+ // Wait for the circuit to settle
142
+ await circuit.renderUntilSettled()
143
+
144
+ return circuit.getCircuitJson() as AnyCircuitElement[]
145
+ } catch (e) {
146
+ throw new Error("Circuit generation failed!")
147
+ }
148
+ }
@@ -0,0 +1,96 @@
1
+ import { afterEach } from "bun:test"
2
+ import { tmpdir } from "node:os"
3
+ import defaultAxios from "redaxios"
4
+ import { startServer } from "./start-server"
5
+ import { DbClient } from "fake-snippets-api/lib/db/db-client"
6
+
7
+ let testNumber = 1
8
+
9
+ interface TestFixture {
10
+ url: string
11
+ server: any
12
+ axios: typeof defaultAxios
13
+ db: DbClient
14
+ seed: ReturnType<typeof seedDatabase>
15
+ }
16
+
17
+ export const getTestServer = async (): Promise<TestFixture> => {
18
+ const port = 3000 + testNumber++
19
+ const testInstanceId = Math.random().toString(36).substring(2, 15)
20
+ const testDbName = `testdb${testInstanceId}`
21
+
22
+ const { server, db } = await startServer({
23
+ port,
24
+ testDbName,
25
+ })
26
+
27
+ const url = `http://127.0.0.1:${port}`
28
+ const seed = seedDatabase(db)
29
+ const axios = defaultAxios.create({
30
+ baseURL: url,
31
+ headers: {
32
+ Authorization: `Bearer ${seed.account.account_id}`,
33
+ },
34
+ })
35
+
36
+ afterEach(async () => {
37
+ if (server && typeof server.stop === "function") {
38
+ await server.stop()
39
+ }
40
+ // Here you might want to add logic to drop the test database
41
+ })
42
+
43
+ return {
44
+ url,
45
+ server,
46
+ axios,
47
+ db,
48
+ seed,
49
+ }
50
+ }
51
+
52
+ const seedDatabase = (db: DbClient) => {
53
+ const account = db.addAccount({
54
+ github_username: "testuser",
55
+ shippingInfo: {
56
+ firstName: "Test",
57
+ lastName: "User",
58
+ companyName: "Test Company",
59
+ address: "123 Test St",
60
+ apartment: "Apt 4B",
61
+ city: "Testville",
62
+ state: "NY",
63
+ zipCode: "10001",
64
+ country: "United States of America",
65
+ phone: "555-123-4567",
66
+ },
67
+ })
68
+ const order = db.addOrder({
69
+ account_id: account.account_id,
70
+ is_draft: true,
71
+ is_pending_validation_by_fab: false,
72
+ is_pending_review_by_fab: false,
73
+ is_validated_by_fab: false,
74
+ is_approved_by_fab_review: false,
75
+ is_approved_by_orderer: false,
76
+ is_in_production: false,
77
+ is_shipped: false,
78
+ is_cancelled: false,
79
+ should_be_blank_pcb: false,
80
+ should_include_stencil: false,
81
+ jlcpcb_order_params: {},
82
+ circuit_json: [
83
+ {
84
+ type: "source_component",
85
+ ftype: "simple_resistor",
86
+ source_component_id: "source_component_1",
87
+ name: "R1",
88
+ resistance: "1k",
89
+ },
90
+ ],
91
+ created_at: new Date().toISOString(),
92
+ updated_at: new Date().toISOString(),
93
+ })
94
+
95
+ return { account, order }
96
+ }
@@ -0,0 +1,44 @@
1
+ import {
2
+ createFetchHandlerFromDir,
3
+ createWinterSpecBundleFromDir,
4
+ } from "winterspec/adapters/node"
5
+ import { Request as EdgeRuntimeRequest } from "@edge-runtime/primitives"
6
+ import { join } from "node:path"
7
+ import os from "node:os"
8
+ import type { Middleware } from "winterspec"
9
+ import { createDatabase } from "fake-snippets-api/lib/db/db-client"
10
+
11
+ export const startServer = async ({
12
+ port,
13
+ testDbName,
14
+ }: { port: number; testDbName: string }) => {
15
+ const winterspecBundle = await createWinterSpecBundleFromDir(
16
+ join(import.meta.dir, "../../../fake-snippets-api/routes"),
17
+ )
18
+
19
+ const db = createDatabase()
20
+
21
+ const middleware: Middleware[] = [
22
+ async (req: any, ctx: any, next: any) => {
23
+ ;(ctx as any).db = db
24
+
25
+ return next(req, ctx)
26
+ },
27
+ ]
28
+
29
+ const server = Bun.serve({
30
+ fetch: (bunReq) => {
31
+ const req = new EdgeRuntimeRequest(bunReq.url, {
32
+ headers: bunReq.headers,
33
+ method: bunReq.method,
34
+ body: bunReq.body,
35
+ })
36
+ return winterspecBundle.makeRequest(req as any, {
37
+ middleware,
38
+ })
39
+ },
40
+ port,
41
+ })
42
+
43
+ return { server: { ...server, stop: () => server.stop() }, db }
44
+ }
@@ -0,0 +1,18 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { test, expect } from "bun:test"
3
+
4
+ test("get account balance", async () => {
5
+ const { axios } = await getTestServer()
6
+
7
+ const response = await axios.get("/api/accounts/get_account_balance", {
8
+ headers: {
9
+ Authorization: "Bearer 1234",
10
+ },
11
+ })
12
+
13
+ expect(response.status).toBe(200)
14
+ expect(response.data.account_balance).toBeDefined()
15
+ expect(typeof response.data.account_balance.monthly_ai_budget_used_usd).toBe(
16
+ "number",
17
+ )
18
+ })
@@ -0,0 +1,9 @@
1
+ import { it, expect } from "bun:test"
2
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
3
+
4
+ it("GET /health should return ok", async () => {
5
+ const { axios, url } = await getTestServer()
6
+ const res = await axios.get("/api/health")
7
+ expect(res.status).toBe(200)
8
+ expect(res.data).toEqual({ ok: true })
9
+ })
@@ -0,0 +1,48 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { test, expect } from "bun:test"
3
+
4
+ test("get order file", async () => {
5
+ const {
6
+ axios,
7
+ seed: {
8
+ order: { order_id },
9
+ },
10
+ } = await getTestServer()
11
+
12
+ const fileContent = "test file content"
13
+ const fileContentBase64 = Buffer.from(fileContent).toString("base64")
14
+
15
+ const uploadResponse = await axios.post("/api/order_files/upload", {
16
+ order_id,
17
+ content_base64: fileContentBase64,
18
+ is_gerbers_zip: false,
19
+ })
20
+
21
+ const orderFileId = uploadResponse.data.order_file.order_file_id
22
+
23
+ const response = await axios.get("/api/order_files/get", {
24
+ params: { order_file_id: orderFileId },
25
+ })
26
+
27
+ expect(response.status).toBe(200)
28
+ expect(response.data.order_file).toBeDefined()
29
+ expect(response.data.order_file.order_file_id).toBe(orderFileId)
30
+ expect(response.data.order_file.order_id).toBe(order_id)
31
+ expect(response.data.order_file.content_type).toBe("base64")
32
+ expect(response.data.order_file.is_gerbers_zip).toBe(false)
33
+ })
34
+
35
+ test("get non-existent order file", async () => {
36
+ const { axios } = await getTestServer()
37
+
38
+ try {
39
+ await axios.get("/api/order_files/get", {
40
+ params: { order_file_id: "non-existent-id" },
41
+ })
42
+
43
+ expect(true).toBe(false)
44
+ } catch (error: any) {
45
+ expect(error.status).toBe(404)
46
+ expect(error.data.error.message).toBe("Order file not found")
47
+ }
48
+ })
@@ -0,0 +1,77 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { test, expect } from "bun:test"
3
+
4
+ test("upload order file", async () => {
5
+ const {
6
+ axios,
7
+ seed: {
8
+ order: { order_id },
9
+ },
10
+ } = await getTestServer()
11
+
12
+ const fileContent = "test file content"
13
+ const fileContentBase64 = Buffer.from(fileContent).toString("base64")
14
+
15
+ const response = await axios.post("/api/order_files/upload", {
16
+ order_id,
17
+ content_base64: fileContentBase64,
18
+ is_gerbers_zip: false,
19
+ })
20
+
21
+ expect(response.status).toBe(200)
22
+ expect(response.data.order_file).toBeDefined()
23
+ expect(response.data.order_file.order_id).toBe(order_id)
24
+ expect(response.data.order_file.file_content).toBeDefined()
25
+ expect(response.data.order_file.content_type).toBe("base64")
26
+ expect(response.data.order_file.is_gerbers_zip).toBe(false)
27
+ expect(response.data.order_file.uploaded_at).toBeDefined()
28
+ })
29
+
30
+ test("upload order file with for_provider", async () => {
31
+ const { axios, db } = await getTestServer()
32
+
33
+ const orderResponse = await axios.post("/api/orders/create", {
34
+ circuit_json: [{ test: "circuit data" }],
35
+ })
36
+
37
+ const orderId = orderResponse.data.order.order_id
38
+
39
+ const fileContent = "test file content for provider"
40
+ const fileContentBase64 = Buffer.from(fileContent).toString("base64")
41
+
42
+ const response = await axios.post("/api/order_files/upload", {
43
+ order_id: orderId,
44
+ content_base64: fileContentBase64,
45
+ is_gerbers_zip: true,
46
+ for_provider: "jlcpcb",
47
+ })
48
+
49
+ expect(response.status).toBe(200)
50
+ expect(response.data.order_file).toBeDefined()
51
+ expect(response.data.order_file.order_id).toBe(orderId)
52
+ expect(response.data.order_file.file_content).toBeDefined()
53
+ expect(response.data.order_file.content_type).toBe("base64")
54
+ expect(response.data.order_file.is_gerbers_zip).toBe(true)
55
+ expect(response.data.order_file.for_provider).toBe("jlcpcb")
56
+ expect(response.data.order_file.uploaded_at).toBeDefined()
57
+ })
58
+
59
+ test("upload order file for non-existent order", async () => {
60
+ const { axios } = await getTestServer()
61
+
62
+ const fileContent = "test file content"
63
+ const fileContentBase64 = Buffer.from(fileContent).toString("base64")
64
+
65
+ try {
66
+ await axios.post("/api/order_files/upload", {
67
+ order_id: "non-existent-order-id",
68
+ content_base64: fileContentBase64,
69
+ is_gerbers_zip: false,
70
+ })
71
+ // If the request doesn't throw an error, fail the test
72
+ expect(true).toBe(false)
73
+ } catch (error: any) {
74
+ expect(error.status).toBe(404)
75
+ expect(error.data.error.message).toBe("Order not found")
76
+ }
77
+ })
@@ -0,0 +1,19 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { test, expect } from "bun:test"
3
+
4
+ test("create order", async () => {
5
+ const {
6
+ axios,
7
+ seed: { order },
8
+ } = await getTestServer()
9
+
10
+ const response = await axios.post("/api/orders/create", {
11
+ circuit_json: order.circuit_json,
12
+ })
13
+
14
+ expect(response.status).toBe(200)
15
+ expect(response.data.order).toBeDefined()
16
+ expect(response.data.order.account_id).toBe("account-1234")
17
+ expect(response.data.order.is_draft).toBe(true)
18
+ expect(response.data.order.circuit_json).toEqual(order.circuit_json)
19
+ })
@@ -0,0 +1,38 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { test, expect } from "bun:test"
3
+
4
+ test("get order", async () => {
5
+ const {
6
+ axios,
7
+ seed: { order, account },
8
+ } = await getTestServer()
9
+
10
+ const orderId = order.order_id
11
+
12
+ // Get the seeded order
13
+ const response = await axios.get("/api/orders/get", {
14
+ params: { order_id: orderId },
15
+ })
16
+
17
+ expect(response.status).toBe(200)
18
+ expect(response.data.order).toBeDefined()
19
+ expect(response.data.order.order_id).toBe(orderId)
20
+ expect(response.data.order.account_id).toBe(account.account_id)
21
+ expect(response.data.order.is_draft).toBe(true)
22
+ })
23
+
24
+ test("get non-existent order", async () => {
25
+ const { axios } = await getTestServer()
26
+
27
+ try {
28
+ await axios.get("/api/orders/get", {
29
+ params: { order_id: "non-existent-id" },
30
+ })
31
+
32
+ // If the request doesn't throw an error, fail the test
33
+ expect(true).toBe(false)
34
+ } catch (error: any) {
35
+ expect(error.status).toBe(404)
36
+ expect(error.data.error.message).toBe("Order not found")
37
+ }
38
+ })
@@ -0,0 +1,30 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { test, expect } from "bun:test"
3
+
4
+ test("list orders", async () => {
5
+ const {
6
+ axios,
7
+ seed: { order },
8
+ } = await getTestServer()
9
+
10
+ await axios.post("/api/orders/create", {
11
+ circuit_json: order.circuit_json,
12
+ })
13
+
14
+ const response = await axios.get("/api/orders/list")
15
+
16
+ expect(response.status).toBe(200)
17
+ expect(response.data.orders).toBeDefined()
18
+ expect(response.data.orders).toHaveLength(1)
19
+ expect(response.data.orders[0].circuit_json).toEqual(order.circuit_json)
20
+ })
21
+
22
+ test("list orders with empty result", async () => {
23
+ const { axios } = await getTestServer()
24
+
25
+ const response = await axios.get("/api/orders/list")
26
+
27
+ expect(response.status).toBe(200)
28
+ expect(response.data.orders).toBeDefined()
29
+ expect(response.data.orders).toHaveLength(0)
30
+ })
@@ -0,0 +1,46 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { test, expect } from "bun:test"
3
+
4
+ test("update order", async () => {
5
+ const {
6
+ axios,
7
+ seed: {
8
+ order: { order_id },
9
+ },
10
+ } = await getTestServer()
11
+
12
+ const response = await axios.patch("/api/orders/update", {
13
+ order_id,
14
+ updates: {
15
+ is_draft: false,
16
+ is_pending_validation_by_fab: true,
17
+ jlcpcb_order_params: { param1: "value1" },
18
+ },
19
+ })
20
+
21
+ expect(response.status).toBe(200)
22
+ expect(response.data.order).toBeDefined()
23
+ expect(response.data.order.order_id).toBe(order_id)
24
+ expect(response.data.order.is_draft).toBe(false)
25
+ expect(response.data.order.is_pending_validation_by_fab).toBe(true)
26
+ expect(response.data.order.jlcpcb_order_params).toEqual({ param1: "value1" })
27
+ })
28
+
29
+ test("update non-existent order", async () => {
30
+ const { axios } = await getTestServer()
31
+
32
+ try {
33
+ await axios.patch("/api/orders/update", {
34
+ order_id: "non-existent-id",
35
+ updates: {
36
+ is_draft: false,
37
+ },
38
+ })
39
+
40
+ // If the request doesn't throw an error, fail the test
41
+ expect(true).toBe(false)
42
+ } catch (error: any) {
43
+ expect(error.status).toBe(404)
44
+ expect(error.data.error.message).toBe("Order not found")
45
+ }
46
+ })
@@ -0,0 +1,114 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { test, expect } from "bun:test"
3
+
4
+ test("add star to snippet", async () => {
5
+ const { axios, db } = await getTestServer()
6
+
7
+ // Add a test snippet
8
+ const snippet = {
9
+ unscoped_name: "TestSnippet",
10
+ owner_name: "otheruser",
11
+ code: "Test Content",
12
+ created_at: "2023-01-01T00:00:00Z",
13
+ updated_at: "2023-01-01T00:00:00Z",
14
+ name: "otheruser/TestSnippet",
15
+ snippet_type: "package",
16
+ description: "Test Description",
17
+ }
18
+ const addedSnippet = db.addSnippet(snippet as any)!
19
+
20
+ // Star the snippet
21
+ const response = await axios.post(
22
+ "/api/snippets/add_star",
23
+ {
24
+ snippet_id: addedSnippet.snippet_id,
25
+ },
26
+ {
27
+ headers: {
28
+ Authorization: "Bearer 1234",
29
+ },
30
+ },
31
+ )
32
+
33
+ expect(response.status).toBe(200)
34
+ expect(response.data.ok).toBe(true)
35
+ expect(response.data.account_snippet).toBeDefined()
36
+ expect(response.data.account_snippet.snippet_id).toBe(addedSnippet.snippet_id)
37
+ expect(response.data.account_snippet.has_starred).toBe(true)
38
+
39
+ // Verify star was added in database
40
+ expect(db.hasStarred("account-1234", addedSnippet.snippet_id)).toBe(true)
41
+ })
42
+
43
+ test("add star to non-existent snippet", async () => {
44
+ const { axios } = await getTestServer()
45
+
46
+ try {
47
+ await axios.post(
48
+ "/api/snippets/add_star",
49
+ {
50
+ snippet_id: "non-existent-id",
51
+ },
52
+ {
53
+ headers: {
54
+ Authorization: "Bearer 1234",
55
+ },
56
+ },
57
+ )
58
+ expect(true).toBe(false) // Should not reach here
59
+ } catch (error: any) {
60
+ expect(error.status).toBe(404)
61
+ expect(error.data.error.message).toBe("Snippet not found")
62
+ }
63
+ })
64
+
65
+ test("add star to already starred snippet", async () => {
66
+ const { axios, db } = await getTestServer()
67
+
68
+ // Add a test snippet
69
+ const snippet = {
70
+ unscoped_name: "TestSnippet",
71
+ owner_name: "otheruser",
72
+ code: "Test Content",
73
+ created_at: "2023-01-01T00:00:00Z",
74
+ updated_at: "2023-01-01T00:00:00Z",
75
+ name: "otheruser/TestSnippet",
76
+ snippet_type: "package",
77
+ description: "Test Description",
78
+ }
79
+ const addedSnippet = db.addSnippet(snippet as any)
80
+
81
+ // Star the snippet first time
82
+ await axios.post(
83
+ "/api/snippets/add_star",
84
+ {
85
+ snippet_id: addedSnippet.snippet_id,
86
+ },
87
+ {
88
+ headers: {
89
+ Authorization: "Bearer 1234",
90
+ },
91
+ },
92
+ )
93
+
94
+ // Try to star again
95
+ try {
96
+ await axios.post(
97
+ "/api/snippets/add_star",
98
+ {
99
+ snippet_id: addedSnippet.snippet_id,
100
+ },
101
+ {
102
+ headers: {
103
+ Authorization: "Bearer 1234",
104
+ },
105
+ },
106
+ )
107
+ expect(true).toBe(false) // Should not reach here
108
+ } catch (error: any) {
109
+ expect(error.status).toBe(400)
110
+ expect(error.data.error.message).toBe(
111
+ "You have already starred this snippet",
112
+ )
113
+ }
114
+ })