@tsed/oidc-provider-plugin-wildcard-redirect-uri 7.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintignore ADDED
@@ -0,0 +1,13 @@
1
+ node_modules
2
+ docs
3
+ docs-references
4
+ lib
5
+ dist
6
+ coverage
7
+ .nyc_output
8
+ *-lock.json
9
+ *.lock
10
+ benchmarks.*
11
+ **/generated
12
+
13
+ **/*.js
package/.eslintrc.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require("@tsed/eslint/node.js");
package/jest.config.js ADDED
@@ -0,0 +1,19 @@
1
+ // For a detailed explanation regarding each configuration property, visit:
2
+ // https://jestjs.io/docs/en/configuration.html
3
+
4
+ module.exports = {
5
+ ...require("@tsed/jest-config"),
6
+ coverageProvider: "babel",
7
+ roots: ["<rootDir>/src"],
8
+ moduleNameMapper: {},
9
+ transformIgnorePatterns: ["^.+\\.module\\.(css|sass|scss)$"],
10
+
11
+ coverageThreshold: {
12
+ global: {
13
+ statements: 100,
14
+ branches: 87.5,
15
+ functions: 100,
16
+ lines: 100
17
+ }
18
+ }
19
+ };
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OidcWildcardRedirectUriModule = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const di_1 = require("@tsed/di");
6
+ const logger_1 = require("@tsed/logger");
7
+ const oidc_provider_1 = require("@tsed/oidc-provider");
8
+ // @ts-ignore
9
+ const psl_1 = tslib_1.__importDefault(require("psl"));
10
+ const wildcardRedirectUriAllowed_1 = require("./utils/wildcardRedirectUriAllowed");
11
+ let OidcWildcardRedirectUriModule = class OidcWildcardRedirectUriModule {
12
+ module;
13
+ enabled;
14
+ logger;
15
+ constructor(module) {
16
+ this.module = module;
17
+ }
18
+ async $onCreateOIDC(provider) {
19
+ if (this.enabled) {
20
+ const { redirectUriAllowed } = provider.Client.prototype;
21
+ provider.Client.prototype.redirectUriAllowed = (0, wildcardRedirectUriAllowed_1.wildcardRedirectUriAllowed)(redirectUriAllowed);
22
+ this.logger.warn("⚠️⚠️⚠️ OIDC Wildcard Uris plugin is ENABLED ⚠️⚠️⚠️");
23
+ }
24
+ }
25
+ async $alterOidcConfiguration(config) {
26
+ if (this.enabled) {
27
+ const actualProperties = config?.extraClientMetadata?.properties || [];
28
+ config.extraClientMetadata = {
29
+ properties: [...actualProperties, "redirect_uris"],
30
+ validator: this.validator.bind(this)
31
+ };
32
+ }
33
+ return config;
34
+ }
35
+ validator(ctx, key, value) {
36
+ if (key === "redirect_uris") {
37
+ for (const redirectUri of value) {
38
+ if (redirectUri.includes("*")) {
39
+ const { hostname, href } = new URL(redirectUri);
40
+ if (href.split("*").length !== 2) {
41
+ throw new this.module.errors.InvalidClientMetadata("redirect_uris with a wildcard may only contain a single one");
42
+ }
43
+ if (!hostname.includes("*")) {
44
+ throw new this.module.errors.InvalidClientMetadata("redirect_uris may only have a wildcard in the hostname");
45
+ }
46
+ if (!psl_1.default.get(hostname.split("*.")[1])) {
47
+ throw new this.module.errors.InvalidClientMetadata("redirect_uris with a wildcard must not match an eTLD+1 of a known public suffix domain");
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ };
54
+ tslib_1.__decorate([
55
+ (0, di_1.Constant)("oidc.plugins.wildcard.enabled", false),
56
+ tslib_1.__metadata("design:type", Boolean)
57
+ ], OidcWildcardRedirectUriModule.prototype, "enabled", void 0);
58
+ tslib_1.__decorate([
59
+ (0, di_1.Inject)(logger_1.Logger),
60
+ tslib_1.__metadata("design:type", logger_1.Logger)
61
+ ], OidcWildcardRedirectUriModule.prototype, "logger", void 0);
62
+ OidcWildcardRedirectUriModule = tslib_1.__decorate([
63
+ (0, di_1.Module)(),
64
+ tslib_1.__param(0, (0, di_1.Inject)(oidc_provider_1.OIDC_PROVIDER_NODE_MODULE)),
65
+ tslib_1.__metadata("design:paramtypes", [Object])
66
+ ], OidcWildcardRedirectUriModule);
67
+ exports.OidcWildcardRedirectUriModule = OidcWildcardRedirectUriModule;
68
+ //# sourceMappingURL=OidcWildcardRedirectUriModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OidcWildcardRedirectUriModule.js","sourceRoot":"","sources":["../../src/OidcWildcardRedirectUriModule.ts"],"names":[],"mappings":";;;;AAAA,iCAAkD;AAClD,yCAAoC;AACpC,uDAA4E;AAG5E,aAAa;AACb,sDAAsB;AACtB,mFAA8E;AAavE,IAAM,6BAA6B,GAAnC,MAAM,6BAA6B;IAOiB;IALhD,OAAO,CAAU;IAGhB,MAAM,CAAS;IAEzB,YAAyD,MAAiC;QAAjC,WAAM,GAAN,MAAM,CAA2B;IAAG,CAAC;IAE9F,KAAK,CAAC,aAAa,CAAC,QAAkB;QACpC,IAAI,IAAI,CAAC,OAAO,EAAE;YAChB,MAAM,EAAC,kBAAkB,EAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;YACvD,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,kBAAkB,GAAG,IAAA,uDAA0B,EAAC,kBAAkB,CAAC,CAAC;YAE9F,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;SACxE;IACH,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,MAAoB;QAChD,IAAI,IAAI,CAAC,OAAO,EAAE;YAChB,MAAM,gBAAgB,GAAG,MAAM,EAAE,mBAAmB,EAAE,UAAU,IAAI,EAAE,CAAC;YAEvE,MAAM,CAAC,mBAAmB,GAAG;gBAC3B,UAAU,EAAE,CAAC,GAAG,gBAAgB,EAAE,eAAe,CAAC;gBAClD,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;aACrC,CAAC;SACH;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,SAAS,CAAC,GAAuB,EAAE,GAAW,EAAE,KAAU;QACxD,IAAI,GAAG,KAAK,eAAe,EAAE;YAC3B,KAAK,MAAM,WAAW,IAAI,KAAK,EAAE;gBAC/B,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;oBAC7B,MAAM,EAAC,QAAQ,EAAE,IAAI,EAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;oBAE9C,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;wBAChC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC,6DAA6D,CAAC,CAAC;qBACnH;oBAED,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;wBAC3B,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC,wDAAwD,CAAC,CAAC;qBAC9G;oBAED,IAAI,CAAC,aAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;wBACrC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAChD,wFAAwF,CACzF,CAAC;qBACH;iBACF;aACF;SACF;IACH,CAAC;CACF,CAAA;AArDC;IAAC,IAAA,aAAQ,EAAC,+BAA+B,EAAE,KAAK,CAAC;;8DACvB;AAE1B;IAAC,IAAA,WAAM,EAAC,eAAM,CAAC;sCACG,eAAM;6DAAC;AALd,6BAA6B;IADzC,IAAA,WAAM,GAAE;IAQM,mBAAA,IAAA,WAAM,EAAC,yCAAyB,CAAC,CAAA;;GAPnC,6BAA6B,CAsDzC;AAtDY,sEAA6B"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ /**
3
+ * @file Automatically generated by barrelsby.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const tslib_1 = require("tslib");
7
+ tslib_1.__exportStar(require("./OidcWildcardRedirectUriModule"), exports);
8
+ tslib_1.__exportStar(require("./utils/wildcardRedirectUriAllowed"), exports);
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,0EAAgD;AAChD,6EAAmD"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wildcardRedirectUriAllowed = void 0;
4
+ const tslib_1 = require("tslib");
5
+ // @ts-ignore
6
+ const wildcard_1 = tslib_1.__importDefault(require("wildcard"));
7
+ const hasWildcardHost = (redirectUri) => {
8
+ const { hostname } = new URL(redirectUri);
9
+ return hostname.includes("*");
10
+ };
11
+ const wildcardMatches = (redirectUri, wildcardUri) => !!(0, wildcard_1.default)(wildcardUri, redirectUri);
12
+ function wildcardRedirectUriAllowed(originalRedirectUriAllowed) {
13
+ return function (redirectUri) {
14
+ if (this.redirectUris.some(hasWildcardHost)) {
15
+ const wildcardUris = this.redirectUris.filter(hasWildcardHost);
16
+ return wildcardUris.some(wildcardMatches.bind(undefined, redirectUri)) || originalRedirectUriAllowed.call(this, redirectUri);
17
+ }
18
+ return originalRedirectUriAllowed.call(this, redirectUri);
19
+ };
20
+ }
21
+ exports.wildcardRedirectUriAllowed = wildcardRedirectUriAllowed;
22
+ //# sourceMappingURL=wildcardRedirectUriAllowed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wildcardRedirectUriAllowed.js","sourceRoot":"","sources":["../../../src/utils/wildcardRedirectUriAllowed.ts"],"names":[],"mappings":";;;;AAAA,aAAa;AACb,gEAAgC;AAEhC,MAAM,eAAe,GAAG,CAAC,WAAmB,EAAE,EAAE;IAC9C,MAAM,EAAC,QAAQ,EAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IACxC,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,WAAmB,EAAE,WAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAA,kBAAQ,EAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAE3G,SAAgB,0BAA0B,CAAC,0BAA+B;IACxE,OAAO,UAAU,WAAmB;QAClC,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE;YAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAC/D,OAAO,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,IAAI,0BAA0B,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;SAC9H;QACD,OAAO,0BAA0B,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC5D,CAAC,CAAC;AACJ,CAAC;AARD,gEAQC"}
@@ -0,0 +1,65 @@
1
+ import { __decorate, __metadata, __param } from "tslib";
2
+ import { Constant, Inject, Module } from "@tsed/di";
3
+ import { Logger } from "@tsed/logger";
4
+ import { OIDC_PROVIDER_NODE_MODULE } from "@tsed/oidc-provider";
5
+ // @ts-ignore
6
+ import psl from "psl";
7
+ import { wildcardRedirectUriAllowed } from "./utils/wildcardRedirectUriAllowed.js";
8
+ let OidcWildcardRedirectUriModule = class OidcWildcardRedirectUriModule {
9
+ module;
10
+ enabled;
11
+ logger;
12
+ constructor(module) {
13
+ this.module = module;
14
+ }
15
+ async $onCreateOIDC(provider) {
16
+ if (this.enabled) {
17
+ const { redirectUriAllowed } = provider.Client.prototype;
18
+ provider.Client.prototype.redirectUriAllowed = wildcardRedirectUriAllowed(redirectUriAllowed);
19
+ this.logger.warn("⚠️⚠️⚠️ OIDC Wildcard Uris plugin is ENABLED ⚠️⚠️⚠️");
20
+ }
21
+ }
22
+ async $alterOidcConfiguration(config) {
23
+ if (this.enabled) {
24
+ const actualProperties = config?.extraClientMetadata?.properties || [];
25
+ config.extraClientMetadata = {
26
+ properties: [...actualProperties, "redirect_uris"],
27
+ validator: this.validator.bind(this)
28
+ };
29
+ }
30
+ return config;
31
+ }
32
+ validator(ctx, key, value) {
33
+ if (key === "redirect_uris") {
34
+ for (const redirectUri of value) {
35
+ if (redirectUri.includes("*")) {
36
+ const { hostname, href } = new URL(redirectUri);
37
+ if (href.split("*").length !== 2) {
38
+ throw new this.module.errors.InvalidClientMetadata("redirect_uris with a wildcard may only contain a single one");
39
+ }
40
+ if (!hostname.includes("*")) {
41
+ throw new this.module.errors.InvalidClientMetadata("redirect_uris may only have a wildcard in the hostname");
42
+ }
43
+ if (!psl.get(hostname.split("*.")[1])) {
44
+ throw new this.module.errors.InvalidClientMetadata("redirect_uris with a wildcard must not match an eTLD+1 of a known public suffix domain");
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ };
51
+ __decorate([
52
+ Constant("oidc.plugins.wildcard.enabled", false),
53
+ __metadata("design:type", Boolean)
54
+ ], OidcWildcardRedirectUriModule.prototype, "enabled", void 0);
55
+ __decorate([
56
+ Inject(Logger),
57
+ __metadata("design:type", Logger)
58
+ ], OidcWildcardRedirectUriModule.prototype, "logger", void 0);
59
+ OidcWildcardRedirectUriModule = __decorate([
60
+ Module(),
61
+ __param(0, Inject(OIDC_PROVIDER_NODE_MODULE)),
62
+ __metadata("design:paramtypes", [Object])
63
+ ], OidcWildcardRedirectUriModule);
64
+ export { OidcWildcardRedirectUriModule };
65
+ //# sourceMappingURL=OidcWildcardRedirectUriModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OidcWildcardRedirectUriModule.js","sourceRoot":"","sources":["../../src/OidcWildcardRedirectUriModule.ts"],"names":[],"mappings":";AAAA,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAC,MAAM,UAAU,CAAC;AAClD,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAC;AACpC,OAAO,EAAC,yBAAyB,EAAe,MAAM,qBAAqB,CAAC;AAG5E,aAAa;AACb,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAC,0BAA0B,EAAC,MAAM,oCAAoC,CAAC;AAavE,IAAM,6BAA6B,GAAnC,MAAM,6BAA6B;IAOiB;IALhD,OAAO,CAAU;IAGhB,MAAM,CAAS;IAEzB,YAAyD,MAAiC;QAAjC,WAAM,GAAN,MAAM,CAA2B;IAAG,CAAC;IAE9F,KAAK,CAAC,aAAa,CAAC,QAAkB;QACpC,IAAI,IAAI,CAAC,OAAO,EAAE;YAChB,MAAM,EAAC,kBAAkB,EAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;YACvD,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,kBAAkB,GAAG,0BAA0B,CAAC,kBAAkB,CAAC,CAAC;YAE9F,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAC;SACxE;IACH,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,MAAoB;QAChD,IAAI,IAAI,CAAC,OAAO,EAAE;YAChB,MAAM,gBAAgB,GAAG,MAAM,EAAE,mBAAmB,EAAE,UAAU,IAAI,EAAE,CAAC;YAEvE,MAAM,CAAC,mBAAmB,GAAG;gBAC3B,UAAU,EAAE,CAAC,GAAG,gBAAgB,EAAE,eAAe,CAAC;gBAClD,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;aACrC,CAAC;SACH;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,SAAS,CAAC,GAAuB,EAAE,GAAW,EAAE,KAAU;QACxD,IAAI,GAAG,KAAK,eAAe,EAAE;YAC3B,KAAK,MAAM,WAAW,IAAI,KAAK,EAAE;gBAC/B,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;oBAC7B,MAAM,EAAC,QAAQ,EAAE,IAAI,EAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;oBAE9C,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;wBAChC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC,6DAA6D,CAAC,CAAC;qBACnH;oBAED,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;wBAC3B,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAAC,wDAAwD,CAAC,CAAC;qBAC9G;oBAED,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;wBACrC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB,CAChD,wFAAwF,CACzF,CAAC;qBACH;iBACF;aACF;SACF;IACH,CAAC;CACF,CAAA;AArDC;IAAC,QAAQ,CAAC,+BAA+B,EAAE,KAAK,CAAC;;8DACvB;AAE1B;IAAC,MAAM,CAAC,MAAM,CAAC;8BACG,MAAM;6DAAC;AALd,6BAA6B;IADzC,MAAM,EAAE;IAQM,WAAA,MAAM,CAAC,yBAAyB,CAAC,CAAA;;GAPnC,6BAA6B,CAsDzC;SAtDY,6BAA6B"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @file Automatically generated by barrelsby.
3
+ */
4
+ export * from "./OidcWildcardRedirectUriModule.js";
5
+ export * from "./utils/wildcardRedirectUriAllowed.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,iCAAiC,CAAC;AAChD,cAAc,oCAAoC,CAAC"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,17 @@
1
+ // @ts-ignore
2
+ import wildcard from "wildcard";
3
+ const hasWildcardHost = (redirectUri) => {
4
+ const { hostname } = new URL(redirectUri);
5
+ return hostname.includes("*");
6
+ };
7
+ const wildcardMatches = (redirectUri, wildcardUri) => !!wildcard(wildcardUri, redirectUri);
8
+ export function wildcardRedirectUriAllowed(originalRedirectUriAllowed) {
9
+ return function (redirectUri) {
10
+ if (this.redirectUris.some(hasWildcardHost)) {
11
+ const wildcardUris = this.redirectUris.filter(hasWildcardHost);
12
+ return wildcardUris.some(wildcardMatches.bind(undefined, redirectUri)) || originalRedirectUriAllowed.call(this, redirectUri);
13
+ }
14
+ return originalRedirectUriAllowed.call(this, redirectUri);
15
+ };
16
+ }
17
+ //# sourceMappingURL=wildcardRedirectUriAllowed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wildcardRedirectUriAllowed.js","sourceRoot":"","sources":["../../../src/utils/wildcardRedirectUriAllowed.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,MAAM,eAAe,GAAG,CAAC,WAAmB,EAAE,EAAE;IAC9C,MAAM,EAAC,QAAQ,EAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IACxC,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,WAAmB,EAAE,WAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAE3G,MAAM,UAAU,0BAA0B,CAAC,0BAA+B;IACxE,OAAO,UAAU,WAAmB;QAClC,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE;YAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YAC/D,OAAO,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,IAAI,0BAA0B,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;SAC9H;QACD,OAAO,0BAA0B,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC5D,CAAC,CAAC;AACJ,CAAC"}