- Uses slingshot first to try and find the did, pds
- If the repo is already created it conts on with the migration
+5559
-1813
Diff
round #0
+8
.oxfmtrc.json
+8
.oxfmtrc.json
+113
.oxlintrc.json
+113
.oxlintrc.json
···
1
+
{
2
+
"$schema": "https://unpkg.com/oxlint/configuration_schema.json",
3
+
"plugins": ["unicorn", "typescript", "oxc", "vue", "vitest"],
4
+
"jsPlugins": ["@e18e/eslint-plugin", "eslint-plugin-regexp"],
5
+
"categories": {
6
+
"correctness": "error",
7
+
"suspicious": "warn",
8
+
"perf": "warn"
9
+
},
10
+
"rules": {
11
+
"no-console": "warn",
12
+
"no-await-in-loop": "off",
13
+
"unicorn/no-array-sort": "off",
14
+
"no-restricted-globals": "error",
15
+
"typescript/consistent-type-imports": "error",
16
+
"e18e/prefer-array-from-map": "error",
17
+
"e18e/prefer-timer-args": "error",
18
+
"e18e/prefer-date-now": "error",
19
+
"e18e/prefer-regex-test": "error",
20
+
"e18e/prefer-array-some": "error",
21
+
// RegExp - Possible Errors (most critical)
22
+
"regexp/no-contradiction-with-assertion": "error",
23
+
"regexp/no-dupe-disjunctions": "error",
24
+
"regexp/no-empty-alternative": "error",
25
+
"regexp/no-empty-capturing-group": "error",
26
+
"regexp/no-empty-character-class": "error",
27
+
"regexp/no-empty-group": "error",
28
+
"regexp/no-empty-lookarounds-assertion": "error",
29
+
"regexp/no-escape-backspace": "error",
30
+
"regexp/no-invalid-regexp": "error",
31
+
"regexp/no-lazy-ends": "error",
32
+
"regexp/no-misleading-capturing-group": "error",
33
+
"regexp/no-misleading-unicode-character": "error",
34
+
"regexp/no-missing-g-flag": "error",
35
+
"regexp/no-optional-assertion": "error",
36
+
"regexp/no-potentially-useless-backreference": "error",
37
+
"regexp/no-super-linear-backtracking": "error",
38
+
"regexp/no-useless-assertions": "error",
39
+
"regexp/no-useless-backreference": "error",
40
+
"regexp/no-useless-dollar-replacements": "error",
41
+
"regexp/strict": "error",
42
+
// RegExp - Best Practices
43
+
"regexp/confusing-quantifier": "warn",
44
+
"regexp/control-character-escape": "error",
45
+
"regexp/negation": "error",
46
+
"regexp/no-dupe-characters-character-class": "error",
47
+
"regexp/no-empty-string-literal": "error",
48
+
"regexp/no-extra-lookaround-assertions": "error",
49
+
"regexp/no-invisible-character": "error",
50
+
"regexp/no-legacy-features": "error",
51
+
"regexp/no-non-standard-flag": "error",
52
+
"regexp/no-obscure-range": "error",
53
+
"regexp/no-octal": "error",
54
+
"regexp/no-standalone-backslash": "error",
55
+
"regexp/no-trivially-nested-assertion": "error",
56
+
"regexp/no-trivially-nested-quantifier": "error",
57
+
"regexp/no-unused-capturing-group": "warn",
58
+
"regexp/no-useless-character-class": "error",
59
+
"regexp/no-useless-flag": "error",
60
+
"regexp/no-useless-lazy": "error",
61
+
"regexp/no-useless-quantifier": "error",
62
+
"regexp/no-useless-range": "error",
63
+
"regexp/no-useless-set-operand": "error",
64
+
"regexp/no-useless-string-literal": "error",
65
+
"regexp/no-useless-two-nums-quantifier": "error",
66
+
"regexp/no-zero-quantifier": "error",
67
+
"regexp/optimal-lookaround-quantifier": "warn",
68
+
"regexp/optimal-quantifier-concatenation": "error",
69
+
"regexp/prefer-predefined-assertion": "error",
70
+
"regexp/prefer-range": "error",
71
+
"regexp/prefer-set-operation": "error",
72
+
"regexp/simplify-set-operations": "error",
73
+
"regexp/use-ignore-case": "error",
74
+
// RegExp - Stylistic Issues (less critical, focused on consistency)
75
+
"regexp/match-any": "warn",
76
+
"regexp/no-useless-escape": "warn",
77
+
"regexp/no-useless-non-capturing-group": "warn",
78
+
"regexp/prefer-character-class": "warn",
79
+
"regexp/prefer-d": "warn",
80
+
"regexp/prefer-plus-quantifier": "warn",
81
+
"regexp/prefer-question-quantifier": "warn",
82
+
"regexp/prefer-star-quantifier": "warn",
83
+
"regexp/prefer-unicode-codepoint-escapes": "warn",
84
+
"regexp/prefer-w": "warn",
85
+
"regexp/sort-flags": "warn"
86
+
},
87
+
"overrides": [
88
+
{
89
+
"files": [
90
+
"server/**/*",
91
+
"cli/**/*",
92
+
"scripts/**/*",
93
+
"modules/**/*",
94
+
"app/components/OgImage/*"
95
+
],
96
+
"rules": {
97
+
"no-console": "off"
98
+
}
99
+
}
100
+
],
101
+
"ignorePatterns": [
102
+
".output/**",
103
+
".data/**",
104
+
".nuxt/**",
105
+
".nitro/**",
106
+
".cache/**",
107
+
"dist/**",
108
+
"node_modules/**",
109
+
"coverage/**",
110
+
"playwright-report/**",
111
+
"test-results/**"
112
+
]
113
+
}
+100
.zed/settings.json
+100
.zed/settings.json
···
1
+
{
2
+
"lsp": {
3
+
"oxlint": {
4
+
"initialization_options": {
5
+
"settings": {
6
+
"configPath": ".oxlintrc.json",
7
+
"run": "onType"
8
+
}
9
+
}
10
+
},
11
+
"oxfmt": {
12
+
"initialization_options": {
13
+
"settings": {
14
+
"run": "onSave",
15
+
"configPath": ".oxfmtrc.json"
16
+
}
17
+
}
18
+
}
19
+
},
20
+
"languages": {
21
+
"TypeScript": {
22
+
"format_on_save": "on",
23
+
"prettier": {
24
+
"allowed": false
25
+
},
26
+
"formatter": [
27
+
{
28
+
"language_server": {
29
+
"name": "oxfmt"
30
+
}
31
+
}
32
+
]
33
+
},
34
+
"JavaScript": {
35
+
"format_on_save": "on",
36
+
"prettier": {
37
+
"allowed": false
38
+
},
39
+
"formatter": [
40
+
{
41
+
"language_server": {
42
+
"name": "oxfmt"
43
+
}
44
+
}
45
+
]
46
+
},
47
+
"Svelte": {
48
+
"format_on_save": "on",
49
+
"prettier": {
50
+
"allowed": false
51
+
},
52
+
"formatter": [
53
+
{
54
+
"language_server": {
55
+
"name": "oxfmt"
56
+
}
57
+
}
58
+
]
59
+
},
60
+
"JSON": {
61
+
"format_on_save": "on",
62
+
"prettier": {
63
+
"allowed": false
64
+
},
65
+
"formatter": [
66
+
{
67
+
"language_server": {
68
+
"name": "oxfmt"
69
+
}
70
+
}
71
+
]
72
+
},
73
+
"JSONC": {
74
+
"format_on_save": "on",
75
+
"prettier": {
76
+
"allowed": false
77
+
},
78
+
"formatter": [
79
+
{
80
+
"language_server": {
81
+
"name": "oxfmt"
82
+
}
83
+
}
84
+
]
85
+
},
86
+
"YAML": {
87
+
"format_on_save": "on",
88
+
"prettier": {
89
+
"allowed": false
90
+
},
91
+
"formatter": [
92
+
{
93
+
"language_server": {
94
+
"name": "oxfmt"
95
+
}
96
+
}
97
+
]
98
+
}
99
+
}
100
+
}
+1
-1
justfile
+1
-1
justfile
+1
-1
packages/moover/README.md
+1
-1
packages/moover/README.md
···
12
12
instance
13
13
- [MissingBlobs](./lib/missingBlobs.js) - Finds missing blobs on your old PDS and uploads them to your new PDS
14
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
15
+
- [Restore](./lib/restore.js) - Handles a recovery and restores the at proto from the backup
+9
-9
packages/moover/index.html
+9
-9
packages/moover/index.html
···
1
1
<!doctype html>
2
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"/>
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
7
<title>moover</title>
8
-
</head>
9
-
<body>
10
-
<div id="app"></div>
11
-
<script type="module" src="/lib/main.js"></script>
12
-
</body>
8
+
</head>
9
+
<body>
10
+
<div id="app"></div>
11
+
<script type="module" src="/lib/main.js"></script>
12
+
</body>
13
13
</html>
+50
packages/moover/lexicons/blue/microcosm/identity/resolveMiniDoc.json
+50
packages/moover/lexicons/blue/microcosm/identity/resolveMiniDoc.json
···
1
+
{
2
+
"id": "blue.microcosm.identity.resolveMiniDoc",
3
+
"defs": {
4
+
"main": {
5
+
"type": "query",
6
+
"output": {
7
+
"schema": {
8
+
"type": "object",
9
+
"required": ["did", "handle", "pds", "signing_key"],
10
+
"properties": {
11
+
"did": {
12
+
"type": "string",
13
+
"format": "did",
14
+
"description": "DID, bi-directionally verified if a handle was provided in the query."
15
+
},
16
+
"pds": {
17
+
"type": "string",
18
+
"format": "uri",
19
+
"description": "The identity's PDS URL"
20
+
},
21
+
"handle": {
22
+
"type": "string",
23
+
"format": "handle",
24
+
"description": "The validated handle of the account or `handle.invalid` if the handle\ndid not bi-directionally match the DID document."
25
+
},
26
+
"signing_key": {
27
+
"type": "string",
28
+
"description": "The atproto signing key publicKeyMultibase\n\nLegacy key encoding not supported. the key is returned directly; `id`,\n`type`, and `controller` are omitted."
29
+
}
30
+
}
31
+
},
32
+
"encoding": "application/json"
33
+
},
34
+
"parameters": {
35
+
"type": "params",
36
+
"required": ["identifier"],
37
+
"properties": {
38
+
"identifier": {
39
+
"type": "string",
40
+
"format": "at-identifier",
41
+
"description": "Handle or DID to resolve"
42
+
}
43
+
}
44
+
},
45
+
"description": "Like [com.atproto.identity.resolveIdentity](https://docs.bsky.app/docs/api/com-atproto-identity-resolve-identity) but instead of the full `didDoc` it returns an atproto-relevant subset."
46
+
}
47
+
},
48
+
"$type": "com.atproto.lexicon.schema",
49
+
"lexicon": 1
50
+
}
+70
-50
packages/moover/lib/atprotoUtils.js
+70
-50
packages/moover/lib/atprotoUtils.js
···
1
1
import {
2
-
CompositeDidDocumentResolver, CompositeHandleResolver,
3
-
DohJsonHandleResolver,
4
-
PlcDidDocumentResolver, WebDidDocumentResolver,
5
-
WellKnownHandleResolver
6
-
} from '@atcute/identity-resolver';
2
+
CompositeDidDocumentResolver,
3
+
CompositeHandleResolver,
4
+
DohJsonHandleResolver,
5
+
PlcDidDocumentResolver,
6
+
WebDidDocumentResolver,
7
+
WellKnownHandleResolver,
8
+
} from '@atcute/identity-resolver'
7
9
8
10
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
-
});
11
+
strategy: 'race',
12
+
methods: {
13
+
dns: new DohJsonHandleResolver({
14
+
dohUrl: 'https://mozilla.cloudflare-dns.com/dns-query',
15
+
}),
16
+
http: new WellKnownHandleResolver(),
17
+
},
18
+
})
17
19
18
20
const docResolver = new CompositeDidDocumentResolver({
19
-
methods: {
20
-
plc: new PlcDidDocumentResolver(),
21
-
web: new WebDidDocumentResolver(),
22
-
},
23
-
});
21
+
methods: {
22
+
plc: new PlcDidDocumentResolver(),
23
+
web: new WebDidDocumentResolver(),
24
+
},
25
+
})
26
+
27
+
/**
28
+
* Fetches a minidoc from slingshot
29
+
*
30
+
* @param identifier {string}
31
+
* @returns {Promise<{did: string, handle: string, pds: string}>}
32
+
*/
33
+
async function getMiniDoc(identifier) {
34
+
const result = await fetch(
35
+
`https://slingshot.microcosm.blue/xrpc/blue.microcosm.identity.resolveMiniDoc?identifier=${identifier}`,
36
+
)
37
+
if (!result.ok) {
38
+
throw new Error(`Failed to fetch minidoc: ${result.status} ${result.statusText}`)
39
+
}
40
+
return await result.json()
41
+
}
24
42
25
43
/**
26
44
* Cleans the handle of @ and some other unicode characters that used to show up when copied from the profile
27
45
* @param handle {string}
28
46
* @returns {string}
29
47
*/
30
-
const cleanHandle = (handle) =>
31
-
handle.replace('@', '').trim().replace(
32
-
/[\u202A\u202C\u200E\u200F\u2066-\u2069]/g,
33
-
'',
34
-
);
35
-
48
+
const cleanHandle = handle =>
49
+
handle
50
+
.replace('@', '')
51
+
.trim()
52
+
.replace(/[\u202A\u202C\u200E\u200F\u2066-\u2069]/g, '')
36
53
37
54
/**
38
55
* Convince helper to resolve a handle to a did and then find the PDS url from the did document.
···
41
58
* @returns {Promise<{usersDid: string, pds: string}>}
42
59
*/
43
60
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);
61
+
try {
62
+
const { did, handle: _, pds } = await getMiniDoc(handle)
63
+
return { usersDid: did, pds }
64
+
} catch (error) {
65
+
console.error('Failed to load mini doc, trying other routes', error)
66
+
}
52
67
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
-
}
68
+
let usersDid = null
69
+
if (handle.startsWith('did:')) {
70
+
usersDid = handle
71
+
} else {
72
+
const cleanedHandle = cleanHandle(handle)
73
+
usersDid = await handleResolver.resolve(cleanedHandle)
74
+
}
75
+
const didDoc = await docResolver.resolve(usersDid)
63
76
77
+
let pds
78
+
try {
79
+
pds = didDoc.service?.filter(s => s.type === 'AtprotoPersonalDataServer')[0].serviceEndpoint
80
+
} catch (error) {
81
+
throw new Error('Could not find a PDS in the DID document.')
82
+
}
83
+
return { usersDid, pds }
84
+
}
64
85
65
86
/**
66
87
* Fetches the DID Web from the .well-known/did.json endpoint of the server.
···
69
90
* @returns {Promise<*>}
70
91
*/
71
92
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;
93
+
const response = await fetch(`${baseUrl}/.well-known/did.json`)
94
+
if (!response.ok) {
95
+
throw new Error(`Failed to fetch DID document: ${response.status}`)
96
+
}
97
+
const didDoc = await response.json()
98
+
return didDoc.id
78
99
}
79
100
80
-
81
-
export {handleResolver, docResolver, cleanHandle, handleAndPDSResolver, fetchPDSMooverDIDWeb};
101
+
export { handleResolver, docResolver, cleanHandle, handleAndPDSResolver, fetchPDSMooverDIDWeb }
+221
-225
packages/moover/lib/backup.js
+221
-225
packages/moover/lib/backup.js
···
1
-
import {Client, CredentialManager, ok} from '@atcute/client';
2
-
import {handleAndPDSResolver} from './atprotoUtils.js';
1
+
import { Client, CredentialManager, ok } from '@atcute/client'
2
+
import { handleAndPDSResolver } from './atprotoUtils.js'
3
3
//Shows as unused, but is used in the return types
4
-
import {ComPdsmooverBackupDescribeServer} from '@pds-moover/lexicons';
4
+
import { ComPdsmooverBackupDescribeServer } from '@pds-moover/lexicons'
5
5
6
6
/**
7
7
* JSDoc type-only import to avoid runtime import errors in the browser.
8
8
* @typedef {import('@atcute/lexicons').InferXRPCBodyOutput} InferXRPCBodyOutput
9
9
*/
10
-
11
10
12
11
/**
13
12
* Logic to sign up and manage backups for pdsmoover.com (or your own selfhosted instance)
14
13
*/
15
14
class BackupService {
15
+
/**
16
+
*
17
+
* @param backupDidWeb {string} - The did:web for the xrpc service for backups, defaults to did:web:pdsmoover.com
18
+
*/
19
+
constructor(backupDidWeb = 'did:web:pdsmoover.com') {
16
20
/**
17
21
*
18
-
* @param backupDidWeb {string} - The did:web for the xrpc service for backups, defaults to did:web:pdsmoover.com
22
+
* @type {Client}
19
23
*/
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
-
24
+
this.atCuteClient = null
40
25
/**
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
26
*
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>}
27
+
* @type {CredentialManager}
55
28
*/
56
-
async loginAndStatus(identifier, password, onStatus = null, twoFactorCode = null) {
57
-
let {pds} = await handleAndPDSResolver(identifier);
29
+
this.atCuteCredentialManager = null
58
30
31
+
/**
32
+
* The did:web for the xrpc service for backups, defaults to pdsmoover.com
33
+
* @type {string}
34
+
*/
35
+
this.backupDidWeb = backupDidWeb
36
+
}
59
37
60
-
const manager = new CredentialManager({
61
-
service: pds
62
-
});
38
+
/**
39
+
* Logs in and returns the backup status.
40
+
* To use the rest of the BackupService, it is assumed that this has ran first,
41
+
* and the user has successfully signed up. A successful login is a returned null if the user has not signed up.
42
+
* or the backup status if they are
43
+
*
44
+
* If the server requires 2FA,
45
+
* it will throw with error.error === 'AuthFactorTokenRequired'.
46
+
* @param identifier {string} handle or did
47
+
* @param password {string}
48
+
* @param {function|null} onStatus - a function that takes a string used to update the UI.
49
+
* Like (status) => console.log(status)
50
+
* @param twoFactorCode {string|null}
51
+
*
52
+
* @returns {Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>|null>}
53
+
*/
54
+
async loginAndStatus(identifier, password, onStatus = null, twoFactorCode = null) {
55
+
let { pds } = await handleAndPDSResolver(identifier)
63
56
57
+
const manager = new CredentialManager({
58
+
service: pds,
59
+
})
64
60
65
-
const rpc = new Client({
66
-
handler: manager,
67
-
proxy: {
68
-
did: this.backupDidWeb,
69
-
serviceId: '#repo_backup'
70
-
}
71
-
});
61
+
const rpc = new Client({
62
+
handler: manager,
63
+
proxy: {
64
+
did: this.backupDidWeb,
65
+
serviceId: '#repo_backup',
66
+
},
67
+
})
72
68
73
-
try {
74
-
if (onStatus) onStatus('Signing in…');
69
+
try {
70
+
if (onStatus) onStatus('Signing in…')
75
71
76
-
let loginInput = {
77
-
identifier,
78
-
password,
72
+
let loginInput = {
73
+
identifier,
74
+
password,
75
+
}
76
+
if (twoFactorCode) {
77
+
loginInput.code = twoFactorCode
78
+
}
79
+
await manager.login(loginInput)
79
80
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
-
}
81
+
// Make the client/manager available regardless of repo status so we can sign up if needed.
82
+
this.atCuteClient = rpc
83
+
this.atCuteCredentialManager = manager
106
84
107
-
}
108
-
} catch (err) {
109
-
throw err;
85
+
if (onStatus) onStatus('Checking backup status')
86
+
const result = await rpc.get('com.pdsmoover.backup.getRepoStatus', {
87
+
params: {
88
+
did: manager.session.did.toString(),
89
+
},
90
+
})
91
+
if (result.ok) {
92
+
return result.data
93
+
} else {
94
+
switch (result.data.error) {
95
+
case 'RepoNotFound':
96
+
return null
97
+
default:
98
+
throw result.data.error
110
99
}
100
+
}
101
+
} catch (err) {
102
+
throw err
111
103
}
104
+
}
112
105
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
106
+
/**
107
+
* Signs the user up for backups with the service
108
+
* @param onStatus
109
+
* @returns {Promise<void>}
110
+
*/
111
+
async signUp(onStatus = null) {
112
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
113
+
throw new Error('Not signed in')
130
114
}
115
+
if (onStatus) onStatus('Creating backup registration…')
116
+
await ok(
117
+
this.atCuteClient.post('com.pdsmoover.backup.signUp', {
118
+
as: null,
119
+
}),
120
+
)
121
+
if (onStatus) onStatus('Backup registration complete')
122
+
//No return if successful
123
+
}
131
124
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
-
}
125
+
/**
126
+
* Requests a PLC token to be sent to the user's email, needed to add a new rotation key
127
+
* @returns {Promise<void>}
128
+
*/
129
+
async requestAPlcToken() {
130
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
131
+
throw new Error('Not signed in')
150
132
}
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
-
});
133
+
const rpc = new Client({
134
+
handler: this.atCuteCredentialManager,
135
+
})
169
136
170
-
let getDidCredentials = await rpc.get('com.atproto.identity.getRecommendedDidCredentials');
137
+
let response = await rpc.post('com.atproto.identity.requestPlcOperationSignature', {
138
+
as: null,
139
+
})
140
+
if (!response.ok) {
141
+
throw new Error(response.data?.message || 'Failed to request PLC token')
142
+
}
143
+
}
171
144
172
-
if (getDidCredentials.ok) {
173
-
const pdsProvidedRotationKeys = getDidCredentials.data.rotationKeys ?? [];
174
-
const updatedRotationKeys = [rotationKey, ...pdsProvidedRotationKeys];
145
+
/**
146
+
* Adds a new rotation to the users did document. Assumes you are already signed in.
147
+
*
148
+
* WARNING: This will overwrite any existing rotation keys with the new one at the top, and the PDS key as the second one
149
+
* @param plcToken {string} - PLC token from the user's email that was sent from requestAPlcToken
150
+
* @param rotationKey {string} - The new rotation key to add to the user's did document
151
+
* @returns {Promise<void>}
152
+
*/
153
+
async addANewRotationKey(plcToken, rotationKey) {
154
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
155
+
throw new Error('Not signed in')
156
+
}
175
157
176
-
const credentials = {
177
-
...getDidCredentials.data,
178
-
rotationKeys: updatedRotationKeys,
179
-
};
158
+
const rpc = new Client({
159
+
handler: this.atCuteCredentialManager,
160
+
})
180
161
181
-
const signDocRes = await rpc.post('com.atproto.identity.signPlcOperation', {
182
-
input: {
183
-
token: plcToken,
184
-
...credentials,
185
-
}
186
-
});
162
+
let getDidCredentials = await rpc.get('com.atproto.identity.getRecommendedDidCredentials')
187
163
188
-
if (signDocRes.ok) {
189
-
const submitDocRes = await rpc.post('com.atproto.identity.submitPlcOperation', {
190
-
input: signDocRes.data,
191
-
as: null,
192
-
});
164
+
if (getDidCredentials.ok) {
165
+
const pdsProvidedRotationKeys = getDidCredentials.data.rotationKeys ?? []
166
+
const updatedRotationKeys = [rotationKey, ...pdsProvidedRotationKeys]
193
167
194
-
if (!submitDocRes.ok) {
195
-
throw new Error(submitDocRes.data?.message || 'Failed to submit PLC operation');
196
-
}
168
+
const credentials = {
169
+
...getDidCredentials.data,
170
+
rotationKeys: updatedRotationKeys,
171
+
}
197
172
198
-
} else {
199
-
throw new Error(signDocRes.data?.message || 'Failed to sign PLC operation');
200
-
}
173
+
const signDocRes = await rpc.post('com.atproto.identity.signPlcOperation', {
174
+
input: {
175
+
token: plcToken,
176
+
...credentials,
177
+
},
178
+
})
201
179
180
+
if (signDocRes.ok) {
181
+
const submitDocRes = await rpc.post('com.atproto.identity.submitPlcOperation', {
182
+
input: signDocRes.data,
183
+
as: null,
184
+
})
202
185
203
-
} else {
204
-
throw new Error(getDidCredentials.data?.message || 'Failed to get status');
186
+
if (!submitDocRes.ok) {
187
+
throw new Error(submitDocRes.data?.message || 'Failed to submit PLC operation')
205
188
}
189
+
} else {
190
+
throw new Error(signDocRes.data?.message || 'Failed to sign PLC operation')
191
+
}
192
+
} else {
193
+
throw new Error(getDidCredentials.data?.message || 'Failed to get status')
206
194
}
195
+
}
207
196
197
+
/**
198
+
*
199
+
* Gets the current status of the user's backup repository.
200
+
*
201
+
* @param onStatus {function|null} - a function that takes a string used to update the UI.
202
+
* @returns {Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>>}
203
+
*/
204
+
async getUsersRepoStatus(onStatus = null) {
205
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
206
+
throw new Error('Not signed in')
207
+
}
208
+
if (onStatus) onStatus('Refreshing backup status…')
209
+
const result = await this.atCuteClient.get('com.pdsmoover.backup.getRepoStatus', {
210
+
params: { did: this.atCuteCredentialManager.session.did.toString() },
211
+
})
212
+
if (result.ok) {
213
+
return result.data
214
+
} else {
215
+
throw new Error(result.data?.message || 'Failed to get status')
216
+
}
217
+
}
208
218
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');
219
+
/**
220
+
* Requests a backup to be run immediately for the signed-in user. Usually does, depend on the server's backup queue
221
+
* @param onStatus
222
+
* @returns {Promise<boolean>}
223
+
*/
224
+
async runBackupNow(onStatus = null) {
225
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
226
+
throw new Error('Not signed in')
227
+
}
228
+
if (onStatus) onStatus('Requesting backup…')
229
+
const res = await this.atCuteClient.post('com.pdsmoover.backup.requestBackup', {
230
+
as: null,
231
+
data: {},
232
+
})
233
+
if (res.ok) {
234
+
if (onStatus) onStatus('Backup requested.')
235
+
return true
236
+
} else {
237
+
const err = res.data
238
+
if (err?.error === 'Timeout') {
239
+
throw {
240
+
error: 'Timeout',
241
+
message: err?.message || 'Please wait a few minutes before requesting again.',
228
242
}
243
+
}
244
+
throw new Error(err?.message || 'Failed to request backup')
229
245
}
246
+
}
230
247
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
-
}
248
+
/**
249
+
* Remove (delete) the signed-in user's backup repository. this also deletes all the user's backup data.
250
+
* @param onStatus
251
+
* @returns {Promise<boolean>}
252
+
*/
253
+
async removeRepo(onStatus = null) {
254
+
if (!this.atCuteClient || !this.atCuteCredentialManager) {
255
+
throw new Error('Not signed in')
252
256
}
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
-
}
257
+
if (onStatus) onStatus('Deleting backup repository…')
258
+
const res = await this.atCuteClient.post('com.pdsmoover.backup.removeRepo', {
259
+
as: null,
260
+
data: {},
261
+
})
262
+
if (res.ok) {
263
+
if (onStatus) onStatus('Backup repository deleted.')
264
+
return true
265
+
} else {
266
+
const err = res.data
267
+
throw new Error(err?.message || 'Failed to delete backup repository')
272
268
}
269
+
}
273
270
}
274
271
275
-
276
-
export {BackupService};
272
+
export { BackupService }
+7
-16
packages/moover/lib/main.js
+7
-16
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';
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
7
8
-
export {
9
-
Migrator,
10
-
MissingBlobs,
11
-
BackupService,
12
-
PlcOps,
13
-
Restore,
14
-
handleAndPDSResolver,
15
-
16
-
}
17
-
8
+
export { Migrator, MissingBlobs, BackupService, PlcOps, Restore, handleAndPDSResolver }
+162
-166
packages/moover/lib/missingBlobs.js
+162
-166
packages/moover/lib/missingBlobs.js
···
1
-
import {AtpAgent} from '@atproto/api';
2
-
import {handleAndPDSResolver} from './atprotoUtils.js';
3
-
1
+
import { AtpAgent } from '@atproto/api'
2
+
import { handleAndPDSResolver } from './atprotoUtils.js'
4
3
5
4
/**
6
5
* Class to help find missing blobs from the did's previous PDS and import them into the current PDS
7
6
*/
8
7
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
-
8
+
constructor() {
39
9
/**
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}>}
10
+
* The user's current PDS agent
11
+
* @type {AtpAgent}
45
12
*/
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
-
}
13
+
this.currentPdsAgent = null
14
+
/**
15
+
* The user's old PDS agent
16
+
* @type {AtpAgent}
17
+
*/
18
+
this.oldPdsAgent = null
19
+
/**
20
+
* the user's did
21
+
* @type {string|null}
22
+
*/
23
+
this.did = null
24
+
/**
25
+
* The user's current PDS url
26
+
* @type {null}
27
+
*/
28
+
this.currentPdsUrl = null
29
+
/**
30
+
* 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
31
+
* @type {string[]}
32
+
*/
33
+
this.missingBlobs = []
34
+
}
63
35
64
-
this.currentPdsAgent = agent;
36
+
/**
37
+
* Logs the user into the current PDS and gets the account status
38
+
* @param handle {string}
39
+
* @param password {string}
40
+
* @param twoFactorCode {string|null}
41
+
* @returns {Promise<{accountStatus: OutputSchema, missingBlobsCount: number}>}
42
+
*/
43
+
async currentAgentLogin(handle, password, twoFactorCode = null) {
44
+
let { usersDid, pds } = await handleAndPDSResolver(handle)
45
+
this.did = usersDid
46
+
this.currentPdsUrl = pds
47
+
const agent = new AtpAgent({
48
+
service: pds,
49
+
})
65
50
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};
51
+
if (twoFactorCode === null) {
52
+
await agent.login({ identifier: usersDid, password })
53
+
} else {
54
+
await agent.login({
55
+
identifier: usersDid,
56
+
password: password,
57
+
authFactorToken: twoFactorCode,
58
+
})
71
59
}
72
60
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;
61
+
this.currentPdsAgent = agent
88
62
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
-
}
63
+
const result = await agent.com.atproto.server.checkAccountStatus()
64
+
const missingBlobs = await this.currentPdsAgent.com.atproto.repo.listMissingBlobs({
65
+
limit: 10,
66
+
})
67
+
return { accountStatus: result.data, missingBlobsCount: missingBlobs.data.blobs.length }
68
+
}
116
69
117
-
const agent = new AtpAgent({
118
-
service: oldPds,
119
-
});
70
+
/**
71
+
* Logs into the old PDS and gets the account status.
72
+
* Does not need a handle
73
+
* since it is assumed the user has already logged in with the current PDS and we are using their did
74
+
* @param password {string}
75
+
* @param twoFactorCode {string|null}
76
+
* @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
77
+
* @returns {Promise<void>}
78
+
*/
79
+
async oldAgentLogin(password, twoFactorCode = null, pdsUrl = null) {
80
+
let oldPds = null
120
81
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});
82
+
if (pdsUrl === null) {
83
+
const response = await fetch(`https://plc.directory/${this.did}/log`)
84
+
let auditLog = await response.json()
85
+
auditLog = auditLog.reverse()
86
+
let debugCount = 0
87
+
for (const entry of auditLog) {
88
+
console.log(`Loop: ${debugCount++}`)
89
+
console.log(entry)
90
+
if (entry.services) {
91
+
if (entry.services.atproto_pds) {
92
+
if (entry.services.atproto_pds.type === 'AtprotoPersonalDataServer') {
93
+
const pds = entry.services.atproto_pds.endpoint
94
+
console.log(`Found PDS: ${pds}`)
95
+
if (pds.toLowerCase() !== this.currentPdsUrl.toLowerCase()) {
96
+
oldPds = pds
97
+
break
98
+
}
99
+
}
100
+
}
125
101
}
126
-
this.oldPdsAgent = agent;
102
+
}
103
+
if (oldPds === null) {
104
+
throw new Error('Could not find your old PDS')
105
+
}
106
+
} else {
107
+
oldPds = pdsUrl
127
108
}
128
109
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...');
110
+
const agent = new AtpAgent({
111
+
service: oldPds,
112
+
})
142
113
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 {
114
+
if (twoFactorCode === null) {
115
+
await agent.login({ identifier: this.did, password })
116
+
} else {
117
+
await agent.login({
118
+
identifier: this.did,
119
+
password: password,
120
+
authFactorToken: twoFactorCode,
121
+
})
122
+
}
123
+
this.oldPdsAgent = agent
124
+
}
157
125
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
-
});
126
+
/**
127
+
* Gets the missing blobs from the old PDS and uploads them to the current PDS
128
+
* @param statusUpdateHandler {function} - A function to update the status of the migration. This is useful for showing the user the progress of the migration
129
+
* @returns {Promise<{accountStatus: OutputSchema, missingBlobsCount: number}>}
130
+
*/
131
+
async migrateMissingBlobs(statusUpdateHandler) {
132
+
if (this.currentPdsAgent === null) {
133
+
throw new Error('Current PDS agent is not set')
134
+
}
135
+
if (this.oldPdsAgent === null) {
136
+
throw new Error('Old PDS agent is not set')
137
+
}
138
+
statusUpdateHandler('Starting to import blobs...')
165
139
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
-
}
140
+
let totalMissingBlobs = 0
141
+
let missingBlobCursor = undefined
142
+
let missingUploadedBlobs = 0
169
143
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);
144
+
do {
145
+
const missingBlobs = await this.currentPdsAgent.com.atproto.repo.listMissingBlobs({
146
+
cursor: missingBlobCursor,
147
+
limit: 1000,
148
+
})
149
+
totalMissingBlobs += missingBlobs.data.blobs.length
181
150
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};
151
+
for (const recordBlob of missingBlobs.data.blobs) {
152
+
try {
153
+
const blobRes = await this.oldPdsAgent.com.atproto.sync.getBlob({
154
+
did: this.did,
155
+
cid: recordBlob.cid,
156
+
})
157
+
let result = await this.currentPdsAgent.com.atproto.repo.uploadBlob(blobRes.data, {
158
+
encoding: blobRes.headers['content-type'],
159
+
})
187
160
161
+
if (result.status === 429) {
162
+
statusUpdateHandler(
163
+
`You are being rate limited. Will need to try again later to get the rest of the blobs. Migrated blobs: ${missingUploadedBlobs}/${totalMissingBlobs}`,
164
+
)
165
+
}
188
166
189
-
}
167
+
if (missingUploadedBlobs % 2 === 0) {
168
+
statusUpdateHandler(
169
+
`Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs} (The total may increase as we find more)`,
170
+
)
171
+
}
172
+
missingUploadedBlobs++
173
+
} catch (error) {
174
+
console.error(error)
175
+
this.missingBlobs.push(recordBlob.cid)
176
+
}
177
+
}
178
+
missingBlobCursor = missingBlobs.data.cursor
179
+
} while (missingBlobCursor)
190
180
181
+
const accountStatus = await this.currentPdsAgent.com.atproto.server.checkAccountStatus()
182
+
const missingBlobs = await this.currentPdsAgent.com.atproto.repo.listMissingBlobs({
183
+
limit: 10,
184
+
})
185
+
return { accountStatus: accountStatus.data, missingBlobsCount: missingBlobs.data.blobs.length }
186
+
}
191
187
}
192
188
193
-
export {MissingBlobs};
189
+
export { MissingBlobs }
+389
-341
packages/moover/lib/pdsmoover.js
+389
-341
packages/moover/lib/pdsmoover.js
···
1
-
import {docResolver, cleanHandle, handleResolver} from './atprotoUtils.js';
2
-
import {AtpAgent} from '@atproto/api';
3
-
1
+
import { docResolver, cleanHandle, handleResolver, handleAndPDSResolver } from './atprotoUtils.js'
2
+
import { AtpAgent } from '@atproto/api'
4
3
5
4
function safeStatusUpdate(statusUpdateHandler, status) {
6
-
if (statusUpdateHandler) {
7
-
statusUpdateHandler(status);
8
-
}
5
+
if (statusUpdateHandler) {
6
+
statusUpdateHandler(status)
7
+
}
9
8
}
10
9
11
10
/**
···
13
12
* On pdsmoover.com this is the logic for the MOOver
14
13
*/
15
14
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;
15
+
constructor() {
16
+
/** @type {AtpAgent} */
17
+
this.oldAgent = null
18
+
/** @type {AtpAgent} */
19
+
this.newAgent = null
20
+
/** @type {[string]} */
21
+
this.missingBlobs = []
22
+
//State for reruns
23
+
/** @type {boolean} */
24
+
this.createNewAccount = true
25
+
/** @type {boolean} */
26
+
this.migrateRepo = true
27
+
/** @type {boolean} */
28
+
this.migrateBlobs = true
29
+
/** @type {boolean} */
30
+
this.migrateMissingBlobs = true
31
+
/** @type {boolean} */
32
+
this.migratePrefs = true
33
+
/** @type {boolean} */
34
+
this.migratePlcRecord = true
35
+
}
36
+
37
+
/**
38
+
* This migrator is pretty cut and dry and makes a few assumptions
39
+
* 1. You are using the same password between each account
40
+
* 2. If this command fails for something like oauth 2fa code it throws an error and expects the same values when ran again.
41
+
* 3. You can control which "actions" happen by setting the class variables to false.
42
+
* 4. Each instance of the class is assumed to be for a single migration
43
+
* @param {string} oldHandle - The handle you use on your old pds, something like alice.bsky.social
44
+
* @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
45
+
* @param {string} newPdsUrl - The new URL for your pds. Like https://coolnewpds.com
46
+
* @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)
47
+
* @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.
48
+
* @param {string|null} inviteCode - The invite code you got from the PDS you are migrating to. If null does not include one
49
+
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI. Like (status) => console.log(status)
50
+
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
51
+
* @param verificationCode - Optional verification captcha code for account creation if the PDS requires it
52
+
*/
53
+
async migrate(
54
+
oldHandle,
55
+
password,
56
+
newPdsUrl,
57
+
newEmail,
58
+
newHandle,
59
+
inviteCode,
60
+
statusUpdateHandler = null,
61
+
twoFactorCode = null,
62
+
verificationCode = null,
63
+
) {
64
+
//Leaving this logic that either sets the agent to bsky.social, or the PDS since it's what I found worked best for migrations.
65
+
// handleAndPDSResolver should be able to handle it, but there have been edge cases and this was what worked best
66
+
oldHandle = cleanHandle(oldHandle)
67
+
let oldAgent
68
+
let usersDid
69
+
//If it's a bsky handle just go with the entryway and let it sort everything
70
+
if (oldHandle.endsWith('.bsky.social')) {
71
+
oldAgent = new AtpAgent({ service: 'https://bsky.social' })
72
+
const publicAgent = new AtpAgent({
73
+
service: 'https://public.api.bsky.app',
74
+
})
75
+
const resolveIdentityFromEntryway = await publicAgent.com.atproto.identity.resolveHandle({
76
+
handle: oldHandle,
77
+
})
78
+
usersDid = resolveIdentityFromEntryway.data.did
79
+
} else {
80
+
//Resolves the did and finds the did document for the old PDS
81
+
safeStatusUpdate(statusUpdateHandler, 'Resolving old PDS')
82
+
let { usersDid: didFromLookUp, pds: oldPds } = await handleAndPDSResolver(oldHandle)
83
+
usersDid = didFromLookUp
84
+
85
+
oldAgent = new AtpAgent({
86
+
service: oldPds,
87
+
})
88
+
}
89
+
90
+
safeStatusUpdate(statusUpdateHandler, 'Logging you in to the old PDS')
91
+
//Login to the old PDS
92
+
if (twoFactorCode === null) {
93
+
await oldAgent.login({ identifier: oldHandle, password })
94
+
} else {
95
+
await oldAgent.login({
96
+
identifier: oldHandle,
97
+
password: password,
98
+
authFactorToken: twoFactorCode,
99
+
})
36
100
}
37
101
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
-
* @param verificationCode - Optional verification captcha code for account creation if the PDS requires it
53
-
*/
54
-
async migrate(oldHandle, password, newPdsUrl, newEmail, newHandle, inviteCode, statusUpdateHandler = null, twoFactorCode = null, verificationCode = null) {
55
-
//Leaving this logic that either sets the agent to bsky.social, or the PDS since it's what I found worked best for migrations.
56
-
// handleAndPDSResolver should be able to handle it, but there have been edge cases and this was what worked best
57
-
oldHandle = cleanHandle(oldHandle);
58
-
let oldAgent;
59
-
let usersDid;
60
-
//If it's a bsky handle just go with the entryway and let it sort everything
61
-
if (oldHandle.endsWith('.bsky.social')) {
62
-
oldAgent = new AtpAgent({service: 'https://bsky.social'});
63
-
const publicAgent = new AtpAgent({service: 'https://public.api.bsky.app'});
64
-
const resolveIdentityFromEntryway = await publicAgent.com.atproto.identity.resolveHandle({handle: oldHandle});
65
-
usersDid = resolveIdentityFromEntryway.data.did;
102
+
safeStatusUpdate(
103
+
statusUpdateHandler,
104
+
'Checking that the new PDS is an actual PDS (if the url is wrong this takes a while to error out)',
105
+
)
106
+
const newAgent = new AtpAgent({ service: newPdsUrl })
107
+
const newHostDesc = await newAgent.com.atproto.server.describeServer()
108
+
if (this.createNewAccount) {
109
+
const newHostWebDid = newHostDesc.data.did
66
110
67
-
} else {
68
-
//Resolves the did and finds the did document for the old PDS
69
-
safeStatusUpdate(statusUpdateHandler, 'Resolving old PDS');
70
-
usersDid = await handleResolver.resolve(oldHandle);
71
-
const didDoc = await docResolver.resolve(usersDid);
72
-
safeStatusUpdate(statusUpdateHandler, 'Resolving did document and finding your current PDS URL');
111
+
safeStatusUpdate(statusUpdateHandler, 'Creating a new account on the new PDS')
73
112
74
-
let oldPds;
75
-
try {
76
-
oldPds = didDoc.service.filter(s => s.type === 'AtprotoPersonalDataServer')[0].serviceEndpoint;
77
-
} catch (error) {
78
-
console.error(error);
79
-
throw new Error('Could not find a PDS in the DID document.');
80
-
}
113
+
const createAuthResp = await oldAgent.com.atproto.server.getServiceAuth({
114
+
aud: newHostWebDid,
115
+
lxm: 'com.atproto.server.createAccount',
116
+
})
117
+
const serviceJwt = createAuthResp.data.token
81
118
82
-
oldAgent = new AtpAgent({
83
-
service: oldPds,
84
-
});
119
+
let createAccountRequest = {
120
+
did: usersDid,
121
+
handle: newHandle,
122
+
email: newEmail,
123
+
password: password,
124
+
}
125
+
if (inviteCode) {
126
+
createAccountRequest.inviteCode = inviteCode
127
+
}
128
+
if (verificationCode) {
129
+
createAccountRequest.verificationCode = verificationCode
130
+
}
131
+
try {
132
+
const createNewAccount = await newAgent.com.atproto.server.createAccount(
133
+
createAccountRequest,
134
+
{
135
+
headers: { authorization: `Bearer ${serviceJwt}` },
136
+
encoding: 'application/json',
137
+
},
138
+
)
85
139
140
+
if (createNewAccount.data.did !== usersDid.toString()) {
141
+
throw new Error('Did not create the new account with the same did as the old account')
86
142
}
87
-
88
-
safeStatusUpdate(statusUpdateHandler, 'Logging you in to the old PDS');
89
-
//Login to the old PDS
90
-
if (twoFactorCode === null) {
91
-
await oldAgent.login({identifier: oldHandle, password});
143
+
} catch (error) {
144
+
// Ideally should catch if the repo already exists, and if so silently log it and move along to the next step
145
+
if (error?.error === 'AlreadyExists') {
146
+
console.log('Repo already exists, logging in')
92
147
} else {
93
-
await oldAgent.login({identifier: oldHandle, password: password, authFactorToken: twoFactorCode});
148
+
// Catches any other error and stops the migration process
149
+
throw error
94
150
}
151
+
}
152
+
}
153
+
safeStatusUpdate(statusUpdateHandler, 'Logging in with the new account')
95
154
96
-
safeStatusUpdate(statusUpdateHandler, 'Checking that the new PDS is an actual PDS (if the url is wrong this takes a while to error out)');
97
-
const newAgent = new AtpAgent({service: newPdsUrl});
98
-
const newHostDesc = await newAgent.com.atproto.server.describeServer();
99
-
if (this.createNewAccount) {
100
-
const newHostWebDid = newHostDesc.data.did;
155
+
await newAgent.login({
156
+
identifier: usersDid,
157
+
password: password,
158
+
})
101
159
102
-
safeStatusUpdate(statusUpdateHandler, 'Creating a new account on the new PDS');
103
-
104
-
const createAuthResp = await oldAgent.com.atproto.server.getServiceAuth({
105
-
aud: newHostWebDid,
106
-
lxm: 'com.atproto.server.createAccount',
107
-
});
108
-
const serviceJwt = createAuthResp.data.token;
109
-
110
-
let createAccountRequest = {
111
-
did: usersDid,
112
-
handle: newHandle,
113
-
email: newEmail,
114
-
password: password,
115
-
};
116
-
if (inviteCode) {
117
-
createAccountRequest.inviteCode = inviteCode;
118
-
}
119
-
if (verificationCode) {
120
-
createAccountRequest.verificationCode = verificationCode;
121
-
}
122
-
const createNewAccount = await newAgent.com.atproto.server.createAccount(
123
-
createAccountRequest,
124
-
{
125
-
headers: {authorization: `Bearer ${serviceJwt}`},
126
-
encoding: 'application/json',
127
-
});
128
-
129
-
if (createNewAccount.data.did !== usersDid.toString()) {
130
-
throw new Error('Did not create the new account with the same did as the old account');
131
-
}
132
-
}
133
-
safeStatusUpdate(statusUpdateHandler, 'Logging in with the new account');
134
-
135
-
await newAgent.login({
136
-
identifier: usersDid,
137
-
password: password,
138
-
});
139
-
140
-
if (this.migrateRepo) {
141
-
safeStatusUpdate(statusUpdateHandler, 'Migrating your repo');
142
-
const repoRes = await oldAgent.com.atproto.sync.getRepo({did: usersDid});
143
-
await newAgent.com.atproto.repo.importRepo(repoRes.data, {
144
-
encoding: 'application/vnd.ipld.car',
145
-
});
146
-
}
160
+
if (this.migrateRepo) {
161
+
safeStatusUpdate(statusUpdateHandler, 'Migrating your repo')
162
+
const repoRes = await oldAgent.com.atproto.sync.getRepo({
163
+
did: usersDid,
164
+
})
165
+
await newAgent.com.atproto.repo.importRepo(repoRes.data, {
166
+
encoding: 'application/vnd.ipld.car',
167
+
})
168
+
}
147
169
148
-
let newAccountStatus = await newAgent.com.atproto.server.checkAccountStatus();
170
+
let newAccountStatus = await newAgent.com.atproto.server.checkAccountStatus()
149
171
150
-
if (this.migrateBlobs) {
151
-
safeStatusUpdate(statusUpdateHandler, 'Migrating your blobs');
172
+
if (this.migrateBlobs) {
173
+
safeStatusUpdate(statusUpdateHandler, 'Migrating your blobs')
152
174
153
-
let blobCursor = undefined;
154
-
let uploadedBlobs = 0;
155
-
do {
156
-
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${uploadedBlobs}/${newAccountStatus.data.expectedBlobs}`);
175
+
let blobCursor = undefined
176
+
let uploadedBlobs = 0
177
+
do {
178
+
safeStatusUpdate(
179
+
statusUpdateHandler,
180
+
`Migrating blobs: ${uploadedBlobs}/${newAccountStatus.data.expectedBlobs}`,
181
+
)
157
182
158
-
const listedBlobs = await oldAgent.com.atproto.sync.listBlobs({
159
-
did: usersDid,
160
-
cursor: blobCursor,
161
-
limit: 100,
162
-
});
183
+
const listedBlobs = await oldAgent.com.atproto.sync.listBlobs({
184
+
did: usersDid,
185
+
cursor: blobCursor,
186
+
limit: 100,
187
+
})
163
188
164
-
for (const cid of listedBlobs.data.cids) {
165
-
try {
166
-
const blobRes = await oldAgent.com.atproto.sync.getBlob({
167
-
did: usersDid,
168
-
cid,
169
-
});
170
-
await newAgent.com.atproto.repo.uploadBlob(blobRes.data, {
171
-
encoding: blobRes.headers['content-type'],
172
-
});
173
-
uploadedBlobs++;
174
-
if (uploadedBlobs % 10 === 0) {
175
-
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${uploadedBlobs}/${newAccountStatus.data.expectedBlobs}`);
176
-
}
177
-
} catch (error) {
178
-
console.error(error);
179
-
}
180
-
}
181
-
blobCursor = listedBlobs.data.cursor;
182
-
} while (blobCursor);
189
+
for (const cid of listedBlobs.data.cids) {
190
+
try {
191
+
const blobRes = await oldAgent.com.atproto.sync.getBlob({
192
+
did: usersDid,
193
+
cid,
194
+
})
195
+
await newAgent.com.atproto.repo.uploadBlob(blobRes.data, {
196
+
encoding: blobRes.headers['content-type'],
197
+
})
198
+
uploadedBlobs++
199
+
if (uploadedBlobs % 10 === 0) {
200
+
safeStatusUpdate(
201
+
statusUpdateHandler,
202
+
`Migrating blobs: ${uploadedBlobs}/${newAccountStatus.data.expectedBlobs}`,
203
+
)
204
+
}
205
+
} catch (error) {
206
+
console.error(error)
207
+
}
183
208
}
209
+
blobCursor = listedBlobs.data.cursor
210
+
} while (blobCursor)
211
+
}
184
212
185
-
if (this.migrateMissingBlobs) {
186
-
newAccountStatus = await newAgent.com.atproto.server.checkAccountStatus();
187
-
if (newAccountStatus.data.expectedBlobs !== newAccountStatus.data.importedBlobs) {
188
-
let totalMissingBlobs = newAccountStatus.data.expectedBlobs - newAccountStatus.data.importedBlobs;
189
-
safeStatusUpdate(statusUpdateHandler, 'Looks like there are some missing blobs. Going to try and upload them now.');
190
-
//Probably should be shared between main blob uploader, but eh
191
-
let missingBlobCursor = undefined;
192
-
let missingUploadedBlobs = 0;
193
-
do {
194
-
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs}`);
195
-
196
-
const missingBlobs = await newAgent.com.atproto.repo.listMissingBlobs({
197
-
cursor: missingBlobCursor,
198
-
limit: 100,
199
-
});
200
-
201
-
for (const recordBlob of missingBlobs.data.blobs) {
202
-
try {
213
+
if (this.migrateMissingBlobs) {
214
+
newAccountStatus = await newAgent.com.atproto.server.checkAccountStatus()
215
+
if (newAccountStatus.data.expectedBlobs !== newAccountStatus.data.importedBlobs) {
216
+
let totalMissingBlobs =
217
+
newAccountStatus.data.expectedBlobs - newAccountStatus.data.importedBlobs
218
+
safeStatusUpdate(
219
+
statusUpdateHandler,
220
+
'Looks like there are some missing blobs. Going to try and upload them now.',
221
+
)
222
+
//Probably should be shared between main blob uploader, but eh
223
+
let missingBlobCursor = undefined
224
+
let missingUploadedBlobs = 0
225
+
do {
226
+
safeStatusUpdate(
227
+
statusUpdateHandler,
228
+
`Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs}`,
229
+
)
203
230
204
-
const blobRes = await oldAgent.com.atproto.sync.getBlob({
205
-
did: usersDid,
206
-
cid: recordBlob.cid,
207
-
});
208
-
await newAgent.com.atproto.repo.uploadBlob(blobRes.data, {
209
-
encoding: blobRes.headers['content-type'],
210
-
});
211
-
if (missingUploadedBlobs % 10 === 0) {
212
-
safeStatusUpdate(statusUpdateHandler, `Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs}`);
213
-
}
214
-
missingUploadedBlobs++;
215
-
} catch (error) {
216
-
//TODO silently logging prob should list them so user can manually download
217
-
console.error(error);
218
-
this.missingBlobs.push(recordBlob.cid);
219
-
}
220
-
}
221
-
missingBlobCursor = missingBlobs.data.cursor;
222
-
} while (missingBlobCursor);
231
+
const missingBlobs = await newAgent.com.atproto.repo.listMissingBlobs({
232
+
cursor: missingBlobCursor,
233
+
limit: 100,
234
+
})
223
235
236
+
for (const recordBlob of missingBlobs.data.blobs) {
237
+
try {
238
+
const blobRes = await oldAgent.com.atproto.sync.getBlob({
239
+
did: usersDid,
240
+
cid: recordBlob.cid,
241
+
})
242
+
await newAgent.com.atproto.repo.uploadBlob(blobRes.data, {
243
+
encoding: blobRes.headers['content-type'],
244
+
})
245
+
if (missingUploadedBlobs % 10 === 0) {
246
+
safeStatusUpdate(
247
+
statusUpdateHandler,
248
+
`Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs}`,
249
+
)
250
+
}
251
+
missingUploadedBlobs++
252
+
} catch (error) {
253
+
//TODO silently logging prob should list them so user can manually download
254
+
console.error(error)
255
+
this.missingBlobs.push(recordBlob.cid)
224
256
}
225
-
}
226
-
if (this.migratePrefs) {
227
-
const prefs = await oldAgent.app.bsky.actor.getPreferences();
228
-
await newAgent.app.bsky.actor.putPreferences(prefs.data);
229
-
}
257
+
}
258
+
missingBlobCursor = missingBlobs.data.cursor
259
+
} while (missingBlobCursor)
260
+
}
261
+
}
262
+
if (this.migratePrefs) {
263
+
const prefs = await oldAgent.app.bsky.actor.getPreferences()
264
+
await newAgent.app.bsky.actor.putPreferences(prefs.data)
265
+
}
230
266
231
-
this.oldAgent = oldAgent;
232
-
this.newAgent = newAgent;
267
+
this.oldAgent = oldAgent
268
+
this.newAgent = newAgent
233
269
234
-
if (this.migratePlcRecord) {
235
-
await oldAgent.com.atproto.identity.requestPlcOperationSignature();
236
-
safeStatusUpdate(statusUpdateHandler, 'Please check your email for a PLC token');
237
-
}
270
+
if (this.migratePlcRecord) {
271
+
await oldAgent.com.atproto.identity.requestPlcOperationSignature()
272
+
safeStatusUpdate(statusUpdateHandler, 'Please check your email for a PLC token')
238
273
}
274
+
}
239
275
240
-
/**
241
-
* Sign and submits the PLC operation to officially migrate the account
242
-
* @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
243
-
* @param additionalRotationKeysToAdd {string[]} - additional rotation keys to add in addition to the ones provided by the new PDS.
244
-
* @returns {Promise<void>}
245
-
*/
246
-
async signPlcOperation(token, additionalRotationKeysToAdd = []) {
247
-
const getDidCredentials =
248
-
await this.newAgent.com.atproto.identity.getRecommendedDidCredentials();
249
-
const pdsProvidedRotationKeys = getDidCredentials.data.rotationKeys ?? [];
250
-
// Prepend any additional rotation keys (e.g., user-added keys, newly created key) so they appear above the new PDS rotation key
251
-
const rotationKeys = [...(additionalRotationKeysToAdd || []), ...pdsProvidedRotationKeys];
252
-
if (!rotationKeys) {
253
-
throw new Error('No rotation key provided from the new PDS');
254
-
}
255
-
const credentials = {
256
-
...getDidCredentials.data,
257
-
rotationKeys: rotationKeys,
258
-
};
276
+
/**
277
+
* Sign and submits the PLC operation to officially migrate the account
278
+
* @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
279
+
* @param additionalRotationKeysToAdd {string[]} - additional rotation keys to add in addition to the ones provided by the new PDS.
280
+
* @returns {Promise<void>}
281
+
*/
282
+
async signPlcOperation(token, additionalRotationKeysToAdd = []) {
283
+
const getDidCredentials =
284
+
await this.newAgent.com.atproto.identity.getRecommendedDidCredentials()
285
+
const pdsProvidedRotationKeys = getDidCredentials.data.rotationKeys ?? []
286
+
// Prepend any additional rotation keys (e.g., user-added keys, newly created key) so they appear above the new PDS rotation key
287
+
const rotationKeys = [...(additionalRotationKeysToAdd || []), ...pdsProvidedRotationKeys]
288
+
if (!rotationKeys) {
289
+
throw new Error('No rotation key provided from the new PDS')
290
+
}
291
+
const credentials = {
292
+
...getDidCredentials.data,
293
+
rotationKeys: rotationKeys,
294
+
}
259
295
296
+
const plcOp = await this.oldAgent.com.atproto.identity.signPlcOperation({
297
+
token: token,
298
+
...credentials,
299
+
})
260
300
261
-
const plcOp = await this.oldAgent.com.atproto.identity.signPlcOperation({
262
-
token: token,
263
-
...credentials,
264
-
});
301
+
await this.newAgent.com.atproto.identity.submitPlcOperation({
302
+
operation: plcOp.data.operation,
303
+
})
265
304
266
-
await this.newAgent.com.atproto.identity.submitPlcOperation({
267
-
operation: plcOp.data.operation,
268
-
});
305
+
await this.newAgent.com.atproto.server.activateAccount()
306
+
await this.oldAgent.com.atproto.server.deactivateAccount({})
307
+
}
269
308
270
-
await this.newAgent.com.atproto.server.activateAccount();
271
-
await this.oldAgent.com.atproto.server.deactivateAccount({});
309
+
/**
310
+
* Using this method assumes the Migrator class was constructed new and this was called.
311
+
* Find the user's previous PDS from the PLC op logs,
312
+
* logs in and deactivates their old account if it was found still active.
313
+
*
314
+
* @param oldHandle {string}
315
+
* @param oldPassword {string}
316
+
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI.
317
+
* Like (status) => console.log(status)
318
+
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
319
+
* @returns {Promise<void>}
320
+
*/
321
+
async deactivateOldAccount(
322
+
oldHandle,
323
+
oldPassword,
324
+
statusUpdateHandler = null,
325
+
twoFactorCode = null,
326
+
) {
327
+
//Leaving this logic that either sets the agent to bsky.social, or the PDS since it's what I found worked best for migrations.
328
+
// handleAndPDSResolver should be able to handle it, but there have been edge cases and this was what worked best oldHandle = cleanHandle(oldHandle);
329
+
let usersDid
330
+
//If it's a bsky handle just go with the entryway and let it sort everything
331
+
if (oldHandle.endsWith('.bsky.social')) {
332
+
const publicAgent = new AtpAgent({
333
+
service: 'https://public.api.bsky.app',
334
+
})
335
+
const resolveIdentityFromEntryway = await publicAgent.com.atproto.identity.resolveHandle({
336
+
handle: oldHandle,
337
+
})
338
+
usersDid = resolveIdentityFromEntryway.data.did
339
+
} else {
340
+
//Resolves the did and finds the did document for the old PDS
341
+
safeStatusUpdate(statusUpdateHandler, 'Resolving did from handle')
342
+
usersDid = await handleResolver.resolve(oldHandle)
272
343
}
273
344
274
-
/**
275
-
* Using this method assumes the Migrator class was constructed new and this was called.
276
-
* Find the user's previous PDS from the PLC op logs,
277
-
* logs in and deactivates their old account if it was found still active.
278
-
*
279
-
* @param oldHandle {string}
280
-
* @param oldPassword {string}
281
-
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI.
282
-
* Like (status) => console.log(status)
283
-
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
284
-
* @returns {Promise<void>}
285
-
*/
286
-
async deactivateOldAccount(oldHandle, oldPassword, statusUpdateHandler = null, twoFactorCode = null) {
287
-
//Leaving this logic that either sets the agent to bsky.social, or the PDS since it's what I found worked best for migrations.
288
-
// handleAndPDSResolver should be able to handle it, but there have been edge cases and this was what worked best oldHandle = cleanHandle(oldHandle);
289
-
let usersDid;
290
-
//If it's a bsky handle just go with the entryway and let it sort everything
291
-
if (oldHandle.endsWith('.bsky.social')) {
292
-
const publicAgent = new AtpAgent({service: 'https://public.api.bsky.app'});
293
-
const resolveIdentityFromEntryway = await publicAgent.com.atproto.identity.resolveHandle({handle: oldHandle});
294
-
usersDid = resolveIdentityFromEntryway.data.did;
295
-
} else {
296
-
//Resolves the did and finds the did document for the old PDS
297
-
safeStatusUpdate(statusUpdateHandler, 'Resolving did from handle');
298
-
usersDid = await handleResolver.resolve(oldHandle);
299
-
}
345
+
const didDoc = await docResolver.resolve(usersDid)
346
+
let currentPds
347
+
try {
348
+
currentPds = didDoc.service.filter(s => s.type === 'AtprotoPersonalDataServer')[0]
349
+
.serviceEndpoint
350
+
} catch (error) {
351
+
console.error(error)
352
+
throw new Error('Could not find a PDS in the DID document.')
353
+
}
300
354
301
-
const didDoc = await docResolver.resolve(usersDid);
302
-
let currentPds;
303
-
try {
304
-
currentPds = didDoc.service.filter(s => s.type === 'AtprotoPersonalDataServer')[0].serviceEndpoint;
305
-
} catch (error) {
306
-
console.error(error);
307
-
throw new Error('Could not find a PDS in the DID document.');
355
+
const plcLogRequest = await fetch(`https://plc.directory/${usersDid}/log`)
356
+
const plcLog = await plcLogRequest.json()
357
+
let pdsBeforeCurrent = ''
358
+
for (const log of plcLog) {
359
+
try {
360
+
const pds = log.services.atproto_pds.endpoint
361
+
if (pds.toLowerCase() === currentPds.toLowerCase()) {
362
+
console.log('Found the PDS before the current one')
363
+
break
308
364
}
309
-
310
-
const plcLogRequest = await fetch(`https://plc.directory/${usersDid}/log`);
311
-
const plcLog = await plcLogRequest.json();
312
-
let pdsBeforeCurrent = '';
313
-
for (const log of plcLog) {
314
-
try {
315
-
const pds = log.services.atproto_pds.endpoint;
316
-
if (pds.toLowerCase() === currentPds.toLowerCase()) {
317
-
console.log('Found the PDS before the current one');
318
-
break;
319
-
}
320
-
pdsBeforeCurrent = pds;
321
-
} catch (e) {
322
-
console.log(e);
323
-
}
324
-
}
325
-
if (pdsBeforeCurrent === '') {
326
-
throw new Error('Could not find the PDS before the current one');
327
-
}
328
-
329
-
let oldAgent = new AtpAgent({service: pdsBeforeCurrent});
330
-
safeStatusUpdate(statusUpdateHandler, `Logging you in to the old PDS: ${pdsBeforeCurrent}`);
331
-
//Login to the old PDS
332
-
if (twoFactorCode === null) {
333
-
await oldAgent.login({identifier: oldHandle, password: oldPassword});
334
-
} else {
335
-
await oldAgent.login({identifier: oldHandle, password: oldPassword, authFactorToken: twoFactorCode});
336
-
}
337
-
safeStatusUpdate(statusUpdateHandler, 'Checking this isn\'t your current PDS');
338
-
if (pdsBeforeCurrent === currentPds) {
339
-
throw new Error('This is your current PDS. Login to your old account username and password');
340
-
}
341
-
342
-
let currentAccountStatus = await oldAgent.com.atproto.server.checkAccountStatus();
343
-
if (!currentAccountStatus.data.activated) {
344
-
safeStatusUpdate(statusUpdateHandler, 'All good. Your old account is not activated.');
345
-
}
346
-
safeStatusUpdate(statusUpdateHandler, 'Deactivating your OLD account');
347
-
await oldAgent.com.atproto.server.deactivateAccount({});
348
-
safeStatusUpdate(statusUpdateHandler, 'Successfully deactivated your OLD account');
365
+
pdsBeforeCurrent = pds
366
+
} catch (e) {
367
+
console.log(e)
368
+
}
369
+
}
370
+
if (pdsBeforeCurrent === '') {
371
+
throw new Error('Could not find the PDS before the current one')
349
372
}
350
373
351
-
/**
352
-
* Signs the logged-in user in this.newAgent for backups with PDS MOOver. This is usually called after migrate and signPlcOperation are successful
353
-
*
354
-
* @param {string} didWeb
355
-
* @returns {Promise<void>}
356
-
*/
357
-
async signUpForBackupsFromMigration(didWeb = 'did:web:pdsmoover.com') {
374
+
let oldAgent = new AtpAgent({ service: pdsBeforeCurrent })
375
+
safeStatusUpdate(statusUpdateHandler, `Logging you in to the old PDS: ${pdsBeforeCurrent}`)
376
+
//Login to the old PDS
377
+
if (twoFactorCode === null) {
378
+
await oldAgent.login({ identifier: oldHandle, password: oldPassword })
379
+
} else {
380
+
await oldAgent.login({
381
+
identifier: oldHandle,
382
+
password: oldPassword,
383
+
authFactorToken: twoFactorCode,
384
+
})
385
+
}
386
+
safeStatusUpdate(statusUpdateHandler, "Checking this isn't your current PDS")
387
+
if (pdsBeforeCurrent === currentPds) {
388
+
throw new Error('This is your current PDS. Login to your old account username and password')
389
+
}
358
390
359
-
//Manually grabbing the jwt and making a call with fetch cause for the life of me I could not figure out
360
-
//how you used @atproto/api to make a call for proxying
361
-
const url = `${this.newAgent.serviceUrl.origin}/xrpc/com.pdsmoover.backup.signUp`;
391
+
let currentAccountStatus = await oldAgent.com.atproto.server.checkAccountStatus()
392
+
if (!currentAccountStatus.data.activated) {
393
+
safeStatusUpdate(statusUpdateHandler, 'All good. Your old account is not activated.')
394
+
}
395
+
safeStatusUpdate(statusUpdateHandler, 'Deactivating your OLD account')
396
+
await oldAgent.com.atproto.server.deactivateAccount({})
397
+
safeStatusUpdate(statusUpdateHandler, 'Successfully deactivated your OLD account')
398
+
}
362
399
363
-
const accessJwt = this.newAgent?.session?.accessJwt;
364
-
if (!accessJwt) {
365
-
throw new Error('Missing access token for authorization');
366
-
}
400
+
/**
401
+
* Signs the logged-in user in this.newAgent for backups with PDS MOOver. This is usually called after migrate and signPlcOperation are successful
402
+
*
403
+
* @param {string} didWeb
404
+
* @returns {Promise<void>}
405
+
*/
406
+
async signUpForBackupsFromMigration(didWeb = 'did:web:pdsmoover.com') {
407
+
//Manually grabbing the jwt and making a call with fetch cause for the life of me I could not figure out
408
+
//how you used @atproto/api to make a call for proxying
409
+
const url = `${this.newAgent.serviceUrl.origin}/xrpc/com.pdsmoover.backup.signUp`
367
410
368
-
const res = await fetch(url, {
369
-
method: 'POST',
370
-
headers: {
371
-
'Authorization': `Bearer ${accessJwt}`,
372
-
'Content-Type': 'application/json',
373
-
'Accept': 'application/json',
374
-
'atproto-proxy': `${didWeb}#repo_backup`,
375
-
},
376
-
body: JSON.stringify({}),
377
-
});
411
+
const accessJwt = this.newAgent?.session?.accessJwt
412
+
if (!accessJwt) {
413
+
throw new Error('Missing access token for authorization')
414
+
}
378
415
379
-
if (!res.ok) {
380
-
let bodyText = '';
381
-
try {
382
-
bodyText = await res.text();
383
-
} catch {
384
-
}
385
-
throw new Error(`Backup signup failed: ${res.status} ${res.statusText}${bodyText ? ` - ${bodyText}` : ''}`);
386
-
}
416
+
const res = await fetch(url, {
417
+
method: 'POST',
418
+
headers: {
419
+
'Authorization': `Bearer ${accessJwt}`,
420
+
'Content-Type': 'application/json',
421
+
'Accept': 'application/json',
422
+
'atproto-proxy': `${didWeb}#repo_backup`,
423
+
},
424
+
body: JSON.stringify({}),
425
+
})
387
426
388
-
//No return the success is all that is needed, if there's an error it will throw
427
+
if (!res.ok) {
428
+
let bodyText = ''
429
+
try {
430
+
bodyText = await res.text()
431
+
} catch {}
432
+
throw new Error(
433
+
`Backup signup failed: ${res.status} ${res.statusText}${bodyText ? ` - ${bodyText}` : ''}`,
434
+
)
389
435
}
436
+
437
+
//No return the success is all that is needed, if there's an error it will throw
438
+
}
390
439
}
391
440
392
-
export {Migrator};
393
-
441
+
export { Migrator }
+242
-239
packages/moover/lib/plc-ops.js
+242
-239
packages/moover/lib/plc-ops.js
···
8
8
* @typedef {import('@atcute/did-plc').IndexedEntry} IndexedEntry
9
9
*/
10
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
-
11
+
import { defs, normalizeOp } from '@atcute/did-plc'
12
+
import {
13
+
P256PrivateKey,
14
+
parsePrivateMultikey,
15
+
Secp256k1PrivateKey,
16
+
Secp256k1PrivateKeyExportable,
17
+
} from '@atcute/crypto'
18
+
import * as CBOR from '@atcute/cbor'
19
+
import { fromBase16, toBase64Url } from '@atcute/multibase'
16
20
17
21
// 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
-
};
22
+
const jsonToB64Url = obj => {
23
+
const enc = new TextEncoder()
24
+
const json = JSON.stringify(obj)
25
+
return toBase64Url(enc.encode(json))
26
+
}
23
27
24
28
/**
25
29
* Class to help with various PLC operations
26
30
*/
27
31
class PlcOps {
32
+
/**
33
+
*
34
+
* @param plcDirectoryUrl {string} - The url of the plc directory, defaults to https://plc.directory
35
+
*/
36
+
constructor(plcDirectoryUrl = 'https://plc.directory') {
28
37
/**
29
-
*
30
-
* @param plcDirectoryUrl {string} - The url of the plc directory, defaults to https://plc.directory
38
+
* The url of the plc directory
39
+
* @type {string}
31
40
*/
32
-
constructor(plcDirectoryUrl = 'https://plc.directory') {
33
-
/**
34
-
* The url of the plc directory
35
-
* @type {string}
36
-
*/
37
-
this.plcDirectoryUrl = plcDirectoryUrl;
38
-
}
41
+
this.plcDirectoryUrl = plcDirectoryUrl
42
+
}
39
43
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
-
}
44
+
/**
45
+
* Gets the current rotation keys for a user via their last PlC operation
46
+
* @param did
47
+
* @returns {Promise<string[]>}
48
+
*/
49
+
async getCurrentRotationKeysForUser(did) {
50
+
const logs = await this.getPlcAuditLogs(did)
51
+
const { lastOperation } = this.getLastPlcOp(logs)
52
+
return lastOperation.rotationKeys || []
53
+
}
54
+
55
+
/**
56
+
* Gets the last PlC operation for a user from the plc directory
57
+
* @param did
58
+
* @returns {Promise<{lastOperation: Operation, base: any}>}
59
+
*/
60
+
async getLastPlcOpFromPlc(did) {
61
+
const logs = await this.getPlcAuditLogs(did)
62
+
return this.getLastPlcOp(logs)
63
+
}
50
64
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
-
}
65
+
/**
66
+
*
67
+
* @param logs {IndexedEntryLog}
68
+
* @returns {{lastOperation: Operation, base: IndexedEntry}}
69
+
*/
70
+
getLastPlcOp(logs) {
71
+
const lastOp = logs.at(-1)
72
+
return { lastOperation: normalizeOp(lastOp.operation), base: lastOp }
73
+
}
60
74
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};
75
+
/**
76
+
* Gets the plc audit logs for a user from the plc directory
77
+
* @param did
78
+
* @returns {Promise<IndexedEntryLog>}
79
+
*/
80
+
async getPlcAuditLogs(did) {
81
+
const response = await fetch(`${this.plcDirectoryUrl}/${did}/log/audit`)
82
+
if (!response.ok) {
83
+
throw new Error(`got response ${response.status}`)
69
84
}
70
85
86
+
const json = await response.json()
87
+
return defs.indexedEntryLog.parse(json)
88
+
}
71
89
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);
90
+
/**
91
+
* Creates a new secp256k1 key that can be used for either rotation or verification key
92
+
* @returns {Promise<{privateKey: string, publicKey: `did:key:${string}`}>}
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,
85
101
}
102
+
}
86
103
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
-
};
104
+
/**
105
+
* Signs a new operation with the provided signing key, and information and submits it to the plc directory
106
+
* @param did {string} - The user's did
107
+
* @param signingRotationKey { P256PrivateKey|Secp256k1PrivateKey} - The keypair to sign the op with
108
+
* @param alsoKnownAs {string[]}
109
+
* @param rotationKeys {string[]}
110
+
* @param pds {string}
111
+
* @param verificationKey {string} - The public verification key
112
+
* @param prev {string} - The previous valid operation's cid.
113
+
* @returns {Promise<void>}
114
+
*/
115
+
async signAndPublishNewOp(
116
+
did,
117
+
signingRotationKey,
118
+
alsoKnownAs,
119
+
rotationKeys,
120
+
pds,
121
+
verificationKey,
122
+
prev,
123
+
) {
124
+
const rotationKeysToUse = [...new Set(rotationKeys)]
125
+
if (!rotationKeysToUse) {
126
+
throw new Error('No rotation keys were found to be added to the PLC')
99
127
}
100
128
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);
129
+
if (rotationKeysToUse.length > 5) {
130
+
throw new Error('You can only add up to 5 rotation keys to the PLC')
131
+
}
141
132
142
-
const signature = toBase64Url(sigBytes);
133
+
const operation = {
134
+
type: 'plc_operation',
135
+
prev,
136
+
alsoKnownAs,
137
+
rotationKeys: rotationKeysToUse,
138
+
services: {
139
+
atproto_pds: {
140
+
type: 'AtprotoPersonalDataServer',
141
+
endpoint: pds,
142
+
},
143
+
},
144
+
verificationMethods: {
145
+
atproto: verificationKey,
146
+
},
147
+
}
148
+
const opBytes = CBOR.encode(operation)
149
+
const sigBytes = await signingRotationKey.sign(opBytes)
143
150
144
-
const signedOperation = {
145
-
...operation,
146
-
sig: signature,
147
-
};
151
+
const signature = toBase64Url(sigBytes)
148
152
149
-
await this.pushPlcOperation(did, signedOperation);
153
+
const signedOperation = {
154
+
...operation,
155
+
sig: signature,
150
156
}
151
157
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;
158
+
await this.pushPlcOperation(did, signedOperation)
159
+
}
162
160
163
-
if (HEX_REGEX.test(privateKeyString)) {
164
-
const privateKeyBytes = fromBase16(privateKeyString);
161
+
/**
162
+
* Takes a multi or hex based private key and returns a keypair
163
+
* @param privateKeyString {string}
164
+
* @param type {string} - secp256k1 or p256, needed if the private key is hex based, can be assumed if it's a multikey
165
+
* @returns {Promise<{type: string, didPublicKey: `did:key:${string}`, keypair: P256PrivateKey|Secp256k1PrivateKey}>}
166
+
*/
167
+
async getKeyPair(privateKeyString, type = 'secp256k1') {
168
+
const HEX_REGEX = /^[0-9a-f]+$/i
169
+
const MULTIKEY_REGEX = /^z[a-km-zA-HJ-NP-Z1-9]+$/
170
+
let keypair = undefined
165
171
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)) {
172
+
if (HEX_REGEX.test(privateKeyString)) {
173
+
const privateKeyBytes = fromBase16(privateKeyString)
180
174
181
-
const match = parsePrivateMultikey(privateKeyString);
182
-
const privateKeyBytes = match.privateKeyBytes;
175
+
switch (type) {
176
+
case 'p256': {
177
+
keypair = await P256PrivateKey.importRaw(privateKeyBytes)
178
+
break
179
+
}
180
+
case 'secp256k1': {
181
+
keypair = await Secp256k1PrivateKey.importRaw(privateKeyBytes)
182
+
break
183
+
}
184
+
default: {
185
+
throw new Error(`unsupported "${type}" type`)
186
+
}
187
+
}
188
+
} else if (MULTIKEY_REGEX.test(privateKeyString)) {
189
+
const match = parsePrivateMultikey(privateKeyString)
190
+
const privateKeyBytes = match.privateKeyBytes
183
191
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');
192
+
switch (match.type) {
193
+
case 'p256': {
194
+
keypair = await P256PrivateKey.importRaw(privateKeyBytes)
195
+
console.log(keypair)
196
+
break
200
197
}
201
-
return {
202
-
type: 'private_key',
203
-
didPublicKey: await keypair.exportPublicKey('did'),
204
-
keypair: keypair,
205
-
};
198
+
case 'secp256k1': {
199
+
keypair = await Secp256k1PrivateKey.importRaw(privateKeyBytes)
200
+
break
201
+
}
202
+
default: {
203
+
throw new Error(`unsupported "${type}" type`)
204
+
}
205
+
}
206
+
} else {
207
+
throw new Error('unknown input format')
206
208
}
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
-
});
209
+
return {
210
+
type: 'private_key',
211
+
didPublicKey: await keypair.exportPublicKey('did'),
212
+
keypair: keypair,
213
+
}
214
+
}
222
215
223
-
const headers = response.headers;
224
-
if (!response.ok) {
225
-
const type = headers.get('content-type');
216
+
/**
217
+
* Submits a new operation to the plc directory
218
+
* @param did {string} - The user's did
219
+
* @param operation
220
+
* @returns {Promise<void>}
221
+
*/
222
+
async pushPlcOperation(did, operation) {
223
+
const response = await fetch(`${this.plcDirectoryUrl}/${did}`, {
224
+
method: 'post',
225
+
headers: {
226
+
'content-type': 'application/json',
227
+
},
228
+
body: JSON.stringify(operation),
229
+
})
226
230
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
-
}
231
+
const headers = response.headers
232
+
if (!response.ok) {
233
+
const type = headers.get('content-type')
233
234
234
-
throw new Error(`got http ${response.status} from plc`);
235
+
if (type?.includes('application/json')) {
236
+
const json = await response.json()
237
+
if (typeof json === 'object' && json !== null && typeof json.message === 'string') {
238
+
throw new Error(json.message)
235
239
}
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
-
})();
240
+
}
262
241
242
+
throw new Error(`got http ${response.status} from plc`)
243
+
}
244
+
}
263
245
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;
246
+
/**
247
+
* 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
248
+
*
249
+
* @param iss The user's did
250
+
* @param aud The did:web, if it's a PDS it's usually from /xrpc/com.atproto.server.describeServer
251
+
* @param keypair The keypair to sign with only supporting ES256K atm
252
+
* @param lxm The lxm which is usually com.atproto.server.createAccount for creating a new account
253
+
* @returns {Promise<string>}
254
+
*/
255
+
async createANewServiceAuthToken(iss, aud, keypair, lxm) {
256
+
// Compute iat/exp defaults (60s window like reference: MINUTE/1e3)
257
+
const iat = Math.floor(Date.now() / 1e3)
258
+
const exp = iat + 60
274
259
275
-
const headerB64 = jsonToB64Url(header);
276
-
const payloadB64 = jsonToB64Url(payload);
277
-
const toSignStr = `${headerB64}.${payloadB64}`;
260
+
// Generate a 16-byte hex jti
261
+
const jti = (() => {
262
+
const bytes = new Uint8Array(16)
263
+
// crypto in browser or node; fall back safely
264
+
;(globalThis.crypto || window.crypto).getRandomValues(bytes)
265
+
return Array.from(bytes)
266
+
.map(b => b.toString(16).padStart(2, '0'))
267
+
.join('')
268
+
})()
278
269
279
-
// Sign
280
-
const toSignBytes = new TextEncoder().encode(toSignStr);
281
-
const sigBytes = await keypair.sign(toSignBytes);
270
+
// Build header and payload (omit undefined fields)
271
+
// Just defaulting to ES256K since p256 was not importing on firefox
272
+
const header = { typ: 'JWT', alg: 'ES256K' }
273
+
const payload = {}
274
+
payload.iat = iat
275
+
payload.iss = iss
276
+
payload.aud = aud
277
+
payload.exp = exp
278
+
payload.lxm = lxm
279
+
payload.jti = jti
282
280
283
-
// Return compact JWS
284
-
const sigB64 = toBase64Url(sigBytes);
285
-
return `${toSignStr}.${sigB64}`;
286
-
}
281
+
const headerB64 = jsonToB64Url(header)
282
+
const payloadB64 = jsonToB64Url(payload)
283
+
const toSignStr = `${headerB64}.${payloadB64}`
287
284
285
+
// Sign
286
+
const toSignBytes = new TextEncoder().encode(toSignStr)
287
+
const sigBytes = await keypair.sign(toSignBytes)
288
288
289
+
// Return compact JWS
290
+
const sigB64 = toBase64Url(sigBytes)
291
+
return `${toSignStr}.${sigB64}`
292
+
}
289
293
}
290
294
291
-
292
-
export {PlcOps};
295
+
export { PlcOps }
+283
-281
packages/moover/lib/restore.js
+283
-281
packages/moover/lib/restore.js
···
1
1
/**
2
2
* @typedef {import('@atcute/did-plc').Operation} Operation
3
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';
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
12
13
13
class Restore {
14
+
/**
15
+
*
16
+
* @param pdsMooverInstance {string} - The url of the pds moover instance to restore from. Defaults to https://pdsmover.com
17
+
*/
18
+
constructor(pdsMooverInstance = 'https://pdsmover.com') {
19
+
/**
20
+
* If you want to use a different plc directory create your own instance of the plc ops class and pass it in here
21
+
* @type {PlcOps} */
22
+
this.plcOps = new PlcOps()
14
23
15
24
/**
16
-
*
17
-
* @param pdsMooverInstance {string} - The url of the pds moover instance to restore from. Defaults to https://pdsmover.com
25
+
* This is the base url for the pds moover instance used to restore the files from a backup.
26
+
* @type {string}
18
27
*/
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
-
}
28
+
this.pdsMooverInstance = pdsMooverInstance
60
29
61
30
/**
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.
31
+
* To keep it simple, only uses secp256k for the temp verification key that is used to create the new account on the new PDS
32
+
* and is temporarily assigned to the user's account on PLC
33
+
* @type {null|Secp256k1PrivateKeyExportable}
76
34
*/
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;
35
+
this.tempVerificationKeypair = null
104
36
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
-
}
37
+
/** @type {AtpAgent} */
38
+
this.atpAgent = null
138
39
139
-
}
40
+
/**
41
+
* The keypair that is used to sign the plc operation
42
+
* @type {null|{type: string, didPublicKey: `did:key:${string}`, keypair: P256PrivateKey|Secp256k1PrivateKey}}
43
+
*/
44
+
this.recoveryRotationKeyPair = null
140
45
141
-
if (this.AccountRecovery) {
46
+
/**
47
+
* If this is true we are just restoring the repo and blobs. Ideally for rerunning a restore process after account recovery
48
+
* @type {boolean}
49
+
*/
50
+
this.RestoreFromBackup = true
142
51
143
-
if (onStatus) onStatus('Validating your private rotation key is in the correct format...');
52
+
/**
53
+
* If set to true then it will do the account recovery. Writes a temp key to the did doc,
54
+
* 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)
55
+
* @type {boolean}
56
+
*/
57
+
this.AccountRecovery = true
58
+
}
144
59
145
-
this.recoveryRotationKeyPair = await this.plcOps.getKeyPair(rotationKey, rotationKeyType);
60
+
/**
61
+
* Recovers an account with the users rotation key and restores the repo from a PDS MOOver backup
62
+
* 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
63
+
* @param rotationKey {string} - The users private rotation key, can be a multi key or hex key
64
+
* @param rotationKeyType {string} - The type of the key, secp256k1 or p256. Required if the key is in hex format, defaults to secp256k1
65
+
* @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
66
+
* @param newPDS {string} - The new PDS url, like https://coolnewpds.com
67
+
* @param newHandle {string} - Can be the users DNS handle if it is already setup with their did, if not it's bob.mypds.com
68
+
* @param newPassword {string} - The new password for the new account
69
+
* @param newEmail {string} - The new email for the new account
70
+
* @param inviteCode {string|null} - The invite code for the new PDS if it requires one
71
+
* @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
72
+
* @param onStatus {function|null} - A function that takes a string used to update the UI. Like (status) => console.log(status)
73
+
* @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
74
+
* recovered and future runs need to have the RestoreFromBackup flag set to true and AccountRecovery set to false.
75
+
*/
76
+
async recover(
77
+
rotationKey,
78
+
rotationKeyType = 'secp256k1',
79
+
currentHandleOrDid,
80
+
newPDS,
81
+
newHandle,
82
+
newPassword,
83
+
newEmail,
84
+
inviteCode,
85
+
cidToRestoreTo = null,
86
+
onStatus = null,
87
+
) {
88
+
if (onStatus) onStatus('Resolving your handle...')
146
89
90
+
let { usersDid } = await handleAndPDSResolver(currentHandleOrDid)
147
91
148
-
if (onStatus) onStatus('Resolving PlC operation logs...');
92
+
if (onStatus)
93
+
onStatus(
94
+
'Checking that the new PDS is an actual PDS (if the url is wrong, this takes a while to error out)',
95
+
)
96
+
this.atpAgent = new AtpAgent({ service: newPDS })
97
+
const newHostDesc = await this.atpAgent.com.atproto.server.describeServer()
149
98
150
-
/** @type {Operation} */
151
-
let baseOpForSigning = null;
152
-
let opPrevCid = null;
99
+
//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
100
+
try {
101
+
await this.atpAgent.com.atproto.repo.describeRepo({ repo: usersDid.toString() })
102
+
//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.
103
+
//We do not want to mess with the plc ops if we dont have to
104
+
this.AccountRecovery = false
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
+
}
153
117
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
-
}
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({
122
+
handle: newHandle,
123
+
})
124
+
if (resolveHandle.data.did === usersDid.toString()) {
125
+
//This was originally setting the AccountRecovery to false, which works if it is resolved via .well-known, but not dns
126
+
//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
127
+
//their did should be set anyhow
128
+
} else {
129
+
//There is a repo with that name and it's not the users did,
130
+
throw new Error('The new handle is already taken, please select a different handle')
131
+
}
132
+
} catch (error) {
133
+
// Going to silently log this and just assume the handle has not been taken.
134
+
console.error(error)
135
+
if (error.message.startsWith('The new handle')) {
136
+
//it's not our custom error, so we can just throw it
137
+
throw error
138
+
}
139
+
}
172
140
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];
141
+
if (this.AccountRecovery) {
142
+
if (onStatus) onStatus('Validating your private rotation key is in the correct format...')
181
143
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);
144
+
this.recoveryRotationKeyPair = await this.plcOps.getKeyPair(rotationKey, rotationKeyType)
192
145
146
+
if (onStatus) onStatus('Resolving PlC operation logs...')
193
147
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');
148
+
/** @type {Operation} */
149
+
let baseOpForSigning = null
150
+
let opPrevCid = null
196
151
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
-
});
152
+
//This is for reversals against a rogue plc op and you want to restore to a specific cid in the audit log
153
+
if (cidToRestoreTo) {
154
+
let auditLogs = await this.plcOps.getPlcAuditLogs(usersDid)
155
+
for (const log of auditLogs) {
156
+
if (log.cid === cidToRestoreTo) {
157
+
baseOpForSigning = normalizeOp(log.operation)
158
+
opPrevCid = log.cid
159
+
break
160
+
}
212
161
}
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);
162
+
if (!baseOpForSigning) {
163
+
throw new Error('Could not find the cid in the audit logs')
224
164
}
165
+
} else {
166
+
let { lastOperation, base } = await this.plcOps.getLastPlcOpFromPlc(usersDid)
167
+
opPrevCid = base.cid
168
+
baseOpForSigning = lastOperation
169
+
}
225
170
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
-
});
171
+
if (onStatus) onStatus('Preparing to switch to a temp atproto key...')
172
+
if (this.tempVerificationKeypair == null) {
173
+
if (onStatus) onStatus('Creating a new temp atproto key...')
174
+
this.tempVerificationKeypair = await Secp256k1PrivateKeyExportable.createKeypair()
175
+
}
176
+
//Just defaulting to the user's recovery key for now. Advance cases will be something else
177
+
//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
178
+
let tempRotationKeys = [this.recoveryRotationKeyPair.didPublicKey]
233
179
234
-
if (onStatus) onStatus('Restoring your blobs...');
180
+
if (onStatus) onStatus('Modifying the PLC OP for recovery...')
181
+
//A temp plc op for control of the atproto key to create a serviceAuth and new account on the new PDS
182
+
await this.plcOps.signAndPublishNewOp(
183
+
usersDid,
184
+
this.recoveryRotationKeyPair.keypair,
185
+
baseOpForSigning.alsoKnownAs,
186
+
tempRotationKeys,
187
+
newPDS,
188
+
await this.tempVerificationKeypair.exportPublicKey('did'),
189
+
opPrevCid,
190
+
)
235
191
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;
192
+
if (onStatus) onStatus('Creating your new account on the new PDS...')
193
+
let serviceAuthToken = await this.plcOps.createANewServiceAuthToken(
194
+
usersDid,
195
+
newHostDesc.data.did,
196
+
this.tempVerificationKeypair,
197
+
'com.atproto.server.createAccount',
198
+
)
240
199
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 {
200
+
let createAccountRequest = {
201
+
did: usersDid,
202
+
handle: newHandle,
203
+
email: newEmail,
204
+
password: newPassword,
205
+
}
206
+
if (inviteCode) {
207
+
createAccountRequest.inviteCode = inviteCode
208
+
}
209
+
const _ = await this.atpAgent.com.atproto.server.createAccount(createAccountRequest, {
210
+
headers: { authorization: `Bearer ${serviceAuthToken}` },
211
+
encoding: 'application/json',
212
+
})
213
+
}
251
214
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
-
});
215
+
await this.atpAgent.login({
216
+
identifier: usersDid,
217
+
password: newPassword,
218
+
})
259
219
220
+
if (this.AccountRecovery) {
221
+
//Moving the user offically to the new PDS
222
+
if (onStatus) onStatus('Signing the papers...')
223
+
let { base } = await this.plcOps.getLastPlcOpFromPlc(usersDid)
224
+
await this.signRestorePlcOperation(
225
+
usersDid,
226
+
[this.recoveryRotationKeyPair.didPublicKey],
227
+
base.cid,
228
+
)
229
+
}
260
230
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
-
}
231
+
if (this.RestoreFromBackup) {
232
+
if (onStatus) onStatus('Success! Restoring your repo...')
233
+
const pdsMoover = new AtpAgent({ service: this.pdsMooverInstance })
234
+
const repoRes = await pdsMoover.com.atproto.sync.getRepo({ did: usersDid })
235
+
await this.atpAgent.com.atproto.repo.importRepo(repoRes.data, {
236
+
encoding: 'application/vnd.ipld.car',
237
+
})
277
238
278
-
}
239
+
if (onStatus) onStatus('Restoring your blobs...')
279
240
241
+
//Using the missing endpoint to findout what's missing then the PDS MOOver endpoint to restore
242
+
let totalMissingBlobs = 0
243
+
let missingBlobCursor = undefined
244
+
let missingUploadedBlobs = 0
280
245
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();
246
+
do {
247
+
const missingBlobs = await this.atpAgent.com.atproto.repo.listMissingBlobs({
248
+
cursor: missingBlobCursor,
249
+
limit: 1000,
250
+
})
251
+
totalMissingBlobs += missingBlobs.data.blobs.length
294
252
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
-
}
253
+
for (const recordBlob of missingBlobs.data.blobs) {
254
+
try {
255
+
const blobRes = await pdsMoover.com.atproto.sync.getBlob({
256
+
did: usersDid,
257
+
cid: recordBlob.cid,
258
+
})
259
+
let result = await this.atpAgent.com.atproto.repo.uploadBlob(blobRes.data, {
260
+
encoding: blobRes.headers['content-type'],
261
+
})
301
262
302
-
if (rotationKeys.length > 5) {
303
-
throw new Error('You can only add up to 5 rotation keys to the PLC');
263
+
if (missingUploadedBlobs % 2 === 0) {
264
+
if (onStatus)
265
+
onStatus(
266
+
`Migrating blobs: ${missingUploadedBlobs}/${totalMissingBlobs} (The total may increase as we find more)`,
267
+
)
268
+
}
269
+
missingUploadedBlobs++
270
+
} catch (error) {
271
+
console.error(error)
272
+
}
304
273
}
274
+
missingBlobCursor = missingBlobs.data.cursor
275
+
} while (missingBlobCursor)
276
+
}
277
+
const accountStatus = await this.atpAgent.com.atproto.server.checkAccountStatus()
278
+
if (!accountStatus.data.activated) {
279
+
if (onStatus) onStatus('Activating your account...')
280
+
await this.atpAgent.com.atproto.server.activateAccount()
281
+
}
282
+
}
305
283
284
+
/**
285
+
* This method signs the plc operation over to the new PDS and activates the account
286
+
* Assumes you have already created a new account during the recovery process and logged in
287
+
* Uses the recommended did doc from the PDS as a base and adds the users rotation key to the rotation keys array
288
+
*
289
+
* @param usersDid
290
+
* @param additionalRotationKeysToAdd
291
+
* @param prevCid
292
+
* @returns {Promise<void>}
293
+
*/
294
+
async signRestorePlcOperation(usersDid, additionalRotationKeysToAdd = [], prevCid) {
295
+
const getDidCredentials =
296
+
await this.atpAgent.com.atproto.identity.getRecommendedDidCredentials()
306
297
307
-
const plcOpToSubmit = {
308
-
type: 'plc_operation',
309
-
...getDidCredentials.data,
310
-
prev: prevCid,
311
-
rotationKeys: rotationKeys,
312
-
};
313
-
298
+
const pdsProvidedRotationKeys = getDidCredentials.data.rotationKeys ?? []
299
+
//Puts the provided rotation keys above the pds pro
300
+
const rotationKeys = [
301
+
...new Set([...(additionalRotationKeysToAdd || []), ...pdsProvidedRotationKeys]),
302
+
]
303
+
if (!rotationKeys) {
304
+
throw new Error('No rotation keys were found to be added to the PLC')
305
+
}
314
306
315
-
const opBytes = CBOR.encode(plcOpToSubmit);
316
-
const sigBytes = await this.recoveryRotationKeyPair.keypair.sign(opBytes);
307
+
if (rotationKeys.length > 5) {
308
+
throw new Error('You can only add up to 5 rotation keys to the PLC')
309
+
}
317
310
318
-
const signature = toBase64Url(sigBytes);
311
+
const plcOpToSubmit = {
312
+
type: 'plc_operation',
313
+
...getDidCredentials.data,
314
+
prev: prevCid,
315
+
rotationKeys: rotationKeys,
316
+
}
319
317
320
-
const signedOperation = {
321
-
...plcOpToSubmit,
322
-
sig: signature,
323
-
};
318
+
const opBytes = CBOR.encode(plcOpToSubmit)
319
+
const sigBytes = await this.recoveryRotationKeyPair.keypair.sign(opBytes)
324
320
325
-
await this.plcOps.pushPlcOperation(usersDid, signedOperation);
326
-
await this.atpAgent.com.atproto.server.activateAccount();
321
+
const signature = toBase64Url(sigBytes)
327
322
323
+
const signedOperation = {
324
+
...plcOpToSubmit,
325
+
sig: signature,
328
326
}
327
+
328
+
await this.plcOps.pushPlcOperation(usersDid, signedOperation)
329
+
await this.atpAgent.com.atproto.server.activateAccount()
330
+
}
329
331
}
330
332
331
-
export {Restore};
333
+
export { Restore }
+3
-2
packages/moover/package.json
+3
-2
packages/moover/package.json
···
1
1
{
2
2
"name": "@pds-moover/moover",
3
-
"version": "1.0.5",
3
+
"version": "1.0.6",
4
4
"description": "Utilities for ATProto PDS migrations and recovery",
5
5
"repository": {
6
6
"type": "git",
···
35
35
"dev": "vite",
36
36
"build": "vite build",
37
37
"gen:types": "tsc -p .",
38
-
"preview": "vite preview"
38
+
"preview": "vite preview",
39
+
"generate:lexicons": "lex build --lexicons lexicons --out lib/lexicons --clear"
39
40
},
40
41
"devDependencies": {
41
42
"eslint": "^9.34.0",
+3342
packages/moover/pnpm-lock.yaml
+3342
packages/moover/pnpm-lock.yaml
···
1
+
lockfileVersion: '9.0'
2
+
3
+
settings:
4
+
autoInstallPeers: true
5
+
excludeLinksFromLockfile: false
6
+
7
+
importers:
8
+
9
+
.:
10
+
dependencies:
11
+
'@atcute/cbor':
12
+
specifier: ^2.2.7
13
+
version: 2.3.0
14
+
'@atcute/client':
15
+
specifier: ^4.0.4
16
+
version: 4.2.1
17
+
'@atcute/crypto':
18
+
specifier: ^2.2.5
19
+
version: 2.3.0
20
+
'@atcute/did-plc':
21
+
specifier: ^0.1.7
22
+
version: 0.1.7
23
+
'@atcute/identity-resolver':
24
+
specifier: ^1.1.3
25
+
version: 1.2.2(@atcute/identity@1.1.3)
26
+
'@atcute/lexicons':
27
+
specifier: ^1.2.2
28
+
version: 1.2.7
29
+
'@atcute/multibase':
30
+
specifier: ^1.1.6
31
+
version: 1.1.7
32
+
'@atproto/api':
33
+
specifier: ^0.16.7
34
+
version: 0.16.11
35
+
'@atproto/lex':
36
+
specifier: ^0.0.16
37
+
version: 0.0.16
38
+
'@pds-moover/lexicons':
39
+
specifier: ^1.0.0
40
+
version: 1.0.1
41
+
alpinejs:
42
+
specifier: ^3.15.0
43
+
version: 3.15.8
44
+
vite-plugin-full-reload:
45
+
specifier: ^1.2.0
46
+
version: 1.2.0
47
+
vite-rs-plugin:
48
+
specifier: 1.0.1
49
+
version: 1.0.1(vite@7.3.1)
50
+
devDependencies:
51
+
eslint:
52
+
specifier: ^9.34.0
53
+
version: 9.39.2
54
+
eslint-plugin-import:
55
+
specifier: ^2.32.0
56
+
version: 2.32.0(eslint@9.39.2)
57
+
vite:
58
+
specifier: ^7.1.7
59
+
version: 7.3.1
60
+
61
+
packages:
62
+
63
+
'@atcute/cbor@2.3.0':
64
+
resolution: {integrity: sha512-7G2AndkfYzIXMBOBqUPUWP6oIJJm77KY5nYzS4Mr5NNxnmnrBrXEQqp+seCE3X5TV8FUSWQK5YRTU87uPjafMQ==}
65
+
66
+
'@atcute/cid@2.4.0':
67
+
resolution: {integrity: sha512-6+5u9MpUrgSRQ94z7vaIX4BYk8fYr2KXUBS+rrr2NhlPy8xam8nbTlmd3hvBbtpSwShbhRAE4tA5Ab7eYUp2Yw==}
68
+
69
+
'@atcute/client@4.2.1':
70
+
resolution: {integrity: sha512-ZBFM2pW075JtgGFu5g7HHZBecrClhlcNH8GVP9Zz1aViWR+cjjBsTpeE63rJs+FCOHFYlirUyo5L8SGZ4kMINw==}
71
+
72
+
'@atcute/crypto@2.3.0':
73
+
resolution: {integrity: sha512-w5pkJKCjbNMQu+F4JRHbR3ROQyhi1wbn+GSC6WDQamcYHkZmEZk1/eoI354bIQOOfkEM6aFLv718iskrkon4GQ==}
74
+
75
+
'@atcute/did-plc@0.1.7':
76
+
resolution: {integrity: sha512-a7yOQNqViae3rB5/xa3U0EPJbFD9l8zOHXx6XASZ5F8+Vy2uTgXK3omurpNZ5UxRpy1ni1AMhSohXr61cqWbkg==}
77
+
78
+
'@atcute/identity-resolver@1.2.2':
79
+
resolution: {integrity: sha512-eUh/UH4bFvuXS0X7epYCeJC/kj4rbBXfSRumLEH4smMVwNOgTo7cL/0Srty+P/qVPoZEyXdfEbS0PHJyzoXmHw==}
80
+
peerDependencies:
81
+
'@atcute/identity': ^1.0.0
82
+
83
+
'@atcute/identity@1.1.3':
84
+
resolution: {integrity: sha512-oIqPoI8TwWeQxvcLmFEZLdN2XdWcaLVtlm8pNk0E72As9HNzzD9pwKPrLr3rmTLRIoULPPFmq9iFNsTeCIU9ng==}
85
+
86
+
'@atcute/lexicons@1.2.7':
87
+
resolution: {integrity: sha512-gCvkSMI1F1zx7xXa59iPiSKMH3L5Hga6iurGqQjaQbE2V/np/2QuDqQzt96TNbWfaFAXE9f9oY+0z3ljf/bweA==}
88
+
89
+
'@atcute/multibase@1.1.7':
90
+
resolution: {integrity: sha512-YmWds7U52b7Qri0xNfGeqSOvgyNfHR8Yy/NNDQx4d5TkCX2fHJIo0pXquEhCyMNAwKt53uH5yQDswy4TNP1Zhw==}
91
+
92
+
'@atcute/uint8array@1.1.0':
93
+
resolution: {integrity: sha512-JtHXIVW6LPU9FMWp7SgE4HbUs3uV2WdfkK/2RWdEGjr4EgMV50P3FdU6fPeGlTfDNBJVYMIsuD2wwaKRPV/Aqg==}
94
+
95
+
'@atcute/util-fetch@1.0.5':
96
+
resolution: {integrity: sha512-qjHj01BGxjSjIFdPiAjSARnodJIIyKxnCMMEcXMESo9TAyND6XZQqrie5fia+LlYWVXdpsTds8uFQwc9jdKTig==}
97
+
98
+
'@atcute/util-text@1.1.0':
99
+
resolution: {integrity: sha512-34G9KD5Z9f7oEdFpZOmqrMnU86p8ne6LlxJowfZzKNszRcl1GH+FtEPh3N1woelJT2SkPXMK2anwT8DESTluwA==}
100
+
101
+
'@atproto-labs/did-resolver@0.2.6':
102
+
resolution: {integrity: sha512-2K1bC04nI2fmgNcvof+yA28IhGlpWn2JKYlPa7To9JTKI45FINCGkQSGiL2nyXlyzDJJ34fZ1aq6/IRFIOIiqg==}
103
+
104
+
'@atproto-labs/fetch@0.2.3':
105
+
resolution: {integrity: sha512-NZtbJOCbxKUFRFKMpamT38PUQMY0hX0p7TG5AEYOPhZKZEP7dHZ1K2s1aB8MdVH0qxmqX7nQleNrrvLf09Zfdw==}
106
+
107
+
'@atproto-labs/pipe@0.1.1':
108
+
resolution: {integrity: sha512-hdNw2oUs2B6BN1lp+32pF7cp8EMKuIN5Qok2Vvv/aOpG/3tNSJ9YkvfI0k6Zd188LeDDYRUpYpxcoFIcGH/FNg==}
109
+
110
+
'@atproto-labs/simple-store-memory@0.1.4':
111
+
resolution: {integrity: sha512-3mKY4dP8I7yKPFj9VKpYyCRzGJOi5CEpOLPlRhoJyLmgs3J4RzDrjn323Oakjz2Aj2JzRU/AIvWRAZVhpYNJHw==}
112
+
113
+
'@atproto-labs/simple-store@0.3.0':
114
+
resolution: {integrity: sha512-nOb6ONKBRJHRlukW1sVawUkBqReLlLx6hT35VS3imaNPwiXDxLnTK7lxw3Lrl9k5yugSBDQAkZAq3MPTEFSUBQ==}
115
+
116
+
'@atproto/api@0.16.11':
117
+
resolution: {integrity: sha512-1dhfQNHiclb102RW+Ea8Nft5olfqU0Ev/vlQaSX6mWNo1aP5zT+sPODJ8+BTUOYk3vcuvL7QMkqA/rLYy2PMyw==}
118
+
119
+
'@atproto/common-web@0.4.16':
120
+
resolution: {integrity: sha512-Ufvaff5JgxUyUyTAG0/3o7ltpy3lnZ1DvLjyAnvAf+hHfiK7OMQg+8byr+orN+KP9MtIQaRTsCgYPX+PxMKUoA==}
121
+
122
+
'@atproto/common@0.5.11':
123
+
resolution: {integrity: sha512-WRlT4s+wv80WdQuzkQub9D5vTD82O8dH2p91u4b+x3O17q5IQbmA3Lj+1NICINNSy2voqloqAWdqXEkRfdlAPw==}
124
+
engines: {node: '>=18.7.0'}
125
+
126
+
'@atproto/crypto@0.4.5':
127
+
resolution: {integrity: sha512-n40aKkMoCatP0u9Yvhrdk6fXyOHFDDbkdm4h4HCyWW+KlKl8iXfD5iV+ECq+w5BM+QH25aIpt3/j6EUNerhLxw==}
128
+
engines: {node: '>=18.7.0'}
129
+
130
+
'@atproto/did@0.3.0':
131
+
resolution: {integrity: sha512-raUPzUGegtW/6OxwCmM8bhZvuIMzxG5t9oWsth6Tp91Kb5fTnHV2h/KKNF1C82doeA4BdXCErTyg7ISwLbQkzA==}
132
+
133
+
'@atproto/lex-builder@0.0.15':
134
+
resolution: {integrity: sha512-OtAjQD02vTaJNOWFMO5+9o+z3sGEDTb6Gre9/8JsjnweZk9JzZ46rGpK7old8Unw9oQDP/l58uzAGTywV350NQ==}
135
+
136
+
'@atproto/lex-cbor@0.0.11':
137
+
resolution: {integrity: sha512-A7ETtPsEsJ/VuPJOFw4bPNTKxHvFN1JbTQ2NjLuisd3ry7fVxgMpo/qGXsUQsAh/I/uziGbhpNqdS6GnI2p/Wg==}
138
+
139
+
'@atproto/lex-client@0.0.12':
140
+
resolution: {integrity: sha512-ef4jQQ7SOtBsXr+Gf1UHuBfCiAGYZxO5PCCXl3eT4ObO83SROtIf7pyO06jBQI/IZChSVsXqXsgakR0aru6lYQ==}
141
+
142
+
'@atproto/lex-data@0.0.11':
143
+
resolution: {integrity: sha512-4+KTtHdqwlhiTKA7D4SACea4jprsNpCQsNALW09wsZ6IHhCDGO5tr1cmV+QnLYe3G3mu1E1yXHXbPUHrUUDT/A==}
144
+
145
+
'@atproto/lex-document@0.0.13':
146
+
resolution: {integrity: sha512-LWsBsKIbyuG7jFObTtnCFQNYHxWWVpVVspqv6UtnS/QsaCyCMg1GIz5vlgi8QBnmGvaPiQxIzGt6mERpTvEXpg==}
147
+
148
+
'@atproto/lex-installer@0.0.16':
149
+
resolution: {integrity: sha512-fHLu8VUf9zf2Jz+wJ9+5fvFGxi3930VyUBk/FtszcccTLg1uzb0qElUpVHpieFAHbA2fYqjvPgCpZpH6iploYQ==}
150
+
151
+
'@atproto/lex-json@0.0.11':
152
+
resolution: {integrity: sha512-2IExAoQ4KsR5fyPa1JjIvtR316PvdgRH/l3BVGLBd3cSxM3m5MftIv1B6qZ9HjNiK60SgkWp0mi9574bTNDhBQ==}
153
+
154
+
'@atproto/lex-resolver@0.0.14':
155
+
resolution: {integrity: sha512-jBkYRmMKap2OM1zm0VDvs7Heuf3pGjw9xJEHQx1ohkMmM5f+cHPS40RQ8x8SNE+Vl9gMuOrgmgKyPDIuYSIBTw==}
156
+
157
+
'@atproto/lex-schema@0.0.12':
158
+
resolution: {integrity: sha512-l1RNYmqNwIEjgMEjC9i2o6FLsUFdpAc610xQYK/CRxN31cRzY0lAJ2GFbp2GZ4rRAD3FGYCXid6gZ42KsieUcw==}
159
+
160
+
'@atproto/lex@0.0.16':
161
+
resolution: {integrity: sha512-k7cxIFxEiztHVVMFzqOOvThPDZ2RaK8+X9L27v0B2DmNPhbqRoKFdDU3dWHFhUhBP/CrK34zDo8YPQ4JmcradA==}
162
+
hasBin: true
163
+
164
+
'@atproto/lexicon@0.5.2':
165
+
resolution: {integrity: sha512-lRmJgMA8f5j7VB5Iu5cp188ald5FuI4FlmZ7nn6EBrk1dgOstWVrI5Ft6K3z2vjyLZRG6nzknlsw+tDP63p7bQ==}
166
+
167
+
'@atproto/lexicon@0.6.1':
168
+
resolution: {integrity: sha512-/vI1kVlY50Si+5MXpvOucelnYwb0UJ6Qto5mCp+7Q5C+Jtp+SoSykAPVvjVtTnQUH2vrKOFOwpb3C375vSKzXw==}
169
+
170
+
'@atproto/repo@0.8.12':
171
+
resolution: {integrity: sha512-QpVTVulgfz5PUiCTELlDBiRvnsnwrFWi+6CfY88VwXzrRHd9NE8GItK7sfxQ6U65vD/idH8ddCgFrlrsn1REPQ==}
172
+
engines: {node: '>=18.7.0'}
173
+
174
+
'@atproto/syntax@0.4.3':
175
+
resolution: {integrity: sha512-YoZUz40YAJr5nPwvCDWgodEOlt5IftZqPJvA0JDWjuZKD8yXddTwSzXSaKQAzGOpuM+/A3uXRtPzJJqlScc+iA==}
176
+
177
+
'@atproto/xrpc@0.7.7':
178
+
resolution: {integrity: sha512-K1ZyO/BU8JNtXX5dmPp7b5UrkLMMqpsIa/Lrj5D3Su+j1Xwq1m6QJ2XJ1AgjEjkI1v4Muzm7klianLE6XGxtmA==}
179
+
180
+
'@badrap/valita@0.4.6':
181
+
resolution: {integrity: sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==}
182
+
engines: {node: '>= 18'}
183
+
184
+
'@esbuild/aix-ppc64@0.27.3':
185
+
resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==}
186
+
engines: {node: '>=18'}
187
+
cpu: [ppc64]
188
+
os: [aix]
189
+
190
+
'@esbuild/android-arm64@0.27.3':
191
+
resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==}
192
+
engines: {node: '>=18'}
193
+
cpu: [arm64]
194
+
os: [android]
195
+
196
+
'@esbuild/android-arm@0.27.3':
197
+
resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==}
198
+
engines: {node: '>=18'}
199
+
cpu: [arm]
200
+
os: [android]
201
+
202
+
'@esbuild/android-x64@0.27.3':
203
+
resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==}
204
+
engines: {node: '>=18'}
205
+
cpu: [x64]
206
+
os: [android]
207
+
208
+
'@esbuild/darwin-arm64@0.27.3':
209
+
resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==}
210
+
engines: {node: '>=18'}
211
+
cpu: [arm64]
212
+
os: [darwin]
213
+
214
+
'@esbuild/darwin-x64@0.27.3':
215
+
resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==}
216
+
engines: {node: '>=18'}
217
+
cpu: [x64]
218
+
os: [darwin]
219
+
220
+
'@esbuild/freebsd-arm64@0.27.3':
221
+
resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==}
222
+
engines: {node: '>=18'}
223
+
cpu: [arm64]
224
+
os: [freebsd]
225
+
226
+
'@esbuild/freebsd-x64@0.27.3':
227
+
resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==}
228
+
engines: {node: '>=18'}
229
+
cpu: [x64]
230
+
os: [freebsd]
231
+
232
+
'@esbuild/linux-arm64@0.27.3':
233
+
resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==}
234
+
engines: {node: '>=18'}
235
+
cpu: [arm64]
236
+
os: [linux]
237
+
238
+
'@esbuild/linux-arm@0.27.3':
239
+
resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==}
240
+
engines: {node: '>=18'}
241
+
cpu: [arm]
242
+
os: [linux]
243
+
244
+
'@esbuild/linux-ia32@0.27.3':
245
+
resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==}
246
+
engines: {node: '>=18'}
247
+
cpu: [ia32]
248
+
os: [linux]
249
+
250
+
'@esbuild/linux-loong64@0.27.3':
251
+
resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==}
252
+
engines: {node: '>=18'}
253
+
cpu: [loong64]
254
+
os: [linux]
255
+
256
+
'@esbuild/linux-mips64el@0.27.3':
257
+
resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==}
258
+
engines: {node: '>=18'}
259
+
cpu: [mips64el]
260
+
os: [linux]
261
+
262
+
'@esbuild/linux-ppc64@0.27.3':
263
+
resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==}
264
+
engines: {node: '>=18'}
265
+
cpu: [ppc64]
266
+
os: [linux]
267
+
268
+
'@esbuild/linux-riscv64@0.27.3':
269
+
resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==}
270
+
engines: {node: '>=18'}
271
+
cpu: [riscv64]
272
+
os: [linux]
273
+
274
+
'@esbuild/linux-s390x@0.27.3':
275
+
resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==}
276
+
engines: {node: '>=18'}
277
+
cpu: [s390x]
278
+
os: [linux]
279
+
280
+
'@esbuild/linux-x64@0.27.3':
281
+
resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==}
282
+
engines: {node: '>=18'}
283
+
cpu: [x64]
284
+
os: [linux]
285
+
286
+
'@esbuild/netbsd-arm64@0.27.3':
287
+
resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==}
288
+
engines: {node: '>=18'}
289
+
cpu: [arm64]
290
+
os: [netbsd]
291
+
292
+
'@esbuild/netbsd-x64@0.27.3':
293
+
resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==}
294
+
engines: {node: '>=18'}
295
+
cpu: [x64]
296
+
os: [netbsd]
297
+
298
+
'@esbuild/openbsd-arm64@0.27.3':
299
+
resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==}
300
+
engines: {node: '>=18'}
301
+
cpu: [arm64]
302
+
os: [openbsd]
303
+
304
+
'@esbuild/openbsd-x64@0.27.3':
305
+
resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==}
306
+
engines: {node: '>=18'}
307
+
cpu: [x64]
308
+
os: [openbsd]
309
+
310
+
'@esbuild/openharmony-arm64@0.27.3':
311
+
resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==}
312
+
engines: {node: '>=18'}
313
+
cpu: [arm64]
314
+
os: [openharmony]
315
+
316
+
'@esbuild/sunos-x64@0.27.3':
317
+
resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==}
318
+
engines: {node: '>=18'}
319
+
cpu: [x64]
320
+
os: [sunos]
321
+
322
+
'@esbuild/win32-arm64@0.27.3':
323
+
resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==}
324
+
engines: {node: '>=18'}
325
+
cpu: [arm64]
326
+
os: [win32]
327
+
328
+
'@esbuild/win32-ia32@0.27.3':
329
+
resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==}
330
+
engines: {node: '>=18'}
331
+
cpu: [ia32]
332
+
os: [win32]
333
+
334
+
'@esbuild/win32-x64@0.27.3':
335
+
resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==}
336
+
engines: {node: '>=18'}
337
+
cpu: [x64]
338
+
os: [win32]
339
+
340
+
'@eslint-community/eslint-utils@4.9.1':
341
+
resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
342
+
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
343
+
peerDependencies:
344
+
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
345
+
346
+
'@eslint-community/regexpp@4.12.2':
347
+
resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
348
+
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
349
+
350
+
'@eslint/config-array@0.21.1':
351
+
resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==}
352
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
353
+
354
+
'@eslint/config-helpers@0.4.2':
355
+
resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==}
356
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
357
+
358
+
'@eslint/core@0.17.0':
359
+
resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
360
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
361
+
362
+
'@eslint/eslintrc@3.3.3':
363
+
resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==}
364
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
365
+
366
+
'@eslint/js@9.39.2':
367
+
resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==}
368
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
369
+
370
+
'@eslint/object-schema@2.1.7':
371
+
resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
372
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
373
+
374
+
'@eslint/plugin-kit@0.4.1':
375
+
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
376
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
377
+
378
+
'@humanfs/core@0.19.1':
379
+
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
380
+
engines: {node: '>=18.18.0'}
381
+
382
+
'@humanfs/node@0.16.7':
383
+
resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==}
384
+
engines: {node: '>=18.18.0'}
385
+
386
+
'@humanwhocodes/module-importer@1.0.1':
387
+
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
388
+
engines: {node: '>=12.22'}
389
+
390
+
'@humanwhocodes/retry@0.4.3':
391
+
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
392
+
engines: {node: '>=18.18'}
393
+
394
+
'@ipld/dag-cbor@7.0.3':
395
+
resolution: {integrity: sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA==}
396
+
397
+
'@noble/curves@1.9.7':
398
+
resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==}
399
+
engines: {node: ^14.21.3 || >=16}
400
+
401
+
'@noble/hashes@1.8.0':
402
+
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
403
+
engines: {node: ^14.21.3 || >=16}
404
+
405
+
'@noble/secp256k1@3.0.0':
406
+
resolution: {integrity: sha512-NJBaR352KyIvj3t6sgT/+7xrNyF9Xk9QlLSIqUGVUYlsnDTAUqY8LOmwpcgEx4AMJXRITQ5XEVHD+mMaPfr3mg==}
407
+
408
+
'@pds-moover/lexicons@1.0.1':
409
+
resolution: {integrity: sha512-fv5b/DtHM7FEo/JklyF9gdK0ainlb6mWjWrBe6cmSAeg9G/4O2jBlQUOqfOAICY9gOcrCpkOrk9PHgGw//JQ2A==}
410
+
411
+
'@rollup/rollup-android-arm-eabi@4.57.1':
412
+
resolution: {integrity: sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==}
413
+
cpu: [arm]
414
+
os: [android]
415
+
416
+
'@rollup/rollup-android-arm64@4.57.1':
417
+
resolution: {integrity: sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==}
418
+
cpu: [arm64]
419
+
os: [android]
420
+
421
+
'@rollup/rollup-darwin-arm64@4.57.1':
422
+
resolution: {integrity: sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==}
423
+
cpu: [arm64]
424
+
os: [darwin]
425
+
426
+
'@rollup/rollup-darwin-x64@4.57.1':
427
+
resolution: {integrity: sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==}
428
+
cpu: [x64]
429
+
os: [darwin]
430
+
431
+
'@rollup/rollup-freebsd-arm64@4.57.1':
432
+
resolution: {integrity: sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==}
433
+
cpu: [arm64]
434
+
os: [freebsd]
435
+
436
+
'@rollup/rollup-freebsd-x64@4.57.1':
437
+
resolution: {integrity: sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==}
438
+
cpu: [x64]
439
+
os: [freebsd]
440
+
441
+
'@rollup/rollup-linux-arm-gnueabihf@4.57.1':
442
+
resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==}
443
+
cpu: [arm]
444
+
os: [linux]
445
+
libc: [glibc]
446
+
447
+
'@rollup/rollup-linux-arm-musleabihf@4.57.1':
448
+
resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==}
449
+
cpu: [arm]
450
+
os: [linux]
451
+
libc: [musl]
452
+
453
+
'@rollup/rollup-linux-arm64-gnu@4.57.1':
454
+
resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==}
455
+
cpu: [arm64]
456
+
os: [linux]
457
+
libc: [glibc]
458
+
459
+
'@rollup/rollup-linux-arm64-musl@4.57.1':
460
+
resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==}
461
+
cpu: [arm64]
462
+
os: [linux]
463
+
libc: [musl]
464
+
465
+
'@rollup/rollup-linux-loong64-gnu@4.57.1':
466
+
resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==}
467
+
cpu: [loong64]
468
+
os: [linux]
469
+
libc: [glibc]
470
+
471
+
'@rollup/rollup-linux-loong64-musl@4.57.1':
472
+
resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==}
473
+
cpu: [loong64]
474
+
os: [linux]
475
+
libc: [musl]
476
+
477
+
'@rollup/rollup-linux-ppc64-gnu@4.57.1':
478
+
resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==}
479
+
cpu: [ppc64]
480
+
os: [linux]
481
+
libc: [glibc]
482
+
483
+
'@rollup/rollup-linux-ppc64-musl@4.57.1':
484
+
resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==}
485
+
cpu: [ppc64]
486
+
os: [linux]
487
+
libc: [musl]
488
+
489
+
'@rollup/rollup-linux-riscv64-gnu@4.57.1':
490
+
resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==}
491
+
cpu: [riscv64]
492
+
os: [linux]
493
+
libc: [glibc]
494
+
495
+
'@rollup/rollup-linux-riscv64-musl@4.57.1':
496
+
resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==}
497
+
cpu: [riscv64]
498
+
os: [linux]
499
+
libc: [musl]
500
+
501
+
'@rollup/rollup-linux-s390x-gnu@4.57.1':
502
+
resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==}
503
+
cpu: [s390x]
504
+
os: [linux]
505
+
libc: [glibc]
506
+
507
+
'@rollup/rollup-linux-x64-gnu@4.57.1':
508
+
resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==}
509
+
cpu: [x64]
510
+
os: [linux]
511
+
libc: [glibc]
512
+
513
+
'@rollup/rollup-linux-x64-musl@4.57.1':
514
+
resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==}
515
+
cpu: [x64]
516
+
os: [linux]
517
+
libc: [musl]
518
+
519
+
'@rollup/rollup-openbsd-x64@4.57.1':
520
+
resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==}
521
+
cpu: [x64]
522
+
os: [openbsd]
523
+
524
+
'@rollup/rollup-openharmony-arm64@4.57.1':
525
+
resolution: {integrity: sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==}
526
+
cpu: [arm64]
527
+
os: [openharmony]
528
+
529
+
'@rollup/rollup-win32-arm64-msvc@4.57.1':
530
+
resolution: {integrity: sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==}
531
+
cpu: [arm64]
532
+
os: [win32]
533
+
534
+
'@rollup/rollup-win32-ia32-msvc@4.57.1':
535
+
resolution: {integrity: sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==}
536
+
cpu: [ia32]
537
+
os: [win32]
538
+
539
+
'@rollup/rollup-win32-x64-gnu@4.57.1':
540
+
resolution: {integrity: sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==}
541
+
cpu: [x64]
542
+
os: [win32]
543
+
544
+
'@rollup/rollup-win32-x64-msvc@4.57.1':
545
+
resolution: {integrity: sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==}
546
+
cpu: [x64]
547
+
os: [win32]
548
+
549
+
'@rtsao/scc@1.1.0':
550
+
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
551
+
552
+
'@standard-schema/spec@1.1.0':
553
+
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
554
+
555
+
'@ts-morph/common@0.28.1':
556
+
resolution: {integrity: sha512-W74iWf7ILp1ZKNYXY5qbddNaml7e9Sedv5lvU1V8lftlitkc9Pq1A+jlH23ltDgWYeZFFEqGCD1Ies9hqu3O+g==}
557
+
558
+
'@types/estree@1.0.8':
559
+
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
560
+
561
+
'@types/json-schema@7.0.15':
562
+
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
563
+
564
+
'@types/json5@0.0.29':
565
+
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
566
+
567
+
'@vue/reactivity@3.1.5':
568
+
resolution: {integrity: sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==}
569
+
570
+
'@vue/shared@3.1.5':
571
+
resolution: {integrity: sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==}
572
+
573
+
abort-controller@3.0.0:
574
+
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
575
+
engines: {node: '>=6.5'}
576
+
577
+
acorn-jsx@5.3.2:
578
+
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
579
+
peerDependencies:
580
+
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
581
+
582
+
acorn@8.15.0:
583
+
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
584
+
engines: {node: '>=0.4.0'}
585
+
hasBin: true
586
+
587
+
ajv@6.12.6:
588
+
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
589
+
590
+
alpinejs@3.15.8:
591
+
resolution: {integrity: sha512-zxIfCRTBGvF1CCLIOMQOxAyBuqibxSEwS6Jm1a3HGA9rgrJVcjEWlwLcQTVGAWGS8YhAsTRLVrtQ5a5QT9bSSQ==}
592
+
593
+
ansi-regex@5.0.1:
594
+
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
595
+
engines: {node: '>=8'}
596
+
597
+
ansi-styles@4.3.0:
598
+
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
599
+
engines: {node: '>=8'}
600
+
601
+
argparse@2.0.1:
602
+
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
603
+
604
+
array-buffer-byte-length@1.0.2:
605
+
resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
606
+
engines: {node: '>= 0.4'}
607
+
608
+
array-includes@3.1.9:
609
+
resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
610
+
engines: {node: '>= 0.4'}
611
+
612
+
array.prototype.findlastindex@1.2.6:
613
+
resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==}
614
+
engines: {node: '>= 0.4'}
615
+
616
+
array.prototype.flat@1.3.3:
617
+
resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
618
+
engines: {node: '>= 0.4'}
619
+
620
+
array.prototype.flatmap@1.3.3:
621
+
resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==}
622
+
engines: {node: '>= 0.4'}
623
+
624
+
arraybuffer.prototype.slice@1.0.4:
625
+
resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
626
+
engines: {node: '>= 0.4'}
627
+
628
+
async-function@1.0.0:
629
+
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
630
+
engines: {node: '>= 0.4'}
631
+
632
+
atomic-sleep@1.0.0:
633
+
resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
634
+
engines: {node: '>=8.0.0'}
635
+
636
+
available-typed-arrays@1.0.7:
637
+
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
638
+
engines: {node: '>= 0.4'}
639
+
640
+
await-lock@2.2.2:
641
+
resolution: {integrity: sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==}
642
+
643
+
balanced-match@1.0.2:
644
+
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
645
+
646
+
balanced-match@4.0.3:
647
+
resolution: {integrity: sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==}
648
+
engines: {node: 20 || >=22}
649
+
650
+
base64-js@1.5.1:
651
+
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
652
+
653
+
brace-expansion@1.1.12:
654
+
resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
655
+
656
+
brace-expansion@5.0.2:
657
+
resolution: {integrity: sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==}
658
+
engines: {node: 20 || >=22}
659
+
660
+
buffer@6.0.3:
661
+
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
662
+
663
+
call-bind-apply-helpers@1.0.2:
664
+
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
665
+
engines: {node: '>= 0.4'}
666
+
667
+
call-bind@1.0.8:
668
+
resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
669
+
engines: {node: '>= 0.4'}
670
+
671
+
call-bound@1.0.4:
672
+
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
673
+
engines: {node: '>= 0.4'}
674
+
675
+
callsites@3.1.0:
676
+
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
677
+
engines: {node: '>=6'}
678
+
679
+
cborg@1.10.2:
680
+
resolution: {integrity: sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==}
681
+
hasBin: true
682
+
683
+
chalk@4.1.2:
684
+
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
685
+
engines: {node: '>=10'}
686
+
687
+
cliui@8.0.1:
688
+
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
689
+
engines: {node: '>=12'}
690
+
691
+
code-block-writer@13.0.3:
692
+
resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==}
693
+
694
+
color-convert@2.0.1:
695
+
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
696
+
engines: {node: '>=7.0.0'}
697
+
698
+
color-name@1.1.4:
699
+
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
700
+
701
+
concat-map@0.0.1:
702
+
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
703
+
704
+
core-js@3.48.0:
705
+
resolution: {integrity: sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==}
706
+
707
+
cross-spawn@7.0.6:
708
+
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
709
+
engines: {node: '>= 8'}
710
+
711
+
data-view-buffer@1.0.2:
712
+
resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
713
+
engines: {node: '>= 0.4'}
714
+
715
+
data-view-byte-length@1.0.2:
716
+
resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==}
717
+
engines: {node: '>= 0.4'}
718
+
719
+
data-view-byte-offset@1.0.1:
720
+
resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
721
+
engines: {node: '>= 0.4'}
722
+
723
+
debug@3.2.7:
724
+
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
725
+
peerDependencies:
726
+
supports-color: '*'
727
+
peerDependenciesMeta:
728
+
supports-color:
729
+
optional: true
730
+
731
+
debug@4.4.3:
732
+
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
733
+
engines: {node: '>=6.0'}
734
+
peerDependencies:
735
+
supports-color: '*'
736
+
peerDependenciesMeta:
737
+
supports-color:
738
+
optional: true
739
+
740
+
deep-is@0.1.4:
741
+
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
742
+
743
+
define-data-property@1.1.4:
744
+
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
745
+
engines: {node: '>= 0.4'}
746
+
747
+
define-properties@1.2.1:
748
+
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
749
+
engines: {node: '>= 0.4'}
750
+
751
+
doctrine@2.1.0:
752
+
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
753
+
engines: {node: '>=0.10.0'}
754
+
755
+
dunder-proto@1.0.1:
756
+
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
757
+
engines: {node: '>= 0.4'}
758
+
759
+
emoji-regex@8.0.0:
760
+
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
761
+
762
+
es-abstract@1.24.1:
763
+
resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==}
764
+
engines: {node: '>= 0.4'}
765
+
766
+
es-define-property@1.0.1:
767
+
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
768
+
engines: {node: '>= 0.4'}
769
+
770
+
es-errors@1.3.0:
771
+
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
772
+
engines: {node: '>= 0.4'}
773
+
774
+
es-object-atoms@1.1.1:
775
+
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
776
+
engines: {node: '>= 0.4'}
777
+
778
+
es-set-tostringtag@2.1.0:
779
+
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
780
+
engines: {node: '>= 0.4'}
781
+
782
+
es-shim-unscopables@1.1.0:
783
+
resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==}
784
+
engines: {node: '>= 0.4'}
785
+
786
+
es-to-primitive@1.3.0:
787
+
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
788
+
engines: {node: '>= 0.4'}
789
+
790
+
esbuild@0.27.3:
791
+
resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==}
792
+
engines: {node: '>=18'}
793
+
hasBin: true
794
+
795
+
escalade@3.2.0:
796
+
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
797
+
engines: {node: '>=6'}
798
+
799
+
escape-string-regexp@4.0.0:
800
+
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
801
+
engines: {node: '>=10'}
802
+
803
+
eslint-import-resolver-node@0.3.9:
804
+
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
805
+
806
+
eslint-module-utils@2.12.1:
807
+
resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==}
808
+
engines: {node: '>=4'}
809
+
peerDependencies:
810
+
'@typescript-eslint/parser': '*'
811
+
eslint: '*'
812
+
eslint-import-resolver-node: '*'
813
+
eslint-import-resolver-typescript: '*'
814
+
eslint-import-resolver-webpack: '*'
815
+
peerDependenciesMeta:
816
+
'@typescript-eslint/parser':
817
+
optional: true
818
+
eslint:
819
+
optional: true
820
+
eslint-import-resolver-node:
821
+
optional: true
822
+
eslint-import-resolver-typescript:
823
+
optional: true
824
+
eslint-import-resolver-webpack:
825
+
optional: true
826
+
827
+
eslint-plugin-import@2.32.0:
828
+
resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==}
829
+
engines: {node: '>=4'}
830
+
peerDependencies:
831
+
'@typescript-eslint/parser': '*'
832
+
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9
833
+
peerDependenciesMeta:
834
+
'@typescript-eslint/parser':
835
+
optional: true
836
+
837
+
eslint-scope@8.4.0:
838
+
resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
839
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
840
+
841
+
eslint-visitor-keys@3.4.3:
842
+
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
843
+
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
844
+
845
+
eslint-visitor-keys@4.2.1:
846
+
resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
847
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
848
+
849
+
eslint@9.39.2:
850
+
resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==}
851
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
852
+
hasBin: true
853
+
peerDependencies:
854
+
jiti: '*'
855
+
peerDependenciesMeta:
856
+
jiti:
857
+
optional: true
858
+
859
+
esm-env@1.2.2:
860
+
resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==}
861
+
862
+
espree@10.4.0:
863
+
resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
864
+
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
865
+
866
+
esquery@1.7.0:
867
+
resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==}
868
+
engines: {node: '>=0.10'}
869
+
870
+
esrecurse@4.3.0:
871
+
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
872
+
engines: {node: '>=4.0'}
873
+
874
+
estraverse@5.3.0:
875
+
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
876
+
engines: {node: '>=4.0'}
877
+
878
+
esutils@2.0.3:
879
+
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
880
+
engines: {node: '>=0.10.0'}
881
+
882
+
event-target-shim@5.0.1:
883
+
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
884
+
engines: {node: '>=6'}
885
+
886
+
events@3.3.0:
887
+
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
888
+
engines: {node: '>=0.8.x'}
889
+
890
+
fast-deep-equal@3.1.3:
891
+
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
892
+
893
+
fast-json-stable-stringify@2.1.0:
894
+
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
895
+
896
+
fast-levenshtein@2.0.6:
897
+
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
898
+
899
+
fast-redact@3.5.0:
900
+
resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==}
901
+
engines: {node: '>=6'}
902
+
903
+
fdir@6.5.0:
904
+
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
905
+
engines: {node: '>=12.0.0'}
906
+
peerDependencies:
907
+
picomatch: ^3 || ^4
908
+
peerDependenciesMeta:
909
+
picomatch:
910
+
optional: true
911
+
912
+
file-entry-cache@8.0.0:
913
+
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
914
+
engines: {node: '>=16.0.0'}
915
+
916
+
find-up@5.0.0:
917
+
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
918
+
engines: {node: '>=10'}
919
+
920
+
flat-cache@4.0.1:
921
+
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
922
+
engines: {node: '>=16'}
923
+
924
+
flatted@3.3.3:
925
+
resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
926
+
927
+
for-each@0.3.5:
928
+
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
929
+
engines: {node: '>= 0.4'}
930
+
931
+
fsevents@2.3.3:
932
+
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
933
+
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
934
+
os: [darwin]
935
+
936
+
function-bind@1.1.2:
937
+
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
938
+
939
+
function.prototype.name@1.1.8:
940
+
resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
941
+
engines: {node: '>= 0.4'}
942
+
943
+
functions-have-names@1.2.3:
944
+
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
945
+
946
+
generator-function@2.0.1:
947
+
resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
948
+
engines: {node: '>= 0.4'}
949
+
950
+
get-caller-file@2.0.5:
951
+
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
952
+
engines: {node: 6.* || 8.* || >= 10.*}
953
+
954
+
get-intrinsic@1.3.0:
955
+
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
956
+
engines: {node: '>= 0.4'}
957
+
958
+
get-proto@1.0.1:
959
+
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
960
+
engines: {node: '>= 0.4'}
961
+
962
+
get-symbol-description@1.1.0:
963
+
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
964
+
engines: {node: '>= 0.4'}
965
+
966
+
glob-parent@6.0.2:
967
+
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
968
+
engines: {node: '>=10.13.0'}
969
+
970
+
globals@14.0.0:
971
+
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
972
+
engines: {node: '>=18'}
973
+
974
+
globalthis@1.0.4:
975
+
resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
976
+
engines: {node: '>= 0.4'}
977
+
978
+
gopd@1.2.0:
979
+
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
980
+
engines: {node: '>= 0.4'}
981
+
982
+
has-bigints@1.1.0:
983
+
resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
984
+
engines: {node: '>= 0.4'}
985
+
986
+
has-flag@4.0.0:
987
+
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
988
+
engines: {node: '>=8'}
989
+
990
+
has-property-descriptors@1.0.2:
991
+
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
992
+
993
+
has-proto@1.2.0:
994
+
resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==}
995
+
engines: {node: '>= 0.4'}
996
+
997
+
has-symbols@1.1.0:
998
+
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
999
+
engines: {node: '>= 0.4'}
1000
+
1001
+
has-tostringtag@1.0.2:
1002
+
resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
1003
+
engines: {node: '>= 0.4'}
1004
+
1005
+
hasown@2.0.2:
1006
+
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
1007
+
engines: {node: '>= 0.4'}
1008
+
1009
+
ieee754@1.2.1:
1010
+
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
1011
+
1012
+
ignore@5.3.2:
1013
+
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
1014
+
engines: {node: '>= 4'}
1015
+
1016
+
import-fresh@3.3.1:
1017
+
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
1018
+
engines: {node: '>=6'}
1019
+
1020
+
imurmurhash@0.1.4:
1021
+
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
1022
+
engines: {node: '>=0.8.19'}
1023
+
1024
+
internal-slot@1.1.0:
1025
+
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
1026
+
engines: {node: '>= 0.4'}
1027
+
1028
+
is-array-buffer@3.0.5:
1029
+
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
1030
+
engines: {node: '>= 0.4'}
1031
+
1032
+
is-async-function@2.1.1:
1033
+
resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
1034
+
engines: {node: '>= 0.4'}
1035
+
1036
+
is-bigint@1.1.0:
1037
+
resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
1038
+
engines: {node: '>= 0.4'}
1039
+
1040
+
is-boolean-object@1.2.2:
1041
+
resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
1042
+
engines: {node: '>= 0.4'}
1043
+
1044
+
is-callable@1.2.7:
1045
+
resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
1046
+
engines: {node: '>= 0.4'}
1047
+
1048
+
is-core-module@2.16.1:
1049
+
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
1050
+
engines: {node: '>= 0.4'}
1051
+
1052
+
is-data-view@1.0.2:
1053
+
resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
1054
+
engines: {node: '>= 0.4'}
1055
+
1056
+
is-date-object@1.1.0:
1057
+
resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
1058
+
engines: {node: '>= 0.4'}
1059
+
1060
+
is-extglob@2.1.1:
1061
+
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
1062
+
engines: {node: '>=0.10.0'}
1063
+
1064
+
is-finalizationregistry@1.1.1:
1065
+
resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
1066
+
engines: {node: '>= 0.4'}
1067
+
1068
+
is-fullwidth-code-point@3.0.0:
1069
+
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
1070
+
engines: {node: '>=8'}
1071
+
1072
+
is-generator-function@1.1.2:
1073
+
resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
1074
+
engines: {node: '>= 0.4'}
1075
+
1076
+
is-glob@4.0.3:
1077
+
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
1078
+
engines: {node: '>=0.10.0'}
1079
+
1080
+
is-map@2.0.3:
1081
+
resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
1082
+
engines: {node: '>= 0.4'}
1083
+
1084
+
is-negative-zero@2.0.3:
1085
+
resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
1086
+
engines: {node: '>= 0.4'}
1087
+
1088
+
is-number-object@1.1.1:
1089
+
resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
1090
+
engines: {node: '>= 0.4'}
1091
+
1092
+
is-regex@1.2.1:
1093
+
resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
1094
+
engines: {node: '>= 0.4'}
1095
+
1096
+
is-set@2.0.3:
1097
+
resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==}
1098
+
engines: {node: '>= 0.4'}
1099
+
1100
+
is-shared-array-buffer@1.0.4:
1101
+
resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
1102
+
engines: {node: '>= 0.4'}
1103
+
1104
+
is-string@1.1.1:
1105
+
resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
1106
+
engines: {node: '>= 0.4'}
1107
+
1108
+
is-symbol@1.1.1:
1109
+
resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
1110
+
engines: {node: '>= 0.4'}
1111
+
1112
+
is-typed-array@1.1.15:
1113
+
resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
1114
+
engines: {node: '>= 0.4'}
1115
+
1116
+
is-weakmap@2.0.2:
1117
+
resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
1118
+
engines: {node: '>= 0.4'}
1119
+
1120
+
is-weakref@1.1.1:
1121
+
resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==}
1122
+
engines: {node: '>= 0.4'}
1123
+
1124
+
is-weakset@2.0.4:
1125
+
resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
1126
+
engines: {node: '>= 0.4'}
1127
+
1128
+
isarray@2.0.5:
1129
+
resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
1130
+
1131
+
isexe@2.0.0:
1132
+
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
1133
+
1134
+
iso-datestring-validator@2.2.2:
1135
+
resolution: {integrity: sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==}
1136
+
1137
+
js-yaml@4.1.1:
1138
+
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
1139
+
hasBin: true
1140
+
1141
+
json-buffer@3.0.1:
1142
+
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
1143
+
1144
+
json-schema-traverse@0.4.1:
1145
+
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
1146
+
1147
+
json-stable-stringify-without-jsonify@1.0.1:
1148
+
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
1149
+
1150
+
json5@1.0.2:
1151
+
resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
1152
+
hasBin: true
1153
+
1154
+
keyv@4.5.4:
1155
+
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
1156
+
1157
+
levn@0.4.1:
1158
+
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
1159
+
engines: {node: '>= 0.8.0'}
1160
+
1161
+
locate-path@6.0.0:
1162
+
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
1163
+
engines: {node: '>=10'}
1164
+
1165
+
lodash.merge@4.6.2:
1166
+
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
1167
+
1168
+
lru-cache@10.4.3:
1169
+
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
1170
+
1171
+
math-intrinsics@1.1.0:
1172
+
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
1173
+
engines: {node: '>= 0.4'}
1174
+
1175
+
minimatch@10.2.1:
1176
+
resolution: {integrity: sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==}
1177
+
engines: {node: 20 || >=22}
1178
+
1179
+
minimatch@3.1.2:
1180
+
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
1181
+
1182
+
minimist@1.2.8:
1183
+
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
1184
+
1185
+
ms@2.1.3:
1186
+
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
1187
+
1188
+
multiformats@9.9.0:
1189
+
resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==}
1190
+
1191
+
nanoid@3.3.11:
1192
+
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
1193
+
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
1194
+
hasBin: true
1195
+
1196
+
natural-compare@1.4.0:
1197
+
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
1198
+
1199
+
object-inspect@1.13.4:
1200
+
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
1201
+
engines: {node: '>= 0.4'}
1202
+
1203
+
object-keys@1.1.1:
1204
+
resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
1205
+
engines: {node: '>= 0.4'}
1206
+
1207
+
object.assign@4.1.7:
1208
+
resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==}
1209
+
engines: {node: '>= 0.4'}
1210
+
1211
+
object.fromentries@2.0.8:
1212
+
resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
1213
+
engines: {node: '>= 0.4'}
1214
+
1215
+
object.groupby@1.0.3:
1216
+
resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==}
1217
+
engines: {node: '>= 0.4'}
1218
+
1219
+
object.values@1.2.1:
1220
+
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
1221
+
engines: {node: '>= 0.4'}
1222
+
1223
+
on-exit-leak-free@2.1.2:
1224
+
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
1225
+
engines: {node: '>=14.0.0'}
1226
+
1227
+
optionator@0.9.4:
1228
+
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
1229
+
engines: {node: '>= 0.8.0'}
1230
+
1231
+
own-keys@1.0.1:
1232
+
resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
1233
+
engines: {node: '>= 0.4'}
1234
+
1235
+
p-limit@3.1.0:
1236
+
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
1237
+
engines: {node: '>=10'}
1238
+
1239
+
p-locate@5.0.0:
1240
+
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
1241
+
engines: {node: '>=10'}
1242
+
1243
+
parent-module@1.0.1:
1244
+
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
1245
+
engines: {node: '>=6'}
1246
+
1247
+
path-browserify@1.0.1:
1248
+
resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
1249
+
1250
+
path-exists@4.0.0:
1251
+
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
1252
+
engines: {node: '>=8'}
1253
+
1254
+
path-key@3.1.1:
1255
+
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
1256
+
engines: {node: '>=8'}
1257
+
1258
+
path-parse@1.0.7:
1259
+
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
1260
+
1261
+
picocolors@1.1.1:
1262
+
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
1263
+
1264
+
picomatch@2.3.1:
1265
+
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
1266
+
engines: {node: '>=8.6'}
1267
+
1268
+
picomatch@4.0.3:
1269
+
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
1270
+
engines: {node: '>=12'}
1271
+
1272
+
pino-abstract-transport@1.2.0:
1273
+
resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==}
1274
+
1275
+
pino-std-serializers@6.2.2:
1276
+
resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==}
1277
+
1278
+
pino@8.21.0:
1279
+
resolution: {integrity: sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==}
1280
+
hasBin: true
1281
+
1282
+
possible-typed-array-names@1.1.0:
1283
+
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
1284
+
engines: {node: '>= 0.4'}
1285
+
1286
+
postcss@8.5.6:
1287
+
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
1288
+
engines: {node: ^10 || ^12 || >=14}
1289
+
1290
+
prelude-ls@1.2.1:
1291
+
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
1292
+
engines: {node: '>= 0.8.0'}
1293
+
1294
+
prettier@3.8.1:
1295
+
resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==}
1296
+
engines: {node: '>=14'}
1297
+
hasBin: true
1298
+
1299
+
process-warning@3.0.0:
1300
+
resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==}
1301
+
1302
+
process@0.11.10:
1303
+
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
1304
+
engines: {node: '>= 0.6.0'}
1305
+
1306
+
punycode@2.3.1:
1307
+
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
1308
+
engines: {node: '>=6'}
1309
+
1310
+
quick-format-unescaped@4.0.4:
1311
+
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
1312
+
1313
+
readable-stream@4.7.0:
1314
+
resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==}
1315
+
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
1316
+
1317
+
real-require@0.2.0:
1318
+
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
1319
+
engines: {node: '>= 12.13.0'}
1320
+
1321
+
reflect.getprototypeof@1.0.10:
1322
+
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
1323
+
engines: {node: '>= 0.4'}
1324
+
1325
+
regexp.prototype.flags@1.5.4:
1326
+
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
1327
+
engines: {node: '>= 0.4'}
1328
+
1329
+
require-directory@2.1.1:
1330
+
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
1331
+
engines: {node: '>=0.10.0'}
1332
+
1333
+
resolve-from@4.0.0:
1334
+
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
1335
+
engines: {node: '>=4'}
1336
+
1337
+
resolve@1.22.11:
1338
+
resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
1339
+
engines: {node: '>= 0.4'}
1340
+
hasBin: true
1341
+
1342
+
rollup@4.57.1:
1343
+
resolution: {integrity: sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==}
1344
+
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
1345
+
hasBin: true
1346
+
1347
+
safe-array-concat@1.1.3:
1348
+
resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
1349
+
engines: {node: '>=0.4'}
1350
+
1351
+
safe-buffer@5.2.1:
1352
+
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
1353
+
1354
+
safe-push-apply@1.0.0:
1355
+
resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
1356
+
engines: {node: '>= 0.4'}
1357
+
1358
+
safe-regex-test@1.1.0:
1359
+
resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
1360
+
engines: {node: '>= 0.4'}
1361
+
1362
+
safe-stable-stringify@2.5.0:
1363
+
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
1364
+
engines: {node: '>=10'}
1365
+
1366
+
semver@6.3.1:
1367
+
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
1368
+
hasBin: true
1369
+
1370
+
set-function-length@1.2.2:
1371
+
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
1372
+
engines: {node: '>= 0.4'}
1373
+
1374
+
set-function-name@2.0.2:
1375
+
resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
1376
+
engines: {node: '>= 0.4'}
1377
+
1378
+
set-proto@1.0.0:
1379
+
resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
1380
+
engines: {node: '>= 0.4'}
1381
+
1382
+
shebang-command@2.0.0:
1383
+
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
1384
+
engines: {node: '>=8'}
1385
+
1386
+
shebang-regex@3.0.0:
1387
+
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
1388
+
engines: {node: '>=8'}
1389
+
1390
+
side-channel-list@1.0.0:
1391
+
resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
1392
+
engines: {node: '>= 0.4'}
1393
+
1394
+
side-channel-map@1.0.1:
1395
+
resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
1396
+
engines: {node: '>= 0.4'}
1397
+
1398
+
side-channel-weakmap@1.0.2:
1399
+
resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
1400
+
engines: {node: '>= 0.4'}
1401
+
1402
+
side-channel@1.1.0:
1403
+
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
1404
+
engines: {node: '>= 0.4'}
1405
+
1406
+
sonic-boom@3.8.1:
1407
+
resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==}
1408
+
1409
+
source-map-js@1.2.1:
1410
+
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
1411
+
engines: {node: '>=0.10.0'}
1412
+
1413
+
split2@4.2.0:
1414
+
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
1415
+
engines: {node: '>= 10.x'}
1416
+
1417
+
stop-iteration-iterator@1.1.0:
1418
+
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
1419
+
engines: {node: '>= 0.4'}
1420
+
1421
+
string-width@4.2.3:
1422
+
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
1423
+
engines: {node: '>=8'}
1424
+
1425
+
string.prototype.trim@1.2.10:
1426
+
resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==}
1427
+
engines: {node: '>= 0.4'}
1428
+
1429
+
string.prototype.trimend@1.0.9:
1430
+
resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==}
1431
+
engines: {node: '>= 0.4'}
1432
+
1433
+
string.prototype.trimstart@1.0.8:
1434
+
resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
1435
+
engines: {node: '>= 0.4'}
1436
+
1437
+
string_decoder@1.3.0:
1438
+
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
1439
+
1440
+
strip-ansi@6.0.1:
1441
+
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
1442
+
engines: {node: '>=8'}
1443
+
1444
+
strip-bom@3.0.0:
1445
+
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
1446
+
engines: {node: '>=4'}
1447
+
1448
+
strip-json-comments@3.1.1:
1449
+
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
1450
+
engines: {node: '>=8'}
1451
+
1452
+
supports-color@7.2.0:
1453
+
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
1454
+
engines: {node: '>=8'}
1455
+
1456
+
supports-preserve-symlinks-flag@1.0.0:
1457
+
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
1458
+
engines: {node: '>= 0.4'}
1459
+
1460
+
thread-stream@2.7.0:
1461
+
resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==}
1462
+
1463
+
tinyglobby@0.2.15:
1464
+
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
1465
+
engines: {node: '>=12.0.0'}
1466
+
1467
+
tlds@1.261.0:
1468
+
resolution: {integrity: sha512-QXqwfEl9ddlGBaRFXIvNKK6OhipSiLXuRuLJX5DErz0o0Q0rYxulWLdFryTkV5PkdZct5iMInwYEGe/eR++1AA==}
1469
+
hasBin: true
1470
+
1471
+
ts-morph@27.0.2:
1472
+
resolution: {integrity: sha512-fhUhgeljcrdZ+9DZND1De1029PrE+cMkIP7ooqkLRTrRLTqcki2AstsyJm0vRNbTbVCNJ0idGlbBrfqc7/nA8w==}
1473
+
1474
+
tsconfig-paths@3.15.0:
1475
+
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
1476
+
1477
+
tslib@2.8.1:
1478
+
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
1479
+
1480
+
type-check@0.4.0:
1481
+
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
1482
+
engines: {node: '>= 0.8.0'}
1483
+
1484
+
typed-array-buffer@1.0.3:
1485
+
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
1486
+
engines: {node: '>= 0.4'}
1487
+
1488
+
typed-array-byte-length@1.0.3:
1489
+
resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==}
1490
+
engines: {node: '>= 0.4'}
1491
+
1492
+
typed-array-byte-offset@1.0.4:
1493
+
resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==}
1494
+
engines: {node: '>= 0.4'}
1495
+
1496
+
typed-array-length@1.0.7:
1497
+
resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
1498
+
engines: {node: '>= 0.4'}
1499
+
1500
+
uint8arrays@3.0.0:
1501
+
resolution: {integrity: sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==}
1502
+
1503
+
unbox-primitive@1.1.0:
1504
+
resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
1505
+
engines: {node: '>= 0.4'}
1506
+
1507
+
unicode-segmenter@0.14.5:
1508
+
resolution: {integrity: sha512-jHGmj2LUuqDcX3hqY12Ql+uhUTn8huuxNZGq7GvtF6bSybzH3aFgedYu/KTzQStEgt1Ra2F3HxadNXsNjb3m3g==}
1509
+
1510
+
uri-js@4.4.1:
1511
+
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
1512
+
1513
+
varint@6.0.0:
1514
+
resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==}
1515
+
1516
+
vite-plugin-full-reload@1.2.0:
1517
+
resolution: {integrity: sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA==}
1518
+
1519
+
vite-rs-plugin@1.0.1:
1520
+
resolution: {integrity: sha512-YhgflKQIRzuS5x66J3yICoVLH25D2fNU+jThK8tpYl/jGrXeIKT4w5VH1lkLPRC0SjK2ZCm9S6K9Z2ZFVDHjPQ==}
1521
+
hasBin: true
1522
+
peerDependencies:
1523
+
vite: ^5.0.0
1524
+
1525
+
vite@7.3.1:
1526
+
resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
1527
+
engines: {node: ^20.19.0 || >=22.12.0}
1528
+
hasBin: true
1529
+
peerDependencies:
1530
+
'@types/node': ^20.19.0 || >=22.12.0
1531
+
jiti: '>=1.21.0'
1532
+
less: ^4.0.0
1533
+
lightningcss: ^1.21.0
1534
+
sass: ^1.70.0
1535
+
sass-embedded: ^1.70.0
1536
+
stylus: '>=0.54.8'
1537
+
sugarss: ^5.0.0
1538
+
terser: ^5.16.0
1539
+
tsx: ^4.8.1
1540
+
yaml: ^2.4.2
1541
+
peerDependenciesMeta:
1542
+
'@types/node':
1543
+
optional: true
1544
+
jiti:
1545
+
optional: true
1546
+
less:
1547
+
optional: true
1548
+
lightningcss:
1549
+
optional: true
1550
+
sass:
1551
+
optional: true
1552
+
sass-embedded:
1553
+
optional: true
1554
+
stylus:
1555
+
optional: true
1556
+
sugarss:
1557
+
optional: true
1558
+
terser:
1559
+
optional: true
1560
+
tsx:
1561
+
optional: true
1562
+
yaml:
1563
+
optional: true
1564
+
1565
+
which-boxed-primitive@1.1.1:
1566
+
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
1567
+
engines: {node: '>= 0.4'}
1568
+
1569
+
which-builtin-type@1.2.1:
1570
+
resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
1571
+
engines: {node: '>= 0.4'}
1572
+
1573
+
which-collection@1.0.2:
1574
+
resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==}
1575
+
engines: {node: '>= 0.4'}
1576
+
1577
+
which-typed-array@1.1.20:
1578
+
resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==}
1579
+
engines: {node: '>= 0.4'}
1580
+
1581
+
which@2.0.2:
1582
+
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
1583
+
engines: {node: '>= 8'}
1584
+
hasBin: true
1585
+
1586
+
word-wrap@1.2.5:
1587
+
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
1588
+
engines: {node: '>=0.10.0'}
1589
+
1590
+
wrap-ansi@7.0.0:
1591
+
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
1592
+
engines: {node: '>=10'}
1593
+
1594
+
y18n@5.0.8:
1595
+
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
1596
+
engines: {node: '>=10'}
1597
+
1598
+
yargs-parser@21.1.1:
1599
+
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
1600
+
engines: {node: '>=12'}
1601
+
1602
+
yargs@17.7.2:
1603
+
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
1604
+
engines: {node: '>=12'}
1605
+
1606
+
yocto-queue@0.1.0:
1607
+
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
1608
+
engines: {node: '>=10'}
1609
+
1610
+
zod@3.25.76:
1611
+
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
1612
+
1613
+
snapshots:
1614
+
1615
+
'@atcute/cbor@2.3.0':
1616
+
dependencies:
1617
+
'@atcute/cid': 2.4.0
1618
+
'@atcute/multibase': 1.1.7
1619
+
'@atcute/uint8array': 1.1.0
1620
+
1621
+
'@atcute/cid@2.4.0':
1622
+
dependencies:
1623
+
'@atcute/multibase': 1.1.7
1624
+
'@atcute/uint8array': 1.1.0
1625
+
1626
+
'@atcute/client@4.2.1':
1627
+
dependencies:
1628
+
'@atcute/identity': 1.1.3
1629
+
'@atcute/lexicons': 1.2.7
1630
+
1631
+
'@atcute/crypto@2.3.0':
1632
+
dependencies:
1633
+
'@atcute/multibase': 1.1.7
1634
+
'@atcute/uint8array': 1.1.0
1635
+
'@noble/secp256k1': 3.0.0
1636
+
1637
+
'@atcute/did-plc@0.1.7':
1638
+
dependencies:
1639
+
'@atcute/cbor': 2.3.0
1640
+
'@atcute/cid': 2.4.0
1641
+
'@atcute/crypto': 2.3.0
1642
+
'@atcute/identity': 1.1.3
1643
+
'@atcute/lexicons': 1.2.7
1644
+
'@atcute/multibase': 1.1.7
1645
+
'@atcute/uint8array': 1.1.0
1646
+
'@badrap/valita': 0.4.6
1647
+
1648
+
'@atcute/identity-resolver@1.2.2(@atcute/identity@1.1.3)':
1649
+
dependencies:
1650
+
'@atcute/identity': 1.1.3
1651
+
'@atcute/lexicons': 1.2.7
1652
+
'@atcute/util-fetch': 1.0.5
1653
+
'@badrap/valita': 0.4.6
1654
+
1655
+
'@atcute/identity@1.1.3':
1656
+
dependencies:
1657
+
'@atcute/lexicons': 1.2.7
1658
+
'@badrap/valita': 0.4.6
1659
+
1660
+
'@atcute/lexicons@1.2.7':
1661
+
dependencies:
1662
+
'@atcute/uint8array': 1.1.0
1663
+
'@atcute/util-text': 1.1.0
1664
+
'@standard-schema/spec': 1.1.0
1665
+
esm-env: 1.2.2
1666
+
1667
+
'@atcute/multibase@1.1.7':
1668
+
dependencies:
1669
+
'@atcute/uint8array': 1.1.0
1670
+
1671
+
'@atcute/uint8array@1.1.0': {}
1672
+
1673
+
'@atcute/util-fetch@1.0.5':
1674
+
dependencies:
1675
+
'@badrap/valita': 0.4.6
1676
+
1677
+
'@atcute/util-text@1.1.0':
1678
+
dependencies:
1679
+
unicode-segmenter: 0.14.5
1680
+
1681
+
'@atproto-labs/did-resolver@0.2.6':
1682
+
dependencies:
1683
+
'@atproto-labs/fetch': 0.2.3
1684
+
'@atproto-labs/pipe': 0.1.1
1685
+
'@atproto-labs/simple-store': 0.3.0
1686
+
'@atproto-labs/simple-store-memory': 0.1.4
1687
+
'@atproto/did': 0.3.0
1688
+
zod: 3.25.76
1689
+
1690
+
'@atproto-labs/fetch@0.2.3':
1691
+
dependencies:
1692
+
'@atproto-labs/pipe': 0.1.1
1693
+
1694
+
'@atproto-labs/pipe@0.1.1': {}
1695
+
1696
+
'@atproto-labs/simple-store-memory@0.1.4':
1697
+
dependencies:
1698
+
'@atproto-labs/simple-store': 0.3.0
1699
+
lru-cache: 10.4.3
1700
+
1701
+
'@atproto-labs/simple-store@0.3.0': {}
1702
+
1703
+
'@atproto/api@0.16.11':
1704
+
dependencies:
1705
+
'@atproto/common-web': 0.4.16
1706
+
'@atproto/lexicon': 0.5.2
1707
+
'@atproto/syntax': 0.4.3
1708
+
'@atproto/xrpc': 0.7.7
1709
+
await-lock: 2.2.2
1710
+
multiformats: 9.9.0
1711
+
tlds: 1.261.0
1712
+
zod: 3.25.76
1713
+
1714
+
'@atproto/common-web@0.4.16':
1715
+
dependencies:
1716
+
'@atproto/lex-data': 0.0.11
1717
+
'@atproto/lex-json': 0.0.11
1718
+
'@atproto/syntax': 0.4.3
1719
+
zod: 3.25.76
1720
+
1721
+
'@atproto/common@0.5.11':
1722
+
dependencies:
1723
+
'@atproto/common-web': 0.4.16
1724
+
'@atproto/lex-cbor': 0.0.11
1725
+
'@atproto/lex-data': 0.0.11
1726
+
iso-datestring-validator: 2.2.2
1727
+
multiformats: 9.9.0
1728
+
pino: 8.21.0
1729
+
1730
+
'@atproto/crypto@0.4.5':
1731
+
dependencies:
1732
+
'@noble/curves': 1.9.7
1733
+
'@noble/hashes': 1.8.0
1734
+
uint8arrays: 3.0.0
1735
+
1736
+
'@atproto/did@0.3.0':
1737
+
dependencies:
1738
+
zod: 3.25.76
1739
+
1740
+
'@atproto/lex-builder@0.0.15':
1741
+
dependencies:
1742
+
'@atproto/lex-document': 0.0.13
1743
+
'@atproto/lex-schema': 0.0.12
1744
+
prettier: 3.8.1
1745
+
ts-morph: 27.0.2
1746
+
tslib: 2.8.1
1747
+
1748
+
'@atproto/lex-cbor@0.0.11':
1749
+
dependencies:
1750
+
'@atproto/lex-data': 0.0.11
1751
+
tslib: 2.8.1
1752
+
1753
+
'@atproto/lex-client@0.0.12':
1754
+
dependencies:
1755
+
'@atproto/lex-data': 0.0.11
1756
+
'@atproto/lex-json': 0.0.11
1757
+
'@atproto/lex-schema': 0.0.12
1758
+
tslib: 2.8.1
1759
+
1760
+
'@atproto/lex-data@0.0.11':
1761
+
dependencies:
1762
+
multiformats: 9.9.0
1763
+
tslib: 2.8.1
1764
+
uint8arrays: 3.0.0
1765
+
unicode-segmenter: 0.14.5
1766
+
1767
+
'@atproto/lex-document@0.0.13':
1768
+
dependencies:
1769
+
'@atproto/lex-schema': 0.0.12
1770
+
core-js: 3.48.0
1771
+
tslib: 2.8.1
1772
+
1773
+
'@atproto/lex-installer@0.0.16':
1774
+
dependencies:
1775
+
'@atproto/lex-builder': 0.0.15
1776
+
'@atproto/lex-cbor': 0.0.11
1777
+
'@atproto/lex-data': 0.0.11
1778
+
'@atproto/lex-document': 0.0.13
1779
+
'@atproto/lex-resolver': 0.0.14
1780
+
'@atproto/lex-schema': 0.0.12
1781
+
'@atproto/syntax': 0.4.3
1782
+
tslib: 2.8.1
1783
+
1784
+
'@atproto/lex-json@0.0.11':
1785
+
dependencies:
1786
+
'@atproto/lex-data': 0.0.11
1787
+
tslib: 2.8.1
1788
+
1789
+
'@atproto/lex-resolver@0.0.14':
1790
+
dependencies:
1791
+
'@atproto-labs/did-resolver': 0.2.6
1792
+
'@atproto/crypto': 0.4.5
1793
+
'@atproto/lex-client': 0.0.12
1794
+
'@atproto/lex-data': 0.0.11
1795
+
'@atproto/lex-document': 0.0.13
1796
+
'@atproto/lex-schema': 0.0.12
1797
+
'@atproto/repo': 0.8.12
1798
+
'@atproto/syntax': 0.4.3
1799
+
tslib: 2.8.1
1800
+
1801
+
'@atproto/lex-schema@0.0.12':
1802
+
dependencies:
1803
+
'@atproto/lex-data': 0.0.11
1804
+
'@atproto/syntax': 0.4.3
1805
+
tslib: 2.8.1
1806
+
1807
+
'@atproto/lex@0.0.16':
1808
+
dependencies:
1809
+
'@atproto/lex-builder': 0.0.15
1810
+
'@atproto/lex-client': 0.0.12
1811
+
'@atproto/lex-data': 0.0.11
1812
+
'@atproto/lex-installer': 0.0.16
1813
+
'@atproto/lex-json': 0.0.11
1814
+
'@atproto/lex-schema': 0.0.12
1815
+
tslib: 2.8.1
1816
+
yargs: 17.7.2
1817
+
1818
+
'@atproto/lexicon@0.5.2':
1819
+
dependencies:
1820
+
'@atproto/common-web': 0.4.16
1821
+
'@atproto/syntax': 0.4.3
1822
+
iso-datestring-validator: 2.2.2
1823
+
multiformats: 9.9.0
1824
+
zod: 3.25.76
1825
+
1826
+
'@atproto/lexicon@0.6.1':
1827
+
dependencies:
1828
+
'@atproto/common-web': 0.4.16
1829
+
'@atproto/syntax': 0.4.3
1830
+
iso-datestring-validator: 2.2.2
1831
+
multiformats: 9.9.0
1832
+
zod: 3.25.76
1833
+
1834
+
'@atproto/repo@0.8.12':
1835
+
dependencies:
1836
+
'@atproto/common': 0.5.11
1837
+
'@atproto/common-web': 0.4.16
1838
+
'@atproto/crypto': 0.4.5
1839
+
'@atproto/lexicon': 0.6.1
1840
+
'@ipld/dag-cbor': 7.0.3
1841
+
multiformats: 9.9.0
1842
+
uint8arrays: 3.0.0
1843
+
varint: 6.0.0
1844
+
zod: 3.25.76
1845
+
1846
+
'@atproto/syntax@0.4.3':
1847
+
dependencies:
1848
+
tslib: 2.8.1
1849
+
1850
+
'@atproto/xrpc@0.7.7':
1851
+
dependencies:
1852
+
'@atproto/lexicon': 0.6.1
1853
+
zod: 3.25.76
1854
+
1855
+
'@badrap/valita@0.4.6': {}
1856
+
1857
+
'@esbuild/aix-ppc64@0.27.3':
1858
+
optional: true
1859
+
1860
+
'@esbuild/android-arm64@0.27.3':
1861
+
optional: true
1862
+
1863
+
'@esbuild/android-arm@0.27.3':
1864
+
optional: true
1865
+
1866
+
'@esbuild/android-x64@0.27.3':
1867
+
optional: true
1868
+
1869
+
'@esbuild/darwin-arm64@0.27.3':
1870
+
optional: true
1871
+
1872
+
'@esbuild/darwin-x64@0.27.3':
1873
+
optional: true
1874
+
1875
+
'@esbuild/freebsd-arm64@0.27.3':
1876
+
optional: true
1877
+
1878
+
'@esbuild/freebsd-x64@0.27.3':
1879
+
optional: true
1880
+
1881
+
'@esbuild/linux-arm64@0.27.3':
1882
+
optional: true
1883
+
1884
+
'@esbuild/linux-arm@0.27.3':
1885
+
optional: true
1886
+
1887
+
'@esbuild/linux-ia32@0.27.3':
1888
+
optional: true
1889
+
1890
+
'@esbuild/linux-loong64@0.27.3':
1891
+
optional: true
1892
+
1893
+
'@esbuild/linux-mips64el@0.27.3':
1894
+
optional: true
1895
+
1896
+
'@esbuild/linux-ppc64@0.27.3':
1897
+
optional: true
1898
+
1899
+
'@esbuild/linux-riscv64@0.27.3':
1900
+
optional: true
1901
+
1902
+
'@esbuild/linux-s390x@0.27.3':
1903
+
optional: true
1904
+
1905
+
'@esbuild/linux-x64@0.27.3':
1906
+
optional: true
1907
+
1908
+
'@esbuild/netbsd-arm64@0.27.3':
1909
+
optional: true
1910
+
1911
+
'@esbuild/netbsd-x64@0.27.3':
1912
+
optional: true
1913
+
1914
+
'@esbuild/openbsd-arm64@0.27.3':
1915
+
optional: true
1916
+
1917
+
'@esbuild/openbsd-x64@0.27.3':
1918
+
optional: true
1919
+
1920
+
'@esbuild/openharmony-arm64@0.27.3':
1921
+
optional: true
1922
+
1923
+
'@esbuild/sunos-x64@0.27.3':
1924
+
optional: true
1925
+
1926
+
'@esbuild/win32-arm64@0.27.3':
1927
+
optional: true
1928
+
1929
+
'@esbuild/win32-ia32@0.27.3':
1930
+
optional: true
1931
+
1932
+
'@esbuild/win32-x64@0.27.3':
1933
+
optional: true
1934
+
1935
+
'@eslint-community/eslint-utils@4.9.1(eslint@9.39.2)':
1936
+
dependencies:
1937
+
eslint: 9.39.2
1938
+
eslint-visitor-keys: 3.4.3
1939
+
1940
+
'@eslint-community/regexpp@4.12.2': {}
1941
+
1942
+
'@eslint/config-array@0.21.1':
1943
+
dependencies:
1944
+
'@eslint/object-schema': 2.1.7
1945
+
debug: 4.4.3
1946
+
minimatch: 3.1.2
1947
+
transitivePeerDependencies:
1948
+
- supports-color
1949
+
1950
+
'@eslint/config-helpers@0.4.2':
1951
+
dependencies:
1952
+
'@eslint/core': 0.17.0
1953
+
1954
+
'@eslint/core@0.17.0':
1955
+
dependencies:
1956
+
'@types/json-schema': 7.0.15
1957
+
1958
+
'@eslint/eslintrc@3.3.3':
1959
+
dependencies:
1960
+
ajv: 6.12.6
1961
+
debug: 4.4.3
1962
+
espree: 10.4.0
1963
+
globals: 14.0.0
1964
+
ignore: 5.3.2
1965
+
import-fresh: 3.3.1
1966
+
js-yaml: 4.1.1
1967
+
minimatch: 3.1.2
1968
+
strip-json-comments: 3.1.1
1969
+
transitivePeerDependencies:
1970
+
- supports-color
1971
+
1972
+
'@eslint/js@9.39.2': {}
1973
+
1974
+
'@eslint/object-schema@2.1.7': {}
1975
+
1976
+
'@eslint/plugin-kit@0.4.1':
1977
+
dependencies:
1978
+
'@eslint/core': 0.17.0
1979
+
levn: 0.4.1
1980
+
1981
+
'@humanfs/core@0.19.1': {}
1982
+
1983
+
'@humanfs/node@0.16.7':
1984
+
dependencies:
1985
+
'@humanfs/core': 0.19.1
1986
+
'@humanwhocodes/retry': 0.4.3
1987
+
1988
+
'@humanwhocodes/module-importer@1.0.1': {}
1989
+
1990
+
'@humanwhocodes/retry@0.4.3': {}
1991
+
1992
+
'@ipld/dag-cbor@7.0.3':
1993
+
dependencies:
1994
+
cborg: 1.10.2
1995
+
multiformats: 9.9.0
1996
+
1997
+
'@noble/curves@1.9.7':
1998
+
dependencies:
1999
+
'@noble/hashes': 1.8.0
2000
+
2001
+
'@noble/hashes@1.8.0': {}
2002
+
2003
+
'@noble/secp256k1@3.0.0': {}
2004
+
2005
+
'@pds-moover/lexicons@1.0.1':
2006
+
dependencies:
2007
+
'@atproto/lexicon': 0.5.2
2008
+
'@atproto/xrpc': 0.7.7
2009
+
2010
+
'@rollup/rollup-android-arm-eabi@4.57.1':
2011
+
optional: true
2012
+
2013
+
'@rollup/rollup-android-arm64@4.57.1':
2014
+
optional: true
2015
+
2016
+
'@rollup/rollup-darwin-arm64@4.57.1':
2017
+
optional: true
2018
+
2019
+
'@rollup/rollup-darwin-x64@4.57.1':
2020
+
optional: true
2021
+
2022
+
'@rollup/rollup-freebsd-arm64@4.57.1':
2023
+
optional: true
2024
+
2025
+
'@rollup/rollup-freebsd-x64@4.57.1':
2026
+
optional: true
2027
+
2028
+
'@rollup/rollup-linux-arm-gnueabihf@4.57.1':
2029
+
optional: true
2030
+
2031
+
'@rollup/rollup-linux-arm-musleabihf@4.57.1':
2032
+
optional: true
2033
+
2034
+
'@rollup/rollup-linux-arm64-gnu@4.57.1':
2035
+
optional: true
2036
+
2037
+
'@rollup/rollup-linux-arm64-musl@4.57.1':
2038
+
optional: true
2039
+
2040
+
'@rollup/rollup-linux-loong64-gnu@4.57.1':
2041
+
optional: true
2042
+
2043
+
'@rollup/rollup-linux-loong64-musl@4.57.1':
2044
+
optional: true
2045
+
2046
+
'@rollup/rollup-linux-ppc64-gnu@4.57.1':
2047
+
optional: true
2048
+
2049
+
'@rollup/rollup-linux-ppc64-musl@4.57.1':
2050
+
optional: true
2051
+
2052
+
'@rollup/rollup-linux-riscv64-gnu@4.57.1':
2053
+
optional: true
2054
+
2055
+
'@rollup/rollup-linux-riscv64-musl@4.57.1':
2056
+
optional: true
2057
+
2058
+
'@rollup/rollup-linux-s390x-gnu@4.57.1':
2059
+
optional: true
2060
+
2061
+
'@rollup/rollup-linux-x64-gnu@4.57.1':
2062
+
optional: true
2063
+
2064
+
'@rollup/rollup-linux-x64-musl@4.57.1':
2065
+
optional: true
2066
+
2067
+
'@rollup/rollup-openbsd-x64@4.57.1':
2068
+
optional: true
2069
+
2070
+
'@rollup/rollup-openharmony-arm64@4.57.1':
2071
+
optional: true
2072
+
2073
+
'@rollup/rollup-win32-arm64-msvc@4.57.1':
2074
+
optional: true
2075
+
2076
+
'@rollup/rollup-win32-ia32-msvc@4.57.1':
2077
+
optional: true
2078
+
2079
+
'@rollup/rollup-win32-x64-gnu@4.57.1':
2080
+
optional: true
2081
+
2082
+
'@rollup/rollup-win32-x64-msvc@4.57.1':
2083
+
optional: true
2084
+
2085
+
'@rtsao/scc@1.1.0': {}
2086
+
2087
+
'@standard-schema/spec@1.1.0': {}
2088
+
2089
+
'@ts-morph/common@0.28.1':
2090
+
dependencies:
2091
+
minimatch: 10.2.1
2092
+
path-browserify: 1.0.1
2093
+
tinyglobby: 0.2.15
2094
+
2095
+
'@types/estree@1.0.8': {}
2096
+
2097
+
'@types/json-schema@7.0.15': {}
2098
+
2099
+
'@types/json5@0.0.29': {}
2100
+
2101
+
'@vue/reactivity@3.1.5':
2102
+
dependencies:
2103
+
'@vue/shared': 3.1.5
2104
+
2105
+
'@vue/shared@3.1.5': {}
2106
+
2107
+
abort-controller@3.0.0:
2108
+
dependencies:
2109
+
event-target-shim: 5.0.1
2110
+
2111
+
acorn-jsx@5.3.2(acorn@8.15.0):
2112
+
dependencies:
2113
+
acorn: 8.15.0
2114
+
2115
+
acorn@8.15.0: {}
2116
+
2117
+
ajv@6.12.6:
2118
+
dependencies:
2119
+
fast-deep-equal: 3.1.3
2120
+
fast-json-stable-stringify: 2.1.0
2121
+
json-schema-traverse: 0.4.1
2122
+
uri-js: 4.4.1
2123
+
2124
+
alpinejs@3.15.8:
2125
+
dependencies:
2126
+
'@vue/reactivity': 3.1.5
2127
+
2128
+
ansi-regex@5.0.1: {}
2129
+
2130
+
ansi-styles@4.3.0:
2131
+
dependencies:
2132
+
color-convert: 2.0.1
2133
+
2134
+
argparse@2.0.1: {}
2135
+
2136
+
array-buffer-byte-length@1.0.2:
2137
+
dependencies:
2138
+
call-bound: 1.0.4
2139
+
is-array-buffer: 3.0.5
2140
+
2141
+
array-includes@3.1.9:
2142
+
dependencies:
2143
+
call-bind: 1.0.8
2144
+
call-bound: 1.0.4
2145
+
define-properties: 1.2.1
2146
+
es-abstract: 1.24.1
2147
+
es-object-atoms: 1.1.1
2148
+
get-intrinsic: 1.3.0
2149
+
is-string: 1.1.1
2150
+
math-intrinsics: 1.1.0
2151
+
2152
+
array.prototype.findlastindex@1.2.6:
2153
+
dependencies:
2154
+
call-bind: 1.0.8
2155
+
call-bound: 1.0.4
2156
+
define-properties: 1.2.1
2157
+
es-abstract: 1.24.1
2158
+
es-errors: 1.3.0
2159
+
es-object-atoms: 1.1.1
2160
+
es-shim-unscopables: 1.1.0
2161
+
2162
+
array.prototype.flat@1.3.3:
2163
+
dependencies:
2164
+
call-bind: 1.0.8
2165
+
define-properties: 1.2.1
2166
+
es-abstract: 1.24.1
2167
+
es-shim-unscopables: 1.1.0
2168
+
2169
+
array.prototype.flatmap@1.3.3:
2170
+
dependencies:
2171
+
call-bind: 1.0.8
2172
+
define-properties: 1.2.1
2173
+
es-abstract: 1.24.1
2174
+
es-shim-unscopables: 1.1.0
2175
+
2176
+
arraybuffer.prototype.slice@1.0.4:
2177
+
dependencies:
2178
+
array-buffer-byte-length: 1.0.2
2179
+
call-bind: 1.0.8
2180
+
define-properties: 1.2.1
2181
+
es-abstract: 1.24.1
2182
+
es-errors: 1.3.0
2183
+
get-intrinsic: 1.3.0
2184
+
is-array-buffer: 3.0.5
2185
+
2186
+
async-function@1.0.0: {}
2187
+
2188
+
atomic-sleep@1.0.0: {}
2189
+
2190
+
available-typed-arrays@1.0.7:
2191
+
dependencies:
2192
+
possible-typed-array-names: 1.1.0
2193
+
2194
+
await-lock@2.2.2: {}
2195
+
2196
+
balanced-match@1.0.2: {}
2197
+
2198
+
balanced-match@4.0.3: {}
2199
+
2200
+
base64-js@1.5.1: {}
2201
+
2202
+
brace-expansion@1.1.12:
2203
+
dependencies:
2204
+
balanced-match: 1.0.2
2205
+
concat-map: 0.0.1
2206
+
2207
+
brace-expansion@5.0.2:
2208
+
dependencies:
2209
+
balanced-match: 4.0.3
2210
+
2211
+
buffer@6.0.3:
2212
+
dependencies:
2213
+
base64-js: 1.5.1
2214
+
ieee754: 1.2.1
2215
+
2216
+
call-bind-apply-helpers@1.0.2:
2217
+
dependencies:
2218
+
es-errors: 1.3.0
2219
+
function-bind: 1.1.2
2220
+
2221
+
call-bind@1.0.8:
2222
+
dependencies:
2223
+
call-bind-apply-helpers: 1.0.2
2224
+
es-define-property: 1.0.1
2225
+
get-intrinsic: 1.3.0
2226
+
set-function-length: 1.2.2
2227
+
2228
+
call-bound@1.0.4:
2229
+
dependencies:
2230
+
call-bind-apply-helpers: 1.0.2
2231
+
get-intrinsic: 1.3.0
2232
+
2233
+
callsites@3.1.0: {}
2234
+
2235
+
cborg@1.10.2: {}
2236
+
2237
+
chalk@4.1.2:
2238
+
dependencies:
2239
+
ansi-styles: 4.3.0
2240
+
supports-color: 7.2.0
2241
+
2242
+
cliui@8.0.1:
2243
+
dependencies:
2244
+
string-width: 4.2.3
2245
+
strip-ansi: 6.0.1
2246
+
wrap-ansi: 7.0.0
2247
+
2248
+
code-block-writer@13.0.3: {}
2249
+
2250
+
color-convert@2.0.1:
2251
+
dependencies:
2252
+
color-name: 1.1.4
2253
+
2254
+
color-name@1.1.4: {}
2255
+
2256
+
concat-map@0.0.1: {}
2257
+
2258
+
core-js@3.48.0: {}
2259
+
2260
+
cross-spawn@7.0.6:
2261
+
dependencies:
2262
+
path-key: 3.1.1
2263
+
shebang-command: 2.0.0
2264
+
which: 2.0.2
2265
+
2266
+
data-view-buffer@1.0.2:
2267
+
dependencies:
2268
+
call-bound: 1.0.4
2269
+
es-errors: 1.3.0
2270
+
is-data-view: 1.0.2
2271
+
2272
+
data-view-byte-length@1.0.2:
2273
+
dependencies:
2274
+
call-bound: 1.0.4
2275
+
es-errors: 1.3.0
2276
+
is-data-view: 1.0.2
2277
+
2278
+
data-view-byte-offset@1.0.1:
2279
+
dependencies:
2280
+
call-bound: 1.0.4
2281
+
es-errors: 1.3.0
2282
+
is-data-view: 1.0.2
2283
+
2284
+
debug@3.2.7:
2285
+
dependencies:
2286
+
ms: 2.1.3
2287
+
2288
+
debug@4.4.3:
2289
+
dependencies:
2290
+
ms: 2.1.3
2291
+
2292
+
deep-is@0.1.4: {}
2293
+
2294
+
define-data-property@1.1.4:
2295
+
dependencies:
2296
+
es-define-property: 1.0.1
2297
+
es-errors: 1.3.0
2298
+
gopd: 1.2.0
2299
+
2300
+
define-properties@1.2.1:
2301
+
dependencies:
2302
+
define-data-property: 1.1.4
2303
+
has-property-descriptors: 1.0.2
2304
+
object-keys: 1.1.1
2305
+
2306
+
doctrine@2.1.0:
2307
+
dependencies:
2308
+
esutils: 2.0.3
2309
+
2310
+
dunder-proto@1.0.1:
2311
+
dependencies:
2312
+
call-bind-apply-helpers: 1.0.2
2313
+
es-errors: 1.3.0
2314
+
gopd: 1.2.0
2315
+
2316
+
emoji-regex@8.0.0: {}
2317
+
2318
+
es-abstract@1.24.1:
2319
+
dependencies:
2320
+
array-buffer-byte-length: 1.0.2
2321
+
arraybuffer.prototype.slice: 1.0.4
2322
+
available-typed-arrays: 1.0.7
2323
+
call-bind: 1.0.8
2324
+
call-bound: 1.0.4
2325
+
data-view-buffer: 1.0.2
2326
+
data-view-byte-length: 1.0.2
2327
+
data-view-byte-offset: 1.0.1
2328
+
es-define-property: 1.0.1
2329
+
es-errors: 1.3.0
2330
+
es-object-atoms: 1.1.1
2331
+
es-set-tostringtag: 2.1.0
2332
+
es-to-primitive: 1.3.0
2333
+
function.prototype.name: 1.1.8
2334
+
get-intrinsic: 1.3.0
2335
+
get-proto: 1.0.1
2336
+
get-symbol-description: 1.1.0
2337
+
globalthis: 1.0.4
2338
+
gopd: 1.2.0
2339
+
has-property-descriptors: 1.0.2
2340
+
has-proto: 1.2.0
2341
+
has-symbols: 1.1.0
2342
+
hasown: 2.0.2
2343
+
internal-slot: 1.1.0
2344
+
is-array-buffer: 3.0.5
2345
+
is-callable: 1.2.7
2346
+
is-data-view: 1.0.2
2347
+
is-negative-zero: 2.0.3
2348
+
is-regex: 1.2.1
2349
+
is-set: 2.0.3
2350
+
is-shared-array-buffer: 1.0.4
2351
+
is-string: 1.1.1
2352
+
is-typed-array: 1.1.15
2353
+
is-weakref: 1.1.1
2354
+
math-intrinsics: 1.1.0
2355
+
object-inspect: 1.13.4
2356
+
object-keys: 1.1.1
2357
+
object.assign: 4.1.7
2358
+
own-keys: 1.0.1
2359
+
regexp.prototype.flags: 1.5.4
2360
+
safe-array-concat: 1.1.3
2361
+
safe-push-apply: 1.0.0
2362
+
safe-regex-test: 1.1.0
2363
+
set-proto: 1.0.0
2364
+
stop-iteration-iterator: 1.1.0
2365
+
string.prototype.trim: 1.2.10
2366
+
string.prototype.trimend: 1.0.9
2367
+
string.prototype.trimstart: 1.0.8
2368
+
typed-array-buffer: 1.0.3
2369
+
typed-array-byte-length: 1.0.3
2370
+
typed-array-byte-offset: 1.0.4
2371
+
typed-array-length: 1.0.7
2372
+
unbox-primitive: 1.1.0
2373
+
which-typed-array: 1.1.20
2374
+
2375
+
es-define-property@1.0.1: {}
2376
+
2377
+
es-errors@1.3.0: {}
2378
+
2379
+
es-object-atoms@1.1.1:
2380
+
dependencies:
2381
+
es-errors: 1.3.0
2382
+
2383
+
es-set-tostringtag@2.1.0:
2384
+
dependencies:
2385
+
es-errors: 1.3.0
2386
+
get-intrinsic: 1.3.0
2387
+
has-tostringtag: 1.0.2
2388
+
hasown: 2.0.2
2389
+
2390
+
es-shim-unscopables@1.1.0:
2391
+
dependencies:
2392
+
hasown: 2.0.2
2393
+
2394
+
es-to-primitive@1.3.0:
2395
+
dependencies:
2396
+
is-callable: 1.2.7
2397
+
is-date-object: 1.1.0
2398
+
is-symbol: 1.1.1
2399
+
2400
+
esbuild@0.27.3:
2401
+
optionalDependencies:
2402
+
'@esbuild/aix-ppc64': 0.27.3
2403
+
'@esbuild/android-arm': 0.27.3
2404
+
'@esbuild/android-arm64': 0.27.3
2405
+
'@esbuild/android-x64': 0.27.3
2406
+
'@esbuild/darwin-arm64': 0.27.3
2407
+
'@esbuild/darwin-x64': 0.27.3
2408
+
'@esbuild/freebsd-arm64': 0.27.3
2409
+
'@esbuild/freebsd-x64': 0.27.3
2410
+
'@esbuild/linux-arm': 0.27.3
2411
+
'@esbuild/linux-arm64': 0.27.3
2412
+
'@esbuild/linux-ia32': 0.27.3
2413
+
'@esbuild/linux-loong64': 0.27.3
2414
+
'@esbuild/linux-mips64el': 0.27.3
2415
+
'@esbuild/linux-ppc64': 0.27.3
2416
+
'@esbuild/linux-riscv64': 0.27.3
2417
+
'@esbuild/linux-s390x': 0.27.3
2418
+
'@esbuild/linux-x64': 0.27.3
2419
+
'@esbuild/netbsd-arm64': 0.27.3
2420
+
'@esbuild/netbsd-x64': 0.27.3
2421
+
'@esbuild/openbsd-arm64': 0.27.3
2422
+
'@esbuild/openbsd-x64': 0.27.3
2423
+
'@esbuild/openharmony-arm64': 0.27.3
2424
+
'@esbuild/sunos-x64': 0.27.3
2425
+
'@esbuild/win32-arm64': 0.27.3
2426
+
'@esbuild/win32-ia32': 0.27.3
2427
+
'@esbuild/win32-x64': 0.27.3
2428
+
2429
+
escalade@3.2.0: {}
2430
+
2431
+
escape-string-regexp@4.0.0: {}
2432
+
2433
+
eslint-import-resolver-node@0.3.9:
2434
+
dependencies:
2435
+
debug: 3.2.7
2436
+
is-core-module: 2.16.1
2437
+
resolve: 1.22.11
2438
+
transitivePeerDependencies:
2439
+
- supports-color
2440
+
2441
+
eslint-module-utils@2.12.1(eslint-import-resolver-node@0.3.9)(eslint@9.39.2):
2442
+
dependencies:
2443
+
debug: 3.2.7
2444
+
optionalDependencies:
2445
+
eslint: 9.39.2
2446
+
eslint-import-resolver-node: 0.3.9
2447
+
transitivePeerDependencies:
2448
+
- supports-color
2449
+
2450
+
eslint-plugin-import@2.32.0(eslint@9.39.2):
2451
+
dependencies:
2452
+
'@rtsao/scc': 1.1.0
2453
+
array-includes: 3.1.9
2454
+
array.prototype.findlastindex: 1.2.6
2455
+
array.prototype.flat: 1.3.3
2456
+
array.prototype.flatmap: 1.3.3
2457
+
debug: 3.2.7
2458
+
doctrine: 2.1.0
2459
+
eslint: 9.39.2
2460
+
eslint-import-resolver-node: 0.3.9
2461
+
eslint-module-utils: 2.12.1(eslint-import-resolver-node@0.3.9)(eslint@9.39.2)
2462
+
hasown: 2.0.2
2463
+
is-core-module: 2.16.1
2464
+
is-glob: 4.0.3
2465
+
minimatch: 3.1.2
2466
+
object.fromentries: 2.0.8
2467
+
object.groupby: 1.0.3
2468
+
object.values: 1.2.1
2469
+
semver: 6.3.1
2470
+
string.prototype.trimend: 1.0.9
2471
+
tsconfig-paths: 3.15.0
2472
+
transitivePeerDependencies:
2473
+
- eslint-import-resolver-typescript
2474
+
- eslint-import-resolver-webpack
2475
+
- supports-color
2476
+
2477
+
eslint-scope@8.4.0:
2478
+
dependencies:
2479
+
esrecurse: 4.3.0
2480
+
estraverse: 5.3.0
2481
+
2482
+
eslint-visitor-keys@3.4.3: {}
2483
+
2484
+
eslint-visitor-keys@4.2.1: {}
2485
+
2486
+
eslint@9.39.2:
2487
+
dependencies:
2488
+
'@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2)
2489
+
'@eslint-community/regexpp': 4.12.2
2490
+
'@eslint/config-array': 0.21.1
2491
+
'@eslint/config-helpers': 0.4.2
2492
+
'@eslint/core': 0.17.0
2493
+
'@eslint/eslintrc': 3.3.3
2494
+
'@eslint/js': 9.39.2
2495
+
'@eslint/plugin-kit': 0.4.1
2496
+
'@humanfs/node': 0.16.7
2497
+
'@humanwhocodes/module-importer': 1.0.1
2498
+
'@humanwhocodes/retry': 0.4.3
2499
+
'@types/estree': 1.0.8
2500
+
ajv: 6.12.6
2501
+
chalk: 4.1.2
2502
+
cross-spawn: 7.0.6
2503
+
debug: 4.4.3
2504
+
escape-string-regexp: 4.0.0
2505
+
eslint-scope: 8.4.0
2506
+
eslint-visitor-keys: 4.2.1
2507
+
espree: 10.4.0
2508
+
esquery: 1.7.0
2509
+
esutils: 2.0.3
2510
+
fast-deep-equal: 3.1.3
2511
+
file-entry-cache: 8.0.0
2512
+
find-up: 5.0.0
2513
+
glob-parent: 6.0.2
2514
+
ignore: 5.3.2
2515
+
imurmurhash: 0.1.4
2516
+
is-glob: 4.0.3
2517
+
json-stable-stringify-without-jsonify: 1.0.1
2518
+
lodash.merge: 4.6.2
2519
+
minimatch: 3.1.2
2520
+
natural-compare: 1.4.0
2521
+
optionator: 0.9.4
2522
+
transitivePeerDependencies:
2523
+
- supports-color
2524
+
2525
+
esm-env@1.2.2: {}
2526
+
2527
+
espree@10.4.0:
2528
+
dependencies:
2529
+
acorn: 8.15.0
2530
+
acorn-jsx: 5.3.2(acorn@8.15.0)
2531
+
eslint-visitor-keys: 4.2.1
2532
+
2533
+
esquery@1.7.0:
2534
+
dependencies:
2535
+
estraverse: 5.3.0
2536
+
2537
+
esrecurse@4.3.0:
2538
+
dependencies:
2539
+
estraverse: 5.3.0
2540
+
2541
+
estraverse@5.3.0: {}
2542
+
2543
+
esutils@2.0.3: {}
2544
+
2545
+
event-target-shim@5.0.1: {}
2546
+
2547
+
events@3.3.0: {}
2548
+
2549
+
fast-deep-equal@3.1.3: {}
2550
+
2551
+
fast-json-stable-stringify@2.1.0: {}
2552
+
2553
+
fast-levenshtein@2.0.6: {}
2554
+
2555
+
fast-redact@3.5.0: {}
2556
+
2557
+
fdir@6.5.0(picomatch@4.0.3):
2558
+
optionalDependencies:
2559
+
picomatch: 4.0.3
2560
+
2561
+
file-entry-cache@8.0.0:
2562
+
dependencies:
2563
+
flat-cache: 4.0.1
2564
+
2565
+
find-up@5.0.0:
2566
+
dependencies:
2567
+
locate-path: 6.0.0
2568
+
path-exists: 4.0.0
2569
+
2570
+
flat-cache@4.0.1:
2571
+
dependencies:
2572
+
flatted: 3.3.3
2573
+
keyv: 4.5.4
2574
+
2575
+
flatted@3.3.3: {}
2576
+
2577
+
for-each@0.3.5:
2578
+
dependencies:
2579
+
is-callable: 1.2.7
2580
+
2581
+
fsevents@2.3.3:
2582
+
optional: true
2583
+
2584
+
function-bind@1.1.2: {}
2585
+
2586
+
function.prototype.name@1.1.8:
2587
+
dependencies:
2588
+
call-bind: 1.0.8
2589
+
call-bound: 1.0.4
2590
+
define-properties: 1.2.1
2591
+
functions-have-names: 1.2.3
2592
+
hasown: 2.0.2
2593
+
is-callable: 1.2.7
2594
+
2595
+
functions-have-names@1.2.3: {}
2596
+
2597
+
generator-function@2.0.1: {}
2598
+
2599
+
get-caller-file@2.0.5: {}
2600
+
2601
+
get-intrinsic@1.3.0:
2602
+
dependencies:
2603
+
call-bind-apply-helpers: 1.0.2
2604
+
es-define-property: 1.0.1
2605
+
es-errors: 1.3.0
2606
+
es-object-atoms: 1.1.1
2607
+
function-bind: 1.1.2
2608
+
get-proto: 1.0.1
2609
+
gopd: 1.2.0
2610
+
has-symbols: 1.1.0
2611
+
hasown: 2.0.2
2612
+
math-intrinsics: 1.1.0
2613
+
2614
+
get-proto@1.0.1:
2615
+
dependencies:
2616
+
dunder-proto: 1.0.1
2617
+
es-object-atoms: 1.1.1
2618
+
2619
+
get-symbol-description@1.1.0:
2620
+
dependencies:
2621
+
call-bound: 1.0.4
2622
+
es-errors: 1.3.0
2623
+
get-intrinsic: 1.3.0
2624
+
2625
+
glob-parent@6.0.2:
2626
+
dependencies:
2627
+
is-glob: 4.0.3
2628
+
2629
+
globals@14.0.0: {}
2630
+
2631
+
globalthis@1.0.4:
2632
+
dependencies:
2633
+
define-properties: 1.2.1
2634
+
gopd: 1.2.0
2635
+
2636
+
gopd@1.2.0: {}
2637
+
2638
+
has-bigints@1.1.0: {}
2639
+
2640
+
has-flag@4.0.0: {}
2641
+
2642
+
has-property-descriptors@1.0.2:
2643
+
dependencies:
2644
+
es-define-property: 1.0.1
2645
+
2646
+
has-proto@1.2.0:
2647
+
dependencies:
2648
+
dunder-proto: 1.0.1
2649
+
2650
+
has-symbols@1.1.0: {}
2651
+
2652
+
has-tostringtag@1.0.2:
2653
+
dependencies:
2654
+
has-symbols: 1.1.0
2655
+
2656
+
hasown@2.0.2:
2657
+
dependencies:
2658
+
function-bind: 1.1.2
2659
+
2660
+
ieee754@1.2.1: {}
2661
+
2662
+
ignore@5.3.2: {}
2663
+
2664
+
import-fresh@3.3.1:
2665
+
dependencies:
2666
+
parent-module: 1.0.1
2667
+
resolve-from: 4.0.0
2668
+
2669
+
imurmurhash@0.1.4: {}
2670
+
2671
+
internal-slot@1.1.0:
2672
+
dependencies:
2673
+
es-errors: 1.3.0
2674
+
hasown: 2.0.2
2675
+
side-channel: 1.1.0
2676
+
2677
+
is-array-buffer@3.0.5:
2678
+
dependencies:
2679
+
call-bind: 1.0.8
2680
+
call-bound: 1.0.4
2681
+
get-intrinsic: 1.3.0
2682
+
2683
+
is-async-function@2.1.1:
2684
+
dependencies:
2685
+
async-function: 1.0.0
2686
+
call-bound: 1.0.4
2687
+
get-proto: 1.0.1
2688
+
has-tostringtag: 1.0.2
2689
+
safe-regex-test: 1.1.0
2690
+
2691
+
is-bigint@1.1.0:
2692
+
dependencies:
2693
+
has-bigints: 1.1.0
2694
+
2695
+
is-boolean-object@1.2.2:
2696
+
dependencies:
2697
+
call-bound: 1.0.4
2698
+
has-tostringtag: 1.0.2
2699
+
2700
+
is-callable@1.2.7: {}
2701
+
2702
+
is-core-module@2.16.1:
2703
+
dependencies:
2704
+
hasown: 2.0.2
2705
+
2706
+
is-data-view@1.0.2:
2707
+
dependencies:
2708
+
call-bound: 1.0.4
2709
+
get-intrinsic: 1.3.0
2710
+
is-typed-array: 1.1.15
2711
+
2712
+
is-date-object@1.1.0:
2713
+
dependencies:
2714
+
call-bound: 1.0.4
2715
+
has-tostringtag: 1.0.2
2716
+
2717
+
is-extglob@2.1.1: {}
2718
+
2719
+
is-finalizationregistry@1.1.1:
2720
+
dependencies:
2721
+
call-bound: 1.0.4
2722
+
2723
+
is-fullwidth-code-point@3.0.0: {}
2724
+
2725
+
is-generator-function@1.1.2:
2726
+
dependencies:
2727
+
call-bound: 1.0.4
2728
+
generator-function: 2.0.1
2729
+
get-proto: 1.0.1
2730
+
has-tostringtag: 1.0.2
2731
+
safe-regex-test: 1.1.0
2732
+
2733
+
is-glob@4.0.3:
2734
+
dependencies:
2735
+
is-extglob: 2.1.1
2736
+
2737
+
is-map@2.0.3: {}
2738
+
2739
+
is-negative-zero@2.0.3: {}
2740
+
2741
+
is-number-object@1.1.1:
2742
+
dependencies:
2743
+
call-bound: 1.0.4
2744
+
has-tostringtag: 1.0.2
2745
+
2746
+
is-regex@1.2.1:
2747
+
dependencies:
2748
+
call-bound: 1.0.4
2749
+
gopd: 1.2.0
2750
+
has-tostringtag: 1.0.2
2751
+
hasown: 2.0.2
2752
+
2753
+
is-set@2.0.3: {}
2754
+
2755
+
is-shared-array-buffer@1.0.4:
2756
+
dependencies:
2757
+
call-bound: 1.0.4
2758
+
2759
+
is-string@1.1.1:
2760
+
dependencies:
2761
+
call-bound: 1.0.4
2762
+
has-tostringtag: 1.0.2
2763
+
2764
+
is-symbol@1.1.1:
2765
+
dependencies:
2766
+
call-bound: 1.0.4
2767
+
has-symbols: 1.1.0
2768
+
safe-regex-test: 1.1.0
2769
+
2770
+
is-typed-array@1.1.15:
2771
+
dependencies:
2772
+
which-typed-array: 1.1.20
2773
+
2774
+
is-weakmap@2.0.2: {}
2775
+
2776
+
is-weakref@1.1.1:
2777
+
dependencies:
2778
+
call-bound: 1.0.4
2779
+
2780
+
is-weakset@2.0.4:
2781
+
dependencies:
2782
+
call-bound: 1.0.4
2783
+
get-intrinsic: 1.3.0
2784
+
2785
+
isarray@2.0.5: {}
2786
+
2787
+
isexe@2.0.0: {}
2788
+
2789
+
iso-datestring-validator@2.2.2: {}
2790
+
2791
+
js-yaml@4.1.1:
2792
+
dependencies:
2793
+
argparse: 2.0.1
2794
+
2795
+
json-buffer@3.0.1: {}
2796
+
2797
+
json-schema-traverse@0.4.1: {}
2798
+
2799
+
json-stable-stringify-without-jsonify@1.0.1: {}
2800
+
2801
+
json5@1.0.2:
2802
+
dependencies:
2803
+
minimist: 1.2.8
2804
+
2805
+
keyv@4.5.4:
2806
+
dependencies:
2807
+
json-buffer: 3.0.1
2808
+
2809
+
levn@0.4.1:
2810
+
dependencies:
2811
+
prelude-ls: 1.2.1
2812
+
type-check: 0.4.0
2813
+
2814
+
locate-path@6.0.0:
2815
+
dependencies:
2816
+
p-locate: 5.0.0
2817
+
2818
+
lodash.merge@4.6.2: {}
2819
+
2820
+
lru-cache@10.4.3: {}
2821
+
2822
+
math-intrinsics@1.1.0: {}
2823
+
2824
+
minimatch@10.2.1:
2825
+
dependencies:
2826
+
brace-expansion: 5.0.2
2827
+
2828
+
minimatch@3.1.2:
2829
+
dependencies:
2830
+
brace-expansion: 1.1.12
2831
+
2832
+
minimist@1.2.8: {}
2833
+
2834
+
ms@2.1.3: {}
2835
+
2836
+
multiformats@9.9.0: {}
2837
+
2838
+
nanoid@3.3.11: {}
2839
+
2840
+
natural-compare@1.4.0: {}
2841
+
2842
+
object-inspect@1.13.4: {}
2843
+
2844
+
object-keys@1.1.1: {}
2845
+
2846
+
object.assign@4.1.7:
2847
+
dependencies:
2848
+
call-bind: 1.0.8
2849
+
call-bound: 1.0.4
2850
+
define-properties: 1.2.1
2851
+
es-object-atoms: 1.1.1
2852
+
has-symbols: 1.1.0
2853
+
object-keys: 1.1.1
2854
+
2855
+
object.fromentries@2.0.8:
2856
+
dependencies:
2857
+
call-bind: 1.0.8
2858
+
define-properties: 1.2.1
2859
+
es-abstract: 1.24.1
2860
+
es-object-atoms: 1.1.1
2861
+
2862
+
object.groupby@1.0.3:
2863
+
dependencies:
2864
+
call-bind: 1.0.8
2865
+
define-properties: 1.2.1
2866
+
es-abstract: 1.24.1
2867
+
2868
+
object.values@1.2.1:
2869
+
dependencies:
2870
+
call-bind: 1.0.8
2871
+
call-bound: 1.0.4
2872
+
define-properties: 1.2.1
2873
+
es-object-atoms: 1.1.1
2874
+
2875
+
on-exit-leak-free@2.1.2: {}
2876
+
2877
+
optionator@0.9.4:
2878
+
dependencies:
2879
+
deep-is: 0.1.4
2880
+
fast-levenshtein: 2.0.6
2881
+
levn: 0.4.1
2882
+
prelude-ls: 1.2.1
2883
+
type-check: 0.4.0
2884
+
word-wrap: 1.2.5
2885
+
2886
+
own-keys@1.0.1:
2887
+
dependencies:
2888
+
get-intrinsic: 1.3.0
2889
+
object-keys: 1.1.1
2890
+
safe-push-apply: 1.0.0
2891
+
2892
+
p-limit@3.1.0:
2893
+
dependencies:
2894
+
yocto-queue: 0.1.0
2895
+
2896
+
p-locate@5.0.0:
2897
+
dependencies:
2898
+
p-limit: 3.1.0
2899
+
2900
+
parent-module@1.0.1:
2901
+
dependencies:
2902
+
callsites: 3.1.0
2903
+
2904
+
path-browserify@1.0.1: {}
2905
+
2906
+
path-exists@4.0.0: {}
2907
+
2908
+
path-key@3.1.1: {}
2909
+
2910
+
path-parse@1.0.7: {}
2911
+
2912
+
picocolors@1.1.1: {}
2913
+
2914
+
picomatch@2.3.1: {}
2915
+
2916
+
picomatch@4.0.3: {}
2917
+
2918
+
pino-abstract-transport@1.2.0:
2919
+
dependencies:
2920
+
readable-stream: 4.7.0
2921
+
split2: 4.2.0
2922
+
2923
+
pino-std-serializers@6.2.2: {}
2924
+
2925
+
pino@8.21.0:
2926
+
dependencies:
2927
+
atomic-sleep: 1.0.0
2928
+
fast-redact: 3.5.0
2929
+
on-exit-leak-free: 2.1.2
2930
+
pino-abstract-transport: 1.2.0
2931
+
pino-std-serializers: 6.2.2
2932
+
process-warning: 3.0.0
2933
+
quick-format-unescaped: 4.0.4
2934
+
real-require: 0.2.0
2935
+
safe-stable-stringify: 2.5.0
2936
+
sonic-boom: 3.8.1
2937
+
thread-stream: 2.7.0
2938
+
2939
+
possible-typed-array-names@1.1.0: {}
2940
+
2941
+
postcss@8.5.6:
2942
+
dependencies:
2943
+
nanoid: 3.3.11
2944
+
picocolors: 1.1.1
2945
+
source-map-js: 1.2.1
2946
+
2947
+
prelude-ls@1.2.1: {}
2948
+
2949
+
prettier@3.8.1: {}
2950
+
2951
+
process-warning@3.0.0: {}
2952
+
2953
+
process@0.11.10: {}
2954
+
2955
+
punycode@2.3.1: {}
2956
+
2957
+
quick-format-unescaped@4.0.4: {}
2958
+
2959
+
readable-stream@4.7.0:
2960
+
dependencies:
2961
+
abort-controller: 3.0.0
2962
+
buffer: 6.0.3
2963
+
events: 3.3.0
2964
+
process: 0.11.10
2965
+
string_decoder: 1.3.0
2966
+
2967
+
real-require@0.2.0: {}
2968
+
2969
+
reflect.getprototypeof@1.0.10:
2970
+
dependencies:
2971
+
call-bind: 1.0.8
2972
+
define-properties: 1.2.1
2973
+
es-abstract: 1.24.1
2974
+
es-errors: 1.3.0
2975
+
es-object-atoms: 1.1.1
2976
+
get-intrinsic: 1.3.0
2977
+
get-proto: 1.0.1
2978
+
which-builtin-type: 1.2.1
2979
+
2980
+
regexp.prototype.flags@1.5.4:
2981
+
dependencies:
2982
+
call-bind: 1.0.8
2983
+
define-properties: 1.2.1
2984
+
es-errors: 1.3.0
2985
+
get-proto: 1.0.1
2986
+
gopd: 1.2.0
2987
+
set-function-name: 2.0.2
2988
+
2989
+
require-directory@2.1.1: {}
2990
+
2991
+
resolve-from@4.0.0: {}
2992
+
2993
+
resolve@1.22.11:
2994
+
dependencies:
2995
+
is-core-module: 2.16.1
2996
+
path-parse: 1.0.7
2997
+
supports-preserve-symlinks-flag: 1.0.0
2998
+
2999
+
rollup@4.57.1:
3000
+
dependencies:
3001
+
'@types/estree': 1.0.8
3002
+
optionalDependencies:
3003
+
'@rollup/rollup-android-arm-eabi': 4.57.1
3004
+
'@rollup/rollup-android-arm64': 4.57.1
3005
+
'@rollup/rollup-darwin-arm64': 4.57.1
3006
+
'@rollup/rollup-darwin-x64': 4.57.1
3007
+
'@rollup/rollup-freebsd-arm64': 4.57.1
3008
+
'@rollup/rollup-freebsd-x64': 4.57.1
3009
+
'@rollup/rollup-linux-arm-gnueabihf': 4.57.1
3010
+
'@rollup/rollup-linux-arm-musleabihf': 4.57.1
3011
+
'@rollup/rollup-linux-arm64-gnu': 4.57.1
3012
+
'@rollup/rollup-linux-arm64-musl': 4.57.1
3013
+
'@rollup/rollup-linux-loong64-gnu': 4.57.1
3014
+
'@rollup/rollup-linux-loong64-musl': 4.57.1
3015
+
'@rollup/rollup-linux-ppc64-gnu': 4.57.1
3016
+
'@rollup/rollup-linux-ppc64-musl': 4.57.1
3017
+
'@rollup/rollup-linux-riscv64-gnu': 4.57.1
3018
+
'@rollup/rollup-linux-riscv64-musl': 4.57.1
3019
+
'@rollup/rollup-linux-s390x-gnu': 4.57.1
3020
+
'@rollup/rollup-linux-x64-gnu': 4.57.1
3021
+
'@rollup/rollup-linux-x64-musl': 4.57.1
3022
+
'@rollup/rollup-openbsd-x64': 4.57.1
3023
+
'@rollup/rollup-openharmony-arm64': 4.57.1
3024
+
'@rollup/rollup-win32-arm64-msvc': 4.57.1
3025
+
'@rollup/rollup-win32-ia32-msvc': 4.57.1
3026
+
'@rollup/rollup-win32-x64-gnu': 4.57.1
3027
+
'@rollup/rollup-win32-x64-msvc': 4.57.1
3028
+
fsevents: 2.3.3
3029
+
3030
+
safe-array-concat@1.1.3:
3031
+
dependencies:
3032
+
call-bind: 1.0.8
3033
+
call-bound: 1.0.4
3034
+
get-intrinsic: 1.3.0
3035
+
has-symbols: 1.1.0
3036
+
isarray: 2.0.5
3037
+
3038
+
safe-buffer@5.2.1: {}
3039
+
3040
+
safe-push-apply@1.0.0:
3041
+
dependencies:
3042
+
es-errors: 1.3.0
3043
+
isarray: 2.0.5
3044
+
3045
+
safe-regex-test@1.1.0:
3046
+
dependencies:
3047
+
call-bound: 1.0.4
3048
+
es-errors: 1.3.0
3049
+
is-regex: 1.2.1
3050
+
3051
+
safe-stable-stringify@2.5.0: {}
3052
+
3053
+
semver@6.3.1: {}
3054
+
3055
+
set-function-length@1.2.2:
3056
+
dependencies:
3057
+
define-data-property: 1.1.4
3058
+
es-errors: 1.3.0
3059
+
function-bind: 1.1.2
3060
+
get-intrinsic: 1.3.0
3061
+
gopd: 1.2.0
3062
+
has-property-descriptors: 1.0.2
3063
+
3064
+
set-function-name@2.0.2:
3065
+
dependencies:
3066
+
define-data-property: 1.1.4
3067
+
es-errors: 1.3.0
3068
+
functions-have-names: 1.2.3
3069
+
has-property-descriptors: 1.0.2
3070
+
3071
+
set-proto@1.0.0:
3072
+
dependencies:
3073
+
dunder-proto: 1.0.1
3074
+
es-errors: 1.3.0
3075
+
es-object-atoms: 1.1.1
3076
+
3077
+
shebang-command@2.0.0:
3078
+
dependencies:
3079
+
shebang-regex: 3.0.0
3080
+
3081
+
shebang-regex@3.0.0: {}
3082
+
3083
+
side-channel-list@1.0.0:
3084
+
dependencies:
3085
+
es-errors: 1.3.0
3086
+
object-inspect: 1.13.4
3087
+
3088
+
side-channel-map@1.0.1:
3089
+
dependencies:
3090
+
call-bound: 1.0.4
3091
+
es-errors: 1.3.0
3092
+
get-intrinsic: 1.3.0
3093
+
object-inspect: 1.13.4
3094
+
3095
+
side-channel-weakmap@1.0.2:
3096
+
dependencies:
3097
+
call-bound: 1.0.4
3098
+
es-errors: 1.3.0
3099
+
get-intrinsic: 1.3.0
3100
+
object-inspect: 1.13.4
3101
+
side-channel-map: 1.0.1
3102
+
3103
+
side-channel@1.1.0:
3104
+
dependencies:
3105
+
es-errors: 1.3.0
3106
+
object-inspect: 1.13.4
3107
+
side-channel-list: 1.0.0
3108
+
side-channel-map: 1.0.1
3109
+
side-channel-weakmap: 1.0.2
3110
+
3111
+
sonic-boom@3.8.1:
3112
+
dependencies:
3113
+
atomic-sleep: 1.0.0
3114
+
3115
+
source-map-js@1.2.1: {}
3116
+
3117
+
split2@4.2.0: {}
3118
+
3119
+
stop-iteration-iterator@1.1.0:
3120
+
dependencies:
3121
+
es-errors: 1.3.0
3122
+
internal-slot: 1.1.0
3123
+
3124
+
string-width@4.2.3:
3125
+
dependencies:
3126
+
emoji-regex: 8.0.0
3127
+
is-fullwidth-code-point: 3.0.0
3128
+
strip-ansi: 6.0.1
3129
+
3130
+
string.prototype.trim@1.2.10:
3131
+
dependencies:
3132
+
call-bind: 1.0.8
3133
+
call-bound: 1.0.4
3134
+
define-data-property: 1.1.4
3135
+
define-properties: 1.2.1
3136
+
es-abstract: 1.24.1
3137
+
es-object-atoms: 1.1.1
3138
+
has-property-descriptors: 1.0.2
3139
+
3140
+
string.prototype.trimend@1.0.9:
3141
+
dependencies:
3142
+
call-bind: 1.0.8
3143
+
call-bound: 1.0.4
3144
+
define-properties: 1.2.1
3145
+
es-object-atoms: 1.1.1
3146
+
3147
+
string.prototype.trimstart@1.0.8:
3148
+
dependencies:
3149
+
call-bind: 1.0.8
3150
+
define-properties: 1.2.1
3151
+
es-object-atoms: 1.1.1
3152
+
3153
+
string_decoder@1.3.0:
3154
+
dependencies:
3155
+
safe-buffer: 5.2.1
3156
+
3157
+
strip-ansi@6.0.1:
3158
+
dependencies:
3159
+
ansi-regex: 5.0.1
3160
+
3161
+
strip-bom@3.0.0: {}
3162
+
3163
+
strip-json-comments@3.1.1: {}
3164
+
3165
+
supports-color@7.2.0:
3166
+
dependencies:
3167
+
has-flag: 4.0.0
3168
+
3169
+
supports-preserve-symlinks-flag@1.0.0: {}
3170
+
3171
+
thread-stream@2.7.0:
3172
+
dependencies:
3173
+
real-require: 0.2.0
3174
+
3175
+
tinyglobby@0.2.15:
3176
+
dependencies:
3177
+
fdir: 6.5.0(picomatch@4.0.3)
3178
+
picomatch: 4.0.3
3179
+
3180
+
tlds@1.261.0: {}
3181
+
3182
+
ts-morph@27.0.2:
3183
+
dependencies:
3184
+
'@ts-morph/common': 0.28.1
3185
+
code-block-writer: 13.0.3
3186
+
3187
+
tsconfig-paths@3.15.0:
3188
+
dependencies:
3189
+
'@types/json5': 0.0.29
3190
+
json5: 1.0.2
3191
+
minimist: 1.2.8
3192
+
strip-bom: 3.0.0
3193
+
3194
+
tslib@2.8.1: {}
3195
+
3196
+
type-check@0.4.0:
3197
+
dependencies:
3198
+
prelude-ls: 1.2.1
3199
+
3200
+
typed-array-buffer@1.0.3:
3201
+
dependencies:
3202
+
call-bound: 1.0.4
3203
+
es-errors: 1.3.0
3204
+
is-typed-array: 1.1.15
3205
+
3206
+
typed-array-byte-length@1.0.3:
3207
+
dependencies:
3208
+
call-bind: 1.0.8
3209
+
for-each: 0.3.5
3210
+
gopd: 1.2.0
3211
+
has-proto: 1.2.0
3212
+
is-typed-array: 1.1.15
3213
+
3214
+
typed-array-byte-offset@1.0.4:
3215
+
dependencies:
3216
+
available-typed-arrays: 1.0.7
3217
+
call-bind: 1.0.8
3218
+
for-each: 0.3.5
3219
+
gopd: 1.2.0
3220
+
has-proto: 1.2.0
3221
+
is-typed-array: 1.1.15
3222
+
reflect.getprototypeof: 1.0.10
3223
+
3224
+
typed-array-length@1.0.7:
3225
+
dependencies:
3226
+
call-bind: 1.0.8
3227
+
for-each: 0.3.5
3228
+
gopd: 1.2.0
3229
+
is-typed-array: 1.1.15
3230
+
possible-typed-array-names: 1.1.0
3231
+
reflect.getprototypeof: 1.0.10
3232
+
3233
+
uint8arrays@3.0.0:
3234
+
dependencies:
3235
+
multiformats: 9.9.0
3236
+
3237
+
unbox-primitive@1.1.0:
3238
+
dependencies:
3239
+
call-bound: 1.0.4
3240
+
has-bigints: 1.1.0
3241
+
has-symbols: 1.1.0
3242
+
which-boxed-primitive: 1.1.1
3243
+
3244
+
unicode-segmenter@0.14.5: {}
3245
+
3246
+
uri-js@4.4.1:
3247
+
dependencies:
3248
+
punycode: 2.3.1
3249
+
3250
+
varint@6.0.0: {}
3251
+
3252
+
vite-plugin-full-reload@1.2.0:
3253
+
dependencies:
3254
+
picocolors: 1.1.1
3255
+
picomatch: 2.3.1
3256
+
3257
+
vite-rs-plugin@1.0.1(vite@7.3.1):
3258
+
dependencies:
3259
+
vite: 7.3.1
3260
+
vite-plugin-full-reload: 1.2.0
3261
+
3262
+
vite@7.3.1:
3263
+
dependencies:
3264
+
esbuild: 0.27.3
3265
+
fdir: 6.5.0(picomatch@4.0.3)
3266
+
picomatch: 4.0.3
3267
+
postcss: 8.5.6
3268
+
rollup: 4.57.1
3269
+
tinyglobby: 0.2.15
3270
+
optionalDependencies:
3271
+
fsevents: 2.3.3
3272
+
3273
+
which-boxed-primitive@1.1.1:
3274
+
dependencies:
3275
+
is-bigint: 1.1.0
3276
+
is-boolean-object: 1.2.2
3277
+
is-number-object: 1.1.1
3278
+
is-string: 1.1.1
3279
+
is-symbol: 1.1.1
3280
+
3281
+
which-builtin-type@1.2.1:
3282
+
dependencies:
3283
+
call-bound: 1.0.4
3284
+
function.prototype.name: 1.1.8
3285
+
has-tostringtag: 1.0.2
3286
+
is-async-function: 2.1.1
3287
+
is-date-object: 1.1.0
3288
+
is-finalizationregistry: 1.1.1
3289
+
is-generator-function: 1.1.2
3290
+
is-regex: 1.2.1
3291
+
is-weakref: 1.1.1
3292
+
isarray: 2.0.5
3293
+
which-boxed-primitive: 1.1.1
3294
+
which-collection: 1.0.2
3295
+
which-typed-array: 1.1.20
3296
+
3297
+
which-collection@1.0.2:
3298
+
dependencies:
3299
+
is-map: 2.0.3
3300
+
is-set: 2.0.3
3301
+
is-weakmap: 2.0.2
3302
+
is-weakset: 2.0.4
3303
+
3304
+
which-typed-array@1.1.20:
3305
+
dependencies:
3306
+
available-typed-arrays: 1.0.7
3307
+
call-bind: 1.0.8
3308
+
call-bound: 1.0.4
3309
+
for-each: 0.3.5
3310
+
get-proto: 1.0.1
3311
+
gopd: 1.2.0
3312
+
has-tostringtag: 1.0.2
3313
+
3314
+
which@2.0.2:
3315
+
dependencies:
3316
+
isexe: 2.0.0
3317
+
3318
+
word-wrap@1.2.5: {}
3319
+
3320
+
wrap-ansi@7.0.0:
3321
+
dependencies:
3322
+
ansi-styles: 4.3.0
3323
+
string-width: 4.2.3
3324
+
strip-ansi: 6.0.1
3325
+
3326
+
y18n@5.0.8: {}
3327
+
3328
+
yargs-parser@21.1.1: {}
3329
+
3330
+
yargs@17.7.2:
3331
+
dependencies:
3332
+
cliui: 8.0.1
3333
+
escalade: 3.2.0
3334
+
get-caller-file: 2.0.5
3335
+
require-directory: 2.1.1
3336
+
string-width: 4.2.3
3337
+
y18n: 5.0.8
3338
+
yargs-parser: 21.1.1
3339
+
3340
+
yocto-queue@0.1.0: {}
3341
+
3342
+
zod@3.25.76: {}
+4
-12
packages/moover/tsconfig.json
+4
-12
packages/moover/tsconfig.json
···
1
1
{
2
-
"include": [
3
-
"lib/**/*"
4
-
],
5
-
"exclude": [
6
-
"node_modules",
7
-
"dist",
8
-
"types"
9
-
],
2
+
"include": ["lib/**/*"],
3
+
"exclude": ["node_modules", "dist", "types"],
10
4
"compilerOptions": {
11
5
"allowJs": true,
12
6
"checkJs": false,
···
17
11
// or use "declarationDir": "types"
18
12
19
13
"target": "ES2022",
20
-
"lib": [
21
-
"ES2022"
22
-
],
14
+
"lib": ["ES2022"],
23
15
// add "DOM" if you use browser APIs
24
16
"skipLibCheck": true,
25
17
"module": "ESNext",
···
27
19
// or "NodeNext" depending on your setup
28
20
"rootDir": "lib"
29
21
}
30
-
}
22
+
}
+10
-10
packages/moover/types/atprotoUtils.d.ts
+10
-10
packages/moover/types/atprotoUtils.d.ts
···
1
-
export const handleResolver: CompositeHandleResolver;
2
-
export const docResolver: CompositeDidDocumentResolver<"plc" | "web">;
1
+
export const handleResolver: CompositeHandleResolver
2
+
export const docResolver: CompositeDidDocumentResolver<'plc' | 'web'>
3
3
/**
4
4
* Cleans the handle of @ and some other unicode characters that used to show up when copied from the profile
5
5
* @param handle {string}
6
6
* @returns {string}
7
7
*/
8
-
export function cleanHandle(handle: string): string;
8
+
export function cleanHandle(handle: string): string
9
9
/**
10
10
* Convince helper to resolve a handle to a did and then find the PDS url from the did document.
11
11
*
···
13
13
* @returns {Promise<{usersDid: string, pds: string}>}
14
14
*/
15
15
export function handleAndPDSResolver(handle: any): Promise<{
16
-
usersDid: string;
17
-
pds: string;
18
-
}>;
16
+
usersDid: string
17
+
pds: string
18
+
}>
19
19
/**
20
20
* Fetches the DID Web from the .well-known/did.json endpoint of the server.
21
21
* Legacy and was helpful if the web ui and server are on the same domain, not as useful now
22
22
* @param baseUrl
23
23
* @returns {Promise<*>}
24
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
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
+89
-82
packages/moover/types/backup.d.ts
+89
-82
packages/moover/types/backup.d.ts
···
1
1
/**
2
2
* JSDoc type-only import to avoid runtime import errors in the browser.
3
3
*/
4
-
export type InferXRPCBodyOutput = any;
4
+
export type InferXRPCBodyOutput = any
5
5
/**
6
6
* JSDoc type-only import to avoid runtime import errors in the browser.
7
7
* @typedef {import('@atcute/lexicons').InferXRPCBodyOutput} InferXRPCBodyOutput
···
10
10
* Logic to sign up and manage backups for pdsmoover.com (or your own selfhosted instance)
11
11
*/
12
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>;
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(
50
+
identifier: string,
51
+
password: string,
52
+
onStatus?: Function | null,
53
+
twoFactorCode?: string | null,
54
+
): Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']> | null>
55
+
/**
56
+
* Signs the user up for backups with the service
57
+
* @param onStatus
58
+
* @returns {Promise<void>}
59
+
*/
60
+
signUp(onStatus?: any): Promise<void>
61
+
/**
62
+
* Requests a PLC token to be sent to the user's email, needed to add a new rotation key
63
+
* @returns {Promise<void>}
64
+
*/
65
+
requestAPlcToken(): Promise<void>
66
+
/**
67
+
* Adds a new rotation to the users did document. Assumes you are already signed in.
68
+
*
69
+
* WARNING: This will overwrite any existing rotation keys with the new one at the top, and the PDS key as the second one
70
+
* @param plcToken {string} - PLC token from the user's email that was sent from requestAPlcToken
71
+
* @param rotationKey {string} - The new rotation key to add to the user's did document
72
+
* @returns {Promise<void>}
73
+
*/
74
+
addANewRotationKey(plcToken: string, rotationKey: string): Promise<void>
75
+
/**
76
+
*
77
+
* Gets the current status of the user's backup repository.
78
+
*
79
+
* @param onStatus {function|null} - a function that takes a string used to update the UI.
80
+
* @returns {Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>>}
81
+
*/
82
+
getUsersRepoStatus(
83
+
onStatus?: Function | null,
84
+
): Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>>
85
+
/**
86
+
* Requests a backup to be run immediately for the signed-in user. Usually does, depend on the server's backup queue
87
+
* @param onStatus
88
+
* @returns {Promise<boolean>}
89
+
*/
90
+
runBackupNow(onStatus?: any): Promise<boolean>
91
+
/**
92
+
* Remove (delete) the signed-in user's backup repository. this also deletes all the user's backup data.
93
+
* @param onStatus
94
+
* @returns {Promise<boolean>}
95
+
*/
96
+
removeRepo(onStatus?: any): Promise<boolean>
90
97
}
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
98
+
import { Client } from '@atcute/client'
99
+
import { CredentialManager } from '@atcute/client'
100
+
import { ComPdsmooverBackupDescribeServer } from '@pds-moover/lexicons'
101
+
//# sourceMappingURL=backup.d.ts.map
+8
-8
packages/moover/types/main.d.ts
+8
-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
+
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
+65
-57
packages/moover/types/missingBlobs.d.ts
+65
-57
packages/moover/types/missingBlobs.d.ts
···
2
2
* Class to help find missing blobs from the did's previous PDS and import them into the current PDS
3
3
*/
4
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
-
}>;
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(
38
+
handle: string,
39
+
password: string,
40
+
twoFactorCode?: string | null,
41
+
): Promise<{
42
+
accountStatus: OutputSchema
43
+
missingBlobsCount: number
44
+
}>
45
+
/**
46
+
* Logs into the old PDS and gets the account status.
47
+
* Does not need a handle
48
+
* since it is assumed the user has already logged in with the current PDS and we are using their did
49
+
* @param password {string}
50
+
* @param twoFactorCode {string|null}
51
+
* @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
52
+
* @returns {Promise<void>}
53
+
*/
54
+
oldAgentLogin(
55
+
password: string,
56
+
twoFactorCode?: string | null,
57
+
pdsUrl?: string | null,
58
+
): Promise<void>
59
+
/**
60
+
* Gets the missing blobs from the old PDS and uploads them to the current PDS
61
+
* @param statusUpdateHandler {function} - A function to update the status of the migration. This is useful for showing the user the progress of the migration
62
+
* @returns {Promise<{accountStatus: OutputSchema, missingBlobsCount: number}>}
63
+
*/
64
+
migrateMissingBlobs(statusUpdateHandler: Function): Promise<{
65
+
accountStatus: OutputSchema
66
+
missingBlobsCount: number
67
+
}>
60
68
}
61
-
import { AtpAgent } from '@atproto/api';
62
-
//# sourceMappingURL=missingBlobs.d.ts.map
69
+
import { AtpAgent } from '@atproto/api'
70
+
//# sourceMappingURL=missingBlobs.d.ts.map
+79
-64
packages/moover/types/pdsmoover.d.ts
+79
-64
packages/moover/types/pdsmoover.d.ts
···
3
3
* On pdsmoover.com this is the logic for the MOOver
4
4
*/
5
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
-
* @param verificationCode - Optional verification captcha code for account creation if the PDS requires it
39
-
*/
40
-
migrate(oldHandle: string, password: string, newPdsUrl: string, newEmail: string, newHandle: string, inviteCode: string | null, statusUpdateHandler?: Function | null, twoFactorCode?: string | null, verificationCode?: any): Promise<void>;
41
-
/**
42
-
* Sign and submits the PLC operation to officially migrate the account
43
-
* @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
44
-
* @param additionalRotationKeysToAdd {string[]} - additional rotation keys to add in addition to the ones provided by the new PDS.
45
-
* @returns {Promise<void>}
46
-
*/
47
-
signPlcOperation(token: string, additionalRotationKeysToAdd?: string[]): Promise<void>;
48
-
/**
49
-
* Using this method assumes the Migrator class was constructed new and this was called.
50
-
* Find the user's previous PDS from the PLC op logs,
51
-
* logs in and deactivates their old account if it was found still active.
52
-
*
53
-
* @param oldHandle {string}
54
-
* @param oldPassword {string}
55
-
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI.
56
-
* Like (status) => console.log(status)
57
-
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
58
-
* @returns {Promise<void>}
59
-
*/
60
-
deactivateOldAccount(oldHandle: string, oldPassword: string, statusUpdateHandler?: Function | null, twoFactorCode?: string | null): Promise<void>;
61
-
/**
62
-
* Signs the logged-in user in this.newAgent for backups with PDS MOOver. This is usually called after migrate and signPlcOperation are successful
63
-
*
64
-
* @param {string} didWeb
65
-
* @returns {Promise<void>}
66
-
*/
67
-
signUpForBackupsFromMigration(didWeb?: string): Promise<void>;
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
+
* @param verificationCode - Optional verification captcha code for account creation if the PDS requires it
39
+
*/
40
+
migrate(
41
+
oldHandle: string,
42
+
password: string,
43
+
newPdsUrl: string,
44
+
newEmail: string,
45
+
newHandle: string,
46
+
inviteCode: string | null,
47
+
statusUpdateHandler?: Function | null,
48
+
twoFactorCode?: string | null,
49
+
verificationCode?: any,
50
+
): Promise<void>
51
+
/**
52
+
* Sign and submits the PLC operation to officially migrate the account
53
+
* @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
54
+
* @param additionalRotationKeysToAdd {string[]} - additional rotation keys to add in addition to the ones provided by the new PDS.
55
+
* @returns {Promise<void>}
56
+
*/
57
+
signPlcOperation(token: string, additionalRotationKeysToAdd?: string[]): Promise<void>
58
+
/**
59
+
* Using this method assumes the Migrator class was constructed new and this was called.
60
+
* Find the user's previous PDS from the PLC op logs,
61
+
* logs in and deactivates their old account if it was found still active.
62
+
*
63
+
* @param oldHandle {string}
64
+
* @param oldPassword {string}
65
+
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI.
66
+
* Like (status) => console.log(status)
67
+
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
68
+
* @returns {Promise<void>}
69
+
*/
70
+
deactivateOldAccount(
71
+
oldHandle: string,
72
+
oldPassword: string,
73
+
statusUpdateHandler?: Function | null,
74
+
twoFactorCode?: string | null,
75
+
): Promise<void>
76
+
/**
77
+
* Signs the logged-in user in this.newAgent for backups with PDS MOOver. This is usually called after migrate and signPlcOperation are successful
78
+
*
79
+
* @param {string} didWeb
80
+
* @returns {Promise<void>}
81
+
*/
82
+
signUpForBackupsFromMigration(didWeb?: string): Promise<void>
68
83
}
69
-
import { AtpAgent } from '@atproto/api';
70
-
//# sourceMappingURL=pdsmoover.d.ts.map
84
+
import { AtpAgent } from '@atproto/api'
85
+
//# sourceMappingURL=pdsmoover.d.ts.map
+109
-98
packages/moover/types/plc-ops.d.ts
+109
-98
packages/moover/types/plc-ops.d.ts
···
1
1
/**
2
2
* JSDoc type-only import to avoid runtime import errors in the browser.
3
3
*/
4
-
export type defs = typeof defs;
4
+
export type defs = typeof defs
5
5
/**
6
6
* JSDoc type-only import to avoid runtime import errors in the browser.
7
7
*/
8
-
export type normalizeOp = any;
8
+
export type normalizeOp = any
9
9
/**
10
10
* JSDoc type-only import to avoid runtime import errors in the browser.
11
11
*/
12
-
export type Operation = import("@atcute/did-plc").Operation;
12
+
export type Operation = import('@atcute/did-plc').Operation
13
13
/**
14
14
* JSDoc type-only import to avoid runtime import errors in the browser.
15
15
*/
16
-
export type CompatibleOperation = import("@atcute/did-plc").CompatibleOperation;
16
+
export type CompatibleOperation = import('@atcute/did-plc').CompatibleOperation
17
17
/**
18
18
* JSDoc type-only import to avoid runtime import errors in the browser.
19
19
*/
20
-
export type IndexedEntryLog = import("@atcute/did-plc").IndexedEntryLog;
20
+
export type IndexedEntryLog = import('@atcute/did-plc').IndexedEntryLog
21
21
/**
22
22
* JSDoc type-only import to avoid runtime import errors in the browser.
23
23
*/
24
-
export type IndexedEntry = import("@atcute/did-plc").IndexedEntry;
24
+
export type IndexedEntry = import('@atcute/did-plc').IndexedEntry
25
25
/**
26
26
* Class to help with various PLC operations
27
27
*/
28
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>;
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(
89
+
did: string,
90
+
signingRotationKey: P256PrivateKey | Secp256k1PrivateKey,
91
+
alsoKnownAs: string[],
92
+
rotationKeys: string[],
93
+
pds: string,
94
+
verificationKey: string,
95
+
prev: string,
96
+
): Promise<void>
97
+
/**
98
+
* Takes a multi or hex based private key and returns a keypair
99
+
* @param privateKeyString {string}
100
+
* @param type {string} - secp256k1 or p256, needed if the private key is hex based, can be assumed if it's a multikey
101
+
* @returns {Promise<{type: string, didPublicKey: `did:key:${string}`, keypair: P256PrivateKey|Secp256k1PrivateKey}>}
102
+
*/
103
+
getKeyPair(
104
+
privateKeyString: string,
105
+
type?: string,
106
+
): Promise<{
107
+
type: string
108
+
didPublicKey: `did:key:${string}`
109
+
keypair: P256PrivateKey | Secp256k1PrivateKey
110
+
}>
111
+
/**
112
+
* Submits a new operation to the plc directory
113
+
* @param did {string} - The user's did
114
+
* @param operation
115
+
* @returns {Promise<void>}
116
+
*/
117
+
pushPlcOperation(did: string, operation: any): Promise<void>
118
+
/**
119
+
* 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
120
+
*
121
+
* @param iss The user's did
122
+
* @param aud The did:web, if it's a PDS it's usually from /xrpc/com.atproto.server.describeServer
123
+
* @param keypair The keypair to sign with only supporting ES256K atm
124
+
* @param lxm The lxm which is usually com.atproto.server.createAccount for creating a new account
125
+
* @returns {Promise<string>}
126
+
*/
127
+
createANewServiceAuthToken(iss: any, aud: any, keypair: any, lxm: any): Promise<string>
117
128
}
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
129
+
import { defs } from '@atcute/did-plc'
130
+
import { P256PrivateKey } from '@atcute/crypto'
131
+
import { Secp256k1PrivateKey } from '@atcute/crypto'
132
+
//# sourceMappingURL=plc-ops.d.ts.map
+92
-77
packages/moover/types/restore.d.ts
+92
-77
packages/moover/types/restore.d.ts
···
1
-
export type Operation = import("@atcute/did-plc").Operation;
1
+
export type Operation = import('@atcute/did-plc').Operation
2
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>;
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(
62
+
rotationKey: string,
63
+
rotationKeyType: string,
64
+
currentHandleOrDid: string,
65
+
newPDS: string,
66
+
newHandle: string,
67
+
newPassword: string,
68
+
newEmail: string,
69
+
inviteCode: string | null,
70
+
cidToRestoreTo?: string | null,
71
+
onStatus?: Function | null,
72
+
): Promise<void>
73
+
/**
74
+
* This method signs the plc operation over to the new PDS and activates the account
75
+
* Assumes you have already created a new account during the recovery process and logged in
76
+
* Uses the recommended did doc from the PDS as a base and adds the users rotation key to the rotation keys array
77
+
*
78
+
* @param usersDid
79
+
* @param additionalRotationKeysToAdd
80
+
* @param prevCid
81
+
* @returns {Promise<void>}
82
+
*/
83
+
signRestorePlcOperation(
84
+
usersDid: any,
85
+
additionalRotationKeysToAdd: any[],
86
+
prevCid: any,
87
+
): Promise<void>
73
88
}
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
89
+
import { PlcOps } from './plc-ops.js'
90
+
import { Secp256k1PrivateKeyExportable } from '@atcute/crypto'
91
+
import { AtpAgent } from '@atproto/api'
92
+
import { P256PrivateKey } from '@atcute/crypto'
93
+
import { Secp256k1PrivateKey } from '@atcute/crypto'
94
+
//# sourceMappingURL=restore.d.ts.map
+23
-23
packages/moover/vite.config.js
+23
-23
packages/moover/vite.config.js
···
1
-
import {dirname, resolve} from 'node:path'
2
-
import {fileURLToPath} from 'node:url'
3
-
import {defineConfig} from 'vite'
1
+
import { dirname, resolve } from 'node:path'
2
+
import { fileURLToPath } from 'node:url'
3
+
import { defineConfig } from 'vite'
4
4
5
5
const __dirname = dirname(fileURLToPath(import.meta.url))
6
6
7
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
-
},
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
+
// },
27
26
},
28
-
})
27
+
},
28
+
})
+1
-1
web-ui/package.json
+1
-1
web-ui/package.json
+76
-49
web-ui/pnpm-lock.yaml
+76
-49
web-ui/pnpm-lock.yaml
···
21
21
specifier: ^1.0.1
22
22
version: 1.0.1
23
23
'@pds-moover/moover':
24
-
specifier: ^1.0.5
25
-
version: 1.0.5(@atcute/identity@1.1.1)(vite@7.1.12(@types/node@22.19.0))
24
+
specifier: ^1.0.6
25
+
version: 1.0.6(@atcute/identity@1.1.1)(vite@7.1.12(@types/node@22.19.0))
26
26
devDependencies:
27
27
'@eslint/compat':
28
28
specifier: ^1.4.0
···
79
79
'@atcute/atproto@3.1.9':
80
80
resolution: {integrity: sha512-DyWwHCTdR4hY2BPNbLXgVmm7lI+fceOwWbE4LXbGvbvVtSn+ejSVFaAv01Ra3kWDha0whsOmbJL8JP0QPpf1+w==}
81
81
82
-
'@atcute/cbor@2.2.8':
83
-
resolution: {integrity: sha512-UzOAN9BuN6JCXgn0ryV8qZuRJUDrNqrbLd6EFM8jc6RYssjRyGRxNy6RZ1NU/07Hd8Tq/0pz8+nQiMu5Zai5uw==}
82
+
'@atcute/cbor@2.3.2':
83
+
resolution: {integrity: sha512-xP2SORSau/VVI00x2V4BjwIkHr6EQ7l/MXEOPaa4LGYtePFc4gnD4L1yN10dT5NEuUnvGEuCh6arLB7gz1smVQ==}
84
84
85
-
'@atcute/cid@2.2.6':
86
-
resolution: {integrity: sha512-bTAHHbJ24p+E//V4KCS4xdmd39o211jJswvqQOevj7vk+5IYcgDLx1ryZWZ1sEPOo9x875li/kj5gpKL14RDwQ==}
85
+
'@atcute/cid@2.4.1':
86
+
resolution: {integrity: sha512-bwhna69RCv7yetXudtj+2qrMPYvhhIQqvJz6YUpUS98v7OdF3X2dnye9Nig2NDrklZcuyOsu7sQo7GOykJXRLQ==}
87
87
88
88
'@atcute/client@4.0.5':
89
89
resolution: {integrity: sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA==}
90
90
91
-
'@atcute/crypto@2.2.6':
92
-
resolution: {integrity: sha512-vkuexF+kmrKE1/Uqzub99Qi4QpnxA2jbu60E6PTgL4XypELQ6rb59MB/J1VbY2gs0kd3ET7+L3+NWpKD5nXyfA==}
91
+
'@atcute/crypto@2.3.0':
92
+
resolution: {integrity: sha512-w5pkJKCjbNMQu+F4JRHbR3ROQyhi1wbn+GSC6WDQamcYHkZmEZk1/eoI354bIQOOfkEM6aFLv718iskrkon4GQ==}
93
93
94
94
'@atcute/did-plc@0.1.7':
95
95
resolution: {integrity: sha512-a7yOQNqViae3rB5/xa3U0EPJbFD9l8zOHXx6XASZ5F8+Vy2uTgXK3omurpNZ5UxRpy1ni1AMhSohXr61cqWbkg==}
96
96
97
-
'@atcute/identity-resolver@1.1.4':
98
-
resolution: {integrity: sha512-/SVh8vf2cXFJenmBnGeYF2aY3WGQm3cJeew5NWTlkqoy3LvJ5wkvKq9PWu4Tv653VF40rPOp6LOdVr9Fa+q5rA==}
97
+
'@atcute/identity-resolver@1.2.2':
98
+
resolution: {integrity: sha512-eUh/UH4bFvuXS0X7epYCeJC/kj4rbBXfSRumLEH4smMVwNOgTo7cL/0Srty+P/qVPoZEyXdfEbS0PHJyzoXmHw==}
99
99
peerDependencies:
100
100
'@atcute/identity': ^1.0.0
101
101
···
105
105
'@atcute/lexicons@1.2.2':
106
106
resolution: {integrity: sha512-bgEhJq5Z70/0TbK5sx+tAkrR8FsCODNiL2gUEvS5PuJfPxmFmRYNWaMGehxSPaXWpU2+Oa9ckceHiYbrItDTkA==}
107
107
108
-
'@atcute/multibase@1.1.6':
109
-
resolution: {integrity: sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg==}
108
+
'@atcute/lexicons@1.2.9':
109
+
resolution: {integrity: sha512-/RRHm2Cw9o8Mcsrq0eo8fjS9okKYLGfuFwrQ0YoP/6sdSDsXshaTLJsvLlcUcaDaSJ1YFOuHIo3zr2Om2F/16g==}
110
110
111
-
'@atcute/uint8array@1.0.5':
112
-
resolution: {integrity: sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q==}
111
+
'@atcute/multibase@1.1.8':
112
+
resolution: {integrity: sha512-pJgtImMZKCjqwRbu+2GzB+4xQjKBXDwdZOzeqe0u97zYKRGftpGYGvYv3+pMe2xXe+msDyu7Nv8iJp+U14otTA==}
113
+
114
+
'@atcute/uint8array@1.1.1':
115
+
resolution: {integrity: sha512-3LsC8XB8TKe9q/5hOA5sFuzGaIFdJZJNewC5OKa3o/eU6+K7JR6see9Zy2JbQERNVnRl11EzbNov1efgLMAs4g==}
116
+
117
+
'@atcute/util-fetch@1.0.5':
118
+
resolution: {integrity: sha512-qjHj01BGxjSjIFdPiAjSARnodJIIyKxnCMMEcXMESo9TAyND6XZQqrie5fia+LlYWVXdpsTds8uFQwc9jdKTig==}
113
119
114
-
'@atcute/util-fetch@1.0.4':
115
-
resolution: {integrity: sha512-sIU9Qk0dE8PLEXSfhy+gIJV+HpiiknMytCI2SqLlqd0vgZUtEKI/EQfP+23LHWvP+CLCzVDOa6cpH045OlmNBg==}
120
+
'@atcute/util-text@1.1.1':
121
+
resolution: {integrity: sha512-JH0SxzUQJAmbOBTYyhxQbkkI6M33YpjlVLEcbP5GYt43xgFArzV0FJVmEpvIj0kjsmphHB45b6IitdvxPdec9w==}
116
122
117
123
'@atproto/api@0.16.11':
118
124
resolution: {integrity: sha512-1dhfQNHiclb102RW+Ea8Nft5olfqU0Ev/vlQaSX6mWNo1aP5zT+sPODJ8+BTUOYk3vcuvL7QMkqA/rLYy2PMyw==}
···
386
392
'@pds-moover/lexicons@1.0.1':
387
393
resolution: {integrity: sha512-fv5b/DtHM7FEo/JklyF9gdK0ainlb6mWjWrBe6cmSAeg9G/4O2jBlQUOqfOAICY9gOcrCpkOrk9PHgGw//JQ2A==}
388
394
389
-
'@pds-moover/moover@1.0.5':
390
-
resolution: {integrity: sha512-do8Itd1mrH/446KYJf+velZqsA45ldJCPrEV10eD3nhFJyhf4KBEuseSHIhV0+KIZGU06HvmofBO+v8EZx9ToA==}
395
+
'@pds-moover/moover@1.0.6':
396
+
resolution: {integrity: sha512-Zy+wcrZwoyne7NhuG+5MDFoJ+lpteCpfS6w2pmma9F2IKrVTj2G3Pca7ZVDaibGmCMTJMo21XYaPg+9nLXFD4Q==}
391
397
392
398
'@polka/url@1.0.0-next.29':
393
399
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
···
541
547
'@standard-schema/spec@1.0.0':
542
548
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
543
549
550
+
'@standard-schema/spec@1.1.0':
551
+
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
552
+
544
553
'@sveltejs/acorn-typescript@1.0.6':
545
554
resolution: {integrity: sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ==}
546
555
peerDependencies:
···
677
686
ajv@6.12.6:
678
687
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
679
688
680
-
alpinejs@3.15.2:
681
-
resolution: {integrity: sha512-2kYF2aG+DTFkE6p0rHG5XmN4VEb6sO9b02aOdU4+i8QN6rL0DbRZQiypDE1gBcGO65yDcqMz5KKYUYgMUxgNkw==}
689
+
alpinejs@3.15.8:
690
+
resolution: {integrity: sha512-zxIfCRTBGvF1CCLIOMQOxAyBuqibxSEwS6Jm1a3HGA9rgrJVcjEWlwLcQTVGAWGS8YhAsTRLVrtQ5a5QT9bSSQ==}
682
691
683
692
ansi-styles@4.3.0:
684
693
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
···
1260
1269
undici-types@6.21.0:
1261
1270
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
1262
1271
1272
+
unicode-segmenter@0.14.5:
1273
+
resolution: {integrity: sha512-jHGmj2LUuqDcX3hqY12Ql+uhUTn8huuxNZGq7GvtF6bSybzH3aFgedYu/KTzQStEgt1Ra2F3HxadNXsNjb3m3g==}
1274
+
1263
1275
uri-js@4.4.1:
1264
1276
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
1265
1277
···
1352
1364
dependencies:
1353
1365
'@atcute/lexicons': 1.2.2
1354
1366
1355
-
'@atcute/cbor@2.2.8':
1367
+
'@atcute/cbor@2.3.2':
1356
1368
dependencies:
1357
-
'@atcute/cid': 2.2.6
1358
-
'@atcute/multibase': 1.1.6
1359
-
'@atcute/uint8array': 1.0.5
1369
+
'@atcute/cid': 2.4.1
1370
+
'@atcute/multibase': 1.1.8
1371
+
'@atcute/uint8array': 1.1.1
1360
1372
1361
-
'@atcute/cid@2.2.6':
1373
+
'@atcute/cid@2.4.1':
1362
1374
dependencies:
1363
-
'@atcute/multibase': 1.1.6
1364
-
'@atcute/uint8array': 1.0.5
1375
+
'@atcute/multibase': 1.1.8
1376
+
'@atcute/uint8array': 1.1.1
1365
1377
1366
1378
'@atcute/client@4.0.5':
1367
1379
dependencies:
1368
1380
'@atcute/identity': 1.1.1
1369
1381
'@atcute/lexicons': 1.2.2
1370
1382
1371
-
'@atcute/crypto@2.2.6':
1383
+
'@atcute/crypto@2.3.0':
1372
1384
dependencies:
1373
-
'@atcute/multibase': 1.1.6
1374
-
'@atcute/uint8array': 1.0.5
1385
+
'@atcute/multibase': 1.1.8
1386
+
'@atcute/uint8array': 1.1.1
1375
1387
'@noble/secp256k1': 3.0.0
1376
1388
1377
1389
'@atcute/did-plc@0.1.7':
1378
1390
dependencies:
1379
-
'@atcute/cbor': 2.2.8
1380
-
'@atcute/cid': 2.2.6
1381
-
'@atcute/crypto': 2.2.6
1391
+
'@atcute/cbor': 2.3.2
1392
+
'@atcute/cid': 2.4.1
1393
+
'@atcute/crypto': 2.3.0
1382
1394
'@atcute/identity': 1.1.1
1383
1395
'@atcute/lexicons': 1.2.2
1384
-
'@atcute/multibase': 1.1.6
1385
-
'@atcute/uint8array': 1.0.5
1396
+
'@atcute/multibase': 1.1.8
1397
+
'@atcute/uint8array': 1.1.1
1386
1398
'@badrap/valita': 0.4.6
1387
1399
1388
-
'@atcute/identity-resolver@1.1.4(@atcute/identity@1.1.1)':
1400
+
'@atcute/identity-resolver@1.2.2(@atcute/identity@1.1.1)':
1389
1401
dependencies:
1390
1402
'@atcute/identity': 1.1.1
1391
-
'@atcute/lexicons': 1.2.2
1392
-
'@atcute/util-fetch': 1.0.4
1403
+
'@atcute/lexicons': 1.2.9
1404
+
'@atcute/util-fetch': 1.0.5
1393
1405
'@badrap/valita': 0.4.6
1394
1406
1395
1407
'@atcute/identity@1.1.1':
···
1402
1414
'@standard-schema/spec': 1.0.0
1403
1415
esm-env: 1.2.2
1404
1416
1405
-
'@atcute/multibase@1.1.6':
1417
+
'@atcute/lexicons@1.2.9':
1406
1418
dependencies:
1407
-
'@atcute/uint8array': 1.0.5
1419
+
'@atcute/uint8array': 1.1.1
1420
+
'@atcute/util-text': 1.1.1
1421
+
'@standard-schema/spec': 1.1.0
1422
+
esm-env: 1.2.2
1408
1423
1409
-
'@atcute/uint8array@1.0.5': {}
1424
+
'@atcute/multibase@1.1.8':
1425
+
dependencies:
1426
+
'@atcute/uint8array': 1.1.1
1427
+
1428
+
'@atcute/uint8array@1.1.1': {}
1410
1429
1411
-
'@atcute/util-fetch@1.0.4':
1430
+
'@atcute/util-fetch@1.0.5':
1412
1431
dependencies:
1413
1432
'@badrap/valita': 0.4.6
1433
+
1434
+
'@atcute/util-text@1.1.1':
1435
+
dependencies:
1436
+
unicode-segmenter: 0.14.5
1414
1437
1415
1438
'@atproto/api@0.16.11':
1416
1439
dependencies:
···
1626
1649
'@atproto/lexicon': 0.5.1
1627
1650
'@atproto/xrpc': 0.7.5
1628
1651
1629
-
'@pds-moover/moover@1.0.5(@atcute/identity@1.1.1)(vite@7.1.12(@types/node@22.19.0))':
1652
+
'@pds-moover/moover@1.0.6(@atcute/identity@1.1.1)(vite@7.1.12(@types/node@22.19.0))':
1630
1653
dependencies:
1631
-
'@atcute/cbor': 2.2.8
1654
+
'@atcute/cbor': 2.3.2
1632
1655
'@atcute/client': 4.0.5
1633
-
'@atcute/crypto': 2.2.6
1656
+
'@atcute/crypto': 2.3.0
1634
1657
'@atcute/did-plc': 0.1.7
1635
-
'@atcute/identity-resolver': 1.1.4(@atcute/identity@1.1.1)
1658
+
'@atcute/identity-resolver': 1.2.2(@atcute/identity@1.1.1)
1636
1659
'@atcute/lexicons': 1.2.2
1637
-
'@atcute/multibase': 1.1.6
1660
+
'@atcute/multibase': 1.1.8
1638
1661
'@atproto/api': 0.16.11
1639
1662
'@pds-moover/lexicons': 1.0.1
1640
-
alpinejs: 3.15.2
1663
+
alpinejs: 3.15.8
1641
1664
vite-plugin-full-reload: 1.2.0
1642
1665
vite-rs-plugin: 1.0.1(vite@7.1.12(@types/node@22.19.0))
1643
1666
transitivePeerDependencies:
···
1749
1772
optional: true
1750
1773
1751
1774
'@standard-schema/spec@1.0.0': {}
1775
+
1776
+
'@standard-schema/spec@1.1.0': {}
1752
1777
1753
1778
'@sveltejs/acorn-typescript@1.0.6(acorn@8.15.0)':
1754
1779
dependencies:
···
1930
1955
json-schema-traverse: 0.4.1
1931
1956
uri-js: 4.4.1
1932
1957
1933
-
alpinejs@3.15.2:
1958
+
alpinejs@3.15.8:
1934
1959
dependencies:
1935
1960
'@vue/reactivity': 3.1.5
1936
1961
···
2513
2538
multiformats: 9.9.0
2514
2539
2515
2540
undici-types@6.21.0: {}
2541
+
2542
+
unicode-segmenter@0.14.5: {}
2516
2543
2517
2544
uri-js@4.4.1:
2518
2545
dependencies: