@typedb/driver-http 3.10.0 → 3.11.1
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/dist/index.cjs +159 -16
- package/dist/index.d.ts +36 -1
- package/dist/index.mjs +158 -15
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); 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 _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
|
}
|
|
@@ -9,11 +9,52 @@ function remoteOrigin(params) {
|
|
|
9
9
|
if (isBasicParams(params)) return `${params.addresses[0]}`;
|
|
10
10
|
else return `${params.translatedAddresses[0].external}`;
|
|
11
11
|
}
|
|
12
|
+
function hostPortFromOrigin(origin) {
|
|
13
|
+
try {
|
|
14
|
+
const url = new URL(origin);
|
|
15
|
+
return url.host;
|
|
16
|
+
} catch (e) {
|
|
17
|
+
return origin;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function resolveOrigin(params, primaryAddress) {
|
|
21
|
+
if (isBasicParams(params)) {
|
|
22
|
+
for (const addr of params.addresses) {
|
|
23
|
+
if (hostPortFromOrigin(addr) === primaryAddress) return addr;
|
|
24
|
+
}
|
|
25
|
+
return deriveOriginWithScheme(params.addresses[0], primaryAddress);
|
|
26
|
+
} else {
|
|
27
|
+
for (const ta of params.translatedAddresses) {
|
|
28
|
+
if (hostPortFromOrigin(ta.internal) === primaryAddress || hostPortFromOrigin(ta.external) === primaryAddress) {
|
|
29
|
+
return ta.external;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return deriveOriginWithScheme(params.translatedAddresses[0].external, primaryAddress);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function deriveOriginWithScheme(referenceUrl, hostPort) {
|
|
36
|
+
try {
|
|
37
|
+
const url = new URL(referenceUrl);
|
|
38
|
+
return `${url.protocol}//${hostPort}`;
|
|
39
|
+
} catch (e2) {
|
|
40
|
+
return `https://${hostPort}`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function allOrigins(params) {
|
|
44
|
+
if (isBasicParams(params)) return params.addresses;
|
|
45
|
+
else return params.translatedAddresses.map((ta) => ta.external);
|
|
46
|
+
}
|
|
12
47
|
|
|
13
48
|
// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/response.ts
|
|
14
49
|
function isApiError(err) {
|
|
15
50
|
return err != null && typeof err.code === "string" && typeof err.message === "string";
|
|
16
51
|
}
|
|
52
|
+
function isMisdirectedError(err) {
|
|
53
|
+
return err != null && typeof err.code === "string" && typeof err.message === "string" && typeof err.primaryAddress === "string";
|
|
54
|
+
}
|
|
55
|
+
function driverError(code, message) {
|
|
56
|
+
return { err: { code, message }, status: 503 };
|
|
57
|
+
}
|
|
17
58
|
function isOkResponse(res) {
|
|
18
59
|
return typeof res === "object" && "ok" in res;
|
|
19
60
|
}
|
|
@@ -31,9 +72,18 @@ function getVariableName(structure, variable) {
|
|
|
31
72
|
|
|
32
73
|
// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/index.ts
|
|
33
74
|
var HTTP_UNAUTHORIZED = 401;
|
|
75
|
+
var HTTP_MISDIRECTED = 421;
|
|
76
|
+
var TRANSIENT_SIGNIN_ERROR_CODES = /* @__PURE__ */ new Set(["HDR2", "SRV14"]);
|
|
77
|
+
function isApiErrResp(value) {
|
|
78
|
+
return value !== null && "err" in value;
|
|
79
|
+
}
|
|
80
|
+
function tokenErrToResult(tokenResp) {
|
|
81
|
+
return TRANSIENT_SIGNIN_ERROR_CODES.has(tokenResp.err.code) ? null : tokenResp;
|
|
82
|
+
}
|
|
34
83
|
var TypeDBHttpDriver = class {
|
|
35
84
|
constructor(params) {
|
|
36
85
|
this.params = params;
|
|
86
|
+
this.currentOrigin = remoteOrigin(params);
|
|
37
87
|
}
|
|
38
88
|
getDatabases() {
|
|
39
89
|
return this.apiGet(`/v1/databases`);
|
|
@@ -98,6 +148,9 @@ var TypeDBHttpDriver = class {
|
|
|
98
148
|
version() {
|
|
99
149
|
return this.apiGet(`/v1/version`);
|
|
100
150
|
}
|
|
151
|
+
getServers() {
|
|
152
|
+
return this.apiGet(`/v1/servers`);
|
|
153
|
+
}
|
|
101
154
|
async apiGetString(path, options) {
|
|
102
155
|
return this.stringApiReq("GET", path, options);
|
|
103
156
|
}
|
|
@@ -135,21 +188,98 @@ var TypeDBHttpDriver = class {
|
|
|
135
188
|
}
|
|
136
189
|
}
|
|
137
190
|
async apiReq(method, path, body, options) {
|
|
138
|
-
const
|
|
191
|
+
const initial = await this.tryApiReq(method, path, body, options);
|
|
192
|
+
if (isApiErrResp(initial)) return initial;
|
|
193
|
+
let result = initial;
|
|
194
|
+
if (result !== null && result.status === HTTP_MISDIRECTED) {
|
|
195
|
+
const redirected = await this.followMisdirected(result, method, path, body, options);
|
|
196
|
+
if (isApiErrResp(redirected)) return redirected;
|
|
197
|
+
result = redirected;
|
|
198
|
+
}
|
|
199
|
+
if (result === null || !result.ok) {
|
|
200
|
+
const startOrigin = this.currentOrigin;
|
|
201
|
+
const fallback = await this.tryFallbackOrigins(method, path, body, options);
|
|
202
|
+
if (isApiErrResp(fallback)) return fallback;
|
|
203
|
+
if (fallback !== null && (result === null || fallback.ok)) {
|
|
204
|
+
result = fallback;
|
|
205
|
+
} else if (result !== null) {
|
|
206
|
+
this.switchOrigin(startOrigin);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return _nullishCoalesce(result, () => ( driverError("HDR1", "Cannot connect to any server")));
|
|
210
|
+
}
|
|
211
|
+
async tryApiReq(method, path, body, options) {
|
|
212
|
+
const url = `${this.currentOrigin}${path}`;
|
|
139
213
|
let tokenResp = await this.getToken();
|
|
140
|
-
if ("err" in tokenResp) return tokenResp;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
let
|
|
144
|
-
|
|
214
|
+
if ("err" in tokenResp) return tokenErrToResult(tokenResp);
|
|
215
|
+
const bodyString = body !== void 0 ? JSON.stringify(body) : void 0;
|
|
216
|
+
let headers = this.authHeaders(tokenResp.ok.token, options);
|
|
217
|
+
let resp;
|
|
218
|
+
try {
|
|
219
|
+
resp = await fetch(url, { method, body: bodyString, headers });
|
|
220
|
+
} catch (e3) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
145
223
|
if (resp.status === HTTP_UNAUTHORIZED) {
|
|
146
224
|
tokenResp = await this.refreshToken();
|
|
147
|
-
if ("err" in tokenResp) return tokenResp;
|
|
148
|
-
headers =
|
|
149
|
-
|
|
225
|
+
if ("err" in tokenResp) return tokenErrToResult(tokenResp);
|
|
226
|
+
headers = this.authHeaders(tokenResp.ok.token, options);
|
|
227
|
+
try {
|
|
228
|
+
resp = await fetch(url, { method, body: bodyString, headers });
|
|
229
|
+
} catch (e4) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
150
232
|
}
|
|
151
233
|
return resp;
|
|
152
234
|
}
|
|
235
|
+
async followMisdirected(resp, method, path, body, options) {
|
|
236
|
+
if (await this.switchToRedirectTarget(resp)) {
|
|
237
|
+
return await this.tryApiReq(method, path, body, options);
|
|
238
|
+
}
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
async switchToRedirectTarget(resp) {
|
|
242
|
+
let json;
|
|
243
|
+
try {
|
|
244
|
+
json = await resp.json();
|
|
245
|
+
} catch (e5) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
if (!isMisdirectedError(json)) return false;
|
|
249
|
+
const newOrigin = resolveOrigin(this.params, json.primaryAddress);
|
|
250
|
+
if (newOrigin === this.currentOrigin) return false;
|
|
251
|
+
this.switchOrigin(newOrigin);
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
async tryFallbackOrigins(method, path, body, options) {
|
|
255
|
+
const origins = allOrigins(this.params);
|
|
256
|
+
const failedOrigin = this.currentOrigin;
|
|
257
|
+
let lastError = null;
|
|
258
|
+
for (const origin of origins) {
|
|
259
|
+
if (origin === failedOrigin) continue;
|
|
260
|
+
this.switchOrigin(origin);
|
|
261
|
+
const initial = await this.tryApiReq(method, path, body, options);
|
|
262
|
+
if (initial === null) continue;
|
|
263
|
+
if (isApiErrResp(initial)) return initial;
|
|
264
|
+
let result = initial;
|
|
265
|
+
if (result.status === HTTP_MISDIRECTED) {
|
|
266
|
+
const redirected = await this.followMisdirected(result, method, path, body, options);
|
|
267
|
+
if (redirected === null) continue;
|
|
268
|
+
if (isApiErrResp(redirected)) return redirected;
|
|
269
|
+
result = redirected;
|
|
270
|
+
}
|
|
271
|
+
if (result.ok) return result;
|
|
272
|
+
lastError = result;
|
|
273
|
+
}
|
|
274
|
+
return lastError;
|
|
275
|
+
}
|
|
276
|
+
switchOrigin(origin) {
|
|
277
|
+
this.currentOrigin = origin;
|
|
278
|
+
this.token = void 0;
|
|
279
|
+
}
|
|
280
|
+
authHeaders(token, options) {
|
|
281
|
+
return { "Authorization": `Bearer ${token}`, "Content-Type": "application/json", ..._optionalChain([options, 'optionalAccess', _4 => _4.headers]) };
|
|
282
|
+
}
|
|
153
283
|
getToken() {
|
|
154
284
|
if (this.token) {
|
|
155
285
|
const resp = { ok: { token: this.token } };
|
|
@@ -157,16 +287,24 @@ var TypeDBHttpDriver = class {
|
|
|
157
287
|
} else return this.refreshToken();
|
|
158
288
|
}
|
|
159
289
|
async refreshToken() {
|
|
160
|
-
|
|
290
|
+
return this.signinOnce();
|
|
291
|
+
}
|
|
292
|
+
async signinOnce() {
|
|
293
|
+
const url = `${this.currentOrigin}/v1/signin`;
|
|
161
294
|
const body = { username: this.params.username, password: this.params.password };
|
|
162
|
-
|
|
295
|
+
let resp;
|
|
296
|
+
try {
|
|
297
|
+
resp = await fetch(url, { method: "POST", body: JSON.stringify(body), headers: { "Content-Type": "application/json" } });
|
|
298
|
+
} catch (e6) {
|
|
299
|
+
return driverError("HDR2", `Cannot connect to server at ${this.currentOrigin}`);
|
|
300
|
+
}
|
|
163
301
|
const json = await this.jsonOrNull(resp);
|
|
164
302
|
if (resp.ok) {
|
|
165
303
|
this.token = json.token;
|
|
166
304
|
return { ok: json };
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
305
|
+
}
|
|
306
|
+
if (isApiError(json)) return { err: json, status: resp.status };
|
|
307
|
+
throw resp;
|
|
170
308
|
}
|
|
171
309
|
async jsonOrNull(resp) {
|
|
172
310
|
const contentLengthRaw = resp.headers.get("Content-Length");
|
|
@@ -193,5 +331,10 @@ var TypeDBHttpDriver = class {
|
|
|
193
331
|
|
|
194
332
|
|
|
195
333
|
|
|
196
|
-
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
exports.TypeDBHttpDriver = TypeDBHttpDriver; exports.allOrigins = allOrigins; exports.driverError = driverError; exports.getVariableName = getVariableName; exports.hostPortFromOrigin = hostPortFromOrigin; exports.isApiError = isApiError; exports.isApiErrorResponse = isApiErrorResponse; exports.isBasicParams = isBasicParams; exports.isMisdirectedError = isMisdirectedError; exports.isOkResponse = isOkResponse; exports.isQueryResponseLegacy = isQueryResponseLegacy; exports.isTranslatedParams = isTranslatedParams; exports.remoteOrigin = remoteOrigin; exports.resolveOrigin = resolveOrigin;
|
|
197
340
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,12 @@ type DriverParams = DriverParamsBasic | DriverParamsTranslated;
|
|
|
16
16
|
declare function isBasicParams(params: DriverParams): params is DriverParamsBasic;
|
|
17
17
|
declare function isTranslatedParams(params: DriverParams): params is DriverParamsTranslated;
|
|
18
18
|
declare function remoteOrigin(params: DriverParams): string;
|
|
19
|
+
/** Extract host:port from a URL string. "https://127.0.0.1:18000" → "127.0.0.1:18000" */
|
|
20
|
+
declare function hostPortFromOrigin(origin: string): string;
|
|
21
|
+
/** Resolve a bare primaryAddress (host:port) to a full URL using configured params. */
|
|
22
|
+
declare function resolveOrigin(params: DriverParams, primaryAddress: string): string;
|
|
23
|
+
/** Return all configured origins for connection error fallback. */
|
|
24
|
+
declare function allOrigins(params: DriverParams): string[];
|
|
19
25
|
|
|
20
26
|
type TypeKind = "entityType" | "relationType" | "attributeType" | "roleType";
|
|
21
27
|
type ThingKind = "entity" | "relation" | "attribute";
|
|
@@ -374,6 +380,19 @@ interface DatabasesListResponse {
|
|
|
374
380
|
interface UsersListResponse {
|
|
375
381
|
users: User[];
|
|
376
382
|
}
|
|
383
|
+
type ReplicationRole = "primary" | "candidate" | "secondary";
|
|
384
|
+
interface ReplicationStatus {
|
|
385
|
+
id: number;
|
|
386
|
+
role: ReplicationRole | null;
|
|
387
|
+
term: number | null;
|
|
388
|
+
}
|
|
389
|
+
interface Server {
|
|
390
|
+
address: string | null;
|
|
391
|
+
replicationStatus: ReplicationStatus | null;
|
|
392
|
+
}
|
|
393
|
+
interface ServersListResponse {
|
|
394
|
+
servers: Server[];
|
|
395
|
+
}
|
|
377
396
|
interface TransactionOpenResponse {
|
|
378
397
|
transactionId: string;
|
|
379
398
|
}
|
|
@@ -424,6 +443,13 @@ interface ApiErrorResponse {
|
|
|
424
443
|
status: number;
|
|
425
444
|
}
|
|
426
445
|
declare function isApiError(err: any): err is ApiError;
|
|
446
|
+
interface MisdirectedError {
|
|
447
|
+
code: string;
|
|
448
|
+
message: string;
|
|
449
|
+
primaryAddress: string;
|
|
450
|
+
}
|
|
451
|
+
declare function isMisdirectedError(err: any): err is MisdirectedError;
|
|
452
|
+
declare function driverError(code: string, message: string): ApiErrorResponse;
|
|
427
453
|
type ApiResponse<OK_RES = {} | null> = ApiOkResponse<OK_RES> | ApiErrorResponse;
|
|
428
454
|
declare function isOkResponse<OK_RES>(res: ApiResponse<OK_RES>): res is ApiOkResponse<OK_RES>;
|
|
429
455
|
declare function isApiErrorResponse(res: ApiResponse): res is ApiErrorResponse;
|
|
@@ -432,6 +458,7 @@ declare function isQueryResponseLegacy(res: ConceptRowsQueryResponse | ConceptRo
|
|
|
432
458
|
declare class TypeDBHttpDriver {
|
|
433
459
|
private params;
|
|
434
460
|
private token?;
|
|
461
|
+
private currentOrigin;
|
|
435
462
|
constructor(params: DriverParams);
|
|
436
463
|
getDatabases(): Promise<ApiResponse<DatabasesListResponse>>;
|
|
437
464
|
getDatabase(name: string): Promise<ApiResponse<Database>>;
|
|
@@ -454,6 +481,7 @@ declare class TypeDBHttpDriver {
|
|
|
454
481
|
oneShotQuery(query: string, commit: boolean, databaseName: string, transactionType: TransactionType, transactionOptions?: TransactionOptions, queryOptions?: QueryOptions): Promise<ApiResponse<QueryResponse>>;
|
|
455
482
|
health(): Promise<ApiResponse>;
|
|
456
483
|
version(): Promise<ApiResponse<VersionResponse>>;
|
|
484
|
+
getServers(): Promise<ApiResponse<ServersListResponse>>;
|
|
457
485
|
private apiGetString;
|
|
458
486
|
private apiGet;
|
|
459
487
|
private apiDelete;
|
|
@@ -463,8 +491,15 @@ declare class TypeDBHttpDriver {
|
|
|
463
491
|
private jsonApiReq;
|
|
464
492
|
private stringApiReq;
|
|
465
493
|
private apiReq;
|
|
494
|
+
private tryApiReq;
|
|
495
|
+
private followMisdirected;
|
|
496
|
+
private switchToRedirectTarget;
|
|
497
|
+
private tryFallbackOrigins;
|
|
498
|
+
private switchOrigin;
|
|
499
|
+
private authHeaders;
|
|
466
500
|
private getToken;
|
|
467
501
|
private refreshToken;
|
|
502
|
+
private signinOnce;
|
|
468
503
|
private jsonOrNull;
|
|
469
504
|
private stringOrNull;
|
|
470
505
|
}
|
|
@@ -488,4 +523,4 @@ interface User {
|
|
|
488
523
|
username: string;
|
|
489
524
|
}
|
|
490
525
|
|
|
491
|
-
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 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 InstantiableType, type OkQueryResponse, type PipelineStage, type QueryConjunctionLegacy, type QueryOptions, type QueryResponse, type QueryResponseBase, type QueryStructureLegacy, type QueryType, type Reducer, type Relation, type RelationType, type RoleType, 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, getVariableName, isApiError, isApiErrorResponse, isBasicParams, isOkResponse, isQueryResponseLegacy, isTranslatedParams, remoteOrigin };
|
|
526
|
+
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 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 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, remoteOrigin, resolveOrigin };
|
package/dist/index.mjs
CHANGED
|
@@ -9,11 +9,52 @@ function remoteOrigin(params) {
|
|
|
9
9
|
if (isBasicParams(params)) return `${params.addresses[0]}`;
|
|
10
10
|
else return `${params.translatedAddresses[0].external}`;
|
|
11
11
|
}
|
|
12
|
+
function hostPortFromOrigin(origin) {
|
|
13
|
+
try {
|
|
14
|
+
const url = new URL(origin);
|
|
15
|
+
return url.host;
|
|
16
|
+
} catch {
|
|
17
|
+
return origin;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function resolveOrigin(params, primaryAddress) {
|
|
21
|
+
if (isBasicParams(params)) {
|
|
22
|
+
for (const addr of params.addresses) {
|
|
23
|
+
if (hostPortFromOrigin(addr) === primaryAddress) return addr;
|
|
24
|
+
}
|
|
25
|
+
return deriveOriginWithScheme(params.addresses[0], primaryAddress);
|
|
26
|
+
} else {
|
|
27
|
+
for (const ta of params.translatedAddresses) {
|
|
28
|
+
if (hostPortFromOrigin(ta.internal) === primaryAddress || hostPortFromOrigin(ta.external) === primaryAddress) {
|
|
29
|
+
return ta.external;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return deriveOriginWithScheme(params.translatedAddresses[0].external, primaryAddress);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function deriveOriginWithScheme(referenceUrl, hostPort) {
|
|
36
|
+
try {
|
|
37
|
+
const url = new URL(referenceUrl);
|
|
38
|
+
return `${url.protocol}//${hostPort}`;
|
|
39
|
+
} catch {
|
|
40
|
+
return `https://${hostPort}`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function allOrigins(params) {
|
|
44
|
+
if (isBasicParams(params)) return params.addresses;
|
|
45
|
+
else return params.translatedAddresses.map((ta) => ta.external);
|
|
46
|
+
}
|
|
12
47
|
|
|
13
48
|
// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/response.ts
|
|
14
49
|
function isApiError(err) {
|
|
15
50
|
return err != null && typeof err.code === "string" && typeof err.message === "string";
|
|
16
51
|
}
|
|
52
|
+
function isMisdirectedError(err) {
|
|
53
|
+
return err != null && typeof err.code === "string" && typeof err.message === "string" && typeof err.primaryAddress === "string";
|
|
54
|
+
}
|
|
55
|
+
function driverError(code, message) {
|
|
56
|
+
return { err: { code, message }, status: 503 };
|
|
57
|
+
}
|
|
17
58
|
function isOkResponse(res) {
|
|
18
59
|
return typeof res === "object" && "ok" in res;
|
|
19
60
|
}
|
|
@@ -31,9 +72,18 @@ function getVariableName(structure, variable) {
|
|
|
31
72
|
|
|
32
73
|
// ../../../../../../../../../execroot/_main/bazel-out/k8-opt/bin/http-ts/src/index.ts
|
|
33
74
|
var HTTP_UNAUTHORIZED = 401;
|
|
75
|
+
var HTTP_MISDIRECTED = 421;
|
|
76
|
+
var TRANSIENT_SIGNIN_ERROR_CODES = /* @__PURE__ */ new Set(["HDR2", "SRV14"]);
|
|
77
|
+
function isApiErrResp(value) {
|
|
78
|
+
return value !== null && "err" in value;
|
|
79
|
+
}
|
|
80
|
+
function tokenErrToResult(tokenResp) {
|
|
81
|
+
return TRANSIENT_SIGNIN_ERROR_CODES.has(tokenResp.err.code) ? null : tokenResp;
|
|
82
|
+
}
|
|
34
83
|
var TypeDBHttpDriver = class {
|
|
35
84
|
constructor(params) {
|
|
36
85
|
this.params = params;
|
|
86
|
+
this.currentOrigin = remoteOrigin(params);
|
|
37
87
|
}
|
|
38
88
|
getDatabases() {
|
|
39
89
|
return this.apiGet(`/v1/databases`);
|
|
@@ -98,6 +148,9 @@ var TypeDBHttpDriver = class {
|
|
|
98
148
|
version() {
|
|
99
149
|
return this.apiGet(`/v1/version`);
|
|
100
150
|
}
|
|
151
|
+
getServers() {
|
|
152
|
+
return this.apiGet(`/v1/servers`);
|
|
153
|
+
}
|
|
101
154
|
async apiGetString(path, options) {
|
|
102
155
|
return this.stringApiReq("GET", path, options);
|
|
103
156
|
}
|
|
@@ -135,21 +188,98 @@ var TypeDBHttpDriver = class {
|
|
|
135
188
|
}
|
|
136
189
|
}
|
|
137
190
|
async apiReq(method, path, body, options) {
|
|
138
|
-
const
|
|
191
|
+
const initial = await this.tryApiReq(method, path, body, options);
|
|
192
|
+
if (isApiErrResp(initial)) return initial;
|
|
193
|
+
let result = initial;
|
|
194
|
+
if (result !== null && result.status === HTTP_MISDIRECTED) {
|
|
195
|
+
const redirected = await this.followMisdirected(result, method, path, body, options);
|
|
196
|
+
if (isApiErrResp(redirected)) return redirected;
|
|
197
|
+
result = redirected;
|
|
198
|
+
}
|
|
199
|
+
if (result === null || !result.ok) {
|
|
200
|
+
const startOrigin = this.currentOrigin;
|
|
201
|
+
const fallback = await this.tryFallbackOrigins(method, path, body, options);
|
|
202
|
+
if (isApiErrResp(fallback)) return fallback;
|
|
203
|
+
if (fallback !== null && (result === null || fallback.ok)) {
|
|
204
|
+
result = fallback;
|
|
205
|
+
} else if (result !== null) {
|
|
206
|
+
this.switchOrigin(startOrigin);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return result ?? driverError("HDR1", "Cannot connect to any server");
|
|
210
|
+
}
|
|
211
|
+
async tryApiReq(method, path, body, options) {
|
|
212
|
+
const url = `${this.currentOrigin}${path}`;
|
|
139
213
|
let tokenResp = await this.getToken();
|
|
140
|
-
if ("err" in tokenResp) return tokenResp;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
let
|
|
144
|
-
|
|
214
|
+
if ("err" in tokenResp) return tokenErrToResult(tokenResp);
|
|
215
|
+
const bodyString = body !== void 0 ? JSON.stringify(body) : void 0;
|
|
216
|
+
let headers = this.authHeaders(tokenResp.ok.token, options);
|
|
217
|
+
let resp;
|
|
218
|
+
try {
|
|
219
|
+
resp = await fetch(url, { method, body: bodyString, headers });
|
|
220
|
+
} catch {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
145
223
|
if (resp.status === HTTP_UNAUTHORIZED) {
|
|
146
224
|
tokenResp = await this.refreshToken();
|
|
147
|
-
if ("err" in tokenResp) return tokenResp;
|
|
148
|
-
headers =
|
|
149
|
-
|
|
225
|
+
if ("err" in tokenResp) return tokenErrToResult(tokenResp);
|
|
226
|
+
headers = this.authHeaders(tokenResp.ok.token, options);
|
|
227
|
+
try {
|
|
228
|
+
resp = await fetch(url, { method, body: bodyString, headers });
|
|
229
|
+
} catch {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
150
232
|
}
|
|
151
233
|
return resp;
|
|
152
234
|
}
|
|
235
|
+
async followMisdirected(resp, method, path, body, options) {
|
|
236
|
+
if (await this.switchToRedirectTarget(resp)) {
|
|
237
|
+
return await this.tryApiReq(method, path, body, options);
|
|
238
|
+
}
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
async switchToRedirectTarget(resp) {
|
|
242
|
+
let json;
|
|
243
|
+
try {
|
|
244
|
+
json = await resp.json();
|
|
245
|
+
} catch {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
if (!isMisdirectedError(json)) return false;
|
|
249
|
+
const newOrigin = resolveOrigin(this.params, json.primaryAddress);
|
|
250
|
+
if (newOrigin === this.currentOrigin) return false;
|
|
251
|
+
this.switchOrigin(newOrigin);
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
async tryFallbackOrigins(method, path, body, options) {
|
|
255
|
+
const origins = allOrigins(this.params);
|
|
256
|
+
const failedOrigin = this.currentOrigin;
|
|
257
|
+
let lastError = null;
|
|
258
|
+
for (const origin of origins) {
|
|
259
|
+
if (origin === failedOrigin) continue;
|
|
260
|
+
this.switchOrigin(origin);
|
|
261
|
+
const initial = await this.tryApiReq(method, path, body, options);
|
|
262
|
+
if (initial === null) continue;
|
|
263
|
+
if (isApiErrResp(initial)) return initial;
|
|
264
|
+
let result = initial;
|
|
265
|
+
if (result.status === HTTP_MISDIRECTED) {
|
|
266
|
+
const redirected = await this.followMisdirected(result, method, path, body, options);
|
|
267
|
+
if (redirected === null) continue;
|
|
268
|
+
if (isApiErrResp(redirected)) return redirected;
|
|
269
|
+
result = redirected;
|
|
270
|
+
}
|
|
271
|
+
if (result.ok) return result;
|
|
272
|
+
lastError = result;
|
|
273
|
+
}
|
|
274
|
+
return lastError;
|
|
275
|
+
}
|
|
276
|
+
switchOrigin(origin) {
|
|
277
|
+
this.currentOrigin = origin;
|
|
278
|
+
this.token = void 0;
|
|
279
|
+
}
|
|
280
|
+
authHeaders(token, options) {
|
|
281
|
+
return { "Authorization": `Bearer ${token}`, "Content-Type": "application/json", ...options?.headers };
|
|
282
|
+
}
|
|
153
283
|
getToken() {
|
|
154
284
|
if (this.token) {
|
|
155
285
|
const resp = { ok: { token: this.token } };
|
|
@@ -157,16 +287,24 @@ var TypeDBHttpDriver = class {
|
|
|
157
287
|
} else return this.refreshToken();
|
|
158
288
|
}
|
|
159
289
|
async refreshToken() {
|
|
160
|
-
|
|
290
|
+
return this.signinOnce();
|
|
291
|
+
}
|
|
292
|
+
async signinOnce() {
|
|
293
|
+
const url = `${this.currentOrigin}/v1/signin`;
|
|
161
294
|
const body = { username: this.params.username, password: this.params.password };
|
|
162
|
-
|
|
295
|
+
let resp;
|
|
296
|
+
try {
|
|
297
|
+
resp = await fetch(url, { method: "POST", body: JSON.stringify(body), headers: { "Content-Type": "application/json" } });
|
|
298
|
+
} catch {
|
|
299
|
+
return driverError("HDR2", `Cannot connect to server at ${this.currentOrigin}`);
|
|
300
|
+
}
|
|
163
301
|
const json = await this.jsonOrNull(resp);
|
|
164
302
|
if (resp.ok) {
|
|
165
303
|
this.token = json.token;
|
|
166
304
|
return { ok: json };
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
305
|
+
}
|
|
306
|
+
if (isApiError(json)) return { err: json, status: resp.status };
|
|
307
|
+
throw resp;
|
|
170
308
|
}
|
|
171
309
|
async jsonOrNull(resp) {
|
|
172
310
|
const contentLengthRaw = resp.headers.get("Content-Length");
|
|
@@ -185,13 +323,18 @@ var TypeDBHttpDriver = class {
|
|
|
185
323
|
};
|
|
186
324
|
export {
|
|
187
325
|
TypeDBHttpDriver,
|
|
326
|
+
allOrigins,
|
|
327
|
+
driverError,
|
|
188
328
|
getVariableName,
|
|
329
|
+
hostPortFromOrigin,
|
|
189
330
|
isApiError,
|
|
190
331
|
isApiErrorResponse,
|
|
191
332
|
isBasicParams,
|
|
333
|
+
isMisdirectedError,
|
|
192
334
|
isOkResponse,
|
|
193
335
|
isQueryResponseLegacy,
|
|
194
336
|
isTranslatedParams,
|
|
195
|
-
remoteOrigin
|
|
337
|
+
remoteOrigin,
|
|
338
|
+
resolveOrigin
|
|
196
339
|
};
|
|
197
340
|
//# sourceMappingURL=index.mjs.map
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name": "@typedb/driver-http", "version": "3.
|
|
1
|
+
{"name": "@typedb/driver-http", "version": "3.11.1", "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"}}
|