@mikeargento/bitgraph 1.10.1 → 1.11.0
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/export.d.ts +88 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +298 -0
- package/dist/export.js.map +1 -0
- package/dist/fuse.d.ts +136 -2
- package/dist/fuse.d.ts.map +1 -1
- package/dist/fuse.js +349 -2
- package/dist/fuse.js.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/recovery-write.d.ts +58 -0
- package/dist/recovery-write.d.ts.map +1 -0
- package/dist/recovery-write.js +265 -0
- package/dist/recovery-write.js.map +1 -0
- package/dist/recovery.d.ts +490 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +1124 -0
- package/dist/recovery.js.map +1 -0
- package/package.json +2 -2
- package/src/export.ts +365 -0
- package/src/fuse.ts +470 -3
- package/src/index.ts +28 -3
- package/src/recovery-write.ts +334 -0
- package/src/recovery.ts +1261 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type FetchLike, type RecoveryTreeInput } from "./recovery.js";
|
|
2
|
+
export interface RecoveryWriteInput extends RecoveryTreeInput {
|
|
3
|
+
/** A file name per leaf, tree order. Advisory, sealed with each entry. */
|
|
4
|
+
names?: ReadonlyArray<string | null | undefined>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* What a writer keeps between runs: one progress byte per member
|
|
8
|
+
* (RECOVERY_SIDE_BITS) and the salts chosen for entries whose deterministic
|
|
9
|
+
* key was held, base64 by recoverySaltKey. The same shape the browser's
|
|
10
|
+
* queue saves for its jobs.
|
|
11
|
+
*/
|
|
12
|
+
export interface RecoveryWriteState {
|
|
13
|
+
progress: Uint8Array;
|
|
14
|
+
salts: Record<string, string>;
|
|
15
|
+
}
|
|
16
|
+
export interface RecoveryWriteOptions {
|
|
17
|
+
/** Default https://bitgraph.ing. */
|
|
18
|
+
baseUrl?: string;
|
|
19
|
+
fetch?: FetchLike;
|
|
20
|
+
/** Rounds of retry for conflicts, errors and transient failures. Default 3. */
|
|
21
|
+
retries?: number;
|
|
22
|
+
/** Milliseconds before the first retry; doubles each round. Default 500. */
|
|
23
|
+
backoffMs?: number;
|
|
24
|
+
/** Milliseconds one request may take. Default 60,000. */
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
/** Milliseconds the whole call may take; what is not written by then is reported pending. Default: no budget. */
|
|
27
|
+
budgetMs?: number;
|
|
28
|
+
/** An earlier run's state to resume from. */
|
|
29
|
+
state?: RecoveryWriteState;
|
|
30
|
+
/** Hears the state whenever it is worth keeping: a salt before its write, progress after every batch. */
|
|
31
|
+
onState?: (state: RecoveryWriteState) => void | Promise<void>;
|
|
32
|
+
/** False: a held deterministic key leaves the side blocked instead of trying its salted name. Default true. */
|
|
33
|
+
saltedFallback?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface RecoveryWriteResult {
|
|
36
|
+
/** Entries this tree needs: two per placed member, one per as-is member. */
|
|
37
|
+
entries: number;
|
|
38
|
+
/** Kept when this call ended: created now, or already stored as this member, in this run or one before it. */
|
|
39
|
+
kept: number;
|
|
40
|
+
/** Created in this call. */
|
|
41
|
+
written: number;
|
|
42
|
+
/** Already stored, and opened to hold this same member, in this call. */
|
|
43
|
+
alreadyThere: number;
|
|
44
|
+
/** Of `kept`, those under a salted name: their deterministic key was held by another member's entry. */
|
|
45
|
+
salted: number;
|
|
46
|
+
/** Both names held by other entries (see SPEC section 13, squatting). */
|
|
47
|
+
blocked: number;
|
|
48
|
+
/** Not written: the site refused writes, the attempts or the budget ran out. */
|
|
49
|
+
pending: number;
|
|
50
|
+
/** Why entries are pending, in words, when any are. */
|
|
51
|
+
reason: string | null;
|
|
52
|
+
/** The state to resume from when `pending` is not zero. */
|
|
53
|
+
state: RecoveryWriteState;
|
|
54
|
+
/** Every entry is kept or blocked: nothing left to write. */
|
|
55
|
+
done: boolean;
|
|
56
|
+
}
|
|
57
|
+
export declare function writeRecoveryEntries(input: RecoveryWriteInput, opts?: RecoveryWriteOptions): Promise<RecoveryWriteResult>;
|
|
58
|
+
//# sourceMappingURL=recovery-write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-write.d.ts","sourceRoot":"","sources":["../src/recovery-write.ts"],"names":[],"mappings":"AAkCA,OAAO,EAaL,KAAK,SAAS,EACd,KAAK,iBAAiB,EAEvB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,0EAA0E;IAC1E,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CAClD;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,UAAU,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iHAAiH;IACjH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,yGAAyG;IACzG,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,+GAA+G;IAC/G,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,8GAA8G;IAC9G,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,YAAY,EAAE,MAAM,CAAC;IACrB,wGAAwG;IACxG,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,2DAA2D;IAC3D,KAAK,EAAE,kBAAkB,CAAC;IAC1B,6DAA6D;IAC7D,IAAI,EAAE,OAAO,CAAC;CACf;AAsBD,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,kBAAkB,EAAE,IAAI,GAAE,oBAAyB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA0MnI"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
// Copyright (c) 2024-2026 Argento Computing Inc. Licensed under the MIT License. See LICENSE.
|
|
2
|
+
/**
|
|
3
|
+
* Writing a tree's recovery entries from outside the browser (2026-10-03).
|
|
4
|
+
*
|
|
5
|
+
* The drop box keeps its trees recoverable through a persistent queue
|
|
6
|
+
* (website/src/lib/recovery-queue.ts). The CLI, SDK and MCP make trees too,
|
|
7
|
+
* and a file they made should be found again the same way when someone drops
|
|
8
|
+
* it on bitgraph.ing. This posts the same sealed entries (recovery.ts, the
|
|
9
|
+
* Node twin of the site's module) to POST /api/recovery, after the proof is
|
|
10
|
+
* already in hand: it never stands between anyone and a proof.
|
|
11
|
+
*
|
|
12
|
+
* Every write is create-only. "created" counts as kept; "exists" counts
|
|
13
|
+
* only after the stored envelope is opened and holds this same member.
|
|
14
|
+
* A key that holds ANOTHER member's entry (SPEC section 13, squatting) is
|
|
15
|
+
* not the end of it: the same entry is written again under its salted name,
|
|
16
|
+
* with a fresh 32-byte salt sealed inside, and only a salted name that is
|
|
17
|
+
* held too leaves the side blocked. "conflict" and "error" are retried. A
|
|
18
|
+
* site that does not take recovery writes yet (503, or no route at all)
|
|
19
|
+
* leaves the entries pending, and the caller says so: the tree is exactly as
|
|
20
|
+
* made, it is just not recoverable from the file until its entries are
|
|
21
|
+
* written.
|
|
22
|
+
*
|
|
23
|
+
* STATE, FOR A WRITER THAT RESUMES. Progress is one byte per member
|
|
24
|
+
* (recovery.ts, RECOVERY_SIDE_BITS) plus the salts chosen so far, the same
|
|
25
|
+
* shape the browser's queue saves. A caller passes the state of an earlier
|
|
26
|
+
* run to pick up where it stopped, and `onState` hears every change worth
|
|
27
|
+
* keeping: a salt the moment it is chosen (BEFORE its write, so a retry lands
|
|
28
|
+
* on the same name) and progress after every batch. Entries are sealed a
|
|
29
|
+
* batch at a time, never all at once: a 100,000-file tree is 200,000
|
|
30
|
+
* envelopes, and they need not all be in memory together.
|
|
31
|
+
*/
|
|
32
|
+
import { base64ToBytes, bytesToBase64 } from "@mikeargento/bitgraph-verify";
|
|
33
|
+
import { MAX_BATCH_ENTRIES, RECOVERY_SIDE_BITS, existingEntryHoldsMember, findOwnRecoveryEntry, newRecoverySalt, recoverySaltKey, recoverySaltsFor, recoverySideResolved, recoverySideState, recoverySidesOf, recoveryTreeFrom, sealRecoveryMember, } from "./recovery.js";
|
|
34
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
35
|
+
function hostOf(base) {
|
|
36
|
+
try {
|
|
37
|
+
return new URL(base).host;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return base;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Base64 salts by recoverySaltKey, with the progress, as a fresh copy for a caller to keep. */
|
|
44
|
+
const snapshot = (progress, salts) => ({ progress: progress.slice(), salts: { ...salts } });
|
|
45
|
+
export async function writeRecoveryEntries(input, opts = {}) {
|
|
46
|
+
const tree = recoveryTreeFrom(input);
|
|
47
|
+
const f = opts.fetch ?? ((url, init) => fetch(url, init));
|
|
48
|
+
const base = opts.baseUrl ?? "https://bitgraph.ing";
|
|
49
|
+
const retries = opts.retries ?? 3;
|
|
50
|
+
const timeoutMs = opts.timeoutMs ?? 60_000;
|
|
51
|
+
const deadline = opts.budgetMs !== undefined ? Date.now() + opts.budgetMs : Infinity;
|
|
52
|
+
let waitMs = opts.backoffMs ?? 500;
|
|
53
|
+
const names = input.names;
|
|
54
|
+
const progress = new Uint8Array(tree.count);
|
|
55
|
+
if (opts.state?.progress !== undefined)
|
|
56
|
+
progress.set(opts.state.progress.subarray(0, tree.count));
|
|
57
|
+
const salts = { ...(opts.state?.salts ?? {}) };
|
|
58
|
+
let written = 0;
|
|
59
|
+
let alreadyThere = 0;
|
|
60
|
+
let reason = null;
|
|
61
|
+
// The site takes no writes, or the budget ran out: no more requests this call.
|
|
62
|
+
let stopped = false;
|
|
63
|
+
const keep = async () => {
|
|
64
|
+
if (opts.onState !== undefined)
|
|
65
|
+
await opts.onState(snapshot(progress, salts));
|
|
66
|
+
};
|
|
67
|
+
/** The pending sides of the members from `cursor.at` on, sealed, up to MAX_BATCH_ENTRIES entries. */
|
|
68
|
+
async function nextBatch(cursor) {
|
|
69
|
+
const out = [];
|
|
70
|
+
while (cursor.at < tree.count) {
|
|
71
|
+
const i = cursor.at;
|
|
72
|
+
const sides = recoverySidesOf(tree, i).filter((s) => !recoverySideResolved(progress[i], s));
|
|
73
|
+
if (sides.length > 0) {
|
|
74
|
+
if (out.length + sides.length > MAX_BATCH_ENTRIES)
|
|
75
|
+
break;
|
|
76
|
+
const { writes } = await sealRecoveryMember(tree, i, names?.[i] ?? null, sides, recoverySaltsFor(salts, i));
|
|
77
|
+
for (const w of writes)
|
|
78
|
+
out.push({ index: i, w });
|
|
79
|
+
}
|
|
80
|
+
cursor.at++;
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
/** What one operation may still take: its own limit, or what is left of the budget, whichever is less. Zero or less: the budget is spent. */
|
|
85
|
+
const remaining = () => Math.min(timeoutMs, deadline - Date.now());
|
|
86
|
+
/** POST one batch. The answers by key, or null when the request failed as a whole (the reason says how). */
|
|
87
|
+
async function post(batch) {
|
|
88
|
+
const allowed = remaining();
|
|
89
|
+
if (allowed <= 0) {
|
|
90
|
+
reason = "the time budget ran out";
|
|
91
|
+
stopped = true;
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
let res;
|
|
95
|
+
try {
|
|
96
|
+
res = await f(`${base}/api/recovery`, {
|
|
97
|
+
method: "POST",
|
|
98
|
+
headers: { "content-type": "application/json" },
|
|
99
|
+
body: JSON.stringify({ entries: batch.map((p) => ({ key: p.w.objectKey, envelope: bytesToBase64(p.w.envelope) })) }),
|
|
100
|
+
signal: AbortSignal.timeout(allowed),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
reason = `the site could not be reached (${e.message})`;
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
if (res.status === 503 || res.status === 404 || res.status === 405 || res.status === 501) {
|
|
108
|
+
// Writes off on the site (503), or a site without the route at all:
|
|
109
|
+
// nothing will land this run. Stop asking.
|
|
110
|
+
stopped = true;
|
|
111
|
+
reason = `${hostOf(base)} is not taking recovery writes yet; the tree is made, but these files cannot be found from the file alone until their entries are written`;
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
if (!res.ok) {
|
|
115
|
+
reason = `POST /api/recovery answered ${res.status}`;
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
let body;
|
|
119
|
+
try {
|
|
120
|
+
body = await res.json();
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
reason = "the site's answer was not JSON";
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const answers = new Map();
|
|
127
|
+
const list = body.results;
|
|
128
|
+
if (Array.isArray(list)) {
|
|
129
|
+
for (const r of list) {
|
|
130
|
+
if (typeof r.key === "string" && typeof r.status === "string")
|
|
131
|
+
answers.set(r.key, { status: r.status, ...(typeof r.envelope === "string" ? { envelope: r.envelope } : {}) });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return answers;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Apply one request's answers. A deterministic key held by another member
|
|
138
|
+
* gets a salt, kept first, and its salted write goes out at once; a salted
|
|
139
|
+
* name that is held too is blocked, so this recurses at most once.
|
|
140
|
+
*/
|
|
141
|
+
async function apply(batch, answers) {
|
|
142
|
+
const fallbacks = [];
|
|
143
|
+
for (const p of batch) {
|
|
144
|
+
const a = answers.get(p.w.objectKey);
|
|
145
|
+
const bits = RECOVERY_SIDE_BITS[p.w.side];
|
|
146
|
+
if (a?.status === "created") {
|
|
147
|
+
progress[p.index] |= bits.kept;
|
|
148
|
+
written++;
|
|
149
|
+
}
|
|
150
|
+
else if (a?.status === "exists" && a.envelope !== undefined) {
|
|
151
|
+
const stored = base64ToBytes(a.envelope);
|
|
152
|
+
if (stored !== null && (await existingEntryHoldsMember(p.w.digest, p.w.objectKey, stored, p.w.plaintext))) {
|
|
153
|
+
progress[p.index] |= bits.kept;
|
|
154
|
+
alreadyThere++;
|
|
155
|
+
}
|
|
156
|
+
else if (p.w.salted || opts.saltedFallback === false) {
|
|
157
|
+
progress[p.index] |= bits.blocked;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
fallbacks.push(p);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// "conflict", "error", or no answer: pending for the next round.
|
|
164
|
+
}
|
|
165
|
+
if (fallbacks.length === 0 || stopped)
|
|
166
|
+
return;
|
|
167
|
+
// Another member holds these keys. Before a fresh salt, the address is
|
|
168
|
+
// read: an entry of this member may already sit there under a salted name
|
|
169
|
+
// from an earlier run whose salt was not kept. Found, it counts and its
|
|
170
|
+
// salt is kept now; an address that cannot be read leaves the side
|
|
171
|
+
// pending (nothing is guessed, no second copy is written).
|
|
172
|
+
const fresh = [];
|
|
173
|
+
for (const p of fallbacks) {
|
|
174
|
+
const allowed = remaining();
|
|
175
|
+
if (allowed <= 0) {
|
|
176
|
+
reason = "the time budget ran out";
|
|
177
|
+
stopped = true;
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
let own;
|
|
181
|
+
try {
|
|
182
|
+
own = await findOwnRecoveryEntry(p.w.digest, p.w.plaintext, f, { baseUrl: base, timeoutMs: allowed });
|
|
183
|
+
}
|
|
184
|
+
catch (e) {
|
|
185
|
+
reason = `the address could not be read before a salted write (${e.message})`;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (own !== null) {
|
|
189
|
+
progress[p.index] |= RECOVERY_SIDE_BITS[p.w.side].kept;
|
|
190
|
+
alreadyThere++;
|
|
191
|
+
if (own.salt !== null)
|
|
192
|
+
salts[recoverySaltKey(p.index, p.w.side)] = bytesToBase64(own.salt);
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
fresh.push(p);
|
|
196
|
+
}
|
|
197
|
+
if (fresh.length === 0)
|
|
198
|
+
return;
|
|
199
|
+
for (const p of fresh)
|
|
200
|
+
salts[recoverySaltKey(p.index, p.w.side)] ??= bytesToBase64(newRecoverySalt());
|
|
201
|
+
await keep();
|
|
202
|
+
const resealed = [];
|
|
203
|
+
for (const p of fresh) {
|
|
204
|
+
const { writes } = await sealRecoveryMember(tree, p.index, names?.[p.index] ?? null, [p.w.side], recoverySaltsFor(salts, p.index));
|
|
205
|
+
for (const w of writes)
|
|
206
|
+
resealed.push({ index: p.index, w });
|
|
207
|
+
}
|
|
208
|
+
const again = await post(resealed);
|
|
209
|
+
if (again !== null)
|
|
210
|
+
await apply(resealed, again);
|
|
211
|
+
}
|
|
212
|
+
for (let round = 0; round <= retries && !stopped; round++) {
|
|
213
|
+
if (round > 0) {
|
|
214
|
+
if (Date.now() + waitMs > deadline) {
|
|
215
|
+
reason = "the time budget ran out";
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
await sleep(waitMs);
|
|
219
|
+
waitMs *= 2;
|
|
220
|
+
}
|
|
221
|
+
const cursor = { at: 0 };
|
|
222
|
+
let sentAny = false;
|
|
223
|
+
while (!stopped) {
|
|
224
|
+
if (Date.now() > deadline) {
|
|
225
|
+
reason = "the time budget ran out";
|
|
226
|
+
stopped = true;
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
const batch = await nextBatch(cursor);
|
|
230
|
+
if (batch.length === 0)
|
|
231
|
+
break;
|
|
232
|
+
sentAny = true;
|
|
233
|
+
const answers = await post(batch);
|
|
234
|
+
if (answers !== null)
|
|
235
|
+
await apply(batch, answers);
|
|
236
|
+
await keep();
|
|
237
|
+
}
|
|
238
|
+
if (!sentAny)
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
let entries = 0;
|
|
242
|
+
let kept = 0;
|
|
243
|
+
let salted = 0;
|
|
244
|
+
let blocked = 0;
|
|
245
|
+
let pending = 0;
|
|
246
|
+
for (let i = 0; i < tree.count; i++) {
|
|
247
|
+
for (const side of recoverySidesOf(tree, i)) {
|
|
248
|
+
entries++;
|
|
249
|
+
const state = recoverySideState(progress[i], side);
|
|
250
|
+
if (state === "kept") {
|
|
251
|
+
kept++;
|
|
252
|
+
if (salts[recoverySaltKey(i, side)] !== undefined)
|
|
253
|
+
salted++;
|
|
254
|
+
}
|
|
255
|
+
else if (state === "blocked")
|
|
256
|
+
blocked++;
|
|
257
|
+
else
|
|
258
|
+
pending++;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (pending > 0 && reason === null)
|
|
262
|
+
reason = "some entries were not written after every retry";
|
|
263
|
+
return { entries, kept, written, alreadyThere, salted, blocked, pending, reason: pending > 0 ? reason : null, state: snapshot(progress, salts), done: pending === 0 };
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=recovery-write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-write.js","sourceRoot":"","sources":["../src/recovery-write.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAE9F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,kBAAkB,GAInB,MAAM,eAAe,CAAC;AAoEvB,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAEpE,SAAS,MAAM,CAAC,IAAY;IAC1B,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,gGAAgG;AAChG,MAAM,QAAQ,GAAG,CAAC,QAAoB,EAAE,KAA6B,EAAsB,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,CAAC,CAAC;AAEpJ,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAyB,EAAE,OAA6B,EAAE;IACnG,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,CAAC,GAAc,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IACrE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,IAAI,sBAAsB,CAAC;IACpD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrF,IAAI,MAAM,GAAG,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC;IACnC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAE1B,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5C,IAAI,IAAI,CAAC,KAAK,EAAE,QAAQ,KAAK,SAAS;QAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAClG,MAAM,KAAK,GAA2B,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;IACvE,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,+EAA+E;IAC/E,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;QACrC,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAChF,CAAC,CAAC;IAEF,qGAAqG;IACrG,KAAK,UAAU,SAAS,CAAC,MAAsB;QAC7C,MAAM,GAAG,GAAc,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7F,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,IAAI,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,iBAAiB;oBAAE,MAAM;gBACzD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,KAAK,EAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC5G,KAAK,MAAM,CAAC,IAAI,MAAM;oBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,6IAA6I;IAC7I,MAAM,SAAS,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAE3E,4GAA4G;IAC5G,KAAK,UAAU,IAAI,CAAC,KAAgB;QAClC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;QAC5B,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;YACjB,MAAM,GAAG,yBAAyB,CAAC;YACnC,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,GAAa,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,CAAC,CAAC,GAAG,IAAI,eAAe,EAAE;gBACpC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBACpH,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;aACrC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,GAAG,kCAAmC,CAAW,CAAC,OAAO,GAAG,CAAC;YACnE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACzF,oEAAoE;YACpE,2CAA2C;YAC3C,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,2IAA2I,CAAC;YACpK,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,GAAG,+BAA+B,GAAG,CAAC,MAAM,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,gCAAgC,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC1C,MAAM,IAAI,GAAI,IAA8B,CAAC,OAAO,CAAC;QACrD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,KAAK,MAAM,CAAC,IAAI,IAAsE,EAAE,CAAC;gBACvF,IAAI,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;oBAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAC/K,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACH,KAAK,UAAU,KAAK,CAAC,KAAgB,EAAE,OAA4B;QACjE,MAAM,SAAS,GAAc,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACrC,MAAM,IAAI,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,CAAC,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC5B,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAE,IAAI,IAAI,CAAC,IAAI,CAAC;gBAChC,OAAO,EAAE,CAAC;YACZ,CAAC;iBAAM,IAAI,CAAC,EAAE,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC9D,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;gBACzC,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;oBAC1G,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAE,IAAI,IAAI,CAAC,IAAI,CAAC;oBAChC,YAAY,EAAE,CAAC;gBACjB,CAAC;qBAAM,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc,KAAK,KAAK,EAAE,CAAC;oBACvD,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAE,IAAI,IAAI,CAAC,OAAO,CAAC;gBACrC,CAAC;qBAAM,CAAC;oBACN,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;YACD,iEAAiE;QACnE,CAAC;QACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO;YAAE,OAAO;QAC9C,uEAAuE;QACvE,0EAA0E;QAC1E,wEAAwE;QACxE,mEAAmE;QACnE,2DAA2D;QAC3D,MAAM,KAAK,GAAc,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;YAC5B,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;gBACjB,MAAM,GAAG,yBAAyB,CAAC;gBACnC,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO;YACT,CAAC;YACD,IAAI,GAAqD,CAAC;YAC1D,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;YACxG,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,GAAG,wDAAyD,CAAW,CAAC,OAAO,GAAG,CAAC;gBACzF,SAAS;YACX,CAAC;YACD,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACjB,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAE,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;gBACxD,YAAY,EAAE,CAAC;gBACf,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI;oBAAE,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC3F,SAAS;YACX,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAChB,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC/B,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,aAAa,CAAC,eAAe,EAAE,CAAC,CAAC;QACtG,MAAM,IAAI,EAAE,CAAC;QACb,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YACnI,KAAK,MAAM,CAAC,IAAI,MAAM;gBAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,KAAK,KAAK,IAAI;YAAE,MAAM,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,OAAO,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;QAC1D,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,GAAG,QAAQ,EAAE,CAAC;gBACnC,MAAM,GAAG,yBAAyB,CAAC;gBACnC,MAAM;YACR,CAAC;YACD,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;YACpB,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;QACzB,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,OAAO,CAAC,OAAO,EAAE,CAAC;YAChB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;gBAC1B,MAAM,GAAG,yBAAyB,CAAC;gBACnC,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM;YACR,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC;YACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM;YAC9B,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;YAClC,IAAI,OAAO,KAAK,IAAI;gBAAE,MAAM,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YAClD,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;QACD,IAAI,CAAC,OAAO;YAAE,MAAM;IACtB,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,KAAK,MAAM,IAAI,IAAI,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YAC5C,OAAO,EAAE,CAAC;YACV,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,CAAC;YACpD,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;gBACrB,IAAI,EAAE,CAAC;gBACP,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,SAAS;oBAAE,MAAM,EAAE,CAAC;YAC9D,CAAC;iBAAM,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,EAAE,CAAC;;gBACrC,OAAO,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,IAAI,MAAM,KAAK,IAAI;QAAE,MAAM,GAAG,iDAAiD,CAAC;IAC/F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,OAAO,KAAK,CAAC,EAAE,CAAC;AACxK,CAAC"}
|