@xylex-group/athena 2.6.0 → 2.8.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 +210 -17
- package/dist/browser.cjs +2102 -527
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +8 -7
- package/dist/browser.d.ts +8 -7
- package/dist/browser.js +2096 -528
- package/dist/browser.js.map +1 -1
- package/dist/cli/index.cjs +2116 -559
- 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 +2116 -559
- package/dist/cli/index.js.map +1 -1
- package/dist/cookies.cjs +10 -3
- package/dist/cookies.cjs.map +1 -1
- package/dist/cookies.js +10 -3
- package/dist/cookies.js.map +1 -1
- package/dist/index.cjs +2694 -748
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -7
- package/dist/index.d.ts +8 -7
- package/dist/index.js +2688 -749
- package/dist/index.js.map +1 -1
- package/dist/model-form-DMed05gE.d.cts +3037 -0
- package/dist/model-form-DXPlOnlI.d.ts +3037 -0
- package/dist/{pipeline-Ce3pTw5h.d.ts → pipeline-CkMnhwPI.d.ts} +1 -1
- package/dist/{pipeline-D1ZYeoH7.d.cts → pipeline-D4sJRKqN.d.cts} +1 -1
- package/dist/react-email-DZhDDlEl.d.cts +417 -0
- package/dist/react-email-Lrz9A-BW.d.ts +417 -0
- package/dist/react.cjs +178 -71
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +22 -5
- package/dist/react.d.ts +22 -5
- package/dist/react.js +92 -5
- package/dist/react.js.map +1 -1
- package/dist/{types-CUuo4NDi.d.cts → types-BzY6fETM.d.ts} +47 -5
- package/dist/{types-DapchQY5.d.ts → types-CAtTGGoz.d.cts} +47 -5
- package/dist/{types-DSX6AT5B.d.cts → types-vikz9YIO.d.cts} +23 -1
- package/dist/{types-DSX6AT5B.d.ts → types-vikz9YIO.d.ts} +23 -1
- package/package.json +194 -193
- package/dist/model-form-BaHWi3gm.d.cts +0 -1383
- package/dist/model-form-Dh6gWjL0.d.ts +0 -1383
- package/dist/react-email-B8O1Jeff.d.cts +0 -1230
- package/dist/react-email-CDEF0jij.d.ts +0 -1230
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# athena-js
|
|
2
2
|
|
|
3
|
-
current version: `2.
|
|
3
|
+
current version: `2.8.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,10 +24,14 @@ 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(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
const athenaClient = createClient(
|
|
28
|
+
ATHENA_URL,
|
|
29
|
+
ATHENA_API_KEY,
|
|
30
|
+
{
|
|
31
|
+
client: "CLIENT_NAME",
|
|
32
|
+
backend: { type: "athena" },
|
|
33
|
+
},
|
|
34
|
+
);
|
|
31
35
|
|
|
32
36
|
const { data, error } = await athenaClient.from("orchestral_sections").findMany({
|
|
33
37
|
select: {
|
|
@@ -47,6 +51,34 @@ if (error) {
|
|
|
47
51
|
}
|
|
48
52
|
```
|
|
49
53
|
|
|
54
|
+
`createClient(url, key)` is the canonical SDK shape. The SDK treats `url` as the public unified Athena base URL and derives:
|
|
55
|
+
|
|
56
|
+
- DB: `${url}/db`
|
|
57
|
+
- Auth: `${url}/auth`
|
|
58
|
+
- Storage: `${url}/storage`
|
|
59
|
+
|
|
60
|
+
You can still override individual services when needed:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
const athena = createClient({
|
|
64
|
+
key: ATHENA_API_KEY,
|
|
65
|
+
db: { url: process.env.ATHENA_DB_URL },
|
|
66
|
+
auth: { url: process.env.ATHENA_AUTH_URL },
|
|
67
|
+
storage: { url: process.env.ATHENA_STORAGE_URL },
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Legacy top-level aliases are also supported:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const athena = createClient({
|
|
75
|
+
key: ATHENA_API_KEY,
|
|
76
|
+
gatewayUrl: process.env.ATHENA_DB_URL,
|
|
77
|
+
authUrl: process.env.ATHENA_AUTH_URL,
|
|
78
|
+
storageUrl: process.env.ATHENA_STORAGE_URL,
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
50
82
|
Example version baseline: SDK `@xylex-group/athena` `2.4.0`, Athena server `3.12.3` verified on 2026-06-04.
|
|
51
83
|
|
|
52
84
|
`.findMany({ select, where, orderBy, limit })` is the clean canonical read surface.
|
|
@@ -238,28 +270,38 @@ It also supports dynamic `baseURL` host resolution plus static/dynamic
|
|
|
238
270
|
|
|
239
271
|
For the full details and current scope, see [`docs/auth/server-bootstrap.mdx`](docs/auth/server-bootstrap.mdx).
|
|
240
272
|
|
|
241
|
-
### Typed schema registry (
|
|
273
|
+
### Typed schema registry (table-first)
|
|
242
274
|
|
|
243
|
-
You can keep `createClient(...).from<T>(...)` as-is, or opt into a typed registry:
|
|
275
|
+
You can keep `createClient(...).from<T>(...)` as-is, or opt into a typed registry with the new Zero-style table DSL:
|
|
244
276
|
|
|
245
277
|
```ts
|
|
246
278
|
import {
|
|
279
|
+
boolean,
|
|
247
280
|
createTypedClient,
|
|
248
281
|
defineDatabase,
|
|
249
|
-
defineModel,
|
|
250
282
|
defineRegistry,
|
|
251
283
|
defineSchema,
|
|
284
|
+
enumeration,
|
|
285
|
+
json,
|
|
286
|
+
string,
|
|
287
|
+
table,
|
|
252
288
|
} from "@xylex-group/athena";
|
|
253
289
|
|
|
290
|
+
const users = table("users")
|
|
291
|
+
.schema("public")
|
|
292
|
+
.columns({
|
|
293
|
+
id: string().generated(),
|
|
294
|
+
email: string(),
|
|
295
|
+
active: boolean().defaulted(),
|
|
296
|
+
mood: enumeration(["happy", "sad"] as const).optional(),
|
|
297
|
+
settings: json<{ theme: "light" | "dark" }>(),
|
|
298
|
+
})
|
|
299
|
+
.primaryKey("id");
|
|
300
|
+
|
|
254
301
|
const registry = defineRegistry({
|
|
255
302
|
primary: defineDatabase({
|
|
256
303
|
public: defineSchema({
|
|
257
|
-
users
|
|
258
|
-
meta: {
|
|
259
|
-
primaryKey: ["id"],
|
|
260
|
-
nullable: { id: false, email: false },
|
|
261
|
-
},
|
|
262
|
-
}),
|
|
304
|
+
users,
|
|
263
305
|
}),
|
|
264
306
|
}),
|
|
265
307
|
});
|
|
@@ -274,8 +316,45 @@ await typed
|
|
|
274
316
|
.withTenantContext({ organizationId: "org_1" })
|
|
275
317
|
.fromModel("primary", "public", "users")
|
|
276
318
|
.select("*");
|
|
319
|
+
|
|
320
|
+
const insert = users.schemas.form.parse({
|
|
321
|
+
email: "ada@example.com",
|
|
322
|
+
mood: "",
|
|
323
|
+
settings: { theme: "light" },
|
|
324
|
+
});
|
|
277
325
|
```
|
|
278
326
|
|
|
327
|
+
You can also pass that native Athena table/model value directly into the root client to avoid repeating the string table target:
|
|
328
|
+
|
|
329
|
+
```ts
|
|
330
|
+
const result = await athena.from(users)
|
|
331
|
+
.select("id, email, active")
|
|
332
|
+
.eq("active", true)
|
|
333
|
+
.order("created_at", { ascending: false })
|
|
334
|
+
.limit(25);
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
This is the viable opt-in short form because the `users` value carries runtime target metadata. A generic-only call like `from<UserPublicSchema>()` cannot resolve a table at runtime after TypeScript erases types.
|
|
338
|
+
|
|
339
|
+
If you want compile-time validation for simple string selects and RPC column names, enable the experimental strict mode:
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
const strictAthena = createClient(ATHENA_URL, ATHENA_API_KEY, {
|
|
343
|
+
experimental: {
|
|
344
|
+
typecheckColumns: true,
|
|
345
|
+
},
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
await strictAthena.from(users).select("id, email").order("created_at");
|
|
349
|
+
|
|
350
|
+
// compile-time error
|
|
351
|
+
strictAthena.from(users).select("id, missing_column");
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
For the DB helper surface, use `strictAthena.db.from<UserRow>("users").select("id, email")` when you want inline typed column validation. `strictAthena.db.select<UserRow>("users")` still gives a typed row-aware chain, but it does not accept inline typed column arguments.
|
|
355
|
+
|
|
356
|
+
`defineModel(...)` remains fully supported for compatibility and manual contracts.
|
|
357
|
+
|
|
279
358
|
For full details, see [`docs/typed-schema-registry.md`](./docs/typed-schema-registry.md).
|
|
280
359
|
|
|
281
360
|
For exhaustive method-by-method documentation with usage snippets (root client, runtime builders, auth bindings, react runtime, cookies, and utils), see [`docs/complete-method-reference.md`](./docs/complete-method-reference.md).
|
|
@@ -294,15 +373,91 @@ athena-js generate --help
|
|
|
294
373
|
athena-js help generate
|
|
295
374
|
```
|
|
296
375
|
|
|
376
|
+
Out of the box, `athena-js generate` now works without an `athena.config.*` file in the common cases:
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/app_db athena-js generate --dry-run
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
ATHENA_URL=https://athena-db.com ATHENA_API_KEY=secret ATHENA_GENERATOR_DB=app_db athena-js generate --dry-run
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
Smallest direct-mode config file:
|
|
387
|
+
|
|
388
|
+
```ts
|
|
389
|
+
import { defineGeneratorConfig } from "@xylex-group/athena";
|
|
390
|
+
|
|
391
|
+
export default defineGeneratorConfig({
|
|
392
|
+
provider: {
|
|
393
|
+
kind: "postgres",
|
|
394
|
+
mode: "direct",
|
|
395
|
+
},
|
|
396
|
+
});
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
Smallest table-builder config:
|
|
400
|
+
|
|
401
|
+
```ts
|
|
402
|
+
import { defineGeneratorConfig } from "@xylex-group/athena";
|
|
403
|
+
|
|
404
|
+
export default defineGeneratorConfig({
|
|
405
|
+
provider: {
|
|
406
|
+
kind: "postgres",
|
|
407
|
+
mode: "direct",
|
|
408
|
+
},
|
|
409
|
+
output: {
|
|
410
|
+
format: "table-builder",
|
|
411
|
+
},
|
|
412
|
+
});
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
Common copy-paste starts:
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
# direct postgres, no config file
|
|
419
|
+
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/app_db athena-js generate --dry-run
|
|
420
|
+
|
|
421
|
+
# direct postgres + Zero-style output + multiple schemas
|
|
422
|
+
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/app_db \
|
|
423
|
+
ATHENA_GENERATOR_OUTPUT_FORMAT=table-builder \
|
|
424
|
+
ATHENA_GENERATOR_SCHEMAS=public,analytics \
|
|
425
|
+
athena-js generate --dry-run
|
|
426
|
+
|
|
427
|
+
# gateway-only CI job, no config file
|
|
428
|
+
ATHENA_URL=https://athena-db.com \
|
|
429
|
+
ATHENA_API_KEY=secret \
|
|
430
|
+
ATHENA_GENERATOR_DB=app_db \
|
|
431
|
+
athena-js generate --dry-run
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
Smallest gateway table-builder config:
|
|
435
|
+
|
|
436
|
+
```ts
|
|
437
|
+
import { defineGeneratorConfig } from "@xylex-group/athena";
|
|
438
|
+
|
|
439
|
+
export default defineGeneratorConfig({
|
|
440
|
+
provider: {
|
|
441
|
+
kind: "postgres",
|
|
442
|
+
mode: "gateway",
|
|
443
|
+
},
|
|
444
|
+
output: {
|
|
445
|
+
format: "table-builder",
|
|
446
|
+
},
|
|
447
|
+
});
|
|
448
|
+
```
|
|
449
|
+
|
|
297
450
|
Generator supports:
|
|
298
451
|
|
|
299
452
|
- PostgreSQL direct introspection (`provider.mode = "direct"`, `provider.connectionString` from your `PG_URL`/`DATABASE_URL`)
|
|
300
453
|
- PostgreSQL gateway-only introspection (`provider.mode = "gateway"` via Athena `POST /gateway/query`)
|
|
301
454
|
- Multiple schema syncs such as `public` plus `athena`, with schema-safe default output paths
|
|
455
|
+
- Two output formats: legacy `define-model` artifacts (default) or the new Zero-style `table-builder` format via `output.format`
|
|
302
456
|
- Placeholder-driven output paths
|
|
303
457
|
- Feature flags (`features.emitRegistry`, `features.emitRelations`)
|
|
304
458
|
- Typed env-backed config fields via `generatorEnv(...)` for connection strings, schema lists, naming styles, flags, and placeholder maps
|
|
305
459
|
|
|
460
|
+
For copy-paste quickstarts and more example profiles, see [`docs/generator-quickstart.md`](./docs/generator-quickstart.md).
|
|
306
461
|
For full generator configuration and troubleshooting, see [`docs/generator-config.md`](./docs/generator-config.md).
|
|
307
462
|
For full CLI commands, help behavior, and troubleshooting, see [`docs/cli-command-reference.md`](./docs/cli-command-reference.md).
|
|
308
463
|
For CI/CD pipelines and generated-file branch policy, see [`docs/generator-cicd.md`](./docs/generator-cicd.md).
|
|
@@ -375,7 +530,7 @@ requireAffected(inserted, { min: 1 }, { table: "users", operation: "insert" });
|
|
|
375
530
|
### Structured errors by default
|
|
376
531
|
|
|
377
532
|
```ts
|
|
378
|
-
import { createClient
|
|
533
|
+
import { createClient } from "@xylex-group/athena";
|
|
379
534
|
|
|
380
535
|
const athena = createClient(ATHENA_URL, ATHENA_API_KEY);
|
|
381
536
|
|
|
@@ -391,13 +546,13 @@ if (error) {
|
|
|
391
546
|
|
|
392
547
|
`result.error` already carries normalized `kind` values (`unique_violation`, `validation`, `auth`, `rate_limit`, `transient`, etc.) plus operation metadata.
|
|
393
548
|
|
|
394
|
-
`normalizeAthenaError(
|
|
549
|
+
`normalizeAthenaError(...)` is deprecated. Prefer `result.error` on failed results and the structured fields already attached to thrown SDK errors.
|
|
395
550
|
|
|
396
551
|
### Query tracing (experimental)
|
|
397
552
|
|
|
398
553
|
```ts
|
|
399
554
|
const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
|
|
400
|
-
experimental: { traceQueries: true },
|
|
555
|
+
experimental: { traceQueries: true, debugAst: true },
|
|
401
556
|
});
|
|
402
557
|
```
|
|
403
558
|
|
|
@@ -426,6 +581,44 @@ const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
|
|
|
426
581
|
});
|
|
427
582
|
```
|
|
428
583
|
|
|
584
|
+
If you also enable `debugAst: true`, every traced operation includes a normalized AST, and successful results expose the same AST through `getAthenaDebugAst(...)`:
|
|
585
|
+
|
|
586
|
+
```ts
|
|
587
|
+
import { createClient, getAthenaDebugAst } from "@xylex-group/athena";
|
|
588
|
+
|
|
589
|
+
const athena = createClient(ATHENA_URL, ATHENA_API_KEY, {
|
|
590
|
+
experimental: {
|
|
591
|
+
debugAst: true,
|
|
592
|
+
},
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
const result = await athena.from("users").eq("id", 1).select("id");
|
|
596
|
+
const ast = getAthenaDebugAst(result);
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
This works across the runtime operation families too:
|
|
600
|
+
|
|
601
|
+
```ts
|
|
602
|
+
const inserted = await athena
|
|
603
|
+
.from("users")
|
|
604
|
+
.insert({ email: "ada@example.com" })
|
|
605
|
+
.select("id,email");
|
|
606
|
+
|
|
607
|
+
const insertedAst = getAthenaDebugAst(inserted);
|
|
608
|
+
|
|
609
|
+
const rpcResult = await athena
|
|
610
|
+
.rpc("list_users", { role: "admin" })
|
|
611
|
+
.eq("active", true)
|
|
612
|
+
.select("id,email");
|
|
613
|
+
|
|
614
|
+
const rpcAst = getAthenaDebugAst(rpcResult);
|
|
615
|
+
|
|
616
|
+
const sqlResult = await athena.query<{ id: number }>("select id from users where active = true");
|
|
617
|
+
const sqlAst = getAthenaDebugAst(sqlResult);
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
If `traceQueries` is enabled too, the same normalized AST is emitted on each `AthenaQueryTraceEvent.ast`.
|
|
621
|
+
|
|
429
622
|
### Read retries (experimental)
|
|
430
623
|
|
|
431
624
|
```ts
|