@mdbase-dev/connect 0.1.0-beta.61 → 0.1.0-beta.63
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/browser/integrity.json +1 -1
- package/dist/browser/mdbase-connect.min.js +3 -3
- package/dist/browser/mdbase-connect.min.js.sha384 +1 -1
- package/dist/connection-transport.js +33 -32
- package/dist/crypto.d.ts +1 -1
- package/dist/crypto.js +6 -1
- package/dist/files.js +7 -1
- package/dist/fresh-encrypted-request.d.ts +1 -1
- package/dist/fresh-encrypted-request.js +2 -2
- package/dist/operation-helpers.d.ts +4 -1
- package/dist/operation-helpers.js +29 -1
- package/dist/request-budget.d.ts +5 -0
- package/dist/request-budget.js +7 -0
- package/dist/runtime-utils.js +6 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
sha384-
|
|
1
|
+
sha384-lle3e5SEN8S45RwEaaerEa1VKEBzMw7JZGQcuO1VI734WP7P95QHHR5DbXASXaaL
|
|
@@ -4,10 +4,10 @@ import { MdbaseConnectError, connectError, serverConnectError } from "./errors.j
|
|
|
4
4
|
import { ConnectionFileTransport } from "./connection-file-transport.js";
|
|
5
5
|
import { authorityProofHeaders } from "./authority-proof.js";
|
|
6
6
|
import { PendingMutationStore } from "./pending-mutation-store.js";
|
|
7
|
-
import { directFallbackStatus, isMutation, localNetworkPermission, loopbackRequest, operationFingerprint, operationTransportError, sameAuthorization, throwIfCancelled, unknownMutationOutcome } from "./operation-helpers.js";
|
|
7
|
+
import { directFallbackStatus, encryptedOperationError, fetchOperationRequest, isMutation, localNetworkPermission, loopbackRequest, operationFingerprint, operationTransportError, sameAuthorization, throwIfCancelled, unknownMutationOutcome, withOperationDeadline } from "./operation-helpers.js";
|
|
8
8
|
import { apiError, decodeJsonResponse, oauthErrorCode, parseStored, } from "./runtime-utils.js";
|
|
9
9
|
import { readStoredToken } from "./stored-token.js";
|
|
10
|
-
import { withCooperativeRequestBudget, withRequestBudget } from "./request-budget.js";
|
|
10
|
+
import { requestOptionsWithinBudget, withCooperativeRequestBudget, withRequestBudget } from "./request-budget.js";
|
|
11
11
|
import { sendAuthoritySyncRequest } from "./authority-sync-request.js";
|
|
12
12
|
import { freshEncryptedRequest } from "./fresh-encrypted-request.js";
|
|
13
13
|
import { isExplicitConnectorBusyResponse, retryExplicitConnectorBusy } from "./transient-retry.js";
|
|
@@ -124,13 +124,10 @@ export class ConnectionTransport {
|
|
|
124
124
|
if (!pending) {
|
|
125
125
|
throw connectError("no_pending_mutation", "There is no interrupted mutation to resume.");
|
|
126
126
|
}
|
|
127
|
-
return withCooperativeRequestBudget(options, this.timeouts.requestMs, (budget) => this.performOperationWithinBudget(pending.operation, pending.request?.input ?? {},
|
|
127
|
+
return withCooperativeRequestBudget(options, this.timeouts.requestMs, (budget) => this.performOperationWithinBudget(pending.operation, pending.request?.input ?? {}, requestOptionsWithinBudget(options ?? {}, budget), pending));
|
|
128
128
|
}
|
|
129
129
|
async performOperation(operation, input, options = {}) {
|
|
130
|
-
return withCooperativeRequestBudget(options, this.timeouts.requestMs, (budget) => this.performOperationWithinBudget(operation, input,
|
|
131
|
-
...options,
|
|
132
|
-
signal: budget.signal
|
|
133
|
-
}));
|
|
130
|
+
return withCooperativeRequestBudget(options, this.timeouts.requestMs, (budget) => this.performOperationWithinBudget(operation, input, requestOptionsWithinBudget(options, budget)));
|
|
134
131
|
}
|
|
135
132
|
async performOperationWithinBudget(operation, input, options, storedPending, freshReadRetried = false, connectorBusyRetries = 0, knownRejectedMutationRetry = false) {
|
|
136
133
|
throwIfCancelled(options.signal);
|
|
@@ -214,6 +211,8 @@ export class ConnectionTransport {
|
|
|
214
211
|
&& !freshReadRetried) {
|
|
215
212
|
return this.performOperationWithinBudget(operation, input, options, undefined, true);
|
|
216
213
|
}
|
|
214
|
+
if (attempt.pendingMutation && error.outcomeUnknown)
|
|
215
|
+
throw error;
|
|
217
216
|
if (attempt.pendingMutation
|
|
218
217
|
&& (attempt.directDeliveryUncertain
|
|
219
218
|
|| (attempt.encryptedRequest && attempt.resumingMutation))) {
|
|
@@ -251,16 +250,14 @@ export class ConnectionTransport {
|
|
|
251
250
|
&& !freshReadRetried) {
|
|
252
251
|
return this.performOperationWithinBudget(operation, input, options, undefined, true);
|
|
253
252
|
}
|
|
253
|
+
if (!decrypted.ok) {
|
|
254
|
+
const error = encryptedOperationError(decrypted.problem);
|
|
255
|
+
if (attempt.pendingMutation && !error.outcomeUnknown)
|
|
256
|
+
this.clearPendingMutation(attempt.requestId);
|
|
257
|
+
throw error;
|
|
258
|
+
}
|
|
254
259
|
if (attempt.pendingMutation)
|
|
255
260
|
this.clearPendingMutation(attempt.requestId);
|
|
256
|
-
if (!decrypted.ok)
|
|
257
|
-
throw serverConnectError(decrypted.problem.code === "unknown"
|
|
258
|
-
? decrypted.problem.server_code
|
|
259
|
-
: decrypted.problem.code, decrypted.problem.message, {
|
|
260
|
-
details: decrypted.problem.details,
|
|
261
|
-
operationOutcome: decrypted.problem.operation_outcome ?? "rejected",
|
|
262
|
-
traceId: decrypted.problem.trace_id
|
|
263
|
-
});
|
|
264
261
|
return decrypted.result;
|
|
265
262
|
}
|
|
266
263
|
catch (error) {
|
|
@@ -292,7 +289,7 @@ export class ConnectionTransport {
|
|
|
292
289
|
const recovery = await retryBusy(error);
|
|
293
290
|
if (recovery.retried)
|
|
294
291
|
return recovery.result;
|
|
295
|
-
if (attempt.pendingMutation)
|
|
292
|
+
if (attempt.pendingMutation && !error.outcomeUnknown)
|
|
296
293
|
this.clearPendingMutation(attempt.requestId);
|
|
297
294
|
throw error;
|
|
298
295
|
}
|
|
@@ -380,10 +377,12 @@ export class ConnectionTransport {
|
|
|
380
377
|
if (!pending.envelope) {
|
|
381
378
|
throw connectError("pending_mutation_unresolved", "The pending write belongs to a different transport. Reconnect before retrying it.");
|
|
382
379
|
}
|
|
383
|
-
|
|
380
|
+
// Preserve the durable identity and ciphertext, but refresh the
|
|
381
|
+
// unauthenticated scheduling deadline for this recovery attempt.
|
|
382
|
+
encryptedRequest = withOperationDeadline(pending.envelope, options.deadlineUnixMs);
|
|
384
383
|
}
|
|
385
384
|
else {
|
|
386
|
-
encryptedRequest = await encryptRelayRequest(this.keyStore, token.keyHandle, { grantId: token.grantId, applicationId: token.clientId, encryption: token.encryption }, operation, input, requestId);
|
|
385
|
+
encryptedRequest = await encryptRelayRequest(this.keyStore, token.keyHandle, { grantId: token.grantId, applicationId: token.clientId, encryption: token.encryption }, operation, input, requestId, options.deadlineUnixMs);
|
|
387
386
|
this.pendingMutationStore.store({
|
|
388
387
|
collectionId: token.collectionId,
|
|
389
388
|
...(token.grantId ? { grantId: token.grantId } : {}),
|
|
@@ -401,7 +400,7 @@ export class ConnectionTransport {
|
|
|
401
400
|
}
|
|
402
401
|
}
|
|
403
402
|
else {
|
|
404
|
-
encryptedRequest = await encryptRelayRequest(this.keyStore, token.keyHandle, { grantId: token.grantId, applicationId: token.clientId, encryption: token.encryption }, operation, input);
|
|
403
|
+
encryptedRequest = await encryptRelayRequest(this.keyStore, token.keyHandle, { grantId: token.grantId, applicationId: token.clientId, encryption: token.encryption }, operation, input, undefined, options.deadlineUnixMs);
|
|
405
404
|
}
|
|
406
405
|
}
|
|
407
406
|
catch (error) {
|
|
@@ -460,8 +459,11 @@ export class ConnectionTransport {
|
|
|
460
459
|
this.markDirectUnavailable();
|
|
461
460
|
}
|
|
462
461
|
catch (error) {
|
|
463
|
-
if (options.signal?.aborted)
|
|
462
|
+
if (options.signal?.aborted) {
|
|
463
|
+
if (pendingMutation)
|
|
464
|
+
throw unknownMutationOutcome(requestId, error);
|
|
464
465
|
throw error;
|
|
466
|
+
}
|
|
465
467
|
directDeliveryUncertain = true;
|
|
466
468
|
if ((await localNetworkPermission()) === "denied")
|
|
467
469
|
this.setDirectStatus("denied");
|
|
@@ -481,7 +483,7 @@ export class ConnectionTransport {
|
|
|
481
483
|
}
|
|
482
484
|
let response;
|
|
483
485
|
if (!pendingMutation) {
|
|
484
|
-
encryptedRequest = await freshEncryptedRequest(this.keyStore, relayToken, operation, input);
|
|
486
|
+
encryptedRequest = await freshEncryptedRequest(this.keyStore, relayToken, operation, input, options.deadlineUnixMs);
|
|
485
487
|
requestId = encryptedRequest.request_id;
|
|
486
488
|
}
|
|
487
489
|
try {
|
|
@@ -496,7 +498,7 @@ export class ConnectionTransport {
|
|
|
496
498
|
});
|
|
497
499
|
}
|
|
498
500
|
catch (error) {
|
|
499
|
-
if (pendingMutation
|
|
501
|
+
if (pendingMutation)
|
|
500
502
|
throw unknownMutationOutcome(requestId, error);
|
|
501
503
|
throw error;
|
|
502
504
|
}
|
|
@@ -519,16 +521,15 @@ export class ConnectionTransport {
|
|
|
519
521
|
const proof = token.authority
|
|
520
522
|
? await authorityProofHeaders(this.keyStore, token, "POST", operationUrl, operationBody, token.authority.accessToken)
|
|
521
523
|
: {};
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
});
|
|
524
|
+
let response;
|
|
525
|
+
try {
|
|
526
|
+
response = await fetchOperationRequest(operationUrl, token.authority?.accessToken ?? token.accessToken, proof, operationBody, options.signal);
|
|
527
|
+
}
|
|
528
|
+
catch (error) {
|
|
529
|
+
if (pendingMutation)
|
|
530
|
+
throw unknownMutationOutcome(requestId, error);
|
|
531
|
+
throw error;
|
|
532
|
+
}
|
|
532
533
|
if (response.ok)
|
|
533
534
|
this.setRoute(token.authority ? "remote" : "relay");
|
|
534
535
|
return {
|
package/dist/crypto.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export interface AuthorityProofInput {
|
|
|
46
46
|
/** Sign one remote-authority or token-refresh request with the approved grant key. */
|
|
47
47
|
export declare function signAuthorityRequest(store: GrantKeyStore, handle: string, expectedPublicKey: string, input: AuthorityProofInput): Promise<Record<string, string>>;
|
|
48
48
|
export declare function authorityProofMessage(input: Required<Pick<AuthorityProofInput, "method" | "target" | "credential" | "timestamp" | "nonce">> & Pick<AuthorityProofInput, "body">): Promise<string>;
|
|
49
|
-
export declare function encryptRelayRequest(store: GrantKeyStore, handle: string, binding: RelayBinding, operation: EncryptedRelayOperation, input: unknown, requestId?: string): Promise<EncryptedRelayOperationRequest>;
|
|
49
|
+
export declare function encryptRelayRequest(store: GrantKeyStore, handle: string, binding: RelayBinding, operation: EncryptedRelayOperation, input: unknown, requestId?: string, deadlineUnixMs?: number): Promise<EncryptedRelayOperationRequest>;
|
|
50
50
|
export declare function decryptRelayResponse<Result>(store: GrantKeyStore, handle: string, binding: RelayBinding, request: EncryptedRelayOperationRequest, response: EncryptedRelayOperationResponse): Promise<{
|
|
51
51
|
ok: true;
|
|
52
52
|
result: Result;
|
package/dist/crypto.js
CHANGED
|
@@ -157,8 +157,12 @@ export async function authorityProofMessage(input) {
|
|
|
157
157
|
input.nonce
|
|
158
158
|
].join("\n");
|
|
159
159
|
}
|
|
160
|
-
export async function encryptRelayRequest(store, handle, binding, operation, input, requestId = crypto.randomUUID()) {
|
|
160
|
+
export async function encryptRelayRequest(store, handle, binding, operation, input, requestId = crypto.randomUUID(), deadlineUnixMs) {
|
|
161
161
|
validateGrantEncryption(binding.encryption);
|
|
162
|
+
if (deadlineUnixMs !== undefined
|
|
163
|
+
&& (!Number.isSafeInteger(deadlineUnixMs) || deadlineUnixMs <= 0)) {
|
|
164
|
+
throw new RelayCryptoError("invalid_deadline", "The operation deadline is invalid.");
|
|
165
|
+
}
|
|
162
166
|
const record = await requireAgreementKey(store, handle, binding.encryption.application_agreement_public_key);
|
|
163
167
|
const counter = await store.nextCounter(handle);
|
|
164
168
|
const metadata = {
|
|
@@ -179,6 +183,7 @@ export async function encryptRelayRequest(store, handle, binding, operation, inp
|
|
|
179
183
|
return {
|
|
180
184
|
type: "encrypted_operation_request",
|
|
181
185
|
...envelopeMetadata(metadata),
|
|
186
|
+
...(deadlineUnixMs === undefined ? {} : { deadline_unix_ms: deadlineUnixMs }),
|
|
182
187
|
ciphertext: bytesToBase64Url(new Uint8Array(ciphertext))
|
|
183
188
|
};
|
|
184
189
|
}
|
package/dist/files.js
CHANGED
|
@@ -387,8 +387,14 @@ export class MdbaseFileClient {
|
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
389
|
catch (error) {
|
|
390
|
+
const failure = options.signal?.aborted
|
|
391
|
+
? connectError("operation_cancelled", "The file transfer was cancelled.", {
|
|
392
|
+
operationOutcome: "not_sent",
|
|
393
|
+
cause: options.signal.reason
|
|
394
|
+
})
|
|
395
|
+
: error;
|
|
390
396
|
await finish();
|
|
391
|
-
controller.error(normalizeFileError(
|
|
397
|
+
controller.error(normalizeFileError(failure));
|
|
392
398
|
}
|
|
393
399
|
},
|
|
394
400
|
cancel: finish
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { CollectionOperation, EncryptedRelayOperationRequest } from "@mdbase-dev/connect-protocol";
|
|
2
2
|
import { type GrantKeyStore } from "./crypto.js";
|
|
3
3
|
import type { StoredToken } from "./internal-types.js";
|
|
4
|
-
export declare function freshEncryptedRequest(keyStore: GrantKeyStore, token: StoredToken, operation: CollectionOperation, input: unknown): Promise<EncryptedRelayOperationRequest>;
|
|
4
|
+
export declare function freshEncryptedRequest(keyStore: GrantKeyStore, token: StoredToken, operation: CollectionOperation, input: unknown, deadlineUnixMs?: number): Promise<EncryptedRelayOperationRequest>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { encryptRelayRequest, RelayCryptoError } from "./crypto.js";
|
|
2
2
|
import { connectError, serverConnectError } from "./errors.js";
|
|
3
|
-
export async function freshEncryptedRequest(keyStore, token, operation, input) {
|
|
3
|
+
export async function freshEncryptedRequest(keyStore, token, operation, input, deadlineUnixMs) {
|
|
4
4
|
if (!token.encryption || !token.grantId || !token.keyHandle) {
|
|
5
5
|
throw connectError("authorization_binding_incompatible", "The refreshed authorization no longer supports encrypted connector operations.", {
|
|
6
6
|
details: {
|
|
@@ -17,7 +17,7 @@ export async function freshEncryptedRequest(keyStore, token, operation, input) {
|
|
|
17
17
|
grantId: token.grantId,
|
|
18
18
|
applicationId: token.clientId,
|
|
19
19
|
encryption: token.encryption
|
|
20
|
-
}, operation, input);
|
|
20
|
+
}, operation, input, undefined, deadlineUnixMs);
|
|
21
21
|
}
|
|
22
22
|
catch (error) {
|
|
23
23
|
if (error instanceof RelayCryptoError) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CollectionOperation } from "@mdbase-dev/connect-protocol";
|
|
1
|
+
import { type CollectionOperation, type ConnectProblem, type EncryptedRelayOperationRequest } from "@mdbase-dev/connect-protocol";
|
|
2
2
|
import { MdbaseConnectError } from "./errors.js";
|
|
3
3
|
import type { StoredToken } from "./internal-types.js";
|
|
4
4
|
import type { DeleteInput, DeletePreflightResult, MutationEstimate, RenameInput, RenamePreflightResult } from "./operation-types.js";
|
|
@@ -9,10 +9,13 @@ export declare function loopbackRequest(init: RequestInit): LoopbackRequestInit;
|
|
|
9
9
|
export declare function localNetworkPermission(): Promise<PermissionState | null>;
|
|
10
10
|
export declare function directFallbackStatus(status: number): boolean;
|
|
11
11
|
export declare function isMutation(operation: CollectionOperation, input?: unknown): boolean;
|
|
12
|
+
export declare function withOperationDeadline(request: EncryptedRelayOperationRequest, deadlineUnixMs?: number): EncryptedRelayOperationRequest;
|
|
12
13
|
export declare function uniqueOperations(operations: CollectionOperation[]): CollectionOperation[];
|
|
13
14
|
export declare function sameAuthorization(left: StoredToken, right: StoredToken): boolean;
|
|
14
15
|
export declare function throwIfCancelled(signal?: AbortSignal): void;
|
|
15
16
|
export declare function operationTransportError(error: unknown, signal: AbortSignal | undefined, pendingRequestId: string | undefined, unavailableCode: "hosted_provider_unavailable" | "relay_unavailable"): Error;
|
|
17
|
+
export declare function encryptedOperationError(problem: ConnectProblem): MdbaseConnectError;
|
|
18
|
+
export declare function fetchOperationRequest(url: string, accessToken: string, proof: Record<string, string>, body: string, signal?: AbortSignal): Promise<Response>;
|
|
16
19
|
export declare function isCancellation(error: unknown, signal?: AbortSignal): boolean;
|
|
17
20
|
export declare function assertRenamePreview(input: RenameInput, preview: RenamePreflightResult): void;
|
|
18
21
|
export declare function assertDeletePreview(input: DeleteInput, preview: DeletePreflightResult): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isMutatingOperation, mutationFingerprint } from "@mdbase-dev/connect-protocol";
|
|
2
|
-
import { MdbaseConnectError, connectError } from "./errors.js";
|
|
2
|
+
import { MdbaseConnectError, connectError, serverConnectError } from "./errors.js";
|
|
3
3
|
export function loopbackRequest(init) {
|
|
4
4
|
return { ...init, credentials: "omit", targetAddressSpace: "loopback" };
|
|
5
5
|
}
|
|
@@ -22,6 +22,15 @@ export function directFallbackStatus(status) {
|
|
|
22
22
|
export function isMutation(operation, input) {
|
|
23
23
|
return isMutatingOperation(operation, input);
|
|
24
24
|
}
|
|
25
|
+
export function withOperationDeadline(request, deadlineUnixMs) {
|
|
26
|
+
if (request.deadline_unix_ms === deadlineUnixMs)
|
|
27
|
+
return request;
|
|
28
|
+
const { deadline_unix_ms: _previousDeadline, ...identity } = request;
|
|
29
|
+
return {
|
|
30
|
+
...identity,
|
|
31
|
+
...(deadlineUnixMs === undefined ? {} : { deadline_unix_ms: deadlineUnixMs })
|
|
32
|
+
};
|
|
33
|
+
}
|
|
25
34
|
export function uniqueOperations(operations) {
|
|
26
35
|
return [...new Set(operations)];
|
|
27
36
|
}
|
|
@@ -61,6 +70,25 @@ export function operationTransportError(error, signal, pendingRequestId, unavail
|
|
|
61
70
|
}
|
|
62
71
|
return error instanceof Error ? error : new Error(String(error));
|
|
63
72
|
}
|
|
73
|
+
export function encryptedOperationError(problem) {
|
|
74
|
+
return serverConnectError(problem.code === "unknown" ? problem.server_code : problem.code, problem.message, {
|
|
75
|
+
details: problem.details,
|
|
76
|
+
operationOutcome: problem.operation_outcome ?? "rejected",
|
|
77
|
+
traceId: problem.trace_id
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
export function fetchOperationRequest(url, accessToken, proof, body, signal) {
|
|
81
|
+
return fetch(url, {
|
|
82
|
+
method: "POST",
|
|
83
|
+
headers: {
|
|
84
|
+
authorization: `Bearer ${accessToken}`,
|
|
85
|
+
"content-type": "application/json",
|
|
86
|
+
...proof
|
|
87
|
+
},
|
|
88
|
+
body,
|
|
89
|
+
signal
|
|
90
|
+
});
|
|
91
|
+
}
|
|
64
92
|
export function isCancellation(error, signal) {
|
|
65
93
|
return signal?.aborted === true
|
|
66
94
|
|| (error instanceof MdbaseConnectError && error.code === "operation_cancelled");
|
package/dist/request-budget.d.ts
CHANGED
|
@@ -19,6 +19,11 @@ export interface RequestBudget {
|
|
|
19
19
|
remainingMs(): number | null;
|
|
20
20
|
dispose(): void;
|
|
21
21
|
}
|
|
22
|
+
export type OperationRequestOptions = ConnectRequestOptions & {
|
|
23
|
+
/** Absolute budget shared with the connector; never supplied directly by callers. */
|
|
24
|
+
deadlineUnixMs?: number;
|
|
25
|
+
};
|
|
26
|
+
export declare function requestOptionsWithinBudget(options: ConnectRequestOptions, budget: RequestBudget): OperationRequestOptions;
|
|
22
27
|
export declare function createRequestBudget(options?: ConnectRequestOptions, defaultTimeoutMs?: number | null, now?: () => number): RequestBudget;
|
|
23
28
|
export declare function withRequestBudget<Result>(options: ConnectRequestOptions | undefined, defaultTimeoutMs: number | null, operation: (budget: RequestBudget) => Promise<Result>): Promise<Result>;
|
|
24
29
|
/**
|
package/dist/request-budget.js
CHANGED
|
@@ -13,6 +13,13 @@ export function resolveConnectTimeouts(timeouts = {}) {
|
|
|
13
13
|
syncMs: configuredTimeout(timeouts.syncMs, DEFAULT_SYNC_TIMEOUT_MS, "syncMs")
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
|
+
export function requestOptionsWithinBudget(options, budget) {
|
|
17
|
+
return {
|
|
18
|
+
...options,
|
|
19
|
+
signal: budget.signal,
|
|
20
|
+
...(budget.deadline === null ? {} : { deadlineUnixMs: budget.deadline })
|
|
21
|
+
};
|
|
22
|
+
}
|
|
16
23
|
export function createRequestBudget(options = {}, defaultTimeoutMs = DEFAULT_REQUEST_TIMEOUT_MS, now = Date.now) {
|
|
17
24
|
const configured = options.timeoutMs === undefined ? defaultTimeoutMs : options.timeoutMs;
|
|
18
25
|
const timeoutMs = configured === null ? null : validTimeout(configured);
|
package/dist/runtime-utils.js
CHANGED
|
@@ -49,7 +49,12 @@ export async function createPkce() {
|
|
|
49
49
|
return { verifier, challenge: bytesToBase64Url(new Uint8Array(digest)) };
|
|
50
50
|
}
|
|
51
51
|
export function apiError(body, fallbackCode, fallbackMessage, status) {
|
|
52
|
-
return serverConnectError(oauthErrorCode(body) ?? body?.error?.code ?? fallbackCode, body?.error_description ?? body?.error?.message ?? fallbackMessage, {
|
|
52
|
+
return serverConnectError(oauthErrorCode(body) ?? body?.error?.code ?? fallbackCode, body?.error_description ?? body?.error?.message ?? fallbackMessage, {
|
|
53
|
+
status,
|
|
54
|
+
details: body?.error?.details,
|
|
55
|
+
operationOutcome: body?.error?.operation_outcome,
|
|
56
|
+
traceId: body?.error?.trace_id
|
|
57
|
+
});
|
|
53
58
|
}
|
|
54
59
|
export function oauthErrorCode(body) {
|
|
55
60
|
return typeof body?.error === "string" ? body.error : undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mdbase-dev/connect",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.63",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"README.md"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@mdbase-dev/connect-protocol": "0.1.0-beta.
|
|
36
|
+
"@mdbase-dev/connect-protocol": "0.1.0-beta.63"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"esbuild": "^0.28.1",
|