@typedb/driver-http 3.14.0-rc0 → 3.15.0-rc3
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 +13 -0
- package/dist/index.cjs +189 -49
- package/dist/index.d.ts +24 -2
- package/dist/index.mjs +183 -43
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,3 +45,16 @@ if (answer.answerType === "conceptRows") {
|
|
|
45
45
|
})
|
|
46
46
|
}
|
|
47
47
|
```
|
|
48
|
+
|
|
49
|
+
To connect over TLS to a server whose certificate is signed by a private CA, pass the CA certificate file in Node.js:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
const driver = new TypeDBHttpDriver({
|
|
53
|
+
username: "admin",
|
|
54
|
+
password: "password",
|
|
55
|
+
addresses: [ "https://typedb.example.com:8000" ],
|
|
56
|
+
tls: { rootCAPath: "ca.pem" },
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
With a root CA, every address must use `https`. In browsers, add the CA to the operating system's or the browser's trust store instead.
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/params.ts
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/params.ts
|
|
2
2
|
function isBasicParams(params) {
|
|
3
3
|
return `addresses` in params;
|
|
4
4
|
}
|
|
@@ -47,6 +47,126 @@ function allOrigins(params) {
|
|
|
47
47
|
else return params.translatedAddresses.map((ta) => ta.external);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/transport.ts
|
|
51
|
+
var CONNECT_TIMEOUT_MILLIS = 1e4;
|
|
52
|
+
var REQUEST_INACTIVITY_TIMEOUT_MILLIS = 3e5;
|
|
53
|
+
var KEEP_ALIVE_SOCKET_TIMEOUT_MILLIS = 5e3;
|
|
54
|
+
var PEM_CERTIFICATE_REGEX = /-----BEGIN (TRUSTED )?CERTIFICATE-----.*?-----END \1CERTIFICATE-----/gs;
|
|
55
|
+
var TlsConfigError = class extends Error {
|
|
56
|
+
};
|
|
57
|
+
function createFetch(tls, origins) {
|
|
58
|
+
const rootCAPath = _optionalChain([tls, 'optionalAccess', _ => _.rootCAPath]);
|
|
59
|
+
if (rootCAPath === void 0) return (url, init) => fetch(url, init);
|
|
60
|
+
const plainOrigin = origins.find((origin) => !isHttps(origin));
|
|
61
|
+
const plainOriginError = plainOrigin === void 0 ? void 0 : plainHttpError(plainOrigin);
|
|
62
|
+
let httpsClient;
|
|
63
|
+
return async (url, init) => {
|
|
64
|
+
if (plainOriginError !== void 0) throw plainOriginError;
|
|
65
|
+
if (!isHttps(url)) {
|
|
66
|
+
const { protocol, host } = new URL(url);
|
|
67
|
+
throw plainHttpError(`${protocol}//${host}`);
|
|
68
|
+
}
|
|
69
|
+
_nullishCoalesce(httpsClient, () => ( (httpsClient = createHttpsClient(rootCAPath).catch((error) => {
|
|
70
|
+
httpsClient = void 0;
|
|
71
|
+
throw error;
|
|
72
|
+
}))));
|
|
73
|
+
const { https, agent } = await httpsClient;
|
|
74
|
+
return requestWithAgent(https, agent, url, init);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async function createHttpsClient(rootCAPath) {
|
|
78
|
+
if (!isNodeJs()) {
|
|
79
|
+
throw new TlsConfigError("A TLS root CA can only be set in Node.js: in browsers, add the CA to the trust store.");
|
|
80
|
+
}
|
|
81
|
+
let https;
|
|
82
|
+
let fs;
|
|
83
|
+
let crypto;
|
|
84
|
+
try {
|
|
85
|
+
[https, fs, crypto] = await Promise.all([
|
|
86
|
+
importNodeModule("node:https"),
|
|
87
|
+
importNodeModule("node:fs/promises"),
|
|
88
|
+
importNodeModule("node:crypto")
|
|
89
|
+
]);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
throw new TlsConfigError(`Cannot load the Node.js modules for TLS: ${error.message}`);
|
|
92
|
+
}
|
|
93
|
+
let rootCA;
|
|
94
|
+
try {
|
|
95
|
+
rootCA = await fs.readFile(rootCAPath, "utf8");
|
|
96
|
+
} catch (error) {
|
|
97
|
+
throw new TlsConfigError(`Cannot read the TLS root CA file '${rootCAPath}': ${error.message}`);
|
|
98
|
+
}
|
|
99
|
+
const certificates = _nullishCoalesce(rootCA.match(PEM_CERTIFICATE_REGEX), () => ( []));
|
|
100
|
+
if (certificates.length === 0) {
|
|
101
|
+
throw new TlsConfigError(`The TLS root CA file '${rootCAPath}' does not contain a PEM certificate.`);
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
certificates.forEach((certificate) => new crypto.X509Certificate(certificate));
|
|
105
|
+
} catch (error) {
|
|
106
|
+
throw new TlsConfigError(
|
|
107
|
+
`The TLS root CA file '${rootCAPath}' contains an invalid certificate: ${error.message}`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
const agent = new https.Agent({ ca: rootCA, keepAlive: true, timeout: KEEP_ALIVE_SOCKET_TIMEOUT_MILLIS });
|
|
111
|
+
return { https, agent };
|
|
112
|
+
}
|
|
113
|
+
function plainHttpError(origin) {
|
|
114
|
+
return new TlsConfigError(`A TLS root CA is set, but ${origin} does not use https.`);
|
|
115
|
+
}
|
|
116
|
+
function isHttps(url) {
|
|
117
|
+
try {
|
|
118
|
+
return new URL(url).protocol === "https:";
|
|
119
|
+
} catch (e3) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function isNodeJs() {
|
|
124
|
+
return typeof process !== "undefined" && typeof _optionalChain([process, 'access', _2 => _2.versions, 'optionalAccess', _3 => _3.node]) === "string";
|
|
125
|
+
}
|
|
126
|
+
function importNodeModule(specifier) {
|
|
127
|
+
return Promise.resolve().then(() => _interopRequireWildcard(require(
|
|
128
|
+
/* @vite-ignore */
|
|
129
|
+
/* webpackIgnore: true */
|
|
130
|
+
specifier
|
|
131
|
+
)));
|
|
132
|
+
}
|
|
133
|
+
function requestWithAgent(https, agent, url, init) {
|
|
134
|
+
return new Promise((resolve, reject) => {
|
|
135
|
+
const options = { method: init.method, headers: init.headers, agent };
|
|
136
|
+
const request = https.request(url, options, (response) => {
|
|
137
|
+
const chunks = [];
|
|
138
|
+
response.on("data", (chunk) => chunks.push(chunk));
|
|
139
|
+
response.on("error", reject);
|
|
140
|
+
response.on("end", () => {
|
|
141
|
+
try {
|
|
142
|
+
const status = _nullishCoalesce(response.statusCode, () => ( 0));
|
|
143
|
+
const headers = new Headers();
|
|
144
|
+
for (const [name, value] of Object.entries(response.headers)) {
|
|
145
|
+
if (value !== void 0) headers.set(name, Array.isArray(value) ? value.join(", ") : value);
|
|
146
|
+
}
|
|
147
|
+
const body = status === 204 || status === 304 ? null : Buffer.concat(chunks);
|
|
148
|
+
resolve(new Response(body, { status, statusText: response.statusMessage, headers }));
|
|
149
|
+
} catch (error) {
|
|
150
|
+
reject(error);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
request.on("error", reject);
|
|
155
|
+
request.on("socket", (socket) => {
|
|
156
|
+
if (!socket.connecting) return;
|
|
157
|
+
socket.setTimeout(0);
|
|
158
|
+
const connectTimeout = setTimeout(
|
|
159
|
+
() => request.destroy(new Error("Connection timed out")),
|
|
160
|
+
CONNECT_TIMEOUT_MILLIS
|
|
161
|
+
);
|
|
162
|
+
socket.once("secureConnect", () => clearTimeout(connectTimeout));
|
|
163
|
+
socket.once("close", () => clearTimeout(connectTimeout));
|
|
164
|
+
});
|
|
165
|
+
request.setTimeout(REQUEST_INACTIVITY_TIMEOUT_MILLIS, () => request.destroy(new Error("Request timed out")));
|
|
166
|
+
request.end(init.body);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
50
170
|
// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/response.ts
|
|
51
171
|
function isApiError(err) {
|
|
52
172
|
return err != null && typeof err.code === "string" && typeof err.message === "string";
|
|
@@ -293,25 +413,38 @@ function isDigit(c) {
|
|
|
293
413
|
|
|
294
414
|
// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/analyzed-conjunction.ts
|
|
295
415
|
function getVariableName(structure, variable) {
|
|
296
|
-
return _optionalChain([structure, 'access',
|
|
416
|
+
return _optionalChain([structure, 'access', _4 => _4.variables, 'access', _5 => _5[variable.id], 'optionalAccess', _6 => _6.name]);
|
|
297
417
|
}
|
|
298
418
|
|
|
299
419
|
// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/index.ts
|
|
300
420
|
var HTTP_UNAUTHORIZED = 401;
|
|
301
421
|
var HTTP_MISDIRECTED = 421;
|
|
302
|
-
var TRANSIENT_SIGNIN_ERROR_CODES = /* @__PURE__ */ new Set(["
|
|
422
|
+
var TRANSIENT_SIGNIN_ERROR_CODES = /* @__PURE__ */ new Set(["SRV14", "CSV8", "CSV9"]);
|
|
303
423
|
var PRIMARY_FAILOVER_RETRIES = 3;
|
|
304
424
|
var PRIMARY_SELECTION_WAIT_MS = 2e3;
|
|
305
425
|
function isApiErrResp(value) {
|
|
306
|
-
return
|
|
426
|
+
return "err" in value;
|
|
427
|
+
}
|
|
428
|
+
function isOriginFailure(value) {
|
|
429
|
+
return "failure" in value;
|
|
430
|
+
}
|
|
431
|
+
function tokenErrToResult(tokenResp, origin) {
|
|
432
|
+
const { code, message } = tokenResp.err;
|
|
433
|
+
if (TRANSIENT_SIGNIN_ERROR_CODES.has(code))
|
|
434
|
+
return { failure: `Server at ${origin} failed signin with [${code}] ${message}` };
|
|
435
|
+
else
|
|
436
|
+
return tokenResp;
|
|
307
437
|
}
|
|
308
|
-
function
|
|
309
|
-
|
|
438
|
+
function errorMessage(error) {
|
|
439
|
+
const reason = _nullishCoalesce(_optionalChain([error, 'optionalAccess', _7 => _7.cause]), () => ( error));
|
|
440
|
+
const { message, code } = _nullishCoalesce(reason, () => ( {}));
|
|
441
|
+
return (message || code || String(reason)).trim();
|
|
310
442
|
}
|
|
311
443
|
var TypeDBHttpDriver = class {
|
|
312
444
|
constructor(params) {
|
|
313
445
|
this.params = params;
|
|
314
446
|
this.currentOrigin = remoteOrigin(params);
|
|
447
|
+
this.fetch = createFetch(params.tls, allOrigins(params));
|
|
315
448
|
}
|
|
316
449
|
getDatabases() {
|
|
317
450
|
return this.apiGet(`/v1/databases`);
|
|
@@ -428,59 +561,58 @@ var TypeDBHttpDriver = class {
|
|
|
428
561
|
const initial = await this.tryApiReq(method, path, body, options);
|
|
429
562
|
if (isApiErrResp(initial)) return initial;
|
|
430
563
|
let result = initial;
|
|
431
|
-
if (result
|
|
564
|
+
if (!isOriginFailure(result) && result.status === HTTP_MISDIRECTED) {
|
|
432
565
|
const redirected = await this.followMisdirected(result, method, path, body, options);
|
|
433
566
|
if (isApiErrResp(redirected)) return redirected;
|
|
434
567
|
result = redirected;
|
|
435
568
|
}
|
|
436
|
-
if (result
|
|
437
|
-
const
|
|
438
|
-
triedOrigins.add(startOrigin);
|
|
439
|
-
const fallback = await this.tryFallbackOrigins(method, path, body, options, triedOrigins);
|
|
569
|
+
if (isOriginFailure(result) || !result.ok) {
|
|
570
|
+
const fallback = await this.tryFallbackOrigins(method, path, body, options, triedOrigins, result);
|
|
440
571
|
if (isApiErrResp(fallback)) return fallback;
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
}
|
|
572
|
+
result = fallback;
|
|
573
|
+
}
|
|
574
|
+
if (isOriginFailure(result)) {
|
|
575
|
+
return driverError("HDR1", `Cannot connect to any server (last error: ${result.failure})`);
|
|
446
576
|
}
|
|
447
|
-
return
|
|
577
|
+
return result;
|
|
448
578
|
}
|
|
449
579
|
async tryApiReq(method, path, body, options) {
|
|
450
|
-
const
|
|
580
|
+
const origin = this.currentOrigin;
|
|
451
581
|
let tokenResp = await this.getToken();
|
|
452
|
-
if (
|
|
582
|
+
if (isOriginFailure(tokenResp)) return tokenResp;
|
|
583
|
+
if (isApiErrResp(tokenResp)) return tokenErrToResult(tokenResp, origin);
|
|
453
584
|
const bodyString = body !== void 0 ? stringifyJson(body) : void 0;
|
|
454
585
|
let headers = this.authHeaders(tokenResp.ok.token, options);
|
|
455
|
-
let resp;
|
|
456
|
-
|
|
457
|
-
resp = await fetch(url, { method, body: bodyString, headers });
|
|
458
|
-
} catch (e3) {
|
|
459
|
-
return null;
|
|
460
|
-
}
|
|
461
|
-
if (resp.status === HTTP_UNAUTHORIZED) {
|
|
586
|
+
let resp = await this.fetchFrom(origin, path, { method, body: bodyString, headers });
|
|
587
|
+
if (!isApiErrResp(resp) && !isOriginFailure(resp) && resp.status === HTTP_UNAUTHORIZED) {
|
|
462
588
|
tokenResp = await this.refreshToken();
|
|
463
|
-
if (
|
|
589
|
+
if (isOriginFailure(tokenResp)) return tokenResp;
|
|
590
|
+
if (isApiErrResp(tokenResp)) return tokenErrToResult(tokenResp, origin);
|
|
464
591
|
headers = this.authHeaders(tokenResp.ok.token, options);
|
|
465
|
-
|
|
466
|
-
resp = await fetch(url, { method, body: bodyString, headers });
|
|
467
|
-
} catch (e4) {
|
|
468
|
-
return null;
|
|
469
|
-
}
|
|
592
|
+
resp = await this.fetchFrom(origin, path, { method, body: bodyString, headers });
|
|
470
593
|
}
|
|
471
594
|
return resp;
|
|
472
595
|
}
|
|
596
|
+
async fetchFrom(origin, path, init) {
|
|
597
|
+
try {
|
|
598
|
+
return await this.fetch(`${origin}${path}`, init);
|
|
599
|
+
} catch (error) {
|
|
600
|
+
if (error instanceof TlsConfigError) return driverError("HDR3", error.message);
|
|
601
|
+
return { failure: `Cannot connect to server at ${origin}: ${errorMessage(error)}` };
|
|
602
|
+
}
|
|
603
|
+
}
|
|
473
604
|
async followMisdirected(resp, method, path, body, options) {
|
|
605
|
+
const origin = this.currentOrigin;
|
|
474
606
|
if (await this.switchToRedirectTarget(resp)) {
|
|
475
607
|
return await this.tryApiReq(method, path, body, options);
|
|
476
608
|
}
|
|
477
|
-
return
|
|
609
|
+
return { failure: `Server at ${origin} returned 421 Misdirected Request without another primary address` };
|
|
478
610
|
}
|
|
479
611
|
async switchToRedirectTarget(resp) {
|
|
480
612
|
let json;
|
|
481
613
|
try {
|
|
482
614
|
json = parseJson(await resp.text());
|
|
483
|
-
} catch (
|
|
615
|
+
} catch (e4) {
|
|
484
616
|
return false;
|
|
485
617
|
}
|
|
486
618
|
if (!isMisdirectedError(json)) return false;
|
|
@@ -489,33 +621,46 @@ var TypeDBHttpDriver = class {
|
|
|
489
621
|
this.switchOrigin(newOrigin);
|
|
490
622
|
return true;
|
|
491
623
|
}
|
|
492
|
-
async tryFallbackOrigins(method, path, body, options, triedOrigins) {
|
|
624
|
+
async tryFallbackOrigins(method, path, body, options, triedOrigins, startResult) {
|
|
625
|
+
const startOrigin = this.currentOrigin;
|
|
626
|
+
triedOrigins.add(startOrigin);
|
|
493
627
|
const origins = allOrigins(this.params);
|
|
494
628
|
let lastError = null;
|
|
629
|
+
let lastFailure = null;
|
|
495
630
|
for (const origin of origins) {
|
|
496
631
|
if (triedOrigins.has(origin)) continue;
|
|
497
632
|
this.switchOrigin(origin);
|
|
498
633
|
const initial = await this.tryApiReq(method, path, body, options);
|
|
499
|
-
if (initial
|
|
634
|
+
if (isOriginFailure(initial)) {
|
|
635
|
+
lastFailure = initial;
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
500
638
|
if (isApiErrResp(initial)) return initial;
|
|
501
639
|
let result = initial;
|
|
502
640
|
if (result.status === HTTP_MISDIRECTED) {
|
|
503
641
|
const redirected = await this.followMisdirected(result, method, path, body, options);
|
|
504
|
-
if (redirected
|
|
642
|
+
if (isOriginFailure(redirected)) {
|
|
643
|
+
lastFailure = redirected;
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
505
646
|
if (isApiErrResp(redirected)) return redirected;
|
|
506
647
|
result = redirected;
|
|
507
648
|
}
|
|
508
649
|
if (result.ok) return result;
|
|
509
650
|
lastError = result;
|
|
510
651
|
}
|
|
511
|
-
|
|
652
|
+
if (!isOriginFailure(startResult)) {
|
|
653
|
+
this.switchOrigin(startOrigin);
|
|
654
|
+
return startResult;
|
|
655
|
+
}
|
|
656
|
+
return _nullishCoalesce(_nullishCoalesce(lastError, () => ( lastFailure)), () => ( startResult));
|
|
512
657
|
}
|
|
513
658
|
switchOrigin(origin) {
|
|
514
659
|
this.currentOrigin = origin;
|
|
515
660
|
this.token = void 0;
|
|
516
661
|
}
|
|
517
662
|
authHeaders(token, options) {
|
|
518
|
-
return { "Authorization": `Bearer ${token}`, "Content-Type": "application/json", ..._optionalChain([options, 'optionalAccess',
|
|
663
|
+
return { "Authorization": `Bearer ${token}`, "Content-Type": "application/json", ..._optionalChain([options, 'optionalAccess', _8 => _8.headers]) };
|
|
519
664
|
}
|
|
520
665
|
getToken() {
|
|
521
666
|
if (this.token) {
|
|
@@ -527,26 +672,21 @@ var TypeDBHttpDriver = class {
|
|
|
527
672
|
return this.signinOnce();
|
|
528
673
|
}
|
|
529
674
|
async signinOnce() {
|
|
530
|
-
const url = `${this.currentOrigin}/v1/signin`;
|
|
531
675
|
const body = { username: this.params.username, password: this.params.password };
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
resp = await fetch(url, { method: "POST", body: stringifyJson(body), headers: { "Content-Type": "application/json" } });
|
|
535
|
-
} catch (e6) {
|
|
536
|
-
return driverError("HDR2", `Cannot connect to server at ${this.currentOrigin}`);
|
|
537
|
-
}
|
|
676
|
+
const resp = await this.fetchFrom(this.currentOrigin, "/v1/signin", { method: "POST", body: stringifyJson(body), headers: { "Content-Type": "application/json" } });
|
|
677
|
+
if (isApiErrResp(resp) || isOriginFailure(resp)) return resp;
|
|
538
678
|
const json = await this.jsonOrNull(resp);
|
|
539
|
-
if (resp.ok && typeof _optionalChain([json, 'optionalAccess',
|
|
679
|
+
if (resp.ok && typeof _optionalChain([json, 'optionalAccess', _9 => _9.token]) === "string") {
|
|
540
680
|
this.token = json.token;
|
|
541
681
|
return { ok: json };
|
|
542
682
|
}
|
|
543
683
|
if (isApiError(json)) return { err: json, status: resp.status };
|
|
544
|
-
return
|
|
684
|
+
return { failure: `Unexpected signin response from ${this.currentOrigin} (HTTP ${resp.status})` };
|
|
545
685
|
}
|
|
546
686
|
async jsonOrNull(resp) {
|
|
547
687
|
try {
|
|
548
688
|
return parseJson(await resp.text());
|
|
549
|
-
} catch (
|
|
689
|
+
} catch (e5) {
|
|
550
690
|
return null;
|
|
551
691
|
}
|
|
552
692
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,11 +2,26 @@ interface DriverParamsBasic {
|
|
|
2
2
|
username: string;
|
|
3
3
|
password: string;
|
|
4
4
|
addresses: string[];
|
|
5
|
+
tls?: DriverTlsConfig;
|
|
5
6
|
}
|
|
6
7
|
interface DriverParamsTranslated {
|
|
7
8
|
username: string;
|
|
8
9
|
password: string;
|
|
9
10
|
translatedAddresses: TranslatedAddress[];
|
|
11
|
+
tls?: DriverTlsConfig;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* TLS settings for `https` addresses. Without them, the driver trusts the certificate authorities that the
|
|
15
|
+
* runtime trusts by default.
|
|
16
|
+
*/
|
|
17
|
+
interface DriverTlsConfig {
|
|
18
|
+
/**
|
|
19
|
+
* The path to the PEM file with the certificate of the CA that signed the servers' certificates. When set, the
|
|
20
|
+
* driver trusts only this CA, and every address must use `https`. The file is read on the first request, and
|
|
21
|
+
* requests fail with `HDR3` if it cannot be used. Supported in Node.js only: browsers trust the certificates of
|
|
22
|
+
* their own trust store.
|
|
23
|
+
*/
|
|
24
|
+
rootCAPath?: string;
|
|
10
25
|
}
|
|
11
26
|
interface TranslatedAddress {
|
|
12
27
|
external: string;
|
|
@@ -123,7 +138,7 @@ type ConjunctionIndex$1 = number;
|
|
|
123
138
|
type VariableInfo = {
|
|
124
139
|
name: string | null;
|
|
125
140
|
};
|
|
126
|
-
type ConstraintAny = ConstraintIsa | ConstraintIsaExact | ConstraintHas | ConstraintLinks | ConstraintSub | ConstraintSubExact | ConstraintOwns | ConstraintRelates | ConstraintPlays | ConstraintExpression | ConstraintFunction | ConstraintComparison | ConstraintIs | ConstraintIid | ConstraintDeleteConcepts | ConstraintKind | ConstraintValue | ConstraintLabel | ConstraintOr | ConstraintNot | ConstraintTry;
|
|
141
|
+
type ConstraintAny = ConstraintIsa | ConstraintIsaExact | ConstraintHas | ConstraintLinks | ConstraintSub | ConstraintSubExact | ConstraintOwns | ConstraintRelates | ConstraintPlays | ConstraintExpression | ConstraintFunction | ConstraintComparison | ConstraintIs | ConstraintIid | ConstraintDeleteConcepts | ConstraintKind | ConstraintValue | ConstraintIsSet | ConstraintLabel | ConstraintOr | ConstraintNot | ConstraintTry;
|
|
127
142
|
type ConstraintSpan = {
|
|
128
143
|
begin: number;
|
|
129
144
|
end: number;
|
|
@@ -233,6 +248,11 @@ interface ConstraintValue {
|
|
|
233
248
|
attributeType: ConstraintVertexVariable;
|
|
234
249
|
valueType: string;
|
|
235
250
|
}
|
|
251
|
+
interface ConstraintIsSet {
|
|
252
|
+
tag: "isSet";
|
|
253
|
+
textSpan: ConstraintSpan;
|
|
254
|
+
variables: ConstraintVertexVariable[];
|
|
255
|
+
}
|
|
236
256
|
interface ConstraintKind {
|
|
237
257
|
tag: "kind";
|
|
238
258
|
textSpan: ConstraintSpan;
|
|
@@ -485,6 +505,7 @@ declare class TypeDBHttpDriver {
|
|
|
485
505
|
private params;
|
|
486
506
|
private token?;
|
|
487
507
|
private currentOrigin;
|
|
508
|
+
private readonly fetch;
|
|
488
509
|
constructor(params: DriverParams);
|
|
489
510
|
getDatabases(): Promise<ApiResponse<DatabasesListResponse>>;
|
|
490
511
|
getDatabase(name: string): Promise<ApiResponse<Database>>;
|
|
@@ -519,6 +540,7 @@ declare class TypeDBHttpDriver {
|
|
|
519
540
|
private apiReq;
|
|
520
541
|
private apiReqOnce;
|
|
521
542
|
private tryApiReq;
|
|
543
|
+
private fetchFrom;
|
|
522
544
|
private followMisdirected;
|
|
523
545
|
private switchToRedirectTarget;
|
|
524
546
|
private tryFallbackOrigins;
|
|
@@ -554,4 +576,4 @@ type GivenRows = {
|
|
|
554
576
|
[varName: string]: GivenRowEntry;
|
|
555
577
|
}[];
|
|
556
578
|
|
|
557
|
-
export { type AnalyzeOptions, type AnalyzeResponse, type AnalyzedConjunction, type AnalyzedFetch, type AnalyzedFunction, type AnalyzedPipeline, type Answer, type AnswerType, type ApiError, type ApiErrorResponse, type ApiOkResponse, type ApiResponse, type Attribute, type AttributeType, type Concept, type ConceptDocument, type ConceptDocumentsQueryResponse, type ConceptRow, type ConceptRowAnswer, type ConceptRowsQueryResponse, type ConceptRowsQueryResponseLegacy, type ConjunctionAnnotations, type ConstraintAny, type ConstraintComparison, type ConstraintDeleteConcepts, type ConstraintExpression, type ConstraintExpressionLegacy, type ConstraintFunction, type ConstraintHas, type ConstraintIid, type ConstraintIs, type ConstraintIsa, type ConstraintIsaExact, type ConstraintKind, type ConstraintLabel, type ConstraintLinks, type ConstraintLinksLegacy, type ConstraintNot, type ConstraintOr, type ConstraintOwns, type ConstraintPlays, type ConstraintRelates, type ConstraintSpan, type ConstraintSub, type ConstraintSubExact, type ConstraintTry, type ConstraintValue, type ConstraintVertexAny, type ConstraintVertexLabel, type ConstraintVertexNamedRole, type ConstraintVertexValue, type ConstraintVertexVariable, type Database, type DatabasesListResponse, type Distribution, type DriverParams, type DriverParamsBasic, type DriverParamsTranslated, type EdgeKind, type Entity, type EntityType, type FetchAnnotationFieldEntry, type FunctionReturnStructure, type FunctionSingleReturnSelector, type Given, type GivenRowEntry, type GivenRows, type InstantiableType, type MisdirectedError, type OkQueryResponse, type PipelineStage, type QueryConjunctionLegacy, type QueryOptions, type QueryResponse, type QueryResponseBase, type QueryStructureLegacy, type QueryType, type Reducer, type Relation, type RelationType, type ReplicationRole, type ReplicationStatus, type RoleType, type Server, type ServersListResponse, type SignInResponse, type ThingKind, type TransactionOpenResponse, type TransactionOptions, type TransactionType, type TranslatedAddress, type Type, TypeDBHttpDriver, type TypeKind, type User, type UsersListResponse, type Value, type ValueKind, type ValueType, type VariableAnnotations, type VariableId, type VariableInfo, type VersionResponse, allOrigins, driverError, getVariableName, hostPortFromOrigin, isApiError, isApiErrorResponse, isBasicParams, isMisdirectedError, isOkResponse, isQueryResponseLegacy, isTranslatedParams, parseJson, remoteOrigin, resolveOrigin, stringifyJson };
|
|
579
|
+
export { type AnalyzeOptions, type AnalyzeResponse, type AnalyzedConjunction, type AnalyzedFetch, type AnalyzedFunction, type AnalyzedPipeline, type Answer, type AnswerType, type ApiError, type ApiErrorResponse, type ApiOkResponse, type ApiResponse, type Attribute, type AttributeType, type Concept, type ConceptDocument, type ConceptDocumentsQueryResponse, type ConceptRow, type ConceptRowAnswer, type ConceptRowsQueryResponse, type ConceptRowsQueryResponseLegacy, type ConjunctionAnnotations, type ConstraintAny, type ConstraintComparison, type ConstraintDeleteConcepts, type ConstraintExpression, type ConstraintExpressionLegacy, type ConstraintFunction, type ConstraintHas, type ConstraintIid, type ConstraintIs, type ConstraintIsSet, type ConstraintIsa, type ConstraintIsaExact, type ConstraintKind, type ConstraintLabel, type ConstraintLinks, type ConstraintLinksLegacy, type ConstraintNot, type ConstraintOr, type ConstraintOwns, type ConstraintPlays, type ConstraintRelates, type ConstraintSpan, type ConstraintSub, type ConstraintSubExact, type ConstraintTry, type ConstraintValue, type ConstraintVertexAny, type ConstraintVertexLabel, type ConstraintVertexNamedRole, type ConstraintVertexValue, type ConstraintVertexVariable, type Database, type DatabasesListResponse, type Distribution, type DriverParams, type DriverParamsBasic, type DriverParamsTranslated, type DriverTlsConfig, type EdgeKind, type Entity, type EntityType, type FetchAnnotationFieldEntry, type FunctionReturnStructure, type FunctionSingleReturnSelector, type Given, type GivenRowEntry, type GivenRows, type InstantiableType, type MisdirectedError, type OkQueryResponse, type PipelineStage, type QueryConjunctionLegacy, type QueryOptions, type QueryResponse, type QueryResponseBase, type QueryStructureLegacy, type QueryType, type Reducer, type Relation, type RelationType, type ReplicationRole, type ReplicationStatus, type RoleType, type Server, type ServersListResponse, type SignInResponse, type ThingKind, type TransactionOpenResponse, type TransactionOptions, type TransactionType, type TranslatedAddress, type Type, TypeDBHttpDriver, type TypeKind, type User, type UsersListResponse, type Value, type ValueKind, type ValueType, type VariableAnnotations, type VariableId, type VariableInfo, type VersionResponse, allOrigins, driverError, getVariableName, hostPortFromOrigin, isApiError, isApiErrorResponse, isBasicParams, isMisdirectedError, isOkResponse, isQueryResponseLegacy, isTranslatedParams, parseJson, remoteOrigin, resolveOrigin, stringifyJson };
|
package/dist/index.mjs
CHANGED
|
@@ -47,6 +47,126 @@ function allOrigins(params) {
|
|
|
47
47
|
else return params.translatedAddresses.map((ta) => ta.external);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/transport.ts
|
|
51
|
+
var CONNECT_TIMEOUT_MILLIS = 1e4;
|
|
52
|
+
var REQUEST_INACTIVITY_TIMEOUT_MILLIS = 3e5;
|
|
53
|
+
var KEEP_ALIVE_SOCKET_TIMEOUT_MILLIS = 5e3;
|
|
54
|
+
var PEM_CERTIFICATE_REGEX = /-----BEGIN (TRUSTED )?CERTIFICATE-----.*?-----END \1CERTIFICATE-----/gs;
|
|
55
|
+
var TlsConfigError = class extends Error {
|
|
56
|
+
};
|
|
57
|
+
function createFetch(tls, origins) {
|
|
58
|
+
const rootCAPath = tls?.rootCAPath;
|
|
59
|
+
if (rootCAPath === void 0) return (url, init) => fetch(url, init);
|
|
60
|
+
const plainOrigin = origins.find((origin) => !isHttps(origin));
|
|
61
|
+
const plainOriginError = plainOrigin === void 0 ? void 0 : plainHttpError(plainOrigin);
|
|
62
|
+
let httpsClient;
|
|
63
|
+
return async (url, init) => {
|
|
64
|
+
if (plainOriginError !== void 0) throw plainOriginError;
|
|
65
|
+
if (!isHttps(url)) {
|
|
66
|
+
const { protocol, host } = new URL(url);
|
|
67
|
+
throw plainHttpError(`${protocol}//${host}`);
|
|
68
|
+
}
|
|
69
|
+
httpsClient ?? (httpsClient = createHttpsClient(rootCAPath).catch((error) => {
|
|
70
|
+
httpsClient = void 0;
|
|
71
|
+
throw error;
|
|
72
|
+
}));
|
|
73
|
+
const { https, agent } = await httpsClient;
|
|
74
|
+
return requestWithAgent(https, agent, url, init);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async function createHttpsClient(rootCAPath) {
|
|
78
|
+
if (!isNodeJs()) {
|
|
79
|
+
throw new TlsConfigError("A TLS root CA can only be set in Node.js: in browsers, add the CA to the trust store.");
|
|
80
|
+
}
|
|
81
|
+
let https;
|
|
82
|
+
let fs;
|
|
83
|
+
let crypto;
|
|
84
|
+
try {
|
|
85
|
+
[https, fs, crypto] = await Promise.all([
|
|
86
|
+
importNodeModule("node:https"),
|
|
87
|
+
importNodeModule("node:fs/promises"),
|
|
88
|
+
importNodeModule("node:crypto")
|
|
89
|
+
]);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
throw new TlsConfigError(`Cannot load the Node.js modules for TLS: ${error.message}`);
|
|
92
|
+
}
|
|
93
|
+
let rootCA;
|
|
94
|
+
try {
|
|
95
|
+
rootCA = await fs.readFile(rootCAPath, "utf8");
|
|
96
|
+
} catch (error) {
|
|
97
|
+
throw new TlsConfigError(`Cannot read the TLS root CA file '${rootCAPath}': ${error.message}`);
|
|
98
|
+
}
|
|
99
|
+
const certificates = rootCA.match(PEM_CERTIFICATE_REGEX) ?? [];
|
|
100
|
+
if (certificates.length === 0) {
|
|
101
|
+
throw new TlsConfigError(`The TLS root CA file '${rootCAPath}' does not contain a PEM certificate.`);
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
certificates.forEach((certificate) => new crypto.X509Certificate(certificate));
|
|
105
|
+
} catch (error) {
|
|
106
|
+
throw new TlsConfigError(
|
|
107
|
+
`The TLS root CA file '${rootCAPath}' contains an invalid certificate: ${error.message}`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
const agent = new https.Agent({ ca: rootCA, keepAlive: true, timeout: KEEP_ALIVE_SOCKET_TIMEOUT_MILLIS });
|
|
111
|
+
return { https, agent };
|
|
112
|
+
}
|
|
113
|
+
function plainHttpError(origin) {
|
|
114
|
+
return new TlsConfigError(`A TLS root CA is set, but ${origin} does not use https.`);
|
|
115
|
+
}
|
|
116
|
+
function isHttps(url) {
|
|
117
|
+
try {
|
|
118
|
+
return new URL(url).protocol === "https:";
|
|
119
|
+
} catch {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function isNodeJs() {
|
|
124
|
+
return typeof process !== "undefined" && typeof process.versions?.node === "string";
|
|
125
|
+
}
|
|
126
|
+
function importNodeModule(specifier) {
|
|
127
|
+
return import(
|
|
128
|
+
/* @vite-ignore */
|
|
129
|
+
/* webpackIgnore: true */
|
|
130
|
+
specifier
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
function requestWithAgent(https, agent, url, init) {
|
|
134
|
+
return new Promise((resolve, reject) => {
|
|
135
|
+
const options = { method: init.method, headers: init.headers, agent };
|
|
136
|
+
const request = https.request(url, options, (response) => {
|
|
137
|
+
const chunks = [];
|
|
138
|
+
response.on("data", (chunk) => chunks.push(chunk));
|
|
139
|
+
response.on("error", reject);
|
|
140
|
+
response.on("end", () => {
|
|
141
|
+
try {
|
|
142
|
+
const status = response.statusCode ?? 0;
|
|
143
|
+
const headers = new Headers();
|
|
144
|
+
for (const [name, value] of Object.entries(response.headers)) {
|
|
145
|
+
if (value !== void 0) headers.set(name, Array.isArray(value) ? value.join(", ") : value);
|
|
146
|
+
}
|
|
147
|
+
const body = status === 204 || status === 304 ? null : Buffer.concat(chunks);
|
|
148
|
+
resolve(new Response(body, { status, statusText: response.statusMessage, headers }));
|
|
149
|
+
} catch (error) {
|
|
150
|
+
reject(error);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
request.on("error", reject);
|
|
155
|
+
request.on("socket", (socket) => {
|
|
156
|
+
if (!socket.connecting) return;
|
|
157
|
+
socket.setTimeout(0);
|
|
158
|
+
const connectTimeout = setTimeout(
|
|
159
|
+
() => request.destroy(new Error("Connection timed out")),
|
|
160
|
+
CONNECT_TIMEOUT_MILLIS
|
|
161
|
+
);
|
|
162
|
+
socket.once("secureConnect", () => clearTimeout(connectTimeout));
|
|
163
|
+
socket.once("close", () => clearTimeout(connectTimeout));
|
|
164
|
+
});
|
|
165
|
+
request.setTimeout(REQUEST_INACTIVITY_TIMEOUT_MILLIS, () => request.destroy(new Error("Request timed out")));
|
|
166
|
+
request.end(init.body);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
50
170
|
// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/response.ts
|
|
51
171
|
function isApiError(err) {
|
|
52
172
|
return err != null && typeof err.code === "string" && typeof err.message === "string";
|
|
@@ -299,19 +419,32 @@ function getVariableName(structure, variable) {
|
|
|
299
419
|
// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/index.ts
|
|
300
420
|
var HTTP_UNAUTHORIZED = 401;
|
|
301
421
|
var HTTP_MISDIRECTED = 421;
|
|
302
|
-
var TRANSIENT_SIGNIN_ERROR_CODES = /* @__PURE__ */ new Set(["
|
|
422
|
+
var TRANSIENT_SIGNIN_ERROR_CODES = /* @__PURE__ */ new Set(["SRV14", "CSV8", "CSV9"]);
|
|
303
423
|
var PRIMARY_FAILOVER_RETRIES = 3;
|
|
304
424
|
var PRIMARY_SELECTION_WAIT_MS = 2e3;
|
|
305
425
|
function isApiErrResp(value) {
|
|
306
|
-
return
|
|
426
|
+
return "err" in value;
|
|
427
|
+
}
|
|
428
|
+
function isOriginFailure(value) {
|
|
429
|
+
return "failure" in value;
|
|
430
|
+
}
|
|
431
|
+
function tokenErrToResult(tokenResp, origin) {
|
|
432
|
+
const { code, message } = tokenResp.err;
|
|
433
|
+
if (TRANSIENT_SIGNIN_ERROR_CODES.has(code))
|
|
434
|
+
return { failure: `Server at ${origin} failed signin with [${code}] ${message}` };
|
|
435
|
+
else
|
|
436
|
+
return tokenResp;
|
|
307
437
|
}
|
|
308
|
-
function
|
|
309
|
-
|
|
438
|
+
function errorMessage(error) {
|
|
439
|
+
const reason = error?.cause ?? error;
|
|
440
|
+
const { message, code } = reason ?? {};
|
|
441
|
+
return (message || code || String(reason)).trim();
|
|
310
442
|
}
|
|
311
443
|
var TypeDBHttpDriver = class {
|
|
312
444
|
constructor(params) {
|
|
313
445
|
this.params = params;
|
|
314
446
|
this.currentOrigin = remoteOrigin(params);
|
|
447
|
+
this.fetch = createFetch(params.tls, allOrigins(params));
|
|
315
448
|
}
|
|
316
449
|
getDatabases() {
|
|
317
450
|
return this.apiGet(`/v1/databases`);
|
|
@@ -428,53 +561,52 @@ var TypeDBHttpDriver = class {
|
|
|
428
561
|
const initial = await this.tryApiReq(method, path, body, options);
|
|
429
562
|
if (isApiErrResp(initial)) return initial;
|
|
430
563
|
let result = initial;
|
|
431
|
-
if (result
|
|
564
|
+
if (!isOriginFailure(result) && result.status === HTTP_MISDIRECTED) {
|
|
432
565
|
const redirected = await this.followMisdirected(result, method, path, body, options);
|
|
433
566
|
if (isApiErrResp(redirected)) return redirected;
|
|
434
567
|
result = redirected;
|
|
435
568
|
}
|
|
436
|
-
if (result
|
|
437
|
-
const
|
|
438
|
-
triedOrigins.add(startOrigin);
|
|
439
|
-
const fallback = await this.tryFallbackOrigins(method, path, body, options, triedOrigins);
|
|
569
|
+
if (isOriginFailure(result) || !result.ok) {
|
|
570
|
+
const fallback = await this.tryFallbackOrigins(method, path, body, options, triedOrigins, result);
|
|
440
571
|
if (isApiErrResp(fallback)) return fallback;
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
}
|
|
572
|
+
result = fallback;
|
|
573
|
+
}
|
|
574
|
+
if (isOriginFailure(result)) {
|
|
575
|
+
return driverError("HDR1", `Cannot connect to any server (last error: ${result.failure})`);
|
|
446
576
|
}
|
|
447
|
-
return result
|
|
577
|
+
return result;
|
|
448
578
|
}
|
|
449
579
|
async tryApiReq(method, path, body, options) {
|
|
450
|
-
const
|
|
580
|
+
const origin = this.currentOrigin;
|
|
451
581
|
let tokenResp = await this.getToken();
|
|
452
|
-
if (
|
|
582
|
+
if (isOriginFailure(tokenResp)) return tokenResp;
|
|
583
|
+
if (isApiErrResp(tokenResp)) return tokenErrToResult(tokenResp, origin);
|
|
453
584
|
const bodyString = body !== void 0 ? stringifyJson(body) : void 0;
|
|
454
585
|
let headers = this.authHeaders(tokenResp.ok.token, options);
|
|
455
|
-
let resp;
|
|
456
|
-
|
|
457
|
-
resp = await fetch(url, { method, body: bodyString, headers });
|
|
458
|
-
} catch {
|
|
459
|
-
return null;
|
|
460
|
-
}
|
|
461
|
-
if (resp.status === HTTP_UNAUTHORIZED) {
|
|
586
|
+
let resp = await this.fetchFrom(origin, path, { method, body: bodyString, headers });
|
|
587
|
+
if (!isApiErrResp(resp) && !isOriginFailure(resp) && resp.status === HTTP_UNAUTHORIZED) {
|
|
462
588
|
tokenResp = await this.refreshToken();
|
|
463
|
-
if (
|
|
589
|
+
if (isOriginFailure(tokenResp)) return tokenResp;
|
|
590
|
+
if (isApiErrResp(tokenResp)) return tokenErrToResult(tokenResp, origin);
|
|
464
591
|
headers = this.authHeaders(tokenResp.ok.token, options);
|
|
465
|
-
|
|
466
|
-
resp = await fetch(url, { method, body: bodyString, headers });
|
|
467
|
-
} catch {
|
|
468
|
-
return null;
|
|
469
|
-
}
|
|
592
|
+
resp = await this.fetchFrom(origin, path, { method, body: bodyString, headers });
|
|
470
593
|
}
|
|
471
594
|
return resp;
|
|
472
595
|
}
|
|
596
|
+
async fetchFrom(origin, path, init) {
|
|
597
|
+
try {
|
|
598
|
+
return await this.fetch(`${origin}${path}`, init);
|
|
599
|
+
} catch (error) {
|
|
600
|
+
if (error instanceof TlsConfigError) return driverError("HDR3", error.message);
|
|
601
|
+
return { failure: `Cannot connect to server at ${origin}: ${errorMessage(error)}` };
|
|
602
|
+
}
|
|
603
|
+
}
|
|
473
604
|
async followMisdirected(resp, method, path, body, options) {
|
|
605
|
+
const origin = this.currentOrigin;
|
|
474
606
|
if (await this.switchToRedirectTarget(resp)) {
|
|
475
607
|
return await this.tryApiReq(method, path, body, options);
|
|
476
608
|
}
|
|
477
|
-
return
|
|
609
|
+
return { failure: `Server at ${origin} returned 421 Misdirected Request without another primary address` };
|
|
478
610
|
}
|
|
479
611
|
async switchToRedirectTarget(resp) {
|
|
480
612
|
let json;
|
|
@@ -489,26 +621,39 @@ var TypeDBHttpDriver = class {
|
|
|
489
621
|
this.switchOrigin(newOrigin);
|
|
490
622
|
return true;
|
|
491
623
|
}
|
|
492
|
-
async tryFallbackOrigins(method, path, body, options, triedOrigins) {
|
|
624
|
+
async tryFallbackOrigins(method, path, body, options, triedOrigins, startResult) {
|
|
625
|
+
const startOrigin = this.currentOrigin;
|
|
626
|
+
triedOrigins.add(startOrigin);
|
|
493
627
|
const origins = allOrigins(this.params);
|
|
494
628
|
let lastError = null;
|
|
629
|
+
let lastFailure = null;
|
|
495
630
|
for (const origin of origins) {
|
|
496
631
|
if (triedOrigins.has(origin)) continue;
|
|
497
632
|
this.switchOrigin(origin);
|
|
498
633
|
const initial = await this.tryApiReq(method, path, body, options);
|
|
499
|
-
if (initial
|
|
634
|
+
if (isOriginFailure(initial)) {
|
|
635
|
+
lastFailure = initial;
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
500
638
|
if (isApiErrResp(initial)) return initial;
|
|
501
639
|
let result = initial;
|
|
502
640
|
if (result.status === HTTP_MISDIRECTED) {
|
|
503
641
|
const redirected = await this.followMisdirected(result, method, path, body, options);
|
|
504
|
-
if (redirected
|
|
642
|
+
if (isOriginFailure(redirected)) {
|
|
643
|
+
lastFailure = redirected;
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
505
646
|
if (isApiErrResp(redirected)) return redirected;
|
|
506
647
|
result = redirected;
|
|
507
648
|
}
|
|
508
649
|
if (result.ok) return result;
|
|
509
650
|
lastError = result;
|
|
510
651
|
}
|
|
511
|
-
|
|
652
|
+
if (!isOriginFailure(startResult)) {
|
|
653
|
+
this.switchOrigin(startOrigin);
|
|
654
|
+
return startResult;
|
|
655
|
+
}
|
|
656
|
+
return lastError ?? lastFailure ?? startResult;
|
|
512
657
|
}
|
|
513
658
|
switchOrigin(origin) {
|
|
514
659
|
this.currentOrigin = origin;
|
|
@@ -527,21 +672,16 @@ var TypeDBHttpDriver = class {
|
|
|
527
672
|
return this.signinOnce();
|
|
528
673
|
}
|
|
529
674
|
async signinOnce() {
|
|
530
|
-
const url = `${this.currentOrigin}/v1/signin`;
|
|
531
675
|
const body = { username: this.params.username, password: this.params.password };
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
resp = await fetch(url, { method: "POST", body: stringifyJson(body), headers: { "Content-Type": "application/json" } });
|
|
535
|
-
} catch {
|
|
536
|
-
return driverError("HDR2", `Cannot connect to server at ${this.currentOrigin}`);
|
|
537
|
-
}
|
|
676
|
+
const resp = await this.fetchFrom(this.currentOrigin, "/v1/signin", { method: "POST", body: stringifyJson(body), headers: { "Content-Type": "application/json" } });
|
|
677
|
+
if (isApiErrResp(resp) || isOriginFailure(resp)) return resp;
|
|
538
678
|
const json = await this.jsonOrNull(resp);
|
|
539
679
|
if (resp.ok && typeof json?.token === "string") {
|
|
540
680
|
this.token = json.token;
|
|
541
681
|
return { ok: json };
|
|
542
682
|
}
|
|
543
683
|
if (isApiError(json)) return { err: json, status: resp.status };
|
|
544
|
-
return
|
|
684
|
+
return { failure: `Unexpected signin response from ${this.currentOrigin} (HTTP ${resp.status})` };
|
|
545
685
|
}
|
|
546
686
|
async jsonOrNull(resp) {
|
|
547
687
|
try {
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name": "@typedb/driver-http", "version": "3.
|
|
1
|
+
{"name": "@typedb/driver-http", "version": "3.15.0-rc3", "description": "TypeDB HTTP Driver", "author": "TypeDB Community <community@typedb.com>", "license": "Apache-2.0", "homepage": "https://typedb.com", "repository": {"type": "git", "url": "https://github.com/typedb/typedb-driver"}, "bugs": {"url": "https://github.com/typedb/typedb-driver/issues"}, "keywords": ["database", "typedb"], "main": "dist/index.cjs", "module": "dist/index.mjs", "types": "dist/index.d.ts", "type": "module", "exports": {".": {"types": "./dist/index.d.ts", "import": "./dist/index.mjs", "require": "./dist/index.cjs"}}, "scripts": {"build:dev": "tsc", "build": "tsup", "test": "cucumber-js", "docs": "typedoc"}, "packageManager": "pnpm@8.15.9", "packageConfig": {"access": "public"}, "devDependencies": {"@cucumber/cucumber": "9.0.0", "@types/node": "24.0.12", "tsup": "8.5.0", "typedoc": "^0.28.7", "typescript": "5.8.3"}}
|