@sixthsummit/ship-testing 0.0.0-stage → 1.2.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/lib/jobs.js ADDED
@@ -0,0 +1,499 @@
1
+ import { backoffDelay, createExecutor, DEFAULT_JOB_RETENTION, JOB_INPUT_LOCATION, systemActor, } from "@sixthsummit/ship-core";
2
+ /** Deterministic process-local lock provider for unit tests. */
3
+ export function createInMemoryLockProvider(clock = () => new Date()) {
4
+ const leases = new Map();
5
+ let sequence = 0;
6
+ const id = (jobId, key) => `${jobId}:${key}`;
7
+ const live = (lease) => lease !== undefined && lease.expiresAt.getTime() > clock().getTime();
8
+ return Object.freeze({
9
+ kind: "ship.lock-provider",
10
+ adapter: "memory",
11
+ acquire: async (jobId, key, ttlMs) => {
12
+ const existing = leases.get(id(jobId, key));
13
+ if (live(existing))
14
+ return undefined;
15
+ sequence += 1;
16
+ const lease = Object.freeze({
17
+ jobId,
18
+ key,
19
+ token: `lease-${sequence}`,
20
+ expiresAt: new Date(clock().getTime() + ttlMs),
21
+ });
22
+ leases.set(id(jobId, key), lease);
23
+ return lease;
24
+ },
25
+ release: async (lease) => {
26
+ const existing = leases.get(id(lease.jobId, lease.key));
27
+ if (existing?.token === lease.token)
28
+ leases.delete(id(lease.jobId, lease.key));
29
+ },
30
+ extend: async (lease, ttlMs) => {
31
+ const existing = leases.get(id(lease.jobId, lease.key));
32
+ if (existing?.token !== lease.token || !live(existing))
33
+ return false;
34
+ leases.set(id(lease.jobId, lease.key), Object.freeze({ ...existing, expiresAt: new Date(clock().getTime() + ttlMs) }));
35
+ return true;
36
+ },
37
+ leases: () => new Map(leases),
38
+ reset: () => leases.clear(),
39
+ });
40
+ }
41
+ const TERMINAL = new Set(["completed", "failed", "discarded"]);
42
+ /**
43
+ * Deterministic in-memory job backend for unit tests and the conformance suite.
44
+ * It implements the same claim, per-key fairness, retry, dead-letter,
45
+ * schedule reconciliation and retention semantics adapters are expected to,
46
+ * without any external service.
47
+ */
48
+ export function createInMemoryJobBackend(options = {}) {
49
+ const clock = options.clock ?? (() => new Date());
50
+ const budget = Object.freeze({
51
+ maxInFlight: options.maxInFlight ?? 4,
52
+ maxQueueDepth: options.maxQueueDepth ?? 100,
53
+ });
54
+ const pollMs = options.pollMs ?? 5;
55
+ let runs = [];
56
+ let sequence = 0;
57
+ let binding;
58
+ let quitting = false;
59
+ let timer;
60
+ let workerBudget = budget;
61
+ const schedules = new Map();
62
+ const cursors = new Map();
63
+ const inFlight = new Set();
64
+ const lastRunAt = new Map();
65
+ const lastSuccessAt = new Map();
66
+ const declaration = (jobId) => {
67
+ const found = binding?.jobs.find((job) => job.id === jobId);
68
+ if (!found)
69
+ throw new Error(`in-memory job backend knows no job ${JSON.stringify(jobId)}`);
70
+ return found;
71
+ };
72
+ const enqueue = async (jobId, input, enqueueOptions = {}) => {
73
+ const job = declaration(jobId);
74
+ if (enqueueOptions.dedupeKey !== undefined &&
75
+ runs.some((run) => run.jobId === jobId &&
76
+ run.dedupeKey === enqueueOptions.dedupeKey &&
77
+ !TERMINAL.has(run.status))) {
78
+ const existing = runs.find((run) => run.jobId === jobId &&
79
+ run.dedupeKey === enqueueOptions.dedupeKey &&
80
+ !TERMINAL.has(run.status));
81
+ return Object.freeze({ accepted: true, runId: existing.runId, deduplicated: true });
82
+ }
83
+ const queued = runs.filter((run) => run.jobId === jobId && (run.status === "waiting" || run.status === "delayed")).length;
84
+ if (queued >= budget.maxQueueDepth) {
85
+ return Object.freeze({ accepted: false, rejected: "queue-full" });
86
+ }
87
+ sequence += 1;
88
+ const now = clock();
89
+ const delayMs = enqueueOptions.delayMs ?? 0;
90
+ const run = {
91
+ runId: `${jobId}:${sequence}`,
92
+ jobId,
93
+ input,
94
+ ...(job.key ? { key: job.key(input) } : {}),
95
+ ...(enqueueOptions.dedupeKey !== undefined ? { dedupeKey: enqueueOptions.dedupeKey } : {}),
96
+ status: delayMs > 0 ? "delayed" : "waiting",
97
+ attempts: 0,
98
+ history: [],
99
+ createdAt: now,
100
+ availableAt: new Date(now.getTime() + delayMs),
101
+ };
102
+ runs.push(run);
103
+ return Object.freeze({ accepted: true, runId: run.runId, deduplicated: false });
104
+ };
105
+ const schedule = async (jobId, trigger) => {
106
+ declaration(jobId);
107
+ schedules.set(jobId, { trigger, nextAt: nextOccurrence(trigger, clock()) });
108
+ };
109
+ const tick = async (now = clock()) => {
110
+ let enqueued = 0;
111
+ for (const [jobId, entry] of [...schedules].sort(([left], [right]) => left.localeCompare(right))) {
112
+ let nextAt = entry.nextAt;
113
+ while (nextAt.getTime() <= now.getTime()) {
114
+ const runId = `${jobId}:${nextAt.toISOString()}`;
115
+ if (!runs.some((run) => run.runId === runId)) {
116
+ runs.push({
117
+ runId,
118
+ jobId,
119
+ input: {},
120
+ status: "waiting",
121
+ attempts: 0,
122
+ history: [],
123
+ createdAt: nextAt,
124
+ availableAt: nextAt,
125
+ });
126
+ enqueued += 1;
127
+ }
128
+ nextAt = nextOccurrence(entry.trigger, nextAt);
129
+ }
130
+ schedules.set(jobId, { trigger: entry.trigger, nextAt });
131
+ }
132
+ return enqueued;
133
+ };
134
+ const claimable = (now) => {
135
+ if (!binding)
136
+ return undefined;
137
+ if (inFlight.size >= workerBudget.maxInFlight)
138
+ return undefined;
139
+ for (const run of runs) {
140
+ if (run.status === "delayed" && run.availableAt.getTime() <= now.getTime()) {
141
+ run.status = "waiting";
142
+ }
143
+ }
144
+ const jobIds = [
145
+ ...new Set(runs.filter((run) => run.status === "waiting").map((run) => run.jobId)),
146
+ ].sort();
147
+ for (const jobId of jobIds) {
148
+ const job = declaration(jobId);
149
+ const active = runs.filter((run) => run.jobId === jobId && run.status === "active");
150
+ if (active.length >= job.concurrency.max)
151
+ continue;
152
+ const waiting = runs.filter((run) => run.jobId === jobId &&
153
+ run.status === "waiting" &&
154
+ run.availableAt.getTime() <= now.getTime());
155
+ if (waiting.length === 0)
156
+ continue;
157
+ // Round-robin: continue from the key after the one claimed last time.
158
+ const keys = [...new Set(waiting.map((run) => run.key ?? ""))].sort();
159
+ const last = cursors.get(jobId);
160
+ const start = last === undefined ? 0 : keys.findIndex((key) => key > last);
161
+ const offset = start < 0 ? 0 : start;
162
+ for (let step = 0; step < keys.length; step += 1) {
163
+ const key = keys[(offset + step) % keys.length];
164
+ if (job.concurrency.mode === "single-runner" &&
165
+ active.some((run) => (run.key ?? "") === key)) {
166
+ continue;
167
+ }
168
+ const candidate = waiting.find((run) => (run.key ?? "") === key);
169
+ if (!candidate)
170
+ continue;
171
+ cursors.set(jobId, key);
172
+ return candidate;
173
+ }
174
+ }
175
+ return undefined;
176
+ };
177
+ const execute = async (run) => {
178
+ const job = declaration(run.jobId);
179
+ const bound = binding;
180
+ run.status = "active";
181
+ run.attempts += 1;
182
+ run.startedAt = clock();
183
+ lastRunAt.set(run.jobId, run.startedAt);
184
+ const outcome = await bound.execute(run.jobId, run.input, {
185
+ runId: run.runId,
186
+ attempt: run.attempts,
187
+ ...(run.key !== undefined ? { key: run.key } : {}),
188
+ });
189
+ const now = clock();
190
+ if (outcome.ok) {
191
+ run.status = "completed";
192
+ run.completedAt = now;
193
+ lastSuccessAt.set(run.jobId, now);
194
+ return "completed";
195
+ }
196
+ if (outcome.lockHeld) {
197
+ // Contention is not a failed attempt; wait one backoff step and try again.
198
+ run.attempts -= 1;
199
+ run.status = "delayed";
200
+ run.availableAt = new Date(now.getTime() + backoffDelay(job.retry.backoff, 1));
201
+ return "retried";
202
+ }
203
+ run.history.push({ attempt: run.attempts, error: outcome.error, at: now });
204
+ run.lastError = outcome.error;
205
+ if (!outcome.retryable || run.attempts >= job.retry.attempts) {
206
+ run.status = "failed";
207
+ run.failedAt = now;
208
+ return "failed";
209
+ }
210
+ run.status = "delayed";
211
+ run.availableAt = new Date(now.getTime() + backoffDelay(job.retry.backoff, run.attempts));
212
+ return "retried";
213
+ };
214
+ const processOnce = async () => {
215
+ const run = claimable(clock());
216
+ if (!run)
217
+ return false;
218
+ const pending = execute(run).then(() => undefined, () => undefined);
219
+ inFlight.add(pending);
220
+ await pending;
221
+ inFlight.delete(pending);
222
+ return true;
223
+ };
224
+ const drain = async (drainOptions = {}) => {
225
+ const maxRuns = drainOptions.maxRuns ?? 1_000;
226
+ let executed = 0;
227
+ let completed = 0;
228
+ let failed = 0;
229
+ await tick();
230
+ while (true) {
231
+ const run = claimable(clock());
232
+ if (!run)
233
+ return Object.freeze({ executed, completed, failed });
234
+ if (executed >= maxRuns) {
235
+ throw new Error(`in-memory job backend still had runnable runs after ${maxRuns} runs`);
236
+ }
237
+ const result = await execute(run);
238
+ executed += 1;
239
+ if (result === "completed")
240
+ completed += 1;
241
+ if (result === "failed")
242
+ failed += 1;
243
+ }
244
+ };
245
+ const startWorkers = async (mode, override = {}) => {
246
+ workerBudget = Object.freeze({ ...budget, ...override });
247
+ if (mode === "api" || timer !== undefined)
248
+ return timer === undefined ? 0 : 1;
249
+ quitting = false;
250
+ timer = setInterval(() => {
251
+ if (quitting)
252
+ return;
253
+ void tick().then(async () => {
254
+ while (!quitting && (await processOnce())) {
255
+ // keep claiming until nothing is runnable
256
+ }
257
+ });
258
+ }, pollMs);
259
+ if (typeof timer === "object" && timer !== null && "unref" in timer) {
260
+ timer.unref();
261
+ }
262
+ return 1;
263
+ };
264
+ const quit = async () => {
265
+ quitting = true;
266
+ if (timer !== undefined) {
267
+ clearInterval(timer);
268
+ timer = undefined;
269
+ }
270
+ await Promise.all([...inFlight]);
271
+ };
272
+ const health = async (now) => {
273
+ for (const run of runs) {
274
+ if (run.status === "delayed" && run.availableAt.getTime() <= now.getTime()) {
275
+ run.status = "waiting";
276
+ }
277
+ }
278
+ const jobIds = [
279
+ ...new Set([...(binding?.jobs ?? []).map((job) => job.id), ...runs.map((run) => run.jobId)]),
280
+ ].sort();
281
+ const entries = jobIds.map((jobId) => {
282
+ const own = runs.filter((run) => run.jobId === jobId);
283
+ const waiting = own.filter((run) => run.status === "waiting");
284
+ const oldest = waiting.reduce((best, run) => (best === undefined || run.availableAt < best ? run.availableAt : best), undefined);
285
+ const lastRun = lastRunAt.get(jobId);
286
+ const lastSuccess = lastSuccessAt.get(jobId);
287
+ return Object.freeze({
288
+ jobId,
289
+ waiting: waiting.length,
290
+ active: own.filter((run) => run.status === "active").length,
291
+ delayed: own.filter((run) => run.status === "delayed").length,
292
+ failed: own.filter((run) => run.status === "failed").length,
293
+ lagMs: oldest ? Math.max(0, now.getTime() - oldest.getTime()) : 0,
294
+ ...(lastRun ? { lastRunAt: lastRun } : {}),
295
+ ...(lastSuccess ? { lastSuccessAt: lastSuccess } : {}),
296
+ });
297
+ });
298
+ return Object.freeze({ jobs: Object.freeze(entries) });
299
+ };
300
+ const listFailed = async ({ limit }) => Object.freeze(runs
301
+ .filter((run) => run.status === "failed")
302
+ .sort((left, right) => (left.failedAt?.getTime() ?? 0) - (right.failedAt?.getTime() ?? 0))
303
+ .slice(0, limit)
304
+ .map(snapshot));
305
+ const retry = async (runId) => {
306
+ const run = runs.find((item) => item.runId === runId);
307
+ if (!run || run.status !== "failed")
308
+ return undefined;
309
+ run.status = "waiting";
310
+ run.availableAt = clock();
311
+ run.failedAt = undefined;
312
+ return snapshot(run);
313
+ };
314
+ const discard = async (runId, reason) => {
315
+ const run = runs.find((item) => item.runId === runId);
316
+ if (!run || run.status !== "failed")
317
+ return undefined;
318
+ run.status = "discarded";
319
+ run.discardedAt = clock();
320
+ run.discardReason = reason;
321
+ return snapshot(run);
322
+ };
323
+ const cleanup = async (now) => {
324
+ let completedDeleted = 0;
325
+ let deadLetteredDeleted = 0;
326
+ runs = runs.filter((run) => {
327
+ const retention = binding?.jobs.find((job) => job.id === run.jobId)?.retention ?? DEFAULT_JOB_RETENTION;
328
+ if (run.status === "completed" &&
329
+ run.completedAt &&
330
+ now.getTime() - run.completedAt.getTime() >= retention.completedMs) {
331
+ completedDeleted += 1;
332
+ return false;
333
+ }
334
+ const terminalAt = run.status === "failed" ? run.failedAt : run.discardedAt;
335
+ if ((run.status === "failed" || run.status === "discarded") &&
336
+ terminalAt &&
337
+ now.getTime() - terminalAt.getTime() >= retention.deadLetteredMs) {
338
+ deadLetteredDeleted += 1;
339
+ return false;
340
+ }
341
+ return true;
342
+ });
343
+ return Object.freeze({ completedDeleted, deadLetteredDeleted });
344
+ };
345
+ return Object.freeze({
346
+ kind: "ship.job-backend",
347
+ adapter: "memory",
348
+ concurrencyBudget: budget,
349
+ attach: (value) => {
350
+ binding = value;
351
+ },
352
+ enqueue,
353
+ schedule,
354
+ unschedule: async (jobId) => {
355
+ schedules.delete(jobId);
356
+ },
357
+ startWorkers,
358
+ quit,
359
+ health,
360
+ listFailed,
361
+ retry,
362
+ discard,
363
+ cleanup,
364
+ runs: () => Object.freeze(runs.map(snapshot)),
365
+ schedules: () => Object.freeze([...schedules]
366
+ .sort(([left], [right]) => left.localeCompare(right))
367
+ .map(([jobId, entry]) => Object.freeze({ jobId, trigger: entry.trigger, nextAt: entry.nextAt }))),
368
+ tick,
369
+ drain,
370
+ reset: () => {
371
+ runs = [];
372
+ sequence = 0;
373
+ schedules.clear();
374
+ cursors.clear();
375
+ lastRunAt.clear();
376
+ lastSuccessAt.clear();
377
+ },
378
+ });
379
+ }
380
+ function snapshot(run) {
381
+ return Object.freeze({
382
+ runId: run.runId,
383
+ jobId: run.jobId,
384
+ input: run.input,
385
+ ...(run.key !== undefined ? { key: run.key } : {}),
386
+ ...(run.dedupeKey !== undefined ? { dedupeKey: run.dedupeKey } : {}),
387
+ status: run.status,
388
+ attempts: run.attempts,
389
+ ...(run.lastError !== undefined ? { lastError: run.lastError } : {}),
390
+ history: Object.freeze(run.history.map((item) => Object.freeze({ ...item }))),
391
+ createdAt: run.createdAt,
392
+ availableAt: run.availableAt,
393
+ ...(run.startedAt ? { startedAt: run.startedAt } : {}),
394
+ ...(run.completedAt ? { completedAt: run.completedAt } : {}),
395
+ ...(run.failedAt ? { failedAt: run.failedAt } : {}),
396
+ ...(run.discardedAt ? { discardedAt: run.discardedAt } : {}),
397
+ ...(run.discardReason !== undefined ? { discardReason: run.discardReason } : {}),
398
+ });
399
+ }
400
+ // ---------------------------------------------------------------------------
401
+ // Schedules
402
+ // ---------------------------------------------------------------------------
403
+ /** The first occurrence strictly after `from` for an interval or cron trigger. */
404
+ export function nextOccurrence(trigger, from) {
405
+ if (trigger.kind === "interval")
406
+ return new Date(from.getTime() + trigger.everyMs);
407
+ const fields = parseCron(trigger.cron);
408
+ const start = Math.floor(from.getTime() / 60_000) * 60_000 + 60_000;
409
+ const limit = start + 366 * 24 * 60 * 60_000;
410
+ let candidate = start;
411
+ while (candidate < limit) {
412
+ const parts = localParts(new Date(candidate), trigger.tz);
413
+ const toNextHour = (60 - parts.minute) * 60_000;
414
+ if (!fields.dayOfMonth.has(parts.day) ||
415
+ !fields.month.has(parts.month) ||
416
+ !fields.dayOfWeek.has(parts.weekday)) {
417
+ candidate += toNextHour;
418
+ }
419
+ else if (!fields.hour.has(parts.hour)) {
420
+ candidate += toNextHour;
421
+ }
422
+ else if (!fields.minute.has(parts.minute)) {
423
+ candidate += 60_000;
424
+ }
425
+ else {
426
+ return new Date(candidate);
427
+ }
428
+ }
429
+ throw new Error(`cron expression ${JSON.stringify(trigger.cron)} has no occurrence within a year`);
430
+ }
431
+ function parseCron(expression) {
432
+ const parts = expression.trim().split(/\s+/u);
433
+ const [minute, hour, dayOfMonth, month, dayOfWeek] = parts.length === 6 ? parts.slice(1) : parts;
434
+ return {
435
+ minute: parseField(minute, 0, 59),
436
+ hour: parseField(hour, 0, 23),
437
+ dayOfMonth: parseField(dayOfMonth, 1, 31),
438
+ month: parseField(month, 1, 12),
439
+ dayOfWeek: new Set([...parseField(dayOfWeek, 0, 7)].map((day) => day % 7)),
440
+ };
441
+ }
442
+ function parseField(field, minimum, maximum) {
443
+ const values = new Set();
444
+ for (const part of field.split(",")) {
445
+ const [range, stepText] = part.split("/");
446
+ const step = stepText === undefined ? 1 : Number(stepText);
447
+ let low = minimum;
448
+ let high = maximum;
449
+ if (range !== "*") {
450
+ const [lowText, highText] = range.split("-");
451
+ low = Number(lowText);
452
+ high = highText === undefined ? (stepText === undefined ? low : maximum) : Number(highText);
453
+ }
454
+ if (!Number.isInteger(low) || !Number.isInteger(high) || !Number.isInteger(step) || step <= 0) {
455
+ throw new Error(`unsupported cron field ${JSON.stringify(field)}`);
456
+ }
457
+ for (let value = low; value <= high; value += step)
458
+ values.add(value);
459
+ }
460
+ return values;
461
+ }
462
+ const formatters = new Map();
463
+ function localParts(date, tz) {
464
+ let formatter = formatters.get(tz);
465
+ if (!formatter) {
466
+ formatter = new Intl.DateTimeFormat("en-US", {
467
+ timeZone: tz,
468
+ hourCycle: "h23",
469
+ minute: "numeric",
470
+ hour: "numeric",
471
+ day: "numeric",
472
+ month: "numeric",
473
+ weekday: "short",
474
+ });
475
+ formatters.set(tz, formatter);
476
+ }
477
+ const parts = Object.fromEntries(formatter.formatToParts(date).map((part) => [part.type, part.value]));
478
+ return {
479
+ minute: Number(parts.minute),
480
+ hour: Number(parts.hour) % 24,
481
+ day: Number(parts.day),
482
+ month: Number(parts.month),
483
+ weekday: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].indexOf(parts.weekday),
484
+ };
485
+ }
486
+ /**
487
+ * Runs one job through the executor exactly as a backend would, as a system
488
+ * actor with no permissions, and returns the executor result. Single-runner
489
+ * jobs still take their lease, so an application must bind a lock provider.
490
+ */
491
+ export async function runJobOnce(app, jobId, input, options = {}) {
492
+ const executor = options.executor ?? createExecutor(app);
493
+ const actor = options.actor ?? systemActor({ id: "ship.testing.jobs" });
494
+ return (await executor.run(jobId, { [JOB_INPUT_LOCATION]: input }, {
495
+ actor,
496
+ ...(options.requestId ? { requestId: options.requestId } : {}),
497
+ }));
498
+ }
499
+ //# sourceMappingURL=jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../src/jobs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { AnyModule, AnyOutbox, ApplicationExecutor, CompiledApplication, IdempotencyStore, OperationActor, OutboxBackend, OutboxDispatchResult, OutboxRecord } from "@sixthsummit/ship-core";
2
+ /**
3
+ * Deterministic in-memory outbox backend for unit tests.
4
+ *
5
+ * It ignores the unit-of-work scope, so intents are visible as soon as
6
+ * `enqueue()` resolves even if the surrounding fake transaction later fails.
7
+ * Use the Drizzle backend with a real database to prove rollback semantics.
8
+ */
9
+ export interface InMemoryOutbox extends OutboxBackend {
10
+ readonly adapter: "memory";
11
+ /** Snapshot of every stored record, oldest first. */
12
+ readonly records: () => readonly OutboxRecord[];
13
+ readonly reset: () => void;
14
+ }
15
+ export declare function createInMemoryOutbox(outbox: AnyOutbox): InMemoryOutbox;
16
+ /** Deterministic in-memory idempotency store for unit tests. */
17
+ export interface InMemoryIdempotencyStore extends IdempotencyStore {
18
+ readonly adapter: "memory";
19
+ readonly reset: () => void;
20
+ /** Deletes entries that expired before `before`, optionally only under a key prefix; returns the count. */
21
+ readonly purgeExpired: (before: Date, prefix?: string) => number;
22
+ }
23
+ export declare function createInMemoryIdempotencyStore(): InMemoryIdempotencyStore;
24
+ export interface DrainOutboxOptions {
25
+ /** Defaults to a system actor named `ship.testing.drain`. */
26
+ readonly actor?: OperationActor;
27
+ /** Safety bound on dispatcher runs; defaults to 100. */
28
+ readonly maxRuns?: number;
29
+ }
30
+ /**
31
+ * Runs `<outbox>.dispatch` until a pass claims nothing and returns the totals.
32
+ * Pair it with `createInMemoryOutbox()` in unit tests to assert on effects.
33
+ */
34
+ export declare function drainOutbox(executor: ApplicationExecutor<CompiledApplication<string, readonly AnyModule[]>>, outbox: AnyOutbox | string, options?: DrainOutboxOptions): Promise<OutboxDispatchResult>;
35
+ //# sourceMappingURL=outbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../src/outbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EAGnB,gBAAgB,EAChB,cAAc,EACd,aAAa,EAEb,oBAAoB,EAIpB,YAAY,EAGb,MAAM,wBAAwB,CAAC;AAGhC;;;;;;GAMG;AACH,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,MAAM,SAAS,YAAY,EAAE,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,cAAc,CAqMtE;AAED,gEAAgE;AAChE,MAAM,WAAW,wBAAyB,SAAQ,gBAAgB;IAChE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;IAC3B,2GAA2G;IAC3G,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CAClE;AAED,wBAAgB,8BAA8B,IAAI,wBAAwB,CAgDzE;AAED,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;IAChC,wDAAwD;IACxD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,mBAAmB,CAAC,mBAAmB,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC,EAChF,MAAM,EAAE,SAAS,GAAG,MAAM,EAC1B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CAuB/B"}