@wovin/core 0.2.2 → 0.3.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/dist/applog/applog-utils.d.ts +25 -1
- package/dist/applog/applog-utils.d.ts.map +1 -1
- package/dist/applog/datom-types.d.ts.map +1 -1
- package/dist/applog.js +5 -3
- package/dist/blockstore.js +2 -0
- package/dist/blockstore.js.map +1 -1
- package/dist/{chunk-SHUHRHOT.js → chunk-4MKPGQIM.js} +17 -18
- package/dist/chunk-4MKPGQIM.js.map +1 -0
- package/dist/chunk-64EJIJAJ.js +17 -0
- package/dist/chunk-64EJIJAJ.js.map +1 -0
- package/dist/{chunk-HUIQ54TT.js → chunk-6CSJTSQP.js} +3 -3
- package/dist/chunk-7QEGHKR4.js +17 -0
- package/dist/chunk-7QEGHKR4.js.map +1 -0
- package/dist/{chunk-BLF5MAWU.js → chunk-BIYQEX3N.js} +2 -2
- package/dist/{chunk-6ALNRM3J.js → chunk-H3JNNTVP.js} +21 -8
- package/dist/chunk-H3JNNTVP.js.map +1 -0
- package/dist/{chunk-OC6Z6CQW.js → chunk-H4YVJKB7.js} +2 -2
- package/dist/chunk-ICBK7NC4.js +27 -0
- package/dist/chunk-ICBK7NC4.js.map +1 -0
- package/dist/chunk-N5QPZNKD.js +288 -0
- package/dist/chunk-N5QPZNKD.js.map +1 -0
- package/dist/{chunk-3SUFNJEZ.js → chunk-N7SEGHU4.js} +7 -2
- package/dist/{chunk-3SUFNJEZ.js.map → chunk-N7SEGHU4.js.map} +1 -1
- package/dist/chunk-XF4DWOAE.js +25 -0
- package/dist/chunk-XF4DWOAE.js.map +1 -0
- package/dist/index.js +20 -10
- package/dist/ipfs/car.d.ts.map +1 -1
- package/dist/ipfs.js +4 -4
- package/dist/ipns/gateway-resolver.d.ts +21 -0
- package/dist/ipns/gateway-resolver.d.ts.map +1 -0
- package/dist/ipns/ipns-record.d.ts +46 -7
- package/dist/ipns/ipns-record.d.ts.map +1 -1
- package/dist/ipns/ipns-w3name.d.ts +45 -0
- package/dist/ipns/ipns-w3name.d.ts.map +1 -0
- package/dist/ipns/ipns-watcher.d.ts +190 -0
- package/dist/ipns/ipns-watcher.d.ts.map +1 -0
- package/dist/ipns.d.ts +3 -0
- package/dist/ipns.d.ts.map +1 -1
- package/dist/ipns.js +591 -14
- package/dist/ipns.js.map +1 -1
- package/dist/pubsub/snap-push.d.ts +2 -2
- package/dist/pubsub/snap-push.d.ts.map +1 -1
- package/dist/pubsub.js +4 -4
- package/dist/query/epoch-snapshot.d.ts +205 -0
- package/dist/query/epoch-snapshot.d.ts.map +1 -0
- package/dist/query.d.ts +1 -0
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +12 -4
- package/dist/retrieve.js +4 -4
- package/dist/thread.js +1 -1
- package/dist/viewmodel/adapters/arktype.d.ts +33 -0
- package/dist/viewmodel/adapters/arktype.d.ts.map +1 -0
- package/dist/viewmodel/adapters/arktype.js +7 -0
- package/dist/viewmodel/adapters/arktype.js.map +1 -0
- package/dist/viewmodel/adapters/typebox.d.ts +35 -0
- package/dist/viewmodel/adapters/typebox.d.ts.map +1 -0
- package/dist/viewmodel/adapters/typebox.js +7 -0
- package/dist/viewmodel/adapters/typebox.js.map +1 -0
- package/dist/viewmodel/adapters/typia.d.ts +40 -0
- package/dist/viewmodel/adapters/typia.d.ts.map +1 -0
- package/dist/viewmodel/adapters/typia.js +7 -0
- package/dist/viewmodel/adapters/typia.js.map +1 -0
- package/dist/viewmodel/adapters/zod.d.ts +30 -0
- package/dist/viewmodel/adapters/zod.d.ts.map +1 -0
- package/dist/viewmodel/adapters/zod.js +7 -0
- package/dist/viewmodel/adapters/zod.js.map +1 -0
- package/dist/viewmodel/builder.d.ts +40 -0
- package/dist/viewmodel/builder.d.ts.map +1 -0
- package/dist/viewmodel/examples/all-adapters.d.ts +26 -0
- package/dist/viewmodel/examples/all-adapters.d.ts.map +1 -0
- package/dist/viewmodel/factory.d.ts +38 -0
- package/dist/viewmodel/factory.d.ts.map +1 -0
- package/dist/viewmodel/index.d.ts +10 -0
- package/dist/viewmodel/index.d.ts.map +1 -0
- package/dist/viewmodel/index.js +313 -0
- package/dist/viewmodel/index.js.map +1 -0
- package/dist/viewmodel/schema-adapter.d.ts +16 -0
- package/dist/viewmodel/schema-adapter.d.ts.map +1 -0
- package/dist/viewmodel/types.d.ts +97 -0
- package/dist/viewmodel/types.d.ts.map +1 -0
- package/package.json +29 -3
- package/src/applog/applog-utils.test.ts +43 -1
- package/src/applog/applog-utils.ts +38 -21
- package/src/applog/datom-types.ts +2 -2
- package/src/applog/object-values.test.ts +9 -9
- package/src/ipfs/car.ts +14 -2
- package/src/ipns/gateway-resolver.ts +63 -0
- package/src/ipns/ipns-record.ts +158 -29
- package/src/ipns/ipns-w3name.ts +207 -0
- package/src/ipns/ipns-watcher.ts +608 -0
- package/src/ipns.ts +3 -0
- package/src/pubsub/snap-push.ts +6 -5
- package/src/query/epoch-snapshot.test.ts +594 -0
- package/src/query/epoch-snapshot.ts +392 -0
- package/src/query.ts +1 -0
- package/src/viewmodel/adapters/arktype.ts +44 -0
- package/src/viewmodel/adapters/typebox.ts +59 -0
- package/src/viewmodel/adapters/typia.ts +50 -0
- package/src/viewmodel/adapters/zod.ts +55 -0
- package/src/viewmodel/builder.ts +71 -0
- package/src/viewmodel/examples/all-adapters.ts +206 -0
- package/src/viewmodel/factory.ts +330 -0
- package/src/viewmodel/index.ts +22 -0
- package/src/viewmodel/schema-adapter.ts +27 -0
- package/src/viewmodel/types.ts +152 -0
- package/dist/chunk-22WDFLXO.js +0 -138
- package/dist/chunk-22WDFLXO.js.map +0 -1
- package/dist/chunk-6ALNRM3J.js.map +0 -1
- package/dist/chunk-SHUHRHOT.js.map +0 -1
- /package/dist/{chunk-HUIQ54TT.js.map → chunk-6CSJTSQP.js.map} +0 -0
- /package/dist/{chunk-BLF5MAWU.js.map → chunk-BIYQEX3N.js.map} +0 -0
- /package/dist/{chunk-OC6Z6CQW.js.map → chunk-H4YVJKB7.js.map} +0 -0
package/dist/ipns.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ipns/ipns-record.ts"],"sourcesContent":["import { createIPNSRecord, marshalIPNSRecord, unmarshalIPNSRecord } from 'ipns'\nimport { privateKeyFromRaw } from '@libp2p/crypto/keys'\nimport { base36 } from 'multiformats/bases/base36'\nimport { base64pad } from 'multiformats/bases/base64'\nimport type { CID } from 'multiformats/cid'\n\nexport interface SignedIPNSRecord {\n\trecordBytes: Uint8Array // marshalled protobuf, signed — the wire format\n\tipnsName: string // k51... string\n\tvalue: string // /ipfs/<cid>\n\tsequence: bigint\n}\n\n/** Derive IPNS name string (k51...) from Ed25519 private key bytes */\nexport function ipnsNameFromPrivateKey(privKeyBytes: Uint8Array): string {\n\tconst privKey = privateKeyFromRaw(privKeyBytes)\n\treturn privKey.publicKey.toCID().toString(base36)\n}\n\n/**\n * Create a signed IPNS record (protobuf wire format).\n * Same bytes can be published to any naming service.\n */\nexport async function createSignedIPNSRecord(\n\tprivateKey: Uint8Array,\n\tcid: CID,\n\tsequence: bigint,\n\tlifetimeMs = 365 * 24 * 60 * 60 * 1000, // 1 year\n): Promise<SignedIPNSRecord> {\n\tconst privKey = privateKeyFromRaw(privateKey)\n\tconst value = `/ipfs/${cid.toV1()}`\n\tconst record = await createIPNSRecord(privKey, value, sequence, lifetimeMs)\n\tconst recordBytes = marshalIPNSRecord(record)\n\tconst ipnsName = privKey.publicKey.toCID().toString(base36)\n\treturn { recordBytes, ipnsName, value, sequence }\n}\n\nexport { unmarshalIPNSRecord }\n\n/** A target that can receive a signed IPNS record */\nexport interface IPNSPublishTarget {\n\tname: string\n\tpublish(ipnsName: string, recordBytes: Uint8Array): Promise<void>\n}\n\n/**\n * Resolve current IPNS sequence number from a naming service.\n * Returns null if the name was never published (404).\n * Throws on network/server errors.\n */\nexport async function resolveIPNSSequence(\n\tnameServiceUrl: string,\n\tipnsName: string,\n): Promise<bigint | null> {\n\tconst url = `${nameServiceUrl}/name/${ipnsName}`\n\tlet response: Response\n\ttry {\n\t\tresponse = await fetch(url)\n\t} catch (err) {\n\t\tthrow new Error(`Network error resolving IPNS ${ipnsName}: ${err}`)\n\t}\n\n\tif (response.status === 404) return null\n\tif (!response.ok) {\n\t\tthrow new Error(`HTTP ${response.status} resolving IPNS ${ipnsName}: ${response.statusText}`)\n\t}\n\n\tconst { record, value } = await response.json()\n\tif (!record && !value) return null // never published\n\n\t// If raw record is available, unmarshal to get sequence\n\tif (record) {\n\t\tconst bytes = base64pad.baseDecode(record)\n\t\tconst entry = unmarshalIPNSRecord(bytes)\n\t\treturn entry.sequence\n\t}\n\n\t// Some servers return value but not raw record — can't get sequence\n\treturn 0n\n}\n\n/**\n * Create a signed IPNS record and publish to all configured targets.\n * Resolves sequence from sequenceServiceUrl, creates record once, fans out.\n * Throws if ALL targets fail; warns on partial failure.\n */\nexport async function publishIPNSRecord(\n\tprivateKey: Uint8Array,\n\tcid: CID,\n\ttargets: IPNSPublishTarget[],\n\tsequenceServiceUrl = 'https://name.web3.storage',\n): Promise<SignedIPNSRecord> {\n\tconst ipnsName = ipnsNameFromPrivateKey(privateKey)\n\tconst currentSeq = await resolveIPNSSequence(sequenceServiceUrl, ipnsName)\n\tconst sequence = currentSeq != null ? currentSeq + 1n : 0n\n\tconst signed = await createSignedIPNSRecord(privateKey, cid, sequence)\n\n\tconst results = await Promise.allSettled(\n\t\ttargets.map(t => t.publish(ipnsName, signed.recordBytes))\n\t)\n\tconst failures = results\n\t\t.map((r, i) => ({ r, name: targets[i].name }))\n\t\t.filter(({ r }) => r.status === 'rejected') as { r: PromiseRejectedResult; name: string }[]\n\n\tif (failures.length > 0 && failures.length < targets.length) {\n\t\t// Partial failure — log but don't throw\n\t\tfor (const { r, name } of failures) {\n\t\t\tconsole.warn(`[publishIPNSRecord] target '${name}' failed:`, r.reason)\n\t\t}\n\t} else if (failures.length === targets.length) {\n\t\tthrow new Error(`All IPNS publish targets failed: ${failures.map(({ r, name }) => `${name}: ${r.reason}`).join('; ')}`)\n\t}\n\n\treturn signed\n}\n"],"mappings":";AAAA,SAAS,kBAAkB,mBAAmB,2BAA2B;AACzE,SAAS,yBAAyB;AAClC,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAWnB,SAAS,uBAAuB,cAAkC;AACxE,QAAM,UAAU,kBAAkB,YAAY;AAC9C,SAAO,QAAQ,UAAU,MAAM,EAAE,SAAS,MAAM;AACjD;AAMA,eAAsB,uBACrB,YACA,KACA,UACA,aAAa,MAAM,KAAK,KAAK,KAAK,KACN;AAC5B,QAAM,UAAU,kBAAkB,UAAU;AAC5C,QAAM,QAAQ,SAAS,IAAI,KAAK,CAAC;AACjC,QAAM,SAAS,MAAM,iBAAiB,SAAS,OAAO,UAAU,UAAU;AAC1E,QAAM,cAAc,kBAAkB,MAAM;AAC5C,QAAM,WAAW,QAAQ,UAAU,MAAM,EAAE,SAAS,MAAM;AAC1D,SAAO,EAAE,aAAa,UAAU,OAAO,SAAS;AACjD;AAeA,eAAsB,oBACrB,gBACA,UACyB;AACzB,QAAM,MAAM,GAAG,cAAc,SAAS,QAAQ;AAC9C,MAAI;AACJ,MAAI;AACH,eAAW,MAAM,MAAM,GAAG;AAAA,EAC3B,SAAS,KAAK;AACb,UAAM,IAAI,MAAM,gCAAgC,QAAQ,KAAK,GAAG,EAAE;AAAA,EACnE;AAEA,MAAI,SAAS,WAAW,IAAK,QAAO;AACpC,MAAI,CAAC,SAAS,IAAI;AACjB,UAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,mBAAmB,QAAQ,KAAK,SAAS,UAAU,EAAE;AAAA,EAC7F;AAEA,QAAM,EAAE,QAAQ,MAAM,IAAI,MAAM,SAAS,KAAK;AAC9C,MAAI,CAAC,UAAU,CAAC,MAAO,QAAO;AAG9B,MAAI,QAAQ;AACX,UAAM,QAAQ,UAAU,WAAW,MAAM;AACzC,UAAM,QAAQ,oBAAoB,KAAK;AACvC,WAAO,MAAM;AAAA,EACd;AAGA,SAAO;AACR;AAOA,eAAsB,kBACrB,YACA,KACA,SACA,qBAAqB,6BACO;AAC5B,QAAM,WAAW,uBAAuB,UAAU;AAClD,QAAM,aAAa,MAAM,oBAAoB,oBAAoB,QAAQ;AACzE,QAAM,WAAW,cAAc,OAAO,aAAa,KAAK;AACxD,QAAM,SAAS,MAAM,uBAAuB,YAAY,KAAK,QAAQ;AAErE,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC7B,QAAQ,IAAI,OAAK,EAAE,QAAQ,UAAU,OAAO,WAAW,CAAC;AAAA,EACzD;AACA,QAAM,WAAW,QACf,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,EAAE,KAAK,EAAE,EAC5C,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,UAAU;AAE3C,MAAI,SAAS,SAAS,KAAK,SAAS,SAAS,QAAQ,QAAQ;AAE5D,eAAW,EAAE,GAAG,KAAK,KAAK,UAAU;AACnC,cAAQ,KAAK,+BAA+B,IAAI,aAAa,EAAE,MAAM;AAAA,IACtE;AAAA,EACD,WAAW,SAAS,WAAW,QAAQ,QAAQ;AAC9C,UAAM,IAAI,MAAM,oCAAoC,SAAS,IAAI,CAAC,EAAE,GAAG,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EACvH;AAEA,SAAO;AACR;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/ipns/gateway-resolver.ts","../src/ipns/ipns-record.ts","../src/ipns/ipns-w3name.ts","../src/ipns/ipns-watcher.ts"],"sourcesContent":["import { CID } from 'multiformats/cid'\nimport { Logger } from 'besonders-logger'\n\nconst { WARN, LOG, DEBUG } = Logger.setup(Logger.INFO) // eslint-disable-line unused-imports/no-unused-vars\n\n/**\n * Resolve an IPNS name to a CID using a public IPFS gateway's HTTP HEAD response.\n *\n * Mechanism: per the IPFS HTTP Gateway spec, `HEAD <gateway>/ipns/<name>/` returns the\n * IPNS-resolved root CID in the `X-Ipfs-Roots` response header (space-separated, ordered\n * from root to leaf). The first entry is the IPNS-resolved CID.\n *\n * This works against any gateway that follows the spec and exposes CORS for HEAD\n * (most public gateways do, e.g. ipfs.zt.ax, ipfs.io, dweb.link).\n *\n * The legacy w3name HTTP endpoint (`GET <base>/name/<ipns>` returning `{value: \"/ipfs/<cid>\"}`)\n * is also supported here for back-compat with self-hosted w3name-like services — but the\n * X-Ipfs-Roots path is preferred since it's the standardised gateway mechanism.\n *\n * @param ipns - The IPNS name (k51... string)\n * @param gateways - List of gateway base URLs (e.g. `[\"https://ipfs.zt.ax\"]`)\n * @returns The resolved CID, or null if no gateway could resolve the name\n */\nexport async function resolveIPNSViaGateway(ipns: string, gateways: string[]): Promise<CID | null> {\n\tif (!ipns.startsWith('k51')) return null // only IPNS libp2p-key names go through gateway\n\tif (!gateways?.length) return null\n\n\tfor (const rawGateway of gateways) {\n\t\tconst gateway = rawGateway.replace(/\\/+$/, '')\n\t\tconst url = `${gateway}/ipns/${ipns}/`\n\t\ttry {\n\t\t\tDEBUG(`[resolveIPNSViaGateway] HEAD ${url}`)\n\t\t\tconst response = await fetch(url, { method: 'HEAD' })\n\t\t\tif (!response.ok) {\n\t\t\t\tDEBUG(`[resolveIPNSViaGateway] ${gateway} returned ${response.status}`)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst roots = response.headers.get('x-ipfs-roots') ?? response.headers.get('X-Ipfs-Roots')\n\t\t\tif (roots) {\n\t\t\t\tconst first = roots.split(/[\\s,]+/)[0]?.trim()\n\t\t\t\tif (first) {\n\t\t\t\t\tconst cid = CID.parse(first)\n\t\t\t\t\tDEBUG(`[resolveIPNSViaGateway] resolved via ${gateway} x-ipfs-roots:`, cid.toString())\n\t\t\t\t\treturn cid\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Some gateways omit X-Ipfs-Roots but put the CID in etag (e.g. `<cid>.dag-json`)\n\t\t\tconst etag = response.headers.get('etag')\n\t\t\tif (etag) {\n\t\t\t\tconst m = etag.match(/^\"?([a-z0-9]+)/i)\n\t\t\t\tif (m) {\n\t\t\t\t\tconst cid = CID.parse(m[1])\n\t\t\t\t\tDEBUG(`[resolveIPNSViaGateway] resolved via ${gateway} etag:`, cid.toString())\n\t\t\t\t\treturn cid\n\t\t\t\t}\n\t\t\t}\n\t\t\tWARN(`[resolveIPNSViaGateway] ${gateway} returned 200 but no usable CID header`)\n\t\t} catch (err) {\n\t\t\tWARN(`[resolveIPNSViaGateway] ${gateway} failed:`, err)\n\t\t}\n\t}\n\treturn null\n}\n","import { createIPNSRecord, marshalIPNSRecord, unmarshalIPNSRecord } from 'ipns'\nimport { privateKeyFromRaw } from '@libp2p/crypto/keys'\nimport { base36 } from 'multiformats/bases/base36'\nimport { base64pad } from 'multiformats/bases/base64'\nimport type { CID } from 'multiformats/cid'\n\nexport interface SignedIPNSRecord {\n\trecordBytes: Uint8Array // marshalled protobuf, signed — the wire format\n\tipnsName: string // k51... string\n\tvalue: string // /ipfs/<cid>\n\tsequence: bigint\n}\n\n/** Derive IPNS name string (k51...) from Ed25519 private key bytes */\nexport function ipnsNameFromPrivateKey(privKeyBytes: Uint8Array): string {\n\tconst privKey = privateKeyFromRaw(privKeyBytes)\n\treturn privKey.publicKey.toCID().toString(base36)\n}\n\n/**\n * Create a signed IPNS record (protobuf wire format).\n * Same bytes can be published to any naming service.\n */\nexport async function createSignedIPNSRecord(\n\tprivateKey: Uint8Array,\n\tcid: CID,\n\tsequence: bigint,\n\tlifetimeMs = 365 * 24 * 60 * 60 * 1000, // 1 year\n): Promise<SignedIPNSRecord> {\n\tconst privKey = privateKeyFromRaw(privateKey)\n\tconst value = `/ipfs/${cid.toV1()}`\n\tconst record = await createIPNSRecord(privKey, value, sequence, lifetimeMs)\n\tconst recordBytes = marshalIPNSRecord(record)\n\tconst ipnsName = privKey.publicKey.toCID().toString(base36)\n\treturn { recordBytes, ipnsName, value, sequence }\n}\n\nexport { unmarshalIPNSRecord }\n\n/**\n * A target that can receive a signed IPNS record, advertise its current\n * sequence, or both.\n *\n * - `publish` is called by `publishIPNSRecord` to actually store the record\n * on the target's backing service. Targets without `publish` are skipped\n * during the fan-out (e.g. a sequence-only source).\n * - `resolveSequence` is consulted by `publishIPNSRecord` to compute the\n * next IPNS sequence. The first target to return a value (including\n * `null` for \"never published\") wins. Throw to indicate a transient\n * error — the caller will try the next target.\n *\n * Most real targets (e.g. a storage connector) provide both. A simple\n * \"track sequence in localStorage\" target only needs `resolveSequence`.\n */\nexport interface IPNSPublishTarget {\n\tname: string\n\tpublish?(ipnsName: string, recordBytes: Uint8Array): Promise<void>\n\tresolveSequence?(ipnsName: string): Promise<bigint | null>\n}\n\n/**\n * Resolve the current IPNS sequence from a generic naming service.\n * Returns null if the name was never published (404).\n * Throws on network/server errors so the caller can try a different target.\n */\nexport async function resolveIPNSSequence(\n\tnameServiceUrl: string,\n\tipnsName: string,\n): Promise<bigint | null> {\n\tconst url = `${nameServiceUrl}/name/${ipnsName}`\n\tlet response: Response\n\ttry {\n\t\tresponse = await fetch(url)\n\t} catch (err) {\n\t\tthrow new Error(`Network error resolving IPNS ${ipnsName}: ${err}`)\n\t}\n\n\tif (response.status === 404) return null\n\tif (!response.ok) {\n\t\tthrow new Error(`HTTP ${response.status} resolving IPNS ${ipnsName}: ${response.statusText}`)\n\t}\n\n\tconst { record, value } = await response.json()\n\tif (!record && !value) return null // never published\n\n\t// If raw record is available, unmarshal to get sequence\n\tif (record) {\n\t\tconst bytes = base64pad.baseDecode(record)\n\t\tconst entry = unmarshalIPNSRecord(bytes)\n\t\treturn entry.sequence\n\t}\n\n\t// Server only returned a value, no raw record — can't know the exact sequence.\n\t// Most services still accept this as \"previous published\"; treat as seq=0n.\n\treturn 0n\n}\n\n/** Regex to detect Kubo IPNS sequence conflict in error messages */\nconst SEQ_CONFLICT_RE = /existing IPNS record has sequence (\\d+) >= new record sequence (\\d+)/\n\n/**\n * Options for {@link publishIPNSRecord}.\n */\nexport interface PublishIPNSRecordOptions {\n\t/**\n\t * Max number of times to bump the sequence on \"existing >= new\" conflict.\n\t * Defaults to 3. Each bump re-signs the record with a higher sequence\n\t * and retries all targets.\n\t */\n\tmaxSequenceBumps?: number\n}\n\n/**\n * Create a signed IPNS record and publish to all configured targets.\n *\n * Sequence resolution: walks `targets` in order asking each one with a\n * `resolveSequence` method. The first target to successfully return a value\n * (including `null` for \"never published\") determines the next sequence.\n * If every target throws or none supports `resolveSequence`, falls back to 0n.\n *\n * Publish fan-out: only targets with a `publish` method are called.\n * Throws if every publish-capable target fails; partial failures are logged.\n *\n * **Sequence-coherence retry:** if a publish target rejects with the Kubo\n * \"existing IPNS record has sequence X >= new record sequence Y\" error,\n * the function parses `X`, bumps the sequence to `max(X + 1n, Y + 1n)`,\n * re-signs the record, and retries (up to `maxSequenceBumps` times).\n * This is the \"increment and clobber\" mechanism that recovers from\n * sequence drift without requiring server-side `--force` support.\n */\nexport async function publishIPNSRecord(\n\tprivateKey: Uint8Array,\n\tcid: CID,\n\ttargets: IPNSPublishTarget[],\n\toptions?: PublishIPNSRecordOptions,\n): Promise<SignedIPNSRecord> {\n\tconst ipnsName = ipnsNameFromPrivateKey(privateKey)\n\tconst maxBumps = options?.maxSequenceBumps ?? 3\n\n\tconst publishTargets = targets.filter(t => typeof t.publish === 'function')\n\tif (publishTargets.length === 0) {\n\t\tthrow new Error('No publish-capable targets supplied to publishIPNSRecord')\n\t}\n\n\tlet sequence: bigint | undefined\n\tlet bumpFloor: bigint | undefined\n\n\tfor (let attempt = 0; ; attempt++) {\n\t\t// Compute next sequence on first pass or after a conflict bump\n\t\tif (sequence === undefined) {\n\t\t\tsequence = await pickNextSequence(ipnsName, targets)\n\t\t}\n\t\tif (bumpFloor !== undefined) {\n\t\t\t// bumpFloor was set on previous attempt from a conflict error\n\t\t\tif (bumpFloor > sequence) sequence = bumpFloor\n\t\t\tbumpFloor = undefined\n\t\t}\n\n\t\tconst signed = await createSignedIPNSRecord(privateKey, cid, sequence)\n\n\t\tconst results = await Promise.allSettled(\n\t\t\tpublishTargets.map(t => t.publish!(ipnsName, signed.recordBytes)),\n\t\t)\n\t\tconst failures = results\n\t\t\t.map((r, i) => ({ r, name: publishTargets[i].name }))\n\t\t\t.filter(({ r }) => r.status === 'rejected') as { r: PromiseRejectedResult; name: string }[]\n\n\t\t// All succeeded — done\n\t\tif (failures.length === 0) {\n\t\t\treturn signed\n\t\t}\n\n\t\t// Check if any failure is a sequence conflict we can recover from\n\t\tconst conflictReasons = failures.filter(({ r }) =>\n\t\t\tSEQ_CONFLICT_RE.test(typeof r.reason === 'string' ? r.reason : String(r.reason)),\n\t\t)\n\n\t\tif (conflictReasons.length > 0 && attempt < maxBumps) {\n\t\t\t// Parse the highest existing sequence from each conflict error\n\t\t\tlet bump = sequence\n\t\t\tfor (const { r } of conflictReasons) {\n\t\t\t\tconst msg = typeof r.reason === 'string' ? r.reason : String(r.reason)\n\t\t\t\tconst m = msg.match(SEQ_CONFLICT_RE)\n\t\t\t\tif (m) {\n\t\t\t\t\tconst existing = BigInt(m[1])\n\t\t\t\t\tif (existing >= bump) bump = existing + 1n\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (bump > sequence) {\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`[publishIPNSRecord] Sequence conflict: server seq ${bump - 1n} >= current ${sequence}, ` +\n\t\t\t\t\t`bumping to ${bump} (attempt ${attempt + 1}/${maxBumps})`,\n\t\t\t\t)\n\t\t\t\tsequence = bump\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\t// Partial failure (some targets succeeded) — log and return the signed record\n\t\tif (failures.length < publishTargets.length) {\n\t\t\tfor (const { r, name } of failures) {\n\t\t\t\tconsole.warn(`[publishIPNSRecord] target '${name}' failed:`, r.reason)\n\t\t\t}\n\t\t\treturn signed\n\t\t}\n\n\t\t// Every publish-capable target failed and we cannot recover\n\t\tif (conflictReasons.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`IPNS sequence conflict not resolved after ${Math.min(attempt + 1, maxBumps)} bumps. ` +\n\t\t\t\t`All publish targets failed: ${failures.map(({ r, name }) => `${name}: ${r.reason}`).join('; ')}`,\n\t\t\t)\n\t\t}\n\t\tthrow new Error(\n\t\t\t`All IPNS publish targets failed: ${failures.map(({ r, name }) => `${name}: ${r.reason}`).join('; ')}`,\n\t\t)\n\t}\n}\n\n/**\n * Walk targets, asking each to resolve the current IPNS sequence. First success wins.\n * Falls back to 0n if no target can answer.\n */\nasync function pickNextSequence(\n\tipnsName: string,\n\ttargets: IPNSPublishTarget[],\n): Promise<bigint> {\n\tconst capable = targets.filter(t => typeof t.resolveSequence === 'function')\n\tif (capable.length === 0) {\n\t\treturn 0n\n\t}\n\n\tfor (const target of capable) {\n\t\ttry {\n\t\t\tconst current = await target.resolveSequence!(ipnsName)\n\t\t\treturn current == null ? 0n : current + 1n\n\t\t} catch (err) {\n\t\t\tconsole.warn(`[publishIPNSRecord] target '${target.name}' sequence resolve failed:`, err)\n\t\t}\n\t}\n\n\tconsole.warn(`[publishIPNSRecord] no target could resolve sequence for ${ipnsName} — starting at 0n`)\n\treturn 0n\n}\n","import type { IPNSPublishTarget } from '@wovin/core/ipns'\nimport { Logger } from 'besonders-logger'\nimport { base64pad } from 'multiformats/bases/base64'\nimport { resolveIPNSSequence, unmarshalIPNSRecord } from './ipns-record.ts'\nimport { CID } from 'multiformats/cid'\nimport * as W3Name from 'w3name'\n\nconst { WARN, LOG, DEBUG, ERROR } = Logger.setup(Logger.INFO)\n\n/**\n * Try to resolve IPNS name to get existing revision.\n * Returns null if record doesn't exist (404).\n * Throws on network errors or server errors.\n *\n * This does a custom HTTP check first to distinguish 404 from network errors,\n * then delegates to W3Name.resolve() for validation if record exists.\n */\nasync function tryResolveIPNS(ipns: W3Name.WritableName): Promise<W3Name.Revision | null> {\n\tconst url = `https://name.web3.storage/name/${ipns.toString()}`\n\n\tlet response: Response\n\ttry {\n\t\tresponse = await fetch(url, { signal: AbortSignal.timeout(30_000) })\n\t} catch (err) {\n\t\t// Network error (no connection, DNS failure, etc.)\n\t\tthrow ERROR('[w3name] Network error resolving IPNS:', err)\n\t}\n\n\t// 404 = record never published\n\tif (response.status === 404) {\n\t\tDEBUG('[w3name] IPNS record not found (never published):', ipns.toString())\n\t\treturn null\n\t}\n\n\t// Other HTTP errors (5xx server error, etc.)\n\tif (!response.ok) {\n\t\tthrow ERROR(`[w3name] HTTP ${response.status} resolving IPNS:`, response.statusText)\n\t}\n\n\t// Success - use W3Name.resolve to get validated Revision\n\t// (We could parse the record ourselves, but W3Name does validation/signature checks)\n\tconst existing = await W3Name.resolve(ipns)\n\treturn existing\n}\n\n/**\n * Publish CID to IPNS, automatically handling increment vs v0.\n * Returns the revision for further processing (e.g., Kubo integration).\n */\nexport async function publishIPNS(ipnsPrivateKey: Uint8Array, cid: CID): Promise<W3Name.Revision> {\n\tconst TIMEOUT_MS = 30_000\n\tconst timeout = new Promise<never>((_, reject) =>\n\t\tsetTimeout(() => reject(new Error(`publishIPNS timed out after ${TIMEOUT_MS}ms`)), TIMEOUT_MS),\n\t)\n\treturn Promise.race([_publishIPNSImpl(ipnsPrivateKey, cid), timeout])\n}\n\nasync function _publishIPNSImpl(ipnsPrivateKey: Uint8Array, cid: CID): Promise<W3Name.Revision> {\n\tconst value = `/ipfs/${cid}`\n\tconst ipns = await W3Name.from(ipnsPrivateKey)\n\n\tlet revision: W3Name.Revision\n\tconst existing = await tryResolveIPNS(ipns)\n\n\tif (existing) {\n\t\t// Record exists - increment sequence number\n\t\trevision = await W3Name.increment(existing, value)\n\t\tDEBUG('[w3name] incrementing revision for', ipns.toString())\n\t} else {\n\t\t// First publish - use v0\n\t\trevision = await W3Name.v0(ipns, value)\n\t\tDEBUG('[w3name] creating initial revision for', ipns.toString())\n\t}\n\n\tawait W3Name.publish(revision, ipns.key)\n\tDEBUG('[w3name] published', cid.toString(), 'to', ipns.toString())\n\n\treturn revision // Return for Kubo integration or other uses\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// zt.ax naming service target (primary)\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Resolve the current IPNS sequence from a zt.ax-compatible naming service.\n *\n * The naming service API uses the simple W3NameRecord format:\n * `GET <baseUrl>/<ipnsName>` → `{ value: \"/ipfs/<cid>\", seq?: number, validity?: string }`\n *\n * Also supports the legacy w3name record format (`{ record: \"<base64>\", value: \"...\" }`)\n * for backward compatibility with hybrid services.\n */\nexport async function resolveZtaxSequence(\n\tbaseUrl: string,\n\tipnsName: string,\n): Promise<bigint | null> {\n\tconst url = `${baseUrl.replace(/\\/+$/, '')}/${ipnsName}`\n\tlet response: Response\n\ttry {\n\t\tresponse = await fetch(url)\n\t} catch (err) {\n\t\tthrow new Error(`Network error resolving sequence from ${baseUrl}: ${err}`)\n\t}\n\n\tif (response.status === 404) return null\n\tif (!response.ok) {\n\t\tthrow new Error(`HTTP ${response.status} resolving sequence from ${baseUrl}: ${response.statusText}`)\n\t}\n\n\tconst body: Record<string, unknown> = await response.json()\n\n\t// Format 1: simple W3NameRecord with seq number\n\tif (typeof body.seq === 'number') {\n\t\treturn BigInt(body.seq)\n\t}\n\n\t// Format 2: legacy w3name record with base64-encoded protobuf\n\tif (typeof body.record === 'string') {\n\t\ttry {\n\t\t\tconst bytes = base64pad.baseDecode(body.record)\n\t\t\tconst entry = unmarshalIPNSRecord(bytes)\n\t\t\treturn entry.sequence\n\t\t} catch {\n\t\t\tWARN('[resolveZtaxSequence] failed to unmarshal record for', ipnsName)\n\t\t\treturn null\n\t\t}\n\t}\n\n\t// No sequence info — treat as never published or zero\n\treturn null\n}\n\n/**\n * Create an IPNSPublishTarget that publishes to a zt.ax naming service.\n *\n * Uses HTTP POST to publish signed IPNS records and HTTP GET to resolve\n * the current sequence number, following the same wire format as the\n * standard w3name API but at a configurable base URL.\n *\n * The naming service is expected to support:\n * - `POST <baseUrl>/<ipnsName>` — publish signed IPNS record (base64-encoded body)\n * - `GET <baseUrl>/<ipnsName>` — resolve current record (`{ value, seq?, record? }`)\n *\n * @param baseUrl - Base URL of the naming service (default: https://ipfs.zt.ax)\n */\nexport function ztaxTarget(baseUrl = 'https://ipfs.zt.ax'): IPNSPublishTarget {\n\tconst cleanBase = baseUrl.replace(/\\/+$/, '')\n\treturn {\n\t\tname: 'zt.ax',\n\t\tasync publish(ipnsName: string, recordBytes: Uint8Array) {\n\t\t\tconst url = `${cleanBase}/${ipnsName}`\n\t\t\tDEBUG(`[ztaxTarget] POST ${url}`)\n\t\t\tconst res = await fetch(url, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: base64pad.baseEncode(recordBytes),\n\t\t\t})\n\t\t\tif (!res.ok) {\n\t\t\t\tlet detail = ''\n\t\t\t\ttry {\n\t\t\t\t\tconst body = await res.json() as Record<string, unknown>\n\t\t\t\t\tdetail = body.message ? ` — ${body.message}` : ''\n\t\t\t\t} catch {\n\t\t\t\t\tdetail = res.statusText ? ` — ${res.statusText}` : ''\n\t\t\t\t}\n\t\t\t\tthrow new Error(`zt.ax HTTP ${res.status}${detail}`)\n\t\t\t}\n\t\t},\n\t\tasync resolveSequence(ipnsName: string): Promise<bigint | null> {\n\t\t\treturn resolveZtaxSequence(cleanBase, ipnsName)\n\t\t},\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// w3name naming service target (deprecated — read‑only backup)\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Create an IPNSPublishTarget for the w3name service.\n *\n * @deprecated w3name is shut down for publishing. This target is kept as a\n * read‑only backup for sequence resolution only (no publish method).\n * Use {@link ztaxTarget} for all publishing.\n *\n * @param serviceUrl - Base URL of the w3name-compatible service (default: https://name.web3.storage)\n */\nexport function w3nameTarget(serviceUrl = 'https://name.web3.storage'): IPNSPublishTarget {\n\treturn {\n\t\tname: 'w3name',\n\t\t// No publish() — w3name is read-only; publishing goes through ztaxTarget\n\t\tasync resolveSequence(ipnsName: string): Promise<bigint | null> {\n\t\t\treturn resolveIPNSSequence(serviceUrl, ipnsName)\n\t\t},\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport async function generateIpnsKey() {\n\treturn W3Name.create() // Returns W3Name.WritableName type\n}\n\nexport async function getW3NamePublic(pk: Uint8Array) {\n\tconst ipns = await W3Name.from(pk)\n\treturn ipns.toString()\n}\n","import { Logger } from 'besonders-logger'\nimport { CID } from 'multiformats/cid'\nimport ReconnectingWebSocket, { type Options as PartysocketOptions } from 'partysocket/ws'\n\nexport type { PartysocketOptions }\n\nconst { WARN, LOG, DEBUG, ERROR } = Logger.setup(Logger.INFO) // eslint-disable-line unused-imports/no-unused-vars\n\n/**\n * `nameBaseUrl` is required for both `watchNameRaw` and `IpnsWatcher`. The\n * legacy `https://name.web3.storage` endpoint (used by the old hardcoded\n * `NAME_WS_URL`/`NAME_HTTP_URL` constants) is **shut down** — these classes\n * will not work without a real, configured naming service that supports\n * WebSocket subscriptions to `/name/<ipns>/watch` and HTTP GET on `/name/<ipns>`.\n *\n * As of writing no such public service exists, so most callers should expect\n * these to fail at runtime and handle the error in their `onError` handler.\n */\nfunction buildWsUrl(nameBaseUrl: string, name: string) {\n\tconst base = nameBaseUrl.replace(/\\/+$/, '').replace(/^http/, 'ws')\n\treturn `${base}/${name}/watch`\n}\nfunction buildHttpUrl(nameBaseUrl: string, name: string) {\n\tconst base = nameBaseUrl.replace(/\\/+$/, '')\n\treturn `${base}/${name}`\n}\n\nfunction requireNameBaseUrl(nameBaseUrl: string | undefined, fn: string): string {\n\tif (!nameBaseUrl) {\n\t\tthrow new Error(\n\t\t\t`[${fn}] nameBaseUrl is required. The legacy default `\n\t\t\t+ `https://name.web3.storage is shut down. Pass the base URL of a naming `\n\t\t\t+ `service that supports WebSocket subscriptions to /name/<ipns>/watch `\n\t\t\t+ `and HTTP GET on /name/<ipns>.`,\n\t\t)\n\t}\n\treturn nameBaseUrl\n}\n\nexport interface W3NameRecord {\n\tvalue: string // e.g. \"/ipfs/bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi\"\n\tseq?: number\n\tvalidity?: string\n}\n\n/**\n * Debug info provided when a stale WebSocket connection is detected.\n */\nexport interface StaleConnectionInfo {\n\t/** When the WebSocket connection was established */\n\tconnectedAt: Date\n\t/** When we last received a WebSocket message */\n\tlastMessageAt: Date | null\n\t/** How long since last message (ms) */\n\tsilenceDuration: number\n\t/** The stale value from WebSocket */\n\tstaleValue: string | null\n\t/** The current value from HTTP */\n\tcurrentValue: string\n}\n\n/**\n * Enriched IPNS update with parsed CID and change detection.\n * Backwards compatible - `.value` still works as before.\n */\nexport interface IpnsUpdate {\n\t/** Raw IPNS value string (e.g. '/ipfs/bafy...') — same as W3NameRecord.value */\n\tvalue: string\n\t/** Parsed CID if value is valid IPFS path, null otherwise */\n\tcid: CID | null\n\t/** Previous value (null on first update) */\n\tlastValue: string | null\n\t/** Whether this is a change from lastValue */\n\tisNew: boolean\n\t/** Original W3NameRecord for access to seq/validity */\n\trecord: W3NameRecord\n}\n\n/**\n * Parse CID from IPNS value string (e.g. \"/ipfs/bafybeig...\")\n * @returns CID if valid, null otherwise\n */\nfunction parseCidFromIpnsValue(value: string): CID | null {\n\ttry {\n\t\t// Strip /ipfs/ prefix if present\n\t\tconst cidStr = value.startsWith('/ipfs/') ? value.slice(6) : value\n\t\treturn CID.parse(cidStr)\n\t} catch {\n\t\tDEBUG('[parseCidFromIpnsValue] failed to parse:', value)\n\t\treturn null\n\t}\n}\n\nexport interface WatchRawOptions {\n\t/** Called when the IPNS record is updated */\n\tonUpdate: (record: W3NameRecord) => void\n\t/** Called when an error occurs */\n\tonError?: (error: Event | Error) => void\n\t/** Called when the connection is opened */\n\tonOpen?: () => void\n\t/** Called when the connection is closed */\n\tonClose?: (event: CloseEvent) => void\n}\n\nexport interface WatchRawSubscription {\n\t/** Close the WebSocket connection */\n\tclose: () => void\n\t/** The underlying WebSocket instance */\n\tws: WebSocket\n}\n\n/**\n * Low-level WebSocket watcher for IPNS (no reconnect logic).\n * Use this when you want full control over connection lifecycle.\n * For most cases, prefer `watchName` or `IpnsWatcher` which handle reconnection.\n *\n * @param nameBaseUrl - Base URL of a naming service that supports `/name/<ipns>/watch` (WebSocket) and `/name/<ipns>` (HTTP)\n * @param name - The IPNS name/key to watch\n * @param options - Callback options\n * @returns Subscription with close() and ws\n *\n * @example\n * ```ts\n * const sub = watchNameRaw('https://name.example.com', 'k51qzi5u...', {\n * onUpdate: (record) => console.log('Update:', record.value),\n * onClose: () => console.log('Disconnected - handle reconnect yourself'),\n * })\n * ```\n */\nexport function watchNameRaw(nameBaseUrl: string, name: string, options: WatchRawOptions): WatchRawSubscription {\n\tconst resolvedBase = requireNameBaseUrl(nameBaseUrl, 'watchNameRaw')\n\tconst url = buildWsUrl(resolvedBase, name)\n\tDEBUG('[watchNameRaw] connecting to', url)\n\n\tconst ws = new WebSocket(url)\n\n\tws.onopen = () => {\n\t\tLOG('[watchNameRaw] connected to', name)\n\t\toptions.onOpen?.()\n\t}\n\n\tws.onmessage = (event) => {\n\t\ttry {\n\t\t\tconst record: W3NameRecord = JSON.parse(event.data)\n\t\t\tDEBUG('[watchNameRaw] received update for', name, record)\n\t\t\toptions.onUpdate(record)\n\t\t} catch (err) {\n\t\t\tWARN('[watchNameRaw] failed to parse message:', event.data, err)\n\t\t\toptions.onError?.(err instanceof Error ? err : new Error(String(err)))\n\t\t}\n\t}\n\n\tws.onerror = (event) => {\n\t\tconst errorMsg = event instanceof ErrorEvent ? event.message : 'WebSocket error'\n\t\tWARN('[watchNameRaw] error for', name, ':', errorMsg)\n\t\toptions.onError?.(new Error(errorMsg))\n\t}\n\n\tws.onclose = (event) => {\n\t\tDEBUG('[watchNameRaw] closed for', name, 'code:', event.code)\n\t\toptions.onClose?.(event)\n\t}\n\n\treturn {\n\t\tclose: () => {\n\t\t\tDEBUG('[watchNameRaw] closing connection for', name)\n\t\t\tws.close()\n\t\t},\n\t\tws,\n\t}\n}\n\nexport interface IpnsWatcherOptions {\n\t/** Called when the IPNS record is updated (enriched payload with CID and change detection) */\n\tonUpdate: (update: IpnsUpdate) => void | Promise<void>\n\t/** Called when an error occurs */\n\tonError?: (error: Error | Event) => void\n\t/** Called when the connection is opened/reconnected */\n\tonConnected?: () => void\n\t/** Called when the connection is closed */\n\tonDisconnected?: () => void\n\t/** Fetch current IPNS state on first connect (default: false) */\n\tfetchInitialState?: boolean\n\t/** Fetch current IPNS state on reconnect to catch missed updates (default: true) */\n\tcatchUpOnReconnect?: boolean\n\t/** If true, call onUpdate even when value hasn't changed (default: false) */\n\tincludeUnchanged?: boolean\n\t/**\n\t * Enable periodic liveness checks via HTTP to detect zombie connections (default: true).\n\t * When enabled, periodically fetches current IPNS value and forces reconnect if it\n\t * differs from the last WebSocket update.\n\t */\n\tlivenessCheck?: boolean\n\t/**\n\t * Liveness check interval in milliseconds (default: 3600000 = 1 hour).\n\t * Only used when livenessCheck is enabled.\n\t */\n\tlivenessCheckInterval?: number\n\t/**\n\t * Called when a stale connection is detected (WebSocket missed updates).\n\t * Provides debug info about the connection state.\n\t */\n\tonStaleConnection?: (info: StaleConnectionInfo) => void\n\t/**\n\t * Partysocket options (passed through to ReconnectingWebSocket).\n\t * Useful options: startClosed, maxReconnectionDelay, minReconnectionDelay, etc.\n\t * @see https://github.com/partykit/partykit/tree/main/packages/partysocket\n\t */\n\twsOptions?: PartysocketOptions\n}\n\n/**\n * Robust IPNS watcher with auto-reconnect and catch-up logic.\n * Uses partysocket for reliable WebSocket reconnection.\n *\n * @example\n * ```ts\n * const watcher = new IpnsWatcher('k51qzi5uqu...', {\n * onUpdate: (update) => console.log('New CID:', update.cid?.toString()),\n * onError: (err) => console.error('Error:', err),\n * })\n *\n * // Later, to stop watching:\n * watcher.close()\n * ```\n */\nconst DEFAULT_LIVENESS_INTERVAL = 3600000 // 1 hour\n\nexport class IpnsWatcher {\n\tprivate name: string\n\tprivate nameBaseUrl: string\n\tprivate ws: ReconnectingWebSocket\n\tprivate lastKnownValue: string | null = null\n\tprivate options: IpnsWatcherOptions\n\tprivate isFirstConnect = true\n\tprivate livenessTimer: ReturnType<typeof setInterval> | null = null\n\tprivate connectedAt: Date | null = null\n\tprivate lastMessageAt: Date | null = null\n\n\tconstructor(nameBaseUrl: string, name: string, options: IpnsWatcherOptions) {\n\t\tthis.nameBaseUrl = requireNameBaseUrl(nameBaseUrl, 'IpnsWatcher')\n\t\tthis.name = name\n\t\tthis.options = options\n\n\t\tconst url = buildWsUrl(this.nameBaseUrl, name)\n\t\tDEBUG('[IpnsWatcher] creating for', name)\n\n\t\tthis.ws = new ReconnectingWebSocket(url, [], {\n\t\t\tmaxReconnectionDelay: 900000, // 15min\n\t\t\tminReconnectionDelay: 5000,\n\t\t\treconnectionDelayGrowFactor: 2,\n\t\t\tmaxRetries: Infinity,\n\t\t\t...options.wsOptions,\n\t\t})\n\n\t\tthis.ws.onopen = () => {\n\t\t\tLOG('[IpnsWatcher] connected to', name)\n\t\t\tthis.connectedAt = new Date()\n\t\t\toptions.onConnected?.()\n\n\t\t\t// Check for current state on first connect if requested\n\t\t\tif (this.isFirstConnect && (options.fetchInitialState ?? false)) {\n\t\t\t\tthis.checkForMissedUpdates()\n\t\t\t}\n\t\t\t// Check for missed updates on reconnect\n\t\t\telse if (!this.isFirstConnect && (options.catchUpOnReconnect ?? true)) {\n\t\t\t\tthis.checkForMissedUpdates()\n\t\t\t}\n\n\t\t\tthis.isFirstConnect = false\n\n\t\t\t// Start liveness checking (default: enabled)\n\t\t\tif (options.livenessCheck !== false) {\n\t\t\t\tthis.startLivenessCheck()\n\t\t\t}\n\t\t}\n\n\t\tthis.ws.onmessage = (event) => {\n\t\t\tthis.lastMessageAt = new Date()\n\t\t\ttry {\n\t\t\t\tconst record: W3NameRecord = JSON.parse(event.data as string)\n\t\t\t\tDEBUG('[IpnsWatcher] received update for', name, record)\n\n\t\t\t\tconst lastValue = this.lastKnownValue\n\t\t\t\tconst isNew = record.value !== lastValue\n\t\t\t\tconst cid = parseCidFromIpnsValue(record.value)\n\n\t\t\t\t// Skip unchanged values unless includeUnchanged is set\n\t\t\t\tif (!isNew && !options.includeUnchanged) {\n\t\t\t\t\tDEBUG('[IpnsWatcher] skipping unchanged value for', name)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Update lastKnownValue after the skip check\n\t\t\t\tthis.lastKnownValue = record.value\n\n\t\t\t\tconst update: IpnsUpdate = {\n\t\t\t\t\tvalue: record.value,\n\t\t\t\t\tcid,\n\t\t\t\t\tlastValue,\n\t\t\t\t\tisNew,\n\t\t\t\t\trecord,\n\t\t\t\t}\n\n\t\t\t\tvoid options.onUpdate(update)\n\t\t\t} catch (err) {\n\t\t\t\tWARN('[IpnsWatcher] failed to parse message:', event.data, err)\n\t\t\t\toptions.onError?.(err instanceof Error ? err : new Error(String(err)))\n\t\t\t}\n\t\t}\n\n\t\tthis.ws.onerror = (event) => {\n\t\t\t// Extract meaningful error info instead of logging entire ErrorEvent\n\t\t\tconst errorMsg = event instanceof ErrorEvent ? event.message : 'WebSocket error'\n\n\t\t\t// \"Unexpected EOF\" is a normal disconnection - partysocket will auto-reconnect\n\t\t\t// Log at INFO level as it's expected behavior, not an error\n\t\t\tif (errorMsg === 'Unexpected EOF') {\n\t\t\t\tLOG('[IpnsWatcher] error for', name, ':', errorMsg, '(auto-reconnect enabled)')\n\t\t\t} else {\n\t\t\t\tWARN('[IpnsWatcher] error for', name, ':', errorMsg)\n\t\t\t}\n\n\t\t\t// Still call the error handler for unexpected errors\n\t\t\tif (errorMsg !== 'Unexpected EOF') {\n\t\t\t\toptions.onError?.(new Error(errorMsg))\n\t\t\t}\n\t\t}\n\n\t\tthis.ws.onclose = () => {\n\t\t\tDEBUG('[IpnsWatcher] disconnected from', name)\n\t\t\tthis.stopLivenessCheck()\n\t\t\tthis.connectedAt = null\n\t\t\tthis.lastMessageAt = null\n\t\t\toptions.onDisconnected?.()\n\t\t}\n\t}\n\n\t/**\n\t * Resolve current IPNS value via HTTP API to catch missed updates\n\t */\n\tprivate async checkForMissedUpdates(): Promise<void> {\n\t\ttry {\n\t\t\tDEBUG('[IpnsWatcher] checking for missed updates for', this.name)\n\t\t\tconst response = await fetch(buildHttpUrl(this.nameBaseUrl, this.name))\n\n\t\t\tif (!response.ok) {\n\t\t\t\tif (response.status === 404) {\n\t\t\t\t\tDEBUG('[IpnsWatcher] IPNS not yet published:', this.name)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthrow new Error(`HTTP ${response.status}: ${response.statusText}`)\n\t\t\t}\n\n\t\t\tconst record: W3NameRecord = await response.json()\n\t\t\tconst lastValue = this.lastKnownValue\n\t\t\tconst isNew = record.value !== lastValue\n\t\t\tconst cid = parseCidFromIpnsValue(record.value)\n\n\t\t\t// Skip unchanged values unless includeUnchanged is set\n\t\t\tif (!isNew && !this.options.includeUnchanged) {\n\t\t\t\tDEBUG('[IpnsWatcher] no new updates for', this.name)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst logMsg = lastValue === null\n\t\t\t\t? '[IpnsWatcher] fetched initial state for'\n\t\t\t\t: '[IpnsWatcher] caught missed update for'\n\t\t\tLOG(logMsg, this.name, {\n\t\t\t\tprevious: lastValue,\n\t\t\t\tcurrent: record.value,\n\t\t\t})\n\n\t\t\t// Update lastKnownValue after the skip check\n\t\t\tthis.lastKnownValue = record.value\n\n\t\t\tconst update: IpnsUpdate = {\n\t\t\t\tvalue: record.value,\n\t\t\t\tcid,\n\t\t\t\tlastValue,\n\t\t\t\tisNew,\n\t\t\t\trecord,\n\t\t\t}\n\n\t\t\tvoid this.options.onUpdate(update)\n\t\t} catch (err) {\n\t\t\tWARN('[IpnsWatcher] failed to check for missed updates:', this.name, err)\n\t\t\tthis.options.onError?.(err instanceof Error ? err : new Error(String(err)))\n\t\t}\n\t}\n\n\t/**\n\t * Start periodic liveness checks to detect zombie connections.\n\t */\n\tprivate startLivenessCheck(): void {\n\t\tthis.stopLivenessCheck() // Clear any existing timer\n\t\tconst interval = this.options.livenessCheckInterval ?? DEFAULT_LIVENESS_INTERVAL\n\t\tDEBUG('[IpnsWatcher] starting liveness check for', this.name, 'interval:', interval)\n\n\t\tthis.livenessTimer = setInterval(() => {\n\t\t\tvoid this.performLivenessCheck()\n\t\t}, interval)\n\t}\n\n\t/**\n\t * Stop periodic liveness checks.\n\t */\n\tprivate stopLivenessCheck(): void {\n\t\tif (this.livenessTimer !== null) {\n\t\t\tDEBUG('[IpnsWatcher] stopping liveness check for', this.name)\n\t\t\tclearInterval(this.livenessTimer)\n\t\t\tthis.livenessTimer = null\n\t\t}\n\t}\n\n\t/**\n\t * Perform a single liveness check via HTTP.\n\t * If the HTTP value differs from lastKnownValue, the connection is stale.\n\t */\n\tprivate async performLivenessCheck(): Promise<void> {\n\t\ttry {\n\t\t\tDEBUG('[IpnsWatcher] performing liveness check for', this.name)\n\t\t\tconst response = await fetch(buildHttpUrl(this.nameBaseUrl, this.name))\n\n\t\t\tif (!response.ok) {\n\t\t\t\tif (response.status === 404) {\n\t\t\t\t\t// IPNS not published - if we also have null, that's consistent\n\t\t\t\t\tif (this.lastKnownValue === null) {\n\t\t\t\t\t\tDEBUG('[IpnsWatcher] liveness check OK (both null) for', this.name)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\t// We have a value but HTTP says 404 - this shouldn't happen normally\n\t\t\t\t\tWARN('[IpnsWatcher] liveness check inconsistent (we have value, HTTP 404) for', this.name)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthrow new Error(`HTTP ${response.status}: ${response.statusText}`)\n\t\t\t}\n\n\t\t\tconst record: W3NameRecord = await response.json()\n\n\t\t\t// Check if values match\n\t\t\tif (record.value === this.lastKnownValue) {\n\t\t\t\tDEBUG('[IpnsWatcher] liveness check OK for', this.name)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Stale connection detected!\n\t\t\tconst now = new Date()\n\t\t\tconst silenceDuration = this.lastMessageAt\n\t\t\t\t? now.getTime() - this.lastMessageAt.getTime()\n\t\t\t\t: this.connectedAt\n\t\t\t\t\t? now.getTime() - this.connectedAt.getTime()\n\t\t\t\t\t: 0\n\n\t\t\tconst staleInfo: StaleConnectionInfo = {\n\t\t\t\tconnectedAt: this.connectedAt ?? now,\n\t\t\t\tlastMessageAt: this.lastMessageAt,\n\t\t\t\tsilenceDuration,\n\t\t\t\tstaleValue: this.lastKnownValue,\n\t\t\t\tcurrentValue: record.value,\n\t\t\t}\n\n\t\t\tWARN('[IpnsWatcher] stale connection detected for', this.name, {\n\t\t\t\tconnectedAt: staleInfo.connectedAt.toISOString(),\n\t\t\t\tlastMessageAt: staleInfo.lastMessageAt?.toISOString() ?? 'never',\n\t\t\t\tsilenceDuration: `${Math.round(silenceDuration / 1000)}s`,\n\t\t\t\tstaleValue: staleInfo.staleValue,\n\t\t\t\tcurrentValue: staleInfo.currentValue,\n\t\t\t})\n\n\t\t\t// Notify via callback\n\t\t\tthis.options.onStaleConnection?.(staleInfo)\n\n\t\t\t// Fire immediate update with the current value\n\t\t\tconst lastValue = this.lastKnownValue\n\t\t\tconst cid = parseCidFromIpnsValue(record.value)\n\t\t\tthis.lastKnownValue = record.value\n\n\t\t\tconst update: IpnsUpdate = {\n\t\t\t\tvalue: record.value,\n\t\t\t\tcid,\n\t\t\t\tlastValue,\n\t\t\t\tisNew: true,\n\t\t\t\trecord,\n\t\t\t}\n\t\t\tvoid this.options.onUpdate(update)\n\n\t\t\t// Force reconnect to get a fresh connection\n\t\t\tLOG('[IpnsWatcher] forcing reconnect due to stale connection for', this.name)\n\t\t\tthis.ws.reconnect()\n\t\t} catch (err) {\n\t\t\t// Don't treat HTTP errors as stale - could be network issue\n\t\t\tWARN('[IpnsWatcher] liveness check failed for', this.name, err)\n\t\t}\n\t}\n\n\t/**\n\t * Manually start/reconnect the WebSocket.\n\t * Only needed if you used `wsOptions: { startClosed: true }`.\n\t */\n\tstart(): void {\n\t\tLOG('[IpnsWatcher] starting watcher for', this.name)\n\t\tthis.ws.reconnect()\n\t}\n\n\t/**\n\t * Alias for close() - for backward compatibility\n\t */\n\tstop(): void {\n\t\tthis.close()\n\t}\n\n\t/**\n\t * Close the WebSocket connection and stop watching\n\t */\n\tclose(): void {\n\t\tLOG('[IpnsWatcher] closing watcher for', this.name)\n\t\tthis.stopLivenessCheck()\n\t\tthis.ws.close()\n\t}\n\n\t/**\n\t * Get the last known IPNS value\n\t */\n\tget lastValue(): string | null {\n\t\treturn this.lastKnownValue\n\t}\n\n\t/**\n\t * Get the WebSocket ready state\n\t */\n\tget readyState(): number {\n\t\treturn this.ws.readyState\n\t}\n}\n\n/**\n * Create an IPNS watcher with auto-reconnect and catch-up logic.\n * Convenience function that creates and returns an IpnsWatcher instance.\n *\n * @param nameBaseUrl - Base URL of a naming service that supports `/name/<ipns>/watch` (WebSocket) and `/name/<ipns>` (HTTP)\n * @param name - The IPNS name/key to watch (e.g. \"k51qzi5u...\")\n * @param options - Callback options for handling events\n * @returns An IpnsWatcher instance with close() method\n */\nexport function watchName(nameBaseUrl: string, name: string, options: IpnsWatcherOptions): IpnsWatcher {\n\treturn new IpnsWatcher(nameBaseUrl, name, options)\n}\n\n/**\n * Watch an IPNS name and return updates as an async iterator.\n * Includes auto-reconnect - iterator continues through disconnections.\n *\n * @param nameBaseUrl - Base URL of a naming service that supports `/name/<ipns>/watch` (WebSocket) and `/name/<ipns>` (HTTP)\n * @param name - The IPNS name/key to watch\n * @param signal - Optional AbortSignal to stop the watch\n *\n * @example\n * ```ts\n * const controller = new AbortController()\n * for await (const update of watchNameIterator('https://name.example.com', 'k51qzi5u...', controller.signal)) {\n * console.log('Update:', update.cid?.toString())\n * }\n * ```\n */\nexport async function* watchNameIterator(\n\tnameBaseUrl: string,\n\tname: string,\n\tsignal?: AbortSignal,\n): AsyncGenerator<IpnsUpdate, void, unknown> {\n\tconst queue: IpnsUpdate[] = []\n\tlet resolve: (() => void) | null = null\n\tlet error: Error | null = null\n\n\tconst watcher = new IpnsWatcher(nameBaseUrl, name, {\n\t\tonUpdate: (update) => {\n\t\t\tqueue.push(update)\n\t\t\tresolve?.()\n\t\t},\n\t\tonError: (err) => {\n\t\t\terror = err instanceof Error ? err : new Error('WebSocket error')\n\t\t\tresolve?.()\n\t\t},\n\t})\n\n\tsignal?.addEventListener('abort', () => {\n\t\twatcher.close()\n\t})\n\n\ttry {\n\t\twhile (!signal?.aborted) {\n\t\t\tif (queue.length > 0) {\n\t\t\t\tyield queue.shift()!\n\t\t\t} else if (error) {\n\t\t\t\t// Log error but continue - partysocket will reconnect\n\t\t\t\tWARN('[watchNameIterator] error occurred, continuing:', error)\n\t\t\t\terror = null\n\t\t\t} else {\n\t\t\t\tawait new Promise<void>((r) => {\n\t\t\t\t\tresolve = r\n\t\t\t\t})\n\t\t\t\tresolve = null\n\t\t\t}\n\t\t}\n\t} finally {\n\t\twatcher.close()\n\t}\n}\n"],"mappings":";AAAA,SAAS,WAAW;AACpB,SAAS,cAAc;AAEvB,IAAM,EAAE,MAAM,KAAK,MAAM,IAAI,OAAO,MAAM,OAAO,IAAI;AAoBrD,eAAsB,sBAAsB,MAAc,UAAyC;AAClG,MAAI,CAAC,KAAK,WAAW,KAAK,EAAG,QAAO;AACpC,MAAI,CAAC,UAAU,OAAQ,QAAO;AAE9B,aAAW,cAAc,UAAU;AAClC,UAAM,UAAU,WAAW,QAAQ,QAAQ,EAAE;AAC7C,UAAM,MAAM,GAAG,OAAO,SAAS,IAAI;AACnC,QAAI;AACH,YAAM,gCAAgC,GAAG,EAAE;AAC3C,YAAM,WAAW,MAAM,MAAM,KAAK,EAAE,QAAQ,OAAO,CAAC;AACpD,UAAI,CAAC,SAAS,IAAI;AACjB,cAAM,2BAA2B,OAAO,aAAa,SAAS,MAAM,EAAE;AACtE;AAAA,MACD;AACA,YAAM,QAAQ,SAAS,QAAQ,IAAI,cAAc,KAAK,SAAS,QAAQ,IAAI,cAAc;AACzF,UAAI,OAAO;AACV,cAAM,QAAQ,MAAM,MAAM,QAAQ,EAAE,CAAC,GAAG,KAAK;AAC7C,YAAI,OAAO;AACV,gBAAM,MAAM,IAAI,MAAM,KAAK;AAC3B,gBAAM,wCAAwC,OAAO,kBAAkB,IAAI,SAAS,CAAC;AACrF,iBAAO;AAAA,QACR;AAAA,MACD;AAEA,YAAM,OAAO,SAAS,QAAQ,IAAI,MAAM;AACxC,UAAI,MAAM;AACT,cAAM,IAAI,KAAK,MAAM,iBAAiB;AACtC,YAAI,GAAG;AACN,gBAAM,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC;AAC1B,gBAAM,wCAAwC,OAAO,UAAU,IAAI,SAAS,CAAC;AAC7E,iBAAO;AAAA,QACR;AAAA,MACD;AACA,WAAK,2BAA2B,OAAO,wCAAwC;AAAA,IAChF,SAAS,KAAK;AACb,WAAK,2BAA2B,OAAO,YAAY,GAAG;AAAA,IACvD;AAAA,EACD;AACA,SAAO;AACR;;;AC9DA,SAAS,kBAAkB,mBAAmB,2BAA2B;AACzE,SAAS,yBAAyB;AAClC,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAWnB,SAAS,uBAAuB,cAAkC;AACxE,QAAM,UAAU,kBAAkB,YAAY;AAC9C,SAAO,QAAQ,UAAU,MAAM,EAAE,SAAS,MAAM;AACjD;AAMA,eAAsB,uBACrB,YACA,KACA,UACA,aAAa,MAAM,KAAK,KAAK,KAAK,KACN;AAC5B,QAAM,UAAU,kBAAkB,UAAU;AAC5C,QAAM,QAAQ,SAAS,IAAI,KAAK,CAAC;AACjC,QAAM,SAAS,MAAM,iBAAiB,SAAS,OAAO,UAAU,UAAU;AAC1E,QAAM,cAAc,kBAAkB,MAAM;AAC5C,QAAM,WAAW,QAAQ,UAAU,MAAM,EAAE,SAAS,MAAM;AAC1D,SAAO,EAAE,aAAa,UAAU,OAAO,SAAS;AACjD;AA8BA,eAAsB,oBACrB,gBACA,UACyB;AACzB,QAAM,MAAM,GAAG,cAAc,SAAS,QAAQ;AAC9C,MAAI;AACJ,MAAI;AACH,eAAW,MAAM,MAAM,GAAG;AAAA,EAC3B,SAAS,KAAK;AACb,UAAM,IAAI,MAAM,gCAAgC,QAAQ,KAAK,GAAG,EAAE;AAAA,EACnE;AAEA,MAAI,SAAS,WAAW,IAAK,QAAO;AACpC,MAAI,CAAC,SAAS,IAAI;AACjB,UAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,mBAAmB,QAAQ,KAAK,SAAS,UAAU,EAAE;AAAA,EAC7F;AAEA,QAAM,EAAE,QAAQ,MAAM,IAAI,MAAM,SAAS,KAAK;AAC9C,MAAI,CAAC,UAAU,CAAC,MAAO,QAAO;AAG9B,MAAI,QAAQ;AACX,UAAM,QAAQ,UAAU,WAAW,MAAM;AACzC,UAAM,QAAQ,oBAAoB,KAAK;AACvC,WAAO,MAAM;AAAA,EACd;AAIA,SAAO;AACR;AAGA,IAAM,kBAAkB;AAgCxB,eAAsB,kBACrB,YACA,KACA,SACA,SAC4B;AAC5B,QAAM,WAAW,uBAAuB,UAAU;AAClD,QAAM,WAAW,SAAS,oBAAoB;AAE9C,QAAM,iBAAiB,QAAQ,OAAO,OAAK,OAAO,EAAE,YAAY,UAAU;AAC1E,MAAI,eAAe,WAAW,GAAG;AAChC,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC3E;AAEA,MAAI;AACJ,MAAI;AAEJ,WAAS,UAAU,KAAK,WAAW;AAElC,QAAI,aAAa,QAAW;AAC3B,iBAAW,MAAM,iBAAiB,UAAU,OAAO;AAAA,IACpD;AACA,QAAI,cAAc,QAAW;AAE5B,UAAI,YAAY,SAAU,YAAW;AACrC,kBAAY;AAAA,IACb;AAEA,UAAM,SAAS,MAAM,uBAAuB,YAAY,KAAK,QAAQ;AAErE,UAAM,UAAU,MAAM,QAAQ;AAAA,MAC7B,eAAe,IAAI,OAAK,EAAE,QAAS,UAAU,OAAO,WAAW,CAAC;AAAA,IACjE;AACA,UAAM,WAAW,QACf,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,MAAM,eAAe,CAAC,EAAE,KAAK,EAAE,EACnD,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,UAAU;AAG3C,QAAI,SAAS,WAAW,GAAG;AAC1B,aAAO;AAAA,IACR;AAGA,UAAM,kBAAkB,SAAS;AAAA,MAAO,CAAC,EAAE,EAAE,MAC5C,gBAAgB,KAAK,OAAO,EAAE,WAAW,WAAW,EAAE,SAAS,OAAO,EAAE,MAAM,CAAC;AAAA,IAChF;AAEA,QAAI,gBAAgB,SAAS,KAAK,UAAU,UAAU;AAErD,UAAI,OAAO;AACX,iBAAW,EAAE,EAAE,KAAK,iBAAiB;AACpC,cAAM,MAAM,OAAO,EAAE,WAAW,WAAW,EAAE,SAAS,OAAO,EAAE,MAAM;AACrE,cAAM,IAAI,IAAI,MAAM,eAAe;AACnC,YAAI,GAAG;AACN,gBAAM,WAAW,OAAO,EAAE,CAAC,CAAC;AAC5B,cAAI,YAAY,KAAM,QAAO,WAAW;AAAA,QACzC;AAAA,MACD;AACA,UAAI,OAAO,UAAU;AACpB,gBAAQ;AAAA,UACP,qDAAqD,OAAO,EAAE,eAAe,QAAQ,gBACvE,IAAI,aAAa,UAAU,CAAC,IAAI,QAAQ;AAAA,QACvD;AACA,mBAAW;AACX;AAAA,MACD;AAAA,IACD;AAGA,QAAI,SAAS,SAAS,eAAe,QAAQ;AAC5C,iBAAW,EAAE,GAAG,KAAK,KAAK,UAAU;AACnC,gBAAQ,KAAK,+BAA+B,IAAI,aAAa,EAAE,MAAM;AAAA,MACtE;AACA,aAAO;AAAA,IACR;AAGA,QAAI,gBAAgB,SAAS,GAAG;AAC/B,YAAM,IAAI;AAAA,QACT,6CAA6C,KAAK,IAAI,UAAU,GAAG,QAAQ,CAAC,uCAC7C,SAAS,IAAI,CAAC,EAAE,GAAG,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,MAChG;AAAA,IACD;AACA,UAAM,IAAI;AAAA,MACT,oCAAoC,SAAS,IAAI,CAAC,EAAE,GAAG,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,IACrG;AAAA,EACD;AACD;AAMA,eAAe,iBACd,UACA,SACkB;AAClB,QAAM,UAAU,QAAQ,OAAO,OAAK,OAAO,EAAE,oBAAoB,UAAU;AAC3E,MAAI,QAAQ,WAAW,GAAG;AACzB,WAAO;AAAA,EACR;AAEA,aAAW,UAAU,SAAS;AAC7B,QAAI;AACH,YAAM,UAAU,MAAM,OAAO,gBAAiB,QAAQ;AACtD,aAAO,WAAW,OAAO,KAAK,UAAU;AAAA,IACzC,SAAS,KAAK;AACb,cAAQ,KAAK,+BAA+B,OAAO,IAAI,8BAA8B,GAAG;AAAA,IACzF;AAAA,EACD;AAEA,UAAQ,KAAK,4DAA4D,QAAQ,wBAAmB;AACpG,SAAO;AACR;;;AClPA,SAAS,UAAAA,eAAc;AACvB,SAAS,aAAAC,kBAAiB;AAG1B,YAAY,YAAY;AAExB,IAAM,EAAE,MAAAC,OAAM,KAAAC,MAAK,OAAAC,QAAO,MAAM,IAAIC,QAAO,MAAMA,QAAO,IAAI;AAU5D,eAAe,eAAe,MAA4D;AACzF,QAAM,MAAM,kCAAkC,KAAK,SAAS,CAAC;AAE7D,MAAI;AACJ,MAAI;AACH,eAAW,MAAM,MAAM,KAAK,EAAE,QAAQ,YAAY,QAAQ,GAAM,EAAE,CAAC;AAAA,EACpE,SAAS,KAAK;AAEb,UAAM,MAAM,0CAA0C,GAAG;AAAA,EAC1D;AAGA,MAAI,SAAS,WAAW,KAAK;AAC5B,IAAAD,OAAM,qDAAqD,KAAK,SAAS,CAAC;AAC1E,WAAO;AAAA,EACR;AAGA,MAAI,CAAC,SAAS,IAAI;AACjB,UAAM,MAAM,iBAAiB,SAAS,MAAM,oBAAoB,SAAS,UAAU;AAAA,EACpF;AAIA,QAAM,WAAW,MAAa,eAAQ,IAAI;AAC1C,SAAO;AACR;AAMA,eAAsB,YAAY,gBAA4B,KAAoC;AACjG,QAAM,aAAa;AACnB,QAAM,UAAU,IAAI;AAAA,IAAe,CAAC,GAAG,WACtC,WAAW,MAAM,OAAO,IAAI,MAAM,+BAA+B,UAAU,IAAI,CAAC,GAAG,UAAU;AAAA,EAC9F;AACA,SAAO,QAAQ,KAAK,CAAC,iBAAiB,gBAAgB,GAAG,GAAG,OAAO,CAAC;AACrE;AAEA,eAAe,iBAAiB,gBAA4B,KAAoC;AAC/F,QAAM,QAAQ,SAAS,GAAG;AAC1B,QAAM,OAAO,MAAa,YAAK,cAAc;AAE7C,MAAI;AACJ,QAAM,WAAW,MAAM,eAAe,IAAI;AAE1C,MAAI,UAAU;AAEb,eAAW,MAAa,iBAAU,UAAU,KAAK;AACjD,IAAAA,OAAM,sCAAsC,KAAK,SAAS,CAAC;AAAA,EAC5D,OAAO;AAEN,eAAW,MAAa,UAAG,MAAM,KAAK;AACtC,IAAAA,OAAM,0CAA0C,KAAK,SAAS,CAAC;AAAA,EAChE;AAEA,QAAa,eAAQ,UAAU,KAAK,GAAG;AACvC,EAAAA,OAAM,sBAAsB,IAAI,SAAS,GAAG,MAAM,KAAK,SAAS,CAAC;AAEjE,SAAO;AACR;AAeA,eAAsB,oBACrB,SACA,UACyB;AACzB,QAAM,MAAM,GAAG,QAAQ,QAAQ,QAAQ,EAAE,CAAC,IAAI,QAAQ;AACtD,MAAI;AACJ,MAAI;AACH,eAAW,MAAM,MAAM,GAAG;AAAA,EAC3B,SAAS,KAAK;AACb,UAAM,IAAI,MAAM,yCAAyC,OAAO,KAAK,GAAG,EAAE;AAAA,EAC3E;AAEA,MAAI,SAAS,WAAW,IAAK,QAAO;AACpC,MAAI,CAAC,SAAS,IAAI;AACjB,UAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,4BAA4B,OAAO,KAAK,SAAS,UAAU,EAAE;AAAA,EACrG;AAEA,QAAM,OAAgC,MAAM,SAAS,KAAK;AAG1D,MAAI,OAAO,KAAK,QAAQ,UAAU;AACjC,WAAO,OAAO,KAAK,GAAG;AAAA,EACvB;AAGA,MAAI,OAAO,KAAK,WAAW,UAAU;AACpC,QAAI;AACH,YAAM,QAAQE,WAAU,WAAW,KAAK,MAAM;AAC9C,YAAM,QAAQ,oBAAoB,KAAK;AACvC,aAAO,MAAM;AAAA,IACd,QAAQ;AACP,MAAAJ,MAAK,wDAAwD,QAAQ;AACrE,aAAO;AAAA,IACR;AAAA,EACD;AAGA,SAAO;AACR;AAeO,SAAS,WAAW,UAAU,sBAAyC;AAC7E,QAAM,YAAY,QAAQ,QAAQ,QAAQ,EAAE;AAC5C,SAAO;AAAA,IACN,MAAM;AAAA,IACN,MAAM,QAAQ,UAAkB,aAAyB;AACxD,YAAM,MAAM,GAAG,SAAS,IAAI,QAAQ;AACpC,MAAAE,OAAM,qBAAqB,GAAG,EAAE;AAChC,YAAM,MAAM,MAAM,MAAM,KAAK;AAAA,QAC5B,QAAQ;AAAA,QACR,MAAME,WAAU,WAAW,WAAW;AAAA,MACvC,CAAC;AACD,UAAI,CAAC,IAAI,IAAI;AACZ,YAAI,SAAS;AACb,YAAI;AACH,gBAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,mBAAS,KAAK,UAAU,WAAM,KAAK,OAAO,KAAK;AAAA,QAChD,QAAQ;AACP,mBAAS,IAAI,aAAa,WAAM,IAAI,UAAU,KAAK;AAAA,QACpD;AACA,cAAM,IAAI,MAAM,cAAc,IAAI,MAAM,GAAG,MAAM,EAAE;AAAA,MACpD;AAAA,IACD;AAAA,IACA,MAAM,gBAAgB,UAA0C;AAC/D,aAAO,oBAAoB,WAAW,QAAQ;AAAA,IAC/C;AAAA,EACD;AACD;AAeO,SAAS,aAAa,aAAa,6BAAgD;AACzF,SAAO;AAAA,IACN,MAAM;AAAA;AAAA,IAEN,MAAM,gBAAgB,UAA0C;AAC/D,aAAO,oBAAoB,YAAY,QAAQ;AAAA,IAChD;AAAA,EACD;AACD;AAIA,eAAsB,kBAAkB;AACvC,SAAc,cAAO;AACtB;AAEA,eAAsB,gBAAgB,IAAgB;AACrD,QAAM,OAAO,MAAa,YAAK,EAAE;AACjC,SAAO,KAAK,SAAS;AACtB;;;AC9MA,SAAS,UAAAC,eAAc;AACvB,SAAS,OAAAC,YAAW;AACpB,OAAO,2BAAmE;AAI1E,IAAM,EAAE,MAAAC,OAAM,KAAAC,MAAK,OAAAC,QAAO,OAAAC,OAAM,IAAIL,QAAO,MAAMA,QAAO,IAAI;AAY5D,SAAS,WAAW,aAAqB,MAAc;AACtD,QAAM,OAAO,YAAY,QAAQ,QAAQ,EAAE,EAAE,QAAQ,SAAS,IAAI;AAClE,SAAO,GAAG,IAAI,IAAI,IAAI;AACvB;AACA,SAAS,aAAa,aAAqB,MAAc;AACxD,QAAM,OAAO,YAAY,QAAQ,QAAQ,EAAE;AAC3C,SAAO,GAAG,IAAI,IAAI,IAAI;AACvB;AAEA,SAAS,mBAAmB,aAAiC,IAAoB;AAChF,MAAI,CAAC,aAAa;AACjB,UAAM,IAAI;AAAA,MACT,IAAI,EAAE;AAAA,IAIP;AAAA,EACD;AACA,SAAO;AACR;AA6CA,SAAS,sBAAsB,OAA2B;AACzD,MAAI;AAEH,UAAM,SAAS,MAAM,WAAW,QAAQ,IAAI,MAAM,MAAM,CAAC,IAAI;AAC7D,WAAOC,KAAI,MAAM,MAAM;AAAA,EACxB,QAAQ;AACP,IAAAG,OAAM,4CAA4C,KAAK;AACvD,WAAO;AAAA,EACR;AACD;AAsCO,SAAS,aAAa,aAAqB,MAAc,SAAgD;AAC/G,QAAM,eAAe,mBAAmB,aAAa,cAAc;AACnE,QAAM,MAAM,WAAW,cAAc,IAAI;AACzC,EAAAA,OAAM,gCAAgC,GAAG;AAEzC,QAAM,KAAK,IAAI,UAAU,GAAG;AAE5B,KAAG,SAAS,MAAM;AACjB,IAAAD,KAAI,+BAA+B,IAAI;AACvC,YAAQ,SAAS;AAAA,EAClB;AAEA,KAAG,YAAY,CAAC,UAAU;AACzB,QAAI;AACH,YAAM,SAAuB,KAAK,MAAM,MAAM,IAAI;AAClD,MAAAC,OAAM,sCAAsC,MAAM,MAAM;AACxD,cAAQ,SAAS,MAAM;AAAA,IACxB,SAAS,KAAK;AACb,MAAAF,MAAK,2CAA2C,MAAM,MAAM,GAAG;AAC/D,cAAQ,UAAU,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AAAA,IACtE;AAAA,EACD;AAEA,KAAG,UAAU,CAAC,UAAU;AACvB,UAAM,WAAW,iBAAiB,aAAa,MAAM,UAAU;AAC/D,IAAAA,MAAK,4BAA4B,MAAM,KAAK,QAAQ;AACpD,YAAQ,UAAU,IAAI,MAAM,QAAQ,CAAC;AAAA,EACtC;AAEA,KAAG,UAAU,CAAC,UAAU;AACvB,IAAAE,OAAM,6BAA6B,MAAM,SAAS,MAAM,IAAI;AAC5D,YAAQ,UAAU,KAAK;AAAA,EACxB;AAEA,SAAO;AAAA,IACN,OAAO,MAAM;AACZ,MAAAA,OAAM,yCAAyC,IAAI;AACnD,SAAG,MAAM;AAAA,IACV;AAAA,IACA;AAAA,EACD;AACD;AAwDA,IAAM,4BAA4B;AAE3B,IAAM,cAAN,MAAkB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAgC;AAAA,EAChC;AAAA,EACA,iBAAiB;AAAA,EACjB,gBAAuD;AAAA,EACvD,cAA2B;AAAA,EAC3B,gBAA6B;AAAA,EAErC,YAAY,aAAqB,MAAc,SAA6B;AAC3E,SAAK,cAAc,mBAAmB,aAAa,aAAa;AAChE,SAAK,OAAO;AACZ,SAAK,UAAU;AAEf,UAAM,MAAM,WAAW,KAAK,aAAa,IAAI;AAC7C,IAAAA,OAAM,8BAA8B,IAAI;AAExC,SAAK,KAAK,IAAI,sBAAsB,KAAK,CAAC,GAAG;AAAA,MAC5C,sBAAsB;AAAA;AAAA,MACtB,sBAAsB;AAAA,MACtB,6BAA6B;AAAA,MAC7B,YAAY;AAAA,MACZ,GAAG,QAAQ;AAAA,IACZ,CAAC;AAED,SAAK,GAAG,SAAS,MAAM;AACtB,MAAAD,KAAI,8BAA8B,IAAI;AACtC,WAAK,cAAc,oBAAI,KAAK;AAC5B,cAAQ,cAAc;AAGtB,UAAI,KAAK,mBAAmB,QAAQ,qBAAqB,QAAQ;AAChE,aAAK,sBAAsB;AAAA,MAC5B,WAES,CAAC,KAAK,mBAAmB,QAAQ,sBAAsB,OAAO;AACtE,aAAK,sBAAsB;AAAA,MAC5B;AAEA,WAAK,iBAAiB;AAGtB,UAAI,QAAQ,kBAAkB,OAAO;AACpC,aAAK,mBAAmB;AAAA,MACzB;AAAA,IACD;AAEA,SAAK,GAAG,YAAY,CAAC,UAAU;AAC9B,WAAK,gBAAgB,oBAAI,KAAK;AAC9B,UAAI;AACH,cAAM,SAAuB,KAAK,MAAM,MAAM,IAAc;AAC5D,QAAAC,OAAM,qCAAqC,MAAM,MAAM;AAEvD,cAAM,YAAY,KAAK;AACvB,cAAM,QAAQ,OAAO,UAAU;AAC/B,cAAM,MAAM,sBAAsB,OAAO,KAAK;AAG9C,YAAI,CAAC,SAAS,CAAC,QAAQ,kBAAkB;AACxC,UAAAA,OAAM,8CAA8C,IAAI;AACxD;AAAA,QACD;AAGA,aAAK,iBAAiB,OAAO;AAE7B,cAAM,SAAqB;AAAA,UAC1B,OAAO,OAAO;AAAA,UACd;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAEA,aAAK,QAAQ,SAAS,MAAM;AAAA,MAC7B,SAAS,KAAK;AACb,QAAAF,MAAK,0CAA0C,MAAM,MAAM,GAAG;AAC9D,gBAAQ,UAAU,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AAAA,MACtE;AAAA,IACD;AAEA,SAAK,GAAG,UAAU,CAAC,UAAU;AAE5B,YAAM,WAAW,iBAAiB,aAAa,MAAM,UAAU;AAI/D,UAAI,aAAa,kBAAkB;AAClC,QAAAC,KAAI,2BAA2B,MAAM,KAAK,UAAU,0BAA0B;AAAA,MAC/E,OAAO;AACN,QAAAD,MAAK,2BAA2B,MAAM,KAAK,QAAQ;AAAA,MACpD;AAGA,UAAI,aAAa,kBAAkB;AAClC,gBAAQ,UAAU,IAAI,MAAM,QAAQ,CAAC;AAAA,MACtC;AAAA,IACD;AAEA,SAAK,GAAG,UAAU,MAAM;AACvB,MAAAE,OAAM,mCAAmC,IAAI;AAC7C,WAAK,kBAAkB;AACvB,WAAK,cAAc;AACnB,WAAK,gBAAgB;AACrB,cAAQ,iBAAiB;AAAA,IAC1B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,wBAAuC;AACpD,QAAI;AACH,MAAAA,OAAM,iDAAiD,KAAK,IAAI;AAChE,YAAM,WAAW,MAAM,MAAM,aAAa,KAAK,aAAa,KAAK,IAAI,CAAC;AAEtE,UAAI,CAAC,SAAS,IAAI;AACjB,YAAI,SAAS,WAAW,KAAK;AAC5B,UAAAA,OAAM,yCAAyC,KAAK,IAAI;AACxD;AAAA,QACD;AACA,cAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAAA,MAClE;AAEA,YAAM,SAAuB,MAAM,SAAS,KAAK;AACjD,YAAM,YAAY,KAAK;AACvB,YAAM,QAAQ,OAAO,UAAU;AAC/B,YAAM,MAAM,sBAAsB,OAAO,KAAK;AAG9C,UAAI,CAAC,SAAS,CAAC,KAAK,QAAQ,kBAAkB;AAC7C,QAAAA,OAAM,oCAAoC,KAAK,IAAI;AACnD;AAAA,MACD;AAEA,YAAM,SAAS,cAAc,OAC1B,4CACA;AACH,MAAAD,KAAI,QAAQ,KAAK,MAAM;AAAA,QACtB,UAAU;AAAA,QACV,SAAS,OAAO;AAAA,MACjB,CAAC;AAGD,WAAK,iBAAiB,OAAO;AAE7B,YAAM,SAAqB;AAAA,QAC1B,OAAO,OAAO;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAEA,WAAK,KAAK,QAAQ,SAAS,MAAM;AAAA,IAClC,SAAS,KAAK;AACb,MAAAD,MAAK,qDAAqD,KAAK,MAAM,GAAG;AACxE,WAAK,QAAQ,UAAU,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AAAA,IAC3E;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAA2B;AAClC,SAAK,kBAAkB;AACvB,UAAM,WAAW,KAAK,QAAQ,yBAAyB;AACvD,IAAAE,OAAM,6CAA6C,KAAK,MAAM,aAAa,QAAQ;AAEnF,SAAK,gBAAgB,YAAY,MAAM;AACtC,WAAK,KAAK,qBAAqB;AAAA,IAChC,GAAG,QAAQ;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAA0B;AACjC,QAAI,KAAK,kBAAkB,MAAM;AAChC,MAAAA,OAAM,6CAA6C,KAAK,IAAI;AAC5D,oBAAc,KAAK,aAAa;AAChC,WAAK,gBAAgB;AAAA,IACtB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,uBAAsC;AACnD,QAAI;AACH,MAAAA,OAAM,+CAA+C,KAAK,IAAI;AAC9D,YAAM,WAAW,MAAM,MAAM,aAAa,KAAK,aAAa,KAAK,IAAI,CAAC;AAEtE,UAAI,CAAC,SAAS,IAAI;AACjB,YAAI,SAAS,WAAW,KAAK;AAE5B,cAAI,KAAK,mBAAmB,MAAM;AACjC,YAAAA,OAAM,mDAAmD,KAAK,IAAI;AAClE;AAAA,UACD;AAEA,UAAAF,MAAK,2EAA2E,KAAK,IAAI;AACzF;AAAA,QACD;AACA,cAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AAAA,MAClE;AAEA,YAAM,SAAuB,MAAM,SAAS,KAAK;AAGjD,UAAI,OAAO,UAAU,KAAK,gBAAgB;AACzC,QAAAE,OAAM,uCAAuC,KAAK,IAAI;AACtD;AAAA,MACD;AAGA,YAAM,MAAM,oBAAI,KAAK;AACrB,YAAM,kBAAkB,KAAK,gBAC1B,IAAI,QAAQ,IAAI,KAAK,cAAc,QAAQ,IAC3C,KAAK,cACJ,IAAI,QAAQ,IAAI,KAAK,YAAY,QAAQ,IACzC;AAEJ,YAAM,YAAiC;AAAA,QACtC,aAAa,KAAK,eAAe;AAAA,QACjC,eAAe,KAAK;AAAA,QACpB;AAAA,QACA,YAAY,KAAK;AAAA,QACjB,cAAc,OAAO;AAAA,MACtB;AAEA,MAAAF,MAAK,+CAA+C,KAAK,MAAM;AAAA,QAC9D,aAAa,UAAU,YAAY,YAAY;AAAA,QAC/C,eAAe,UAAU,eAAe,YAAY,KAAK;AAAA,QACzD,iBAAiB,GAAG,KAAK,MAAM,kBAAkB,GAAI,CAAC;AAAA,QACtD,YAAY,UAAU;AAAA,QACtB,cAAc,UAAU;AAAA,MACzB,CAAC;AAGD,WAAK,QAAQ,oBAAoB,SAAS;AAG1C,YAAM,YAAY,KAAK;AACvB,YAAM,MAAM,sBAAsB,OAAO,KAAK;AAC9C,WAAK,iBAAiB,OAAO;AAE7B,YAAM,SAAqB;AAAA,QAC1B,OAAO,OAAO;AAAA,QACd;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP;AAAA,MACD;AACA,WAAK,KAAK,QAAQ,SAAS,MAAM;AAGjC,MAAAC,KAAI,+DAA+D,KAAK,IAAI;AAC5E,WAAK,GAAG,UAAU;AAAA,IACnB,SAAS,KAAK;AAEb,MAAAD,MAAK,2CAA2C,KAAK,MAAM,GAAG;AAAA,IAC/D;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAc;AACb,IAAAC,KAAI,sCAAsC,KAAK,IAAI;AACnD,SAAK,GAAG,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAa;AACZ,SAAK,MAAM;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACb,IAAAA,KAAI,qCAAqC,KAAK,IAAI;AAClD,SAAK,kBAAkB;AACvB,SAAK,GAAG,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAA2B;AAC9B,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,aAAqB;AACxB,WAAO,KAAK,GAAG;AAAA,EAChB;AACD;AAWO,SAAS,UAAU,aAAqB,MAAc,SAA0C;AACtG,SAAO,IAAI,YAAY,aAAa,MAAM,OAAO;AAClD;AAkBA,gBAAuB,kBACtB,aACA,MACA,QAC4C;AAC5C,QAAM,QAAsB,CAAC;AAC7B,MAAIG,WAA+B;AACnC,MAAI,QAAsB;AAE1B,QAAM,UAAU,IAAI,YAAY,aAAa,MAAM;AAAA,IAClD,UAAU,CAAC,WAAW;AACrB,YAAM,KAAK,MAAM;AACjB,MAAAA,WAAU;AAAA,IACX;AAAA,IACA,SAAS,CAAC,QAAQ;AACjB,cAAQ,eAAe,QAAQ,MAAM,IAAI,MAAM,iBAAiB;AAChE,MAAAA,WAAU;AAAA,IACX;AAAA,EACD,CAAC;AAED,UAAQ,iBAAiB,SAAS,MAAM;AACvC,YAAQ,MAAM;AAAA,EACf,CAAC;AAED,MAAI;AACH,WAAO,CAAC,QAAQ,SAAS;AACxB,UAAI,MAAM,SAAS,GAAG;AACrB,cAAM,MAAM,MAAM;AAAA,MACnB,WAAW,OAAO;AAEjB,QAAAJ,MAAK,mDAAmD,KAAK;AAC7D,gBAAQ;AAAA,MACT,OAAO;AACN,cAAM,IAAI,QAAc,CAAC,MAAM;AAC9B,UAAAI,WAAU;AAAA,QACX,CAAC;AACD,QAAAA,WAAU;AAAA,MACX;AAAA,IACD;AAAA,EACD,UAAE;AACD,YAAQ,MAAM;AAAA,EACf;AACD;","names":["Logger","base64pad","WARN","LOG","DEBUG","Logger","base64pad","Logger","CID","WARN","LOG","DEBUG","ERROR","resolve"]}
|
|
@@ -31,8 +31,8 @@ export declare function chunkApplogs(applogCids: CID<unknown, 297, 18, 1>[], siz
|
|
|
31
31
|
blocks: any[];
|
|
32
32
|
chunks: any[];
|
|
33
33
|
}>;
|
|
34
|
-
export declare function unchunkApplogsBlock(block: SnapBlockLogsOrChunks, blockStore: BlockStoreish): Promise<CID[]>;
|
|
35
|
-
export declare function isSnapBlockChunks(block: SnapBlockLogsOrChunks): block is SnapBlockChunks;
|
|
34
|
+
export declare function unchunkApplogsBlock(block: SnapBlockLogsOrChunks | null | undefined, blockStore: BlockStoreish): Promise<CID[]>;
|
|
35
|
+
export declare function isSnapBlockChunks(block: SnapBlockLogsOrChunks | null | undefined): block is SnapBlockChunks;
|
|
36
36
|
/**
|
|
37
37
|
* @param applogs Encrypted or plain applogs
|
|
38
38
|
* @returns Car file
|
|
@@ -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,0BAA0B,CAAA;AACjC,OAAO,EAAE,aAAa,EAA4C,MAAM,gBAAgB,CAAA;AAIxF,OAAO,EAAE,eAAe,EAAqB,MAAM,EAAE,MAAM,cAAc,CAAA;AAGzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAiB,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAehH,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,EAAE,MAAM,GAAG,IAAI;;;;;;GA+H1B;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,EAAE,MAAM,GAAG,IAAI;;;;;;GAiC1B;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,
|
|
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,0BAA0B,CAAA;AACjC,OAAO,EAAE,aAAa,EAA4C,MAAM,gBAAgB,CAAA;AAIxF,OAAO,EAAE,eAAe,EAAqB,MAAM,EAAE,MAAM,cAAc,CAAA;AAGzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAiB,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAehH,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,EAAE,MAAM,GAAG,IAAI;;;;;;GA+H1B;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,EAAE,MAAM,GAAG,IAAI;;;;;;GAiC1B;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,GAAG,IAAI,GAAG,SAAS,EAAE,UAAU,EAAE,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAapI;AACD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,IAAI,eAAe,CAE3G;AACD;;;GAGG;AACH,wBAAsB,0BAA0B,CAC/C,OAAO,EAAE,2BAA2B,iBAUpC"}
|
package/dist/pubsub.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
integratePub,
|
|
4
4
|
isShare,
|
|
5
5
|
isSubscription
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-H4YVJKB7.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-
|
|
14
|
+
} from "./chunk-H3JNNTVP.js";
|
|
15
15
|
import "./chunk-YDAKBU6Q.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-N7SEGHU4.js";
|
|
17
|
+
import "./chunk-4MKPGQIM.js";
|
|
18
18
|
import "./chunk-ZAADLBSB.js";
|
|
19
19
|
export {
|
|
20
20
|
agentToShortHash,
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import type { Applog, Attribute, Timestamp } from '../applog/datom-types.ts';
|
|
2
|
+
import type { Thread } from '../thread/basic.ts';
|
|
3
|
+
import type { WriteableThread } from '../thread/writeable.ts';
|
|
4
|
+
/**
|
|
5
|
+
* An EpochSnapshot maps every {@link Attribute} present in a time window to the
|
|
6
|
+
* array of {@link Applog}s (from any entity) that carry that attribute.
|
|
7
|
+
*
|
|
8
|
+
* This is **not** a flat array — logs are grouped by attribute first so that
|
|
9
|
+
* consumers can answer questions like "which entities had their `movie/title`
|
|
10
|
+
* updated in this window?" without re-filtering.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const snap = createEpochSnapshot(thread, {
|
|
15
|
+
* start: '2024-01-01T00:00:00.000Z',
|
|
16
|
+
* end: '2024-06-01T00:00:00.000Z',
|
|
17
|
+
* })
|
|
18
|
+
* for (const [attr, logs] of snap) {
|
|
19
|
+
* console.log(`${attr}: ${logs.length} logs`)
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export type EpochSnapshot = ReadonlyMap<Attribute, readonly Applog[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Options for {@link createEpochSnapshot}.
|
|
26
|
+
*/
|
|
27
|
+
export interface EpochSnapshotOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Start of the time window (inclusive). ISO 8601 string matching the
|
|
30
|
+
* {@link Timestamp} format used on every {@link Applog}.
|
|
31
|
+
*/
|
|
32
|
+
readonly start: Timestamp;
|
|
33
|
+
/**
|
|
34
|
+
* End of the time window (exclusive). ISO 8601 string.
|
|
35
|
+
* Logs whose `ts` is **equal to** `end` are excluded.
|
|
36
|
+
*/
|
|
37
|
+
readonly end: Timestamp;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Creates an {@link EpochSnapshot} — a point-in-time grouping of all app logs
|
|
41
|
+
* within `[start, end)` grouped by their attribute name.
|
|
42
|
+
*
|
|
43
|
+
* The function is a **one-off (snapshot) computation**: it reads the current
|
|
44
|
+
* state of the thread and returns a frozen map. If you need reactivity, wrap
|
|
45
|
+
* the result in a reactive derivation or subscribe to thread changes and
|
|
46
|
+
* re-compute.
|
|
47
|
+
*
|
|
48
|
+
* @param thread - The thread to snapshot.
|
|
49
|
+
* @param options - Time range bounds.
|
|
50
|
+
* @returns A `ReadonlyMap` keyed by attribute name. Each value is the
|
|
51
|
+
* (chronologically sorted) array of applogs whose `at` matches that
|
|
52
|
+
* key and whose `ts` falls inside `[start, end)`.
|
|
53
|
+
*
|
|
54
|
+
* @throws {Error} If `start` is lexically `>=` `end` (empty range).
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const snap = createEpochSnapshot(thread, {
|
|
59
|
+
* start: '2024-01-01T00:00:00.000Z',
|
|
60
|
+
* end: '2025-01-01T00:00:00.000Z',
|
|
61
|
+
* })
|
|
62
|
+
* // Iterate attribute groups:
|
|
63
|
+
* for (const [attr, logs] of snap) {
|
|
64
|
+
* console.log(attr, logs.length)
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function createEpochSnapshot(thread: Thread, options: EpochSnapshotOptions): EpochSnapshot;
|
|
69
|
+
/**
|
|
70
|
+
* A flexible time specification used by {@link purgeHistory}.
|
|
71
|
+
*
|
|
72
|
+
* - `-1` (number) — the earliest log's timestamp in the thread ("beginning")
|
|
73
|
+
* - `0` (number) — current time ("now")
|
|
74
|
+
* - Positive number — treated as a Unix millisecond timestamp
|
|
75
|
+
* - `'-1d'`, `'-2h'`, `'-30m'`, `'-5s'` — relative offset **before** now
|
|
76
|
+
* - `'+1d'`, `'2h'` — relative offset **after** now (no sign = forward)
|
|
77
|
+
* - ISO 8601 string — absolute timestamp, used as-is
|
|
78
|
+
* - `'now'` — current time
|
|
79
|
+
*/
|
|
80
|
+
export type TimeSpec = number | string;
|
|
81
|
+
/**
|
|
82
|
+
* Resolve a {@link TimeSpec} to an absolute ISO {@link Timestamp}.
|
|
83
|
+
*
|
|
84
|
+
* @param spec - The time specification to resolve.
|
|
85
|
+
* @param thread - The thread (used to find earliest log when spec is `-1`).
|
|
86
|
+
* @param now - The reference "now" for relative specs.
|
|
87
|
+
* @returns An ISO 8601 timestamp string.
|
|
88
|
+
*/
|
|
89
|
+
export declare function resolveTimeSpec(spec: TimeSpec, thread: Thread, now: Date): Timestamp;
|
|
90
|
+
/**
|
|
91
|
+
* A JSON-serializable representation of an {@link EpochSnapshot}, safe for
|
|
92
|
+
* writing to disk, sending over the wire, or storing in IPFS.
|
|
93
|
+
*/
|
|
94
|
+
export interface SerializedEpochSnapshot {
|
|
95
|
+
/** Format marker for versioning */
|
|
96
|
+
readonly format: 'wovin-epoch-snapshot-v1';
|
|
97
|
+
/** The attribute whose history was captured / purged */
|
|
98
|
+
readonly attribute: string;
|
|
99
|
+
/** The time range this snapshot covers */
|
|
100
|
+
readonly timeRange: {
|
|
101
|
+
readonly start: Timestamp;
|
|
102
|
+
readonly end: Timestamp;
|
|
103
|
+
};
|
|
104
|
+
/** When this snapshot was created */
|
|
105
|
+
readonly createdAt: Timestamp;
|
|
106
|
+
/** Total number of applogs across all groups */
|
|
107
|
+
readonly logCount: number;
|
|
108
|
+
/**
|
|
109
|
+
* The grouped applogs. Each key is an attribute name; the value is the
|
|
110
|
+
* array of applogs that carried that attribute within the time window.
|
|
111
|
+
*/
|
|
112
|
+
readonly groups: Record<string, readonly Applog[]>;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Converts an {@link EpochSnapshot} into a {@link SerializedEpochSnapshot}
|
|
116
|
+
* that can be persisted as JSON.
|
|
117
|
+
*
|
|
118
|
+
* @param snapshot - The live snapshot to serialize.
|
|
119
|
+
* @param metadata - Identifying metadata to attach.
|
|
120
|
+
* @returns A plain, JSON-safe object.
|
|
121
|
+
*/
|
|
122
|
+
export declare function serializeEpochSnapshot(snapshot: EpochSnapshot, metadata: {
|
|
123
|
+
/** The attribute this purge targets */
|
|
124
|
+
readonly attribute: string;
|
|
125
|
+
/** The time range of the snapshot */
|
|
126
|
+
readonly timeRange: {
|
|
127
|
+
readonly start: Timestamp;
|
|
128
|
+
readonly end: Timestamp;
|
|
129
|
+
};
|
|
130
|
+
}): SerializedEpochSnapshot;
|
|
131
|
+
/**
|
|
132
|
+
* Options for {@link purgeHistory}.
|
|
133
|
+
*/
|
|
134
|
+
export interface PurgeHistoryOptions {
|
|
135
|
+
/**
|
|
136
|
+
* Callback invoked with the serialized snapshot **before** any logs are
|
|
137
|
+
* purged. Use this to persist the snapshot to a file, database, IPFS, or
|
|
138
|
+
* any other storage you choose.
|
|
139
|
+
*
|
|
140
|
+
* If omitted, the snapshot is created and returned in the result but not
|
|
141
|
+
* automatically persisted anywhere.
|
|
142
|
+
*/
|
|
143
|
+
persistSnapshot?: (serialized: SerializedEpochSnapshot) => Promise<void> | void;
|
|
144
|
+
/**
|
|
145
|
+
* Override "now" for deterministic tests. Defaults to `new Date()`.
|
|
146
|
+
*/
|
|
147
|
+
now?: Date;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The result of a successful {@link purgeHistory} call.
|
|
151
|
+
*/
|
|
152
|
+
export interface PurgeHistoryResult {
|
|
153
|
+
/**
|
|
154
|
+
* The {@link EpochSnapshot} that was taken **before** the purge.
|
|
155
|
+
* Contains all logs (across all attributes) within the time window, even
|
|
156
|
+
* though only one attribute was purged.
|
|
157
|
+
*/
|
|
158
|
+
readonly snapshot: EpochSnapshot;
|
|
159
|
+
/** Number of applogs that were removed from the thread. */
|
|
160
|
+
readonly purgedCount: number;
|
|
161
|
+
/** Number of applogs kept as LWW winners for the purged attribute. */
|
|
162
|
+
readonly keptCount: number;
|
|
163
|
+
/** The resolved time range that was processed. */
|
|
164
|
+
readonly timeRange: {
|
|
165
|
+
readonly start: Timestamp;
|
|
166
|
+
readonly end: Timestamp;
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* For a given **attribute** and **time range**:
|
|
171
|
+
*
|
|
172
|
+
* 1. Creates an {@link EpochSnapshot} capturing all app logs within
|
|
173
|
+
* `[start, end)` across **all** attributes.
|
|
174
|
+
* 2. Calls `options.persistSnapshot` with a serialized copy of the snapshot
|
|
175
|
+
* (so you can store the pre-purge state before any data is removed).
|
|
176
|
+
* 3. For the target attribute, groups the captured logs by entity and keeps
|
|
177
|
+
* only the **latest** (last-write-wins) applog per `(en, at)` pair.
|
|
178
|
+
* All older logs for that pair are purged from the thread.
|
|
179
|
+
*
|
|
180
|
+
* Logs for **other** attributes are never touched.
|
|
181
|
+
*
|
|
182
|
+
* @param thread - A writable thread to purge from.
|
|
183
|
+
* @param attribute - Only logs carrying this attribute are candidates for
|
|
184
|
+
* removal. Logs with other attributes are left untouched.
|
|
185
|
+
* @param start - Start of the time window (see {@link TimeSpec}).
|
|
186
|
+
* @param end - End of the time window, exclusive (see {@link TimeSpec}).
|
|
187
|
+
* @param options - Optional persistence callback and time override.
|
|
188
|
+
* @returns A {@link PurgeHistoryResult} with the snapshot and counts.
|
|
189
|
+
*
|
|
190
|
+
* @throws {RangeError} If the resolved `start` is not before `end`.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* // Purge all but the latest block/content per entity from the beginning
|
|
195
|
+
* // up to yesterday, saving a snapshot first.
|
|
196
|
+
* const result = await purgeHistory(thread, 'block/content', -1, '-1d', {
|
|
197
|
+
* persistSnapshot: async (snap) => {
|
|
198
|
+
* await writeFile('purge-archive.json', JSON.stringify(snap, null, 2))
|
|
199
|
+
* },
|
|
200
|
+
* })
|
|
201
|
+
* console.log(`Purged ${result.purgedCount}, kept ${result.keptCount}`)
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
204
|
+
export declare function purgeHistory(thread: WriteableThread, attribute: Attribute, start: TimeSpec, end: TimeSpec, options?: PurgeHistoryOptions): Promise<PurgeHistoryResult>;
|
|
205
|
+
//# sourceMappingURL=epoch-snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"epoch-snapshot.d.ts","sourceRoot":"","sources":["../../src/query/epoch-snapshot.ts"],"names":[],"mappings":"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"}
|
package/dist/query.d.ts
CHANGED
package/dist/query.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAA;AACrC,cAAc,kBAAkB,CAAA;AAChC,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA"}
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAA;AACrC,cAAc,kBAAkB,CAAA;AAChC,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA"}
|
package/dist/query.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
+
createEpochSnapshot,
|
|
2
3
|
liveEntityCollection,
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
purgeHistory,
|
|
5
|
+
queryDivergencesByPrev,
|
|
6
|
+
resolveTimeSpec,
|
|
7
|
+
serializeEpochSnapshot
|
|
8
|
+
} from "./chunk-N5QPZNKD.js";
|
|
5
9
|
import {
|
|
6
10
|
LiveQueryResult,
|
|
7
11
|
QueryNode,
|
|
@@ -44,7 +48,7 @@ import {
|
|
|
44
48
|
throwOnTimeout,
|
|
45
49
|
withTimeout,
|
|
46
50
|
withoutDeleted
|
|
47
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-N7SEGHU4.js";
|
|
48
52
|
import {
|
|
49
53
|
SubscribableArrayImpl,
|
|
50
54
|
SubscribableImpl,
|
|
@@ -57,7 +61,7 @@ import {
|
|
|
57
61
|
memoizedFn,
|
|
58
62
|
prettifyThreadName,
|
|
59
63
|
refCountedMemoizedFn
|
|
60
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-4MKPGQIM.js";
|
|
61
65
|
import "./chunk-ZAADLBSB.js";
|
|
62
66
|
export {
|
|
63
67
|
LiveQueryResult,
|
|
@@ -69,6 +73,7 @@ export {
|
|
|
69
73
|
anyOf,
|
|
70
74
|
createDebugName,
|
|
71
75
|
createDebugNameObj,
|
|
76
|
+
createEpochSnapshot,
|
|
72
77
|
createObjMapper,
|
|
73
78
|
entityOverlap,
|
|
74
79
|
entityOverlapCount,
|
|
@@ -98,6 +103,7 @@ export {
|
|
|
98
103
|
prefixAt,
|
|
99
104
|
prefixAttrs,
|
|
100
105
|
prettifyThreadName,
|
|
106
|
+
purgeHistory,
|
|
101
107
|
query,
|
|
102
108
|
queryAndMap,
|
|
103
109
|
queryDivergencesByPrev,
|
|
@@ -108,6 +114,8 @@ export {
|
|
|
108
114
|
queryStepOnce,
|
|
109
115
|
refCountedMemoizedFn,
|
|
110
116
|
resolveKeyMapper,
|
|
117
|
+
resolveTimeSpec,
|
|
118
|
+
serializeEpochSnapshot,
|
|
111
119
|
startsWith,
|
|
112
120
|
stripAtPrefix,
|
|
113
121
|
threadFromMaybeArray,
|
package/dist/retrieve.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
updateThreadFromSnapshot,
|
|
3
3
|
withBlockCache
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-6CSJTSQP.js";
|
|
5
|
+
import "./chunk-H3JNNTVP.js";
|
|
6
6
|
import "./chunk-YDAKBU6Q.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-N7SEGHU4.js";
|
|
8
|
+
import "./chunk-4MKPGQIM.js";
|
|
9
9
|
import "./chunk-ZAADLBSB.js";
|
|
10
10
|
export {
|
|
11
11
|
updateThreadFromSnapshot,
|
package/dist/thread.js
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ApplogValue } from '../../applog/datom-types.ts';
|
|
2
|
+
import type { ISchemaAdapter, VMAttributeDef } from '../types.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Pattern for creating a schema adapter from an ArkType schema.
|
|
5
|
+
*
|
|
6
|
+
* ArkType is NOT a runtime dependency of @wovin/core, so this adapter
|
|
7
|
+
* works by accepting the ArkType type object directly.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { type } from 'arktype'
|
|
12
|
+
* import { createArkTypeAdapter } from '@wovin/core/viewmodel/adapters/arktype'
|
|
13
|
+
*
|
|
14
|
+
* const MySchema = type({
|
|
15
|
+
* name: 'string',
|
|
16
|
+
* age: 'number | undefined',
|
|
17
|
+
* })
|
|
18
|
+
*
|
|
19
|
+
* const adapter = createArkTypeAdapter(MySchema, 'myEntity')
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function createArkTypeAdapter<T extends Record<string, ApplogValue>>(_arkTypeSchema: {
|
|
23
|
+
infer: T;
|
|
24
|
+
(input: unknown): T | string;
|
|
25
|
+
}, entityPrefix: string, options?: {
|
|
26
|
+
/** Override at-paths for specific attributes */
|
|
27
|
+
atOverrides?: Record<string, string>;
|
|
28
|
+
/** Attribute definitions (must be provided for ArkType since we can't introspect the type) */
|
|
29
|
+
attributes: VMAttributeDef[];
|
|
30
|
+
/** Default values */
|
|
31
|
+
defaults?: Partial<T>;
|
|
32
|
+
}): ISchemaAdapter<T>;
|
|
33
|
+
//# sourceMappingURL=arktype.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arktype.d.ts","sourceRoot":"","sources":["../../../src/viewmodel/adapters/arktype.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACzE,cAAc,EAAE;IAAE,KAAK,EAAE,CAAC,CAAC;IAAC,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,GAAG,MAAM,CAAA;CAAE,EAC1D,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE;IACT,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,8FAA8F;IAC9F,UAAU,EAAE,cAAc,EAAE,CAAA;IAC5B,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;CACrB,GACC,cAAc,CAAC,CAAC,CAAC,CAUnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ApplogValue } from '../../applog/datom-types.ts';
|
|
2
|
+
import type { ISchemaAdapter } from '../types.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Create a schema adapter from a TypeBox object schema.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { Type } from '@sinclair/typebox'
|
|
9
|
+
* import { createTypeBoxAdapter } from '@wovin/core/viewmodel/adapters/typebox'
|
|
10
|
+
*
|
|
11
|
+
* const MySchema = Type.Object({
|
|
12
|
+
* name: Type.String(),
|
|
13
|
+
* age: Type.Optional(Type.Number()),
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* const adapter = createTypeBoxAdapter(MySchema, 'myEntity')
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* The type parameter `T` is the inferred static type of the schema.
|
|
20
|
+
* Can pass a compiled validator separately if runtime validation is needed.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createTypeBoxAdapter<T extends Record<string, ApplogValue>>(typeBoxSchema: {
|
|
23
|
+
properties: Record<string, any>;
|
|
24
|
+
type?: string;
|
|
25
|
+
}, entityPrefix: string, options?: {
|
|
26
|
+
/** Override at-paths for specific attributes */
|
|
27
|
+
atOverrides?: Record<string, string>;
|
|
28
|
+
/** Default values */
|
|
29
|
+
defaults?: Partial<T>;
|
|
30
|
+
/** Property name to at-path mapping function */
|
|
31
|
+
toAtPath?: (entityPrefix: string, attrName: string) => string;
|
|
32
|
+
/** A pre-compiled validator function (e.g. from TypeCompiler.Compile) */
|
|
33
|
+
validator?: (value: unknown) => value is T;
|
|
34
|
+
}): ISchemaAdapter<T>;
|
|
35
|
+
//# sourceMappingURL=typebox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typebox.d.ts","sourceRoot":"","sources":["../../../src/viewmodel/adapters/typebox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,aAAa,CAAA;AAEjE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACzE,aAAa,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EACjE,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE;IACT,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,qBAAqB;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACrB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAA;IAC7D,yEAAyE;IACzE,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,CAAA;CAC1C,GACC,cAAc,CAAC,CAAC,CAAC,CAuBnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|