@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.
- package/README.md +124 -106
- package/dist/browser.cjs +584 -99
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +7 -7
- package/dist/browser.d.ts +7 -7
- package/dist/browser.js +583 -100
- package/dist/browser.js.map +1 -1
- package/dist/cli/index.cjs +573 -97
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +3 -3
- package/dist/cli/index.d.ts +3 -3
- package/dist/cli/index.js +573 -97
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +584 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +583 -100
- package/dist/index.js.map +1 -1
- package/dist/{model-form-BpDXlbxb.d.ts → model-form-C0FAbOaf.d.ts} +1 -1
- package/dist/{model-form-hoE2jHIi.d.cts → model-form-GzTqhEzM.d.cts} +1 -1
- package/dist/{pipeline-BNIw8pDQ.d.ts → pipeline-CR4V15jF.d.ts} +1 -1
- package/dist/{pipeline-DNIpEsN8.d.cts → pipeline-DZeExYMA.d.cts} +1 -1
- package/dist/{react-email-BvyCZnfW.d.cts → react-email-BuApZuyG.d.ts} +19 -6
- package/dist/{react-email-qPA1wjFV.d.ts → react-email-CQJq92zQ.d.cts} +19 -6
- package/dist/react.cjs +249 -12
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +4 -4
- package/dist/react.d.ts +4 -4
- package/dist/react.js +249 -12
- package/dist/react.js.map +1 -1
- package/dist/{types-A5e97acl.d.cts → types-09Q4D86N.d.cts} +23 -2
- package/dist/{types-A5e97acl.d.ts → types-09Q4D86N.d.ts} +23 -2
- package/dist/{types-bDlr4u7p.d.cts → types-D1JvL21V.d.cts} +1 -1
- package/dist/{types-BnD22-vb.d.ts → types-DU3gNdFv.d.ts} +1 -1
- package/package.json +40 -40
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# athena-js
|
|
2
2
|
|
|
3
|
-
current version: `2.
|
|
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.
|
|
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
|
-
|
|
612
|
+
Both resolve the table target to `public.users`.
|
|
595
613
|
|
|
596
614
|
### RPC
|
|
597
615
|
|