A decentralized music tracking and discovery platform built on AT Protocol 🎵

Use CAR parsing for repo sync and increase batch size

Replace paginated listRecords calls with getRepo and parse CAR blocks
using @ipld/car and @ipld/dag-cbor. Add related dependencies (and
multiformats) and update bun.lock (apps/cli version 0.2.0 → 0.3.0).

+181 -76
+4
apps/cli/package.json
··· 32 32 "@atproto/jwk-jose": "0.1.5", 33 33 "@atproto/lex-cli": "^0.5.6", 34 34 "@atproto/lexicon": "^0.4.5", 35 + "@atproto/repo": "^0.6.2", 35 36 "@atproto/sync": "^0.1.11", 36 37 "@atproto/syntax": "^0.3.1", 38 + "@ipld/car": "^3.2.4", 39 + "@ipld/dag-cbor": "^9.2.2", 37 40 "@hono/node-server": "^1.13.8", 38 41 "@logtape/logtape": "^1.3.6", 39 42 "@modelcontextprotocol/sdk": "^1.10.2", ··· 56 59 "kysely": "^0.27.5", 57 60 "lodash": "^4.17.21", 58 61 "md5": "^2.3.0", 62 + "multiformats": "^9.9.0", 59 63 "open": "^10.1.0", 60 64 "table": "^6.9.0", 61 65 "unstorage": "^1.14.4",
+149 -70
apps/cli/src/cmd/sync.ts
··· 21 21 import { getDidAndHandle } from "lib/getDidAndHandle"; 22 22 import { cleanUpJetstreamLockOnExit } from "lib/cleanUpJetstreamLock"; 23 23 import { cleanUpSyncLockOnExit } from "lib/cleanUpSyncLock"; 24 - 25 - const PAGE_SIZE = 100; 24 + import { CarReader } from "@ipld/car"; 25 + import * as cbor from "@ipld/dag-cbor"; 26 26 27 27 type Artists = { value: Artist.Record; uri: string; cid: string }[]; 28 28 type Albums = { value: Album.Record; uri: string; cid: string }[]; ··· 133 133 name: tag, 134 134 })); 135 135 136 - const BATCH_SIZE = 500; 136 + const BATCH_SIZE = 1000; 137 137 for (let i = 0; i < uniqueTags.length; i += BATCH_SIZE) { 138 138 const batch = uniqueTags.slice(i, i + BATCH_SIZE); 139 139 await ctx.db ··· 241 241 .filter(({ artist }) => artist); 242 242 243 243 // Process albums in batches 244 - const BATCH_SIZE = 500; 244 + const BATCH_SIZE = 1000; 245 245 let totalAlbumsImported = 0; 246 246 247 247 for (let i = 0; i < validAlbumData.length; i += BATCH_SIZE) { ··· 332 332 .filter(({ artist, album }) => artist && album); 333 333 334 334 // Process in batches to avoid stack overflow with large datasets 335 - const BATCH_SIZE = 500; 335 + const BATCH_SIZE = 1000; 336 336 let totalTracksImported = 0; 337 337 338 338 for (let i = 0; i < validSongData.length; i += BATCH_SIZE) { ··· 481 481 .filter(({ track, album, artist }) => track && album && artist); 482 482 483 483 // Process in batches to avoid stack overflow with large datasets 484 - const BATCH_SIZE = 500; 484 + const BATCH_SIZE = 1000; 485 485 let totalScrobblesImported = 0; 486 486 487 487 for (let i = 0; i < validScrobbleData.length; i += BATCH_SIZE) { ··· 687 687 }; 688 688 689 689 const getRockskyUserSongs = async (agent: Agent): Promise<Songs> => { 690 - let results: { 690 + const results: { 691 691 value: Song.Record; 692 692 uri: string; 693 693 cid: string; 694 694 }[] = []; 695 - let cursor: string | undefined; 696 - do { 697 - const res = await agent.com.atproto.repo.listRecords({ 698 - repo: agent.assertDid, 699 - collection: "app.rocksky.song", 700 - limit: PAGE_SIZE, 701 - cursor, 695 + 696 + try { 697 + logger.info(`Fetching repository CAR file for songs...`); 698 + 699 + const repoRes = await agent.com.atproto.sync.getRepo({ 700 + did: agent.assertDid, 702 701 }); 703 - const records = res.data.records as Array<{ 704 - uri: string; 705 - cid: string; 706 - value: Song.Record; 707 - }>; 708 - results = results.concat(records); 709 - cursor = res.data.cursor; 702 + 703 + const carReader = await CarReader.fromBytes(new Uint8Array(repoRes.data)); 704 + const collection = "app.rocksky.song"; 705 + 706 + for await (const { cid, bytes } of carReader.blocks()) { 707 + try { 708 + const decoded = cbor.decode(bytes); 709 + 710 + // Check if this is a record with $type matching our collection 711 + if (decoded && typeof decoded === "object" && "$type" in decoded) { 712 + if (decoded.$type === collection) { 713 + const value = decoded as unknown as Song.Record; 714 + // Extract rkey from uri if present in the block, otherwise use cid 715 + const uri = `at://${agent.assertDid}/${collection}/${cid.toString()}`; 716 + 717 + results.push({ 718 + value, 719 + uri, 720 + cid: cid.toString(), 721 + }); 722 + } 723 + } 724 + } catch (e) { 725 + logger.warn` Skipping block with CID ${cid.toString()} due to decode error: ${e}`; 726 + continue; 727 + } 728 + } 729 + 710 730 logger.info( 711 731 `${chalk.cyanBright(agent.assertDid)} ${chalk.greenBright(results.length)} songs`, 712 732 ); 713 - } while (cursor); 733 + } catch (error) { 734 + logger.error(`Error fetching songs from CAR: ${error}`); 735 + throw error; 736 + } 714 737 715 738 return results; 716 739 }; 717 740 718 741 const getRockskyUserAlbums = async (agent: Agent): Promise<Albums> => { 719 - let results: { 742 + const results: { 720 743 value: Album.Record; 721 744 uri: string; 722 745 cid: string; 723 746 }[] = []; 724 - let cursor: string | undefined; 725 - do { 726 - const res = await agent.com.atproto.repo.listRecords({ 727 - repo: agent.assertDid, 728 - collection: "app.rocksky.album", 729 - limit: PAGE_SIZE, 730 - cursor, 747 + 748 + try { 749 + logger.info(`Fetching repository CAR file for albums...`); 750 + 751 + // Use getRepo to fetch the entire repository as a CAR file 752 + const repoRes = await agent.com.atproto.sync.getRepo({ 753 + did: agent.assertDid, 731 754 }); 732 755 733 - const records = res.data.records as Array<{ 734 - uri: string; 735 - cid: string; 736 - value: Album.Record; 737 - }>; 756 + // Parse the CAR file 757 + const carReader = await CarReader.fromBytes(new Uint8Array(repoRes.data)); 758 + const collection = "app.rocksky.album"; 759 + 760 + for await (const { cid, bytes } of carReader.blocks()) { 761 + try { 762 + const decoded = cbor.decode(bytes); 763 + 764 + if (decoded && typeof decoded === "object" && "$type" in decoded) { 765 + if (decoded.$type === collection) { 766 + const value = decoded as unknown as Album.Record; 767 + const uri = `at://${agent.assertDid}/${collection}/${cid.toString()}`; 738 768 739 - results = results.concat(records); 769 + results.push({ 770 + value, 771 + uri, 772 + cid: cid.toString(), 773 + }); 774 + } 775 + } 776 + } catch (e) { 777 + logger.warn` Skipping block with CID ${cid.toString()} due to decode error: ${e}`; 778 + continue; 779 + } 780 + } 740 781 741 - cursor = res.data.cursor; 742 782 logger.info( 743 783 `${chalk.cyanBright(agent.assertDid)} ${chalk.greenBright(results.length)} albums`, 744 784 ); 745 - } while (cursor); 785 + } catch (error) { 786 + logger.error(`Error fetching albums from CAR: ${error}`); 787 + throw error; 788 + } 746 789 747 790 return results; 748 791 }; 749 792 750 793 const getRockskyUserArtists = async (agent: Agent): Promise<Artists> => { 751 - let results: { 794 + const results: { 752 795 value: Artist.Record; 753 796 uri: string; 754 797 cid: string; 755 798 }[] = []; 756 - let cursor: string | undefined; 757 - do { 758 - const res = await agent.com.atproto.repo.listRecords({ 759 - repo: agent.assertDid, 760 - collection: "app.rocksky.artist", 761 - limit: PAGE_SIZE, 762 - cursor, 799 + 800 + try { 801 + logger.info(`Fetching repository CAR file for artists...`); 802 + 803 + const repoRes = await agent.com.atproto.sync.getRepo({ 804 + did: agent.assertDid, 763 805 }); 764 806 765 - const records = res.data.records as Array<{ 766 - uri: string; 767 - cid: string; 768 - value: Artist.Record; 769 - }>; 807 + const carReader = await CarReader.fromBytes(new Uint8Array(repoRes.data)); 808 + const collection = "app.rocksky.artist"; 809 + 810 + for await (const { cid, bytes } of carReader.blocks()) { 811 + try { 812 + const decoded = cbor.decode(bytes); 770 813 771 - results = results.concat(records); 814 + if (decoded && typeof decoded === "object" && "$type" in decoded) { 815 + if (decoded.$type === collection) { 816 + const value = decoded as unknown as Artist.Record; 817 + const uri = `at://${agent.assertDid}/${collection}/${cid.toString()}`; 818 + 819 + results.push({ 820 + value, 821 + uri, 822 + cid: cid.toString(), 823 + }); 824 + } 825 + } 826 + } catch (e) { 827 + // Skip blocks that can't be decoded 828 + continue; 829 + } 830 + } 772 831 773 - cursor = res.data.cursor; 774 832 logger.info( 775 833 `${chalk.cyanBright(agent.assertDid)} ${chalk.greenBright(results.length)} artists`, 776 834 ); 777 - } while (cursor); 835 + } catch (error) { 836 + logger.error(`Error fetching artists from CAR: ${error}`); 837 + throw error; 838 + } 778 839 779 840 return results; 780 841 }; 781 842 782 843 const getRockskyUserScrobbles = async (agent: Agent): Promise<Scrobbles> => { 783 - let results: { 844 + const results: { 784 845 value: Scrobble.Record; 785 846 uri: string; 786 847 cid: string; 787 848 }[] = []; 788 - let cursor: string | undefined; 789 - do { 790 - const res = await agent.com.atproto.repo.listRecords({ 791 - repo: agent.assertDid, 792 - collection: "app.rocksky.scrobble", 793 - limit: PAGE_SIZE, 794 - cursor, 849 + 850 + try { 851 + logger.info(`Fetching repository CAR file for scrobbles...`); 852 + 853 + const repoRes = await agent.com.atproto.sync.getRepo({ 854 + did: agent.assertDid, 795 855 }); 796 856 797 - const records = res.data.records as Array<{ 798 - uri: string; 799 - cid: string; 800 - value: Scrobble.Record; 801 - }>; 857 + const carReader = await CarReader.fromBytes(new Uint8Array(repoRes.data)); 858 + const collection = "app.rocksky.scrobble"; 802 859 803 - results = results.concat(records); 860 + for await (const { cid, bytes } of carReader.blocks()) { 861 + try { 862 + const decoded = cbor.decode(bytes); 804 863 805 - cursor = res.data.cursor; 864 + if (decoded && typeof decoded === "object" && "$type" in decoded) { 865 + if (decoded.$type === collection) { 866 + const value = decoded as unknown as Scrobble.Record; 867 + const uri = `at://${agent.assertDid}/${collection}/${cid.toString()}`; 868 + 869 + results.push({ 870 + value, 871 + uri, 872 + cid: cid.toString(), 873 + }); 874 + } 875 + } 876 + } catch (e) { 877 + logger.warn` Skipping block with CID ${cid.toString()} due to decode error: ${e}`; 878 + continue; 879 + } 880 + } 881 + 806 882 logger.info( 807 883 `${chalk.cyanBright(agent.assertDid)} ${chalk.greenBright(results.length)} scrobbles`, 808 884 ); 809 - } while (cursor); 885 + } catch (error) { 886 + logger.error(`Error fetching scrobbles from CAR: ${error}`); 887 + throw error; 888 + } 810 889 811 890 return results; 812 891 };
+28 -6
bun.lock
··· 103 103 }, 104 104 "apps/cli": { 105 105 "name": "@rocksky/cli", 106 - "version": "0.2.0", 106 + "version": "0.3.0", 107 107 "bin": { 108 108 "rocksky": "./dist/index.js", 109 109 }, ··· 114 114 "@atproto/jwk-jose": "0.1.5", 115 115 "@atproto/lex-cli": "^0.5.6", 116 116 "@atproto/lexicon": "^0.4.5", 117 + "@atproto/repo": "^0.6.2", 117 118 "@atproto/sync": "^0.1.11", 118 119 "@atproto/syntax": "^0.3.1", 119 120 "@hono/node-server": "^1.13.8", 121 + "@ipld/car": "^3.2.4", 122 + "@ipld/dag-cbor": "^9.2.2", 120 123 "@logtape/logtape": "^1.3.6", 121 124 "@modelcontextprotocol/sdk": "^1.10.2", 122 125 "@paralleldrive/cuid2": "^3.0.6", ··· 138 141 "kysely": "^0.27.5", 139 142 "lodash": "^4.17.21", 140 143 "md5": "^2.3.0", 144 + "multiformats": "^9.9.0", 141 145 "open": "^10.1.0", 142 146 "table": "^6.9.0", 143 147 "unstorage": "^1.14.4", ··· 413 417 414 418 "@atproto/oauth-types": ["@atproto/oauth-types@0.2.4", "", { "dependencies": { "@atproto/jwk": "0.1.4", "zod": "^3.23.8" } }, "sha512-V2LnlXi1CSmBQWTQgDm8l4oN7xYxlftVwM7hrvYNP+Jxo3Ozfe0QLK1Wy/CH6/ZqzrBBhYvcbf4DJYTUwPA+hw=="], 415 419 416 - "@atproto/repo": ["@atproto/repo@0.8.10", "", { "dependencies": { "@atproto/common": "^0.4.12", "@atproto/common-web": "^0.4.3", "@atproto/crypto": "^0.4.4", "@atproto/lexicon": "^0.5.1", "@ipld/dag-cbor": "^7.0.0", "multiformats": "^9.9.0", "uint8arrays": "3.0.0", "varint": "^6.0.0", "zod": "^3.23.8" } }, "sha512-REs6TZGyxNaYsjqLf447u+gSdyzhvMkVbxMBiKt1ouEVRkiho1CY32+omn62UkpCuGK2y6SCf6x3sVMctgmX4g=="], 420 + "@atproto/repo": ["@atproto/repo@0.6.5", "", { "dependencies": { "@atproto/common": "^0.4.8", "@atproto/common-web": "^0.4.0", "@atproto/crypto": "^0.4.4", "@atproto/lexicon": "^0.4.7", "@ipld/car": "^3.2.3", "@ipld/dag-cbor": "^7.0.0", "multiformats": "^9.9.0", "uint8arrays": "3.0.0", "zod": "^3.23.8" } }, "sha512-Sa95LaEMDtwL9M0kp3vuVQIcgEJI+6EssDLIiuPnJAi9SbEPESdUfEiIR5t2oFCkMwrS7OJQCLdCa7CMy+plUg=="], 417 421 418 422 "@atproto/sync": ["@atproto/sync@0.1.35", "", { "dependencies": { "@atproto/common": "^0.4.12", "@atproto/identity": "^0.4.9", "@atproto/lexicon": "^0.5.1", "@atproto/repo": "^0.8.10", "@atproto/syntax": "^0.4.1", "@atproto/xrpc-server": "^0.9.5", "multiformats": "^9.9.0", "p-queue": "^6.6.2", "ws": "^8.12.0" } }, "sha512-MPvmTjJYCilZEQF1ds7itzF9tNEZtw4Ez0HeMO5E5GaPtTAccBU3AsTxwWST87EX5qsVxMlBTq2go6G6+Swd7Q=="], 419 423 ··· 713 717 714 718 "@ioredis/commands": ["@ioredis/commands@1.4.0", "", {}, "sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ=="], 715 719 716 - "@ipld/dag-cbor": ["@ipld/dag-cbor@7.0.3", "", { "dependencies": { "cborg": "^1.6.0", "multiformats": "^9.5.4" } }, "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA=="], 720 + "@ipld/car": ["@ipld/car@3.2.4", "", { "dependencies": { "@ipld/dag-cbor": "^7.0.0", "multiformats": "^9.5.4", "varint": "^6.0.0" } }, "sha512-rezKd+jk8AsTGOoJKqzfjLJ3WVft7NZNH95f0pfPbicROvzTyvHCNy567HzSUd6gRXZ9im29z5ZEv9Hw49jSYw=="], 721 + 722 + "@ipld/dag-cbor": ["@ipld/dag-cbor@9.2.5", "", { "dependencies": { "cborg": "^4.0.0", "multiformats": "^13.1.0" } }, "sha512-84wSr4jv30biui7endhobYhXBQzQE4c/wdoWlFrKcfiwH+ofaPg8fwsM8okX9cOzkkrsAsNdDyH3ou+kiLquwQ=="], 717 723 718 724 "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], 719 725 ··· 1529 1535 1530 1536 "cbor-x": ["cbor-x@1.6.0", "", { "optionalDependencies": { "cbor-extract": "^2.2.0" } }, "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg=="], 1531 1537 1532 - "cborg": ["cborg@1.10.2", "", { "bin": { "cborg": "cli.js" } }, "sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug=="], 1538 + "cborg": ["cborg@4.3.2", "", { "bin": { "cborg": "lib/bin.js" } }, "sha512-l+QzebEAG0vb09YKkaOrMi2zmm80UNjmbvocMIeW5hO7JOXWdrQ/H49yOKfYX0MBgrj/KWgatBnEgRXyNyKD+A=="], 1533 1539 1534 1540 "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], 1535 1541 ··· 2939 2945 2940 2946 "@atproto-labs/identity-resolver/@atproto/syntax": ["@atproto/syntax@0.4.0", "", {}, "sha512-b9y5ceHS8YKOfP3mdKmwAx5yVj9294UN7FG2XzP6V5aKUdFazEYRnR9m5n5ZQFKa3GNvz7de9guZCJ/sUTcOAA=="], 2941 2947 2948 + "@atproto/common/@ipld/dag-cbor": ["@ipld/dag-cbor@7.0.3", "", { "dependencies": { "cborg": "^1.6.0", "multiformats": "^9.5.4" } }, "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA=="], 2949 + 2942 2950 "@atproto/crypto/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], 2943 2951 2944 2952 "@atproto/jwk-jose/jose": ["jose@5.10.0", "", {}, "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg=="], ··· 2949 2957 2950 2958 "@atproto/lexicon/@atproto/syntax": ["@atproto/syntax@0.4.0", "", {}, "sha512-b9y5ceHS8YKOfP3mdKmwAx5yVj9294UN7FG2XzP6V5aKUdFazEYRnR9m5n5ZQFKa3GNvz7de9guZCJ/sUTcOAA=="], 2951 2959 2952 - "@atproto/repo/@atproto/lexicon": ["@atproto/lexicon@0.5.1", "", { "dependencies": { "@atproto/common-web": "^0.4.3", "@atproto/syntax": "^0.4.1", "iso-datestring-validator": "^2.2.2", "multiformats": "^9.9.0", "zod": "^3.23.8" } }, "sha512-y8AEtYmfgVl4fqFxqXAeGvhesiGkxiy3CWoJIfsFDDdTlZUC8DFnZrYhcqkIop3OlCkkljvpSJi1hbeC1tbi8A=="], 2960 + "@atproto/repo/@ipld/dag-cbor": ["@ipld/dag-cbor@7.0.3", "", { "dependencies": { "cborg": "^1.6.0", "multiformats": "^9.5.4" } }, "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA=="], 2953 2961 2954 2962 "@atproto/sync/@atproto/lexicon": ["@atproto/lexicon@0.5.1", "", { "dependencies": { "@atproto/common-web": "^0.4.3", "@atproto/syntax": "^0.4.1", "iso-datestring-validator": "^2.2.2", "multiformats": "^9.9.0", "zod": "^3.23.8" } }, "sha512-y8AEtYmfgVl4fqFxqXAeGvhesiGkxiy3CWoJIfsFDDdTlZUC8DFnZrYhcqkIop3OlCkkljvpSJi1hbeC1tbi8A=="], 2963 + 2964 + "@atproto/sync/@atproto/repo": ["@atproto/repo@0.8.10", "", { "dependencies": { "@atproto/common": "^0.4.12", "@atproto/common-web": "^0.4.3", "@atproto/crypto": "^0.4.4", "@atproto/lexicon": "^0.5.1", "@ipld/dag-cbor": "^7.0.0", "multiformats": "^9.9.0", "uint8arrays": "3.0.0", "varint": "^6.0.0", "zod": "^3.23.8" } }, "sha512-REs6TZGyxNaYsjqLf447u+gSdyzhvMkVbxMBiKt1ouEVRkiho1CY32+omn62UkpCuGK2y6SCf6x3sVMctgmX4g=="], 2955 2965 2956 2966 "@atproto/sync/@atproto/syntax": ["@atproto/syntax@0.4.1", "", {}, "sha512-CJdImtLAiFO+0z3BWTtxwk6aY5w4t8orHTMVJgkf++QRJWTxPbIFko/0hrkADB7n2EruDxDSeAgfUGehpH6ngw=="], 2957 2967 ··· 2988 2998 "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], 2989 2999 2990 3000 "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], 3001 + 3002 + "@ipld/car/@ipld/dag-cbor": ["@ipld/dag-cbor@7.0.3", "", { "dependencies": { "cborg": "^1.6.0", "multiformats": "^9.5.4" } }, "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA=="], 3003 + 3004 + "@ipld/dag-cbor/multiformats": ["multiformats@13.4.2", "", {}, "sha512-eh6eHCrRi1+POZ3dA+Dq1C6jhP1GNtr9CRINMb67OKzqW9I5DUuZM/3jLPlzhgpGeiNUlEGEbkCYChXMCc/8DQ=="], 2991 3005 2992 3006 "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], 2993 3007 ··· 3336 3350 "yargs/yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], 3337 3351 3338 3352 "youch/cookie": ["cookie@0.5.0", "", {}, "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="], 3353 + 3354 + "@atproto/common/@ipld/dag-cbor/cborg": ["cborg@1.10.2", "", { "bin": { "cborg": "cli.js" } }, "sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug=="], 3339 3355 3340 3356 "@atproto/lex-cli/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], 3341 3357 3342 - "@atproto/repo/@atproto/lexicon/@atproto/syntax": ["@atproto/syntax@0.4.1", "", {}, "sha512-CJdImtLAiFO+0z3BWTtxwk6aY5w4t8orHTMVJgkf++QRJWTxPbIFko/0hrkADB7n2EruDxDSeAgfUGehpH6ngw=="], 3358 + "@atproto/repo/@ipld/dag-cbor/cborg": ["cborg@1.10.2", "", { "bin": { "cborg": "cli.js" } }, "sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug=="], 3359 + 3360 + "@atproto/sync/@atproto/repo/@ipld/dag-cbor": ["@ipld/dag-cbor@7.0.3", "", { "dependencies": { "cborg": "^1.6.0", "multiformats": "^9.5.4" } }, "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA=="], 3343 3361 3344 3362 "@atproto/sync/@atproto/xrpc-server/@atproto/xrpc": ["@atproto/xrpc@0.7.5", "", { "dependencies": { "@atproto/lexicon": "^0.5.1", "zod": "^3.23.8" } }, "sha512-MUYNn5d2hv8yVegRL0ccHvTHAVj5JSnW07bkbiaz96UH45lvYNRVwt44z+yYVnb0/mvBzyD3/ZQ55TRGt7fHkA=="], 3345 3363 ··· 3472 3490 "@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="], 3473 3491 3474 3492 "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], 3493 + 3494 + "@ipld/car/@ipld/dag-cbor/cborg": ["cborg@1.10.2", "", { "bin": { "cborg": "cli.js" } }, "sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug=="], 3475 3495 3476 3496 "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], 3477 3497 ··· 3704 3724 "wrangler/miniflare/youch": ["youch@3.3.4", "", { "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg=="], 3705 3725 3706 3726 "wrangler/miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], 3727 + 3728 + "@atproto/sync/@atproto/repo/@ipld/dag-cbor/cborg": ["cborg@1.10.2", "", { "bin": { "cborg": "cli.js" } }, "sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug=="], 3707 3729 3708 3730 "@atproto/sync/@atproto/xrpc-server/express/accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], 3709 3731