@douvery/auth 0.3.3 → 0.4.1

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.
@@ -1,7 +1,46 @@
1
1
  import * as _builder_io_qwik from '@builder.io/qwik';
2
2
  import { Signal, NoSerialize, QRL } from '@builder.io/qwik';
3
- import { AuthState, DouveryAuthClient, DouveryAuthConfig, LoginOptions, LogoutOptions, SelectAccountOptions, AddAccountOptions, RegisterOptions, RecoverAccountOptions, VerifyAccountOptions, UpgradeAccountOptions, SetupPasskeyOptions, SetupAddressOptions, RevokeTokenOptions, AuthUrl, User } from '@douvery/auth';
4
- export { AddAccountOptions, AuthState, AuthUrl, DouveryAuthClient, DouveryAuthConfig, LoginOptions, LogoutOptions, RecoverAccountOptions, RegisterOptions, RevokeTokenOptions, SelectAccountOptions, SetupAddressOptions, SetupPasskeyOptions, UpgradeAccountOptions, User, VerifyAccountOptions, createDouveryAuth } from '@douvery/auth';
3
+ import { CookieAdapter, AuthState, DouveryAuthClient, DouveryAuthConfig, LoginOptions, LogoutOptions, SelectAccountOptions, AddAccountOptions, RegisterOptions, RecoverAccountOptions, VerifyAccountOptions, UpgradeAccountOptions, SetupPasskeyOptions, SetupAddressOptions, RevokeTokenOptions, AuthUrl, User } from '@douvery/auth';
4
+ export { AddAccountOptions, AuthState, AuthUrl, CookieAdapter, CookieSetOptions, DouveryAuthClient, DouveryAuthConfig, LoginOptions, LogoutOptions, RecoverAccountOptions, RegisterOptions, RevokeTokenOptions, SelectAccountOptions, SetupAddressOptions, SetupPasskeyOptions, UpgradeAccountOptions, User, VerifyAccountOptions, createDouveryAuth } from '@douvery/auth';
5
+
6
+ /**
7
+ * @douvery/auth/qwik - Session Adapter
8
+ *
9
+ * Adapts Qwik City's Cookie interface to the generic CookieAdapter
10
+ * used by createSessionResolver().
11
+ *
12
+ * Memoized: returns the same adapter instance for the same Cookie object,
13
+ * ensuring the resolver's per-request WeakMap cache works correctly when
14
+ * multiple routeLoaders call getAccessToken() in the same SSR request.
15
+ */
16
+
17
+ /**
18
+ * Qwik City Cookie-like interface.
19
+ * Duck-typed to avoid hard dependency on @builder.io/qwik-city.
20
+ */
21
+ interface QwikCookieLike {
22
+ get(name: string): {
23
+ value: string;
24
+ } | null;
25
+ set(name: string, value: string | number | Record<string, unknown>, options?: Record<string, unknown>): void;
26
+ }
27
+ /**
28
+ * Create a CookieAdapter from a Qwik City Cookie object.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * import { createQwikSessionAdapter } from '@douvery/auth/qwik';
33
+ * import { createSessionResolver } from '@douvery/auth/session';
34
+ *
35
+ * const resolver = createSessionResolver({ ... });
36
+ *
37
+ * export const useMyLoader = routeLoader$(async ({ cookie }) => {
38
+ * const adapter = createQwikSessionAdapter(cookie);
39
+ * const token = await resolver.getAccessToken(adapter);
40
+ * });
41
+ * ```
42
+ */
43
+ declare function createQwikSessionAdapter(cookie: QwikCookieLike): CookieAdapter;
5
44
 
6
45
  interface DouveryAuthContextValue {
7
46
  state: Signal<AuthState>;
@@ -86,4 +125,4 @@ declare function useAppUserActions<T = unknown>(): {
86
125
  refreshUser: QRL<() => Promise<void>>;
87
126
  };
88
127
 
89
- export { DouveryAuthContext, DouveryAuthProvider, type DouveryAuthProviderProps, useAppUser, useAppUserActions, useAuthActions, useAuthUrls, useDouveryAuth, useIsAuthenticated, useSessionStatus, useUser };
128
+ export { DouveryAuthContext, DouveryAuthProvider, type DouveryAuthProviderProps, createQwikSessionAdapter, useAppUser, useAppUserActions, useAuthActions, useAuthUrls, useDouveryAuth, useIsAuthenticated, useSessionStatus, useUser };
@@ -4,6 +4,23 @@ export { DouveryAuthClient, createDouveryAuth } from '@douvery/auth';
4
4
  import { jsx } from '@builder.io/qwik/jsx-runtime';
5
5
 
6
6
  // src/qwik/index.tsx
7
+
8
+ // src/qwik/session.ts
9
+ var adapterCache = /* @__PURE__ */ new WeakMap();
10
+ function createQwikSessionAdapter(cookie) {
11
+ let adapter = adapterCache.get(cookie);
12
+ if (adapter) return adapter;
13
+ adapter = {
14
+ get(name) {
15
+ return cookie.get(name)?.value ?? void 0;
16
+ },
17
+ set(name, value, options) {
18
+ cookie.set(name, value, options);
19
+ }
20
+ };
21
+ adapterCache.set(cookie, adapter);
22
+ return adapter;
23
+ }
7
24
  var DouveryAuthContext = createContextId("douvery-auth");
8
25
  var DEFAULT_STATE = {
9
26
  status: "unauthenticated",
@@ -35,7 +52,19 @@ var DouveryAuthProvider = component$(
35
52
  appUserAuthenticated
36
53
  });
37
54
  useVisibleTask$(async () => {
38
- const config = await config$();
55
+ let config;
56
+ try {
57
+ config = await config$();
58
+ } catch (err) {
59
+ error.value = err instanceof Error ? err : new Error(String(err));
60
+ return;
61
+ }
62
+ if (!config) {
63
+ error.value = new Error(
64
+ "[DouveryAuthProvider] config$() returned undefined. Check that the QRL correctly returns a DouveryAuthConfig object."
65
+ );
66
+ return;
67
+ }
39
68
  const client = createDouveryAuth(config);
40
69
  clientRef.value = noSerialize(client);
41
70
  try {
@@ -259,6 +288,6 @@ function useAppUserActions() {
259
288
  };
260
289
  }
261
290
 
262
- export { DouveryAuthContext, DouveryAuthProvider, useAppUser, useAppUserActions, useAuthActions, useAuthUrls, useDouveryAuth, useIsAuthenticated, useSessionStatus, useUser };
291
+ export { DouveryAuthContext, DouveryAuthProvider, createQwikSessionAdapter, useAppUser, useAppUserActions, useAuthActions, useAuthUrls, useDouveryAuth, useIsAuthenticated, useSessionStatus, useUser };
263
292
  //# sourceMappingURL=index.js.map
264
293
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/qwik/index.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @douvery/auth/qwik - Qwik adapter\n *\n * Uses QRL for config to avoid Qwik serialization issues with\n * function-based storage adapters (customStorage).\n * The client is created inside useVisibleTask$ and wrapped with\n * noSerialize() since DouveryAuthClient has non-serializable methods.\n */\n\nimport {\n createContextId,\n useContextProvider,\n useContext,\n useSignal,\n useTask$,\n useVisibleTask$,\n component$,\n $,\n Slot,\n noSerialize,\n type Signal,\n type NoSerialize,\n type QRL,\n} from \"@builder.io/qwik\";\nimport {\n DouveryAuthClient,\n createDouveryAuth,\n type DouveryAuthConfig,\n type AuthState,\n type User,\n type LoginOptions,\n type LogoutOptions,\n type SelectAccountOptions,\n type RegisterOptions,\n type RecoverAccountOptions,\n type VerifyAccountOptions,\n type UpgradeAccountOptions,\n type SetupPasskeyOptions,\n type SetupAddressOptions,\n type AddAccountOptions,\n type RevokeTokenOptions,\n type AuthUrl,\n} from \"@douvery/auth\";\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface DouveryAuthContextValue {\n state: Signal<AuthState>;\n isInitialized: Signal<boolean>;\n isLoading: Signal<boolean>;\n error: Signal<Error | null>;\n clientRef: Signal<NoSerialize<DouveryAuthClient> | undefined>;\n /** Application-specific user data from SSR (e.g. routeLoader$). */\n appUser: Signal<unknown>;\n appUserAuthenticated: Signal<boolean>;\n}\n\nexport const DouveryAuthContext =\n createContextId<DouveryAuthContextValue>(\"douvery-auth\");\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport interface DouveryAuthProviderProps {\n /**\n * QRL that returns the auth configuration.\n * Use $(() => getDouveryAuthConfig()) to wrap your config factory.\n * This avoids Qwik serialization issues with customStorage functions.\n */\n config$: QRL<() => DouveryAuthConfig>;\n /**\n * Optional application-specific user data loaded from SSR (routeLoader$).\n * This is separate from OAuth user – it holds the full app user object\n * (e.g. UserACC with address, active, sessionId, etc.).\n * Pass the routeLoader$ signal directly.\n */\n appUser?: Signal<unknown>;\n}\n\nconst DEFAULT_STATE: AuthState = {\n status: \"unauthenticated\",\n user: null,\n tokens: null,\n error: null,\n};\n\nexport const DouveryAuthProvider = component$<DouveryAuthProviderProps>(\n ({ config$, appUser: externalAppUser }) => {\n // All signals are serializable - no functions stored directly\n const state = useSignal<AuthState>(DEFAULT_STATE);\n const isInitialized = useSignal(false);\n const isLoading = useSignal(false);\n const error = useSignal<Error | null>(null);\n const clientRef = useSignal<NoSerialize<DouveryAuthClient>>();\n\n // App user data: use external signal if provided, otherwise create internal one\n const internalAppUser = useSignal<unknown>(externalAppUser?.value ?? null);\n const appUser = externalAppUser ?? internalAppUser;\n const appUserAuthenticated = useSignal<boolean>(!!appUser.value);\n\n // Keep appUserAuthenticated in sync\n useTask$(({ track }) => {\n const u = track(() => appUser.value);\n appUserAuthenticated.value = !!u;\n });\n\n useContextProvider(DouveryAuthContext, {\n state,\n isInitialized,\n isLoading,\n error,\n clientRef,\n appUser,\n appUserAuthenticated,\n });\n\n // Client creation deferred to browser-only task.\n // The QRL is invoked here, returning the full config (with customStorage).\n // noSerialize() wraps the client so Qwik doesn't try to serialize it.\n useVisibleTask$(async () => {\n const config = await config$();\n const client = createDouveryAuth(config);\n clientRef.value = noSerialize(client);\n\n try {\n await client.initialize();\n isInitialized.value = true;\n state.value = client.getState();\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err));\n }\n\n const unsubscribe = client.subscribe((event) => {\n state.value = client.getState();\n if (\n event.type === \"LOGIN_ERROR\" ||\n event.type === \"LOGOUT_ERROR\" ||\n event.type === \"TOKEN_REFRESH_ERROR\"\n ) {\n error.value = event.error;\n }\n });\n\n return () => unsubscribe();\n });\n\n return <Slot />;\n },\n);\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport function useDouveryAuth() {\n return useContext(DouveryAuthContext);\n}\n\n/**\n * Internal helper: safely access the client from context.\n * Throws if the client hasn't been initialized yet (before useVisibleTask$ runs).\n */\nfunction getClient(ctx: DouveryAuthContextValue): DouveryAuthClient {\n const client = ctx.clientRef.value;\n if (!client) {\n throw new Error(\n \"DouveryAuth client not initialized. \" +\n \"Ensure DouveryAuthProvider is mounted and the page has hydrated.\",\n );\n }\n return client;\n}\n\nexport function useUser(): Signal<User | null> {\n const { state } = useDouveryAuth();\n const user = useSignal<User | null>(state.value.user);\n useTask$(({ track }) => {\n track(() => state.value);\n user.value = state.value.user;\n });\n return user;\n}\n\nexport function useIsAuthenticated(): Signal<boolean> {\n const { state } = useDouveryAuth();\n const isAuth = useSignal(state.value.status === \"authenticated\");\n useTask$(({ track }) => {\n track(() => state.value);\n isAuth.value = state.value.status === \"authenticated\";\n });\n return isAuth;\n}\n\nexport function useAuthActions() {\n const ctx = useDouveryAuth();\n const { isLoading, error } = ctx;\n\n const login = $(async (options?: LoginOptions) => {\n const client = getClient(ctx);\n isLoading.value = true;\n error.value = null;\n try {\n await client.login(options);\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err));\n throw err;\n } finally {\n isLoading.value = false;\n }\n });\n\n const logout = $(async (options?: LogoutOptions) => {\n const client = getClient(ctx);\n isLoading.value = true;\n error.value = null;\n try {\n await client.logout(options);\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err));\n throw err;\n } finally {\n isLoading.value = false;\n }\n });\n\n const selectAccount = $((options?: SelectAccountOptions) => {\n getClient(ctx).selectAccount(options);\n });\n\n const addAccount = $((options?: AddAccountOptions) => {\n getClient(ctx).addAccount(options);\n });\n\n const register = $((options?: RegisterOptions) => {\n getClient(ctx).register(options);\n });\n\n const recoverAccount = $((options?: RecoverAccountOptions) => {\n getClient(ctx).recoverAccount(options);\n });\n\n const verifyAccount = $((options?: VerifyAccountOptions) => {\n getClient(ctx).verifyAccount(options);\n });\n\n const upgradeAccount = $((options?: UpgradeAccountOptions) => {\n getClient(ctx).upgradeAccount(options);\n });\n\n const setupPasskey = $((options?: SetupPasskeyOptions) => {\n getClient(ctx).setupPasskey(options);\n });\n\n const setupAddress = $((options?: SetupAddressOptions) => {\n getClient(ctx).setupAddress(options);\n });\n\n const revokeToken = $(async (options?: RevokeTokenOptions) => {\n const client = getClient(ctx);\n isLoading.value = true;\n error.value = null;\n try {\n await client.revokeToken(options);\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err));\n throw err;\n } finally {\n isLoading.value = false;\n }\n });\n\n return {\n login,\n logout,\n selectAccount,\n addAccount,\n register,\n recoverAccount,\n verifyAccount,\n upgradeAccount,\n setupPasskey,\n setupAddress,\n revokeToken,\n isLoading,\n };\n}\n\n/** Get URL builders for auth pages (non-redirecting, useful for <a> tags) */\nexport function useAuthUrls() {\n const ctx = useDouveryAuth();\n return {\n loginUrl: $(\n (options?: LoginOptions): AuthUrl =>\n getClient(ctx).buildLoginUrl(options),\n ),\n logoutUrl: $(\n (options?: LogoutOptions): AuthUrl =>\n getClient(ctx).buildLogoutUrl(options),\n ),\n selectAccountUrl: $(\n (options?: SelectAccountOptions): AuthUrl =>\n getClient(ctx).buildSelectAccountUrl(options),\n ),\n addAccountUrl: $(\n (options?: AddAccountOptions): AuthUrl =>\n getClient(ctx).buildAddAccountUrl(options),\n ),\n registerUrl: $(\n (options?: RegisterOptions): AuthUrl =>\n getClient(ctx).buildRegisterUrl(options),\n ),\n recoverAccountUrl: $(\n (options?: RecoverAccountOptions): AuthUrl =>\n getClient(ctx).buildRecoverAccountUrl(options),\n ),\n verifyAccountUrl: $(\n (options?: VerifyAccountOptions): AuthUrl =>\n getClient(ctx).buildVerifyAccountUrl(options),\n ),\n upgradeAccountUrl: $(\n (options?: UpgradeAccountOptions): AuthUrl =>\n getClient(ctx).buildUpgradeAccountUrl(options),\n ),\n setupPasskeyUrl: $(\n (options?: SetupPasskeyOptions): AuthUrl =>\n getClient(ctx).buildSetupPasskeyUrl(options),\n ),\n setupAddressUrl: $(\n (options?: SetupAddressOptions): AuthUrl =>\n getClient(ctx).buildSetupAddressUrl(options),\n ),\n };\n}\n\n/** Get session status helpers */\nexport function useSessionStatus() {\n const ctx = useDouveryAuth();\n const { state } = ctx;\n const c = ctx.clientRef.value;\n const isExpired = useSignal(c ? c.isSessionExpired() : false);\n const needsVerification = useSignal(c ? c.needsEmailVerification() : false);\n const isGuest = useSignal(c ? c.isGuestAccount() : false);\n\n useTask$(({ track }) => {\n track(() => state.value);\n const client = ctx.clientRef.value;\n if (client) {\n isExpired.value = client.isSessionExpired();\n needsVerification.value = client.needsEmailVerification();\n isGuest.value = client.isGuestAccount();\n }\n });\n\n return { isExpired, needsVerification, isGuest };\n}\n\n// ============================================================================\n// App User hooks\n// ============================================================================\n\n/**\n * Returns the application-specific user data provided via `appUser` prop.\n * Cast to your app's user type: `const user = useAppUser<UserACC>()`.\n * Returns `{ user: Signal<T | null>, isAuthenticated: Signal<boolean> }`.\n */\nexport function useAppUser<T = unknown>() {\n const { appUser, appUserAuthenticated } = useDouveryAuth();\n return {\n user: appUser as Signal<T | null>,\n isAuthenticated: appUserAuthenticated,\n };\n}\n\n/**\n * Full app user context with refresh capabilities.\n * Use when you need to re-fetch user data from the server.\n */\nexport function useAppUserActions<T = unknown>() {\n const { appUser, appUserAuthenticated } = useDouveryAuth();\n\n const updateUser = $((userData: T | null) => {\n (appUser as Signal<T | null>).value = userData;\n appUserAuthenticated.value = !!userData;\n });\n\n const refreshUser = $(async () => {\n try {\n const response = await fetch(\"/api/auth/me\", {\n method: \"GET\",\n credentials: \"include\",\n headers: { \"Cache-Control\": \"no-cache\", Pragma: \"no-cache\" },\n });\n\n if (response.ok) {\n const data = await response.json();\n (appUser as Signal<T | null>).value = data.user;\n appUserAuthenticated.value = true;\n } else if (response.status === 401 || response.status === 403) {\n (appUser as Signal<T | null>).value = null;\n appUserAuthenticated.value = false;\n }\n } catch {\n // Network error: keep current state\n }\n });\n\n return {\n user: appUser as Signal<T | null>,\n isAuthenticated: appUserAuthenticated,\n updateUser,\n refreshUser,\n };\n}\n\n// ============================================================================\n// Re-exports\n// ============================================================================\n\nexport { DouveryAuthClient, createDouveryAuth } from \"@douvery/auth\";\nexport type {\n DouveryAuthConfig,\n AuthState,\n User,\n LoginOptions,\n LogoutOptions,\n SelectAccountOptions,\n RegisterOptions,\n RecoverAccountOptions,\n VerifyAccountOptions,\n UpgradeAccountOptions,\n SetupPasskeyOptions,\n SetupAddressOptions,\n AddAccountOptions,\n RevokeTokenOptions,\n AuthUrl,\n} from \"@douvery/auth\";\n"]}
1
+ {"version":3,"sources":["../../src/qwik/session.ts","../../src/qwik/index.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @douvery/auth/qwik - Session Adapter\n *\n * Adapts Qwik City's Cookie interface to the generic CookieAdapter\n * used by createSessionResolver().\n *\n * Memoized: returns the same adapter instance for the same Cookie object,\n * ensuring the resolver's per-request WeakMap cache works correctly when\n * multiple routeLoaders call getAccessToken() in the same SSR request.\n */\n\nimport type { CookieAdapter, CookieSetOptions } from \"@douvery/auth\";\n\n/**\n * Qwik City Cookie-like interface.\n * Duck-typed to avoid hard dependency on @builder.io/qwik-city.\n */\ninterface QwikCookieLike {\n get(name: string): { value: string } | null;\n set(\n name: string,\n value: string | number | Record<string, unknown>,\n options?: Record<string, unknown>,\n ): void;\n}\n\n/**\n * Adapter cache ensures the SAME CookieAdapter instance is returned\n * for the same Qwik Cookie object. This is critical because:\n *\n * 1. The resolver uses WeakMap<CookieAdapter> for per-request caching\n * 2. Multiple routeLoaders in the same SSR request share the same Cookie\n * 3. Each routeLoader calls createQwikSessionAdapter(cookie)\n * 4. Without memoization, each call would create a different object\n * → WeakMap would fail to deduplicate → duplicate network calls\n */\nconst adapterCache = new WeakMap<object, CookieAdapter>();\n\n/**\n * Create a CookieAdapter from a Qwik City Cookie object.\n *\n * @example\n * ```typescript\n * import { createQwikSessionAdapter } from '@douvery/auth/qwik';\n * import { createSessionResolver } from '@douvery/auth/session';\n *\n * const resolver = createSessionResolver({ ... });\n *\n * export const useMyLoader = routeLoader$(async ({ cookie }) => {\n * const adapter = createQwikSessionAdapter(cookie);\n * const token = await resolver.getAccessToken(adapter);\n * });\n * ```\n */\nexport function createQwikSessionAdapter(\n cookie: QwikCookieLike,\n): CookieAdapter {\n let adapter = adapterCache.get(cookie);\n if (adapter) return adapter;\n\n adapter = {\n get(name: string): string | undefined {\n return cookie.get(name)?.value ?? undefined;\n },\n set(name: string, value: string, options: CookieSetOptions): void {\n cookie.set(name, value, options as Record<string, unknown>);\n },\n };\n\n adapterCache.set(cookie, adapter);\n return adapter;\n}\n","/**\n * @douvery/auth/qwik - Qwik adapter\n *\n * Uses QRL for config to avoid Qwik serialization issues with\n * function-based storage adapters (customStorage).\n * The client is created inside useVisibleTask$ and wrapped with\n * noSerialize() since DouveryAuthClient has non-serializable methods.\n */\n\nimport {\n createContextId,\n useContextProvider,\n useContext,\n useSignal,\n useTask$,\n useVisibleTask$,\n component$,\n $,\n Slot,\n noSerialize,\n type Signal,\n type NoSerialize,\n type QRL,\n} from \"@builder.io/qwik\";\nimport {\n DouveryAuthClient,\n createDouveryAuth,\n type DouveryAuthConfig,\n type AuthState,\n type User,\n type LoginOptions,\n type LogoutOptions,\n type SelectAccountOptions,\n type RegisterOptions,\n type RecoverAccountOptions,\n type VerifyAccountOptions,\n type UpgradeAccountOptions,\n type SetupPasskeyOptions,\n type SetupAddressOptions,\n type AddAccountOptions,\n type RevokeTokenOptions,\n type AuthUrl,\n} from \"@douvery/auth\";\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface DouveryAuthContextValue {\n state: Signal<AuthState>;\n isInitialized: Signal<boolean>;\n isLoading: Signal<boolean>;\n error: Signal<Error | null>;\n clientRef: Signal<NoSerialize<DouveryAuthClient> | undefined>;\n /** Application-specific user data from SSR (e.g. routeLoader$). */\n appUser: Signal<unknown>;\n appUserAuthenticated: Signal<boolean>;\n}\n\nexport const DouveryAuthContext =\n createContextId<DouveryAuthContextValue>(\"douvery-auth\");\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport interface DouveryAuthProviderProps {\n /**\n * QRL that returns the auth configuration.\n * Use $(() => getDouveryAuthConfig()) to wrap your config factory.\n * This avoids Qwik serialization issues with customStorage functions.\n */\n config$: QRL<() => DouveryAuthConfig>;\n /**\n * Optional application-specific user data loaded from SSR (routeLoader$).\n * This is separate from OAuth user – it holds the full app user object\n * (e.g. UserACC with address, active, sessionId, etc.).\n * Pass the routeLoader$ signal directly.\n */\n appUser?: Signal<unknown>;\n}\n\nconst DEFAULT_STATE: AuthState = {\n status: \"unauthenticated\",\n user: null,\n tokens: null,\n error: null,\n};\n\nexport const DouveryAuthProvider = component$<DouveryAuthProviderProps>(\n ({ config$, appUser: externalAppUser }) => {\n // All signals are serializable - no functions stored directly\n const state = useSignal<AuthState>(DEFAULT_STATE);\n const isInitialized = useSignal(false);\n const isLoading = useSignal(false);\n const error = useSignal<Error | null>(null);\n const clientRef = useSignal<NoSerialize<DouveryAuthClient>>();\n\n // App user data: use external signal if provided, otherwise create internal one\n const internalAppUser = useSignal<unknown>(externalAppUser?.value ?? null);\n const appUser = externalAppUser ?? internalAppUser;\n const appUserAuthenticated = useSignal<boolean>(!!appUser.value);\n\n // Keep appUserAuthenticated in sync\n useTask$(({ track }) => {\n const u = track(() => appUser.value);\n appUserAuthenticated.value = !!u;\n });\n\n useContextProvider(DouveryAuthContext, {\n state,\n isInitialized,\n isLoading,\n error,\n clientRef,\n appUser,\n appUserAuthenticated,\n });\n\n // Client creation deferred to browser-only task.\n // The QRL is invoked here, returning the full config (with customStorage).\n // noSerialize() wraps the client so Qwik doesn't try to serialize it.\n useVisibleTask$(async () => {\n let config: DouveryAuthConfig | undefined;\n try {\n config = await config$();\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err));\n return;\n }\n\n if (!config) {\n error.value = new Error(\n \"[DouveryAuthProvider] config$() returned undefined. \" +\n \"Check that the QRL correctly returns a DouveryAuthConfig object.\",\n );\n return;\n }\n\n const client = createDouveryAuth(config);\n clientRef.value = noSerialize(client);\n\n try {\n await client.initialize();\n isInitialized.value = true;\n state.value = client.getState();\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err));\n }\n\n const unsubscribe = client.subscribe((event) => {\n state.value = client.getState();\n if (\n event.type === \"LOGIN_ERROR\" ||\n event.type === \"LOGOUT_ERROR\" ||\n event.type === \"TOKEN_REFRESH_ERROR\"\n ) {\n error.value = event.error;\n }\n });\n\n return () => unsubscribe();\n });\n\n return <Slot />;\n },\n);\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport function useDouveryAuth() {\n return useContext(DouveryAuthContext);\n}\n\n/**\n * Internal helper: safely access the client from context.\n * Throws if the client hasn't been initialized yet (before useVisibleTask$ runs).\n */\nfunction getClient(ctx: DouveryAuthContextValue): DouveryAuthClient {\n const client = ctx.clientRef.value;\n if (!client) {\n throw new Error(\n \"DouveryAuth client not initialized. \" +\n \"Ensure DouveryAuthProvider is mounted and the page has hydrated.\",\n );\n }\n return client;\n}\n\nexport function useUser(): Signal<User | null> {\n const { state } = useDouveryAuth();\n const user = useSignal<User | null>(state.value.user);\n useTask$(({ track }) => {\n track(() => state.value);\n user.value = state.value.user;\n });\n return user;\n}\n\nexport function useIsAuthenticated(): Signal<boolean> {\n const { state } = useDouveryAuth();\n const isAuth = useSignal(state.value.status === \"authenticated\");\n useTask$(({ track }) => {\n track(() => state.value);\n isAuth.value = state.value.status === \"authenticated\";\n });\n return isAuth;\n}\n\nexport function useAuthActions() {\n const ctx = useDouveryAuth();\n const { isLoading, error } = ctx;\n\n const login = $(async (options?: LoginOptions) => {\n const client = getClient(ctx);\n isLoading.value = true;\n error.value = null;\n try {\n await client.login(options);\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err));\n throw err;\n } finally {\n isLoading.value = false;\n }\n });\n\n const logout = $(async (options?: LogoutOptions) => {\n const client = getClient(ctx);\n isLoading.value = true;\n error.value = null;\n try {\n await client.logout(options);\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err));\n throw err;\n } finally {\n isLoading.value = false;\n }\n });\n\n const selectAccount = $((options?: SelectAccountOptions) => {\n getClient(ctx).selectAccount(options);\n });\n\n const addAccount = $((options?: AddAccountOptions) => {\n getClient(ctx).addAccount(options);\n });\n\n const register = $((options?: RegisterOptions) => {\n getClient(ctx).register(options);\n });\n\n const recoverAccount = $((options?: RecoverAccountOptions) => {\n getClient(ctx).recoverAccount(options);\n });\n\n const verifyAccount = $((options?: VerifyAccountOptions) => {\n getClient(ctx).verifyAccount(options);\n });\n\n const upgradeAccount = $((options?: UpgradeAccountOptions) => {\n getClient(ctx).upgradeAccount(options);\n });\n\n const setupPasskey = $((options?: SetupPasskeyOptions) => {\n getClient(ctx).setupPasskey(options);\n });\n\n const setupAddress = $((options?: SetupAddressOptions) => {\n getClient(ctx).setupAddress(options);\n });\n\n const revokeToken = $(async (options?: RevokeTokenOptions) => {\n const client = getClient(ctx);\n isLoading.value = true;\n error.value = null;\n try {\n await client.revokeToken(options);\n } catch (err) {\n error.value = err instanceof Error ? err : new Error(String(err));\n throw err;\n } finally {\n isLoading.value = false;\n }\n });\n\n return {\n login,\n logout,\n selectAccount,\n addAccount,\n register,\n recoverAccount,\n verifyAccount,\n upgradeAccount,\n setupPasskey,\n setupAddress,\n revokeToken,\n isLoading,\n };\n}\n\n/** Get URL builders for auth pages (non-redirecting, useful for <a> tags) */\nexport function useAuthUrls() {\n const ctx = useDouveryAuth();\n return {\n loginUrl: $(\n (options?: LoginOptions): AuthUrl =>\n getClient(ctx).buildLoginUrl(options),\n ),\n logoutUrl: $(\n (options?: LogoutOptions): AuthUrl =>\n getClient(ctx).buildLogoutUrl(options),\n ),\n selectAccountUrl: $(\n (options?: SelectAccountOptions): AuthUrl =>\n getClient(ctx).buildSelectAccountUrl(options),\n ),\n addAccountUrl: $(\n (options?: AddAccountOptions): AuthUrl =>\n getClient(ctx).buildAddAccountUrl(options),\n ),\n registerUrl: $(\n (options?: RegisterOptions): AuthUrl =>\n getClient(ctx).buildRegisterUrl(options),\n ),\n recoverAccountUrl: $(\n (options?: RecoverAccountOptions): AuthUrl =>\n getClient(ctx).buildRecoverAccountUrl(options),\n ),\n verifyAccountUrl: $(\n (options?: VerifyAccountOptions): AuthUrl =>\n getClient(ctx).buildVerifyAccountUrl(options),\n ),\n upgradeAccountUrl: $(\n (options?: UpgradeAccountOptions): AuthUrl =>\n getClient(ctx).buildUpgradeAccountUrl(options),\n ),\n setupPasskeyUrl: $(\n (options?: SetupPasskeyOptions): AuthUrl =>\n getClient(ctx).buildSetupPasskeyUrl(options),\n ),\n setupAddressUrl: $(\n (options?: SetupAddressOptions): AuthUrl =>\n getClient(ctx).buildSetupAddressUrl(options),\n ),\n };\n}\n\n/** Get session status helpers */\nexport function useSessionStatus() {\n const ctx = useDouveryAuth();\n const { state } = ctx;\n const c = ctx.clientRef.value;\n const isExpired = useSignal(c ? c.isSessionExpired() : false);\n const needsVerification = useSignal(c ? c.needsEmailVerification() : false);\n const isGuest = useSignal(c ? c.isGuestAccount() : false);\n\n useTask$(({ track }) => {\n track(() => state.value);\n const client = ctx.clientRef.value;\n if (client) {\n isExpired.value = client.isSessionExpired();\n needsVerification.value = client.needsEmailVerification();\n isGuest.value = client.isGuestAccount();\n }\n });\n\n return { isExpired, needsVerification, isGuest };\n}\n\n// ============================================================================\n// App User hooks\n// ============================================================================\n\n/**\n * Returns the application-specific user data provided via `appUser` prop.\n * Cast to your app's user type: `const user = useAppUser<UserACC>()`.\n * Returns `{ user: Signal<T | null>, isAuthenticated: Signal<boolean> }`.\n */\nexport function useAppUser<T = unknown>() {\n const { appUser, appUserAuthenticated } = useDouveryAuth();\n return {\n user: appUser as Signal<T | null>,\n isAuthenticated: appUserAuthenticated,\n };\n}\n\n/**\n * Full app user context with refresh capabilities.\n * Use when you need to re-fetch user data from the server.\n */\nexport function useAppUserActions<T = unknown>() {\n const { appUser, appUserAuthenticated } = useDouveryAuth();\n\n const updateUser = $((userData: T | null) => {\n (appUser as Signal<T | null>).value = userData;\n appUserAuthenticated.value = !!userData;\n });\n\n const refreshUser = $(async () => {\n try {\n const response = await fetch(\"/api/auth/me\", {\n method: \"GET\",\n credentials: \"include\",\n headers: { \"Cache-Control\": \"no-cache\", Pragma: \"no-cache\" },\n });\n\n if (response.ok) {\n const data = await response.json();\n (appUser as Signal<T | null>).value = data.user;\n appUserAuthenticated.value = true;\n } else if (response.status === 401 || response.status === 403) {\n (appUser as Signal<T | null>).value = null;\n appUserAuthenticated.value = false;\n }\n } catch {\n // Network error: keep current state\n }\n });\n\n return {\n user: appUser as Signal<T | null>,\n isAuthenticated: appUserAuthenticated,\n updateUser,\n refreshUser,\n };\n}\n\n// ============================================================================\n// Re-exports\n// ============================================================================\n\nexport { DouveryAuthClient, createDouveryAuth } from \"@douvery/auth\";\nexport type {\n DouveryAuthConfig,\n AuthState,\n User,\n LoginOptions,\n LogoutOptions,\n SelectAccountOptions,\n RegisterOptions,\n RecoverAccountOptions,\n VerifyAccountOptions,\n UpgradeAccountOptions,\n SetupPasskeyOptions,\n SetupAddressOptions,\n AddAccountOptions,\n RevokeTokenOptions,\n AuthUrl,\n CookieAdapter,\n CookieSetOptions,\n} from \"@douvery/auth\";\n\n// Session adapter for Qwik City\nexport { createQwikSessionAdapter } from \"./session\";\n"]}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * @douvery/auth - Session Types
3
+ * Framework-agnostic opaque session resolution types
4
+ */
5
+ /** Configuration for the session resolver factory */
6
+ interface SessionResolverConfig {
7
+ /** Auth server session API base URL (e.g. "http://localhost:9924/api/session") */
8
+ sessionApiUrl: string;
9
+ /**
10
+ * Internal service name for IdP UI auth via X-Douvery-Internal-Service header.
11
+ * Used by the IdP's own UI (like accounts.google.com) — NOT an OAuth client.
12
+ * Requires internalServiceSecret.
13
+ */
14
+ internalServiceName?: string;
15
+ /**
16
+ * HMAC secret for internal service auth.
17
+ * Signs X-Douvery-Internal-Signature: HMAC-SHA256(timestamp:serviceName, secret).
18
+ * Used together with internalServiceName.
19
+ */
20
+ internalServiceSecret?: string;
21
+ /**
22
+ * OAuth Client ID for consumer app auth via X-Client-Id header.
23
+ * For apps that ARE OAuth clients (douvery-web, center, mobile).
24
+ */
25
+ clientId?: string;
26
+ /**
27
+ * OAuth Client Secret for consumer app auth via X-Client-Secret header.
28
+ * Used together with clientId. Validated against oauth_clients table (Argon2).
29
+ */
30
+ clientSecret?: string;
31
+ /** Cookie name for the session ID (e.g. "douvery-session") */
32
+ cookieName: string;
33
+ /** Session cookie max age in seconds @default 2592000 (30 days) */
34
+ cookieMaxAge?: number;
35
+ /** Whether cookies should use the 'secure' flag @default true */
36
+ secureCookies?: boolean;
37
+ /** Timeout for lightweight session API calls like /token (ms) @default 3000 */
38
+ fetchTimeoutMs?: number;
39
+ /** Timeout for heavy session API calls like /refresh (ms) @default 8000 */
40
+ refreshTimeoutMs?: number;
41
+ /** Fallback cache TTL when JWT exp cannot be parsed (ms) @default 30000 */
42
+ fallbackCacheTtlMs?: number;
43
+ /** Enable debug logging @default false */
44
+ debug?: boolean;
45
+ /** Custom logger implementation. Defaults to console when debug is true. */
46
+ logger?: SessionLogger;
47
+ }
48
+ /**
49
+ * Minimal cookie adapter interface.
50
+ * Each framework implements this for its own cookie API (Qwik, Next.js, Express, etc).
51
+ *
52
+ * The resolver uses the adapter object reference as a WeakMap key for per-request
53
+ * caching. Ensure the SAME adapter instance is used for all calls within a single
54
+ * request to benefit from deduplication and caching.
55
+ */
56
+ interface CookieAdapter {
57
+ /** Read a cookie value by name. Returns undefined if not found. */
58
+ get(name: string): string | undefined;
59
+ /** Set a cookie with the given name, value, and options. */
60
+ set(name: string, value: string, options: CookieSetOptions): void;
61
+ }
62
+ /** Options for setting a cookie (standard HTTP cookie attributes) */
63
+ interface CookieSetOptions {
64
+ path?: string;
65
+ httpOnly?: boolean;
66
+ secure?: boolean;
67
+ sameSite?: "strict" | "lax" | "none";
68
+ maxAge?: number;
69
+ }
70
+ /**
71
+ * Result of a refresh attempt. Callers MUST distinguish between:
72
+ * - 'success': tokens refreshed, cache invalidated — proceed normally
73
+ * - 'definitive_failure': server confirmed session is dead (401/404) — safe to clear cookie
74
+ * - 'transient_failure': timeout/network/500 — session may still be valid, DON'T clear cookie
75
+ */
76
+ type RefreshResult = "success" | "definitive_failure" | "transient_failure";
77
+ interface SessionLogger {
78
+ debug(...args: unknown[]): void;
79
+ warn(...args: unknown[]): void;
80
+ error(...args: unknown[]): void;
81
+ }
82
+ /** The public API returned by createSessionResolver() */
83
+ interface SessionResolver {
84
+ /**
85
+ * Resolve opaque session to JWT access_token (async).
86
+ * Uses per-request caching and deduplication.
87
+ * Returns the JWT even if expired — the caller handles refresh.
88
+ */
89
+ getAccessToken(cookies: CookieAdapter): Promise<string | undefined>;
90
+ /**
91
+ * Synchronous access to cached token (for sync header builders).
92
+ * Returns cached value only — NO network call.
93
+ */
94
+ getAccessTokenSync(cookies: CookieAdapter): string | undefined;
95
+ /**
96
+ * Refresh session tokens via auth server.
97
+ * Triggers full token rotation. Deduplicates concurrent refresh calls
98
+ * across all requests for the same session_id.
99
+ */
100
+ refreshSession(cookies: CookieAdapter): Promise<RefreshResult>;
101
+ /** Destroy session on auth server and clear local cookie. */
102
+ destroySession(cookies: CookieAdapter): Promise<void>;
103
+ /** Save session ID in an HttpOnly cookie after OAuth callback. */
104
+ setSessionCookie(sessionId: string, cookies: CookieAdapter): void;
105
+ /** Read session ID from cookie. */
106
+ getSessionId(cookies: CookieAdapter): string | undefined;
107
+ /** Check if user has an active session cookie. */
108
+ hasSession(cookies: CookieAdapter): boolean;
109
+ /**
110
+ * Clear session cookie and invalidate cached token.
111
+ * Sets an expired cookie to ensure the browser removes it.
112
+ */
113
+ clearSessionCookie(cookies: CookieAdapter): void;
114
+ }
115
+
116
+ /**
117
+ * @douvery/auth - Session Resolver
118
+ * Factory for creating framework-agnostic opaque session resolvers.
119
+ *
120
+ * Architecture:
121
+ * ┌─────────┐ session_id cookie ┌──────────────┐ JWT ┌──────────────┐
122
+ * │ Browser │ ──────────────────▶ │ SSR App │ ─────────▶ │ Resource │
123
+ * │ │ │ │ │ Server │
124
+ * └─────────┘ └──────┬───────┘ │ (GraphQL) │
125
+ * │ └──────────────┘
126
+ * │ POST /api/session/token
127
+ * ▼
128
+ * ┌──────────────┐
129
+ * │ Auth Server │
130
+ * │ (Redis) │
131
+ * └──────────────┘
132
+ *
133
+ * Security:
134
+ * - Browser only sees opaque session_id (256-bit random, base64url)
135
+ * - JWT access_token lives only in Redis + server memory
136
+ * - IdP UI auth: X-Douvery-Internal-Service + HMAC signature (internal trust)
137
+ * - Consumer app auth: X-Client-Id + X-Client-Secret headers (OAuth per-client)
138
+ * - Per-request WeakMap cache prevents duplicate network calls
139
+ * - Cross-request Map<string> dedup prevents refresh token reuse detection
140
+ */
141
+
142
+ /**
143
+ * Create a session resolver instance.
144
+ *
145
+ * Returns a {@link SessionResolver} with internal state (caches, dedup maps)
146
+ * scoped to this resolver instance. Multiple resolvers can coexist
147
+ * (e.g., for different auth servers or cookie names).
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * // IdP UI (like accounts.google.com — internal service, NOT an OAuth client)
152
+ * const resolver = createSessionResolver({
153
+ * sessionApiUrl: 'http://localhost:9924/api/session',
154
+ * internalServiceName: 'auth-web',
155
+ * internalServiceSecret: process.env.INTERNAL_SERVICE_SECRET,
156
+ * cookieName: 'my-session',
157
+ * debug: process.env.NODE_ENV === 'development',
158
+ * });
159
+ *
160
+ * // Consumer app (OAuth client — douvery-web, center, mobile)
161
+ * const resolver = createSessionResolver({
162
+ * sessionApiUrl: 'http://localhost:9924/api/session',
163
+ * clientId: process.env.OAUTH_CLIENT_ID,
164
+ * clientSecret: process.env.OAUTH_CLIENT_SECRET,
165
+ * cookieName: 'my-session',
166
+ * });
167
+ *
168
+ * // In a request handler:
169
+ * const token = await resolver.getAccessToken(cookieAdapter);
170
+ * ```
171
+ */
172
+ declare function createSessionResolver(config: SessionResolverConfig): SessionResolver;
173
+
174
+ /**
175
+ * Extract `exp` claim from a JWT without full verification.
176
+ * Returns the exp as Unix seconds, or undefined if parsing fails.
177
+ *
178
+ * This is a lightweight alternative to full JWT decoding when you
179
+ * only need the expiration timestamp.
180
+ */
181
+ declare function parseJwtExp(token: string): number | undefined;
182
+ /**
183
+ * Calculate cache TTL based on the JWT's `exp` claim.
184
+ *
185
+ * Strategy:
186
+ * 1. If auth server provides `expires_in`, use 90% of that
187
+ * 2. If JWT has `exp`, use 90% of remaining lifetime
188
+ * 3. Fall back to `fallbackTtlMs`
189
+ *
190
+ * Result is clamped between 5s and 5min to prevent both
191
+ * excessive polling and stale caches.
192
+ */
193
+ declare function computeCacheTTL(jwtExp: number | undefined, serverExpiresIn?: number, fallbackTtlMs?: number): number;
194
+ /**
195
+ * Fetch wrapper with AbortController timeout.
196
+ * Prevents SSR from hanging if the auth server is unresponsive.
197
+ *
198
+ * @param url - The URL to fetch
199
+ * @param options - Standard fetch RequestInit options
200
+ * @param timeoutMs - Timeout in milliseconds (default: 3000)
201
+ * @throws DOMException with name 'AbortError' on timeout
202
+ */
203
+ declare function fetchWithTimeout(url: string, options: RequestInit, timeoutMs?: number): Promise<Response>;
204
+
205
+ export { type CookieAdapter, type CookieSetOptions, type RefreshResult, type SessionLogger, type SessionResolver, type SessionResolverConfig, computeCacheTTL, createSessionResolver, fetchWithTimeout, parseJwtExp };