@xylex-group/better-auth-athena 1.0.6 → 1.0.7
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 +1 -1
- package/dist/index.cjs +9 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# better-auth-athena
|
|
2
2
|
|
|
3
|
-
current version: `1.0.
|
|
3
|
+
current version: `1.0.7`
|
|
4
4
|
A Better-Auth database adapter for the `@xylex-group/athena` gateway. It lets Better-Auth read and write data through Athena while keeping column names in `snake_case` as required by the gateway.
|
|
5
5
|
|
|
6
6
|
## Installation
|
package/dist/index.cjs
CHANGED
|
@@ -493,6 +493,10 @@ function findOneMethod(deps) {
|
|
|
493
493
|
// src/methods/find-many.ts
|
|
494
494
|
function findManyMethod(deps) {
|
|
495
495
|
const { ensureDbClient } = deps;
|
|
496
|
+
const isTransientGatewayError = (error) => {
|
|
497
|
+
const message = String(error ?? "").toLowerCase();
|
|
498
|
+
return message.includes("application failed to respond") || message.includes("timeout") || message.includes("timed out") || message.includes("gateway timeout") || message.includes("econnreset") || message.includes("connection reset");
|
|
499
|
+
};
|
|
496
500
|
return async function findMany({
|
|
497
501
|
model,
|
|
498
502
|
where,
|
|
@@ -527,7 +531,11 @@ function findManyMethod(deps) {
|
|
|
527
531
|
const { data: result, error } = await builder;
|
|
528
532
|
return { result, error };
|
|
529
533
|
};
|
|
530
|
-
|
|
534
|
+
let first = await run(snakeMapper);
|
|
535
|
+
if (first.error && isTransientGatewayError(first.error)) {
|
|
536
|
+
const retry = await run(snakeMapper);
|
|
537
|
+
if (!retry.error) first = retry;
|
|
538
|
+
}
|
|
531
539
|
const pickRows = (res) => Array.isArray(res) ? res : [];
|
|
532
540
|
const applySort = (rows) => {
|
|
533
541
|
if (!sortBy) return rows;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/utils.ts","../src/methods/create.ts","../src/methods/update.ts","../src/methods/update-many.ts","../src/methods/delete.ts","../src/methods/delete-many.ts","../src/methods/find-one.ts","../src/methods/find-many.ts","../src/methods/count.ts"],"sourcesContent":["import {\r\n createAdapterFactory,\r\n type AdapterFactory,\r\n type DBAdapterDebugLogOption,\r\n} from \"better-auth/adapters\";\r\nimport type { BetterAuthOptions } from \"better-auth\";\r\nimport { createClient } from \"@xylex-group/athena\";\r\nimport { getAthenaGlobalConfig } from \"./config\";\r\nimport { createMethod } from \"./methods/create\";\r\nimport { updateMethod } from \"./methods/update\";\r\nimport { updateManyMethod } from \"./methods/update-many\";\r\nimport { deleteMethod } from \"./methods/delete\";\r\nimport { deleteManyMethod } from \"./methods/delete-many\";\r\nimport { findOneMethod } from \"./methods/find-one\";\r\nimport { findManyMethod } from \"./methods/find-many\";\r\nimport { countMethod } from \"./methods/count\";\r\n\r\n/**\r\n * Configuration options for the Athena adapter.\r\n */\r\nexport interface AthenaAdapterConfig {\r\n /**\r\n * The URL of your Athena gateway.\r\n */\r\n url?: string;\r\n /**\r\n * The API key for authenticating with the Athena gateway.\r\n */\r\n apiKey?: string;\r\n /**\r\n * The client name sent in requests to the Athena gateway.\r\n */\r\n client?: string;\r\n\r\n /**\r\n * Optional override for the YAML config path.\r\n * Defaults to `./config.yaml` (resolved from `process.cwd()`).\r\n */\r\n configPath?: string;\r\n\r\n /**\r\n * When enabled, the adapter will reload `config.yaml` on changes.\r\n *\r\n * @default true\r\n */\r\n watchConfig?: boolean;\r\n /**\r\n * Helps you debug issues with the adapter.\r\n */\r\n debugLogs?: DBAdapterDebugLogOption;\r\n /**\r\n * If the table names in the schema are plural.\r\n *\r\n * @default false\r\n */\r\n usePlural?: boolean;\r\n\r\n /**\r\n * Optional headers sent with every request (e.g. `X-User-Id` if your gateway requires it for delete).\r\n */\r\n headers?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * Create a Better-Auth database adapter backed by @xylex-group/athena.\r\n *\r\n * Column names are kept in snake_case as required by the Athena gateway.\r\n *\r\n * @example\r\n * ```ts\r\n * import { betterAuth } from \"better-auth\";\r\n * import { athenaAdapter } from \"better-auth-athena\";\r\n *\r\n * export const auth = betterAuth({\r\n * database: athenaAdapter({\r\n * url: process.env.ATHENA_URL!,\r\n * apiKey: process.env.ATHENA_API_KEY!,\r\n * client: \"my-app\",\r\n * }),\r\n * });\r\n * ```\r\n */\r\nexport const athenaAdapter = (\r\n config: AthenaAdapterConfig,\r\n): AdapterFactory<BetterAuthOptions> => {\r\n let dbClient: any | null = null;\r\n let lastDbConfigVersion = -1;\r\n\r\n const shouldUseFixedConfig =\r\n typeof config.url === \"string\" &&\r\n config.url.length > 0 &&\r\n typeof config.apiKey === \"string\" &&\r\n config.apiKey.length > 0;\r\n\r\n function ensureDbClient(): any {\r\n if (shouldUseFixedConfig) {\r\n if (!dbClient) {\r\n dbClient = createClient(config.url!, config.apiKey!, {\r\n client: config.client,\r\n ...(config.headers && { headers: config.headers }),\r\n } as any);\r\n }\r\n return dbClient;\r\n }\r\n\r\n const { config: globalConfig, version } = getAthenaGlobalConfig({\r\n configPath: config.configPath,\r\n watch: config.watchConfig ?? true,\r\n });\r\n\r\n const url = config.url ?? globalConfig.athena.url;\r\n const apiKey = config.apiKey ?? globalConfig.athena.apiKey;\r\n const client = config.client ?? globalConfig.athena.client;\r\n\r\n if (!url || !apiKey) {\r\n throw new Error(\r\n `[AthenaAdapter] Missing Athena connection details. Set both 'athena.url' and 'athena.apiKey' in config.yaml (or pass 'url'/'apiKey' to athenaAdapter).`,\r\n );\r\n }\r\n\r\n if (!dbClient || version !== lastDbConfigVersion) {\r\n dbClient = createClient(url, apiKey, {\r\n client,\r\n ...(config.headers && { headers: config.headers }),\r\n } as any);\r\n lastDbConfigVersion = version;\r\n }\r\n\r\n return dbClient;\r\n }\r\n\r\n const deps = { ensureDbClient, headers: config.headers };\r\n\r\n return createAdapterFactory({\r\n config: {\r\n adapterId: \"athena\",\r\n adapterName: \"Athena Adapter\",\r\n usePlural: config.usePlural ?? false,\r\n debugLogs: config.debugLogs ?? false,\r\n supportsJSON: true,\r\n supportsDates: true,\r\n supportsBooleans: true,\r\n supportsNumericIds: true,\r\n supportsUUIDs: true,\r\n },\r\n adapter: () => {\r\n return {\r\n create: createMethod(deps),\r\n update: updateMethod(deps),\r\n updateMany: updateManyMethod(deps),\r\n delete: deleteMethod(deps),\r\n deleteMany: deleteManyMethod(deps),\r\n findOne: findOneMethod(deps),\r\n findMany: findManyMethod(deps),\r\n count: countMethod(deps),\r\n };\r\n },\r\n });\r\n};\r\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport YAML from \"yaml\";\r\n\r\nexport type AthenaGlobalConfig = {\r\n athena: {\r\n url: string;\r\n apiKey: string;\r\n client?: string;\r\n };\r\n};\r\n\r\n// Defaults written to `config.yaml` if it doesn't exist.\r\n// These values are intentionally placeholders; the adapter will throw if\r\n// `url`/`apiKey` are still unset when used.\r\nexport const defaultAthenaGlobalConfig: AthenaGlobalConfig = {\r\n athena: {\r\n url: \"https://mirror3.athena-db.com\",\r\n apiKey: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYXV0aGVudGljYXRlZCIsImVtYWlsIjoiZmxvcmlzQHh5bGV4LmFpIiwiZXhwIjoyNDk3MDMzNjY2fQ.LdPqTGaFq5pTokW1DA81WFjmG4nReJCOSKr3mFtXNoA\",\r\n client: \"athena_logging\",\r\n },\r\n};\r\n\r\nexport const DEFAULT_CONFIG_FILENAME = \"config.yaml\";\r\n\r\nfunction resolveConfigPath(configPath?: string): string {\r\n if (configPath) return path.resolve(configPath);\r\n return path.resolve(process.cwd(), DEFAULT_CONFIG_FILENAME);\r\n}\r\n\r\nlet cached: AthenaGlobalConfig | null = null;\r\nlet cachedConfigPath: string | null = null;\r\nlet version = 0;\r\n\r\nlet watcher: fs.FSWatcher | null = null;\r\n\r\nfunction isObject(value: unknown): value is Record<string, unknown> {\r\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction deepMerge<T extends Record<string, unknown>>(\r\n base: T,\r\n partial: unknown,\r\n): T {\r\n if (!isObject(partial)) return base;\r\n const out: Record<string, unknown> = { ...base };\r\n for (const [k, v] of Object.entries(partial)) {\r\n if (v && isObject(v) && isObject(out[k])) {\r\n out[k] = deepMerge(out[k] as Record<string, unknown>, v);\r\n } else {\r\n out[k] = v;\r\n }\r\n }\r\n return out as T;\r\n}\r\n\r\nfunction ensureConfigFile(configPath: string): void {\r\n const dir = path.dirname(configPath);\r\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\r\n\r\n if (!fs.existsSync(configPath)) {\r\n const yaml = YAML.stringify(defaultAthenaGlobalConfig);\r\n fs.writeFileSync(configPath, yaml, \"utf-8\");\r\n }\r\n}\r\n\r\nfunction readConfigFromDisk(configPath: string): AthenaGlobalConfig {\r\n ensureConfigFile(configPath);\r\n const raw = fs.readFileSync(configPath, \"utf-8\");\r\n const parsed = YAML.parse(raw) as unknown;\r\n return deepMerge(defaultAthenaGlobalConfig, parsed);\r\n}\r\n\r\nfunction startWatcher(configPath: string): void {\r\n // Avoid multiple watchers when multiple adapter instances are created.\r\n if (cachedConfigPath !== null && cachedConfigPath !== configPath && watcher) {\r\n try {\r\n watcher.close();\r\n } catch {\r\n // ignore\r\n }\r\n watcher = null;\r\n }\r\n if (watcher || cachedConfigPath === configPath) return;\r\n\r\n try {\r\n watcher = fs.watch(configPath, { persistent: false }, (event) => {\r\n if (event !== \"change\" && event !== \"rename\") return;\r\n try {\r\n cached = readConfigFromDisk(configPath);\r\n version += 1;\r\n } catch {\r\n // Keep last known good config if reload fails.\r\n }\r\n });\r\n cachedConfigPath = configPath;\r\n } catch {\r\n // If watching isn't supported in the environment, just run without it.\r\n }\r\n}\r\n\r\nexport function getAthenaGlobalConfig(options?: {\r\n configPath?: string;\r\n watch?: boolean;\r\n}): { config: AthenaGlobalConfig; version: number } {\r\n const configPath = resolveConfigPath(options?.configPath);\r\n const shouldWatch = options?.watch ?? true;\r\n\r\n if (!cached || cachedConfigPath !== configPath) {\r\n cached = readConfigFromDisk(configPath);\r\n cachedConfigPath = configPath;\r\n version += 1;\r\n }\r\n\r\n if (shouldWatch) startWatcher(configPath);\r\n\r\n return { config: cached, version };\r\n}\r\n","/**\r\n * Shared helpers and types for the Athena adapter.\r\n */\r\n\r\nexport function toSnakeCase(key: string): string {\r\n return key\r\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\r\n .replace(/__/g, \"_\")\r\n .toLowerCase();\r\n}\r\n\r\nexport function toCamelCase(key: string): string {\r\n return key.replace(/_([a-z0-9])/g, (_, ch: string) => ch.toUpperCase());\r\n}\r\n\r\nexport function hasUppercase(key: string): boolean {\r\n return /[A-Z]/.test(key);\r\n}\r\n\r\nexport function mapKeys<T extends Record<string, unknown>>(\r\n obj: T,\r\n mapKey: (k: string) => string,\r\n): Record<string, unknown> {\r\n const out: Record<string, unknown> = {};\r\n for (const [k, v] of Object.entries(obj)) out[mapKey(k)] = v;\r\n return out;\r\n}\r\n\r\nexport function mapRowToBetterAuth<T>(row: T): T {\r\n if (!row || typeof row !== \"object\") return row;\r\n if (Array.isArray(row)) return row.map(mapRowToBetterAuth) as unknown as T;\r\n return mapKeys(row as Record<string, unknown>, toCamelCase) as T;\r\n}\r\n\r\nexport function isLikelyIsoDateString(value: string): boolean {\r\n if (!/^\\d{4}-\\d{2}-\\d{2}T/.test(value)) return false;\r\n const ms = Date.parse(value);\r\n return Number.isFinite(ms);\r\n}\r\n\r\nexport function isTimestampKey(key: string): boolean {\r\n return key.endsWith(\"At\") || key.endsWith(\"_at\") || key === \"expires\";\r\n}\r\n\r\nexport function coerceDateFields<T extends Record<string, unknown>>(data: T): T {\r\n const out: Record<string, unknown> = { ...data };\r\n for (const [key, val] of Object.entries(out)) {\r\n if (val == null) continue;\r\n if (\r\n typeof val === \"string\" &&\r\n isTimestampKey(key) &&\r\n isLikelyIsoDateString(val)\r\n ) {\r\n out[key] = new Date(val);\r\n }\r\n }\r\n return out as T;\r\n}\r\n\r\nexport function toDbRecord<T extends Record<string, unknown>>(\r\n data: T,\r\n): Record<string, unknown> {\r\n const withDbKeys = mapKeys(data, (k) =>\r\n hasUppercase(k) ? toSnakeCase(k) : k,\r\n );\r\n return coerceDateFields(withDbKeys);\r\n}\r\n\r\nexport type AthenaFilterBuilder = {\r\n eq(col: string, val: unknown): AthenaFilterBuilder;\r\n neq(col: string, val: unknown): AthenaFilterBuilder;\r\n gt(col: string, val: unknown): AthenaFilterBuilder;\r\n gte(col: string, val: unknown): AthenaFilterBuilder;\r\n lt(col: string, val: unknown): AthenaFilterBuilder;\r\n lte(col: string, val: unknown): AthenaFilterBuilder;\r\n in(col: string, vals: unknown[]): AthenaFilterBuilder;\r\n not(col: string, op?: string, val?: unknown): AthenaFilterBuilder;\r\n like(col: string, val: string): AthenaFilterBuilder;\r\n delete?(): { select(): Promise<{ data: unknown; error: unknown }> };\r\n select?(columns?: string): Promise<{ data: unknown; error: unknown }> | { select(): Promise<{ data: unknown; error: unknown }> };\r\n};\r\n\r\nexport type WhereClause = { field: string; operator: string; value: unknown };\r\n\r\nconst defaultColumnMapper = (col: string) =>\r\n hasUppercase(col) ? toSnakeCase(col) : col;\r\n\r\nexport function applyWhere(\r\n builder: AthenaFilterBuilder,\r\n field: string,\r\n operator: string,\r\n value: unknown,\r\n columnMapper: (col: string) => string = defaultColumnMapper,\r\n): AthenaFilterBuilder {\r\n const dbField = columnMapper(field);\r\n switch (operator) {\r\n case \"eq\":\r\n return builder.eq(dbField, value);\r\n case \"ne\":\r\n return builder.neq(dbField, value);\r\n case \"gt\":\r\n return builder.gt(dbField, value);\r\n case \"gte\":\r\n return builder.gte(dbField, value);\r\n case \"lt\":\r\n return builder.lt(dbField, value);\r\n case \"lte\":\r\n return builder.lte(dbField, value);\r\n case \"in\":\r\n return builder.in(dbField, value as unknown[]);\r\n case \"not_in\":\r\n return builder.not(dbField, \"in\", value);\r\n case \"contains\":\r\n return builder.like(dbField, `%${value}%`);\r\n case \"starts_with\":\r\n return builder.like(dbField, `${value}%`);\r\n case \"ends_with\":\r\n return builder.like(dbField, `%${value}`);\r\n default:\r\n return builder.eq(dbField, value);\r\n }\r\n}\r\n\r\nexport function isMissingColumnError(error: unknown): boolean {\r\n const msg = String(error ?? \"\");\r\n return (\r\n msg.includes(\"specified column does not exist\") ||\r\n msg.includes(\"column does not exist\")\r\n );\r\n}\r\n\r\n/** True when the Athena gateway returns a success message in the error field (treat as success). */\r\nexport function isSuccessMessageInError(error: unknown): boolean {\r\n const msg = String(error ?? \"\").toLowerCase();\r\n return (\r\n msg === \"data inserted successfully\" ||\r\n msg === \"data updated successfully\" ||\r\n msg === \"data deleted successfully\"\r\n );\r\n}\r\n\r\nexport function snakeMapper(col: string): string {\r\n return hasUppercase(col) ? toSnakeCase(col) : col;\r\n}\r\n\r\nexport function identityMapper(col: string): string {\r\n return col;\r\n}\r\n\r\n/** Get value from row by field name (camelCase or snake_case). */\r\nfunction getRowValue(row: Record<string, unknown>, field: string): unknown {\r\n if (Object.prototype.hasOwnProperty.call(row, field)) return row[field];\r\n const snake = hasUppercase(field) ? toSnakeCase(field) : field;\r\n return row[snake];\r\n}\r\n\r\n/**\r\n * Filter rows in-memory by where clauses (fallback when gateway does not apply filters).\r\n * Supports eq, ne, in, not_in; row keys may be camelCase or snake_case.\r\n */\r\nexport function filterRowsByWhere(\r\n rows: Record<string, unknown>[],\r\n where: WhereClause[],\r\n): Record<string, unknown>[] {\r\n if (!where.length) return rows;\r\n return rows.filter((row) => {\r\n for (const { field, operator, value } of where) {\r\n const rowVal = getRowValue(row, field);\r\n switch (operator) {\r\n case \"eq\":\r\n if (rowVal !== value) return false;\r\n break;\r\n case \"ne\":\r\n if (rowVal === value) return false;\r\n break;\r\n case \"in\":\r\n if (!Array.isArray(value) || !value.includes(rowVal)) return false;\r\n break;\r\n case \"not_in\":\r\n if (Array.isArray(value) && value.includes(rowVal)) return false;\r\n break;\r\n default:\r\n if (rowVal !== value) return false;\r\n }\r\n }\r\n return true;\r\n });\r\n}\r\n","import { toDbRecord, mapRowToBetterAuth, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type CreateDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function createMethod(deps: CreateDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function create<T extends Record<string, unknown>>({\r\n model,\r\n data,\r\n }: {\r\n model: string;\r\n data: T;\r\n select?: string[];\r\n }) {\r\n const db = ensureDbClient();\r\n const insertData = toDbRecord(data);\r\n const { data: result, error } = await db\r\n .from(model)\r\n .insert(insertData)\r\n .select();\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(`[AthenaAdapter] create on \"${model}\" failed: ${error}`);\r\n }\r\n\r\n const row = Array.isArray(result) ? result[0] : result;\r\n return mapRowToBetterAuth((row ?? insertData) as T);\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport {\r\n toDbRecord,\r\n mapRowToBetterAuth,\r\n applyWhere,\r\n isSuccessMessageInError,\r\n} from \"../utils\";\r\n\r\nexport type UpdateDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function updateMethod(deps: UpdateDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function update<T>({\r\n model,\r\n where,\r\n update,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n update: T;\r\n }) {\r\n const db = ensureDbClient();\r\n const updateData = toDbRecord(update as Record<string, unknown>);\r\n const build = (useRetryShape: boolean) => {\r\n // Primary shape: some gateway versions accept back-compat update_body keys.\r\n if (!useRetryShape) {\r\n let b = db\r\n .from(model)\r\n .update({ data: updateData, set: updateData } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n }\r\n\r\n // Retry shape: send the plain update values, but also provide an explicit `updateBody`.\r\n let b = db\r\n .from(model)\r\n .update(updateData, {\r\n updateBody: { data: updateData, set: updateData },\r\n } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n };\r\n\r\n const run = async (b: AthenaFilterBuilder) => {\r\n const { data: result, error } = await (b as any).select();\r\n return { result, error };\r\n };\r\n\r\n const first = await run(build(false));\r\n if (first.error && !isSuccessMessageInError(first.error)) {\r\n const msg = String(first.error);\r\n if (msg.toLowerCase().includes(\"update payload required\")) {\r\n const retry = await run(build(true));\r\n if (retry.error && !isSuccessMessageInError(retry.error)) {\r\n throw new Error(\r\n `[AthenaAdapter] update on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n const row = Array.isArray(retry.result)\r\n ? (retry.result[0] as unknown)\r\n : (retry.result as unknown);\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n }\r\n\r\n throw new Error(`[AthenaAdapter] update on \"${model}\" failed: ${first.error}`);\r\n }\r\n\r\n const row = Array.isArray(first.result)\r\n ? (first.result[0] as unknown)\r\n : (first.result as unknown);\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { toDbRecord, applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type UpdateManyDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function updateManyMethod(deps: UpdateManyDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function updateMany({\r\n model,\r\n where,\r\n update,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n update: Record<string, unknown>;\r\n }) {\r\n const db = ensureDbClient();\r\n const updateData = toDbRecord(update);\r\n const build = (useRetryShape: boolean) => {\r\n if (!useRetryShape) {\r\n let b = db\r\n .from(model)\r\n .update({ data: updateData, set: updateData } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n }\r\n\r\n let b = db\r\n .from(model)\r\n .update(updateData, {\r\n updateBody: { data: updateData, set: updateData },\r\n } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n };\r\n\r\n const run = async (b: AthenaFilterBuilder) => {\r\n const { data: result, error } = await (b as any).select();\r\n return { result, error };\r\n };\r\n\r\n const first = await run(build(false));\r\n if (first.error && !isSuccessMessageInError(first.error)) {\r\n const msg = String(first.error);\r\n if (msg.toLowerCase().includes(\"update payload required\")) {\r\n const retry = await run(build(true));\r\n if (retry.error && !isSuccessMessageInError(retry.error)) {\r\n throw new Error(\r\n `[AthenaAdapter] updateMany on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n return Array.isArray(retry.result) ? retry.result.length : retry.result ? 1 : 0;\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] updateMany on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n return Array.isArray(first.result) ? first.result.length : first.result ? 1 : 0;\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type DeleteDeps = {\r\n ensureDbClient: () => any;\r\n headers?: Record<string, string>;\r\n};\r\n\r\nexport function deleteMethod(deps: DeleteDeps) {\r\n const { ensureDbClient, headers } = deps;\r\n\r\n return async function del({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n let builder = db.from(model) as AthenaFilterBuilder;\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n );\r\n }\r\n\r\n const { error } = await (builder as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n );\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(\r\n `[AthenaAdapter] delete on \"${model}\" failed: ${error}`,\r\n );\r\n }\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type DeleteManyDeps = {\r\n ensureDbClient: () => any;\r\n headers?: Record<string, string>;\r\n};\r\n\r\nexport function deleteManyMethod(deps: DeleteManyDeps) {\r\n const { ensureDbClient, headers } = deps;\r\n\r\n return async function deleteMany({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n const mainBuilder = db.from(model) as AthenaFilterBuilder;\r\n let builder = mainBuilder;\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n );\r\n }\r\n\r\n const { data: result, error } = await (builder as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n ).select();\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(\r\n `[AthenaAdapter] deleteMany on \"${model}\" failed: ${error}`,\r\n );\r\n }\r\n\r\n const deletedCount = Array.isArray(result) ? result.length : result ? 1 : 0;\r\n // Fallback: if the live gateway doesn't apply `in` conditions correctly,\r\n // delete rows one-by-one so counts are stable for e2e tests.\r\n const inClause = where.find(\r\n (c) => c.operator === \"in\" && c.value != null,\r\n );\r\n if (\r\n inClause &&\r\n Array.isArray(inClause.value) &&\r\n deletedCount < inClause.value.length\r\n ) {\r\n let n = 0;\r\n for (const v of inClause.value) {\r\n const b = db.from(model);\r\n const filtered = applyWhere(\r\n b as any,\r\n inClause.field,\r\n \"eq\",\r\n v,\r\n );\r\n const { data: rowData, error: rowErr } = await (filtered as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n ).select();\r\n if (rowErr && isSuccessMessageInError(rowErr)) continue;\r\n n += Array.isArray(rowData) ? rowData.length : rowData ? 1 : 0;\r\n }\r\n return n;\r\n }\r\n\r\n return deletedCount;\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n mapRowToBetterAuth,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n filterRowsByWhere,\r\n} from \"../utils\";\r\n\r\nexport type FindOneDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function findOneMethod(deps: FindOneDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function findOne<T>({\r\n model,\r\n where,\r\n select,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n select?: string[];\r\n join?: unknown;\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (columnMapper: (col: string) => string) => {\r\n const columns =\r\n select && select.length > 0\r\n ? select.map((c) => columnMapper(c)).join(\", \")\r\n : undefined;\r\n\r\n let builder = db.from(model).select(columns);\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n\r\n const { data: result, error } = await builder.limit(1);\r\n return { result, error };\r\n };\r\n\r\n const first = await run(snakeMapper);\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] findOne on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n\r\n const rows = Array.isArray(retry.result)\r\n ? retry.result\r\n : retry.result\r\n ? [retry.result]\r\n : [];\r\n const row = rows[0] ?? null;\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] findOne on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n const rows = Array.isArray(first.result)\r\n ? first.result\r\n : first.result\r\n ? [first.result]\r\n : [];\r\n const row = rows[0] ?? null;\r\n if (!row) return null;\r\n\r\n const mapped = mapRowToBetterAuth(row as T) as T;\r\n const filtered = filterRowsByWhere(\r\n [mapped as unknown as Record<string, unknown>],\r\n where,\r\n );\r\n return (filtered[0] ? mapped : null) as T | null;\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n mapRowToBetterAuth,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n filterRowsByWhere,\r\n} from \"../utils\";\r\n\r\nexport type FindManyDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function findManyMethod(deps: FindManyDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function findMany<T>({\r\n model,\r\n where,\r\n limit,\r\n sortBy,\r\n offset,\r\n select,\r\n }: {\r\n model: string;\r\n where?: WhereClause[];\r\n limit: number;\r\n select?: string[];\r\n sortBy?: { field: string; direction: \"asc\" | \"desc\" };\r\n offset?: number;\r\n join?: unknown;\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (\r\n columnMapper: (col: string) => string,\r\n opts?: { skipWhere?: boolean; limitOverride?: number; offsetOverride?: number },\r\n ) => {\r\n const columns =\r\n select && select.length > 0\r\n ? select.map((c) => columnMapper(c)).join(\", \")\r\n : undefined;\r\n\r\n let builder = db.from(model).select(columns);\r\n\r\n if (!opts?.skipWhere && where) {\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n }\r\n\r\n const effectiveLimit = opts?.limitOverride ?? limit;\r\n const effectiveOffset = opts?.offsetOverride ?? offset;\r\n\r\n if (effectiveLimit !== undefined) {\r\n builder = builder.limit(effectiveLimit);\r\n }\r\n\r\n if (effectiveOffset !== undefined) {\r\n builder = builder.offset(effectiveOffset);\r\n }\r\n\r\n const { data: result, error } = await builder;\r\n return { result, error };\r\n };\r\n\r\n const first = await run(snakeMapper);\r\n const pickRows = (res: unknown) =>\r\n (Array.isArray(res) ? res : []) as Record<string, unknown>[];\r\n\r\n const applySort = (rows: T[]) => {\r\n if (!sortBy) return rows;\r\n const sortField = sortBy.field;\r\n rows.sort((a, b) => {\r\n const aVal = (a as Record<string, unknown>)[sortField];\r\n const bVal = (b as Record<string, unknown>)[sortField];\r\n if (aVal == null && bVal == null) return 0;\r\n if (aVal == null) return sortBy.direction === \"asc\" ? -1 : 1;\r\n if (bVal == null) return sortBy.direction === \"asc\" ? 1 : -1;\r\n const cmp =\r\n typeof aVal === \"string\" && typeof bVal === \"string\"\r\n ? aVal.localeCompare(bVal)\r\n : aVal < bVal\r\n ? -1\r\n : aVal > bVal\r\n ? 1\r\n : 0;\r\n return sortBy.direction === \"asc\" ? cmp : -cmp;\r\n });\r\n return rows;\r\n };\r\n\r\n const mapAndSort = (rows: Record<string, unknown>[]) => {\r\n const betterAuthRows = rows.map((r) => mapRowToBetterAuth(r)) as unknown as T[];\r\n\r\n if (!where?.length) return applySort(betterAuthRows);\r\n\r\n const filtered = filterRowsByWhere(\r\n betterAuthRows as unknown as Record<string, unknown>[],\r\n where,\r\n ) as unknown as T[];\r\n\r\n // If filtering changed the row set, the gateway likely ignored `where`\r\n // (or applied it before limiting/offset). In that case, re-apply sorting\r\n // and slice using the requested offset/limit.\r\n if (filtered.length !== betterAuthRows.length) {\r\n const off = offset ?? 0;\r\n const end = limit !== undefined ? off + limit : undefined;\r\n return applySort(filtered).slice(off, end);\r\n }\r\n\r\n return applySort(filtered);\r\n };\r\n\r\n const postFilterAndSlice = (rows: Record<string, unknown>[]) => {\r\n const mappedSorted = mapAndSort(rows);\r\n const off = offset ?? 0;\r\n const end = limit !== undefined ? off + limit : undefined;\r\n return mappedSorted.slice(off, end);\r\n };\r\n\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] findMany on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n const retryRows = pickRows(retry.result);\r\n // Decisive fallback: if gateway-side `where` yields empty/insufficient rows,\r\n // fetch a broader candidate set and apply `where`/sort/offset/limit in-memory.\r\n if (where?.length) {\r\n const broad = await run(identityMapper, {\r\n skipWhere: true,\r\n limitOverride: Math.max((offset ?? 0) + (limit ?? 0) + 500, 5000),\r\n offsetOverride: 0,\r\n });\r\n if (!broad.error) return postFilterAndSlice(pickRows(broad.result));\r\n }\r\n return mapAndSort(retryRows);\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] findMany on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n const firstRows = pickRows(first.result);\r\n if (where?.length) {\r\n const broad = await run(snakeMapper, {\r\n skipWhere: true,\r\n limitOverride: Math.max((offset ?? 0) + (limit ?? 0) + 500, 5000),\r\n offsetOverride: 0,\r\n });\r\n if (!broad.error) return postFilterAndSlice(pickRows(broad.result));\r\n }\r\n return mapAndSort(firstRows);\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n} from \"../utils\";\r\n\r\nexport type CountDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function countMethod(deps: CountDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function count({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where?: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (columnMapper: (col: string) => string) => {\r\n let builder = db.from(model).select();\r\n\r\n if (where) {\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n }\r\n\r\n const { data: result, error } = await builder;\r\n return { result, error };\r\n };\r\n\r\n const first = await run(snakeMapper);\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] count on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n return Array.isArray(retry.result) ? retry.result.length : 0;\r\n }\r\n throw new Error(\r\n `[AthenaAdapter] count on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n return Array.isArray(first.result) ? first.result.length : 0;\r\n };\r\n}\r\n"],"mappings":"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","names":["path","fs","YAML","b","row","b","rows","row","version"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/utils.ts","../src/methods/create.ts","../src/methods/update.ts","../src/methods/update-many.ts","../src/methods/delete.ts","../src/methods/delete-many.ts","../src/methods/find-one.ts","../src/methods/find-many.ts","../src/methods/count.ts"],"sourcesContent":["import {\r\n createAdapterFactory,\r\n type AdapterFactory,\r\n type DBAdapterDebugLogOption,\r\n} from \"better-auth/adapters\";\r\nimport type { BetterAuthOptions } from \"better-auth\";\r\nimport { createClient } from \"@xylex-group/athena\";\r\nimport { getAthenaGlobalConfig } from \"./config\";\r\nimport { createMethod } from \"./methods/create\";\r\nimport { updateMethod } from \"./methods/update\";\r\nimport { updateManyMethod } from \"./methods/update-many\";\r\nimport { deleteMethod } from \"./methods/delete\";\r\nimport { deleteManyMethod } from \"./methods/delete-many\";\r\nimport { findOneMethod } from \"./methods/find-one\";\r\nimport { findManyMethod } from \"./methods/find-many\";\r\nimport { countMethod } from \"./methods/count\";\r\n\r\n/**\r\n * Configuration options for the Athena adapter.\r\n */\r\nexport interface AthenaAdapterConfig {\r\n /**\r\n * The URL of your Athena gateway.\r\n */\r\n url?: string;\r\n /**\r\n * The API key for authenticating with the Athena gateway.\r\n */\r\n apiKey?: string;\r\n /**\r\n * The client name sent in requests to the Athena gateway.\r\n */\r\n client?: string;\r\n\r\n /**\r\n * Optional override for the YAML config path.\r\n * Defaults to `./config.yaml` (resolved from `process.cwd()`).\r\n */\r\n configPath?: string;\r\n\r\n /**\r\n * When enabled, the adapter will reload `config.yaml` on changes.\r\n *\r\n * @default true\r\n */\r\n watchConfig?: boolean;\r\n /**\r\n * Helps you debug issues with the adapter.\r\n */\r\n debugLogs?: DBAdapterDebugLogOption;\r\n /**\r\n * If the table names in the schema are plural.\r\n *\r\n * @default false\r\n */\r\n usePlural?: boolean;\r\n\r\n /**\r\n * Optional headers sent with every request (e.g. `X-User-Id` if your gateway requires it for delete).\r\n */\r\n headers?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * Create a Better-Auth database adapter backed by @xylex-group/athena.\r\n *\r\n * Column names are kept in snake_case as required by the Athena gateway.\r\n *\r\n * @example\r\n * ```ts\r\n * import { betterAuth } from \"better-auth\";\r\n * import { athenaAdapter } from \"better-auth-athena\";\r\n *\r\n * export const auth = betterAuth({\r\n * database: athenaAdapter({\r\n * url: process.env.ATHENA_URL!,\r\n * apiKey: process.env.ATHENA_API_KEY!,\r\n * client: \"my-app\",\r\n * }),\r\n * });\r\n * ```\r\n */\r\nexport const athenaAdapter = (\r\n config: AthenaAdapterConfig,\r\n): AdapterFactory<BetterAuthOptions> => {\r\n let dbClient: any | null = null;\r\n let lastDbConfigVersion = -1;\r\n\r\n const shouldUseFixedConfig =\r\n typeof config.url === \"string\" &&\r\n config.url.length > 0 &&\r\n typeof config.apiKey === \"string\" &&\r\n config.apiKey.length > 0;\r\n\r\n function ensureDbClient(): any {\r\n if (shouldUseFixedConfig) {\r\n if (!dbClient) {\r\n dbClient = createClient(config.url!, config.apiKey!, {\r\n client: config.client,\r\n ...(config.headers && { headers: config.headers }),\r\n } as any);\r\n }\r\n return dbClient;\r\n }\r\n\r\n const { config: globalConfig, version } = getAthenaGlobalConfig({\r\n configPath: config.configPath,\r\n watch: config.watchConfig ?? true,\r\n });\r\n\r\n const url = config.url ?? globalConfig.athena.url;\r\n const apiKey = config.apiKey ?? globalConfig.athena.apiKey;\r\n const client = config.client ?? globalConfig.athena.client;\r\n\r\n if (!url || !apiKey) {\r\n throw new Error(\r\n `[AthenaAdapter] Missing Athena connection details. Set both 'athena.url' and 'athena.apiKey' in config.yaml (or pass 'url'/'apiKey' to athenaAdapter).`,\r\n );\r\n }\r\n\r\n if (!dbClient || version !== lastDbConfigVersion) {\r\n dbClient = createClient(url, apiKey, {\r\n client,\r\n ...(config.headers && { headers: config.headers }),\r\n } as any);\r\n lastDbConfigVersion = version;\r\n }\r\n\r\n return dbClient;\r\n }\r\n\r\n const deps = { ensureDbClient, headers: config.headers };\r\n\r\n return createAdapterFactory({\r\n config: {\r\n adapterId: \"athena\",\r\n adapterName: \"Athena Adapter\",\r\n usePlural: config.usePlural ?? false,\r\n debugLogs: config.debugLogs ?? false,\r\n supportsJSON: true,\r\n supportsDates: true,\r\n supportsBooleans: true,\r\n supportsNumericIds: true,\r\n supportsUUIDs: true,\r\n },\r\n adapter: () => {\r\n return {\r\n create: createMethod(deps),\r\n update: updateMethod(deps),\r\n updateMany: updateManyMethod(deps),\r\n delete: deleteMethod(deps),\r\n deleteMany: deleteManyMethod(deps),\r\n findOne: findOneMethod(deps),\r\n findMany: findManyMethod(deps),\r\n count: countMethod(deps),\r\n };\r\n },\r\n });\r\n};\r\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport YAML from \"yaml\";\r\n\r\nexport type AthenaGlobalConfig = {\r\n athena: {\r\n url: string;\r\n apiKey: string;\r\n client?: string;\r\n };\r\n};\r\n\r\n// Defaults written to `config.yaml` if it doesn't exist.\r\n// These values are intentionally placeholders; the adapter will throw if\r\n// `url`/`apiKey` are still unset when used.\r\nexport const defaultAthenaGlobalConfig: AthenaGlobalConfig = {\r\n athena: {\r\n url: \"https://mirror3.athena-db.com\",\r\n apiKey: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYXV0aGVudGljYXRlZCIsImVtYWlsIjoiZmxvcmlzQHh5bGV4LmFpIiwiZXhwIjoyNDk3MDMzNjY2fQ.LdPqTGaFq5pTokW1DA81WFjmG4nReJCOSKr3mFtXNoA\",\r\n client: \"athena_logging\",\r\n },\r\n};\r\n\r\nexport const DEFAULT_CONFIG_FILENAME = \"config.yaml\";\r\n\r\nfunction resolveConfigPath(configPath?: string): string {\r\n if (configPath) return path.resolve(configPath);\r\n return path.resolve(process.cwd(), DEFAULT_CONFIG_FILENAME);\r\n}\r\n\r\nlet cached: AthenaGlobalConfig | null = null;\r\nlet cachedConfigPath: string | null = null;\r\nlet version = 0;\r\n\r\nlet watcher: fs.FSWatcher | null = null;\r\n\r\nfunction isObject(value: unknown): value is Record<string, unknown> {\r\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction deepMerge<T extends Record<string, unknown>>(\r\n base: T,\r\n partial: unknown,\r\n): T {\r\n if (!isObject(partial)) return base;\r\n const out: Record<string, unknown> = { ...base };\r\n for (const [k, v] of Object.entries(partial)) {\r\n if (v && isObject(v) && isObject(out[k])) {\r\n out[k] = deepMerge(out[k] as Record<string, unknown>, v);\r\n } else {\r\n out[k] = v;\r\n }\r\n }\r\n return out as T;\r\n}\r\n\r\nfunction ensureConfigFile(configPath: string): void {\r\n const dir = path.dirname(configPath);\r\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\r\n\r\n if (!fs.existsSync(configPath)) {\r\n const yaml = YAML.stringify(defaultAthenaGlobalConfig);\r\n fs.writeFileSync(configPath, yaml, \"utf-8\");\r\n }\r\n}\r\n\r\nfunction readConfigFromDisk(configPath: string): AthenaGlobalConfig {\r\n ensureConfigFile(configPath);\r\n const raw = fs.readFileSync(configPath, \"utf-8\");\r\n const parsed = YAML.parse(raw) as unknown;\r\n return deepMerge(defaultAthenaGlobalConfig, parsed);\r\n}\r\n\r\nfunction startWatcher(configPath: string): void {\r\n // Avoid multiple watchers when multiple adapter instances are created.\r\n if (cachedConfigPath !== null && cachedConfigPath !== configPath && watcher) {\r\n try {\r\n watcher.close();\r\n } catch {\r\n // ignore\r\n }\r\n watcher = null;\r\n }\r\n if (watcher || cachedConfigPath === configPath) return;\r\n\r\n try {\r\n watcher = fs.watch(configPath, { persistent: false }, (event) => {\r\n if (event !== \"change\" && event !== \"rename\") return;\r\n try {\r\n cached = readConfigFromDisk(configPath);\r\n version += 1;\r\n } catch {\r\n // Keep last known good config if reload fails.\r\n }\r\n });\r\n cachedConfigPath = configPath;\r\n } catch {\r\n // If watching isn't supported in the environment, just run without it.\r\n }\r\n}\r\n\r\nexport function getAthenaGlobalConfig(options?: {\r\n configPath?: string;\r\n watch?: boolean;\r\n}): { config: AthenaGlobalConfig; version: number } {\r\n const configPath = resolveConfigPath(options?.configPath);\r\n const shouldWatch = options?.watch ?? true;\r\n\r\n if (!cached || cachedConfigPath !== configPath) {\r\n cached = readConfigFromDisk(configPath);\r\n cachedConfigPath = configPath;\r\n version += 1;\r\n }\r\n\r\n if (shouldWatch) startWatcher(configPath);\r\n\r\n return { config: cached, version };\r\n}\r\n","/**\r\n * Shared helpers and types for the Athena adapter.\r\n */\r\n\r\nexport function toSnakeCase(key: string): string {\r\n return key\r\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\r\n .replace(/__/g, \"_\")\r\n .toLowerCase();\r\n}\r\n\r\nexport function toCamelCase(key: string): string {\r\n return key.replace(/_([a-z0-9])/g, (_, ch: string) => ch.toUpperCase());\r\n}\r\n\r\nexport function hasUppercase(key: string): boolean {\r\n return /[A-Z]/.test(key);\r\n}\r\n\r\nexport function mapKeys<T extends Record<string, unknown>>(\r\n obj: T,\r\n mapKey: (k: string) => string,\r\n): Record<string, unknown> {\r\n const out: Record<string, unknown> = {};\r\n for (const [k, v] of Object.entries(obj)) out[mapKey(k)] = v;\r\n return out;\r\n}\r\n\r\nexport function mapRowToBetterAuth<T>(row: T): T {\r\n if (!row || typeof row !== \"object\") return row;\r\n if (Array.isArray(row)) return row.map(mapRowToBetterAuth) as unknown as T;\r\n return mapKeys(row as Record<string, unknown>, toCamelCase) as T;\r\n}\r\n\r\nexport function isLikelyIsoDateString(value: string): boolean {\r\n if (!/^\\d{4}-\\d{2}-\\d{2}T/.test(value)) return false;\r\n const ms = Date.parse(value);\r\n return Number.isFinite(ms);\r\n}\r\n\r\nexport function isTimestampKey(key: string): boolean {\r\n return key.endsWith(\"At\") || key.endsWith(\"_at\") || key === \"expires\";\r\n}\r\n\r\nexport function coerceDateFields<T extends Record<string, unknown>>(data: T): T {\r\n const out: Record<string, unknown> = { ...data };\r\n for (const [key, val] of Object.entries(out)) {\r\n if (val == null) continue;\r\n if (\r\n typeof val === \"string\" &&\r\n isTimestampKey(key) &&\r\n isLikelyIsoDateString(val)\r\n ) {\r\n out[key] = new Date(val);\r\n }\r\n }\r\n return out as T;\r\n}\r\n\r\nexport function toDbRecord<T extends Record<string, unknown>>(\r\n data: T,\r\n): Record<string, unknown> {\r\n const withDbKeys = mapKeys(data, (k) =>\r\n hasUppercase(k) ? toSnakeCase(k) : k,\r\n );\r\n return coerceDateFields(withDbKeys);\r\n}\r\n\r\nexport type AthenaFilterBuilder = {\r\n eq(col: string, val: unknown): AthenaFilterBuilder;\r\n neq(col: string, val: unknown): AthenaFilterBuilder;\r\n gt(col: string, val: unknown): AthenaFilterBuilder;\r\n gte(col: string, val: unknown): AthenaFilterBuilder;\r\n lt(col: string, val: unknown): AthenaFilterBuilder;\r\n lte(col: string, val: unknown): AthenaFilterBuilder;\r\n in(col: string, vals: unknown[]): AthenaFilterBuilder;\r\n not(col: string, op?: string, val?: unknown): AthenaFilterBuilder;\r\n like(col: string, val: string): AthenaFilterBuilder;\r\n delete?(): { select(): Promise<{ data: unknown; error: unknown }> };\r\n select?(columns?: string): Promise<{ data: unknown; error: unknown }> | { select(): Promise<{ data: unknown; error: unknown }> };\r\n};\r\n\r\nexport type WhereClause = { field: string; operator: string; value: unknown };\r\n\r\nconst defaultColumnMapper = (col: string) =>\r\n hasUppercase(col) ? toSnakeCase(col) : col;\r\n\r\nexport function applyWhere(\r\n builder: AthenaFilterBuilder,\r\n field: string,\r\n operator: string,\r\n value: unknown,\r\n columnMapper: (col: string) => string = defaultColumnMapper,\r\n): AthenaFilterBuilder {\r\n const dbField = columnMapper(field);\r\n switch (operator) {\r\n case \"eq\":\r\n return builder.eq(dbField, value);\r\n case \"ne\":\r\n return builder.neq(dbField, value);\r\n case \"gt\":\r\n return builder.gt(dbField, value);\r\n case \"gte\":\r\n return builder.gte(dbField, value);\r\n case \"lt\":\r\n return builder.lt(dbField, value);\r\n case \"lte\":\r\n return builder.lte(dbField, value);\r\n case \"in\":\r\n return builder.in(dbField, value as unknown[]);\r\n case \"not_in\":\r\n return builder.not(dbField, \"in\", value);\r\n case \"contains\":\r\n return builder.like(dbField, `%${value}%`);\r\n case \"starts_with\":\r\n return builder.like(dbField, `${value}%`);\r\n case \"ends_with\":\r\n return builder.like(dbField, `%${value}`);\r\n default:\r\n return builder.eq(dbField, value);\r\n }\r\n}\r\n\r\nexport function isMissingColumnError(error: unknown): boolean {\r\n const msg = String(error ?? \"\");\r\n return (\r\n msg.includes(\"specified column does not exist\") ||\r\n msg.includes(\"column does not exist\")\r\n );\r\n}\r\n\r\n/** True when the Athena gateway returns a success message in the error field (treat as success). */\r\nexport function isSuccessMessageInError(error: unknown): boolean {\r\n const msg = String(error ?? \"\").toLowerCase();\r\n return (\r\n msg === \"data inserted successfully\" ||\r\n msg === \"data updated successfully\" ||\r\n msg === \"data deleted successfully\"\r\n );\r\n}\r\n\r\nexport function snakeMapper(col: string): string {\r\n return hasUppercase(col) ? toSnakeCase(col) : col;\r\n}\r\n\r\nexport function identityMapper(col: string): string {\r\n return col;\r\n}\r\n\r\n/** Get value from row by field name (camelCase or snake_case). */\r\nfunction getRowValue(row: Record<string, unknown>, field: string): unknown {\r\n if (Object.prototype.hasOwnProperty.call(row, field)) return row[field];\r\n const snake = hasUppercase(field) ? toSnakeCase(field) : field;\r\n return row[snake];\r\n}\r\n\r\n/**\r\n * Filter rows in-memory by where clauses (fallback when gateway does not apply filters).\r\n * Supports eq, ne, in, not_in; row keys may be camelCase or snake_case.\r\n */\r\nexport function filterRowsByWhere(\r\n rows: Record<string, unknown>[],\r\n where: WhereClause[],\r\n): Record<string, unknown>[] {\r\n if (!where.length) return rows;\r\n return rows.filter((row) => {\r\n for (const { field, operator, value } of where) {\r\n const rowVal = getRowValue(row, field);\r\n switch (operator) {\r\n case \"eq\":\r\n if (rowVal !== value) return false;\r\n break;\r\n case \"ne\":\r\n if (rowVal === value) return false;\r\n break;\r\n case \"in\":\r\n if (!Array.isArray(value) || !value.includes(rowVal)) return false;\r\n break;\r\n case \"not_in\":\r\n if (Array.isArray(value) && value.includes(rowVal)) return false;\r\n break;\r\n default:\r\n if (rowVal !== value) return false;\r\n }\r\n }\r\n return true;\r\n });\r\n}\r\n","import { toDbRecord, mapRowToBetterAuth, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type CreateDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function createMethod(deps: CreateDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function create<T extends Record<string, unknown>>({\r\n model,\r\n data,\r\n }: {\r\n model: string;\r\n data: T;\r\n select?: string[];\r\n }) {\r\n const db = ensureDbClient();\r\n const insertData = toDbRecord(data);\r\n const { data: result, error } = await db\r\n .from(model)\r\n .insert(insertData)\r\n .select();\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(`[AthenaAdapter] create on \"${model}\" failed: ${error}`);\r\n }\r\n\r\n const row = Array.isArray(result) ? result[0] : result;\r\n return mapRowToBetterAuth((row ?? insertData) as T);\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport {\r\n toDbRecord,\r\n mapRowToBetterAuth,\r\n applyWhere,\r\n isSuccessMessageInError,\r\n} from \"../utils\";\r\n\r\nexport type UpdateDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function updateMethod(deps: UpdateDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function update<T>({\r\n model,\r\n where,\r\n update,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n update: T;\r\n }) {\r\n const db = ensureDbClient();\r\n const updateData = toDbRecord(update as Record<string, unknown>);\r\n const build = (useRetryShape: boolean) => {\r\n // Primary shape: some gateway versions accept back-compat update_body keys.\r\n if (!useRetryShape) {\r\n let b = db\r\n .from(model)\r\n .update({ data: updateData, set: updateData } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n }\r\n\r\n // Retry shape: send the plain update values, but also provide an explicit `updateBody`.\r\n let b = db\r\n .from(model)\r\n .update(updateData, {\r\n updateBody: { data: updateData, set: updateData },\r\n } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n };\r\n\r\n const run = async (b: AthenaFilterBuilder) => {\r\n const { data: result, error } = await (b as any).select();\r\n return { result, error };\r\n };\r\n\r\n const first = await run(build(false));\r\n if (first.error && !isSuccessMessageInError(first.error)) {\r\n const msg = String(first.error);\r\n if (msg.toLowerCase().includes(\"update payload required\")) {\r\n const retry = await run(build(true));\r\n if (retry.error && !isSuccessMessageInError(retry.error)) {\r\n throw new Error(\r\n `[AthenaAdapter] update on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n const row = Array.isArray(retry.result)\r\n ? (retry.result[0] as unknown)\r\n : (retry.result as unknown);\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n }\r\n\r\n throw new Error(`[AthenaAdapter] update on \"${model}\" failed: ${first.error}`);\r\n }\r\n\r\n const row = Array.isArray(first.result)\r\n ? (first.result[0] as unknown)\r\n : (first.result as unknown);\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { toDbRecord, applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type UpdateManyDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function updateManyMethod(deps: UpdateManyDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function updateMany({\r\n model,\r\n where,\r\n update,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n update: Record<string, unknown>;\r\n }) {\r\n const db = ensureDbClient();\r\n const updateData = toDbRecord(update);\r\n const build = (useRetryShape: boolean) => {\r\n if (!useRetryShape) {\r\n let b = db\r\n .from(model)\r\n .update({ data: updateData, set: updateData } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n }\r\n\r\n let b = db\r\n .from(model)\r\n .update(updateData, {\r\n updateBody: { data: updateData, set: updateData },\r\n } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n };\r\n\r\n const run = async (b: AthenaFilterBuilder) => {\r\n const { data: result, error } = await (b as any).select();\r\n return { result, error };\r\n };\r\n\r\n const first = await run(build(false));\r\n if (first.error && !isSuccessMessageInError(first.error)) {\r\n const msg = String(first.error);\r\n if (msg.toLowerCase().includes(\"update payload required\")) {\r\n const retry = await run(build(true));\r\n if (retry.error && !isSuccessMessageInError(retry.error)) {\r\n throw new Error(\r\n `[AthenaAdapter] updateMany on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n return Array.isArray(retry.result) ? retry.result.length : retry.result ? 1 : 0;\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] updateMany on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n return Array.isArray(first.result) ? first.result.length : first.result ? 1 : 0;\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type DeleteDeps = {\r\n ensureDbClient: () => any;\r\n headers?: Record<string, string>;\r\n};\r\n\r\nexport function deleteMethod(deps: DeleteDeps) {\r\n const { ensureDbClient, headers } = deps;\r\n\r\n return async function del({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n let builder = db.from(model) as AthenaFilterBuilder;\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n );\r\n }\r\n\r\n const { error } = await (builder as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n );\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(\r\n `[AthenaAdapter] delete on \"${model}\" failed: ${error}`,\r\n );\r\n }\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type DeleteManyDeps = {\r\n ensureDbClient: () => any;\r\n headers?: Record<string, string>;\r\n};\r\n\r\nexport function deleteManyMethod(deps: DeleteManyDeps) {\r\n const { ensureDbClient, headers } = deps;\r\n\r\n return async function deleteMany({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n const mainBuilder = db.from(model) as AthenaFilterBuilder;\r\n let builder = mainBuilder;\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n );\r\n }\r\n\r\n const { data: result, error } = await (builder as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n ).select();\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(\r\n `[AthenaAdapter] deleteMany on \"${model}\" failed: ${error}`,\r\n );\r\n }\r\n\r\n const deletedCount = Array.isArray(result) ? result.length : result ? 1 : 0;\r\n // Fallback: if the live gateway doesn't apply `in` conditions correctly,\r\n // delete rows one-by-one so counts are stable for e2e tests.\r\n const inClause = where.find(\r\n (c) => c.operator === \"in\" && c.value != null,\r\n );\r\n if (\r\n inClause &&\r\n Array.isArray(inClause.value) &&\r\n deletedCount < inClause.value.length\r\n ) {\r\n let n = 0;\r\n for (const v of inClause.value) {\r\n const b = db.from(model);\r\n const filtered = applyWhere(\r\n b as any,\r\n inClause.field,\r\n \"eq\",\r\n v,\r\n );\r\n const { data: rowData, error: rowErr } = await (filtered as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n ).select();\r\n if (rowErr && isSuccessMessageInError(rowErr)) continue;\r\n n += Array.isArray(rowData) ? rowData.length : rowData ? 1 : 0;\r\n }\r\n return n;\r\n }\r\n\r\n return deletedCount;\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n mapRowToBetterAuth,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n filterRowsByWhere,\r\n} from \"../utils\";\r\n\r\nexport type FindOneDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function findOneMethod(deps: FindOneDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function findOne<T>({\r\n model,\r\n where,\r\n select,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n select?: string[];\r\n join?: unknown;\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (columnMapper: (col: string) => string) => {\r\n const columns =\r\n select && select.length > 0\r\n ? select.map((c) => columnMapper(c)).join(\", \")\r\n : undefined;\r\n\r\n let builder = db.from(model).select(columns);\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n\r\n const { data: result, error } = await builder.limit(1);\r\n return { result, error };\r\n };\r\n\r\n const first = await run(snakeMapper);\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] findOne on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n\r\n const rows = Array.isArray(retry.result)\r\n ? retry.result\r\n : retry.result\r\n ? [retry.result]\r\n : [];\r\n const row = rows[0] ?? null;\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] findOne on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n const rows = Array.isArray(first.result)\r\n ? first.result\r\n : first.result\r\n ? [first.result]\r\n : [];\r\n const row = rows[0] ?? null;\r\n if (!row) return null;\r\n\r\n const mapped = mapRowToBetterAuth(row as T) as T;\r\n const filtered = filterRowsByWhere(\r\n [mapped as unknown as Record<string, unknown>],\r\n where,\r\n );\r\n return (filtered[0] ? mapped : null) as T | null;\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n mapRowToBetterAuth,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n filterRowsByWhere,\r\n} from \"../utils\";\r\n\r\nexport type FindManyDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function findManyMethod(deps: FindManyDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n const isTransientGatewayError = (error: unknown): boolean => {\r\n const message = String(error ?? \"\").toLowerCase();\r\n return (\r\n message.includes(\"application failed to respond\") ||\r\n message.includes(\"timeout\") ||\r\n message.includes(\"timed out\") ||\r\n message.includes(\"gateway timeout\") ||\r\n message.includes(\"econnreset\") ||\r\n message.includes(\"connection reset\")\r\n );\r\n };\r\n\r\n return async function findMany<T>({\r\n model,\r\n where,\r\n limit,\r\n sortBy,\r\n offset,\r\n select,\r\n }: {\r\n model: string;\r\n where?: WhereClause[];\r\n limit: number;\r\n select?: string[];\r\n sortBy?: { field: string; direction: \"asc\" | \"desc\" };\r\n offset?: number;\r\n join?: unknown;\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (\r\n columnMapper: (col: string) => string,\r\n opts?: { skipWhere?: boolean; limitOverride?: number; offsetOverride?: number },\r\n ) => {\r\n const columns =\r\n select && select.length > 0\r\n ? select.map((c) => columnMapper(c)).join(\", \")\r\n : undefined;\r\n\r\n let builder = db.from(model).select(columns);\r\n\r\n if (!opts?.skipWhere && where) {\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n }\r\n\r\n const effectiveLimit = opts?.limitOverride ?? limit;\r\n const effectiveOffset = opts?.offsetOverride ?? offset;\r\n\r\n if (effectiveLimit !== undefined) {\r\n builder = builder.limit(effectiveLimit);\r\n }\r\n\r\n if (effectiveOffset !== undefined) {\r\n builder = builder.offset(effectiveOffset);\r\n }\r\n\r\n const { data: result, error } = await builder;\r\n return { result, error };\r\n };\r\n\r\n let first = await run(snakeMapper);\r\n if (first.error && isTransientGatewayError(first.error)) {\r\n const retry = await run(snakeMapper);\r\n if (!retry.error) first = retry;\r\n }\r\n\r\n const pickRows = (res: unknown) =>\r\n (Array.isArray(res) ? res : []) as Record<string, unknown>[];\r\n\r\n const applySort = (rows: T[]) => {\r\n if (!sortBy) return rows;\r\n const sortField = sortBy.field;\r\n rows.sort((a, b) => {\r\n const aVal = (a as Record<string, unknown>)[sortField];\r\n const bVal = (b as Record<string, unknown>)[sortField];\r\n if (aVal == null && bVal == null) return 0;\r\n if (aVal == null) return sortBy.direction === \"asc\" ? -1 : 1;\r\n if (bVal == null) return sortBy.direction === \"asc\" ? 1 : -1;\r\n const cmp =\r\n typeof aVal === \"string\" && typeof bVal === \"string\"\r\n ? aVal.localeCompare(bVal)\r\n : aVal < bVal\r\n ? -1\r\n : aVal > bVal\r\n ? 1\r\n : 0;\r\n return sortBy.direction === \"asc\" ? cmp : -cmp;\r\n });\r\n return rows;\r\n };\r\n\r\n const mapAndSort = (rows: Record<string, unknown>[]) => {\r\n const betterAuthRows = rows.map((r) => mapRowToBetterAuth(r)) as unknown as T[];\r\n\r\n if (!where?.length) return applySort(betterAuthRows);\r\n\r\n const filtered = filterRowsByWhere(\r\n betterAuthRows as unknown as Record<string, unknown>[],\r\n where,\r\n ) as unknown as T[];\r\n\r\n // If filtering changed the row set, the gateway likely ignored `where`\r\n // (or applied it before limiting/offset). In that case, re-apply sorting\r\n // and slice using the requested offset/limit.\r\n if (filtered.length !== betterAuthRows.length) {\r\n const off = offset ?? 0;\r\n const end = limit !== undefined ? off + limit : undefined;\r\n return applySort(filtered).slice(off, end);\r\n }\r\n\r\n return applySort(filtered);\r\n };\r\n\r\n const postFilterAndSlice = (rows: Record<string, unknown>[]) => {\r\n const mappedSorted = mapAndSort(rows);\r\n const off = offset ?? 0;\r\n const end = limit !== undefined ? off + limit : undefined;\r\n return mappedSorted.slice(off, end);\r\n };\r\n\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] findMany on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n const retryRows = pickRows(retry.result);\r\n // Decisive fallback: if gateway-side `where` yields empty/insufficient rows,\r\n // fetch a broader candidate set and apply `where`/sort/offset/limit in-memory.\r\n if (where?.length) {\r\n const broad = await run(identityMapper, {\r\n skipWhere: true,\r\n limitOverride: Math.max((offset ?? 0) + (limit ?? 0) + 500, 5000),\r\n offsetOverride: 0,\r\n });\r\n if (!broad.error) return postFilterAndSlice(pickRows(broad.result));\r\n }\r\n return mapAndSort(retryRows);\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] findMany on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n const firstRows = pickRows(first.result);\r\n if (where?.length) {\r\n const broad = await run(snakeMapper, {\r\n skipWhere: true,\r\n limitOverride: Math.max((offset ?? 0) + (limit ?? 0) + 500, 5000),\r\n offsetOverride: 0,\r\n });\r\n if (!broad.error) return postFilterAndSlice(pickRows(broad.result));\r\n }\r\n return mapAndSort(firstRows);\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n} from \"../utils\";\r\n\r\nexport type CountDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function countMethod(deps: CountDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function count({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where?: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (columnMapper: (col: string) => string) => {\r\n let builder = db.from(model).select();\r\n\r\n if (where) {\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n }\r\n\r\n const { data: result, error } = await builder;\r\n return { result, error };\r\n };\r\n\r\n const first = await run(snakeMapper);\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] count on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n return Array.isArray(retry.result) ? retry.result.length : 0;\r\n }\r\n throw new Error(\r\n `[AthenaAdapter] count on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n return Array.isArray(first.result) ? first.result.length : 0;\r\n };\r\n}\r\n"],"mappings":"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","names":["path","fs","YAML","b","row","b","rows","row","version"]}
|
package/dist/index.js
CHANGED
|
@@ -461,6 +461,10 @@ function findOneMethod(deps) {
|
|
|
461
461
|
// src/methods/find-many.ts
|
|
462
462
|
function findManyMethod(deps) {
|
|
463
463
|
const { ensureDbClient } = deps;
|
|
464
|
+
const isTransientGatewayError = (error) => {
|
|
465
|
+
const message = String(error ?? "").toLowerCase();
|
|
466
|
+
return message.includes("application failed to respond") || message.includes("timeout") || message.includes("timed out") || message.includes("gateway timeout") || message.includes("econnreset") || message.includes("connection reset");
|
|
467
|
+
};
|
|
464
468
|
return async function findMany({
|
|
465
469
|
model,
|
|
466
470
|
where,
|
|
@@ -495,7 +499,11 @@ function findManyMethod(deps) {
|
|
|
495
499
|
const { data: result, error } = await builder;
|
|
496
500
|
return { result, error };
|
|
497
501
|
};
|
|
498
|
-
|
|
502
|
+
let first = await run(snakeMapper);
|
|
503
|
+
if (first.error && isTransientGatewayError(first.error)) {
|
|
504
|
+
const retry = await run(snakeMapper);
|
|
505
|
+
if (!retry.error) first = retry;
|
|
506
|
+
}
|
|
499
507
|
const pickRows = (res) => Array.isArray(res) ? res : [];
|
|
500
508
|
const applySort = (rows) => {
|
|
501
509
|
if (!sortBy) return rows;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/utils.ts","../src/methods/create.ts","../src/methods/update.ts","../src/methods/update-many.ts","../src/methods/delete.ts","../src/methods/delete-many.ts","../src/methods/find-one.ts","../src/methods/find-many.ts","../src/methods/count.ts"],"sourcesContent":["import {\r\n createAdapterFactory,\r\n type AdapterFactory,\r\n type DBAdapterDebugLogOption,\r\n} from \"better-auth/adapters\";\r\nimport type { BetterAuthOptions } from \"better-auth\";\r\nimport { createClient } from \"@xylex-group/athena\";\r\nimport { getAthenaGlobalConfig } from \"./config\";\r\nimport { createMethod } from \"./methods/create\";\r\nimport { updateMethod } from \"./methods/update\";\r\nimport { updateManyMethod } from \"./methods/update-many\";\r\nimport { deleteMethod } from \"./methods/delete\";\r\nimport { deleteManyMethod } from \"./methods/delete-many\";\r\nimport { findOneMethod } from \"./methods/find-one\";\r\nimport { findManyMethod } from \"./methods/find-many\";\r\nimport { countMethod } from \"./methods/count\";\r\n\r\n/**\r\n * Configuration options for the Athena adapter.\r\n */\r\nexport interface AthenaAdapterConfig {\r\n /**\r\n * The URL of your Athena gateway.\r\n */\r\n url?: string;\r\n /**\r\n * The API key for authenticating with the Athena gateway.\r\n */\r\n apiKey?: string;\r\n /**\r\n * The client name sent in requests to the Athena gateway.\r\n */\r\n client?: string;\r\n\r\n /**\r\n * Optional override for the YAML config path.\r\n * Defaults to `./config.yaml` (resolved from `process.cwd()`).\r\n */\r\n configPath?: string;\r\n\r\n /**\r\n * When enabled, the adapter will reload `config.yaml` on changes.\r\n *\r\n * @default true\r\n */\r\n watchConfig?: boolean;\r\n /**\r\n * Helps you debug issues with the adapter.\r\n */\r\n debugLogs?: DBAdapterDebugLogOption;\r\n /**\r\n * If the table names in the schema are plural.\r\n *\r\n * @default false\r\n */\r\n usePlural?: boolean;\r\n\r\n /**\r\n * Optional headers sent with every request (e.g. `X-User-Id` if your gateway requires it for delete).\r\n */\r\n headers?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * Create a Better-Auth database adapter backed by @xylex-group/athena.\r\n *\r\n * Column names are kept in snake_case as required by the Athena gateway.\r\n *\r\n * @example\r\n * ```ts\r\n * import { betterAuth } from \"better-auth\";\r\n * import { athenaAdapter } from \"better-auth-athena\";\r\n *\r\n * export const auth = betterAuth({\r\n * database: athenaAdapter({\r\n * url: process.env.ATHENA_URL!,\r\n * apiKey: process.env.ATHENA_API_KEY!,\r\n * client: \"my-app\",\r\n * }),\r\n * });\r\n * ```\r\n */\r\nexport const athenaAdapter = (\r\n config: AthenaAdapterConfig,\r\n): AdapterFactory<BetterAuthOptions> => {\r\n let dbClient: any | null = null;\r\n let lastDbConfigVersion = -1;\r\n\r\n const shouldUseFixedConfig =\r\n typeof config.url === \"string\" &&\r\n config.url.length > 0 &&\r\n typeof config.apiKey === \"string\" &&\r\n config.apiKey.length > 0;\r\n\r\n function ensureDbClient(): any {\r\n if (shouldUseFixedConfig) {\r\n if (!dbClient) {\r\n dbClient = createClient(config.url!, config.apiKey!, {\r\n client: config.client,\r\n ...(config.headers && { headers: config.headers }),\r\n } as any);\r\n }\r\n return dbClient;\r\n }\r\n\r\n const { config: globalConfig, version } = getAthenaGlobalConfig({\r\n configPath: config.configPath,\r\n watch: config.watchConfig ?? true,\r\n });\r\n\r\n const url = config.url ?? globalConfig.athena.url;\r\n const apiKey = config.apiKey ?? globalConfig.athena.apiKey;\r\n const client = config.client ?? globalConfig.athena.client;\r\n\r\n if (!url || !apiKey) {\r\n throw new Error(\r\n `[AthenaAdapter] Missing Athena connection details. Set both 'athena.url' and 'athena.apiKey' in config.yaml (or pass 'url'/'apiKey' to athenaAdapter).`,\r\n );\r\n }\r\n\r\n if (!dbClient || version !== lastDbConfigVersion) {\r\n dbClient = createClient(url, apiKey, {\r\n client,\r\n ...(config.headers && { headers: config.headers }),\r\n } as any);\r\n lastDbConfigVersion = version;\r\n }\r\n\r\n return dbClient;\r\n }\r\n\r\n const deps = { ensureDbClient, headers: config.headers };\r\n\r\n return createAdapterFactory({\r\n config: {\r\n adapterId: \"athena\",\r\n adapterName: \"Athena Adapter\",\r\n usePlural: config.usePlural ?? false,\r\n debugLogs: config.debugLogs ?? false,\r\n supportsJSON: true,\r\n supportsDates: true,\r\n supportsBooleans: true,\r\n supportsNumericIds: true,\r\n supportsUUIDs: true,\r\n },\r\n adapter: () => {\r\n return {\r\n create: createMethod(deps),\r\n update: updateMethod(deps),\r\n updateMany: updateManyMethod(deps),\r\n delete: deleteMethod(deps),\r\n deleteMany: deleteManyMethod(deps),\r\n findOne: findOneMethod(deps),\r\n findMany: findManyMethod(deps),\r\n count: countMethod(deps),\r\n };\r\n },\r\n });\r\n};\r\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport YAML from \"yaml\";\r\n\r\nexport type AthenaGlobalConfig = {\r\n athena: {\r\n url: string;\r\n apiKey: string;\r\n client?: string;\r\n };\r\n};\r\n\r\n// Defaults written to `config.yaml` if it doesn't exist.\r\n// These values are intentionally placeholders; the adapter will throw if\r\n// `url`/`apiKey` are still unset when used.\r\nexport const defaultAthenaGlobalConfig: AthenaGlobalConfig = {\r\n athena: {\r\n url: \"https://mirror3.athena-db.com\",\r\n apiKey: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYXV0aGVudGljYXRlZCIsImVtYWlsIjoiZmxvcmlzQHh5bGV4LmFpIiwiZXhwIjoyNDk3MDMzNjY2fQ.LdPqTGaFq5pTokW1DA81WFjmG4nReJCOSKr3mFtXNoA\",\r\n client: \"athena_logging\",\r\n },\r\n};\r\n\r\nexport const DEFAULT_CONFIG_FILENAME = \"config.yaml\";\r\n\r\nfunction resolveConfigPath(configPath?: string): string {\r\n if (configPath) return path.resolve(configPath);\r\n return path.resolve(process.cwd(), DEFAULT_CONFIG_FILENAME);\r\n}\r\n\r\nlet cached: AthenaGlobalConfig | null = null;\r\nlet cachedConfigPath: string | null = null;\r\nlet version = 0;\r\n\r\nlet watcher: fs.FSWatcher | null = null;\r\n\r\nfunction isObject(value: unknown): value is Record<string, unknown> {\r\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction deepMerge<T extends Record<string, unknown>>(\r\n base: T,\r\n partial: unknown,\r\n): T {\r\n if (!isObject(partial)) return base;\r\n const out: Record<string, unknown> = { ...base };\r\n for (const [k, v] of Object.entries(partial)) {\r\n if (v && isObject(v) && isObject(out[k])) {\r\n out[k] = deepMerge(out[k] as Record<string, unknown>, v);\r\n } else {\r\n out[k] = v;\r\n }\r\n }\r\n return out as T;\r\n}\r\n\r\nfunction ensureConfigFile(configPath: string): void {\r\n const dir = path.dirname(configPath);\r\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\r\n\r\n if (!fs.existsSync(configPath)) {\r\n const yaml = YAML.stringify(defaultAthenaGlobalConfig);\r\n fs.writeFileSync(configPath, yaml, \"utf-8\");\r\n }\r\n}\r\n\r\nfunction readConfigFromDisk(configPath: string): AthenaGlobalConfig {\r\n ensureConfigFile(configPath);\r\n const raw = fs.readFileSync(configPath, \"utf-8\");\r\n const parsed = YAML.parse(raw) as unknown;\r\n return deepMerge(defaultAthenaGlobalConfig, parsed);\r\n}\r\n\r\nfunction startWatcher(configPath: string): void {\r\n // Avoid multiple watchers when multiple adapter instances are created.\r\n if (cachedConfigPath !== null && cachedConfigPath !== configPath && watcher) {\r\n try {\r\n watcher.close();\r\n } catch {\r\n // ignore\r\n }\r\n watcher = null;\r\n }\r\n if (watcher || cachedConfigPath === configPath) return;\r\n\r\n try {\r\n watcher = fs.watch(configPath, { persistent: false }, (event) => {\r\n if (event !== \"change\" && event !== \"rename\") return;\r\n try {\r\n cached = readConfigFromDisk(configPath);\r\n version += 1;\r\n } catch {\r\n // Keep last known good config if reload fails.\r\n }\r\n });\r\n cachedConfigPath = configPath;\r\n } catch {\r\n // If watching isn't supported in the environment, just run without it.\r\n }\r\n}\r\n\r\nexport function getAthenaGlobalConfig(options?: {\r\n configPath?: string;\r\n watch?: boolean;\r\n}): { config: AthenaGlobalConfig; version: number } {\r\n const configPath = resolveConfigPath(options?.configPath);\r\n const shouldWatch = options?.watch ?? true;\r\n\r\n if (!cached || cachedConfigPath !== configPath) {\r\n cached = readConfigFromDisk(configPath);\r\n cachedConfigPath = configPath;\r\n version += 1;\r\n }\r\n\r\n if (shouldWatch) startWatcher(configPath);\r\n\r\n return { config: cached, version };\r\n}\r\n","/**\r\n * Shared helpers and types for the Athena adapter.\r\n */\r\n\r\nexport function toSnakeCase(key: string): string {\r\n return key\r\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\r\n .replace(/__/g, \"_\")\r\n .toLowerCase();\r\n}\r\n\r\nexport function toCamelCase(key: string): string {\r\n return key.replace(/_([a-z0-9])/g, (_, ch: string) => ch.toUpperCase());\r\n}\r\n\r\nexport function hasUppercase(key: string): boolean {\r\n return /[A-Z]/.test(key);\r\n}\r\n\r\nexport function mapKeys<T extends Record<string, unknown>>(\r\n obj: T,\r\n mapKey: (k: string) => string,\r\n): Record<string, unknown> {\r\n const out: Record<string, unknown> = {};\r\n for (const [k, v] of Object.entries(obj)) out[mapKey(k)] = v;\r\n return out;\r\n}\r\n\r\nexport function mapRowToBetterAuth<T>(row: T): T {\r\n if (!row || typeof row !== \"object\") return row;\r\n if (Array.isArray(row)) return row.map(mapRowToBetterAuth) as unknown as T;\r\n return mapKeys(row as Record<string, unknown>, toCamelCase) as T;\r\n}\r\n\r\nexport function isLikelyIsoDateString(value: string): boolean {\r\n if (!/^\\d{4}-\\d{2}-\\d{2}T/.test(value)) return false;\r\n const ms = Date.parse(value);\r\n return Number.isFinite(ms);\r\n}\r\n\r\nexport function isTimestampKey(key: string): boolean {\r\n return key.endsWith(\"At\") || key.endsWith(\"_at\") || key === \"expires\";\r\n}\r\n\r\nexport function coerceDateFields<T extends Record<string, unknown>>(data: T): T {\r\n const out: Record<string, unknown> = { ...data };\r\n for (const [key, val] of Object.entries(out)) {\r\n if (val == null) continue;\r\n if (\r\n typeof val === \"string\" &&\r\n isTimestampKey(key) &&\r\n isLikelyIsoDateString(val)\r\n ) {\r\n out[key] = new Date(val);\r\n }\r\n }\r\n return out as T;\r\n}\r\n\r\nexport function toDbRecord<T extends Record<string, unknown>>(\r\n data: T,\r\n): Record<string, unknown> {\r\n const withDbKeys = mapKeys(data, (k) =>\r\n hasUppercase(k) ? toSnakeCase(k) : k,\r\n );\r\n return coerceDateFields(withDbKeys);\r\n}\r\n\r\nexport type AthenaFilterBuilder = {\r\n eq(col: string, val: unknown): AthenaFilterBuilder;\r\n neq(col: string, val: unknown): AthenaFilterBuilder;\r\n gt(col: string, val: unknown): AthenaFilterBuilder;\r\n gte(col: string, val: unknown): AthenaFilterBuilder;\r\n lt(col: string, val: unknown): AthenaFilterBuilder;\r\n lte(col: string, val: unknown): AthenaFilterBuilder;\r\n in(col: string, vals: unknown[]): AthenaFilterBuilder;\r\n not(col: string, op?: string, val?: unknown): AthenaFilterBuilder;\r\n like(col: string, val: string): AthenaFilterBuilder;\r\n delete?(): { select(): Promise<{ data: unknown; error: unknown }> };\r\n select?(columns?: string): Promise<{ data: unknown; error: unknown }> | { select(): Promise<{ data: unknown; error: unknown }> };\r\n};\r\n\r\nexport type WhereClause = { field: string; operator: string; value: unknown };\r\n\r\nconst defaultColumnMapper = (col: string) =>\r\n hasUppercase(col) ? toSnakeCase(col) : col;\r\n\r\nexport function applyWhere(\r\n builder: AthenaFilterBuilder,\r\n field: string,\r\n operator: string,\r\n value: unknown,\r\n columnMapper: (col: string) => string = defaultColumnMapper,\r\n): AthenaFilterBuilder {\r\n const dbField = columnMapper(field);\r\n switch (operator) {\r\n case \"eq\":\r\n return builder.eq(dbField, value);\r\n case \"ne\":\r\n return builder.neq(dbField, value);\r\n case \"gt\":\r\n return builder.gt(dbField, value);\r\n case \"gte\":\r\n return builder.gte(dbField, value);\r\n case \"lt\":\r\n return builder.lt(dbField, value);\r\n case \"lte\":\r\n return builder.lte(dbField, value);\r\n case \"in\":\r\n return builder.in(dbField, value as unknown[]);\r\n case \"not_in\":\r\n return builder.not(dbField, \"in\", value);\r\n case \"contains\":\r\n return builder.like(dbField, `%${value}%`);\r\n case \"starts_with\":\r\n return builder.like(dbField, `${value}%`);\r\n case \"ends_with\":\r\n return builder.like(dbField, `%${value}`);\r\n default:\r\n return builder.eq(dbField, value);\r\n }\r\n}\r\n\r\nexport function isMissingColumnError(error: unknown): boolean {\r\n const msg = String(error ?? \"\");\r\n return (\r\n msg.includes(\"specified column does not exist\") ||\r\n msg.includes(\"column does not exist\")\r\n );\r\n}\r\n\r\n/** True when the Athena gateway returns a success message in the error field (treat as success). */\r\nexport function isSuccessMessageInError(error: unknown): boolean {\r\n const msg = String(error ?? \"\").toLowerCase();\r\n return (\r\n msg === \"data inserted successfully\" ||\r\n msg === \"data updated successfully\" ||\r\n msg === \"data deleted successfully\"\r\n );\r\n}\r\n\r\nexport function snakeMapper(col: string): string {\r\n return hasUppercase(col) ? toSnakeCase(col) : col;\r\n}\r\n\r\nexport function identityMapper(col: string): string {\r\n return col;\r\n}\r\n\r\n/** Get value from row by field name (camelCase or snake_case). */\r\nfunction getRowValue(row: Record<string, unknown>, field: string): unknown {\r\n if (Object.prototype.hasOwnProperty.call(row, field)) return row[field];\r\n const snake = hasUppercase(field) ? toSnakeCase(field) : field;\r\n return row[snake];\r\n}\r\n\r\n/**\r\n * Filter rows in-memory by where clauses (fallback when gateway does not apply filters).\r\n * Supports eq, ne, in, not_in; row keys may be camelCase or snake_case.\r\n */\r\nexport function filterRowsByWhere(\r\n rows: Record<string, unknown>[],\r\n where: WhereClause[],\r\n): Record<string, unknown>[] {\r\n if (!where.length) return rows;\r\n return rows.filter((row) => {\r\n for (const { field, operator, value } of where) {\r\n const rowVal = getRowValue(row, field);\r\n switch (operator) {\r\n case \"eq\":\r\n if (rowVal !== value) return false;\r\n break;\r\n case \"ne\":\r\n if (rowVal === value) return false;\r\n break;\r\n case \"in\":\r\n if (!Array.isArray(value) || !value.includes(rowVal)) return false;\r\n break;\r\n case \"not_in\":\r\n if (Array.isArray(value) && value.includes(rowVal)) return false;\r\n break;\r\n default:\r\n if (rowVal !== value) return false;\r\n }\r\n }\r\n return true;\r\n });\r\n}\r\n","import { toDbRecord, mapRowToBetterAuth, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type CreateDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function createMethod(deps: CreateDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function create<T extends Record<string, unknown>>({\r\n model,\r\n data,\r\n }: {\r\n model: string;\r\n data: T;\r\n select?: string[];\r\n }) {\r\n const db = ensureDbClient();\r\n const insertData = toDbRecord(data);\r\n const { data: result, error } = await db\r\n .from(model)\r\n .insert(insertData)\r\n .select();\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(`[AthenaAdapter] create on \"${model}\" failed: ${error}`);\r\n }\r\n\r\n const row = Array.isArray(result) ? result[0] : result;\r\n return mapRowToBetterAuth((row ?? insertData) as T);\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport {\r\n toDbRecord,\r\n mapRowToBetterAuth,\r\n applyWhere,\r\n isSuccessMessageInError,\r\n} from \"../utils\";\r\n\r\nexport type UpdateDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function updateMethod(deps: UpdateDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function update<T>({\r\n model,\r\n where,\r\n update,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n update: T;\r\n }) {\r\n const db = ensureDbClient();\r\n const updateData = toDbRecord(update as Record<string, unknown>);\r\n const build = (useRetryShape: boolean) => {\r\n // Primary shape: some gateway versions accept back-compat update_body keys.\r\n if (!useRetryShape) {\r\n let b = db\r\n .from(model)\r\n .update({ data: updateData, set: updateData } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n }\r\n\r\n // Retry shape: send the plain update values, but also provide an explicit `updateBody`.\r\n let b = db\r\n .from(model)\r\n .update(updateData, {\r\n updateBody: { data: updateData, set: updateData },\r\n } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n };\r\n\r\n const run = async (b: AthenaFilterBuilder) => {\r\n const { data: result, error } = await (b as any).select();\r\n return { result, error };\r\n };\r\n\r\n const first = await run(build(false));\r\n if (first.error && !isSuccessMessageInError(first.error)) {\r\n const msg = String(first.error);\r\n if (msg.toLowerCase().includes(\"update payload required\")) {\r\n const retry = await run(build(true));\r\n if (retry.error && !isSuccessMessageInError(retry.error)) {\r\n throw new Error(\r\n `[AthenaAdapter] update on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n const row = Array.isArray(retry.result)\r\n ? (retry.result[0] as unknown)\r\n : (retry.result as unknown);\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n }\r\n\r\n throw new Error(`[AthenaAdapter] update on \"${model}\" failed: ${first.error}`);\r\n }\r\n\r\n const row = Array.isArray(first.result)\r\n ? (first.result[0] as unknown)\r\n : (first.result as unknown);\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { toDbRecord, applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type UpdateManyDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function updateManyMethod(deps: UpdateManyDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function updateMany({\r\n model,\r\n where,\r\n update,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n update: Record<string, unknown>;\r\n }) {\r\n const db = ensureDbClient();\r\n const updateData = toDbRecord(update);\r\n const build = (useRetryShape: boolean) => {\r\n if (!useRetryShape) {\r\n let b = db\r\n .from(model)\r\n .update({ data: updateData, set: updateData } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n }\r\n\r\n let b = db\r\n .from(model)\r\n .update(updateData, {\r\n updateBody: { data: updateData, set: updateData },\r\n } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n };\r\n\r\n const run = async (b: AthenaFilterBuilder) => {\r\n const { data: result, error } = await (b as any).select();\r\n return { result, error };\r\n };\r\n\r\n const first = await run(build(false));\r\n if (first.error && !isSuccessMessageInError(first.error)) {\r\n const msg = String(first.error);\r\n if (msg.toLowerCase().includes(\"update payload required\")) {\r\n const retry = await run(build(true));\r\n if (retry.error && !isSuccessMessageInError(retry.error)) {\r\n throw new Error(\r\n `[AthenaAdapter] updateMany on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n return Array.isArray(retry.result) ? retry.result.length : retry.result ? 1 : 0;\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] updateMany on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n return Array.isArray(first.result) ? first.result.length : first.result ? 1 : 0;\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type DeleteDeps = {\r\n ensureDbClient: () => any;\r\n headers?: Record<string, string>;\r\n};\r\n\r\nexport function deleteMethod(deps: DeleteDeps) {\r\n const { ensureDbClient, headers } = deps;\r\n\r\n return async function del({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n let builder = db.from(model) as AthenaFilterBuilder;\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n );\r\n }\r\n\r\n const { error } = await (builder as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n );\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(\r\n `[AthenaAdapter] delete on \"${model}\" failed: ${error}`,\r\n );\r\n }\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type DeleteManyDeps = {\r\n ensureDbClient: () => any;\r\n headers?: Record<string, string>;\r\n};\r\n\r\nexport function deleteManyMethod(deps: DeleteManyDeps) {\r\n const { ensureDbClient, headers } = deps;\r\n\r\n return async function deleteMany({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n const mainBuilder = db.from(model) as AthenaFilterBuilder;\r\n let builder = mainBuilder;\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n );\r\n }\r\n\r\n const { data: result, error } = await (builder as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n ).select();\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(\r\n `[AthenaAdapter] deleteMany on \"${model}\" failed: ${error}`,\r\n );\r\n }\r\n\r\n const deletedCount = Array.isArray(result) ? result.length : result ? 1 : 0;\r\n // Fallback: if the live gateway doesn't apply `in` conditions correctly,\r\n // delete rows one-by-one so counts are stable for e2e tests.\r\n const inClause = where.find(\r\n (c) => c.operator === \"in\" && c.value != null,\r\n );\r\n if (\r\n inClause &&\r\n Array.isArray(inClause.value) &&\r\n deletedCount < inClause.value.length\r\n ) {\r\n let n = 0;\r\n for (const v of inClause.value) {\r\n const b = db.from(model);\r\n const filtered = applyWhere(\r\n b as any,\r\n inClause.field,\r\n \"eq\",\r\n v,\r\n );\r\n const { data: rowData, error: rowErr } = await (filtered as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n ).select();\r\n if (rowErr && isSuccessMessageInError(rowErr)) continue;\r\n n += Array.isArray(rowData) ? rowData.length : rowData ? 1 : 0;\r\n }\r\n return n;\r\n }\r\n\r\n return deletedCount;\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n mapRowToBetterAuth,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n filterRowsByWhere,\r\n} from \"../utils\";\r\n\r\nexport type FindOneDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function findOneMethod(deps: FindOneDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function findOne<T>({\r\n model,\r\n where,\r\n select,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n select?: string[];\r\n join?: unknown;\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (columnMapper: (col: string) => string) => {\r\n const columns =\r\n select && select.length > 0\r\n ? select.map((c) => columnMapper(c)).join(\", \")\r\n : undefined;\r\n\r\n let builder = db.from(model).select(columns);\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n\r\n const { data: result, error } = await builder.limit(1);\r\n return { result, error };\r\n };\r\n\r\n const first = await run(snakeMapper);\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] findOne on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n\r\n const rows = Array.isArray(retry.result)\r\n ? retry.result\r\n : retry.result\r\n ? [retry.result]\r\n : [];\r\n const row = rows[0] ?? null;\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] findOne on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n const rows = Array.isArray(first.result)\r\n ? first.result\r\n : first.result\r\n ? [first.result]\r\n : [];\r\n const row = rows[0] ?? null;\r\n if (!row) return null;\r\n\r\n const mapped = mapRowToBetterAuth(row as T) as T;\r\n const filtered = filterRowsByWhere(\r\n [mapped as unknown as Record<string, unknown>],\r\n where,\r\n );\r\n return (filtered[0] ? mapped : null) as T | null;\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n mapRowToBetterAuth,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n filterRowsByWhere,\r\n} from \"../utils\";\r\n\r\nexport type FindManyDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function findManyMethod(deps: FindManyDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function findMany<T>({\r\n model,\r\n where,\r\n limit,\r\n sortBy,\r\n offset,\r\n select,\r\n }: {\r\n model: string;\r\n where?: WhereClause[];\r\n limit: number;\r\n select?: string[];\r\n sortBy?: { field: string; direction: \"asc\" | \"desc\" };\r\n offset?: number;\r\n join?: unknown;\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (\r\n columnMapper: (col: string) => string,\r\n opts?: { skipWhere?: boolean; limitOverride?: number; offsetOverride?: number },\r\n ) => {\r\n const columns =\r\n select && select.length > 0\r\n ? select.map((c) => columnMapper(c)).join(\", \")\r\n : undefined;\r\n\r\n let builder = db.from(model).select(columns);\r\n\r\n if (!opts?.skipWhere && where) {\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n }\r\n\r\n const effectiveLimit = opts?.limitOverride ?? limit;\r\n const effectiveOffset = opts?.offsetOverride ?? offset;\r\n\r\n if (effectiveLimit !== undefined) {\r\n builder = builder.limit(effectiveLimit);\r\n }\r\n\r\n if (effectiveOffset !== undefined) {\r\n builder = builder.offset(effectiveOffset);\r\n }\r\n\r\n const { data: result, error } = await builder;\r\n return { result, error };\r\n };\r\n\r\n const first = await run(snakeMapper);\r\n const pickRows = (res: unknown) =>\r\n (Array.isArray(res) ? res : []) as Record<string, unknown>[];\r\n\r\n const applySort = (rows: T[]) => {\r\n if (!sortBy) return rows;\r\n const sortField = sortBy.field;\r\n rows.sort((a, b) => {\r\n const aVal = (a as Record<string, unknown>)[sortField];\r\n const bVal = (b as Record<string, unknown>)[sortField];\r\n if (aVal == null && bVal == null) return 0;\r\n if (aVal == null) return sortBy.direction === \"asc\" ? -1 : 1;\r\n if (bVal == null) return sortBy.direction === \"asc\" ? 1 : -1;\r\n const cmp =\r\n typeof aVal === \"string\" && typeof bVal === \"string\"\r\n ? aVal.localeCompare(bVal)\r\n : aVal < bVal\r\n ? -1\r\n : aVal > bVal\r\n ? 1\r\n : 0;\r\n return sortBy.direction === \"asc\" ? cmp : -cmp;\r\n });\r\n return rows;\r\n };\r\n\r\n const mapAndSort = (rows: Record<string, unknown>[]) => {\r\n const betterAuthRows = rows.map((r) => mapRowToBetterAuth(r)) as unknown as T[];\r\n\r\n if (!where?.length) return applySort(betterAuthRows);\r\n\r\n const filtered = filterRowsByWhere(\r\n betterAuthRows as unknown as Record<string, unknown>[],\r\n where,\r\n ) as unknown as T[];\r\n\r\n // If filtering changed the row set, the gateway likely ignored `where`\r\n // (or applied it before limiting/offset). In that case, re-apply sorting\r\n // and slice using the requested offset/limit.\r\n if (filtered.length !== betterAuthRows.length) {\r\n const off = offset ?? 0;\r\n const end = limit !== undefined ? off + limit : undefined;\r\n return applySort(filtered).slice(off, end);\r\n }\r\n\r\n return applySort(filtered);\r\n };\r\n\r\n const postFilterAndSlice = (rows: Record<string, unknown>[]) => {\r\n const mappedSorted = mapAndSort(rows);\r\n const off = offset ?? 0;\r\n const end = limit !== undefined ? off + limit : undefined;\r\n return mappedSorted.slice(off, end);\r\n };\r\n\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] findMany on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n const retryRows = pickRows(retry.result);\r\n // Decisive fallback: if gateway-side `where` yields empty/insufficient rows,\r\n // fetch a broader candidate set and apply `where`/sort/offset/limit in-memory.\r\n if (where?.length) {\r\n const broad = await run(identityMapper, {\r\n skipWhere: true,\r\n limitOverride: Math.max((offset ?? 0) + (limit ?? 0) + 500, 5000),\r\n offsetOverride: 0,\r\n });\r\n if (!broad.error) return postFilterAndSlice(pickRows(broad.result));\r\n }\r\n return mapAndSort(retryRows);\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] findMany on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n const firstRows = pickRows(first.result);\r\n if (where?.length) {\r\n const broad = await run(snakeMapper, {\r\n skipWhere: true,\r\n limitOverride: Math.max((offset ?? 0) + (limit ?? 0) + 500, 5000),\r\n offsetOverride: 0,\r\n });\r\n if (!broad.error) return postFilterAndSlice(pickRows(broad.result));\r\n }\r\n return mapAndSort(firstRows);\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n} from \"../utils\";\r\n\r\nexport type CountDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function countMethod(deps: CountDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function count({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where?: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (columnMapper: (col: string) => string) => {\r\n let builder = db.from(model).select();\r\n\r\n if (where) {\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n }\r\n\r\n const { data: result, error } = await builder;\r\n return { result, error };\r\n };\r\n\r\n const first = await run(snakeMapper);\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] count on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n return Array.isArray(retry.result) ? retry.result.length : 0;\r\n }\r\n throw new Error(\r\n `[AthenaAdapter] count on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n return Array.isArray(first.result) ? first.result.length : 0;\r\n };\r\n}\r\n"],"mappings":"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","names":["b","row","b","rows","row","version"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/utils.ts","../src/methods/create.ts","../src/methods/update.ts","../src/methods/update-many.ts","../src/methods/delete.ts","../src/methods/delete-many.ts","../src/methods/find-one.ts","../src/methods/find-many.ts","../src/methods/count.ts"],"sourcesContent":["import {\r\n createAdapterFactory,\r\n type AdapterFactory,\r\n type DBAdapterDebugLogOption,\r\n} from \"better-auth/adapters\";\r\nimport type { BetterAuthOptions } from \"better-auth\";\r\nimport { createClient } from \"@xylex-group/athena\";\r\nimport { getAthenaGlobalConfig } from \"./config\";\r\nimport { createMethod } from \"./methods/create\";\r\nimport { updateMethod } from \"./methods/update\";\r\nimport { updateManyMethod } from \"./methods/update-many\";\r\nimport { deleteMethod } from \"./methods/delete\";\r\nimport { deleteManyMethod } from \"./methods/delete-many\";\r\nimport { findOneMethod } from \"./methods/find-one\";\r\nimport { findManyMethod } from \"./methods/find-many\";\r\nimport { countMethod } from \"./methods/count\";\r\n\r\n/**\r\n * Configuration options for the Athena adapter.\r\n */\r\nexport interface AthenaAdapterConfig {\r\n /**\r\n * The URL of your Athena gateway.\r\n */\r\n url?: string;\r\n /**\r\n * The API key for authenticating with the Athena gateway.\r\n */\r\n apiKey?: string;\r\n /**\r\n * The client name sent in requests to the Athena gateway.\r\n */\r\n client?: string;\r\n\r\n /**\r\n * Optional override for the YAML config path.\r\n * Defaults to `./config.yaml` (resolved from `process.cwd()`).\r\n */\r\n configPath?: string;\r\n\r\n /**\r\n * When enabled, the adapter will reload `config.yaml` on changes.\r\n *\r\n * @default true\r\n */\r\n watchConfig?: boolean;\r\n /**\r\n * Helps you debug issues with the adapter.\r\n */\r\n debugLogs?: DBAdapterDebugLogOption;\r\n /**\r\n * If the table names in the schema are plural.\r\n *\r\n * @default false\r\n */\r\n usePlural?: boolean;\r\n\r\n /**\r\n * Optional headers sent with every request (e.g. `X-User-Id` if your gateway requires it for delete).\r\n */\r\n headers?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * Create a Better-Auth database adapter backed by @xylex-group/athena.\r\n *\r\n * Column names are kept in snake_case as required by the Athena gateway.\r\n *\r\n * @example\r\n * ```ts\r\n * import { betterAuth } from \"better-auth\";\r\n * import { athenaAdapter } from \"better-auth-athena\";\r\n *\r\n * export const auth = betterAuth({\r\n * database: athenaAdapter({\r\n * url: process.env.ATHENA_URL!,\r\n * apiKey: process.env.ATHENA_API_KEY!,\r\n * client: \"my-app\",\r\n * }),\r\n * });\r\n * ```\r\n */\r\nexport const athenaAdapter = (\r\n config: AthenaAdapterConfig,\r\n): AdapterFactory<BetterAuthOptions> => {\r\n let dbClient: any | null = null;\r\n let lastDbConfigVersion = -1;\r\n\r\n const shouldUseFixedConfig =\r\n typeof config.url === \"string\" &&\r\n config.url.length > 0 &&\r\n typeof config.apiKey === \"string\" &&\r\n config.apiKey.length > 0;\r\n\r\n function ensureDbClient(): any {\r\n if (shouldUseFixedConfig) {\r\n if (!dbClient) {\r\n dbClient = createClient(config.url!, config.apiKey!, {\r\n client: config.client,\r\n ...(config.headers && { headers: config.headers }),\r\n } as any);\r\n }\r\n return dbClient;\r\n }\r\n\r\n const { config: globalConfig, version } = getAthenaGlobalConfig({\r\n configPath: config.configPath,\r\n watch: config.watchConfig ?? true,\r\n });\r\n\r\n const url = config.url ?? globalConfig.athena.url;\r\n const apiKey = config.apiKey ?? globalConfig.athena.apiKey;\r\n const client = config.client ?? globalConfig.athena.client;\r\n\r\n if (!url || !apiKey) {\r\n throw new Error(\r\n `[AthenaAdapter] Missing Athena connection details. Set both 'athena.url' and 'athena.apiKey' in config.yaml (or pass 'url'/'apiKey' to athenaAdapter).`,\r\n );\r\n }\r\n\r\n if (!dbClient || version !== lastDbConfigVersion) {\r\n dbClient = createClient(url, apiKey, {\r\n client,\r\n ...(config.headers && { headers: config.headers }),\r\n } as any);\r\n lastDbConfigVersion = version;\r\n }\r\n\r\n return dbClient;\r\n }\r\n\r\n const deps = { ensureDbClient, headers: config.headers };\r\n\r\n return createAdapterFactory({\r\n config: {\r\n adapterId: \"athena\",\r\n adapterName: \"Athena Adapter\",\r\n usePlural: config.usePlural ?? false,\r\n debugLogs: config.debugLogs ?? false,\r\n supportsJSON: true,\r\n supportsDates: true,\r\n supportsBooleans: true,\r\n supportsNumericIds: true,\r\n supportsUUIDs: true,\r\n },\r\n adapter: () => {\r\n return {\r\n create: createMethod(deps),\r\n update: updateMethod(deps),\r\n updateMany: updateManyMethod(deps),\r\n delete: deleteMethod(deps),\r\n deleteMany: deleteManyMethod(deps),\r\n findOne: findOneMethod(deps),\r\n findMany: findManyMethod(deps),\r\n count: countMethod(deps),\r\n };\r\n },\r\n });\r\n};\r\n","import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport YAML from \"yaml\";\r\n\r\nexport type AthenaGlobalConfig = {\r\n athena: {\r\n url: string;\r\n apiKey: string;\r\n client?: string;\r\n };\r\n};\r\n\r\n// Defaults written to `config.yaml` if it doesn't exist.\r\n// These values are intentionally placeholders; the adapter will throw if\r\n// `url`/`apiKey` are still unset when used.\r\nexport const defaultAthenaGlobalConfig: AthenaGlobalConfig = {\r\n athena: {\r\n url: \"https://mirror3.athena-db.com\",\r\n apiKey: \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYXV0aGVudGljYXRlZCIsImVtYWlsIjoiZmxvcmlzQHh5bGV4LmFpIiwiZXhwIjoyNDk3MDMzNjY2fQ.LdPqTGaFq5pTokW1DA81WFjmG4nReJCOSKr3mFtXNoA\",\r\n client: \"athena_logging\",\r\n },\r\n};\r\n\r\nexport const DEFAULT_CONFIG_FILENAME = \"config.yaml\";\r\n\r\nfunction resolveConfigPath(configPath?: string): string {\r\n if (configPath) return path.resolve(configPath);\r\n return path.resolve(process.cwd(), DEFAULT_CONFIG_FILENAME);\r\n}\r\n\r\nlet cached: AthenaGlobalConfig | null = null;\r\nlet cachedConfigPath: string | null = null;\r\nlet version = 0;\r\n\r\nlet watcher: fs.FSWatcher | null = null;\r\n\r\nfunction isObject(value: unknown): value is Record<string, unknown> {\r\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n}\r\n\r\nfunction deepMerge<T extends Record<string, unknown>>(\r\n base: T,\r\n partial: unknown,\r\n): T {\r\n if (!isObject(partial)) return base;\r\n const out: Record<string, unknown> = { ...base };\r\n for (const [k, v] of Object.entries(partial)) {\r\n if (v && isObject(v) && isObject(out[k])) {\r\n out[k] = deepMerge(out[k] as Record<string, unknown>, v);\r\n } else {\r\n out[k] = v;\r\n }\r\n }\r\n return out as T;\r\n}\r\n\r\nfunction ensureConfigFile(configPath: string): void {\r\n const dir = path.dirname(configPath);\r\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\r\n\r\n if (!fs.existsSync(configPath)) {\r\n const yaml = YAML.stringify(defaultAthenaGlobalConfig);\r\n fs.writeFileSync(configPath, yaml, \"utf-8\");\r\n }\r\n}\r\n\r\nfunction readConfigFromDisk(configPath: string): AthenaGlobalConfig {\r\n ensureConfigFile(configPath);\r\n const raw = fs.readFileSync(configPath, \"utf-8\");\r\n const parsed = YAML.parse(raw) as unknown;\r\n return deepMerge(defaultAthenaGlobalConfig, parsed);\r\n}\r\n\r\nfunction startWatcher(configPath: string): void {\r\n // Avoid multiple watchers when multiple adapter instances are created.\r\n if (cachedConfigPath !== null && cachedConfigPath !== configPath && watcher) {\r\n try {\r\n watcher.close();\r\n } catch {\r\n // ignore\r\n }\r\n watcher = null;\r\n }\r\n if (watcher || cachedConfigPath === configPath) return;\r\n\r\n try {\r\n watcher = fs.watch(configPath, { persistent: false }, (event) => {\r\n if (event !== \"change\" && event !== \"rename\") return;\r\n try {\r\n cached = readConfigFromDisk(configPath);\r\n version += 1;\r\n } catch {\r\n // Keep last known good config if reload fails.\r\n }\r\n });\r\n cachedConfigPath = configPath;\r\n } catch {\r\n // If watching isn't supported in the environment, just run without it.\r\n }\r\n}\r\n\r\nexport function getAthenaGlobalConfig(options?: {\r\n configPath?: string;\r\n watch?: boolean;\r\n}): { config: AthenaGlobalConfig; version: number } {\r\n const configPath = resolveConfigPath(options?.configPath);\r\n const shouldWatch = options?.watch ?? true;\r\n\r\n if (!cached || cachedConfigPath !== configPath) {\r\n cached = readConfigFromDisk(configPath);\r\n cachedConfigPath = configPath;\r\n version += 1;\r\n }\r\n\r\n if (shouldWatch) startWatcher(configPath);\r\n\r\n return { config: cached, version };\r\n}\r\n","/**\r\n * Shared helpers and types for the Athena adapter.\r\n */\r\n\r\nexport function toSnakeCase(key: string): string {\r\n return key\r\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\r\n .replace(/__/g, \"_\")\r\n .toLowerCase();\r\n}\r\n\r\nexport function toCamelCase(key: string): string {\r\n return key.replace(/_([a-z0-9])/g, (_, ch: string) => ch.toUpperCase());\r\n}\r\n\r\nexport function hasUppercase(key: string): boolean {\r\n return /[A-Z]/.test(key);\r\n}\r\n\r\nexport function mapKeys<T extends Record<string, unknown>>(\r\n obj: T,\r\n mapKey: (k: string) => string,\r\n): Record<string, unknown> {\r\n const out: Record<string, unknown> = {};\r\n for (const [k, v] of Object.entries(obj)) out[mapKey(k)] = v;\r\n return out;\r\n}\r\n\r\nexport function mapRowToBetterAuth<T>(row: T): T {\r\n if (!row || typeof row !== \"object\") return row;\r\n if (Array.isArray(row)) return row.map(mapRowToBetterAuth) as unknown as T;\r\n return mapKeys(row as Record<string, unknown>, toCamelCase) as T;\r\n}\r\n\r\nexport function isLikelyIsoDateString(value: string): boolean {\r\n if (!/^\\d{4}-\\d{2}-\\d{2}T/.test(value)) return false;\r\n const ms = Date.parse(value);\r\n return Number.isFinite(ms);\r\n}\r\n\r\nexport function isTimestampKey(key: string): boolean {\r\n return key.endsWith(\"At\") || key.endsWith(\"_at\") || key === \"expires\";\r\n}\r\n\r\nexport function coerceDateFields<T extends Record<string, unknown>>(data: T): T {\r\n const out: Record<string, unknown> = { ...data };\r\n for (const [key, val] of Object.entries(out)) {\r\n if (val == null) continue;\r\n if (\r\n typeof val === \"string\" &&\r\n isTimestampKey(key) &&\r\n isLikelyIsoDateString(val)\r\n ) {\r\n out[key] = new Date(val);\r\n }\r\n }\r\n return out as T;\r\n}\r\n\r\nexport function toDbRecord<T extends Record<string, unknown>>(\r\n data: T,\r\n): Record<string, unknown> {\r\n const withDbKeys = mapKeys(data, (k) =>\r\n hasUppercase(k) ? toSnakeCase(k) : k,\r\n );\r\n return coerceDateFields(withDbKeys);\r\n}\r\n\r\nexport type AthenaFilterBuilder = {\r\n eq(col: string, val: unknown): AthenaFilterBuilder;\r\n neq(col: string, val: unknown): AthenaFilterBuilder;\r\n gt(col: string, val: unknown): AthenaFilterBuilder;\r\n gte(col: string, val: unknown): AthenaFilterBuilder;\r\n lt(col: string, val: unknown): AthenaFilterBuilder;\r\n lte(col: string, val: unknown): AthenaFilterBuilder;\r\n in(col: string, vals: unknown[]): AthenaFilterBuilder;\r\n not(col: string, op?: string, val?: unknown): AthenaFilterBuilder;\r\n like(col: string, val: string): AthenaFilterBuilder;\r\n delete?(): { select(): Promise<{ data: unknown; error: unknown }> };\r\n select?(columns?: string): Promise<{ data: unknown; error: unknown }> | { select(): Promise<{ data: unknown; error: unknown }> };\r\n};\r\n\r\nexport type WhereClause = { field: string; operator: string; value: unknown };\r\n\r\nconst defaultColumnMapper = (col: string) =>\r\n hasUppercase(col) ? toSnakeCase(col) : col;\r\n\r\nexport function applyWhere(\r\n builder: AthenaFilterBuilder,\r\n field: string,\r\n operator: string,\r\n value: unknown,\r\n columnMapper: (col: string) => string = defaultColumnMapper,\r\n): AthenaFilterBuilder {\r\n const dbField = columnMapper(field);\r\n switch (operator) {\r\n case \"eq\":\r\n return builder.eq(dbField, value);\r\n case \"ne\":\r\n return builder.neq(dbField, value);\r\n case \"gt\":\r\n return builder.gt(dbField, value);\r\n case \"gte\":\r\n return builder.gte(dbField, value);\r\n case \"lt\":\r\n return builder.lt(dbField, value);\r\n case \"lte\":\r\n return builder.lte(dbField, value);\r\n case \"in\":\r\n return builder.in(dbField, value as unknown[]);\r\n case \"not_in\":\r\n return builder.not(dbField, \"in\", value);\r\n case \"contains\":\r\n return builder.like(dbField, `%${value}%`);\r\n case \"starts_with\":\r\n return builder.like(dbField, `${value}%`);\r\n case \"ends_with\":\r\n return builder.like(dbField, `%${value}`);\r\n default:\r\n return builder.eq(dbField, value);\r\n }\r\n}\r\n\r\nexport function isMissingColumnError(error: unknown): boolean {\r\n const msg = String(error ?? \"\");\r\n return (\r\n msg.includes(\"specified column does not exist\") ||\r\n msg.includes(\"column does not exist\")\r\n );\r\n}\r\n\r\n/** True when the Athena gateway returns a success message in the error field (treat as success). */\r\nexport function isSuccessMessageInError(error: unknown): boolean {\r\n const msg = String(error ?? \"\").toLowerCase();\r\n return (\r\n msg === \"data inserted successfully\" ||\r\n msg === \"data updated successfully\" ||\r\n msg === \"data deleted successfully\"\r\n );\r\n}\r\n\r\nexport function snakeMapper(col: string): string {\r\n return hasUppercase(col) ? toSnakeCase(col) : col;\r\n}\r\n\r\nexport function identityMapper(col: string): string {\r\n return col;\r\n}\r\n\r\n/** Get value from row by field name (camelCase or snake_case). */\r\nfunction getRowValue(row: Record<string, unknown>, field: string): unknown {\r\n if (Object.prototype.hasOwnProperty.call(row, field)) return row[field];\r\n const snake = hasUppercase(field) ? toSnakeCase(field) : field;\r\n return row[snake];\r\n}\r\n\r\n/**\r\n * Filter rows in-memory by where clauses (fallback when gateway does not apply filters).\r\n * Supports eq, ne, in, not_in; row keys may be camelCase or snake_case.\r\n */\r\nexport function filterRowsByWhere(\r\n rows: Record<string, unknown>[],\r\n where: WhereClause[],\r\n): Record<string, unknown>[] {\r\n if (!where.length) return rows;\r\n return rows.filter((row) => {\r\n for (const { field, operator, value } of where) {\r\n const rowVal = getRowValue(row, field);\r\n switch (operator) {\r\n case \"eq\":\r\n if (rowVal !== value) return false;\r\n break;\r\n case \"ne\":\r\n if (rowVal === value) return false;\r\n break;\r\n case \"in\":\r\n if (!Array.isArray(value) || !value.includes(rowVal)) return false;\r\n break;\r\n case \"not_in\":\r\n if (Array.isArray(value) && value.includes(rowVal)) return false;\r\n break;\r\n default:\r\n if (rowVal !== value) return false;\r\n }\r\n }\r\n return true;\r\n });\r\n}\r\n","import { toDbRecord, mapRowToBetterAuth, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type CreateDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function createMethod(deps: CreateDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function create<T extends Record<string, unknown>>({\r\n model,\r\n data,\r\n }: {\r\n model: string;\r\n data: T;\r\n select?: string[];\r\n }) {\r\n const db = ensureDbClient();\r\n const insertData = toDbRecord(data);\r\n const { data: result, error } = await db\r\n .from(model)\r\n .insert(insertData)\r\n .select();\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(`[AthenaAdapter] create on \"${model}\" failed: ${error}`);\r\n }\r\n\r\n const row = Array.isArray(result) ? result[0] : result;\r\n return mapRowToBetterAuth((row ?? insertData) as T);\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport {\r\n toDbRecord,\r\n mapRowToBetterAuth,\r\n applyWhere,\r\n isSuccessMessageInError,\r\n} from \"../utils\";\r\n\r\nexport type UpdateDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function updateMethod(deps: UpdateDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function update<T>({\r\n model,\r\n where,\r\n update,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n update: T;\r\n }) {\r\n const db = ensureDbClient();\r\n const updateData = toDbRecord(update as Record<string, unknown>);\r\n const build = (useRetryShape: boolean) => {\r\n // Primary shape: some gateway versions accept back-compat update_body keys.\r\n if (!useRetryShape) {\r\n let b = db\r\n .from(model)\r\n .update({ data: updateData, set: updateData } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n }\r\n\r\n // Retry shape: send the plain update values, but also provide an explicit `updateBody`.\r\n let b = db\r\n .from(model)\r\n .update(updateData, {\r\n updateBody: { data: updateData, set: updateData },\r\n } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n };\r\n\r\n const run = async (b: AthenaFilterBuilder) => {\r\n const { data: result, error } = await (b as any).select();\r\n return { result, error };\r\n };\r\n\r\n const first = await run(build(false));\r\n if (first.error && !isSuccessMessageInError(first.error)) {\r\n const msg = String(first.error);\r\n if (msg.toLowerCase().includes(\"update payload required\")) {\r\n const retry = await run(build(true));\r\n if (retry.error && !isSuccessMessageInError(retry.error)) {\r\n throw new Error(\r\n `[AthenaAdapter] update on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n const row = Array.isArray(retry.result)\r\n ? (retry.result[0] as unknown)\r\n : (retry.result as unknown);\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n }\r\n\r\n throw new Error(`[AthenaAdapter] update on \"${model}\" failed: ${first.error}`);\r\n }\r\n\r\n const row = Array.isArray(first.result)\r\n ? (first.result[0] as unknown)\r\n : (first.result as unknown);\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { toDbRecord, applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type UpdateManyDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function updateManyMethod(deps: UpdateManyDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function updateMany({\r\n model,\r\n where,\r\n update,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n update: Record<string, unknown>;\r\n }) {\r\n const db = ensureDbClient();\r\n const updateData = toDbRecord(update);\r\n const build = (useRetryShape: boolean) => {\r\n if (!useRetryShape) {\r\n let b = db\r\n .from(model)\r\n .update({ data: updateData, set: updateData } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n }\r\n\r\n let b = db\r\n .from(model)\r\n .update(updateData, {\r\n updateBody: { data: updateData, set: updateData },\r\n } as any) as AthenaFilterBuilder;\r\n for (const clause of where) {\r\n b = applyWhere(b, clause.field, clause.operator, clause.value);\r\n }\r\n return b;\r\n };\r\n\r\n const run = async (b: AthenaFilterBuilder) => {\r\n const { data: result, error } = await (b as any).select();\r\n return { result, error };\r\n };\r\n\r\n const first = await run(build(false));\r\n if (first.error && !isSuccessMessageInError(first.error)) {\r\n const msg = String(first.error);\r\n if (msg.toLowerCase().includes(\"update payload required\")) {\r\n const retry = await run(build(true));\r\n if (retry.error && !isSuccessMessageInError(retry.error)) {\r\n throw new Error(\r\n `[AthenaAdapter] updateMany on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n return Array.isArray(retry.result) ? retry.result.length : retry.result ? 1 : 0;\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] updateMany on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n return Array.isArray(first.result) ? first.result.length : first.result ? 1 : 0;\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type DeleteDeps = {\r\n ensureDbClient: () => any;\r\n headers?: Record<string, string>;\r\n};\r\n\r\nexport function deleteMethod(deps: DeleteDeps) {\r\n const { ensureDbClient, headers } = deps;\r\n\r\n return async function del({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n let builder = db.from(model) as AthenaFilterBuilder;\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n );\r\n }\r\n\r\n const { error } = await (builder as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n );\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(\r\n `[AthenaAdapter] delete on \"${model}\" failed: ${error}`,\r\n );\r\n }\r\n };\r\n}\r\n","import type { WhereClause, AthenaFilterBuilder } from \"../utils\";\r\nimport { applyWhere, isSuccessMessageInError } from \"../utils\";\r\n\r\nexport type DeleteManyDeps = {\r\n ensureDbClient: () => any;\r\n headers?: Record<string, string>;\r\n};\r\n\r\nexport function deleteManyMethod(deps: DeleteManyDeps) {\r\n const { ensureDbClient, headers } = deps;\r\n\r\n return async function deleteMany({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n const mainBuilder = db.from(model) as AthenaFilterBuilder;\r\n let builder = mainBuilder;\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n );\r\n }\r\n\r\n const { data: result, error } = await (builder as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n ).select();\r\n\r\n if (error && !isSuccessMessageInError(error)) {\r\n throw new Error(\r\n `[AthenaAdapter] deleteMany on \"${model}\" failed: ${error}`,\r\n );\r\n }\r\n\r\n const deletedCount = Array.isArray(result) ? result.length : result ? 1 : 0;\r\n // Fallback: if the live gateway doesn't apply `in` conditions correctly,\r\n // delete rows one-by-one so counts are stable for e2e tests.\r\n const inClause = where.find(\r\n (c) => c.operator === \"in\" && c.value != null,\r\n );\r\n if (\r\n inClause &&\r\n Array.isArray(inClause.value) &&\r\n deletedCount < inClause.value.length\r\n ) {\r\n let n = 0;\r\n for (const v of inClause.value) {\r\n const b = db.from(model);\r\n const filtered = applyWhere(\r\n b as any,\r\n inClause.field,\r\n \"eq\",\r\n v,\r\n );\r\n const { data: rowData, error: rowErr } = await (filtered as any).delete(\r\n headers ? ({ headers } as any) : undefined,\r\n ).select();\r\n if (rowErr && isSuccessMessageInError(rowErr)) continue;\r\n n += Array.isArray(rowData) ? rowData.length : rowData ? 1 : 0;\r\n }\r\n return n;\r\n }\r\n\r\n return deletedCount;\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n mapRowToBetterAuth,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n filterRowsByWhere,\r\n} from \"../utils\";\r\n\r\nexport type FindOneDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function findOneMethod(deps: FindOneDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function findOne<T>({\r\n model,\r\n where,\r\n select,\r\n }: {\r\n model: string;\r\n where: WhereClause[];\r\n select?: string[];\r\n join?: unknown;\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (columnMapper: (col: string) => string) => {\r\n const columns =\r\n select && select.length > 0\r\n ? select.map((c) => columnMapper(c)).join(\", \")\r\n : undefined;\r\n\r\n let builder = db.from(model).select(columns);\r\n\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n\r\n const { data: result, error } = await builder.limit(1);\r\n return { result, error };\r\n };\r\n\r\n const first = await run(snakeMapper);\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] findOne on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n\r\n const rows = Array.isArray(retry.result)\r\n ? retry.result\r\n : retry.result\r\n ? [retry.result]\r\n : [];\r\n const row = rows[0] ?? null;\r\n return (row ? mapRowToBetterAuth(row as T) : null) as T | null;\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] findOne on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n const rows = Array.isArray(first.result)\r\n ? first.result\r\n : first.result\r\n ? [first.result]\r\n : [];\r\n const row = rows[0] ?? null;\r\n if (!row) return null;\r\n\r\n const mapped = mapRowToBetterAuth(row as T) as T;\r\n const filtered = filterRowsByWhere(\r\n [mapped as unknown as Record<string, unknown>],\r\n where,\r\n );\r\n return (filtered[0] ? mapped : null) as T | null;\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n mapRowToBetterAuth,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n filterRowsByWhere,\r\n} from \"../utils\";\r\n\r\nexport type FindManyDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function findManyMethod(deps: FindManyDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n const isTransientGatewayError = (error: unknown): boolean => {\r\n const message = String(error ?? \"\").toLowerCase();\r\n return (\r\n message.includes(\"application failed to respond\") ||\r\n message.includes(\"timeout\") ||\r\n message.includes(\"timed out\") ||\r\n message.includes(\"gateway timeout\") ||\r\n message.includes(\"econnreset\") ||\r\n message.includes(\"connection reset\")\r\n );\r\n };\r\n\r\n return async function findMany<T>({\r\n model,\r\n where,\r\n limit,\r\n sortBy,\r\n offset,\r\n select,\r\n }: {\r\n model: string;\r\n where?: WhereClause[];\r\n limit: number;\r\n select?: string[];\r\n sortBy?: { field: string; direction: \"asc\" | \"desc\" };\r\n offset?: number;\r\n join?: unknown;\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (\r\n columnMapper: (col: string) => string,\r\n opts?: { skipWhere?: boolean; limitOverride?: number; offsetOverride?: number },\r\n ) => {\r\n const columns =\r\n select && select.length > 0\r\n ? select.map((c) => columnMapper(c)).join(\", \")\r\n : undefined;\r\n\r\n let builder = db.from(model).select(columns);\r\n\r\n if (!opts?.skipWhere && where) {\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n }\r\n\r\n const effectiveLimit = opts?.limitOverride ?? limit;\r\n const effectiveOffset = opts?.offsetOverride ?? offset;\r\n\r\n if (effectiveLimit !== undefined) {\r\n builder = builder.limit(effectiveLimit);\r\n }\r\n\r\n if (effectiveOffset !== undefined) {\r\n builder = builder.offset(effectiveOffset);\r\n }\r\n\r\n const { data: result, error } = await builder;\r\n return { result, error };\r\n };\r\n\r\n let first = await run(snakeMapper);\r\n if (first.error && isTransientGatewayError(first.error)) {\r\n const retry = await run(snakeMapper);\r\n if (!retry.error) first = retry;\r\n }\r\n\r\n const pickRows = (res: unknown) =>\r\n (Array.isArray(res) ? res : []) as Record<string, unknown>[];\r\n\r\n const applySort = (rows: T[]) => {\r\n if (!sortBy) return rows;\r\n const sortField = sortBy.field;\r\n rows.sort((a, b) => {\r\n const aVal = (a as Record<string, unknown>)[sortField];\r\n const bVal = (b as Record<string, unknown>)[sortField];\r\n if (aVal == null && bVal == null) return 0;\r\n if (aVal == null) return sortBy.direction === \"asc\" ? -1 : 1;\r\n if (bVal == null) return sortBy.direction === \"asc\" ? 1 : -1;\r\n const cmp =\r\n typeof aVal === \"string\" && typeof bVal === \"string\"\r\n ? aVal.localeCompare(bVal)\r\n : aVal < bVal\r\n ? -1\r\n : aVal > bVal\r\n ? 1\r\n : 0;\r\n return sortBy.direction === \"asc\" ? cmp : -cmp;\r\n });\r\n return rows;\r\n };\r\n\r\n const mapAndSort = (rows: Record<string, unknown>[]) => {\r\n const betterAuthRows = rows.map((r) => mapRowToBetterAuth(r)) as unknown as T[];\r\n\r\n if (!where?.length) return applySort(betterAuthRows);\r\n\r\n const filtered = filterRowsByWhere(\r\n betterAuthRows as unknown as Record<string, unknown>[],\r\n where,\r\n ) as unknown as T[];\r\n\r\n // If filtering changed the row set, the gateway likely ignored `where`\r\n // (or applied it before limiting/offset). In that case, re-apply sorting\r\n // and slice using the requested offset/limit.\r\n if (filtered.length !== betterAuthRows.length) {\r\n const off = offset ?? 0;\r\n const end = limit !== undefined ? off + limit : undefined;\r\n return applySort(filtered).slice(off, end);\r\n }\r\n\r\n return applySort(filtered);\r\n };\r\n\r\n const postFilterAndSlice = (rows: Record<string, unknown>[]) => {\r\n const mappedSorted = mapAndSort(rows);\r\n const off = offset ?? 0;\r\n const end = limit !== undefined ? off + limit : undefined;\r\n return mappedSorted.slice(off, end);\r\n };\r\n\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] findMany on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n const retryRows = pickRows(retry.result);\r\n // Decisive fallback: if gateway-side `where` yields empty/insufficient rows,\r\n // fetch a broader candidate set and apply `where`/sort/offset/limit in-memory.\r\n if (where?.length) {\r\n const broad = await run(identityMapper, {\r\n skipWhere: true,\r\n limitOverride: Math.max((offset ?? 0) + (limit ?? 0) + 500, 5000),\r\n offsetOverride: 0,\r\n });\r\n if (!broad.error) return postFilterAndSlice(pickRows(broad.result));\r\n }\r\n return mapAndSort(retryRows);\r\n }\r\n\r\n throw new Error(\r\n `[AthenaAdapter] findMany on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n const firstRows = pickRows(first.result);\r\n if (where?.length) {\r\n const broad = await run(snakeMapper, {\r\n skipWhere: true,\r\n limitOverride: Math.max((offset ?? 0) + (limit ?? 0) + 500, 5000),\r\n offsetOverride: 0,\r\n });\r\n if (!broad.error) return postFilterAndSlice(pickRows(broad.result));\r\n }\r\n return mapAndSort(firstRows);\r\n };\r\n}\r\n","import type { WhereClause } from \"../utils\";\r\nimport {\r\n applyWhere,\r\n isMissingColumnError,\r\n snakeMapper,\r\n identityMapper,\r\n} from \"../utils\";\r\n\r\nexport type CountDeps = {\r\n ensureDbClient: () => any;\r\n};\r\n\r\nexport function countMethod(deps: CountDeps) {\r\n const { ensureDbClient } = deps;\r\n\r\n return async function count({\r\n model,\r\n where,\r\n }: {\r\n model: string;\r\n where?: WhereClause[];\r\n }) {\r\n const db = ensureDbClient();\r\n\r\n const run = async (columnMapper: (col: string) => string) => {\r\n let builder = db.from(model).select();\r\n\r\n if (where) {\r\n for (const clause of where) {\r\n builder = applyWhere(\r\n builder,\r\n clause.field,\r\n clause.operator,\r\n clause.value,\r\n columnMapper,\r\n );\r\n }\r\n }\r\n\r\n const { data: result, error } = await builder;\r\n return { result, error };\r\n };\r\n\r\n const first = await run(snakeMapper);\r\n if (first.error) {\r\n if (isMissingColumnError(first.error)) {\r\n const retry = await run(identityMapper);\r\n if (retry.error) {\r\n throw new Error(\r\n `[AthenaAdapter] count on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n return Array.isArray(retry.result) ? retry.result.length : 0;\r\n }\r\n throw new Error(\r\n `[AthenaAdapter] count on \"${model}\" failed: ${first.error}`,\r\n );\r\n }\r\n\r\n return Array.isArray(first.result) ? first.result.length : 0;\r\n };\r\n}\r\n"],"mappings":";AAAA;AAAA,EACE;AAAA,OAGK;AAEP,SAAS,oBAAoB;;;ACN7B,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,UAAU;AAaV,IAAM,4BAAgD;AAAA,EAC3D,QAAQ;AAAA,IACN,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACF;AAEO,IAAM,0BAA0B;AAEvC,SAAS,kBAAkB,YAA6B;AACtD,MAAI,WAAY,QAAO,KAAK,QAAQ,UAAU;AAC9C,SAAO,KAAK,QAAQ,QAAQ,IAAI,GAAG,uBAAuB;AAC5D;AAEA,IAAI,SAAoC;AACxC,IAAI,mBAAkC;AACtC,IAAI,UAAU;AAEd,IAAI,UAA+B;AAEnC,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,UACP,MACA,SACG;AACH,MAAI,CAAC,SAAS,OAAO,EAAG,QAAO;AAC/B,QAAM,MAA+B,EAAE,GAAG,KAAK;AAC/C,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,OAAO,GAAG;AAC5C,QAAI,KAAK,SAAS,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG;AACxC,UAAI,CAAC,IAAI,UAAU,IAAI,CAAC,GAA8B,CAAC;AAAA,IACzD,OAAO;AACL,UAAI,CAAC,IAAI;AAAA,IACX;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,YAA0B;AAClD,QAAM,MAAM,KAAK,QAAQ,UAAU;AACnC,MAAI,CAAC,GAAG,WAAW,GAAG,EAAG,IAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAE9D,MAAI,CAAC,GAAG,WAAW,UAAU,GAAG;AAC9B,UAAM,OAAO,KAAK,UAAU,yBAAyB;AACrD,OAAG,cAAc,YAAY,MAAM,OAAO;AAAA,EAC5C;AACF;AAEA,SAAS,mBAAmB,YAAwC;AAClE,mBAAiB,UAAU;AAC3B,QAAM,MAAM,GAAG,aAAa,YAAY,OAAO;AAC/C,QAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,SAAO,UAAU,2BAA2B,MAAM;AACpD;AAEA,SAAS,aAAa,YAA0B;AAE9C,MAAI,qBAAqB,QAAQ,qBAAqB,cAAc,SAAS;AAC3E,QAAI;AACF,cAAQ,MAAM;AAAA,IAChB,QAAQ;AAAA,IAER;AACA,cAAU;AAAA,EACZ;AACA,MAAI,WAAW,qBAAqB,WAAY;AAEhD,MAAI;AACF,cAAU,GAAG,MAAM,YAAY,EAAE,YAAY,MAAM,GAAG,CAAC,UAAU;AAC/D,UAAI,UAAU,YAAY,UAAU,SAAU;AAC9C,UAAI;AACF,iBAAS,mBAAmB,UAAU;AACtC,mBAAW;AAAA,MACb,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AACD,uBAAmB;AAAA,EACrB,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,sBAAsB,SAGc;AAClD,QAAM,aAAa,kBAAkB,SAAS,UAAU;AACxD,QAAM,cAAc,SAAS,SAAS;AAEtC,MAAI,CAAC,UAAU,qBAAqB,YAAY;AAC9C,aAAS,mBAAmB,UAAU;AACtC,uBAAmB;AACnB,eAAW;AAAA,EACb;AAEA,MAAI,YAAa,cAAa,UAAU;AAExC,SAAO,EAAE,QAAQ,QAAQ,QAAQ;AACnC;;;ACjHO,SAAS,YAAY,KAAqB;AAC/C,SAAO,IACJ,QAAQ,sBAAsB,OAAO,EACrC,QAAQ,OAAO,GAAG,EAClB,YAAY;AACjB;AAEO,SAAS,YAAY,KAAqB;AAC/C,SAAO,IAAI,QAAQ,gBAAgB,CAAC,GAAG,OAAe,GAAG,YAAY,CAAC;AACxE;AAEO,SAAS,aAAa,KAAsB;AACjD,SAAO,QAAQ,KAAK,GAAG;AACzB;AAEO,SAAS,QACd,KACA,QACyB;AACzB,QAAM,MAA+B,CAAC;AACtC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,EAAG,KAAI,OAAO,CAAC,CAAC,IAAI;AAC3D,SAAO;AACT;AAEO,SAAS,mBAAsB,KAAW;AAC/C,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,MAAI,MAAM,QAAQ,GAAG,EAAG,QAAO,IAAI,IAAI,kBAAkB;AACzD,SAAO,QAAQ,KAAgC,WAAW;AAC5D;AAEO,SAAS,sBAAsB,OAAwB;AAC5D,MAAI,CAAC,sBAAsB,KAAK,KAAK,EAAG,QAAO;AAC/C,QAAM,KAAK,KAAK,MAAM,KAAK;AAC3B,SAAO,OAAO,SAAS,EAAE;AAC3B;AAEO,SAAS,eAAe,KAAsB;AACnD,SAAO,IAAI,SAAS,IAAI,KAAK,IAAI,SAAS,KAAK,KAAK,QAAQ;AAC9D;AAEO,SAAS,iBAAoD,MAAY;AAC9E,QAAM,MAA+B,EAAE,GAAG,KAAK;AAC/C,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC5C,QAAI,OAAO,KAAM;AACjB,QACE,OAAO,QAAQ,YACf,eAAe,GAAG,KAClB,sBAAsB,GAAG,GACzB;AACA,UAAI,GAAG,IAAI,IAAI,KAAK,GAAG;AAAA,IACzB;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,WACd,MACyB;AACzB,QAAM,aAAa;AAAA,IAAQ;AAAA,IAAM,CAAC,MAChC,aAAa,CAAC,IAAI,YAAY,CAAC,IAAI;AAAA,EACrC;AACA,SAAO,iBAAiB,UAAU;AACpC;AAkBA,IAAM,sBAAsB,CAAC,QAC3B,aAAa,GAAG,IAAI,YAAY,GAAG,IAAI;AAElC,SAAS,WACd,SACA,OACA,UACA,OACA,eAAwC,qBACnB;AACrB,QAAM,UAAU,aAAa,KAAK;AAClC,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO,QAAQ,GAAG,SAAS,KAAK;AAAA,IAClC,KAAK;AACH,aAAO,QAAQ,IAAI,SAAS,KAAK;AAAA,IACnC,KAAK;AACH,aAAO,QAAQ,GAAG,SAAS,KAAK;AAAA,IAClC,KAAK;AACH,aAAO,QAAQ,IAAI,SAAS,KAAK;AAAA,IACnC,KAAK;AACH,aAAO,QAAQ,GAAG,SAAS,KAAK;AAAA,IAClC,KAAK;AACH,aAAO,QAAQ,IAAI,SAAS,KAAK;AAAA,IACnC,KAAK;AACH,aAAO,QAAQ,GAAG,SAAS,KAAkB;AAAA,IAC/C,KAAK;AACH,aAAO,QAAQ,IAAI,SAAS,MAAM,KAAK;AAAA,IACzC,KAAK;AACH,aAAO,QAAQ,KAAK,SAAS,IAAI,KAAK,GAAG;AAAA,IAC3C,KAAK;AACH,aAAO,QAAQ,KAAK,SAAS,GAAG,KAAK,GAAG;AAAA,IAC1C,KAAK;AACH,aAAO,QAAQ,KAAK,SAAS,IAAI,KAAK,EAAE;AAAA,IAC1C;AACE,aAAO,QAAQ,GAAG,SAAS,KAAK;AAAA,EACpC;AACF;AAEO,SAAS,qBAAqB,OAAyB;AAC5D,QAAM,MAAM,OAAO,SAAS,EAAE;AAC9B,SACE,IAAI,SAAS,iCAAiC,KAC9C,IAAI,SAAS,uBAAuB;AAExC;AAGO,SAAS,wBAAwB,OAAyB;AAC/D,QAAM,MAAM,OAAO,SAAS,EAAE,EAAE,YAAY;AAC5C,SACE,QAAQ,gCACR,QAAQ,+BACR,QAAQ;AAEZ;AAEO,SAAS,YAAY,KAAqB;AAC/C,SAAO,aAAa,GAAG,IAAI,YAAY,GAAG,IAAI;AAChD;AAEO,SAAS,eAAe,KAAqB;AAClD,SAAO;AACT;AAGA,SAAS,YAAY,KAA8B,OAAwB;AACzE,MAAI,OAAO,UAAU,eAAe,KAAK,KAAK,KAAK,EAAG,QAAO,IAAI,KAAK;AACtE,QAAM,QAAQ,aAAa,KAAK,IAAI,YAAY,KAAK,IAAI;AACzD,SAAO,IAAI,KAAK;AAClB;AAMO,SAAS,kBACd,MACA,OAC2B;AAC3B,MAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,SAAO,KAAK,OAAO,CAAC,QAAQ;AAC1B,eAAW,EAAE,OAAO,UAAU,MAAM,KAAK,OAAO;AAC9C,YAAM,SAAS,YAAY,KAAK,KAAK;AACrC,cAAQ,UAAU;AAAA,QAChB,KAAK;AACH,cAAI,WAAW,MAAO,QAAO;AAC7B;AAAA,QACF,KAAK;AACH,cAAI,WAAW,MAAO,QAAO;AAC7B;AAAA,QACF,KAAK;AACH,cAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,SAAS,MAAM,EAAG,QAAO;AAC7D;AAAA,QACF,KAAK;AACH,cAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,MAAM,EAAG,QAAO;AAC3D;AAAA,QACF;AACE,cAAI,WAAW,MAAO,QAAO;AAAA,MACjC;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACH;;;ACrLO,SAAS,aAAa,MAAkB;AAC7C,QAAM,EAAE,eAAe,IAAI;AAE3B,SAAO,eAAe,OAA0C;AAAA,IAC9D;AAAA,IACA;AAAA,EACF,GAIG;AACD,UAAM,KAAK,eAAe;AAC1B,UAAM,aAAa,WAAW,IAAI;AAClC,UAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM,GACnC,KAAK,KAAK,EACV,OAAO,UAAU,EACjB,OAAO;AAEV,QAAI,SAAS,CAAC,wBAAwB,KAAK,GAAG;AAC5C,YAAM,IAAI,MAAM,8BAA8B,KAAK,aAAa,KAAK,EAAE;AAAA,IACzE;AAEA,UAAM,MAAM,MAAM,QAAQ,MAAM,IAAI,OAAO,CAAC,IAAI;AAChD,WAAO,mBAAoB,OAAO,UAAgB;AAAA,EACpD;AACF;;;ACnBO,SAAS,aAAa,MAAkB;AAC7C,QAAM,EAAE,eAAe,IAAI;AAE3B,SAAO,eAAe,OAAU;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAIG;AACD,UAAM,KAAK,eAAe;AAC1B,UAAM,aAAa,WAAW,MAAiC;AAC/D,UAAM,QAAQ,CAAC,kBAA2B;AAExC,UAAI,CAAC,eAAe;AAClB,YAAIA,KAAI,GACL,KAAK,KAAK,EACV,OAAO,EAAE,MAAM,YAAY,KAAK,WAAW,CAAQ;AACtD,mBAAW,UAAU,OAAO;AAC1B,UAAAA,KAAI,WAAWA,IAAG,OAAO,OAAO,OAAO,UAAU,OAAO,KAAK;AAAA,QAC/D;AACA,eAAOA;AAAA,MACT;AAGA,UAAI,IAAI,GACL,KAAK,KAAK,EACV,OAAO,YAAY;AAAA,QAClB,YAAY,EAAE,MAAM,YAAY,KAAK,WAAW;AAAA,MAClD,CAAQ;AACV,iBAAW,UAAU,OAAO;AAC1B,YAAI,WAAW,GAAG,OAAO,OAAO,OAAO,UAAU,OAAO,KAAK;AAAA,MAC/D;AACA,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,OAAO,MAA2B;AAC5C,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAO,EAAU,OAAO;AACxD,aAAO,EAAE,QAAQ,MAAM;AAAA,IACzB;AAEA,UAAM,QAAQ,MAAM,IAAI,MAAM,KAAK,CAAC;AACpC,QAAI,MAAM,SAAS,CAAC,wBAAwB,MAAM,KAAK,GAAG;AACxD,YAAM,MAAM,OAAO,MAAM,KAAK;AAC9B,UAAI,IAAI,YAAY,EAAE,SAAS,yBAAyB,GAAG;AACzD,cAAM,QAAQ,MAAM,IAAI,MAAM,IAAI,CAAC;AACnC,YAAI,MAAM,SAAS,CAAC,wBAAwB,MAAM,KAAK,GAAG;AACxD,gBAAM,IAAI;AAAA,YACR,8BAA8B,KAAK,aAAa,MAAM,KAAK;AAAA,UAC7D;AAAA,QACF;AACA,cAAMC,OAAM,MAAM,QAAQ,MAAM,MAAM,IACjC,MAAM,OAAO,CAAC,IACd,MAAM;AACX,eAAQA,OAAM,mBAAmBA,IAAQ,IAAI;AAAA,MAC/C;AAEA,YAAM,IAAI,MAAM,8BAA8B,KAAK,aAAa,MAAM,KAAK,EAAE;AAAA,IAC/E;AAEA,UAAM,MAAM,MAAM,QAAQ,MAAM,MAAM,IACjC,MAAM,OAAO,CAAC,IACd,MAAM;AACX,WAAQ,MAAM,mBAAmB,GAAQ,IAAI;AAAA,EAC/C;AACF;;;ACxEO,SAAS,iBAAiB,MAAsB;AACrD,QAAM,EAAE,eAAe,IAAI;AAE3B,SAAO,eAAe,WAAW;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAIG;AACD,UAAM,KAAK,eAAe;AAC1B,UAAM,aAAa,WAAW,MAAM;AACpC,UAAM,QAAQ,CAAC,kBAA2B;AACxC,UAAI,CAAC,eAAe;AAClB,YAAIC,KAAI,GACL,KAAK,KAAK,EACV,OAAO,EAAE,MAAM,YAAY,KAAK,WAAW,CAAQ;AACtD,mBAAW,UAAU,OAAO;AAC1B,UAAAA,KAAI,WAAWA,IAAG,OAAO,OAAO,OAAO,UAAU,OAAO,KAAK;AAAA,QAC/D;AACA,eAAOA;AAAA,MACT;AAEA,UAAI,IAAI,GACL,KAAK,KAAK,EACV,OAAO,YAAY;AAAA,QAClB,YAAY,EAAE,MAAM,YAAY,KAAK,WAAW;AAAA,MAClD,CAAQ;AACV,iBAAW,UAAU,OAAO;AAC1B,YAAI,WAAW,GAAG,OAAO,OAAO,OAAO,UAAU,OAAO,KAAK;AAAA,MAC/D;AACA,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,OAAO,MAA2B;AAC5C,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAO,EAAU,OAAO;AACxD,aAAO,EAAE,QAAQ,MAAM;AAAA,IACzB;AAEA,UAAM,QAAQ,MAAM,IAAI,MAAM,KAAK,CAAC;AACpC,QAAI,MAAM,SAAS,CAAC,wBAAwB,MAAM,KAAK,GAAG;AACxD,YAAM,MAAM,OAAO,MAAM,KAAK;AAC9B,UAAI,IAAI,YAAY,EAAE,SAAS,yBAAyB,GAAG;AACzD,cAAM,QAAQ,MAAM,IAAI,MAAM,IAAI,CAAC;AACnC,YAAI,MAAM,SAAS,CAAC,wBAAwB,MAAM,KAAK,GAAG;AACxD,gBAAM,IAAI;AAAA,YACR,kCAAkC,KAAK,aAAa,MAAM,KAAK;AAAA,UACjE;AAAA,QACF;AACA,eAAO,MAAM,QAAQ,MAAM,MAAM,IAAI,MAAM,OAAO,SAAS,MAAM,SAAS,IAAI;AAAA,MAChF;AAEA,YAAM,IAAI;AAAA,QACR,kCAAkC,KAAK,aAAa,MAAM,KAAK;AAAA,MACjE;AAAA,IACF;AAEA,WAAO,MAAM,QAAQ,MAAM,MAAM,IAAI,MAAM,OAAO,SAAS,MAAM,SAAS,IAAI;AAAA,EAChF;AACF;;;AC5DO,SAAS,aAAa,MAAkB;AAC7C,QAAM,EAAE,gBAAgB,QAAQ,IAAI;AAEpC,SAAO,eAAe,IAAI;AAAA,IACxB;AAAA,IACA;AAAA,EACF,GAGG;AACD,UAAM,KAAK,eAAe;AAC1B,QAAI,UAAU,GAAG,KAAK,KAAK;AAE3B,eAAW,UAAU,OAAO;AAC1B,gBAAU;AAAA,QACR;AAAA,QACA,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,IAAI,MAAO,QAAgB;AAAA,MACvC,UAAW,EAAE,QAAQ,IAAY;AAAA,IACnC;AAEA,QAAI,SAAS,CAAC,wBAAwB,KAAK,GAAG;AAC5C,YAAM,IAAI;AAAA,QACR,8BAA8B,KAAK,aAAa,KAAK;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AACF;;;AChCO,SAAS,iBAAiB,MAAsB;AACrD,QAAM,EAAE,gBAAgB,QAAQ,IAAI;AAEpC,SAAO,eAAe,WAAW;AAAA,IAC/B;AAAA,IACA;AAAA,EACF,GAGG;AACD,UAAM,KAAK,eAAe;AAC1B,UAAM,cAAc,GAAG,KAAK,KAAK;AACjC,QAAI,UAAU;AAEd,eAAW,UAAU,OAAO;AAC1B,gBAAU;AAAA,QACR;AAAA,QACA,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAO,QAAgB;AAAA,MACrD,UAAW,EAAE,QAAQ,IAAY;AAAA,IACnC,EAAE,OAAO;AAET,QAAI,SAAS,CAAC,wBAAwB,KAAK,GAAG;AAC5C,YAAM,IAAI;AAAA,QACR,kCAAkC,KAAK,aAAa,KAAK;AAAA,MAC3D;AAAA,IACF;AAEA,UAAM,eAAe,MAAM,QAAQ,MAAM,IAAI,OAAO,SAAS,SAAS,IAAI;AAG1E,UAAM,WAAW,MAAM;AAAA,MACrB,CAAC,MAAM,EAAE,aAAa,QAAQ,EAAE,SAAS;AAAA,IAC3C;AACA,QACE,YACA,MAAM,QAAQ,SAAS,KAAK,KAC5B,eAAe,SAAS,MAAM,QAC9B;AACA,UAAI,IAAI;AACR,iBAAW,KAAK,SAAS,OAAO;AAC9B,cAAM,IAAI,GAAG,KAAK,KAAK;AACvB,cAAM,WAAW;AAAA,UACf;AAAA,UACA,SAAS;AAAA,UACT;AAAA,UACA;AAAA,QACF;AACA,cAAM,EAAE,MAAM,SAAS,OAAO,OAAO,IAAI,MAAO,SAAiB;AAAA,UAC/D,UAAW,EAAE,QAAQ,IAAY;AAAA,QACnC,EAAE,OAAO;AACT,YAAI,UAAU,wBAAwB,MAAM,EAAG;AAC/C,aAAK,MAAM,QAAQ,OAAO,IAAI,QAAQ,SAAS,UAAU,IAAI;AAAA,MAC/D;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AACF;;;AC1DO,SAAS,cAAc,MAAmB;AAC/C,QAAM,EAAE,eAAe,IAAI;AAE3B,SAAO,eAAe,QAAW;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAKG;AACD,UAAM,KAAK,eAAe;AAE1B,UAAM,MAAM,OAAO,iBAA0C;AAC3D,YAAM,UACJ,UAAU,OAAO,SAAS,IACtB,OAAO,IAAI,CAAC,MAAM,aAAa,CAAC,CAAC,EAAE,KAAK,IAAI,IAC5C;AAEN,UAAI,UAAU,GAAG,KAAK,KAAK,EAAE,OAAO,OAAO;AAE3C,iBAAW,UAAU,OAAO;AAC1B,kBAAU;AAAA,UACR;AAAA,UACA,OAAO;AAAA,UACP,OAAO;AAAA,UACP,OAAO;AAAA,UACP;AAAA,QACF;AAAA,MACF;AAEA,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM,QAAQ,MAAM,CAAC;AACrD,aAAO,EAAE,QAAQ,MAAM;AAAA,IACzB;AAEA,UAAM,QAAQ,MAAM,IAAI,WAAW;AACnC,QAAI,MAAM,OAAO;AACf,UAAI,qBAAqB,MAAM,KAAK,GAAG;AACrC,cAAM,QAAQ,MAAM,IAAI,cAAc;AACtC,YAAI,MAAM,OAAO;AACf,gBAAM,IAAI;AAAA,YACR,+BAA+B,KAAK,aAAa,MAAM,KAAK;AAAA,UAC9D;AAAA,QACF;AAEA,cAAMC,QAAO,MAAM,QAAQ,MAAM,MAAM,IACnC,MAAM,SACN,MAAM,SACJ,CAAC,MAAM,MAAM,IACb,CAAC;AACP,cAAMC,OAAMD,MAAK,CAAC,KAAK;AACvB,eAAQC,OAAM,mBAAmBA,IAAQ,IAAI;AAAA,MAC/C;AAEA,YAAM,IAAI;AAAA,QACR,+BAA+B,KAAK,aAAa,MAAM,KAAK;AAAA,MAC9D;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,QAAQ,MAAM,MAAM,IACnC,MAAM,SACN,MAAM,SACJ,CAAC,MAAM,MAAM,IACb,CAAC;AACP,UAAM,MAAM,KAAK,CAAC,KAAK;AACvB,QAAI,CAAC,IAAK,QAAO;AAEjB,UAAM,SAAS,mBAAmB,GAAQ;AAC1C,UAAM,WAAW;AAAA,MACf,CAAC,MAA4C;AAAA,MAC7C;AAAA,IACF;AACA,WAAQ,SAAS,CAAC,IAAI,SAAS;AAAA,EACjC;AACF;;;AC5EO,SAAS,eAAe,MAAoB;AACjD,QAAM,EAAE,eAAe,IAAI;AAE3B,QAAM,0BAA0B,CAAC,UAA4B;AAC3D,UAAM,UAAU,OAAO,SAAS,EAAE,EAAE,YAAY;AAChD,WACE,QAAQ,SAAS,+BAA+B,KAChD,QAAQ,SAAS,SAAS,KAC1B,QAAQ,SAAS,WAAW,KAC5B,QAAQ,SAAS,iBAAiB,KAClC,QAAQ,SAAS,YAAY,KAC7B,QAAQ,SAAS,kBAAkB;AAAA,EAEvC;AAEA,SAAO,eAAe,SAAY;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAQG;AACD,UAAM,KAAK,eAAe;AAE1B,UAAM,MAAM,OACV,cACA,SACG;AACH,YAAM,UACJ,UAAU,OAAO,SAAS,IACtB,OAAO,IAAI,CAAC,MAAM,aAAa,CAAC,CAAC,EAAE,KAAK,IAAI,IAC5C;AAEN,UAAI,UAAU,GAAG,KAAK,KAAK,EAAE,OAAO,OAAO;AAE3C,UAAI,CAAC,MAAM,aAAa,OAAO;AAC7B,mBAAW,UAAU,OAAO;AAC1B,oBAAU;AAAA,YACR;AAAA,YACA,OAAO;AAAA,YACP,OAAO;AAAA,YACP,OAAO;AAAA,YACP;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,iBAAiB,MAAM,iBAAiB;AAC9C,YAAM,kBAAkB,MAAM,kBAAkB;AAEhD,UAAI,mBAAmB,QAAW;AAChC,kBAAU,QAAQ,MAAM,cAAc;AAAA,MACxC;AAEA,UAAI,oBAAoB,QAAW;AACjC,kBAAU,QAAQ,OAAO,eAAe;AAAA,MAC1C;AAEA,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM;AACtC,aAAO,EAAE,QAAQ,MAAM;AAAA,IACzB;AAEA,QAAI,QAAQ,MAAM,IAAI,WAAW;AACjC,QAAI,MAAM,SAAS,wBAAwB,MAAM,KAAK,GAAG;AACvD,YAAM,QAAQ,MAAM,IAAI,WAAW;AACnC,UAAI,CAAC,MAAM,MAAO,SAAQ;AAAA,IAC5B;AAEA,UAAM,WAAW,CAAC,QACf,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC;AAE/B,UAAM,YAAY,CAAC,SAAc;AAC/B,UAAI,CAAC,OAAQ,QAAO;AACpB,YAAM,YAAY,OAAO;AACzB,WAAK,KAAK,CAAC,GAAG,MAAM;AAClB,cAAM,OAAQ,EAA8B,SAAS;AACrD,cAAM,OAAQ,EAA8B,SAAS;AACrD,YAAI,QAAQ,QAAQ,QAAQ,KAAM,QAAO;AACzC,YAAI,QAAQ,KAAM,QAAO,OAAO,cAAc,QAAQ,KAAK;AAC3D,YAAI,QAAQ,KAAM,QAAO,OAAO,cAAc,QAAQ,IAAI;AAC1D,cAAM,MACJ,OAAO,SAAS,YAAY,OAAO,SAAS,WACxC,KAAK,cAAc,IAAI,IACvB,OAAO,OACL,KACA,OAAO,OACL,IACA;AACV,eAAO,OAAO,cAAc,QAAQ,MAAM,CAAC;AAAA,MAC7C,CAAC;AACD,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,CAAC,SAAoC;AACtD,YAAM,iBAAiB,KAAK,IAAI,CAAC,MAAM,mBAAmB,CAAC,CAAC;AAE5D,UAAI,CAAC,OAAO,OAAQ,QAAO,UAAU,cAAc;AAEnD,YAAM,WAAW;AAAA,QACf;AAAA,QACA;AAAA,MACF;AAKA,UAAI,SAAS,WAAW,eAAe,QAAQ;AAC7C,cAAM,MAAM,UAAU;AACtB,cAAM,MAAM,UAAU,SAAY,MAAM,QAAQ;AAChD,eAAO,UAAU,QAAQ,EAAE,MAAM,KAAK,GAAG;AAAA,MAC3C;AAEA,aAAO,UAAU,QAAQ;AAAA,IAC3B;AAEA,UAAM,qBAAqB,CAAC,SAAoC;AAC9D,YAAM,eAAe,WAAW,IAAI;AACpC,YAAM,MAAM,UAAU;AACtB,YAAM,MAAM,UAAU,SAAY,MAAM,QAAQ;AAChD,aAAO,aAAa,MAAM,KAAK,GAAG;AAAA,IACpC;AAEA,QAAI,MAAM,OAAO;AACf,UAAI,qBAAqB,MAAM,KAAK,GAAG;AACrC,cAAM,QAAQ,MAAM,IAAI,cAAc;AACtC,YAAI,MAAM,OAAO;AACf,gBAAM,IAAI;AAAA,YACR,gCAAgC,KAAK,aAAa,MAAM,KAAK;AAAA,UAC/D;AAAA,QACF;AACA,cAAM,YAAY,SAAS,MAAM,MAAM;AAGvC,YAAI,OAAO,QAAQ;AACjB,gBAAM,QAAQ,MAAM,IAAI,gBAAgB;AAAA,YACtC,WAAW;AAAA,YACX,eAAe,KAAK,KAAK,UAAU,MAAM,SAAS,KAAK,KAAK,GAAI;AAAA,YAChE,gBAAgB;AAAA,UAClB,CAAC;AACD,cAAI,CAAC,MAAM,MAAO,QAAO,mBAAmB,SAAS,MAAM,MAAM,CAAC;AAAA,QACpE;AACA,eAAO,WAAW,SAAS;AAAA,MAC7B;AAEA,YAAM,IAAI;AAAA,QACR,gCAAgC,KAAK,aAAa,MAAM,KAAK;AAAA,MAC/D;AAAA,IACF;AAEA,UAAM,YAAY,SAAS,MAAM,MAAM;AACvC,QAAI,OAAO,QAAQ;AACjB,YAAM,QAAQ,MAAM,IAAI,aAAa;AAAA,QACnC,WAAW;AAAA,QACX,eAAe,KAAK,KAAK,UAAU,MAAM,SAAS,KAAK,KAAK,GAAI;AAAA,QAChE,gBAAgB;AAAA,MAClB,CAAC;AACD,UAAI,CAAC,MAAM,MAAO,QAAO,mBAAmB,SAAS,MAAM,MAAM,CAAC;AAAA,IACpE;AACA,WAAO,WAAW,SAAS;AAAA,EAC7B;AACF;;;AC3KO,SAAS,YAAY,MAAiB;AAC3C,QAAM,EAAE,eAAe,IAAI;AAE3B,SAAO,eAAe,MAAM;AAAA,IAC1B;AAAA,IACA;AAAA,EACF,GAGG;AACD,UAAM,KAAK,eAAe;AAE1B,UAAM,MAAM,OAAO,iBAA0C;AAC3D,UAAI,UAAU,GAAG,KAAK,KAAK,EAAE,OAAO;AAEpC,UAAI,OAAO;AACT,mBAAW,UAAU,OAAO;AAC1B,oBAAU;AAAA,YACR;AAAA,YACA,OAAO;AAAA,YACP,OAAO;AAAA,YACP,OAAO;AAAA,YACP;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM;AACtC,aAAO,EAAE,QAAQ,MAAM;AAAA,IACzB;AAEA,UAAM,QAAQ,MAAM,IAAI,WAAW;AACnC,QAAI,MAAM,OAAO;AACf,UAAI,qBAAqB,MAAM,KAAK,GAAG;AACrC,cAAM,QAAQ,MAAM,IAAI,cAAc;AACtC,YAAI,MAAM,OAAO;AACf,gBAAM,IAAI;AAAA,YACR,6BAA6B,KAAK,aAAa,MAAM,KAAK;AAAA,UAC5D;AAAA,QACF;AACA,eAAO,MAAM,QAAQ,MAAM,MAAM,IAAI,MAAM,OAAO,SAAS;AAAA,MAC7D;AACA,YAAM,IAAI;AAAA,QACR,6BAA6B,KAAK,aAAa,MAAM,KAAK;AAAA,MAC5D;AAAA,IACF;AAEA,WAAO,MAAM,QAAQ,MAAM,MAAM,IAAI,MAAM,OAAO,SAAS;AAAA,EAC7D;AACF;;;AVqBO,IAAM,gBAAgB,CAC3B,WACsC;AACtC,MAAI,WAAuB;AAC3B,MAAI,sBAAsB;AAE1B,QAAM,uBACJ,OAAO,OAAO,QAAQ,YACtB,OAAO,IAAI,SAAS,KACpB,OAAO,OAAO,WAAW,YACzB,OAAO,OAAO,SAAS;AAEzB,WAAS,iBAAsB;AAC7B,QAAI,sBAAsB;AACxB,UAAI,CAAC,UAAU;AACb,mBAAW,aAAa,OAAO,KAAM,OAAO,QAAS;AAAA,UACnD,QAAQ,OAAO;AAAA,UACf,GAAI,OAAO,WAAW,EAAE,SAAS,OAAO,QAAQ;AAAA,QAClD,CAAQ;AAAA,MACV;AACA,aAAO;AAAA,IACT;AAEA,UAAM,EAAE,QAAQ,cAAc,SAAAC,SAAQ,IAAI,sBAAsB;AAAA,MAC9D,YAAY,OAAO;AAAA,MACnB,OAAO,OAAO,eAAe;AAAA,IAC/B,CAAC;AAED,UAAM,MAAM,OAAO,OAAO,aAAa,OAAO;AAC9C,UAAM,SAAS,OAAO,UAAU,aAAa,OAAO;AACpD,UAAM,SAAS,OAAO,UAAU,aAAa,OAAO;AAEpD,QAAI,CAAC,OAAO,CAAC,QAAQ;AACnB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,YAAYA,aAAY,qBAAqB;AAChD,iBAAW,aAAa,KAAK,QAAQ;AAAA,QACnC;AAAA,QACA,GAAI,OAAO,WAAW,EAAE,SAAS,OAAO,QAAQ;AAAA,MAClD,CAAQ;AACR,4BAAsBA;AAAA,IACxB;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,EAAE,gBAAgB,SAAS,OAAO,QAAQ;AAEvD,SAAO,qBAAqB;AAAA,IAC1B,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,aAAa;AAAA,MACb,WAAW,OAAO,aAAa;AAAA,MAC/B,WAAW,OAAO,aAAa;AAAA,MAC/B,cAAc;AAAA,MACd,eAAe;AAAA,MACf,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB,eAAe;AAAA,IACjB;AAAA,IACA,SAAS,MAAM;AACb,aAAO;AAAA,QACL,QAAQ,aAAa,IAAI;AAAA,QACzB,QAAQ,aAAa,IAAI;AAAA,QACzB,YAAY,iBAAiB,IAAI;AAAA,QACjC,QAAQ,aAAa,IAAI;AAAA,QACzB,YAAY,iBAAiB,IAAI;AAAA,QACjC,SAAS,cAAc,IAAI;AAAA,QAC3B,UAAU,eAAe,IAAI;AAAA,QAC7B,OAAO,YAAY,IAAI;AAAA,MACzB;AAAA,IACF;AAAA,EACF,CAAC;AACH;","names":["b","row","b","rows","row","version"]}
|