@spool-lab/core 0.4.0 → 0.4.12
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/db/db.d.ts +19 -0
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +210 -15
- package/dist/db/db.js.map +1 -1
- package/dist/db/queries.d.ts +36 -10
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +96 -75
- package/dist/db/queries.js.map +1 -1
- package/dist/db/share-drafts.d.ts +51 -0
- package/dist/db/share-drafts.d.ts.map +1 -0
- package/dist/db/share-drafts.js +47 -0
- package/dist/db/share-drafts.js.map +1 -0
- package/dist/doctor/checks/config.d.ts +3 -0
- package/dist/doctor/checks/config.d.ts.map +1 -0
- package/dist/doctor/checks/config.js +123 -0
- package/dist/doctor/checks/config.js.map +1 -0
- package/dist/doctor/checks/db.d.ts +3 -0
- package/dist/doctor/checks/db.d.ts.map +1 -0
- package/dist/doctor/checks/db.js +225 -0
- package/dist/doctor/checks/db.js.map +1 -0
- package/dist/doctor/checks/env.d.ts +3 -0
- package/dist/doctor/checks/env.d.ts.map +1 -0
- package/dist/doctor/checks/env.js +70 -0
- package/dist/doctor/checks/env.js.map +1 -0
- package/dist/doctor/checks/index.d.ts +3 -0
- package/dist/doctor/checks/index.d.ts.map +1 -0
- package/dist/doctor/checks/index.js +13 -0
- package/dist/doctor/checks/index.js.map +1 -0
- package/dist/doctor/checks/native.d.ts +3 -0
- package/dist/doctor/checks/native.d.ts.map +1 -0
- package/dist/doctor/checks/native.js +42 -0
- package/dist/doctor/checks/native.js.map +1 -0
- package/dist/doctor/checks/versions.d.ts +3 -0
- package/dist/doctor/checks/versions.d.ts.map +1 -0
- package/dist/doctor/checks/versions.js +79 -0
- package/dist/doctor/checks/versions.js.map +1 -0
- package/dist/doctor/index.d.ts +3 -0
- package/dist/doctor/index.d.ts.map +1 -0
- package/dist/doctor/index.js +3 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/doctor/preflight.d.ts +18 -0
- package/dist/doctor/preflight.d.ts.map +1 -0
- package/dist/doctor/preflight.js +27 -0
- package/dist/doctor/preflight.js.map +1 -0
- package/dist/doctor/runner.d.ts +12 -0
- package/dist/doctor/runner.d.ts.map +1 -0
- package/dist/doctor/runner.js +37 -0
- package/dist/doctor/runner.js.map +1 -0
- package/dist/doctor/types.d.ts +27 -0
- package/dist/doctor/types.d.ts.map +1 -0
- package/dist/doctor/types.js +2 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/migrations/agent-search-cleanup.d.ts +36 -0
- package/dist/migrations/agent-search-cleanup.d.ts.map +1 -0
- package/dist/migrations/agent-search-cleanup.js +182 -0
- package/dist/migrations/agent-search-cleanup.js.map +1 -0
- package/dist/migrations/worktree-identity-upgrade.d.ts +31 -0
- package/dist/migrations/worktree-identity-upgrade.d.ts.map +1 -0
- package/dist/migrations/worktree-identity-upgrade.js +22 -0
- package/dist/migrations/worktree-identity-upgrade.js.map +1 -0
- package/dist/parsers/claude.d.ts.map +1 -1
- package/dist/parsers/claude.js +25 -12
- package/dist/parsers/claude.js.map +1 -1
- package/dist/parsers/codex.d.ts.map +1 -1
- package/dist/parsers/codex.js +32 -5
- package/dist/parsers/codex.js.map +1 -1
- package/dist/parsers/gemini.d.ts.map +1 -1
- package/dist/parsers/gemini.js +5 -5
- package/dist/parsers/gemini.js.map +1 -1
- package/dist/parsers/spool-prelude.d.ts +16 -0
- package/dist/parsers/spool-prelude.d.ts.map +1 -0
- package/dist/parsers/spool-prelude.js +21 -0
- package/dist/parsers/spool-prelude.js.map +1 -0
- package/dist/projects/display-name.d.ts +2 -0
- package/dist/projects/display-name.d.ts.map +1 -0
- package/dist/projects/display-name.js +8 -0
- package/dist/projects/display-name.js.map +1 -0
- package/dist/projects/fs.d.ts +3 -0
- package/dist/projects/fs.d.ts.map +1 -0
- package/dist/projects/fs.js +20 -0
- package/dist/projects/fs.js.map +1 -0
- package/dist/projects/groups.d.ts +4 -0
- package/dist/projects/groups.d.ts.map +1 -0
- package/dist/projects/groups.js +20 -0
- package/dist/projects/groups.js.map +1 -0
- package/dist/projects/identity-synthesizers.d.ts +22 -0
- package/dist/projects/identity-synthesizers.d.ts.map +1 -0
- package/dist/projects/identity-synthesizers.js +29 -0
- package/dist/projects/identity-synthesizers.js.map +1 -0
- package/dist/projects/identity.d.ts +16 -0
- package/dist/projects/identity.d.ts.map +1 -0
- package/dist/projects/identity.js +172 -0
- package/dist/projects/identity.js.map +1 -0
- package/dist/projects/sessions.d.ts +12 -0
- package/dist/projects/sessions.d.ts.map +1 -0
- package/dist/projects/sessions.js +47 -0
- package/dist/projects/sessions.js.map +1 -0
- package/dist/projects/worktree-resolvers.d.ts +19 -0
- package/dist/projects/worktree-resolvers.d.ts.map +1 -0
- package/dist/projects/worktree-resolvers.js +65 -0
- package/dist/projects/worktree-resolvers.js.map +1 -0
- package/dist/sync/syncer.d.ts.map +1 -1
- package/dist/sync/syncer.js +11 -3
- package/dist/sync/syncer.js.map +1 -1
- package/dist/types.d.ts +15 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/connectors/capabilities/cookies-chrome.d.ts +0 -19
- package/dist/connectors/capabilities/cookies-chrome.d.ts.map +0 -1
- package/dist/connectors/capabilities/cookies-chrome.js +0 -199
- package/dist/connectors/capabilities/cookies-chrome.js.map +0 -1
- package/dist/connectors/capabilities/exec-impl.d.ts +0 -3
- package/dist/connectors/capabilities/exec-impl.d.ts.map +0 -1
- package/dist/connectors/capabilities/exec-impl.js +0 -108
- package/dist/connectors/capabilities/exec-impl.js.map +0 -1
- package/dist/connectors/capabilities/fetch-impl.d.ts +0 -3
- package/dist/connectors/capabilities/fetch-impl.d.ts.map +0 -1
- package/dist/connectors/capabilities/fetch-impl.js +0 -4
- package/dist/connectors/capabilities/fetch-impl.js.map +0 -1
- package/dist/connectors/capabilities/index.d.ts +0 -6
- package/dist/connectors/capabilities/index.d.ts.map +0 -1
- package/dist/connectors/capabilities/index.js +0 -6
- package/dist/connectors/capabilities/index.js.map +0 -1
- package/dist/connectors/capabilities/log-impl.d.ts +0 -3
- package/dist/connectors/capabilities/log-impl.d.ts.map +0 -1
- package/dist/connectors/capabilities/log-impl.js +0 -26
- package/dist/connectors/capabilities/log-impl.js.map +0 -1
- package/dist/connectors/capabilities/sqlite-impl.d.ts +0 -3
- package/dist/connectors/capabilities/sqlite-impl.d.ts.map +0 -1
- package/dist/connectors/capabilities/sqlite-impl.js +0 -19
- package/dist/connectors/capabilities/sqlite-impl.js.map +0 -1
- package/dist/connectors/loader.d.ts +0 -47
- package/dist/connectors/loader.d.ts.map +0 -1
- package/dist/connectors/loader.js +0 -328
- package/dist/connectors/loader.js.map +0 -1
- package/dist/connectors/npm-install.d.ts +0 -26
- package/dist/connectors/npm-install.d.ts.map +0 -1
- package/dist/connectors/npm-install.js +0 -74
- package/dist/connectors/npm-install.js.map +0 -1
- package/dist/connectors/prerequisites.d.ts +0 -14
- package/dist/connectors/prerequisites.d.ts.map +0 -1
- package/dist/connectors/prerequisites.js +0 -109
- package/dist/connectors/prerequisites.js.map +0 -1
- package/dist/connectors/registry-fetch.d.ts +0 -22
- package/dist/connectors/registry-fetch.d.ts.map +0 -1
- package/dist/connectors/registry-fetch.js +0 -54
- package/dist/connectors/registry-fetch.js.map +0 -1
- package/dist/connectors/registry.d.ts +0 -23
- package/dist/connectors/registry.d.ts.map +0 -1
- package/dist/connectors/registry.js +0 -59
- package/dist/connectors/registry.js.map +0 -1
- package/dist/connectors/sync-engine.d.ts +0 -31
- package/dist/connectors/sync-engine.d.ts.map +0 -1
- package/dist/connectors/sync-engine.js +0 -604
- package/dist/connectors/sync-engine.js.map +0 -1
- package/dist/connectors/sync-scheduler.d.ts +0 -56
- package/dist/connectors/sync-scheduler.d.ts.map +0 -1
- package/dist/connectors/sync-scheduler.js +0 -238
- package/dist/connectors/sync-scheduler.js.map +0 -1
- package/dist/connectors/trust-store.d.ts +0 -13
- package/dist/connectors/trust-store.d.ts.map +0 -1
- package/dist/connectors/trust-store.js +0 -48
- package/dist/connectors/trust-store.js.map +0 -1
- package/dist/connectors/types.d.ts +0 -111
- package/dist/connectors/types.d.ts.map +0 -1
- package/dist/connectors/types.js +0 -50
- package/dist/connectors/types.js.map +0 -1
|
@@ -1,604 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { Clock, Deferred, Duration, Effect } from 'effect';
|
|
3
|
-
import { SyncError, DEFAULT_SCHEDULE } from './types.js';
|
|
4
|
-
/**
|
|
5
|
-
* Bridge an optional AbortSignal into a CancelSignal registered in the
|
|
6
|
-
* ambient Scope. The listener is cleaned up by the scope's finalizer.
|
|
7
|
-
*/
|
|
8
|
-
function bridgeAbortSignal(signal, cancel) {
|
|
9
|
-
if (!signal)
|
|
10
|
-
return Effect.void;
|
|
11
|
-
if (signal.aborted)
|
|
12
|
-
return Deferred.succeed(cancel, undefined).pipe(Effect.asVoid);
|
|
13
|
-
return Effect.acquireRelease(Effect.sync(() => {
|
|
14
|
-
const handler = () => {
|
|
15
|
-
Deferred.unsafeDone(cancel, Effect.void);
|
|
16
|
-
};
|
|
17
|
-
signal.addEventListener('abort', handler, { once: true });
|
|
18
|
-
return handler;
|
|
19
|
-
}), (handler) => Effect.sync(() => signal.removeEventListener('abort', handler))).pipe(Effect.asVoid);
|
|
20
|
-
}
|
|
21
|
-
function cancelDeferredToSignal(cancel) {
|
|
22
|
-
return Effect.sync(() => {
|
|
23
|
-
const controller = new AbortController();
|
|
24
|
-
Effect.runFork(Effect.gen(function* () {
|
|
25
|
-
yield* Deferred.await(cancel);
|
|
26
|
-
controller.abort();
|
|
27
|
-
}));
|
|
28
|
-
return controller.signal;
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Sleep `ms` milliseconds but wake immediately if the cancel signal fires.
|
|
33
|
-
* The loop top still polls the cancel signal for a graceful
|
|
34
|
-
* `stopReason='cancelled'` return; this racer just cuts the sleep short.
|
|
35
|
-
*/
|
|
36
|
-
function interruptibleSleep(ms, cancel) {
|
|
37
|
-
return Effect.race(Effect.sleep(Duration.millis(ms)), Deferred.await(cancel)).pipe(Effect.asVoid);
|
|
38
|
-
}
|
|
39
|
-
const nowIso = Effect.map(Clock.currentTimeMillis, (ms) => new Date(ms).toISOString());
|
|
40
|
-
// ── Sync State Persistence ──────────────────────────────────────────────────
|
|
41
|
-
export function loadSyncState(db, connectorId) {
|
|
42
|
-
const row = db.prepare('SELECT * FROM connector_sync_state WHERE connector_id = ?')
|
|
43
|
-
.get(connectorId);
|
|
44
|
-
if (!row) {
|
|
45
|
-
return {
|
|
46
|
-
connectorId,
|
|
47
|
-
headCursor: null,
|
|
48
|
-
headItemId: null,
|
|
49
|
-
tailCursor: null,
|
|
50
|
-
tailComplete: false,
|
|
51
|
-
lastForwardSyncAt: null,
|
|
52
|
-
lastBackfillSyncAt: null,
|
|
53
|
-
totalSynced: 0,
|
|
54
|
-
consecutiveErrors: 0,
|
|
55
|
-
enabled: false,
|
|
56
|
-
configJson: {},
|
|
57
|
-
lastErrorAt: null,
|
|
58
|
-
lastErrorCode: null,
|
|
59
|
-
lastErrorMessage: null,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
let configJson = {};
|
|
63
|
-
try {
|
|
64
|
-
configJson = JSON.parse(row['config_json']);
|
|
65
|
-
}
|
|
66
|
-
catch { }
|
|
67
|
-
return {
|
|
68
|
-
connectorId,
|
|
69
|
-
headCursor: row['head_cursor'],
|
|
70
|
-
headItemId: row['head_item_id'],
|
|
71
|
-
tailCursor: row['tail_cursor'],
|
|
72
|
-
tailComplete: Boolean(row['tail_complete']),
|
|
73
|
-
lastForwardSyncAt: row['last_forward_sync_at'],
|
|
74
|
-
lastBackfillSyncAt: row['last_backfill_sync_at'],
|
|
75
|
-
totalSynced: row['total_synced'],
|
|
76
|
-
consecutiveErrors: row['consecutive_errors'],
|
|
77
|
-
enabled: Boolean(row['enabled']),
|
|
78
|
-
configJson,
|
|
79
|
-
lastErrorAt: row['last_error_at'],
|
|
80
|
-
lastErrorCode: row['last_error_code'],
|
|
81
|
-
lastErrorMessage: row['last_error_message'],
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
export function saveSyncState(db, state) {
|
|
85
|
-
db.prepare(`
|
|
86
|
-
INSERT INTO connector_sync_state
|
|
87
|
-
(connector_id, head_cursor, head_item_id, tail_cursor, tail_complete,
|
|
88
|
-
last_forward_sync_at, last_backfill_sync_at, total_synced,
|
|
89
|
-
consecutive_errors, enabled, config_json,
|
|
90
|
-
last_error_at, last_error_code, last_error_message)
|
|
91
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
92
|
-
ON CONFLICT(connector_id) DO UPDATE SET
|
|
93
|
-
head_cursor = excluded.head_cursor,
|
|
94
|
-
head_item_id = excluded.head_item_id,
|
|
95
|
-
tail_cursor = excluded.tail_cursor,
|
|
96
|
-
tail_complete = excluded.tail_complete,
|
|
97
|
-
last_forward_sync_at = excluded.last_forward_sync_at,
|
|
98
|
-
last_backfill_sync_at = excluded.last_backfill_sync_at,
|
|
99
|
-
total_synced = excluded.total_synced,
|
|
100
|
-
consecutive_errors = excluded.consecutive_errors,
|
|
101
|
-
enabled = excluded.enabled,
|
|
102
|
-
config_json = excluded.config_json,
|
|
103
|
-
last_error_at = excluded.last_error_at,
|
|
104
|
-
last_error_code = excluded.last_error_code,
|
|
105
|
-
last_error_message = excluded.last_error_message
|
|
106
|
-
`).run(state.connectorId, state.headCursor, state.headItemId, state.tailCursor, state.tailComplete ? 1 : 0, state.lastForwardSyncAt, state.lastBackfillSyncAt, state.totalSynced, state.consecutiveErrors, state.enabled ? 1 : 0, JSON.stringify(state.configJson), state.lastErrorAt, state.lastErrorCode, state.lastErrorMessage);
|
|
107
|
-
}
|
|
108
|
-
function upsertItems(db, sourceId, connectorId, items) {
|
|
109
|
-
let newCount = 0;
|
|
110
|
-
let updatedCount = 0;
|
|
111
|
-
const checkStmt = db.prepare('SELECT id FROM captures WHERE platform = ? AND platform_id = ?');
|
|
112
|
-
const updateStmt = db.prepare(`
|
|
113
|
-
UPDATE captures SET
|
|
114
|
-
title = ?, content_text = ?, author = ?, metadata = ?,
|
|
115
|
-
captured_at = ?, raw_json = ?, thumbnail_url = ?
|
|
116
|
-
WHERE id = ?
|
|
117
|
-
`);
|
|
118
|
-
const insertStmt = db.prepare(`
|
|
119
|
-
INSERT INTO captures
|
|
120
|
-
(source_id, capture_uuid, url, title, content_text,
|
|
121
|
-
author, platform, platform_id, content_type, thumbnail_url,
|
|
122
|
-
metadata, captured_at, raw_json)
|
|
123
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
124
|
-
`);
|
|
125
|
-
const linkStmt = db.prepare('INSERT OR IGNORE INTO capture_connectors (capture_id, connector_id) VALUES (?, ?)');
|
|
126
|
-
for (const item of items) {
|
|
127
|
-
let captureId = null;
|
|
128
|
-
if (item.platformId) {
|
|
129
|
-
const existing = checkStmt.get(item.platform, item.platformId);
|
|
130
|
-
if (existing) {
|
|
131
|
-
updateStmt.run(item.title, item.contentText, item.author, JSON.stringify(item.metadata), item.capturedAt, item.rawJson, item.thumbnailUrl, existing.id);
|
|
132
|
-
captureId = existing.id;
|
|
133
|
-
updatedCount++;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
if (captureId === null) {
|
|
137
|
-
const info = insertStmt.run(sourceId, randomUUID(), item.url, item.title, item.contentText, item.author, item.platform, item.platformId, item.contentType, item.thumbnailUrl, JSON.stringify(item.metadata), item.capturedAt, item.rawJson);
|
|
138
|
-
captureId = info.lastInsertRowid;
|
|
139
|
-
newCount++;
|
|
140
|
-
}
|
|
141
|
-
linkStmt.run(captureId, connectorId);
|
|
142
|
-
}
|
|
143
|
-
return { newCount, updatedCount };
|
|
144
|
-
}
|
|
145
|
-
export function deleteConnectorItems(db, connectorId) {
|
|
146
|
-
// 1. Drop this connector's M:N claims.
|
|
147
|
-
db.prepare('DELETE FROM capture_connectors WHERE connector_id = ?').run(connectorId);
|
|
148
|
-
// 2. Drop stars on captures that are about to disappear. Bulk-replace
|
|
149
|
-
// connectors (ephemeral or full-wipe) re-insert captures with new UUIDs
|
|
150
|
-
// on the next sync, so without this the star becomes a permanent orphan.
|
|
151
|
-
// Scoped with the same predicate as the capture delete below.
|
|
152
|
-
db.prepare(`
|
|
153
|
-
DELETE FROM stars
|
|
154
|
-
WHERE item_type = 'capture'
|
|
155
|
-
AND item_uuid IN (
|
|
156
|
-
SELECT capture_uuid FROM captures
|
|
157
|
-
WHERE source_id = (SELECT id FROM sources WHERE name = 'connector')
|
|
158
|
-
AND NOT EXISTS (
|
|
159
|
-
SELECT 1 FROM capture_connectors WHERE capture_id = captures.id
|
|
160
|
-
)
|
|
161
|
-
)
|
|
162
|
-
`).run();
|
|
163
|
-
// 3. Delete captures that belonged to this connector and have no other
|
|
164
|
-
// connector attribution left. Scoped to source='connector' so we never
|
|
165
|
-
// touch session-world captures.
|
|
166
|
-
db.prepare(`
|
|
167
|
-
DELETE FROM captures
|
|
168
|
-
WHERE source_id = (SELECT id FROM sources WHERE name = 'connector')
|
|
169
|
-
AND NOT EXISTS (
|
|
170
|
-
SELECT 1 FROM capture_connectors WHERE capture_id = captures.id
|
|
171
|
-
)
|
|
172
|
-
`).run();
|
|
173
|
-
}
|
|
174
|
-
// ── Sync Engine ─────────────────────────────────────────────────────────────
|
|
175
|
-
function getSourceId(db) {
|
|
176
|
-
// Connector captures all share a single generic 'connector' source row.
|
|
177
|
-
// Per-connector attribution lives in the capture_connectors M:N table.
|
|
178
|
-
const row = db.prepare("SELECT id FROM sources WHERE name = 'connector'").get();
|
|
179
|
-
if (!row)
|
|
180
|
-
throw new Error("Source 'connector' not found in DB");
|
|
181
|
-
return row.id;
|
|
182
|
-
}
|
|
183
|
-
function hasKnownItem(db, platform, items) {
|
|
184
|
-
if (items.length === 0)
|
|
185
|
-
return false;
|
|
186
|
-
const stmt = db.prepare('SELECT 1 FROM captures WHERE platform = ? AND platform_id = ? LIMIT 1');
|
|
187
|
-
for (const item of items) {
|
|
188
|
-
if (item.platformId && stmt.get(platform, item.platformId))
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
|
-
return false;
|
|
192
|
-
}
|
|
193
|
-
export class SyncEngine {
|
|
194
|
-
db;
|
|
195
|
-
constructor(db) {
|
|
196
|
-
this.db = db;
|
|
197
|
-
}
|
|
198
|
-
loadState(connectorId) {
|
|
199
|
-
return loadSyncState(this.db, connectorId);
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Effect-native entry point. Returns an Effect that, when run, executes a
|
|
203
|
-
* full sync cycle (ephemeral or dual-frontier persistent) and records the
|
|
204
|
-
* outcome in connector_sync_state. The Effect is `Effect<ConnectorSyncResult, never>`
|
|
205
|
-
* because all SyncErrors are caught internally and encoded in `result.error`.
|
|
206
|
-
*
|
|
207
|
-
* Preferred by callers that already live in the Effect world (the Scheduler
|
|
208
|
-
* Effect migration, tests that want to inject Logger / Tracer layers via
|
|
209
|
-
* `Effect.provide`). Promise-based callers should use `sync()` instead.
|
|
210
|
-
*/
|
|
211
|
-
syncEffect(connector, opts = {}) {
|
|
212
|
-
const db = this.db;
|
|
213
|
-
const self = this;
|
|
214
|
-
return Effect.gen(function* () {
|
|
215
|
-
const state = yield* Effect.sync(() => loadSyncState(db, connector.id));
|
|
216
|
-
const startedAt = yield* Clock.currentTimeMillis;
|
|
217
|
-
const cancel = opts.cancel ?? (yield* Deferred.make());
|
|
218
|
-
yield* bridgeAbortSignal(opts.signal, cancel);
|
|
219
|
-
const body = connector.ephemeral
|
|
220
|
-
? self.syncEphemeralEffect(connector, state, opts, startedAt, cancel)
|
|
221
|
-
: self.syncPersistentEffect(connector, state, opts, startedAt, cancel);
|
|
222
|
-
const result = yield* body.pipe(Effect.withSpan('sync.cycle', {
|
|
223
|
-
attributes: {
|
|
224
|
-
'connector.id': connector.id,
|
|
225
|
-
'sync.direction': opts.direction ?? 'both',
|
|
226
|
-
},
|
|
227
|
-
}));
|
|
228
|
-
if (result.error) {
|
|
229
|
-
state.consecutiveErrors += 1;
|
|
230
|
-
state.lastErrorAt = yield* nowIso;
|
|
231
|
-
state.lastErrorCode = result.error.code;
|
|
232
|
-
state.lastErrorMessage = result.error.message;
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
state.consecutiveErrors = 0;
|
|
236
|
-
state.lastErrorAt = null;
|
|
237
|
-
state.lastErrorCode = null;
|
|
238
|
-
state.lastErrorMessage = null;
|
|
239
|
-
}
|
|
240
|
-
yield* Effect.sync(() => saveSyncState(db, state));
|
|
241
|
-
return result;
|
|
242
|
-
// Effect.scoped discharges the Scope required by bridgeAbortSignal's
|
|
243
|
-
// acquireRelease, guaranteeing removeEventListener runs on every exit
|
|
244
|
-
// path (success, failure, interruption).
|
|
245
|
-
}).pipe(Effect.scoped);
|
|
246
|
-
}
|
|
247
|
-
async sync(connector, opts = {}) {
|
|
248
|
-
// opts.signal is bridged into an internal Deferred by syncEffect —
|
|
249
|
-
// NOT passed to runPromise, because runtime interruption would
|
|
250
|
-
// skip state persistence and surface as an error. Cancellation must
|
|
251
|
-
// be observable inside the loop (via Deferred.isDone) so the loop
|
|
252
|
-
// can return gracefully with stopReason='cancelled' + partial progress.
|
|
253
|
-
try {
|
|
254
|
-
return await Effect.runPromise(this.syncEffect(connector, opts));
|
|
255
|
-
}
|
|
256
|
-
catch (err) {
|
|
257
|
-
// Defect surfaced past the typed error channel — defensive fallback.
|
|
258
|
-
const state = loadSyncState(this.db, connector.id);
|
|
259
|
-
const syncErr = SyncError.from(err);
|
|
260
|
-
state.consecutiveErrors += 1;
|
|
261
|
-
state.lastErrorAt = new Date().toISOString();
|
|
262
|
-
state.lastErrorCode = syncErr.code;
|
|
263
|
-
state.lastErrorMessage = syncErr.message;
|
|
264
|
-
saveSyncState(this.db, state);
|
|
265
|
-
return {
|
|
266
|
-
connectorId: connector.id,
|
|
267
|
-
added: 0,
|
|
268
|
-
total: state.totalSynced,
|
|
269
|
-
pages: 0,
|
|
270
|
-
direction: opts.direction ?? 'both',
|
|
271
|
-
stopReason: `error: ${syncErr.code}`,
|
|
272
|
-
error: { code: syncErr.code, message: syncErr.message },
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Fetch pages in an Effect-based loop until a stop condition is met.
|
|
278
|
-
* Errors are caught internally and returned in the result (never fails).
|
|
279
|
-
*/
|
|
280
|
-
fetchLoopEffect(connector, state, opts, sourceId, startCursor, startedAt, cancel, signal) {
|
|
281
|
-
const db = this.db;
|
|
282
|
-
const delayMs = opts.delayMs ?? DEFAULT_SCHEDULE.pageDelayMs;
|
|
283
|
-
const maxMinutes = opts.maxMinutes ?? 0;
|
|
284
|
-
const maxPages = opts.maxPages ?? 100;
|
|
285
|
-
const stalePageLimit = opts.stalePageLimit ?? 3;
|
|
286
|
-
const checkpointEvery = 25;
|
|
287
|
-
const deadline = maxMinutes > 0 ? startedAt + maxMinutes * 60_000 : Number.POSITIVE_INFINITY;
|
|
288
|
-
// Initial sync handoff: forward writes tailCursor ONLY on the very first sync
|
|
289
|
-
// (tailCursor still null, no prior forward interrupted = headCursor null).
|
|
290
|
-
// This lets backfill pick up where forward left off. On subsequent cycles,
|
|
291
|
-
// forward must NOT touch tailCursor — otherwise it overwrites backfill's
|
|
292
|
-
// deep progress with a shallow position near the newest end.
|
|
293
|
-
const isInitialSync = opts.phase === 'forward'
|
|
294
|
-
&& state.tailCursor === null
|
|
295
|
-
&& state.headCursor === null;
|
|
296
|
-
// Capture the since-anchor at loop entry, before page-0 may update
|
|
297
|
-
// headItemId. This is the stop signal for forward early-exit:
|
|
298
|
-
// "stop when you reach this item — everything at or beyond it is already indexed."
|
|
299
|
-
const sinceItemId = opts.phase === 'forward' ? state.headItemId : null;
|
|
300
|
-
return Effect.gen(function* () {
|
|
301
|
-
let cursor = startCursor;
|
|
302
|
-
let added = 0;
|
|
303
|
-
let pages = 0;
|
|
304
|
-
let stalePages = 0;
|
|
305
|
-
while (true) {
|
|
306
|
-
const now = yield* Clock.currentTimeMillis;
|
|
307
|
-
if (now >= deadline) {
|
|
308
|
-
return { added, pages, stopReason: 'timeout' };
|
|
309
|
-
}
|
|
310
|
-
if (pages >= maxPages) {
|
|
311
|
-
return { added, pages, stopReason: 'max_pages' };
|
|
312
|
-
}
|
|
313
|
-
if (yield* Deferred.isDone(cancel)) {
|
|
314
|
-
return { added, pages, stopReason: 'cancelled' };
|
|
315
|
-
}
|
|
316
|
-
const fetchCtx = { cursor, sinceItemId, phase: opts.phase, signal };
|
|
317
|
-
const outcome = yield* Effect.either(Effect.tryPromise({
|
|
318
|
-
try: () => connector.fetchPage(fetchCtx),
|
|
319
|
-
catch: SyncError.from,
|
|
320
|
-
}).pipe(Effect.withSpan('sync.fetchPage', {
|
|
321
|
-
attributes: {
|
|
322
|
-
'connector.id': connector.id,
|
|
323
|
-
'sync.phase': opts.phase,
|
|
324
|
-
'sync.page': pages + 1,
|
|
325
|
-
},
|
|
326
|
-
})));
|
|
327
|
-
if (outcome._tag === 'Left') {
|
|
328
|
-
const err = outcome.left;
|
|
329
|
-
yield* Effect.logError(`[sync-engine] ${connector.id} ${opts.phase} page ${pages + 1} error: ${err.message}`);
|
|
330
|
-
yield* Effect.sync(() => saveSyncState(db, state));
|
|
331
|
-
return {
|
|
332
|
-
added,
|
|
333
|
-
pages,
|
|
334
|
-
stopReason: `error: ${err.code}`,
|
|
335
|
-
error: { code: err.code, message: err.message },
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
const result = outcome.right;
|
|
339
|
-
pages++;
|
|
340
|
-
if (result.items.length === 0 && !result.nextCursor) {
|
|
341
|
-
if (opts.phase === 'forward')
|
|
342
|
-
state.headCursor = null;
|
|
343
|
-
if (opts.phase === 'backfill')
|
|
344
|
-
state.tailComplete = true;
|
|
345
|
-
return {
|
|
346
|
-
added,
|
|
347
|
-
pages,
|
|
348
|
-
stopReason: opts.phase === 'backfill' ? 'backfill_complete' : 'end_of_data',
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
const { newCount } = yield* Effect.sync(() => db.transaction(() => upsertItems(db, sourceId, connector.id, result.items))()).pipe(Effect.withSpan('sync.upsert', {
|
|
352
|
-
attributes: { 'items.count': result.items.length },
|
|
353
|
-
}));
|
|
354
|
-
added += newCount;
|
|
355
|
-
// Update headItemId: the platform ID of the newest item we've ever seen.
|
|
356
|
-
// Only on forward, only on the first page (pages === 1 after increment),
|
|
357
|
-
// and only when NOT resuming from headCursor — a resumed forward is
|
|
358
|
-
// catching up to the existing anchor, not establishing a new one.
|
|
359
|
-
// On platforms with cursor-walking (no server-side since), the first page
|
|
360
|
-
// of a fresh forward always starts at the newest end, so page-0's first
|
|
361
|
-
// item is guaranteed to be >= the current headItemId.
|
|
362
|
-
if (opts.phase === 'forward' && pages === 1 && startCursor === null) {
|
|
363
|
-
const firstItem = result.items[0];
|
|
364
|
-
if (firstItem?.platformId && firstItem.platformId !== state.headItemId) {
|
|
365
|
-
state.headItemId = firstItem.platformId;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
if (opts.onProgress) {
|
|
369
|
-
const progress = {
|
|
370
|
-
connectorId: connector.id,
|
|
371
|
-
phase: opts.phase,
|
|
372
|
-
page: pages,
|
|
373
|
-
fetched: result.items.length,
|
|
374
|
-
added,
|
|
375
|
-
running: true,
|
|
376
|
-
};
|
|
377
|
-
yield* Effect.sync(() => opts.onProgress(progress));
|
|
378
|
-
}
|
|
379
|
-
// Early-exit: forward stops when it reaches the since-anchor (headItemId).
|
|
380
|
-
// This means we've caught up to the point where the last forward left off.
|
|
381
|
-
// Much more efficient than stale-page detection for small incremental syncs
|
|
382
|
-
// (e.g. 2 new bookmarks → 1 page instead of 3+ stale pages).
|
|
383
|
-
// Note: sinceItemId was already captured into headItemId before page 0's
|
|
384
|
-
// update (headItemId is only updated on page 0 of a fresh forward),
|
|
385
|
-
// so we compare against the original anchor stored at fetchLoop entry.
|
|
386
|
-
if (opts.phase === 'forward' && sinceItemId) {
|
|
387
|
-
const hitAnchor = result.items.some(item => item.platformId === sinceItemId);
|
|
388
|
-
if (hitAnchor) {
|
|
389
|
-
state.headCursor = null;
|
|
390
|
-
return { added, pages, stopReason: 'reached_since' };
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
// Stale page detection: stop when we keep seeing only known data
|
|
394
|
-
if (newCount === 0)
|
|
395
|
-
stalePages++;
|
|
396
|
-
else
|
|
397
|
-
stalePages = 0;
|
|
398
|
-
if (stalePages >= stalePageLimit) {
|
|
399
|
-
if (opts.phase === 'forward')
|
|
400
|
-
state.headCursor = null;
|
|
401
|
-
if (opts.phase === 'backfill')
|
|
402
|
-
state.tailComplete = true;
|
|
403
|
-
return {
|
|
404
|
-
added,
|
|
405
|
-
pages,
|
|
406
|
-
stopReason: opts.phase === 'forward' ? 'caught_up' : 'backfill_complete',
|
|
407
|
-
};
|
|
408
|
-
}
|
|
409
|
-
if (!result.nextCursor) {
|
|
410
|
-
if (opts.phase === 'forward')
|
|
411
|
-
state.headCursor = null;
|
|
412
|
-
if (opts.phase === 'backfill')
|
|
413
|
-
state.tailComplete = true;
|
|
414
|
-
return {
|
|
415
|
-
added,
|
|
416
|
-
pages,
|
|
417
|
-
stopReason: opts.phase === 'backfill' ? 'backfill_complete' : 'end_of_data',
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
cursor = result.nextCursor;
|
|
421
|
-
if (opts.phase === 'forward') {
|
|
422
|
-
// Save forward progress so an interrupted cycle can resume here
|
|
423
|
-
// instead of re-fetching from the newest end.
|
|
424
|
-
state.headCursor = cursor;
|
|
425
|
-
// Only write tailCursor during initial sync (handoff to backfill).
|
|
426
|
-
if (isInitialSync)
|
|
427
|
-
state.tailCursor = cursor;
|
|
428
|
-
}
|
|
429
|
-
else {
|
|
430
|
-
state.tailCursor = cursor;
|
|
431
|
-
}
|
|
432
|
-
if (pages % checkpointEvery === 0) {
|
|
433
|
-
yield* Effect.sync(() => saveSyncState(db, state));
|
|
434
|
-
}
|
|
435
|
-
// Cap the inter-page delay at the remaining deadline so maxMinutes
|
|
436
|
-
// has ms-level precision instead of being gated on polling frequency.
|
|
437
|
-
const nowAfter = yield* Clock.currentTimeMillis;
|
|
438
|
-
const remaining = deadline - nowAfter;
|
|
439
|
-
const actualDelay = Math.max(0, Math.min(delayMs, remaining));
|
|
440
|
-
if (actualDelay > 0) {
|
|
441
|
-
yield* interruptibleSleep(actualDelay, cancel);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
}
|
|
446
|
-
syncPersistentEffect(connector, state, opts, startedAt, cancel) {
|
|
447
|
-
const db = this.db;
|
|
448
|
-
const direction = opts.direction ?? 'both';
|
|
449
|
-
const sourceId = getSourceId(db);
|
|
450
|
-
const self = this;
|
|
451
|
-
return Effect.gen(function* () {
|
|
452
|
-
const signal = yield* cancelDeferredToSignal(cancel);
|
|
453
|
-
let totalAdded = 0;
|
|
454
|
-
let totalPages = 0;
|
|
455
|
-
let stopReason = 'complete';
|
|
456
|
-
let lastError;
|
|
457
|
-
if (direction === 'forward' || direction === 'both') {
|
|
458
|
-
const hadAnchor = state.headItemId !== null;
|
|
459
|
-
const fwd = yield* self
|
|
460
|
-
.fetchLoopEffect(connector, state, { ...opts, phase: 'forward' }, sourceId, state.headCursor ?? null, startedAt, cancel, signal)
|
|
461
|
-
.pipe(Effect.withSpan('sync.forward'));
|
|
462
|
-
totalAdded += fwd.added;
|
|
463
|
-
totalPages += fwd.pages;
|
|
464
|
-
stopReason = fwd.stopReason;
|
|
465
|
-
if (fwd.error)
|
|
466
|
-
lastError = fwd.error;
|
|
467
|
-
state.lastForwardSyncAt = yield* nowIso;
|
|
468
|
-
// Anchor invalidation recovery (Q3): if forward ran to completion
|
|
469
|
-
// (not interrupted) but never hit the since-anchor, the anchor is stale
|
|
470
|
-
// (e.g. user un-bookmarked that item). Clear it so next forward starts
|
|
471
|
-
// fresh and re-establishes the anchor from page 0.
|
|
472
|
-
const completedWithoutHit = hadAnchor
|
|
473
|
-
&& fwd.stopReason !== 'reached_since'
|
|
474
|
-
&& fwd.stopReason !== 'timeout'
|
|
475
|
-
&& fwd.stopReason !== 'cancelled'
|
|
476
|
-
&& !fwd.stopReason.startsWith('error');
|
|
477
|
-
if (completedWithoutHit) {
|
|
478
|
-
state.headItemId = null;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
if (!lastError && !state.tailComplete && (direction === 'backfill' || direction === 'both')) {
|
|
482
|
-
const bf = yield* self
|
|
483
|
-
.fetchLoopEffect(connector, state, { ...opts, phase: 'backfill' }, sourceId, state.tailCursor, startedAt, cancel, signal)
|
|
484
|
-
.pipe(Effect.withSpan('sync.backfill'));
|
|
485
|
-
totalAdded += bf.added;
|
|
486
|
-
totalPages += bf.pages;
|
|
487
|
-
stopReason = bf.stopReason;
|
|
488
|
-
if (bf.error)
|
|
489
|
-
lastError = bf.error;
|
|
490
|
-
state.lastBackfillSyncAt = yield* nowIso;
|
|
491
|
-
}
|
|
492
|
-
state.totalSynced += totalAdded;
|
|
493
|
-
yield* Effect.sync(() => saveSyncState(db, state));
|
|
494
|
-
yield* Effect.logInfo(`[sync-engine] ${connector.id} done: added=${totalAdded} pages=${totalPages} reason=${stopReason}`);
|
|
495
|
-
if (opts.onProgress) {
|
|
496
|
-
const progress = {
|
|
497
|
-
connectorId: connector.id,
|
|
498
|
-
phase: 'forward',
|
|
499
|
-
page: totalPages,
|
|
500
|
-
fetched: 0,
|
|
501
|
-
added: totalAdded,
|
|
502
|
-
running: false,
|
|
503
|
-
};
|
|
504
|
-
yield* Effect.sync(() => opts.onProgress(progress));
|
|
505
|
-
}
|
|
506
|
-
const ret = {
|
|
507
|
-
connectorId: connector.id,
|
|
508
|
-
added: totalAdded,
|
|
509
|
-
total: state.totalSynced,
|
|
510
|
-
pages: totalPages,
|
|
511
|
-
direction,
|
|
512
|
-
stopReason,
|
|
513
|
-
};
|
|
514
|
-
if (lastError) {
|
|
515
|
-
ret.error = { code: lastError.code, message: lastError.message };
|
|
516
|
-
}
|
|
517
|
-
return ret;
|
|
518
|
-
});
|
|
519
|
-
}
|
|
520
|
-
syncEphemeralEffect(connector, state, opts, startedAt, cancel) {
|
|
521
|
-
const db = this.db;
|
|
522
|
-
const delayMs = opts.delayMs ?? DEFAULT_SCHEDULE.pageDelayMs;
|
|
523
|
-
const maxMinutes = opts.maxMinutes ?? 0;
|
|
524
|
-
const maxPages = opts.maxPages ?? 100;
|
|
525
|
-
const sourceId = getSourceId(db);
|
|
526
|
-
const deadline = maxMinutes > 0 ? startedAt + maxMinutes * 60_000 : Number.POSITIVE_INFINITY;
|
|
527
|
-
return Effect.gen(function* () {
|
|
528
|
-
const signal = yield* cancelDeferredToSignal(cancel);
|
|
529
|
-
yield* Effect.sync(() => db.transaction(() => deleteConnectorItems(db, connector.id))());
|
|
530
|
-
let cursor = null;
|
|
531
|
-
let totalAdded = 0;
|
|
532
|
-
let totalPages = 0;
|
|
533
|
-
let stopReason = 'complete';
|
|
534
|
-
while (true) {
|
|
535
|
-
const now = yield* Clock.currentTimeMillis;
|
|
536
|
-
if (now >= deadline) {
|
|
537
|
-
stopReason = 'timeout';
|
|
538
|
-
break;
|
|
539
|
-
}
|
|
540
|
-
if (totalPages >= maxPages) {
|
|
541
|
-
stopReason = 'max_pages';
|
|
542
|
-
break;
|
|
543
|
-
}
|
|
544
|
-
if (yield* Deferred.isDone(cancel)) {
|
|
545
|
-
stopReason = 'cancelled';
|
|
546
|
-
break;
|
|
547
|
-
}
|
|
548
|
-
const outcome = yield* Effect.either(Effect.tryPromise({
|
|
549
|
-
try: () => connector.fetchPage({ cursor, sinceItemId: null, phase: 'forward', signal }),
|
|
550
|
-
catch: SyncError.from,
|
|
551
|
-
}).pipe(Effect.withSpan('sync.fetchPage', {
|
|
552
|
-
attributes: {
|
|
553
|
-
'connector.id': connector.id,
|
|
554
|
-
'sync.phase': 'forward',
|
|
555
|
-
'sync.page': totalPages + 1,
|
|
556
|
-
},
|
|
557
|
-
})));
|
|
558
|
-
if (outcome._tag === 'Left') {
|
|
559
|
-
const err = outcome.left;
|
|
560
|
-
yield* Effect.logError(`[sync-engine] ${connector.id} forward page ${totalPages + 1} error: ${err.message}`);
|
|
561
|
-
state.totalSynced = totalAdded;
|
|
562
|
-
state.lastForwardSyncAt = yield* nowIso;
|
|
563
|
-
yield* Effect.sync(() => saveSyncState(db, state));
|
|
564
|
-
return {
|
|
565
|
-
connectorId: connector.id,
|
|
566
|
-
added: totalAdded,
|
|
567
|
-
total: totalAdded,
|
|
568
|
-
pages: totalPages,
|
|
569
|
-
direction: 'forward',
|
|
570
|
-
stopReason: `error: ${err.code}`,
|
|
571
|
-
error: { code: err.code, message: err.message },
|
|
572
|
-
};
|
|
573
|
-
}
|
|
574
|
-
const result = outcome.right;
|
|
575
|
-
totalPages++;
|
|
576
|
-
const { newCount } = yield* Effect.sync(() => db.transaction(() => upsertItems(db, sourceId, connector.id, result.items))()).pipe(Effect.withSpan('sync.upsert', {
|
|
577
|
-
attributes: { 'items.count': result.items.length },
|
|
578
|
-
}));
|
|
579
|
-
totalAdded += newCount;
|
|
580
|
-
if (!result.nextCursor)
|
|
581
|
-
break;
|
|
582
|
-
cursor = result.nextCursor;
|
|
583
|
-
const nowAfter = yield* Clock.currentTimeMillis;
|
|
584
|
-
const remaining = deadline - nowAfter;
|
|
585
|
-
const actualDelay = Math.max(0, Math.min(delayMs, remaining));
|
|
586
|
-
if (actualDelay > 0) {
|
|
587
|
-
yield* interruptibleSleep(actualDelay, cancel);
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
state.totalSynced = totalAdded;
|
|
591
|
-
state.lastForwardSyncAt = yield* nowIso;
|
|
592
|
-
yield* Effect.sync(() => saveSyncState(db, state));
|
|
593
|
-
return {
|
|
594
|
-
connectorId: connector.id,
|
|
595
|
-
added: totalAdded,
|
|
596
|
-
total: totalAdded,
|
|
597
|
-
pages: totalPages,
|
|
598
|
-
direction: 'forward',
|
|
599
|
-
stopReason,
|
|
600
|
-
};
|
|
601
|
-
});
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
//# sourceMappingURL=sync-engine.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sync-engine.js","sourceRoot":"","sources":["../../src/connectors/sync-engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAS,MAAM,QAAQ,CAAA;AASjE,OAAO,EAAE,SAAS,EAAiB,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAYvE;;;GAGG;AACH,SAAS,iBAAiB,CACxB,MAA+B,EAC/B,MAAoB;IAEpB,IAAI,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC,IAAI,CAAA;IAC/B,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAClF,OAAO,MAAM,CAAC,cAAc,CAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QACf,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;QAC1C,CAAC,CAAA;QACD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QACzD,OAAO,OAAO,CAAA;IAChB,CAAC,CAAC,EACF,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAC7E,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;AACvB,CAAC;AAED,SAAS,sBAAsB,CAC7B,MAA+B;IAE/B,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QACtB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;QACxC,MAAM,CAAC,OAAO,CACZ,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YAC7B,UAAU,CAAC,KAAK,EAAE,CAAA;QACpB,CAAC,CAAC,CACH,CAAA;QACD,OAAO,UAAU,CAAC,MAAM,CAAA;IAC1B,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,EAAU,EAAE,MAAoB;IAC1D,OAAO,MAAM,CAAC,IAAI,CAChB,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EACjC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CACvB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;AACvB,CAAC;AAED,MAAM,MAAM,GAA0B,MAAM,CAAC,GAAG,CAC9C,KAAK,CAAC,iBAAiB,EACvB,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CACnC,CAAA;AAED,+EAA+E;AAE/E,MAAM,UAAU,aAAa,CAAC,EAAqB,EAAE,WAAmB;IACtE,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,2DAA2D,CAAC;SAChF,GAAG,CAAC,WAAW,CAAwC,CAAA;IAE1D,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO;YACL,WAAW;YACX,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,KAAK;YACnB,iBAAiB,EAAE,IAAI;YACvB,kBAAkB,EAAE,IAAI;YACxB,WAAW,EAAE,CAAC;YACd,iBAAiB,EAAE,CAAC;YACpB,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,EAAE;YACd,WAAW,EAAE,IAAI;YACjB,aAAa,EAAE,IAAI;YACnB,gBAAgB,EAAE,IAAI;SACvB,CAAA;IACH,CAAC;IAED,IAAI,UAAU,GAA4B,EAAE,CAAA;IAC5C,IAAI,CAAC;QAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAW,CAAC,CAAA;IAAC,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEtE,OAAO;QACL,WAAW;QACX,UAAU,EAAE,GAAG,CAAC,aAAa,CAAkB;QAC/C,UAAU,EAAE,GAAG,CAAC,cAAc,CAAkB;QAChD,UAAU,EAAE,GAAG,CAAC,aAAa,CAAkB;QAC/C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC3C,iBAAiB,EAAE,GAAG,CAAC,sBAAsB,CAAkB;QAC/D,kBAAkB,EAAE,GAAG,CAAC,uBAAuB,CAAkB;QACjE,WAAW,EAAE,GAAG,CAAC,cAAc,CAAW;QAC1C,iBAAiB,EAAE,GAAG,CAAC,oBAAoB,CAAW;QACtD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAChC,UAAU;QACV,WAAW,EAAE,GAAG,CAAC,eAAe,CAAkB;QAClD,aAAa,EAAE,GAAG,CAAC,iBAAiB,CAAyB;QAC7D,gBAAgB,EAAE,GAAG,CAAC,oBAAoB,CAAkB;KAC7D,CAAA;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAqB,EAAE,KAAgB;IACnE,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;GAqBV,CAAC,CAAC,GAAG,CACJ,KAAK,CAAC,WAAW,EACjB,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,EAClC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAC5C,KAAK,CAAC,iBAAiB,EAAE,KAAK,CAAC,kBAAkB,EACjD,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,iBAAiB,EAC1C,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACrB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,EAChC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAC/D,CAAA;AACH,CAAC;AASD,SAAS,WAAW,CAClB,EAAqB,EACrB,QAAgB,EAChB,WAAmB,EACnB,KAAqB;IAErB,IAAI,QAAQ,GAAG,CAAC,CAAA;IAChB,IAAI,YAAY,GAAG,CAAC,CAAA;IAEpB,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAC1B,gEAAgE,CACjE,CAAA;IACD,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;GAK7B,CAAC,CAAA;IACF,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;GAM7B,CAAC,CAAA;IACF,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CACzB,mFAAmF,CACpF,CAAA;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,SAAS,GAA2B,IAAI,CAAA;QAE5C,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,CAEhD,CAAA;YACb,IAAI,QAAQ,EAAE,CAAC;gBACb,UAAU,CAAC,GAAG,CACZ,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,EACzC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,EAC5D,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,CAC/B,CAAA;gBACD,SAAS,GAAG,QAAQ,CAAC,EAAE,CAAA;gBACvB,YAAY,EAAE,CAAA;YAChB,CAAC;QACH,CAAC;QAED,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CACzB,QAAQ,EAAE,UAAU,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAC9D,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,EAC7D,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,UAAU,EACjE,IAAI,CAAC,OAAO,CACb,CAAA;YACD,SAAS,GAAG,IAAI,CAAC,eAAe,CAAA;YAChC,QAAQ,EAAE,CAAA;QACZ,CAAC;QAED,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IACtC,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAA;AACnC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,EAAqB,EAAE,WAAmB;IAC7E,uCAAuC;IACvC,EAAE,CAAC,OAAO,CAAC,uDAAuD,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACpF,sEAAsE;IACtE,2EAA2E;IAC3E,4EAA4E;IAC5E,iEAAiE;IACjE,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;GAUV,CAAC,CAAC,GAAG,EAAE,CAAA;IACR,uEAAuE;IACvE,0EAA0E;IAC1E,mCAAmC;IACnC,EAAE,CAAC,OAAO,CAAC;;;;;;GAMV,CAAC,CAAC,GAAG,EAAE,CAAA;AACV,CAAC;AAED,+EAA+E;AAE/E,SAAS,WAAW,CAAC,EAAqB;IACxC,wEAAwE;IACxE,uEAAuE;IACvE,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC,GAAG,EAEhE,CAAA;IACb,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;IAC/D,OAAO,GAAG,CAAC,EAAE,CAAA;AACf,CAAC;AAED,SAAS,YAAY,CACnB,EAAqB,EACrB,QAAgB,EAChB,KAAqB;IAErB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACpC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CACrB,uEAAuE,CACxE,CAAA;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAA;IACzE,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,OAAO,UAAU;IACD;IAApB,YAAoB,EAAqB;QAArB,OAAE,GAAF,EAAE,CAAmB;IAAG,CAAC;IAE7C,SAAS,CAAC,WAAmB;QAC3B,OAAO,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,CAAA;IAC5C,CAAC;IAED;;;;;;;;;OASG;IACH,UAAU,CACR,SAAoB,EACpB,OAAoB,EAAE;QAEtB,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;QAClB,MAAM,IAAI,GAAG,IAAI,CAAA;QAEjB,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACzB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAA;YACvE,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAA;YAChD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAQ,CAAC,CAAA;YAC5D,KAAK,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAE7C,MAAM,IAAI,GAAG,SAAS,CAAC,SAAS;gBAC9B,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC;gBACrE,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAA;YAExE,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAC7B,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE;gBAC5B,UAAU,EAAE;oBACV,cAAc,EAAE,SAAS,CAAC,EAAE;oBAC5B,gBAAgB,EAAE,IAAI,CAAC,SAAS,IAAI,MAAM;iBAC3C;aACF,CAAC,CACH,CAAA;YAED,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjB,KAAK,CAAC,iBAAiB,IAAI,CAAC,CAAA;gBAC5B,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC,MAAM,CAAA;gBACjC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,IAAqB,CAAA;gBACxD,KAAK,CAAC,gBAAgB,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAA;YAC/C,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,iBAAiB,GAAG,CAAC,CAAA;gBAC3B,KAAK,CAAC,WAAW,GAAG,IAAI,CAAA;gBACxB,KAAK,CAAC,aAAa,GAAG,IAAI,CAAA;gBAC1B,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAA;YAC/B,CAAC;YACD,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAA;YAClD,OAAO,MAAM,CAAA;YACb,qEAAqE;YACrE,sEAAsE;YACtE,yCAAyC;QAC3C,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAoB,EAAE,OAAoB,EAAE;QACrD,mEAAmE;QACnE,+DAA+D;QAC/D,oEAAoE;QACpE,kEAAkE;QAClE,wEAAwE;QACxE,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAA;QAClE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,qEAAqE;YACrE,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,CAAC,CAAA;YAClD,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACnC,KAAK,CAAC,iBAAiB,IAAI,CAAC,CAAA;YAC5B,KAAK,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;YAC5C,KAAK,CAAC,aAAa,GAAG,OAAO,CAAC,IAAI,CAAA;YAClC,KAAK,CAAC,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAA;YACxC,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;YAC7B,OAAO;gBACL,WAAW,EAAE,SAAS,CAAC,EAAE;gBACzB,KAAK,EAAE,CAAC;gBACR,KAAK,EAAE,KAAK,CAAC,WAAW;gBACxB,KAAK,EAAE,CAAC;gBACR,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,MAAM;gBACnC,UAAU,EAAE,UAAU,OAAO,CAAC,IAAI,EAAE;gBACpC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE;aACxD,CAAA;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,eAAe,CACrB,SAAoB,EACpB,KAAgB,EAChB,IAAqD,EACrD,QAAgB,EAChB,WAA0B,EAC1B,SAAiB,EACjB,MAAoB,EACpB,MAAmB;QAEnB,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,gBAAgB,CAAC,WAAW,CAAA;QAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAA;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAA;QACrC,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,IAAI,CAAC,CAAA;QAC/C,MAAM,eAAe,GAAG,EAAE,CAAA;QAC1B,MAAM,QAAQ,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAA;QAE5F,8EAA8E;QAC9E,2EAA2E;QAC3E,2EAA2E;QAC3E,yEAAyE;QACzE,6DAA6D;QAC7D,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS;eACzC,KAAK,CAAC,UAAU,KAAK,IAAI;eACzB,KAAK,CAAC,UAAU,KAAK,IAAI,CAAA;QAE9B,mEAAmE;QACnE,8DAA8D;QAC9D,mFAAmF;QACnF,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAA;QAEtE,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACzB,IAAI,MAAM,GAAG,WAAW,CAAA;YACxB,IAAI,KAAK,GAAG,CAAC,CAAA;YACb,IAAI,KAAK,GAAG,CAAC,CAAA;YACb,IAAI,UAAU,GAAG,CAAC,CAAA;YAElB,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAA;gBAC1C,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;oBACpB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,CAAA;gBAChD,CAAC;gBACD,IAAI,KAAK,IAAI,QAAQ,EAAE,CAAC;oBACtB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,CAAA;gBAClD,CAAC;gBACD,IAAI,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;oBACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,CAAA;gBAClD,CAAC;gBAED,MAAM,QAAQ,GAAiB,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAA;gBACjF,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAClC,MAAM,CAAC,UAAU,CAAC;oBAChB,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC;oBACxC,KAAK,EAAE,SAAS,CAAC,IAAI;iBACtB,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE;oBAChC,UAAU,EAAE;wBACV,cAAc,EAAE,SAAS,CAAC,EAAE;wBAC5B,YAAY,EAAE,IAAI,CAAC,KAAK;wBACxB,WAAW,EAAE,KAAK,GAAG,CAAC;qBACvB;iBACF,CAAC,CACH,CACF,CAAA;gBAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAC5B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAA;oBACxB,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CACpB,iBAAiB,SAAS,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK,SAAS,KAAK,GAAG,CAAC,WAAW,GAAG,CAAC,OAAO,EAAE,CACtF,CAAA;oBACD,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAA;oBAClD,OAAO;wBACL,KAAK;wBACL,KAAK;wBACL,UAAU,EAAE,UAAU,GAAG,CAAC,IAAI,EAAE;wBAChC,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE;qBAChD,CAAA;gBACH,CAAC;gBAED,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAA;gBAC5B,KAAK,EAAE,CAAA;gBAEP,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;oBACpD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;wBAAE,KAAK,CAAC,UAAU,GAAG,IAAI,CAAA;oBACrD,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU;wBAAE,KAAK,CAAC,YAAY,GAAG,IAAI,CAAA;oBACxD,OAAO;wBACL,KAAK;wBACL,KAAK;wBACL,UAAU,EAAE,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,aAAa;qBAC5E,CAAA;gBACH,CAAC;gBAED,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAC3C,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAC9E,CAAC,IAAI,CACJ,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE;oBAC7B,UAAU,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE;iBACnD,CAAC,CACH,CAAA;gBACD,KAAK,IAAI,QAAQ,CAAA;gBAEjB,yEAAyE;gBACzE,yEAAyE;gBACzE,oEAAoE;gBACpE,kEAAkE;gBAClE,0EAA0E;gBAC1E,wEAAwE;gBACxE,sDAAsD;gBACtD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,CAAC,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;oBACpE,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;oBACjC,IAAI,SAAS,EAAE,UAAU,IAAI,SAAS,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC;wBACvE,KAAK,CAAC,UAAU,GAAG,SAAS,CAAC,UAAU,CAAA;oBACzC,CAAC;gBACH,CAAC;gBAED,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBACpB,MAAM,QAAQ,GAAiB;wBAC7B,WAAW,EAAE,SAAS,CAAC,EAAE;wBACzB,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,IAAI,EAAE,KAAK;wBACX,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;wBAC5B,KAAK;wBACL,OAAO,EAAE,IAAI;qBACd,CAAA;oBACD,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAW,CAAC,QAAQ,CAAC,CAAC,CAAA;gBACtD,CAAC;gBAED,2EAA2E;gBAC3E,2EAA2E;gBAC3E,4EAA4E;gBAC5E,6DAA6D;gBAC7D,yEAAyE;gBACzE,oEAAoE;gBACpE,uEAAuE;gBACvE,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,WAAW,EAAE,CAAC;oBAC5C,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CACjC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,KAAK,WAAW,CACxC,CAAA;oBACD,IAAI,SAAS,EAAE,CAAC;wBACd,KAAK,CAAC,UAAU,GAAG,IAAI,CAAA;wBACvB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,CAAA;oBACtD,CAAC;gBACH,CAAC;gBAED,iEAAiE;gBACjE,IAAI,QAAQ,KAAK,CAAC;oBAAE,UAAU,EAAE,CAAA;;oBAC3B,UAAU,GAAG,CAAC,CAAA;gBACnB,IAAI,UAAU,IAAI,cAAc,EAAE,CAAC;oBACjC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;wBAAE,KAAK,CAAC,UAAU,GAAG,IAAI,CAAA;oBACrD,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU;wBAAE,KAAK,CAAC,YAAY,GAAG,IAAI,CAAA;oBACxD,OAAO;wBACL,KAAK;wBACL,KAAK;wBACL,UAAU,EAAE,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,mBAAmB;qBACzE,CAAA;gBACH,CAAC;gBAED,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;oBACvB,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;wBAAE,KAAK,CAAC,UAAU,GAAG,IAAI,CAAA;oBACrD,IAAI,IAAI,CAAC,KAAK,KAAK,UAAU;wBAAE,KAAK,CAAC,YAAY,GAAG,IAAI,CAAA;oBACxD,OAAO;wBACL,KAAK;wBACL,KAAK;wBACL,UAAU,EAAE,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,aAAa;qBAC5E,CAAA;gBACH,CAAC;gBAED,MAAM,GAAG,MAAM,CAAC,UAAU,CAAA;gBAE1B,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC7B,gEAAgE;oBAChE,8CAA8C;oBAC9C,KAAK,CAAC,UAAU,GAAG,MAAM,CAAA;oBACzB,mEAAmE;oBACnE,IAAI,aAAa;wBAAE,KAAK,CAAC,UAAU,GAAG,MAAM,CAAA;gBAC9C,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,UAAU,GAAG,MAAM,CAAA;gBAC3B,CAAC;gBAED,IAAI,KAAK,GAAG,eAAe,KAAK,CAAC,EAAE,CAAC;oBAClC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAA;gBACpD,CAAC;gBAED,mEAAmE;gBACnE,sEAAsE;gBACtE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAA;gBAC/C,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;gBACrC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAA;gBAC7D,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;oBACpB,KAAK,CAAC,CAAC,kBAAkB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;gBAChD,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,oBAAoB,CAC1B,SAAoB,EACpB,KAAgB,EAChB,IAAiB,EACjB,SAAiB,EACjB,MAAoB;QAEpB,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;QAClB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAA;QAC1C,MAAM,QAAQ,GAAG,WAAW,CAAC,EAAE,CAAC,CAAA;QAChC,MAAM,IAAI,GAAG,IAAI,CAAA;QAEjB,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACzB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAA;YACpD,IAAI,UAAU,GAAG,CAAC,CAAA;YAClB,IAAI,UAAU,GAAG,CAAC,CAAA;YAClB,IAAI,UAAU,GAAG,UAAU,CAAA;YAC3B,IAAI,SAAwD,CAAA;YAE5D,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;gBACpD,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,KAAK,IAAI,CAAA;gBAC3C,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,IAAI;qBACpB,eAAe,CACd,SAAS,EACT,KAAK,EACL,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,EAC7B,QAAQ,EACR,KAAK,CAAC,UAAU,IAAI,IAAI,EACxB,SAAS,EACT,MAAM,EACN,MAAM,CACP;qBACA,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAA;gBAExC,UAAU,IAAI,GAAG,CAAC,KAAK,CAAA;gBACvB,UAAU,IAAI,GAAG,CAAC,KAAK,CAAA;gBACvB,UAAU,GAAG,GAAG,CAAC,UAAU,CAAA;gBAC3B,IAAI,GAAG,CAAC,KAAK;oBAAE,SAAS,GAAG,GAAG,CAAC,KAAK,CAAA;gBACpC,KAAK,CAAC,iBAAiB,GAAG,KAAK,CAAC,CAAC,MAAM,CAAA;gBAEvC,kEAAkE;gBAClE,wEAAwE;gBACxE,uEAAuE;gBACvE,mDAAmD;gBACnD,MAAM,mBAAmB,GAAG,SAAS;uBAChC,GAAG,CAAC,UAAU,KAAK,eAAe;uBAClC,GAAG,CAAC,UAAU,KAAK,SAAS;uBAC5B,GAAG,CAAC,UAAU,KAAK,WAAW;uBAC9B,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;gBACxC,IAAI,mBAAmB,EAAE,CAAC;oBACxB,KAAK,CAAC,UAAU,GAAG,IAAI,CAAA;gBACzB,CAAC;YACH,CAAC;YAED,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,SAAS,KAAK,UAAU,IAAI,SAAS,KAAK,MAAM,CAAC,EAAE,CAAC;gBAC5F,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI;qBACnB,eAAe,CACd,SAAS,EACT,KAAK,EACL,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,EAC9B,QAAQ,EACR,KAAK,CAAC,UAAU,EAChB,SAAS,EACT,MAAM,EACN,MAAM,CACP;qBACA,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAA;gBAEzC,UAAU,IAAI,EAAE,CAAC,KAAK,CAAA;gBACtB,UAAU,IAAI,EAAE,CAAC,KAAK,CAAA;gBACtB,UAAU,GAAG,EAAE,CAAC,UAAU,CAAA;gBAC1B,IAAI,EAAE,CAAC,KAAK;oBAAE,SAAS,GAAG,EAAE,CAAC,KAAK,CAAA;gBAClC,KAAK,CAAC,kBAAkB,GAAG,KAAK,CAAC,CAAC,MAAM,CAAA;YAC1C,CAAC;YAED,KAAK,CAAC,WAAW,IAAI,UAAU,CAAA;YAC/B,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAA;YAElD,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CACnB,iBAAiB,SAAS,CAAC,EAAE,gBAAgB,UAAU,UAAU,UAAU,WAAW,UAAU,EAAE,CACnG,CAAA;YAED,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACpB,MAAM,QAAQ,GAAiB;oBAC7B,WAAW,EAAE,SAAS,CAAC,EAAE;oBACzB,KAAK,EAAE,SAAS;oBAChB,IAAI,EAAE,UAAU;oBAChB,OAAO,EAAE,CAAC;oBACV,KAAK,EAAE,UAAU;oBACjB,OAAO,EAAE,KAAK;iBACf,CAAA;gBACD,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,UAAW,CAAC,QAAQ,CAAC,CAAC,CAAA;YACtD,CAAC;YAED,MAAM,GAAG,GAAwB;gBAC/B,WAAW,EAAE,SAAS,CAAC,EAAE;gBACzB,KAAK,EAAE,UAAU;gBACjB,KAAK,EAAE,KAAK,CAAC,WAAW;gBACxB,KAAK,EAAE,UAAU;gBACjB,SAAS;gBACT,UAAU;aACX,CAAA;YACD,IAAI,SAAS,EAAE,CAAC;gBACd,GAAG,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,IAAqB,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAA;YACnF,CAAC;YACD,OAAO,GAAG,CAAA;QACZ,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,mBAAmB,CACzB,SAAoB,EACpB,KAAgB,EAChB,IAAiB,EACjB,SAAiB,EACjB,MAAoB;QAEpB,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,gBAAgB,CAAC,WAAW,CAAA;QAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAA;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAA;QACrC,MAAM,QAAQ,GAAG,WAAW,CAAC,EAAE,CAAC,CAAA;QAChC,MAAM,QAAQ,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAA;QAE5F,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACzB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAA;YACpD,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CACtB,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,CAC/D,CAAA;YAED,IAAI,MAAM,GAAkB,IAAI,CAAA;YAChC,IAAI,UAAU,GAAG,CAAC,CAAA;YAClB,IAAI,UAAU,GAAG,CAAC,CAAA;YAClB,IAAI,UAAU,GAAG,UAAU,CAAA;YAE3B,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAA;gBAC1C,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;oBACpB,UAAU,GAAG,SAAS,CAAA;oBACtB,MAAK;gBACP,CAAC;gBACD,IAAI,UAAU,IAAI,QAAQ,EAAE,CAAC;oBAC3B,UAAU,GAAG,WAAW,CAAA;oBACxB,MAAK;gBACP,CAAC;gBACD,IAAI,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;oBACnC,UAAU,GAAG,WAAW,CAAA;oBACxB,MAAK;gBACP,CAAC;gBAED,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAClC,MAAM,CAAC,UAAU,CAAC;oBAChB,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;oBACvF,KAAK,EAAE,SAAS,CAAC,IAAI;iBACtB,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,QAAQ,CAAC,gBAAgB,EAAE;oBAChC,UAAU,EAAE;wBACV,cAAc,EAAE,SAAS,CAAC,EAAE;wBAC5B,YAAY,EAAE,SAAS;wBACvB,WAAW,EAAE,UAAU,GAAG,CAAC;qBAC5B;iBACF,CAAC,CACH,CACF,CAAA;gBAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAC5B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAA;oBACxB,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CACpB,iBAAiB,SAAS,CAAC,EAAE,iBAAiB,UAAU,GAAG,CAAC,WAAW,GAAG,CAAC,OAAO,EAAE,CACrF,CAAA;oBACD,KAAK,CAAC,WAAW,GAAG,UAAU,CAAA;oBAC9B,KAAK,CAAC,iBAAiB,GAAG,KAAK,CAAC,CAAC,MAAM,CAAA;oBACvC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAA;oBAClD,OAAO;wBACL,WAAW,EAAE,SAAS,CAAC,EAAE;wBACzB,KAAK,EAAE,UAAU;wBACjB,KAAK,EAAE,UAAU;wBACjB,KAAK,EAAE,UAAU;wBACjB,SAAS,EAAE,SAAS;wBACpB,UAAU,EAAE,UAAU,GAAG,CAAC,IAAI,EAAE;wBAChC,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE;qBAChD,CAAA;gBACH,CAAC;gBAED,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAA;gBAC5B,UAAU,EAAE,CAAA;gBAEZ,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAC3C,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAC9E,CAAC,IAAI,CACJ,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE;oBAC7B,UAAU,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE;iBACnD,CAAC,CACH,CAAA;gBACD,UAAU,IAAI,QAAQ,CAAA;gBAEtB,IAAI,CAAC,MAAM,CAAC,UAAU;oBAAE,MAAK;gBAC7B,MAAM,GAAG,MAAM,CAAC,UAAU,CAAA;gBAE1B,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAA;gBAC/C,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;gBACrC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAA;gBAC7D,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;oBACpB,KAAK,CAAC,CAAC,kBAAkB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;gBAChD,CAAC;YACH,CAAC;YAED,KAAK,CAAC,WAAW,GAAG,UAAU,CAAA;YAC9B,KAAK,CAAC,iBAAiB,GAAG,KAAK,CAAC,CAAC,MAAM,CAAA;YACvC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAA;YAElD,OAAO;gBACL,WAAW,EAAE,SAAS,CAAC,EAAE;gBACzB,KAAK,EAAE,UAAU;gBACjB,KAAK,EAAE,UAAU;gBACjB,KAAK,EAAE,UAAU;gBACjB,SAAS,EAAE,SAAS;gBACpB,UAAU;aACX,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;CACF"}
|