oakbun 0.5.0 → 0.5.2

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.
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  init_sqlite,
4
4
  sqlite_exports
5
- } from "./chunk-F3WAOTEN.js";
5
+ } from "./chunk-WFUUGGXJ.js";
6
6
  import {
7
7
  __esm,
8
8
  __export,
@@ -14,11 +14,20 @@ var postgres_exports = {};
14
14
  __export(postgres_exports, {
15
15
  PostgresAdapter: () => PostgresAdapter
16
16
  });
17
+ function toPositional(sql) {
18
+ let i = 0;
19
+ return sql.replace(/\?/g, () => `$${++i}`);
20
+ }
21
+ function unsafeCall(client, sql, params) {
22
+ const positional = toPositional(sql);
23
+ return params.length > 0 ? client.unsafe(positional, params) : client.unsafe(positional);
24
+ }
17
25
  var PostgresAdapter;
18
26
  var init_postgres = __esm({
19
27
  "src/adapter/postgres.ts"() {
20
28
  "use strict";
21
29
  PostgresAdapter = class {
30
+ dialect = "postgres";
22
31
  // Typed as any: Bun.SQL's instance type is not reliably exported across
23
32
  // bun-types versions and the class is a Bun global — no stable import path.
24
33
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -38,13 +47,13 @@ var init_postgres = __esm({
38
47
  }
39
48
  async query(sql, params = []) {
40
49
  const t0 = performance.now();
41
- const rows = await this.sql.unsafe(sql, params);
50
+ const rows = await unsafeCall(this.sql, sql, params);
42
51
  this.onQuery?.({ sql, params, durationMs: performance.now() - t0, type: "query" });
43
52
  return rows;
44
53
  }
45
54
  async execute(sql, params = []) {
46
55
  const t0 = performance.now();
47
- const result = await this.sql.unsafe(sql, params);
56
+ const result = await unsafeCall(this.sql, sql, params);
48
57
  this.onQuery?.({ sql, params, durationMs: performance.now() - t0, type: "execute" });
49
58
  const rowsAffected = typeof result?.count === "number" ? result.count : result?.length ?? 0;
50
59
  return { rowsAffected };
@@ -52,9 +61,10 @@ var init_postgres = __esm({
52
61
  async transaction(fn) {
53
62
  return this.sql.begin(async (tx) => {
54
63
  const txAdapter = {
55
- query: (s, p = []) => tx.unsafe(s, p),
64
+ dialect: "postgres",
65
+ query: (s, p = []) => unsafeCall(tx, s, p),
56
66
  execute: async (s, p = []) => {
57
- const r = await tx.unsafe(s, p);
67
+ const r = await unsafeCall(tx, s, p);
58
68
  const rowsAffected = typeof r?.count === "number" ? r.count : r?.length ?? 0;
59
69
  return { rowsAffected };
60
70
  },
@@ -84,6 +94,7 @@ var init_mysql = __esm({
84
94
  "src/adapter/mysql.ts"() {
85
95
  "use strict";
86
96
  MySQLAdapter = class {
97
+ dialect = "mysql";
87
98
  // Typed as any: Bun.SQL's instance type is not reliably exported across
88
99
  // bun-types versions and the class is a Bun global — no stable import path.
89
100
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -120,6 +131,7 @@ var init_mysql = __esm({
120
131
  async transaction(fn) {
121
132
  return this.sql.begin(async (tx) => {
122
133
  const txAdapter = {
134
+ dialect: "mysql",
123
135
  query: (s, p = []) => tx.unsafe(s, p),
124
136
  execute: async (s, p = []) => {
125
137
  const r = await tx.unsafe(s, p);
@@ -169,15 +181,18 @@ import { readdir, readFile } from "fs/promises";
169
181
  import { join } from "path";
170
182
 
171
183
  // src/db/migrations/tracker.ts
172
- var CREATE_TRACKING_TABLE = `
173
- CREATE TABLE IF NOT EXISTS "_veln_migrations" (
174
- "id" INTEGER PRIMARY KEY AUTOINCREMENT,
175
- "name" TEXT NOT NULL UNIQUE,
176
- "applied_at" TEXT NOT NULL
177
- )
178
- `;
184
+ function buildCreateTableSql(tableName, dialect) {
185
+ const pk = dialect === "sqlite" ? '"id" INTEGER PRIMARY KEY AUTOINCREMENT' : '"id" INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY';
186
+ return `
187
+ CREATE TABLE IF NOT EXISTS "${tableName}" (
188
+ ${pk},
189
+ "name" TEXT NOT NULL UNIQUE,
190
+ "applied_at" TEXT NOT NULL
191
+ )
192
+ `;
193
+ }
179
194
  async function ensureTable(adapter, tableName) {
180
- const sql = CREATE_TRACKING_TABLE.replace('"_veln_migrations"', `"${tableName}"`);
195
+ const sql = buildCreateTableSql(tableName, adapter.dialect);
181
196
  await adapter.execute(sql);
182
197
  }
183
198
  async function getApplied(adapter, tableName) {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  SQLiteAdapter,
4
4
  init_sqlite
5
- } from "./chunk-F3WAOTEN.js";
5
+ } from "./chunk-WFUUGGXJ.js";
6
6
  import "./chunk-FJSYS3BT.js";
7
7
  init_sqlite();
8
8
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oakbun",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Bun-native backend framework — No Magic, just code.",
5
5
  "author": "René (SchildW3rk)",
6
6
  "license": "MIT",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapter/postgres.ts"],"sourcesContent":["import type { VelnAdapter, BindingValue, ExecuteResult, QueryLogEntry } from './types'\n\nexport interface PostgresConfig {\n url: string\n max?: number\n idleTimeout?: number\n}\n\nexport class PostgresAdapter implements VelnAdapter {\n // Typed as any: Bun.SQL's instance type is not reliably exported across\n // bun-types versions and the class is a Bun global — no stable import path.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly sql: any\n onQuery?: (entry: QueryLogEntry) => void\n\n constructor(config: PostgresConfig) {\n if (config.max !== undefined && config.max < 1) {\n throw new Error(`PostgresAdapter: max connections must be at least 1, got ${config.max}`)\n }\n // Set DATABASE_URL if not already set — Bun.sql reads from environment\n if (!process.env['DATABASE_URL']) {\n process.env['DATABASE_URL'] = config.url\n }\n // @ts-ignore — Bun.SQL is a Bun global constructor, not in all bun-types versions\n this.sql = new Bun.SQL(config.url, {\n max: config.max ?? 10,\n idleTimeout: config.idleTimeout ?? 30,\n })\n }\n\n async query<T>(sql: string, params: BindingValue[] = []): Promise<T[]> {\n const t0 = performance.now()\n // .unsafe() accepts a raw SQL string + positional params array\n const rows = await this.sql.unsafe(sql, params) as T[]\n this.onQuery?.({ sql, params, durationMs: performance.now() - t0, type: 'query' })\n return rows\n }\n\n async execute(sql: string, params: BindingValue[] = []): Promise<ExecuteResult> {\n const t0 = performance.now()\n const result = await this.sql.unsafe(sql, params)\n this.onQuery?.({ sql, params, durationMs: performance.now() - t0, type: 'execute' })\n // Bun.SQL result exposes .count for rows affected on DML statements\n const rowsAffected = typeof result?.count === 'number' ? result.count : (result?.length ?? 0)\n return { rowsAffected } // lastInsertId not available without RETURNING clause\n }\n\n async transaction<T>(fn: (tx: VelnAdapter) => Promise<T>): Promise<T> {\n return this.sql.begin(async (tx: any) => {\n const txAdapter: VelnAdapter = {\n query: (s, p = []) => tx.unsafe(s, p),\n execute: async (s, p = []) => {\n const r = await tx.unsafe(s, p)\n const rowsAffected = typeof r?.count === 'number' ? r.count : (r?.length ?? 0)\n return { rowsAffected }\n },\n transaction: (innerFn) => innerFn(txAdapter), // nested: reuse same tx\n close: async () => {}, // no-op inside transaction\n }\n return fn(txAdapter)\n })\n }\n\n async close(): Promise<void> {\n await this.sql.end?.()\n }\n}\n"],"mappings":";;;;;;AAAA;AAAA;AAAA;AAAA;AAAA,IAQa;AARb;AAAA;AAQO,IAAM,kBAAN,MAA6C;AAAA;AAAA;AAAA;AAAA,MAIjC;AAAA,MACjB;AAAA,MAEA,YAAY,QAAwB;AAClC,YAAI,OAAO,QAAQ,UAAa,OAAO,MAAM,GAAG;AAC9C,gBAAM,IAAI,MAAM,4DAA4D,OAAO,GAAG,EAAE;AAAA,QAC1F;AAEA,YAAI,CAAC,QAAQ,IAAI,cAAc,GAAG;AAChC,kBAAQ,IAAI,cAAc,IAAI,OAAO;AAAA,QACvC;AAEA,aAAK,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK;AAAA,UACjC,KAAK,OAAO,OAAO;AAAA,UACnB,aAAa,OAAO,eAAe;AAAA,QACrC,CAAC;AAAA,MACH;AAAA,MAEA,MAAM,MAAS,KAAa,SAAyB,CAAC,GAAiB;AACrE,cAAM,KAAK,YAAY,IAAI;AAE3B,cAAM,OAAO,MAAM,KAAK,IAAI,OAAO,KAAK,MAAM;AAC9C,aAAK,UAAU,EAAE,KAAK,QAAQ,YAAY,YAAY,IAAI,IAAI,IAAI,MAAM,QAAQ,CAAC;AACjF,eAAO;AAAA,MACT;AAAA,MAEA,MAAM,QAAQ,KAAa,SAAyB,CAAC,GAA2B;AAC9E,cAAM,KAAK,YAAY,IAAI;AAC3B,cAAM,SAAS,MAAM,KAAK,IAAI,OAAO,KAAK,MAAM;AAChD,aAAK,UAAU,EAAE,KAAK,QAAQ,YAAY,YAAY,IAAI,IAAI,IAAI,MAAM,UAAU,CAAC;AAEnF,cAAM,eAAe,OAAO,QAAQ,UAAU,WAAW,OAAO,QAAS,QAAQ,UAAU;AAC3F,eAAO,EAAE,aAAa;AAAA,MACxB;AAAA,MAEA,MAAM,YAAe,IAAiD;AACpE,eAAO,KAAK,IAAI,MAAM,OAAO,OAAY;AACvC,gBAAM,YAAyB;AAAA,YAC7B,OAAa,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,OAAO,GAAG,CAAC;AAAA,YAC1C,SAAa,OAAO,GAAG,IAAI,CAAC,MAAM;AAChC,oBAAM,IAAI,MAAM,GAAG,OAAO,GAAG,CAAC;AAC9B,oBAAM,eAAe,OAAO,GAAG,UAAU,WAAW,EAAE,QAAS,GAAG,UAAU;AAC5E,qBAAO,EAAE,aAAa;AAAA,YACxB;AAAA,YACA,aAAa,CAAC,YAAY,QAAQ,SAAS;AAAA;AAAA,YAC3C,OAAa,YAAY;AAAA,YAAC;AAAA;AAAA,UAC5B;AACA,iBAAO,GAAG,SAAS;AAAA,QACrB,CAAC;AAAA,MACH;AAAA,MAEA,MAAM,QAAuB;AAC3B,cAAM,KAAK,IAAI,MAAM;AAAA,MACvB;AAAA,IACF;AAAA;AAAA;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapter/sqlite.ts"],"sourcesContent":["import { Database } from 'bun:sqlite'\nimport type { VelnAdapter, BindingValue, ExecuteResult, QueryLogEntry } from './types'\n\nexport interface SQLiteConfig {\n path?: string // default ':memory:'\n wal?: boolean // default true\n}\n\n// Maximum number of prepared statements cached per adapter instance.\n// Prevents unbounded memory growth when queries are dynamically constructed.\nconst STMT_CACHE_MAX = 500\n\nexport class SQLiteAdapter implements VelnAdapter {\n private readonly db: Database\n // LRU cache for prepared statements — Map preserves insertion order.\n // On cache hit: entry is moved to end (most recently used).\n // On cache full: oldest entry (front of Map) is evicted before inserting.\n private readonly _stmtCache = new Map<string, ReturnType<Database['prepare']>>()\n onQuery?: (entry: QueryLogEntry) => void\n\n constructor(config: SQLiteConfig | string = {}) {\n const path = typeof config === 'string' ? config : (config.path ?? ':memory:')\n const wal = typeof config === 'string' ? true : (config.wal ?? true)\n\n this.db = new Database(path)\n if (wal) this.db.run('PRAGMA journal_mode = WAL')\n this.db.run('PRAGMA foreign_keys = ON')\n }\n\n private _prepare(sql: string): ReturnType<Database['prepare']> {\n const cached = this._stmtCache.get(sql)\n if (cached) {\n // LRU: move to end (most recently used)\n this._stmtCache.delete(sql)\n this._stmtCache.set(sql, cached)\n return cached\n }\n // Evict oldest entry if at capacity\n if (this._stmtCache.size >= STMT_CACHE_MAX) {\n const oldest = this._stmtCache.keys().next().value\n if (oldest !== undefined) this._stmtCache.delete(oldest)\n }\n const stmt = this.db.prepare(sql)\n this._stmtCache.set(sql, stmt)\n return stmt\n }\n\n async query<T>(sql: string, params: BindingValue[] = []): Promise<T[]> {\n const t0 = performance.now()\n const stmt = this._prepare(sql)\n const rows = stmt.all(...params) as T[]\n this.onQuery?.({ sql, params, durationMs: performance.now() - t0, type: 'query' })\n return rows\n }\n\n async execute(sql: string, params: BindingValue[] = []): Promise<ExecuteResult> {\n const t0 = performance.now()\n const stmt = this._prepare(sql)\n const result = stmt.run(...params)\n this.onQuery?.({ sql, params, durationMs: performance.now() - t0, type: 'execute' })\n // result.changes and lastInsertRowid can be bigint in some bun:sqlite versions\n const rowsAffected = typeof result.changes === 'bigint'\n ? Number(result.changes)\n : result.changes\n return {\n rowsAffected,\n lastInsertId: result.lastInsertRowid,\n }\n }\n\n async transaction<T>(fn: (tx: VelnAdapter) => Promise<T>): Promise<T> {\n // Use db.run() directly — prepared statements for control statements (BEGIN/COMMIT/ROLLBACK)\n // are not reliable in SQLite; db.run() is the correct low-level API for these.\n this.db.run('BEGIN')\n try {\n const result = await fn(this)\n this.db.run('COMMIT')\n return result\n } catch (err) {\n this.db.run('ROLLBACK')\n throw err\n }\n }\n\n async close(): Promise<void> {\n this.db.close()\n }\n}\n"],"mappings":";;;;;;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,gBAAgB;AAAzB,IAUM,gBAEO;AAZb;AAAA;AAUA,IAAM,iBAAiB;AAEhB,IAAM,gBAAN,MAA2C;AAAA,MAC/B;AAAA;AAAA;AAAA;AAAA,MAIA,aAAa,oBAAI,IAA6C;AAAA,MAC/E;AAAA,MAEA,YAAY,SAAgC,CAAC,GAAG;AAC9C,cAAM,OAAO,OAAO,WAAW,WAAW,SAAU,OAAO,QAAQ;AACnE,cAAM,MAAO,OAAO,WAAW,WAAW,OAAU,OAAO,OAAQ;AAEnE,aAAK,KAAK,IAAI,SAAS,IAAI;AAC3B,YAAI,IAAK,MAAK,GAAG,IAAI,2BAA2B;AAChD,aAAK,GAAG,IAAI,0BAA0B;AAAA,MACxC;AAAA,MAEQ,SAAS,KAA8C;AAC7D,cAAM,SAAS,KAAK,WAAW,IAAI,GAAG;AACtC,YAAI,QAAQ;AAEV,eAAK,WAAW,OAAO,GAAG;AAC1B,eAAK,WAAW,IAAI,KAAK,MAAM;AAC/B,iBAAO;AAAA,QACT;AAEA,YAAI,KAAK,WAAW,QAAQ,gBAAgB;AAC1C,gBAAM,SAAS,KAAK,WAAW,KAAK,EAAE,KAAK,EAAE;AAC7C,cAAI,WAAW,OAAW,MAAK,WAAW,OAAO,MAAM;AAAA,QACzD;AACA,cAAM,OAAO,KAAK,GAAG,QAAQ,GAAG;AAChC,aAAK,WAAW,IAAI,KAAK,IAAI;AAC7B,eAAO;AAAA,MACT;AAAA,MAEA,MAAM,MAAS,KAAa,SAAyB,CAAC,GAAiB;AACrE,cAAM,KAAK,YAAY,IAAI;AAC3B,cAAM,OAAO,KAAK,SAAS,GAAG;AAC9B,cAAM,OAAO,KAAK,IAAI,GAAG,MAAM;AAC/B,aAAK,UAAU,EAAE,KAAK,QAAQ,YAAY,YAAY,IAAI,IAAI,IAAI,MAAM,QAAQ,CAAC;AACjF,eAAO;AAAA,MACT;AAAA,MAEA,MAAM,QAAQ,KAAa,SAAyB,CAAC,GAA2B;AAC9E,cAAM,KAAK,YAAY,IAAI;AAC3B,cAAM,OAAO,KAAK,SAAS,GAAG;AAC9B,cAAM,SAAS,KAAK,IAAI,GAAG,MAAM;AACjC,aAAK,UAAU,EAAE,KAAK,QAAQ,YAAY,YAAY,IAAI,IAAI,IAAI,MAAM,UAAU,CAAC;AAEnF,cAAM,eAAe,OAAO,OAAO,YAAY,WAC3C,OAAO,OAAO,OAAO,IACrB,OAAO;AACX,eAAO;AAAA,UACL;AAAA,UACA,cAAc,OAAO;AAAA,QACvB;AAAA,MACF;AAAA,MAEA,MAAM,YAAe,IAAiD;AAGpE,aAAK,GAAG,IAAI,OAAO;AACnB,YAAI;AACF,gBAAM,SAAS,MAAM,GAAG,IAAI;AAC5B,eAAK,GAAG,IAAI,QAAQ;AACpB,iBAAO;AAAA,QACT,SAAS,KAAK;AACZ,eAAK,GAAG,IAAI,UAAU;AACtB,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,MAEA,MAAM,QAAuB;AAC3B,aAAK,GAAG,MAAM;AAAA,MAChB;AAAA,IACF;AAAA;AAAA;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapter/mysql.ts"],"sourcesContent":["import type { VelnAdapter, BindingValue, ExecuteResult, QueryLogEntry } from './types'\n\nexport interface MySQLConfig {\n url?: string\n hostname?: string\n port?: number\n database?: string\n username?: string\n password?: string\n max?: number\n idleTimeout?: number\n}\n\nexport class MySQLAdapter implements VelnAdapter {\n // Typed as any: Bun.SQL's instance type is not reliably exported across\n // bun-types versions and the class is a Bun global — no stable import path.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly sql: any\n onQuery?: (entry: QueryLogEntry) => void\n\n constructor(config: MySQLConfig) {\n if (config.max !== undefined && config.max < 1) {\n throw new Error(`MySQLAdapter: max connections must be at least 1, got ${config.max}`)\n }\n // @ts-ignore — Bun.SQL is a Bun global constructor, supports both MySQL and Postgres\n this.sql = new Bun.SQL({\n url: config.url,\n hostname: config.hostname,\n port: config.port,\n database: config.database,\n username: config.username,\n password: config.password,\n max: config.max ?? 10,\n idleTimeout: config.idleTimeout ?? 30,\n })\n }\n\n async query<T>(sql: string, params: BindingValue[] = []): Promise<T[]> {\n const t0 = performance.now()\n // Bun.SQL .unsafe() handles both MySQL (?) and Postgres ($1) placeholders\n const rows = await this.sql.unsafe(sql, params) as T[]\n this.onQuery?.({ sql, params, durationMs: performance.now() - t0, type: 'query' })\n return rows\n }\n\n async execute(sql: string, params: BindingValue[] = []): Promise<ExecuteResult> {\n const t0 = performance.now()\n const result = await this.sql.unsafe(sql, params)\n this.onQuery?.({ sql, params, durationMs: performance.now() - t0, type: 'execute' })\n const rowsAffected = typeof result?.count === 'number' ? result.count : (result?.length ?? 0)\n return { rowsAffected } // lastInsertId not available without explicit query\n }\n\n async transaction<T>(fn: (tx: VelnAdapter) => Promise<T>): Promise<T> {\n return this.sql.begin(async (tx: any) => {\n const txAdapter: VelnAdapter = {\n query: (s, p = []) => tx.unsafe(s, p),\n execute: async (s, p = []) => {\n const r = await tx.unsafe(s, p)\n const rowsAffected = typeof r?.count === 'number' ? r.count : (r?.length ?? 0)\n return { rowsAffected }\n },\n transaction: (innerFn) => innerFn(txAdapter), // nested: reuse same tx\n close: async () => {}, // no-op inside transaction\n }\n return fn(txAdapter)\n })\n }\n\n async close(): Promise<void> {\n await this.sql.end?.()\n }\n}\n"],"mappings":";;;;;;AAAA;AAAA;AAAA;AAAA;AAAA,IAaa;AAbb;AAAA;AAaO,IAAM,eAAN,MAA0C;AAAA;AAAA;AAAA;AAAA,MAI9B;AAAA,MACjB;AAAA,MAEA,YAAY,QAAqB;AAC/B,YAAI,OAAO,QAAQ,UAAa,OAAO,MAAM,GAAG;AAC9C,gBAAM,IAAI,MAAM,yDAAyD,OAAO,GAAG,EAAE;AAAA,QACvF;AAEA,aAAK,MAAM,IAAI,IAAI,IAAI;AAAA,UACrB,KAAa,OAAO;AAAA,UACpB,UAAa,OAAO;AAAA,UACpB,MAAa,OAAO;AAAA,UACpB,UAAa,OAAO;AAAA,UACpB,UAAa,OAAO;AAAA,UACpB,UAAa,OAAO;AAAA,UACpB,KAAa,OAAO,OAAO;AAAA,UAC3B,aAAa,OAAO,eAAe;AAAA,QACrC,CAAC;AAAA,MACH;AAAA,MAEA,MAAM,MAAS,KAAa,SAAyB,CAAC,GAAiB;AACrE,cAAM,KAAK,YAAY,IAAI;AAE3B,cAAM,OAAO,MAAM,KAAK,IAAI,OAAO,KAAK,MAAM;AAC9C,aAAK,UAAU,EAAE,KAAK,QAAQ,YAAY,YAAY,IAAI,IAAI,IAAI,MAAM,QAAQ,CAAC;AACjF,eAAO;AAAA,MACT;AAAA,MAEA,MAAM,QAAQ,KAAa,SAAyB,CAAC,GAA2B;AAC9E,cAAM,KAAK,YAAY,IAAI;AAC3B,cAAM,SAAS,MAAM,KAAK,IAAI,OAAO,KAAK,MAAM;AAChD,aAAK,UAAU,EAAE,KAAK,QAAQ,YAAY,YAAY,IAAI,IAAI,IAAI,MAAM,UAAU,CAAC;AACnF,cAAM,eAAe,OAAO,QAAQ,UAAU,WAAW,OAAO,QAAS,QAAQ,UAAU;AAC3F,eAAO,EAAE,aAAa;AAAA,MACxB;AAAA,MAEA,MAAM,YAAe,IAAiD;AACpE,eAAO,KAAK,IAAI,MAAM,OAAO,OAAY;AACvC,gBAAM,YAAyB;AAAA,YAC7B,OAAa,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,OAAO,GAAG,CAAC;AAAA,YAC1C,SAAa,OAAO,GAAG,IAAI,CAAC,MAAM;AAChC,oBAAM,IAAI,MAAM,GAAG,OAAO,GAAG,CAAC;AAC9B,oBAAM,eAAe,OAAO,GAAG,UAAU,WAAW,EAAE,QAAS,GAAG,UAAU;AAC5E,qBAAO,EAAE,aAAa;AAAA,YACxB;AAAA,YACA,aAAa,CAAC,YAAY,QAAQ,SAAS;AAAA;AAAA,YAC3C,OAAa,YAAY;AAAA,YAAC;AAAA;AAAA,UAC5B;AACA,iBAAO,GAAG,SAAS;AAAA,QACrB,CAAC;AAAA,MACH;AAAA,MAEA,MAAM,QAAuB;AAC3B,cAAM,KAAK,IAAI,MAAM;AAAA,MACvB;AAAA,IACF;AAAA;AAAA;","names":[]}