@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.cjs
CHANGED
|
@@ -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);
|
|
@@ -348,8 +351,30 @@ var AthenaGatewayError = class _AthenaGatewayError extends Error {
|
|
|
348
351
|
});
|
|
349
352
|
}
|
|
350
353
|
};
|
|
354
|
+
function isAthenaGatewayError(error) {
|
|
355
|
+
return error instanceof AthenaGatewayError;
|
|
356
|
+
}
|
|
351
357
|
|
|
352
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
|
+
};
|
|
353
378
|
function parseBooleanFlag(rawValue, fallback) {
|
|
354
379
|
if (!rawValue) return fallback;
|
|
355
380
|
const normalized = rawValue.trim().toLowerCase();
|
|
@@ -361,6 +386,203 @@ function parseBooleanFlag(rawValue, fallback) {
|
|
|
361
386
|
}
|
|
362
387
|
return fallback;
|
|
363
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
|
+
}
|
|
364
586
|
|
|
365
587
|
// src/generator/schema-selection.ts
|
|
366
588
|
var DEFAULT_POSTGRES_SCHEMAS = ["public"];
|
|
@@ -392,6 +614,7 @@ function resolveProviderSchemas(providerConfig) {
|
|
|
392
614
|
}
|
|
393
615
|
|
|
394
616
|
// src/generator/config.ts
|
|
617
|
+
var POSTGRES_PROTOCOLS = /* @__PURE__ */ new Set(["postgres:", "postgresql:"]);
|
|
395
618
|
var DEFAULT_CONFIG_CANDIDATES = [
|
|
396
619
|
"athena.config.ts",
|
|
397
620
|
"athena.config.js",
|
|
@@ -421,6 +644,151 @@ var DEFAULT_EXPERIMENTAL_FLAGS = {
|
|
|
421
644
|
postgresGatewayIntrospection: false,
|
|
422
645
|
scyllaProviderContracts: true
|
|
423
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
|
+
}
|
|
424
792
|
function normalizeBooleanFlag(rawValue, fallback) {
|
|
425
793
|
if (typeof rawValue === "boolean") {
|
|
426
794
|
return rawValue;
|
|
@@ -466,9 +834,41 @@ function normalizeOutputConfig(output) {
|
|
|
466
834
|
};
|
|
467
835
|
}
|
|
468
836
|
function normalizeProviderConfig(provider) {
|
|
469
|
-
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);
|
|
470
844
|
return {
|
|
471
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
|
+
);
|
|
867
|
+
return {
|
|
868
|
+
...provider,
|
|
869
|
+
gatewayUrl,
|
|
870
|
+
apiKey,
|
|
871
|
+
database,
|
|
472
872
|
schemas: normalizeSchemaSelection(provider.schemas)
|
|
473
873
|
};
|
|
474
874
|
}
|
|
@@ -527,6 +927,11 @@ function extractConfigExport(module) {
|
|
|
527
927
|
if (moduleExports && typeof moduleExports === "object") {
|
|
528
928
|
queue.push(moduleExports);
|
|
529
929
|
}
|
|
930
|
+
for (const value of Object.values(record)) {
|
|
931
|
+
if (value && typeof value === "object") {
|
|
932
|
+
queue.push(value);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
530
935
|
}
|
|
531
936
|
throw new Error(
|
|
532
937
|
"Generator config file must export a config object as default export or `config`."
|
|
@@ -541,19 +946,24 @@ function importConfigModule(moduleSpecifier) {
|
|
|
541
946
|
}
|
|
542
947
|
async function loadGeneratorConfig(options = {}) {
|
|
543
948
|
const cwd = options.cwd ?? process.cwd();
|
|
949
|
+
const restoreProjectEnv = applyProjectEnv(cwd);
|
|
544
950
|
const resolvedPath = options.configPath ? path.resolve(cwd, options.configPath) : findGeneratorConfigPath(cwd);
|
|
545
951
|
if (!resolvedPath) {
|
|
546
952
|
throw new Error(
|
|
547
953
|
`No generator config found in ${cwd}. Expected one of: ${DEFAULT_CONFIG_CANDIDATES.join(", ")}`
|
|
548
954
|
);
|
|
549
955
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
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
|
+
}
|
|
557
967
|
}
|
|
558
968
|
|
|
559
969
|
// src/generator/renderer.ts
|
|
@@ -695,13 +1105,65 @@ function assertNoDuplicatePaths(files) {
|
|
|
695
1105
|
[
|
|
696
1106
|
`Generator output collision detected for path: ${file.path}`,
|
|
697
1107
|
`Collision: ${existing.kind} and ${file.kind}.`,
|
|
698
|
-
"
|
|
1108
|
+
"Use explicit placeholders such as {model}, {model_kebab}, {schema}, or {schema_kebab} in output targets so each artifact resolves to a unique path."
|
|
699
1109
|
].join(" ")
|
|
700
1110
|
);
|
|
701
1111
|
}
|
|
702
1112
|
seen.set(file.path, file);
|
|
703
1113
|
}
|
|
704
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
|
+
}
|
|
705
1167
|
var ArtifactComposer = class {
|
|
706
1168
|
constructor(snapshot, config) {
|
|
707
1169
|
this.snapshot = snapshot;
|
|
@@ -740,7 +1202,8 @@ var ArtifactComposer = class {
|
|
|
740
1202
|
});
|
|
741
1203
|
}
|
|
742
1204
|
}
|
|
743
|
-
const
|
|
1205
|
+
const scopedModelDescriptors = scopeDuplicateDescriptorPathsBySchema(modelDescriptors);
|
|
1206
|
+
let schemaDescriptors = Object.keys(this.snapshot.schemas).sort().map((schemaName) => {
|
|
744
1207
|
const schemaPath = normalizePath(
|
|
745
1208
|
renderOutputPath(this.config.output.targets.schema, {
|
|
746
1209
|
provider: providerName,
|
|
@@ -758,9 +1221,10 @@ var ArtifactComposer = class {
|
|
|
758
1221
|
this.config.naming.schemaConst,
|
|
759
1222
|
"schema"
|
|
760
1223
|
),
|
|
761
|
-
models:
|
|
1224
|
+
models: scopedModelDescriptors.filter((model) => model.schemaName === schemaName)
|
|
762
1225
|
};
|
|
763
1226
|
});
|
|
1227
|
+
schemaDescriptors = scopeDuplicateDescriptorPathsBySchema(schemaDescriptors);
|
|
764
1228
|
const databasePath = normalizePath(
|
|
765
1229
|
renderOutputPath(this.config.output.targets.database, {
|
|
766
1230
|
provider: providerName,
|
|
@@ -780,7 +1244,7 @@ var ArtifactComposer = class {
|
|
|
780
1244
|
schemas: schemaDescriptors
|
|
781
1245
|
};
|
|
782
1246
|
const files = [];
|
|
783
|
-
for (const modelDescriptor of
|
|
1247
|
+
for (const modelDescriptor of scopedModelDescriptors) {
|
|
784
1248
|
files.push(renderModelArtifact(this.snapshot, modelDescriptor, this.config));
|
|
785
1249
|
}
|
|
786
1250
|
for (const schemaDescriptor of schemaDescriptors) {
|
|
@@ -844,14 +1308,14 @@ function parseResponseBody(rawText, contentType) {
|
|
|
844
1308
|
function normalizeHeaderValue(value) {
|
|
845
1309
|
return value ? value : void 0;
|
|
846
1310
|
}
|
|
847
|
-
function
|
|
1311
|
+
function isRecord2(value) {
|
|
848
1312
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
849
1313
|
}
|
|
850
1314
|
function resolveRequestId(headers) {
|
|
851
1315
|
return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
|
|
852
1316
|
}
|
|
853
1317
|
function resolveErrorMessage(payload, fallback) {
|
|
854
|
-
if (
|
|
1318
|
+
if (isRecord2(payload)) {
|
|
855
1319
|
const messageCandidates = [payload.error, payload.message, payload.details];
|
|
856
1320
|
for (const candidate of messageCandidates) {
|
|
857
1321
|
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
@@ -1041,7 +1505,7 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
1041
1505
|
};
|
|
1042
1506
|
}
|
|
1043
1507
|
const parsed = parsedBody.parsed;
|
|
1044
|
-
const parsedPayload =
|
|
1508
|
+
const parsedPayload = isRecord2(parsed) ? parsed : null;
|
|
1045
1509
|
if (!response.ok) {
|
|
1046
1510
|
const httpError = new AthenaGatewayError({
|
|
1047
1511
|
code: "HTTP_ERROR",
|
|
@@ -1249,7 +1713,7 @@ var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
|
|
|
1249
1713
|
function normalizeBaseUrl(baseUrl) {
|
|
1250
1714
|
return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
|
|
1251
1715
|
}
|
|
1252
|
-
function
|
|
1716
|
+
function isRecord3(value) {
|
|
1253
1717
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1254
1718
|
}
|
|
1255
1719
|
function normalizeHeaderValue2(value) {
|
|
@@ -1274,7 +1738,7 @@ function resolveRequestId2(headers) {
|
|
|
1274
1738
|
return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
|
|
1275
1739
|
}
|
|
1276
1740
|
function resolveErrorMessage2(payload, fallback) {
|
|
1277
|
-
if (
|
|
1741
|
+
if (isRecord3(payload)) {
|
|
1278
1742
|
const messageCandidates = [payload.error, payload.message, payload.details];
|
|
1279
1743
|
for (const candidate of messageCandidates) {
|
|
1280
1744
|
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
@@ -1627,7 +2091,7 @@ function createAuthClient(config = {}) {
|
|
|
1627
2091
|
data: null
|
|
1628
2092
|
};
|
|
1629
2093
|
}
|
|
1630
|
-
const fallbackStatus =
|
|
2094
|
+
const fallbackStatus = isRecord3(fallback.data) && typeof fallback.data.ok === "boolean" ? fallback.data.ok ? "ok" : "error" : "ok";
|
|
1631
2095
|
return {
|
|
1632
2096
|
...fallback,
|
|
1633
2097
|
data: {
|
|
@@ -2278,10 +2742,42 @@ function createAuthClient(config = {}) {
|
|
|
2278
2742
|
};
|
|
2279
2743
|
}
|
|
2280
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;
|
|
2774
|
+
}
|
|
2775
|
+
|
|
2281
2776
|
// src/client.ts
|
|
2282
2777
|
var DEFAULT_COLUMNS = "*";
|
|
2283
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;
|
|
2284
2779
|
var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
|
|
2780
|
+
var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
|
|
2285
2781
|
function formatResult(response) {
|
|
2286
2782
|
const result = {
|
|
2287
2783
|
data: response.data ?? null,
|
|
@@ -2295,6 +2791,28 @@ function formatResult(response) {
|
|
|
2295
2791
|
}
|
|
2296
2792
|
return result;
|
|
2297
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
|
+
}
|
|
2298
2816
|
function toSingleResult(response) {
|
|
2299
2817
|
const payload = response.data;
|
|
2300
2818
|
const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
|
|
@@ -2669,7 +3187,7 @@ function createRpcFilterMethods(filters, self) {
|
|
|
2669
3187
|
}
|
|
2670
3188
|
};
|
|
2671
3189
|
}
|
|
2672
|
-
function createRpcBuilder(functionName, args, baseOptions, client) {
|
|
3190
|
+
function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult) {
|
|
2673
3191
|
const state = {
|
|
2674
3192
|
filters: []
|
|
2675
3193
|
};
|
|
@@ -2691,7 +3209,7 @@ function createRpcBuilder(functionName, args, baseOptions, client) {
|
|
|
2691
3209
|
order: state.order
|
|
2692
3210
|
};
|
|
2693
3211
|
const response = await client.rpcGateway(payload, mergedOptions);
|
|
2694
|
-
return
|
|
3212
|
+
return formatGatewayResult(response, { operation: "rpc" });
|
|
2695
3213
|
};
|
|
2696
3214
|
const run = (columns, options) => {
|
|
2697
3215
|
const payloadColumns = columns ?? selectedColumns;
|
|
@@ -2745,7 +3263,7 @@ function createRpcBuilder(functionName, args, baseOptions, client) {
|
|
|
2745
3263
|
});
|
|
2746
3264
|
return builder;
|
|
2747
3265
|
}
|
|
2748
|
-
function createTableBuilder(tableName, client) {
|
|
3266
|
+
function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
2749
3267
|
const state = {
|
|
2750
3268
|
conditions: []
|
|
2751
3269
|
};
|
|
@@ -2802,7 +3320,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2802
3320
|
});
|
|
2803
3321
|
if (query) {
|
|
2804
3322
|
const queryResponse = await client.queryGateway({ query }, options);
|
|
2805
|
-
return
|
|
3323
|
+
return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
|
|
2806
3324
|
}
|
|
2807
3325
|
}
|
|
2808
3326
|
const payload = {
|
|
@@ -2820,7 +3338,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2820
3338
|
head: options?.head
|
|
2821
3339
|
};
|
|
2822
3340
|
const response = await client.fetchGateway(payload, options);
|
|
2823
|
-
return
|
|
3341
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
|
|
2824
3342
|
};
|
|
2825
3343
|
const createSelectChain = (columns, options) => {
|
|
2826
3344
|
const chain = {};
|
|
@@ -2875,7 +3393,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2875
3393
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2876
3394
|
}
|
|
2877
3395
|
const response = await client.insertGateway(payload, mergedOptions);
|
|
2878
|
-
return
|
|
3396
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2879
3397
|
};
|
|
2880
3398
|
return createMutationQuery(executeInsertMany);
|
|
2881
3399
|
}
|
|
@@ -2893,7 +3411,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2893
3411
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2894
3412
|
}
|
|
2895
3413
|
const response = await client.insertGateway(payload, mergedOptions);
|
|
2896
|
-
return
|
|
3414
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2897
3415
|
};
|
|
2898
3416
|
return createMutationQuery(executeInsertOne);
|
|
2899
3417
|
},
|
|
@@ -2915,7 +3433,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2915
3433
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2916
3434
|
}
|
|
2917
3435
|
const response = await client.insertGateway(payload, mergedOptions);
|
|
2918
|
-
return
|
|
3436
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2919
3437
|
};
|
|
2920
3438
|
return createMutationQuery(executeUpsertMany);
|
|
2921
3439
|
}
|
|
@@ -2935,7 +3453,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2935
3453
|
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2936
3454
|
}
|
|
2937
3455
|
const response = await client.insertGateway(payload, mergedOptions);
|
|
2938
|
-
return
|
|
3456
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2939
3457
|
};
|
|
2940
3458
|
return createMutationQuery(executeUpsertOne);
|
|
2941
3459
|
},
|
|
@@ -2956,7 +3474,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2956
3474
|
if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
|
|
2957
3475
|
if (columns) payload.columns = columns;
|
|
2958
3476
|
const response = await client.updateGateway(payload, mergedOptions);
|
|
2959
|
-
return
|
|
3477
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "update" });
|
|
2960
3478
|
};
|
|
2961
3479
|
const mutation = createMutationQuery(executeUpdate, null);
|
|
2962
3480
|
const updateChain = {};
|
|
@@ -2984,7 +3502,7 @@ function createTableBuilder(tableName, client) {
|
|
|
2984
3502
|
if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
|
|
2985
3503
|
if (columns) payload.columns = columns;
|
|
2986
3504
|
const response = await client.deleteGateway(payload, mergedOptions);
|
|
2987
|
-
return
|
|
3505
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "delete" });
|
|
2988
3506
|
};
|
|
2989
3507
|
return createMutationQuery(executeDelete, null);
|
|
2990
3508
|
},
|
|
@@ -2998,14 +3516,14 @@ function createTableBuilder(tableName, client) {
|
|
|
2998
3516
|
});
|
|
2999
3517
|
return builder;
|
|
3000
3518
|
}
|
|
3001
|
-
function createQueryBuilder(client) {
|
|
3519
|
+
function createQueryBuilder(client, formatGatewayResult) {
|
|
3002
3520
|
return async function query(query, options) {
|
|
3003
3521
|
const normalizedQuery = query.trim();
|
|
3004
3522
|
if (!normalizedQuery) {
|
|
3005
3523
|
throw new Error("query requires a non-empty string");
|
|
3006
3524
|
}
|
|
3007
3525
|
const response = await client.queryGateway({ query: normalizedQuery }, options);
|
|
3008
|
-
return
|
|
3526
|
+
return formatGatewayResult(response, { operation: "query" });
|
|
3009
3527
|
};
|
|
3010
3528
|
}
|
|
3011
3529
|
function createClientFromConfig(config) {
|
|
@@ -3016,24 +3534,29 @@ function createClientFromConfig(config) {
|
|
|
3016
3534
|
backend: config.backend,
|
|
3017
3535
|
headers: config.headers
|
|
3018
3536
|
});
|
|
3537
|
+
const formatGatewayResult = createResultFormatter(config.experimental);
|
|
3019
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 });
|
|
3020
3555
|
return {
|
|
3021
|
-
from
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
const normalizedFn = fn.trim();
|
|
3026
|
-
if (!normalizedFn) {
|
|
3027
|
-
throw new Error("rpc requires a function name");
|
|
3028
|
-
}
|
|
3029
|
-
return createRpcBuilder(
|
|
3030
|
-
normalizedFn,
|
|
3031
|
-
args,
|
|
3032
|
-
options,
|
|
3033
|
-
gateway
|
|
3034
|
-
);
|
|
3035
|
-
},
|
|
3036
|
-
query: createQueryBuilder(gateway),
|
|
3556
|
+
from,
|
|
3557
|
+
db,
|
|
3558
|
+
rpc,
|
|
3559
|
+
query,
|
|
3037
3560
|
auth: auth.auth
|
|
3038
3561
|
};
|
|
3039
3562
|
}
|
|
@@ -3042,77 +3565,16 @@ function toBackendConfig(b) {
|
|
|
3042
3565
|
if (!b) return DEFAULT_BACKEND;
|
|
3043
3566
|
return typeof b === "string" ? { type: b } : b;
|
|
3044
3567
|
}
|
|
3045
|
-
var AthenaClientBuilderImpl = class {
|
|
3046
|
-
baseUrl;
|
|
3047
|
-
apiKey;
|
|
3048
|
-
backendConfig = DEFAULT_BACKEND;
|
|
3049
|
-
clientName;
|
|
3050
|
-
defaultHeaders;
|
|
3051
|
-
isHealthTrackingEnabled = false;
|
|
3052
|
-
url(url) {
|
|
3053
|
-
this.baseUrl = url;
|
|
3054
|
-
return this;
|
|
3055
|
-
}
|
|
3056
|
-
key(apiKey) {
|
|
3057
|
-
this.apiKey = apiKey;
|
|
3058
|
-
return this;
|
|
3059
|
-
}
|
|
3060
|
-
backend(backend) {
|
|
3061
|
-
this.backendConfig = toBackendConfig(backend);
|
|
3062
|
-
return this;
|
|
3063
|
-
}
|
|
3064
|
-
client(clientName) {
|
|
3065
|
-
this.clientName = clientName;
|
|
3066
|
-
return this;
|
|
3067
|
-
}
|
|
3068
|
-
headers(headers) {
|
|
3069
|
-
this.defaultHeaders = headers;
|
|
3070
|
-
return this;
|
|
3071
|
-
}
|
|
3072
|
-
healthTracking(enabled) {
|
|
3073
|
-
this.isHealthTrackingEnabled = enabled;
|
|
3074
|
-
return this;
|
|
3075
|
-
}
|
|
3076
|
-
build() {
|
|
3077
|
-
if (!this.baseUrl || !this.apiKey) {
|
|
3078
|
-
throw new Error("AthenaClient requires url and key; call .url() and .key() before .build()");
|
|
3079
|
-
}
|
|
3080
|
-
return createClientFromConfig({
|
|
3081
|
-
baseUrl: this.baseUrl,
|
|
3082
|
-
apiKey: this.apiKey,
|
|
3083
|
-
client: this.clientName,
|
|
3084
|
-
backend: this.backendConfig,
|
|
3085
|
-
headers: this.defaultHeaders,
|
|
3086
|
-
healthTracking: this.isHealthTrackingEnabled
|
|
3087
|
-
});
|
|
3088
|
-
}
|
|
3089
|
-
};
|
|
3090
|
-
var AthenaClient = class _AthenaClient {
|
|
3091
|
-
/** Create a fluent builder for a strongly-typed Athena SDK client. */
|
|
3092
|
-
static builder() {
|
|
3093
|
-
return new AthenaClientBuilderImpl();
|
|
3094
|
-
}
|
|
3095
|
-
/** Build a client from process environment variables. */
|
|
3096
|
-
static fromEnvironment() {
|
|
3097
|
-
const url = process.env.ATHENA_URL ?? process.env.ATHENA_GATEWAY_URL;
|
|
3098
|
-
const key = process.env.ATHENA_API_KEY ?? process.env.ATHENA_GATEWAY_API_KEY;
|
|
3099
|
-
if (!url || !key) {
|
|
3100
|
-
throw new Error(
|
|
3101
|
-
"ATHENA_URL and ATHENA_API_KEY (or ATHENA_GATEWAY_URL and ATHENA_GATEWAY_API_KEY) are required"
|
|
3102
|
-
);
|
|
3103
|
-
}
|
|
3104
|
-
return _AthenaClient.builder().url(url).key(key).build();
|
|
3105
|
-
}
|
|
3106
|
-
};
|
|
3107
3568
|
function createClient(url, apiKey, options) {
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
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
|
+
});
|
|
3116
3578
|
}
|
|
3117
3579
|
|
|
3118
3580
|
// src/schema/postgres-introspection-core.ts
|
|
@@ -3462,6 +3924,23 @@ var PostgresCatalogSnapshotAssembler = class {
|
|
|
3462
3924
|
table.relations[key] = relation;
|
|
3463
3925
|
}
|
|
3464
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
|
+
}
|
|
3465
3944
|
var PgCatalogClient = class {
|
|
3466
3945
|
constructor(pool) {
|
|
3467
3946
|
this.pool = pool;
|
|
@@ -3501,7 +3980,8 @@ var PostgresIntrospectionProvider = class {
|
|
|
3501
3980
|
}
|
|
3502
3981
|
async inspect(options) {
|
|
3503
3982
|
const schemas = options?.schemas && options.schemas.length > 0 ? normalizePostgresCatalogSchemas(options.schemas) : this.schemas;
|
|
3504
|
-
const
|
|
3983
|
+
const PoolConstructor = await loadPgPoolConstructor();
|
|
3984
|
+
const pool = new PoolConstructor({
|
|
3505
3985
|
connectionString: this.connectionString
|
|
3506
3986
|
});
|
|
3507
3987
|
const catalogClient = new PgCatalogClient(pool);
|