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
···
-
# what to filter by. currently only supports one string.
-
FILTER_BY=
-
-
# cache location. sqlite db url. technically supports an external cache if you want.
-
# https://bsky.app/profile/piss.beauty/post/3lkc3efbipc23
-
# https://bsky.app/profile/nekomimi.pet/post/3m3losk3rys2n
-
# usually either :memory: or file:path/to/file.db. defaults to ":memory:"
-
CACHE_LOCATION=":memory:"
+
DATABASE_URL=postgres://prism:prism@localhost:5432/prism
+4 -6
README.md
···
# Prism
-
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.
+
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.
<a href="https://docs.bsky.app/docs/advanced-guides/federation-architecture#app-views">
<img src="https://docs.bsky.app/assets/images/app-view-prism-e90e1bf6093bafcb6df2e5c592be1bc6.png" width="400" alt="appview-prism-pinkfloyd"/>
</a>
-
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.
+
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.
-
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.
+
Prism implements endpoints for accessing the cache feed, which are `xrpc` compatible and the lexicons can be found in `lexicons/`.
-
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/`
-
-
Backfill coming soon (if you're crazy ig).
+
Backfill batteries included. :3
+16
migrations/20251104191300_create_pds_table.ts
···
+
import { Kysely, sql } from 'kysely';
+
+
export async function up(db: Kysely<any>): Promise<void> {
+
await db.schema
+
.createTable('pds')
+
.addColumn('hostname', 'text', (col) => col.primaryKey())
+
.addColumn('added_at', 'timestamp', (col) =>
+
col.defaultTo(sql`now()`).notNull()
+
)
+
.addColumn('backfilled_at', 'timestamp')
+
.execute();
+
}
+
+
export async function down(db: Kysely<any>): Promise<void> {
+
await db.schema.dropTable('pds').execute();
+
}
+5
package.json
···
"packageManager": "pnpm@10.20.0",
"dependencies": {
"@atproto/xrpc-server": "^0.9.5",
+
"@ipld/car": "^5.4.2",
+
"@ipld/dag-cbor": "^9.2.5",
"@skyware/firehose": "^0.5.2",
+
"biome": "^0.3.3",
"dotenv": "^17.2.3",
"kysely": "^0.28.8",
"pg": "^8.16.3",
···
"devDependencies": {
"@atcute/atproto": "^3.1.8",
"@types/node": "^24.9.2",
+
"@types/pg": "^8.15.6",
"@types/ws": "^8.18.1",
"ts-node": "^10.9.2",
+
"tsconfig-paths": "^4.2.0",
"tsx": "^4.20.6",
"typescript": "^5.9.3"
}
+846
pnpm-lock.yaml
···
'@atproto/xrpc-server':
specifier: ^0.9.5
version: 0.9.5
+
'@ipld/car':
+
specifier: ^5.4.2
+
version: 5.4.2
+
'@ipld/dag-cbor':
+
specifier: ^9.2.5
+
version: 9.2.5
'@skyware/firehose':
specifier: ^0.5.2
version: 0.5.2
+
biome:
+
specifier: ^0.3.3
+
version: 0.3.3
dotenv:
specifier: ^17.2.3
version: 17.2.3
···
'@types/node':
specifier: ^24.9.2
version: 24.9.2
+
'@types/pg':
+
specifier: ^8.15.6
+
version: 8.15.6
'@types/ws':
specifier: ^8.18.1
version: 8.18.1
ts-node:
specifier: ^10.9.2
version: 10.9.2(@types/node@24.9.2)(typescript@5.9.3)
+
tsconfig-paths:
+
specifier: ^4.2.0
+
version: 4.2.0
tsx:
specifier: ^4.20.6
version: 4.20.6
···
cpu: [x64]
os: [win32]
+
'@ipld/car@5.4.2':
+
resolution: {integrity: sha512-gfyrJvePyXnh2Fbj8mPg4JYvEZ3izhk8C9WgAle7xIYbrJNSXmNQ6BxAls8Gof97vvGbCROdxbTWRmHJtTCbcg==}
+
engines: {node: '>=16.0.0', npm: '>=7.0.0'}
+
'@ipld/dag-cbor@7.0.3':
resolution: {integrity: sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA==}
+
'@ipld/dag-cbor@9.2.5':
+
resolution: {integrity: sha512-84wSr4jv30biui7endhobYhXBQzQE4c/wdoWlFrKcfiwH+ofaPg8fwsM8okX9cOzkkrsAsNdDyH3ou+kiLquwQ==}
+
engines: {node: '>=16.0.0', npm: '>=7.0.0'}
+
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
···
'@types/node@24.9.2':
resolution: {integrity: sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==}
+
'@types/pg@8.15.6':
+
resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==}
+
'@types/ws@8.18.1':
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
···
engines: {node: '>=0.4.0'}
hasBin: true
+
ajv@6.12.6:
+
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+
+
ansi-escapes@1.4.0:
+
resolution: {integrity: sha512-wiXutNjDUlNEDWHcYH3jtZUhd3c4/VojassD8zHdHCY13xbZy2XbW+NKQwA0tWGBVzDA9qEzYwfoSsWmviidhw==}
+
engines: {node: '>=0.10.0'}
+
+
ansi-regex@2.1.1:
+
resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==}
+
engines: {node: '>=0.10.0'}
+
+
ansi-styles@2.2.1:
+
resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==}
+
engines: {node: '>=0.10.0'}
+
+
any-promise@1.3.0:
+
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
arg@4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
array-flatten@1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
+
asn1@0.2.6:
+
resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
+
+
assert-plus@1.0.0:
+
resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
+
engines: {node: '>=0.8'}
+
+
asynckit@0.4.0:
+
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
atomic-sleep@1.0.0:
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
engines: {node: '>=8.0.0'}
+
aws-sign2@0.7.0:
+
resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==}
+
+
aws4@1.13.2:
+
resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==}
+
+
balanced-match@1.0.2:
+
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
bcrypt-pbkdf@1.0.2:
+
resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
+
+
biome@0.3.3:
+
resolution: {integrity: sha512-4LXjrQYbn9iTXu9Y4SKT7ABzTV0WnLDHCVSd2fPUOKsy1gQ+E4xPFmlY1zcWexoi0j7fGHItlL6OWA2CZ/yYAQ==}
+
hasBin: true
+
+
bluebird@3.7.2:
+
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
+
body-parser@1.20.3:
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
+
brace-expansion@1.1.12:
+
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
+
buffer@6.0.3:
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
···
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
engines: {node: '>= 0.4'}
+
caseless@0.12.0:
+
resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
+
cbor-extract@2.2.0:
resolution: {integrity: sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==}
hasBin: true
···
resolution: {integrity: sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==}
hasBin: true
+
cborg@4.2.18:
+
resolution: {integrity: sha512-uzhkd5HOaLccokqeZa5B0Qz7/aa9C12pmUq5yU3vcy6I6OhTKdPHSzOuBPZfcoQHdcx8Emz/dWZbPNNfF/puvg==}
+
hasBin: true
+
+
chalk@1.1.3:
+
resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==}
+
engines: {node: '>=0.10.0'}
+
+
cli-cursor@1.0.2:
+
resolution: {integrity: sha512-25tABq090YNKkF6JH7lcwO0zFJTRke4Jcq9iX2nr/Sz0Cjjv4gckmwlW6Ty/aoyFd6z3ysR2hMGC2GFugmBo6A==}
+
engines: {node: '>=0.10.0'}
+
+
cli-width@1.1.1:
+
resolution: {integrity: sha512-eMU2akIeEIkCxGXUNmDnJq1KzOIiPnJ+rKqRe6hcxE3vIOPvpMrBYOn/Bl7zNlYJj/zQxXquAnozHUCf9Whnsg==}
+
+
code-point-at@1.1.0:
+
resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==}
+
engines: {node: '>=0.10.0'}
+
+
combined-stream@1.0.8:
+
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+
engines: {node: '>= 0.8'}
+
+
commander@2.20.3:
+
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+
+
concat-map@0.0.1:
+
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
content-disposition@0.5.4:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'}
···
resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==}
engines: {node: '>= 0.6'}
+
core-js@2.6.12:
+
resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==}
+
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.
+
+
core-util-is@1.0.2:
+
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
+
create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
+
dashdash@1.14.1:
+
resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
+
engines: {node: '>=0.10'}
+
debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
···
supports-color:
optional: true
+
delayed-stream@1.0.0:
+
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+
engines: {node: '>=0.4.0'}
+
depd@2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
···
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
+
earlgrey-runtime@0.1.2:
+
resolution: {integrity: sha512-T4qoScXi5TwALDv8nlGTvOuCT8jXcKcxtO8qVdqv46IA2GHJfQzwoBPbkOmORnyhu3A98cVVuhWLsM2CzPljJg==}
+
+
ecc-jsbn@0.1.2:
+
resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
+
+
editor@1.0.0:
+
resolution: {integrity: sha512-SoRmbGStwNYHgKfjOrX2L0mUvp9bUVv0uPppZSOMAntEbcFtoC3MKF5b3T6HQPXKIV+QGY3xPO3JK5it5lVkuw==}
+
ee-first@1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
···
escape-html@1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+
escape-string-regexp@1.0.5:
+
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+
engines: {node: '>=0.8.0'}
+
esm-env@1.2.2:
resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==}
···
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
engines: {node: '>=0.8.x'}
+
exit-hook@1.1.1:
+
resolution: {integrity: sha512-MsG3prOVw1WtLXAZbM3KiYtooKR1LvxHh3VHsVtIy0uiUu8usxgB/94DP2HxtD/661lLdB6yzQ09lGJSQr6nkg==}
+
engines: {node: '>=0.10.0'}
+
express@4.21.2:
resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==}
engines: {node: '>= 0.10.0'}
+
extend@3.0.2:
+
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+
+
extsprintf@1.3.0:
+
resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==}
+
engines: {'0': node >=0.6.0}
+
+
fast-deep-equal@3.1.3:
+
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+
fast-json-stable-stringify@2.1.0:
+
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+
fast-redact@3.5.0:
resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==}
engines: {node: '>=6'}
+
figures@1.7.0:
+
resolution: {integrity: sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==}
+
engines: {node: '>=0.10.0'}
+
finalhandler@1.3.1:
resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==}
engines: {node: '>= 0.8'}
+
forever-agent@0.6.1:
+
resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
+
+
form-data@2.3.3:
+
resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==}
+
engines: {node: '>= 0.12'}
+
forwarded@0.2.0:
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
engines: {node: '>= 0.6'}
···
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
engines: {node: '>= 0.6'}
+
fs-extra@0.26.7:
+
resolution: {integrity: sha512-waKu+1KumRhYv8D8gMRCKJGAMI9pRnPuEb1mvgYD0f7wBscg+h6bW4FDTmEZhB9VKxvoTtxW+Y7bnIlB7zja6Q==}
+
+
fs-promise@0.5.0:
+
resolution: {integrity: sha512-Y+4F4ujhEcayCJt6JmzcOun9MYGQwz+bVUiuBmTkJImhBHKpBvmVPZR9wtfiF7k3ffwAOAuurygQe+cPLSFQhw==}
+
deprecated: Use mz or fs-extra^3.0 with Promise Support
+
+
fs.realpath@1.0.0:
+
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
···
get-tsconfig@4.13.0:
resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==}
+
getpass@0.1.7:
+
resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==}
+
+
glob@7.2.3:
+
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+
deprecated: Glob versions prior to v9 are no longer supported
+
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
+
graceful-fs@4.2.11:
+
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+
har-schema@2.0.0:
+
resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==}
+
engines: {node: '>=4'}
+
+
har-validator@5.1.5:
+
resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==}
+
engines: {node: '>=6'}
+
deprecated: this library is no longer supported
+
+
has-ansi@2.0.0:
+
resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==}
+
engines: {node: '>=0.10.0'}
+
has-symbols@1.1.0:
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
engines: {node: '>= 0.4'}
···
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
engines: {node: '>= 0.8'}
+
http-signature@1.2.0:
+
resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==}
+
engines: {node: '>=0.8', npm: '>=1.3.7'}
+
iconv-lite@0.4.24:
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
engines: {node: '>=0.10.0'}
···
ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+
inflight@1.0.6:
+
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+
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.
+
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
inquirer-promise@0.0.3:
+
resolution: {integrity: sha512-82CQX586JAV9GAgU9yXZsMDs+NorjA0nLhkfFx9+PReyOnuoHRbHrC1Z90sS95bFJI1Tm1gzMObuE0HabzkJpg==}
+
+
inquirer@0.11.4:
+
resolution: {integrity: sha512-QR+2TW90jnKk9LUUtbcA3yQXKt2rDEKMh6+BAZQIeumtzHexnwVLdPakSslGijXYLJCzFv7GMXbFCn0pA00EUw==}
+
ipaddr.js@1.9.1:
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
engines: {node: '>= 0.10'}
+
is-fullwidth-code-point@1.0.0:
+
resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==}
+
engines: {node: '>=0.10.0'}
+
+
is-typedarray@1.0.0:
+
resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==}
+
iso-datestring-validator@2.2.2:
resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==}
+
isstream@0.1.2:
+
resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==}
+
+
jsbn@0.1.1:
+
resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==}
+
+
json-schema-traverse@0.4.1:
+
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+
+
json-schema@0.4.0:
+
resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
+
+
json-stringify-safe@5.0.1:
+
resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
+
+
json5@2.2.3:
+
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+
engines: {node: '>=6'}
+
hasBin: true
+
+
jsonfile@2.4.0:
+
resolution: {integrity: sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==}
+
+
jsprim@1.4.2:
+
resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==}
+
engines: {node: '>=0.6.0'}
+
+
kaiser@0.0.4:
+
resolution: {integrity: sha512-m8ju+rmBqvclZmyrOXgGGhOYSjKJK6RN1NhqEltemY87UqZOxEkizg9TOy1vQSyJ01Wx6SAPuuN0iO2Mgislvw==}
+
+
klaw@1.3.1:
+
resolution: {integrity: sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==}
+
kysely@0.28.8:
resolution: {integrity: sha512-QUOgl5ZrS9IRuhq5FvOKFSsD/3+IA6MLE81/bOOTRA/YQpKDza2sFdN5g6JCB9BOpqMJDGefLCQ9F12hRS13TA==}
engines: {node: '>=20.0.0'}
+
lodash@3.10.1:
+
resolution: {integrity: sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==}
+
+
lodash@4.17.21:
+
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+
make-error@1.3.6:
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
···
engines: {node: '>=4'}
hasBin: true
+
minimatch@3.1.2:
+
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+
+
minimist@1.2.8:
+
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
ms@2.0.0:
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
multiformats@13.4.1:
+
resolution: {integrity: sha512-VqO6OSvLrFVAYYjgsr8tyv62/rCQhPgsZUXLTqoFLSgdkgiUYKYeArbt1uWLlEpkjxQe+P0+sHlbPEte1Bi06Q==}
+
multiformats@9.9.0:
resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==}
+
mute-stream@0.0.5:
+
resolution: {integrity: sha512-EbrziT4s8cWPmzr47eYVW3wimS4HsvlnV5ri1xw1aR6JQo/OrJX5rkl32K/QQHdxeabJETtfeaROGhd8W7uBgg==}
+
+
mz@2.7.0:
+
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+
nanoevents@9.1.0:
resolution: {integrity: sha512-Jd0fILWG44a9luj8v5kED4WI+zfkkgwKyRQKItTtlPfEsh7Lznfi1kr8/iZ+XAIss4Qq5GqRB0qtWbaz9ceO/A==}
engines: {node: ^18.0.0 || >=20.0.0}
···
resolution: {integrity: sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==}
hasBin: true
+
number-is-nan@1.0.1:
+
resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==}
+
engines: {node: '>=0.10.0'}
+
+
oauth-sign@0.9.0:
+
resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==}
+
+
object-assign@4.1.1:
+
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+
engines: {node: '>=0.10.0'}
+
object-inspect@1.13.4:
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
engines: {node: '>= 0.4'}
···
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
engines: {node: '>= 0.8'}
+
once@1.4.0:
+
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+
onetime@1.1.0:
+
resolution: {integrity: sha512-GZ+g4jayMqzCRMgB2sol7GiCLjKfS1PINkjmx8spcKce1LiVqcbQreXwqs2YAFXC6R03VIG28ZS31t8M866v6A==}
+
engines: {node: '>=0.10.0'}
+
+
os-homedir@1.0.2:
+
resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==}
+
engines: {node: '>=0.10.0'}
+
parseurl@1.3.3:
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
engines: {node: '>= 0.8'}
+
path-is-absolute@1.0.1:
+
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+
engines: {node: '>=0.10.0'}
+
path-to-regexp@0.1.12:
resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==}
+
performance-now@2.1.0:
+
resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
+
pg-cloudflare@1.2.7:
resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==}
···
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
+
psl@1.15.0:
+
resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
+
+
punycode@2.3.1:
+
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+
engines: {node: '>=6'}
+
qs@6.13.0:
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
engines: {node: '>=0.6'}
+
qs@6.5.3:
+
resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==}
+
engines: {node: '>=0.6'}
+
quick-format-unescaped@4.0.4:
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
···
resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
readline2@1.0.1:
+
resolution: {integrity: sha512-8/td4MmwUB6PkZUbV25uKz7dfrmjYWxsW8DVfibWdlHRk/l/DfHKn4pU+dfcoGLFgWOdyGCzINRQD7jn+Bv+/g==}
+
real-require@0.2.0:
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
engines: {node: '>= 12.13.0'}
+
regenerator-runtime@0.9.6:
+
resolution: {integrity: sha512-D0Y/JJ4VhusyMOd/o25a3jdUqN/bC85EFsaoL9Oqmy/O4efCh+xhp7yj2EEOsj974qvMkcW8AwUzJ1jB/MbxCw==}
+
+
request-promise@3.0.0:
+
resolution: {integrity: sha512-wVGUX+BoKxYsavTA72i6qHcyLbjzM4LR4y/AmDCqlbuMAursZdDWO7PmgbGAUvD2SeEJ5iB99VSq/U51i/DNbw==}
+
engines: {node: '>=0.10.0'}
+
deprecated: request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142
+
+
request@2.88.2:
+
resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==}
+
engines: {node: '>= 6'}
+
deprecated: request has been deprecated, see https://github.com/request/request/issues/3142
+
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+
restore-cursor@1.0.1:
+
resolution: {integrity: sha512-reSjH4HuiFlxlaBaFCiS6O76ZGG2ygKoSlCsipKdaZuKSPx/+bt9mULkn4l0asVzbEfQQmXRg6Wp6gv6m0wElw==}
+
engines: {node: '>=0.10.0'}
+
+
rimraf@2.7.1:
+
resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==}
+
deprecated: Rimraf versions prior to v4 are no longer supported
+
hasBin: true
+
+
run-async@0.1.0:
+
resolution: {integrity: sha512-qOX+w+IxFgpUpJfkv2oGN0+ExPs68F4sZHfaRRx4dDexAQkG83atugKVEylyT5ARees3HBbfmuvnjbrd8j9Wjw==}
+
+
rx-lite@3.1.2:
+
resolution: {integrity: sha512-1I1+G2gteLB8Tkt8YI1sJvSIfa0lWuRtC8GjvtyPBcLSF5jBCCJJqKrpER5JU5r6Bhe+i9/pK3VMuUcXu0kdwQ==}
+
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
···
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
engines: {node: '>= 10.x'}
+
sshpk@1.18.0:
+
resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==}
+
engines: {node: '>=0.10.0'}
+
hasBin: true
+
statuses@2.0.1:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}
+
string-width@1.0.2:
+
resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==}
+
engines: {node: '>=0.10.0'}
+
string_decoder@1.3.0:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+
strip-ansi@3.0.1:
+
resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==}
+
engines: {node: '>=0.10.0'}
+
+
strip-bom@3.0.0:
+
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+
engines: {node: '>=4'}
+
+
supports-color@2.0.0:
+
resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==}
+
engines: {node: '>=0.8.0'}
+
+
thenify-all@1.6.0:
+
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+
engines: {node: '>=0.8'}
+
+
thenify@3.3.1:
+
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+
thread-stream@2.7.0:
resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==}
+
through@2.3.8:
+
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
+
toidentifier@1.0.1:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
+
tough-cookie@2.5.0:
+
resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==}
+
engines: {node: '>=0.8'}
+
ts-node@10.9.2:
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
hasBin: true
···
'@swc/wasm':
optional: true
+
tsconfig-paths@4.2.0:
+
resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==}
+
engines: {node: '>=6'}
+
tsx@4.20.6:
resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==}
engines: {node: '>=18.0.0'}
hasBin: true
+
tunnel-agent@0.6.0:
+
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
+
+
tweetnacl@0.14.5:
+
resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
+
type-is@1.6.18:
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
engines: {node: '>= 0.6'}
···
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'}
+
untildify@3.0.3:
+
resolution: {integrity: sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==}
+
engines: {node: '>=4'}
+
+
uri-js@4.4.1:
+
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+
+
user-home@2.0.0:
+
resolution: {integrity: sha512-KMWqdlOcjCYdtIJpicDSFBQ8nFwS2i9sslAd6f4+CBGcU4gist2REnr2fxj2YocvJFxSF3ZOHLYLVZnUxv4BZQ==}
+
engines: {node: '>=0.10.0'}
+
utils-merge@1.0.1:
resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==}
engines: {node: '>= 0.4.0'}
+
uuid@3.4.0:
+
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
+
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.
+
hasBin: true
+
v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
+
varint@6.0.0:
+
resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==}
+
vary@1.1.2:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
+
verror@1.10.0:
+
resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==}
+
engines: {'0': node >=0.6.0}
+
+
wrappy@1.0.2:
+
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
ws@8.18.3:
resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
engines: {node: '>=10.0.0'}
···
'@esbuild/win32-x64@0.25.11':
optional: true
+
'@ipld/car@5.4.2':
+
dependencies:
+
'@ipld/dag-cbor': 9.2.5
+
cborg: 4.2.18
+
multiformats: 13.4.1
+
varint: 6.0.0
+
'@ipld/dag-cbor@7.0.3':
dependencies:
cborg: 1.10.2
multiformats: 9.9.0
+
'@ipld/dag-cbor@9.2.5':
+
dependencies:
+
cborg: 4.2.18
+
multiformats: 13.4.1
+
'@jridgewell/resolve-uri@3.1.2': {}
'@jridgewell/sourcemap-codec@1.5.5': {}
···
dependencies:
undici-types: 7.16.0
+
'@types/pg@8.15.6':
+
dependencies:
+
'@types/node': 24.9.2
+
pg-protocol: 1.10.3
+
pg-types: 2.2.0
+
'@types/ws@8.18.1':
dependencies:
'@types/node': 24.9.2
···
acorn@8.15.0: {}
+
ajv@6.12.6:
+
dependencies:
+
fast-deep-equal: 3.1.3
+
fast-json-stable-stringify: 2.1.0
+
json-schema-traverse: 0.4.1
+
uri-js: 4.4.1
+
+
ansi-escapes@1.4.0: {}
+
+
ansi-regex@2.1.1: {}
+
+
ansi-styles@2.2.1: {}
+
+
any-promise@1.3.0: {}
+
arg@4.1.3: {}
array-flatten@1.1.1: {}
+
asn1@0.2.6:
+
dependencies:
+
safer-buffer: 2.1.2
+
+
assert-plus@1.0.0: {}
+
+
asynckit@0.4.0: {}
+
atomic-sleep@1.0.0: {}
+
aws-sign2@0.7.0: {}
+
+
aws4@1.13.2: {}
+
+
balanced-match@1.0.2: {}
+
base64-js@1.5.1: {}
+
bcrypt-pbkdf@1.0.2:
+
dependencies:
+
tweetnacl: 0.14.5
+
+
biome@0.3.3:
+
dependencies:
+
bluebird: 3.7.2
+
chalk: 1.1.3
+
commander: 2.20.3
+
editor: 1.0.0
+
fs-promise: 0.5.0
+
inquirer-promise: 0.0.3
+
request-promise: 3.0.0
+
untildify: 3.0.3
+
user-home: 2.0.0
+
+
bluebird@3.7.2: {}
+
body-parser@1.20.3:
dependencies:
bytes: 3.1.2
···
transitivePeerDependencies:
- supports-color
+
brace-expansion@1.1.12:
+
dependencies:
+
balanced-match: 1.0.2
+
concat-map: 0.0.1
+
buffer@6.0.3:
dependencies:
base64-js: 1.5.1
···
call-bind-apply-helpers: 1.0.2
get-intrinsic: 1.3.0
+
caseless@0.12.0: {}
+
cbor-extract@2.2.0:
dependencies:
node-gyp-build-optional-packages: 5.1.1
···
cborg@1.10.2: {}
+
cborg@4.2.18: {}
+
+
chalk@1.1.3:
+
dependencies:
+
ansi-styles: 2.2.1
+
escape-string-regexp: 1.0.5
+
has-ansi: 2.0.0
+
strip-ansi: 3.0.1
+
supports-color: 2.0.0
+
+
cli-cursor@1.0.2:
+
dependencies:
+
restore-cursor: 1.0.1
+
+
cli-width@1.1.1: {}
+
+
code-point-at@1.1.0: {}
+
+
combined-stream@1.0.8:
+
dependencies:
+
delayed-stream: 1.0.0
+
+
commander@2.20.3: {}
+
+
concat-map@0.0.1: {}
+
content-disposition@0.5.4:
dependencies:
safe-buffer: 5.2.1
···
cookie@0.7.1: {}
+
core-js@2.6.12: {}
+
+
core-util-is@1.0.2: {}
+
create-require@1.1.1: {}
+
dashdash@1.14.1:
+
dependencies:
+
assert-plus: 1.0.0
+
debug@2.6.9:
dependencies:
ms: 2.0.0
+
delayed-stream@1.0.0: {}
+
depd@2.0.0: {}
destroy@1.2.0: {}
···
es-errors: 1.3.0
gopd: 1.2.0
+
earlgrey-runtime@0.1.2:
+
dependencies:
+
core-js: 2.6.12
+
kaiser: 0.0.4
+
lodash: 4.17.21
+
regenerator-runtime: 0.9.6
+
+
ecc-jsbn@0.1.2:
+
dependencies:
+
jsbn: 0.1.1
+
safer-buffer: 2.1.2
+
+
editor@1.0.0: {}
+
ee-first@1.1.1: {}
encodeurl@1.0.2: {}
···
escape-html@1.0.3: {}
+
escape-string-regexp@1.0.5: {}
+
esm-env@1.2.2: {}
etag@1.8.1: {}
···
events@3.3.0: {}
+
exit-hook@1.1.1: {}
+
express@4.21.2:
dependencies:
accepts: 1.3.8
···
transitivePeerDependencies:
- supports-color
+
extend@3.0.2: {}
+
+
extsprintf@1.3.0: {}
+
+
fast-deep-equal@3.1.3: {}
+
+
fast-json-stable-stringify@2.1.0: {}
+
fast-redact@3.5.0: {}
+
figures@1.7.0:
+
dependencies:
+
escape-string-regexp: 1.0.5
+
object-assign: 4.1.1
+
finalhandler@1.3.1:
dependencies:
debug: 2.6.9
···
transitivePeerDependencies:
- supports-color
+
forever-agent@0.6.1: {}
+
+
form-data@2.3.3:
+
dependencies:
+
asynckit: 0.4.0
+
combined-stream: 1.0.8
+
mime-types: 2.1.35
+
forwarded@0.2.0: {}
fresh@0.5.2: {}
+
fs-extra@0.26.7:
+
dependencies:
+
graceful-fs: 4.2.11
+
jsonfile: 2.4.0
+
klaw: 1.3.1
+
path-is-absolute: 1.0.1
+
rimraf: 2.7.1
+
+
fs-promise@0.5.0:
+
dependencies:
+
any-promise: 1.3.0
+
fs-extra: 0.26.7
+
mz: 2.7.0
+
thenify-all: 1.6.0
+
+
fs.realpath@1.0.0: {}
+
fsevents@2.3.3:
optional: true
···
dependencies:
resolve-pkg-maps: 1.0.0
+
getpass@0.1.7:
+
dependencies:
+
assert-plus: 1.0.0
+
+
glob@7.2.3:
+
dependencies:
+
fs.realpath: 1.0.0
+
inflight: 1.0.6
+
inherits: 2.0.4
+
minimatch: 3.1.2
+
once: 1.4.0
+
path-is-absolute: 1.0.1
+
gopd@1.2.0: {}
+
graceful-fs@4.2.11: {}
+
graphemer@1.4.0: {}
+
har-schema@2.0.0: {}
+
+
har-validator@5.1.5:
+
dependencies:
+
ajv: 6.12.6
+
har-schema: 2.0.0
+
+
has-ansi@2.0.0:
+
dependencies:
+
ansi-regex: 2.1.1
+
has-symbols@1.1.0: {}
hasown@2.0.2:
···
statuses: 2.0.1
toidentifier: 1.0.1
+
http-signature@1.2.0:
+
dependencies:
+
assert-plus: 1.0.0
+
jsprim: 1.4.2
+
sshpk: 1.18.0
+
iconv-lite@0.4.24:
dependencies:
safer-buffer: 2.1.2
ieee754@1.2.1: {}
+
inflight@1.0.6:
+
dependencies:
+
once: 1.4.0
+
wrappy: 1.0.2
+
inherits@2.0.4: {}
+
inquirer-promise@0.0.3:
+
dependencies:
+
earlgrey-runtime: 0.1.2
+
inquirer: 0.11.4
+
+
inquirer@0.11.4:
+
dependencies:
+
ansi-escapes: 1.4.0
+
ansi-regex: 2.1.1
+
chalk: 1.1.3
+
cli-cursor: 1.0.2
+
cli-width: 1.1.1
+
figures: 1.7.0
+
lodash: 3.10.1
+
readline2: 1.0.1
+
run-async: 0.1.0
+
rx-lite: 3.1.2
+
string-width: 1.0.2
+
strip-ansi: 3.0.1
+
through: 2.3.8
+
ipaddr.js@1.9.1: {}
+
is-fullwidth-code-point@1.0.0:
+
dependencies:
+
number-is-nan: 1.0.1
+
+
is-typedarray@1.0.0: {}
+
iso-datestring-validator@2.2.2: {}
+
isstream@0.1.2: {}
+
+
jsbn@0.1.1: {}
+
+
json-schema-traverse@0.4.1: {}
+
+
json-schema@0.4.0: {}
+
+
json-stringify-safe@5.0.1: {}
+
+
json5@2.2.3: {}
+
+
jsonfile@2.4.0:
+
optionalDependencies:
+
graceful-fs: 4.2.11
+
+
jsprim@1.4.2:
+
dependencies:
+
assert-plus: 1.0.0
+
extsprintf: 1.3.0
+
json-schema: 0.4.0
+
verror: 1.10.0
+
+
kaiser@0.0.4:
+
dependencies:
+
earlgrey-runtime: 0.1.2
+
+
klaw@1.3.1:
+
optionalDependencies:
+
graceful-fs: 4.2.11
+
kysely@0.28.8: {}
+
lodash@3.10.1: {}
+
+
lodash@4.17.21: {}
+
make-error@1.3.6: {}
math-intrinsics@1.1.0: {}
···
mime@1.6.0: {}
+
minimatch@3.1.2:
+
dependencies:
+
brace-expansion: 1.1.12
+
+
minimist@1.2.8: {}
+
ms@2.0.0: {}
ms@2.1.3: {}
+
multiformats@13.4.1: {}
+
multiformats@9.9.0: {}
+
mute-stream@0.0.5: {}
+
+
mz@2.7.0:
+
dependencies:
+
any-promise: 1.3.0
+
object-assign: 4.1.1
+
thenify-all: 1.6.0
+
nanoevents@9.1.0: {}
negotiator@0.6.3: {}
···
detect-libc: 2.1.2
optional: true
+
number-is-nan@1.0.1: {}
+
+
oauth-sign@0.9.0: {}
+
+
object-assign@4.1.1: {}
+
object-inspect@1.13.4: {}
on-exit-leak-free@2.1.2: {}
···
dependencies:
ee-first: 1.1.1
+
once@1.4.0:
+
dependencies:
+
wrappy: 1.0.2
+
+
onetime@1.1.0: {}
+
+
os-homedir@1.0.2: {}
+
parseurl@1.3.3: {}
+
path-is-absolute@1.0.1: {}
+
path-to-regexp@0.1.12: {}
+
performance-now@2.1.0: {}
+
pg-cloudflare@1.2.7:
optional: true
···
forwarded: 0.2.0
ipaddr.js: 1.9.1
+
psl@1.15.0:
+
dependencies:
+
punycode: 2.3.1
+
+
punycode@2.3.1: {}
+
qs@6.13.0:
dependencies:
side-channel: 1.1.0
+
qs@6.5.3: {}
+
quick-format-unescaped@4.0.4: {}
range-parser@1.2.1: {}
···
process: 0.11.10
string_decoder: 1.3.0
+
readline2@1.0.1:
+
dependencies:
+
code-point-at: 1.1.0
+
is-fullwidth-code-point: 1.0.0
+
mute-stream: 0.0.5
+
real-require@0.2.0: {}
+
regenerator-runtime@0.9.6: {}
+
+
request-promise@3.0.0:
+
dependencies:
+
bluebird: 3.7.2
+
lodash: 4.17.21
+
request: 2.88.2
+
+
request@2.88.2:
+
dependencies:
+
aws-sign2: 0.7.0
+
aws4: 1.13.2
+
caseless: 0.12.0
+
combined-stream: 1.0.8
+
extend: 3.0.2
+
forever-agent: 0.6.1
+
form-data: 2.3.3
+
har-validator: 5.1.5
+
http-signature: 1.2.0
+
is-typedarray: 1.0.0
+
isstream: 0.1.2
+
json-stringify-safe: 5.0.1
+
mime-types: 2.1.35
+
oauth-sign: 0.9.0
+
performance-now: 2.1.0
+
qs: 6.5.3
+
safe-buffer: 5.2.1
+
tough-cookie: 2.5.0
+
tunnel-agent: 0.6.0
+
uuid: 3.4.0
+
resolve-pkg-maps@1.0.0: {}
+
restore-cursor@1.0.1:
+
dependencies:
+
exit-hook: 1.1.1
+
onetime: 1.1.0
+
+
rimraf@2.7.1:
+
dependencies:
+
glob: 7.2.3
+
+
run-async@0.1.0:
+
dependencies:
+
once: 1.4.0
+
+
rx-lite@3.1.2: {}
+
safe-buffer@5.2.1: {}
safe-stable-stringify@2.5.0: {}
···
split2@4.2.0: {}
+
sshpk@1.18.0:
+
dependencies:
+
asn1: 0.2.6
+
assert-plus: 1.0.0
+
bcrypt-pbkdf: 1.0.2
+
dashdash: 1.14.1
+
ecc-jsbn: 0.1.2
+
getpass: 0.1.7
+
jsbn: 0.1.1
+
safer-buffer: 2.1.2
+
tweetnacl: 0.14.5
+
statuses@2.0.1: {}
+
string-width@1.0.2:
+
dependencies:
+
code-point-at: 1.1.0
+
is-fullwidth-code-point: 1.0.0
+
strip-ansi: 3.0.1
+
string_decoder@1.3.0:
dependencies:
safe-buffer: 5.2.1
+
strip-ansi@3.0.1:
+
dependencies:
+
ansi-regex: 2.1.1
+
+
strip-bom@3.0.0: {}
+
+
supports-color@2.0.0: {}
+
+
thenify-all@1.6.0:
+
dependencies:
+
thenify: 3.3.1
+
+
thenify@3.3.1:
+
dependencies:
+
any-promise: 1.3.0
+
thread-stream@2.7.0:
dependencies:
real-require: 0.2.0
+
through@2.3.8: {}
+
toidentifier@1.0.1: {}
+
tough-cookie@2.5.0:
+
dependencies:
+
psl: 1.15.0
+
punycode: 2.3.1
+
ts-node@10.9.2(@types/node@24.9.2)(typescript@5.9.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
···
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
+
tsconfig-paths@4.2.0:
+
dependencies:
+
json5: 2.2.3
+
minimist: 1.2.8
+
strip-bom: 3.0.0
+
tsx@4.20.6:
dependencies:
esbuild: 0.25.11
···
optionalDependencies:
fsevents: 2.3.3
+
tunnel-agent@0.6.0:
+
dependencies:
+
safe-buffer: 5.2.1
+
+
tweetnacl@0.14.5: {}
+
type-is@1.6.18:
dependencies:
media-typer: 0.3.0
···
unpipe@1.0.0: {}
+
untildify@3.0.3: {}
+
+
uri-js@4.4.1:
+
dependencies:
+
punycode: 2.3.1
+
+
user-home@2.0.0:
+
dependencies:
+
os-homedir: 1.0.2
+
utils-merge@1.0.1: {}
+
uuid@3.4.0: {}
+
v8-compile-cache-lib@3.0.1: {}
+
varint@6.0.0: {}
+
vary@1.1.2: {}
+
verror@1.10.0:
+
dependencies:
+
assert-plus: 1.0.0
+
core-util-is: 1.0.2
+
extsprintf: 1.3.0
+
+
wrappy@1.0.2: {}
+
ws@8.18.3: {}
xtend@4.0.2: {}
+21 -38
src/firehose.ts
···
import { Insertable } from "kysely";
import { FirehoseEventTable } from "./db";
-
const pretty_print = (event_type: string, data: object) => {
-
    const colors = {
-
        commit: "\x1b[34m",
-
        identity: "\x1b[32m",
-
        account: "\x1b[33m",
-
        reset: "\x1b[0m",
-
    };
-
    const color = colors[event_type.toLowerCase()] || colors.reset;
-
    console.debug(`\n${color}## RECEIVED [${event_type.toUpperCase()}] EVENT ##${colors.reset}`);
-
    console.debug(JSON.stringify(
-
        data,
-
        (key, value) => typeof value === 'bigint' ? value.toString() : value,
-
        2
-
    ));
-
};
-
const saveEvent = async (type: 'commit' | 'identity' | 'account', data: any) => {
-
try {
-
await db.insertInto('firehose_event').values({
-
event_type: type,
-
event_data: data
-
}).execute();
-
} catch (error) {
-
console.error("\nFailed to save event to database:", error);
-
}
+
    try {
+
        await db.insertInto('firehose_event').values({
+
            event_type: type,
+
            event_data: data
+
        }).execute();
+
    } catch (error) {
+
        console.error("\nFailed to save event to database:", error);
+
    }
};
const main = () => {
···
        ws: WebSocket,
    });
-
    firehose.on("commit", (commit: CommitEvent) => {
-
saveEvent('commit', commit);
+
    firehose.on("commit", async (commit: CommitEvent) => {
        const createOps = commit.ops.filter(op => op.action === 'create');
+
        const relevantOps = [];
        for (const op of createOps) {
            const recordType = op.record['$type'];
            if (recordType && (recordType.startsWith('com.atproto.') || recordType.startsWith('systems.gmstn.'))) {
-
                pretty_print(`COMMIT - ${recordType}`, {
-
                    repo: commit.repo,
-
                    path: op.path,
-
                    record: op.record
-
                });
+
                relevantOps.push(op);
            }
        }
+
+
        if (relevantOps.length > 0) {
+
            await saveEvent('commit', commit);
+
        }
    });
-
    firehose.on("identity", (identity: IdentityEvent) => {
-
saveEvent('identity', identity);
-
        pretty_print("IDENTITY", identity);
+
    firehose.on("identity", async (identity: IdentityEvent) => {
+
        await saveEvent('identity', identity);
    });
-
    firehose.on("account", (account: AccountEvent) => {
-
saveEvent('account', account);
-
        pretty_print("ACCOUNT", account);
+
    firehose.on("account", async (account: AccountEvent) => {
+
        await saveEvent('account', account);
    });
    firehose.on("open", () => {
···
    });
    firehose.on("close", (cursor) => {
-
        console.log(`\nConnection closed. Last cursor was: ${cursor}`);
+
        console.log(`\nConnection closed. Last cursor was: ${cursor}. Restarting.`);
+
        firehose.start();
    });
    firehose.on("error", ({ error, cursor }) => {
+10
src/index.ts
···
console.log('Main app starting...');
+
const pdsListSyncPath = path.resolve(__dirname, 'pds-list-sync.ts');
+
const pdsListSyncProcess = fork(pdsListSyncPath);
+
+
console.log(`pdsListSync process started with PID: ${pdsListSyncProcess.pid}`);
+
+
const pdsBackfillPath = path.resolve(__dirname, 'pds-backfill.ts');
+
const pdsBackfillProcess = fork(pdsBackfillPath);
+
+
console.log(`pdsBackfill process started with PID: ${pdsBackfillProcess.pid}`);
+
const firehosePath = path.resolve(__dirname, 'firehose.ts');
const firehoseProcess = fork(firehosePath);
+182
src/pds-backfill.ts
···
+
import { db } from './db';
+
+
export interface FirehoseEventTable {
+
timestamp: ColumnType<Date, string | Date, never>;
+
event_type: string;
+
event_data: Record<string, any>;
+
}
+
export type FirehoseEvent = Selectable<FirehoseEventTable>;
+
export type NewFirehoseEvent = Insertable<FirehoseEventTable>;
+
+
interface AtpRecord {
+
$type: string;
+
createdAt: string;
+
[key: string]: any;
+
}
+
+
async function processSingleRepo(pdsHostname: string, did: string) {
+
const pdsBaseUrl = `https://` + pdsHostname;
+
const getRepoUrl = new URL(`/xrpc/com.atproto.sync.getRepo`, pdsBaseUrl);
+
getRepoUrl.searchParams.set('did', did);
+
+
let car: any;
+
try {
+
const { CarReader } = await import('@ipld/car');
+
+
const response = await fetch(getRepoUrl.href);
+
if (!response.ok) {
+
throw new Error(`Failed to getRepo for ${did}: ${response.status} ${response.statusText}`);
+
}
+
const carBytes = new Uint8Array(await response.arrayBuffer());
+
car = await CarReader.fromBytes(carBytes);
+
} catch (e: any) {
+
console.error(`[${did}] Failed to fetch or parse CAR: ${e.message}`);
+
return;
+
}
+
+
const recordsToInsert: NewFirehoseEvent[] = [];
+
+
try {
+
const cbor = await import('@ipld/dag-cbor');
+
+
for await (const block of car.blocks()) {
+
const record = cbor.decode(block.bytes) as AtpRecord;
+
+
if (
+
record &&
+
record.$type &&
+
typeof record.$type === 'string' &&
+
record.$type.startsWith('systems.gmstn.')
+
) {
+
if (!record.createdAt || typeof record.createdAt !== 'string') {
+
console.warn(`[${did}] Found matching record without valid 'createdAt', skipping.`);
+
continue;
+
}
+
+
recordsToInsert.push({
+
timestamp: record.createdAt,
+
event_type: record.$type,
+
event_data: record,
+
});
+
}
+
}
+
} catch (e: any) {
+
console.error(`[${did}] Error parsing CAR blocks: ${e.message}. Skipping rest of repo.`);
+
return;
+
}
+
+
if (recordsToInsert.length > 0) {
+
try {
+
await db.insertInto('firehose_event').values(recordsToInsert).execute();
+
console.log(`[${did}] Inserted ${recordsToInsert.length} 'systems.gmstn.*' records.`);
+
} catch (e: any) {
+
console.error(`[${did}] Failed to insert records into DB: ${e.message}`);
+
}
+
}
+
}
+
+
async function backfillPds(pdsHostname: string) {
+
console.log(`Starting backfill for: ${pdsHostname}`);
+
const pdsBaseUrl = `https://` + pdsHostname;
+
let cursor: string | undefined;
+
let totalReposProcessed = 0;
+
+
try {
+
do {
+
const listReposUrl = new URL('/xrpc/com.atproto.sync.listRepos', pdsBaseUrl);
+
if (cursor) {
+
listReposUrl.searchParams.set('cursor', cursor);
+
}
+
+
const response = await fetch(listReposUrl.href);
+
if (!response.ok) {
+
throw new Error(`Failed to listRepos: ${response.status} ${response.statusText}`);
+
}
+
+
const data = await response.json();
+
cursor = data.cursor;
+
const dids: string[] = data.repos.map((r: { did: string }) => r.did);
+
+
if (dids.length === 0) {
+
break;
+
}
+
+
console.log(`Fetched ${dids.length} repos. Cursor: ${cursor}`);
+
+
const BATCH_SIZE = 10;
+
for (let i = 0; i < dids.length; i += BATCH_SIZE) {
+
const batch = dids.slice(i, i + BATCH_SIZE);
+
const tasks = batch.map(did => processSingleRepo(pdsHostname, did));
+
await Promise.allSettled(tasks);
+
}
+
+
totalReposProcessed += dids.length;
+
+
} while (cursor);
+
+
console.log(`[${pdsHostname}] Finished paginating repos.`);
+
+
await db
+
.updateTable('pds')
+
.set({ backfilled_at: new Date() })
+
.where('hostname', '=', pdsHostname)
+
.execute();
+
+
console.log(`Successfully completed backfill for ${pdsHostname}. Total repos: ${totalReposProcessed}`);
+
+
} catch (error) {
+
console.error(`[${pdsHostname}] Fatal error during backfill:`, error);
+
throw error;
+
}
+
}
+
+
async function main() {
+
let pdsesToBackfill: { hostname: string }[] = [];
+
+
try {
+
pdsesToBackfill = await db
+
.selectFrom('pds')
+
.select('hostname')
+
.where('backfilled_at', 'is', null)
+
.orderBy(
+
(eb) => eb
+
.case()
+
.when('hostname', 'like', '%.bsky.network')
+
.then(1)
+
.else(0)
+
.end(),
+
'asc'
+
)
+
.orderBy('added_at', 'asc')
+
.execute();
+
+
if (pdsesToBackfill.length === 0) {
+
console.log('No PDSs to backfill. All caught up! Exiting.');
+
await db.destroy();
+
return;
+
}
+
+
console.log(`Found ${pdsesToBackfill.length} PDS(s) to backfill. Starting job...`);
+
+
} catch (e: any) {
+
console.error('Failed to fetch PDS list from database:', e.message);
+
process.exit(1);
+
}
+
+
for (const pds of pdsesToBackfill) {
+
try {
+
await backfillPds(pds.hostname);
+
} catch (e) {
+
console.error(`---`);
+
console.error(`Job for ${pds.hostname} failed. Moving to next PDS.`);
+
console.error(`---`);
+
}
+
}
+
+
console.log('All backfill jobs complete. Closing database connection.');
+
await db.destroy();
+
}
+
+
if (require.main === module) {
+
main();
+
}
+75
src/pds-list-sync.ts
···
+
import { db } from './db';
+
+
const PDS_LIST_URL = 'https://raw.githubusercontent.com/mary-ext/atproto-scraping/refs/heads/trunk/state.json';
+
+
interface StateJson {
+
pdses: {
+
[url: string]: {
+
inviteCodeRequired?: boolean;
+
version?: string;
+
}
+
}
+
}
+
+
async function syncPdsList() {
+
console.log('Starting PDS list sync...');
+
+
try {
+
const response = await fetch(PDS_LIST_URL);
+
if (!response.ok) {
+
throw new Error(`Failed to fetch PDS list: ${response.statusText}`);
+
}
+
+
const data = (await response.json()) as StateJson;
+
const pdsUrls = Object.keys(data?.pdses || {});
+
+
if (pdsUrls.length === 0) {
+
console.warn('No PDS hosts found in the upstream list.');
+
return;
+
}
+
+
const pdsToInsert = pdsUrls
+
.map(url => {
+
try {
+
return { hostname: new URL(url).hostname };
+
} catch (e) {
+
console.warn(`Invalid URL format in PDS list, skipping: ${url}`);
+
return null;
+
}
+
})
+
.filter(Boolean) as { hostname: string }[];
+
+
if (pdsToInsert.length === 0) {
+
console.log('No new valid PDS hosts to insert.');
+
return;
+
}
+
+
const result = await db
+
.insertInto('pds')
+
.values(pdsToInsert)
+
.onConflict((oc) => oc
+
.column('hostname')
+
.doNothing()
+
)
+
.execute();
+
+
console.log(`PDS list sync complete. Checked ${pdsToInsert.length} hosts.`);
+
+
} catch (error) {
+
console.error('Error during PDS list sync:', error);
+
process.exit(1);
+
}
+
}
+
+
if (require.main === module) {
+
syncPdsList()
+
.then(() => {
+
console.log('Sync finished successfully.');
+
db.destroy();
+
})
+
.catch((err) => {
+
console.error('Unhandled error in syncPdsList:', err);
+
db.destroy();
+
process.exit(1);
+
});
+
}