@bravely-studios/account-web 0.3.4
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/LICENSE +10 -0
- package/README.md +262 -0
- package/dist/ActivationStateMachine.d.ts +50 -0
- package/dist/ActivationStateMachine.d.ts.map +1 -0
- package/dist/ActivationStateMachine.js +141 -0
- package/dist/ActivationStateMachine.js.map +1 -0
- package/dist/BravelyAccountManager.d.ts +156 -0
- package/dist/BravelyAccountManager.d.ts.map +1 -0
- package/dist/BravelyAccountManager.js +621 -0
- package/dist/BravelyAccountManager.js.map +1 -0
- package/dist/EntitlementCache.d.ts +50 -0
- package/dist/EntitlementCache.d.ts.map +1 -0
- package/dist/EntitlementCache.js +116 -0
- package/dist/EntitlementCache.js.map +1 -0
- package/dist/components/ActivationLadder.d.ts +78 -0
- package/dist/components/ActivationLadder.d.ts.map +1 -0
- package/dist/components/ActivationLadder.js +145 -0
- package/dist/components/ActivationLadder.js.map +1 -0
- package/dist/components/CrossAppCard.d.ts +48 -0
- package/dist/components/CrossAppCard.d.ts.map +1 -0
- package/dist/components/CrossAppCard.js +45 -0
- package/dist/components/CrossAppCard.js.map +1 -0
- package/dist/deprecation.d.ts +19 -0
- package/dist/deprecation.d.ts.map +1 -0
- package/dist/deprecation.js +83 -0
- package/dist/deprecation.js.map +1 -0
- package/dist/displayName.d.ts +15 -0
- package/dist/displayName.d.ts.map +1 -0
- package/dist/displayName.js +41 -0
- package/dist/displayName.js.map +1 -0
- package/dist/dpop.d.ts +30 -0
- package/dist/dpop.d.ts.map +1 -0
- package/dist/dpop.js +87 -0
- package/dist/dpop.js.map +1 -0
- package/dist/hooks/useActivationLaneFromUrl.d.ts +54 -0
- package/dist/hooks/useActivationLaneFromUrl.d.ts.map +1 -0
- package/dist/hooks/useActivationLaneFromUrl.js +105 -0
- package/dist/hooks/useActivationLaneFromUrl.js.map +1 -0
- package/dist/hooks/useFreshLaunchRestoration.d.ts +62 -0
- package/dist/hooks/useFreshLaunchRestoration.d.ts.map +1 -0
- package/dist/hooks/useFreshLaunchRestoration.js +135 -0
- package/dist/hooks/useFreshLaunchRestoration.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/oauth.d.ts +50 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +107 -0
- package/dist/oauth.js.map +1 -0
- package/dist/storage.d.ts +48 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +153 -0
- package/dist/storage.js.map +1 -0
- package/dist/types.d.ts +172 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
// `BravelyAccountManager` — the thin web facade over the Bravely identity API.
|
|
2
|
+
//
|
|
3
|
+
// Wraps OAuth 2.1 + PKCE sign-in, BAS lifecycle, the 72h entitlement cache,
|
|
4
|
+
// the activation state machine, and the `Bravely-Deprecation` header
|
|
5
|
+
// handler. Used by the 9 utility web variants + bravely.dev.
|
|
6
|
+
//
|
|
7
|
+
// Public surface mirrors the platform facades on iOS/Mac/Windows/Android.
|
|
8
|
+
import { preparePkce, parseCallback } from "./oauth.js";
|
|
9
|
+
import { defaultStorage } from "./storage.js";
|
|
10
|
+
import { EntitlementCache } from "./EntitlementCache.js";
|
|
11
|
+
import { ActivationStateMachine, POST_CHECKOUT_RETRY } from "./ActivationStateMachine.js";
|
|
12
|
+
import { generateKeypair, generateProof } from "./dpop.js";
|
|
13
|
+
import { parseDeprecation, BravelyClientKilledError, OAuthError, } from "./deprecation.js";
|
|
14
|
+
/** Default identity API origin. */
|
|
15
|
+
const DEFAULT_IDENTITY = "https://identity.bravely.dev";
|
|
16
|
+
/** Default OAuth scope. */
|
|
17
|
+
const DEFAULT_SCOPE = "bravely.account bravely.entitlements";
|
|
18
|
+
/** Keys we persist via the storage abstraction. */
|
|
19
|
+
const KEY_BAS = "bas";
|
|
20
|
+
const KEY_REFRESH = "refresh_token";
|
|
21
|
+
const KEY_BA_ID = "ba_id";
|
|
22
|
+
const KEY_EMAIL = "email";
|
|
23
|
+
const KEY_DPOP_JKT = "dpop_jkt_thumbprint";
|
|
24
|
+
const KEY_PKCE_VERIFIER = "pkce_verifier";
|
|
25
|
+
const KEY_PKCE_STATE = "pkce_state";
|
|
26
|
+
export class BravelyAccountManager {
|
|
27
|
+
cfg;
|
|
28
|
+
storage;
|
|
29
|
+
cache;
|
|
30
|
+
activation;
|
|
31
|
+
state = { kind: "signed_out" };
|
|
32
|
+
listeners = new Set();
|
|
33
|
+
libVersionPolicy = null;
|
|
34
|
+
dpopKeypairPromise = null;
|
|
35
|
+
dpopJktThumbprint = null;
|
|
36
|
+
constructor(config) {
|
|
37
|
+
if (!config.authority)
|
|
38
|
+
throw new Error("authority is required");
|
|
39
|
+
if (!config.appSlug)
|
|
40
|
+
throw new Error("appSlug is required");
|
|
41
|
+
if (!config.clientVersion)
|
|
42
|
+
throw new Error("clientVersion is required");
|
|
43
|
+
const redirectUri = config.redirectUri ??
|
|
44
|
+
(typeof globalThis !== "undefined" && globalThis.location?.origin
|
|
45
|
+
? `${globalThis.location.origin}/auth/callback`
|
|
46
|
+
: "https://example.invalid/auth/callback");
|
|
47
|
+
this.cfg = {
|
|
48
|
+
authority: stripTrailingSlash(config.authority),
|
|
49
|
+
appSlug: config.appSlug,
|
|
50
|
+
clientVersion: config.clientVersion,
|
|
51
|
+
identityOrigin: stripTrailingSlash(config.identityOrigin ?? DEFAULT_IDENTITY),
|
|
52
|
+
redirectUri,
|
|
53
|
+
scope: config.scope ?? DEFAULT_SCOPE,
|
|
54
|
+
libName: config.libName ?? "bravely-account-web",
|
|
55
|
+
libVersion: config.libVersion ?? "0.3.4",
|
|
56
|
+
};
|
|
57
|
+
this.storage = config.storage ?? defaultStorage();
|
|
58
|
+
this.cache = new EntitlementCache({ storage: this.storage });
|
|
59
|
+
this.activation = new ActivationStateMachine("idle");
|
|
60
|
+
}
|
|
61
|
+
// ---- public API ---------------------------------------------------------
|
|
62
|
+
/**
|
|
63
|
+
* Return the current state. The returned reference is **stable across
|
|
64
|
+
* calls** until `setState()` is invoked — i.e. while the state has not
|
|
65
|
+
* changed, two consecutive `getState()` calls produce values for which
|
|
66
|
+
* `Object.is(a, b)` is true.
|
|
67
|
+
*
|
|
68
|
+
* This is the contract React 19's `useSyncExternalStore` requires: the
|
|
69
|
+
* `getSnapshot` callback must return `===` identical values until the
|
|
70
|
+
* `subscribe` callback fires. Returning a fresh clone on every read (which
|
|
71
|
+
* an earlier version of this facade did) triggers React error #185 —
|
|
72
|
+
* "Maximum update depth exceeded" — because the snapshot keeps "changing"
|
|
73
|
+
* even when nothing has happened.
|
|
74
|
+
*
|
|
75
|
+
* The clone happens once, at write time, inside `setState()`. Listeners
|
|
76
|
+
* receive the same reference this method returns until the next
|
|
77
|
+
* `setState()` swaps in a new canonical clone.
|
|
78
|
+
*/
|
|
79
|
+
getState() {
|
|
80
|
+
return this.state;
|
|
81
|
+
}
|
|
82
|
+
onStateChange(cb) {
|
|
83
|
+
this.listeners.add(cb);
|
|
84
|
+
return () => this.listeners.delete(cb);
|
|
85
|
+
}
|
|
86
|
+
getActivationState() {
|
|
87
|
+
return this.activation.current();
|
|
88
|
+
}
|
|
89
|
+
getLibVersionPolicy() {
|
|
90
|
+
return this.libVersionPolicy ? { ...this.libVersionPolicy } : null;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Hydrate from persistent storage and (if a BAS is present) verify it
|
|
94
|
+
* against the identity API. Call once on page load before rendering UI
|
|
95
|
+
* that depends on `getState()`.
|
|
96
|
+
*/
|
|
97
|
+
async restore() {
|
|
98
|
+
await this.cache.hydrate();
|
|
99
|
+
const bas = await this.storage.get(KEY_BAS);
|
|
100
|
+
const baId = await this.storage.get(KEY_BA_ID);
|
|
101
|
+
const email = await this.storage.get(KEY_EMAIL);
|
|
102
|
+
if (!bas || !baId || !email) {
|
|
103
|
+
this.activation.transition("app_launched_no_session", { bas_present: false });
|
|
104
|
+
return this.setState({ kind: "signed_out" });
|
|
105
|
+
}
|
|
106
|
+
// Serve cached entitlements immediately if fresh.
|
|
107
|
+
this.activation.transition("app_launched", { bas_present: true });
|
|
108
|
+
const cached = this.cache.getCached();
|
|
109
|
+
const cachedEntitlements = cached?.entitlements ?? [];
|
|
110
|
+
if (cached) {
|
|
111
|
+
this.activation.transition("bas_found");
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// No valid entitlement cache: show the M2 fresh-launch lane until the
|
|
115
|
+
// background entitlement check resolves to Pro, free, or failed.
|
|
116
|
+
this.activation.force("fresh_launch_restoration");
|
|
117
|
+
}
|
|
118
|
+
this.setState({ kind: "signed_in", ba_id: baId, email, bas, entitlements: cachedEntitlements });
|
|
119
|
+
// Refresh in the background; failures fall back to cache.
|
|
120
|
+
void this.refreshEntitlements().catch(() => {
|
|
121
|
+
// Already handled by transition logic; nothing else to do.
|
|
122
|
+
});
|
|
123
|
+
return this.getState();
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Begin the OAuth 2.1 + PKCE sign-in dance. Resolves to the new state. If
|
|
127
|
+
* the browser is at the start of the dance, this triggers a redirect
|
|
128
|
+
* (and the promise effectively never resolves before unload). If the
|
|
129
|
+
* browser is on the callback URL with `?code=...&state=...`, this finishes
|
|
130
|
+
* the exchange.
|
|
131
|
+
*/
|
|
132
|
+
async signIn(opts = {}) {
|
|
133
|
+
this.setState({ kind: "signing_in", pending: true });
|
|
134
|
+
// Detect callback (browser already returned from the authorize endpoint).
|
|
135
|
+
const callback = typeof location !== "undefined" ? parseCallback(location.href) : null;
|
|
136
|
+
if (callback) {
|
|
137
|
+
try {
|
|
138
|
+
return await this.completeAuthorization(callback.code, callback.state);
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
return this.setState({ kind: "failed", error: errorMessage(err) });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Otherwise, kick off the redirect.
|
|
145
|
+
const { verifier, state, authorizeUrl } = await preparePkce({
|
|
146
|
+
authority: this.cfg.authority,
|
|
147
|
+
clientId: this.cfg.appSlug,
|
|
148
|
+
redirectUri: this.cfg.redirectUri,
|
|
149
|
+
scope: this.cfg.scope,
|
|
150
|
+
loginHint: opts.loginHint,
|
|
151
|
+
});
|
|
152
|
+
await this.storage.set(KEY_PKCE_VERIFIER, verifier);
|
|
153
|
+
await this.storage.set(KEY_PKCE_STATE, state);
|
|
154
|
+
if (typeof location !== "undefined") {
|
|
155
|
+
location.assign(authorizeUrl);
|
|
156
|
+
}
|
|
157
|
+
return this.getState(); // technically unreachable past the navigation
|
|
158
|
+
}
|
|
159
|
+
/** Sign out: drop local state. Server-side revoke is best-effort. */
|
|
160
|
+
async signOut() {
|
|
161
|
+
try {
|
|
162
|
+
const bas = await this.storage.get(KEY_BAS);
|
|
163
|
+
if (bas) {
|
|
164
|
+
// Fire-and-forget revoke; if the OAuth server doesn't have a revoke
|
|
165
|
+
// endpoint yet (Gate 1), this is a no-op. Wrapped in try/catch so
|
|
166
|
+
// network failures don't block sign-out.
|
|
167
|
+
await this.fetchWithDeprecation(`${this.cfg.authority}/oauth/revoke`, {
|
|
168
|
+
method: "POST",
|
|
169
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
170
|
+
body: new URLSearchParams({ token: bas, client_id: this.cfg.appSlug }).toString(),
|
|
171
|
+
}).catch(() => undefined);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
await this.storage.remove(KEY_BAS);
|
|
176
|
+
await this.storage.remove(KEY_REFRESH);
|
|
177
|
+
await this.storage.remove(KEY_BA_ID);
|
|
178
|
+
await this.storage.remove(KEY_EMAIL);
|
|
179
|
+
await this.storage.remove(KEY_DPOP_JKT);
|
|
180
|
+
await this.cache.invalidate();
|
|
181
|
+
this.dpopKeypairPromise = null;
|
|
182
|
+
this.dpopJktThumbprint = null;
|
|
183
|
+
this.setState({ kind: "signed_out" });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Read entitlements, serving the cached row if fresh and refreshing
|
|
188
|
+
* opportunistically. Always returns an array (possibly empty).
|
|
189
|
+
*/
|
|
190
|
+
async getEntitlements() {
|
|
191
|
+
const cached = this.cache.getCached();
|
|
192
|
+
if (cached) {
|
|
193
|
+
// Fresh; refresh in background.
|
|
194
|
+
void this.refreshEntitlements().catch(() => undefined);
|
|
195
|
+
return cached.entitlements;
|
|
196
|
+
}
|
|
197
|
+
return this.refreshEntitlements();
|
|
198
|
+
}
|
|
199
|
+
/** Convenience: check a single entitlement (e.g. `diskaroo_pro`). */
|
|
200
|
+
async hasEntitlement(lookupKey) {
|
|
201
|
+
const ents = await this.getEntitlements();
|
|
202
|
+
return ents.some((e) => e.lookup_key === lookupKey);
|
|
203
|
+
}
|
|
204
|
+
/** Mint an app-data-token for apps that need direct Firebase SDK access. */
|
|
205
|
+
async getAppDataToken() {
|
|
206
|
+
const bas = await this.requireBas();
|
|
207
|
+
const res = await this.fetchWithBas(`${this.cfg.identityOrigin}/api/app-data-token`, bas, {
|
|
208
|
+
method: "POST",
|
|
209
|
+
headers: { "Content-Type": "application/json" },
|
|
210
|
+
body: JSON.stringify({ app_slug: this.cfg.appSlug }),
|
|
211
|
+
});
|
|
212
|
+
if (!res.ok)
|
|
213
|
+
throw new Error(`getAppDataToken failed: ${res.status}`);
|
|
214
|
+
const data = (await res.json());
|
|
215
|
+
return data.app_data_token;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Open Paddle hosted-checkout for the given plan. Hits
|
|
219
|
+
* `/api/checkout/sessions` (BAS-authed), opens the returned URL via the
|
|
220
|
+
* system browser (`window.open(url, '_blank')`). The promise resolves once
|
|
221
|
+
* the request returns; the caller is responsible for polling
|
|
222
|
+
* `getEntitlements()` (or watching `getActivationState()`) for the
|
|
223
|
+
* post-checkout activation.
|
|
224
|
+
*/
|
|
225
|
+
async openCheckout(plan) {
|
|
226
|
+
const bas = await this.requireBas();
|
|
227
|
+
const res = await this.fetchWithBas(`${this.cfg.identityOrigin}/api/checkout/sessions`, bas, {
|
|
228
|
+
method: "POST",
|
|
229
|
+
headers: { "Content-Type": "application/json" },
|
|
230
|
+
body: JSON.stringify({ app_slug: this.cfg.appSlug, plan }),
|
|
231
|
+
});
|
|
232
|
+
if (!res.ok)
|
|
233
|
+
throw new Error(`openCheckout failed: ${res.status}`);
|
|
234
|
+
const data = (await res.json());
|
|
235
|
+
if (typeof globalThis !== "undefined" && globalThis.open) {
|
|
236
|
+
globalThis.open(data.checkout_url, "_blank");
|
|
237
|
+
}
|
|
238
|
+
// The host page should now drive the activation state machine via:
|
|
239
|
+
// manager.notifyCheckoutCompleted() once the user returns.
|
|
240
|
+
this.activation.transition("checkout_completed");
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Mint a Paddle customer-portal session for the signed-in account.
|
|
244
|
+
* Consumers decide how to open `session.url`; checkout activation state is
|
|
245
|
+
* intentionally unchanged.
|
|
246
|
+
*/
|
|
247
|
+
async createPaddlePortalSession() {
|
|
248
|
+
const bas = await this.requireBas();
|
|
249
|
+
const res = await this.fetchWithBas(`${this.cfg.identityOrigin}/api/paddle-portal`, bas, {
|
|
250
|
+
method: "POST",
|
|
251
|
+
headers: { "Content-Type": "application/json" },
|
|
252
|
+
body: JSON.stringify({ app_slug: this.cfg.appSlug }),
|
|
253
|
+
});
|
|
254
|
+
if (!res.ok)
|
|
255
|
+
throw new Error(`createPaddlePortalSession failed: ${res.status}`);
|
|
256
|
+
return (await res.json());
|
|
257
|
+
}
|
|
258
|
+
/** Inform the manager that checkout completion was observed. */
|
|
259
|
+
notifyCheckoutCompleted() {
|
|
260
|
+
this.activation.transition("checkout_completed");
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Return the active entitlements that count as "cross-app" for the M4
|
|
264
|
+
* `<CrossAppCard>`. Excludes the current app's own `<slug>_pro` token.
|
|
265
|
+
* `bravely_premium` (the bundle entitlement) is included — it's the
|
|
266
|
+
* unifying signal that drives the M4 copy ("You own N Bravely Pro
|
|
267
|
+
* apps").
|
|
268
|
+
*
|
|
269
|
+
* Reads from the in-memory signed-in state (which mirrors the
|
|
270
|
+
* `EntitlementCache`); does not hit the network. Host pages that need a
|
|
271
|
+
* fresh fetch should call `getEntitlements()` first.
|
|
272
|
+
*/
|
|
273
|
+
crossAppEntitlements() {
|
|
274
|
+
const ents = this.state.kind === "signed_in" ? this.state.entitlements : [];
|
|
275
|
+
const own = `${this.cfg.appSlug}_pro`;
|
|
276
|
+
return ents.filter((e) => e.lookup_key !== own);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Run the canonical M3 post-checkout activation polling loop against
|
|
280
|
+
* `/api/entitlements?app=<slug>`. Uses the retry budget locked in
|
|
281
|
+
* `POST_CHECKOUT_RETRY` (30 retries, 1s..8s capped exponential
|
|
282
|
+
* backoff). Fires the right activation state events as it runs.
|
|
283
|
+
*
|
|
284
|
+
* Returns:
|
|
285
|
+
* - `{ outcome: "active" }` as soon as an entitlement is observed
|
|
286
|
+
* (typically `<currentApp>_pro` or `bravely_premium`).
|
|
287
|
+
* - `{ outcome: "exhausted" }` after `maxRetries` attempts without an
|
|
288
|
+
* active entitlement.
|
|
289
|
+
* - `{ outcome: "timeout" }` if total elapsed time hits the auto-
|
|
290
|
+
* advance ceiling for `post_checkout_activation` (120s).
|
|
291
|
+
* - `{ outcome: "not_signed_in" }` if no BAS is present.
|
|
292
|
+
*
|
|
293
|
+
* The promise resolves regardless of network failures. Each failure
|
|
294
|
+
* is treated as an inactive poll (the user's purchase is still safe;
|
|
295
|
+
* the activation state machine surfaces this via the ladder copy).
|
|
296
|
+
*/
|
|
297
|
+
async pollForActivation() {
|
|
298
|
+
const bas = await this.storage.get(KEY_BAS);
|
|
299
|
+
if (!bas) {
|
|
300
|
+
return { outcome: "not_signed_in" };
|
|
301
|
+
}
|
|
302
|
+
// Force the state machine into `post_checkout_activation` if it isn't
|
|
303
|
+
// there already so the host page's ladder mounts.
|
|
304
|
+
if (this.activation.current().name !== "post_checkout_activation") {
|
|
305
|
+
this.activation.force("post_checkout_activation");
|
|
306
|
+
}
|
|
307
|
+
const startedAt = Date.now();
|
|
308
|
+
const timeoutMs = 120_000;
|
|
309
|
+
let attempts = 0;
|
|
310
|
+
let backoffMs = POST_CHECKOUT_RETRY.initialBackoffMs;
|
|
311
|
+
while (attempts < POST_CHECKOUT_RETRY.maxRetries) {
|
|
312
|
+
if (Date.now() - startedAt >= timeoutMs) {
|
|
313
|
+
this.activation.transition("activation_timed_out");
|
|
314
|
+
return { outcome: "timeout", attempts };
|
|
315
|
+
}
|
|
316
|
+
attempts += 1;
|
|
317
|
+
let entitlements = [];
|
|
318
|
+
try {
|
|
319
|
+
const url = new URL("/api/entitlements", this.cfg.identityOrigin);
|
|
320
|
+
url.searchParams.set("app", this.cfg.appSlug);
|
|
321
|
+
const res = await this.fetchWithBas(url.toString(), bas, {
|
|
322
|
+
method: "GET",
|
|
323
|
+
});
|
|
324
|
+
if (res.ok) {
|
|
325
|
+
const snapshot = (await res.json());
|
|
326
|
+
entitlements = snapshot.active_entitlements.map((lk) => ({
|
|
327
|
+
lookup_key: lk,
|
|
328
|
+
expires_at: null,
|
|
329
|
+
will_renew: false,
|
|
330
|
+
store: null,
|
|
331
|
+
}));
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
// Network blip — treat as inactive poll; the ladder copy is
|
|
336
|
+
// already user-safe ("your purchase is safe").
|
|
337
|
+
}
|
|
338
|
+
// An "active" poll requires at least one entitlement to be present.
|
|
339
|
+
// Host pages typically check for `<app>_pro` or `bravely_premium`,
|
|
340
|
+
// but the activation lane only cares that *something* came back.
|
|
341
|
+
if (entitlements.length > 0) {
|
|
342
|
+
await this.cache.update({ entitlements, dpopJktThumbprint: this.dpopJktThumbprint });
|
|
343
|
+
if (this.state.kind === "signed_in") {
|
|
344
|
+
this.setState({ ...this.state, entitlements });
|
|
345
|
+
}
|
|
346
|
+
this.activation.transition("activation_polled_active");
|
|
347
|
+
return { outcome: "active", entitlements, attempts };
|
|
348
|
+
}
|
|
349
|
+
this.activation.transition("activation_polled_inactive");
|
|
350
|
+
// If we've already hit the retry ceiling don't sleep — exit.
|
|
351
|
+
if (attempts >= POST_CHECKOUT_RETRY.maxRetries)
|
|
352
|
+
break;
|
|
353
|
+
// Bail early if the next sleep would push us over the timeout.
|
|
354
|
+
const sleepMs = Math.min(backoffMs, POST_CHECKOUT_RETRY.maxBackoffMs);
|
|
355
|
+
if (Date.now() - startedAt + sleepMs >= timeoutMs) {
|
|
356
|
+
this.activation.transition("activation_timed_out");
|
|
357
|
+
return { outcome: "timeout", attempts };
|
|
358
|
+
}
|
|
359
|
+
await sleep(sleepMs);
|
|
360
|
+
backoffMs = Math.min(backoffMs * POST_CHECKOUT_RETRY.backoffMultiplier, POST_CHECKOUT_RETRY.maxBackoffMs);
|
|
361
|
+
}
|
|
362
|
+
return { outcome: "exhausted", attempts };
|
|
363
|
+
}
|
|
364
|
+
// ---- internals ----------------------------------------------------------
|
|
365
|
+
async completeAuthorization(code, callbackState) {
|
|
366
|
+
const expectedState = await this.storage.get(KEY_PKCE_STATE);
|
|
367
|
+
if (!expectedState || expectedState !== callbackState) {
|
|
368
|
+
throw new Error("oauth_state_mismatch");
|
|
369
|
+
}
|
|
370
|
+
const verifier = await this.storage.get(KEY_PKCE_VERIFIER);
|
|
371
|
+
if (!verifier)
|
|
372
|
+
throw new Error("missing_pkce_verifier");
|
|
373
|
+
await this.storage.remove(KEY_PKCE_VERIFIER);
|
|
374
|
+
await this.storage.remove(KEY_PKCE_STATE);
|
|
375
|
+
const body = new URLSearchParams({
|
|
376
|
+
grant_type: "authorization_code",
|
|
377
|
+
code,
|
|
378
|
+
redirect_uri: this.cfg.redirectUri,
|
|
379
|
+
code_verifier: verifier,
|
|
380
|
+
client_id: this.cfg.appSlug,
|
|
381
|
+
});
|
|
382
|
+
const res = await this.fetchWithDeprecation(`${this.cfg.authority}/oauth/token`, {
|
|
383
|
+
method: "POST",
|
|
384
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
385
|
+
body: body.toString(),
|
|
386
|
+
});
|
|
387
|
+
if (!res.ok) {
|
|
388
|
+
let err = {};
|
|
389
|
+
try {
|
|
390
|
+
err = (await res.json());
|
|
391
|
+
}
|
|
392
|
+
catch {
|
|
393
|
+
/* ignore */
|
|
394
|
+
}
|
|
395
|
+
throw new OAuthError(err.error ?? `http_${res.status}`, err.error_description);
|
|
396
|
+
}
|
|
397
|
+
const data = (await res.json());
|
|
398
|
+
await this.persistToken(data);
|
|
399
|
+
return this.getState();
|
|
400
|
+
}
|
|
401
|
+
async persistToken(data) {
|
|
402
|
+
const bas = "access_token" in data ? data.access_token : data.bas;
|
|
403
|
+
const refresh = data.refresh_token ?? null;
|
|
404
|
+
await this.storage.set(KEY_BAS, bas);
|
|
405
|
+
if (refresh)
|
|
406
|
+
await this.storage.set(KEY_REFRESH, refresh);
|
|
407
|
+
await this.storage.set(KEY_BA_ID, data.bravely_account_id);
|
|
408
|
+
await this.storage.set(KEY_EMAIL, data.email);
|
|
409
|
+
if ("bravely_lib_version" in data && data.bravely_lib_version) {
|
|
410
|
+
this.libVersionPolicy = data.bravely_lib_version;
|
|
411
|
+
}
|
|
412
|
+
// Active entitlements ride along on Gate 1 BAS exchange (B6).
|
|
413
|
+
const entitlements = (data.active_entitlements ?? []);
|
|
414
|
+
await this.cache.update({ entitlements });
|
|
415
|
+
this.setState({
|
|
416
|
+
kind: "signed_in",
|
|
417
|
+
ba_id: data.bravely_account_id,
|
|
418
|
+
email: data.email,
|
|
419
|
+
bas,
|
|
420
|
+
entitlements,
|
|
421
|
+
});
|
|
422
|
+
this.activation.transition("bas_found");
|
|
423
|
+
if (entitlements.length > 0) {
|
|
424
|
+
this.activation.transition("entitlement_check_success_pro");
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
this.activation.transition("entitlement_check_success_none");
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
async refreshEntitlements() {
|
|
431
|
+
const bas = await this.storage.get(KEY_BAS);
|
|
432
|
+
if (!bas)
|
|
433
|
+
return [];
|
|
434
|
+
try {
|
|
435
|
+
const url = new URL("/api/entitlements", this.cfg.identityOrigin);
|
|
436
|
+
url.searchParams.set("app", this.cfg.appSlug);
|
|
437
|
+
const res = await this.fetchWithBas(url.toString(), bas, {
|
|
438
|
+
method: "GET",
|
|
439
|
+
});
|
|
440
|
+
if (res.status === 401) {
|
|
441
|
+
// BAS invalid; treat as signed-out.
|
|
442
|
+
await this.signOut();
|
|
443
|
+
return [];
|
|
444
|
+
}
|
|
445
|
+
if (!res.ok) {
|
|
446
|
+
const cached = this.cache.getCached();
|
|
447
|
+
this.activation.transition("entitlement_check_failure", {
|
|
448
|
+
entitlement_cache_present: !!cached,
|
|
449
|
+
});
|
|
450
|
+
return cached?.entitlements ?? [];
|
|
451
|
+
}
|
|
452
|
+
const snapshot = (await res.json());
|
|
453
|
+
const entitlements = snapshot.active_entitlements.map((lk) => ({
|
|
454
|
+
lookup_key: lk,
|
|
455
|
+
expires_at: null,
|
|
456
|
+
will_renew: false,
|
|
457
|
+
store: null,
|
|
458
|
+
}));
|
|
459
|
+
await this.cache.update({ entitlements, dpopJktThumbprint: this.dpopJktThumbprint });
|
|
460
|
+
if (this.state.kind === "signed_in") {
|
|
461
|
+
this.setState({ ...this.state, entitlements });
|
|
462
|
+
}
|
|
463
|
+
this.activation.transition(entitlements.length > 0 ? "entitlement_check_success_pro" : "entitlement_check_success_none");
|
|
464
|
+
return entitlements;
|
|
465
|
+
}
|
|
466
|
+
catch (err) {
|
|
467
|
+
// Network failure — fall back to cache.
|
|
468
|
+
const cached = this.cache.getCached();
|
|
469
|
+
this.activation.transition("entitlement_check_failure", {
|
|
470
|
+
entitlement_cache_present: !!cached,
|
|
471
|
+
});
|
|
472
|
+
if (cached)
|
|
473
|
+
return cached.entitlements;
|
|
474
|
+
throw err;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Gate 1 compatibility path: keep `Authorization: Bearer <bas>` because
|
|
479
|
+
* the current router accepts Bearer on shared BAS endpoints, but attach a
|
|
480
|
+
* real RFC 9449 proof in the `DPoP` header so Gate 2 traffic is already
|
|
481
|
+
* exercising proof generation.
|
|
482
|
+
*/
|
|
483
|
+
async fetchWithBas(input, bas, init = {}) {
|
|
484
|
+
const method = init.method ?? "GET";
|
|
485
|
+
const headers = new Headers(init.headers);
|
|
486
|
+
headers.set("Authorization", `Bearer ${bas}`);
|
|
487
|
+
const proof = await this.dpopProof(method, input, bas);
|
|
488
|
+
if (proof)
|
|
489
|
+
headers.set("DPoP", proof);
|
|
490
|
+
return this.fetchWithDeprecation(input, { ...init, method, headers });
|
|
491
|
+
}
|
|
492
|
+
async dpopProof(method, url, accessToken) {
|
|
493
|
+
const keypair = await this.getDpopKeypair();
|
|
494
|
+
if (!keypair)
|
|
495
|
+
return null;
|
|
496
|
+
try {
|
|
497
|
+
return await generateProof({
|
|
498
|
+
keypair,
|
|
499
|
+
htm: method,
|
|
500
|
+
htu: dpopHtu(url),
|
|
501
|
+
accessToken,
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
catch (error) {
|
|
505
|
+
console.info("[bravely-account-web] dpop_unavailable", { error: errorMessage(error) });
|
|
506
|
+
return null;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
async getDpopKeypair() {
|
|
510
|
+
if (!supportsDpopCrypto())
|
|
511
|
+
return null;
|
|
512
|
+
if (!this.dpopKeypairPromise) {
|
|
513
|
+
this.dpopKeypairPromise = generateKeypair()
|
|
514
|
+
.then(async (keypair) => {
|
|
515
|
+
this.dpopJktThumbprint = keypair.jktThumbprint;
|
|
516
|
+
await this.storage.set(KEY_DPOP_JKT, keypair.jktThumbprint).catch(() => undefined);
|
|
517
|
+
return keypair;
|
|
518
|
+
})
|
|
519
|
+
.catch((error) => {
|
|
520
|
+
console.info("[bravely-account-web] dpop_unavailable", { error: errorMessage(error) });
|
|
521
|
+
this.dpopKeypairPromise = null;
|
|
522
|
+
this.dpopJktThumbprint = null;
|
|
523
|
+
return null;
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
return this.dpopKeypairPromise;
|
|
527
|
+
}
|
|
528
|
+
/** Fetch wrapper that processes the `Bravely-Deprecation` header on every response. */
|
|
529
|
+
async fetchWithDeprecation(input, init = {}) {
|
|
530
|
+
const headers = new Headers(init.headers);
|
|
531
|
+
headers.set("X-Bravely-Client", this.cfg.libName);
|
|
532
|
+
headers.set("X-Bravely-Client-Version", this.cfg.libVersion);
|
|
533
|
+
headers.set("X-Bravely-App-Version", this.cfg.clientVersion);
|
|
534
|
+
const res = await fetch(input, { ...init, headers });
|
|
535
|
+
// Server kill-switch.
|
|
536
|
+
if (res.status === 426) {
|
|
537
|
+
const directives = parseDeprecation(res.headers.get("Bravely-Deprecation"));
|
|
538
|
+
const client = directives.find((d) => d.kind === "client");
|
|
539
|
+
const endpoint = directives.find((d) => d.kind === "endpoint");
|
|
540
|
+
throw new BravelyClientKilledError("bravely_client_killed", {
|
|
541
|
+
replacement: endpoint?.replacement,
|
|
542
|
+
reason: client?.reason,
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
// Soft deprecation hints.
|
|
546
|
+
const directives = parseDeprecation(res.headers.get("Bravely-Deprecation"));
|
|
547
|
+
for (const d of directives) {
|
|
548
|
+
if (d.kind === "endpoint") {
|
|
549
|
+
console.info("[bravely-account-web] bravely_deprecation_endpoint", d);
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
console.info("[bravely-account-web] bravely_deprecation_client", d);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return res;
|
|
556
|
+
}
|
|
557
|
+
async requireBas() {
|
|
558
|
+
const bas = await this.storage.get(KEY_BAS);
|
|
559
|
+
if (!bas)
|
|
560
|
+
throw new Error("not_signed_in");
|
|
561
|
+
return bas;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Replace the canonical in-memory state.
|
|
565
|
+
*
|
|
566
|
+
* Clones `next` once and stores the clone as `this.state` BEFORE notifying
|
|
567
|
+
* listeners. Listeners receive the same reference subsequent `getState()`
|
|
568
|
+
* calls will return — required for `useSyncExternalStore` consumers (see
|
|
569
|
+
* `getState()` for the React #185 background).
|
|
570
|
+
*
|
|
571
|
+
* Cloning at write time also seals off any external references the caller
|
|
572
|
+
* still holds to `next`: later mutations of `next` (or its nested
|
|
573
|
+
* `entitlements` array) cannot leak into `this.state`.
|
|
574
|
+
*/
|
|
575
|
+
setState(next) {
|
|
576
|
+
const cloned = cloneState(next);
|
|
577
|
+
this.state = cloned;
|
|
578
|
+
for (const cb of this.listeners)
|
|
579
|
+
cb(cloned);
|
|
580
|
+
return cloned;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
function stripTrailingSlash(s) {
|
|
584
|
+
return s.endsWith("/") ? s.slice(0, -1) : s;
|
|
585
|
+
}
|
|
586
|
+
function supportsDpopCrypto() {
|
|
587
|
+
return (typeof globalThis !== "undefined" &&
|
|
588
|
+
typeof globalThis.crypto !== "undefined" &&
|
|
589
|
+
typeof globalThis.crypto.subtle !== "undefined" &&
|
|
590
|
+
typeof globalThis.crypto.getRandomValues === "function");
|
|
591
|
+
}
|
|
592
|
+
function dpopHtu(input) {
|
|
593
|
+
try {
|
|
594
|
+
const url = new URL(input);
|
|
595
|
+
url.search = "";
|
|
596
|
+
url.hash = "";
|
|
597
|
+
return url.toString();
|
|
598
|
+
}
|
|
599
|
+
catch {
|
|
600
|
+
return input;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
function cloneState(s) {
|
|
604
|
+
if (s.kind === "signed_in")
|
|
605
|
+
return { ...s, entitlements: [...s.entitlements] };
|
|
606
|
+
return { ...s };
|
|
607
|
+
}
|
|
608
|
+
function errorMessage(err) {
|
|
609
|
+
if (err instanceof Error)
|
|
610
|
+
return err.message;
|
|
611
|
+
return String(err);
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Internal helper for `pollForActivation()`. Resolves after `ms` ms.
|
|
615
|
+
* Kept separate so test fakes can mock `setTimeout` via `vi.useFakeTimers`.
|
|
616
|
+
*/
|
|
617
|
+
function sleep(ms) {
|
|
618
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
619
|
+
}
|
|
620
|
+
export { BravelyClientKilledError, OAuthError };
|
|
621
|
+
//# sourceMappingURL=BravelyAccountManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BravelyAccountManager.js","sourceRoot":"","sources":["../src/BravelyAccountManager.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,EAAE;AACF,4EAA4E;AAC5E,qEAAqE;AACrE,6DAA6D;AAC7D,EAAE;AACF,0EAA0E;AAc1E,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,cAAc,EAAgB,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,aAAa,EAAoB,MAAM,WAAW,CAAC;AAC7E,OAAO,EACL,gBAAgB,EAChB,wBAAwB,EACxB,UAAU,GACX,MAAM,kBAAkB,CAAC;AAS1B,mCAAmC;AACnC,MAAM,gBAAgB,GAAG,8BAA8B,CAAC;AACxD,2BAA2B;AAC3B,MAAM,aAAa,GAAG,sCAAsC,CAAC;AAE7D,mDAAmD;AACnD,MAAM,OAAO,GAAG,KAAK,CAAC;AACtB,MAAM,WAAW,GAAG,eAAe,CAAC;AACpC,MAAM,SAAS,GAAG,OAAO,CAAC;AAC1B,MAAM,SAAS,GAAG,OAAO,CAAC;AAC1B,MAAM,YAAY,GAAG,qBAAqB,CAAC;AAC3C,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAC1C,MAAM,cAAc,GAAG,YAAY,CAAC;AAIpC,MAAM,OAAO,qBAAqB;IACf,GAAG,CACmF;IACtF,OAAO,CAAU;IACjB,KAAK,CAAmB;IACxB,UAAU,CAAyB;IAC5C,KAAK,GAAwB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IACpD,SAAS,GAAG,IAAI,GAAG,EAAiB,CAAC;IACrC,gBAAgB,GAA4B,IAAI,CAAC;IACjD,kBAAkB,GAAuC,IAAI,CAAC;IAC9D,iBAAiB,GAAkB,IAAI,CAAC;IAEhD,YAAY,MAAqB;QAC/B,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAChE,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACxE,MAAM,WAAW,GACf,MAAM,CAAC,WAAW;YAClB,CAAC,OAAO,UAAU,KAAK,WAAW,IAAK,UAAiD,CAAC,QAAQ,EAAE,MAAM;gBACvG,CAAC,CAAC,GAAI,UAA+C,CAAC,QAAQ,CAAC,MAAM,gBAAgB;gBACrF,CAAC,CAAC,uCAAuC,CAAC,CAAC;QAC/C,IAAI,CAAC,GAAG,GAAG;YACT,SAAS,EAAE,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC;YAC/C,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,cAAc,EAAE,kBAAkB,CAAC,MAAM,CAAC,cAAc,IAAI,gBAAgB,CAAC;YAC7E,WAAW;YACX,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,aAAa;YACpC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,qBAAqB;YAChD,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,OAAO;SACzC,CAAC;QACF,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,cAAc,EAAE,CAAC;QAClD,IAAI,CAAC,KAAK,GAAG,IAAI,gBAAgB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,UAAU,GAAG,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACvD,CAAC;IAED,4EAA4E;IAE5E;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,aAAa,CAAC,EAAiB;QAC7B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,kBAAkB;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;IACnC,CAAC;IAED,mBAAmB;QACjB,OAAO,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACrE,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,yBAAyB,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9E,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,kDAAkD;QAClD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACtC,MAAM,kBAAkB,GAAG,MAAM,EAAE,YAAY,IAAI,EAAE,CAAC;QACtD,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,sEAAsE;YACtE,iEAAiE;YACjE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAChG,0DAA0D;QAC1D,KAAK,IAAI,CAAC,mBAAmB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;YACzC,2DAA2D;QAC7D,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;IACzB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,CAAC,OAA+B,EAAE;QAC5C,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAErD,0EAA0E;QAC1E,MAAM,QAAQ,GAAG,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACvF,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;YACzE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM,WAAW,CAAC;YAC1D,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS;YAC7B,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO;YAC1B,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW;YACjC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK;YACrB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;QACpD,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QAC9C,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;YACpC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,8CAA8C;IACxE,CAAC;IAED,qEAAqE;IACrE,KAAK,CAAC,OAAO;QACX,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5C,IAAI,GAAG,EAAE,CAAC;gBACR,oEAAoE;gBACpE,kEAAkE;gBAClE,yCAAyC;gBACzC,MAAM,IAAI,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,eAAe,EAAE;oBACpE,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;oBAChE,IAAI,EAAE,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;iBAClF,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACnC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YACvC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACrC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACrC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACxC,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YAC9B,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;YAC/B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;YAC9B,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACtC,IAAI,MAAM,EAAE,CAAC;YACX,gCAAgC;YAChC,KAAK,IAAI,CAAC,mBAAmB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACvD,OAAO,MAAM,CAAC,YAAY,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC,mBAAmB,EAAE,CAAC;IACpC,CAAC;IAED,qEAAqE;IACrE,KAAK,CAAC,cAAc,CAAC,SAAiB;QACpC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC;IACtD,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,eAAe;QACnB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,qBAAqB,EAAE,GAAG,EAAE;YACxF,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;SACrD,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACtE,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA+B,CAAC;QAC9D,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,YAAY,CAAC,IAAkB;QACnC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,wBAAwB,EAAE,GAAG,EAAE;YAC3F,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;SAC3D,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACnE,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA6B,CAAC;QAC5D,IAAI,OAAO,UAAU,KAAK,WAAW,IAAK,UAA4C,CAAC,IAAI,EAAE,CAAC;YAC3F,UAA2C,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACjF,CAAC;QACD,mEAAmE;QACnE,6DAA6D;QAC7D,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;IACnD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,yBAAyB;QAC7B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,oBAAoB,EAAE,GAAG,EAAE;YACvF,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;SACrD,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAChF,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAC;IACnD,CAAC;IAED,gEAAgE;IAChE,uBAAuB;QACrB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;IACnD,CAAC;IAED;;;;;;;;;;OAUG;IACH,oBAAoB;QAClB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,MAAM,CAAC;QACtC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,GAAG,CAAC,CAAC;IAClD,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAK,CAAC,iBAAiB;QACrB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;QACtC,CAAC;QACD,sEAAsE;QACtE,kDAAkD;QAClD,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,IAAI,KAAK,0BAA0B,EAAE,CAAC;YAClE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,OAAO,CAAC;QAC1B,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,SAAS,GAAW,mBAAmB,CAAC,gBAAgB,CAAC;QAC7D,OAAO,QAAQ,GAAG,mBAAmB,CAAC,UAAU,EAAE,CAAC;YACjD,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,SAAS,EAAE,CAAC;gBACxC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC;gBACnD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;YAC1C,CAAC;YACD,QAAQ,IAAI,CAAC,CAAC;YACd,IAAI,YAAY,GAAkB,EAAE,CAAC;YACrC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBAClE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC9C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE;oBACvD,MAAM,EAAE,KAAK;iBACd,CAAC,CAAC;gBACH,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;oBACX,MAAM,QAAQ,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAC;oBAC3D,YAAY,GAAG,QAAQ,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;wBACvD,UAAU,EAAE,EAAE;wBACd,UAAU,EAAE,IAAI;wBAChB,UAAU,EAAE,KAAK;wBACjB,KAAK,EAAE,IAAI;qBACZ,CAAC,CAAC,CAAC;gBACN,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,4DAA4D;gBAC5D,+CAA+C;YACjD,CAAC;YACD,oEAAoE;YACpE,mEAAmE;YACnE,iEAAiE;YACjE,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;gBACrF,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBACpC,IAAI,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;gBACjD,CAAC;gBACD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,0BAA0B,CAAC,CAAC;gBACvD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;YACvD,CAAC;YACD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,4BAA4B,CAAC,CAAC;YACzD,6DAA6D;YAC7D,IAAI,QAAQ,IAAI,mBAAmB,CAAC,UAAU;gBAAE,MAAM;YACtD,+DAA+D;YAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAC;YACtE,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,OAAO,IAAI,SAAS,EAAE,CAAC;gBAClD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC;gBACnD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;YAC1C,CAAC;YACD,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;YACrB,SAAS,GAAG,IAAI,CAAC,GAAG,CAClB,SAAS,GAAG,mBAAmB,CAAC,iBAAiB,EACjD,mBAAmB,CAAC,YAAY,CACjC,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;IAC5C,CAAC;IAED,4EAA4E;IAEpE,KAAK,CAAC,qBAAqB,CAAC,IAAY,EAAE,aAAqB;QACrE,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAC7D,IAAI,CAAC,aAAa,IAAI,aAAa,KAAK,aAAa,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC1C,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC3D,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACxD,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QAC7C,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAE1C,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC;YAC/B,UAAU,EAAE,oBAAoB;YAChC,IAAI;YACJ,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW;YAClC,aAAa,EAAE,QAAQ;YACvB,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO;SAC5B,CAAC,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,cAAc,EAAE;YAC/E,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;YAChE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE;SACtB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,GAAG,GAAmD,EAAE,CAAC;YAC7D,IAAI,CAAC;gBACH,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAe,CAAC;YACzC,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;YACD,MAAM,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,IAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC;QACjF,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuB,CAAC;QACtD,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;IACzB,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,IAAsC;QAC/D,MAAM,GAAG,GAAG,cAAc,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAClE,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC;QAC3C,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACrC,IAAI,OAAO;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC3D,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,IAAI,qBAAqB,IAAI,IAAI,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC9D,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,CAAC;QACnD,CAAC;QACD,8DAA8D;QAC9D,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,mBAAmB,IAAI,EAAE,CAAkB,CAAC;QACvE,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,QAAQ,CAAC;YACZ,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,IAAI,CAAC,kBAAkB;YAC9B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,GAAG;YACH,YAAY;SACb,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QACxC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,+BAA+B,CAAC,CAAC;QAC9D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,gCAAgC,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,mBAAmB;QAC/B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAClE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE;gBACvD,MAAM,EAAE,KAAK;aACd,CAAC,CAAC;YACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvB,oCAAoC;gBACpC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;gBACrB,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;gBACtC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,2BAA2B,EAAE;oBACtD,yBAAyB,EAAE,CAAC,CAAC,MAAM;iBACpC,CAAC,CAAC;gBACH,OAAO,MAAM,EAAE,YAAY,IAAI,EAAE,CAAC;YACpC,CAAC;YACD,MAAM,QAAQ,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAC;YAC3D,MAAM,YAAY,GAAkB,QAAQ,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC5E,UAAU,EAAE,EAAE;gBACd,UAAU,EAAE,IAAI;gBAChB,UAAU,EAAE,KAAK;gBACjB,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC,CAAC;YACJ,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;YACrF,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACpC,IAAI,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;YACjD,CAAC;YACD,IAAI,CAAC,UAAU,CAAC,UAAU,CACxB,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,gCAAgC,CAC7F,CAAC;YACF,OAAO,YAAY,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,wCAAwC;YACxC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,2BAA2B,EAAE;gBACtD,yBAAyB,EAAE,CAAC,CAAC,MAAM;aACpC,CAAC,CAAC;YACH,IAAI,MAAM;gBAAE,OAAO,MAAM,CAAC,YAAY,CAAC;YACvC,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,YAAY,CAAC,KAAa,EAAE,GAAW,EAAE,OAAoB,EAAE;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,GAAG,EAAE,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACvD,IAAI,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IACxE,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,MAAc,EAAE,GAAW,EAAE,WAAmB;QACtE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC5C,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,IAAI,CAAC;YACH,OAAO,MAAM,aAAa,CAAC;gBACzB,OAAO;gBACP,GAAG,EAAE,MAAM;gBACX,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC;gBACjB,WAAW;aACZ,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,wCAAwC,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACvF,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc;QAC1B,IAAI,CAAC,kBAAkB,EAAE;YAAE,OAAO,IAAI,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC7B,IAAI,CAAC,kBAAkB,GAAG,eAAe,EAAE;iBACxC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;gBACtB,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,aAAa,CAAC;gBAC/C,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBACnF,OAAO,OAAO,CAAC;YACjB,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;gBACf,OAAO,CAAC,IAAI,CAAC,wCAAwC,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBACvF,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;gBAC/B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;gBAC9B,OAAO,IAAI,CAAC;YACd,CAAC,CAAC,CAAC;QACP,CAAC;QACD,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACjC,CAAC;IAED,uFAAuF;IAC/E,KAAK,CAAC,oBAAoB,CAAC,KAAa,EAAE,OAAoB,EAAE;QACtE,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC7D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAErD,sBAAsB;QACtB,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC;YAC5E,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAE5C,CAAC;YACd,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAEhD,CAAC;YACd,MAAM,IAAI,wBAAwB,CAAC,uBAAuB,EAAE;gBAC1D,WAAW,EAAE,QAAQ,EAAE,WAAW;gBAClC,MAAM,EAAE,MAAM,EAAE,MAAM;aACvB,CAAC,CAAC;QACL,CAAC;QAED,0BAA0B;QAC1B,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAC5E,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC1B,OAAO,CAAC,IAAI,CAAC,oDAAoD,EAAE,CAAC,CAAC,CAAC;YACxE,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,kDAAkD,EAAE,CAAC,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QAC3C,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;;;;;;;;OAWG;IACK,QAAQ,CAAC,IAAyB;QACxC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC;QACpB,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,SAAS;YAAE,EAAE,CAAC,MAAM,CAAC,CAAC;QAC5C,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAED,SAAS,kBAAkB,CAAC,CAAS;IACnC,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO,CACL,OAAO,UAAU,KAAK,WAAW;QACjC,OAAO,UAAU,CAAC,MAAM,KAAK,WAAW;QACxC,OAAO,UAAU,CAAC,MAAM,CAAC,MAAM,KAAK,WAAW;QAC/C,OAAO,UAAU,CAAC,MAAM,CAAC,eAAe,KAAK,UAAU,CACxD,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,KAAa;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;QAChB,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;QACd,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,CAAsB;IACxC,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,EAAE,GAAG,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;IAC/E,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC;AAClB,CAAC;AAED,SAAS,YAAY,CAAC,GAAY;IAChC,IAAI,GAAG,YAAY,KAAK;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC7C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,OAAO,EAAE,wBAAwB,EAAE,UAAU,EAAE,CAAC"}
|