@bcts/hubert 1.0.0-alpha.17
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/LICENSE +48 -0
- package/README.md +18 -0
- package/dist/arid-derivation-1CJuU-kZ.cjs +150 -0
- package/dist/arid-derivation-1CJuU-kZ.cjs.map +1 -0
- package/dist/arid-derivation-CbqACjdg.mjs +126 -0
- package/dist/arid-derivation-CbqACjdg.mjs.map +1 -0
- package/dist/bin/hubert.cjs +384 -0
- package/dist/bin/hubert.cjs.map +1 -0
- package/dist/bin/hubert.d.cts +1 -0
- package/dist/bin/hubert.d.mts +1 -0
- package/dist/bin/hubert.mjs +383 -0
- package/dist/bin/hubert.mjs.map +1 -0
- package/dist/chunk-CbDLau6x.cjs +34 -0
- package/dist/hybrid/index.cjs +14 -0
- package/dist/hybrid/index.d.cts +3 -0
- package/dist/hybrid/index.d.mts +3 -0
- package/dist/hybrid/index.mjs +6 -0
- package/dist/hybrid-BZhumygj.mjs +356 -0
- package/dist/hybrid-BZhumygj.mjs.map +1 -0
- package/dist/hybrid-dX5JLumO.cjs +410 -0
- package/dist/hybrid-dX5JLumO.cjs.map +1 -0
- package/dist/index-BEzpUC7r.d.mts +380 -0
- package/dist/index-BEzpUC7r.d.mts.map +1 -0
- package/dist/index-C2F6ugLL.d.mts +210 -0
- package/dist/index-C2F6ugLL.d.mts.map +1 -0
- package/dist/index-CUnDouMb.d.mts +215 -0
- package/dist/index-CUnDouMb.d.mts.map +1 -0
- package/dist/index-CV6lZJqY.d.cts +380 -0
- package/dist/index-CV6lZJqY.d.cts.map +1 -0
- package/dist/index-CY3TCzIm.d.cts +217 -0
- package/dist/index-CY3TCzIm.d.cts.map +1 -0
- package/dist/index-DEr4SR1J.d.cts +215 -0
- package/dist/index-DEr4SR1J.d.cts.map +1 -0
- package/dist/index-T1LHanIb.d.mts +217 -0
- package/dist/index-T1LHanIb.d.mts.map +1 -0
- package/dist/index-jyzuOhFB.d.cts +210 -0
- package/dist/index-jyzuOhFB.d.cts.map +1 -0
- package/dist/index.cjs +60 -0
- package/dist/index.d.cts +161 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +161 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +10 -0
- package/dist/ipfs/index.cjs +13 -0
- package/dist/ipfs/index.d.cts +3 -0
- package/dist/ipfs/index.d.mts +3 -0
- package/dist/ipfs/index.mjs +5 -0
- package/dist/ipfs-BRMMCBjv.mjs +1 -0
- package/dist/ipfs-CetOVQcO.cjs +0 -0
- package/dist/kv-BAmhmMOo.cjs +425 -0
- package/dist/kv-BAmhmMOo.cjs.map +1 -0
- package/dist/kv-C-emxv0w.mjs +375 -0
- package/dist/kv-C-emxv0w.mjs.map +1 -0
- package/dist/kv-DJiKvypY.mjs +403 -0
- package/dist/kv-DJiKvypY.mjs.map +1 -0
- package/dist/kv-store-DmngWWuw.d.mts +183 -0
- package/dist/kv-store-DmngWWuw.d.mts.map +1 -0
- package/dist/kv-store-ww-AUyLd.d.cts +183 -0
- package/dist/kv-store-ww-AUyLd.d.cts.map +1 -0
- package/dist/kv-yjvQa_LH.cjs +457 -0
- package/dist/kv-yjvQa_LH.cjs.map +1 -0
- package/dist/logging-hmzNzifq.mjs +158 -0
- package/dist/logging-hmzNzifq.mjs.map +1 -0
- package/dist/logging-qc9uMgil.cjs +212 -0
- package/dist/logging-qc9uMgil.cjs.map +1 -0
- package/dist/mainline/index.cjs +12 -0
- package/dist/mainline/index.d.cts +3 -0
- package/dist/mainline/index.d.mts +3 -0
- package/dist/mainline/index.mjs +5 -0
- package/dist/mainline-D_jfeFMh.cjs +0 -0
- package/dist/mainline-cFIuXbo-.mjs +1 -0
- package/dist/server/index.cjs +14 -0
- package/dist/server/index.d.cts +3 -0
- package/dist/server/index.d.mts +3 -0
- package/dist/server/index.mjs +3 -0
- package/dist/server-BBNRZ30D.cjs +912 -0
- package/dist/server-BBNRZ30D.cjs.map +1 -0
- package/dist/server-DVyk9gqU.mjs +836 -0
- package/dist/server-DVyk9gqU.mjs.map +1 -0
- package/package.json +125 -0
- package/src/arid-derivation.ts +155 -0
- package/src/bin/hubert.ts +667 -0
- package/src/error.ts +89 -0
- package/src/hybrid/error.ts +77 -0
- package/src/hybrid/index.ts +24 -0
- package/src/hybrid/kv.ts +236 -0
- package/src/hybrid/reference.ts +176 -0
- package/src/index.ts +145 -0
- package/src/ipfs/error.ts +83 -0
- package/src/ipfs/index.ts +24 -0
- package/src/ipfs/kv.ts +476 -0
- package/src/ipfs/value.ts +85 -0
- package/src/kv-store.ts +128 -0
- package/src/logging.ts +88 -0
- package/src/mainline/error.ts +108 -0
- package/src/mainline/index.ts +23 -0
- package/src/mainline/kv.ts +411 -0
- package/src/server/error.ts +83 -0
- package/src/server/index.ts +29 -0
- package/src/server/kv.ts +211 -0
- package/src/server/memory-kv.ts +191 -0
- package/src/server/server-kv.ts +92 -0
- package/src/server/server.ts +369 -0
- package/src/server/sqlite-kv.ts +295 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { r as HubertError, t as KvStore } from "./kv-store-ww-AUyLd.cjs";
|
|
2
|
+
import { ARID } from "@bcts/components";
|
|
3
|
+
import { Envelope } from "@bcts/envelope";
|
|
4
|
+
|
|
5
|
+
//#region src/hybrid/error.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Base class for Hybrid-specific errors.
|
|
8
|
+
*
|
|
9
|
+
* @category Hybrid
|
|
10
|
+
*/
|
|
11
|
+
declare class HybridError extends HubertError {
|
|
12
|
+
constructor(message: string);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Referenced IPFS content not found.
|
|
16
|
+
*
|
|
17
|
+
* Port of `Error::ContentNotFound` from hybrid/error.rs line 4-5.
|
|
18
|
+
*
|
|
19
|
+
* @category Hybrid
|
|
20
|
+
*/
|
|
21
|
+
declare class ContentNotFoundError extends HybridError {
|
|
22
|
+
constructor();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Not a reference envelope.
|
|
26
|
+
*
|
|
27
|
+
* Port of `Error::NotReferenceEnvelope` from hybrid/error.rs line 7-8.
|
|
28
|
+
*
|
|
29
|
+
* @category Hybrid
|
|
30
|
+
*/
|
|
31
|
+
declare class NotReferenceEnvelopeError extends HybridError {
|
|
32
|
+
constructor();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Invalid ARID in reference envelope.
|
|
36
|
+
*
|
|
37
|
+
* Port of `Error::InvalidReferenceArid` from hybrid/error.rs line 10-11.
|
|
38
|
+
*
|
|
39
|
+
* @category Hybrid
|
|
40
|
+
*/
|
|
41
|
+
declare class InvalidReferenceAridError extends HybridError {
|
|
42
|
+
constructor();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* No id assertion found in reference envelope.
|
|
46
|
+
*
|
|
47
|
+
* Port of `Error::NoIdAssertion` from hybrid/error.rs line 13-14.
|
|
48
|
+
*
|
|
49
|
+
* @category Hybrid
|
|
50
|
+
*/
|
|
51
|
+
declare class NoIdAssertionError extends HybridError {
|
|
52
|
+
constructor();
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/hybrid/reference.d.ts
|
|
56
|
+
/**
|
|
57
|
+
* Creates a reference envelope that points to content stored in IPFS.
|
|
58
|
+
*
|
|
59
|
+
* Reference envelopes are small envelopes stored in the DHT that contain
|
|
60
|
+
* a pointer to the actual envelope stored in IPFS. This allows the hybrid
|
|
61
|
+
* storage layer to transparently handle large envelopes that exceed the
|
|
62
|
+
* DHT size limit.
|
|
63
|
+
*
|
|
64
|
+
* Port of `create_reference_envelope()` from hybrid/reference.rs lines 31-39.
|
|
65
|
+
*
|
|
66
|
+
* # Format
|
|
67
|
+
*
|
|
68
|
+
* ```text
|
|
69
|
+
* '' [
|
|
70
|
+
* 'dereferenceVia': "ipfs",
|
|
71
|
+
* 'id': <ARID>,
|
|
72
|
+
* "size": <number>
|
|
73
|
+
* ]
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @param referenceArid - The ARID used to look up the actual envelope in IPFS
|
|
77
|
+
* @param actualSize - Size of the actual envelope in bytes (for diagnostics)
|
|
78
|
+
* @returns A reference envelope that can be stored in the DHT
|
|
79
|
+
*
|
|
80
|
+
* @category Hybrid
|
|
81
|
+
*/
|
|
82
|
+
declare function createReferenceEnvelope(referenceArid: ARID, actualSize: number): Envelope;
|
|
83
|
+
/**
|
|
84
|
+
* Checks if an envelope is a reference envelope.
|
|
85
|
+
*
|
|
86
|
+
* A reference envelope contains `dereferenceVia: "ipfs"` and an `id` assertion.
|
|
87
|
+
*
|
|
88
|
+
* Port of `is_reference_envelope()` from hybrid/reference.rs lines 53-91.
|
|
89
|
+
*
|
|
90
|
+
* @param envelope - The envelope to check
|
|
91
|
+
* @returns `true` if this is a reference envelope, `false` otherwise
|
|
92
|
+
*
|
|
93
|
+
* @category Hybrid
|
|
94
|
+
*/
|
|
95
|
+
declare function isReferenceEnvelope(envelope: Envelope): boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Extracts the reference ARID from a reference envelope.
|
|
98
|
+
*
|
|
99
|
+
* Port of `extract_reference_arid()` from hybrid/reference.rs lines 104-129.
|
|
100
|
+
*
|
|
101
|
+
* @param envelope - The reference envelope
|
|
102
|
+
* @returns The reference ARID
|
|
103
|
+
* @throws {NotReferenceEnvelopeError} If the envelope is not a reference envelope
|
|
104
|
+
* @throws {InvalidReferenceAridError} If the ARID cannot be extracted
|
|
105
|
+
* @throws {NoIdAssertionError} If no id assertion is found
|
|
106
|
+
*
|
|
107
|
+
* @category Hybrid
|
|
108
|
+
*/
|
|
109
|
+
declare function extractReferenceArid(envelope: Envelope): ARID;
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/hybrid/kv.d.ts
|
|
112
|
+
/**
|
|
113
|
+
* Hybrid storage layer combining Mainline DHT and IPFS.
|
|
114
|
+
*
|
|
115
|
+
* Automatically optimizes storage based on envelope size:
|
|
116
|
+
* - **Small envelopes (≤1000 bytes)**: Stored directly in DHT
|
|
117
|
+
* - **Large envelopes (>1000 bytes)**: Reference in DHT → actual envelope in IPFS
|
|
118
|
+
*
|
|
119
|
+
* This provides the best of both worlds:
|
|
120
|
+
* - Fast lookups for small messages via DHT
|
|
121
|
+
* - Large capacity for big messages via IPFS
|
|
122
|
+
* - Transparent indirection handled automatically
|
|
123
|
+
*
|
|
124
|
+
* Port of `struct HybridKv` from hybrid/kv.rs lines 59-63.
|
|
125
|
+
*
|
|
126
|
+
* # Requirements
|
|
127
|
+
*
|
|
128
|
+
* - No external daemon for DHT (embedded client)
|
|
129
|
+
* - Requires Kubo daemon for IPFS (http://127.0.0.1:5001)
|
|
130
|
+
*
|
|
131
|
+
* @category Hybrid Backend
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const store = await HybridKv.create("http://127.0.0.1:5001");
|
|
136
|
+
*
|
|
137
|
+
* // Small envelope → DHT only
|
|
138
|
+
* const arid1 = ARID.new();
|
|
139
|
+
* const small = Envelope.new("Small message");
|
|
140
|
+
* await store.put(arid1, small);
|
|
141
|
+
*
|
|
142
|
+
* // Large envelope → DHT reference + IPFS
|
|
143
|
+
* const arid2 = ARID.new();
|
|
144
|
+
* const large = Envelope.new("x".repeat(2000));
|
|
145
|
+
* await store.put(arid2, large);
|
|
146
|
+
*
|
|
147
|
+
* // Get works the same for both
|
|
148
|
+
* const retrieved1 = await store.get(arid1);
|
|
149
|
+
* const retrieved2 = await store.get(arid2);
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
declare class HybridKv implements KvStore {
|
|
153
|
+
private readonly dht;
|
|
154
|
+
private ipfs;
|
|
155
|
+
private dhtSizeLimit;
|
|
156
|
+
/**
|
|
157
|
+
* Private constructor - use `create()` factory method.
|
|
158
|
+
*/
|
|
159
|
+
private constructor();
|
|
160
|
+
/**
|
|
161
|
+
* Create a new Hybrid KV store with default settings.
|
|
162
|
+
*
|
|
163
|
+
* Port of `HybridKv::new()` from hybrid/kv.rs lines 75-84.
|
|
164
|
+
*
|
|
165
|
+
* @param ipfsRpcUrl - IPFS RPC endpoint (e.g., "http://127.0.0.1:5001")
|
|
166
|
+
*/
|
|
167
|
+
static create(ipfsRpcUrl: string): Promise<HybridKv>;
|
|
168
|
+
/**
|
|
169
|
+
* Set custom DHT size limit (default: 1000 bytes).
|
|
170
|
+
*
|
|
171
|
+
* Envelopes larger than this will use IPFS indirection.
|
|
172
|
+
*
|
|
173
|
+
* Port of `HybridKv::with_dht_size_limit()` from hybrid/kv.rs lines 89-92.
|
|
174
|
+
*/
|
|
175
|
+
withDhtSizeLimit(limit: number): this;
|
|
176
|
+
/**
|
|
177
|
+
* Set whether to pin content in IPFS (default: false).
|
|
178
|
+
*
|
|
179
|
+
* Only affects envelopes stored in IPFS (when larger than DHT limit).
|
|
180
|
+
*
|
|
181
|
+
* Port of `HybridKv::with_pin_content()` from hybrid/kv.rs lines 97-100.
|
|
182
|
+
*/
|
|
183
|
+
withPinContent(pin: boolean): this;
|
|
184
|
+
/**
|
|
185
|
+
* Check if an envelope fits in the DHT.
|
|
186
|
+
*
|
|
187
|
+
* Port of `HybridKv::fits_in_dht()` from hybrid/kv.rs lines 103-106.
|
|
188
|
+
*
|
|
189
|
+
* @internal
|
|
190
|
+
*/
|
|
191
|
+
private fitsInDht;
|
|
192
|
+
/**
|
|
193
|
+
* Store an envelope at the given ARID.
|
|
194
|
+
*
|
|
195
|
+
* Port of `KvStore::put()` implementation from hybrid/kv.rs lines 109-168.
|
|
196
|
+
*/
|
|
197
|
+
put(arid: ARID, envelope: Envelope, ttlSeconds?: number, verbose?: boolean): Promise<string>;
|
|
198
|
+
/**
|
|
199
|
+
* Retrieve an envelope for the given ARID.
|
|
200
|
+
*
|
|
201
|
+
* Port of `KvStore::get()` implementation from hybrid/kv.rs lines 171-230.
|
|
202
|
+
*/
|
|
203
|
+
get(arid: ARID, timeoutSeconds?: number, verbose?: boolean): Promise<Envelope | null>;
|
|
204
|
+
/**
|
|
205
|
+
* Check if an envelope exists at the given ARID.
|
|
206
|
+
*
|
|
207
|
+
* Port of `KvStore::exists()` implementation from hybrid/kv.rs lines 254-257.
|
|
208
|
+
*/
|
|
209
|
+
exists(arid: ARID): Promise<boolean>;
|
|
210
|
+
/**
|
|
211
|
+
* Destroy the hybrid store and release resources.
|
|
212
|
+
*/
|
|
213
|
+
destroy(): Promise<void>;
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
export { ContentNotFoundError as a, NoIdAssertionError as c, isReferenceEnvelope as i, NotReferenceEnvelopeError as l, createReferenceEnvelope as n, HybridError as o, extractReferenceArid as r, InvalidReferenceAridError as s, HybridKv as t };
|
|
217
|
+
//# sourceMappingURL=index-CY3TCzIm.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CY3TCzIm.d.cts","names":[],"sources":["../src/hybrid/error.ts","../src/hybrid/reference.ts","../src/hybrid/kv.ts"],"mappings":";;;;;;;;;;cAea,WAAA,SAAoB,WAAA;cACnB,OAAA;AAAA;;;;AA2Bd;;;;cAda,oBAAA,SAA6B,WAAA;EAAA,WAAA,CAAA;AAAA;;;;AA0C1C;;;;cA5Ba,yBAAA,SAAkC,WAAA;EAAA,WAAA,CAAA;AAAA;;ACa/C;;;;;;cDCa,yBAAA,SAAkC,WAAA;EAAA,WAAA,CAAA;AAAA;;ACkB/C;;;;;AAyDA;cD7Da,kBAAA,SAA2B,WAAA;EAAA,WAAA,CAAA;AAAA;;;;;;;;AA1CxC;;;;;AAcA;;;;;AAcA;;;;;AAcA;;;;;;iBCfgB,uBAAA,CAAwB,aAAA,EAAe,IAAA,EAAM,UAAA,WAAqB,QAAA;;AAAlF;;;;;;;;;;AAmBA;iBAAgB,mBAAA,CAAoB,QAAA,EAAU,QAAA;;;;AAyD9C;;;;;;;;;;iBAAgB,oBAAA,CAAqB,QAAA,EAAU,QAAA,GAAW,IAAA;;;;;;;ADvG1D;;;;;AAcA;;;;;AAcA;;;;;AAcA;;;;;;;;ACfA;;;;;;;;;;AAmBA;;;cCjBa,QAAA,YAAoB,OAAA;EAAA,iBACd,GAAA;EAAA,QACT,IAAA;EAAA,QACA,YAAA;;;;UAKD,WAAA,CAAA;EDkEiD;;;;;;AC1E1D;ED0E0D,OCrD3C,MAAA,CAAO,UAAA,WAAqB,OAAA,CAAQ,QAAA;;;;;;;;EAcjD,gBAAA,CAAiB,KAAA;EAoFkD;;;;;;;EAxEnE,cAAA,CAAe,GAAA;EA9CE;;;;;;;EAAA,QA0DT,SAAA;EAxBR;;;;;EAkCM,GAAA,CACJ,IAAA,EAAM,IAAA,EACN,QAAA,EAAU,QAAA,EACV,UAAA,WACA,OAAA,aACC,OAAA;EAJK;;;;;EAiDF,GAAA,CAAI,IAAA,EAAM,IAAA,EAAM,cAAA,WAAyB,OAAA,aAAoB,OAAA,CAAQ,QAAA;EA7CxE;;;;;EA4FG,MAAA,CAAO,IAAA,EAAM,IAAA,GAAO,OAAA;EA/CyC;;;EAuD7D,OAAA,CAAA,GAAW,OAAA;AAAA"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { r as HubertError, t as KvStore } from "./kv-store-ww-AUyLd.cjs";
|
|
2
|
+
import { ARID } from "@bcts/components";
|
|
3
|
+
import { Envelope } from "@bcts/envelope";
|
|
4
|
+
import { KuboRPCClient } from "kubo-rpc-client";
|
|
5
|
+
|
|
6
|
+
//#region src/ipfs/error.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Base class for IPFS-specific errors.
|
|
9
|
+
*
|
|
10
|
+
* @category IPFS
|
|
11
|
+
*/
|
|
12
|
+
declare class IpfsError extends HubertError {
|
|
13
|
+
constructor(message: string);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Envelope size exceeds practical limit.
|
|
17
|
+
*
|
|
18
|
+
* Port of `Error::EnvelopeTooLarge { size }` from ipfs/error.rs line 5.
|
|
19
|
+
*
|
|
20
|
+
* @category IPFS
|
|
21
|
+
*/
|
|
22
|
+
declare class EnvelopeTooLargeError extends IpfsError {
|
|
23
|
+
readonly size: number;
|
|
24
|
+
constructor(size: number);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* IPFS daemon error.
|
|
28
|
+
*
|
|
29
|
+
* Port of `Error::DaemonError` from ipfs/error.rs line 8.
|
|
30
|
+
*
|
|
31
|
+
* @category IPFS
|
|
32
|
+
*/
|
|
33
|
+
declare class IpfsDaemonError extends IpfsError {
|
|
34
|
+
constructor(message: string);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Operation timed out.
|
|
38
|
+
*
|
|
39
|
+
* Port of `Error::Timeout` from ipfs/error.rs line 11.
|
|
40
|
+
*
|
|
41
|
+
* @category IPFS
|
|
42
|
+
*/
|
|
43
|
+
declare class IpfsTimeoutError extends IpfsError {
|
|
44
|
+
constructor();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Unexpected IPNS path format.
|
|
48
|
+
*
|
|
49
|
+
* Port of `Error::UnexpectedIpnsPathFormat` from ipfs/error.rs line 14.
|
|
50
|
+
*
|
|
51
|
+
* @category IPFS
|
|
52
|
+
*/
|
|
53
|
+
declare class UnexpectedIpnsPathFormatError extends IpfsError {
|
|
54
|
+
readonly path: string;
|
|
55
|
+
constructor(path: string);
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/ipfs/value.d.ts
|
|
59
|
+
/**
|
|
60
|
+
* Add (upload) bytes to IPFS and return the CID.
|
|
61
|
+
*
|
|
62
|
+
* Port of `add_bytes()` from ipfs/value.rs lines 9-15.
|
|
63
|
+
*
|
|
64
|
+
* @param client - Kubo RPC client
|
|
65
|
+
* @param bytes - Data to add
|
|
66
|
+
* @returns CID of the added content
|
|
67
|
+
*
|
|
68
|
+
* @category IPFS
|
|
69
|
+
*/
|
|
70
|
+
declare function addBytes(client: KuboRPCClient, bytes: Uint8Array): Promise<string>;
|
|
71
|
+
/**
|
|
72
|
+
* Cat (download) bytes from IPFS by CID.
|
|
73
|
+
*
|
|
74
|
+
* Port of `cat_bytes()` from ipfs/value.rs lines 18-28.
|
|
75
|
+
*
|
|
76
|
+
* @param client - Kubo RPC client
|
|
77
|
+
* @param cid - Content identifier
|
|
78
|
+
* @returns Content bytes
|
|
79
|
+
*
|
|
80
|
+
* @category IPFS
|
|
81
|
+
*/
|
|
82
|
+
declare function catBytes(client: KuboRPCClient, cid: string): Promise<Uint8Array>;
|
|
83
|
+
/**
|
|
84
|
+
* Pin a CID to ensure it persists in local IPFS storage.
|
|
85
|
+
*
|
|
86
|
+
* Port of `pin_cid()` from ipfs/value.rs lines 31-38.
|
|
87
|
+
*
|
|
88
|
+
* @param client - Kubo RPC client
|
|
89
|
+
* @param cid - Content identifier to pin
|
|
90
|
+
* @param recursive - Whether to recursively pin linked content
|
|
91
|
+
*
|
|
92
|
+
* @category IPFS
|
|
93
|
+
*/
|
|
94
|
+
declare function pinCid(client: KuboRPCClient, cid: string, recursive: boolean): Promise<void>;
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/ipfs/kv.d.ts
|
|
97
|
+
/**
|
|
98
|
+
* IPFS-backed key-value store using IPNS for ARID-based addressing.
|
|
99
|
+
*
|
|
100
|
+
* This implementation uses:
|
|
101
|
+
* - ARID → IPNS key name derivation (deterministic)
|
|
102
|
+
* - IPFS content addressing (CID) for immutable storage
|
|
103
|
+
* - IPNS for publish-once mutable names
|
|
104
|
+
* - Write-once semantics (publish fails if name already exists)
|
|
105
|
+
*
|
|
106
|
+
* Port of `struct IpfsKv` from ipfs/kv.rs lines 54-60.
|
|
107
|
+
*
|
|
108
|
+
* # Requirements
|
|
109
|
+
*
|
|
110
|
+
* Requires a running Kubo daemon (or compatible IPFS node) with RPC API
|
|
111
|
+
* available at the configured endpoint (default: http://127.0.0.1:5001).
|
|
112
|
+
*
|
|
113
|
+
* @category IPFS Backend
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* const store = new IpfsKv("http://127.0.0.1:5001");
|
|
118
|
+
* const arid = ARID.new();
|
|
119
|
+
* const envelope = Envelope.new("Hello, IPFS!");
|
|
120
|
+
*
|
|
121
|
+
* // Put envelope (write-once)
|
|
122
|
+
* await store.put(arid, envelope);
|
|
123
|
+
*
|
|
124
|
+
* // Get envelope with verbose logging
|
|
125
|
+
* const retrieved = await store.get(arid, undefined, true);
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
declare class IpfsKv implements KvStore {
|
|
129
|
+
private readonly client;
|
|
130
|
+
private readonly keyCache;
|
|
131
|
+
private maxEnvelopeSize;
|
|
132
|
+
private resolveTimeoutMs;
|
|
133
|
+
private pinContent;
|
|
134
|
+
/**
|
|
135
|
+
* Create a new IPFS KV store with default settings.
|
|
136
|
+
*
|
|
137
|
+
* Port of `IpfsKv::new()` from ipfs/kv.rs lines 73-81.
|
|
138
|
+
*
|
|
139
|
+
* @param rpcUrl - IPFS RPC endpoint (e.g., "http://127.0.0.1:5001")
|
|
140
|
+
*/
|
|
141
|
+
constructor(rpcUrl: string);
|
|
142
|
+
/**
|
|
143
|
+
* Set the maximum envelope size (default: 10 MB).
|
|
144
|
+
*
|
|
145
|
+
* Port of `IpfsKv::with_max_size()` from ipfs/kv.rs lines 84-87.
|
|
146
|
+
*/
|
|
147
|
+
withMaxSize(size: number): this;
|
|
148
|
+
/**
|
|
149
|
+
* Set the IPNS resolve timeout (default: 30 seconds).
|
|
150
|
+
*
|
|
151
|
+
* Port of `IpfsKv::with_resolve_timeout()` from ipfs/kv.rs lines 90-93.
|
|
152
|
+
*
|
|
153
|
+
* @param timeoutMs - Timeout in milliseconds
|
|
154
|
+
*/
|
|
155
|
+
withResolveTimeout(timeoutMs: number): this;
|
|
156
|
+
/**
|
|
157
|
+
* Set whether to pin content (default: false).
|
|
158
|
+
*
|
|
159
|
+
* Port of `IpfsKv::with_pin_content()` from ipfs/kv.rs lines 96-99.
|
|
160
|
+
*/
|
|
161
|
+
withPinContent(pin: boolean): this;
|
|
162
|
+
/**
|
|
163
|
+
* Get or create an IPNS key for the given ARID.
|
|
164
|
+
*
|
|
165
|
+
* Port of `IpfsKv::get_or_create_key()` from ipfs/kv.rs lines 102-142.
|
|
166
|
+
*
|
|
167
|
+
* @internal
|
|
168
|
+
*/
|
|
169
|
+
private getOrCreateKey;
|
|
170
|
+
/**
|
|
171
|
+
* Check if an IPNS name is already published.
|
|
172
|
+
*
|
|
173
|
+
* Port of `IpfsKv::is_published()` from ipfs/kv.rs lines 145-161.
|
|
174
|
+
*
|
|
175
|
+
* @internal
|
|
176
|
+
*/
|
|
177
|
+
private isPublished;
|
|
178
|
+
/**
|
|
179
|
+
* Publish a CID to an IPNS name (write-once).
|
|
180
|
+
*
|
|
181
|
+
* Port of `IpfsKv::publish_once()` from ipfs/kv.rs lines 164-204.
|
|
182
|
+
*
|
|
183
|
+
* @internal
|
|
184
|
+
*/
|
|
185
|
+
private publishOnce;
|
|
186
|
+
/**
|
|
187
|
+
* Resolve an IPNS name to a CID with polling and custom timeout.
|
|
188
|
+
*
|
|
189
|
+
* Port of `IpfsKv::resolve_with_retry_timeout()` from ipfs/kv.rs lines 207-258.
|
|
190
|
+
*
|
|
191
|
+
* @internal
|
|
192
|
+
*/
|
|
193
|
+
private resolveWithRetryTimeout;
|
|
194
|
+
/**
|
|
195
|
+
* Store an envelope at the given ARID.
|
|
196
|
+
*
|
|
197
|
+
* Port of `KvStore::put()` implementation from ipfs/kv.rs lines 289-367.
|
|
198
|
+
*/
|
|
199
|
+
put(arid: ARID, envelope: Envelope, ttlSeconds?: number, verbose?: boolean): Promise<string>;
|
|
200
|
+
/**
|
|
201
|
+
* Retrieve an envelope for the given ARID.
|
|
202
|
+
*
|
|
203
|
+
* Port of `KvStore::get()` implementation from ipfs/kv.rs lines 370-450.
|
|
204
|
+
*/
|
|
205
|
+
get(arid: ARID, timeoutSeconds?: number, verbose?: boolean): Promise<Envelope | null>;
|
|
206
|
+
/**
|
|
207
|
+
* Check if an envelope exists at the given ARID.
|
|
208
|
+
*
|
|
209
|
+
* Port of `KvStore::exists()` implementation from ipfs/kv.rs lines 453-481.
|
|
210
|
+
*/
|
|
211
|
+
exists(arid: ARID): Promise<boolean>;
|
|
212
|
+
}
|
|
213
|
+
//#endregion
|
|
214
|
+
export { EnvelopeTooLargeError as a, IpfsTimeoutError as c, pinCid as i, UnexpectedIpnsPathFormatError as l, addBytes as n, IpfsDaemonError as o, catBytes as r, IpfsError as s, IpfsKv as t };
|
|
215
|
+
//# sourceMappingURL=index-DEr4SR1J.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-DEr4SR1J.d.cts","names":[],"sources":["../src/ipfs/error.ts","../src/ipfs/value.ts","../src/ipfs/kv.ts"],"mappings":";;;;;;;;;;;cAea,SAAA,SAAkB,WAAA;cACjB,OAAA;AAAA;;;;;;;;cAaD,qBAAA,SAA8B,SAAA;EAAA,SAChC,IAAA;cAEG,IAAA;AAAA;;;;;;;;cAcD,eAAA,SAAwB,SAAA;cACvB,OAAA;AAAA;;;AA2Bd;;;;;cAda,gBAAA,SAAyB,SAAA;EAAA,WAAA,CAAA;AAAA;;;;;;ACrCtC;;cDmDa,6BAAA,SAAsC,SAAA;EAAA,SACxC,IAAA;cAEG,IAAA;AAAA;;;;;;;;;;AAhDd;;;;iBCNsB,QAAA,CAAS,MAAA,EAAQ,aAAA,EAAe,KAAA,EAAO,UAAA,GAAa,OAAA;;;;;;ADuB1E;;;;;;iBCHsB,QAAA,CAAS,MAAA,EAAQ,aAAA,EAAe,GAAA,WAAc,OAAA,CAAQ,UAAA;;;ADiB5E;;;;;AAcA;;;;iBCAsB,MAAA,CACpB,MAAA,EAAQ,aAAA,EACR,GAAA,UACA,SAAA,YACC,OAAA;;;;;;;;ADjDH;;;;;;;;;;AAiBA;;;;;;;;;AAcA;;;;;AAcA;;cEVa,MAAA,YAAkB,OAAA;EAAA,iBACZ,MAAA;EAAA,iBACA,QAAA;EAAA,QACT,eAAA;EAAA,QACA,gBAAA;EAAA,QACA,UAAA;EFQgB;;;;;ACtD1B;;cCuDc,MAAA;EDvDyB;;;;;ECoErC,WAAA,CAAY,IAAA;EDpEiB;;;;;;AAoB/B;EC4DE,kBAAA,CAAmB,SAAA;;;;;;EAUnB,cAAA,CAAe,GAAA;EDtEsB;;;;;;;EAAA,QCkFvB,cAAA;EDnDY;;;;;;;EAAA,QCwFZ,WAAA;EDpFN;;;;;ACdV;;EDcU,QCiHM,WAAA;EAqGN;;;;;;;EAAA,QAvDM,uBAAA;EA7Ke;;;;;EAmOvB,GAAA,CACJ,IAAA,EAAM,IAAA,EACN,QAAA,EAAU,QAAA,EACV,UAAA,WACA,OAAA,aACC,OAAA;EArOK;;;;;EAySF,GAAA,CAAI,IAAA,EAAM,IAAA,EAAM,cAAA,WAAyB,OAAA,aAAoB,OAAA,CAAQ,QAAA;EAjR/D;;;;;EAyWN,MAAA,CAAO,IAAA,EAAM,IAAA,GAAO,OAAA;AAAA"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { r as HubertError, t as KvStore } from "./kv-store-DmngWWuw.mjs";
|
|
2
|
+
import { ARID } from "@bcts/components";
|
|
3
|
+
import { Envelope } from "@bcts/envelope";
|
|
4
|
+
|
|
5
|
+
//#region src/hybrid/error.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Base class for Hybrid-specific errors.
|
|
8
|
+
*
|
|
9
|
+
* @category Hybrid
|
|
10
|
+
*/
|
|
11
|
+
declare class HybridError extends HubertError {
|
|
12
|
+
constructor(message: string);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Referenced IPFS content not found.
|
|
16
|
+
*
|
|
17
|
+
* Port of `Error::ContentNotFound` from hybrid/error.rs line 4-5.
|
|
18
|
+
*
|
|
19
|
+
* @category Hybrid
|
|
20
|
+
*/
|
|
21
|
+
declare class ContentNotFoundError extends HybridError {
|
|
22
|
+
constructor();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Not a reference envelope.
|
|
26
|
+
*
|
|
27
|
+
* Port of `Error::NotReferenceEnvelope` from hybrid/error.rs line 7-8.
|
|
28
|
+
*
|
|
29
|
+
* @category Hybrid
|
|
30
|
+
*/
|
|
31
|
+
declare class NotReferenceEnvelopeError extends HybridError {
|
|
32
|
+
constructor();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Invalid ARID in reference envelope.
|
|
36
|
+
*
|
|
37
|
+
* Port of `Error::InvalidReferenceArid` from hybrid/error.rs line 10-11.
|
|
38
|
+
*
|
|
39
|
+
* @category Hybrid
|
|
40
|
+
*/
|
|
41
|
+
declare class InvalidReferenceAridError extends HybridError {
|
|
42
|
+
constructor();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* No id assertion found in reference envelope.
|
|
46
|
+
*
|
|
47
|
+
* Port of `Error::NoIdAssertion` from hybrid/error.rs line 13-14.
|
|
48
|
+
*
|
|
49
|
+
* @category Hybrid
|
|
50
|
+
*/
|
|
51
|
+
declare class NoIdAssertionError extends HybridError {
|
|
52
|
+
constructor();
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/hybrid/reference.d.ts
|
|
56
|
+
/**
|
|
57
|
+
* Creates a reference envelope that points to content stored in IPFS.
|
|
58
|
+
*
|
|
59
|
+
* Reference envelopes are small envelopes stored in the DHT that contain
|
|
60
|
+
* a pointer to the actual envelope stored in IPFS. This allows the hybrid
|
|
61
|
+
* storage layer to transparently handle large envelopes that exceed the
|
|
62
|
+
* DHT size limit.
|
|
63
|
+
*
|
|
64
|
+
* Port of `create_reference_envelope()` from hybrid/reference.rs lines 31-39.
|
|
65
|
+
*
|
|
66
|
+
* # Format
|
|
67
|
+
*
|
|
68
|
+
* ```text
|
|
69
|
+
* '' [
|
|
70
|
+
* 'dereferenceVia': "ipfs",
|
|
71
|
+
* 'id': <ARID>,
|
|
72
|
+
* "size": <number>
|
|
73
|
+
* ]
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @param referenceArid - The ARID used to look up the actual envelope in IPFS
|
|
77
|
+
* @param actualSize - Size of the actual envelope in bytes (for diagnostics)
|
|
78
|
+
* @returns A reference envelope that can be stored in the DHT
|
|
79
|
+
*
|
|
80
|
+
* @category Hybrid
|
|
81
|
+
*/
|
|
82
|
+
declare function createReferenceEnvelope(referenceArid: ARID, actualSize: number): Envelope;
|
|
83
|
+
/**
|
|
84
|
+
* Checks if an envelope is a reference envelope.
|
|
85
|
+
*
|
|
86
|
+
* A reference envelope contains `dereferenceVia: "ipfs"` and an `id` assertion.
|
|
87
|
+
*
|
|
88
|
+
* Port of `is_reference_envelope()` from hybrid/reference.rs lines 53-91.
|
|
89
|
+
*
|
|
90
|
+
* @param envelope - The envelope to check
|
|
91
|
+
* @returns `true` if this is a reference envelope, `false` otherwise
|
|
92
|
+
*
|
|
93
|
+
* @category Hybrid
|
|
94
|
+
*/
|
|
95
|
+
declare function isReferenceEnvelope(envelope: Envelope): boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Extracts the reference ARID from a reference envelope.
|
|
98
|
+
*
|
|
99
|
+
* Port of `extract_reference_arid()` from hybrid/reference.rs lines 104-129.
|
|
100
|
+
*
|
|
101
|
+
* @param envelope - The reference envelope
|
|
102
|
+
* @returns The reference ARID
|
|
103
|
+
* @throws {NotReferenceEnvelopeError} If the envelope is not a reference envelope
|
|
104
|
+
* @throws {InvalidReferenceAridError} If the ARID cannot be extracted
|
|
105
|
+
* @throws {NoIdAssertionError} If no id assertion is found
|
|
106
|
+
*
|
|
107
|
+
* @category Hybrid
|
|
108
|
+
*/
|
|
109
|
+
declare function extractReferenceArid(envelope: Envelope): ARID;
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/hybrid/kv.d.ts
|
|
112
|
+
/**
|
|
113
|
+
* Hybrid storage layer combining Mainline DHT and IPFS.
|
|
114
|
+
*
|
|
115
|
+
* Automatically optimizes storage based on envelope size:
|
|
116
|
+
* - **Small envelopes (≤1000 bytes)**: Stored directly in DHT
|
|
117
|
+
* - **Large envelopes (>1000 bytes)**: Reference in DHT → actual envelope in IPFS
|
|
118
|
+
*
|
|
119
|
+
* This provides the best of both worlds:
|
|
120
|
+
* - Fast lookups for small messages via DHT
|
|
121
|
+
* - Large capacity for big messages via IPFS
|
|
122
|
+
* - Transparent indirection handled automatically
|
|
123
|
+
*
|
|
124
|
+
* Port of `struct HybridKv` from hybrid/kv.rs lines 59-63.
|
|
125
|
+
*
|
|
126
|
+
* # Requirements
|
|
127
|
+
*
|
|
128
|
+
* - No external daemon for DHT (embedded client)
|
|
129
|
+
* - Requires Kubo daemon for IPFS (http://127.0.0.1:5001)
|
|
130
|
+
*
|
|
131
|
+
* @category Hybrid Backend
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const store = await HybridKv.create("http://127.0.0.1:5001");
|
|
136
|
+
*
|
|
137
|
+
* // Small envelope → DHT only
|
|
138
|
+
* const arid1 = ARID.new();
|
|
139
|
+
* const small = Envelope.new("Small message");
|
|
140
|
+
* await store.put(arid1, small);
|
|
141
|
+
*
|
|
142
|
+
* // Large envelope → DHT reference + IPFS
|
|
143
|
+
* const arid2 = ARID.new();
|
|
144
|
+
* const large = Envelope.new("x".repeat(2000));
|
|
145
|
+
* await store.put(arid2, large);
|
|
146
|
+
*
|
|
147
|
+
* // Get works the same for both
|
|
148
|
+
* const retrieved1 = await store.get(arid1);
|
|
149
|
+
* const retrieved2 = await store.get(arid2);
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
declare class HybridKv implements KvStore {
|
|
153
|
+
private readonly dht;
|
|
154
|
+
private ipfs;
|
|
155
|
+
private dhtSizeLimit;
|
|
156
|
+
/**
|
|
157
|
+
* Private constructor - use `create()` factory method.
|
|
158
|
+
*/
|
|
159
|
+
private constructor();
|
|
160
|
+
/**
|
|
161
|
+
* Create a new Hybrid KV store with default settings.
|
|
162
|
+
*
|
|
163
|
+
* Port of `HybridKv::new()` from hybrid/kv.rs lines 75-84.
|
|
164
|
+
*
|
|
165
|
+
* @param ipfsRpcUrl - IPFS RPC endpoint (e.g., "http://127.0.0.1:5001")
|
|
166
|
+
*/
|
|
167
|
+
static create(ipfsRpcUrl: string): Promise<HybridKv>;
|
|
168
|
+
/**
|
|
169
|
+
* Set custom DHT size limit (default: 1000 bytes).
|
|
170
|
+
*
|
|
171
|
+
* Envelopes larger than this will use IPFS indirection.
|
|
172
|
+
*
|
|
173
|
+
* Port of `HybridKv::with_dht_size_limit()` from hybrid/kv.rs lines 89-92.
|
|
174
|
+
*/
|
|
175
|
+
withDhtSizeLimit(limit: number): this;
|
|
176
|
+
/**
|
|
177
|
+
* Set whether to pin content in IPFS (default: false).
|
|
178
|
+
*
|
|
179
|
+
* Only affects envelopes stored in IPFS (when larger than DHT limit).
|
|
180
|
+
*
|
|
181
|
+
* Port of `HybridKv::with_pin_content()` from hybrid/kv.rs lines 97-100.
|
|
182
|
+
*/
|
|
183
|
+
withPinContent(pin: boolean): this;
|
|
184
|
+
/**
|
|
185
|
+
* Check if an envelope fits in the DHT.
|
|
186
|
+
*
|
|
187
|
+
* Port of `HybridKv::fits_in_dht()` from hybrid/kv.rs lines 103-106.
|
|
188
|
+
*
|
|
189
|
+
* @internal
|
|
190
|
+
*/
|
|
191
|
+
private fitsInDht;
|
|
192
|
+
/**
|
|
193
|
+
* Store an envelope at the given ARID.
|
|
194
|
+
*
|
|
195
|
+
* Port of `KvStore::put()` implementation from hybrid/kv.rs lines 109-168.
|
|
196
|
+
*/
|
|
197
|
+
put(arid: ARID, envelope: Envelope, ttlSeconds?: number, verbose?: boolean): Promise<string>;
|
|
198
|
+
/**
|
|
199
|
+
* Retrieve an envelope for the given ARID.
|
|
200
|
+
*
|
|
201
|
+
* Port of `KvStore::get()` implementation from hybrid/kv.rs lines 171-230.
|
|
202
|
+
*/
|
|
203
|
+
get(arid: ARID, timeoutSeconds?: number, verbose?: boolean): Promise<Envelope | null>;
|
|
204
|
+
/**
|
|
205
|
+
* Check if an envelope exists at the given ARID.
|
|
206
|
+
*
|
|
207
|
+
* Port of `KvStore::exists()` implementation from hybrid/kv.rs lines 254-257.
|
|
208
|
+
*/
|
|
209
|
+
exists(arid: ARID): Promise<boolean>;
|
|
210
|
+
/**
|
|
211
|
+
* Destroy the hybrid store and release resources.
|
|
212
|
+
*/
|
|
213
|
+
destroy(): Promise<void>;
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
export { ContentNotFoundError as a, NoIdAssertionError as c, isReferenceEnvelope as i, NotReferenceEnvelopeError as l, createReferenceEnvelope as n, HybridError as o, extractReferenceArid as r, InvalidReferenceAridError as s, HybridKv as t };
|
|
217
|
+
//# sourceMappingURL=index-T1LHanIb.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-T1LHanIb.d.mts","names":[],"sources":["../src/hybrid/error.ts","../src/hybrid/reference.ts","../src/hybrid/kv.ts"],"mappings":";;;;;;;;;;cAea,WAAA,SAAoB,WAAA;cACnB,OAAA;AAAA;;;;AA2Bd;;;;cAda,oBAAA,SAA6B,WAAA;EAAA,WAAA,CAAA;AAAA;;;;AA0C1C;;;;cA5Ba,yBAAA,SAAkC,WAAA;EAAA,WAAA,CAAA;AAAA;;ACa/C;;;;;;cDCa,yBAAA,SAAkC,WAAA;EAAA,WAAA,CAAA;AAAA;;ACkB/C;;;;;AAyDA;cD7Da,kBAAA,SAA2B,WAAA;EAAA,WAAA,CAAA;AAAA;;;;;;;;AA1CxC;;;;;AAcA;;;;;AAcA;;;;;AAcA;;;;;;iBCfgB,uBAAA,CAAwB,aAAA,EAAe,IAAA,EAAM,UAAA,WAAqB,QAAA;;AAAlF;;;;;;;;;;AAmBA;iBAAgB,mBAAA,CAAoB,QAAA,EAAU,QAAA;;;;AAyD9C;;;;;;;;;;iBAAgB,oBAAA,CAAqB,QAAA,EAAU,QAAA,GAAW,IAAA;;;;;;;ADvG1D;;;;;AAcA;;;;;AAcA;;;;;AAcA;;;;;;;;ACfA;;;;;;;;;;AAmBA;;;cCjBa,QAAA,YAAoB,OAAA;EAAA,iBACd,GAAA;EAAA,QACT,IAAA;EAAA,QACA,YAAA;;;;UAKD,WAAA,CAAA;EDkEiD;;;;;;AC1E1D;ED0E0D,OCrD3C,MAAA,CAAO,UAAA,WAAqB,OAAA,CAAQ,QAAA;;;;;;;;EAcjD,gBAAA,CAAiB,KAAA;EAoFkD;;;;;;;EAxEnE,cAAA,CAAe,GAAA;EA9CE;;;;;;;EAAA,QA0DT,SAAA;EAxBR;;;;;EAkCM,GAAA,CACJ,IAAA,EAAM,IAAA,EACN,QAAA,EAAU,QAAA,EACV,UAAA,WACA,OAAA,aACC,OAAA;EAJK;;;;;EAiDF,GAAA,CAAI,IAAA,EAAM,IAAA,EAAM,cAAA,WAAyB,OAAA,aAAoB,OAAA,CAAQ,QAAA;EA7CxE;;;;;EA4FG,MAAA,CAAO,IAAA,EAAM,IAAA,GAAO,OAAA;EA/CyC;;;EAuD7D,OAAA,CAAA,GAAW,OAAA;AAAA"}
|