@zola_do/authorization 0.1.9 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # @zola_do/authorization
2
+
3
+ JWT authentication, API key validation, guards, and strategies for NestJS.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # Install individually
9
+ npm install @zola_do/authorization
10
+
11
+ # Or via meta package
12
+ npm install @zola_do/nestjs-shared
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Module Setup
18
+
19
+ ```typescript
20
+ import { Module } from '@nestjs/common';
21
+ import { AuthorizationModule } from '@zola_do/authorization';
22
+
23
+ @Module({
24
+ imports: [AuthorizationModule],
25
+ })
26
+ export class AppModule {}
27
+ ```
28
+
29
+ By default, `JwtGuard` is registered as a global guard. Protect routes automatically; use `@AllowAnonymous()` for public routes.
30
+
31
+ ### Protected Routes
32
+
33
+ ```typescript
34
+ import { Controller, Get } from '@nestjs/common';
35
+ import { CurrentUser, JwtGuard, UseGuards } from '@zola_do/authorization';
36
+
37
+ @Controller('profile')
38
+ @UseGuards(JwtGuard)
39
+ export class ProfileController {
40
+ @Get()
41
+ getProfile(@CurrentUser() user: any) {
42
+ return user; // Contains JWT payload (id, email, organization, etc.)
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### Anonymous Routes
48
+
49
+ ```typescript
50
+ import { AllowAnonymous } from '@zola_do/authorization';
51
+
52
+ @Get('public')
53
+ @AllowAnonymous()
54
+ getPublicData() {
55
+ return { message: 'No auth required' };
56
+ }
57
+ ```
58
+
59
+ ### Permission Guards
60
+
61
+ Require specific permissions on routes:
62
+
63
+ ```typescript
64
+ import { PermissionsGuard } from '@zola_do/authorization';
65
+
66
+ @Post()
67
+ @UseGuards(JwtGuard, PermissionsGuard('product:create'))
68
+ createProduct(@Body() dto: CreateProductDto) {}
69
+ ```
70
+
71
+ ### API Key Guard
72
+
73
+ Protect routes with API key validation:
74
+
75
+ ```typescript
76
+ import { ApiKeyGuard } from '@zola_do/authorization';
77
+
78
+ @UseGuards(ApiKeyGuard)
79
+ @Get('api-data')
80
+ getApiData() {}
81
+ ```
82
+
83
+ ### AuthHelper
84
+
85
+ Generate and verify tokens:
86
+
87
+ ```typescript
88
+ import { AuthHelper } from '@zola_do/authorization';
89
+
90
+ @Injectable()
91
+ export class AuthService {
92
+ constructor(private readonly authHelper: AuthHelper) {}
93
+
94
+ async login(user: User) {
95
+ return this.authHelper.generateTokens(user);
96
+ }
97
+ }
98
+ ```
99
+
100
+ ## Environment Variables
101
+
102
+ | Variable | Description |
103
+ |----------|-------------|
104
+ | `JWT_ACCESS_TOKEN_SECRET` | Secret for access token signing |
105
+ | `JWT_REFRESH_TOKEN_SECRET` | Secret for refresh token signing |
106
+ | `JWT_ACCESS_TOKEN_EXPIRES` | Access token TTL (e.g. `15m`) |
107
+ | `JWT_REFRESH_TOKEN_EXPIRES` | Refresh token TTL (e.g. `7d`) |
108
+ | `API_KEY` | API key for `ApiKeyGuard` validation |
109
+
110
+ ## Exports
111
+
112
+ - **Guards:** `JwtGuard`, `JwtRefreshGuard`, `PermissionsGuard`, `ApiKeyGuard`, `VendorGuard`, `OptionalJwtGuard`, `ThrottlerBehindProxyGuard`
113
+ - **Decorators:** `@CurrentUser()`, `@AllowAnonymous()`
114
+ - **Strategies:** `JwtStrategy`, `JwtRefreshTokenStrategy`
115
+ - **Helpers:** `AuthHelper`
116
+
117
+ ## Related Packages
118
+
119
+ - [@zola_do/core](../core) — Shared types and decorators
120
+ - [@zola_do/interceptors](../interceptors) — TenantInterceptor uses `req.user` from JWT
121
+ - [@zola_do/crud](../crud) — Uses JwtGuard and PermissionsGuard
@@ -14,7 +14,6 @@ const common_1 = require("@nestjs/common");
14
14
  const core_1 = require("@nestjs/core");
15
15
  const allow_anonymous_decorator_1 = require("../decorators/allow-anonymous.decorator");
16
16
  const jsonwebtoken = require("jsonwebtoken");
17
- const extract_user_1 = require("../utils/extract-user");
18
17
  let JwtGuard = class JwtGuard {
19
18
  constructor(reflector) {
20
19
  this.reflector = reflector;
@@ -37,8 +36,7 @@ let JwtGuard = class JwtGuard {
37
36
  throw new common_1.UnauthorizedException('ConfigurationError', 'JWT_ACCESS_TOKEN_SECRET is not configured');
38
37
  }
39
38
  const user = jsonwebtoken.verify(token, secret);
40
- const parsedUser = (0, extract_user_1.extractUser)(request, user);
41
- request.user = parsedUser;
39
+ request.user = user;
42
40
  return true;
43
41
  }
44
42
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"jwt.guard.js","sourceRoot":"","sources":["../../src/guards/jwt.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAKwB;AAExB,uCAAyC;AACzC,uFAAmF;AACnF,6CAA4C;AAC5C,wDAAoD;AAG7C,IAAM,QAAQ,GAAd,MAAM,QAAQ;IACnB,YACmB,SAAoB;QAApB,cAAS,GAAT,SAAS,CAAW;IACnC,CAAC;IAEL,KAAK,CAAC,WAAW,CAAC,OAAyB;;QACzC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;YACpD,MAAM,kBAAkB,GAAG,MAAA,IAAI,CAAC,SAAS,0CAAE,iBAAiB,CAC1D,oDAAwB,EACxB,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAC3C,CAAC;YACF,IAAI,kBAAkB,EAAE,CAAC;gBACvB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;gBAC3B,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;YACnD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,8BAAqB,CAC7B,mBAAmB,EACnB,sBAAsB,CACvB,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;YACnD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,8BAAqB,CAC7B,oBAAoB,EACpB,2CAA2C,CAC5C,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAEhD,MAAM,UAAU,GAAQ,IAAA,0BAAW,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAEnD,OAAO,CAAC,IAAI,GAAG,UAAU,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAEO,sBAAsB,CAAC,OAAgB;;QAC7C,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAA,MAAA,OAAO,CAAC,OAAO,CAAC,aAAa,0CAAE,KAAK,CAAC,GAAG,CAAC,mCAAI,EAAE,CAAC;QACtE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,CAAC;CACF,CAAA;AAhDY,4BAAQ;mBAAR,QAAQ;IADpB,IAAA,mBAAU,GAAE;qCAGmB,gBAAS;GAF5B,QAAQ,CAgDpB"}
1
+ {"version":3,"file":"jwt.guard.js","sourceRoot":"","sources":["../../src/guards/jwt.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAKwB;AAExB,uCAAyC;AACzC,uFAAmF;AACnF,6CAA4C;AAGrC,IAAM,QAAQ,GAAd,MAAM,QAAQ;IACnB,YACmB,SAAoB;QAApB,cAAS,GAAT,SAAS,CAAW;IACnC,CAAC;IAEL,KAAK,CAAC,WAAW,CAAC,OAAyB;;QACzC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;YACpD,MAAM,kBAAkB,GAAG,MAAA,IAAI,CAAC,SAAS,0CAAE,iBAAiB,CAC1D,oDAAwB,EACxB,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAC3C,CAAC;YACF,IAAI,kBAAkB,EAAE,CAAC;gBACvB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;gBAC3B,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;YACnD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,8BAAqB,CAC7B,mBAAmB,EACnB,sBAAsB,CACvB,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;YACnD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,8BAAqB,CAC7B,oBAAoB,EACpB,2CAA2C,CAC5C,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAEhD,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAEO,sBAAsB,CAAC,OAAgB;;QAC7C,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAA,MAAA,OAAO,CAAC,OAAO,CAAC,aAAa,0CAAE,KAAK,CAAC,GAAG,CAAC,mCAAI,EAAE,CAAC;QACtE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,CAAC;CACF,CAAA;AA9CY,4BAAQ;mBAAR,QAAQ;IADpB,IAAA,mBAAU,GAAE;qCAGmB,gBAAS;GAF5B,QAAQ,CA8CpB"}
@@ -12,7 +12,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.OptionalJwtGuard = void 0;
13
13
  const common_1 = require("@nestjs/common");
14
14
  const auth_helper_1 = require("../helper/auth.helper");
15
- const extract_user_1 = require("../utils/extract-user");
16
15
  let OptionalJwtGuard = class OptionalJwtGuard {
17
16
  constructor(authHelper) {
18
17
  this.authHelper = authHelper;
@@ -32,8 +31,7 @@ let OptionalJwtGuard = class OptionalJwtGuard {
32
31
  return true;
33
32
  }
34
33
  const user = await this.authHelper.verify(token, secret);
35
- const parsedUser = (0, extract_user_1.extractUser)(request, user);
36
- request.user = parsedUser;
34
+ request.user = user;
37
35
  return true;
38
36
  }
39
37
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"optional-jwt.guard.js","sourceRoot":"","sources":["../../src/guards/optional-jwt.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA2E;AAE3E,uDAAmD;AACnD,wDAAoD;AAG7C,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC3B,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAEvD,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;YACpD,MAAM,KAAK,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;YACnD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;YACnD,IAAI,CAAC,MAAM,EAAE,CAAC;gBAGZ,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;oBAC1C,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;gBAC5D,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAEzD,MAAM,UAAU,GAAQ,IAAA,0BAAW,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAEnD,OAAO,CAAC,IAAI,GAAG,UAAU,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAEO,sBAAsB,CAAC,OAAgB;;QAC7C,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAA,MAAA,OAAO,CAAC,OAAO,CAAC,aAAa,0CAAE,KAAK,CAAC,GAAG,CAAC,mCAAI,EAAE,CAAC;QACtE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,CAAC;CACF,CAAA;AApCY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;qCAE8B,wBAAU;GADxC,gBAAgB,CAoC5B"}
1
+ {"version":3,"file":"optional-jwt.guard.js","sourceRoot":"","sources":["../../src/guards/optional-jwt.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA2E;AAE3E,uDAAmD;AAG5C,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC3B,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAEvD,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;YACpD,MAAM,KAAK,GAAG,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;YACnD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;YACnD,IAAI,CAAC,MAAM,EAAE,CAAC;gBAGZ,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;oBAC1C,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;gBAC5D,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAEzD,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;YACpB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAEO,sBAAsB,CAAC,OAAgB;;QAC7C,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAA,MAAA,OAAO,CAAC,OAAO,CAAC,aAAa,0CAAE,KAAK,CAAC,GAAG,CAAC,mCAAI,EAAE,CAAC;QACtE,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/C,CAAC;CACF,CAAA;AAlCY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;qCAE8B,wBAAU;GADxC,gBAAgB,CAkC5B"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export * from './authorization.module';
1
+ export { AuthorizationModule } from './authorization.module';
2
2
  export * from './decorators/allow-anonymous.decorator';
3
3
  export * from './decorators/current-user.decorator';
4
4
  export * from './guards/jwt.guard';
package/dist/index.js CHANGED
@@ -14,7 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./authorization.module"), exports);
17
+ exports.AuthorizationModule = void 0;
18
+ var authorization_module_1 = require("./authorization.module");
19
+ Object.defineProperty(exports, "AuthorizationModule", { enumerable: true, get: function () { return authorization_module_1.AuthorizationModule; } });
18
20
  __exportStar(require("./decorators/allow-anonymous.decorator"), exports);
19
21
  __exportStar(require("./decorators/current-user.decorator"), exports);
20
22
  __exportStar(require("./guards/jwt.guard"), exports);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,yEAAuD;AACvD,sEAAoD;AACpD,qDAAmC;AACnC,6DAA2C;AAC3C,uDAAqC;AACrC,6DAA2C;AAC3C,wEAAsD;AACtD,yDAAuC;AACvC,wDAAsC;AACtC,8DAA4C;AAC5C,wEAAsD;AACtD,0DAAwC;AACxC,sDAAoC;AACpC,oDAAkC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,+DAA6D;AAApD,2HAAA,mBAAmB,OAAA;AAC5B,yEAAuD;AACvD,sEAAoD;AACpD,qDAAmC;AACnC,6DAA2C;AAC3C,uDAAqC;AACrC,6DAA2C;AAC3C,wEAAsD;AACtD,yDAAuC;AACvC,wDAAsC;AACtC,8DAA4C;AAC5C,wEAAsD;AACtD,0DAAwC;AACxC,sDAAoC;AACpC,oDAAkC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zola_do/authorization",
3
- "version": "0.1.9",
3
+ "version": "0.1.13",
4
4
  "description": "JWT auth, guards, strategies for NestJS",
5
5
  "author": "zolaDO",
6
6
  "license": "ISC",
@@ -15,7 +15,10 @@
15
15
  "default": "./dist/index.js"
16
16
  }
17
17
  },
18
- "files": ["dist", "README.md"],
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
19
22
  "scripts": {
20
23
  "build": "rimraf dist && tsc",
21
24
  "prepublishOnly": "npm run build"
@@ -33,10 +36,12 @@
33
36
  "rxjs": "^7.0.0 || ^8.0.0"
34
37
  },
35
38
  "peerDependenciesMeta": {
36
- "@nestjs/throttler": { "optional": true }
39
+ "@nestjs/throttler": {
40
+ "optional": true
41
+ }
37
42
  },
38
43
  "dependencies": {
39
- "@zola_do/core": "file:../core",
44
+ "@zola_do/core": "^0.1.9",
40
45
  "bcrypt": "^6.0.0",
41
46
  "jsonwebtoken": "^9.0.2"
42
47
  },
@@ -1 +0,0 @@
1
- export declare const extractUser: (request: any, user: any) => any;
@@ -1,31 +0,0 @@
1
- "use strict";
2
- var __rest = (this && this.__rest) || function (s, e) {
3
- var t = {};
4
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
- t[p] = s[p];
6
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
- t[p[i]] = s[p[i]];
10
- }
11
- return t;
12
- };
13
- Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.extractUser = void 0;
15
- const extractUser = (request, user) => {
16
- const { organizations } = user, rest = __rest(user, ["organizations"]);
17
- let parsedUser = rest;
18
- if (organizations && organizations.length > 0) {
19
- let organization;
20
- if (request.headers && request.headers['x-organization-id']) {
21
- organization = organizations.find((x) => x.organization.id == request.headers['x-organization-id']);
22
- }
23
- else {
24
- organization = organizations[0];
25
- }
26
- parsedUser = Object.assign(Object.assign(Object.assign({}, parsedUser), { fullName: parsedUser.firstName + ' ' + parsedUser.lastName }), organization);
27
- }
28
- return parsedUser;
29
- };
30
- exports.extractUser = extractUser;
31
- //# sourceMappingURL=extract-user.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extract-user.js","sourceRoot":"","sources":["../../src/utils/extract-user.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAO,MAAM,WAAW,GAAG,CAAC,OAAY,EAAE,IAAS,EAAE,EAAE;IACrD,MAAM,EAAE,aAAa,KAAc,IAAI,EAAb,IAAI,UAAK,IAAI,EAAjC,iBAA0B,CAAO,CAAC;IACxC,IAAI,UAAU,GAAQ,IAAI,CAAC;IAC3B,IAAI,aAAa,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,IAAI,YAAiB,CAAC;QAEtB,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC5D,YAAY,GAAG,aAAa,CAAC,IAAI,CAC/B,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CACtE,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC;QAED,UAAU,iDACL,UAAU,KACb,QAAQ,EAAE,UAAU,CAAC,SAAS,GAAG,GAAG,GAAG,UAAU,CAAC,QAAQ,KACvD,YAAY,CAChB,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC;AArBW,QAAA,WAAW,eAqBtB"}