@descryy/adapter-csharp 0.1.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.
@@ -0,0 +1,123 @@
1
+ /**
2
+ * D-FIX-3's client-base extractor — DEC-164's contract, and the first adapter
3
+ * in this project to build it. `client.ts` already reads a call's own literal
4
+ * path; this is the separate, larger row that row's own header named as
5
+ * unaddressed: what the receiver's *base* is, so a bare-relative call
6
+ * (`client.GetAsync("Users/Me")`, no leading slash) composes against
7
+ * something real instead of being refused for want of one.
8
+ *
9
+ * ## Two shapes built, and why not more
10
+ *
11
+ * §7's original audit named `services.AddHttpClient<T>(c => c.BaseAddress =
12
+ * new Uri(...))` as *the* pattern to build, on the strength of "jellyfin and
13
+ * eShopOnWeb both confirmed to use exactly this shape." Read against the real
14
+ * source, that premise does not hold for either named repository: jellyfin's
15
+ * own `AddHttpClient(NamedClient.Default, ...)` registrations
16
+ * (`Jellyfin.Server/Startup.cs`) never set `BaseAddress` at all, and
17
+ * eShopOnWeb has no `AddHttpClient<T>(...)` call anywhere.
18
+ *
19
+ * **What every one of both corpora's real `USES_API` edges (and several
20
+ * previously-silent call sites) actually goes through** is
21
+ * `WebApplicationFactory<TEntryPoint>.CreateClient(...)` — ASP.NET's own
22
+ * integration-test client, whose documented default `BaseAddress` is the
23
+ * application under test itself. `derivesFromWebApplicationFactory` (in
24
+ * `extract.ts`, where the type graph lives) is the whole mechanism: does the
25
+ * receiver's own class (directly, or through one in-repo indirection —
26
+ * `CustomWebApplicationFactory<TProgram> : WebApplicationFactory<TProgram>`
27
+ * is `CleanArchitecture`'s own shape) carry `WebApplicationFactory<` in its
28
+ * written base list. Measured: **100% of jellyfin's and eShopOnWeb's existing
29
+ * 27 `USES_API` edges, plus every previously-silent or previously-refused
30
+ * bare-relative call this row newly reaches, go through exactly this
31
+ * receiver.**
32
+ *
33
+ * The named `AddHttpClient<T>(...)` shape is real, just not in the two
34
+ * repositories the audit cited — `dotnet/eShop` has it
35
+ * (`WebApp/Extensions.cs`, `WebhookClient/Extensions.cs`,
36
+ * `HybridApp/MauiProgram.cs`, 4 sites), and every one of those typed clients'
37
+ * own call sites builds its path by string interpolation
38
+ * (`$"{remoteServiceBaseUrl}items/{id}"`), already and separately refused by
39
+ * `client.ts`'s "not a bare string literal" rule — so resolving this base
40
+ * moves **zero** measured edges in any corpus this row has on disk.
41
+ * {@link typedClientBases} below reads it anyway, narrowly (a literal string
42
+ * argument to `new Uri(...)`/`new(...)` only — a field, a config read, or any
43
+ * other expression stays `unresolved`, never guessed): the mechanism is real
44
+ * corpus evidence, not invented for a fixture, and golden pattern 08a needs a
45
+ * *non-empty* composed path to prove `DEC-097`'s composition is real rather
46
+ * than coincidentally correct when the prefix is always empty. No other DI
47
+ * mechanism — `IHttpClientFactory.CreateClient(name)`'s named-client form
48
+ * included — is read here; every such call was invisible before this row and
49
+ * stays exactly as invisible after it, a disclosed, unaffected limit rather
50
+ * than a claim this file makes and cannot back.
51
+ *
52
+ * ## The state built but never produced by real corpus evidence
53
+ *
54
+ * DEC-164 names four states; three are real here. `unresolved` is reachable
55
+ * in code (a `AddHttpClient<T>` registration whose `BaseAddress` is a field
56
+ * or a config read rather than a literal) but has zero witnesses in any of
57
+ * the six corpora this row measured — kept rather than deleted, the same way
58
+ * `efcore.ts`'s rival-ORM exclusion rule stays written down at zero
59
+ * witnesses: a real rule with no corpus evidence yet, not a guess.
60
+ */
61
+ /**
62
+ * DEC-097: only the origin — scheme, host, port — is stripped from an
63
+ * absolute URI; the path is kept. `undefined` when `uri` is not an absolute
64
+ * URI this reader can split (no `scheme://`); refused by the caller rather
65
+ * than guessed, same as every other shape in this file.
66
+ */
67
+ function pathPrefixOf(uri) {
68
+ const match = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^/]*(\/.*)?$/.exec(uri.trim());
69
+ if (match === null)
70
+ return undefined;
71
+ const path = match[1] ?? "";
72
+ return path === "/" ? "" : path.replace(/\/+$/, "");
73
+ }
74
+ /**
75
+ * `services.AddHttpClient<TClient>(o => o.BaseAddress = <expr>)` —
76
+ * `dotnet/eShop`'s own shape (`WebApp/Extensions.cs`,
77
+ * `WebhookClient/Extensions.cs`, `HybridApp/MauiProgram.cs`), read textually
78
+ * rather than through the AST (the same division of labour `aspnetcore.ts`
79
+ * and `efcore.ts` already keep for a fluent registration chain — see
80
+ * `extract.ts`'s own header for why). Keyed by `TClient`'s own written name
81
+ * (short, unqualified — matched the same way against the enclosing type's own
82
+ * simple name, a disclosed limit rather than a full type resolution this
83
+ * textual pass cannot do): DI hands the configured client straight to
84
+ * `TClient`'s own constructor, so a call inside `TClient` whose receiver
85
+ * resolves to a bare, otherwise-untraced `HttpClient` is exactly this base.
86
+ *
87
+ * The RHS is matched as `new(...)`/`new Uri(...)`'s own single argument —
88
+ * not "everything up to the next `;`", which real `eShop` source would get
89
+ * wrong: `AddHttpClient<CatalogService>(o => o.BaseAddress = new(...))` is
90
+ * followed by a fluent chain (`.AddApiVersion(2.0).AddAuthToken();`) whose
91
+ * terminating `;` is lines away and whose own parentheses would otherwise be
92
+ * swallowed into the "expression." Real corpus shapes have no nested parens
93
+ * inside the argument itself (a string literal, or a bare field reference),
94
+ * so matching up to the first `)` is exact for both, not an approximation.
95
+ * A bare string literal (`new Uri("https+http://catalog-api")`,
96
+ * `new("http://webhooks-api")`) resolves; anything else (`new(MobileBffHost)`
97
+ * — a static field, `eShop`'s own `HybridApp/MauiProgram.cs`) is `unresolved`
98
+ * with the argument's own text as `why`. Both are measured, not invented for
99
+ * this file.
100
+ */
101
+ export function typedClientBases(files) {
102
+ const bases = new Map();
103
+ const pattern = /AddHttpClient\s*<\s*([A-Za-z_][A-Za-z0-9_.]*)\s*>\s*\(\s*[A-Za-z_][A-Za-z0-9_]*\s*=>[\s\S]{0,240}?\.BaseAddress\s*=\s*new(?:\s+Uri)?\s*\(\s*([^)]*)\)/g;
104
+ for (const { source } of files) {
105
+ for (const match of source.matchAll(pattern)) {
106
+ const clientType = match[1];
107
+ const argument = match[2]?.trim();
108
+ if (clientType === undefined || argument === undefined || bases.has(clientType))
109
+ continue;
110
+ const literal = /^"([^"]*)"$/.exec(argument);
111
+ if (literal === null) {
112
+ bases.set(clientType, { state: "unresolved", why: argument });
113
+ continue;
114
+ }
115
+ const path = pathPrefixOf(literal[1] ?? "");
116
+ if (path === undefined)
117
+ continue; // not an absolute URI this reader can split — leave untraced
118
+ bases.set(clientType, { state: "resolved", path });
119
+ }
120
+ }
121
+ return bases;
122
+ }
123
+ //# sourceMappingURL=client-base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-base.js","sourceRoot":"","sources":["../src/client-base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AAsCH;;;;;GAKG;AACH,SAAS,YAAY,CAAC,GAAW;IAC/B,MAAM,KAAK,GAAG,4CAA4C,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5E,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACrC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,OAAO,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA6C;IAC5E,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAC;IAClD,MAAM,OAAO,GACX,wJAAwJ,CAAC;IAC3J,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7C,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC5B,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YAClC,IAAI,UAAU,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;gBAAE,SAAS;YAE1F,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC7C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAC9D,SAAS;YACX,CAAC;YACD,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5C,IAAI,IAAI,KAAK,SAAS;gBAAE,SAAS,CAAC,6DAA6D;YAC/F,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * D-FIX-3's C# half: a call through a known HTTP client is disclosed, never
3
+ * silent — even though this adapter extracts no `USES_API` edges in C# at
4
+ * all yet.
5
+ *
6
+ * ## Why disclosure without extraction is the right first producer here
7
+ *
8
+ * Java's `client.ts` extracts real edges for Spring's clients and files a
9
+ * ledger row for the shapes it cannot read. C# has no extraction path at
10
+ * all — `capabilities()` already declares no `USES_API` for this adapter
11
+ * (PROGRESS.md), so *every* call through a known client is unclaimed today.
12
+ * Building the extractor itself (reading `GetAsync("/orders/{id}")`'s literal
13
+ * path, the way `bench/client-call-census.mjs`'s C# census shows is
14
+ * structurally the same shape as Spring's `RestTemplate` — the URL is the
15
+ * call's own first argument, not a separately built request object) is a
16
+ * **separate, larger row**: it needs the DEC-129 counting-first admission
17
+ * this project requires before an extractor ships, a golden fixture change,
18
+ * and a capability declaration tested against pattern 08 the way DEC-195
19
+ * records for Java. That is not built here.
20
+ *
21
+ * What *is* in scope, and small: recognise the receiver's declared type and
22
+ * turn "nothing" into a disclosed refusal, so `0 USES_API edges` stops being
23
+ * indistinguishable from "no HTTP calls in this codebase" — the exact
24
+ * distinction DEC-113's ledger exists to carry, and the reason a `cf-worker`
25
+ * zero and a `sherpa-frontend` zero are different facts.
26
+ *
27
+ * ## The bounded population, measured before it was picked
28
+ *
29
+ * `bench/client-call-census.mjs csharp` names `HttpClient`, `IHttpClientFactory`,
30
+ * `HttpRequestMessage` and `RestClient` as candidates. Measured directly against
31
+ * this row: `RestClient` (RestSharp's type) has **zero** occurrences across all
32
+ * six C# reference corpora (`jellyfin`, `eShop`, `eShopOnWeb`, `Ocelot`,
33
+ * `CleanArchitecture`, `Dapper`) — counted, not assumed, the same way DEC-129
34
+ * counted before admitting a corpus. `IHttpClientFactory` produces an
35
+ * `HttpClient` from `CreateClient()`; the client census's 61 relative-path call
36
+ * sites are all through `HttpClient` variables and fields once the factory call
37
+ * has already returned. So the known-type set here is **just `HttpClient`** —
38
+ * narrower than the census's candidate list, on a measurement rather than a
39
+ * guess, and it can widen the day a corpus exercises `RestClient` for real.
40
+ *
41
+ * `HttpRequestMessage` is not a receiver in any of the census's call sites — it
42
+ * is the *argument* to `SendAsync`, never the thing a verb method is called on
43
+ * — so it does not belong in a receiver-type set at all; including it would
44
+ * have been the coarser-than-node-key mistake DEC-165/187 already paid for once.
45
+ *
46
+ * ## Origin check, added after DEC-260
47
+ *
48
+ * The first pass of this file filed every candidate as "no extractor," with no
49
+ * distinction between a call whose literal path stays inside this repository
50
+ * and one that names a different origin outright — a divergence from Java's
51
+ * `client.ts`, which has always told the two apart. DEC-260 §3 names the
52
+ * consequence directly: two adapters disagreeing on the same refusal shape
53
+ * corrupts `refusalClass` (DEC-242) the moment a consumer trusts it, because
54
+ * C# would systematically over-report `capability-gap` against Java's
55
+ * classifier on the same underlying population.
56
+ *
57
+ * **Not Java's exact predicate, on purpose — measured, not assumed.** A first
58
+ * attempt reused Java's "does not start with `/`" rule verbatim and ran it
59
+ * against the real admitted corpora before calling the row done, per this
60
+ * project's own discipline. It misfired: `jellyfin` and `eShopOnWeb` both pass
61
+ * a **bare relative path with no leading slash** (`"Users/New"`) to `HttpClient`
62
+ * calls resolved against `HttpClient.BaseAddress` at run time — a shape Java's
63
+ * own population never contains, so Java's rule was never tested against it.
64
+ * Every such call site found is an integration test through
65
+ * `_factory.CreateClient()`, ASP.NET's in-process test client pointed at the
66
+ * application under test — a same-repository call this reader was about to
67
+ * mislabel as "another origin." See {@link namesAnotherOrigin}'s own comment
68
+ * for the corrected, narrower rule. This origin check was later carried back
69
+ * into `adapter-java`'s own `relativePath` rule, which carried the identical
70
+ * latent defect (`adapter-java` `1bfd2ae`) — the two adapters now agree on
71
+ * this shape by construction, not by two independently-tuned rules.
72
+ *
73
+ * ## Extraction, built on the shape the origin check already separated out
74
+ *
75
+ * `DEC-241` §4 named this row: `HttpClient`'s verb methods take the path as
76
+ * their **own first argument** — `GetAsync("/orders/{id}")`, never a
77
+ * separately built request object the way `OkHttpClient`/`java.net.http.HttpClient`
78
+ * require — the same structurally-straightforward shape Java's `RestTemplate`
79
+ * already extracts from. `clientCalls` below mints a real `USES_API` edge for
80
+ * every call whose receiver is a known client type, whose method names a
81
+ * literal verb, and whose path is a repository-relative literal
82
+ * (`relativePath`, unchanged from the origin check's own reasoning) — and
83
+ * files a ledger row, never silently drops the call, for every other shape:
84
+ * an unrecognised verb (`SendAsync`, which takes a pre-built
85
+ * `HttpRequestMessage` — verb and path both live inside an object this reader
86
+ * does not open), a non-literal path, an origin outside this repository, or a
87
+ * bare relative path this reader genuinely cannot place (the same
88
+ * `BaseAddress`-resolved shape the origin check exists to disclose rather
89
+ * than guess).
90
+ */
91
+ import { type IdentityScope, type IRNode } from "@descryy/ir";
92
+ import type { CsRef } from "./parse.ts";
93
+ import type { ClientBaseResult } from "./client-base.ts";
94
+ export interface ClientCall {
95
+ /** The `FUNCTION` node making the call. */
96
+ readonly fromId: string;
97
+ readonly method: string;
98
+ readonly template: string;
99
+ readonly verb: string;
100
+ readonly line: number;
101
+ /** `test` when the enclosing method is a test case, else `production`. */
102
+ readonly callerKind: "test" | "production";
103
+ /** DEC-164's contract, resolved by `extract.ts`'s `client-base.ts` pass. See that file's own header. */
104
+ readonly clientBase: ClientBaseResult;
105
+ }
106
+ export interface ClientRefusal {
107
+ readonly fromId: string;
108
+ readonly raw: string;
109
+ readonly line: number;
110
+ readonly reason: string;
111
+ /** DEC-242's `attrs.blockedBy` — the literal blocking expression, or `null`. */
112
+ readonly blockedBy: string | null;
113
+ /** DEC-242's `attrs.refusalClass` — `undefined` means unclassified, never askable. */
114
+ readonly refusalClass: BaseRefusalClass | "out-of-scope" | undefined;
115
+ /**
116
+ * Diagnostic only, not part of DEC-242 — see `adapter-rust/src/client.ts`'s
117
+ * own doc for what this is and why it is not shipped as part of the
118
+ * contract. Present only on the generic fallthrough of `diagnoseArgument`.
119
+ */
120
+ readonly argumentKind?: "field" | "call" | "concatenation" | "other";
121
+ /**
122
+ * Present only when the refusal is DEC-164's own `unresolved` state — a
123
+ * base-setting mechanism was found but its value could not be read as a
124
+ * literal. Zero witnesses in this row's six corpora; see `client-base.ts`'s
125
+ * own header for why the mechanism that would produce this is not built.
126
+ */
127
+ readonly clientBase?: ClientBaseResult;
128
+ }
129
+ export type BaseRefusalClass = "value-unknown" | "varies-per-call" | "capability-gap";
130
+ /**
131
+ * Every reference {@link clientCalls} will act on — an unbounded receiver
132
+ * type still makes it a true silence past this point, exactly as in Java. See
133
+ * `client.test.ts` for the reconciliation this makes checkable: every
134
+ * candidate whose type resolves lands in either `calls` or `refusals`, with
135
+ * nothing else.
136
+ */
137
+ export declare function candidateClientRefs(refs: readonly CsRef[]): readonly (CsRef & {
138
+ readonly receiver: string;
139
+ })[];
140
+ /**
141
+ * Read one method's calls for outbound HTTP.
142
+ *
143
+ * `typeOfReceiver` is supplied by `extract.ts`, which already has the scope
144
+ * tables (`fn.scope.locals`, the enclosing type's members) a second copy of
145
+ * here would drift from — the same division of labour as Java's `client.ts`.
146
+ *
147
+ * `clientBaseOfReceiver` is DEC-164's contract (`client-base.ts`'s own
148
+ * header): a per-call determination of what base, if any, this reader traced
149
+ * for the receiver. Called only for refs that already passed the known-client-
150
+ * type gate below, matching `typeOfReceiver`'s own division of labour.
151
+ */
152
+ export declare function clientCalls(refs: readonly CsRef[], fromId: string, typeOfReceiver: (ref: CsRef & {
153
+ readonly receiver: string;
154
+ }) => string | undefined, isTest: boolean, parameterNames: ReadonlySet<string>, clientBaseOfReceiver: (ref: CsRef & {
155
+ readonly receiver: string;
156
+ }) => ClientBaseResult): {
157
+ readonly calls: readonly ClientCall[];
158
+ readonly refusals: readonly ClientRefusal[];
159
+ };
160
+ /**
161
+ * The `API_ENDPOINT` a call joins to — minted identically to the route side.
162
+ *
163
+ * Shares `endpointQsp` with `extract.ts`'s `SERVES_API` block rather than
164
+ * recomputing the id, because the two must agree exactly and the failure when
165
+ * they do not is silent.
166
+ */
167
+ export declare function endpointFor(scope: IdentityScope, call: ClientCall, producedBy: string, normalise: (template: string) => string): IRNode;
168
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyFG;AAEH,OAAO,EAAuB,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAEnF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,CAAC;IAC3C,wGAAwG;IACxG,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,sFAAsF;IACtF,QAAQ,CAAC,YAAY,EAAE,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAC;IACrE;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,eAAe,GAAG,OAAO,CAAC;IACrE;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CACxC;AAkBD,MAAM,MAAM,gBAAgB,GAAG,eAAe,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AA8HtF;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,KAAK,EAAE,GAAG,SAAS,CAAC,KAAK,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,CAS9G;AAwBD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,SAAS,KAAK,EAAE,EACtB,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAK,MAAM,GAAG,SAAS,EAClF,MAAM,EAAE,OAAO,EACf,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,EACnC,oBAAoB,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAK,gBAAgB,GACrF;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,CAoIxF;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GACtC,MAAM,CAaR"}