@lushly-dev/afd-auth 0.6.0 → 2.0.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.
Files changed (56) hide show
  1. package/README.md +134 -0
  2. package/dist/adapters/better-auth.d.ts +34 -6
  3. package/dist/adapters/better-auth.d.ts.map +1 -1
  4. package/dist/adapters/better-auth.js +73 -25
  5. package/dist/adapters/better-auth.js.map +1 -1
  6. package/dist/adapters/convex.d.ts +29 -6
  7. package/dist/adapters/convex.d.ts.map +1 -1
  8. package/dist/adapters/convex.js +139 -56
  9. package/dist/adapters/convex.js.map +1 -1
  10. package/dist/adapters/mock.d.ts +16 -4
  11. package/dist/adapters/mock.d.ts.map +1 -1
  12. package/dist/adapters/mock.js +13 -11
  13. package/dist/adapters/mock.js.map +1 -1
  14. package/dist/adapters/provider-errors.d.ts +16 -0
  15. package/dist/adapters/provider-errors.d.ts.map +1 -0
  16. package/dist/adapters/provider-errors.js +27 -0
  17. package/dist/adapters/provider-errors.js.map +1 -0
  18. package/dist/command-names.d.ts +13 -0
  19. package/dist/command-names.d.ts.map +1 -0
  20. package/dist/command-names.js +13 -0
  21. package/dist/command-names.js.map +1 -0
  22. package/dist/commands.d.ts +11 -2
  23. package/dist/commands.d.ts.map +1 -1
  24. package/dist/commands.js +141 -9
  25. package/dist/commands.js.map +1 -1
  26. package/dist/index.d.ts +5 -4
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +2 -6
  29. package/dist/index.js.map +1 -1
  30. package/dist/listeners.d.ts +39 -0
  31. package/dist/listeners.d.ts.map +1 -0
  32. package/dist/listeners.js +72 -0
  33. package/dist/listeners.js.map +1 -0
  34. package/dist/middleware.d.ts +22 -3
  35. package/dist/middleware.d.ts.map +1 -1
  36. package/dist/middleware.js +32 -14
  37. package/dist/middleware.js.map +1 -1
  38. package/dist/react.d.ts.map +1 -1
  39. package/dist/react.js +19 -5
  40. package/dist/react.js.map +1 -1
  41. package/dist/session-state.d.ts +19 -0
  42. package/dist/session-state.d.ts.map +1 -0
  43. package/dist/session-state.js +42 -0
  44. package/dist/session-state.js.map +1 -0
  45. package/dist/session-sync-message.d.ts +29 -0
  46. package/dist/session-sync-message.d.ts.map +1 -0
  47. package/dist/session-sync-message.js +27 -0
  48. package/dist/session-sync-message.js.map +1 -0
  49. package/dist/session-sync.d.ts +35 -8
  50. package/dist/session-sync.d.ts.map +1 -1
  51. package/dist/session-sync.js +178 -44
  52. package/dist/session-sync.js.map +1 -1
  53. package/dist/types.d.ts +35 -2
  54. package/dist/types.d.ts.map +1 -1
  55. package/dist/types.js.map +1 -1
  56. package/package.json +21 -15
@@ -4,74 +4,157 @@
4
4
  * Bridges @convex-dev/auth React hooks to the AuthAdapter interface.
5
5
  * This is a React hook — must be called inside a component.
6
6
  */
7
- import { useCallback, useEffect, useRef } from 'react';
7
+ import { useEffect, useRef, useState } from 'react';
8
+ import { AuthAdapterError } from '../errors.js';
9
+ import { ListenerSet, reportListenerError } from '../listeners.js';
10
+ import { areSessionStatesEqual, areUsersEqual } from '../session-state.js';
8
11
  import { LOADING, UNAUTHENTICATED } from '../types.js';
12
+ import { describeThrown, isKnownNetworkFailure } from './provider-errors.js';
13
+ /** Id of `Password()` from `@convex-dev/auth/providers/Password`. */
14
+ const DEFAULT_PASSWORD_PROVIDER_ID = 'password';
9
15
  /**
10
16
  * React hook that creates an AuthAdapter backed by Convex.
11
17
  *
12
- * Must be called inside a ConvexProvider + ConvexAuthProvider tree.
18
+ * Must be called inside a ConvexProvider + ConvexAuthProvider tree. It returns
19
+ * the same adapter object on every render; the adapter always uses the latest
20
+ * actions and options passed to the hook.
13
21
  */
14
22
  export function useConvexAuthAdapter(options) {
15
- const { signIn: convexSignIn, signOut: convexSignOut } = options.useAuthActions();
23
+ const actions = options.useAuthActions();
16
24
  const { isAuthenticated, isLoading } = options.useConvexAuth();
17
25
  const me = options.meQuery();
18
- const listenersRef = useRef(new Set());
26
+ const latest = useRef({ actions, options });
27
+ latest.current = { actions, options };
19
28
  const stateRef = useRef(LOADING);
20
- // Derive current state
21
- let currentState;
22
- if (isLoading) {
23
- currentState = LOADING;
24
- }
25
- else if (isAuthenticated && me) {
26
- currentState = {
27
- status: 'authenticated',
28
- session: {
29
- id: `convex-${me.id}`,
30
- expiresAt: new Date(Date.now() + 86_400_000), // Synthetic — 24h
31
- },
32
- user: me,
33
- };
34
- if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'development') {
35
- // Dev-only warning for synthetic expiresAt
36
- console.debug('[afd-auth] Convex adapter uses synthetic expiresAt — token lifecycle managed by Convex internally');
37
- }
38
- }
39
- else {
40
- currentState = UNAUTHENTICATED;
41
- }
42
- // Notify listeners on state change
43
- const prevStatusRef = useRef(stateRef.current.status);
29
+ const notifiedStateRef = useRef(LOADING);
30
+ const [listeners] = useState(() => new ListenerSet((error) => reportListenerError(error, latest.current.options.onListenerError)));
31
+ // Keep the previous object when its values are unchanged. Auth hooks may
32
+ // rerender for unrelated Convex data, and useSyncExternalStore requires a
33
+ // cached snapshot in that case.
34
+ const previousState = stateRef.current;
35
+ const nextState = deriveState(previousState, isLoading, isAuthenticated, me);
36
+ const currentState = areSessionStatesEqual(previousState, nextState) ? previousState : nextState;
44
37
  stateRef.current = currentState;
45
38
  useEffect(() => {
46
- if (prevStatusRef.current !== currentState.status) {
47
- prevStatusRef.current = currentState.status;
48
- for (const listener of listenersRef.current) {
49
- listener(currentState);
50
- }
51
- }
52
- }, [currentState]);
53
- const signIn = useCallback(async (opts) => {
54
- if (opts.method === 'credentials') {
55
- await convexSignIn('credentials', { email: opts.email, password: opts.password });
39
+ if (!areSessionStatesEqual(notifiedStateRef.current, currentState)) {
40
+ notifiedStateRef.current = currentState;
41
+ listeners.emit(currentState);
56
42
  }
57
- else {
58
- await convexSignIn(opts.provider);
43
+ }, [currentState, listeners]);
44
+ const [adapter] = useState(() => ({
45
+ signIn: (signInOptions) => signInWithConvex(latest.current.actions, latest.current.options.passwordProviderId ?? DEFAULT_PASSWORD_PROVIDER_ID, signInOptions),
46
+ signOut: async () => {
47
+ try {
48
+ await latest.current.actions.signOut();
49
+ }
50
+ catch (error) {
51
+ throw mapConvexError(error, false);
52
+ }
53
+ },
54
+ getSession: () => stateRef.current,
55
+ onAuthStateChange: (callback) => listeners.add(callback),
56
+ }));
57
+ return adapter;
58
+ }
59
+ function deriveState(previous, isLoading, isAuthenticated, me) {
60
+ if (isLoading)
61
+ return LOADING;
62
+ if (!isAuthenticated || me === null)
63
+ return UNAUTHENTICATED;
64
+ // The token is valid but the user query has not resolved yet.
65
+ if (me === undefined)
66
+ return LOADING;
67
+ const previousUser = previous.status === 'authenticated' ? previous.user : null;
68
+ return {
69
+ status: 'authenticated',
70
+ // Convex refreshes its JWT internally and does not expose an expiry, so
71
+ // the session carries no expiresAt rather than an invented one.
72
+ session: previous.status === 'authenticated' && previousUser?.id === me.id
73
+ ? previous.session
74
+ : { id: `convex-${me.id}` },
75
+ user: previousUser && areUsersEqual(previousUser, me) ? previousUser : me,
76
+ };
77
+ }
78
+ async function signInWithConvex(actions, passwordProviderId, options) {
79
+ const request = toSignInRequest(passwordProviderId, options);
80
+ try {
81
+ return toSignInOutcome(await actions.signIn(...request));
82
+ }
83
+ catch (error) {
84
+ throw mapConvexError(error, options.method === 'credentials');
85
+ }
86
+ }
87
+ /**
88
+ * The stock Password provider signs in with `flow: 'signIn'`. OAuth providers
89
+ * take only `redirectTo`; their scopes are part of the server-side provider
90
+ * config, so scopes passed at sign-in are rejected rather than dropped.
91
+ */
92
+ function toSignInRequest(passwordProviderId, options) {
93
+ if (options.method === 'credentials') {
94
+ if (options.password === undefined) {
95
+ throw new AuthAdapterError({
96
+ code: 'INVALID_CREDENTIALS',
97
+ message: 'A password is required to sign in with the Convex Password provider',
98
+ suggestion: 'Provide the account password and try again',
99
+ });
59
100
  }
60
- }, [convexSignIn]);
61
- const signOut = useCallback(async () => {
62
- await convexSignOut();
63
- }, [convexSignOut]);
64
- const getSession = useCallback(() => {
65
- return stateRef.current;
66
- }, []);
67
- const onAuthStateChange = useCallback((callback) => {
68
- listenersRef.current.add(callback);
69
- return {
70
- unsubscribe: () => {
71
- listenersRef.current.delete(callback);
72
- },
73
- };
74
- }, []);
75
- return { signIn, signOut, getSession, onAuthStateChange };
101
+ return [
102
+ passwordProviderId,
103
+ { email: options.email, password: options.password, flow: 'signIn' },
104
+ ];
105
+ }
106
+ if (options.scopes !== undefined && options.scopes.length > 0) {
107
+ throw new AuthAdapterError({
108
+ code: 'PROVIDER_ERROR',
109
+ message: 'Convex Auth does not accept OAuth scopes at sign-in',
110
+ suggestion: `Configure scopes on the '${options.provider}' provider in convex/auth.ts, then sign in without scopes`,
111
+ });
112
+ }
113
+ return options.redirectTo === undefined
114
+ ? [options.provider]
115
+ : [options.provider, { redirectTo: options.redirectTo }];
116
+ }
117
+ /**
118
+ * @convex-dev/auth resolves signIn() with `{ signingIn, redirect? }`: a
119
+ * redirect starts an OAuth flow, and `signingIn: false` without one means a
120
+ * further step (such as email verification) is needed.
121
+ */
122
+ function toSignInOutcome(result) {
123
+ if (typeof result !== 'object' || result === null)
124
+ return { kind: 'signed-in' };
125
+ const redirect = 'redirect' in result ? result.redirect : undefined;
126
+ if (redirect instanceof URL)
127
+ return { kind: 'redirect', url: redirect.href };
128
+ if (typeof redirect === 'string')
129
+ return { kind: 'redirect', url: redirect };
130
+ if ('signingIn' in result && result.signingIn === false)
131
+ return { kind: 'pending' };
132
+ return { kind: 'signed-in' };
133
+ }
134
+ /**
135
+ * Map a Convex error to the codes the other adapters use. The Password
136
+ * provider fails with `InvalidAccountId`, `InvalidSecret` or
137
+ * `Invalid credentials`, and the account lock with `TooManyFailedAttempts`.
138
+ * Production deployments hide server error text unless it is thrown as a
139
+ * `ConvexError`, so those failures surface as PROVIDER_ERROR.
140
+ */
141
+ function mapConvexError(error, credentials) {
142
+ if (error instanceof AuthAdapterError)
143
+ return error;
144
+ const message = describeThrown(error);
145
+ if (credentials && /InvalidAccountId|InvalidSecret|Invalid credentials/i.test(message)) {
146
+ return AuthAdapterError.invalidCredentials();
147
+ }
148
+ if (/TooManyFailedAttempts/.test(message)) {
149
+ return new AuthAdapterError({
150
+ code: 'PROVIDER_ERROR',
151
+ message: 'Too many failed sign-in attempts for this account',
152
+ suggestion: 'Wait before trying again, or reset the password',
153
+ });
154
+ }
155
+ if (isKnownNetworkFailure(error, message)) {
156
+ return AuthAdapterError.networkError();
157
+ }
158
+ return AuthAdapterError.providerError('convex', message);
76
159
  }
77
160
  //# sourceMappingURL=convex.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"convex.js","sourceRoot":"","sources":["../../src/adapters/convex.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"convex.js","sourceRoot":"","sources":["../../src/adapters/convex.ts"],"names":[],"mappings":"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"}
@@ -2,24 +2,36 @@
2
2
  * @fileoverview Mock auth adapter for testing
3
3
  */
4
4
  import { AuthAdapterError } from '../errors.js';
5
- import type { AuthAdapter, AuthSessionState, SignInOptions, User } from '../types.js';
5
+ import { type ListenerErrorHandler } from '../listeners.js';
6
+ import type { AuthAdapter, AuthSessionState, Session, SignInOptions, SignInOutcome, User } from '../types.js';
6
7
  export interface MockAuthAdapterOptions {
7
8
  /** Simulated async delay in milliseconds (default: 0) */
8
9
  delay?: number;
10
+ /**
11
+ * Receives errors thrown by `onAuthStateChange` subscribers. Without it,
12
+ * they are rethrown in a microtask. Either way the other subscribers still
13
+ * run and the adapter method that changed the state does not reject.
14
+ */
15
+ onListenerError?: ListenerErrorHandler;
9
16
  }
10
17
  export declare class MockAuthAdapter implements AuthAdapter {
11
18
  private state;
12
- private listeners;
19
+ private readonly listeners;
13
20
  private readonly delay;
14
21
  constructor(options?: MockAuthAdapterOptions);
15
- signIn(options: SignInOptions): Promise<void>;
22
+ signIn(options: SignInOptions): Promise<SignInOutcome>;
16
23
  signOut(): Promise<void>;
17
24
  getSession(): AuthSessionState;
18
25
  onAuthStateChange(callback: (state: AuthSessionState) => void): {
19
26
  unsubscribe: () => void;
20
27
  };
21
28
  _reset(): void;
22
- _setUser(user: User): void;
29
+ /**
30
+ * Sign in as `user`. The session expires in one hour unless `session`
31
+ * overrides its fields, for example `{ expiresAt: new Date(0) }` for an
32
+ * expired session or `{ expiresAt: undefined }` for one without an expiry.
33
+ */
34
+ _setUser(user: User, session?: Partial<Session>): void;
23
35
  _setLoading(): void;
24
36
  _triggerError(code: 'INVALID_CREDENTIALS' | 'TOKEN_EXPIRED' | 'PROVIDER_ERROR' | 'NETWORK_ERROR' | 'REFRESH_FAILED'): AuthAdapterError;
25
37
  _getListenerCount(): number;
@@ -1 +1 @@
1
- {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/adapters/mock.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGtF,MAAM,WAAW,sBAAsB;IACtC,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,eAAgB,YAAW,WAAW;IAClD,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,SAAS,CAAgD;IACjE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,OAAO,GAAE,sBAA2B;IAI1C,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B,UAAU,IAAI,gBAAgB;IAI9B,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG;QAAE,WAAW,EAAE,MAAM,IAAI,CAAA;KAAE;IAa3F,MAAM,IAAI,IAAI;IAId,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAW1B,WAAW,IAAI,IAAI;IAInB,aAAa,CACZ,IAAI,EACD,qBAAqB,GACrB,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,gBAAgB,GACjB,gBAAgB;IAenB,iBAAiB,IAAI,MAAM;IAI3B,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,KAAK;CAGb"}
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/adapters/mock.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,KAAK,oBAAoB,EAAe,MAAM,iBAAiB,CAAC;AACzE,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,aAAa,EACb,aAAa,EACb,IAAI,EACJ,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,sBAAsB;IACtC,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,eAAe,CAAC,EAAE,oBAAoB,CAAC;CACvC;AAED,qBAAa,eAAgB,YAAW,WAAW;IAClD,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,OAAO,GAAE,sBAA2B;IAK1C,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAsBtD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B,UAAU,IAAI,gBAAgB;IAI9B,iBAAiB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAAG;QAAE,WAAW,EAAE,MAAM,IAAI,CAAA;KAAE;IAQ3F,MAAM,IAAI,IAAI;IAId;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,OAAO,CAAC,OAAO,CAAM,GAAG,IAAI;IAY1D,WAAW,IAAI,IAAI;IAInB,aAAa,CACZ,IAAI,EACD,qBAAqB,GACrB,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,gBAAgB,GACjB,gBAAgB;IAenB,iBAAiB,IAAI,MAAM;IAI3B,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,KAAK;CAGb"}
@@ -2,13 +2,15 @@
2
2
  * @fileoverview Mock auth adapter for testing
3
3
  */
4
4
  import { AuthAdapterError } from '../errors.js';
5
+ import { ListenerSet } from '../listeners.js';
5
6
  import { LOADING, UNAUTHENTICATED } from '../types.js';
6
7
  export class MockAuthAdapter {
7
8
  state = UNAUTHENTICATED;
8
- listeners = new Set();
9
+ listeners;
9
10
  delay;
10
11
  constructor(options = {}) {
11
12
  this.delay = options.delay ?? 0;
13
+ this.listeners = new ListenerSet(options.onListenerError);
12
14
  }
13
15
  async signIn(options) {
14
16
  if (this.delay > 0) {
@@ -27,6 +29,7 @@ export class MockAuthAdapter {
27
29
  name: email.split('@')[0],
28
30
  },
29
31
  });
32
+ return { kind: 'signed-in' };
30
33
  }
31
34
  async signOut() {
32
35
  if (this.delay > 0) {
@@ -38,12 +41,7 @@ export class MockAuthAdapter {
38
41
  return this.state;
39
42
  }
40
43
  onAuthStateChange(callback) {
41
- this.listeners.add(callback);
42
- return {
43
- unsubscribe: () => {
44
- this.listeners.delete(callback);
45
- },
46
- };
44
+ return this.listeners.add(callback);
47
45
  }
48
46
  // ═══════════════════════════════════════════════════════════════════════════
49
47
  // TEST HELPERS
@@ -51,12 +49,18 @@ export class MockAuthAdapter {
51
49
  _reset() {
52
50
  this.setState(UNAUTHENTICATED);
53
51
  }
54
- _setUser(user) {
52
+ /**
53
+ * Sign in as `user`. The session expires in one hour unless `session`
54
+ * overrides its fields, for example `{ expiresAt: new Date(0) }` for an
55
+ * expired session or `{ expiresAt: undefined }` for one without an expiry.
56
+ */
57
+ _setUser(user, session = {}) {
55
58
  this.setState({
56
59
  status: 'authenticated',
57
60
  session: {
58
61
  id: `mock-session-${Date.now()}`,
59
62
  expiresAt: new Date(Date.now() + 3600_000),
63
+ ...session,
60
64
  },
61
65
  user,
62
66
  });
@@ -83,9 +87,7 @@ export class MockAuthAdapter {
83
87
  }
84
88
  setState(state) {
85
89
  this.state = state;
86
- for (const listener of this.listeners) {
87
- listener(state);
88
- }
90
+ this.listeners.emit(state);
89
91
  }
90
92
  sleep(ms) {
91
93
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -1 +1 @@
1
- {"version":3,"file":"mock.js","sourceRoot":"","sources":["../../src/adapters/mock.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../../src/adapters/mock.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @fileoverview Helpers for classifying errors thrown by auth provider clients
3
+ */
4
+ /**
5
+ * Collect the readable text of a thrown value: the message, plus the `data`
6
+ * string of a Convex `ConvexError`, which carries the application's message
7
+ * when the deployment hides server error text.
8
+ */
9
+ export declare function describeThrown(error: unknown): string;
10
+ /**
11
+ * Whether a thrown value is a transport failure rather than a provider
12
+ * answer. Matches the fetch failure messages of Chrome, Firefox, Safari,
13
+ * undici and cross-fetch.
14
+ */
15
+ export declare function isKnownNetworkFailure(error: unknown, message: string): boolean;
16
+ //# sourceMappingURL=provider-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-errors.d.ts","sourceRoot":"","sources":["../../src/adapters/provider-errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOrD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAQ9E"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @fileoverview Helpers for classifying errors thrown by auth provider clients
3
+ */
4
+ /**
5
+ * Collect the readable text of a thrown value: the message, plus the `data`
6
+ * string of a Convex `ConvexError`, which carries the application's message
7
+ * when the deployment hides server error text.
8
+ */
9
+ export function describeThrown(error) {
10
+ const message = error instanceof Error ? error.message : String(error);
11
+ const data = typeof error === 'object' && error !== null && 'data' in error && typeof error.data === 'string'
12
+ ? error.data
13
+ : undefined;
14
+ return data === undefined || message.includes(data) ? message : `${message} (${data})`;
15
+ }
16
+ /**
17
+ * Whether a thrown value is a transport failure rather than a provider
18
+ * answer. Matches the fetch failure messages of Chrome, Firefox, Safari,
19
+ * undici and cross-fetch.
20
+ */
21
+ export function isKnownNetworkFailure(error, message) {
22
+ if (error instanceof Error && (error.name === 'NetworkError' || error.name === 'TimeoutError')) {
23
+ return true;
24
+ }
25
+ return /failed to fetch|fetch failed|load failed|networkerror when attempting to fetch|network (?:request )?failed|connection (?:refused|reset|closed)|request timed out|internet connection appears to be offline/i.test(message);
26
+ }
27
+ //# sourceMappingURL=provider-errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-errors.js","sourceRoot":"","sources":["../../src/adapters/provider-errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC5C,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,IAAI,GACT,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC/F,CAAC,CAAC,KAAK,CAAC,IAAI;QACZ,CAAC,CAAC,SAAS,CAAC;IACd,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,IAAI,GAAG,CAAC;AACxF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAc,EAAE,OAAe;IACpE,IAAI,KAAK,YAAY,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,EAAE,CAAC;QAChG,OAAO,IAAI,CAAC;IACb,CAAC;IAED,OAAO,6MAA6M,CAAC,IAAI,CACxN,OAAO,CACP,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @fileoverview Names of the built-in auth commands
3
+ *
4
+ * Kept apart from commands.ts so the middleware can use them without pulling
5
+ * in the optional `@lushly-dev/afd-server` and `zod` peer dependencies.
6
+ */
7
+ /**
8
+ * The commands created by `createAuthCommands`. `createAuthMiddleware` always
9
+ * lets them through, so a signed-out caller can sign in, sign out and read
10
+ * the session state.
11
+ */
12
+ export declare const AUTH_COMMAND_NAMES: readonly ["auth-sign-in", "auth-sign-out", "auth-session-get"];
13
+ //# sourceMappingURL=command-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-names.d.ts","sourceRoot":"","sources":["../src/command-names.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,gEAAiE,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @fileoverview Names of the built-in auth commands
3
+ *
4
+ * Kept apart from commands.ts so the middleware can use them without pulling
5
+ * in the optional `@lushly-dev/afd-server` and `zod` peer dependencies.
6
+ */
7
+ /**
8
+ * The commands created by `createAuthCommands`. `createAuthMiddleware` always
9
+ * lets them through, so a signed-out caller can sign in, sign out and read
10
+ * the session state.
11
+ */
12
+ export const AUTH_COMMAND_NAMES = ['auth-sign-in', 'auth-sign-out', 'auth-session-get'];
13
+ //# sourceMappingURL=command-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-names.js","sourceRoot":"","sources":["../src/command-names.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,cAAc,EAAE,eAAe,EAAE,kBAAkB,CAAU,CAAC"}
@@ -3,13 +3,22 @@
3
3
  *
4
4
  * Requires optional peer dependencies: @lushly-dev/afd-server, zod
5
5
  */
6
- import { type ZodCommandDefinition } from '@lushly-dev/afd-server';
6
+ import { type ZodCommandDefinition } from '@lushly-dev/afd-server/define';
7
7
  import type { AuthAdapter } from './types.js';
8
+ export interface AuthCommandsOptions {
9
+ /**
10
+ * How long `auth-sign-in` waits, after the adapter's `signIn()` resolves,
11
+ * for the adapter to report the new session through `onAuthStateChange`,
12
+ * in milliseconds (default: 10_000). When the wait runs out, the command
13
+ * returns the current state with a `SIGN_IN_PENDING` warning.
14
+ */
15
+ signInTimeoutMs?: number;
16
+ }
8
17
  /**
9
18
  * Create AFD command definitions for auth operations.
10
19
  *
11
20
  * Returns ZodCommandDefinition[] that can be passed directly to `createMcpServer`.
12
21
  * Requires `@lushly-dev/afd-server` and `zod` as peer dependencies.
13
22
  */
14
- export declare function createAuthCommands(adapter: AuthAdapter): ZodCommandDefinition[];
23
+ export declare function createAuthCommands(adapter: AuthAdapter, options?: AuthCommandsOptions): ZodCommandDefinition[];
15
24
  //# sourceMappingURL=commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAiB,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAGlF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,oBAAoB,EAAE,CA0F/E"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAIN,KAAK,oBAAoB,EACzB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,KAAK,EAAE,WAAW,EAAkD,MAAM,YAAY,CAAC;AAE9F,MAAM,WAAW,mBAAmB;IACnC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAKD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,mBAAwB,GAC/B,oBAAoB,EAAE,CAmGxB"}