@arbidocs/client 0.4.1 → 0.4.3
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 +132 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -2
- package/dist/index.d.ts +50 -2
- package/dist/index.js +132 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -11765,6 +11765,13 @@ interface components {
|
|
|
11765
11765
|
email_notifications?: components['schemas']['EmailNotificationSettings'];
|
|
11766
11766
|
/** Premium Model */
|
|
11767
11767
|
premium_model?: string | null;
|
|
11768
|
+
/**
|
|
11769
|
+
* Retired Premium Model
|
|
11770
|
+
* @description One-shot notice: set only on the response that cleared a stored premium_model which is no longer an available Premium model. Never persisted; the choice is already cleared.
|
|
11771
|
+
*/
|
|
11772
|
+
retired_premium_model?: string | null;
|
|
11773
|
+
/** Retired Premium Model Suggestion */
|
|
11774
|
+
retired_premium_model_suggestion?: string | null;
|
|
11768
11775
|
/** Picture */
|
|
11769
11776
|
picture?: string | null;
|
|
11770
11777
|
/** Extra Discount */
|
|
@@ -17192,6 +17199,13 @@ interface AutoReloginMiddlewareConfig {
|
|
|
17192
17199
|
reloginHandler: ReloginHandler;
|
|
17193
17200
|
/** URL substrings that should never trigger re-login (e.g. the login endpoint itself) */
|
|
17194
17201
|
reloginExcludePatterns?: string[];
|
|
17202
|
+
/**
|
|
17203
|
+
* Re-open the selected workspace on the server session without a new login. Resolves true when
|
|
17204
|
+
* done. Used on 400 "No active workspace" (the server lost the open-workspace state while the
|
|
17205
|
+
* token is still valid); when it is absent or returns false, a full re-login (which also
|
|
17206
|
+
* re-opens the workspace) is tried instead.
|
|
17207
|
+
*/
|
|
17208
|
+
reopenWorkspaceHandler?: () => Promise<boolean>;
|
|
17195
17209
|
onRetryCloneFailed?: () => void;
|
|
17196
17210
|
/** Called when re-login was attempted but failed (returned null). Use to clear stale auth state. */
|
|
17197
17211
|
onReloginFailed?: () => void;
|
|
@@ -17808,6 +17822,13 @@ interface ArbiClientOptions {
|
|
|
17808
17822
|
userExtId?: string;
|
|
17809
17823
|
serverSessionKey: Uint8Array;
|
|
17810
17824
|
}) => void;
|
|
17825
|
+
/**
|
|
17826
|
+
* Called when the session cannot be recovered: a request failed with 401 (or 400 "No active
|
|
17827
|
+
* workspace") and neither a workspace re-open nor a silent re-login worked because the server
|
|
17828
|
+
* REFUSED it (not a network failure, which leaves the session alone). The host shows "your
|
|
17829
|
+
* session expired, sign in again". Not called before anyone has logged in.
|
|
17830
|
+
*/
|
|
17831
|
+
onSessionExpired?: () => void;
|
|
17811
17832
|
/**
|
|
17812
17833
|
* Optional session storage provider for the relogin handler.
|
|
17813
17834
|
*
|
|
@@ -17837,8 +17858,10 @@ interface ArbiClient {
|
|
|
17837
17858
|
loginWithKey(params: LoginWithKeyParams): Promise<LoginResult>;
|
|
17838
17859
|
logout(): Promise<void>;
|
|
17839
17860
|
changePassword(params: ChangePasswordParams): Promise<ChangePasswordResult>;
|
|
17840
|
-
/** Instant re-login using stored private key */
|
|
17861
|
+
/** Instant re-login using stored private key (re-opens the selected workspace too) */
|
|
17841
17862
|
relogin(): Promise<string | null>;
|
|
17863
|
+
/** Re-open the selected workspace on the server session, without a new login */
|
|
17864
|
+
reopenWorkspace(): Promise<boolean>;
|
|
17842
17865
|
};
|
|
17843
17866
|
/** Crypto utilities */
|
|
17844
17867
|
crypto: {
|
|
@@ -17960,4 +17983,29 @@ declare function isMessageType<T extends WebSocketServerMessage>(msg: WebSocketS
|
|
|
17960
17983
|
*/
|
|
17961
17984
|
declare function createReloginHandler(deps: ReloginDeps): () => Promise<string | null>;
|
|
17962
17985
|
|
|
17963
|
-
|
|
17986
|
+
/**
|
|
17987
|
+
* Workspace re-open (no re-login)
|
|
17988
|
+
*
|
|
17989
|
+
* The server keeps "which workspace is open, and its key sealed for this session" on the session.
|
|
17990
|
+
* When that state is gone while the access token is still valid (a server restart, a rotated
|
|
17991
|
+
* session, an expired workspace session), requests fail with 400 "No active workspace - call
|
|
17992
|
+
* /open first". Re-opening needs no new login: unwrap the workspace key with the stored signing
|
|
17993
|
+
* key, seal it for the stored server session key, POST /open.
|
|
17994
|
+
*/
|
|
17995
|
+
|
|
17996
|
+
interface ReopenDeps {
|
|
17997
|
+
crypto: Pick<CryptoProvider, 'ensureReady' | 'deriveEncryptionKeypair' | 'sealedBoxDecrypt' | 'sealKeyForSession'>;
|
|
17998
|
+
sessionStorage: SessionStorageProvider;
|
|
17999
|
+
authState: Pick<AuthStateProvider, 'getSelectedWorkspaceId'>;
|
|
18000
|
+
getAccessToken(): string | null;
|
|
18001
|
+
workspaceKeyRefreshProvider: WorkspaceKeyRefreshProvider;
|
|
18002
|
+
workspaceOpenProvider: WorkspaceOpenProvider;
|
|
18003
|
+
}
|
|
18004
|
+
/**
|
|
18005
|
+
* Returns `reopenWorkspace()`: resolves true when the selected workspace is open again on the
|
|
18006
|
+
* server session, false when it cannot be (nothing selected, no stored keys, server refused).
|
|
18007
|
+
* Concurrent calls share one in-flight attempt.
|
|
18008
|
+
*/
|
|
18009
|
+
declare function createWorkspaceReopener(deps: ReopenDeps): () => Promise<boolean>;
|
|
18010
|
+
|
|
18011
|
+
export { type $defs, API_PREFIX, type ArbiClient, type ArbiClientOptions, type AuthStateProvider, type AutoReloginMiddlewareConfig, type BearerAuthMiddlewareConfig, type ChangePasswordParams, type ChangePasswordRequest, type ChangePasswordResult, type CryptoProvider, type KeyPair, type LoginCredentials, type LoginParams, type LoginProvider, type LoginRequest, type LoginResult, type LoginWithKeyParams, type OnReloginSuccess, type PasswordChangeCredentials, type RegisterParams, type RegisterRequest, type RegisterResult, type RegistrationCredentials, type ReloginDeps, type ReloginHandler, type ReopenDeps, type SessionData, type SessionKeys, type SessionManager, type SessionState, type SessionStorageProvider, type SsoTokenProvider, type TokenProvider, type UserKeypairs, type WebSocketClientMessage, type WebSocketServerMessage, type WorkspaceKeyRefreshProvider, type WorkspaceOpenProvider, type WsAuthMessage, type WsAuthResultMessage, type WsBatchCompleteMessage, type WsConnectionClosedMessage, type WsErrorMessage, type WsNotificationResponse, type WsPresenceUpdateMessage, type WsResponseCompleteMessage, type WsTaskUpdateMessage, base64Decode, base64Encode, base64ToBytes, buildWebSocketUrl, bytesToBase64, clearAllData, clearSession, type components, computeSharedSecret, createArbiClient, createAuthMessage, createAutoReloginMiddleware, createBearerAuthMiddleware, createContentHash, createReloginHandler, createSessionManager, createWorkspaceReopener, decryptFile, decryptMessage, decryptMessageWithSharedSecret, deriveEncryptionKeypairFromSigning, derivePublicKey, encryptFile, encryptMessage, encryptMessageWithSharedSecret, generateKeyPairs, generateLoginCredentials, generateLoginCredentialsFromKey, generatePasswordChangeCredentials, generateRandomSigningKeypair, generateRecoveryPasswordChangeCredentials, generateRegistrationCredentials, generateUserKeypairs, getSession, getUserEncryptionKeypair, hasSession, initSodium, initializeDatabase, isMessageType, type operations, parseServerMessage, type paths, prewarmKeyPairs, saveSession, sealKeyForSession, sealedBoxDecrypt, sealedBoxEncrypt, signMessage, updateSigningPrivateKey, type webhooks };
|
package/dist/index.d.ts
CHANGED
|
@@ -11765,6 +11765,13 @@ interface components {
|
|
|
11765
11765
|
email_notifications?: components['schemas']['EmailNotificationSettings'];
|
|
11766
11766
|
/** Premium Model */
|
|
11767
11767
|
premium_model?: string | null;
|
|
11768
|
+
/**
|
|
11769
|
+
* Retired Premium Model
|
|
11770
|
+
* @description One-shot notice: set only on the response that cleared a stored premium_model which is no longer an available Premium model. Never persisted; the choice is already cleared.
|
|
11771
|
+
*/
|
|
11772
|
+
retired_premium_model?: string | null;
|
|
11773
|
+
/** Retired Premium Model Suggestion */
|
|
11774
|
+
retired_premium_model_suggestion?: string | null;
|
|
11768
11775
|
/** Picture */
|
|
11769
11776
|
picture?: string | null;
|
|
11770
11777
|
/** Extra Discount */
|
|
@@ -17192,6 +17199,13 @@ interface AutoReloginMiddlewareConfig {
|
|
|
17192
17199
|
reloginHandler: ReloginHandler;
|
|
17193
17200
|
/** URL substrings that should never trigger re-login (e.g. the login endpoint itself) */
|
|
17194
17201
|
reloginExcludePatterns?: string[];
|
|
17202
|
+
/**
|
|
17203
|
+
* Re-open the selected workspace on the server session without a new login. Resolves true when
|
|
17204
|
+
* done. Used on 400 "No active workspace" (the server lost the open-workspace state while the
|
|
17205
|
+
* token is still valid); when it is absent or returns false, a full re-login (which also
|
|
17206
|
+
* re-opens the workspace) is tried instead.
|
|
17207
|
+
*/
|
|
17208
|
+
reopenWorkspaceHandler?: () => Promise<boolean>;
|
|
17195
17209
|
onRetryCloneFailed?: () => void;
|
|
17196
17210
|
/** Called when re-login was attempted but failed (returned null). Use to clear stale auth state. */
|
|
17197
17211
|
onReloginFailed?: () => void;
|
|
@@ -17808,6 +17822,13 @@ interface ArbiClientOptions {
|
|
|
17808
17822
|
userExtId?: string;
|
|
17809
17823
|
serverSessionKey: Uint8Array;
|
|
17810
17824
|
}) => void;
|
|
17825
|
+
/**
|
|
17826
|
+
* Called when the session cannot be recovered: a request failed with 401 (or 400 "No active
|
|
17827
|
+
* workspace") and neither a workspace re-open nor a silent re-login worked because the server
|
|
17828
|
+
* REFUSED it (not a network failure, which leaves the session alone). The host shows "your
|
|
17829
|
+
* session expired, sign in again". Not called before anyone has logged in.
|
|
17830
|
+
*/
|
|
17831
|
+
onSessionExpired?: () => void;
|
|
17811
17832
|
/**
|
|
17812
17833
|
* Optional session storage provider for the relogin handler.
|
|
17813
17834
|
*
|
|
@@ -17837,8 +17858,10 @@ interface ArbiClient {
|
|
|
17837
17858
|
loginWithKey(params: LoginWithKeyParams): Promise<LoginResult>;
|
|
17838
17859
|
logout(): Promise<void>;
|
|
17839
17860
|
changePassword(params: ChangePasswordParams): Promise<ChangePasswordResult>;
|
|
17840
|
-
/** Instant re-login using stored private key */
|
|
17861
|
+
/** Instant re-login using stored private key (re-opens the selected workspace too) */
|
|
17841
17862
|
relogin(): Promise<string | null>;
|
|
17863
|
+
/** Re-open the selected workspace on the server session, without a new login */
|
|
17864
|
+
reopenWorkspace(): Promise<boolean>;
|
|
17842
17865
|
};
|
|
17843
17866
|
/** Crypto utilities */
|
|
17844
17867
|
crypto: {
|
|
@@ -17960,4 +17983,29 @@ declare function isMessageType<T extends WebSocketServerMessage>(msg: WebSocketS
|
|
|
17960
17983
|
*/
|
|
17961
17984
|
declare function createReloginHandler(deps: ReloginDeps): () => Promise<string | null>;
|
|
17962
17985
|
|
|
17963
|
-
|
|
17986
|
+
/**
|
|
17987
|
+
* Workspace re-open (no re-login)
|
|
17988
|
+
*
|
|
17989
|
+
* The server keeps "which workspace is open, and its key sealed for this session" on the session.
|
|
17990
|
+
* When that state is gone while the access token is still valid (a server restart, a rotated
|
|
17991
|
+
* session, an expired workspace session), requests fail with 400 "No active workspace - call
|
|
17992
|
+
* /open first". Re-opening needs no new login: unwrap the workspace key with the stored signing
|
|
17993
|
+
* key, seal it for the stored server session key, POST /open.
|
|
17994
|
+
*/
|
|
17995
|
+
|
|
17996
|
+
interface ReopenDeps {
|
|
17997
|
+
crypto: Pick<CryptoProvider, 'ensureReady' | 'deriveEncryptionKeypair' | 'sealedBoxDecrypt' | 'sealKeyForSession'>;
|
|
17998
|
+
sessionStorage: SessionStorageProvider;
|
|
17999
|
+
authState: Pick<AuthStateProvider, 'getSelectedWorkspaceId'>;
|
|
18000
|
+
getAccessToken(): string | null;
|
|
18001
|
+
workspaceKeyRefreshProvider: WorkspaceKeyRefreshProvider;
|
|
18002
|
+
workspaceOpenProvider: WorkspaceOpenProvider;
|
|
18003
|
+
}
|
|
18004
|
+
/**
|
|
18005
|
+
* Returns `reopenWorkspace()`: resolves true when the selected workspace is open again on the
|
|
18006
|
+
* server session, false when it cannot be (nothing selected, no stored keys, server refused).
|
|
18007
|
+
* Concurrent calls share one in-flight attempt.
|
|
18008
|
+
*/
|
|
18009
|
+
declare function createWorkspaceReopener(deps: ReopenDeps): () => Promise<boolean>;
|
|
18010
|
+
|
|
18011
|
+
export { type $defs, API_PREFIX, type ArbiClient, type ArbiClientOptions, type AuthStateProvider, type AutoReloginMiddlewareConfig, type BearerAuthMiddlewareConfig, type ChangePasswordParams, type ChangePasswordRequest, type ChangePasswordResult, type CryptoProvider, type KeyPair, type LoginCredentials, type LoginParams, type LoginProvider, type LoginRequest, type LoginResult, type LoginWithKeyParams, type OnReloginSuccess, type PasswordChangeCredentials, type RegisterParams, type RegisterRequest, type RegisterResult, type RegistrationCredentials, type ReloginDeps, type ReloginHandler, type ReopenDeps, type SessionData, type SessionKeys, type SessionManager, type SessionState, type SessionStorageProvider, type SsoTokenProvider, type TokenProvider, type UserKeypairs, type WebSocketClientMessage, type WebSocketServerMessage, type WorkspaceKeyRefreshProvider, type WorkspaceOpenProvider, type WsAuthMessage, type WsAuthResultMessage, type WsBatchCompleteMessage, type WsConnectionClosedMessage, type WsErrorMessage, type WsNotificationResponse, type WsPresenceUpdateMessage, type WsResponseCompleteMessage, type WsTaskUpdateMessage, base64Decode, base64Encode, base64ToBytes, buildWebSocketUrl, bytesToBase64, clearAllData, clearSession, type components, computeSharedSecret, createArbiClient, createAuthMessage, createAutoReloginMiddleware, createBearerAuthMiddleware, createContentHash, createReloginHandler, createSessionManager, createWorkspaceReopener, decryptFile, decryptMessage, decryptMessageWithSharedSecret, deriveEncryptionKeypairFromSigning, derivePublicKey, encryptFile, encryptMessage, encryptMessageWithSharedSecret, generateKeyPairs, generateLoginCredentials, generateLoginCredentialsFromKey, generatePasswordChangeCredentials, generateRandomSigningKeypair, generateRecoveryPasswordChangeCredentials, generateRegistrationCredentials, generateUserKeypairs, getSession, getUserEncryptionKeypair, hasSession, initSodium, initializeDatabase, isMessageType, type operations, parseServerMessage, type paths, prewarmKeyPairs, saveSession, sealKeyForSession, sealedBoxDecrypt, sealedBoxEncrypt, signMessage, updateSigningPrivateKey, type webhooks };
|
package/dist/index.js
CHANGED
|
@@ -385,6 +385,21 @@ function createBearerAuthMiddleware(config) {
|
|
|
385
385
|
}
|
|
386
386
|
|
|
387
387
|
// src/middleware/auto-relogin.ts
|
|
388
|
+
var NO_ACTIVE_WORKSPACE = /no active workspace/i;
|
|
389
|
+
async function isNoActiveWorkspace(response) {
|
|
390
|
+
try {
|
|
391
|
+
return NO_ACTIVE_WORKSPACE.test(await response.clone().text());
|
|
392
|
+
} catch {
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
function safeClone(request) {
|
|
397
|
+
try {
|
|
398
|
+
return request.clone();
|
|
399
|
+
} catch {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
388
403
|
function createAutoReloginMiddleware(config) {
|
|
389
404
|
const cloneCache = /* @__PURE__ */ new WeakMap();
|
|
390
405
|
return {
|
|
@@ -395,6 +410,25 @@ function createAutoReloginMiddleware(config) {
|
|
|
395
410
|
}
|
|
396
411
|
},
|
|
397
412
|
async onResponse({ response, request }) {
|
|
413
|
+
if (response.status === 400 && await isNoActiveWorkspace(response)) {
|
|
414
|
+
let token = null;
|
|
415
|
+
let recovered = await config.reopenWorkspaceHandler?.() ?? false;
|
|
416
|
+
if (!recovered) {
|
|
417
|
+
token = await config.reloginHandler();
|
|
418
|
+
recovered = token !== null;
|
|
419
|
+
}
|
|
420
|
+
if (!recovered) {
|
|
421
|
+
config.onReloginFailed?.();
|
|
422
|
+
return response;
|
|
423
|
+
}
|
|
424
|
+
const retry = cloneCache.get(request) ?? safeClone(request);
|
|
425
|
+
if (retry) {
|
|
426
|
+
if (token) retry.headers.set("Authorization", `Bearer ${token}`);
|
|
427
|
+
return fetch(retry);
|
|
428
|
+
}
|
|
429
|
+
config.onRetryCloneFailed?.();
|
|
430
|
+
return response;
|
|
431
|
+
}
|
|
398
432
|
if (response.status === 400) {
|
|
399
433
|
const isSafeMethod = ["GET", "HEAD", "DELETE"].includes(request.method);
|
|
400
434
|
if (isSafeMethod) {
|
|
@@ -555,6 +589,47 @@ function createReloginHandler(deps) {
|
|
|
555
589
|
};
|
|
556
590
|
}
|
|
557
591
|
|
|
592
|
+
// src/relogin/reopen.ts
|
|
593
|
+
function createWorkspaceReopener(deps) {
|
|
594
|
+
let inFlight = null;
|
|
595
|
+
return function reopenWorkspace() {
|
|
596
|
+
if (inFlight) return inFlight;
|
|
597
|
+
inFlight = (async () => {
|
|
598
|
+
try {
|
|
599
|
+
const workspaceId = deps.authState.getSelectedWorkspaceId();
|
|
600
|
+
const accessToken = deps.getAccessToken();
|
|
601
|
+
if (!workspaceId || !accessToken) return false;
|
|
602
|
+
const session = await deps.sessionStorage.getSession();
|
|
603
|
+
if (!session?.signingPrivateKey || !session.serverSessionKey) return false;
|
|
604
|
+
await deps.crypto.ensureReady();
|
|
605
|
+
const wrappedKey = await deps.workspaceKeyRefreshProvider.getWrappedKey(
|
|
606
|
+
accessToken,
|
|
607
|
+
workspaceId
|
|
608
|
+
);
|
|
609
|
+
if (!wrappedKey) return false;
|
|
610
|
+
const encryptionKeyPair = deps.crypto.deriveEncryptionKeypair({
|
|
611
|
+
publicKey: session.signingPrivateKey.slice(32, 64),
|
|
612
|
+
secretKey: session.signingPrivateKey
|
|
613
|
+
});
|
|
614
|
+
const workspaceKey = deps.crypto.sealedBoxDecrypt(wrappedKey, encryptionKeyPair.secretKey);
|
|
615
|
+
const sealed = await deps.crypto.sealKeyForSession(workspaceKey, session.serverSessionKey);
|
|
616
|
+
const opened = await deps.workspaceOpenProvider.openWorkspace(
|
|
617
|
+
accessToken,
|
|
618
|
+
workspaceId,
|
|
619
|
+
sealed
|
|
620
|
+
);
|
|
621
|
+
return opened === true;
|
|
622
|
+
} catch (error) {
|
|
623
|
+
console.error("[API] Failed to re-open workspace:", error);
|
|
624
|
+
return false;
|
|
625
|
+
} finally {
|
|
626
|
+
inFlight = null;
|
|
627
|
+
}
|
|
628
|
+
})();
|
|
629
|
+
return inFlight;
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
|
|
558
633
|
// src/storage/indexed-db.ts
|
|
559
634
|
var DB_NAME = "arbi-crypto";
|
|
560
635
|
var DB_VERSION = 2;
|
|
@@ -1002,6 +1077,7 @@ function createArbiClient(options) {
|
|
|
1002
1077
|
credentials = "include",
|
|
1003
1078
|
ssoTokenProvider = null,
|
|
1004
1079
|
onReloginSuccess,
|
|
1080
|
+
onSessionExpired,
|
|
1005
1081
|
sessionStorage: sessionStorageOverride,
|
|
1006
1082
|
userEmail
|
|
1007
1083
|
} = options;
|
|
@@ -1022,6 +1098,7 @@ function createArbiClient(options) {
|
|
|
1022
1098
|
sealKeyForSession,
|
|
1023
1099
|
fromBase64: base64ToBytes
|
|
1024
1100
|
};
|
|
1101
|
+
let reloginUnreachable = false;
|
|
1025
1102
|
const loginProvider = {
|
|
1026
1103
|
async login(payload) {
|
|
1027
1104
|
const rawFetch = createFetchClient({
|
|
@@ -1029,14 +1106,21 @@ function createArbiClient(options) {
|
|
|
1029
1106
|
credentials,
|
|
1030
1107
|
fetch: retryFetch
|
|
1031
1108
|
});
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1109
|
+
let response;
|
|
1110
|
+
try {
|
|
1111
|
+
response = await rawFetch.POST("/v1/user/login", {
|
|
1112
|
+
body: {
|
|
1113
|
+
email: payload.email,
|
|
1114
|
+
signature: payload.signature,
|
|
1115
|
+
timestamp: payload.timestamp,
|
|
1116
|
+
sso_token: payload.ssoToken
|
|
1117
|
+
}
|
|
1118
|
+
});
|
|
1119
|
+
} catch (error) {
|
|
1120
|
+
console.warn("[API] Login call unreachable:", error);
|
|
1121
|
+
reloginUnreachable = true;
|
|
1122
|
+
return null;
|
|
1123
|
+
}
|
|
1040
1124
|
if (response.error || !response.data) {
|
|
1041
1125
|
console.warn("[API] Login call failed:", response.error);
|
|
1042
1126
|
return null;
|
|
@@ -1067,15 +1151,46 @@ function createArbiClient(options) {
|
|
|
1067
1151
|
return workspace?.wrapped_key ?? null;
|
|
1068
1152
|
}
|
|
1069
1153
|
};
|
|
1070
|
-
const
|
|
1154
|
+
const workspaceOpenProvider = {
|
|
1155
|
+
async openWorkspace(accessToken, workspaceId, encryptedWorkspaceKey) {
|
|
1156
|
+
try {
|
|
1157
|
+
const response = await retryFetch(`${baseUrl}${API_PREFIX}/workspace/${workspaceId}/open`, {
|
|
1158
|
+
method: "POST",
|
|
1159
|
+
headers: {
|
|
1160
|
+
Authorization: `Bearer ${accessToken}`,
|
|
1161
|
+
"Content-Type": "application/json"
|
|
1162
|
+
},
|
|
1163
|
+
body: JSON.stringify({ workspace_key: encryptedWorkspaceKey }),
|
|
1164
|
+
credentials
|
|
1165
|
+
});
|
|
1166
|
+
return response.ok ? true : null;
|
|
1167
|
+
} catch {
|
|
1168
|
+
return null;
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
};
|
|
1172
|
+
const rawReloginHandler = createReloginHandler({
|
|
1071
1173
|
crypto: cryptoProvider,
|
|
1072
1174
|
sessionStorage,
|
|
1073
1175
|
authState,
|
|
1074
1176
|
ssoTokenProvider,
|
|
1075
1177
|
loginProvider,
|
|
1076
1178
|
workspaceKeyRefreshProvider,
|
|
1179
|
+
workspaceOpenProvider,
|
|
1077
1180
|
onReloginSuccess
|
|
1078
1181
|
});
|
|
1182
|
+
const reloginHandler = () => {
|
|
1183
|
+
reloginUnreachable = false;
|
|
1184
|
+
return rawReloginHandler();
|
|
1185
|
+
};
|
|
1186
|
+
const reopenWorkspace = createWorkspaceReopener({
|
|
1187
|
+
crypto: cryptoProvider,
|
|
1188
|
+
sessionStorage,
|
|
1189
|
+
authState,
|
|
1190
|
+
getAccessToken: () => session.getState().accessToken,
|
|
1191
|
+
workspaceKeyRefreshProvider,
|
|
1192
|
+
workspaceOpenProvider
|
|
1193
|
+
});
|
|
1079
1194
|
const fetchClient = createFetchClient({
|
|
1080
1195
|
baseUrl,
|
|
1081
1196
|
credentials,
|
|
@@ -1085,7 +1200,11 @@ function createArbiClient(options) {
|
|
|
1085
1200
|
fetchClient.use(
|
|
1086
1201
|
createAutoReloginMiddleware({
|
|
1087
1202
|
reloginHandler,
|
|
1088
|
-
reloginExcludePatterns
|
|
1203
|
+
reloginExcludePatterns,
|
|
1204
|
+
reopenWorkspaceHandler: reopenWorkspace,
|
|
1205
|
+
onReloginFailed: () => {
|
|
1206
|
+
if (!reloginUnreachable && session.getState().userEmail) onSessionExpired?.();
|
|
1207
|
+
}
|
|
1089
1208
|
})
|
|
1090
1209
|
);
|
|
1091
1210
|
const authDeps = {
|
|
@@ -1102,7 +1221,8 @@ function createArbiClient(options) {
|
|
|
1102
1221
|
loginWithKey: (params) => loginWithKey(params, authDeps),
|
|
1103
1222
|
logout: () => logout(session),
|
|
1104
1223
|
changePassword: (params) => changePassword(params, authDeps),
|
|
1105
|
-
relogin: reloginHandler
|
|
1224
|
+
relogin: reloginHandler,
|
|
1225
|
+
reopenWorkspace
|
|
1106
1226
|
},
|
|
1107
1227
|
crypto: {
|
|
1108
1228
|
initSodium,
|
|
@@ -1156,6 +1276,6 @@ function isMessageType(msg, type) {
|
|
|
1156
1276
|
return msg.type === type;
|
|
1157
1277
|
}
|
|
1158
1278
|
|
|
1159
|
-
export { API_PREFIX, base64Decode, base64Encode, base64ToBytes, buildWebSocketUrl, bytesToBase64, clearAllData, clearSession, computeSharedSecret, createArbiClient, createAuthMessage, createAutoReloginMiddleware, createBearerAuthMiddleware, createContentHash, createReloginHandler, createSessionManager, decryptFile, decryptMessage, decryptMessageWithSharedSecret, deriveEncryptionKeypairFromSigning, derivePublicKey, encryptFile, encryptMessage, encryptMessageWithSharedSecret, generateKeyPairs, generateLoginCredentials, generateLoginCredentialsFromKey, generatePasswordChangeCredentials, generateRandomSigningKeypair, generateRecoveryPasswordChangeCredentials, generateRegistrationCredentials, generateUserKeypairs, getSession, getUserEncryptionKeypair, hasSession, initSodium, initializeDatabase, isMessageType, parseServerMessage, prewarmKeyPairs, saveSession, sealKeyForSession, sealedBoxDecrypt, sealedBoxEncrypt, signMessage, updateSigningPrivateKey };
|
|
1279
|
+
export { API_PREFIX, base64Decode, base64Encode, base64ToBytes, buildWebSocketUrl, bytesToBase64, clearAllData, clearSession, computeSharedSecret, createArbiClient, createAuthMessage, createAutoReloginMiddleware, createBearerAuthMiddleware, createContentHash, createReloginHandler, createSessionManager, createWorkspaceReopener, decryptFile, decryptMessage, decryptMessageWithSharedSecret, deriveEncryptionKeypairFromSigning, derivePublicKey, encryptFile, encryptMessage, encryptMessageWithSharedSecret, generateKeyPairs, generateLoginCredentials, generateLoginCredentialsFromKey, generatePasswordChangeCredentials, generateRandomSigningKeypair, generateRecoveryPasswordChangeCredentials, generateRegistrationCredentials, generateUserKeypairs, getSession, getUserEncryptionKeypair, hasSession, initSodium, initializeDatabase, isMessageType, parseServerMessage, prewarmKeyPairs, saveSession, sealKeyForSession, sealedBoxDecrypt, sealedBoxEncrypt, signMessage, updateSigningPrivateKey };
|
|
1160
1280
|
//# sourceMappingURL=index.js.map
|
|
1161
1281
|
//# sourceMappingURL=index.js.map
|