@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # better-auth-athena
2
2
 
3
- current version: `1.0.7`
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({ data: updateData, set: updateData });
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({ data: updateData, set: updateData });
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
@@ -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({ data: updateData, set: updateData });
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({ data: updateData, set: updateData });
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"]}
package/package.json CHANGED
@@ -55,7 +55,7 @@
55
55
  },
56
56
  "type": "module",
57
57
  "types": "./dist/index.d.ts",
58
- "version": "1.0.7",
58
+ "version": "1.0.8",
59
59
  "scripts": {
60
60
  "build": "tsup",
61
61
  "dev": "tsup --watch",