@xylex-group/athena 2.1.2 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +306 -117
- package/dist/browser.cjs +2151 -194
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +14 -14
- package/dist/browser.d.ts +14 -14
- package/dist/browser.js +2146 -194
- package/dist/browser.js.map +1 -1
- package/dist/cli/index.cjs +2035 -172
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +3 -3
- package/dist/cli/index.d.ts +3 -3
- package/dist/cli/index.js +2036 -173
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +2166 -190
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +2162 -191
- package/dist/index.js.map +1 -1
- package/dist/{model-form-2hqmoOUX.d.ts → model-form-C0FAbOaf.d.ts} +97 -2
- package/dist/{model-form-Cy-zaO0u.d.cts → model-form-GzTqhEzM.d.cts} +97 -2
- package/dist/{pipeline-BOPszLsL.d.ts → pipeline-CR4V15jF.d.ts} +1 -1
- package/dist/{pipeline-E3FDbs4W.d.cts → pipeline-DZeExYMA.d.cts} +1 -1
- package/dist/{client-BX0NQqOn.d.ts → react-email-BuApZuyG.d.ts} +362 -174
- package/dist/{client-dpAp-NZK.d.cts → react-email-CQJq92zQ.d.cts} +362 -174
- package/dist/react.cjs +279 -21
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +4 -4
- package/dist/react.d.ts +4 -4
- package/dist/react.js +279 -21
- package/dist/react.js.map +1 -1
- package/dist/{types-BaBzjwXr.d.cts → types-09Q4D86N.d.cts} +24 -2
- package/dist/{types-BaBzjwXr.d.ts → types-09Q4D86N.d.ts} +24 -2
- package/dist/{types-CpqL-pZx.d.cts → types-D1JvL21V.d.cts} +1 -1
- package/dist/{types-CeBPrnGj.d.ts → types-DU3gNdFv.d.ts} +1 -1
- package/dist/utils.cjs +153 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +23 -0
- package/dist/utils.d.ts +23 -0
- package/dist/utils.js +146 -0
- package/dist/utils.js.map +1 -0
- package/package.json +74 -16
package/dist/react.cjs
CHANGED
|
@@ -65,8 +65,74 @@ function isAthenaGatewayError(error) {
|
|
|
65
65
|
return error instanceof AthenaGatewayError;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
// src/gateway/url.ts
|
|
69
|
+
var ATHENA_DEFAULT_BASE_URL = "https://athena-db.com";
|
|
70
|
+
function describeReceivedValue(value) {
|
|
71
|
+
if (value === void 0) return "undefined";
|
|
72
|
+
if (value === null) return "null";
|
|
73
|
+
if (typeof value === "string") {
|
|
74
|
+
return value.trim().length > 0 ? JSON.stringify(value) : "an empty string";
|
|
75
|
+
}
|
|
76
|
+
return `${typeof value} ${JSON.stringify(value)}`;
|
|
77
|
+
}
|
|
78
|
+
function invalidBaseUrlError(message, hint) {
|
|
79
|
+
return new AthenaGatewayError({
|
|
80
|
+
code: "INVALID_URL",
|
|
81
|
+
message,
|
|
82
|
+
status: 0,
|
|
83
|
+
hint
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function normalizeAthenaGatewayBaseUrl(input, options = {}) {
|
|
87
|
+
const label = options.label ?? "Athena gateway base URL";
|
|
88
|
+
const candidate = input ?? options.defaultBaseUrl;
|
|
89
|
+
if (candidate === void 0 || candidate === null) {
|
|
90
|
+
throw invalidBaseUrlError(
|
|
91
|
+
`${label} must be a non-empty absolute http(s) URL. Received ${describeReceivedValue(input)}.`,
|
|
92
|
+
'Set ATHENA_URL (or pass createClient(url, ...)) to a full URL such as "https://mirror3.athena-db.com".'
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
const trimmed = candidate.trim();
|
|
96
|
+
if (!trimmed) {
|
|
97
|
+
throw invalidBaseUrlError(
|
|
98
|
+
`${label} must be a non-empty absolute http(s) URL. Received ${describeReceivedValue(candidate)}.`,
|
|
99
|
+
'Set ATHENA_URL (or pass createClient(url, ...)) to a full URL such as "https://mirror3.athena-db.com".'
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
let parsed;
|
|
103
|
+
try {
|
|
104
|
+
parsed = new URL(trimmed);
|
|
105
|
+
} catch {
|
|
106
|
+
throw invalidBaseUrlError(
|
|
107
|
+
`${label} must be a valid absolute http(s) URL. Received ${describeReceivedValue(candidate)}.`,
|
|
108
|
+
'Use a full URL including the protocol, for example "https://mirror3.athena-db.com".'
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
112
|
+
throw invalidBaseUrlError(
|
|
113
|
+
`${label} must use http or https. Received ${JSON.stringify(trimmed)}.`,
|
|
114
|
+
'Use an Athena gateway URL such as "https://mirror3.athena-db.com".'
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
if (parsed.search || parsed.hash) {
|
|
118
|
+
throw invalidBaseUrlError(
|
|
119
|
+
`${label} must not include query parameters or hash fragments. Received ${JSON.stringify(trimmed)}.`,
|
|
120
|
+
'Pass only the base URL. Endpoint paths such as "/gateway/fetch" are appended by the SDK.'
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
return parsed.toString().replace(/\/+$/, "");
|
|
124
|
+
}
|
|
125
|
+
function buildAthenaGatewayUrl(baseUrl, path) {
|
|
126
|
+
if (!path.startsWith("/")) {
|
|
127
|
+
throw invalidBaseUrlError(
|
|
128
|
+
`Athena gateway path must start with "/". Received ${JSON.stringify(path)}.`,
|
|
129
|
+
'Use a leading slash such as "/gateway/fetch" or "/".'
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
return `${baseUrl}${path}`;
|
|
133
|
+
}
|
|
134
|
+
|
|
68
135
|
// src/gateway/client.ts
|
|
69
|
-
var DEFAULT_BASE_URL = "https://athena-db.com";
|
|
70
136
|
var DEFAULT_CLIENT = "railway_direct";
|
|
71
137
|
var FALLBACK_SDK_VERSION = "1.3.0";
|
|
72
138
|
var SDK_NAME = "xylex-group/athena";
|
|
@@ -93,23 +159,39 @@ function normalizeHeaderValue(value) {
|
|
|
93
159
|
function isRecord(value) {
|
|
94
160
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
95
161
|
}
|
|
162
|
+
function nonEmptyString(value) {
|
|
163
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
164
|
+
}
|
|
165
|
+
function resolveStructuredErrorPayload(payload) {
|
|
166
|
+
if (!isRecord(payload)) return null;
|
|
167
|
+
return isRecord(payload.error) ? payload.error : payload;
|
|
168
|
+
}
|
|
96
169
|
function resolveRequestId(headers) {
|
|
97
170
|
return headers.get("x-request-id") ?? headers.get("x-correlation-id") ?? headers.get("x-athena-request-id") ?? void 0;
|
|
98
171
|
}
|
|
99
172
|
function resolveErrorMessage(payload, fallback) {
|
|
100
|
-
|
|
101
|
-
|
|
173
|
+
const structuredPayload = resolveStructuredErrorPayload(payload);
|
|
174
|
+
if (structuredPayload) {
|
|
175
|
+
const messageCandidates = [structuredPayload.message, structuredPayload.error, structuredPayload.details];
|
|
102
176
|
for (const candidate of messageCandidates) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
177
|
+
const resolved = nonEmptyString(candidate);
|
|
178
|
+
if (resolved) return resolved;
|
|
106
179
|
}
|
|
107
180
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
181
|
+
const rawMessage = nonEmptyString(payload);
|
|
182
|
+
if (rawMessage) return rawMessage;
|
|
111
183
|
return fallback;
|
|
112
184
|
}
|
|
185
|
+
function resolveErrorHint(payload) {
|
|
186
|
+
const structuredPayload = resolveStructuredErrorPayload(payload);
|
|
187
|
+
return structuredPayload ? nonEmptyString(structuredPayload.hint) : void 0;
|
|
188
|
+
}
|
|
189
|
+
function resolveStatusText(response, payload) {
|
|
190
|
+
const rawStatusText = nonEmptyString(response.statusText);
|
|
191
|
+
if (rawStatusText) return rawStatusText;
|
|
192
|
+
const payloadRecord = isRecord(payload) ? payload : null;
|
|
193
|
+
return payloadRecord ? nonEmptyString(payloadRecord.statusText) ?? null : null;
|
|
194
|
+
}
|
|
113
195
|
function detailsFromError(error) {
|
|
114
196
|
return error.toDetails();
|
|
115
197
|
}
|
|
@@ -247,9 +329,168 @@ function buildHeaders(config, options) {
|
|
|
247
329
|
});
|
|
248
330
|
return headers;
|
|
249
331
|
}
|
|
332
|
+
function toInvalidUrlResponse(error, endpoint, method) {
|
|
333
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
334
|
+
const gatewayError = error instanceof AthenaGatewayError ? error : new AthenaGatewayError({
|
|
335
|
+
code: "INVALID_URL",
|
|
336
|
+
message,
|
|
337
|
+
status: 0,
|
|
338
|
+
endpoint,
|
|
339
|
+
method,
|
|
340
|
+
cause: message,
|
|
341
|
+
hint: "Set ATHENA_URL to a full http(s) URL before running queries."
|
|
342
|
+
});
|
|
343
|
+
return {
|
|
344
|
+
ok: false,
|
|
345
|
+
status: 0,
|
|
346
|
+
statusText: null,
|
|
347
|
+
data: null,
|
|
348
|
+
error: gatewayError.message,
|
|
349
|
+
errorDetails: detailsFromError(
|
|
350
|
+
new AthenaGatewayError({
|
|
351
|
+
code: gatewayError.code,
|
|
352
|
+
message: gatewayError.message,
|
|
353
|
+
status: gatewayError.status,
|
|
354
|
+
endpoint,
|
|
355
|
+
method,
|
|
356
|
+
requestId: gatewayError.requestId,
|
|
357
|
+
hint: gatewayError.hint,
|
|
358
|
+
cause: gatewayError.causeDetail
|
|
359
|
+
})
|
|
360
|
+
),
|
|
361
|
+
raw: null
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
function resolveGatewayBaseUrl(input) {
|
|
365
|
+
return normalizeAthenaGatewayBaseUrl(input, {
|
|
366
|
+
defaultBaseUrl: ATHENA_DEFAULT_BASE_URL
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
function resolveProbePath(path) {
|
|
370
|
+
if (!path) return "/";
|
|
371
|
+
if (!path.startsWith("/")) {
|
|
372
|
+
throw new AthenaGatewayError({
|
|
373
|
+
code: "INVALID_URL",
|
|
374
|
+
message: `Athena gateway probe path must start with "/". Received ${JSON.stringify(path)}.`,
|
|
375
|
+
status: 0,
|
|
376
|
+
hint: 'Use a leading slash such as "/" or "/health".'
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
return path;
|
|
380
|
+
}
|
|
381
|
+
function mergeConnectionHeaders(baseHeaders, headers) {
|
|
382
|
+
const merged = {
|
|
383
|
+
...baseHeaders,
|
|
384
|
+
...headers ?? {}
|
|
385
|
+
};
|
|
386
|
+
if (!merged["X-Athena-Sdk"] && !merged["x-athena-sdk"]) {
|
|
387
|
+
merged["X-Athena-Sdk"] = SDK_HEADER_VALUE;
|
|
388
|
+
}
|
|
389
|
+
return merged;
|
|
390
|
+
}
|
|
391
|
+
async function performConnectionCheck(baseUrl, requestHeaders, options) {
|
|
392
|
+
const path = resolveProbePath(options?.path);
|
|
393
|
+
const url = buildAthenaGatewayUrl(baseUrl, path);
|
|
394
|
+
try {
|
|
395
|
+
const response = await fetch(url, {
|
|
396
|
+
method: "GET",
|
|
397
|
+
headers: mergeConnectionHeaders(requestHeaders, options?.headers),
|
|
398
|
+
signal: options?.signal
|
|
399
|
+
});
|
|
400
|
+
const rawText = await response.text();
|
|
401
|
+
const requestId = resolveRequestId(response.headers);
|
|
402
|
+
const parsedBody = parseResponseBody(
|
|
403
|
+
rawText ?? "",
|
|
404
|
+
response.headers.get("content-type")
|
|
405
|
+
);
|
|
406
|
+
if (parsedBody.parseFailed) {
|
|
407
|
+
const invalidJsonError = new AthenaGatewayError({
|
|
408
|
+
code: "INVALID_JSON",
|
|
409
|
+
message: "Gateway probe returned malformed JSON",
|
|
410
|
+
status: response.status,
|
|
411
|
+
method: "GET",
|
|
412
|
+
requestId,
|
|
413
|
+
hint: "Verify the gateway response body is valid JSON.",
|
|
414
|
+
cause: rawText.slice(0, 300)
|
|
415
|
+
});
|
|
416
|
+
return {
|
|
417
|
+
ok: false,
|
|
418
|
+
reachable: true,
|
|
419
|
+
status: response.status,
|
|
420
|
+
statusText: resolveStatusText(response, parsedBody.parsed),
|
|
421
|
+
baseUrl,
|
|
422
|
+
url,
|
|
423
|
+
error: invalidJsonError.message,
|
|
424
|
+
errorDetails: detailsFromError(invalidJsonError),
|
|
425
|
+
raw: parsedBody.parsed
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
const parsed = parsedBody.parsed;
|
|
429
|
+
if (!response.ok) {
|
|
430
|
+
const httpError = new AthenaGatewayError({
|
|
431
|
+
code: "HTTP_ERROR",
|
|
432
|
+
message: resolveErrorMessage(
|
|
433
|
+
parsed,
|
|
434
|
+
`Athena gateway GET ${path} failed with status ${response.status}`
|
|
435
|
+
),
|
|
436
|
+
status: response.status,
|
|
437
|
+
method: "GET",
|
|
438
|
+
requestId,
|
|
439
|
+
hint: resolveErrorHint(parsed)
|
|
440
|
+
});
|
|
441
|
+
return {
|
|
442
|
+
ok: false,
|
|
443
|
+
reachable: true,
|
|
444
|
+
status: response.status,
|
|
445
|
+
statusText: resolveStatusText(response, parsed),
|
|
446
|
+
baseUrl,
|
|
447
|
+
url,
|
|
448
|
+
error: httpError.message,
|
|
449
|
+
errorDetails: detailsFromError(httpError),
|
|
450
|
+
raw: parsed
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
return {
|
|
454
|
+
ok: true,
|
|
455
|
+
reachable: true,
|
|
456
|
+
status: response.status,
|
|
457
|
+
statusText: resolveStatusText(response, parsed),
|
|
458
|
+
baseUrl,
|
|
459
|
+
url,
|
|
460
|
+
error: void 0,
|
|
461
|
+
errorDetails: null,
|
|
462
|
+
raw: parsed
|
|
463
|
+
};
|
|
464
|
+
} catch (callError) {
|
|
465
|
+
const message = callError instanceof Error ? callError.message : String(callError);
|
|
466
|
+
const networkError = new AthenaGatewayError({
|
|
467
|
+
code: "NETWORK_ERROR",
|
|
468
|
+
message: `Network error while probing Athena gateway ${url}: ${message}`,
|
|
469
|
+
method: "GET",
|
|
470
|
+
cause: message,
|
|
471
|
+
hint: "Check gateway URL, DNS, and network reachability."
|
|
472
|
+
});
|
|
473
|
+
return {
|
|
474
|
+
ok: false,
|
|
475
|
+
reachable: false,
|
|
476
|
+
status: 0,
|
|
477
|
+
statusText: null,
|
|
478
|
+
baseUrl,
|
|
479
|
+
url,
|
|
480
|
+
error: networkError.message,
|
|
481
|
+
errorDetails: detailsFromError(networkError),
|
|
482
|
+
raw: null
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
}
|
|
250
486
|
async function callAthena(config, endpoint, method, payload, options) {
|
|
251
|
-
|
|
252
|
-
|
|
487
|
+
let baseUrl;
|
|
488
|
+
try {
|
|
489
|
+
baseUrl = resolveGatewayBaseUrl(options?.baseUrl ?? config.baseUrl);
|
|
490
|
+
} catch (error) {
|
|
491
|
+
return toInvalidUrlResponse(error, endpoint, method);
|
|
492
|
+
}
|
|
493
|
+
const url = buildAthenaGatewayUrl(baseUrl, endpoint);
|
|
253
494
|
const headers = buildHeaders(config, options);
|
|
254
495
|
try {
|
|
255
496
|
const requestInit = {
|
|
@@ -280,6 +521,7 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
280
521
|
return {
|
|
281
522
|
ok: false,
|
|
282
523
|
status: response.status,
|
|
524
|
+
statusText: resolveStatusText(response, parsedBody.parsed),
|
|
283
525
|
data: null,
|
|
284
526
|
error: invalidJsonError.message,
|
|
285
527
|
errorDetails: detailsFromError(invalidJsonError),
|
|
@@ -298,11 +540,13 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
298
540
|
status: response.status,
|
|
299
541
|
endpoint,
|
|
300
542
|
method,
|
|
301
|
-
requestId
|
|
543
|
+
requestId,
|
|
544
|
+
hint: resolveErrorHint(parsed)
|
|
302
545
|
});
|
|
303
546
|
return {
|
|
304
547
|
ok: false,
|
|
305
548
|
status: response.status,
|
|
549
|
+
statusText: resolveStatusText(response, parsed),
|
|
306
550
|
data: null,
|
|
307
551
|
error: httpError.message,
|
|
308
552
|
errorDetails: detailsFromError(httpError),
|
|
@@ -314,6 +558,7 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
314
558
|
return {
|
|
315
559
|
ok: true,
|
|
316
560
|
status: response.status,
|
|
561
|
+
statusText: resolveStatusText(response, parsed),
|
|
317
562
|
data: payloadData ?? null,
|
|
318
563
|
count: payloadCount,
|
|
319
564
|
error: void 0,
|
|
@@ -333,6 +578,7 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
333
578
|
return {
|
|
334
579
|
ok: false,
|
|
335
580
|
status: 0,
|
|
581
|
+
statusText: null,
|
|
336
582
|
data: null,
|
|
337
583
|
error: networkError.message,
|
|
338
584
|
errorDetails: detailsFromError(networkError),
|
|
@@ -341,32 +587,44 @@ async function callAthena(config, endpoint, method, payload, options) {
|
|
|
341
587
|
}
|
|
342
588
|
}
|
|
343
589
|
function createAthenaGatewayClient(config = {}) {
|
|
590
|
+
const normalizedBaseUrl = resolveGatewayBaseUrl(config.baseUrl);
|
|
591
|
+
const normalizedConfig = {
|
|
592
|
+
...config,
|
|
593
|
+
baseUrl: normalizedBaseUrl
|
|
594
|
+
};
|
|
344
595
|
return {
|
|
345
|
-
baseUrl:
|
|
596
|
+
baseUrl: normalizedBaseUrl,
|
|
346
597
|
buildHeaders(options) {
|
|
347
|
-
return buildHeaders(
|
|
598
|
+
return buildHeaders(normalizedConfig, options);
|
|
599
|
+
},
|
|
600
|
+
verifyConnection(options) {
|
|
601
|
+
return performConnectionCheck(
|
|
602
|
+
normalizedBaseUrl,
|
|
603
|
+
buildHeaders(normalizedConfig),
|
|
604
|
+
options
|
|
605
|
+
);
|
|
348
606
|
},
|
|
349
607
|
fetchGateway(payload, options) {
|
|
350
|
-
return callAthena(
|
|
608
|
+
return callAthena(normalizedConfig, "/gateway/fetch", "POST", payload, options);
|
|
351
609
|
},
|
|
352
610
|
insertGateway(payload, options) {
|
|
353
|
-
return callAthena(
|
|
611
|
+
return callAthena(normalizedConfig, "/gateway/insert", "PUT", payload, options);
|
|
354
612
|
},
|
|
355
613
|
updateGateway(payload, options) {
|
|
356
|
-
return callAthena(
|
|
614
|
+
return callAthena(normalizedConfig, "/gateway/update", "POST", payload, options);
|
|
357
615
|
},
|
|
358
616
|
deleteGateway(payload, options) {
|
|
359
|
-
return callAthena(
|
|
617
|
+
return callAthena(normalizedConfig, "/gateway/delete", "DELETE", payload, options);
|
|
360
618
|
},
|
|
361
619
|
rpcGateway(payload, options) {
|
|
362
620
|
if (options?.get) {
|
|
363
621
|
const endpoint = buildRpcGetEndpoint(payload);
|
|
364
|
-
return callAthena(
|
|
622
|
+
return callAthena(normalizedConfig, endpoint, "GET", null, options);
|
|
365
623
|
}
|
|
366
|
-
return callAthena(
|
|
624
|
+
return callAthena(normalizedConfig, "/gateway/rpc", "POST", payload, options);
|
|
367
625
|
},
|
|
368
626
|
queryGateway(payload, options) {
|
|
369
|
-
return callAthena(
|
|
627
|
+
return callAthena(normalizedConfig, "/gateway/query", "POST", payload, options);
|
|
370
628
|
}
|
|
371
629
|
};
|
|
372
630
|
}
|