oidc-spa 8.2.3 → 8.2.5
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/core/Oidc.d.ts +1 -0
- package/core/createOidc.js +6 -26
- package/core/createOidc.js.map +1 -1
- package/core/homeAndRedirectUri.d.ts +5 -0
- package/core/homeAndRedirectUri.js +32 -0
- package/core/homeAndRedirectUri.js.map +1 -0
- package/esm/angular.d.ts +1 -0
- package/esm/angular.js +3 -0
- package/esm/angular.js.map +1 -1
- package/esm/core/Oidc.d.ts +1 -0
- package/esm/core/createOidc.js +6 -26
- package/esm/core/createOidc.js.map +1 -1
- package/esm/core/homeAndRedirectUri.d.ts +5 -0
- package/esm/core/homeAndRedirectUri.js +29 -0
- package/esm/core/homeAndRedirectUri.js.map +1 -0
- package/esm/keycloak/keycloak-js/Keycloak.js +11 -2
- package/esm/keycloak/keycloak-js/Keycloak.js.map +1 -1
- package/esm/keycloak/keycloakUtils.d.ts +3 -1
- package/esm/keycloak/keycloakUtils.js +26 -5
- package/esm/keycloak/keycloakUtils.js.map +1 -1
- package/esm/mock/oidc.js +2 -1
- package/esm/mock/oidc.js.map +1 -1
- package/esm/react-spa/apiBuilder.d.ts +2 -2
- package/esm/react-spa/apiBuilder.js +1 -1
- package/esm/react-spa/apiBuilder.js.map +1 -1
- package/esm/react-spa/createOidcSpaApi.js +3 -1
- package/esm/react-spa/createOidcSpaApi.js.map +1 -1
- package/esm/react-spa/types.d.ts +1 -0
- package/esm/tanstack-start/react/apiBuilder.d.ts +2 -2
- package/esm/tanstack-start/react/apiBuilder.js +1 -1
- package/esm/tanstack-start/react/apiBuilder.js.map +1 -1
- package/esm/tanstack-start/react/createOidcSpaApi.js +3 -1
- package/esm/tanstack-start/react/createOidcSpaApi.js.map +1 -1
- package/esm/tanstack-start/react/types.d.ts +1 -0
- package/esm/tools/parseKeycloakIssuerUri.js +5 -1
- package/esm/tools/parseKeycloakIssuerUri.js.map +1 -1
- package/keycloak/keycloak-js/Keycloak.js +11 -2
- package/keycloak/keycloak-js/Keycloak.js.map +1 -1
- package/keycloak/keycloakUtils.d.ts +3 -1
- package/keycloak/keycloakUtils.js +26 -5
- package/keycloak/keycloakUtils.js.map +1 -1
- package/mock/oidc.js +2 -1
- package/mock/oidc.js.map +1 -1
- package/package.json +1 -1
- package/react-spa/apiBuilder.d.ts +2 -2
- package/react-spa/apiBuilder.js +1 -1
- package/react-spa/apiBuilder.js.map +1 -1
- package/react-spa/createOidcSpaApi.js +3 -1
- package/react-spa/createOidcSpaApi.js.map +1 -1
- package/react-spa/types.d.ts +1 -0
- package/src/angular.ts +4 -0
- package/src/core/Oidc.ts +1 -0
- package/src/core/createOidc.ts +5 -30
- package/src/core/homeAndRedirectUri.ts +36 -0
- package/src/keycloak/keycloak-js/Keycloak.ts +13 -2
- package/src/keycloak/keycloakUtils.ts +38 -6
- package/src/mock/oidc.ts +2 -1
- package/src/react-spa/apiBuilder.ts +3 -3
- package/src/react-spa/createOidcSpaApi.tsx +3 -1
- package/src/react-spa/types.tsx +1 -0
- package/src/tanstack-start/react/apiBuilder.ts +3 -3
- package/src/tanstack-start/react/createOidcSpaApi.tsx +3 -1
- package/src/tanstack-start/react/types.tsx +1 -0
- package/src/tools/parseKeycloakIssuerUri.ts +6 -1
- package/tools/parseKeycloakIssuerUri.js +5 -1
- package/tools/parseKeycloakIssuerUri.js.map +1 -1
package/src/core/createOidc.ts
CHANGED
|
@@ -45,7 +45,6 @@ import { getIsOnline } from "../tools/getIsOnline";
|
|
|
45
45
|
import { isKeycloak } from "../keycloak/isKeycloak";
|
|
46
46
|
import { INFINITY_TIME } from "../tools/INFINITY_TIME";
|
|
47
47
|
import { prShouldLoadApp } from "./prShouldLoadApp";
|
|
48
|
-
import { getBASE_URL } from "./BASE_URL";
|
|
49
48
|
import { getIsLikelyDevServer } from "../tools/isLikelyDevServer";
|
|
50
49
|
import { createObjectThatThrowsIfAccessed } from "../tools/createObjectThatThrowsIfAccessed";
|
|
51
50
|
import {
|
|
@@ -53,6 +52,7 @@ import {
|
|
|
53
52
|
notifyNewInstanceThatCantUseIframes
|
|
54
53
|
} from "./instancesThatCantUseIframes";
|
|
55
54
|
import { getDesiredPostLoginRedirectUrl } from "./desiredPostLoginRedirectUrl";
|
|
55
|
+
import { getHomeAndRedirectUri } from "./homeAndRedirectUri";
|
|
56
56
|
|
|
57
57
|
// NOTE: Replaced at build time
|
|
58
58
|
const VERSION = "{{OIDC_SPA_VERSION}}";
|
|
@@ -405,33 +405,7 @@ export async function createOidc_nonMemoized<
|
|
|
405
405
|
return extraTokenParamsOrGetter;
|
|
406
406
|
})();
|
|
407
407
|
|
|
408
|
-
const homeUrlAndRedirectUri =
|
|
409
|
-
urlish: (() => {
|
|
410
|
-
if (BASE_URL_params !== undefined) {
|
|
411
|
-
return BASE_URL_params;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
const BASE_URL = getBASE_URL();
|
|
415
|
-
|
|
416
|
-
if (BASE_URL === undefined) {
|
|
417
|
-
throw new Error(
|
|
418
|
-
[
|
|
419
|
-
"oidc-spa: If you do not use the oidc-spa Vite plugin",
|
|
420
|
-
"you must provide the BASE_URL to the earlyInit() examples:",
|
|
421
|
-
"oidcSpaEarlyInit({ BASE_URL: import.meta.env.BASE_URL })",
|
|
422
|
-
"oidcSpaEarlyInit({ BASE_URL: '/' })",
|
|
423
|
-
"",
|
|
424
|
-
"You can also pass this parameter to createOidc({ BASE_URL: '...' })",
|
|
425
|
-
"or bootstrapOidc({ BASE_URL: '...' })"
|
|
426
|
-
].join("\n")
|
|
427
|
-
);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
return BASE_URL;
|
|
431
|
-
})(),
|
|
432
|
-
doAssertNoQueryParams: true,
|
|
433
|
-
doOutputWithTrailingSlash: true
|
|
434
|
-
});
|
|
408
|
+
const { homeUrlAndRedirectUri } = getHomeAndRedirectUri({ BASE_URL_params });
|
|
435
409
|
|
|
436
410
|
log?.(
|
|
437
411
|
`Calling createOidc v${VERSION} ${JSON.stringify(
|
|
@@ -439,7 +413,7 @@ export async function createOidc_nonMemoized<
|
|
|
439
413
|
issuerUri,
|
|
440
414
|
clientId,
|
|
441
415
|
scopes,
|
|
442
|
-
|
|
416
|
+
validRedirectUri: homeUrlAndRedirectUri
|
|
443
417
|
},
|
|
444
418
|
null,
|
|
445
419
|
2
|
|
@@ -1066,7 +1040,8 @@ export async function createOidc_nonMemoized<
|
|
|
1066
1040
|
const oidc_common: Oidc.Common = {
|
|
1067
1041
|
params: {
|
|
1068
1042
|
issuerUri,
|
|
1069
|
-
clientId
|
|
1043
|
+
clientId,
|
|
1044
|
+
validRedirectUri: homeUrlAndRedirectUri
|
|
1070
1045
|
}
|
|
1071
1046
|
};
|
|
1072
1047
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { toFullyQualifiedUrl } from "../tools/toFullyQualifiedUrl";
|
|
2
|
+
import { getBASE_URL } from "./BASE_URL";
|
|
3
|
+
|
|
4
|
+
export function getHomeAndRedirectUri(params: { BASE_URL_params: string | undefined }) {
|
|
5
|
+
const { BASE_URL_params } = params;
|
|
6
|
+
|
|
7
|
+
const homeUrlAndRedirectUri = toFullyQualifiedUrl({
|
|
8
|
+
urlish: (() => {
|
|
9
|
+
if (BASE_URL_params !== undefined) {
|
|
10
|
+
return BASE_URL_params;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const BASE_URL = getBASE_URL();
|
|
14
|
+
|
|
15
|
+
if (BASE_URL === undefined) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
[
|
|
18
|
+
"oidc-spa: If you do not use the oidc-spa Vite plugin",
|
|
19
|
+
"you must provide the BASE_URL to the earlyInit() examples:",
|
|
20
|
+
"oidcSpaEarlyInit({ BASE_URL: import.meta.env.BASE_URL })",
|
|
21
|
+
"oidcSpaEarlyInit({ BASE_URL: '/' })",
|
|
22
|
+
"",
|
|
23
|
+
"You can also pass this parameter to createOidc({ BASE_URL: '...' })",
|
|
24
|
+
"or bootstrapOidc({ BASE_URL: '...' })"
|
|
25
|
+
].join("\n")
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return BASE_URL;
|
|
30
|
+
})(),
|
|
31
|
+
doAssertNoQueryParams: true,
|
|
32
|
+
doOutputWithTrailingSlash: true
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return { homeUrlAndRedirectUri };
|
|
36
|
+
}
|
|
@@ -21,6 +21,7 @@ import { type KeycloakUtils, createKeycloakUtils } from "../keycloakUtils";
|
|
|
21
21
|
import { workerTimers } from "../../vendor/frontend/worker-timers";
|
|
22
22
|
import { type StatefulEvt, createStatefulEvt } from "../../tools/StatefulEvt";
|
|
23
23
|
import { readExpirationTimeInJwt } from "../../tools/readExpirationTimeInJwt";
|
|
24
|
+
import { getHomeAndRedirectUri } from "../../core/homeAndRedirectUri";
|
|
24
25
|
|
|
25
26
|
type ConstructorParams = KeycloakServerConfig & {
|
|
26
27
|
/**
|
|
@@ -934,11 +935,21 @@ export class Keycloak {
|
|
|
934
935
|
createAccountUrl(options?: KeycloakAccountOptions & { locale?: string }): string {
|
|
935
936
|
const { locale, redirectUri } = options ?? {};
|
|
936
937
|
|
|
937
|
-
const { keycloakUtils } = this.#state;
|
|
938
|
+
const { keycloakUtils, constructorParams } = this.#state;
|
|
938
939
|
|
|
939
940
|
return keycloakUtils.getAccountUrl({
|
|
940
941
|
clientId: this.clientId,
|
|
941
|
-
|
|
942
|
+
validRedirectUri: (() => {
|
|
943
|
+
if (redirectUri !== undefined) {
|
|
944
|
+
return redirectUri;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
const { homeUrlAndRedirectUri } = getHomeAndRedirectUri({
|
|
948
|
+
BASE_URL_params: constructorParams.BASE_URL
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
return homeUrlAndRedirectUri;
|
|
952
|
+
})(),
|
|
942
953
|
locale
|
|
943
954
|
});
|
|
944
955
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { toFullyQualifiedUrl } from "../tools/toFullyQualifiedUrl";
|
|
2
2
|
import { type KeycloakIssuerUriParsed, parseKeycloakIssuerUri } from "./keycloakIssuerUriParsed";
|
|
3
|
+
import { assert } from "../tools/tsafe/assert";
|
|
3
4
|
|
|
4
5
|
export type KeycloakUtils = {
|
|
5
6
|
issuerUriParsed: KeycloakIssuerUriParsed;
|
|
@@ -7,7 +8,9 @@ export type KeycloakUtils = {
|
|
|
7
8
|
adminConsoleUrl_master: string;
|
|
8
9
|
getAccountUrl: (params: {
|
|
9
10
|
clientId: string;
|
|
10
|
-
|
|
11
|
+
validRedirectUri?: string;
|
|
12
|
+
/** @deprecated: Use validRedirectUri */
|
|
13
|
+
backToAppFromAccountUrl?: string;
|
|
11
14
|
locale?: string;
|
|
12
15
|
}) => string;
|
|
13
16
|
fetchUserProfile: (params: { accessToken: string }) => Promise<KeycloakProfile>;
|
|
@@ -49,17 +52,46 @@ export function createKeycloakUtils(params: { issuerUri: string }): KeycloakUtil
|
|
|
49
52
|
issuerUriParsed,
|
|
50
53
|
adminConsoleUrl: getAdminConsoleUrl(issuerUriParsed.realm),
|
|
51
54
|
adminConsoleUrl_master: getAdminConsoleUrl("master"),
|
|
52
|
-
getAccountUrl: ({ clientId,
|
|
55
|
+
getAccountUrl: ({ clientId, locale, ...rest }) => {
|
|
56
|
+
const validRedirectUri = (() => {
|
|
57
|
+
const { validRedirectUri, backToAppFromAccountUrl } = rest;
|
|
58
|
+
|
|
59
|
+
if (validRedirectUri !== undefined) {
|
|
60
|
+
assert(
|
|
61
|
+
backToAppFromAccountUrl === undefined,
|
|
62
|
+
"getAccountUrl: backToAppFromAccountUrl is deprecated"
|
|
63
|
+
);
|
|
64
|
+
return validRedirectUri;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
assert(
|
|
68
|
+
backToAppFromAccountUrl !== undefined,
|
|
69
|
+
"getAccountUrl: Must provide validRedirectUri"
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return backToAppFromAccountUrl;
|
|
73
|
+
})();
|
|
74
|
+
|
|
53
75
|
const accountUrlObj = new URL(
|
|
54
76
|
`${keycloakServerUrl}/realms/${issuerUriParsed.realm}/account`
|
|
55
77
|
);
|
|
56
78
|
accountUrlObj.searchParams.set("referrer", clientId);
|
|
57
79
|
accountUrlObj.searchParams.set(
|
|
58
80
|
"referrer_uri",
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
81
|
+
(() => {
|
|
82
|
+
try {
|
|
83
|
+
return toFullyQualifiedUrl({
|
|
84
|
+
urlish: validRedirectUri,
|
|
85
|
+
doAssertNoQueryParams: true,
|
|
86
|
+
doOutputWithTrailingSlash: true
|
|
87
|
+
});
|
|
88
|
+
} catch {
|
|
89
|
+
return toFullyQualifiedUrl({
|
|
90
|
+
urlish: validRedirectUri,
|
|
91
|
+
doAssertNoQueryParams: false
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
})()
|
|
63
95
|
);
|
|
64
96
|
if (locale !== undefined) {
|
|
65
97
|
accountUrlObj.searchParams.set("kc_locale", locale);
|
package/src/mock/oidc.ts
CHANGED
|
@@ -96,7 +96,8 @@ export async function createMockOidc<
|
|
|
96
96
|
const common: Oidc.Common = {
|
|
97
97
|
params: {
|
|
98
98
|
clientId: mockedParams.clientId ?? "mymockclient",
|
|
99
|
-
issuerUri: mockedParams.issuerUri ?? "https://my-mock-oidc-server.net/realms/mymockrealm"
|
|
99
|
+
issuerUri: mockedParams.issuerUri ?? "https://my-mock-oidc-server.net/realms/mymockrealm",
|
|
100
|
+
validRedirectUri: homeUrl
|
|
100
101
|
}
|
|
101
102
|
};
|
|
102
103
|
|
|
@@ -10,7 +10,7 @@ export type OidcSpaApiBuilder<
|
|
|
10
10
|
| "withAutoLogin"
|
|
11
11
|
| "withExpectedDecodedIdTokenShape"
|
|
12
12
|
| "withAccessTokenValidation"
|
|
13
|
-
| "
|
|
13
|
+
| "createUtils" = never
|
|
14
14
|
> = Omit<
|
|
15
15
|
{
|
|
16
16
|
withAutoLogin: () => OidcSpaApiBuilder<true, DecodedIdToken, ExcludedMethod | "withAutoLogin">;
|
|
@@ -26,7 +26,7 @@ export type OidcSpaApiBuilder<
|
|
|
26
26
|
ExcludedMethod | "withExpectedDecodedIdTokenShape"
|
|
27
27
|
>;
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
createUtils: () => OidcSpaApi<AutoLogin, DecodedIdToken>;
|
|
30
30
|
},
|
|
31
31
|
ExcludedMethod
|
|
32
32
|
>;
|
|
@@ -54,7 +54,7 @@ function createOidcSpaApiBuilder<
|
|
|
54
54
|
decodedIdTokenSchema,
|
|
55
55
|
decodedIdToken_mock: decodedIdToken_mock
|
|
56
56
|
}),
|
|
57
|
-
|
|
57
|
+
createUtils: () =>
|
|
58
58
|
createOidcSpaApi<AutoLogin, DecodedIdToken>({
|
|
59
59
|
autoLogin: params.autoLogin,
|
|
60
60
|
decodedIdTokenSchema: params.decodedIdTokenSchema,
|
|
@@ -226,6 +226,7 @@ export function createOidcSpaApi<
|
|
|
226
226
|
initializationError: oidcCore.initializationError,
|
|
227
227
|
issuerUri: oidcCore.params.issuerUri,
|
|
228
228
|
clientId: oidcCore.params.clientId,
|
|
229
|
+
validRedirectUri: oidcCore.params.validRedirectUri,
|
|
229
230
|
autoLogoutState: { shouldDisplayWarning: false },
|
|
230
231
|
login: params =>
|
|
231
232
|
oidcCore.login({
|
|
@@ -251,7 +252,8 @@ export function createOidcSpaApi<
|
|
|
251
252
|
return evtAutoLogoutState.current;
|
|
252
253
|
},
|
|
253
254
|
issuerUri: oidcCore.params.issuerUri,
|
|
254
|
-
clientId: oidcCore.params.clientId
|
|
255
|
+
clientId: oidcCore.params.clientId,
|
|
256
|
+
validRedirectUri: oidcCore.params.validRedirectUri
|
|
255
257
|
});
|
|
256
258
|
}
|
|
257
259
|
|
package/src/react-spa/types.tsx
CHANGED
|
@@ -14,7 +14,7 @@ export type OidcSpaApiBuilder<
|
|
|
14
14
|
| "withAutoLogin"
|
|
15
15
|
| "withExpectedDecodedIdTokenShape"
|
|
16
16
|
| "withAccessTokenValidation"
|
|
17
|
-
| "
|
|
17
|
+
| "createUtils" = never
|
|
18
18
|
> = Omit<
|
|
19
19
|
{
|
|
20
20
|
withAutoLogin: () => OidcSpaApiBuilder<
|
|
@@ -61,7 +61,7 @@ export type OidcSpaApiBuilder<
|
|
|
61
61
|
ExcludedMethod | "withAccessTokenValidation"
|
|
62
62
|
>;
|
|
63
63
|
};
|
|
64
|
-
|
|
64
|
+
createUtils: () => OidcSpaApi<AutoLogin, DecodedIdToken, AccessTokenClaims>;
|
|
65
65
|
},
|
|
66
66
|
ExcludedMethod
|
|
67
67
|
>;
|
|
@@ -127,7 +127,7 @@ function createOidcSpaApiBuilder<
|
|
|
127
127
|
}
|
|
128
128
|
})()
|
|
129
129
|
}),
|
|
130
|
-
|
|
130
|
+
createUtils: () =>
|
|
131
131
|
createOidcSpaApi<AutoLogin, DecodedIdToken, AccessTokenClaims>({
|
|
132
132
|
autoLogin: params.autoLogin,
|
|
133
133
|
decodedIdTokenSchema: params.decodedIdTokenSchema,
|
|
@@ -216,6 +216,7 @@ export function createOidcSpaApi<
|
|
|
216
216
|
initializationError: oidcCore.initializationError,
|
|
217
217
|
issuerUri: oidcCore.params.issuerUri,
|
|
218
218
|
clientId: oidcCore.params.clientId,
|
|
219
|
+
validRedirectUri: oidcCore.params.validRedirectUri,
|
|
219
220
|
autoLogoutState: { shouldDisplayWarning: false },
|
|
220
221
|
login: params =>
|
|
221
222
|
oidcCore.login({
|
|
@@ -241,7 +242,8 @@ export function createOidcSpaApi<
|
|
|
241
242
|
return evtAutoLogoutState.current;
|
|
242
243
|
},
|
|
243
244
|
issuerUri: oidcCore.params.issuerUri,
|
|
244
|
-
clientId: oidcCore.params.clientId
|
|
245
|
+
clientId: oidcCore.params.clientId,
|
|
246
|
+
validRedirectUri: oidcCore.params.validRedirectUri
|
|
245
247
|
});
|
|
246
248
|
}
|
|
247
249
|
|
|
@@ -44,6 +44,11 @@ export function parseKeycloakIssuerUri(issuerUri: string):
|
|
|
44
44
|
kcHttpRelativePath: keycloakUtils.issuerUriParsed.kcHttpRelativePath,
|
|
45
45
|
adminConsoleUrl: keycloakUtils.adminConsoleUrl,
|
|
46
46
|
adminConsoleUrl_master: keycloakUtils.adminConsoleUrl_master,
|
|
47
|
-
getAccountUrl:
|
|
47
|
+
getAccountUrl: ({ clientId, backToAppFromAccountUrl, locale }) =>
|
|
48
|
+
keycloakUtils.getAccountUrl({
|
|
49
|
+
clientId,
|
|
50
|
+
validRedirectUri: backToAppFromAccountUrl,
|
|
51
|
+
locale
|
|
52
|
+
})
|
|
48
53
|
};
|
|
49
54
|
}
|
|
@@ -30,7 +30,11 @@ function parseKeycloakIssuerUri(issuerUri) {
|
|
|
30
30
|
kcHttpRelativePath: keycloakUtils.issuerUriParsed.kcHttpRelativePath,
|
|
31
31
|
adminConsoleUrl: keycloakUtils.adminConsoleUrl,
|
|
32
32
|
adminConsoleUrl_master: keycloakUtils.adminConsoleUrl_master,
|
|
33
|
-
getAccountUrl: keycloakUtils.getAccountUrl
|
|
33
|
+
getAccountUrl: ({ clientId, backToAppFromAccountUrl, locale }) => keycloakUtils.getAccountUrl({
|
|
34
|
+
clientId,
|
|
35
|
+
validRedirectUri: backToAppFromAccountUrl,
|
|
36
|
+
locale
|
|
37
|
+
})
|
|
34
38
|
};
|
|
35
39
|
}
|
|
36
40
|
//# sourceMappingURL=parseKeycloakIssuerUri.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseKeycloakIssuerUri.js","sourceRoot":"","sources":["../src/tools/parseKeycloakIssuerUri.ts"],"names":[],"mappings":";;AAmBA,
|
|
1
|
+
{"version":3,"file":"parseKeycloakIssuerUri.js","sourceRoot":"","sources":["../src/tools/parseKeycloakIssuerUri.ts"],"names":[],"mappings":";;AAmBA,wDAkCC;AArDD,0CAA8D;AAE9D;;;;;;;;;;;;;;;;KAgBK;AACL,SAAgB,sBAAsB,CAAC,SAAiB;IAepD,IAAI,CAAC,IAAA,qBAAU,EAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;QAC7B,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,MAAM,aAAa,GAAG,IAAA,8BAAmB,EAAC,EAAE,SAAS,EAAE,CAAC,CAAC;IAEzD,OAAO;QACH,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,MAAM;QAC5C,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,KAAK;QAC1C,kBAAkB,EAAE,aAAa,CAAC,eAAe,CAAC,kBAAkB;QACpE,eAAe,EAAE,aAAa,CAAC,eAAe;QAC9C,sBAAsB,EAAE,aAAa,CAAC,sBAAsB;QAC5D,aAAa,EAAE,CAAC,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,EAAE,EAAE,EAAE,CAC7D,aAAa,CAAC,aAAa,CAAC;YACxB,QAAQ;YACR,gBAAgB,EAAE,uBAAuB;YACzC,MAAM;SACT,CAAC;KACT,CAAC;AACN,CAAC"}
|