This adds a couple of new forked processes which go and grab all PDSes (in a horrible way) from mary's scraper, then for all pdses go through and get repo history checking for systems.gmstn events. This PR aims to show the idea rather than being polished code, so that we don't waste time polishing a poop!
+1
-8
.example.env
+1
-8
.example.env
···
1
-
# what to filter by. currently only supports one string.
2
-
FILTER_BY=
3
-
4
-
# cache location. sqlite db url. technically supports an external cache if you want.
5
-
# https://bsky.app/profile/piss.beauty/post/3lkc3efbipc23
6
-
# https://bsky.app/profile/nekomimi.pet/post/3m3losk3rys2n
7
-
# usually either :memory: or file:path/to/file.db. defaults to ":memory:"
8
-
CACHE_LOCATION=":memory:"
1
+
DATABASE_URL=postgres://prism:prism@localhost:5432/prism
+4
-6
README.md
+4
-6
README.md
···
1
1
# Prism
2
2
3
-
Prism is a simple [ATProto](https://atproto.com/) [Relay](https://docs.bsky.app/docs/advanced-guides/firehose) filtering service. Point it to a relay, give it some NSID, partial NSID, or domain authority, and it'll filter relay events for you and store/cache them for future retrieval if you want to.
3
+
Prism is a simple [ATProto](https://atproto.com/) AppView service for gmstn. Point it to a relay and it'll filter relay events for you and store/cache them for future retrieval so that queries aren't so heavy on other PDSes directly.
4
4
5
5
<a href="https://docs.bsky.app/docs/advanced-guides/federation-architecture#app-views">
6
6
<img src="https://docs.bsky.app/assets/images/app-view-prism-e90e1bf6093bafcb6df2e5c592be1bc6.png" width="400" alt="appview-prism-pinkfloyd"/>
7
7
</a>
8
8
9
-
For example, if you want to only filter all events relating to `sh.tangled.*`, simply configure your `.env` file with `FILTER_BY="sh.tangled"` and it'll monitor the relay for those records.
9
+
Other services may subscribe to a Prism instance as though it is a relay itself and receive the filtered gmstn events as they are played from the parent relay.
10
10
11
-
Other services may subscribe to a Prism instance as though it is a relay itself and receive the filtered events as they are played from the parent relay.
11
+
Prism implements endpoints for accessing the cache feed, which are `xrpc` compatible and the lexicons can be found in `lexicons/`.
12
12
13
-
Prism also implements a very minimal cache (24h, configurable). Endpoints for accessing the cache are `xrpc` compatible and the lexicons can be found in `lexicons/`
14
-
15
-
Backfill coming soon (if you're crazy ig).
13
+
Backfill batteries included. :3
+16
migrations/20251104191300_create_pds_table.ts
+16
migrations/20251104191300_create_pds_table.ts
···
1
+
import { Kysely, sql } from 'kysely';
2
+
3
+
export async function up(db: Kysely<any>): Promise<void> {
4
+
await db.schema
5
+
.createTable('pds')
6
+
.addColumn('hostname', 'text', (col) => col.primaryKey())
7
+
.addColumn('added_at', 'timestamp', (col) =>
8
+
col.defaultTo(sql`now()`).notNull()
9
+
)
10
+
.addColumn('backfilled_at', 'timestamp')
11
+
.execute();
12
+
}
13
+
14
+
export async function down(db: Kysely<any>): Promise<void> {
15
+
await db.schema.dropTable('pds').execute();
16
+
}
+5
package.json
+5
package.json
···
16
16
"packageManager": "pnpm@10.20.0",
17
17
"dependencies": {
18
18
"@atproto/xrpc-server": "^0.9.5",
19
+
"@ipld/car": "^5.4.2",
20
+
"@ipld/dag-cbor": "^9.2.5",
19
21
"@skyware/firehose": "^0.5.2",
22
+
"biome": "^0.3.3",
20
23
"dotenv": "^17.2.3",
21
24
"kysely": "^0.28.8",
22
25
"pg": "^8.16.3",
···
25
28
"devDependencies": {
26
29
"@atcute/atproto": "^3.1.8",
27
30
"@types/node": "^24.9.2",
31
+
"@types/pg": "^8.15.6",
28
32
"@types/ws": "^8.18.1",
29
33
"ts-node": "^10.9.2",
34
+
"tsconfig-paths": "^4.2.0",
30
35
"tsx": "^4.20.6",
31
36
"typescript": "^5.9.3"
32
37
}
+846
pnpm-lock.yaml
+846
pnpm-lock.yaml
···
11
11
'@atproto/xrpc-server':
12
12
specifier: ^0.9.5
13
13
version: 0.9.5
14
+
'@ipld/car':
15
+
specifier: ^5.4.2
16
+
version: 5.4.2
17
+
'@ipld/dag-cbor':
18
+
specifier: ^9.2.5
19
+
version: 9.2.5
14
20
'@skyware/firehose':
15
21
specifier: ^0.5.2
16
22
version: 0.5.2
23
+
biome:
24
+
specifier: ^0.3.3
25
+
version: 0.3.3
17
26
dotenv:
18
27
specifier: ^17.2.3
19
28
version: 17.2.3
···
33
42
'@types/node':
34
43
specifier: ^24.9.2
35
44
version: 24.9.2
45
+
'@types/pg':
46
+
specifier: ^8.15.6
47
+
version: 8.15.6
36
48
'@types/ws':
37
49
specifier: ^8.18.1
38
50
version: 8.18.1
39
51
ts-node:
40
52
specifier: ^10.9.2
41
53
version: 10.9.2(@types/node@24.9.2)(typescript@5.9.3)
54
+
tsconfig-paths:
55
+
specifier: ^4.2.0
56
+
version: 4.2.0
42
57
tsx:
43
58
specifier: ^4.20.6
44
59
version: 4.20.6
···
286
301
cpu: [x64]
287
302
os: [win32]
288
303
304
+
'@ipld/car@5.4.2':
305
+
resolution: {integrity: sha512-gfyrJvePyXnh2Fbj8mPg4JYvEZ3izhk8C9WgAle7xIYbrJNSXmNQ6BxAls8Gof97vvGbCROdxbTWRmHJtTCbcg==}
306
+
engines: {node: '>=16.0.0', npm: '>=7.0.0'}
307
+
289
308
'@ipld/dag-cbor@7.0.3':
290
309
resolution: {integrity: sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA==}
291
310
311
+
'@ipld/dag-cbor@9.2.5':
312
+
resolution: {integrity: sha512-84wSr4jv30biui7endhobYhXBQzQE4c/wdoWlFrKcfiwH+ofaPg8fwsM8okX9cOzkkrsAsNdDyH3ou+kiLquwQ==}
313
+
engines: {node: '>=16.0.0', npm: '>=7.0.0'}
314
+
292
315
'@jridgewell/resolve-uri@3.1.2':
293
316
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
294
317
engines: {node: '>=6.0.0'}
···
328
351
'@types/node@24.9.2':
329
352
resolution: {integrity: sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==}
330
353
354
+
'@types/pg@8.15.6':
355
+
resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==}
356
+
331
357
'@types/ws@8.18.1':
332
358
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
333
359
···
348
374
engines: {node: '>=0.4.0'}
349
375
hasBin: true
350
376
377
+
ajv@6.12.6:
378
+
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
379
+
380
+
ansi-escapes@1.4.0:
381
+
resolution: {integrity: sha512-wiXutNjDUlNEDWHcYH3jtZUhd3c4/VojassD8zHdHCY13xbZy2XbW+NKQwA0tWGBVzDA9qEzYwfoSsWmviidhw==}
382
+
engines: {node: '>=0.10.0'}
383
+
384
+
ansi-regex@2.1.1:
385
+
resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==}
386
+
engines: {node: '>=0.10.0'}
387
+
388
+
ansi-styles@2.2.1:
389
+
resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==}
390
+
engines: {node: '>=0.10.0'}
391
+
392
+
any-promise@1.3.0:
393
+
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
394
+
351
395
arg@4.1.3:
352
396
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
353
397
354
398
array-flatten@1.1.1:
355
399
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
356
400
401
+
asn1@0.2.6:
402
+
resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
403
+
404
+
assert-plus@1.0.0:
405
+
resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
406
+
engines: {node: '>=0.8'}
407
+
408
+
asynckit@0.4.0:
409
+
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
410
+
357
411
atomic-sleep@1.0.0:
358
412
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
359
413
engines: {node: '>=8.0.0'}
360
414
415
+
aws-sign2@0.7.0:
416
+
resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==}
417
+
418
+
aws4@1.13.2:
419
+
resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==}
420
+
421
+
balanced-match@1.0.2:
422
+
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
423
+
361
424
base64-js@1.5.1:
362
425
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
363
426
427
+
bcrypt-pbkdf@1.0.2:
428
+
resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
429
+
430
+
biome@0.3.3:
431
+
resolution: {integrity: sha512-4LXjrQYbn9iTXu9Y4SKT7ABzTV0WnLDHCVSd2fPUOKsy1gQ+E4xPFmlY1zcWexoi0j7fGHItlL6OWA2CZ/yYAQ==}
432
+
hasBin: true
433
+
434
+
bluebird@3.7.2:
435
+
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
436
+
364
437
body-parser@1.20.3:
365
438
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
366
439
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
367
440
441
+
brace-expansion@1.1.12:
442
+
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
443
+
368
444
buffer@6.0.3:
369
445
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
370
446
···
380
456
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
381
457
engines: {node: '>= 0.4'}
382
458
459
+
caseless@0.12.0:
460
+
resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
461
+
383
462
cbor-extract@2.2.0:
384
463
resolution: {integrity: sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==}
385
464
hasBin: true
···
391
470
resolution: {integrity: sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==}
392
471
hasBin: true
393
472
473
+
cborg@4.2.18:
474
+
resolution: {integrity: sha512-uzhkd5HOaLccokqeZa5B0Qz7/aa9C12pmUq5yU3vcy6I6OhTKdPHSzOuBPZfcoQHdcx8Emz/dWZbPNNfF/puvg==}
475
+
hasBin: true
476
+
477
+
chalk@1.1.3:
478
+
resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==}
479
+
engines: {node: '>=0.10.0'}
480
+
481
+
cli-cursor@1.0.2:
482
+
resolution: {integrity: sha512-25tABq090YNKkF6JH7lcwO0zFJTRke4Jcq9iX2nr/Sz0Cjjv4gckmwlW6Ty/aoyFd6z3ysR2hMGC2GFugmBo6A==}
483
+
engines: {node: '>=0.10.0'}
484
+
485
+
cli-width@1.1.1:
486
+
resolution: {integrity: sha512-eMU2akIeEIkCxGXUNmDnJq1KzOIiPnJ+rKqRe6hcxE3vIOPvpMrBYOn/Bl7zNlYJj/zQxXquAnozHUCf9Whnsg==}
487
+
488
+
code-point-at@1.1.0:
489
+
resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==}
490
+
engines: {node: '>=0.10.0'}
491
+
492
+
combined-stream@1.0.8:
493
+
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
494
+
engines: {node: '>= 0.8'}
495
+
496
+
commander@2.20.3:
497
+
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
498
+
499
+
concat-map@0.0.1:
500
+
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
501
+
394
502
content-disposition@0.5.4:
395
503
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
396
504
engines: {node: '>= 0.6'}
···
406
514
resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==}
407
515
engines: {node: '>= 0.6'}
408
516
517
+
core-js@2.6.12:
518
+
resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==}
519
+
deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
520
+
521
+
core-util-is@1.0.2:
522
+
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
523
+
409
524
create-require@1.1.1:
410
525
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
411
526
527
+
dashdash@1.14.1:
528
+
resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
529
+
engines: {node: '>=0.10'}
530
+
412
531
debug@2.6.9:
413
532
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
414
533
peerDependencies:
···
417
536
supports-color:
418
537
optional: true
419
538
539
+
delayed-stream@1.0.0:
540
+
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
541
+
engines: {node: '>=0.4.0'}
542
+
420
543
depd@2.0.0:
421
544
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
422
545
engines: {node: '>= 0.8'}
···
441
564
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
442
565
engines: {node: '>= 0.4'}
443
566
567
+
earlgrey-runtime@0.1.2:
568
+
resolution: {integrity: sha512-T4qoScXi5TwALDv8nlGTvOuCT8jXcKcxtO8qVdqv46IA2GHJfQzwoBPbkOmORnyhu3A98cVVuhWLsM2CzPljJg==}
569
+
570
+
ecc-jsbn@0.1.2:
571
+
resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
572
+
573
+
editor@1.0.0:
574
+
resolution: {integrity: sha512-SoRmbGStwNYHgKfjOrX2L0mUvp9bUVv0uPppZSOMAntEbcFtoC3MKF5b3T6HQPXKIV+QGY3xPO3JK5it5lVkuw==}
575
+
444
576
ee-first@1.1.1:
445
577
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
446
578
···
472
604
escape-html@1.0.3:
473
605
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
474
606
607
+
escape-string-regexp@1.0.5:
608
+
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
609
+
engines: {node: '>=0.8.0'}
610
+
475
611
esm-env@1.2.2:
476
612
resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==}
477
613
···
487
623
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
488
624
engines: {node: '>=0.8.x'}
489
625
626
+
exit-hook@1.1.1:
627
+
resolution: {integrity: sha512-MsG3prOVw1WtLXAZbM3KiYtooKR1LvxHh3VHsVtIy0uiUu8usxgB/94DP2HxtD/661lLdB6yzQ09lGJSQr6nkg==}
628
+
engines: {node: '>=0.10.0'}
629
+
490
630
express@4.21.2:
491
631
resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==}
492
632
engines: {node: '>= 0.10.0'}
493
633
634
+
extend@3.0.2:
635
+
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
636
+
637
+
extsprintf@1.3.0:
638
+
resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==}
639
+
engines: {'0': node >=0.6.0}
640
+
641
+
fast-deep-equal@3.1.3:
642
+
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
643
+
644
+
fast-json-stable-stringify@2.1.0:
645
+
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
646
+
494
647
fast-redact@3.5.0:
495
648
resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==}
496
649
engines: {node: '>=6'}
497
650
651
+
figures@1.7.0:
652
+
resolution: {integrity: sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==}
653
+
engines: {node: '>=0.10.0'}
654
+
498
655
finalhandler@1.3.1:
499
656
resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==}
500
657
engines: {node: '>= 0.8'}
501
658
659
+
forever-agent@0.6.1:
660
+
resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
661
+
662
+
form-data@2.3.3:
663
+
resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==}
664
+
engines: {node: '>= 0.12'}
665
+
502
666
forwarded@0.2.0:
503
667
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
504
668
engines: {node: '>= 0.6'}
···
507
671
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
508
672
engines: {node: '>= 0.6'}
509
673
674
+
fs-extra@0.26.7:
675
+
resolution: {integrity: sha512-waKu+1KumRhYv8D8gMRCKJGAMI9pRnPuEb1mvgYD0f7wBscg+h6bW4FDTmEZhB9VKxvoTtxW+Y7bnIlB7zja6Q==}
676
+
677
+
fs-promise@0.5.0:
678
+
resolution: {integrity: sha512-Y+4F4ujhEcayCJt6JmzcOun9MYGQwz+bVUiuBmTkJImhBHKpBvmVPZR9wtfiF7k3ffwAOAuurygQe+cPLSFQhw==}
679
+
deprecated: Use mz or fs-extra^3.0 with Promise Support
680
+
681
+
fs.realpath@1.0.0:
682
+
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
683
+
510
684
fsevents@2.3.3:
511
685
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
512
686
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
···
526
700
get-tsconfig@4.13.0:
527
701
resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==}
528
702
703
+
getpass@0.1.7:
704
+
resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==}
705
+
706
+
glob@7.2.3:
707
+
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
708
+
deprecated: Glob versions prior to v9 are no longer supported
709
+
529
710
gopd@1.2.0:
530
711
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
531
712
engines: {node: '>= 0.4'}
532
713
714
+
graceful-fs@4.2.11:
715
+
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
716
+
533
717
graphemer@1.4.0:
534
718
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
535
719
720
+
har-schema@2.0.0:
721
+
resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==}
722
+
engines: {node: '>=4'}
723
+
724
+
har-validator@5.1.5:
725
+
resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==}
726
+
engines: {node: '>=6'}
727
+
deprecated: this library is no longer supported
728
+
729
+
has-ansi@2.0.0:
730
+
resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==}
731
+
engines: {node: '>=0.10.0'}
732
+
536
733
has-symbols@1.1.0:
537
734
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
538
735
engines: {node: '>= 0.4'}
···
545
742
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
546
743
engines: {node: '>= 0.8'}
547
744
745
+
http-signature@1.2.0:
746
+
resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==}
747
+
engines: {node: '>=0.8', npm: '>=1.3.7'}
748
+
548
749
iconv-lite@0.4.24:
549
750
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
550
751
engines: {node: '>=0.10.0'}
···
552
753
ieee754@1.2.1:
553
754
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
554
755
756
+
inflight@1.0.6:
757
+
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
758
+
deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
759
+
555
760
inherits@2.0.4:
556
761
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
557
762
763
+
inquirer-promise@0.0.3:
764
+
resolution: {integrity: sha512-82CQX586JAV9GAgU9yXZsMDs+NorjA0nLhkfFx9+PReyOnuoHRbHrC1Z90sS95bFJI1Tm1gzMObuE0HabzkJpg==}
765
+
766
+
inquirer@0.11.4:
767
+
resolution: {integrity: sha512-QR+2TW90jnKk9LUUtbcA3yQXKt2rDEKMh6+BAZQIeumtzHexnwVLdPakSslGijXYLJCzFv7GMXbFCn0pA00EUw==}
768
+
558
769
ipaddr.js@1.9.1:
559
770
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
560
771
engines: {node: '>= 0.10'}
561
772
773
+
is-fullwidth-code-point@1.0.0:
774
+
resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==}
775
+
engines: {node: '>=0.10.0'}
776
+
777
+
is-typedarray@1.0.0:
778
+
resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==}
779
+
562
780
iso-datestring-validator@2.2.2:
563
781
resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==}
564
782
783
+
isstream@0.1.2:
784
+
resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==}
785
+
786
+
jsbn@0.1.1:
787
+
resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==}
788
+
789
+
json-schema-traverse@0.4.1:
790
+
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
791
+
792
+
json-schema@0.4.0:
793
+
resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
794
+
795
+
json-stringify-safe@5.0.1:
796
+
resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
797
+
798
+
json5@2.2.3:
799
+
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
800
+
engines: {node: '>=6'}
801
+
hasBin: true
802
+
803
+
jsonfile@2.4.0:
804
+
resolution: {integrity: sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==}
805
+
806
+
jsprim@1.4.2:
807
+
resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==}
808
+
engines: {node: '>=0.6.0'}
809
+
810
+
kaiser@0.0.4:
811
+
resolution: {integrity: sha512-m8ju+rmBqvclZmyrOXgGGhOYSjKJK6RN1NhqEltemY87UqZOxEkizg9TOy1vQSyJ01Wx6SAPuuN0iO2Mgislvw==}
812
+
813
+
klaw@1.3.1:
814
+
resolution: {integrity: sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==}
815
+
565
816
kysely@0.28.8:
566
817
resolution: {integrity: sha512-QUOgl5ZrS9IRuhq5FvOKFSsD/3+IA6MLE81/bOOTRA/YQpKDza2sFdN5g6JCB9BOpqMJDGefLCQ9F12hRS13TA==}
567
818
engines: {node: '>=20.0.0'}
568
819
820
+
lodash@3.10.1:
821
+
resolution: {integrity: sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==}
822
+
823
+
lodash@4.17.21:
824
+
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
825
+
569
826
make-error@1.3.6:
570
827
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
571
828
···
597
854
engines: {node: '>=4'}
598
855
hasBin: true
599
856
857
+
minimatch@3.1.2:
858
+
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
859
+
860
+
minimist@1.2.8:
861
+
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
862
+
600
863
ms@2.0.0:
601
864
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
602
865
603
866
ms@2.1.3:
604
867
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
605
868
869
+
multiformats@13.4.1:
870
+
resolution: {integrity: sha512-VqO6OSvLrFVAYYjgsr8tyv62/rCQhPgsZUXLTqoFLSgdkgiUYKYeArbt1uWLlEpkjxQe+P0+sHlbPEte1Bi06Q==}
871
+
606
872
multiformats@9.9.0:
607
873
resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==}
608
874
875
+
mute-stream@0.0.5:
876
+
resolution: {integrity: sha512-EbrziT4s8cWPmzr47eYVW3wimS4HsvlnV5ri1xw1aR6JQo/OrJX5rkl32K/QQHdxeabJETtfeaROGhd8W7uBgg==}
877
+
878
+
mz@2.7.0:
879
+
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
880
+
609
881
nanoevents@9.1.0:
610
882
resolution: {integrity: sha512-Jd0fILWG44a9luj8v5kED4WI+zfkkgwKyRQKItTtlPfEsh7Lznfi1kr8/iZ+XAIss4Qq5GqRB0qtWbaz9ceO/A==}
611
883
engines: {node: ^18.0.0 || >=20.0.0}
···
618
890
resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==}
619
891
hasBin: true
620
892
893
+
number-is-nan@1.0.1:
894
+
resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==}
895
+
engines: {node: '>=0.10.0'}
896
+
897
+
oauth-sign@0.9.0:
898
+
resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==}
899
+
900
+
object-assign@4.1.1:
901
+
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
902
+
engines: {node: '>=0.10.0'}
903
+
621
904
object-inspect@1.13.4:
622
905
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
623
906
engines: {node: '>= 0.4'}
···
630
913
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
631
914
engines: {node: '>= 0.8'}
632
915
916
+
once@1.4.0:
917
+
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
918
+
919
+
onetime@1.1.0:
920
+
resolution: {integrity: sha512-GZ+g4jayMqzCRMgB2sol7GiCLjKfS1PINkjmx8spcKce1LiVqcbQreXwqs2YAFXC6R03VIG28ZS31t8M866v6A==}
921
+
engines: {node: '>=0.10.0'}
922
+
923
+
os-homedir@1.0.2:
924
+
resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==}
925
+
engines: {node: '>=0.10.0'}
926
+
633
927
parseurl@1.3.3:
634
928
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
635
929
engines: {node: '>= 0.8'}
636
930
931
+
path-is-absolute@1.0.1:
932
+
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
933
+
engines: {node: '>=0.10.0'}
934
+
637
935
path-to-regexp@0.1.12:
638
936
resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==}
639
937
938
+
performance-now@2.1.0:
939
+
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
940
+
640
941
pg-cloudflare@1.2.7:
641
942
resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==}
642
943
···
708
1009
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
709
1010
engines: {node: '>= 0.10'}
710
1011
1012
+
psl@1.15.0:
1013
+
resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
1014
+
1015
+
punycode@2.3.1:
1016
+
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
1017
+
engines: {node: '>=6'}
1018
+
711
1019
qs@6.13.0:
712
1020
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
713
1021
engines: {node: '>=0.6'}
714
1022
1023
+
qs@6.5.3:
1024
+
resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==}
1025
+
engines: {node: '>=0.6'}
1026
+
715
1027
quick-format-unescaped@4.0.4:
716
1028
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
717
1029
···
730
1042
resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==}
731
1043
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
732
1044
1045
+
readline2@1.0.1:
1046
+
resolution: {integrity: sha512-8/td4MmwUB6PkZUbV25uKz7dfrmjYWxsW8DVfibWdlHRk/l/DfHKn4pU+dfcoGLFgWOdyGCzINRQD7jn+Bv+/g==}
1047
+
733
1048
real-require@0.2.0:
734
1049
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
735
1050
engines: {node: '>= 12.13.0'}
736
1051
1052
+
regenerator-runtime@0.9.6:
1053
+
resolution: {integrity: sha512-D0Y/JJ4VhusyMOd/o25a3jdUqN/bC85EFsaoL9Oqmy/O4efCh+xhp7yj2EEOsj974qvMkcW8AwUzJ1jB/MbxCw==}
1054
+
1055
+
request-promise@3.0.0:
1056
+
resolution: {integrity: sha512-wVGUX+BoKxYsavTA72i6qHcyLbjzM4LR4y/AmDCqlbuMAursZdDWO7PmgbGAUvD2SeEJ5iB99VSq/U51i/DNbw==}
1057
+
engines: {node: '>=0.10.0'}
1058
+
deprecated: request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142
1059
+
1060
+
request@2.88.2:
1061
+
resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==}
1062
+
engines: {node: '>= 6'}
1063
+
deprecated: request has been deprecated, see https://github.com/request/request/issues/3142
1064
+
737
1065
resolve-pkg-maps@1.0.0:
738
1066
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
739
1067
1068
+
restore-cursor@1.0.1:
1069
+
resolution: {integrity: sha512-reSjH4HuiFlxlaBaFCiS6O76ZGG2ygKoSlCsipKdaZuKSPx/+bt9mULkn4l0asVzbEfQQmXRg6Wp6gv6m0wElw==}
1070
+
engines: {node: '>=0.10.0'}
1071
+
1072
+
rimraf@2.7.1:
1073
+
resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
1074
+
deprecated: Rimraf versions prior to v4 are no longer supported
1075
+
hasBin: true
1076
+
1077
+
run-async@0.1.0:
1078
+
resolution: {integrity: sha512-qOX+w+IxFgpUpJfkv2oGN0+ExPs68F4sZHfaRRx4dDexAQkG83atugKVEylyT5ARees3HBbfmuvnjbrd8j9Wjw==}
1079
+
1080
+
rx-lite@3.1.2:
1081
+
resolution: {integrity: sha512-1I1+G2gteLB8Tkt8YI1sJvSIfa0lWuRtC8GjvtyPBcLSF5jBCCJJqKrpER5JU5r6Bhe+i9/pK3VMuUcXu0kdwQ==}
1082
+
740
1083
safe-buffer@5.2.1:
741
1084
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
742
1085
···
781
1124
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
782
1125
engines: {node: '>= 10.x'}
783
1126
1127
+
sshpk@1.18.0:
1128
+
resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==}
1129
+
engines: {node: '>=0.10.0'}
1130
+
hasBin: true
1131
+
784
1132
statuses@2.0.1:
785
1133
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
786
1134
engines: {node: '>= 0.8'}
787
1135
1136
+
string-width@1.0.2:
1137
+
resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==}
1138
+
engines: {node: '>=0.10.0'}
1139
+
788
1140
string_decoder@1.3.0:
789
1141
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
790
1142
1143
+
strip-ansi@3.0.1:
1144
+
resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==}
1145
+
engines: {node: '>=0.10.0'}
1146
+
1147
+
strip-bom@3.0.0:
1148
+
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
1149
+
engines: {node: '>=4'}
1150
+
1151
+
supports-color@2.0.0:
1152
+
resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==}
1153
+
engines: {node: '>=0.8.0'}
1154
+
1155
+
thenify-all@1.6.0:
1156
+
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
1157
+
engines: {node: '>=0.8'}
1158
+
1159
+
thenify@3.3.1:
1160
+
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
1161
+
791
1162
thread-stream@2.7.0:
792
1163
resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==}
793
1164
1165
+
through@2.3.8:
1166
+
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
1167
+
794
1168
toidentifier@1.0.1:
795
1169
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
796
1170
engines: {node: '>=0.6'}
797
1171
1172
+
tough-cookie@2.5.0:
1173
+
resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==}
1174
+
engines: {node: '>=0.8'}
1175
+
798
1176
ts-node@10.9.2:
799
1177
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
800
1178
hasBin: true
···
809
1187
'@swc/wasm':
810
1188
optional: true
811
1189
1190
+
tsconfig-paths@4.2.0:
1191
+
resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==}
1192
+
engines: {node: '>=6'}
1193
+
812
1194
tsx@4.20.6:
813
1195
resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==}
814
1196
engines: {node: '>=18.0.0'}
815
1197
hasBin: true
816
1198
1199
+
tunnel-agent@0.6.0:
1200
+
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
1201
+
1202
+
tweetnacl@0.14.5:
1203
+
resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
1204
+
817
1205
type-is@1.6.18:
818
1206
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
819
1207
engines: {node: '>= 0.6'}
···
833
1221
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
834
1222
engines: {node: '>= 0.8'}
835
1223
1224
+
untildify@3.0.3:
1225
+
resolution: {integrity: sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==}
1226
+
engines: {node: '>=4'}
1227
+
1228
+
uri-js@4.4.1:
1229
+
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
1230
+
1231
+
user-home@2.0.0:
1232
+
resolution: {integrity: sha512-KMWqdlOcjCYdtIJpicDSFBQ8nFwS2i9sslAd6f4+CBGcU4gist2REnr2fxj2YocvJFxSF3ZOHLYLVZnUxv4BZQ==}
1233
+
engines: {node: '>=0.10.0'}
1234
+
836
1235
utils-merge@1.0.1:
837
1236
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
838
1237
engines: {node: '>= 0.4.0'}
839
1238
1239
+
uuid@3.4.0:
1240
+
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
1241
+
deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
1242
+
hasBin: true
1243
+
840
1244
v8-compile-cache-lib@3.0.1:
841
1245
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
842
1246
1247
+
varint@6.0.0:
1248
+
resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==}
1249
+
843
1250
vary@1.1.2:
844
1251
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
845
1252
engines: {node: '>= 0.8'}
846
1253
1254
+
verror@1.10.0:
1255
+
resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==}
1256
+
engines: {'0': node >=0.6.0}
1257
+
1258
+
wrappy@1.0.2:
1259
+
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
1260
+
847
1261
ws@8.18.3:
848
1262
resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
849
1263
engines: {node: '>=10.0.0'}
···
1065
1479
'@esbuild/win32-x64@0.25.11':
1066
1480
optional: true
1067
1481
1482
+
'@ipld/car@5.4.2':
1483
+
dependencies:
1484
+
'@ipld/dag-cbor': 9.2.5
1485
+
cborg: 4.2.18
1486
+
multiformats: 13.4.1
1487
+
varint: 6.0.0
1488
+
1068
1489
'@ipld/dag-cbor@7.0.3':
1069
1490
dependencies:
1070
1491
cborg: 1.10.2
1071
1492
multiformats: 9.9.0
1072
1493
1494
+
'@ipld/dag-cbor@9.2.5':
1495
+
dependencies:
1496
+
cborg: 4.2.18
1497
+
multiformats: 13.4.1
1498
+
1073
1499
'@jridgewell/resolve-uri@3.1.2': {}
1074
1500
1075
1501
'@jridgewell/sourcemap-codec@1.5.5': {}
···
1105
1531
dependencies:
1106
1532
undici-types: 7.16.0
1107
1533
1534
+
'@types/pg@8.15.6':
1535
+
dependencies:
1536
+
'@types/node': 24.9.2
1537
+
pg-protocol: 1.10.3
1538
+
pg-types: 2.2.0
1539
+
1108
1540
'@types/ws@8.18.1':
1109
1541
dependencies:
1110
1542
'@types/node': 24.9.2
···
1124
1556
1125
1557
acorn@8.15.0: {}
1126
1558
1559
+
ajv@6.12.6:
1560
+
dependencies:
1561
+
fast-deep-equal: 3.1.3
1562
+
fast-json-stable-stringify: 2.1.0
1563
+
json-schema-traverse: 0.4.1
1564
+
uri-js: 4.4.1
1565
+
1566
+
ansi-escapes@1.4.0: {}
1567
+
1568
+
ansi-regex@2.1.1: {}
1569
+
1570
+
ansi-styles@2.2.1: {}
1571
+
1572
+
any-promise@1.3.0: {}
1573
+
1127
1574
arg@4.1.3: {}
1128
1575
1129
1576
array-flatten@1.1.1: {}
1130
1577
1578
+
asn1@0.2.6:
1579
+
dependencies:
1580
+
safer-buffer: 2.1.2
1581
+
1582
+
assert-plus@1.0.0: {}
1583
+
1584
+
asynckit@0.4.0: {}
1585
+
1131
1586
atomic-sleep@1.0.0: {}
1132
1587
1588
+
aws-sign2@0.7.0: {}
1589
+
1590
+
aws4@1.13.2: {}
1591
+
1592
+
balanced-match@1.0.2: {}
1593
+
1133
1594
base64-js@1.5.1: {}
1134
1595
1596
+
bcrypt-pbkdf@1.0.2:
1597
+
dependencies:
1598
+
tweetnacl: 0.14.5
1599
+
1600
+
biome@0.3.3:
1601
+
dependencies:
1602
+
bluebird: 3.7.2
1603
+
chalk: 1.1.3
1604
+
commander: 2.20.3
1605
+
editor: 1.0.0
1606
+
fs-promise: 0.5.0
1607
+
inquirer-promise: 0.0.3
1608
+
request-promise: 3.0.0
1609
+
untildify: 3.0.3
1610
+
user-home: 2.0.0
1611
+
1612
+
bluebird@3.7.2: {}
1613
+
1135
1614
body-parser@1.20.3:
1136
1615
dependencies:
1137
1616
bytes: 3.1.2
···
1149
1628
transitivePeerDependencies:
1150
1629
- supports-color
1151
1630
1631
+
brace-expansion@1.1.12:
1632
+
dependencies:
1633
+
balanced-match: 1.0.2
1634
+
concat-map: 0.0.1
1635
+
1152
1636
buffer@6.0.3:
1153
1637
dependencies:
1154
1638
base64-js: 1.5.1
···
1166
1650
call-bind-apply-helpers: 1.0.2
1167
1651
get-intrinsic: 1.3.0
1168
1652
1653
+
caseless@0.12.0: {}
1654
+
1169
1655
cbor-extract@2.2.0:
1170
1656
dependencies:
1171
1657
node-gyp-build-optional-packages: 5.1.1
···
1184
1670
1185
1671
cborg@1.10.2: {}
1186
1672
1673
+
cborg@4.2.18: {}
1674
+
1675
+
chalk@1.1.3:
1676
+
dependencies:
1677
+
ansi-styles: 2.2.1
1678
+
escape-string-regexp: 1.0.5
1679
+
has-ansi: 2.0.0
1680
+
strip-ansi: 3.0.1
1681
+
supports-color: 2.0.0
1682
+
1683
+
cli-cursor@1.0.2:
1684
+
dependencies:
1685
+
restore-cursor: 1.0.1
1686
+
1687
+
cli-width@1.1.1: {}
1688
+
1689
+
code-point-at@1.1.0: {}
1690
+
1691
+
combined-stream@1.0.8:
1692
+
dependencies:
1693
+
delayed-stream: 1.0.0
1694
+
1695
+
commander@2.20.3: {}
1696
+
1697
+
concat-map@0.0.1: {}
1698
+
1187
1699
content-disposition@0.5.4:
1188
1700
dependencies:
1189
1701
safe-buffer: 5.2.1
···
1194
1706
1195
1707
cookie@0.7.1: {}
1196
1708
1709
+
core-js@2.6.12: {}
1710
+
1711
+
core-util-is@1.0.2: {}
1712
+
1197
1713
create-require@1.1.1: {}
1198
1714
1715
+
dashdash@1.14.1:
1716
+
dependencies:
1717
+
assert-plus: 1.0.0
1718
+
1199
1719
debug@2.6.9:
1200
1720
dependencies:
1201
1721
ms: 2.0.0
1202
1722
1723
+
delayed-stream@1.0.0: {}
1724
+
1203
1725
depd@2.0.0: {}
1204
1726
1205
1727
destroy@1.2.0: {}
···
1217
1739
es-errors: 1.3.0
1218
1740
gopd: 1.2.0
1219
1741
1742
+
earlgrey-runtime@0.1.2:
1743
+
dependencies:
1744
+
core-js: 2.6.12
1745
+
kaiser: 0.0.4
1746
+
lodash: 4.17.21
1747
+
regenerator-runtime: 0.9.6
1748
+
1749
+
ecc-jsbn@0.1.2:
1750
+
dependencies:
1751
+
jsbn: 0.1.1
1752
+
safer-buffer: 2.1.2
1753
+
1754
+
editor@1.0.0: {}
1755
+
1220
1756
ee-first@1.1.1: {}
1221
1757
1222
1758
encodeurl@1.0.2: {}
···
1262
1798
1263
1799
escape-html@1.0.3: {}
1264
1800
1801
+
escape-string-regexp@1.0.5: {}
1802
+
1265
1803
esm-env@1.2.2: {}
1266
1804
1267
1805
etag@1.8.1: {}
···
1270
1808
1271
1809
events@3.3.0: {}
1272
1810
1811
+
exit-hook@1.1.1: {}
1812
+
1273
1813
express@4.21.2:
1274
1814
dependencies:
1275
1815
accepts: 1.3.8
···
1306
1846
transitivePeerDependencies:
1307
1847
- supports-color
1308
1848
1849
+
extend@3.0.2: {}
1850
+
1851
+
extsprintf@1.3.0: {}
1852
+
1853
+
fast-deep-equal@3.1.3: {}
1854
+
1855
+
fast-json-stable-stringify@2.1.0: {}
1856
+
1309
1857
fast-redact@3.5.0: {}
1310
1858
1859
+
figures@1.7.0:
1860
+
dependencies:
1861
+
escape-string-regexp: 1.0.5
1862
+
object-assign: 4.1.1
1863
+
1311
1864
finalhandler@1.3.1:
1312
1865
dependencies:
1313
1866
debug: 2.6.9
···
1320
1873
transitivePeerDependencies:
1321
1874
- supports-color
1322
1875
1876
+
forever-agent@0.6.1: {}
1877
+
1878
+
form-data@2.3.3:
1879
+
dependencies:
1880
+
asynckit: 0.4.0
1881
+
combined-stream: 1.0.8
1882
+
mime-types: 2.1.35
1883
+
1323
1884
forwarded@0.2.0: {}
1324
1885
1325
1886
fresh@0.5.2: {}
1326
1887
1888
+
fs-extra@0.26.7:
1889
+
dependencies:
1890
+
graceful-fs: 4.2.11
1891
+
jsonfile: 2.4.0
1892
+
klaw: 1.3.1
1893
+
path-is-absolute: 1.0.1
1894
+
rimraf: 2.7.1
1895
+
1896
+
fs-promise@0.5.0:
1897
+
dependencies:
1898
+
any-promise: 1.3.0
1899
+
fs-extra: 0.26.7
1900
+
mz: 2.7.0
1901
+
thenify-all: 1.6.0
1902
+
1903
+
fs.realpath@1.0.0: {}
1904
+
1327
1905
fsevents@2.3.3:
1328
1906
optional: true
1329
1907
···
1351
1929
dependencies:
1352
1930
resolve-pkg-maps: 1.0.0
1353
1931
1932
+
getpass@0.1.7:
1933
+
dependencies:
1934
+
assert-plus: 1.0.0
1935
+
1936
+
glob@7.2.3:
1937
+
dependencies:
1938
+
fs.realpath: 1.0.0
1939
+
inflight: 1.0.6
1940
+
inherits: 2.0.4
1941
+
minimatch: 3.1.2
1942
+
once: 1.4.0
1943
+
path-is-absolute: 1.0.1
1944
+
1354
1945
gopd@1.2.0: {}
1355
1946
1947
+
graceful-fs@4.2.11: {}
1948
+
1356
1949
graphemer@1.4.0: {}
1357
1950
1951
+
har-schema@2.0.0: {}
1952
+
1953
+
har-validator@5.1.5:
1954
+
dependencies:
1955
+
ajv: 6.12.6
1956
+
har-schema: 2.0.0
1957
+
1958
+
has-ansi@2.0.0:
1959
+
dependencies:
1960
+
ansi-regex: 2.1.1
1961
+
1358
1962
has-symbols@1.1.0: {}
1359
1963
1360
1964
hasown@2.0.2:
···
1369
1973
statuses: 2.0.1
1370
1974
toidentifier: 1.0.1
1371
1975
1976
+
http-signature@1.2.0:
1977
+
dependencies:
1978
+
assert-plus: 1.0.0
1979
+
jsprim: 1.4.2
1980
+
sshpk: 1.18.0
1981
+
1372
1982
iconv-lite@0.4.24:
1373
1983
dependencies:
1374
1984
safer-buffer: 2.1.2
1375
1985
1376
1986
ieee754@1.2.1: {}
1377
1987
1988
+
inflight@1.0.6:
1989
+
dependencies:
1990
+
once: 1.4.0
1991
+
wrappy: 1.0.2
1992
+
1378
1993
inherits@2.0.4: {}
1379
1994
1995
+
inquirer-promise@0.0.3:
1996
+
dependencies:
1997
+
earlgrey-runtime: 0.1.2
1998
+
inquirer: 0.11.4
1999
+
2000
+
inquirer@0.11.4:
2001
+
dependencies:
2002
+
ansi-escapes: 1.4.0
2003
+
ansi-regex: 2.1.1
2004
+
chalk: 1.1.3
2005
+
cli-cursor: 1.0.2
2006
+
cli-width: 1.1.1
2007
+
figures: 1.7.0
2008
+
lodash: 3.10.1
2009
+
readline2: 1.0.1
2010
+
run-async: 0.1.0
2011
+
rx-lite: 3.1.2
2012
+
string-width: 1.0.2
2013
+
strip-ansi: 3.0.1
2014
+
through: 2.3.8
2015
+
1380
2016
ipaddr.js@1.9.1: {}
1381
2017
2018
+
is-fullwidth-code-point@1.0.0:
2019
+
dependencies:
2020
+
number-is-nan: 1.0.1
2021
+
2022
+
is-typedarray@1.0.0: {}
2023
+
1382
2024
iso-datestring-validator@2.2.2: {}
1383
2025
2026
+
isstream@0.1.2: {}
2027
+
2028
+
jsbn@0.1.1: {}
2029
+
2030
+
json-schema-traverse@0.4.1: {}
2031
+
2032
+
json-schema@0.4.0: {}
2033
+
2034
+
json-stringify-safe@5.0.1: {}
2035
+
2036
+
json5@2.2.3: {}
2037
+
2038
+
jsonfile@2.4.0:
2039
+
optionalDependencies:
2040
+
graceful-fs: 4.2.11
2041
+
2042
+
jsprim@1.4.2:
2043
+
dependencies:
2044
+
assert-plus: 1.0.0
2045
+
extsprintf: 1.3.0
2046
+
json-schema: 0.4.0
2047
+
verror: 1.10.0
2048
+
2049
+
kaiser@0.0.4:
2050
+
dependencies:
2051
+
earlgrey-runtime: 0.1.2
2052
+
2053
+
klaw@1.3.1:
2054
+
optionalDependencies:
2055
+
graceful-fs: 4.2.11
2056
+
1384
2057
kysely@0.28.8: {}
1385
2058
2059
+
lodash@3.10.1: {}
2060
+
2061
+
lodash@4.17.21: {}
2062
+
1386
2063
make-error@1.3.6: {}
1387
2064
1388
2065
math-intrinsics@1.1.0: {}
···
1401
2078
1402
2079
mime@1.6.0: {}
1403
2080
2081
+
minimatch@3.1.2:
2082
+
dependencies:
2083
+
brace-expansion: 1.1.12
2084
+
2085
+
minimist@1.2.8: {}
2086
+
1404
2087
ms@2.0.0: {}
1405
2088
1406
2089
ms@2.1.3: {}
1407
2090
2091
+
multiformats@13.4.1: {}
2092
+
1408
2093
multiformats@9.9.0: {}
1409
2094
2095
+
mute-stream@0.0.5: {}
2096
+
2097
+
mz@2.7.0:
2098
+
dependencies:
2099
+
any-promise: 1.3.0
2100
+
object-assign: 4.1.1
2101
+
thenify-all: 1.6.0
2102
+
1410
2103
nanoevents@9.1.0: {}
1411
2104
1412
2105
negotiator@0.6.3: {}
···
1416
2109
detect-libc: 2.1.2
1417
2110
optional: true
1418
2111
2112
+
number-is-nan@1.0.1: {}
2113
+
2114
+
oauth-sign@0.9.0: {}
2115
+
2116
+
object-assign@4.1.1: {}
2117
+
1419
2118
object-inspect@1.13.4: {}
1420
2119
1421
2120
on-exit-leak-free@2.1.2: {}
···
1424
2123
dependencies:
1425
2124
ee-first: 1.1.1
1426
2125
2126
+
once@1.4.0:
2127
+
dependencies:
2128
+
wrappy: 1.0.2
2129
+
2130
+
onetime@1.1.0: {}
2131
+
2132
+
os-homedir@1.0.2: {}
2133
+
1427
2134
parseurl@1.3.3: {}
1428
2135
2136
+
path-is-absolute@1.0.1: {}
2137
+
1429
2138
path-to-regexp@0.1.12: {}
1430
2139
2140
+
performance-now@2.1.0: {}
2141
+
1431
2142
pg-cloudflare@1.2.7:
1432
2143
optional: true
1433
2144
···
1503
2214
forwarded: 0.2.0
1504
2215
ipaddr.js: 1.9.1
1505
2216
2217
+
psl@1.15.0:
2218
+
dependencies:
2219
+
punycode: 2.3.1
2220
+
2221
+
punycode@2.3.1: {}
2222
+
1506
2223
qs@6.13.0:
1507
2224
dependencies:
1508
2225
side-channel: 1.1.0
1509
2226
2227
+
qs@6.5.3: {}
2228
+
1510
2229
quick-format-unescaped@4.0.4: {}
1511
2230
1512
2231
range-parser@1.2.1: {}
···
1528
2247
process: 0.11.10
1529
2248
string_decoder: 1.3.0
1530
2249
2250
+
readline2@1.0.1:
2251
+
dependencies:
2252
+
code-point-at: 1.1.0
2253
+
is-fullwidth-code-point: 1.0.0
2254
+
mute-stream: 0.0.5
2255
+
1531
2256
real-require@0.2.0: {}
1532
2257
2258
+
regenerator-runtime@0.9.6: {}
2259
+
2260
+
request-promise@3.0.0:
2261
+
dependencies:
2262
+
bluebird: 3.7.2
2263
+
lodash: 4.17.21
2264
+
request: 2.88.2
2265
+
2266
+
request@2.88.2:
2267
+
dependencies:
2268
+
aws-sign2: 0.7.0
2269
+
aws4: 1.13.2
2270
+
caseless: 0.12.0
2271
+
combined-stream: 1.0.8
2272
+
extend: 3.0.2
2273
+
forever-agent: 0.6.1
2274
+
form-data: 2.3.3
2275
+
har-validator: 5.1.5
2276
+
http-signature: 1.2.0
2277
+
is-typedarray: 1.0.0
2278
+
isstream: 0.1.2
2279
+
json-stringify-safe: 5.0.1
2280
+
mime-types: 2.1.35
2281
+
oauth-sign: 0.9.0
2282
+
performance-now: 2.1.0
2283
+
qs: 6.5.3
2284
+
safe-buffer: 5.2.1
2285
+
tough-cookie: 2.5.0
2286
+
tunnel-agent: 0.6.0
2287
+
uuid: 3.4.0
2288
+
1533
2289
resolve-pkg-maps@1.0.0: {}
1534
2290
2291
+
restore-cursor@1.0.1:
2292
+
dependencies:
2293
+
exit-hook: 1.1.1
2294
+
onetime: 1.1.0
2295
+
2296
+
rimraf@2.7.1:
2297
+
dependencies:
2298
+
glob: 7.2.3
2299
+
2300
+
run-async@0.1.0:
2301
+
dependencies:
2302
+
once: 1.4.0
2303
+
2304
+
rx-lite@3.1.2: {}
2305
+
1535
2306
safe-buffer@5.2.1: {}
1536
2307
1537
2308
safe-stable-stringify@2.5.0: {}
···
1601
2372
1602
2373
split2@4.2.0: {}
1603
2374
2375
+
sshpk@1.18.0:
2376
+
dependencies:
2377
+
asn1: 0.2.6
2378
+
assert-plus: 1.0.0
2379
+
bcrypt-pbkdf: 1.0.2
2380
+
dashdash: 1.14.1
2381
+
ecc-jsbn: 0.1.2
2382
+
getpass: 0.1.7
2383
+
jsbn: 0.1.1
2384
+
safer-buffer: 2.1.2
2385
+
tweetnacl: 0.14.5
2386
+
1604
2387
statuses@2.0.1: {}
1605
2388
2389
+
string-width@1.0.2:
2390
+
dependencies:
2391
+
code-point-at: 1.1.0
2392
+
is-fullwidth-code-point: 1.0.0
2393
+
strip-ansi: 3.0.1
2394
+
1606
2395
string_decoder@1.3.0:
1607
2396
dependencies:
1608
2397
safe-buffer: 5.2.1
1609
2398
2399
+
strip-ansi@3.0.1:
2400
+
dependencies:
2401
+
ansi-regex: 2.1.1
2402
+
2403
+
strip-bom@3.0.0: {}
2404
+
2405
+
supports-color@2.0.0: {}
2406
+
2407
+
thenify-all@1.6.0:
2408
+
dependencies:
2409
+
thenify: 3.3.1
2410
+
2411
+
thenify@3.3.1:
2412
+
dependencies:
2413
+
any-promise: 1.3.0
2414
+
1610
2415
thread-stream@2.7.0:
1611
2416
dependencies:
1612
2417
real-require: 0.2.0
1613
2418
2419
+
through@2.3.8: {}
2420
+
1614
2421
toidentifier@1.0.1: {}
1615
2422
2423
+
tough-cookie@2.5.0:
2424
+
dependencies:
2425
+
psl: 1.15.0
2426
+
punycode: 2.3.1
2427
+
1616
2428
ts-node@10.9.2(@types/node@24.9.2)(typescript@5.9.3):
1617
2429
dependencies:
1618
2430
'@cspotcode/source-map-support': 0.8.1
···
1631
2443
v8-compile-cache-lib: 3.0.1
1632
2444
yn: 3.1.1
1633
2445
2446
+
tsconfig-paths@4.2.0:
2447
+
dependencies:
2448
+
json5: 2.2.3
2449
+
minimist: 1.2.8
2450
+
strip-bom: 3.0.0
2451
+
1634
2452
tsx@4.20.6:
1635
2453
dependencies:
1636
2454
esbuild: 0.25.11
···
1638
2456
optionalDependencies:
1639
2457
fsevents: 2.3.3
1640
2458
2459
+
tunnel-agent@0.6.0:
2460
+
dependencies:
2461
+
safe-buffer: 5.2.1
2462
+
2463
+
tweetnacl@0.14.5: {}
2464
+
1641
2465
type-is@1.6.18:
1642
2466
dependencies:
1643
2467
media-typer: 0.3.0
···
1653
2477
1654
2478
unpipe@1.0.0: {}
1655
2479
2480
+
untildify@3.0.3: {}
2481
+
2482
+
uri-js@4.4.1:
2483
+
dependencies:
2484
+
punycode: 2.3.1
2485
+
2486
+
user-home@2.0.0:
2487
+
dependencies:
2488
+
os-homedir: 1.0.2
2489
+
1656
2490
utils-merge@1.0.1: {}
1657
2491
2492
+
uuid@3.4.0: {}
2493
+
1658
2494
v8-compile-cache-lib@3.0.1: {}
1659
2495
2496
+
varint@6.0.0: {}
2497
+
1660
2498
vary@1.1.2: {}
1661
2499
2500
+
verror@1.10.0:
2501
+
dependencies:
2502
+
assert-plus: 1.0.0
2503
+
core-util-is: 1.0.2
2504
+
extsprintf: 1.3.0
2505
+
2506
+
wrappy@1.0.2: {}
2507
+
1662
2508
ws@8.18.3: {}
1663
2509
1664
2510
xtend@4.0.2: {}
+21
-38
src/firehose.ts
+21
-38
src/firehose.ts
···
4
4
import { Insertable } from "kysely";
5
5
import { FirehoseEventTable } from "./db";
6
6
7
-
const pretty_print = (event_type: string, data: object) => {
8
-
const colors = {
9
-
commit: "\x1b[34m",
10
-
identity: "\x1b[32m",
11
-
account: "\x1b[33m",
12
-
reset: "\x1b[0m",
13
-
};
14
-
const color = colors[event_type.toLowerCase()] || colors.reset;
15
-
console.debug(`\n${color}## RECEIVED [${event_type.toUpperCase()}] EVENT ##${colors.reset}`);
16
-
console.debug(JSON.stringify(
17
-
data,
18
-
(key, value) => typeof value === 'bigint' ? value.toString() : value,
19
-
2
20
-
));
21
-
};
22
-
23
7
const saveEvent = async (type: 'commit' | 'identity' | 'account', data: any) => {
24
-
try {
25
-
await db.insertInto('firehose_event').values({
26
-
event_type: type,
27
-
event_data: data
28
-
}).execute();
29
-
} catch (error) {
30
-
console.error("\nFailed to save event to database:", error);
31
-
}
8
+
try {
9
+
await db.insertInto('firehose_event').values({
10
+
event_type: type,
11
+
event_data: data
12
+
}).execute();
13
+
} catch (error) {
14
+
console.error("\nFailed to save event to database:", error);
15
+
}
32
16
};
33
17
34
18
const main = () => {
···
38
22
ws: WebSocket,
39
23
});
40
24
41
-
firehose.on("commit", (commit: CommitEvent) => {
42
-
saveEvent('commit', commit);
25
+
firehose.on("commit", async (commit: CommitEvent) => {
43
26
const createOps = commit.ops.filter(op => op.action === 'create');
27
+
const relevantOps = [];
44
28
45
29
for (const op of createOps) {
46
30
const recordType = op.record['$type'];
47
31
48
32
if (recordType && (recordType.startsWith('com.atproto.') || recordType.startsWith('systems.gmstn.'))) {
49
-
pretty_print(`COMMIT - ${recordType}`, {
50
-
repo: commit.repo,
51
-
path: op.path,
52
-
record: op.record
53
-
});
33
+
relevantOps.push(op);
54
34
}
55
35
}
36
+
37
+
if (relevantOps.length > 0) {
38
+
await saveEvent('commit', commit);
39
+
}
56
40
});
57
41
58
-
firehose.on("identity", (identity: IdentityEvent) => {
59
-
saveEvent('identity', identity);
60
-
pretty_print("IDENTITY", identity);
42
+
firehose.on("identity", async (identity: IdentityEvent) => {
43
+
await saveEvent('identity', identity);
61
44
});
62
45
63
-
firehose.on("account", (account: AccountEvent) => {
64
-
saveEvent('account', account);
65
-
pretty_print("ACCOUNT", account);
46
+
firehose.on("account", async (account: AccountEvent) => {
47
+
await saveEvent('account', account);
66
48
});
67
49
68
50
firehose.on("open", () => {
···
70
52
});
71
53
72
54
firehose.on("close", (cursor) => {
73
-
console.log(`\nConnection closed. Last cursor was: ${cursor}`);
55
+
console.log(`\nConnection closed. Last cursor was: ${cursor}. Restarting.`);
56
+
firehose.start();
74
57
});
75
58
76
59
firehose.on("error", ({ error, cursor }) => {
+10
src/index.ts
+10
src/index.ts
···
3
3
4
4
console.log('Main app starting...');
5
5
6
+
const pdsListSyncPath = path.resolve(__dirname, 'pds-list-sync.ts');
7
+
const pdsListSyncProcess = fork(pdsListSyncPath);
8
+
9
+
console.log(`pdsListSync process started with PID: ${pdsListSyncProcess.pid}`);
10
+
11
+
const pdsBackfillPath = path.resolve(__dirname, 'pds-backfill.ts');
12
+
const pdsBackfillProcess = fork(pdsBackfillPath);
13
+
14
+
console.log(`pdsBackfill process started with PID: ${pdsBackfillProcess.pid}`);
15
+
6
16
const firehosePath = path.resolve(__dirname, 'firehose.ts');
7
17
const firehoseProcess = fork(firehosePath);
8
18
+182
src/pds-backfill.ts
+182
src/pds-backfill.ts
···
1
+
import { db } from './db';
2
+
3
+
export interface FirehoseEventTable {
4
+
timestamp: ColumnType<Date, string | Date, never>;
5
+
event_type: string;
6
+
event_data: Record<string, any>;
7
+
}
8
+
export type FirehoseEvent = Selectable<FirehoseEventTable>;
9
+
export type NewFirehoseEvent = Insertable<FirehoseEventTable>;
10
+
11
+
interface AtpRecord {
12
+
$type: string;
13
+
createdAt: string;
14
+
[key: string]: any;
15
+
}
16
+
17
+
async function processSingleRepo(pdsHostname: string, did: string) {
18
+
const pdsBaseUrl = `https://` + pdsHostname;
19
+
const getRepoUrl = new URL(`/xrpc/com.atproto.sync.getRepo`, pdsBaseUrl);
20
+
getRepoUrl.searchParams.set('did', did);
21
+
22
+
let car: any;
23
+
try {
24
+
const { CarReader } = await import('@ipld/car');
25
+
26
+
const response = await fetch(getRepoUrl.href);
27
+
if (!response.ok) {
28
+
throw new Error(`Failed to getRepo for ${did}: ${response.status} ${response.statusText}`);
29
+
}
30
+
const carBytes = new Uint8Array(await response.arrayBuffer());
31
+
car = await CarReader.fromBytes(carBytes);
32
+
} catch (e: any) {
33
+
console.error(`[${did}] Failed to fetch or parse CAR: ${e.message}`);
34
+
return;
35
+
}
36
+
37
+
const recordsToInsert: NewFirehoseEvent[] = [];
38
+
39
+
try {
40
+
const cbor = await import('@ipld/dag-cbor');
41
+
42
+
for await (const block of car.blocks()) {
43
+
const record = cbor.decode(block.bytes) as AtpRecord;
44
+
45
+
if (
46
+
record &&
47
+
record.$type &&
48
+
typeof record.$type === 'string' &&
49
+
record.$type.startsWith('systems.gmstn.')
50
+
) {
51
+
if (!record.createdAt || typeof record.createdAt !== 'string') {
52
+
console.warn(`[${did}] Found matching record without valid 'createdAt', skipping.`);
53
+
continue;
54
+
}
55
+
56
+
recordsToInsert.push({
57
+
timestamp: record.createdAt,
58
+
event_type: record.$type,
59
+
event_data: record,
60
+
});
61
+
}
62
+
}
63
+
} catch (e: any) {
64
+
console.error(`[${did}] Error parsing CAR blocks: ${e.message}. Skipping rest of repo.`);
65
+
return;
66
+
}
67
+
68
+
if (recordsToInsert.length > 0) {
69
+
try {
70
+
await db.insertInto('firehose_event').values(recordsToInsert).execute();
71
+
console.log(`[${did}] Inserted ${recordsToInsert.length} 'systems.gmstn.*' records.`);
72
+
} catch (e: any) {
73
+
console.error(`[${did}] Failed to insert records into DB: ${e.message}`);
74
+
}
75
+
}
76
+
}
77
+
78
+
async function backfillPds(pdsHostname: string) {
79
+
console.log(`Starting backfill for: ${pdsHostname}`);
80
+
const pdsBaseUrl = `https://` + pdsHostname;
81
+
let cursor: string | undefined;
82
+
let totalReposProcessed = 0;
83
+
84
+
try {
85
+
do {
86
+
const listReposUrl = new URL('/xrpc/com.atproto.sync.listRepos', pdsBaseUrl);
87
+
if (cursor) {
88
+
listReposUrl.searchParams.set('cursor', cursor);
89
+
}
90
+
91
+
const response = await fetch(listReposUrl.href);
92
+
if (!response.ok) {
93
+
throw new Error(`Failed to listRepos: ${response.status} ${response.statusText}`);
94
+
}
95
+
96
+
const data = await response.json();
97
+
cursor = data.cursor;
98
+
const dids: string[] = data.repos.map((r: { did: string }) => r.did);
99
+
100
+
if (dids.length === 0) {
101
+
break;
102
+
}
103
+
104
+
console.log(`Fetched ${dids.length} repos. Cursor: ${cursor}`);
105
+
106
+
const BATCH_SIZE = 10;
107
+
for (let i = 0; i < dids.length; i += BATCH_SIZE) {
108
+
const batch = dids.slice(i, i + BATCH_SIZE);
109
+
const tasks = batch.map(did => processSingleRepo(pdsHostname, did));
110
+
await Promise.allSettled(tasks);
111
+
}
112
+
113
+
totalReposProcessed += dids.length;
114
+
115
+
} while (cursor);
116
+
117
+
console.log(`[${pdsHostname}] Finished paginating repos.`);
118
+
119
+
await db
120
+
.updateTable('pds')
121
+
.set({ backfilled_at: new Date() })
122
+
.where('hostname', '=', pdsHostname)
123
+
.execute();
124
+
125
+
console.log(`Successfully completed backfill for ${pdsHostname}. Total repos: ${totalReposProcessed}`);
126
+
127
+
} catch (error) {
128
+
console.error(`[${pdsHostname}] Fatal error during backfill:`, error);
129
+
throw error;
130
+
}
131
+
}
132
+
133
+
async function main() {
134
+
let pdsesToBackfill: { hostname: string }[] = [];
135
+
136
+
try {
137
+
pdsesToBackfill = await db
138
+
.selectFrom('pds')
139
+
.select('hostname')
140
+
.where('backfilled_at', 'is', null)
141
+
.orderBy(
142
+
(eb) => eb
143
+
.case()
144
+
.when('hostname', 'like', '%.bsky.network')
145
+
.then(1)
146
+
.else(0)
147
+
.end(),
148
+
'asc'
149
+
)
150
+
.orderBy('added_at', 'asc')
151
+
.execute();
152
+
153
+
if (pdsesToBackfill.length === 0) {
154
+
console.log('No PDSs to backfill. All caught up! Exiting.');
155
+
await db.destroy();
156
+
return;
157
+
}
158
+
159
+
console.log(`Found ${pdsesToBackfill.length} PDS(s) to backfill. Starting job...`);
160
+
161
+
} catch (e: any) {
162
+
console.error('Failed to fetch PDS list from database:', e.message);
163
+
process.exit(1);
164
+
}
165
+
166
+
for (const pds of pdsesToBackfill) {
167
+
try {
168
+
await backfillPds(pds.hostname);
169
+
} catch (e) {
170
+
console.error(`---`);
171
+
console.error(`Job for ${pds.hostname} failed. Moving to next PDS.`);
172
+
console.error(`---`);
173
+
}
174
+
}
175
+
176
+
console.log('All backfill jobs complete. Closing database connection.');
177
+
await db.destroy();
178
+
}
179
+
180
+
if (require.main === module) {
181
+
main();
182
+
}
+75
src/pds-list-sync.ts
+75
src/pds-list-sync.ts
···
1
+
import { db } from './db';
2
+
3
+
const PDS_LIST_URL = 'https://raw.githubusercontent.com/mary-ext/atproto-scraping/refs/heads/trunk/state.json';
4
+
5
+
interface StateJson {
6
+
pdses: {
7
+
[url: string]: {
8
+
inviteCodeRequired?: boolean;
9
+
version?: string;
10
+
}
11
+
}
12
+
}
13
+
14
+
async function syncPdsList() {
15
+
console.log('Starting PDS list sync...');
16
+
17
+
try {
18
+
const response = await fetch(PDS_LIST_URL);
19
+
if (!response.ok) {
20
+
throw new Error(`Failed to fetch PDS list: ${response.statusText}`);
21
+
}
22
+
23
+
const data = (await response.json()) as StateJson;
24
+
const pdsUrls = Object.keys(data?.pdses || {});
25
+
26
+
if (pdsUrls.length === 0) {
27
+
console.warn('No PDS hosts found in the upstream list.');
28
+
return;
29
+
}
30
+
31
+
const pdsToInsert = pdsUrls
32
+
.map(url => {
33
+
try {
34
+
return { hostname: new URL(url).hostname };
35
+
} catch (e) {
36
+
console.warn(`Invalid URL format in PDS list, skipping: ${url}`);
37
+
return null;
38
+
}
39
+
})
40
+
.filter(Boolean) as { hostname: string }[];
41
+
42
+
if (pdsToInsert.length === 0) {
43
+
console.log('No new valid PDS hosts to insert.');
44
+
return;
45
+
}
46
+
47
+
const result = await db
48
+
.insertInto('pds')
49
+
.values(pdsToInsert)
50
+
.onConflict((oc) => oc
51
+
.column('hostname')
52
+
.doNothing()
53
+
)
54
+
.execute();
55
+
56
+
console.log(`PDS list sync complete. Checked ${pdsToInsert.length} hosts.`);
57
+
58
+
} catch (error) {
59
+
console.error('Error during PDS list sync:', error);
60
+
process.exit(1);
61
+
}
62
+
}
63
+
64
+
if (require.main === module) {
65
+
syncPdsList()
66
+
.then(() => {
67
+
console.log('Sync finished successfully.');
68
+
db.destroy();
69
+
})
70
+
.catch((err) => {
71
+
console.error('Unhandled error in syncPdsList:', err);
72
+
db.destroy();
73
+
process.exit(1);
74
+
});
75
+
}