@tscircuit/fake-snippets 0.0.108 → 0.0.110

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 (203) hide show
  1. package/.github/workflows/bun-formatcheck.yml +2 -2
  2. package/.github/workflows/bun-pver-release.yml +3 -3
  3. package/.github/workflows/bun-test.yml +1 -1
  4. package/.github/workflows/bun-typecheck.yml +2 -2
  5. package/.github/workflows/update-snapshots.yml +1 -1
  6. package/README.md +4 -0
  7. package/api/generated-index.js +37 -3
  8. package/biome.json +2 -1
  9. package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +31 -3
  10. package/bun-tests/fake-snippets-api/fixtures/preload.ts +18 -0
  11. package/bun-tests/fake-snippets-api/routes/orgs/add_member.test.ts +26 -0
  12. package/bun-tests/fake-snippets-api/routes/orgs/create.test.ts +37 -0
  13. package/bun-tests/fake-snippets-api/routes/orgs/get.test.ts +52 -0
  14. package/bun-tests/fake-snippets-api/routes/orgs/list.test.ts +17 -0
  15. package/bun-tests/fake-snippets-api/routes/orgs/list_members.test.ts +23 -0
  16. package/bun-tests/fake-snippets-api/routes/orgs/remove_member.test.ts +81 -0
  17. package/bun-tests/fake-snippets-api/routes/orgs/update.test.ts +99 -0
  18. package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +1 -1
  19. package/bun-tests/fake-snippets-api/routes/package_files/create.test.ts +15 -13
  20. package/bun-tests/fake-snippets-api/routes/package_files/create_or_update.test.ts +26 -24
  21. package/bun-tests/fake-snippets-api/routes/package_files/delete.test.ts +9 -9
  22. package/bun-tests/fake-snippets-api/routes/package_files/download.test.ts +4 -4
  23. package/bun-tests/fake-snippets-api/routes/package_files/get.test.ts +38 -28
  24. package/bun-tests/fake-snippets-api/routes/package_files/list.test.ts +23 -15
  25. package/bun-tests/fake-snippets-api/routes/package_releases/create.test.ts +33 -0
  26. package/bun-tests/fake-snippets-api/routes/package_releases/get.test.ts +4 -4
  27. package/bun-tests/fake-snippets-api/routes/package_releases/get_image_generation_fields.test.ts +38 -0
  28. package/bun-tests/fake-snippets-api/routes/packages/create.test.ts +19 -0
  29. package/bun-tests/fake-snippets-api/routes/packages/fork.test.ts +3 -4
  30. package/bun-tests/fake-snippets-api/routes/packages/get.test.ts +30 -0
  31. package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +4 -2
  32. package/bun-tests/fake-snippets-api/routes/packages/list-1.test.ts +34 -0
  33. package/bun.lock +389 -450
  34. package/bunfig.toml +2 -1
  35. package/dist/bundle.js +1255 -625
  36. package/dist/index.d.ts +296 -4
  37. package/dist/index.js +325 -24
  38. package/dist/schema.d.ts +282 -1
  39. package/dist/schema.js +54 -2
  40. package/fake-snippets-api/lib/db/autoload-dev-packages.ts +31 -20
  41. package/fake-snippets-api/lib/db/db-client.ts +214 -3
  42. package/fake-snippets-api/lib/db/schema.ts +62 -0
  43. package/fake-snippets-api/lib/db/seed.ts +100 -0
  44. package/fake-snippets-api/lib/middleware/with-session-auth.ts +1 -1
  45. package/fake-snippets-api/lib/package_file/get-package-file-id-from-file-descriptor.ts +2 -2
  46. package/fake-snippets-api/lib/public-mapping/public-map-org.ts +32 -0
  47. package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +10 -0
  48. package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +17 -0
  49. package/fake-snippets-api/routes/api/orgs/add_member.ts +52 -0
  50. package/fake-snippets-api/routes/api/orgs/create.ts +46 -0
  51. package/fake-snippets-api/routes/api/orgs/get.ts +39 -0
  52. package/fake-snippets-api/routes/api/orgs/list.ts +31 -0
  53. package/fake-snippets-api/routes/api/orgs/list_members.ts +67 -0
  54. package/fake-snippets-api/routes/api/orgs/remove_member.ts +46 -0
  55. package/fake-snippets-api/routes/api/orgs/update.ts +93 -0
  56. package/fake-snippets-api/routes/api/package_files/get.ts +3 -6
  57. package/fake-snippets-api/routes/api/package_files/list.ts +7 -4
  58. package/fake-snippets-api/routes/api/packages/create.ts +54 -10
  59. package/fake-snippets-api/routes/api/packages/get.ts +23 -0
  60. package/fake-snippets-api/routes/api/packages/images/[owner_github_username]/[unscoped_name]/[view_format].ts +13 -11
  61. package/fake-snippets-api/routes/api/packages/list.ts +29 -2
  62. package/fake-snippets-api/routes/api/packages/update_ai_description.ts +37 -0
  63. package/package.json +27 -24
  64. package/renovate.json +1 -1
  65. package/scripts/generate-sitemap.ts +1 -1
  66. package/src/App.tsx +29 -10
  67. package/src/ContextProviders.tsx +25 -2
  68. package/src/components/CircuitJsonImportDialog.tsx +1 -1
  69. package/src/components/CmdKMenu.tsx +281 -247
  70. package/src/components/DownloadButtonAndMenu.tsx +133 -36
  71. package/src/components/FileSidebar.tsx +41 -50
  72. package/src/components/Footer.tsx +8 -10
  73. package/src/components/Header.tsx +19 -32
  74. package/src/components/Header2.tsx +16 -32
  75. package/src/components/HeaderDropdown.tsx +13 -8
  76. package/src/components/HeaderLogin.tsx +44 -16
  77. package/src/components/HiddenFilesDropdown.tsx +0 -2
  78. package/src/components/NotFound.tsx +5 -5
  79. package/src/components/PackageBreadcrumb.tsx +6 -12
  80. package/src/components/PackageCard.tsx +0 -1
  81. package/src/components/PackageSearchResults.tsx +1 -1
  82. package/src/components/PrefetchPageLink.tsx +7 -1
  83. package/src/components/ProfileRouter.tsx +32 -0
  84. package/src/components/SearchComponent.tsx +12 -8
  85. package/src/components/UserCard.tsx +80 -0
  86. package/src/components/ViewPackagePage/components/ShikiCodeViewer.tsx +20 -11
  87. package/src/components/ViewPackagePage/components/build-status.tsx +1 -1
  88. package/src/components/ViewPackagePage/components/important-files-view.tsx +174 -87
  89. package/src/components/ViewPackagePage/components/main-content-header.tsx +8 -4
  90. package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +1 -2
  91. package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +54 -20
  92. package/src/components/ViewPackagePage/components/package-header.tsx +26 -37
  93. package/src/components/ViewPackagePage/components/preview-image-squares.tsx +11 -19
  94. package/src/components/ViewPackagePage/components/repo-page-content.tsx +33 -25
  95. package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +16 -10
  96. package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +11 -11
  97. package/src/components/ViewPackagePage/components/sidebar.tsx +0 -2
  98. package/src/components/ViewPackagePage/components/tab-views/files-view.tsx +18 -17
  99. package/src/components/ViewPackagePage/components/tab-views/pcb-view.tsx +1 -2
  100. package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +2 -1
  101. package/src/components/ViewPackagePage/components/theme-toggle.tsx +0 -2
  102. package/src/components/ViewPackagePage/hooks/use-toast.tsx +0 -1
  103. package/src/components/dialogs/GitHubRepositorySelector.tsx +56 -49
  104. package/src/components/dialogs/edit-package-details-dialog.tsx +5 -6
  105. package/src/components/dialogs/import-component-dialog.tsx +16 -9
  106. package/src/components/dialogs/import-package-dialog.tsx +3 -2
  107. package/src/components/dialogs/new-package-save-prompt-dialog.tsx +190 -0
  108. package/src/components/organization/OrganizationCard.tsx +204 -0
  109. package/src/components/organization/OrganizationCardSkeleton.tsx +55 -0
  110. package/src/components/organization/OrganizationHeader.tsx +154 -0
  111. package/src/components/organization/OrganizationMembers.tsx +146 -0
  112. package/src/components/package-port/CodeAndPreview.tsx +32 -46
  113. package/src/components/package-port/CodeEditor.tsx +28 -31
  114. package/src/components/package-port/CodeEditorHeader.tsx +128 -63
  115. package/src/components/package-port/EditorNav.tsx +32 -49
  116. package/src/components/preview/ConnectedPackagesList.tsx +8 -8
  117. package/src/components/preview/ConnectedRepoOverview.tsx +102 -2
  118. package/src/components/preview/PackageReleasesDashboard.tsx +53 -36
  119. package/src/components/ui/tree-view.tsx +6 -3
  120. package/src/hooks/use-add-org-member-mutation.ts +51 -0
  121. package/src/hooks/use-create-org-mutation.ts +38 -0
  122. package/src/hooks/use-create-package-mutation.ts +3 -0
  123. package/src/hooks/use-current-package-id.ts +5 -30
  124. package/src/hooks/use-current-package-info.ts +29 -5
  125. package/src/hooks/use-current-package-release.ts +4 -3
  126. package/src/hooks/use-download-zip.ts +2 -2
  127. package/src/hooks/use-global-store.ts +6 -4
  128. package/src/hooks/use-jlcpcb-component-import.tsx +164 -0
  129. package/src/hooks/use-list-org-members.ts +27 -0
  130. package/src/hooks/use-list-user-orgs.ts +25 -0
  131. package/src/hooks/use-org-by-github-handle.ts +26 -0
  132. package/src/hooks/use-org.ts +24 -0
  133. package/src/hooks/use-organization.ts +42 -0
  134. package/src/hooks/use-package-as-snippet.ts +4 -2
  135. package/src/hooks/use-package-builds.ts +6 -2
  136. package/src/hooks/use-package-files.ts +5 -3
  137. package/src/hooks/use-package-release-by-id-or-version.ts +29 -20
  138. package/src/hooks/use-package-release-images.ts +105 -0
  139. package/src/hooks/use-package-release.ts +2 -2
  140. package/src/hooks/use-package-stars.ts +80 -4
  141. package/src/hooks/use-preview-images.ts +6 -3
  142. package/src/hooks/use-remove-org-member-mutation.ts +32 -0
  143. package/src/hooks/use-update-ai-description-mutation.ts +42 -0
  144. package/src/hooks/use-update-org-mutation.ts +41 -0
  145. package/src/hooks/use-warn-user-on-page-change.ts +71 -4
  146. package/src/hooks/useFileManagement.ts +183 -35
  147. package/src/hooks/useOptimizedPackageFilesLoader.ts +136 -0
  148. package/src/hooks/usePackageFilesLoader.ts +2 -2
  149. package/src/hooks/useUpdatePackageFilesMutation.ts +15 -1
  150. package/src/lib/download-fns/download-circuit-png.ts +11 -3
  151. package/src/lib/download-fns/download-gltf-from-circuit-json.ts +44 -0
  152. package/src/lib/download-fns/download-kicad-files.ts +12 -11
  153. package/src/lib/normalize-svg-for-tile.ts +50 -0
  154. package/src/lib/posthog.ts +11 -9
  155. package/src/lib/react-query-api-failure-tracking.ts +148 -0
  156. package/src/lib/sentry.ts +14 -0
  157. package/src/lib/templates/blank-circuit-board-template.ts +0 -4
  158. package/src/lib/ts-lib-cache.ts +122 -7
  159. package/src/lib/utils/checkIfManualEditsImported.ts +4 -4
  160. package/src/lib/utils/findTargetFile.ts +45 -10
  161. package/src/lib/utils/isComponentExported.ts +10 -0
  162. package/src/main.tsx +2 -1
  163. package/src/pages/authorize.tsx +0 -2
  164. package/src/pages/create-organization.tsx +168 -0
  165. package/src/pages/dashboard.tsx +38 -6
  166. package/src/pages/datasheet.tsx +1 -1
  167. package/src/pages/datasheets.tsx +3 -3
  168. package/src/pages/editor.tsx +4 -6
  169. package/src/pages/landing.tsx +6 -7
  170. package/src/pages/latest.tsx +3 -0
  171. package/src/pages/organization-profile.tsx +199 -0
  172. package/src/pages/organization-settings.tsx +566 -0
  173. package/src/pages/package-editor.tsx +21 -21
  174. package/src/pages/preview-release.tsx +76 -136
  175. package/src/pages/quickstart.tsx +159 -123
  176. package/src/pages/release-detail.tsx +119 -31
  177. package/src/pages/search.tsx +192 -57
  178. package/src/pages/settings-redirect.tsx +44 -0
  179. package/src/pages/trending.tsx +29 -20
  180. package/src/pages/user-profile.tsx +58 -7
  181. package/src/pages/view-package.tsx +21 -26
  182. package/vite.config.ts +9 -0
  183. package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +0 -133
  184. package/src/components/Footer2.tsx +0 -100
  185. package/src/components/JLCPCBImportDialog.tsx +0 -280
  186. package/src/components/PackageBuildsPage/LogContent.tsx +0 -72
  187. package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +0 -115
  188. package/src/components/PackageBuildsPage/build-preview-content.tsx +0 -27
  189. package/src/components/PackageBuildsPage/collapsible-section.tsx +0 -63
  190. package/src/components/PackageBuildsPage/package-build-details-panel.tsx +0 -166
  191. package/src/components/PackageBuildsPage/package-build-header.tsx +0 -79
  192. package/src/components/PageSearchComponent.tsx +0 -148
  193. package/src/components/ShippingInformationForm.tsx +0 -423
  194. package/src/components/StaticViewSnippetHeader.tsx +0 -70
  195. package/src/components/ViewPackagePage/components/file-explorer.tsx +0 -67
  196. package/src/components/ViewPackagePage/components/readme-view.tsx +0 -58
  197. package/src/components/ViewPackagePage/components/repo-header-button.tsx +0 -36
  198. package/src/components/ViewPackagePage/components/repo-header.tsx +0 -4
  199. package/src/components/ViewPackagePage/components/sidebar-contributors-section.tsx +0 -31
  200. package/src/components/ViewSnippetHeader.tsx +0 -181
  201. package/src/components/ui/input-otp.tsx +0 -69
  202. package/src/pages/package-builds.tsx +0 -33
  203. package/src/pages/settings.tsx +0 -25
@@ -16,7 +16,7 @@ const extractTsciDependencies = (
16
16
  }
17
17
 
18
18
  const registryApi = axios.create({
19
- baseURL: "https://registry-api.tscircuit.com",
19
+ baseURL: "https://api.tscircuit.com",
20
20
  headers: {
21
21
  Accept: "application/json",
22
22
  "Content-Type": "application/json",
@@ -25,7 +25,7 @@ const registryApi = axios.create({
25
25
 
26
26
  const fetchPackageFromRegistry = async (owner: string, name: string) => {
27
27
  const fullName = `${owner}/${name}`
28
- console.log(`Fetching package ${fullName}...`)
28
+ console.log(`[autoload-dev-pkgs] 📦 Fetching package ${fullName}...`)
29
29
 
30
30
  let packageData
31
31
  try {
@@ -46,35 +46,42 @@ const fetchPackageFromRegistry = async (owner: string, name: string) => {
46
46
  })
47
47
  releaseData = response.data
48
48
  } catch (e) {
49
- console.error(`Failed to fetch release data for ${fullName}:`, e)
49
+ console.error(
50
+ `[autoload-dev-pkgs] ❌ Failed to fetch release data for ${fullName}:`,
51
+ e,
52
+ )
50
53
  throw e
51
54
  }
52
55
 
53
56
  let filesData
54
57
  try {
55
- const response = await registryApi.post("/package_files/list", {
56
- package_release_id: releaseData.package_release.package_release_id,
57
- })
58
+ const response = await registryApi.post(
59
+ `package_files/list?package_release_id=${releaseData.package_release.package_release_id}`,
60
+ {},
61
+ )
58
62
  filesData = response.data
59
63
 
60
64
  // Fetch content_text for each file individually
61
65
  for (const file of filesData.package_files) {
62
66
  try {
63
- const fileResponse = await registryApi.post("/package_files/get", {
64
- package_release_id: releaseData.package_release.package_release_id,
65
- file_path: file.file_path,
66
- })
67
+ const fileResponse = await registryApi.post(
68
+ `/package_files/get?package_file_id=${file.package_file_id}`,
69
+ {},
70
+ )
67
71
  file.content_text = fileResponse.data.package_file.content_text
68
72
  } catch (e) {
69
73
  console.error(
70
- `Failed to fetch content for file ${file.file_path} in package ${fullName}:`,
74
+ `[autoload-dev-pkgs] ❌ Failed to fetch content for file ${file.file_path} in package ${fullName}:`,
71
75
  e,
72
76
  )
73
77
  throw e
74
78
  }
75
79
  }
76
80
  } catch (e) {
77
- console.error(`Failed to fetch files data for ${fullName}:`, e)
81
+ console.error(
82
+ `[autoload-dev-pkgs] ❌ Failed to fetch files data for ${fullName}:`,
83
+ e,
84
+ )
78
85
  throw e
79
86
  }
80
87
 
@@ -100,7 +107,7 @@ const loadPackageWithDependencies = async (
100
107
  try {
101
108
  result = await fetchPackageFromRegistry(owner, name)
102
109
  } catch (e) {
103
- console.error(`✗ Failed to load ${packageKey}`)
110
+ console.error(`[autoload-dev-pkgs] Failed to load ${packageKey}`)
104
111
  return false
105
112
  }
106
113
 
@@ -108,7 +115,7 @@ const loadPackageWithDependencies = async (
108
115
 
109
116
  // Check if package already exists
110
117
  if (db.getPackageById(pkg.package_id)) {
111
- console.log(`✓ Package ${packageKey} already exists`)
118
+ console.log(`[autoload-dev-pkgs] Package ${packageKey} already exists`)
112
119
  return true
113
120
  }
114
121
 
@@ -142,7 +149,7 @@ const loadPackageWithDependencies = async (
142
149
  }
143
150
 
144
151
  loadedPackages.add(packageKey)
145
- console.log(`✓ Loaded ${packageKey}`)
152
+ console.log(`[autoload-dev-pkgs] 📦 Loaded ${packageKey}`)
146
153
 
147
154
  // Load dependencies
148
155
  const mainFile = files.find(
@@ -165,7 +172,7 @@ const loadPackageWithDependencies = async (
165
172
  if (!depLoaded) {
166
173
  allDepsLoaded = false
167
174
  console.warn(
168
- `⚠️ Failed to load dependency ${dep.owner}/${dep.name} for ${packageKey}`,
175
+ `[autoload-dev-pkgs] ⚠️ Failed to load dependency ${dep.owner}/${dep.name} for ${packageKey}`,
169
176
  )
170
177
  }
171
178
  }
@@ -180,7 +187,7 @@ export const loadAutoloadPackages = async (db: DbClient) => {
180
187
  "autoload-packages.json",
181
188
  )
182
189
  if (!fs.existsSync(autoloadPath)) {
183
- console.error("No autoload-packages.json found")
190
+ console.error("[autoload-dev-pkgs] ❌ No autoload-packages.json found")
184
191
  return
185
192
  }
186
193
 
@@ -203,9 +210,13 @@ export const loadAutoloadPackages = async (db: DbClient) => {
203
210
  }
204
211
  }
205
212
 
206
- console.log(`\nPackage loading complete:`)
207
- console.log(`✓ Successfully loaded: ${successCount} packages`)
213
+ console.log(`\n[autoload-dev-pkgs] 📋 Package loading complete:`)
214
+ console.log(
215
+ `[autoload-dev-pkgs] ✅ Successfully loaded: ${successCount} packages`,
216
+ )
208
217
  if (failureCount > 0) {
209
- console.log(`✗ Failed to load: ${failureCount} packages`)
218
+ console.log(
219
+ `[autoload-dev-pkgs] ❌ Failed to load: ${failureCount} packages`,
220
+ )
210
221
  }
211
222
  }
@@ -17,6 +17,7 @@ import {
17
17
  type PackageRelease,
18
18
  packageReleaseSchema,
19
19
  type PackageBuild,
20
+ packageBuildSchema,
20
21
  type AiReview,
21
22
  aiReviewSchema,
22
23
  type Datasheet,
@@ -26,6 +27,8 @@ import {
26
27
  databaseSchema,
27
28
  type packageSchema,
28
29
  type snippetSchema,
30
+ Organization,
31
+ OrgAccount,
29
32
  } from "./schema.ts"
30
33
  import { seed as seedFn } from "./seed"
31
34
  import { generateFsSha } from "../package_file/generate-fs-sha"
@@ -1489,12 +1492,12 @@ const initializer = combine(databaseSchema.parse({}), (set, get) => ({
1489
1492
  return updated
1490
1493
  },
1491
1494
  addPackageBuild: (
1492
- packageBuild: Omit<PackageBuild, "package_build_id">,
1495
+ packageBuild: Omit<z.input<typeof packageBuildSchema>, "package_build_id">,
1493
1496
  ): PackageBuild => {
1494
- const newPackageBuild = {
1497
+ const newPackageBuild = packageBuildSchema.parse({
1495
1498
  package_build_id: crypto.randomUUID(),
1496
1499
  ...packageBuild,
1497
- }
1500
+ })
1498
1501
  set((state) => ({
1499
1502
  packageBuilds: [...state.packageBuilds, newPackageBuild],
1500
1503
  // Automatically update the package release to reference this as the latest build
@@ -1541,4 +1544,212 @@ const initializer = combine(databaseSchema.parse({}), (set, get) => ({
1541
1544
  })
1542
1545
  return updated
1543
1546
  },
1547
+ addOrganization: (organization: {
1548
+ name: string
1549
+ org_id?: string
1550
+ is_personal_org?: boolean
1551
+ owner_account_id: string
1552
+ }) => {
1553
+ const newOrganization: Organization = {
1554
+ org_id: organization.org_id || `org_${get().idCounter + 1}`,
1555
+ github_handle: organization.name,
1556
+ is_personal_org: organization.is_personal_org || false,
1557
+ created_at: new Date().toISOString(),
1558
+ ...organization,
1559
+ }
1560
+ set((state) => ({
1561
+ idCounter: state.idCounter + 1,
1562
+ organizations: [...state.organizations, newOrganization as Organization],
1563
+ // Add the creator as a member of the new org by setting their personal_org_id
1564
+ accounts: state.accounts.map((account) =>
1565
+ account.account_id === organization.owner_account_id
1566
+ ? { ...account, personal_org_id: newOrganization.org_id }
1567
+ : account,
1568
+ ),
1569
+ }))
1570
+ return newOrganization
1571
+ },
1572
+ getOrgs: (
1573
+ filters?: {
1574
+ owner_account_id?: string
1575
+ github_handle?: string
1576
+ name?: string
1577
+ },
1578
+ auth?: { account_id?: string },
1579
+ ) => {
1580
+ let orgs = get().organizations
1581
+ if (filters?.owner_account_id) {
1582
+ orgs = orgs.filter(
1583
+ (org) => org.owner_account_id === filters.owner_account_id,
1584
+ )
1585
+ }
1586
+ if (filters?.github_handle) {
1587
+ orgs = orgs.filter((org) => {
1588
+ const account = get().accounts.find(
1589
+ (account) => account.account_id === org.owner_account_id,
1590
+ )
1591
+ return account?.github_username === filters.github_handle
1592
+ })
1593
+ }
1594
+ if (filters?.name) {
1595
+ orgs = orgs.filter((org) => org.github_handle === filters.name)
1596
+ }
1597
+
1598
+ return orgs.map((org) => {
1599
+ const member_count = get().accounts.filter(
1600
+ (account) => account.personal_org_id === org.org_id,
1601
+ ).length
1602
+
1603
+ const package_count = get().packages.filter(
1604
+ (pkg) => pkg.owner_org_id === org.org_id,
1605
+ ).length
1606
+
1607
+ const can_manage_org = auth
1608
+ ? org.owner_account_id === auth.account_id
1609
+ : false
1610
+
1611
+ return {
1612
+ ...org,
1613
+ member_count,
1614
+ package_count,
1615
+ can_manage_org,
1616
+ }
1617
+ })
1618
+ },
1619
+ getOrg: (
1620
+ filters: {
1621
+ org_id?: string
1622
+ org_name?: string
1623
+ github_handle?: string
1624
+ },
1625
+ auth?: { account_id: string },
1626
+ ) => {
1627
+ let orgs = get().organizations
1628
+
1629
+ if (filters?.org_id) {
1630
+ orgs = orgs.filter((org) => org.org_id === filters.org_id)
1631
+ }
1632
+ if (filters?.org_name) {
1633
+ orgs = orgs.filter((org) => org.github_handle === filters.org_name)
1634
+ }
1635
+ // if (filters?.org_name && auth?.account_id) {
1636
+ // const account = get().accounts.find(x => x.account_id == auth?.account_id)
1637
+ // orgs = orgs.filter((org) => org.github_handle === account?.github_username)
1638
+ // }
1639
+ if (filters?.github_handle) {
1640
+ orgs = orgs.filter((org) => org.github_handle === filters.github_handle)
1641
+ }
1642
+
1643
+ if (orgs.length === 0) {
1644
+ return null
1645
+ }
1646
+
1647
+ const org = orgs[0]
1648
+
1649
+ const member_count = get().accounts.filter(
1650
+ (account) => account.personal_org_id === org.org_id,
1651
+ ).length
1652
+
1653
+ const package_count = get().packages.filter(
1654
+ (pkg) => pkg.owner_org_id === org.org_id,
1655
+ ).length
1656
+
1657
+ const can_manage_org = auth
1658
+ ? org.owner_account_id === auth.account_id
1659
+ : false
1660
+
1661
+ return {
1662
+ ...org,
1663
+ member_count,
1664
+ package_count,
1665
+ can_manage_org,
1666
+ }
1667
+ },
1668
+ addOrganizationAccount: (organizationAccount: {
1669
+ org_id: string
1670
+ account_id: string
1671
+ is_owner?: boolean
1672
+ }) => {
1673
+ const newOrgAccount: OrgAccount = {
1674
+ org_account_id: `org_account_${get().idCounter + 1}`,
1675
+ org_id: organizationAccount.org_id,
1676
+ account_id: organizationAccount.account_id,
1677
+ is_owner: organizationAccount.is_owner || false,
1678
+ created_at: new Date().toISOString(),
1679
+ }
1680
+ set((state) => ({
1681
+ orgAccounts: [...state.orgAccounts, newOrgAccount],
1682
+ idCounter: state.idCounter + 1,
1683
+ }))
1684
+ return newOrgAccount
1685
+ },
1686
+ getOrganizationAccount: (filters: {
1687
+ org_id?: string
1688
+ account_id?: string
1689
+ }): OrgAccount | undefined => {
1690
+ const state = get()
1691
+ return state.orgAccounts.find((orgAccount) => {
1692
+ if (filters.org_id && orgAccount.org_id !== filters.org_id) {
1693
+ return false
1694
+ }
1695
+ if (filters.account_id && orgAccount.account_id !== filters.account_id) {
1696
+ return false
1697
+ }
1698
+ return true
1699
+ })
1700
+ },
1701
+ getOrganizationAccounts: (filters?: {
1702
+ org_id?: string
1703
+ account_id?: string
1704
+ }): OrgAccount[] => {
1705
+ const state = get()
1706
+ return state.orgAccounts.filter((orgAccount) => {
1707
+ if (filters?.org_id && orgAccount.org_id !== filters.org_id) {
1708
+ return false
1709
+ }
1710
+ if (filters?.account_id && orgAccount.account_id !== filters.account_id) {
1711
+ return false
1712
+ }
1713
+ return true
1714
+ })
1715
+ },
1716
+ removeOrganizationAccount: (filters: {
1717
+ org_id: string
1718
+ account_id: string
1719
+ }): boolean => {
1720
+ let removed = false
1721
+ set((state) => {
1722
+ const index = state.orgAccounts.findIndex(
1723
+ (orgAccount) =>
1724
+ orgAccount.org_id === filters.org_id &&
1725
+ orgAccount.account_id === filters.account_id,
1726
+ )
1727
+ if (index !== -1) {
1728
+ state.orgAccounts.splice(index, 1)
1729
+ removed = true
1730
+ }
1731
+ return state
1732
+ })
1733
+ return removed
1734
+ },
1735
+ updateOrganization: (
1736
+ orgId: string,
1737
+ updates: Partial<Organization>,
1738
+ ): Organization | undefined => {
1739
+ let updatedOrg: Organization | undefined
1740
+ set((state) => {
1741
+ const orgIndex = state.organizations.findIndex(
1742
+ (org) => org.org_id === orgId,
1743
+ )
1744
+ if (orgIndex === -1) return state
1745
+ const updatedOrganizations = [...state.organizations]
1746
+ updatedOrganizations[orgIndex] = {
1747
+ ...updatedOrganizations[orgIndex],
1748
+ ...updates,
1749
+ }
1750
+ updatedOrg = updatedOrganizations[orgIndex]
1751
+ return { ...state, organizations: updatedOrganizations }
1752
+ })
1753
+ return updatedOrg
1754
+ },
1544
1755
  }))
@@ -72,6 +72,7 @@ export const accountSchema = z.object({
72
72
  account_id: z.string(),
73
73
  github_username: z.string(),
74
74
  shippingInfo: shippingInfoSchema.optional(),
75
+ personal_org_id: z.string().optional(),
75
76
  })
76
77
  export type Account = z.infer<typeof accountSchema>
77
78
 
@@ -244,6 +245,22 @@ export const packageReleaseSchema = z.object({
244
245
  circuit_json_build_logs: z.array(z.any()).default([]),
245
246
  circuit_json_build_is_stale: z.boolean().default(false),
246
247
 
248
+ // Image Generation Process
249
+ image_generation_display_status: z
250
+ .enum(["pending", "building", "complete", "error"])
251
+ .default("pending"),
252
+ image_generation_in_progress: z.boolean().default(false),
253
+ image_generation_started_at: z.string().datetime().nullable().optional(),
254
+ image_generation_completed_at: z.string().datetime().nullable().optional(),
255
+ image_generation_logs: z.array(z.any()).nullable().default(null),
256
+ image_generation_is_stale: z.boolean().default(false),
257
+ image_generation_error: z.string().nullable().optional(),
258
+ image_generation_error_last_updated_at: z
259
+ .string()
260
+ .datetime()
261
+ .nullable()
262
+ .optional(),
263
+
247
264
  // AI Review
248
265
  ai_review_text: z.string().nullable().default(null).optional(),
249
266
  ai_review_started_at: z.string().datetime().nullable().optional(),
@@ -311,6 +328,7 @@ export const packageSchema = z.object({
311
328
  .default("files")
312
329
  .optional(),
313
330
  allow_pr_previews: z.boolean().default(false).optional(),
331
+ is_starred: z.boolean().default(false).optional(),
314
332
  })
315
333
  export type Package = z.infer<typeof packageSchema>
316
334
 
@@ -366,6 +384,11 @@ export const packageBuildSchema = z.object({
366
384
  circuit_json_build_completed_at: z.string().datetime().nullable().optional(),
367
385
  circuit_json_build_logs: z.array(z.any()).default([]),
368
386
  circuit_json_build_error: z.string().nullable().optional(),
387
+ image_generation_in_progress: z.boolean().default(false),
388
+ image_generation_started_at: z.string().datetime().nullable().optional(),
389
+ image_generation_completed_at: z.string().datetime().nullable().optional(),
390
+ image_generation_logs: z.array(z.any()).default([]),
391
+ image_generation_error: z.string().nullable().optional(),
369
392
  build_in_progress: z.boolean().default(false),
370
393
  build_started_at: z.string().datetime().nullable().optional(),
371
394
  build_completed_at: z.string().datetime().nullable().optional(),
@@ -376,6 +399,43 @@ export const packageBuildSchema = z.object({
376
399
  })
377
400
  export type PackageBuild = z.infer<typeof packageBuildSchema>
378
401
 
402
+ export const orgSchema = z.object({
403
+ org_id: z.string(),
404
+ github_handle: z.string(),
405
+ owner_account_id: z.string(),
406
+ is_personal_org: z.boolean().default(false),
407
+ created_at: z.string().datetime(),
408
+ org_display_name: z.string().optional(),
409
+ })
410
+ export type Organization = z.infer<typeof orgSchema>
411
+
412
+ export const orgAccountSchema = z.object({
413
+ org_account_id: z.string(),
414
+ org_id: z.string(),
415
+ account_id: z.string(),
416
+ is_owner: z.boolean().default(false),
417
+ created_at: z.string().datetime(),
418
+ })
419
+ export type OrgAccount = z.infer<typeof orgAccountSchema>
420
+
421
+ export const publicOrgSchema = z.object({
422
+ org_id: z.string(), //.uuid(),
423
+ owner_account_id: z.string(), //.uuid(),
424
+ name: z.string().nullable(),
425
+ member_count: z.number(),
426
+ is_personal_org: z.boolean(),
427
+ display_name: z.string().optional(),
428
+ package_count: z.number(),
429
+ created_at: z.string(),
430
+ user_permissions: z
431
+ .object({
432
+ can_manage_org: z.boolean().optional(),
433
+ can_manage_package: z.boolean().optional(),
434
+ })
435
+ .optional(),
436
+ })
437
+ export type PublicOrgSchema = z.infer<typeof publicOrgSchema>
438
+
379
439
  export const databaseSchema = z.object({
380
440
  idCounter: z.number().default(0),
381
441
  snippets: z.array(snippetSchema).default([]),
@@ -386,6 +446,8 @@ export const databaseSchema = z.object({
386
446
  accounts: z.array(accountSchema).default([]),
387
447
  packages: z.array(packageSchema).default([]),
388
448
  orders: z.array(orderSchema).default([]),
449
+ organizations: z.array(orgSchema).default([]),
450
+ orgAccounts: z.array(orgAccountSchema).default([]),
389
451
  orderFiles: z.array(orderFileSchema).default([]),
390
452
  accountSnippets: z.array(accountSnippetSchema).default([]),
391
453
  accountPackages: z.array(accountPackageSchema).default([]),
@@ -1733,4 +1733,104 @@ export const SquareWaveModule = () => (
1733
1733
  started_at: null,
1734
1734
  completed_at: null,
1735
1735
  })
1736
+
1737
+ const testOrg = db.addOrganization({
1738
+ name: "test-organization",
1739
+ owner_account_id: account_id,
1740
+ })
1741
+
1742
+ // Add org member
1743
+ db.addOrganizationAccount({
1744
+ org_id: testOrg.org_id,
1745
+ account_id: account_id,
1746
+ is_owner: true,
1747
+ })
1748
+
1749
+ const { package_release_id: orgPackageReleaseId } = db.addSnippet({
1750
+ name: "test-organization/test-package",
1751
+ unscoped_name: "test-package",
1752
+ owner_name: "test-organization",
1753
+ code: `
1754
+ export const TestComponent = ({ name }: { name: string }) => (
1755
+ <resistor name={name} resistance="10k" />
1756
+ )
1757
+ `.trim(),
1758
+ dts: `
1759
+ declare module "@tsci/test-organization.test-package" {
1760
+ export const TestComponent: ({ name }: {
1761
+ name: string;
1762
+ }) => any;
1763
+ }
1764
+ `.trim(),
1765
+ compiled_js: `
1766
+ "use strict";
1767
+
1768
+ Object.defineProperty(exports, "__esModule", {
1769
+ value: true
1770
+ });
1771
+ exports.TestComponent = void 0;
1772
+ const TestComponent = ({
1773
+ name
1774
+ }) => /*#__PURE__*/React.createElement("resistor", {
1775
+ name: name,
1776
+ resistance: "10k"
1777
+ });
1778
+ exports.TestComponent = TestComponent;
1779
+ `.trim(),
1780
+ created_at: new Date().toISOString(),
1781
+ updated_at: new Date().toISOString(),
1782
+ snippet_type: "package",
1783
+ description: "Test package for organization",
1784
+ circuit_json: [
1785
+ {
1786
+ type: "source_component",
1787
+ source_component_id: "source_component_0",
1788
+ ftype: "simple_resistor",
1789
+ name: "R1",
1790
+ resistance: "10k",
1791
+ },
1792
+ ],
1793
+ })
1794
+
1795
+ // Add successful build for org package
1796
+ const orgPackageBuild = db.addPackageBuild({
1797
+ package_release_id: orgPackageReleaseId,
1798
+ created_at: new Date().toISOString(),
1799
+ transpilation_in_progress: false,
1800
+ transpilation_started_at: new Date(Date.now() - 5000).toISOString(),
1801
+ transpilation_completed_at: new Date(Date.now() - 3000).toISOString(),
1802
+ transpilation_logs: [
1803
+ "[INFO] Starting transpilation...",
1804
+ "[SUCCESS] Transpilation completed successfully",
1805
+ ],
1806
+ transpilation_error: null,
1807
+ circuit_json_build_in_progress: false,
1808
+ circuit_json_build_started_at: new Date(Date.now() - 3000).toISOString(),
1809
+ circuit_json_build_completed_at: new Date(Date.now() - 1000).toISOString(),
1810
+ circuit_json_build_logs: [
1811
+ "[INFO] Starting circuit JSON build...",
1812
+ "[SUCCESS] Circuit JSON build completed",
1813
+ ],
1814
+ circuit_json_build_error: null,
1815
+ build_in_progress: false,
1816
+ build_started_at: new Date(Date.now() - 10000).toISOString(),
1817
+ build_completed_at: new Date().toISOString(),
1818
+ build_error: null,
1819
+ build_error_last_updated_at: new Date().toISOString(),
1820
+ preview_url: "http://localhost:3000/preview/org_package_build",
1821
+ build_logs: "Build completed successfully",
1822
+ })
1823
+
1824
+ // Update the org package release with the build ID
1825
+ const orgRelease = db.getPackageReleaseById(orgPackageReleaseId)!
1826
+ db.updatePackageRelease({
1827
+ ...orgRelease,
1828
+ latest_package_build_id: orgPackageBuild.package_build_id,
1829
+ })
1830
+
1831
+ db.addOrganization({
1832
+ name: "testuser",
1833
+ owner_account_id: account_id,
1834
+ is_personal_org: true,
1835
+ })
1736
1836
  }
@@ -29,7 +29,7 @@ export const withSessionAuth: Middleware<
29
29
  ctx.auth = {
30
30
  type: "session",
31
31
  account_id: account.account_id,
32
- personal_org_id: `org-${account.account_id}`,
32
+ personal_org_id: account.personal_org_id || `org-${account.account_id}`,
33
33
  github_username: account.github_username,
34
34
  session_id: `session-${account.account_id}`,
35
35
  }
@@ -125,8 +125,8 @@ export const getPackageFileIdFromFileDescriptor = async (
125
125
 
126
126
  if ("package_name_with_version" in descriptor) {
127
127
  const { package_name_with_version, file_path } = descriptor
128
- const packageName = package_name_with_version.split("@")[1]
129
- const version = package_name_with_version.split("@")[2]
128
+ const packageName = package_name_with_version.split("@")[0]
129
+ const version = package_name_with_version.split("@")[1]
130
130
 
131
131
  // Find the package
132
132
  const pkg = ctx.db.packages.find((p: ZT.Package) => p.name === packageName)
@@ -0,0 +1,32 @@
1
+ import { z } from "zod"
2
+ import * as ZT from "fake-snippets-api/lib/db/schema"
3
+
4
+ export const publicMapOrg = (
5
+ internal_org: ZT.Organization & {
6
+ member_count: number
7
+ package_count: number
8
+ can_manage_org: boolean
9
+ },
10
+ ): z.infer<typeof ZT.publicOrgSchema> => {
11
+ const {
12
+ can_manage_org,
13
+ github_handle,
14
+ member_count,
15
+ package_count,
16
+ created_at,
17
+ is_personal_org,
18
+ org_display_name,
19
+ ...org
20
+ } = internal_org
21
+ return {
22
+ org_id: org.org_id,
23
+ display_name: org_display_name ?? github_handle ?? "",
24
+ owner_account_id: org.owner_account_id,
25
+ name: github_handle,
26
+ member_count: Number(member_count) || 0,
27
+ package_count: Number(package_count) || 0,
28
+ is_personal_org: Boolean(is_personal_org),
29
+ created_at: String(created_at),
30
+ ...(can_manage_org ? { user_permissions: { can_manage_org: true } } : {}),
31
+ }
32
+ }
@@ -25,6 +25,16 @@ export const publicMapPackageBuild = (
25
25
  ? internalPackageBuild.circuit_json_build_logs
26
26
  : [],
27
27
  circuit_json_build_error: internalPackageBuild.circuit_json_build_error,
28
+ image_generation_in_progress:
29
+ internalPackageBuild.image_generation_in_progress,
30
+ image_generation_started_at:
31
+ internalPackageBuild.image_generation_started_at,
32
+ image_generation_completed_at:
33
+ internalPackageBuild.image_generation_completed_at,
34
+ image_generation_logs: options.include_logs
35
+ ? internalPackageBuild.image_generation_logs
36
+ : [],
37
+ image_generation_error: internalPackageBuild.image_generation_error,
28
38
  build_started_at: internalPackageBuild.build_started_at,
29
39
  build_completed_at: internalPackageBuild.build_completed_at,
30
40
  build_error: internalPackageBuild.build_error,
@@ -24,6 +24,23 @@ export const publicMapPackageRelease = (
24
24
  circuit_json_build_logs: options.include_logs
25
25
  ? internal_package_release.circuit_json_build_logs
26
26
  : [],
27
+ image_generation_logs: options.include_logs
28
+ ? internal_package_release.image_generation_logs
29
+ : null,
30
+ image_generation_in_progress:
31
+ internal_package_release.image_generation_in_progress,
32
+ image_generation_started_at:
33
+ internal_package_release.image_generation_started_at ?? null,
34
+ image_generation_completed_at:
35
+ internal_package_release.image_generation_completed_at ?? null,
36
+ image_generation_is_stale:
37
+ internal_package_release.image_generation_is_stale,
38
+ image_generation_error:
39
+ internal_package_release.image_generation_error ?? null,
40
+ image_generation_error_last_updated_at:
41
+ internal_package_release.image_generation_error_last_updated_at ?? null,
42
+ image_generation_display_status:
43
+ internal_package_release.image_generation_display_status,
27
44
  is_pr_preview: Boolean(internal_package_release.is_pr_preview),
28
45
  github_pr_number: internal_package_release.github_pr_number,
29
46
  branch_name: internal_package_release.branch_name,