@xylex-group/athena 1.9.0 → 2.1.2

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 (45) hide show
  1. package/README.md +86 -68
  2. package/bin/athena-js.js +0 -0
  3. package/dist/browser.cjs +3319 -0
  4. package/dist/browser.cjs.map +1 -0
  5. package/dist/browser.d.cts +25 -0
  6. package/dist/browser.d.ts +25 -0
  7. package/dist/browser.js +3276 -0
  8. package/dist/browser.js.map +1 -0
  9. package/dist/cli/index.cjs +1839 -275
  10. package/dist/cli/index.cjs.map +1 -1
  11. package/dist/cli/index.d.cts +3 -2
  12. package/dist/cli/index.d.ts +3 -2
  13. package/dist/cli/index.js +1840 -276
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/client-BX0NQqOn.d.ts +435 -0
  16. package/dist/client-dpAp-NZK.d.cts +435 -0
  17. package/dist/cookies.cjs +890 -0
  18. package/dist/cookies.cjs.map +1 -0
  19. package/dist/cookies.d.cts +174 -0
  20. package/dist/cookies.d.ts +174 -0
  21. package/dist/cookies.js +869 -0
  22. package/dist/cookies.js.map +1 -0
  23. package/dist/index.cjs +2724 -1777
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +8 -641
  26. package/dist/index.d.ts +8 -641
  27. package/dist/index.js +2725 -1779
  28. package/dist/index.js.map +1 -1
  29. package/dist/model-form-2hqmoOUX.d.ts +1284 -0
  30. package/dist/model-form-Cy-zaO0u.d.cts +1284 -0
  31. package/dist/pipeline-BOPszLsL.d.ts +8 -0
  32. package/dist/pipeline-E3FDbs4W.d.cts +8 -0
  33. package/dist/react.cjs +93 -0
  34. package/dist/react.cjs.map +1 -1
  35. package/dist/react.d.cts +38 -4
  36. package/dist/react.d.ts +38 -4
  37. package/dist/react.js +93 -1
  38. package/dist/react.js.map +1 -1
  39. package/dist/{types-BnzoaNRC.d.cts → types-BaBzjwXr.d.cts} +1 -1
  40. package/dist/{types-BnzoaNRC.d.ts → types-BaBzjwXr.d.ts} +1 -1
  41. package/dist/{pipeline-CQgV-Yfo.d.ts → types-CeBPrnGj.d.ts} +2 -7
  42. package/dist/{pipeline-C-cN0ACi.d.cts → types-CpqL-pZx.d.cts} +2 -7
  43. package/package.json +36 -17
  44. package/dist/model-form-Bm_kqCn2.d.ts +0 -92
  45. package/dist/model-form-DkS48fsh.d.cts +0 -92
@@ -4,7 +4,6 @@ var promises = require('fs/promises');
4
4
  var path = require('path');
5
5
  var fs = require('fs');
6
6
  var url = require('url');
7
- var pg = require('pg');
8
7
 
9
8
  // src/generator/pipeline.ts
10
9
 
@@ -149,9 +148,13 @@ function resolvePlaceholderMap(baseTokens, outputConfig) {
149
148
  const resolved = {
150
149
  ...baseTokens
151
150
  };
151
+ const reservedTokenKeys = new Set(Object.keys(baseTokens));
152
152
  const entries = Object.entries(outputConfig.placeholderMap ?? {});
153
153
  for (let index = 0; index < entries.length; index += 1) {
154
154
  const [key, value] = entries[index];
155
+ if (reservedTokenKeys.has(key)) {
156
+ continue;
157
+ }
155
158
  let current = value;
156
159
  for (let depth = 0; depth < 8; depth += 1) {
157
160
  const next = renderTemplate(current, resolved);
@@ -292,6 +295,295 @@ function resolvePostgresColumnType(column) {
292
295
  return wrapArrayType(baseType, column.arrayDimensions);
293
296
  }
294
297
 
298
+ // src/gateway/errors.ts
299
+ var AthenaGatewayError = class _AthenaGatewayError extends Error {
300
+ code;
301
+ status;
302
+ endpoint;
303
+ method;
304
+ requestId;
305
+ hint;
306
+ causeDetail;
307
+ constructor(input) {
308
+ super(input.message);
309
+ this.name = "AthenaGatewayError";
310
+ this.code = input.code;
311
+ this.status = input.status ?? 0;
312
+ this.endpoint = input.endpoint;
313
+ this.method = input.method;
314
+ this.requestId = input.requestId;
315
+ this.hint = input.hint;
316
+ this.causeDetail = input.cause;
317
+ }
318
+ toDetails() {
319
+ return {
320
+ code: this.code,
321
+ message: this.message,
322
+ status: this.status,
323
+ endpoint: this.endpoint,
324
+ method: this.method,
325
+ requestId: this.requestId,
326
+ hint: this.hint,
327
+ cause: this.causeDetail
328
+ };
329
+ }
330
+ static fromResponse(response, fallback) {
331
+ const details = response.errorDetails;
332
+ if (details) {
333
+ return new _AthenaGatewayError({
334
+ code: details.code,
335
+ message: details.message,
336
+ status: details.status,
337
+ endpoint: details.endpoint ?? fallback.endpoint,
338
+ method: details.method ?? fallback.method,
339
+ requestId: details.requestId ?? fallback.requestId,
340
+ hint: details.hint,
341
+ cause: details.cause
342
+ });
343
+ }
344
+ return new _AthenaGatewayError({
345
+ code: "HTTP_ERROR",
346
+ message: response.error ?? "Gateway request failed",
347
+ status: response.status,
348
+ endpoint: fallback.endpoint,
349
+ method: fallback.method,
350
+ requestId: fallback.requestId
351
+ });
352
+ }
353
+ };
354
+ function isAthenaGatewayError(error) {
355
+ return error instanceof AthenaGatewayError;
356
+ }
357
+
358
+ // src/auxiliaries.ts
359
+ var AthenaErrorCode = {
360
+ UniqueViolation: "UNIQUE_VIOLATION",
361
+ NotFound: "NOT_FOUND",
362
+ ValidationFailed: "VALIDATION_FAILED",
363
+ AuthUnauthorized: "AUTH_UNAUTHORIZED",
364
+ AuthForbidden: "AUTH_FORBIDDEN",
365
+ RateLimited: "RATE_LIMITED",
366
+ NetworkUnavailable: "NETWORK_UNAVAILABLE",
367
+ TransientFailure: "TRANSIENT_FAILURE",
368
+ HttpFailure: "HTTP_FAILURE",
369
+ Unknown: "UNKNOWN"
370
+ };
371
+ var AthenaErrorCategory = {
372
+ Transport: "transport",
373
+ Client: "client",
374
+ Server: "server",
375
+ Database: "database",
376
+ Unknown: "unknown"
377
+ };
378
+ function parseBooleanFlag(rawValue, fallback) {
379
+ if (!rawValue) return fallback;
380
+ const normalized = rawValue.trim().toLowerCase();
381
+ if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
382
+ return true;
383
+ }
384
+ if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
385
+ return false;
386
+ }
387
+ return fallback;
388
+ }
389
+ function isRecord(value) {
390
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
391
+ }
392
+ function isAthenaErrorKind(value) {
393
+ return value === "unique_violation" || value === "not_found" || value === "validation" || value === "auth" || value === "rate_limit" || value === "transient" || value === "unknown";
394
+ }
395
+ function isAthenaErrorCode(value) {
396
+ return value === "UNIQUE_VIOLATION" || value === "NOT_FOUND" || value === "VALIDATION_FAILED" || value === "AUTH_UNAUTHORIZED" || value === "AUTH_FORBIDDEN" || value === "RATE_LIMITED" || value === "NETWORK_UNAVAILABLE" || value === "TRANSIENT_FAILURE" || value === "HTTP_FAILURE" || value === "UNKNOWN";
397
+ }
398
+ function isAthenaErrorCategory(value) {
399
+ return value === "transport" || value === "client" || value === "server" || value === "database" || value === "unknown";
400
+ }
401
+ function isNormalizedAthenaError(value) {
402
+ return isRecord(value) && isAthenaErrorKind(value.kind) && isAthenaErrorCode(value.code) && isAthenaErrorCategory(value.category) && typeof value.retryable === "boolean" && typeof value.message === "string" && "raw" in value;
403
+ }
404
+ function withContextOverrides(normalized, context) {
405
+ if (!context?.table && !context?.operation) {
406
+ return normalized;
407
+ }
408
+ return {
409
+ ...normalized,
410
+ table: context.table ?? normalized.table,
411
+ operation: context.operation ?? normalized.operation
412
+ };
413
+ }
414
+ function resolveAttachedNormalizedError(resultOrError) {
415
+ if (!isRecord(resultOrError)) return void 0;
416
+ if (!("__athenaNormalizedError" in resultOrError)) return void 0;
417
+ const candidate = resultOrError.__athenaNormalizedError;
418
+ return isNormalizedAthenaError(candidate) ? candidate : void 0;
419
+ }
420
+ function isAthenaResultLike(value) {
421
+ return isRecord(value) && "status" in value && "error" in value && "data" in value && typeof value.status === "number";
422
+ }
423
+ function operationFromDetails(details) {
424
+ if (!details?.endpoint) return void 0;
425
+ if (details.endpoint === "/gateway/fetch" || details.endpoint === "/gateway/query") return "select";
426
+ if (details.endpoint === "/gateway/insert") return "insert";
427
+ if (details.endpoint === "/gateway/update") return "update";
428
+ if (details.endpoint === "/gateway/delete") return "delete";
429
+ if (details.endpoint === "/gateway/rpc" || details.endpoint.startsWith("/rpc/")) return "rpc";
430
+ return void 0;
431
+ }
432
+ function matchRegex(input, patterns) {
433
+ for (const pattern of patterns) {
434
+ const match = pattern.exec(input);
435
+ if (match?.[1]) return match[1];
436
+ }
437
+ return void 0;
438
+ }
439
+ function extractConstraint(message) {
440
+ return matchRegex(message, [
441
+ /unique constraint\s+["'`]([^"'`]+)["'`]/i,
442
+ /constraint\s+["'`]([^"'`]+)["'`]/i
443
+ ]);
444
+ }
445
+ function extractTable(message) {
446
+ return matchRegex(message, [
447
+ /(?:table|relation)\s+["'`]([^"'`]+)["'`]/i,
448
+ /on\s+table\s+([a-zA-Z0-9_.]+)/i
449
+ ]);
450
+ }
451
+ function classifyKind(status, code, message) {
452
+ const lower = message.toLowerCase();
453
+ const hasUniquePattern = lower.includes("unique constraint") || lower.includes("duplicate key") || lower.includes("already exists") || lower.includes("duplicate");
454
+ const hasNotFoundPattern = lower.includes("not found") || lower.includes("no rows");
455
+ const hasValidationPattern = lower.includes("validation") || lower.includes("invalid") || lower.includes("malformed");
456
+ const hasAuthPattern = lower.includes("unauthorized") || lower.includes("forbidden") || lower.includes("auth");
457
+ const hasRateLimitPattern = lower.includes("rate limit") || lower.includes("too many requests");
458
+ const hasTransientPattern = lower.includes("timeout") || lower.includes("temporar") || lower.includes("connection reset") || lower.includes("socket") || lower.includes("deadlock");
459
+ if (status === 409 || hasUniquePattern) return "unique_violation";
460
+ if (status === 404 || hasNotFoundPattern) return "not_found";
461
+ if (status === 401 || status === 403 || hasAuthPattern) return "auth";
462
+ if (status === 429 || hasRateLimitPattern) return "rate_limit";
463
+ if (status === 400 || status === 422 || hasValidationPattern) return "validation";
464
+ if (code === "NETWORK_ERROR" || status === 0 || status !== void 0 && status >= 500 || hasTransientPattern) {
465
+ return "transient";
466
+ }
467
+ return "unknown";
468
+ }
469
+ function toAthenaErrorCode(kind, status, gatewayCode) {
470
+ if (gatewayCode === "NETWORK_ERROR" || kind === "transient" && status === 0) {
471
+ return AthenaErrorCode.NetworkUnavailable;
472
+ }
473
+ switch (kind) {
474
+ case "unique_violation":
475
+ return AthenaErrorCode.UniqueViolation;
476
+ case "not_found":
477
+ return AthenaErrorCode.NotFound;
478
+ case "validation":
479
+ return AthenaErrorCode.ValidationFailed;
480
+ case "rate_limit":
481
+ return AthenaErrorCode.RateLimited;
482
+ case "auth":
483
+ if (status === 403) {
484
+ return AthenaErrorCode.AuthForbidden;
485
+ }
486
+ return AthenaErrorCode.AuthUnauthorized;
487
+ case "transient":
488
+ return status !== void 0 && status >= 500 ? AthenaErrorCode.HttpFailure : AthenaErrorCode.TransientFailure;
489
+ case "unknown":
490
+ default:
491
+ return status !== void 0 && status >= 400 ? AthenaErrorCode.HttpFailure : AthenaErrorCode.Unknown;
492
+ }
493
+ }
494
+ function toAthenaErrorCategory(kind, status) {
495
+ if (kind === "transient" && (status === 0 || status === void 0)) {
496
+ return AthenaErrorCategory.Transport;
497
+ }
498
+ if (kind === "unique_violation") return AthenaErrorCategory.Database;
499
+ if (kind === "validation" || kind === "auth" || kind === "not_found") return AthenaErrorCategory.Client;
500
+ if (kind === "rate_limit" || kind === "transient") return AthenaErrorCategory.Server;
501
+ return AthenaErrorCategory.Unknown;
502
+ }
503
+ function isRetryable(kind, status) {
504
+ if (kind === "rate_limit" || kind === "transient") return true;
505
+ return status !== void 0 && status >= 500;
506
+ }
507
+ function normalizeAthenaError(resultOrError, context) {
508
+ const attached = resolveAttachedNormalizedError(resultOrError);
509
+ if (attached) {
510
+ return withContextOverrides(attached, context);
511
+ }
512
+ if (isAthenaResultLike(resultOrError)) {
513
+ const details = resultOrError.errorDetails;
514
+ const message2 = resultOrError.error ?? details?.message ?? `Athena ${context?.operation ?? operationFromDetails(details) ?? "request"} failed`;
515
+ const operation = context?.operation ?? operationFromDetails(details);
516
+ const table = context?.table ?? extractTable(message2);
517
+ const constraint = extractConstraint(message2);
518
+ const kind2 = classifyKind(resultOrError.status, details?.code, message2);
519
+ const code = toAthenaErrorCode(kind2, resultOrError.status, details?.code);
520
+ const category = toAthenaErrorCategory(kind2, resultOrError.status);
521
+ return {
522
+ kind: kind2,
523
+ code,
524
+ category,
525
+ retryable: isRetryable(kind2, resultOrError.status),
526
+ status: resultOrError.status,
527
+ constraint,
528
+ table,
529
+ operation,
530
+ message: message2,
531
+ raw: resultOrError.raw
532
+ };
533
+ }
534
+ if (isAthenaGatewayError(resultOrError)) {
535
+ const details = resultOrError.toDetails();
536
+ const operation = context?.operation ?? operationFromDetails(details);
537
+ const table = context?.table ?? extractTable(resultOrError.message);
538
+ const constraint = extractConstraint(resultOrError.message);
539
+ const kind2 = classifyKind(resultOrError.status, resultOrError.code, resultOrError.message);
540
+ const code = toAthenaErrorCode(kind2, resultOrError.status, resultOrError.code);
541
+ const category = toAthenaErrorCategory(kind2, resultOrError.status);
542
+ return {
543
+ kind: kind2,
544
+ code,
545
+ category,
546
+ retryable: isRetryable(kind2, resultOrError.status),
547
+ status: resultOrError.status,
548
+ constraint,
549
+ table,
550
+ operation,
551
+ message: resultOrError.message,
552
+ raw: resultOrError
553
+ };
554
+ }
555
+ if (resultOrError instanceof Error) {
556
+ const maybeStatus = isRecord(resultOrError) && typeof resultOrError.status === "number" ? resultOrError.status : void 0;
557
+ const kind2 = classifyKind(maybeStatus, void 0, resultOrError.message);
558
+ return {
559
+ kind: kind2,
560
+ code: toAthenaErrorCode(kind2, maybeStatus),
561
+ category: toAthenaErrorCategory(kind2, maybeStatus),
562
+ retryable: isRetryable(kind2, maybeStatus),
563
+ status: maybeStatus,
564
+ constraint: extractConstraint(resultOrError.message),
565
+ table: context?.table ?? extractTable(resultOrError.message),
566
+ operation: context?.operation,
567
+ message: resultOrError.message,
568
+ raw: resultOrError
569
+ };
570
+ }
571
+ const message = typeof resultOrError === "string" ? resultOrError : "Unknown Athena error";
572
+ const kind = classifyKind(void 0, void 0, message);
573
+ return {
574
+ kind,
575
+ code: toAthenaErrorCode(kind, void 0),
576
+ category: toAthenaErrorCategory(kind, void 0),
577
+ retryable: isRetryable(kind, void 0),
578
+ status: void 0,
579
+ constraint: extractConstraint(message),
580
+ table: context?.table ?? extractTable(message),
581
+ operation: context?.operation,
582
+ message,
583
+ raw: resultOrError
584
+ };
585
+ }
586
+
295
587
  // src/generator/schema-selection.ts
296
588
  var DEFAULT_POSTGRES_SCHEMAS = ["public"];
297
589
  function collectSchemaNames(input) {
@@ -322,6 +614,7 @@ function resolveProviderSchemas(providerConfig) {
322
614
  }
323
615
 
324
616
  // src/generator/config.ts
617
+ var POSTGRES_PROTOCOLS = /* @__PURE__ */ new Set(["postgres:", "postgresql:"]);
325
618
  var DEFAULT_CONFIG_CANDIDATES = [
326
619
  "athena.config.ts",
327
620
  "athena.config.js",
@@ -351,6 +644,184 @@ var DEFAULT_EXPERIMENTAL_FLAGS = {
351
644
  postgresGatewayIntrospection: false,
352
645
  scyllaProviderContracts: true
353
646
  };
647
+ var PROJECT_ENV_FILENAMES = [".env", ".env.local"];
648
+ var DIRECT_CONNECTION_STRING_ENV_KEYS = [
649
+ "ATHENA_GENERATOR_PG_URL",
650
+ "DATABASE_URL",
651
+ "PG_URL",
652
+ "POSTGRES_URL",
653
+ "POSTGRESQL_URL"
654
+ ];
655
+ var POSTGRES_DATABASE_ENV_KEYS = ["ATHENA_GENERATOR_DB", "ATHENA_DATABASE", "PGDATABASE"];
656
+ var POSTGRES_PASSWORD_ENV_KEYS = ["ATHENA_GENERATOR_PG_PASSWORD", "PGPASSWORD"];
657
+ var GATEWAY_URL_ENV_KEYS = ["ATHENA_URL", "ATHENA_GATEWAY_URL", "ATHENA_GENERATOR_URL"];
658
+ var GATEWAY_API_KEY_ENV_KEYS = [
659
+ "ATHENA_API_KEY",
660
+ "ATHENA_GATEWAY_API_KEY",
661
+ "ATHENA_GENERATOR_API_KEY"
662
+ ];
663
+ function normalizeRawEnvValue(rawValue) {
664
+ if (rawValue.startsWith('"') && rawValue.endsWith('"') && rawValue.length >= 2) {
665
+ const inner = rawValue.slice(1, -1);
666
+ return inner.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
667
+ }
668
+ if (rawValue.startsWith("'") && rawValue.endsWith("'") && rawValue.length >= 2) {
669
+ return rawValue.slice(1, -1);
670
+ }
671
+ const commentIndex = rawValue.search(/\s+#/);
672
+ const withoutComment = commentIndex >= 0 ? rawValue.slice(0, commentIndex) : rawValue;
673
+ return withoutComment.trim();
674
+ }
675
+ function parseEnvLine(line) {
676
+ const trimmed = line.trim();
677
+ if (!trimmed || trimmed.startsWith("#")) {
678
+ return void 0;
679
+ }
680
+ const match = trimmed.match(/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
681
+ if (!match) {
682
+ return void 0;
683
+ }
684
+ const [, key, rawValue] = match;
685
+ return [key, normalizeRawEnvValue(rawValue.trim())];
686
+ }
687
+ function readProjectEnvEntries(cwd) {
688
+ const nodeEnv = process.env.NODE_ENV?.trim();
689
+ const filenames = [
690
+ ...PROJECT_ENV_FILENAMES,
691
+ ...nodeEnv ? [`.env.${nodeEnv}`, `.env.${nodeEnv}.local`] : []
692
+ ];
693
+ const entries = /* @__PURE__ */ new Map();
694
+ for (const filename of filenames) {
695
+ const absolutePath = path.resolve(cwd, filename);
696
+ if (!fs.existsSync(absolutePath)) {
697
+ continue;
698
+ }
699
+ const content = fs.readFileSync(absolutePath, "utf8");
700
+ const lines = content.split(/\r?\n/g);
701
+ for (const line of lines) {
702
+ const parsed = parseEnvLine(line);
703
+ if (!parsed) {
704
+ continue;
705
+ }
706
+ const [key, value] = parsed;
707
+ entries.set(key, value);
708
+ }
709
+ }
710
+ return entries;
711
+ }
712
+ function applyProjectEnv(cwd) {
713
+ const envEntries = readProjectEnvEntries(cwd);
714
+ if (envEntries.size === 0) {
715
+ return () => {
716
+ };
717
+ }
718
+ const initialKeys = new Set(
719
+ Object.keys(process.env).filter((key) => process.env[key] !== void 0)
720
+ );
721
+ const staged = /* @__PURE__ */ new Map();
722
+ for (const [key, value] of envEntries.entries()) {
723
+ if (initialKeys.has(key)) {
724
+ continue;
725
+ }
726
+ staged.set(key, value);
727
+ }
728
+ for (const [key, value] of staged.entries()) {
729
+ process.env[key] = value;
730
+ }
731
+ return () => {
732
+ for (const key of staged.keys()) {
733
+ delete process.env[key];
734
+ }
735
+ };
736
+ }
737
+ function readEnvStringValue(key) {
738
+ const value = process.env[key];
739
+ if (typeof value !== "string") {
740
+ return void 0;
741
+ }
742
+ const trimmed = value.trim();
743
+ return trimmed.length > 0 ? trimmed : void 0;
744
+ }
745
+ function resolveFallbackValue(fallbackKeys) {
746
+ for (const key of fallbackKeys) {
747
+ const value = readEnvStringValue(key);
748
+ if (value) {
749
+ return value;
750
+ }
751
+ }
752
+ return void 0;
753
+ }
754
+ function normalizeOptionalString(value, fallbackKeys) {
755
+ if (typeof value === "string") {
756
+ const trimmed = value.trim();
757
+ if (trimmed.length > 0) {
758
+ return trimmed;
759
+ }
760
+ }
761
+ return resolveFallbackValue(fallbackKeys);
762
+ }
763
+ function normalizeRequiredString(value, fieldLabel, fallbackKeys) {
764
+ const resolved = normalizeOptionalString(value, fallbackKeys);
765
+ if (resolved) {
766
+ return resolved;
767
+ }
768
+ throw new Error(
769
+ `Generator config is missing ${fieldLabel}. Set ${fieldLabel} directly or provide one of: ${fallbackKeys.join(", ")}.`
770
+ );
771
+ }
772
+ function applyPostgresPasswordFallback(connectionString) {
773
+ let parsedUrl;
774
+ try {
775
+ parsedUrl = new URL(connectionString);
776
+ } catch {
777
+ return connectionString;
778
+ }
779
+ if (!POSTGRES_PROTOCOLS.has(parsedUrl.protocol)) {
780
+ return connectionString;
781
+ }
782
+ if (!parsedUrl.username || parsedUrl.password) {
783
+ return connectionString;
784
+ }
785
+ const fallbackPassword = resolveFallbackValue(POSTGRES_PASSWORD_ENV_KEYS);
786
+ if (!fallbackPassword) {
787
+ return connectionString;
788
+ }
789
+ parsedUrl.password = fallbackPassword;
790
+ return parsedUrl.toString();
791
+ }
792
+ function normalizeBooleanFlag(rawValue, fallback) {
793
+ if (typeof rawValue === "boolean") {
794
+ return rawValue;
795
+ }
796
+ if (typeof rawValue === "string") {
797
+ return parseBooleanFlag(rawValue, fallback);
798
+ }
799
+ return fallback;
800
+ }
801
+ function normalizeFeatureFlags(input) {
802
+ return {
803
+ emitRelations: normalizeBooleanFlag(
804
+ input?.emitRelations,
805
+ DEFAULT_FEATURES.emitRelations
806
+ ),
807
+ emitRegistry: normalizeBooleanFlag(
808
+ input?.emitRegistry,
809
+ DEFAULT_FEATURES.emitRegistry
810
+ )
811
+ };
812
+ }
813
+ function normalizeExperimentalFlags(input) {
814
+ return {
815
+ postgresGatewayIntrospection: normalizeBooleanFlag(
816
+ input?.postgresGatewayIntrospection,
817
+ DEFAULT_EXPERIMENTAL_FLAGS.postgresGatewayIntrospection
818
+ ),
819
+ scyllaProviderContracts: normalizeBooleanFlag(
820
+ input?.scyllaProviderContracts,
821
+ DEFAULT_EXPERIMENTAL_FLAGS.scyllaProviderContracts
822
+ )
823
+ };
824
+ }
354
825
  function normalizeOutputConfig(output) {
355
826
  return {
356
827
  targets: {
@@ -363,9 +834,41 @@ function normalizeOutputConfig(output) {
363
834
  };
364
835
  }
365
836
  function normalizeProviderConfig(provider) {
366
- if (provider.kind === "postgres") {
837
+ if (provider.kind === "postgres" && provider.mode === "direct") {
838
+ const connectionString = normalizeRequiredString(
839
+ provider.connectionString,
840
+ "provider.connectionString",
841
+ DIRECT_CONNECTION_STRING_ENV_KEYS
842
+ );
843
+ const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS);
844
+ return {
845
+ ...provider,
846
+ connectionString: applyPostgresPasswordFallback(connectionString),
847
+ database,
848
+ schemas: normalizeSchemaSelection(provider.schemas)
849
+ };
850
+ }
851
+ if (provider.kind === "postgres" && provider.mode === "gateway") {
852
+ const gatewayUrl = normalizeRequiredString(
853
+ provider.gatewayUrl,
854
+ "provider.gatewayUrl",
855
+ GATEWAY_URL_ENV_KEYS
856
+ );
857
+ const apiKey = normalizeRequiredString(
858
+ provider.apiKey,
859
+ "provider.apiKey",
860
+ GATEWAY_API_KEY_ENV_KEYS
861
+ );
862
+ const database = normalizeRequiredString(
863
+ provider.database,
864
+ "provider.database",
865
+ POSTGRES_DATABASE_ENV_KEYS
866
+ );
367
867
  return {
368
868
  ...provider,
869
+ gatewayUrl,
870
+ apiKey,
871
+ database,
369
872
  schemas: normalizeSchemaSelection(provider.schemas)
370
873
  };
371
874
  }
@@ -386,14 +889,8 @@ function normalizeGeneratorConfig(input) {
386
889
  ...DEFAULT_NAMING,
387
890
  ...input.naming ?? {}
388
891
  },
389
- features: {
390
- ...DEFAULT_FEATURES,
391
- ...input.features ?? {}
392
- },
393
- experimental: {
394
- ...DEFAULT_EXPERIMENTAL_FLAGS,
395
- ...input.experimental ?? {}
396
- }
892
+ features: normalizeFeatureFlags(input.features),
893
+ experimental: normalizeExperimentalFlags(input.experimental)
397
894
  };
398
895
  }
399
896
  function findGeneratorConfigPath(cwd = process.cwd()) {
@@ -430,6 +927,11 @@ function extractConfigExport(module) {
430
927
  if (moduleExports && typeof moduleExports === "object") {
431
928
  queue.push(moduleExports);
432
929
  }
930
+ for (const value of Object.values(record)) {
931
+ if (value && typeof value === "object") {
932
+ queue.push(value);
933
+ }
934
+ }
433
935
  }
434
936
  throw new Error(
435
937
  "Generator config file must export a config object as default export or `config`."
@@ -444,19 +946,24 @@ function importConfigModule(moduleSpecifier) {
444
946
  }
445
947
  async function loadGeneratorConfig(options = {}) {
446
948
  const cwd = options.cwd ?? process.cwd();
949
+ const restoreProjectEnv = applyProjectEnv(cwd);
447
950
  const resolvedPath = options.configPath ? path.resolve(cwd, options.configPath) : findGeneratorConfigPath(cwd);
448
951
  if (!resolvedPath) {
449
952
  throw new Error(
450
953
  `No generator config found in ${cwd}. Expected one of: ${DEFAULT_CONFIG_CANDIDATES.join(", ")}`
451
954
  );
452
955
  }
453
- const moduleUrl = url.pathToFileURL(resolvedPath);
454
- const module = await importConfigModule(`${moduleUrl.href}?cacheBust=${Date.now()}`);
455
- const rawConfig = extractConfigExport(module);
456
- return {
457
- configPath: resolvedPath,
458
- config: normalizeGeneratorConfig(rawConfig)
459
- };
956
+ try {
957
+ const moduleUrl = url.pathToFileURL(resolvedPath);
958
+ const module = await importConfigModule(`${moduleUrl.href}?cacheBust=${Date.now()}`);
959
+ const rawConfig = extractConfigExport(module);
960
+ return {
961
+ configPath: resolvedPath,
962
+ config: normalizeGeneratorConfig(rawConfig)
963
+ };
964
+ } finally {
965
+ restoreProjectEnv();
966
+ }
460
967
  }
461
968
 
462
969
  // src/generator/renderer.ts
@@ -598,13 +1105,65 @@ function assertNoDuplicatePaths(files) {
598
1105
  [
599
1106
  `Generator output collision detected for path: ${file.path}`,
600
1107
  `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."
1108
+ "Use explicit placeholders such as {model}, {model_kebab}, {schema}, or {schema_kebab} in output targets so each artifact resolves to a unique path."
602
1109
  ].join(" ")
603
1110
  );
604
1111
  }
605
1112
  seen.set(file.path, file);
606
1113
  }
607
1114
  }
1115
+ function addSchemaSegmentToPath(pathValue, schemaName) {
1116
+ const normalizedPath = normalizePath(pathValue);
1117
+ const parsedPath = path.posix.parse(normalizedPath);
1118
+ const schemaSegment = applyNamingStyle(schemaName, "kebab");
1119
+ if (!schemaSegment) {
1120
+ return normalizedPath;
1121
+ }
1122
+ const dir = parsedPath.dir.length > 0 ? `${parsedPath.dir}/${schemaSegment}` : schemaSegment;
1123
+ return normalizePath(path.posix.join(dir, parsedPath.base));
1124
+ }
1125
+ function scopeDuplicateDescriptorPathsBySchema(descriptors) {
1126
+ const nextDescriptors = descriptors.map((descriptor) => ({ ...descriptor }));
1127
+ const duplicates = /* @__PURE__ */ new Map();
1128
+ for (let index = 0; index < nextDescriptors.length; index += 1) {
1129
+ const descriptor = nextDescriptors[index];
1130
+ const indexes = duplicates.get(descriptor.filePath) ?? [];
1131
+ indexes.push(index);
1132
+ duplicates.set(descriptor.filePath, indexes);
1133
+ }
1134
+ let appliedSchemaScoping = false;
1135
+ for (const indexes of duplicates.values()) {
1136
+ if (indexes.length <= 1) {
1137
+ continue;
1138
+ }
1139
+ const schemaNames = new Set(indexes.map((index) => nextDescriptors[index].schemaName));
1140
+ if (schemaNames.size <= 1) {
1141
+ continue;
1142
+ }
1143
+ for (const index of indexes) {
1144
+ const descriptor = nextDescriptors[index];
1145
+ descriptor.filePath = addSchemaSegmentToPath(descriptor.filePath, descriptor.schemaName);
1146
+ }
1147
+ appliedSchemaScoping = true;
1148
+ }
1149
+ if (!appliedSchemaScoping) {
1150
+ return nextDescriptors;
1151
+ }
1152
+ const normalizedPaths = /* @__PURE__ */ new Set();
1153
+ for (const descriptor of nextDescriptors) {
1154
+ if (normalizedPaths.has(descriptor.filePath)) {
1155
+ throw new Error(
1156
+ [
1157
+ `Generator output collision detected for path: ${descriptor.filePath}`,
1158
+ "Automatic schema path scoping was applied but collisions remain.",
1159
+ "Add explicit placeholders such as {model}, {model_kebab}, {schema}, or {schema_kebab} to your output targets."
1160
+ ].join(" ")
1161
+ );
1162
+ }
1163
+ normalizedPaths.add(descriptor.filePath);
1164
+ }
1165
+ return nextDescriptors;
1166
+ }
608
1167
  var ArtifactComposer = class {
609
1168
  constructor(snapshot, config) {
610
1169
  this.snapshot = snapshot;
@@ -643,7 +1202,8 @@ var ArtifactComposer = class {
643
1202
  });
644
1203
  }
645
1204
  }
646
- const schemaDescriptors = Object.keys(this.snapshot.schemas).sort().map((schemaName) => {
1205
+ const scopedModelDescriptors = scopeDuplicateDescriptorPathsBySchema(modelDescriptors);
1206
+ let schemaDescriptors = Object.keys(this.snapshot.schemas).sort().map((schemaName) => {
647
1207
  const schemaPath = normalizePath(
648
1208
  renderOutputPath(this.config.output.targets.schema, {
649
1209
  provider: providerName,
@@ -661,9 +1221,10 @@ var ArtifactComposer = class {
661
1221
  this.config.naming.schemaConst,
662
1222
  "schema"
663
1223
  ),
664
- models: modelDescriptors.filter((model) => model.schemaName === schemaName)
1224
+ models: scopedModelDescriptors.filter((model) => model.schemaName === schemaName)
665
1225
  };
666
1226
  });
1227
+ schemaDescriptors = scopeDuplicateDescriptorPathsBySchema(schemaDescriptors);
667
1228
  const databasePath = normalizePath(
668
1229
  renderOutputPath(this.config.output.targets.database, {
669
1230
  provider: providerName,
@@ -683,7 +1244,7 @@ var ArtifactComposer = class {
683
1244
  schemas: schemaDescriptors
684
1245
  };
685
1246
  const files = [];
686
- for (const modelDescriptor of modelDescriptors) {
1247
+ for (const modelDescriptor of scopedModelDescriptors) {
687
1248
  files.push(renderModelArtifact(this.snapshot, modelDescriptor, this.config));
688
1249
  }
689
1250
  for (const schemaDescriptor of schemaDescriptors) {
@@ -722,63 +1283,6 @@ function generateArtifactsFromSnapshot(snapshot, config) {
722
1283
  return new ArtifactComposer(snapshot, normalizedConfig).compose();
723
1284
  }
724
1285
 
725
- // src/gateway/errors.ts
726
- var AthenaGatewayError = class _AthenaGatewayError extends Error {
727
- code;
728
- status;
729
- endpoint;
730
- method;
731
- requestId;
732
- hint;
733
- causeDetail;
734
- constructor(input) {
735
- super(input.message);
736
- this.name = "AthenaGatewayError";
737
- this.code = input.code;
738
- this.status = input.status ?? 0;
739
- this.endpoint = input.endpoint;
740
- this.method = input.method;
741
- this.requestId = input.requestId;
742
- this.hint = input.hint;
743
- this.causeDetail = input.cause;
744
- }
745
- toDetails() {
746
- return {
747
- code: this.code,
748
- message: this.message,
749
- status: this.status,
750
- endpoint: this.endpoint,
751
- method: this.method,
752
- requestId: this.requestId,
753
- hint: this.hint,
754
- cause: this.causeDetail
755
- };
756
- }
757
- static fromResponse(response, fallback) {
758
- const details = response.errorDetails;
759
- if (details) {
760
- return new _AthenaGatewayError({
761
- code: details.code,
762
- message: details.message,
763
- status: details.status,
764
- endpoint: details.endpoint ?? fallback.endpoint,
765
- method: details.method ?? fallback.method,
766
- requestId: details.requestId ?? fallback.requestId,
767
- hint: details.hint,
768
- cause: details.cause
769
- });
770
- }
771
- return new _AthenaGatewayError({
772
- code: "HTTP_ERROR",
773
- message: response.error ?? "Gateway request failed",
774
- status: response.status,
775
- endpoint: fallback.endpoint,
776
- method: fallback.method,
777
- requestId: fallback.requestId
778
- });
779
- }
780
- };
781
-
782
1286
  // src/gateway/client.ts
783
1287
  var DEFAULT_BASE_URL = "https://athena-db.com";
784
1288
  var DEFAULT_CLIENT = "railway_direct";
@@ -804,14 +1308,14 @@ function parseResponseBody(rawText, contentType) {
804
1308
  function normalizeHeaderValue(value) {
805
1309
  return value ? value : void 0;
806
1310
  }
807
- function isRecord(value) {
1311
+ function isRecord2(value) {
808
1312
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
809
1313
  }
810
1314
  function resolveRequestId(headers) {
811
1315
  return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
812
1316
  }
813
1317
  function resolveErrorMessage(payload, fallback) {
814
- if (isRecord(payload)) {
1318
+ if (isRecord2(payload)) {
815
1319
  const messageCandidates = [payload.error, payload.message, payload.details];
816
1320
  for (const candidate of messageCandidates) {
817
1321
  if (typeof candidate === "string" && candidate.trim().length > 0) {
@@ -1001,7 +1505,7 @@ async function callAthena(config, endpoint, method, payload, options) {
1001
1505
  };
1002
1506
  }
1003
1507
  const parsed = parsedBody.parsed;
1004
- const parsedPayload = isRecord(parsed) ? parsed : null;
1508
+ const parsedPayload = isRecord2(parsed) ? parsed : null;
1005
1509
  if (!response.ok) {
1006
1510
  const httpError = new AthenaGatewayError({
1007
1511
  code: "HTTP_ERROR",
@@ -1084,126 +1588,1196 @@ function createAthenaGatewayClient(config = {}) {
1084
1588
  }
1085
1589
  };
1086
1590
  }
1087
-
1088
- // src/sql-identifiers.ts
1089
- var SIMPLE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
1090
- var COMPOSITE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
1091
- var ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_.]*)\s+(?:as\s+)?([A-Za-z_][A-Za-z0-9_]*)$/i;
1092
- function quoteIdentifierSegment(identifier) {
1093
- return `"${identifier.replace(/"/g, '""')}"`;
1591
+
1592
+ // src/sql-identifiers.ts
1593
+ var SIMPLE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
1594
+ var COMPOSITE_IDENTIFIER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
1595
+ var ALIAS_PATTERN = /^([A-Za-z_][A-Za-z0-9_.]*)\s+(?:as\s+)?([A-Za-z_][A-Za-z0-9_]*)$/i;
1596
+ function quoteIdentifierSegment(identifier) {
1597
+ return `"${identifier.replace(/"/g, '""')}"`;
1598
+ }
1599
+ function quoteQualifiedIdentifier(identifier) {
1600
+ return identifier.split(".").map((segment) => quoteIdentifierSegment(segment)).join(".");
1601
+ }
1602
+ function quoteSelectToken(token) {
1603
+ if (token === "*") return token;
1604
+ if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) {
1605
+ return quoteQualifiedIdentifier(token);
1606
+ }
1607
+ const aliasMatch = ALIAS_PATTERN.exec(token);
1608
+ if (!aliasMatch) {
1609
+ return token;
1610
+ }
1611
+ const [, baseIdentifier, aliasIdentifier] = aliasMatch;
1612
+ if (!COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) || !SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier)) {
1613
+ return token;
1614
+ }
1615
+ return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteIdentifierSegment(aliasIdentifier)}`;
1616
+ }
1617
+ function canAutoQuoteToken(token) {
1618
+ if (token === "*") return true;
1619
+ if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) return true;
1620
+ const aliasMatch = ALIAS_PATTERN.exec(token);
1621
+ if (!aliasMatch) return false;
1622
+ const [, baseIdentifier, aliasIdentifier] = aliasMatch;
1623
+ return COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) && SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier);
1624
+ }
1625
+ function splitTopLevelCommaSeparated(input) {
1626
+ const parts = [];
1627
+ let buffer = "";
1628
+ let singleQuoted = false;
1629
+ let doubleQuoted = false;
1630
+ let depth = 0;
1631
+ for (let index = 0; index < input.length; index += 1) {
1632
+ const char = input[index];
1633
+ const next = index + 1 < input.length ? input[index + 1] : "";
1634
+ if (singleQuoted) {
1635
+ buffer += char;
1636
+ if (char === "'" && next === "'") {
1637
+ buffer += next;
1638
+ index += 1;
1639
+ continue;
1640
+ }
1641
+ if (char === "'") {
1642
+ singleQuoted = false;
1643
+ }
1644
+ continue;
1645
+ }
1646
+ if (doubleQuoted) {
1647
+ buffer += char;
1648
+ if (char === '"' && next === '"') {
1649
+ buffer += next;
1650
+ index += 1;
1651
+ continue;
1652
+ }
1653
+ if (char === '"') {
1654
+ doubleQuoted = false;
1655
+ }
1656
+ continue;
1657
+ }
1658
+ if (char === "'") {
1659
+ singleQuoted = true;
1660
+ buffer += char;
1661
+ continue;
1662
+ }
1663
+ if (char === '"') {
1664
+ doubleQuoted = true;
1665
+ buffer += char;
1666
+ continue;
1667
+ }
1668
+ if (char === "(") {
1669
+ depth += 1;
1670
+ buffer += char;
1671
+ continue;
1672
+ }
1673
+ if (char === ")") {
1674
+ depth -= 1;
1675
+ if (depth < 0) return null;
1676
+ buffer += char;
1677
+ continue;
1678
+ }
1679
+ if (char === "," && depth === 0) {
1680
+ parts.push(buffer.trim());
1681
+ buffer = "";
1682
+ continue;
1683
+ }
1684
+ buffer += char;
1685
+ }
1686
+ if (singleQuoted || doubleQuoted || depth !== 0) {
1687
+ return null;
1688
+ }
1689
+ if (buffer.trim().length > 0) {
1690
+ parts.push(buffer.trim());
1691
+ }
1692
+ return parts;
1693
+ }
1694
+ function quoteSelectColumnsExpression(columns) {
1695
+ const trimmed = columns.trim();
1696
+ if (!trimmed || trimmed === "*") return trimmed || "*";
1697
+ const tokens = splitTopLevelCommaSeparated(trimmed);
1698
+ if (!tokens || tokens.length === 0) {
1699
+ return trimmed;
1700
+ }
1701
+ if (!tokens.every(canAutoQuoteToken)) {
1702
+ return trimmed;
1703
+ }
1704
+ return tokens.map(quoteSelectToken).join(", ");
1705
+ }
1706
+
1707
+ // src/auth/client.ts
1708
+ var DEFAULT_AUTH_BASE_URL = "http://localhost:3001/api/auth";
1709
+ var FALLBACK_SDK_VERSION2 = "1.0.0";
1710
+ var SDK_NAME2 = "xylex-group/athena-auth";
1711
+ var SDK_VERSION2 = typeof process !== "undefined" && process?.env?.npm_package_version ? process.env.npm_package_version : FALLBACK_SDK_VERSION2;
1712
+ var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
1713
+ function normalizeBaseUrl(baseUrl) {
1714
+ return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
1715
+ }
1716
+ function isRecord3(value) {
1717
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1718
+ }
1719
+ function normalizeHeaderValue2(value) {
1720
+ return value ? value : void 0;
1721
+ }
1722
+ function parseResponseBody2(rawText, contentType) {
1723
+ if (!rawText) {
1724
+ return { parsed: null, parseFailed: false };
1725
+ }
1726
+ const contentTypeSuggestsJson = contentType?.toLowerCase().includes("application/json") ?? false;
1727
+ const looksJson = contentTypeSuggestsJson || rawText.startsWith("{") || rawText.startsWith("[");
1728
+ if (!looksJson) {
1729
+ return { parsed: rawText, parseFailed: false };
1730
+ }
1731
+ try {
1732
+ return { parsed: JSON.parse(rawText), parseFailed: false };
1733
+ } catch {
1734
+ return { parsed: rawText, parseFailed: true };
1735
+ }
1736
+ }
1737
+ function resolveRequestId2(headers) {
1738
+ return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
1739
+ }
1740
+ function resolveErrorMessage2(payload, fallback) {
1741
+ if (isRecord3(payload)) {
1742
+ const messageCandidates = [payload.error, payload.message, payload.details];
1743
+ for (const candidate of messageCandidates) {
1744
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
1745
+ return candidate.trim();
1746
+ }
1747
+ }
1748
+ }
1749
+ if (typeof payload === "string" && payload.trim().length > 0) {
1750
+ return payload.trim();
1751
+ }
1752
+ return fallback;
1753
+ }
1754
+ function toErrorDetails(input) {
1755
+ return {
1756
+ code: input.code,
1757
+ message: input.message,
1758
+ status: input.status,
1759
+ endpoint: input.endpoint,
1760
+ method: input.method,
1761
+ requestId: input.requestId,
1762
+ hint: input.hint,
1763
+ cause: input.cause
1764
+ };
1765
+ }
1766
+ function mergeCallOptions(base, override) {
1767
+ if (!base && !override) return void 0;
1768
+ return {
1769
+ ...base,
1770
+ ...override,
1771
+ headers: {
1772
+ ...base?.headers ?? {},
1773
+ ...override?.headers ?? {}
1774
+ }
1775
+ };
1776
+ }
1777
+ function extractFetchOptions(input) {
1778
+ if (!input) {
1779
+ return {
1780
+ payload: void 0,
1781
+ fetchOptions: void 0
1782
+ };
1783
+ }
1784
+ const { fetchOptions, ...rest } = input;
1785
+ const hasPayloadKeys = Object.keys(rest).length > 0;
1786
+ return {
1787
+ payload: hasPayloadKeys ? rest : void 0,
1788
+ fetchOptions
1789
+ };
1790
+ }
1791
+ function buildHeaders2(config, options) {
1792
+ const headers = {
1793
+ "Content-Type": "application/json",
1794
+ "X-Athena-Sdk": SDK_HEADER_VALUE2
1795
+ };
1796
+ const apiKey = options?.apiKey ?? config.apiKey;
1797
+ if (apiKey) {
1798
+ headers.apikey = apiKey;
1799
+ headers["x-api-key"] = apiKey;
1800
+ }
1801
+ const bearerToken = options?.bearerToken ?? config.bearerToken;
1802
+ if (bearerToken) {
1803
+ headers.Authorization = `Bearer ${bearerToken}`;
1804
+ }
1805
+ const mergedExtraHeaders = {
1806
+ ...config.headers ?? {},
1807
+ ...options?.headers ?? {}
1808
+ };
1809
+ Object.entries(mergedExtraHeaders).forEach(([key, value]) => {
1810
+ const normalized = normalizeHeaderValue2(value);
1811
+ if (normalized) {
1812
+ headers[key] = normalized;
1813
+ }
1814
+ });
1815
+ return headers;
1816
+ }
1817
+ function appendQueryParam(searchParams, key, value) {
1818
+ if (value === void 0 || value === null) return;
1819
+ if (Array.isArray(value)) {
1820
+ value.forEach((item) => {
1821
+ searchParams.append(key, String(item));
1822
+ });
1823
+ return;
1824
+ }
1825
+ searchParams.append(key, String(value));
1826
+ }
1827
+ function buildRequestUrl(baseUrl, endpoint, query) {
1828
+ const url = `${baseUrl}${endpoint}`;
1829
+ if (!query || Object.keys(query).length === 0) return url;
1830
+ const searchParams = new URLSearchParams();
1831
+ Object.entries(query).forEach(([key, value]) => appendQueryParam(searchParams, key, value));
1832
+ const queryText = searchParams.toString();
1833
+ return queryText ? `${url}?${queryText}` : url;
1834
+ }
1835
+ function inferDefaultMethod(endpoint) {
1836
+ if (endpoint.startsWith("/reset-password/")) {
1837
+ return "GET";
1838
+ }
1839
+ switch (endpoint) {
1840
+ case "/get-session":
1841
+ case "/list-sessions":
1842
+ case "/verify-email":
1843
+ case "/change-email/verify":
1844
+ case "/delete-user/verify":
1845
+ case "/email-list":
1846
+ case "/email/list":
1847
+ case "/delete-user/callback":
1848
+ case "/list-accounts":
1849
+ case "/passkey/generate-register-options":
1850
+ case "/passkey/list-user-passkeys":
1851
+ case "/.well-known/webauthn":
1852
+ case "/admin/list-users":
1853
+ case "/admin/athena-client/list":
1854
+ case "/admin/audit-log/list":
1855
+ case "/admin/email/get":
1856
+ case "/admin/email-failure/list":
1857
+ case "/admin/email-failure/get":
1858
+ case "/admin/email-template/get":
1859
+ case "/admin/email-template/list":
1860
+ case "/admin/email/list":
1861
+ case "/api-key/get":
1862
+ case "/api-key/list":
1863
+ case "/organization/get-full-organization":
1864
+ case "/organization/list":
1865
+ case "/organization/get-invitation":
1866
+ case "/organization/list-invitations":
1867
+ case "/organization/list-user-invitations":
1868
+ case "/organization/list-members":
1869
+ case "/organization/get-active-member":
1870
+ case "/health":
1871
+ case "/ok":
1872
+ case "/error":
1873
+ return "GET";
1874
+ default:
1875
+ return "POST";
1876
+ }
1877
+ }
1878
+ async function callAuthEndpoint(config, context, body, query, options) {
1879
+ const baseUrl = normalizeBaseUrl(options?.baseUrl ?? config.baseUrl);
1880
+ const url = buildRequestUrl(baseUrl, context.endpoint, query);
1881
+ const headers = buildHeaders2(config, options);
1882
+ const credentials = options?.credentials ?? config.credentials ?? "include";
1883
+ const requestInit = {
1884
+ method: context.method,
1885
+ headers,
1886
+ credentials,
1887
+ signal: options?.signal
1888
+ };
1889
+ if (context.method !== "GET") {
1890
+ requestInit.body = JSON.stringify(body ?? {});
1891
+ }
1892
+ const fetcher = config.fetch ?? globalThis.fetch;
1893
+ if (!fetcher) {
1894
+ const details = toErrorDetails({
1895
+ code: "UNKNOWN_ERROR",
1896
+ message: "No fetch implementation available for auth client",
1897
+ status: 0,
1898
+ endpoint: context.endpoint,
1899
+ method: context.method,
1900
+ hint: "Use Node 18+ or provide `fetch` via createClient(..., { auth: { fetch } }) or createAuthClient({ fetch })"
1901
+ });
1902
+ return {
1903
+ ok: false,
1904
+ status: 0,
1905
+ data: null,
1906
+ error: details.message,
1907
+ errorDetails: details,
1908
+ raw: null
1909
+ };
1910
+ }
1911
+ try {
1912
+ const response = await fetcher(url, requestInit);
1913
+ const rawText = await response.text();
1914
+ const requestId = resolveRequestId2(response.headers);
1915
+ const parsedBody = parseResponseBody2(rawText ?? "", response.headers.get("content-type"));
1916
+ if (parsedBody.parseFailed) {
1917
+ const details = toErrorDetails({
1918
+ code: "INVALID_JSON",
1919
+ message: "Auth server returned malformed JSON",
1920
+ status: response.status,
1921
+ endpoint: context.endpoint,
1922
+ method: context.method,
1923
+ requestId,
1924
+ hint: "Verify the auth endpoint response body is valid JSON.",
1925
+ cause: rawText.slice(0, 300)
1926
+ });
1927
+ return {
1928
+ ok: false,
1929
+ status: response.status,
1930
+ data: null,
1931
+ error: details.message,
1932
+ errorDetails: details,
1933
+ raw: parsedBody.parsed
1934
+ };
1935
+ }
1936
+ const parsed = parsedBody.parsed;
1937
+ if (!response.ok) {
1938
+ const details = toErrorDetails({
1939
+ code: "HTTP_ERROR",
1940
+ message: resolveErrorMessage2(
1941
+ parsed,
1942
+ `Auth endpoint ${context.method} ${context.endpoint} failed with status ${response.status}`
1943
+ ),
1944
+ status: response.status,
1945
+ endpoint: context.endpoint,
1946
+ method: context.method,
1947
+ requestId
1948
+ });
1949
+ return {
1950
+ ok: false,
1951
+ status: response.status,
1952
+ data: null,
1953
+ error: details.message,
1954
+ errorDetails: details,
1955
+ raw: parsed
1956
+ };
1957
+ }
1958
+ return {
1959
+ ok: true,
1960
+ status: response.status,
1961
+ data: parsed ?? null,
1962
+ error: null,
1963
+ errorDetails: null,
1964
+ raw: parsed
1965
+ };
1966
+ } catch (callError) {
1967
+ const message = callError instanceof Error ? callError.message : String(callError);
1968
+ const details = toErrorDetails({
1969
+ code: "NETWORK_ERROR",
1970
+ message: `Network error while calling ${context.method} ${context.endpoint}: ${message}`,
1971
+ status: 0,
1972
+ endpoint: context.endpoint,
1973
+ method: context.method,
1974
+ cause: message,
1975
+ hint: "Check auth server URL, DNS, and network reachability."
1976
+ });
1977
+ return {
1978
+ ok: false,
1979
+ status: 0,
1980
+ data: null,
1981
+ error: details.message,
1982
+ errorDetails: details,
1983
+ raw: null
1984
+ };
1985
+ }
1986
+ }
1987
+ function executePostWithCompatibleInput(config, context, input, options) {
1988
+ const { payload, fetchOptions } = extractFetchOptions(input);
1989
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
1990
+ return callAuthEndpoint(config, context, payload ?? {}, void 0, mergedOptions);
1094
1991
  }
1095
- function quoteQualifiedIdentifier(identifier) {
1096
- return identifier.split(".").map((segment) => quoteIdentifierSegment(segment)).join(".");
1992
+ function executePostWithOptionalInput(config, context, input, options) {
1993
+ const { fetchOptions } = extractFetchOptions(input);
1994
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
1995
+ return callAuthEndpoint(config, context, {}, void 0, mergedOptions);
1097
1996
  }
1098
- function quoteSelectToken(token) {
1099
- if (token === "*") return token;
1100
- if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) {
1101
- return quoteQualifiedIdentifier(token);
1102
- }
1103
- const aliasMatch = ALIAS_PATTERN.exec(token);
1104
- if (!aliasMatch) {
1105
- return token;
1106
- }
1107
- const [, baseIdentifier, aliasIdentifier] = aliasMatch;
1108
- if (!COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) || !SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier)) {
1109
- return token;
1110
- }
1111
- return `${quoteQualifiedIdentifier(baseIdentifier)} AS ${quoteIdentifierSegment(aliasIdentifier)}`;
1997
+ function executeGetWithCompatibleInput(config, context, input, options) {
1998
+ const { fetchOptions } = extractFetchOptions(input);
1999
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
2000
+ return callAuthEndpoint(config, context, void 0, void 0, mergedOptions);
1112
2001
  }
1113
- function canAutoQuoteToken(token) {
1114
- if (token === "*") return true;
1115
- if (COMPOSITE_IDENTIFIER_PATTERN.test(token)) return true;
1116
- const aliasMatch = ALIAS_PATTERN.exec(token);
1117
- if (!aliasMatch) return false;
1118
- const [, baseIdentifier, aliasIdentifier] = aliasMatch;
1119
- return COMPOSITE_IDENTIFIER_PATTERN.test(baseIdentifier) && SIMPLE_IDENTIFIER_PATTERN.test(aliasIdentifier);
2002
+ function executeGetWithQueryCompatibleInput(config, context, input, options) {
2003
+ const { payload, fetchOptions } = extractFetchOptions(input);
2004
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
2005
+ const query = payload?.query;
2006
+ return callAuthEndpoint(
2007
+ config,
2008
+ context,
2009
+ void 0,
2010
+ query,
2011
+ mergedOptions
2012
+ );
1120
2013
  }
1121
- function splitTopLevelCommaSeparated(input) {
1122
- const parts = [];
1123
- let buffer = "";
1124
- let singleQuoted = false;
1125
- let doubleQuoted = false;
1126
- let depth = 0;
1127
- for (let index = 0; index < input.length; index += 1) {
1128
- const char = input[index];
1129
- const next = index + 1 < input.length ? input[index + 1] : "";
1130
- if (singleQuoted) {
1131
- buffer += char;
1132
- if (char === "'" && next === "'") {
1133
- buffer += next;
1134
- index += 1;
1135
- continue;
2014
+ function createAuthClient(config = {}) {
2015
+ const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
2016
+ const resolvedConfig = {
2017
+ ...config,
2018
+ baseUrl: normalizedBaseUrl
2019
+ };
2020
+ const request = (input, options) => {
2021
+ const method = input.method ?? (input.body !== void 0 ? "POST" : inferDefaultMethod(input.endpoint));
2022
+ const mergedOptions = mergeCallOptions(input.fetchOptions, options);
2023
+ return callAuthEndpoint(
2024
+ resolvedConfig,
2025
+ { endpoint: input.endpoint, method },
2026
+ input.body,
2027
+ input.query,
2028
+ mergedOptions
2029
+ );
2030
+ };
2031
+ const postGeneric = (endpoint, input, options) => {
2032
+ const { payload, fetchOptions } = extractFetchOptions(input);
2033
+ return request(
2034
+ {
2035
+ endpoint,
2036
+ method: "POST",
2037
+ body: payload ?? {},
2038
+ fetchOptions
2039
+ },
2040
+ options
2041
+ );
2042
+ };
2043
+ const getGeneric = (endpoint, input, options) => {
2044
+ const { fetchOptions } = extractFetchOptions(input);
2045
+ return request(
2046
+ {
2047
+ endpoint,
2048
+ method: "GET",
2049
+ fetchOptions
2050
+ },
2051
+ options
2052
+ );
2053
+ };
2054
+ const getWithQuery = (endpoint, input, options) => {
2055
+ const { payload, fetchOptions } = extractFetchOptions(input);
2056
+ const query = payload?.query;
2057
+ return request(
2058
+ {
2059
+ endpoint,
2060
+ method: "GET",
2061
+ query,
2062
+ fetchOptions
2063
+ },
2064
+ options
2065
+ );
2066
+ };
2067
+ const listUserEmailsWithFallback = async (input, options) => {
2068
+ const primary = await getWithQuery(
2069
+ "/email/list",
2070
+ input,
2071
+ options
2072
+ );
2073
+ if (primary.ok || primary.status !== 404 || primary.errorDetails?.code !== "HTTP_ERROR") {
2074
+ return primary;
2075
+ }
2076
+ return getWithQuery(
2077
+ "/email-list",
2078
+ input,
2079
+ options
2080
+ );
2081
+ };
2082
+ const healthWithFallback = async (input, options) => {
2083
+ const primary = await getGeneric("/health", input, options);
2084
+ if (primary.ok || primary.status !== 404 || primary.errorDetails?.code !== "HTTP_ERROR") {
2085
+ return primary;
2086
+ }
2087
+ const fallback = await getGeneric("/ok", input, options);
2088
+ if (!fallback.ok) {
2089
+ return {
2090
+ ...fallback,
2091
+ data: null
2092
+ };
2093
+ }
2094
+ const fallbackStatus = isRecord3(fallback.data) && typeof fallback.data.ok === "boolean" ? fallback.data.ok ? "ok" : "error" : "ok";
2095
+ return {
2096
+ ...fallback,
2097
+ data: {
2098
+ status: fallbackStatus
1136
2099
  }
1137
- if (char === "'") {
1138
- singleQuoted = false;
2100
+ };
2101
+ };
2102
+ const signOut = (input, options) => executePostWithOptionalInput(
2103
+ resolvedConfig,
2104
+ { endpoint: "/sign-out", method: "POST" },
2105
+ input,
2106
+ options
2107
+ );
2108
+ const revokeSessions = (input, options) => executePostWithOptionalInput(
2109
+ resolvedConfig,
2110
+ { endpoint: "/revoke-sessions", method: "POST" },
2111
+ input,
2112
+ options
2113
+ );
2114
+ const revokeOtherSessions = (input, options) => executePostWithOptionalInput(
2115
+ resolvedConfig,
2116
+ { endpoint: "/revoke-other-sessions", method: "POST" },
2117
+ input,
2118
+ options
2119
+ );
2120
+ const revokeSession = (input, options) => executePostWithCompatibleInput(
2121
+ resolvedConfig,
2122
+ { endpoint: "/revoke-session", method: "POST" },
2123
+ input,
2124
+ options
2125
+ );
2126
+ const deleteUser = (input, options) => {
2127
+ const { payload, fetchOptions } = extractFetchOptions(input);
2128
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
2129
+ return callAuthEndpoint(
2130
+ resolvedConfig,
2131
+ { endpoint: "/delete-user", method: "POST" },
2132
+ payload ?? {},
2133
+ void 0,
2134
+ mergedOptions
2135
+ );
2136
+ };
2137
+ const deleteUserCallback = (input, options) => {
2138
+ const { payload, fetchOptions } = extractFetchOptions(input);
2139
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
2140
+ const query = payload ?? {};
2141
+ return callAuthEndpoint(
2142
+ resolvedConfig,
2143
+ { endpoint: "/delete-user/callback", method: "GET" },
2144
+ void 0,
2145
+ {
2146
+ token: query.token,
2147
+ callbackURL: query.callbackURL
2148
+ },
2149
+ mergedOptions
2150
+ );
2151
+ };
2152
+ const resolveResetPasswordToken = (input, options) => {
2153
+ const { payload, fetchOptions } = extractFetchOptions(input);
2154
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
2155
+ const query = payload;
2156
+ const token = query?.token?.trim();
2157
+ if (!token) {
2158
+ throw new Error("resolveResetPasswordToken requires a non-empty token");
2159
+ }
2160
+ const endpoint = `/reset-password/${encodeURIComponent(token)}`;
2161
+ return callAuthEndpoint(
2162
+ resolvedConfig,
2163
+ { endpoint, method: "GET" },
2164
+ void 0,
2165
+ query?.callbackURL ? { callbackURL: query.callbackURL } : void 0,
2166
+ mergedOptions
2167
+ );
2168
+ };
2169
+ const organization = {
2170
+ create: (input, options) => executePostWithCompatibleInput(
2171
+ resolvedConfig,
2172
+ { endpoint: "/organization/create", method: "POST" },
2173
+ input,
2174
+ options
2175
+ ),
2176
+ update: (input, options) => executePostWithCompatibleInput(
2177
+ resolvedConfig,
2178
+ { endpoint: "/organization/update", method: "POST" },
2179
+ input,
2180
+ options
2181
+ ),
2182
+ delete: (input, options) => executePostWithCompatibleInput(
2183
+ resolvedConfig,
2184
+ { endpoint: "/organization/delete", method: "POST" },
2185
+ input,
2186
+ options
2187
+ ),
2188
+ setActive: (input, options) => executePostWithCompatibleInput(
2189
+ resolvedConfig,
2190
+ { endpoint: "/organization/set-active", method: "POST" },
2191
+ input,
2192
+ options
2193
+ ),
2194
+ list: (input, options) => getGeneric(
2195
+ "/organization/list",
2196
+ input,
2197
+ options
2198
+ ),
2199
+ getFull: (input, options) => executeGetWithQueryCompatibleInput(
2200
+ resolvedConfig,
2201
+ { endpoint: "/organization/get-full-organization", method: "GET" },
2202
+ input,
2203
+ options
2204
+ ),
2205
+ checkSlug: (input, options) => executePostWithCompatibleInput(
2206
+ resolvedConfig,
2207
+ { endpoint: "/organization/check-slug", method: "POST" },
2208
+ input,
2209
+ options
2210
+ ),
2211
+ leave: (input, options) => executePostWithCompatibleInput(
2212
+ resolvedConfig,
2213
+ { endpoint: "/organization/leave", method: "POST" },
2214
+ input,
2215
+ options
2216
+ ),
2217
+ listUserInvitations: (input, options) => executeGetWithQueryCompatibleInput(
2218
+ resolvedConfig,
2219
+ { endpoint: "/organization/list-user-invitations", method: "GET" },
2220
+ input,
2221
+ options
2222
+ ),
2223
+ hasPermission: (input, options) => postGeneric(
2224
+ "/organization/has-permission",
2225
+ input,
2226
+ options
2227
+ ),
2228
+ invitation: {
2229
+ cancel: (input, options) => executePostWithCompatibleInput(
2230
+ resolvedConfig,
2231
+ { endpoint: "/organization/cancel-invitation", method: "POST" },
2232
+ input,
2233
+ options
2234
+ ),
2235
+ accept: (input, options) => executePostWithCompatibleInput(
2236
+ resolvedConfig,
2237
+ { endpoint: "/organization/accept-invitation", method: "POST" },
2238
+ input,
2239
+ options
2240
+ ),
2241
+ get: (input, options) => executeGetWithQueryCompatibleInput(
2242
+ resolvedConfig,
2243
+ { endpoint: "/organization/get-invitation", method: "GET" },
2244
+ input,
2245
+ options
2246
+ ),
2247
+ reject: (input, options) => executePostWithCompatibleInput(
2248
+ resolvedConfig,
2249
+ { endpoint: "/organization/reject-invitation", method: "POST" },
2250
+ input,
2251
+ options
2252
+ ),
2253
+ list: (input, options) => executeGetWithQueryCompatibleInput(
2254
+ resolvedConfig,
2255
+ { endpoint: "/organization/list-invitations", method: "GET" },
2256
+ input,
2257
+ options
2258
+ )
2259
+ },
2260
+ member: {
2261
+ remove: (input, options) => executePostWithCompatibleInput(
2262
+ resolvedConfig,
2263
+ { endpoint: "/organization/remove-member", method: "POST" },
2264
+ input,
2265
+ options
2266
+ ),
2267
+ updateRole: (input, options) => executePostWithCompatibleInput(
2268
+ resolvedConfig,
2269
+ { endpoint: "/organization/update-member-role", method: "POST" },
2270
+ input,
2271
+ options
2272
+ ),
2273
+ invite: (input, options) => executePostWithCompatibleInput(
2274
+ resolvedConfig,
2275
+ { endpoint: "/organization/invite-member", method: "POST" },
2276
+ input,
2277
+ options
2278
+ ),
2279
+ getActive: (input, options) => executeGetWithCompatibleInput(
2280
+ resolvedConfig,
2281
+ { endpoint: "/organization/get-active-member", method: "GET" },
2282
+ input,
2283
+ options
2284
+ ),
2285
+ list: (input, options) => executeGetWithQueryCompatibleInput(
2286
+ resolvedConfig,
2287
+ { endpoint: "/organization/list-members", method: "GET" },
2288
+ input,
2289
+ options
2290
+ )
2291
+ }
2292
+ };
2293
+ const authResetPassword = Object.assign(
2294
+ (input, options) => executePostWithCompatibleInput(
2295
+ resolvedConfig,
2296
+ { endpoint: "/reset-password", method: "POST" },
2297
+ input,
2298
+ options
2299
+ ),
2300
+ {
2301
+ token: resolveResetPasswordToken
2302
+ }
2303
+ );
2304
+ const sessionRevokeBinding = (input, options) => {
2305
+ if (Array.isArray(input)) {
2306
+ if (input.length === 0) {
2307
+ throw new Error("session.revoke requires at least one session token");
1139
2308
  }
1140
- continue;
2309
+ if (input.length === 1) {
2310
+ return revokeSession(input[0], options);
2311
+ }
2312
+ return revokeSessions(void 0, options);
1141
2313
  }
1142
- if (doubleQuoted) {
1143
- buffer += char;
1144
- if (char === '"' && next === '"') {
1145
- buffer += next;
1146
- index += 1;
1147
- continue;
2314
+ const parsed = input;
2315
+ const tokens = Array.isArray(parsed.tokens) ? parsed.tokens.filter((token2) => token2.trim().length > 0) : void 0;
2316
+ if (tokens && tokens.length > 1) {
2317
+ return revokeSessions(
2318
+ parsed.fetchOptions ? { fetchOptions: parsed.fetchOptions } : void 0,
2319
+ options
2320
+ );
2321
+ }
2322
+ if (tokens && tokens.length === 1) {
2323
+ return revokeSession(
2324
+ { token: tokens[0], fetchOptions: parsed.fetchOptions },
2325
+ options
2326
+ );
2327
+ }
2328
+ const token = parsed.token?.trim();
2329
+ if (!token) {
2330
+ throw new Error("session.revoke requires a non-empty token or a non-empty token list");
2331
+ }
2332
+ return revokeSession(
2333
+ {
2334
+ token,
2335
+ fetchOptions: parsed.fetchOptions
2336
+ },
2337
+ options
2338
+ );
2339
+ };
2340
+ const adminUserSessionRevokeBinding = (input, options) => {
2341
+ const requireUserId = (userId) => {
2342
+ const trimmed = String(userId ?? "").trim();
2343
+ if (!trimmed) {
2344
+ throw new Error("admin.user.session.revoke requires a non-empty userId");
1148
2345
  }
1149
- if (char === '"') {
1150
- doubleQuoted = false;
2346
+ return trimmed;
2347
+ };
2348
+ const requireSinglePluralUserId = (sessions2) => {
2349
+ const uniqueUserIds = [...new Set(sessions2.map((session) => requireUserId(session.userId)))];
2350
+ if (uniqueUserIds.length !== 1) {
2351
+ throw new Error("admin.user.session.revoke requires the same userId across plural payloads");
1151
2352
  }
1152
- continue;
2353
+ return { userId: uniqueUserIds[0] };
2354
+ };
2355
+ if (Array.isArray(input)) {
2356
+ if (input.length === 0) {
2357
+ throw new Error("admin.user.session.revoke requires at least one payload item");
2358
+ }
2359
+ if (input.length === 1) {
2360
+ return postGeneric(
2361
+ "/admin/revoke-user-session",
2362
+ {
2363
+ ...input[0],
2364
+ userId: requireUserId(input[0].userId)
2365
+ },
2366
+ options
2367
+ );
2368
+ }
2369
+ return postGeneric(
2370
+ "/admin/revoke-user-sessions",
2371
+ requireSinglePluralUserId(input),
2372
+ options
2373
+ );
1153
2374
  }
1154
- if (char === "'") {
1155
- singleQuoted = true;
1156
- buffer += char;
1157
- continue;
2375
+ const parsed = input;
2376
+ const sessions = parsed.sessions;
2377
+ if (sessions && sessions.length === 0) {
2378
+ throw new Error("admin.user.session.revoke requires at least one payload item");
1158
2379
  }
1159
- if (char === '"') {
1160
- doubleQuoted = true;
1161
- buffer += char;
1162
- continue;
2380
+ if (sessions && sessions.length === 1) {
2381
+ return postGeneric(
2382
+ "/admin/revoke-user-session",
2383
+ {
2384
+ ...sessions[0],
2385
+ userId: requireUserId(sessions[0].userId),
2386
+ fetchOptions: parsed.fetchOptions
2387
+ },
2388
+ options
2389
+ );
1163
2390
  }
1164
- if (char === "(") {
1165
- depth += 1;
1166
- buffer += char;
1167
- continue;
2391
+ if (sessions && sessions.length > 1) {
2392
+ return postGeneric(
2393
+ "/admin/revoke-user-sessions",
2394
+ {
2395
+ ...requireSinglePluralUserId(sessions),
2396
+ fetchOptions: parsed.fetchOptions
2397
+ },
2398
+ options
2399
+ );
1168
2400
  }
1169
- if (char === ")") {
1170
- depth -= 1;
1171
- if (depth < 0) return null;
1172
- buffer += char;
1173
- continue;
2401
+ const normalizedUserId = requireUserId(parsed.userId);
2402
+ if (!parsed.sessionToken) {
2403
+ return postGeneric(
2404
+ "/admin/revoke-user-sessions",
2405
+ {
2406
+ userId: normalizedUserId,
2407
+ fetchOptions: parsed.fetchOptions
2408
+ },
2409
+ options
2410
+ );
1174
2411
  }
1175
- if (char === "," && depth === 0) {
1176
- parts.push(buffer.trim());
1177
- buffer = "";
1178
- continue;
2412
+ return postGeneric(
2413
+ "/admin/revoke-user-session",
2414
+ {
2415
+ ...parsed,
2416
+ userId: normalizedUserId
2417
+ },
2418
+ options
2419
+ );
2420
+ };
2421
+ const auth = {
2422
+ getSession: (input, options) => getGeneric("/get-session", input, options),
2423
+ signOut,
2424
+ forgetPassword: (input, options) => postGeneric("/forget-password", input, options),
2425
+ resetPassword: authResetPassword,
2426
+ setPassword: (input, options) => postGeneric("/set-password", input, options),
2427
+ verifyEmail: (input, options) => {
2428
+ const queryInput = {
2429
+ query: {
2430
+ token: input.token,
2431
+ callbackURL: input.callbackURL
2432
+ },
2433
+ fetchOptions: input.fetchOptions
2434
+ };
2435
+ return getWithQuery(
2436
+ "/verify-email",
2437
+ queryInput,
2438
+ options
2439
+ );
2440
+ },
2441
+ sendVerificationEmail: (input, options) => postGeneric("/send-verification-email", input, options),
2442
+ changeEmail: (input, options) => postGeneric("/change-email", input, options),
2443
+ changeEmailVerify: (input, options) => getWithQuery("/change-email/verify", input, options),
2444
+ deleteUserVerify: (input, options) => getWithQuery("/delete-user/verify", input, options),
2445
+ changePassword: (input, options) => postGeneric("/change-password", input, options),
2446
+ user: {
2447
+ update: (input, options) => postGeneric("/update-user", input, options),
2448
+ delete: (input, options) => postGeneric("/delete-user", input, options),
2449
+ email: {
2450
+ list: listUserEmailsWithFallback
2451
+ }
2452
+ },
2453
+ session: {
2454
+ list: (input, options) => getGeneric("/list-sessions", input, options),
2455
+ revoke: sessionRevokeBinding,
2456
+ revokeOther: revokeOtherSessions
2457
+ },
2458
+ social: {
2459
+ link: (input, options) => postGeneric("/link-social", input, options)
2460
+ },
2461
+ account: {
2462
+ list: (input, options) => getGeneric("/list-accounts", input, options),
2463
+ unlink: (input, options) => postGeneric("/unlink-account", input, options)
2464
+ },
2465
+ deleteUser: {
2466
+ callback: deleteUserCallback
2467
+ },
2468
+ refreshToken: (input, options) => postGeneric("/refresh-token", input, options),
2469
+ getAccessToken: (input, options) => postGeneric("/get-access-token", input, options),
2470
+ health: healthWithFallback,
2471
+ ok: (input, options) => getGeneric("/ok", input, options),
2472
+ error: (input, options) => getGeneric("/error", input, options),
2473
+ twoFactor: {
2474
+ getTotpUri: (input, options) => postGeneric("/two-factor/get-totp-uri", input, options),
2475
+ verifyTotp: (input, options) => postGeneric("/two-factor/verify-totp", input, options),
2476
+ sendOtp: (input, options) => postGeneric("/two-factor/send-otp", input, options),
2477
+ verifyOtp: (input, options) => postGeneric("/two-factor/verify-otp", input, options),
2478
+ verifyBackupCode: (input, options) => postGeneric("/two-factor/verify-backup-code", input, options),
2479
+ generateBackupCodes: (input, options) => executePostWithCompatibleInput(
2480
+ resolvedConfig,
2481
+ { endpoint: "/two-factor/generate-backup-codes", method: "POST" },
2482
+ input,
2483
+ options
2484
+ ),
2485
+ enable: (input, options) => postGeneric("/two-factor/enable", input, options),
2486
+ disable: (input, options) => postGeneric("/two-factor/disable", input, options)
2487
+ },
2488
+ passkey: {
2489
+ generateRegisterOptions: (input, options) => getGeneric("/passkey/generate-register-options", input, options),
2490
+ generateAuthenticateOptions: (input, options) => postGeneric("/passkey/generate-authenticate-options", input, options),
2491
+ verifyRegistration: (input, options) => postGeneric("/passkey/verify-registration", input, options),
2492
+ verifyAuthentication: (input, options) => postGeneric("/passkey/verify-authentication", input, options),
2493
+ listUserPasskeys: (input, options) => getGeneric("/passkey/list-user-passkeys", input, options),
2494
+ deletePasskey: (input, options) => postGeneric("/passkey/delete-passkey", input, options),
2495
+ updatePasskey: (input, options) => postGeneric("/passkey/update-passkey", input, options),
2496
+ getRelatedOrigins: (input, options) => getGeneric("/.well-known/webauthn", input, options)
2497
+ },
2498
+ admin: {
2499
+ role: {
2500
+ set: (input, options) => postGeneric("/admin/set-role", input, options)
2501
+ },
2502
+ user: {
2503
+ list: (input, options) => getWithQuery("/admin/list-users", input, options),
2504
+ create: (input, options) => postGeneric("/admin/create-user", input, options),
2505
+ unban: (input, options) => postGeneric("/admin/unban-user", input, options),
2506
+ ban: (input, options) => postGeneric("/admin/ban-user", input, options),
2507
+ impersonate: (input, options) => postGeneric("/admin/impersonate-user", input, options),
2508
+ stopImpersonating: (input, options) => postGeneric("/admin/stop-impersonating", input, options),
2509
+ remove: (input, options) => postGeneric("/admin/remove-user", input, options),
2510
+ setPassword: (input, options) => postGeneric("/admin/set-user-password", input, options),
2511
+ session: {
2512
+ list: (input, options) => postGeneric("/admin/list-user-sessions", input, options),
2513
+ revoke: adminUserSessionRevokeBinding
2514
+ }
2515
+ },
2516
+ hasPermission: (input, options) => postGeneric("/admin/has-permission", input, options),
2517
+ apiKey: {
2518
+ create: (input, options) => postGeneric("/admin/api-key/create", input, options)
2519
+ },
2520
+ athenaClient: {
2521
+ create: (input, options) => postGeneric("/admin/athena-client/create", input, options),
2522
+ list: (input, options) => getWithQuery("/admin/athena-client/list", input, options)
2523
+ },
2524
+ auditLog: {
2525
+ list: (input, options) => getWithQuery("/admin/audit-log/list", input, options)
2526
+ },
2527
+ email: {
2528
+ list: (input, options) => getWithQuery("/admin/email/list", input, options),
2529
+ get: (input, options) => getWithQuery("/admin/email/get", input, options),
2530
+ create: (input, options) => postGeneric("/admin/email/create", input, options),
2531
+ update: (input, options) => postGeneric("/admin/email/update", input, options),
2532
+ delete: (input, options) => postGeneric("/admin/email/delete", input, options),
2533
+ failure: {
2534
+ list: (input, options) => getWithQuery("/admin/email-failure/list", input, options),
2535
+ get: (input, options) => getWithQuery("/admin/email-failure/get", input, options),
2536
+ create: (input, options) => postGeneric("/admin/email-failure/create", input, options),
2537
+ update: (input, options) => postGeneric("/admin/email-failure/update", input, options),
2538
+ delete: (input, options) => postGeneric("/admin/email-failure/delete", input, options)
2539
+ },
2540
+ template: {
2541
+ list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
2542
+ get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
2543
+ create: (input, options) => postGeneric("/admin/email-template/create", input, options),
2544
+ update: (input, options) => postGeneric("/admin/email-template/update", input, options),
2545
+ delete: (input, options) => postGeneric("/admin/email-template/delete", input, options)
2546
+ }
2547
+ },
2548
+ emailTemplate: {
2549
+ get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
2550
+ create: (input, options) => postGeneric("/admin/email-template/create", input, options),
2551
+ delete: (input, options) => postGeneric("/admin/email-template/delete", input, options),
2552
+ list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
2553
+ update: (input, options) => postGeneric("/admin/email-template/update", input, options)
2554
+ }
2555
+ },
2556
+ apiKey: {
2557
+ create: (input, options) => postGeneric("/api-key/create", input, options),
2558
+ get: (input, options) => getWithQuery("/api-key/get", input, options),
2559
+ update: (input, options) => postGeneric("/api-key/update", input, options),
2560
+ delete: (input, options) => postGeneric("/api-key/delete", input, options),
2561
+ list: (input, options) => getWithQuery("/api-key/list", input, options),
2562
+ verify: (input, options) => postGeneric("/api-key/verify", input, options),
2563
+ deleteAllExpired: (input, options) => executePostWithOptionalInput(
2564
+ resolvedConfig,
2565
+ { endpoint: "/api-key/delete-all-expired-api-keys", method: "POST" },
2566
+ input,
2567
+ options
2568
+ )
2569
+ },
2570
+ signIn: {
2571
+ email: (input, options) => postGeneric("/sign-in/email", input, options),
2572
+ username: (input, options) => postGeneric("/sign-in/username", input, options),
2573
+ social: (input, options) => postGeneric("/sign-in/social", input, options)
2574
+ },
2575
+ signUp: {
2576
+ email: (input, options) => postGeneric("/sign-up/email", input, options)
2577
+ },
2578
+ organization,
2579
+ callback: {
2580
+ provider: (input, options) => {
2581
+ const { payload, fetchOptions } = extractFetchOptions(input);
2582
+ const parsed = payload;
2583
+ const provider = String(parsed?.provider ?? "").trim();
2584
+ if (!provider) {
2585
+ throw new Error("callback.provider requires a non-empty provider value");
2586
+ }
2587
+ const code = String(parsed?.code ?? "").trim();
2588
+ const state = String(parsed?.state ?? "").trim();
2589
+ if (!code || !state) {
2590
+ throw new Error("callback.provider requires non-empty code and state values");
2591
+ }
2592
+ const endpoint = `/callback/${encodeURIComponent(provider)}`;
2593
+ return request({
2594
+ endpoint,
2595
+ method: "GET",
2596
+ query: {
2597
+ code,
2598
+ state
2599
+ },
2600
+ fetchOptions
2601
+ }, options);
2602
+ }
1179
2603
  }
1180
- buffer += char;
1181
- }
1182
- if (singleQuoted || doubleQuoted || depth !== 0) {
1183
- return null;
1184
- }
1185
- if (buffer.trim().length > 0) {
1186
- parts.push(buffer.trim());
1187
- }
1188
- return parts;
2604
+ };
2605
+ return {
2606
+ baseUrl: normalizedBaseUrl,
2607
+ request,
2608
+ signIn: {
2609
+ email: (input, options) => executePostWithCompatibleInput(
2610
+ resolvedConfig,
2611
+ { endpoint: "/sign-in/email", method: "POST" },
2612
+ input,
2613
+ options
2614
+ ),
2615
+ username: (input, options) => executePostWithCompatibleInput(
2616
+ resolvedConfig,
2617
+ { endpoint: "/sign-in/username", method: "POST" },
2618
+ input,
2619
+ options
2620
+ ),
2621
+ social: (input, options) => executePostWithCompatibleInput(
2622
+ resolvedConfig,
2623
+ { endpoint: "/sign-in/social", method: "POST" },
2624
+ input,
2625
+ options
2626
+ )
2627
+ },
2628
+ signUp: {
2629
+ email: (input, options) => executePostWithCompatibleInput(
2630
+ resolvedConfig,
2631
+ { endpoint: "/sign-up/email", method: "POST" },
2632
+ input,
2633
+ options
2634
+ )
2635
+ },
2636
+ signOut,
2637
+ logout: signOut,
2638
+ getSession: (input, options) => executeGetWithCompatibleInput(
2639
+ resolvedConfig,
2640
+ { endpoint: "/get-session", method: "GET" },
2641
+ input,
2642
+ options
2643
+ ),
2644
+ listSessions: (input, options) => executeGetWithCompatibleInput(
2645
+ resolvedConfig,
2646
+ { endpoint: "/list-sessions", method: "GET" },
2647
+ input,
2648
+ options
2649
+ ),
2650
+ revokeSession,
2651
+ clearSession: revokeSession,
2652
+ revokeSessions,
2653
+ clearSessions: revokeSessions,
2654
+ revokeOtherSessions,
2655
+ clearOtherSessions: revokeOtherSessions,
2656
+ forgetPassword: (input, options) => executePostWithCompatibleInput(
2657
+ resolvedConfig,
2658
+ { endpoint: "/forget-password", method: "POST" },
2659
+ input,
2660
+ options
2661
+ ),
2662
+ resetPassword: (input, options) => executePostWithCompatibleInput(
2663
+ resolvedConfig,
2664
+ { endpoint: "/reset-password", method: "POST" },
2665
+ input,
2666
+ options
2667
+ ),
2668
+ resolveResetPasswordToken,
2669
+ verifyEmail: (input, options) => {
2670
+ const { payload, fetchOptions } = extractFetchOptions(input);
2671
+ const mergedOptions = mergeCallOptions(fetchOptions, options);
2672
+ const query = payload;
2673
+ return callAuthEndpoint(
2674
+ resolvedConfig,
2675
+ { endpoint: "/verify-email", method: "GET" },
2676
+ void 0,
2677
+ query ? {
2678
+ token: query.token,
2679
+ callbackURL: query.callbackURL
2680
+ } : void 0,
2681
+ mergedOptions
2682
+ );
2683
+ },
2684
+ sendVerificationEmail: (input, options) => executePostWithCompatibleInput(
2685
+ resolvedConfig,
2686
+ { endpoint: "/send-verification-email", method: "POST" },
2687
+ input,
2688
+ options
2689
+ ),
2690
+ changeEmail: (input, options) => executePostWithCompatibleInput(
2691
+ resolvedConfig,
2692
+ { endpoint: "/change-email", method: "POST" },
2693
+ input,
2694
+ options
2695
+ ),
2696
+ changePassword: (input, options) => executePostWithCompatibleInput(
2697
+ resolvedConfig,
2698
+ { endpoint: "/change-password", method: "POST" },
2699
+ input,
2700
+ options
2701
+ ),
2702
+ updateUser: (input, options) => executePostWithCompatibleInput(
2703
+ resolvedConfig,
2704
+ { endpoint: "/update-user", method: "POST" },
2705
+ input,
2706
+ options
2707
+ ),
2708
+ deleteUser,
2709
+ deleteUserCallback,
2710
+ linkSocial: (input, options) => executePostWithCompatibleInput(
2711
+ resolvedConfig,
2712
+ { endpoint: "/link-social", method: "POST" },
2713
+ input,
2714
+ options
2715
+ ),
2716
+ listAccounts: (input, options) => executeGetWithCompatibleInput(
2717
+ resolvedConfig,
2718
+ { endpoint: "/list-accounts", method: "GET" },
2719
+ input,
2720
+ options
2721
+ ),
2722
+ unlinkAccount: (input, options) => executePostWithCompatibleInput(
2723
+ resolvedConfig,
2724
+ { endpoint: "/unlink-account", method: "POST" },
2725
+ input,
2726
+ options
2727
+ ),
2728
+ refreshToken: (input, options) => executePostWithCompatibleInput(
2729
+ resolvedConfig,
2730
+ { endpoint: "/refresh-token", method: "POST" },
2731
+ input,
2732
+ options
2733
+ ),
2734
+ getAccessToken: (input, options) => executePostWithCompatibleInput(
2735
+ resolvedConfig,
2736
+ { endpoint: "/get-access-token", method: "POST" },
2737
+ input,
2738
+ options
2739
+ ),
2740
+ organization,
2741
+ auth
2742
+ };
1189
2743
  }
1190
- function quoteSelectColumnsExpression(columns) {
1191
- const trimmed = columns.trim();
1192
- if (!trimmed || trimmed === "*") return trimmed || "*";
1193
- const tokens = splitTopLevelCommaSeparated(trimmed);
1194
- if (!tokens || tokens.length === 0) {
1195
- return trimmed;
1196
- }
1197
- if (!tokens.every(canAutoQuoteToken)) {
1198
- return trimmed;
1199
- }
1200
- return tokens.map(quoteSelectToken).join(", ");
2744
+
2745
+ // src/db/module.ts
2746
+ function createDbModule(input) {
2747
+ const db = {
2748
+ from(table) {
2749
+ return input.from(table);
2750
+ },
2751
+ select(table, columns, options) {
2752
+ return input.from(table).select(columns, options);
2753
+ },
2754
+ insert(table, values, options) {
2755
+ return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
2756
+ },
2757
+ upsert(table, values, options) {
2758
+ return Array.isArray(values) ? input.from(table).upsert(values, options) : input.from(table).upsert(values, options);
2759
+ },
2760
+ update(table, values, options) {
2761
+ return input.from(table).update(values, options);
2762
+ },
2763
+ delete(table, options) {
2764
+ return input.from(table).delete(options);
2765
+ },
2766
+ rpc(fn, args, options) {
2767
+ return input.rpc(fn, args, options);
2768
+ },
2769
+ query(query, options) {
2770
+ return input.query(query, options);
2771
+ }
2772
+ };
2773
+ return db;
1201
2774
  }
1202
2775
 
1203
2776
  // src/client.ts
1204
2777
  var DEFAULT_COLUMNS = "*";
1205
2778
  var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
1206
2779
  var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
2780
+ var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
1207
2781
  function formatResult(response) {
1208
2782
  const result = {
1209
2783
  data: response.data ?? null,
@@ -1217,6 +2791,28 @@ function formatResult(response) {
1217
2791
  }
1218
2792
  return result;
1219
2793
  }
2794
+ function attachNormalizedError(result, normalizedError) {
2795
+ Object.defineProperty(result, ATHENA_NORMALIZED_ERROR_KEY, {
2796
+ value: normalizedError,
2797
+ enumerable: false,
2798
+ configurable: true,
2799
+ writable: false
2800
+ });
2801
+ }
2802
+ function createResultFormatter(experimental) {
2803
+ if (!experimental?.enableErrorNormalization) {
2804
+ return formatResult;
2805
+ }
2806
+ return (response, context) => {
2807
+ const result = formatResult(response);
2808
+ if (result.error == null) {
2809
+ return result;
2810
+ }
2811
+ const normalizedError = normalizeAthenaError(result, context);
2812
+ attachNormalizedError(result, normalizedError);
2813
+ return result;
2814
+ };
2815
+ }
1220
2816
  function toSingleResult(response) {
1221
2817
  const payload = response.data;
1222
2818
  const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
@@ -1591,7 +3187,7 @@ function createRpcFilterMethods(filters, self) {
1591
3187
  }
1592
3188
  };
1593
3189
  }
1594
- function createRpcBuilder(functionName, args, baseOptions, client) {
3190
+ function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult) {
1595
3191
  const state = {
1596
3192
  filters: []
1597
3193
  };
@@ -1613,7 +3209,7 @@ function createRpcBuilder(functionName, args, baseOptions, client) {
1613
3209
  order: state.order
1614
3210
  };
1615
3211
  const response = await client.rpcGateway(payload, mergedOptions);
1616
- return formatResult(response);
3212
+ return formatGatewayResult(response, { operation: "rpc" });
1617
3213
  };
1618
3214
  const run = (columns, options) => {
1619
3215
  const payloadColumns = columns ?? selectedColumns;
@@ -1667,7 +3263,7 @@ function createRpcBuilder(functionName, args, baseOptions, client) {
1667
3263
  });
1668
3264
  return builder;
1669
3265
  }
1670
- function createTableBuilder(tableName, client) {
3266
+ function createTableBuilder(tableName, client, formatGatewayResult) {
1671
3267
  const state = {
1672
3268
  conditions: []
1673
3269
  };
@@ -1724,7 +3320,7 @@ function createTableBuilder(tableName, client) {
1724
3320
  });
1725
3321
  if (query) {
1726
3322
  const queryResponse = await client.queryGateway({ query }, options);
1727
- return formatResult(queryResponse);
3323
+ return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
1728
3324
  }
1729
3325
  }
1730
3326
  const payload = {
@@ -1742,7 +3338,7 @@ function createTableBuilder(tableName, client) {
1742
3338
  head: options?.head
1743
3339
  };
1744
3340
  const response = await client.fetchGateway(payload, options);
1745
- return formatResult(response);
3341
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
1746
3342
  };
1747
3343
  const createSelectChain = (columns, options) => {
1748
3344
  const chain = {};
@@ -1797,7 +3393,7 @@ function createTableBuilder(tableName, client) {
1797
3393
  payload.default_to_null = mergedOptions.defaultToNull;
1798
3394
  }
1799
3395
  const response = await client.insertGateway(payload, mergedOptions);
1800
- return formatResult(response);
3396
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
1801
3397
  };
1802
3398
  return createMutationQuery(executeInsertMany);
1803
3399
  }
@@ -1815,7 +3411,7 @@ function createTableBuilder(tableName, client) {
1815
3411
  payload.default_to_null = mergedOptions.defaultToNull;
1816
3412
  }
1817
3413
  const response = await client.insertGateway(payload, mergedOptions);
1818
- return formatResult(response);
3414
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
1819
3415
  };
1820
3416
  return createMutationQuery(executeInsertOne);
1821
3417
  },
@@ -1837,7 +3433,7 @@ function createTableBuilder(tableName, client) {
1837
3433
  payload.default_to_null = mergedOptions.defaultToNull;
1838
3434
  }
1839
3435
  const response = await client.insertGateway(payload, mergedOptions);
1840
- return formatResult(response);
3436
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
1841
3437
  };
1842
3438
  return createMutationQuery(executeUpsertMany);
1843
3439
  }
@@ -1857,7 +3453,7 @@ function createTableBuilder(tableName, client) {
1857
3453
  payload.default_to_null = mergedOptions.defaultToNull;
1858
3454
  }
1859
3455
  const response = await client.insertGateway(payload, mergedOptions);
1860
- return formatResult(response);
3456
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
1861
3457
  };
1862
3458
  return createMutationQuery(executeUpsertOne);
1863
3459
  },
@@ -1878,7 +3474,7 @@ function createTableBuilder(tableName, client) {
1878
3474
  if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
1879
3475
  if (columns) payload.columns = columns;
1880
3476
  const response = await client.updateGateway(payload, mergedOptions);
1881
- return formatResult(response);
3477
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "update" });
1882
3478
  };
1883
3479
  const mutation = createMutationQuery(executeUpdate, null);
1884
3480
  const updateChain = {};
@@ -1906,7 +3502,7 @@ function createTableBuilder(tableName, client) {
1906
3502
  if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
1907
3503
  if (columns) payload.columns = columns;
1908
3504
  const response = await client.deleteGateway(payload, mergedOptions);
1909
- return formatResult(response);
3505
+ return formatGatewayResult(response, { table: resolvedTableName, operation: "delete" });
1910
3506
  };
1911
3507
  return createMutationQuery(executeDelete, null);
1912
3508
  },
@@ -1920,14 +3516,14 @@ function createTableBuilder(tableName, client) {
1920
3516
  });
1921
3517
  return builder;
1922
3518
  }
1923
- function createQueryBuilder(client) {
3519
+ function createQueryBuilder(client, formatGatewayResult) {
1924
3520
  return async function query(query, options) {
1925
3521
  const normalizedQuery = query.trim();
1926
3522
  if (!normalizedQuery) {
1927
3523
  throw new Error("query requires a non-empty string");
1928
3524
  }
1929
3525
  const response = await client.queryGateway({ query: normalizedQuery }, options);
1930
- return formatResult(response);
3526
+ return formatGatewayResult(response, { operation: "query" });
1931
3527
  };
1932
3528
  }
1933
3529
  function createClientFromConfig(config) {
@@ -1938,23 +3534,30 @@ function createClientFromConfig(config) {
1938
3534
  backend: config.backend,
1939
3535
  headers: config.headers
1940
3536
  });
3537
+ const formatGatewayResult = createResultFormatter(config.experimental);
3538
+ const auth = createAuthClient(config.auth);
3539
+ const from = (table) => createTableBuilder(table, gateway, formatGatewayResult);
3540
+ const rpc = (fn, args, options) => {
3541
+ const normalizedFn = fn.trim();
3542
+ if (!normalizedFn) {
3543
+ throw new Error("rpc requires a function name");
3544
+ }
3545
+ return createRpcBuilder(
3546
+ normalizedFn,
3547
+ args,
3548
+ options,
3549
+ gateway,
3550
+ formatGatewayResult
3551
+ );
3552
+ };
3553
+ const query = createQueryBuilder(gateway, formatGatewayResult);
3554
+ const db = createDbModule({ from, rpc, query });
1941
3555
  return {
1942
- from(table) {
1943
- return createTableBuilder(table, gateway);
1944
- },
1945
- rpc(fn, args, options) {
1946
- const normalizedFn = fn.trim();
1947
- if (!normalizedFn) {
1948
- throw new Error("rpc requires a function name");
1949
- }
1950
- return createRpcBuilder(
1951
- normalizedFn,
1952
- args,
1953
- options,
1954
- gateway
1955
- );
1956
- },
1957
- query: createQueryBuilder(gateway)
3556
+ from,
3557
+ db,
3558
+ rpc,
3559
+ query,
3560
+ auth: auth.auth
1958
3561
  };
1959
3562
  }
1960
3563
  var DEFAULT_BACKEND = { type: "athena" };
@@ -1962,73 +3565,16 @@ function toBackendConfig(b) {
1962
3565
  if (!b) return DEFAULT_BACKEND;
1963
3566
  return typeof b === "string" ? { type: b } : b;
1964
3567
  }
1965
- var AthenaClientBuilderImpl = class {
1966
- baseUrl;
1967
- apiKey;
1968
- backendConfig = DEFAULT_BACKEND;
1969
- clientName;
1970
- defaultHeaders;
1971
- isHealthTrackingEnabled = false;
1972
- url(url) {
1973
- this.baseUrl = url;
1974
- return this;
1975
- }
1976
- key(apiKey) {
1977
- this.apiKey = apiKey;
1978
- return this;
1979
- }
1980
- backend(backend) {
1981
- this.backendConfig = toBackendConfig(backend);
1982
- return this;
1983
- }
1984
- client(clientName) {
1985
- this.clientName = clientName;
1986
- return this;
1987
- }
1988
- headers(headers) {
1989
- this.defaultHeaders = headers;
1990
- return this;
1991
- }
1992
- healthTracking(enabled) {
1993
- this.isHealthTrackingEnabled = enabled;
1994
- return this;
1995
- }
1996
- build() {
1997
- if (!this.baseUrl || !this.apiKey) {
1998
- throw new Error("AthenaClient requires url and key; call .url() and .key() before .build()");
1999
- }
2000
- return createClientFromConfig({
2001
- baseUrl: this.baseUrl,
2002
- apiKey: this.apiKey,
2003
- client: this.clientName,
2004
- backend: this.backendConfig,
2005
- headers: this.defaultHeaders,
2006
- healthTracking: this.isHealthTrackingEnabled
2007
- });
2008
- }
2009
- };
2010
- var AthenaClient = class _AthenaClient {
2011
- /** Create a fluent builder for a strongly-typed Athena SDK client. */
2012
- static builder() {
2013
- return new AthenaClientBuilderImpl();
2014
- }
2015
- /** Build a client from process environment variables. */
2016
- static fromEnvironment() {
2017
- const url = process.env.ATHENA_URL ?? process.env.ATHENA_GATEWAY_URL;
2018
- const key = process.env.ATHENA_API_KEY ?? process.env.ATHENA_GATEWAY_API_KEY;
2019
- if (!url || !key) {
2020
- throw new Error(
2021
- "ATHENA_URL and ATHENA_API_KEY (or ATHENA_GATEWAY_URL and ATHENA_GATEWAY_API_KEY) are required"
2022
- );
2023
- }
2024
- return _AthenaClient.builder().url(url).key(key).build();
2025
- }
2026
- };
2027
3568
  function createClient(url, apiKey, options) {
2028
- const b = AthenaClient.builder().url(url).key(apiKey).backend(toBackendConfig(options?.backend));
2029
- if (options?.client) b.client(options.client);
2030
- if (options?.headers && Object.keys(options.headers).length > 0) b.headers(options.headers);
2031
- return b.build();
3569
+ return createClientFromConfig({
3570
+ baseUrl: url,
3571
+ apiKey,
3572
+ client: options?.client,
3573
+ backend: toBackendConfig(options?.backend),
3574
+ headers: options?.headers,
3575
+ auth: options?.auth,
3576
+ experimental: options?.experimental
3577
+ });
2032
3578
  }
2033
3579
 
2034
3580
  // src/schema/postgres-introspection-core.ts
@@ -2378,6 +3924,23 @@ var PostgresCatalogSnapshotAssembler = class {
2378
3924
  table.relations[key] = relation;
2379
3925
  }
2380
3926
  };
3927
+
3928
+ // src/schema/postgres-provider.ts
3929
+ var pgPoolConstructorPromise;
3930
+ async function loadPgPoolConstructor() {
3931
+ if (!pgPoolConstructorPromise) {
3932
+ pgPoolConstructorPromise = import('pg').then((module) => {
3933
+ const poolConstructor = module.Pool ?? module.default?.Pool;
3934
+ if (!poolConstructor) {
3935
+ throw new Error(
3936
+ '@xylex-group/athena: Unable to load the PostgreSQL driver. Ensure "pg" is installed and this API runs in a Node.js server runtime.'
3937
+ );
3938
+ }
3939
+ return poolConstructor;
3940
+ });
3941
+ }
3942
+ return pgPoolConstructorPromise;
3943
+ }
2381
3944
  var PgCatalogClient = class {
2382
3945
  constructor(pool) {
2383
3946
  this.pool = pool;
@@ -2417,7 +3980,8 @@ var PostgresIntrospectionProvider = class {
2417
3980
  }
2418
3981
  async inspect(options) {
2419
3982
  const schemas = options?.schemas && options.schemas.length > 0 ? normalizePostgresCatalogSchemas(options.schemas) : this.schemas;
2420
- const pool = new pg.Pool({
3983
+ const PoolConstructor = await loadPgPoolConstructor();
3984
+ const pool = new PoolConstructor({
2421
3985
  connectionString: this.connectionString
2422
3986
  });
2423
3987
  const catalogClient = new PgCatalogClient(pool);