@tscircuit/fake-snippets 0.0.30 → 0.0.31
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.
- package/bun-tests/fake-snippets-api/routes/packages/get.test.ts +21 -1
- package/dist/bundle.js +128 -44
- package/dist/index.js +127 -42
- package/fake-snippets-api/lib/db/autoload-dev-packages.ts +185 -0
- package/fake-snippets-api/lib/db/{autoload-snippets.json → autoload-packages.json} +5 -1
- package/fake-snippets-api/lib/db/seed.ts +3 -3
- package/package.json +1 -1
- package/src/components/ViewPackagePage/hooks/use-current-package-circuit-json.ts +2 -2
- package/src/hooks/use-current-package-id.ts +46 -2
- package/fake-snippets-api/lib/db/autoload-dev-snippets.ts +0 -84
package/dist/index.js
CHANGED
|
@@ -198,10 +198,10 @@ var databaseSchema = z.object({
|
|
|
198
198
|
jlcpcbOrderStepRuns: z.array(jlcpcbOrderStepRunSchema).default([])
|
|
199
199
|
});
|
|
200
200
|
|
|
201
|
-
// fake-snippets-api/lib/db/autoload-dev-
|
|
202
|
-
import axios from "redaxios";
|
|
201
|
+
// fake-snippets-api/lib/db/autoload-dev-packages.ts
|
|
203
202
|
import fs from "fs";
|
|
204
203
|
import path from "path";
|
|
204
|
+
import axios from "redaxios";
|
|
205
205
|
var extractTsciDependencies = (code) => {
|
|
206
206
|
const regex = /@tsci\/([^.]+)\.([^"'\s]+)/g;
|
|
207
207
|
const matches = Array.from(code.matchAll(regex));
|
|
@@ -217,52 +217,137 @@ var registryApi = axios.create({
|
|
|
217
217
|
"Content-Type": "application/json"
|
|
218
218
|
}
|
|
219
219
|
});
|
|
220
|
-
var
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
220
|
+
var fetchPackageFromRegistry = async (owner, name) => {
|
|
221
|
+
const fullName = `${owner}/${name}`;
|
|
222
|
+
console.log(`Fetching package ${fullName}...`);
|
|
223
|
+
let packageData;
|
|
224
|
+
try {
|
|
225
|
+
const response = await registryApi.post("/packages/get", {
|
|
226
|
+
name: fullName
|
|
227
|
+
});
|
|
228
|
+
packageData = response.data;
|
|
229
|
+
} catch (e) {
|
|
230
|
+
console.error(`Failed to fetch package data for ${fullName}:`, e);
|
|
231
|
+
throw e;
|
|
230
232
|
}
|
|
233
|
+
let releaseData;
|
|
231
234
|
try {
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
for (const dep of dependencies) {
|
|
238
|
-
loadSnippetWithDependencies(db, dep.owner, dep.name, loadedSnippets);
|
|
239
|
-
}
|
|
235
|
+
const response = await registryApi.post("/package_releases/get", {
|
|
236
|
+
package_id: packageData.package.package_id,
|
|
237
|
+
is_latest: true
|
|
238
|
+
});
|
|
239
|
+
releaseData = response.data;
|
|
240
240
|
} catch (e) {
|
|
241
|
-
console.error(
|
|
241
|
+
console.error(`Failed to fetch release data for ${fullName}:`, e);
|
|
242
|
+
throw e;
|
|
242
243
|
}
|
|
244
|
+
let filesData;
|
|
245
|
+
try {
|
|
246
|
+
const response = await registryApi.post("/package_files/list", {
|
|
247
|
+
package_release_id: releaseData.package_release.package_release_id
|
|
248
|
+
});
|
|
249
|
+
filesData = response.data;
|
|
250
|
+
} catch (e) {
|
|
251
|
+
console.error(`Failed to fetch files data for ${fullName}:`, e);
|
|
252
|
+
throw e;
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
package: packageData.package,
|
|
256
|
+
release: releaseData.package_release,
|
|
257
|
+
files: filesData.package_files
|
|
258
|
+
};
|
|
243
259
|
};
|
|
244
|
-
var
|
|
260
|
+
var loadPackageWithDependencies = async (db, owner, name, loadedPackages = /* @__PURE__ */ new Set()) => {
|
|
261
|
+
const packageKey = `${owner}/${name}`;
|
|
262
|
+
if (loadedPackages.has(packageKey)) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
let result;
|
|
245
266
|
try {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
267
|
+
result = await fetchPackageFromRegistry(owner, name);
|
|
268
|
+
} catch (e) {
|
|
269
|
+
console.error(`\u2717 Failed to load ${packageKey}`);
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
const { package: pkg, release, files } = result;
|
|
273
|
+
if (db.getPackageById(pkg.package_id)) {
|
|
274
|
+
console.log(`\u2713 Package ${packageKey} already exists`);
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
db.addPackage({
|
|
278
|
+
...pkg,
|
|
279
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
280
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
281
|
+
latest_package_release_id: release.package_release_id
|
|
282
|
+
});
|
|
283
|
+
db.addPackageRelease({
|
|
284
|
+
...release,
|
|
285
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
286
|
+
});
|
|
287
|
+
for (const file of files) {
|
|
288
|
+
db.addPackageFile({
|
|
289
|
+
...file,
|
|
290
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
loadedPackages.add(packageKey);
|
|
294
|
+
console.log(`\u2713 Loaded ${packageKey}`);
|
|
295
|
+
const mainFile = files.find(
|
|
296
|
+
(f) => f.file_path === "index.tsx" || f.file_path === "index.ts"
|
|
297
|
+
);
|
|
298
|
+
if (!mainFile?.content_text) {
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
const dependencies = extractTsciDependencies(mainFile.content_text);
|
|
302
|
+
let allDepsLoaded = true;
|
|
303
|
+
for (const dep of dependencies) {
|
|
304
|
+
const depLoaded = await loadPackageWithDependencies(
|
|
305
|
+
db,
|
|
306
|
+
dep.owner,
|
|
307
|
+
dep.name,
|
|
308
|
+
loadedPackages
|
|
250
309
|
);
|
|
251
|
-
if (
|
|
252
|
-
|
|
253
|
-
console.
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
loadSnippetWithDependencies(
|
|
257
|
-
db,
|
|
258
|
-
snippetRef.owner,
|
|
259
|
-
snippetRef.name,
|
|
260
|
-
loadedSnippets
|
|
261
|
-
);
|
|
262
|
-
}
|
|
310
|
+
if (!depLoaded) {
|
|
311
|
+
allDepsLoaded = false;
|
|
312
|
+
console.warn(
|
|
313
|
+
`\u26A0\uFE0F Failed to load dependency ${dep.owner}/${dep.name} for ${packageKey}`
|
|
314
|
+
);
|
|
263
315
|
}
|
|
264
|
-
}
|
|
265
|
-
|
|
316
|
+
}
|
|
317
|
+
return allDepsLoaded;
|
|
318
|
+
};
|
|
319
|
+
var loadAutoloadPackages = async (db) => {
|
|
320
|
+
const autoloadPath = path.join(
|
|
321
|
+
path.dirname(__dirname),
|
|
322
|
+
"db",
|
|
323
|
+
"autoload-packages.json"
|
|
324
|
+
);
|
|
325
|
+
if (!fs.existsSync(autoloadPath)) {
|
|
326
|
+
console.error("No autoload-packages.json found");
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const autoloadContent = JSON.parse(fs.readFileSync(autoloadPath, "utf8"));
|
|
330
|
+
const loadedPackages = /* @__PURE__ */ new Set();
|
|
331
|
+
let successCount = 0;
|
|
332
|
+
let failureCount = 0;
|
|
333
|
+
for (const packageRef of autoloadContent.packages) {
|
|
334
|
+
const success = await loadPackageWithDependencies(
|
|
335
|
+
db,
|
|
336
|
+
packageRef.owner,
|
|
337
|
+
packageRef.name,
|
|
338
|
+
loadedPackages
|
|
339
|
+
);
|
|
340
|
+
if (success) {
|
|
341
|
+
successCount++;
|
|
342
|
+
} else {
|
|
343
|
+
failureCount++;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
console.log(`
|
|
347
|
+
Package loading complete:`);
|
|
348
|
+
console.log(`\u2713 Successfully loaded: ${successCount} packages`);
|
|
349
|
+
if (failureCount > 0) {
|
|
350
|
+
console.log(`\u2717 Failed to load: ${failureCount} packages`);
|
|
266
351
|
}
|
|
267
352
|
};
|
|
268
353
|
|
|
@@ -287,8 +372,8 @@ var seed = (db) => {
|
|
|
287
372
|
db.addAccount({
|
|
288
373
|
github_username: "seveibar"
|
|
289
374
|
});
|
|
290
|
-
if (process.env.
|
|
291
|
-
|
|
375
|
+
if (process.env.AUTOLOAD_PACKAGES === "true") {
|
|
376
|
+
loadAutoloadPackages(db);
|
|
292
377
|
}
|
|
293
378
|
db.addSnippet({
|
|
294
379
|
name: "testuser/my-test-board",
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import fs from "fs"
|
|
2
|
+
import path from "path"
|
|
3
|
+
import axios from "redaxios"
|
|
4
|
+
import type { DbClient } from "./db-client"
|
|
5
|
+
import type { Package, PackageFile, PackageRelease } from "./schema"
|
|
6
|
+
|
|
7
|
+
const extractTsciDependencies = (
|
|
8
|
+
code: string,
|
|
9
|
+
): Array<{ owner: string; name: string }> => {
|
|
10
|
+
const regex = /@tsci\/([^.]+)\.([^"'\s]+)/g
|
|
11
|
+
const matches = Array.from(code.matchAll(regex))
|
|
12
|
+
return matches.map((match) => ({
|
|
13
|
+
owner: match[1],
|
|
14
|
+
name: match[2],
|
|
15
|
+
}))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const registryApi = axios.create({
|
|
19
|
+
baseURL: "https://registry-api.tscircuit.com",
|
|
20
|
+
headers: {
|
|
21
|
+
Accept: "application/json",
|
|
22
|
+
"Content-Type": "application/json",
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const fetchPackageFromRegistry = async (owner: string, name: string) => {
|
|
27
|
+
const fullName = `${owner}/${name}`
|
|
28
|
+
console.log(`Fetching package ${fullName}...`)
|
|
29
|
+
|
|
30
|
+
let packageData
|
|
31
|
+
try {
|
|
32
|
+
const response = await registryApi.post("/packages/get", {
|
|
33
|
+
name: fullName,
|
|
34
|
+
})
|
|
35
|
+
packageData = response.data
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.error(`Failed to fetch package data for ${fullName}:`, e)
|
|
38
|
+
throw e
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let releaseData
|
|
42
|
+
try {
|
|
43
|
+
const response = await registryApi.post("/package_releases/get", {
|
|
44
|
+
package_id: packageData.package.package_id,
|
|
45
|
+
is_latest: true,
|
|
46
|
+
})
|
|
47
|
+
releaseData = response.data
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.error(`Failed to fetch release data for ${fullName}:`, e)
|
|
50
|
+
throw e
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let filesData
|
|
54
|
+
try {
|
|
55
|
+
const response = await registryApi.post("/package_files/list", {
|
|
56
|
+
package_release_id: releaseData.package_release.package_release_id,
|
|
57
|
+
})
|
|
58
|
+
filesData = response.data
|
|
59
|
+
} catch (e) {
|
|
60
|
+
console.error(`Failed to fetch files data for ${fullName}:`, e)
|
|
61
|
+
throw e
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
package: packageData.package as Package,
|
|
66
|
+
release: releaseData.package_release as PackageRelease,
|
|
67
|
+
files: filesData.package_files as PackageFile[],
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const loadPackageWithDependencies = async (
|
|
72
|
+
db: DbClient,
|
|
73
|
+
owner: string,
|
|
74
|
+
name: string,
|
|
75
|
+
loadedPackages = new Set<string>(),
|
|
76
|
+
) => {
|
|
77
|
+
const packageKey = `${owner}/${name}`
|
|
78
|
+
if (loadedPackages.has(packageKey)) {
|
|
79
|
+
return true
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let result
|
|
83
|
+
try {
|
|
84
|
+
result = await fetchPackageFromRegistry(owner, name)
|
|
85
|
+
} catch (e) {
|
|
86
|
+
console.error(`✗ Failed to load ${packageKey}`)
|
|
87
|
+
return false
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const { package: pkg, release, files } = result
|
|
91
|
+
|
|
92
|
+
// Check if package already exists
|
|
93
|
+
if (db.getPackageById(pkg.package_id)) {
|
|
94
|
+
console.log(`✓ Package ${packageKey} already exists`)
|
|
95
|
+
return true
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Add package, release, and files to db
|
|
99
|
+
db.addPackage({
|
|
100
|
+
...pkg,
|
|
101
|
+
created_at: new Date().toISOString(),
|
|
102
|
+
updated_at: new Date().toISOString(),
|
|
103
|
+
latest_package_release_id: release.package_release_id,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
db.addPackageRelease({
|
|
107
|
+
...release,
|
|
108
|
+
created_at: new Date().toISOString(),
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
for (const file of files) {
|
|
112
|
+
db.addPackageFile({
|
|
113
|
+
...file,
|
|
114
|
+
created_at: new Date().toISOString(),
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
loadedPackages.add(packageKey)
|
|
119
|
+
console.log(`✓ Loaded ${packageKey}`)
|
|
120
|
+
|
|
121
|
+
// Load dependencies
|
|
122
|
+
const mainFile = files.find(
|
|
123
|
+
(f) => f.file_path === "index.tsx" || f.file_path === "index.ts",
|
|
124
|
+
)
|
|
125
|
+
if (!mainFile?.content_text) {
|
|
126
|
+
return true
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const dependencies = extractTsciDependencies(mainFile.content_text)
|
|
130
|
+
let allDepsLoaded = true
|
|
131
|
+
|
|
132
|
+
for (const dep of dependencies) {
|
|
133
|
+
const depLoaded = await loadPackageWithDependencies(
|
|
134
|
+
db,
|
|
135
|
+
dep.owner,
|
|
136
|
+
dep.name,
|
|
137
|
+
loadedPackages,
|
|
138
|
+
)
|
|
139
|
+
if (!depLoaded) {
|
|
140
|
+
allDepsLoaded = false
|
|
141
|
+
console.warn(
|
|
142
|
+
`⚠️ Failed to load dependency ${dep.owner}/${dep.name} for ${packageKey}`,
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return allDepsLoaded
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export const loadAutoloadPackages = async (db: DbClient) => {
|
|
151
|
+
const autoloadPath = path.join(
|
|
152
|
+
path.dirname(__dirname),
|
|
153
|
+
"db",
|
|
154
|
+
"autoload-packages.json",
|
|
155
|
+
)
|
|
156
|
+
if (!fs.existsSync(autoloadPath)) {
|
|
157
|
+
console.error("No autoload-packages.json found")
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const autoloadContent = JSON.parse(fs.readFileSync(autoloadPath, "utf8"))
|
|
162
|
+
const loadedPackages = new Set<string>()
|
|
163
|
+
let successCount = 0
|
|
164
|
+
let failureCount = 0
|
|
165
|
+
|
|
166
|
+
for (const packageRef of autoloadContent.packages) {
|
|
167
|
+
const success = await loadPackageWithDependencies(
|
|
168
|
+
db,
|
|
169
|
+
packageRef.owner,
|
|
170
|
+
packageRef.name,
|
|
171
|
+
loadedPackages,
|
|
172
|
+
)
|
|
173
|
+
if (success) {
|
|
174
|
+
successCount++
|
|
175
|
+
} else {
|
|
176
|
+
failureCount++
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
console.log(`\nPackage loading complete:`)
|
|
181
|
+
console.log(`✓ Successfully loaded: ${successCount} packages`)
|
|
182
|
+
if (failureCount > 0) {
|
|
183
|
+
console.log(`✗ Failed to load: ${failureCount} packages`)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"packages": [
|
|
3
3
|
{
|
|
4
4
|
"owner": "Abse2001",
|
|
5
5
|
"name": "Arduino-Nano-Servo-Breakout"
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
{
|
|
24
24
|
"owner": "AnasSarkiz",
|
|
25
25
|
"name": "grid-of-LEDs-with-an-ESP32"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"owner": "seveibar",
|
|
29
|
+
"name": "keyboard-default60"
|
|
26
30
|
}
|
|
27
31
|
]
|
|
28
32
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DbClient } from "./db-client"
|
|
2
|
-
import {
|
|
2
|
+
import { loadAutoloadPackages } from "./autoload-dev-packages"
|
|
3
3
|
|
|
4
4
|
export const seed = (db: DbClient) => {
|
|
5
5
|
const { account_id } = db.addAccount({
|
|
@@ -22,8 +22,8 @@ export const seed = (db: DbClient) => {
|
|
|
22
22
|
github_username: "seveibar",
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
-
if (process.env.
|
|
26
|
-
|
|
25
|
+
if (process.env.AUTOLOAD_PACKAGES === "true") {
|
|
26
|
+
loadAutoloadPackages(db)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
db.addSnippet({
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useCurrentPackageId } from "@/hooks/use-current-package-id"
|
|
2
2
|
import { usePackageFile } from "@/hooks/use-package-files"
|
|
3
3
|
import { useEffect, useState } from "react"
|
|
4
4
|
|
|
5
5
|
export function useCurrentPackageCircuitJson() {
|
|
6
|
-
const { packageId } =
|
|
6
|
+
const { packageId } = useCurrentPackageId()
|
|
7
7
|
|
|
8
8
|
const [circuitJson, setCircuitJson] = useState<any>(null)
|
|
9
9
|
const [isLoading, setIsLoading] = useState(true)
|
|
@@ -1,3 +1,47 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffect, useState } from "react"
|
|
2
|
+
import { useParams } from "wouter"
|
|
3
|
+
import { usePackageById } from "./use-package-by-package-id"
|
|
4
|
+
import { usePackageByName } from "./use-package-by-package-name"
|
|
5
|
+
import { useUrlParams } from "./use-url-params"
|
|
2
6
|
|
|
3
|
-
export const useCurrentPackageId =
|
|
7
|
+
export const useCurrentPackageId = (): {
|
|
8
|
+
packageId: string | null
|
|
9
|
+
isLoading: boolean
|
|
10
|
+
error: (Error & { status: number }) | null
|
|
11
|
+
} => {
|
|
12
|
+
const urlParams = useUrlParams()
|
|
13
|
+
const urlPackageId = urlParams.package_id
|
|
14
|
+
const wouter = useParams()
|
|
15
|
+
const [packageIdFromUrl, setPackageId] = useState<string | null>(urlPackageId)
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (urlPackageId) {
|
|
19
|
+
setPackageId(urlPackageId)
|
|
20
|
+
}
|
|
21
|
+
}, [urlPackageId])
|
|
22
|
+
|
|
23
|
+
const packageName =
|
|
24
|
+
wouter.author && wouter.packageName
|
|
25
|
+
? `${wouter.author}/${wouter.packageName}`
|
|
26
|
+
: null
|
|
27
|
+
|
|
28
|
+
const {
|
|
29
|
+
data: packageByName,
|
|
30
|
+
isLoading: isLoadingPackageByName,
|
|
31
|
+
error: errorPackageByName,
|
|
32
|
+
} = usePackageByName(packageName)
|
|
33
|
+
|
|
34
|
+
const {
|
|
35
|
+
data: packageById,
|
|
36
|
+
isLoading: isLoadingPackageById,
|
|
37
|
+
error: errorPackageById,
|
|
38
|
+
} = usePackageById(packageIdFromUrl)
|
|
39
|
+
|
|
40
|
+
const packageId = packageIdFromUrl ?? packageByName?.package_id ?? null
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
packageId,
|
|
44
|
+
isLoading: isLoadingPackageByName || isLoadingPackageById,
|
|
45
|
+
error: errorPackageByName || errorPackageById,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import axios from "redaxios"
|
|
2
|
-
import fs from "fs"
|
|
3
|
-
import path from "path"
|
|
4
|
-
import { DbClient } from "./db-client"
|
|
5
|
-
|
|
6
|
-
const extractTsciDependencies = (
|
|
7
|
-
code: string,
|
|
8
|
-
): Array<{ owner: string; name: string }> => {
|
|
9
|
-
const regex = /@tsci\/([^.]+)\.([^"'\s]+)/g
|
|
10
|
-
const matches = Array.from(code.matchAll(regex))
|
|
11
|
-
return matches.map((match) => ({
|
|
12
|
-
owner: match[1],
|
|
13
|
-
name: match[2],
|
|
14
|
-
}))
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const registryApi = axios.create({
|
|
18
|
-
baseURL: "https://registry-api.tscircuit.com",
|
|
19
|
-
headers: {
|
|
20
|
-
Accept: "application/json",
|
|
21
|
-
"Content-Type": "application/json",
|
|
22
|
-
},
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
const fetchSnippetFromRegistry = async (owner: string, name: string) => {
|
|
26
|
-
const response = await registryApi.get(
|
|
27
|
-
`/snippets/get?owner_name=${owner}&unscoped_name=${name}`,
|
|
28
|
-
)
|
|
29
|
-
return response.data.snippet
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const loadSnippetWithDependencies = async (
|
|
33
|
-
db: DbClient,
|
|
34
|
-
owner: string,
|
|
35
|
-
name: string,
|
|
36
|
-
loadedSnippets = new Set<string>(),
|
|
37
|
-
) => {
|
|
38
|
-
const snippetKey = `${owner}/${name}`
|
|
39
|
-
if (loadedSnippets.has(snippetKey)) {
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
const snippet = await fetchSnippetFromRegistry(owner, name)
|
|
45
|
-
|
|
46
|
-
if (db.getSnippetByAuthorAndName(owner, name)) return
|
|
47
|
-
|
|
48
|
-
db.addSnippet(snippet)
|
|
49
|
-
loadedSnippets.add(snippetKey)
|
|
50
|
-
|
|
51
|
-
const dependencies = extractTsciDependencies(snippet.code)
|
|
52
|
-
for (const dep of dependencies) {
|
|
53
|
-
loadSnippetWithDependencies(db, dep.owner, dep.name, loadedSnippets)
|
|
54
|
-
}
|
|
55
|
-
} catch (e) {
|
|
56
|
-
console.error(`✗ Failed to load ${snippetKey}:`, e)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export const loadAutoloadSnippets = async (db: DbClient) => {
|
|
61
|
-
try {
|
|
62
|
-
const autoloadPath = path.join(
|
|
63
|
-
path.dirname(__dirname),
|
|
64
|
-
"db",
|
|
65
|
-
"autoload-snippets.json",
|
|
66
|
-
)
|
|
67
|
-
if (fs.existsSync(autoloadPath)) {
|
|
68
|
-
const autoloadContent = JSON.parse(fs.readFileSync(autoloadPath, "utf8"))
|
|
69
|
-
console.log("Loading development snippets from registry...")
|
|
70
|
-
|
|
71
|
-
const loadedSnippets = new Set<string>()
|
|
72
|
-
for (const snippetRef of autoloadContent.snippets) {
|
|
73
|
-
loadSnippetWithDependencies(
|
|
74
|
-
db,
|
|
75
|
-
snippetRef.owner,
|
|
76
|
-
snippetRef.name,
|
|
77
|
-
loadedSnippets,
|
|
78
|
-
)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
} catch (e) {
|
|
82
|
-
console.error("Failed to load autoload-snippets.json:", e)
|
|
83
|
-
}
|
|
84
|
-
}
|