@xylex-group/athena 2.4.0 → 2.4.1

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
  # athena-js
2
2
 
3
- current version: `2.4.0`
3
+ current version: `2.4.1`
4
4
  `@xylex-group/athena` is a database driver and API gateway SDK that lets you interact with SQL backends over HTTP through a fluent builder API. It ships a typed query builder for Node.js / server environments plus Athena-native React hooks for client-side use.
5
5
 
6
6
  ## Install
@@ -54,6 +54,31 @@ The existing string-based `.select(...)` chain remains fully supported for compa
54
54
  including alias/FK patterns like `from:sender_id(name)`.
55
55
  For the full AST model, route contract, error behavior, and Athena server implications,
56
56
  see [`docs/findmany-ast-and-server-contract.md`](docs/findmany-ast-and-server-contract.md).
57
+ For method-by-method runtime AST/state/payload models across `select(...)`, mutations,
58
+ `rpc(...)`, `query(...)`, and fluent builder filters, see
59
+ [`docs/runtime-method-ast-models.md`](docs/runtime-method-ast-models.md).
60
+
61
+ ### Gateway auth-session forwarding
62
+
63
+ If you need Athena server-side auth rollout to inspect auth context on normal query requests, the SDK now mirrors available auth state into gateway headers while still forwarding the original headers too.
64
+
65
+ Current behavior:
66
+
67
+ - `headers.Cookie` containing an Athena auth session cookie keeps `Cookie` and also adds `X-Athena-Auth-Session-Token`
68
+ - `headers.Authorization: Bearer ...` keeps `Authorization` and also adds `X-Athena-Auth-Bearer-Token`
69
+ - `createClient(..., { auth: { bearerToken } })` mirrors that token onto gateway/query requests as `X-Athena-Auth-Bearer-Token`
70
+
71
+ Server-side cookie forwarding example:
72
+
73
+ ```ts
74
+ const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
75
+ headers: {
76
+ Cookie: request.headers.get("cookie") ?? "",
77
+ },
78
+ });
79
+ ```
80
+
81
+ For the full contract, precedence rules, browser/server caveats, and rollout guidance, see [`docs/auth-session-forwarding.md`](docs/auth-session-forwarding.md).
57
82
 
58
83
  ### Auth client (Athena Auth server)
59
84
 
@@ -350,6 +375,22 @@ const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
350
375
  });
351
376
  ```
352
377
 
378
+ ### Read retries (experimental)
379
+
380
+ ```ts
381
+ const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
382
+ experimental: {
383
+ retryReads: true,
384
+ },
385
+ });
386
+ ```
387
+
388
+ With `retryReads: true`, the SDK automatically retries retryable read failures for `select`, `findMany(...)`, and `query(...)`.
389
+
390
+ - two additional attempts are applied internally
391
+ - retry classification follows the SDK's normalized `retryable` signal
392
+ - writes (`insert`, `upsert`, `update`, `delete`) are not retried by this flag
393
+
353
394
  ### findMany AST transport (experimental)
354
395
 
355
396
  ```ts
@@ -360,10 +401,13 @@ const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
360
401
  });
361
402
  ```
362
403
 
363
- With `findManyAst: true`, clean `findMany(...)` calls send the original object AST body to `/gateway/fetch` instead of compiling the select tree down to `columns` and `conditions` first.
404
+ With `findManyAst: true`, clean `findMany(...)` calls can send an AST-style body to `/gateway/fetch` instead of compiling the select tree down to `columns` and `conditions` first.
364
405
 
365
406
  - this is opt-in and meant for gateways that explicitly support direct AST bodies
366
407
  - existing compiled `findMany(...)` transport remains the default
408
+ - shorthand `where` filters are normalized to explicit operator objects before the AST body is sent
409
+ - UUID-like equality filters that need the SDK's `::text` comparison still fall back to the legacy query/compiled path
410
+ - nested relation select strings stay off the SQL query fallback path and continue through `/gateway/fetch`
367
411
  - chained builder filters or pagination state that the AST body cannot represent losslessly yet continue to use the legacy compiled path
368
412
  - trace output still includes synthesized SQL so diagnostics stay readable
369
413
 
@@ -384,12 +428,27 @@ Utilities that are intentionally not exported from the root package are availabl
384
428
 
385
429
  ```ts
386
430
  import {
431
+ asString,
432
+ asBoolean,
433
+ asBooleanOrNull,
434
+ asRecord,
435
+ asIdentifier,
436
+ firstString,
437
+ readTrimmedString,
438
+ asNumber,
439
+ asStringArray,
387
440
  slugify,
388
441
  trimTrailingSlashes,
389
442
  parseBooleanFlag,
390
443
  isLocalHostname,
391
444
  clearAuthCookies,
392
445
  proxyRequestHeaders,
446
+ sqlText,
447
+ escapeLikePatternValue,
448
+ quoteSqlStringLiteral,
449
+ sqlNullableText,
450
+ sqlJsonbLiteral,
451
+ sqlBigInt,
393
452
  } from "@xylex-group/athena/utils";
394
453
  ```
395
454
 
@@ -400,15 +459,27 @@ const slug = slugify("Customer Success / Q4 Report"); // customer-success-q4-rep
400
459
  const local = isLocalHostname("api.localhost"); // true
401
460
  const normalized = trimTrailingSlashes("https://example.com///"); // https://example.com
402
461
  const enabled = parseBooleanFlag(process.env.FEATURE_FLAG, false);
462
+ const count = asNumber("42"); // 42
463
+ const label = asString(" ready "); // ready
464
+ const active = asBooleanOrNull("yes"); // true
465
+ const tags = asStringArray([" alpha ", "", "beta"]); // ["alpha", "beta"]
466
+ const likePattern = escapeLikePatternValue("%admin_"); // \%admin\_
403
467
 
404
468
  // Browser-only helper (safe no-op on server runtimes)
405
469
  clearAuthCookies();
406
470
 
407
471
  // Preserve forwarded headers when proxying auth requests
408
472
  const upstreamHeaders = proxyRequestHeaders(request);
473
+
474
+ // Safely embed raw SQL values when using athena.query(...)
475
+ const emailLiteral = sqlText("floris@example.com");
476
+ const metadataLiteral = sqlJsonbLiteral({ role: "admin" });
477
+ const actorIdLiteral = sqlBigInt(42);
478
+ const exactLiteral = quoteSqlStringLiteral("Athena's SDK");
409
479
  ```
410
480
 
411
481
  `clearAuthCookies()` clears cookies matching Athena/Better Auth prefixes (`athena-auth`, `__Secure-athena-auth`, `better-auth`, `__Secure-better-auth`) and also attempts parent-domain cleanup for subdomain deployments.
482
+ For SQL identifiers, keep using `identifier(...)`; `sqlText(...)`-style helpers are for literal values only.
412
483
 
413
484
  ### Retry helper
414
485