@xylex-group/athena 2.3.0 → 2.4.0

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.
Files changed (36) hide show
  1. package/README.md +124 -106
  2. package/dist/browser.cjs +584 -99
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.cts +7 -7
  5. package/dist/browser.d.ts +7 -7
  6. package/dist/browser.js +583 -100
  7. package/dist/browser.js.map +1 -1
  8. package/dist/cli/index.cjs +573 -97
  9. package/dist/cli/index.cjs.map +1 -1
  10. package/dist/cli/index.d.cts +3 -3
  11. package/dist/cli/index.d.ts +3 -3
  12. package/dist/cli/index.js +573 -97
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/index.cjs +584 -99
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +7 -7
  17. package/dist/index.d.ts +7 -7
  18. package/dist/index.js +583 -100
  19. package/dist/index.js.map +1 -1
  20. package/dist/{model-form-BpDXlbxb.d.ts → model-form-C0FAbOaf.d.ts} +1 -1
  21. package/dist/{model-form-hoE2jHIi.d.cts → model-form-GzTqhEzM.d.cts} +1 -1
  22. package/dist/{pipeline-BNIw8pDQ.d.ts → pipeline-CR4V15jF.d.ts} +1 -1
  23. package/dist/{pipeline-DNIpEsN8.d.cts → pipeline-DZeExYMA.d.cts} +1 -1
  24. package/dist/{react-email-BvyCZnfW.d.cts → react-email-BuApZuyG.d.ts} +19 -6
  25. package/dist/{react-email-qPA1wjFV.d.ts → react-email-CQJq92zQ.d.cts} +19 -6
  26. package/dist/react.cjs +249 -12
  27. package/dist/react.cjs.map +1 -1
  28. package/dist/react.d.cts +4 -4
  29. package/dist/react.d.ts +4 -4
  30. package/dist/react.js +249 -12
  31. package/dist/react.js.map +1 -1
  32. package/dist/{types-A5e97acl.d.cts → types-09Q4D86N.d.cts} +23 -2
  33. package/dist/{types-A5e97acl.d.ts → types-09Q4D86N.d.ts} +23 -2
  34. package/dist/{types-bDlr4u7p.d.cts → types-D1JvL21V.d.cts} +1 -1
  35. package/dist/{types-BnD22-vb.d.ts → types-DU3gNdFv.d.ts} +1 -1
  36. package/package.json +40 -40
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # athena-js
2
2
 
3
- current version: `2.3.0`
3
+ current version: `2.4.0`
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
@@ -24,36 +24,36 @@ npm install react # React >=17 required for the hook
24
24
  ```ts
25
25
  import { createClient } from "@xylex-group/athena";
26
26
 
27
- const athenaClient = createClient(ATHENA_URL, ATHENA_API_KEY, {
28
- client: "CLIENT_NAME",
29
- backend: { type: "athena" },
30
- });
31
-
32
- const { data, error } = await athenaClient.from("orchestral_sections").findMany({
33
- select: {
34
- name: true,
35
- instruments: {
36
- select: {
37
- name: true,
38
- },
39
- },
40
- },
41
- });
42
-
43
- if (error) {
44
- console.error("gateway error", error);
45
- } else {
46
- console.table(data);
47
- }
48
- ```
49
-
50
- Example version baseline: SDK `@xylex-group/athena` `2.3.0`, Athena server `3.12.3` verified on 2026-06-04.
51
-
52
- `.findMany({ select, where, orderBy, limit })` is the clean canonical read surface.
53
- The existing string-based `.select(...)` chain remains fully supported for compatibility,
54
- including alias/FK patterns like `from:sender_id(name)`.
55
- For the full AST model, route contract, error behavior, and Athena server implications,
56
- see [`docs/findmany-ast-and-server-contract.md`](docs/findmany-ast-and-server-contract.md).
27
+ const athenaClient = createClient(ATHENA_URL, ATHENA_API_KEY, {
28
+ client: "CLIENT_NAME",
29
+ backend: { type: "athena" },
30
+ });
31
+
32
+ const { data, error } = await athenaClient.from("orchestral_sections").findMany({
33
+ select: {
34
+ name: true,
35
+ instruments: {
36
+ select: {
37
+ name: true,
38
+ },
39
+ },
40
+ },
41
+ });
42
+
43
+ if (error) {
44
+ console.error("gateway error", error);
45
+ } else {
46
+ console.table(data);
47
+ }
48
+ ```
49
+
50
+ Example version baseline: SDK `@xylex-group/athena` `2.4.0`, Athena server `3.12.3` verified on 2026-06-04.
51
+
52
+ `.findMany({ select, where, orderBy, limit })` is the clean canonical read surface.
53
+ The existing string-based `.select(...)` chain remains fully supported for compatibility,
54
+ including alias/FK patterns like `from:sender_id(name)`.
55
+ For the full AST model, route contract, error behavior, and Athena server implications,
56
+ see [`docs/findmany-ast-and-server-contract.md`](docs/findmany-ast-and-server-contract.md).
57
57
 
58
58
  ### Auth client (Athena Auth server)
59
59
 
@@ -245,19 +245,19 @@ For prompt-ready documentation handoff text, see [`docs/generator-codex-handoff-
245
245
  - `athena-rs` for Rust backend throughput
246
246
  - `athena-js` for app/tooling layers that need TypeScript contracts and frontend-facing ergonomics
247
247
 
248
- Every query resolves to `{ data, error, errorDetails?, status, statusText?, count?, raw }`. `data` is `null` on error; `error` is `null` on success.
249
-
250
- Failed results now include a structured `error` object with the useful fields inline:
251
-
252
- - `message`
253
- - `code`
254
- - `details`
255
- - `hint`
256
- - `status`
257
- - `statusText`
258
- - normalized metadata such as `kind`, `table`, `operation`, and `retryable`
259
-
260
- `errorDetails` is still present as a compatibility alias for low-level gateway metadata (`gatewayCode`, `endpoint`, `method`, `requestId`, etc.).
248
+ Every query resolves to `{ data, error, errorDetails?, status, statusText?, count?, raw }`. `data` is `null` on error; `error` is `null` on success.
249
+
250
+ Failed results now include a structured `error` object with the useful fields inline:
251
+
252
+ - `message`
253
+ - `code`
254
+ - `details`
255
+ - `hint`
256
+ - `status`
257
+ - `statusText`
258
+ - normalized metadata such as `kind`, `table`, `operation`, and `retryable`
259
+
260
+ `errorDetails` is still present as a compatibility alias for low-level gateway metadata (`gatewayCode`, `endpoint`, `method`, `requestId`, etc.).
261
261
 
262
262
  ## Reliability helper APIs
263
263
 
@@ -296,26 +296,26 @@ requireAffected(inserted, { min: 1 }, { table: "users", operation: "insert" });
296
296
 
297
297
  `requireAffected` uses `result.count`; request it on writes with `{ count: "exact" }` when you need enforced postconditions.
298
298
 
299
- ### Structured errors by default
300
-
301
- ```ts
302
- import { createClient, normalizeAthenaError } from "@xylex-group/athena";
303
-
304
- const athena = createClient(ATHENA_URL, ATHENA_API_KEY);
305
-
306
- const { data, error, status, statusText } = await athena.from("users").insert({ id: 1 }).select();
307
- if (error) {
308
- console.error(error);
309
- console.error(error.hint ?? error.message, status, statusText);
310
- if (error.kind === "unique_violation") {
311
- // deterministic conflict handling
312
- }
313
- }
314
- ```
315
-
316
- `result.error` already carries normalized `kind` values (`unique_violation`, `validation`, `auth`, `rate_limit`, `transient`, etc.) plus operation metadata.
317
-
318
- `normalizeAthenaError(result)` still exists when you need the normalized envelope from an arbitrary thrown value or mixed unknown input.
299
+ ### Structured errors by default
300
+
301
+ ```ts
302
+ import { createClient, normalizeAthenaError } from "@xylex-group/athena";
303
+
304
+ const athena = createClient(ATHENA_URL, ATHENA_API_KEY);
305
+
306
+ const { data, error, status, statusText } = await athena.from("users").insert({ id: 1 }).select();
307
+ if (error) {
308
+ console.error(error);
309
+ console.error(error.hint ?? error.message, status, statusText);
310
+ if (error.kind === "unique_violation") {
311
+ // deterministic conflict handling
312
+ }
313
+ }
314
+ ```
315
+
316
+ `result.error` already carries normalized `kind` values (`unique_violation`, `validation`, `auth`, `rate_limit`, `transient`, etc.) plus operation metadata.
317
+
318
+ `normalizeAthenaError(result)` still exists when you need the normalized envelope from an arbitrary thrown value or mixed unknown input.
319
319
 
320
320
  ### Query tracing (experimental)
321
321
 
@@ -325,49 +325,49 @@ const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
325
325
  });
326
326
  ```
327
327
 
328
- With `traceQueries: true`, the SDK logs every runtime execution (`select`, `insert`, `upsert`, `update`, `delete`, `rpc`, `query`) and includes:
329
-
330
- - the gateway endpoint used
331
- - synthesized SQL (or raw SQL for `query(...)` and SQL fallback reads)
332
- - payload and call options
333
- - full outcome (`status`, `error`, `count`, `data`, `raw`)
334
- - callsite metadata (`filePath`, `fileName`, `line`, `column`)
335
-
336
- For deferred chains, Athena captures that callsite from the public SDK seam that declared or finalized the operation and reuses it for the eventual network execution. That keeps traces pinned to user code instead of drifting into SDK internals when async stack shapes differ between local runs and CI.
328
+ With `traceQueries: true`, the SDK logs every runtime execution (`select`, `insert`, `upsert`, `update`, `delete`, `rpc`, `query`) and includes:
329
+
330
+ - the gateway endpoint used
331
+ - synthesized SQL (or raw SQL for `query(...)` and SQL fallback reads)
332
+ - payload and call options
333
+ - full outcome (`status`, `error`, `count`, `data`, `raw`)
334
+ - callsite metadata (`filePath`, `fileName`, `line`, `column`)
335
+
336
+ For deferred chains, Athena captures that callsite from the public SDK seam that declared or finalized the operation and reuses it for the eventual network execution. That keeps traces pinned to user code instead of drifting into SDK internals when async stack shapes differ between local runs and CI.
337
337
 
338
338
  Use a custom sink:
339
339
 
340
- ```ts
341
- const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
342
- experimental: {
343
- traceQueries: {
344
- logger(event) {
345
- // Forward into your logger/observability sink
346
- console.log(event.operation, event.endpoint, event.sql, event.callsite);
347
- },
348
- },
349
- },
350
- });
351
- ```
352
-
353
- ### findMany AST transport (experimental)
354
-
355
- ```ts
356
- const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
357
- experimental: {
358
- findManyAst: true,
359
- },
360
- });
361
- ```
362
-
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.
364
-
365
- - this is opt-in and meant for gateways that explicitly support direct AST bodies
366
- - existing compiled `findMany(...)` transport remains the default
367
- - chained builder filters or pagination state that the AST body cannot represent losslessly yet continue to use the legacy compiled path
368
- - trace output still includes synthesized SQL so diagnostics stay readable
369
-
370
- ### Numeric coercion
340
+ ```ts
341
+ const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
342
+ experimental: {
343
+ traceQueries: {
344
+ logger(event) {
345
+ // Forward into your logger/observability sink
346
+ console.log(event.operation, event.endpoint, event.sql, event.callsite);
347
+ },
348
+ },
349
+ },
350
+ });
351
+ ```
352
+
353
+ ### findMany AST transport (experimental)
354
+
355
+ ```ts
356
+ const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
357
+ experimental: {
358
+ findManyAst: true,
359
+ },
360
+ });
361
+ ```
362
+
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.
364
+
365
+ - this is opt-in and meant for gateways that explicitly support direct AST bodies
366
+ - existing compiled `findMany(...)` transport remains the default
367
+ - chained builder filters or pagination state that the AST body cannot represent losslessly yet continue to use the legacy compiled path
368
+ - trace output still includes synthesized SQL so diagnostics stay readable
369
+
370
+ ### Numeric coercion
371
371
 
372
372
  ```ts
373
373
  import { coerceInt, assertInt } from "@xylex-group/athena";
@@ -583,15 +583,33 @@ const { data: user } = await athena
583
583
 
584
584
  ### Table schema targeting
585
585
 
586
- Use `schema` in table call options to qualify unqualified table names:
586
+ Use `schema` either on `from(...)` itself or in table call options to qualify unqualified table names:
587
587
 
588
588
  ```ts
589
589
  const { data } = await athena
590
+ .from("users", { schema: "public" })
591
+ .select("id,email");
592
+
593
+ const { data: sameTarget } = await athena
590
594
  .from("users")
591
595
  .select("id,email", { schema: "public" });
596
+
597
+ const { data: crossSchema } = await athena
598
+ .from("chat_subscriptions", { schema: "private" })
599
+ .findMany({
600
+ select: {
601
+ user_id: true,
602
+ user: {
603
+ schema: "athena",
604
+ select: {
605
+ id: true,
606
+ },
607
+ },
608
+ },
609
+ });
592
610
  ```
593
611
 
594
- This resolves the table target to `public.users`.
612
+ Both resolve the table target to `public.users`.
595
613
 
596
614
  ### RPC
597
615