Client side atproto account migrator in your web browser, along with services for backups and adversarial migrations. pdsmoover.com
pds atproto migrations moo cow

feat: various qols #9

merged opened by baileytownsend.dev targeting main from feat/batch-two-qol
  • 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
Labels

None yet.

Participants 1
AT URI
at://did:plc:rnpkyqnmsw4ipey6eotbdnnf/sh.tangled.repo.pull/3mf6qdjs42n22
+872 -661
Diff #0
+1 -1
.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",
··· 1 { 2 "$schema": "https://unpkg.com/oxlint/configuration_schema.json", 3 + "plugins": ["unicorn", "typescript", "oxc"], 4 "jsPlugins": ["@e18e/eslint-plugin", "eslint-plugin-regexp"], 5 "categories": { 6 "correctness": "error",
+1 -1
justfile
··· 27 docker buildx build \ 28 --platform linux/arm64,linux/amd64 \ 29 --tag fatfingers23/moover_ui:latest \ 30 - --tag fatfingers23/moover_ui:0.0.7 \ 31 --file Dockerfiles/web-ui.Dockerfile \ 32 --builder desktop-linux \ 33 --push .
··· 27 docker buildx build \ 28 --platform linux/arm64,linux/amd64 \ 29 --tag fatfingers23/moover_ui:latest \ 30 + --tag fatfingers23/moover_ui:0.0.8 \ 31 --file Dockerfiles/web-ui.Dockerfile \ 32 --builder desktop-linux \ 33 --push .
+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
··· 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
··· 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 - {"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
··· 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 - {"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
··· 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 - {"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
··· 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 - {"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
··· 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 - {"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
··· 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 - {"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
··· 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 - {"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
··· 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
··· 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
··· 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
···
··· 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
··· 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
··· 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
··· 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>

History

1 round 0 comments
sign up or login to add to the discussion
3 commits
expand
some small qol
get ready for release
lockdown
expand 0 comments
pull request successfully merged