pm-csv 2026.10.28 → 2026.10.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -2
- package/dist/admission.d.ts +93 -0
- package/dist/admission.d.ts.map +1 -0
- package/dist/admission.js +362 -0
- package/dist/admission.js.map +1 -0
- package/dist/atomic-update.d.ts.map +1 -1
- package/dist/atomic-update.js +16 -14
- package/dist/atomic-update.js.map +1 -1
- package/dist/edit-refusal.d.ts +1 -1
- package/dist/edit-refusal.d.ts.map +1 -1
- package/dist/index.d.ts +46 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +364 -117
- package/dist/index.js.map +1 -1
- package/dist/join-plans.d.ts +110 -0
- package/dist/join-plans.d.ts.map +1 -0
- package/dist/join-plans.js +557 -0
- package/dist/join-plans.js.map +1 -0
- package/dist/lineage.d.ts +3 -6
- package/dist/lineage.d.ts.map +1 -1
- package/dist/lineage.js +32 -11
- package/dist/lineage.js.map +1 -1
- package/dist/mutation-intent.d.ts +57 -0
- package/dist/mutation-intent.d.ts.map +1 -0
- package/dist/mutation-intent.js +145 -0
- package/dist/mutation-intent.js.map +1 -0
- package/dist/roundtrip.d.ts +2 -8
- package/dist/roundtrip.d.ts.map +1 -1
- package/dist/roundtrip.js +78 -24
- package/dist/roundtrip.js.map +1 -1
- package/dist/settings-snapshot.d.ts +37 -0
- package/dist/settings-snapshot.d.ts.map +1 -0
- package/dist/settings-snapshot.js +128 -0
- package/dist/settings-snapshot.js.map +1 -0
- package/dist/table-schema.d.ts +10 -7
- package/dist/table-schema.d.ts.map +1 -1
- package/dist/table-schema.js +36 -12
- package/dist/table-schema.js.map +1 -1
- package/docs/import-admission.md +199 -0
- package/docs/join-plans.md +201 -0
- package/docs/join-validation.md +240 -0
- package/docs/spreadsheet-roundtrip.md +17 -2
- package/manifest.json +1 -1
- package/package.json +10 -6
package/README.md
CHANGED
|
@@ -42,11 +42,32 @@ tracker without a Git repository. None of these commands requires Git.
|
|
|
42
42
|
| `pm csv import <file>` | Import a required CSV file; `--dry-run` previews without writes. |
|
|
43
43
|
| `pm csv-import import <file>` | Same required file, flags, implementation and results as `csv import`. |
|
|
44
44
|
| `pm csv validate <file>` | Validate a CSV file without writes. |
|
|
45
|
+
| `pm csv admit <file>` | Stream bounded initial/full validation, counts, widths and mutation upper bounds without writes. |
|
|
45
46
|
| `pm csv export` / `pm csv-export export` | Export tracker items as CSV. |
|
|
46
47
|
| `pm csv schema describe <file>` | Propose a reusable versioned table schema with `--output schema.json`. |
|
|
47
48
|
| `pm csv schema preview <file> --schema schema.json` | Refuse changed dialect, columns, domains or target contracts without writes. |
|
|
48
49
|
| `pm csv schema import <file> --schema schema.json` | Negotiate before importing through the existing mutation core; `--dry-run` is read-only. |
|
|
49
50
|
|
|
51
|
+
### Bounded import admission
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
pm csv admit large.csv --initial-rows 1000 --json
|
|
55
|
+
pm csv admit large.csv --json
|
|
56
|
+
pm csv import reviewed.csv --atomic --admission --json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Full admission reports exact row counts, column widths, mutation upper bounds
|
|
60
|
+
and explicit resource limits. Initial observations report prefix counts and never
|
|
61
|
+
authorize apply. A million-row regression runs below a fixed 128 MiB heap cap;
|
|
62
|
+
atomic application separately requires at most 1,000 rows and 8 MiB. The opt-in
|
|
63
|
+
import guard finishes full validation and binds the captured source bytes before
|
|
64
|
+
any mutation, so an invalid final row refuses the entire admitted import.
|
|
65
|
+
|
|
66
|
+
The typed SDK, limit/refusal tables and an example are in
|
|
67
|
+
[bounded import admission](docs/import-admission.md). All admission commands work
|
|
68
|
+
without git. SDK transaction coordination does not isolate ordinary SDK/CLI
|
|
69
|
+
writers; the remaining target read/write window is documented there.
|
|
70
|
+
|
|
50
71
|
### Versioned table schema negotiation
|
|
51
72
|
|
|
52
73
|
Save a reviewed mapping once and reuse it without silently reinterpreting a
|
|
@@ -84,9 +105,24 @@ pm csv import legacy.csv --encoding latin1 # non-UTF-8 source
|
|
|
84
105
|
pm csv import sprint12.csv --source 'jira-export-2026-06'
|
|
85
106
|
pm csv import vendor.csv --strict # fail before writing on bad row data
|
|
86
107
|
pm csv import items.csv --dry-run
|
|
87
|
-
pm csv import tasks.csv --atomic #
|
|
108
|
+
pm csv import tasks.csv --atomic # SDK-coordinated, crash-recoverable import
|
|
88
109
|
```
|
|
89
110
|
|
|
111
|
+
**Column ownership on keyed updates:** an absent header means “do not touch”.
|
|
112
|
+
Empty cells also leave existing values alone. A nonempty cell sets a supported
|
|
113
|
+
field; `none` or `null` (case-insensitive) explicitly clears a supported nullable scope
|
|
114
|
+
field: `parent`, `assignee`, `sprint`, `release` or `blocked_by`. Tags are additive;
|
|
115
|
+
`blocked_by` adds a blocker without deleting other dependency edges. Custom fields
|
|
116
|
+
are export-only and remain unchanged on import. Thus a title-only `--key title`
|
|
117
|
+
reimport preserves status, assignment, planning fields, body, links and custom data.
|
|
118
|
+
New items explicitly suppress implicit focus parents and planning defaults.
|
|
119
|
+
Spreadsheet edit sessions have their own documented explicit-clear contract.
|
|
120
|
+
Replay compares command values through SDK field normalization: local parents such
|
|
121
|
+
as `abcd`, `#ABCD` and `pm-abcd` resolve using the tracker prefix; provider locators
|
|
122
|
+
retain their native spelling. Assignment/planning whitespace and clear aliases
|
|
123
|
+
follow native command semantics. Stored edit-session values instead use SDK document
|
|
124
|
+
canonicalization, preserving literal strings such as `none`.
|
|
125
|
+
|
|
90
126
|
**Flags**
|
|
91
127
|
|
|
92
128
|
| Flag | Type | Default | Description |
|
|
@@ -102,7 +138,8 @@ pm csv import tasks.csv --atomic # writer-locked, crash-recoverable import
|
|
|
102
138
|
| `--priority <n>` | integer | — | Import **only** rows whose integer priority equals this value |
|
|
103
139
|
| `--strict` | boolean | false | Abort before writing if validation finds missing titles, unknown statuses, invalid/out-of-range priorities, or duplicate mapped columns |
|
|
104
140
|
| `--dry-run` | boolean | false | Preview what would be imported without writing any data |
|
|
105
|
-
| `--
|
|
141
|
+
| `--admission` | boolean | false | Finish bounded full validation and enforce atomic row/byte budgets before application; requires `--atomic` |
|
|
142
|
+
| `--atomic` | boolean | false | Use one SDK-coordinated, crash-recoverable transaction. On failure, attempt best-effort create compensation; pre-existing updates restore captured prior values unless a conflict prevents safe compensation. Inspect and reconcile any marked orphan before retrying. Incompatible with `--stream` |
|
|
106
143
|
|
|
107
144
|
#### Strict import gate
|
|
108
145
|
|
|
@@ -533,3 +570,50 @@ keys make unchanged retries idempotent. The compact TOON/JSON receipt reports
|
|
|
533
570
|
counts; artifacts include SHA-256 checksums. See the [protocol and worked
|
|
534
571
|
example](docs/row-lineage.md) for the typed SDK, mapping revisions, refusals,
|
|
535
572
|
privacy policy and recovery behavior.
|
|
573
|
+
|
|
574
|
+
## Cross-table reference joins
|
|
575
|
+
|
|
576
|
+
Resolve explicit external-key parent and dependency columns across selected tables
|
|
577
|
+
in one preview, then apply the reviewed source digests through SDK transactions.
|
|
578
|
+
|
|
579
|
+
```sh
|
|
580
|
+
pm csv join preview joins.json --output reviewed.json --json
|
|
581
|
+
pm csv join apply reviewed.json --json
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
Duplicate or unresolved keys include cell coordinates and block import. See the
|
|
585
|
+
[three-table example, typed SDK API, bounds and recovery contract](docs/join-plans.md).
|
|
586
|
+
These create-only plans work without git. Retain the reviewed artifact for crash
|
|
587
|
+
recovery. Ordinary failures compensate unchanged owned creates and retain native
|
|
588
|
+
delete history; interrupted cleanup revalidates every target before continuing.
|
|
589
|
+
After compensation, preview fresh identities. Configured type/field lookups never
|
|
590
|
+
accept inherited object properties, while prototype-looking external keys remain
|
|
591
|
+
literal data. Foreign records and peer edits are preserved.
|
|
592
|
+
|
|
593
|
+
Saved join and checkout IDs must use distinct canonical native spellings under
|
|
594
|
+
the reviewed SDK prefix. All IDs validate before target leases or writes;
|
|
595
|
+
`abcd` and `review-abcd` cannot identify two rows with prefix `review`, even in
|
|
596
|
+
a correctly rehashed artifact. Preview a fresh plan after `csv_join_invalid`.
|
|
597
|
+
|
|
598
|
+
Join journal identity covers the full reviewed plan, independent of current
|
|
599
|
+
foreign-row eligibility. Retry resumes pending compensation under its recorded
|
|
600
|
+
key and step list before new work. Historical subset journals remain recoverable;
|
|
601
|
+
convergent spreadsheet values cannot bypass their cleanup. Atomic CSV retry with
|
|
602
|
+
changed filters or mappings refuses when it would shrink or change an existing
|
|
603
|
+
journal's row domain: resume using the original options to finish recovery first.
|
|
604
|
+
|
|
605
|
+
Join planning captures one settings/schema snapshot. Create type and status
|
|
606
|
+
defaults are resolved from that snapshot before writes; every mutation batch
|
|
607
|
+
rechecks its digest inside SDK writer coordination. A settings change between
|
|
608
|
+
rows returns `csv_join_settings_changed` and compensates unchanged owned creates.
|
|
609
|
+
Recovery uses one separately guarded current-policy snapshot for cleanup. Peer
|
|
610
|
+
edits or further policy changes can require journal reconciliation. Inputs and
|
|
611
|
+
the tracker root are captured before asynchronous SDK reads, so caller edits or
|
|
612
|
+
working-directory changes cannot redirect an in-flight plan.
|
|
613
|
+
|
|
614
|
+
CSV mutations use explicit source-owned scope: missing or empty create parents
|
|
615
|
+
are unset through the SDK, so session focus cannot add links. Empty supported
|
|
616
|
+
scope cells preserve legacy keyed-import state; spreadsheet patches preserve
|
|
617
|
+
unselected fields. Join replay refuses unreviewed stored scope. Public join
|
|
618
|
+
failures consistently use `JoinRefusal`, with lower-level `sourceCode` and remedy
|
|
619
|
+
retained. See [scope and refusal contracts](docs/join-plans.md#explicit-scope-and-refusal-boundaries).
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { PmCliError } from "@unbrained/pm-cli/sdk";
|
|
2
|
+
import type { ExtensionApi } from "@unbrained/pm-cli/sdk/authoring";
|
|
3
|
+
import type { PmSettings } from "@unbrained/pm-cli/sdk";
|
|
4
|
+
import type { ImportRowFilter } from "./index.ts";
|
|
5
|
+
/** Hard allocation and materialization ceilings; callers can only lower them. Units are UTF-16 code units unless named bytes. */
|
|
6
|
+
export declare const ADMISSION_LIMITS: Readonly<Record<"maxFieldCodeUnits" | "maxRecordCodeUnits" | "maxColumns" | "maxAtomicBytes" | "maxAtomicRows" | "maxSourceBytes", number>>;
|
|
7
|
+
/** One strict SDK/CLI boundary; initial scans never authorize apply. */
|
|
8
|
+
export interface AdmissionOptions {
|
|
9
|
+
mode?: "initial" | "full";
|
|
10
|
+
initialRows?: number;
|
|
11
|
+
delimiter?: string;
|
|
12
|
+
encoding?: "utf-8" | "utf8" | "utf16le" | "latin1";
|
|
13
|
+
skipHeaders?: boolean;
|
|
14
|
+
fieldMap?: Record<string, string>;
|
|
15
|
+
autoMap?: boolean;
|
|
16
|
+
filter?: ImportRowFilter;
|
|
17
|
+
maxFieldCodeUnits?: number;
|
|
18
|
+
maxRecordCodeUnits?: number;
|
|
19
|
+
maxColumns?: number;
|
|
20
|
+
maxAtomicBytes?: number;
|
|
21
|
+
maxAtomicRows?: number;
|
|
22
|
+
maxSourceBytes?: number;
|
|
23
|
+
}
|
|
24
|
+
/** Compact source-free receipt. Mutation work is a row-operation upper bound, never an exact create/update count or heap prediction. */
|
|
25
|
+
export interface AdmissionReceipt {
|
|
26
|
+
version: 1;
|
|
27
|
+
mode: "initial" | "full";
|
|
28
|
+
ok: boolean;
|
|
29
|
+
complete: boolean;
|
|
30
|
+
admitted: boolean;
|
|
31
|
+
digest?: string;
|
|
32
|
+
rows: {
|
|
33
|
+
value: number;
|
|
34
|
+
kind: "exact" | "lower_bound";
|
|
35
|
+
};
|
|
36
|
+
invalidRows: number;
|
|
37
|
+
issues: {
|
|
38
|
+
row: number;
|
|
39
|
+
code: "row_width" | "row_invalid";
|
|
40
|
+
}[];
|
|
41
|
+
fieldWidths: number[];
|
|
42
|
+
mutationWork: {
|
|
43
|
+
value: number;
|
|
44
|
+
kind: "upper_bound";
|
|
45
|
+
};
|
|
46
|
+
sourceBytes: number;
|
|
47
|
+
limits: typeof ADMISSION_LIMITS;
|
|
48
|
+
remedy?: string;
|
|
49
|
+
}
|
|
50
|
+
/** Stable refusal families; no source cells, source paths or low-level IO text is exposed. */
|
|
51
|
+
export type AdmissionRefusalCode = "csv_admission_options" | "csv_admission_io" | "csv_admission_limit" | "csv_admission_invalid" | "csv_admission_incomplete" | "csv_admission_source_changed" | "csv_admission_settings_changed" | "csv_admission_target_changed" | "csv_admission_sdk";
|
|
52
|
+
/** Expected semantic failure with a concrete retry action. */
|
|
53
|
+
export declare class AdmissionRefusal extends PmCliError {
|
|
54
|
+
/** Stable category for an automated retry decision. */
|
|
55
|
+
readonly code: AdmissionRefusalCode;
|
|
56
|
+
/** Concrete repair action, excluding source content. */
|
|
57
|
+
readonly remedy: string;
|
|
58
|
+
constructor(code: AdmissionRefusalCode, remedy: string);
|
|
59
|
+
}
|
|
60
|
+
/** Keep admission and its native application in one settings-refusal family. */
|
|
61
|
+
export declare function admissionSettingsChanged(): AdmissionRefusal;
|
|
62
|
+
/** Preserve typed admission remedies when native transaction compensation aggregates failures. */
|
|
63
|
+
export declare function findAdmissionFailure(error: unknown, seen?: Set<unknown>): AdmissionRefusal | undefined;
|
|
64
|
+
/** Older hosts keep read-only admission; applying needs the native semantic preview capability. */
|
|
65
|
+
export declare function requireAdmissionCapability<T extends (...args: never[]) => unknown>(value: T | undefined): T;
|
|
66
|
+
/** Preserve a concrete host/storage remedy when an older SDK previews installed dependency links. */
|
|
67
|
+
export declare function admissionPreviewFailure(error: unknown): AdmissionRefusal;
|
|
68
|
+
/** Validate options once before IO, including finite integer domains and bounded own-key mappings. */
|
|
69
|
+
export declare function parseAdmissionOptions(value: AdmissionOptions): Required<AdmissionOptions>;
|
|
70
|
+
/** Normalize a selected status through the same native registry as row writes, preserving source-based type filtering. */
|
|
71
|
+
export declare function normalizeAdmissionFilter(filter: ImportRowFilter, settings: PmSettings): ImportRowFilter | undefined;
|
|
72
|
+
/** Refuse unusable resource reports before an atomic caller allocates a row plan. */
|
|
73
|
+
export declare function assertCSVAdmission(receipt: AdmissionReceipt): void;
|
|
74
|
+
/** Capture bounded bytes for the existing atomic parser, refusing source drift before materialization or writes. */
|
|
75
|
+
export declare function readAdmittedSource(file: string, digest: string, maxBytes?: number): Buffer;
|
|
76
|
+
/** Require current native state or the latest immutable success of exactly this row. */
|
|
77
|
+
export declare function admissionTargetRevision(pmRoot: string, id: string, expected?: string, appliedMarker?: string): Promise<string>;
|
|
78
|
+
/** Reconcile ordered writes to one native target; later rows prove the completed prefix, including reverse compensation. */
|
|
79
|
+
export declare function admissionTargetSequence(pmRoot: string, id: string, expected: string, markers: readonly string[]): Promise<{
|
|
80
|
+
revision: string;
|
|
81
|
+
completed: number;
|
|
82
|
+
}>;
|
|
83
|
+
/** Check every emitted count and width before returning success, also useful to consumers validating receipts. */
|
|
84
|
+
export declare function assertAdmissionNumbers(receipt: AdmissionReceipt): void;
|
|
85
|
+
/** Read-only admission against one SDK settings revision. Source size never determines retained row count. */
|
|
86
|
+
export declare function admitCSV(pmRoot: string, file: string, options?: AdmissionOptions, diagnostics?: AdmissionDiagnostics): Promise<AdmissionReceipt>;
|
|
87
|
+
/** Trusted observer for deterministic concurrency diagnostics, outside the untrusted options schema. */
|
|
88
|
+
export interface AdmissionDiagnostics {
|
|
89
|
+
onBoundary?: (phase: "opened" | "read" | "validated") => void | Promise<void>;
|
|
90
|
+
}
|
|
91
|
+
/** Register one host-rendered compact TOON/JSON command; no source values or artifacts are emitted. */
|
|
92
|
+
export declare function registerAdmissionCommand(api: ExtensionApi): void;
|
|
93
|
+
//# sourceMappingURL=admission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../admission.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { open } from "node:fs/promises";
|
|
3
|
+
import { openSync, closeSync, readSync, fstatSync, constants } from "node:fs";
|
|
4
|
+
import { resolveItemTypeRegistry, resolveRuntimeStatusRegistry, normalizeStatusInput, getHistoryPath, readHistoryEntries, verifyHistoryEntries, locateItem, readLocatedItem, PmCliError } from "@unbrained/pm-cli/sdk";
|
|
5
|
+
import { readPinnedSettings, verifySettings, withSettings } from "./settings-snapshot.js";
|
|
6
|
+
import { mutationMessageBase } from "./mutation-intent.js";
|
|
7
|
+
import { StreamingCSVParser, IMPORT_COLUMNS, resolveDelimiter, resolveEncoding, stripBOM, parseFieldMap, resolveImportFieldMap, applyFieldMap, validateFieldMapTargets, checkMapSourcesPresent, validateParsedCSV, strictValidationIssues, readBoolOption } from "./index.js";
|
|
8
|
+
/** Hard allocation and materialization ceilings; callers can only lower them. Units are UTF-16 code units unless named bytes. */
|
|
9
|
+
export const ADMISSION_LIMITS = Object.freeze({ maxFieldCodeUnits: 65536, maxRecordCodeUnits: 262144, maxColumns: 128,
|
|
10
|
+
maxAtomicBytes: 8 * 1024 * 1024, maxAtomicRows: 1000, maxSourceBytes: 1024 ** 4 });
|
|
11
|
+
/** Expected semantic failure with a concrete retry action. */
|
|
12
|
+
export class AdmissionRefusal extends PmCliError {
|
|
13
|
+
/** Stable category for an automated retry decision. */
|
|
14
|
+
code;
|
|
15
|
+
/** Concrete repair action, excluding source content. */
|
|
16
|
+
remedy;
|
|
17
|
+
constructor(code, remedy) {
|
|
18
|
+
super(`${code}: ${remedy}`, 2, { code, required: remedy, nextSteps: [remedy] });
|
|
19
|
+
this.code = code;
|
|
20
|
+
this.remedy = remedy;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Keep admission and its native application in one settings-refusal family. */
|
|
24
|
+
export function admissionSettingsChanged() {
|
|
25
|
+
return new AdmissionRefusal("csv_admission_settings_changed", "Tracker settings changed; scan again against current schemas and status roles.");
|
|
26
|
+
}
|
|
27
|
+
/** Preserve typed admission remedies when native transaction compensation aggregates failures. */
|
|
28
|
+
export function findAdmissionFailure(error, seen = new Set()) {
|
|
29
|
+
if (seen.has(error))
|
|
30
|
+
return undefined;
|
|
31
|
+
seen.add(error);
|
|
32
|
+
if (error instanceof AdmissionRefusal)
|
|
33
|
+
return error;
|
|
34
|
+
if (error instanceof AggregateError) {
|
|
35
|
+
for (const nested of error.errors) {
|
|
36
|
+
const refusal = findAdmissionFailure(nested, seen);
|
|
37
|
+
if (refusal)
|
|
38
|
+
return refusal;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return error instanceof Error && error.cause !== undefined ? findAdmissionFailure(error.cause, seen) : undefined;
|
|
42
|
+
}
|
|
43
|
+
/** Older hosts keep read-only admission; applying needs the native semantic preview capability. */
|
|
44
|
+
export function requireAdmissionCapability(value) {
|
|
45
|
+
if (typeof value !== "function")
|
|
46
|
+
throw new AdmissionRefusal("csv_admission_sdk", "Upgrade the pm host to one exposing semantic mutation preview and transaction-key derivation (the development SDK is supported); csv admit remains available without applying.");
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
/** Preserve a concrete host/storage remedy when an older SDK previews installed dependency links. */
|
|
50
|
+
export function admissionPreviewFailure(error) {
|
|
51
|
+
const storage = typeof error === "object" && error !== null && "code" in error && error.code === "transaction_preview_non_regular_file";
|
|
52
|
+
const refusal = new AdmissionRefusal(storage ? "csv_admission_sdk" : "csv_admission_invalid", storage
|
|
53
|
+
? "Native preview refused linked or special tracker storage. Use pm 2026.10.28 or newer for installed dependency links; inspect authoritative tracker links or special files without following them, then retry. No mutations were attempted."
|
|
54
|
+
: "Native SDK validation refused the bounded plan before application. Correct native fields, references or governance policies, then review the import again.");
|
|
55
|
+
refusal.cause = error;
|
|
56
|
+
return refusal;
|
|
57
|
+
}
|
|
58
|
+
/** Validate options once before IO, including finite integer domains and bounded own-key mappings. */
|
|
59
|
+
export function parseAdmissionOptions(value) {
|
|
60
|
+
const keys = ["mode", "initialRows", "delimiter", "encoding", "skipHeaders", "fieldMap", "autoMap", "filter", ...Object.keys(ADMISSION_LIMITS)];
|
|
61
|
+
const invalid = new AdmissionRefusal("csv_admission_options", "Use full or initial mode, supported encoding/mappings, booleans and positive safe integer limits no larger than ADMISSION_LIMITS.");
|
|
62
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value)) ||
|
|
63
|
+
Reflect.ownKeys(value).some(key => typeof key !== "string" || !keys.includes(key)))
|
|
64
|
+
throw invalid;
|
|
65
|
+
if ((value.mode !== undefined && !["initial", "full"].includes(value.mode)) ||
|
|
66
|
+
[value.skipHeaders, value.autoMap].some(flag => flag !== undefined && typeof flag !== "boolean") ||
|
|
67
|
+
(value.delimiter !== undefined && typeof value.delimiter !== "string") ||
|
|
68
|
+
(value.encoding !== undefined && typeof value.encoding !== "string"))
|
|
69
|
+
throw invalid;
|
|
70
|
+
const fieldMap = value.fieldMap === undefined ? {} : value.fieldMap;
|
|
71
|
+
if (!fieldMap || typeof fieldMap !== "object" || Array.isArray(fieldMap) || ![Object.prototype, null].includes(Object.getPrototypeOf(fieldMap)) ||
|
|
72
|
+
Reflect.ownKeys(fieldMap).length > 128 || Reflect.ownKeys(fieldMap).some(key => typeof key !== "string") ||
|
|
73
|
+
Object.entries(fieldMap).some(([key, field]) => !key.trim() || key.length > 128 || typeof field !== "string" || !IMPORT_COLUMNS.includes(field)))
|
|
74
|
+
throw invalid;
|
|
75
|
+
const filter = value.filter === undefined ? {} : value.filter;
|
|
76
|
+
if (!filter || typeof filter !== "object" || Array.isArray(filter) || ![Object.prototype, null].includes(Object.getPrototypeOf(filter)) ||
|
|
77
|
+
Reflect.ownKeys(filter).some(key => typeof key !== "string" || !["status", "type", "priority"].includes(key)) ||
|
|
78
|
+
[filter.status, filter.type].some(v => v !== undefined && (typeof v !== "string" || !v.trim() || v.length > 128)) ||
|
|
79
|
+
(filter.priority !== undefined && (!Number.isSafeInteger(filter.priority) || filter.priority < 0 || filter.priority > 4)))
|
|
80
|
+
throw invalid;
|
|
81
|
+
const limits = { ...ADMISSION_LIMITS };
|
|
82
|
+
for (const key of Object.keys(limits)) {
|
|
83
|
+
const n = value[key] === undefined ? limits[key] : value[key];
|
|
84
|
+
if (!Number.isSafeInteger(n) || n < 1 || n > ADMISSION_LIMITS[key])
|
|
85
|
+
throw invalid;
|
|
86
|
+
limits[key] = n;
|
|
87
|
+
}
|
|
88
|
+
const initialRows = value.initialRows === undefined ? 1000 : value.initialRows;
|
|
89
|
+
if (!Number.isSafeInteger(initialRows) || initialRows < 1 || initialRows > 1000000)
|
|
90
|
+
throw invalid;
|
|
91
|
+
let delimiter, encoding;
|
|
92
|
+
try {
|
|
93
|
+
delimiter = resolveDelimiter(value.delimiter);
|
|
94
|
+
encoding = resolveEncoding(value.encoding);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
throw invalid;
|
|
98
|
+
}
|
|
99
|
+
if (delimiter.length !== 1 || /["\r\n\uFEFF]/.test(delimiter))
|
|
100
|
+
throw invalid;
|
|
101
|
+
return { ...limits, mode: value.mode ?? "full", initialRows, delimiter, encoding,
|
|
102
|
+
skipHeaders: value.skipHeaders ?? false, autoMap: value.autoMap ?? false, fieldMap: { ...fieldMap }, filter: { ...filter } };
|
|
103
|
+
}
|
|
104
|
+
/** Normalize a selected status through the same native registry as row writes, preserving source-based type filtering. */
|
|
105
|
+
export function normalizeAdmissionFilter(filter, settings) {
|
|
106
|
+
const status = filter.status === undefined ? undefined : normalizeStatusInput(filter.status, resolveRuntimeStatusRegistry(settings.schema));
|
|
107
|
+
if (filter.status !== undefined && status === undefined)
|
|
108
|
+
throw new AdmissionRefusal("csv_admission_options", "Select a configured native status for the import filter, then scan again.");
|
|
109
|
+
const type = filter.type?.trim().toLowerCase();
|
|
110
|
+
if (status === undefined && type === undefined && filter.priority === undefined)
|
|
111
|
+
return undefined;
|
|
112
|
+
return { status, type, priority: filter.priority };
|
|
113
|
+
}
|
|
114
|
+
/** Refuse unusable resource reports before an atomic caller allocates a row plan. */
|
|
115
|
+
export function assertCSVAdmission(receipt) {
|
|
116
|
+
if (receipt.mode === "initial" || !receipt.complete)
|
|
117
|
+
throw new AdmissionRefusal("csv_admission_incomplete", "Run a full scan; an initial scan never authorizes atomic import.");
|
|
118
|
+
if (!receipt.ok)
|
|
119
|
+
throw new AdmissionRefusal("csv_admission_invalid", "Repair the reported row coordinates and run full admission again; no mutations were attempted.");
|
|
120
|
+
if (!receipt.admitted)
|
|
121
|
+
throw new AdmissionRefusal("csv_admission_limit", "Split the source into explicitly reviewed imports within the reported atomic row/byte budgets, or lower the requested work; admission did not apply anything.");
|
|
122
|
+
}
|
|
123
|
+
/** Capture bounded bytes for the existing atomic parser, refusing source drift before materialization or writes. */
|
|
124
|
+
export function readAdmittedSource(file, digest, maxBytes = ADMISSION_LIMITS.maxAtomicBytes) {
|
|
125
|
+
const budget = parseAdmissionOptions({ maxAtomicBytes: maxBytes }).maxAtomicBytes;
|
|
126
|
+
let fd;
|
|
127
|
+
try {
|
|
128
|
+
fd = openSync(file, constants.O_RDONLY | constants.O_NONBLOCK);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
throw new AdmissionRefusal("csv_admission_io", "The admitted file is no longer readable; restore a readable regular source and scan again.");
|
|
132
|
+
}
|
|
133
|
+
const chunks = [];
|
|
134
|
+
let total = 0;
|
|
135
|
+
try {
|
|
136
|
+
if (!fstatSync(fd).isFile())
|
|
137
|
+
throw new AdmissionRefusal("csv_admission_io", "Use a regular file for admitted materialization; the source changed type after scanning.");
|
|
138
|
+
for (;;) {
|
|
139
|
+
const chunk = Buffer.alloc(16384), length = readSync(fd, chunk, 0, chunk.length, null);
|
|
140
|
+
if (!length)
|
|
141
|
+
break;
|
|
142
|
+
total += length;
|
|
143
|
+
if (total > budget)
|
|
144
|
+
throw new AdmissionRefusal("csv_admission_limit", "Source grew beyond the atomic byte budget; stabilize it and scan again.");
|
|
145
|
+
chunks.push(chunk.subarray(0, length));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
closeSync(fd);
|
|
150
|
+
}
|
|
151
|
+
const bytes = Buffer.concat(chunks);
|
|
152
|
+
if (createHash("sha256").update(bytes).digest("hex") !== digest)
|
|
153
|
+
throw new AdmissionRefusal("csv_admission_source_changed", "Source bytes changed after admission; review and scan the new source before retrying.");
|
|
154
|
+
return bytes;
|
|
155
|
+
}
|
|
156
|
+
/** Bind a mutation step to verified native state plus append-only history, preventing ABA replay. */
|
|
157
|
+
async function readAdmissionTarget(pmRoot, id, expected) {
|
|
158
|
+
const settings = await readPinnedSettings(pmRoot);
|
|
159
|
+
const located = await locateItem(pmRoot, id, settings.id_prefix, settings.item_format, resolveItemTypeRegistry(settings).type_to_folder);
|
|
160
|
+
const history = await readHistoryEntries(getHistoryPath(pmRoot, id), id);
|
|
161
|
+
if (!located) {
|
|
162
|
+
if (expected === "absent" && history.length === 0)
|
|
163
|
+
return { revision: "absent" };
|
|
164
|
+
throw new AdmissionRefusal("csv_admission_target_changed", "A target is missing or has retained history; reconcile its SDK state before retrying the original plan.");
|
|
165
|
+
}
|
|
166
|
+
const document = (await readLocatedItem(located, { schema: settings.schema })).document;
|
|
167
|
+
const revision = createHash("sha256").update(JSON.stringify([document, history])).digest("hex");
|
|
168
|
+
if (!verifyHistoryEntries(history, document).ok)
|
|
169
|
+
throw admissionTargetChanged();
|
|
170
|
+
return { revision, message: mutationMessageBase(history.at(-1)?.message) };
|
|
171
|
+
}
|
|
172
|
+
/** Require current native state or the latest immutable success of exactly this row. */
|
|
173
|
+
export async function admissionTargetRevision(pmRoot, id, expected, appliedMarker) {
|
|
174
|
+
const { revision, message } = await readAdmissionTarget(pmRoot, id, expected);
|
|
175
|
+
const owned = appliedMarker !== undefined && ["create", "apply", "close"].some(phase => message === `${appliedMarker}:${phase}`);
|
|
176
|
+
if (expected !== undefined && revision !== expected && !owned)
|
|
177
|
+
throw admissionTargetChanged();
|
|
178
|
+
return revision;
|
|
179
|
+
}
|
|
180
|
+
/** Reconcile ordered writes to one native target; later rows prove the completed prefix, including reverse compensation. */
|
|
181
|
+
export async function admissionTargetSequence(pmRoot, id, expected, markers) {
|
|
182
|
+
const { revision, message } = await readAdmissionTarget(pmRoot, id, expected);
|
|
183
|
+
if (revision === expected)
|
|
184
|
+
return { revision, completed: -1 };
|
|
185
|
+
const completed = markers.findIndex(marker => ["apply", "close", "restore", "compensate"].some(phase => message === `${marker}:${phase}`));
|
|
186
|
+
if (completed < 0)
|
|
187
|
+
throw admissionTargetChanged();
|
|
188
|
+
return { revision, completed: message === `${markers[completed]}:compensate` ? completed - 1 : completed };
|
|
189
|
+
}
|
|
190
|
+
/** Keep foreign writes, ABA changes and unverifiable target histories in one refusal family. */
|
|
191
|
+
function admissionTargetChanged() {
|
|
192
|
+
return new AdmissionRefusal("csv_admission_target_changed", "A target revision changed after planning or a prior import. Reconcile current SDK state and preview a fresh import; no frozen target plan was replayed.");
|
|
193
|
+
}
|
|
194
|
+
/** Check every emitted count and width before returning success, also useful to consumers validating receipts. */
|
|
195
|
+
export function assertAdmissionNumbers(receipt) {
|
|
196
|
+
const counts = [receipt.rows.value, receipt.invalidRows, receipt.sourceBytes, receipt.mutationWork.value,
|
|
197
|
+
...receipt.fieldWidths, ...receipt.issues.map(issue => issue.row), ...Object.values(receipt.limits)];
|
|
198
|
+
if (counts.some(n => !Number.isSafeInteger(n) || n < 0) || receipt.sourceBytes > ADMISSION_LIMITS.maxSourceBytes ||
|
|
199
|
+
Object.keys(ADMISSION_LIMITS).some(key => receipt.limits[key] < 1 || receipt.limits[key] > ADMISSION_LIMITS[key]) ||
|
|
200
|
+
receipt.mutationWork.value > receipt.sourceBytes || receipt.issues.some(issue => issue.row < 1 || issue.row > receipt.sourceBytes) ||
|
|
201
|
+
receipt.rows.value > receipt.sourceBytes || receipt.invalidRows > receipt.rows.value || receipt.fieldWidths.length > receipt.limits.maxColumns ||
|
|
202
|
+
receipt.fieldWidths.some(n => n > receipt.limits.maxFieldCodeUnits) || receipt.issues.length > 8) {
|
|
203
|
+
throw new AdmissionRefusal("csv_admission_limit", "The source exceeded the finite receipt domain; reduce the resource limits and rescan.");
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/** Stream one open regular-file descriptor, keeping a single bounded record and aggregate counters. */
|
|
207
|
+
async function scan(pmRoot, file, opts, diagnostics) {
|
|
208
|
+
const settings = await readPinnedSettings(pmRoot);
|
|
209
|
+
normalizeAdmissionFilter(opts.filter, settings);
|
|
210
|
+
const statuses = resolveRuntimeStatusRegistry(settings.schema), types = resolveItemTypeRegistry(settings);
|
|
211
|
+
const knownStatus = (status) => normalizeStatusInput(status, statuses) !== undefined;
|
|
212
|
+
let headers, rows = 0, invalidRows = 0, record = 0;
|
|
213
|
+
const widths = [], issues = [];
|
|
214
|
+
const stop = Symbol("initial_scan_complete");
|
|
215
|
+
/** Resolve through the import's existing mapping path; reject lossy/ambiguous mappings before scanning rows. */
|
|
216
|
+
const setHeaders = (raw) => {
|
|
217
|
+
if (raw.some(h => !h.trim() || h.length > 128) || validateFieldMapTargets(opts.fieldMap).length || checkMapSourcesPresent(raw, opts.fieldMap).length) {
|
|
218
|
+
throw new AdmissionRefusal("csv_admission_invalid", "Use distinct nonempty headers up to 128 code units and map existing columns to supported CSV fields.");
|
|
219
|
+
}
|
|
220
|
+
const mapped = resolveImportFieldMap(raw, opts.fieldMap, opts.autoMap);
|
|
221
|
+
headers = applyFieldMap(raw, mapped.fieldMap);
|
|
222
|
+
if (strictValidationIssues(validateParsedCSV(headers, [], {}, knownStatus)).length) {
|
|
223
|
+
throw new AdmissionRefusal("csv_admission_invalid", "Provide a title column with distinct mapped fields; reuse csv schema describe to review mappings.");
|
|
224
|
+
}
|
|
225
|
+
for (const field of raw)
|
|
226
|
+
widths.push(opts.skipHeaders ? 0 : field.length);
|
|
227
|
+
};
|
|
228
|
+
/** Bound initial observation work even when the prefix consists entirely of blank records. */
|
|
229
|
+
const stopInitial = () => {
|
|
230
|
+
if (opts.mode === "initial" && record >= opts.initialRows + (opts.skipHeaders ? 0 : 1))
|
|
231
|
+
throw stop;
|
|
232
|
+
};
|
|
233
|
+
if (opts.skipHeaders)
|
|
234
|
+
setHeaders([...IMPORT_COLUMNS]);
|
|
235
|
+
const parser = new StreamingCSVParser(opts.delimiter, row => {
|
|
236
|
+
record++;
|
|
237
|
+
if (!row.some(cell => cell.trim())) {
|
|
238
|
+
stopInitial();
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (!headers) {
|
|
242
|
+
setHeaders(row.map(h => h.trim().toLowerCase()));
|
|
243
|
+
stopInitial();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
rows++;
|
|
247
|
+
for (let index = 0; index < row.length; index++)
|
|
248
|
+
widths[index] = Math.max(widths[index] ?? 0, row[index].length);
|
|
249
|
+
const report = validateParsedCSV(headers, [row], {}, knownStatus);
|
|
250
|
+
const type = row[headers.indexOf("type")]?.trim();
|
|
251
|
+
const badWidth = row.length !== headers.length;
|
|
252
|
+
if (badWidth || strictValidationIssues(report).length || (type && !Object.hasOwn(types.alias_to_type, type.toLowerCase()))) {
|
|
253
|
+
invalidRows++;
|
|
254
|
+
if (issues.length < 8)
|
|
255
|
+
issues.push({ row: record, code: badWidth ? "row_width" : "row_invalid" });
|
|
256
|
+
}
|
|
257
|
+
stopInitial();
|
|
258
|
+
}, opts);
|
|
259
|
+
const handle = await open(file, constants.O_RDONLY | constants.O_NONBLOCK).catch(() => { throw new AdmissionRefusal("csv_admission_io", "Provide a readable regular CSV file; no source or target was modified."); });
|
|
260
|
+
try {
|
|
261
|
+
const before = await handle.stat({ bigint: true });
|
|
262
|
+
if (!before.isFile() || before.size > BigInt(opts.maxSourceBytes))
|
|
263
|
+
throw new AdmissionRefusal("csv_admission_limit", "Use a regular file within maxSourceBytes; pipes, devices and oversized inputs are refused.");
|
|
264
|
+
await diagnostics.onBoundary?.("opened");
|
|
265
|
+
const buffer = Buffer.alloc(16384);
|
|
266
|
+
const hash = createHash("sha256");
|
|
267
|
+
const decoder = new TextDecoder(opts.encoding === "utf8" ? "utf-8" : opts.encoding === "utf16le" ? "utf-16le" : opts.encoding === "latin1" ? "windows-1252" : opts.encoding, { fatal: true, ignoreBOM: true });
|
|
268
|
+
let first = true, complete = true, readBytes = 0;
|
|
269
|
+
try {
|
|
270
|
+
for (;;) {
|
|
271
|
+
const { bytesRead } = await handle.read(buffer, 0, buffer.length, null);
|
|
272
|
+
if (!bytesRead)
|
|
273
|
+
break;
|
|
274
|
+
const bytes = buffer.subarray(0, bytesRead);
|
|
275
|
+
readBytes += bytes.length;
|
|
276
|
+
if (readBytes > opts.maxSourceBytes)
|
|
277
|
+
throw new RangeError("csv_source_limit");
|
|
278
|
+
hash.update(bytes);
|
|
279
|
+
let text = opts.encoding === "latin1" ? bytes.toString("latin1") : decoder.decode(bytes, { stream: true });
|
|
280
|
+
if (first) {
|
|
281
|
+
text = stripBOM(text);
|
|
282
|
+
first = false;
|
|
283
|
+
}
|
|
284
|
+
parser.push(text);
|
|
285
|
+
await diagnostics.onBoundary?.("read");
|
|
286
|
+
}
|
|
287
|
+
parser.push(decoder.decode());
|
|
288
|
+
parser.end();
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
if (error === stop)
|
|
292
|
+
complete = false;
|
|
293
|
+
else if (error instanceof AdmissionRefusal)
|
|
294
|
+
throw error;
|
|
295
|
+
else
|
|
296
|
+
throw new AdmissionRefusal(error instanceof RangeError ? "csv_admission_limit" : "csv_admission_invalid", "Correct encoding/quoting or reduce field, record and column widths to the declared limits; scan stopped before any mutation.");
|
|
297
|
+
}
|
|
298
|
+
await diagnostics.onBoundary?.("validated");
|
|
299
|
+
const after = await handle.stat({ bigint: true });
|
|
300
|
+
if (["size", "mtimeNs", "ctimeNs"].some(key => before[key] !== after[key])) {
|
|
301
|
+
throw new AdmissionRefusal("csv_admission_source_changed", "The open source changed during scanning; stabilize the file and run full admission again.");
|
|
302
|
+
}
|
|
303
|
+
if (!headers && complete)
|
|
304
|
+
throw new AdmissionRefusal("csv_admission_invalid", "Provide a nonempty CSV with a title header.");
|
|
305
|
+
await verifySettings(pmRoot);
|
|
306
|
+
const sourceBytes = Number(before.size);
|
|
307
|
+
const limits = Object.fromEntries(Object.keys(ADMISSION_LIMITS).map(key => [key, opts[key]]));
|
|
308
|
+
const admitted = opts.mode === "full" && complete && invalidRows === 0 && rows <= opts.maxAtomicRows && sourceBytes <= opts.maxAtomicBytes;
|
|
309
|
+
const receipt = { version: 1, mode: opts.mode, ok: headers !== undefined && invalidRows === 0, complete, admitted,
|
|
310
|
+
...(complete ? { digest: hash.digest("hex") } : {}), rows: { value: rows, kind: complete ? "exact" : "lower_bound" },
|
|
311
|
+
invalidRows, issues, fieldWidths: widths, sourceBytes, mutationWork: { value: complete ? rows : sourceBytes, kind: "upper_bound" }, limits,
|
|
312
|
+
...(!admitted ? { remedy: opts.mode === "initial" || !complete ? "Run a full scan before atomic admission." : invalidRows ? "Repair reported rows and rescan." : "Split into reviewed imports within atomic row/byte limits." } : {}) };
|
|
313
|
+
assertAdmissionNumbers(receipt);
|
|
314
|
+
return receipt;
|
|
315
|
+
}
|
|
316
|
+
finally {
|
|
317
|
+
await handle.close();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/** Read-only admission against one SDK settings revision. Source size never determines retained row count. */
|
|
321
|
+
export async function admitCSV(pmRoot, file, options = {}, diagnostics = {}) {
|
|
322
|
+
const opts = parseAdmissionOptions(options);
|
|
323
|
+
return withSettings(pmRoot, admissionSettingsChanged, () => scan(pmRoot, file, opts, diagnostics));
|
|
324
|
+
}
|
|
325
|
+
/** Register one host-rendered compact TOON/JSON command; no source values or artifacts are emitted. */
|
|
326
|
+
export function registerAdmissionCommand(api) {
|
|
327
|
+
api.registerCommand({ name: "csv admit", description: "Stream full or initial CSV validation and report bounded import admission without writes.",
|
|
328
|
+
arguments: [{ name: "file", required: true, description: "Readable regular CSV file" }],
|
|
329
|
+
flags: [
|
|
330
|
+
{ long: "--initial-rows", value_name: "count", description: "Initial scan only; positive integer up to 1000000, never authorizes apply" },
|
|
331
|
+
{ long: "--delimiter", value_name: "char", description: "Existing CSV delimiter vocabulary" },
|
|
332
|
+
{ long: "--encoding", value_name: "encoding", description: "utf-8, utf8, utf16le or latin1" },
|
|
333
|
+
{ long: "--map", value_name: "mapping", description: "Existing Source=field mapping" },
|
|
334
|
+
{ long: "--auto-map", description: "Reuse existing well-known header aliases" },
|
|
335
|
+
{ long: "--skip-headers", description: "Use canonical positional import columns" },
|
|
336
|
+
...Object.keys(ADMISSION_LIMITS).map(key => ({ long: `--${key.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`)}`, value_name: "count", description: `Lower ${key} for this scan` })),
|
|
337
|
+
],
|
|
338
|
+
async run(ctx) {
|
|
339
|
+
const options = {};
|
|
340
|
+
for (const key of Object.keys(ADMISSION_LIMITS)) {
|
|
341
|
+
const raw = ctx.options[key] ?? ctx.options[key.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`)];
|
|
342
|
+
if (raw !== undefined)
|
|
343
|
+
options[key] = typeof raw === "string" && /^\d+$/.test(raw) ? Number(raw) : NaN;
|
|
344
|
+
}
|
|
345
|
+
const initial = ctx.options["initialRows"] ?? ctx.options["initial-rows"];
|
|
346
|
+
if (initial !== undefined) {
|
|
347
|
+
options.mode = "initial";
|
|
348
|
+
options.initialRows = typeof initial === "string" && /^\d+$/.test(initial) ? Number(initial) : NaN;
|
|
349
|
+
}
|
|
350
|
+
try {
|
|
351
|
+
options.fieldMap = parseFieldMap(ctx.options["map"]);
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
throw new AdmissionRefusal("csv_admission_options", "Use Source=title,Rank=priority mappings to existing supported CSV fields.");
|
|
355
|
+
}
|
|
356
|
+
return { ...await admitCSV(ctx.pm_root, ctx.args[0], { ...options, delimiter: ctx.options["delimiter"],
|
|
357
|
+
encoding: ctx.options["encoding"], autoMap: readBoolOption(ctx.options, "auto-map", "autoMap"),
|
|
358
|
+
skipHeaders: readBoolOption(ctx.options, "skip-headers", "skipHeaders") }) };
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
//# sourceMappingURL=admission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admission.js","sourceRoot":"","sources":["../admission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,oBAAoB,EAAE,cAAc,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAIvN,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,gBAAgB,EAAE,eAAe,EAAE,QAAQ,EAAE,aAAa,EACrG,qBAAqB,EAAE,aAAa,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEvK,iIAAiI;AACjI,MAAM,CAAC,MAAM,gBAAgB,GAAgJ,MAAM,CAAC,MAAM,CAAC,EAAE,iBAAiB,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG;IAChQ,cAAc,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;AAsCrF,8DAA8D;AAC9D,MAAM,OAAO,gBAAiB,SAAQ,UAAU;IAC9C,uDAAuD;IAC9C,IAAI,CAAuB;IACpC,wDAAwD;IAC/C,MAAM,CAAS;IACxB,YAAY,IAA0B,EAAE,MAAc;QACpD,KAAK,CAAC,GAAG,IAAI,KAAK,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAChF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AACD,gFAAgF;AAChF,MAAM,UAAU,wBAAwB;IACtC,OAAO,IAAI,gBAAgB,CAAC,gCAAgC,EAAE,gFAAgF,CAAC,CAAC;AAClJ,CAAC;AACD,kGAAkG;AAClG,MAAM,UAAU,oBAAoB,CAAC,KAAc,EAAE,IAAI,GAAG,IAAI,GAAG,EAAW;IAC5E,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACtC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChB,IAAI,KAAK,YAAY,gBAAgB;QAAE,OAAO,KAAK,CAAC;IACpD,IAAI,KAAK,YAAY,cAAc,EAAE,CAAC;QACpC,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACnD,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACnH,CAAC;AACD,mGAAmG;AACnG,MAAM,UAAU,0BAA0B,CAA0C,KAAoB;IACtG,IAAI,OAAO,KAAK,KAAK,UAAU;QAAE,MAAM,IAAI,gBAAgB,CAAC,mBAAmB,EAAE,gLAAgL,CAAC,CAAC;IACnQ,OAAO,KAAK,CAAC;AACf,CAAC;AACD,qGAAqG;AACrG,MAAM,UAAU,uBAAuB,CAAC,KAAc;IACpD,MAAM,OAAO,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,sCAAsC,CAAC;IACxI,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,uBAAuB,EAAE,OAAO;QACnG,CAAC,CAAC,4OAA4O;QAC9O,CAAC,CAAC,4JAA4J,CAAC,CAAC;IAClK,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IACtB,OAAO,OAAO,CAAC;AACjB,CAAC;AACD,sGAAsG;AACtG,MAAM,UAAU,qBAAqB,CAAC,KAAuB;IAC3D,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAChJ,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,uBAAuB,EAAE,mIAAmI,CAAC,CAAC;IACnM,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAC/H,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAAE,MAAM,OAAO,CAAC;IACtG,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvE,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,KAAK,SAAS,CAAC;QAChG,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC;QACtE,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC;QAAE,MAAM,OAAO,CAAC;IACxF,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;IACpE,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC3I,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC;QACxG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAsC,CAAC,CAAC;QAAE,MAAM,OAAO,CAAC;IACrM,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;IAC9D,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACnI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC7G,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;QACjH,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;QAAE,MAAM,OAAO,CAAC;IAC7I,MAAM,MAAM,GAAG,EAAE,GAAG,gBAAgB,EAAE,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAA4B,EAAE,CAAC;QACjE,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC;YAAE,MAAM,OAAO,CAAC;QAClF,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;IAC/E,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,IAAI,WAAW,GAAG,OAAO;QAAE,MAAM,OAAO,CAAC;IAClG,IAAI,SAAiB,EAAE,QAAgD,CAAC;IACxE,IAAI,CAAC;QAAC,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAAC,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAAC,CAAC;IAClG,MAAM,CAAC;QAAC,MAAM,OAAO,CAAC;IAAC,CAAC;IACxB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,MAAM,OAAO,CAAC;IAC7E,OAAO,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ;QAC9E,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK,EAAE,QAAQ,EAAE,EAAE,GAAG,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC;AACjI,CAAC;AACD,0HAA0H;AAC1H,MAAM,UAAU,wBAAwB,CAAC,MAAuB,EAAE,QAAoB;IACpF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,MAAM,EAAE,4BAA4B,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5I,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,gBAAgB,CAAC,uBAAuB,EAAE,2EAA2E,CAAC,CAAC;IAC1L,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/C,IAAI,MAAM,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAClG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;AACrD,CAAC;AACD,qFAAqF;AACrF,MAAM,UAAU,kBAAkB,CAAC,OAAyB;IAC1D,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,QAAQ;QAAE,MAAM,IAAI,gBAAgB,CAAC,0BAA0B,EAAE,kEAAkE,CAAC,CAAC;IAChL,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,IAAI,gBAAgB,CAAC,uBAAuB,EAAE,gGAAgG,CAAC,CAAC;IACvK,IAAI,CAAC,OAAO,CAAC,QAAQ;QAAE,MAAM,IAAI,gBAAgB,CAAC,qBAAqB,EAAE,+JAA+J,CAAC,CAAC;AAC5O,CAAC;AACD,oHAAoH;AACpH,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,MAAc,EAAE,QAAQ,GAAG,gBAAgB,CAAC,cAAc;IACzG,MAAM,MAAM,GAAG,qBAAqB,CAAC,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC,CAAC,cAAc,CAAC;IAClF,IAAI,EAAU,CAAC;IACf,IAAI,CAAC;QAAC,EAAE,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;IAAC,CAAC;IACvE,MAAM,CAAC;QAAC,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,EAAE,4FAA4F,CAAC,CAAC;IAAC,CAAC;IACvJ,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,CAAC;QACH,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;YAAE,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,EAAE,0FAA0F,CAAC,CAAC;QACxK,SAAS,CAAC;YACR,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACvF,IAAI,CAAC,MAAM;gBAAE,MAAM;YACnB,KAAK,IAAI,MAAM,CAAC;YAChB,IAAI,KAAK,GAAG,MAAM;gBAAE,MAAM,IAAI,gBAAgB,CAAC,qBAAqB,EAAE,yEAAyE,CAAC,CAAC;YACjJ,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;YAAS,CAAC;QAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM;QAAE,MAAM,IAAI,gBAAgB,CAAC,8BAA8B,EAAE,uFAAuF,CAAC,CAAC;IACrN,OAAO,KAAK,CAAC;AACf,CAAC;AACD,qGAAqG;AACrG,KAAK,UAAU,mBAAmB,CAAC,MAAc,EAAE,EAAU,EAAE,QAAiB;IAC9E,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,EAAE,EAAE,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,WAAW,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,CAAC;IACzI,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACzE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,IAAI,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;QACjF,MAAM,IAAI,gBAAgB,CAAC,8BAA8B,EAAE,yGAAyG,CAAC,CAAC;IACxK,CAAC;IACD,MAAM,QAAQ,GAAG,CAAC,MAAM,eAAe,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IACxF,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChG,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,EAAE;QAAE,MAAM,sBAAsB,EAAE,CAAC;IAChF,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC;AAC7E,CAAC;AACD,wFAAwF;AACxF,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,MAAc,EAAE,EAAU,EAAE,QAAiB,EAAE,aAAsB;IACjH,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,mBAAmB,CAAC,MAAM,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC9E,MAAM,KAAK,GAAG,aAAa,KAAK,SAAS,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,KAAK,GAAG,aAAa,IAAI,KAAK,EAAE,CAAC,CAAC;IACjI,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,QAAQ,IAAI,CAAC,KAAK;QAAE,MAAM,sBAAsB,EAAE,CAAC;IAC9F,OAAO,QAAQ,CAAC;AAClB,CAAC;AACD,4HAA4H;AAC5H,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,MAAc,EAAE,EAAU,EAAE,QAAgB,EAAE,OAA0B;IACpH,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,mBAAmB,CAAC,MAAM,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC9E,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC;IAC9D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,KAAK,GAAG,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;IAC3I,IAAI,SAAS,GAAG,CAAC;QAAE,MAAM,sBAAsB,EAAE,CAAC;IAClD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAC7G,CAAC;AACD,gGAAgG;AAChG,SAAS,sBAAsB;IAC7B,OAAO,IAAI,gBAAgB,CAAC,8BAA8B,EAAE,yJAAyJ,CAAC,CAAC;AACzN,CAAC;AACD,kHAAkH;AAClH,MAAM,UAAU,sBAAsB,CAAC,OAAyB;IAC9D,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK;QACtG,GAAG,OAAO,CAAC,WAAW,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACvG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,OAAO,CAAC,WAAW,GAAG,gBAAgB,CAAC,cAAc;QAC3G,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAuC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACxJ,OAAO,CAAC,YAAY,CAAC,KAAK,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC;QAClI,OAAO,CAAC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU;QAC9I,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrG,MAAM,IAAI,gBAAgB,CAAC,qBAAqB,EAAE,uFAAuF,CAAC,CAAC;IAC7I,CAAC;AACH,CAAC;AACD,uGAAuG;AACvG,KAAK,UAAU,IAAI,CAAC,MAAc,EAAE,IAAY,EAAE,IAAgC,EAAE,WAAiC;IACnH,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAClD,wBAAwB,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,4BAA4B,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC1G,MAAM,WAAW,GAAG,CAAC,MAAc,EAAW,EAAE,CAAC,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,SAAS,CAAC;IACtG,IAAI,OAA6B,EAAE,IAAI,GAAG,CAAC,EAAE,WAAW,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;IACzE,MAAM,MAAM,GAAa,EAAE,EAAE,MAAM,GAA+B,EAAE,CAAC;IACrE,MAAM,IAAI,GAAG,MAAM,CAAC,uBAAuB,CAAC,CAAC;IAC7C,gHAAgH;IAChH,MAAM,UAAU,GAAG,CAAC,GAAa,EAAQ,EAAE;QACzC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,uBAAuB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,IAAI,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;YACrJ,MAAM,IAAI,gBAAgB,CAAC,uBAAuB,EAAE,sGAAsG,CAAC,CAAC;QAC9J,CAAC;QACD,MAAM,MAAM,GAAG,qBAAqB,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACvE,OAAO,GAAG,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,sBAAsB,CAAC,iBAAiB,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YACnF,MAAM,IAAI,gBAAgB,CAAC,uBAAuB,EAAE,mGAAmG,CAAC,CAAC;QAC3J,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,GAAG;YAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5E,CAAC,CAAC;IACF,8FAA8F;IAC9F,MAAM,WAAW,GAAG,GAAS,EAAE;QAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,CAAC;IACrG,CAAC,CAAC;IACF,IAAI,IAAI,CAAC,WAAW;QAAE,UAAU,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,EAAE;QAC1D,MAAM,EAAE,CAAC;QACT,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAAC,WAAW,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QAC9D,IAAI,CAAC,OAAO,EAAE,CAAC;YAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;YAAC,WAAW,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QAC1F,IAAI,EAAE,CAAC;QACP,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE;YAAE,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;QACjH,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC;QAClE,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QAClD,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC;QAC/C,IAAI,QAAQ,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC;YAC3H,WAAW,EAAE,CAAC;YACd,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;QACpG,CAAC;QACD,WAAW,EAAE,CAAC;IAChB,CAAC,EAAE,IAAI,CAAC,CAAC;IACT,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,MAAM,IAAI,gBAAgB,CAAC,kBAAkB,EAAE,wEAAwE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtN,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC;YAAE,MAAM,IAAI,gBAAgB,CAAC,qBAAqB,EAAE,4FAA4F,CAAC,CAAC;QACnN,MAAM,WAAW,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/M,IAAI,KAAK,GAAG,IAAI,EAAE,QAAQ,GAAG,IAAI,EAAE,SAAS,GAAG,CAAC,CAAC;QACjD,IAAI,CAAC;YACH,SAAS,CAAC;gBACR,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACxE,IAAI,CAAC,SAAS;oBAAE,MAAM;gBACtB,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;gBAC5C,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC;gBAC1B,IAAI,SAAS,GAAG,IAAI,CAAC,cAAc;oBAAE,MAAM,IAAI,UAAU,CAAC,kBAAkB,CAAC,CAAC;gBAC9E,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACnB,IAAI,IAAI,GAAG,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3G,IAAI,KAAK,EAAE,CAAC;oBAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;oBAAC,KAAK,GAAG,KAAK,CAAC;gBAAC,CAAC;gBACpD,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClB,MAAM,WAAW,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC;YACzC,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAC9B,MAAM,CAAC,GAAG,EAAE,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,KAAK,IAAI;gBAAE,QAAQ,GAAG,KAAK,CAAC;iBAChC,IAAI,KAAK,YAAY,gBAAgB;gBAAE,MAAM,KAAK,CAAC;;gBACnD,MAAM,IAAI,gBAAgB,CAAC,KAAK,YAAY,UAAU,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,uBAAuB,EAC3G,8HAA8H,CAAC,CAAC;QACpI,CAAC;QACD,MAAM,WAAW,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,GAAqC,CAAC,KAAK,KAAK,CAAC,GAAqC,CAAC,CAAC,EAAE,CAAC;YAC/I,MAAM,IAAI,gBAAgB,CAAC,8BAA8B,EAAE,2FAA2F,CAAC,CAAC;QAC1J,CAAC;QACD,IAAI,CAAC,OAAO,IAAI,QAAQ;YAAE,MAAM,IAAI,gBAAgB,CAAC,uBAAuB,EAAE,6CAA6C,CAAC,CAAC;QAC7H,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;QAC7B,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAoC,CAAC,CAAC,CAAC,CAA4B,CAAC;QAC1J,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,QAAQ,IAAI,WAAW,KAAK,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,aAAa,IAAI,WAAW,IAAI,IAAI,CAAC,cAAc,CAAC;QAC3I,MAAM,OAAO,GAAqB,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,KAAK,SAAS,IAAI,WAAW,KAAK,CAAC,EAAE,QAAQ,EAAE,QAAQ;YACjI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE;YACpH,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,MAAM;YAC1I,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,0CAA0C,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,4DAA4D,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QAC1O,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO,OAAO,CAAC;IACjB,CAAC;YAAS,CAAC;QAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IAAC,CAAC;AACrC,CAAC;AACD,8GAA8G;AAC9G,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAc,EAAE,IAAY,EAAE,OAAO,GAAqB,EAAE,EAAE,WAAW,GAAyB,EAAE;IACjI,MAAM,IAAI,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC5C,OAAO,YAAY,CAAC,MAAM,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;AACrG,CAAC;AAKD,uGAAuG;AACvG,MAAM,UAAU,wBAAwB,CAAC,GAAiB;IACxD,GAAG,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,2FAA2F;QAC/I,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;QACvF,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,gBAAgB,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,2EAA2E,EAAE;YACzI,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,mCAAmC,EAAE;YAC7F,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,gCAAgC,EAAE;YAC7F,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,+BAA+B,EAAE;YACtF,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,0CAA0C,EAAE;YAC/E,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAW,EAAE,yCAAyC,EAAE;YAClF,GAAG,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,GAAG,gBAAgB,EAAE,CAAC,CAAC;SAC5L;QACD,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,MAAM,OAAO,GAA4B,EAAE,CAAC;YAC5C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBAChD,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;gBACzG,IAAI,GAAG,KAAK,SAAS;oBAAE,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YACzG,CAAC;YACD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAC1E,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAAC,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;gBAAC,OAAO,CAAC,WAAW,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAAC,CAAC;YAC5J,IAAI,CAAC;gBAAC,OAAO,CAAC,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAuB,CAAC,CAAC;YAAC,CAAC;YACnF,MAAM,CAAC;gBAAC,MAAM,IAAI,gBAAgB,CAAC,uBAAuB,EAAE,2EAA2E,CAAC,CAAC;YAAC,CAAC;YAC3I,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW,CAAuB;oBAC1H,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU,CAAiC,EAAE,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC;oBAC9H,WAAW,EAAE,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,aAAa,CAAC,EAAE,CAAC,EAAE,CAAC;QACjF,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|