@mdbase-dev/connect 0.1.0-beta.100
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/LICENSE +21 -0
- package/README.md +696 -0
- package/dist/advanced.d.ts +9 -0
- package/dist/advanced.js +6 -0
- package/dist/application-contract.d.ts +22 -0
- package/dist/application-contract.js +75 -0
- package/dist/application-identity.d.ts +34 -0
- package/dist/application-identity.js +148 -0
- package/dist/application-session.d.ts +167 -0
- package/dist/application-session.js +722 -0
- package/dist/async.d.ts +1 -0
- package/dist/async.js +19 -0
- package/dist/authority-proof.d.ts +3 -0
- package/dist/authority-proof.js +24 -0
- package/dist/authority-sync-request.d.ts +3 -0
- package/dist/authority-sync-request.js +20 -0
- package/dist/authorization-refresh.d.ts +14 -0
- package/dist/authorization-refresh.js +41 -0
- package/dist/authorization-types.d.ts +7 -0
- package/dist/authorization-types.js +1 -0
- package/dist/authorization-url.d.ts +5 -0
- package/dist/authorization-url.js +34 -0
- package/dist/base64.d.ts +3 -0
- package/dist/base64.js +21 -0
- package/dist/browser/integrity.json +4 -0
- package/dist/browser/mdbase-connect.min.js +3 -0
- package/dist/browser/mdbase-connect.min.js.sha384 +1 -0
- package/dist/browser.d.ts +3 -0
- package/dist/browser.js +5 -0
- package/dist/capabilities.d.ts +24 -0
- package/dist/capabilities.js +91 -0
- package/dist/collection-client.d.ts +66 -0
- package/dist/collection-client.js +686 -0
- package/dist/connect-authorization-helpers.d.ts +4 -0
- package/dist/connect-authorization-helpers.js +25 -0
- package/dist/connect-options.d.ts +35 -0
- package/dist/connect-options.js +1 -0
- package/dist/connect.d.ts +66 -0
- package/dist/connect.js +711 -0
- package/dist/connection-file-transport.d.ts +34 -0
- package/dist/connection-file-transport.js +85 -0
- package/dist/connection-index.d.ts +3 -0
- package/dist/connection-index.js +20 -0
- package/dist/connection-notifications.d.ts +31 -0
- package/dist/connection-notifications.js +197 -0
- package/dist/connection-transport-internals.d.ts +24 -0
- package/dist/connection-transport-internals.js +1 -0
- package/dist/connection-transport.d.ts +64 -0
- package/dist/connection-transport.js +725 -0
- package/dist/connection-types.d.ts +38 -0
- package/dist/connection-types.js +1 -0
- package/dist/connection.d.ts +175 -0
- package/dist/connection.js +606 -0
- package/dist/crypto-entry.d.ts +7 -0
- package/dist/crypto-entry.js +4 -0
- package/dist/crypto.d.ts +63 -0
- package/dist/crypto.js +409 -0
- package/dist/direct-access.d.ts +3 -0
- package/dist/direct-access.js +29 -0
- package/dist/errors.d.ts +45 -0
- package/dist/errors.js +142 -0
- package/dist/external-store.d.ts +10 -0
- package/dist/external-store.js +10 -0
- package/dist/file-crypto.d.ts +25 -0
- package/dist/file-crypto.js +132 -0
- package/dist/file-sha256.d.ts +12 -0
- package/dist/file-sha256.js +143 -0
- package/dist/file-stream-source.d.ts +17 -0
- package/dist/file-stream-source.js +157 -0
- package/dist/file-transfer-internals.d.ts +23 -0
- package/dist/file-transfer-internals.js +228 -0
- package/dist/files.d.ts +115 -0
- package/dist/files.js +563 -0
- package/dist/fresh-encrypted-request.d.ts +4 -0
- package/dist/fresh-encrypted-request.js +28 -0
- package/dist/grant-key-leases.d.ts +24 -0
- package/dist/grant-key-leases.js +144 -0
- package/dist/hosted-file-request.d.ts +6 -0
- package/dist/hosted-file-request.js +63 -0
- package/dist/hosted-operation-response.d.ts +5 -0
- package/dist/hosted-operation-response.js +26 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +10 -0
- package/dist/internal-types.d.ts +100 -0
- package/dist/internal-types.js +1 -0
- package/dist/local-file-transport.d.ts +37 -0
- package/dist/local-file-transport.js +457 -0
- package/dist/mdbase-connect.d.ts +28 -0
- package/dist/mdbase-connect.js +53 -0
- package/dist/notifications.d.ts +48 -0
- package/dist/notifications.js +52 -0
- package/dist/operation-helpers.d.ts +27 -0
- package/dist/operation-helpers.js +144 -0
- package/dist/operation-types.d.ts +707 -0
- package/dist/operation-types.js +1 -0
- package/dist/outcomes.d.ts +51 -0
- package/dist/outcomes.js +194 -0
- package/dist/pending-mutation-store.d.ts +13 -0
- package/dist/pending-mutation-store.js +64 -0
- package/dist/pending-recovery-transports.d.ts +5 -0
- package/dist/pending-recovery-transports.js +52 -0
- package/dist/popup-authorization.d.ts +31 -0
- package/dist/popup-authorization.js +100 -0
- package/dist/query-pagination.d.ts +6 -0
- package/dist/query-pagination.js +119 -0
- package/dist/request-budget.d.ts +34 -0
- package/dist/request-budget.js +104 -0
- package/dist/request-coordinator.d.ts +29 -0
- package/dist/request-coordinator.js +213 -0
- package/dist/retired-grant-keys.d.ts +9 -0
- package/dist/retired-grant-keys.js +56 -0
- package/dist/runtime-utils.d.ts +52 -0
- package/dist/runtime-utils.js +368 -0
- package/dist/saved-view-pagination.d.ts +6 -0
- package/dist/saved-view-pagination.js +76 -0
- package/dist/selection.d.ts +48 -0
- package/dist/selection.js +112 -0
- package/dist/session.d.ts +114 -0
- package/dist/session.js +569 -0
- package/dist/shared-operation.d.ts +7 -0
- package/dist/shared-operation.js +41 -0
- package/dist/stored-token.d.ts +10 -0
- package/dist/stored-token.js +64 -0
- package/dist/structured-readiness.d.ts +77 -0
- package/dist/structured-readiness.js +126 -0
- package/dist/token-response.d.ts +12 -0
- package/dist/token-response.js +81 -0
- package/dist/transient-retry.d.ts +22 -0
- package/dist/transient-retry.js +59 -0
- package/dist/watch-policy.d.ts +8 -0
- package/dist/watch-policy.js +12 -0
- package/package.json +51 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
export class GrantKeyLeaseRegistry {
|
|
2
|
+
namespace;
|
|
3
|
+
onFinalRelease;
|
|
4
|
+
leases = new Map();
|
|
5
|
+
locks = webLockManager();
|
|
6
|
+
retainAutomaticallyRetiredKeys = this.locks === null;
|
|
7
|
+
constructor(namespace, onFinalRelease) {
|
|
8
|
+
this.namespace = namespace;
|
|
9
|
+
this.onFinalRelease = onFinalRelease;
|
|
10
|
+
}
|
|
11
|
+
async acquire(collectionId, keyHandle, signal) {
|
|
12
|
+
const releaseLocal = this.acquireLocal(collectionId, keyHandle);
|
|
13
|
+
if (!this.locks)
|
|
14
|
+
return releaseLocal;
|
|
15
|
+
try {
|
|
16
|
+
const releaseWeb = await acquireSharedWebLock(this.locks, this.lockName(collectionId, keyHandle), signal);
|
|
17
|
+
return once(() => {
|
|
18
|
+
releaseWeb();
|
|
19
|
+
releaseLocal();
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
releaseLocal();
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
deleteExclusive(collectionId, keyHandle, action) {
|
|
28
|
+
if (this.retainAutomaticallyRetiredKeys)
|
|
29
|
+
return;
|
|
30
|
+
if (this.locks) {
|
|
31
|
+
void this.locks.request(this.lockName(collectionId, keyHandle), { mode: "exclusive" }, action).catch(() => undefined);
|
|
32
|
+
}
|
|
33
|
+
else if (!this.has(collectionId, keyHandle)) {
|
|
34
|
+
void Promise.resolve().then(action).catch(() => undefined);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
has(collectionId, keyHandle) {
|
|
38
|
+
return this.leases.get(collectionId)?.has(keyHandle) ?? false;
|
|
39
|
+
}
|
|
40
|
+
handles(collectionId) {
|
|
41
|
+
return this.leases.get(collectionId)?.keys() ?? [];
|
|
42
|
+
}
|
|
43
|
+
acquireLocal(collectionId, keyHandle) {
|
|
44
|
+
const collection = this.leases.get(collectionId) ?? new Map();
|
|
45
|
+
collection.set(keyHandle, (collection.get(keyHandle) ?? 0) + 1);
|
|
46
|
+
this.leases.set(collectionId, collection);
|
|
47
|
+
return once(() => {
|
|
48
|
+
const remaining = (collection.get(keyHandle) ?? 1) - 1;
|
|
49
|
+
if (remaining > 0)
|
|
50
|
+
collection.set(keyHandle, remaining);
|
|
51
|
+
else {
|
|
52
|
+
collection.delete(keyHandle);
|
|
53
|
+
if (collection.size === 0)
|
|
54
|
+
this.leases.delete(collectionId);
|
|
55
|
+
this.onFinalRelease(collectionId, keyHandle);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
lockName(collectionId, keyHandle) {
|
|
60
|
+
return `mdbase-connect:grant-key:${this.namespace}:${collectionId}:${keyHandle}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export class GrantKeyLeaseSet {
|
|
64
|
+
collectionId;
|
|
65
|
+
acquire;
|
|
66
|
+
releases = new Map();
|
|
67
|
+
constructor(collectionId, acquire) {
|
|
68
|
+
this.collectionId = collectionId;
|
|
69
|
+
this.acquire = acquire;
|
|
70
|
+
}
|
|
71
|
+
async retain(tokenOrHandle, signal) {
|
|
72
|
+
const handle = typeof tokenOrHandle === "string" ? tokenOrHandle : tokenOrHandle?.keyHandle;
|
|
73
|
+
if (!handle)
|
|
74
|
+
return;
|
|
75
|
+
let lease = this.releases.get(handle);
|
|
76
|
+
if (!lease) {
|
|
77
|
+
lease = this.acquire(this.collectionId, handle, signal);
|
|
78
|
+
this.releases.set(handle, lease);
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
await lease;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (this.releases.get(handle) === lease)
|
|
85
|
+
this.releases.delete(handle);
|
|
86
|
+
this.release();
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
release() {
|
|
91
|
+
for (const lease of this.releases.values())
|
|
92
|
+
void lease.then((release) => release());
|
|
93
|
+
this.releases.clear();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export async function retainCurrentGrantToken(readCurrent, leases, signal) {
|
|
97
|
+
while (true) {
|
|
98
|
+
const snapshot = readCurrent();
|
|
99
|
+
if (!snapshot)
|
|
100
|
+
return null;
|
|
101
|
+
await leases.retain(snapshot, signal);
|
|
102
|
+
const current = readCurrent();
|
|
103
|
+
if (!current)
|
|
104
|
+
return null;
|
|
105
|
+
if (current.keyHandle === snapshot.keyHandle)
|
|
106
|
+
return current;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function webLockManager() {
|
|
110
|
+
const locks = typeof navigator === "undefined"
|
|
111
|
+
? undefined
|
|
112
|
+
: navigator.locks;
|
|
113
|
+
if (locks)
|
|
114
|
+
return locks;
|
|
115
|
+
const browser = typeof window !== "undefined"
|
|
116
|
+
|| typeof globalThis.importScripts === "function";
|
|
117
|
+
return browser ? null : undefined;
|
|
118
|
+
}
|
|
119
|
+
async function acquireSharedWebLock(locks, name, signal) {
|
|
120
|
+
let acquired;
|
|
121
|
+
let rejectAcquisition;
|
|
122
|
+
let release;
|
|
123
|
+
const ready = new Promise((resolve, reject) => {
|
|
124
|
+
acquired = resolve;
|
|
125
|
+
rejectAcquisition = reject;
|
|
126
|
+
});
|
|
127
|
+
const held = new Promise((resolve) => { release = resolve; });
|
|
128
|
+
const request = locks.request(name, { mode: "shared", ...(signal ? { signal } : {}) }, async () => {
|
|
129
|
+
acquired();
|
|
130
|
+
await held;
|
|
131
|
+
});
|
|
132
|
+
void request.catch(rejectAcquisition);
|
|
133
|
+
await ready;
|
|
134
|
+
return once(release);
|
|
135
|
+
}
|
|
136
|
+
function once(action) {
|
|
137
|
+
let called = false;
|
|
138
|
+
return () => {
|
|
139
|
+
if (called)
|
|
140
|
+
return;
|
|
141
|
+
called = true;
|
|
142
|
+
action();
|
|
143
|
+
};
|
|
144
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { StoredToken } from "./internal-types.js";
|
|
2
|
+
type ProofHeaders = (token: StoredToken, method: "GET" | "POST" | "DELETE", url: string, body: string | undefined, credential: string) => Promise<Record<string, string>>;
|
|
3
|
+
export declare function sendHostedFileRequest(token: StoredToken, method: "GET" | "POST" | "DELETE", path: string, input: unknown, signal: AbortSignal | undefined, proofHeaders: ProofHeaders): Promise<Response>;
|
|
4
|
+
export declare function performHostedFileRequest<Result>(token: StoredToken, method: "GET" | "POST" | "DELETE", path: string, input: unknown, signal: AbortSignal | undefined, refresh: (signal?: AbortSignal) => Promise<StoredToken>, proofHeaders: ProofHeaders, retain?: (token: StoredToken) => Promise<StoredToken>): Promise<Result>;
|
|
5
|
+
export declare function performHostedFilePartRequest(token: StoredToken, path: string, expectedLength: number, signal: AbortSignal | undefined, refresh: (signal?: AbortSignal) => Promise<StoredToken>, proofHeaders: ProofHeaders, retain?: (token: StoredToken) => Promise<StoredToken>): Promise<ReadableStream<Uint8Array>>;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { connectError } from "./errors.js";
|
|
2
|
+
import { apiError, decodeJsonResponse } from "./runtime-utils.js";
|
|
3
|
+
export async function sendHostedFileRequest(token, method, path, input, signal, proofHeaders) {
|
|
4
|
+
if (!token.authority) {
|
|
5
|
+
throw connectError("not_remote_authority", "This authorization has no remote authority endpoint.");
|
|
6
|
+
}
|
|
7
|
+
const suffix = path === "" || path.startsWith("?") ? path : `/${path}`;
|
|
8
|
+
const url = `${token.authority.filesUrl}${suffix}`;
|
|
9
|
+
const body = input === undefined ? undefined : JSON.stringify(input);
|
|
10
|
+
const proof = await proofHeaders(token, method, url, body, token.authority.accessToken);
|
|
11
|
+
return fetch(url, {
|
|
12
|
+
method,
|
|
13
|
+
redirect: "error",
|
|
14
|
+
headers: {
|
|
15
|
+
authorization: `Bearer ${token.authority.accessToken}`,
|
|
16
|
+
...(body === undefined ? {} : { "content-type": "application/json" }),
|
|
17
|
+
...proof
|
|
18
|
+
},
|
|
19
|
+
...(body === undefined ? {} : { body }),
|
|
20
|
+
...(signal ? { signal } : {})
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export async function performHostedFileRequest(token, method, path, input, signal, refresh, proofHeaders, retain = async (token) => token) {
|
|
24
|
+
let active = token;
|
|
25
|
+
let response = await sendHostedFileRequest(active, method, path, input, signal, proofHeaders);
|
|
26
|
+
if (response.status === 401 && active.refreshToken) {
|
|
27
|
+
active = await retain(await refresh(signal));
|
|
28
|
+
if (!active.authority || !active.fileCapability) {
|
|
29
|
+
throw connectError("authority_authorization_changed", "Reconnect this collection before accessing its files.");
|
|
30
|
+
}
|
|
31
|
+
response = await sendHostedFileRequest(active, method, path, input, signal, proofHeaders);
|
|
32
|
+
}
|
|
33
|
+
const body = await decodeJsonResponse(response, "invalid_operation_response", "The hosted authority returned an invalid file response.");
|
|
34
|
+
if (!response.ok) {
|
|
35
|
+
throw apiError(body, "operation_failed", "Collection file request failed.", response.status);
|
|
36
|
+
}
|
|
37
|
+
return body;
|
|
38
|
+
}
|
|
39
|
+
export async function performHostedFilePartRequest(token, path, expectedLength, signal, refresh, proofHeaders, retain = async (token) => token) {
|
|
40
|
+
let active = token;
|
|
41
|
+
let response = await sendHostedFileRequest(active, "GET", path, undefined, signal, proofHeaders);
|
|
42
|
+
if (response.status === 401 && active.refreshToken) {
|
|
43
|
+
active = await retain(await refresh(signal));
|
|
44
|
+
if (!active.authority || !active.fileCapability) {
|
|
45
|
+
throw connectError("authority_authorization_changed", "Reconnect this collection before accessing its files.");
|
|
46
|
+
}
|
|
47
|
+
response = await sendHostedFileRequest(active, "GET", path, undefined, signal, proofHeaders);
|
|
48
|
+
}
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
const body = await decodeJsonResponse(response, "invalid_operation_response", "The hosted authority returned an invalid file range error response.");
|
|
51
|
+
throw apiError(body, "operation_failed", "Collection file range request failed.", response.status);
|
|
52
|
+
}
|
|
53
|
+
const contentLength = response.headers.get("content-length");
|
|
54
|
+
if (contentLength === null || !/^(0|[1-9][0-9]*)$/u.test(contentLength)
|
|
55
|
+
|| Number(contentLength) !== expectedLength) {
|
|
56
|
+
await response.body?.cancel().catch(() => undefined);
|
|
57
|
+
throw connectError("invalid_operation_response", "The hosted file response declared an unexpected byte length.");
|
|
58
|
+
}
|
|
59
|
+
if (!response.body) {
|
|
60
|
+
throw connectError("invalid_operation_response", "The hosted file response did not contain a byte stream.");
|
|
61
|
+
}
|
|
62
|
+
return response.body;
|
|
63
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { connectError, serverConnectError } from "./errors.js";
|
|
2
|
+
import { decodeJsonResponse } from "./runtime-utils.js";
|
|
3
|
+
export async function decodeHostedOperationResponse(response, hosted) {
|
|
4
|
+
try {
|
|
5
|
+
return {
|
|
6
|
+
body: await decodeJsonResponse(response, "invalid_operation_response", "The collection authority returned a response that is not valid JSON.")
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
catch (cause) {
|
|
10
|
+
if (!response.ok && hosted && isDefinitiveHostedHttpRejection(response.status)) {
|
|
11
|
+
return {
|
|
12
|
+
body: undefined,
|
|
13
|
+
httpError: serverConnectError("operation_failed", "Collection operation failed.", {
|
|
14
|
+
status: response.status,
|
|
15
|
+
operationOutcome: "rejected"
|
|
16
|
+
})
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
throw connectError("invalid_operation_response", "The collection authority returned a response that is not valid JSON.", { cause });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function isDefinitiveHostedHttpRejection(status) {
|
|
23
|
+
return status >= 400
|
|
24
|
+
&& status < 500
|
|
25
|
+
&& ![408, 425, 429].includes(status);
|
|
26
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type { MdbaseDeviceAuthorization } from "./authorization-types.js";
|
|
2
|
+
export { MdbaseApplicationSession, MdbaseMemoryVerificationStore } from "./application-session.js";
|
|
3
|
+
export type { MdbaseApplicationSessionOptions, MdbaseApplicationVerificationStore, MdbaseDefinitionUpdate, MdbaseCollectionSetupUpdate, MdbaseApplicationSessionSnapshot } from "./application-session.js";
|
|
4
|
+
export type { MdbaseConnectOptions, MdbaseConnectTimeouts, MdbaseFrontmatter } from "./connect-options.js";
|
|
5
|
+
export { MdbaseConnect } from "./mdbase-connect.js";
|
|
6
|
+
export { MdbaseConnection } from "./connection.js";
|
|
7
|
+
export type { MdbaseAuthorizationTarget, MdbaseAuthorizeOptions, MdbaseConnectionAuthorizeOptions, MdbaseConnectEnvironment, MdbaseAuthorizationResult, MdbaseAuthorizationOutcome } from "./connection.js";
|
|
8
|
+
export type { MdbaseConnectionRoute, DirectAccessStatus, MdbaseConnectionInfo, MdbaseAuthorizationCapabilities, MdbaseSyncTransport, MdbaseSyncConnection } from "./connection-types.js";
|
|
9
|
+
export { effectiveCapabilities } from "./capabilities.js";
|
|
10
|
+
export type { MdbaseStructuredReadiness } from "./structured-readiness.js";
|
|
11
|
+
export type { MdbaseCapabilityState, MdbaseCapabilityEvidence, MdbaseEffectiveCapability, MdbaseEffectiveCapabilities } from "./capabilities.js";
|
|
12
|
+
export { MdbaseConnectError, isRetryableConnectError } from "./errors.js";
|
|
13
|
+
export type { ConnectErrorContext } from "./errors.js";
|
|
14
|
+
export { MdbaseFileClient } from "./files.js";
|
|
15
|
+
export type { MdbaseFileSource, CollectionFileDescriptor, MdbaseFileDeleteReceipt, MdbaseFileStreamSource, MdbaseFileProgress, MdbaseFileListOptions, MdbaseFileUploadOptions, MdbaseFileStreamUploadOptions, MdbaseFileDownloadOptions, MdbaseFileMoveOptions, MdbaseFileDeleteOptions } from "./files.js";
|
|
16
|
+
export { parseMdbasePushPayload, parseMdbaseNativeNotificationData, showMdbasePushNotification } from "./notifications.js";
|
|
17
|
+
export type { MdbaseNotificationRegistrationOptions, MdbaseNotificationRegistration, MdbaseNativeNotificationRegistrationOptions, MdbaseNativeNotificationRegistration, MdbaseNativeNotificationData, MdbasePushPayload } from "./notifications.js";
|
|
18
|
+
export type { ConnectSuccess, ConnectFailure, ConnectOutcome, CommonOperationProblemCode, RegistrationProblemCode, AuthorizationProblemCode, NotificationProblemCode, DirectAccessProblemCode, SessionProblemCode, CollectionSetupProblemCode, CollectionDescriptionProblemCode, CollectionReadProblemCode, CollectionQueryProblemCode, CollectionMutationProblemCode, CollectionChangesProblemCode, CollectionTypeProblemCode } from "./outcomes.js";
|
|
19
|
+
export type { MdbaseDesiredTimer, MdbaseTimer, MdbaseTimerList, MdbaseTimerReconciliation, ReadInput, DataContractSelector, CollectionFileMetadata, DataContractViewIdentity, QueryRecord, RecordDocument, QueryInput, QueryProjection, QuerySelectionExpression, QueryOrder, QuerySummary, QueryResult, QueryPagesOptions, QueryAllOptions, QueryPage, ConnectRequestOptions, MutationEstimate, MutationProgressState, MutationProgress, MutationProgressOptions, RequestCoordinationOptions, RenameProgressOptions, DeleteProgressOptions, PendingMutationSummary, PendingMutation, CreateInput, UpdateInput, DeleteInput, DeleteResult, DeletePreflightResult, RenameInput, RenameResult, RenamePreflightResult, ReadTypeInput, CreateTypeInput, UpdateTypeInput, ReadViewSourceInput, CreateViewSourceInput, UpdateViewSourceInput, DeleteViewSourceInput, DeleteViewSourceResult, ExecuteViewInput, SavedViewPresentation, SavedViewSource, SavedViewProperty, SavedNamedView, SavedViewDocument, SavedViewList, SavedViewSourceDocument, SavedViewExecution, SavedViewPage, SavedViewPagesOptions, ContractSetupChoice, TypePackResourceDiff, TypePackReceipt, TypePackAssessment, TypePackApplyResult, ConfigurationContributionValue, ConfigurationRequirement, ConfigurationProvision, ApplicationCollectionSetupRequirements, ApplicationCollectionSetupProvisions, ConfigurationSetupConflict, ConfigurationSetupAssessment, CollectionSetupAssessment, CollectionSetupReceipt, CollectionSetupApplyResult, AssessTypePackInput, ApplyTypePackInput, AssessCollectionSetupInput, ApplyCollectionSetupInput, ChangesInput, WatchOptions, WatchRetryOptions, WatchStatus, WatchInput, MdbaseWatchSubscription, CollectionChange, CollectionChangesPage, CollectionDescription, CollectionContractDescriptor, CollectionContractImplementationDescriptor, CollectionTypeDescriptor } from "./operation-types.js";
|
|
20
|
+
export { externalStore } from "./external-store.js";
|
|
21
|
+
export type { MdbaseExternalStore } from "./external-store.js";
|
|
22
|
+
export { MdbaseBrowserSelection, MdbaseMemorySelection } from "./selection.js";
|
|
23
|
+
export type { MdbaseSelectionHistory, MdbaseApplicationSelection, MdbaseBrowserSelectionOptions } from "./selection.js";
|
|
24
|
+
export type { MdbaseUnavailableReason } from "./session.js";
|
|
25
|
+
export { MDBASE_RECORD_CREATED_CONTRACT, MDBASE_TIMER_FIRED_CONTRACT, operationsForApplicationCapabilities } from "@mdbase-dev/connect-protocol";
|
|
26
|
+
export type { MdbaseApplicationManifest, MdbaseApplicationManifest as MdbaseAppManifest, MdbaseApplicationRequirements, MdbaseApplicationCapabilityId as ApplicationCapabilityId, MdbaseApplicationCapabilityRequirements as ApplicationCapabilityRequirements } from "./application-contract.js";
|
|
27
|
+
export type { ApplicationProvisions, ApplicationRequirements, LegacyApplicationRequirements, LegacyApplicationCapabilityId, LegacyApplicationCapabilityRequirements, LegacyMdbaseAppManifest, ApplicationNotifications, ApplicationAuthorizationBinding, ApplicationAuthorizationProof, FileAction, FileCapability, CollectionOperation as MdbaseOperation, CollectionTypeDocument, ConnectOperationOutcome, ConnectProblem, ConnectProblemCategory, ConnectProblemCode, ConnectProblemDetailsByCode, ConnectRecoveryAction, ContractRequirement, GrantScope, JsonObject, NotificationCriterion, MdbaseDiagnostic, MdbaseOperationEnvelope, KnownConnectProblem, TypePackManifest, TypePackManifestResource, TypePackProvision, TypePackSourceResource, UnknownConnectProblem } from "@mdbase-dev/connect-protocol";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { MdbaseApplicationSession, MdbaseMemoryVerificationStore } from "./application-session.js";
|
|
2
|
+
export { MdbaseConnect } from "./mdbase-connect.js";
|
|
3
|
+
export { MdbaseConnection } from "./connection.js";
|
|
4
|
+
export { effectiveCapabilities } from "./capabilities.js";
|
|
5
|
+
export { MdbaseConnectError, isRetryableConnectError } from "./errors.js";
|
|
6
|
+
export { MdbaseFileClient } from "./files.js";
|
|
7
|
+
export { parseMdbasePushPayload, parseMdbaseNativeNotificationData, showMdbasePushNotification } from "./notifications.js";
|
|
8
|
+
export { externalStore } from "./external-store.js";
|
|
9
|
+
export { MdbaseBrowserSelection, MdbaseMemorySelection } from "./selection.js";
|
|
10
|
+
export { MDBASE_RECORD_CREATED_CONTRACT, MDBASE_TIMER_FIRED_CONTRACT, operationsForApplicationCapabilities } from "@mdbase-dev/connect-protocol";
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { ApplicationNotifications, ApplicationProvisions, CollectionOperation, EncryptedRelayOperationRequest, GrantEncryption, FileCapability, GrantScope, MdbaseOperationRequest, MutationOperationIdentifier } from "@mdbase-dev/connect-protocol";
|
|
2
|
+
import type { MdbaseApplicationRequirements as ApplicationRequirements } from "./application-contract.js";
|
|
3
|
+
import { encryptRelayRequest } from "./crypto.js";
|
|
4
|
+
export interface Application {
|
|
5
|
+
id: string;
|
|
6
|
+
family_identity: string;
|
|
7
|
+
manifest_digest: string;
|
|
8
|
+
name: string;
|
|
9
|
+
distribution?: "web" | "portable";
|
|
10
|
+
homepage?: string;
|
|
11
|
+
project_url?: string;
|
|
12
|
+
notifications?: ApplicationNotifications;
|
|
13
|
+
requirements: ApplicationRequirements;
|
|
14
|
+
provisions?: ApplicationProvisions;
|
|
15
|
+
}
|
|
16
|
+
export interface StoredAuthorization {
|
|
17
|
+
version: 1;
|
|
18
|
+
verifier: string;
|
|
19
|
+
state: string;
|
|
20
|
+
clientId: string;
|
|
21
|
+
redirectUri: string;
|
|
22
|
+
relayEncryption: "required" | "disabled";
|
|
23
|
+
collectionId?: string;
|
|
24
|
+
returnTo?: string;
|
|
25
|
+
keyHandle?: string;
|
|
26
|
+
authorizationId?: string;
|
|
27
|
+
applicationAgreementPublicKey?: string;
|
|
28
|
+
applicationSigningPublicKey?: string;
|
|
29
|
+
presentation?: "popup";
|
|
30
|
+
}
|
|
31
|
+
export type StoredAuthorizationCompletion = {
|
|
32
|
+
version: 1;
|
|
33
|
+
status: "connected";
|
|
34
|
+
collectionId: string;
|
|
35
|
+
returnTo?: string;
|
|
36
|
+
} | {
|
|
37
|
+
version: 1;
|
|
38
|
+
status: "failed";
|
|
39
|
+
code: string;
|
|
40
|
+
message: string;
|
|
41
|
+
returnTo?: string;
|
|
42
|
+
};
|
|
43
|
+
export interface StoredToken {
|
|
44
|
+
version: 1;
|
|
45
|
+
accessToken: string;
|
|
46
|
+
refreshToken?: string;
|
|
47
|
+
clientId: string;
|
|
48
|
+
collectionId: string;
|
|
49
|
+
collectionName: string;
|
|
50
|
+
operations: CollectionOperation[];
|
|
51
|
+
scope: GrantScope;
|
|
52
|
+
expiresAt: number;
|
|
53
|
+
refreshExpiresAt?: number;
|
|
54
|
+
grantId?: string;
|
|
55
|
+
encryption?: GrantEncryption;
|
|
56
|
+
fileCapability?: FileCapability;
|
|
57
|
+
applicationOrigin?: string;
|
|
58
|
+
keyHandle?: string;
|
|
59
|
+
/** Previous grant keys retained for durable pending-mutation recovery. */
|
|
60
|
+
retiredKeyHandles?: string[];
|
|
61
|
+
savedAt: number;
|
|
62
|
+
authority?: {
|
|
63
|
+
operationsUrl: string;
|
|
64
|
+
syncUrl: string;
|
|
65
|
+
filesUrl: string;
|
|
66
|
+
replicaId: string;
|
|
67
|
+
accessToken: string;
|
|
68
|
+
proofPublicKey?: string;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export interface StoredConnectionIndex {
|
|
72
|
+
version: 1;
|
|
73
|
+
collectionIds: string[];
|
|
74
|
+
}
|
|
75
|
+
export interface PendingMutation {
|
|
76
|
+
collectionId: string;
|
|
77
|
+
grantId?: string;
|
|
78
|
+
keyId?: string;
|
|
79
|
+
keyHandle?: string;
|
|
80
|
+
applicationId?: string;
|
|
81
|
+
encryption?: GrantEncryption;
|
|
82
|
+
operation: CollectionOperation;
|
|
83
|
+
mutation?: MutationOperationIdentifier;
|
|
84
|
+
inputFingerprint: string;
|
|
85
|
+
requestId: string;
|
|
86
|
+
envelope?: EncryptedRelayOperationRequest;
|
|
87
|
+
/** Exact plaintext protocol request for transports that do not use a grant envelope. */
|
|
88
|
+
request?: MdbaseOperationRequest;
|
|
89
|
+
createdAt: number;
|
|
90
|
+
}
|
|
91
|
+
export interface OperationAttempt {
|
|
92
|
+
response: Response;
|
|
93
|
+
requestId: string;
|
|
94
|
+
encryptedRequest?: Awaited<ReturnType<typeof encryptRelayRequest>>;
|
|
95
|
+
directDeliveryUncertain?: boolean;
|
|
96
|
+
pendingMutation?: boolean;
|
|
97
|
+
pendingMutationRecord?: PendingMutation;
|
|
98
|
+
resumingMutation?: boolean;
|
|
99
|
+
}
|
|
100
|
+
export { DEFAULT_OPERATIONS } from "./application-contract.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DEFAULT_OPERATIONS } from "./application-contract.js";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { FileTransferSession } from "@mdbase-dev/connect-protocol";
|
|
2
|
+
import { type GrantKeyStore } from "./crypto.js";
|
|
3
|
+
import type { StoredToken } from "./internal-types.js";
|
|
4
|
+
interface LocalFileTransportOptions {
|
|
5
|
+
keyStore: GrantKeyStore;
|
|
6
|
+
serverUrl: string;
|
|
7
|
+
loopbackUrl: string;
|
|
8
|
+
currentToken?(): StoredToken | null;
|
|
9
|
+
authorizedToken(signal?: AbortSignal): Promise<StoredToken | null>;
|
|
10
|
+
refreshAuthorization(signal?: AbortSignal): Promise<StoredToken>;
|
|
11
|
+
shouldAttemptDirect(token: StoredToken): Promise<boolean>;
|
|
12
|
+
onDirectAvailable(): void;
|
|
13
|
+
onDirectUnavailable(): void;
|
|
14
|
+
onRelayAvailable(): void;
|
|
15
|
+
acquireGrantKeyLease?(collectionId: string, keyHandle: string, signal?: AbortSignal): Promise<() => void>;
|
|
16
|
+
}
|
|
17
|
+
/** Keeps grant-bound file crypto and loopback framing out of the operation transport. */
|
|
18
|
+
export declare class LocalFileTransport {
|
|
19
|
+
private readonly options;
|
|
20
|
+
constructor(options: LocalFileTransportOptions);
|
|
21
|
+
control<Result>(token: StoredToken, method: "GET" | "POST" | "DELETE", path: string, input: unknown, signal?: AbortSignal): Promise<Result>;
|
|
22
|
+
private controlAttempt;
|
|
23
|
+
private decryptControlResponse;
|
|
24
|
+
uploadChunk(session: FileTransferSession, chunkIndex: number, bytes: Uint8Array, signal?: AbortSignal, authorizedToken?: StoredToken): Promise<void>;
|
|
25
|
+
private uploadChunkWithLease;
|
|
26
|
+
downloadChunk(session: FileTransferSession, chunkIndex: number, signal?: AbortSignal, authorizedToken?: StoredToken): Promise<Uint8Array>;
|
|
27
|
+
private downloadChunkWithLease;
|
|
28
|
+
private decryptDownloadResponse;
|
|
29
|
+
private encryptControl;
|
|
30
|
+
private sendRelayControl;
|
|
31
|
+
private sendRelayUpload;
|
|
32
|
+
private sendRelayDownload;
|
|
33
|
+
private localFileToken;
|
|
34
|
+
private grantKeyLeases;
|
|
35
|
+
private retainEntryToken;
|
|
36
|
+
}
|
|
37
|
+
export {};
|