@xylex-group/athena 1.9.0 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -68
- package/bin/athena-js.js +0 -0
- 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 +1839 -275
- 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 +1840 -276
- 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 +2724 -1777
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -641
- package/dist/index.d.ts +8 -641
- package/dist/index.js +2725 -1779
- package/dist/index.js.map +1 -1
- package/dist/model-form-2hqmoOUX.d.ts +1284 -0
- package/dist/model-form-Cy-zaO0u.d.cts +1284 -0
- package/dist/pipeline-BOPszLsL.d.ts +8 -0
- package/dist/pipeline-E3FDbs4W.d.cts +8 -0
- package/dist/react.cjs +93 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +38 -4
- package/dist/react.d.ts +38 -4
- package/dist/react.js +93 -1
- package/dist/react.js.map +1 -1
- 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 +36 -17
- package/dist/model-form-Bm_kqCn2.d.ts +0 -92
- package/dist/model-form-DkS48fsh.d.cts +0 -92
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var pg = require('pg');
|
|
4
3
|
var fs = require('fs');
|
|
5
4
|
var path = require('path');
|
|
6
5
|
var url = require('url');
|
|
@@ -503,1264 +502,2411 @@ function identifier(...segments) {
|
|
|
503
502
|
return new SqlIdentifierPath(expandedSegments);
|
|
504
503
|
}
|
|
505
504
|
|
|
506
|
-
// src/client.ts
|
|
507
|
-
var
|
|
508
|
-
var
|
|
509
|
-
var
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
errorDetails: response.errorDetails ?? null,
|
|
515
|
-
status: response.status,
|
|
516
|
-
raw: response.raw
|
|
517
|
-
};
|
|
518
|
-
if (response.count !== void 0) {
|
|
519
|
-
result.count = response.count;
|
|
520
|
-
}
|
|
521
|
-
return result;
|
|
505
|
+
// src/auth/client.ts
|
|
506
|
+
var DEFAULT_AUTH_BASE_URL = "http://localhost:3001/api/auth";
|
|
507
|
+
var FALLBACK_SDK_VERSION2 = "1.0.0";
|
|
508
|
+
var SDK_NAME2 = "xylex-group/athena-auth";
|
|
509
|
+
var SDK_VERSION2 = typeof process !== "undefined" && process?.env?.npm_package_version ? process.env.npm_package_version : FALLBACK_SDK_VERSION2;
|
|
510
|
+
var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
|
|
511
|
+
function normalizeBaseUrl(baseUrl) {
|
|
512
|
+
return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
|
|
522
513
|
}
|
|
523
|
-
function
|
|
524
|
-
|
|
525
|
-
const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
|
|
526
|
-
return {
|
|
527
|
-
...response,
|
|
528
|
-
data: singleData
|
|
529
|
-
};
|
|
514
|
+
function isRecord2(value) {
|
|
515
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
530
516
|
}
|
|
531
|
-
function
|
|
532
|
-
return
|
|
533
|
-
if (!next) return acc;
|
|
534
|
-
return { ...acc, ...next };
|
|
535
|
-
}, void 0);
|
|
517
|
+
function normalizeHeaderValue2(value) {
|
|
518
|
+
return value ? value : void 0;
|
|
536
519
|
}
|
|
537
|
-
function
|
|
538
|
-
|
|
520
|
+
function parseResponseBody2(rawText, contentType) {
|
|
521
|
+
if (!rawText) {
|
|
522
|
+
return { parsed: null, parseFailed: false };
|
|
523
|
+
}
|
|
524
|
+
const contentTypeSuggestsJson = contentType?.toLowerCase().includes("application/json") ?? false;
|
|
525
|
+
const looksJson = contentTypeSuggestsJson || rawText.startsWith("{") || rawText.startsWith("[");
|
|
526
|
+
if (!looksJson) {
|
|
527
|
+
return { parsed: rawText, parseFailed: false };
|
|
528
|
+
}
|
|
529
|
+
try {
|
|
530
|
+
return { parsed: JSON.parse(rawText), parseFailed: false };
|
|
531
|
+
} catch {
|
|
532
|
+
return { parsed: rawText, parseFailed: true };
|
|
533
|
+
}
|
|
539
534
|
}
|
|
540
|
-
function
|
|
541
|
-
return
|
|
535
|
+
function resolveRequestId2(headers) {
|
|
536
|
+
return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
|
|
542
537
|
}
|
|
543
|
-
function
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
if (!promise) {
|
|
551
|
-
promise = executor(payloadColumns, payloadOptions);
|
|
538
|
+
function resolveErrorMessage2(payload, fallback) {
|
|
539
|
+
if (isRecord2(payload)) {
|
|
540
|
+
const messageCandidates = [payload.error, payload.message, payload.details];
|
|
541
|
+
for (const candidate of messageCandidates) {
|
|
542
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
543
|
+
return candidate.trim();
|
|
544
|
+
}
|
|
552
545
|
}
|
|
553
|
-
|
|
546
|
+
}
|
|
547
|
+
if (typeof payload === "string" && payload.trim().length > 0) {
|
|
548
|
+
return payload.trim();
|
|
549
|
+
}
|
|
550
|
+
return fallback;
|
|
551
|
+
}
|
|
552
|
+
function toErrorDetails(input) {
|
|
553
|
+
return {
|
|
554
|
+
code: input.code,
|
|
555
|
+
message: input.message,
|
|
556
|
+
status: input.status,
|
|
557
|
+
endpoint: input.endpoint,
|
|
558
|
+
method: input.method,
|
|
559
|
+
requestId: input.requestId,
|
|
560
|
+
hint: input.hint,
|
|
561
|
+
cause: input.cause
|
|
554
562
|
};
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
single(columns = selectedColumns, options) {
|
|
565
|
-
selectedColumns = columns;
|
|
566
|
-
selectedOptions = options ?? selectedOptions;
|
|
567
|
-
return run(columns, options).then(toSingleResult);
|
|
568
|
-
},
|
|
569
|
-
maybeSingle(columns = selectedColumns, options) {
|
|
570
|
-
return mutationQuery.single(columns, options);
|
|
571
|
-
},
|
|
572
|
-
then(onfulfilled, onrejected) {
|
|
573
|
-
return run(selectedColumns, selectedOptions).then(onfulfilled, onrejected);
|
|
574
|
-
},
|
|
575
|
-
catch(onrejected) {
|
|
576
|
-
return run(selectedColumns, selectedOptions).catch(onrejected);
|
|
577
|
-
},
|
|
578
|
-
finally(onfinally) {
|
|
579
|
-
return run(selectedColumns, selectedOptions).finally(onfinally);
|
|
563
|
+
}
|
|
564
|
+
function mergeCallOptions(base, override) {
|
|
565
|
+
if (!base && !override) return void 0;
|
|
566
|
+
return {
|
|
567
|
+
...base,
|
|
568
|
+
...override,
|
|
569
|
+
headers: {
|
|
570
|
+
...base?.headers ?? {},
|
|
571
|
+
...override?.headers ?? {}
|
|
580
572
|
}
|
|
581
573
|
};
|
|
582
|
-
return mutationQuery;
|
|
583
|
-
}
|
|
584
|
-
function getResourceId(state) {
|
|
585
|
-
const candidate = state.conditions.find(
|
|
586
|
-
(condition) => condition.operator === "eq" && (condition.column === "resource_id" || condition.column === "id")
|
|
587
|
-
);
|
|
588
|
-
return candidate?.value?.toString();
|
|
589
574
|
}
|
|
590
|
-
function
|
|
591
|
-
if (
|
|
592
|
-
return
|
|
575
|
+
function extractFetchOptions(input) {
|
|
576
|
+
if (!input) {
|
|
577
|
+
return {
|
|
578
|
+
payload: void 0,
|
|
579
|
+
fetchOptions: void 0
|
|
580
|
+
};
|
|
593
581
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
return column === "id" || /(?:^|_)uuid(?:_|$)/i.test(column) || /_id$/i.test(column);
|
|
601
|
-
}
|
|
602
|
-
function shouldUseUuidTextComparison(column, value) {
|
|
603
|
-
return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
|
|
582
|
+
const { fetchOptions, ...rest } = input;
|
|
583
|
+
const hasPayloadKeys = Object.keys(rest).length > 0;
|
|
584
|
+
return {
|
|
585
|
+
payload: hasPayloadKeys ? rest : void 0,
|
|
586
|
+
fetchOptions
|
|
587
|
+
};
|
|
604
588
|
}
|
|
605
|
-
function
|
|
606
|
-
const
|
|
607
|
-
|
|
608
|
-
|
|
589
|
+
function buildHeaders2(config, options) {
|
|
590
|
+
const headers = {
|
|
591
|
+
"Content-Type": "application/json",
|
|
592
|
+
"X-Athena-Sdk": SDK_HEADER_VALUE2
|
|
593
|
+
};
|
|
594
|
+
const apiKey = options?.apiKey ?? config.apiKey;
|
|
595
|
+
if (apiKey) {
|
|
596
|
+
headers.apikey = apiKey;
|
|
597
|
+
headers["x-api-key"] = apiKey;
|
|
609
598
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
599
|
+
const bearerToken = options?.bearerToken ?? config.bearerToken;
|
|
600
|
+
if (bearerToken) {
|
|
601
|
+
headers.Authorization = `Bearer ${bearerToken}`;
|
|
602
|
+
}
|
|
603
|
+
const mergedExtraHeaders = {
|
|
604
|
+
...config.headers ?? {},
|
|
605
|
+
...options?.headers ?? {}
|
|
606
|
+
};
|
|
607
|
+
Object.entries(mergedExtraHeaders).forEach(([key, value]) => {
|
|
608
|
+
const normalized = normalizeHeaderValue2(value);
|
|
609
|
+
if (normalized) {
|
|
610
|
+
headers[key] = normalized;
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
return headers;
|
|
624
614
|
}
|
|
625
|
-
function
|
|
626
|
-
if (
|
|
627
|
-
|
|
615
|
+
function appendQueryParam(searchParams, key, value) {
|
|
616
|
+
if (value === void 0 || value === null) return;
|
|
617
|
+
if (Array.isArray(value)) {
|
|
618
|
+
value.forEach((item) => {
|
|
619
|
+
searchParams.append(key, String(item));
|
|
620
|
+
});
|
|
621
|
+
return;
|
|
628
622
|
}
|
|
629
|
-
|
|
623
|
+
searchParams.append(key, String(value));
|
|
630
624
|
}
|
|
631
|
-
function
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
625
|
+
function buildRequestUrl(baseUrl, endpoint, query) {
|
|
626
|
+
const url = `${baseUrl}${endpoint}`;
|
|
627
|
+
if (!query || Object.keys(query).length === 0) return url;
|
|
628
|
+
const searchParams = new URLSearchParams();
|
|
629
|
+
Object.entries(query).forEach(([key, value]) => appendQueryParam(searchParams, key, value));
|
|
630
|
+
const queryText = searchParams.toString();
|
|
631
|
+
return queryText ? `${url}?${queryText}` : url;
|
|
632
|
+
}
|
|
633
|
+
function inferDefaultMethod(endpoint) {
|
|
634
|
+
if (endpoint.startsWith("/reset-password/")) {
|
|
635
|
+
return "GET";
|
|
636
636
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
637
|
+
switch (endpoint) {
|
|
638
|
+
case "/get-session":
|
|
639
|
+
case "/list-sessions":
|
|
640
|
+
case "/verify-email":
|
|
641
|
+
case "/change-email/verify":
|
|
642
|
+
case "/delete-user/verify":
|
|
643
|
+
case "/email-list":
|
|
644
|
+
case "/email/list":
|
|
645
|
+
case "/delete-user/callback":
|
|
646
|
+
case "/list-accounts":
|
|
647
|
+
case "/passkey/generate-register-options":
|
|
648
|
+
case "/passkey/list-user-passkeys":
|
|
649
|
+
case "/.well-known/webauthn":
|
|
650
|
+
case "/admin/list-users":
|
|
651
|
+
case "/admin/athena-client/list":
|
|
652
|
+
case "/admin/audit-log/list":
|
|
653
|
+
case "/admin/email/get":
|
|
654
|
+
case "/admin/email-failure/list":
|
|
655
|
+
case "/admin/email-failure/get":
|
|
656
|
+
case "/admin/email-template/get":
|
|
657
|
+
case "/admin/email-template/list":
|
|
658
|
+
case "/admin/email/list":
|
|
659
|
+
case "/api-key/get":
|
|
660
|
+
case "/api-key/list":
|
|
661
|
+
case "/organization/get-full-organization":
|
|
662
|
+
case "/organization/list":
|
|
663
|
+
case "/organization/get-invitation":
|
|
664
|
+
case "/organization/list-invitations":
|
|
665
|
+
case "/organization/list-user-invitations":
|
|
666
|
+
case "/organization/list-members":
|
|
667
|
+
case "/organization/get-active-member":
|
|
668
|
+
case "/health":
|
|
669
|
+
case "/ok":
|
|
670
|
+
case "/error":
|
|
671
|
+
return "GET";
|
|
672
|
+
default:
|
|
673
|
+
return "POST";
|
|
644
674
|
}
|
|
645
|
-
return `${normalizedSchema}.${tableName}`;
|
|
646
675
|
}
|
|
647
|
-
function
|
|
648
|
-
|
|
649
|
-
const
|
|
650
|
-
const
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
lte: "<=",
|
|
658
|
-
like: "LIKE",
|
|
659
|
-
ilike: "ILIKE"
|
|
676
|
+
async function callAuthEndpoint(config, context, body, query, options) {
|
|
677
|
+
const baseUrl = normalizeBaseUrl(options?.baseUrl ?? config.baseUrl);
|
|
678
|
+
const url = buildRequestUrl(baseUrl, context.endpoint, query);
|
|
679
|
+
const headers = buildHeaders2(config, options);
|
|
680
|
+
const credentials = options?.credentials ?? config.credentials ?? "include";
|
|
681
|
+
const requestInit = {
|
|
682
|
+
method: context.method,
|
|
683
|
+
headers,
|
|
684
|
+
credentials,
|
|
685
|
+
signal: options?.signal
|
|
660
686
|
};
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
687
|
+
if (context.method !== "GET") {
|
|
688
|
+
requestInit.body = JSON.stringify(body ?? {});
|
|
689
|
+
}
|
|
690
|
+
const fetcher = config.fetch ?? globalThis.fetch;
|
|
691
|
+
if (!fetcher) {
|
|
692
|
+
const details = toErrorDetails({
|
|
693
|
+
code: "UNKNOWN_ERROR",
|
|
694
|
+
message: "No fetch implementation available for auth client",
|
|
695
|
+
status: 0,
|
|
696
|
+
endpoint: context.endpoint,
|
|
697
|
+
method: context.method,
|
|
698
|
+
hint: "Use Node 18+ or provide `fetch` via createClient(..., { auth: { fetch } }) or createAuthClient({ fetch })"
|
|
699
|
+
});
|
|
700
|
+
return {
|
|
701
|
+
ok: false,
|
|
702
|
+
status: 0,
|
|
703
|
+
data: null,
|
|
704
|
+
error: details.message,
|
|
705
|
+
errorDetails: details,
|
|
706
|
+
raw: null
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
try {
|
|
710
|
+
const response = await fetcher(url, requestInit);
|
|
711
|
+
const rawText = await response.text();
|
|
712
|
+
const requestId = resolveRequestId2(response.headers);
|
|
713
|
+
const parsedBody = parseResponseBody2(rawText ?? "", response.headers.get("content-type"));
|
|
714
|
+
if (parsedBody.parseFailed) {
|
|
715
|
+
const details = toErrorDetails({
|
|
716
|
+
code: "INVALID_JSON",
|
|
717
|
+
message: "Auth server returned malformed JSON",
|
|
718
|
+
status: response.status,
|
|
719
|
+
endpoint: context.endpoint,
|
|
720
|
+
method: context.method,
|
|
721
|
+
requestId,
|
|
722
|
+
hint: "Verify the auth endpoint response body is valid JSON.",
|
|
723
|
+
cause: rawText.slice(0, 300)
|
|
724
|
+
});
|
|
725
|
+
return {
|
|
726
|
+
ok: false,
|
|
727
|
+
status: response.status,
|
|
728
|
+
data: null,
|
|
729
|
+
error: details.message,
|
|
730
|
+
errorDetails: details,
|
|
731
|
+
raw: parsedBody.parsed
|
|
732
|
+
};
|
|
679
733
|
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
734
|
+
const parsed = parsedBody.parsed;
|
|
735
|
+
if (!response.ok) {
|
|
736
|
+
const details = toErrorDetails({
|
|
737
|
+
code: "HTTP_ERROR",
|
|
738
|
+
message: resolveErrorMessage2(
|
|
739
|
+
parsed,
|
|
740
|
+
`Auth endpoint ${context.method} ${context.endpoint} failed with status ${response.status}`
|
|
741
|
+
),
|
|
742
|
+
status: response.status,
|
|
743
|
+
endpoint: context.endpoint,
|
|
744
|
+
method: context.method,
|
|
745
|
+
requestId
|
|
746
|
+
});
|
|
747
|
+
return {
|
|
748
|
+
ok: false,
|
|
749
|
+
status: response.status,
|
|
750
|
+
data: null,
|
|
751
|
+
error: details.message,
|
|
752
|
+
errorDetails: details,
|
|
753
|
+
raw: parsed
|
|
754
|
+
};
|
|
685
755
|
}
|
|
686
|
-
|
|
687
|
-
|
|
756
|
+
return {
|
|
757
|
+
ok: true,
|
|
758
|
+
status: response.status,
|
|
759
|
+
data: parsed ?? null,
|
|
760
|
+
error: null,
|
|
761
|
+
errorDetails: null,
|
|
762
|
+
raw: parsed
|
|
763
|
+
};
|
|
764
|
+
} catch (callError) {
|
|
765
|
+
const message = callError instanceof Error ? callError.message : String(callError);
|
|
766
|
+
const details = toErrorDetails({
|
|
767
|
+
code: "NETWORK_ERROR",
|
|
768
|
+
message: `Network error while calling ${context.method} ${context.endpoint}: ${message}`,
|
|
769
|
+
status: 0,
|
|
770
|
+
endpoint: context.endpoint,
|
|
771
|
+
method: context.method,
|
|
772
|
+
cause: message,
|
|
773
|
+
hint: "Check auth server URL, DNS, and network reachability."
|
|
774
|
+
});
|
|
775
|
+
return {
|
|
776
|
+
ok: false,
|
|
777
|
+
status: 0,
|
|
778
|
+
data: null,
|
|
779
|
+
error: details.message,
|
|
780
|
+
errorDetails: details,
|
|
781
|
+
raw: null
|
|
782
|
+
};
|
|
688
783
|
}
|
|
689
784
|
}
|
|
690
|
-
function
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
if (!clause) return null;
|
|
695
|
-
whereClauses.push(clause);
|
|
696
|
-
}
|
|
697
|
-
let limit = input.limit;
|
|
698
|
-
let offset = input.offset;
|
|
699
|
-
if (limit === void 0 && input.pageSize !== void 0) {
|
|
700
|
-
limit = input.pageSize;
|
|
701
|
-
}
|
|
702
|
-
if (offset === void 0 && input.pageSize !== void 0 && input.currentPage !== void 0 && input.currentPage > 0) {
|
|
703
|
-
offset = (input.currentPage - 1) * input.pageSize;
|
|
704
|
-
}
|
|
705
|
-
const sqlParts = [
|
|
706
|
-
`SELECT ${buildSelectColumnsClause(input.columns)} FROM ${quoteQualifiedIdentifier(input.tableName)}`
|
|
707
|
-
];
|
|
708
|
-
if (whereClauses.length > 0) {
|
|
709
|
-
sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
|
|
710
|
-
}
|
|
711
|
-
if (input.order?.field) {
|
|
712
|
-
const direction = input.order.direction === "descending" ? "DESC" : "ASC";
|
|
713
|
-
sqlParts.push(`ORDER BY ${quoteQualifiedIdentifier(input.order.field)} ${direction}`);
|
|
714
|
-
}
|
|
715
|
-
if (limit !== void 0) {
|
|
716
|
-
sqlParts.push(`LIMIT ${Math.max(0, Math.trunc(limit))}`);
|
|
717
|
-
}
|
|
718
|
-
if (offset !== void 0) {
|
|
719
|
-
sqlParts.push(`OFFSET ${Math.max(0, Math.trunc(offset))}`);
|
|
720
|
-
}
|
|
721
|
-
return `${sqlParts.join(" ")};`;
|
|
785
|
+
function executePostWithCompatibleInput(config, context, input, options) {
|
|
786
|
+
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
787
|
+
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
788
|
+
return callAuthEndpoint(config, context, payload ?? {}, void 0, mergedOptions);
|
|
722
789
|
}
|
|
723
|
-
function
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
790
|
+
function executePostWithOptionalInput(config, context, input, options) {
|
|
791
|
+
const { fetchOptions } = extractFetchOptions(input);
|
|
792
|
+
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
793
|
+
return callAuthEndpoint(config, context, {}, void 0, mergedOptions);
|
|
794
|
+
}
|
|
795
|
+
function executeGetWithCompatibleInput(config, context, input, options) {
|
|
796
|
+
const { fetchOptions } = extractFetchOptions(input);
|
|
797
|
+
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
798
|
+
return callAuthEndpoint(config, context, void 0, void 0, mergedOptions);
|
|
799
|
+
}
|
|
800
|
+
function executeGetWithQueryCompatibleInput(config, context, input, options) {
|
|
801
|
+
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
802
|
+
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
803
|
+
const query = payload?.query;
|
|
804
|
+
return callAuthEndpoint(
|
|
805
|
+
config,
|
|
806
|
+
context,
|
|
807
|
+
void 0,
|
|
808
|
+
query,
|
|
809
|
+
mergedOptions
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
function createAuthClient(config = {}) {
|
|
813
|
+
const normalizedBaseUrl = normalizeBaseUrl(config.baseUrl);
|
|
814
|
+
const resolvedConfig = {
|
|
815
|
+
...config,
|
|
816
|
+
baseUrl: normalizedBaseUrl
|
|
817
|
+
};
|
|
818
|
+
const request = (input, options) => {
|
|
819
|
+
const method = input.method ?? (input.body !== void 0 ? "POST" : inferDefaultMethod(input.endpoint));
|
|
820
|
+
const mergedOptions = mergeCallOptions(input.fetchOptions, options);
|
|
821
|
+
return callAuthEndpoint(
|
|
822
|
+
resolvedConfig,
|
|
823
|
+
{ endpoint: input.endpoint, method },
|
|
824
|
+
input.body,
|
|
825
|
+
input.query,
|
|
826
|
+
mergedOptions
|
|
827
|
+
);
|
|
828
|
+
};
|
|
829
|
+
const postGeneric = (endpoint, input, options) => {
|
|
830
|
+
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
831
|
+
return request(
|
|
832
|
+
{
|
|
833
|
+
endpoint,
|
|
834
|
+
method: "POST",
|
|
835
|
+
body: payload ?? {},
|
|
836
|
+
fetchOptions
|
|
837
|
+
},
|
|
838
|
+
options
|
|
839
|
+
);
|
|
840
|
+
};
|
|
841
|
+
const getGeneric = (endpoint, input, options) => {
|
|
842
|
+
const { fetchOptions } = extractFetchOptions(input);
|
|
843
|
+
return request(
|
|
844
|
+
{
|
|
845
|
+
endpoint,
|
|
846
|
+
method: "GET",
|
|
847
|
+
fetchOptions
|
|
848
|
+
},
|
|
849
|
+
options
|
|
850
|
+
);
|
|
851
|
+
};
|
|
852
|
+
const getWithQuery = (endpoint, input, options) => {
|
|
853
|
+
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
854
|
+
const query = payload?.query;
|
|
855
|
+
return request(
|
|
856
|
+
{
|
|
857
|
+
endpoint,
|
|
858
|
+
method: "GET",
|
|
859
|
+
query,
|
|
860
|
+
fetchOptions
|
|
861
|
+
},
|
|
862
|
+
options
|
|
863
|
+
);
|
|
864
|
+
};
|
|
865
|
+
const listUserEmailsWithFallback = async (input, options) => {
|
|
866
|
+
const primary = await getWithQuery(
|
|
867
|
+
"/email/list",
|
|
868
|
+
input,
|
|
869
|
+
options
|
|
870
|
+
);
|
|
871
|
+
if (primary.ok || primary.status !== 404 || primary.errorDetails?.code !== "HTTP_ERROR") {
|
|
872
|
+
return primary;
|
|
873
|
+
}
|
|
874
|
+
return getWithQuery(
|
|
875
|
+
"/email-list",
|
|
876
|
+
input,
|
|
877
|
+
options
|
|
878
|
+
);
|
|
879
|
+
};
|
|
880
|
+
const healthWithFallback = async (input, options) => {
|
|
881
|
+
const primary = await getGeneric("/health", input, options);
|
|
882
|
+
if (primary.ok || primary.status !== 404 || primary.errorDetails?.code !== "HTTP_ERROR") {
|
|
883
|
+
return primary;
|
|
884
|
+
}
|
|
885
|
+
const fallback = await getGeneric("/ok", input, options);
|
|
886
|
+
if (!fallback.ok) {
|
|
887
|
+
return {
|
|
888
|
+
...fallback,
|
|
889
|
+
data: null
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
const fallbackStatus = isRecord2(fallback.data) && typeof fallback.data.ok === "boolean" ? fallback.data.ok ? "ok" : "error" : "ok";
|
|
893
|
+
return {
|
|
894
|
+
...fallback,
|
|
895
|
+
data: {
|
|
896
|
+
status: fallbackStatus
|
|
731
897
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
898
|
+
};
|
|
899
|
+
};
|
|
900
|
+
const signOut = (input, options) => executePostWithOptionalInput(
|
|
901
|
+
resolvedConfig,
|
|
902
|
+
{ endpoint: "/sign-out", method: "POST" },
|
|
903
|
+
input,
|
|
904
|
+
options
|
|
905
|
+
);
|
|
906
|
+
const revokeSessions = (input, options) => executePostWithOptionalInput(
|
|
907
|
+
resolvedConfig,
|
|
908
|
+
{ endpoint: "/revoke-sessions", method: "POST" },
|
|
909
|
+
input,
|
|
910
|
+
options
|
|
911
|
+
);
|
|
912
|
+
const revokeOtherSessions = (input, options) => executePostWithOptionalInput(
|
|
913
|
+
resolvedConfig,
|
|
914
|
+
{ endpoint: "/revoke-other-sessions", method: "POST" },
|
|
915
|
+
input,
|
|
916
|
+
options
|
|
917
|
+
);
|
|
918
|
+
const revokeSession = (input, options) => executePostWithCompatibleInput(
|
|
919
|
+
resolvedConfig,
|
|
920
|
+
{ endpoint: "/revoke-session", method: "POST" },
|
|
921
|
+
input,
|
|
922
|
+
options
|
|
923
|
+
);
|
|
924
|
+
const deleteUser = (input, options) => {
|
|
925
|
+
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
926
|
+
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
927
|
+
return callAuthEndpoint(
|
|
928
|
+
resolvedConfig,
|
|
929
|
+
{ endpoint: "/delete-user", method: "POST" },
|
|
930
|
+
payload ?? {},
|
|
931
|
+
void 0,
|
|
932
|
+
mergedOptions
|
|
933
|
+
);
|
|
934
|
+
};
|
|
935
|
+
const deleteUserCallback = (input, options) => {
|
|
936
|
+
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
937
|
+
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
938
|
+
const query = payload ?? {};
|
|
939
|
+
return callAuthEndpoint(
|
|
940
|
+
resolvedConfig,
|
|
941
|
+
{ endpoint: "/delete-user/callback", method: "GET" },
|
|
942
|
+
void 0,
|
|
943
|
+
{
|
|
944
|
+
token: query.token,
|
|
945
|
+
callbackURL: query.callbackURL
|
|
946
|
+
},
|
|
947
|
+
mergedOptions
|
|
948
|
+
);
|
|
949
|
+
};
|
|
950
|
+
const resolveResetPasswordToken = (input, options) => {
|
|
951
|
+
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
952
|
+
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
953
|
+
const query = payload;
|
|
954
|
+
const token = query?.token?.trim();
|
|
955
|
+
if (!token) {
|
|
956
|
+
throw new Error("resolveResetPasswordToken requires a non-empty token");
|
|
957
|
+
}
|
|
958
|
+
const endpoint = `/reset-password/${encodeURIComponent(token)}`;
|
|
959
|
+
return callAuthEndpoint(
|
|
960
|
+
resolvedConfig,
|
|
961
|
+
{ endpoint, method: "GET" },
|
|
962
|
+
void 0,
|
|
963
|
+
query?.callbackURL ? { callbackURL: query.callbackURL } : void 0,
|
|
964
|
+
mergedOptions
|
|
965
|
+
);
|
|
966
|
+
};
|
|
967
|
+
const organization = {
|
|
968
|
+
create: (input, options) => executePostWithCompatibleInput(
|
|
969
|
+
resolvedConfig,
|
|
970
|
+
{ endpoint: "/organization/create", method: "POST" },
|
|
971
|
+
input,
|
|
972
|
+
options
|
|
973
|
+
),
|
|
974
|
+
update: (input, options) => executePostWithCompatibleInput(
|
|
975
|
+
resolvedConfig,
|
|
976
|
+
{ endpoint: "/organization/update", method: "POST" },
|
|
977
|
+
input,
|
|
978
|
+
options
|
|
979
|
+
),
|
|
980
|
+
delete: (input, options) => executePostWithCompatibleInput(
|
|
981
|
+
resolvedConfig,
|
|
982
|
+
{ endpoint: "/organization/delete", method: "POST" },
|
|
983
|
+
input,
|
|
984
|
+
options
|
|
985
|
+
),
|
|
986
|
+
setActive: (input, options) => executePostWithCompatibleInput(
|
|
987
|
+
resolvedConfig,
|
|
988
|
+
{ endpoint: "/organization/set-active", method: "POST" },
|
|
989
|
+
input,
|
|
990
|
+
options
|
|
991
|
+
),
|
|
992
|
+
list: (input, options) => getGeneric(
|
|
993
|
+
"/organization/list",
|
|
994
|
+
input,
|
|
995
|
+
options
|
|
996
|
+
),
|
|
997
|
+
getFull: (input, options) => executeGetWithQueryCompatibleInput(
|
|
998
|
+
resolvedConfig,
|
|
999
|
+
{ endpoint: "/organization/get-full-organization", method: "GET" },
|
|
1000
|
+
input,
|
|
1001
|
+
options
|
|
1002
|
+
),
|
|
1003
|
+
checkSlug: (input, options) => executePostWithCompatibleInput(
|
|
1004
|
+
resolvedConfig,
|
|
1005
|
+
{ endpoint: "/organization/check-slug", method: "POST" },
|
|
1006
|
+
input,
|
|
1007
|
+
options
|
|
1008
|
+
),
|
|
1009
|
+
leave: (input, options) => executePostWithCompatibleInput(
|
|
1010
|
+
resolvedConfig,
|
|
1011
|
+
{ endpoint: "/organization/leave", method: "POST" },
|
|
1012
|
+
input,
|
|
1013
|
+
options
|
|
1014
|
+
),
|
|
1015
|
+
listUserInvitations: (input, options) => executeGetWithQueryCompatibleInput(
|
|
1016
|
+
resolvedConfig,
|
|
1017
|
+
{ endpoint: "/organization/list-user-invitations", method: "GET" },
|
|
1018
|
+
input,
|
|
1019
|
+
options
|
|
1020
|
+
),
|
|
1021
|
+
hasPermission: (input, options) => postGeneric(
|
|
1022
|
+
"/organization/has-permission",
|
|
1023
|
+
input,
|
|
1024
|
+
options
|
|
1025
|
+
),
|
|
1026
|
+
invitation: {
|
|
1027
|
+
cancel: (input, options) => executePostWithCompatibleInput(
|
|
1028
|
+
resolvedConfig,
|
|
1029
|
+
{ endpoint: "/organization/cancel-invitation", method: "POST" },
|
|
1030
|
+
input,
|
|
1031
|
+
options
|
|
1032
|
+
),
|
|
1033
|
+
accept: (input, options) => executePostWithCompatibleInput(
|
|
1034
|
+
resolvedConfig,
|
|
1035
|
+
{ endpoint: "/organization/accept-invitation", method: "POST" },
|
|
1036
|
+
input,
|
|
1037
|
+
options
|
|
1038
|
+
),
|
|
1039
|
+
get: (input, options) => executeGetWithQueryCompatibleInput(
|
|
1040
|
+
resolvedConfig,
|
|
1041
|
+
{ endpoint: "/organization/get-invitation", method: "GET" },
|
|
1042
|
+
input,
|
|
1043
|
+
options
|
|
1044
|
+
),
|
|
1045
|
+
reject: (input, options) => executePostWithCompatibleInput(
|
|
1046
|
+
resolvedConfig,
|
|
1047
|
+
{ endpoint: "/organization/reject-invitation", method: "POST" },
|
|
1048
|
+
input,
|
|
1049
|
+
options
|
|
1050
|
+
),
|
|
1051
|
+
list: (input, options) => executeGetWithQueryCompatibleInput(
|
|
1052
|
+
resolvedConfig,
|
|
1053
|
+
{ endpoint: "/organization/list-invitations", method: "GET" },
|
|
1054
|
+
input,
|
|
1055
|
+
options
|
|
1056
|
+
)
|
|
754
1057
|
},
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
1058
|
+
member: {
|
|
1059
|
+
remove: (input, options) => executePostWithCompatibleInput(
|
|
1060
|
+
resolvedConfig,
|
|
1061
|
+
{ endpoint: "/organization/remove-member", method: "POST" },
|
|
1062
|
+
input,
|
|
1063
|
+
options
|
|
1064
|
+
),
|
|
1065
|
+
updateRole: (input, options) => executePostWithCompatibleInput(
|
|
1066
|
+
resolvedConfig,
|
|
1067
|
+
{ endpoint: "/organization/update-member-role", method: "POST" },
|
|
1068
|
+
input,
|
|
1069
|
+
options
|
|
1070
|
+
),
|
|
1071
|
+
invite: (input, options) => executePostWithCompatibleInput(
|
|
1072
|
+
resolvedConfig,
|
|
1073
|
+
{ endpoint: "/organization/invite-member", method: "POST" },
|
|
1074
|
+
input,
|
|
1075
|
+
options
|
|
1076
|
+
),
|
|
1077
|
+
getActive: (input, options) => executeGetWithCompatibleInput(
|
|
1078
|
+
resolvedConfig,
|
|
1079
|
+
{ endpoint: "/organization/get-active-member", method: "GET" },
|
|
1080
|
+
input,
|
|
1081
|
+
options
|
|
1082
|
+
),
|
|
1083
|
+
list: (input, options) => executeGetWithQueryCompatibleInput(
|
|
1084
|
+
resolvedConfig,
|
|
1085
|
+
{ endpoint: "/organization/list-members", method: "GET" },
|
|
1086
|
+
input,
|
|
1087
|
+
options
|
|
1088
|
+
)
|
|
1089
|
+
}
|
|
1090
|
+
};
|
|
1091
|
+
const authResetPassword = Object.assign(
|
|
1092
|
+
(input, options) => executePostWithCompatibleInput(
|
|
1093
|
+
resolvedConfig,
|
|
1094
|
+
{ endpoint: "/reset-password", method: "POST" },
|
|
1095
|
+
input,
|
|
1096
|
+
options
|
|
1097
|
+
),
|
|
1098
|
+
{
|
|
1099
|
+
token: resolveResetPasswordToken
|
|
1100
|
+
}
|
|
1101
|
+
);
|
|
1102
|
+
const sessionRevokeBinding = (input, options) => {
|
|
1103
|
+
if (Array.isArray(input)) {
|
|
1104
|
+
if (input.length === 0) {
|
|
1105
|
+
throw new Error("session.revoke requires at least one session token");
|
|
1106
|
+
}
|
|
1107
|
+
if (input.length === 1) {
|
|
1108
|
+
return revokeSession(input[0], options);
|
|
1109
|
+
}
|
|
1110
|
+
return revokeSessions(void 0, options);
|
|
1111
|
+
}
|
|
1112
|
+
const parsed = input;
|
|
1113
|
+
const tokens = Array.isArray(parsed.tokens) ? parsed.tokens.filter((token2) => token2.trim().length > 0) : void 0;
|
|
1114
|
+
if (tokens && tokens.length > 1) {
|
|
1115
|
+
return revokeSessions(
|
|
1116
|
+
parsed.fetchOptions ? { fetchOptions: parsed.fetchOptions } : void 0,
|
|
1117
|
+
options
|
|
1118
|
+
);
|
|
1119
|
+
}
|
|
1120
|
+
if (tokens && tokens.length === 1) {
|
|
1121
|
+
return revokeSession(
|
|
1122
|
+
{ token: tokens[0], fetchOptions: parsed.fetchOptions },
|
|
1123
|
+
options
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
const token = parsed.token?.trim();
|
|
1127
|
+
if (!token) {
|
|
1128
|
+
throw new Error("session.revoke requires a non-empty token or a non-empty token list");
|
|
1129
|
+
}
|
|
1130
|
+
return revokeSession(
|
|
1131
|
+
{
|
|
1132
|
+
token,
|
|
1133
|
+
fetchOptions: parsed.fetchOptions
|
|
1134
|
+
},
|
|
1135
|
+
options
|
|
1136
|
+
);
|
|
1137
|
+
};
|
|
1138
|
+
const adminUserSessionRevokeBinding = (input, options) => {
|
|
1139
|
+
const requireUserId = (userId) => {
|
|
1140
|
+
const trimmed = String(userId ?? "").trim();
|
|
1141
|
+
if (!trimmed) {
|
|
1142
|
+
throw new Error("admin.user.session.revoke requires a non-empty userId");
|
|
1143
|
+
}
|
|
1144
|
+
return trimmed;
|
|
1145
|
+
};
|
|
1146
|
+
const requireSinglePluralUserId = (sessions2) => {
|
|
1147
|
+
const uniqueUserIds = [...new Set(sessions2.map((session) => requireUserId(session.userId)))];
|
|
1148
|
+
if (uniqueUserIds.length !== 1) {
|
|
1149
|
+
throw new Error("admin.user.session.revoke requires the same userId across plural payloads");
|
|
1150
|
+
}
|
|
1151
|
+
return { userId: uniqueUserIds[0] };
|
|
1152
|
+
};
|
|
1153
|
+
if (Array.isArray(input)) {
|
|
1154
|
+
if (input.length === 0) {
|
|
1155
|
+
throw new Error("admin.user.session.revoke requires at least one payload item");
|
|
1156
|
+
}
|
|
1157
|
+
if (input.length === 1) {
|
|
1158
|
+
return postGeneric(
|
|
1159
|
+
"/admin/revoke-user-session",
|
|
1160
|
+
{
|
|
1161
|
+
...input[0],
|
|
1162
|
+
userId: requireUserId(input[0].userId)
|
|
1163
|
+
},
|
|
1164
|
+
options
|
|
1165
|
+
);
|
|
1166
|
+
}
|
|
1167
|
+
return postGeneric(
|
|
1168
|
+
"/admin/revoke-user-sessions",
|
|
1169
|
+
requireSinglePluralUserId(input),
|
|
1170
|
+
options
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
1173
|
+
const parsed = input;
|
|
1174
|
+
const sessions = parsed.sessions;
|
|
1175
|
+
if (sessions && sessions.length === 0) {
|
|
1176
|
+
throw new Error("admin.user.session.revoke requires at least one payload item");
|
|
1177
|
+
}
|
|
1178
|
+
if (sessions && sessions.length === 1) {
|
|
1179
|
+
return postGeneric(
|
|
1180
|
+
"/admin/revoke-user-session",
|
|
1181
|
+
{
|
|
1182
|
+
...sessions[0],
|
|
1183
|
+
userId: requireUserId(sessions[0].userId),
|
|
1184
|
+
fetchOptions: parsed.fetchOptions
|
|
1185
|
+
},
|
|
1186
|
+
options
|
|
1187
|
+
);
|
|
1188
|
+
}
|
|
1189
|
+
if (sessions && sessions.length > 1) {
|
|
1190
|
+
return postGeneric(
|
|
1191
|
+
"/admin/revoke-user-sessions",
|
|
1192
|
+
{
|
|
1193
|
+
...requireSinglePluralUserId(sessions),
|
|
1194
|
+
fetchOptions: parsed.fetchOptions
|
|
1195
|
+
},
|
|
1196
|
+
options
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1199
|
+
const normalizedUserId = requireUserId(parsed.userId);
|
|
1200
|
+
if (!parsed.sessionToken) {
|
|
1201
|
+
return postGeneric(
|
|
1202
|
+
"/admin/revoke-user-sessions",
|
|
1203
|
+
{
|
|
1204
|
+
userId: normalizedUserId,
|
|
1205
|
+
fetchOptions: parsed.fetchOptions
|
|
1206
|
+
},
|
|
1207
|
+
options
|
|
1208
|
+
);
|
|
1209
|
+
}
|
|
1210
|
+
return postGeneric(
|
|
1211
|
+
"/admin/revoke-user-session",
|
|
1212
|
+
{
|
|
1213
|
+
...parsed,
|
|
1214
|
+
userId: normalizedUserId
|
|
1215
|
+
},
|
|
1216
|
+
options
|
|
1217
|
+
);
|
|
1218
|
+
};
|
|
1219
|
+
const auth = {
|
|
1220
|
+
getSession: (input, options) => getGeneric("/get-session", input, options),
|
|
1221
|
+
signOut,
|
|
1222
|
+
forgetPassword: (input, options) => postGeneric("/forget-password", input, options),
|
|
1223
|
+
resetPassword: authResetPassword,
|
|
1224
|
+
setPassword: (input, options) => postGeneric("/set-password", input, options),
|
|
1225
|
+
verifyEmail: (input, options) => {
|
|
1226
|
+
const queryInput = {
|
|
1227
|
+
query: {
|
|
1228
|
+
token: input.token,
|
|
1229
|
+
callbackURL: input.callbackURL
|
|
1230
|
+
},
|
|
1231
|
+
fetchOptions: input.fetchOptions
|
|
1232
|
+
};
|
|
1233
|
+
return getWithQuery(
|
|
1234
|
+
"/verify-email",
|
|
1235
|
+
queryInput,
|
|
1236
|
+
options
|
|
1237
|
+
);
|
|
759
1238
|
},
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
1239
|
+
sendVerificationEmail: (input, options) => postGeneric("/send-verification-email", input, options),
|
|
1240
|
+
changeEmail: (input, options) => postGeneric("/change-email", input, options),
|
|
1241
|
+
changeEmailVerify: (input, options) => getWithQuery("/change-email/verify", input, options),
|
|
1242
|
+
deleteUserVerify: (input, options) => getWithQuery("/delete-user/verify", input, options),
|
|
1243
|
+
changePassword: (input, options) => postGeneric("/change-password", input, options),
|
|
1244
|
+
user: {
|
|
1245
|
+
update: (input, options) => postGeneric("/update-user", input, options),
|
|
1246
|
+
delete: (input, options) => postGeneric("/delete-user", input, options),
|
|
1247
|
+
email: {
|
|
1248
|
+
list: listUserEmailsWithFallback
|
|
1249
|
+
}
|
|
763
1250
|
},
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
1251
|
+
session: {
|
|
1252
|
+
list: (input, options) => getGeneric("/list-sessions", input, options),
|
|
1253
|
+
revoke: sessionRevokeBinding,
|
|
1254
|
+
revokeOther: revokeOtherSessions
|
|
767
1255
|
},
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
return self;
|
|
1256
|
+
social: {
|
|
1257
|
+
link: (input, options) => postGeneric("/link-social", input, options)
|
|
771
1258
|
},
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
1259
|
+
account: {
|
|
1260
|
+
list: (input, options) => getGeneric("/list-accounts", input, options),
|
|
1261
|
+
unlink: (input, options) => postGeneric("/unlink-account", input, options)
|
|
775
1262
|
},
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
return self;
|
|
1263
|
+
deleteUser: {
|
|
1264
|
+
callback: deleteUserCallback
|
|
779
1265
|
},
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
1266
|
+
refreshToken: (input, options) => postGeneric("/refresh-token", input, options),
|
|
1267
|
+
getAccessToken: (input, options) => postGeneric("/get-access-token", input, options),
|
|
1268
|
+
health: healthWithFallback,
|
|
1269
|
+
ok: (input, options) => getGeneric("/ok", input, options),
|
|
1270
|
+
error: (input, options) => getGeneric("/error", input, options),
|
|
1271
|
+
twoFactor: {
|
|
1272
|
+
getTotpUri: (input, options) => postGeneric("/two-factor/get-totp-uri", input, options),
|
|
1273
|
+
verifyTotp: (input, options) => postGeneric("/two-factor/verify-totp", input, options),
|
|
1274
|
+
sendOtp: (input, options) => postGeneric("/two-factor/send-otp", input, options),
|
|
1275
|
+
verifyOtp: (input, options) => postGeneric("/two-factor/verify-otp", input, options),
|
|
1276
|
+
verifyBackupCode: (input, options) => postGeneric("/two-factor/verify-backup-code", input, options),
|
|
1277
|
+
generateBackupCodes: (input, options) => executePostWithCompatibleInput(
|
|
1278
|
+
resolvedConfig,
|
|
1279
|
+
{ endpoint: "/two-factor/generate-backup-codes", method: "POST" },
|
|
1280
|
+
input,
|
|
1281
|
+
options
|
|
1282
|
+
),
|
|
1283
|
+
enable: (input, options) => postGeneric("/two-factor/enable", input, options),
|
|
1284
|
+
disable: (input, options) => postGeneric("/two-factor/disable", input, options)
|
|
786
1285
|
},
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
1286
|
+
passkey: {
|
|
1287
|
+
generateRegisterOptions: (input, options) => getGeneric("/passkey/generate-register-options", input, options),
|
|
1288
|
+
generateAuthenticateOptions: (input, options) => postGeneric("/passkey/generate-authenticate-options", input, options),
|
|
1289
|
+
verifyRegistration: (input, options) => postGeneric("/passkey/verify-registration", input, options),
|
|
1290
|
+
verifyAuthentication: (input, options) => postGeneric("/passkey/verify-authentication", input, options),
|
|
1291
|
+
listUserPasskeys: (input, options) => getGeneric("/passkey/list-user-passkeys", input, options),
|
|
1292
|
+
deletePasskey: (input, options) => postGeneric("/passkey/delete-passkey", input, options),
|
|
1293
|
+
updatePasskey: (input, options) => postGeneric("/passkey/update-passkey", input, options),
|
|
1294
|
+
getRelatedOrigins: (input, options) => getGeneric("/.well-known/webauthn", input, options)
|
|
790
1295
|
},
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
1296
|
+
admin: {
|
|
1297
|
+
role: {
|
|
1298
|
+
set: (input, options) => postGeneric("/admin/set-role", input, options)
|
|
1299
|
+
},
|
|
1300
|
+
user: {
|
|
1301
|
+
list: (input, options) => getWithQuery("/admin/list-users", input, options),
|
|
1302
|
+
create: (input, options) => postGeneric("/admin/create-user", input, options),
|
|
1303
|
+
unban: (input, options) => postGeneric("/admin/unban-user", input, options),
|
|
1304
|
+
ban: (input, options) => postGeneric("/admin/ban-user", input, options),
|
|
1305
|
+
impersonate: (input, options) => postGeneric("/admin/impersonate-user", input, options),
|
|
1306
|
+
stopImpersonating: (input, options) => postGeneric("/admin/stop-impersonating", input, options),
|
|
1307
|
+
remove: (input, options) => postGeneric("/admin/remove-user", input, options),
|
|
1308
|
+
setPassword: (input, options) => postGeneric("/admin/set-user-password", input, options),
|
|
1309
|
+
session: {
|
|
1310
|
+
list: (input, options) => postGeneric("/admin/list-user-sessions", input, options),
|
|
1311
|
+
revoke: adminUserSessionRevokeBinding
|
|
1312
|
+
}
|
|
1313
|
+
},
|
|
1314
|
+
hasPermission: (input, options) => postGeneric("/admin/has-permission", input, options),
|
|
1315
|
+
apiKey: {
|
|
1316
|
+
create: (input, options) => postGeneric("/admin/api-key/create", input, options)
|
|
1317
|
+
},
|
|
1318
|
+
athenaClient: {
|
|
1319
|
+
create: (input, options) => postGeneric("/admin/athena-client/create", input, options),
|
|
1320
|
+
list: (input, options) => getWithQuery("/admin/athena-client/list", input, options)
|
|
1321
|
+
},
|
|
1322
|
+
auditLog: {
|
|
1323
|
+
list: (input, options) => getWithQuery("/admin/audit-log/list", input, options)
|
|
1324
|
+
},
|
|
1325
|
+
email: {
|
|
1326
|
+
list: (input, options) => getWithQuery("/admin/email/list", input, options),
|
|
1327
|
+
get: (input, options) => getWithQuery("/admin/email/get", input, options),
|
|
1328
|
+
create: (input, options) => postGeneric("/admin/email/create", input, options),
|
|
1329
|
+
update: (input, options) => postGeneric("/admin/email/update", input, options),
|
|
1330
|
+
delete: (input, options) => postGeneric("/admin/email/delete", input, options),
|
|
1331
|
+
failure: {
|
|
1332
|
+
list: (input, options) => getWithQuery("/admin/email-failure/list", input, options),
|
|
1333
|
+
get: (input, options) => getWithQuery("/admin/email-failure/get", input, options),
|
|
1334
|
+
create: (input, options) => postGeneric("/admin/email-failure/create", input, options),
|
|
1335
|
+
update: (input, options) => postGeneric("/admin/email-failure/update", input, options),
|
|
1336
|
+
delete: (input, options) => postGeneric("/admin/email-failure/delete", input, options)
|
|
1337
|
+
},
|
|
1338
|
+
template: {
|
|
1339
|
+
list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
|
|
1340
|
+
get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
|
|
1341
|
+
create: (input, options) => postGeneric("/admin/email-template/create", input, options),
|
|
1342
|
+
update: (input, options) => postGeneric("/admin/email-template/update", input, options),
|
|
1343
|
+
delete: (input, options) => postGeneric("/admin/email-template/delete", input, options)
|
|
1344
|
+
}
|
|
1345
|
+
},
|
|
1346
|
+
emailTemplate: {
|
|
1347
|
+
get: (input, options) => getWithQuery("/admin/email-template/get", input, options),
|
|
1348
|
+
create: (input, options) => postGeneric("/admin/email-template/create", input, options),
|
|
1349
|
+
delete: (input, options) => postGeneric("/admin/email-template/delete", input, options),
|
|
1350
|
+
list: (input, options) => getWithQuery("/admin/email-template/list", input, options),
|
|
1351
|
+
update: (input, options) => postGeneric("/admin/email-template/update", input, options)
|
|
1352
|
+
}
|
|
794
1353
|
},
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
addCondition("like", String(column), value);
|
|
809
|
-
return self;
|
|
810
|
-
},
|
|
811
|
-
ilike(column, value) {
|
|
812
|
-
addCondition("ilike", String(column), value);
|
|
813
|
-
return self;
|
|
814
|
-
},
|
|
815
|
-
is(column, value) {
|
|
816
|
-
addCondition("is", String(column), value);
|
|
817
|
-
return self;
|
|
818
|
-
},
|
|
819
|
-
in(column, values) {
|
|
820
|
-
addCondition("in", String(column), values);
|
|
821
|
-
return self;
|
|
1354
|
+
apiKey: {
|
|
1355
|
+
create: (input, options) => postGeneric("/api-key/create", input, options),
|
|
1356
|
+
get: (input, options) => getWithQuery("/api-key/get", input, options),
|
|
1357
|
+
update: (input, options) => postGeneric("/api-key/update", input, options),
|
|
1358
|
+
delete: (input, options) => postGeneric("/api-key/delete", input, options),
|
|
1359
|
+
list: (input, options) => getWithQuery("/api-key/list", input, options),
|
|
1360
|
+
verify: (input, options) => postGeneric("/api-key/verify", input, options),
|
|
1361
|
+
deleteAllExpired: (input, options) => executePostWithOptionalInput(
|
|
1362
|
+
resolvedConfig,
|
|
1363
|
+
{ endpoint: "/api-key/delete-all-expired-api-keys", method: "POST" },
|
|
1364
|
+
input,
|
|
1365
|
+
options
|
|
1366
|
+
)
|
|
822
1367
|
},
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
1368
|
+
signIn: {
|
|
1369
|
+
email: (input, options) => postGeneric("/sign-in/email", input, options),
|
|
1370
|
+
username: (input, options) => postGeneric("/sign-in/username", input, options),
|
|
1371
|
+
social: (input, options) => postGeneric("/sign-in/social", input, options)
|
|
826
1372
|
},
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
return self;
|
|
1373
|
+
signUp: {
|
|
1374
|
+
email: (input, options) => postGeneric("/sign-up/email", input, options)
|
|
830
1375
|
},
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
1376
|
+
organization,
|
|
1377
|
+
callback: {
|
|
1378
|
+
provider: (input, options) => {
|
|
1379
|
+
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
1380
|
+
const parsed = payload;
|
|
1381
|
+
const provider = String(parsed?.provider ?? "").trim();
|
|
1382
|
+
if (!provider) {
|
|
1383
|
+
throw new Error("callback.provider requires a non-empty provider value");
|
|
1384
|
+
}
|
|
1385
|
+
const code = String(parsed?.code ?? "").trim();
|
|
1386
|
+
const state = String(parsed?.state ?? "").trim();
|
|
1387
|
+
if (!code || !state) {
|
|
1388
|
+
throw new Error("callback.provider requires non-empty code and state values");
|
|
1389
|
+
}
|
|
1390
|
+
const endpoint = `/callback/${encodeURIComponent(provider)}`;
|
|
1391
|
+
return request({
|
|
1392
|
+
endpoint,
|
|
1393
|
+
method: "GET",
|
|
1394
|
+
query: {
|
|
1395
|
+
code,
|
|
1396
|
+
state
|
|
1397
|
+
},
|
|
1398
|
+
fetchOptions
|
|
1399
|
+
}, options);
|
|
837
1400
|
}
|
|
838
|
-
return self;
|
|
839
|
-
},
|
|
840
|
-
or(expression) {
|
|
841
|
-
addCondition("or", void 0, expression);
|
|
842
|
-
return self;
|
|
843
1401
|
}
|
|
844
1402
|
};
|
|
845
|
-
}
|
|
846
|
-
function toRpcSelect(columns) {
|
|
847
|
-
if (!columns) return void 0;
|
|
848
|
-
return Array.isArray(columns) ? columns.join(",") : columns;
|
|
849
|
-
}
|
|
850
|
-
function createRpcFilterMethods(filters, self) {
|
|
851
|
-
const addFilter = (operator, column, value) => {
|
|
852
|
-
filters.push({ column, operator, value });
|
|
853
|
-
};
|
|
854
1403
|
return {
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
addFilter("lte", column, value);
|
|
877
|
-
return self;
|
|
878
|
-
},
|
|
879
|
-
like(column, value) {
|
|
880
|
-
addFilter("like", column, value);
|
|
881
|
-
return self;
|
|
1404
|
+
baseUrl: normalizedBaseUrl,
|
|
1405
|
+
request,
|
|
1406
|
+
signIn: {
|
|
1407
|
+
email: (input, options) => executePostWithCompatibleInput(
|
|
1408
|
+
resolvedConfig,
|
|
1409
|
+
{ endpoint: "/sign-in/email", method: "POST" },
|
|
1410
|
+
input,
|
|
1411
|
+
options
|
|
1412
|
+
),
|
|
1413
|
+
username: (input, options) => executePostWithCompatibleInput(
|
|
1414
|
+
resolvedConfig,
|
|
1415
|
+
{ endpoint: "/sign-in/username", method: "POST" },
|
|
1416
|
+
input,
|
|
1417
|
+
options
|
|
1418
|
+
),
|
|
1419
|
+
social: (input, options) => executePostWithCompatibleInput(
|
|
1420
|
+
resolvedConfig,
|
|
1421
|
+
{ endpoint: "/sign-in/social", method: "POST" },
|
|
1422
|
+
input,
|
|
1423
|
+
options
|
|
1424
|
+
)
|
|
882
1425
|
},
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
1426
|
+
signUp: {
|
|
1427
|
+
email: (input, options) => executePostWithCompatibleInput(
|
|
1428
|
+
resolvedConfig,
|
|
1429
|
+
{ endpoint: "/sign-up/email", method: "POST" },
|
|
1430
|
+
input,
|
|
1431
|
+
options
|
|
1432
|
+
)
|
|
886
1433
|
},
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
1434
|
+
signOut,
|
|
1435
|
+
logout: signOut,
|
|
1436
|
+
getSession: (input, options) => executeGetWithCompatibleInput(
|
|
1437
|
+
resolvedConfig,
|
|
1438
|
+
{ endpoint: "/get-session", method: "GET" },
|
|
1439
|
+
input,
|
|
1440
|
+
options
|
|
1441
|
+
),
|
|
1442
|
+
listSessions: (input, options) => executeGetWithCompatibleInput(
|
|
1443
|
+
resolvedConfig,
|
|
1444
|
+
{ endpoint: "/list-sessions", method: "GET" },
|
|
1445
|
+
input,
|
|
1446
|
+
options
|
|
1447
|
+
),
|
|
1448
|
+
revokeSession,
|
|
1449
|
+
clearSession: revokeSession,
|
|
1450
|
+
revokeSessions,
|
|
1451
|
+
clearSessions: revokeSessions,
|
|
1452
|
+
revokeOtherSessions,
|
|
1453
|
+
clearOtherSessions: revokeOtherSessions,
|
|
1454
|
+
forgetPassword: (input, options) => executePostWithCompatibleInput(
|
|
1455
|
+
resolvedConfig,
|
|
1456
|
+
{ endpoint: "/forget-password", method: "POST" },
|
|
1457
|
+
input,
|
|
1458
|
+
options
|
|
1459
|
+
),
|
|
1460
|
+
resetPassword: (input, options) => executePostWithCompatibleInput(
|
|
1461
|
+
resolvedConfig,
|
|
1462
|
+
{ endpoint: "/reset-password", method: "POST" },
|
|
1463
|
+
input,
|
|
1464
|
+
options
|
|
1465
|
+
),
|
|
1466
|
+
resolveResetPasswordToken,
|
|
1467
|
+
verifyEmail: (input, options) => {
|
|
1468
|
+
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
1469
|
+
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
1470
|
+
const query = payload;
|
|
1471
|
+
return callAuthEndpoint(
|
|
1472
|
+
resolvedConfig,
|
|
1473
|
+
{ endpoint: "/verify-email", method: "GET" },
|
|
1474
|
+
void 0,
|
|
1475
|
+
query ? {
|
|
1476
|
+
token: query.token,
|
|
1477
|
+
callbackURL: query.callbackURL
|
|
1478
|
+
} : void 0,
|
|
1479
|
+
mergedOptions
|
|
1480
|
+
);
|
|
890
1481
|
},
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1482
|
+
sendVerificationEmail: (input, options) => executePostWithCompatibleInput(
|
|
1483
|
+
resolvedConfig,
|
|
1484
|
+
{ endpoint: "/send-verification-email", method: "POST" },
|
|
1485
|
+
input,
|
|
1486
|
+
options
|
|
1487
|
+
),
|
|
1488
|
+
changeEmail: (input, options) => executePostWithCompatibleInput(
|
|
1489
|
+
resolvedConfig,
|
|
1490
|
+
{ endpoint: "/change-email", method: "POST" },
|
|
1491
|
+
input,
|
|
1492
|
+
options
|
|
1493
|
+
),
|
|
1494
|
+
changePassword: (input, options) => executePostWithCompatibleInput(
|
|
1495
|
+
resolvedConfig,
|
|
1496
|
+
{ endpoint: "/change-password", method: "POST" },
|
|
1497
|
+
input,
|
|
1498
|
+
options
|
|
1499
|
+
),
|
|
1500
|
+
updateUser: (input, options) => executePostWithCompatibleInput(
|
|
1501
|
+
resolvedConfig,
|
|
1502
|
+
{ endpoint: "/update-user", method: "POST" },
|
|
1503
|
+
input,
|
|
1504
|
+
options
|
|
1505
|
+
),
|
|
1506
|
+
deleteUser,
|
|
1507
|
+
deleteUserCallback,
|
|
1508
|
+
linkSocial: (input, options) => executePostWithCompatibleInput(
|
|
1509
|
+
resolvedConfig,
|
|
1510
|
+
{ endpoint: "/link-social", method: "POST" },
|
|
1511
|
+
input,
|
|
1512
|
+
options
|
|
1513
|
+
),
|
|
1514
|
+
listAccounts: (input, options) => executeGetWithCompatibleInput(
|
|
1515
|
+
resolvedConfig,
|
|
1516
|
+
{ endpoint: "/list-accounts", method: "GET" },
|
|
1517
|
+
input,
|
|
1518
|
+
options
|
|
1519
|
+
),
|
|
1520
|
+
unlinkAccount: (input, options) => executePostWithCompatibleInput(
|
|
1521
|
+
resolvedConfig,
|
|
1522
|
+
{ endpoint: "/unlink-account", method: "POST" },
|
|
1523
|
+
input,
|
|
1524
|
+
options
|
|
1525
|
+
),
|
|
1526
|
+
refreshToken: (input, options) => executePostWithCompatibleInput(
|
|
1527
|
+
resolvedConfig,
|
|
1528
|
+
{ endpoint: "/refresh-token", method: "POST" },
|
|
1529
|
+
input,
|
|
1530
|
+
options
|
|
1531
|
+
),
|
|
1532
|
+
getAccessToken: (input, options) => executePostWithCompatibleInput(
|
|
1533
|
+
resolvedConfig,
|
|
1534
|
+
{ endpoint: "/get-access-token", method: "POST" },
|
|
1535
|
+
input,
|
|
1536
|
+
options
|
|
1537
|
+
),
|
|
1538
|
+
organization,
|
|
1539
|
+
auth
|
|
895
1540
|
};
|
|
896
1541
|
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
const
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
async single(columns, options) {
|
|
938
|
-
const result = await run(columns, options);
|
|
939
|
-
return toSingleResult(result);
|
|
940
|
-
},
|
|
941
|
-
maybeSingle(columns, options) {
|
|
942
|
-
return builder.single(columns, options);
|
|
943
|
-
},
|
|
944
|
-
order(column, options) {
|
|
945
|
-
state.order = { column, ascending: options?.ascending ?? true };
|
|
946
|
-
return builder;
|
|
947
|
-
},
|
|
948
|
-
limit(count) {
|
|
949
|
-
state.limit = count;
|
|
950
|
-
return builder;
|
|
951
|
-
},
|
|
952
|
-
offset(count) {
|
|
953
|
-
state.offset = count;
|
|
954
|
-
return builder;
|
|
955
|
-
},
|
|
956
|
-
range(from, to) {
|
|
957
|
-
state.offset = from;
|
|
958
|
-
state.limit = to - from + 1;
|
|
959
|
-
return builder;
|
|
960
|
-
},
|
|
961
|
-
then(onfulfilled, onrejected) {
|
|
962
|
-
return run(selectedColumns, selectedOptions).then(onfulfilled, onrejected);
|
|
963
|
-
},
|
|
964
|
-
catch(onrejected) {
|
|
965
|
-
return run(selectedColumns, selectedOptions).catch(onrejected);
|
|
966
|
-
},
|
|
967
|
-
finally(onfinally) {
|
|
968
|
-
return run(selectedColumns, selectedOptions).finally(onfinally);
|
|
969
|
-
}
|
|
970
|
-
});
|
|
971
|
-
return builder;
|
|
1542
|
+
|
|
1543
|
+
// src/auxiliaries.ts
|
|
1544
|
+
var AthenaErrorKind = {
|
|
1545
|
+
UniqueViolation: "unique_violation",
|
|
1546
|
+
NotFound: "not_found",
|
|
1547
|
+
Validation: "validation",
|
|
1548
|
+
Auth: "auth",
|
|
1549
|
+
RateLimit: "rate_limit",
|
|
1550
|
+
Transient: "transient",
|
|
1551
|
+
Unknown: "unknown"
|
|
1552
|
+
};
|
|
1553
|
+
var AthenaErrorCode = {
|
|
1554
|
+
UniqueViolation: "UNIQUE_VIOLATION",
|
|
1555
|
+
NotFound: "NOT_FOUND",
|
|
1556
|
+
ValidationFailed: "VALIDATION_FAILED",
|
|
1557
|
+
AuthUnauthorized: "AUTH_UNAUTHORIZED",
|
|
1558
|
+
AuthForbidden: "AUTH_FORBIDDEN",
|
|
1559
|
+
RateLimited: "RATE_LIMITED",
|
|
1560
|
+
NetworkUnavailable: "NETWORK_UNAVAILABLE",
|
|
1561
|
+
TransientFailure: "TRANSIENT_FAILURE",
|
|
1562
|
+
HttpFailure: "HTTP_FAILURE",
|
|
1563
|
+
Unknown: "UNKNOWN"
|
|
1564
|
+
};
|
|
1565
|
+
var AthenaErrorCategory = {
|
|
1566
|
+
Transport: "transport",
|
|
1567
|
+
Client: "client",
|
|
1568
|
+
Server: "server",
|
|
1569
|
+
Database: "database",
|
|
1570
|
+
Unknown: "unknown"
|
|
1571
|
+
};
|
|
1572
|
+
function parseBooleanFlag(rawValue, fallback) {
|
|
1573
|
+
if (!rawValue) return fallback;
|
|
1574
|
+
const normalized = rawValue.trim().toLowerCase();
|
|
1575
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
|
|
1576
|
+
return true;
|
|
1577
|
+
}
|
|
1578
|
+
if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
|
|
1579
|
+
return false;
|
|
1580
|
+
}
|
|
1581
|
+
return fallback;
|
|
972
1582
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1583
|
+
var AthenaError = class extends Error {
|
|
1584
|
+
code;
|
|
1585
|
+
kind;
|
|
1586
|
+
category;
|
|
1587
|
+
status;
|
|
1588
|
+
retryable;
|
|
1589
|
+
requestId;
|
|
1590
|
+
context;
|
|
1591
|
+
raw;
|
|
1592
|
+
constructor(input) {
|
|
1593
|
+
super(input.message);
|
|
1594
|
+
this.name = "AthenaError";
|
|
1595
|
+
this.code = input.code;
|
|
1596
|
+
this.kind = input.kind;
|
|
1597
|
+
this.category = input.category;
|
|
1598
|
+
this.status = input.status;
|
|
1599
|
+
this.retryable = input.retryable ?? false;
|
|
1600
|
+
this.requestId = input.requestId;
|
|
1601
|
+
this.context = input.context;
|
|
1602
|
+
this.raw = input.raw;
|
|
1603
|
+
}
|
|
1604
|
+
};
|
|
1605
|
+
function isRecord3(value) {
|
|
1606
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1607
|
+
}
|
|
1608
|
+
function isAthenaErrorKind(value) {
|
|
1609
|
+
return value === "unique_violation" || value === "not_found" || value === "validation" || value === "auth" || value === "rate_limit" || value === "transient" || value === "unknown";
|
|
1610
|
+
}
|
|
1611
|
+
function isAthenaErrorCode(value) {
|
|
1612
|
+
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";
|
|
1613
|
+
}
|
|
1614
|
+
function isAthenaErrorCategory(value) {
|
|
1615
|
+
return value === "transport" || value === "client" || value === "server" || value === "database" || value === "unknown";
|
|
1616
|
+
}
|
|
1617
|
+
function isNormalizedAthenaError(value) {
|
|
1618
|
+
return isRecord3(value) && isAthenaErrorKind(value.kind) && isAthenaErrorCode(value.code) && isAthenaErrorCategory(value.category) && typeof value.retryable === "boolean" && typeof value.message === "string" && "raw" in value;
|
|
1619
|
+
}
|
|
1620
|
+
function withContextOverrides(normalized, context) {
|
|
1621
|
+
if (!context?.table && !context?.operation) {
|
|
1622
|
+
return normalized;
|
|
1623
|
+
}
|
|
1624
|
+
return {
|
|
1625
|
+
...normalized,
|
|
1626
|
+
table: context.table ?? normalized.table,
|
|
1627
|
+
operation: context.operation ?? normalized.operation
|
|
976
1628
|
};
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1629
|
+
}
|
|
1630
|
+
function resolveAttachedNormalizedError(resultOrError) {
|
|
1631
|
+
if (!isRecord3(resultOrError)) return void 0;
|
|
1632
|
+
if (!("__athenaNormalizedError" in resultOrError)) return void 0;
|
|
1633
|
+
const candidate = resultOrError.__athenaNormalizedError;
|
|
1634
|
+
return isNormalizedAthenaError(candidate) ? candidate : void 0;
|
|
1635
|
+
}
|
|
1636
|
+
function safeStringify(value) {
|
|
1637
|
+
try {
|
|
1638
|
+
const serialized = JSON.stringify(value);
|
|
1639
|
+
return serialized ?? String(value);
|
|
1640
|
+
} catch {
|
|
1641
|
+
return "[unserializable]";
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
function contextHint(context) {
|
|
1645
|
+
if (!context?.identity) return void 0;
|
|
1646
|
+
const identity = typeof context.identity === "string" ? context.identity : safeStringify(context.identity);
|
|
1647
|
+
return `Identity: ${identity}`;
|
|
1648
|
+
}
|
|
1649
|
+
function isAthenaResultLike(value) {
|
|
1650
|
+
return isRecord3(value) && "status" in value && "error" in value && "data" in value && typeof value.status === "number";
|
|
1651
|
+
}
|
|
1652
|
+
function operationFromDetails(details) {
|
|
1653
|
+
if (!details?.endpoint) return void 0;
|
|
1654
|
+
if (details.endpoint === "/gateway/fetch" || details.endpoint === "/gateway/query") return "select";
|
|
1655
|
+
if (details.endpoint === "/gateway/insert") return "insert";
|
|
1656
|
+
if (details.endpoint === "/gateway/update") return "update";
|
|
1657
|
+
if (details.endpoint === "/gateway/delete") return "delete";
|
|
1658
|
+
if (details.endpoint === "/gateway/rpc" || details.endpoint.startsWith("/rpc/")) return "rpc";
|
|
1659
|
+
return void 0;
|
|
1660
|
+
}
|
|
1661
|
+
function matchRegex(input, patterns) {
|
|
1662
|
+
for (const pattern of patterns) {
|
|
1663
|
+
const match = pattern.exec(input);
|
|
1664
|
+
if (match?.[1]) return match[1];
|
|
1665
|
+
}
|
|
1666
|
+
return void 0;
|
|
1667
|
+
}
|
|
1668
|
+
function extractConstraint(message) {
|
|
1669
|
+
return matchRegex(message, [
|
|
1670
|
+
/unique constraint\s+["'`]([^"'`]+)["'`]/i,
|
|
1671
|
+
/constraint\s+["'`]([^"'`]+)["'`]/i
|
|
1672
|
+
]);
|
|
1673
|
+
}
|
|
1674
|
+
function extractTable(message) {
|
|
1675
|
+
return matchRegex(message, [
|
|
1676
|
+
/(?:table|relation)\s+["'`]([^"'`]+)["'`]/i,
|
|
1677
|
+
/on\s+table\s+([a-zA-Z0-9_.]+)/i
|
|
1678
|
+
]);
|
|
1679
|
+
}
|
|
1680
|
+
function classifyKind(status, code, message) {
|
|
1681
|
+
const lower = message.toLowerCase();
|
|
1682
|
+
const hasUniquePattern = lower.includes("unique constraint") || lower.includes("duplicate key") || lower.includes("already exists") || lower.includes("duplicate");
|
|
1683
|
+
const hasNotFoundPattern = lower.includes("not found") || lower.includes("no rows");
|
|
1684
|
+
const hasValidationPattern = lower.includes("validation") || lower.includes("invalid") || lower.includes("malformed");
|
|
1685
|
+
const hasAuthPattern = lower.includes("unauthorized") || lower.includes("forbidden") || lower.includes("auth");
|
|
1686
|
+
const hasRateLimitPattern = lower.includes("rate limit") || lower.includes("too many requests");
|
|
1687
|
+
const hasTransientPattern = lower.includes("timeout") || lower.includes("temporar") || lower.includes("connection reset") || lower.includes("socket") || lower.includes("deadlock");
|
|
1688
|
+
if (status === 409 || hasUniquePattern) return "unique_violation";
|
|
1689
|
+
if (status === 404 || hasNotFoundPattern) return "not_found";
|
|
1690
|
+
if (status === 401 || status === 403 || hasAuthPattern) return "auth";
|
|
1691
|
+
if (status === 429 || hasRateLimitPattern) return "rate_limit";
|
|
1692
|
+
if (status === 400 || status === 422 || hasValidationPattern) return "validation";
|
|
1693
|
+
if (code === "NETWORK_ERROR" || status === 0 || status !== void 0 && status >= 500 || hasTransientPattern) {
|
|
1694
|
+
return "transient";
|
|
1695
|
+
}
|
|
1696
|
+
return "unknown";
|
|
1697
|
+
}
|
|
1698
|
+
function toAthenaErrorCode(kind, status, gatewayCode) {
|
|
1699
|
+
if (gatewayCode === "NETWORK_ERROR" || kind === "transient" && status === 0) {
|
|
1700
|
+
return AthenaErrorCode.NetworkUnavailable;
|
|
1701
|
+
}
|
|
1702
|
+
switch (kind) {
|
|
1703
|
+
case "unique_violation":
|
|
1704
|
+
return AthenaErrorCode.UniqueViolation;
|
|
1705
|
+
case "not_found":
|
|
1706
|
+
return AthenaErrorCode.NotFound;
|
|
1707
|
+
case "validation":
|
|
1708
|
+
return AthenaErrorCode.ValidationFailed;
|
|
1709
|
+
case "rate_limit":
|
|
1710
|
+
return AthenaErrorCode.RateLimited;
|
|
1711
|
+
case "auth":
|
|
1712
|
+
if (status === 403) {
|
|
1713
|
+
return AthenaErrorCode.AuthForbidden;
|
|
1001
1714
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1715
|
+
return AthenaErrorCode.AuthUnauthorized;
|
|
1716
|
+
case "transient":
|
|
1717
|
+
return status !== void 0 && status >= 500 ? AthenaErrorCode.HttpFailure : AthenaErrorCode.TransientFailure;
|
|
1718
|
+
case "unknown":
|
|
1719
|
+
default:
|
|
1720
|
+
return status !== void 0 && status >= 400 ? AthenaErrorCode.HttpFailure : AthenaErrorCode.Unknown;
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
function toAthenaErrorCategory(kind, status) {
|
|
1724
|
+
if (kind === "transient" && (status === 0 || status === void 0)) {
|
|
1725
|
+
return AthenaErrorCategory.Transport;
|
|
1726
|
+
}
|
|
1727
|
+
if (kind === "unique_violation") return AthenaErrorCategory.Database;
|
|
1728
|
+
if (kind === "validation" || kind === "auth" || kind === "not_found") return AthenaErrorCategory.Client;
|
|
1729
|
+
if (kind === "rate_limit" || kind === "transient") return AthenaErrorCategory.Server;
|
|
1730
|
+
return AthenaErrorCategory.Unknown;
|
|
1731
|
+
}
|
|
1732
|
+
function isRetryable(kind, status) {
|
|
1733
|
+
if (kind === "rate_limit" || kind === "transient") return true;
|
|
1734
|
+
return status !== void 0 && status >= 500;
|
|
1735
|
+
}
|
|
1736
|
+
function toGatewayCode(kind, status) {
|
|
1737
|
+
if (kind === "transient" && (status === 0 || status === void 0)) return "NETWORK_ERROR";
|
|
1738
|
+
if (kind === "validation") return "INVALID_JSON";
|
|
1739
|
+
if (status !== void 0 && status >= 400) return "HTTP_ERROR";
|
|
1740
|
+
return "UNKNOWN_ERROR";
|
|
1741
|
+
}
|
|
1742
|
+
function toAthenaGatewayError(source, fallbackMessage, context) {
|
|
1743
|
+
if (isAthenaGatewayError(source)) {
|
|
1744
|
+
return source;
|
|
1745
|
+
}
|
|
1746
|
+
if (isAthenaResultLike(source) && source.errorDetails) {
|
|
1747
|
+
return new AthenaGatewayError({
|
|
1748
|
+
code: source.errorDetails.code,
|
|
1749
|
+
message: source.error ?? source.errorDetails.message,
|
|
1750
|
+
status: source.status,
|
|
1751
|
+
endpoint: source.errorDetails.endpoint,
|
|
1752
|
+
method: source.errorDetails.method,
|
|
1753
|
+
requestId: source.errorDetails.requestId,
|
|
1754
|
+
hint: source.errorDetails.hint,
|
|
1755
|
+
cause: source.errorDetails.cause
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1758
|
+
const normalized = normalizeAthenaError(source, context);
|
|
1759
|
+
const message = isAthenaResultLike(source) && source.error == null && source.errorDetails == null ? fallbackMessage : normalized.message || fallbackMessage;
|
|
1760
|
+
return new AthenaGatewayError({
|
|
1761
|
+
code: toGatewayCode(normalized.kind, normalized.status),
|
|
1762
|
+
message,
|
|
1763
|
+
status: normalized.status ?? 0,
|
|
1764
|
+
hint: normalized.constraint != null ? `Constraint: ${normalized.constraint}` : contextHint(context),
|
|
1765
|
+
cause: typeof normalized.raw === "string" ? normalized.raw : safeStringify(normalized.raw)
|
|
1766
|
+
});
|
|
1767
|
+
}
|
|
1768
|
+
function isOk(result) {
|
|
1769
|
+
return result.error == null && result.status >= 200 && result.status < 300;
|
|
1770
|
+
}
|
|
1771
|
+
function normalizeAthenaError(resultOrError, context) {
|
|
1772
|
+
const attached = resolveAttachedNormalizedError(resultOrError);
|
|
1773
|
+
if (attached) {
|
|
1774
|
+
return withContextOverrides(attached, context);
|
|
1775
|
+
}
|
|
1776
|
+
if (isAthenaResultLike(resultOrError)) {
|
|
1777
|
+
const details = resultOrError.errorDetails;
|
|
1778
|
+
const message2 = resultOrError.error ?? details?.message ?? `Athena ${context?.operation ?? operationFromDetails(details) ?? "request"} failed`;
|
|
1779
|
+
const operation = context?.operation ?? operationFromDetails(details);
|
|
1780
|
+
const table = context?.table ?? extractTable(message2);
|
|
1781
|
+
const constraint = extractConstraint(message2);
|
|
1782
|
+
const kind2 = classifyKind(resultOrError.status, details?.code, message2);
|
|
1783
|
+
const code = toAthenaErrorCode(kind2, resultOrError.status, details?.code);
|
|
1784
|
+
const category = toAthenaErrorCategory(kind2, resultOrError.status);
|
|
1785
|
+
return {
|
|
1786
|
+
kind: kind2,
|
|
1787
|
+
code,
|
|
1788
|
+
category,
|
|
1789
|
+
retryable: isRetryable(kind2, resultOrError.status),
|
|
1790
|
+
status: resultOrError.status,
|
|
1791
|
+
constraint,
|
|
1792
|
+
table,
|
|
1793
|
+
operation,
|
|
1794
|
+
message: message2,
|
|
1795
|
+
raw: resultOrError.raw
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
if (isAthenaGatewayError(resultOrError)) {
|
|
1799
|
+
const details = resultOrError.toDetails();
|
|
1800
|
+
const operation = context?.operation ?? operationFromDetails(details);
|
|
1801
|
+
const table = context?.table ?? extractTable(resultOrError.message);
|
|
1802
|
+
const constraint = extractConstraint(resultOrError.message);
|
|
1803
|
+
const kind2 = classifyKind(resultOrError.status, resultOrError.code, resultOrError.message);
|
|
1804
|
+
const code = toAthenaErrorCode(kind2, resultOrError.status, resultOrError.code);
|
|
1805
|
+
const category = toAthenaErrorCategory(kind2, resultOrError.status);
|
|
1806
|
+
return {
|
|
1807
|
+
kind: kind2,
|
|
1808
|
+
code,
|
|
1809
|
+
category,
|
|
1810
|
+
retryable: isRetryable(kind2, resultOrError.status),
|
|
1811
|
+
status: resultOrError.status,
|
|
1812
|
+
constraint,
|
|
1813
|
+
table,
|
|
1814
|
+
operation,
|
|
1815
|
+
message: resultOrError.message,
|
|
1816
|
+
raw: resultOrError
|
|
1817
|
+
};
|
|
1818
|
+
}
|
|
1819
|
+
if (resultOrError instanceof Error) {
|
|
1820
|
+
const maybeStatus = isRecord3(resultOrError) && typeof resultOrError.status === "number" ? resultOrError.status : void 0;
|
|
1821
|
+
const kind2 = classifyKind(maybeStatus, void 0, resultOrError.message);
|
|
1822
|
+
return {
|
|
1823
|
+
kind: kind2,
|
|
1824
|
+
code: toAthenaErrorCode(kind2, maybeStatus),
|
|
1825
|
+
category: toAthenaErrorCategory(kind2, maybeStatus),
|
|
1826
|
+
retryable: isRetryable(kind2, maybeStatus),
|
|
1827
|
+
status: maybeStatus,
|
|
1828
|
+
constraint: extractConstraint(resultOrError.message),
|
|
1829
|
+
table: context?.table ?? extractTable(resultOrError.message),
|
|
1830
|
+
operation: context?.operation,
|
|
1831
|
+
message: resultOrError.message,
|
|
1832
|
+
raw: resultOrError
|
|
1833
|
+
};
|
|
1834
|
+
}
|
|
1835
|
+
const message = typeof resultOrError === "string" ? resultOrError : "Unknown Athena error";
|
|
1836
|
+
const kind = classifyKind(void 0, void 0, message);
|
|
1837
|
+
return {
|
|
1838
|
+
kind,
|
|
1839
|
+
code: toAthenaErrorCode(kind, void 0),
|
|
1840
|
+
category: toAthenaErrorCategory(kind, void 0),
|
|
1841
|
+
retryable: isRetryable(kind, void 0),
|
|
1842
|
+
status: void 0,
|
|
1843
|
+
constraint: extractConstraint(message),
|
|
1844
|
+
table: context?.table ?? extractTable(message),
|
|
1845
|
+
operation: context?.operation,
|
|
1846
|
+
message,
|
|
1847
|
+
raw: resultOrError
|
|
1004
1848
|
};
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
);
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1849
|
+
}
|
|
1850
|
+
function unwrapRows(result, options) {
|
|
1851
|
+
if (!isOk(result)) {
|
|
1852
|
+
throw toAthenaGatewayError(result, "Athena request failed", options?.context);
|
|
1853
|
+
}
|
|
1854
|
+
if (result.data == null) return [];
|
|
1855
|
+
return Array.isArray(result.data) ? result.data : [result.data];
|
|
1856
|
+
}
|
|
1857
|
+
function unwrap(result, options) {
|
|
1858
|
+
if (!isOk(result)) {
|
|
1859
|
+
throw toAthenaGatewayError(result, "Athena request failed", options?.context);
|
|
1860
|
+
}
|
|
1861
|
+
if (result.data == null && !options?.allowNull) {
|
|
1862
|
+
throw toAthenaGatewayError(result, "Expected data but received null", options?.context);
|
|
1863
|
+
}
|
|
1864
|
+
return result.data;
|
|
1865
|
+
}
|
|
1866
|
+
function unwrapOne(result, options) {
|
|
1867
|
+
const rows = unwrapRows(result, options);
|
|
1868
|
+
if (!rows.length) {
|
|
1869
|
+
if (options?.allowNull) return null;
|
|
1870
|
+
throw toAthenaGatewayError(result, "Expected one row but received none", options?.context);
|
|
1871
|
+
}
|
|
1872
|
+
if (options?.requireExactlyOne && rows.length !== 1) {
|
|
1873
|
+
throw toAthenaGatewayError(
|
|
1874
|
+
result,
|
|
1875
|
+
`Expected exactly one row but received ${rows.length}`,
|
|
1876
|
+
options.context
|
|
1877
|
+
);
|
|
1878
|
+
}
|
|
1879
|
+
return rows[0];
|
|
1880
|
+
}
|
|
1881
|
+
function requireSuccess(result, context) {
|
|
1882
|
+
if (!isOk(result)) {
|
|
1883
|
+
throw toAthenaGatewayError(
|
|
1884
|
+
result,
|
|
1885
|
+
`Athena ${context?.operation ?? "request"} failed`,
|
|
1886
|
+
context
|
|
1887
|
+
);
|
|
1888
|
+
}
|
|
1889
|
+
return result;
|
|
1890
|
+
}
|
|
1891
|
+
function requireAffected(result, options, context) {
|
|
1892
|
+
requireSuccess(result, context);
|
|
1893
|
+
const minimum = options?.min ?? 1;
|
|
1894
|
+
const count = result.count;
|
|
1895
|
+
if (count == null) {
|
|
1896
|
+
throw new AthenaGatewayError({
|
|
1897
|
+
code: "UNKNOWN_ERROR",
|
|
1898
|
+
status: result.status,
|
|
1899
|
+
message: "Expected affected row count but response.count is missing",
|
|
1900
|
+
hint: 'Set call option { count: "exact" } for mutation postcondition checks.',
|
|
1901
|
+
cause: safeStringify(result.raw)
|
|
1902
|
+
});
|
|
1903
|
+
}
|
|
1904
|
+
if (count < minimum) {
|
|
1905
|
+
throw new AthenaGatewayError({
|
|
1906
|
+
code: "UNKNOWN_ERROR",
|
|
1907
|
+
status: result.status,
|
|
1908
|
+
message: `Expected at least ${minimum} affected rows but received ${count}`,
|
|
1909
|
+
hint: contextHint(context),
|
|
1910
|
+
cause: safeStringify(result.raw)
|
|
1911
|
+
});
|
|
1912
|
+
}
|
|
1913
|
+
return count;
|
|
1914
|
+
}
|
|
1915
|
+
function applyBounds(value, options) {
|
|
1916
|
+
if (options?.min !== void 0 && value < options.min) return null;
|
|
1917
|
+
if (options?.max !== void 0 && value > options.max) return null;
|
|
1918
|
+
return value;
|
|
1919
|
+
}
|
|
1920
|
+
function parseIntegerString(value) {
|
|
1921
|
+
const normalized = value.trim();
|
|
1922
|
+
if (!/^[-+]?\d+$/.test(normalized)) return null;
|
|
1923
|
+
const parsed = Number(normalized);
|
|
1924
|
+
if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) return null;
|
|
1925
|
+
return parsed;
|
|
1926
|
+
}
|
|
1927
|
+
function coerceInt(value, options) {
|
|
1928
|
+
if (value == null) return null;
|
|
1929
|
+
if (typeof value === "number") {
|
|
1930
|
+
if (!Number.isFinite(value) || !Number.isInteger(value)) return null;
|
|
1931
|
+
return applyBounds(value, options);
|
|
1932
|
+
}
|
|
1933
|
+
if (typeof value === "string") {
|
|
1934
|
+
const parsed = parseIntegerString(value);
|
|
1935
|
+
if (parsed == null) return null;
|
|
1936
|
+
return applyBounds(parsed, options);
|
|
1937
|
+
}
|
|
1938
|
+
if (typeof value === "bigint") {
|
|
1939
|
+
if (options?.strictBigInt) {
|
|
1940
|
+
if (value > BigInt(Number.MAX_SAFE_INTEGER) || value < BigInt(Number.MIN_SAFE_INTEGER)) {
|
|
1941
|
+
return null;
|
|
1031
1942
|
}
|
|
1032
1943
|
}
|
|
1033
|
-
const
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1944
|
+
const parsed = Number(value);
|
|
1945
|
+
if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) return null;
|
|
1946
|
+
return applyBounds(parsed, options);
|
|
1947
|
+
}
|
|
1948
|
+
return null;
|
|
1949
|
+
}
|
|
1950
|
+
function assertInt(value, label = "value", options) {
|
|
1951
|
+
const parsed = coerceInt(value, options);
|
|
1952
|
+
if (parsed == null) {
|
|
1953
|
+
throw new TypeError(`${label} must be a finite integer`);
|
|
1954
|
+
}
|
|
1955
|
+
return parsed;
|
|
1956
|
+
}
|
|
1957
|
+
function defaultShouldRetry(error) {
|
|
1958
|
+
const normalized = normalizeAthenaError(error);
|
|
1959
|
+
return normalized.kind === "transient" || normalized.kind === "rate_limit";
|
|
1960
|
+
}
|
|
1961
|
+
function computeDelayMs(attempt, error, config) {
|
|
1962
|
+
const baseDelay = config.baseDelayMs;
|
|
1963
|
+
const rawDelay = typeof config.backoff === "function" ? config.backoff(attempt, error) : config.backoff === "linear" ? baseDelay * attempt : baseDelay * Math.pow(2, attempt - 1);
|
|
1964
|
+
const safeDelay = Number.isFinite(rawDelay) ? Math.max(0, rawDelay) : 0;
|
|
1965
|
+
const clamped = Math.min(config.maxDelayMs, safeDelay);
|
|
1966
|
+
const jitterFactor = typeof config.jitter === "number" ? Math.max(0, Math.min(1, config.jitter)) : config.jitter ? 0.2 : 0;
|
|
1967
|
+
if (!jitterFactor) return clamped;
|
|
1968
|
+
const deviation = clamped * jitterFactor;
|
|
1969
|
+
const offset = (Math.random() * 2 - 1) * deviation;
|
|
1970
|
+
return Math.max(0, clamped + offset);
|
|
1971
|
+
}
|
|
1972
|
+
function sleep(ms) {
|
|
1973
|
+
if (ms <= 0) return Promise.resolve();
|
|
1974
|
+
return new Promise((resolve3) => {
|
|
1975
|
+
setTimeout(resolve3, ms);
|
|
1976
|
+
});
|
|
1977
|
+
}
|
|
1978
|
+
async function withRetry(config, fn) {
|
|
1979
|
+
const retries = Math.max(0, Math.trunc(config.retries));
|
|
1980
|
+
const shouldRetry = config.shouldRetry ?? defaultShouldRetry;
|
|
1981
|
+
const resolvedConfig = {
|
|
1982
|
+
baseDelayMs: config.baseDelayMs ?? 100,
|
|
1983
|
+
maxDelayMs: config.maxDelayMs ?? 1e4,
|
|
1984
|
+
backoff: config.backoff ?? "exponential",
|
|
1985
|
+
jitter: config.jitter ?? false
|
|
1049
1986
|
};
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
return toSingleResult(r);
|
|
1057
|
-
},
|
|
1058
|
-
maybeSingle(cols, opts) {
|
|
1059
|
-
return chain.single(cols, opts);
|
|
1060
|
-
},
|
|
1061
|
-
then(onfulfilled, onrejected) {
|
|
1062
|
-
return runSelect(columns, options).then(onfulfilled, onrejected);
|
|
1063
|
-
},
|
|
1064
|
-
catch(onrejected) {
|
|
1065
|
-
return runSelect(columns, options).catch(onrejected);
|
|
1066
|
-
},
|
|
1067
|
-
finally(onfinally) {
|
|
1068
|
-
return runSelect(columns, options).finally(onfinally);
|
|
1987
|
+
for (let attempts = 0; attempts <= retries; attempts += 1) {
|
|
1988
|
+
try {
|
|
1989
|
+
return await fn();
|
|
1990
|
+
} catch (error) {
|
|
1991
|
+
if (attempts >= retries) {
|
|
1992
|
+
throw error;
|
|
1069
1993
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1994
|
+
const currentAttempt = attempts + 1;
|
|
1995
|
+
const retry = await shouldRetry(error, currentAttempt);
|
|
1996
|
+
if (!retry) {
|
|
1997
|
+
throw error;
|
|
1998
|
+
}
|
|
1999
|
+
const delay = computeDelayMs(currentAttempt, error, resolvedConfig);
|
|
2000
|
+
await sleep(delay);
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
throw new Error("withRetry reached an unexpected state");
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
// src/db/module.ts
|
|
2007
|
+
function createDbModule(input) {
|
|
2008
|
+
const db = {
|
|
2009
|
+
from(table) {
|
|
2010
|
+
return input.from(table);
|
|
1083
2011
|
},
|
|
1084
|
-
select(columns
|
|
1085
|
-
return
|
|
2012
|
+
select(table, columns, options) {
|
|
2013
|
+
return input.from(table).select(columns, options);
|
|
1086
2014
|
},
|
|
1087
|
-
insert(values, options) {
|
|
1088
|
-
|
|
1089
|
-
const executeInsertMany = async (columns, selectOptions) => {
|
|
1090
|
-
const mergedOptions = mergeOptions(options, selectOptions);
|
|
1091
|
-
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
1092
|
-
const payload = {
|
|
1093
|
-
table_name: resolvedTableName,
|
|
1094
|
-
insert_body: asAthenaJsonObjectArray(values)
|
|
1095
|
-
};
|
|
1096
|
-
if (columns) payload.columns = columns;
|
|
1097
|
-
if (mergedOptions?.count) payload.count = mergedOptions.count;
|
|
1098
|
-
if (mergedOptions?.head) payload.head = mergedOptions.head;
|
|
1099
|
-
if (mergedOptions?.defaultToNull !== void 0) {
|
|
1100
|
-
payload.default_to_null = mergedOptions.defaultToNull;
|
|
1101
|
-
}
|
|
1102
|
-
const response = await client.insertGateway(payload, mergedOptions);
|
|
1103
|
-
return formatResult(response);
|
|
1104
|
-
};
|
|
1105
|
-
return createMutationQuery(executeInsertMany);
|
|
1106
|
-
}
|
|
1107
|
-
const executeInsertOne = async (columns, selectOptions) => {
|
|
1108
|
-
const mergedOptions = mergeOptions(options, selectOptions);
|
|
1109
|
-
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
1110
|
-
const payload = {
|
|
1111
|
-
table_name: resolvedTableName,
|
|
1112
|
-
insert_body: asAthenaJsonObject(values)
|
|
1113
|
-
};
|
|
1114
|
-
if (columns) payload.columns = columns;
|
|
1115
|
-
if (mergedOptions?.count) payload.count = mergedOptions.count;
|
|
1116
|
-
if (mergedOptions?.head) payload.head = mergedOptions.head;
|
|
1117
|
-
if (mergedOptions?.defaultToNull !== void 0) {
|
|
1118
|
-
payload.default_to_null = mergedOptions.defaultToNull;
|
|
1119
|
-
}
|
|
1120
|
-
const response = await client.insertGateway(payload, mergedOptions);
|
|
1121
|
-
return formatResult(response);
|
|
1122
|
-
};
|
|
1123
|
-
return createMutationQuery(executeInsertOne);
|
|
2015
|
+
insert(table, values, options) {
|
|
2016
|
+
return Array.isArray(values) ? input.from(table).insert(values, options) : input.from(table).insert(values, options);
|
|
1124
2017
|
},
|
|
1125
|
-
upsert(values, options) {
|
|
1126
|
-
|
|
1127
|
-
const executeUpsertMany = async (columns, selectOptions) => {
|
|
1128
|
-
const mergedOptions = mergeOptions(options, selectOptions);
|
|
1129
|
-
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
1130
|
-
const payload = {
|
|
1131
|
-
table_name: resolvedTableName,
|
|
1132
|
-
insert_body: asAthenaJsonObjectArray(values),
|
|
1133
|
-
update_body: options?.updateBody ? asAthenaJsonObject(options.updateBody) : void 0
|
|
1134
|
-
};
|
|
1135
|
-
if (columns) payload.columns = columns;
|
|
1136
|
-
if (options?.onConflict) payload.on_conflict = options.onConflict;
|
|
1137
|
-
if (mergedOptions?.count) payload.count = mergedOptions.count;
|
|
1138
|
-
if (mergedOptions?.head) payload.head = mergedOptions.head;
|
|
1139
|
-
if (mergedOptions?.defaultToNull !== void 0) {
|
|
1140
|
-
payload.default_to_null = mergedOptions.defaultToNull;
|
|
1141
|
-
}
|
|
1142
|
-
const response = await client.insertGateway(payload, mergedOptions);
|
|
1143
|
-
return formatResult(response);
|
|
1144
|
-
};
|
|
1145
|
-
return createMutationQuery(executeUpsertMany);
|
|
1146
|
-
}
|
|
1147
|
-
const executeUpsertOne = async (columns, selectOptions) => {
|
|
1148
|
-
const mergedOptions = mergeOptions(options, selectOptions);
|
|
1149
|
-
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
1150
|
-
const payload = {
|
|
1151
|
-
table_name: resolvedTableName,
|
|
1152
|
-
insert_body: asAthenaJsonObject(values),
|
|
1153
|
-
update_body: options?.updateBody ? asAthenaJsonObject(options.updateBody) : void 0
|
|
1154
|
-
};
|
|
1155
|
-
if (columns) payload.columns = columns;
|
|
1156
|
-
if (options?.onConflict) payload.on_conflict = options.onConflict;
|
|
1157
|
-
if (mergedOptions?.count) payload.count = mergedOptions.count;
|
|
1158
|
-
if (mergedOptions?.head) payload.head = mergedOptions.head;
|
|
1159
|
-
if (mergedOptions?.defaultToNull !== void 0) {
|
|
1160
|
-
payload.default_to_null = mergedOptions.defaultToNull;
|
|
1161
|
-
}
|
|
1162
|
-
const response = await client.insertGateway(payload, mergedOptions);
|
|
1163
|
-
return formatResult(response);
|
|
1164
|
-
};
|
|
1165
|
-
return createMutationQuery(executeUpsertOne);
|
|
2018
|
+
upsert(table, values, options) {
|
|
2019
|
+
return Array.isArray(values) ? input.from(table).upsert(values, options) : input.from(table).upsert(values, options);
|
|
1166
2020
|
},
|
|
1167
|
-
update(values, options) {
|
|
1168
|
-
|
|
1169
|
-
const filters = state.conditions.length ? [...state.conditions] : void 0;
|
|
1170
|
-
const mergedOptions = mergeOptions(options, selectOptions);
|
|
1171
|
-
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
1172
|
-
const payload = {
|
|
1173
|
-
table_name: resolvedTableName,
|
|
1174
|
-
set: asAthenaJsonObject(values),
|
|
1175
|
-
conditions: filters,
|
|
1176
|
-
strip_nulls: mergedOptions?.stripNulls ?? true
|
|
1177
|
-
};
|
|
1178
|
-
if (state.order) payload.sort_by = state.order;
|
|
1179
|
-
if (state.currentPage !== void 0) payload.current_page = state.currentPage;
|
|
1180
|
-
if (state.pageSize !== void 0) payload.page_size = state.pageSize;
|
|
1181
|
-
if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
|
|
1182
|
-
if (columns) payload.columns = columns;
|
|
1183
|
-
const response = await client.updateGateway(payload, mergedOptions);
|
|
1184
|
-
return formatResult(response);
|
|
1185
|
-
};
|
|
1186
|
-
const mutation = createMutationQuery(executeUpdate, null);
|
|
1187
|
-
const updateChain = {};
|
|
1188
|
-
const filterMethods2 = createFilterMethods(state, addCondition, updateChain);
|
|
1189
|
-
Object.assign(updateChain, filterMethods2, mutation);
|
|
1190
|
-
return updateChain;
|
|
2021
|
+
update(table, values, options) {
|
|
2022
|
+
return input.from(table).update(values, options);
|
|
1191
2023
|
},
|
|
1192
|
-
delete(options) {
|
|
1193
|
-
|
|
1194
|
-
const resourceId = options?.resourceId ?? getResourceId(state);
|
|
1195
|
-
if (!resourceId && !filters?.length) {
|
|
1196
|
-
throw new Error('delete requires a resource_id either via eq("resource_id", ...) or options.resourceId');
|
|
1197
|
-
}
|
|
1198
|
-
const executeDelete = async (columns, selectOptions) => {
|
|
1199
|
-
const mergedOptions = mergeOptions(options, selectOptions);
|
|
1200
|
-
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
1201
|
-
const payload = {
|
|
1202
|
-
table_name: resolvedTableName,
|
|
1203
|
-
resource_id: resourceId,
|
|
1204
|
-
conditions: filters
|
|
1205
|
-
};
|
|
1206
|
-
if (state.order) payload.sort_by = state.order;
|
|
1207
|
-
if (state.currentPage !== void 0) payload.current_page = state.currentPage;
|
|
1208
|
-
if (state.pageSize !== void 0) payload.page_size = state.pageSize;
|
|
1209
|
-
if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
|
|
1210
|
-
if (columns) payload.columns = columns;
|
|
1211
|
-
const response = await client.deleteGateway(payload, mergedOptions);
|
|
1212
|
-
return formatResult(response);
|
|
1213
|
-
};
|
|
1214
|
-
return createMutationQuery(executeDelete, null);
|
|
2024
|
+
delete(table, options) {
|
|
2025
|
+
return input.from(table).delete(options);
|
|
1215
2026
|
},
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
return toSingleResult(response);
|
|
2027
|
+
rpc(fn, args, options) {
|
|
2028
|
+
return input.rpc(fn, args, options);
|
|
1219
2029
|
},
|
|
1220
|
-
|
|
1221
|
-
return
|
|
2030
|
+
query(query, options) {
|
|
2031
|
+
return input.query(query, options);
|
|
1222
2032
|
}
|
|
2033
|
+
};
|
|
2034
|
+
return db;
|
|
2035
|
+
}
|
|
2036
|
+
|
|
2037
|
+
// src/client.ts
|
|
2038
|
+
var DEFAULT_COLUMNS = "*";
|
|
2039
|
+
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;
|
|
2040
|
+
var SAFE_CAST_PATTERN = /^[a-z_][a-z0-9_]*(?:\[\])?$/i;
|
|
2041
|
+
var ATHENA_NORMALIZED_ERROR_KEY = "__athenaNormalizedError";
|
|
2042
|
+
function formatResult(response) {
|
|
2043
|
+
const result = {
|
|
2044
|
+
data: response.data ?? null,
|
|
2045
|
+
error: response.error ?? null,
|
|
2046
|
+
errorDetails: response.errorDetails ?? null,
|
|
2047
|
+
status: response.status,
|
|
2048
|
+
raw: response.raw
|
|
2049
|
+
};
|
|
2050
|
+
if (response.count !== void 0) {
|
|
2051
|
+
result.count = response.count;
|
|
2052
|
+
}
|
|
2053
|
+
return result;
|
|
2054
|
+
}
|
|
2055
|
+
function attachNormalizedError(result, normalizedError) {
|
|
2056
|
+
Object.defineProperty(result, ATHENA_NORMALIZED_ERROR_KEY, {
|
|
2057
|
+
value: normalizedError,
|
|
2058
|
+
enumerable: false,
|
|
2059
|
+
configurable: true,
|
|
2060
|
+
writable: false
|
|
1223
2061
|
});
|
|
1224
|
-
return builder;
|
|
1225
2062
|
}
|
|
1226
|
-
function
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
2063
|
+
function createResultFormatter(experimental) {
|
|
2064
|
+
if (!experimental?.enableErrorNormalization) {
|
|
2065
|
+
return formatResult;
|
|
2066
|
+
}
|
|
2067
|
+
return (response, context) => {
|
|
2068
|
+
const result = formatResult(response);
|
|
2069
|
+
if (result.error == null) {
|
|
2070
|
+
return result;
|
|
1231
2071
|
}
|
|
1232
|
-
const
|
|
1233
|
-
|
|
2072
|
+
const normalizedError = normalizeAthenaError(result, context);
|
|
2073
|
+
attachNormalizedError(result, normalizedError);
|
|
2074
|
+
return result;
|
|
1234
2075
|
};
|
|
1235
2076
|
}
|
|
1236
|
-
function
|
|
1237
|
-
const
|
|
1238
|
-
|
|
1239
|
-
apiKey: config.apiKey,
|
|
1240
|
-
client: config.client,
|
|
1241
|
-
backend: config.backend,
|
|
1242
|
-
headers: config.headers
|
|
1243
|
-
});
|
|
2077
|
+
function toSingleResult(response) {
|
|
2078
|
+
const payload = response.data;
|
|
2079
|
+
const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
|
|
1244
2080
|
return {
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
},
|
|
1248
|
-
rpc(fn, args, options) {
|
|
1249
|
-
const normalizedFn = fn.trim();
|
|
1250
|
-
if (!normalizedFn) {
|
|
1251
|
-
throw new Error("rpc requires a function name");
|
|
1252
|
-
}
|
|
1253
|
-
return createRpcBuilder(
|
|
1254
|
-
normalizedFn,
|
|
1255
|
-
args,
|
|
1256
|
-
options,
|
|
1257
|
-
gateway
|
|
1258
|
-
);
|
|
1259
|
-
},
|
|
1260
|
-
query: createQueryBuilder(gateway)
|
|
2081
|
+
...response,
|
|
2082
|
+
data: singleData
|
|
1261
2083
|
};
|
|
1262
2084
|
}
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
2085
|
+
function mergeOptions(...options) {
|
|
2086
|
+
return options.reduce((acc, next) => {
|
|
2087
|
+
if (!next) return acc;
|
|
2088
|
+
return { ...acc, ...next };
|
|
2089
|
+
}, void 0);
|
|
1267
2090
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
backend(backend) {
|
|
1284
|
-
this.backendConfig = toBackendConfig(backend);
|
|
1285
|
-
return this;
|
|
1286
|
-
}
|
|
1287
|
-
client(clientName) {
|
|
1288
|
-
this.clientName = clientName;
|
|
1289
|
-
return this;
|
|
1290
|
-
}
|
|
1291
|
-
headers(headers) {
|
|
1292
|
-
this.defaultHeaders = headers;
|
|
1293
|
-
return this;
|
|
1294
|
-
}
|
|
1295
|
-
healthTracking(enabled) {
|
|
1296
|
-
this.isHealthTrackingEnabled = enabled;
|
|
1297
|
-
return this;
|
|
1298
|
-
}
|
|
1299
|
-
build() {
|
|
1300
|
-
if (!this.baseUrl || !this.apiKey) {
|
|
1301
|
-
throw new Error("AthenaClient requires url and key; call .url() and .key() before .build()");
|
|
2091
|
+
function asAthenaJsonObject(value) {
|
|
2092
|
+
return value;
|
|
2093
|
+
}
|
|
2094
|
+
function asAthenaJsonObjectArray(values) {
|
|
2095
|
+
return values;
|
|
2096
|
+
}
|
|
2097
|
+
function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
|
|
2098
|
+
let selectedColumns = defaultColumns === null ? void 0 : defaultColumns;
|
|
2099
|
+
let selectedOptions;
|
|
2100
|
+
let promise = null;
|
|
2101
|
+
const run = (columns, options) => {
|
|
2102
|
+
const payloadColumns = columns ?? selectedColumns;
|
|
2103
|
+
const payloadOptions = options ?? selectedOptions;
|
|
2104
|
+
if (!promise) {
|
|
2105
|
+
promise = executor(payloadColumns, payloadOptions);
|
|
1302
2106
|
}
|
|
1303
|
-
return
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
}
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
2107
|
+
return promise;
|
|
2108
|
+
};
|
|
2109
|
+
const mutationQuery = {
|
|
2110
|
+
select(columns = selectedColumns, options) {
|
|
2111
|
+
selectedColumns = columns;
|
|
2112
|
+
selectedOptions = options ?? selectedOptions;
|
|
2113
|
+
return run(columns, options);
|
|
2114
|
+
},
|
|
2115
|
+
returning(columns = selectedColumns, options) {
|
|
2116
|
+
return mutationQuery.select(columns, options);
|
|
2117
|
+
},
|
|
2118
|
+
single(columns = selectedColumns, options) {
|
|
2119
|
+
selectedColumns = columns;
|
|
2120
|
+
selectedOptions = options ?? selectedOptions;
|
|
2121
|
+
return run(columns, options).then(toSingleResult);
|
|
2122
|
+
},
|
|
2123
|
+
maybeSingle(columns = selectedColumns, options) {
|
|
2124
|
+
return mutationQuery.single(columns, options);
|
|
2125
|
+
},
|
|
2126
|
+
then(onfulfilled, onrejected) {
|
|
2127
|
+
return run(selectedColumns, selectedOptions).then(onfulfilled, onrejected);
|
|
2128
|
+
},
|
|
2129
|
+
catch(onrejected) {
|
|
2130
|
+
return run(selectedColumns, selectedOptions).catch(onrejected);
|
|
2131
|
+
},
|
|
2132
|
+
finally(onfinally) {
|
|
2133
|
+
return run(selectedColumns, selectedOptions).finally(onfinally);
|
|
1326
2134
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
};
|
|
1330
|
-
function createClient(url, apiKey, options) {
|
|
1331
|
-
const b = AthenaClient.builder().url(url).key(apiKey).backend(toBackendConfig(options?.backend));
|
|
1332
|
-
if (options?.client) b.client(options.client);
|
|
1333
|
-
if (options?.headers && Object.keys(options.headers).length > 0) b.headers(options.headers);
|
|
1334
|
-
return b.build();
|
|
2135
|
+
};
|
|
2136
|
+
return mutationQuery;
|
|
1335
2137
|
}
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
// src/auxiliaries.ts
|
|
1346
|
-
var AthenaErrorKind = {
|
|
1347
|
-
UniqueViolation: "unique_violation",
|
|
1348
|
-
NotFound: "not_found",
|
|
1349
|
-
Validation: "validation",
|
|
1350
|
-
Auth: "auth",
|
|
1351
|
-
RateLimit: "rate_limit",
|
|
1352
|
-
Transient: "transient",
|
|
1353
|
-
Unknown: "unknown"
|
|
1354
|
-
};
|
|
1355
|
-
var AthenaErrorCode = {
|
|
1356
|
-
UniqueViolation: "UNIQUE_VIOLATION",
|
|
1357
|
-
NotFound: "NOT_FOUND",
|
|
1358
|
-
ValidationFailed: "VALIDATION_FAILED",
|
|
1359
|
-
AuthUnauthorized: "AUTH_UNAUTHORIZED",
|
|
1360
|
-
AuthForbidden: "AUTH_FORBIDDEN",
|
|
1361
|
-
RateLimited: "RATE_LIMITED",
|
|
1362
|
-
NetworkUnavailable: "NETWORK_UNAVAILABLE",
|
|
1363
|
-
TransientFailure: "TRANSIENT_FAILURE",
|
|
1364
|
-
HttpFailure: "HTTP_FAILURE",
|
|
1365
|
-
Unknown: "UNKNOWN"
|
|
1366
|
-
};
|
|
1367
|
-
var AthenaErrorCategory = {
|
|
1368
|
-
Transport: "transport",
|
|
1369
|
-
Client: "client",
|
|
1370
|
-
Server: "server",
|
|
1371
|
-
Database: "database",
|
|
1372
|
-
Unknown: "unknown"
|
|
1373
|
-
};
|
|
1374
|
-
var AthenaError = class extends Error {
|
|
1375
|
-
code;
|
|
1376
|
-
kind;
|
|
1377
|
-
category;
|
|
1378
|
-
status;
|
|
1379
|
-
retryable;
|
|
1380
|
-
requestId;
|
|
1381
|
-
context;
|
|
1382
|
-
raw;
|
|
1383
|
-
constructor(input) {
|
|
1384
|
-
super(input.message);
|
|
1385
|
-
this.name = "AthenaError";
|
|
1386
|
-
this.code = input.code;
|
|
1387
|
-
this.kind = input.kind;
|
|
1388
|
-
this.category = input.category;
|
|
1389
|
-
this.status = input.status;
|
|
1390
|
-
this.retryable = input.retryable ?? false;
|
|
1391
|
-
this.requestId = input.requestId;
|
|
1392
|
-
this.context = input.context;
|
|
1393
|
-
this.raw = input.raw;
|
|
2138
|
+
function getResourceId(state) {
|
|
2139
|
+
const candidate = state.conditions.find(
|
|
2140
|
+
(condition) => condition.operator === "eq" && (condition.column === "resource_id" || condition.column === "id")
|
|
2141
|
+
);
|
|
2142
|
+
return candidate?.value?.toString();
|
|
2143
|
+
}
|
|
2144
|
+
function stringifyFilterValue(value) {
|
|
2145
|
+
if (Array.isArray(value)) {
|
|
2146
|
+
return value.join(",");
|
|
1394
2147
|
}
|
|
1395
|
-
|
|
1396
|
-
function isRecord2(value) {
|
|
1397
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2148
|
+
return String(value);
|
|
1398
2149
|
}
|
|
1399
|
-
function
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
2150
|
+
function isUuidString(value) {
|
|
2151
|
+
return UUID_PATTERN.test(value.trim());
|
|
2152
|
+
}
|
|
2153
|
+
function isUuidIdentifierColumn(column) {
|
|
2154
|
+
return column === "id" || /(?:^|_)uuid(?:_|$)/i.test(column) || /_id$/i.test(column);
|
|
2155
|
+
}
|
|
2156
|
+
function shouldUseUuidTextComparison(column, value) {
|
|
2157
|
+
return typeof value === "string" && isUuidString(value) && isUuidIdentifierColumn(column);
|
|
2158
|
+
}
|
|
2159
|
+
function normalizeCast(cast) {
|
|
2160
|
+
const normalized = cast.trim().toLowerCase();
|
|
2161
|
+
if (!SAFE_CAST_PATTERN.test(normalized)) {
|
|
2162
|
+
throw new Error(`Invalid cast type "${cast}"`);
|
|
1405
2163
|
}
|
|
2164
|
+
return normalized;
|
|
1406
2165
|
}
|
|
1407
|
-
function
|
|
1408
|
-
|
|
1409
|
-
const identity = typeof context.identity === "string" ? context.identity : safeStringify(context.identity);
|
|
1410
|
-
return `Identity: ${identity}`;
|
|
2166
|
+
function escapeSqlStringLiteral(value) {
|
|
2167
|
+
return value.replace(/'/g, "''");
|
|
1411
2168
|
}
|
|
1412
|
-
function
|
|
1413
|
-
|
|
2169
|
+
function toSqlLiteral(value) {
|
|
2170
|
+
if (value === null) return "NULL";
|
|
2171
|
+
if (typeof value === "number") return Number.isFinite(value) ? String(value) : "NULL";
|
|
2172
|
+
if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
|
|
2173
|
+
return `'${escapeSqlStringLiteral(value)}'`;
|
|
1414
2174
|
}
|
|
1415
|
-
function
|
|
1416
|
-
if (!
|
|
1417
|
-
|
|
1418
|
-
if (details.endpoint === "/gateway/insert") return "insert";
|
|
1419
|
-
if (details.endpoint === "/gateway/update") return "update";
|
|
1420
|
-
if (details.endpoint === "/gateway/delete") return "delete";
|
|
1421
|
-
if (details.endpoint === "/gateway/rpc" || details.endpoint.startsWith("/rpc/")) return "rpc";
|
|
1422
|
-
return void 0;
|
|
2175
|
+
function withCast(expression, cast) {
|
|
2176
|
+
if (!cast) return expression;
|
|
2177
|
+
return `${expression}::${normalizeCast(cast)}`;
|
|
1423
2178
|
}
|
|
1424
|
-
function
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
if (match?.[1]) return match[1];
|
|
2179
|
+
function buildSelectColumnsClause(columns) {
|
|
2180
|
+
if (Array.isArray(columns)) {
|
|
2181
|
+
return columns.map((column) => quoteQualifiedIdentifier(column)).join(", ");
|
|
1428
2182
|
}
|
|
1429
|
-
return
|
|
1430
|
-
}
|
|
1431
|
-
function extractConstraint(message) {
|
|
1432
|
-
return matchRegex(message, [
|
|
1433
|
-
/unique constraint\s+["'`]([^"'`]+)["'`]/i,
|
|
1434
|
-
/constraint\s+["'`]([^"'`]+)["'`]/i
|
|
1435
|
-
]);
|
|
2183
|
+
return quoteSelectColumnsExpression(columns);
|
|
1436
2184
|
}
|
|
1437
|
-
function
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
2185
|
+
function resolveTableNameForCall(tableName, schema) {
|
|
2186
|
+
if (!schema) return tableName;
|
|
2187
|
+
const normalizedSchema = schema.trim();
|
|
2188
|
+
if (!normalizedSchema) {
|
|
2189
|
+
throw new Error("schema option must be a non-empty string");
|
|
2190
|
+
}
|
|
2191
|
+
if (tableName.includes(".")) {
|
|
2192
|
+
if (tableName.startsWith(`${normalizedSchema}.`)) {
|
|
2193
|
+
return tableName;
|
|
2194
|
+
}
|
|
2195
|
+
throw new Error(
|
|
2196
|
+
`schema option "${normalizedSchema}" conflicts with schema-qualified table "${tableName}"`
|
|
2197
|
+
);
|
|
2198
|
+
}
|
|
2199
|
+
return `${normalizedSchema}.${tableName}`;
|
|
1442
2200
|
}
|
|
1443
|
-
function
|
|
1444
|
-
|
|
1445
|
-
const
|
|
1446
|
-
const
|
|
1447
|
-
const
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
2201
|
+
function conditionToSqlClause(condition) {
|
|
2202
|
+
if (!condition.column) return null;
|
|
2203
|
+
const column = withCast(quoteQualifiedIdentifier(condition.column), condition.column_cast);
|
|
2204
|
+
const value = condition.value;
|
|
2205
|
+
const sqlOperator = {
|
|
2206
|
+
eq: "=",
|
|
2207
|
+
neq: "!=",
|
|
2208
|
+
gt: ">",
|
|
2209
|
+
gte: ">=",
|
|
2210
|
+
lt: "<",
|
|
2211
|
+
lte: "<=",
|
|
2212
|
+
like: "LIKE",
|
|
2213
|
+
ilike: "ILIKE"
|
|
2214
|
+
};
|
|
2215
|
+
switch (condition.operator) {
|
|
2216
|
+
case "eq":
|
|
2217
|
+
case "neq":
|
|
2218
|
+
case "gt":
|
|
2219
|
+
case "gte":
|
|
2220
|
+
case "lt":
|
|
2221
|
+
case "lte":
|
|
2222
|
+
case "like":
|
|
2223
|
+
case "ilike": {
|
|
2224
|
+
if (Array.isArray(value) || value === void 0) return null;
|
|
2225
|
+
const rhs = withCast(toSqlLiteral(value), condition.value_cast);
|
|
2226
|
+
return `${column} ${sqlOperator[condition.operator]} ${rhs}`;
|
|
2227
|
+
}
|
|
2228
|
+
case "is": {
|
|
2229
|
+
if (value === null) return `${column} IS NULL`;
|
|
2230
|
+
if (value === true) return `${column} IS TRUE`;
|
|
2231
|
+
if (value === false) return `${column} IS FALSE`;
|
|
2232
|
+
return null;
|
|
2233
|
+
}
|
|
2234
|
+
case "in": {
|
|
2235
|
+
if (!Array.isArray(value)) return null;
|
|
2236
|
+
if (value.length === 0) return "FALSE";
|
|
2237
|
+
const values = value.map((item) => withCast(toSqlLiteral(item), condition.value_cast));
|
|
2238
|
+
return `${column} IN (${values.join(", ")})`;
|
|
2239
|
+
}
|
|
2240
|
+
default:
|
|
2241
|
+
return null;
|
|
1458
2242
|
}
|
|
1459
|
-
return "unknown";
|
|
1460
2243
|
}
|
|
1461
|
-
function
|
|
1462
|
-
|
|
1463
|
-
|
|
2244
|
+
function buildTypedSelectQuery(input) {
|
|
2245
|
+
const whereClauses = [];
|
|
2246
|
+
for (const condition of input.conditions) {
|
|
2247
|
+
const clause = conditionToSqlClause(condition);
|
|
2248
|
+
if (!clause) return null;
|
|
2249
|
+
whereClauses.push(clause);
|
|
1464
2250
|
}
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
2251
|
+
let limit = input.limit;
|
|
2252
|
+
let offset = input.offset;
|
|
2253
|
+
if (limit === void 0 && input.pageSize !== void 0) {
|
|
2254
|
+
limit = input.pageSize;
|
|
2255
|
+
}
|
|
2256
|
+
if (offset === void 0 && input.pageSize !== void 0 && input.currentPage !== void 0 && input.currentPage > 0) {
|
|
2257
|
+
offset = (input.currentPage - 1) * input.pageSize;
|
|
2258
|
+
}
|
|
2259
|
+
const sqlParts = [
|
|
2260
|
+
`SELECT ${buildSelectColumnsClause(input.columns)} FROM ${quoteQualifiedIdentifier(input.tableName)}`
|
|
2261
|
+
];
|
|
2262
|
+
if (whereClauses.length > 0) {
|
|
2263
|
+
sqlParts.push(`WHERE ${whereClauses.join(" AND ")}`);
|
|
2264
|
+
}
|
|
2265
|
+
if (input.order?.field) {
|
|
2266
|
+
const direction = input.order.direction === "descending" ? "DESC" : "ASC";
|
|
2267
|
+
sqlParts.push(`ORDER BY ${quoteQualifiedIdentifier(input.order.field)} ${direction}`);
|
|
2268
|
+
}
|
|
2269
|
+
if (limit !== void 0) {
|
|
2270
|
+
sqlParts.push(`LIMIT ${Math.max(0, Math.trunc(limit))}`);
|
|
1484
2271
|
}
|
|
2272
|
+
if (offset !== void 0) {
|
|
2273
|
+
sqlParts.push(`OFFSET ${Math.max(0, Math.trunc(offset))}`);
|
|
2274
|
+
}
|
|
2275
|
+
return `${sqlParts.join(" ")};`;
|
|
2276
|
+
}
|
|
2277
|
+
function createFilterMethods(state, addCondition, self) {
|
|
2278
|
+
return {
|
|
2279
|
+
eq(column, value) {
|
|
2280
|
+
const columnName = String(column);
|
|
2281
|
+
if (shouldUseUuidTextComparison(columnName, value)) {
|
|
2282
|
+
addCondition("eq", columnName, value, { columnCast: "text" });
|
|
2283
|
+
} else {
|
|
2284
|
+
addCondition("eq", columnName, value);
|
|
2285
|
+
}
|
|
2286
|
+
return self;
|
|
2287
|
+
},
|
|
2288
|
+
eqCast(column, value, cast) {
|
|
2289
|
+
addCondition("eq", String(column), value, { valueCast: cast });
|
|
2290
|
+
return self;
|
|
2291
|
+
},
|
|
2292
|
+
eqUuid(column, value) {
|
|
2293
|
+
addCondition("eq", String(column), value, { valueCast: "uuid" });
|
|
2294
|
+
return self;
|
|
2295
|
+
},
|
|
2296
|
+
match(filters) {
|
|
2297
|
+
Object.entries(filters).forEach(([column, value]) => {
|
|
2298
|
+
if (value === void 0) {
|
|
2299
|
+
return;
|
|
2300
|
+
}
|
|
2301
|
+
if (shouldUseUuidTextComparison(column, value)) {
|
|
2302
|
+
addCondition("eq", column, value, { columnCast: "text" });
|
|
2303
|
+
} else {
|
|
2304
|
+
addCondition("eq", column, value);
|
|
2305
|
+
}
|
|
2306
|
+
});
|
|
2307
|
+
return self;
|
|
2308
|
+
},
|
|
2309
|
+
range(from, to) {
|
|
2310
|
+
state.offset = from;
|
|
2311
|
+
state.limit = to - from + 1;
|
|
2312
|
+
return self;
|
|
2313
|
+
},
|
|
2314
|
+
limit(count) {
|
|
2315
|
+
state.limit = count;
|
|
2316
|
+
return self;
|
|
2317
|
+
},
|
|
2318
|
+
offset(count) {
|
|
2319
|
+
state.offset = count;
|
|
2320
|
+
return self;
|
|
2321
|
+
},
|
|
2322
|
+
currentPage(value) {
|
|
2323
|
+
state.currentPage = value;
|
|
2324
|
+
return self;
|
|
2325
|
+
},
|
|
2326
|
+
pageSize(value) {
|
|
2327
|
+
state.pageSize = value;
|
|
2328
|
+
return self;
|
|
2329
|
+
},
|
|
2330
|
+
totalPages(value) {
|
|
2331
|
+
state.totalPages = value;
|
|
2332
|
+
return self;
|
|
2333
|
+
},
|
|
2334
|
+
order(column, options) {
|
|
2335
|
+
state.order = {
|
|
2336
|
+
field: String(column),
|
|
2337
|
+
direction: options?.ascending === false ? "descending" : "ascending"
|
|
2338
|
+
};
|
|
2339
|
+
return self;
|
|
2340
|
+
},
|
|
2341
|
+
gt(column, value) {
|
|
2342
|
+
addCondition("gt", String(column), value);
|
|
2343
|
+
return self;
|
|
2344
|
+
},
|
|
2345
|
+
gte(column, value) {
|
|
2346
|
+
addCondition("gte", String(column), value);
|
|
2347
|
+
return self;
|
|
2348
|
+
},
|
|
2349
|
+
lt(column, value) {
|
|
2350
|
+
addCondition("lt", String(column), value);
|
|
2351
|
+
return self;
|
|
2352
|
+
},
|
|
2353
|
+
lte(column, value) {
|
|
2354
|
+
addCondition("lte", String(column), value);
|
|
2355
|
+
return self;
|
|
2356
|
+
},
|
|
2357
|
+
neq(column, value) {
|
|
2358
|
+
addCondition("neq", String(column), value);
|
|
2359
|
+
return self;
|
|
2360
|
+
},
|
|
2361
|
+
like(column, value) {
|
|
2362
|
+
addCondition("like", String(column), value);
|
|
2363
|
+
return self;
|
|
2364
|
+
},
|
|
2365
|
+
ilike(column, value) {
|
|
2366
|
+
addCondition("ilike", String(column), value);
|
|
2367
|
+
return self;
|
|
2368
|
+
},
|
|
2369
|
+
is(column, value) {
|
|
2370
|
+
addCondition("is", String(column), value);
|
|
2371
|
+
return self;
|
|
2372
|
+
},
|
|
2373
|
+
in(column, values) {
|
|
2374
|
+
addCondition("in", String(column), values);
|
|
2375
|
+
return self;
|
|
2376
|
+
},
|
|
2377
|
+
contains(column, values) {
|
|
2378
|
+
addCondition("contains", String(column), values);
|
|
2379
|
+
return self;
|
|
2380
|
+
},
|
|
2381
|
+
containedBy(column, values) {
|
|
2382
|
+
addCondition("containedBy", String(column), values);
|
|
2383
|
+
return self;
|
|
2384
|
+
},
|
|
2385
|
+
not(columnOrExpression, operator, value) {
|
|
2386
|
+
const expression = String(columnOrExpression);
|
|
2387
|
+
if (operator != null && value !== void 0) {
|
|
2388
|
+
addCondition("not", void 0, `${expression}.${operator}.${stringifyFilterValue(value)}`);
|
|
2389
|
+
} else {
|
|
2390
|
+
addCondition("not", void 0, expression);
|
|
2391
|
+
}
|
|
2392
|
+
return self;
|
|
2393
|
+
},
|
|
2394
|
+
or(expression) {
|
|
2395
|
+
addCondition("or", void 0, expression);
|
|
2396
|
+
return self;
|
|
2397
|
+
}
|
|
2398
|
+
};
|
|
1485
2399
|
}
|
|
1486
|
-
function
|
|
1487
|
-
if (
|
|
1488
|
-
|
|
1489
|
-
}
|
|
1490
|
-
if (kind === "unique_violation") return AthenaErrorCategory.Database;
|
|
1491
|
-
if (kind === "validation" || kind === "auth" || kind === "not_found") return AthenaErrorCategory.Client;
|
|
1492
|
-
if (kind === "rate_limit" || kind === "transient") return AthenaErrorCategory.Server;
|
|
1493
|
-
return AthenaErrorCategory.Unknown;
|
|
2400
|
+
function toRpcSelect(columns) {
|
|
2401
|
+
if (!columns) return void 0;
|
|
2402
|
+
return Array.isArray(columns) ? columns.join(",") : columns;
|
|
1494
2403
|
}
|
|
1495
|
-
function
|
|
1496
|
-
|
|
1497
|
-
|
|
2404
|
+
function createRpcFilterMethods(filters, self) {
|
|
2405
|
+
const addFilter = (operator, column, value) => {
|
|
2406
|
+
filters.push({ column, operator, value });
|
|
2407
|
+
};
|
|
2408
|
+
return {
|
|
2409
|
+
eq(column, value) {
|
|
2410
|
+
addFilter("eq", column, value);
|
|
2411
|
+
return self;
|
|
2412
|
+
},
|
|
2413
|
+
neq(column, value) {
|
|
2414
|
+
addFilter("neq", column, value);
|
|
2415
|
+
return self;
|
|
2416
|
+
},
|
|
2417
|
+
gt(column, value) {
|
|
2418
|
+
addFilter("gt", column, value);
|
|
2419
|
+
return self;
|
|
2420
|
+
},
|
|
2421
|
+
gte(column, value) {
|
|
2422
|
+
addFilter("gte", column, value);
|
|
2423
|
+
return self;
|
|
2424
|
+
},
|
|
2425
|
+
lt(column, value) {
|
|
2426
|
+
addFilter("lt", column, value);
|
|
2427
|
+
return self;
|
|
2428
|
+
},
|
|
2429
|
+
lte(column, value) {
|
|
2430
|
+
addFilter("lte", column, value);
|
|
2431
|
+
return self;
|
|
2432
|
+
},
|
|
2433
|
+
like(column, value) {
|
|
2434
|
+
addFilter("like", column, value);
|
|
2435
|
+
return self;
|
|
2436
|
+
},
|
|
2437
|
+
ilike(column, value) {
|
|
2438
|
+
addFilter("ilike", column, value);
|
|
2439
|
+
return self;
|
|
2440
|
+
},
|
|
2441
|
+
is(column, value) {
|
|
2442
|
+
addFilter("is", column, value);
|
|
2443
|
+
return self;
|
|
2444
|
+
},
|
|
2445
|
+
in(column, values) {
|
|
2446
|
+
addFilter("in", column, values);
|
|
2447
|
+
return self;
|
|
2448
|
+
}
|
|
2449
|
+
};
|
|
1498
2450
|
}
|
|
1499
|
-
function
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
2451
|
+
function createRpcBuilder(functionName, args, baseOptions, client, formatGatewayResult) {
|
|
2452
|
+
const state = {
|
|
2453
|
+
filters: []
|
|
2454
|
+
};
|
|
2455
|
+
let selectedColumns;
|
|
2456
|
+
let selectedOptions;
|
|
2457
|
+
let promise = null;
|
|
2458
|
+
const executeRpc = async (columns, options) => {
|
|
2459
|
+
const mergedOptions = mergeOptions(baseOptions, options);
|
|
2460
|
+
const payload = {
|
|
2461
|
+
function: functionName,
|
|
2462
|
+
args,
|
|
2463
|
+
schema: mergedOptions?.schema,
|
|
2464
|
+
select: toRpcSelect(columns),
|
|
2465
|
+
filters: state.filters.length ? [...state.filters] : void 0,
|
|
2466
|
+
count: mergedOptions?.count,
|
|
2467
|
+
head: mergedOptions?.head,
|
|
2468
|
+
limit: state.limit,
|
|
2469
|
+
offset: state.offset,
|
|
2470
|
+
order: state.order
|
|
2471
|
+
};
|
|
2472
|
+
const response = await client.rpcGateway(payload, mergedOptions);
|
|
2473
|
+
return formatGatewayResult(response, { operation: "rpc" });
|
|
2474
|
+
};
|
|
2475
|
+
const run = (columns, options) => {
|
|
2476
|
+
const payloadColumns = columns ?? selectedColumns;
|
|
2477
|
+
const payloadOptions = options ?? selectedOptions;
|
|
2478
|
+
if (!promise) {
|
|
2479
|
+
promise = executeRpc(payloadColumns, payloadOptions);
|
|
2480
|
+
}
|
|
2481
|
+
return promise;
|
|
2482
|
+
};
|
|
2483
|
+
const builder = {};
|
|
2484
|
+
const filterMethods = createRpcFilterMethods(state.filters, builder);
|
|
2485
|
+
Object.assign(builder, filterMethods, {
|
|
2486
|
+
select(columns = selectedColumns, options) {
|
|
2487
|
+
selectedColumns = columns;
|
|
2488
|
+
selectedOptions = options ?? selectedOptions;
|
|
2489
|
+
return run(columns, options);
|
|
2490
|
+
},
|
|
2491
|
+
async single(columns, options) {
|
|
2492
|
+
const result = await run(columns, options);
|
|
2493
|
+
return toSingleResult(result);
|
|
2494
|
+
},
|
|
2495
|
+
maybeSingle(columns, options) {
|
|
2496
|
+
return builder.single(columns, options);
|
|
2497
|
+
},
|
|
2498
|
+
order(column, options) {
|
|
2499
|
+
state.order = { column, ascending: options?.ascending ?? true };
|
|
2500
|
+
return builder;
|
|
2501
|
+
},
|
|
2502
|
+
limit(count) {
|
|
2503
|
+
state.limit = count;
|
|
2504
|
+
return builder;
|
|
2505
|
+
},
|
|
2506
|
+
offset(count) {
|
|
2507
|
+
state.offset = count;
|
|
2508
|
+
return builder;
|
|
2509
|
+
},
|
|
2510
|
+
range(from, to) {
|
|
2511
|
+
state.offset = from;
|
|
2512
|
+
state.limit = to - from + 1;
|
|
2513
|
+
return builder;
|
|
2514
|
+
},
|
|
2515
|
+
then(onfulfilled, onrejected) {
|
|
2516
|
+
return run(selectedColumns, selectedOptions).then(onfulfilled, onrejected);
|
|
2517
|
+
},
|
|
2518
|
+
catch(onrejected) {
|
|
2519
|
+
return run(selectedColumns, selectedOptions).catch(onrejected);
|
|
2520
|
+
},
|
|
2521
|
+
finally(onfinally) {
|
|
2522
|
+
return run(selectedColumns, selectedOptions).finally(onfinally);
|
|
2523
|
+
}
|
|
2524
|
+
});
|
|
2525
|
+
return builder;
|
|
1504
2526
|
}
|
|
1505
|
-
function
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
2527
|
+
function createTableBuilder(tableName, client, formatGatewayResult) {
|
|
2528
|
+
const state = {
|
|
2529
|
+
conditions: []
|
|
2530
|
+
};
|
|
2531
|
+
const addCondition = (operator, column, value, hints) => {
|
|
2532
|
+
const condition = { operator };
|
|
2533
|
+
if (column) {
|
|
2534
|
+
condition.column = column;
|
|
2535
|
+
if (operator === "eq") {
|
|
2536
|
+
condition.eq_column = column;
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
if (value !== void 0) {
|
|
2540
|
+
condition.value = value;
|
|
2541
|
+
if (operator === "eq") {
|
|
2542
|
+
condition.eq_value = value;
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
if (hints?.valueCast) {
|
|
2546
|
+
condition.value_cast = hints.valueCast;
|
|
2547
|
+
if (operator === "eq") {
|
|
2548
|
+
condition.eq_value_cast = hints.valueCast;
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
if (hints?.columnCast) {
|
|
2552
|
+
condition.column_cast = hints.columnCast;
|
|
2553
|
+
if (operator === "eq") {
|
|
2554
|
+
condition.eq_column_cast = hints.columnCast;
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
state.conditions.push(condition);
|
|
2558
|
+
};
|
|
2559
|
+
const builder = {};
|
|
2560
|
+
const filterMethods = createFilterMethods(
|
|
2561
|
+
state,
|
|
2562
|
+
addCondition,
|
|
2563
|
+
builder
|
|
2564
|
+
);
|
|
2565
|
+
const runSelect = async (columns = DEFAULT_COLUMNS, options) => {
|
|
2566
|
+
const resolvedTableName = resolveTableNameForCall(tableName, options?.schema);
|
|
2567
|
+
const conditions = state.conditions.length ? state.conditions.map((condition) => ({ ...condition })) : void 0;
|
|
2568
|
+
const hasTypedEqualityComparison = conditions?.some(
|
|
2569
|
+
(condition) => condition.operator === "eq" && (condition.value_cast !== void 0 || condition.column_cast !== void 0)
|
|
2570
|
+
) ?? false;
|
|
2571
|
+
if (hasTypedEqualityComparison && !options?.head && !options?.count && conditions) {
|
|
2572
|
+
const query = buildTypedSelectQuery({
|
|
2573
|
+
tableName: resolvedTableName,
|
|
2574
|
+
columns,
|
|
2575
|
+
conditions,
|
|
2576
|
+
limit: state.limit,
|
|
2577
|
+
offset: state.offset,
|
|
2578
|
+
currentPage: state.currentPage,
|
|
2579
|
+
pageSize: state.pageSize,
|
|
2580
|
+
order: state.order
|
|
2581
|
+
});
|
|
2582
|
+
if (query) {
|
|
2583
|
+
const queryResponse = await client.queryGateway({ query }, options);
|
|
2584
|
+
return formatGatewayResult(queryResponse, { table: resolvedTableName, operation: "select" });
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
const payload = {
|
|
2588
|
+
table_name: resolvedTableName,
|
|
2589
|
+
columns,
|
|
2590
|
+
conditions,
|
|
2591
|
+
limit: state.limit,
|
|
2592
|
+
offset: state.offset,
|
|
2593
|
+
current_page: state.currentPage,
|
|
2594
|
+
page_size: state.pageSize,
|
|
2595
|
+
total_pages: state.totalPages,
|
|
2596
|
+
sort_by: state.order,
|
|
2597
|
+
strip_nulls: options?.stripNulls ?? true,
|
|
2598
|
+
count: options?.count,
|
|
2599
|
+
head: options?.head
|
|
2600
|
+
};
|
|
2601
|
+
const response = await client.fetchGateway(payload, options);
|
|
2602
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "select" });
|
|
2603
|
+
};
|
|
2604
|
+
const createSelectChain = (columns, options) => {
|
|
2605
|
+
const chain = {};
|
|
2606
|
+
const filterMethods2 = createFilterMethods(state, addCondition, chain);
|
|
2607
|
+
Object.assign(chain, filterMethods2, {
|
|
2608
|
+
async single(cols, opts) {
|
|
2609
|
+
const r = await runSelect(cols ?? columns, opts ?? options);
|
|
2610
|
+
return toSingleResult(r);
|
|
2611
|
+
},
|
|
2612
|
+
maybeSingle(cols, opts) {
|
|
2613
|
+
return chain.single(cols, opts);
|
|
2614
|
+
},
|
|
2615
|
+
then(onfulfilled, onrejected) {
|
|
2616
|
+
return runSelect(columns, options).then(onfulfilled, onrejected);
|
|
2617
|
+
},
|
|
2618
|
+
catch(onrejected) {
|
|
2619
|
+
return runSelect(columns, options).catch(onrejected);
|
|
2620
|
+
},
|
|
2621
|
+
finally(onfinally) {
|
|
2622
|
+
return runSelect(columns, options).finally(onfinally);
|
|
2623
|
+
}
|
|
1519
2624
|
});
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
2625
|
+
return chain;
|
|
2626
|
+
};
|
|
2627
|
+
Object.assign(builder, filterMethods, {
|
|
2628
|
+
reset() {
|
|
2629
|
+
state.conditions = [];
|
|
2630
|
+
state.limit = void 0;
|
|
2631
|
+
state.offset = void 0;
|
|
2632
|
+
state.order = void 0;
|
|
2633
|
+
state.currentPage = void 0;
|
|
2634
|
+
state.pageSize = void 0;
|
|
2635
|
+
state.totalPages = void 0;
|
|
2636
|
+
return builder;
|
|
2637
|
+
},
|
|
2638
|
+
select(columns = DEFAULT_COLUMNS, options) {
|
|
2639
|
+
return createSelectChain(columns, options);
|
|
2640
|
+
},
|
|
2641
|
+
insert(values, options) {
|
|
2642
|
+
if (Array.isArray(values)) {
|
|
2643
|
+
const executeInsertMany = async (columns, selectOptions) => {
|
|
2644
|
+
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2645
|
+
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
2646
|
+
const payload = {
|
|
2647
|
+
table_name: resolvedTableName,
|
|
2648
|
+
insert_body: asAthenaJsonObjectArray(values)
|
|
2649
|
+
};
|
|
2650
|
+
if (columns) payload.columns = columns;
|
|
2651
|
+
if (mergedOptions?.count) payload.count = mergedOptions.count;
|
|
2652
|
+
if (mergedOptions?.head) payload.head = mergedOptions.head;
|
|
2653
|
+
if (mergedOptions?.defaultToNull !== void 0) {
|
|
2654
|
+
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2655
|
+
}
|
|
2656
|
+
const response = await client.insertGateway(payload, mergedOptions);
|
|
2657
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2658
|
+
};
|
|
2659
|
+
return createMutationQuery(executeInsertMany);
|
|
2660
|
+
}
|
|
2661
|
+
const executeInsertOne = async (columns, selectOptions) => {
|
|
2662
|
+
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2663
|
+
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
2664
|
+
const payload = {
|
|
2665
|
+
table_name: resolvedTableName,
|
|
2666
|
+
insert_body: asAthenaJsonObject(values)
|
|
2667
|
+
};
|
|
2668
|
+
if (columns) payload.columns = columns;
|
|
2669
|
+
if (mergedOptions?.count) payload.count = mergedOptions.count;
|
|
2670
|
+
if (mergedOptions?.head) payload.head = mergedOptions.head;
|
|
2671
|
+
if (mergedOptions?.defaultToNull !== void 0) {
|
|
2672
|
+
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2673
|
+
}
|
|
2674
|
+
const response = await client.insertGateway(payload, mergedOptions);
|
|
2675
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2676
|
+
};
|
|
2677
|
+
return createMutationQuery(executeInsertOne);
|
|
2678
|
+
},
|
|
2679
|
+
upsert(values, options) {
|
|
2680
|
+
if (Array.isArray(values)) {
|
|
2681
|
+
const executeUpsertMany = async (columns, selectOptions) => {
|
|
2682
|
+
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2683
|
+
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
2684
|
+
const payload = {
|
|
2685
|
+
table_name: resolvedTableName,
|
|
2686
|
+
insert_body: asAthenaJsonObjectArray(values),
|
|
2687
|
+
update_body: options?.updateBody ? asAthenaJsonObject(options.updateBody) : void 0
|
|
2688
|
+
};
|
|
2689
|
+
if (columns) payload.columns = columns;
|
|
2690
|
+
if (options?.onConflict) payload.on_conflict = options.onConflict;
|
|
2691
|
+
if (mergedOptions?.count) payload.count = mergedOptions.count;
|
|
2692
|
+
if (mergedOptions?.head) payload.head = mergedOptions.head;
|
|
2693
|
+
if (mergedOptions?.defaultToNull !== void 0) {
|
|
2694
|
+
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2695
|
+
}
|
|
2696
|
+
const response = await client.insertGateway(payload, mergedOptions);
|
|
2697
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2698
|
+
};
|
|
2699
|
+
return createMutationQuery(executeUpsertMany);
|
|
2700
|
+
}
|
|
2701
|
+
const executeUpsertOne = async (columns, selectOptions) => {
|
|
2702
|
+
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2703
|
+
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
2704
|
+
const payload = {
|
|
2705
|
+
table_name: resolvedTableName,
|
|
2706
|
+
insert_body: asAthenaJsonObject(values),
|
|
2707
|
+
update_body: options?.updateBody ? asAthenaJsonObject(options.updateBody) : void 0
|
|
2708
|
+
};
|
|
2709
|
+
if (columns) payload.columns = columns;
|
|
2710
|
+
if (options?.onConflict) payload.on_conflict = options.onConflict;
|
|
2711
|
+
if (mergedOptions?.count) payload.count = mergedOptions.count;
|
|
2712
|
+
if (mergedOptions?.head) payload.head = mergedOptions.head;
|
|
2713
|
+
if (mergedOptions?.defaultToNull !== void 0) {
|
|
2714
|
+
payload.default_to_null = mergedOptions.defaultToNull;
|
|
2715
|
+
}
|
|
2716
|
+
const response = await client.insertGateway(payload, mergedOptions);
|
|
2717
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "insert" });
|
|
2718
|
+
};
|
|
2719
|
+
return createMutationQuery(executeUpsertOne);
|
|
2720
|
+
},
|
|
2721
|
+
update(values, options) {
|
|
2722
|
+
const executeUpdate = async (columns, selectOptions) => {
|
|
2723
|
+
const filters = state.conditions.length ? [...state.conditions] : void 0;
|
|
2724
|
+
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2725
|
+
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
2726
|
+
const payload = {
|
|
2727
|
+
table_name: resolvedTableName,
|
|
2728
|
+
set: asAthenaJsonObject(values),
|
|
2729
|
+
conditions: filters,
|
|
2730
|
+
strip_nulls: mergedOptions?.stripNulls ?? true
|
|
2731
|
+
};
|
|
2732
|
+
if (state.order) payload.sort_by = state.order;
|
|
2733
|
+
if (state.currentPage !== void 0) payload.current_page = state.currentPage;
|
|
2734
|
+
if (state.pageSize !== void 0) payload.page_size = state.pageSize;
|
|
2735
|
+
if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
|
|
2736
|
+
if (columns) payload.columns = columns;
|
|
2737
|
+
const response = await client.updateGateway(payload, mergedOptions);
|
|
2738
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "update" });
|
|
2739
|
+
};
|
|
2740
|
+
const mutation = createMutationQuery(executeUpdate, null);
|
|
2741
|
+
const updateChain = {};
|
|
2742
|
+
const filterMethods2 = createFilterMethods(state, addCondition, updateChain);
|
|
2743
|
+
Object.assign(updateChain, filterMethods2, mutation);
|
|
2744
|
+
return updateChain;
|
|
2745
|
+
},
|
|
2746
|
+
delete(options) {
|
|
2747
|
+
const filters = state.conditions.length ? [...state.conditions] : void 0;
|
|
2748
|
+
const resourceId = options?.resourceId ?? getResourceId(state);
|
|
2749
|
+
if (!resourceId && !filters?.length) {
|
|
2750
|
+
throw new Error('delete requires a resource_id either via eq("resource_id", ...) or options.resourceId');
|
|
2751
|
+
}
|
|
2752
|
+
const executeDelete = async (columns, selectOptions) => {
|
|
2753
|
+
const mergedOptions = mergeOptions(options, selectOptions);
|
|
2754
|
+
const resolvedTableName = resolveTableNameForCall(tableName, mergedOptions?.schema);
|
|
2755
|
+
const payload = {
|
|
2756
|
+
table_name: resolvedTableName,
|
|
2757
|
+
resource_id: resourceId,
|
|
2758
|
+
conditions: filters
|
|
2759
|
+
};
|
|
2760
|
+
if (state.order) payload.sort_by = state.order;
|
|
2761
|
+
if (state.currentPage !== void 0) payload.current_page = state.currentPage;
|
|
2762
|
+
if (state.pageSize !== void 0) payload.page_size = state.pageSize;
|
|
2763
|
+
if (state.totalPages !== void 0) payload.total_pages = state.totalPages;
|
|
2764
|
+
if (columns) payload.columns = columns;
|
|
2765
|
+
const response = await client.deleteGateway(payload, mergedOptions);
|
|
2766
|
+
return formatGatewayResult(response, { table: resolvedTableName, operation: "delete" });
|
|
2767
|
+
};
|
|
2768
|
+
return createMutationQuery(executeDelete, null);
|
|
2769
|
+
},
|
|
2770
|
+
async single(columns, options) {
|
|
2771
|
+
const response = await builder.select(columns, options);
|
|
2772
|
+
return toSingleResult(response);
|
|
2773
|
+
},
|
|
2774
|
+
async maybeSingle(columns, options) {
|
|
2775
|
+
return builder.single(columns, options);
|
|
2776
|
+
}
|
|
1529
2777
|
});
|
|
2778
|
+
return builder;
|
|
1530
2779
|
}
|
|
1531
|
-
function
|
|
1532
|
-
return
|
|
2780
|
+
function createQueryBuilder(client, formatGatewayResult) {
|
|
2781
|
+
return async function query(query, options) {
|
|
2782
|
+
const normalizedQuery = query.trim();
|
|
2783
|
+
if (!normalizedQuery) {
|
|
2784
|
+
throw new Error("query requires a non-empty string");
|
|
2785
|
+
}
|
|
2786
|
+
const response = await client.queryGateway({ query: normalizedQuery }, options);
|
|
2787
|
+
return formatGatewayResult(response, { operation: "query" });
|
|
2788
|
+
};
|
|
1533
2789
|
}
|
|
1534
|
-
function
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
const table = context?.table ?? extractTable(resultOrError.message);
|
|
1561
|
-
const constraint = extractConstraint(resultOrError.message);
|
|
1562
|
-
const kind2 = classifyKind(resultOrError.status, resultOrError.code, resultOrError.message);
|
|
1563
|
-
const code = toAthenaErrorCode(kind2, resultOrError.status, resultOrError.code);
|
|
1564
|
-
const category = toAthenaErrorCategory(kind2, resultOrError.status);
|
|
1565
|
-
return {
|
|
1566
|
-
kind: kind2,
|
|
1567
|
-
code,
|
|
1568
|
-
category,
|
|
1569
|
-
retryable: isRetryable(kind2, resultOrError.status),
|
|
1570
|
-
status: resultOrError.status,
|
|
1571
|
-
constraint,
|
|
1572
|
-
table,
|
|
1573
|
-
operation,
|
|
1574
|
-
message: resultOrError.message,
|
|
1575
|
-
raw: resultOrError
|
|
1576
|
-
};
|
|
1577
|
-
}
|
|
1578
|
-
if (resultOrError instanceof Error) {
|
|
1579
|
-
const maybeStatus = isRecord2(resultOrError) && typeof resultOrError.status === "number" ? resultOrError.status : void 0;
|
|
1580
|
-
const kind2 = classifyKind(maybeStatus, void 0, resultOrError.message);
|
|
1581
|
-
return {
|
|
1582
|
-
kind: kind2,
|
|
1583
|
-
code: toAthenaErrorCode(kind2, maybeStatus),
|
|
1584
|
-
category: toAthenaErrorCategory(kind2, maybeStatus),
|
|
1585
|
-
retryable: isRetryable(kind2, maybeStatus),
|
|
1586
|
-
status: maybeStatus,
|
|
1587
|
-
constraint: extractConstraint(resultOrError.message),
|
|
1588
|
-
table: context?.table ?? extractTable(resultOrError.message),
|
|
1589
|
-
operation: context?.operation,
|
|
1590
|
-
message: resultOrError.message,
|
|
1591
|
-
raw: resultOrError
|
|
1592
|
-
};
|
|
1593
|
-
}
|
|
1594
|
-
const message = typeof resultOrError === "string" ? resultOrError : "Unknown Athena error";
|
|
1595
|
-
const kind = classifyKind(void 0, void 0, message);
|
|
2790
|
+
function createClientFromConfig(config) {
|
|
2791
|
+
const gateway = createAthenaGatewayClient({
|
|
2792
|
+
baseUrl: config.baseUrl,
|
|
2793
|
+
apiKey: config.apiKey,
|
|
2794
|
+
client: config.client,
|
|
2795
|
+
backend: config.backend,
|
|
2796
|
+
headers: config.headers
|
|
2797
|
+
});
|
|
2798
|
+
const formatGatewayResult = createResultFormatter(config.experimental);
|
|
2799
|
+
const auth = createAuthClient(config.auth);
|
|
2800
|
+
const from = (table) => createTableBuilder(table, gateway, formatGatewayResult);
|
|
2801
|
+
const rpc = (fn, args, options) => {
|
|
2802
|
+
const normalizedFn = fn.trim();
|
|
2803
|
+
if (!normalizedFn) {
|
|
2804
|
+
throw new Error("rpc requires a function name");
|
|
2805
|
+
}
|
|
2806
|
+
return createRpcBuilder(
|
|
2807
|
+
normalizedFn,
|
|
2808
|
+
args,
|
|
2809
|
+
options,
|
|
2810
|
+
gateway,
|
|
2811
|
+
formatGatewayResult
|
|
2812
|
+
);
|
|
2813
|
+
};
|
|
2814
|
+
const query = createQueryBuilder(gateway, formatGatewayResult);
|
|
2815
|
+
const db = createDbModule({ from, rpc, query });
|
|
1596
2816
|
return {
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
constraint: extractConstraint(message),
|
|
1603
|
-
table: context?.table ?? extractTable(message),
|
|
1604
|
-
operation: context?.operation,
|
|
1605
|
-
message,
|
|
1606
|
-
raw: resultOrError
|
|
2817
|
+
from,
|
|
2818
|
+
db,
|
|
2819
|
+
rpc,
|
|
2820
|
+
query,
|
|
2821
|
+
auth: auth.auth
|
|
1607
2822
|
};
|
|
1608
2823
|
}
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
}
|
|
1613
|
-
if (result.data == null) return [];
|
|
1614
|
-
return Array.isArray(result.data) ? result.data : [result.data];
|
|
2824
|
+
var DEFAULT_BACKEND = { type: "athena" };
|
|
2825
|
+
function toBackendConfig(b) {
|
|
2826
|
+
if (!b) return DEFAULT_BACKEND;
|
|
2827
|
+
return typeof b === "string" ? { type: b } : b;
|
|
1615
2828
|
}
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
2829
|
+
var AthenaClientBuilderImpl = class {
|
|
2830
|
+
baseUrl;
|
|
2831
|
+
apiKey;
|
|
2832
|
+
backendConfig = DEFAULT_BACKEND;
|
|
2833
|
+
clientName;
|
|
2834
|
+
defaultHeaders;
|
|
2835
|
+
isHealthTrackingEnabled = false;
|
|
2836
|
+
url(url) {
|
|
2837
|
+
this.baseUrl = url;
|
|
2838
|
+
return this;
|
|
1619
2839
|
}
|
|
1620
|
-
|
|
1621
|
-
|
|
2840
|
+
key(apiKey) {
|
|
2841
|
+
this.apiKey = apiKey;
|
|
2842
|
+
return this;
|
|
1622
2843
|
}
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
const rows = unwrapRows(result, options);
|
|
1627
|
-
if (!rows.length) {
|
|
1628
|
-
if (options?.allowNull) return null;
|
|
1629
|
-
throw toAthenaGatewayError(result, "Expected one row but received none", options?.context);
|
|
2844
|
+
backend(backend) {
|
|
2845
|
+
this.backendConfig = toBackendConfig(backend);
|
|
2846
|
+
return this;
|
|
1630
2847
|
}
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
`Expected exactly one row but received ${rows.length}`,
|
|
1635
|
-
options.context
|
|
1636
|
-
);
|
|
2848
|
+
client(clientName) {
|
|
2849
|
+
this.clientName = clientName;
|
|
2850
|
+
return this;
|
|
1637
2851
|
}
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
if (!isOk(result)) {
|
|
1642
|
-
throw toAthenaGatewayError(
|
|
1643
|
-
result,
|
|
1644
|
-
`Athena ${context?.operation ?? "request"} failed`,
|
|
1645
|
-
context
|
|
1646
|
-
);
|
|
2852
|
+
headers(headers) {
|
|
2853
|
+
this.defaultHeaders = headers;
|
|
2854
|
+
return this;
|
|
1647
2855
|
}
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
requireSuccess(result, context);
|
|
1652
|
-
const minimum = options?.min ?? 1;
|
|
1653
|
-
const count = result.count;
|
|
1654
|
-
if (count == null) {
|
|
1655
|
-
throw new AthenaGatewayError({
|
|
1656
|
-
code: "UNKNOWN_ERROR",
|
|
1657
|
-
status: result.status,
|
|
1658
|
-
message: "Expected affected row count but response.count is missing",
|
|
1659
|
-
hint: 'Set call option { count: "exact" } for mutation postcondition checks.',
|
|
1660
|
-
cause: safeStringify(result.raw)
|
|
1661
|
-
});
|
|
2856
|
+
healthTracking(enabled) {
|
|
2857
|
+
this.isHealthTrackingEnabled = enabled;
|
|
2858
|
+
return this;
|
|
1662
2859
|
}
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
2860
|
+
build() {
|
|
2861
|
+
if (!this.baseUrl || !this.apiKey) {
|
|
2862
|
+
throw new Error("AthenaClient requires url and key; call .url() and .key() before .build()");
|
|
2863
|
+
}
|
|
2864
|
+
return createClientFromConfig({
|
|
2865
|
+
baseUrl: this.baseUrl,
|
|
2866
|
+
apiKey: this.apiKey,
|
|
2867
|
+
client: this.clientName,
|
|
2868
|
+
backend: this.backendConfig,
|
|
2869
|
+
headers: this.defaultHeaders,
|
|
2870
|
+
healthTracking: this.isHealthTrackingEnabled
|
|
1670
2871
|
});
|
|
1671
2872
|
}
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
return value;
|
|
1678
|
-
}
|
|
1679
|
-
function parseIntegerString(value) {
|
|
1680
|
-
const normalized = value.trim();
|
|
1681
|
-
if (!/^[-+]?\d+$/.test(normalized)) return null;
|
|
1682
|
-
const parsed = Number(normalized);
|
|
1683
|
-
if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) return null;
|
|
1684
|
-
return parsed;
|
|
1685
|
-
}
|
|
1686
|
-
function coerceInt(value, options) {
|
|
1687
|
-
if (value == null) return null;
|
|
1688
|
-
if (typeof value === "number") {
|
|
1689
|
-
if (!Number.isFinite(value) || !Number.isInteger(value)) return null;
|
|
1690
|
-
return applyBounds(value, options);
|
|
1691
|
-
}
|
|
1692
|
-
if (typeof value === "string") {
|
|
1693
|
-
const parsed = parseIntegerString(value);
|
|
1694
|
-
if (parsed == null) return null;
|
|
1695
|
-
return applyBounds(parsed, options);
|
|
2873
|
+
};
|
|
2874
|
+
var AthenaClient = class _AthenaClient {
|
|
2875
|
+
/** Create a fluent builder for a strongly-typed Athena SDK client. */
|
|
2876
|
+
static builder() {
|
|
2877
|
+
return new AthenaClientBuilderImpl();
|
|
1696
2878
|
}
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
2879
|
+
/** Build a client from process environment variables. */
|
|
2880
|
+
static fromEnvironment() {
|
|
2881
|
+
const url = process.env.ATHENA_URL ?? process.env.ATHENA_GATEWAY_URL;
|
|
2882
|
+
const key = process.env.ATHENA_API_KEY ?? process.env.ATHENA_GATEWAY_API_KEY;
|
|
2883
|
+
if (!url || !key) {
|
|
2884
|
+
throw new Error(
|
|
2885
|
+
"ATHENA_URL and ATHENA_API_KEY (or ATHENA_GATEWAY_URL and ATHENA_GATEWAY_API_KEY) are required"
|
|
2886
|
+
);
|
|
1702
2887
|
}
|
|
1703
|
-
|
|
1704
|
-
if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) return null;
|
|
1705
|
-
return applyBounds(parsed, options);
|
|
1706
|
-
}
|
|
1707
|
-
return null;
|
|
1708
|
-
}
|
|
1709
|
-
function assertInt(value, label = "value", options) {
|
|
1710
|
-
const parsed = coerceInt(value, options);
|
|
1711
|
-
if (parsed == null) {
|
|
1712
|
-
throw new TypeError(`${label} must be a finite integer`);
|
|
2888
|
+
return _AthenaClient.builder().url(url).key(key).build();
|
|
1713
2889
|
}
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
const clamped = Math.min(config.maxDelayMs, safeDelay);
|
|
1725
|
-
const jitterFactor = typeof config.jitter === "number" ? Math.max(0, Math.min(1, config.jitter)) : config.jitter ? 0.2 : 0;
|
|
1726
|
-
if (!jitterFactor) return clamped;
|
|
1727
|
-
const deviation = clamped * jitterFactor;
|
|
1728
|
-
const offset = (Math.random() * 2 - 1) * deviation;
|
|
1729
|
-
return Math.max(0, clamped + offset);
|
|
1730
|
-
}
|
|
1731
|
-
function sleep(ms) {
|
|
1732
|
-
if (ms <= 0) return Promise.resolve();
|
|
1733
|
-
return new Promise((resolve3) => {
|
|
1734
|
-
setTimeout(resolve3, ms);
|
|
2890
|
+
};
|
|
2891
|
+
function createClient(url, apiKey, options) {
|
|
2892
|
+
return createClientFromConfig({
|
|
2893
|
+
baseUrl: url,
|
|
2894
|
+
apiKey,
|
|
2895
|
+
client: options?.client,
|
|
2896
|
+
backend: toBackendConfig(options?.backend),
|
|
2897
|
+
headers: options?.headers,
|
|
2898
|
+
auth: options?.auth,
|
|
2899
|
+
experimental: options?.experimental
|
|
1735
2900
|
});
|
|
1736
2901
|
}
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
};
|
|
1746
|
-
for (let attempts = 0; attempts <= retries; attempts += 1) {
|
|
1747
|
-
try {
|
|
1748
|
-
return await fn();
|
|
1749
|
-
} catch (error) {
|
|
1750
|
-
if (attempts >= retries) {
|
|
1751
|
-
throw error;
|
|
1752
|
-
}
|
|
1753
|
-
const currentAttempt = attempts + 1;
|
|
1754
|
-
const retry = await shouldRetry(error, currentAttempt);
|
|
1755
|
-
if (!retry) {
|
|
1756
|
-
throw error;
|
|
1757
|
-
}
|
|
1758
|
-
const delay = computeDelayMs(currentAttempt, error, resolvedConfig);
|
|
1759
|
-
await sleep(delay);
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
throw new Error("withRetry reached an unexpected state");
|
|
1763
|
-
}
|
|
2902
|
+
|
|
2903
|
+
// src/gateway/types.ts
|
|
2904
|
+
var Backend = {
|
|
2905
|
+
Athena: { type: "athena" },
|
|
2906
|
+
Postgrest: { type: "postgrest" },
|
|
2907
|
+
PostgreSQL: { type: "postgresql" },
|
|
2908
|
+
ScyllaDB: { type: "scylladb" }
|
|
2909
|
+
};
|
|
1764
2910
|
|
|
1765
2911
|
// src/schema/definitions.ts
|
|
1766
2912
|
function defineModel(input) {
|
|
@@ -1827,6 +2973,7 @@ var TypedAthenaClientImpl = class _TypedAthenaClientImpl {
|
|
|
1827
2973
|
registry;
|
|
1828
2974
|
tenantKeyMap;
|
|
1829
2975
|
tenantContext;
|
|
2976
|
+
db;
|
|
1830
2977
|
baseClient;
|
|
1831
2978
|
registryNavigator;
|
|
1832
2979
|
tenantHeaderMapper;
|
|
@@ -1853,6 +3000,7 @@ var TypedAthenaClientImpl = class _TypedAthenaClientImpl {
|
|
|
1853
3000
|
client: this.clientOptions.client,
|
|
1854
3001
|
headers: this.tenantHeaderMapper.apply(this.clientOptions.headers, tenantContext)
|
|
1855
3002
|
});
|
|
3003
|
+
this.db = this.baseClient.db;
|
|
1856
3004
|
}
|
|
1857
3005
|
from(table) {
|
|
1858
3006
|
return this.baseClient.from(table);
|
|
@@ -2242,6 +3390,21 @@ var PostgresCatalogSnapshotAssembler = class {
|
|
|
2242
3390
|
};
|
|
2243
3391
|
|
|
2244
3392
|
// src/schema/postgres-provider.ts
|
|
3393
|
+
var pgPoolConstructorPromise;
|
|
3394
|
+
async function loadPgPoolConstructor() {
|
|
3395
|
+
if (!pgPoolConstructorPromise) {
|
|
3396
|
+
pgPoolConstructorPromise = import('pg').then((module) => {
|
|
3397
|
+
const poolConstructor = module.Pool ?? module.default?.Pool;
|
|
3398
|
+
if (!poolConstructor) {
|
|
3399
|
+
throw new Error(
|
|
3400
|
+
'@xylex-group/athena: Unable to load the PostgreSQL driver. Ensure "pg" is installed and this API runs in a Node.js server runtime.'
|
|
3401
|
+
);
|
|
3402
|
+
}
|
|
3403
|
+
return poolConstructor;
|
|
3404
|
+
});
|
|
3405
|
+
}
|
|
3406
|
+
return pgPoolConstructorPromise;
|
|
3407
|
+
}
|
|
2245
3408
|
var PgCatalogClient = class {
|
|
2246
3409
|
constructor(pool) {
|
|
2247
3410
|
this.pool = pool;
|
|
@@ -2281,7 +3444,8 @@ var PostgresIntrospectionProvider = class {
|
|
|
2281
3444
|
}
|
|
2282
3445
|
async inspect(options) {
|
|
2283
3446
|
const schemas = options?.schemas && options.schemas.length > 0 ? normalizePostgresCatalogSchemas(options.schemas) : this.schemas;
|
|
2284
|
-
const
|
|
3447
|
+
const PoolConstructor = await loadPgPoolConstructor();
|
|
3448
|
+
const pool = new PoolConstructor({
|
|
2285
3449
|
connectionString: this.connectionString
|
|
2286
3450
|
});
|
|
2287
3451
|
const catalogClient = new PgCatalogClient(pool);
|
|
@@ -2318,7 +3482,7 @@ function resolveNullishValue(mode) {
|
|
|
2318
3482
|
if (mode === "null") return null;
|
|
2319
3483
|
return "";
|
|
2320
3484
|
}
|
|
2321
|
-
function
|
|
3485
|
+
function isRecord4(value) {
|
|
2322
3486
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2323
3487
|
}
|
|
2324
3488
|
function isNullableColumn(model, key) {
|
|
@@ -2327,7 +3491,7 @@ function isNullableColumn(model, key) {
|
|
|
2327
3491
|
}
|
|
2328
3492
|
function toModelFormDefaults(model, values, options) {
|
|
2329
3493
|
const source = values;
|
|
2330
|
-
if (!
|
|
3494
|
+
if (!isRecord4(source)) {
|
|
2331
3495
|
return {};
|
|
2332
3496
|
}
|
|
2333
3497
|
const mode = options?.nullishMode ?? "empty-string";
|
|
@@ -2403,6 +3567,7 @@ function resolveProviderSchemas(providerConfig) {
|
|
|
2403
3567
|
}
|
|
2404
3568
|
|
|
2405
3569
|
// src/generator/config.ts
|
|
3570
|
+
var POSTGRES_PROTOCOLS = /* @__PURE__ */ new Set(["postgres:", "postgresql:"]);
|
|
2406
3571
|
var DEFAULT_CONFIG_CANDIDATES = [
|
|
2407
3572
|
"athena.config.ts",
|
|
2408
3573
|
"athena.config.js",
|
|
@@ -2432,6 +3597,184 @@ var DEFAULT_EXPERIMENTAL_FLAGS = {
|
|
|
2432
3597
|
postgresGatewayIntrospection: false,
|
|
2433
3598
|
scyllaProviderContracts: true
|
|
2434
3599
|
};
|
|
3600
|
+
var PROJECT_ENV_FILENAMES = [".env", ".env.local"];
|
|
3601
|
+
var DIRECT_CONNECTION_STRING_ENV_KEYS = [
|
|
3602
|
+
"ATHENA_GENERATOR_PG_URL",
|
|
3603
|
+
"DATABASE_URL",
|
|
3604
|
+
"PG_URL",
|
|
3605
|
+
"POSTGRES_URL",
|
|
3606
|
+
"POSTGRESQL_URL"
|
|
3607
|
+
];
|
|
3608
|
+
var POSTGRES_DATABASE_ENV_KEYS = ["ATHENA_GENERATOR_DB", "ATHENA_DATABASE", "PGDATABASE"];
|
|
3609
|
+
var POSTGRES_PASSWORD_ENV_KEYS = ["ATHENA_GENERATOR_PG_PASSWORD", "PGPASSWORD"];
|
|
3610
|
+
var GATEWAY_URL_ENV_KEYS = ["ATHENA_URL", "ATHENA_GATEWAY_URL", "ATHENA_GENERATOR_URL"];
|
|
3611
|
+
var GATEWAY_API_KEY_ENV_KEYS = [
|
|
3612
|
+
"ATHENA_API_KEY",
|
|
3613
|
+
"ATHENA_GATEWAY_API_KEY",
|
|
3614
|
+
"ATHENA_GENERATOR_API_KEY"
|
|
3615
|
+
];
|
|
3616
|
+
function normalizeRawEnvValue(rawValue) {
|
|
3617
|
+
if (rawValue.startsWith('"') && rawValue.endsWith('"') && rawValue.length >= 2) {
|
|
3618
|
+
const inner = rawValue.slice(1, -1);
|
|
3619
|
+
return inner.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
3620
|
+
}
|
|
3621
|
+
if (rawValue.startsWith("'") && rawValue.endsWith("'") && rawValue.length >= 2) {
|
|
3622
|
+
return rawValue.slice(1, -1);
|
|
3623
|
+
}
|
|
3624
|
+
const commentIndex = rawValue.search(/\s+#/);
|
|
3625
|
+
const withoutComment = commentIndex >= 0 ? rawValue.slice(0, commentIndex) : rawValue;
|
|
3626
|
+
return withoutComment.trim();
|
|
3627
|
+
}
|
|
3628
|
+
function parseEnvLine(line) {
|
|
3629
|
+
const trimmed = line.trim();
|
|
3630
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
3631
|
+
return void 0;
|
|
3632
|
+
}
|
|
3633
|
+
const match = trimmed.match(/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
|
|
3634
|
+
if (!match) {
|
|
3635
|
+
return void 0;
|
|
3636
|
+
}
|
|
3637
|
+
const [, key, rawValue] = match;
|
|
3638
|
+
return [key, normalizeRawEnvValue(rawValue.trim())];
|
|
3639
|
+
}
|
|
3640
|
+
function readProjectEnvEntries(cwd) {
|
|
3641
|
+
const nodeEnv = process.env.NODE_ENV?.trim();
|
|
3642
|
+
const filenames = [
|
|
3643
|
+
...PROJECT_ENV_FILENAMES,
|
|
3644
|
+
...nodeEnv ? [`.env.${nodeEnv}`, `.env.${nodeEnv}.local`] : []
|
|
3645
|
+
];
|
|
3646
|
+
const entries = /* @__PURE__ */ new Map();
|
|
3647
|
+
for (const filename of filenames) {
|
|
3648
|
+
const absolutePath = path.resolve(cwd, filename);
|
|
3649
|
+
if (!fs.existsSync(absolutePath)) {
|
|
3650
|
+
continue;
|
|
3651
|
+
}
|
|
3652
|
+
const content = fs.readFileSync(absolutePath, "utf8");
|
|
3653
|
+
const lines = content.split(/\r?\n/g);
|
|
3654
|
+
for (const line of lines) {
|
|
3655
|
+
const parsed = parseEnvLine(line);
|
|
3656
|
+
if (!parsed) {
|
|
3657
|
+
continue;
|
|
3658
|
+
}
|
|
3659
|
+
const [key, value] = parsed;
|
|
3660
|
+
entries.set(key, value);
|
|
3661
|
+
}
|
|
3662
|
+
}
|
|
3663
|
+
return entries;
|
|
3664
|
+
}
|
|
3665
|
+
function applyProjectEnv(cwd) {
|
|
3666
|
+
const envEntries = readProjectEnvEntries(cwd);
|
|
3667
|
+
if (envEntries.size === 0) {
|
|
3668
|
+
return () => {
|
|
3669
|
+
};
|
|
3670
|
+
}
|
|
3671
|
+
const initialKeys = new Set(
|
|
3672
|
+
Object.keys(process.env).filter((key) => process.env[key] !== void 0)
|
|
3673
|
+
);
|
|
3674
|
+
const staged = /* @__PURE__ */ new Map();
|
|
3675
|
+
for (const [key, value] of envEntries.entries()) {
|
|
3676
|
+
if (initialKeys.has(key)) {
|
|
3677
|
+
continue;
|
|
3678
|
+
}
|
|
3679
|
+
staged.set(key, value);
|
|
3680
|
+
}
|
|
3681
|
+
for (const [key, value] of staged.entries()) {
|
|
3682
|
+
process.env[key] = value;
|
|
3683
|
+
}
|
|
3684
|
+
return () => {
|
|
3685
|
+
for (const key of staged.keys()) {
|
|
3686
|
+
delete process.env[key];
|
|
3687
|
+
}
|
|
3688
|
+
};
|
|
3689
|
+
}
|
|
3690
|
+
function readEnvStringValue(key) {
|
|
3691
|
+
const value = process.env[key];
|
|
3692
|
+
if (typeof value !== "string") {
|
|
3693
|
+
return void 0;
|
|
3694
|
+
}
|
|
3695
|
+
const trimmed = value.trim();
|
|
3696
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
3697
|
+
}
|
|
3698
|
+
function resolveFallbackValue(fallbackKeys) {
|
|
3699
|
+
for (const key of fallbackKeys) {
|
|
3700
|
+
const value = readEnvStringValue(key);
|
|
3701
|
+
if (value) {
|
|
3702
|
+
return value;
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3705
|
+
return void 0;
|
|
3706
|
+
}
|
|
3707
|
+
function normalizeOptionalString(value, fallbackKeys) {
|
|
3708
|
+
if (typeof value === "string") {
|
|
3709
|
+
const trimmed = value.trim();
|
|
3710
|
+
if (trimmed.length > 0) {
|
|
3711
|
+
return trimmed;
|
|
3712
|
+
}
|
|
3713
|
+
}
|
|
3714
|
+
return resolveFallbackValue(fallbackKeys);
|
|
3715
|
+
}
|
|
3716
|
+
function normalizeRequiredString(value, fieldLabel, fallbackKeys) {
|
|
3717
|
+
const resolved = normalizeOptionalString(value, fallbackKeys);
|
|
3718
|
+
if (resolved) {
|
|
3719
|
+
return resolved;
|
|
3720
|
+
}
|
|
3721
|
+
throw new Error(
|
|
3722
|
+
`Generator config is missing ${fieldLabel}. Set ${fieldLabel} directly or provide one of: ${fallbackKeys.join(", ")}.`
|
|
3723
|
+
);
|
|
3724
|
+
}
|
|
3725
|
+
function applyPostgresPasswordFallback(connectionString) {
|
|
3726
|
+
let parsedUrl;
|
|
3727
|
+
try {
|
|
3728
|
+
parsedUrl = new URL(connectionString);
|
|
3729
|
+
} catch {
|
|
3730
|
+
return connectionString;
|
|
3731
|
+
}
|
|
3732
|
+
if (!POSTGRES_PROTOCOLS.has(parsedUrl.protocol)) {
|
|
3733
|
+
return connectionString;
|
|
3734
|
+
}
|
|
3735
|
+
if (!parsedUrl.username || parsedUrl.password) {
|
|
3736
|
+
return connectionString;
|
|
3737
|
+
}
|
|
3738
|
+
const fallbackPassword = resolveFallbackValue(POSTGRES_PASSWORD_ENV_KEYS);
|
|
3739
|
+
if (!fallbackPassword) {
|
|
3740
|
+
return connectionString;
|
|
3741
|
+
}
|
|
3742
|
+
parsedUrl.password = fallbackPassword;
|
|
3743
|
+
return parsedUrl.toString();
|
|
3744
|
+
}
|
|
3745
|
+
function normalizeBooleanFlag(rawValue, fallback) {
|
|
3746
|
+
if (typeof rawValue === "boolean") {
|
|
3747
|
+
return rawValue;
|
|
3748
|
+
}
|
|
3749
|
+
if (typeof rawValue === "string") {
|
|
3750
|
+
return parseBooleanFlag(rawValue, fallback);
|
|
3751
|
+
}
|
|
3752
|
+
return fallback;
|
|
3753
|
+
}
|
|
3754
|
+
function normalizeFeatureFlags(input) {
|
|
3755
|
+
return {
|
|
3756
|
+
emitRelations: normalizeBooleanFlag(
|
|
3757
|
+
input?.emitRelations,
|
|
3758
|
+
DEFAULT_FEATURES.emitRelations
|
|
3759
|
+
),
|
|
3760
|
+
emitRegistry: normalizeBooleanFlag(
|
|
3761
|
+
input?.emitRegistry,
|
|
3762
|
+
DEFAULT_FEATURES.emitRegistry
|
|
3763
|
+
)
|
|
3764
|
+
};
|
|
3765
|
+
}
|
|
3766
|
+
function normalizeExperimentalFlags(input) {
|
|
3767
|
+
return {
|
|
3768
|
+
postgresGatewayIntrospection: normalizeBooleanFlag(
|
|
3769
|
+
input?.postgresGatewayIntrospection,
|
|
3770
|
+
DEFAULT_EXPERIMENTAL_FLAGS.postgresGatewayIntrospection
|
|
3771
|
+
),
|
|
3772
|
+
scyllaProviderContracts: normalizeBooleanFlag(
|
|
3773
|
+
input?.scyllaProviderContracts,
|
|
3774
|
+
DEFAULT_EXPERIMENTAL_FLAGS.scyllaProviderContracts
|
|
3775
|
+
)
|
|
3776
|
+
};
|
|
3777
|
+
}
|
|
2435
3778
|
function normalizeOutputConfig(output) {
|
|
2436
3779
|
return {
|
|
2437
3780
|
targets: {
|
|
@@ -2444,9 +3787,41 @@ function normalizeOutputConfig(output) {
|
|
|
2444
3787
|
};
|
|
2445
3788
|
}
|
|
2446
3789
|
function normalizeProviderConfig(provider) {
|
|
2447
|
-
if (provider.kind === "postgres") {
|
|
3790
|
+
if (provider.kind === "postgres" && provider.mode === "direct") {
|
|
3791
|
+
const connectionString = normalizeRequiredString(
|
|
3792
|
+
provider.connectionString,
|
|
3793
|
+
"provider.connectionString",
|
|
3794
|
+
DIRECT_CONNECTION_STRING_ENV_KEYS
|
|
3795
|
+
);
|
|
3796
|
+
const database = normalizeOptionalString(provider.database, POSTGRES_DATABASE_ENV_KEYS);
|
|
3797
|
+
return {
|
|
3798
|
+
...provider,
|
|
3799
|
+
connectionString: applyPostgresPasswordFallback(connectionString),
|
|
3800
|
+
database,
|
|
3801
|
+
schemas: normalizeSchemaSelection(provider.schemas)
|
|
3802
|
+
};
|
|
3803
|
+
}
|
|
3804
|
+
if (provider.kind === "postgres" && provider.mode === "gateway") {
|
|
3805
|
+
const gatewayUrl = normalizeRequiredString(
|
|
3806
|
+
provider.gatewayUrl,
|
|
3807
|
+
"provider.gatewayUrl",
|
|
3808
|
+
GATEWAY_URL_ENV_KEYS
|
|
3809
|
+
);
|
|
3810
|
+
const apiKey = normalizeRequiredString(
|
|
3811
|
+
provider.apiKey,
|
|
3812
|
+
"provider.apiKey",
|
|
3813
|
+
GATEWAY_API_KEY_ENV_KEYS
|
|
3814
|
+
);
|
|
3815
|
+
const database = normalizeRequiredString(
|
|
3816
|
+
provider.database,
|
|
3817
|
+
"provider.database",
|
|
3818
|
+
POSTGRES_DATABASE_ENV_KEYS
|
|
3819
|
+
);
|
|
2448
3820
|
return {
|
|
2449
3821
|
...provider,
|
|
3822
|
+
gatewayUrl,
|
|
3823
|
+
apiKey,
|
|
3824
|
+
database,
|
|
2450
3825
|
schemas: normalizeSchemaSelection(provider.schemas)
|
|
2451
3826
|
};
|
|
2452
3827
|
}
|
|
@@ -2467,14 +3842,8 @@ function normalizeGeneratorConfig(input) {
|
|
|
2467
3842
|
...DEFAULT_NAMING,
|
|
2468
3843
|
...input.naming ?? {}
|
|
2469
3844
|
},
|
|
2470
|
-
features:
|
|
2471
|
-
|
|
2472
|
-
...input.features ?? {}
|
|
2473
|
-
},
|
|
2474
|
-
experimental: {
|
|
2475
|
-
...DEFAULT_EXPERIMENTAL_FLAGS,
|
|
2476
|
-
...input.experimental ?? {}
|
|
2477
|
-
}
|
|
3845
|
+
features: normalizeFeatureFlags(input.features),
|
|
3846
|
+
experimental: normalizeExperimentalFlags(input.experimental)
|
|
2478
3847
|
};
|
|
2479
3848
|
}
|
|
2480
3849
|
function defineGeneratorConfig(config) {
|
|
@@ -2514,6 +3883,11 @@ function extractConfigExport(module) {
|
|
|
2514
3883
|
if (moduleExports && typeof moduleExports === "object") {
|
|
2515
3884
|
queue.push(moduleExports);
|
|
2516
3885
|
}
|
|
3886
|
+
for (const value of Object.values(record)) {
|
|
3887
|
+
if (value && typeof value === "object") {
|
|
3888
|
+
queue.push(value);
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
2517
3891
|
}
|
|
2518
3892
|
throw new Error(
|
|
2519
3893
|
"Generator config file must export a config object as default export or `config`."
|
|
@@ -2528,19 +3902,24 @@ function importConfigModule(moduleSpecifier) {
|
|
|
2528
3902
|
}
|
|
2529
3903
|
async function loadGeneratorConfig(options = {}) {
|
|
2530
3904
|
const cwd = options.cwd ?? process.cwd();
|
|
3905
|
+
const restoreProjectEnv = applyProjectEnv(cwd);
|
|
2531
3906
|
const resolvedPath = options.configPath ? path.resolve(cwd, options.configPath) : findGeneratorConfigPath(cwd);
|
|
2532
3907
|
if (!resolvedPath) {
|
|
2533
3908
|
throw new Error(
|
|
2534
3909
|
`No generator config found in ${cwd}. Expected one of: ${DEFAULT_CONFIG_CANDIDATES.join(", ")}`
|
|
2535
3910
|
);
|
|
2536
3911
|
}
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
3912
|
+
try {
|
|
3913
|
+
const moduleUrl = url.pathToFileURL(resolvedPath);
|
|
3914
|
+
const module = await importConfigModule(`${moduleUrl.href}?cacheBust=${Date.now()}`);
|
|
3915
|
+
const rawConfig = extractConfigExport(module);
|
|
3916
|
+
return {
|
|
3917
|
+
configPath: resolvedPath,
|
|
3918
|
+
config: normalizeGeneratorConfig(rawConfig)
|
|
3919
|
+
};
|
|
3920
|
+
} finally {
|
|
3921
|
+
restoreProjectEnv();
|
|
3922
|
+
}
|
|
2544
3923
|
}
|
|
2545
3924
|
|
|
2546
3925
|
// src/generator/naming.ts
|
|
@@ -2684,9 +4063,13 @@ function resolvePlaceholderMap(baseTokens, outputConfig) {
|
|
|
2684
4063
|
const resolved = {
|
|
2685
4064
|
...baseTokens
|
|
2686
4065
|
};
|
|
4066
|
+
const reservedTokenKeys = new Set(Object.keys(baseTokens));
|
|
2687
4067
|
const entries = Object.entries(outputConfig.placeholderMap ?? {});
|
|
2688
4068
|
for (let index = 0; index < entries.length; index += 1) {
|
|
2689
4069
|
const [key, value] = entries[index];
|
|
4070
|
+
if (reservedTokenKeys.has(key)) {
|
|
4071
|
+
continue;
|
|
4072
|
+
}
|
|
2690
4073
|
let current = value;
|
|
2691
4074
|
for (let depth = 0; depth < 8; depth += 1) {
|
|
2692
4075
|
const next = renderTemplate(current, resolved);
|
|
@@ -2966,13 +4349,65 @@ function assertNoDuplicatePaths(files) {
|
|
|
2966
4349
|
[
|
|
2967
4350
|
`Generator output collision detected for path: ${file.path}`,
|
|
2968
4351
|
`Collision: ${existing.kind} and ${file.kind}.`,
|
|
2969
|
-
"
|
|
4352
|
+
"Use explicit placeholders such as {model}, {model_kebab}, {schema}, or {schema_kebab} in output targets so each artifact resolves to a unique path."
|
|
2970
4353
|
].join(" ")
|
|
2971
4354
|
);
|
|
2972
4355
|
}
|
|
2973
4356
|
seen.set(file.path, file);
|
|
2974
4357
|
}
|
|
2975
4358
|
}
|
|
4359
|
+
function addSchemaSegmentToPath(pathValue, schemaName) {
|
|
4360
|
+
const normalizedPath = normalizePath(pathValue);
|
|
4361
|
+
const parsedPath = path.posix.parse(normalizedPath);
|
|
4362
|
+
const schemaSegment = applyNamingStyle(schemaName, "kebab");
|
|
4363
|
+
if (!schemaSegment) {
|
|
4364
|
+
return normalizedPath;
|
|
4365
|
+
}
|
|
4366
|
+
const dir = parsedPath.dir.length > 0 ? `${parsedPath.dir}/${schemaSegment}` : schemaSegment;
|
|
4367
|
+
return normalizePath(path.posix.join(dir, parsedPath.base));
|
|
4368
|
+
}
|
|
4369
|
+
function scopeDuplicateDescriptorPathsBySchema(descriptors) {
|
|
4370
|
+
const nextDescriptors = descriptors.map((descriptor) => ({ ...descriptor }));
|
|
4371
|
+
const duplicates = /* @__PURE__ */ new Map();
|
|
4372
|
+
for (let index = 0; index < nextDescriptors.length; index += 1) {
|
|
4373
|
+
const descriptor = nextDescriptors[index];
|
|
4374
|
+
const indexes = duplicates.get(descriptor.filePath) ?? [];
|
|
4375
|
+
indexes.push(index);
|
|
4376
|
+
duplicates.set(descriptor.filePath, indexes);
|
|
4377
|
+
}
|
|
4378
|
+
let appliedSchemaScoping = false;
|
|
4379
|
+
for (const indexes of duplicates.values()) {
|
|
4380
|
+
if (indexes.length <= 1) {
|
|
4381
|
+
continue;
|
|
4382
|
+
}
|
|
4383
|
+
const schemaNames = new Set(indexes.map((index) => nextDescriptors[index].schemaName));
|
|
4384
|
+
if (schemaNames.size <= 1) {
|
|
4385
|
+
continue;
|
|
4386
|
+
}
|
|
4387
|
+
for (const index of indexes) {
|
|
4388
|
+
const descriptor = nextDescriptors[index];
|
|
4389
|
+
descriptor.filePath = addSchemaSegmentToPath(descriptor.filePath, descriptor.schemaName);
|
|
4390
|
+
}
|
|
4391
|
+
appliedSchemaScoping = true;
|
|
4392
|
+
}
|
|
4393
|
+
if (!appliedSchemaScoping) {
|
|
4394
|
+
return nextDescriptors;
|
|
4395
|
+
}
|
|
4396
|
+
const normalizedPaths = /* @__PURE__ */ new Set();
|
|
4397
|
+
for (const descriptor of nextDescriptors) {
|
|
4398
|
+
if (normalizedPaths.has(descriptor.filePath)) {
|
|
4399
|
+
throw new Error(
|
|
4400
|
+
[
|
|
4401
|
+
`Generator output collision detected for path: ${descriptor.filePath}`,
|
|
4402
|
+
"Automatic schema path scoping was applied but collisions remain.",
|
|
4403
|
+
"Add explicit placeholders such as {model}, {model_kebab}, {schema}, or {schema_kebab} to your output targets."
|
|
4404
|
+
].join(" ")
|
|
4405
|
+
);
|
|
4406
|
+
}
|
|
4407
|
+
normalizedPaths.add(descriptor.filePath);
|
|
4408
|
+
}
|
|
4409
|
+
return nextDescriptors;
|
|
4410
|
+
}
|
|
2976
4411
|
var ArtifactComposer = class {
|
|
2977
4412
|
constructor(snapshot, config) {
|
|
2978
4413
|
this.snapshot = snapshot;
|
|
@@ -3011,7 +4446,8 @@ var ArtifactComposer = class {
|
|
|
3011
4446
|
});
|
|
3012
4447
|
}
|
|
3013
4448
|
}
|
|
3014
|
-
const
|
|
4449
|
+
const scopedModelDescriptors = scopeDuplicateDescriptorPathsBySchema(modelDescriptors);
|
|
4450
|
+
let schemaDescriptors = Object.keys(this.snapshot.schemas).sort().map((schemaName) => {
|
|
3015
4451
|
const schemaPath = normalizePath(
|
|
3016
4452
|
renderOutputPath(this.config.output.targets.schema, {
|
|
3017
4453
|
provider: providerName,
|
|
@@ -3029,9 +4465,10 @@ var ArtifactComposer = class {
|
|
|
3029
4465
|
this.config.naming.schemaConst,
|
|
3030
4466
|
"schema"
|
|
3031
4467
|
),
|
|
3032
|
-
models:
|
|
4468
|
+
models: scopedModelDescriptors.filter((model) => model.schemaName === schemaName)
|
|
3033
4469
|
};
|
|
3034
4470
|
});
|
|
4471
|
+
schemaDescriptors = scopeDuplicateDescriptorPathsBySchema(schemaDescriptors);
|
|
3035
4472
|
const databasePath = normalizePath(
|
|
3036
4473
|
renderOutputPath(this.config.output.targets.database, {
|
|
3037
4474
|
provider: providerName,
|
|
@@ -3051,7 +4488,7 @@ var ArtifactComposer = class {
|
|
|
3051
4488
|
schemas: schemaDescriptors
|
|
3052
4489
|
};
|
|
3053
4490
|
const files = [];
|
|
3054
|
-
for (const modelDescriptor of
|
|
4491
|
+
for (const modelDescriptor of scopedModelDescriptors) {
|
|
3055
4492
|
files.push(renderModelArtifact(this.snapshot, modelDescriptor, this.config));
|
|
3056
4493
|
}
|
|
3057
4494
|
for (const schemaDescriptor of schemaDescriptors) {
|
|
@@ -3084,633 +4521,142 @@ var ArtifactComposer = class {
|
|
|
3084
4521
|
files
|
|
3085
4522
|
};
|
|
3086
4523
|
}
|
|
3087
|
-
};
|
|
3088
|
-
function generateArtifactsFromSnapshot(snapshot, config) {
|
|
3089
|
-
const normalizedConfig = "naming" in config && "features" in config && "experimental" in config ? config : normalizeGeneratorConfig(config);
|
|
3090
|
-
return new ArtifactComposer(snapshot, normalizedConfig).compose();
|
|
3091
|
-
}
|
|
3092
|
-
|
|
3093
|
-
// src/generator/providers.ts
|
|
3094
|
-
var AthenaGatewayCatalogClient = class {
|
|
3095
|
-
constructor(client) {
|
|
3096
|
-
this.client = client;
|
|
3097
|
-
}
|
|
3098
|
-
async queryRows(query) {
|
|
3099
|
-
const result = await this.client.query(query);
|
|
3100
|
-
if (result.error || result.status < 200 || result.status >= 300) {
|
|
3101
|
-
throw new Error(result.error ?? `Gateway query failed with status ${result.status}`);
|
|
3102
|
-
}
|
|
3103
|
-
return result.data ?? [];
|
|
3104
|
-
}
|
|
3105
|
-
async queryColumns(query) {
|
|
3106
|
-
return this.queryRows(query);
|
|
3107
|
-
}
|
|
3108
|
-
async queryEnums(query) {
|
|
3109
|
-
const rows = await this.queryRows(query);
|
|
3110
|
-
const enumMap = /* @__PURE__ */ new Map();
|
|
3111
|
-
for (const row of rows) {
|
|
3112
|
-
const existing = enumMap.get(row.type_oid) ?? [];
|
|
3113
|
-
existing.push(row.enum_label);
|
|
3114
|
-
enumMap.set(row.type_oid, existing);
|
|
3115
|
-
}
|
|
3116
|
-
return enumMap;
|
|
3117
|
-
}
|
|
3118
|
-
async queryPrimaryKeys(query) {
|
|
3119
|
-
return this.queryRows(query);
|
|
3120
|
-
}
|
|
3121
|
-
async queryForeignKeys(query) {
|
|
3122
|
-
return this.queryRows(query);
|
|
3123
|
-
}
|
|
3124
|
-
};
|
|
3125
|
-
var AthenaGatewayPostgresIntrospectionProvider = class {
|
|
3126
|
-
constructor(config) {
|
|
3127
|
-
this.config = config;
|
|
3128
|
-
this.client = createClient(this.config.gatewayUrl, this.config.apiKey, {
|
|
3129
|
-
backend: {
|
|
3130
|
-
type: this.config.backend ?? "postgresql"
|
|
3131
|
-
}
|
|
3132
|
-
});
|
|
3133
|
-
this.schemas = normalizeSchemaSelection(this.config.schemas);
|
|
3134
|
-
}
|
|
3135
|
-
backend = "postgresql";
|
|
3136
|
-
client;
|
|
3137
|
-
schemas;
|
|
3138
|
-
async inspect(options) {
|
|
3139
|
-
const schemas = options?.schemas && options.schemas.length > 0 ? normalizeSchemaSelection(options.schemas) : this.schemas;
|
|
3140
|
-
const catalogClient = new AthenaGatewayCatalogClient(this.client);
|
|
3141
|
-
const queries = buildGatewayCatalogQueries(schemas);
|
|
3142
|
-
const [columnRows, enumMap, primaryKeyRows, foreignKeyRows] = await Promise.all([
|
|
3143
|
-
catalogClient.queryColumns(queries.columns),
|
|
3144
|
-
catalogClient.queryEnums(queries.enums),
|
|
3145
|
-
catalogClient.queryPrimaryKeys(queries.primaryKeys),
|
|
3146
|
-
catalogClient.queryForeignKeys(queries.foreignKeys)
|
|
3147
|
-
]);
|
|
3148
|
-
const assembler = new PostgresCatalogSnapshotAssembler();
|
|
3149
|
-
assembler.addColumnRows(columnRows, enumMap);
|
|
3150
|
-
assembler.addPrimaryKeyRows(primaryKeyRows);
|
|
3151
|
-
assembler.addForeignKeyRows(foreignKeyRows);
|
|
3152
|
-
assembler.addManyToManyRows(foreignKeyRows);
|
|
3153
|
-
return {
|
|
3154
|
-
backend: "postgresql",
|
|
3155
|
-
database: this.config.database,
|
|
3156
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3157
|
-
schemas: assembler.toSchemas()
|
|
3158
|
-
};
|
|
3159
|
-
}
|
|
3160
|
-
};
|
|
3161
|
-
var ScyllaIntrospectionProvider = class {
|
|
3162
|
-
constructor(config) {
|
|
3163
|
-
this.config = config;
|
|
3164
|
-
}
|
|
3165
|
-
backend = "scylladb";
|
|
3166
|
-
async inspect() {
|
|
3167
|
-
throw new Error(
|
|
3168
|
-
`Scylla introspection provider is not implemented yet for keyspace ${this.config.keyspace}.`
|
|
3169
|
-
);
|
|
3170
|
-
}
|
|
3171
|
-
};
|
|
3172
|
-
function createPostgresProvider(config) {
|
|
3173
|
-
return createPostgresIntrospectionProvider({
|
|
3174
|
-
connectionString: config.connectionString,
|
|
3175
|
-
database: config.database,
|
|
3176
|
-
schemas: normalizeSchemaSelection(config.schemas)
|
|
3177
|
-
});
|
|
3178
|
-
}
|
|
3179
|
-
function resolveGeneratorProvider(providerConfig, experimentalFlags) {
|
|
3180
|
-
if (providerConfig.kind === "postgres" && providerConfig.mode === "direct") {
|
|
3181
|
-
return createPostgresProvider(providerConfig);
|
|
3182
|
-
}
|
|
3183
|
-
if (providerConfig.kind === "postgres" && providerConfig.mode === "gateway") {
|
|
3184
|
-
return new AthenaGatewayPostgresIntrospectionProvider(providerConfig);
|
|
3185
|
-
}
|
|
3186
|
-
if (providerConfig.kind === "scylla") {
|
|
3187
|
-
if (!experimentalFlags.scyllaProviderContracts) {
|
|
3188
|
-
throw new Error(
|
|
3189
|
-
"Scylla provider contracts are disabled. Set experimental.scyllaProviderContracts=true to enable placeholders."
|
|
3190
|
-
);
|
|
3191
|
-
}
|
|
3192
|
-
return new ScyllaIntrospectionProvider(providerConfig);
|
|
3193
|
-
}
|
|
3194
|
-
throw new Error(`Unsupported generator provider kind: ${providerConfig.kind ?? "unknown"}`);
|
|
3195
|
-
}
|
|
3196
|
-
async function writeArtifacts(files, cwd) {
|
|
3197
|
-
const writtenFiles = [];
|
|
3198
|
-
for (const file of files) {
|
|
3199
|
-
const absolutePath = path.resolve(cwd, file.path);
|
|
3200
|
-
await promises.mkdir(path.dirname(absolutePath), { recursive: true });
|
|
3201
|
-
await promises.writeFile(absolutePath, file.content, "utf8");
|
|
3202
|
-
writtenFiles.push(file.path);
|
|
3203
|
-
}
|
|
3204
|
-
return writtenFiles;
|
|
3205
|
-
}
|
|
3206
|
-
async function runSchemaGenerator(options = {}) {
|
|
3207
|
-
const cwd = options.cwd ?? process.cwd();
|
|
3208
|
-
const configOptions = {
|
|
3209
|
-
cwd,
|
|
3210
|
-
configPath: options.configPath
|
|
3211
|
-
};
|
|
3212
|
-
const { configPath, config } = await loadGeneratorConfig(configOptions);
|
|
3213
|
-
const provider = options.provider ?? resolveGeneratorProvider(config.provider, config.experimental);
|
|
3214
|
-
const snapshot = await provider.inspect({
|
|
3215
|
-
schemas: resolveProviderSchemas(config.provider)
|
|
3216
|
-
});
|
|
3217
|
-
const generated = generateArtifactsFromSnapshot(snapshot, config);
|
|
3218
|
-
const writtenFiles = options.dryRun ? [] : await writeArtifacts(generated.files, cwd);
|
|
3219
|
-
return {
|
|
3220
|
-
...generated,
|
|
3221
|
-
configPath,
|
|
3222
|
-
writtenFiles
|
|
3223
|
-
};
|
|
3224
|
-
}
|
|
3225
|
-
|
|
3226
|
-
// src/auth/client.ts
|
|
3227
|
-
var DEFAULT_AUTH_BASE_URL = "http://localhost:3001/api/auth";
|
|
3228
|
-
var FALLBACK_SDK_VERSION2 = "1.0.0";
|
|
3229
|
-
var SDK_NAME2 = "xylex-group/athena-auth";
|
|
3230
|
-
var SDK_VERSION2 = typeof process !== "undefined" && process?.env?.npm_package_version ? process.env.npm_package_version : FALLBACK_SDK_VERSION2;
|
|
3231
|
-
var SDK_HEADER_VALUE2 = `${SDK_NAME2} ${SDK_VERSION2}`;
|
|
3232
|
-
function normalizeBaseUrl(baseUrl) {
|
|
3233
|
-
return (baseUrl ?? DEFAULT_AUTH_BASE_URL).replace(/\/$/, "");
|
|
3234
|
-
}
|
|
3235
|
-
function isRecord4(value) {
|
|
3236
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
3237
|
-
}
|
|
3238
|
-
function normalizeHeaderValue2(value) {
|
|
3239
|
-
return value ? value : void 0;
|
|
3240
|
-
}
|
|
3241
|
-
function parseResponseBody2(rawText, contentType) {
|
|
3242
|
-
if (!rawText) {
|
|
3243
|
-
return { parsed: null, parseFailed: false };
|
|
3244
|
-
}
|
|
3245
|
-
const contentTypeSuggestsJson = contentType?.toLowerCase().includes("application/json") ?? false;
|
|
3246
|
-
const looksJson = contentTypeSuggestsJson || rawText.startsWith("{") || rawText.startsWith("[");
|
|
3247
|
-
if (!looksJson) {
|
|
3248
|
-
return { parsed: rawText, parseFailed: false };
|
|
3249
|
-
}
|
|
3250
|
-
try {
|
|
3251
|
-
return { parsed: JSON.parse(rawText), parseFailed: false };
|
|
3252
|
-
} catch {
|
|
3253
|
-
return { parsed: rawText, parseFailed: true };
|
|
3254
|
-
}
|
|
3255
|
-
}
|
|
3256
|
-
function resolveRequestId2(headers) {
|
|
3257
|
-
return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
|
|
3258
|
-
}
|
|
3259
|
-
function resolveErrorMessage2(payload, fallback) {
|
|
3260
|
-
if (isRecord4(payload)) {
|
|
3261
|
-
const messageCandidates = [payload.error, payload.message, payload.details];
|
|
3262
|
-
for (const candidate of messageCandidates) {
|
|
3263
|
-
if (typeof candidate === "string" && candidate.trim().length > 0) {
|
|
3264
|
-
return candidate.trim();
|
|
3265
|
-
}
|
|
3266
|
-
}
|
|
3267
|
-
}
|
|
3268
|
-
if (typeof payload === "string" && payload.trim().length > 0) {
|
|
3269
|
-
return payload.trim();
|
|
3270
|
-
}
|
|
3271
|
-
return fallback;
|
|
3272
|
-
}
|
|
3273
|
-
function toErrorDetails(input) {
|
|
3274
|
-
return {
|
|
3275
|
-
code: input.code,
|
|
3276
|
-
message: input.message,
|
|
3277
|
-
status: input.status,
|
|
3278
|
-
endpoint: input.endpoint,
|
|
3279
|
-
method: input.method,
|
|
3280
|
-
requestId: input.requestId,
|
|
3281
|
-
hint: input.hint,
|
|
3282
|
-
cause: input.cause
|
|
3283
|
-
};
|
|
3284
|
-
}
|
|
3285
|
-
function mergeCallOptions(base, override) {
|
|
3286
|
-
if (!base && !override) return void 0;
|
|
3287
|
-
return {
|
|
3288
|
-
...base,
|
|
3289
|
-
...override,
|
|
3290
|
-
headers: {
|
|
3291
|
-
...base?.headers ?? {},
|
|
3292
|
-
...override?.headers ?? {}
|
|
3293
|
-
}
|
|
3294
|
-
};
|
|
3295
|
-
}
|
|
3296
|
-
function extractFetchOptions(input) {
|
|
3297
|
-
if (!input) {
|
|
3298
|
-
return {
|
|
3299
|
-
payload: void 0,
|
|
3300
|
-
fetchOptions: void 0
|
|
3301
|
-
};
|
|
3302
|
-
}
|
|
3303
|
-
const { fetchOptions, ...rest } = input;
|
|
3304
|
-
const hasPayloadKeys = Object.keys(rest).length > 0;
|
|
3305
|
-
return {
|
|
3306
|
-
payload: hasPayloadKeys ? rest : void 0,
|
|
3307
|
-
fetchOptions
|
|
3308
|
-
};
|
|
4524
|
+
};
|
|
4525
|
+
function generateArtifactsFromSnapshot(snapshot, config) {
|
|
4526
|
+
const normalizedConfig = "naming" in config && "features" in config && "experimental" in config ? config : normalizeGeneratorConfig(config);
|
|
4527
|
+
return new ArtifactComposer(snapshot, normalizedConfig).compose();
|
|
3309
4528
|
}
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
const apiKey = options?.apiKey ?? config.apiKey;
|
|
3316
|
-
if (apiKey) {
|
|
3317
|
-
headers.apikey = apiKey;
|
|
3318
|
-
headers["x-api-key"] = apiKey;
|
|
3319
|
-
}
|
|
3320
|
-
const bearerToken = options?.bearerToken ?? config.bearerToken;
|
|
3321
|
-
if (bearerToken) {
|
|
3322
|
-
headers.Authorization = `Bearer ${bearerToken}`;
|
|
4529
|
+
|
|
4530
|
+
// src/generator/providers.ts
|
|
4531
|
+
var AthenaGatewayCatalogClient = class {
|
|
4532
|
+
constructor(client) {
|
|
4533
|
+
this.client = client;
|
|
3323
4534
|
}
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
Object.entries(mergedExtraHeaders).forEach(([key, value]) => {
|
|
3329
|
-
const normalized = normalizeHeaderValue2(value);
|
|
3330
|
-
if (normalized) {
|
|
3331
|
-
headers[key] = normalized;
|
|
4535
|
+
async queryRows(query) {
|
|
4536
|
+
const result = await this.client.query(query);
|
|
4537
|
+
if (result.error || result.status < 200 || result.status >= 300) {
|
|
4538
|
+
throw new Error(result.error ?? `Gateway query failed with status ${result.status}`);
|
|
3332
4539
|
}
|
|
3333
|
-
|
|
3334
|
-
return headers;
|
|
3335
|
-
}
|
|
3336
|
-
function appendQueryParam(searchParams, key, value) {
|
|
3337
|
-
if (value === void 0 || value === null) return;
|
|
3338
|
-
if (Array.isArray(value)) {
|
|
3339
|
-
value.forEach((item) => {
|
|
3340
|
-
searchParams.append(key, String(item));
|
|
3341
|
-
});
|
|
3342
|
-
return;
|
|
4540
|
+
return result.data ?? [];
|
|
3343
4541
|
}
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
function buildRequestUrl(baseUrl, endpoint, query) {
|
|
3347
|
-
const url = `${baseUrl}${endpoint}`;
|
|
3348
|
-
if (!query || Object.keys(query).length === 0) return url;
|
|
3349
|
-
const searchParams = new URLSearchParams();
|
|
3350
|
-
Object.entries(query).forEach(([key, value]) => appendQueryParam(searchParams, key, value));
|
|
3351
|
-
const queryText = searchParams.toString();
|
|
3352
|
-
return queryText ? `${url}?${queryText}` : url;
|
|
3353
|
-
}
|
|
3354
|
-
function inferDefaultMethod(endpoint) {
|
|
3355
|
-
if (endpoint.startsWith("/reset-password/")) {
|
|
3356
|
-
return "GET";
|
|
4542
|
+
async queryColumns(query) {
|
|
4543
|
+
return this.queryRows(query);
|
|
3357
4544
|
}
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
default:
|
|
3368
|
-
return "POST";
|
|
4545
|
+
async queryEnums(query) {
|
|
4546
|
+
const rows = await this.queryRows(query);
|
|
4547
|
+
const enumMap = /* @__PURE__ */ new Map();
|
|
4548
|
+
for (const row of rows) {
|
|
4549
|
+
const existing = enumMap.get(row.type_oid) ?? [];
|
|
4550
|
+
existing.push(row.enum_label);
|
|
4551
|
+
enumMap.set(row.type_oid, existing);
|
|
4552
|
+
}
|
|
4553
|
+
return enumMap;
|
|
3369
4554
|
}
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
const baseUrl = normalizeBaseUrl(options?.baseUrl ?? config.baseUrl);
|
|
3373
|
-
const url = buildRequestUrl(baseUrl, context.endpoint, query);
|
|
3374
|
-
const headers = buildHeaders2(config, options);
|
|
3375
|
-
const credentials = options?.credentials ?? config.credentials ?? "include";
|
|
3376
|
-
const requestInit = {
|
|
3377
|
-
method: context.method,
|
|
3378
|
-
headers,
|
|
3379
|
-
credentials,
|
|
3380
|
-
signal: options?.signal
|
|
3381
|
-
};
|
|
3382
|
-
if (context.method !== "GET") {
|
|
3383
|
-
requestInit.body = JSON.stringify(body ?? {});
|
|
4555
|
+
async queryPrimaryKeys(query) {
|
|
4556
|
+
return this.queryRows(query);
|
|
3384
4557
|
}
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
4558
|
+
async queryForeignKeys(query) {
|
|
4559
|
+
return this.queryRows(query);
|
|
4560
|
+
}
|
|
4561
|
+
};
|
|
4562
|
+
var AthenaGatewayPostgresIntrospectionProvider = class {
|
|
4563
|
+
constructor(config) {
|
|
4564
|
+
this.config = config;
|
|
4565
|
+
this.client = createClient(this.config.gatewayUrl, this.config.apiKey, {
|
|
4566
|
+
backend: {
|
|
4567
|
+
type: this.config.backend ?? "postgresql"
|
|
4568
|
+
}
|
|
3394
4569
|
});
|
|
4570
|
+
this.schemas = normalizeSchemaSelection(this.config.schemas);
|
|
4571
|
+
}
|
|
4572
|
+
backend = "postgresql";
|
|
4573
|
+
client;
|
|
4574
|
+
schemas;
|
|
4575
|
+
async inspect(options) {
|
|
4576
|
+
const schemas = options?.schemas && options.schemas.length > 0 ? normalizeSchemaSelection(options.schemas) : this.schemas;
|
|
4577
|
+
const catalogClient = new AthenaGatewayCatalogClient(this.client);
|
|
4578
|
+
const queries = buildGatewayCatalogQueries(schemas);
|
|
4579
|
+
const [columnRows, enumMap, primaryKeyRows, foreignKeyRows] = await Promise.all([
|
|
4580
|
+
catalogClient.queryColumns(queries.columns),
|
|
4581
|
+
catalogClient.queryEnums(queries.enums),
|
|
4582
|
+
catalogClient.queryPrimaryKeys(queries.primaryKeys),
|
|
4583
|
+
catalogClient.queryForeignKeys(queries.foreignKeys)
|
|
4584
|
+
]);
|
|
4585
|
+
const assembler = new PostgresCatalogSnapshotAssembler();
|
|
4586
|
+
assembler.addColumnRows(columnRows, enumMap);
|
|
4587
|
+
assembler.addPrimaryKeyRows(primaryKeyRows);
|
|
4588
|
+
assembler.addForeignKeyRows(foreignKeyRows);
|
|
4589
|
+
assembler.addManyToManyRows(foreignKeyRows);
|
|
3395
4590
|
return {
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
errorDetails: details,
|
|
3401
|
-
raw: null
|
|
4591
|
+
backend: "postgresql",
|
|
4592
|
+
database: this.config.database,
|
|
4593
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4594
|
+
schemas: assembler.toSchemas()
|
|
3402
4595
|
};
|
|
3403
4596
|
}
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
`Auth endpoint ${context.method} ${context.endpoint} failed with status ${response.status}`
|
|
3436
|
-
),
|
|
3437
|
-
status: response.status,
|
|
3438
|
-
endpoint: context.endpoint,
|
|
3439
|
-
method: context.method,
|
|
3440
|
-
requestId
|
|
3441
|
-
});
|
|
3442
|
-
return {
|
|
3443
|
-
ok: false,
|
|
3444
|
-
status: response.status,
|
|
3445
|
-
data: null,
|
|
3446
|
-
error: details.message,
|
|
3447
|
-
errorDetails: details,
|
|
3448
|
-
raw: parsed
|
|
3449
|
-
};
|
|
4597
|
+
};
|
|
4598
|
+
var ScyllaIntrospectionProvider = class {
|
|
4599
|
+
constructor(config) {
|
|
4600
|
+
this.config = config;
|
|
4601
|
+
}
|
|
4602
|
+
backend = "scylladb";
|
|
4603
|
+
async inspect() {
|
|
4604
|
+
throw new Error(
|
|
4605
|
+
`Scylla introspection provider is not implemented yet for keyspace ${this.config.keyspace}.`
|
|
4606
|
+
);
|
|
4607
|
+
}
|
|
4608
|
+
};
|
|
4609
|
+
function createPostgresProvider(config) {
|
|
4610
|
+
return createPostgresIntrospectionProvider({
|
|
4611
|
+
connectionString: config.connectionString,
|
|
4612
|
+
database: config.database,
|
|
4613
|
+
schemas: normalizeSchemaSelection(config.schemas)
|
|
4614
|
+
});
|
|
4615
|
+
}
|
|
4616
|
+
function resolveGeneratorProvider(providerConfig, experimentalFlags) {
|
|
4617
|
+
if (providerConfig.kind === "postgres" && providerConfig.mode === "direct") {
|
|
4618
|
+
return createPostgresProvider(providerConfig);
|
|
4619
|
+
}
|
|
4620
|
+
if (providerConfig.kind === "postgres" && providerConfig.mode === "gateway") {
|
|
4621
|
+
return new AthenaGatewayPostgresIntrospectionProvider(providerConfig);
|
|
4622
|
+
}
|
|
4623
|
+
if (providerConfig.kind === "scylla") {
|
|
4624
|
+
if (!experimentalFlags.scyllaProviderContracts) {
|
|
4625
|
+
throw new Error(
|
|
4626
|
+
"Scylla provider contracts are disabled. Set experimental.scyllaProviderContracts=true to enable placeholders."
|
|
4627
|
+
);
|
|
3450
4628
|
}
|
|
3451
|
-
return
|
|
3452
|
-
ok: true,
|
|
3453
|
-
status: response.status,
|
|
3454
|
-
data: parsed ?? null,
|
|
3455
|
-
error: null,
|
|
3456
|
-
errorDetails: null,
|
|
3457
|
-
raw: parsed
|
|
3458
|
-
};
|
|
3459
|
-
} catch (callError) {
|
|
3460
|
-
const message = callError instanceof Error ? callError.message : String(callError);
|
|
3461
|
-
const details = toErrorDetails({
|
|
3462
|
-
code: "NETWORK_ERROR",
|
|
3463
|
-
message: `Network error while calling ${context.method} ${context.endpoint}: ${message}`,
|
|
3464
|
-
status: 0,
|
|
3465
|
-
endpoint: context.endpoint,
|
|
3466
|
-
method: context.method,
|
|
3467
|
-
cause: message,
|
|
3468
|
-
hint: "Check auth server URL, DNS, and network reachability."
|
|
3469
|
-
});
|
|
3470
|
-
return {
|
|
3471
|
-
ok: false,
|
|
3472
|
-
status: 0,
|
|
3473
|
-
data: null,
|
|
3474
|
-
error: details.message,
|
|
3475
|
-
errorDetails: details,
|
|
3476
|
-
raw: null
|
|
3477
|
-
};
|
|
4629
|
+
return new ScyllaIntrospectionProvider(providerConfig);
|
|
3478
4630
|
}
|
|
4631
|
+
throw new Error(`Unsupported generator provider kind: ${providerConfig.kind ?? "unknown"}`);
|
|
3479
4632
|
}
|
|
3480
|
-
function
|
|
3481
|
-
const
|
|
3482
|
-
const
|
|
3483
|
-
|
|
3484
|
-
}
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
return
|
|
3489
|
-
}
|
|
3490
|
-
function executeGetWithCompatibleInput(config, context, input, options) {
|
|
3491
|
-
const { fetchOptions } = extractFetchOptions(input);
|
|
3492
|
-
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
3493
|
-
return callAuthEndpoint(config, context, void 0, void 0, mergedOptions);
|
|
4633
|
+
async function writeArtifacts(files, cwd) {
|
|
4634
|
+
const writtenFiles = [];
|
|
4635
|
+
for (const file of files) {
|
|
4636
|
+
const absolutePath = path.resolve(cwd, file.path);
|
|
4637
|
+
await promises.mkdir(path.dirname(absolutePath), { recursive: true });
|
|
4638
|
+
await promises.writeFile(absolutePath, file.content, "utf8");
|
|
4639
|
+
writtenFiles.push(file.path);
|
|
4640
|
+
}
|
|
4641
|
+
return writtenFiles;
|
|
3494
4642
|
}
|
|
3495
|
-
function
|
|
3496
|
-
const
|
|
3497
|
-
const
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
};
|
|
3501
|
-
const request = (input, options) => {
|
|
3502
|
-
const method = input.method ?? (input.body !== void 0 ? "POST" : inferDefaultMethod(input.endpoint));
|
|
3503
|
-
const mergedOptions = mergeCallOptions(input.fetchOptions, options);
|
|
3504
|
-
return callAuthEndpoint(
|
|
3505
|
-
resolvedConfig,
|
|
3506
|
-
{ endpoint: input.endpoint, method },
|
|
3507
|
-
input.body,
|
|
3508
|
-
input.query,
|
|
3509
|
-
mergedOptions
|
|
3510
|
-
);
|
|
3511
|
-
};
|
|
3512
|
-
const signOut = (input, options) => executePostWithOptionalInput(
|
|
3513
|
-
resolvedConfig,
|
|
3514
|
-
{ endpoint: "/sign-out", method: "POST" },
|
|
3515
|
-
input,
|
|
3516
|
-
options
|
|
3517
|
-
);
|
|
3518
|
-
const revokeSessions = (input, options) => executePostWithOptionalInput(
|
|
3519
|
-
resolvedConfig,
|
|
3520
|
-
{ endpoint: "/revoke-sessions", method: "POST" },
|
|
3521
|
-
input,
|
|
3522
|
-
options
|
|
3523
|
-
);
|
|
3524
|
-
const revokeOtherSessions = (input, options) => executePostWithOptionalInput(
|
|
3525
|
-
resolvedConfig,
|
|
3526
|
-
{ endpoint: "/revoke-other-sessions", method: "POST" },
|
|
3527
|
-
input,
|
|
3528
|
-
options
|
|
3529
|
-
);
|
|
3530
|
-
const revokeSession = (input, options) => executePostWithCompatibleInput(
|
|
3531
|
-
resolvedConfig,
|
|
3532
|
-
{ endpoint: "/revoke-session", method: "POST" },
|
|
3533
|
-
input,
|
|
3534
|
-
options
|
|
3535
|
-
);
|
|
3536
|
-
const deleteUser = (input, options) => {
|
|
3537
|
-
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
3538
|
-
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
3539
|
-
return callAuthEndpoint(
|
|
3540
|
-
resolvedConfig,
|
|
3541
|
-
{ endpoint: "/delete-user", method: "POST" },
|
|
3542
|
-
payload ?? {},
|
|
3543
|
-
void 0,
|
|
3544
|
-
mergedOptions
|
|
3545
|
-
);
|
|
3546
|
-
};
|
|
3547
|
-
const deleteUserCallback = (input, options) => {
|
|
3548
|
-
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
3549
|
-
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
3550
|
-
const query = payload ?? {};
|
|
3551
|
-
return callAuthEndpoint(
|
|
3552
|
-
resolvedConfig,
|
|
3553
|
-
{ endpoint: "/delete-user/callback", method: "GET" },
|
|
3554
|
-
void 0,
|
|
3555
|
-
{
|
|
3556
|
-
token: query.token,
|
|
3557
|
-
callbackURL: query.callbackURL
|
|
3558
|
-
},
|
|
3559
|
-
mergedOptions
|
|
3560
|
-
);
|
|
3561
|
-
};
|
|
3562
|
-
const resolveResetPasswordToken = (input, options) => {
|
|
3563
|
-
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
3564
|
-
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
3565
|
-
const query = payload;
|
|
3566
|
-
const token = query?.token?.trim();
|
|
3567
|
-
if (!token) {
|
|
3568
|
-
throw new Error("resolveResetPasswordToken requires a non-empty token");
|
|
3569
|
-
}
|
|
3570
|
-
const endpoint = `/reset-password/${encodeURIComponent(token)}`;
|
|
3571
|
-
return callAuthEndpoint(
|
|
3572
|
-
resolvedConfig,
|
|
3573
|
-
{ endpoint, method: "GET" },
|
|
3574
|
-
void 0,
|
|
3575
|
-
query?.callbackURL ? { callbackURL: query.callbackURL } : void 0,
|
|
3576
|
-
mergedOptions
|
|
3577
|
-
);
|
|
4643
|
+
async function runSchemaGenerator(options = {}) {
|
|
4644
|
+
const cwd = options.cwd ?? process.cwd();
|
|
4645
|
+
const configOptions = {
|
|
4646
|
+
cwd,
|
|
4647
|
+
configPath: options.configPath
|
|
3578
4648
|
};
|
|
4649
|
+
const { configPath, config } = await loadGeneratorConfig(configOptions);
|
|
4650
|
+
const provider = options.provider ?? resolveGeneratorProvider(config.provider, config.experimental);
|
|
4651
|
+
const snapshot = await provider.inspect({
|
|
4652
|
+
schemas: resolveProviderSchemas(config.provider)
|
|
4653
|
+
});
|
|
4654
|
+
const generated = generateArtifactsFromSnapshot(snapshot, config);
|
|
4655
|
+
const writtenFiles = options.dryRun ? [] : await writeArtifacts(generated.files, cwd);
|
|
3579
4656
|
return {
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
email: (input, options) => executePostWithCompatibleInput(
|
|
3584
|
-
resolvedConfig,
|
|
3585
|
-
{ endpoint: "/sign-in/email", method: "POST" },
|
|
3586
|
-
input,
|
|
3587
|
-
options
|
|
3588
|
-
),
|
|
3589
|
-
username: (input, options) => executePostWithCompatibleInput(
|
|
3590
|
-
resolvedConfig,
|
|
3591
|
-
{ endpoint: "/sign-in/username", method: "POST" },
|
|
3592
|
-
input,
|
|
3593
|
-
options
|
|
3594
|
-
),
|
|
3595
|
-
social: (input, options) => executePostWithCompatibleInput(
|
|
3596
|
-
resolvedConfig,
|
|
3597
|
-
{ endpoint: "/sign-in/social", method: "POST" },
|
|
3598
|
-
input,
|
|
3599
|
-
options
|
|
3600
|
-
)
|
|
3601
|
-
},
|
|
3602
|
-
signUp: {
|
|
3603
|
-
email: (input, options) => executePostWithCompatibleInput(
|
|
3604
|
-
resolvedConfig,
|
|
3605
|
-
{ endpoint: "/sign-up/email", method: "POST" },
|
|
3606
|
-
input,
|
|
3607
|
-
options
|
|
3608
|
-
)
|
|
3609
|
-
},
|
|
3610
|
-
signOut,
|
|
3611
|
-
logout: signOut,
|
|
3612
|
-
getSession: (input, options) => executeGetWithCompatibleInput(
|
|
3613
|
-
resolvedConfig,
|
|
3614
|
-
{ endpoint: "/get-session", method: "GET" },
|
|
3615
|
-
input,
|
|
3616
|
-
options
|
|
3617
|
-
),
|
|
3618
|
-
listSessions: (input, options) => executeGetWithCompatibleInput(
|
|
3619
|
-
resolvedConfig,
|
|
3620
|
-
{ endpoint: "/list-sessions", method: "GET" },
|
|
3621
|
-
input,
|
|
3622
|
-
options
|
|
3623
|
-
),
|
|
3624
|
-
revokeSession,
|
|
3625
|
-
clearSession: revokeSession,
|
|
3626
|
-
revokeSessions,
|
|
3627
|
-
clearSessions: revokeSessions,
|
|
3628
|
-
revokeOtherSessions,
|
|
3629
|
-
clearOtherSessions: revokeOtherSessions,
|
|
3630
|
-
forgetPassword: (input, options) => executePostWithCompatibleInput(
|
|
3631
|
-
resolvedConfig,
|
|
3632
|
-
{ endpoint: "/forget-password", method: "POST" },
|
|
3633
|
-
input,
|
|
3634
|
-
options
|
|
3635
|
-
),
|
|
3636
|
-
resetPassword: (input, options) => executePostWithCompatibleInput(
|
|
3637
|
-
resolvedConfig,
|
|
3638
|
-
{ endpoint: "/reset-password", method: "POST" },
|
|
3639
|
-
input,
|
|
3640
|
-
options
|
|
3641
|
-
),
|
|
3642
|
-
resolveResetPasswordToken,
|
|
3643
|
-
verifyEmail: (input, options) => {
|
|
3644
|
-
const { payload, fetchOptions } = extractFetchOptions(input);
|
|
3645
|
-
const mergedOptions = mergeCallOptions(fetchOptions, options);
|
|
3646
|
-
const query = payload;
|
|
3647
|
-
return callAuthEndpoint(
|
|
3648
|
-
resolvedConfig,
|
|
3649
|
-
{ endpoint: "/verify-email", method: "GET" },
|
|
3650
|
-
void 0,
|
|
3651
|
-
query ? {
|
|
3652
|
-
token: query.token,
|
|
3653
|
-
callbackURL: query.callbackURL
|
|
3654
|
-
} : void 0,
|
|
3655
|
-
mergedOptions
|
|
3656
|
-
);
|
|
3657
|
-
},
|
|
3658
|
-
sendVerificationEmail: (input, options) => executePostWithCompatibleInput(
|
|
3659
|
-
resolvedConfig,
|
|
3660
|
-
{ endpoint: "/send-verification-email", method: "POST" },
|
|
3661
|
-
input,
|
|
3662
|
-
options
|
|
3663
|
-
),
|
|
3664
|
-
changeEmail: (input, options) => executePostWithCompatibleInput(
|
|
3665
|
-
resolvedConfig,
|
|
3666
|
-
{ endpoint: "/change-email", method: "POST" },
|
|
3667
|
-
input,
|
|
3668
|
-
options
|
|
3669
|
-
),
|
|
3670
|
-
changePassword: (input, options) => executePostWithCompatibleInput(
|
|
3671
|
-
resolvedConfig,
|
|
3672
|
-
{ endpoint: "/change-password", method: "POST" },
|
|
3673
|
-
input,
|
|
3674
|
-
options
|
|
3675
|
-
),
|
|
3676
|
-
updateUser: (input, options) => executePostWithCompatibleInput(
|
|
3677
|
-
resolvedConfig,
|
|
3678
|
-
{ endpoint: "/update-user", method: "POST" },
|
|
3679
|
-
input,
|
|
3680
|
-
options
|
|
3681
|
-
),
|
|
3682
|
-
deleteUser,
|
|
3683
|
-
deleteUserCallback,
|
|
3684
|
-
linkSocial: (input, options) => executePostWithCompatibleInput(
|
|
3685
|
-
resolvedConfig,
|
|
3686
|
-
{ endpoint: "/link-social", method: "POST" },
|
|
3687
|
-
input,
|
|
3688
|
-
options
|
|
3689
|
-
),
|
|
3690
|
-
listAccounts: (input, options) => executeGetWithCompatibleInput(
|
|
3691
|
-
resolvedConfig,
|
|
3692
|
-
{ endpoint: "/list-accounts", method: "GET" },
|
|
3693
|
-
input,
|
|
3694
|
-
options
|
|
3695
|
-
),
|
|
3696
|
-
unlinkAccount: (input, options) => executePostWithCompatibleInput(
|
|
3697
|
-
resolvedConfig,
|
|
3698
|
-
{ endpoint: "/unlink-account", method: "POST" },
|
|
3699
|
-
input,
|
|
3700
|
-
options
|
|
3701
|
-
),
|
|
3702
|
-
refreshToken: (input, options) => executePostWithCompatibleInput(
|
|
3703
|
-
resolvedConfig,
|
|
3704
|
-
{ endpoint: "/refresh-token", method: "POST" },
|
|
3705
|
-
input,
|
|
3706
|
-
options
|
|
3707
|
-
),
|
|
3708
|
-
getAccessToken: (input, options) => executePostWithCompatibleInput(
|
|
3709
|
-
resolvedConfig,
|
|
3710
|
-
{ endpoint: "/get-access-token", method: "POST" },
|
|
3711
|
-
input,
|
|
3712
|
-
options
|
|
3713
|
-
)
|
|
4657
|
+
...generated,
|
|
4658
|
+
configPath,
|
|
4659
|
+
writtenFiles
|
|
3714
4660
|
};
|
|
3715
4661
|
}
|
|
3716
4662
|
|
|
@@ -3743,6 +4689,7 @@ exports.loadGeneratorConfig = loadGeneratorConfig;
|
|
|
3743
4689
|
exports.normalizeAthenaError = normalizeAthenaError;
|
|
3744
4690
|
exports.normalizeGeneratorConfig = normalizeGeneratorConfig;
|
|
3745
4691
|
exports.normalizeSchemaSelection = normalizeSchemaSelection;
|
|
4692
|
+
exports.parseBooleanFlag = parseBooleanFlag;
|
|
3746
4693
|
exports.requireAffected = requireAffected;
|
|
3747
4694
|
exports.requireSuccess = requireSuccess;
|
|
3748
4695
|
exports.resolveGeneratorProvider = resolveGeneratorProvider;
|