@nest-boot/row-level-security 7.1.0 → 7.2.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.
Files changed (81) hide show
  1. package/dist/enums/row-level-security-role.enum.d.ts +7 -0
  2. package/dist/enums/row-level-security-role.enum.js +12 -0
  3. package/dist/enums/row-level-security-role.enum.js.map +1 -0
  4. package/dist/index.d.ts +3 -2
  5. package/dist/index.js +3 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.spec.js +6 -14
  8. package/dist/index.spec.js.map +1 -1
  9. package/dist/interfaces/index.d.ts +0 -1
  10. package/dist/interfaces/index.js +0 -1
  11. package/dist/interfaces/index.js.map +1 -1
  12. package/dist/interfaces/policy-options.interface.d.ts +2 -2
  13. package/dist/interfaces/policy-sql-options.interface.d.ts +2 -2
  14. package/dist/row-level-security-driver.d.ts +15 -0
  15. package/dist/row-level-security-driver.js +136 -0
  16. package/dist/row-level-security-driver.js.map +1 -0
  17. package/dist/row-level-security-driver.spec.js +267 -0
  18. package/dist/row-level-security-driver.spec.js.map +1 -0
  19. package/dist/row-level-security-migration-generator.d.ts +1 -0
  20. package/dist/row-level-security-migration-generator.js +39 -8
  21. package/dist/row-level-security-migration-generator.js.map +1 -1
  22. package/dist/row-level-security-migration-generator.spec.js +181 -10
  23. package/dist/row-level-security-migration-generator.spec.js.map +1 -1
  24. package/dist/row-level-security-migration.d.ts +2 -4
  25. package/dist/row-level-security-migration.js +9 -7
  26. package/dist/row-level-security-migration.js.map +1 -1
  27. package/dist/row-level-security-migration.spec.js +7 -16
  28. package/dist/row-level-security-migration.spec.js.map +1 -1
  29. package/dist/row-level-security.d.ts +29 -0
  30. package/dist/row-level-security.js +69 -0
  31. package/dist/row-level-security.js.map +1 -0
  32. package/dist/row-level-security.spec.js +52 -0
  33. package/dist/row-level-security.spec.js.map +1 -0
  34. package/dist/tsconfig.build.tsbuildinfo +1 -1
  35. package/dist/utils/create-policy-bootstrap-sql-statements.d.ts +1 -1
  36. package/dist/utils/create-policy-bootstrap-sql-statements.js +1 -7
  37. package/dist/utils/create-policy-bootstrap-sql-statements.js.map +1 -1
  38. package/dist/utils/create-policy-privilege-down-sql-statements.d.ts +8 -0
  39. package/dist/utils/create-policy-privilege-down-sql-statements.js +93 -0
  40. package/dist/utils/create-policy-privilege-down-sql-statements.js.map +1 -0
  41. package/dist/utils/create-policy-role-sql-statements.d.ts +6 -0
  42. package/dist/utils/create-policy-role-sql-statements.js +48 -0
  43. package/dist/utils/create-policy-role-sql-statements.js.map +1 -0
  44. package/dist/utils/create-policy-up-sql-statements.js +8 -2
  45. package/dist/utils/create-policy-up-sql-statements.js.map +1 -1
  46. package/dist/utils/create-row-level-security-transaction-setup.d.ts +20 -0
  47. package/dist/utils/create-row-level-security-transaction-setup.js +53 -0
  48. package/dist/utils/create-row-level-security-transaction-setup.js.map +1 -0
  49. package/dist/utils/index.d.ts +2 -3
  50. package/dist/utils/index.js +2 -3
  51. package/dist/utils/index.js.map +1 -1
  52. package/dist/utils/policy-migration-sql.spec.js +125 -7
  53. package/dist/utils/policy-migration-sql.spec.js.map +1 -1
  54. package/package.json +3 -3
  55. package/dist/interfaces/row-level-security-options.interface.d.ts +0 -18
  56. package/dist/interfaces/row-level-security-options.interface.js +0 -3
  57. package/dist/interfaces/row-level-security-options.interface.js.map +0 -1
  58. package/dist/row-level-security-context.d.ts +0 -14
  59. package/dist/row-level-security-context.js +0 -38
  60. package/dist/row-level-security-context.js.map +0 -1
  61. package/dist/row-level-security-context.spec.js +0 -29
  62. package/dist/row-level-security-context.spec.js.map +0 -1
  63. package/dist/row-level-security-entity-manager.d.ts +0 -22
  64. package/dist/row-level-security-entity-manager.js +0 -135
  65. package/dist/row-level-security-entity-manager.js.map +0 -1
  66. package/dist/row-level-security-entity-manager.spec.js +0 -200
  67. package/dist/row-level-security-entity-manager.spec.js.map +0 -1
  68. package/dist/utils/default-row-level-security-options.d.ts +0 -3
  69. package/dist/utils/default-row-level-security-options.js +0 -9
  70. package/dist/utils/default-row-level-security-options.js.map +0 -1
  71. package/dist/utils/get-row-level-security-options.d.ts +0 -8
  72. package/dist/utils/get-row-level-security-options.js +0 -9
  73. package/dist/utils/get-row-level-security-options.js.map +0 -1
  74. package/dist/utils/row-level-security-options-state.d.ts +0 -4
  75. package/dist/utils/row-level-security-options-state.js +0 -8
  76. package/dist/utils/row-level-security-options-state.js.map +0 -1
  77. package/dist/utils/set-row-level-security-options.d.ts +0 -3
  78. package/dist/utils/set-row-level-security-options.js +0 -13
  79. package/dist/utils/set-row-level-security-options.js.map +0 -1
  80. /package/dist/{row-level-security-context.spec.d.ts → row-level-security-driver.spec.d.ts} +0 -0
  81. /package/dist/{row-level-security-entity-manager.spec.d.ts → row-level-security.spec.d.ts} +0 -0
@@ -0,0 +1,29 @@
1
+ import { RowLevelSecurityContextValue, SnakeCase } from "./utils/row-level-security-context-builder.types";
2
+ /** Request-scoped row-level security execution mode. */
3
+ export declare enum RowLevelSecurityMode {
4
+ /** Apply RLS only when a role or context value is present. */
5
+ AUTO = "auto",
6
+ /** Always apply RLS while request context is active. */
7
+ ENABLED = "enabled",
8
+ /** Never apply RLS, even when role or context values are present. */
9
+ DISABLED = "disabled"
10
+ }
11
+ /** Request-scoped row-level security mode, role, and context helpers. */
12
+ export declare class RowLevelSecurity {
13
+ /** Stores the row-level security mode for the current request context. */
14
+ static setMode(mode: RowLevelSecurityMode): void;
15
+ /** Reads the request-scoped row-level security mode. */
16
+ static getMode(): RowLevelSecurityMode;
17
+ /** Stores the database role that should be applied to the next RLS query. */
18
+ static setRole(role: string): void;
19
+ /** Reads the request-scoped database role, if one is active. */
20
+ static getRole(): string | undefined;
21
+ /** Stores a context value that will be converted to a PostgreSQL setting. */
22
+ static setContext<S extends string>(key: SnakeCase<S>, value: RowLevelSecurityContextValue): void;
23
+ /** Reads a request-scoped context value by key. */
24
+ static getContext<S extends string>(key: SnakeCase<S>): RowLevelSecurityContextValue;
25
+ /** Returns all request-scoped context entries for RLS transaction setup. */
26
+ static entries(): [string, RowLevelSecurityContextValue][];
27
+ /** Clears request-scoped RLS mode, role, and context values. */
28
+ static clear(): void;
29
+ }
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RowLevelSecurity = exports.RowLevelSecurityMode = void 0;
4
+ const request_context_1 = require("@nest-boot/request-context");
5
+ const ROW_LEVEL_SECURITY_CONTEXT = Symbol("ROW_LEVEL_SECURITY_CONTEXT");
6
+ const ROW_LEVEL_SECURITY_MODE = Symbol("ROW_LEVEL_SECURITY_MODE");
7
+ const ROW_LEVEL_SECURITY_ROLE = Symbol("ROW_LEVEL_SECURITY_ROLE");
8
+ /** Request-scoped row-level security execution mode. */
9
+ var RowLevelSecurityMode;
10
+ (function (RowLevelSecurityMode) {
11
+ /** Apply RLS only when a role or context value is present. */
12
+ RowLevelSecurityMode["AUTO"] = "auto";
13
+ /** Always apply RLS while request context is active. */
14
+ RowLevelSecurityMode["ENABLED"] = "enabled";
15
+ /** Never apply RLS, even when role or context values are present. */
16
+ RowLevelSecurityMode["DISABLED"] = "disabled";
17
+ })(RowLevelSecurityMode || (exports.RowLevelSecurityMode = RowLevelSecurityMode = {}));
18
+ /** Request-scoped row-level security mode, role, and context helpers. */
19
+ class RowLevelSecurity {
20
+ /** Stores the row-level security mode for the current request context. */
21
+ static setMode(mode) {
22
+ request_context_1.RequestContext.set(ROW_LEVEL_SECURITY_MODE, mode);
23
+ }
24
+ /** Reads the request-scoped row-level security mode. */
25
+ static getMode() {
26
+ return request_context_1.RequestContext.isActive()
27
+ ? (request_context_1.RequestContext.get(ROW_LEVEL_SECURITY_MODE) ??
28
+ RowLevelSecurityMode.AUTO)
29
+ : RowLevelSecurityMode.AUTO;
30
+ }
31
+ /** Stores the database role that should be applied to the next RLS query. */
32
+ static setRole(role) {
33
+ request_context_1.RequestContext.set(ROW_LEVEL_SECURITY_ROLE, role);
34
+ }
35
+ /** Reads the request-scoped database role, if one is active. */
36
+ static getRole() {
37
+ return request_context_1.RequestContext.isActive()
38
+ ? request_context_1.RequestContext.get(ROW_LEVEL_SECURITY_ROLE)
39
+ : undefined;
40
+ }
41
+ /** Stores a context value that will be converted to a PostgreSQL setting. */
42
+ static setContext(key, value) {
43
+ const context = request_context_1.RequestContext.getOrSet(ROW_LEVEL_SECURITY_CONTEXT, new Map());
44
+ context.set(key, value);
45
+ }
46
+ /** Reads a request-scoped context value by key. */
47
+ static getContext(key) {
48
+ return request_context_1.RequestContext.isActive()
49
+ ? request_context_1.RequestContext.get(ROW_LEVEL_SECURITY_CONTEXT)?.get(key)
50
+ : undefined;
51
+ }
52
+ /** Returns all request-scoped context entries for RLS transaction setup. */
53
+ static entries() {
54
+ return request_context_1.RequestContext.isActive()
55
+ ? Array.from(request_context_1.RequestContext.get(ROW_LEVEL_SECURITY_CONTEXT) ?? [])
56
+ : [];
57
+ }
58
+ /** Clears request-scoped RLS mode, role, and context values. */
59
+ static clear() {
60
+ if (!request_context_1.RequestContext.isActive()) {
61
+ return;
62
+ }
63
+ request_context_1.RequestContext.set(ROW_LEVEL_SECURITY_MODE, RowLevelSecurityMode.AUTO);
64
+ request_context_1.RequestContext.set(ROW_LEVEL_SECURITY_ROLE, undefined);
65
+ request_context_1.RequestContext.set(ROW_LEVEL_SECURITY_CONTEXT, new Map());
66
+ }
67
+ }
68
+ exports.RowLevelSecurity = RowLevelSecurity;
69
+ //# sourceMappingURL=row-level-security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row-level-security.js","sourceRoot":"","sources":["../src/row-level-security.ts"],"names":[],"mappings":";;;AAAA,gEAA4D;AAS5D,MAAM,0BAA0B,GAAG,MAAM,CAAC,4BAA4B,CAAC,CAAC;AACxE,MAAM,uBAAuB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAClE,MAAM,uBAAuB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAElE,wDAAwD;AACxD,IAAY,oBAOX;AAPD,WAAY,oBAAoB;IAC9B,8DAA8D;IAC9D,qCAAa,CAAA;IACb,wDAAwD;IACxD,2CAAmB,CAAA;IACnB,qEAAqE;IACrE,6CAAqB,CAAA;AACvB,CAAC,EAPW,oBAAoB,oCAApB,oBAAoB,QAO/B;AAED,yEAAyE;AACzE,MAAa,gBAAgB;IAC3B,0EAA0E;IAC1E,MAAM,CAAC,OAAO,CAAC,IAA0B;QACvC,gCAAc,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,wDAAwD;IACxD,MAAM,CAAC,OAAO;QACZ,OAAO,gCAAc,CAAC,QAAQ,EAAE;YAC9B,CAAC,CAAC,CAAC,gCAAc,CAAC,GAAG,CAAuB,uBAAuB,CAAC;gBAChE,oBAAoB,CAAC,IAAI,CAAC;YAC9B,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC;IAChC,CAAC;IAED,6EAA6E;IAC7E,MAAM,CAAC,OAAO,CAAC,IAAY;QACzB,gCAAc,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,gEAAgE;IAChE,MAAM,CAAC,OAAO;QACZ,OAAO,gCAAc,CAAC,QAAQ,EAAE;YAC9B,CAAC,CAAC,gCAAc,CAAC,GAAG,CAAS,uBAAuB,CAAC;YACrD,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED,6EAA6E;IAC7E,MAAM,CAAC,UAAU,CACf,GAAiB,EACjB,KAAmC;QAEnC,MAAM,OAAO,GAAG,gCAAc,CAAC,QAAQ,CACrC,0BAA0B,EAC1B,IAAI,GAAG,EAAE,CACV,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,mDAAmD;IACnD,MAAM,CAAC,UAAU,CACf,GAAiB;QAEjB,OAAO,gCAAc,CAAC,QAAQ,EAAE;YAC9B,CAAC,CAAC,gCAAc,CAAC,GAAG,CAChB,0BAA0B,CAC3B,EAAE,GAAG,CAAC,GAAG,CAAC;YACb,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED,4EAA4E;IAC5E,MAAM,CAAC,OAAO;QACZ,OAAO,gCAAc,CAAC,QAAQ,EAAE;YAC9B,CAAC,CAAC,KAAK,CAAC,IAAI,CACR,gCAAc,CAAC,GAAG,CAChB,0BAA0B,CAC3B,IAAI,EAAE,CACR;YACH,CAAC,CAAC,EAAE,CAAC;IACT,CAAC;IAED,gEAAgE;IAChE,MAAM,CAAC,KAAK;QACV,IAAI,CAAC,gCAAc,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,gCAAc,CAAC,GAAG,CAAC,uBAAuB,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACvE,gCAAc,CAAC,GAAG,CAAqB,uBAAuB,EAAE,SAAS,CAAC,CAAC;QAC3E,gCAAc,CAAC,GAAG,CAChB,0BAA0B,EAC1B,IAAI,GAAG,EAAE,CACV,CAAC;IACJ,CAAC;CACF;AA1ED,4CA0EC"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const request_context_1 = require("@nest-boot/request-context");
4
+ const row_level_security_1 = require("./row-level-security");
5
+ describe("RowLevelSecurity", () => {
6
+ it("stores the database role in RequestContext", async () => {
7
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "http" }), () => {
8
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
9
+ expect(row_level_security_1.RowLevelSecurity.getRole()).toBe("authenticated");
10
+ });
11
+ });
12
+ it("stores policy context values in RequestContext", async () => {
13
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "http" }), () => {
14
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", "42");
15
+ row_level_security_1.RowLevelSecurity.setContext("user_id", 7);
16
+ expect(row_level_security_1.RowLevelSecurity.getContext("tenant_id")).toBe("42");
17
+ expect(row_level_security_1.RowLevelSecurity.entries()).toEqual([
18
+ ["tenant_id", "42"],
19
+ ["user_id", 7],
20
+ ]);
21
+ });
22
+ });
23
+ it("defaults to auto mode and stores mode in RequestContext", async () => {
24
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.AUTO);
25
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "http" }), () => {
26
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.AUTO);
27
+ row_level_security_1.RowLevelSecurity.setMode(row_level_security_1.RowLevelSecurityMode.DISABLED);
28
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.DISABLED);
29
+ row_level_security_1.RowLevelSecurity.setMode(row_level_security_1.RowLevelSecurityMode.ENABLED);
30
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.ENABLED);
31
+ });
32
+ });
33
+ it("clears mode, role, and context values", async () => {
34
+ await request_context_1.RequestContext.run(new request_context_1.RequestContext({ type: "http" }), () => {
35
+ row_level_security_1.RowLevelSecurity.setMode(row_level_security_1.RowLevelSecurityMode.ENABLED);
36
+ row_level_security_1.RowLevelSecurity.setRole("authenticated");
37
+ row_level_security_1.RowLevelSecurity.setContext("tenant_id", "42");
38
+ row_level_security_1.RowLevelSecurity.clear();
39
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.AUTO);
40
+ expect(row_level_security_1.RowLevelSecurity.getRole()).toBeUndefined();
41
+ expect(row_level_security_1.RowLevelSecurity.getContext("tenant_id")).toBeUndefined();
42
+ expect(row_level_security_1.RowLevelSecurity.entries()).toEqual([]);
43
+ });
44
+ });
45
+ it("returns empty values when RequestContext is inactive", () => {
46
+ expect(row_level_security_1.RowLevelSecurity.getMode()).toBe(row_level_security_1.RowLevelSecurityMode.AUTO);
47
+ expect(row_level_security_1.RowLevelSecurity.getRole()).toBeUndefined();
48
+ expect(row_level_security_1.RowLevelSecurity.getContext("tenant_id")).toBeUndefined();
49
+ expect(row_level_security_1.RowLevelSecurity.entries()).toEqual([]);
50
+ });
51
+ });
52
+ //# sourceMappingURL=row-level-security.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"row-level-security.spec.js","sourceRoot":"","sources":["../src/row-level-security.spec.ts"],"names":[],"mappings":";;AAAA,gEAA4D;AAE5D,6DAA8E;AAE9E,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,gCAAc,CAAC,GAAG,CAAC,IAAI,gCAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE;YAClE,qCAAgB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YAE1C,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,gCAAc,CAAC,GAAG,CAAC,IAAI,gCAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE;YAClE,qCAAgB,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YAC/C,qCAAgB,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;YAE1C,MAAM,CAAC,qCAAgB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5D,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC;gBACzC,CAAC,WAAW,EAAE,IAAI,CAAC;gBACnB,CAAC,SAAS,EAAE,CAAC,CAAC;aACf,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,yCAAoB,CAAC,IAAI,CAAC,CAAC;QAEnE,MAAM,gCAAc,CAAC,GAAG,CAAC,IAAI,gCAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE;YAClE,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,yCAAoB,CAAC,IAAI,CAAC,CAAC;YAEnE,qCAAgB,CAAC,OAAO,CAAC,yCAAoB,CAAC,QAAQ,CAAC,CAAC;YACxD,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,yCAAoB,CAAC,QAAQ,CAAC,CAAC;YAEvE,qCAAgB,CAAC,OAAO,CAAC,yCAAoB,CAAC,OAAO,CAAC,CAAC;YACvD,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,yCAAoB,CAAC,OAAO,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,gCAAc,CAAC,GAAG,CAAC,IAAI,gCAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE;YAClE,qCAAgB,CAAC,OAAO,CAAC,yCAAoB,CAAC,OAAO,CAAC,CAAC;YACvD,qCAAgB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YAC1C,qCAAgB,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YAE/C,qCAAgB,CAAC,KAAK,EAAE,CAAC;YAEzB,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,yCAAoB,CAAC,IAAI,CAAC,CAAC;YACnE,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC;YACnD,MAAM,CAAC,qCAAgB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;YACjE,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,yCAAoB,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC;QACnD,MAAM,CAAC,qCAAgB,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACjE,MAAM,CAAC,qCAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}