talizen 0.2.14 → 0.2.15

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.
Files changed (3) hide show
  1. package/auth.d.ts +5 -0
  2. package/auth.js +110 -40
  3. package/package.json +1 -1
package/auth.d.ts CHANGED
@@ -49,6 +49,7 @@ export interface AuthProviderListResponse {
49
49
  export interface AuthOAuthLoginURLOptions extends TalizenRequestOptions {
50
50
  redirectUrl?: string;
51
51
  }
52
+ export type User = AuthUser;
52
53
  export declare class TalizenAuthError extends Error {
53
54
  constructor(message: string);
54
55
  }
@@ -58,9 +59,13 @@ export interface UseAuthResult {
58
59
  user: AuthUser | null;
59
60
  loading: boolean;
60
61
  error: unknown;
62
+ isAuthenticated: boolean;
63
+ isInitialized: boolean;
61
64
  refresh(): Promise<AuthUser | null>;
62
65
  login(input: AuthPasswordInput): Promise<AuthUser>;
66
+ login(account: string, password: string): Promise<AuthUser>;
63
67
  register(input: AuthRegisterInput): Promise<AuthUser>;
68
+ register(account: string, password: string, name?: string): Promise<AuthUser>;
64
69
  logout(): Promise<void>;
65
70
  updateProfile(profile: AuthProfile): Promise<AuthUser>;
66
71
  }
package/auth.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { getTalizenConfig, requestJson, subscribeTalizenConfig, } from "./core.js";
2
+ import { getTalizenConfig, requestJson, subscribeTalizenConfig, TalizenHttpError, } from "./core.js";
3
3
  export class TalizenAuthError extends Error {
4
4
  constructor(message) {
5
5
  super(message);
@@ -18,8 +18,102 @@ export async function login(input, options) {
18
18
  body: JSON.stringify(input),
19
19
  }, options);
20
20
  }
21
- function readAuthConfigSnapshot() {
22
- return getTalizenConfig();
21
+ const authListeners = new Set();
22
+ let currentUserState = null;
23
+ let authErrorState = null;
24
+ let isAuthInitialized = false;
25
+ let isAuthLoading = false;
26
+ let authSnapshot = readAuthSnapshot();
27
+ let authRequestId = 0;
28
+ let isAuthConfigSubscriptionStarted = false;
29
+ function readAuthSnapshot() {
30
+ return {
31
+ user: currentUserState,
32
+ loading: isAuthLoading,
33
+ error: authErrorState,
34
+ isAuthenticated: !!currentUserState,
35
+ isInitialized: isAuthInitialized,
36
+ };
37
+ }
38
+ function emitAuthChange() {
39
+ authSnapshot = readAuthSnapshot();
40
+ authListeners.forEach(listener => listener());
41
+ }
42
+ function subscribeAuth(listener) {
43
+ authListeners.add(listener);
44
+ return () => {
45
+ authListeners.delete(listener);
46
+ };
47
+ }
48
+ function ensureAuthConfigSubscription() {
49
+ if (isAuthConfigSubscriptionStarted)
50
+ return;
51
+ isAuthConfigSubscriptionStarted = true;
52
+ subscribeTalizenConfig(() => {
53
+ void refreshAuthState().catch(() => { });
54
+ });
55
+ }
56
+ function normalizeLoginInput(input, password) {
57
+ if (typeof input === "string") {
58
+ return {
59
+ account: input,
60
+ password: password ?? "",
61
+ };
62
+ }
63
+ return input;
64
+ }
65
+ function normalizeRegisterInput(input, password, name) {
66
+ if (typeof input === "string") {
67
+ return {
68
+ account: input,
69
+ email: input,
70
+ password: password ?? "",
71
+ name,
72
+ };
73
+ }
74
+ return input;
75
+ }
76
+ function isUnauthenticatedError(error) {
77
+ return error instanceof TalizenHttpError && error.status === 401;
78
+ }
79
+ async function refreshAuthState(options) {
80
+ const requestId = authRequestId + 1;
81
+ authRequestId = requestId;
82
+ isAuthLoading = true;
83
+ authErrorState = null;
84
+ emitAuthChange();
85
+ try {
86
+ const user = await currentUser(options);
87
+ if (authRequestId === requestId) {
88
+ currentUserState = user;
89
+ authErrorState = null;
90
+ isAuthInitialized = true;
91
+ isAuthLoading = false;
92
+ emitAuthChange();
93
+ }
94
+ return user;
95
+ }
96
+ catch (error) {
97
+ if (authRequestId === requestId) {
98
+ currentUserState = null;
99
+ authErrorState = isUnauthenticatedError(error) ? null : error;
100
+ isAuthInitialized = true;
101
+ isAuthLoading = false;
102
+ emitAuthChange();
103
+ }
104
+ if (isUnauthenticatedError(error)) {
105
+ return null;
106
+ }
107
+ throw error;
108
+ }
109
+ }
110
+ function setAuthUser(user) {
111
+ authRequestId += 1;
112
+ currentUserState = user;
113
+ authErrorState = null;
114
+ isAuthInitialized = true;
115
+ isAuthLoading = false;
116
+ emitAuthChange();
23
117
  }
24
118
  /**
25
119
  * Subscribe to the current auth user.
@@ -28,63 +122,39 @@ function readAuthConfigSnapshot() {
28
122
  * config, which lets preview auth headers update the page without remounting.
29
123
  */
30
124
  export function useAuth(options) {
31
- const configSnapshot = React.useSyncExternalStore(subscribeTalizenConfig, readAuthConfigSnapshot, readAuthConfigSnapshot);
125
+ const snapshot = React.useSyncExternalStore(subscribeAuth, () => authSnapshot, () => authSnapshot);
32
126
  const optionsRef = React.useRef(options);
33
- const requestIdRef = React.useRef(0);
34
- const [state, setState] = React.useState({
35
- user: null,
36
- loading: true,
37
- error: null,
38
- });
39
127
  React.useEffect(() => {
40
128
  optionsRef.current = options;
41
129
  }, [options]);
42
130
  const refresh = React.useCallback(async () => {
43
- const requestId = requestIdRef.current + 1;
44
- requestIdRef.current = requestId;
45
- setState(current => ({ ...current, loading: true, error: null }));
46
- try {
47
- const nextUser = await currentUser(optionsRef.current);
48
- if (requestIdRef.current === requestId) {
49
- setState({ user: nextUser, loading: false, error: null });
50
- }
51
- return nextUser;
52
- }
53
- catch (error) {
54
- if (requestIdRef.current === requestId) {
55
- setState(current => ({ ...current, loading: false, error }));
56
- }
57
- throw error;
58
- }
131
+ return refreshAuthState(optionsRef.current);
59
132
  }, []);
60
133
  React.useEffect(() => {
134
+ ensureAuthConfigSubscription();
61
135
  void refresh().catch(() => { });
62
- }, [configSnapshot, refresh]);
63
- const loginAndRefresh = React.useCallback(async (input) => {
64
- const nextUser = await login(input, optionsRef.current);
65
- requestIdRef.current += 1;
66
- setState({ user: nextUser, loading: false, error: null });
136
+ }, [refresh]);
137
+ const loginAndRefresh = React.useCallback(async (input, password) => {
138
+ const nextUser = await login(normalizeLoginInput(input, password), optionsRef.current);
139
+ setAuthUser(nextUser);
67
140
  return nextUser;
68
141
  }, []);
69
- const registerAndRefresh = React.useCallback(async (input) => {
70
- const nextUser = await register(input, optionsRef.current);
71
- requestIdRef.current += 1;
72
- setState({ user: nextUser, loading: false, error: null });
142
+ const registerAndRefresh = React.useCallback(async (input, password, name) => {
143
+ const nextUser = await register(normalizeRegisterInput(input, password, name), optionsRef.current);
144
+ setAuthUser(nextUser);
73
145
  return nextUser;
74
146
  }, []);
75
147
  const logoutAndRefresh = React.useCallback(async () => {
76
148
  await logout(optionsRef.current);
77
- requestIdRef.current += 1;
78
- setState({ user: null, loading: false, error: null });
149
+ setAuthUser(null);
79
150
  }, []);
80
151
  const updateProfileAndRefresh = React.useCallback(async (profile) => {
81
152
  const nextUser = await updateProfile(profile, optionsRef.current);
82
- requestIdRef.current += 1;
83
- setState({ user: nextUser, loading: false, error: null });
153
+ setAuthUser(nextUser);
84
154
  return nextUser;
85
155
  }, []);
86
156
  return {
87
- ...state,
157
+ ...snapshot,
88
158
  refresh,
89
159
  login: loginAndRefresh,
90
160
  register: registerAndRefresh,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "talizen",
3
- "version": "0.2.14",
3
+ "version": "0.2.15",
4
4
  "description": "Talizen frontend SDK types for cms, form and core.",
5
5
  "type": "module",
6
6
  "license": "MIT",