@hashtree/nostr 0.1.4 → 0.1.5
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 +41 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/snapshot.d.ts +12 -2
- package/dist/snapshot.d.ts.map +1 -1
- package/dist/snapshot.js +14 -4
- package/dist/snapshot.js.map +1 -1
- package/dist/treeEventSnapshots.d.ts +30 -0
- package/dist/treeEventSnapshots.d.ts.map +1 -0
- package/dist/treeEventSnapshots.js +186 -0
- package/dist/treeEventSnapshots.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -82,6 +82,47 @@ const resolver = createNostrRefResolver({
|
|
|
82
82
|
const root = await resolver.resolve('npub1.../myfiles');
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
## Signed Tree Snapshots
|
|
86
|
+
|
|
87
|
+
For immutable permalinks, store a copy of the signed kind `30078` root event as a plain hashtree blob. The snapshot gives you one signed root even when relays do not answer, and you can still watch for newer events later.
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import {
|
|
91
|
+
storeTreeEventSnapshot,
|
|
92
|
+
readTreeEventSnapshot,
|
|
93
|
+
fetchLatestTreeEventSnapshot,
|
|
94
|
+
watchLatestTreeEventSnapshot,
|
|
95
|
+
} from '@hashtree/nostr';
|
|
96
|
+
import { HashTree } from '@hashtree/core';
|
|
97
|
+
|
|
98
|
+
const hashTree = new HashTree({ store });
|
|
99
|
+
|
|
100
|
+
const snapshot = await storeTreeEventSnapshot(hashTree, nip19, signedRootEvent);
|
|
101
|
+
const sameSnapshot = snapshot
|
|
102
|
+
? await readTreeEventSnapshot(hashTree, nip19, snapshot.snapshotCid)
|
|
103
|
+
: null;
|
|
104
|
+
|
|
105
|
+
const latest = await fetchLatestTreeEventSnapshot(
|
|
106
|
+
{ snapshotTarget: hashTree, nip19, fetchEvents },
|
|
107
|
+
'npub1...owner',
|
|
108
|
+
'videos/demo',
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const stop = watchLatestTreeEventSnapshot(
|
|
112
|
+
{ snapshotTarget: hashTree, nip19, fetchEvents, subscribeEvents },
|
|
113
|
+
'npub1...owner',
|
|
114
|
+
'videos/demo',
|
|
115
|
+
(nextSnapshot) => {
|
|
116
|
+
console.log(nextSnapshot.snapshotNhash, nextSnapshot.rootCid);
|
|
117
|
+
},
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
// later
|
|
121
|
+
stop();
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The library does not keep a global snapshot cache for you. It provides stateless helpers plus a live watcher; route caching and reuse policy stay with the app. Pass a `HashTree` when you already have one controlling write policy, or a raw `Store` when the default wrapper is enough.
|
|
125
|
+
|
|
85
126
|
## License
|
|
86
127
|
|
|
87
128
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,6 @@
|
|
|
6
6
|
export { WebRTCStore, DEFAULT_RELAYS, Peer, PeerSelector, PeerId, generateUuid, MAX_HTL, MSG_TYPE_REQUEST, MSG_TYPE_RESPONSE, FRAGMENT_SIZE, encodeRequest, encodeResponse, parseMessage, createRequest, createResponse, createFragmentResponse, hashToKey, verifyHash, generatePeerHTLConfig, decrementHTLWithPolicy, decrementHTL, shouldForwardHTL, peerPrincipal, normalizeDispatchConfig, buildHedgedWavePlan, syncSelectorPeers, shouldForward, type SignalingMessage, type WebRTCStoreConfig, type PeerStatus, type WebRTCStoreEvent, type WebRTCStoreEventHandler, type EventSigner, type EventEncrypter, type EventDecrypter, type GiftWrapper, type GiftUnwrapper, type SignedEvent, type PeerPool, type PeerClassifier, type PoolConfig, type SelectionStrategy, type RequestDispatchConfig, type PersistedPeerMetadata, type PeerMetadataSnapshot, type MeshStats, type WebRTCStats, type BandwidthSample, type DataRequest, type DataResponse, type PeerHTLConfig, type PendingRequest, } from './webrtc/index.js';
|
|
7
7
|
export { createNostrRefResolver, createNostrRefResolver as createNostrRootResolver, type NostrRefResolverConfig, type NostrRefResolverConfig as NostrRootResolverConfig, type NostrEvent, type NostrFilter, type Nip19Like, type VisibilityCallbacks, type ParsedTreeVisibility, } from './resolver/index.js';
|
|
8
8
|
export { NostrEventStore, type StoredNostrEvent, type NostrEventManifest, type ListEventsOptions, } from './events.js';
|
|
9
|
-
export { encodeSignedNostrEventJson, decodeSignedNostrEventJson, storeSignedNostrEventSnapshot, readSignedNostrEventSnapshot, parseHashtreeRootEvent, type ParsedHashtreeRootEvent, } from './snapshot.js';
|
|
9
|
+
export { encodeSignedNostrEventJson, decodeSignedNostrEventJson, storeSignedNostrEventSnapshot, readSignedNostrEventSnapshot, parseHashtreeRootEvent, type ParsedHashtreeRootEvent, type SnapshotTreeLike, type SnapshotTarget, } from './snapshot.js';
|
|
10
|
+
export { storeTreeEventSnapshot, readTreeEventSnapshot, fetchLatestTreeEventSnapshot, watchLatestTreeEventSnapshot, compareTreeEventSnapshots, isNewerTreeEventSnapshot, snapshotMatchesRootCid, resolveSnapshotRootCid, type TreeEventSnapshotInfo, type TreeEventSnapshotQuery, type FetchLatestTreeEventSnapshotConfig, type WatchTreeEventSnapshotsConfig, } from './treeEventSnapshots.js';
|
|
10
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,WAAW,EACX,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EAEb,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,sBAAsB,EAEtB,sBAAsB,IAAI,uBAAuB,EACjD,KAAK,sBAAsB,EAE3B,KAAK,sBAAsB,IAAI,uBAAuB,EACtD,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,EACtB,KAAK,uBAAuB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,WAAW,EACX,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EAEb,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,sBAAsB,EAEtB,sBAAsB,IAAI,uBAAuB,EACjD,KAAK,sBAAsB,EAE3B,KAAK,sBAAsB,IAAI,uBAAuB,EACtD,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,4BAA4B,EAC5B,4BAA4B,EAC5B,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,kCAAkC,EACvC,KAAK,6BAA6B,GACnC,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -14,4 +14,5 @@ createNostrRefResolver as createNostrRootResolver, } from './resolver/index.js';
|
|
|
14
14
|
// Event storage and indexing
|
|
15
15
|
export { NostrEventStore, } from './events.js';
|
|
16
16
|
export { encodeSignedNostrEventJson, decodeSignedNostrEventJson, storeSignedNostrEventSnapshot, readSignedNostrEventSnapshot, parseHashtreeRootEvent, } from './snapshot.js';
|
|
17
|
+
export { storeTreeEventSnapshot, readTreeEventSnapshot, fetchLatestTreeEventSnapshot, watchLatestTreeEventSnapshot, compareTreeEventSnapshots, isNewerTreeEventSnapshot, snapshotMatchesRootCid, resolveSnapshotRootCid, } from './treeEventSnapshots.js';
|
|
17
18
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,iBAAiB,EACjB,aAAa;AACb,qBAAqB;AACrB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,GA0Bd,MAAM,mBAAmB,CAAC;AAE3B,gBAAgB;AAChB,OAAO,EACL,sBAAsB;AACtB,eAAe;AACf,sBAAsB,IAAI,uBAAuB,GASlD,MAAM,qBAAqB,CAAC;AAE7B,6BAA6B;AAC7B,OAAO,EACL,eAAe,GAIhB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,mBAAmB;AACnB,OAAO,EACL,WAAW,EACX,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,iBAAiB,EACjB,aAAa;AACb,qBAAqB;AACrB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,uBAAuB,EACvB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,GA0Bd,MAAM,mBAAmB,CAAC;AAE3B,gBAAgB;AAChB,OAAO,EACL,sBAAsB;AACtB,eAAe;AACf,sBAAsB,IAAI,uBAAuB,GASlD,MAAM,qBAAqB,CAAC;AAE7B,6BAA6B;AAC7B,OAAO,EACL,eAAe,GAIhB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,GAIvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,4BAA4B,EAC5B,4BAA4B,EAC5B,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,GAKvB,MAAM,yBAAyB,CAAC"}
|
package/dist/snapshot.d.ts
CHANGED
|
@@ -11,10 +11,20 @@ export interface ParsedHashtreeRootEvent {
|
|
|
11
11
|
selfEncryptedKey?: string;
|
|
12
12
|
selfEncryptedLinkKey?: string;
|
|
13
13
|
}
|
|
14
|
+
export interface SnapshotTreeLike {
|
|
15
|
+
putFile(data: Uint8Array, options?: {
|
|
16
|
+
unencrypted?: boolean;
|
|
17
|
+
}): Promise<{
|
|
18
|
+
cid: CID;
|
|
19
|
+
size: number;
|
|
20
|
+
}>;
|
|
21
|
+
readFileRange(id: CID, start: number, end?: number): Promise<Uint8Array | null>;
|
|
22
|
+
}
|
|
23
|
+
export type SnapshotTarget = Store | SnapshotTreeLike;
|
|
14
24
|
export declare function normalizeSignedNostrEvent(event: StoredNostrEvent): StoredNostrEvent;
|
|
15
25
|
export declare function encodeSignedNostrEventJson(event: StoredNostrEvent): Uint8Array;
|
|
16
26
|
export declare function decodeSignedNostrEventJson(data: Uint8Array): StoredNostrEvent;
|
|
17
|
-
export declare function storeSignedNostrEventSnapshot(
|
|
18
|
-
export declare function readSignedNostrEventSnapshot(
|
|
27
|
+
export declare function storeSignedNostrEventSnapshot(target: SnapshotTarget, event: StoredNostrEvent): Promise<CID>;
|
|
28
|
+
export declare function readSignedNostrEventSnapshot(target: SnapshotTarget, snapshotCid: CID, maxBytes?: number): Promise<StoredNostrEvent>;
|
|
19
29
|
export declare function parseHashtreeRootEvent(event: StoredNostrEvent): ParsedHashtreeRootEvent | null;
|
|
20
30
|
//# sourceMappingURL=snapshot.d.ts.map
|
package/dist/snapshot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,GAAG,EAAE,KAAK,KAAK,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACnG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAQpD,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,GAAG,CAAC;IACb,UAAU,EAAE,cAAc,CAAC;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;
|
|
1
|
+
{"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,GAAG,EAAE,KAAK,KAAK,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACnG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAQpD,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,GAAG,CAAC;IACb,UAAU,EAAE,cAAc,CAAC;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CACL,IAAI,EAAE,UAAU,EAChB,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,GAClC,OAAO,CAAC;QAAE,GAAG,EAAE,GAAG,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvC,aAAa,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;CACjF;AAED,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,gBAAgB,CAAC;AAsCtD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,gBAAgB,GAAG,gBAAgB,CA+BnF;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,gBAAgB,GAAG,UAAU,CAW9E;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,UAAU,GAAG,gBAAgB,CAW7E;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,CAGjH;AAED,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,GAAG,EAChB,QAAQ,SAAqB,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAU3B;AAUD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,GAAG,uBAAuB,GAAG,IAAI,CAgD9F"}
|
package/dist/snapshot.js
CHANGED
|
@@ -4,6 +4,16 @@ const HEX_128 = /^[0-9a-f]{128}$/;
|
|
|
4
4
|
const MAX_SNAPSHOT_BYTES = 256 * 1024;
|
|
5
5
|
const textEncoder = new TextEncoder();
|
|
6
6
|
const textDecoder = new TextDecoder();
|
|
7
|
+
function isSnapshotTreeLike(target) {
|
|
8
|
+
return (typeof target.putFile === 'function' &&
|
|
9
|
+
typeof target.readFileRange === 'function');
|
|
10
|
+
}
|
|
11
|
+
function getSnapshotTree(target) {
|
|
12
|
+
if (isSnapshotTreeLike(target)) {
|
|
13
|
+
return target;
|
|
14
|
+
}
|
|
15
|
+
return new HashTree({ store: target });
|
|
16
|
+
}
|
|
7
17
|
function assertStringTags(tags) {
|
|
8
18
|
if (!Array.isArray(tags)) {
|
|
9
19
|
throw new Error('Nostr event tags must be an array');
|
|
@@ -80,12 +90,12 @@ export function decodeSignedNostrEventJson(data) {
|
|
|
80
90
|
sig: typeof parsed.sig === 'string' ? parsed.sig : '',
|
|
81
91
|
});
|
|
82
92
|
}
|
|
83
|
-
export async function storeSignedNostrEventSnapshot(
|
|
84
|
-
const tree =
|
|
93
|
+
export async function storeSignedNostrEventSnapshot(target, event) {
|
|
94
|
+
const tree = getSnapshotTree(target);
|
|
85
95
|
return (await tree.putFile(encodeSignedNostrEventJson(event), { unencrypted: true })).cid;
|
|
86
96
|
}
|
|
87
|
-
export async function readSignedNostrEventSnapshot(
|
|
88
|
-
const tree =
|
|
97
|
+
export async function readSignedNostrEventSnapshot(target, snapshotCid, maxBytes = MAX_SNAPSHOT_BYTES) {
|
|
98
|
+
const tree = getSnapshotTree(target);
|
|
89
99
|
const bytes = await tree.readFileRange(snapshotCid, 0, maxBytes + 1);
|
|
90
100
|
if (!bytes) {
|
|
91
101
|
throw new Error('Signed Nostr event snapshot is missing');
|
package/dist/snapshot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAA6C,MAAM,gBAAgB,CAAC;AAGnG,MAAM,MAAM,GAAG,gBAAgB,CAAC;AAChC,MAAM,OAAO,GAAG,iBAAiB,CAAC;AAClC,MAAM,kBAAkB,GAAG,GAAG,GAAG,IAAI,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type CID } from '@hashtree/core';
|
|
2
|
+
import type { StoredNostrEvent } from './events.js';
|
|
3
|
+
import type { Nip19Like, NostrFilter } from './resolver/nostr.js';
|
|
4
|
+
import { type ParsedHashtreeRootEvent, type SnapshotTarget } from './snapshot.js';
|
|
5
|
+
export interface TreeEventSnapshotInfo extends ParsedHashtreeRootEvent {
|
|
6
|
+
snapshotCid: CID;
|
|
7
|
+
snapshotNhash: string;
|
|
8
|
+
npub: string;
|
|
9
|
+
}
|
|
10
|
+
export interface TreeEventSnapshotQuery extends NostrFilter {
|
|
11
|
+
limit?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface FetchLatestTreeEventSnapshotConfig {
|
|
14
|
+
snapshotTarget: SnapshotTarget;
|
|
15
|
+
nip19: Nip19Like;
|
|
16
|
+
fetchEvents: (filter: TreeEventSnapshotQuery) => Promise<StoredNostrEvent[]>;
|
|
17
|
+
snapshotFetchLimit?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface WatchTreeEventSnapshotsConfig extends FetchLatestTreeEventSnapshotConfig {
|
|
20
|
+
subscribeEvents: (filter: TreeEventSnapshotQuery, onEvent: (event: StoredNostrEvent) => void) => () => void;
|
|
21
|
+
}
|
|
22
|
+
export declare function compareTreeEventSnapshots(a: TreeEventSnapshotInfo, b: TreeEventSnapshotInfo): number;
|
|
23
|
+
export declare function isNewerTreeEventSnapshot(candidate: TreeEventSnapshotInfo, current: TreeEventSnapshotInfo): boolean;
|
|
24
|
+
export declare function snapshotMatchesRootCid(snapshot: TreeEventSnapshotInfo | null | undefined, rootCid: CID | null | undefined): boolean;
|
|
25
|
+
export declare function resolveSnapshotRootCid(snapshot: TreeEventSnapshotInfo, linkKey?: string | Uint8Array | null): Promise<CID | null>;
|
|
26
|
+
export declare function storeTreeEventSnapshot(snapshotTarget: SnapshotTarget, nip19: Nip19Like, event: StoredNostrEvent): Promise<TreeEventSnapshotInfo | null>;
|
|
27
|
+
export declare function readTreeEventSnapshot(snapshotTarget: SnapshotTarget, nip19: Nip19Like, snapshotCid: CID, maxBytes?: number): Promise<TreeEventSnapshotInfo | null>;
|
|
28
|
+
export declare function fetchLatestTreeEventSnapshot(config: FetchLatestTreeEventSnapshotConfig, npub: string, treeName: string): Promise<TreeEventSnapshotInfo | null>;
|
|
29
|
+
export declare function watchLatestTreeEventSnapshot(config: WatchTreeEventSnapshotsConfig, npub: string, treeName: string, onSnapshot: (snapshot: TreeEventSnapshotInfo) => void | Promise<void>): () => void;
|
|
30
|
+
//# sourceMappingURL=treeEventSnapshots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treeEventSnapshots.d.ts","sourceRoot":"","sources":["../src/treeEventSnapshots.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,GAAG,EACT,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAIL,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACpB,MAAM,eAAe,CAAC;AAIvB,MAAM,WAAW,qBAAsB,SAAQ,uBAAuB;IACpE,WAAW,EAAE,GAAG,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,sBAAuB,SAAQ,WAAW;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kCAAkC;IACjD,cAAc,EAAE,cAAc,CAAC;IAC/B,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC7E,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,6BAA8B,SAAQ,kCAAkC;IACvF,eAAe,EAAE,CACf,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,KACvC,MAAM,IAAI,CAAC;CACjB;AAiDD,wBAAgB,yBAAyB,CAAC,CAAC,EAAE,qBAAqB,EAAE,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAEpG;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,qBAAqB,EAChC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAET;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,EAClD,OAAO,EAAE,GAAG,GAAG,IAAI,GAAG,SAAS,GAC9B,OAAO,CAgBT;AAED,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,GACnC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAwBrB;AAED,wBAAsB,sBAAsB,CAC1C,cAAc,EAAE,cAAc,EAC9B,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAOvC;AAED,wBAAsB,qBAAqB,CACzC,cAAc,EAAE,cAAc,EAC9B,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,GAAG,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAWvC;AAED,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,kCAAkC,EAC1C,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CA+BvC;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,6BAA6B,EACrC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACpE,MAAM,IAAI,CA4DZ"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { decryptKeyFromLink, fromHex, nhashEncode, toHex, } from '@hashtree/core';
|
|
2
|
+
import { parseHashtreeRootEvent, readSignedNostrEventSnapshot, storeSignedNostrEventSnapshot, } from './snapshot.js';
|
|
3
|
+
const DEFAULT_SNAPSHOT_FETCH_LIMIT = 20;
|
|
4
|
+
function compareEvents(a, b) {
|
|
5
|
+
if (a.created_at !== b.created_at) {
|
|
6
|
+
return a.created_at - b.created_at;
|
|
7
|
+
}
|
|
8
|
+
return a.id.localeCompare(b.id);
|
|
9
|
+
}
|
|
10
|
+
function snapshotInfoFromParsed(parsed, snapshotCid, nip19) {
|
|
11
|
+
return {
|
|
12
|
+
...parsed,
|
|
13
|
+
snapshotCid,
|
|
14
|
+
snapshotNhash: nhashEncode(snapshotCid),
|
|
15
|
+
npub: nip19.npubEncode(parsed.event.pubkey),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function tryParseHashtreeRootEvent(event) {
|
|
19
|
+
try {
|
|
20
|
+
return parseHashtreeRootEvent(event);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function normalizeLinkKey(linkKey) {
|
|
27
|
+
if (!linkKey) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return typeof linkKey === 'string' ? fromHex(linkKey) : linkKey;
|
|
31
|
+
}
|
|
32
|
+
function isValidTreeEventFor(event, pubkey, treeName) {
|
|
33
|
+
if (event.pubkey !== pubkey) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const parsed = tryParseHashtreeRootEvent(event);
|
|
37
|
+
return parsed?.treeName === treeName;
|
|
38
|
+
}
|
|
39
|
+
export function compareTreeEventSnapshots(a, b) {
|
|
40
|
+
return compareEvents(a.event, b.event);
|
|
41
|
+
}
|
|
42
|
+
export function isNewerTreeEventSnapshot(candidate, current) {
|
|
43
|
+
return compareTreeEventSnapshots(candidate, current) > 0;
|
|
44
|
+
}
|
|
45
|
+
export function snapshotMatchesRootCid(snapshot, rootCid) {
|
|
46
|
+
if (!snapshot || !rootCid) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
if (toHex(snapshot.rootCid.hash) !== toHex(rootCid.hash)) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if (snapshot.visibility !== 'public') {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
const snapshotKey = snapshot.rootCid.key ? toHex(snapshot.rootCid.key) : null;
|
|
56
|
+
const rootKey = rootCid.key ? toHex(rootCid.key) : null;
|
|
57
|
+
if (snapshotKey === null || rootKey === null) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
return snapshotKey === rootKey;
|
|
61
|
+
}
|
|
62
|
+
export async function resolveSnapshotRootCid(snapshot, linkKey) {
|
|
63
|
+
if (snapshot.visibility === 'public') {
|
|
64
|
+
return snapshot.rootCid;
|
|
65
|
+
}
|
|
66
|
+
if (snapshot.visibility === 'link-visible' && snapshot.encryptedKey) {
|
|
67
|
+
const normalizedLinkKey = normalizeLinkKey(linkKey);
|
|
68
|
+
if (!normalizedLinkKey) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const decryptedKey = await decryptKeyFromLink(fromHex(snapshot.encryptedKey), normalizedLinkKey);
|
|
73
|
+
if (decryptedKey) {
|
|
74
|
+
return { hash: snapshot.rootCid.hash, key: decryptedKey };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
export async function storeTreeEventSnapshot(snapshotTarget, nip19, event) {
|
|
84
|
+
const parsed = tryParseHashtreeRootEvent(event);
|
|
85
|
+
if (!parsed) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const snapshotCid = await storeSignedNostrEventSnapshot(snapshotTarget, parsed.event);
|
|
89
|
+
return snapshotInfoFromParsed(parsed, snapshotCid, nip19);
|
|
90
|
+
}
|
|
91
|
+
export async function readTreeEventSnapshot(snapshotTarget, nip19, snapshotCid, maxBytes) {
|
|
92
|
+
try {
|
|
93
|
+
const event = await readSignedNostrEventSnapshot(snapshotTarget, snapshotCid, maxBytes);
|
|
94
|
+
const parsed = tryParseHashtreeRootEvent(event);
|
|
95
|
+
if (!parsed) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return snapshotInfoFromParsed(parsed, snapshotCid, nip19);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export async function fetchLatestTreeEventSnapshot(config, npub, treeName) {
|
|
105
|
+
let decoded;
|
|
106
|
+
try {
|
|
107
|
+
decoded = config.nip19.decode(npub);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
if (decoded.type !== 'npub' || typeof decoded.data !== 'string') {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
const events = await config.fetchEvents({
|
|
116
|
+
kinds: [30078],
|
|
117
|
+
authors: [decoded.data],
|
|
118
|
+
'#d': [treeName],
|
|
119
|
+
limit: config.snapshotFetchLimit ?? DEFAULT_SNAPSHOT_FETCH_LIMIT,
|
|
120
|
+
});
|
|
121
|
+
const candidates = [];
|
|
122
|
+
for (const event of events) {
|
|
123
|
+
if (!isValidTreeEventFor(event, decoded.data, treeName)) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
candidates.push(event);
|
|
127
|
+
}
|
|
128
|
+
if (candidates.length === 0) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
candidates.sort(compareEvents);
|
|
132
|
+
return storeTreeEventSnapshot(config.snapshotTarget, config.nip19, candidates[candidates.length - 1]);
|
|
133
|
+
}
|
|
134
|
+
export function watchLatestTreeEventSnapshot(config, npub, treeName, onSnapshot) {
|
|
135
|
+
let decoded;
|
|
136
|
+
try {
|
|
137
|
+
decoded = config.nip19.decode(npub);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return () => { };
|
|
141
|
+
}
|
|
142
|
+
if (decoded.type !== 'npub' || typeof decoded.data !== 'string') {
|
|
143
|
+
return () => { };
|
|
144
|
+
}
|
|
145
|
+
const pubkey = decoded.data;
|
|
146
|
+
let closed = false;
|
|
147
|
+
let latestSnapshot = null;
|
|
148
|
+
const emitIfNewer = async (event) => {
|
|
149
|
+
if (closed || !isValidTreeEventFor(event, pubkey, treeName)) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const snapshot = await storeTreeEventSnapshot(config.snapshotTarget, config.nip19, event);
|
|
153
|
+
if (!snapshot) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (latestSnapshot && compareTreeEventSnapshots(snapshot, latestSnapshot) <= 0) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
latestSnapshot = snapshot;
|
|
160
|
+
await onSnapshot(snapshot);
|
|
161
|
+
};
|
|
162
|
+
fetchLatestTreeEventSnapshot(config, npub, treeName)
|
|
163
|
+
.then(async (snapshot) => {
|
|
164
|
+
if (closed || !snapshot) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (latestSnapshot && compareTreeEventSnapshots(snapshot, latestSnapshot) <= 0) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
latestSnapshot = snapshot;
|
|
171
|
+
await onSnapshot(snapshot);
|
|
172
|
+
})
|
|
173
|
+
.catch(() => { });
|
|
174
|
+
const unsubscribe = config.subscribeEvents({
|
|
175
|
+
kinds: [30078],
|
|
176
|
+
authors: [pubkey],
|
|
177
|
+
'#d': [treeName],
|
|
178
|
+
}, (event) => {
|
|
179
|
+
void emitIfNewer(event);
|
|
180
|
+
});
|
|
181
|
+
return () => {
|
|
182
|
+
closed = true;
|
|
183
|
+
unsubscribe();
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=treeEventSnapshots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treeEventSnapshots.js","sourceRoot":"","sources":["../src/treeEventSnapshots.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,OAAO,EACP,WAAW,EACX,KAAK,GAEN,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,6BAA6B,GAG9B,MAAM,eAAe,CAAC;AAEvB,MAAM,4BAA4B,GAAG,EAAE,CAAC;AA0BxC,SAAS,aAAa,CAAC,CAAmB,EAAE,CAAmB;IAC7D,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC;QAClC,OAAO,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,sBAAsB,CAC7B,MAA+B,EAC/B,WAAgB,EAChB,KAAgB;IAEhB,OAAO;QACL,GAAG,MAAM;QACT,WAAW;QACX,aAAa,EAAE,WAAW,CAAC,WAAW,CAAC;QACvC,IAAI,EAAE,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;KAC5C,CAAC;AACJ,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAuB;IACxD,IAAI,CAAC;QACH,OAAO,sBAAsB,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAoC;IAC5D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AAClE,CAAC;AAED,SAAS,mBAAmB,CAC1B,KAAuB,EACvB,MAAc,EACd,QAAgB;IAEhB,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,MAAM,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;IAChD,OAAO,MAAM,EAAE,QAAQ,KAAK,QAAQ,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,CAAwB,EAAE,CAAwB;IAC1F,OAAO,aAAa,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,SAAgC,EAChC,OAA8B;IAE9B,OAAO,yBAAyB,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,QAAkD,EAClD,OAA+B;IAE/B,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,QAAQ,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,IAAI,WAAW,KAAK,IAAI,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,WAAW,KAAK,OAAO,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,QAA+B,EAC/B,OAAoC;IAEpC,IAAI,QAAQ,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACrC,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC1B,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,KAAK,cAAc,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;QACpE,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACpD,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAC9B,iBAAiB,CAClB,CAAC;YACF,IAAI,YAAY,EAAE,CAAC;gBACjB,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC;YAC5D,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,cAA8B,EAC9B,KAAgB,EAChB,KAAuB;IAEvB,MAAM,MAAM,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,6BAA6B,CAAC,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACtF,OAAO,sBAAsB,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,cAA8B,EAC9B,KAAgB,EAChB,WAAgB,EAChB,QAAiB;IAEjB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,4BAA4B,CAAC,cAAc,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;QACxF,MAAM,MAAM,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,sBAAsB,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,MAA0C,EAC1C,IAAY,EACZ,QAAgB;IAEhB,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC;QACtC,KAAK,EAAE,CAAC,KAAK,CAAC;QACd,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;QACvB,IAAI,EAAE,CAAC,QAAQ,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC,kBAAkB,IAAI,4BAA4B;KACjE,CAAC,CAAC;IAEH,MAAM,UAAU,GAAuB,EAAE,CAAC;IAC1C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;YACxD,SAAS;QACX,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC/B,OAAO,sBAAsB,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,CAAC;AACzG,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,MAAqC,EACrC,IAAY,EACZ,QAAgB,EAChB,UAAqE;IAErE,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAChE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAE5B,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,cAAc,GAAiC,IAAI,CAAC;IAExD,MAAM,WAAW,GAAG,KAAK,EAAE,KAAuB,EAAiB,EAAE;QACnE,IAAI,MAAM,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC5D,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC1F,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QACD,IAAI,cAAc,IAAI,yBAAyB,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/E,OAAO;QACT,CAAC;QAED,cAAc,GAAG,QAAQ,CAAC;QAC1B,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC,CAAC;IAEF,4BAA4B,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC;SACjD,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QACvB,IAAI,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxB,OAAO;QACT,CAAC;QACD,IAAI,cAAc,IAAI,yBAAyB,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/E,OAAO;QACT,CAAC;QACD,cAAc,GAAG,QAAQ,CAAC;QAC1B,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC,CAAC;SACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAEnB,MAAM,WAAW,GAAG,MAAM,CAAC,eAAe,CACxC;QACE,KAAK,EAAE,CAAC,KAAK,CAAC;QACd,OAAO,EAAE,CAAC,MAAM,CAAC;QACjB,IAAI,EAAE,CAAC,QAAQ,CAAC;KACjB,EACD,CAAC,KAAK,EAAE,EAAE;QACR,KAAK,WAAW,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC,CACF,CAAC;IAEF,OAAO,GAAG,EAAE;QACV,MAAM,GAAG,IAAI,CAAC;QACd,WAAW,EAAE,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
|