@xylex-group/better-auth-athena 1.0.7 → 1.0.8
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 +38 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +36 -5
- 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.8`
|
|
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
|
@@ -30,7 +30,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
athenaAdapter: () => athenaAdapter
|
|
33
|
+
athenaAdapter: () => athenaAdapter,
|
|
34
|
+
getAthenaGlobalConfig: () => getAthenaGlobalConfig
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(index_exports);
|
|
36
37
|
var import_adapters = require("better-auth/adapters");
|
|
@@ -267,9 +268,18 @@ function updateMethod(deps) {
|
|
|
267
268
|
}) {
|
|
268
269
|
const db = ensureDbClient();
|
|
269
270
|
const updateData = toDbRecord(update);
|
|
271
|
+
const debugUpdates = process?.env?.ATHENA_ADAPTER_DEBUG_UPDATES === "1";
|
|
272
|
+
const debugLog = (event, extra) => {
|
|
273
|
+
if (!debugUpdates) return;
|
|
274
|
+
console.info("[AthenaAdapter][update]", {
|
|
275
|
+
event,
|
|
276
|
+
model,
|
|
277
|
+
...extra
|
|
278
|
+
});
|
|
279
|
+
};
|
|
270
280
|
const build = (useRetryShape) => {
|
|
271
281
|
if (!useRetryShape) {
|
|
272
|
-
let b2 = db.from(model).update(
|
|
282
|
+
let b2 = db.from(model).update(updateData);
|
|
273
283
|
for (const clause of where) {
|
|
274
284
|
b2 = applyWhere(b2, clause.field, clause.operator, clause.value);
|
|
275
285
|
}
|
|
@@ -289,19 +299,23 @@ function updateMethod(deps) {
|
|
|
289
299
|
};
|
|
290
300
|
const first = await run(build(false));
|
|
291
301
|
if (first.error && !isSuccessMessageInError(first.error)) {
|
|
302
|
+
debugLog("primary_failed", { error: String(first.error) });
|
|
292
303
|
const msg = String(first.error);
|
|
293
304
|
if (msg.toLowerCase().includes("update payload required")) {
|
|
294
305
|
const retry = await run(build(true));
|
|
295
306
|
if (retry.error && !isSuccessMessageInError(retry.error)) {
|
|
307
|
+
debugLog("retry_failed", { error: String(retry.error) });
|
|
296
308
|
throw new Error(
|
|
297
309
|
`[AthenaAdapter] update on "${model}" failed: ${retry.error}`
|
|
298
310
|
);
|
|
299
311
|
}
|
|
312
|
+
debugLog("retry_succeeded", { shape: "updateBody(data/set)" });
|
|
300
313
|
const row2 = Array.isArray(retry.result) ? retry.result[0] : retry.result;
|
|
301
314
|
return row2 ? mapRowToBetterAuth(row2) : null;
|
|
302
315
|
}
|
|
303
316
|
throw new Error(`[AthenaAdapter] update on "${model}" failed: ${first.error}`);
|
|
304
317
|
}
|
|
318
|
+
debugLog("primary_succeeded", { shape: "plain" });
|
|
305
319
|
const row = Array.isArray(first.result) ? first.result[0] : first.result;
|
|
306
320
|
return row ? mapRowToBetterAuth(row) : null;
|
|
307
321
|
};
|
|
@@ -317,9 +331,18 @@ function updateManyMethod(deps) {
|
|
|
317
331
|
}) {
|
|
318
332
|
const db = ensureDbClient();
|
|
319
333
|
const updateData = toDbRecord(update);
|
|
334
|
+
const debugUpdates = process.env.ATHENA_ADAPTER_DEBUG_UPDATES === "1";
|
|
335
|
+
const debugLog = (event, extra) => {
|
|
336
|
+
if (!debugUpdates) return;
|
|
337
|
+
console.info("[AthenaAdapter][updateMany]", {
|
|
338
|
+
event,
|
|
339
|
+
model,
|
|
340
|
+
...extra
|
|
341
|
+
});
|
|
342
|
+
};
|
|
320
343
|
const build = (useRetryShape) => {
|
|
321
344
|
if (!useRetryShape) {
|
|
322
|
-
let b2 = db.from(model).update(
|
|
345
|
+
let b2 = db.from(model).update(updateData);
|
|
323
346
|
for (const clause of where) {
|
|
324
347
|
b2 = applyWhere(b2, clause.field, clause.operator, clause.value);
|
|
325
348
|
}
|
|
@@ -339,20 +362,24 @@ function updateManyMethod(deps) {
|
|
|
339
362
|
};
|
|
340
363
|
const first = await run(build(false));
|
|
341
364
|
if (first.error && !isSuccessMessageInError(first.error)) {
|
|
365
|
+
debugLog("primary_failed", { error: String(first.error) });
|
|
342
366
|
const msg = String(first.error);
|
|
343
367
|
if (msg.toLowerCase().includes("update payload required")) {
|
|
344
368
|
const retry = await run(build(true));
|
|
345
369
|
if (retry.error && !isSuccessMessageInError(retry.error)) {
|
|
370
|
+
debugLog("retry_failed", { error: String(retry.error) });
|
|
346
371
|
throw new Error(
|
|
347
372
|
`[AthenaAdapter] updateMany on "${model}" failed: ${retry.error}`
|
|
348
373
|
);
|
|
349
374
|
}
|
|
375
|
+
debugLog("retry_succeeded", { shape: "updateBody(data/set)" });
|
|
350
376
|
return Array.isArray(retry.result) ? retry.result.length : retry.result ? 1 : 0;
|
|
351
377
|
}
|
|
352
378
|
throw new Error(
|
|
353
379
|
`[AthenaAdapter] updateMany on "${model}" failed: ${first.error}`
|
|
354
380
|
);
|
|
355
381
|
}
|
|
382
|
+
debugLog("primary_succeeded", { shape: "plain" });
|
|
356
383
|
return Array.isArray(first.result) ? first.result.length : first.result ? 1 : 0;
|
|
357
384
|
};
|
|
358
385
|
}
|
|
@@ -697,7 +724,8 @@ var athenaAdapter = (config) => {
|
|
|
697
724
|
supportsDates: true,
|
|
698
725
|
supportsBooleans: true,
|
|
699
726
|
supportsNumericIds: true,
|
|
700
|
-
supportsUUIDs: true
|
|
727
|
+
supportsUUIDs: true,
|
|
728
|
+
supportsArrays: true
|
|
701
729
|
},
|
|
702
730
|
adapter: () => {
|
|
703
731
|
return {
|
|
@@ -708,13 +736,17 @@ var athenaAdapter = (config) => {
|
|
|
708
736
|
deleteMany: deleteManyMethod(deps),
|
|
709
737
|
findOne: findOneMethod(deps),
|
|
710
738
|
findMany: findManyMethod(deps),
|
|
711
|
-
count: countMethod(deps)
|
|
739
|
+
count: countMethod(deps),
|
|
740
|
+
options: {
|
|
741
|
+
debugLogs: config.debugLogs ?? false
|
|
742
|
+
}
|
|
712
743
|
};
|
|
713
744
|
}
|
|
714
745
|
});
|
|
715
746
|
};
|
|
716
747
|
// Annotate the CommonJS export names for ESM import in node:
|
|
717
748
|
0 && (module.exports = {
|
|
718
|
-
athenaAdapter
|
|
749
|
+
athenaAdapter,
|
|
750
|
+
getAthenaGlobalConfig
|
|
719
751
|
});
|
|
720
752
|
//# sourceMappingURL=index.cjs.map
|
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 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"]}
|
|
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 supportsArrays: 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 options: {\r\n debugLogs: config.debugLogs ?? false,\r\n \r\n },\r\n };\r\n },\r\n });\r\n};\r\n\r\n// For testing purposes, we export the internal config function to allow resetting the cached client between tests.\r\nexport { getAthenaGlobalConfig } from \"./config\";\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 debugUpdates = process?.env?.ATHENA_ADAPTER_DEBUG_UPDATES === \"1\";\r\n const debugLog = (event: string, extra?: Record<string, unknown>) => {\r\n if (!debugUpdates) return;\r\n console.info(\"[AthenaAdapter][update]\", {\r\n event,\r\n model,\r\n ...extra,\r\n });\r\n };\r\n const build = (useRetryShape: boolean) => {\r\n // Primary shape: modern gateway/client combinations accept plain update values.\r\n if (!useRetryShape) {\r\n let b = db.from(model).update(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: explicit wrappers for gateways expecting data/set.\r\n let b = db\r\n .from(model)\r\n .update(updateData as any, {\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 debugLog(\"primary_failed\", { error: String(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 debugLog(\"retry_failed\", { error: String(retry.error) });\r\n throw new Error(\r\n `[AthenaAdapter] update on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n debugLog(\"retry_succeeded\", { shape: \"updateBody(data/set)\" });\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 debugLog(\"primary_succeeded\", { shape: \"plain\" });\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 debugUpdates = process.env.ATHENA_ADAPTER_DEBUG_UPDATES === \"1\";\r\n const debugLog = (event: string, extra?: Record<string, unknown>) => {\r\n if (!debugUpdates) return;\r\n console.info(\"[AthenaAdapter][updateMany]\", {\r\n event,\r\n model,\r\n ...extra,\r\n });\r\n };\r\n const build = (useRetryShape: boolean) => {\r\n if (!useRetryShape) {\r\n let b = db.from(model).update(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 as any, {\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 debugLog(\"primary_failed\", { error: String(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 debugLog(\"retry_failed\", { error: String(retry.error) });\r\n throw new Error(\r\n `[AthenaAdapter] updateMany on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n debugLog(\"retry_succeeded\", { shape: \"updateBody(data/set)\" });\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 debugLog(\"primary_succeeded\", { shape: \"plain\" });\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.d.cts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { DBAdapterDebugLogOption, AdapterFactory } from 'better-auth/adapters';
|
|
2
2
|
import { BetterAuthOptions } from 'better-auth';
|
|
3
3
|
|
|
4
|
+
type AthenaGlobalConfig = {
|
|
5
|
+
athena: {
|
|
6
|
+
url: string;
|
|
7
|
+
apiKey: string;
|
|
8
|
+
client?: string;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
declare function getAthenaGlobalConfig(options?: {
|
|
12
|
+
configPath?: string;
|
|
13
|
+
watch?: boolean;
|
|
14
|
+
}): {
|
|
15
|
+
config: AthenaGlobalConfig;
|
|
16
|
+
version: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
4
19
|
/**
|
|
5
20
|
* Configuration options for the Athena adapter.
|
|
6
21
|
*/
|
|
@@ -64,4 +79,4 @@ interface AthenaAdapterConfig {
|
|
|
64
79
|
*/
|
|
65
80
|
declare const athenaAdapter: (config: AthenaAdapterConfig) => AdapterFactory<BetterAuthOptions>;
|
|
66
81
|
|
|
67
|
-
export { type AthenaAdapterConfig, athenaAdapter };
|
|
82
|
+
export { type AthenaAdapterConfig, athenaAdapter, getAthenaGlobalConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { DBAdapterDebugLogOption, AdapterFactory } from 'better-auth/adapters';
|
|
2
2
|
import { BetterAuthOptions } from 'better-auth';
|
|
3
3
|
|
|
4
|
+
type AthenaGlobalConfig = {
|
|
5
|
+
athena: {
|
|
6
|
+
url: string;
|
|
7
|
+
apiKey: string;
|
|
8
|
+
client?: string;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
declare function getAthenaGlobalConfig(options?: {
|
|
12
|
+
configPath?: string;
|
|
13
|
+
watch?: boolean;
|
|
14
|
+
}): {
|
|
15
|
+
config: AthenaGlobalConfig;
|
|
16
|
+
version: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
4
19
|
/**
|
|
5
20
|
* Configuration options for the Athena adapter.
|
|
6
21
|
*/
|
|
@@ -64,4 +79,4 @@ interface AthenaAdapterConfig {
|
|
|
64
79
|
*/
|
|
65
80
|
declare const athenaAdapter: (config: AthenaAdapterConfig) => AdapterFactory<BetterAuthOptions>;
|
|
66
81
|
|
|
67
|
-
export { type AthenaAdapterConfig, athenaAdapter };
|
|
82
|
+
export { type AthenaAdapterConfig, athenaAdapter, getAthenaGlobalConfig };
|
package/dist/index.js
CHANGED
|
@@ -235,9 +235,18 @@ function updateMethod(deps) {
|
|
|
235
235
|
}) {
|
|
236
236
|
const db = ensureDbClient();
|
|
237
237
|
const updateData = toDbRecord(update);
|
|
238
|
+
const debugUpdates = process?.env?.ATHENA_ADAPTER_DEBUG_UPDATES === "1";
|
|
239
|
+
const debugLog = (event, extra) => {
|
|
240
|
+
if (!debugUpdates) return;
|
|
241
|
+
console.info("[AthenaAdapter][update]", {
|
|
242
|
+
event,
|
|
243
|
+
model,
|
|
244
|
+
...extra
|
|
245
|
+
});
|
|
246
|
+
};
|
|
238
247
|
const build = (useRetryShape) => {
|
|
239
248
|
if (!useRetryShape) {
|
|
240
|
-
let b2 = db.from(model).update(
|
|
249
|
+
let b2 = db.from(model).update(updateData);
|
|
241
250
|
for (const clause of where) {
|
|
242
251
|
b2 = applyWhere(b2, clause.field, clause.operator, clause.value);
|
|
243
252
|
}
|
|
@@ -257,19 +266,23 @@ function updateMethod(deps) {
|
|
|
257
266
|
};
|
|
258
267
|
const first = await run(build(false));
|
|
259
268
|
if (first.error && !isSuccessMessageInError(first.error)) {
|
|
269
|
+
debugLog("primary_failed", { error: String(first.error) });
|
|
260
270
|
const msg = String(first.error);
|
|
261
271
|
if (msg.toLowerCase().includes("update payload required")) {
|
|
262
272
|
const retry = await run(build(true));
|
|
263
273
|
if (retry.error && !isSuccessMessageInError(retry.error)) {
|
|
274
|
+
debugLog("retry_failed", { error: String(retry.error) });
|
|
264
275
|
throw new Error(
|
|
265
276
|
`[AthenaAdapter] update on "${model}" failed: ${retry.error}`
|
|
266
277
|
);
|
|
267
278
|
}
|
|
279
|
+
debugLog("retry_succeeded", { shape: "updateBody(data/set)" });
|
|
268
280
|
const row2 = Array.isArray(retry.result) ? retry.result[0] : retry.result;
|
|
269
281
|
return row2 ? mapRowToBetterAuth(row2) : null;
|
|
270
282
|
}
|
|
271
283
|
throw new Error(`[AthenaAdapter] update on "${model}" failed: ${first.error}`);
|
|
272
284
|
}
|
|
285
|
+
debugLog("primary_succeeded", { shape: "plain" });
|
|
273
286
|
const row = Array.isArray(first.result) ? first.result[0] : first.result;
|
|
274
287
|
return row ? mapRowToBetterAuth(row) : null;
|
|
275
288
|
};
|
|
@@ -285,9 +298,18 @@ function updateManyMethod(deps) {
|
|
|
285
298
|
}) {
|
|
286
299
|
const db = ensureDbClient();
|
|
287
300
|
const updateData = toDbRecord(update);
|
|
301
|
+
const debugUpdates = process.env.ATHENA_ADAPTER_DEBUG_UPDATES === "1";
|
|
302
|
+
const debugLog = (event, extra) => {
|
|
303
|
+
if (!debugUpdates) return;
|
|
304
|
+
console.info("[AthenaAdapter][updateMany]", {
|
|
305
|
+
event,
|
|
306
|
+
model,
|
|
307
|
+
...extra
|
|
308
|
+
});
|
|
309
|
+
};
|
|
288
310
|
const build = (useRetryShape) => {
|
|
289
311
|
if (!useRetryShape) {
|
|
290
|
-
let b2 = db.from(model).update(
|
|
312
|
+
let b2 = db.from(model).update(updateData);
|
|
291
313
|
for (const clause of where) {
|
|
292
314
|
b2 = applyWhere(b2, clause.field, clause.operator, clause.value);
|
|
293
315
|
}
|
|
@@ -307,20 +329,24 @@ function updateManyMethod(deps) {
|
|
|
307
329
|
};
|
|
308
330
|
const first = await run(build(false));
|
|
309
331
|
if (first.error && !isSuccessMessageInError(first.error)) {
|
|
332
|
+
debugLog("primary_failed", { error: String(first.error) });
|
|
310
333
|
const msg = String(first.error);
|
|
311
334
|
if (msg.toLowerCase().includes("update payload required")) {
|
|
312
335
|
const retry = await run(build(true));
|
|
313
336
|
if (retry.error && !isSuccessMessageInError(retry.error)) {
|
|
337
|
+
debugLog("retry_failed", { error: String(retry.error) });
|
|
314
338
|
throw new Error(
|
|
315
339
|
`[AthenaAdapter] updateMany on "${model}" failed: ${retry.error}`
|
|
316
340
|
);
|
|
317
341
|
}
|
|
342
|
+
debugLog("retry_succeeded", { shape: "updateBody(data/set)" });
|
|
318
343
|
return Array.isArray(retry.result) ? retry.result.length : retry.result ? 1 : 0;
|
|
319
344
|
}
|
|
320
345
|
throw new Error(
|
|
321
346
|
`[AthenaAdapter] updateMany on "${model}" failed: ${first.error}`
|
|
322
347
|
);
|
|
323
348
|
}
|
|
349
|
+
debugLog("primary_succeeded", { shape: "plain" });
|
|
324
350
|
return Array.isArray(first.result) ? first.result.length : first.result ? 1 : 0;
|
|
325
351
|
};
|
|
326
352
|
}
|
|
@@ -665,7 +691,8 @@ var athenaAdapter = (config) => {
|
|
|
665
691
|
supportsDates: true,
|
|
666
692
|
supportsBooleans: true,
|
|
667
693
|
supportsNumericIds: true,
|
|
668
|
-
supportsUUIDs: true
|
|
694
|
+
supportsUUIDs: true,
|
|
695
|
+
supportsArrays: true
|
|
669
696
|
},
|
|
670
697
|
adapter: () => {
|
|
671
698
|
return {
|
|
@@ -676,12 +703,16 @@ var athenaAdapter = (config) => {
|
|
|
676
703
|
deleteMany: deleteManyMethod(deps),
|
|
677
704
|
findOne: findOneMethod(deps),
|
|
678
705
|
findMany: findManyMethod(deps),
|
|
679
|
-
count: countMethod(deps)
|
|
706
|
+
count: countMethod(deps),
|
|
707
|
+
options: {
|
|
708
|
+
debugLogs: config.debugLogs ?? false
|
|
709
|
+
}
|
|
680
710
|
};
|
|
681
711
|
}
|
|
682
712
|
});
|
|
683
713
|
};
|
|
684
714
|
export {
|
|
685
|
-
athenaAdapter
|
|
715
|
+
athenaAdapter,
|
|
716
|
+
getAthenaGlobalConfig
|
|
686
717
|
};
|
|
687
718
|
//# sourceMappingURL=index.js.map
|
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 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":["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 supportsArrays: 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 options: {\r\n debugLogs: config.debugLogs ?? false,\r\n \r\n },\r\n };\r\n },\r\n });\r\n};\r\n\r\n// For testing purposes, we export the internal config function to allow resetting the cached client between tests.\r\nexport { getAthenaGlobalConfig } from \"./config\";\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 debugUpdates = process?.env?.ATHENA_ADAPTER_DEBUG_UPDATES === \"1\";\r\n const debugLog = (event: string, extra?: Record<string, unknown>) => {\r\n if (!debugUpdates) return;\r\n console.info(\"[AthenaAdapter][update]\", {\r\n event,\r\n model,\r\n ...extra,\r\n });\r\n };\r\n const build = (useRetryShape: boolean) => {\r\n // Primary shape: modern gateway/client combinations accept plain update values.\r\n if (!useRetryShape) {\r\n let b = db.from(model).update(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: explicit wrappers for gateways expecting data/set.\r\n let b = db\r\n .from(model)\r\n .update(updateData as any, {\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 debugLog(\"primary_failed\", { error: String(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 debugLog(\"retry_failed\", { error: String(retry.error) });\r\n throw new Error(\r\n `[AthenaAdapter] update on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n debugLog(\"retry_succeeded\", { shape: \"updateBody(data/set)\" });\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 debugLog(\"primary_succeeded\", { shape: \"plain\" });\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 debugUpdates = process.env.ATHENA_ADAPTER_DEBUG_UPDATES === \"1\";\r\n const debugLog = (event: string, extra?: Record<string, unknown>) => {\r\n if (!debugUpdates) return;\r\n console.info(\"[AthenaAdapter][updateMany]\", {\r\n event,\r\n model,\r\n ...extra,\r\n });\r\n };\r\n const build = (useRetryShape: boolean) => {\r\n if (!useRetryShape) {\r\n let b = db.from(model).update(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 as any, {\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 debugLog(\"primary_failed\", { error: String(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 debugLog(\"retry_failed\", { error: String(retry.error) });\r\n throw new Error(\r\n `[AthenaAdapter] updateMany on \"${model}\" failed: ${retry.error}`,\r\n );\r\n }\r\n debugLog(\"retry_succeeded\", { shape: \"updateBody(data/set)\" });\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 debugLog(\"primary_succeeded\", { shape: \"plain\" });\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":["b","row","b","rows","row","version"]}
|