Initial backfill idea #2

merged
opened by lewis.moe targeting main

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 - # 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
··· 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
··· 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
··· 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
··· 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
··· 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
··· 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
··· 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
··· 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 + }