mindcache 3.4.4 → 3.5.0
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/{CloudAdapter-DOvDQswy.d.mts → CloudAdapter-CM7nyJaG.d.mts} +16 -2
- package/dist/{CloudAdapter-DOvDQswy.d.ts → CloudAdapter-CM7nyJaG.d.ts} +16 -2
- package/dist/cloud/index.d.mts +2 -2
- package/dist/cloud/index.d.ts +2 -2
- package/dist/cloud/index.js.map +1 -1
- package/dist/cloud/index.mjs.map +1 -1
- package/dist/index.d.mts +125 -3
- package/dist/index.d.ts +125 -3
- package/dist/index.js +321 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +320 -1
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js.map +1 -1
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,130 @@
|
|
|
1
|
-
import { e as MindCacheOptions, M as MindCache } from './CloudAdapter-
|
|
2
|
-
export { A as AccessLevel, a as CloudAdapter, c as CloudAdapterEvents, C as CloudConfig, b as ConnectionState, h as ContextRules, n as DEFAULT_KEY_ATTRIBUTES, G as GlobalListener, H as HistoryEntry, k as HistoryOptions, K as KeyAttributes, j as KeyEntry, f as KeyType, L as Listener, l as MindCacheCloudOptions, m as MindCacheIndexedDBOptions, i as STM, j as STMEntry, g as SystemTag, o as SystemTagHelpers } from './CloudAdapter-
|
|
1
|
+
import { e as MindCacheOptions, M as MindCache } from './CloudAdapter-CM7nyJaG.mjs';
|
|
2
|
+
export { A as AccessLevel, a as CloudAdapter, c as CloudAdapterEvents, C as CloudConfig, b as ConnectionState, h as ContextRules, n as DEFAULT_KEY_ATTRIBUTES, G as GlobalListener, H as HistoryEntry, k as HistoryOptions, K as KeyAttributes, j as KeyEntry, f as KeyType, L as Listener, l as MindCacheCloudOptions, m as MindCacheIndexedDBOptions, i as STM, j as STMEntry, g as SystemTag, o as SystemTagHelpers } from './CloudAdapter-CM7nyJaG.mjs';
|
|
3
3
|
export { IndexedDBAdapter, IndexedDBConfig } from './server.mjs';
|
|
4
4
|
import 'yjs';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* MindCache OAuth Client
|
|
8
|
+
*
|
|
9
|
+
* Browser-compatible OAuth 2.0 client for "Sign in with MindCache"
|
|
10
|
+
* Supports PKCE for secure authorization
|
|
11
|
+
*/
|
|
12
|
+
interface OAuthConfig {
|
|
13
|
+
/** Client ID from developer portal */
|
|
14
|
+
clientId: string;
|
|
15
|
+
/** Redirect URI (defaults to current URL) */
|
|
16
|
+
redirectUri?: string;
|
|
17
|
+
/** Scopes to request (default: ['read', 'write']) */
|
|
18
|
+
scopes?: string[];
|
|
19
|
+
/** MindCache authorize URL (default: production) */
|
|
20
|
+
authUrl?: string;
|
|
21
|
+
/** MindCache token URL (default: production) */
|
|
22
|
+
tokenUrl?: string;
|
|
23
|
+
/** Use PKCE for security (default: true) */
|
|
24
|
+
usePKCE?: boolean;
|
|
25
|
+
/** Storage key prefix (default: 'mindcache_oauth') */
|
|
26
|
+
storagePrefix?: string;
|
|
27
|
+
}
|
|
28
|
+
interface OAuthTokens {
|
|
29
|
+
accessToken: string;
|
|
30
|
+
refreshToken?: string;
|
|
31
|
+
expiresAt: number;
|
|
32
|
+
scopes: string[];
|
|
33
|
+
instanceId?: string;
|
|
34
|
+
}
|
|
35
|
+
interface MindCacheUser {
|
|
36
|
+
id: string;
|
|
37
|
+
email?: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
instanceId?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* OAuth client for browser applications
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const oauth = new OAuthClient({ clientId: 'mc_app_abc123' });
|
|
47
|
+
*
|
|
48
|
+
* // Start OAuth flow
|
|
49
|
+
* await oauth.authorize();
|
|
50
|
+
*
|
|
51
|
+
* // Handle callback (on redirect page)
|
|
52
|
+
* const tokens = await oauth.handleCallback();
|
|
53
|
+
*
|
|
54
|
+
* // Get access token for API calls
|
|
55
|
+
* const token = await oauth.getAccessToken();
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
declare class OAuthClient {
|
|
59
|
+
private config;
|
|
60
|
+
private tokens;
|
|
61
|
+
private refreshPromise;
|
|
62
|
+
constructor(config: OAuthConfig);
|
|
63
|
+
/**
|
|
64
|
+
* Check if user is authenticated
|
|
65
|
+
*/
|
|
66
|
+
isAuthenticated(): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Get stored tokens (if any)
|
|
69
|
+
*/
|
|
70
|
+
getTokens(): OAuthTokens | null;
|
|
71
|
+
/**
|
|
72
|
+
* Get instance ID for this user+app
|
|
73
|
+
*/
|
|
74
|
+
getInstanceId(): string | null;
|
|
75
|
+
/**
|
|
76
|
+
* Start OAuth authorization flow
|
|
77
|
+
* Redirects to MindCache authorization page
|
|
78
|
+
*/
|
|
79
|
+
authorize(options?: {
|
|
80
|
+
popup?: boolean;
|
|
81
|
+
state?: string;
|
|
82
|
+
}): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Handle OAuth callback
|
|
85
|
+
* Call this on your redirect URI page
|
|
86
|
+
*
|
|
87
|
+
* @returns Tokens if successful
|
|
88
|
+
*/
|
|
89
|
+
handleCallback(): Promise<OAuthTokens>;
|
|
90
|
+
/**
|
|
91
|
+
* Get a valid access token
|
|
92
|
+
* Automatically refreshes if needed
|
|
93
|
+
*/
|
|
94
|
+
getAccessToken(): Promise<string>;
|
|
95
|
+
/**
|
|
96
|
+
* Refresh access token
|
|
97
|
+
*/
|
|
98
|
+
private refreshTokens;
|
|
99
|
+
/**
|
|
100
|
+
* Get user info from MindCache
|
|
101
|
+
*/
|
|
102
|
+
getUserInfo(): Promise<MindCacheUser>;
|
|
103
|
+
/**
|
|
104
|
+
* Logout - revoke tokens and clear storage
|
|
105
|
+
*/
|
|
106
|
+
logout(): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Clear authentication state
|
|
109
|
+
*/
|
|
110
|
+
private clearAuth;
|
|
111
|
+
/**
|
|
112
|
+
* Token provider function for MindCache cloud config
|
|
113
|
+
* Use this with MindCacheCloudOptions.tokenProvider
|
|
114
|
+
*/
|
|
115
|
+
tokenProvider: () => Promise<string>;
|
|
116
|
+
private getStorage;
|
|
117
|
+
private setStorage;
|
|
118
|
+
private removeStorage;
|
|
119
|
+
private clearStorage;
|
|
120
|
+
private loadTokens;
|
|
121
|
+
private saveTokens;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Create OAuth client with environment-appropriate defaults
|
|
125
|
+
*/
|
|
126
|
+
declare function createOAuthClient(config: OAuthConfig): OAuthClient;
|
|
127
|
+
|
|
6
128
|
interface UseMindCacheResult {
|
|
7
129
|
/** The MindCache instance, null until loaded */
|
|
8
130
|
mindcache: MindCache | null;
|
|
@@ -34,4 +156,4 @@ declare function useMindCache(options?: MindCacheOptions): UseMindCacheResult;
|
|
|
34
156
|
|
|
35
157
|
declare const mindcache: MindCache;
|
|
36
158
|
|
|
37
|
-
export { MindCache, MindCacheOptions, type UseMindCacheResult, mindcache, useMindCache };
|
|
159
|
+
export { MindCache, MindCacheOptions, type MindCacheUser, OAuthClient, type OAuthConfig, type OAuthTokens, type UseMindCacheResult, createOAuthClient, mindcache, useMindCache };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,130 @@
|
|
|
1
|
-
import { e as MindCacheOptions, M as MindCache } from './CloudAdapter-
|
|
2
|
-
export { A as AccessLevel, a as CloudAdapter, c as CloudAdapterEvents, C as CloudConfig, b as ConnectionState, h as ContextRules, n as DEFAULT_KEY_ATTRIBUTES, G as GlobalListener, H as HistoryEntry, k as HistoryOptions, K as KeyAttributes, j as KeyEntry, f as KeyType, L as Listener, l as MindCacheCloudOptions, m as MindCacheIndexedDBOptions, i as STM, j as STMEntry, g as SystemTag, o as SystemTagHelpers } from './CloudAdapter-
|
|
1
|
+
import { e as MindCacheOptions, M as MindCache } from './CloudAdapter-CM7nyJaG.js';
|
|
2
|
+
export { A as AccessLevel, a as CloudAdapter, c as CloudAdapterEvents, C as CloudConfig, b as ConnectionState, h as ContextRules, n as DEFAULT_KEY_ATTRIBUTES, G as GlobalListener, H as HistoryEntry, k as HistoryOptions, K as KeyAttributes, j as KeyEntry, f as KeyType, L as Listener, l as MindCacheCloudOptions, m as MindCacheIndexedDBOptions, i as STM, j as STMEntry, g as SystemTag, o as SystemTagHelpers } from './CloudAdapter-CM7nyJaG.js';
|
|
3
3
|
export { IndexedDBAdapter, IndexedDBConfig } from './server.js';
|
|
4
4
|
import 'yjs';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* MindCache OAuth Client
|
|
8
|
+
*
|
|
9
|
+
* Browser-compatible OAuth 2.0 client for "Sign in with MindCache"
|
|
10
|
+
* Supports PKCE for secure authorization
|
|
11
|
+
*/
|
|
12
|
+
interface OAuthConfig {
|
|
13
|
+
/** Client ID from developer portal */
|
|
14
|
+
clientId: string;
|
|
15
|
+
/** Redirect URI (defaults to current URL) */
|
|
16
|
+
redirectUri?: string;
|
|
17
|
+
/** Scopes to request (default: ['read', 'write']) */
|
|
18
|
+
scopes?: string[];
|
|
19
|
+
/** MindCache authorize URL (default: production) */
|
|
20
|
+
authUrl?: string;
|
|
21
|
+
/** MindCache token URL (default: production) */
|
|
22
|
+
tokenUrl?: string;
|
|
23
|
+
/** Use PKCE for security (default: true) */
|
|
24
|
+
usePKCE?: boolean;
|
|
25
|
+
/** Storage key prefix (default: 'mindcache_oauth') */
|
|
26
|
+
storagePrefix?: string;
|
|
27
|
+
}
|
|
28
|
+
interface OAuthTokens {
|
|
29
|
+
accessToken: string;
|
|
30
|
+
refreshToken?: string;
|
|
31
|
+
expiresAt: number;
|
|
32
|
+
scopes: string[];
|
|
33
|
+
instanceId?: string;
|
|
34
|
+
}
|
|
35
|
+
interface MindCacheUser {
|
|
36
|
+
id: string;
|
|
37
|
+
email?: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
instanceId?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* OAuth client for browser applications
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const oauth = new OAuthClient({ clientId: 'mc_app_abc123' });
|
|
47
|
+
*
|
|
48
|
+
* // Start OAuth flow
|
|
49
|
+
* await oauth.authorize();
|
|
50
|
+
*
|
|
51
|
+
* // Handle callback (on redirect page)
|
|
52
|
+
* const tokens = await oauth.handleCallback();
|
|
53
|
+
*
|
|
54
|
+
* // Get access token for API calls
|
|
55
|
+
* const token = await oauth.getAccessToken();
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
declare class OAuthClient {
|
|
59
|
+
private config;
|
|
60
|
+
private tokens;
|
|
61
|
+
private refreshPromise;
|
|
62
|
+
constructor(config: OAuthConfig);
|
|
63
|
+
/**
|
|
64
|
+
* Check if user is authenticated
|
|
65
|
+
*/
|
|
66
|
+
isAuthenticated(): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Get stored tokens (if any)
|
|
69
|
+
*/
|
|
70
|
+
getTokens(): OAuthTokens | null;
|
|
71
|
+
/**
|
|
72
|
+
* Get instance ID for this user+app
|
|
73
|
+
*/
|
|
74
|
+
getInstanceId(): string | null;
|
|
75
|
+
/**
|
|
76
|
+
* Start OAuth authorization flow
|
|
77
|
+
* Redirects to MindCache authorization page
|
|
78
|
+
*/
|
|
79
|
+
authorize(options?: {
|
|
80
|
+
popup?: boolean;
|
|
81
|
+
state?: string;
|
|
82
|
+
}): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Handle OAuth callback
|
|
85
|
+
* Call this on your redirect URI page
|
|
86
|
+
*
|
|
87
|
+
* @returns Tokens if successful
|
|
88
|
+
*/
|
|
89
|
+
handleCallback(): Promise<OAuthTokens>;
|
|
90
|
+
/**
|
|
91
|
+
* Get a valid access token
|
|
92
|
+
* Automatically refreshes if needed
|
|
93
|
+
*/
|
|
94
|
+
getAccessToken(): Promise<string>;
|
|
95
|
+
/**
|
|
96
|
+
* Refresh access token
|
|
97
|
+
*/
|
|
98
|
+
private refreshTokens;
|
|
99
|
+
/**
|
|
100
|
+
* Get user info from MindCache
|
|
101
|
+
*/
|
|
102
|
+
getUserInfo(): Promise<MindCacheUser>;
|
|
103
|
+
/**
|
|
104
|
+
* Logout - revoke tokens and clear storage
|
|
105
|
+
*/
|
|
106
|
+
logout(): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Clear authentication state
|
|
109
|
+
*/
|
|
110
|
+
private clearAuth;
|
|
111
|
+
/**
|
|
112
|
+
* Token provider function for MindCache cloud config
|
|
113
|
+
* Use this with MindCacheCloudOptions.tokenProvider
|
|
114
|
+
*/
|
|
115
|
+
tokenProvider: () => Promise<string>;
|
|
116
|
+
private getStorage;
|
|
117
|
+
private setStorage;
|
|
118
|
+
private removeStorage;
|
|
119
|
+
private clearStorage;
|
|
120
|
+
private loadTokens;
|
|
121
|
+
private saveTokens;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Create OAuth client with environment-appropriate defaults
|
|
125
|
+
*/
|
|
126
|
+
declare function createOAuthClient(config: OAuthConfig): OAuthClient;
|
|
127
|
+
|
|
6
128
|
interface UseMindCacheResult {
|
|
7
129
|
/** The MindCache instance, null until loaded */
|
|
8
130
|
mindcache: MindCache | null;
|
|
@@ -34,4 +156,4 @@ declare function useMindCache(options?: MindCacheOptions): UseMindCacheResult;
|
|
|
34
156
|
|
|
35
157
|
declare const mindcache: MindCache;
|
|
36
158
|
|
|
37
|
-
export { MindCache, MindCacheOptions, type UseMindCacheResult, mindcache, useMindCache };
|
|
159
|
+
export { MindCache, MindCacheOptions, type MindCacheUser, OAuthClient, type OAuthConfig, type OAuthTokens, type UseMindCacheResult, createOAuthClient, mindcache, useMindCache };
|
package/dist/index.js
CHANGED
|
@@ -2645,6 +2645,325 @@ var MindCache = class {
|
|
|
2645
2645
|
init_CloudAdapter();
|
|
2646
2646
|
init_CloudAdapter();
|
|
2647
2647
|
|
|
2648
|
+
// src/cloud/OAuthClient.ts
|
|
2649
|
+
var DEFAULT_AUTH_URL = "https://api.mindcache.dev/oauth/authorize";
|
|
2650
|
+
var DEFAULT_TOKEN_URL = "https://api.mindcache.dev/oauth/token";
|
|
2651
|
+
var DEFAULT_USERINFO_URL = "https://api.mindcache.dev/oauth/userinfo";
|
|
2652
|
+
var TOKEN_REFRESH_BUFFER = 5 * 60 * 1e3;
|
|
2653
|
+
function generateRandomString(length2) {
|
|
2654
|
+
const array = new Uint8Array(length2);
|
|
2655
|
+
crypto.getRandomValues(array);
|
|
2656
|
+
return Array.from(array).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, length2);
|
|
2657
|
+
}
|
|
2658
|
+
function base64UrlEncode(buffer) {
|
|
2659
|
+
const bytes = new Uint8Array(buffer);
|
|
2660
|
+
let binary = "";
|
|
2661
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
2662
|
+
binary += String.fromCharCode(bytes[i]);
|
|
2663
|
+
}
|
|
2664
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
2665
|
+
}
|
|
2666
|
+
function generateCodeVerifier() {
|
|
2667
|
+
return generateRandomString(64);
|
|
2668
|
+
}
|
|
2669
|
+
async function generateCodeChallenge(verifier) {
|
|
2670
|
+
const encoder = new TextEncoder();
|
|
2671
|
+
const data = encoder.encode(verifier);
|
|
2672
|
+
const hash = await crypto.subtle.digest("SHA-256", data);
|
|
2673
|
+
return base64UrlEncode(hash);
|
|
2674
|
+
}
|
|
2675
|
+
var OAuthClient = class {
|
|
2676
|
+
config;
|
|
2677
|
+
tokens = null;
|
|
2678
|
+
refreshPromise = null;
|
|
2679
|
+
constructor(config) {
|
|
2680
|
+
let redirectUri = config.redirectUri;
|
|
2681
|
+
if (!redirectUri && typeof window !== "undefined") {
|
|
2682
|
+
const url = new URL(window.location.href);
|
|
2683
|
+
url.search = "";
|
|
2684
|
+
url.hash = "";
|
|
2685
|
+
redirectUri = url.toString();
|
|
2686
|
+
}
|
|
2687
|
+
this.config = {
|
|
2688
|
+
clientId: config.clientId,
|
|
2689
|
+
redirectUri: redirectUri || "",
|
|
2690
|
+
scopes: config.scopes || ["read", "write"],
|
|
2691
|
+
authUrl: config.authUrl || DEFAULT_AUTH_URL,
|
|
2692
|
+
tokenUrl: config.tokenUrl || DEFAULT_TOKEN_URL,
|
|
2693
|
+
usePKCE: config.usePKCE !== false,
|
|
2694
|
+
// Default true
|
|
2695
|
+
storagePrefix: config.storagePrefix || "mindcache_oauth"
|
|
2696
|
+
};
|
|
2697
|
+
this.loadTokens();
|
|
2698
|
+
}
|
|
2699
|
+
/**
|
|
2700
|
+
* Check if user is authenticated
|
|
2701
|
+
*/
|
|
2702
|
+
isAuthenticated() {
|
|
2703
|
+
return this.tokens !== null && this.tokens.expiresAt > Date.now();
|
|
2704
|
+
}
|
|
2705
|
+
/**
|
|
2706
|
+
* Get stored tokens (if any)
|
|
2707
|
+
*/
|
|
2708
|
+
getTokens() {
|
|
2709
|
+
return this.tokens;
|
|
2710
|
+
}
|
|
2711
|
+
/**
|
|
2712
|
+
* Get instance ID for this user+app
|
|
2713
|
+
*/
|
|
2714
|
+
getInstanceId() {
|
|
2715
|
+
return this.tokens?.instanceId || null;
|
|
2716
|
+
}
|
|
2717
|
+
/**
|
|
2718
|
+
* Start OAuth authorization flow
|
|
2719
|
+
* Redirects to MindCache authorization page
|
|
2720
|
+
*/
|
|
2721
|
+
async authorize(options) {
|
|
2722
|
+
const state = options?.state || generateRandomString(32);
|
|
2723
|
+
this.setStorage("state", state);
|
|
2724
|
+
const url = new URL(this.config.authUrl);
|
|
2725
|
+
url.searchParams.set("response_type", "code");
|
|
2726
|
+
url.searchParams.set("client_id", this.config.clientId);
|
|
2727
|
+
url.searchParams.set("redirect_uri", this.config.redirectUri);
|
|
2728
|
+
url.searchParams.set("scope", this.config.scopes.join(" "));
|
|
2729
|
+
url.searchParams.set("state", state);
|
|
2730
|
+
if (this.config.usePKCE) {
|
|
2731
|
+
const codeVerifier = generateCodeVerifier();
|
|
2732
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
2733
|
+
this.setStorage("code_verifier", codeVerifier);
|
|
2734
|
+
url.searchParams.set("code_challenge", codeChallenge);
|
|
2735
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
2736
|
+
}
|
|
2737
|
+
if (options?.popup) {
|
|
2738
|
+
const popup = window.open(url.toString(), "mindcache_oauth", "width=500,height=600");
|
|
2739
|
+
if (!popup) {
|
|
2740
|
+
throw new Error("Popup blocked. Please allow popups for this site.");
|
|
2741
|
+
}
|
|
2742
|
+
} else {
|
|
2743
|
+
window.location.href = url.toString();
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
/**
|
|
2747
|
+
* Handle OAuth callback
|
|
2748
|
+
* Call this on your redirect URI page
|
|
2749
|
+
*
|
|
2750
|
+
* @returns Tokens if successful
|
|
2751
|
+
*/
|
|
2752
|
+
async handleCallback() {
|
|
2753
|
+
if (typeof window === "undefined") {
|
|
2754
|
+
throw new Error("handleCallback must be called in browser");
|
|
2755
|
+
}
|
|
2756
|
+
const url = new URL(window.location.href);
|
|
2757
|
+
const code = url.searchParams.get("code");
|
|
2758
|
+
const state = url.searchParams.get("state");
|
|
2759
|
+
const error = url.searchParams.get("error");
|
|
2760
|
+
const errorDescription = url.searchParams.get("error_description");
|
|
2761
|
+
if (error) {
|
|
2762
|
+
this.clearStorage();
|
|
2763
|
+
throw new Error(errorDescription || error);
|
|
2764
|
+
}
|
|
2765
|
+
const storedState = this.getStorage("state");
|
|
2766
|
+
if (!state || state !== storedState) {
|
|
2767
|
+
this.clearStorage();
|
|
2768
|
+
throw new Error("Invalid state parameter");
|
|
2769
|
+
}
|
|
2770
|
+
if (!code) {
|
|
2771
|
+
this.clearStorage();
|
|
2772
|
+
throw new Error("No authorization code received");
|
|
2773
|
+
}
|
|
2774
|
+
const body = {
|
|
2775
|
+
grant_type: "authorization_code",
|
|
2776
|
+
code,
|
|
2777
|
+
client_id: this.config.clientId,
|
|
2778
|
+
redirect_uri: this.config.redirectUri
|
|
2779
|
+
};
|
|
2780
|
+
if (this.config.usePKCE) {
|
|
2781
|
+
const codeVerifier = this.getStorage("code_verifier");
|
|
2782
|
+
if (!codeVerifier) {
|
|
2783
|
+
throw new Error("Missing code verifier");
|
|
2784
|
+
}
|
|
2785
|
+
body.code_verifier = codeVerifier;
|
|
2786
|
+
}
|
|
2787
|
+
const response = await fetch(this.config.tokenUrl, {
|
|
2788
|
+
method: "POST",
|
|
2789
|
+
headers: {
|
|
2790
|
+
"Content-Type": "application/json"
|
|
2791
|
+
},
|
|
2792
|
+
body: JSON.stringify(body)
|
|
2793
|
+
});
|
|
2794
|
+
if (!response.ok) {
|
|
2795
|
+
const data2 = await response.json().catch(() => ({}));
|
|
2796
|
+
throw new Error(data2.error_description || data2.error || "Token exchange failed");
|
|
2797
|
+
}
|
|
2798
|
+
const data = await response.json();
|
|
2799
|
+
this.tokens = {
|
|
2800
|
+
accessToken: data.access_token,
|
|
2801
|
+
refreshToken: data.refresh_token,
|
|
2802
|
+
expiresAt: Date.now() + data.expires_in * 1e3,
|
|
2803
|
+
scopes: data.scope?.split(" ") || this.config.scopes,
|
|
2804
|
+
instanceId: data.instance_id
|
|
2805
|
+
};
|
|
2806
|
+
this.saveTokens();
|
|
2807
|
+
url.searchParams.delete("code");
|
|
2808
|
+
url.searchParams.delete("state");
|
|
2809
|
+
window.history.replaceState({}, "", url.toString());
|
|
2810
|
+
this.removeStorage("state");
|
|
2811
|
+
this.removeStorage("code_verifier");
|
|
2812
|
+
return this.tokens;
|
|
2813
|
+
}
|
|
2814
|
+
/**
|
|
2815
|
+
* Get a valid access token
|
|
2816
|
+
* Automatically refreshes if needed
|
|
2817
|
+
*/
|
|
2818
|
+
async getAccessToken() {
|
|
2819
|
+
if (!this.tokens) {
|
|
2820
|
+
throw new Error("Not authenticated. Call authorize() first.");
|
|
2821
|
+
}
|
|
2822
|
+
const needsRefresh = this.tokens.expiresAt - Date.now() < TOKEN_REFRESH_BUFFER;
|
|
2823
|
+
if (needsRefresh && this.tokens.refreshToken) {
|
|
2824
|
+
if (!this.refreshPromise) {
|
|
2825
|
+
this.refreshPromise = this.refreshTokens();
|
|
2826
|
+
}
|
|
2827
|
+
return this.refreshPromise;
|
|
2828
|
+
}
|
|
2829
|
+
return this.tokens.accessToken;
|
|
2830
|
+
}
|
|
2831
|
+
/**
|
|
2832
|
+
* Refresh access token
|
|
2833
|
+
*/
|
|
2834
|
+
async refreshTokens() {
|
|
2835
|
+
if (!this.tokens?.refreshToken) {
|
|
2836
|
+
throw new Error("No refresh token available");
|
|
2837
|
+
}
|
|
2838
|
+
try {
|
|
2839
|
+
const response = await fetch(this.config.tokenUrl, {
|
|
2840
|
+
method: "POST",
|
|
2841
|
+
headers: {
|
|
2842
|
+
"Content-Type": "application/json"
|
|
2843
|
+
},
|
|
2844
|
+
body: JSON.stringify({
|
|
2845
|
+
grant_type: "refresh_token",
|
|
2846
|
+
refresh_token: this.tokens.refreshToken,
|
|
2847
|
+
client_id: this.config.clientId
|
|
2848
|
+
})
|
|
2849
|
+
});
|
|
2850
|
+
if (!response.ok) {
|
|
2851
|
+
this.clearAuth();
|
|
2852
|
+
throw new Error("Session expired. Please sign in again.");
|
|
2853
|
+
}
|
|
2854
|
+
const data = await response.json();
|
|
2855
|
+
this.tokens = {
|
|
2856
|
+
accessToken: data.access_token,
|
|
2857
|
+
refreshToken: data.refresh_token || this.tokens.refreshToken,
|
|
2858
|
+
expiresAt: Date.now() + data.expires_in * 1e3,
|
|
2859
|
+
scopes: data.scope?.split(" ") || this.tokens.scopes,
|
|
2860
|
+
instanceId: data.instance_id || this.tokens.instanceId
|
|
2861
|
+
};
|
|
2862
|
+
this.saveTokens();
|
|
2863
|
+
return this.tokens.accessToken;
|
|
2864
|
+
} finally {
|
|
2865
|
+
this.refreshPromise = null;
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
/**
|
|
2869
|
+
* Get user info from MindCache
|
|
2870
|
+
*/
|
|
2871
|
+
async getUserInfo() {
|
|
2872
|
+
const token = await this.getAccessToken();
|
|
2873
|
+
const response = await fetch(DEFAULT_USERINFO_URL, {
|
|
2874
|
+
headers: {
|
|
2875
|
+
Authorization: `Bearer ${token}`
|
|
2876
|
+
}
|
|
2877
|
+
});
|
|
2878
|
+
if (!response.ok) {
|
|
2879
|
+
throw new Error("Failed to get user info");
|
|
2880
|
+
}
|
|
2881
|
+
const data = await response.json();
|
|
2882
|
+
return {
|
|
2883
|
+
id: data.sub,
|
|
2884
|
+
email: data.email,
|
|
2885
|
+
name: data.name,
|
|
2886
|
+
instanceId: data.instance_id
|
|
2887
|
+
};
|
|
2888
|
+
}
|
|
2889
|
+
/**
|
|
2890
|
+
* Logout - revoke tokens and clear storage
|
|
2891
|
+
*/
|
|
2892
|
+
async logout() {
|
|
2893
|
+
if (this.tokens?.accessToken) {
|
|
2894
|
+
try {
|
|
2895
|
+
await fetch(this.config.tokenUrl.replace("/token", "/revoke"), {
|
|
2896
|
+
method: "POST",
|
|
2897
|
+
headers: {
|
|
2898
|
+
"Content-Type": "application/json"
|
|
2899
|
+
},
|
|
2900
|
+
body: JSON.stringify({
|
|
2901
|
+
token: this.tokens.accessToken
|
|
2902
|
+
})
|
|
2903
|
+
});
|
|
2904
|
+
} catch {
|
|
2905
|
+
}
|
|
2906
|
+
}
|
|
2907
|
+
this.clearAuth();
|
|
2908
|
+
}
|
|
2909
|
+
/**
|
|
2910
|
+
* Clear authentication state
|
|
2911
|
+
*/
|
|
2912
|
+
clearAuth() {
|
|
2913
|
+
this.tokens = null;
|
|
2914
|
+
this.removeStorage("tokens");
|
|
2915
|
+
}
|
|
2916
|
+
/**
|
|
2917
|
+
* Token provider function for MindCache cloud config
|
|
2918
|
+
* Use this with MindCacheCloudOptions.tokenProvider
|
|
2919
|
+
*/
|
|
2920
|
+
tokenProvider = async () => {
|
|
2921
|
+
return this.getAccessToken();
|
|
2922
|
+
};
|
|
2923
|
+
// Storage helpers
|
|
2924
|
+
getStorage(key) {
|
|
2925
|
+
if (typeof localStorage === "undefined") {
|
|
2926
|
+
return null;
|
|
2927
|
+
}
|
|
2928
|
+
return localStorage.getItem(`${this.config.storagePrefix}_${key}`);
|
|
2929
|
+
}
|
|
2930
|
+
setStorage(key, value) {
|
|
2931
|
+
if (typeof localStorage === "undefined") {
|
|
2932
|
+
return;
|
|
2933
|
+
}
|
|
2934
|
+
localStorage.setItem(`${this.config.storagePrefix}_${key}`, value);
|
|
2935
|
+
}
|
|
2936
|
+
removeStorage(key) {
|
|
2937
|
+
if (typeof localStorage === "undefined") {
|
|
2938
|
+
return;
|
|
2939
|
+
}
|
|
2940
|
+
localStorage.removeItem(`${this.config.storagePrefix}_${key}`);
|
|
2941
|
+
}
|
|
2942
|
+
clearStorage() {
|
|
2943
|
+
this.removeStorage("state");
|
|
2944
|
+
this.removeStorage("code_verifier");
|
|
2945
|
+
this.removeStorage("tokens");
|
|
2946
|
+
}
|
|
2947
|
+
loadTokens() {
|
|
2948
|
+
const stored = this.getStorage("tokens");
|
|
2949
|
+
if (stored) {
|
|
2950
|
+
try {
|
|
2951
|
+
this.tokens = JSON.parse(stored);
|
|
2952
|
+
} catch {
|
|
2953
|
+
this.tokens = null;
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
saveTokens() {
|
|
2958
|
+
if (this.tokens) {
|
|
2959
|
+
this.setStorage("tokens", JSON.stringify(this.tokens));
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
};
|
|
2963
|
+
function createOAuthClient(config) {
|
|
2964
|
+
return new OAuthClient(config);
|
|
2965
|
+
}
|
|
2966
|
+
|
|
2648
2967
|
// src/local/index.ts
|
|
2649
2968
|
init_IndexedDBAdapter();
|
|
2650
2969
|
function useMindCache(options) {
|
|
@@ -2687,7 +3006,9 @@ var mindcache = new MindCache();
|
|
|
2687
3006
|
|
|
2688
3007
|
exports.DEFAULT_KEY_ATTRIBUTES = DEFAULT_KEY_ATTRIBUTES;
|
|
2689
3008
|
exports.MindCache = MindCache;
|
|
3009
|
+
exports.OAuthClient = OAuthClient;
|
|
2690
3010
|
exports.SystemTagHelpers = SystemTagHelpers;
|
|
3011
|
+
exports.createOAuthClient = createOAuthClient;
|
|
2691
3012
|
exports.mindcache = mindcache;
|
|
2692
3013
|
exports.useMindCache = useMindCache;
|
|
2693
3014
|
//# sourceMappingURL=index.js.map
|