+3
-2
.dockerignore
+3
-2
.dockerignore
+4
-82
Cargo.lock
+4
-82
Cargo.lock
···
229
229
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
230
230
231
231
[[package]]
232
-
name = "askama"
233
-
version = "0.14.0"
234
-
source = "registry+https://github.com/rust-lang/crates.io-index"
235
-
checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4"
236
-
dependencies = [
237
-
"askama_derive",
238
-
"itoa",
239
-
"percent-encoding",
240
-
"serde",
241
-
"serde_json",
242
-
]
243
-
244
-
[[package]]
245
-
name = "askama_derive"
246
-
version = "0.14.0"
247
-
source = "registry+https://github.com/rust-lang/crates.io-index"
248
-
checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f"
249
-
dependencies = [
250
-
"askama_parser",
251
-
"basic-toml",
252
-
"memchr",
253
-
"proc-macro2",
254
-
"quote",
255
-
"rustc-hash",
256
-
"serde",
257
-
"serde_derive",
258
-
"syn 2.0.106",
259
-
]
260
-
261
-
[[package]]
262
-
name = "askama_parser"
263
-
version = "0.14.0"
264
-
source = "registry+https://github.com/rust-lang/crates.io-index"
265
-
checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358"
266
-
dependencies = [
267
-
"memchr",
268
-
"serde",
269
-
"serde_derive",
270
-
"winnow 0.7.13",
271
-
]
272
-
273
-
[[package]]
274
232
name = "async-compression"
275
233
version = "0.4.32"
276
234
source = "registry+https://github.com/rust-lang/crates.io-index"
···
511
469
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
512
470
513
471
[[package]]
514
-
name = "basic-toml"
515
-
version = "0.1.10"
516
-
source = "registry+https://github.com/rust-lang/crates.io-index"
517
-
checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a"
518
-
dependencies = [
519
-
"serde",
520
-
]
521
-
522
-
[[package]]
523
472
name = "bigdecimal"
524
473
version = "0.4.8"
525
474
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1017
966
dependencies = [
1018
967
"chrono",
1019
968
"once_cell",
1020
-
"winnow 0.6.26",
969
+
"winnow",
1021
970
]
1022
971
1023
972
[[package]]
···
1027
976
"apalis",
1028
977
"apalis-cron",
1029
978
"apalis-sql",
1030
-
"chrono",
1031
979
"dotenvy",
1032
980
"log",
1033
-
"serde",
1034
981
"shared",
1035
982
"tokio",
1036
983
"tower",
1037
-
"tracing",
1038
984
"tracing-subscriber",
1039
985
]
1040
986
···
2934
2880
"dotenvy",
2935
2881
"env_logger",
2936
2882
"jacquard",
2937
-
"jacquard-api",
2938
2883
"jacquard-common",
2939
2884
"lexicon_types_crate",
2940
2885
"log",
2941
2886
"reqwest",
2887
+
"rust-s3",
2888
+
"shared",
2889
+
"sqlx",
2942
2890
"tokio",
2943
2891
]
2944
2892
···
5324
5272
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
5325
5273
5326
5274
[[package]]
5327
-
name = "vite-rust"
5328
-
version = "0.2.4"
5329
-
source = "registry+https://github.com/rust-lang/crates.io-index"
5330
-
checksum = "4ae9a5cd007a52d1227f4de7488c9da0a46b7946b3e9803025677e797ffe6f41"
5331
-
dependencies = [
5332
-
"hex",
5333
-
"log",
5334
-
"md-5",
5335
-
"regex",
5336
-
"reqwest",
5337
-
"serde",
5338
-
"serde_json",
5339
-
]
5340
-
5341
-
[[package]]
5342
5275
name = "walkdir"
5343
5276
version = "2.5.0"
5344
5277
source = "registry+https://github.com/rust-lang/crates.io-index"
···
5470
5403
"anyhow",
5471
5404
"apalis",
5472
5405
"apalis-sql",
5473
-
"askama",
5474
5406
"async-compression",
5475
5407
"atproto-identity",
5476
5408
"axum",
···
5500
5432
"tower_governor",
5501
5433
"tracing",
5502
5434
"tracing-subscriber",
5503
-
"vite-rust",
5504
5435
]
5505
5436
5506
5437
[[package]]
···
6066
5997
version = "0.6.26"
6067
5998
source = "registry+https://github.com/rust-lang/crates.io-index"
6068
5999
checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28"
6069
-
dependencies = [
6070
-
"memchr",
6071
-
]
6072
-
6073
-
[[package]]
6074
-
name = "winnow"
6075
-
version = "0.7.13"
6076
-
source = "registry+https://github.com/rust-lang/crates.io-index"
6077
-
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
6078
6000
dependencies = [
6079
6001
"memchr",
6080
6002
]
+18
Dockerfiles/web-ui.Dockerfile
+18
Dockerfiles/web-ui.Dockerfile
···
1
+
FROM node:24-slim as builder
2
+
ENV PNPM_HOME="/pnpm"
3
+
ENV PATH="$PNPM_HOME:$PATH"
4
+
RUN corepack enable
5
+
WORKDIR /app
6
+
7
+
COPY ./web-ui /app
8
+
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install
9
+
RUN pnpm run build
10
+
11
+
FROM node:24-alpine3.22 as web-ui
12
+
WORKDIR /app
13
+
14
+
COPY --from=builder /app/build /app/build
15
+
COPY --from=builder /app/package*.json /app/
16
+
RUN npm install --omit=dev
17
+
18
+
CMD ["node", "build"]
-10
Dockerfiles/web.Dockerfile
-10
Dockerfiles/web.Dockerfile
···
1
-
FROM node:24-alpine3.21 as node_builder
2
-
WORKDIR /app
3
-
4
-
COPY ./web/ui-code/ /app
5
-
#Not a fan of the --force here
6
-
RUN npm install --force
7
-
RUN npm run build
8
-
9
1
FROM rust:1.90.0-bookworm AS builder
10
2
WORKDIR /app
11
3
COPY . /app
12
4
RUN cargo build --bin web --release
13
5
14
6
FROM rust:1.90.0-bookworm AS web
15
-
COPY --from=node_builder /app/dist /app/vite/dist
16
-
COPY ./web/public /app/public
17
7
COPY --from=builder /app/target/release/web /usr/local/bin/web
18
8
19
9
CMD ["web"]
+16
ProductionComposes/Caddyfile
+16
ProductionComposes/Caddyfile
···
1
+
:80 {
2
+
@xrpc {
3
+
path /xrpc/*
4
+
path /.well-known/*
5
+
}
6
+
7
+
# Handle /xrpc/ routes - forward to the API backend (web service)
8
+
handle @xrpc {
9
+
reverse_proxy localhost:3000
10
+
}
11
+
12
+
# Handle all other routes - forward to the web-ui frontend
13
+
handle /* {
14
+
reverse_proxy localhost:3001
15
+
}
16
+
}
+34
-2
ProductionComposes/compose.web.yml
+34
-2
ProductionComposes/compose.web.yml
···
1
1
services:
2
2
web:
3
3
image: fatfingers23/moover_web:latest
4
-
network_mode: host
5
4
restart: unless-stopped
5
+
network_mode: host
6
6
ports:
7
7
- "3000:3000"
8
8
env_file:
···
11
11
environment:
12
12
- VITE_DIST=/app/vite/dist
13
13
- PUBLIC_ASSETS=/app/public
14
+
web-ui:
15
+
image: fatfingers23/moover_ui:latest
16
+
network_mode: host
17
+
restart: unless-stopped
18
+
ports:
19
+
- "3001:3001"
20
+
environment:
21
+
- PORT=3001
22
+
- PUBLIC_XRPC_BASE=pdsmoover.com
23
+
caddy:
24
+
image: caddy:2-alpine
25
+
network_mode: host
26
+
restart: unless-stopped
27
+
ports:
28
+
- "80:80"
29
+
- "443:443"
30
+
volumes:
31
+
- ./Caddyfile:/etc/caddy/Caddyfile
32
+
- caddy_data:/data
33
+
- caddy_config:/config
34
+
depends_on:
35
+
- web
36
+
- web-ui
14
37
#Only a single one of these instances should be running
15
38
#it's what triggers daily backups
16
39
cron-worker:
17
40
image: fatfingers23/moover_cron_worker:latest
18
41
network_mode: host
42
+
restart: unless-stopped
19
43
build:
20
44
context: .
21
45
dockerfile: ./Dockerfiles/cron-worker.Dockerfile
22
46
env_file:
23
47
- path: .env
24
-
required: true
48
+
required: true
49
+
50
+
networks:
51
+
moover_network:
52
+
driver: bridge
53
+
54
+
volumes:
55
+
caddy_data:
56
+
caddy_config:
+2
ProductionComposes/compose.workers.yml
+2
ProductionComposes/compose.workers.yml
···
11
11
worker-two:
12
12
image: fatfingers23/moover_worker:latest
13
13
network_mode: host
14
+
restart: unless-stopped
14
15
env_file:
15
16
- path: .env
16
17
required: true
···
19
20
worker-three:
20
21
image: fatfingers23/moover_worker:latest
21
22
network_mode: host
23
+
restart: unless-stopped
22
24
env_file:
23
25
- path: .env
24
26
required: true
+6
-3
README.md
+6
-3
README.md
···
3
3
A series of web tools to help users: migrate to a new PDS, find missing blobs, have free backups, and restore from
4
4
backups in the event of emergency. [pdsmoover.com](https://pdsmoover.com)
5
5
6
-

6
+

7
7
8
8
A little light on documentation as I come off of about a week long crunch but.
9
9
···
23
23
- [cron-worker](./cron-worker) - Very simple binary to tick every hour telling the main worker to check for repos that
24
24
need an update
25
25
- [Dockerfiles](./Dockerfiles) - Dockerfiles for all the services in the repo
26
-
- [lexicon_types](./lexicon_types) - TypeScript types for PDS MOOver lexicons (not currently in use)
26
+
- [packages/lexicons](./packages/lexicons) - TypeScript types for PDS MOOver lexicons
27
+
- [packages/moover](./packages/moover) - Frontend logic that handles all the atproto processes. Also published as a node
28
+
module
29
+
at [@pds-moover/moover](https://www.npmjs.com/package/@pds-moover/moover)
27
30
- [lexicon_types_crate](./lexicon_types_crate) - Rust lexicon types
28
31
- [lexicons](./lexicons) - JSON Lexicons
29
32
- [ProductionComposes](./ProductionComposes) - What I use to run PDS MOOver in production. One instance of web behind a
30
33
load balancer, one worker node currently with 3 instances on that one server. All can scale horizontally
31
34
- [shared](./shared) - Shared code between all the services
32
35
- [web](./web) - The web frontend that servers XRPC endpoints and the frontend
33
-
- [web-ui](./web/ui-code) - JS code to handle everything to do with atproto such as Migrations, missing blobs, signing
36
+
- [web-ui](./web-ui) - Svelte frontend.
34
37
plc ops, restores, etc
35
38
- [worker](./worker) - What acutally handles all the backing up, but the actual logic is
36
39
in [./shared/src/jobs/](./shared/src/jobs/)
+4
-2
admin_cli/Cargo.toml
+4
-2
admin_cli/Cargo.toml
···
12
12
env_logger = "0.11"
13
13
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
14
14
jacquard-common.workspace = true
15
-
jacquard-api.workspace = true
16
15
jacquard.workspace = true
17
16
lexicon_types_crate.workspace = true
18
17
reqwest.workspace = true
19
-
base64 = "0.22"
18
+
base64 = "0.22"
19
+
shared = { path = "../shared" }
20
+
sqlx = { version = "0.8.6", features = ["runtime-tokio", "postgres"] }
21
+
rust-s3.workspace = true
+57
admin_cli/src/main.rs
+57
admin_cli/src/main.rs
···
11
11
use log;
12
12
use reqwest::header;
13
13
use reqwest::header::{HeaderMap, HeaderValue};
14
+
use s3::creds::Credentials;
15
+
use s3::{Bucket, Region};
16
+
use sqlx::PgPool;
14
17
use std::env;
15
18
16
19
fn init_logging() {
···
52
55
},
53
56
/// Trigger an instance-wide backup job (no parameters)
54
57
RequestInstanceBackup,
58
+
/// Verify all backups in S3 against the database
59
+
VerifyBackups,
55
60
}
56
61
57
62
#[derive(Debug, Subcommand)]
···
219
224
}
220
225
Err(err) => {
221
226
log::error!("Instance backup request failed: {}", err);
227
+
}
228
+
}
229
+
}
230
+
Commands::VerifyBackups => {
231
+
//Not really a part of the cli per say. But I needed it and is a good place as any
232
+
log::info!("Verifying backups in S3...");
233
+
234
+
// Get database URL from environment
235
+
let database_url =
236
+
env::var("DATABASE_URL").context("DATABASE_URL environment variable not set")?;
237
+
238
+
// Connect to database
239
+
let pool = PgPool::connect(&database_url)
240
+
.await
241
+
.context("Failed to connect to database")?;
242
+
243
+
// Setup S3 client
244
+
let region_name = env::var("S3_REGION")?;
245
+
let endpoint = env::var("S3_ENDPOINT")?;
246
+
let region = Region::Custom {
247
+
region: region_name,
248
+
endpoint,
249
+
};
250
+
let bucket = Bucket::new(
251
+
env::var("S3_BUCKET_NAME")?.as_str(),
252
+
region,
253
+
Credentials::new(
254
+
Some(env::var("S3_ACCESS_KEY")?.as_str()),
255
+
Some(env::var("S3_SECRET_KEY")?.as_str()),
256
+
None,
257
+
None,
258
+
None,
259
+
)?,
260
+
)?;
261
+
262
+
// Call the verify_backups function
263
+
match shared::jobs::verify_backups::verify_backups(&pool, &bucket).await {
264
+
Ok(missing_blobs) => {
265
+
if missing_blobs.is_empty() {
266
+
log::info!("✓ All backups verified successfully! No missing blobs found.");
267
+
} else {
268
+
log::error!("✗ Found {} missing blobs:", missing_blobs.len());
269
+
for missing in &missing_blobs {
270
+
println!(
271
+
"Missing: DID={}, CID/REV={}, TYPE={:?}, PATH={}",
272
+
missing.did, missing.cid_or_rev, missing.blob_type, missing.s3_path
273
+
);
274
+
}
275
+
}
276
+
}
277
+
Err(err) => {
278
+
log::error!("Failed to verify backups: {}", err);
222
279
}
223
280
}
224
281
}
+2
-2
compose.dev.yml
+2
-2
compose.dev.yml
···
1
1
services:
2
2
postgres:
3
-
image: postgres:latest
3
+
image: postgres:18
4
4
restart: unless-stopped
5
5
environment:
6
6
POSTGRES_USER: ${DB_USER}
···
9
9
ports:
10
10
- "5432:5432"
11
11
volumes:
12
-
- moove-postgres-data:/var/lib/postgresql/data
12
+
- moove-postgres-data:/var/lib/postgresql
13
13
extra_hosts:
14
14
- "host.docker.internal:host-gateway"
15
15
networks:
+14
compose.selfhost.yml
+14
compose.selfhost.yml
···
16
16
- PUBLIC_ASSETS=/app/public
17
17
depends_on:
18
18
- postgres
19
+
web-ui:
20
+
# image: fatfingers23/moover_web_ui:latest
21
+
build:
22
+
context: .
23
+
dockerfile: ./Dockerfiles/web-ui.Dockerfile
24
+
ports:
25
+
- "3001:3001"
26
+
env_file:
27
+
- path: .env
28
+
required: false
29
+
environment:
30
+
- PORT=3001
31
+
networks:
32
+
- moover-network
19
33
cron-worker:
20
34
image: fatfingers23/moover_cron_worker:latest
21
35
# build:
-3
cron-worker/Cargo.toml
-3
cron-worker/Cargo.toml
···
9
9
apalis-sql.workspace = true
10
10
apalis-cron.workspace = true
11
11
dotenvy.workspace = true
12
-
tracing.workspace = true
13
12
tracing-subscriber.workspace = true
14
13
shared.workspace = true
15
14
log.workspace = true
16
-
serde.workspace = true
17
-
chrono.workspace = true
18
15
tower = { version = "0.5.2", features = ["load-shed"] }
19
16
tokio.workspace = true
+11
-3
justfile
+11
-3
justfile
···
3
3
docker buildx build \
4
4
--platform linux/arm64,linux/amd64 \
5
5
--tag fatfingers23/moover_web:latest \
6
-
--tag fatfingers23/moover_web:0.0.1 \
6
+
--tag fatfingers23/moover_web:0.0.2 \
7
7
--file Dockerfiles/web.Dockerfile \
8
8
--push .
9
9
# Worker
10
10
docker buildx build \
11
11
--platform linux/arm64,linux/amd64 \
12
12
--tag fatfingers23/moover_worker:latest \
13
-
--tag fatfingers23/moover_worker:0.0.1 \
13
+
--tag fatfingers23/moover_worker:0.0.2 \
14
14
--file Dockerfiles/worker.Dockerfile \
15
15
--push .
16
16
#cron worker
17
17
docker buildx build \
18
18
--platform linux/arm64,linux/amd64 \
19
19
--tag fatfingers23/moover_cron_worker:latest \
20
-
--tag fatfingers23/moover_cron_worker:0.0.1 \
20
+
--tag fatfingers23/moover_cron_worker:0.0.2 \
21
21
--file Dockerfiles/cron-worker.Dockerfile \
22
+
--push .
23
+
24
+
#web ui
25
+
docker buildx build \
26
+
--platform linux/arm64,linux/amd64 \
27
+
--tag fatfingers23/moover_ui:latest \
28
+
--tag fatfingers23/moover_ui:0.0.2 \
29
+
--file Dockerfiles/web-ui.Dockerfile \
22
30
--push .
lexicon_types/.gitignore
packages/lexicons/.gitignore
lexicon_types/.gitignore
packages/lexicons/.gitignore
lexicon_types/bun.lock
packages/lexicons/bun.lock
lexicon_types/bun.lock
packages/lexicons/bun.lock
+2
-2
lexicon_types/lex.config.js
packages/lexicons/lex.config.js
+2
-2
lexicon_types/lex.config.js
packages/lexicons/lex.config.js
-31
lexicon_types/package.json
-31
lexicon_types/package.json
···
1
-
{
2
-
"name": "@pds-moover/lexicon_types",
3
-
"version": "0.0.0",
4
-
"type": "module",
5
-
"main": "./dist/lexicon_types.umd.cjs",
6
-
"module": "./dist/lexicon_types.js",
7
-
"types": "./dist/index.d.ts",
8
-
"exports": {
9
-
".": {
10
-
"import": "./dist/lexicon_types.js",
11
-
"require": "./dist/lexicon_types.umd.cjs"
12
-
}
13
-
},
14
-
"scripts": {
15
-
"dev": "vite",
16
-
"build": "tsc && vite build",
17
-
"preview": "vite preview"
18
-
},
19
-
"devDependencies": {
20
-
"@atcute/lex-cli": "^2.2.2",
21
-
"@types/node": "^24.7.2",
22
-
"typescript": "~5.9.3",
23
-
"vite": "^7.1.7",
24
-
"vite-plugin-dts": "^4.5.4"
25
-
},
26
-
"dependencies": {
27
-
"@atproto/lexicon": "^0.5.1",
28
-
"@atproto/xrpc": "^0.7.5",
29
-
"cid": "multiformats/cid"
30
-
}
31
-
}
lexicon_types/src/index.ts
packages/lexicons/lib/lexicons/index.ts
lexicon_types/src/index.ts
packages/lexicons/lib/lexicons/index.ts
lexicon_types/src/types/app/bsky/actor/defs.ts
packages/lexicons/lib/lexicons/types/app/bsky/actor/defs.ts
lexicon_types/src/types/app/bsky/actor/defs.ts
packages/lexicons/lib/lexicons/types/app/bsky/actor/defs.ts
lexicon_types/src/types/app/bsky/actor/getPreferences.ts
packages/lexicons/lib/lexicons/types/app/bsky/actor/getPreferences.ts
lexicon_types/src/types/app/bsky/actor/getPreferences.ts
packages/lexicons/lib/lexicons/types/app/bsky/actor/getPreferences.ts
lexicon_types/src/types/app/bsky/feed/postgate.ts
packages/lexicons/lib/lexicons/types/app/bsky/feed/postgate.ts
lexicon_types/src/types/app/bsky/feed/postgate.ts
packages/lexicons/lib/lexicons/types/app/bsky/feed/postgate.ts
lexicon_types/src/types/app/bsky/feed/threadgate.ts
packages/lexicons/lib/lexicons/types/app/bsky/feed/threadgate.ts
lexicon_types/src/types/app/bsky/feed/threadgate.ts
packages/lexicons/lib/lexicons/types/app/bsky/feed/threadgate.ts
lexicon_types/src/types/com/atproto/sync/getBlob.ts
packages/lexicons/lib/lexicons/types/com/atproto/sync/getBlob.ts
lexicon_types/src/types/com/atproto/sync/getBlob.ts
packages/lexicons/lib/lexicons/types/com/atproto/sync/getBlob.ts
lexicon_types/src/types/com/atproto/sync/getRepo.ts
packages/lexicons/lib/lexicons/types/com/atproto/sync/getRepo.ts
lexicon_types/src/types/com/atproto/sync/getRepo.ts
packages/lexicons/lib/lexicons/types/com/atproto/sync/getRepo.ts
lexicon_types/src/types/com/pdsmoover/admin/removePds.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/removePds.ts
lexicon_types/src/types/com/pdsmoover/admin/removePds.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/removePds.ts
lexicon_types/src/types/com/pdsmoover/admin/removeRepo.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/removeRepo.ts
lexicon_types/src/types/com/pdsmoover/admin/removeRepo.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/removeRepo.ts
-26
lexicon_types/src/types/com/pdsmoover/admin/requestBackup.ts
-26
lexicon_types/src/types/com/pdsmoover/admin/requestBackup.ts
···
1
-
import type {} from "@atcute/lexicons";
2
-
import * as v from "@atcute/lexicons/validations";
3
-
import type {} from "@atcute/lexicons/ambient";
4
-
5
-
const _mainSchema = /*#__PURE__*/ v.procedure(
6
-
"com.pdsmoover.admin.requestBackup",
7
-
{
8
-
params: null,
9
-
input: null,
10
-
output: null,
11
-
},
12
-
);
13
-
14
-
type main$schematype = typeof _mainSchema;
15
-
16
-
export interface mainSchema extends main$schematype {}
17
-
18
-
export const mainSchema = _mainSchema as mainSchema;
19
-
20
-
export interface $params {}
21
-
22
-
declare module "@atcute/lexicons/ambient" {
23
-
interface XRPCProcedures {
24
-
"com.pdsmoover.admin.requestBackup": mainSchema;
25
-
}
26
-
}
lexicon_types/src/types/com/pdsmoover/admin/requestInstanceBackup.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/requestInstanceBackup.ts
lexicon_types/src/types/com/pdsmoover/admin/requestInstanceBackup.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/requestInstanceBackup.ts
lexicon_types/src/types/com/pdsmoover/admin/requestPdsBackup.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/requestPdsBackup.ts
lexicon_types/src/types/com/pdsmoover/admin/requestPdsBackup.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/requestPdsBackup.ts
lexicon_types/src/types/com/pdsmoover/admin/requestRepoBackup.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/requestRepoBackup.ts
lexicon_types/src/types/com/pdsmoover/admin/requestRepoBackup.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/requestRepoBackup.ts
lexicon_types/src/types/com/pdsmoover/admin/signUpPds.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/signUpPds.ts
lexicon_types/src/types/com/pdsmoover/admin/signUpPds.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/admin/signUpPds.ts
lexicon_types/src/types/com/pdsmoover/backup/describeServer.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/backup/describeServer.ts
lexicon_types/src/types/com/pdsmoover/backup/describeServer.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/backup/describeServer.ts
lexicon_types/src/types/com/pdsmoover/backup/getRepoStatus.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/backup/getRepoStatus.ts
lexicon_types/src/types/com/pdsmoover/backup/getRepoStatus.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/backup/getRepoStatus.ts
lexicon_types/src/types/com/pdsmoover/backup/removeRepo.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/backup/removeRepo.ts
lexicon_types/src/types/com/pdsmoover/backup/removeRepo.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/backup/removeRepo.ts
lexicon_types/src/types/com/pdsmoover/backup/requestBackup.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/backup/requestBackup.ts
lexicon_types/src/types/com/pdsmoover/backup/requestBackup.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/backup/requestBackup.ts
lexicon_types/src/types/com/pdsmoover/backup/signUp.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/backup/signUp.ts
lexicon_types/src/types/com/pdsmoover/backup/signUp.ts
packages/lexicons/lib/lexicons/types/com/pdsmoover/backup/signUp.ts
-32
lexicon_types/tsconfig.json
-32
lexicon_types/tsconfig.json
···
1
-
{
2
-
"compilerOptions": {
3
-
"target": "ES2022",
4
-
"useDefineForClassFields": true,
5
-
"module": "ESNext",
6
-
"lib": [
7
-
"ES2022",
8
-
"DOM",
9
-
"DOM.Iterable"
10
-
],
11
-
"types": [
12
-
"vite/client"
13
-
],
14
-
"skipLibCheck": true,
15
-
/* Bundler mode */
16
-
"moduleResolution": "bundler",
17
-
"allowImportingTsExtensions": true,
18
-
"verbatimModuleSyntax": true,
19
-
"moduleDetection": "force",
20
-
"noEmit": true,
21
-
/* Linting */
22
-
"strict": true,
23
-
"noUnusedLocals": false,
24
-
"noUnusedParameters": true,
25
-
"erasableSyntaxOnly": true,
26
-
"noFallthroughCasesInSwitch": true,
27
-
"noUncheckedSideEffectImports": true
28
-
},
29
-
"include": [
30
-
"src"
31
-
]
32
-
}
-15
lexicon_types/vite.config.ts
-15
lexicon_types/vite.config.ts
···
1
-
import {resolve} from 'path';
2
-
import {defineConfig} from 'vite';
3
-
import dts from 'vite-plugin-dts';
4
-
5
-
// https://vitejs.dev/guide/build.html#library-mode
6
-
export default defineConfig({
7
-
build: {
8
-
lib: {
9
-
entry: resolve(__dirname, 'src/index.ts'),
10
-
name: 'lexicon_types',
11
-
fileName: 'lexicon_types',
12
-
},
13
-
},
14
-
plugins: [dts()],
15
-
});
+1
packages/lexicons/lib/index.ts
+1
packages/lexicons/lib/index.ts
···
1
+
export * from './lexicons/index.js'
+27
packages/lexicons/package.json
+27
packages/lexicons/package.json
···
1
+
{
2
+
"type": "module",
3
+
"name": "@pds-moover/lexicons",
4
+
"description": "PDS MOOver Lexicon Types",
5
+
"version": "1.0.1",
6
+
"license": "MIT",
7
+
"repository": "https://tangled.org/@baileytownsend.dev/pds-moover",
8
+
"files": [
9
+
"dist"
10
+
],
11
+
"exports": {
12
+
".": "./dist/index.js",
13
+
"./types/*": "./dist/lexicons/types/sh/tangled/*.js"
14
+
},
15
+
"scripts": {
16
+
"build": "tsc",
17
+
"generate": "rm -r ./lib/lexicons/; lex-cli generate -c ./lex.config.js",
18
+
"prepublishOnly": "rm -rf dist; npm run build"
19
+
},
20
+
"devDependencies": {
21
+
"@atcute/lex-cli": "^2.2.2"
22
+
},
23
+
"dependencies": {
24
+
"@atproto/lexicon": "^0.5.1",
25
+
"@atproto/xrpc": "^0.7.5"
26
+
}
27
+
}
+25
packages/lexicons/tsconfig.json
+25
packages/lexicons/tsconfig.json
···
1
+
{
2
+
"compilerOptions": {
3
+
"outDir": "dist/",
4
+
"esModuleInterop": true,
5
+
"skipLibCheck": true,
6
+
"target": "ESNext",
7
+
"allowJs": true,
8
+
"resolveJsonModule": true,
9
+
"moduleDetection": "force",
10
+
"isolatedModules": true,
11
+
"verbatimModuleSyntax": true,
12
+
"strict": true,
13
+
"noImplicitOverride": true,
14
+
"noUnusedLocals": true,
15
+
"noUnusedParameters": true,
16
+
"noFallthroughCasesInSwitch": true,
17
+
"module": "NodeNext",
18
+
"sourceMap": true,
19
+
"declaration": true,
20
+
"declarationMap": true
21
+
},
22
+
"include": [
23
+
"lib"
24
+
]
25
+
}
+1
packages/moover/.npmrc
+1
packages/moover/.npmrc
···
1
+
@atpkgs:registry=https://registry.atpkgs.easrng.net/
+15
packages/moover/README.md
+15
packages/moover/README.md
···
1
+
# @pds-moover/moover
2
+
3
+

4
+
5
+
This is the core logic that runs [PDS MOOver](https://pdsmoover.com). With this you should be able to create your own
6
+
"PDS MOOver" without having
7
+
to figure out the atproto logic.
8
+
9
+
- [lib/atprotoUtils.js](./lib/atprotoUtils.js) - Helpers for atproto actions
10
+
- [Migrator](./lib/pdsmoover.js) - For handling regular migrations
11
+
- [BackupService](./lib/backup.js) - For signing up for backups, request a back up, and remove backups to a PDS MOOver
12
+
instance
13
+
- [MissingBlobs](./lib/missingBlobs.js) - Finds missing blobs on your old PDS and uploads them to your new PDS
14
+
- [PlcOps](./lib/plc-ops.js) - Helpers for manual PCL operations
15
+
- [Restore](./lib/restore.js) - Handles a recovery and restores the at proto from the backup
packages/moover/images/moo.webp
packages/moover/images/moo.webp
This is a binary file and will not be displayed.
+13
packages/moover/index.html
+13
packages/moover/index.html
···
1
+
<!doctype html>
2
+
<html lang="en">
3
+
<head>
4
+
<meta charset="UTF-8"/>
5
+
<link rel="icon" type="image/svg+xml" href="/vite.svg"/>
6
+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
7
+
<title>moover</title>
8
+
</head>
9
+
<body>
10
+
<div id="app"></div>
11
+
<script type="module" src="/lib/main.js"></script>
12
+
</body>
13
+
</html>
+81
packages/moover/lib/atprotoUtils.js
+81
packages/moover/lib/atprotoUtils.js
···
1
+
import {
2
+
CompositeDidDocumentResolver, CompositeHandleResolver,
3
+
DohJsonHandleResolver,
4
+
PlcDidDocumentResolver, WebDidDocumentResolver,
5
+
WellKnownHandleResolver
6
+
} from '@atcute/identity-resolver';
7
+
8
+
const handleResolver = new CompositeHandleResolver({
9
+
strategy: 'race',
10
+
methods: {
11
+
dns: new DohJsonHandleResolver({
12
+
dohUrl: 'https://mozilla.cloudflare-dns.com/dns-query',
13
+
}),
14
+
http: new WellKnownHandleResolver(),
15
+
},
16
+
});
17
+
18
+
const docResolver = new CompositeDidDocumentResolver({
19
+
methods: {
20
+
plc: new PlcDidDocumentResolver(),
21
+
web: new WebDidDocumentResolver(),
22
+
},
23
+
});
24
+
25
+
/**
26
+
* Cleans the handle of @ and some other unicode characters that used to show up when copied from the profile
27
+
* @param handle {string}
28
+
* @returns {string}
29
+
*/
30
+
const cleanHandle = (handle) =>
31
+
handle.replace('@', '').trim().replace(
32
+
/[\u202A\u202C\u200E\u200F\u2066-\u2069]/g,
33
+
'',
34
+
);
35
+
36
+
37
+
/**
38
+
* Convince helper to resolve a handle to a did and then find the PDS url from the did document.
39
+
*
40
+
* @param handle
41
+
* @returns {Promise<{usersDid: string, pds: string}>}
42
+
*/
43
+
async function handleAndPDSResolver(handle) {
44
+
let usersDid = null;
45
+
if (handle.startsWith('did:')) {
46
+
usersDid = handle;
47
+
} else {
48
+
const cleanedHandle = cleanHandle(handle);
49
+
usersDid = await handleResolver.resolve(cleanedHandle);
50
+
}
51
+
const didDoc = await docResolver.resolve(usersDid);
52
+
53
+
let pds;
54
+
try {
55
+
pds = didDoc.service?.filter((s) =>
56
+
s.type === 'AtprotoPersonalDataServer'
57
+
)[0].serviceEndpoint;
58
+
} catch (error) {
59
+
throw new Error('Could not find a PDS in the DID document.');
60
+
}
61
+
return {usersDid, pds};
62
+
}
63
+
64
+
65
+
/**
66
+
* Fetches the DID Web from the .well-known/did.json endpoint of the server.
67
+
* Legacy and was helpful if the web ui and server are on the same domain, not as useful now
68
+
* @param baseUrl
69
+
* @returns {Promise<*>}
70
+
*/
71
+
async function fetchPDSMooverDIDWeb(baseUrl) {
72
+
const response = await fetch(`${baseUrl}/.well-known/did.json`);
73
+
if (!response.ok) {
74
+
throw new Error(`Failed to fetch DID document: ${response.status}`);
75
+
}
76
+
const didDoc = await response.json();
77
+
return didDoc.id;
78
+
}
79
+
80
+
81
+
export {handleResolver, docResolver, cleanHandle, handleAndPDSResolver, fetchPDSMooverDIDWeb};
+276
packages/moover/lib/backup.js
+276
packages/moover/lib/backup.js
···
1
+
import {Client, CredentialManager, ok} from '@atcute/client';
2
+
import {handleAndPDSResolver} from './atprotoUtils.js';
3
+
//Shows as unused, but is used in the return types
4
+
import {ComPdsmooverBackupDescribeServer} from '@pds-moover/lexicons';
5
+
6
+
/**
7
+
* JSDoc type-only import to avoid runtime import errors in the browser.
8
+
* @typedef {import('@atcute/lexicons').InferXRPCBodyOutput} InferXRPCBodyOutput
9
+
*/
10
+
11
+
12
+
/**
13
+
* Logic to sign up and manage backups for pdsmoover.com (or your own selfhosted instance)
14
+
*/
15
+
class BackupService {
16
+
/**
17
+
*
18
+
* @param backupDidWeb {string} - The did:web for the xrpc service for backups, defaults to did:web:pdsmoover.com
19
+
*/
20
+
constructor(backupDidWeb = 'did:web:pdsmoover.com') {
21
+
/**
22
+
*
23
+
* @type {Client}
24
+
*/
25
+
this.atCuteClient = null;
26
+
/**
27
+
*
28
+
* @type {CredentialManager}
29
+
*/
30
+
this.atCuteCredentialManager = null;
31
+
32
+
/**
33
+
* The did:web for the xrpc service for backups, defaults to pdsmoover.com
34
+
* @type {string}
35
+
*/
36
+
this.backupDidWeb = backupDidWeb;
37
+
}
38
+
39
+
40
+
/**
41
+
* Logs in and returns the backup status.
42
+
* To use the rest of the BackupService, it is assumed that this has ran first,
43
+
* and the user has successfully signed up. A successful login is a returned null if the user has not signed up.
44
+
* or the backup status if they are
45
+
*
46
+
* If the server requires 2FA,
47
+
* it will throw with error.error === 'AuthFactorTokenRequired'.
48
+
* @param identifier {string} handle or did
49
+
* @param password {string}
50
+
* @param {function|null} onStatus - a function that takes a string used to update the UI.
51
+
* Like (status) => console.log(status)
52
+
* @param twoFactorCode {string|null}
53
+
*
54
+
* @returns {Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>|null>}
55
+
*/
56
+
async loginAndStatus(identifier, password, onStatus = null, twoFactorCode = null) {
57
+
let {pds} = await handleAndPDSResolver(identifier);
58
+
59
+
60
+
const manager = new CredentialManager({
61
+
service: pds
62
+
});
63
+
64
+
65
+
const rpc = new Client({
66
+
handler: manager,
67
+
proxy: {
68
+
did: this.backupDidWeb,
69
+
serviceId: '#repo_backup'
70
+
}
71
+
});
72
+
73
+
try {
74
+
if (onStatus) onStatus('Signing in…');
75
+
76
+
let loginInput = {
77
+
identifier,
78
+
password,
79
+
80
+
};
81
+
if (twoFactorCode) {
82
+
loginInput.code = twoFactorCode;
83
+
}
84
+
await manager.login(loginInput);
85
+
86
+
87
+
// Make the client/manager available regardless of repo status so we can sign up if needed.
88
+
this.atCuteClient = rpc;
89
+
this.atCuteCredentialManager = manager;
90
+
91
+
if (onStatus) onStatus('Checking backup status');
92
+
const result = await rpc.get('com.pdsmoover.backup.getRepoStatus', {
93
+
params: {
94
+
did: manager.session.did.toString()
95
+
}
96
+
});
97
+
if (result.ok) {
98
+
return result.data;
99
+
} else {
100
+
switch (result.data.error) {
101
+
case 'RepoNotFound':
102
+
return null;
103
+
default:
104
+
throw result.data.error;
105
+
}
106
+
107
+
}
108
+
} catch (err) {
109
+
throw err;
110
+
}
111
+
}
112
+
113
+
/**
114
+
* Signs the user up for backups with the service
115
+
* @param onStatus
116
+
* @returns {Promise<void>}
117
+
*/
118
+
async signUp(onStatus = null) {
119
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
120
+
throw new Error('Not signed in');
121
+
}
122
+
if (onStatus) onStatus('Creating backup registration…');
123
+
await ok(
124
+
this.atCuteClient.post('com.pdsmoover.backup.signUp', {
125
+
as: null,
126
+
})
127
+
);
128
+
if (onStatus) onStatus('Backup registration complete');
129
+
//No return if successful
130
+
}
131
+
132
+
/**
133
+
* Requests a PLC token to be sent to the user's email, needed to add a new rotation key
134
+
* @returns {Promise<void>}
135
+
*/
136
+
async requestAPlcToken() {
137
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
138
+
throw new Error('Not signed in');
139
+
}
140
+
const rpc = new Client({
141
+
handler: this.atCuteCredentialManager,
142
+
});
143
+
144
+
let response = await rpc.post('com.atproto.identity.requestPlcOperationSignature', {
145
+
as: null,
146
+
});
147
+
if (!response.ok) {
148
+
throw new Error(response.data?.message || 'Failed to request PLC token');
149
+
}
150
+
}
151
+
152
+
/**
153
+
* Adds a new rotation to the users did document. Assumes you are already signed in.
154
+
*
155
+
* WARNING: This will overwrite any existing rotation keys with the new one at the top, and the PDS key as the second one
156
+
* @param plcToken {string} - PLC token from the user's email that was sent from requestAPlcToken
157
+
* @param rotationKey {string} - The new rotation key to add to the user's did document
158
+
* @returns {Promise<void>}
159
+
*/
160
+
async addANewRotationKey(plcToken, rotationKey) {
161
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
162
+
throw new Error('Not signed in');
163
+
}
164
+
165
+
166
+
const rpc = new Client({
167
+
handler: this.atCuteCredentialManager,
168
+
});
169
+
170
+
let getDidCredentials = await rpc.get('com.atproto.identity.getRecommendedDidCredentials');
171
+
172
+
if (getDidCredentials.ok) {
173
+
const pdsProvidedRotationKeys = getDidCredentials.data.rotationKeys ?? [];
174
+
const updatedRotationKeys = [rotationKey, ...pdsProvidedRotationKeys];
175
+
176
+
const credentials = {
177
+
...getDidCredentials.data,
178
+
rotationKeys: updatedRotationKeys,
179
+
};
180
+
181
+
const signDocRes = await rpc.post('com.atproto.identity.signPlcOperation', {
182
+
input: {
183
+
token: plcToken,
184
+
...credentials,
185
+
}
186
+
});
187
+
188
+
if (signDocRes.ok) {
189
+
const submitDocRes = await rpc.post('com.atproto.identity.submitPlcOperation', {
190
+
input: signDocRes.data,
191
+
as: null,
192
+
});
193
+
194
+
if (!submitDocRes.ok) {
195
+
throw new Error(submitDocRes.data?.message || 'Failed to submit PLC operation');
196
+
}
197
+
198
+
} else {
199
+
throw new Error(signDocRes.data?.message || 'Failed to sign PLC operation');
200
+
}
201
+
202
+
203
+
} else {
204
+
throw new Error(getDidCredentials.data?.message || 'Failed to get status');
205
+
}
206
+
}
207
+
208
+
209
+
/**
210
+
*
211
+
* Gets the current status of the user's backup repository.
212
+
*
213
+
* @param onStatus {function|null} - a function that takes a string used to update the UI.
214
+
* @returns {Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>>}
215
+
*/
216
+
async getUsersRepoStatus(onStatus = null) {
217
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
218
+
throw new Error('Not signed in');
219
+
}
220
+
if (onStatus) onStatus('Refreshing backup status…');
221
+
const result = await this.atCuteClient.get('com.pdsmoover.backup.getRepoStatus', {
222
+
params: {did: this.atCuteCredentialManager.session.did.toString()}
223
+
});
224
+
if (result.ok) {
225
+
return result.data;
226
+
} else {
227
+
throw new Error(result.data?.message || 'Failed to get status');
228
+
}
229
+
}
230
+
231
+
/**
232
+
* Requests a backup to be run immediately for the signed-in user. Usually does, depend on the server's backup queue
233
+
* @param onStatus
234
+
* @returns {Promise<boolean>}
235
+
*/
236
+
async runBackupNow(onStatus = null) {
237
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
238
+
throw new Error('Not signed in');
239
+
}
240
+
if (onStatus) onStatus('Requesting backup…');
241
+
const res = await this.atCuteClient.post('com.pdsmoover.backup.requestBackup', {as: null, data: {}});
242
+
if (res.ok) {
243
+
if (onStatus) onStatus('Backup requested.');
244
+
return true;
245
+
} else {
246
+
const err = res.data;
247
+
if (err?.error === 'Timeout') {
248
+
throw {error: 'Timeout', message: err?.message || 'Please wait a few minutes before requesting again.'};
249
+
}
250
+
throw new Error(err?.message || 'Failed to request backup');
251
+
}
252
+
}
253
+
254
+
/**
255
+
* Remove (delete) the signed-in user's backup repository. this also deletes all the user's backup data.
256
+
* @param onStatus
257
+
* @returns {Promise<boolean>}
258
+
*/
259
+
async removeRepo(onStatus = null) {
260
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
261
+
throw new Error('Not signed in');
262
+
}
263
+
if (onStatus) onStatus('Deleting backup repository…');
264
+
const res = await this.atCuteClient.post('com.pdsmoover.backup.removeRepo', {as: null, data: {}});
265
+
if (res.ok) {
266
+
if (onStatus) onStatus('Backup repository deleted.');
267
+
return true;
268
+
} else {
269
+
const err = res.data;
270
+
throw new Error(err?.message || 'Failed to delete backup repository');
271
+
}
272
+
}
273
+
}
274
+
275
+
276
+
export {BackupService};
+17
packages/moover/lib/main.js
+17
packages/moover/lib/main.js
···
1
+
import {Migrator} from './pdsmoover.js';
2
+
import {MissingBlobs} from './missingBlobs.js';
3
+
import {BackupService} from './backup.js';
4
+
import {PlcOps} from './plc-ops.js';
5
+
import {Restore} from './restore.js';
6
+
import {handleAndPDSResolver} from './atprotoUtils.js';
7
+
8
+
export {
9
+
Migrator,
10
+
MissingBlobs,
11
+
BackupService,
12
+
PlcOps,
13
+
Restore,
14
+
handleAndPDSResolver,
15
+
16
+
}
17
+
+193
packages/moover/lib/missingBlobs.js
+193
packages/moover/lib/missingBlobs.js
···
1
+
import {AtpAgent} from '@atproto/api';
2
+
import {handleAndPDSResolver} from './atprotoUtils.js';
3
+
4
+
5
+
/**
6
+
* Class to help find missing blobs from the did's previous PDS and import them into the current PDS
7
+
*/
8
+
class MissingBlobs {
9
+
10
+
constructor() {
11
+
/**
12
+
* The user's current PDS agent
13
+
* @type {AtpAgent}
14
+
*/
15
+
this.currentPdsAgent = null;
16
+
/**
17
+
* The user's old PDS agent
18
+
* @type {AtpAgent}
19
+
*/
20
+
this.oldPdsAgent = null;
21
+
/**
22
+
* the user's did
23
+
* @type {string|null}
24
+
*/
25
+
this.did = null;
26
+
/**
27
+
* The user's current PDS url
28
+
* @type {null}
29
+
*/
30
+
this.currentPdsUrl = null;
31
+
/**
32
+
* A list of the missing cids blobs from the old PDS. In this case if a retry upload fails it gets put in this array for the ui
33
+
* @type {string[]}
34
+
*/
35
+
this.missingBlobs = [];
36
+
37
+
}
38
+
39
+
/**
40
+
* Logs the user into the current PDS and gets the account status
41
+
* @param handle {string}
42
+
* @param password {string}
43
+
* @param twoFactorCode {string|null}
44
+
* @returns {Promise<{accountStatus: OutputSchema, missingBlobsCount: number}>}
45
+
*/
46
+
async currentAgentLogin(
47
+
handle,
48
+
password,
49
+
twoFactorCode = null,
50
+
) {
51
+
let {usersDid, pds} = await handleAndPDSResolver(handle);
52
+
this.did = usersDid;
53
+
this.currentPdsUrl = pds;
54
+
const agent = new AtpAgent({
55
+
service: pds,
56
+
});
57
+
58
+
if (twoFactorCode === null) {
59
+
await agent.login({identifier: usersDid, password});
60
+
} else {
61
+
await agent.login({identifier: usersDid, password: password, authFactorToken: twoFactorCode});
62
+
}
63
+
64
+
this.currentPdsAgent = agent;
65
+
66
+
const result = await agent.com.atproto.server.checkAccountStatus();
67
+
const missingBlobs = await this.currentPdsAgent.com.atproto.repo.listMissingBlobs({
68
+
limit: 10,
69
+
});
70
+
return {accountStatus: result.data, missingBlobsCount: missingBlobs.data.blobs.length};
71
+
}
72
+
73
+
/**
74
+
* Logs into the old PDS and gets the account status.
75
+
* Does not need a handle
76
+
* since it is assumed the user has already logged in with the current PDS and we are using their did
77
+
* @param password {string}
78
+
* @param twoFactorCode {string|null}
79
+
* @param pdsUrl {string|null} - If you know the url of the old PDS you can pass it in here. If not it will be guessed at from plc ops
80
+
* @returns {Promise<void>}
81
+
*/
82
+
async oldAgentLogin(
83
+
password,
84
+
twoFactorCode = null,
85
+
pdsUrl = null,
86
+
) {
87
+
let oldPds = null;
88
+
89
+
if (pdsUrl === null) {
90
+
const response = await fetch(`https://plc.directory/${this.did}/log`);
91
+
let auditLog = await response.json();
92
+
auditLog = auditLog.reverse();
93
+
let debugCount = 0;
94
+
for (const entry of auditLog) {
95
+
console.log(`Loop: ${debugCount++}`);
96
+
console.log(entry);
97
+
if (entry.services) {
98
+
if (entry.services.atproto_pds) {
99
+
if (entry.services.atproto_pds.type === 'AtprotoPersonalDataServer') {
100
+
const pds = entry.services.atproto_pds.endpoint;
101
+
console.log(`Found PDS: ${pds}`);
102
+
if (pds.toLowerCase() !== this.currentPdsUrl.toLowerCase()) {
103
+
oldPds = pds;
104
+
break;
105
+
}
106
+
}
107
+
}
108
+
}
109
+
}
110
+
if (oldPds === null) {
111
+
throw new Error('Could not find your old PDS');
112
+
}
113
+
} else {
114
+
oldPds = pdsUrl;
115
+
}
116
+
117
+
const agent = new AtpAgent({
118
+
service: oldPds,
119
+
});
120
+
121
+
if (twoFactorCode === null) {
122
+
await agent.login({identifier: this.did, password});
123
+
} else {
124
+
await agent.login({identifier: this.did, password: password, authFactorToken: twoFactorCode});
125
+
}
126
+
this.oldPdsAgent = agent;
127
+
}
128
+
129
+
/**
130
+
* Gets the missing blobs from the old PDS and uploads them to the current PDS
131
+
* @param statusUpdateHandler {function} - A function to update the status of the migration. This is useful for showing the user the progress of the migration
132
+
* @returns {Promise<{accountStatus: OutputSchema, missingBlobsCount: number}>}
133
+
*/
134
+
async migrateMissingBlobs(statusUpdateHandler) {
135
+
if (this.currentPdsAgent === null) {
136
+
throw new Error('Current PDS agent is not set');
137
+
}
138
+
if (this.oldPdsAgent === null) {
139
+
throw new Error('Old PDS agent is not set');
140
+
}
141
+
statusUpdateHandler('Starting to import blobs...');
142
+
143
+
let totalMissingBlobs = 0;
144
+
let missingBlobCursor = undefined;
145
+
let missingUploadedBlobs = 0;
146
+
147
+
do {
148
+
149
+
const missingBlobs = await this.currentPdsAgent.com.atproto.repo.listMissingBlobs({
150
+
cursor: missingBlobCursor,
151
+
limit: 1000,
152
+
});
153
+
totalMissingBlobs += missingBlobs.data.blobs.length;
154
+
155
+
for (const recordBlob of missingBlobs.data.blobs) {
156
+
try {
157
+
158
+
const blobRes = await this.oldPdsAgent.com.atproto.sync.getBlob({
159
+
did: this.did,
160
+
cid: recordBlob.cid,
161
+
});
162
+
let result = await this.currentPdsAgent.com.atproto.repo.uploadBlob(blobRes.data, {
163
+
encoding: blobRes.headers['content-type'],
164
+
});
165
+
166
+
if (result.status === 429) {
167
+
statusUpdateHandler(`You are being rate limited. Will need to try again later to get the rest of the blobs. Migrated blobs: ${missingUploadedBlobs}/${totalMissingBlobs}`);
168
+
}
169
+
170
+
if (missingUploadedBlobs % 2 === 0) {
171
+
statusUpdateHandler(`Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs} (The total may increase as we find more)`);
172
+
}
173
+
missingUploadedBlobs++;
174
+
} catch (error) {
175
+
console.error(error);
176
+
this.missingBlobs.push(recordBlob.cid);
177
+
}
178
+
}
179
+
missingBlobCursor = missingBlobs.data.cursor;
180
+
} while (missingBlobCursor);
181
+
182
+
const accountStatus = await this.currentPdsAgent.com.atproto.server.checkAccountStatus();
183
+
const missingBlobs = await this.currentPdsAgent.com.atproto.repo.listMissingBlobs({
184
+
limit: 10,
185
+
});
186
+
return {accountStatus: accountStatus.data, missingBlobsCount: missingBlobs.data.blobs.length};
187
+
188
+
189
+
}
190
+
191
+
}
192
+
193
+
export {MissingBlobs};
+389
packages/moover/lib/pdsmoover.js
+389
packages/moover/lib/pdsmoover.js
···
1
+
import {docResolver, cleanHandle, handleResolver} from './atprotoUtils.js';
2
+
import {AtpAgent} from '@atproto/api';
3
+
4
+
5
+
function safeStatusUpdate(statusUpdateHandler, status) {
6
+
if (statusUpdateHandler) {
7
+
statusUpdateHandler(status);
8
+
}
9
+
}
10
+
11
+
/**
12
+
* Handles normal PDS Migrations between two PDSs that are both up.
13
+
* On pdsmoover.com this is the logic for the MOOver
14
+
*/
15
+
class Migrator {
16
+
constructor() {
17
+
/** @type {AtpAgent} */
18
+
this.oldAgent = null;
19
+
/** @type {AtpAgent} */
20
+
this.newAgent = null;
21
+
/** @type {[string]} */
22
+
this.missingBlobs = [];
23
+
//State for reruns
24
+
/** @type {boolean} */
25
+
this.createNewAccount = true;
26
+
/** @type {boolean} */
27
+
this.migrateRepo = true;
28
+
/** @type {boolean} */
29
+
this.migrateBlobs = true;
30
+
/** @type {boolean} */
31
+
this.migrateMissingBlobs = true;
32
+
/** @type {boolean} */
33
+
this.migratePrefs = true;
34
+
/** @type {boolean} */
35
+
this.migratePlcRecord = true;
36
+
}
37
+
38
+
/**
39
+
* This migrator is pretty cut and dry and makes a few assumptions
40
+
* 1. You are using the same password between each account
41
+
* 2. If this command fails for something like oauth 2fa code it throws an error and expects the same values when ran again.
42
+
* 3. You can control which "actions" happen by setting the class variables to false.
43
+
* 4. Each instance of the class is assumed to be for a single migration
44
+
* @param {string} oldHandle - The handle you use on your old pds, something like alice.bsky.social
45
+
* @param {string} password - Your password for your current login. Has to be your real password, no app password. When setting up a new account we reuse it as well for that account
46
+
* @param {string} newPdsUrl - The new URL for your pds. Like https://coolnewpds.com
47
+
* @param {string} newEmail - The email you want to use on the new pds (can be the same as the previous one as long as it's not already being used on the new pds)
48
+
* @param {string} newHandle - The new handle you want, like alice.bsky.social, or if you already have a domain name set as a handle can use it myname.com.
49
+
* @param {string|null} inviteCode - The invite code you got from the PDS you are migrating to. If null does not include one
50
+
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI. Like (status) => console.log(status)
51
+
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
52
+
*/
53
+
async migrate(oldHandle, password, newPdsUrl, newEmail, newHandle, inviteCode, statusUpdateHandler = null, twoFactorCode = null) {
54
+
//Leaving this logic that either sets the agent to bsky.social, or the PDS since it's what I found worked best for migrations.
55
+
// handleAndPDSResolver should be able to handle it, but there have been edge cases and this was what worked best
56
+
oldHandle = cleanHandle(oldHandle);
57
+
let oldAgent;
58
+
let usersDid;
59
+
//If it's a bsky handle just go with the entryway and let it sort everything
60
+
if (oldHandle.endsWith('.bsky.social')) {
61
+
oldAgent = new AtpAgent({service: 'https://bsky.social'});
62
+
const publicAgent = new AtpAgent({service: 'https://public.api.bsky.app'});
63
+
const resolveIdentityFromEntryway = await publicAgent.com.atproto.identity.resolveHandle({handle: oldHandle});
64
+
usersDid = resolveIdentityFromEntryway.data.did;
65
+
66
+
} else {
67
+
//Resolves the did and finds the did document for the old PDS
68
+
safeStatusUpdate(statusUpdateHandler, 'Resolving old PDS');
69
+
usersDid = await handleResolver.resolve(oldHandle);
70
+
const didDoc = await docResolver.resolve(usersDid);
71
+
safeStatusUpdate(statusUpdateHandler, 'Resolving did document and finding your current PDS URL');
72
+
73
+
let oldPds;
74
+
try {
75
+
oldPds = didDoc.service.filter(s => s.type === 'AtprotoPersonalDataServer')[0].serviceEndpoint;
76
+
} catch (error) {
77
+
console.error(error);
78
+
throw new Error('Could not find a PDS in the DID document.');
79
+
}
80
+
81
+
oldAgent = new AtpAgent({
82
+
service: oldPds,
83
+
});
84
+
85
+
}
86
+
87
+
safeStatusUpdate(statusUpdateHandler, 'Logging you in to the old PDS');
88
+
//Login to the old PDS
89
+
if (twoFactorCode === null) {
90
+
await oldAgent.login({identifier: oldHandle, password});
91
+
} else {
92
+
await oldAgent.login({identifier: oldHandle, password: password, authFactorToken: twoFactorCode});
93
+
}
94
+
95
+
safeStatusUpdate(statusUpdateHandler, 'Checking that the new PDS is an actual PDS (if the url is wrong this takes a while to error out)');
96
+
const newAgent = new AtpAgent({service: newPdsUrl});
97
+
const newHostDesc = await newAgent.com.atproto.server.describeServer();
98
+
if (this.createNewAccount) {
99
+
const newHostWebDid = newHostDesc.data.did;
100
+
101
+
safeStatusUpdate(statusUpdateHandler, 'Creating a new account on the new PDS');
102
+
103
+
const createAuthResp = await oldAgent.com.atproto.server.getServiceAuth({
104
+
aud: newHostWebDid,
105
+
lxm: 'com.atproto.server.createAccount',
106
+
});
107
+
const serviceJwt = createAuthResp.data.token;
108
+
109
+
let createAccountRequest = {
110
+
did: usersDid,
111
+
handle: newHandle,
112
+
email: newEmail,
113
+
password: password,
114
+
};
115
+
if (inviteCode) {
116
+
createAccountRequest.inviteCode = inviteCode;
117
+
}
118
+
const createNewAccount = await newAgent.com.atproto.server.createAccount(
119
+
createAccountRequest,
120
+
{
121
+
headers: {authorization: `Bearer ${serviceJwt}`},
122
+
encoding: 'application/json',
123
+
});
124
+
125
+
if (createNewAccount.data.did !== usersDid.toString()) {
126
+
throw new Error('Did not create the new account with the same did as the old account');
127
+
}
128
+
}
129
+
safeStatusUpdate(statusUpdateHandler, 'Logging in with the new account');
130
+
131
+
await newAgent.login({
132
+
identifier: usersDid,
133
+
password: password,
134
+
});
135
+
136
+
if (this.migrateRepo) {
137
+
safeStatusUpdate(statusUpdateHandler, 'Migrating your repo');
138
+
const repoRes = await oldAgent.com.atproto.sync.getRepo({did: usersDid});
139
+
await newAgent.com.atproto.repo.importRepo(repoRes.data, {
140
+
encoding: 'application/vnd.ipld.car',
141
+
});
142
+
}
143
+
144
+
let newAccountStatus = await newAgent.com.atproto.server.checkAccountStatus();
145
+
146
+
if (this.migrateBlobs) {
147
+
safeStatusUpdate(statusUpdateHandler, 'Migrating your blobs');
148
+
149
+
let blobCursor = undefined;
150
+
let uploadedBlobs = 0;
151
+
do {
152
+
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${uploadedBlobs}/${newAccountStatus.data.expectedBlobs}`);
153
+
154
+
const listedBlobs = await oldAgent.com.atproto.sync.listBlobs({
155
+
did: usersDid,
156
+
cursor: blobCursor,
157
+
limit: 100,
158
+
});
159
+
160
+
for (const cid of listedBlobs.data.cids) {
161
+
try {
162
+
const blobRes = await oldAgent.com.atproto.sync.getBlob({
163
+
did: usersDid,
164
+
cid,
165
+
});
166
+
await newAgent.com.atproto.repo.uploadBlob(blobRes.data, {
167
+
encoding: blobRes.headers['content-type'],
168
+
});
169
+
uploadedBlobs++;
170
+
if (uploadedBlobs % 10 === 0) {
171
+
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${uploadedBlobs}/${newAccountStatus.data.expectedBlobs}`);
172
+
}
173
+
} catch (error) {
174
+
console.error(error);
175
+
}
176
+
}
177
+
blobCursor = listedBlobs.data.cursor;
178
+
} while (blobCursor);
179
+
}
180
+
181
+
if (this.migrateMissingBlobs) {
182
+
newAccountStatus = await newAgent.com.atproto.server.checkAccountStatus();
183
+
if (newAccountStatus.data.expectedBlobs !== newAccountStatus.data.importedBlobs) {
184
+
let totalMissingBlobs = newAccountStatus.data.expectedBlobs - newAccountStatus.data.importedBlobs;
185
+
safeStatusUpdate(statusUpdateHandler, 'Looks like there are some missing blobs. Going to try and upload them now.');
186
+
//Probably should be shared between main blob uploader, but eh
187
+
let missingBlobCursor = undefined;
188
+
let missingUploadedBlobs = 0;
189
+
do {
190
+
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs}`);
191
+
192
+
const missingBlobs = await newAgent.com.atproto.repo.listMissingBlobs({
193
+
cursor: missingBlobCursor,
194
+
limit: 100,
195
+
});
196
+
197
+
for (const recordBlob of missingBlobs.data.blobs) {
198
+
try {
199
+
200
+
const blobRes = await oldAgent.com.atproto.sync.getBlob({
201
+
did: usersDid,
202
+
cid: recordBlob.cid,
203
+
});
204
+
await newAgent.com.atproto.repo.uploadBlob(blobRes.data, {
205
+
encoding: blobRes.headers['content-type'],
206
+
});
207
+
if (missingUploadedBlobs % 10 === 0) {
208
+
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs}`);
209
+
}
210
+
missingUploadedBlobs++;
211
+
} catch (error) {
212
+
//TODO silently logging prob should list them so user can manually download
213
+
console.error(error);
214
+
this.missingBlobs.push(recordBlob.cid);
215
+
}
216
+
}
217
+
missingBlobCursor = missingBlobs.data.cursor;
218
+
} while (missingBlobCursor);
219
+
220
+
}
221
+
}
222
+
if (this.migratePrefs) {
223
+
const prefs = await oldAgent.app.bsky.actor.getPreferences();
224
+
await newAgent.app.bsky.actor.putPreferences(prefs.data);
225
+
}
226
+
227
+
this.oldAgent = oldAgent;
228
+
this.newAgent = newAgent;
229
+
230
+
if (this.migratePlcRecord) {
231
+
await oldAgent.com.atproto.identity.requestPlcOperationSignature();
232
+
safeStatusUpdate(statusUpdateHandler, 'Please check your email for a PLC token');
233
+
}
234
+
}
235
+
236
+
/**
237
+
* Sign and submits the PLC operation to officially migrate the account
238
+
* @param {string} token - the PLC token sent in the email. If you're just wanting to run this rerun migrate with all the flags set as false except for migratePlcRecord
239
+
* @param additionalRotationKeysToAdd {string[]} - additional rotation keys to add in addition to the ones provided by the new PDS.
240
+
* @returns {Promise<void>}
241
+
*/
242
+
async signPlcOperation(token, additionalRotationKeysToAdd = []) {
243
+
const getDidCredentials =
244
+
await this.newAgent.com.atproto.identity.getRecommendedDidCredentials();
245
+
const pdsProvidedRotationKeys = getDidCredentials.data.rotationKeys ?? [];
246
+
// Prepend any additional rotation keys (e.g., user-added keys, newly created key) so they appear above the new PDS rotation key
247
+
const rotationKeys = [...(additionalRotationKeysToAdd || []), ...pdsProvidedRotationKeys];
248
+
if (!rotationKeys) {
249
+
throw new Error('No rotation key provided from the new PDS');
250
+
}
251
+
const credentials = {
252
+
...getDidCredentials.data,
253
+
rotationKeys: rotationKeys,
254
+
};
255
+
256
+
257
+
const plcOp = await this.oldAgent.com.atproto.identity.signPlcOperation({
258
+
token: token,
259
+
...credentials,
260
+
});
261
+
262
+
await this.newAgent.com.atproto.identity.submitPlcOperation({
263
+
operation: plcOp.data.operation,
264
+
});
265
+
266
+
await this.newAgent.com.atproto.server.activateAccount();
267
+
await this.oldAgent.com.atproto.server.deactivateAccount({});
268
+
}
269
+
270
+
/**
271
+
* Using this method assumes the Migrator class was constructed new and this was called.
272
+
* Find the user's previous PDS from the PLC op logs,
273
+
* logs in and deactivates their old account if it was found still active.
274
+
*
275
+
* @param oldHandle {string}
276
+
* @param oldPassword {string}
277
+
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI.
278
+
* Like (status) => console.log(status)
279
+
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
280
+
* @returns {Promise<void>}
281
+
*/
282
+
async deactivateOldAccount(oldHandle, oldPassword, statusUpdateHandler = null, twoFactorCode = null) {
283
+
//Leaving this logic that either sets the agent to bsky.social, or the PDS since it's what I found worked best for migrations.
284
+
// handleAndPDSResolver should be able to handle it, but there have been edge cases and this was what worked best oldHandle = cleanHandle(oldHandle);
285
+
let usersDid;
286
+
//If it's a bsky handle just go with the entryway and let it sort everything
287
+
if (oldHandle.endsWith('.bsky.social')) {
288
+
const publicAgent = new AtpAgent({service: 'https://public.api.bsky.app'});
289
+
const resolveIdentityFromEntryway = await publicAgent.com.atproto.identity.resolveHandle({handle: oldHandle});
290
+
usersDid = resolveIdentityFromEntryway.data.did;
291
+
} else {
292
+
//Resolves the did and finds the did document for the old PDS
293
+
safeStatusUpdate(statusUpdateHandler, 'Resolving did from handle');
294
+
usersDid = await handleResolver.resolve(oldHandle);
295
+
}
296
+
297
+
const didDoc = await docResolver.resolve(usersDid);
298
+
let currentPds;
299
+
try {
300
+
currentPds = didDoc.service.filter(s => s.type === 'AtprotoPersonalDataServer')[0].serviceEndpoint;
301
+
} catch (error) {
302
+
console.error(error);
303
+
throw new Error('Could not find a PDS in the DID document.');
304
+
}
305
+
306
+
const plcLogRequest = await fetch(`https://plc.directory/${usersDid}/log`);
307
+
const plcLog = await plcLogRequest.json();
308
+
let pdsBeforeCurrent = '';
309
+
for (const log of plcLog) {
310
+
try {
311
+
const pds = log.services.atproto_pds.endpoint;
312
+
if (pds.toLowerCase() === currentPds.toLowerCase()) {
313
+
console.log('Found the PDS before the current one');
314
+
break;
315
+
}
316
+
pdsBeforeCurrent = pds;
317
+
} catch (e) {
318
+
console.log(e);
319
+
}
320
+
}
321
+
if (pdsBeforeCurrent === '') {
322
+
throw new Error('Could not find the PDS before the current one');
323
+
}
324
+
325
+
let oldAgent = new AtpAgent({service: pdsBeforeCurrent});
326
+
safeStatusUpdate(statusUpdateHandler, `Logging you in to the old PDS: ${pdsBeforeCurrent}`);
327
+
//Login to the old PDS
328
+
if (twoFactorCode === null) {
329
+
await oldAgent.login({identifier: oldHandle, password: oldPassword});
330
+
} else {
331
+
await oldAgent.login({identifier: oldHandle, password: oldPassword, authFactorToken: twoFactorCode});
332
+
}
333
+
safeStatusUpdate(statusUpdateHandler, 'Checking this isn\'t your current PDS');
334
+
if (pdsBeforeCurrent === currentPds) {
335
+
throw new Error('This is your current PDS. Login to your old account username and password');
336
+
}
337
+
338
+
let currentAccountStatus = await oldAgent.com.atproto.server.checkAccountStatus();
339
+
if (!currentAccountStatus.data.activated) {
340
+
safeStatusUpdate(statusUpdateHandler, 'All good. Your old account is not activated.');
341
+
}
342
+
safeStatusUpdate(statusUpdateHandler, 'Deactivating your OLD account');
343
+
await oldAgent.com.atproto.server.deactivateAccount({});
344
+
safeStatusUpdate(statusUpdateHandler, 'Successfully deactivated your OLD account');
345
+
}
346
+
347
+
/**
348
+
* Signs the logged-in user in this.newAgent for backups with PDS MOOver. This is usually called after migrate and signPlcOperation are successful
349
+
*
350
+
* @param {string} didWeb
351
+
* @returns {Promise<void>}
352
+
*/
353
+
async signUpForBackupsFromMigration(didWeb = 'did:web:pdsmoover.com') {
354
+
355
+
//Manually grabbing the jwt and making a call with fetch cause for the life of me I could not figure out
356
+
//how you used @atproto/api to make a call for proxying
357
+
const url = `${this.newAgent.serviceUrl.origin}/xrpc/com.pdsmoover.backup.signUp`;
358
+
359
+
const accessJwt = this.newAgent?.session?.accessJwt;
360
+
if (!accessJwt) {
361
+
throw new Error('Missing access token for authorization');
362
+
}
363
+
364
+
const res = await fetch(url, {
365
+
method: 'POST',
366
+
headers: {
367
+
'Authorization': `Bearer ${accessJwt}`,
368
+
'Content-Type': 'application/json',
369
+
'Accept': 'application/json',
370
+
'atproto-proxy': `${didWeb}#repo_backup`,
371
+
},
372
+
body: JSON.stringify({}),
373
+
});
374
+
375
+
if (!res.ok) {
376
+
let bodyText = '';
377
+
try {
378
+
bodyText = await res.text();
379
+
} catch {
380
+
}
381
+
throw new Error(`Backup signup failed: ${res.status} ${res.statusText}${bodyText ? ` - ${bodyText}` : ''}`);
382
+
}
383
+
384
+
//No return the success is all that is needed, if there's an error it will throw
385
+
}
386
+
}
387
+
388
+
export {Migrator};
389
+
+292
packages/moover/lib/plc-ops.js
+292
packages/moover/lib/plc-ops.js
···
1
+
/**
2
+
* JSDoc type-only import to avoid runtime import errors in the browser.
3
+
* @typedef {import('@atcute/did-plc').defs} defs
4
+
* @typedef {import('@atcute/did-plc').normalizeOp} normalizeOp
5
+
* @typedef {import('@atcute/did-plc').Operation} Operation
6
+
* @typedef {import('@atcute/did-plc').CompatibleOperation} CompatibleOperation
7
+
* @typedef {import('@atcute/did-plc').IndexedEntryLog} IndexedEntryLog
8
+
* @typedef {import('@atcute/did-plc').IndexedEntry} IndexedEntry
9
+
*/
10
+
11
+
import {defs, normalizeOp} from '@atcute/did-plc';
12
+
import {P256PrivateKey, parsePrivateMultikey, Secp256k1PrivateKey, Secp256k1PrivateKeyExportable} from '@atcute/crypto';
13
+
import * as CBOR from '@atcute/cbor';
14
+
import {fromBase16, toBase64Url} from '@atcute/multibase';
15
+
16
+
17
+
// Helper to base64url-encode JSON
18
+
const jsonToB64Url = (obj) => {
19
+
const enc = new TextEncoder();
20
+
const json = JSON.stringify(obj);
21
+
return toBase64Url(enc.encode(json));
22
+
};
23
+
24
+
/**
25
+
* Class to help with various PLC operations
26
+
*/
27
+
class PlcOps {
28
+
/**
29
+
*
30
+
* @param plcDirectoryUrl {string} - The url of the plc directory, defaults to https://plc.directory
31
+
*/
32
+
constructor(plcDirectoryUrl = 'https://plc.directory') {
33
+
/**
34
+
* The url of the plc directory
35
+
* @type {string}
36
+
*/
37
+
this.plcDirectoryUrl = plcDirectoryUrl;
38
+
}
39
+
40
+
/**
41
+
* Gets the current rotation keys for a user via their last PlC operation
42
+
* @param did
43
+
* @returns {Promise<string[]>}
44
+
*/
45
+
async getCurrentRotationKeysForUser(did) {
46
+
const logs = await this.getPlcAuditLogs(did);
47
+
const {lastOperation} = this.getLastPlcOp(logs);
48
+
return lastOperation.rotationKeys || [];
49
+
}
50
+
51
+
/**
52
+
* Gets the last PlC operation for a user from the plc directory
53
+
* @param did
54
+
* @returns {Promise<{lastOperation: Operation, base: any}>}
55
+
*/
56
+
async getLastPlcOpFromPlc(did) {
57
+
const logs = await this.getPlcAuditLogs(did);
58
+
return this.getLastPlcOp(logs);
59
+
}
60
+
61
+
/**
62
+
*
63
+
* @param logs {IndexedEntryLog}
64
+
* @returns {{lastOperation: Operation, base: IndexedEntry}}
65
+
*/
66
+
getLastPlcOp(logs) {
67
+
const lastOp = logs.at(-1);
68
+
return {lastOperation: normalizeOp(lastOp.operation), base: lastOp};
69
+
}
70
+
71
+
72
+
/**
73
+
* Gets the plc audit logs for a user from the plc directory
74
+
* @param did
75
+
* @returns {Promise<IndexedEntryLog>}
76
+
*/
77
+
async getPlcAuditLogs(did) {
78
+
const response = await fetch(`${this.plcDirectoryUrl}/${did}/log/audit`);
79
+
if (!response.ok) {
80
+
throw new Error(`got response ${response.status}`);
81
+
}
82
+
83
+
const json = await response.json();
84
+
return defs.indexedEntryLog.parse(json);
85
+
}
86
+
87
+
/**
88
+
* Creates a new secp256k1 key that can be used for either rotation or verification key
89
+
* @returns {Promise<{privateKey: string, publicKey: `did:key:${string}`}>}
90
+
*/
91
+
async createANewSecp256k1() {
92
+
let keypair = await Secp256k1PrivateKeyExportable.createKeypair();
93
+
let publicKey = await keypair.exportPublicKey('did');
94
+
let privateKey = await keypair.exportPrivateKey('multikey');
95
+
return {
96
+
privateKey,
97
+
publicKey
98
+
};
99
+
}
100
+
101
+
102
+
/**
103
+
* Signs a new operation with the provided signing key, and information and submits it to the plc directory
104
+
* @param did {string} - The user's did
105
+
* @param signingRotationKey { P256PrivateKey|Secp256k1PrivateKey} - The keypair to sign the op with
106
+
* @param alsoKnownAs {string[]}
107
+
* @param rotationKeys {string[]}
108
+
* @param pds {string}
109
+
* @param verificationKey {string} - The public verification key
110
+
* @param prev {string} - The previous valid operation's cid.
111
+
* @returns {Promise<void>}
112
+
*/
113
+
async signAndPublishNewOp(did, signingRotationKey, alsoKnownAs, rotationKeys, pds, verificationKey, prev) {
114
+
115
+
const rotationKeysToUse = [...new Set(rotationKeys)];
116
+
if (!rotationKeysToUse) {
117
+
throw new Error('No rotation keys were found to be added to the PLC');
118
+
}
119
+
120
+
if (rotationKeysToUse.length > 5) {
121
+
throw new Error('You can only add up to 5 rotation keys to the PLC');
122
+
}
123
+
124
+
const operation = {
125
+
type: 'plc_operation',
126
+
prev,
127
+
alsoKnownAs,
128
+
rotationKeys: rotationKeysToUse,
129
+
services: {
130
+
atproto_pds: {
131
+
type: 'AtprotoPersonalDataServer',
132
+
endpoint: pds
133
+
}
134
+
},
135
+
verificationMethods: {
136
+
atproto: verificationKey
137
+
}
138
+
};
139
+
const opBytes = CBOR.encode(operation);
140
+
const sigBytes = await signingRotationKey.sign(opBytes);
141
+
142
+
const signature = toBase64Url(sigBytes);
143
+
144
+
const signedOperation = {
145
+
...operation,
146
+
sig: signature,
147
+
};
148
+
149
+
await this.pushPlcOperation(did, signedOperation);
150
+
}
151
+
152
+
/**
153
+
* Takes a multi or hex based private key and returns a keypair
154
+
* @param privateKeyString {string}
155
+
* @param type {string} - secp256k1 or p256, needed if the private key is hex based, can be assumed if it's a multikey
156
+
* @returns {Promise<{type: string, didPublicKey: `did:key:${string}`, keypair: P256PrivateKey|Secp256k1PrivateKey}>}
157
+
*/
158
+
async getKeyPair(privateKeyString, type = 'secp256k1') {
159
+
const HEX_REGEX = /^[0-9a-f]+$/i;
160
+
const MULTIKEY_REGEX = /^z[a-km-zA-HJ-NP-Z1-9]+$/;
161
+
let keypair = undefined;
162
+
163
+
if (HEX_REGEX.test(privateKeyString)) {
164
+
const privateKeyBytes = fromBase16(privateKeyString);
165
+
166
+
switch (type) {
167
+
case 'p256': {
168
+
keypair = await P256PrivateKey.importRaw(privateKeyBytes);
169
+
break;
170
+
}
171
+
case 'secp256k1': {
172
+
keypair = await Secp256k1PrivateKey.importRaw(privateKeyBytes);
173
+
break;
174
+
}
175
+
default: {
176
+
throw new Error(`unsupported "${type}" type`);
177
+
}
178
+
}
179
+
} else if (MULTIKEY_REGEX.test(privateKeyString)) {
180
+
181
+
const match = parsePrivateMultikey(privateKeyString);
182
+
const privateKeyBytes = match.privateKeyBytes;
183
+
184
+
switch (match.type) {
185
+
case 'p256': {
186
+
keypair = await P256PrivateKey.importRaw(privateKeyBytes);
187
+
console.log(keypair);
188
+
break;
189
+
}
190
+
case 'secp256k1': {
191
+
keypair = await Secp256k1PrivateKey.importRaw(privateKeyBytes);
192
+
break;
193
+
}
194
+
default: {
195
+
throw new Error(`unsupported "${type}" type`);
196
+
}
197
+
}
198
+
} else {
199
+
throw new Error('unknown input format');
200
+
}
201
+
return {
202
+
type: 'private_key',
203
+
didPublicKey: await keypair.exportPublicKey('did'),
204
+
keypair: keypair,
205
+
};
206
+
}
207
+
208
+
/**
209
+
* Submits a new operation to the plc directory
210
+
* @param did {string} - The user's did
211
+
* @param operation
212
+
* @returns {Promise<void>}
213
+
*/
214
+
async pushPlcOperation(did, operation) {
215
+
const response = await fetch(`${this.plcDirectoryUrl}/${did}`, {
216
+
method: 'post',
217
+
headers: {
218
+
'content-type': 'application/json',
219
+
},
220
+
body: JSON.stringify(operation),
221
+
});
222
+
223
+
const headers = response.headers;
224
+
if (!response.ok) {
225
+
const type = headers.get('content-type');
226
+
227
+
if (type?.includes('application/json')) {
228
+
const json = await response.json();
229
+
if (typeof json === 'object' && json !== null && typeof json.message === 'string') {
230
+
throw new Error(json.message);
231
+
}
232
+
}
233
+
234
+
throw new Error(`got http ${response.status} from plc`);
235
+
}
236
+
};
237
+
238
+
239
+
/**
240
+
* Creates a new service auth token for a user. This is what is used to create a new account on a PDS for your did
241
+
*
242
+
* @param iss The user's did
243
+
* @param aud The did:web, if it's a PDS it's usually from /xrpc/com.atproto.server.describeServer
244
+
* @param keypair The keypair to sign with only supporting ES256K atm
245
+
* @param lxm The lxm which is usually com.atproto.server.createAccount for creating a new account
246
+
* @returns {Promise<string>}
247
+
*/
248
+
async createANewServiceAuthToken(iss, aud, keypair, lxm) {
249
+
250
+
251
+
// Compute iat/exp defaults (60s window like reference: MINUTE/1e3)
252
+
const iat = Math.floor(Date.now() / 1e3);
253
+
const exp = iat + 60;
254
+
255
+
// Generate a 16-byte hex jti
256
+
const jti = (() => {
257
+
const bytes = new Uint8Array(16);
258
+
// crypto in browser or node; fall back safely
259
+
(globalThis.crypto || window.crypto).getRandomValues(bytes);
260
+
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
261
+
})();
262
+
263
+
264
+
// Build header and payload (omit undefined fields)
265
+
// Just defaulting to ES256K since p256 was not importing on firefox
266
+
const header = {typ: 'JWT', alg: 'ES256K'};
267
+
const payload = {};
268
+
payload.iat = iat;
269
+
payload.iss = iss;
270
+
payload.aud = aud;
271
+
payload.exp = exp;
272
+
payload.lxm = lxm;
273
+
payload.jti = jti;
274
+
275
+
const headerB64 = jsonToB64Url(header);
276
+
const payloadB64 = jsonToB64Url(payload);
277
+
const toSignStr = `${headerB64}.${payloadB64}`;
278
+
279
+
// Sign
280
+
const toSignBytes = new TextEncoder().encode(toSignStr);
281
+
const sigBytes = await keypair.sign(toSignBytes);
282
+
283
+
// Return compact JWS
284
+
const sigB64 = toBase64Url(sigBytes);
285
+
return `${toSignStr}.${sigB64}`;
286
+
}
287
+
288
+
289
+
}
290
+
291
+
292
+
export {PlcOps};
+331
packages/moover/lib/restore.js
+331
packages/moover/lib/restore.js
···
1
+
/**
2
+
* @typedef {import('@atcute/did-plc').Operation} Operation
3
+
*/
4
+
import {P256PrivateKey, Secp256k1PrivateKey} from '@atcute/crypto';
5
+
import {handleAndPDSResolver} from './atprotoUtils.js';
6
+
import {PlcOps} from './plc-ops.js';
7
+
import {normalizeOp} from '@atcute/did-plc';
8
+
import {AtpAgent} from '@atproto/api';
9
+
import {Secp256k1PrivateKeyExportable} from '@atcute/crypto';
10
+
import * as CBOR from '@atcute/cbor';
11
+
import {toBase64Url} from '@atcute/multibase';
12
+
13
+
class Restore {
14
+
15
+
/**
16
+
*
17
+
* @param pdsMooverInstance {string} - The url of the pds moover instance to restore from. Defaults to https://pdsmover.com
18
+
*/
19
+
constructor(pdsMooverInstance = 'https://pdsmover.com') {
20
+
/**
21
+
* If you want to use a different plc directory create your own instance of the plc ops class and pass it in here
22
+
* @type {PlcOps} */
23
+
this.plcOps = new PlcOps();
24
+
25
+
/**
26
+
* This is the base url for the pds moover instance used to restore the files from a backup.
27
+
* @type {string}
28
+
*/
29
+
this.pdsMooverInstance = pdsMooverInstance
30
+
31
+
/**
32
+
* To keep it simple, only uses secp256k for the temp verification key that is used to create the new account on the new PDS
33
+
* and is temporarily assigned to the user's account on PLC
34
+
* @type {null|Secp256k1PrivateKeyExportable}
35
+
*/
36
+
this.tempVerificationKeypair = null;
37
+
38
+
/** @type {AtpAgent} */
39
+
this.atpAgent = null;
40
+
41
+
/**
42
+
* The keypair that is used to sign the plc operation
43
+
* @type {null|{type: string, didPublicKey: `did:key:${string}`, keypair: P256PrivateKey|Secp256k1PrivateKey}}
44
+
*/
45
+
this.recoveryRotationKeyPair = null;
46
+
47
+
/**
48
+
* If this is true we are just restoring the repo and blobs. Ideally for rerunning a restore process after account recovery
49
+
* @type {boolean}
50
+
*/
51
+
this.RestoreFromBackup = true;
52
+
53
+
/**
54
+
* If set to true then it will do the account recovery. Writes a temp key to the did doc,
55
+
* create a new account on the new pds, and then submit a new plc op for the pds to have control (finishes the migration, can always restore the backup later)
56
+
* @type {boolean}
57
+
*/
58
+
this.AccountRecovery = true;
59
+
}
60
+
61
+
/**
62
+
* Recovers an account with the users rotation key and restores the repo from a PDS MOOver backup
63
+
* This method can fail, and the account was still recovered, it's best to check the PLC logs to see where an account stands before reruns
64
+
* @param rotationKey {string} - The users private rotation key, can be a multi key or hex key
65
+
* @param rotationKeyType {string} - The type of the key, secp256k1 or p256. Required if the key is in hex format, defaults to secp256k1
66
+
* @param currentHandleOrDid {string} - The users current handle or did, if they don't have a DNS record it will have to be their did for success
67
+
* @param newPDS {string} - The new PDS url, like https://coolnewpds.com
68
+
* @param newHandle {string} - Can be the users DNS handle if it is already setup with their did, if not it's bob.mypds.com
69
+
* @param newPassword {string} - The new password for the new account
70
+
* @param newEmail {string} - The new email for the new account
71
+
* @param inviteCode {string|null} - The invite code for the new PDS if it requires one
72
+
* @param cidToRestoreTo {string|null} - The cid of the plc op to restore to, used mostly to revert a fraudulent plc op. Want to give it the last valid operations cid
73
+
* @param onStatus {function|null} - A function that takes a string used to update the UI. Like (status) => console.log(status)
74
+
* @returns {Promise<void>} If there is a failure during restoring the back up (after the status Success! Restoring your repo...) then your account is most likely
75
+
* recovered and future runs need to have the RestoreFromBackup flag set to true and AccountRecovery set to false.
76
+
*/
77
+
async recover(
78
+
rotationKey,
79
+
rotationKeyType = 'secp256k1',
80
+
currentHandleOrDid,
81
+
newPDS,
82
+
newHandle,
83
+
newPassword,
84
+
newEmail,
85
+
inviteCode,
86
+
cidToRestoreTo = null,
87
+
onStatus = null) {
88
+
89
+
if (onStatus) onStatus('Resolving your handle...');
90
+
91
+
let {usersDid} = await handleAndPDSResolver(currentHandleOrDid);
92
+
93
+
if (onStatus) onStatus('Checking that the new PDS is an actual PDS (if the url is wrong, this takes a while to error out)');
94
+
this.atpAgent = new AtpAgent({service: newPDS});
95
+
const newHostDesc = await this.atpAgent.com.atproto.server.describeServer();
96
+
97
+
98
+
//Check to see if the user already has a repo on the new PDS, if they do no reason to try and restore via the plc operations
99
+
try {
100
+
await this.atpAgent.com.atproto.repo.describeRepo({repo: usersDid.toString()});
101
+
//If we got this far and there is a repo on the new PDS with the users did, we can just move on and restore the files.
102
+
//We do not want to mess with the plc ops if we dont have to
103
+
this.AccountRecovery = false;
104
+
105
+
} catch (error) {
106
+
console.error(error);
107
+
let parsedError = error.error;
108
+
if (parsedError === 'RepoDeactivated') {
109
+
//Ideally should mean they already have a repo on the new PDS and we just need to restore the files
110
+
this.AccountRecovery = false;
111
+
}
112
+
//This is the error we want to see, anything else throw
113
+
if (parsedError !== 'RepoNotFound') {
114
+
throw error;
115
+
}
116
+
}
117
+
118
+
//We need to double check that the new handle has not been taken, if it has we need to throw an error
119
+
//We care a bit more because we do not want any unnecessary plc ops to be created
120
+
try {
121
+
let resolveHandle = await this.atpAgent.com.atproto.identity.resolveHandle({handle: newHandle});
122
+
if (resolveHandle.data.did === usersDid.toString()) {
123
+
//This was originally setting the AccountRecovery to false, which works if it is resolved via .well-known, but not dns
124
+
//The idea was to check and see if the handle has been taken. just leaving for now since it does that check and if the user owns the handle
125
+
//their did should be set anyhow
126
+
127
+
} else {
128
+
//There is a repo with that name and it's not the users did,
129
+
throw new Error('The new handle is already taken, please select a different handle');
130
+
}
131
+
} catch (error) {
132
+
// Going to silently log this and just assume the handle has not been taken.
133
+
console.error(error);
134
+
if (error.message.startsWith('The new handle')) {
135
+
//it's not our custom error, so we can just throw it
136
+
throw error;
137
+
}
138
+
139
+
}
140
+
141
+
if (this.AccountRecovery) {
142
+
143
+
if (onStatus) onStatus('Validating your private rotation key is in the correct format...');
144
+
145
+
this.recoveryRotationKeyPair = await this.plcOps.getKeyPair(rotationKey, rotationKeyType);
146
+
147
+
148
+
if (onStatus) onStatus('Resolving PlC operation logs...');
149
+
150
+
/** @type {Operation} */
151
+
let baseOpForSigning = null;
152
+
let opPrevCid = null;
153
+
154
+
//This is for reversals against a rogue plc op and you want to restore to a specific cid in the audit log
155
+
if (cidToRestoreTo) {
156
+
let auditLogs = await this.plcOps.getPlcAuditLogs(usersDid);
157
+
for (const log of auditLogs) {
158
+
if (log.cid === cidToRestoreTo) {
159
+
baseOpForSigning = normalizeOp(log.operation);
160
+
opPrevCid = log.cid;
161
+
break;
162
+
}
163
+
}
164
+
if (!baseOpForSigning) {
165
+
throw new Error('Could not find the cid in the audit logs');
166
+
}
167
+
} else {
168
+
let {lastOperation, base} = await this.plcOps.getLastPlcOpFromPlc(usersDid);
169
+
opPrevCid = base.cid;
170
+
baseOpForSigning = lastOperation;
171
+
}
172
+
173
+
if (onStatus) onStatus('Preparing to switch to a temp atproto key...');
174
+
if (this.tempVerificationKeypair == null) {
175
+
if (onStatus) onStatus('Creating a new temp atproto key...');
176
+
this.tempVerificationKeypair = await Secp256k1PrivateKeyExportable.createKeypair();
177
+
}
178
+
//Just defaulting to the user's recovery key for now. Advance cases will be something else
179
+
//Maybe just a new ui to edit the PLC doc in a limited capacity, but sinc ethis is a temp plc op i don't think it's needed
180
+
let tempRotationKeys = [this.recoveryRotationKeyPair.didPublicKey];
181
+
182
+
if (onStatus) onStatus('Modifying the PLC OP for recovery...');
183
+
//A temp plc op for control of the atproto key to create a serviceAuth and new account on the new PDS
184
+
await this.plcOps.signAndPublishNewOp(
185
+
usersDid,
186
+
this.recoveryRotationKeyPair.keypair,
187
+
baseOpForSigning.alsoKnownAs,
188
+
tempRotationKeys,
189
+
newPDS,
190
+
await this.tempVerificationKeypair.exportPublicKey('did'),
191
+
opPrevCid);
192
+
193
+
194
+
if (onStatus) onStatus('Creating your new account on the new PDS...');
195
+
let serviceAuthToken = await this.plcOps.createANewServiceAuthToken(usersDid, newHostDesc.data.did, this.tempVerificationKeypair, 'com.atproto.server.createAccount');
196
+
197
+
let createAccountRequest = {
198
+
did: usersDid,
199
+
handle: newHandle,
200
+
email: newEmail,
201
+
password: newPassword,
202
+
};
203
+
if (inviteCode) {
204
+
createAccountRequest.inviteCode = inviteCode;
205
+
}
206
+
const _ = await this.atpAgent.com.atproto.server.createAccount(
207
+
createAccountRequest,
208
+
{
209
+
headers: {authorization: `Bearer ${serviceAuthToken}`},
210
+
encoding: 'application/json',
211
+
});
212
+
}
213
+
214
+
await this.atpAgent.login({
215
+
identifier: usersDid,
216
+
password: newPassword,
217
+
});
218
+
219
+
if (this.AccountRecovery) {
220
+
//Moving the user offically to the new PDS
221
+
if (onStatus) onStatus('Signing the papers...');
222
+
let {base} = await this.plcOps.getLastPlcOpFromPlc(usersDid);
223
+
await this.signRestorePlcOperation(usersDid, [this.recoveryRotationKeyPair.didPublicKey], base.cid);
224
+
}
225
+
226
+
if (this.RestoreFromBackup) {
227
+
if (onStatus) onStatus('Success! Restoring your repo...');
228
+
const pdsMoover = new AtpAgent({service: this.pdsMooverInstance});
229
+
const repoRes = await pdsMoover.com.atproto.sync.getRepo({did: usersDid});
230
+
await this.atpAgent.com.atproto.repo.importRepo(repoRes.data, {
231
+
encoding: 'application/vnd.ipld.car',
232
+
});
233
+
234
+
if (onStatus) onStatus('Restoring your blobs...');
235
+
236
+
//Using the missing endpoint to findout what's missing then the PDS MOOver endpoint to restore
237
+
let totalMissingBlobs = 0;
238
+
let missingBlobCursor = undefined;
239
+
let missingUploadedBlobs = 0;
240
+
241
+
do {
242
+
243
+
const missingBlobs = await this.atpAgent.com.atproto.repo.listMissingBlobs({
244
+
cursor: missingBlobCursor,
245
+
limit: 1000,
246
+
});
247
+
totalMissingBlobs += missingBlobs.data.blobs.length;
248
+
249
+
for (const recordBlob of missingBlobs.data.blobs) {
250
+
try {
251
+
252
+
const blobRes = await pdsMoover.com.atproto.sync.getBlob({
253
+
did: usersDid,
254
+
cid: recordBlob.cid,
255
+
});
256
+
let result = await this.atpAgent.com.atproto.repo.uploadBlob(blobRes.data, {
257
+
encoding: blobRes.headers['content-type'],
258
+
});
259
+
260
+
261
+
if (missingUploadedBlobs % 2 === 0) {
262
+
if (onStatus) onStatus(`Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs} (The total may increase as we find more)`);
263
+
}
264
+
missingUploadedBlobs++;
265
+
} catch (error) {
266
+
console.error(error);
267
+
}
268
+
}
269
+
missingBlobCursor = missingBlobs.data.cursor;
270
+
} while (missingBlobCursor);
271
+
}
272
+
const accountStatus = await this.atpAgent.com.atproto.server.checkAccountStatus();
273
+
if (!accountStatus.data.activated) {
274
+
if (onStatus) onStatus('Activating your account...');
275
+
await this.atpAgent.com.atproto.server.activateAccount();
276
+
}
277
+
278
+
}
279
+
280
+
281
+
/**
282
+
* This method signs the plc operation over to the new PDS and activates the account
283
+
* Assumes you have already created a new account during the recovery process and logged in
284
+
* Uses the recommended did doc from the PDS as a base and adds the users rotation key to the rotation keys array
285
+
*
286
+
* @param usersDid
287
+
* @param additionalRotationKeysToAdd
288
+
* @param prevCid
289
+
* @returns {Promise<void>}
290
+
*/
291
+
async signRestorePlcOperation(usersDid, additionalRotationKeysToAdd = [], prevCid) {
292
+
const getDidCredentials =
293
+
await this.atpAgent.com.atproto.identity.getRecommendedDidCredentials();
294
+
295
+
const pdsProvidedRotationKeys = getDidCredentials.data.rotationKeys ?? [];
296
+
//Puts the provided rotation keys above the pds pro
297
+
const rotationKeys = [...new Set([...(additionalRotationKeysToAdd || []), ...pdsProvidedRotationKeys])];
298
+
if (!rotationKeys) {
299
+
throw new Error('No rotation keys were found to be added to the PLC');
300
+
}
301
+
302
+
if (rotationKeys.length > 5) {
303
+
throw new Error('You can only add up to 5 rotation keys to the PLC');
304
+
}
305
+
306
+
307
+
const plcOpToSubmit = {
308
+
type: 'plc_operation',
309
+
...getDidCredentials.data,
310
+
prev: prevCid,
311
+
rotationKeys: rotationKeys,
312
+
};
313
+
314
+
315
+
const opBytes = CBOR.encode(plcOpToSubmit);
316
+
const sigBytes = await this.recoveryRotationKeyPair.keypair.sign(opBytes);
317
+
318
+
const signature = toBase64Url(sigBytes);
319
+
320
+
const signedOperation = {
321
+
...plcOpToSubmit,
322
+
sig: signature,
323
+
};
324
+
325
+
await this.plcOps.pushPlcOperation(usersDid, signedOperation);
326
+
await this.atpAgent.com.atproto.server.activateAccount();
327
+
328
+
}
329
+
}
330
+
331
+
export {Restore};
+59
packages/moover/package.json
+59
packages/moover/package.json
···
1
+
{
2
+
"name": "@pds-moover/moover",
3
+
"version": "1.0.4",
4
+
"description": "Utilities for ATProto PDS migrations and recovery",
5
+
"repository": {
6
+
"type": "git",
7
+
"url": "https://tangled.org/@baileytownsend.dev/pds-moover",
8
+
"directory": "packages/moover"
9
+
},
10
+
"keywords": [
11
+
"atproto",
12
+
"pds",
13
+
"migration",
14
+
"recovery",
15
+
"PDS MOOver"
16
+
],
17
+
"author": "Bailey Townsend",
18
+
"license": "MIT",
19
+
"type": "module",
20
+
"files": [
21
+
"dist",
22
+
"types"
23
+
],
24
+
"main": "./dist/pds-moover.umd.cjs",
25
+
"module": "./dist/pds-moover.js",
26
+
"types": "./types/main.d.ts",
27
+
"exports": {
28
+
".": {
29
+
"types": "./types/main.d.ts",
30
+
"import": "./dist/pds-moover.js",
31
+
"require": "./dist/pds-moover.umd.cjs"
32
+
}
33
+
},
34
+
"scripts": {
35
+
"dev": "vite",
36
+
"build": "vite build",
37
+
"gen:types": "tsc -p .",
38
+
"preview": "vite preview"
39
+
},
40
+
"devDependencies": {
41
+
"eslint": "^9.34.0",
42
+
"eslint-plugin-import": "^2.32.0",
43
+
"vite": "^7.1.7"
44
+
},
45
+
"dependencies": {
46
+
"@atcute/cbor": "^2.2.7",
47
+
"@atcute/client": "^4.0.4",
48
+
"@atcute/crypto": "^2.2.5",
49
+
"@atcute/did-plc": "^0.1.7",
50
+
"@atcute/identity-resolver": "^1.1.3",
51
+
"@atcute/lexicons": "^1.2.2",
52
+
"@atcute/multibase": "^1.1.6",
53
+
"@atproto/api": "^0.16.7",
54
+
"@pds-moover/lexicons": "^1.0.0",
55
+
"alpinejs": "^3.15.0",
56
+
"vite-plugin-full-reload": "^1.2.0",
57
+
"vite-rs-plugin": "1.0.1"
58
+
}
59
+
}
+30
packages/moover/tsconfig.json
+30
packages/moover/tsconfig.json
···
1
+
{
2
+
"include": [
3
+
"lib/**/*"
4
+
],
5
+
"exclude": [
6
+
"node_modules",
7
+
"dist",
8
+
"types"
9
+
],
10
+
"compilerOptions": {
11
+
"allowJs": true,
12
+
"checkJs": false,
13
+
"declaration": true,
14
+
"emitDeclarationOnly": true,
15
+
"declarationMap": true,
16
+
"outDir": "types",
17
+
// or use "declarationDir": "types"
18
+
19
+
"target": "ES2022",
20
+
"lib": [
21
+
"ES2022"
22
+
],
23
+
// add "DOM" if you use browser APIs
24
+
"skipLibCheck": true,
25
+
"module": "ESNext",
26
+
"moduleResolution": "Bundler",
27
+
// or "NodeNext" depending on your setup
28
+
"rootDir": "lib"
29
+
}
30
+
}
+28
packages/moover/types/atprotoUtils.d.ts
+28
packages/moover/types/atprotoUtils.d.ts
···
1
+
export const handleResolver: CompositeHandleResolver;
2
+
export const docResolver: CompositeDidDocumentResolver<"plc" | "web">;
3
+
/**
4
+
* Cleans the handle of @ and some other unicode characters that used to show up when copied from the profile
5
+
* @param handle {string}
6
+
* @returns {string}
7
+
*/
8
+
export function cleanHandle(handle: string): string;
9
+
/**
10
+
* Convince helper to resolve a handle to a did and then find the PDS url from the did document.
11
+
*
12
+
* @param handle
13
+
* @returns {Promise<{usersDid: string, pds: string}>}
14
+
*/
15
+
export function handleAndPDSResolver(handle: any): Promise<{
16
+
usersDid: string;
17
+
pds: string;
18
+
}>;
19
+
/**
20
+
* Fetches the DID Web from the .well-known/did.json endpoint of the server.
21
+
* Legacy and was helpful if the web ui and server are on the same domain, not as useful now
22
+
* @param baseUrl
23
+
* @returns {Promise<*>}
24
+
*/
25
+
export function fetchPDSMooverDIDWeb(baseUrl: any): Promise<any>;
26
+
import { CompositeHandleResolver } from '@atcute/identity-resolver';
27
+
import { CompositeDidDocumentResolver } from '@atcute/identity-resolver';
28
+
//# sourceMappingURL=atprotoUtils.d.ts.map
+1
packages/moover/types/atprotoUtils.d.ts.map
+1
packages/moover/types/atprotoUtils.d.ts.map
···
1
+
{"version":3,"file":"atprotoUtils.d.ts","sourceRoot":"","sources":["../lib/atprotoUtils.js"],"names":[],"mappings":"AAOA,qDAQG;AAEH,sEAKG;AAEH;;;;GAIG;AACH,oCAHkB,MAAM,GACX,MAAM,CAMd;AAGL;;;;;GAKG;AACH,mDAFa,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,CAAC,CAqBpD;AAGD;;;;;GAKG;AACH,oDAFa,OAAO,CAAC,GAAC,CAAC,CAStB;wCAxEM,2BAA2B;6CAA3B,2BAA2B"}
+94
packages/moover/types/backup.d.ts
+94
packages/moover/types/backup.d.ts
···
1
+
/**
2
+
* JSDoc type-only import to avoid runtime import errors in the browser.
3
+
*/
4
+
export type InferXRPCBodyOutput = any;
5
+
/**
6
+
* JSDoc type-only import to avoid runtime import errors in the browser.
7
+
* @typedef {import('@atcute/lexicons').InferXRPCBodyOutput} InferXRPCBodyOutput
8
+
*/
9
+
/**
10
+
* Logic to sign up and manage backups for pdsmoover.com (or your own selfhosted instance)
11
+
*/
12
+
export class BackupService {
13
+
/**
14
+
*
15
+
* @param backupDidWeb {string} - The did:web for the xrpc service for backups, defaults to did:web:pdsmoover.com
16
+
*/
17
+
constructor(backupDidWeb?: string);
18
+
/**
19
+
*
20
+
* @type {Client}
21
+
*/
22
+
atCuteClient: Client;
23
+
/**
24
+
*
25
+
* @type {CredentialManager}
26
+
*/
27
+
atCuteCredentialManager: CredentialManager;
28
+
/**
29
+
* The did:web for the xrpc service for backups, defaults to pdsmoover.com
30
+
* @type {string}
31
+
*/
32
+
backupDidWeb: string;
33
+
/**
34
+
* Logs in and returns the backup status.
35
+
* To use the rest of the BackupService, it is assumed that this has ran first,
36
+
* and the user has successfully signed up. A successful login is a returned null if the user has not signed up.
37
+
* or the backup status if they are
38
+
*
39
+
* If the server requires 2FA,
40
+
* it will throw with error.error === 'AuthFactorTokenRequired'.
41
+
* @param identifier {string} handle or did
42
+
* @param password {string}
43
+
* @param {function|null} onStatus - a function that takes a string used to update the UI.
44
+
* Like (status) => console.log(status)
45
+
* @param twoFactorCode {string|null}
46
+
*
47
+
* @returns {Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>|null>}
48
+
*/
49
+
loginAndStatus(identifier: string, password: string, onStatus?: Function | null, twoFactorCode?: string | null): Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema["output"]> | null>;
50
+
/**
51
+
* Signs the user up for backups with the service
52
+
* @param onStatus
53
+
* @returns {Promise<void>}
54
+
*/
55
+
signUp(onStatus?: any): Promise<void>;
56
+
/**
57
+
* Requests a PLC token to be sent to the user's email, needed to add a new rotation key
58
+
* @returns {Promise<void>}
59
+
*/
60
+
requestAPlcToken(): Promise<void>;
61
+
/**
62
+
* Adds a new rotation to the users did document. Assumes you are already signed in.
63
+
*
64
+
* WARNING: This will overwrite any existing rotation keys with the new one at the top, and the PDS key as the second one
65
+
* @param plcToken {string} - PLC token from the user's email that was sent from requestAPlcToken
66
+
* @param rotationKey {string} - The new rotation key to add to the user's did document
67
+
* @returns {Promise<void>}
68
+
*/
69
+
addANewRotationKey(plcToken: string, rotationKey: string): Promise<void>;
70
+
/**
71
+
*
72
+
* Gets the current status of the user's backup repository.
73
+
*
74
+
* @param onStatus {function|null} - a function that takes a string used to update the UI.
75
+
* @returns {Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>>}
76
+
*/
77
+
getUsersRepoStatus(onStatus?: Function | null): Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema["output"]>>;
78
+
/**
79
+
* Requests a backup to be run immediately for the signed-in user. Usually does, depend on the server's backup queue
80
+
* @param onStatus
81
+
* @returns {Promise<boolean>}
82
+
*/
83
+
runBackupNow(onStatus?: any): Promise<boolean>;
84
+
/**
85
+
* Remove (delete) the signed-in user's backup repository. this also deletes all the user's backup data.
86
+
* @param onStatus
87
+
* @returns {Promise<boolean>}
88
+
*/
89
+
removeRepo(onStatus?: any): Promise<boolean>;
90
+
}
91
+
import { Client } from '@atcute/client';
92
+
import { CredentialManager } from '@atcute/client';
93
+
import { ComPdsmooverBackupDescribeServer } from '@pds-moover/lexicons';
94
+
//# sourceMappingURL=backup.d.ts.map
+1
packages/moover/types/backup.d.ts.map
+1
packages/moover/types/backup.d.ts.map
···
1
+
{"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../lib/backup.js"],"names":[],"mappings":";;;;AAKA;;;GAGG;AAGH;;GAEG;AACH;IACI;;;OAGG;IACH,2BAFwB,MAAM,EAmB7B;IAhBG;;;OAGG;IACH,cAFU,MAAM,CAEQ;IACxB;;;OAGG;IACH,yBAFU,iBAAiB,CAEQ;IAEnC;;;OAGG;IACH,cAFU,MAAM,CAEgB;IAIpC;;;;;;;;;;;;;;;OAeG;IACH,2BARsB,MAAM,YACR,MAAM,aACf,WAAS,IAAI,kBAEC,MAAM,GAAC,IAAI,GAEvB,OAAO,CAAC,mBAAmB,CAAC,gCAAgC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAC,IAAI,CAAC,CAyDpG;IAED;;;;OAIG;IACH,wBAFa,OAAO,CAAC,IAAI,CAAC,CAczB;IAED;;;OAGG;IACH,oBAFa,OAAO,CAAC,IAAI,CAAC,CAgBzB;IAED;;;;;;;OAOG;IACH,6BAJoB,MAAM,eACH,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAgDzB;IAGD;;;;;;OAMG;IACH,8BAHoB,WAAS,IAAI,GACpB,OAAO,CAAC,mBAAmB,CAAC,gCAAgC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAe/F;IAED;;;;OAIG;IACH,8BAFa,OAAO,CAAC,OAAO,CAAC,CAkB5B;IAED;;;;OAIG;IACH,4BAFa,OAAO,CAAC,OAAO,CAAC,CAe5B;CACJ;uBAhR2C,gBAAgB;kCAAhB,gBAAgB;iDAGb,sBAAsB"}
+8
packages/moover/types/main.d.ts
+8
packages/moover/types/main.d.ts
···
1
+
import { Migrator } from './pdsmoover.js';
2
+
import { MissingBlobs } from './missingBlobs.js';
3
+
import { BackupService } from './backup.js';
4
+
import { PlcOps } from './plc-ops.js';
5
+
import { Restore } from './restore.js';
6
+
import { handleAndPDSResolver } from './atprotoUtils.js';
7
+
export { Migrator, MissingBlobs, BackupService, PlcOps, Restore, handleAndPDSResolver };
8
+
//# sourceMappingURL=main.d.ts.map
+1
packages/moover/types/main.d.ts.map
+1
packages/moover/types/main.d.ts.map
···
1
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../lib/main.js"],"names":[],"mappings":"yBAAuB,gBAAgB;6BACZ,mBAAmB;8BAClB,aAAa;uBACpB,cAAc;wBACb,cAAc;qCACD,mBAAmB"}
+62
packages/moover/types/missingBlobs.d.ts
+62
packages/moover/types/missingBlobs.d.ts
···
1
+
/**
2
+
* Class to help find missing blobs from the did's previous PDS and import them into the current PDS
3
+
*/
4
+
export class MissingBlobs {
5
+
/**
6
+
* The user's current PDS agent
7
+
* @type {AtpAgent}
8
+
*/
9
+
currentPdsAgent: AtpAgent;
10
+
/**
11
+
* The user's old PDS agent
12
+
* @type {AtpAgent}
13
+
*/
14
+
oldPdsAgent: AtpAgent;
15
+
/**
16
+
* the user's did
17
+
* @type {string|null}
18
+
*/
19
+
did: string | null;
20
+
/**
21
+
* The user's current PDS url
22
+
* @type {null}
23
+
*/
24
+
currentPdsUrl: any;
25
+
/**
26
+
* A list of the missing cids blobs from the old PDS. In this case if a retry upload fails it gets put in this array for the ui
27
+
* @type {string[]}
28
+
*/
29
+
missingBlobs: string[];
30
+
/**
31
+
* Logs the user into the current PDS and gets the account status
32
+
* @param handle {string}
33
+
* @param password {string}
34
+
* @param twoFactorCode {string|null}
35
+
* @returns {Promise<{accountStatus: OutputSchema, missingBlobsCount: number}>}
36
+
*/
37
+
currentAgentLogin(handle: string, password: string, twoFactorCode?: string | null): Promise<{
38
+
accountStatus: OutputSchema;
39
+
missingBlobsCount: number;
40
+
}>;
41
+
/**
42
+
* Logs into the old PDS and gets the account status.
43
+
* Does not need a handle
44
+
* since it is assumed the user has already logged in with the current PDS and we are using their did
45
+
* @param password {string}
46
+
* @param twoFactorCode {string|null}
47
+
* @param pdsUrl {string|null} - If you know the url of the old PDS you can pass it in here. If not it will be guessed at from plc ops
48
+
* @returns {Promise<void>}
49
+
*/
50
+
oldAgentLogin(password: string, twoFactorCode?: string | null, pdsUrl?: string | null): Promise<void>;
51
+
/**
52
+
* Gets the missing blobs from the old PDS and uploads them to the current PDS
53
+
* @param statusUpdateHandler {function} - A function to update the status of the migration. This is useful for showing the user the progress of the migration
54
+
* @returns {Promise<{accountStatus: OutputSchema, missingBlobsCount: number}>}
55
+
*/
56
+
migrateMissingBlobs(statusUpdateHandler: Function): Promise<{
57
+
accountStatus: OutputSchema;
58
+
missingBlobsCount: number;
59
+
}>;
60
+
}
61
+
import { AtpAgent } from '@atproto/api';
62
+
//# sourceMappingURL=missingBlobs.d.ts.map
+1
packages/moover/types/missingBlobs.d.ts.map
+1
packages/moover/types/missingBlobs.d.ts.map
···
1
+
{"version":3,"file":"missingBlobs.d.ts","sourceRoot":"","sources":["../lib/missingBlobs.js"],"names":[],"mappings":"AAIA;;GAEG;AACH;IAGQ;;;OAGG;IACH,iBAFU,QAAQ,CAES;IAC3B;;;OAGG;IACH,aAFU,QAAQ,CAEK;IACvB;;;OAGG;IACH,KAFU,MAAM,GAAC,IAAI,CAEN;IACf;;;OAGG;IACH,mBAAyB;IACzB;;;OAGG;IACH,cAFU,MAAM,EAAE,CAEI;IAI1B;;;;;;OAMG;IACH,0BALkB,MAAM,YACJ,MAAM,kBACD,MAAM,GAAC,IAAI,GACvB,OAAO,CAAC;QAAC,aAAa,EAAE,YAAY,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAC,CAAC,CA2B7E;IAED;;;;;;;;OAQG;IACH,wBALoB,MAAM,kBACD,MAAM,GAAC,IAAI,WAClB,MAAM,GAAC,IAAI,GAChB,OAAO,CAAC,IAAI,CAAC,CA+CzB;IAED;;;;OAIG;IACH,oDAFa,OAAO,CAAC;QAAC,aAAa,EAAE,YAAY,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAC,CAAC,CAyD7E;CAEJ;yBA9LsB,cAAc"}
+69
packages/moover/types/pdsmoover.d.ts
+69
packages/moover/types/pdsmoover.d.ts
···
1
+
/**
2
+
* Handles normal PDS Migrations between two PDSs that are both up.
3
+
* On pdsmoover.com this is the logic for the MOOver
4
+
*/
5
+
export class Migrator {
6
+
/** @type {AtpAgent} */
7
+
oldAgent: AtpAgent;
8
+
/** @type {AtpAgent} */
9
+
newAgent: AtpAgent;
10
+
/** @type {[string]} */
11
+
missingBlobs: [string];
12
+
/** @type {boolean} */
13
+
createNewAccount: boolean;
14
+
/** @type {boolean} */
15
+
migrateRepo: boolean;
16
+
/** @type {boolean} */
17
+
migrateBlobs: boolean;
18
+
/** @type {boolean} */
19
+
migrateMissingBlobs: boolean;
20
+
/** @type {boolean} */
21
+
migratePrefs: boolean;
22
+
/** @type {boolean} */
23
+
migratePlcRecord: boolean;
24
+
/**
25
+
* This migrator is pretty cut and dry and makes a few assumptions
26
+
* 1. You are using the same password between each account
27
+
* 2. If this command fails for something like oauth 2fa code it throws an error and expects the same values when ran again.
28
+
* 3. You can control which "actions" happen by setting the class variables to false.
29
+
* 4. Each instance of the class is assumed to be for a single migration
30
+
* @param {string} oldHandle - The handle you use on your old pds, something like alice.bsky.social
31
+
* @param {string} password - Your password for your current login. Has to be your real password, no app password. When setting up a new account we reuse it as well for that account
32
+
* @param {string} newPdsUrl - The new URL for your pds. Like https://coolnewpds.com
33
+
* @param {string} newEmail - The email you want to use on the new pds (can be the same as the previous one as long as it's not already being used on the new pds)
34
+
* @param {string} newHandle - The new handle you want, like alice.bsky.social, or if you already have a domain name set as a handle can use it myname.com.
35
+
* @param {string|null} inviteCode - The invite code you got from the PDS you are migrating to. If null does not include one
36
+
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI. Like (status) => console.log(status)
37
+
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
38
+
*/
39
+
migrate(oldHandle: string, password: string, newPdsUrl: string, newEmail: string, newHandle: string, inviteCode: string | null, statusUpdateHandler?: Function | null, twoFactorCode?: string | null): Promise<void>;
40
+
/**
41
+
* Sign and submits the PLC operation to officially migrate the account
42
+
* @param {string} token - the PLC token sent in the email. If you're just wanting to run this rerun migrate with all the flags set as false except for migratePlcRecord
43
+
* @param additionalRotationKeysToAdd {string[]} - additional rotation keys to add in addition to the ones provided by the new PDS.
44
+
* @returns {Promise<void>}
45
+
*/
46
+
signPlcOperation(token: string, additionalRotationKeysToAdd?: string[]): Promise<void>;
47
+
/**
48
+
* Using this method assumes the Migrator class was constructed new and this was called.
49
+
* Find the user's previous PDS from the PLC op logs,
50
+
* logs in and deactivates their old account if it was found still active.
51
+
*
52
+
* @param oldHandle {string}
53
+
* @param oldPassword {string}
54
+
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI.
55
+
* Like (status) => console.log(status)
56
+
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
57
+
* @returns {Promise<void>}
58
+
*/
59
+
deactivateOldAccount(oldHandle: string, oldPassword: string, statusUpdateHandler?: Function | null, twoFactorCode?: string | null): Promise<void>;
60
+
/**
61
+
* Signs the logged-in user in this.newAgent for backups with PDS MOOver. This is usually called after migrate and signPlcOperation are successful
62
+
*
63
+
* @param {string} didWeb
64
+
* @returns {Promise<void>}
65
+
*/
66
+
signUpForBackupsFromMigration(didWeb?: string): Promise<void>;
67
+
}
68
+
import { AtpAgent } from '@atproto/api';
69
+
//# sourceMappingURL=pdsmoover.d.ts.map
+1
packages/moover/types/pdsmoover.d.ts.map
+1
packages/moover/types/pdsmoover.d.ts.map
···
1
+
{"version":3,"file":"pdsmoover.d.ts","sourceRoot":"","sources":["../lib/pdsmoover.js"],"names":[],"mappings":"AAUA;;;GAGG;AACH;IAEQ,uBAAuB;IACvB,UADW,QAAQ,CACC;IACpB,uBAAuB;IACvB,UADW,QAAQ,CACC;IACpB,uBAAuB;IACvB,cADW,CAAC,MAAM,CAAC,CACG;IAEtB,sBAAsB;IACtB,kBADW,OAAO,CACU;IAC5B,sBAAsB;IACtB,aADW,OAAO,CACK;IACvB,sBAAsB;IACtB,cADW,OAAO,CACM;IACxB,sBAAsB;IACtB,qBADW,OAAO,CACa;IAC/B,sBAAsB;IACtB,cADW,OAAO,CACM;IACxB,sBAAsB;IACtB,kBADW,OAAO,CACU;IAGhC;;;;;;;;;;;;;;OAcG;IACH,mBATW,MAAM,YACN,MAAM,aACN,MAAM,YACN,MAAM,aACN,MAAM,cACN,MAAM,GAAC,IAAI,wBACX,WAAS,IAAI,kBACb,MAAM,GAAC,IAAI,iBAuLrB;IAED;;;;;OAKG;IACH,wBAJW,MAAM,gCACsB,MAAM,EAAE,GAClC,OAAO,CAAC,IAAI,CAAC,CA4BzB;IAED;;;;;;;;;;;OAWG;IACH,gCAPqB,MAAM,eACJ,MAAM,wBAClB,WAAS,IAAI,kBAEb,MAAM,GAAC,IAAI,GACT,OAAO,CAAC,IAAI,CAAC,CAiEzB;IAED;;;;;OAKG;IACH,uCAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAkCzB;CACJ;yBAhYsB,cAAc"}
+121
packages/moover/types/plc-ops.d.ts
+121
packages/moover/types/plc-ops.d.ts
···
1
+
/**
2
+
* JSDoc type-only import to avoid runtime import errors in the browser.
3
+
*/
4
+
export type defs = typeof defs;
5
+
/**
6
+
* JSDoc type-only import to avoid runtime import errors in the browser.
7
+
*/
8
+
export type normalizeOp = any;
9
+
/**
10
+
* JSDoc type-only import to avoid runtime import errors in the browser.
11
+
*/
12
+
export type Operation = import("@atcute/did-plc").Operation;
13
+
/**
14
+
* JSDoc type-only import to avoid runtime import errors in the browser.
15
+
*/
16
+
export type CompatibleOperation = import("@atcute/did-plc").CompatibleOperation;
17
+
/**
18
+
* JSDoc type-only import to avoid runtime import errors in the browser.
19
+
*/
20
+
export type IndexedEntryLog = import("@atcute/did-plc").IndexedEntryLog;
21
+
/**
22
+
* JSDoc type-only import to avoid runtime import errors in the browser.
23
+
*/
24
+
export type IndexedEntry = import("@atcute/did-plc").IndexedEntry;
25
+
/**
26
+
* Class to help with various PLC operations
27
+
*/
28
+
export class PlcOps {
29
+
/**
30
+
*
31
+
* @param plcDirectoryUrl {string} - The url of the plc directory, defaults to https://plc.directory
32
+
*/
33
+
constructor(plcDirectoryUrl?: string);
34
+
/**
35
+
* The url of the plc directory
36
+
* @type {string}
37
+
*/
38
+
plcDirectoryUrl: string;
39
+
/**
40
+
* Gets the current rotation keys for a user via their last PlC operation
41
+
* @param did
42
+
* @returns {Promise<string[]>}
43
+
*/
44
+
getCurrentRotationKeysForUser(did: any): Promise<string[]>;
45
+
/**
46
+
* Gets the last PlC operation for a user from the plc directory
47
+
* @param did
48
+
* @returns {Promise<{lastOperation: Operation, base: any}>}
49
+
*/
50
+
getLastPlcOpFromPlc(did: any): Promise<{
51
+
lastOperation: Operation;
52
+
base: any;
53
+
}>;
54
+
/**
55
+
*
56
+
* @param logs {IndexedEntryLog}
57
+
* @returns {{lastOperation: Operation, base: IndexedEntry}}
58
+
*/
59
+
getLastPlcOp(logs: IndexedEntryLog): {
60
+
lastOperation: Operation;
61
+
base: IndexedEntry;
62
+
};
63
+
/**
64
+
* Gets the plc audit logs for a user from the plc directory
65
+
* @param did
66
+
* @returns {Promise<IndexedEntryLog>}
67
+
*/
68
+
getPlcAuditLogs(did: any): Promise<IndexedEntryLog>;
69
+
/**
70
+
* Creates a new secp256k1 key that can be used for either rotation or verification key
71
+
* @returns {Promise<{privateKey: string, publicKey: `did:key:${string}`}>}
72
+
*/
73
+
createANewSecp256k1(): Promise<{
74
+
privateKey: string;
75
+
publicKey: `did:key:${string}`;
76
+
}>;
77
+
/**
78
+
* Signs a new operation with the provided signing key, and information and submits it to the plc directory
79
+
* @param did {string} - The user's did
80
+
* @param signingRotationKey { P256PrivateKey|Secp256k1PrivateKey} - The keypair to sign the op with
81
+
* @param alsoKnownAs {string[]}
82
+
* @param rotationKeys {string[]}
83
+
* @param pds {string}
84
+
* @param verificationKey {string} - The public verification key
85
+
* @param prev {string} - The previous valid operation's cid.
86
+
* @returns {Promise<void>}
87
+
*/
88
+
signAndPublishNewOp(did: string, signingRotationKey: P256PrivateKey | Secp256k1PrivateKey, alsoKnownAs: string[], rotationKeys: string[], pds: string, verificationKey: string, prev: string): Promise<void>;
89
+
/**
90
+
* Takes a multi or hex based private key and returns a keypair
91
+
* @param privateKeyString {string}
92
+
* @param type {string} - secp256k1 or p256, needed if the private key is hex based, can be assumed if it's a multikey
93
+
* @returns {Promise<{type: string, didPublicKey: `did:key:${string}`, keypair: P256PrivateKey|Secp256k1PrivateKey}>}
94
+
*/
95
+
getKeyPair(privateKeyString: string, type?: string): Promise<{
96
+
type: string;
97
+
didPublicKey: `did:key:${string}`;
98
+
keypair: P256PrivateKey | Secp256k1PrivateKey;
99
+
}>;
100
+
/**
101
+
* Submits a new operation to the plc directory
102
+
* @param did {string} - The user's did
103
+
* @param operation
104
+
* @returns {Promise<void>}
105
+
*/
106
+
pushPlcOperation(did: string, operation: any): Promise<void>;
107
+
/**
108
+
* Creates a new service auth token for a user. This is what is used to create a new account on a PDS for your did
109
+
*
110
+
* @param iss The user's did
111
+
* @param aud The did:web, if it's a PDS it's usually from /xrpc/com.atproto.server.describeServer
112
+
* @param keypair The keypair to sign with only supporting ES256K atm
113
+
* @param lxm The lxm which is usually com.atproto.server.createAccount for creating a new account
114
+
* @returns {Promise<string>}
115
+
*/
116
+
createANewServiceAuthToken(iss: any, aud: any, keypair: any, lxm: any): Promise<string>;
117
+
}
118
+
import { defs } from '@atcute/did-plc';
119
+
import { P256PrivateKey } from '@atcute/crypto';
120
+
import { Secp256k1PrivateKey } from '@atcute/crypto';
121
+
//# sourceMappingURL=plc-ops.d.ts.map
+1
packages/moover/types/plc-ops.d.ts.map
+1
packages/moover/types/plc-ops.d.ts.map
···
1
+
{"version":3,"file":"plc-ops.d.ts","sourceRoot":"","sources":["../lib/plc-ops.js"],"names":[],"mappings":";;;;;;;;;;;wBAIa,OAAO,iBAAiB,EAAE,SAAS;;;;kCACnC,OAAO,iBAAiB,EAAE,mBAAmB;;;;8BAC7C,OAAO,iBAAiB,EAAE,eAAe;;;;2BACzC,OAAO,iBAAiB,EAAE,YAAY;AAgBnD;;GAEG;AACH;IACI;;;OAGG;IACH,8BAF2B,MAAM,EAQhC;IALG;;;OAGG;IACH,iBAFU,MAAM,CAEsB;IAG1C;;;;OAIG;IACH,yCAFa,OAAO,CAAC,MAAM,EAAE,CAAC,CAM7B;IAED;;;;OAIG;IACH,+BAFa,OAAO,CAAC;QAAC,aAAa,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAC,CAAC,CAK1D;IAED;;;;OAIG;IACH,mBAHgB,eAAe,GAClB;QAAC,aAAa,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,YAAY,CAAA;KAAC,CAK1D;IAGD;;;;OAIG;IACH,2BAFa,OAAO,CAAC,eAAe,CAAC,CAUpC;IAED;;;OAGG;IACH,uBAFa,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,WAAW,MAAM,EAAE,CAAA;KAAC,CAAC,CAUzE;IAGD;;;;;;;;;;OAUG;IACH,yBATe,MAAM,sBACU,cAAc,GAAC,mBAAmB,eAC1C,MAAM,EAAE,gBACP,MAAM,EAAE,OACjB,MAAM,mBACM,MAAM,QACjB,MAAM,GACT,OAAO,CAAC,IAAI,CAAC,CAuCzB;IAED;;;;;OAKG;IACH,6BAJ4B,MAAM,SAClB,MAAM,GACT,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,WAAW,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,cAAc,GAAC,mBAAmB,CAAA;KAAC,CAAC,CAkDnH;IAED;;;;;OAKG;IACH,sBAJe,MAAM,mBAER,OAAO,CAAC,IAAI,CAAC,CAwBzB;IAGD;;;;;;;;OAQG;IACH,wEAFa,OAAO,CAAC,MAAM,CAAC,CAwC3B;CAGJ;qBAtR+B,iBAAiB;+BACsD,gBAAgB;oCAAhB,gBAAgB"}
+79
packages/moover/types/restore.d.ts
+79
packages/moover/types/restore.d.ts
···
1
+
export type Operation = import("@atcute/did-plc").Operation;
2
+
export class Restore {
3
+
/**
4
+
*
5
+
* @param pdsMooverInstance {string} - The url of the pds moover instance to restore from. Defaults to https://pdsmover.com
6
+
*/
7
+
constructor(pdsMooverInstance?: string);
8
+
/**
9
+
* If you want to use a different plc directory create your own instance of the plc ops class and pass it in here
10
+
* @type {PlcOps} */
11
+
plcOps: PlcOps;
12
+
/**
13
+
* This is the base url for the pds moover instance used to restore the files from a backup.
14
+
* @type {string}
15
+
*/
16
+
pdsMooverInstance: string;
17
+
/**
18
+
* To keep it simple, only uses secp256k for the temp verification key that is used to create the new account on the new PDS
19
+
* and is temporarily assigned to the user's account on PLC
20
+
* @type {null|Secp256k1PrivateKeyExportable}
21
+
*/
22
+
tempVerificationKeypair: null | Secp256k1PrivateKeyExportable;
23
+
/** @type {AtpAgent} */
24
+
atpAgent: AtpAgent;
25
+
/**
26
+
* The keypair that is used to sign the plc operation
27
+
* @type {null|{type: string, didPublicKey: `did:key:${string}`, keypair: P256PrivateKey|Secp256k1PrivateKey}}
28
+
*/
29
+
recoveryRotationKeyPair: null | {
30
+
type: string;
31
+
didPublicKey: `did:key:${string}`;
32
+
keypair: P256PrivateKey | Secp256k1PrivateKey;
33
+
};
34
+
/**
35
+
* If this is true we are just restoring the repo and blobs. Ideally for rerunning a restore process after account recovery
36
+
* @type {boolean}
37
+
*/
38
+
RestoreFromBackup: boolean;
39
+
/**
40
+
* If set to true then it will do the account recovery. Writes a temp key to the did doc,
41
+
* create a new account on the new pds, and then submit a new plc op for the pds to have control (finishes the migration, can always restore the backup later)
42
+
* @type {boolean}
43
+
*/
44
+
AccountRecovery: boolean;
45
+
/**
46
+
* Recovers an account with the users rotation key and restores the repo from a PDS MOOver backup
47
+
* This method can fail, and the account was still recovered, it's best to check the PLC logs to see where an account stands before reruns
48
+
* @param rotationKey {string} - The users private rotation key, can be a multi key or hex key
49
+
* @param rotationKeyType {string} - The type of the key, secp256k1 or p256. Required if the key is in hex format, defaults to secp256k1
50
+
* @param currentHandleOrDid {string} - The users current handle or did, if they don't have a DNS record it will have to be their did for success
51
+
* @param newPDS {string} - The new PDS url, like https://coolnewpds.com
52
+
* @param newHandle {string} - Can be the users DNS handle if it is already setup with their did, if not it's bob.mypds.com
53
+
* @param newPassword {string} - The new password for the new account
54
+
* @param newEmail {string} - The new email for the new account
55
+
* @param inviteCode {string|null} - The invite code for the new PDS if it requires one
56
+
* @param cidToRestoreTo {string|null} - The cid of the plc op to restore to, used mostly to revert a fraudulent plc op. Want to give it the last valid operations cid
57
+
* @param onStatus {function|null} - A function that takes a string used to update the UI. Like (status) => console.log(status)
58
+
* @returns {Promise<void>} If there is a failure during restoring the back up (after the status Success! Restoring your repo...) then your account is most likely
59
+
* recovered and future runs need to have the RestoreFromBackup flag set to true and AccountRecovery set to false.
60
+
*/
61
+
recover(rotationKey: string, rotationKeyType: string, currentHandleOrDid: string, newPDS: string, newHandle: string, newPassword: string, newEmail: string, inviteCode: string | null, cidToRestoreTo?: string | null, onStatus?: Function | null): Promise<void>;
62
+
/**
63
+
* This method signs the plc operation over to the new PDS and activates the account
64
+
* Assumes you have already created a new account during the recovery process and logged in
65
+
* Uses the recommended did doc from the PDS as a base and adds the users rotation key to the rotation keys array
66
+
*
67
+
* @param usersDid
68
+
* @param additionalRotationKeysToAdd
69
+
* @param prevCid
70
+
* @returns {Promise<void>}
71
+
*/
72
+
signRestorePlcOperation(usersDid: any, additionalRotationKeysToAdd: any[], prevCid: any): Promise<void>;
73
+
}
74
+
import { PlcOps } from './plc-ops.js';
75
+
import { Secp256k1PrivateKeyExportable } from '@atcute/crypto';
76
+
import { AtpAgent } from '@atproto/api';
77
+
import { P256PrivateKey } from '@atcute/crypto';
78
+
import { Secp256k1PrivateKey } from '@atcute/crypto';
79
+
//# sourceMappingURL=restore.d.ts.map
+1
packages/moover/types/restore.d.ts.map
+1
packages/moover/types/restore.d.ts.map
···
1
+
{"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../lib/restore.js"],"names":[],"mappings":"wBACa,OAAO,iBAAiB,EAAE,SAAS;AAWhD;IAEI;;;OAGG;IACH,gCAF6B,MAAM,EA0ClC;IAvCG;;wBAEoB;IACpB,QADU,MAAM,CACU;IAE1B;;;OAGG;IACH,mBAFU,MAAM,CAE0B;IAE1C;;;;OAIG;IACH,yBAFU,IAAI,GAAC,6BAA6B,CAET;IAEnC,uBAAuB;IACvB,UADW,QAAQ,CACC;IAEpB;;;OAGG;IACH,yBAFU,IAAI,GAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,WAAW,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,cAAc,GAAC,mBAAmB,CAAA;KAAC,CAE1E;IAEnC;;;OAGG;IACH,mBAFU,OAAO,CAEY;IAE7B;;;;OAIG;IACH,iBAFU,OAAO,CAEU;IAG/B;;;;;;;;;;;;;;;OAeG;IACH,qBAbuB,MAAM,mBACF,MAAM,sBACH,MAAM,UAClB,MAAM,aACH,MAAM,eACJ,MAAM,YACT,MAAM,cACJ,MAAM,GAAC,IAAI,mBACP,MAAM,GAAC,IAAI,aACjB,WAAS,IAAI,GACpB,OAAO,CAAC,IAAI,CAAC,CA4MzB;IAGD;;;;;;;;;OASG;IACH,0FAFa,OAAO,CAAC,IAAI,CAAC,CAuCzB;CACJ;uBAnUoB,cAAc;8CAGS,gBAAgB;yBADrC,cAAc;+BAJa,gBAAgB;oCAAhB,gBAAgB"}
+28
packages/moover/vite.config.js
+28
packages/moover/vite.config.js
···
1
+
import {dirname, resolve} from 'node:path'
2
+
import {fileURLToPath} from 'node:url'
3
+
import {defineConfig} from 'vite'
4
+
5
+
const __dirname = dirname(fileURLToPath(import.meta.url))
6
+
7
+
export default defineConfig({
8
+
build: {
9
+
lib: {
10
+
entry: resolve(__dirname, 'lib/main.js'),
11
+
name: '@pds-moover/moover',
12
+
// the proper extensions will be added
13
+
fileName: 'pds-moover',
14
+
},
15
+
rollupOptions: {
16
+
// // make sure to externalize deps that shouldn't be bundled
17
+
// // into your library
18
+
// external: ['vue'],
19
+
// output: {
20
+
// // Provide global variables to use in the UMD build
21
+
// // for externalized deps
22
+
// globals: {
23
+
// vue: 'Vue',
24
+
// },
25
+
// },
26
+
},
27
+
},
28
+
})
+23
web-ui/.gitignore
+23
web-ui/.gitignore
···
1
+
node_modules
2
+
3
+
# Output
4
+
.output
5
+
.vercel
6
+
.netlify
7
+
.wrangler
8
+
/.svelte-kit
9
+
/build
10
+
11
+
# OS
12
+
.DS_Store
13
+
Thumbs.db
14
+
15
+
# Env
16
+
.env.local
17
+
.env.*
18
+
!.env.example
19
+
!.env.test
20
+
21
+
# Vite
22
+
vite.config.js.timestamp-*
23
+
vite.config.ts.timestamp-*
+1
web-ui/.npmrc
+1
web-ui/.npmrc
···
1
+
engine-strict=true
+38
web-ui/README.md
+38
web-ui/README.md
···
1
+
# sv
2
+
3
+
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
4
+
5
+
## Creating a project
6
+
7
+
If you're seeing this, you've probably already done this step. Congrats!
8
+
9
+
```sh
10
+
# create a new project in the current directory
11
+
npx sv create
12
+
13
+
# create a new project in my-app
14
+
npx sv create my-app
15
+
```
16
+
17
+
## Developing
18
+
19
+
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
20
+
21
+
```sh
22
+
npm run dev
23
+
24
+
# or start the server and open the app in a new browser tab
25
+
npm run dev -- --open
26
+
```
27
+
28
+
## Building
29
+
30
+
To create a production version of your app:
31
+
32
+
```sh
33
+
npm run build
34
+
```
35
+
36
+
You can preview the production build with `npm run preview`.
37
+
38
+
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
+588
web-ui/bun.lock
+588
web-ui/bun.lock
···
1
+
{
2
+
"lockfileVersion": 1,
3
+
"workspaces": {
4
+
"": {
5
+
"name": "web-ui",
6
+
"dependencies": {
7
+
"@atcute/client": "^4.0.5",
8
+
"@atcute/lexicons": "^1.2.2",
9
+
"@pds-moover/lexicons": "^1.0.1",
10
+
"@pds-moover/moover": "^1.0.0",
11
+
},
12
+
"devDependencies": {
13
+
"@eslint/compat": "^1.4.0",
14
+
"@eslint/js": "^9.36.0",
15
+
"@sveltejs/adapter-auto": "^6.1.0",
16
+
"@sveltejs/adapter-node": "^5.4.0",
17
+
"@sveltejs/kit": "^2.43.2",
18
+
"@sveltejs/vite-plugin-svelte": "^6.2.0",
19
+
"@types/node": "^22",
20
+
"eslint": "^9.36.0",
21
+
"eslint-plugin-svelte": "^3.12.4",
22
+
"globals": "^16.4.0",
23
+
"svelte": "^5.39.5",
24
+
"svelte-check": "^4.3.2",
25
+
"typescript": "^5.9.2",
26
+
"typescript-eslint": "^8.44.1",
27
+
"vite": "^7.1.7",
28
+
},
29
+
},
30
+
},
31
+
"packages": {
32
+
"@atcute/cbor": ["@atcute/cbor@2.2.7", "", { "dependencies": { "@atcute/cid": "^2.2.5", "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5" } }, "sha512-/mwAF0gnokOphceZqFq3uzMGdd8sbw5y6bxF8CRutRkCCUcpjjpJc5fkLwhxyGgOveF3mZuHE6p7t/+IAqb7Aw=="],
33
+
34
+
"@atcute/cid": ["@atcute/cid@2.2.6", "", { "dependencies": { "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5" } }, "sha512-bTAHHbJ24p+E//V4KCS4xdmd39o211jJswvqQOevj7vk+5IYcgDLx1ryZWZ1sEPOo9x875li/kj5gpKL14RDwQ=="],
35
+
36
+
"@atcute/client": ["@atcute/client@4.0.5", "", { "dependencies": { "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2" } }, "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA=="],
37
+
38
+
"@atcute/crypto": ["@atcute/crypto@2.2.5", "", { "dependencies": { "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5", "@noble/secp256k1": "^2.3.0" } }, "sha512-9CbQ9cJ68XewsbLrgdmWQS2uDD9D0hizWFJ3OOZ16TCuARREmzKEpFgHlMxPswR3bDxjwfiXzmYUlHaTqsnxRQ=="],
39
+
40
+
"@atcute/did-plc": ["@atcute/did-plc@0.1.7", "", { "dependencies": { "@atcute/cbor": "^2.2.6", "@atcute/cid": "^2.2.4", "@atcute/crypto": "^2.2.5", "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2", "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5", "@badrap/valita": "^0.4.6" } }, "sha512-a7yOQNqViae3rB5/xa3U0EPJbFD9l8zOHXx6XASZ5F8+Vy2uTgXK3omurpNZ5UxRpy1ni1AMhSohXr61cqWbkg=="],
41
+
42
+
"@atcute/identity": ["@atcute/identity@1.1.1", "", { "dependencies": { "@atcute/lexicons": "^1.2.2", "@badrap/valita": "^0.4.6" } }, "sha512-zax42n693VEhnC+5tndvO2KLDTMkHOz8UExwmklvJv7R9VujfEwiSWhcv6Jgwb3ellaG8wjiQ1lMOIjLLvwh0Q=="],
43
+
44
+
"@atcute/identity-resolver": ["@atcute/identity-resolver@1.1.4", "", { "dependencies": { "@atcute/lexicons": "^1.2.2", "@atcute/util-fetch": "^1.0.3", "@badrap/valita": "^0.4.6" }, "peerDependencies": { "@atcute/identity": "^1.0.0" } }, "sha512-/SVh8vf2cXFJenmBnGeYF2aY3WGQm3cJeew5NWTlkqoy3LvJ5wkvKq9PWu4Tv653VF40rPOp6LOdVr9Fa+q5rA=="],
45
+
46
+
"@atcute/lexicons": ["@atcute/lexicons@1.2.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "esm-env": "^1.2.2" } }, "sha512-bgEhJq5Z70/0TbK5sx+tAkrR8FsCODNiL2gUEvS5PuJfPxmFmRYNWaMGehxSPaXWpU2+Oa9ckceHiYbrItDTkA=="],
47
+
48
+
"@atcute/multibase": ["@atcute/multibase@1.1.6", "", { "dependencies": { "@atcute/uint8array": "^1.0.5" } }, "sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg=="],
49
+
50
+
"@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="],
51
+
52
+
"@atcute/util-fetch": ["@atcute/util-fetch@1.0.3", "", { "dependencies": { "@badrap/valita": "^0.4.6" } }, "sha512-f8zzTb/xlKIwv2OQ31DhShPUNCmIIleX6p7qIXwWwEUjX6x8skUtpdISSjnImq01LXpltGV5y8yhV4/Mlb7CRQ=="],
53
+
54
+
"@atproto/api": ["@atproto/api@0.16.11", "", { "dependencies": { "@atproto/common-web": "^0.4.3", "@atproto/lexicon": "^0.5.1", "@atproto/syntax": "^0.4.1", "@atproto/xrpc": "^0.7.5", "await-lock": "^2.2.2", "multiformats": "^9.9.0", "tlds": "^1.234.0", "zod": "^3.23.8" } }, "sha512-1dhfQNHiclb102RW+Ea8Nft5olfqU0Ev/vlQaSX6mWNo1aP5zT+sPODJ8+BTUOYk3vcuvL7QMkqA/rLYy2PMyw=="],
55
+
56
+
"@atproto/common-web": ["@atproto/common-web@0.4.3", "", { "dependencies": { "graphemer": "^1.4.0", "multiformats": "^9.9.0", "uint8arrays": "3.0.0", "zod": "^3.23.8" } }, "sha512-nRDINmSe4VycJzPo6fP/hEltBcULFxt9Kw7fQk6405FyAWZiTluYHlXOnU7GkQfeUK44OENG1qFTBcmCJ7e8pg=="],
57
+
58
+
"@atproto/lexicon": ["@atproto/lexicon@0.5.1", "", { "dependencies": { "@atproto/common-web": "^0.4.3", "@atproto/syntax": "^0.4.1", "iso-datestring-validator": "^2.2.2", "multiformats": "^9.9.0", "zod": "^3.23.8" } }, "sha512-y8AEtYmfgVl4fqFxqXAeGvhesiGkxiy3CWoJIfsFDDdTlZUC8DFnZrYhcqkIop3OlCkkljvpSJi1hbeC1tbi8A=="],
59
+
60
+
"@atproto/syntax": ["@atproto/syntax@0.4.1", "", {}, "sha512-CJdImtLAiFO+0z3BWTtxwk6aY5w4t8orHTMVJgkf++QRJWTxPbIFko/0hrkADB7n2EruDxDSeAgfUGehpH6ngw=="],
61
+
62
+
"@atproto/xrpc": ["@atproto/xrpc@0.7.5", "", { "dependencies": { "@atproto/lexicon": "^0.5.1", "zod": "^3.23.8" } }, "sha512-MUYNn5d2hv8yVegRL0ccHvTHAVj5JSnW07bkbiaz96UH45lvYNRVwt44z+yYVnb0/mvBzyD3/ZQ55TRGt7fHkA=="],
63
+
64
+
"@badrap/valita": ["@badrap/valita@0.4.6", "", {}, "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg=="],
65
+
66
+
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.11", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg=="],
67
+
68
+
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.11", "", { "os": "android", "cpu": "arm" }, "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg=="],
69
+
70
+
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.11", "", { "os": "android", "cpu": "arm64" }, "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ=="],
71
+
72
+
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.11", "", { "os": "android", "cpu": "x64" }, "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g=="],
73
+
74
+
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w=="],
75
+
76
+
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ=="],
77
+
78
+
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.11", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA=="],
79
+
80
+
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw=="],
81
+
82
+
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.11", "", { "os": "linux", "cpu": "arm" }, "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw=="],
83
+
84
+
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA=="],
85
+
86
+
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.11", "", { "os": "linux", "cpu": "ia32" }, "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw=="],
87
+
88
+
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw=="],
89
+
90
+
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ=="],
91
+
92
+
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.11", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw=="],
93
+
94
+
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww=="],
95
+
96
+
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.11", "", { "os": "linux", "cpu": "s390x" }, "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw=="],
97
+
98
+
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.11", "", { "os": "linux", "cpu": "x64" }, "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ=="],
99
+
100
+
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg=="],
101
+
102
+
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.11", "", { "os": "none", "cpu": "x64" }, "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A=="],
103
+
104
+
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.11", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg=="],
105
+
106
+
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.11", "", { "os": "openbsd", "cpu": "x64" }, "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw=="],
107
+
108
+
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ=="],
109
+
110
+
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.11", "", { "os": "sunos", "cpu": "x64" }, "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA=="],
111
+
112
+
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q=="],
113
+
114
+
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA=="],
115
+
116
+
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.11", "", { "os": "win32", "cpu": "x64" }, "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA=="],
117
+
118
+
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="],
119
+
120
+
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
121
+
122
+
"@eslint/compat": ["@eslint/compat@1.4.0", "", { "dependencies": { "@eslint/core": "^0.16.0" }, "peerDependencies": { "eslint": "^8.40 || 9" }, "optionalPeers": ["eslint"] }, "sha512-DEzm5dKeDBPm3r08Ixli/0cmxr8LkRdwxMRUIJBlSCpAwSrvFEJpVBzV+66JhDxiaqKxnRzCXhtiMiczF7Hglg=="],
123
+
124
+
"@eslint/config-array": ["@eslint/config-array@0.21.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA=="],
125
+
126
+
"@eslint/config-helpers": ["@eslint/config-helpers@0.4.1", "", { "dependencies": { "@eslint/core": "^0.16.0" } }, "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw=="],
127
+
128
+
"@eslint/core": ["@eslint/core@0.16.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q=="],
129
+
130
+
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
131
+
132
+
"@eslint/js": ["@eslint/js@9.38.0", "", {}, "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A=="],
133
+
134
+
"@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
135
+
136
+
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.0", "", { "dependencies": { "@eslint/core": "^0.16.0", "levn": "^0.4.1" } }, "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A=="],
137
+
138
+
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
139
+
140
+
"@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="],
141
+
142
+
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
143
+
144
+
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
145
+
146
+
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
147
+
148
+
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
149
+
150
+
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
151
+
152
+
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
153
+
154
+
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
155
+
156
+
"@noble/secp256k1": ["@noble/secp256k1@2.3.0", "", {}, "sha512-0TQed2gcBbIrh7Ccyw+y/uZQvbJwm7Ao4scBUxqpBCcsOlZG0O4KGfjtNAy/li4W8n1xt3dxrwJ0beZ2h2G6Kw=="],
157
+
158
+
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
159
+
160
+
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
161
+
162
+
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
163
+
164
+
"@pds-moover/lexicons": ["@pds-moover/lexicons@1.0.1", "", { "dependencies": { "@atproto/lexicon": "^0.5.1", "@atproto/xrpc": "^0.7.5" } }, "sha512-fv5b/DtHM7FEo/JklyF9gdK0ainlb6mWjWrBe6cmSAeg9G/4O2jBlQUOqfOAICY9gOcrCpkOrk9PHgGw//JQ2A=="],
165
+
166
+
"@pds-moover/moover": ["@pds-moover/moover@1.0.0", "", { "dependencies": { "@atcute/cbor": "^2.2.7", "@atcute/client": "^4.0.4", "@atcute/crypto": "^2.2.5", "@atcute/did-plc": "^0.1.7", "@atcute/identity-resolver": "^1.1.3", "@atcute/lexicons": "^1.2.2", "@atcute/multibase": "^1.1.6", "@atproto/api": "^0.16.7", "@pds-moover/lexicons": "^1.0.0", "alpinejs": "^3.15.0", "vite-plugin-full-reload": "^1.2.0", "vite-rs-plugin": "1.0.1" } }, "sha512-RTwxM7K8M3PbFladdrnMv2N7qNz5ikWR/trw3wipijDfZl7VcpvPlFliEhIO1JqHnr2PTRc9ORXQsFGgCjSmRg=="],
167
+
168
+
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
169
+
170
+
"@rollup/plugin-commonjs": ["@rollup/plugin-commonjs@28.0.9", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", "fdir": "^6.2.0", "is-reference": "1.2.1", "magic-string": "^0.30.3", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-PIR4/OHZ79romx0BVVll/PkwWpJ7e5lsqFa3gFfcrFPWwLXLV39JVUzQV9RKjWerE7B845Hqjj9VYlQeieZ2dA=="],
171
+
172
+
"@rollup/plugin-json": ["@rollup/plugin-json@6.1.0", "", { "dependencies": { "@rollup/pluginutils": "^5.1.0" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA=="],
173
+
174
+
"@rollup/plugin-node-resolve": ["@rollup/plugin-node-resolve@16.0.3", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", "is-module": "^1.0.0", "resolve": "^1.22.1" }, "peerDependencies": { "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg=="],
175
+
176
+
"@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="],
177
+
178
+
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.5", "", { "os": "android", "cpu": "arm" }, "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ=="],
179
+
180
+
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.5", "", { "os": "android", "cpu": "arm64" }, "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA=="],
181
+
182
+
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA=="],
183
+
184
+
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA=="],
185
+
186
+
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA=="],
187
+
188
+
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ=="],
189
+
190
+
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ=="],
191
+
192
+
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ=="],
193
+
194
+
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg=="],
195
+
196
+
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q=="],
197
+
198
+
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA=="],
199
+
200
+
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw=="],
201
+
202
+
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw=="],
203
+
204
+
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg=="],
205
+
206
+
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ=="],
207
+
208
+
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q=="],
209
+
210
+
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg=="],
211
+
212
+
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.5", "", { "os": "none", "cpu": "arm64" }, "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw=="],
213
+
214
+
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w=="],
215
+
216
+
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg=="],
217
+
218
+
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ=="],
219
+
220
+
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg=="],
221
+
222
+
"@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
223
+
224
+
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.6", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ=="],
225
+
226
+
"@sveltejs/adapter-auto": ["@sveltejs/adapter-auto@6.1.1", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-cBNt4jgH4KuaNO5gRSB2CZKkGtz+OCZ8lPjRQGjhvVUD4akotnj2weUia6imLl2v07K3IgsQRyM36909miSwoQ=="],
227
+
228
+
"@sveltejs/adapter-node": ["@sveltejs/adapter-node@5.4.0", "", { "dependencies": { "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.0", "rollup": "^4.9.5" }, "peerDependencies": { "@sveltejs/kit": "^2.4.0" } }, "sha512-NMsrwGVPEn+J73zH83Uhss/hYYZN6zT3u31R3IHAn3MiKC3h8fjmIAhLfTSOeNHr5wPYfjjMg8E+1gyFgyrEcQ=="],
229
+
230
+
"@sveltejs/kit": ["@sveltejs/kit@2.48.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", "devalue": "^5.3.2", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["@opentelemetry/api"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-GAAbkWrbRJvysL7+HOWs5v/+TmnRcEQPeED2sUcDFTHpPvRYADEtScL6x8hWuKp0DKauJVaVJLTjQVy9e7cMiw=="],
231
+
232
+
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@6.2.1", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "debug": "^4.4.1", "deepmerge": "^4.3.1", "magic-string": "^0.30.17", "vitefu": "^1.1.1" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ=="],
233
+
234
+
"@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@5.0.1", "", { "dependencies": { "debug": "^4.4.1" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", "vite": "^6.3.0 || ^7.0.0" } }, "sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA=="],
235
+
236
+
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
237
+
238
+
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
239
+
240
+
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
241
+
242
+
"@types/node": ["@types/node@22.18.12", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-BICHQ67iqxQGFSzfCFTT7MRQ5XcBjG5aeKh5Ok38UBbPe5fxTyE+aHFxwVrGyr8GNlqFMLKD1D3P2K/1ks8tog=="],
243
+
244
+
"@types/resolve": ["@types/resolve@1.20.2", "", {}, "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="],
245
+
246
+
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.46.2", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/type-utils": "8.46.2", "@typescript-eslint/utils": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.46.2", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w=="],
247
+
248
+
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.46.2", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/types": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g=="],
249
+
250
+
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.46.2", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.46.2", "@typescript-eslint/types": "^8.46.2", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg=="],
251
+
252
+
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.46.2", "", { "dependencies": { "@typescript-eslint/types": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2" } }, "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA=="],
253
+
254
+
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.46.2", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag=="],
255
+
256
+
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.46.2", "", { "dependencies": { "@typescript-eslint/types": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2", "@typescript-eslint/utils": "8.46.2", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA=="],
257
+
258
+
"@typescript-eslint/types": ["@typescript-eslint/types@8.46.2", "", {}, "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ=="],
259
+
260
+
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.46.2", "", { "dependencies": { "@typescript-eslint/project-service": "8.46.2", "@typescript-eslint/tsconfig-utils": "8.46.2", "@typescript-eslint/types": "8.46.2", "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ=="],
261
+
262
+
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.46.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.46.2", "@typescript-eslint/types": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg=="],
263
+
264
+
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.46.2", "", { "dependencies": { "@typescript-eslint/types": "8.46.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w=="],
265
+
266
+
"@vue/reactivity": ["@vue/reactivity@3.1.5", "", { "dependencies": { "@vue/shared": "3.1.5" } }, "sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg=="],
267
+
268
+
"@vue/shared": ["@vue/shared@3.1.5", "", {}, "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA=="],
269
+
270
+
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
271
+
272
+
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
273
+
274
+
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
275
+
276
+
"alpinejs": ["alpinejs@3.15.1", "", { "dependencies": { "@vue/reactivity": "~3.1.1" } }, "sha512-HLO1TtiE92VajFHtLLPK8BWaK1YepV/uj31UrfoGnQ00lyFOJZ+oVY3F0DghPAwvg8sLU79pmjGQSytERa2gEg=="],
277
+
278
+
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
279
+
280
+
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
281
+
282
+
"aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
283
+
284
+
"await-lock": ["await-lock@2.2.2", "", {}, "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw=="],
285
+
286
+
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
287
+
288
+
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
289
+
290
+
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
291
+
292
+
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
293
+
294
+
"callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
295
+
296
+
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
297
+
298
+
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
299
+
300
+
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
301
+
302
+
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
303
+
304
+
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
305
+
306
+
"commondir": ["commondir@1.0.1", "", {}, "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="],
307
+
308
+
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
309
+
310
+
"cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="],
311
+
312
+
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
313
+
314
+
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
315
+
316
+
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
317
+
318
+
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
319
+
320
+
"deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
321
+
322
+
"devalue": ["devalue@5.4.2", "", {}, "sha512-MwPZTKEPK2k8Qgfmqrd48ZKVvzSQjgW0lXLxiIBA8dQjtf/6mw6pggHNLcyDKyf+fI6eXxlQwPsfaCMTU5U+Bw=="],
323
+
324
+
"esbuild": ["esbuild@0.25.11", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.11", "@esbuild/android-arm": "0.25.11", "@esbuild/android-arm64": "0.25.11", "@esbuild/android-x64": "0.25.11", "@esbuild/darwin-arm64": "0.25.11", "@esbuild/darwin-x64": "0.25.11", "@esbuild/freebsd-arm64": "0.25.11", "@esbuild/freebsd-x64": "0.25.11", "@esbuild/linux-arm": "0.25.11", "@esbuild/linux-arm64": "0.25.11", "@esbuild/linux-ia32": "0.25.11", "@esbuild/linux-loong64": "0.25.11", "@esbuild/linux-mips64el": "0.25.11", "@esbuild/linux-ppc64": "0.25.11", "@esbuild/linux-riscv64": "0.25.11", "@esbuild/linux-s390x": "0.25.11", "@esbuild/linux-x64": "0.25.11", "@esbuild/netbsd-arm64": "0.25.11", "@esbuild/netbsd-x64": "0.25.11", "@esbuild/openbsd-arm64": "0.25.11", "@esbuild/openbsd-x64": "0.25.11", "@esbuild/openharmony-arm64": "0.25.11", "@esbuild/sunos-x64": "0.25.11", "@esbuild/win32-arm64": "0.25.11", "@esbuild/win32-ia32": "0.25.11", "@esbuild/win32-x64": "0.25.11" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q=="],
325
+
326
+
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
327
+
328
+
"eslint": ["eslint@9.38.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.1", "@eslint/core": "^0.16.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.38.0", "@eslint/plugin-kit": "^0.4.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw=="],
329
+
330
+
"eslint-plugin-svelte": ["eslint-plugin-svelte@3.12.5", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.6.1", "@jridgewell/sourcemap-codec": "^1.5.0", "esutils": "^2.0.3", "globals": "^16.0.0", "known-css-properties": "^0.37.0", "postcss": "^8.4.49", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^7.0.0", "semver": "^7.6.3", "svelte-eslint-parser": "^1.4.0" }, "peerDependencies": { "eslint": "^8.57.1 || ^9.0.0", "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-4KRG84eAHQfYd9OjZ1K7sCHy0nox+9KwT+s5WCCku3jTim5RV4tVENob274nCwIaApXsYPKAUAZFBxKZ3Wyfjw=="],
331
+
332
+
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
333
+
334
+
"eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
335
+
336
+
"esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="],
337
+
338
+
"espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
339
+
340
+
"esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
341
+
342
+
"esrap": ["esrap@2.1.1", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-ebTT9B6lOtZGMgJ3o5r12wBacHctG7oEWazIda8UlPfA3HD/Wrv8FdXoVo73vzdpwCxNyXjPauyN2bbJzMkB9A=="],
343
+
344
+
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
345
+
346
+
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
347
+
348
+
"estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
349
+
350
+
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
351
+
352
+
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
353
+
354
+
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
355
+
356
+
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
357
+
358
+
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
359
+
360
+
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
361
+
362
+
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
363
+
364
+
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
365
+
366
+
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
367
+
368
+
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
369
+
370
+
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
371
+
372
+
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
373
+
374
+
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
375
+
376
+
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
377
+
378
+
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
379
+
380
+
"globals": ["globals@16.4.0", "", {}, "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw=="],
381
+
382
+
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
383
+
384
+
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
385
+
386
+
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
387
+
388
+
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
389
+
390
+
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
391
+
392
+
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
393
+
394
+
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
395
+
396
+
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
397
+
398
+
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
399
+
400
+
"is-module": ["is-module@1.0.0", "", {}, "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="],
401
+
402
+
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
403
+
404
+
"is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="],
405
+
406
+
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
407
+
408
+
"iso-datestring-validator": ["iso-datestring-validator@2.2.2", "", {}, "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA=="],
409
+
410
+
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
411
+
412
+
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
413
+
414
+
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
415
+
416
+
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
417
+
418
+
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
419
+
420
+
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
421
+
422
+
"known-css-properties": ["known-css-properties@0.37.0", "", {}, "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ=="],
423
+
424
+
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
425
+
426
+
"lilconfig": ["lilconfig@2.1.0", "", {}, "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ=="],
427
+
428
+
"locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="],
429
+
430
+
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
431
+
432
+
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
433
+
434
+
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
435
+
436
+
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
437
+
438
+
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
439
+
440
+
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
441
+
442
+
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
443
+
444
+
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
445
+
446
+
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
447
+
448
+
"multiformats": ["multiformats@9.9.0", "", {}, "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg=="],
449
+
450
+
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
451
+
452
+
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
453
+
454
+
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
455
+
456
+
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
457
+
458
+
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
459
+
460
+
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
461
+
462
+
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
463
+
464
+
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
465
+
466
+
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
467
+
468
+
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
469
+
470
+
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
471
+
472
+
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
473
+
474
+
"postcss-load-config": ["postcss-load-config@3.1.4", "", { "dependencies": { "lilconfig": "^2.0.5", "yaml": "^1.10.2" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" }, "optionalPeers": ["postcss", "ts-node"] }, "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg=="],
475
+
476
+
"postcss-safe-parser": ["postcss-safe-parser@7.0.1", "", { "peerDependencies": { "postcss": "^8.4.31" } }, "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A=="],
477
+
478
+
"postcss-scss": ["postcss-scss@4.0.9", "", { "peerDependencies": { "postcss": "^8.4.29" } }, "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A=="],
479
+
480
+
"postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="],
481
+
482
+
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
483
+
484
+
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
485
+
486
+
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
487
+
488
+
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
489
+
490
+
"resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
491
+
492
+
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
493
+
494
+
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
495
+
496
+
"rollup": ["rollup@4.52.5", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.5", "@rollup/rollup-android-arm64": "4.52.5", "@rollup/rollup-darwin-arm64": "4.52.5", "@rollup/rollup-darwin-x64": "4.52.5", "@rollup/rollup-freebsd-arm64": "4.52.5", "@rollup/rollup-freebsd-x64": "4.52.5", "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", "@rollup/rollup-linux-arm-musleabihf": "4.52.5", "@rollup/rollup-linux-arm64-gnu": "4.52.5", "@rollup/rollup-linux-arm64-musl": "4.52.5", "@rollup/rollup-linux-loong64-gnu": "4.52.5", "@rollup/rollup-linux-ppc64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-musl": "4.52.5", "@rollup/rollup-linux-s390x-gnu": "4.52.5", "@rollup/rollup-linux-x64-gnu": "4.52.5", "@rollup/rollup-linux-x64-musl": "4.52.5", "@rollup/rollup-openharmony-arm64": "4.52.5", "@rollup/rollup-win32-arm64-msvc": "4.52.5", "@rollup/rollup-win32-ia32-msvc": "4.52.5", "@rollup/rollup-win32-x64-gnu": "4.52.5", "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw=="],
497
+
498
+
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
499
+
500
+
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
501
+
502
+
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
503
+
504
+
"set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="],
505
+
506
+
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
507
+
508
+
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
509
+
510
+
"sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
511
+
512
+
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
513
+
514
+
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
515
+
516
+
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
517
+
518
+
"supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
519
+
520
+
"svelte": ["svelte@5.42.2", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "acorn": "^8.12.1", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "esm-env": "^1.2.1", "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-iSry5jsBHispVczyt9UrBX/1qu3HQ/UyKPAIjqlvlu3o/eUvc+kpyMyRS2O4HLLx4MvLurLGIUOyyP11pyD59g=="],
521
+
522
+
"svelte-check": ["svelte-check@4.3.3", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-RYP0bEwenDXzfv0P1sKAwjZSlaRyqBn0Fz1TVni58lqyEiqgwztTpmodJrGzP6ZT2aHl4MbTvWP6gbmQ3FOnBg=="],
523
+
524
+
"svelte-eslint-parser": ["svelte-eslint-parser@1.4.0", "", { "dependencies": { "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.0.0", "espree": "^10.0.0", "postcss": "^8.4.49", "postcss-scss": "^4.0.9", "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "optionalPeers": ["svelte"] }, "sha512-fjPzOfipR5S7gQ/JvI9r2H8y9gMGXO3JtmrylHLLyahEMquXI0lrebcjT+9/hNgDej0H7abTyox5HpHmW1PSWA=="],
525
+
526
+
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
527
+
528
+
"tlds": ["tlds@1.261.0", "", { "bin": { "tlds": "bin.js" } }, "sha512-QXqwfEl9ddlGBaRFXIvNKK6OhipSiLXuRuLJX5DErz0o0Q0rYxulWLdFryTkV5PkdZct5iMInwYEGe/eR++1AA=="],
529
+
530
+
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
531
+
532
+
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
533
+
534
+
"ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="],
535
+
536
+
"type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
537
+
538
+
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
539
+
540
+
"typescript-eslint": ["typescript-eslint@8.46.2", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.46.2", "@typescript-eslint/parser": "8.46.2", "@typescript-eslint/typescript-estree": "8.46.2", "@typescript-eslint/utils": "8.46.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg=="],
541
+
542
+
"uint8arrays": ["uint8arrays@3.0.0", "", { "dependencies": { "multiformats": "^9.4.2" } }, "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA=="],
543
+
544
+
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
545
+
546
+
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
547
+
548
+
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
549
+
550
+
"vite": ["vite@7.1.12", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug=="],
551
+
552
+
"vite-plugin-full-reload": ["vite-plugin-full-reload@1.2.0", "", { "dependencies": { "picocolors": "^1.0.0", "picomatch": "^2.3.1" } }, "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA=="],
553
+
554
+
"vite-rs-plugin": ["vite-rs-plugin@1.0.1", "", { "dependencies": { "vite-plugin-full-reload": "^1.2.0" }, "peerDependencies": { "vite": "^5.0.0" }, "bin": { "cleanup": "bin/cleanForBuild.js" } }, "sha512-YhgflKQIRzuS5x66J3yICoVLH25D2fNU+jThK8tpYl/jGrXeIKT4w5VH1lkLPRC0SjK2ZCm9S6K9Z2ZFVDHjPQ=="],
555
+
556
+
"vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="],
557
+
558
+
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
559
+
560
+
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
561
+
562
+
"yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="],
563
+
564
+
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
565
+
566
+
"zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="],
567
+
568
+
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
569
+
570
+
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
571
+
572
+
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
573
+
574
+
"@rollup/plugin-commonjs/is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="],
575
+
576
+
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
577
+
578
+
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
579
+
580
+
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
581
+
582
+
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
583
+
584
+
"vite-plugin-full-reload/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
585
+
586
+
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
587
+
}
588
+
}
+43
web-ui/eslint.config.js
+43
web-ui/eslint.config.js
···
1
+
import {fileURLToPath} from 'node:url';
2
+
import {includeIgnoreFile} from '@eslint/compat';
3
+
import js from '@eslint/js';
4
+
import svelte from 'eslint-plugin-svelte';
5
+
import {defineConfig} from 'eslint/config';
6
+
import globals from 'globals';
7
+
import ts from 'typescript-eslint';
8
+
import svelteConfig from './svelte.config.js';
9
+
10
+
const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url));
11
+
12
+
export default defineConfig(
13
+
includeIgnoreFile(gitignorePath),
14
+
js.configs.recommended,
15
+
...ts.configs.recommended,
16
+
...svelte.configs.recommended,
17
+
{
18
+
languageOptions: {
19
+
globals: {...globals.browser, ...globals.node}
20
+
},
21
+
rules: { // typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.
22
+
// see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
23
+
'no-undef': 'off',
24
+
'quotes': ['error', 'single'],
25
+
26
+
}
27
+
},
28
+
{
29
+
files: [
30
+
'**/*.svelte',
31
+
'**/*.svelte.ts',
32
+
'**/*.svelte.js'
33
+
],
34
+
languageOptions: {
35
+
parserOptions: {
36
+
projectService: true,
37
+
extraFileExtensions: ['.svelte'],
38
+
parser: ts.parser,
39
+
svelteConfig
40
+
}
41
+
}
42
+
}
43
+
);
+2713
web-ui/package-lock.json
+2713
web-ui/package-lock.json
···
1
+
{
2
+
"name": "web-ui",
3
+
"version": "0.0.1",
4
+
"lockfileVersion": 3,
5
+
"requires": true,
6
+
"packages": {
7
+
"": {
8
+
"name": "web-ui",
9
+
"version": "0.0.1",
10
+
"dependencies": {
11
+
"@atcute/client": "^4.0.5",
12
+
"@atcute/lexicons": "^1.2.2",
13
+
"@pds-moover/lexicons": "^1.0.1",
14
+
"@pds-moover/moover": "^1.0.4"
15
+
},
16
+
"devDependencies": {
17
+
"@eslint/compat": "^1.4.0",
18
+
"@eslint/js": "^9.36.0",
19
+
"@sveltejs/adapter-auto": "^6.1.0",
20
+
"@sveltejs/adapter-node": "^5.4.0",
21
+
"@sveltejs/kit": "^2.43.2",
22
+
"@sveltejs/vite-plugin-svelte": "^6.2.0",
23
+
"@types/node": "^22",
24
+
"eslint": "^9.36.0",
25
+
"eslint-plugin-svelte": "^3.12.4",
26
+
"globals": "^16.4.0",
27
+
"svelte": "^5.39.5",
28
+
"svelte-check": "^4.3.2",
29
+
"typescript": "^5.9.2",
30
+
"typescript-eslint": "^8.44.1",
31
+
"vite": "^7.1.7"
32
+
},
33
+
"optionalDependencies": {
34
+
"@rollup/rollup-linux-x64-musl": "^4.52.5"
35
+
}
36
+
},
37
+
"../lexicon_types": {
38
+
"name": "@pds-moover/lexicon_types",
39
+
"version": "0.0.0",
40
+
"extraneous": true,
41
+
"dependencies": {
42
+
"@atproto/lexicon": "^0.5.1",
43
+
"@atproto/xrpc": "^0.7.5",
44
+
"cid": "multiformats/cid"
45
+
},
46
+
"devDependencies": {
47
+
"@atcute/lex-cli": "^2.2.2",
48
+
"@types/node": "^24.7.2",
49
+
"typescript": "~5.9.3",
50
+
"vite": "^7.1.7",
51
+
"vite-plugin-dts": "^4.5.4"
52
+
}
53
+
},
54
+
"../packages/lexicon_types": {
55
+
"name": "@pds-moover/lexicon_types",
56
+
"version": "0.0.0",
57
+
"extraneous": true,
58
+
"dependencies": {
59
+
"@atproto/lexicon": "^0.5.1",
60
+
"@atproto/xrpc": "^0.7.5",
61
+
"cid": "multiformats/cid"
62
+
},
63
+
"devDependencies": {
64
+
"@atcute/lex-cli": "^2.2.2"
65
+
}
66
+
},
67
+
"../packages/moover": {
68
+
"name": "@pds-moover/moover",
69
+
"version": "1.0.4",
70
+
"license": "MIT",
71
+
"dependencies": {
72
+
"@atcute/cbor": "^2.2.7",
73
+
"@atcute/client": "^4.0.4",
74
+
"@atcute/crypto": "^2.2.5",
75
+
"@atcute/did-plc": "^0.1.7",
76
+
"@atcute/identity-resolver": "^1.1.3",
77
+
"@atcute/lexicons": "^1.2.2",
78
+
"@atcute/multibase": "^1.1.6",
79
+
"@atproto/api": "^0.16.7",
80
+
"@pds-moover/lexicons": "^1.0.0",
81
+
"alpinejs": "^3.15.0",
82
+
"vite-plugin-full-reload": "^1.2.0",
83
+
"vite-rs-plugin": "1.0.1"
84
+
},
85
+
"devDependencies": {
86
+
"eslint": "^9.34.0",
87
+
"eslint-plugin-import": "^2.32.0",
88
+
"vite": "^7.1.7"
89
+
}
90
+
},
91
+
"../packages/moover/types": {
92
+
"extraneous": true
93
+
},
94
+
"node_modules/@atcute/client": {
95
+
"version": "4.0.5",
96
+
"resolved": "https://registry.npmjs.org/@atcute/client/-/client-4.0.5.tgz",
97
+
"integrity": "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA==",
98
+
"license": "0BSD",
99
+
"dependencies": {
100
+
"@atcute/identity": "^1.1.1",
101
+
"@atcute/lexicons": "^1.2.2"
102
+
}
103
+
},
104
+
"node_modules/@atcute/identity": {
105
+
"version": "1.1.1",
106
+
"resolved": "https://registry.npmjs.org/@atcute/identity/-/identity-1.1.1.tgz",
107
+
"integrity": "sha512-zax42n693VEhnC+5tndvO2KLDTMkHOz8UExwmklvJv7R9VujfEwiSWhcv6Jgwb3ellaG8wjiQ1lMOIjLLvwh0Q==",
108
+
"license": "0BSD",
109
+
"dependencies": {
110
+
"@atcute/lexicons": "^1.2.2",
111
+
"@badrap/valita": "^0.4.6"
112
+
}
113
+
},
114
+
"node_modules/@atcute/lexicons": {
115
+
"version": "1.2.2",
116
+
"resolved": "https://registry.npmjs.org/@atcute/lexicons/-/lexicons-1.2.2.tgz",
117
+
"integrity": "sha512-bgEhJq5Z70/0TbK5sx+tAkrR8FsCODNiL2gUEvS5PuJfPxmFmRYNWaMGehxSPaXWpU2+Oa9ckceHiYbrItDTkA==",
118
+
"license": "0BSD",
119
+
"dependencies": {
120
+
"@standard-schema/spec": "^1.0.0",
121
+
"esm-env": "^1.2.2"
122
+
}
123
+
},
124
+
"node_modules/@atproto/common-web": {
125
+
"version": "0.4.3",
126
+
"resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.4.3.tgz",
127
+
"integrity": "sha512-nRDINmSe4VycJzPo6fP/hEltBcULFxt9Kw7fQk6405FyAWZiTluYHlXOnU7GkQfeUK44OENG1qFTBcmCJ7e8pg==",
128
+
"license": "MIT",
129
+
"dependencies": {
130
+
"graphemer": "^1.4.0",
131
+
"multiformats": "^9.9.0",
132
+
"uint8arrays": "3.0.0",
133
+
"zod": "^3.23.8"
134
+
}
135
+
},
136
+
"node_modules/@atproto/lexicon": {
137
+
"version": "0.5.1",
138
+
"resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.5.1.tgz",
139
+
"integrity": "sha512-y8AEtYmfgVl4fqFxqXAeGvhesiGkxiy3CWoJIfsFDDdTlZUC8DFnZrYhcqkIop3OlCkkljvpSJi1hbeC1tbi8A==",
140
+
"license": "MIT",
141
+
"dependencies": {
142
+
"@atproto/common-web": "^0.4.3",
143
+
"@atproto/syntax": "^0.4.1",
144
+
"iso-datestring-validator": "^2.2.2",
145
+
"multiformats": "^9.9.0",
146
+
"zod": "^3.23.8"
147
+
}
148
+
},
149
+
"node_modules/@atproto/syntax": {
150
+
"version": "0.4.1",
151
+
"resolved": "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.4.1.tgz",
152
+
"integrity": "sha512-CJdImtLAiFO+0z3BWTtxwk6aY5w4t8orHTMVJgkf++QRJWTxPbIFko/0hrkADB7n2EruDxDSeAgfUGehpH6ngw==",
153
+
"license": "MIT"
154
+
},
155
+
"node_modules/@atproto/xrpc": {
156
+
"version": "0.7.5",
157
+
"resolved": "https://registry.npmjs.org/@atproto/xrpc/-/xrpc-0.7.5.tgz",
158
+
"integrity": "sha512-MUYNn5d2hv8yVegRL0ccHvTHAVj5JSnW07bkbiaz96UH45lvYNRVwt44z+yYVnb0/mvBzyD3/ZQ55TRGt7fHkA==",
159
+
"license": "MIT",
160
+
"dependencies": {
161
+
"@atproto/lexicon": "^0.5.1",
162
+
"zod": "^3.23.8"
163
+
}
164
+
},
165
+
"node_modules/@badrap/valita": {
166
+
"version": "0.4.6",
167
+
"resolved": "https://registry.npmjs.org/@badrap/valita/-/valita-0.4.6.tgz",
168
+
"integrity": "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==",
169
+
"license": "MIT",
170
+
"engines": {
171
+
"node": ">= 18"
172
+
}
173
+
},
174
+
"node_modules/@esbuild/darwin-arm64": {
175
+
"version": "0.25.11",
176
+
"cpu": [
177
+
"arm64"
178
+
],
179
+
"dev": true,
180
+
"license": "MIT",
181
+
"optional": true,
182
+
"os": [
183
+
"darwin"
184
+
],
185
+
"engines": {
186
+
"node": ">=18"
187
+
}
188
+
},
189
+
"node_modules/@eslint-community/eslint-utils": {
190
+
"version": "4.9.0",
191
+
"dev": true,
192
+
"license": "MIT",
193
+
"dependencies": {
194
+
"eslint-visitor-keys": "^3.4.3"
195
+
},
196
+
"engines": {
197
+
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
198
+
},
199
+
"funding": {
200
+
"url": "https://opencollective.com/eslint"
201
+
},
202
+
"peerDependencies": {
203
+
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
204
+
}
205
+
},
206
+
"node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
207
+
"version": "3.4.3",
208
+
"dev": true,
209
+
"license": "Apache-2.0",
210
+
"engines": {
211
+
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
212
+
},
213
+
"funding": {
214
+
"url": "https://opencollective.com/eslint"
215
+
}
216
+
},
217
+
"node_modules/@eslint-community/regexpp": {
218
+
"version": "4.12.2",
219
+
"dev": true,
220
+
"license": "MIT",
221
+
"engines": {
222
+
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
223
+
}
224
+
},
225
+
"node_modules/@eslint/compat": {
226
+
"version": "1.4.0",
227
+
"dev": true,
228
+
"license": "Apache-2.0",
229
+
"dependencies": {
230
+
"@eslint/core": "^0.16.0"
231
+
},
232
+
"engines": {
233
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
234
+
},
235
+
"peerDependencies": {
236
+
"eslint": "^8.40 || 9"
237
+
},
238
+
"peerDependenciesMeta": {
239
+
"eslint": {
240
+
"optional": true
241
+
}
242
+
}
243
+
},
244
+
"node_modules/@eslint/config-array": {
245
+
"version": "0.21.1",
246
+
"dev": true,
247
+
"license": "Apache-2.0",
248
+
"dependencies": {
249
+
"@eslint/object-schema": "^2.1.7",
250
+
"debug": "^4.3.1",
251
+
"minimatch": "^3.1.2"
252
+
},
253
+
"engines": {
254
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
255
+
}
256
+
},
257
+
"node_modules/@eslint/config-helpers": {
258
+
"version": "0.4.1",
259
+
"dev": true,
260
+
"license": "Apache-2.0",
261
+
"dependencies": {
262
+
"@eslint/core": "^0.16.0"
263
+
},
264
+
"engines": {
265
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
266
+
}
267
+
},
268
+
"node_modules/@eslint/core": {
269
+
"version": "0.16.0",
270
+
"dev": true,
271
+
"license": "Apache-2.0",
272
+
"dependencies": {
273
+
"@types/json-schema": "^7.0.15"
274
+
},
275
+
"engines": {
276
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
277
+
}
278
+
},
279
+
"node_modules/@eslint/eslintrc": {
280
+
"version": "3.3.1",
281
+
"dev": true,
282
+
"license": "MIT",
283
+
"dependencies": {
284
+
"ajv": "^6.12.4",
285
+
"debug": "^4.3.2",
286
+
"espree": "^10.0.1",
287
+
"globals": "^14.0.0",
288
+
"ignore": "^5.2.0",
289
+
"import-fresh": "^3.2.1",
290
+
"js-yaml": "^4.1.0",
291
+
"minimatch": "^3.1.2",
292
+
"strip-json-comments": "^3.1.1"
293
+
},
294
+
"engines": {
295
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
296
+
},
297
+
"funding": {
298
+
"url": "https://opencollective.com/eslint"
299
+
}
300
+
},
301
+
"node_modules/@eslint/eslintrc/node_modules/globals": {
302
+
"version": "14.0.0",
303
+
"dev": true,
304
+
"license": "MIT",
305
+
"engines": {
306
+
"node": ">=18"
307
+
},
308
+
"funding": {
309
+
"url": "https://github.com/sponsors/sindresorhus"
310
+
}
311
+
},
312
+
"node_modules/@eslint/js": {
313
+
"version": "9.38.0",
314
+
"dev": true,
315
+
"license": "MIT",
316
+
"engines": {
317
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
318
+
},
319
+
"funding": {
320
+
"url": "https://eslint.org/donate"
321
+
}
322
+
},
323
+
"node_modules/@eslint/object-schema": {
324
+
"version": "2.1.7",
325
+
"dev": true,
326
+
"license": "Apache-2.0",
327
+
"engines": {
328
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
329
+
}
330
+
},
331
+
"node_modules/@eslint/plugin-kit": {
332
+
"version": "0.4.0",
333
+
"dev": true,
334
+
"license": "Apache-2.0",
335
+
"dependencies": {
336
+
"@eslint/core": "^0.16.0",
337
+
"levn": "^0.4.1"
338
+
},
339
+
"engines": {
340
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
341
+
}
342
+
},
343
+
"node_modules/@humanfs/core": {
344
+
"version": "0.19.1",
345
+
"dev": true,
346
+
"license": "Apache-2.0",
347
+
"engines": {
348
+
"node": ">=18.18.0"
349
+
}
350
+
},
351
+
"node_modules/@humanfs/node": {
352
+
"version": "0.16.7",
353
+
"dev": true,
354
+
"license": "Apache-2.0",
355
+
"dependencies": {
356
+
"@humanfs/core": "^0.19.1",
357
+
"@humanwhocodes/retry": "^0.4.0"
358
+
},
359
+
"engines": {
360
+
"node": ">=18.18.0"
361
+
}
362
+
},
363
+
"node_modules/@humanwhocodes/module-importer": {
364
+
"version": "1.0.1",
365
+
"dev": true,
366
+
"license": "Apache-2.0",
367
+
"engines": {
368
+
"node": ">=12.22"
369
+
},
370
+
"funding": {
371
+
"type": "github",
372
+
"url": "https://github.com/sponsors/nzakas"
373
+
}
374
+
},
375
+
"node_modules/@humanwhocodes/retry": {
376
+
"version": "0.4.3",
377
+
"dev": true,
378
+
"license": "Apache-2.0",
379
+
"engines": {
380
+
"node": ">=18.18"
381
+
},
382
+
"funding": {
383
+
"type": "github",
384
+
"url": "https://github.com/sponsors/nzakas"
385
+
}
386
+
},
387
+
"node_modules/@jridgewell/gen-mapping": {
388
+
"version": "0.3.13",
389
+
"dev": true,
390
+
"license": "MIT",
391
+
"dependencies": {
392
+
"@jridgewell/sourcemap-codec": "^1.5.0",
393
+
"@jridgewell/trace-mapping": "^0.3.24"
394
+
}
395
+
},
396
+
"node_modules/@jridgewell/remapping": {
397
+
"version": "2.3.5",
398
+
"dev": true,
399
+
"license": "MIT",
400
+
"dependencies": {
401
+
"@jridgewell/gen-mapping": "^0.3.5",
402
+
"@jridgewell/trace-mapping": "^0.3.24"
403
+
}
404
+
},
405
+
"node_modules/@jridgewell/resolve-uri": {
406
+
"version": "3.1.2",
407
+
"dev": true,
408
+
"license": "MIT",
409
+
"engines": {
410
+
"node": ">=6.0.0"
411
+
}
412
+
},
413
+
"node_modules/@jridgewell/sourcemap-codec": {
414
+
"version": "1.5.5",
415
+
"dev": true,
416
+
"license": "MIT"
417
+
},
418
+
"node_modules/@jridgewell/trace-mapping": {
419
+
"version": "0.3.31",
420
+
"dev": true,
421
+
"license": "MIT",
422
+
"dependencies": {
423
+
"@jridgewell/resolve-uri": "^3.1.0",
424
+
"@jridgewell/sourcemap-codec": "^1.4.14"
425
+
}
426
+
},
427
+
"node_modules/@nodelib/fs.scandir": {
428
+
"version": "2.1.5",
429
+
"dev": true,
430
+
"license": "MIT",
431
+
"dependencies": {
432
+
"@nodelib/fs.stat": "2.0.5",
433
+
"run-parallel": "^1.1.9"
434
+
},
435
+
"engines": {
436
+
"node": ">= 8"
437
+
}
438
+
},
439
+
"node_modules/@nodelib/fs.stat": {
440
+
"version": "2.0.5",
441
+
"dev": true,
442
+
"license": "MIT",
443
+
"engines": {
444
+
"node": ">= 8"
445
+
}
446
+
},
447
+
"node_modules/@nodelib/fs.walk": {
448
+
"version": "1.2.8",
449
+
"dev": true,
450
+
"license": "MIT",
451
+
"dependencies": {
452
+
"@nodelib/fs.scandir": "2.1.5",
453
+
"fastq": "^1.6.0"
454
+
},
455
+
"engines": {
456
+
"node": ">= 8"
457
+
}
458
+
},
459
+
"node_modules/@pds-moover/lexicons": {
460
+
"version": "1.0.1",
461
+
"resolved": "https://registry.npmjs.org/@pds-moover/lexicons/-/lexicons-1.0.1.tgz",
462
+
"integrity": "sha512-fv5b/DtHM7FEo/JklyF9gdK0ainlb6mWjWrBe6cmSAeg9G/4O2jBlQUOqfOAICY9gOcrCpkOrk9PHgGw//JQ2A==",
463
+
"license": "MIT",
464
+
"dependencies": {
465
+
"@atproto/lexicon": "^0.5.1",
466
+
"@atproto/xrpc": "^0.7.5"
467
+
}
468
+
},
469
+
"node_modules/@pds-moover/moover": {
470
+
"resolved": "../packages/moover",
471
+
"link": true
472
+
},
473
+
"node_modules/@polka/url": {
474
+
"version": "1.0.0-next.29",
475
+
"dev": true,
476
+
"license": "MIT"
477
+
},
478
+
"node_modules/@rollup/plugin-commonjs": {
479
+
"version": "28.0.9",
480
+
"dev": true,
481
+
"license": "MIT",
482
+
"dependencies": {
483
+
"@rollup/pluginutils": "^5.0.1",
484
+
"commondir": "^1.0.1",
485
+
"estree-walker": "^2.0.2",
486
+
"fdir": "^6.2.0",
487
+
"is-reference": "1.2.1",
488
+
"magic-string": "^0.30.3",
489
+
"picomatch": "^4.0.2"
490
+
},
491
+
"engines": {
492
+
"node": ">=16.0.0 || 14 >= 14.17"
493
+
},
494
+
"peerDependencies": {
495
+
"rollup": "^2.68.0||^3.0.0||^4.0.0"
496
+
},
497
+
"peerDependenciesMeta": {
498
+
"rollup": {
499
+
"optional": true
500
+
}
501
+
}
502
+
},
503
+
"node_modules/@rollup/plugin-commonjs/node_modules/is-reference": {
504
+
"version": "1.2.1",
505
+
"dev": true,
506
+
"license": "MIT",
507
+
"dependencies": {
508
+
"@types/estree": "*"
509
+
}
510
+
},
511
+
"node_modules/@rollup/plugin-json": {
512
+
"version": "6.1.0",
513
+
"dev": true,
514
+
"license": "MIT",
515
+
"dependencies": {
516
+
"@rollup/pluginutils": "^5.1.0"
517
+
},
518
+
"engines": {
519
+
"node": ">=14.0.0"
520
+
},
521
+
"peerDependencies": {
522
+
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
523
+
},
524
+
"peerDependenciesMeta": {
525
+
"rollup": {
526
+
"optional": true
527
+
}
528
+
}
529
+
},
530
+
"node_modules/@rollup/plugin-node-resolve": {
531
+
"version": "16.0.3",
532
+
"dev": true,
533
+
"license": "MIT",
534
+
"dependencies": {
535
+
"@rollup/pluginutils": "^5.0.1",
536
+
"@types/resolve": "1.20.2",
537
+
"deepmerge": "^4.2.2",
538
+
"is-module": "^1.0.0",
539
+
"resolve": "^1.22.1"
540
+
},
541
+
"engines": {
542
+
"node": ">=14.0.0"
543
+
},
544
+
"peerDependencies": {
545
+
"rollup": "^2.78.0||^3.0.0||^4.0.0"
546
+
},
547
+
"peerDependenciesMeta": {
548
+
"rollup": {
549
+
"optional": true
550
+
}
551
+
}
552
+
},
553
+
"node_modules/@rollup/pluginutils": {
554
+
"version": "5.3.0",
555
+
"dev": true,
556
+
"license": "MIT",
557
+
"dependencies": {
558
+
"@types/estree": "^1.0.0",
559
+
"estree-walker": "^2.0.2",
560
+
"picomatch": "^4.0.2"
561
+
},
562
+
"engines": {
563
+
"node": ">=14.0.0"
564
+
},
565
+
"peerDependencies": {
566
+
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
567
+
},
568
+
"peerDependenciesMeta": {
569
+
"rollup": {
570
+
"optional": true
571
+
}
572
+
}
573
+
},
574
+
"node_modules/@rollup/rollup-darwin-arm64": {
575
+
"version": "4.52.5",
576
+
"cpu": [
577
+
"arm64"
578
+
],
579
+
"dev": true,
580
+
"license": "MIT",
581
+
"optional": true,
582
+
"os": [
583
+
"darwin"
584
+
]
585
+
},
586
+
"node_modules/@rollup/rollup-linux-x64-musl": {
587
+
"version": "4.52.5",
588
+
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.5.tgz",
589
+
"integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==",
590
+
"cpu": [
591
+
"x64"
592
+
],
593
+
"license": "MIT",
594
+
"optional": true,
595
+
"os": [
596
+
"linux"
597
+
]
598
+
},
599
+
"node_modules/@standard-schema/spec": {
600
+
"version": "1.0.0",
601
+
"license": "MIT"
602
+
},
603
+
"node_modules/@sveltejs/acorn-typescript": {
604
+
"version": "1.0.6",
605
+
"dev": true,
606
+
"license": "MIT",
607
+
"peerDependencies": {
608
+
"acorn": "^8.9.0"
609
+
}
610
+
},
611
+
"node_modules/@sveltejs/adapter-auto": {
612
+
"version": "6.1.1",
613
+
"dev": true,
614
+
"license": "MIT",
615
+
"peerDependencies": {
616
+
"@sveltejs/kit": "^2.0.0"
617
+
}
618
+
},
619
+
"node_modules/@sveltejs/adapter-node": {
620
+
"version": "5.4.0",
621
+
"dev": true,
622
+
"license": "MIT",
623
+
"dependencies": {
624
+
"@rollup/plugin-commonjs": "^28.0.1",
625
+
"@rollup/plugin-json": "^6.1.0",
626
+
"@rollup/plugin-node-resolve": "^16.0.0",
627
+
"rollup": "^4.9.5"
628
+
},
629
+
"peerDependencies": {
630
+
"@sveltejs/kit": "^2.4.0"
631
+
}
632
+
},
633
+
"node_modules/@sveltejs/kit": {
634
+
"version": "2.48.0",
635
+
"dev": true,
636
+
"license": "MIT",
637
+
"dependencies": {
638
+
"@standard-schema/spec": "^1.0.0",
639
+
"@sveltejs/acorn-typescript": "^1.0.5",
640
+
"@types/cookie": "^0.6.0",
641
+
"acorn": "^8.14.1",
642
+
"cookie": "^0.6.0",
643
+
"devalue": "^5.3.2",
644
+
"esm-env": "^1.2.2",
645
+
"kleur": "^4.1.5",
646
+
"magic-string": "^0.30.5",
647
+
"mrmime": "^2.0.0",
648
+
"sade": "^1.8.1",
649
+
"set-cookie-parser": "^2.6.0",
650
+
"sirv": "^3.0.0"
651
+
},
652
+
"bin": {
653
+
"svelte-kit": "svelte-kit.js"
654
+
},
655
+
"engines": {
656
+
"node": ">=18.13"
657
+
},
658
+
"peerDependencies": {
659
+
"@opentelemetry/api": "^1.0.0",
660
+
"@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0",
661
+
"svelte": "^4.0.0 || ^5.0.0-next.0",
662
+
"vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0"
663
+
},
664
+
"peerDependenciesMeta": {
665
+
"@opentelemetry/api": {
666
+
"optional": true
667
+
}
668
+
}
669
+
},
670
+
"node_modules/@sveltejs/vite-plugin-svelte": {
671
+
"version": "6.2.1",
672
+
"dev": true,
673
+
"license": "MIT",
674
+
"dependencies": {
675
+
"@sveltejs/vite-plugin-svelte-inspector": "^5.0.0",
676
+
"debug": "^4.4.1",
677
+
"deepmerge": "^4.3.1",
678
+
"magic-string": "^0.30.17",
679
+
"vitefu": "^1.1.1"
680
+
},
681
+
"engines": {
682
+
"node": "^20.19 || ^22.12 || >=24"
683
+
},
684
+
"peerDependencies": {
685
+
"svelte": "^5.0.0",
686
+
"vite": "^6.3.0 || ^7.0.0"
687
+
}
688
+
},
689
+
"node_modules/@sveltejs/vite-plugin-svelte-inspector": {
690
+
"version": "5.0.1",
691
+
"dev": true,
692
+
"license": "MIT",
693
+
"dependencies": {
694
+
"debug": "^4.4.1"
695
+
},
696
+
"engines": {
697
+
"node": "^20.19 || ^22.12 || >=24"
698
+
},
699
+
"peerDependencies": {
700
+
"@sveltejs/vite-plugin-svelte": "^6.0.0-next.0",
701
+
"svelte": "^5.0.0",
702
+
"vite": "^6.3.0 || ^7.0.0"
703
+
}
704
+
},
705
+
"node_modules/@types/cookie": {
706
+
"version": "0.6.0",
707
+
"dev": true,
708
+
"license": "MIT"
709
+
},
710
+
"node_modules/@types/estree": {
711
+
"version": "1.0.8",
712
+
"dev": true,
713
+
"license": "MIT"
714
+
},
715
+
"node_modules/@types/json-schema": {
716
+
"version": "7.0.15",
717
+
"dev": true,
718
+
"license": "MIT"
719
+
},
720
+
"node_modules/@types/node": {
721
+
"version": "22.18.12",
722
+
"dev": true,
723
+
"license": "MIT",
724
+
"dependencies": {
725
+
"undici-types": "~6.21.0"
726
+
}
727
+
},
728
+
"node_modules/@types/resolve": {
729
+
"version": "1.20.2",
730
+
"dev": true,
731
+
"license": "MIT"
732
+
},
733
+
"node_modules/@typescript-eslint/eslint-plugin": {
734
+
"version": "8.46.2",
735
+
"dev": true,
736
+
"license": "MIT",
737
+
"dependencies": {
738
+
"@eslint-community/regexpp": "^4.10.0",
739
+
"@typescript-eslint/scope-manager": "8.46.2",
740
+
"@typescript-eslint/type-utils": "8.46.2",
741
+
"@typescript-eslint/utils": "8.46.2",
742
+
"@typescript-eslint/visitor-keys": "8.46.2",
743
+
"graphemer": "^1.4.0",
744
+
"ignore": "^7.0.0",
745
+
"natural-compare": "^1.4.0",
746
+
"ts-api-utils": "^2.1.0"
747
+
},
748
+
"engines": {
749
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
750
+
},
751
+
"funding": {
752
+
"type": "opencollective",
753
+
"url": "https://opencollective.com/typescript-eslint"
754
+
},
755
+
"peerDependencies": {
756
+
"@typescript-eslint/parser": "^8.46.2",
757
+
"eslint": "^8.57.0 || ^9.0.0",
758
+
"typescript": ">=4.8.4 <6.0.0"
759
+
}
760
+
},
761
+
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
762
+
"version": "7.0.5",
763
+
"dev": true,
764
+
"license": "MIT",
765
+
"engines": {
766
+
"node": ">= 4"
767
+
}
768
+
},
769
+
"node_modules/@typescript-eslint/parser": {
770
+
"version": "8.46.2",
771
+
"dev": true,
772
+
"license": "MIT",
773
+
"dependencies": {
774
+
"@typescript-eslint/scope-manager": "8.46.2",
775
+
"@typescript-eslint/types": "8.46.2",
776
+
"@typescript-eslint/typescript-estree": "8.46.2",
777
+
"@typescript-eslint/visitor-keys": "8.46.2",
778
+
"debug": "^4.3.4"
779
+
},
780
+
"engines": {
781
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
782
+
},
783
+
"funding": {
784
+
"type": "opencollective",
785
+
"url": "https://opencollective.com/typescript-eslint"
786
+
},
787
+
"peerDependencies": {
788
+
"eslint": "^8.57.0 || ^9.0.0",
789
+
"typescript": ">=4.8.4 <6.0.0"
790
+
}
791
+
},
792
+
"node_modules/@typescript-eslint/project-service": {
793
+
"version": "8.46.2",
794
+
"dev": true,
795
+
"license": "MIT",
796
+
"dependencies": {
797
+
"@typescript-eslint/tsconfig-utils": "^8.46.2",
798
+
"@typescript-eslint/types": "^8.46.2",
799
+
"debug": "^4.3.4"
800
+
},
801
+
"engines": {
802
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
803
+
},
804
+
"funding": {
805
+
"type": "opencollective",
806
+
"url": "https://opencollective.com/typescript-eslint"
807
+
},
808
+
"peerDependencies": {
809
+
"typescript": ">=4.8.4 <6.0.0"
810
+
}
811
+
},
812
+
"node_modules/@typescript-eslint/scope-manager": {
813
+
"version": "8.46.2",
814
+
"dev": true,
815
+
"license": "MIT",
816
+
"dependencies": {
817
+
"@typescript-eslint/types": "8.46.2",
818
+
"@typescript-eslint/visitor-keys": "8.46.2"
819
+
},
820
+
"engines": {
821
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
822
+
},
823
+
"funding": {
824
+
"type": "opencollective",
825
+
"url": "https://opencollective.com/typescript-eslint"
826
+
}
827
+
},
828
+
"node_modules/@typescript-eslint/tsconfig-utils": {
829
+
"version": "8.46.2",
830
+
"dev": true,
831
+
"license": "MIT",
832
+
"engines": {
833
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
834
+
},
835
+
"funding": {
836
+
"type": "opencollective",
837
+
"url": "https://opencollective.com/typescript-eslint"
838
+
},
839
+
"peerDependencies": {
840
+
"typescript": ">=4.8.4 <6.0.0"
841
+
}
842
+
},
843
+
"node_modules/@typescript-eslint/type-utils": {
844
+
"version": "8.46.2",
845
+
"dev": true,
846
+
"license": "MIT",
847
+
"dependencies": {
848
+
"@typescript-eslint/types": "8.46.2",
849
+
"@typescript-eslint/typescript-estree": "8.46.2",
850
+
"@typescript-eslint/utils": "8.46.2",
851
+
"debug": "^4.3.4",
852
+
"ts-api-utils": "^2.1.0"
853
+
},
854
+
"engines": {
855
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
856
+
},
857
+
"funding": {
858
+
"type": "opencollective",
859
+
"url": "https://opencollective.com/typescript-eslint"
860
+
},
861
+
"peerDependencies": {
862
+
"eslint": "^8.57.0 || ^9.0.0",
863
+
"typescript": ">=4.8.4 <6.0.0"
864
+
}
865
+
},
866
+
"node_modules/@typescript-eslint/types": {
867
+
"version": "8.46.2",
868
+
"dev": true,
869
+
"license": "MIT",
870
+
"engines": {
871
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
872
+
},
873
+
"funding": {
874
+
"type": "opencollective",
875
+
"url": "https://opencollective.com/typescript-eslint"
876
+
}
877
+
},
878
+
"node_modules/@typescript-eslint/typescript-estree": {
879
+
"version": "8.46.2",
880
+
"dev": true,
881
+
"license": "MIT",
882
+
"dependencies": {
883
+
"@typescript-eslint/project-service": "8.46.2",
884
+
"@typescript-eslint/tsconfig-utils": "8.46.2",
885
+
"@typescript-eslint/types": "8.46.2",
886
+
"@typescript-eslint/visitor-keys": "8.46.2",
887
+
"debug": "^4.3.4",
888
+
"fast-glob": "^3.3.2",
889
+
"is-glob": "^4.0.3",
890
+
"minimatch": "^9.0.4",
891
+
"semver": "^7.6.0",
892
+
"ts-api-utils": "^2.1.0"
893
+
},
894
+
"engines": {
895
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
896
+
},
897
+
"funding": {
898
+
"type": "opencollective",
899
+
"url": "https://opencollective.com/typescript-eslint"
900
+
},
901
+
"peerDependencies": {
902
+
"typescript": ">=4.8.4 <6.0.0"
903
+
}
904
+
},
905
+
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
906
+
"version": "9.0.5",
907
+
"dev": true,
908
+
"license": "ISC",
909
+
"dependencies": {
910
+
"brace-expansion": "^2.0.1"
911
+
},
912
+
"engines": {
913
+
"node": ">=16 || 14 >=14.17"
914
+
},
915
+
"funding": {
916
+
"url": "https://github.com/sponsors/isaacs"
917
+
}
918
+
},
919
+
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch/node_modules/brace-expansion": {
920
+
"version": "2.0.2",
921
+
"dev": true,
922
+
"license": "MIT",
923
+
"dependencies": {
924
+
"balanced-match": "^1.0.0"
925
+
}
926
+
},
927
+
"node_modules/@typescript-eslint/utils": {
928
+
"version": "8.46.2",
929
+
"dev": true,
930
+
"license": "MIT",
931
+
"dependencies": {
932
+
"@eslint-community/eslint-utils": "^4.7.0",
933
+
"@typescript-eslint/scope-manager": "8.46.2",
934
+
"@typescript-eslint/types": "8.46.2",
935
+
"@typescript-eslint/typescript-estree": "8.46.2"
936
+
},
937
+
"engines": {
938
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
939
+
},
940
+
"funding": {
941
+
"type": "opencollective",
942
+
"url": "https://opencollective.com/typescript-eslint"
943
+
},
944
+
"peerDependencies": {
945
+
"eslint": "^8.57.0 || ^9.0.0",
946
+
"typescript": ">=4.8.4 <6.0.0"
947
+
}
948
+
},
949
+
"node_modules/@typescript-eslint/visitor-keys": {
950
+
"version": "8.46.2",
951
+
"dev": true,
952
+
"license": "MIT",
953
+
"dependencies": {
954
+
"@typescript-eslint/types": "8.46.2",
955
+
"eslint-visitor-keys": "^4.2.1"
956
+
},
957
+
"engines": {
958
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
959
+
},
960
+
"funding": {
961
+
"type": "opencollective",
962
+
"url": "https://opencollective.com/typescript-eslint"
963
+
}
964
+
},
965
+
"node_modules/acorn": {
966
+
"version": "8.15.0",
967
+
"dev": true,
968
+
"license": "MIT",
969
+
"bin": {
970
+
"acorn": "bin/acorn"
971
+
},
972
+
"engines": {
973
+
"node": ">=0.4.0"
974
+
}
975
+
},
976
+
"node_modules/acorn-jsx": {
977
+
"version": "5.3.2",
978
+
"dev": true,
979
+
"license": "MIT",
980
+
"peerDependencies": {
981
+
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
982
+
}
983
+
},
984
+
"node_modules/ajv": {
985
+
"version": "6.12.6",
986
+
"dev": true,
987
+
"license": "MIT",
988
+
"dependencies": {
989
+
"fast-deep-equal": "^3.1.1",
990
+
"fast-json-stable-stringify": "^2.0.0",
991
+
"json-schema-traverse": "^0.4.1",
992
+
"uri-js": "^4.2.2"
993
+
},
994
+
"funding": {
995
+
"type": "github",
996
+
"url": "https://github.com/sponsors/epoberezkin"
997
+
}
998
+
},
999
+
"node_modules/ansi-styles": {
1000
+
"version": "4.3.0",
1001
+
"dev": true,
1002
+
"license": "MIT",
1003
+
"dependencies": {
1004
+
"color-convert": "^2.0.1"
1005
+
},
1006
+
"engines": {
1007
+
"node": ">=8"
1008
+
},
1009
+
"funding": {
1010
+
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
1011
+
}
1012
+
},
1013
+
"node_modules/argparse": {
1014
+
"version": "2.0.1",
1015
+
"dev": true,
1016
+
"license": "Python-2.0"
1017
+
},
1018
+
"node_modules/aria-query": {
1019
+
"version": "5.3.2",
1020
+
"dev": true,
1021
+
"license": "Apache-2.0",
1022
+
"engines": {
1023
+
"node": ">= 0.4"
1024
+
}
1025
+
},
1026
+
"node_modules/axobject-query": {
1027
+
"version": "4.1.0",
1028
+
"dev": true,
1029
+
"license": "Apache-2.0",
1030
+
"engines": {
1031
+
"node": ">= 0.4"
1032
+
}
1033
+
},
1034
+
"node_modules/balanced-match": {
1035
+
"version": "1.0.2",
1036
+
"dev": true,
1037
+
"license": "MIT"
1038
+
},
1039
+
"node_modules/brace-expansion": {
1040
+
"version": "1.1.12",
1041
+
"dev": true,
1042
+
"license": "MIT",
1043
+
"dependencies": {
1044
+
"balanced-match": "^1.0.0",
1045
+
"concat-map": "0.0.1"
1046
+
}
1047
+
},
1048
+
"node_modules/braces": {
1049
+
"version": "3.0.3",
1050
+
"dev": true,
1051
+
"license": "MIT",
1052
+
"dependencies": {
1053
+
"fill-range": "^7.1.1"
1054
+
},
1055
+
"engines": {
1056
+
"node": ">=8"
1057
+
}
1058
+
},
1059
+
"node_modules/callsites": {
1060
+
"version": "3.1.0",
1061
+
"dev": true,
1062
+
"license": "MIT",
1063
+
"engines": {
1064
+
"node": ">=6"
1065
+
}
1066
+
},
1067
+
"node_modules/chalk": {
1068
+
"version": "4.1.2",
1069
+
"dev": true,
1070
+
"license": "MIT",
1071
+
"dependencies": {
1072
+
"ansi-styles": "^4.1.0",
1073
+
"supports-color": "^7.1.0"
1074
+
},
1075
+
"engines": {
1076
+
"node": ">=10"
1077
+
},
1078
+
"funding": {
1079
+
"url": "https://github.com/chalk/chalk?sponsor=1"
1080
+
}
1081
+
},
1082
+
"node_modules/chokidar": {
1083
+
"version": "4.0.3",
1084
+
"dev": true,
1085
+
"license": "MIT",
1086
+
"dependencies": {
1087
+
"readdirp": "^4.0.1"
1088
+
},
1089
+
"engines": {
1090
+
"node": ">= 14.16.0"
1091
+
},
1092
+
"funding": {
1093
+
"url": "https://paulmillr.com/funding/"
1094
+
}
1095
+
},
1096
+
"node_modules/clsx": {
1097
+
"version": "2.1.1",
1098
+
"dev": true,
1099
+
"license": "MIT",
1100
+
"engines": {
1101
+
"node": ">=6"
1102
+
}
1103
+
},
1104
+
"node_modules/color-convert": {
1105
+
"version": "2.0.1",
1106
+
"dev": true,
1107
+
"license": "MIT",
1108
+
"dependencies": {
1109
+
"color-name": "~1.1.4"
1110
+
},
1111
+
"engines": {
1112
+
"node": ">=7.0.0"
1113
+
}
1114
+
},
1115
+
"node_modules/color-name": {
1116
+
"version": "1.1.4",
1117
+
"dev": true,
1118
+
"license": "MIT"
1119
+
},
1120
+
"node_modules/commondir": {
1121
+
"version": "1.0.1",
1122
+
"dev": true,
1123
+
"license": "MIT"
1124
+
},
1125
+
"node_modules/concat-map": {
1126
+
"version": "0.0.1",
1127
+
"dev": true,
1128
+
"license": "MIT"
1129
+
},
1130
+
"node_modules/cookie": {
1131
+
"version": "0.6.0",
1132
+
"dev": true,
1133
+
"license": "MIT",
1134
+
"engines": {
1135
+
"node": ">= 0.6"
1136
+
}
1137
+
},
1138
+
"node_modules/cross-spawn": {
1139
+
"version": "7.0.6",
1140
+
"dev": true,
1141
+
"license": "MIT",
1142
+
"dependencies": {
1143
+
"path-key": "^3.1.0",
1144
+
"shebang-command": "^2.0.0",
1145
+
"which": "^2.0.1"
1146
+
},
1147
+
"engines": {
1148
+
"node": ">= 8"
1149
+
}
1150
+
},
1151
+
"node_modules/cssesc": {
1152
+
"version": "3.0.0",
1153
+
"dev": true,
1154
+
"license": "MIT",
1155
+
"bin": {
1156
+
"cssesc": "bin/cssesc"
1157
+
},
1158
+
"engines": {
1159
+
"node": ">=4"
1160
+
}
1161
+
},
1162
+
"node_modules/debug": {
1163
+
"version": "4.4.3",
1164
+
"dev": true,
1165
+
"license": "MIT",
1166
+
"dependencies": {
1167
+
"ms": "^2.1.3"
1168
+
},
1169
+
"engines": {
1170
+
"node": ">=6.0"
1171
+
},
1172
+
"peerDependenciesMeta": {
1173
+
"supports-color": {
1174
+
"optional": true
1175
+
}
1176
+
}
1177
+
},
1178
+
"node_modules/deep-is": {
1179
+
"version": "0.1.4",
1180
+
"dev": true,
1181
+
"license": "MIT"
1182
+
},
1183
+
"node_modules/deepmerge": {
1184
+
"version": "4.3.1",
1185
+
"dev": true,
1186
+
"license": "MIT",
1187
+
"engines": {
1188
+
"node": ">=0.10.0"
1189
+
}
1190
+
},
1191
+
"node_modules/devalue": {
1192
+
"version": "5.4.2",
1193
+
"dev": true,
1194
+
"license": "MIT"
1195
+
},
1196
+
"node_modules/esbuild": {
1197
+
"version": "0.25.11",
1198
+
"dev": true,
1199
+
"hasInstallScript": true,
1200
+
"license": "MIT",
1201
+
"bin": {
1202
+
"esbuild": "bin/esbuild"
1203
+
},
1204
+
"engines": {
1205
+
"node": ">=18"
1206
+
},
1207
+
"optionalDependencies": {
1208
+
"@esbuild/aix-ppc64": "0.25.11",
1209
+
"@esbuild/android-arm": "0.25.11",
1210
+
"@esbuild/android-arm64": "0.25.11",
1211
+
"@esbuild/android-x64": "0.25.11",
1212
+
"@esbuild/darwin-arm64": "0.25.11",
1213
+
"@esbuild/darwin-x64": "0.25.11",
1214
+
"@esbuild/freebsd-arm64": "0.25.11",
1215
+
"@esbuild/freebsd-x64": "0.25.11",
1216
+
"@esbuild/linux-arm": "0.25.11",
1217
+
"@esbuild/linux-arm64": "0.25.11",
1218
+
"@esbuild/linux-ia32": "0.25.11",
1219
+
"@esbuild/linux-loong64": "0.25.11",
1220
+
"@esbuild/linux-mips64el": "0.25.11",
1221
+
"@esbuild/linux-ppc64": "0.25.11",
1222
+
"@esbuild/linux-riscv64": "0.25.11",
1223
+
"@esbuild/linux-s390x": "0.25.11",
1224
+
"@esbuild/linux-x64": "0.25.11",
1225
+
"@esbuild/netbsd-arm64": "0.25.11",
1226
+
"@esbuild/netbsd-x64": "0.25.11",
1227
+
"@esbuild/openbsd-arm64": "0.25.11",
1228
+
"@esbuild/openbsd-x64": "0.25.11",
1229
+
"@esbuild/openharmony-arm64": "0.25.11",
1230
+
"@esbuild/sunos-x64": "0.25.11",
1231
+
"@esbuild/win32-arm64": "0.25.11",
1232
+
"@esbuild/win32-ia32": "0.25.11",
1233
+
"@esbuild/win32-x64": "0.25.11"
1234
+
}
1235
+
},
1236
+
"node_modules/escape-string-regexp": {
1237
+
"version": "4.0.0",
1238
+
"dev": true,
1239
+
"license": "MIT",
1240
+
"engines": {
1241
+
"node": ">=10"
1242
+
},
1243
+
"funding": {
1244
+
"url": "https://github.com/sponsors/sindresorhus"
1245
+
}
1246
+
},
1247
+
"node_modules/eslint": {
1248
+
"version": "9.38.0",
1249
+
"dev": true,
1250
+
"license": "MIT",
1251
+
"dependencies": {
1252
+
"@eslint-community/eslint-utils": "^4.8.0",
1253
+
"@eslint-community/regexpp": "^4.12.1",
1254
+
"@eslint/config-array": "^0.21.1",
1255
+
"@eslint/config-helpers": "^0.4.1",
1256
+
"@eslint/core": "^0.16.0",
1257
+
"@eslint/eslintrc": "^3.3.1",
1258
+
"@eslint/js": "9.38.0",
1259
+
"@eslint/plugin-kit": "^0.4.0",
1260
+
"@humanfs/node": "^0.16.6",
1261
+
"@humanwhocodes/module-importer": "^1.0.1",
1262
+
"@humanwhocodes/retry": "^0.4.2",
1263
+
"@types/estree": "^1.0.6",
1264
+
"ajv": "^6.12.4",
1265
+
"chalk": "^4.0.0",
1266
+
"cross-spawn": "^7.0.6",
1267
+
"debug": "^4.3.2",
1268
+
"escape-string-regexp": "^4.0.0",
1269
+
"eslint-scope": "^8.4.0",
1270
+
"eslint-visitor-keys": "^4.2.1",
1271
+
"espree": "^10.4.0",
1272
+
"esquery": "^1.5.0",
1273
+
"esutils": "^2.0.2",
1274
+
"fast-deep-equal": "^3.1.3",
1275
+
"file-entry-cache": "^8.0.0",
1276
+
"find-up": "^5.0.0",
1277
+
"glob-parent": "^6.0.2",
1278
+
"ignore": "^5.2.0",
1279
+
"imurmurhash": "^0.1.4",
1280
+
"is-glob": "^4.0.0",
1281
+
"json-stable-stringify-without-jsonify": "^1.0.1",
1282
+
"lodash.merge": "^4.6.2",
1283
+
"minimatch": "^3.1.2",
1284
+
"natural-compare": "^1.4.0",
1285
+
"optionator": "^0.9.3"
1286
+
},
1287
+
"bin": {
1288
+
"eslint": "bin/eslint.js"
1289
+
},
1290
+
"engines": {
1291
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1292
+
},
1293
+
"funding": {
1294
+
"url": "https://eslint.org/donate"
1295
+
},
1296
+
"peerDependencies": {
1297
+
"jiti": "*"
1298
+
},
1299
+
"peerDependenciesMeta": {
1300
+
"jiti": {
1301
+
"optional": true
1302
+
}
1303
+
}
1304
+
},
1305
+
"node_modules/eslint-plugin-svelte": {
1306
+
"version": "3.12.5",
1307
+
"dev": true,
1308
+
"license": "MIT",
1309
+
"dependencies": {
1310
+
"@eslint-community/eslint-utils": "^4.6.1",
1311
+
"@jridgewell/sourcemap-codec": "^1.5.0",
1312
+
"esutils": "^2.0.3",
1313
+
"globals": "^16.0.0",
1314
+
"known-css-properties": "^0.37.0",
1315
+
"postcss": "^8.4.49",
1316
+
"postcss-load-config": "^3.1.4",
1317
+
"postcss-safe-parser": "^7.0.0",
1318
+
"semver": "^7.6.3",
1319
+
"svelte-eslint-parser": "^1.4.0"
1320
+
},
1321
+
"engines": {
1322
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1323
+
},
1324
+
"funding": {
1325
+
"url": "https://github.com/sponsors/ota-meshi"
1326
+
},
1327
+
"peerDependencies": {
1328
+
"eslint": "^8.57.1 || ^9.0.0",
1329
+
"svelte": "^3.37.0 || ^4.0.0 || ^5.0.0"
1330
+
},
1331
+
"peerDependenciesMeta": {
1332
+
"svelte": {
1333
+
"optional": true
1334
+
}
1335
+
}
1336
+
},
1337
+
"node_modules/eslint-scope": {
1338
+
"version": "8.4.0",
1339
+
"dev": true,
1340
+
"license": "BSD-2-Clause",
1341
+
"dependencies": {
1342
+
"esrecurse": "^4.3.0",
1343
+
"estraverse": "^5.2.0"
1344
+
},
1345
+
"engines": {
1346
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1347
+
},
1348
+
"funding": {
1349
+
"url": "https://opencollective.com/eslint"
1350
+
}
1351
+
},
1352
+
"node_modules/eslint-visitor-keys": {
1353
+
"version": "4.2.1",
1354
+
"dev": true,
1355
+
"license": "Apache-2.0",
1356
+
"engines": {
1357
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1358
+
},
1359
+
"funding": {
1360
+
"url": "https://opencollective.com/eslint"
1361
+
}
1362
+
},
1363
+
"node_modules/esm-env": {
1364
+
"version": "1.2.2",
1365
+
"license": "MIT"
1366
+
},
1367
+
"node_modules/espree": {
1368
+
"version": "10.4.0",
1369
+
"dev": true,
1370
+
"license": "BSD-2-Clause",
1371
+
"dependencies": {
1372
+
"acorn": "^8.15.0",
1373
+
"acorn-jsx": "^5.3.2",
1374
+
"eslint-visitor-keys": "^4.2.1"
1375
+
},
1376
+
"engines": {
1377
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1378
+
},
1379
+
"funding": {
1380
+
"url": "https://opencollective.com/eslint"
1381
+
}
1382
+
},
1383
+
"node_modules/esquery": {
1384
+
"version": "1.6.0",
1385
+
"dev": true,
1386
+
"license": "BSD-3-Clause",
1387
+
"dependencies": {
1388
+
"estraverse": "^5.1.0"
1389
+
},
1390
+
"engines": {
1391
+
"node": ">=0.10"
1392
+
}
1393
+
},
1394
+
"node_modules/esrap": {
1395
+
"version": "2.1.1",
1396
+
"dev": true,
1397
+
"license": "MIT",
1398
+
"dependencies": {
1399
+
"@jridgewell/sourcemap-codec": "^1.4.15"
1400
+
}
1401
+
},
1402
+
"node_modules/esrecurse": {
1403
+
"version": "4.3.0",
1404
+
"dev": true,
1405
+
"license": "BSD-2-Clause",
1406
+
"dependencies": {
1407
+
"estraverse": "^5.2.0"
1408
+
},
1409
+
"engines": {
1410
+
"node": ">=4.0"
1411
+
}
1412
+
},
1413
+
"node_modules/estraverse": {
1414
+
"version": "5.3.0",
1415
+
"dev": true,
1416
+
"license": "BSD-2-Clause",
1417
+
"engines": {
1418
+
"node": ">=4.0"
1419
+
}
1420
+
},
1421
+
"node_modules/estree-walker": {
1422
+
"version": "2.0.2",
1423
+
"dev": true,
1424
+
"license": "MIT"
1425
+
},
1426
+
"node_modules/esutils": {
1427
+
"version": "2.0.3",
1428
+
"dev": true,
1429
+
"license": "BSD-2-Clause",
1430
+
"engines": {
1431
+
"node": ">=0.10.0"
1432
+
}
1433
+
},
1434
+
"node_modules/fast-deep-equal": {
1435
+
"version": "3.1.3",
1436
+
"dev": true,
1437
+
"license": "MIT"
1438
+
},
1439
+
"node_modules/fast-glob": {
1440
+
"version": "3.3.3",
1441
+
"dev": true,
1442
+
"license": "MIT",
1443
+
"dependencies": {
1444
+
"@nodelib/fs.stat": "^2.0.2",
1445
+
"@nodelib/fs.walk": "^1.2.3",
1446
+
"glob-parent": "^5.1.2",
1447
+
"merge2": "^1.3.0",
1448
+
"micromatch": "^4.0.8"
1449
+
},
1450
+
"engines": {
1451
+
"node": ">=8.6.0"
1452
+
}
1453
+
},
1454
+
"node_modules/fast-glob/node_modules/glob-parent": {
1455
+
"version": "5.1.2",
1456
+
"dev": true,
1457
+
"license": "ISC",
1458
+
"dependencies": {
1459
+
"is-glob": "^4.0.1"
1460
+
},
1461
+
"engines": {
1462
+
"node": ">= 6"
1463
+
}
1464
+
},
1465
+
"node_modules/fast-json-stable-stringify": {
1466
+
"version": "2.1.0",
1467
+
"dev": true,
1468
+
"license": "MIT"
1469
+
},
1470
+
"node_modules/fast-levenshtein": {
1471
+
"version": "2.0.6",
1472
+
"dev": true,
1473
+
"license": "MIT"
1474
+
},
1475
+
"node_modules/fastq": {
1476
+
"version": "1.19.1",
1477
+
"dev": true,
1478
+
"license": "ISC",
1479
+
"dependencies": {
1480
+
"reusify": "^1.0.4"
1481
+
}
1482
+
},
1483
+
"node_modules/fdir": {
1484
+
"version": "6.5.0",
1485
+
"dev": true,
1486
+
"license": "MIT",
1487
+
"engines": {
1488
+
"node": ">=12.0.0"
1489
+
},
1490
+
"peerDependencies": {
1491
+
"picomatch": "^3 || ^4"
1492
+
},
1493
+
"peerDependenciesMeta": {
1494
+
"picomatch": {
1495
+
"optional": true
1496
+
}
1497
+
}
1498
+
},
1499
+
"node_modules/file-entry-cache": {
1500
+
"version": "8.0.0",
1501
+
"dev": true,
1502
+
"license": "MIT",
1503
+
"dependencies": {
1504
+
"flat-cache": "^4.0.0"
1505
+
},
1506
+
"engines": {
1507
+
"node": ">=16.0.0"
1508
+
}
1509
+
},
1510
+
"node_modules/fill-range": {
1511
+
"version": "7.1.1",
1512
+
"dev": true,
1513
+
"license": "MIT",
1514
+
"dependencies": {
1515
+
"to-regex-range": "^5.0.1"
1516
+
},
1517
+
"engines": {
1518
+
"node": ">=8"
1519
+
}
1520
+
},
1521
+
"node_modules/find-up": {
1522
+
"version": "5.0.0",
1523
+
"dev": true,
1524
+
"license": "MIT",
1525
+
"dependencies": {
1526
+
"locate-path": "^6.0.0",
1527
+
"path-exists": "^4.0.0"
1528
+
},
1529
+
"engines": {
1530
+
"node": ">=10"
1531
+
},
1532
+
"funding": {
1533
+
"url": "https://github.com/sponsors/sindresorhus"
1534
+
}
1535
+
},
1536
+
"node_modules/flat-cache": {
1537
+
"version": "4.0.1",
1538
+
"dev": true,
1539
+
"license": "MIT",
1540
+
"dependencies": {
1541
+
"flatted": "^3.2.9",
1542
+
"keyv": "^4.5.4"
1543
+
},
1544
+
"engines": {
1545
+
"node": ">=16"
1546
+
}
1547
+
},
1548
+
"node_modules/flatted": {
1549
+
"version": "3.3.3",
1550
+
"dev": true,
1551
+
"license": "ISC"
1552
+
},
1553
+
"node_modules/fsevents": {
1554
+
"version": "2.3.3",
1555
+
"dev": true,
1556
+
"license": "MIT",
1557
+
"optional": true,
1558
+
"os": [
1559
+
"darwin"
1560
+
],
1561
+
"engines": {
1562
+
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
1563
+
}
1564
+
},
1565
+
"node_modules/function-bind": {
1566
+
"version": "1.1.2",
1567
+
"dev": true,
1568
+
"license": "MIT",
1569
+
"funding": {
1570
+
"url": "https://github.com/sponsors/ljharb"
1571
+
}
1572
+
},
1573
+
"node_modules/glob-parent": {
1574
+
"version": "6.0.2",
1575
+
"dev": true,
1576
+
"license": "ISC",
1577
+
"dependencies": {
1578
+
"is-glob": "^4.0.3"
1579
+
},
1580
+
"engines": {
1581
+
"node": ">=10.13.0"
1582
+
}
1583
+
},
1584
+
"node_modules/globals": {
1585
+
"version": "16.4.0",
1586
+
"dev": true,
1587
+
"license": "MIT",
1588
+
"engines": {
1589
+
"node": ">=18"
1590
+
},
1591
+
"funding": {
1592
+
"url": "https://github.com/sponsors/sindresorhus"
1593
+
}
1594
+
},
1595
+
"node_modules/graphemer": {
1596
+
"version": "1.4.0",
1597
+
"license": "MIT"
1598
+
},
1599
+
"node_modules/has-flag": {
1600
+
"version": "4.0.0",
1601
+
"dev": true,
1602
+
"license": "MIT",
1603
+
"engines": {
1604
+
"node": ">=8"
1605
+
}
1606
+
},
1607
+
"node_modules/hasown": {
1608
+
"version": "2.0.2",
1609
+
"dev": true,
1610
+
"license": "MIT",
1611
+
"dependencies": {
1612
+
"function-bind": "^1.1.2"
1613
+
},
1614
+
"engines": {
1615
+
"node": ">= 0.4"
1616
+
}
1617
+
},
1618
+
"node_modules/ignore": {
1619
+
"version": "5.3.2",
1620
+
"dev": true,
1621
+
"license": "MIT",
1622
+
"engines": {
1623
+
"node": ">= 4"
1624
+
}
1625
+
},
1626
+
"node_modules/import-fresh": {
1627
+
"version": "3.3.1",
1628
+
"dev": true,
1629
+
"license": "MIT",
1630
+
"dependencies": {
1631
+
"parent-module": "^1.0.0",
1632
+
"resolve-from": "^4.0.0"
1633
+
},
1634
+
"engines": {
1635
+
"node": ">=6"
1636
+
},
1637
+
"funding": {
1638
+
"url": "https://github.com/sponsors/sindresorhus"
1639
+
}
1640
+
},
1641
+
"node_modules/imurmurhash": {
1642
+
"version": "0.1.4",
1643
+
"dev": true,
1644
+
"license": "MIT",
1645
+
"engines": {
1646
+
"node": ">=0.8.19"
1647
+
}
1648
+
},
1649
+
"node_modules/is-core-module": {
1650
+
"version": "2.16.1",
1651
+
"dev": true,
1652
+
"license": "MIT",
1653
+
"dependencies": {
1654
+
"hasown": "^2.0.2"
1655
+
},
1656
+
"engines": {
1657
+
"node": ">= 0.4"
1658
+
},
1659
+
"funding": {
1660
+
"url": "https://github.com/sponsors/ljharb"
1661
+
}
1662
+
},
1663
+
"node_modules/is-extglob": {
1664
+
"version": "2.1.1",
1665
+
"dev": true,
1666
+
"license": "MIT",
1667
+
"engines": {
1668
+
"node": ">=0.10.0"
1669
+
}
1670
+
},
1671
+
"node_modules/is-glob": {
1672
+
"version": "4.0.3",
1673
+
"dev": true,
1674
+
"license": "MIT",
1675
+
"dependencies": {
1676
+
"is-extglob": "^2.1.1"
1677
+
},
1678
+
"engines": {
1679
+
"node": ">=0.10.0"
1680
+
}
1681
+
},
1682
+
"node_modules/is-module": {
1683
+
"version": "1.0.0",
1684
+
"dev": true,
1685
+
"license": "MIT"
1686
+
},
1687
+
"node_modules/is-number": {
1688
+
"version": "7.0.0",
1689
+
"dev": true,
1690
+
"license": "MIT",
1691
+
"engines": {
1692
+
"node": ">=0.12.0"
1693
+
}
1694
+
},
1695
+
"node_modules/is-reference": {
1696
+
"version": "3.0.3",
1697
+
"dev": true,
1698
+
"license": "MIT",
1699
+
"dependencies": {
1700
+
"@types/estree": "^1.0.6"
1701
+
}
1702
+
},
1703
+
"node_modules/isexe": {
1704
+
"version": "2.0.0",
1705
+
"dev": true,
1706
+
"license": "ISC"
1707
+
},
1708
+
"node_modules/iso-datestring-validator": {
1709
+
"version": "2.2.2",
1710
+
"resolved": "https://registry.npmjs.org/iso-datestring-validator/-/iso-datestring-validator-2.2.2.tgz",
1711
+
"integrity": "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==",
1712
+
"license": "MIT"
1713
+
},
1714
+
"node_modules/js-yaml": {
1715
+
"version": "4.1.0",
1716
+
"dev": true,
1717
+
"license": "MIT",
1718
+
"dependencies": {
1719
+
"argparse": "^2.0.1"
1720
+
},
1721
+
"bin": {
1722
+
"js-yaml": "bin/js-yaml.js"
1723
+
}
1724
+
},
1725
+
"node_modules/json-buffer": {
1726
+
"version": "3.0.1",
1727
+
"dev": true,
1728
+
"license": "MIT"
1729
+
},
1730
+
"node_modules/json-schema-traverse": {
1731
+
"version": "0.4.1",
1732
+
"dev": true,
1733
+
"license": "MIT"
1734
+
},
1735
+
"node_modules/json-stable-stringify-without-jsonify": {
1736
+
"version": "1.0.1",
1737
+
"dev": true,
1738
+
"license": "MIT"
1739
+
},
1740
+
"node_modules/keyv": {
1741
+
"version": "4.5.4",
1742
+
"dev": true,
1743
+
"license": "MIT",
1744
+
"dependencies": {
1745
+
"json-buffer": "3.0.1"
1746
+
}
1747
+
},
1748
+
"node_modules/kleur": {
1749
+
"version": "4.1.5",
1750
+
"dev": true,
1751
+
"license": "MIT",
1752
+
"engines": {
1753
+
"node": ">=6"
1754
+
}
1755
+
},
1756
+
"node_modules/known-css-properties": {
1757
+
"version": "0.37.0",
1758
+
"dev": true,
1759
+
"license": "MIT"
1760
+
},
1761
+
"node_modules/levn": {
1762
+
"version": "0.4.1",
1763
+
"dev": true,
1764
+
"license": "MIT",
1765
+
"dependencies": {
1766
+
"prelude-ls": "^1.2.1",
1767
+
"type-check": "~0.4.0"
1768
+
},
1769
+
"engines": {
1770
+
"node": ">= 0.8.0"
1771
+
}
1772
+
},
1773
+
"node_modules/lilconfig": {
1774
+
"version": "2.1.0",
1775
+
"dev": true,
1776
+
"license": "MIT",
1777
+
"engines": {
1778
+
"node": ">=10"
1779
+
}
1780
+
},
1781
+
"node_modules/locate-character": {
1782
+
"version": "3.0.0",
1783
+
"dev": true,
1784
+
"license": "MIT"
1785
+
},
1786
+
"node_modules/locate-path": {
1787
+
"version": "6.0.0",
1788
+
"dev": true,
1789
+
"license": "MIT",
1790
+
"dependencies": {
1791
+
"p-locate": "^5.0.0"
1792
+
},
1793
+
"engines": {
1794
+
"node": ">=10"
1795
+
},
1796
+
"funding": {
1797
+
"url": "https://github.com/sponsors/sindresorhus"
1798
+
}
1799
+
},
1800
+
"node_modules/lodash.merge": {
1801
+
"version": "4.6.2",
1802
+
"dev": true,
1803
+
"license": "MIT"
1804
+
},
1805
+
"node_modules/magic-string": {
1806
+
"version": "0.30.21",
1807
+
"dev": true,
1808
+
"license": "MIT",
1809
+
"dependencies": {
1810
+
"@jridgewell/sourcemap-codec": "^1.5.5"
1811
+
}
1812
+
},
1813
+
"node_modules/merge2": {
1814
+
"version": "1.4.1",
1815
+
"dev": true,
1816
+
"license": "MIT",
1817
+
"engines": {
1818
+
"node": ">= 8"
1819
+
}
1820
+
},
1821
+
"node_modules/micromatch": {
1822
+
"version": "4.0.8",
1823
+
"dev": true,
1824
+
"license": "MIT",
1825
+
"dependencies": {
1826
+
"braces": "^3.0.3",
1827
+
"picomatch": "^2.3.1"
1828
+
},
1829
+
"engines": {
1830
+
"node": ">=8.6"
1831
+
}
1832
+
},
1833
+
"node_modules/micromatch/node_modules/picomatch": {
1834
+
"version": "2.3.1",
1835
+
"dev": true,
1836
+
"license": "MIT",
1837
+
"engines": {
1838
+
"node": ">=8.6"
1839
+
},
1840
+
"funding": {
1841
+
"url": "https://github.com/sponsors/jonschlinkert"
1842
+
}
1843
+
},
1844
+
"node_modules/minimatch": {
1845
+
"version": "3.1.2",
1846
+
"dev": true,
1847
+
"license": "ISC",
1848
+
"dependencies": {
1849
+
"brace-expansion": "^1.1.7"
1850
+
},
1851
+
"engines": {
1852
+
"node": "*"
1853
+
}
1854
+
},
1855
+
"node_modules/mri": {
1856
+
"version": "1.2.0",
1857
+
"dev": true,
1858
+
"license": "MIT",
1859
+
"engines": {
1860
+
"node": ">=4"
1861
+
}
1862
+
},
1863
+
"node_modules/mrmime": {
1864
+
"version": "2.0.1",
1865
+
"dev": true,
1866
+
"license": "MIT",
1867
+
"engines": {
1868
+
"node": ">=10"
1869
+
}
1870
+
},
1871
+
"node_modules/ms": {
1872
+
"version": "2.1.3",
1873
+
"dev": true,
1874
+
"license": "MIT"
1875
+
},
1876
+
"node_modules/multiformats": {
1877
+
"version": "9.9.0",
1878
+
"resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz",
1879
+
"integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==",
1880
+
"license": "(Apache-2.0 AND MIT)"
1881
+
},
1882
+
"node_modules/nanoid": {
1883
+
"version": "3.3.11",
1884
+
"dev": true,
1885
+
"funding": [
1886
+
{
1887
+
"type": "github",
1888
+
"url": "https://github.com/sponsors/ai"
1889
+
}
1890
+
],
1891
+
"license": "MIT",
1892
+
"bin": {
1893
+
"nanoid": "bin/nanoid.cjs"
1894
+
},
1895
+
"engines": {
1896
+
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
1897
+
}
1898
+
},
1899
+
"node_modules/natural-compare": {
1900
+
"version": "1.4.0",
1901
+
"dev": true,
1902
+
"license": "MIT"
1903
+
},
1904
+
"node_modules/optionator": {
1905
+
"version": "0.9.4",
1906
+
"dev": true,
1907
+
"license": "MIT",
1908
+
"dependencies": {
1909
+
"deep-is": "^0.1.3",
1910
+
"fast-levenshtein": "^2.0.6",
1911
+
"levn": "^0.4.1",
1912
+
"prelude-ls": "^1.2.1",
1913
+
"type-check": "^0.4.0",
1914
+
"word-wrap": "^1.2.5"
1915
+
},
1916
+
"engines": {
1917
+
"node": ">= 0.8.0"
1918
+
}
1919
+
},
1920
+
"node_modules/p-limit": {
1921
+
"version": "3.1.0",
1922
+
"dev": true,
1923
+
"license": "MIT",
1924
+
"dependencies": {
1925
+
"yocto-queue": "^0.1.0"
1926
+
},
1927
+
"engines": {
1928
+
"node": ">=10"
1929
+
},
1930
+
"funding": {
1931
+
"url": "https://github.com/sponsors/sindresorhus"
1932
+
}
1933
+
},
1934
+
"node_modules/p-locate": {
1935
+
"version": "5.0.0",
1936
+
"dev": true,
1937
+
"license": "MIT",
1938
+
"dependencies": {
1939
+
"p-limit": "^3.0.2"
1940
+
},
1941
+
"engines": {
1942
+
"node": ">=10"
1943
+
},
1944
+
"funding": {
1945
+
"url": "https://github.com/sponsors/sindresorhus"
1946
+
}
1947
+
},
1948
+
"node_modules/parent-module": {
1949
+
"version": "1.0.1",
1950
+
"dev": true,
1951
+
"license": "MIT",
1952
+
"dependencies": {
1953
+
"callsites": "^3.0.0"
1954
+
},
1955
+
"engines": {
1956
+
"node": ">=6"
1957
+
}
1958
+
},
1959
+
"node_modules/path-exists": {
1960
+
"version": "4.0.0",
1961
+
"dev": true,
1962
+
"license": "MIT",
1963
+
"engines": {
1964
+
"node": ">=8"
1965
+
}
1966
+
},
1967
+
"node_modules/path-key": {
1968
+
"version": "3.1.1",
1969
+
"dev": true,
1970
+
"license": "MIT",
1971
+
"engines": {
1972
+
"node": ">=8"
1973
+
}
1974
+
},
1975
+
"node_modules/path-parse": {
1976
+
"version": "1.0.7",
1977
+
"dev": true,
1978
+
"license": "MIT"
1979
+
},
1980
+
"node_modules/picocolors": {
1981
+
"version": "1.1.1",
1982
+
"dev": true,
1983
+
"license": "ISC"
1984
+
},
1985
+
"node_modules/picomatch": {
1986
+
"version": "4.0.3",
1987
+
"dev": true,
1988
+
"license": "MIT",
1989
+
"engines": {
1990
+
"node": ">=12"
1991
+
},
1992
+
"funding": {
1993
+
"url": "https://github.com/sponsors/jonschlinkert"
1994
+
}
1995
+
},
1996
+
"node_modules/postcss": {
1997
+
"version": "8.5.6",
1998
+
"dev": true,
1999
+
"funding": [
2000
+
{
2001
+
"type": "opencollective",
2002
+
"url": "https://opencollective.com/postcss/"
2003
+
},
2004
+
{
2005
+
"type": "tidelift",
2006
+
"url": "https://tidelift.com/funding/github/npm/postcss"
2007
+
},
2008
+
{
2009
+
"type": "github",
2010
+
"url": "https://github.com/sponsors/ai"
2011
+
}
2012
+
],
2013
+
"license": "MIT",
2014
+
"dependencies": {
2015
+
"nanoid": "^3.3.11",
2016
+
"picocolors": "^1.1.1",
2017
+
"source-map-js": "^1.2.1"
2018
+
},
2019
+
"engines": {
2020
+
"node": "^10 || ^12 || >=14"
2021
+
}
2022
+
},
2023
+
"node_modules/postcss-load-config": {
2024
+
"version": "3.1.4",
2025
+
"dev": true,
2026
+
"license": "MIT",
2027
+
"dependencies": {
2028
+
"lilconfig": "^2.0.5",
2029
+
"yaml": "^1.10.2"
2030
+
},
2031
+
"engines": {
2032
+
"node": ">= 10"
2033
+
},
2034
+
"funding": {
2035
+
"type": "opencollective",
2036
+
"url": "https://opencollective.com/postcss/"
2037
+
},
2038
+
"peerDependencies": {
2039
+
"postcss": ">=8.0.9",
2040
+
"ts-node": ">=9.0.0"
2041
+
},
2042
+
"peerDependenciesMeta": {
2043
+
"postcss": {
2044
+
"optional": true
2045
+
},
2046
+
"ts-node": {
2047
+
"optional": true
2048
+
}
2049
+
}
2050
+
},
2051
+
"node_modules/postcss-load-config/node_modules/yaml": {
2052
+
"version": "1.10.2",
2053
+
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
2054
+
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
2055
+
"dev": true,
2056
+
"license": "ISC",
2057
+
"engines": {
2058
+
"node": ">= 6"
2059
+
}
2060
+
},
2061
+
"node_modules/postcss-safe-parser": {
2062
+
"version": "7.0.1",
2063
+
"dev": true,
2064
+
"funding": [
2065
+
{
2066
+
"type": "opencollective",
2067
+
"url": "https://opencollective.com/postcss/"
2068
+
},
2069
+
{
2070
+
"type": "tidelift",
2071
+
"url": "https://tidelift.com/funding/github/npm/postcss-safe-parser"
2072
+
},
2073
+
{
2074
+
"type": "github",
2075
+
"url": "https://github.com/sponsors/ai"
2076
+
}
2077
+
],
2078
+
"license": "MIT",
2079
+
"engines": {
2080
+
"node": ">=18.0"
2081
+
},
2082
+
"peerDependencies": {
2083
+
"postcss": "^8.4.31"
2084
+
}
2085
+
},
2086
+
"node_modules/postcss-scss": {
2087
+
"version": "4.0.9",
2088
+
"dev": true,
2089
+
"funding": [
2090
+
{
2091
+
"type": "opencollective",
2092
+
"url": "https://opencollective.com/postcss/"
2093
+
},
2094
+
{
2095
+
"type": "tidelift",
2096
+
"url": "https://tidelift.com/funding/github/npm/postcss-scss"
2097
+
},
2098
+
{
2099
+
"type": "github",
2100
+
"url": "https://github.com/sponsors/ai"
2101
+
}
2102
+
],
2103
+
"license": "MIT",
2104
+
"engines": {
2105
+
"node": ">=12.0"
2106
+
},
2107
+
"peerDependencies": {
2108
+
"postcss": "^8.4.29"
2109
+
}
2110
+
},
2111
+
"node_modules/postcss-selector-parser": {
2112
+
"version": "7.1.0",
2113
+
"dev": true,
2114
+
"license": "MIT",
2115
+
"dependencies": {
2116
+
"cssesc": "^3.0.0",
2117
+
"util-deprecate": "^1.0.2"
2118
+
},
2119
+
"engines": {
2120
+
"node": ">=4"
2121
+
}
2122
+
},
2123
+
"node_modules/prelude-ls": {
2124
+
"version": "1.2.1",
2125
+
"dev": true,
2126
+
"license": "MIT",
2127
+
"engines": {
2128
+
"node": ">= 0.8.0"
2129
+
}
2130
+
},
2131
+
"node_modules/punycode": {
2132
+
"version": "2.3.1",
2133
+
"dev": true,
2134
+
"license": "MIT",
2135
+
"engines": {
2136
+
"node": ">=6"
2137
+
}
2138
+
},
2139
+
"node_modules/queue-microtask": {
2140
+
"version": "1.2.3",
2141
+
"dev": true,
2142
+
"funding": [
2143
+
{
2144
+
"type": "github",
2145
+
"url": "https://github.com/sponsors/feross"
2146
+
},
2147
+
{
2148
+
"type": "patreon",
2149
+
"url": "https://www.patreon.com/feross"
2150
+
},
2151
+
{
2152
+
"type": "consulting",
2153
+
"url": "https://feross.org/support"
2154
+
}
2155
+
],
2156
+
"license": "MIT"
2157
+
},
2158
+
"node_modules/readdirp": {
2159
+
"version": "4.1.2",
2160
+
"dev": true,
2161
+
"license": "MIT",
2162
+
"engines": {
2163
+
"node": ">= 14.18.0"
2164
+
},
2165
+
"funding": {
2166
+
"type": "individual",
2167
+
"url": "https://paulmillr.com/funding/"
2168
+
}
2169
+
},
2170
+
"node_modules/resolve": {
2171
+
"version": "1.22.11",
2172
+
"dev": true,
2173
+
"license": "MIT",
2174
+
"dependencies": {
2175
+
"is-core-module": "^2.16.1",
2176
+
"path-parse": "^1.0.7",
2177
+
"supports-preserve-symlinks-flag": "^1.0.0"
2178
+
},
2179
+
"bin": {
2180
+
"resolve": "bin/resolve"
2181
+
},
2182
+
"engines": {
2183
+
"node": ">= 0.4"
2184
+
},
2185
+
"funding": {
2186
+
"url": "https://github.com/sponsors/ljharb"
2187
+
}
2188
+
},
2189
+
"node_modules/resolve-from": {
2190
+
"version": "4.0.0",
2191
+
"dev": true,
2192
+
"license": "MIT",
2193
+
"engines": {
2194
+
"node": ">=4"
2195
+
}
2196
+
},
2197
+
"node_modules/reusify": {
2198
+
"version": "1.1.0",
2199
+
"dev": true,
2200
+
"license": "MIT",
2201
+
"engines": {
2202
+
"iojs": ">=1.0.0",
2203
+
"node": ">=0.10.0"
2204
+
}
2205
+
},
2206
+
"node_modules/rollup": {
2207
+
"version": "4.52.5",
2208
+
"dev": true,
2209
+
"license": "MIT",
2210
+
"dependencies": {
2211
+
"@types/estree": "1.0.8"
2212
+
},
2213
+
"bin": {
2214
+
"rollup": "dist/bin/rollup"
2215
+
},
2216
+
"engines": {
2217
+
"node": ">=18.0.0",
2218
+
"npm": ">=8.0.0"
2219
+
},
2220
+
"optionalDependencies": {
2221
+
"@rollup/rollup-android-arm-eabi": "4.52.5",
2222
+
"@rollup/rollup-android-arm64": "4.52.5",
2223
+
"@rollup/rollup-darwin-arm64": "4.52.5",
2224
+
"@rollup/rollup-darwin-x64": "4.52.5",
2225
+
"@rollup/rollup-freebsd-arm64": "4.52.5",
2226
+
"@rollup/rollup-freebsd-x64": "4.52.5",
2227
+
"@rollup/rollup-linux-arm-gnueabihf": "4.52.5",
2228
+
"@rollup/rollup-linux-arm-musleabihf": "4.52.5",
2229
+
"@rollup/rollup-linux-arm64-gnu": "4.52.5",
2230
+
"@rollup/rollup-linux-arm64-musl": "4.52.5",
2231
+
"@rollup/rollup-linux-loong64-gnu": "4.52.5",
2232
+
"@rollup/rollup-linux-ppc64-gnu": "4.52.5",
2233
+
"@rollup/rollup-linux-riscv64-gnu": "4.52.5",
2234
+
"@rollup/rollup-linux-riscv64-musl": "4.52.5",
2235
+
"@rollup/rollup-linux-s390x-gnu": "4.52.5",
2236
+
"@rollup/rollup-linux-x64-gnu": "4.52.5",
2237
+
"@rollup/rollup-linux-x64-musl": "4.52.5",
2238
+
"@rollup/rollup-openharmony-arm64": "4.52.5",
2239
+
"@rollup/rollup-win32-arm64-msvc": "4.52.5",
2240
+
"@rollup/rollup-win32-ia32-msvc": "4.52.5",
2241
+
"@rollup/rollup-win32-x64-gnu": "4.52.5",
2242
+
"@rollup/rollup-win32-x64-msvc": "4.52.5",
2243
+
"fsevents": "~2.3.2"
2244
+
}
2245
+
},
2246
+
"node_modules/run-parallel": {
2247
+
"version": "1.2.0",
2248
+
"dev": true,
2249
+
"funding": [
2250
+
{
2251
+
"type": "github",
2252
+
"url": "https://github.com/sponsors/feross"
2253
+
},
2254
+
{
2255
+
"type": "patreon",
2256
+
"url": "https://www.patreon.com/feross"
2257
+
},
2258
+
{
2259
+
"type": "consulting",
2260
+
"url": "https://feross.org/support"
2261
+
}
2262
+
],
2263
+
"license": "MIT",
2264
+
"dependencies": {
2265
+
"queue-microtask": "^1.2.2"
2266
+
}
2267
+
},
2268
+
"node_modules/sade": {
2269
+
"version": "1.8.1",
2270
+
"dev": true,
2271
+
"license": "MIT",
2272
+
"dependencies": {
2273
+
"mri": "^1.1.0"
2274
+
},
2275
+
"engines": {
2276
+
"node": ">=6"
2277
+
}
2278
+
},
2279
+
"node_modules/semver": {
2280
+
"version": "7.7.3",
2281
+
"dev": true,
2282
+
"license": "ISC",
2283
+
"bin": {
2284
+
"semver": "bin/semver.js"
2285
+
},
2286
+
"engines": {
2287
+
"node": ">=10"
2288
+
}
2289
+
},
2290
+
"node_modules/set-cookie-parser": {
2291
+
"version": "2.7.1",
2292
+
"dev": true,
2293
+
"license": "MIT"
2294
+
},
2295
+
"node_modules/shebang-command": {
2296
+
"version": "2.0.0",
2297
+
"dev": true,
2298
+
"license": "MIT",
2299
+
"dependencies": {
2300
+
"shebang-regex": "^3.0.0"
2301
+
},
2302
+
"engines": {
2303
+
"node": ">=8"
2304
+
}
2305
+
},
2306
+
"node_modules/shebang-regex": {
2307
+
"version": "3.0.0",
2308
+
"dev": true,
2309
+
"license": "MIT",
2310
+
"engines": {
2311
+
"node": ">=8"
2312
+
}
2313
+
},
2314
+
"node_modules/sirv": {
2315
+
"version": "3.0.2",
2316
+
"dev": true,
2317
+
"license": "MIT",
2318
+
"dependencies": {
2319
+
"@polka/url": "^1.0.0-next.24",
2320
+
"mrmime": "^2.0.0",
2321
+
"totalist": "^3.0.0"
2322
+
},
2323
+
"engines": {
2324
+
"node": ">=18"
2325
+
}
2326
+
},
2327
+
"node_modules/source-map-js": {
2328
+
"version": "1.2.1",
2329
+
"dev": true,
2330
+
"license": "BSD-3-Clause",
2331
+
"engines": {
2332
+
"node": ">=0.10.0"
2333
+
}
2334
+
},
2335
+
"node_modules/strip-json-comments": {
2336
+
"version": "3.1.1",
2337
+
"dev": true,
2338
+
"license": "MIT",
2339
+
"engines": {
2340
+
"node": ">=8"
2341
+
},
2342
+
"funding": {
2343
+
"url": "https://github.com/sponsors/sindresorhus"
2344
+
}
2345
+
},
2346
+
"node_modules/supports-color": {
2347
+
"version": "7.2.0",
2348
+
"dev": true,
2349
+
"license": "MIT",
2350
+
"dependencies": {
2351
+
"has-flag": "^4.0.0"
2352
+
},
2353
+
"engines": {
2354
+
"node": ">=8"
2355
+
}
2356
+
},
2357
+
"node_modules/supports-preserve-symlinks-flag": {
2358
+
"version": "1.0.0",
2359
+
"dev": true,
2360
+
"license": "MIT",
2361
+
"engines": {
2362
+
"node": ">= 0.4"
2363
+
},
2364
+
"funding": {
2365
+
"url": "https://github.com/sponsors/ljharb"
2366
+
}
2367
+
},
2368
+
"node_modules/svelte": {
2369
+
"version": "5.42.2",
2370
+
"dev": true,
2371
+
"license": "MIT",
2372
+
"dependencies": {
2373
+
"@jridgewell/remapping": "^2.3.4",
2374
+
"@jridgewell/sourcemap-codec": "^1.5.0",
2375
+
"@sveltejs/acorn-typescript": "^1.0.5",
2376
+
"@types/estree": "^1.0.5",
2377
+
"acorn": "^8.12.1",
2378
+
"aria-query": "^5.3.1",
2379
+
"axobject-query": "^4.1.0",
2380
+
"clsx": "^2.1.1",
2381
+
"esm-env": "^1.2.1",
2382
+
"esrap": "^2.1.0",
2383
+
"is-reference": "^3.0.3",
2384
+
"locate-character": "^3.0.0",
2385
+
"magic-string": "^0.30.11",
2386
+
"zimmerframe": "^1.1.2"
2387
+
},
2388
+
"engines": {
2389
+
"node": ">=18"
2390
+
}
2391
+
},
2392
+
"node_modules/svelte-check": {
2393
+
"version": "4.3.3",
2394
+
"dev": true,
2395
+
"license": "MIT",
2396
+
"dependencies": {
2397
+
"@jridgewell/trace-mapping": "^0.3.25",
2398
+
"chokidar": "^4.0.1",
2399
+
"fdir": "^6.2.0",
2400
+
"picocolors": "^1.0.0",
2401
+
"sade": "^1.7.4"
2402
+
},
2403
+
"bin": {
2404
+
"svelte-check": "bin/svelte-check"
2405
+
},
2406
+
"engines": {
2407
+
"node": ">= 18.0.0"
2408
+
},
2409
+
"peerDependencies": {
2410
+
"svelte": "^4.0.0 || ^5.0.0-next.0",
2411
+
"typescript": ">=5.0.0"
2412
+
}
2413
+
},
2414
+
"node_modules/svelte-eslint-parser": {
2415
+
"version": "1.4.0",
2416
+
"dev": true,
2417
+
"license": "MIT",
2418
+
"dependencies": {
2419
+
"eslint-scope": "^8.2.0",
2420
+
"eslint-visitor-keys": "^4.0.0",
2421
+
"espree": "^10.0.0",
2422
+
"postcss": "^8.4.49",
2423
+
"postcss-scss": "^4.0.9",
2424
+
"postcss-selector-parser": "^7.0.0"
2425
+
},
2426
+
"engines": {
2427
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0",
2428
+
"pnpm": "10.18.3"
2429
+
},
2430
+
"funding": {
2431
+
"url": "https://github.com/sponsors/ota-meshi"
2432
+
},
2433
+
"peerDependencies": {
2434
+
"svelte": "^3.37.0 || ^4.0.0 || ^5.0.0"
2435
+
},
2436
+
"peerDependenciesMeta": {
2437
+
"svelte": {
2438
+
"optional": true
2439
+
}
2440
+
}
2441
+
},
2442
+
"node_modules/tinyglobby": {
2443
+
"version": "0.2.15",
2444
+
"dev": true,
2445
+
"license": "MIT",
2446
+
"dependencies": {
2447
+
"fdir": "^6.5.0",
2448
+
"picomatch": "^4.0.3"
2449
+
},
2450
+
"engines": {
2451
+
"node": ">=12.0.0"
2452
+
},
2453
+
"funding": {
2454
+
"url": "https://github.com/sponsors/SuperchupuDev"
2455
+
}
2456
+
},
2457
+
"node_modules/to-regex-range": {
2458
+
"version": "5.0.1",
2459
+
"dev": true,
2460
+
"license": "MIT",
2461
+
"dependencies": {
2462
+
"is-number": "^7.0.0"
2463
+
},
2464
+
"engines": {
2465
+
"node": ">=8.0"
2466
+
}
2467
+
},
2468
+
"node_modules/totalist": {
2469
+
"version": "3.0.1",
2470
+
"dev": true,
2471
+
"license": "MIT",
2472
+
"engines": {
2473
+
"node": ">=6"
2474
+
}
2475
+
},
2476
+
"node_modules/ts-api-utils": {
2477
+
"version": "2.1.0",
2478
+
"dev": true,
2479
+
"license": "MIT",
2480
+
"engines": {
2481
+
"node": ">=18.12"
2482
+
},
2483
+
"peerDependencies": {
2484
+
"typescript": ">=4.8.4"
2485
+
}
2486
+
},
2487
+
"node_modules/type-check": {
2488
+
"version": "0.4.0",
2489
+
"dev": true,
2490
+
"license": "MIT",
2491
+
"dependencies": {
2492
+
"prelude-ls": "^1.2.1"
2493
+
},
2494
+
"engines": {
2495
+
"node": ">= 0.8.0"
2496
+
}
2497
+
},
2498
+
"node_modules/typescript": {
2499
+
"version": "5.9.3",
2500
+
"dev": true,
2501
+
"license": "Apache-2.0",
2502
+
"bin": {
2503
+
"tsc": "bin/tsc",
2504
+
"tsserver": "bin/tsserver"
2505
+
},
2506
+
"engines": {
2507
+
"node": ">=14.17"
2508
+
}
2509
+
},
2510
+
"node_modules/typescript-eslint": {
2511
+
"version": "8.46.2",
2512
+
"dev": true,
2513
+
"license": "MIT",
2514
+
"dependencies": {
2515
+
"@typescript-eslint/eslint-plugin": "8.46.2",
2516
+
"@typescript-eslint/parser": "8.46.2",
2517
+
"@typescript-eslint/typescript-estree": "8.46.2",
2518
+
"@typescript-eslint/utils": "8.46.2"
2519
+
},
2520
+
"engines": {
2521
+
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2522
+
},
2523
+
"funding": {
2524
+
"type": "opencollective",
2525
+
"url": "https://opencollective.com/typescript-eslint"
2526
+
},
2527
+
"peerDependencies": {
2528
+
"eslint": "^8.57.0 || ^9.0.0",
2529
+
"typescript": ">=4.8.4 <6.0.0"
2530
+
}
2531
+
},
2532
+
"node_modules/uint8arrays": {
2533
+
"version": "3.0.0",
2534
+
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz",
2535
+
"integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==",
2536
+
"license": "MIT",
2537
+
"dependencies": {
2538
+
"multiformats": "^9.4.2"
2539
+
}
2540
+
},
2541
+
"node_modules/undici-types": {
2542
+
"version": "6.21.0",
2543
+
"dev": true,
2544
+
"license": "MIT"
2545
+
},
2546
+
"node_modules/uri-js": {
2547
+
"version": "4.4.1",
2548
+
"dev": true,
2549
+
"license": "BSD-2-Clause",
2550
+
"dependencies": {
2551
+
"punycode": "^2.1.0"
2552
+
}
2553
+
},
2554
+
"node_modules/util-deprecate": {
2555
+
"version": "1.0.2",
2556
+
"dev": true,
2557
+
"license": "MIT"
2558
+
},
2559
+
"node_modules/vite": {
2560
+
"version": "7.1.12",
2561
+
"dev": true,
2562
+
"license": "MIT",
2563
+
"dependencies": {
2564
+
"esbuild": "^0.25.0",
2565
+
"fdir": "^6.5.0",
2566
+
"picomatch": "^4.0.3",
2567
+
"postcss": "^8.5.6",
2568
+
"rollup": "^4.43.0",
2569
+
"tinyglobby": "^0.2.15"
2570
+
},
2571
+
"bin": {
2572
+
"vite": "bin/vite.js"
2573
+
},
2574
+
"engines": {
2575
+
"node": "^20.19.0 || >=22.12.0"
2576
+
},
2577
+
"funding": {
2578
+
"url": "https://github.com/vitejs/vite?sponsor=1"
2579
+
},
2580
+
"optionalDependencies": {
2581
+
"fsevents": "~2.3.3"
2582
+
},
2583
+
"peerDependencies": {
2584
+
"@types/node": "^20.19.0 || >=22.12.0",
2585
+
"jiti": ">=1.21.0",
2586
+
"less": "^4.0.0",
2587
+
"lightningcss": "^1.21.0",
2588
+
"sass": "^1.70.0",
2589
+
"sass-embedded": "^1.70.0",
2590
+
"stylus": ">=0.54.8",
2591
+
"sugarss": "^5.0.0",
2592
+
"terser": "^5.16.0",
2593
+
"tsx": "^4.8.1",
2594
+
"yaml": "^2.4.2"
2595
+
},
2596
+
"peerDependenciesMeta": {
2597
+
"@types/node": {
2598
+
"optional": true
2599
+
},
2600
+
"jiti": {
2601
+
"optional": true
2602
+
},
2603
+
"less": {
2604
+
"optional": true
2605
+
},
2606
+
"lightningcss": {
2607
+
"optional": true
2608
+
},
2609
+
"sass": {
2610
+
"optional": true
2611
+
},
2612
+
"sass-embedded": {
2613
+
"optional": true
2614
+
},
2615
+
"stylus": {
2616
+
"optional": true
2617
+
},
2618
+
"sugarss": {
2619
+
"optional": true
2620
+
},
2621
+
"terser": {
2622
+
"optional": true
2623
+
},
2624
+
"tsx": {
2625
+
"optional": true
2626
+
},
2627
+
"yaml": {
2628
+
"optional": true
2629
+
}
2630
+
}
2631
+
},
2632
+
"node_modules/vitefu": {
2633
+
"version": "1.1.1",
2634
+
"dev": true,
2635
+
"license": "MIT",
2636
+
"workspaces": [
2637
+
"tests/deps/*",
2638
+
"tests/projects/*",
2639
+
"tests/projects/workspace/packages/*"
2640
+
],
2641
+
"peerDependencies": {
2642
+
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0"
2643
+
},
2644
+
"peerDependenciesMeta": {
2645
+
"vite": {
2646
+
"optional": true
2647
+
}
2648
+
}
2649
+
},
2650
+
"node_modules/which": {
2651
+
"version": "2.0.2",
2652
+
"dev": true,
2653
+
"license": "ISC",
2654
+
"dependencies": {
2655
+
"isexe": "^2.0.0"
2656
+
},
2657
+
"bin": {
2658
+
"node-which": "bin/node-which"
2659
+
},
2660
+
"engines": {
2661
+
"node": ">= 8"
2662
+
}
2663
+
},
2664
+
"node_modules/word-wrap": {
2665
+
"version": "1.2.5",
2666
+
"dev": true,
2667
+
"license": "MIT",
2668
+
"engines": {
2669
+
"node": ">=0.10.0"
2670
+
}
2671
+
},
2672
+
"node_modules/yaml": {
2673
+
"version": "2.8.1",
2674
+
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
2675
+
"integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
2676
+
"dev": true,
2677
+
"license": "ISC",
2678
+
"optional": true,
2679
+
"peer": true,
2680
+
"bin": {
2681
+
"yaml": "bin.mjs"
2682
+
},
2683
+
"engines": {
2684
+
"node": ">= 14.6"
2685
+
}
2686
+
},
2687
+
"node_modules/yocto-queue": {
2688
+
"version": "0.1.0",
2689
+
"dev": true,
2690
+
"license": "MIT",
2691
+
"engines": {
2692
+
"node": ">=10"
2693
+
},
2694
+
"funding": {
2695
+
"url": "https://github.com/sponsors/sindresorhus"
2696
+
}
2697
+
},
2698
+
"node_modules/zimmerframe": {
2699
+
"version": "1.1.4",
2700
+
"dev": true,
2701
+
"license": "MIT"
2702
+
},
2703
+
"node_modules/zod": {
2704
+
"version": "3.25.76",
2705
+
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
2706
+
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
2707
+
"license": "MIT",
2708
+
"funding": {
2709
+
"url": "https://github.com/sponsors/colinhacks"
2710
+
}
2711
+
}
2712
+
}
2713
+
}
+41
web-ui/package.json
+41
web-ui/package.json
···
1
+
{
2
+
"name": "web-ui",
3
+
"private": true,
4
+
"version": "0.0.1",
5
+
"type": "module",
6
+
"scripts": {
7
+
"dev": "vite dev",
8
+
"build": "vite build",
9
+
"preview": "vite preview",
10
+
"prepare": "svelte-kit sync || echo ''",
11
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
12
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
13
+
"lint": "eslint ."
14
+
},
15
+
"dependencies": {
16
+
"@atcute/client": "^4.0.5",
17
+
"@atcute/lexicons": "^1.2.2",
18
+
"@pds-moover/lexicons": "^1.0.1",
19
+
"@pds-moover/moover": "^1.0.4"
20
+
},
21
+
"devDependencies": {
22
+
"@eslint/compat": "^1.4.0",
23
+
"@eslint/js": "^9.36.0",
24
+
"@sveltejs/adapter-auto": "^6.1.0",
25
+
"@sveltejs/adapter-node": "^5.4.0",
26
+
"@sveltejs/kit": "^2.43.2",
27
+
"@sveltejs/vite-plugin-svelte": "^6.2.0",
28
+
"@types/node": "^22",
29
+
"eslint": "^9.36.0",
30
+
"eslint-plugin-svelte": "^3.12.4",
31
+
"globals": "^16.4.0",
32
+
"svelte": "^5.39.5",
33
+
"svelte-check": "^4.3.2",
34
+
"typescript": "^5.9.2",
35
+
"typescript-eslint": "^8.44.1",
36
+
"vite": "^7.1.7"
37
+
},
38
+
"optionalDependencies": {
39
+
"@rollup/rollup-linux-x64-musl": "^4.52.5"
40
+
}
41
+
}
+15
web-ui/src/app.d.ts
+15
web-ui/src/app.d.ts
···
1
+
import {} from '@pds-moover/lexicons'
2
+
3
+
// See https://svelte.dev/docs/kit/types#app.d.ts
4
+
// for information about these interfaces
5
+
declare global {
6
+
namespace App {
7
+
// interface Error {}
8
+
// interface Locals {}
9
+
// interface PageData {}
10
+
// interface PageState {}
11
+
// interface Platform {}
12
+
}
13
+
}
14
+
15
+
export {};
+11
web-ui/src/app.html
+11
web-ui/src/app.html
···
1
+
<!doctype html>
2
+
<html lang="en">
3
+
<head>
4
+
<meta charset="utf-8" />
5
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6
+
%sveltekit.head%
7
+
</head>
8
+
<body data-sveltekit-preload-data="hover">
9
+
<div style="display: contents">%sveltekit.body%</div>
10
+
</body>
11
+
</html>
+1
web-ui/src/lib/assets/favicon.svg
+1
web-ui/src/lib/assets/favicon.svg
···
1
+
<svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.157 22.819c-10.4-14.885-30.94-19.297-45.792-9.835L22.282 29.608A29.92 29.92 0 0 0 8.764 49.65a31.5 31.5 0 0 0 3.108 20.231 30 30 0 0 0-4.477 11.183 31.9 31.9 0 0 0 5.448 24.116c10.402 14.887 30.942 19.297 45.791 9.835l26.083-16.624A29.92 29.92 0 0 0 98.235 78.35a31.53 31.53 0 0 0-3.105-20.232 30 30 0 0 0 4.474-11.182 31.88 31.88 0 0 0-5.447-24.116" style="fill:#ff3e00"/><path d="M45.817 106.582a20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.503 18 18 0 0 1 .624-2.435l.49-1.498 1.337.981a33.6 33.6 0 0 0 10.203 5.098l.97.294-.09.968a5.85 5.85 0 0 0 1.052 3.878 6.24 6.24 0 0 0 6.695 2.485 5.8 5.8 0 0 0 1.603-.704L69.27 76.28a5.43 5.43 0 0 0 2.45-3.631 5.8 5.8 0 0 0-.987-4.371 6.24 6.24 0 0 0-6.698-2.487 5.7 5.7 0 0 0-1.6.704l-9.953 6.345a19 19 0 0 1-5.296 2.326 20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.502 17.99 17.99 0 0 1 8.13-12.052l26.081-16.623a19 19 0 0 1 5.3-2.329 20.72 20.72 0 0 1 22.237 8.243 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-.624 2.435l-.49 1.498-1.337-.98a33.6 33.6 0 0 0-10.203-5.1l-.97-.294.09-.968a5.86 5.86 0 0 0-1.052-3.878 6.24 6.24 0 0 0-6.696-2.485 5.8 5.8 0 0 0-1.602.704L37.73 51.72a5.42 5.42 0 0 0-2.449 3.63 5.79 5.79 0 0 0 .986 4.372 6.24 6.24 0 0 0 6.698 2.486 5.8 5.8 0 0 0 1.602-.704l9.952-6.342a19 19 0 0 1 5.295-2.328 20.72 20.72 0 0 1 22.237 8.242 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-8.13 12.053l-26.081 16.622a19 19 0 0 1-5.3 2.328" style="fill:#fff"/></svg>
+27
web-ui/src/lib/components/LoadingSpinner.svelte
+27
web-ui/src/lib/components/LoadingSpinner.svelte
···
1
+
<script lang="ts">
2
+
let { size = 16, className = '' }: { size?: number; className?: string } = $props();
3
+
</script>
4
+
5
+
<svg
6
+
class="spinner {className}"
7
+
viewBox="0 0 24 24"
8
+
style="display: inline-block; width: {size}px; height: {size}px; margin-right: 8px;"
9
+
>
10
+
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="3" fill="none" opacity="0.25" />
11
+
<path
12
+
d="M12 2 A10 10 0 0 1 22 12"
13
+
stroke="currentColor"
14
+
stroke-width="3"
15
+
fill="none"
16
+
stroke-linecap="round"
17
+
>
18
+
<animateTransform
19
+
attributeName="transform"
20
+
type="rotate"
21
+
from="0 12 12"
22
+
to="360 12 12"
23
+
dur="1s"
24
+
repeatCount="indefinite"
25
+
/>
26
+
</path>
27
+
</svg>
+31
web-ui/src/lib/components/MooHeader.svelte
+31
web-ui/src/lib/components/MooHeader.svelte
···
1
+
<script lang="ts">
2
+
import cowPicture from '$lib/assets/moo.webp'
3
+
4
+
let {title, customImg = null} = $props();
5
+
6
+
</script>
7
+
8
+
9
+
<div>
10
+
<h1>{ title }</h1>
11
+
<div class="cow-image">
12
+
{#if customImg === null }
13
+
<img src={cowPicture} alt="Cartoon milk cow"
14
+
style="max-width: 100%; max-height: 100%; object-fit: contain;">
15
+
{:else}
16
+
{@render customImg()}
17
+
{/if}
18
+
</div>
19
+
<div class="made-by-blur">Made by <a href="https://bsky.app/profile/baileytownsend.dev">@baileytownsend.dev</a>
20
+
</div>
21
+
<div class="support-buttons">
22
+
<span class="kofi-slot">
23
+
<a href='https://ko-fi.com/T6T61FYPX' target='_blank'><img height='36' style='border:0px;height:36px;'
24
+
src='https://storage.ko-fi.com/cdn/kofi1.png?v=6'
25
+
border='0'
26
+
alt='Buy Me a Coffee at ko-fi.com'/></a>
27
+
</span>
28
+
<iframe src="https://github.com/sponsors/fatfingers23/button" title="Sponsor fatfingers23" height="32"
29
+
width="114" style="border: 0; border-radius: 6px;"></iframe>
30
+
</div>
31
+
</div>
+4
web-ui/src/lib/components/OgImage.svelte
+4
web-ui/src/lib/components/OgImage.svelte
+74
web-ui/src/lib/components/RotationKeyDisplay.svelte
+74
web-ui/src/lib/components/RotationKeyDisplay.svelte
···
1
+
<script lang="ts">
2
+
import {handleAndPDSResolver} from '@pds-moover/moover'
3
+
import type {RotationKeyType} from '$lib/types';
4
+
5
+
6
+
let {handle, rotationKey}: {
7
+
handle: string,
8
+
rotationKey: RotationKeyType
9
+
} = $props();
10
+
11
+
12
+
const copyToClipboard = async (text: string) => {
13
+
try {
14
+
await navigator.clipboard.writeText(text);
15
+
alert('Copied to clipboard');
16
+
} catch (e) {
17
+
console.error(e);
18
+
alert('Failed to copy to clipboard');
19
+
}
20
+
}
21
+
22
+
const downloadNewRotationKey = async (rotationKey: RotationKeyType, handle: string) => {
23
+
if (!rotationKey) return;
24
+
//try and find the did to add to the file as well
25
+
let didText = '';
26
+
try {
27
+
let {usersDid} = await handleAndPDSResolver(handle);
28
+
didText = `DID: ${usersDid}\n`;
29
+
} catch (e) {
30
+
//sliently log. Rather the user have their rotation key than not. a did can always be found other ways if needed
31
+
console.error(e);
32
+
}
33
+
34
+
const content = `You can use these to recover your account if it's ever necessary via https://pdsmoover.com/restore. The restore process will ask for the Private key\n\nKEEP IN A SECURE LOCATION\n\n${didText}PublicKey: ${rotationKey.publicKey}\nPrivateKey: ${rotationKey.privateKey}\n`;
35
+
const blob = new Blob([content], {type: 'text/plain'});
36
+
const url = URL.createObjectURL(blob);
37
+
const a = document.createElement('a');
38
+
a.href = url;
39
+
40
+
41
+
a.download = `${handle}-rotation-key.txt`;
42
+
document.body.appendChild(a);
43
+
a.click();
44
+
document.body.removeChild(a);
45
+
URL.revokeObjectURL(url);
46
+
}
47
+
</script>
48
+
49
+
50
+
<div class="section" style="margin-top: 16px; border: 2px solid #f39c12; padding: 16px;">
51
+
<h3 style="color: #d35400;">Important: Save Your New Rotation Key Now</h3>
52
+
<p style="color: #c0392b; font-weight: bold;">
53
+
Warning: This is the only time we will show you your private rotation key. Save it in a secure place.
54
+
If you lose it, you may not be able to recover your account in the event of a PDS failure or hijack.
55
+
</p>
56
+
<div class="form-group">
57
+
<span>New Rotation Key (Private - keep secret)</span>
58
+
<div style="display:flex; gap:8px; align-items:center;">
59
+
{#if rotationKey}
60
+
<code
61
+
style="overflow-wrap:anywhere;">{rotationKey.privateKey}</code>
62
+
{/if}
63
+
64
+
<button type="button"
65
+
onclick={async () => await copyToClipboard(rotationKey.privateKey)}>Copy
66
+
</button>
67
+
</div>
68
+
</div>
69
+
<div class="form-group">
70
+
<button type="button" onclick={async () => await downloadNewRotationKey(rotationKey, handle)}>Download
71
+
Key File
72
+
</button>
73
+
</div>
74
+
</div>
+1
web-ui/src/lib/index.ts
+1
web-ui/src/lib/index.ts
···
1
+
// place files you want to import through the `$lib` alias in this folder.
+4
web-ui/src/lib/types.ts
+4
web-ui/src/lib/types.ts
+23
web-ui/src/lib/utils/displayUtils.ts
+23
web-ui/src/lib/utils/displayUtils.ts
···
1
+
function formatBytes(bytes: number | null) {
2
+
if (bytes == null) return '—';
3
+
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
4
+
let i = 0;
5
+
let v = Number(bytes);
6
+
while (v >= 1024 && i < units.length - 1) {
7
+
v /= 1024;
8
+
i++;
9
+
}
10
+
return v.toFixed(1) + ' ' + units[i];
11
+
}
12
+
13
+
function formatDate(value: string | undefined) {
14
+
if (!value) return '—';
15
+
try {
16
+
const d = new Date(value);
17
+
return d.toLocaleString();
18
+
} catch (_) {
19
+
return String(value);
20
+
}
21
+
}
22
+
23
+
export {formatBytes, formatDate};
+20
web-ui/src/routes/+layout.svelte
+20
web-ui/src/routes/+layout.svelte
···
1
+
<script lang="ts">
2
+
import favicon from '$lib/assets/moo.webp';
3
+
import '$lib/assets/style.css'
4
+
import NavBar from '$lib/components/NavBar.svelte';
5
+
6
+
let {children} = $props();
7
+
8
+
9
+
</script>
10
+
11
+
<svelte:head>
12
+
<link rel="icon" href={favicon}/>
13
+
</svelte:head>
14
+
15
+
16
+
<NavBar/>
17
+
18
+
<main class="page-content">
19
+
{@render children?.()}
20
+
</main>
+79
web-ui/src/routes/+page.svelte
+79
web-ui/src/routes/+page.svelte
···
1
+
<script lang="ts">
2
+
import MooHeader from '$lib/components/MooHeader.svelte';
3
+
import type {PageProps} from '../../.svelte-kit/types/src/routes/$types';
4
+
import {formatDate, formatBytes} from '$lib/utils/displayUtils';
5
+
import {resolve} from '$app/paths';
6
+
import OgImage from '$lib/components/OgImage.svelte';
7
+
8
+
let {data}: PageProps = $props();
9
+
let repoSize = $derived(formatBytes(data.estimatedReposSizeOnDisk));
10
+
let blobSize = $derived(formatBytes(data.estimatedBlobsSizeOnDisk));
11
+
let lastBackedUp = $derived(formatDate(data.lastBackupAt))
12
+
let lastStatusUpdate = $derived(formatDate(data.statusLastUpdated))
13
+
14
+
</script>
15
+
16
+
<svelte:head>
17
+
<title>PDS MOOver</title>
18
+
<meta property="og:description" content="PDS MOOver – ATProto tools for PDS migrations and backups"/>
19
+
<OgImage/>
20
+
</svelte:head>
21
+
22
+
<div class="container">
23
+
24
+
<MooHeader title="PDS MOOver"/>
25
+
<section class="section" style="text-align:left">
26
+
<p>
27
+
PDS MOOver is a set of AT Protocol tools to help you
28
+
<a href={resolve('/moover')}>migrate to a new PDS</a>,
29
+
<a href="/missing-blobs">find your missing blobs</a>,
30
+
sign up for free automated <a href="/backups">backups</a>, and <a href="/restore">restore your account</a>
31
+
in the event you need to.
32
+
</p>
33
+
<ul>
34
+
<li><a href={resolve('/moover')}>Moover</a> – helps you migrate to a new PDS.</li>
35
+
<li><a href="/missing-blobs">Missing Blobs</a> – find any missing blobs (pictures/videos) from a previous
36
+
migration.
37
+
</li>
38
+
<li><a href="/backups">Backups</a> – sign up for free automated backups stored on PDS MOOver servers and
39
+
view your account's backup status.
40
+
</li>
41
+
<li><a href="/restore">Restore</a> – restore from your backups if needed.</li>
42
+
<li><a href="/turn-off">Turn Off</a> – helper to make sure your old account is deactivated.</li>
43
+
<li><a href={resolve('/info')}>Info</a> – FAQs and a few other bits of information about our tools.</li>
44
+
<li><a href="https://tangled.org/@baileytownsend.dev/pds-moover">Check our source code on tangled</a></li>
45
+
</ul>
46
+
</section>
47
+
48
+
<section class="section" aria-labelledby="stats-heading">
49
+
<h2 id="stats-heading">Server stats</h2>
50
+
<span>Total stats for all accounts backed up on pdsmoover.com</span>
51
+
<div style="padding-top: 5%" class="stats-grid">
52
+
<div class="stat-card">
53
+
<div class="stat-label">Total repositories</div>
54
+
<div class="stat-value">{data.totalRepos.toLocaleString()}</div>
55
+
</div>
56
+
<div class="stat-card">
57
+
<div class="stat-label">Total blobs</div>
58
+
<div class="stat-value">{data.totalBlobs.toLocaleString()}</div>
59
+
</div>
60
+
<div class="stat-card">
61
+
<div class="stat-label">Estimated total repo size</div>
62
+
<div class="stat-value">{repoSize}</div>
63
+
</div>
64
+
<div class="stat-card">
65
+
<div class="stat-label">Estimated total blob size</div>
66
+
<div class="stat-value">{blobSize}</div>
67
+
</div>
68
+
<div class="stat-card">
69
+
<div class="stat-label">Last backup ran at</div>
70
+
<div class="stat-value stat-value--small">{lastBackedUp}</div>
71
+
</div>
72
+
<div class="stat-card">
73
+
<div class="stat-label">Server Status last updated</div>
74
+
<div class="stat-value stat-value--small">{lastStatusUpdate}</div>
75
+
</div>
76
+
</div>
77
+
<!-- <div class="warning-message" x-show="error" x-text="error"></div>-->
78
+
</section>
79
+
</div>
+15
web-ui/src/routes/+page.ts
+15
web-ui/src/routes/+page.ts
···
1
+
import {Client, ok, simpleFetchHandler} from '@atcute/client';
2
+
import {ComPdsmooverBackupDescribeServer} from '@pds-moover/lexicons';
3
+
import type {PageLoad} from './$types';
4
+
import {PUBLIC_XRPC_BASE} from '$env/static/public';
5
+
import type {InferXRPCBodyOutput} from '@atcute/lexicons';
6
+
7
+
export const load: PageLoad = async () => {
8
+
const handler = simpleFetchHandler({service: `https://${PUBLIC_XRPC_BASE}`});
9
+
const rpc = new Client({handler});
10
+
return await ok(
11
+
//@ts-expect-error: says it's not assignable to never
12
+
rpc.get('com.pdsmoover.backup.describeServer'),
13
+
) as InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>
14
+
15
+
};
+187
web-ui/src/routes/backups/+page.svelte
+187
web-ui/src/routes/backups/+page.svelte
···
1
+
<script lang="ts">
2
+
import {BackupService, PlcOps} from '@pds-moover/moover';
3
+
import MooHeader from '$lib/components/MooHeader.svelte';
4
+
import SignUpForm from './SignUpForm.svelte';
5
+
import RepoStatus from './RepoStatus.svelte';
6
+
import LoadingSpinner from '$lib/components/LoadingSpinner.svelte';
7
+
import type {InferXRPCBodyOutput} from '@atcute/lexicons';
8
+
import {ComPdsmooverBackupGetRepoStatus} from '@pds-moover/lexicons';
9
+
import {PUBLIC_XRPC_BASE} from '$env/static/public';
10
+
11
+
12
+
// Service instances
13
+
let backupService = $state(new BackupService(`did:web:${PUBLIC_XRPC_BASE}`));
14
+
let plcOps = $state(new PlcOps());
15
+
16
+
// State variables
17
+
let handle = $state('');
18
+
let password = $state('');
19
+
let twoFactorCode = $state('');
20
+
let showTwoFactorCodeInput = $state(false);
21
+
let errorMessage = $state<string | null>(null);
22
+
let showStatusMessage = $state(false);
23
+
let showLoginScreen = $state(true);
24
+
let showRepoNotFoundScreen = $state(false);
25
+
let repoStatus = $state<null | InferXRPCBodyOutput<
26
+
ComPdsmooverBackupGetRepoStatus.mainSchema['output']
27
+
>>(null);
28
+
let statusMessageText = $state('');
29
+
let isLoggingIn = $state(false);
30
+
31
+
function updateStatusHandler(status: string) {
32
+
console.log('Status update:', status);
33
+
statusMessageText = status;
34
+
}
35
+
36
+
async function handleLoginSubmit() {
37
+
errorMessage = null;
38
+
showStatusMessage = false;
39
+
isLoggingIn = true;
40
+
41
+
try {
42
+
if (showTwoFactorCodeInput && !twoFactorCode) {
43
+
errorMessage = 'Please enter the 2FA that was sent to your email.';
44
+
isLoggingIn = false;
45
+
return;
46
+
}
47
+
statusMessageText = 'Logging in...';
48
+
showStatusMessage = true;
49
+
const result = await backupService.loginAndStatus(
50
+
handle,
51
+
password,
52
+
updateStatusHandler,
53
+
twoFactorCode
54
+
);
55
+
if (result === null) {
56
+
showRepoNotFoundScreen = true;
57
+
showLoginScreen = false;
58
+
showStatusMessage = false;
59
+
} else {
60
+
repoStatus = result;
61
+
showLoginScreen = false;
62
+
showStatusMessage = false;
63
+
}
64
+
} catch (e) {
65
+
console.error(e);
66
+
showStatusMessage = false;
67
+
//@ts-expect-error: Error is handled
68
+
if (e.error === 'AuthFactorTokenRequired') {
69
+
showTwoFactorCodeInput = true;
70
+
errorMessage = 'Two-factor code required. Check your email and enter the code.';
71
+
} else {
72
+
//@ts-expect-error: Error is handled
73
+
errorMessage = e.message || 'An unexpected error occurred.';
74
+
}
75
+
} finally {
76
+
isLoggingIn = false;
77
+
}
78
+
}
79
+
80
+
function handleSignUpComplete(
81
+
status: InferXRPCBodyOutput<ComPdsmooverBackupGetRepoStatus.mainSchema['output']>
82
+
) {
83
+
repoStatus = status;
84
+
showRepoNotFoundScreen = false;
85
+
showLoginScreen = false;
86
+
}
87
+
</script>
88
+
89
+
<svelte:head>
90
+
<title>PDS MOOver - Backups</title>
91
+
<meta property="og:description" content="PDS MOOver backups"/>
92
+
<meta property="og:image" content="/halloween_moover.webp"/>
93
+
</svelte:head>
94
+
95
+
<div class="container">
96
+
<MooHeader title="Backups"/>
97
+
98
+
<!-- Login Screen -->
99
+
{#if showLoginScreen}
100
+
<div class="section" style="text-align: left;">
101
+
<p>
102
+
PDS MOOver can provide worry-free backups of your AT Protocol account. This is a free
103
+
service for individual accounts and stores the backups on PDS MOOver's servers. Just like
104
+
your <a
105
+
target="_blank"
106
+
rel="noopener noreferrer"
107
+
href="https://blueskyweb.zendesk.com/hc/en-us/articles/15835264007693-Data-Privacy"
108
+
>AT Proto data</a
109
+
>, this is also public. On login, you will be asked if you'd like to add a rotation key to
110
+
your account. A rotation key is a recovery key that allows you to restore your account if
111
+
your PDS ever goes down. If you're already signed up for backups, then you can log in here
112
+
to manage them.
113
+
</p>
114
+
</div>
115
+
116
+
<form
117
+
id="backup-signup-form"
118
+
onsubmit={(e) => {
119
+
e.preventDefault();
120
+
handleLoginSubmit();
121
+
}}
122
+
>
123
+
<div class="section">
124
+
<h2>Sign in to your account</h2>
125
+
<div class="form-group">
126
+
<label for="handle">Handle</label>
127
+
<input
128
+
type="text"
129
+
id="handle"
130
+
name="handle"
131
+
placeholder="alice.bsky.social"
132
+
bind:value={handle}
133
+
required
134
+
/>
135
+
</div>
136
+
137
+
<div class="form-group">
138
+
<label for="password">Real Password</label>
139
+
<input type="password" id="password" name="password" bind:value={password} required/>
140
+
<p>
141
+
If you are signing up and adding a rotation key you have to use your account's real
142
+
password. If you are just managing your backups or have your own rotation key you can use
143
+
an app password
144
+
</p>
145
+
</div>
146
+
147
+
{#if showTwoFactorCodeInput}
148
+
<div class="form-group">
149
+
<label for="two-factor-code">Two-factor code (email)</label>
150
+
<input
151
+
type="text"
152
+
id="two-factor-code"
153
+
name="two-factor-code"
154
+
bind:value={twoFactorCode}
155
+
/>
156
+
<div class="error-message">Enter the 2FA code from your email.</div>
157
+
</div>
158
+
{/if}
159
+
</div>
160
+
161
+
{#if errorMessage}
162
+
<div class="error-message">{errorMessage}</div>
163
+
{/if}
164
+
{#if showStatusMessage}
165
+
<div class="status-message">{statusMessageText}</div>
166
+
{/if}
167
+
<div>
168
+
<button type="submit" disabled={isLoggingIn}>
169
+
{#if isLoggingIn}
170
+
<LoadingSpinner/>
171
+
{/if}
172
+
Login for backups
173
+
</button>
174
+
</div>
175
+
</form>
176
+
{/if}
177
+
178
+
<!-- Sign Up Screen -->
179
+
{#if showRepoNotFoundScreen}
180
+
<SignUpForm {backupService} {plcOps} {handle} onComplete={handleSignUpComplete}/>
181
+
{/if}
182
+
183
+
<!-- Repo Status View -->
184
+
{#if repoStatus && !showLoginScreen && !showRepoNotFoundScreen}
185
+
<RepoStatus {backupService} bind:repoStatus/>
186
+
{/if}
187
+
</div>
+181
web-ui/src/routes/backups/RepoStatus.svelte
+181
web-ui/src/routes/backups/RepoStatus.svelte
···
1
+
<script lang="ts">
2
+
import type {BackupService} from '@pds-moover/moover';
3
+
import type {InferXRPCBodyOutput} from '@atcute/lexicons';
4
+
import {ComPdsmooverBackupGetRepoStatus} from '@pds-moover/lexicons';
5
+
import {formatDate, formatBytes} from '$lib/utils/displayUtils';
6
+
import LoadingSpinner from '$lib/components/LoadingSpinner.svelte';
7
+
8
+
9
+
let {
10
+
backupService,
11
+
repoStatus = $bindable()
12
+
}: {
13
+
backupService: BackupService;
14
+
repoStatus: InferXRPCBodyOutput<ComPdsmooverBackupGetRepoStatus.mainSchema['output']> | null;
15
+
} = $props();
16
+
17
+
// State variables
18
+
let errorMessage = $state<string | null>(null);
19
+
let showStatusMessage = $state(false);
20
+
let statusMessageText = $state('');
21
+
let isRefreshing = $state(false);
22
+
let isRunningBackup = $state(false);
23
+
let isDeleting = $state(false);
24
+
25
+
function updateStatusHandler(status: string) {
26
+
console.log('Status update:', status);
27
+
statusMessageText = status;
28
+
}
29
+
30
+
async function handleRunBackupNow() {
31
+
errorMessage = null;
32
+
isRunningBackup = true;
33
+
showStatusMessage = true;
34
+
try {
35
+
await backupService.runBackupNow(updateStatusHandler);
36
+
repoStatus = await backupService.getUsersRepoStatus(updateStatusHandler);
37
+
updateStatusHandler('Backup request sent. Status refreshed.');
38
+
showStatusMessage = false;
39
+
} catch (e) {
40
+
console.error(e);
41
+
//@ts-expect-error: Error is handled
42
+
errorMessage = e.message || 'Failed to request backup.';
43
+
} finally {
44
+
isRunningBackup = false;
45
+
}
46
+
}
47
+
48
+
async function handleRemoveRepo() {
49
+
if (
50
+
confirm(
51
+
'Deleting your backups removes all your data and unregisters you for automatic backups. Your rotation key created here will stay valid, but you will not be able to restore your data from PDS MOOver.'
52
+
)
53
+
) {
54
+
isDeleting = true;
55
+
try {
56
+
await backupService.removeRepo(updateStatusHandler);
57
+
repoStatus = await backupService.getUsersRepoStatus(updateStatusHandler);
58
+
} catch (e) {
59
+
console.error(e);
60
+
//@ts-expect-error: Error is handled
61
+
errorMessage = e.message || 'Failed to delete backup repository';
62
+
} finally {
63
+
isDeleting = false;
64
+
}
65
+
}
66
+
}
67
+
68
+
async function refreshStatus() {
69
+
isRefreshing = true;
70
+
try {
71
+
repoStatus = await backupService.getUsersRepoStatus(updateStatusHandler);
72
+
} catch (e) {
73
+
console.error(e);
74
+
//@ts-expect-error: Error is handled
75
+
errorMessage = e.message || 'Failed to refresh status';
76
+
} finally {
77
+
showStatusMessage = false;
78
+
isRefreshing = false;
79
+
}
80
+
}
81
+
</script>
82
+
83
+
<div class="section">
84
+
<div class="section-header">
85
+
<h2 style="margin: 0;">Backup repository status</h2>
86
+
<button
87
+
type="button"
88
+
class="icon-button"
89
+
title="Refresh status"
90
+
aria-label="Refresh status"
91
+
onclick={refreshStatus}
92
+
disabled={isRefreshing}
93
+
style={isRefreshing ? 'opacity: 0.6;' : ''}
94
+
>
95
+
<svg class="icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"
96
+
style={isRefreshing ? 'animation: spin 1s linear infinite;' : ''}>
97
+
<path
98
+
d="M17.65 6.35A7.95 7.95 0 0012 4a8 8 0 108 8h-2a6 6 0 11-6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"
99
+
></path>
100
+
</svg>
101
+
</button>
102
+
</div>
103
+
<div class="stats-grid">
104
+
<div class="stat-card">
105
+
<div class="stat-label">DID</div>
106
+
<div class="stat-value stat-value--small">{repoStatus?.did || '—'}</div>
107
+
</div>
108
+
<div class="stat-card">
109
+
<div class="stat-label">Created</div>
110
+
<div class="stat-value stat-value--small">{formatDate(repoStatus?.createdAt)}</div>
111
+
</div>
112
+
{#if repoStatus?.lastBackup != null}
113
+
<div class="stat-card">
114
+
<div class="stat-label">Last backup</div>
115
+
<div class="stat-value stat-value--small">{formatDate(repoStatus.lastBackup)}</div>
116
+
</div>
117
+
{/if}
118
+
{#if repoStatus?.rev != null}
119
+
<div class="stat-card">
120
+
<div class="stat-label">Current rev</div>
121
+
<div class="stat-value stat-value--small">{repoStatus.rev}</div>
122
+
</div>
123
+
{/if}
124
+
{#if repoStatus?.blobCount != null}
125
+
<div class="stat-card">
126
+
<div class="stat-label">Total blobs</div>
127
+
<div class="stat-value">{repoStatus.blobCount.toLocaleString()}</div>
128
+
</div>
129
+
{/if}
130
+
{#if repoStatus?.estimatedBackupSize != null}
131
+
<div class="stat-card">
132
+
<div class="stat-label">Estimated size</div>
133
+
<div class="stat-value">{formatBytes(repoStatus.estimatedBackupSize)}</div>
134
+
</div>
135
+
{/if}
136
+
{#if repoStatus?.missingBlobCount != null}
137
+
<div class="stat-card">
138
+
<div class="stat-label">Missing blobs</div>
139
+
<div class="stat-value">{repoStatus.missingBlobCount.toLocaleString()}</div>
140
+
</div>
141
+
{/if}
142
+
{#if repoStatus?.source != null}
143
+
<div class="stat-card">
144
+
<div class="stat-label">Source</div>
145
+
<div class="stat-value stat-value--small">{repoStatus.source}</div>
146
+
</div>
147
+
{/if}
148
+
</div>
149
+
<div class="actions" style="padding-top: 5%">
150
+
<button type="button" onclick={handleRunBackupNow} disabled={isRunningBackup}>
151
+
{#if isRunningBackup}
152
+
<LoadingSpinner/>
153
+
{/if}
154
+
Manually run backup now
155
+
</button>
156
+
<button type="button" style="background-color: #c62828; color: #fff;" onclick={handleRemoveRepo}
157
+
disabled={isDeleting}>
158
+
{#if isDeleting}
159
+
<LoadingSpinner/>
160
+
{/if}
161
+
Delete Backups
162
+
</button>
163
+
</div>
164
+
{#if errorMessage}
165
+
<div class="error-message">{errorMessage}</div>
166
+
{/if}
167
+
{#if showStatusMessage}
168
+
<div class="status-message">{statusMessageText}</div>
169
+
{/if}
170
+
</div>
171
+
172
+
<style>
173
+
@keyframes spin {
174
+
from {
175
+
transform: rotate(0deg);
176
+
}
177
+
to {
178
+
transform: rotate(360deg);
179
+
}
180
+
}
181
+
</style>
+225
web-ui/src/routes/backups/SignUpForm.svelte
+225
web-ui/src/routes/backups/SignUpForm.svelte
···
1
+
<script lang="ts">
2
+
import type {BackupService, PlcOps} from '@pds-moover/moover';
3
+
import type {RotationKeyType} from '$lib/types';
4
+
import type {InferXRPCBodyOutput} from '@atcute/lexicons';
5
+
import {ComPdsmooverBackupGetRepoStatus} from '@pds-moover/lexicons';
6
+
import RotationKeyDisplay from '$lib/components/RotationKeyDisplay.svelte';
7
+
import LoadingSpinner from '$lib/components/LoadingSpinner.svelte';
8
+
9
+
let {
10
+
backupService,
11
+
plcOps,
12
+
handle,
13
+
onComplete
14
+
}: {
15
+
backupService: BackupService;
16
+
plcOps: PlcOps;
17
+
handle: string;
18
+
onComplete: (
19
+
repoStatus: InferXRPCBodyOutput<ComPdsmooverBackupGetRepoStatus.mainSchema['output']>
20
+
) => void;
21
+
} = $props();
22
+
23
+
// State variables
24
+
let errorMessage = $state<string | null>(null);
25
+
let showStatusMessage = $state(false);
26
+
let statusMessageText = $state('');
27
+
let addRecoveryKey = $state(true);
28
+
let plcTokenInput = $state<string | null>(null);
29
+
let newlyCreatedRotationKey = $state<RotationKeyType | null>(null);
30
+
let showRotationKeyScreen = $state(false);
31
+
let isRequestingToken = $state(false);
32
+
let isSigningUp = $state(false);
33
+
let isProceeding = $state(false);
34
+
35
+
function updateStatusHandler(status: string) {
36
+
console.log('Status update:', status);
37
+
statusMessageText = status;
38
+
}
39
+
40
+
async function requestPlcToken() {
41
+
errorMessage = null;
42
+
isRequestingToken = true;
43
+
try {
44
+
showStatusMessage = true;
45
+
updateStatusHandler('Requesting PLC token…');
46
+
await backupService.requestAPlcToken();
47
+
updateStatusHandler('PLC token emailed. Check your inbox and paste the token below.');
48
+
} catch (e) {
49
+
//@ts-expect-error: Error is handled
50
+
errorMessage = e?.message || 'Failed to request PLC token';
51
+
} finally {
52
+
showStatusMessage = false;
53
+
isRequestingToken = false;
54
+
}
55
+
}
56
+
57
+
async function handleSignUpSubmit() {
58
+
errorMessage = null;
59
+
isSigningUp = true;
60
+
showStatusMessage = true;
61
+
try {
62
+
if (addRecoveryKey) {
63
+
if (!plcTokenInput) {
64
+
errorMessage =
65
+
'Please paste your PLC token. Use the "Email me a PLC token" button to request one.';
66
+
showStatusMessage = false;
67
+
isSigningUp = false;
68
+
return;
69
+
}
70
+
updateStatusHandler('Creating new rotation key…');
71
+
const created = await plcOps.createANewSecp256k1();
72
+
newlyCreatedRotationKey = created;
73
+
updateStatusHandler('Adding new rotation key to your DID…');
74
+
await backupService.addANewRotationKey(plcTokenInput, created.publicKey);
75
+
updateStatusHandler('Rotation key added. Please save the private key now.');
76
+
showRotationKeyScreen = true;
77
+
showStatusMessage = false;
78
+
isSigningUp = false;
79
+
//Return and then on next button click we sign the user up that way if it fails it won't ruin them from
80
+
//Getting their rotation key
81
+
return;
82
+
}
83
+
await backupService.signUp(updateStatusHandler);
84
+
updateStatusHandler('Signed up for backups successfully.');
85
+
86
+
const repoStatus = await backupService.getUsersRepoStatus(updateStatusHandler);
87
+
showStatusMessage = false;
88
+
isSigningUp = false;
89
+
onComplete(repoStatus);
90
+
} catch (e) {
91
+
console.error(e);
92
+
//@ts-expect-error: Error is handled
93
+
errorMessage = e.message || 'Failed to sign up for backups.';
94
+
showStatusMessage = false;
95
+
isSigningUp = false;
96
+
}
97
+
}
98
+
99
+
async function proceedToRepoStatus() {
100
+
isProceeding = true;
101
+
try {
102
+
await backupService.signUp(updateStatusHandler);
103
+
updateStatusHandler('Signed up for backups successfully.');
104
+
105
+
showStatusMessage = true;
106
+
updateStatusHandler('Fetching repository status…');
107
+
const repoStatus = await backupService.getUsersRepoStatus(updateStatusHandler);
108
+
showRotationKeyScreen = false;
109
+
showStatusMessage = false;
110
+
isProceeding = false;
111
+
onComplete(repoStatus);
112
+
} catch (e) {
113
+
console.error(e);
114
+
//@ts-expect-error: Error is handled
115
+
errorMessage = e?.message || 'Failed to load repository status';
116
+
showStatusMessage = false;
117
+
isProceeding = false;
118
+
}
119
+
}
120
+
</script>
121
+
122
+
{#if showRotationKeyScreen && newlyCreatedRotationKey}
123
+
<div class="section">
124
+
<RotationKeyDisplay {handle} rotationKey={newlyCreatedRotationKey}/>
125
+
<div class="form-group">
126
+
<button type="button" onclick={proceedToRepoStatus} disabled={isProceeding}>
127
+
{#if isProceeding}
128
+
<LoadingSpinner/>
129
+
{/if}
130
+
Next
131
+
</button>
132
+
</div>
133
+
</div>
134
+
{:else}
135
+
<div class="section">
136
+
<h2>No backup repository found</h2>
137
+
<p style="text-align: left;">
138
+
Sign up now to backup your AT Protocol account. PDS MOOver automatically backups your posts,
139
+
likes, media, and all account data every 6 hours. This is stored on our servers in something
140
+
called an <a
141
+
target="_blank"
142
+
rel="noopener noreferrer"
143
+
href="https://en.wikipedia.org/wiki/Object_storage">object store.</a
144
+
>
145
+
Just like your
146
+
<a
147
+
target="_blank"
148
+
rel="noopener noreferrer"
149
+
href="https://blueskyweb.zendesk.com/hc/en-us/articles/15835264007693-Data-Privacy"
150
+
>AT Proto data</a
151
+
>, this data is public.
152
+
</p>
153
+
<div class="info">
154
+
<h3>Critical: Save your rotation key</h3>
155
+
<p style="text-align: left;">
156
+
A rotation key is your account recovery key. If you've migrated to a selfhosted or
157
+
thirdparty PDS, this key is the <span class="bold">ONLY</span> way to recover your account if
158
+
your PDS goes down. Without it, a failed or rogue PDS means permanent account loss. Generate
159
+
one and store it safely.
160
+
</p>
161
+
</div>
162
+
<div class="form-group">
163
+
<label style="display: inline-flex; align-items: center; gap: 0.5rem; white-space: nowrap;">
164
+
<input type="checkbox" bind:checked={addRecoveryKey} style="margin: 0;"/>
165
+
<span>Create a rotation key (recommended)</span>
166
+
</label>
167
+
</div>
168
+
{#if addRecoveryKey}
169
+
<div class="form-group">
170
+
<p>
171
+
To add a new rotation key, you must authorize a PLC operation. Click the button to email
172
+
yourself a PLC token, then paste it below.
173
+
<span class="bold"
174
+
>NOTE: Adding a new key will remove all current rotation keys except for the one created
175
+
and the one from your PDS</span
176
+
>
177
+
</p>
178
+
179
+
<div class="actions" style="margin-bottom: 0.5rem;">
180
+
<button type="button" onclick={requestPlcToken} disabled={isRequestingToken}>
181
+
{#if isRequestingToken}
182
+
<LoadingSpinner/>
183
+
{/if}
184
+
Email me a PLC token
185
+
</button>
186
+
</div>
187
+
<div class="form-group">
188
+
<label for="plc-token">PLC token</label>
189
+
<input
190
+
type="text"
191
+
id="plc-token"
192
+
name="plc-token"
193
+
bind:value={plcTokenInput}
194
+
placeholder="Paste PLC token from email"
195
+
autocomplete="one-time-code"
196
+
/>
197
+
</div>
198
+
</div>
199
+
{:else}
200
+
<div class="form-group">
201
+
<div class="status-message" style="text-align: left;">
202
+
<p>
203
+
<span class="bold">Note:</span> a recovery key is
204
+
<span class="bold">required</span> to restore your account. If you're not sure what this means,
205
+
then it is important to check the above box and save the rotation key file given.
206
+
</p>
207
+
</div>
208
+
</div>
209
+
{/if}
210
+
{#if errorMessage}
211
+
<div class="error-message">{errorMessage}</div>
212
+
{/if}
213
+
{#if showStatusMessage}
214
+
<div class="status-message">{statusMessageText}</div>
215
+
{/if}
216
+
<div>
217
+
<button type="button" onclick={handleSignUpSubmit} disabled={isSigningUp}>
218
+
{#if isSigningUp}
219
+
<LoadingSpinner/>
220
+
{/if}
221
+
Sign up for backups
222
+
</button>
223
+
</div>
224
+
</div>
225
+
{/if}
+202
web-ui/src/routes/info/+page.svelte
+202
web-ui/src/routes/info/+page.svelte
···
1
+
<script lang="ts">
2
+
import OgImage from '$lib/components/OgImage.svelte';
3
+
import MooHeader from '$lib/components/MooHeader.svelte';
4
+
import SignThePapersImg from '$lib/assets/sign_the_papers.png'
5
+
</script>
6
+
7
+
<svelte:head>
8
+
<title>PDS MOOver - Info</title>
9
+
<meta property="og:description" content="ATProto account migration tool"/>
10
+
<OgImage/>
11
+
</svelte:head>
12
+
13
+
<div class="container">
14
+
<MooHeader title="PDS MOOver Info"/>
15
+
16
+
17
+
<div class="section" id="top">
18
+
<p> This page is to help you decide if you want to use PDS MOOver to move your ATProto(Bluesky) account to a new
19
+
PDS along with some other information about all the new tools.
20
+
One way or the other. TLDR (You should still read the whole thing), at least read and follow the <a
21
+
href="#precautions">precautions section</a>.</p>
22
+
23
+
24
+
<section class="section" style="text-align:left">
25
+
<h2>Info</h2>
26
+
<p>PDS MOOver is a set of tools to help you migrate to a new PDS. The creator
27
+
or host of this tool will not be able to help you recover your account if something goes wrong. So be
28
+
advised you and your PDS admin may be on your own besides helpful answers and understand the risk you
29
+
take in doing an account movement.</p>
30
+
</section>
31
+
32
+
33
+
<nav aria-label="Table of contents" class="section" style="text-align:left">
34
+
<h3>Table of contents</h3>
35
+
<ol>
36
+
<li><a href="#precautions">Precautions</a></li>
37
+
<li><a href="#backups">Backups</a></li>
38
+
<li><a href="#restore">Restore</a></li>
39
+
<li><a href="#blacksky">I'm here for Blacksky, is there a video guide?</a></li>
40
+
<li><a href="#cant-login">I can't log in?/Says my account is deactivated?</a></li>
41
+
<li><a href="#invalid-handle">My account says Invalid Handle?</a></li>
42
+
<li><a href="#help">!!!!!HELP!!!!!</a></li>
43
+
<li><a href="#why">Why doesn't PDS MOOver have xyz?</a></li>
44
+
<li><a href="#done">Alright account migrated, now what?</a></li>
45
+
<li><a href="#slow">Why is it so SLOW?</a></li>
46
+
<li><a href="#open-source">Can I check out the code anywhere?</a></li>
47
+
</ol>
48
+
</nav>
49
+
50
+
<section id="precautions" class="section" style="text-align:left">
51
+
<h2>Precautions</h2>
52
+
<p> Migrations can be a potentially dangerous operation. It is recommended to follow these few steps to
53
+
protect your account and identity.</p>
54
+
<ul>
55
+
<li>During migration make sure to do not leave the page</li>
56
+
<li>It is recommended to use a desktop computer for this process due to the amount of time it can
57
+
take.
58
+
</li>
59
+
<li>Your account is not actually fully moved over to the new PDS till you receive a code in your email
60
+
and enter it on PDS MOOver, this is the final step.
61
+
</li>
62
+
<li>Your data will not be deleted from Bluesky(or your previous PDS) during migration. If you find you
63
+
are missing any pictures or videos after the move you can use the <a href="/missing">Missing
64
+
tool</a> to recover those from your previous PDS.
65
+
</li>
66
+
</ul>
67
+
68
+
<p>At the end of your migration and before you move you will be asked if you'd like to sign up for PDS
69
+
MOOver's backup service and to add a rotation key. Both of these are recommended and secure your account
70
+
if your PDS ever goes down, allowing for account recovery. </p>
71
+
<img src="{SignThePapersImg}" alt="Sign the papers"
72
+
style="max-width: 100%; max-height: 100%; object-fit: contain;">
73
+
74
+
</section>
75
+
76
+
<section id="backups" class="section" style="text-align:left">
77
+
<h2>Backups</h2>
78
+
<p>PDS MOOver now supports backups. These are automated backups of your account saving your repo
79
+
(posts,likes,etc), and your blobs(picture/videos) from your AT Proto account to a cloud base object
80
+
store (S3). This is a free service for individual accounts and stores the backups on PDS MOOver's
81
+
servers. These backups will happen every 6 hours from the time you sign up. We are expecting to lower
82
+
this as we see how the service does. On login, you will be asked if you'd like to add a rotation key to
83
+
your account. It is highly recommended to do this if you do not already have one. This is the only way
84
+
you can recover your account in the event of a PDS failure or rogue account takeover</p>
85
+
86
+
<p>Just like your <a target="_blank" rel="noopener noreferrer"
87
+
href="https://blueskyweb.zendesk.com/hc/en-us/articles/15835264007693-Data-Privacy">AT
88
+
Proto data</a>, your backedup data is also public.
89
+
You can access your data much the same way you do on your PDS by calling these endpoints. Since these
90
+
behave much the same as the PDS they are public.
91
+
</p>
92
+
<ul>
93
+
<li><code>/xrpc/com.atproto.sync.getRepo?did="your did"</code> to get a copy of your repo's CAR export
94
+
</li>
95
+
<li><code>/xrpc/com.atproto.sync.getBlob?did="your did"&cid="cid of the blob"</code></li>
96
+
</ul>
97
+
98
+
</section>
99
+
100
+
<section id="restore" class="section" style="text-align:left">
101
+
<h2>Restore</h2>
102
+
<p>Backups without a restore option aren't very good backups. So to pair well with our new backup service
103
+
PDS MOOver now also offers recovery of your account and restoring from a backup. To use this you must
104
+
have your Private Rotation Key. You can add one to your account either after migration or during backups
105
+
sign up. This recovery process follows much the same process as out line in <a
106
+
href="https://www.da.vidbuchanan.co.uk/blog/adversarial-pds-migration.html">Adversarial ATProto
107
+
PDS Migration</a> blog post by <a href="https://bsky.app/profile/retr0.id">@retr0.id</a>. </p>
108
+
</section>
109
+
110
+
<section id="blacksky" class="section" style="text-align:left">
111
+
<h2>I'm here for Blacksky, Is there a video guide?</h2>
112
+
<p>
113
+
<a href="https://blacksky.community/profile/did:plc:g7j6qok5us4hjqlwjxwrrkjm">@sharpiepls.com</a> has
114
+
made an amazing video guide on
115
+
how to use PDS MOOver to move your bluesky account to blacksky.app.
116
+
<video width="100%" controls>
117
+
118
+
<source src="https://blacksky.app/xrpc/com.atproto.sync.getBlob?did=did:plc:g7j6qok5us4hjqlwjxwrrkjm&cid=bafkreielhdoa2lcyiat5oumkbkwy26hlj36rwwwfi5fbnvd5haxq3t4joa"/>
119
+
</video>
120
+
</p>
121
+
</section>
122
+
123
+
<section id="cant-login" class="section" style="text-align:left">
124
+
<h2>I can't log in?/Says my account is deactivated?</h2>
125
+
<p>When you move to a non Bluesky PDS you have to do an extra step on login.</p>
126
+
<ol>
127
+
<li>On the Sign in screen for <a href="https://bsky.app">bsky.app</a> or on the app click the top input
128
+
titled "Hosting provider" and has a globe icon and says Bluesky Social"
129
+
</li>
130
+
<li>Click the tab labeled custom</li>
131
+
<li>In the input for server address you put the same URL you used for the new PDS URL with the https://
132
+
like so <code>https://example.com</code></li>
133
+
<li>Click done and enter your new handle(or email) and password</li>
134
+
</ol>
135
+
</section>
136
+
137
+
<section id="invalid-handle" class="section" style="text-align:left">
138
+
<h2>My account says Invalid Handle?</h2>
139
+
<p>It's a bit of a bug sometimes. I'm not sure what causes it, but usually mentioning your handle in a post
140
+
or reply fixes it.
141
+
Like <code>@fullhandle.newpds.com</code>, may or may not highlight it blue and autofill it but make sure
142
+
you have the
143
+
full handle and the @ like that. Can also check your handle with the <a
144
+
href="https://bsky-debug.app/handle">Bluesky Debug Page</a>. If you see green, and it says one
145
+
of
146
+
them pass you should be fine and just may take a while to update.</p>
147
+
</section>
148
+
149
+
<section id="help" class="section" style="text-align:left">
150
+
<h2>!!!!!HELP!!!!!</h2>
151
+
<p>If you're having issues with PDS MOOver first of all, I'm very sorry. I have tested this to the best of
152
+
my
153
+
ability, but PDS migrations do come with risks. I would recommend getting with the owner of the PDS and
154
+
seeing where the account stands with tools like <a href="https://pdsls.dev">pdsls</a>.</p>
155
+
156
+
<p> The tool is designed to be able to be re ran IF you set the Advance Options flags.For example, lets say
157
+
if it created the account, repo is there but some blobs are missing. You can uncheck everything but
158
+
"Migrate Missing Blobs", "Migrate Prefs", and "Migrate PLC record" and it will pick up after the account
159
+
repo migration. It is odd in the fact that all the fields are required. That's just to cut down on logic
160
+
to hopefully cut down on bugs. If you don't ever see the "Please enter your PLC Token" and enter the
161
+
token sent to your email, you can just
162
+
forget about it and call it a day if it's too much. Your old account is still active and working.</p>
163
+
</section>
164
+
165
+
166
+
<section id="why" class="section" style="text-align:left">
167
+
<h2>Why doesn't PDS MOOver have xyz for migrations?</h2>
168
+
<p>PDS MOOver was designed to pretty much be the goat account migration with a UI. Like in this <a
169
+
href="https://whtwnd.com/bnewbold.net/3l5ii332pf32u"> post</a>. Keeping it simple and hard fails if
170
+
anything
171
+
goes wrong
172
+
to
173
+
hopefully cover most use cases.</p>
174
+
</section>
175
+
176
+
<section id="done" class="section" style="text-align:left">
177
+
<h2>Alright account migrated, now what?</h2>
178
+
<p>Welcome to your new PDS! You can login to your new PDS on Bluesky's login screen by selecting "Hosting
179
+
provider" and entering your PDS url. I also recommend making sure you are signed up for our <a
180
+
href="/backups">backups</a> and have a recovery key that you control in case your PDS disappears
181
+
overnight you can regain your account. </p>
182
+
</section>
183
+
184
+
<section id="slow" class="section" style="text-align:left">
185
+
<h2>Why is it so SLOW?</h2>
186
+
<p>Everything happens client side, and the blob uploads take a while. Nothing runs in parallel. Blob uploads
187
+
happen one at a time; once one is done, the next goes. This is done just to keep it as simple as
188
+
possible and to hopefully limit the chance of failures on uploads. My personal account takes about
189
+
20-30ish mins to move with 1,700ish blobs at 800mb on a 1gig internet connection.</p>
190
+
</section>
191
+
192
+
<section id="open-source" class="section" style="text-align:left">
193
+
<h2>Can I check out the code anywhere?</h2>
194
+
<p>Yep! PDS MOOver is 100% open source and can find the code on <a
195
+
href="https://tangled.sh/@baileytownsend.dev/pds-moover">tangled.sh</a>. Also, if you're a
196
+
developer,
197
+
and you want to fork the code for a new UI. PDS MOOver's logic is all in one js file. Just take it and
198
+
its dependencies and have at it.</p>
199
+
</section>
200
+
</div>
201
+
202
+
</div>
+230
web-ui/src/routes/missing-blobs/+page.svelte
+230
web-ui/src/routes/missing-blobs/+page.svelte
···
1
+
<script lang="ts">
2
+
import MooHeader from '$lib/components/MooHeader.svelte';
3
+
import missingPicture from '$lib/assets/missing.webp'
4
+
import {MissingBlobs} from '@pds-moover/moover';
5
+
6
+
let missingBlobs = $state(new MissingBlobs());
7
+
8
+
// Form state
9
+
let showCurrentLogin = $state(true);
10
+
let showOldLogin = $state(false);
11
+
let showAdvance = $state(false);
12
+
let disableLoginButton = $state(false);
13
+
let showBlobMoveProgress = $state(false);
14
+
let oldPdsUrl = $state<string | null>(null);
15
+
let showTryAgain = $state(false);
16
+
let errorMessage: string | null = $state(null);
17
+
let showStatusMessage = $state(false);
18
+
let statusMessage = $state('');
19
+
20
+
let loginForm = $state({
21
+
handle: '',
22
+
password: '',
23
+
twoFactorCode: '',
24
+
showTwoFactorCodeInput: false,
25
+
});
26
+
27
+
28
+
function resetStatusAndErrors() {
29
+
showStatusMessage = false;
30
+
statusMessage = '';
31
+
errorMessage = '';
32
+
disableLoginButton = true;
33
+
}
34
+
35
+
async function handleCurrentLogin(event: SubmitEvent) {
36
+
event.preventDefault();
37
+
resetStatusAndErrors();
38
+
try {
39
+
const {
40
+
accountStatus,
41
+
missingBlobsCount
42
+
} = await missingBlobs.currentAgentLogin(loginForm.handle, loginForm.password, loginForm.twoFactorCode);
43
+
console.log(missingBlobsCount);
44
+
const noMissingBlobs = missingBlobsCount === 0;
45
+
if (noMissingBlobs) {
46
+
statusMessage = `You are good to go! You are not missing any blobs. Your account has ${accountStatus.importedBlobs} imported blobs and expects to have at least ${accountStatus.expectedBlobs} blobs. No action is required.`
47
+
} else {
48
+
showCurrentLogin = false;
49
+
statusMessage = 'You are currently missing some blobs. Login with your old password to import the missing blobs. We will automatically find your old handle.';
50
+
showOldLogin = true;
51
+
//Reset the form
52
+
loginForm.showTwoFactorCodeInput = false;
53
+
loginForm.twoFactorCode = '';
54
+
loginForm.password = '';
55
+
loginForm.handle = '';
56
+
}
57
+
showStatusMessage = true;
58
+
59
+
} catch (err) {
60
+
//@ts-expect-error: Should always have an error message
61
+
if (err.error === 'AuthFactorTokenRequired') {
62
+
loginForm.showTwoFactorCodeInput = true;
63
+
}
64
+
//@ts-expect-error: Should always have an error message
65
+
errorMessage = err.message;
66
+
}
67
+
disableLoginButton = false;
68
+
}
69
+
70
+
async function handleOldLogin(event: SubmitEvent) {
71
+
event.preventDefault();
72
+
resetStatusAndErrors();
73
+
try {
74
+
await missingBlobs.oldAgentLogin(loginForm.password, loginForm.twoFactorCode, oldPdsUrl);
75
+
showOldLogin = false;
76
+
showBlobMoveProgress = true;
77
+
showStatusMessage = true;
78
+
statusMessage = '';
79
+
await migrateMissingBlobs();
80
+
} catch (err) {
81
+
//@ts-expect-error: Should always have an error message
82
+
if (err.error === 'AuthFactorTokenRequired') {
83
+
loginForm.showTwoFactorCodeInput = true;
84
+
}
85
+
//@ts-expect-error: Should always have an error message
86
+
errorMessage = err.message;
87
+
}
88
+
disableLoginButton = false;
89
+
}
90
+
91
+
function updateStatusHandler(status: string) {
92
+
console.log('Status update:', status);
93
+
statusMessage = status;
94
+
}
95
+
96
+
async function migrateMissingBlobs() {
97
+
try {
98
+
resetStatusAndErrors();
99
+
showStatusMessage = true;
100
+
showTryAgain = false;
101
+
const {
102
+
accountStatus,
103
+
missingBlobsCount
104
+
} = await missingBlobs.migrateMissingBlobs(updateStatusHandler);
105
+
const noMissingBlobs = missingBlobsCount === 0;
106
+
if (noMissingBlobs) {
107
+
statusMessage = `You are good to go! You have all ${accountStatus.importedBlobs} of the expected ${accountStatus.expectedBlobs} blobs. You're done!!`
108
+
} else {
109
+
statusMessage = `Expected blobs: ${accountStatus.expectedBlobs} Imported blobs: ${accountStatus.importedBlobs}`;
110
+
showTryAgain = true;
111
+
}
112
+
} catch (err) {
113
+
//@ts-expect-error: Should always have an error message
114
+
errorMessage = err.message;
115
+
showTryAgain = true;
116
+
}
117
+
disableLoginButton = false;
118
+
}
119
+
120
+
function toggleAdvanceMenu() {
121
+
showAdvance = !showAdvance;
122
+
}
123
+
</script>
124
+
125
+
<svelte:head>
126
+
<title>PDS MOOver - Missing Blobs</title>
127
+
<meta property="og:description" content="Import missing blobs from your old PDS to your new PDS"/>
128
+
<meta property="og:image" content="{missingPicture}">
129
+
</svelte:head>
130
+
131
+
{#snippet custom_img()}
132
+
<img src='{missingPicture}' alt='Cartoon milk cow on a missing poster'
133
+
style='max-width: 100%; max-height: 100%; object-fit: contain;'>
134
+
{/snippet}
135
+
136
+
<div class="container">
137
+
<MooHeader title="Missing Blobs Importer" customImg={custom_img}/>
138
+
139
+
<a href="https://blacksky.community/profile/did:plc:g7j6qok5us4hjqlwjxwrrkjm/post/3lyylumcpok2c">How to video
140
+
guide</a>
141
+
142
+
<!-- Login Form -->
143
+
{#if showCurrentLogin || showOldLogin}
144
+
<form id="moover-form" onsubmit={showCurrentLogin ? handleCurrentLogin : handleOldLogin}>
145
+
<div class="section">
146
+
<h2>{showCurrentLogin ? 'Login for your current PDS' : 'Password for your OLD PDS'}</h2>
147
+
148
+
{#if showOldLogin}
149
+
<p>We only need your password for your old account. We can find your old handle from your current
150
+
login.</p>
151
+
{/if}
152
+
153
+
{#if showCurrentLogin}
154
+
<div class="form-group">
155
+
<label for="handle">Current Handle:</label>
156
+
<input type="text" id="handle" name="handle" placeholder="alice.bsky.social"
157
+
bind:value={loginForm.handle}
158
+
required>
159
+
</div>
160
+
{/if}
161
+
162
+
<div class="form-group">
163
+
<label for="password">{showCurrentLogin ? 'Current' : 'OLD'} Password:</label>
164
+
<input type="password" id="password" name="password"
165
+
bind:value={loginForm.password}
166
+
required>
167
+
</div>
168
+
169
+
{#if (showCurrentLogin && loginForm.showTwoFactorCodeInput) || (showOldLogin && loginForm.showTwoFactorCodeInput)}
170
+
<div class="form-group">
171
+
<label for="two-factor-code">2FA from the email sent</label>
172
+
<input type="text" id="two-factor-code" name="two-factor-code"
173
+
bind:value={loginForm.twoFactorCode}>
174
+
<div class="error-message">Enter your 2fa code here</div>
175
+
</div>
176
+
{/if}
177
+
178
+
{#if showOldLogin}
179
+
{#if showAdvance}
180
+
<div class="form-group show-advance">
181
+
<label for="old_pds">This is optional. If you do not know your old PDS url please leave it
182
+
blank. We will find it for you.</label>
183
+
<input type="url" id="old_pds" name="old-pds"
184
+
placeholder="(Optional) Your old PDS URL" bind:value={oldPdsUrl}>
185
+
</div>
186
+
{/if}
187
+
<div class="form-group">
188
+
<button type="button" onclick={toggleAdvanceMenu} id="advance" name="advance">Advance Options
189
+
</button>
190
+
</div>
191
+
{/if}
192
+
193
+
{#if errorMessage}
194
+
<div class="error-message">{errorMessage}</div>
195
+
{/if}
196
+
{#if showStatusMessage}
197
+
<div class="status-message">{statusMessage}</div>
198
+
{/if}
199
+
200
+
<div>
201
+
<button disabled={disableLoginButton} type="submit">
202
+
{showCurrentLogin ? 'Login' : 'Login and start the import of missing blobs'}
203
+
</button>
204
+
</div>
205
+
</div>
206
+
</form>
207
+
{/if}
208
+
209
+
<!-- Progress while uploading blobs-->
210
+
{#if showBlobMoveProgress}
211
+
<div>
212
+
{#if showStatusMessage}
213
+
<div id="warning">*This will take a while. Please do not close this tab. And watch
214
+
the status message below for updates
215
+
</div>
216
+
<div id="missing-status-message" class="status-message">{statusMessage}</div>
217
+
{/if}
218
+
{#if errorMessage}
219
+
<div class="error-message">{errorMessage}</div>
220
+
{/if}
221
+
{#if showTryAgain}
222
+
<p style="color: yellow">We were unable to import all of your previous blobs, please try again. If it is
223
+
still not completing give it a few hours and come back and try again. It may be rate limited. Re
224
+
running this tool does not harm your account.</p>
225
+
<br>
226
+
<button onclick={migrateMissingBlobs}>Try again</button>
227
+
{/if}
228
+
</div>
229
+
{/if}
230
+
</div>
+267
web-ui/src/routes/moover/+page.svelte
+267
web-ui/src/routes/moover/+page.svelte
···
1
+
<script lang="ts">
2
+
import MooHeader from '$lib/components/MooHeader.svelte';
3
+
import OgImage from '$lib/components/OgImage.svelte';
4
+
import {resolve} from '$app/paths';
5
+
import {Migrator} from '@pds-moover/moover';
6
+
import SignThePapers from './SignThePapers.svelte';
7
+
8
+
let formData = $state({
9
+
handle: '',
10
+
password: '',
11
+
newPds: '',
12
+
newEmail: '',
13
+
newHandle: '',
14
+
inviteCode: null,
15
+
twoFactorCode: null,
16
+
confirmation: false,
17
+
// Advanced options
18
+
createNewAccount: true,
19
+
migrateRepo: true,
20
+
migrateBlobs: true,
21
+
migrateMissingBlobs: true,
22
+
migratePrefs: true,
23
+
migratePlcRecord: true,
24
+
});
25
+
26
+
let migrator = $state(new Migrator());
27
+
28
+
//UI state
29
+
let showTwoFactorCodeInput = $state(false);
30
+
let showAdvance = $state(false);
31
+
let showStatusMessage = $state(false);
32
+
let askForPlcToken = $state(false);
33
+
let disableSubmit = $state(false);
34
+
35
+
let errorMessage: null | string = $state(null);
36
+
let statusMessage: null | string = $state(null);
37
+
38
+
const updateStatusHandler = (status: string) => {
39
+
statusMessage = status;
40
+
}
41
+
42
+
async function submitMoove(event: SubmitEvent & { currentTarget: EventTarget & HTMLFormElement }) {
43
+
event.preventDefault();
44
+
disableSubmit = true;
45
+
errorMessage = null;
46
+
showStatusMessage = false;
47
+
48
+
if (!formData.confirmation) {
49
+
errorMessage = 'Please confirm that you understand the risks of doing an account migration';
50
+
disableSubmit = false;
51
+
return;
52
+
}
53
+
54
+
try {
55
+
56
+
if (showTwoFactorCodeInput) {
57
+
if (showTwoFactorCodeInput === null) {
58
+
errorMessage = 'Please enter the 2FA that was sent to your email.'
59
+
disableSubmit = false;
60
+
return;
61
+
}
62
+
}
63
+
64
+
// Advance options from $state
65
+
migrator.createNewAccount = formData.createNewAccount;
66
+
migrator.migrateRepo = formData.migrateRepo;
67
+
migrator.migrateBlobs = formData.migrateBlobs;
68
+
migrator.migrateMissingBlobs = formData.migrateMissingBlobs;
69
+
migrator.migratePrefs = formData.migratePrefs;
70
+
migrator.migratePlcRecord = formData.migratePlcRecord;
71
+
72
+
console.log(migrator);
73
+
74
+
updateStatusHandler('Starting migration...');
75
+
showStatusMessage = true;
76
+
await migrator.migrate(
77
+
formData.handle,
78
+
formData.password,
79
+
formData.newPds,
80
+
formData.newEmail,
81
+
formData.newHandle,
82
+
formData.inviteCode,
83
+
updateStatusHandler,
84
+
formData.twoFactorCode,
85
+
);
86
+
if (migrator.migratePlcRecord) {
87
+
//I don't think disable submit is needed, but you never know.
88
+
disableSubmit = false;
89
+
askForPlcToken = true;
90
+
} else {
91
+
updateStatusHandler('Migration of your repo is complete! But the PLC operation was not done so your old account is still the valid one.');
92
+
}
93
+
} catch (error) {
94
+
disableSubmit = false;
95
+
console.error(error);
96
+
//@ts-expect-error: JS being js. doesn't like not having the type'
97
+
if (error.error === 'AuthFactorTokenRequired') {
98
+
showTwoFactorCodeInput = true;
99
+
}
100
+
//@ts-expect-error: JS being js. doesn't like not having the type'
101
+
errorMessage = error.message;
102
+
}
103
+
}
104
+
</script>
105
+
106
+
<svelte:head>
107
+
<title>PDS MOOver</title>
108
+
<meta property="og:description" content="ATProto account migration tool"/>
109
+
<OgImage/>
110
+
</svelte:head>
111
+
112
+
<div class="container">
113
+
<MooHeader title="PDS MOOver"/>
114
+
{#if !askForPlcToken}
115
+
<a href={resolve('/info')}>Idk if I trust a cow to move my atproto account to a new PDS</a>
116
+
<br/>
117
+
<a href="https://blacksky.community/profile/did:plc:g7j6qok5us4hjqlwjxwrrkjm/post/3lw3hcuojck2u">Video guide for
118
+
joining blacksky.app</a>
119
+
120
+
<form id="moover-form" onsubmit={submitMoove}>
121
+
<!-- First section: Login credentials -->
122
+
<div class="section">
123
+
<h2>Login for your current PDS</h2>
124
+
<div class="form-group">
125
+
<label for="handle">Old Handle:</label>
126
+
<input type="text" id="handle" name="handle" placeholder="alice.bsky.social" required
127
+
bind:value={formData.handle}>
128
+
</div>
129
+
130
+
<div class="form-group">
131
+
<label for="password">Old Password (Will also be your new password):</label>
132
+
<input type="password" id="password" name="password" required bind:value={formData.password}>
133
+
</div>
134
+
{#if showTwoFactorCodeInput}
135
+
<div class="form-group">
136
+
<label for="two-factor-code">2FA from the email sent</label>
137
+
<input type="text" id="two-factor-code" name="twoFactorCode"
138
+
bind:value={formData.twoFactorCode}>
139
+
<div class="error-message">Enter your 2fa code here</div>
140
+
141
+
</div>
142
+
{/if}
143
+
</div>
144
+
145
+
<!-- Second section: New account details -->
146
+
<div class="section">
147
+
<h2>Setup for the new PDS</h2>
148
+
<div class="form-group">
149
+
<label for="new-pds">New PDS (URL):</label>
150
+
<input type="url" id="new-pds" name="newPds" placeholder="https://coolnewpds.com"
151
+
required bind:value={formData.newPds}>
152
+
</div>
153
+
154
+
<div class="form-group">
155
+
<label for="new-email">New Email:</label>
156
+
<input type="email" id="new-email" name="newEmail" placeholder="CanBeSameEmailAsTheOldPds@email.com"
157
+
required bind:value={formData.newEmail}>
158
+
</div>
159
+
160
+
<div class="form-group">
161
+
<label for="new-handle">New Handle:</label>
162
+
<input type="text" id="new-handle" name="newHandle"
163
+
placeholder="username.newpds.com or mycooldomain.com" required
164
+
bind:value={formData.newHandle}>
165
+
</div>
166
+
167
+
<div class="form-group">
168
+
<label for="invite-code">Invite Code:</label>
169
+
<input type="text" id="invite-code" name="inviteCode"
170
+
placeholder="Invite code from your new PDS (Leave blank if you don't have one)"
171
+
bind:value={formData.inviteCode}>
172
+
</div>
173
+
</div>
174
+
175
+
<div class="form-group">
176
+
<button type="button" onclick={() => showAdvance = !showAdvance} id="advance" name="advance">Advance
177
+
Options
178
+
</button>
179
+
</div>
180
+
{#if showAdvance}
181
+
<div class="section" style="padding-bottom: 10px; text-align: left">
182
+
<h3>Pick and choose which actions to run</h3>
183
+
<p>Useful if a migration failed and you want to have a bit more manual control</p>
184
+
<div class="form-control">
185
+
<label class="moove-checkbox-label">
186
+
<input type="checkbox" id="createNewAccount" name="createNewAccount"
187
+
bind:checked={formData.createNewAccount}>
188
+
Create a New Account on the New PDS
189
+
</label>
190
+
</div>
191
+
<div class="form-control">
192
+
<label class="moove-checkbox-label">
193
+
<input bind:checked={formData.migrateRepo} type="checkbox" id="migrateRepo"
194
+
name="migrateRepo">
195
+
Migrate Repo
196
+
</label>
197
+
</div>
198
+
<div class="form-control">
199
+
<label class="moove-checkbox-label">
200
+
<input bind:checked={formData.migrateBlobs} type="checkbox" id="migrateBlobs"
201
+
name="migrateBlobs">
202
+
Migrate Blobs
203
+
</label>
204
+
</div>
205
+
<div class="form-control">
206
+
<label class="moove-checkbox-label">
207
+
<input bind:checked={formData.migrateMissingBlobs} type="checkbox" id="migrateMissingBlobs"
208
+
name="migrateMissingBlobs">
209
+
Migrate Missing Blobs
210
+
</label>
211
+
</div>
212
+
<div class="form-control">
213
+
<label class="moove-checkbox-label">
214
+
<input bind:checked={formData.migratePrefs} type="checkbox" id="migratePrefs"
215
+
name="migratePrefs">
216
+
Migrate Prefs
217
+
</label>
218
+
</div>
219
+
<div class="form-control">
220
+
<label class="moove-checkbox-label">
221
+
<input bind:checked={formData.migratePlcRecord} type="checkbox" id="migratePlcRecord"
222
+
name="migratePlcRecord">
223
+
Migrate PLC Record
224
+
</label>
225
+
</div>
226
+
227
+
</div>
228
+
{/if}
229
+
230
+
<p style="text-align: left">There are some risks that come with doing an account migration.
231
+
(Can view them
232
+
<a href="https://github.com/bluesky-social/pds/blob/main/ACCOUNT_MIGRATION.md#%EF%B8%8F-warning-%EF%B8%8F-%EF%B8%8F">here</a>)
233
+
and that the creator or host of this migration tool is not liable and will not be able to help you in
234
+
the
235
+
event something goes wrong. I also have read over the <a href={resolve('/info')}>extended information
236
+
from
237
+
PDS MOOver
238
+
about account
239
+
migrations.</a>
240
+
</p>
241
+
<div class="form-group">
242
+
<label for="confirmation" class="moove-checkbox-label">
243
+
<input bind:checked={formData.confirmation} type="checkbox" id="confirmation" name="confirmation"
244
+
required>
245
+
<span>I understand</span>
246
+
</label>
247
+
</div>
248
+
{#if errorMessage !== null}
249
+
<div class="error-message">{errorMessage}</div>
250
+
{/if}
251
+
252
+
{#if showStatusMessage}
253
+
<div id="warning">*Please make sure to stay on this page during the MOOve for the
254
+
best result
255
+
</div>
256
+
<div id="status-message" class="status-message">{statusMessage}</div>
257
+
{/if}
258
+
259
+
<div>
260
+
<button disabled={disableSubmit} type="submit">MOOve</button>
261
+
</div>
262
+
</form>
263
+
264
+
{:else}
265
+
<SignThePapers migrator={migrator} newHandle={formData.newHandle}/>
266
+
{/if}
267
+
</div>
+178
web-ui/src/routes/moover/SignThePapers.svelte
+178
web-ui/src/routes/moover/SignThePapers.svelte
···
1
+
<script lang="ts">
2
+
import {Migrator, PlcOps} from '@pds-moover/moover'
3
+
import {resolve} from '$app/paths'
4
+
import RotationKeyDisplay from '$lib/components/RotationKeyDisplay.svelte';
5
+
import type {RotationKeyType} from '$lib/types';
6
+
import {PUBLIC_XRPC_BASE} from '$env/static/public';
7
+
8
+
let {migrator, newHandle}: { migrator: Migrator, newHandle: string } = $props();
9
+
10
+
//UI State
11
+
let errorMessage: null | string = $state(null);
12
+
let done = $state(false);
13
+
let plcStatus: null | string = $state(null);
14
+
let showAdvancedPlcOptions = $state(false);
15
+
let backupSignupMessage: null | string = $state(null);
16
+
let backupSignupError: null | string = $state(null);
17
+
18
+
//Input State
19
+
let createANewRotationKey = $state(false);
20
+
let signupForBackups = $state(false);
21
+
let plcToken = $state('');
22
+
let rotationKeys = $state(['', '', '', '']);
23
+
let newlyCreatedRotationKey: RotationKeyType | null = $state(null);
24
+
25
+
26
+
async function signPlcOperation(event: SubmitEvent & { currentTarget: EventTarget & HTMLFormElement }) {
27
+
event.preventDefault();
28
+
try {
29
+
plcStatus = 'Signing PLC operation...';
30
+
backupSignupMessage = null;
31
+
backupSignupError = null;
32
+
// Build an additional rotation keys list (user-provided and/or newly created)
33
+
const additionalRotationKeysToAdd: string[] = [];
34
+
// Generate a new rotation key if requested
35
+
if (createANewRotationKey) {
36
+
37
+
let plcOps = new PlcOps();
38
+
const created = await plcOps.createANewSecp256k1();
39
+
newlyCreatedRotationKey = created; // { publicKey, privateKey }
40
+
// Reserve the first slot for the newly created key (will appear above the PDS rotation key)
41
+
additionalRotationKeysToAdd.push(created.publicKey);
42
+
}
43
+
// Append any manually entered rotation keys (non-empty)
44
+
//TODO idk about this i need to look at it again
45
+
for (let i = 0; i < rotationKeys.length; i++) {
46
+
const k = (rotationKeys[i] || '').trim();
47
+
if (k) {
48
+
additionalRotationKeysToAdd.push(k);
49
+
}
50
+
}
51
+
52
+
//TODO nervous about this state
53
+
await migrator.signPlcOperation(plcToken, additionalRotationKeysToAdd);
54
+
plcStatus = 'PLC operation signed successfully! Your account has been MOOved to the new PDS.';
55
+
done = true;
56
+
57
+
if (signupForBackups) {
58
+
try {
59
+
backupSignupMessage = 'Signing you up for automated backups...';
60
+
//TODO nervous about this state
61
+
await migrator.signUpForBackupsFromMigration(`did:web:${PUBLIC_XRPC_BASE}`);
62
+
backupSignupMessage = 'Signed up for automated backups successfully.';
63
+
} catch (e) {
64
+
console.error(e);
65
+
//@ts-expect-error: There is a e.message, or at least a check for it
66
+
backupSignupError = e?.message || 'Failed to sign you up for automated backups.';
67
+
}
68
+
}
69
+
} catch (error) {
70
+
//@ts-expect-error: There is a message
71
+
errorMessage = error.message;
72
+
console.error(error);
73
+
}
74
+
}
75
+
76
+
</script>
77
+
78
+
79
+
<div class="section">
80
+
<form onsubmit="{signPlcOperation}">
81
+
{#if !done}
82
+
<div>
83
+
<h2>Please enter your PLC Token you received in an email</h2>
84
+
<div class="form-group">
85
+
<label for="plc-token">PLC Token:</label>
86
+
<input type="text" id="plc-token" name="plc-token" bind:value={plcToken} required>
87
+
</div>
88
+
<p style="text-align: left">You can now select to add a new Rotation Key during migration and sign up
89
+
for PDS MOOver's free backup service. With a Rotation Key and backups if your new PDS ever goes down
90
+
you can recover your account and it's data.</p>
91
+
<div class="form-group">
92
+
<label for="rotation-key" class="moove-checkbox-label">
93
+
<input bind:checked={createANewRotationKey} type="checkbox" id="rotation-key"
94
+
name="rotation-key">
95
+
<span>Create and add a new Rotation Key</span>
96
+
</label>
97
+
</div>
98
+
<div class="form-group">
99
+
<label for="backups-signup" class="moove-checkbox-label">
100
+
<input bind:checked={signupForBackups} type="checkbox" id="backups-signup"
101
+
name="backups-signup">
102
+
<span>Signup for automated account backups</span>
103
+
</label>
104
+
</div>
105
+
<div class="form-group">
106
+
<button type="button" id="plc-advance"
107
+
onclick={() => showAdvancedPlcOptions = !showAdvancedPlcOptions}>Add
108
+
Additional Rotation Keys
109
+
</button>
110
+
</div>
111
+
{#if showAdvancedPlcOptions}
112
+
<div class="section" style="padding-bottom: 10px;">
113
+
<div style="text-align: left;">
114
+
You can pick up to 4 rotation keys to your PLC document. These will appear above your new
115
+
PDS
116
+
rotation key so you can recover your account in the event of an adversarial take over from a
117
+
rogue PDS
118
+
</div>
119
+
<div class="form-group" style="margin-top: 10px;">
120
+
<label for="rotation-key-1">Rotation key 1</label>
121
+
<input type="text" id="rotation-key-1" name="rotation-key-1"
122
+
bind:value={rotationKeys[0]}
123
+
disabled={createANewRotationKey}
124
+
placeholder={createANewRotationKey ? 'reserved for the newly created rotation key' : ''}>
125
+
</div>
126
+
<div class="form-group">
127
+
<label for="rotation-key-2">Rotation key 2</label>
128
+
<input type="text" id="rotation-key-2" name="rotation-key-2" bind:value={rotationKeys[1]}>
129
+
</div>
130
+
<div class="form-group">
131
+
<label for="rotation-key-3">Rotation key 3</label>
132
+
<input type="text" id="rotation-key-3" name="rotation-key-3" bind:value={rotationKeys[2]}>
133
+
</div>
134
+
<div class="form-group">
135
+
<label for="rotation-key-4">Rotation key 4</label>
136
+
<input type="text" id="rotation-key-4" name="rotation-key-4" bind:value={rotationKeys[3]}>
137
+
</div>
138
+
</div>
139
+
{/if}
140
+
</div>
141
+
{/if}
142
+
{#if errorMessage}
143
+
<div class="error-message">{errorMessage}</div>
144
+
{/if}
145
+
146
+
{#if done && createANewRotationKey && newlyCreatedRotationKey}
147
+
<div>
148
+
<RotationKeyDisplay handle={newHandle} rotationKey={newlyCreatedRotationKey}/>
149
+
</div>
150
+
{/if}
151
+
152
+
{#if !done && plcStatus}
153
+
<div class="status-message">{plcStatus}</div>
154
+
{/if}
155
+
156
+
{#if signupForBackups && backupSignupMessage}
157
+
<div>
158
+
<div class="status-message">{backupSignupMessage}</div>
159
+
{#if backupSignupError}
160
+
<div class="error-message">{backupSignupError}</div>
161
+
{/if}
162
+
163
+
</div>
164
+
{/if}
165
+
166
+
{#if done}
167
+
<div class="status-message">Congratulations! You have MOOved to a new PDS! Remember to use
168
+
your new PDS URL under "Hosting provider" when logging in on Bluesky. Can find more detail information
169
+
<a href={resolve('/info#cant-login')}>here.</a></div>
170
+
{:else }
171
+
<div>
172
+
<button type="submit">Sign the papers</button>
173
+
</div>
174
+
{/if}
175
+
176
+
177
+
</form>
178
+
</div>
+296
web-ui/src/routes/restore/+page.svelte
+296
web-ui/src/routes/restore/+page.svelte
···
1
+
<script lang="ts">
2
+
import {Restore} from '@pds-moover/moover';
3
+
import MooHeader from '$lib/components/MooHeader.svelte';
4
+
import LoadingSpinner from '$lib/components/LoadingSpinner.svelte';
5
+
import {PUBLIC_XRPC_BASE} from '$env/static/public';
6
+
import OgImage from '$lib/components/OgImage.svelte';
7
+
8
+
//Regexs to catch rotation key type
9
+
const HEX_REGEX = /^[0-9a-f]+$/i;
10
+
11
+
// Service instances
12
+
let restoreService = $state(new Restore(`https://${PUBLIC_XRPC_BASE}`));
13
+
14
+
// Form inputs
15
+
let currentHandle = $state('');
16
+
let rotationKey = $state('');
17
+
let newPds = $state('');
18
+
let newHandle = $state('');
19
+
let newPassword = $state('');
20
+
let newEmail = $state('');
21
+
let inviteCode = $state('');
22
+
let cid = $state('');
23
+
24
+
// Rotation key type detection and selection
25
+
let isHexKey = $state(false);
26
+
let rotationKeyType = $state<'secp256k1' | 'p256'>('secp256k1');
27
+
28
+
// Advanced options
29
+
let restoreFilesFromBackup = $state(true);
30
+
let recoverAccount = $state(true);
31
+
32
+
// UI state
33
+
let errorMessage = $state<string | null>(null);
34
+
let showStatusMessage = $state(false);
35
+
let showAdvanced = $state(false);
36
+
let done = $state(false);
37
+
let statusMessageText = $state('');
38
+
let isSubmitting = $state(false);
39
+
40
+
function setStatus(message: string) {
41
+
console.log('Status update:', message);
42
+
statusMessageText = message;
43
+
showStatusMessage = true;
44
+
}
45
+
46
+
function handleRotationKeyChange() {
47
+
const trimmedKey = rotationKey.trim();
48
+
if (trimmedKey && HEX_REGEX.test(trimmedKey)) {
49
+
isHexKey = true;
50
+
} else {
51
+
isHexKey = false;
52
+
}
53
+
}
54
+
55
+
async function handleSubmit() {
56
+
errorMessage = null;
57
+
showStatusMessage = false;
58
+
isSubmitting = true;
59
+
60
+
try {
61
+
restoreService.RestoreFromBackup = restoreFilesFromBackup;
62
+
restoreService.AccountRecovery = recoverAccount;
63
+
64
+
await restoreService.recover(
65
+
rotationKey,
66
+
rotationKeyType,
67
+
currentHandle,
68
+
newPds,
69
+
newHandle,
70
+
newPassword,
71
+
newEmail,
72
+
inviteCode || null,
73
+
cid || null,
74
+
setStatus
75
+
);
76
+
done = true;
77
+
} catch (e) {
78
+
console.error(e);
79
+
// @ts-expect-error: Error is handled
80
+
errorMessage = e.message || 'An error occurred';
81
+
} finally {
82
+
isSubmitting = false;
83
+
}
84
+
}
85
+
</script>
86
+
87
+
<svelte:head>
88
+
<title>PDS MOOver - Restore</title>
89
+
<meta property="og:description" content="Recovery and restore your ATProto account"/>
90
+
<OgImage/>
91
+
</svelte:head>
92
+
93
+
<div class="container">
94
+
<MooHeader title="Restore"/>
95
+
96
+
<div class="section">
97
+
<p style="text-align: left">
98
+
Use this page to restore your AT Protocol account on a new PDS using your private rotation
99
+
key. It's intended to be used in the worst case scenario, and not for normal account
100
+
migrations. We do not need your password since your rotation key is what is used to recover
101
+
your account. Once your account has been moved to a new PDS we will also attempt to restore
102
+
your repo and blobs(pictures/videos) from our backups.
103
+
</p>
104
+
</div>
105
+
106
+
{#if !done}
107
+
<form
108
+
id="restore-form"
109
+
onsubmit={(e) => {
110
+
e.preventDefault();
111
+
handleSubmit();
112
+
}}
113
+
>
114
+
<div class="form-group">
115
+
<label for="current-handle"
116
+
>Your current handle or did (found in the recovery rotation-key.txt)</label
117
+
>
118
+
<input
119
+
id="current-handle"
120
+
bind:value={currentHandle}
121
+
placeholder="did:plc:rnpkyqnmsw4ipey6eotbdnnf"
122
+
required
123
+
/>
124
+
</div>
125
+
126
+
{#if recoverAccount}
127
+
<div class="form-group">
128
+
<label for="rotationKey">Private Rotation Key</label>
129
+
<input
130
+
id="rotationKey"
131
+
bind:value={rotationKey}
132
+
oninput={handleRotationKeyChange}
133
+
placeholder="a secp256k1 or p256 in either hex or multikey format"
134
+
required={recoverAccount}
135
+
/>
136
+
</div>
137
+
138
+
{#if isHexKey}
139
+
<div class="form-group">
140
+
<fieldset style="border: none; padding: 0; margin: 0;">
141
+
<legend style="margin-bottom: 0.5rem;">Rotation Key Type</legend>
142
+
<div style="display: flex; gap: 1rem;">
143
+
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
144
+
<input
145
+
type="radio"
146
+
name="rotationKeyType"
147
+
value="secp256k1"
148
+
bind:group={rotationKeyType}
149
+
/>
150
+
secp256k1
151
+
</label>
152
+
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
153
+
<input
154
+
type="radio"
155
+
name="rotationKeyType"
156
+
value="p256"
157
+
bind:group={rotationKeyType}
158
+
/>
159
+
p256
160
+
</label>
161
+
</div>
162
+
<small class="help-text">Select the type of your hex-encoded rotation key</small>
163
+
</fieldset>
164
+
</div>
165
+
{/if}
166
+
{/if}
167
+
168
+
<div class="form-group">
169
+
<label for="newPds">New PDS</label>
170
+
<input
171
+
id="newPds"
172
+
type="text"
173
+
bind:value={newPds}
174
+
placeholder="https://newpds.com"
175
+
required
176
+
/>
177
+
</div>
178
+
179
+
<div class="form-group">
180
+
<label for="newHandle">New Handle</label>
181
+
<input
182
+
id="newHandle"
183
+
type="text"
184
+
bind:value={newHandle}
185
+
placeholder="you.newpds.com or thisisme.com"
186
+
required
187
+
/>
188
+
</div>
189
+
190
+
<div class="form-group">
191
+
<label for="newPassword">New Password</label>
192
+
<input id="newPassword" type="password" bind:value={newPassword} required/>
193
+
</div>
194
+
195
+
<div class="form-group">
196
+
<label for="newEmail">New Email</label>
197
+
<input
198
+
id="newEmail"
199
+
type="email"
200
+
bind:value={newEmail}
201
+
placeholder="you@example.com"
202
+
required
203
+
/>
204
+
</div>
205
+
206
+
<div class="form-group">
207
+
<label for="inviteCode">Invite code (optional)</label>
208
+
<input id="inviteCode" type="text" bind:value={inviteCode} placeholder="Optional"/>
209
+
</div>
210
+
211
+
<div class="form-group">
212
+
<button type="button" onclick={() => (showAdvanced = !showAdvanced)}>
213
+
{showAdvanced ? 'Hide advanced options' : 'Show advanced options'}
214
+
</button>
215
+
</div>
216
+
217
+
{#if showAdvanced}
218
+
<div class="advanced-options">
219
+
<div class="form-group">
220
+
<label class="moove-checkbox-label">
221
+
<input
222
+
id="recoverAccount"
223
+
type="checkbox"
224
+
bind:checked={recoverAccount}
225
+
/>
226
+
Recover the did doc & account.
227
+
</label>
228
+
<br/>
229
+
<small class="help-text">This option temporary assigns a signing key to your did doc, uses it to
230
+
create a new account on the new PDS with your did, and migrates the account to the new
231
+
PDS.</small>
232
+
</div>
233
+
234
+
<div class="form-group">
235
+
<label class="moove-checkbox-label">
236
+
<input
237
+
id="restoreFilesFromBackup"
238
+
type="checkbox"
239
+
bind:checked={restoreFilesFromBackup}
240
+
/>
241
+
Restores files from backup.
242
+
</label>
243
+
</div>
244
+
245
+
{#if recoverAccount}
246
+
<div class="form-group">
247
+
<label for="cid">Cid (optional)</label>
248
+
<input
249
+
id="cid"
250
+
type="text"
251
+
bind:value={cid}
252
+
placeholder="Specific PLC audit log CID to restore to (advanced)"
253
+
/>
254
+
<small class="help-text"
255
+
>Leave empty for normal restore. IF someone besides you changed your did doc and
256
+
stole your atproto identity or a mistake was made you have up to 72hrs to reverse that
257
+
change with a valid
258
+
rotation key from the last valid operation. This input allows you to restore to the
259
+
last good PLC op via it's
260
+
CID.</small
261
+
>
262
+
</div>
263
+
{/if}
264
+
</div>
265
+
{/if}
266
+
267
+
{#if errorMessage}
268
+
<div class="error-message">{errorMessage}</div>
269
+
{/if}
270
+
{#if showStatusMessage}
271
+
<div class="status-message">{statusMessageText}</div>
272
+
{/if}
273
+
274
+
<div class="form-actions">
275
+
<button type="submit" disabled={isSubmitting}>
276
+
{#if isSubmitting}
277
+
<LoadingSpinner/>
278
+
{/if}
279
+
Recover and restore your account
280
+
</button>
281
+
</div>
282
+
</form>
283
+
{/if}
284
+
285
+
<!-- Done -->
286
+
{#if done}
287
+
<div class="section">
288
+
<div class="status-message">
289
+
Congratulations! You have successfully recovered your account! Remember to use your new
290
+
PDS URL under "Hosting provider" when logging in on Bluesky. Can find more detail
291
+
information
292
+
<a href="/info#cant-login">here.</a>
293
+
</div>
294
+
</div>
295
+
{/if}
296
+
</div>
+59
web-ui/src/routes/rotation-key/+page.svelte
+59
web-ui/src/routes/rotation-key/+page.svelte
···
1
+
<script lang="ts">
2
+
import MooHeader from '$lib/components/MooHeader.svelte';
3
+
import {PlcOps} from '@pds-moover/moover';
4
+
import type {RotationKeyType} from '$lib/types';
5
+
import RotationKeyDisplay from '$lib/components/RotationKeyDisplay.svelte';
6
+
7
+
let handle: string = $state('');
8
+
let errorMessage: null | string = $state(null);
9
+
let status: null | string = $state(null);
10
+
let newlyCreatedRotationPrivateKey: null | RotationKeyType = $state(null);
11
+
12
+
13
+
const generateNewKey = async () => {
14
+
errorMessage = null;
15
+
status = 'Generating a new rotation key…';
16
+
try {
17
+
const plcOps = new PlcOps();
18
+
newlyCreatedRotationPrivateKey = await plcOps.createANewSecp256k1();
19
+
status = 'New rotation key generated.';
20
+
} catch (e) {
21
+
console.error(e);
22
+
// @ts-expect-error: already checked for null
23
+
errorMessage = e?.message || 'Failed to generate a new rotation key';
24
+
status = null;
25
+
}
26
+
};
27
+
28
+
</script>
29
+
30
+
31
+
<div class="container">
32
+
33
+
<MooHeader title="Rotation Key"/>
34
+
<div class="section">
35
+
<p style="text-align: left;">This page is intended for development and is not listed. This will NOT save a key
36
+
to your account.</p>
37
+
<div class="form-group">
38
+
<label for="handle">Handle</label>
39
+
<input bind:value={handle} type="text" id="handle" name="handle" placeholder="Enter your handle"/>
40
+
</div>
41
+
<div class="form-group">
42
+
<button type="button" onclick={generateNewKey}>Generate New Rotation Key</button>
43
+
</div>
44
+
</div>
45
+
46
+
{#if status}
47
+
<div class="status-message">{status}</div>
48
+
{/if}
49
+
50
+
{#if errorMessage}
51
+
<div class="error-message">{errorMessage}</div>
52
+
{/if}
53
+
54
+
55
+
{#if newlyCreatedRotationPrivateKey}
56
+
<RotationKeyDisplay handle={handle} rotationKey={newlyCreatedRotationPrivateKey}/>
57
+
{/if}
58
+
59
+
</div>
+105
web-ui/src/routes/terms/+page.svelte
+105
web-ui/src/routes/terms/+page.svelte
···
1
+
<script lang="ts">
2
+
import OgImage from '$lib/components/OgImage.svelte';
3
+
</script>
4
+
5
+
<svelte:head>
6
+
<title>PDS MOOver - Legal</title>
7
+
<meta name="description" content="Terms of Service and Privacy Policy for PDS MOOver"/>
8
+
<meta property="og:description" content="Terms of Service and Privacy Policy for PDS MOOver"/>
9
+
<OgImage/>
10
+
</svelte:head>
11
+
12
+
<div class="container" style="text-align:left">
13
+
<section class="section">
14
+
15
+
<h1>Privacy Policy</h1>
16
+
<p>Last updated: 2025-10-20</p>
17
+
18
+
<h2>Overview</h2>
19
+
<p>PDS MOOver performs migrations in your browser. Where possible, operations are client side to minimize
20
+
collection of personal data by the server. Backups happen on our servers, and your data is stored in a cloud
21
+
base object store we have access to</p>
22
+
23
+
<h2>Information We May Receive</h2>
24
+
<ul>
25
+
<li>If you use optional features (e.g., backups), we take a backup of your AT Proto repo when it has a
26
+
change, any blobs you have posted to your account are stored in a <a target="_blank"
27
+
rel="noopener noreferrer"
28
+
href="https://en.wikipedia.org/wiki/Object_storage">object
29
+
store</a> that we control. Just like your <a target="_blank" rel="noopener noreferrer"
30
+
href="https://blueskyweb.zendesk.com/hc/en-us/articles/15835264007693-Data-Privacy">AT
31
+
Proto data</a> this is public and accessible to anyone. But this does not mean anyone is able to
32
+
take this data and impersonate you without what is known as a Rotation Key.
33
+
</li>
34
+
</ul>
35
+
36
+
<h2>What We Do Not Do</h2>
37
+
<ul>
38
+
<li>If you use PDS MOOver just for migrations, missing blobs, or turn off feature. We do not collect or
39
+
store any information. This happens all client side.
40
+
</li>
41
+
<li>We do not collect any personal information beyond your current PDS host and your DID if you sign up for
42
+
backups.
43
+
</li>
44
+
<li>Your passwords are only ever sent to your PDS. Your passwords are never collected, and all authenticated
45
+
requests happen proxied via your PDS to our services for backups
46
+
</li>
47
+
</ul>
48
+
49
+
<h2>Retention</h2>
50
+
<p>Server-side logs may be retained for a limited time for security, debugging, and rate-limiting. This is short
51
+
term logging and cleared on instance reboots and kept no longer than 60 days. Backup-related data, if
52
+
enabled by you, is stored indefinitely for the life of this service unless you opt out via <a
53
+
href="/backups">backups</a> and click delete to remove all of your backups and from any future ones.
54
+
</p>
55
+
56
+
<h2>Your Choices</h2>
57
+
<p>You may choose not to use the service. If you proceed, ensure you have backups and understand the migration
58
+
risks. If you ever want to be removed from our services you can also login via <a
59
+
href="/backups">backups</a> and click delete to remove all of your backups and from any future ones.
60
+
</p>
61
+
62
+
<h2>Changes</h2>
63
+
<p>We may update this Privacy Policy from time to time. Continued use after changes means you accept the updated
64
+
policy.</p>
65
+
66
+
<h2>Service Provider and Location</h2>
67
+
<p>All backup data is currently being stored on <a href="https://upcloud.com/">UpCloud's</a> <a
68
+
href="https://upcloud.com/products/object-storage/">object store</a> in a data center located in the US.
69
+
UpCloud is also our service provider for the VPS running the services. We may change service providers in
70
+
the future, if we do this terms of service will be updated to reflect that.</p>
71
+
72
+
</section>
73
+
74
+
<section class="section">
75
+
<h1>Terms of Service</h1>
76
+
<p>Last updated: 2025-10-20</p>
77
+
78
+
<p>PDS MOOver is provided on an as-is and as-available basis, without warranties of any kind. By using this site
79
+
and its tools, you agree that you understand the risks of migrating and or restoring ATProto/Bluesky
80
+
accounts and that neither the creator nor the host of this tool is responsible for any loss, corruption, or
81
+
unavailability of data, accounts, or services.</p>
82
+
83
+
<h2>Acceptable Use</h2>
84
+
<p>You agree not to misuse the service, disrupt other users, or attempt to gain unauthorized access to systems
85
+
or data. You are responsible for complying with applicable laws and policies of your hosting
86
+
provider(s).</p>
87
+
88
+
<h2>Limitation of Liability</h2>
89
+
<p>To the fullest extent permitted by law, the creator and host are not liable for any indirect, incidental,
90
+
special, consequential, or punitive damages, or any loss of data, profits, or revenues, whether incurred
91
+
directly or indirectly, resulting from your use of the service.</p>
92
+
93
+
<h2>Changes to the Service</h2>
94
+
<p>Features may change, be limited, or be discontinued at any time without notice.</p>
95
+
96
+
<h2>Backup User Content</h2>
97
+
<p>In extreme circumstances we reserve the right to ban, block, and or remove your content placed on our servers
98
+
if it is found to be illegal or harmful. We will notify you via Bluesky that you are being removed along
99
+
with giving you an export of your backed-up data.</p>
100
+
101
+
<h2>Contact</h2>
102
+
<p>If you have questions about these terms, please reach out via the project repository or to <a
103
+
href="https://bsky.app/profile/baileytownsend.dev">@baileytownsend.dev</a> directly.</p>
104
+
</section>
105
+
</div>
+101
web-ui/src/routes/turn-off/+page.svelte
+101
web-ui/src/routes/turn-off/+page.svelte
···
1
+
<script lang="ts">
2
+
import MooHeader from '$lib/components/MooHeader.svelte';
3
+
import {Migrator} from '@pds-moover/moover';
4
+
import OgImage from '$lib/components/OgImage.svelte';
5
+
6
+
let migrator = $state(new Migrator());
7
+
8
+
// Form state
9
+
let oldHandle = $state('');
10
+
let oldPassword = $state('');
11
+
let twoFactorCode = $state('');
12
+
let showTwoFactorCodeInput = $state(false);
13
+
let errorMessage: string | null = $state(null);
14
+
let showStatusMessage = $state(false);
15
+
let statusMessage = $state('');
16
+
17
+
function updateStatusHandler(status: string) {
18
+
console.log('Status update:', status);
19
+
statusMessage = status;
20
+
}
21
+
22
+
async function handleSubmit(event: SubmitEvent) {
23
+
event.preventDefault();
24
+
errorMessage = null;
25
+
showStatusMessage = false;
26
+
27
+
28
+
try {
29
+
if (showTwoFactorCodeInput) {
30
+
if (twoFactorCode === null || twoFactorCode === '') {
31
+
errorMessage = 'Please enter the 2FA that was sent to your email.';
32
+
return;
33
+
}
34
+
}
35
+
36
+
showStatusMessage = true;
37
+
await migrator.deactivateOldAccount(
38
+
oldHandle,
39
+
oldPassword,
40
+
updateStatusHandler,
41
+
twoFactorCode
42
+
);
43
+
} catch (err) {
44
+
//@ts-expect-error: error should be fine
45
+
if (err.error === 'AuthFactorTokenRequired') {
46
+
showTwoFactorCodeInput = true;
47
+
}
48
+
//@ts-expect-error: error should be fine
49
+
errorMessage = err.message;
50
+
}
51
+
}
52
+
</script>
53
+
54
+
<svelte:head>
55
+
<title>PDS MOOver - Turn OFF</title>
56
+
<meta property="og:description" content="Deactivate your old account"/>
57
+
<OgImage/>
58
+
</svelte:head>
59
+
60
+
<div class="container">
61
+
<MooHeader title="Turn OFF"/>
62
+
63
+
<p>Use this page to make sure your old account is deactivated</p>
64
+
65
+
<form id="moover-form" onsubmit={handleSubmit}>
66
+
<!-- Login credentials -->
67
+
<div class="section">
68
+
<h2>Login for your old PDS</h2>
69
+
<div class="form-group">
70
+
<label for="handle">Old Handle:</label>
71
+
<input type="text" id="handle" name="handle" placeholder="alice.bsky.social"
72
+
bind:value={oldHandle}
73
+
required>
74
+
</div>
75
+
76
+
<div class="form-group">
77
+
<label for="password">Old Password:</label>
78
+
<input type="password" id="password" name="password" bind:value={oldPassword} required>
79
+
</div>
80
+
81
+
{#if showTwoFactorCodeInput}
82
+
<div class="form-group">
83
+
<label for="two-factor-code">2FA from the email sent</label>
84
+
<input type="text" id="two-factor-code" name="two-factor-code" bind:value={twoFactorCode}>
85
+
<div class="error-message">Enter your 2fa code here</div>
86
+
</div>
87
+
{/if}
88
+
</div>
89
+
90
+
{#if errorMessage}
91
+
<div class="error-message">{errorMessage}</div>
92
+
{/if}
93
+
{#if showStatusMessage}
94
+
<div id="status-message" class="status-message">{statusMessage}</div>
95
+
{/if}
96
+
97
+
<div>
98
+
<button type="submit">Turn it off</button>
99
+
</div>
100
+
</form>
101
+
</div>
+6
web-ui/src/routes/turnoff.html/+server.ts
+6
web-ui/src/routes/turnoff.html/+server.ts
+3
web-ui/static/robots.txt
+3
web-ui/static/robots.txt
+16
web-ui/svelte.config.js
+16
web-ui/svelte.config.js
···
1
+
import adapter from '@sveltejs/adapter-node';
2
+
import {vitePreprocess} from '@sveltejs/vite-plugin-svelte';
3
+
4
+
/** @type {import('@sveltejs/kit').Config} */
5
+
const config = {
6
+
// Consult https://svelte.dev/docs/kit/integrations
7
+
// for more information about preprocessors
8
+
preprocess: vitePreprocess(),
9
+
10
+
kit: {
11
+
// https://svelte.dev/docs/kit/adapter-node
12
+
adapter: adapter()
13
+
}
14
+
};
15
+
16
+
export default config;
+22
web-ui/tsconfig.json
+22
web-ui/tsconfig.json
···
1
+
{
2
+
"extends": "./.svelte-kit/tsconfig.json",
3
+
"compilerOptions": {
4
+
"allowJs": true,
5
+
"checkJs": true,
6
+
"esModuleInterop": true,
7
+
"forceConsistentCasingInFileNames": true,
8
+
"resolveJsonModule": true,
9
+
"skipLibCheck": true,
10
+
"sourceMap": true,
11
+
"strict": true,
12
+
"moduleResolution": "bundler",
13
+
"types": [
14
+
"@pds-moover/lexicon_types"
15
+
]
16
+
}
17
+
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
18
+
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
19
+
//
20
+
// To make changes to top-level options such as include and exclude, we recommend extending
21
+
// the generated config; see https://svelte.dev/docs/kit/configuration#typescript
22
+
}
+6
web-ui/vite.config.ts
+6
web-ui/vite.config.ts
+1
-3
web/Cargo.toml
+1
-3
web/Cargo.toml
···
11
11
tracing = "0.1"
12
12
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
13
13
dotenvy.workspace = true
14
-
askama = "0.14"
15
14
serde = { version = "1", features = ["derive"] }
16
15
serde_json = "1"
17
16
anyhow.workspace = true
18
17
log.workspace = true
19
18
shared = { path = "../shared" }
20
-
vite-rust = "0.2.4"
21
-
tower-http = { version = "0.6.1", features = ["fs", "trace"] }
19
+
tower-http = { version = "0.6.1", features = ["fs", "trace", "cors"] }
22
20
tower = { version = "0.5.1", features = ["util"] }
23
21
jacquard-axum.workspace = true
24
22
jacquard-common.workspace = true
web/public/PDSMOOver.excalidraw.png
web-ui/src/lib/assets/PDSMOOver.excalidraw.png
web/public/PDSMOOver.excalidraw.png
web-ui/src/lib/assets/PDSMOOver.excalidraw.png
web/public/halloween_moover.webp
web-ui/src/lib/assets/halloween_moover.webp
web/public/halloween_moover.webp
web-ui/src/lib/assets/halloween_moover.webp
web/public/missing.webp
web-ui/src/lib/assets/missing.webp
web/public/missing.webp
web-ui/src/lib/assets/missing.webp
web/public/moo.webp
web-ui/src/lib/assets/moo.webp
web/public/moo.webp
web-ui/src/lib/assets/moo.webp
web/public/sign_the_papers.png
web-ui/src/lib/assets/sign_the_papers.png
web/public/sign_the_papers.png
web-ui/src/lib/assets/sign_the_papers.png
+1
-1
web/public/style.css
web-ui/src/lib/assets/style.css
+1
-1
web/public/style.css
web-ui/src/lib/assets/style.css
-172
web/src/handlers/pages.rs
-172
web/src/handlers/pages.rs
···
1
-
use crate::AppState;
2
-
use crate::templates::{
3
-
BackupsPage, HtmlTemplate, IndexPage, InfoPage, LayoutContext, MissingBlobsPage, MooverPage,
4
-
RestorePage, RotationKeyPage, TermsPrivacyPage, TurnOffPage, error_response,
5
-
};
6
-
use axum::Router;
7
-
use axum::extract::State;
8
-
use axum::http::StatusCode;
9
-
use axum::response::{IntoResponse, Response};
10
-
use axum::routing::get;
11
-
12
-
pub async fn index_handler(State(state): State<AppState>) -> Result<impl IntoResponse, Response> {
13
-
let layout = LayoutContext::new("PDS MOOver".to_string(), state.vite, "/").map_err(|err| {
14
-
tracing::error!(?err, "Error rendering out the index page");
15
-
error_response(
16
-
StatusCode::INTERNAL_SERVER_ERROR,
17
-
"Error rendering out the index page",
18
-
)
19
-
})?;
20
-
21
-
Ok(HtmlTemplate(IndexPage {
22
-
layout_context: layout,
23
-
}))
24
-
}
25
-
26
-
pub async fn moover_handler(State(state): State<AppState>) -> Result<impl IntoResponse, Response> {
27
-
let layout =
28
-
LayoutContext::new("PDS MOOver".to_string(), state.vite, "/moover").map_err(|err| {
29
-
tracing::error!(?err, "Error rendering out the index page");
30
-
error_response(
31
-
StatusCode::INTERNAL_SERVER_ERROR,
32
-
"Error rendering out the index page",
33
-
)
34
-
})?;
35
-
36
-
Ok(HtmlTemplate(MooverPage {
37
-
layout_context: layout,
38
-
}))
39
-
}
40
-
41
-
pub async fn info_handler(State(state): State<AppState>) -> Result<impl IntoResponse, Response> {
42
-
let layout = LayoutContext::new("PDS MOOver - Info".to_string(), state.vite, "/info").map_err(
43
-
|err| {
44
-
tracing::error!(?err, "Error rendering out the index page");
45
-
error_response(
46
-
StatusCode::INTERNAL_SERVER_ERROR,
47
-
"Error rendering out the index page",
48
-
)
49
-
},
50
-
)?;
51
-
52
-
Ok(HtmlTemplate(InfoPage {
53
-
layout_context: layout,
54
-
}))
55
-
}
56
-
57
-
pub async fn turn_off_handler(
58
-
State(state): State<AppState>,
59
-
) -> Result<impl IntoResponse, Response> {
60
-
let layout = LayoutContext::new("PDS MOOver - Turn OFF".to_string(), state.vite, "/turn-off")
61
-
.map_err(|err| {
62
-
tracing::error!(?err, "Error rendering out the index page");
63
-
error_response(
64
-
StatusCode::INTERNAL_SERVER_ERROR,
65
-
"Error rendering out the index page",
66
-
)
67
-
})?;
68
-
69
-
Ok(HtmlTemplate(TurnOffPage {
70
-
layout_context: layout,
71
-
}))
72
-
}
73
-
74
-
pub async fn missing_blobs_handler(
75
-
State(state): State<AppState>,
76
-
) -> Result<impl IntoResponse, Response> {
77
-
let layout = LayoutContext::new(
78
-
"Import Missing Blobs".to_string(),
79
-
state.vite,
80
-
"/missing-blobs",
81
-
)
82
-
.map_err(|err| {
83
-
tracing::error!(?err, "Error rendering out the index page");
84
-
error_response(
85
-
StatusCode::INTERNAL_SERVER_ERROR,
86
-
"Error rendering out the index page",
87
-
)
88
-
})?;
89
-
90
-
Ok(HtmlTemplate(MissingBlobsPage {
91
-
layout_context: layout,
92
-
}))
93
-
}
94
-
95
-
pub async fn backups_signup_handler(
96
-
State(state): State<AppState>,
97
-
) -> Result<impl IntoResponse, Response> {
98
-
let layout = LayoutContext::new("Backups - Signup".to_string(), state.vite, "/backups")
99
-
.map_err(|err| {
100
-
tracing::error!(?err, "Error rendering out the index page");
101
-
error_response(
102
-
StatusCode::INTERNAL_SERVER_ERROR,
103
-
"Error rendering out the index page",
104
-
)
105
-
})?;
106
-
107
-
Ok(HtmlTemplate(BackupsPage {
108
-
layout_context: layout,
109
-
}))
110
-
}
111
-
112
-
pub async fn rotation_key_handler(
113
-
State(state): State<AppState>,
114
-
) -> Result<impl IntoResponse, Response> {
115
-
let layout = LayoutContext::new("Rotation Key".to_string(), state.vite, "/rotation-key")
116
-
.map_err(|err| {
117
-
tracing::error!(?err, "Error rendering out the rotation key page");
118
-
error_response(
119
-
StatusCode::INTERNAL_SERVER_ERROR,
120
-
"Error rendering out the rotation key page",
121
-
)
122
-
})?;
123
-
124
-
Ok(HtmlTemplate(RotationKeyPage {
125
-
layout_context: layout,
126
-
}))
127
-
}
128
-
129
-
pub async fn restore_handler(State(state): State<AppState>) -> Result<impl IntoResponse, Response> {
130
-
let layout =
131
-
LayoutContext::new("Restore".to_string(), state.vite, "/restore").map_err(|err| {
132
-
tracing::error!(?err, "Error rendering out the restore page");
133
-
error_response(
134
-
StatusCode::INTERNAL_SERVER_ERROR,
135
-
"Error rendering out the restore page",
136
-
)
137
-
})?;
138
-
139
-
Ok(HtmlTemplate(RestorePage {
140
-
layout_context: layout,
141
-
}))
142
-
}
143
-
144
-
pub async fn terms_privacy_handler(
145
-
State(state): State<AppState>,
146
-
) -> Result<impl IntoResponse, Response> {
147
-
let layout =
148
-
LayoutContext::new("Terms & Privacy".to_string(), state.vite, "/legal").map_err(|err| {
149
-
tracing::error!(?err, "Error rendering out the legal page");
150
-
error_response(
151
-
StatusCode::INTERNAL_SERVER_ERROR,
152
-
"Error rendering out the legal page",
153
-
)
154
-
})?;
155
-
156
-
Ok(HtmlTemplate(TermsPrivacyPage {
157
-
layout_context: layout,
158
-
}))
159
-
}
160
-
161
-
pub fn pages_handlers() -> Router<AppState> {
162
-
Router::new()
163
-
.route("/", get(index_handler))
164
-
.route("/moover", get(moover_handler))
165
-
.route("/info", get(info_handler))
166
-
.route("/turn-off", get(turn_off_handler))
167
-
.route("/missing-blobs", get(missing_blobs_handler))
168
-
.route("/backups", get(backups_signup_handler))
169
-
.route("/rotation-key", get(rotation_key_handler))
170
-
.route("/restore", get(restore_handler))
171
-
.route("/terms", get(terms_privacy_handler))
172
-
}
+35
-48
web/src/main.rs
+35
-48
web/src/main.rs
···
1
1
mod handlers;
2
-
mod templates;
3
2
4
-
use crate::handlers::pages::pages_handlers;
5
3
use crate::handlers::well_known::{
6
4
ServiceDID, ServiceDocument, ServiceKey, build_service_document, handle_wellknown_did_web,
7
5
};
···
9
7
use crate::handlers::xrpc::com_pdsmoover_admin_handlers::admin_routes;
10
8
use crate::handlers::xrpc::com_pdsmoover_backup_handlers::backup_routes;
11
9
use atproto_identity::key::to_public;
12
-
use axum::handler::HandlerWithoutStateExt;
13
-
use axum::http::StatusCode;
14
-
use axum::response::Redirect;
10
+
use axum::http::header;
15
11
use axum::{Router, routing::get};
16
12
use chrono::{DateTime, Utc};
17
13
use dotenvy::dotenv;
···
28
24
use tower_governor::GovernorLayer;
29
25
use tower_governor::governor::GovernorConfigBuilder;
30
26
use tower_governor::key_extractor::SmartIpKeyExtractor;
31
-
use tower_http::services::ServeDir;
27
+
use tower_http::cors::{Any, CorsLayer};
32
28
use tracing::info;
33
29
use tracing_subscriber::{EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt};
34
-
use vite_rust::utils::resolve_path;
35
-
use vite_rust::{Vite, ViteConfig};
36
30
37
31
#[derive(Clone)]
38
32
struct AppState {
39
33
db: Db,
40
-
vite: Arc<Vite>,
41
34
public_resolver: Arc<PublicResolver>,
42
35
service_document: ServiceDocument,
43
36
did_web: ServiceDID,
···
69
62
let db = Db::connect(&database_url).await?;
70
63
db.apply_migrations().await?;
71
64
72
-
//Vite setup
73
-
let vite_dist = std::env::var("VITE_DIST").unwrap_or_else(|_| "../ui-code/dist".to_string());
74
-
let manifest_path: String =
75
-
resolve_path(file!(), format!("{vite_dist}/.vite/manifest.json").as_str());
76
-
let mut vite_config: ViteConfig<'_> = ViteConfig::default().set_manifest_path(&manifest_path);
77
-
vite_config.entrypoints = Some(vec![
78
-
"src/main.js",
79
-
"src/pdsmoover.js",
80
-
"src/missingBlobs.js",
81
-
]);
82
-
let vite = vite_rust::Vite::new(vite_config).await?;
83
-
84
-
let fallback_404_service = handle_404.into_service();
85
-
let dist_dir = ServeDir::new(format!("{vite_dist}/assets"))
86
-
.not_found_service(fallback_404_service.clone());
87
-
let public_dir =
88
-
ServeDir::new(env::var("PUBLIC_ASSETS")?).not_found_service(fallback_404_service);
89
-
90
65
//did:web/atproto service setup
91
66
let external_domain = env::var("EXTERNAL_DOMAIN")?;
92
67
let service_key_string = env::var("SERVICE_KEY")?;
···
125
100
126
101
let state = AppState {
127
102
db,
128
-
vite: Arc::new(vite),
129
103
service_document,
130
104
public_resolver: Arc::new(resolver),
131
105
did_web: service_did,
···
136
110
137
111
// Build Axum router
138
112
let mut app = Router::new()
113
+
.route("/", get(root_handler))
139
114
//XRPC Routes
140
115
.merge(backup_routes(state.clone()))
141
116
.merge(atproto_routes(state.clone()))
142
117
//Other routes
143
-
.merge(pages_handlers())
144
-
.route("/.well-known/did.json", get(handle_wellknown_did_web))
145
-
// Example legacy redirects
146
-
.route(
147
-
"/turnoff.html",
148
-
get(async move || Redirect::permanent("/turn-off")),
149
-
)
150
-
.route(
151
-
"/info.html",
152
-
get(async move || Redirect::permanent("/turn-off")),
153
-
);
118
+
.route("/.well-known/did.json", get(handle_wellknown_did_web));
154
119
155
120
// Conditionally add admin endpoints only if ADMIN_PASSWORD is set
156
121
if state.admin_token.is_some() {
···
177
142
app = app.merge(admin_routes(state.clone()).layer(governor_layer));
178
143
}
179
144
180
-
//catch all routes
181
-
app = app
182
-
.nest_service("/assets", dist_dir)
183
-
.fallback_service(public_dir);
145
+
//CORS
146
+
let cors = CorsLayer::new()
147
+
.allow_methods(Any)
148
+
.allow_origin(Any)
149
+
.allow_headers(Any);
184
150
185
151
// Finalize with state
186
-
let app = app
187
-
// .route("/demo", post(create_demo))
188
-
.with_state(state);
152
+
let app = app.layer(cors).with_state(state);
189
153
190
154
// Read PORT from env or default to 3000
191
155
let port: u16 = std::env::var("PORT")
···
202
166
Ok(())
203
167
}
204
168
205
-
async fn handle_404() -> (StatusCode, &'static str) {
206
-
(StatusCode::NOT_FOUND, "Not found")
169
+
async fn root_handler() -> impl axum::response::IntoResponse {
170
+
let body = r"
171
+
.---. .---. .--.
172
+
: .; :: . :: .--'
173
+
: _.': :: :`. `.
174
+
: : : :; : _`, :
175
+
:_; :___.'`.__.'
176
+
177
+
178
+
.-..-. .--. .--.
179
+
: `' :: ,. :: ,. :
180
+
: .. :: :: :: :: :.-..-. .--. .--.
181
+
: :; :: :; :: :; :: `; :' '_.': ..'
182
+
:_;:_;`.__.'`.__.'`.__.'`.__.':_;
183
+
184
+
";
185
+
186
+
let intro = "\n\nThis is a PDS MOOver xrpc service\n\nCode: https://tangled.sh/@baileytownsend.dev/pds-moover\n";
187
+
188
+
let banner = format!(" {body}\n{intro}");
189
+
190
+
(
191
+
[(header::CONTENT_TYPE, "text/plain; charset=utf-8")],
192
+
banner,
193
+
)
207
194
}
-127
web/src/templates.rs
-127
web/src/templates.rs
···
1
-
use askama::Template;
2
-
use axum::http::StatusCode;
3
-
use axum::response::{Html, IntoResponse, Response};
4
-
use serde::{Deserialize, Serialize};
5
-
use std::sync::Arc;
6
-
use vite_rust::Vite;
7
-
8
-
#[derive(Clone, Debug, Serialize, Deserialize)]
9
-
pub struct LayoutContext {
10
-
pub title: String,
11
-
pub script_tags: String,
12
-
pub vite_hmr_url: Option<String>,
13
-
pub current_path: String,
14
-
}
15
-
16
-
impl LayoutContext {
17
-
pub fn new(title: String, vite: Arc<Vite>, current_path: &str) -> anyhow::Result<Self> {
18
-
let vite_script_tags = vite.get_resolved_vite_scripts()?;
19
-
let hmr = if vite.get_hmr_script() == "" {
20
-
None
21
-
} else {
22
-
Some(vite.get_hmr_script())
23
-
};
24
-
Ok(Self {
25
-
title,
26
-
script_tags: vite_script_tags,
27
-
vite_hmr_url: hmr,
28
-
current_path: current_path.to_string(),
29
-
})
30
-
}
31
-
}
32
-
33
-
pub fn error_response(status: StatusCode, message: &str) -> Response {
34
-
IntoResponse::into_response((
35
-
status,
36
-
HtmlTemplate(ErrorTemplate {
37
-
title: "PDS MOOver - Error",
38
-
message,
39
-
}),
40
-
))
41
-
}
42
-
pub struct HtmlTemplate<T>(pub T);
43
-
44
-
/// Allows us to convert Askama HTML templates into valid HTML
45
-
/// for axum to serve in the response.
46
-
impl<T> IntoResponse for HtmlTemplate<T>
47
-
where
48
-
T: Template,
49
-
{
50
-
fn into_response(self) -> Response {
51
-
// Attempt to render the template with askama
52
-
match self.0.render() {
53
-
// If we're able to successfully parse and aggregate the template, serve it
54
-
Ok(html) => Html(html).into_response(),
55
-
// If we're not, return an error or some bit of fallback HTML
56
-
Err(err) => {
57
-
log::error!("Failed to render template: {}", err);
58
-
IntoResponse::into_response((
59
-
StatusCode::INTERNAL_SERVER_ERROR,
60
-
"Failed to render the HTML Template",
61
-
))
62
-
}
63
-
}
64
-
}
65
-
}
66
-
67
-
#[derive(Template)]
68
-
#[template(path = "error.askama.html")]
69
-
pub struct ErrorTemplate<'a> {
70
-
pub title: &'a str,
71
-
pub message: &'a str,
72
-
}
73
-
74
-
#[derive(Template, Debug)]
75
-
#[template(path = "index.askama.html")]
76
-
pub struct IndexPage {
77
-
pub(crate) layout_context: LayoutContext,
78
-
}
79
-
80
-
#[derive(Template, Debug)]
81
-
#[template(path = "moover.askama.html")]
82
-
pub struct MooverPage {
83
-
pub(crate) layout_context: LayoutContext,
84
-
}
85
-
86
-
#[derive(Template, Debug)]
87
-
#[template(path = "info.askama.html")]
88
-
pub struct InfoPage {
89
-
pub(crate) layout_context: LayoutContext,
90
-
}
91
-
92
-
#[derive(Template, Debug)]
93
-
#[template(path = "turn-off.askama.html")]
94
-
pub struct TurnOffPage {
95
-
pub(crate) layout_context: LayoutContext,
96
-
}
97
-
98
-
#[derive(Template, Debug)]
99
-
#[template(path = "missing-blobs.askama.html")]
100
-
pub struct MissingBlobsPage {
101
-
pub(crate) layout_context: LayoutContext,
102
-
}
103
-
104
-
#[derive(Template, Debug)]
105
-
#[template(path = "backups.askama.html")]
106
-
pub struct BackupsPage {
107
-
pub(crate) layout_context: LayoutContext,
108
-
}
109
-
110
-
111
-
#[derive(Template, Debug)]
112
-
#[template(path = "rotation-key.askama.html")]
113
-
pub struct RotationKeyPage {
114
-
pub(crate) layout_context: LayoutContext,
115
-
}
116
-
117
-
#[derive(Template, Debug)]
118
-
#[template(path = "restore.askama.html")]
119
-
pub struct RestorePage {
120
-
pub(crate) layout_context: LayoutContext,
121
-
}
122
-
123
-
#[derive(Template, Debug)]
124
-
#[template(path = "terms.askama.html")]
125
-
pub struct TermsPrivacyPage {
126
-
pub(crate) layout_context: LayoutContext,
127
-
}
+64
-30
web/templates/backups.askama.html
+64
-30
web/templates/backups.askama.html
···
17
17
showTwoFactorCodeInput: false,
18
18
error: null,
19
19
showStatusMessage: false,
20
-
showLoginScreen: true,
20
+
//The landing page to pick to login with password or oauth
21
+
showLandingButtons: true,
22
+
//Password login
23
+
showLoginScreen: false,
21
24
showRepoNotFoundScreen: false,
22
25
addRecoveryKey: true,
23
26
// Rotation key flow state
···
47
50
this.showStatusMessage = false;
48
51
}
49
52
},
53
+
handleShowLogin() {
54
+
this.showLandingButtons = false;
55
+
this.showLoginScreen = true;
56
+
},
57
+
async handleOAuthSignup() {
58
+
// TODO: Replace this URL with your actual OAuth signup endpoint for backups
59
+
// If you have an environment-specific route, consider injecting it or making it configurable
60
+
window.location.href = '/oauth/backups';
61
+
},
50
62
async handleLoginSubmit() {
63
+
this.error = null;
64
+
this.showStatusMessage = false;
65
+
this.showLandingButtons = false;
51
66
this.error = null;
52
67
this.showStatusMessage = false;
53
68
···
203
218
{% call cow::cow_header("Backups") %}
204
219
205
220
206
-
<form id="backup-signup-form" @submit.prevent="await handleLoginSubmit()" x-show="showLoginScreen">
221
+
<!-- Landing choice: two buttons -->
222
+
<div x-show="showLoginScreen">
207
223
<!-- Informational section before sign-in -->
208
224
<div class="section" style="text-align: left;">
209
-
<p>
210
-
PDS MOOver can provide worry free backups of your AT Protocol account. This is a free service for individual accounts and stores the backups on PDS MOOver's servers. Just like your <a target="_blank" rel="noopener noreferrer" href="https://blueskyweb.zendesk.com/hc/en-us/articles/15835264007693-Data-Privacy">AT Proto data</a>, this is also public. On login, you will be asked if you'd like to add a rotation key to your account.
211
-
A rotation key is a recovery key that allows you to restore your account if your PDS ever goes down. If you're already signed up for backups, then you can log in here to manage them.
212
-
</p>
225
+
<p>
226
+
PDS MOOver can provide worry-free backups of your AT Protocol account.
227
+
This is a free service for individual accounts
228
+
and stores the backups on PDS MOOver's servers.
229
+
Just like your <a target="_blank" rel="noopener noreferrer" href="https://blueskyweb.zendesk.com/hc/en-us/articles/15835264007693-Data-Privacy">AT Proto data</a>,
230
+
this is also public.
231
+
<span x-show="showLoginScreen">On login,
232
+
you will be asked if you'd like to add a rotation key to your account.
233
+
A rotation key is a recovery key
234
+
that allows you to restore your account if your PDS ever goes down.
235
+
If you're already signed up for backups, then you can log in here to manage them.</span>
236
+
237
+
</p>
213
238
</div>
214
-
<!-- Sign-in section -->
215
-
<div class="section">
216
-
<h2>Sign in to your account</h2>
217
-
<div class="form-group">
218
-
<label for="handle">Handle</label>
219
-
<input type="text" id="handle" name="handle" placeholder="alice.bsky.social" x-model="handle" required>
220
-
</div>
221
239
222
-
<div class="form-group">
223
-
<label for="password">Real Password</label>
224
-
<input type="password" id="password" name="password" x-model="password" required>
225
-
<p> If you are signing up and adding a rotation key you have to use your account's real password. If you are just managing your backups or have your own rotation key you can use an app password</p>
240
+
<div x-show="showLandingButtons" class="actions" style="display: flex; gap: 1rem; flex-wrap: wrap;">
241
+
<button type="button" @click="handleShowLogin()">Sign in to add a recovery key</button>
242
+
<button type="button" @click="await handleOAuthSignup()">Sign in for backups with OAuth</button>
243
+
</div>
244
+
245
+
<!-- Sign in with password section -->
246
+
<form id="backup-signup-form" @submit.prevent="await handleLoginSubmit()">
247
+
248
+
<div class="section">
249
+
<h2>Sign in to your account</h2>
250
+
<div class="form-group">
251
+
<label for="handle">Handle</label>
252
+
<input type="text" id="handle" name="handle" placeholder="alice.bsky.social" x-model="handle" required>
253
+
</div>
254
+
255
+
<div class="form-group">
256
+
<label for="password">Real Password</label>
257
+
<input type="password" id="password" name="password" x-model="password" required>
258
+
<p> If you are signing up and adding a rotation key you have to use your account's real password. If you are just managing your backups or have your own rotation key you can use an app password</p>
259
+
260
+
</div>
226
261
262
+
<div x-show="showTwoFactorCodeInput" class="form-group">
263
+
<label for="two-factor-code">Two-factor code (email)</label>
264
+
<input type="text" id="two-factor-code" name="two-factor-code" x-model="twoFactorCode">
265
+
<div class="error-message">Enter the 2FA code from your email.</div>
266
+
</div>
227
267
</div>
228
268
229
-
<div x-show="showTwoFactorCodeInput" class="form-group">
230
-
<label for="two-factor-code">Two-factor code (email)</label>
231
-
<input type="text" id="two-factor-code" name="two-factor-code" x-model="twoFactorCode">
232
-
<div class="error-message">Enter the 2FA code from your email.</div>
269
+
<div x-show="error" x-text="error" class="error-message"></div>
270
+
<div x-show="showStatusMessage" id="status-message" class="status-message"></div>
271
+
<div>
272
+
<button type="submit">Login for backups</button>
233
273
</div>
234
-
</div>
235
-
236
-
<div x-show="error" x-text="error" class="error-message"></div>
237
-
<div x-show="showStatusMessage" id="status-message" class="status-message"></div>
238
-
<div>
239
-
<button type="submit">Login for backups</button>
240
-
</div>
241
-
</form>
274
+
</form>
275
+
</div>
242
276
243
277
<!-- Repo not found prompt -->
244
278
<div class="section" x-show="showRepoNotFoundScreen">
···
298
332
</template>
299
333
300
334
<!-- Repo status view for signed-up users -->
301
-
<div class="section" x-show="!showLoginScreen && !showRepoNotFoundScreen && !showRotationKeyScreen">
335
+
<div class="section" x-show="!showLandingButtons && !showLoginScreen && !showRepoNotFoundScreen && !showRotationKeyScreen">
302
336
<div class="section-header">
303
337
<h2 style="margin: 0;">Backup repository status</h2>
304
338
<button type="button" class="icon-button" title="Refresh status" aria-label="Refresh status" @click="refreshStatus">
+1
-20
web/templates/index.askama.html
+1
-20
web/templates/index.askama.html
···
28
28
}
29
29
},
30
30
//TODO bad but do not want to figure out onload with current setup
31
-
fmtBytes(bytes) {
32
-
if (bytes == null) return '—';
33
-
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
34
-
let i = 0;
35
-
let v = Number(bytes);
36
-
while (v >= 1024 && i < units.length - 1) {
37
-
v /= 1024;
38
-
i++;
39
-
}
40
-
return v.toFixed(1) + ' ' + units[i];
41
-
},
42
-
fmtDate(value) {
43
-
if (!value) return '—';
44
-
try {
45
-
const d = new Date(value);
46
-
return d.toLocaleString();
47
-
} catch (_) {
48
-
return String(value);
49
-
}
50
-
}
31
+
51
32
52
33
}));
53
34
});
+1
web/templates/moover.askama.html
+1
web/templates/moover.askama.html
web/ui-code/.gitignore
packages/moover/.gitignore
web/ui-code/.gitignore
packages/moover/.gitignore
+92
-60
web/ui-code/bun.lock
packages/moover/bun.lock
+92
-60
web/ui-code/bun.lock
packages/moover/bun.lock
···
2
2
"lockfileVersion": 1,
3
3
"workspaces": {
4
4
"": {
5
-
"name": "ui-code",
5
+
"name": "moover",
6
6
"dependencies": {
7
+
"@atcute/cbor": "^2.2.7",
8
+
"@atcute/client": "^4.0.4",
9
+
"@atcute/crypto": "^2.2.5",
10
+
"@atcute/did-plc": "^0.1.7",
7
11
"@atcute/identity-resolver": "^1.1.3",
12
+
"@atcute/lexicons": "^1.2.2",
13
+
"@atcute/multibase": "^1.1.6",
8
14
"@atproto/api": "^0.16.7",
15
+
"@pds-moover/lexicons": "^1.0.0",
16
+
"alpinejs": "^3.15.0",
9
17
"vite-plugin-full-reload": "^1.2.0",
10
18
"vite-rs-plugin": "1.0.1",
11
19
},
···
17
25
},
18
26
},
19
27
"packages": {
28
+
"@atcute/cbor": ["@atcute/cbor@2.2.7", "", { "dependencies": { "@atcute/cid": "^2.2.5", "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5" } }, "sha512-/mwAF0gnokOphceZqFq3uzMGdd8sbw5y6bxF8CRutRkCCUcpjjpJc5fkLwhxyGgOveF3mZuHE6p7t/+IAqb7Aw=="],
29
+
30
+
"@atcute/cid": ["@atcute/cid@2.2.6", "", { "dependencies": { "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5" } }, "sha512-bTAHHbJ24p+E//V4KCS4xdmd39o211jJswvqQOevj7vk+5IYcgDLx1ryZWZ1sEPOo9x875li/kj5gpKL14RDwQ=="],
31
+
32
+
"@atcute/client": ["@atcute/client@4.0.5", "", { "dependencies": { "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2" } }, "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA=="],
33
+
34
+
"@atcute/crypto": ["@atcute/crypto@2.2.5", "", { "dependencies": { "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5", "@noble/secp256k1": "^2.3.0" } }, "sha512-9CbQ9cJ68XewsbLrgdmWQS2uDD9D0hizWFJ3OOZ16TCuARREmzKEpFgHlMxPswR3bDxjwfiXzmYUlHaTqsnxRQ=="],
35
+
36
+
"@atcute/did-plc": ["@atcute/did-plc@0.1.7", "", { "dependencies": { "@atcute/cbor": "^2.2.6", "@atcute/cid": "^2.2.4", "@atcute/crypto": "^2.2.5", "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2", "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5", "@badrap/valita": "^0.4.6" } }, "sha512-a7yOQNqViae3rB5/xa3U0EPJbFD9l8zOHXx6XASZ5F8+Vy2uTgXK3omurpNZ5UxRpy1ni1AMhSohXr61cqWbkg=="],
37
+
20
38
"@atcute/identity": ["@atcute/identity@1.1.1", "", { "dependencies": { "@atcute/lexicons": "^1.2.2", "@badrap/valita": "^0.4.6" } }, "sha512-zax42n693VEhnC+5tndvO2KLDTMkHOz8UExwmklvJv7R9VujfEwiSWhcv6Jgwb3ellaG8wjiQ1lMOIjLLvwh0Q=="],
21
39
22
40
"@atcute/identity-resolver": ["@atcute/identity-resolver@1.1.4", "", { "dependencies": { "@atcute/lexicons": "^1.2.2", "@atcute/util-fetch": "^1.0.3", "@badrap/valita": "^0.4.6" }, "peerDependencies": { "@atcute/identity": "^1.0.0" } }, "sha512-/SVh8vf2cXFJenmBnGeYF2aY3WGQm3cJeew5NWTlkqoy3LvJ5wkvKq9PWu4Tv653VF40rPOp6LOdVr9Fa+q5rA=="],
23
41
24
42
"@atcute/lexicons": ["@atcute/lexicons@1.2.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "esm-env": "^1.2.2" } }, "sha512-bgEhJq5Z70/0TbK5sx+tAkrR8FsCODNiL2gUEvS5PuJfPxmFmRYNWaMGehxSPaXWpU2+Oa9ckceHiYbrItDTkA=="],
43
+
44
+
"@atcute/multibase": ["@atcute/multibase@1.1.6", "", { "dependencies": { "@atcute/uint8array": "^1.0.5" } }, "sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg=="],
45
+
46
+
"@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="],
25
47
26
48
"@atcute/util-fetch": ["@atcute/util-fetch@1.0.3", "", { "dependencies": { "@badrap/valita": "^0.4.6" } }, "sha512-f8zzTb/xlKIwv2OQ31DhShPUNCmIIleX6p7qIXwWwEUjX6x8skUtpdISSjnImq01LXpltGV5y8yhV4/Mlb7CRQ=="],
27
49
···
37
59
38
60
"@badrap/valita": ["@badrap/valita@0.4.6", "", {}, "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg=="],
39
61
40
-
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.10", "", { "os": "aix", "cpu": "ppc64" }, "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw=="],
62
+
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.11", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg=="],
41
63
42
-
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.10", "", { "os": "android", "cpu": "arm" }, "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w=="],
64
+
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.11", "", { "os": "android", "cpu": "arm" }, "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg=="],
43
65
44
-
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.10", "", { "os": "android", "cpu": "arm64" }, "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg=="],
66
+
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.11", "", { "os": "android", "cpu": "arm64" }, "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ=="],
45
67
46
-
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.10", "", { "os": "android", "cpu": "x64" }, "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg=="],
68
+
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.11", "", { "os": "android", "cpu": "x64" }, "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g=="],
47
69
48
-
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA=="],
70
+
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w=="],
49
71
50
-
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg=="],
72
+
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ=="],
51
73
52
-
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.10", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg=="],
74
+
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.11", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA=="],
53
75
54
-
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.10", "", { "os": "freebsd", "cpu": "x64" }, "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA=="],
76
+
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw=="],
55
77
56
-
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.10", "", { "os": "linux", "cpu": "arm" }, "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg=="],
78
+
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.11", "", { "os": "linux", "cpu": "arm" }, "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw=="],
57
79
58
-
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ=="],
80
+
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA=="],
59
81
60
-
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.10", "", { "os": "linux", "cpu": "ia32" }, "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ=="],
82
+
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.11", "", { "os": "linux", "cpu": "ia32" }, "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw=="],
61
83
62
-
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg=="],
84
+
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw=="],
63
85
64
-
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA=="],
86
+
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ=="],
65
87
66
-
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.10", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA=="],
88
+
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.11", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw=="],
67
89
68
-
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA=="],
90
+
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.11", "", { "os": "linux", "cpu": "none" }, "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww=="],
69
91
70
-
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.10", "", { "os": "linux", "cpu": "s390x" }, "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew=="],
92
+
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.11", "", { "os": "linux", "cpu": "s390x" }, "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw=="],
71
93
72
-
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.10", "", { "os": "linux", "cpu": "x64" }, "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA=="],
94
+
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.11", "", { "os": "linux", "cpu": "x64" }, "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ=="],
73
95
74
-
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A=="],
96
+
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg=="],
75
97
76
-
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.10", "", { "os": "none", "cpu": "x64" }, "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig=="],
98
+
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.11", "", { "os": "none", "cpu": "x64" }, "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A=="],
77
99
78
-
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.10", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw=="],
100
+
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.11", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg=="],
79
101
80
-
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.10", "", { "os": "openbsd", "cpu": "x64" }, "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw=="],
102
+
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.11", "", { "os": "openbsd", "cpu": "x64" }, "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw=="],
81
103
82
-
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag=="],
104
+
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.11", "", { "os": "none", "cpu": "arm64" }, "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ=="],
83
105
84
-
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.10", "", { "os": "sunos", "cpu": "x64" }, "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ=="],
106
+
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.11", "", { "os": "sunos", "cpu": "x64" }, "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA=="],
85
107
86
-
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw=="],
108
+
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q=="],
87
109
88
-
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.10", "", { "os": "win32", "cpu": "ia32" }, "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw=="],
110
+
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA=="],
89
111
90
-
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.10", "", { "os": "win32", "cpu": "x64" }, "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw=="],
112
+
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.11", "", { "os": "win32", "cpu": "x64" }, "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA=="],
91
113
92
114
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="],
93
115
94
-
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="],
116
+
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
95
117
96
-
"@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="],
118
+
"@eslint/config-array": ["@eslint/config-array@0.21.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA=="],
97
119
98
-
"@eslint/config-helpers": ["@eslint/config-helpers@0.4.0", "", { "dependencies": { "@eslint/core": "^0.16.0" } }, "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog=="],
120
+
"@eslint/config-helpers": ["@eslint/config-helpers@0.4.1", "", { "dependencies": { "@eslint/core": "^0.16.0" } }, "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw=="],
99
121
100
122
"@eslint/core": ["@eslint/core@0.16.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q=="],
101
123
102
124
"@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
103
125
104
-
"@eslint/js": ["@eslint/js@9.37.0", "", {}, "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg=="],
126
+
"@eslint/js": ["@eslint/js@9.38.0", "", {}, "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A=="],
105
127
106
-
"@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
128
+
"@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
107
129
108
130
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.0", "", { "dependencies": { "@eslint/core": "^0.16.0", "levn": "^0.4.1" } }, "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A=="],
109
131
···
115
137
116
138
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
117
139
118
-
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.4", "", { "os": "android", "cpu": "arm" }, "sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA=="],
140
+
"@noble/secp256k1": ["@noble/secp256k1@2.3.0", "", {}, "sha512-0TQed2gcBbIrh7Ccyw+y/uZQvbJwm7Ao4scBUxqpBCcsOlZG0O4KGfjtNAy/li4W8n1xt3dxrwJ0beZ2h2G6Kw=="],
119
141
120
-
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.4", "", { "os": "android", "cpu": "arm64" }, "sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w=="],
142
+
"@pds-moover/lexicons": ["@pds-moover/lexicons@1.0.0", "", { "dependencies": { "@atproto/lexicon": "^0.5.1", "@atproto/xrpc": "^0.7.5" } }, "sha512-1/q4ZUf0PuyDTLuyuGunsBvQBo1+V8W80/QAw7VHqO6Uvu/+VjcriM2C7O4F7Q+KFX3QPFEiK0vRSyaSdgg5Zw=="],
121
143
122
-
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg=="],
144
+
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.5", "", { "os": "android", "cpu": "arm" }, "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ=="],
123
145
124
-
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw=="],
146
+
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.52.5", "", { "os": "android", "cpu": "arm64" }, "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA=="],
125
147
126
-
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ=="],
148
+
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.52.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA=="],
127
149
128
-
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw=="],
150
+
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.52.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA=="],
129
151
130
-
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.4", "", { "os": "linux", "cpu": "arm" }, "sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ=="],
152
+
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.52.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA=="],
131
153
132
-
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.4", "", { "os": "linux", "cpu": "arm" }, "sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q=="],
154
+
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.52.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ=="],
133
155
134
-
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg=="],
156
+
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ=="],
135
157
136
-
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g=="],
158
+
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.52.5", "", { "os": "linux", "cpu": "arm" }, "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ=="],
137
159
138
-
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.4", "", { "os": "linux", "cpu": "none" }, "sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ=="],
160
+
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg=="],
139
161
140
-
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g=="],
162
+
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.52.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q=="],
141
163
142
-
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.4", "", { "os": "linux", "cpu": "none" }, "sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg=="],
164
+
"@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA=="],
143
165
144
-
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.4", "", { "os": "linux", "cpu": "none" }, "sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA=="],
166
+
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.52.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw=="],
145
167
146
-
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA=="],
168
+
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw=="],
147
169
148
-
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.4", "", { "os": "linux", "cpu": "x64" }, "sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg=="],
170
+
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.52.5", "", { "os": "linux", "cpu": "none" }, "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg=="],
149
171
150
-
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.4", "", { "os": "linux", "cpu": "x64" }, "sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw=="],
172
+
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.52.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ=="],
151
173
152
-
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.4", "", { "os": "none", "cpu": "arm64" }, "sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA=="],
174
+
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q=="],
153
175
154
-
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ=="],
176
+
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg=="],
155
177
156
-
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw=="],
178
+
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.52.5", "", { "os": "none", "cpu": "arm64" }, "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw=="],
157
179
158
-
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.4", "", { "os": "win32", "cpu": "x64" }, "sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ=="],
180
+
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.52.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w=="],
159
181
160
-
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.4", "", { "os": "win32", "cpu": "x64" }, "sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w=="],
182
+
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.52.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg=="],
183
+
184
+
"@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ=="],
185
+
186
+
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg=="],
161
187
162
188
"@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="],
163
189
···
169
195
170
196
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
171
197
198
+
"@vue/reactivity": ["@vue/reactivity@3.1.5", "", { "dependencies": { "@vue/shared": "3.1.5" } }, "sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg=="],
199
+
200
+
"@vue/shared": ["@vue/shared@3.1.5", "", {}, "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA=="],
201
+
172
202
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
173
203
174
204
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
175
205
176
206
"ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
207
+
208
+
"alpinejs": ["alpinejs@3.15.1", "", { "dependencies": { "@vue/reactivity": "~3.1.1" } }, "sha512-HLO1TtiE92VajFHtLLPK8BWaK1YepV/uj31UrfoGnQ00lyFOJZ+oVY3F0DghPAwvg8sLU79pmjGQSytERa2gEg=="],
177
209
178
210
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
179
211
···
251
283
252
284
"es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],
253
285
254
-
"esbuild": ["esbuild@0.25.10", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.10", "@esbuild/android-arm": "0.25.10", "@esbuild/android-arm64": "0.25.10", "@esbuild/android-x64": "0.25.10", "@esbuild/darwin-arm64": "0.25.10", "@esbuild/darwin-x64": "0.25.10", "@esbuild/freebsd-arm64": "0.25.10", "@esbuild/freebsd-x64": "0.25.10", "@esbuild/linux-arm": "0.25.10", "@esbuild/linux-arm64": "0.25.10", "@esbuild/linux-ia32": "0.25.10", "@esbuild/linux-loong64": "0.25.10", "@esbuild/linux-mips64el": "0.25.10", "@esbuild/linux-ppc64": "0.25.10", "@esbuild/linux-riscv64": "0.25.10", "@esbuild/linux-s390x": "0.25.10", "@esbuild/linux-x64": "0.25.10", "@esbuild/netbsd-arm64": "0.25.10", "@esbuild/netbsd-x64": "0.25.10", "@esbuild/openbsd-arm64": "0.25.10", "@esbuild/openbsd-x64": "0.25.10", "@esbuild/openharmony-arm64": "0.25.10", "@esbuild/sunos-x64": "0.25.10", "@esbuild/win32-arm64": "0.25.10", "@esbuild/win32-ia32": "0.25.10", "@esbuild/win32-x64": "0.25.10" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ=="],
286
+
"esbuild": ["esbuild@0.25.11", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.11", "@esbuild/android-arm": "0.25.11", "@esbuild/android-arm64": "0.25.11", "@esbuild/android-x64": "0.25.11", "@esbuild/darwin-arm64": "0.25.11", "@esbuild/darwin-x64": "0.25.11", "@esbuild/freebsd-arm64": "0.25.11", "@esbuild/freebsd-x64": "0.25.11", "@esbuild/linux-arm": "0.25.11", "@esbuild/linux-arm64": "0.25.11", "@esbuild/linux-ia32": "0.25.11", "@esbuild/linux-loong64": "0.25.11", "@esbuild/linux-mips64el": "0.25.11", "@esbuild/linux-ppc64": "0.25.11", "@esbuild/linux-riscv64": "0.25.11", "@esbuild/linux-s390x": "0.25.11", "@esbuild/linux-x64": "0.25.11", "@esbuild/netbsd-arm64": "0.25.11", "@esbuild/netbsd-x64": "0.25.11", "@esbuild/openbsd-arm64": "0.25.11", "@esbuild/openbsd-x64": "0.25.11", "@esbuild/openharmony-arm64": "0.25.11", "@esbuild/sunos-x64": "0.25.11", "@esbuild/win32-arm64": "0.25.11", "@esbuild/win32-ia32": "0.25.11", "@esbuild/win32-x64": "0.25.11" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q=="],
255
287
256
288
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
257
289
258
-
"eslint": ["eslint@9.37.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.4.0", "@eslint/core": "^0.16.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.37.0", "@eslint/plugin-kit": "^0.4.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig=="],
290
+
"eslint": ["eslint@9.38.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.1", "@eslint/core": "^0.16.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.38.0", "@eslint/plugin-kit": "^0.4.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw=="],
259
291
260
292
"eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="],
261
293
···
475
507
476
508
"regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
477
509
478
-
"resolve": ["resolve@1.22.10", "", { "dependencies": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w=="],
510
+
"resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
479
511
480
512
"resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
481
513
482
-
"rollup": ["rollup@4.52.4", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.4", "@rollup/rollup-android-arm64": "4.52.4", "@rollup/rollup-darwin-arm64": "4.52.4", "@rollup/rollup-darwin-x64": "4.52.4", "@rollup/rollup-freebsd-arm64": "4.52.4", "@rollup/rollup-freebsd-x64": "4.52.4", "@rollup/rollup-linux-arm-gnueabihf": "4.52.4", "@rollup/rollup-linux-arm-musleabihf": "4.52.4", "@rollup/rollup-linux-arm64-gnu": "4.52.4", "@rollup/rollup-linux-arm64-musl": "4.52.4", "@rollup/rollup-linux-loong64-gnu": "4.52.4", "@rollup/rollup-linux-ppc64-gnu": "4.52.4", "@rollup/rollup-linux-riscv64-gnu": "4.52.4", "@rollup/rollup-linux-riscv64-musl": "4.52.4", "@rollup/rollup-linux-s390x-gnu": "4.52.4", "@rollup/rollup-linux-x64-gnu": "4.52.4", "@rollup/rollup-linux-x64-musl": "4.52.4", "@rollup/rollup-openharmony-arm64": "4.52.4", "@rollup/rollup-win32-arm64-msvc": "4.52.4", "@rollup/rollup-win32-ia32-msvc": "4.52.4", "@rollup/rollup-win32-x64-gnu": "4.52.4", "@rollup/rollup-win32-x64-msvc": "4.52.4", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ=="],
514
+
"rollup": ["rollup@4.52.5", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.52.5", "@rollup/rollup-android-arm64": "4.52.5", "@rollup/rollup-darwin-arm64": "4.52.5", "@rollup/rollup-darwin-x64": "4.52.5", "@rollup/rollup-freebsd-arm64": "4.52.5", "@rollup/rollup-freebsd-x64": "4.52.5", "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", "@rollup/rollup-linux-arm-musleabihf": "4.52.5", "@rollup/rollup-linux-arm64-gnu": "4.52.5", "@rollup/rollup-linux-arm64-musl": "4.52.5", "@rollup/rollup-linux-loong64-gnu": "4.52.5", "@rollup/rollup-linux-ppc64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-gnu": "4.52.5", "@rollup/rollup-linux-riscv64-musl": "4.52.5", "@rollup/rollup-linux-s390x-gnu": "4.52.5", "@rollup/rollup-linux-x64-gnu": "4.52.5", "@rollup/rollup-linux-x64-musl": "4.52.5", "@rollup/rollup-openharmony-arm64": "4.52.5", "@rollup/rollup-win32-arm64-msvc": "4.52.5", "@rollup/rollup-win32-ia32-msvc": "4.52.5", "@rollup/rollup-win32-x64-gnu": "4.52.5", "@rollup/rollup-win32-x64-msvc": "4.52.5", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw=="],
483
515
484
516
"safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="],
485
517
···
527
559
528
560
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
529
561
530
-
"tlds": ["tlds@1.260.0", "", { "bin": { "tlds": "bin.js" } }, "sha512-78+28EWBhCEE7qlyaHA9OR3IPvbCLiDh3Ckla593TksfFc9vfTsgvH7eS+dr3o9qr31gwGbogcI16yN91PoRjQ=="],
562
+
"tlds": ["tlds@1.261.0", "", { "bin": { "tlds": "bin.js" } }, "sha512-QXqwfEl9ddlGBaRFXIvNKK6OhipSiLXuRuLJX5DErz0o0Q0rYxulWLdFryTkV5PkdZct5iMInwYEGe/eR++1AA=="],
531
563
532
564
"tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
533
565
···
547
579
548
580
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
549
581
550
-
"vite": ["vite@7.1.9", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg=="],
582
+
"vite": ["vite@7.1.12", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug=="],
551
583
552
584
"vite-plugin-full-reload": ["vite-plugin-full-reload@1.2.0", "", { "dependencies": { "picocolors": "^1.0.0", "picomatch": "^2.3.1" } }, "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA=="],
553
585
-26
web/ui-code/eslint.config.js
-26
web/ui-code/eslint.config.js
···
1
-
export default [
2
-
{
3
-
ignores: ['node_modules/**', 'dist/**']
4
-
},
5
-
{
6
-
languageOptions: {
7
-
ecmaVersion: 'latest',
8
-
sourceType: 'module',
9
-
globals: {
10
-
document: 'readonly',
11
-
navigator: 'readonly',
12
-
window: 'readonly',
13
-
console: 'readonly'
14
-
}
15
-
},
16
-
linterOptions: {
17
-
reportUnusedDisableDirectives: true
18
-
},
19
-
rules: {
20
-
'semi': ['error', 'always'],
21
-
'quotes': ['error', 'single'],
22
-
'indent': ['error', 2],
23
-
'no-unused-vars': 'warn'
24
-
}
25
-
}
26
-
];
-26
web/ui-code/index.html
-26
web/ui-code/index.html
···
1
-
<!doctype html>
2
-
<html lang="en">
3
-
<head>
4
-
<meta charset="UTF-8"/>
5
-
<link rel="icon" type="image/svg+xml" href="/vite.svg"/>
6
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
7
-
<title>ui-code</title>
8
-
</head>
9
-
<body>
10
-
<div id="app"></div>
11
-
<!--<script type="module" src="/src/plc-ops.js">-->
12
-
13
-
14
-
<script type="module">
15
-
import {PlcOps} from './src/plc-ops.js';
16
-
17
-
const plcOps = new PlcOps();
18
-
19
-
window.runTest = async () => plcOps.test('did:plc:uc7pehijmk5jrllip4cglxdd');
20
-
</script>
21
-
22
-
<button onclick="window.runTest()">Run Test</button>
23
-
24
-
</body>
25
-
26
-
</html>
-4287
web/ui-code/package-lock.json
-4287
web/ui-code/package-lock.json
···
1
-
{
2
-
"name": "ui-code",
3
-
"version": "0.0.0",
4
-
"lockfileVersion": 3,
5
-
"requires": true,
6
-
"packages": {
7
-
"": {
8
-
"name": "ui-code",
9
-
"version": "0.0.0",
10
-
"dependencies": {
11
-
"@atcute/cbor": "^2.2.7",
12
-
"@atcute/client": "^4.0.4",
13
-
"@atcute/crypto": "^2.2.5",
14
-
"@atcute/did-plc": "^0.1.7",
15
-
"@atcute/identity-resolver": "^1.1.3",
16
-
"@atcute/multibase": "^1.1.6",
17
-
"@atproto/api": "^0.16.7",
18
-
"alpinejs": "^3.15.0",
19
-
"vite-plugin-full-reload": "^1.2.0",
20
-
"vite-rs-plugin": "1.0.1"
21
-
},
22
-
"devDependencies": {
23
-
"eslint": "^9.34.0",
24
-
"eslint-plugin-import": "^2.32.0",
25
-
"vite": "^7.1.7"
26
-
}
27
-
},
28
-
"node_modules/@atcute/cbor": {
29
-
"version": "2.2.7",
30
-
"resolved": "https://registry.npmjs.org/@atcute/cbor/-/cbor-2.2.7.tgz",
31
-
"integrity": "sha512-/mwAF0gnokOphceZqFq3uzMGdd8sbw5y6bxF8CRutRkCCUcpjjpJc5fkLwhxyGgOveF3mZuHE6p7t/+IAqb7Aw==",
32
-
"license": "0BSD",
33
-
"dependencies": {
34
-
"@atcute/cid": "^2.2.5",
35
-
"@atcute/multibase": "^1.1.6",
36
-
"@atcute/uint8array": "^1.0.5"
37
-
}
38
-
},
39
-
"node_modules/@atcute/cid": {
40
-
"version": "2.2.5",
41
-
"resolved": "https://registry.npmjs.org/@atcute/cid/-/cid-2.2.5.tgz",
42
-
"integrity": "sha512-7SId61nMyuxSwsDI02wEZn6/gVeha2TrAN4W0UPSdSEcwQD3R2W8VU7zvR4XGfU7A/KmBnVkwx5FTfzyizKj6g==",
43
-
"license": "0BSD",
44
-
"dependencies": {
45
-
"@atcute/multibase": "^1.1.6",
46
-
"@atcute/uint8array": "^1.0.5"
47
-
}
48
-
},
49
-
"node_modules/@atcute/client": {
50
-
"version": "4.0.5",
51
-
"resolved": "https://registry.npmjs.org/@atcute/client/-/client-4.0.5.tgz",
52
-
"integrity": "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA==",
53
-
"license": "0BSD",
54
-
"dependencies": {
55
-
"@atcute/identity": "^1.1.1",
56
-
"@atcute/lexicons": "^1.2.2"
57
-
}
58
-
},
59
-
"node_modules/@atcute/crypto": {
60
-
"version": "2.2.5",
61
-
"resolved": "https://registry.npmjs.org/@atcute/crypto/-/crypto-2.2.5.tgz",
62
-
"integrity": "sha512-9CbQ9cJ68XewsbLrgdmWQS2uDD9D0hizWFJ3OOZ16TCuARREmzKEpFgHlMxPswR3bDxjwfiXzmYUlHaTqsnxRQ==",
63
-
"license": "0BSD",
64
-
"dependencies": {
65
-
"@atcute/multibase": "^1.1.6",
66
-
"@atcute/uint8array": "^1.0.5",
67
-
"@noble/secp256k1": "^2.3.0"
68
-
}
69
-
},
70
-
"node_modules/@atcute/did-plc": {
71
-
"version": "0.1.7",
72
-
"resolved": "https://registry.npmjs.org/@atcute/did-plc/-/did-plc-0.1.7.tgz",
73
-
"integrity": "sha512-a7yOQNqViae3rB5/xa3U0EPJbFD9l8zOHXx6XASZ5F8+Vy2uTgXK3omurpNZ5UxRpy1ni1AMhSohXr61cqWbkg==",
74
-
"license": "0BSD",
75
-
"dependencies": {
76
-
"@atcute/cbor": "^2.2.6",
77
-
"@atcute/cid": "^2.2.4",
78
-
"@atcute/crypto": "^2.2.5",
79
-
"@atcute/identity": "^1.1.1",
80
-
"@atcute/lexicons": "^1.2.2",
81
-
"@atcute/multibase": "^1.1.6",
82
-
"@atcute/uint8array": "^1.0.5",
83
-
"@badrap/valita": "^0.4.6"
84
-
}
85
-
},
86
-
"node_modules/@atcute/identity": {
87
-
"version": "1.1.1",
88
-
"resolved": "https://registry.npmjs.org/@atcute/identity/-/identity-1.1.1.tgz",
89
-
"integrity": "sha512-zax42n693VEhnC+5tndvO2KLDTMkHOz8UExwmklvJv7R9VujfEwiSWhcv6Jgwb3ellaG8wjiQ1lMOIjLLvwh0Q==",
90
-
"license": "0BSD",
91
-
"dependencies": {
92
-
"@atcute/lexicons": "^1.2.2",
93
-
"@badrap/valita": "^0.4.6"
94
-
}
95
-
},
96
-
"node_modules/@atcute/identity-resolver": {
97
-
"version": "1.1.4",
98
-
"resolved": "https://registry.npmjs.org/@atcute/identity-resolver/-/identity-resolver-1.1.4.tgz",
99
-
"integrity": "sha512-/SVh8vf2cXFJenmBnGeYF2aY3WGQm3cJeew5NWTlkqoy3LvJ5wkvKq9PWu4Tv653VF40rPOp6LOdVr9Fa+q5rA==",
100
-
"license": "0BSD",
101
-
"dependencies": {
102
-
"@atcute/lexicons": "^1.2.2",
103
-
"@atcute/util-fetch": "^1.0.3",
104
-
"@badrap/valita": "^0.4.6"
105
-
},
106
-
"peerDependencies": {
107
-
"@atcute/identity": "^1.0.0"
108
-
}
109
-
},
110
-
"node_modules/@atcute/lexicons": {
111
-
"version": "1.2.2",
112
-
"resolved": "https://registry.npmjs.org/@atcute/lexicons/-/lexicons-1.2.2.tgz",
113
-
"integrity": "sha512-bgEhJq5Z70/0TbK5sx+tAkrR8FsCODNiL2gUEvS5PuJfPxmFmRYNWaMGehxSPaXWpU2+Oa9ckceHiYbrItDTkA==",
114
-
"license": "0BSD",
115
-
"dependencies": {
116
-
"@standard-schema/spec": "^1.0.0",
117
-
"esm-env": "^1.2.2"
118
-
}
119
-
},
120
-
"node_modules/@atcute/multibase": {
121
-
"version": "1.1.6",
122
-
"resolved": "https://registry.npmjs.org/@atcute/multibase/-/multibase-1.1.6.tgz",
123
-
"integrity": "sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg==",
124
-
"license": "0BSD",
125
-
"dependencies": {
126
-
"@atcute/uint8array": "^1.0.5"
127
-
}
128
-
},
129
-
"node_modules/@atcute/uint8array": {
130
-
"version": "1.0.5",
131
-
"resolved": "https://registry.npmjs.org/@atcute/uint8array/-/uint8array-1.0.5.tgz",
132
-
"integrity": "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q==",
133
-
"license": "0BSD"
134
-
},
135
-
"node_modules/@atcute/util-fetch": {
136
-
"version": "1.0.3",
137
-
"resolved": "https://registry.npmjs.org/@atcute/util-fetch/-/util-fetch-1.0.3.tgz",
138
-
"integrity": "sha512-f8zzTb/xlKIwv2OQ31DhShPUNCmIIleX6p7qIXwWwEUjX6x8skUtpdISSjnImq01LXpltGV5y8yhV4/Mlb7CRQ==",
139
-
"license": "0BSD",
140
-
"dependencies": {
141
-
"@badrap/valita": "^0.4.6"
142
-
}
143
-
},
144
-
"node_modules/@atproto/api": {
145
-
"version": "0.16.11",
146
-
"resolved": "https://registry.npmjs.org/@atproto/api/-/api-0.16.11.tgz",
147
-
"integrity": "sha512-1dhfQNHiclb102RW+Ea8Nft5olfqU0Ev/vlQaSX6mWNo1aP5zT+sPODJ8+BTUOYk3vcuvL7QMkqA/rLYy2PMyw==",
148
-
"license": "MIT",
149
-
"dependencies": {
150
-
"@atproto/common-web": "^0.4.3",
151
-
"@atproto/lexicon": "^0.5.1",
152
-
"@atproto/syntax": "^0.4.1",
153
-
"@atproto/xrpc": "^0.7.5",
154
-
"await-lock": "^2.2.2",
155
-
"multiformats": "^9.9.0",
156
-
"tlds": "^1.234.0",
157
-
"zod": "^3.23.8"
158
-
}
159
-
},
160
-
"node_modules/@atproto/common-web": {
161
-
"version": "0.4.3",
162
-
"resolved": "https://registry.npmjs.org/@atproto/common-web/-/common-web-0.4.3.tgz",
163
-
"integrity": "sha512-nRDINmSe4VycJzPo6fP/hEltBcULFxt9Kw7fQk6405FyAWZiTluYHlXOnU7GkQfeUK44OENG1qFTBcmCJ7e8pg==",
164
-
"license": "MIT",
165
-
"dependencies": {
166
-
"graphemer": "^1.4.0",
167
-
"multiformats": "^9.9.0",
168
-
"uint8arrays": "3.0.0",
169
-
"zod": "^3.23.8"
170
-
}
171
-
},
172
-
"node_modules/@atproto/lexicon": {
173
-
"version": "0.5.1",
174
-
"resolved": "https://registry.npmjs.org/@atproto/lexicon/-/lexicon-0.5.1.tgz",
175
-
"integrity": "sha512-y8AEtYmfgVl4fqFxqXAeGvhesiGkxiy3CWoJIfsFDDdTlZUC8DFnZrYhcqkIop3OlCkkljvpSJi1hbeC1tbi8A==",
176
-
"license": "MIT",
177
-
"dependencies": {
178
-
"@atproto/common-web": "^0.4.3",
179
-
"@atproto/syntax": "^0.4.1",
180
-
"iso-datestring-validator": "^2.2.2",
181
-
"multiformats": "^9.9.0",
182
-
"zod": "^3.23.8"
183
-
}
184
-
},
185
-
"node_modules/@atproto/syntax": {
186
-
"version": "0.4.1",
187
-
"resolved": "https://registry.npmjs.org/@atproto/syntax/-/syntax-0.4.1.tgz",
188
-
"integrity": "sha512-CJdImtLAiFO+0z3BWTtxwk6aY5w4t8orHTMVJgkf++QRJWTxPbIFko/0hrkADB7n2EruDxDSeAgfUGehpH6ngw==",
189
-
"license": "MIT"
190
-
},
191
-
"node_modules/@atproto/xrpc": {
192
-
"version": "0.7.5",
193
-
"resolved": "https://registry.npmjs.org/@atproto/xrpc/-/xrpc-0.7.5.tgz",
194
-
"integrity": "sha512-MUYNn5d2hv8yVegRL0ccHvTHAVj5JSnW07bkbiaz96UH45lvYNRVwt44z+yYVnb0/mvBzyD3/ZQ55TRGt7fHkA==",
195
-
"license": "MIT",
196
-
"dependencies": {
197
-
"@atproto/lexicon": "^0.5.1",
198
-
"zod": "^3.23.8"
199
-
}
200
-
},
201
-
"node_modules/@badrap/valita": {
202
-
"version": "0.4.6",
203
-
"resolved": "https://registry.npmjs.org/@badrap/valita/-/valita-0.4.6.tgz",
204
-
"integrity": "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==",
205
-
"license": "MIT",
206
-
"engines": {
207
-
"node": ">= 18"
208
-
}
209
-
},
210
-
"node_modules/@esbuild/aix-ppc64": {
211
-
"version": "0.25.11",
212
-
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz",
213
-
"integrity": "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==",
214
-
"cpu": [
215
-
"ppc64"
216
-
],
217
-
"license": "MIT",
218
-
"optional": true,
219
-
"os": [
220
-
"aix"
221
-
],
222
-
"engines": {
223
-
"node": ">=18"
224
-
}
225
-
},
226
-
"node_modules/@esbuild/android-arm": {
227
-
"version": "0.25.11",
228
-
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.11.tgz",
229
-
"integrity": "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==",
230
-
"cpu": [
231
-
"arm"
232
-
],
233
-
"license": "MIT",
234
-
"optional": true,
235
-
"os": [
236
-
"android"
237
-
],
238
-
"engines": {
239
-
"node": ">=18"
240
-
}
241
-
},
242
-
"node_modules/@esbuild/android-arm64": {
243
-
"version": "0.25.11",
244
-
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.11.tgz",
245
-
"integrity": "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==",
246
-
"cpu": [
247
-
"arm64"
248
-
],
249
-
"license": "MIT",
250
-
"optional": true,
251
-
"os": [
252
-
"android"
253
-
],
254
-
"engines": {
255
-
"node": ">=18"
256
-
}
257
-
},
258
-
"node_modules/@esbuild/android-x64": {
259
-
"version": "0.25.11",
260
-
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.11.tgz",
261
-
"integrity": "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==",
262
-
"cpu": [
263
-
"x64"
264
-
],
265
-
"license": "MIT",
266
-
"optional": true,
267
-
"os": [
268
-
"android"
269
-
],
270
-
"engines": {
271
-
"node": ">=18"
272
-
}
273
-
},
274
-
"node_modules/@esbuild/darwin-arm64": {
275
-
"version": "0.25.11",
276
-
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.11.tgz",
277
-
"integrity": "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==",
278
-
"cpu": [
279
-
"arm64"
280
-
],
281
-
"license": "MIT",
282
-
"optional": true,
283
-
"os": [
284
-
"darwin"
285
-
],
286
-
"engines": {
287
-
"node": ">=18"
288
-
}
289
-
},
290
-
"node_modules/@esbuild/darwin-x64": {
291
-
"version": "0.25.11",
292
-
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.11.tgz",
293
-
"integrity": "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==",
294
-
"cpu": [
295
-
"x64"
296
-
],
297
-
"license": "MIT",
298
-
"optional": true,
299
-
"os": [
300
-
"darwin"
301
-
],
302
-
"engines": {
303
-
"node": ">=18"
304
-
}
305
-
},
306
-
"node_modules/@esbuild/freebsd-arm64": {
307
-
"version": "0.25.11",
308
-
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.11.tgz",
309
-
"integrity": "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==",
310
-
"cpu": [
311
-
"arm64"
312
-
],
313
-
"license": "MIT",
314
-
"optional": true,
315
-
"os": [
316
-
"freebsd"
317
-
],
318
-
"engines": {
319
-
"node": ">=18"
320
-
}
321
-
},
322
-
"node_modules/@esbuild/freebsd-x64": {
323
-
"version": "0.25.11",
324
-
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.11.tgz",
325
-
"integrity": "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==",
326
-
"cpu": [
327
-
"x64"
328
-
],
329
-
"license": "MIT",
330
-
"optional": true,
331
-
"os": [
332
-
"freebsd"
333
-
],
334
-
"engines": {
335
-
"node": ">=18"
336
-
}
337
-
},
338
-
"node_modules/@esbuild/linux-arm": {
339
-
"version": "0.25.11",
340
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.11.tgz",
341
-
"integrity": "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==",
342
-
"cpu": [
343
-
"arm"
344
-
],
345
-
"license": "MIT",
346
-
"optional": true,
347
-
"os": [
348
-
"linux"
349
-
],
350
-
"engines": {
351
-
"node": ">=18"
352
-
}
353
-
},
354
-
"node_modules/@esbuild/linux-arm64": {
355
-
"version": "0.25.11",
356
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.11.tgz",
357
-
"integrity": "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==",
358
-
"cpu": [
359
-
"arm64"
360
-
],
361
-
"license": "MIT",
362
-
"optional": true,
363
-
"os": [
364
-
"linux"
365
-
],
366
-
"engines": {
367
-
"node": ">=18"
368
-
}
369
-
},
370
-
"node_modules/@esbuild/linux-ia32": {
371
-
"version": "0.25.11",
372
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.11.tgz",
373
-
"integrity": "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==",
374
-
"cpu": [
375
-
"ia32"
376
-
],
377
-
"license": "MIT",
378
-
"optional": true,
379
-
"os": [
380
-
"linux"
381
-
],
382
-
"engines": {
383
-
"node": ">=18"
384
-
}
385
-
},
386
-
"node_modules/@esbuild/linux-loong64": {
387
-
"version": "0.25.11",
388
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.11.tgz",
389
-
"integrity": "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==",
390
-
"cpu": [
391
-
"loong64"
392
-
],
393
-
"license": "MIT",
394
-
"optional": true,
395
-
"os": [
396
-
"linux"
397
-
],
398
-
"engines": {
399
-
"node": ">=18"
400
-
}
401
-
},
402
-
"node_modules/@esbuild/linux-mips64el": {
403
-
"version": "0.25.11",
404
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.11.tgz",
405
-
"integrity": "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==",
406
-
"cpu": [
407
-
"mips64el"
408
-
],
409
-
"license": "MIT",
410
-
"optional": true,
411
-
"os": [
412
-
"linux"
413
-
],
414
-
"engines": {
415
-
"node": ">=18"
416
-
}
417
-
},
418
-
"node_modules/@esbuild/linux-ppc64": {
419
-
"version": "0.25.11",
420
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.11.tgz",
421
-
"integrity": "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==",
422
-
"cpu": [
423
-
"ppc64"
424
-
],
425
-
"license": "MIT",
426
-
"optional": true,
427
-
"os": [
428
-
"linux"
429
-
],
430
-
"engines": {
431
-
"node": ">=18"
432
-
}
433
-
},
434
-
"node_modules/@esbuild/linux-riscv64": {
435
-
"version": "0.25.11",
436
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.11.tgz",
437
-
"integrity": "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==",
438
-
"cpu": [
439
-
"riscv64"
440
-
],
441
-
"license": "MIT",
442
-
"optional": true,
443
-
"os": [
444
-
"linux"
445
-
],
446
-
"engines": {
447
-
"node": ">=18"
448
-
}
449
-
},
450
-
"node_modules/@esbuild/linux-s390x": {
451
-
"version": "0.25.11",
452
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.11.tgz",
453
-
"integrity": "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==",
454
-
"cpu": [
455
-
"s390x"
456
-
],
457
-
"license": "MIT",
458
-
"optional": true,
459
-
"os": [
460
-
"linux"
461
-
],
462
-
"engines": {
463
-
"node": ">=18"
464
-
}
465
-
},
466
-
"node_modules/@esbuild/linux-x64": {
467
-
"version": "0.25.11",
468
-
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.11.tgz",
469
-
"integrity": "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==",
470
-
"cpu": [
471
-
"x64"
472
-
],
473
-
"license": "MIT",
474
-
"optional": true,
475
-
"os": [
476
-
"linux"
477
-
],
478
-
"engines": {
479
-
"node": ">=18"
480
-
}
481
-
},
482
-
"node_modules/@esbuild/netbsd-arm64": {
483
-
"version": "0.25.11",
484
-
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.11.tgz",
485
-
"integrity": "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==",
486
-
"cpu": [
487
-
"arm64"
488
-
],
489
-
"license": "MIT",
490
-
"optional": true,
491
-
"os": [
492
-
"netbsd"
493
-
],
494
-
"engines": {
495
-
"node": ">=18"
496
-
}
497
-
},
498
-
"node_modules/@esbuild/netbsd-x64": {
499
-
"version": "0.25.11",
500
-
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.11.tgz",
501
-
"integrity": "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==",
502
-
"cpu": [
503
-
"x64"
504
-
],
505
-
"license": "MIT",
506
-
"optional": true,
507
-
"os": [
508
-
"netbsd"
509
-
],
510
-
"engines": {
511
-
"node": ">=18"
512
-
}
513
-
},
514
-
"node_modules/@esbuild/openbsd-arm64": {
515
-
"version": "0.25.11",
516
-
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.11.tgz",
517
-
"integrity": "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==",
518
-
"cpu": [
519
-
"arm64"
520
-
],
521
-
"license": "MIT",
522
-
"optional": true,
523
-
"os": [
524
-
"openbsd"
525
-
],
526
-
"engines": {
527
-
"node": ">=18"
528
-
}
529
-
},
530
-
"node_modules/@esbuild/openbsd-x64": {
531
-
"version": "0.25.11",
532
-
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.11.tgz",
533
-
"integrity": "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==",
534
-
"cpu": [
535
-
"x64"
536
-
],
537
-
"license": "MIT",
538
-
"optional": true,
539
-
"os": [
540
-
"openbsd"
541
-
],
542
-
"engines": {
543
-
"node": ">=18"
544
-
}
545
-
},
546
-
"node_modules/@esbuild/openharmony-arm64": {
547
-
"version": "0.25.11",
548
-
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.11.tgz",
549
-
"integrity": "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==",
550
-
"cpu": [
551
-
"arm64"
552
-
],
553
-
"license": "MIT",
554
-
"optional": true,
555
-
"os": [
556
-
"openharmony"
557
-
],
558
-
"engines": {
559
-
"node": ">=18"
560
-
}
561
-
},
562
-
"node_modules/@esbuild/sunos-x64": {
563
-
"version": "0.25.11",
564
-
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.11.tgz",
565
-
"integrity": "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==",
566
-
"cpu": [
567
-
"x64"
568
-
],
569
-
"license": "MIT",
570
-
"optional": true,
571
-
"os": [
572
-
"sunos"
573
-
],
574
-
"engines": {
575
-
"node": ">=18"
576
-
}
577
-
},
578
-
"node_modules/@esbuild/win32-arm64": {
579
-
"version": "0.25.11",
580
-
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.11.tgz",
581
-
"integrity": "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==",
582
-
"cpu": [
583
-
"arm64"
584
-
],
585
-
"license": "MIT",
586
-
"optional": true,
587
-
"os": [
588
-
"win32"
589
-
],
590
-
"engines": {
591
-
"node": ">=18"
592
-
}
593
-
},
594
-
"node_modules/@esbuild/win32-ia32": {
595
-
"version": "0.25.11",
596
-
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.11.tgz",
597
-
"integrity": "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==",
598
-
"cpu": [
599
-
"ia32"
600
-
],
601
-
"license": "MIT",
602
-
"optional": true,
603
-
"os": [
604
-
"win32"
605
-
],
606
-
"engines": {
607
-
"node": ">=18"
608
-
}
609
-
},
610
-
"node_modules/@esbuild/win32-x64": {
611
-
"version": "0.25.11",
612
-
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.11.tgz",
613
-
"integrity": "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==",
614
-
"cpu": [
615
-
"x64"
616
-
],
617
-
"license": "MIT",
618
-
"optional": true,
619
-
"os": [
620
-
"win32"
621
-
],
622
-
"engines": {
623
-
"node": ">=18"
624
-
}
625
-
},
626
-
"node_modules/@eslint-community/eslint-utils": {
627
-
"version": "4.9.0",
628
-
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
629
-
"integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
630
-
"dev": true,
631
-
"license": "MIT",
632
-
"dependencies": {
633
-
"eslint-visitor-keys": "^3.4.3"
634
-
},
635
-
"engines": {
636
-
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
637
-
},
638
-
"funding": {
639
-
"url": "https://opencollective.com/eslint"
640
-
},
641
-
"peerDependencies": {
642
-
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
643
-
}
644
-
},
645
-
"node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
646
-
"version": "3.4.3",
647
-
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
648
-
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
649
-
"dev": true,
650
-
"license": "Apache-2.0",
651
-
"engines": {
652
-
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
653
-
},
654
-
"funding": {
655
-
"url": "https://opencollective.com/eslint"
656
-
}
657
-
},
658
-
"node_modules/@eslint-community/regexpp": {
659
-
"version": "4.12.1",
660
-
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
661
-
"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
662
-
"dev": true,
663
-
"license": "MIT",
664
-
"engines": {
665
-
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
666
-
}
667
-
},
668
-
"node_modules/@eslint/config-array": {
669
-
"version": "0.21.1",
670
-
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
671
-
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
672
-
"dev": true,
673
-
"license": "Apache-2.0",
674
-
"dependencies": {
675
-
"@eslint/object-schema": "^2.1.7",
676
-
"debug": "^4.3.1",
677
-
"minimatch": "^3.1.2"
678
-
},
679
-
"engines": {
680
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
681
-
}
682
-
},
683
-
"node_modules/@eslint/config-helpers": {
684
-
"version": "0.4.1",
685
-
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.1.tgz",
686
-
"integrity": "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==",
687
-
"dev": true,
688
-
"license": "Apache-2.0",
689
-
"dependencies": {
690
-
"@eslint/core": "^0.16.0"
691
-
},
692
-
"engines": {
693
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
694
-
}
695
-
},
696
-
"node_modules/@eslint/core": {
697
-
"version": "0.16.0",
698
-
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz",
699
-
"integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==",
700
-
"dev": true,
701
-
"license": "Apache-2.0",
702
-
"dependencies": {
703
-
"@types/json-schema": "^7.0.15"
704
-
},
705
-
"engines": {
706
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
707
-
}
708
-
},
709
-
"node_modules/@eslint/eslintrc": {
710
-
"version": "3.3.1",
711
-
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
712
-
"integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
713
-
"dev": true,
714
-
"license": "MIT",
715
-
"dependencies": {
716
-
"ajv": "^6.12.4",
717
-
"debug": "^4.3.2",
718
-
"espree": "^10.0.1",
719
-
"globals": "^14.0.0",
720
-
"ignore": "^5.2.0",
721
-
"import-fresh": "^3.2.1",
722
-
"js-yaml": "^4.1.0",
723
-
"minimatch": "^3.1.2",
724
-
"strip-json-comments": "^3.1.1"
725
-
},
726
-
"engines": {
727
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
728
-
},
729
-
"funding": {
730
-
"url": "https://opencollective.com/eslint"
731
-
}
732
-
},
733
-
"node_modules/@eslint/js": {
734
-
"version": "9.38.0",
735
-
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.38.0.tgz",
736
-
"integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==",
737
-
"dev": true,
738
-
"license": "MIT",
739
-
"engines": {
740
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
741
-
},
742
-
"funding": {
743
-
"url": "https://eslint.org/donate"
744
-
}
745
-
},
746
-
"node_modules/@eslint/object-schema": {
747
-
"version": "2.1.7",
748
-
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
749
-
"integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
750
-
"dev": true,
751
-
"license": "Apache-2.0",
752
-
"engines": {
753
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
754
-
}
755
-
},
756
-
"node_modules/@eslint/plugin-kit": {
757
-
"version": "0.4.0",
758
-
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz",
759
-
"integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==",
760
-
"dev": true,
761
-
"license": "Apache-2.0",
762
-
"dependencies": {
763
-
"@eslint/core": "^0.16.0",
764
-
"levn": "^0.4.1"
765
-
},
766
-
"engines": {
767
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
768
-
}
769
-
},
770
-
"node_modules/@humanfs/core": {
771
-
"version": "0.19.1",
772
-
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
773
-
"integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
774
-
"dev": true,
775
-
"license": "Apache-2.0",
776
-
"engines": {
777
-
"node": ">=18.18.0"
778
-
}
779
-
},
780
-
"node_modules/@humanfs/node": {
781
-
"version": "0.16.7",
782
-
"resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
783
-
"integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
784
-
"dev": true,
785
-
"license": "Apache-2.0",
786
-
"dependencies": {
787
-
"@humanfs/core": "^0.19.1",
788
-
"@humanwhocodes/retry": "^0.4.0"
789
-
},
790
-
"engines": {
791
-
"node": ">=18.18.0"
792
-
}
793
-
},
794
-
"node_modules/@humanwhocodes/module-importer": {
795
-
"version": "1.0.1",
796
-
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
797
-
"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
798
-
"dev": true,
799
-
"license": "Apache-2.0",
800
-
"engines": {
801
-
"node": ">=12.22"
802
-
},
803
-
"funding": {
804
-
"type": "github",
805
-
"url": "https://github.com/sponsors/nzakas"
806
-
}
807
-
},
808
-
"node_modules/@humanwhocodes/retry": {
809
-
"version": "0.4.3",
810
-
"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
811
-
"integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
812
-
"dev": true,
813
-
"license": "Apache-2.0",
814
-
"engines": {
815
-
"node": ">=18.18"
816
-
},
817
-
"funding": {
818
-
"type": "github",
819
-
"url": "https://github.com/sponsors/nzakas"
820
-
}
821
-
},
822
-
"node_modules/@noble/secp256k1": {
823
-
"version": "2.3.0",
824
-
"resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-2.3.0.tgz",
825
-
"integrity": "sha512-0TQed2gcBbIrh7Ccyw+y/uZQvbJwm7Ao4scBUxqpBCcsOlZG0O4KGfjtNAy/li4W8n1xt3dxrwJ0beZ2h2G6Kw==",
826
-
"license": "MIT",
827
-
"funding": {
828
-
"url": "https://paulmillr.com/funding/"
829
-
}
830
-
},
831
-
"node_modules/@rollup/rollup-android-arm-eabi": {
832
-
"version": "4.52.5",
833
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz",
834
-
"integrity": "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==",
835
-
"cpu": [
836
-
"arm"
837
-
],
838
-
"license": "MIT",
839
-
"optional": true,
840
-
"os": [
841
-
"android"
842
-
]
843
-
},
844
-
"node_modules/@rollup/rollup-android-arm64": {
845
-
"version": "4.52.5",
846
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.5.tgz",
847
-
"integrity": "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==",
848
-
"cpu": [
849
-
"arm64"
850
-
],
851
-
"license": "MIT",
852
-
"optional": true,
853
-
"os": [
854
-
"android"
855
-
]
856
-
},
857
-
"node_modules/@rollup/rollup-darwin-arm64": {
858
-
"version": "4.52.5",
859
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.5.tgz",
860
-
"integrity": "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==",
861
-
"cpu": [
862
-
"arm64"
863
-
],
864
-
"license": "MIT",
865
-
"optional": true,
866
-
"os": [
867
-
"darwin"
868
-
]
869
-
},
870
-
"node_modules/@rollup/rollup-darwin-x64": {
871
-
"version": "4.52.5",
872
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.5.tgz",
873
-
"integrity": "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==",
874
-
"cpu": [
875
-
"x64"
876
-
],
877
-
"license": "MIT",
878
-
"optional": true,
879
-
"os": [
880
-
"darwin"
881
-
]
882
-
},
883
-
"node_modules/@rollup/rollup-freebsd-arm64": {
884
-
"version": "4.52.5",
885
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.5.tgz",
886
-
"integrity": "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==",
887
-
"cpu": [
888
-
"arm64"
889
-
],
890
-
"license": "MIT",
891
-
"optional": true,
892
-
"os": [
893
-
"freebsd"
894
-
]
895
-
},
896
-
"node_modules/@rollup/rollup-freebsd-x64": {
897
-
"version": "4.52.5",
898
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.5.tgz",
899
-
"integrity": "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==",
900
-
"cpu": [
901
-
"x64"
902
-
],
903
-
"license": "MIT",
904
-
"optional": true,
905
-
"os": [
906
-
"freebsd"
907
-
]
908
-
},
909
-
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
910
-
"version": "4.52.5",
911
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.5.tgz",
912
-
"integrity": "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==",
913
-
"cpu": [
914
-
"arm"
915
-
],
916
-
"license": "MIT",
917
-
"optional": true,
918
-
"os": [
919
-
"linux"
920
-
]
921
-
},
922
-
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
923
-
"version": "4.52.5",
924
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.5.tgz",
925
-
"integrity": "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==",
926
-
"cpu": [
927
-
"arm"
928
-
],
929
-
"license": "MIT",
930
-
"optional": true,
931
-
"os": [
932
-
"linux"
933
-
]
934
-
},
935
-
"node_modules/@rollup/rollup-linux-arm64-gnu": {
936
-
"version": "4.52.5",
937
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.5.tgz",
938
-
"integrity": "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==",
939
-
"cpu": [
940
-
"arm64"
941
-
],
942
-
"license": "MIT",
943
-
"optional": true,
944
-
"os": [
945
-
"linux"
946
-
]
947
-
},
948
-
"node_modules/@rollup/rollup-linux-arm64-musl": {
949
-
"version": "4.52.5",
950
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.5.tgz",
951
-
"integrity": "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==",
952
-
"cpu": [
953
-
"arm64"
954
-
],
955
-
"license": "MIT",
956
-
"optional": true,
957
-
"os": [
958
-
"linux"
959
-
]
960
-
},
961
-
"node_modules/@rollup/rollup-linux-loong64-gnu": {
962
-
"version": "4.52.5",
963
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.5.tgz",
964
-
"integrity": "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==",
965
-
"cpu": [
966
-
"loong64"
967
-
],
968
-
"license": "MIT",
969
-
"optional": true,
970
-
"os": [
971
-
"linux"
972
-
]
973
-
},
974
-
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
975
-
"version": "4.52.5",
976
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.5.tgz",
977
-
"integrity": "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==",
978
-
"cpu": [
979
-
"ppc64"
980
-
],
981
-
"license": "MIT",
982
-
"optional": true,
983
-
"os": [
984
-
"linux"
985
-
]
986
-
},
987
-
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
988
-
"version": "4.52.5",
989
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.5.tgz",
990
-
"integrity": "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==",
991
-
"cpu": [
992
-
"riscv64"
993
-
],
994
-
"license": "MIT",
995
-
"optional": true,
996
-
"os": [
997
-
"linux"
998
-
]
999
-
},
1000
-
"node_modules/@rollup/rollup-linux-riscv64-musl": {
1001
-
"version": "4.52.5",
1002
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.5.tgz",
1003
-
"integrity": "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==",
1004
-
"cpu": [
1005
-
"riscv64"
1006
-
],
1007
-
"license": "MIT",
1008
-
"optional": true,
1009
-
"os": [
1010
-
"linux"
1011
-
]
1012
-
},
1013
-
"node_modules/@rollup/rollup-linux-s390x-gnu": {
1014
-
"version": "4.52.5",
1015
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.5.tgz",
1016
-
"integrity": "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==",
1017
-
"cpu": [
1018
-
"s390x"
1019
-
],
1020
-
"license": "MIT",
1021
-
"optional": true,
1022
-
"os": [
1023
-
"linux"
1024
-
]
1025
-
},
1026
-
"node_modules/@rollup/rollup-linux-x64-gnu": {
1027
-
"version": "4.52.5",
1028
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.5.tgz",
1029
-
"integrity": "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==",
1030
-
"cpu": [
1031
-
"x64"
1032
-
],
1033
-
"license": "MIT",
1034
-
"optional": true,
1035
-
"os": [
1036
-
"linux"
1037
-
]
1038
-
},
1039
-
"node_modules/@rollup/rollup-linux-x64-musl": {
1040
-
"version": "4.52.5",
1041
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.5.tgz",
1042
-
"integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==",
1043
-
"cpu": [
1044
-
"x64"
1045
-
],
1046
-
"license": "MIT",
1047
-
"optional": true,
1048
-
"os": [
1049
-
"linux"
1050
-
]
1051
-
},
1052
-
"node_modules/@rollup/rollup-openharmony-arm64": {
1053
-
"version": "4.52.5",
1054
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.5.tgz",
1055
-
"integrity": "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==",
1056
-
"cpu": [
1057
-
"arm64"
1058
-
],
1059
-
"license": "MIT",
1060
-
"optional": true,
1061
-
"os": [
1062
-
"openharmony"
1063
-
]
1064
-
},
1065
-
"node_modules/@rollup/rollup-win32-arm64-msvc": {
1066
-
"version": "4.52.5",
1067
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.5.tgz",
1068
-
"integrity": "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==",
1069
-
"cpu": [
1070
-
"arm64"
1071
-
],
1072
-
"license": "MIT",
1073
-
"optional": true,
1074
-
"os": [
1075
-
"win32"
1076
-
]
1077
-
},
1078
-
"node_modules/@rollup/rollup-win32-ia32-msvc": {
1079
-
"version": "4.52.5",
1080
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.5.tgz",
1081
-
"integrity": "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==",
1082
-
"cpu": [
1083
-
"ia32"
1084
-
],
1085
-
"license": "MIT",
1086
-
"optional": true,
1087
-
"os": [
1088
-
"win32"
1089
-
]
1090
-
},
1091
-
"node_modules/@rollup/rollup-win32-x64-gnu": {
1092
-
"version": "4.52.5",
1093
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.5.tgz",
1094
-
"integrity": "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==",
1095
-
"cpu": [
1096
-
"x64"
1097
-
],
1098
-
"license": "MIT",
1099
-
"optional": true,
1100
-
"os": [
1101
-
"win32"
1102
-
]
1103
-
},
1104
-
"node_modules/@rollup/rollup-win32-x64-msvc": {
1105
-
"version": "4.52.5",
1106
-
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.5.tgz",
1107
-
"integrity": "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==",
1108
-
"cpu": [
1109
-
"x64"
1110
-
],
1111
-
"license": "MIT",
1112
-
"optional": true,
1113
-
"os": [
1114
-
"win32"
1115
-
]
1116
-
},
1117
-
"node_modules/@rtsao/scc": {
1118
-
"version": "1.1.0",
1119
-
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
1120
-
"integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
1121
-
"dev": true,
1122
-
"license": "MIT"
1123
-
},
1124
-
"node_modules/@standard-schema/spec": {
1125
-
"version": "1.0.0",
1126
-
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
1127
-
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
1128
-
"license": "MIT"
1129
-
},
1130
-
"node_modules/@types/estree": {
1131
-
"version": "1.0.8",
1132
-
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
1133
-
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
1134
-
"license": "MIT"
1135
-
},
1136
-
"node_modules/@types/json-schema": {
1137
-
"version": "7.0.15",
1138
-
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
1139
-
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
1140
-
"dev": true,
1141
-
"license": "MIT"
1142
-
},
1143
-
"node_modules/@types/json5": {
1144
-
"version": "0.0.29",
1145
-
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
1146
-
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
1147
-
"dev": true,
1148
-
"license": "MIT"
1149
-
},
1150
-
"node_modules/@vue/reactivity": {
1151
-
"version": "3.1.5",
1152
-
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz",
1153
-
"integrity": "sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==",
1154
-
"license": "MIT",
1155
-
"dependencies": {
1156
-
"@vue/shared": "3.1.5"
1157
-
}
1158
-
},
1159
-
"node_modules/@vue/shared": {
1160
-
"version": "3.1.5",
1161
-
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.5.tgz",
1162
-
"integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==",
1163
-
"license": "MIT"
1164
-
},
1165
-
"node_modules/acorn": {
1166
-
"version": "8.15.0",
1167
-
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
1168
-
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
1169
-
"dev": true,
1170
-
"license": "MIT",
1171
-
"bin": {
1172
-
"acorn": "bin/acorn"
1173
-
},
1174
-
"engines": {
1175
-
"node": ">=0.4.0"
1176
-
}
1177
-
},
1178
-
"node_modules/acorn-jsx": {
1179
-
"version": "5.3.2",
1180
-
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
1181
-
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
1182
-
"dev": true,
1183
-
"license": "MIT",
1184
-
"peerDependencies": {
1185
-
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
1186
-
}
1187
-
},
1188
-
"node_modules/ajv": {
1189
-
"version": "6.12.6",
1190
-
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
1191
-
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
1192
-
"dev": true,
1193
-
"license": "MIT",
1194
-
"dependencies": {
1195
-
"fast-deep-equal": "^3.1.1",
1196
-
"fast-json-stable-stringify": "^2.0.0",
1197
-
"json-schema-traverse": "^0.4.1",
1198
-
"uri-js": "^4.2.2"
1199
-
},
1200
-
"funding": {
1201
-
"type": "github",
1202
-
"url": "https://github.com/sponsors/epoberezkin"
1203
-
}
1204
-
},
1205
-
"node_modules/alpinejs": {
1206
-
"version": "3.15.0",
1207
-
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.0.tgz",
1208
-
"integrity": "sha512-lpokA5okCF1BKh10LG8YjqhfpxyHBk4gE7boIgVHltJzYoM7O9nK3M7VlntLEJGsVmu7U/RzUWajmHREGT38Eg==",
1209
-
"license": "MIT",
1210
-
"dependencies": {
1211
-
"@vue/reactivity": "~3.1.1"
1212
-
}
1213
-
},
1214
-
"node_modules/ansi-styles": {
1215
-
"version": "4.3.0",
1216
-
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1217
-
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1218
-
"dev": true,
1219
-
"license": "MIT",
1220
-
"dependencies": {
1221
-
"color-convert": "^2.0.1"
1222
-
},
1223
-
"engines": {
1224
-
"node": ">=8"
1225
-
},
1226
-
"funding": {
1227
-
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
1228
-
}
1229
-
},
1230
-
"node_modules/argparse": {
1231
-
"version": "2.0.1",
1232
-
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
1233
-
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
1234
-
"dev": true,
1235
-
"license": "Python-2.0"
1236
-
},
1237
-
"node_modules/array-buffer-byte-length": {
1238
-
"version": "1.0.2",
1239
-
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
1240
-
"integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
1241
-
"dev": true,
1242
-
"license": "MIT",
1243
-
"dependencies": {
1244
-
"call-bound": "^1.0.3",
1245
-
"is-array-buffer": "^3.0.5"
1246
-
},
1247
-
"engines": {
1248
-
"node": ">= 0.4"
1249
-
},
1250
-
"funding": {
1251
-
"url": "https://github.com/sponsors/ljharb"
1252
-
}
1253
-
},
1254
-
"node_modules/array-includes": {
1255
-
"version": "3.1.9",
1256
-
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
1257
-
"integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
1258
-
"dev": true,
1259
-
"license": "MIT",
1260
-
"dependencies": {
1261
-
"call-bind": "^1.0.8",
1262
-
"call-bound": "^1.0.4",
1263
-
"define-properties": "^1.2.1",
1264
-
"es-abstract": "^1.24.0",
1265
-
"es-object-atoms": "^1.1.1",
1266
-
"get-intrinsic": "^1.3.0",
1267
-
"is-string": "^1.1.1",
1268
-
"math-intrinsics": "^1.1.0"
1269
-
},
1270
-
"engines": {
1271
-
"node": ">= 0.4"
1272
-
},
1273
-
"funding": {
1274
-
"url": "https://github.com/sponsors/ljharb"
1275
-
}
1276
-
},
1277
-
"node_modules/array.prototype.findlastindex": {
1278
-
"version": "1.2.6",
1279
-
"resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz",
1280
-
"integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
1281
-
"dev": true,
1282
-
"license": "MIT",
1283
-
"dependencies": {
1284
-
"call-bind": "^1.0.8",
1285
-
"call-bound": "^1.0.4",
1286
-
"define-properties": "^1.2.1",
1287
-
"es-abstract": "^1.23.9",
1288
-
"es-errors": "^1.3.0",
1289
-
"es-object-atoms": "^1.1.1",
1290
-
"es-shim-unscopables": "^1.1.0"
1291
-
},
1292
-
"engines": {
1293
-
"node": ">= 0.4"
1294
-
},
1295
-
"funding": {
1296
-
"url": "https://github.com/sponsors/ljharb"
1297
-
}
1298
-
},
1299
-
"node_modules/array.prototype.flat": {
1300
-
"version": "1.3.3",
1301
-
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
1302
-
"integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
1303
-
"dev": true,
1304
-
"license": "MIT",
1305
-
"dependencies": {
1306
-
"call-bind": "^1.0.8",
1307
-
"define-properties": "^1.2.1",
1308
-
"es-abstract": "^1.23.5",
1309
-
"es-shim-unscopables": "^1.0.2"
1310
-
},
1311
-
"engines": {
1312
-
"node": ">= 0.4"
1313
-
},
1314
-
"funding": {
1315
-
"url": "https://github.com/sponsors/ljharb"
1316
-
}
1317
-
},
1318
-
"node_modules/array.prototype.flatmap": {
1319
-
"version": "1.3.3",
1320
-
"resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
1321
-
"integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
1322
-
"dev": true,
1323
-
"license": "MIT",
1324
-
"dependencies": {
1325
-
"call-bind": "^1.0.8",
1326
-
"define-properties": "^1.2.1",
1327
-
"es-abstract": "^1.23.5",
1328
-
"es-shim-unscopables": "^1.0.2"
1329
-
},
1330
-
"engines": {
1331
-
"node": ">= 0.4"
1332
-
},
1333
-
"funding": {
1334
-
"url": "https://github.com/sponsors/ljharb"
1335
-
}
1336
-
},
1337
-
"node_modules/arraybuffer.prototype.slice": {
1338
-
"version": "1.0.4",
1339
-
"resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
1340
-
"integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
1341
-
"dev": true,
1342
-
"license": "MIT",
1343
-
"dependencies": {
1344
-
"array-buffer-byte-length": "^1.0.1",
1345
-
"call-bind": "^1.0.8",
1346
-
"define-properties": "^1.2.1",
1347
-
"es-abstract": "^1.23.5",
1348
-
"es-errors": "^1.3.0",
1349
-
"get-intrinsic": "^1.2.6",
1350
-
"is-array-buffer": "^3.0.4"
1351
-
},
1352
-
"engines": {
1353
-
"node": ">= 0.4"
1354
-
},
1355
-
"funding": {
1356
-
"url": "https://github.com/sponsors/ljharb"
1357
-
}
1358
-
},
1359
-
"node_modules/async-function": {
1360
-
"version": "1.0.0",
1361
-
"resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
1362
-
"integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
1363
-
"dev": true,
1364
-
"license": "MIT",
1365
-
"engines": {
1366
-
"node": ">= 0.4"
1367
-
}
1368
-
},
1369
-
"node_modules/available-typed-arrays": {
1370
-
"version": "1.0.7",
1371
-
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
1372
-
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
1373
-
"dev": true,
1374
-
"license": "MIT",
1375
-
"dependencies": {
1376
-
"possible-typed-array-names": "^1.0.0"
1377
-
},
1378
-
"engines": {
1379
-
"node": ">= 0.4"
1380
-
},
1381
-
"funding": {
1382
-
"url": "https://github.com/sponsors/ljharb"
1383
-
}
1384
-
},
1385
-
"node_modules/await-lock": {
1386
-
"version": "2.2.2",
1387
-
"resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz",
1388
-
"integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==",
1389
-
"license": "MIT"
1390
-
},
1391
-
"node_modules/balanced-match": {
1392
-
"version": "1.0.2",
1393
-
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
1394
-
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
1395
-
"dev": true,
1396
-
"license": "MIT"
1397
-
},
1398
-
"node_modules/brace-expansion": {
1399
-
"version": "1.1.12",
1400
-
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
1401
-
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
1402
-
"dev": true,
1403
-
"license": "MIT",
1404
-
"dependencies": {
1405
-
"balanced-match": "^1.0.0",
1406
-
"concat-map": "0.0.1"
1407
-
}
1408
-
},
1409
-
"node_modules/call-bind": {
1410
-
"version": "1.0.8",
1411
-
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
1412
-
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
1413
-
"dev": true,
1414
-
"license": "MIT",
1415
-
"dependencies": {
1416
-
"call-bind-apply-helpers": "^1.0.0",
1417
-
"es-define-property": "^1.0.0",
1418
-
"get-intrinsic": "^1.2.4",
1419
-
"set-function-length": "^1.2.2"
1420
-
},
1421
-
"engines": {
1422
-
"node": ">= 0.4"
1423
-
},
1424
-
"funding": {
1425
-
"url": "https://github.com/sponsors/ljharb"
1426
-
}
1427
-
},
1428
-
"node_modules/call-bind-apply-helpers": {
1429
-
"version": "1.0.2",
1430
-
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
1431
-
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
1432
-
"dev": true,
1433
-
"license": "MIT",
1434
-
"dependencies": {
1435
-
"es-errors": "^1.3.0",
1436
-
"function-bind": "^1.1.2"
1437
-
},
1438
-
"engines": {
1439
-
"node": ">= 0.4"
1440
-
}
1441
-
},
1442
-
"node_modules/call-bound": {
1443
-
"version": "1.0.4",
1444
-
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
1445
-
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
1446
-
"dev": true,
1447
-
"license": "MIT",
1448
-
"dependencies": {
1449
-
"call-bind-apply-helpers": "^1.0.2",
1450
-
"get-intrinsic": "^1.3.0"
1451
-
},
1452
-
"engines": {
1453
-
"node": ">= 0.4"
1454
-
},
1455
-
"funding": {
1456
-
"url": "https://github.com/sponsors/ljharb"
1457
-
}
1458
-
},
1459
-
"node_modules/callsites": {
1460
-
"version": "3.1.0",
1461
-
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
1462
-
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
1463
-
"dev": true,
1464
-
"license": "MIT",
1465
-
"engines": {
1466
-
"node": ">=6"
1467
-
}
1468
-
},
1469
-
"node_modules/chalk": {
1470
-
"version": "4.1.2",
1471
-
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1472
-
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1473
-
"dev": true,
1474
-
"license": "MIT",
1475
-
"dependencies": {
1476
-
"ansi-styles": "^4.1.0",
1477
-
"supports-color": "^7.1.0"
1478
-
},
1479
-
"engines": {
1480
-
"node": ">=10"
1481
-
},
1482
-
"funding": {
1483
-
"url": "https://github.com/chalk/chalk?sponsor=1"
1484
-
}
1485
-
},
1486
-
"node_modules/color-convert": {
1487
-
"version": "2.0.1",
1488
-
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1489
-
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1490
-
"dev": true,
1491
-
"license": "MIT",
1492
-
"dependencies": {
1493
-
"color-name": "~1.1.4"
1494
-
},
1495
-
"engines": {
1496
-
"node": ">=7.0.0"
1497
-
}
1498
-
},
1499
-
"node_modules/color-name": {
1500
-
"version": "1.1.4",
1501
-
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1502
-
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1503
-
"dev": true,
1504
-
"license": "MIT"
1505
-
},
1506
-
"node_modules/concat-map": {
1507
-
"version": "0.0.1",
1508
-
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1509
-
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
1510
-
"dev": true,
1511
-
"license": "MIT"
1512
-
},
1513
-
"node_modules/cross-spawn": {
1514
-
"version": "7.0.6",
1515
-
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
1516
-
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
1517
-
"dev": true,
1518
-
"license": "MIT",
1519
-
"dependencies": {
1520
-
"path-key": "^3.1.0",
1521
-
"shebang-command": "^2.0.0",
1522
-
"which": "^2.0.1"
1523
-
},
1524
-
"engines": {
1525
-
"node": ">= 8"
1526
-
}
1527
-
},
1528
-
"node_modules/data-view-buffer": {
1529
-
"version": "1.0.2",
1530
-
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
1531
-
"integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
1532
-
"dev": true,
1533
-
"license": "MIT",
1534
-
"dependencies": {
1535
-
"call-bound": "^1.0.3",
1536
-
"es-errors": "^1.3.0",
1537
-
"is-data-view": "^1.0.2"
1538
-
},
1539
-
"engines": {
1540
-
"node": ">= 0.4"
1541
-
},
1542
-
"funding": {
1543
-
"url": "https://github.com/sponsors/ljharb"
1544
-
}
1545
-
},
1546
-
"node_modules/data-view-byte-length": {
1547
-
"version": "1.0.2",
1548
-
"resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
1549
-
"integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
1550
-
"dev": true,
1551
-
"license": "MIT",
1552
-
"dependencies": {
1553
-
"call-bound": "^1.0.3",
1554
-
"es-errors": "^1.3.0",
1555
-
"is-data-view": "^1.0.2"
1556
-
},
1557
-
"engines": {
1558
-
"node": ">= 0.4"
1559
-
},
1560
-
"funding": {
1561
-
"url": "https://github.com/sponsors/inspect-js"
1562
-
}
1563
-
},
1564
-
"node_modules/data-view-byte-offset": {
1565
-
"version": "1.0.1",
1566
-
"resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
1567
-
"integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
1568
-
"dev": true,
1569
-
"license": "MIT",
1570
-
"dependencies": {
1571
-
"call-bound": "^1.0.2",
1572
-
"es-errors": "^1.3.0",
1573
-
"is-data-view": "^1.0.1"
1574
-
},
1575
-
"engines": {
1576
-
"node": ">= 0.4"
1577
-
},
1578
-
"funding": {
1579
-
"url": "https://github.com/sponsors/ljharb"
1580
-
}
1581
-
},
1582
-
"node_modules/debug": {
1583
-
"version": "4.4.3",
1584
-
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
1585
-
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
1586
-
"dev": true,
1587
-
"license": "MIT",
1588
-
"dependencies": {
1589
-
"ms": "^2.1.3"
1590
-
},
1591
-
"engines": {
1592
-
"node": ">=6.0"
1593
-
},
1594
-
"peerDependenciesMeta": {
1595
-
"supports-color": {
1596
-
"optional": true
1597
-
}
1598
-
}
1599
-
},
1600
-
"node_modules/deep-is": {
1601
-
"version": "0.1.4",
1602
-
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
1603
-
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
1604
-
"dev": true,
1605
-
"license": "MIT"
1606
-
},
1607
-
"node_modules/define-data-property": {
1608
-
"version": "1.1.4",
1609
-
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
1610
-
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
1611
-
"dev": true,
1612
-
"license": "MIT",
1613
-
"dependencies": {
1614
-
"es-define-property": "^1.0.0",
1615
-
"es-errors": "^1.3.0",
1616
-
"gopd": "^1.0.1"
1617
-
},
1618
-
"engines": {
1619
-
"node": ">= 0.4"
1620
-
},
1621
-
"funding": {
1622
-
"url": "https://github.com/sponsors/ljharb"
1623
-
}
1624
-
},
1625
-
"node_modules/define-properties": {
1626
-
"version": "1.2.1",
1627
-
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
1628
-
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
1629
-
"dev": true,
1630
-
"license": "MIT",
1631
-
"dependencies": {
1632
-
"define-data-property": "^1.0.1",
1633
-
"has-property-descriptors": "^1.0.0",
1634
-
"object-keys": "^1.1.1"
1635
-
},
1636
-
"engines": {
1637
-
"node": ">= 0.4"
1638
-
},
1639
-
"funding": {
1640
-
"url": "https://github.com/sponsors/ljharb"
1641
-
}
1642
-
},
1643
-
"node_modules/doctrine": {
1644
-
"version": "2.1.0",
1645
-
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
1646
-
"integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
1647
-
"dev": true,
1648
-
"license": "Apache-2.0",
1649
-
"dependencies": {
1650
-
"esutils": "^2.0.2"
1651
-
},
1652
-
"engines": {
1653
-
"node": ">=0.10.0"
1654
-
}
1655
-
},
1656
-
"node_modules/dunder-proto": {
1657
-
"version": "1.0.1",
1658
-
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
1659
-
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
1660
-
"dev": true,
1661
-
"license": "MIT",
1662
-
"dependencies": {
1663
-
"call-bind-apply-helpers": "^1.0.1",
1664
-
"es-errors": "^1.3.0",
1665
-
"gopd": "^1.2.0"
1666
-
},
1667
-
"engines": {
1668
-
"node": ">= 0.4"
1669
-
}
1670
-
},
1671
-
"node_modules/es-abstract": {
1672
-
"version": "1.24.0",
1673
-
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz",
1674
-
"integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==",
1675
-
"dev": true,
1676
-
"license": "MIT",
1677
-
"dependencies": {
1678
-
"array-buffer-byte-length": "^1.0.2",
1679
-
"arraybuffer.prototype.slice": "^1.0.4",
1680
-
"available-typed-arrays": "^1.0.7",
1681
-
"call-bind": "^1.0.8",
1682
-
"call-bound": "^1.0.4",
1683
-
"data-view-buffer": "^1.0.2",
1684
-
"data-view-byte-length": "^1.0.2",
1685
-
"data-view-byte-offset": "^1.0.1",
1686
-
"es-define-property": "^1.0.1",
1687
-
"es-errors": "^1.3.0",
1688
-
"es-object-atoms": "^1.1.1",
1689
-
"es-set-tostringtag": "^2.1.0",
1690
-
"es-to-primitive": "^1.3.0",
1691
-
"function.prototype.name": "^1.1.8",
1692
-
"get-intrinsic": "^1.3.0",
1693
-
"get-proto": "^1.0.1",
1694
-
"get-symbol-description": "^1.1.0",
1695
-
"globalthis": "^1.0.4",
1696
-
"gopd": "^1.2.0",
1697
-
"has-property-descriptors": "^1.0.2",
1698
-
"has-proto": "^1.2.0",
1699
-
"has-symbols": "^1.1.0",
1700
-
"hasown": "^2.0.2",
1701
-
"internal-slot": "^1.1.0",
1702
-
"is-array-buffer": "^3.0.5",
1703
-
"is-callable": "^1.2.7",
1704
-
"is-data-view": "^1.0.2",
1705
-
"is-negative-zero": "^2.0.3",
1706
-
"is-regex": "^1.2.1",
1707
-
"is-set": "^2.0.3",
1708
-
"is-shared-array-buffer": "^1.0.4",
1709
-
"is-string": "^1.1.1",
1710
-
"is-typed-array": "^1.1.15",
1711
-
"is-weakref": "^1.1.1",
1712
-
"math-intrinsics": "^1.1.0",
1713
-
"object-inspect": "^1.13.4",
1714
-
"object-keys": "^1.1.1",
1715
-
"object.assign": "^4.1.7",
1716
-
"own-keys": "^1.0.1",
1717
-
"regexp.prototype.flags": "^1.5.4",
1718
-
"safe-array-concat": "^1.1.3",
1719
-
"safe-push-apply": "^1.0.0",
1720
-
"safe-regex-test": "^1.1.0",
1721
-
"set-proto": "^1.0.0",
1722
-
"stop-iteration-iterator": "^1.1.0",
1723
-
"string.prototype.trim": "^1.2.10",
1724
-
"string.prototype.trimend": "^1.0.9",
1725
-
"string.prototype.trimstart": "^1.0.8",
1726
-
"typed-array-buffer": "^1.0.3",
1727
-
"typed-array-byte-length": "^1.0.3",
1728
-
"typed-array-byte-offset": "^1.0.4",
1729
-
"typed-array-length": "^1.0.7",
1730
-
"unbox-primitive": "^1.1.0",
1731
-
"which-typed-array": "^1.1.19"
1732
-
},
1733
-
"engines": {
1734
-
"node": ">= 0.4"
1735
-
},
1736
-
"funding": {
1737
-
"url": "https://github.com/sponsors/ljharb"
1738
-
}
1739
-
},
1740
-
"node_modules/es-define-property": {
1741
-
"version": "1.0.1",
1742
-
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
1743
-
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
1744
-
"dev": true,
1745
-
"license": "MIT",
1746
-
"engines": {
1747
-
"node": ">= 0.4"
1748
-
}
1749
-
},
1750
-
"node_modules/es-errors": {
1751
-
"version": "1.3.0",
1752
-
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
1753
-
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
1754
-
"dev": true,
1755
-
"license": "MIT",
1756
-
"engines": {
1757
-
"node": ">= 0.4"
1758
-
}
1759
-
},
1760
-
"node_modules/es-object-atoms": {
1761
-
"version": "1.1.1",
1762
-
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
1763
-
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
1764
-
"dev": true,
1765
-
"license": "MIT",
1766
-
"dependencies": {
1767
-
"es-errors": "^1.3.0"
1768
-
},
1769
-
"engines": {
1770
-
"node": ">= 0.4"
1771
-
}
1772
-
},
1773
-
"node_modules/es-set-tostringtag": {
1774
-
"version": "2.1.0",
1775
-
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
1776
-
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
1777
-
"dev": true,
1778
-
"license": "MIT",
1779
-
"dependencies": {
1780
-
"es-errors": "^1.3.0",
1781
-
"get-intrinsic": "^1.2.6",
1782
-
"has-tostringtag": "^1.0.2",
1783
-
"hasown": "^2.0.2"
1784
-
},
1785
-
"engines": {
1786
-
"node": ">= 0.4"
1787
-
}
1788
-
},
1789
-
"node_modules/es-shim-unscopables": {
1790
-
"version": "1.1.0",
1791
-
"resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
1792
-
"integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
1793
-
"dev": true,
1794
-
"license": "MIT",
1795
-
"dependencies": {
1796
-
"hasown": "^2.0.2"
1797
-
},
1798
-
"engines": {
1799
-
"node": ">= 0.4"
1800
-
}
1801
-
},
1802
-
"node_modules/es-to-primitive": {
1803
-
"version": "1.3.0",
1804
-
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
1805
-
"integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
1806
-
"dev": true,
1807
-
"license": "MIT",
1808
-
"dependencies": {
1809
-
"is-callable": "^1.2.7",
1810
-
"is-date-object": "^1.0.5",
1811
-
"is-symbol": "^1.0.4"
1812
-
},
1813
-
"engines": {
1814
-
"node": ">= 0.4"
1815
-
},
1816
-
"funding": {
1817
-
"url": "https://github.com/sponsors/ljharb"
1818
-
}
1819
-
},
1820
-
"node_modules/esbuild": {
1821
-
"version": "0.25.11",
1822
-
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.11.tgz",
1823
-
"integrity": "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==",
1824
-
"hasInstallScript": true,
1825
-
"license": "MIT",
1826
-
"bin": {
1827
-
"esbuild": "bin/esbuild"
1828
-
},
1829
-
"engines": {
1830
-
"node": ">=18"
1831
-
},
1832
-
"optionalDependencies": {
1833
-
"@esbuild/aix-ppc64": "0.25.11",
1834
-
"@esbuild/android-arm": "0.25.11",
1835
-
"@esbuild/android-arm64": "0.25.11",
1836
-
"@esbuild/android-x64": "0.25.11",
1837
-
"@esbuild/darwin-arm64": "0.25.11",
1838
-
"@esbuild/darwin-x64": "0.25.11",
1839
-
"@esbuild/freebsd-arm64": "0.25.11",
1840
-
"@esbuild/freebsd-x64": "0.25.11",
1841
-
"@esbuild/linux-arm": "0.25.11",
1842
-
"@esbuild/linux-arm64": "0.25.11",
1843
-
"@esbuild/linux-ia32": "0.25.11",
1844
-
"@esbuild/linux-loong64": "0.25.11",
1845
-
"@esbuild/linux-mips64el": "0.25.11",
1846
-
"@esbuild/linux-ppc64": "0.25.11",
1847
-
"@esbuild/linux-riscv64": "0.25.11",
1848
-
"@esbuild/linux-s390x": "0.25.11",
1849
-
"@esbuild/linux-x64": "0.25.11",
1850
-
"@esbuild/netbsd-arm64": "0.25.11",
1851
-
"@esbuild/netbsd-x64": "0.25.11",
1852
-
"@esbuild/openbsd-arm64": "0.25.11",
1853
-
"@esbuild/openbsd-x64": "0.25.11",
1854
-
"@esbuild/openharmony-arm64": "0.25.11",
1855
-
"@esbuild/sunos-x64": "0.25.11",
1856
-
"@esbuild/win32-arm64": "0.25.11",
1857
-
"@esbuild/win32-ia32": "0.25.11",
1858
-
"@esbuild/win32-x64": "0.25.11"
1859
-
}
1860
-
},
1861
-
"node_modules/escape-string-regexp": {
1862
-
"version": "4.0.0",
1863
-
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
1864
-
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
1865
-
"dev": true,
1866
-
"license": "MIT",
1867
-
"engines": {
1868
-
"node": ">=10"
1869
-
},
1870
-
"funding": {
1871
-
"url": "https://github.com/sponsors/sindresorhus"
1872
-
}
1873
-
},
1874
-
"node_modules/eslint": {
1875
-
"version": "9.38.0",
1876
-
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.38.0.tgz",
1877
-
"integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==",
1878
-
"dev": true,
1879
-
"license": "MIT",
1880
-
"dependencies": {
1881
-
"@eslint-community/eslint-utils": "^4.8.0",
1882
-
"@eslint-community/regexpp": "^4.12.1",
1883
-
"@eslint/config-array": "^0.21.1",
1884
-
"@eslint/config-helpers": "^0.4.1",
1885
-
"@eslint/core": "^0.16.0",
1886
-
"@eslint/eslintrc": "^3.3.1",
1887
-
"@eslint/js": "9.38.0",
1888
-
"@eslint/plugin-kit": "^0.4.0",
1889
-
"@humanfs/node": "^0.16.6",
1890
-
"@humanwhocodes/module-importer": "^1.0.1",
1891
-
"@humanwhocodes/retry": "^0.4.2",
1892
-
"@types/estree": "^1.0.6",
1893
-
"ajv": "^6.12.4",
1894
-
"chalk": "^4.0.0",
1895
-
"cross-spawn": "^7.0.6",
1896
-
"debug": "^4.3.2",
1897
-
"escape-string-regexp": "^4.0.0",
1898
-
"eslint-scope": "^8.4.0",
1899
-
"eslint-visitor-keys": "^4.2.1",
1900
-
"espree": "^10.4.0",
1901
-
"esquery": "^1.5.0",
1902
-
"esutils": "^2.0.2",
1903
-
"fast-deep-equal": "^3.1.3",
1904
-
"file-entry-cache": "^8.0.0",
1905
-
"find-up": "^5.0.0",
1906
-
"glob-parent": "^6.0.2",
1907
-
"ignore": "^5.2.0",
1908
-
"imurmurhash": "^0.1.4",
1909
-
"is-glob": "^4.0.0",
1910
-
"json-stable-stringify-without-jsonify": "^1.0.1",
1911
-
"lodash.merge": "^4.6.2",
1912
-
"minimatch": "^3.1.2",
1913
-
"natural-compare": "^1.4.0",
1914
-
"optionator": "^0.9.3"
1915
-
},
1916
-
"bin": {
1917
-
"eslint": "bin/eslint.js"
1918
-
},
1919
-
"engines": {
1920
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
1921
-
},
1922
-
"funding": {
1923
-
"url": "https://eslint.org/donate"
1924
-
},
1925
-
"peerDependencies": {
1926
-
"jiti": "*"
1927
-
},
1928
-
"peerDependenciesMeta": {
1929
-
"jiti": {
1930
-
"optional": true
1931
-
}
1932
-
}
1933
-
},
1934
-
"node_modules/eslint-import-resolver-node": {
1935
-
"version": "0.3.9",
1936
-
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
1937
-
"integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
1938
-
"dev": true,
1939
-
"license": "MIT",
1940
-
"dependencies": {
1941
-
"debug": "^3.2.7",
1942
-
"is-core-module": "^2.13.0",
1943
-
"resolve": "^1.22.4"
1944
-
}
1945
-
},
1946
-
"node_modules/eslint-import-resolver-node/node_modules/debug": {
1947
-
"version": "3.2.7",
1948
-
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
1949
-
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
1950
-
"dev": true,
1951
-
"license": "MIT",
1952
-
"dependencies": {
1953
-
"ms": "^2.1.1"
1954
-
}
1955
-
},
1956
-
"node_modules/eslint-module-utils": {
1957
-
"version": "2.12.1",
1958
-
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz",
1959
-
"integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==",
1960
-
"dev": true,
1961
-
"license": "MIT",
1962
-
"dependencies": {
1963
-
"debug": "^3.2.7"
1964
-
},
1965
-
"engines": {
1966
-
"node": ">=4"
1967
-
},
1968
-
"peerDependenciesMeta": {
1969
-
"eslint": {
1970
-
"optional": true
1971
-
}
1972
-
}
1973
-
},
1974
-
"node_modules/eslint-module-utils/node_modules/debug": {
1975
-
"version": "3.2.7",
1976
-
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
1977
-
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
1978
-
"dev": true,
1979
-
"license": "MIT",
1980
-
"dependencies": {
1981
-
"ms": "^2.1.1"
1982
-
}
1983
-
},
1984
-
"node_modules/eslint-plugin-import": {
1985
-
"version": "2.32.0",
1986
-
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz",
1987
-
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
1988
-
"dev": true,
1989
-
"license": "MIT",
1990
-
"dependencies": {
1991
-
"@rtsao/scc": "^1.1.0",
1992
-
"array-includes": "^3.1.9",
1993
-
"array.prototype.findlastindex": "^1.2.6",
1994
-
"array.prototype.flat": "^1.3.3",
1995
-
"array.prototype.flatmap": "^1.3.3",
1996
-
"debug": "^3.2.7",
1997
-
"doctrine": "^2.1.0",
1998
-
"eslint-import-resolver-node": "^0.3.9",
1999
-
"eslint-module-utils": "^2.12.1",
2000
-
"hasown": "^2.0.2",
2001
-
"is-core-module": "^2.16.1",
2002
-
"is-glob": "^4.0.3",
2003
-
"minimatch": "^3.1.2",
2004
-
"object.fromentries": "^2.0.8",
2005
-
"object.groupby": "^1.0.3",
2006
-
"object.values": "^1.2.1",
2007
-
"semver": "^6.3.1",
2008
-
"string.prototype.trimend": "^1.0.9",
2009
-
"tsconfig-paths": "^3.15.0"
2010
-
},
2011
-
"engines": {
2012
-
"node": ">=4"
2013
-
},
2014
-
"peerDependencies": {
2015
-
"eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
2016
-
}
2017
-
},
2018
-
"node_modules/eslint-plugin-import/node_modules/debug": {
2019
-
"version": "3.2.7",
2020
-
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
2021
-
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
2022
-
"dev": true,
2023
-
"license": "MIT",
2024
-
"dependencies": {
2025
-
"ms": "^2.1.1"
2026
-
}
2027
-
},
2028
-
"node_modules/eslint-scope": {
2029
-
"version": "8.4.0",
2030
-
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
2031
-
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
2032
-
"dev": true,
2033
-
"license": "BSD-2-Clause",
2034
-
"dependencies": {
2035
-
"esrecurse": "^4.3.0",
2036
-
"estraverse": "^5.2.0"
2037
-
},
2038
-
"engines": {
2039
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2040
-
},
2041
-
"funding": {
2042
-
"url": "https://opencollective.com/eslint"
2043
-
}
2044
-
},
2045
-
"node_modules/eslint-visitor-keys": {
2046
-
"version": "4.2.1",
2047
-
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
2048
-
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
2049
-
"dev": true,
2050
-
"license": "Apache-2.0",
2051
-
"engines": {
2052
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2053
-
},
2054
-
"funding": {
2055
-
"url": "https://opencollective.com/eslint"
2056
-
}
2057
-
},
2058
-
"node_modules/esm-env": {
2059
-
"version": "1.2.2",
2060
-
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
2061
-
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
2062
-
"license": "MIT"
2063
-
},
2064
-
"node_modules/espree": {
2065
-
"version": "10.4.0",
2066
-
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
2067
-
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
2068
-
"dev": true,
2069
-
"license": "BSD-2-Clause",
2070
-
"dependencies": {
2071
-
"acorn": "^8.15.0",
2072
-
"acorn-jsx": "^5.3.2",
2073
-
"eslint-visitor-keys": "^4.2.1"
2074
-
},
2075
-
"engines": {
2076
-
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
2077
-
},
2078
-
"funding": {
2079
-
"url": "https://opencollective.com/eslint"
2080
-
}
2081
-
},
2082
-
"node_modules/esquery": {
2083
-
"version": "1.6.0",
2084
-
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
2085
-
"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
2086
-
"dev": true,
2087
-
"license": "BSD-3-Clause",
2088
-
"dependencies": {
2089
-
"estraverse": "^5.1.0"
2090
-
},
2091
-
"engines": {
2092
-
"node": ">=0.10"
2093
-
}
2094
-
},
2095
-
"node_modules/esrecurse": {
2096
-
"version": "4.3.0",
2097
-
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
2098
-
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
2099
-
"dev": true,
2100
-
"license": "BSD-2-Clause",
2101
-
"dependencies": {
2102
-
"estraverse": "^5.2.0"
2103
-
},
2104
-
"engines": {
2105
-
"node": ">=4.0"
2106
-
}
2107
-
},
2108
-
"node_modules/estraverse": {
2109
-
"version": "5.3.0",
2110
-
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
2111
-
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
2112
-
"dev": true,
2113
-
"license": "BSD-2-Clause",
2114
-
"engines": {
2115
-
"node": ">=4.0"
2116
-
}
2117
-
},
2118
-
"node_modules/esutils": {
2119
-
"version": "2.0.3",
2120
-
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
2121
-
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
2122
-
"dev": true,
2123
-
"license": "BSD-2-Clause",
2124
-
"engines": {
2125
-
"node": ">=0.10.0"
2126
-
}
2127
-
},
2128
-
"node_modules/fast-deep-equal": {
2129
-
"version": "3.1.3",
2130
-
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
2131
-
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
2132
-
"dev": true,
2133
-
"license": "MIT"
2134
-
},
2135
-
"node_modules/fast-json-stable-stringify": {
2136
-
"version": "2.1.0",
2137
-
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
2138
-
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
2139
-
"dev": true,
2140
-
"license": "MIT"
2141
-
},
2142
-
"node_modules/fast-levenshtein": {
2143
-
"version": "2.0.6",
2144
-
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
2145
-
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
2146
-
"dev": true,
2147
-
"license": "MIT"
2148
-
},
2149
-
"node_modules/fdir": {
2150
-
"version": "6.5.0",
2151
-
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
2152
-
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
2153
-
"license": "MIT",
2154
-
"engines": {
2155
-
"node": ">=12.0.0"
2156
-
},
2157
-
"peerDependencies": {
2158
-
"picomatch": "^3 || ^4"
2159
-
},
2160
-
"peerDependenciesMeta": {
2161
-
"picomatch": {
2162
-
"optional": true
2163
-
}
2164
-
}
2165
-
},
2166
-
"node_modules/file-entry-cache": {
2167
-
"version": "8.0.0",
2168
-
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
2169
-
"integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
2170
-
"dev": true,
2171
-
"license": "MIT",
2172
-
"dependencies": {
2173
-
"flat-cache": "^4.0.0"
2174
-
},
2175
-
"engines": {
2176
-
"node": ">=16.0.0"
2177
-
}
2178
-
},
2179
-
"node_modules/find-up": {
2180
-
"version": "5.0.0",
2181
-
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
2182
-
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
2183
-
"dev": true,
2184
-
"license": "MIT",
2185
-
"dependencies": {
2186
-
"locate-path": "^6.0.0",
2187
-
"path-exists": "^4.0.0"
2188
-
},
2189
-
"engines": {
2190
-
"node": ">=10"
2191
-
},
2192
-
"funding": {
2193
-
"url": "https://github.com/sponsors/sindresorhus"
2194
-
}
2195
-
},
2196
-
"node_modules/flat-cache": {
2197
-
"version": "4.0.1",
2198
-
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
2199
-
"integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
2200
-
"dev": true,
2201
-
"license": "MIT",
2202
-
"dependencies": {
2203
-
"flatted": "^3.2.9",
2204
-
"keyv": "^4.5.4"
2205
-
},
2206
-
"engines": {
2207
-
"node": ">=16"
2208
-
}
2209
-
},
2210
-
"node_modules/flatted": {
2211
-
"version": "3.3.3",
2212
-
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
2213
-
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
2214
-
"dev": true,
2215
-
"license": "ISC"
2216
-
},
2217
-
"node_modules/for-each": {
2218
-
"version": "0.3.5",
2219
-
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
2220
-
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
2221
-
"dev": true,
2222
-
"license": "MIT",
2223
-
"dependencies": {
2224
-
"is-callable": "^1.2.7"
2225
-
},
2226
-
"engines": {
2227
-
"node": ">= 0.4"
2228
-
},
2229
-
"funding": {
2230
-
"url": "https://github.com/sponsors/ljharb"
2231
-
}
2232
-
},
2233
-
"node_modules/fsevents": {
2234
-
"version": "2.3.3",
2235
-
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
2236
-
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
2237
-
"hasInstallScript": true,
2238
-
"license": "MIT",
2239
-
"optional": true,
2240
-
"os": [
2241
-
"darwin"
2242
-
],
2243
-
"engines": {
2244
-
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
2245
-
}
2246
-
},
2247
-
"node_modules/function-bind": {
2248
-
"version": "1.1.2",
2249
-
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
2250
-
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
2251
-
"dev": true,
2252
-
"license": "MIT",
2253
-
"funding": {
2254
-
"url": "https://github.com/sponsors/ljharb"
2255
-
}
2256
-
},
2257
-
"node_modules/function.prototype.name": {
2258
-
"version": "1.1.8",
2259
-
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
2260
-
"integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
2261
-
"dev": true,
2262
-
"license": "MIT",
2263
-
"dependencies": {
2264
-
"call-bind": "^1.0.8",
2265
-
"call-bound": "^1.0.3",
2266
-
"define-properties": "^1.2.1",
2267
-
"functions-have-names": "^1.2.3",
2268
-
"hasown": "^2.0.2",
2269
-
"is-callable": "^1.2.7"
2270
-
},
2271
-
"engines": {
2272
-
"node": ">= 0.4"
2273
-
},
2274
-
"funding": {
2275
-
"url": "https://github.com/sponsors/ljharb"
2276
-
}
2277
-
},
2278
-
"node_modules/functions-have-names": {
2279
-
"version": "1.2.3",
2280
-
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
2281
-
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
2282
-
"dev": true,
2283
-
"license": "MIT",
2284
-
"funding": {
2285
-
"url": "https://github.com/sponsors/ljharb"
2286
-
}
2287
-
},
2288
-
"node_modules/generator-function": {
2289
-
"version": "2.0.1",
2290
-
"resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
2291
-
"integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
2292
-
"dev": true,
2293
-
"license": "MIT",
2294
-
"engines": {
2295
-
"node": ">= 0.4"
2296
-
}
2297
-
},
2298
-
"node_modules/get-intrinsic": {
2299
-
"version": "1.3.0",
2300
-
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
2301
-
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
2302
-
"dev": true,
2303
-
"license": "MIT",
2304
-
"dependencies": {
2305
-
"call-bind-apply-helpers": "^1.0.2",
2306
-
"es-define-property": "^1.0.1",
2307
-
"es-errors": "^1.3.0",
2308
-
"es-object-atoms": "^1.1.1",
2309
-
"function-bind": "^1.1.2",
2310
-
"get-proto": "^1.0.1",
2311
-
"gopd": "^1.2.0",
2312
-
"has-symbols": "^1.1.0",
2313
-
"hasown": "^2.0.2",
2314
-
"math-intrinsics": "^1.1.0"
2315
-
},
2316
-
"engines": {
2317
-
"node": ">= 0.4"
2318
-
},
2319
-
"funding": {
2320
-
"url": "https://github.com/sponsors/ljharb"
2321
-
}
2322
-
},
2323
-
"node_modules/get-proto": {
2324
-
"version": "1.0.1",
2325
-
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
2326
-
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
2327
-
"dev": true,
2328
-
"license": "MIT",
2329
-
"dependencies": {
2330
-
"dunder-proto": "^1.0.1",
2331
-
"es-object-atoms": "^1.0.0"
2332
-
},
2333
-
"engines": {
2334
-
"node": ">= 0.4"
2335
-
}
2336
-
},
2337
-
"node_modules/get-symbol-description": {
2338
-
"version": "1.1.0",
2339
-
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
2340
-
"integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
2341
-
"dev": true,
2342
-
"license": "MIT",
2343
-
"dependencies": {
2344
-
"call-bound": "^1.0.3",
2345
-
"es-errors": "^1.3.0",
2346
-
"get-intrinsic": "^1.2.6"
2347
-
},
2348
-
"engines": {
2349
-
"node": ">= 0.4"
2350
-
},
2351
-
"funding": {
2352
-
"url": "https://github.com/sponsors/ljharb"
2353
-
}
2354
-
},
2355
-
"node_modules/glob-parent": {
2356
-
"version": "6.0.2",
2357
-
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
2358
-
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
2359
-
"dev": true,
2360
-
"license": "ISC",
2361
-
"dependencies": {
2362
-
"is-glob": "^4.0.3"
2363
-
},
2364
-
"engines": {
2365
-
"node": ">=10.13.0"
2366
-
}
2367
-
},
2368
-
"node_modules/globals": {
2369
-
"version": "14.0.0",
2370
-
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
2371
-
"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
2372
-
"dev": true,
2373
-
"license": "MIT",
2374
-
"engines": {
2375
-
"node": ">=18"
2376
-
},
2377
-
"funding": {
2378
-
"url": "https://github.com/sponsors/sindresorhus"
2379
-
}
2380
-
},
2381
-
"node_modules/globalthis": {
2382
-
"version": "1.0.4",
2383
-
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
2384
-
"integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
2385
-
"dev": true,
2386
-
"license": "MIT",
2387
-
"dependencies": {
2388
-
"define-properties": "^1.2.1",
2389
-
"gopd": "^1.0.1"
2390
-
},
2391
-
"engines": {
2392
-
"node": ">= 0.4"
2393
-
},
2394
-
"funding": {
2395
-
"url": "https://github.com/sponsors/ljharb"
2396
-
}
2397
-
},
2398
-
"node_modules/gopd": {
2399
-
"version": "1.2.0",
2400
-
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
2401
-
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
2402
-
"dev": true,
2403
-
"license": "MIT",
2404
-
"engines": {
2405
-
"node": ">= 0.4"
2406
-
},
2407
-
"funding": {
2408
-
"url": "https://github.com/sponsors/ljharb"
2409
-
}
2410
-
},
2411
-
"node_modules/graphemer": {
2412
-
"version": "1.4.0",
2413
-
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
2414
-
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
2415
-
"license": "MIT"
2416
-
},
2417
-
"node_modules/has-bigints": {
2418
-
"version": "1.1.0",
2419
-
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
2420
-
"integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
2421
-
"dev": true,
2422
-
"license": "MIT",
2423
-
"engines": {
2424
-
"node": ">= 0.4"
2425
-
},
2426
-
"funding": {
2427
-
"url": "https://github.com/sponsors/ljharb"
2428
-
}
2429
-
},
2430
-
"node_modules/has-flag": {
2431
-
"version": "4.0.0",
2432
-
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
2433
-
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
2434
-
"dev": true,
2435
-
"license": "MIT",
2436
-
"engines": {
2437
-
"node": ">=8"
2438
-
}
2439
-
},
2440
-
"node_modules/has-property-descriptors": {
2441
-
"version": "1.0.2",
2442
-
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
2443
-
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
2444
-
"dev": true,
2445
-
"license": "MIT",
2446
-
"dependencies": {
2447
-
"es-define-property": "^1.0.0"
2448
-
},
2449
-
"funding": {
2450
-
"url": "https://github.com/sponsors/ljharb"
2451
-
}
2452
-
},
2453
-
"node_modules/has-proto": {
2454
-
"version": "1.2.0",
2455
-
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
2456
-
"integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
2457
-
"dev": true,
2458
-
"license": "MIT",
2459
-
"dependencies": {
2460
-
"dunder-proto": "^1.0.0"
2461
-
},
2462
-
"engines": {
2463
-
"node": ">= 0.4"
2464
-
},
2465
-
"funding": {
2466
-
"url": "https://github.com/sponsors/ljharb"
2467
-
}
2468
-
},
2469
-
"node_modules/has-symbols": {
2470
-
"version": "1.1.0",
2471
-
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
2472
-
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
2473
-
"dev": true,
2474
-
"license": "MIT",
2475
-
"engines": {
2476
-
"node": ">= 0.4"
2477
-
},
2478
-
"funding": {
2479
-
"url": "https://github.com/sponsors/ljharb"
2480
-
}
2481
-
},
2482
-
"node_modules/has-tostringtag": {
2483
-
"version": "1.0.2",
2484
-
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
2485
-
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
2486
-
"dev": true,
2487
-
"license": "MIT",
2488
-
"dependencies": {
2489
-
"has-symbols": "^1.0.3"
2490
-
},
2491
-
"engines": {
2492
-
"node": ">= 0.4"
2493
-
},
2494
-
"funding": {
2495
-
"url": "https://github.com/sponsors/ljharb"
2496
-
}
2497
-
},
2498
-
"node_modules/hasown": {
2499
-
"version": "2.0.2",
2500
-
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
2501
-
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
2502
-
"dev": true,
2503
-
"license": "MIT",
2504
-
"dependencies": {
2505
-
"function-bind": "^1.1.2"
2506
-
},
2507
-
"engines": {
2508
-
"node": ">= 0.4"
2509
-
}
2510
-
},
2511
-
"node_modules/ignore": {
2512
-
"version": "5.3.2",
2513
-
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
2514
-
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
2515
-
"dev": true,
2516
-
"license": "MIT",
2517
-
"engines": {
2518
-
"node": ">= 4"
2519
-
}
2520
-
},
2521
-
"node_modules/import-fresh": {
2522
-
"version": "3.3.1",
2523
-
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
2524
-
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
2525
-
"dev": true,
2526
-
"license": "MIT",
2527
-
"dependencies": {
2528
-
"parent-module": "^1.0.0",
2529
-
"resolve-from": "^4.0.0"
2530
-
},
2531
-
"engines": {
2532
-
"node": ">=6"
2533
-
},
2534
-
"funding": {
2535
-
"url": "https://github.com/sponsors/sindresorhus"
2536
-
}
2537
-
},
2538
-
"node_modules/imurmurhash": {
2539
-
"version": "0.1.4",
2540
-
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
2541
-
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
2542
-
"dev": true,
2543
-
"license": "MIT",
2544
-
"engines": {
2545
-
"node": ">=0.8.19"
2546
-
}
2547
-
},
2548
-
"node_modules/internal-slot": {
2549
-
"version": "1.1.0",
2550
-
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
2551
-
"integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
2552
-
"dev": true,
2553
-
"license": "MIT",
2554
-
"dependencies": {
2555
-
"es-errors": "^1.3.0",
2556
-
"hasown": "^2.0.2",
2557
-
"side-channel": "^1.1.0"
2558
-
},
2559
-
"engines": {
2560
-
"node": ">= 0.4"
2561
-
}
2562
-
},
2563
-
"node_modules/is-array-buffer": {
2564
-
"version": "3.0.5",
2565
-
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
2566
-
"integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
2567
-
"dev": true,
2568
-
"license": "MIT",
2569
-
"dependencies": {
2570
-
"call-bind": "^1.0.8",
2571
-
"call-bound": "^1.0.3",
2572
-
"get-intrinsic": "^1.2.6"
2573
-
},
2574
-
"engines": {
2575
-
"node": ">= 0.4"
2576
-
},
2577
-
"funding": {
2578
-
"url": "https://github.com/sponsors/ljharb"
2579
-
}
2580
-
},
2581
-
"node_modules/is-async-function": {
2582
-
"version": "2.1.1",
2583
-
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
2584
-
"integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
2585
-
"dev": true,
2586
-
"license": "MIT",
2587
-
"dependencies": {
2588
-
"async-function": "^1.0.0",
2589
-
"call-bound": "^1.0.3",
2590
-
"get-proto": "^1.0.1",
2591
-
"has-tostringtag": "^1.0.2",
2592
-
"safe-regex-test": "^1.1.0"
2593
-
},
2594
-
"engines": {
2595
-
"node": ">= 0.4"
2596
-
},
2597
-
"funding": {
2598
-
"url": "https://github.com/sponsors/ljharb"
2599
-
}
2600
-
},
2601
-
"node_modules/is-bigint": {
2602
-
"version": "1.1.0",
2603
-
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
2604
-
"integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
2605
-
"dev": true,
2606
-
"license": "MIT",
2607
-
"dependencies": {
2608
-
"has-bigints": "^1.0.2"
2609
-
},
2610
-
"engines": {
2611
-
"node": ">= 0.4"
2612
-
},
2613
-
"funding": {
2614
-
"url": "https://github.com/sponsors/ljharb"
2615
-
}
2616
-
},
2617
-
"node_modules/is-boolean-object": {
2618
-
"version": "1.2.2",
2619
-
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
2620
-
"integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
2621
-
"dev": true,
2622
-
"license": "MIT",
2623
-
"dependencies": {
2624
-
"call-bound": "^1.0.3",
2625
-
"has-tostringtag": "^1.0.2"
2626
-
},
2627
-
"engines": {
2628
-
"node": ">= 0.4"
2629
-
},
2630
-
"funding": {
2631
-
"url": "https://github.com/sponsors/ljharb"
2632
-
}
2633
-
},
2634
-
"node_modules/is-callable": {
2635
-
"version": "1.2.7",
2636
-
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
2637
-
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
2638
-
"dev": true,
2639
-
"license": "MIT",
2640
-
"engines": {
2641
-
"node": ">= 0.4"
2642
-
},
2643
-
"funding": {
2644
-
"url": "https://github.com/sponsors/ljharb"
2645
-
}
2646
-
},
2647
-
"node_modules/is-core-module": {
2648
-
"version": "2.16.1",
2649
-
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
2650
-
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
2651
-
"dev": true,
2652
-
"license": "MIT",
2653
-
"dependencies": {
2654
-
"hasown": "^2.0.2"
2655
-
},
2656
-
"engines": {
2657
-
"node": ">= 0.4"
2658
-
},
2659
-
"funding": {
2660
-
"url": "https://github.com/sponsors/ljharb"
2661
-
}
2662
-
},
2663
-
"node_modules/is-data-view": {
2664
-
"version": "1.0.2",
2665
-
"resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
2666
-
"integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
2667
-
"dev": true,
2668
-
"license": "MIT",
2669
-
"dependencies": {
2670
-
"call-bound": "^1.0.2",
2671
-
"get-intrinsic": "^1.2.6",
2672
-
"is-typed-array": "^1.1.13"
2673
-
},
2674
-
"engines": {
2675
-
"node": ">= 0.4"
2676
-
},
2677
-
"funding": {
2678
-
"url": "https://github.com/sponsors/ljharb"
2679
-
}
2680
-
},
2681
-
"node_modules/is-date-object": {
2682
-
"version": "1.1.0",
2683
-
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
2684
-
"integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
2685
-
"dev": true,
2686
-
"license": "MIT",
2687
-
"dependencies": {
2688
-
"call-bound": "^1.0.2",
2689
-
"has-tostringtag": "^1.0.2"
2690
-
},
2691
-
"engines": {
2692
-
"node": ">= 0.4"
2693
-
},
2694
-
"funding": {
2695
-
"url": "https://github.com/sponsors/ljharb"
2696
-
}
2697
-
},
2698
-
"node_modules/is-extglob": {
2699
-
"version": "2.1.1",
2700
-
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
2701
-
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
2702
-
"dev": true,
2703
-
"license": "MIT",
2704
-
"engines": {
2705
-
"node": ">=0.10.0"
2706
-
}
2707
-
},
2708
-
"node_modules/is-finalizationregistry": {
2709
-
"version": "1.1.1",
2710
-
"resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
2711
-
"integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
2712
-
"dev": true,
2713
-
"license": "MIT",
2714
-
"dependencies": {
2715
-
"call-bound": "^1.0.3"
2716
-
},
2717
-
"engines": {
2718
-
"node": ">= 0.4"
2719
-
},
2720
-
"funding": {
2721
-
"url": "https://github.com/sponsors/ljharb"
2722
-
}
2723
-
},
2724
-
"node_modules/is-generator-function": {
2725
-
"version": "1.1.2",
2726
-
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
2727
-
"integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
2728
-
"dev": true,
2729
-
"license": "MIT",
2730
-
"dependencies": {
2731
-
"call-bound": "^1.0.4",
2732
-
"generator-function": "^2.0.0",
2733
-
"get-proto": "^1.0.1",
2734
-
"has-tostringtag": "^1.0.2",
2735
-
"safe-regex-test": "^1.1.0"
2736
-
},
2737
-
"engines": {
2738
-
"node": ">= 0.4"
2739
-
},
2740
-
"funding": {
2741
-
"url": "https://github.com/sponsors/ljharb"
2742
-
}
2743
-
},
2744
-
"node_modules/is-glob": {
2745
-
"version": "4.0.3",
2746
-
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
2747
-
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
2748
-
"dev": true,
2749
-
"license": "MIT",
2750
-
"dependencies": {
2751
-
"is-extglob": "^2.1.1"
2752
-
},
2753
-
"engines": {
2754
-
"node": ">=0.10.0"
2755
-
}
2756
-
},
2757
-
"node_modules/is-map": {
2758
-
"version": "2.0.3",
2759
-
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
2760
-
"integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
2761
-
"dev": true,
2762
-
"license": "MIT",
2763
-
"engines": {
2764
-
"node": ">= 0.4"
2765
-
},
2766
-
"funding": {
2767
-
"url": "https://github.com/sponsors/ljharb"
2768
-
}
2769
-
},
2770
-
"node_modules/is-negative-zero": {
2771
-
"version": "2.0.3",
2772
-
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
2773
-
"integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
2774
-
"dev": true,
2775
-
"license": "MIT",
2776
-
"engines": {
2777
-
"node": ">= 0.4"
2778
-
},
2779
-
"funding": {
2780
-
"url": "https://github.com/sponsors/ljharb"
2781
-
}
2782
-
},
2783
-
"node_modules/is-number-object": {
2784
-
"version": "1.1.1",
2785
-
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
2786
-
"integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
2787
-
"dev": true,
2788
-
"license": "MIT",
2789
-
"dependencies": {
2790
-
"call-bound": "^1.0.3",
2791
-
"has-tostringtag": "^1.0.2"
2792
-
},
2793
-
"engines": {
2794
-
"node": ">= 0.4"
2795
-
},
2796
-
"funding": {
2797
-
"url": "https://github.com/sponsors/ljharb"
2798
-
}
2799
-
},
2800
-
"node_modules/is-regex": {
2801
-
"version": "1.2.1",
2802
-
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
2803
-
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
2804
-
"dev": true,
2805
-
"license": "MIT",
2806
-
"dependencies": {
2807
-
"call-bound": "^1.0.2",
2808
-
"gopd": "^1.2.0",
2809
-
"has-tostringtag": "^1.0.2",
2810
-
"hasown": "^2.0.2"
2811
-
},
2812
-
"engines": {
2813
-
"node": ">= 0.4"
2814
-
},
2815
-
"funding": {
2816
-
"url": "https://github.com/sponsors/ljharb"
2817
-
}
2818
-
},
2819
-
"node_modules/is-set": {
2820
-
"version": "2.0.3",
2821
-
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
2822
-
"integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
2823
-
"dev": true,
2824
-
"license": "MIT",
2825
-
"engines": {
2826
-
"node": ">= 0.4"
2827
-
},
2828
-
"funding": {
2829
-
"url": "https://github.com/sponsors/ljharb"
2830
-
}
2831
-
},
2832
-
"node_modules/is-shared-array-buffer": {
2833
-
"version": "1.0.4",
2834
-
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
2835
-
"integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
2836
-
"dev": true,
2837
-
"license": "MIT",
2838
-
"dependencies": {
2839
-
"call-bound": "^1.0.3"
2840
-
},
2841
-
"engines": {
2842
-
"node": ">= 0.4"
2843
-
},
2844
-
"funding": {
2845
-
"url": "https://github.com/sponsors/ljharb"
2846
-
}
2847
-
},
2848
-
"node_modules/is-string": {
2849
-
"version": "1.1.1",
2850
-
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
2851
-
"integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
2852
-
"dev": true,
2853
-
"license": "MIT",
2854
-
"dependencies": {
2855
-
"call-bound": "^1.0.3",
2856
-
"has-tostringtag": "^1.0.2"
2857
-
},
2858
-
"engines": {
2859
-
"node": ">= 0.4"
2860
-
},
2861
-
"funding": {
2862
-
"url": "https://github.com/sponsors/ljharb"
2863
-
}
2864
-
},
2865
-
"node_modules/is-symbol": {
2866
-
"version": "1.1.1",
2867
-
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
2868
-
"integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
2869
-
"dev": true,
2870
-
"license": "MIT",
2871
-
"dependencies": {
2872
-
"call-bound": "^1.0.2",
2873
-
"has-symbols": "^1.1.0",
2874
-
"safe-regex-test": "^1.1.0"
2875
-
},
2876
-
"engines": {
2877
-
"node": ">= 0.4"
2878
-
},
2879
-
"funding": {
2880
-
"url": "https://github.com/sponsors/ljharb"
2881
-
}
2882
-
},
2883
-
"node_modules/is-typed-array": {
2884
-
"version": "1.1.15",
2885
-
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
2886
-
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
2887
-
"dev": true,
2888
-
"license": "MIT",
2889
-
"dependencies": {
2890
-
"which-typed-array": "^1.1.16"
2891
-
},
2892
-
"engines": {
2893
-
"node": ">= 0.4"
2894
-
},
2895
-
"funding": {
2896
-
"url": "https://github.com/sponsors/ljharb"
2897
-
}
2898
-
},
2899
-
"node_modules/is-weakmap": {
2900
-
"version": "2.0.2",
2901
-
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
2902
-
"integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
2903
-
"dev": true,
2904
-
"license": "MIT",
2905
-
"engines": {
2906
-
"node": ">= 0.4"
2907
-
},
2908
-
"funding": {
2909
-
"url": "https://github.com/sponsors/ljharb"
2910
-
}
2911
-
},
2912
-
"node_modules/is-weakref": {
2913
-
"version": "1.1.1",
2914
-
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
2915
-
"integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
2916
-
"dev": true,
2917
-
"license": "MIT",
2918
-
"dependencies": {
2919
-
"call-bound": "^1.0.3"
2920
-
},
2921
-
"engines": {
2922
-
"node": ">= 0.4"
2923
-
},
2924
-
"funding": {
2925
-
"url": "https://github.com/sponsors/ljharb"
2926
-
}
2927
-
},
2928
-
"node_modules/is-weakset": {
2929
-
"version": "2.0.4",
2930
-
"resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
2931
-
"integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
2932
-
"dev": true,
2933
-
"license": "MIT",
2934
-
"dependencies": {
2935
-
"call-bound": "^1.0.3",
2936
-
"get-intrinsic": "^1.2.6"
2937
-
},
2938
-
"engines": {
2939
-
"node": ">= 0.4"
2940
-
},
2941
-
"funding": {
2942
-
"url": "https://github.com/sponsors/ljharb"
2943
-
}
2944
-
},
2945
-
"node_modules/isarray": {
2946
-
"version": "2.0.5",
2947
-
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
2948
-
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
2949
-
"dev": true,
2950
-
"license": "MIT"
2951
-
},
2952
-
"node_modules/isexe": {
2953
-
"version": "2.0.0",
2954
-
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
2955
-
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
2956
-
"dev": true,
2957
-
"license": "ISC"
2958
-
},
2959
-
"node_modules/iso-datestring-validator": {
2960
-
"version": "2.2.2",
2961
-
"resolved": "https://registry.npmjs.org/iso-datestring-validator/-/iso-datestring-validator-2.2.2.tgz",
2962
-
"integrity": "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==",
2963
-
"license": "MIT"
2964
-
},
2965
-
"node_modules/js-yaml": {
2966
-
"version": "4.1.0",
2967
-
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
2968
-
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
2969
-
"dev": true,
2970
-
"license": "MIT",
2971
-
"dependencies": {
2972
-
"argparse": "^2.0.1"
2973
-
},
2974
-
"bin": {
2975
-
"js-yaml": "bin/js-yaml.js"
2976
-
}
2977
-
},
2978
-
"node_modules/json-buffer": {
2979
-
"version": "3.0.1",
2980
-
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
2981
-
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
2982
-
"dev": true,
2983
-
"license": "MIT"
2984
-
},
2985
-
"node_modules/json-schema-traverse": {
2986
-
"version": "0.4.1",
2987
-
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
2988
-
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
2989
-
"dev": true,
2990
-
"license": "MIT"
2991
-
},
2992
-
"node_modules/json-stable-stringify-without-jsonify": {
2993
-
"version": "1.0.1",
2994
-
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
2995
-
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
2996
-
"dev": true,
2997
-
"license": "MIT"
2998
-
},
2999
-
"node_modules/json5": {
3000
-
"version": "1.0.2",
3001
-
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
3002
-
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
3003
-
"dev": true,
3004
-
"license": "MIT",
3005
-
"dependencies": {
3006
-
"minimist": "^1.2.0"
3007
-
},
3008
-
"bin": {
3009
-
"json5": "lib/cli.js"
3010
-
}
3011
-
},
3012
-
"node_modules/keyv": {
3013
-
"version": "4.5.4",
3014
-
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
3015
-
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
3016
-
"dev": true,
3017
-
"license": "MIT",
3018
-
"dependencies": {
3019
-
"json-buffer": "3.0.1"
3020
-
}
3021
-
},
3022
-
"node_modules/levn": {
3023
-
"version": "0.4.1",
3024
-
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
3025
-
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
3026
-
"dev": true,
3027
-
"license": "MIT",
3028
-
"dependencies": {
3029
-
"prelude-ls": "^1.2.1",
3030
-
"type-check": "~0.4.0"
3031
-
},
3032
-
"engines": {
3033
-
"node": ">= 0.8.0"
3034
-
}
3035
-
},
3036
-
"node_modules/locate-path": {
3037
-
"version": "6.0.0",
3038
-
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
3039
-
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
3040
-
"dev": true,
3041
-
"license": "MIT",
3042
-
"dependencies": {
3043
-
"p-locate": "^5.0.0"
3044
-
},
3045
-
"engines": {
3046
-
"node": ">=10"
3047
-
},
3048
-
"funding": {
3049
-
"url": "https://github.com/sponsors/sindresorhus"
3050
-
}
3051
-
},
3052
-
"node_modules/lodash.merge": {
3053
-
"version": "4.6.2",
3054
-
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
3055
-
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
3056
-
"dev": true,
3057
-
"license": "MIT"
3058
-
},
3059
-
"node_modules/math-intrinsics": {
3060
-
"version": "1.1.0",
3061
-
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
3062
-
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
3063
-
"dev": true,
3064
-
"license": "MIT",
3065
-
"engines": {
3066
-
"node": ">= 0.4"
3067
-
}
3068
-
},
3069
-
"node_modules/minimatch": {
3070
-
"version": "3.1.2",
3071
-
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
3072
-
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
3073
-
"dev": true,
3074
-
"license": "ISC",
3075
-
"dependencies": {
3076
-
"brace-expansion": "^1.1.7"
3077
-
},
3078
-
"engines": {
3079
-
"node": "*"
3080
-
}
3081
-
},
3082
-
"node_modules/minimist": {
3083
-
"version": "1.2.8",
3084
-
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
3085
-
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
3086
-
"dev": true,
3087
-
"license": "MIT",
3088
-
"funding": {
3089
-
"url": "https://github.com/sponsors/ljharb"
3090
-
}
3091
-
},
3092
-
"node_modules/ms": {
3093
-
"version": "2.1.3",
3094
-
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
3095
-
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
3096
-
"dev": true,
3097
-
"license": "MIT"
3098
-
},
3099
-
"node_modules/multiformats": {
3100
-
"version": "9.9.0",
3101
-
"resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz",
3102
-
"integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==",
3103
-
"license": "(Apache-2.0 AND MIT)"
3104
-
},
3105
-
"node_modules/nanoid": {
3106
-
"version": "3.3.11",
3107
-
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
3108
-
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
3109
-
"funding": [
3110
-
{
3111
-
"type": "github",
3112
-
"url": "https://github.com/sponsors/ai"
3113
-
}
3114
-
],
3115
-
"license": "MIT",
3116
-
"bin": {
3117
-
"nanoid": "bin/nanoid.cjs"
3118
-
},
3119
-
"engines": {
3120
-
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
3121
-
}
3122
-
},
3123
-
"node_modules/natural-compare": {
3124
-
"version": "1.4.0",
3125
-
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
3126
-
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
3127
-
"dev": true,
3128
-
"license": "MIT"
3129
-
},
3130
-
"node_modules/object-inspect": {
3131
-
"version": "1.13.4",
3132
-
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
3133
-
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
3134
-
"dev": true,
3135
-
"license": "MIT",
3136
-
"engines": {
3137
-
"node": ">= 0.4"
3138
-
},
3139
-
"funding": {
3140
-
"url": "https://github.com/sponsors/ljharb"
3141
-
}
3142
-
},
3143
-
"node_modules/object-keys": {
3144
-
"version": "1.1.1",
3145
-
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
3146
-
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
3147
-
"dev": true,
3148
-
"license": "MIT",
3149
-
"engines": {
3150
-
"node": ">= 0.4"
3151
-
}
3152
-
},
3153
-
"node_modules/object.assign": {
3154
-
"version": "4.1.7",
3155
-
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
3156
-
"integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
3157
-
"dev": true,
3158
-
"license": "MIT",
3159
-
"dependencies": {
3160
-
"call-bind": "^1.0.8",
3161
-
"call-bound": "^1.0.3",
3162
-
"define-properties": "^1.2.1",
3163
-
"es-object-atoms": "^1.0.0",
3164
-
"has-symbols": "^1.1.0",
3165
-
"object-keys": "^1.1.1"
3166
-
},
3167
-
"engines": {
3168
-
"node": ">= 0.4"
3169
-
},
3170
-
"funding": {
3171
-
"url": "https://github.com/sponsors/ljharb"
3172
-
}
3173
-
},
3174
-
"node_modules/object.fromentries": {
3175
-
"version": "2.0.8",
3176
-
"resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
3177
-
"integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
3178
-
"dev": true,
3179
-
"license": "MIT",
3180
-
"dependencies": {
3181
-
"call-bind": "^1.0.7",
3182
-
"define-properties": "^1.2.1",
3183
-
"es-abstract": "^1.23.2",
3184
-
"es-object-atoms": "^1.0.0"
3185
-
},
3186
-
"engines": {
3187
-
"node": ">= 0.4"
3188
-
},
3189
-
"funding": {
3190
-
"url": "https://github.com/sponsors/ljharb"
3191
-
}
3192
-
},
3193
-
"node_modules/object.groupby": {
3194
-
"version": "1.0.3",
3195
-
"resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
3196
-
"integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
3197
-
"dev": true,
3198
-
"license": "MIT",
3199
-
"dependencies": {
3200
-
"call-bind": "^1.0.7",
3201
-
"define-properties": "^1.2.1",
3202
-
"es-abstract": "^1.23.2"
3203
-
},
3204
-
"engines": {
3205
-
"node": ">= 0.4"
3206
-
}
3207
-
},
3208
-
"node_modules/object.values": {
3209
-
"version": "1.2.1",
3210
-
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
3211
-
"integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
3212
-
"dev": true,
3213
-
"license": "MIT",
3214
-
"dependencies": {
3215
-
"call-bind": "^1.0.8",
3216
-
"call-bound": "^1.0.3",
3217
-
"define-properties": "^1.2.1",
3218
-
"es-object-atoms": "^1.0.0"
3219
-
},
3220
-
"engines": {
3221
-
"node": ">= 0.4"
3222
-
},
3223
-
"funding": {
3224
-
"url": "https://github.com/sponsors/ljharb"
3225
-
}
3226
-
},
3227
-
"node_modules/optionator": {
3228
-
"version": "0.9.4",
3229
-
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
3230
-
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
3231
-
"dev": true,
3232
-
"license": "MIT",
3233
-
"dependencies": {
3234
-
"deep-is": "^0.1.3",
3235
-
"fast-levenshtein": "^2.0.6",
3236
-
"levn": "^0.4.1",
3237
-
"prelude-ls": "^1.2.1",
3238
-
"type-check": "^0.4.0",
3239
-
"word-wrap": "^1.2.5"
3240
-
},
3241
-
"engines": {
3242
-
"node": ">= 0.8.0"
3243
-
}
3244
-
},
3245
-
"node_modules/own-keys": {
3246
-
"version": "1.0.1",
3247
-
"resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
3248
-
"integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
3249
-
"dev": true,
3250
-
"license": "MIT",
3251
-
"dependencies": {
3252
-
"get-intrinsic": "^1.2.6",
3253
-
"object-keys": "^1.1.1",
3254
-
"safe-push-apply": "^1.0.0"
3255
-
},
3256
-
"engines": {
3257
-
"node": ">= 0.4"
3258
-
},
3259
-
"funding": {
3260
-
"url": "https://github.com/sponsors/ljharb"
3261
-
}
3262
-
},
3263
-
"node_modules/p-limit": {
3264
-
"version": "3.1.0",
3265
-
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
3266
-
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
3267
-
"dev": true,
3268
-
"license": "MIT",
3269
-
"dependencies": {
3270
-
"yocto-queue": "^0.1.0"
3271
-
},
3272
-
"engines": {
3273
-
"node": ">=10"
3274
-
},
3275
-
"funding": {
3276
-
"url": "https://github.com/sponsors/sindresorhus"
3277
-
}
3278
-
},
3279
-
"node_modules/p-locate": {
3280
-
"version": "5.0.0",
3281
-
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
3282
-
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
3283
-
"dev": true,
3284
-
"license": "MIT",
3285
-
"dependencies": {
3286
-
"p-limit": "^3.0.2"
3287
-
},
3288
-
"engines": {
3289
-
"node": ">=10"
3290
-
},
3291
-
"funding": {
3292
-
"url": "https://github.com/sponsors/sindresorhus"
3293
-
}
3294
-
},
3295
-
"node_modules/parent-module": {
3296
-
"version": "1.0.1",
3297
-
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
3298
-
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
3299
-
"dev": true,
3300
-
"license": "MIT",
3301
-
"dependencies": {
3302
-
"callsites": "^3.0.0"
3303
-
},
3304
-
"engines": {
3305
-
"node": ">=6"
3306
-
}
3307
-
},
3308
-
"node_modules/path-exists": {
3309
-
"version": "4.0.0",
3310
-
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
3311
-
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
3312
-
"dev": true,
3313
-
"license": "MIT",
3314
-
"engines": {
3315
-
"node": ">=8"
3316
-
}
3317
-
},
3318
-
"node_modules/path-key": {
3319
-
"version": "3.1.1",
3320
-
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
3321
-
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
3322
-
"dev": true,
3323
-
"license": "MIT",
3324
-
"engines": {
3325
-
"node": ">=8"
3326
-
}
3327
-
},
3328
-
"node_modules/path-parse": {
3329
-
"version": "1.0.7",
3330
-
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
3331
-
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
3332
-
"dev": true,
3333
-
"license": "MIT"
3334
-
},
3335
-
"node_modules/picocolors": {
3336
-
"version": "1.1.1",
3337
-
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
3338
-
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
3339
-
"license": "ISC"
3340
-
},
3341
-
"node_modules/picomatch": {
3342
-
"version": "4.0.3",
3343
-
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
3344
-
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
3345
-
"license": "MIT",
3346
-
"engines": {
3347
-
"node": ">=12"
3348
-
},
3349
-
"funding": {
3350
-
"url": "https://github.com/sponsors/jonschlinkert"
3351
-
}
3352
-
},
3353
-
"node_modules/possible-typed-array-names": {
3354
-
"version": "1.1.0",
3355
-
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
3356
-
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
3357
-
"dev": true,
3358
-
"license": "MIT",
3359
-
"engines": {
3360
-
"node": ">= 0.4"
3361
-
}
3362
-
},
3363
-
"node_modules/postcss": {
3364
-
"version": "8.5.6",
3365
-
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
3366
-
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
3367
-
"funding": [
3368
-
{
3369
-
"type": "opencollective",
3370
-
"url": "https://opencollective.com/postcss/"
3371
-
},
3372
-
{
3373
-
"type": "tidelift",
3374
-
"url": "https://tidelift.com/funding/github/npm/postcss"
3375
-
},
3376
-
{
3377
-
"type": "github",
3378
-
"url": "https://github.com/sponsors/ai"
3379
-
}
3380
-
],
3381
-
"license": "MIT",
3382
-
"dependencies": {
3383
-
"nanoid": "^3.3.11",
3384
-
"picocolors": "^1.1.1",
3385
-
"source-map-js": "^1.2.1"
3386
-
},
3387
-
"engines": {
3388
-
"node": "^10 || ^12 || >=14"
3389
-
}
3390
-
},
3391
-
"node_modules/prelude-ls": {
3392
-
"version": "1.2.1",
3393
-
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
3394
-
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
3395
-
"dev": true,
3396
-
"license": "MIT",
3397
-
"engines": {
3398
-
"node": ">= 0.8.0"
3399
-
}
3400
-
},
3401
-
"node_modules/punycode": {
3402
-
"version": "2.3.1",
3403
-
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
3404
-
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
3405
-
"dev": true,
3406
-
"license": "MIT",
3407
-
"engines": {
3408
-
"node": ">=6"
3409
-
}
3410
-
},
3411
-
"node_modules/reflect.getprototypeof": {
3412
-
"version": "1.0.10",
3413
-
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
3414
-
"integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
3415
-
"dev": true,
3416
-
"license": "MIT",
3417
-
"dependencies": {
3418
-
"call-bind": "^1.0.8",
3419
-
"define-properties": "^1.2.1",
3420
-
"es-abstract": "^1.23.9",
3421
-
"es-errors": "^1.3.0",
3422
-
"es-object-atoms": "^1.0.0",
3423
-
"get-intrinsic": "^1.2.7",
3424
-
"get-proto": "^1.0.1",
3425
-
"which-builtin-type": "^1.2.1"
3426
-
},
3427
-
"engines": {
3428
-
"node": ">= 0.4"
3429
-
},
3430
-
"funding": {
3431
-
"url": "https://github.com/sponsors/ljharb"
3432
-
}
3433
-
},
3434
-
"node_modules/regexp.prototype.flags": {
3435
-
"version": "1.5.4",
3436
-
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
3437
-
"integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
3438
-
"dev": true,
3439
-
"license": "MIT",
3440
-
"dependencies": {
3441
-
"call-bind": "^1.0.8",
3442
-
"define-properties": "^1.2.1",
3443
-
"es-errors": "^1.3.0",
3444
-
"get-proto": "^1.0.1",
3445
-
"gopd": "^1.2.0",
3446
-
"set-function-name": "^2.0.2"
3447
-
},
3448
-
"engines": {
3449
-
"node": ">= 0.4"
3450
-
},
3451
-
"funding": {
3452
-
"url": "https://github.com/sponsors/ljharb"
3453
-
}
3454
-
},
3455
-
"node_modules/resolve": {
3456
-
"version": "1.22.10",
3457
-
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
3458
-
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
3459
-
"dev": true,
3460
-
"license": "MIT",
3461
-
"dependencies": {
3462
-
"is-core-module": "^2.16.0",
3463
-
"path-parse": "^1.0.7",
3464
-
"supports-preserve-symlinks-flag": "^1.0.0"
3465
-
},
3466
-
"bin": {
3467
-
"resolve": "bin/resolve"
3468
-
},
3469
-
"engines": {
3470
-
"node": ">= 0.4"
3471
-
},
3472
-
"funding": {
3473
-
"url": "https://github.com/sponsors/ljharb"
3474
-
}
3475
-
},
3476
-
"node_modules/resolve-from": {
3477
-
"version": "4.0.0",
3478
-
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
3479
-
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
3480
-
"dev": true,
3481
-
"license": "MIT",
3482
-
"engines": {
3483
-
"node": ">=4"
3484
-
}
3485
-
},
3486
-
"node_modules/rollup": {
3487
-
"version": "4.52.5",
3488
-
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.5.tgz",
3489
-
"integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==",
3490
-
"license": "MIT",
3491
-
"dependencies": {
3492
-
"@types/estree": "1.0.8"
3493
-
},
3494
-
"bin": {
3495
-
"rollup": "dist/bin/rollup"
3496
-
},
3497
-
"engines": {
3498
-
"node": ">=18.0.0",
3499
-
"npm": ">=8.0.0"
3500
-
},
3501
-
"optionalDependencies": {
3502
-
"@rollup/rollup-android-arm-eabi": "4.52.5",
3503
-
"@rollup/rollup-android-arm64": "4.52.5",
3504
-
"@rollup/rollup-darwin-arm64": "4.52.5",
3505
-
"@rollup/rollup-darwin-x64": "4.52.5",
3506
-
"@rollup/rollup-freebsd-arm64": "4.52.5",
3507
-
"@rollup/rollup-freebsd-x64": "4.52.5",
3508
-
"@rollup/rollup-linux-arm-gnueabihf": "4.52.5",
3509
-
"@rollup/rollup-linux-arm-musleabihf": "4.52.5",
3510
-
"@rollup/rollup-linux-arm64-gnu": "4.52.5",
3511
-
"@rollup/rollup-linux-arm64-musl": "4.52.5",
3512
-
"@rollup/rollup-linux-loong64-gnu": "4.52.5",
3513
-
"@rollup/rollup-linux-ppc64-gnu": "4.52.5",
3514
-
"@rollup/rollup-linux-riscv64-gnu": "4.52.5",
3515
-
"@rollup/rollup-linux-riscv64-musl": "4.52.5",
3516
-
"@rollup/rollup-linux-s390x-gnu": "4.52.5",
3517
-
"@rollup/rollup-linux-x64-gnu": "4.52.5",
3518
-
"@rollup/rollup-linux-x64-musl": "4.52.5",
3519
-
"@rollup/rollup-openharmony-arm64": "4.52.5",
3520
-
"@rollup/rollup-win32-arm64-msvc": "4.52.5",
3521
-
"@rollup/rollup-win32-ia32-msvc": "4.52.5",
3522
-
"@rollup/rollup-win32-x64-gnu": "4.52.5",
3523
-
"@rollup/rollup-win32-x64-msvc": "4.52.5",
3524
-
"fsevents": "~2.3.2"
3525
-
}
3526
-
},
3527
-
"node_modules/safe-array-concat": {
3528
-
"version": "1.1.3",
3529
-
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
3530
-
"integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
3531
-
"dev": true,
3532
-
"license": "MIT",
3533
-
"dependencies": {
3534
-
"call-bind": "^1.0.8",
3535
-
"call-bound": "^1.0.2",
3536
-
"get-intrinsic": "^1.2.6",
3537
-
"has-symbols": "^1.1.0",
3538
-
"isarray": "^2.0.5"
3539
-
},
3540
-
"engines": {
3541
-
"node": ">=0.4"
3542
-
},
3543
-
"funding": {
3544
-
"url": "https://github.com/sponsors/ljharb"
3545
-
}
3546
-
},
3547
-
"node_modules/safe-push-apply": {
3548
-
"version": "1.0.0",
3549
-
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
3550
-
"integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
3551
-
"dev": true,
3552
-
"license": "MIT",
3553
-
"dependencies": {
3554
-
"es-errors": "^1.3.0",
3555
-
"isarray": "^2.0.5"
3556
-
},
3557
-
"engines": {
3558
-
"node": ">= 0.4"
3559
-
},
3560
-
"funding": {
3561
-
"url": "https://github.com/sponsors/ljharb"
3562
-
}
3563
-
},
3564
-
"node_modules/safe-regex-test": {
3565
-
"version": "1.1.0",
3566
-
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
3567
-
"integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
3568
-
"dev": true,
3569
-
"license": "MIT",
3570
-
"dependencies": {
3571
-
"call-bound": "^1.0.2",
3572
-
"es-errors": "^1.3.0",
3573
-
"is-regex": "^1.2.1"
3574
-
},
3575
-
"engines": {
3576
-
"node": ">= 0.4"
3577
-
},
3578
-
"funding": {
3579
-
"url": "https://github.com/sponsors/ljharb"
3580
-
}
3581
-
},
3582
-
"node_modules/semver": {
3583
-
"version": "6.3.1",
3584
-
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
3585
-
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
3586
-
"dev": true,
3587
-
"license": "ISC",
3588
-
"bin": {
3589
-
"semver": "bin/semver.js"
3590
-
}
3591
-
},
3592
-
"node_modules/set-function-length": {
3593
-
"version": "1.2.2",
3594
-
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
3595
-
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
3596
-
"dev": true,
3597
-
"license": "MIT",
3598
-
"dependencies": {
3599
-
"define-data-property": "^1.1.4",
3600
-
"es-errors": "^1.3.0",
3601
-
"function-bind": "^1.1.2",
3602
-
"get-intrinsic": "^1.2.4",
3603
-
"gopd": "^1.0.1",
3604
-
"has-property-descriptors": "^1.0.2"
3605
-
},
3606
-
"engines": {
3607
-
"node": ">= 0.4"
3608
-
}
3609
-
},
3610
-
"node_modules/set-function-name": {
3611
-
"version": "2.0.2",
3612
-
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
3613
-
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
3614
-
"dev": true,
3615
-
"license": "MIT",
3616
-
"dependencies": {
3617
-
"define-data-property": "^1.1.4",
3618
-
"es-errors": "^1.3.0",
3619
-
"functions-have-names": "^1.2.3",
3620
-
"has-property-descriptors": "^1.0.2"
3621
-
},
3622
-
"engines": {
3623
-
"node": ">= 0.4"
3624
-
}
3625
-
},
3626
-
"node_modules/set-proto": {
3627
-
"version": "1.0.0",
3628
-
"resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
3629
-
"integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
3630
-
"dev": true,
3631
-
"license": "MIT",
3632
-
"dependencies": {
3633
-
"dunder-proto": "^1.0.1",
3634
-
"es-errors": "^1.3.0",
3635
-
"es-object-atoms": "^1.0.0"
3636
-
},
3637
-
"engines": {
3638
-
"node": ">= 0.4"
3639
-
}
3640
-
},
3641
-
"node_modules/shebang-command": {
3642
-
"version": "2.0.0",
3643
-
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
3644
-
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
3645
-
"dev": true,
3646
-
"license": "MIT",
3647
-
"dependencies": {
3648
-
"shebang-regex": "^3.0.0"
3649
-
},
3650
-
"engines": {
3651
-
"node": ">=8"
3652
-
}
3653
-
},
3654
-
"node_modules/shebang-regex": {
3655
-
"version": "3.0.0",
3656
-
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
3657
-
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
3658
-
"dev": true,
3659
-
"license": "MIT",
3660
-
"engines": {
3661
-
"node": ">=8"
3662
-
}
3663
-
},
3664
-
"node_modules/side-channel": {
3665
-
"version": "1.1.0",
3666
-
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
3667
-
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
3668
-
"dev": true,
3669
-
"license": "MIT",
3670
-
"dependencies": {
3671
-
"es-errors": "^1.3.0",
3672
-
"object-inspect": "^1.13.3",
3673
-
"side-channel-list": "^1.0.0",
3674
-
"side-channel-map": "^1.0.1",
3675
-
"side-channel-weakmap": "^1.0.2"
3676
-
},
3677
-
"engines": {
3678
-
"node": ">= 0.4"
3679
-
},
3680
-
"funding": {
3681
-
"url": "https://github.com/sponsors/ljharb"
3682
-
}
3683
-
},
3684
-
"node_modules/side-channel-list": {
3685
-
"version": "1.0.0",
3686
-
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
3687
-
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
3688
-
"dev": true,
3689
-
"license": "MIT",
3690
-
"dependencies": {
3691
-
"es-errors": "^1.3.0",
3692
-
"object-inspect": "^1.13.3"
3693
-
},
3694
-
"engines": {
3695
-
"node": ">= 0.4"
3696
-
},
3697
-
"funding": {
3698
-
"url": "https://github.com/sponsors/ljharb"
3699
-
}
3700
-
},
3701
-
"node_modules/side-channel-map": {
3702
-
"version": "1.0.1",
3703
-
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
3704
-
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
3705
-
"dev": true,
3706
-
"license": "MIT",
3707
-
"dependencies": {
3708
-
"call-bound": "^1.0.2",
3709
-
"es-errors": "^1.3.0",
3710
-
"get-intrinsic": "^1.2.5",
3711
-
"object-inspect": "^1.13.3"
3712
-
},
3713
-
"engines": {
3714
-
"node": ">= 0.4"
3715
-
},
3716
-
"funding": {
3717
-
"url": "https://github.com/sponsors/ljharb"
3718
-
}
3719
-
},
3720
-
"node_modules/side-channel-weakmap": {
3721
-
"version": "1.0.2",
3722
-
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
3723
-
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
3724
-
"dev": true,
3725
-
"license": "MIT",
3726
-
"dependencies": {
3727
-
"call-bound": "^1.0.2",
3728
-
"es-errors": "^1.3.0",
3729
-
"get-intrinsic": "^1.2.5",
3730
-
"object-inspect": "^1.13.3",
3731
-
"side-channel-map": "^1.0.1"
3732
-
},
3733
-
"engines": {
3734
-
"node": ">= 0.4"
3735
-
},
3736
-
"funding": {
3737
-
"url": "https://github.com/sponsors/ljharb"
3738
-
}
3739
-
},
3740
-
"node_modules/source-map-js": {
3741
-
"version": "1.2.1",
3742
-
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
3743
-
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
3744
-
"license": "BSD-3-Clause",
3745
-
"engines": {
3746
-
"node": ">=0.10.0"
3747
-
}
3748
-
},
3749
-
"node_modules/stop-iteration-iterator": {
3750
-
"version": "1.1.0",
3751
-
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
3752
-
"integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
3753
-
"dev": true,
3754
-
"license": "MIT",
3755
-
"dependencies": {
3756
-
"es-errors": "^1.3.0",
3757
-
"internal-slot": "^1.1.0"
3758
-
},
3759
-
"engines": {
3760
-
"node": ">= 0.4"
3761
-
}
3762
-
},
3763
-
"node_modules/string.prototype.trim": {
3764
-
"version": "1.2.10",
3765
-
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
3766
-
"integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
3767
-
"dev": true,
3768
-
"license": "MIT",
3769
-
"dependencies": {
3770
-
"call-bind": "^1.0.8",
3771
-
"call-bound": "^1.0.2",
3772
-
"define-data-property": "^1.1.4",
3773
-
"define-properties": "^1.2.1",
3774
-
"es-abstract": "^1.23.5",
3775
-
"es-object-atoms": "^1.0.0",
3776
-
"has-property-descriptors": "^1.0.2"
3777
-
},
3778
-
"engines": {
3779
-
"node": ">= 0.4"
3780
-
},
3781
-
"funding": {
3782
-
"url": "https://github.com/sponsors/ljharb"
3783
-
}
3784
-
},
3785
-
"node_modules/string.prototype.trimend": {
3786
-
"version": "1.0.9",
3787
-
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
3788
-
"integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
3789
-
"dev": true,
3790
-
"license": "MIT",
3791
-
"dependencies": {
3792
-
"call-bind": "^1.0.8",
3793
-
"call-bound": "^1.0.2",
3794
-
"define-properties": "^1.2.1",
3795
-
"es-object-atoms": "^1.0.0"
3796
-
},
3797
-
"engines": {
3798
-
"node": ">= 0.4"
3799
-
},
3800
-
"funding": {
3801
-
"url": "https://github.com/sponsors/ljharb"
3802
-
}
3803
-
},
3804
-
"node_modules/string.prototype.trimstart": {
3805
-
"version": "1.0.8",
3806
-
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
3807
-
"integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
3808
-
"dev": true,
3809
-
"license": "MIT",
3810
-
"dependencies": {
3811
-
"call-bind": "^1.0.7",
3812
-
"define-properties": "^1.2.1",
3813
-
"es-object-atoms": "^1.0.0"
3814
-
},
3815
-
"engines": {
3816
-
"node": ">= 0.4"
3817
-
},
3818
-
"funding": {
3819
-
"url": "https://github.com/sponsors/ljharb"
3820
-
}
3821
-
},
3822
-
"node_modules/strip-bom": {
3823
-
"version": "3.0.0",
3824
-
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
3825
-
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
3826
-
"dev": true,
3827
-
"license": "MIT",
3828
-
"engines": {
3829
-
"node": ">=4"
3830
-
}
3831
-
},
3832
-
"node_modules/strip-json-comments": {
3833
-
"version": "3.1.1",
3834
-
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
3835
-
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
3836
-
"dev": true,
3837
-
"license": "MIT",
3838
-
"engines": {
3839
-
"node": ">=8"
3840
-
},
3841
-
"funding": {
3842
-
"url": "https://github.com/sponsors/sindresorhus"
3843
-
}
3844
-
},
3845
-
"node_modules/supports-color": {
3846
-
"version": "7.2.0",
3847
-
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
3848
-
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
3849
-
"dev": true,
3850
-
"license": "MIT",
3851
-
"dependencies": {
3852
-
"has-flag": "^4.0.0"
3853
-
},
3854
-
"engines": {
3855
-
"node": ">=8"
3856
-
}
3857
-
},
3858
-
"node_modules/supports-preserve-symlinks-flag": {
3859
-
"version": "1.0.0",
3860
-
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
3861
-
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
3862
-
"dev": true,
3863
-
"license": "MIT",
3864
-
"engines": {
3865
-
"node": ">= 0.4"
3866
-
},
3867
-
"funding": {
3868
-
"url": "https://github.com/sponsors/ljharb"
3869
-
}
3870
-
},
3871
-
"node_modules/tinyglobby": {
3872
-
"version": "0.2.15",
3873
-
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
3874
-
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
3875
-
"license": "MIT",
3876
-
"dependencies": {
3877
-
"fdir": "^6.5.0",
3878
-
"picomatch": "^4.0.3"
3879
-
},
3880
-
"engines": {
3881
-
"node": ">=12.0.0"
3882
-
},
3883
-
"funding": {
3884
-
"url": "https://github.com/sponsors/SuperchupuDev"
3885
-
}
3886
-
},
3887
-
"node_modules/tlds": {
3888
-
"version": "1.260.0",
3889
-
"resolved": "https://registry.npmjs.org/tlds/-/tlds-1.260.0.tgz",
3890
-
"integrity": "sha512-78+28EWBhCEE7qlyaHA9OR3IPvbCLiDh3Ckla593TksfFc9vfTsgvH7eS+dr3o9qr31gwGbogcI16yN91PoRjQ==",
3891
-
"license": "MIT",
3892
-
"bin": {
3893
-
"tlds": "bin.js"
3894
-
}
3895
-
},
3896
-
"node_modules/tsconfig-paths": {
3897
-
"version": "3.15.0",
3898
-
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
3899
-
"integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
3900
-
"dev": true,
3901
-
"license": "MIT",
3902
-
"dependencies": {
3903
-
"@types/json5": "^0.0.29",
3904
-
"json5": "^1.0.2",
3905
-
"minimist": "^1.2.6",
3906
-
"strip-bom": "^3.0.0"
3907
-
}
3908
-
},
3909
-
"node_modules/type-check": {
3910
-
"version": "0.4.0",
3911
-
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
3912
-
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
3913
-
"dev": true,
3914
-
"license": "MIT",
3915
-
"dependencies": {
3916
-
"prelude-ls": "^1.2.1"
3917
-
},
3918
-
"engines": {
3919
-
"node": ">= 0.8.0"
3920
-
}
3921
-
},
3922
-
"node_modules/typed-array-buffer": {
3923
-
"version": "1.0.3",
3924
-
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
3925
-
"integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
3926
-
"dev": true,
3927
-
"license": "MIT",
3928
-
"dependencies": {
3929
-
"call-bound": "^1.0.3",
3930
-
"es-errors": "^1.3.0",
3931
-
"is-typed-array": "^1.1.14"
3932
-
},
3933
-
"engines": {
3934
-
"node": ">= 0.4"
3935
-
}
3936
-
},
3937
-
"node_modules/typed-array-byte-length": {
3938
-
"version": "1.0.3",
3939
-
"resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
3940
-
"integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
3941
-
"dev": true,
3942
-
"license": "MIT",
3943
-
"dependencies": {
3944
-
"call-bind": "^1.0.8",
3945
-
"for-each": "^0.3.3",
3946
-
"gopd": "^1.2.0",
3947
-
"has-proto": "^1.2.0",
3948
-
"is-typed-array": "^1.1.14"
3949
-
},
3950
-
"engines": {
3951
-
"node": ">= 0.4"
3952
-
},
3953
-
"funding": {
3954
-
"url": "https://github.com/sponsors/ljharb"
3955
-
}
3956
-
},
3957
-
"node_modules/typed-array-byte-offset": {
3958
-
"version": "1.0.4",
3959
-
"resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
3960
-
"integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
3961
-
"dev": true,
3962
-
"license": "MIT",
3963
-
"dependencies": {
3964
-
"available-typed-arrays": "^1.0.7",
3965
-
"call-bind": "^1.0.8",
3966
-
"for-each": "^0.3.3",
3967
-
"gopd": "^1.2.0",
3968
-
"has-proto": "^1.2.0",
3969
-
"is-typed-array": "^1.1.15",
3970
-
"reflect.getprototypeof": "^1.0.9"
3971
-
},
3972
-
"engines": {
3973
-
"node": ">= 0.4"
3974
-
},
3975
-
"funding": {
3976
-
"url": "https://github.com/sponsors/ljharb"
3977
-
}
3978
-
},
3979
-
"node_modules/typed-array-length": {
3980
-
"version": "1.0.7",
3981
-
"resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
3982
-
"integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
3983
-
"dev": true,
3984
-
"license": "MIT",
3985
-
"dependencies": {
3986
-
"call-bind": "^1.0.7",
3987
-
"for-each": "^0.3.3",
3988
-
"gopd": "^1.0.1",
3989
-
"is-typed-array": "^1.1.13",
3990
-
"possible-typed-array-names": "^1.0.0",
3991
-
"reflect.getprototypeof": "^1.0.6"
3992
-
},
3993
-
"engines": {
3994
-
"node": ">= 0.4"
3995
-
},
3996
-
"funding": {
3997
-
"url": "https://github.com/sponsors/ljharb"
3998
-
}
3999
-
},
4000
-
"node_modules/uint8arrays": {
4001
-
"version": "3.0.0",
4002
-
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz",
4003
-
"integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==",
4004
-
"license": "MIT",
4005
-
"dependencies": {
4006
-
"multiformats": "^9.4.2"
4007
-
}
4008
-
},
4009
-
"node_modules/unbox-primitive": {
4010
-
"version": "1.1.0",
4011
-
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
4012
-
"integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
4013
-
"dev": true,
4014
-
"license": "MIT",
4015
-
"dependencies": {
4016
-
"call-bound": "^1.0.3",
4017
-
"has-bigints": "^1.0.2",
4018
-
"has-symbols": "^1.1.0",
4019
-
"which-boxed-primitive": "^1.1.1"
4020
-
},
4021
-
"engines": {
4022
-
"node": ">= 0.4"
4023
-
},
4024
-
"funding": {
4025
-
"url": "https://github.com/sponsors/ljharb"
4026
-
}
4027
-
},
4028
-
"node_modules/uri-js": {
4029
-
"version": "4.4.1",
4030
-
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
4031
-
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
4032
-
"dev": true,
4033
-
"license": "BSD-2-Clause",
4034
-
"dependencies": {
4035
-
"punycode": "^2.1.0"
4036
-
}
4037
-
},
4038
-
"node_modules/vite": {
4039
-
"version": "7.1.10",
4040
-
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.10.tgz",
4041
-
"integrity": "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==",
4042
-
"license": "MIT",
4043
-
"dependencies": {
4044
-
"esbuild": "^0.25.0",
4045
-
"fdir": "^6.5.0",
4046
-
"picomatch": "^4.0.3",
4047
-
"postcss": "^8.5.6",
4048
-
"rollup": "^4.43.0",
4049
-
"tinyglobby": "^0.2.15"
4050
-
},
4051
-
"bin": {
4052
-
"vite": "bin/vite.js"
4053
-
},
4054
-
"engines": {
4055
-
"node": "^20.19.0 || >=22.12.0"
4056
-
},
4057
-
"funding": {
4058
-
"url": "https://github.com/vitejs/vite?sponsor=1"
4059
-
},
4060
-
"optionalDependencies": {
4061
-
"fsevents": "~2.3.3"
4062
-
},
4063
-
"peerDependencies": {
4064
-
"@types/node": "^20.19.0 || >=22.12.0",
4065
-
"jiti": ">=1.21.0",
4066
-
"less": "^4.0.0",
4067
-
"lightningcss": "^1.21.0",
4068
-
"sass": "^1.70.0",
4069
-
"sass-embedded": "^1.70.0",
4070
-
"stylus": ">=0.54.8",
4071
-
"sugarss": "^5.0.0",
4072
-
"terser": "^5.16.0",
4073
-
"tsx": "^4.8.1",
4074
-
"yaml": "^2.4.2"
4075
-
},
4076
-
"peerDependenciesMeta": {
4077
-
"@types/node": {
4078
-
"optional": true
4079
-
},
4080
-
"jiti": {
4081
-
"optional": true
4082
-
},
4083
-
"less": {
4084
-
"optional": true
4085
-
},
4086
-
"lightningcss": {
4087
-
"optional": true
4088
-
},
4089
-
"sass": {
4090
-
"optional": true
4091
-
},
4092
-
"sass-embedded": {
4093
-
"optional": true
4094
-
},
4095
-
"stylus": {
4096
-
"optional": true
4097
-
},
4098
-
"sugarss": {
4099
-
"optional": true
4100
-
},
4101
-
"terser": {
4102
-
"optional": true
4103
-
},
4104
-
"tsx": {
4105
-
"optional": true
4106
-
},
4107
-
"yaml": {
4108
-
"optional": true
4109
-
}
4110
-
}
4111
-
},
4112
-
"node_modules/vite-plugin-full-reload": {
4113
-
"version": "1.2.0",
4114
-
"resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.2.0.tgz",
4115
-
"integrity": "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA==",
4116
-
"license": "MIT",
4117
-
"dependencies": {
4118
-
"picocolors": "^1.0.0",
4119
-
"picomatch": "^2.3.1"
4120
-
}
4121
-
},
4122
-
"node_modules/vite-plugin-full-reload/node_modules/picomatch": {
4123
-
"version": "2.3.1",
4124
-
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
4125
-
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
4126
-
"license": "MIT",
4127
-
"engines": {
4128
-
"node": ">=8.6"
4129
-
},
4130
-
"funding": {
4131
-
"url": "https://github.com/sponsors/jonschlinkert"
4132
-
}
4133
-
},
4134
-
"node_modules/vite-rs-plugin": {
4135
-
"version": "1.0.1",
4136
-
"resolved": "https://registry.npmjs.org/vite-rs-plugin/-/vite-rs-plugin-1.0.1.tgz",
4137
-
"integrity": "sha512-YhgflKQIRzuS5x66J3yICoVLH25D2fNU+jThK8tpYl/jGrXeIKT4w5VH1lkLPRC0SjK2ZCm9S6K9Z2ZFVDHjPQ==",
4138
-
"license": "MIT",
4139
-
"dependencies": {
4140
-
"vite-plugin-full-reload": "^1.2.0"
4141
-
},
4142
-
"bin": {
4143
-
"cleanup": "bin/cleanForBuild.js"
4144
-
},
4145
-
"peerDependencies": {
4146
-
"vite": "^5.0.0"
4147
-
}
4148
-
},
4149
-
"node_modules/which": {
4150
-
"version": "2.0.2",
4151
-
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
4152
-
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
4153
-
"dev": true,
4154
-
"license": "ISC",
4155
-
"dependencies": {
4156
-
"isexe": "^2.0.0"
4157
-
},
4158
-
"bin": {
4159
-
"node-which": "bin/node-which"
4160
-
},
4161
-
"engines": {
4162
-
"node": ">= 8"
4163
-
}
4164
-
},
4165
-
"node_modules/which-boxed-primitive": {
4166
-
"version": "1.1.1",
4167
-
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
4168
-
"integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
4169
-
"dev": true,
4170
-
"license": "MIT",
4171
-
"dependencies": {
4172
-
"is-bigint": "^1.1.0",
4173
-
"is-boolean-object": "^1.2.1",
4174
-
"is-number-object": "^1.1.1",
4175
-
"is-string": "^1.1.1",
4176
-
"is-symbol": "^1.1.1"
4177
-
},
4178
-
"engines": {
4179
-
"node": ">= 0.4"
4180
-
},
4181
-
"funding": {
4182
-
"url": "https://github.com/sponsors/ljharb"
4183
-
}
4184
-
},
4185
-
"node_modules/which-builtin-type": {
4186
-
"version": "1.2.1",
4187
-
"resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
4188
-
"integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
4189
-
"dev": true,
4190
-
"license": "MIT",
4191
-
"dependencies": {
4192
-
"call-bound": "^1.0.2",
4193
-
"function.prototype.name": "^1.1.6",
4194
-
"has-tostringtag": "^1.0.2",
4195
-
"is-async-function": "^2.0.0",
4196
-
"is-date-object": "^1.1.0",
4197
-
"is-finalizationregistry": "^1.1.0",
4198
-
"is-generator-function": "^1.0.10",
4199
-
"is-regex": "^1.2.1",
4200
-
"is-weakref": "^1.0.2",
4201
-
"isarray": "^2.0.5",
4202
-
"which-boxed-primitive": "^1.1.0",
4203
-
"which-collection": "^1.0.2",
4204
-
"which-typed-array": "^1.1.16"
4205
-
},
4206
-
"engines": {
4207
-
"node": ">= 0.4"
4208
-
},
4209
-
"funding": {
4210
-
"url": "https://github.com/sponsors/ljharb"
4211
-
}
4212
-
},
4213
-
"node_modules/which-collection": {
4214
-
"version": "1.0.2",
4215
-
"resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
4216
-
"integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
4217
-
"dev": true,
4218
-
"license": "MIT",
4219
-
"dependencies": {
4220
-
"is-map": "^2.0.3",
4221
-
"is-set": "^2.0.3",
4222
-
"is-weakmap": "^2.0.2",
4223
-
"is-weakset": "^2.0.3"
4224
-
},
4225
-
"engines": {
4226
-
"node": ">= 0.4"
4227
-
},
4228
-
"funding": {
4229
-
"url": "https://github.com/sponsors/ljharb"
4230
-
}
4231
-
},
4232
-
"node_modules/which-typed-array": {
4233
-
"version": "1.1.19",
4234
-
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
4235
-
"integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
4236
-
"dev": true,
4237
-
"license": "MIT",
4238
-
"dependencies": {
4239
-
"available-typed-arrays": "^1.0.7",
4240
-
"call-bind": "^1.0.8",
4241
-
"call-bound": "^1.0.4",
4242
-
"for-each": "^0.3.5",
4243
-
"get-proto": "^1.0.1",
4244
-
"gopd": "^1.2.0",
4245
-
"has-tostringtag": "^1.0.2"
4246
-
},
4247
-
"engines": {
4248
-
"node": ">= 0.4"
4249
-
},
4250
-
"funding": {
4251
-
"url": "https://github.com/sponsors/ljharb"
4252
-
}
4253
-
},
4254
-
"node_modules/word-wrap": {
4255
-
"version": "1.2.5",
4256
-
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
4257
-
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
4258
-
"dev": true,
4259
-
"license": "MIT",
4260
-
"engines": {
4261
-
"node": ">=0.10.0"
4262
-
}
4263
-
},
4264
-
"node_modules/yocto-queue": {
4265
-
"version": "0.1.0",
4266
-
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
4267
-
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
4268
-
"dev": true,
4269
-
"license": "MIT",
4270
-
"engines": {
4271
-
"node": ">=10"
4272
-
},
4273
-
"funding": {
4274
-
"url": "https://github.com/sponsors/sindresorhus"
4275
-
}
4276
-
},
4277
-
"node_modules/zod": {
4278
-
"version": "3.25.76",
4279
-
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
4280
-
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
4281
-
"license": "MIT",
4282
-
"funding": {
4283
-
"url": "https://github.com/sponsors/colinhacks"
4284
-
}
4285
-
}
4286
-
}
4287
-
}
-31
web/ui-code/package.json
-31
web/ui-code/package.json
···
1
-
{
2
-
"name": "ui-code",
3
-
"private": true,
4
-
"version": "0.0.0",
5
-
"type": "module",
6
-
"scripts": {
7
-
"dev": "vite",
8
-
"build": "vite build",
9
-
"build:watch": "vite build -w",
10
-
"preview": "vite preview",
11
-
"lint": "eslint src --ext .js",
12
-
"lint:fix": "eslint src --ext .js --fix"
13
-
},
14
-
"devDependencies": {
15
-
"eslint": "^9.34.0",
16
-
"eslint-plugin-import": "^2.32.0",
17
-
"vite": "^7.1.7"
18
-
},
19
-
"dependencies": {
20
-
"@atcute/cbor": "^2.2.7",
21
-
"@atcute/client": "^4.0.4",
22
-
"@atcute/crypto": "^2.2.5",
23
-
"@atcute/did-plc": "^0.1.7",
24
-
"@atcute/identity-resolver": "^1.1.3",
25
-
"@atcute/multibase": "^1.1.6",
26
-
"@atproto/api": "^0.16.7",
27
-
"alpinejs": "^3.15.0",
28
-
"vite-plugin-full-reload": "^1.2.0",
29
-
"vite-rs-plugin": "1.0.1"
30
-
}
31
-
}
-83
web/ui-code/src/atprotoUtils.js
-83
web/ui-code/src/atprotoUtils.js
···
1
-
import {
2
-
CompositeDidDocumentResolver, CompositeHandleResolver,
3
-
DohJsonHandleResolver,
4
-
PlcDidDocumentResolver, WebDidDocumentResolver,
5
-
WellKnownHandleResolver
6
-
} from '@atcute/identity-resolver';
7
-
import {Client, simpleFetchHandler} from '@atcute/client';
8
-
9
-
const handleResolver = new CompositeHandleResolver({
10
-
strategy: 'race',
11
-
methods: {
12
-
dns: new DohJsonHandleResolver({
13
-
dohUrl: 'https://mozilla.cloudflare-dns.com/dns-query',
14
-
}),
15
-
http: new WellKnownHandleResolver(),
16
-
},
17
-
});
18
-
19
-
const docResolver = new CompositeDidDocumentResolver({
20
-
methods: {
21
-
plc: new PlcDidDocumentResolver(),
22
-
web: new WebDidDocumentResolver(),
23
-
},
24
-
});
25
-
26
-
const cleanHandle = (handle) =>
27
-
handle.replace('@', '').trim().replace(
28
-
/[\u202A\u202C\u200E\u200F\u2066-\u2069]/g,
29
-
'',
30
-
);
31
-
32
-
33
-
async function handleAndPDSResolver(handle) {
34
-
let usersDid = null;
35
-
if (handle.startsWith('did:')) {
36
-
usersDid = handle;
37
-
} else {
38
-
const cleanedHandle = cleanHandle(handle);
39
-
usersDid = await handleResolver.resolve(cleanedHandle);
40
-
}
41
-
const didDoc = await docResolver.resolve(usersDid);
42
-
43
-
let pds;
44
-
try {
45
-
pds = didDoc.service?.filter((s) =>
46
-
s.type === 'AtprotoPersonalDataServer'
47
-
)[0].serviceEndpoint;
48
-
} catch (error) {
49
-
console.error(error);
50
-
throw new Error('Could not find a PDS in the DID document.');
51
-
}
52
-
return {usersDid, pds};
53
-
}
54
-
55
-
56
-
async function fetchPDSMooverDIDWeb(baseUrl) {
57
-
const response = await fetch(`${baseUrl}/.well-known/did.json`);
58
-
if (!response.ok) {
59
-
throw new Error(`Failed to fetch DID document: ${response.status}`);
60
-
}
61
-
const didDoc = await response.json();
62
-
return didDoc.id;
63
-
}
64
-
65
-
async function describeServer() {
66
-
const baseUrl = window.location.origin;
67
-
const handler = simpleFetchHandler({service: baseUrl});
68
-
const rpc = new Client({
69
-
handler
70
-
});
71
-
72
-
let describeServerResponse = await rpc.get('com.pdsmoover.backup.describeServer');
73
-
if (describeServerResponse.ok) {
74
-
return describeServerResponse.data;
75
-
} else {
76
-
throw new Error('Could not describe server');
77
-
}
78
-
79
-
80
-
}
81
-
82
-
83
-
export {handleResolver, docResolver, cleanHandle, handleAndPDSResolver, fetchPDSMooverDIDWeb, describeServer};
-216
web/ui-code/src/backup.js
-216
web/ui-code/src/backup.js
···
1
-
import {Client, CredentialManager, ok} from '@atcute/client';
2
-
import {fetchPDSMooverDIDWeb, handleAndPDSResolver} from './atprotoUtils.js';
3
-
4
-
5
-
class BackupService {
6
-
constructor() {
7
-
/**
8
-
*
9
-
* @type {Client}
10
-
*/
11
-
this.atCuteClient = null;
12
-
/**
13
-
*
14
-
* @type {CredentialManager}
15
-
*/
16
-
this.atCuteCredentialManager = null;
17
-
}
18
-
19
-
// Perform backup sign-up using user credentials. If the server requires 2FA,
20
-
// it will throw with error.error === 'AuthFactorTokenRequired'.
21
-
async loginAndStatus(identifier, password, onStatus = null, twoFactorCode = null) {
22
-
let {pds} = await handleAndPDSResolver(identifier);
23
-
24
-
25
-
const manager = new CredentialManager({
26
-
service: pds
27
-
});
28
-
29
-
//TODO prob should be a function param, but eh
30
-
const didWeb = await fetchPDSMooverDIDWeb(window.location.origin);
31
-
32
-
const rpc = new Client({
33
-
handler: manager,
34
-
proxy: {
35
-
did: didWeb,
36
-
serviceId: '#repo_backup'
37
-
}
38
-
});
39
-
40
-
try {
41
-
if (onStatus) onStatus('Signing in…');
42
-
43
-
let loginInput = {
44
-
identifier,
45
-
password,
46
-
47
-
};
48
-
if (twoFactorCode) {
49
-
loginInput.code = twoFactorCode;
50
-
}
51
-
await manager.login(loginInput);
52
-
53
-
54
-
// Make the client/manager available regardless of repo status so we can sign up if needed.
55
-
this.atCuteClient = rpc;
56
-
this.atCuteCredentialManager = manager;
57
-
58
-
if (onStatus) onStatus('Checking backup status');
59
-
const result = await rpc.get('com.pdsmoover.backup.getRepoStatus', {
60
-
params: {
61
-
did: manager.session.did.toString()
62
-
}
63
-
});
64
-
if (result.ok) {
65
-
return result.data;
66
-
} else {
67
-
switch (result.data.error) {
68
-
case 'RepoNotFound':
69
-
console.log('Repo not found');
70
-
return null;
71
-
default:
72
-
throw result.data.error;
73
-
}
74
-
75
-
}
76
-
} catch (err) {
77
-
throw err;
78
-
}
79
-
}
80
-
81
-
// Sign up for backups. Optionally create a new recovery key on signup.
82
-
async signUp(onStatus = null) {
83
-
if (!this.atCuteClient || !this.atCuteCredentialManager) {
84
-
throw new Error('Not signed in');
85
-
}
86
-
if (onStatus) onStatus('Creating backup registration…');
87
-
const data = await ok(
88
-
this.atCuteClient.post('com.pdsmoover.backup.signUp', {
89
-
as: null,
90
-
})
91
-
);
92
-
if (onStatus) onStatus('Backup registration complete');
93
-
return data;
94
-
}
95
-
96
-
async requestAPlcToken() {
97
-
if (!this.atCuteClient || !this.atCuteCredentialManager) {
98
-
throw new Error('Not signed in');
99
-
}
100
-
const rpc = new Client({
101
-
handler: this.atCuteCredentialManager,
102
-
});
103
-
104
-
let response = await rpc.post('com.atproto.identity.requestPlcOperationSignature', {
105
-
as: null,
106
-
});
107
-
if (!response.ok) {
108
-
throw new Error(response.data?.message || 'Failed to request PLC token');
109
-
}
110
-
}
111
-
112
-
async addANewRotationKey(plcToken, rotationKey) {
113
-
if (!this.atCuteClient || !this.atCuteCredentialManager) {
114
-
throw new Error('Not signed in');
115
-
}
116
-
117
-
118
-
const rpc = new Client({
119
-
handler: this.atCuteCredentialManager,
120
-
});
121
-
122
-
let getDidCredentials = await rpc.get('com.atproto.identity.getRecommendedDidCredentials');
123
-
124
-
if (getDidCredentials.ok) {
125
-
const pdsProvidedRotationKeys = getDidCredentials.data.rotationKeys ?? [];
126
-
const updatedRotationKeys = [rotationKey, ...pdsProvidedRotationKeys];
127
-
128
-
const credentials = {
129
-
...getDidCredentials.data,
130
-
rotationKeys: updatedRotationKeys,
131
-
};
132
-
133
-
const signDocRes = await rpc.post('com.atproto.identity.signPlcOperation', {
134
-
input: {
135
-
token: plcToken,
136
-
...credentials,
137
-
}
138
-
});
139
-
140
-
if (signDocRes.ok) {
141
-
const submitDocRes = await rpc.post('com.atproto.identity.submitPlcOperation', {
142
-
input: signDocRes.data,
143
-
as: null,
144
-
});
145
-
146
-
if (!submitDocRes.ok) {
147
-
throw new Error(submitDocRes.data?.message || 'Failed to submit PLC operation');
148
-
}
149
-
150
-
} else {
151
-
throw new Error(signDocRes.data?.message || 'Failed to sign PLC operation');
152
-
}
153
-
154
-
155
-
} else {
156
-
throw new Error(getDidCredentials.data?.message || 'Failed to get status');
157
-
}
158
-
}
159
-
160
-
async getUsersRepoStatus(onStatus = null) {
161
-
if (!this.atCuteClient || !this.atCuteCredentialManager) {
162
-
throw new Error('Not signed in');
163
-
}
164
-
if (onStatus) onStatus('Refreshing backup status…');
165
-
const result = await this.atCuteClient.get('com.pdsmoover.backup.getRepoStatus', {
166
-
params: {did: this.atCuteCredentialManager.session.did.toString()}
167
-
});
168
-
if (result.ok) {
169
-
return result.data;
170
-
} else {
171
-
throw new Error(result.data?.message || 'Failed to get status');
172
-
}
173
-
}
174
-
175
-
async runBackupNow(onStatus = null) {
176
-
if (!this.atCuteClient || !this.atCuteCredentialManager) {
177
-
throw new Error('Not signed in');
178
-
}
179
-
if (onStatus) onStatus('Requesting backup…');
180
-
const res = await this.atCuteClient.post('com.pdsmoover.backup.requestBackup', {as: null, data: {}});
181
-
if (res.ok) {
182
-
if (onStatus) onStatus('Backup requested.');
183
-
// After requesting, refresh status to reflect any immediate changes
184
-
try {
185
-
await this.refreshStatus(onStatus);
186
-
} catch (_) { /* ignore */
187
-
}
188
-
return true;
189
-
} else {
190
-
const err = res.data;
191
-
if (err?.error === 'Timeout') {
192
-
throw {error: 'Timeout', message: err?.message || 'Please wait a few minutes before requesting again.'};
193
-
}
194
-
throw new Error(err?.message || 'Failed to request backup');
195
-
}
196
-
}
197
-
198
-
// Remove (delete) the user's backup repository
199
-
async removeRepo(onStatus = null) {
200
-
if (!this.atCuteClient || !this.atCuteCredentialManager) {
201
-
throw new Error('Not signed in');
202
-
}
203
-
if (onStatus) onStatus('Deleting backup repository…');
204
-
const res = await this.atCuteClient.post('com.pdsmoover.backup.removeRepo', {as: null, data: {}});
205
-
if (res.ok) {
206
-
if (onStatus) onStatus('Backup repository deleted.');
207
-
return true;
208
-
} else {
209
-
const err = res.data;
210
-
throw new Error(err?.message || 'Failed to delete backup repository');
211
-
}
212
-
}
213
-
}
214
-
215
-
216
-
export {BackupService};
-24
web/ui-code/src/main.js
-24
web/ui-code/src/main.js
···
1
-
import {Migrator} from './pdsmoover.js';
2
-
import {MissingBlobs} from './missingBlobs.js';
3
-
import {BackupService} from './backup.js';
4
-
import {PlcOps} from './plc-ops.js';
5
-
import {MooverUtils} from './utils.js';
6
-
import {Restore} from './restore.js';
7
-
import {handleAndPDSResolver} from './atprotoUtils.js';
8
-
import Alpine from 'alpinejs';
9
-
10
-
11
-
window.Migrator = new Migrator();
12
-
window.MissingBlobs = new MissingBlobs();
13
-
window.BackupService = new BackupService();
14
-
window.PlcOps = new PlcOps();
15
-
window.MooverUtils = new MooverUtils();
16
-
window.Restore = new Restore();
17
-
window.handleAndPDSResolver = handleAndPDSResolver;
18
-
19
-
window.Alpine = Alpine;
20
-
21
-
Alpine.start();
22
-
23
-
export {Migrator, MissingBlobs};
24
-
-153
web/ui-code/src/missingBlobs.js
-153
web/ui-code/src/missingBlobs.js
···
1
-
//I need to condense this code with the rest of PDS MOOver cause it has a lot of overlap
2
-
import {AtpAgent} from '@atproto/api';
3
-
import {handleAndPDSResolver} from './atprotoUtils.js';
4
-
5
-
6
-
class MissingBlobs {
7
-
8
-
constructor() {
9
-
this.currentPdsAgent = null;
10
-
this.oldPdsAgent = null;
11
-
this.did = null;
12
-
this.currentPdsUrl = null;
13
-
this.missingBlobs = [];
14
-
15
-
}
16
-
17
-
async currentAgentLogin(
18
-
handle,
19
-
password,
20
-
twoFactorCode = null,
21
-
) {
22
-
let {usersDid, pds} = await handleAndPDSResolver(handle);
23
-
this.did = usersDid;
24
-
this.currentPdsUrl = pds;
25
-
const agent = new AtpAgent({
26
-
service: pds,
27
-
});
28
-
29
-
if (twoFactorCode === null) {
30
-
await agent.login({identifier: usersDid, password});
31
-
} else {
32
-
await agent.login({identifier: usersDid, password: password, authFactorToken: twoFactorCode});
33
-
}
34
-
35
-
this.currentPdsAgent = agent;
36
-
37
-
const result = await agent.com.atproto.server.checkAccountStatus();
38
-
const missingBlobs = await this.currentPdsAgent.com.atproto.repo.listMissingBlobs({
39
-
limit: 10,
40
-
});
41
-
return {accountStatus: result.data, missingBlobsCount: missingBlobs.data.blobs.length};
42
-
}
43
-
44
-
async oldAgentLogin(
45
-
password,
46
-
twoFactorCode = null,
47
-
pdsUrl = null,
48
-
) {
49
-
let oldPds = null;
50
-
51
-
if (pdsUrl === null) {
52
-
const response = await fetch(`https://plc.directory/${this.did}/log`);
53
-
let auditLog = await response.json();
54
-
auditLog = auditLog.reverse();
55
-
let debugCount = 0;
56
-
for (const entry of auditLog) {
57
-
console.log(`Loop: ${debugCount++}`);
58
-
console.log(entry);
59
-
if (entry.services) {
60
-
if (entry.services.atproto_pds) {
61
-
if (entry.services.atproto_pds.type === 'AtprotoPersonalDataServer') {
62
-
const pds = entry.services.atproto_pds.endpoint;
63
-
console.log(`Found PDS: ${pds}`);
64
-
if (pds.toLowerCase() !== this.currentPdsUrl.toLowerCase()) {
65
-
oldPds = pds;
66
-
break;
67
-
}
68
-
}
69
-
}
70
-
}
71
-
}
72
-
if (oldPds === null) {
73
-
throw new Error('Could not find your old PDS');
74
-
}
75
-
} else {
76
-
oldPds = pdsUrl;
77
-
}
78
-
79
-
const agent = new AtpAgent({
80
-
service: oldPds,
81
-
});
82
-
83
-
if (twoFactorCode === null) {
84
-
await agent.login({identifier: this.did, password});
85
-
} else {
86
-
await agent.login({identifier: this.did, password: password, authFactorToken: twoFactorCode});
87
-
}
88
-
this.oldPdsAgent = agent;
89
-
}
90
-
91
-
async migrateMissingBlobs(statusUpdateHandler) {
92
-
if (this.currentPdsAgent === null) {
93
-
throw new Error('Current PDS agent is not set');
94
-
}
95
-
if (this.oldPdsAgent === null) {
96
-
throw new Error('Old PDS agent is not set');
97
-
}
98
-
statusUpdateHandler('Starting to import blobs...');
99
-
100
-
// const currentAccountStatus = await this.currentPdsAgent.com.atproto.server.checkAccountStatus();
101
-
// let totalMissingBlobs = currentAccountStatus.data.expectedBlobs - currentAccountStatus.data.importedBlobs;
102
-
let totalMissingBlobs = 0;
103
-
let missingBlobCursor = undefined;
104
-
let missingUploadedBlobs = 0;
105
-
106
-
do {
107
-
108
-
const missingBlobs = await this.currentPdsAgent.com.atproto.repo.listMissingBlobs({
109
-
cursor: missingBlobCursor,
110
-
//Test this cause it may be a big update
111
-
limit: 1000,
112
-
});
113
-
totalMissingBlobs += missingBlobs.data.blobs.length;
114
-
115
-
for (const recordBlob of missingBlobs.data.blobs) {
116
-
try {
117
-
118
-
const blobRes = await this.oldPdsAgent.com.atproto.sync.getBlob({
119
-
did: this.did,
120
-
cid: recordBlob.cid,
121
-
});
122
-
let result = await this.currentPdsAgent.com.atproto.repo.uploadBlob(blobRes.data, {
123
-
encoding: blobRes.headers['content-type'],
124
-
});
125
-
126
-
if (result.status === 429) {
127
-
statusUpdateHandler(`You are being rate limited. Will need to try again later to get the rest of the blobs. Migrated blobs: ${missingUploadedBlobs}/${totalMissingBlobs}`);
128
-
}
129
-
130
-
if (missingUploadedBlobs % 2 === 0) {
131
-
statusUpdateHandler(`Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs} (The total may increase as we find more)`);
132
-
}
133
-
missingUploadedBlobs++;
134
-
} catch (error) {
135
-
console.error(error);
136
-
this.missingBlobs.push(recordBlob.cid);
137
-
}
138
-
}
139
-
missingBlobCursor = missingBlobs.data.cursor;
140
-
} while (missingBlobCursor);
141
-
142
-
const accountStatus = await this.currentPdsAgent.com.atproto.server.checkAccountStatus();
143
-
const missingBlobs = await this.currentPdsAgent.com.atproto.repo.listMissingBlobs({
144
-
limit: 10,
145
-
});
146
-
return {accountStatus: accountStatus.data, missingBlobsCount: missingBlobs.data.blobs.length};
147
-
148
-
149
-
}
150
-
151
-
}
152
-
153
-
export {MissingBlobs};
-361
web/ui-code/src/pdsmoover.js
-361
web/ui-code/src/pdsmoover.js
···
1
-
import {docResolver, fetchPDSMooverDIDWeb, handleResolver} from './atprotoUtils.js';
2
-
import {AtpAgent} from '@atproto/api';
3
-
4
-
5
-
function safeStatusUpdate(statusUpdateHandler, status) {
6
-
if (statusUpdateHandler) {
7
-
statusUpdateHandler(status);
8
-
}
9
-
}
10
-
11
-
12
-
class Migrator {
13
-
constructor() {
14
-
/** @type {AtpAgent} */
15
-
this.oldAgent = null;
16
-
/** @type {AtpAgent} */
17
-
this.newAgent = null;
18
-
this.missingBlobs = [];
19
-
//State for reruns
20
-
this.createNewAccount = true;
21
-
this.migrateRepo = true;
22
-
this.migrateBlobs = true;
23
-
this.migrateMissingBlobs = true;
24
-
this.migratePrefs = true;
25
-
this.migratePlcRecord = true;
26
-
}
27
-
28
-
/**
29
-
* This migrator is pretty cut and dry and makes a few assumptions
30
-
* 1. You are using the same password between each account
31
-
* 2. If this command fails for something like oauth 2fa code it throws an error and expects the same values when ran again.
32
-
* @param {string} oldHandle - The handle you use on your old pds, something like alice.bsky.social
33
-
* @param {string} password - Your password for your current login. Has to be your real password, no app password. When setting up a new account we reuse it as well for that account
34
-
* @param {string} newPdsUrl - The new URL for your pds. Like https://coolnewpds.com
35
-
* @param {string} newEmail - The email you want to use on the new pds (can be the same as the previous one as long as it's not already being used on the new pds)
36
-
* @param {string} newHandle - The new handle you want, like alice.bsky.social, or if you already have a domain name set as a handle can use it myname.com.
37
-
* @param {string|null} inviteCode - The invite code you got from the PDS you are migrating to. If null does not include one
38
-
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI. Like (status) => console.log(status)
39
-
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
40
-
*/
41
-
async migrate(oldHandle, password, newPdsUrl, newEmail, newHandle, inviteCode, statusUpdateHandler = null, twoFactorCode = null) {
42
-
43
-
//Copying the handle from bsky website adds some random unicodes on
44
-
oldHandle = oldHandle.replace('@', '').trim().replace(/[\u202A\u202C\u200E\u200F\u2066-\u2069]/g, '');
45
-
let oldAgent;
46
-
let usersDid;
47
-
//If it's a bsky handle just go with the entryway and let it sort everything
48
-
if (oldHandle.endsWith('.bsky.social')) {
49
-
oldAgent = new AtpAgent({service: 'https://bsky.social'});
50
-
const publicAgent = new AtpAgent({service: 'https://public.api.bsky.app'});
51
-
const resolveIdentityFromEntryway = await publicAgent.com.atproto.identity.resolveHandle({handle: oldHandle});
52
-
usersDid = resolveIdentityFromEntryway.data.did;
53
-
54
-
} else {
55
-
//Resolves the did and finds the did document for the old PDS
56
-
safeStatusUpdate(statusUpdateHandler, 'Resolving old PDS');
57
-
usersDid = await handleResolver.resolve(oldHandle);
58
-
const didDoc = await docResolver.resolve(usersDid);
59
-
safeStatusUpdate(statusUpdateHandler, 'Resolving did document and finding your current PDS URL');
60
-
61
-
let oldPds;
62
-
try {
63
-
oldPds = didDoc.service.filter(s => s.type === 'AtprotoPersonalDataServer')[0].serviceEndpoint;
64
-
} catch (error) {
65
-
console.error(error);
66
-
throw new Error('Could not find a PDS in the DID document.');
67
-
}
68
-
69
-
oldAgent = new AtpAgent({
70
-
service: oldPds,
71
-
});
72
-
73
-
}
74
-
75
-
safeStatusUpdate(statusUpdateHandler, 'Logging you in to the old PDS');
76
-
//Login to the old PDS
77
-
if (twoFactorCode === null) {
78
-
await oldAgent.login({identifier: oldHandle, password});
79
-
} else {
80
-
await oldAgent.login({identifier: oldHandle, password: password, authFactorToken: twoFactorCode});
81
-
}
82
-
83
-
safeStatusUpdate(statusUpdateHandler, 'Checking that the new PDS is an actual PDS (if the url is wrong this takes a while to error out)');
84
-
const newAgent = new AtpAgent({service: newPdsUrl});
85
-
const newHostDesc = await newAgent.com.atproto.server.describeServer();
86
-
if (this.createNewAccount) {
87
-
const newHostWebDid = newHostDesc.data.did;
88
-
89
-
safeStatusUpdate(statusUpdateHandler, 'Creating a new account on the new PDS');
90
-
91
-
const createAuthResp = await oldAgent.com.atproto.server.getServiceAuth({
92
-
aud: newHostWebDid,
93
-
lxm: 'com.atproto.server.createAccount',
94
-
});
95
-
const serviceJwt = createAuthResp.data.token;
96
-
97
-
let createAccountRequest = {
98
-
did: usersDid,
99
-
handle: newHandle,
100
-
email: newEmail,
101
-
password: password,
102
-
};
103
-
if (inviteCode) {
104
-
createAccountRequest.inviteCode = inviteCode;
105
-
}
106
-
const createNewAccount = await newAgent.com.atproto.server.createAccount(
107
-
createAccountRequest,
108
-
{
109
-
headers: {authorization: `Bearer ${serviceJwt}`},
110
-
encoding: 'application/json',
111
-
});
112
-
113
-
if (createNewAccount.data.did !== usersDid.toString()) {
114
-
throw new Error('Did not create the new account with the same did as the old account');
115
-
}
116
-
}
117
-
safeStatusUpdate(statusUpdateHandler, 'Logging in with the new account');
118
-
119
-
await newAgent.login({
120
-
identifier: usersDid,
121
-
password: password,
122
-
});
123
-
124
-
if (this.migrateRepo) {
125
-
safeStatusUpdate(statusUpdateHandler, 'Migrating your repo');
126
-
const repoRes = await oldAgent.com.atproto.sync.getRepo({did: usersDid});
127
-
await newAgent.com.atproto.repo.importRepo(repoRes.data, {
128
-
encoding: 'application/vnd.ipld.car',
129
-
});
130
-
}
131
-
132
-
let newAccountStatus = await newAgent.com.atproto.server.checkAccountStatus();
133
-
134
-
if (this.migrateBlobs) {
135
-
safeStatusUpdate(statusUpdateHandler, 'Migrating your blobs');
136
-
137
-
let blobCursor = undefined;
138
-
let uploadedBlobs = 0;
139
-
do {
140
-
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${uploadedBlobs}/${newAccountStatus.data.expectedBlobs}`);
141
-
142
-
const listedBlobs = await oldAgent.com.atproto.sync.listBlobs({
143
-
did: usersDid,
144
-
cursor: blobCursor,
145
-
limit: 100,
146
-
});
147
-
148
-
for (const cid of listedBlobs.data.cids) {
149
-
try {
150
-
const blobRes = await oldAgent.com.atproto.sync.getBlob({
151
-
did: usersDid,
152
-
cid,
153
-
});
154
-
await newAgent.com.atproto.repo.uploadBlob(blobRes.data, {
155
-
encoding: blobRes.headers['content-type'],
156
-
});
157
-
uploadedBlobs++;
158
-
if (uploadedBlobs % 10 === 0) {
159
-
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${uploadedBlobs}/${newAccountStatus.data.expectedBlobs}`);
160
-
}
161
-
} catch (error) {
162
-
console.error(error);
163
-
}
164
-
}
165
-
blobCursor = listedBlobs.data.cursor;
166
-
} while (blobCursor);
167
-
}
168
-
169
-
if (this.migrateMissingBlobs) {
170
-
newAccountStatus = await newAgent.com.atproto.server.checkAccountStatus();
171
-
if (newAccountStatus.data.expectedBlobs !== newAccountStatus.data.importedBlobs) {
172
-
let totalMissingBlobs = newAccountStatus.data.expectedBlobs - newAccountStatus.data.importedBlobs;
173
-
safeStatusUpdate(statusUpdateHandler, 'Looks like there are some missing blobs. Going to try and upload them now.');
174
-
//Probably should be shared between main blob uploader, but eh
175
-
let missingBlobCursor = undefined;
176
-
let missingUploadedBlobs = 0;
177
-
do {
178
-
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs}`);
179
-
180
-
const missingBlobs = await newAgent.com.atproto.repo.listMissingBlobs({
181
-
cursor: missingBlobCursor,
182
-
limit: 100,
183
-
});
184
-
185
-
for (const recordBlob of missingBlobs.data.blobs) {
186
-
try {
187
-
188
-
const blobRes = await oldAgent.com.atproto.sync.getBlob({
189
-
did: usersDid,
190
-
cid: recordBlob.cid,
191
-
});
192
-
await newAgent.com.atproto.repo.uploadBlob(blobRes.data, {
193
-
encoding: blobRes.headers['content-type'],
194
-
});
195
-
if (missingUploadedBlobs % 10 === 0) {
196
-
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs}`);
197
-
}
198
-
missingUploadedBlobs++;
199
-
} catch (error) {
200
-
//TODO silently logging prob should list them so user can manually download
201
-
console.error(error);
202
-
this.missingBlobs.push(recordBlob.cid);
203
-
}
204
-
}
205
-
missingBlobCursor = missingBlobs.data.cursor;
206
-
} while (missingBlobCursor);
207
-
208
-
}
209
-
}
210
-
if (this.migratePrefs) {
211
-
const prefs = await oldAgent.app.bsky.actor.getPreferences();
212
-
await newAgent.app.bsky.actor.putPreferences(prefs.data);
213
-
}
214
-
215
-
this.oldAgent = oldAgent;
216
-
this.newAgent = newAgent;
217
-
218
-
if (this.migratePlcRecord) {
219
-
await oldAgent.com.atproto.identity.requestPlcOperationSignature();
220
-
safeStatusUpdate(statusUpdateHandler, 'Please check your email for a PLC token');
221
-
}
222
-
}
223
-
224
-
/**
225
-
* Sign and submits the PLC operation to officially migrate the account
226
-
* @param {string} token - the PLC token sent in the email. If you're just wanting to run this rerun migrate with all the flags set as false except for migratePlcRecord
227
-
* @param additionalRotationKeysToAdd {[string]} - additional rotation keys to add in addition to the ones provided by the new PDS.
228
-
* @returns {Promise<void>}
229
-
*/
230
-
async signPlcOperation(token, additionalRotationKeysToAdd = []) {
231
-
const getDidCredentials =
232
-
await this.newAgent.com.atproto.identity.getRecommendedDidCredentials();
233
-
const pdsProvidedRotationKeys = getDidCredentials.data.rotationKeys ?? [];
234
-
// Prepend any additional rotation keys (e.g., user-added keys, newly created key) so they appear above the new PDS rotation key
235
-
const rotationKeys = [...(additionalRotationKeysToAdd || []), ...pdsProvidedRotationKeys];
236
-
if (!rotationKeys) {
237
-
throw new Error('No rotation key provided from the new PDS');
238
-
}
239
-
const credentials = {
240
-
...getDidCredentials.data,
241
-
rotationKeys: rotationKeys,
242
-
};
243
-
244
-
245
-
const plcOp = await this.oldAgent.com.atproto.identity.signPlcOperation({
246
-
token: token,
247
-
...credentials,
248
-
});
249
-
250
-
await this.newAgent.com.atproto.identity.submitPlcOperation({
251
-
operation: plcOp.data.operation,
252
-
});
253
-
254
-
await this.newAgent.com.atproto.server.activateAccount();
255
-
await this.oldAgent.com.atproto.server.deactivateAccount({});
256
-
}
257
-
258
-
// Quick and dirty copy and paste of the above to get a fix out to help people without breaking or introducing any bugs to the migration service...hopefully
259
-
async deactivateOldAccount(oldHandle, oldPassword, statusUpdateHandler = null, twoFactorCode = null) {
260
-
//Copying the handle from bsky website adds some random unicodes on
261
-
oldHandle = oldHandle.replace('@', '').trim().replace(/[\u202A\u202C\u200E\u200F\u2066-\u2069]/g, '');
262
-
let usersDid;
263
-
//If it's a bsky handle just go with the entryway and let it sort everything
264
-
if (oldHandle.endsWith('.bsky.social')) {
265
-
const publicAgent = new AtpAgent({service: 'https://public.api.bsky.app'});
266
-
const resolveIdentityFromEntryway = await publicAgent.com.atproto.identity.resolveHandle({handle: oldHandle});
267
-
usersDid = resolveIdentityFromEntryway.data.did;
268
-
} else {
269
-
//Resolves the did and finds the did document for the old PDS
270
-
safeStatusUpdate(statusUpdateHandler, 'Resolving did from handle');
271
-
usersDid = await handleResolver.resolve(oldHandle);
272
-
}
273
-
274
-
const didDoc = await docResolver.resolve(usersDid);
275
-
let currentPds;
276
-
try {
277
-
currentPds = didDoc.service.filter(s => s.type === 'AtprotoPersonalDataServer')[0].serviceEndpoint;
278
-
} catch (error) {
279
-
console.error(error);
280
-
throw new Error('Could not find a PDS in the DID document.');
281
-
}
282
-
283
-
const plcLogRequest = await fetch(`https://plc.directory/${usersDid}/log`);
284
-
const plcLog = await plcLogRequest.json();
285
-
let pdsBeforeCurrent = '';
286
-
for (const log of plcLog) {
287
-
try {
288
-
const pds = log.services.atproto_pds.endpoint;
289
-
console.log(pds);
290
-
if (pds.toLowerCase() === currentPds.toLowerCase()) {
291
-
console.log('Found the PDS before the current one');
292
-
break;
293
-
}
294
-
pdsBeforeCurrent = pds;
295
-
} catch (e) {
296
-
console.log(e);
297
-
}
298
-
}
299
-
if (pdsBeforeCurrent === '') {
300
-
throw new Error('Could not find the PDS before the current one');
301
-
}
302
-
303
-
let oldAgent = new AtpAgent({service: pdsBeforeCurrent});
304
-
safeStatusUpdate(statusUpdateHandler, `Logging you in to the old PDS: ${pdsBeforeCurrent}`);
305
-
//Login to the old PDS
306
-
if (twoFactorCode === null) {
307
-
await oldAgent.login({identifier: oldHandle, password: oldPassword});
308
-
} else {
309
-
await oldAgent.login({identifier: oldHandle, password: oldPassword, authFactorToken: twoFactorCode});
310
-
}
311
-
safeStatusUpdate(statusUpdateHandler, 'Checking this isn\'t your current PDS');
312
-
if (pdsBeforeCurrent === currentPds) {
313
-
throw new Error('This is your current PDS. Login to your old account username and password');
314
-
}
315
-
316
-
let currentAccountStatus = await oldAgent.com.atproto.server.checkAccountStatus();
317
-
if (!currentAccountStatus.data.activated) {
318
-
safeStatusUpdate(statusUpdateHandler, 'All good. Your old account is not activated.');
319
-
}
320
-
safeStatusUpdate(statusUpdateHandler, 'Deactivating your OLD account');
321
-
await oldAgent.com.atproto.server.deactivateAccount({});
322
-
safeStatusUpdate(statusUpdateHandler, 'Successfully deactivated your OLD account');
323
-
}
324
-
325
-
async signUpForBackupsFromMigration() {
326
-
// Use a plain fetch POST with atproto-proxy header and bearer from the new agent
327
-
const didWeb = await fetchPDSMooverDIDWeb(window.location.origin);
328
-
329
-
const url = `${this.newAgent.serviceUrl.origin}/xrpc/com.pdsmoover.backup.signUp`;
330
-
331
-
const accessJwt = this.newAgent?.session?.accessJwt;
332
-
if (!accessJwt) {
333
-
throw new Error('Missing access token for authorization');
334
-
}
335
-
336
-
const res = await fetch(url, {
337
-
method: 'POST',
338
-
headers: {
339
-
'Authorization': `Bearer ${accessJwt}`,
340
-
'Content-Type': 'application/json',
341
-
'Accept': 'application/json',
342
-
'atproto-proxy': `${didWeb}#repo_backup`,
343
-
},
344
-
body: JSON.stringify({}),
345
-
});
346
-
347
-
if (!res.ok) {
348
-
let bodyText = '';
349
-
try {
350
-
bodyText = await res.text();
351
-
} catch {
352
-
}
353
-
throw new Error(`Backup signup failed: ${res.status} ${res.statusText}${bodyText ? ` - ${bodyText}` : ''}`);
354
-
}
355
-
356
-
//No return the success is all that is needed, if there's an error it will throw
357
-
}
358
-
}
359
-
360
-
export {Migrator};
361
-
-280
web/ui-code/src/plc-ops.js
-280
web/ui-code/src/plc-ops.js
···
1
-
import {defs, normalizeOp} from '@atcute/did-plc';
2
-
import {P256PrivateKey, parsePrivateMultikey, Secp256k1PrivateKey, Secp256k1PrivateKeyExportable} from '@atcute/crypto';
3
-
import * as CBOR from '@atcute/cbor';
4
-
import {fromBase16, toBase64Url} from '@atcute/multibase';
5
-
6
-
//NOTES
7
-
// Don't forget disputes can check https://github.dev/mary-ext/boat/blob/trunk/src/views/identity/plc-applicator/steps/step1_handle-input.tsx
8
-
//This is if a previous operation should be disputed, it will be a check box on recovery
9
-
10
-
const PLC_DIRECTORY_URL = 'https://plc.directory';
11
-
12
-
13
-
// Helper to base64url-encode JSON
14
-
const jsonToB64Url = (obj) => {
15
-
const enc = new TextEncoder();
16
-
const json = JSON.stringify(obj);
17
-
return toBase64Url(enc.encode(json));
18
-
};
19
-
20
-
class PlcOps {
21
-
constructor() {
22
-
23
-
}
24
-
25
-
//TODO ui
26
-
// For unvaldiating a record in 72hr window add an advance option input for that cid
27
-
//that will be the easiest way at launch and just help ppl
28
-
29
-
//NEEDS
30
-
// Function to get current rotation keys
31
-
// function to create a new key
32
-
// function to add a new key and save and submit
33
-
// Can use that same function for signing a recover
34
-
35
-
async testSignAServiceAuthToken(did) {
36
-
//
37
-
const testPrivateKey = 'z3vLhP9c6gwUUwA4jkyYE9SXifE7wD1f3rVMMLmqBq8TaT2B';
38
-
let signingKeypair = await this.getKeyPair(testPrivateKey);
39
-
let test = await this.createANewServiceAuthToken(did, 'did:web:dev.pdsmoover.com', signingKeypair.keypair, 'com.pdsmoover.backup.requestBackup');
40
-
console.log(test);
41
-
}
42
-
43
-
44
-
async exampleOfSigningAPLCOPManuallyThatWorks() {
45
-
//dev keys
46
-
// New Rotation Key: did:key:zQ3shXuksWLbyTTbWrSJ41qZvR2eyNFGTdbjjG3b2MWRo5cSx
47
-
// New Private Key: z3vLhP9c6gwUUwA4jkyYE9SXifE7wD1f3rVMMLmqBq8TaT2B
48
-
const testPrivateKey = 'z3vLhP9c6gwUUwA4jkyYE9SXifE7wD1f3rVMMLmqBq8TaT2B';
49
-
let signingKeypair = await this.getKeyPair(testPrivateKey);
50
-
let {lastOperation, base} = await this.getLastPlcOpFromPlc(did);
51
-
console.log(lastOperation);
52
-
let {privateKey, publicKey} = await this.createANewSecp256k1();
53
-
console.log('New Rotation Key:', publicKey);
54
-
console.log('New Private Key:', privateKey);
55
-
let newRotationKeys = lastOperation.rotationKeys || [];
56
-
//Adds the new one to the top
57
-
newRotationKeys.unshift(publicKey);
58
-
await this.signAndPublishNewOp(did, signingKeypair.keypair, lastOperation.alsoKnownAs, newRotationKeys, lastOperation.services.atproto_pds.endpoint, lastOperation.verificationMethods.atproto, base.cid);
59
-
60
-
}
61
-
62
-
async getCurrentRotationKeysForUser(did) {
63
-
const logs = await this.getPlcAuditLogs(did);
64
-
const {rotationKeys} = this.getLastPlcOp(logs);
65
-
return rotationKeys;
66
-
}
67
-
68
-
async getLastPlcOpFromPlc(did) {
69
-
const logs = await this.getPlcAuditLogs(did);
70
-
return this.getLastPlcOp(logs);
71
-
}
72
-
73
-
getLastPlcOp(logs) {
74
-
const lastOp = logs.at(-1);
75
-
return {lastOperation: normalizeOp(lastOp.operation), base: lastOp};
76
-
}
77
-
78
-
79
-
async getPlcAuditLogs(did) {
80
-
const response = await fetch(`${PLC_DIRECTORY_URL}/${did}/log/audit`);
81
-
if (!response.ok) {
82
-
throw new Error(`got resposne ${response.status}`);
83
-
}
84
-
85
-
const json = await response.json();
86
-
return defs.indexedEntryLog.parse(json);
87
-
}
88
-
89
-
/**
90
-
* Creates a new secp256k1 key that can be used for either rotation or verification key
91
-
* @returns {Promise<{privateKey: string, publicKey: `did:key:${string}`}>}
92
-
*/
93
-
94
-
async createANewSecp256k1() {
95
-
let keypair = await Secp256k1PrivateKeyExportable.createKeypair();
96
-
let publicKey = await keypair.exportPublicKey('did');
97
-
let privateKey = await keypair.exportPrivateKey('multikey');
98
-
return {
99
-
privateKey,
100
-
publicKey
101
-
};
102
-
}
103
-
104
-
105
-
/**
106
-
* Signs a new operation with the provided signing key and submits it
107
-
* @param did
108
-
* @param signingRotationKey
109
-
* @param alsoKnownAs
110
-
* @param rotationKeys
111
-
* @param pds
112
-
* @param verificationKey
113
-
* @returns {Promise<void>}
114
-
*/
115
-
async signAndPublishNewOp(did, signingRotationKey, alsoKnownAs, rotationKeys, pds, verificationKey, prev) {
116
-
const operation = {
117
-
type: 'plc_operation',
118
-
// prev: prev!.cid,
119
-
prev,
120
-
alsoKnownAs,
121
-
rotationKeys,
122
-
services: {
123
-
atproto_pds: {
124
-
type: 'AtprotoPersonalDataServer',
125
-
endpoint: pds
126
-
}
127
-
},
128
-
verificationMethods: {
129
-
atproto: verificationKey
130
-
}
131
-
};
132
-
const opBytes = CBOR.encode(operation);
133
-
const sigBytes = await signingRotationKey.sign(opBytes);
134
-
135
-
const signature = toBase64Url(sigBytes);
136
-
137
-
const signedOperation = {
138
-
...operation,
139
-
sig: signature,
140
-
};
141
-
142
-
await this.pushPlcOperation(did, signedOperation);
143
-
}
144
-
145
-
/**
146
-
* Takes a multi or hexbased private key and returns a keypair
147
-
* @param privateKeyString
148
-
* @param type
149
-
* @returns {Promise<{type: string, didPublicKey: `did:key:${string}`, keypair: P256PrivateKey|Secp256k1PrivateKey}>}
150
-
*/
151
-
async getKeyPair(privateKeyString, type = 'p256') {
152
-
const HEX_REGEX = /^[0-9a-f]+$/i;
153
-
const MULTIKEY_REGEX = /^z[a-km-zA-HJ-NP-Z1-9]+$/;
154
-
let keypair = undefined;
155
-
156
-
if (HEX_REGEX.test(privateKeyString)) {
157
-
const privateKeyBytes = fromBase16(privateKeyString);
158
-
159
-
switch (type) {
160
-
case 'p256': {
161
-
keypair = await P256PrivateKey.importRaw(privateKeyBytes);
162
-
break;
163
-
}
164
-
case 'secp256k1': {
165
-
keypair = await Secp256k1PrivateKey.importRaw(privateKeyBytes);
166
-
break;
167
-
}
168
-
default: {
169
-
throw new Error(`unsupported "${type}" type`);
170
-
}
171
-
}
172
-
} else if (MULTIKEY_REGEX.test(privateKeyString)) {
173
-
174
-
const match = parsePrivateMultikey(privateKeyString);
175
-
console.log(match);
176
-
const privateKeyBytes = match.privateKeyBytes;
177
-
178
-
switch (match.type) {
179
-
case 'p256': {
180
-
keypair = await P256PrivateKey.importRaw(privateKeyBytes);
181
-
console.log(keypair);
182
-
break;
183
-
}
184
-
case 'secp256k1': {
185
-
keypair = await Secp256k1PrivateKey.importRaw(privateKeyBytes);
186
-
break;
187
-
}
188
-
default: {
189
-
throw new Error(`unsupported "${type}" type`);
190
-
}
191
-
}
192
-
} else {
193
-
throw new Error('unknown input format');
194
-
}
195
-
196
-
return {
197
-
type: 'private_key',
198
-
didPublicKey: await keypair.exportPublicKey('did'),
199
-
keypair: keypair,
200
-
};
201
-
}
202
-
203
-
async pushPlcOperation(did, operation) {
204
-
const response = await fetch(`${PLC_DIRECTORY_URL}/${did}`, {
205
-
method: 'post',
206
-
headers: {
207
-
'content-type': 'application/json',
208
-
},
209
-
body: JSON.stringify(operation),
210
-
});
211
-
212
-
const headers = response.headers;
213
-
if (!response.ok) {
214
-
const type = headers.get('content-type');
215
-
216
-
if (type?.includes('application/json')) {
217
-
const json = await response.json();
218
-
if (typeof json === 'object' && json !== null && typeof json.message === 'string') {
219
-
throw new Error(json.message);
220
-
}
221
-
}
222
-
223
-
throw new Error(`got http ${response.status} from plc`);
224
-
}
225
-
};
226
-
227
-
228
-
/**
229
-
*
230
-
* @param iss The user's did
231
-
* @param aud The did:web, if it's a PDS it's usually from /xrpc/com.atproto.server.describeServer
232
-
* @param keypair The keypair to sign with only supporting ES256K atm
233
-
* @param lxm The lxm which is usually com.atproto.server.createAccount for creating a new account
234
-
* @returns {Promise<string>}
235
-
*/
236
-
async createANewServiceAuthToken(iss, aud, keypair, lxm) {
237
-
238
-
239
-
// Compute iat/exp defaults (60s window like reference: MINUTE/1e3)
240
-
const iat = Math.floor(Date.now() / 1e3);
241
-
const exp = iat + 60;
242
-
243
-
// Generate a 16-byte hex jti
244
-
const jti = (() => {
245
-
const bytes = new Uint8Array(16);
246
-
// crypto in browser or node; fall back safely
247
-
(globalThis.crypto || window.crypto).getRandomValues(bytes);
248
-
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
249
-
})();
250
-
251
-
252
-
// Build header and payload (omit undefined fields)
253
-
// Just defaulting to ES256K since p256 was not importing on firefox
254
-
const header = {typ: 'JWT', alg: 'ES256K'};
255
-
const payload = {};
256
-
payload.iat = iat;
257
-
payload.iss = iss;
258
-
payload.aud = aud;
259
-
payload.exp = exp;
260
-
payload.lxm = lxm;
261
-
payload.jti = jti;
262
-
263
-
const headerB64 = jsonToB64Url(header);
264
-
const payloadB64 = jsonToB64Url(payload);
265
-
const toSignStr = `${headerB64}.${payloadB64}`;
266
-
267
-
// Sign
268
-
const toSignBytes = new TextEncoder().encode(toSignStr);
269
-
const sigBytes = await keypair.sign(toSignBytes);
270
-
271
-
// Return compact JWS
272
-
const sigB64 = toBase64Url(sigBytes);
273
-
return `${toSignStr}.${sigB64}`;
274
-
}
275
-
276
-
277
-
}
278
-
279
-
280
-
export {PlcOps};
-254
web/ui-code/src/restore.js
-254
web/ui-code/src/restore.js
···
1
-
import {handleAndPDSResolver} from './atprotoUtils.js';
2
-
import {PlcOps} from './plc-ops.js';
3
-
import {normalizeOp, Operation} from '@atcute/did-plc';
4
-
import {AtpAgent} from '@atproto/api';
5
-
import {Secp256k1PrivateKeyExportable} from '@atcute/crypto';
6
-
import * as CBOR from '@atcute/cbor';
7
-
import {toBase64Url} from '@atcute/multibase';
8
-
9
-
class Restore {
10
-
11
-
constructor() {
12
-
/** @type {PlcOps} */
13
-
this.plcOps = new PlcOps();
14
-
this.tempVerificationKeypair = null;
15
-
/** @type {AtpAgent} */
16
-
this.atpAgent = null;
17
-
this.recoveryRotationKeyPair = null;
18
-
//Feature flags
19
-
this.justRestoreFiles = false;
20
-
}
21
-
22
-
async recover(
23
-
rotationKey,
24
-
currentHandle,
25
-
newPDS,
26
-
newHandle,
27
-
newPassword,
28
-
newEmail,
29
-
inviteCode,
30
-
cidToRestoreTo = null,
31
-
onStatus = null) {
32
-
33
-
34
-
if (onStatus) onStatus('Resolving your handle...');
35
-
36
-
let {usersDid} = await handleAndPDSResolver(currentHandle);
37
-
38
-
if (onStatus) onStatus('Checking that the new PDS is an actual PDS (if the url is wrong, this takes a while to error out)');
39
-
this.atpAgent = new AtpAgent({service: newPDS});
40
-
const newHostDesc = await this.atpAgent.com.atproto.server.describeServer();
41
-
42
-
43
-
//Check to see if the user already has a repo on the new PDS, if they do no reason to try and restore via the plc operations
44
-
try {
45
-
await this.atpAgent.com.atproto.repo.describeRepo({repo: usersDid.toString()});
46
-
//If we got this far and there is a repo on the new PDS with the users did, we can just move on and restore the files
47
-
this.justRestoreFiles = true;
48
-
49
-
} catch (error) {
50
-
console.error(error);
51
-
let parsedError = error.error;
52
-
if (parsedError === 'RepoDeactivated') {
53
-
//Ideally should mean they already have a repo on the new PDS and we just need to restore the files
54
-
this.justRestoreFiles = true;
55
-
}
56
-
//This is the error we want to see, anything else throw
57
-
if (parsedError !== 'RepoNotFound') {
58
-
throw error;
59
-
}
60
-
}
61
-
62
-
//We need to double check that the new handle has not been taken, if it has we need to throw an error
63
-
//We care a bit more because we do not want any unnecessary plc ops to be created
64
-
try {
65
-
let resolveHandle = await this.atpAgent.com.atproto.identity.resolveHandle({handle: newHandle});
66
-
if (resolveHandle.data.did === usersDid.toString()) {
67
-
//Ideally shouldn't get here without the checks above. But we do not need to create a new account or do plc ops. It should already be there
68
-
this.justRestoreFiles = true;
69
-
} else {
70
-
//There is a repo with that name and it's not the users did,
71
-
throw new Error('The new handle is already taken, please select a different handle');
72
-
}
73
-
} catch (error) {
74
-
// Going to silently log this and just assume the handle has not been taken.
75
-
console.error(error);
76
-
if (error.message.startsWith('The new handle')) {
77
-
//it's not our custom error, so we can just throw it
78
-
throw error;
79
-
}
80
-
81
-
}
82
-
83
-
if (!this.justRestoreFiles) {
84
-
85
-
if (onStatus) onStatus('Validating your private rotation key is in the correct format...');
86
-
this.recoveryRotationKeyPair = await this.plcOps.getKeyPair(rotationKey);
87
-
88
-
89
-
if (onStatus) onStatus('Resolving PlC operation logs...');
90
-
91
-
/** @type {Operation} */
92
-
let baseOpForSigning = null;
93
-
let opPrevCid = null;
94
-
95
-
//This is for reversals against a rogue plc op and you want to restore to a specific cid in the audit log
96
-
if (cidToRestoreTo) {
97
-
let auditLogs = await this.plcOps.getPlcAuditLogs(usersDid);
98
-
for (const log of auditLogs) {
99
-
if (log.cid === cidToRestoreTo) {
100
-
baseOpForSigning = normalizeOp(log.operation);
101
-
opPrevCid = log.cid;
102
-
break;
103
-
}
104
-
}
105
-
if (!baseOpForSigning) {
106
-
throw new Error('Could not find the cid in the audit logs');
107
-
}
108
-
} else {
109
-
let {lastOperation, base} = await this.plcOps.getLastPlcOpFromPlc(usersDid);
110
-
opPrevCid = base.cid;
111
-
baseOpForSigning = lastOperation;
112
-
}
113
-
114
-
if (onStatus) onStatus('Preparing to switch to a temp atproto key...');
115
-
if (this.tempVerificationKeypair == null) {
116
-
if (onStatus) onStatus('Creating a new temp atproto key...');
117
-
this.tempVerificationKeypair = await Secp256k1PrivateKeyExportable.createKeypair();
118
-
}
119
-
//Just defaulting to the user's recovery key for now. Advance cases will be something else
120
-
//Maybe just a new ui to edit the PLC doc in a limited capacity, but sinc ethis is a temp plc op i don't think it's needed
121
-
let tempRotationKeys = [this.recoveryRotationKeyPair.didPublicKey];
122
-
123
-
if (onStatus) onStatus('Modifying the PLC OP for recovery...');
124
-
//A temp plc op for control of the atproto key to create a serviceAuth and new account on the new PDS
125
-
await this.plcOps.signAndPublishNewOp(
126
-
usersDid,
127
-
this.recoveryRotationKeyPair.keypair,
128
-
baseOpForSigning.alsoKnownAs,
129
-
tempRotationKeys,
130
-
newPDS,
131
-
await this.tempVerificationKeypair.exportPublicKey('did'),
132
-
opPrevCid);
133
-
134
-
135
-
if (onStatus) onStatus('Creating your new account on the new PDS...');
136
-
let serviceAuthToken = await this.plcOps.createANewServiceAuthToken(usersDid, newHostDesc.data.did, this.tempVerificationKeypair, 'com.atproto.server.createAccount');
137
-
138
-
let createAccountRequest = {
139
-
did: usersDid,
140
-
handle: newHandle,
141
-
email: newEmail,
142
-
password: newPassword,
143
-
};
144
-
if (inviteCode) {
145
-
createAccountRequest.inviteCode = inviteCode;
146
-
}
147
-
const _ = await this.atpAgent.com.atproto.server.createAccount(
148
-
createAccountRequest,
149
-
{
150
-
headers: {authorization: `Bearer ${serviceAuthToken}`},
151
-
encoding: 'application/json',
152
-
});
153
-
}
154
-
155
-
await this.atpAgent.login({
156
-
identifier: usersDid,
157
-
password: newPassword,
158
-
});
159
-
160
-
if (!this.justRestoreFiles) {
161
-
//Moving the user offically to the new PDS
162
-
if (onStatus) onStatus('Signing the papers...');
163
-
let {base} = await this.plcOps.getLastPlcOpFromPlc(usersDid);
164
-
await this.signRestorePlcOperation(usersDid, [this.recoveryRotationKeyPair.didPublicKey], base.cid);
165
-
}
166
-
167
-
if (onStatus) onStatus('Success! Restoring your repo...');
168
-
const pdsMoover = new AtpAgent({service: window.location.origin});
169
-
const repoRes = await pdsMoover.com.atproto.sync.getRepo({did: usersDid});
170
-
await this.atpAgent.com.atproto.repo.importRepo(repoRes.data, {
171
-
encoding: 'application/vnd.ipld.car',
172
-
});
173
-
174
-
if (onStatus) onStatus('Restoring your blobs...');
175
-
176
-
//Using the missing endpoint to findout what's missing then the PDS MOOver endpoint to restore
177
-
let totalMissingBlobs = 0;
178
-
let missingBlobCursor = undefined;
179
-
let missingUploadedBlobs = 0;
180
-
181
-
do {
182
-
183
-
const missingBlobs = await this.atpAgent.com.atproto.repo.listMissingBlobs({
184
-
cursor: missingBlobCursor,
185
-
limit: 1000,
186
-
});
187
-
totalMissingBlobs += missingBlobs.data.blobs.length;
188
-
189
-
for (const recordBlob of missingBlobs.data.blobs) {
190
-
try {
191
-
192
-
const blobRes = await pdsMoover.com.atproto.sync.getBlob({
193
-
did: usersDid,
194
-
cid: recordBlob.cid,
195
-
});
196
-
let result = await this.atpAgent.com.atproto.repo.uploadBlob(blobRes.data, {
197
-
encoding: blobRes.headers['content-type'],
198
-
});
199
-
200
-
201
-
if (missingUploadedBlobs % 2 === 0) {
202
-
if (onStatus) onStatus(`Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs} (The total may increase as we find more)`);
203
-
}
204
-
missingUploadedBlobs++;
205
-
} catch (error) {
206
-
console.error(error);
207
-
}
208
-
}
209
-
missingBlobCursor = missingBlobs.data.cursor;
210
-
} while (missingBlobCursor);
211
-
212
-
const accountStatus = await this.atpAgent.com.atproto.server.checkAccountStatus();
213
-
if (!accountStatus.data.activated) {
214
-
if (onStatus) onStatus('Activating your account...');
215
-
await this.atpAgent.com.atproto.server.activateAccount();
216
-
}
217
-
}
218
-
219
-
async signRestorePlcOperation(usersDid, additionalRotationKeysToAdd = [], prevCid) {
220
-
const getDidCredentials =
221
-
await this.atpAgent.com.atproto.identity.getRecommendedDidCredentials();
222
-
console.log(getDidCredentials);
223
-
224
-
const pdsProvidedRotationKeys = getDidCredentials.data.rotationKeys ?? [];
225
-
// Prepend any additional rotation keys (e.g., user-added keys, newly created key) so they appear above the new PDS rotation key
226
-
const rotationKeys = [...(additionalRotationKeysToAdd || []), ...pdsProvidedRotationKeys];
227
-
if (!rotationKeys) {
228
-
throw new Error('No rotation key provided from the new PDS');
229
-
}
230
-
const plcOpToSubmit = {
231
-
type: 'plc_operation',
232
-
...getDidCredentials.data,
233
-
prev: prevCid,
234
-
rotationKeys: rotationKeys,
235
-
};
236
-
237
-
238
-
const opBytes = CBOR.encode(plcOpToSubmit);
239
-
const sigBytes = await this.recoveryRotationKeyPair.keypair.sign(opBytes);
240
-
241
-
const signature = toBase64Url(sigBytes);
242
-
243
-
const signedOperation = {
244
-
...plcOpToSubmit,
245
-
sig: signature,
246
-
};
247
-
248
-
await this.plcOps.pushPlcOperation(usersDid, signedOperation);
249
-
await this.atpAgent.com.atproto.server.activateAccount();
250
-
251
-
}
252
-
}
253
-
254
-
export {Restore};
-28
web/ui-code/src/utils.js
-28
web/ui-code/src/utils.js
···
1
-
class MooverUtils {
2
-
formatDate(value) {
3
-
if (!value) return '—';
4
-
try {
5
-
const d = new Date(value);
6
-
return d.toLocaleString();
7
-
} catch (err) {
8
-
console.error(err);
9
-
return String(value);
10
-
}
11
-
}
12
-
13
-
formatBytes(bytes) {
14
-
if (bytes == null) return '—';
15
-
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
16
-
let i = 0;
17
-
let v = Number(bytes);
18
-
while (v >= 1024 && i < units.length - 1) {
19
-
v /= 1024;
20
-
i++;
21
-
}
22
-
return v.toFixed(1) + ' ' + units[i];
23
-
}
24
-
25
-
}
26
-
27
-
28
-
export {MooverUtils};
-31
web/ui-code/vite.config.js
-31
web/ui-code/vite.config.js
···
1
-
import {defineConfig} from 'vite';
2
-
import rustVitePlugin from 'vite-rs-plugin';
3
-
4
-
5
-
export default defineConfig({
6
-
port: 5173,
7
-
plugins: [
8
-
rustVitePlugin({
9
-
refresh: './src/**.*',
10
-
entrypoints: [
11
-
'src/main.js',
12
-
'src/pdsmoover.js',
13
-
'src/missingBlobs.js',
14
-
'src/atprotoUtils.js',
15
-
'src/backup.js',
16
-
],
17
-
assetsEndpoint: '/',
18
-
})
19
-
],
20
-
build: {
21
-
rollupOptions: {
22
-
input: ['index.html'],
23
-
},
24
-
},
25
-
// Uncomment this section if you're going to use `start_dev_server` in Rust:
26
-
// server: {
27
-
// hmr: {
28
-
// port: 21012,
29
-
// },
30
-
// },
31
-
});