- By pass migrate blobs if it's a retry, does do migrate missing blobs so it does not miss any
- UI Tweaks to hide inputs during migration along with a bit of a message on what to do if the migration fails
- Moved blob uploads to shared logic for rate limits update later
+1
-1
.oxlintrc.json
+1
-1
.oxlintrc.json
+1
-1
justfile
+1
-1
justfile
+64
-45
packages/moover/lib/pdsmoover.js
+64
-45
packages/moover/lib/pdsmoover.js
···
32
this.migratePrefs = true
33
/** @type {boolean} */
34
this.migratePlcRecord = true
35
}
36
37
/**
···
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
···
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')
147
} else {
148
// Catches any other error and stops the migration process
···
186
limit: 100,
187
})
188
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
-
}
208
-
}
209
blobCursor = listedBlobs.data.cursor
210
} while (blobCursor)
211
}
212
213
if (this.migrateMissingBlobs) {
···
233
limit: 100,
234
})
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)
256
-
}
257
-
}
258
missingBlobCursor = missingBlobs.data.cursor
259
} while (missingBlobCursor)
260
}
261
}
262
if (this.migratePrefs) {
···
269
270
if (this.migratePlcRecord) {
271
await oldAgent.com.atproto.identity.requestPlcOperationSignature()
272
-
safeStatusUpdate(statusUpdateHandler, 'Please check your email for a PLC token')
273
}
274
}
275
···
32
this.migratePrefs = true
33
/** @type {boolean} */
34
this.migratePlcRecord = true
35
+
/**
36
+
* How many blobs have been uploaded to the new PDS in the current step
37
+
@type {number} */
38
+
this.uploadedBlobsCount = 0
39
+
}
40
+
41
+
/**
42
+
* Uploads blobs to the new PDS
43
+
* @param {AtpAgent} oldAgent
44
+
* @param {AtpAgent} newAgent
45
+
* @param {string} usersDid
46
+
* @param {[string]} cids
47
+
* @param {number} totalBlobs
48
+
* @param {function|null} statusUpdateHandler
49
+
*/
50
+
async uploadBlobs(oldAgent, newAgent, usersDid, cids, totalBlobs, statusUpdateHandler) {
51
+
for (const cid of cids) {
52
+
try {
53
+
const blobRes = await oldAgent.com.atproto.sync.getBlob({
54
+
did: usersDid,
55
+
cid,
56
+
})
57
+
await newAgent.com.atproto.repo.uploadBlob(blobRes.data, {
58
+
encoding: blobRes.headers['content-type'],
59
+
})
60
+
this.uploadedBlobsCount++
61
+
if (this.uploadedBlobsCount % 10 === 0) {
62
+
safeStatusUpdate(
63
+
statusUpdateHandler,
64
+
`Migrating blobs: ${this.uploadedBlobsCount}/${totalBlobs}`,
65
+
)
66
+
}
67
+
} catch (error) {
68
+
console.error(error)
69
+
}
70
+
}
71
}
72
73
/**
···
97
twoFactorCode = null,
98
verificationCode = null,
99
) {
100
oldHandle = cleanHandle(oldHandle)
101
let oldAgent
102
let usersDid
···
177
} catch (error) {
178
// Ideally should catch if the repo already exists, and if so silently log it and move along to the next step
179
if (error?.error === 'AlreadyExists') {
180
+
// Sets the migrate blobs flag to false so it moves on to just migrate missing blobs in the event of a retry
181
+
this.migrateBlobs = false
182
console.log('Repo already exists, logging in')
183
} else {
184
// Catches any other error and stops the migration process
···
222
limit: 100,
223
})
224
225
+
await this.uploadBlobs(
226
+
oldAgent,
227
+
newAgent,
228
+
usersDid,
229
+
listedBlobs.data.cids,
230
+
newAccountStatus.data.expectedBlobs,
231
+
statusUpdateHandler,
232
+
)
233
blobCursor = listedBlobs.data.cursor
234
} while (blobCursor)
235
+
// Resets since this is a shared state with missing blobs job
236
+
this.uploadedBlobsCount = 0
237
}
238
239
if (this.migrateMissingBlobs) {
···
259
limit: 100,
260
})
261
262
+
let missingCids = missingBlobs.data.blobs.map(blob => blob.cid)
263
+
await this.uploadBlobs(
264
+
oldAgent,
265
+
newAgent,
266
+
usersDid,
267
+
missingCids,
268
+
totalMissingBlobs,
269
+
statusUpdateHandler,
270
+
)
271
+
272
missingBlobCursor = missingBlobs.data.cursor
273
} while (missingBlobCursor)
274
+
// Resets since this is a shared state with the migrate blobs job
275
+
this.uploadedBlobsCount = 0
276
}
277
}
278
if (this.migratePrefs) {
···
285
286
if (this.migratePlcRecord) {
287
await oldAgent.com.atproto.identity.requestPlcOperationSignature()
288
+
safeStatusUpdate(
289
+
statusUpdateHandler,
290
+
'Please check your email attached to your previous account for a PLC token',
291
+
)
292
}
293
}
294
+3
-3
packages/moover/package.json
+3
-3
packages/moover/package.json
···
1
{
2
"name": "@pds-moover/moover",
3
-
"version": "1.0.6",
4
"description": "Utilities for ATProto PDS migrations and recovery",
5
"repository": {
6
"type": "git",
···
34
"scripts": {
35
"dev": "vite",
36
"build": "vite build",
37
"gen:types": "tsc -p .",
38
-
"preview": "vite preview",
39
-
"generate:lexicons": "lex build --lexicons lexicons --out lib/lexicons --clear"
40
},
41
"devDependencies": {
42
"eslint": "^9.34.0",
···
1
{
2
"name": "@pds-moover/moover",
3
+
"version": "1.0.7",
4
"description": "Utilities for ATProto PDS migrations and recovery",
5
"repository": {
6
"type": "git",
···
34
"scripts": {
35
"dev": "vite",
36
"build": "vite build",
37
+
"build:watch": "vite build --watch",
38
"gen:types": "tsc -p .",
39
+
"preview": "vite preview"
40
},
41
"devDependencies": {
42
"eslint": "^9.34.0",
+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'>
3
/**
4
* Cleans the handle of @ and some other unicode characters that used to show up when copied from the profile
5
* @param handle {string}
6
* @returns {string}
7
*/
8
-
export function cleanHandle(handle: string): string
9
/**
10
* Convince helper to resolve a handle to a did and then find the PDS url from the did document.
11
*
···
13
* @returns {Promise<{usersDid: string, pds: string}>}
14
*/
15
export function handleAndPDSResolver(handle: any): Promise<{
16
-
usersDid: string
17
-
pds: string
18
-
}>
19
/**
20
* Fetches the DID Web from the .well-known/did.json endpoint of the server.
21
* Legacy and was helpful if the web ui and server are on the same domain, not as useful now
22
* @param baseUrl
23
* @returns {Promise<*>}
24
*/
25
-
export function fetchPDSMooverDIDWeb(baseUrl: any): Promise<any>
26
-
import { CompositeHandleResolver } from '@atcute/identity-resolver'
27
-
import { CompositeDidDocumentResolver } from '@atcute/identity-resolver'
28
-
//# sourceMappingURL=atprotoUtils.d.ts.map
···
1
+
export const handleResolver: CompositeHandleResolver;
2
+
export const docResolver: CompositeDidDocumentResolver<"plc" | "web">;
3
/**
4
* Cleans the handle of @ and some other unicode characters that used to show up when copied from the profile
5
* @param handle {string}
6
* @returns {string}
7
*/
8
+
export function cleanHandle(handle: string): string;
9
/**
10
* Convince helper to resolve a handle to a did and then find the PDS url from the did document.
11
*
···
13
* @returns {Promise<{usersDid: string, pds: string}>}
14
*/
15
export function handleAndPDSResolver(handle: any): Promise<{
16
+
usersDid: string;
17
+
pds: string;
18
+
}>;
19
/**
20
* Fetches the DID Web from the .well-known/did.json endpoint of the server.
21
* Legacy and was helpful if the web ui and server are on the same domain, not as useful now
22
* @param baseUrl
23
* @returns {Promise<*>}
24
*/
25
+
export function fetchPDSMooverDIDWeb(baseUrl: any): Promise<any>;
26
+
import { CompositeHandleResolver } from '@atcute/identity-resolver';
27
+
import { CompositeDidDocumentResolver } from '@atcute/identity-resolver';
28
+
//# sourceMappingURL=atprotoUtils.d.ts.map
+1
-1
packages/moover/types/atprotoUtils.d.ts.map
+1
-1
packages/moover/types/atprotoUtils.d.ts.map
···
1
-
{"version":3,"file":"atprotoUtils.d.ts","sourceRoot":"","sources":["../lib/atprotoUtils.js"],"names":[],"mappings":"AAOA,qDAQG;AAEH,sEAKG;AAEH;;;;GAIG;AACH,oCAHkB,MAAM,GACX,MAAM,CAMd;AAGL;;;;;GAKG;AACH,mDAFa,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,CAAC,CAqBpD;AAGD;;;;;GAKG;AACH,oDAFa,OAAO,CAAC,GAAC,CAAC,CAStB;wCAxEM,2BAA2B;6CAA3B,2BAA2B"}
···
1
+
{"version":3,"file":"atprotoUtils.d.ts","sourceRoot":"","sources":["../lib/atprotoUtils.js"],"names":[],"mappings":"AASA,qDAQE;AAEF,sEAKE;AAkBF;;;;GAIG;AACH,oCAHkB,MAAM,GACX,MAAM,CAMyC;AAE5D;;;;;GAKG;AACH,mDAFa,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAC,CAAC,CA0BpD;AAED;;;;;GAKG;AACH,oDAFa,OAAO,CAAC,GAAC,CAAC,CAStB;wCA3FM,2BAA2B;6CAA3B,2BAA2B"}
+82
-89
packages/moover/types/backup.d.ts
+82
-89
packages/moover/types/backup.d.ts
···
1
/**
2
* JSDoc type-only import to avoid runtime import errors in the browser.
3
*/
4
-
export type InferXRPCBodyOutput = any
5
/**
6
* JSDoc type-only import to avoid runtime import errors in the browser.
7
* @typedef {import('@atcute/lexicons').InferXRPCBodyOutput} InferXRPCBodyOutput
···
10
* Logic to sign up and manage backups for pdsmoover.com (or your own selfhosted instance)
11
*/
12
export class BackupService {
13
-
/**
14
-
*
15
-
* @param backupDidWeb {string} - The did:web for the xrpc service for backups, defaults to did:web:pdsmoover.com
16
-
*/
17
-
constructor(backupDidWeb?: string)
18
-
/**
19
-
*
20
-
* @type {Client}
21
-
*/
22
-
atCuteClient: Client
23
-
/**
24
-
*
25
-
* @type {CredentialManager}
26
-
*/
27
-
atCuteCredentialManager: CredentialManager
28
-
/**
29
-
* The did:web for the xrpc service for backups, defaults to pdsmoover.com
30
-
* @type {string}
31
-
*/
32
-
backupDidWeb: string
33
-
/**
34
-
* Logs in and returns the backup status.
35
-
* To use the rest of the BackupService, it is assumed that this has ran first,
36
-
* and the user has successfully signed up. A successful login is a returned null if the user has not signed up.
37
-
* or the backup status if they are
38
-
*
39
-
* If the server requires 2FA,
40
-
* it will throw with error.error === 'AuthFactorTokenRequired'.
41
-
* @param identifier {string} handle or did
42
-
* @param password {string}
43
-
* @param {function|null} onStatus - a function that takes a string used to update the UI.
44
-
* Like (status) => console.log(status)
45
-
* @param twoFactorCode {string|null}
46
-
*
47
-
* @returns {Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>|null>}
48
-
*/
49
-
loginAndStatus(
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>
97
}
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
···
1
/**
2
* JSDoc type-only import to avoid runtime import errors in the browser.
3
*/
4
+
export type InferXRPCBodyOutput = any;
5
/**
6
* JSDoc type-only import to avoid runtime import errors in the browser.
7
* @typedef {import('@atcute/lexicons').InferXRPCBodyOutput} InferXRPCBodyOutput
···
10
* Logic to sign up and manage backups for pdsmoover.com (or your own selfhosted instance)
11
*/
12
export class BackupService {
13
+
/**
14
+
*
15
+
* @param backupDidWeb {string} - The did:web for the xrpc service for backups, defaults to did:web:pdsmoover.com
16
+
*/
17
+
constructor(backupDidWeb?: string);
18
+
/**
19
+
*
20
+
* @type {Client}
21
+
*/
22
+
atCuteClient: Client;
23
+
/**
24
+
*
25
+
* @type {CredentialManager}
26
+
*/
27
+
atCuteCredentialManager: CredentialManager;
28
+
/**
29
+
* The did:web for the xrpc service for backups, defaults to pdsmoover.com
30
+
* @type {string}
31
+
*/
32
+
backupDidWeb: string;
33
+
/**
34
+
* Logs in and returns the backup status.
35
+
* To use the rest of the BackupService, it is assumed that this has ran first,
36
+
* and the user has successfully signed up. A successful login is a returned null if the user has not signed up.
37
+
* or the backup status if they are
38
+
*
39
+
* If the server requires 2FA,
40
+
* it will throw with error.error === 'AuthFactorTokenRequired'.
41
+
* @param identifier {string} handle or did
42
+
* @param password {string}
43
+
* @param {function|null} onStatus - a function that takes a string used to update the UI.
44
+
* Like (status) => console.log(status)
45
+
* @param twoFactorCode {string|null}
46
+
*
47
+
* @returns {Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>|null>}
48
+
*/
49
+
loginAndStatus(identifier: string, password: string, onStatus?: Function | null, twoFactorCode?: string | null): Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema["output"]> | null>;
50
+
/**
51
+
* Signs the user up for backups with the service
52
+
* @param onStatus
53
+
* @returns {Promise<void>}
54
+
*/
55
+
signUp(onStatus?: any): Promise<void>;
56
+
/**
57
+
* Requests a PLC token to be sent to the user's email, needed to add a new rotation key
58
+
* @returns {Promise<void>}
59
+
*/
60
+
requestAPlcToken(): Promise<void>;
61
+
/**
62
+
* Adds a new rotation to the users did document. Assumes you are already signed in.
63
+
*
64
+
* WARNING: This will overwrite any existing rotation keys with the new one at the top, and the PDS key as the second one
65
+
* @param plcToken {string} - PLC token from the user's email that was sent from requestAPlcToken
66
+
* @param rotationKey {string} - The new rotation key to add to the user's did document
67
+
* @returns {Promise<void>}
68
+
*/
69
+
addANewRotationKey(plcToken: string, rotationKey: string): Promise<void>;
70
+
/**
71
+
*
72
+
* Gets the current status of the user's backup repository.
73
+
*
74
+
* @param onStatus {function|null} - a function that takes a string used to update the UI.
75
+
* @returns {Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema['output']>>}
76
+
*/
77
+
getUsersRepoStatus(onStatus?: Function | null): Promise<InferXRPCBodyOutput<ComPdsmooverBackupDescribeServer.mainSchema["output"]>>;
78
+
/**
79
+
* Requests a backup to be run immediately for the signed-in user. Usually does, depend on the server's backup queue
80
+
* @param onStatus
81
+
* @returns {Promise<boolean>}
82
+
*/
83
+
runBackupNow(onStatus?: any): Promise<boolean>;
84
+
/**
85
+
* Remove (delete) the signed-in user's backup repository. this also deletes all the user's backup data.
86
+
* @param onStatus
87
+
* @returns {Promise<boolean>}
88
+
*/
89
+
removeRepo(onStatus?: any): Promise<boolean>;
90
}
91
+
import { Client } from '@atcute/client';
92
+
import { CredentialManager } from '@atcute/client';
93
+
import { ComPdsmooverBackupDescribeServer } from '@pds-moover/lexicons';
94
+
//# sourceMappingURL=backup.d.ts.map
+1
-1
packages/moover/types/backup.d.ts.map
+1
-1
packages/moover/types/backup.d.ts.map
···
1
-
{"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../lib/backup.js"],"names":[],"mappings":";;;;AAKA;;;GAGG;AAGH;;GAEG;AACH;IACI;;;OAGG;IACH,2BAFwB,MAAM,EAmB7B;IAhBG;;;OAGG;IACH,cAFU,MAAM,CAEQ;IACxB;;;OAGG;IACH,yBAFU,iBAAiB,CAEQ;IAEnC;;;OAGG;IACH,cAFU,MAAM,CAEgB;IAIpC;;;;;;;;;;;;;;;OAeG;IACH,2BARsB,MAAM,YACR,MAAM,aACf,WAAS,IAAI,kBAEC,MAAM,GAAC,IAAI,GAEvB,OAAO,CAAC,mBAAmB,CAAC,gCAAgC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAC,IAAI,CAAC,CAyDpG;IAED;;;;OAIG;IACH,wBAFa,OAAO,CAAC,IAAI,CAAC,CAczB;IAED;;;OAGG;IACH,oBAFa,OAAO,CAAC,IAAI,CAAC,CAgBzB;IAED;;;;;;;OAOG;IACH,6BAJoB,MAAM,eACH,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAgDzB;IAGD;;;;;;OAMG;IACH,8BAHoB,WAAS,IAAI,GACpB,OAAO,CAAC,mBAAmB,CAAC,gCAAgC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAe/F;IAED;;;;OAIG;IACH,8BAFa,OAAO,CAAC,OAAO,CAAC,CAkB5B;IAED;;;;OAIG;IACH,4BAFa,OAAO,CAAC,OAAO,CAAC,CAe5B;CACJ;uBAhR2C,gBAAgB;kCAAhB,gBAAgB;iDAGb,sBAAsB"}
···
1
+
{"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../lib/backup.js"],"names":[],"mappings":";;;;AAKA;;;GAGG;AAEH;;GAEG;AACH;IACE;;;OAGG;IACH,2BAFwB,MAAM,EAmB7B;IAhBC;;;OAGG;IACH,cAFU,MAAM,CAEQ;IACxB;;;OAGG;IACH,yBAFU,iBAAiB,CAEQ;IAEnC;;;OAGG;IACH,cAFU,MAAM,CAEgB;IAGlC;;;;;;;;;;;;;;;OAeG;IACH,2BARsB,MAAM,YACR,MAAM,aACf,WAAS,IAAI,kBAEC,MAAM,GAAC,IAAI,GAEvB,OAAO,CAAC,mBAAmB,CAAC,gCAAgC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAC,IAAI,CAAC,CAoDpG;IAED;;;;OAIG;IACH,wBAFa,OAAO,CAAC,IAAI,CAAC,CAczB;IAED;;;OAGG;IACH,oBAFa,OAAO,CAAC,IAAI,CAAC,CAgBzB;IAED;;;;;;;OAOG;IACH,6BAJoB,MAAM,eACH,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA4CzB;IAED;;;;;;OAMG;IACH,8BAHoB,WAAS,IAAI,GACpB,OAAO,CAAC,mBAAmB,CAAC,gCAAgC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAe/F;IAED;;;;OAIG;IACH,8BAFa,OAAO,CAAC,OAAO,CAAC,CAwB5B;IAED;;;;OAIG;IACH,4BAFa,OAAO,CAAC,OAAO,CAAC,CAkB5B;CACF;uBA7Q6C,gBAAgB;kCAAhB,gBAAgB;iDAGb,sBAAsB"}
+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
+1
-1
packages/moover/types/main.d.ts.map
+1
-1
packages/moover/types/main.d.ts.map
···
1
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../lib/main.js"],"names":[],"mappings":"yBAAuB,gBAAgB;6BACZ,mBAAmB;8BAClB,aAAa;uBACpB,cAAc;wBACb,cAAc;qCACD,mBAAmB"}
···
1
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../lib/main.js"],"names":[],"mappings":"yBAAyB,gBAAgB;6BACZ,mBAAmB;8BAClB,aAAa;uBACpB,cAAc;wBACb,cAAc;qCACD,mBAAmB"}
+57
-65
packages/moover/types/missingBlobs.d.ts
+57
-65
packages/moover/types/missingBlobs.d.ts
···
2
* Class to help find missing blobs from the did's previous PDS and import them into the current PDS
3
*/
4
export class MissingBlobs {
5
-
/**
6
-
* The user's current PDS agent
7
-
* @type {AtpAgent}
8
-
*/
9
-
currentPdsAgent: AtpAgent
10
-
/**
11
-
* The user's old PDS agent
12
-
* @type {AtpAgent}
13
-
*/
14
-
oldPdsAgent: AtpAgent
15
-
/**
16
-
* the user's did
17
-
* @type {string|null}
18
-
*/
19
-
did: string | null
20
-
/**
21
-
* The user's current PDS url
22
-
* @type {null}
23
-
*/
24
-
currentPdsUrl: any
25
-
/**
26
-
* A list of the missing cids blobs from the old PDS. In this case if a retry upload fails it gets put in this array for the ui
27
-
* @type {string[]}
28
-
*/
29
-
missingBlobs: string[]
30
-
/**
31
-
* Logs the user into the current PDS and gets the account status
32
-
* @param handle {string}
33
-
* @param password {string}
34
-
* @param twoFactorCode {string|null}
35
-
* @returns {Promise<{accountStatus: OutputSchema, missingBlobsCount: number}>}
36
-
*/
37
-
currentAgentLogin(
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
-
}>
68
}
69
-
import { AtpAgent } from '@atproto/api'
70
-
//# sourceMappingURL=missingBlobs.d.ts.map
···
2
* Class to help find missing blobs from the did's previous PDS and import them into the current PDS
3
*/
4
export class MissingBlobs {
5
+
/**
6
+
* The user's current PDS agent
7
+
* @type {AtpAgent}
8
+
*/
9
+
currentPdsAgent: AtpAgent;
10
+
/**
11
+
* The user's old PDS agent
12
+
* @type {AtpAgent}
13
+
*/
14
+
oldPdsAgent: AtpAgent;
15
+
/**
16
+
* the user's did
17
+
* @type {string|null}
18
+
*/
19
+
did: string | null;
20
+
/**
21
+
* The user's current PDS url
22
+
* @type {null}
23
+
*/
24
+
currentPdsUrl: any;
25
+
/**
26
+
* A list of the missing cids blobs from the old PDS. In this case if a retry upload fails it gets put in this array for the ui
27
+
* @type {string[]}
28
+
*/
29
+
missingBlobs: string[];
30
+
/**
31
+
* Logs the user into the current PDS and gets the account status
32
+
* @param handle {string}
33
+
* @param password {string}
34
+
* @param twoFactorCode {string|null}
35
+
* @returns {Promise<{accountStatus: OutputSchema, missingBlobsCount: number}>}
36
+
*/
37
+
currentAgentLogin(handle: string, password: string, twoFactorCode?: string | null): Promise<{
38
+
accountStatus: OutputSchema;
39
+
missingBlobsCount: number;
40
+
}>;
41
+
/**
42
+
* Logs into the old PDS and gets the account status.
43
+
* Does not need a handle
44
+
* since it is assumed the user has already logged in with the current PDS and we are using their did
45
+
* @param password {string}
46
+
* @param twoFactorCode {string|null}
47
+
* @param pdsUrl {string|null} - If you know the url of the old PDS you can pass it in here. If not it will be guessed at from plc ops
48
+
* @returns {Promise<void>}
49
+
*/
50
+
oldAgentLogin(password: string, twoFactorCode?: string | null, pdsUrl?: string | null): Promise<void>;
51
+
/**
52
+
* Gets the missing blobs from the old PDS and uploads them to the current PDS
53
+
* @param statusUpdateHandler {function} - A function to update the status of the migration. This is useful for showing the user the progress of the migration
54
+
* @returns {Promise<{accountStatus: OutputSchema, missingBlobsCount: number}>}
55
+
*/
56
+
migrateMissingBlobs(statusUpdateHandler: Function): Promise<{
57
+
accountStatus: OutputSchema;
58
+
missingBlobsCount: number;
59
+
}>;
60
}
61
+
import { AtpAgent } from '@atproto/api';
62
+
//# sourceMappingURL=missingBlobs.d.ts.map
+1
-1
packages/moover/types/missingBlobs.d.ts.map
+1
-1
packages/moover/types/missingBlobs.d.ts.map
···
1
-
{"version":3,"file":"missingBlobs.d.ts","sourceRoot":"","sources":["../lib/missingBlobs.js"],"names":[],"mappings":"AAIA;;GAEG;AACH;IAGQ;;;OAGG;IACH,iBAFU,QAAQ,CAES;IAC3B;;;OAGG;IACH,aAFU,QAAQ,CAEK;IACvB;;;OAGG;IACH,KAFU,MAAM,GAAC,IAAI,CAEN;IACf;;;OAGG;IACH,mBAAyB;IACzB;;;OAGG;IACH,cAFU,MAAM,EAAE,CAEI;IAI1B;;;;;;OAMG;IACH,0BALkB,MAAM,YACJ,MAAM,kBACD,MAAM,GAAC,IAAI,GACvB,OAAO,CAAC;QAAC,aAAa,EAAE,YAAY,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAC,CAAC,CA2B7E;IAED;;;;;;;;OAQG;IACH,wBALoB,MAAM,kBACD,MAAM,GAAC,IAAI,WAClB,MAAM,GAAC,IAAI,GAChB,OAAO,CAAC,IAAI,CAAC,CA+CzB;IAED;;;;OAIG;IACH,oDAFa,OAAO,CAAC;QAAC,aAAa,EAAE,YAAY,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAC,CAAC,CAyD7E;CAEJ;yBA9LsB,cAAc"}
···
1
+
{"version":3,"file":"missingBlobs.d.ts","sourceRoot":"","sources":["../lib/missingBlobs.js"],"names":[],"mappings":"AAGA;;GAEG;AACH;IAEI;;;OAGG;IACH,iBAFU,QAAQ,CAES;IAC3B;;;OAGG;IACH,aAFU,QAAQ,CAEK;IACvB;;;OAGG;IACH,KAFU,MAAM,GAAC,IAAI,CAEN;IACf;;;OAGG;IACH,mBAAyB;IACzB;;;OAGG;IACH,cAFU,MAAM,EAAE,CAEI;IAGxB;;;;;;OAMG;IACH,0BALkB,MAAM,YACJ,MAAM,kBACD,MAAM,GAAC,IAAI,GACvB,OAAO,CAAC;QAAC,aAAa,EAAE,YAAY,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAC,CAAC,CA2B7E;IAED;;;;;;;;OAQG;IACH,wBALoB,MAAM,kBACD,MAAM,GAAC,IAAI,WAClB,MAAM,GAAC,IAAI,GAChB,OAAO,CAAC,IAAI,CAAC,CA+CzB;IAED;;;;OAIG;IACH,oDAFa,OAAO,CAAC;QAAC,aAAa,EAAE,YAAY,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAA;KAAC,CAAC,CAyD7E;CACF;yBA1LwB,cAAc"}
+78
-79
packages/moover/types/pdsmoover.d.ts
+78
-79
packages/moover/types/pdsmoover.d.ts
···
3
* On pdsmoover.com this is the logic for the MOOver
4
*/
5
export class Migrator {
6
-
/** @type {AtpAgent} */
7
-
oldAgent: AtpAgent
8
-
/** @type {AtpAgent} */
9
-
newAgent: AtpAgent
10
-
/** @type {[string]} */
11
-
missingBlobs: [string]
12
-
/** @type {boolean} */
13
-
createNewAccount: boolean
14
-
/** @type {boolean} */
15
-
migrateRepo: boolean
16
-
/** @type {boolean} */
17
-
migrateBlobs: boolean
18
-
/** @type {boolean} */
19
-
migrateMissingBlobs: boolean
20
-
/** @type {boolean} */
21
-
migratePrefs: boolean
22
-
/** @type {boolean} */
23
-
migratePlcRecord: boolean
24
-
/**
25
-
* This migrator is pretty cut and dry and makes a few assumptions
26
-
* 1. You are using the same password between each account
27
-
* 2. If this command fails for something like oauth 2fa code it throws an error and expects the same values when ran again.
28
-
* 3. You can control which "actions" happen by setting the class variables to false.
29
-
* 4. Each instance of the class is assumed to be for a single migration
30
-
* @param {string} oldHandle - The handle you use on your old pds, something like alice.bsky.social
31
-
* @param {string} password - Your password for your current login. Has to be your real password, no app password. When setting up a new account we reuse it as well for that account
32
-
* @param {string} newPdsUrl - The new URL for your pds. Like https://coolnewpds.com
33
-
* @param {string} newEmail - The email you want to use on the new pds (can be the same as the previous one as long as it's not already being used on the new pds)
34
-
* @param {string} newHandle - The new handle you want, like alice.bsky.social, or if you already have a domain name set as a handle can use it myname.com.
35
-
* @param {string|null} inviteCode - The invite code you got from the PDS you are migrating to. If null does not include one
36
-
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI. Like (status) => console.log(status)
37
-
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
38
-
* @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>
83
}
84
-
import { AtpAgent } from '@atproto/api'
85
-
//# sourceMappingURL=pdsmoover.d.ts.map
···
3
* On pdsmoover.com this is the logic for the MOOver
4
*/
5
export class Migrator {
6
+
/** @type {AtpAgent} */
7
+
oldAgent: AtpAgent;
8
+
/** @type {AtpAgent} */
9
+
newAgent: AtpAgent;
10
+
/** @type {[string]} */
11
+
missingBlobs: [string];
12
+
/** @type {boolean} */
13
+
createNewAccount: boolean;
14
+
/** @type {boolean} */
15
+
migrateRepo: boolean;
16
+
/** @type {boolean} */
17
+
migrateBlobs: boolean;
18
+
/** @type {boolean} */
19
+
migrateMissingBlobs: boolean;
20
+
/** @type {boolean} */
21
+
migratePrefs: boolean;
22
+
/** @type {boolean} */
23
+
migratePlcRecord: boolean;
24
+
/**
25
+
* How many blobs have been uploaded to the new PDS in the current step
26
+
@type {number} */
27
+
uploadedBlobsCount: number;
28
+
/**
29
+
* Uploads blobs to the new PDS
30
+
* @param {AtpAgent} oldAgent
31
+
* @param {AtpAgent} newAgent
32
+
* @param {string} usersDid
33
+
* @param {[string]} cids
34
+
* @param {number} totalBlobs
35
+
* @param {function|null} statusUpdateHandler
36
+
*/
37
+
uploadBlobs(oldAgent: AtpAgent, newAgent: AtpAgent, usersDid: string, cids: [string], totalBlobs: number, statusUpdateHandler: Function | null): Promise<void>;
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
+
migrate(oldHandle: string, password: string, newPdsUrl: string, newEmail: string, newHandle: string, inviteCode: string | null, statusUpdateHandler?: Function | null, twoFactorCode?: string | null, verificationCode?: any): Promise<void>;
55
+
/**
56
+
* Sign and submits the PLC operation to officially migrate the account
57
+
* @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
58
+
* @param additionalRotationKeysToAdd {string[]} - additional rotation keys to add in addition to the ones provided by the new PDS.
59
+
* @returns {Promise<void>}
60
+
*/
61
+
signPlcOperation(token: string, additionalRotationKeysToAdd?: string[]): Promise<void>;
62
+
/**
63
+
* Using this method assumes the Migrator class was constructed new and this was called.
64
+
* Find the user's previous PDS from the PLC op logs,
65
+
* logs in and deactivates their old account if it was found still active.
66
+
*
67
+
* @param oldHandle {string}
68
+
* @param oldPassword {string}
69
+
* @param {function|null} statusUpdateHandler - a function that takes a string used to update the UI.
70
+
* Like (status) => console.log(status)
71
+
* @param {string|null} twoFactorCode - Optional, but needed if it fails with 2fa required
72
+
* @returns {Promise<void>}
73
+
*/
74
+
deactivateOldAccount(oldHandle: string, oldPassword: string, statusUpdateHandler?: Function | null, twoFactorCode?: string | null): Promise<void>;
75
+
/**
76
+
* Signs the logged-in user in this.newAgent for backups with PDS MOOver. This is usually called after migrate and signPlcOperation are successful
77
+
*
78
+
* @param {string} didWeb
79
+
* @returns {Promise<void>}
80
+
*/
81
+
signUpForBackupsFromMigration(didWeb?: string): Promise<void>;
82
}
83
+
import { AtpAgent } from '@atproto/api';
84
+
//# sourceMappingURL=pdsmoover.d.ts.map
+1
-1
packages/moover/types/pdsmoover.d.ts.map
+1
-1
packages/moover/types/pdsmoover.d.ts.map
···
1
-
{"version":3,"file":"pdsmoover.d.ts","sourceRoot":"","sources":["../lib/pdsmoover.js"],"names":[],"mappings":"AAUA;;;GAGG;AACH;IAEQ,uBAAuB;IACvB,UADW,QAAQ,CACC;IACpB,uBAAuB;IACvB,UADW,QAAQ,CACC;IACpB,uBAAuB;IACvB,cADW,CAAC,MAAM,CAAC,CACG;IAEtB,sBAAsB;IACtB,kBADW,OAAO,CACU;IAC5B,sBAAsB;IACtB,aADW,OAAO,CACK;IACvB,sBAAsB;IACtB,cADW,OAAO,CACM;IACxB,sBAAsB;IACtB,qBADW,OAAO,CACa;IAC/B,sBAAsB;IACtB,cADW,OAAO,CACM;IACxB,sBAAsB;IACtB,kBADW,OAAO,CACU;IAGhC;;;;;;;;;;;;;;;OAeG;IACH,mBAVW,MAAM,YACN,MAAM,aACN,MAAM,YACN,MAAM,aACN,MAAM,cACN,MAAM,GAAC,IAAI,wBACX,WAAS,IAAI,kBACb,MAAM,GAAC,IAAI,yCA2LrB;IAED;;;;;OAKG;IACH,wBAJW,MAAM,gCACsB,MAAM,EAAE,GAClC,OAAO,CAAC,IAAI,CAAC,CA4BzB;IAED;;;;;;;;;;;OAWG;IACH,gCAPqB,MAAM,eACJ,MAAM,wBAClB,WAAS,IAAI,kBAEb,MAAM,GAAC,IAAI,GACT,OAAO,CAAC,IAAI,CAAC,CAiEzB;IAED;;;;;OAKG;IACH,uCAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAkCzB;CACJ;yBApYsB,cAAc"}
···
1
+
{"version":3,"file":"pdsmoover.d.ts","sourceRoot":"","sources":["../lib/pdsmoover.js"],"names":[],"mappings":"AASA;;;GAGG;AACH;IAEI,uBAAuB;IACvB,UADW,QAAQ,CACC;IACpB,uBAAuB;IACvB,UADW,QAAQ,CACC;IACpB,uBAAuB;IACvB,cADW,CAAC,MAAM,CAAC,CACG;IAEtB,sBAAsB;IACtB,kBADW,OAAO,CACU;IAC5B,sBAAsB;IACtB,aADW,OAAO,CACK;IACvB,sBAAsB;IACtB,cADW,OAAO,CACM;IACxB,sBAAsB;IACtB,qBADW,OAAO,CACa;IAC/B,sBAAsB;IACtB,cADW,OAAO,CACM;IACxB,sBAAsB;IACtB,kBADW,OAAO,CACU;IAC5B;;sBAEkB;IAClB,oBADQ,MAAM,CACa;IAG7B;;;;;;;;OAQG;IACH,sBAPW,QAAQ,YACR,QAAQ,YACR,MAAM,QACN,CAAC,MAAM,CAAC,cACR,MAAM,uBACN,WAAS,IAAI,iBAuBvB;IAED;;;;;;;;;;;;;;;OAeG;IACH,mBAVW,MAAM,YACN,MAAM,aACN,MAAM,YACN,MAAM,aACN,MAAM,cACN,MAAM,GAAC,IAAI,wBACX,WAAS,IAAI,kBACb,MAAM,GAAC,IAAI,yCA+MrB;IAED;;;;;OAKG;IACH,wBAJW,MAAM,gCACsB,MAAM,EAAE,GAClC,OAAO,CAAC,IAAI,CAAC,CA2BzB;IAED;;;;;;;;;;;OAWG;IACH,gCAPqB,MAAM,eACJ,MAAM,wBAClB,WAAS,IAAI,kBAEb,MAAM,GAAC,IAAI,GACT,OAAO,CAAC,IAAI,CAAC,CA+EzB;IAED;;;;;OAKG;IACH,uCAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAkCzB;CACF;yBAxcwB,cAAc"}
+98
-109
packages/moover/types/plc-ops.d.ts
+98
-109
packages/moover/types/plc-ops.d.ts
···
1
/**
2
* JSDoc type-only import to avoid runtime import errors in the browser.
3
*/
4
-
export type defs = typeof defs
5
/**
6
* JSDoc type-only import to avoid runtime import errors in the browser.
7
*/
8
-
export type normalizeOp = any
9
/**
10
* JSDoc type-only import to avoid runtime import errors in the browser.
11
*/
12
-
export type Operation = import('@atcute/did-plc').Operation
13
/**
14
* JSDoc type-only import to avoid runtime import errors in the browser.
15
*/
16
-
export type CompatibleOperation = import('@atcute/did-plc').CompatibleOperation
17
/**
18
* JSDoc type-only import to avoid runtime import errors in the browser.
19
*/
20
-
export type IndexedEntryLog = import('@atcute/did-plc').IndexedEntryLog
21
/**
22
* JSDoc type-only import to avoid runtime import errors in the browser.
23
*/
24
-
export type IndexedEntry = import('@atcute/did-plc').IndexedEntry
25
/**
26
* Class to help with various PLC operations
27
*/
28
export class PlcOps {
29
-
/**
30
-
*
31
-
* @param plcDirectoryUrl {string} - The url of the plc directory, defaults to https://plc.directory
32
-
*/
33
-
constructor(plcDirectoryUrl?: string)
34
-
/**
35
-
* The url of the plc directory
36
-
* @type {string}
37
-
*/
38
-
plcDirectoryUrl: string
39
-
/**
40
-
* Gets the current rotation keys for a user via their last PlC operation
41
-
* @param did
42
-
* @returns {Promise<string[]>}
43
-
*/
44
-
getCurrentRotationKeysForUser(did: any): Promise<string[]>
45
-
/**
46
-
* Gets the last PlC operation for a user from the plc directory
47
-
* @param did
48
-
* @returns {Promise<{lastOperation: Operation, base: any}>}
49
-
*/
50
-
getLastPlcOpFromPlc(did: any): Promise<{
51
-
lastOperation: Operation
52
-
base: any
53
-
}>
54
-
/**
55
-
*
56
-
* @param logs {IndexedEntryLog}
57
-
* @returns {{lastOperation: Operation, base: IndexedEntry}}
58
-
*/
59
-
getLastPlcOp(logs: IndexedEntryLog): {
60
-
lastOperation: Operation
61
-
base: IndexedEntry
62
-
}
63
-
/**
64
-
* Gets the plc audit logs for a user from the plc directory
65
-
* @param did
66
-
* @returns {Promise<IndexedEntryLog>}
67
-
*/
68
-
getPlcAuditLogs(did: any): Promise<IndexedEntryLog>
69
-
/**
70
-
* Creates a new secp256k1 key that can be used for either rotation or verification key
71
-
* @returns {Promise<{privateKey: string, publicKey: `did:key:${string}`}>}
72
-
*/
73
-
createANewSecp256k1(): Promise<{
74
-
privateKey: string
75
-
publicKey: `did:key:${string}`
76
-
}>
77
-
/**
78
-
* Signs a new operation with the provided signing key, and information and submits it to the plc directory
79
-
* @param did {string} - The user's did
80
-
* @param signingRotationKey { P256PrivateKey|Secp256k1PrivateKey} - The keypair to sign the op with
81
-
* @param alsoKnownAs {string[]}
82
-
* @param rotationKeys {string[]}
83
-
* @param pds {string}
84
-
* @param verificationKey {string} - The public verification key
85
-
* @param prev {string} - The previous valid operation's cid.
86
-
* @returns {Promise<void>}
87
-
*/
88
-
signAndPublishNewOp(
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>
128
}
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
···
1
/**
2
* JSDoc type-only import to avoid runtime import errors in the browser.
3
*/
4
+
export type defs = typeof defs;
5
/**
6
* JSDoc type-only import to avoid runtime import errors in the browser.
7
*/
8
+
export type normalizeOp = any;
9
/**
10
* JSDoc type-only import to avoid runtime import errors in the browser.
11
*/
12
+
export type Operation = import("@atcute/did-plc").Operation;
13
/**
14
* JSDoc type-only import to avoid runtime import errors in the browser.
15
*/
16
+
export type CompatibleOperation = import("@atcute/did-plc").CompatibleOperation;
17
/**
18
* JSDoc type-only import to avoid runtime import errors in the browser.
19
*/
20
+
export type IndexedEntryLog = import("@atcute/did-plc").IndexedEntryLog;
21
/**
22
* JSDoc type-only import to avoid runtime import errors in the browser.
23
*/
24
+
export type IndexedEntry = import("@atcute/did-plc").IndexedEntry;
25
/**
26
* Class to help with various PLC operations
27
*/
28
export class PlcOps {
29
+
/**
30
+
*
31
+
* @param plcDirectoryUrl {string} - The url of the plc directory, defaults to https://plc.directory
32
+
*/
33
+
constructor(plcDirectoryUrl?: string);
34
+
/**
35
+
* The url of the plc directory
36
+
* @type {string}
37
+
*/
38
+
plcDirectoryUrl: string;
39
+
/**
40
+
* Gets the current rotation keys for a user via their last PlC operation
41
+
* @param did
42
+
* @returns {Promise<string[]>}
43
+
*/
44
+
getCurrentRotationKeysForUser(did: any): Promise<string[]>;
45
+
/**
46
+
* Gets the last PlC operation for a user from the plc directory
47
+
* @param did
48
+
* @returns {Promise<{lastOperation: Operation, base: any}>}
49
+
*/
50
+
getLastPlcOpFromPlc(did: any): Promise<{
51
+
lastOperation: Operation;
52
+
base: any;
53
+
}>;
54
+
/**
55
+
*
56
+
* @param logs {IndexedEntryLog}
57
+
* @returns {{lastOperation: Operation, base: IndexedEntry}}
58
+
*/
59
+
getLastPlcOp(logs: IndexedEntryLog): {
60
+
lastOperation: Operation;
61
+
base: IndexedEntry;
62
+
};
63
+
/**
64
+
* Gets the plc audit logs for a user from the plc directory
65
+
* @param did
66
+
* @returns {Promise<IndexedEntryLog>}
67
+
*/
68
+
getPlcAuditLogs(did: any): Promise<IndexedEntryLog>;
69
+
/**
70
+
* Creates a new secp256k1 key that can be used for either rotation or verification key
71
+
* @returns {Promise<{privateKey: string, publicKey: `did:key:${string}`}>}
72
+
*/
73
+
createANewSecp256k1(): Promise<{
74
+
privateKey: string;
75
+
publicKey: `did:key:${string}`;
76
+
}>;
77
+
/**
78
+
* Signs a new operation with the provided signing key, and information and submits it to the plc directory
79
+
* @param did {string} - The user's did
80
+
* @param signingRotationKey { P256PrivateKey|Secp256k1PrivateKey} - The keypair to sign the op with
81
+
* @param alsoKnownAs {string[]}
82
+
* @param rotationKeys {string[]}
83
+
* @param pds {string}
84
+
* @param verificationKey {string} - The public verification key
85
+
* @param prev {string} - The previous valid operation's cid.
86
+
* @returns {Promise<void>}
87
+
*/
88
+
signAndPublishNewOp(did: string, signingRotationKey: P256PrivateKey | Secp256k1PrivateKey, alsoKnownAs: string[], rotationKeys: string[], pds: string, verificationKey: string, prev: string): Promise<void>;
89
+
/**
90
+
* Takes a multi or hex based private key and returns a keypair
91
+
* @param privateKeyString {string}
92
+
* @param type {string} - secp256k1 or p256, needed if the private key is hex based, can be assumed if it's a multikey
93
+
* @returns {Promise<{type: string, didPublicKey: `did:key:${string}`, keypair: P256PrivateKey|Secp256k1PrivateKey}>}
94
+
*/
95
+
getKeyPair(privateKeyString: string, type?: string): Promise<{
96
+
type: string;
97
+
didPublicKey: `did:key:${string}`;
98
+
keypair: P256PrivateKey | Secp256k1PrivateKey;
99
+
}>;
100
+
/**
101
+
* Submits a new operation to the plc directory
102
+
* @param did {string} - The user's did
103
+
* @param operation
104
+
* @returns {Promise<void>}
105
+
*/
106
+
pushPlcOperation(did: string, operation: any): Promise<void>;
107
+
/**
108
+
* Creates a new service auth token for a user. This is what is used to create a new account on a PDS for your did
109
+
*
110
+
* @param iss The user's did
111
+
* @param aud The did:web, if it's a PDS it's usually from /xrpc/com.atproto.server.describeServer
112
+
* @param keypair The keypair to sign with only supporting ES256K atm
113
+
* @param lxm The lxm which is usually com.atproto.server.createAccount for creating a new account
114
+
* @returns {Promise<string>}
115
+
*/
116
+
createANewServiceAuthToken(iss: any, aud: any, keypair: any, lxm: any): Promise<string>;
117
}
118
+
import { defs } from '@atcute/did-plc';
119
+
import { P256PrivateKey } from '@atcute/crypto';
120
+
import { Secp256k1PrivateKey } from '@atcute/crypto';
121
+
//# sourceMappingURL=plc-ops.d.ts.map
+1
-1
packages/moover/types/plc-ops.d.ts.map
+1
-1
packages/moover/types/plc-ops.d.ts.map
···
1
-
{"version":3,"file":"plc-ops.d.ts","sourceRoot":"","sources":["../lib/plc-ops.js"],"names":[],"mappings":";;;;;;;;;;;wBAIa,OAAO,iBAAiB,EAAE,SAAS;;;;kCACnC,OAAO,iBAAiB,EAAE,mBAAmB;;;;8BAC7C,OAAO,iBAAiB,EAAE,eAAe;;;;2BACzC,OAAO,iBAAiB,EAAE,YAAY;AAgBnD;;GAEG;AACH;IACI;;;OAGG;IACH,8BAF2B,MAAM,EAQhC;IALG;;;OAGG;IACH,iBAFU,MAAM,CAEsB;IAG1C;;;;OAIG;IACH,yCAFa,OAAO,CAAC,MAAM,EAAE,CAAC,CAM7B;IAED;;;;OAIG;IACH,+BAFa,OAAO,CAAC;QAAC,aAAa,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAC,CAAC,CAK1D;IAED;;;;OAIG;IACH,mBAHgB,eAAe,GAClB;QAAC,aAAa,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,YAAY,CAAA;KAAC,CAK1D;IAGD;;;;OAIG;IACH,2BAFa,OAAO,CAAC,eAAe,CAAC,CAUpC;IAED;;;OAGG;IACH,uBAFa,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,WAAW,MAAM,EAAE,CAAA;KAAC,CAAC,CAUzE;IAGD;;;;;;;;;;OAUG;IACH,yBATe,MAAM,sBACU,cAAc,GAAC,mBAAmB,eAC1C,MAAM,EAAE,gBACP,MAAM,EAAE,OACjB,MAAM,mBACM,MAAM,QACjB,MAAM,GACT,OAAO,CAAC,IAAI,CAAC,CAuCzB;IAED;;;;;OAKG;IACH,6BAJ4B,MAAM,SAClB,MAAM,GACT,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,WAAW,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,cAAc,GAAC,mBAAmB,CAAA;KAAC,CAAC,CAkDnH;IAED;;;;;OAKG;IACH,sBAJe,MAAM,mBAER,OAAO,CAAC,IAAI,CAAC,CAwBzB;IAGD;;;;;;;;OAQG;IACH,wEAFa,OAAO,CAAC,MAAM,CAAC,CAwC3B;CAGJ;qBAtR+B,iBAAiB;+BACsD,gBAAgB;oCAAhB,gBAAgB"}
···
1
+
{"version":3,"file":"plc-ops.d.ts","sourceRoot":"","sources":["../lib/plc-ops.js"],"names":[],"mappings":";;;;;;;;;;;wBAIa,OAAO,iBAAiB,EAAE,SAAS;;;;kCACnC,OAAO,iBAAiB,EAAE,mBAAmB;;;;8BAC7C,OAAO,iBAAiB,EAAE,eAAe;;;;2BACzC,OAAO,iBAAiB,EAAE,YAAY;AAoBnD;;GAEG;AACH;IACE;;;OAGG;IACH,8BAF2B,MAAM,EAQhC;IALC;;;OAGG;IACH,iBAFU,MAAM,CAEsB;IAGxC;;;;OAIG;IACH,yCAFa,OAAO,CAAC,MAAM,EAAE,CAAC,CAM7B;IAED;;;;OAIG;IACH,+BAFa,OAAO,CAAC;QAAC,aAAa,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,GAAG,CAAA;KAAC,CAAC,CAK1D;IAED;;;;OAIG;IACH,mBAHgB,eAAe,GAClB;QAAC,aAAa,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,YAAY,CAAA;KAAC,CAK1D;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAC,eAAe,CAAC,CAUpC;IAED;;;OAGG;IACH,uBAFa,OAAO,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,WAAW,MAAM,EAAE,CAAA;KAAC,CAAC,CAUzE;IAED;;;;;;;;;;OAUG;IACH,yBATe,MAAM,sBACU,cAAc,GAAC,mBAAmB,eAC1C,MAAM,EAAE,gBACP,MAAM,EAAE,OACjB,MAAM,mBACM,MAAM,QACjB,MAAM,GACT,OAAO,CAAC,IAAI,CAAC,CA8CzB;IAED;;;;;OAKG;IACH,6BAJ4B,MAAM,SAClB,MAAM,GACT,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,WAAW,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,cAAc,GAAC,mBAAmB,CAAA;KAAC,CAAC,CAiDnH;IAED;;;;;OAKG;IACH,sBAJe,MAAM,mBAER,OAAO,CAAC,IAAI,CAAC,CAwBzB;IAED;;;;;;;;OAQG;IACH,wEAFa,OAAO,CAAC,MAAM,CAAC,CAuC3B;CACF;qBA1RiC,iBAAiB;+BAM5C,gBAAgB;oCAAhB,gBAAgB"}
+77
-92
packages/moover/types/restore.d.ts
+77
-92
packages/moover/types/restore.d.ts
···
1
-
export type Operation = import('@atcute/did-plc').Operation
2
export class Restore {
3
-
/**
4
-
*
5
-
* @param pdsMooverInstance {string} - The url of the pds moover instance to restore from. Defaults to https://pdsmover.com
6
-
*/
7
-
constructor(pdsMooverInstance?: string)
8
-
/**
9
-
* If you want to use a different plc directory create your own instance of the plc ops class and pass it in here
10
-
* @type {PlcOps} */
11
-
plcOps: PlcOps
12
-
/**
13
-
* This is the base url for the pds moover instance used to restore the files from a backup.
14
-
* @type {string}
15
-
*/
16
-
pdsMooverInstance: string
17
-
/**
18
-
* To keep it simple, only uses secp256k for the temp verification key that is used to create the new account on the new PDS
19
-
* and is temporarily assigned to the user's account on PLC
20
-
* @type {null|Secp256k1PrivateKeyExportable}
21
-
*/
22
-
tempVerificationKeypair: null | Secp256k1PrivateKeyExportable
23
-
/** @type {AtpAgent} */
24
-
atpAgent: AtpAgent
25
-
/**
26
-
* The keypair that is used to sign the plc operation
27
-
* @type {null|{type: string, didPublicKey: `did:key:${string}`, keypair: P256PrivateKey|Secp256k1PrivateKey}}
28
-
*/
29
-
recoveryRotationKeyPair: null | {
30
-
type: string
31
-
didPublicKey: `did:key:${string}`
32
-
keypair: P256PrivateKey | Secp256k1PrivateKey
33
-
}
34
-
/**
35
-
* If this is true we are just restoring the repo and blobs. Ideally for rerunning a restore process after account recovery
36
-
* @type {boolean}
37
-
*/
38
-
RestoreFromBackup: boolean
39
-
/**
40
-
* If set to true then it will do the account recovery. Writes a temp key to the did doc,
41
-
* create a new account on the new pds, and then submit a new plc op for the pds to have control (finishes the migration, can always restore the backup later)
42
-
* @type {boolean}
43
-
*/
44
-
AccountRecovery: boolean
45
-
/**
46
-
* Recovers an account with the users rotation key and restores the repo from a PDS MOOver backup
47
-
* This method can fail, and the account was still recovered, it's best to check the PLC logs to see where an account stands before reruns
48
-
* @param rotationKey {string} - The users private rotation key, can be a multi key or hex key
49
-
* @param rotationKeyType {string} - The type of the key, secp256k1 or p256. Required if the key is in hex format, defaults to secp256k1
50
-
* @param currentHandleOrDid {string} - The users current handle or did, if they don't have a DNS record it will have to be their did for success
51
-
* @param newPDS {string} - The new PDS url, like https://coolnewpds.com
52
-
* @param newHandle {string} - Can be the users DNS handle if it is already setup with their did, if not it's bob.mypds.com
53
-
* @param newPassword {string} - The new password for the new account
54
-
* @param newEmail {string} - The new email for the new account
55
-
* @param inviteCode {string|null} - The invite code for the new PDS if it requires one
56
-
* @param cidToRestoreTo {string|null} - The cid of the plc op to restore to, used mostly to revert a fraudulent plc op. Want to give it the last valid operations cid
57
-
* @param onStatus {function|null} - A function that takes a string used to update the UI. Like (status) => console.log(status)
58
-
* @returns {Promise<void>} If there is a failure during restoring the back up (after the status Success! Restoring your repo...) then your account is most likely
59
-
* recovered and future runs need to have the RestoreFromBackup flag set to true and AccountRecovery set to false.
60
-
*/
61
-
recover(
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>
88
}
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
···
1
+
export type Operation = import("@atcute/did-plc").Operation;
2
export class Restore {
3
+
/**
4
+
*
5
+
* @param pdsMooverInstance {string} - The url of the pds moover instance to restore from. Defaults to https://pdsmover.com
6
+
*/
7
+
constructor(pdsMooverInstance?: string);
8
+
/**
9
+
* If you want to use a different plc directory create your own instance of the plc ops class and pass it in here
10
+
* @type {PlcOps} */
11
+
plcOps: PlcOps;
12
+
/**
13
+
* This is the base url for the pds moover instance used to restore the files from a backup.
14
+
* @type {string}
15
+
*/
16
+
pdsMooverInstance: string;
17
+
/**
18
+
* To keep it simple, only uses secp256k for the temp verification key that is used to create the new account on the new PDS
19
+
* and is temporarily assigned to the user's account on PLC
20
+
* @type {null|Secp256k1PrivateKeyExportable}
21
+
*/
22
+
tempVerificationKeypair: null | Secp256k1PrivateKeyExportable;
23
+
/** @type {AtpAgent} */
24
+
atpAgent: AtpAgent;
25
+
/**
26
+
* The keypair that is used to sign the plc operation
27
+
* @type {null|{type: string, didPublicKey: `did:key:${string}`, keypair: P256PrivateKey|Secp256k1PrivateKey}}
28
+
*/
29
+
recoveryRotationKeyPair: null | {
30
+
type: string;
31
+
didPublicKey: `did:key:${string}`;
32
+
keypair: P256PrivateKey | Secp256k1PrivateKey;
33
+
};
34
+
/**
35
+
* If this is true we are just restoring the repo and blobs. Ideally for rerunning a restore process after account recovery
36
+
* @type {boolean}
37
+
*/
38
+
RestoreFromBackup: boolean;
39
+
/**
40
+
* If set to true then it will do the account recovery. Writes a temp key to the did doc,
41
+
* create a new account on the new pds, and then submit a new plc op for the pds to have control (finishes the migration, can always restore the backup later)
42
+
* @type {boolean}
43
+
*/
44
+
AccountRecovery: boolean;
45
+
/**
46
+
* Recovers an account with the users rotation key and restores the repo from a PDS MOOver backup
47
+
* This method can fail, and the account was still recovered, it's best to check the PLC logs to see where an account stands before reruns
48
+
* @param rotationKey {string} - The users private rotation key, can be a multi key or hex key
49
+
* @param rotationKeyType {string} - The type of the key, secp256k1 or p256. Required if the key is in hex format, defaults to secp256k1
50
+
* @param currentHandleOrDid {string} - The users current handle or did, if they don't have a DNS record it will have to be their did for success
51
+
* @param newPDS {string} - The new PDS url, like https://coolnewpds.com
52
+
* @param newHandle {string} - Can be the users DNS handle if it is already setup with their did, if not it's bob.mypds.com
53
+
* @param newPassword {string} - The new password for the new account
54
+
* @param newEmail {string} - The new email for the new account
55
+
* @param inviteCode {string|null} - The invite code for the new PDS if it requires one
56
+
* @param cidToRestoreTo {string|null} - The cid of the plc op to restore to, used mostly to revert a fraudulent plc op. Want to give it the last valid operations cid
57
+
* @param onStatus {function|null} - A function that takes a string used to update the UI. Like (status) => console.log(status)
58
+
* @returns {Promise<void>} If there is a failure during restoring the back up (after the status Success! Restoring your repo...) then your account is most likely
59
+
* recovered and future runs need to have the RestoreFromBackup flag set to true and AccountRecovery set to false.
60
+
*/
61
+
recover(rotationKey: string, rotationKeyType: string, currentHandleOrDid: string, newPDS: string, newHandle: string, newPassword: string, newEmail: string, inviteCode: string | null, cidToRestoreTo?: string | null, onStatus?: Function | null): Promise<void>;
62
+
/**
63
+
* This method signs the plc operation over to the new PDS and activates the account
64
+
* Assumes you have already created a new account during the recovery process and logged in
65
+
* Uses the recommended did doc from the PDS as a base and adds the users rotation key to the rotation keys array
66
+
*
67
+
* @param usersDid
68
+
* @param additionalRotationKeysToAdd
69
+
* @param prevCid
70
+
* @returns {Promise<void>}
71
+
*/
72
+
signRestorePlcOperation(usersDid: any, additionalRotationKeysToAdd: any[], prevCid: any): Promise<void>;
73
}
74
+
import { PlcOps } from './plc-ops.js';
75
+
import { Secp256k1PrivateKeyExportable } from '@atcute/crypto';
76
+
import { AtpAgent } from '@atproto/api';
77
+
import { P256PrivateKey } from '@atcute/crypto';
78
+
import { Secp256k1PrivateKey } from '@atcute/crypto';
79
+
//# sourceMappingURL=restore.d.ts.map
+1
-1
packages/moover/types/restore.d.ts.map
+1
-1
packages/moover/types/restore.d.ts.map
···
1
-
{"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../lib/restore.js"],"names":[],"mappings":"wBACa,OAAO,iBAAiB,EAAE,SAAS;AAWhD;IAEI;;;OAGG;IACH,gCAF6B,MAAM,EA0ClC;IAvCG;;wBAEoB;IACpB,QADU,MAAM,CACU;IAE1B;;;OAGG;IACH,mBAFU,MAAM,CAE0B;IAE1C;;;;OAIG;IACH,yBAFU,IAAI,GAAC,6BAA6B,CAET;IAEnC,uBAAuB;IACvB,UADW,QAAQ,CACC;IAEpB;;;OAGG;IACH,yBAFU,IAAI,GAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,WAAW,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,cAAc,GAAC,mBAAmB,CAAA;KAAC,CAE1E;IAEnC;;;OAGG;IACH,mBAFU,OAAO,CAEY;IAE7B;;;;OAIG;IACH,iBAFU,OAAO,CAEU;IAG/B;;;;;;;;;;;;;;;OAeG;IACH,qBAbuB,MAAM,mBACF,MAAM,sBACH,MAAM,UAClB,MAAM,aACH,MAAM,eACJ,MAAM,YACT,MAAM,cACJ,MAAM,GAAC,IAAI,mBACP,MAAM,GAAC,IAAI,aACjB,WAAS,IAAI,GACpB,OAAO,CAAC,IAAI,CAAC,CA4MzB;IAGD;;;;;;;;;OASG;IACH,0FAFa,OAAO,CAAC,IAAI,CAAC,CAuCzB;CACJ;uBAnUoB,cAAc;8CAGS,gBAAgB;yBADrC,cAAc;+BAJa,gBAAgB;oCAAhB,gBAAgB"}
···
1
+
{"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../lib/restore.js"],"names":[],"mappings":"wBACa,OAAO,iBAAiB,EAAE,SAAS;AAWhD;IACE;;;OAGG;IACH,gCAF6B,MAAM,EA0ClC;IAvCC;;wBAEoB;IACpB,QADU,MAAM,CACU;IAE1B;;;OAGG;IACH,mBAFU,MAAM,CAE0B;IAE1C;;;;OAIG;IACH,yBAFU,IAAI,GAAC,6BAA6B,CAET;IAEnC,uBAAuB;IACvB,UADW,QAAQ,CACC;IAEpB;;;OAGG;IACH,yBAFU,IAAI,GAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,WAAW,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,cAAc,GAAC,mBAAmB,CAAA;KAAC,CAE1E;IAEnC;;;OAGG;IACH,mBAFU,OAAO,CAEY;IAE7B;;;;OAIG;IACH,iBAFU,OAAO,CAEU;IAG7B;;;;;;;;;;;;;;;OAeG;IACH,qBAbuB,MAAM,mBACF,MAAM,sBACH,MAAM,UAClB,MAAM,aACH,MAAM,eACJ,MAAM,YACT,MAAM,cACJ,MAAM,GAAC,IAAI,mBACP,MAAM,GAAC,IAAI,aACjB,WAAS,IAAI,GACpB,OAAO,CAAC,IAAI,CAAC,CAiNzB;IAED;;;;;;;;;OASG;IACH,0FAFa,OAAO,CAAC,IAAI,CAAC,CAsCzB;CACF;uBArUsB,cAAc;8CAGS,gBAAgB;yBADrC,cAAc;+BAJa,gBAAgB;oCAAhB,gBAAgB"}
+2
-1
web-ui/package.json
+2
-1
web-ui/package.json
···
17
"@atcute/client": "^4.0.5",
18
"@atcute/lexicons": "^1.2.2",
19
"@pds-moover/lexicons": "^1.0.1",
20
-
"@pds-moover/moover": "^1.0.6"
21
},
22
"devDependencies": {
23
"@eslint/compat": "^1.4.0",
···
30
"eslint": "^9.36.0",
31
"eslint-plugin-svelte": "^3.12.4",
32
"globals": "^16.4.0",
33
"svelte": "^5.39.5",
34
"svelte-check": "^4.3.2",
35
"typescript": "^5.9.2",
···
17
"@atcute/client": "^4.0.5",
18
"@atcute/lexicons": "^1.2.2",
19
"@pds-moover/lexicons": "^1.0.1",
20
+
"@pds-moover/moover": "^1.0.7"
21
},
22
"devDependencies": {
23
"@eslint/compat": "^1.4.0",
···
30
"eslint": "^9.36.0",
31
"eslint-plugin-svelte": "^3.12.4",
32
"globals": "^16.4.0",
33
+
"oxlint": "^1.48.0",
34
"svelte": "^5.39.5",
35
"svelte-check": "^4.3.2",
36
"typescript": "^5.9.2",
+211
-5
web-ui/pnpm-lock.yaml
+211
-5
web-ui/pnpm-lock.yaml
···
21
specifier: ^1.0.1
22
version: 1.0.1
23
'@pds-moover/moover':
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
devDependencies:
27
'@eslint/compat':
28
specifier: ^1.4.0
···
54
globals:
55
specifier: ^16.4.0
56
version: 16.5.0
57
svelte:
58
specifier: ^5.39.5
59
version: 5.43.2
···
389
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
390
engines: {node: '>= 8'}
391
392
'@pds-moover/lexicons@1.0.1':
393
resolution: {integrity: sha512-fv5b/DtHM7FEo/JklyF9gdK0ainlb6mWjWrBe6cmSAeg9G/4O2jBlQUOqfOAICY9gOcrCpkOrk9PHgGw//JQ2A==}
394
395
-
'@pds-moover/moover@1.0.6':
396
-
resolution: {integrity: sha512-Zy+wcrZwoyne7NhuG+5MDFoJ+lpteCpfS6w2pmma9F2IKrVTj2G3Pca7ZVDaibGmCMTJMo21XYaPg+9nLXFD4Q==}
397
398
'@polka/url@1.0.0-next.29':
399
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
···
1062
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
1063
engines: {node: '>= 0.8.0'}
1064
1065
p-limit@3.1.0:
1066
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
1067
engines: {node: '>=10'}
···
1644
'@nodelib/fs.scandir': 2.1.5
1645
fastq: 1.19.1
1646
1647
'@pds-moover/lexicons@1.0.1':
1648
dependencies:
1649
'@atproto/lexicon': 0.5.1
1650
'@atproto/xrpc': 0.7.5
1651
1652
-
'@pds-moover/moover@1.0.6(@atcute/identity@1.1.1)(vite@7.1.12(@types/node@22.19.0))':
1653
dependencies:
1654
'@atcute/cbor': 2.3.2
1655
'@atcute/client': 4.0.5
···
2328
prelude-ls: 1.2.1
2329
type-check: 0.4.0
2330
word-wrap: 1.2.5
2331
2332
p-limit@3.1.0:
2333
dependencies:
···
21
specifier: ^1.0.1
22
version: 1.0.1
23
'@pds-moover/moover':
24
+
specifier: ^1.0.7
25
+
version: 1.0.7(@atcute/identity@1.1.1)(vite@7.1.12(@types/node@22.19.0))
26
devDependencies:
27
'@eslint/compat':
28
specifier: ^1.4.0
···
54
globals:
55
specifier: ^16.4.0
56
version: 16.5.0
57
+
oxlint:
58
+
specifier: ^1.48.0
59
+
version: 1.48.0
60
svelte:
61
specifier: ^5.39.5
62
version: 5.43.2
···
392
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
393
engines: {node: '>= 8'}
394
395
+
'@oxlint/binding-android-arm-eabi@1.48.0':
396
+
resolution: {integrity: sha512-1Pz/stJvveO9ZO7ll4ZoEY3f6j2FiUgBLBcCRCiW6ylId9L9UKs+gn3X28m3eTnoiFCkhKwmJJ+VO6vwsu7Qtg==}
397
+
engines: {node: ^20.19.0 || >=22.12.0}
398
+
cpu: [arm]
399
+
os: [android]
400
+
401
+
'@oxlint/binding-android-arm64@1.48.0':
402
+
resolution: {integrity: sha512-Zc42RWGE8huo6Ht0lXKjd0NH2lWNmimQHUmD0JFcvShLOuwN+RSEE/kRakc2/0LIgOUuU/R7PaDMCOdQlPgNUQ==}
403
+
engines: {node: ^20.19.0 || >=22.12.0}
404
+
cpu: [arm64]
405
+
os: [android]
406
+
407
+
'@oxlint/binding-darwin-arm64@1.48.0':
408
+
resolution: {integrity: sha512-jgZs563/4vaG5jH2RSt2TSh8A2jwsFdmhLXrElMdm3Mmto0HPf85FgInLSNi9HcwzQFvkYV8JofcoUg2GH1HTA==}
409
+
engines: {node: ^20.19.0 || >=22.12.0}
410
+
cpu: [arm64]
411
+
os: [darwin]
412
+
413
+
'@oxlint/binding-darwin-x64@1.48.0':
414
+
resolution: {integrity: sha512-kvo87BujEUjCJREuWDC4aPh1WoXCRFFWE4C7uF6wuoMw2f6N2hypA/cHHcYn9DdL8R2RrgUZPefC8JExyeIMKA==}
415
+
engines: {node: ^20.19.0 || >=22.12.0}
416
+
cpu: [x64]
417
+
os: [darwin]
418
+
419
+
'@oxlint/binding-freebsd-x64@1.48.0':
420
+
resolution: {integrity: sha512-eyzzPaHQKn0RIM+ueDfgfJF2RU//Wp4oaKs2JVoVYcM5HjbCL36+O0S3wO5Xe1NWpcZIG3cEHc/SuOCDRqZDSg==}
421
+
engines: {node: ^20.19.0 || >=22.12.0}
422
+
cpu: [x64]
423
+
os: [freebsd]
424
+
425
+
'@oxlint/binding-linux-arm-gnueabihf@1.48.0':
426
+
resolution: {integrity: sha512-p3kSloztK7GRO7FyO3u38UCjZxQTl92VaLDsMQAq0eGoiNmeeEF1KPeE4+Fr+LSkQhF8WvJKSuls6TwOlurdPA==}
427
+
engines: {node: ^20.19.0 || >=22.12.0}
428
+
cpu: [arm]
429
+
os: [linux]
430
+
431
+
'@oxlint/binding-linux-arm-musleabihf@1.48.0':
432
+
resolution: {integrity: sha512-uWM+wiTqLW/V0ZmY/eyTWs8ykhIkzU+K2tz/8m35YepYEzohiUGRbnkpAFXj2ioXpQL+GUe5vmM3SLH6ozlfFw==}
433
+
engines: {node: ^20.19.0 || >=22.12.0}
434
+
cpu: [arm]
435
+
os: [linux]
436
+
437
+
'@oxlint/binding-linux-arm64-gnu@1.48.0':
438
+
resolution: {integrity: sha512-OhQNPjs/OICaYqxYJjKKMaIY7p3nJ9IirXcFoHKD+CQE1BZFCeUUAknMzUeLclDCfudH9Vb/UgjFm8+ZM5puAg==}
439
+
engines: {node: ^20.19.0 || >=22.12.0}
440
+
cpu: [arm64]
441
+
os: [linux]
442
+
443
+
'@oxlint/binding-linux-arm64-musl@1.48.0':
444
+
resolution: {integrity: sha512-adu5txuwGvQ4C4fjYHJD+vnY+OCwCixBzn7J3KF3iWlVHBBImcosSv+Ye+fbMMJui4HGjifNXzonjKm9pXmOiw==}
445
+
engines: {node: ^20.19.0 || >=22.12.0}
446
+
cpu: [arm64]
447
+
os: [linux]
448
+
449
+
'@oxlint/binding-linux-ppc64-gnu@1.48.0':
450
+
resolution: {integrity: sha512-inlQQRUnHCny/7b7wA6NjEoJSSZPNea4qnDhWyeqBYWx8ukf2kzNDSiamfhOw6bfAYPm/PVlkVRYaNXQbkLeTQ==}
451
+
engines: {node: ^20.19.0 || >=22.12.0}
452
+
cpu: [ppc64]
453
+
os: [linux]
454
+
455
+
'@oxlint/binding-linux-riscv64-gnu@1.48.0':
456
+
resolution: {integrity: sha512-YiJx6sW6bYebQDZRVWLKm/Drswx/hcjIgbLIhULSn0rRcBKc7d9V6mkqPjKDbhcxJgQD5Zi0yVccJiOdF40AWA==}
457
+
engines: {node: ^20.19.0 || >=22.12.0}
458
+
cpu: [riscv64]
459
+
os: [linux]
460
+
461
+
'@oxlint/binding-linux-riscv64-musl@1.48.0':
462
+
resolution: {integrity: sha512-zwSqxMgmb2ITamNfDv9Q9EKBc/4ZhCBP9gkg2hhcgR6sEVGPUDl1AKPC89CBKMxkmPUi3685C38EvqtZn5OtHw==}
463
+
engines: {node: ^20.19.0 || >=22.12.0}
464
+
cpu: [riscv64]
465
+
os: [linux]
466
+
467
+
'@oxlint/binding-linux-s390x-gnu@1.48.0':
468
+
resolution: {integrity: sha512-c/+2oUWAOsQB5JTem0rW8ODlZllF6pAtGSGXoLSvPTonKI1vAwaKhD9Qw1X36jRbcI3Etkpu/9z/RRjMba8vFQ==}
469
+
engines: {node: ^20.19.0 || >=22.12.0}
470
+
cpu: [s390x]
471
+
os: [linux]
472
+
473
+
'@oxlint/binding-linux-x64-gnu@1.48.0':
474
+
resolution: {integrity: sha512-PhauDqeFW5DGed6QxCY5lXZYKSlcBdCXJnH03ZNU6QmDZ0BFM/zSy1oPT2MNb1Afx1G6yOOVk8ErjWsQ7c59ng==}
475
+
engines: {node: ^20.19.0 || >=22.12.0}
476
+
cpu: [x64]
477
+
os: [linux]
478
+
479
+
'@oxlint/binding-linux-x64-musl@1.48.0':
480
+
resolution: {integrity: sha512-6d7LIFFZGiavbHndhf1cK9kG9qmy2Dmr37sV9Ep7j3H+ciFdKSuOzdLh85mEUYMih+b+esMDlF5DU0WQRZPQjw==}
481
+
engines: {node: ^20.19.0 || >=22.12.0}
482
+
cpu: [x64]
483
+
os: [linux]
484
+
485
+
'@oxlint/binding-openharmony-arm64@1.48.0':
486
+
resolution: {integrity: sha512-r+0KK9lK6vFp3tXAgDMOW32o12dxvKS3B9La1uYMGdWAMoSeu2RzG34KmzSpXu6MyLDl4aSVyZLFM8KGdEjwaw==}
487
+
engines: {node: ^20.19.0 || >=22.12.0}
488
+
cpu: [arm64]
489
+
os: [openharmony]
490
+
491
+
'@oxlint/binding-win32-arm64-msvc@1.48.0':
492
+
resolution: {integrity: sha512-Nkw/MocyT3HSp0OJsKPXrcbxZqSPMTYnLLfsqsoiFKoL1ppVNL65MFa7vuTxJehPlBkjy+95gUgacZtuNMECrg==}
493
+
engines: {node: ^20.19.0 || >=22.12.0}
494
+
cpu: [arm64]
495
+
os: [win32]
496
+
497
+
'@oxlint/binding-win32-ia32-msvc@1.48.0':
498
+
resolution: {integrity: sha512-reO1SpefvRmeZSP+WeyWkQd1ArxxDD1MyKgMUKuB8lNuUoxk9QEohYtKnsfsxJuFwMT0JTr7p9wZjouA85GzGQ==}
499
+
engines: {node: ^20.19.0 || >=22.12.0}
500
+
cpu: [ia32]
501
+
os: [win32]
502
+
503
+
'@oxlint/binding-win32-x64-msvc@1.48.0':
504
+
resolution: {integrity: sha512-T6zwhfcsrorqAybkOglZdPkTLlEwipbtdO1qjE+flbawvwOMsISoyiuaa7vM7zEyfq1hmDvMq1ndvkYFioranA==}
505
+
engines: {node: ^20.19.0 || >=22.12.0}
506
+
cpu: [x64]
507
+
os: [win32]
508
+
509
'@pds-moover/lexicons@1.0.1':
510
resolution: {integrity: sha512-fv5b/DtHM7FEo/JklyF9gdK0ainlb6mWjWrBe6cmSAeg9G/4O2jBlQUOqfOAICY9gOcrCpkOrk9PHgGw//JQ2A==}
511
512
+
'@pds-moover/moover@1.0.7':
513
+
resolution: {integrity: sha512-sIyNejsVFMFqg0SyLMQGTde/4kMF+HyitDRPQn7nIgQdctPi2Nzm1pPeVfec2WeAiquXAYdKDWjawolqrKSPSw==}
514
515
'@polka/url@1.0.0-next.29':
516
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
···
1179
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
1180
engines: {node: '>= 0.8.0'}
1181
1182
+
oxlint@1.48.0:
1183
+
resolution: {integrity: sha512-m5vyVBgPtPhVCJc3xI//8je9lRc8bYuYB4R/1PH3VPGOjA4vjVhkHtyJukdEjYEjwrw4Qf1eIf+pP9xvfhfMow==}
1184
+
engines: {node: ^20.19.0 || >=22.12.0}
1185
+
hasBin: true
1186
+
peerDependencies:
1187
+
oxlint-tsgolint: '>=0.12.2'
1188
+
peerDependenciesMeta:
1189
+
oxlint-tsgolint:
1190
+
optional: true
1191
+
1192
p-limit@3.1.0:
1193
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
1194
engines: {node: '>=10'}
···
1771
'@nodelib/fs.scandir': 2.1.5
1772
fastq: 1.19.1
1773
1774
+
'@oxlint/binding-android-arm-eabi@1.48.0':
1775
+
optional: true
1776
+
1777
+
'@oxlint/binding-android-arm64@1.48.0':
1778
+
optional: true
1779
+
1780
+
'@oxlint/binding-darwin-arm64@1.48.0':
1781
+
optional: true
1782
+
1783
+
'@oxlint/binding-darwin-x64@1.48.0':
1784
+
optional: true
1785
+
1786
+
'@oxlint/binding-freebsd-x64@1.48.0':
1787
+
optional: true
1788
+
1789
+
'@oxlint/binding-linux-arm-gnueabihf@1.48.0':
1790
+
optional: true
1791
+
1792
+
'@oxlint/binding-linux-arm-musleabihf@1.48.0':
1793
+
optional: true
1794
+
1795
+
'@oxlint/binding-linux-arm64-gnu@1.48.0':
1796
+
optional: true
1797
+
1798
+
'@oxlint/binding-linux-arm64-musl@1.48.0':
1799
+
optional: true
1800
+
1801
+
'@oxlint/binding-linux-ppc64-gnu@1.48.0':
1802
+
optional: true
1803
+
1804
+
'@oxlint/binding-linux-riscv64-gnu@1.48.0':
1805
+
optional: true
1806
+
1807
+
'@oxlint/binding-linux-riscv64-musl@1.48.0':
1808
+
optional: true
1809
+
1810
+
'@oxlint/binding-linux-s390x-gnu@1.48.0':
1811
+
optional: true
1812
+
1813
+
'@oxlint/binding-linux-x64-gnu@1.48.0':
1814
+
optional: true
1815
+
1816
+
'@oxlint/binding-linux-x64-musl@1.48.0':
1817
+
optional: true
1818
+
1819
+
'@oxlint/binding-openharmony-arm64@1.48.0':
1820
+
optional: true
1821
+
1822
+
'@oxlint/binding-win32-arm64-msvc@1.48.0':
1823
+
optional: true
1824
+
1825
+
'@oxlint/binding-win32-ia32-msvc@1.48.0':
1826
+
optional: true
1827
+
1828
+
'@oxlint/binding-win32-x64-msvc@1.48.0':
1829
+
optional: true
1830
+
1831
'@pds-moover/lexicons@1.0.1':
1832
dependencies:
1833
'@atproto/lexicon': 0.5.1
1834
'@atproto/xrpc': 0.7.5
1835
1836
+
'@pds-moover/moover@1.0.7(@atcute/identity@1.1.1)(vite@7.1.12(@types/node@22.19.0))':
1837
dependencies:
1838
'@atcute/cbor': 2.3.2
1839
'@atcute/client': 4.0.5
···
2512
prelude-ls: 1.2.1
2513
type-check: 0.4.0
2514
word-wrap: 1.2.5
2515
+
2516
+
oxlint@1.48.0:
2517
+
optionalDependencies:
2518
+
'@oxlint/binding-android-arm-eabi': 1.48.0
2519
+
'@oxlint/binding-android-arm64': 1.48.0
2520
+
'@oxlint/binding-darwin-arm64': 1.48.0
2521
+
'@oxlint/binding-darwin-x64': 1.48.0
2522
+
'@oxlint/binding-freebsd-x64': 1.48.0
2523
+
'@oxlint/binding-linux-arm-gnueabihf': 1.48.0
2524
+
'@oxlint/binding-linux-arm-musleabihf': 1.48.0
2525
+
'@oxlint/binding-linux-arm64-gnu': 1.48.0
2526
+
'@oxlint/binding-linux-arm64-musl': 1.48.0
2527
+
'@oxlint/binding-linux-ppc64-gnu': 1.48.0
2528
+
'@oxlint/binding-linux-riscv64-gnu': 1.48.0
2529
+
'@oxlint/binding-linux-riscv64-musl': 1.48.0
2530
+
'@oxlint/binding-linux-s390x-gnu': 1.48.0
2531
+
'@oxlint/binding-linux-x64-gnu': 1.48.0
2532
+
'@oxlint/binding-linux-x64-musl': 1.48.0
2533
+
'@oxlint/binding-openharmony-arm64': 1.48.0
2534
+
'@oxlint/binding-win32-arm64-msvc': 1.48.0
2535
+
'@oxlint/binding-win32-ia32-msvc': 1.48.0
2536
+
'@oxlint/binding-win32-x64-msvc': 1.48.0
2537
2538
p-limit@3.1.0:
2539
dependencies:
+15
-6
web-ui/src/lib/assets/style.css
+15
-6
web-ui/src/lib/assets/style.css
···
138
justify-content: center;
139
}
140
141
-
142
.section {
143
margin-top: 30px;
144
}
···
179
}
180
181
.form-checkbox {
182
-
183
font-size: 2rem;
184
font-weight: bold;
185
line-height: 1.1;
···
244
text-decoration: none;
245
padding: 6px 10px;
246
border-radius: 8px;
247
-
transition: background-color 0.2s ease, color 0.2s ease;
248
}
249
250
.nav-links a:hover,
···
326
flex-direction: column;
327
gap: 4px;
328
padding: 10px 16px 12px 16px;
329
-
background: rgba(36, 36, 36, 0.95); /* solid enough to not bleed into title */
330
backdrop-filter: saturate(180%) blur(10px);
331
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
332
z-index: 1001; /* above page content */
···
426
}
427
}
428
429
-
430
/* Stats grid and cards for the index page */
431
.stats-grid {
432
display: grid;
···
462
font-size: 0.85rem;
463
opacity: 0.7;
464
margin-top: 6px;
465
-
}
···
138
justify-content: center;
139
}
140
141
.section {
142
margin-top: 30px;
143
}
···
178
}
179
180
.form-checkbox {
181
font-size: 2rem;
182
font-weight: bold;
183
line-height: 1.1;
···
242
text-decoration: none;
243
padding: 6px 10px;
244
border-radius: 8px;
245
+
transition:
246
+
background-color 0.2s ease,
247
+
color 0.2s ease;
248
}
249
250
.nav-links a:hover,
···
326
flex-direction: column;
327
gap: 4px;
328
padding: 10px 16px 12px 16px;
329
+
background: rgba(
330
+
36,
331
+
36,
332
+
36,
333
+
0.95
334
+
); /* solid enough to not bleed into title */
335
backdrop-filter: saturate(180%) blur(10px);
336
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
337
z-index: 1001; /* above page content */
···
431
}
432
}
433
434
/* Stats grid and cards for the index page */
435
.stats-grid {
436
display: grid;
···
466
font-size: 0.85rem;
467
opacity: 0.7;
468
margin-top: 6px;
469
+
}
470
+
471
+
.warning {
472
+
/*text-decoration: underline;*/
473
+
font-weight: bold;
474
+
}
+118
web-ui/src/lib/components/Captcha.svelte
+118
web-ui/src/lib/components/Captcha.svelte
···
···
1
+
<script lang="ts">
2
+
import {onMount} from 'svelte';
3
+
import { browser } from '$app/environment';
4
+
5
+
interface CaptchaProps {
6
+
pdsUrl: string;
7
+
handle: string;
8
+
onSuccess: (code: string) => void;
9
+
onError?: (error: string) => void;
10
+
}
11
+
12
+
let {pdsUrl, handle, onSuccess, onError}: CaptchaProps = $props();
13
+
14
+
function generateState(): string {
15
+
const array = new Uint8Array(32);
16
+
crypto.getRandomValues(array);
17
+
return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
18
+
}
19
+
20
+
let captcha_state = $state(generateState());
21
+
let iframeRef: HTMLIFrameElement | null = $state(null);
22
+
let isLoading = $state(true);
23
+
24
+
25
+
26
+
const gateUrl = $derived(
27
+
`${pdsUrl}/gate/signup?state=${encodeURIComponent(captcha_state)}&handle=${encodeURIComponent(handle)}&redirect_url=${encodeURIComponent(browser ? window.location.origin : 'https://pdsmoover.com')}`,
28
+
);
29
+
30
+
// Monitor iframe for URL changes
31
+
function checkIframeUrl() {
32
+
if (!iframeRef) return;
33
+
34
+
try {
35
+
const iframeUrl = new URL(iframeRef.contentWindow?.location.href ?? '');
36
+
37
+
// Check if the iframe has been redirected with code and state parameters
38
+
// This indicates the captcha was completed
39
+
const urlState = iframeUrl.searchParams.get('state');
40
+
const code = iframeUrl.searchParams.get('code');
41
+
42
+
// Only process if we have at least a state parameter (indicates redirect happened)
43
+
if (urlState) {
44
+
45
+
// Verify state matches
46
+
if (urlState !== captcha_state) {
47
+
const stateError = 'State mismatch - possible security issue';
48
+
onError?.(stateError);
49
+
return;
50
+
}
51
+
if (!code) {
52
+
const codeError = 'No code returned from captcha';
53
+
onError?.(codeError);
54
+
return;
55
+
56
+
}
57
+
58
+
onSuccess(code);
59
+
}
60
+
} catch {
61
+
/* empty */
62
+
}
63
+
}
64
+
65
+
onMount(() => {
66
+
// Poll for URL changes
67
+
const interval = setInterval(checkIframeUrl, 100);
68
+
69
+
return () => clearInterval(interval);
70
+
});
71
+
</script>
72
+
73
+
<div class="iframe-wrapper">
74
+
<iframe
75
+
bind:this={iframeRef}
76
+
src={gateUrl}
77
+
title="Captcha Verification"
78
+
onload={() => isLoading = false}
79
+
></iframe>
80
+
{#if isLoading}
81
+
<div class="loading-overlay">
82
+
<p>Loading verification...</p>
83
+
</div>
84
+
{/if}
85
+
</div>
86
+
87
+
<style>
88
+
89
+
.iframe-wrapper {
90
+
position: relative;
91
+
width: 100%;
92
+
height: 500px;
93
+
background: white;
94
+
border: 1px solid #ddd;
95
+
border-radius: 4px;
96
+
overflow: hidden;
97
+
}
98
+
99
+
iframe {
100
+
width: 100%;
101
+
height: 100%;
102
+
border: none;
103
+
}
104
+
105
+
.loading-overlay {
106
+
position: absolute;
107
+
top: 0;
108
+
left: 0;
109
+
right: 0;
110
+
bottom: 0;
111
+
background: rgba(255, 255, 255, 0.9);
112
+
display: flex;
113
+
align-items: center;
114
+
justify-content: center;
115
+
color: #666;
116
+
}
117
+
118
+
</style>
+33
-18
web-ui/src/routes/moover/[[pds]]/+page.svelte
+33
-18
web-ui/src/routes/moover/[[pds]]/+page.svelte
···
4
import {resolve} from '$app/paths';
5
import {Migrator} from '@pds-moover/moover';
6
import SignThePapers from './SignThePapers.svelte';
7
-
import Captcha from './Captcha.svelte';
8
9
let {data} = $props();
10
···
66
let askForPlcToken = $state(false);
67
let disableSubmit = $state(false);
68
let showCaptcha = $state(false);
69
70
let errorMessage: null | string = $state(null);
71
let statusMessage: null | string = $state(null);
···
134
135
async function performMigration() {
136
try {
137
-
138
if (showTwoFactorCodeInput) {
139
if (showTwoFactorCodeInput === null) {
140
errorMessage = 'Please enter the 2FA that was sent to your email.'
···
151
migrator.migratePrefs = formData.migratePrefs;
152
migrator.migratePlcRecord = formData.migratePlcRecord;
153
154
-
console.log(formData.newPds, newHandle);
155
156
updateStatusHandler('Starting migration...');
157
showStatusMessage = true;
···
183
}
184
//@ts-expect-error: JS being js. doesn't like not having the type'
185
errorMessage = error.message;
186
}
187
}
188
</script>
189
190
<svelte:head>
···
194
</svelte:head>
195
196
<div class="container">
197
-
<MooHeader title="PDS MOOver"/>
198
-
{#if !askForPlcToken}
199
<a href={resolve('/info')}>Idk if I trust a cow to move my atproto account to a new PDS</a>
200
<br/>
201
<a href="https://blacksky.community/profile/did:plc:g7j6qok5us4hjqlwjxwrrkjm/post/3lw3hcuojck2u">Video guide for
202
joining blacksky.app</a>
203
{#if showCaptcha}
204
<Captcha
205
-
pdsUrl={formData.newPds}
206
handle={newHandle}
207
onSuccess={handleCaptchaSuccess}
208
onError={handleCaptchaError}
···
388
<span>I understand</span>
389
</label>
390
</div>
391
{#if errorMessage !== null}
392
<div class="error-message">{errorMessage}</div>
393
{/if}
394
395
{#if showStatusMessage}
396
-
<div id="warning">*Please make sure to stay on this page during the MOOve for the
397
-
best result
398
-
</div>
399
<div id="status-message" class="status-message">{statusMessage}</div>
400
{/if}
401
402
403
-
<div>
404
-
<button disabled={disableSubmit}
405
-
type="submit">{selectedPds ? `MOOve to ${cleanSelectedPds}` : 'MOOve'}</button>
406
-
</div>
407
-
408
-
</form>
409
-
{/if}
410
-
{:else}
411
<SignThePapers migrator={migrator} newHandle={newHandle}/>
412
{/if}
413
-
</div>
···
4
import {resolve} from '$app/paths';
5
import {Migrator} from '@pds-moover/moover';
6
import SignThePapers from './SignThePapers.svelte';
7
+
import Captcha from '$lib/components/Captcha.svelte';
8
+
9
10
let {data} = $props();
11
···
67
let askForPlcToken = $state(false);
68
let disableSubmit = $state(false);
69
let showCaptcha = $state(false);
70
+
let migrationInProgress = $state(false);
71
72
let errorMessage: null | string = $state(null);
73
let statusMessage: null | string = $state(null);
···
136
137
async function performMigration() {
138
try {
139
+
migrationInProgress = true;
140
if (showTwoFactorCodeInput) {
141
if (showTwoFactorCodeInput === null) {
142
errorMessage = 'Please enter the 2FA that was sent to your email.'
···
153
migrator.migratePrefs = formData.migratePrefs;
154
migrator.migratePlcRecord = formData.migratePlcRecord;
155
156
157
updateStatusHandler('Starting migration...');
158
showStatusMessage = true;
···
184
}
185
//@ts-expect-error: JS being js. doesn't like not having the type'
186
errorMessage = error.message;
187
+
// migrationInProgress = false;
188
}
189
}
190
+
191
</script>
192
193
<svelte:head>
···
197
</svelte:head>
198
199
<div class="container">
200
+
<MooHeader title="PDS MOOver"/>
201
+
{#if !migrationInProgress}
202
<a href={resolve('/info')}>Idk if I trust a cow to move my atproto account to a new PDS</a>
203
<br/>
204
<a href="https://blacksky.community/profile/did:plc:g7j6qok5us4hjqlwjxwrrkjm/post/3lw3hcuojck2u">Video guide for
205
joining blacksky.app</a>
206
{#if showCaptcha}
207
<Captcha
208
+
pdsUrl={`https://${cleanSelectedPds}`}
209
handle={newHandle}
210
onSuccess={handleCaptchaSuccess}
211
onError={handleCaptchaError}
···
391
<span>I understand</span>
392
</label>
393
</div>
394
+
<div>
395
+
<button disabled={disableSubmit}
396
+
type="submit">{selectedPds ? `MOOve to ${cleanSelectedPds}` : 'MOOve'}</button>
397
+
</div>
398
+
399
+
</form>
400
+
{/if}
401
+
{:else}
402
+
{#if !askForPlcToken}
403
+
<div id="messageBoxes">
404
+
<div class="warning">***Please make sure to stay on this page during the MOOve for the
405
+
best result.***
406
+
</div>
407
+
408
{#if errorMessage !== null}
409
<div class="error-message">{errorMessage}</div>
410
+
411
+
<div id="status-message" class="status-message">A error has occurred. Please take a screenshot of this screen for support. You can also retry by refreshing the page, it will not harm your account.</div>
412
+
413
{/if}
414
415
{#if showStatusMessage}
416
<div id="status-message" class="status-message">{statusMessage}</div>
417
{/if}
418
+
</div>
419
+
{/if}
420
+
{/if}
421
422
423
+
{#if askForPlcToken}
424
<SignThePapers migrator={migrator} newHandle={newHandle}/>
425
{/if}
426
+
427
+
428
+
</div>
-116
web-ui/src/routes/moover/[[pds]]/Captcha.svelte
-116
web-ui/src/routes/moover/[[pds]]/Captcha.svelte
···
1
-
<script lang="ts">
2
-
import {onMount} from 'svelte';
3
-
4
-
interface CaptchaProps {
5
-
pdsUrl: string;
6
-
handle: string;
7
-
onSuccess: (code: string) => void;
8
-
onError?: (error: string) => void;
9
-
}
10
-
11
-
let {pdsUrl, handle, onSuccess, onError}: CaptchaProps = $props();
12
-
13
-
function generateState(): string {
14
-
const array = new Uint8Array(32);
15
-
crypto.getRandomValues(array);
16
-
return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
17
-
}
18
-
19
-
let captcha_state = $state(generateState());
20
-
let iframeRef: HTMLIFrameElement | null = $state(null);
21
-
let isLoading = $state(true);
22
-
23
-
24
-
const gateUrl = $derived(
25
-
`${pdsUrl}/gate/signup?state=${encodeURIComponent(captcha_state)}&handle=${encodeURIComponent(handle)}&redirect_url=${encodeURIComponent(window.location.origin)}`,
26
-
);
27
-
28
-
// Monitor iframe for URL changes
29
-
function checkIframeUrl() {
30
-
if (!iframeRef) return;
31
-
32
-
try {
33
-
const iframeUrl = new URL(iframeRef.contentWindow?.location.href ?? '');
34
-
35
-
// Check if the iframe has been redirected with code and state parameters
36
-
// This indicates the captcha was completed
37
-
const urlState = iframeUrl.searchParams.get('state');
38
-
const code = iframeUrl.searchParams.get('code');
39
-
40
-
// Only process if we have at least a state parameter (indicates redirect happened)
41
-
if (urlState) {
42
-
43
-
// Verify state matches
44
-
if (urlState !== captcha_state) {
45
-
const stateError = 'State mismatch - possible security issue';
46
-
onError?.(stateError);
47
-
return;
48
-
}
49
-
if (!code) {
50
-
const codeError = 'No code returned from captcha';
51
-
onError?.(codeError);
52
-
return;
53
-
54
-
}
55
-
56
-
onSuccess(code);
57
-
}
58
-
} catch {
59
-
/* empty */
60
-
}
61
-
}
62
-
63
-
onMount(() => {
64
-
// Poll for URL changes
65
-
const interval = setInterval(checkIframeUrl, 100);
66
-
67
-
return () => clearInterval(interval);
68
-
});
69
-
</script>
70
-
71
-
<div class="iframe-wrapper">
72
-
<iframe
73
-
bind:this={iframeRef}
74
-
src={gateUrl}
75
-
title="Captcha Verification"
76
-
onload={() => isLoading = false}
77
-
></iframe>
78
-
{#if isLoading}
79
-
<div class="loading-overlay">
80
-
<p>Loading verification...</p>
81
-
</div>
82
-
{/if}
83
-
</div>
84
-
85
-
<style>
86
-
87
-
.iframe-wrapper {
88
-
position: relative;
89
-
width: 100%;
90
-
height: 500px;
91
-
background: white;
92
-
border: 1px solid #ddd;
93
-
border-radius: 4px;
94
-
overflow: hidden;
95
-
}
96
-
97
-
iframe {
98
-
width: 100%;
99
-
height: 100%;
100
-
border: none;
101
-
}
102
-
103
-
.loading-overlay {
104
-
position: absolute;
105
-
top: 0;
106
-
left: 0;
107
-
right: 0;
108
-
bottom: 0;
109
-
background: rgba(255, 255, 255, 0.9);
110
-
display: flex;
111
-
align-items: center;
112
-
justify-content: center;
113
-
color: #666;
114
-
}
115
-
116
-
</style>
···
+7
-6
web-ui/src/routes/moover/[[pds]]/SignThePapers.svelte
+7
-6
web-ui/src/routes/moover/[[pds]]/SignThePapers.svelte
···
80
<form onsubmit="{signPlcOperation}">
81
{#if !done}
82
<div>
83
-
<h2>Please enter your PLC Token you received in an email</h2>
84
<div class="form-group">
85
<label for="plc-token">PLC Token:</label>
86
<input type="text" id="plc-token" name="plc-token" bind:value={plcToken} required>
87
</div>
88
-
<p style="text-align: left">You can now select to add a new Rotation Key during migration and sign up
89
-
for PDS MOOver's free backup service. With a Rotation Key and backups if your new PDS ever goes down
90
-
you can recover your account and it's data.</p>
91
<div class="form-group">
92
<label for="rotation-key" class="moove-checkbox-label">
93
<input bind:checked={createANewRotationKey} type="checkbox" id="rotation-key"
···
165
166
{#if done}
167
<div class="status-message">Congratulations! You have MOOved to a new PDS! Remember to use
168
-
your new PDS URL under "Hosting provider" when logging in on Bluesky. Can find more detail information
169
<a href={resolve('/info#cant-login')}>here.</a></div>
170
{:else }
171
<div>
···
175
176
177
</form>
178
-
</div>
···
80
<form onsubmit="{signPlcOperation}">
81
{#if !done}
82
<div>
83
+
<h2>Please check your email attached to your previous account for a PLC token to enter below</h2>
84
<div class="form-group">
85
<label for="plc-token">PLC Token:</label>
86
<input type="text" id="plc-token" name="plc-token" bind:value={plcToken} required>
87
</div>
88
+
<p style="text-align: left">
89
+
Please check the boxes below if you would like to add a Rotation Key to your account and to sign up for PDS MOOver's free backup service.
90
+
With a Rotation Key and backups if your new PDS ever goes down
91
+
you can recover your account and it's data. This is not required but highly recommended.</p>
92
<div class="form-group">
93
<label for="rotation-key" class="moove-checkbox-label">
94
<input bind:checked={createANewRotationKey} type="checkbox" id="rotation-key"
···
166
167
{#if done}
168
<div class="status-message">Congratulations! You have MOOved to a new PDS! Remember to use
169
+
your new PDS URL under "Hosting provider" when logging in on Bluesky. If you cannot login or see "Your account is deactivated" please follow the directions here
170
<a href={resolve('/info#cant-login')}>here.</a></div>
171
{:else }
172
<div>
···
176
177
178
</form>
179
+
</div>