@korajs/auth 0.5.0 → 1.0.0-beta.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/react.js CHANGED
@@ -1,5 +1,13 @@
1
+ import {
2
+ checkOrgPermission,
3
+ createAuthSession,
4
+ createOrgMembersActions,
5
+ createOrgSession,
6
+ loadOrgMembers
7
+ } from "./chunk-MPMXJ62R.js";
8
+
1
9
  // src/react/AuthProvider.tsx
2
- import { createElement, useEffect, useState } from "react";
10
+ import { createElement, useEffect, useMemo, useSyncExternalStore } from "react";
3
11
 
4
12
  // src/react/auth-context.ts
5
13
  import { createContext } from "react";
@@ -7,35 +15,14 @@ var AuthContext = createContext(null);
7
15
 
8
16
  // src/react/AuthProvider.tsx
9
17
  function AuthProvider({ client, children, fallback }) {
10
- const [state, setState] = useState(client.state);
11
- const [isLoading, setIsLoading] = useState(true);
12
- const [initError, setInitError] = useState(null);
13
- useEffect(() => {
14
- let cancelled = false;
15
- const unsubscribe = client.onAuthChange((newState) => {
16
- if (!cancelled) {
17
- setState(newState);
18
- }
19
- });
20
- client.initialize().then(() => {
21
- if (!cancelled) {
22
- setState(client.state);
23
- setIsLoading(false);
24
- }
25
- }).catch((error) => {
26
- if (!cancelled) {
27
- const err = error instanceof Error ? error : new Error(String(error));
28
- console.error("[Kora Auth] Initialization failed:", err);
29
- setInitError(err);
30
- setIsLoading(false);
31
- }
32
- });
33
- return () => {
34
- cancelled = true;
35
- unsubscribe();
36
- };
37
- }, [client]);
38
- if (initError) {
18
+ const session = useMemo(() => createAuthSession(client), [client]);
19
+ useEffect(() => () => session.destroy(), [session]);
20
+ const snapshot = useSyncExternalStore(
21
+ (onStoreChange) => session.subscribe(onStoreChange),
22
+ () => session.getSnapshot(),
23
+ () => session.getSnapshot()
24
+ );
25
+ if (snapshot.initError) {
39
26
  return createElement(
40
27
  "div",
41
28
  {
@@ -43,22 +30,23 @@ function AuthProvider({ client, children, fallback }) {
43
30
  role: "alert"
44
31
  },
45
32
  createElement("strong", null, "Kora Auth initialization error: "),
46
- initError.message
33
+ snapshot.initError.message
47
34
  );
48
35
  }
49
- if (isLoading && fallback !== void 0) {
36
+ if (snapshot.isLoading && fallback !== void 0) {
50
37
  return fallback;
51
38
  }
52
39
  const contextValue = {
53
40
  client,
54
- state,
55
- isLoading
41
+ session,
42
+ state: snapshot.state,
43
+ isLoading: snapshot.isLoading
56
44
  };
57
45
  return createElement(AuthContext.Provider, { value: contextValue }, children);
58
46
  }
59
47
 
60
48
  // src/react/hooks.ts
61
- import { useCallback, useContext, useRef, useState as useState2, useSyncExternalStore } from "react";
49
+ import { useContext, useSyncExternalStore as useSyncExternalStore2 } from "react";
62
50
  function useAuthContext() {
63
51
  const ctx = useContext(AuthContext);
64
52
  if (ctx === null) {
@@ -68,192 +56,58 @@ function useAuthContext() {
68
56
  }
69
57
  return ctx;
70
58
  }
71
- function useAuth() {
72
- const { client, state, isLoading } = useAuthContext();
73
- const [error, setError] = useState2(null);
74
- const userSnapshotRef = useRef(client.currentUser);
75
- const stateSerializedRef = useRef(JSON.stringify(client.currentUser));
76
- const subscribe = useCallback(
77
- (onStoreChange) => {
78
- return client.onAuthChange(() => {
79
- const newUser = client.currentUser;
80
- const newSerialized = JSON.stringify(newUser);
81
- if (newSerialized !== stateSerializedRef.current) {
82
- userSnapshotRef.current = newUser;
83
- stateSerializedRef.current = newSerialized;
84
- onStoreChange();
85
- }
86
- });
87
- },
88
- [client]
89
- );
90
- const getSnapshot = useCallback(() => {
91
- return userSnapshotRef.current;
92
- }, []);
93
- const user = useSyncExternalStore(subscribe, getSnapshot);
94
- const signUp = useCallback(
95
- async (params) => {
96
- setError(null);
97
- try {
98
- await client.signUp(params);
99
- } catch (err) {
100
- const message = err instanceof Error ? err.message : String(err);
101
- setError(message);
102
- }
103
- },
104
- [client]
105
- );
106
- const signIn = useCallback(
107
- async (params) => {
108
- setError(null);
109
- try {
110
- await client.signIn(params);
111
- } catch (err) {
112
- const message = err instanceof Error ? err.message : String(err);
113
- setError(message);
114
- }
115
- },
116
- [client]
117
- );
118
- const signInWithOAuth = useCallback(
119
- async (provider, options) => {
120
- setError(null);
121
- try {
122
- return await client.signInWithOAuth(provider, options);
123
- } catch (err) {
124
- const message = err instanceof Error ? err.message : String(err);
125
- setError(message);
126
- throw err;
127
- }
128
- },
129
- [client]
130
- );
131
- const completeOAuthSignIn = useCallback(
132
- async (provider, params) => {
133
- setError(null);
134
- try {
135
- await client.completeOAuthSignIn(provider, params);
136
- } catch (err) {
137
- const message = err instanceof Error ? err.message : String(err);
138
- setError(message);
139
- }
140
- },
141
- [client]
142
- );
143
- const getOAuthAuthorizationUrl = useCallback(
144
- async (provider, options) => {
145
- setError(null);
146
- try {
147
- return await client.getOAuthAuthorizationUrl(provider, options);
148
- } catch (err) {
149
- const message = err instanceof Error ? err.message : String(err);
150
- setError(message);
151
- throw err;
152
- }
153
- },
154
- [client]
155
- );
156
- const linkOAuth = useCallback(
157
- async (provider, params) => {
158
- setError(null);
159
- try {
160
- return await client.linkOAuth(provider, params);
161
- } catch (err) {
162
- const message = err instanceof Error ? err.message : String(err);
163
- setError(message);
164
- return null;
165
- }
166
- },
167
- [client]
59
+ function useAuthSessionSnapshot() {
60
+ const { session } = useAuthContext();
61
+ return useSyncExternalStore2(
62
+ (onStoreChange) => session.subscribe(onStoreChange),
63
+ () => session.getSnapshot(),
64
+ () => session.getSnapshot()
168
65
  );
169
- const listLinkedAccounts = useCallback(async () => {
170
- setError(null);
171
- try {
172
- return await client.listLinkedAccounts();
173
- } catch (err) {
174
- const message = err instanceof Error ? err.message : String(err);
175
- setError(message);
176
- return [];
177
- }
178
- }, [client]);
179
- const unlinkOAuth = useCallback(
180
- async (provider) => {
181
- setError(null);
182
- try {
183
- await client.unlinkOAuth(provider);
184
- } catch (err) {
185
- const message = err instanceof Error ? err.message : String(err);
186
- setError(message);
187
- }
188
- },
189
- [client]
190
- );
191
- const signOut = useCallback(async () => {
192
- setError(null);
193
- try {
194
- await client.signOut();
195
- } catch (err) {
196
- const message = err instanceof Error ? err.message : String(err);
197
- setError(message);
198
- }
199
- }, [client]);
66
+ }
67
+ function useAuth() {
68
+ const { session } = useAuthContext();
69
+ const snapshot = useAuthSessionSnapshot();
200
70
  return {
201
- user,
202
- isAuthenticated: state === "authenticated",
203
- isLoading,
204
- signUp,
205
- signIn,
206
- signInWithOAuth,
207
- completeOAuthSignIn,
208
- getOAuthAuthorizationUrl,
209
- linkOAuth,
210
- listLinkedAccounts,
211
- unlinkOAuth,
212
- signOut,
213
- error
71
+ user: snapshot.user,
72
+ isAuthenticated: snapshot.isAuthenticated,
73
+ isLoading: snapshot.isLoading,
74
+ error: snapshot.error,
75
+ initError: snapshot.initError,
76
+ signUp: (params) => session.signUp(params),
77
+ signIn: (params) => session.signIn(params),
78
+ signInWithOAuth: (provider, options) => session.signInWithOAuth(provider, options),
79
+ completeOAuthSignIn: (provider, params) => session.completeOAuthSignIn(provider, params),
80
+ getOAuthAuthorizationUrl: (provider, options) => session.getOAuthAuthorizationUrl(provider, options),
81
+ linkOAuth: (provider, params) => session.linkOAuth(provider, params),
82
+ listLinkedAccounts: () => session.listLinkedAccounts(),
83
+ unlinkOAuth: (provider) => session.unlinkOAuth(provider),
84
+ signOut: () => session.signOut()
214
85
  };
215
86
  }
216
87
  function useCurrentUser() {
217
- const { client } = useAuthContext();
218
- const userSnapshotRef = useRef(client.currentUser);
219
- const stateSerializedRef = useRef(JSON.stringify(client.currentUser));
220
- const subscribe = useCallback(
221
- (onStoreChange) => {
222
- return client.onAuthChange(() => {
223
- const newUser = client.currentUser;
224
- const newSerialized = JSON.stringify(newUser);
225
- if (newSerialized !== stateSerializedRef.current) {
226
- userSnapshotRef.current = newUser;
227
- stateSerializedRef.current = newSerialized;
228
- onStoreChange();
229
- }
230
- });
231
- },
232
- [client]
233
- );
234
- const getSnapshot = useCallback(() => {
235
- return userSnapshotRef.current;
236
- }, []);
237
- return useSyncExternalStore(subscribe, getSnapshot);
88
+ return useAuthSessionSnapshot().user;
238
89
  }
239
90
  function useAuthStatus() {
240
- const { state, isLoading } = useAuthContext();
91
+ const snapshot = useAuthSessionSnapshot();
241
92
  return {
242
- state,
243
- isAuthenticated: state === "authenticated",
244
- isLoading
93
+ state: snapshot.state,
94
+ isAuthenticated: snapshot.isAuthenticated,
95
+ isLoading: snapshot.isLoading
245
96
  };
246
97
  }
247
98
 
99
+ // src/react/OrgProvider.tsx
100
+ import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2 } from "react";
101
+
248
102
  // src/react/org-hooks.ts
249
103
  import {
250
104
  createContext as createContext2,
251
- useCallback as useCallback2,
105
+ useCallback,
252
106
  useContext as useContext2,
253
- useEffect as useEffect3,
254
- useRef as useRef2,
255
- useState as useState3,
256
- useSyncExternalStore as useSyncExternalStore2
107
+ useEffect as useEffect2,
108
+ useRef,
109
+ useState,
110
+ useSyncExternalStore as useSyncExternalStore3
257
111
  } from "react";
258
112
  var OrgContext = createContext2(null);
259
113
  function useOrgContext() {
@@ -265,30 +119,25 @@ function useOrgContext() {
265
119
  }
266
120
  return ctx;
267
121
  }
268
- function useOrg() {
269
- const { client } = useOrgContext();
270
- const [error, setError] = useState3(null);
271
- const orgSnapshotRef = useRef2({
272
- orgId: client.activeOrgId,
273
- org: client.activeOrg,
274
- role: client.activeRole
275
- });
276
- const subscribe = useCallback2(
122
+ function useOrgSnapshot(session) {
123
+ const snapshotRef = useRef(session.getSnapshot());
124
+ const subscribe = useCallback(
277
125
  (onStoreChange) => {
278
- return client.onOrgChange(() => {
279
- orgSnapshotRef.current = {
280
- orgId: client.activeOrgId,
281
- org: client.activeOrg,
282
- role: client.activeRole
283
- };
126
+ return session.subscribe(() => {
127
+ snapshotRef.current = session.getSnapshot();
284
128
  onStoreChange();
285
129
  });
286
130
  },
287
- [client]
131
+ [session]
288
132
  );
289
- const getSnapshot = useCallback2(() => orgSnapshotRef.current, []);
290
- const { orgId, org, role } = useSyncExternalStore2(subscribe, getSnapshot);
291
- const switchOrg = useCallback2(
133
+ const getSnapshot = useCallback(() => snapshotRef.current, []);
134
+ return useSyncExternalStore3(subscribe, getSnapshot);
135
+ }
136
+ function useOrg() {
137
+ const { client, session } = useOrgContext();
138
+ const { orgId, org, role } = useOrgSnapshot(session);
139
+ const [error, setError] = useState(null);
140
+ const switchOrg = useCallback(
292
141
  async (newOrgId) => {
293
142
  setError(null);
294
143
  try {
@@ -299,7 +148,7 @@ function useOrg() {
299
148
  },
300
149
  [client]
301
150
  );
302
- const createOrg = useCallback2(
151
+ const createOrg = useCallback(
303
152
  async (params) => {
304
153
  setError(null);
305
154
  try {
@@ -312,7 +161,7 @@ function useOrg() {
312
161
  },
313
162
  [client]
314
163
  );
315
- const leaveOrg = useCallback2(async () => {
164
+ const leaveOrg = useCallback(async () => {
316
165
  if (!orgId) return;
317
166
  setError(null);
318
167
  try {
@@ -321,10 +170,10 @@ function useOrg() {
321
170
  setError(err instanceof Error ? err.message : String(err));
322
171
  }
323
172
  }, [client, orgId]);
324
- const clearOrg = useCallback2(() => {
173
+ const clearOrg = useCallback(() => {
325
174
  client.clearActiveOrg();
326
175
  }, [client]);
327
- const listOrgs = useCallback2(async () => {
176
+ const listOrgs = useCallback(async () => {
328
177
  try {
329
178
  return await client.listOrgs();
330
179
  } catch (err) {
@@ -336,99 +185,97 @@ function useOrg() {
336
185
  }
337
186
  function useOrgMembers(orgId) {
338
187
  const { client } = useOrgContext();
339
- const [members, setMembers] = useState3([]);
340
- const [isLoading, setIsLoading] = useState3(true);
341
- const [error, setError] = useState3(null);
342
- const refresh = useCallback2(async () => {
188
+ const [members, setMembers] = useState([]);
189
+ const [isLoading, setIsLoading] = useState(true);
190
+ const [error, setError] = useState(null);
191
+ const refresh = useCallback(async () => {
343
192
  setIsLoading(true);
344
193
  setError(null);
345
194
  try {
346
- const result = await client.listMembers(orgId);
347
- setMembers(result);
195
+ setMembers(await loadOrgMembers(client, orgId));
348
196
  } catch (err) {
349
197
  setError(err instanceof Error ? err.message : String(err));
350
198
  } finally {
351
199
  setIsLoading(false);
352
200
  }
353
201
  }, [client, orgId]);
354
- useEffect3(() => {
355
- refresh();
202
+ useEffect2(() => {
203
+ void refresh();
356
204
  }, [refresh]);
357
- const invite = useCallback2(
205
+ const actions = createOrgMembersActions(client, orgId, setError);
206
+ const invite = useCallback(
358
207
  async (email, role) => {
359
- setError(null);
360
- try {
361
- const result = await client.inviteMember(orgId, { email, role });
362
- return result;
363
- } catch (err) {
364
- const msg = err instanceof Error ? err.message : String(err);
365
- setError(msg);
366
- throw err;
367
- }
208
+ const result = await actions.invite(email, role);
209
+ await refresh();
210
+ return result;
368
211
  },
369
- [client, orgId]
212
+ [actions, refresh]
370
213
  );
371
- const removeMember = useCallback2(
214
+ const removeMember = useCallback(
372
215
  async (userId) => {
373
- setError(null);
374
- try {
375
- await client.removeMember(orgId, userId);
376
- await refresh();
377
- } catch (err) {
378
- setError(err instanceof Error ? err.message : String(err));
379
- }
216
+ await actions.removeMember(userId);
217
+ await refresh();
380
218
  },
381
- [client, orgId, refresh]
219
+ [actions, refresh]
382
220
  );
383
- const updateRole = useCallback2(
221
+ const updateRole = useCallback(
384
222
  async (userId, role) => {
385
- setError(null);
386
- try {
387
- await client.updateMemberRole(orgId, userId, role);
388
- await refresh();
389
- } catch (err) {
390
- setError(err instanceof Error ? err.message : String(err));
391
- }
223
+ await actions.updateRole(userId, role);
224
+ await refresh();
392
225
  },
393
- [client, orgId, refresh]
226
+ [actions, refresh]
394
227
  );
395
228
  return { members, isLoading, refresh, invite, removeMember, updateRole, error };
396
229
  }
397
230
  function usePermission(requiredRole) {
398
- const { client } = useOrgContext();
399
- const snapshotRef = useRef2(checkPermission(client.activeRole, requiredRole));
400
- const subscribe = useCallback2(
231
+ const { session } = useOrgContext();
232
+ const snapshotRef = useRef(session.checkPermission(requiredRole));
233
+ const subscribe = useCallback(
401
234
  (onStoreChange) => {
402
- return client.onOrgChange(() => {
403
- const newValue = checkPermission(client.activeRole, requiredRole);
404
- if (newValue !== snapshotRef.current) {
405
- snapshotRef.current = newValue;
235
+ return session.subscribe(() => {
236
+ const next = session.checkPermission(requiredRole);
237
+ if (next !== snapshotRef.current) {
238
+ snapshotRef.current = next;
406
239
  onStoreChange();
407
240
  }
408
241
  });
409
242
  },
410
- [client, requiredRole]
243
+ [session, requiredRole]
411
244
  );
412
- const getSnapshot = useCallback2(() => snapshotRef.current, []);
413
- return useSyncExternalStore2(subscribe, getSnapshot);
245
+ const getSnapshot = useCallback(() => snapshotRef.current, []);
246
+ return useSyncExternalStore3(subscribe, getSnapshot);
414
247
  }
415
- var ROLE_LEVELS = {
416
- viewer: 10,
417
- billing: 15,
418
- member: 20,
419
- admin: 30,
420
- owner: 40
421
- };
422
- function checkPermission(currentRole, requiredRole) {
423
- if (!currentRole) return false;
424
- const currentLevel = ROLE_LEVELS[currentRole] ?? 0;
425
- const requiredLevel = ROLE_LEVELS[requiredRole] ?? 0;
426
- return currentLevel >= requiredLevel;
248
+
249
+ // src/react/OrgProvider.tsx
250
+ import { jsx } from "react/jsx-runtime";
251
+ function OrgProvider({ client, children }) {
252
+ const sessionRef = useRef2(null);
253
+ if (sessionRef.current === null || sessionRef.current.client !== client) {
254
+ sessionRef.current?.destroy();
255
+ sessionRef.current = createOrgSession(client);
256
+ }
257
+ useEffect3(() => {
258
+ return () => {
259
+ sessionRef.current?.destroy();
260
+ sessionRef.current = null;
261
+ };
262
+ }, []);
263
+ const session = sessionRef.current;
264
+ const value = useMemo2(
265
+ () => ({
266
+ client,
267
+ session
268
+ }),
269
+ [client, session]
270
+ );
271
+ return /* @__PURE__ */ jsx(OrgContext.Provider, { value, children });
427
272
  }
428
273
  export {
429
274
  AuthContext,
430
275
  AuthProvider,
431
276
  OrgContext,
277
+ OrgProvider,
278
+ checkOrgPermission,
432
279
  useAuth,
433
280
  useAuthStatus,
434
281
  useCurrentUser,