@wovin/core 0.1.17 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/applog/applog-helpers.d.ts +5 -4
  2. package/dist/applog/applog-helpers.d.ts.map +1 -1
  3. package/dist/applog.min.js +3 -1
  4. package/dist/{chunk-C22YMCSL.min.js → chunk-3HHBRM32.min.js} +8 -7
  5. package/dist/{chunk-C22YMCSL.min.js.map → chunk-3HHBRM32.min.js.map} +1 -1
  6. package/dist/{chunk-I73T6OVV.min.js → chunk-73CG5VUI.min.js} +20 -4
  7. package/dist/chunk-73CG5VUI.min.js.map +1 -0
  8. package/dist/{chunk-MPOFY7NX.min.js → chunk-CZTDDXGE.min.js} +5 -1
  9. package/dist/{chunk-MPOFY7NX.min.js.map → chunk-CZTDDXGE.min.js.map} +1 -1
  10. package/dist/{chunk-IIZCL4FQ.min.js → chunk-DYHLKKOE.min.js} +2 -2
  11. package/dist/chunk-DYHLKKOE.min.js.map +1 -0
  12. package/dist/{chunk-IFB3AKYA.min.js → chunk-NDHTR5QC.min.js} +2 -2
  13. package/dist/{chunk-AIITTHC6.min.js → chunk-UJMWWDG4.min.js} +2 -2
  14. package/dist/{chunk-TPV3JAXV.min.js → chunk-W477A74Z.min.js} +25 -5
  15. package/dist/chunk-W477A74Z.min.js.map +1 -0
  16. package/dist/index.min.js +9 -7
  17. package/dist/ipfs/fetch-snapshot-chain.d.ts +5 -0
  18. package/dist/ipfs/fetch-snapshot-chain.d.ts.map +1 -1
  19. package/dist/ipfs.min.js +4 -4
  20. package/dist/pubsub/pubsub-types.d.ts +1 -0
  21. package/dist/pubsub/pubsub-types.d.ts.map +1 -1
  22. package/dist/pubsub/snap-push.d.ts +2 -2
  23. package/dist/pubsub/snap-push.d.ts.map +1 -1
  24. package/dist/pubsub.min.js +4 -4
  25. package/dist/query.min.js +3 -3
  26. package/dist/retrieve/update-thread.d.ts +7 -0
  27. package/dist/retrieve/update-thread.d.ts.map +1 -1
  28. package/dist/retrieve.min.js +4 -4
  29. package/dist/thread.min.js +1 -1
  30. package/package.json +2 -1
  31. package/dist/chunk-I73T6OVV.min.js.map +0 -1
  32. package/dist/chunk-IIZCL4FQ.min.js.map +0 -1
  33. package/dist/chunk-TPV3JAXV.min.js.map +0 -1
  34. /package/dist/{chunk-IFB3AKYA.min.js.map → chunk-NDHTR5QC.min.js.map} +0 -0
  35. /package/dist/{chunk-AIITTHC6.min.js.map → chunk-UJMWWDG4.min.js.map} +0 -0
@@ -2,7 +2,7 @@ import {
2
2
  cyrb53hash,
3
3
  ensureTsPvAndFinalizeApplog,
4
4
  g
5
- } from "./chunk-MPOFY7NX.min.js";
5
+ } from "./chunk-CZTDDXGE.min.js";
6
6
 
7
7
  // src/pubsub/pub-pull.ts
8
8
  var { WARN, LOG, DEBUG, VERBOSE, ERROR } = g.setup(g.INFO);
@@ -37,4 +37,4 @@ export {
37
37
  isSubscription,
38
38
  agentToShortHash
39
39
  };
40
- //# sourceMappingURL=chunk-IIZCL4FQ.min.js.map
40
+ //# sourceMappingURL=chunk-DYHLKKOE.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pubsub/pub-pull.ts","../src/pubsub/pubsub-types.ts"],"sourcesContent":["import { Logger } from 'besonders-logger'\nimport { CID } from 'multiformats'\nimport { ensureTsPvAndFinalizeApplog } from '../applog/applog-helpers'\nimport { EntityID } from '../applog/datom-types'\nimport { Thread } from '../thread'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport type PubPullData = {\n\tcid: CID\n\tthread: Thread\n}\n\nexport function integratePub({ targetThread, agentHash, subID, pubData }: {\n\ttargetThread: Thread\n\tagentHash: EntityID\n\tpubData: PubPullData\n\tsubID?: EntityID\n}) {\n\tconst newLogs = pubData.thread.applogs.filter(log => !targetThread.hasApplog(log, false))\n\tDEBUG(`[integratePub] integrating ${newLogs.length} logs`, { targetThread, subID, pubData })\n\tlet toInsert = newLogs\n\tif (subID) {\n\t\ttoInsert = toInsert.concat(ensureTsPvAndFinalizeApplog(\n\t\t\t{ en: subID, at: 'subscription/cid', vl: pubData.cid.toString(), ag: agentHash },\n\t\t\ttargetThread,\n\t\t))\n\t}\n\ttargetThread.insertRaw(toInsert)\n\treturn newLogs\n}\n","import { CID } from 'multiformats/cid'\nimport { cyrb53hash } from './../applog/applog-utils'\nimport { AgentHash, AgentID, CidString } from '../applog/datom-types'\nimport { Tagged } from '../types'\nimport { UCANCapMap } from './ucan'\ntype AgentString = Tagged<string, 'AgentString'>\ntype DIDString = Tagged<string, 'DID'>\nexport type { AgentHash, AgentString, DIDString }\n\n\nexport interface AppAgent {\n\tag: AgentHash\n\tagentString: AgentString\n\tdid: DIDString\n\tsign? (data: Uint8Array): Promise<Uint8Array>\n\tucan?: UCANCapMap\n}\nexport interface AppAgentForWorker extends AppAgent {\n\tsignerSecret?: Uint8Array\n}\nexport interface SnapRootBlock {\n\tapplogs: CID\n\tapplogsSignature: Uint8Array\n\tinfo: CID\n\tinfoSignature: Uint8Array\n\tprev?: CID\n\tprevCounter?: number // Sequential counter: 0 for first, then +1 for each. Undefined if unknown.\n}\nexport interface SnapBlockLogs {\n\tlogs: CID[]\n}\nexport interface SnapBlockChunks {\n\tchunks: CID[]\n}\nexport type SnapBlockLogsOrChunks = SnapBlockLogs | SnapBlockChunks\n\n// HACK: this is actually note3 types, not wovin\nexport interface IShare {\n\tid?: string // string hash of pub (used as unique id in IDB) `W3Name.create().toString()` starts with k51qzi5uqu5d\n\tcreatedAt: string // ISO timestamp of creation\n\tname: string // nick name for the pub\n\tisDeleted?: boolean\n\tpurgeBeforePush?: boolean\n\n\tpk: Uint8Array // exported privatekey - needed to create WritableName for publishing //TODO: store as non-extractable / encrypted?\n\n\tautopush: boolean\n\tlastPush: string | null\n\tlastCID?: string\n\tlatestLogTs?: string\n\tpubCounter?: number\n\n\tpublishedBy: string // local user appAgent\n\tselectors?: string[] // to be used as a filter for which applogs to pub\n\tencryptedFor?: string | null // short agentHash\n\tencryptedWith?: CryptoKey | null // AES-GCM derived key from ECDH keys (local private and remote public)\n\n\t// HACK WIP #39 - shared encryption\n\tsharedKey?: CryptoKey | null // AES-GCM derived key from ECDH keys (local private and ipns public)\n\tsharedAgents?: AgentID[] | null // array of string EntityIDs for the chosen agents (we need public jwkd atoms for each of them)\n\tsharedKeyMap?: Map<AgentID, string> | null // uses public key from each agent to derive an aes key that is used to encrypt and btoa the sharedKey that is actually used to encrypt and decrypt the applogs\n}\nexport interface ISubscription {\n\tid: string // string hash of pub (used as unique id in IDB) `W3Name.create().toString()` starts with k51qzi5uqu5d\n\tcreatedAt: string // ISO timestamp of creation\n\tname: string // nick name for the pub\n\tisDeleted: boolean\n\n\tlastPull?: string | null\n\tlastPullAttempt?: string | null\n\tautopull: boolean\n\trealtime?: boolean // enable real-time WebSocket updates via IPNS watcher\n\tlastCID?: string // ? why not CidString\n\tlastApplogCID?: string\n\tpublishedBy?: string // remote publisher short agentHash\n\tencryptedFor?: string | undefined // short agentHash\n\tencryptedWith?: CryptoKey | undefined // AES-GCM derived key from ECDH keys (local private and remote public)\n}\nexport function isShare(obj: any): obj is IShare {\n\treturn obj?.pk !== undefined && obj?.lastPush !== undefined\n}\nexport function isSubscription(obj: any): obj is ISubscription {\n\treturn obj?.lastPull !== undefined\n}\n\nexport type TShareSub = IShare | ISubscription\n\nexport function agentToShortHash(agentString: string) {\n\treturn cyrb53hash(agentString, 31, 7) as string\n}\n"],"mappings":";;;;;;;AAMA,IAAM,EAAE,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,EAAO,MAAM,EAAO,IAAI;AAO9D,SAAS,aAAa,EAAE,cAAc,WAAW,OAAO,QAAQ,GAKpE;AACF,QAAM,UAAU,QAAQ,OAAO,QAAQ,OAAO,SAAO,CAAC,aAAa,UAAU,KAAK,KAAK,CAAC;AACxF,QAAM,8BAA8B,QAAQ,MAAM,SAAS,EAAE,cAAc,OAAO,QAAQ,CAAC;AAC3F,MAAI,WAAW;AACf,MAAI,OAAO;AACV,eAAW,SAAS,OAAO;AAAA,MAC1B,EAAE,IAAI,OAAO,IAAI,oBAAoB,IAAI,QAAQ,IAAI,SAAS,GAAG,IAAI,UAAU;AAAA,MAC/E;AAAA,IACD,CAAC;AAAA,EACF;AACA,eAAa,UAAU,QAAQ;AAC/B,SAAO;AACR;;;ACgDO,SAAS,QAAQ,KAAyB;AAChD,SAAO,KAAK,OAAO,UAAa,KAAK,aAAa;AACnD;AACO,SAAS,eAAe,KAAgC;AAC9D,SAAO,KAAK,aAAa;AAC1B;AAIO,SAAS,iBAAiB,aAAqB;AACrD,SAAO,WAAW,aAAa,IAAI,CAAC;AACrC;","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  createDebugName,
5
5
  g,
6
6
  observableArrayMap
7
- } from "./chunk-MPOFY7NX.min.js";
7
+ } from "./chunk-CZTDDXGE.min.js";
8
8
  import {
9
9
  autorun,
10
10
  comparer,
@@ -62,4 +62,4 @@ export {
62
62
  includes,
63
63
  includedIn
64
64
  };
65
- //# sourceMappingURL=chunk-IFB3AKYA.min.js.map
65
+ //# sourceMappingURL=chunk-NDHTR5QC.min.js.map
@@ -16,7 +16,7 @@ import {
16
16
  rollingMapper,
17
17
  sortApplogsByTs,
18
18
  wrapper_default
19
- } from "./chunk-MPOFY7NX.min.js";
19
+ } from "./chunk-CZTDDXGE.min.js";
20
20
  import {
21
21
  action,
22
22
  autorun,
@@ -507,4 +507,4 @@ export {
507
507
  withTimeout,
508
508
  throwOnTimeout
509
509
  };
510
- //# sourceMappingURL=chunk-AIITTHC6.min.js.map
510
+ //# sourceMappingURL=chunk-UJMWWDG4.min.js.map
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  unchunkApplogsBlock
3
- } from "./chunk-C22YMCSL.min.js";
3
+ } from "./chunk-3HHBRM32.min.js";
4
4
  import {
5
5
  CID,
6
6
  areCidsEqual,
7
7
  decode,
8
8
  g,
9
9
  removeDuplicateAppLogs
10
- } from "./chunk-MPOFY7NX.min.js";
10
+ } from "./chunk-CZTDDXGE.min.js";
11
11
 
12
12
  // src/retrieve/update-thread.ts
13
13
  var { WARN, LOG, DEBUG, VERBOSE, ERROR } = g.setup(g.INFO);
@@ -28,9 +28,10 @@ async function getDecodedBlock(blockStore, cid) {
28
28
  return decode(bytes);
29
29
  }
30
30
  async function updateThreadFromSnapshot(thread, cid, retriever, options) {
31
- const { excludeSnapshotCID, maxDepth = 100 } = options ?? {};
31
+ const { excludeSnapshotCID, stopAtCounter, maxDepth = 100 } = options ?? {};
32
32
  DEBUG("[updateThreadFromSnapshot] starting from", cid.toString(), {
33
33
  excludeSnapshotCID: excludeSnapshotCID?.toString(),
34
+ stopAtCounter,
34
35
  maxDepth
35
36
  });
36
37
  const blockStore = createMemoryBlockStore();
@@ -38,6 +39,9 @@ async function updateThreadFromSnapshot(thread, cid, retriever, options) {
38
39
  let currentCID = cid;
39
40
  let snapshotCount = 0;
40
41
  const allApplogs = [];
42
+ let minCounter = Infinity;
43
+ let maxCounter = -Infinity;
44
+ let lastCounter;
41
45
  while (currentCID && snapshotCount < maxDepth) {
42
46
  const cidStr = currentCID.toString();
43
47
  if (visited.has(cidStr)) {
@@ -55,6 +59,21 @@ async function updateThreadFromSnapshot(thread, cid, retriever, options) {
55
59
  const rootBytes = await retriever.getBlock(currentCID);
56
60
  blockStore.put(currentCID, rootBytes);
57
61
  const root = decode(rootBytes);
62
+ if (root.prevCounter !== void 0) {
63
+ minCounter = Math.min(minCounter, root.prevCounter);
64
+ maxCounter = Math.max(maxCounter, root.prevCounter);
65
+ if (lastCounter !== void 0 && root.prevCounter !== lastCounter - 1) {
66
+ WARN("[updateThreadFromSnapshot] counter gap detected", {
67
+ expected: lastCounter - 1,
68
+ got: root.prevCounter
69
+ });
70
+ }
71
+ lastCounter = root.prevCounter;
72
+ }
73
+ if (stopAtCounter !== void 0 && root.prevCounter !== void 0 && root.prevCounter <= stopAtCounter) {
74
+ DEBUG("[updateThreadFromSnapshot] reached stopAtCounter", { stopAtCounter, prevCounter: root.prevCounter });
75
+ break;
76
+ }
58
77
  DEBUG("[updateThreadFromSnapshot] fetching applogs", root.applogs.toString());
59
78
  for await (const { cid: blockCid, bytes } of retriever.getDag(root.applogs)) {
60
79
  blockStore.put(blockCid, bytes);
@@ -102,11 +121,12 @@ async function updateThreadFromSnapshot(thread, cid, retriever, options) {
102
121
  cid,
103
122
  applogs: deduplicated,
104
123
  insertedCount: inserted.length,
105
- snapshotCount
124
+ snapshotCount,
125
+ counterRange: minCounter !== Infinity ? { minCounter, maxCounter } : void 0
106
126
  };
107
127
  }
108
128
 
109
129
  export {
110
130
  updateThreadFromSnapshot
111
131
  };
112
- //# sourceMappingURL=chunk-TPV3JAXV.min.js.map
132
+ //# sourceMappingURL=chunk-W477A74Z.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/retrieve/update-thread.ts"],"sourcesContent":["import { CarReader } from '@ipld/car'\nimport * as dagJson from '@ipld/dag-json'\nimport { Logger } from 'besonders-logger'\nimport { CID } from 'multiformats/cid'\nimport type { Applog } from '../applog/datom-types'\nimport { removeDuplicateAppLogs } from '../applog/applog-utils'\nimport type { SnapRootBlock, SnapBlockLogsOrChunks } from '../pubsub/pubsub-types'\nimport { unchunkApplogsBlock } from '../pubsub/snap-push'\nimport { areCidsEqual } from '../ipfs/ipfs-utils'\nimport type { WriteableThread } from '../thread/writeable'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\n/**\n * Block retrieval abstraction - fetch or get blocks.\n * Implemented by gateway retriever or local blockstore.\n */\nexport interface BlockRetriever {\n\t/** Get single block by CID */\n\tgetBlock(cid: CID): Promise<Uint8Array>\n\t/** Get all blocks in DAG rooted at CID (for applogs/info sub-DAGs) */\n\tgetDag(cid: CID): AsyncIterable<{ cid: CID; bytes: Uint8Array }>\n}\n\n/**\n * Options for updateThreadFromSnapshot\n */\nexport interface UpdateOptions {\n\t/** CID of last included snapshot - exclude this and older snapshots */\n\texcludeSnapshotCID?: CID\n\t/** Stop when we reach this counter (walking backwards) */\n\tstopAtCounter?: number\n\t/** Maximum number of snapshots to traverse (default: 100) */\n\tmaxDepth?: number\n}\n\n/**\n * Result from updateThreadFromSnapshot\n */\nexport interface UpdateResult {\n\t/** Root CID that was fetched */\n\tcid: CID\n\t/** All applogs decoded from the chain */\n\tapplogs: Applog[]\n\t/** Count of applogs actually inserted (not duplicates) */\n\tinsertedCount: number\n\t/** Number of snapshots traversed */\n\tsnapshotCount: number\n\t/** Counter range encountered (min/max) */\n\tcounterRange?: { minCounter: number; maxCounter: number }\n}\n\n/**\n * Simple in-memory block store used during snapshot chain fetch.\n */\ninterface MemoryBlockStore {\n\tget(cid: CID): Uint8Array | undefined\n\tput(cid: CID, bytes: Uint8Array): void\n}\n\nfunction createMemoryBlockStore(): MemoryBlockStore {\n\tconst blocks = new Map<string, Uint8Array>()\n\treturn {\n\t\tget(cid: CID) {\n\t\t\treturn blocks.get(cid.toV1().toString())\n\t\t},\n\t\tput(cid: CID, bytes: Uint8Array) {\n\t\t\tblocks.set(cid.toV1().toString(), bytes)\n\t\t},\n\t}\n}\n\nasync function getDecodedBlock<T>(blockStore: MemoryBlockStore, cid: CID): Promise<T | null> {\n\tconst bytes = blockStore.get(cid)\n\tif (!bytes) return null\n\treturn dagJson.decode(bytes) as T\n}\n\n/**\n * Fetch snapshot chain from CID using a BlockRetriever, decode applogs, insert into thread.\n * Stops before excludeSnapshotCID if provided (incremental update).\n *\n * @param thread - WriteableThread to insert applogs into\n * @param cid - Root CID of the snapshot to start from\n * @param retriever - BlockRetriever for fetching blocks\n * @param options - Optional configuration\n * @returns UpdateResult with applogs and counts\n */\nexport async function updateThreadFromSnapshot(\n\tthread: WriteableThread,\n\tcid: CID,\n\tretriever: BlockRetriever,\n\toptions?: UpdateOptions\n): Promise<UpdateResult> {\n\tconst { excludeSnapshotCID, stopAtCounter, maxDepth = 100 } = options ?? {}\n\n\tDEBUG('[updateThreadFromSnapshot] starting from', cid.toString(), {\n\t\texcludeSnapshotCID: excludeSnapshotCID?.toString(),\n\t\tstopAtCounter,\n\t\tmaxDepth,\n\t})\n\n\tconst blockStore = createMemoryBlockStore()\n\tconst visited = new Set<string>()\n\tlet currentCID: CID | undefined = cid\n\tlet snapshotCount = 0\n\tconst allApplogs: Applog[] = []\n\tlet minCounter = Infinity\n\tlet maxCounter = -Infinity\n\tlet lastCounter: number | undefined\n\n\twhile (currentCID && snapshotCount < maxDepth) {\n\t\tconst cidStr = currentCID.toString()\n\n\t\t// Loop detection\n\t\tif (visited.has(cidStr)) {\n\t\t\tthrow ERROR('[updateThreadFromSnapshot] snapshot chain has a loop', {\n\t\t\t\tcurrentCID: cidStr,\n\t\t\t\tvisited: [...visited],\n\t\t\t})\n\t\t}\n\t\tvisited.add(cidStr)\n\n\t\t// Check stop condition BEFORE fetching content\n\t\tif (excludeSnapshotCID && areCidsEqual(currentCID, excludeSnapshotCID)) {\n\t\t\tDEBUG('[updateThreadFromSnapshot] reached excludeSnapshotCID, stopping', excludeSnapshotCID.toString())\n\t\t\tbreak\n\t\t}\n\n\t\t// 1. Fetch root block\n\t\tDEBUG('[updateThreadFromSnapshot] fetching root block', cidStr)\n\t\tconst rootBytes = await retriever.getBlock(currentCID)\n\t\tblockStore.put(currentCID, rootBytes)\n\n\t\t// Parse root to get applogs, info, prev CIDs\n\t\tconst root = dagJson.decode(rootBytes) as SnapRootBlock\n\n\t\t// Track counter range and validate sequentiality\n\t\tif (root.prevCounter !== undefined) {\n\t\t\tminCounter = Math.min(minCounter, root.prevCounter)\n\t\t\tmaxCounter = Math.max(maxCounter, root.prevCounter)\n\n\t\t\t// Validate sequentiality (walking backwards, counter should decrease)\n\t\t\tif (lastCounter !== undefined && root.prevCounter !== lastCounter - 1) {\n\t\t\t\tWARN('[updateThreadFromSnapshot] counter gap detected', {\n\t\t\t\t\texpected: lastCounter - 1,\n\t\t\t\t\tgot: root.prevCounter,\n\t\t\t\t})\n\t\t\t}\n\t\t\tlastCounter = root.prevCounter\n\t\t}\n\n\t\t// Stop condition based on counter\n\t\tif (stopAtCounter !== undefined && root.prevCounter !== undefined && root.prevCounter <= stopAtCounter) {\n\t\t\tDEBUG('[updateThreadFromSnapshot] reached stopAtCounter', { stopAtCounter, prevCounter: root.prevCounter })\n\t\t\tbreak\n\t\t}\n\n\t\t// 2. Fetch applogs DAG\n\t\tDEBUG('[updateThreadFromSnapshot] fetching applogs', root.applogs.toString())\n\t\tfor await (const { cid: blockCid, bytes } of retriever.getDag(root.applogs)) {\n\t\t\tblockStore.put(blockCid, bytes)\n\t\t}\n\n\t\t// 3. Fetch info DAG\n\t\tDEBUG('[updateThreadFromSnapshot] fetching info', root.info.toString())\n\t\tfor await (const { cid: blockCid, bytes } of retriever.getDag(root.info)) {\n\t\t\tblockStore.put(blockCid, bytes)\n\t\t}\n\n\t\t// Decode applogs from this snapshot\n\t\tconst applogsBlock = await getDecodedBlock<SnapBlockLogsOrChunks>(blockStore, root.applogs)\n\t\tif (!applogsBlock) {\n\t\t\tthrow ERROR('[updateThreadFromSnapshot] applogs block not found', { cid: root.applogs.toString() })\n\t\t}\n\n\t\t// Use the unchunk helper which handles both chunked and non-chunked formats\n\t\tconst applogCIDs = await unchunkApplogsBlock(applogsBlock, {\n\t\t\tget: async (cid: CID) => blockStore.get(cid)!,\n\t\t})\n\n\t\t// Resolve each applog CID to actual applog data\n\t\tfor (const applogCID of applogCIDs) {\n\t\t\tconst applog = await getDecodedBlock<Applog>(blockStore, applogCID)\n\t\t\tif (!applog) {\n\t\t\t\tWARN('[updateThreadFromSnapshot] applog not found:', applogCID.toString())\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Normalize pv field if it's a CID instance\n\t\t\tif ((applog.pv as any) instanceof CID) {\n\t\t\t\tapplog.pv = (applog.pv as any as CID).toV1().toString()\n\t\t\t}\n\t\t\tallApplogs.push({\n\t\t\t\t...applog,\n\t\t\t\tcid: applogCID.toV1().toString(),\n\t\t\t})\n\t\t}\n\n\t\tsnapshotCount++\n\t\tcurrentCID = root.prev // Move to previous snapshot\n\t}\n\n\tDEBUG('[updateThreadFromSnapshot] fetched', {\n\t\tsnapshotCount,\n\t\tapplogCount: allApplogs.length,\n\t\trootCID: cid.toString(),\n\t})\n\n\t// Deduplicate applogs (in case of overlapping snapshots)\n\tconst deduplicated = removeDuplicateAppLogs(allApplogs, 'cleanup')\n\n\t// Insert into thread\n\tconst inserted = thread.insertMissing(deduplicated, false)\n\n\tDEBUG('[updateThreadFromSnapshot] inserted', {\n\t\tinsertedCount: inserted.length,\n\t\tduplicateCount: deduplicated.length - inserted.length,\n\t})\n\n\treturn {\n\t\tcid,\n\t\tapplogs: deduplicated,\n\t\tinsertedCount: inserted.length,\n\t\tsnapshotCount,\n\t\tcounterRange: minCounter !== Infinity ? { minCounter, maxCounter } : undefined,\n\t}\n}\n"],"mappings":"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","names":["cid"]}
package/dist/index.min.js CHANGED
@@ -2,21 +2,21 @@ import "./chunk-5MMGBK2U.min.js";
2
2
  import "./chunk-7IDQIMQO.min.js";
3
3
  import {
4
4
  fetchSnapshotChainUntil
5
- } from "./chunk-I73T6OVV.min.js";
5
+ } from "./chunk-73CG5VUI.min.js";
6
6
  import {
7
7
  agentToShortHash,
8
8
  integratePub,
9
9
  isShare,
10
10
  isSubscription
11
- } from "./chunk-IIZCL4FQ.min.js";
11
+ } from "./chunk-DYHLKKOE.min.js";
12
12
  import {
13
13
  includedIn,
14
14
  includes,
15
15
  queryDivergencesByPrev
16
- } from "./chunk-IFB3AKYA.min.js";
16
+ } from "./chunk-NDHTR5QC.min.js";
17
17
  import {
18
18
  updateThreadFromSnapshot
19
- } from "./chunk-TPV3JAXV.min.js";
19
+ } from "./chunk-W477A74Z.min.js";
20
20
  import {
21
21
  carFromBlob,
22
22
  chunkApplogs,
@@ -32,7 +32,7 @@ import {
32
32
  prepareSnapshotForPush,
33
33
  streamReaderToIterable,
34
34
  unchunkApplogsBlock
35
- } from "./chunk-C22YMCSL.min.js";
35
+ } from "./chunk-3HHBRM32.min.js";
36
36
  import "./chunk-QPGEBDMJ.min.js";
37
37
  import {
38
38
  QueryNode,
@@ -60,7 +60,7 @@ import {
60
60
  throwOnTimeout,
61
61
  withTimeout,
62
62
  withoutDeleted
63
- } from "./chunk-AIITTHC6.min.js";
63
+ } from "./chunk-UJMWWDG4.min.js";
64
64
  import {
65
65
  AppLogNoCidTB,
66
66
  AppLogNoCidTBC,
@@ -158,9 +158,10 @@ import {
158
158
  tsNearlySame,
159
159
  uniqueEnFromAppLogs,
160
160
  variableNameWithoutQuestionmark,
161
+ withAg,
161
162
  withPvFrom,
162
163
  withTs
163
- } from "./chunk-MPOFY7NX.min.js";
164
+ } from "./chunk-CZTDDXGE.min.js";
164
165
  import {
165
166
  BOOL,
166
167
  Bool,
@@ -328,6 +329,7 @@ export {
328
329
  uniqueEnFromAppLogs,
329
330
  updateThreadFromSnapshot,
330
331
  variableNameWithoutQuestionmark,
332
+ withAg,
331
333
  withPvFrom,
332
334
  withTimeout,
333
335
  withTs,
@@ -7,6 +7,7 @@ export interface BlockStoreForFetch {
7
7
  export interface FetchChainOptions {
8
8
  rootCID: CID;
9
9
  stopAtCID?: CID;
10
+ stopAtCounter?: number;
10
11
  fetchBlock: (cid: CID) => Promise<CarReader>;
11
12
  fetchAll: (cid: CID) => Promise<CarReader>;
12
13
  maxDepth?: number;
@@ -17,6 +18,10 @@ export interface FetchChainResult {
17
18
  /** Serializable blocks array for worker boundary crossing */
18
19
  blocks: [string, Uint8Array][];
19
20
  snapshotCount: number;
21
+ counterRange?: {
22
+ minCounter: number;
23
+ maxCounter: number;
24
+ };
20
25
  }
21
26
  /**
22
27
  * Fetches a snapshot chain iteratively, stopping at stopAtCID.
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-snapshot-chain.d.ts","sourceRoot":"","sources":["../../src/ipfs/fetch-snapshot-chain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAGrC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAMtC,MAAM,WAAW,kBAAkB;IAC/B,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;IAC9C,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAClD;AAED,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,GAAG,CAAA;IACZ,SAAS,CAAC,EAAE,GAAG,CAAA;IACf,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,SAAS,CAAC,CAAA;IAC5C,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,SAAS,CAAC,CAAA;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,GAAG,CAAA;IACZ,UAAU,EAAE,kBAAkB,CAAA;IAC9B,6DAA6D;IAC7D,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAA;IAC9B,aAAa,EAAE,MAAM,CAAA;CACxB;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAkDnG"}
1
+ {"version":3,"file":"fetch-snapshot-chain.d.ts","sourceRoot":"","sources":["../../src/ipfs/fetch-snapshot-chain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAGrC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAMtC,MAAM,WAAW,kBAAkB;IAC/B,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;IAC9C,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAClD;AAED,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,GAAG,CAAA;IACZ,SAAS,CAAC,EAAE,GAAG,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,SAAS,CAAC,CAAA;IAC5C,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,SAAS,CAAC,CAAA;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,GAAG,CAAA;IACZ,UAAU,EAAE,kBAAkB,CAAA;IAC9B,6DAA6D;IAC7D,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAA;IAC9B,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5D;AAED;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsEnG"}
package/dist/ipfs.min.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  fetchSnapshotChainUntil
3
- } from "./chunk-I73T6OVV.min.js";
3
+ } from "./chunk-73CG5VUI.min.js";
4
4
  import {
5
5
  carFromBlob,
6
6
  decodePubFromBlocks,
@@ -10,9 +10,9 @@ import {
10
10
  makeCarBlob,
11
11
  makeCarOut,
12
12
  streamReaderToIterable
13
- } from "./chunk-C22YMCSL.min.js";
13
+ } from "./chunk-3HHBRM32.min.js";
14
14
  import "./chunk-QPGEBDMJ.min.js";
15
- import "./chunk-AIITTHC6.min.js";
15
+ import "./chunk-UJMWWDG4.min.js";
16
16
  import {
17
17
  MULTICODEC_IPNS_KEY,
18
18
  areCidsEqual,
@@ -28,7 +28,7 @@ import {
28
28
  prepareForPub,
29
29
  toIpnsString,
30
30
  tryParseCID
31
- } from "./chunk-MPOFY7NX.min.js";
31
+ } from "./chunk-CZTDDXGE.min.js";
32
32
  import "./chunk-HYMC7W6S.min.js";
33
33
  import "./chunk-KEHU7HGZ.min.js";
34
34
  import "./chunk-PHITDXZT.min.js";
@@ -21,6 +21,7 @@ export interface SnapRootBlock {
21
21
  info: CID;
22
22
  infoSignature: Uint8Array;
23
23
  prev?: CID;
24
+ prevCounter?: number;
24
25
  }
25
26
  export interface SnapBlockLogs {
26
27
  logs: CID[];
@@ -1 +1 @@
1
- {"version":3,"file":"pubsub-types.d.ts","sourceRoot":"","sources":["../../src/pubsub/pubsub-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAEtC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAa,MAAM,uBAAuB,CAAA;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACnC,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;AAChD,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AACtC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,CAAA;AAGjD,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,SAAS,CAAA;IACb,WAAW,EAAE,WAAW,CAAA;IACxB,GAAG,EAAE,SAAS,CAAA;IACd,IAAI,CAAC,CAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IAC7C,IAAI,CAAC,EAAE,UAAU,CAAA;CACjB;AACD,MAAM,WAAW,iBAAkB,SAAQ,QAAQ;IAClD,YAAY,CAAC,EAAE,UAAU,CAAA;CACzB;AACD,MAAM,WAAW,aAAa;IAC7B,OAAO,EAAE,GAAG,CAAA;IACZ,gBAAgB,EAAE,UAAU,CAAA;IAC5B,IAAI,EAAE,GAAG,CAAA;IACT,aAAa,EAAE,UAAU,CAAA;IACzB,IAAI,CAAC,EAAE,GAAG,CAAA;CACV;AACD,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,GAAG,EAAE,CAAA;CACX;AACD,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,GAAG,EAAE,CAAA;CACb;AACD,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG,eAAe,CAAA;AAGnE,MAAM,WAAW,MAAM;IACtB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,eAAe,CAAC,EAAE,OAAO,CAAA;IAEzB,EAAE,EAAE,UAAU,CAAA;IAEd,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,aAAa,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAGhC,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IAC5B,YAAY,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC/B,YAAY,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;CAC1C;AACD,MAAM,WAAW,aAAa;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,OAAO,CAAA;IAElB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,aAAa,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;CACrC;AACD,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,MAAM,CAE/C;AACD,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,aAAa,CAE7D;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,aAAa,CAAA;AAE9C,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GACV,MAAM,CAC/C"}
1
+ {"version":3,"file":"pubsub-types.d.ts","sourceRoot":"","sources":["../../src/pubsub/pubsub-types.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ import type { Applog, ApplogArrayMaybeEncryptedRO, ApplogArrayNoCIDMaybeEncrypte
3
3
  import { BlockStoreish } from '../ipfs/car';
4
4
  import { ApplogsOrThread, Thread } from '../thread';
5
5
  import type { AppAgent, IShare, SnapBlockChunks, SnapBlockLogsOrChunks } from './pubsub-types';
6
- export declare function prepareSnapshotForPush(agent: AppAgent, appThread: Thread, threadToPublish: ApplogsOrThread, share: IShare, prevSnapCID: CID | null): Promise<{
6
+ export declare function prepareSnapshotForPush(agent: AppAgent, appThread: Thread, threadToPublish: ApplogsOrThread, share: IShare, prevSnapCID: CID | null, prevCounter?: number): Promise<{
7
7
  cid: CID<any, 297, 18, 1>;
8
8
  blob: Blob;
9
9
  blocks: import("multiformats").BlockView<any, 297, 18, 1>[];
@@ -14,7 +14,7 @@ export declare function prepareSnapshotForPush(agent: AppAgent, appThread: Threa
14
14
  * @param applogs Encrypted or plain applogs
15
15
  * @returns Car file
16
16
  */
17
- export declare function encodeSnapshotAsCar(agent: AppAgent, applogs: ApplogArrayNoCIDMaybeEncryptedRO, infoLogs: readonly Applog[], prevSnapCID: CID | null): Promise<{
17
+ export declare function encodeSnapshotAsCar(agent: AppAgent, applogs: ApplogArrayNoCIDMaybeEncryptedRO, infoLogs: readonly Applog[], prevSnapCID: CID | null, prevCounter?: number): Promise<{
18
18
  cid: CID<any, 297, 18, 1>;
19
19
  blob: Blob;
20
20
  blocks: import("multiformats").BlockView<any, 297, 18, 1>[];
@@ -1 +1 @@
1
- {"version":3,"file":"snap-push.d.ts","sourceRoot":"","sources":["../../src/pubsub/snap-push.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAGtC,OAAO,KAAK,EACX,MAAM,EAEN,2BAA2B,EAC3B,gCAAgC,EAIhC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAA4C,MAAM,aAAa,CAAA;AAGrF,OAAO,EAAE,eAAe,EAAqB,MAAM,EAAE,MAAM,WAAW,CAAA;AAGtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAiB,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAe7G,wBAAsB,sBAAsB,CAC3C,KAAK,EAAE,QAAQ,EACf,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,GAAG,GAAG,IAAI;;;;;;GA+HvB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACxC,KAAK,EAAE,QAAQ,EACf,OAAO,EAAE,gCAAgC,EACzC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,WAAW,EAAE,GAAG,GAAG,IAAI;;;;;;GAgCvB;AAED,uEAAuE;AACvE,wBAAsB,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,SAAQ;;;;;;;;GAatF;AACD,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAYjH;AACD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,qBAAqB,GAAG,KAAK,IAAI,eAAe,CAExF;AACD;;;GAGG;AACH,wBAAsB,0BAA0B,CAC/C,OAAO,EAAE,2BAA2B,iBAUpC"}
1
+ {"version":3,"file":"snap-push.d.ts","sourceRoot":"","sources":["../../src/pubsub/snap-push.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAGtC,OAAO,KAAK,EACX,MAAM,EAEN,2BAA2B,EAC3B,gCAAgC,EAIhC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,aAAa,EAA4C,MAAM,aAAa,CAAA;AAGrF,OAAO,EAAE,eAAe,EAAqB,MAAM,EAAE,MAAM,WAAW,CAAA;AAGtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAiB,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAe7G,wBAAsB,sBAAsB,CAC3C,KAAK,EAAE,QAAQ,EACf,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,GAAG,GAAG,IAAI,EACvB,WAAW,CAAC,EAAE,MAAM;;;;;;GA+HpB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACxC,KAAK,EAAE,QAAQ,EACf,OAAO,EAAE,gCAAgC,EACzC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,WAAW,EAAE,GAAG,GAAG,IAAI,EACvB,WAAW,CAAC,EAAE,MAAM;;;;;;GAiCpB;AAED,uEAAuE;AACvE,wBAAsB,YAAY,CAAC,UAAU,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,SAAQ;;;;;;;;GAatF;AACD,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAYjH;AACD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,qBAAqB,GAAG,KAAK,IAAI,eAAe,CAExF;AACD;;;GAGG;AACH,wBAAsB,0BAA0B,CAC/C,OAAO,EAAE,2BAA2B,iBAUpC"}
@@ -3,7 +3,7 @@ import {
3
3
  integratePub,
4
4
  isShare,
5
5
  isSubscription
6
- } from "./chunk-IIZCL4FQ.min.js";
6
+ } from "./chunk-DYHLKKOE.min.js";
7
7
  import {
8
8
  chunkApplogs,
9
9
  encodeSnapshotApplogsAsCar,
@@ -11,10 +11,10 @@ import {
11
11
  isSnapBlockChunks,
12
12
  prepareSnapshotForPush,
13
13
  unchunkApplogsBlock
14
- } from "./chunk-C22YMCSL.min.js";
14
+ } from "./chunk-3HHBRM32.min.js";
15
15
  import "./chunk-QPGEBDMJ.min.js";
16
- import "./chunk-AIITTHC6.min.js";
17
- import "./chunk-MPOFY7NX.min.js";
16
+ import "./chunk-UJMWWDG4.min.js";
17
+ import "./chunk-CZTDDXGE.min.js";
18
18
  import "./chunk-HYMC7W6S.min.js";
19
19
  import "./chunk-KEHU7HGZ.min.js";
20
20
  import "./chunk-PHITDXZT.min.js";
package/dist/query.min.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  includedIn,
3
3
  includes,
4
4
  queryDivergencesByPrev
5
- } from "./chunk-IFB3AKYA.min.js";
5
+ } from "./chunk-NDHTR5QC.min.js";
6
6
  import {
7
7
  QueryNode,
8
8
  QueryResult,
@@ -29,7 +29,7 @@ import {
29
29
  throwOnTimeout,
30
30
  withTimeout,
31
31
  withoutDeleted
32
- } from "./chunk-AIITTHC6.min.js";
32
+ } from "./chunk-UJMWWDG4.min.js";
33
33
  import {
34
34
  applogThreadComparer,
35
35
  autorunButAlsoImmediately,
@@ -45,7 +45,7 @@ import {
45
45
  prettifyThreadName,
46
46
  queryNodesComparer,
47
47
  rootsQueries
48
- } from "./chunk-MPOFY7NX.min.js";
48
+ } from "./chunk-CZTDDXGE.min.js";
49
49
  import "./chunk-HYMC7W6S.min.js";
50
50
  import "./chunk-KEHU7HGZ.min.js";
51
51
  import "./chunk-PHITDXZT.min.js";
@@ -20,6 +20,8 @@ export interface BlockRetriever {
20
20
  export interface UpdateOptions {
21
21
  /** CID of last included snapshot - exclude this and older snapshots */
22
22
  excludeSnapshotCID?: CID;
23
+ /** Stop when we reach this counter (walking backwards) */
24
+ stopAtCounter?: number;
23
25
  /** Maximum number of snapshots to traverse (default: 100) */
24
26
  maxDepth?: number;
25
27
  }
@@ -35,6 +37,11 @@ export interface UpdateResult {
35
37
  insertedCount: number;
36
38
  /** Number of snapshots traversed */
37
39
  snapshotCount: number;
40
+ /** Counter range encountered (min/max) */
41
+ counterRange?: {
42
+ minCounter: number;
43
+ maxCounter: number;
44
+ };
38
45
  }
39
46
  /**
40
47
  * Fetch snapshot chain from CID using a BlockRetriever, decode applogs, insert into thread.
@@ -1 +1 @@
1
- {"version":3,"file":"update-thread.d.ts","sourceRoot":"","sources":["../../src/retrieve/update-thread.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAKnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAI1D;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,8BAA8B;IAC9B,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IACvC,sEAAsE;IACtE,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,aAAa,CAAC;QAAE,GAAG,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC,CAAA;CAChE;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,GAAG,CAAA;IACxB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,gCAAgC;IAChC,GAAG,EAAE,GAAG,CAAA;IACR,yCAAyC;IACzC,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAA;IACrB,oCAAoC;IACpC,aAAa,EAAE,MAAM,CAAA;CACrB;AA4BD;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC7C,MAAM,EAAE,eAAe,EACvB,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,cAAc,EACzB,OAAO,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CA2GvB"}
1
+ {"version":3,"file":"update-thread.d.ts","sourceRoot":"","sources":["../../src/retrieve/update-thread.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAKnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAI1D;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,8BAA8B;IAC9B,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IACvC,sEAAsE;IACtE,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,aAAa,CAAC;QAAE,GAAG,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC,CAAA;CAChE;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,GAAG,CAAA;IACxB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,gCAAgC;IAChC,GAAG,EAAE,GAAG,CAAA;IACR,yCAAyC;IACzC,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAA;IACrB,oCAAoC;IACpC,aAAa,EAAE,MAAM,CAAA;IACrB,0CAA0C;IAC1C,YAAY,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;CACzD;AA4BD;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC7C,MAAM,EAAE,eAAe,EACvB,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,cAAc,EACzB,OAAO,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,YAAY,CAAC,CAqIvB"}
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  updateThreadFromSnapshot
3
- } from "./chunk-TPV3JAXV.min.js";
4
- import "./chunk-C22YMCSL.min.js";
3
+ } from "./chunk-W477A74Z.min.js";
4
+ import "./chunk-3HHBRM32.min.js";
5
5
  import "./chunk-QPGEBDMJ.min.js";
6
- import "./chunk-AIITTHC6.min.js";
7
- import "./chunk-MPOFY7NX.min.js";
6
+ import "./chunk-UJMWWDG4.min.js";
7
+ import "./chunk-CZTDDXGE.min.js";
8
8
  import "./chunk-HYMC7W6S.min.js";
9
9
  import "./chunk-KEHU7HGZ.min.js";
10
10
  import "./chunk-PHITDXZT.min.js";
@@ -23,7 +23,7 @@ import {
23
23
  rollingFilter,
24
24
  rollingMapper,
25
25
  simpleApplogMapper
26
- } from "./chunk-MPOFY7NX.min.js";
26
+ } from "./chunk-CZTDDXGE.min.js";
27
27
  import "./chunk-HYMC7W6S.min.js";
28
28
  import "./chunk-KEHU7HGZ.min.js";
29
29
  import "./chunk-PHITDXZT.min.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wovin/core",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "type": "module",
5
5
  "main": "./dist/index.min.js",
6
6
  "module": "./dist/index.min.js",
@@ -90,6 +90,7 @@
90
90
  "url": "git+https://gitlab.com/wovin/wovin.git",
91
91
  "directory": "packages/@wovin/core"
92
92
  },
93
+ "license": "AGPL-3.0-or-later",
93
94
  "scripts": {
94
95
  "build": "rm -rf dist/ && concurrently \"pnpm build:code\" \"pnpm build:types\"",
95
96
  "build:code": "tsup --external esbuild",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ipfs/fetch-snapshot-chain.ts"],"sourcesContent":["import { CarReader } from '@ipld/car'\nimport * as dagJson from '@ipld/dag-json'\nimport { Logger } from 'besonders-logger'\nimport { CID } from 'multiformats/cid'\nimport type { SnapRootBlock } from '../pubsub/pubsub-types'\nimport { areCidsEqual } from './ipfs-utils'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport interface BlockStoreForFetch {\n get(cid: CID): Promise<Uint8Array | undefined>\n put(cid: CID, bytes: Uint8Array): Promise<void>\n}\n\nexport interface FetchChainOptions {\n rootCID: CID\n stopAtCID?: CID // Stop when we hit this CID (lastCID from subscription)\n fetchBlock: (cid: CID) => Promise<CarReader> // dag-scope=block\n fetchAll: (cid: CID) => Promise<CarReader> // dag-scope=all\n maxDepth?: number\n}\n\nexport interface FetchChainResult {\n rootCID: CID\n blockStore: BlockStoreForFetch\n /** Serializable blocks array for worker boundary crossing */\n blocks: [string, Uint8Array][]\n snapshotCount: number\n}\n\n/**\n * Fetches a snapshot chain iteratively, stopping at stopAtCID.\n * Uses 3 requests per snapshot: root(block), applogs(all), info(all).\n * This avoids the gateway's dag-scope=all following prev links recursively.\n */\nexport async function fetchSnapshotChainUntil(options: FetchChainOptions): Promise<FetchChainResult> {\n const { rootCID, stopAtCID, fetchBlock, fetchAll, maxDepth = 100 } = options\n const blockStore = createMemoryBlockStore()\n const visited = new Set<string>() // Loop detection for fetch\n let currentCID: CID | undefined = rootCID\n let snapshotCount = 0\n\n while (currentCID && snapshotCount < maxDepth) {\n const cidStr = currentCID.toString()\n\n // Loop detection\n if (visited.has(cidStr)) {\n throw ERROR('[fetchSnapshotChain] snapshot chain has a loop', { currentCID: cidStr, visited: [...visited] })\n }\n visited.add(cidStr)\n\n // Check stop condition BEFORE fetching content\n if (stopAtCID && areCidsEqual(currentCID, stopAtCID)) {\n DEBUG('[fetchSnapshotChain] reached stopAtCID, stopping', stopAtCID.toString())\n break // We've reached the last pulled snapshot - don't fetch it again\n }\n\n // 1. Fetch root block only (dag-scope=block)\n DEBUG('[fetchSnapshotChain] fetching root block', cidStr)\n const rootCar = await fetchBlock(currentCID)\n await addCarBlocksToStore(rootCar, blockStore)\n\n // Parse root to get applogs, info, prev CIDs\n const rootBytes = await blockStore.get(currentCID)\n if (!rootBytes) {\n throw ERROR('[fetchSnapshotChain] root block not in store after fetch', { currentCID: cidStr })\n }\n const root = dagJson.decode(rootBytes) as SnapRootBlock\n\n // 2. Fetch applogs with dag-scope=all (gets applogs block + all linked applog blocks)\n DEBUG('[fetchSnapshotChain] fetching applogs', root.applogs.toString())\n const applogsCar = await fetchAll(root.applogs)\n await addCarBlocksToStore(applogsCar, blockStore)\n\n // 3. Fetch info with dag-scope=all (gets info block + all linked info log blocks)\n DEBUG('[fetchSnapshotChain] fetching info', root.info.toString())\n const infoCar = await fetchAll(root.info)\n await addCarBlocksToStore(infoCar, blockStore)\n\n snapshotCount++\n currentCID = root.prev // Move to previous snapshot\n }\n\n DEBUG('[fetchSnapshotChain] done', { snapshotCount, rootCID: rootCID.toString() })\n return { rootCID, blockStore, blocks: blockStore.getBlocksArray(), snapshotCount }\n}\n\nasync function addCarBlocksToStore(car: CarReader, store: BlockStoreForFetch) {\n for await (const { cid, bytes } of car.blocks()) {\n const validCid = typeof cid.toV1 === 'function' ? cid : CID.decode(cid.bytes)\n await store.put(validCid, bytes)\n }\n}\n\ninterface MemoryBlockStoreWithBlocks extends BlockStoreForFetch {\n /** Get all blocks as serializable array */\n getBlocksArray(): [string, Uint8Array][]\n}\n\nfunction createMemoryBlockStore(): MemoryBlockStoreWithBlocks {\n const blocks = new Map<string, Uint8Array>()\n return {\n async get(cid: CID) {\n return blocks.get(cid.toV1().toString())\n },\n async put(cid: CID, bytes: Uint8Array) {\n blocks.set(cid.toV1().toString(), bytes)\n },\n getBlocksArray() {\n return Array.from(blocks.entries())\n },\n }\n}\n"],"mappings":";;;;;;;;AAOA,IAAM,EAAE,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,EAAO,MAAM,EAAO,IAAI;AA4BrE,eAAsB,wBAAwB,SAAuD;AACjG,QAAM,EAAE,SAAS,WAAW,YAAY,UAAU,WAAW,IAAI,IAAI;AACrE,QAAM,aAAa,uBAAuB;AAC1C,QAAM,UAAU,oBAAI,IAAY;AAChC,MAAI,aAA8B;AAClC,MAAI,gBAAgB;AAEpB,SAAO,cAAc,gBAAgB,UAAU;AAC3C,UAAM,SAAS,WAAW,SAAS;AAGnC,QAAI,QAAQ,IAAI,MAAM,GAAG;AACrB,YAAM,MAAM,kDAAkD,EAAE,YAAY,QAAQ,SAAS,CAAC,GAAG,OAAO,EAAE,CAAC;AAAA,IAC/G;AACA,YAAQ,IAAI,MAAM;AAGlB,QAAI,aAAa,aAAa,YAAY,SAAS,GAAG;AAClD,YAAM,oDAAoD,UAAU,SAAS,CAAC;AAC9E;AAAA,IACJ;AAGA,UAAM,4CAA4C,MAAM;AACxD,UAAM,UAAU,MAAM,WAAW,UAAU;AAC3C,UAAM,oBAAoB,SAAS,UAAU;AAG7C,UAAM,YAAY,MAAM,WAAW,IAAI,UAAU;AACjD,QAAI,CAAC,WAAW;AACZ,YAAM,MAAM,4DAA4D,EAAE,YAAY,OAAO,CAAC;AAAA,IAClG;AACA,UAAM,OAAe,OAAO,SAAS;AAGrC,UAAM,yCAAyC,KAAK,QAAQ,SAAS,CAAC;AACtE,UAAM,aAAa,MAAM,SAAS,KAAK,OAAO;AAC9C,UAAM,oBAAoB,YAAY,UAAU;AAGhD,UAAM,sCAAsC,KAAK,KAAK,SAAS,CAAC;AAChE,UAAM,UAAU,MAAM,SAAS,KAAK,IAAI;AACxC,UAAM,oBAAoB,SAAS,UAAU;AAE7C;AACA,iBAAa,KAAK;AAAA,EACtB;AAEA,QAAM,6BAA6B,EAAE,eAAe,SAAS,QAAQ,SAAS,EAAE,CAAC;AACjF,SAAO,EAAE,SAAS,YAAY,QAAQ,WAAW,eAAe,GAAG,cAAc;AACrF;AAEA,eAAe,oBAAoB,KAAgB,OAA2B;AAC1E,mBAAiB,EAAE,KAAK,MAAM,KAAK,IAAI,OAAO,GAAG;AAC7C,UAAM,WAAW,OAAO,IAAI,SAAS,aAAa,MAAM,IAAI,OAAO,IAAI,KAAK;AAC5E,UAAM,MAAM,IAAI,UAAU,KAAK;AAAA,EACnC;AACJ;AAOA,SAAS,yBAAqD;AAC1D,QAAM,SAAS,oBAAI,IAAwB;AAC3C,SAAO;AAAA,IACH,MAAM,IAAI,KAAU;AAChB,aAAO,OAAO,IAAI,IAAI,KAAK,EAAE,SAAS,CAAC;AAAA,IAC3C;AAAA,IACA,MAAM,IAAI,KAAU,OAAmB;AACnC,aAAO,IAAI,IAAI,KAAK,EAAE,SAAS,GAAG,KAAK;AAAA,IAC3C;AAAA,IACA,iBAAiB;AACb,aAAO,MAAM,KAAK,OAAO,QAAQ,CAAC;AAAA,IACtC;AAAA,EACJ;AACJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/pubsub/pub-pull.ts","../src/pubsub/pubsub-types.ts"],"sourcesContent":["import { Logger } from 'besonders-logger'\nimport { CID } from 'multiformats'\nimport { ensureTsPvAndFinalizeApplog } from '../applog/applog-helpers'\nimport { EntityID } from '../applog/datom-types'\nimport { Thread } from '../thread'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport type PubPullData = {\n\tcid: CID\n\tthread: Thread\n}\n\nexport function integratePub({ targetThread, agentHash, subID, pubData }: {\n\ttargetThread: Thread\n\tagentHash: EntityID\n\tpubData: PubPullData\n\tsubID?: EntityID\n}) {\n\tconst newLogs = pubData.thread.applogs.filter(log => !targetThread.hasApplog(log, false))\n\tDEBUG(`[integratePub] integrating ${newLogs.length} logs`, { targetThread, subID, pubData })\n\tlet toInsert = newLogs\n\tif (subID) {\n\t\ttoInsert = toInsert.concat(ensureTsPvAndFinalizeApplog(\n\t\t\t{ en: subID, at: 'subscription/cid', vl: pubData.cid.toString(), ag: agentHash },\n\t\t\ttargetThread,\n\t\t))\n\t}\n\ttargetThread.insertRaw(toInsert)\n\treturn newLogs\n}\n","import { CID } from 'multiformats/cid'\nimport { cyrb53hash } from './../applog/applog-utils'\nimport { AgentHash, AgentID, CidString } from '../applog/datom-types'\nimport { Tagged } from '../types'\nimport { UCANCapMap } from './ucan'\ntype AgentString = Tagged<string, 'AgentString'>\ntype DIDString = Tagged<string, 'DID'>\nexport type { AgentHash, AgentString, DIDString }\n\n\nexport interface AppAgent {\n\tag: AgentHash\n\tagentString: AgentString\n\tdid: DIDString\n\tsign? (data: Uint8Array): Promise<Uint8Array>\n\tucan?: UCANCapMap\n}\nexport interface AppAgentForWorker extends AppAgent {\n\tsignerSecret?: Uint8Array\n}\nexport interface SnapRootBlock {\n\tapplogs: CID\n\tapplogsSignature: Uint8Array\n\tinfo: CID\n\tinfoSignature: Uint8Array\n\tprev?: CID\n}\nexport interface SnapBlockLogs {\n\tlogs: CID[]\n}\nexport interface SnapBlockChunks {\n\tchunks: CID[]\n}\nexport type SnapBlockLogsOrChunks = SnapBlockLogs | SnapBlockChunks\n\n// HACK: this is actually note3 types, not wovin\nexport interface IShare {\n\tid?: string // string hash of pub (used as unique id in IDB) `W3Name.create().toString()` starts with k51qzi5uqu5d\n\tcreatedAt: string // ISO timestamp of creation\n\tname: string // nick name for the pub\n\tisDeleted?: boolean\n\tpurgeBeforePush?: boolean\n\n\tpk: Uint8Array // exported privatekey - needed to create WritableName for publishing //TODO: store as non-extractable / encrypted?\n\n\tautopush: boolean\n\tlastPush: string | null\n\tlastCID?: string\n\tlatestLogTs?: string\n\tpubCounter?: number\n\n\tpublishedBy: string // local user appAgent\n\tselectors?: string[] // to be used as a filter for which applogs to pub\n\tencryptedFor?: string | null // short agentHash\n\tencryptedWith?: CryptoKey | null // AES-GCM derived key from ECDH keys (local private and remote public)\n\n\t// HACK WIP #39 - shared encryption\n\tsharedKey?: CryptoKey | null // AES-GCM derived key from ECDH keys (local private and ipns public)\n\tsharedAgents?: AgentID[] | null // array of string EntityIDs for the chosen agents (we need public jwkd atoms for each of them)\n\tsharedKeyMap?: Map<AgentID, string> | null // uses public key from each agent to derive an aes key that is used to encrypt and btoa the sharedKey that is actually used to encrypt and decrypt the applogs\n}\nexport interface ISubscription {\n\tid: string // string hash of pub (used as unique id in IDB) `W3Name.create().toString()` starts with k51qzi5uqu5d\n\tcreatedAt: string // ISO timestamp of creation\n\tname: string // nick name for the pub\n\tisDeleted: boolean\n\n\tlastPull?: string | null\n\tlastPullAttempt?: string | null\n\tautopull: boolean\n\trealtime?: boolean // enable real-time WebSocket updates via IPNS watcher\n\tlastCID?: string // ? why not CidString\n\tlastApplogCID?: string\n\tpublishedBy?: string // remote publisher short agentHash\n\tencryptedFor?: string | undefined // short agentHash\n\tencryptedWith?: CryptoKey | undefined // AES-GCM derived key from ECDH keys (local private and remote public)\n}\nexport function isShare(obj: any): obj is IShare {\n\treturn obj?.pk !== undefined && obj?.lastPush !== undefined\n}\nexport function isSubscription(obj: any): obj is ISubscription {\n\treturn obj?.lastPull !== undefined\n}\n\nexport type TShareSub = IShare | ISubscription\n\nexport function agentToShortHash(agentString: string) {\n\treturn cyrb53hash(agentString, 31, 7) as string\n}\n"],"mappings":";;;;;;;AAMA,IAAM,EAAE,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,EAAO,MAAM,EAAO,IAAI;AAO9D,SAAS,aAAa,EAAE,cAAc,WAAW,OAAO,QAAQ,GAKpE;AACF,QAAM,UAAU,QAAQ,OAAO,QAAQ,OAAO,SAAO,CAAC,aAAa,UAAU,KAAK,KAAK,CAAC;AACxF,QAAM,8BAA8B,QAAQ,MAAM,SAAS,EAAE,cAAc,OAAO,QAAQ,CAAC;AAC3F,MAAI,WAAW;AACf,MAAI,OAAO;AACV,eAAW,SAAS,OAAO;AAAA,MAC1B,EAAE,IAAI,OAAO,IAAI,oBAAoB,IAAI,QAAQ,IAAI,SAAS,GAAG,IAAI,UAAU;AAAA,MAC/E;AAAA,IACD,CAAC;AAAA,EACF;AACA,eAAa,UAAU,QAAQ;AAC/B,SAAO;AACR;;;AC+CO,SAAS,QAAQ,KAAyB;AAChD,SAAO,KAAK,OAAO,UAAa,KAAK,aAAa;AACnD;AACO,SAAS,eAAe,KAAgC;AAC9D,SAAO,KAAK,aAAa;AAC1B;AAIO,SAAS,iBAAiB,aAAqB;AACrD,SAAO,WAAW,aAAa,IAAI,CAAC;AACrC;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/retrieve/update-thread.ts"],"sourcesContent":["import { CarReader } from '@ipld/car'\nimport * as dagJson from '@ipld/dag-json'\nimport { Logger } from 'besonders-logger'\nimport { CID } from 'multiformats/cid'\nimport type { Applog } from '../applog/datom-types'\nimport { removeDuplicateAppLogs } from '../applog/applog-utils'\nimport type { SnapRootBlock, SnapBlockLogsOrChunks } from '../pubsub/pubsub-types'\nimport { unchunkApplogsBlock } from '../pubsub/snap-push'\nimport { areCidsEqual } from '../ipfs/ipfs-utils'\nimport type { WriteableThread } from '../thread/writeable'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\n/**\n * Block retrieval abstraction - fetch or get blocks.\n * Implemented by gateway retriever or local blockstore.\n */\nexport interface BlockRetriever {\n\t/** Get single block by CID */\n\tgetBlock(cid: CID): Promise<Uint8Array>\n\t/** Get all blocks in DAG rooted at CID (for applogs/info sub-DAGs) */\n\tgetDag(cid: CID): AsyncIterable<{ cid: CID; bytes: Uint8Array }>\n}\n\n/**\n * Options for updateThreadFromSnapshot\n */\nexport interface UpdateOptions {\n\t/** CID of last included snapshot - exclude this and older snapshots */\n\texcludeSnapshotCID?: CID\n\t/** Maximum number of snapshots to traverse (default: 100) */\n\tmaxDepth?: number\n}\n\n/**\n * Result from updateThreadFromSnapshot\n */\nexport interface UpdateResult {\n\t/** Root CID that was fetched */\n\tcid: CID\n\t/** All applogs decoded from the chain */\n\tapplogs: Applog[]\n\t/** Count of applogs actually inserted (not duplicates) */\n\tinsertedCount: number\n\t/** Number of snapshots traversed */\n\tsnapshotCount: number\n}\n\n/**\n * Simple in-memory block store used during snapshot chain fetch.\n */\ninterface MemoryBlockStore {\n\tget(cid: CID): Uint8Array | undefined\n\tput(cid: CID, bytes: Uint8Array): void\n}\n\nfunction createMemoryBlockStore(): MemoryBlockStore {\n\tconst blocks = new Map<string, Uint8Array>()\n\treturn {\n\t\tget(cid: CID) {\n\t\t\treturn blocks.get(cid.toV1().toString())\n\t\t},\n\t\tput(cid: CID, bytes: Uint8Array) {\n\t\t\tblocks.set(cid.toV1().toString(), bytes)\n\t\t},\n\t}\n}\n\nasync function getDecodedBlock<T>(blockStore: MemoryBlockStore, cid: CID): Promise<T | null> {\n\tconst bytes = blockStore.get(cid)\n\tif (!bytes) return null\n\treturn dagJson.decode(bytes) as T\n}\n\n/**\n * Fetch snapshot chain from CID using a BlockRetriever, decode applogs, insert into thread.\n * Stops before excludeSnapshotCID if provided (incremental update).\n *\n * @param thread - WriteableThread to insert applogs into\n * @param cid - Root CID of the snapshot to start from\n * @param retriever - BlockRetriever for fetching blocks\n * @param options - Optional configuration\n * @returns UpdateResult with applogs and counts\n */\nexport async function updateThreadFromSnapshot(\n\tthread: WriteableThread,\n\tcid: CID,\n\tretriever: BlockRetriever,\n\toptions?: UpdateOptions\n): Promise<UpdateResult> {\n\tconst { excludeSnapshotCID, maxDepth = 100 } = options ?? {}\n\n\tDEBUG('[updateThreadFromSnapshot] starting from', cid.toString(), {\n\t\texcludeSnapshotCID: excludeSnapshotCID?.toString(),\n\t\tmaxDepth,\n\t})\n\n\tconst blockStore = createMemoryBlockStore()\n\tconst visited = new Set<string>()\n\tlet currentCID: CID | undefined = cid\n\tlet snapshotCount = 0\n\tconst allApplogs: Applog[] = []\n\n\twhile (currentCID && snapshotCount < maxDepth) {\n\t\tconst cidStr = currentCID.toString()\n\n\t\t// Loop detection\n\t\tif (visited.has(cidStr)) {\n\t\t\tthrow ERROR('[updateThreadFromSnapshot] snapshot chain has a loop', {\n\t\t\t\tcurrentCID: cidStr,\n\t\t\t\tvisited: [...visited],\n\t\t\t})\n\t\t}\n\t\tvisited.add(cidStr)\n\n\t\t// Check stop condition BEFORE fetching content\n\t\tif (excludeSnapshotCID && areCidsEqual(currentCID, excludeSnapshotCID)) {\n\t\t\tDEBUG('[updateThreadFromSnapshot] reached excludeSnapshotCID, stopping', excludeSnapshotCID.toString())\n\t\t\tbreak\n\t\t}\n\n\t\t// 1. Fetch root block\n\t\tDEBUG('[updateThreadFromSnapshot] fetching root block', cidStr)\n\t\tconst rootBytes = await retriever.getBlock(currentCID)\n\t\tblockStore.put(currentCID, rootBytes)\n\n\t\t// Parse root to get applogs, info, prev CIDs\n\t\tconst root = dagJson.decode(rootBytes) as SnapRootBlock\n\n\t\t// 2. Fetch applogs DAG\n\t\tDEBUG('[updateThreadFromSnapshot] fetching applogs', root.applogs.toString())\n\t\tfor await (const { cid: blockCid, bytes } of retriever.getDag(root.applogs)) {\n\t\t\tblockStore.put(blockCid, bytes)\n\t\t}\n\n\t\t// 3. Fetch info DAG\n\t\tDEBUG('[updateThreadFromSnapshot] fetching info', root.info.toString())\n\t\tfor await (const { cid: blockCid, bytes } of retriever.getDag(root.info)) {\n\t\t\tblockStore.put(blockCid, bytes)\n\t\t}\n\n\t\t// Decode applogs from this snapshot\n\t\tconst applogsBlock = await getDecodedBlock<SnapBlockLogsOrChunks>(blockStore, root.applogs)\n\t\tif (!applogsBlock) {\n\t\t\tthrow ERROR('[updateThreadFromSnapshot] applogs block not found', { cid: root.applogs.toString() })\n\t\t}\n\n\t\t// Use the unchunk helper which handles both chunked and non-chunked formats\n\t\tconst applogCIDs = await unchunkApplogsBlock(applogsBlock, {\n\t\t\tget: async (cid: CID) => blockStore.get(cid)!,\n\t\t})\n\n\t\t// Resolve each applog CID to actual applog data\n\t\tfor (const applogCID of applogCIDs) {\n\t\t\tconst applog = await getDecodedBlock<Applog>(blockStore, applogCID)\n\t\t\tif (!applog) {\n\t\t\t\tWARN('[updateThreadFromSnapshot] applog not found:', applogCID.toString())\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Normalize pv field if it's a CID instance\n\t\t\tif ((applog.pv as any) instanceof CID) {\n\t\t\t\tapplog.pv = (applog.pv as any as CID).toV1().toString()\n\t\t\t}\n\t\t\tallApplogs.push({\n\t\t\t\t...applog,\n\t\t\t\tcid: applogCID.toV1().toString(),\n\t\t\t})\n\t\t}\n\n\t\tsnapshotCount++\n\t\tcurrentCID = root.prev // Move to previous snapshot\n\t}\n\n\tDEBUG('[updateThreadFromSnapshot] fetched', {\n\t\tsnapshotCount,\n\t\tapplogCount: allApplogs.length,\n\t\trootCID: cid.toString(),\n\t})\n\n\t// Deduplicate applogs (in case of overlapping snapshots)\n\tconst deduplicated = removeDuplicateAppLogs(allApplogs, 'cleanup')\n\n\t// Insert into thread\n\tconst inserted = thread.insertMissing(deduplicated, false)\n\n\tDEBUG('[updateThreadFromSnapshot] inserted', {\n\t\tinsertedCount: inserted.length,\n\t\tduplicateCount: deduplicated.length - inserted.length,\n\t})\n\n\treturn {\n\t\tcid,\n\t\tapplogs: deduplicated,\n\t\tinsertedCount: inserted.length,\n\t\tsnapshotCount,\n\t}\n}\n"],"mappings":"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","names":["cid"]}