@prisma-next/adapter-postgres 0.12.0 → 0.13.0-dev.10

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 CHANGED
@@ -20,7 +20,7 @@ Provide PostgreSQL-specific adapter implementation, codecs, and capabilities. En
20
20
 
21
21
  - **Adapter Implementation**: Implement `Adapter` SPI for PostgreSQL
22
22
  - Lower SQL ASTs to PostgreSQL dialect SQL
23
- - Render `includeMany` as `LEFT JOIN LATERAL` with `json_agg` for nested array includes
23
+ - Render JSON aggregation (`json_agg`, `json_build_object`) and scalar subqueries
24
24
  - Advertise PostgreSQL capabilities (`lateral`, `jsonAgg`)
25
25
  - Normalize PostgreSQL EXPLAIN output
26
26
  - Map PostgreSQL errors to `RuntimeError` envelope
@@ -89,8 +89,8 @@ flowchart TD
89
89
  **Adapter (`adapter.ts`)**
90
90
  - Main adapter implementation
91
91
  - Lowers SQL ASTs to PostgreSQL SQL
92
- - Renders joins (INNER, LEFT, RIGHT, FULL) with ON conditions
93
- - Renders `includeMany` as `LEFT JOIN LATERAL` with `json_agg` for nested array includes
92
+ - Renders joins (INNER, LEFT, RIGHT, FULL, LATERAL) with ON conditions
93
+ - Renders JSON aggregation (`json_agg`, `json_build_object`) and scalar subqueries
94
94
  - Renders DML operations (INSERT, UPDATE, DELETE) with RETURNING clauses
95
95
  - Advertises PostgreSQL capabilities (`lateral`, `jsonAgg`, `returning`)
96
96
  - Maps PostgreSQL errors to `RuntimeError`
@@ -191,8 +191,8 @@ The adapter declares the following PostgreSQL capabilities:
191
191
 
192
192
  - **`orderBy: true`** - Supports ORDER BY clauses
193
193
  - **`limit: true`** - Supports LIMIT clauses
194
- - **`lateral: true`** - Supports LATERAL joins for `includeMany` nested array includes
195
- - **`jsonAgg: true`** - Supports JSON aggregation functions (`json_agg`) for `includeMany`
194
+ - **`lateral: true`** - Supports LATERAL joins
195
+ - **`jsonAgg: true`** - Supports JSON aggregation functions (`json_agg`)
196
196
  - **`returning: true`** - Supports RETURNING clauses for DML operations (INSERT, UPDATE, DELETE)
197
197
  - **`sql.enums: true`** - Supports contract-defined enum storage types
198
198
 
@@ -205,29 +205,22 @@ The capabilities on the descriptor must match the capabilities in code. If they
205
205
 
206
206
  See `docs/reference/capabilities.md` and `docs/architecture docs/subsystems/5. Adapters & Targets.md` for details.
207
207
 
208
- ## includeMany Support
208
+ ## JSON Aggregation
209
209
 
210
- The adapter supports `includeMany` for nested array includes using PostgreSQL's `LATERAL` joins and `json_agg`:
210
+ The renderer lowers JSON-aggregation AST nodes to PostgreSQL's `json_agg`:
211
211
 
212
- **Lowering Strategy:**
213
- - Renders `includeMany` as `LEFT JOIN LATERAL` with a subquery that uses `json_agg(json_build_object(...))` to aggregate child rows into a JSON array
214
- - The ON condition from the include is moved into the WHERE clause of the lateral subquery
215
- - When both `ORDER BY` and `LIMIT` are present, wraps the query in an inner SELECT that projects individual columns with aliases, then uses `json_agg(row_to_json(sub.*))` on the result
216
- - Uses different aliases for the table (`{alias}_lateral`) and column (`{alias}`) to avoid ambiguity
217
-
218
- **Capabilities Required:**
219
- - `lateral: true` - Enables LATERAL join support
220
- - `jsonAgg: true` - Enables `json_agg` function support
212
+ - `json_agg(json_build_object(...))` aggregates a row set into a JSON array of objects
213
+ - A scalar subquery (`SubqueryExpr`) in the SELECT list correlates against the outer row through its WHERE clause
214
+ - When the subquery carries an inner `ORDER BY` and `LIMIT`, its rows are wrapped in an inner SELECT, then aggregated with `json_agg(row_to_json(sub.*))`
221
215
 
222
216
  **Example SQL Output:**
223
217
  ```sql
224
- SELECT "user"."id" AS "id", "posts_lateral"."posts" AS "posts"
225
- FROM "user"
226
- LEFT JOIN LATERAL (
218
+ SELECT "user"."id" AS "id", (
227
219
  SELECT json_agg(json_build_object('id', "post"."id", 'title', "post"."title")) AS "posts"
228
220
  FROM "post"
229
221
  WHERE "user"."id" = "post"."userId"
230
- ) AS "posts_lateral" ON true
222
+ ) AS "posts"
223
+ FROM "user"
231
224
  ```
232
225
 
233
226
  ## DML Operations with RETURNING
@@ -1,6 +1,6 @@
1
- import { n as createPostgresBuiltinCodecLookup, t as renderLoweredSql } from "./sql-renderer-DlZhVI9B.mjs";
1
+ import { i as createPostgresBuiltinCodecLookup, n as renderLoweredSql, r as renderLoweredDdl, t as PostgresControlAdapter } from "./control-adapter-Xq5__09s.mjs";
2
2
  import { APP_SPACE_ID } from "@prisma-next/framework-components/control";
3
- import { parseContractMarkerRow } from "@prisma-next/sql-runtime";
3
+ import { isDdlNode } from "@prisma-next/sql-relational-core/ast";
4
4
  //#region src/core/adapter.ts
5
5
  const defaultCapabilities = Object.freeze({
6
6
  postgres: {
@@ -25,14 +25,23 @@ var PostgresAdapterImpl = class {
25
25
  codecLookup;
26
26
  constructor(options) {
27
27
  this.codecLookup = options?.codecLookup ?? createPostgresBuiltinCodecLookup();
28
+ const controlAdapter = new PostgresControlAdapter(this.codecLookup);
28
29
  this.profile = Object.freeze({
29
30
  id: options?.profileId ?? "postgres/default@1",
30
31
  target: "postgres",
31
32
  capabilities: defaultCapabilities,
32
- readMarker: (queryable) => readPostgresMarker(queryable)
33
+ readMarker: (queryable) => controlAdapter.readMarkerDiscriminated({
34
+ familyId: "sql",
35
+ targetId: "postgres",
36
+ query: async (sql, params) => {
37
+ return { rows: [...(await queryable.query(sql, params)).rows] };
38
+ },
39
+ close: async () => {}
40
+ }, APP_SPACE_ID)
33
41
  });
34
42
  }
35
43
  lower(ast, context) {
44
+ if (isDdlNode(ast)) return renderLoweredDdl(ast);
36
45
  return renderLoweredSql(ast, context.contract, this.codecLookup);
37
46
  }
38
47
  };
@@ -47,19 +56,10 @@ const postgresRawCodecInferer = { inferCodec(value) {
47
56
  }
48
57
  throw new Error("unsupported JS value type for raw-SQL interpolation: wrap this value in `param(...)` with an explicit codec");
49
58
  } };
50
- async function readPostgresMarker(queryable) {
51
- if ((await queryable.query("select 1 from information_schema.tables where table_schema = $1 and table_name = $2", ["prisma_contract", "marker"])).rows.length === 0) return { kind: "no-table" };
52
- const row = (await queryable.query("select core_hash, profile_hash, contract_json, canonical_version, updated_at, app_tag, meta, invariants from prisma_contract.marker where space = $1", [APP_SPACE_ID])).rows[0];
53
- if (!row) return { kind: "absent" };
54
- return {
55
- kind: "present",
56
- record: parseContractMarkerRow(row)
57
- };
58
- }
59
59
  function createPostgresAdapter(options) {
60
60
  return Object.freeze(new PostgresAdapterImpl(options));
61
61
  }
62
62
  //#endregion
63
63
  export { postgresRawCodecInferer as n, createPostgresAdapter as t };
64
64
 
65
- //# sourceMappingURL=adapter-H8BiuXdq.mjs.map
65
+ //# sourceMappingURL=adapter-u3NV_jRl.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-u3NV_jRl.mjs","names":[],"sources":["../src/core/adapter.ts"],"sourcesContent":["import type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport { APP_SPACE_ID } from '@prisma-next/framework-components/control';\nimport type {\n Adapter,\n AdapterProfile,\n AnyQueryAst,\n LowererContext,\n RawSqlLiteral,\n SqlQueryable,\n} from '@prisma-next/sql-relational-core/ast';\nimport { isDdlNode } from '@prisma-next/sql-relational-core/ast';\nimport type { RawCodecInferer } from '@prisma-next/sql-relational-core/expression';\nimport type { PostgresDdlNode } from '@prisma-next/target-postgres/ddl';\nimport { createPostgresBuiltinCodecLookup } from './codec-lookup';\nimport { PostgresControlAdapter } from './control-adapter';\nimport { renderLoweredDdl } from './ddl-renderer';\nimport { renderLoweredSql } from './sql-renderer';\nimport type { PostgresAdapterOptions, PostgresContract, PostgresLoweredStatement } from './types';\n\nconst defaultCapabilities = Object.freeze({\n postgres: {\n orderBy: true,\n limit: true,\n lateral: true,\n jsonAgg: true,\n returning: true,\n distinctOn: true,\n },\n sql: {\n enums: true,\n returning: true,\n defaultInInsert: true,\n lateral: true,\n },\n});\n\nclass PostgresAdapterImpl\n implements Adapter<AnyQueryAst, PostgresContract, PostgresLoweredStatement>\n{\n // These fields make the adapter instance structurally compatible with RuntimeAdapterInstance<'sql', 'postgres'> without introducing a runtime-plane dependency.\n readonly familyId = 'sql' as const;\n readonly targetId = 'postgres' as const;\n\n readonly profile: AdapterProfile<'postgres'>;\n private readonly codecLookup: CodecLookup;\n\n constructor(options?: PostgresAdapterOptions) {\n this.codecLookup = options?.codecLookup ?? createPostgresBuiltinCodecLookup();\n const controlAdapter = new PostgresControlAdapter(this.codecLookup);\n this.profile = Object.freeze({\n id: options?.profileId ?? 'postgres/default@1',\n target: 'postgres',\n capabilities: defaultCapabilities,\n readMarker: (queryable: SqlQueryable) =>\n controlAdapter.readMarkerDiscriminated(\n {\n familyId: 'sql',\n targetId: 'postgres',\n query: async <Row = Record<string, unknown>>(\n sql: string,\n params?: readonly unknown[],\n ) => {\n const result = await queryable.query<Row>(sql, params);\n return { rows: [...result.rows] };\n },\n close: async () => {},\n },\n APP_SPACE_ID,\n ),\n });\n }\n\n lower(\n ast: AnyQueryAst | PostgresDdlNode,\n context: LowererContext<PostgresContract>,\n ): PostgresLoweredStatement {\n if (isDdlNode(ast)) {\n return renderLoweredDdl(ast);\n }\n return renderLoweredSql(ast, context.contract, this.codecLookup);\n }\n}\n\n/** Codec-id lookup for bare-literal interpolations used by `fns.raw` on a postgres client. Contributed as the descriptor's static `rawCodecInferer` slot. */\nexport const postgresRawCodecInferer: RawCodecInferer = {\n inferCodec(value: RawSqlLiteral): string {\n switch (typeof value) {\n case 'number':\n return Number.isSafeInteger(value) && value % 1 === 0 ? 'pg/int4' : 'pg/float8';\n case 'bigint':\n return 'pg/int8';\n case 'string':\n return 'pg/text';\n case 'boolean':\n return 'pg/bool';\n case 'object':\n if (value instanceof Uint8Array) return 'pg/bytea';\n }\n throw new Error(\n 'unsupported JS value type for raw-SQL interpolation: wrap this value in `param(...)` with an explicit codec',\n );\n },\n};\n\nexport function createPostgresAdapter(options?: PostgresAdapterOptions) {\n return Object.freeze(new PostgresAdapterImpl(options));\n}\n"],"mappings":";;;;AAmBA,MAAM,sBAAsB,OAAO,OAAO;CACxC,UAAU;EACR,SAAS;EACT,OAAO;EACP,SAAS;EACT,SAAS;EACT,WAAW;EACX,YAAY;CACd;CACA,KAAK;EACH,OAAO;EACP,WAAW;EACX,iBAAiB;EACjB,SAAS;CACX;AACF,CAAC;AAED,IAAM,sBAAN,MAEA;CAEE,WAAoB;CACpB,WAAoB;CAEpB;CACA;CAEA,YAAY,SAAkC;EAC5C,KAAK,cAAc,SAAS,eAAe,iCAAiC;EAC5E,MAAM,iBAAiB,IAAI,uBAAuB,KAAK,WAAW;EAClE,KAAK,UAAU,OAAO,OAAO;GAC3B,IAAI,SAAS,aAAa;GAC1B,QAAQ;GACR,cAAc;GACd,aAAa,cACX,eAAe,wBACb;IACE,UAAU;IACV,UAAU;IACV,OAAO,OACL,KACA,WACG;KAEH,OAAO,EAAE,MAAM,CAAC,IAAG,MADE,UAAU,MAAW,KAAK,MAAM,EAAA,CAC3B,IAAI,EAAE;IAClC;IACA,OAAO,YAAY,CAAC;GACtB,GACA,YACF;EACJ,CAAC;CACH;CAEA,MACE,KACA,SAC0B;EAC1B,IAAI,UAAU,GAAG,GACf,OAAO,iBAAiB,GAAG;EAE7B,OAAO,iBAAiB,KAAK,QAAQ,UAAU,KAAK,WAAW;CACjE;AACF;;AAGA,MAAa,0BAA2C,EACtD,WAAW,OAA8B;CACvC,QAAQ,OAAO,OAAf;EACE,KAAK,UACH,OAAO,OAAO,cAAc,KAAK,KAAK,QAAQ,MAAM,IAAI,YAAY;EACtE,KAAK,UACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,KAAK,WACH,OAAO;EACT,KAAK,UACH,IAAI,iBAAiB,YAAY,OAAO;CAC5C;CACA,MAAM,IAAI,MACR,6GACF;AACF,EACF;AAEA,SAAgB,sBAAsB,SAAkC;CACtE,OAAO,OAAO,OAAO,IAAI,oBAAoB,OAAO,CAAC;AACvD"}
@@ -1,6 +1,7 @@
1
- import { c as PostgresContract, l as PostgresLoweredStatement, s as PostgresAdapterOptions } from "./types-B1eiuBHQ.mjs";
1
+ import { c as PostgresContract, l as PostgresLoweredStatement, s as PostgresAdapterOptions } from "./types-Dv7M8jx8.mjs";
2
2
  import { Adapter, AdapterProfile, AnyQueryAst, LowererContext } from "@prisma-next/sql-relational-core/ast";
3
3
  import { RawCodecInferer } from "@prisma-next/sql-relational-core/expression";
4
+ import { PostgresDdlNode } from "@prisma-next/target-postgres/ddl";
4
5
 
5
6
  //#region src/core/adapter.d.ts
6
7
  declare class PostgresAdapterImpl implements Adapter<AnyQueryAst, PostgresContract, PostgresLoweredStatement> {
@@ -9,7 +10,7 @@ declare class PostgresAdapterImpl implements Adapter<AnyQueryAst, PostgresContra
9
10
  readonly profile: AdapterProfile<'postgres'>;
10
11
  private readonly codecLookup;
11
12
  constructor(options?: PostgresAdapterOptions);
12
- lower(ast: AnyQueryAst, context: LowererContext<PostgresContract>): PostgresLoweredStatement;
13
+ lower(ast: AnyQueryAst | PostgresDdlNode, context: LowererContext<PostgresContract>): PostgresLoweredStatement;
13
14
  }
14
15
  /** Codec-id lookup for bare-literal interpolations used by `fns.raw` on a postgres client. Contributed as the descriptor's static `rawCodecInferer` slot. */
15
16
  declare const postgresRawCodecInferer: RawCodecInferer;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.mts","names":[],"sources":["../src/core/adapter.ts"],"mappings":";;;;;cAkCM,mBAAA,YACO,OAAA,CAAQ,WAAA,EAAa,gBAAA,EAAkB,wBAAA;EAAA,SAGzC,QAAA;EAAA,SACA,QAAA;EAAA,SAEA,OAAA,EAAS,cAAA;EAAA,iBACD,WAAA;cAEL,OAAA,GAAU,sBAAA;EAUtB,KAAA,CAAM,GAAA,EAAK,WAAA,EAAa,OAAA,EAAS,cAAA,CAAe,gBAAA,IAAoB,wBAAA;AAAA;;cAMzD,uBAAA,EAAyB,eAkBrC;AAAA,iBAuBe,qBAAA,CAAsB,OAAA,GAAU,sBAAA,GAAsB,QAAA,CAAA,mBAAA"}
1
+ {"version":3,"file":"adapter.d.mts","names":[],"sources":["../src/core/adapter.ts"],"mappings":";;;;;;cAoCM,mBAAA,YACO,OAAA,CAAQ,WAAA,EAAa,gBAAA,EAAkB,wBAAA;EAAA,SAGzC,QAAA;EAAA,SACA,QAAA;EAAA,SAEA,OAAA,EAAS,cAAA;EAAA,iBACD,WAAA;cAEL,OAAA,GAAU,sBAAA;EA0BtB,KAAA,CACE,GAAA,EAAK,WAAA,GAAc,eAAA,EACnB,OAAA,EAAS,cAAA,CAAe,gBAAA,IACvB,wBAAA;AAAA;;cASQ,uBAAA,EAAyB,eAkBrC;AAAA,iBAEe,qBAAA,CAAsB,OAAA,GAAU,sBAAA,GAAsB,QAAA,CAAA,mBAAA"}
package/dist/adapter.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as postgresRawCodecInferer, t as createPostgresAdapter } from "./adapter-H8BiuXdq.mjs";
1
+ import { n as postgresRawCodecInferer, t as createPostgresAdapter } from "./adapter-u3NV_jRl.mjs";
2
2
  export { createPostgresAdapter, postgresRawCodecInferer };
@@ -1 +1 @@
1
- {"version":3,"file":"column-types.d.mts","names":[],"sources":["../src/exports/column-types.ts"],"mappings":";;;;cAgCa,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,UAAA,CAAW,MAAA,WAAiB,oBAAoB;EAAA,SACrD,UAAA;IAAA,SAAuB,MAAA;EAAA;AAAA;AAAA,iBASlB,aAAA,CAAc,MAAA,WAAiB,oBAAoB;EAAA,SACxD,UAAA;IAAA,SAAuB,MAAA;EAAA;AAAA;AAAA,cASrB,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,cAE5B,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,cAE5B,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,cAE5B,YAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,cAE5B,YAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,aAAA,CACd,SAAA,UACA,KAAA,YACC,oBAAoB;EAAA,SACZ,UAAA;IAAA,SAAuB,SAAA;IAAA,SAA4B,KAAA;EAAA;AAAA;AAAA,cASjD,eAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,cAE5B,iBAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,UAAA,CAAW,SAAA,YAAqB,oBAAoB;EAAA,SACzD,UAAA;IAAA,SAAwB,SAAA;EAAA;AAAA;AAAA,iBASnB,YAAA,CAAa,SAAA,YAAqB,oBAAoB;EAAA,SAC3D,UAAA;IAAA,SAAwB,SAAA;EAAA;AAAA;AAAA,cAStB,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,SAAA,CAAU,MAAA,WAAiB,oBAAoB;EAAA,SACpD,UAAA;IAAA,SAAuB,MAAA;EAAA;AAAA;AAAA,iBASlB,YAAA,CAAa,MAAA,WAAiB,oBAAoB;EAAA,SACvD,UAAA;IAAA,SAAuB,MAAA;EAAA;AAAA;;;;;;cAcrB,WAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,cAAA,CAAe,SAAA,YAAqB,oBAAoB;EAAA,SAC7D,UAAA;IAAA,SAAwB,SAAA;EAAA;AAAA;;;AA7CS;AAS5C;;cAkDa,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;;;;cAK5B,WAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,QAAA,wCAAA,CACd,IAAA,UACA,MAAA,EAAQ,MAAA,GACP,gBAAgB;AAAA,iBAIH,UAAA,yBAAA,CACd,QAAA,EAAU,QAAA,EACV,UAAA,WACC,oBAAA;EAAA,SAAkC,OAAA,EAAS,QAAA;AAAA"}
1
+ {"version":3,"file":"column-types.d.mts","names":[],"sources":["../src/exports/column-types.ts"],"mappings":";;;;cAgCa,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,UAAA,CAAW,MAAA,WAAiB,oBAAoB;EAAA,SACrD,UAAA;IAAA,SAAuB,MAAA;EAAA;AAAA;AAAA,iBASlB,aAAA,CAAc,MAAA,WAAiB,oBAAoB;EAAA,SACxD,UAAA;IAAA,SAAuB,MAAA;EAAA;AAAA;AAAA,cASrB,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,cAE5B,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,cAE5B,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,cAE5B,YAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,cAE5B,YAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,aAAA,CACd,SAAA,UACA,KAAA,YACC,oBAAoB;EAAA,SACZ,UAAA;IAAA,SAAuB,SAAA;IAAA,SAA4B,KAAA;EAAA;AAAA;AAAA,cASjD,eAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,cAE5B,iBAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,UAAA,CAAW,SAAA,YAAqB,oBAAoB;EAAA,SACzD,UAAA;IAAA,SAAwB,SAAA;EAAA;AAAA;AAAA,iBASnB,YAAA,CAAa,SAAA,YAAqB,oBAAoB;EAAA,SAC3D,UAAA;IAAA,SAAwB,SAAA;EAAA;AAAA;AAAA,cAStB,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,SAAA,CAAU,MAAA,WAAiB,oBAAoB;EAAA,SACpD,UAAA;IAAA,SAAuB,MAAA;EAAA;AAAA;AAAA,iBASlB,YAAA,CAAa,MAAA,WAAiB,oBAAoB;EAAA,SACvD,UAAA;IAAA,SAAuB,MAAA;EAAA;AAAA;;;;;;cAcrB,WAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,cAAA,CAAe,SAAA,YAAqB,oBAAoB;EAAA,SAC7D,UAAA;IAAA,SAAwB,SAAA;EAAA;AAAA;;;AA7CS;AAS5C;;cAkDa,UAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;;;;cAK5B,WAAA;EAAA,SAG4B,OAAA;EAAA,SAAA,UAAA;AAAA;AAAA,iBAEzB,QAAA,yCACd,IAAA,UACA,MAAA,EAAQ,MAAA,GACP,gBAAgB;AAAA,iBAIH,UAAA,0BACd,QAAA,EAAU,QAAA,EACV,UAAA,WACC,oBAAA;EAAA,SAAkC,OAAA,EAAS,QAAA;AAAA"}