@mondaydotcomorg/monday-authorization 3.3.0-feature-bashanye-navigate-can-action-in-scope-to-graph-63c65ad → 3.3.1-feature-bashanye-add-membership-create-delete-api-d00c165

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.
Files changed (114) hide show
  1. package/README.md +160 -11
  2. package/dist/attributions-service.d.ts +3 -2
  3. package/dist/attributions-service.d.ts.map +1 -1
  4. package/dist/attributions-service.js +1 -0
  5. package/dist/authorization-internal-service.d.ts +1 -1
  6. package/dist/authorization-internal-service.d.ts.map +1 -1
  7. package/dist/authorization-service.d.ts +5 -0
  8. package/dist/authorization-service.d.ts.map +1 -1
  9. package/dist/authorization-service.js +30 -26
  10. package/dist/clients/graph-api.d.ts +28 -0
  11. package/dist/clients/graph-api.d.ts.map +1 -0
  12. package/dist/clients/{graph-api.client.js → graph-api.js} +48 -40
  13. package/dist/clients/platform-api.d.ts +26 -0
  14. package/dist/clients/platform-api.d.ts.map +1 -0
  15. package/dist/clients/{platform-api.client.js → platform-api.js} +20 -20
  16. package/dist/constants.d.ts +1 -0
  17. package/dist/constants.d.ts.map +1 -1
  18. package/dist/constants.js +2 -0
  19. package/dist/esm/attributions-service.d.ts +3 -2
  20. package/dist/esm/attributions-service.d.ts.map +1 -1
  21. package/dist/esm/attributions-service.mjs +1 -0
  22. package/dist/esm/authorization-internal-service.d.ts +1 -1
  23. package/dist/esm/authorization-internal-service.d.ts.map +1 -1
  24. package/dist/esm/authorization-service.d.ts +5 -0
  25. package/dist/esm/authorization-service.d.ts.map +1 -1
  26. package/dist/esm/authorization-service.mjs +31 -27
  27. package/dist/esm/clients/graph-api.d.ts +28 -0
  28. package/dist/esm/clients/graph-api.d.ts.map +1 -0
  29. package/dist/esm/clients/{graph-api.client.mjs → graph-api.mjs} +48 -40
  30. package/dist/esm/clients/platform-api.d.ts +26 -0
  31. package/dist/esm/clients/platform-api.d.ts.map +1 -0
  32. package/dist/esm/clients/{platform-api.client.mjs → platform-api.mjs} +21 -21
  33. package/dist/esm/constants.d.ts +1 -0
  34. package/dist/esm/constants.d.ts.map +1 -1
  35. package/dist/esm/constants.mjs +2 -1
  36. package/dist/esm/index.d.ts +7 -0
  37. package/dist/esm/index.d.ts.map +1 -1
  38. package/dist/esm/index.mjs +9 -0
  39. package/dist/esm/memberships.d.ts +30 -0
  40. package/dist/esm/memberships.d.ts.map +1 -0
  41. package/dist/esm/memberships.mjs +98 -0
  42. package/dist/esm/metrics-service.d.ts +12 -0
  43. package/dist/esm/metrics-service.d.ts.map +1 -0
  44. package/dist/esm/metrics-service.mjs +54 -0
  45. package/dist/esm/prometheus-service.d.ts +1 -3
  46. package/dist/esm/prometheus-service.d.ts.map +1 -1
  47. package/dist/esm/prometheus-service.mjs +5 -58
  48. package/dist/esm/types/graph-api.types.d.ts +8 -7
  49. package/dist/esm/types/graph-api.types.d.ts.map +1 -1
  50. package/dist/esm/types/memberships.d.ts +42 -0
  51. package/dist/esm/types/memberships.d.ts.map +1 -0
  52. package/dist/esm/types/memberships.mjs +1 -0
  53. package/dist/esm/types/scoped-actions-contracts.d.ts +10 -1
  54. package/dist/esm/types/scoped-actions-contracts.d.ts.map +1 -1
  55. package/dist/esm/types/scoped-actions-contracts.mjs +9 -0
  56. package/dist/esm/utils/api-error-handler.d.ts +2 -0
  57. package/dist/esm/utils/api-error-handler.d.ts.map +1 -0
  58. package/dist/esm/utils/api-error-handler.mjs +18 -0
  59. package/dist/index.d.ts +7 -0
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +10 -0
  62. package/dist/memberships.d.ts +30 -0
  63. package/dist/memberships.d.ts.map +1 -0
  64. package/dist/memberships.js +100 -0
  65. package/dist/metrics-service.d.ts +12 -0
  66. package/dist/metrics-service.d.ts.map +1 -0
  67. package/dist/metrics-service.js +58 -0
  68. package/dist/prometheus-service.d.ts +1 -3
  69. package/dist/prometheus-service.d.ts.map +1 -1
  70. package/dist/prometheus-service.js +4 -59
  71. package/dist/types/graph-api.types.d.ts +8 -7
  72. package/dist/types/graph-api.types.d.ts.map +1 -1
  73. package/dist/types/memberships.d.ts +42 -0
  74. package/dist/types/memberships.d.ts.map +1 -0
  75. package/dist/types/memberships.js +1 -0
  76. package/dist/types/scoped-actions-contracts.d.ts +10 -1
  77. package/dist/types/scoped-actions-contracts.d.ts.map +1 -1
  78. package/dist/types/scoped-actions-contracts.js +9 -0
  79. package/dist/utils/api-error-handler.d.ts +2 -0
  80. package/dist/utils/api-error-handler.d.ts.map +1 -0
  81. package/dist/utils/api-error-handler.js +20 -0
  82. package/package.json +5 -2
  83. package/src/attributions-service.ts +93 -0
  84. package/src/authorization-attributes-service.ts +234 -0
  85. package/src/authorization-internal-service.ts +129 -0
  86. package/src/authorization-middleware.ts +51 -0
  87. package/src/authorization-service.ts +356 -0
  88. package/src/clients/graph-api.ts +170 -0
  89. package/src/clients/platform-api.ts +117 -0
  90. package/src/constants/sns.ts +5 -0
  91. package/src/constants.ts +23 -0
  92. package/src/index.ts +63 -0
  93. package/src/memberships.ts +111 -0
  94. package/src/metrics-service.ts +71 -0
  95. package/src/prometheus-service.ts +51 -0
  96. package/src/roles-service.ts +125 -0
  97. package/src/testKit/index.ts +69 -0
  98. package/src/types/authorization-attributes-contracts.ts +33 -0
  99. package/src/types/express.ts +8 -0
  100. package/src/types/general.ts +32 -0
  101. package/src/types/graph-api.types.ts +25 -0
  102. package/src/types/memberships.ts +47 -0
  103. package/src/types/roles.ts +42 -0
  104. package/src/types/scoped-actions-contracts.ts +57 -0
  105. package/src/utils/api-error-handler.ts +25 -0
  106. package/src/utils/authorization.utils.ts +47 -0
  107. package/dist/clients/graph-api.client.d.ts +0 -24
  108. package/dist/clients/graph-api.client.d.ts.map +0 -1
  109. package/dist/clients/platform-api.client.d.ts +0 -31
  110. package/dist/clients/platform-api.client.d.ts.map +0 -1
  111. package/dist/esm/clients/graph-api.client.d.ts +0 -24
  112. package/dist/esm/clients/graph-api.client.d.ts.map +0 -1
  113. package/dist/esm/clients/platform-api.client.d.ts +0 -31
  114. package/dist/esm/clients/platform-api.client.d.ts.map +0 -1
@@ -0,0 +1,57 @@
1
+ export interface WorkspaceScope {
2
+ workspaceId: number;
3
+ }
4
+
5
+ export interface BoardScope {
6
+ boardId: number;
7
+ }
8
+
9
+ export interface PulseScope {
10
+ pulseId: number;
11
+ }
12
+
13
+ export interface AccountProductScope {
14
+ accountProductId: number;
15
+ }
16
+
17
+ export interface AccountScope {
18
+ accountId: number;
19
+ }
20
+
21
+ export type ScopeOptions = WorkspaceScope | BoardScope | PulseScope | AccountProductScope | AccountScope;
22
+
23
+ export interface Translation {
24
+ key: string;
25
+ [option: string]: string;
26
+ }
27
+
28
+ export enum PermitTechnicalReason {
29
+ NO_REASON = 0,
30
+ NOT_ELIGIBLE = 1,
31
+ BY_ROLE_IN_SCOPE = 2,
32
+ /**
33
+ * NOT_APPLICABLE indicates that the permit was requested as part of the `permissions` parameter to the `getPermits`
34
+ * method, but would not otherwise be returned. This is done so that a cache in the monolith can serve
35
+ * two purposes: to mean both that a permit was requested and that it was received; at least: in the
36
+ * case of where a `permissions` parameter is passed to the `getPermits` method.
37
+ */
38
+ NOT_APPLICABLE = 3,
39
+ BY_POLICY = 4,
40
+ BY_OVERRIDE = 5,
41
+ }
42
+
43
+ export interface ScopedActionPermit {
44
+ can: boolean;
45
+ reason: Translation;
46
+ technicalReason: PermitTechnicalReason;
47
+ }
48
+
49
+ export interface ScopedAction {
50
+ action: string;
51
+ scope: ScopeOptions;
52
+ }
53
+
54
+ export interface ScopedActionResponseObject {
55
+ scopedAction: ScopedAction;
56
+ permit: ScopedActionPermit;
57
+ }
@@ -0,0 +1,25 @@
1
+ import { HttpFetcherError } from '@mondaydotcomorg/monday-fetch-api';
2
+ import { AuthorizationInternalService, logger } from '../authorization-internal-service';
3
+ import { recordAuthorizationError } from '../metrics-service';
4
+
5
+ export function handleApiError(
6
+ err: unknown,
7
+ apiType: 'platform' | 'graph' | 'authorization',
8
+ placement: string
9
+ ): never {
10
+ if (err instanceof HttpFetcherError) {
11
+ logger.error(
12
+ { tag: `${apiType}-api`, status: err.status, error: err.message },
13
+ `${apiType.charAt(0).toUpperCase() + apiType.slice(1)} API ${placement} request failed`
14
+ );
15
+ recordAuthorizationError(apiType, err.status, placement);
16
+ AuthorizationInternalService.throwOnHttpError(err.status, placement);
17
+ } else {
18
+ logger.error(
19
+ { tag: `${apiType}-api`, error: err instanceof Error ? err.message : String(err) },
20
+ `${apiType.charAt(0).toUpperCase() + apiType.slice(1)} API ${placement} request failed`
21
+ );
22
+ recordAuthorizationError(apiType, 500, placement);
23
+ throw err;
24
+ }
25
+ }
@@ -0,0 +1,47 @@
1
+ import snakeCase from 'lodash/snakeCase.js';
2
+ import camelCase from 'lodash/camelCase.js';
3
+ import mapKeys from 'lodash/mapKeys.js';
4
+ import { ScopeOptions } from '../types/scoped-actions-contracts';
5
+ import { ResourceType, ResourceId } from '../types/graph-api.types';
6
+
7
+ export type CamelCase<S extends string> = S extends `${infer F}_${infer R}` ? `${F}${Capitalize<CamelCase<R>>}` : S;
8
+ export type CamelCaseKeys<T> = T extends object
9
+ ? { [K in keyof T as K extends string ? CamelCase<K> : K]: CamelCaseKeys<T[K]> }
10
+ : T;
11
+
12
+ /**
13
+ * Converts a scope object to resource type and resource ID
14
+ */
15
+ export function scopeToResource(scope: ScopeOptions): { resourceType: ResourceType; resourceId: ResourceId } {
16
+ if ('workspaceId' in scope) {
17
+ return { resourceType: 'workspace', resourceId: scope.workspaceId };
18
+ }
19
+ if ('boardId' in scope) {
20
+ return { resourceType: 'board', resourceId: scope.boardId };
21
+ }
22
+ if ('pulseId' in scope) {
23
+ return { resourceType: 'pulse', resourceId: scope.pulseId };
24
+ }
25
+ if ('accountProductId' in scope) {
26
+ return { resourceType: 'account_product', resourceId: scope.accountProductId };
27
+ }
28
+ if ('accountId' in scope) {
29
+ return { resourceType: 'account', resourceId: scope.accountId };
30
+ }
31
+
32
+ throw new Error('Unsupported scope provided');
33
+ }
34
+
35
+ /**
36
+ * Converts object keys from snake_case to camelCase
37
+ */
38
+ export function toCamelCase<T extends object>(obj: T): CamelCaseKeys<T> {
39
+ return mapKeys(obj, (_, key) => camelCase(key)) as CamelCaseKeys<T>;
40
+ }
41
+
42
+ /**
43
+ * Converts object keys from camelCase to snake_case
44
+ */
45
+ export function toSnakeCase<T extends object>(obj: T): Record<string, any> {
46
+ return mapKeys(obj, (_, key) => snakeCase(key));
47
+ }
@@ -1,24 +0,0 @@
1
- import { ScopedAction, ScopedActionResponseObject } from '../types/scoped-actions-contracts';
2
- import { GraphIsAllowedDto, GraphIsAllowedResponse } from '../types/graph-api.types';
3
- /**
4
- * Client for handling Graph API authorization operations
5
- */
6
- export declare class GraphApiClient {
7
- /**
8
- * Builds the request body for Graph API calls
9
- */
10
- static buildRequestBody(scopedActions: ScopedAction[]): GraphIsAllowedDto;
11
- /**
12
- * Fetches authorization data from the Graph API
13
- */
14
- static fetchPermissions(internalAuthToken: string, scopedActions: ScopedAction[]): Promise<GraphIsAllowedResponse>;
15
- /**
16
- * Maps Graph API response to the expected format
17
- */
18
- static mapResponse(scopedActions: ScopedAction[], graphResponse: GraphIsAllowedResponse): ScopedActionResponseObject[];
19
- /**
20
- * Performs a complete authorization check using the Graph API
21
- */
22
- static checkPermissions(internalAuthToken: string, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
23
- }
24
- //# sourceMappingURL=graph-api.client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"graph-api.client.d.ts","sourceRoot":"","sources":["../../src/clients/graph-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAG3B,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EAIvB,MAAM,0BAA0B,CAAC;AAMlC;;GAEG;AACH,qBAAa,cAAc;IACzB;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,iBAAiB;IAyBzE;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,sBAAsB,CAAC;IA2ClC;;OAEG;IACH,MAAM,CAAC,WAAW,CAChB,aAAa,EAAE,YAAY,EAAE,EAC7B,aAAa,EAAE,sBAAsB,GACpC,0BAA0B,EAAE;IAsC/B;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAIzC"}
@@ -1,31 +0,0 @@
1
- import { ScopedAction, ScopedActionResponseObject } from '../types/scoped-actions-contracts';
2
- import { PlatformProfile } from '../attributions-service';
3
- type ScopedActionPlatformPayload = Omit<ScopedAction, 'scope'> & {
4
- scope: Record<string, number>;
5
- };
6
- interface CanActionsInScopesResponse {
7
- result: ScopedActionResponseObject[];
8
- }
9
- /**
10
- * Client for handling Platform API authorization operations
11
- */
12
- export declare class PlatformApiClient {
13
- /**
14
- * Builds the request payload for Platform API calls
15
- */
16
- static buildRequestPayload(scopedActions: ScopedAction[]): ScopedActionPlatformPayload[];
17
- /**
18
- * Fetches authorization data from the Platform API
19
- */
20
- static fetchPermissions(profile: PlatformProfile, internalAuthToken: string, userId: number, scopedActionsPayload: ScopedActionPlatformPayload[]): Promise<CanActionsInScopesResponse>;
21
- /**
22
- * Maps Platform API response to the expected format
23
- */
24
- static mapResponse(response: CanActionsInScopesResponse): ScopedActionResponseObject[];
25
- /**
26
- * Performs a complete authorization check using the Platform API
27
- */
28
- static checkPermissions(profile: PlatformProfile, internalAuthToken: string, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
29
- }
30
- export {};
31
- //# sourceMappingURL=platform-api.client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"platform-api.client.d.ts","sourceRoot":"","sources":["../../src/clients/platform-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAE7F,OAAO,EAA0B,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAOlF,KAAK,2BAA2B,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG;IAC/D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC;AAEF,UAAU,0BAA0B;IAClC,MAAM,EAAE,0BAA0B,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,2BAA2B,EAAE;IAOxF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,oBAAoB,EAAE,2BAA2B,EAAE,GAClD,OAAO,CAAC,0BAA0B,CAAC;IAuCtC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,0BAA0B,GAAG,0BAA0B,EAAE;IAkBtF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAKzC"}
@@ -1,24 +0,0 @@
1
- import { ScopedAction, ScopedActionResponseObject } from '../types/scoped-actions-contracts';
2
- import { GraphIsAllowedDto, GraphIsAllowedResponse } from '../types/graph-api.types';
3
- /**
4
- * Client for handling Graph API authorization operations
5
- */
6
- export declare class GraphApiClient {
7
- /**
8
- * Builds the request body for Graph API calls
9
- */
10
- static buildRequestBody(scopedActions: ScopedAction[]): GraphIsAllowedDto;
11
- /**
12
- * Fetches authorization data from the Graph API
13
- */
14
- static fetchPermissions(internalAuthToken: string, scopedActions: ScopedAction[]): Promise<GraphIsAllowedResponse>;
15
- /**
16
- * Maps Graph API response to the expected format
17
- */
18
- static mapResponse(scopedActions: ScopedAction[], graphResponse: GraphIsAllowedResponse): ScopedActionResponseObject[];
19
- /**
20
- * Performs a complete authorization check using the Graph API
21
- */
22
- static checkPermissions(internalAuthToken: string, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
23
- }
24
- //# sourceMappingURL=graph-api.client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"graph-api.client.d.ts","sourceRoot":"","sources":["../../../src/clients/graph-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,0BAA0B,EAG3B,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EAIvB,MAAM,0BAA0B,CAAC;AAMlC;;GAEG;AACH,qBAAa,cAAc;IACzB;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,iBAAiB;IAyBzE;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,sBAAsB,CAAC;IA2ClC;;OAEG;IACH,MAAM,CAAC,WAAW,CAChB,aAAa,EAAE,YAAY,EAAE,EAC7B,aAAa,EAAE,sBAAsB,GACpC,0BAA0B,EAAE;IAsC/B;;OAEG;WACU,gBAAgB,CAC3B,iBAAiB,EAAE,MAAM,EACzB,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAIzC"}
@@ -1,31 +0,0 @@
1
- import { ScopedAction, ScopedActionResponseObject } from '../types/scoped-actions-contracts';
2
- import { PlatformProfile } from '../attributions-service';
3
- type ScopedActionPlatformPayload = Omit<ScopedAction, 'scope'> & {
4
- scope: Record<string, number>;
5
- };
6
- interface CanActionsInScopesResponse {
7
- result: ScopedActionResponseObject[];
8
- }
9
- /**
10
- * Client for handling Platform API authorization operations
11
- */
12
- export declare class PlatformApiClient {
13
- /**
14
- * Builds the request payload for Platform API calls
15
- */
16
- static buildRequestPayload(scopedActions: ScopedAction[]): ScopedActionPlatformPayload[];
17
- /**
18
- * Fetches authorization data from the Platform API
19
- */
20
- static fetchPermissions(profile: PlatformProfile, internalAuthToken: string, userId: number, scopedActionsPayload: ScopedActionPlatformPayload[]): Promise<CanActionsInScopesResponse>;
21
- /**
22
- * Maps Platform API response to the expected format
23
- */
24
- static mapResponse(response: CanActionsInScopesResponse): ScopedActionResponseObject[];
25
- /**
26
- * Performs a complete authorization check using the Platform API
27
- */
28
- static checkPermissions(profile: PlatformProfile, internalAuthToken: string, userId: number, scopedActions: ScopedAction[]): Promise<ScopedActionResponseObject[]>;
29
- }
30
- export {};
31
- //# sourceMappingURL=platform-api.client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"platform-api.client.d.ts","sourceRoot":"","sources":["../../../src/clients/platform-api.client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAE7F,OAAO,EAA0B,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAOlF,KAAK,2BAA2B,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG;IAC/D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B,CAAC;AAEF,UAAU,0BAA0B;IAClC,MAAM,EAAE,0BAA0B,EAAE,CAAC;CACtC;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,2BAA2B,EAAE;IAOxF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,oBAAoB,EAAE,2BAA2B,EAAE,GAClD,OAAO,CAAC,0BAA0B,CAAC;IAuCtC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,0BAA0B,GAAG,0BAA0B,EAAE;IAkBtF;;OAEG;WACU,gBAAgB,CAC3B,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,YAAY,EAAE,GAC5B,OAAO,CAAC,0BAA0B,EAAE,CAAC;CAKzC"}