@xylex-group/athena 2.0.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.
- package/README.md +47 -26
- package/dist/browser.cjs +3319 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.cts +25 -0
- package/dist/browser.d.ts +25 -0
- package/dist/browser.js +3276 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli/index.cjs +599 -119
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +3 -2
- package/dist/cli/index.d.ts +3 -2
- package/dist/cli/index.js +600 -120
- package/dist/cli/index.js.map +1 -1
- package/dist/client-BX0NQqOn.d.ts +435 -0
- package/dist/client-dpAp-NZK.d.cts +435 -0
- package/dist/cookies.cjs +890 -0
- package/dist/cookies.cjs.map +1 -0
- package/dist/cookies.d.cts +174 -0
- package/dist/cookies.d.ts +174 -0
- package/dist/cookies.js +869 -0
- package/dist/cookies.js.map +1 -0
- package/dist/index.cjs +1378 -1023
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -408
- package/dist/index.d.ts +8 -408
- package/dist/index.js +1379 -1024
- package/dist/index.js.map +1 -1
- package/dist/{model-form-CVOtC8jq.d.ts → model-form-2hqmoOUX.d.ts} +2 -2
- package/dist/{model-form-hXkvHS_3.d.cts → model-form-Cy-zaO0u.d.cts} +2 -2
- package/dist/pipeline-BOPszLsL.d.ts +8 -0
- package/dist/pipeline-E3FDbs4W.d.cts +8 -0
- package/dist/react.d.cts +4 -4
- package/dist/react.d.ts +4 -4
- package/dist/{types-BnzoaNRC.d.cts → types-BaBzjwXr.d.cts} +1 -1
- package/dist/{types-BnzoaNRC.d.ts → types-BaBzjwXr.d.ts} +1 -1
- package/dist/{pipeline-CQgV-Yfo.d.ts → types-CeBPrnGj.d.ts} +2 -7
- package/dist/{pipeline-C-cN0ACi.d.cts → types-CpqL-pZx.d.cts} +2 -7
- package/package.json +21 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { mkdir, writeFile } from 'fs/promises';
|
|
2
2
|
import { resolve, dirname, posix } from 'path';
|
|
3
|
-
import { existsSync } from 'fs';
|
|
3
|
+
import { existsSync, readFileSync } from 'fs';
|
|
4
4
|
import { pathToFileURL } from 'url';
|
|
5
|
-
import { Pool } from 'pg';
|
|
6
5
|
|
|
7
6
|
// src/generator/pipeline.ts
|
|
8
7
|
|
|
@@ -147,9 +146,13 @@ function resolvePlaceholderMap(baseTokens, outputConfig) {
|
|
|
147
146
|
const resolved = {
|
|
148
147
|
...baseTokens
|
|
149
148
|
};
|
|
149
|
+
const reservedTokenKeys = new Set(Object.keys(baseTokens));
|
|
150
150
|
const entries = Object.entries(outputConfig.placeholderMap ?? {});
|
|
151
151
|
for (let index = 0; index < entries.length; index += 1) {
|
|
152
152
|
const [key, value] = entries[index];
|
|
153
|
+
if (reservedTokenKeys.has(key)) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
153
156
|
let current = value;
|
|
154
157
|
for (let depth = 0; depth < 8; depth += 1) {
|
|
155
158
|
const next = renderTemplate(current, resolved);
|
|
@@ -346,8 +349,30 @@ var AthenaGatewayError = class _AthenaGatewayError extends Error {
|
|
|
346
349
|
});
|
|
347
350
|
}
|
|
348
351
|
};
|
|
352
|
+
function isAthenaGatewayError(error) {
|
|
353
|
+
return error instanceof AthenaGatewayError;
|
|
354
|
+
}
|
|
349
355
|
|
|
350
356
|
// src/auxiliaries.ts
|
|
357
|
+
var AthenaErrorCode = {
|
|
358
|
+
UniqueViolation: "UNIQUE_VIOLATION",
|
|
359
|
+
NotFound: "NOT_FOUND",
|
|
360
|
+
ValidationFailed: "VALIDATION_FAILED",
|
|
361
|
+
AuthUnauthorized: "AUTH_UNAUTHORIZED",
|
|
362
|
+
AuthForbidden: "AUTH_FORBIDDEN",
|
|
363
|
+
RateLimited: "RATE_LIMITED",
|
|
364
|
+
NetworkUnavailable: "NETWORK_UNAVAILABLE",
|
|
365
|
+
TransientFailure: "TRANSIENT_FAILURE",
|
|
366
|
+
HttpFailure: "HTTP_FAILURE",
|
|
367
|
+
Unknown: "UNKNOWN"
|
|
368
|
+
};
|
|
369
|
+
var AthenaErrorCategory = {
|
|
370
|
+
Transport: "transport",
|
|
371
|
+
Client: "client",
|
|
372
|
+
Server: "server",
|
|
373
|
+
Database: "database",
|
|
374
|
+
Unknown: "unknown"
|
|
375
|
+
};
|
|
351
376
|
function parseBooleanFlag(rawValue, fallback) {
|
|
352
377
|
if (!rawValue) return fallback;
|
|
353
378
|
const normalized = rawValue.trim().toLowerCase();
|
|
@@ -359,6 +384,203 @@ function parseBooleanFlag(rawValue, fallback) {
|
|
|
359
384
|
}
|
|
360
385
|
return fallback;
|
|
361
386
|
}
|
|
387
|
+
function isRecord(value) {
|
|
388
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
389
|
+
}
|
|
390
|
+
function isAthenaErrorKind(value) {
|
|
391
|
+
return value === "unique_violation" || value === "not_found" || value === "validation" || value === "auth" || value === "rate_limit" || value === "transient" || value === "unknown";
|
|
392
|
+
}
|
|
393
|
+
function isAthenaErrorCode(value) {
|
|
394
|
+
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";
|
|
395
|
+
}
|
|
396
|
+
function isAthenaErrorCategory(value) {
|
|
397
|
+
return value === "transport" || value === "client" || value === "server" || value === "database" || value === "unknown";
|
|
398
|
+
}
|
|
399
|
+
function isNormalizedAthenaError(value) {
|
|
400
|
+
return isRecord(value) && isAthenaErrorKind(value.kind) && isAthenaErrorCode(value.code) && isAthenaErrorCategory(value.category) && typeof value.retryable === "boolean" && typeof value.message === "string" && "raw" in value;
|
|
401
|
+
}
|
|
402
|
+
function withContextOverrides(normalized, context) {
|
|
403
|
+
if (!context?.table && !context?.operation) {
|
|
404
|
+
return normalized;
|
|
405
|
+
}
|
|
406
|
+
return {
|
|
407
|
+
...normalized,
|
|
408
|
+
table: context.table ?? normalized.table,
|
|
409
|
+
operation: context.operation ?? normalized.operation
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
function resolveAttachedNormalizedError(resultOrError) {
|
|
413
|
+
if (!isRecord(resultOrError)) return void 0;
|
|
414
|
+
if (!("__athenaNormalizedError" in resultOrError)) return void 0;
|
|
415
|
+
const candidate = resultOrError.__athenaNormalizedError;
|
|
416
|
+
return isNormalizedAthenaError(candidate) ? candidate : void 0;
|
|
417
|
+
}
|
|
418
|
+
function isAthenaResultLike(value) {
|
|
419
|
+
return isRecord(value) && "status" in value && "error" in value && "data" in value && typeof value.status === "number";
|
|
420
|
+
}
|
|
421
|
+
function operationFromDetails(details) {
|
|
422
|
+
if (!details?.endpoint) return void 0;
|
|
423
|
+
if (details.endpoint === "/gateway/fetch" || details.endpoint === "/gateway/query") return "select";
|
|
424
|
+
if (details.endpoint === "/gateway/insert") return "insert";
|
|
425
|
+
if (details.endpoint === "/gateway/update") return "update";
|
|
426
|
+
if (details.endpoint === "/gateway/delete") return "delete";
|
|
427
|
+
if (details.endpoint === "/gateway/rpc" || details.endpoint.startsWith("/rpc/")) return "rpc";
|
|
428
|
+
return void 0;
|
|
429
|
+
}
|
|
430
|
+
function matchRegex(input, patterns) {
|
|
431
|
+
for (const pattern of patterns) {
|
|
432
|
+
const match = pattern.exec(input);
|
|
433
|
+
if (match?.[1]) return match[1];
|
|
434
|
+
}
|
|
435
|
+
return void 0;
|
|
436
|
+
}
|
|
437
|
+
function extractConstraint(message) {
|
|
438
|
+
return matchRegex(message, [
|
|
439
|
+
/unique constraint\s+["'`]([^"'`]+)["'`]/i,
|
|
440
|
+
/constraint\s+["'`]([^"'`]+)["'`]/i
|
|
441
|
+
]);
|
|
442
|
+
}
|
|
443
|
+
function extractTable(message) {
|
|
444
|
+
return matchRegex(message, [
|
|
445
|
+
/(?:table|relation)\s+["'`]([^"'`]+)["'`]/i,
|
|
446
|
+
/on\s+table\s+([a-zA-Z0-9_.]+)/i
|
|
447
|
+
]);
|
|
448
|
+
}
|
|
449
|
+
function classifyKind(status, code, message) {
|
|
450
|
+
const lower = message.toLowerCase();
|
|
451
|
+
const hasUniquePattern = lower.includes("unique constraint") || lower.includes("duplicate key") || lower.includes("already exists") || lower.includes("duplicate");
|
|
452
|
+
const hasNotFoundPattern = lower.includes("not found") || lower.includes("no rows");
|
|
453
|
+
const hasValidationPattern = lower.includes("validation") || lower.includes("invalid") || lower.includes("malformed");
|
|
454
|
+
const hasAuthPattern = lower.includes("unauthorized") || lower.includes("forbidden") || lower.includes("auth");
|
|
455
|
+
const hasRateLimitPattern = lower.includes("rate limit") || lower.includes("too many requests");
|
|
456
|
+
const hasTransientPattern = lower.includes("timeout") || lower.includes("temporar") || lower.includes("connection reset") || lower.includes("socket") || lower.includes("deadlock");
|
|
457
|
+
if (status === 409 || hasUniquePattern) return "unique_violation";
|
|
458
|
+
if (status === 404 || hasNotFoundPattern) return "not_found";
|
|
459
|
+
if (status === 401 || status === 403 || hasAuthPattern) return "auth";
|
|
460
|
+
if (status === 429 || hasRateLimitPattern) return "rate_limit";
|
|
461
|
+
if (status === 400 || status === 422 || hasValidationPattern) return "validation";
|
|
462
|
+
if (code === "NETWORK_ERROR" || status === 0 || status !== void 0 && status >= 500 || hasTransientPattern) {
|
|
463
|
+
return "transient";
|
|
464
|
+
}
|
|
465
|
+
return "unknown";
|
|
466
|
+
}
|
|
467
|
+
function toAthenaErrorCode(kind, status, gatewayCode) {
|
|
468
|
+
if (gatewayCode === "NETWORK_ERROR" || kind === "transient" && status === 0) {
|
|
469
|
+
return AthenaErrorCode.NetworkUnavailable;
|
|
470
|
+
}
|
|
471
|
+
switch (kind) {
|
|
472
|
+
case "unique_violation":
|
|
473
|
+
return AthenaErrorCode.UniqueViolation;
|
|
474
|
+
case "not_found":
|
|
475
|
+
return AthenaErrorCode.NotFound;
|
|
476
|
+
case "validation":
|
|
477
|
+
return AthenaErrorCode.ValidationFailed;
|
|
478
|
+
case "rate_limit":
|
|
479
|
+
return AthenaErrorCode.RateLimited;
|
|
480
|
+
case "auth":
|
|
481
|
+
if (status === 403) {
|
|
482
|
+
return AthenaErrorCode.AuthForbidden;
|
|
483
|
+
}
|
|
484
|
+
return AthenaErrorCode.AuthUnauthorized;
|
|
485
|
+
case "transient":
|
|
486
|
+
return status !== void 0 && status >= 500 ? AthenaErrorCode.HttpFailure : AthenaErrorCode.TransientFailure;
|
|
487
|
+
case "unknown":
|
|
488
|
+
default:
|
|
489
|
+
return status !== void 0 && status >= 400 ? AthenaErrorCode.HttpFailure : AthenaErrorCode.Unknown;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
function toAthenaErrorCategory(kind, status) {
|
|
493
|
+
if (kind === "transient" && (status === 0 || status === void 0)) {
|
|
494
|
+
return AthenaErrorCategory.Transport;
|
|
495
|
+
}
|
|
496
|
+
if (kind === "unique_violation") return AthenaErrorCategory.Database;
|
|
497
|
+
if (kind === "validation" || kind === "auth" || kind === "not_found") return AthenaErrorCategory.Client;
|
|
498
|
+
if (kind === "rate_limit" || kind === "transient") return AthenaErrorCategory.Server;
|
|
499
|
+
return AthenaErrorCategory.Unknown;
|
|
500
|
+
}
|
|
501
|
+
function isRetryable(kind, status) {
|
|
502
|
+
if (kind === "rate_limit" || kind === "transient") return true;
|
|
503
|
+
return status !== void 0 && status >= 500;
|
|
504
|
+
}
|
|
505
|
+
function normalizeAthenaError(resultOrError, context) {
|
|
506
|
+
const attached = resolveAttachedNormalizedError(resultOrError);
|
|
507
|
+
if (attached) {
|
|
508
|
+
return withContextOverrides(attached, context);
|
|
509
|
+
}
|
|
510
|
+
if (isAthenaResultLike(resultOrError)) {
|
|
511
|
+
const details = resultOrError.errorDetails;
|
|
512
|
+
const message2 = resultOrError.error ?? details?.message ?? `Athena ${context?.operation ?? operationFromDetails(details) ?? "request"} failed`;
|
|
513
|
+
const operation = context?.operation ?? operationFromDetails(details);
|
|
514
|
+
const table = context?.table ?? extractTable(message2);
|
|
515
|
+
const constraint = extractConstraint(message2);
|
|
516
|
+
const kind2 = classifyKind(resultOrError.status, details?.code, message2);
|
|
517
|
+
const code = toAthenaErrorCode(kind2, resultOrError.status, details?.code);
|
|
518
|
+
const category = toAthenaErrorCategory(kind2, resultOrError.status);
|
|
519
|
+
return {
|
|
520
|
+
kind: kind2,
|
|
521
|
+
code,
|
|
522
|
+
category,
|
|
523
|
+
retryable: isRetryable(kind2, resultOrError.status),
|
|
524
|
+
status: resultOrError.status,
|
|
525
|
+
constraint,
|
|
526
|
+
table,
|
|
527
|
+
operation,
|
|
528
|
+
message: message2,
|
|
529
|
+
raw: resultOrError.raw
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
if (isAthenaGatewayError(resultOrError)) {
|
|
533
|
+
const details = resultOrError.toDetails();
|
|
534
|
+
const operation = context?.operation ?? operationFromDetails(details);
|
|
535
|
+
const table = context?.table ?? extractTable(resultOrError.message);
|
|
536
|
+
const constraint = extractConstraint(resultOrError.message);
|
|
537
|
+
const kind2 = classifyKind(resultOrError.status, resultOrError.code, resultOrError.message);
|
|
538
|
+
const code = toAthenaErrorCode(kind2, resultOrError.status, resultOrError.code);
|
|
539
|
+
const category = toAthenaErrorCategory(kind2, resultOrError.status);
|
|
540
|
+
return {
|
|
541
|
+
kind: kind2,
|
|
542
|
+
code,
|
|
543
|
+
category,
|
|
544
|
+
retryable: isRetryable(kind2, resultOrError.status),
|
|
545
|
+
status: resultOrError.status,
|
|
546
|
+
constraint,
|
|
547
|
+
table,
|
|
548
|
+
operation,
|
|
549
|
+
message: resultOrError.message,
|
|
550
|
+
raw: resultOrError
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
if (resultOrError instanceof Error) {
|
|
554
|
+
const maybeStatus = isRecord(resultOrError) && typeof resultOrError.status === "number" ? resultOrError.status : void 0;
|
|
555
|
+
const kind2 = classifyKind(maybeStatus, void 0, resultOrError.message);
|
|
556
|
+
return {
|
|
557
|
+
kind: kind2,
|
|
558
|
+
code: toAthenaErrorCode(kind2, maybeStatus),
|
|
559
|
+
category: toAthenaErrorCategory(kind2, maybeStatus),
|
|
560
|
+
retryable: isRetryable(kind2, maybeStatus),
|
|
561
|
+
status: maybeStatus,
|
|
562
|
+
constraint: extractConstraint(resultOrError.message),
|
|
563
|
+
table: context?.table ?? extractTable(resultOrError.message),
|
|
564
|
+
operation: context?.operation,
|
|
565
|
+
message: resultOrError.message,
|
|
566
|
+
raw: resultOrError
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
const message = typeof resultOrError === "string" ? resultOrError : "Unknown Athena error";
|
|
570
|
+
const kind = classifyKind(void 0, void 0, message);
|
|
571
|
+
return {
|
|
572
|
+
kind,
|
|
573
|
+
code: toAthenaErrorCode(kind, void 0),
|
|
574
|
+
category: toAthenaErrorCategory(kind, void 0),
|
|
575
|
+
retryable: isRetryable(kind, void 0),
|
|
576
|
+
status: void 0,
|
|
577
|
+
constraint: extractConstraint(message),
|
|
578
|
+
table: context?.table ?? extractTable(message),
|
|
579
|
+
operation: context?.operation,
|
|
580
|
+
message,
|
|
581
|
+
raw: resultOrError
|
|
582
|
+
};
|
|
583
|
+
}
|
|
362
584
|
|
|
363
585
|
// src/generator/schema-selection.ts
|
|
364
586
|
var DEFAULT_POSTGRES_SCHEMAS = ["public"];
|
|
@@ -390,6 +612,7 @@ function resolveProviderSchemas(providerConfig) {
|
|
|
390
612
|
}
|
|
391
613
|
|
|
392
614
|
// src/generator/config.ts
|
|
615
|
+
var POSTGRES_PROTOCOLS = /* @__PURE__ */ new Set(["postgres:", "postgresql:"]);
|
|
393
616
|
var DEFAULT_CONFIG_CANDIDATES = [
|
|
394
617
|
"athena.config.ts",
|
|
395
618
|
"athena.config.js",
|
|
@@ -419,6 +642,151 @@ var DEFAULT_EXPERIMENTAL_FLAGS = {
|
|
|
419
642
|
postgresGatewayIntrospection: false,
|
|
420
643
|
scyllaProviderContracts: true
|
|
421
644
|
};
|
|
645
|
+
var PROJECT_ENV_FILENAMES = [".env", ".env.local"];
|
|
646
|
+
var DIRECT_CONNECTION_STRING_ENV_KEYS = [
|
|
647
|
+
"ATHENA_GENERATOR_PG_URL",
|
|
648
|
+
"DATABASE_URL",
|
|
649
|
+
"PG_URL",
|
|
650
|
+
"POSTGRES_URL",
|
|
651
|
+
"POSTGRESQL_URL"
|
|
652
|
+
];
|
|
653
|
+
var POSTGRES_DATABASE_ENV_KEYS = ["ATHENA_GENERATOR_DB", "ATHENA_DATABASE", "PGDATABASE"];
|
|
654
|
+
var POSTGRES_PASSWORD_ENV_KEYS = ["ATHENA_GENERATOR_PG_PASSWORD", "PGPASSWORD"];
|
|
655
|
+
var GATEWAY_URL_ENV_KEYS = ["ATHENA_URL", "ATHENA_GATEWAY_URL", "ATHENA_GENERATOR_URL"];
|
|
656
|
+
var GATEWAY_API_KEY_ENV_KEYS = [
|
|
657
|
+
"ATHENA_API_KEY",
|
|
658
|
+
"ATHENA_GATEWAY_API_KEY",
|
|
659
|
+
"ATHENA_GENERATOR_API_KEY"
|
|
660
|
+
];
|
|
661
|
+
function normalizeRawEnvValue(rawValue) {
|
|
662
|
+
if (rawValue.startsWith('"') && rawValue.endsWith('"') && rawValue.length >= 2) {
|
|
663
|
+
const inner = rawValue.slice(1, -1);
|
|
664
|
+
return inner.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
665
|
+
}
|
|
666
|
+
if (rawValue.startsWith("'") && rawValue.endsWith("'") && rawValue.length >= 2) {
|
|
667
|
+
return rawValue.slice(1, -1);
|
|
668
|
+
}
|
|
669
|
+
const commentIndex = rawValue.search(/\s+#/);
|
|
670
|
+
const withoutComment = commentIndex >= 0 ? rawValue.slice(0, commentIndex) : rawValue;
|
|
671
|
+
return withoutComment.trim();
|
|
672
|
+
}
|
|
673
|
+
function parseEnvLine(line) {
|
|
674
|
+
const trimmed = line.trim();
|
|
675
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
676
|
+
return void 0;
|
|
677
|
+
}
|
|
678
|
+
const match = trimmed.match(/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
|
|
679
|
+
if (!match) {
|
|
680
|
+
return void 0;
|
|
681
|
+
}
|
|
682
|
+
const [, key, rawValue] = match;
|
|
683
|
+
return [key, normalizeRawEnvValue(rawValue.trim())];
|
|
684
|
+
}
|
|
685
|
+
function readProjectEnvEntries(cwd) {
|
|
686
|
+
const nodeEnv = process.env.NODE_ENV?.trim();
|
|
687
|
+
const filenames = [
|
|
688
|
+
...PROJECT_ENV_FILENAMES,
|
|
689
|
+
...nodeEnv ? [`.env.${nodeEnv}`, `.env.${nodeEnv}.local`] : []
|
|
690
|
+
];
|
|
691
|
+
const entries = /* @__PURE__ */ new Map();
|
|
692
|
+
for (const filename of filenames) {
|
|
693
|
+
const absolutePath = resolve(cwd, filename);
|
|
694
|
+
if (!existsSync(absolutePath)) {
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
697
|
+
const content = readFileSync(absolutePath, "utf8");
|
|
698
|
+
const lines = content.split(/\r?\n/g);
|
|
699
|
+
for (const line of lines) {
|
|
700
|
+
const parsed = parseEnvLine(line);
|
|
701
|
+
if (!parsed) {
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
const [key, value] = parsed;
|
|
705
|
+
entries.set(key, value);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
return entries;
|
|
709
|
+
}
|
|
710
|
+
function applyProjectEnv(cwd) {
|
|
711
|
+
const envEntries = readProjectEnvEntries(cwd);
|
|
712
|
+
if (envEntries.size === 0) {
|
|
713
|
+
return () => {
|
|
714
|
+
};
|
|
715
|
+
}
|
|
716
|
+
const initialKeys = new Set(
|
|
717
|
+
Object.keys(process.env).filter((key) => process.env[key] !== void 0)
|
|
718
|
+
);
|
|
719
|
+
const staged = /* @__PURE__ */ new Map();
|
|
720
|
+
for (const [key, value] of envEntries.entries()) {
|
|
721
|
+
if (initialKeys.has(key)) {
|
|
722
|
+
continue;
|
|
723
|
+
}
|
|
724
|
+
staged.set(key, value);
|
|
725
|
+
}
|
|
726
|
+
for (const [key, value] of staged.entries()) {
|
|
727
|
+
process.env[key] = value;
|
|
728
|
+
}
|
|
729
|
+
return () => {
|
|
730
|
+
for (const key of staged.keys()) {
|
|
731
|
+
delete process.env[key];
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
}
|
|
735
|
+
function readEnvStringValue(key) {
|
|
736
|
+
const value = process.env[key];
|
|
737
|
+
if (typeof value !== "string") {
|
|
738
|
+
return void 0;
|
|
739
|
+
}
|
|
740
|
+
const trimmed = value.trim();
|
|
741
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
742
|
+
}
|
|
743
|
+
function resolveFallbackValue(fallbackKeys) {
|
|
744
|
+
for (const key of fallbackKeys) {
|
|
745
|
+
const value = readEnvStringValue(key);
|
|
746
|
+
if (value) {
|
|
747
|
+
return value;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
return void 0;
|
|
751
|
+
}
|
|
752
|
+
function normalizeOptionalString(value, fallbackKeys) {
|
|
753
|
+
if (typeof value === "string") {
|
|
754
|
+
const trimmed = value.trim();
|
|
755
|
+
if (trimmed.length > 0) {
|
|
756
|
+
return trimmed;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
return resolveFallbackValue(fallbackKeys);
|
|
760
|
+
}
|
|
761
|
+
function normalizeRequiredString(value, fieldLabel, fallbackKeys) {
|
|
762
|
+
const resolved = normalizeOptionalString(value, fallbackKeys);
|
|
763
|
+
if (resolved) {
|
|
764
|
+
return resolved;
|
|
765
|
+
}
|
|
766
|
+
throw new Error(
|
|
767
|
+
`Generator config is missing ${fieldLabel}. Set ${fieldLabel} directly or provide one of: ${fallbackKeys.join(", ")}.`
|
|
768
|
+
);
|
|
769
|
+
}
|
|
770
|
+
function applyPostgresPasswordFallback(connectionString) {
|
|
771
|
+
let parsedUrl;
|
|
772
|
+
try {
|
|
773
|
+
parsedUrl = new URL(connectionString);
|
|
774
|
+
} catch {
|
|
775
|
+
return connectionString;
|
|
776
|
+
}
|
|
777
|
+
if (!POSTGRES_PROTOCOLS.has(parsedUrl.protocol)) {
|
|
778
|
+
return connectionString;
|
|
779
|
+
}
|
|
780
|
+
if (!parsedUrl.username || parsedUrl.password) {
|
|
781
|
+
return connectionString;
|
|
782
|
+
}
|
|
783
|
+
const fallbackPassword = resolveFallbackValue(POSTGRES_PASSWORD_ENV_KEYS);
|
|
784
|
+
if (!fallbackPassword) {
|
|
785
|
+
return connectionString;
|
|
786
|
+
}
|
|
787
|
+
parsedUrl.password = fallbackPassword;
|
|
788
|
+
return parsedUrl.toString();
|
|
789
|
+
}
|
|
422
790
|
function normalizeBooleanFlag(rawValue, fallback) {
|
|
423
791
|
if (typeof rawValue === "boolean") {
|
|
424
792
|
return rawValue;
|
|
@@ -464,9 +832,41 @@ function normalizeOutputConfig(output) {
|
|
|
464
832
|
};
|
|
465
833
|
}
|
|
466
834
|
function normalizeProviderConfig(provider) {
|
|
467
|
-
if (provider.kind === "postgres") {
|
|
835
|
+
if (provider.kind === "postgres" && provider.mode === "direct") {
|
|
836
|
+
const connectionString = normalizeRequiredString(
|
|
837
|
+
provider.connectionString,
|
|
838
|
+
"provider.connectionString",
|
|
839
|
+
DIRECT_CONNECTION_STRING_ENV_KEYS
|
|
840
|
+
);
|
|
841
|
+
const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS);
|
|
468
842
|
return {
|
|
469
843
|
...provider,
|
|
844
|
+
connectionString: applyPostgresPasswordFallback(connectionString),
|
|
845
|
+
database,
|
|
846
|
+
schemas: normalizeSchemaSelection(provider.schemas)
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
if (provider.kind === "postgres" && provider.mode === "gateway") {
|
|
850
|
+
const gatewayUrl = normalizeRequiredString(
|
|
851
|
+
provider.gatewayUrl,
|
|
852
|
+
"provider.gatewayUrl",
|
|
853
|
+
GATEWAY_URL_ENV_KEYS
|
|
854
|
+
);
|
|
855
|
+
const apiKey = normalizeRequiredString(
|
|
856
|
+
provider.apiKey,
|
|
857
|
+
"provider.apiKey",
|
|
858
|
+
GATEWAY_API_KEY_ENV_KEYS
|
|
859
|
+
);
|
|
860
|
+
const database = normalizeRequiredString(
|
|
861
|
+
provider.database,
|
|
862
|
+
"provider.database",
|
|
863
|
+
POSTGRES_DATABASE_ENV_KEYS
|
|
864
|
+
);
|
|
865
|
+
return {
|
|
866
|
+
...provider,
|
|
867
|
+
gatewayUrl,
|
|
868
|
+
apiKey,
|
|
869
|
+
database,
|
|
470
870
|
schemas: normalizeSchemaSelection(provider.schemas)
|
|
471
871
|
};
|
|
472
872
|
}
|
|
@@ -525,6 +925,11 @@ function extractConfigExport(module) {
|
|
|
525
925
|
if (moduleExports && typeof moduleExports === "object") {
|
|
526
926
|
queue.push(moduleExports);
|
|
527
927
|
}
|
|
928
|
+
for (const value of Object.values(record)) {
|
|
929
|
+
if (value && typeof value === "object") {
|
|
930
|
+
queue.push(value);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
528
933
|
}
|
|
529
934
|
throw new Error(
|
|
530
935
|
"Generator config file must export a config object as default export or `config`."
|
|
@@ -539,19 +944,24 @@ function importConfigModule(moduleSpecifier) {
|
|
|
539
944
|
}
|
|
540
945
|
async function loadGeneratorConfig(options = {}) {
|
|
541
946
|
const cwd = options.cwd ?? process.cwd();
|
|
947
|
+
const restoreProjectEnv = applyProjectEnv(cwd);
|
|
542
948
|
const resolvedPath = options.configPath ? resolve(cwd, options.configPath) : findGeneratorConfigPath(cwd);
|
|
543
949
|
if (!resolvedPath) {
|
|
544
950
|
throw new Error(
|
|
545
951
|
`No generator config found in ${cwd}. Expected one of: ${DEFAULT_CONFIG_CANDIDATES.join(", ")}`
|
|
546
952
|
);
|
|
547
953
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
954
|
+
try {
|
|
955
|
+
const moduleUrl = pathToFileURL(resolvedPath);
|
|
956
|
+
const module = await importConfigModule(`${moduleUrl.href}?cacheBust=${Date.now()}`);
|
|
957
|
+
const rawConfig = extractConfigExport(module);
|
|
958
|
+
return {
|
|
959
|
+
configPath: resolvedPath,
|
|
960
|
+
config: normalizeGeneratorConfig(rawConfig)
|
|
961
|
+
};
|
|
962
|
+
} finally {
|
|
963
|
+
restoreProjectEnv();
|
|
964
|
+
}
|
|
555
965
|
}
|
|
556
966
|
|
|
557
967
|
// src/generator/renderer.ts
|
|
@@ -693,13 +1103,65 @@ function assertNoDuplicatePaths(files) {
|
|
|
693
1103
|
[
|
|
694
1104
|
`Generator output collision detected for path: ${file.path}`,
|
|
695
1105
|
`Collision: ${existing.kind} and ${file.kind}.`,
|
|
696
|
-
"
|
|
1106
|
+
"Use explicit placeholders such as {model}, {model_kebab}, {schema}, or {schema_kebab} in output targets so each artifact resolves to a unique path."
|
|
697
1107
|
].join(" ")
|
|
698
1108
|
);
|
|
699
1109
|
}
|
|
700
1110
|
seen.set(file.path, file);
|
|
701
1111
|
}
|
|
702
1112
|
}
|
|
1113
|
+
function addSchemaSegmentToPath(pathValue, schemaName) {
|
|
1114
|
+
const normalizedPath = normalizePath(pathValue);
|
|
1115
|
+
const parsedPath = posix.parse(normalizedPath);
|
|
1116
|
+
const schemaSegment = applyNamingStyle(schemaName, "kebab");
|
|
1117
|
+
if (!schemaSegment) {
|
|
1118
|
+
return normalizedPath;
|
|
1119
|
+
}
|
|
1120
|
+
const dir = parsedPath.dir.length > 0 ? `${parsedPath.dir}/${schemaSegment}` : schemaSegment;
|
|
1121
|
+
return normalizePath(posix.join(dir, parsedPath.base));
|
|
1122
|
+
}
|
|
1123
|
+
function scopeDuplicateDescriptorPathsBySchema(descriptors) {
|
|
1124
|
+
const nextDescriptors = descriptors.map((descriptor) => ({ ...descriptor }));
|
|
1125
|
+
const duplicates = /* @__PURE__ */ new Map();
|
|
1126
|
+
for (let index = 0; index < nextDescriptors.length; index += 1) {
|
|
1127
|
+
const descriptor = nextDescriptors[index];
|
|
1128
|
+
const indexes = duplicates.get(descriptor.filePath) ?? [];
|
|
1129
|
+
indexes.push(index);
|
|
1130
|
+
duplicates.set(descriptor.filePath, indexes);
|
|
1131
|
+
}
|
|
1132
|
+
let appliedSchemaScoping = false;
|
|
1133
|
+
for (const indexes of duplicates.values()) {
|
|
1134
|
+
if (indexes.length <= 1) {
|
|
1135
|
+
continue;
|
|
1136
|
+
}
|
|
1137
|
+
const schemaNames = new Set(indexes.map((index) => nextDescriptors[index].schemaName));
|
|
1138
|
+
if (schemaNames.size <= 1) {
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1141
|
+
for (const index of indexes) {
|
|
1142
|
+
const descriptor = nextDescriptors[index];
|
|
1143
|
+
descriptor.filePath = addSchemaSegmentToPath(descriptor.filePath, descriptor.schemaName);
|
|
1144
|
+
}
|
|
1145
|
+
appliedSchemaScoping = true;
|
|
1146
|
+
}
|
|
1147
|
+
if (!appliedSchemaScoping) {
|
|
1148
|
+
return nextDescriptors;
|
|
1149
|
+
}
|
|
1150
|
+
const normalizedPaths = /* @__PURE__ */ new Set();
|
|
1151
|
+
for (const descriptor of nextDescriptors) {
|
|
1152
|
+
if (normalizedPaths.has(descriptor.filePath)) {
|
|
1153
|
+
throw new Error(
|
|
1154
|
+
[
|
|
1155
|
+
`Generator output collision detected for path: ${descriptor.filePath}`,
|
|
1156
|
+
"Automatic schema path scoping was applied but collisions remain.",
|
|
1157
|
+
"Add explicit placeholders such as {model}, {model_kebab}, {schema}, or {schema_kebab} to your output targets."
|
|
1158
|
+
].join(" ")
|
|
1159
|
+
);
|
|
1160
|
+
}
|
|
1161
|
+
normalizedPaths.add(descriptor.filePath);
|
|
1162
|
+
}
|
|
1163
|
+
return nextDescriptors;
|
|
1164
|
+
}
|
|
703
1165
|
var ArtifactComposer = class {
|
|
704
1166
|
constructor(snapshot, config) {
|
|
705
1167
|
this.snapshot = snapshot;
|
|
@@ -738,7 +1200,8 @@ var ArtifactComposer = class {
|
|
|
738
1200
|
});
|
|
739
1201
|
}
|
|
740
1202
|
}
|
|
741
|
-
const
|
|
1203
|
+
const scopedModelDescriptors = scopeDuplicateDescriptorPathsBySchema(modelDescriptors);
|
|
1204
|
+
let schemaDescriptors = Object.keys(this.snapshot.schemas).sort().map((schemaName) => {
|
|
742
1205
|
const schemaPath = normalizePath(
|
|
743
1206
|
renderOutputPath(this.config.output.targets.schema, {
|
|
744
1207
|
provider: providerName,
|
|
@@ -756,9 +1219,10 @@ var ArtifactComposer = class {
|
|
|
756
1219
|
this.config.naming.schemaConst,
|
|
757
1220
|
"schema"
|
|
758
1221
|
),
|
|
759
|
-
models:
|
|
1222
|
+
models: scopedModelDescriptors.filter((model) => model.schemaName === schemaName)
|
|
760
1223
|
};
|
|
761
1224
|
});
|
|
1225
|
+
schemaDescriptors = scopeDuplicateDescriptorPathsBySchema(schemaDescriptors);
|
|
762
1226
|
const databasePath = normalizePath(
|
|
763
1227
|
renderOutputPath(this.config.output.targets.database, {
|
|
764
1228
|
provider: providerName,
|
|
@@ -778,7 +1242,7 @@ var ArtifactComposer = class {
|
|
|
778
1242
|
schemas: schemaDescriptors
|
|
779
1243
|
};
|
|
780
1244
|
const files = [];
|
|
781
|
-
for (const modelDescriptor of
|
|
1245
|
+
for (const modelDescriptor of scopedModelDescriptors) {
|
|
782
1246
|
files.push(renderModelArtifact(this.snapshot, modelDescriptor, this.config));
|
|
783
1247
|
}
|
|
784
1248
|
for (const schemaDescriptor of schemaDescriptors) {
|
|
@@ -842,14 +1306,14 @@ function parseResponseBody(rawText, contentType) {
|
|
|
842
1306
|
function normalizeHeaderValue(value) {
|
|
843
1307
|
return value ? value : void 0;
|
|
844
1308
|
}
|
|
845
|
-
function
|
|
1309
|
+
function isRecord2(value) {
|
|
846
1310
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
847
1311
|
}
|
|
848
1312
|
function resolveRequestId(headers) {
|
|
849
1313
|
return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
|
|
850
1314
|
}
|
|
851
1315
|
function resolveErrorMessage(payload, fallback) {
|
|
852
|
-
if (
|
|
1316
|
+
if (isRecord2(payload)) {
|
|
853
1317
|
const messageCandidates = [payload.error, payload.message, payload.details];
|
|
854
1318
|
for (const candidate of messageCandidates) {
|
|
855
1319
|
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
@@ -1039,7 +1503,7 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
1039
1503
|
};
|
|
1040
1504
|
}
|
|
1041
1505
|
const parsed = parsedBody.parsed;
|
|
1042
|
-
const parsedPayload =
|
|
1506
|
+
const parsedPayload = isRecord2(parsed) ? parsed : null;
|
|
1043
1507
|
if (!response.ok) {
|
|
1044
1508
|
const httpError = new AthenaGatewayError({
|
|
1045
1509
|
code: "HTTP_ERROR",
|
|
@@ -1247,7 +1711,7 @@ var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
|
|
|
1247
1711
|
function normalizeBaseUrl(baseUrl) {
|
|
1248
1712
|
return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
|
|
1249
1713
|
}
|
|
1250
|
-
function
|
|
1714
|
+
function isRecord3(value) {
|
|
1251
1715
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1252
1716
|
}
|
|
1253
1717
|
function normalizeHeaderValue2(value) {
|
|
@@ -1272,7 +1736,7 @@ function resolveRequestId2(headers) {
|
|
|
1272
1736
|
return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
|
|
1273
1737
|
}
|
|
1274
1738
|
function resolveErrorMessage2(payload, fallback) {
|
|
1275
|
-
if (
|
|
1739
|
+
if (isRecord3(payload)) {
|
|
1276
1740
|
const messageCandidates = [payload.error, payload.message, payload.details];
|
|
1277
1741
|
for (const candidate of messageCandidates) {
|
|
1278
1742
|
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
@@ -1625,7 +2089,7 @@ function createAuthClient(config = {}) {
|
|
|
1625
2089
|
data: null
|
|
1626
2090
|
};
|
|
1627
2091
|
}
|
|
1628
|
-
const fallbackStatus =
|
|
2092
|
+
const fallbackStatus = isRecord3(fallback.data) && typeof fallback.data.ok === "boolean" ? fallback.data.ok ? "ok" : "error" : "ok";
|
|
1629
2093
|
return {
|
|
1630
2094
|
...fallback,
|
|
1631
2095
|
data: {
|
|
@@ -2276,10 +2740,42 @@ function createAuthClient(config = {}) {
|
|
|
2276
2740
|
};
|
|
2277
2741
|
}
|
|
2278
2742
|
|
|
2743
|
+
// src/db/module.ts
|
|
2744
|
+
function createDbModule(input) {
|
|
2745
|
+
const db = {
|
|
2746
|
+
from(table) {
|
|
2747
|
+
return input.from(table);
|
|
2748
|
+
},
|
|
2749
|
+
select(table, columns, options) {
|
|
2750
|
+
return input.from(table).select(columns, options);
|
|
2751
|
+
},
|
|
2752
|
+
insert(table, values, options) {
|
|
2753
|
+
return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
|
|
2754
|
+
},
|
|
2755
|
+
upsert(table, values, options) {
|
|
2756
|
+
return Array.isArray(values) ? input.from(table).upsert(values, options) : input.from(table).upsert(values, options);
|
|
2757
|
+
},
|
|
2758
|
+
update(table, values, options) {
|
|
2759
|
+
return input.from(table).update(values, options);
|
|
2760
|
+
},
|
|
2761
|
+
delete(table, options) {
|
|
2762
|
+
return input.from(table).delete(options);
|
|
2763
|
+
},
|
|
2764
|
+
rpc(fn, args, options) {
|
|
2765
|
+
return input.rpc(fn, args, options);
|
|
2766
|
+
},
|
|
2767
|
+
query(query, options) {
|
|
2768
|
+
return input.query(query, options);
|
|
2769
|
+
}
|
|
2770
|
+
};
|
|
2771
|
+
return db;
|
|
2772
|
+
}
|
|
2773
|
+
|
|
2279
2774
|
// src/client.ts
|
|
2280
2775
|
var DEFAULT_COLUMNS = "*";
|
|
2281
2776
|
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;
|
|
2282
2777
|
var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
|
|
2778
|
+
var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
|
|
2283
2779
|
function formatResult(response) {
|
|
2284
2780
|
const result = {
|
|
2285
2781
|
data: response.data ?? null,
|
|
@@ -2293,6 +2789,28 @@ function formatResult(response) {
|
|
|
2293
2789
|
}
|
|
2294
2790
|
return result;
|
|
2295
2791
|
}
|
|
2792
|
+
function attachNormalizedError(result, normalizedError) {
|
|
2793
|
+
Object.defineProperty(result, ATHENA_NORMALIZED_ERROR_KEY, {
|
|
2794
|
+
value: normalizedError,
|
|
2795
|
+
enumerable: false,
|
|
2796
|
+
configurable: true,
|
|
2797
|
+
writable: false
|
|
2798
|
+
});
|
|
2799
|
+
}
|
|
2800
|
+
function createResultFormatter(experimental) {
|
|
2801
|
+
if (!experimental?.enableErrorNormalization) {
|
|
2802
|
+
return formatResult;
|
|
2803
|
+
}
|
|
2804
|
+
return (response, context) => {
|
|
2805
|
+
const result = formatResult(response);
|
|
2806
|
+
if (result.error == null) {
|
|
2807
|
+
return result;
|
|
2808
|
+
}
|
|
2809
|
+
const normalizedError = normalizeAthenaError(result, context);
|
|
2810
|
+
attachNormalizedError(result, normalizedError);
|
|
2811
|
+
return result;
|
|
2812
|
+
};
|
|
2813
|
+
}
|
|
2296
2814
|
function toSingleResult(response) {
|
|
2297
2815
|
const payload = response.data;
|
|
2298
2816
|
const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
|
|
@@ -2667,7 +3185,7 @@ function createRpcFilterMethods(filters, self) {
|
|
|
2667
3185
|
}
|
|
2668
3186
|
};
|
|
2669
3187
|
}
|
|
2670
|
-
function createRpcBuilder(functionName, args, baseOptions, client) {
|
|
3188
|
+
function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult) {
|
|
2671
3189
|
const state = {
|
|
2672
3190
|
filters: []
|
|
2673
3191
|
};
|
|
@@ -2689,7 +3207,7 @@ function createRpcBuilder(functionName, args, baseOptions, client) {
|
|
|
2689
3207
|
order: state.order
|
|
2690
3208
|
};
|
|
2691
3209
|
const response = await client.rpcGateway(payload, mergedOptions);
|
|
2692
|
-
return
|
|
3210
|
+
return formatGatewayResult(response, { operation: "rpc" });
|
|
2693
3211
|
};
|
|
2694
3212
|
const run = (columns, options) => {
|
|
2695
3213
|
const payloadColumns = columns ?? selectedColumns;
|
|
@@ -2743,7 +3261,7 @@ function createRpcBuilder(functionName, args, baseOptions, client) {
|
|
|
2743
3261
|
});
|
|
2744
3262
|
return builder;
|
|
2745
3263
|
}
|
|
2746
|
-
function createTableBuilder(tableName, client) {
|
|
3264
|
+
function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
2747
3265
|
const state = {
|
|
2748
3266
|
conditions: []
|
|
2749
3267
|
};
|
|
@@ -2800,7 +3318,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2800
3318
|
});
|
|
2801
3319
|
if (query) {
|
|
2802
3320
|
const queryResponse = await client.queryGateway({ query }, options);
|
|
2803
|
-
return
|
|
3321
|
+
return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
|
|
2804
3322
|
}
|
|
2805
3323
|
}
|
|
2806
3324
|
const payload = {
|
|
@@ -2818,7 +3336,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2818
3336
|
head: options?.head
|
|
2819
3337
|
};
|
|
2820
3338
|
const response = await client.fetchGateway(payload, options);
|
|
2821
|
-
return
|
|
3339
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
|
|
2822
3340
|
};
|
|
2823
3341
|
const createSelectChain = (columns, options) => {
|
|
2824
3342
|
const chain = {};
|
|
@@ -2873,7 +3391,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2873
3391
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2874
3392
|
}
|
|
2875
3393
|
const response = await client.insertGateway(payload, mergedOptions);
|
|
2876
|
-
return
|
|
3394
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2877
3395
|
};
|
|
2878
3396
|
return createMutationQuery(executeInsertMany);
|
|
2879
3397
|
}
|
|
@@ -2891,7 +3409,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2891
3409
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2892
3410
|
}
|
|
2893
3411
|
const response = await client.insertGateway(payload, mergedOptions);
|
|
2894
|
-
return
|
|
3412
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2895
3413
|
};
|
|
2896
3414
|
return createMutationQuery(executeInsertOne);
|
|
2897
3415
|
},
|
|
@@ -2913,7 +3431,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2913
3431
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2914
3432
|
}
|
|
2915
3433
|
const response = await client.insertGateway(payload, mergedOptions);
|
|
2916
|
-
return
|
|
3434
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2917
3435
|
};
|
|
2918
3436
|
return createMutationQuery(executeUpsertMany);
|
|
2919
3437
|
}
|
|
@@ -2933,7 +3451,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2933
3451
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2934
3452
|
}
|
|
2935
3453
|
const response = await client.insertGateway(payload, mergedOptions);
|
|
2936
|
-
return
|
|
3454
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2937
3455
|
};
|
|
2938
3456
|
return createMutationQuery(executeUpsertOne);
|
|
2939
3457
|
},
|
|
@@ -2954,7 +3472,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2954
3472
|
if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
|
|
2955
3473
|
if (columns) payload.columns = columns;
|
|
2956
3474
|
const response = await client.updateGateway(payload, mergedOptions);
|
|
2957
|
-
return
|
|
3475
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "update" });
|
|
2958
3476
|
};
|
|
2959
3477
|
const mutation = createMutationQuery(executeUpdate, null);
|
|
2960
3478
|
const updateChain = {};
|
|
@@ -2982,7 +3500,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2982
3500
|
if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
|
|
2983
3501
|
if (columns) payload.columns = columns;
|
|
2984
3502
|
const response = await client.deleteGateway(payload, mergedOptions);
|
|
2985
|
-
return
|
|
3503
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "delete" });
|
|
2986
3504
|
};
|
|
2987
3505
|
return createMutationQuery(executeDelete, null);
|
|
2988
3506
|
},
|
|
@@ -2996,14 +3514,14 @@ function createTableBuilder(tableName, client) {
|
|
|
2996
3514
|
});
|
|
2997
3515
|
return builder;
|
|
2998
3516
|
}
|
|
2999
|
-
function createQueryBuilder(client) {
|
|
3517
|
+
function createQueryBuilder(client, formatGatewayResult) {
|
|
3000
3518
|
return async function query(query, options) {
|
|
3001
3519
|
const normalizedQuery = query.trim();
|
|
3002
3520
|
if (!normalizedQuery) {
|
|
3003
3521
|
throw new Error("query requires a non-empty string");
|
|
3004
3522
|
}
|
|
3005
3523
|
const response = await client.queryGateway({ query: normalizedQuery }, options);
|
|
3006
|
-
return
|
|
3524
|
+
return formatGatewayResult(response, { operation: "query" });
|
|
3007
3525
|
};
|
|
3008
3526
|
}
|
|
3009
3527
|
function createClientFromConfig(config) {
|
|
@@ -3014,24 +3532,29 @@ function createClientFromConfig(config) {
|
|
|
3014
3532
|
backend: config.backend,
|
|
3015
3533
|
headers: config.headers
|
|
3016
3534
|
});
|
|
3535
|
+
const formatGatewayResult = createResultFormatter(config.experimental);
|
|
3017
3536
|
const auth = createAuthClient(config.auth);
|
|
3537
|
+
const from = (table) => createTableBuilder(table, gateway, formatGatewayResult);
|
|
3538
|
+
const rpc = (fn, args, options) => {
|
|
3539
|
+
const normalizedFn = fn.trim();
|
|
3540
|
+
if (!normalizedFn) {
|
|
3541
|
+
throw new Error("rpc requires a function name");
|
|
3542
|
+
}
|
|
3543
|
+
return createRpcBuilder(
|
|
3544
|
+
normalizedFn,
|
|
3545
|
+
args,
|
|
3546
|
+
options,
|
|
3547
|
+
gateway,
|
|
3548
|
+
formatGatewayResult
|
|
3549
|
+
);
|
|
3550
|
+
};
|
|
3551
|
+
const query = createQueryBuilder(gateway, formatGatewayResult);
|
|
3552
|
+
const db = createDbModule({ from, rpc, query });
|
|
3018
3553
|
return {
|
|
3019
|
-
from
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
const normalizedFn = fn.trim();
|
|
3024
|
-
if (!normalizedFn) {
|
|
3025
|
-
throw new Error("rpc requires a function name");
|
|
3026
|
-
}
|
|
3027
|
-
return createRpcBuilder(
|
|
3028
|
-
normalizedFn,
|
|
3029
|
-
args,
|
|
3030
|
-
options,
|
|
3031
|
-
gateway
|
|
3032
|
-
);
|
|
3033
|
-
},
|
|
3034
|
-
query: createQueryBuilder(gateway),
|
|
3554
|
+
from,
|
|
3555
|
+
db,
|
|
3556
|
+
rpc,
|
|
3557
|
+
query,
|
|
3035
3558
|
auth: auth.auth
|
|
3036
3559
|
};
|
|
3037
3560
|
}
|
|
@@ -3040,77 +3563,16 @@ function toBackendConfig(b) {
|
|
|
3040
3563
|
if (!b) return DEFAULT_BACKEND;
|
|
3041
3564
|
return typeof b === "string" ? { type: b } : b;
|
|
3042
3565
|
}
|
|
3043
|
-
var AthenaClientBuilderImpl = class {
|
|
3044
|
-
baseUrl;
|
|
3045
|
-
apiKey;
|
|
3046
|
-
backendConfig = DEFAULT_BACKEND;
|
|
3047
|
-
clientName;
|
|
3048
|
-
defaultHeaders;
|
|
3049
|
-
isHealthTrackingEnabled = false;
|
|
3050
|
-
url(url) {
|
|
3051
|
-
this.baseUrl = url;
|
|
3052
|
-
return this;
|
|
3053
|
-
}
|
|
3054
|
-
key(apiKey) {
|
|
3055
|
-
this.apiKey = apiKey;
|
|
3056
|
-
return this;
|
|
3057
|
-
}
|
|
3058
|
-
backend(backend) {
|
|
3059
|
-
this.backendConfig = toBackendConfig(backend);
|
|
3060
|
-
return this;
|
|
3061
|
-
}
|
|
3062
|
-
client(clientName) {
|
|
3063
|
-
this.clientName = clientName;
|
|
3064
|
-
return this;
|
|
3065
|
-
}
|
|
3066
|
-
headers(headers) {
|
|
3067
|
-
this.defaultHeaders = headers;
|
|
3068
|
-
return this;
|
|
3069
|
-
}
|
|
3070
|
-
healthTracking(enabled) {
|
|
3071
|
-
this.isHealthTrackingEnabled = enabled;
|
|
3072
|
-
return this;
|
|
3073
|
-
}
|
|
3074
|
-
build() {
|
|
3075
|
-
if (!this.baseUrl || !this.apiKey) {
|
|
3076
|
-
throw new Error("AthenaClient requires url and key; call .url() and .key() before .build()");
|
|
3077
|
-
}
|
|
3078
|
-
return createClientFromConfig({
|
|
3079
|
-
baseUrl: this.baseUrl,
|
|
3080
|
-
apiKey: this.apiKey,
|
|
3081
|
-
client: this.clientName,
|
|
3082
|
-
backend: this.backendConfig,
|
|
3083
|
-
headers: this.defaultHeaders,
|
|
3084
|
-
healthTracking: this.isHealthTrackingEnabled
|
|
3085
|
-
});
|
|
3086
|
-
}
|
|
3087
|
-
};
|
|
3088
|
-
var AthenaClient = class _AthenaClient {
|
|
3089
|
-
/** Create a fluent builder for a strongly-typed Athena SDK client. */
|
|
3090
|
-
static builder() {
|
|
3091
|
-
return new AthenaClientBuilderImpl();
|
|
3092
|
-
}
|
|
3093
|
-
/** Build a client from process environment variables. */
|
|
3094
|
-
static fromEnvironment() {
|
|
3095
|
-
const url = process.env.ATHENA_URL ?? process.env.ATHENA_GATEWAY_URL;
|
|
3096
|
-
const key = process.env.ATHENA_API_KEY ?? process.env.ATHENA_GATEWAY_API_KEY;
|
|
3097
|
-
if (!url || !key) {
|
|
3098
|
-
throw new Error(
|
|
3099
|
-
"ATHENA_URL and ATHENA_API_KEY (or ATHENA_GATEWAY_URL and ATHENA_GATEWAY_API_KEY) are required"
|
|
3100
|
-
);
|
|
3101
|
-
}
|
|
3102
|
-
return _AthenaClient.builder().url(url).key(key).build();
|
|
3103
|
-
}
|
|
3104
|
-
};
|
|
3105
3566
|
function createClient(url, apiKey, options) {
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3567
|
+
return createClientFromConfig({
|
|
3568
|
+
baseUrl: url,
|
|
3569
|
+
apiKey,
|
|
3570
|
+
client: options?.client,
|
|
3571
|
+
backend: toBackendConfig(options?.backend),
|
|
3572
|
+
headers: options?.headers,
|
|
3573
|
+
auth: options?.auth,
|
|
3574
|
+
experimental: options?.experimental
|
|
3575
|
+
});
|
|
3114
3576
|
}
|
|
3115
3577
|
|
|
3116
3578
|
// src/schema/postgres-introspection-core.ts
|
|
@@ -3460,6 +3922,23 @@ var PostgresCatalogSnapshotAssembler = class {
|
|
|
3460
3922
|
table.relations[key] = relation;
|
|
3461
3923
|
}
|
|
3462
3924
|
};
|
|
3925
|
+
|
|
3926
|
+
// src/schema/postgres-provider.ts
|
|
3927
|
+
var pgPoolConstructorPromise;
|
|
3928
|
+
async function loadPgPoolConstructor() {
|
|
3929
|
+
if (!pgPoolConstructorPromise) {
|
|
3930
|
+
pgPoolConstructorPromise = import('pg').then((module) => {
|
|
3931
|
+
const poolConstructor = module.Pool ?? module.default?.Pool;
|
|
3932
|
+
if (!poolConstructor) {
|
|
3933
|
+
throw new Error(
|
|
3934
|
+
'@xylex-group/athena: Unable to load the PostgreSQL driver. Ensure "pg" is installed and this API runs in a Node.js server runtime.'
|
|
3935
|
+
);
|
|
3936
|
+
}
|
|
3937
|
+
return poolConstructor;
|
|
3938
|
+
});
|
|
3939
|
+
}
|
|
3940
|
+
return pgPoolConstructorPromise;
|
|
3941
|
+
}
|
|
3463
3942
|
var PgCatalogClient = class {
|
|
3464
3943
|
constructor(pool) {
|
|
3465
3944
|
this.pool = pool;
|
|
@@ -3499,7 +3978,8 @@ var PostgresIntrospectionProvider = class {
|
|
|
3499
3978
|
}
|
|
3500
3979
|
async inspect(options) {
|
|
3501
3980
|
const schemas = options?.schemas && options.schemas.length > 0 ? normalizePostgresCatalogSchemas(options.schemas) : this.schemas;
|
|
3502
|
-
const
|
|
3981
|
+
const PoolConstructor = await loadPgPoolConstructor();
|
|
3982
|
+
const pool = new PoolConstructor({
|
|
3503
3983
|
connectionString: this.connectionString
|
|
3504
3984
|
});
|
|
3505
3985
|
const catalogClient = new PgCatalogClient(pool);
|