@xylex-group/athena 1.6.2 → 1.7.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 +47 -1
- package/dist/cli/index.cjs +77 -18
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +77 -18
- package/dist/cli/index.js.map +1 -1
- package/dist/{errors-BYRK5phv.d.cts → errors-BJGgjHcI.d.cts} +1 -1
- package/dist/{errors-1b-LSTum.d.ts → errors-Bcf5Sftv.d.ts} +1 -1
- package/dist/index.cjs +572 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +269 -6
- package/dist/index.d.ts +269 -6
- package/dist/index.js +569 -19
- package/dist/index.js.map +1 -1
- package/dist/{pipeline-CA2aexDl.d.cts → pipeline-BsKuBqmE.d.cts} +9 -4
- package/dist/{pipeline-BQzpSLD3.d.ts → pipeline-xQSjGbqF.d.ts} +9 -4
- package/dist/react.d.cts +3 -3
- package/dist/react.d.ts +3 -3
- package/dist/{types-v6UyGg-x.d.cts → types-wPA1Z4vQ.d.cts} +1 -1
- package/dist/{types-v6UyGg-x.d.ts → types-wPA1Z4vQ.d.ts} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# athena-js
|
|
2
2
|
|
|
3
|
-
current version: `1.
|
|
3
|
+
current version: `1.7.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
|
|
@@ -43,6 +43,51 @@ if (error) {
|
|
|
43
43
|
}
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
### Auth client (Athena Auth server)
|
|
47
|
+
|
|
48
|
+
If your auth backend is now Athena Auth, you can keep core login/session flows in this SDK:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { createAuthClient } from "@xylex-group/athena";
|
|
52
|
+
|
|
53
|
+
const auth = createAuthClient({
|
|
54
|
+
baseUrl: "http://localhost:3001/api/auth",
|
|
55
|
+
// optional: bearer token if you are not using cookie-based sessions
|
|
56
|
+
bearerToken: process.env.AUTH_BEARER_TOKEN,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const login = await auth.signIn.email({
|
|
60
|
+
email: "demo@example.com",
|
|
61
|
+
password: "super-secret",
|
|
62
|
+
rememberMe: true,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const session = await auth.getSession();
|
|
66
|
+
const sessions = await auth.listSessions();
|
|
67
|
+
|
|
68
|
+
// clear one session
|
|
69
|
+
await auth.revokeSession({ token: "session_token_here" });
|
|
70
|
+
// or clear all sessions
|
|
71
|
+
await auth.revokeSessions();
|
|
72
|
+
|
|
73
|
+
await auth.signOut();
|
|
74
|
+
|
|
75
|
+
// additional core flows
|
|
76
|
+
await auth.forgetPassword({ email: "demo@example.com", redirectTo: "https://app/reset-password" });
|
|
77
|
+
await auth.resetPassword({ newPassword: "new-secret", token: "reset_token" });
|
|
78
|
+
await auth.verifyEmail({ token: "verify_token", callbackURL: "https://app/verified" });
|
|
79
|
+
await auth.changePassword({ currentPassword: "old-secret", newPassword: "new-secret" });
|
|
80
|
+
await auth.updateUser({ name: "Demo User" });
|
|
81
|
+
|
|
82
|
+
// escape hatch for any endpoint on your Athena Auth instance
|
|
83
|
+
await auth.request({
|
|
84
|
+
endpoint: "/ok",
|
|
85
|
+
query: { ping: "pong" },
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Auth responses follow the same envelope style: `{ ok, status, data, error, errorDetails, raw }`.
|
|
90
|
+
|
|
46
91
|
### Typed schema registry (model-first)
|
|
47
92
|
|
|
48
93
|
You can keep `createClient(...).from<T>(...)` as-is, or opt into a typed registry:
|
|
@@ -101,6 +146,7 @@ Generator supports:
|
|
|
101
146
|
|
|
102
147
|
- PostgreSQL direct introspection (`provider.mode = "direct"`, `provider.connectionString` from your `PG_URL`/`DATABASE_URL`)
|
|
103
148
|
- PostgreSQL gateway-only introspection (`provider.mode = "gateway"` via Athena `POST /gateway/query`)
|
|
149
|
+
- Multiple schema syncs such as `public` plus `athena`, with schema-safe default output paths
|
|
104
150
|
- Placeholder-driven output paths
|
|
105
151
|
- Feature flags (`features.emitRegistry`, `features.emitRelations`)
|
|
106
152
|
|
package/dist/cli/index.cjs
CHANGED
|
@@ -291,6 +291,37 @@ function resolvePostgresColumnType(column) {
|
|
|
291
291
|
}
|
|
292
292
|
return wrapArrayType(baseType, column.arrayDimensions);
|
|
293
293
|
}
|
|
294
|
+
|
|
295
|
+
// src/generator/schema-selection.ts
|
|
296
|
+
var DEFAULT_POSTGRES_SCHEMAS = ["public"];
|
|
297
|
+
function collectSchemaNames(input) {
|
|
298
|
+
if (!input) {
|
|
299
|
+
return [];
|
|
300
|
+
}
|
|
301
|
+
const values = typeof input === "string" ? [input] : input;
|
|
302
|
+
return values.flatMap((value) => String(value).split(","));
|
|
303
|
+
}
|
|
304
|
+
function normalizeSchemaSelection(input) {
|
|
305
|
+
const schemas = [];
|
|
306
|
+
const seen = /* @__PURE__ */ new Set();
|
|
307
|
+
for (const value of collectSchemaNames(input)) {
|
|
308
|
+
const schema = value.trim();
|
|
309
|
+
if (!schema || seen.has(schema)) {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
seen.add(schema);
|
|
313
|
+
schemas.push(schema);
|
|
314
|
+
}
|
|
315
|
+
return schemas.length > 0 ? schemas : [...DEFAULT_POSTGRES_SCHEMAS];
|
|
316
|
+
}
|
|
317
|
+
function resolveProviderSchemas(providerConfig) {
|
|
318
|
+
if (providerConfig.kind === "postgres") {
|
|
319
|
+
return normalizeSchemaSelection(providerConfig.schemas);
|
|
320
|
+
}
|
|
321
|
+
return [...DEFAULT_POSTGRES_SCHEMAS];
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// src/generator/config.ts
|
|
294
325
|
var DEFAULT_CONFIG_CANDIDATES = [
|
|
295
326
|
"athena.config.ts",
|
|
296
327
|
"athena.config.js",
|
|
@@ -300,8 +331,8 @@ var DEFAULT_CONFIG_CANDIDATES = [
|
|
|
300
331
|
".athena.config.js"
|
|
301
332
|
];
|
|
302
333
|
var DEFAULT_TARGETS = {
|
|
303
|
-
model: "athena/models/{model_kebab}.ts",
|
|
304
|
-
schema: "athena/
|
|
334
|
+
model: "athena/models/{schema_kebab}/{model_kebab}.ts",
|
|
335
|
+
schema: "athena/schemas/{schema_kebab}.ts",
|
|
305
336
|
database: "athena/relations.ts",
|
|
306
337
|
registry: "athena/config.ts"
|
|
307
338
|
};
|
|
@@ -331,6 +362,15 @@ function normalizeOutputConfig(output) {
|
|
|
331
362
|
}
|
|
332
363
|
};
|
|
333
364
|
}
|
|
365
|
+
function normalizeProviderConfig(provider) {
|
|
366
|
+
if (provider.kind === "postgres") {
|
|
367
|
+
return {
|
|
368
|
+
...provider,
|
|
369
|
+
schemas: normalizeSchemaSelection(provider.schemas)
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
return provider;
|
|
373
|
+
}
|
|
334
374
|
function isAthenaGeneratorConfig(value) {
|
|
335
375
|
if (!value || typeof value !== "object") {
|
|
336
376
|
return false;
|
|
@@ -340,7 +380,7 @@ function isAthenaGeneratorConfig(value) {
|
|
|
340
380
|
}
|
|
341
381
|
function normalizeGeneratorConfig(input) {
|
|
342
382
|
return {
|
|
343
|
-
provider: input.provider,
|
|
383
|
+
provider: normalizeProviderConfig(input.provider),
|
|
344
384
|
output: normalizeOutputConfig(input.output),
|
|
345
385
|
naming: {
|
|
346
386
|
...DEFAULT_NAMING,
|
|
@@ -550,12 +590,19 @@ export const ${registryConstName} = defineRegistry({
|
|
|
550
590
|
};
|
|
551
591
|
}
|
|
552
592
|
function assertNoDuplicatePaths(files) {
|
|
553
|
-
const seen = /* @__PURE__ */ new
|
|
593
|
+
const seen = /* @__PURE__ */ new Map();
|
|
554
594
|
for (const file of files) {
|
|
555
|
-
|
|
556
|
-
|
|
595
|
+
const existing = seen.get(file.path);
|
|
596
|
+
if (existing) {
|
|
597
|
+
throw new Error(
|
|
598
|
+
[
|
|
599
|
+
`Generator output collision detected for path: ${file.path}`,
|
|
600
|
+
`Collision: ${existing.kind} and ${file.kind}.`,
|
|
601
|
+
"When syncing multiple schemas, include a schema placeholder such as {schema} or {schema_kebab} in model/schema output targets."
|
|
602
|
+
].join(" ")
|
|
603
|
+
);
|
|
557
604
|
}
|
|
558
|
-
seen.
|
|
605
|
+
seen.set(file.path, file);
|
|
559
606
|
}
|
|
560
607
|
}
|
|
561
608
|
var ArtifactComposer = class {
|
|
@@ -2111,8 +2158,21 @@ function coerceStringArray(value) {
|
|
|
2111
2158
|
}
|
|
2112
2159
|
return [];
|
|
2113
2160
|
}
|
|
2161
|
+
function normalizePostgresCatalogSchemas(schemas) {
|
|
2162
|
+
const normalized = [];
|
|
2163
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2164
|
+
for (const value of schemas ?? []) {
|
|
2165
|
+
const schema = value.trim();
|
|
2166
|
+
if (!schema || seen.has(schema)) {
|
|
2167
|
+
continue;
|
|
2168
|
+
}
|
|
2169
|
+
seen.add(schema);
|
|
2170
|
+
normalized.push(schema);
|
|
2171
|
+
}
|
|
2172
|
+
return normalized.length > 0 ? normalized : ["public"];
|
|
2173
|
+
}
|
|
2114
2174
|
function buildSchemaArrayLiteral(schemas) {
|
|
2115
|
-
const normalized = schemas
|
|
2175
|
+
const normalized = normalizePostgresCatalogSchemas(schemas);
|
|
2116
2176
|
const literals = normalized.map((schema) => `'${escapeSqlLiteral(schema)}'`).join(", ");
|
|
2117
2177
|
return `ARRAY[${literals}]`;
|
|
2118
2178
|
}
|
|
@@ -2311,12 +2371,14 @@ var PostgresIntrospectionProvider = class {
|
|
|
2311
2371
|
backend = "postgresql";
|
|
2312
2372
|
connectionString;
|
|
2313
2373
|
database;
|
|
2374
|
+
schemas;
|
|
2314
2375
|
constructor(options) {
|
|
2315
2376
|
this.connectionString = options.connectionString;
|
|
2316
2377
|
this.database = options.database ?? "postgres";
|
|
2378
|
+
this.schemas = normalizePostgresCatalogSchemas(options.schemas);
|
|
2317
2379
|
}
|
|
2318
2380
|
async inspect(options) {
|
|
2319
|
-
const schemas = options?.schemas && options.schemas.length > 0 ? options.schemas :
|
|
2381
|
+
const schemas = options?.schemas && options.schemas.length > 0 ? normalizePostgresCatalogSchemas(options.schemas) : this.schemas;
|
|
2320
2382
|
const pool = new pg.Pool({
|
|
2321
2383
|
connectionString: this.connectionString
|
|
2322
2384
|
});
|
|
@@ -2388,11 +2450,13 @@ var AthenaGatewayPostgresIntrospectionProvider = class {
|
|
|
2388
2450
|
type: this.config.backend ?? "postgresql"
|
|
2389
2451
|
}
|
|
2390
2452
|
});
|
|
2453
|
+
this.schemas = normalizeSchemaSelection(this.config.schemas);
|
|
2391
2454
|
}
|
|
2392
2455
|
backend = "postgresql";
|
|
2393
2456
|
client;
|
|
2457
|
+
schemas;
|
|
2394
2458
|
async inspect(options) {
|
|
2395
|
-
const schemas = options?.schemas && options.schemas.length > 0 ? options.schemas : this.
|
|
2459
|
+
const schemas = options?.schemas && options.schemas.length > 0 ? normalizeSchemaSelection(options.schemas) : this.schemas;
|
|
2396
2460
|
const catalogClient = new AthenaGatewayCatalogClient(this.client);
|
|
2397
2461
|
const queries = buildGatewayCatalogQueries(schemas);
|
|
2398
2462
|
const [columnRows, enumMap, primaryKeyRows, foreignKeyRows] = await Promise.all([
|
|
@@ -2428,7 +2492,8 @@ var ScyllaIntrospectionProvider = class {
|
|
|
2428
2492
|
function createPostgresProvider(config) {
|
|
2429
2493
|
return createPostgresIntrospectionProvider({
|
|
2430
2494
|
connectionString: config.connectionString,
|
|
2431
|
-
database: config.database
|
|
2495
|
+
database: config.database,
|
|
2496
|
+
schemas: normalizeSchemaSelection(config.schemas)
|
|
2432
2497
|
});
|
|
2433
2498
|
}
|
|
2434
2499
|
function resolveGeneratorProvider(providerConfig, experimentalFlags) {
|
|
@@ -2450,12 +2515,6 @@ function resolveGeneratorProvider(providerConfig, experimentalFlags) {
|
|
|
2450
2515
|
}
|
|
2451
2516
|
|
|
2452
2517
|
// src/generator/pipeline.ts
|
|
2453
|
-
function extractProviderSchemas(providerConfig) {
|
|
2454
|
-
if (!("schemas" in providerConfig) || !providerConfig.schemas || providerConfig.schemas.length === 0) {
|
|
2455
|
-
return void 0;
|
|
2456
|
-
}
|
|
2457
|
-
return providerConfig.schemas;
|
|
2458
|
-
}
|
|
2459
2518
|
async function writeArtifacts(files, cwd) {
|
|
2460
2519
|
const writtenFiles = [];
|
|
2461
2520
|
for (const file of files) {
|
|
@@ -2475,7 +2534,7 @@ async function runSchemaGenerator(options = {}) {
|
|
|
2475
2534
|
const { configPath, config } = await loadGeneratorConfig(configOptions);
|
|
2476
2535
|
const provider = options.provider ?? resolveGeneratorProvider(config.provider, config.experimental);
|
|
2477
2536
|
const snapshot = await provider.inspect({
|
|
2478
|
-
schemas:
|
|
2537
|
+
schemas: resolveProviderSchemas(config.provider)
|
|
2479
2538
|
});
|
|
2480
2539
|
const generated = generateArtifactsFromSnapshot(snapshot, config);
|
|
2481
2540
|
const writtenFiles = options.dryRun ? [] : await writeArtifacts(generated.files, cwd);
|