@wovin/core 0.1.36 → 0.2.2
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.
- package/README.md +0 -12
- package/dist/applog/applog-helpers.d.ts +12 -12
- package/dist/applog/applog-helpers.d.ts.map +1 -1
- package/dist/applog/applog-utils.d.ts +40 -6
- package/dist/applog/applog-utils.d.ts.map +1 -1
- package/dist/applog/datom-types.d.ts +67 -12
- package/dist/applog/datom-types.d.ts.map +1 -1
- package/dist/applog.d.ts +3 -3
- package/dist/applog.d.ts.map +1 -1
- package/dist/{applog.min.js → applog.js} +12 -7
- package/dist/blockstore.d.ts +1 -1
- package/dist/blockstore.d.ts.map +1 -1
- package/dist/{blockstore.min.js → blockstore.js} +1 -3
- package/dist/{blockstore.min.js.map → blockstore.js.map} +1 -1
- package/dist/chunk-22WDFLXO.js +138 -0
- package/dist/chunk-22WDFLXO.js.map +1 -0
- package/dist/chunk-3SUFNJEZ.js +1026 -0
- package/dist/chunk-3SUFNJEZ.js.map +1 -0
- package/dist/chunk-6ALNRM3J.js +435 -0
- package/dist/chunk-6ALNRM3J.js.map +1 -0
- package/dist/chunk-7Z5YDQKK.js +1 -0
- package/dist/{chunk-KXMTKPF4.min.js → chunk-BLF5MAWU.js} +8 -8
- package/dist/chunk-BLF5MAWU.js.map +1 -0
- package/dist/chunk-E46VTKTZ.js +1 -0
- package/dist/{chunk-H3VQJP56.min.js → chunk-HUIQ54TT.js} +9 -9
- package/dist/chunk-HUIQ54TT.js.map +1 -0
- package/dist/{chunk-BRC7LSM6.min.js → chunk-OC6Z6CQW.js} +5 -5
- package/dist/chunk-OC6Z6CQW.js.map +1 -0
- package/dist/chunk-SHUHRHOT.js +1923 -0
- package/dist/chunk-SHUHRHOT.js.map +1 -0
- package/dist/{chunk-QPGEBDMJ.min.js → chunk-YDAKBU6Q.js} +1 -1
- package/dist/chunk-YDAKBU6Q.js.map +1 -0
- package/dist/chunk-ZAADLBSB.js +36 -0
- package/dist/chunk-ZAADLBSB.js.map +1 -0
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/{index.min.js → index.js} +81 -46
- package/dist/ipfs/car.d.ts +11 -11
- package/dist/ipfs/car.d.ts.map +1 -1
- package/dist/ipfs/ipfs-utils.d.ts +2 -2
- package/dist/ipfs/ipfs-utils.d.ts.map +1 -1
- package/dist/ipfs.d.ts +3 -3
- package/dist/ipfs.d.ts.map +1 -1
- package/dist/{ipfs.min.js → ipfs.js} +7 -10
- package/dist/ipns.d.ts +1 -1
- package/dist/ipns.d.ts.map +1 -1
- package/dist/ipns.js +64 -0
- package/dist/ipns.js.map +1 -0
- package/dist/pubsub/pub-pull.d.ts +3 -3
- package/dist/pubsub/pub-pull.d.ts.map +1 -1
- package/dist/pubsub/pubsub-types.d.ts +3 -3
- package/dist/pubsub/pubsub-types.d.ts.map +1 -1
- package/dist/pubsub/snap-push.d.ts +4 -4
- package/dist/pubsub/snap-push.d.ts.map +1 -1
- package/dist/pubsub/ucan.d.ts +1 -1
- package/dist/pubsub/ucan.d.ts.map +1 -1
- package/dist/pubsub.d.ts +4 -4
- package/dist/pubsub.d.ts.map +1 -1
- package/dist/{pubsub.min.js → pubsub.js} +7 -10
- package/dist/query/attr-helpers.d.ts +5 -0
- package/dist/query/attr-helpers.d.ts.map +1 -0
- package/dist/query/basic.d.ts +87 -23
- package/dist/query/basic.d.ts.map +1 -1
- package/dist/query/divergences.d.ts +5 -5
- package/dist/query/divergences.d.ts.map +1 -1
- package/dist/query/entity-collection.d.ts +19 -0
- package/dist/query/entity-collection.d.ts.map +1 -0
- package/dist/query/matchers.d.ts +12 -1
- package/dist/query/matchers.d.ts.map +1 -1
- package/dist/query/memoized.d.ts +66 -0
- package/dist/query/memoized.d.ts.map +1 -0
- package/dist/query/situations.d.ts +2 -1
- package/dist/query/situations.d.ts.map +1 -1
- package/dist/query/subscribable.d.ts +111 -0
- package/dist/query/subscribable.d.ts.map +1 -0
- package/dist/query/types.d.ts +54 -14
- package/dist/query/types.d.ts.map +1 -1
- package/dist/query.d.ts +9 -5
- package/dist/query.d.ts.map +1 -1
- package/dist/{query.min.js → query.js} +55 -34
- package/dist/retrieve/index.d.ts +1 -1
- package/dist/retrieve/index.d.ts.map +1 -1
- package/dist/retrieve/update-thread.d.ts +3 -3
- package/dist/retrieve/update-thread.d.ts.map +1 -1
- package/dist/retrieve.d.ts +1 -1
- package/dist/retrieve.d.ts.map +1 -1
- package/dist/retrieve.js +14 -0
- package/dist/thread/basic.d.ts +15 -19
- package/dist/thread/basic.d.ts.map +1 -1
- package/dist/thread/filters.d.ts +8 -10
- package/dist/thread/filters.d.ts.map +1 -1
- package/dist/thread/indexes.d.ts +57 -0
- package/dist/thread/indexes.d.ts.map +1 -0
- package/dist/thread/mapped.d.ts +40 -11
- package/dist/thread/mapped.d.ts.map +1 -1
- package/dist/thread/utils.d.ts +5 -5
- package/dist/thread/utils.d.ts.map +1 -1
- package/dist/thread/writeable.d.ts +2 -2
- package/dist/thread/writeable.d.ts.map +1 -1
- package/dist/thread.d.ts +6 -5
- package/dist/thread.d.ts.map +1 -1
- package/dist/{thread.min.js → thread.js} +9 -6
- package/dist/types/typescript-utils.d.ts +6 -5
- package/dist/types/typescript-utils.d.ts.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/{types.min.js → types.js} +3 -4
- package/dist/utils/debug-name.d.ts +13 -0
- package/dist/utils/debug-name.d.ts.map +1 -0
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +9 -0
- package/package.json +32 -23
- package/src/applog/applog-helpers.ts +155 -0
- package/src/applog/applog-utils.test.ts +108 -0
- package/src/applog/applog-utils.ts +551 -0
- package/src/applog/datom-types.ts +167 -0
- package/src/applog/object-values.test.ts +106 -0
- package/src/applog.ts +3 -0
- package/src/blockstore/index.ts +36 -0
- package/src/blockstore.ts +1 -0
- package/src/index.ts +8 -0
- package/src/ipfs/car.ts +291 -0
- package/src/ipfs/fetch-snapshot-chain.ts +135 -0
- package/src/ipfs/ipfs-utils.ts +132 -0
- package/src/ipfs.ts +3 -0
- package/src/ipns/ipns-record.ts +115 -0
- package/src/ipns.ts +1 -0
- package/src/pubsub/UCAN Specs Overview.md +217 -0
- package/src/pubsub/connector.ts +9 -0
- package/src/pubsub/pub-pull.ts +31 -0
- package/src/pubsub/pubsub-types.ts +90 -0
- package/src/pubsub/snap-push.ts +278 -0
- package/src/pubsub/ucan-example.ts +61 -0
- package/src/pubsub/ucan.ts +56 -0
- package/src/pubsub.ts +4 -0
- package/src/query/attr-helpers.ts +5 -0
- package/src/query/basic.ts +1245 -0
- package/src/query/divergences.ts +50 -0
- package/src/query/entity-collection.ts +132 -0
- package/src/query/liveFilterAndMap.test.ts +102 -0
- package/src/query/matchers.ts +30 -0
- package/src/query/memoized.test.ts +151 -0
- package/src/query/memoized.ts +180 -0
- package/src/query/query-steps.ts +4 -0
- package/src/query/query.test.ts +538 -0
- package/src/query/situations.ts +261 -0
- package/src/query/subscribable.test.ts +245 -0
- package/src/query/subscribable.ts +234 -0
- package/src/query/types.ts +155 -0
- package/src/query/withoutDeleted.test.ts +204 -0
- package/src/query.ts +9 -0
- package/src/retrieve/index.ts +1 -0
- package/src/retrieve/update-thread.ts +248 -0
- package/src/retrieve.ts +1 -0
- package/src/test/perf/query.1m.perf.test.ts +94 -0
- package/src/test/perf/query.perf.test.ts +389 -0
- package/src/test/perf/query.realdata.perf.test.ts +182 -0
- package/src/thread/basic.ts +209 -0
- package/src/thread/filters.ts +227 -0
- package/src/thread/indexes.ts +256 -0
- package/src/thread/joinThreads.test.ts +304 -0
- package/src/thread/mapped.ts +226 -0
- package/src/thread/utils.ts +144 -0
- package/src/thread/writeable.ts +163 -0
- package/src/thread.ts +6 -0
- package/src/types/typescript-utils.ts +64 -0
- package/src/types.ts +1 -0
- package/src/utils/debug-name.ts +54 -0
- package/src/utils.ts +4 -0
- package/dist/chunk-2Y2PYHGR.min.js +0 -65
- package/dist/chunk-2Y2PYHGR.min.js.map +0 -1
- package/dist/chunk-5MMGBK2U.min.js +0 -1
- package/dist/chunk-7IDQIMQO.min.js +0 -1
- package/dist/chunk-BRC7LSM6.min.js.map +0 -1
- package/dist/chunk-COXXILXC.min.js +0 -512
- package/dist/chunk-COXXILXC.min.js.map +0 -1
- package/dist/chunk-GDX2OO7L.min.js +0 -9080
- package/dist/chunk-GDX2OO7L.min.js.map +0 -1
- package/dist/chunk-H3VQJP56.min.js.map +0 -1
- package/dist/chunk-HYMC7W6S.min.js +0 -1549
- package/dist/chunk-HYMC7W6S.min.js.map +0 -1
- package/dist/chunk-KEHU7HGZ.min.js +0 -5216
- package/dist/chunk-KEHU7HGZ.min.js.map +0 -1
- package/dist/chunk-KXMTKPF4.min.js.map +0 -1
- package/dist/chunk-PHITDXZT.min.js +0 -36
- package/dist/chunk-QO2KMGDN.min.js +0 -3771
- package/dist/chunk-QO2KMGDN.min.js.map +0 -1
- package/dist/chunk-QPGEBDMJ.min.js.map +0 -1
- package/dist/chunk-WXLCBTHX.min.js +0 -1606
- package/dist/chunk-WXLCBTHX.min.js.map +0 -1
- package/dist/ipns.min.js +0 -6419
- package/dist/ipns.min.js.map +0 -1
- package/dist/mobx/mobx-utils.d.ts +0 -82
- package/dist/mobx/mobx-utils.d.ts.map +0 -1
- package/dist/mobx.d.ts +0 -2
- package/dist/mobx.d.ts.map +0 -1
- package/dist/mobx.min.js +0 -141
- package/dist/retrieve.min.js +0 -17
- package/dist/types.min.js.map +0 -1
- package/dist/utils.min.js +0 -10
- package/dist/utils.min.js.map +0 -1
- /package/dist/{applog.min.js.map → applog.js.map} +0 -0
- /package/dist/{chunk-5MMGBK2U.min.js.map → chunk-7Z5YDQKK.js.map} +0 -0
- /package/dist/{chunk-7IDQIMQO.min.js.map → chunk-E46VTKTZ.js.map} +0 -0
- /package/dist/{chunk-PHITDXZT.min.js.map → index.js.map} +0 -0
- /package/dist/{index.min.js.map → ipfs.js.map} +0 -0
- /package/dist/{ipfs.min.js.map → pubsub.js.map} +0 -0
- /package/dist/{mobx.min.js.map → query.js.map} +0 -0
- /package/dist/{pubsub.min.js.map → retrieve.js.map} +0 -0
- /package/dist/{query.min.js.map → thread.js.map} +0 -0
- /package/dist/{retrieve.min.js.map → types.js.map} +0 -0
- /package/dist/{thread.min.js.map → utils.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pubsub/snap-push.ts","../src/ipfs/car.ts"],"sourcesContent":["import * as dagJson from '@ipld/dag-json'\nimport { Logger } from 'besonders-logger'\nimport { CID } from 'multiformats/cid'\nimport stringify from 'safe-stable-stringify'\nimport { ensureTsPvAndFinalizeApplog } from '../applog/applog-helpers.ts'\nimport type {\n\tApplog,\n\tApplogArrayMaybeEncrypted,\n\tApplogArrayMaybeEncryptedRO,\n\tApplogArrayNoCIDMaybeEncryptedRO,\n\tApplogEnc,\n\tApplogEncNoCid,\n\tCidString,\n} from '../applog/datom-types.ts'\nimport { BlockStoreish, DecodedCar, getDecodedBlock, makeCarBlob } from '../ipfs/car.ts'\nimport { encodeBlockOriginal, prepareForPub } from '../ipfs/ipfs-utils.ts'\nimport { lastWriteWins } from './../query/basic.ts'\nimport { anyOf } from '../query/matchers.ts'\nimport { ApplogsOrThread, getLogsFromThread, Thread } from '../thread.ts'\nimport { rollingFilter } from '../thread/filters.ts'\nimport { keepTruthy } from '../utils.ts'\nimport type { AppAgent, IShare, SnapBlockChunks, SnapBlockLogs, SnapBlockLogsOrChunks } from './pubsub-types.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\n// export const neverEncryptAttrs = [\n// \t'agent/jwkd',\n// \t'agent/appAgent',\n// \t'pub/encryptedFor',\n// \t'pub/sharedKey',\n// ]\n\n// export interface WovinPublicationInfo {\n// \tid: string\n// }\n\nexport async function prepareSnapshotForPush(\n\tagent: AppAgent,\n\tappThread: Thread,\n\tthreadToPublish: ApplogsOrThread,\n\tshare: IShare,\n\tprevSnapCID: CID | null,\n\tprevCounter: number | null,\n) {\n\tif (prevCounter !== null && !prevSnapCID) {\n\t\tthrow ERROR('[prepareSnapshotForPush] prevCounter provided without prevSnapCID')\n\t}\n\t// TODO prevent publish if there is no new info\n\tlet logsToPublish = getLogsFromThread(threadToPublish)\n\n\t// const logsFromLastPush = await getLogsFromPub(publication)\n\t// logsToPublish = logsToPublish.filter(eachLog => !logsFromLastPush.includes(eachLog.cid)) // TODO deep compare includes\n\t// const prevPushCIDs = [\n\t// \tpublication.lastCID,\n\t// \t//TODO add this one and update the publication data after push\n\t// ]\n\t// const includedLogCIDs = [\n\t// \t'full array of CIDS from all previous pushes'\n\t// ]\n\n\tDEBUG(`[preparePubForPush] Collected ${logsToPublish.length} logs :`, {\n\t\tlogsToPublish,\n\t\tthreadOrLogsCount: (threadToPublish as any).nameAndSizeUntracked || (`[${(threadToPublish as any).length}]`),\n\t})\n\n\tconst { sharedAgents, sharedKeyMap, sharedKey, pubCounter } = share ?? {}\n\n\tconst getExistingOrNewLog = (thread: Thread, share: IShare, ag: string, at: string, vl) => {\n\t\tlet logInQuestion = rollingFilter(lastWriteWins(thread), { en: share.id, at }).latestLog\n\t\tif (!logInQuestion && vl !== undefined) {\n\t\t\tlogInQuestion = ensureTsPvAndFinalizeApplog({ ag, en: share.id, at, vl }, thread)\n\t\t}\n\t\treturn logInQuestion // can be undefined if the passed vl is undefined and the log is not found\n\t}\n\tconst shareNameLog = getExistingOrNewLog(appThread, share, agent.ag, 'share/name', share.name)\n\n\t// ? using did as it is derived from the same ecdh in note3 and part of the minimal AppAgent type required here in wovin core\n\tconst shareCounterLog = getExistingOrNewLog(appThread, share, agent.ag, 'share/counter', `${agent.did}<::>${pubCounter}`)\n\t// ? discuss if this works to bind the counter to a specific derivation key - did is not necessarily derived from the same key by all lib users\n\n\tconst encryptApplog = async (applog: Applog, keyToUse: CryptoKey): Promise<Uint8Array> => {\n\t\tconst { log: eachLog, cid } = prepareForPub(applog) // without cid\n\t\tconst enc = new TextEncoder()\n\t\tconst stringified = stringify(eachLog)\n\t\tconst stringifiedEncodedAppLogPayload = enc.encode(stringified) // TODO: consider encodeToDagJson instead\n\t\tVERBOSE('[odd]', { eachLog, stringified, stringifiedEncodedAppLogPayload })\n\n\t\ttry {\n\t\t\t// @ts-expect-error\n\t\t\tconst encPayload = await agent.crypto?.aes.encrypt(stringifiedEncodedAppLogPayload, keyToUse, 'AES-GCM')\n\t\t\t// TODO get rid of odd down here\n\t\t\tVERBOSE('[odd] encrypted length:', stringifiedEncodedAppLogPayload.length, { encPayload })\n\t\t\treturn encPayload\n\t\t} catch (err) {\n\t\t\tthrow ERROR('FAILED TO ENC payload length:', stringifiedEncodedAppLogPayload.length, { err })\n\t\t}\n\n\t\t// const decrypted = await decryptWithAesSharedKey(encPayload, keyToUse, 'string')\n\t}\n\n\tlet maybeEncryptedApplogs: ApplogEncNoCid[] | readonly Applog[]\n\tconst encryptedApplogs = [] as { enc: Uint8Array }[]\n\tconst agentSharedKeyLogs = []\n\tif (sharedAgents) { // encrypt all Applogs\n\t\tif (!sharedKey || !sharedKeyMap) {\n\t\t\tthrow ERROR('sharedAgents but no Keys/Map', { sharedAgents, sharedKeyMap, sharedKey })\n\t\t}\n\t\tVERBOSE('encrypting', { sharedAgents, sharedKeyMap })\n\n\t\tfor (const [eachAgent, eachEncKey] of Array.from(sharedKeyMap.entries())) {\n\t\t\tVERBOSE('adding key', { eachAgent, eachEncKey })\n\t\t\tagentSharedKeyLogs.push({\n\t\t\t\tag: agent.ag,\n\t\t\t\ten: eachAgent,\n\t\t\t\tat: 'share/sharedKey',\n\t\t\t\tvl: eachEncKey, // these are encrypted with the derived key from the local agent private and remote agent public keys\n\t\t\t})\n\t\t}\n\t\t// const encryptedForLogs = await insertApplogsInAppDB(agentSharedKeyLogs)\n\t\t// DEBUG(`[publish] adding agentSharedKeyLogs:`, encryptedForLogs)\n\t\tconst CIDlist: { cid: CidString; encCID?: CidString }[] = []\n\t\tconst pubCIDmap: Record<CidString, typeof CIDlist> = {}\n\t\t// TODO ensure that all needed keys are in\n\t\tfor (const eachLog of logsToPublish) {\n\t\t\tVERBOSE('[crypto] encrypting ', { eachLog, sharedKey })\n\t\t\t// try {\n\t\t\tconst encPayload = await encryptApplog(eachLog, sharedKey)\n\t\t\tDEBUG('[crypto] encrypted ', { eachLog, encPayload, sharedKey })\n\t\t\t// } catch (err) {\n\t\t\t// \t// its already traced in encryptAndTestDecrypt\n\t\t\t// \t// continue\n\t\t\t// }\n\t\t\tencryptedApplogs.push({ enc: encPayload })\n\t\t}\n\t\tmaybeEncryptedApplogs = encryptedApplogs\n\t} else {\n\t\tmaybeEncryptedApplogs = logsToPublish // publish nonEncrypted\n\t}\n\n\tDEBUG('adding all agent info and shareAtoms', {\n\t\tshare,\n\t\tagent,\n\t\tlogsToPublish,\n\t\t// threadToPublish, - very verbose\n\t\tagentSharedKeyLogs,\n\t})\n\tconst infoLogs = [\n\t\t...rollingFilter(lastWriteWins(appThread), { // TODO: use static filter for performance\n\t\t\ten: agent.ag,\n\t\t\tat: anyOf('agent/ecdh', 'agent/jwkd', 'agent/appAgent'),\n\t\t}).applogs,\n\t\t...(shareNameLog ? [shareNameLog] : []),\n\t\t...(shareCounterLog ? [shareCounterLog] : []),\n\t\t...agentSharedKeyLogs,\n\t]\n\tDEBUG(`[prepareSnapshotForPush] info logs:`, infoLogs)\n\tif (!infoLogs.find(({ at }) => at === 'agent/appAgent')) throw ERROR(`[prepareSnapshotForPush] appThread missing agent/appAgent log`)\n\n\tconst applogsToEncode = keepTruthy(maybeEncryptedApplogs)\n\tconst infologsToEncode = keepTruthy(infoLogs)\n\tif (!applogsToEncode.length) {\n\t\tthrow ERROR('no valid applogs', { agent, maybeEncryptedApplogs, infoLogs, applogsToEncode, infologsToEncode, prevSnapCID })\n\t}\n\tif (!infologsToEncode.length) {\n\t\tthrow ERROR('no valid infologs', { agent, maybeEncryptedApplogs, infoLogs, applogsToEncode, infologsToEncode, prevSnapCID })\n\t}\n\tconst encodedSnapshot = await encodeSnapshotAsCar(agent, applogsToEncode, infologsToEncode, prevSnapCID, prevCounter)\n\tDEBUG('inPrepareSnapshotForPush', { encodedSnapshot })\n\treturn encodedSnapshot\n}\n\n/**\n * @param applogs Encrypted or plain applogs\n * @returns Car file\n */\nexport async function encodeSnapshotAsCar(\n\tagent: AppAgent,\n\tapplogs: ApplogArrayNoCIDMaybeEncryptedRO,\n\tinfoLogs: readonly Applog[],\n\tprevSnapCID: CID | null,\n\tprevCounter: number | null,\n) {\n\tDEBUG(`[encodeSnapshotAsCar] encoding`, { agent, applogs, infoLogs })\n\tconst { cids: infoLogCids, encodedApplogs: encodedInfoLogs } = await encodeApplogsAsIPLD(infoLogs)\n\tconst { cids: applogCids, encodedApplogs } = await encodeApplogsAsIPLD(applogs)\n\tlet blocks = encodedApplogs.concat(encodedInfoLogs)\n\t// We need to wrap the array to get a CID\n\tconst infoLogsWrap = await encodeBlockOriginal({ logs: infoLogCids })\n\tblocks.push(infoLogsWrap)\n\tconst { rootCID: chunkRootCID, blocks: chunkBlocks } = await chunkApplogs(applogCids)\n\tblocks = blocks.concat(chunkBlocks) // (i) concat bc. https://stackoverflow.com/a/51860949\n\tconst infoSignature = await agent.sign(infoLogsWrap.cid.bytes)\n\tconst applogsSignature = await agent.sign(chunkRootCID.bytes)\n\tconst root = {\n\t\tinfo: infoLogsWrap.cid,\n\t\tapplogs: chunkRootCID,\n\t\tinfoSignature,\n\t\tapplogsSignature,\n\t\tprev: prevSnapCID,\n\t\tprevCounter: !prevSnapCID ? 0 : prevCounter !== null ? prevCounter + 1 : null,\n\t}\n\tDEBUG('[encodeSnapshotAsCar] encoding root', { root, logCids: applogCids, infoLogCids })\n\tconst encodedRoot = await encodeBlockOriginal(root)\n\tblocks.push(encodedRoot)\n\tDEBUG('[encodeSnapshotAsCar] => root', { encodedRoot })\n\n\treturn {\n\t\tcid: encodedRoot.cid,\n\t\tblob: await makeCarBlob(encodedRoot.cid, blocks), // TODO: create CarBuilder (incl .encodeAndAdd({...}))\n\t\tblocks,\n\t\tinfoLogCids,\n\t\tapplogCids,\n\t}\n}\n\n/** (i) IPFS has a block size limit of 1MB - which is about 15K CIDs */\nexport async function chunkApplogs(applogCids: CID<unknown, 297, 18, 1>[], size = 10000) {\n\tif (!applogCids.length) throw ERROR(`[chunkApplogs] called with empty array`)\n\tconst chunks = []\n\t// TODO: chunk by stable btree based on size or something like that\n\tfor (let i = 0; i < applogCids.length; i += size) {\n\t\tconst chunk = await encodeBlockOriginal({ logs: applogCids.slice(i, Math.min(i + applogCids.length, i + size)) })\n\t\tchunks.push(chunk)\n\t}\n\tif (chunks.length === 1) return { rootCID: chunks[0].cid, blocks: chunks }\n\tconst root = await encodeBlockOriginal({ chunks: chunks.map(chunk => chunk.cid) })\n\tconst blocks = [root, ...chunks]\n\tDEBUG(`[chunkApplogs] ${applogCids.length} logs chunked into ${chunks.length}`, { applogCids, root, blocks, chunks, dagJson })\n\treturn { rootCID: root.cid, blocks, chunks }\n}\nexport async function unchunkApplogsBlock(block: SnapBlockLogsOrChunks, blockStore: BlockStoreish): Promise<CID[]> {\n\tif (isSnapBlockChunks(block)) {\n\t\treturn (await Promise.all(\n\t\t\tblock.chunks.map(async (chunkCid) => {\n\t\t\t\tconst block = (await getDecodedBlock(blockStore, chunkCid)) as SnapBlockLogs\n\t\t\t\tif (!block.logs) throw ERROR(`Weird chunk`, block)\n\t\t\t\treturn block.logs\n\t\t\t}),\n\t\t)).flat()\n\t} else {\n\t\treturn block.logs\n\t}\n}\nexport function isSnapBlockChunks(block: SnapBlockLogsOrChunks): block is SnapBlockChunks {\n\treturn (block as any).chunks\n}\n/**\n * @param applogs Encrypted or plain applogs\n * @returns Car file\n */\nexport async function encodeSnapshotApplogsAsCar(\n\tapplogs: ApplogArrayMaybeEncryptedRO,\n) {\n\tconst encoded = await encodeApplogsAsIPLD(applogs)\n\tif (!encoded) throw ERROR('invalid applogs cannot continue', { applogs, encoded })\n\tconst { cids, encodedApplogs } = encoded\n\tconst root = { applogs: cids }\n\tconst encodedRoot = await encodeBlockOriginal(root)\n\tDEBUG('[encodeSnapshotApplogsAsCar] encoded root', { cids, encodedRoot })\n\n\treturn await makeCarBlob(encodedRoot.cid, [encodedRoot, ...encodedApplogs])\n}\n\nasync function encodeApplogsAsIPLD(applogs: ApplogArrayNoCIDMaybeEncryptedRO) {\n\tDEBUG({ applogs })\n\tconst validApplogs = applogs.filter(eachLog => !!eachLog)\n\tDEBUG({ validApplogs })\n\tif (!validApplogs.length) throw ERROR('no valid applogs')\n\tconst preppedLogs = validApplogs.map(log => prepareForPub(log as Applog).log)\n\tconst encodedApplogs = await Promise.all(preppedLogs.map(encodeBlockOriginal))\n\tDEBUG('[encodeApplogsAsIpld] encoded applogs', { preppedLogs, encodedApplogs })\n\n\tconst cids = encodedApplogs.map(b => {\n\t\tif (!b.cid) throw ERROR(`[publish] no cid for encoded log:`, b)\n\t\treturn b.cid\n\t})\n\treturn { cids, encodedApplogs }\n}\n","import { CarReader, CarWriter } from '@ipld/car'\nimport * as dagJson from '@ipld/dag-json'\nimport { Logger } from 'besonders-logger'\nimport { BlockView, CID } from 'multiformats'\nimport { sortApplogsByTs } from '../applog/applog-utils.ts'\nimport { Applog, ApplogArrayMaybeEncrypted, CidString } from '../applog/datom-types.ts'\nimport { unchunkApplogsBlock } from '../pubsub/snap-push.ts'\nimport { SnapBlockLogs, SnapBlockLogsOrChunks, SnapRootBlock } from '../pubsub/pubsub-types.ts'\nimport { areCidsEqual, containsCid } from './ipfs-utils.ts'\n\nconst { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line no-unused-vars\n\nexport type CIDForCar = CID // Exclude<Parameters<(typeof CarWriter)['create']>[0], void>\nexport type BlockForCar = Parameters<CarWriter['put']>[0]\n\nexport interface BlockStoreish {\n\tget(cid: CID): PromiseLike<Uint8Array> // (i) not using decoded version to be similar to blockstore-idb\n}\n\nexport interface DecodedCar {\n\trootCID: CID\n\t// blocks: Map<CidString, any>\n\tblockStore: BlockStoreish\n}\n\n/** Warning: unsorted & maybe encrypted */\nexport async function decodePubFromCar(car: CarReader) {\n\tconst decoded = await getBlocksOfCar(car)\n\treturn await decodePubFromBlocks(decoded)\n}\n\nexport async function decodePubFromBlocks(\n\t{ rootCID, blockStore }: DecodedCar,\n\t_recursionTrace: CID[] = [], // DEPRECATED: kept for API compat, unused in iterative version\n\tstopAtCID?: CID // NEW: stop iteration when we hit this CID\n) {\n\tif (!rootCID || !blockStore) {\n\t\tthrow ERROR('Empty roots/blocks', { rootCID, blockStore })\n\t}\n\n\tlet allApplogs: ApplogArrayMaybeEncrypted = []\n\tlet firstInfo: { logs: CID[] } | null = null\n\tlet currentCID: CID | undefined = rootCID\n\tconst visited = new Set<string>() // Loop detection (replaces recursionTrace)\n\tlet applogsCID: CID | null = null // From first snapshot only\n\n\twhile (currentCID) {\n\t\tconst cidStr = currentCID.toString()\n\n\t\t// Loop detection\n\t\tif (visited.has(cidStr)) {\n\t\t\tthrow ERROR('[decodePubFromBlocks] pub 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// Decode current snapshot\n\t\tconst root = (await getDecodedBlock(blockStore, currentCID)) as SnapRootBlock\n\t\tVERBOSE(`[decodePubFromBlocks] root:`, cidStr, root, { blockStore })\n\t\tif (!root) {\n\t\t\tthrow ERROR('[decodePubFromBlocks] root not found in blockStore', { blockStore, currentCID: cidStr })\n\t\t}\n\n\t\t// Decode applogs for this snapshot\n\t\tlet pubLogsArray: CID[]\n\t\tif (root?.info) {\n\t\t\t// New(er) format\n\t\t\tif (!applogsCID) applogsCID = root.applogs // Save from first snapshot\n\t\t\tconst applogsBlock = (await getDecodedBlock(blockStore, root.applogs)) as SnapBlockLogsOrChunks\n\t\t\tpubLogsArray = await unchunkApplogsBlock(applogsBlock, blockStore)\n\t\t\t// Info only from first (most recent) snapshot\n\t\t\tif (!firstInfo) {\n\t\t\t\tfirstInfo = (await getDecodedBlock(blockStore, root.info)) as SnapBlockLogs\n\t\t\t\tDEBUG(`new format - infoLogs`, firstInfo.logs.map(l => ({ [l.toString()]: l })))\n\t\t\t}\n\t\t\t// TODO: verify signatures\n\t\t} else {\n\t\t\t// Old format\n\t\t\tpubLogsArray = root.applogs as any as CID[]\n\t\t}\n\n\t\tconst resolveLogFromCidLink = async (cidOrLink: CID) => {\n\t\t\tconst cid = cidOrLink\n\t\t\tconst applog = (await getDecodedBlock(blockStore, cid)) as Applog\n\t\t\tif (!applog) {\n\t\t\t\tERROR(`Could not find applog CID in pub blocks:`, cid.toString(), { cid, root, blockStore })\n\t\t\t\tthrow new Error(`Could not find applog CID in pub blocks: ${cid.toString()}`)\n\t\t\t}\n\t\t\tif ((applog.pv as any) instanceof CID) applog.pv = (applog.pv as any as CID).toV1().toString()\n\t\t\treturn {\n\t\t\t\t...applog,\n\t\t\t\tcid: cid.toV1().toString(),\n\t\t\t}\n\t\t}\n\n\t\tconst snapshotApplogs = await Promise.all(pubLogsArray.map(resolveLogFromCidLink))\n\t\tallApplogs = allApplogs.concat(snapshotApplogs)\n\n\t\t// Check if we should stop\n\t\tif (!root.prev) {\n\t\t\tbreak // End of chain\n\t\t}\n\t\tif (stopAtCID && areCidsEqual(root.prev, stopAtCID)) {\n\t\t\tDEBUG('[decodePubFromBlocks] stopping at stopAtCID:', stopAtCID.toString())\n\t\t\tbreak // Reached already-pulled snapshot\n\t\t}\n\n\t\t// Verify prev exists before continuing\n\t\tconst prevBytes = await blockStore.get(root.prev)\n\t\tif (!prevBytes) {\n\t\t\tthrow ERROR('[decodePubFromBlocks] prev snapshot missing from blockStore', {\n\t\t\t\tcurrentCID: cidStr,\n\t\t\t\tprev: root.prev.toString(),\n\t\t\t\tstopAtCID: stopAtCID?.toString(),\n\t\t\t\tvisited: [...visited]\n\t\t\t})\n\t\t}\n\n\t\tcurrentCID = root.prev // Move to previous snapshot\n\t}\n\n\tconst result = {\n\t\tcid: rootCID,\n\t\tinfo: firstInfo ? {\n\t\t\t...firstInfo,\n\t\t\tlogs: await Promise.all(firstInfo.logs.map(async (cidOrLink: CID) => {\n\t\t\t\tconst cid = cidOrLink\n\t\t\t\tconst applog = (await getDecodedBlock(blockStore, cid)) as Applog\n\t\t\t\tif (!applog) {\n\t\t\t\t\tERROR(`Could not find info log CID in pub blocks:`, cid.toString(), { cid, blockStore })\n\t\t\t\t\tthrow new Error(`Could not find info log CID in pub blocks: ${cid.toString()}`)\n\t\t\t\t}\n\t\t\t\tif ((applog.pv as any) instanceof CID) applog.pv = (applog.pv as any as CID).toV1().toString()\n\t\t\t\treturn {\n\t\t\t\t\t...applog,\n\t\t\t\t\tcid: cid.toV1().toString(),\n\t\t\t\t}\n\t\t\t})),\n\t\t} : null,\n\t\tapplogsCID,\n\t\tapplogs: allApplogs,\n\t}\n\tDEBUG('[decodePubFromBlocks] result:', result, { rootCID: rootCID.toString(), blockStore, applogs: allApplogs })\n\treturn result\n}\n\nexport async function getBlocksOfCar(car: CarReader) {\n\tconst rootsFromCar = await car.getRoots()\n\tconst roots = rootsFromCar.map(c => ((typeof c.toV1 === 'function') ? c : CID.decode(c.bytes)).toV1().toString() as CidString) // HACK\n\tconst blocks = new Map<CidString, any>()\n\tfor await (const { cid: cidFromCarblocks, bytes } of car.blocks()) {\n\t\tconst cid = (typeof cidFromCarblocks.toV1 === 'function') ? cidFromCarblocks : CID.decode(cidFromCarblocks.bytes)\n\t\tVERBOSE({ cidFromCarblocks, cid })\n\t\t// blocks.set(cid.toV1().toString(), dagJson.decode(bytes)) // HACK: tried using CID as map key, but because it's based on referential equality it's not working\n\t\tblocks.set(cid.toV1().toString(), bytes) // HACK: tried using CID as map key, but because it's based on referential equality it's not working\n\t}\n\tif (roots.length !== 1) {\n\t\tWARN('Unexpected roots count:', roots)\n\t}\n\treturn {\n\t\trootCID: CID.parse(roots[0]),\n\t\tblockStore: {\n\t\t\tget: (cid) => blocks.get(cid.toV1().toString()),\n\t\t},\n\t} satisfies DecodedCar\n}\nexport async function getDecodedBlock(blockStore: BlockStoreish, cid: CID) {\n\ttry {\n\t\tvar blob = await blockStore.get(cid)\n\t\tif (!blob) {\n\t\t\tWARN('returning null')\n\t\t\treturn null // I don't think this ever happens actually\n\t\t}\n\t} catch (err) {\n\t\tif ((err as any).message === 'Not Found') return null\n\t\tthrow err\n\t}\n\treturn dagJson.decode(blob)\n}\n\n// make out in the car... been a while but also sounds nice\nexport async function makeCarOut(roots: CIDForCar, blocks: BlockForCar[]) {\n\tconst { writer, out } = CarWriter.create(Array.isArray(roots) ? roots : [roots])\n\n\t// add the blocks to the CAR and close it\n\tVERBOSE(`Writing ${blocks.length} blocks to CAR`, { roots, blocks })\n\tblocks.forEach(b => writer.put(b))\n\twriter.close()\n\t// VERBOSE(`Wrote ${blocks.length} blocks to CAR`, writer)\n\treturn out\n} /** create a new CarWriter, with the encoded block as the root */\n\n// export async function makeCarReader(roots: CIDForCar, blocks: BlockForCar[]) {\n// \tconst out = await makeCarOut(roots, blocks)\n\n// \t// create a new CarReader we can hand to web3.storage.putCar\n// \tconst reader = await CarReader.fromIterable(out)\n// \tVERBOSE(`CAR reader`, reader)\n// \treturn reader\n// } /** create a new CarWriter, with the encoded block as the root */\n\nexport async function makeCarBlob(roots: CIDForCar, blocks: BlockForCar[]) {\n\tconst carOut = await makeCarOut(roots, blocks)\n\tconst chunks = []\n\tfor await (const chunk of carOut) {\n\t\tchunks.push(chunk)\n\t}\n\tconst blob = new Blob(chunks)\n\treturn blob\n}\nexport async function carFromBlob(blob: Blob | File): Promise<CarReader> {\n\treturn CarReader.fromBytes(new Uint8Array(await blob.arrayBuffer()))\n}\n\nfunction extractCids(value: unknown): CID[] {\n\tif (value instanceof CID) return [value]\n\tif (Array.isArray(value)) return value.flatMap(extractCids)\n\tif (value && typeof value === 'object') return Object.values(value).flatMap(extractCids)\n\treturn []\n}\n\nconst MAX_COLLECT_BLOCKS = 1_000_000\n\nexport async function collectDagBlocks(\n\tstartCID: CID,\n\tblockStore: BlockStoreish,\n): Promise<BlockForCar[]> {\n\tconst visited = new Set<string>()\n\tconst blocks: BlockForCar[] = []\n\tconst queue: CID[] = [startCID]\n\n\twhile (queue.length > 0) {\n\t\tif (blocks.length >= MAX_COLLECT_BLOCKS) {\n\t\t\tWARN(`[collectDagBlocks] hit ${MAX_COLLECT_BLOCKS} block limit, returning partial result`)\n\t\t\tbreak\n\t\t}\n\n\t\tconst cid = queue.shift()!\n\t\tconst cidStr = cid.toString()\n\t\tif (visited.has(cidStr)) continue\n\t\tvisited.add(cidStr)\n\n\t\tlet bytes: Uint8Array\n\t\ttry {\n\t\t\tbytes = await blockStore.get(cid)\n\t\t} catch {\n\t\t\tWARN(`[collectDagBlocks] block not found: ${cidStr}, stopping this branch`)\n\t\t\tcontinue\n\t\t}\n\t\tif (!bytes) {\n\t\t\tWARN(`[collectDagBlocks] block not found: ${cidStr}, stopping this branch`)\n\t\t\tcontinue\n\t\t}\n\n\t\tblocks.push({ cid, bytes })\n\n\t\tif (blocks.length % 1000 === 0) {\n\t\t\tLOG(`[collectDagBlocks] collected ${blocks.length} blocks...`)\n\t\t}\n\n\t\ttry {\n\t\t\tconst decoded = dagJson.decode(bytes)\n\t\t\tconst childCids = extractCids(decoded)\n\t\t\tfor (const child of childCids) {\n\t\t\t\tif (!visited.has(child.toString())) {\n\t\t\t\t\tqueue.push(child)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not dag-json — leaf block, no children to walk\n\t\t}\n\t}\n\n\tDEBUG(`[collectDagBlocks] collected ${blocks.length} blocks from ${startCID.toString()}`)\n\treturn blocks\n}\n\nexport function streamReaderToIterable(bodyReader: ReadableStreamDefaultReader<Uint8Array>): AsyncIterable<Uint8Array> {\n\treturn (async function*() {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await bodyReader.read()\n\t\t\tVERBOSE(`[car] chunk`, { done, value })\n\t\t\tif (done) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tyield value\n\t\t}\n\t})()\n}\n"],"mappings":"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","names":["dagJson","Logger","WARN","LOG","DEBUG","VERBOSE","ERROR","Logger","share","dagJson","block"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-7Z5YDQKK.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
decode,
|
|
5
|
-
g
|
|
6
|
-
} from "./chunk-GDX2OO7L.min.js";
|
|
2
|
+
areCidsEqual
|
|
3
|
+
} from "./chunk-SHUHRHOT.js";
|
|
7
4
|
|
|
8
5
|
// src/ipfs/fetch-snapshot-chain.ts
|
|
9
|
-
|
|
6
|
+
import * as dagJson from "@ipld/dag-json";
|
|
7
|
+
import { Logger } from "besonders-logger";
|
|
8
|
+
import { CID } from "multiformats/cid";
|
|
9
|
+
var { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO);
|
|
10
10
|
async function fetchSnapshotChainUntil(options) {
|
|
11
11
|
const { rootCID, stopAtCID, stopAtCounter, fetchBlock, fetchAll, maxDepth = 100 } = options;
|
|
12
12
|
const blockStore = createMemoryBlockStore();
|
|
@@ -32,7 +32,7 @@ async function fetchSnapshotChainUntil(options) {
|
|
|
32
32
|
if (!rootBytes) {
|
|
33
33
|
throw ERROR("[fetchSnapshotChain] root block not in store after fetch", { currentCID: cidStr });
|
|
34
34
|
}
|
|
35
|
-
const root = decode(rootBytes);
|
|
35
|
+
const root = dagJson.decode(rootBytes);
|
|
36
36
|
if (typeof root.prevCounter === "number") {
|
|
37
37
|
minCounter = Math.min(minCounter, root.prevCounter);
|
|
38
38
|
maxCounter = Math.max(maxCounter, root.prevCounter);
|
|
@@ -83,4 +83,4 @@ function createMemoryBlockStore() {
|
|
|
83
83
|
export {
|
|
84
84
|
fetchSnapshotChainUntil
|
|
85
85
|
};
|
|
86
|
-
//# sourceMappingURL=chunk-
|
|
86
|
+
//# sourceMappingURL=chunk-BLF5MAWU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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.ts'\nimport { areCidsEqual } from './ipfs-utils.ts'\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 stopAtCounter?: number // Stop when we reach this counter (walking backwards)\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 counterRange?: { minCounter: number; maxCounter: 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, stopAtCounter, 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 let minCounter = Infinity\n let maxCounter = -Infinity\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 // Track counter range\n if (typeof root.prevCounter === 'number') {\n minCounter = Math.min(minCounter, root.prevCounter)\n maxCounter = Math.max(maxCounter, root.prevCounter)\n }\n\n // Stop condition based on counter\n if (stopAtCounter !== undefined && typeof root.prevCounter === 'number' && root.prevCounter <= stopAtCounter) {\n DEBUG('[fetchSnapshotChain] reached stopAtCounter', { stopAtCounter, prevCounter: root.prevCounter })\n break\n }\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 {\n rootCID,\n blockStore,\n blocks: blockStore.getBlocksArray(),\n snapshotCount,\n counterRange: minCounter !== Infinity ? { minCounter, maxCounter } : undefined,\n }\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":";;;;;AACA,YAAY,aAAa;AACzB,SAAS,cAAc;AACvB,SAAS,WAAW;AAIpB,IAAM,EAAE,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,OAAO,MAAM,OAAO,IAAI;AA8BrE,eAAsB,wBAAwB,SAAuD;AACjG,QAAM,EAAE,SAAS,WAAW,eAAe,YAAY,UAAU,WAAW,IAAI,IAAI;AACpF,QAAM,aAAa,uBAAuB;AAC1C,QAAM,UAAU,oBAAI,IAAY;AAChC,MAAI,aAA8B;AAClC,MAAI,gBAAgB;AACpB,MAAI,aAAa;AACjB,MAAI,aAAa;AAEjB,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,eAAO,SAAS;AAGrC,QAAI,OAAO,KAAK,gBAAgB,UAAU;AACtC,mBAAa,KAAK,IAAI,YAAY,KAAK,WAAW;AAClD,mBAAa,KAAK,IAAI,YAAY,KAAK,WAAW;AAAA,IACtD;AAGA,QAAI,kBAAkB,UAAa,OAAO,KAAK,gBAAgB,YAAY,KAAK,eAAe,eAAe;AAC1G,YAAM,8CAA8C,EAAE,eAAe,aAAa,KAAK,YAAY,CAAC;AACpG;AAAA,IACJ;AAGA,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;AAAA,IACH;AAAA,IACA;AAAA,IACA,QAAQ,WAAW,eAAe;AAAA,IAClC;AAAA,IACA,cAAc,eAAe,WAAW,EAAE,YAAY,WAAW,IAAI;AAAA,EACzE;AACJ;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":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-E46VTKTZ.js.map
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
unchunkApplogsBlock
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6ALNRM3J.js";
|
|
4
4
|
import {
|
|
5
|
-
CID,
|
|
6
5
|
areCidsEqual,
|
|
7
|
-
decode,
|
|
8
|
-
g,
|
|
9
6
|
removeDuplicateAppLogs
|
|
10
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SHUHRHOT.js";
|
|
11
8
|
|
|
12
9
|
// src/retrieve/update-thread.ts
|
|
13
|
-
|
|
10
|
+
import * as dagJson from "@ipld/dag-json";
|
|
11
|
+
import { Logger } from "besonders-logger";
|
|
12
|
+
import { CID } from "multiformats/cid";
|
|
13
|
+
var { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO);
|
|
14
14
|
function withBlockCache(source, store) {
|
|
15
15
|
return {
|
|
16
16
|
get: (cid) => store.get(cid),
|
|
@@ -36,7 +36,7 @@ function createMemoryBlockStore() {
|
|
|
36
36
|
async function getDecodedBlock(blockStore, cid) {
|
|
37
37
|
const bytes = blockStore.get(cid);
|
|
38
38
|
if (!bytes) return null;
|
|
39
|
-
return decode(bytes);
|
|
39
|
+
return dagJson.decode(bytes);
|
|
40
40
|
}
|
|
41
41
|
async function updateThreadFromSnapshot(thread, cid, retriever, options) {
|
|
42
42
|
const { excludeSnapshotCID, stopAtCounter, maxDepth = 100 } = options ?? {};
|
|
@@ -69,7 +69,7 @@ async function updateThreadFromSnapshot(thread, cid, retriever, options) {
|
|
|
69
69
|
DEBUG("[updateThreadFromSnapshot] fetching root block", cidStr);
|
|
70
70
|
const rootBytes = await retriever.get(currentCID);
|
|
71
71
|
blockStore.put(currentCID, rootBytes);
|
|
72
|
-
const root = decode(rootBytes);
|
|
72
|
+
const root = dagJson.decode(rootBytes);
|
|
73
73
|
if (typeof root.prevCounter === "number") {
|
|
74
74
|
minCounter = Math.min(minCounter, root.prevCounter);
|
|
75
75
|
maxCounter = Math.max(maxCounter, root.prevCounter);
|
|
@@ -141,4 +141,4 @@ export {
|
|
|
141
141
|
withBlockCache,
|
|
142
142
|
updateThreadFromSnapshot
|
|
143
143
|
};
|
|
144
|
-
//# sourceMappingURL=chunk-
|
|
144
|
+
//# sourceMappingURL=chunk-HUIQ54TT.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.ts'\nimport { removeDuplicateAppLogs } from '../applog/applog-utils.ts'\nimport type { SnapRootBlock, SnapBlockLogsOrChunks } from '../pubsub/pubsub-types.ts'\nimport { unchunkApplogsBlock } from '../pubsub/snap-push.ts'\nimport { areCidsEqual } from '../ipfs/ipfs-utils.ts'\nimport type { WriteableThread } from '../thread/writeable.ts'\nimport type { BlockStore } from '../blockstore/index.ts'\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\tget(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 * Wrap a BlockRetriever so fetched blocks flow through a BlockStore.\n * - get: delegates to store.get() (which handles local-first / remote fallback)\n * - getDag: streams from source, puts each block into store\n */\nexport function withBlockCache(\n\tsource: BlockRetriever,\n\tstore: BlockStore,\n): BlockRetriever {\n\treturn {\n\t\tget: (cid) => store.get(cid),\n\t\tasync *getDag(cid) {\n\t\t\tfor await (const block of source.getDag(cid)) {\n\t\t\t\tawait store.put(block.cid, block.bytes)\n\t\t\t\tyield block\n\t\t\t}\n\t\t},\n\t}\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.get(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 (typeof root.prevCounter === 'number') {\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 && typeof root.prevCounter === 'number' && 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"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
cyrb53hash,
|
|
3
|
-
ensureTsPvAndFinalizeApplog
|
|
4
|
-
|
|
5
|
-
} from "./chunk-GDX2OO7L.min.js";
|
|
3
|
+
ensureTsPvAndFinalizeApplog
|
|
4
|
+
} from "./chunk-SHUHRHOT.js";
|
|
6
5
|
|
|
7
6
|
// src/pubsub/pub-pull.ts
|
|
8
|
-
|
|
7
|
+
import { Logger } from "besonders-logger";
|
|
8
|
+
var { WARN, LOG, DEBUG, VERBOSE, ERROR } = Logger.setup(Logger.INFO);
|
|
9
9
|
function integratePub({ targetThread, agentHash, subID, pubData }) {
|
|
10
10
|
const newLogs = pubData.thread.applogs.filter((log) => !targetThread.hasApplog(log, false));
|
|
11
11
|
DEBUG(`[integratePub] integrating ${newLogs.length} logs`, { targetThread, subID, pubData });
|
|
@@ -37,4 +37,4 @@ export {
|
|
|
37
37
|
isSubscription,
|
|
38
38
|
agentToShortHash
|
|
39
39
|
};
|
|
40
|
-
//# sourceMappingURL=chunk-
|
|
40
|
+
//# sourceMappingURL=chunk-OC6Z6CQW.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.ts'\nimport { EntityID } from '../applog/datom-types.ts'\nimport { Thread } from '../thread.ts'\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.ts'\nimport { AgentHash, AgentID, CidString } from '../applog/datom-types.ts'\nimport { Tagged } from '../types.ts'\nimport { UCANCapMap } from './ucan.ts'\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 | null // Sequential counter: 0 for first, then +1 for each. null = unknown (legacy/error).\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":";;;;;;AAAA,SAAS,cAAc;AAMvB,IAAM,EAAE,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,OAAO,MAAM,OAAO,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":[]}
|