hazo_auth 10.8.1 → 10.9.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 (36) hide show
  1. package/SETUP_CHECKLIST.md +49 -0
  2. package/cli-src/lib/auth/with_auth.server.ts +65 -23
  3. package/cli-src/lib/services/user_profiles_service.ts +4 -3
  4. package/dist/admin-issues/install_permission_ux.server.d.ts +26 -0
  5. package/dist/admin-issues/install_permission_ux.server.d.ts.map +1 -0
  6. package/dist/admin-issues/install_permission_ux.server.js +27 -0
  7. package/dist/admin-issues/permission_denied_provider.client.d.ts +19 -0
  8. package/dist/admin-issues/permission_denied_provider.client.d.ts.map +1 -1
  9. package/dist/admin-issues/permission_denied_provider.client.js +46 -2
  10. package/dist/client.d.ts +2 -2
  11. package/dist/client.d.ts.map +1 -1
  12. package/dist/client.js +1 -1
  13. package/dist/components/permission_denied_dialog.client.js +1 -1
  14. package/dist/lib/auth/with_auth.server.d.ts.map +1 -1
  15. package/dist/lib/auth/with_auth.server.js +51 -15
  16. package/dist/lib/services/user_profiles_service.d.ts.map +1 -1
  17. package/dist/lib/services/user_profiles_service.js +4 -3
  18. package/dist/server-lib.d.ts +2 -0
  19. package/dist/server-lib.d.ts.map +1 -1
  20. package/dist/server-lib.js +1 -0
  21. package/package.json +8 -8
  22. package/dist/page_components/forgot_password.d.ts +0 -19
  23. package/dist/page_components/forgot_password.d.ts.map +0 -1
  24. package/dist/page_components/forgot_password.js +0 -50
  25. package/dist/page_components/login.d.ts +0 -30
  26. package/dist/page_components/login.d.ts.map +0 -1
  27. package/dist/page_components/login.js +0 -50
  28. package/dist/page_components/register.d.ts +0 -25
  29. package/dist/page_components/register.d.ts.map +0 -1
  30. package/dist/page_components/register.js +0 -57
  31. package/dist/page_components/reset_password.d.ts +0 -25
  32. package/dist/page_components/reset_password.d.ts.map +0 -1
  33. package/dist/page_components/reset_password.js +0 -57
  34. package/dist/page_components/verify_email.d.ts +0 -21
  35. package/dist/page_components/verify_email.d.ts.map +0 -1
  36. package/dist/page_components/verify_email.js +0 -50
@@ -2170,6 +2170,55 @@ curl -H "Cookie: hazo_auth_session=YOUR_TOKEN; hazo_auth_scope_id=SCOPE_UUID" \
2170
2170
 
2171
2171
  ---
2172
2172
 
2173
+ ## Phase 8.1: Permission-Denied UX Setup (Optional)
2174
+
2175
+ `withAuth` (and `withPermissionIssueCapture`) return the canonical `hazo_api`
2176
+ `FORBIDDEN` envelope on every permission denial and best-effort escalate to a
2177
+ registered handler. Wiring the client + server surfaces is **one call each**:
2178
+
2179
+ **Client-side (once, at the app root):**
2180
+ ```typescript
2181
+ import { PermissionFailureProvider } from "hazo_auth/client";
2182
+ import { HazoUiToaster } from "hazo_ui";
2183
+
2184
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
2185
+ return (
2186
+ <html lang="en">
2187
+ <body>
2188
+ <PermissionFailureProvider>{children}</PermissionFailureProvider>
2189
+ <HazoUiToaster />
2190
+ </body>
2191
+ </html>
2192
+ );
2193
+ }
2194
+ ```
2195
+ Mount `<PermissionFailureProvider>` + `<HazoUiToaster>` once client-side — every
2196
+ 403 fetched via `fetchWithPermissionCapture` (or manually passed to
2197
+ `handlePermissionDenied`) now surfaces a toast. Prefer the heavier
2198
+ `<PermissionDeniedProvider>` (a modal dialog) instead if you want a blocking
2199
+ surface — the two are mutually exclusive; whichever is mounted wins.
2200
+
2201
+ **Server-side (once, at boot):**
2202
+ ```typescript
2203
+ import { installPermissionUX } from "hazo_auth/server-lib";
2204
+
2205
+ installPermissionUX({
2206
+ getAdapter: () => get_hazo_connect_instance(),
2207
+ createIssueStore: (adapter) => createIssueStore(adapter),
2208
+ registerType: (def) => issueRegistry.register(def),
2209
+ });
2210
+ ```
2211
+ `installPermissionUX(...)` registers the `auth_permission` issue type and wires
2212
+ the escalation handler so every FORBIDDEN denial best-effort bumps/creates an
2213
+ admin issue — same options as `wireAdminIssueCapture` (which it wraps).
2214
+
2215
+ **Permission-Denied UX Checklist:**
2216
+ - [ ] `<PermissionFailureProvider>` (toast) or `<PermissionDeniedProvider>` (dialog) mounted once at the client root
2217
+ - [ ] `<HazoUiToaster>` mounted once (only needed for the toast surface)
2218
+ - [ ] `installPermissionUX(...)` called once at server boot
2219
+
2220
+ ---
2221
+
2173
2222
  ## Troubleshooting
2174
2223
 
2175
2224
  ### Issue: "User is inactive" or "auth_utility_fetch_user_failed" errors
@@ -15,6 +15,13 @@ import {
15
15
  type ScopeDetails,
16
16
  type ScopeAccessInfo,
17
17
  } from "./auth_types.js";
18
+ import {
19
+ buildForbiddenResponse,
20
+ buildDenialPayloadFromRequest,
21
+ getPermissionDeniedHandler,
22
+ type PermissionDeniedPayload,
23
+ } from "./with_permission_issue_capture.server.js";
24
+ import { get_app_permission_descriptions } from "../app_permissions_config.server.js";
18
25
 
19
26
  // section: types
20
27
 
@@ -90,10 +97,43 @@ type OptionalAuthHandler<TParams> = (
90
97
 
91
98
  // section: error_response_helper
92
99
 
100
+ /** Converts get_app_permission_descriptions()'s Map into the Record shape PermissionDeniedPayload expects. */
101
+ function descriptions_map_to_record(
102
+ map: Map<string, string>,
103
+ ): Record<string, string> {
104
+ return Object.fromEntries(map);
105
+ }
106
+
107
+ /**
108
+ * Fire the denial escalation handler best-effort (never awaited, never
109
+ * throws), then return the canonical FORBIDDEN envelope.
110
+ */
111
+ async function respond_permission_denied(
112
+ payload: PermissionDeniedPayload,
113
+ ): Promise<NextResponse> {
114
+ try {
115
+ const handler = getPermissionDeniedHandler();
116
+ if (handler) {
117
+ // fire-and-forget; escalation must never delay or fail the 403
118
+ Promise.resolve()
119
+ .then(() => handler(payload))
120
+ .catch(() => {
121
+ /* swallow */
122
+ });
123
+ }
124
+ } catch {
125
+ /* swallow */
126
+ }
127
+ return (await buildForbiddenResponse(payload)) as unknown as NextResponse;
128
+ }
129
+
93
130
  /**
94
131
  * Converts caught errors into appropriate NextResponse JSON responses
95
132
  */
96
- function handle_auth_error(error: unknown): NextResponse {
133
+ async function handle_auth_error(
134
+ error: unknown,
135
+ request: Request,
136
+ ): Promise<NextResponse> {
97
137
  if (error instanceof HazoAuthError) {
98
138
  return NextResponse.json(
99
139
  { error: error.message, code: error.code },
@@ -102,14 +142,18 @@ function handle_auth_error(error: unknown): NextResponse {
102
142
  }
103
143
 
104
144
  if (error instanceof PermissionError) {
105
- return NextResponse.json(
106
- {
107
- error: error.message,
108
- code: "PERMISSION_DENIED",
109
- missing_permissions: error.missing_permissions,
110
- },
111
- { status: 403 },
145
+ const descriptions = get_app_permission_descriptions(
146
+ error.missing_permissions ?? [],
112
147
  );
148
+ const payload = buildDenialPayloadFromRequest(request, {
149
+ user_id: "",
150
+ missing_permissions: error.missing_permissions ?? [],
151
+ required_permissions:
152
+ error.required_permissions ?? error.missing_permissions ?? [],
153
+ permission_descriptions: descriptions_map_to_record(descriptions),
154
+ user_permissions: error.user_permissions ?? [],
155
+ });
156
+ return respond_permission_denied(payload);
113
157
  }
114
158
 
115
159
  console.error("Unexpected error in route handler:", error);
@@ -210,20 +254,18 @@ export function withAuth<TParams = Record<string, never>>(
210
254
 
211
255
  // Check permissions if required_permissions were specified
212
256
  if (options.required_permissions?.length && !auth.permission_ok) {
213
- return NextResponse.json(
214
- {
215
- error: "Insufficient permissions",
216
- code: "PERMISSION_DENIED",
217
- missing_permissions: auth.missing_permissions,
218
- ...(process.env.NODE_ENV === "development" && {
219
- debug: {
220
- user_permissions: auth.permissions,
221
- required_permissions: options.required_permissions,
222
- },
223
- }),
224
- },
225
- { status: 403 },
257
+ const descriptions = get_app_permission_descriptions(
258
+ auth.missing_permissions ?? [],
226
259
  );
260
+ const payload = buildDenialPayloadFromRequest(request, {
261
+ user_id: auth.user?.id ?? "",
262
+ scope_id: options.scope_id,
263
+ missing_permissions: auth.missing_permissions ?? [],
264
+ required_permissions: options.required_permissions,
265
+ permission_descriptions: descriptions_map_to_record(descriptions),
266
+ user_permissions: auth.permissions,
267
+ });
268
+ return respond_permission_denied(payload);
227
269
  }
228
270
 
229
271
  // Check tenant requirement
@@ -246,7 +288,7 @@ export function withAuth<TParams = Record<string, never>>(
246
288
  params,
247
289
  );
248
290
  } catch (error) {
249
- return handle_auth_error(error);
291
+ return await handle_auth_error(error, request);
250
292
  }
251
293
  };
252
294
  }
@@ -285,7 +327,7 @@ export function withOptionalAuth<TParams = Record<string, never>>(
285
327
  const params = await resolve_params(context);
286
328
  return await handler(request, auth, params);
287
329
  } catch (error) {
288
- return handle_auth_error(error);
330
+ return await handle_auth_error(error, request);
289
331
  }
290
332
  };
291
333
  }
@@ -52,10 +52,11 @@ async function fetch_profiles_from_db(
52
52
  ): Promise<{ profiles: UserProfileInfo[]; not_found_ids: string[] }> {
53
53
  const users_service = createCrudService(adapter, "hazo_users");
54
54
 
55
- // Query users by IDs using the 'in' filter
56
- // PostgREST supports 'in' filter syntax: id=in.(id1,id2,id3)
55
+ // Query users by IDs. Pass the array directly so hazo_connect's findBy()
56
+ // selects the SQL `IN` operator (a pre-formatted string falls into `eq` and
57
+ // never matches — this silently returned zero profiles on every call).
57
58
  const users = await users_service.findBy({
58
- id: `in.(${user_ids.join(",")})`,
59
+ id: user_ids,
59
60
  });
60
61
 
61
62
  // Handle case where no users are found
@@ -0,0 +1,26 @@
1
+ import 'server-only';
2
+ import { type WireAdminIssueCaptureOptions } from './wire.server.js';
3
+ export type InstallPermissionUXOptions = WireAdminIssueCaptureOptions;
4
+ /**
5
+ * Mounts the server side of the permission-UX stack in one call, at app boot.
6
+ *
7
+ * Forwards straight to `wireAdminIssueCapture`, which:
8
+ * 1. registers the `auth_permission` issue type with hazo_admin, and
9
+ * 2. calls `setPermissionDeniedHandler(...)` so every FORBIDDEN denial from
10
+ * `withAuth` / `withPermissionIssueCapture` best-effort escalates to the
11
+ * admin issue store.
12
+ *
13
+ * `installPermissionUX` exists as the documented, memorable name for that
14
+ * boot-time call — pair it client-side with `<PermissionFailureProvider>` (or
15
+ * `<PermissionDeniedProvider>`) + `<HazoUiToaster>` mounted once.
16
+ *
17
+ * Usage:
18
+ * // instrumentation.ts / app bootstrap
19
+ * installPermissionUX({
20
+ * getAdapter: () => get_hazo_connect_instance(),
21
+ * createIssueStore: (adapter) => createIssueStore(adapter),
22
+ * registerType: (def) => issueRegistry.register(def),
23
+ * });
24
+ */
25
+ export declare function installPermissionUX(opts: InstallPermissionUXOptions): void;
26
+ //# sourceMappingURL=install_permission_ux.server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install_permission_ux.server.d.ts","sourceRoot":"","sources":["../../src/admin-issues/install_permission_ux.server.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,CAAC;AAErB,OAAO,EAAyB,KAAK,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAEzF,MAAM,MAAM,0BAA0B,GAAG,4BAA4B,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,IAAI,CAE1E"}
@@ -0,0 +1,27 @@
1
+ // file_description: single documented entrypoint that wires the whole permission-UX stack server-side
2
+ import 'server-only';
3
+ import { wireAdminIssueCapture } from './wire.server.js';
4
+ /**
5
+ * Mounts the server side of the permission-UX stack in one call, at app boot.
6
+ *
7
+ * Forwards straight to `wireAdminIssueCapture`, which:
8
+ * 1. registers the `auth_permission` issue type with hazo_admin, and
9
+ * 2. calls `setPermissionDeniedHandler(...)` so every FORBIDDEN denial from
10
+ * `withAuth` / `withPermissionIssueCapture` best-effort escalates to the
11
+ * admin issue store.
12
+ *
13
+ * `installPermissionUX` exists as the documented, memorable name for that
14
+ * boot-time call — pair it client-side with `<PermissionFailureProvider>` (or
15
+ * `<PermissionDeniedProvider>`) + `<HazoUiToaster>` mounted once.
16
+ *
17
+ * Usage:
18
+ * // instrumentation.ts / app bootstrap
19
+ * installPermissionUX({
20
+ * getAdapter: () => get_hazo_connect_instance(),
21
+ * createIssueStore: (adapter) => createIssueStore(adapter),
22
+ * registerType: (def) => issueRegistry.register(def),
23
+ * });
24
+ */
25
+ export function installPermissionUX(opts) {
26
+ wireAdminIssueCapture(opts);
27
+ }
@@ -1,12 +1,31 @@
1
1
  import React from 'react';
2
2
  import { type PermissionDeniedDetails } from '../components/permission_denied_dialog.client.js';
3
3
  export declare function showPermissionDeniedDialog(details: PermissionDeniedDetails, message?: string): void;
4
+ export type PermissionFailureSurface = (details: PermissionDeniedDetails, message?: string) => void | Promise<void>;
5
+ /**
6
+ * Registers the active permission-failure surface. The most recently mounted
7
+ * provider wins; pass `null` to clear (done automatically on unmount by the
8
+ * providers below). Exported for `PermissionFailureProvider` and for tests —
9
+ * consuming apps normally just mount a provider instead of calling this.
10
+ */
11
+ export declare function registerPermissionFailureSurface(surface: PermissionFailureSurface | null): void;
4
12
  export interface PermissionDeniedProviderProps {
5
13
  children?: React.ReactNode;
6
14
  registerCardRenderer?: (typeKey: string, renderer: React.ComponentType<any>) => void;
7
15
  }
8
16
  export declare function PermissionDeniedProvider({ children, registerCardRenderer }: PermissionDeniedProviderProps): React.JSX.Element;
9
17
  export declare function handlePermissionDenied(response: Response): Promise<boolean>;
18
+ export interface PermissionFailureProviderProps {
19
+ children?: React.ReactNode;
20
+ registerCardRenderer?: (typeKey: string, renderer: React.ComponentType<any>) => void;
21
+ }
22
+ /**
23
+ * Batteries-included permission-failure surface: renders a toast via hazo_ui's
24
+ * `permissionToast` (dynamically imported so hazo_ui stays an optional peer).
25
+ * Unlike `PermissionDeniedProvider`, this renders no dialog itself — mount
26
+ * `<HazoUiToaster>` once alongside it for the toast to actually appear.
27
+ */
28
+ export declare function PermissionFailureProvider({ children, registerCardRenderer }: PermissionFailureProviderProps): React.JSX.Element;
10
29
  export declare function fetchWithPermissionCapture(input: RequestInfo | URL, init?: RequestInit & {
11
30
  originUrl?: string;
12
31
  actionLabel?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"permission_denied_provider.client.d.ts","sourceRoot":"","sources":["../../src/admin-issues/permission_denied_provider.client.tsx"],"names":[],"mappings":"AAGA,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,+CAA+C,CAAC;AAOvD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,uBAAuB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAInG;AAID,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;CACtF;AAED,wBAAgB,wBAAwB,CAAC,EAAE,QAAQ,EAAE,oBAAoB,EAAE,EAAE,6BAA6B,qBAgCzG;AAID,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAmBjF;AAID,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAChE,OAAO,CAAC,QAAQ,CAAC,CAcnB"}
1
+ {"version":3,"file":"permission_denied_provider.client.d.ts","sourceRoot":"","sources":["../../src/admin-issues/permission_denied_provider.client.tsx"],"names":[],"mappings":"AAGA,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,+CAA+C,CAAC;AAOvD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,uBAAuB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAInG;AASD,MAAM,MAAM,wBAAwB,GAAG,CACrC,OAAO,EAAE,uBAAuB,EAChC,OAAO,CAAC,EAAE,MAAM,KACb,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAI1B;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,GAAG,IAAI,CAE/F;AAID,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;CACtF;AAED,wBAAgB,wBAAwB,CAAC,EAAE,QAAQ,EAAE,oBAAoB,EAAE,EAAE,6BAA6B,qBAgCzG;AAID,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CA0BjF;AAID,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,oBAAoB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;CACtF;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,QAAQ,EAAE,oBAAoB,EAAE,EAAE,8BAA8B,qBAuB3G;AAID,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAChE,OAAO,CAAC,QAAQ,CAAC,CAcnB"}
@@ -22,6 +22,16 @@ export function showPermissionDeniedDialog(details, message) {
22
22
  _showDialog(details, message);
23
23
  }
24
24
  }
25
+ let _surface = null;
26
+ /**
27
+ * Registers the active permission-failure surface. The most recently mounted
28
+ * provider wins; pass `null` to clear (done automatically on unmount by the
29
+ * providers below). Exported for `PermissionFailureProvider` and for tests —
30
+ * consuming apps normally just mount a provider instead of calling this.
31
+ */
32
+ export function registerPermissionFailureSurface(surface) {
33
+ _surface = surface;
34
+ }
25
35
  export function PermissionDeniedProvider({ children, registerCardRenderer }) {
26
36
  const [open, setOpen] = useState(false);
27
37
  const [details, setDetails] = useState(null);
@@ -47,7 +57,10 @@ export async function handlePermissionDenied(response) {
47
57
  try {
48
58
  const cloned = response.clone();
49
59
  const body = await cloned.json();
50
- if (((_a = body === null || body === void 0 ? void 0 : body.error) === null || _a === void 0 ? void 0 : _a.code) !== 'FORBIDDEN')
60
+ // 'FORBIDDEN' is the canonical code emitted by withAuth/withPermissionIssueCapture.
61
+ // 'PERMISSION_DENIED' is accepted for back-compat with pre-FR-017 servers.
62
+ const code = (_a = body === null || body === void 0 ? void 0 : body.error) === null || _a === void 0 ? void 0 : _a.code;
63
+ if (code !== 'FORBIDDEN' && code !== 'PERMISSION_DENIED')
51
64
  return false;
52
65
  const errDetails = (_b = body.error.details) !== null && _b !== void 0 ? _b : {};
53
66
  const permDetails = {
@@ -56,13 +69,44 @@ export async function handlePermissionDenied(response) {
56
69
  action_label: errDetails.action_label,
57
70
  origin_url: errDetails.origin_url,
58
71
  };
59
- showPermissionDeniedDialog(permDetails, body.error.message);
72
+ if (_surface) {
73
+ _surface(permDetails, body.error.message);
74
+ }
75
+ else {
76
+ showPermissionDeniedDialog(permDetails, body.error.message);
77
+ }
60
78
  return true;
61
79
  }
62
80
  catch (_c) {
63
81
  return false;
64
82
  }
65
83
  }
84
+ /**
85
+ * Batteries-included permission-failure surface: renders a toast via hazo_ui's
86
+ * `permissionToast` (dynamically imported so hazo_ui stays an optional peer).
87
+ * Unlike `PermissionDeniedProvider`, this renders no dialog itself — mount
88
+ * `<HazoUiToaster>` once alongside it for the toast to actually appear.
89
+ */
90
+ export function PermissionFailureProvider({ children, registerCardRenderer }) {
91
+ useEffect(() => {
92
+ _surface = async (details, message) => {
93
+ var _a, _b;
94
+ const ui = (await import('hazo_ui').catch(() => null));
95
+ (_a = ui === null || ui === void 0 ? void 0 : ui.permissionToast) === null || _a === void 0 ? void 0 : _a.call(ui, {
96
+ missingPermissions: (_b = details.missing_permissions) !== null && _b !== void 0 ? _b : [],
97
+ descriptions: details.permission_descriptions,
98
+ });
99
+ void message; // toast has no separate title/message slot beyond permissionToast's own copy
100
+ };
101
+ if (registerCardRenderer) {
102
+ registerCardRenderer('auth_permission', AuthIssueCard);
103
+ }
104
+ return () => {
105
+ _surface = null;
106
+ };
107
+ }, [registerCardRenderer]);
108
+ return _jsx(_Fragment, { children: children });
109
+ }
66
110
  // ── fetchWithPermissionCapture ────────────────────────────────────────────────
67
111
  export async function fetchWithPermissionCapture(input, init) {
68
112
  var _a;
package/dist/client.d.ts CHANGED
@@ -15,6 +15,6 @@ export type { PermissionDeniedDialogProps, PermissionDeniedDetails } from "./com
15
15
  export { UserPickerSelect, UserAvatar, userDisplayName } from "./components/user_picker_select.js";
16
16
  export type { UserPickerSelectProps, UserAvatarProps, PickableUser, } from "./components/user_picker_select";
17
17
  export { AuthIssueCard, registerAuthIssueCardRenderer } from './admin-issues/plugin.client.js';
18
- export { PermissionDeniedProvider, showPermissionDeniedDialog, handlePermissionDenied, fetchWithPermissionCapture, } from './admin-issues/permission_denied_provider.client.js';
19
- export type { PermissionDeniedProviderProps } from './admin-issues/permission_denied_provider.client';
18
+ export { PermissionDeniedProvider, PermissionFailureProvider, showPermissionDeniedDialog, registerPermissionFailureSurface, handlePermissionDenied, fetchWithPermissionCapture, } from './admin-issues/permission_denied_provider.client.js';
19
+ export type { PermissionDeniedProviderProps, PermissionFailureProviderProps, PermissionFailureSurface, } from './admin-issues/permission_denied_provider.client';
20
20
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAYA,cAAc,oBAAoB,CAAC;AAInC,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAInI,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIpD,cAAc,uBAAuB,CAAC;AAItC,OAAO,EAAE,eAAe,EAAE,2BAA2B,EAAE,MAAM,mDAAmD,CAAC;AACjH,OAAO,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAC;AAC3G,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AAC7G,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,qDAAqD,CAAC;AACnH,YAAY,EAAE,YAAY,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,qDAAqD,CAAC;AAGvI,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAIxG,cAAc,8CAA8C,CAAC;AAG7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAGvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AACtF,YAAY,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AAKzH,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAChG,YAAY,EACV,qBAAqB,EACrB,eAAe,EACf,YAAY,GACb,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAAE,aAAa,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAG5F,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,kDAAkD,CAAC;AAC1D,YAAY,EAAE,6BAA6B,EAAE,MAAM,kDAAkD,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAYA,cAAc,oBAAoB,CAAC;AAInC,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAInI,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIpD,cAAc,uBAAuB,CAAC;AAItC,OAAO,EAAE,eAAe,EAAE,2BAA2B,EAAE,MAAM,mDAAmD,CAAC;AACjH,OAAO,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,iDAAiD,CAAC;AAC3G,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AAC7G,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,qDAAqD,CAAC;AACnH,YAAY,EAAE,YAAY,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,qDAAqD,CAAC;AAGvI,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAIxG,cAAc,8CAA8C,CAAC;AAG7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAGvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAC;AACtF,YAAY,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AAKzH,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAChG,YAAY,EACV,qBAAqB,EACrB,eAAe,EACf,YAAY,GACb,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EAAE,aAAa,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC;AAG5F,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,EAC1B,gCAAgC,EAChC,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,kDAAkD,CAAC;AAC1D,YAAY,EACV,6BAA6B,EAC7B,8BAA8B,EAC9B,wBAAwB,GACzB,MAAM,kDAAkD,CAAC"}
package/dist/client.js CHANGED
@@ -40,4 +40,4 @@ export { UserPickerSelect, UserAvatar, userDisplayName } from "./components/user
40
40
  // admin-issues plugin (client card renderer)
41
41
  export { AuthIssueCard, registerAuthIssueCardRenderer } from './admin-issues/plugin.client.js';
42
42
  // permission-denied provider + fetch helper
43
- export { PermissionDeniedProvider, showPermissionDeniedDialog, handlePermissionDenied, fetchWithPermissionCapture, } from './admin-issues/permission_denied_provider.client.js';
43
+ export { PermissionDeniedProvider, PermissionFailureProvider, showPermissionDeniedDialog, registerPermissionFailureSurface, handlePermissionDenied, fetchWithPermissionCapture, } from './admin-issues/permission_denied_provider.client.js';
@@ -1,4 +1,4 @@
1
- // file_description: dialog component shown when a fetch response returns error.code === 'PERMISSION_DENIED'
1
+ // file_description: dialog component shown when a fetch response returns error.code === 'FORBIDDEN' (or legacy 'PERMISSION_DENIED')
2
2
  // Probes hazo_ui at mount time (it's a peer dep) and falls back to plain HTML if unavailable.
3
3
  'use client';
4
4
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -1 +1 @@
1
- {"version":3,"file":"with_auth.server.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/with_auth.server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"with_auth.server.d.ts","sourceRoot":"","sources":["../../../src/lib/auth/with_auth.server.ts"],"names":[],"mappings":"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"}
@@ -5,20 +5,52 @@ import "server-only";
5
5
  import { NextResponse } from "next/server";
6
6
  import { hazo_get_tenant_auth } from "./hazo_get_tenant_auth.server.js";
7
7
  import { HazoAuthError, PermissionError, } from "./auth_types.js";
8
+ import { buildForbiddenResponse, buildDenialPayloadFromRequest, getPermissionDeniedHandler, } from "./with_permission_issue_capture.server.js";
9
+ import { get_app_permission_descriptions } from "../app_permissions_config.server.js";
8
10
  // section: error_response_helper
11
+ /** Converts get_app_permission_descriptions()'s Map into the Record shape PermissionDeniedPayload expects. */
12
+ function descriptions_map_to_record(map) {
13
+ return Object.fromEntries(map);
14
+ }
15
+ /**
16
+ * Fire the denial escalation handler best-effort (never awaited, never
17
+ * throws), then return the canonical FORBIDDEN envelope.
18
+ */
19
+ async function respond_permission_denied(payload) {
20
+ try {
21
+ const handler = getPermissionDeniedHandler();
22
+ if (handler) {
23
+ // fire-and-forget; escalation must never delay or fail the 403
24
+ Promise.resolve()
25
+ .then(() => handler(payload))
26
+ .catch(() => {
27
+ /* swallow */
28
+ });
29
+ }
30
+ }
31
+ catch (_a) {
32
+ /* swallow */
33
+ }
34
+ return (await buildForbiddenResponse(payload));
35
+ }
9
36
  /**
10
37
  * Converts caught errors into appropriate NextResponse JSON responses
11
38
  */
12
- function handle_auth_error(error) {
39
+ async function handle_auth_error(error, request) {
40
+ var _a, _b, _c, _d, _e;
13
41
  if (error instanceof HazoAuthError) {
14
42
  return NextResponse.json({ error: error.message, code: error.code }, { status: error.status_code });
15
43
  }
16
44
  if (error instanceof PermissionError) {
17
- return NextResponse.json({
18
- error: error.message,
19
- code: "PERMISSION_DENIED",
20
- missing_permissions: error.missing_permissions,
21
- }, { status: 403 });
45
+ const descriptions = get_app_permission_descriptions((_a = error.missing_permissions) !== null && _a !== void 0 ? _a : []);
46
+ const payload = buildDenialPayloadFromRequest(request, {
47
+ user_id: "",
48
+ missing_permissions: (_b = error.missing_permissions) !== null && _b !== void 0 ? _b : [],
49
+ required_permissions: (_d = (_c = error.required_permissions) !== null && _c !== void 0 ? _c : error.missing_permissions) !== null && _d !== void 0 ? _d : [],
50
+ permission_descriptions: descriptions_map_to_record(descriptions),
51
+ user_permissions: (_e = error.user_permissions) !== null && _e !== void 0 ? _e : [],
52
+ });
53
+ return respond_permission_denied(payload);
22
54
  }
23
55
  console.error("Unexpected error in route handler:", error);
24
56
  return NextResponse.json({ error: "Internal server error" }, { status: 500 });
@@ -34,7 +66,7 @@ async function resolve_params(context) {
34
66
  }
35
67
  export function withAuth(handler, options = {}) {
36
68
  return async (request, context) => {
37
- var _a;
69
+ var _a, _b, _c, _d, _e;
38
70
  try {
39
71
  const auth = await hazo_get_tenant_auth(request, options);
40
72
  if (!auth.authenticated) {
@@ -42,12 +74,16 @@ export function withAuth(handler, options = {}) {
42
74
  }
43
75
  // Check permissions if required_permissions were specified
44
76
  if (((_a = options.required_permissions) === null || _a === void 0 ? void 0 : _a.length) && !auth.permission_ok) {
45
- return NextResponse.json(Object.assign({ error: "Insufficient permissions", code: "PERMISSION_DENIED", missing_permissions: auth.missing_permissions }, (process.env.NODE_ENV === "development" && {
46
- debug: {
47
- user_permissions: auth.permissions,
48
- required_permissions: options.required_permissions,
49
- },
50
- })), { status: 403 });
77
+ const descriptions = get_app_permission_descriptions((_b = auth.missing_permissions) !== null && _b !== void 0 ? _b : []);
78
+ const payload = buildDenialPayloadFromRequest(request, {
79
+ user_id: (_d = (_c = auth.user) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : "",
80
+ scope_id: options.scope_id,
81
+ missing_permissions: (_e = auth.missing_permissions) !== null && _e !== void 0 ? _e : [],
82
+ required_permissions: options.required_permissions,
83
+ permission_descriptions: descriptions_map_to_record(descriptions),
84
+ user_permissions: auth.permissions,
85
+ });
86
+ return respond_permission_denied(payload);
51
87
  }
52
88
  // Check tenant requirement
53
89
  if (options.require_tenant && !auth.organization) {
@@ -61,7 +97,7 @@ export function withAuth(handler, options = {}) {
61
97
  return await handler(request, auth, params);
62
98
  }
63
99
  catch (error) {
64
- return handle_auth_error(error);
100
+ return await handle_auth_error(error, request);
65
101
  }
66
102
  };
67
103
  }
@@ -90,7 +126,7 @@ export function withOptionalAuth(handler, options = {}) {
90
126
  return await handler(request, auth, params);
91
127
  }
92
128
  catch (error) {
93
- return handle_auth_error(error);
129
+ return await handle_auth_error(error, request);
94
130
  }
95
131
  };
96
132
  }
@@ -1 +1 @@
1
- {"version":3,"file":"user_profiles_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/user_profiles_service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASvD;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,EAAE,OAAO,CAAC;KACxB,CAAC;CACH,CAAC;AAuDF;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,iBAAiB,CAAC,CA4H5B;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAWvE;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,IAAI,IAAI,CAWzD"}
1
+ {"version":3,"file":"user_profiles_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/user_profiles_service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASvD;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,EAAE,OAAO,CAAC;KACxB,CAAC;CACH,CAAC;AAwDF;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,iBAAiB,CAAC,CA4H5B;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAWvE;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,IAAI,IAAI,CAWzD"}
@@ -13,10 +13,11 @@ import { get_user_profiles_cache_config } from "../user_profiles_config.server.j
13
13
  */
14
14
  async function fetch_profiles_from_db(adapter, user_ids) {
15
15
  const users_service = createCrudService(adapter, "hazo_users");
16
- // Query users by IDs using the 'in' filter
17
- // PostgREST supports 'in' filter syntax: id=in.(id1,id2,id3)
16
+ // Query users by IDs. Pass the array directly so hazo_connect's findBy()
17
+ // selects the SQL `IN` operator (a pre-formatted string falls into `eq` and
18
+ // never matches — this silently returned zero profiles on every call).
18
19
  const users = await users_service.findBy({
19
- id: `in.(${user_ids.join(",")})`,
20
+ id: user_ids,
20
21
  });
21
22
  // Handle case where no users are found
22
23
  if (!Array.isArray(users)) {
@@ -37,6 +37,8 @@ export type { RoleWithPermission } from "./lib/services/find_roles_with_permissi
37
37
  export { authIssueTypeDef, registerAuthIssuePlugin } from "./admin-issues/plugin.server.js";
38
38
  export { wireAdminIssueCapture } from "./admin-issues/wire.server.js";
39
39
  export type { WireAdminIssueCaptureOptions } from "./admin-issues/wire.server";
40
+ export { installPermissionUX } from "./admin-issues/install_permission_ux.server.js";
41
+ export type { InstallPermissionUXOptions } from "./admin-issues/install_permission_ux.server";
40
42
  export { denyPermission } from "./lib/auth/deny_permission.server.js";
41
43
  export type { DenyPermissionInput } from "./lib/auth/deny_permission.server";
42
44
  export { logOAuthPreflight, getOAuthPreflightReport } from "./lib/oauth_preflight.server.js";
@@ -1 +1 @@
1
- {"version":3,"file":"server-lib.d.ts","sourceRoot":"","sources":["../src/server-lib.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server-lib.d.ts","sourceRoot":"","sources":["../src/server-lib.ts"],"names":[],"mappings":"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"}
@@ -52,6 +52,7 @@ export { find_roles_with_permission } from "./lib/services/find_roles_with_permi
52
52
  // admin-issues plugin (server)
53
53
  export { authIssueTypeDef, registerAuthIssuePlugin } from "./admin-issues/plugin.server.js";
54
54
  export { wireAdminIssueCapture } from "./admin-issues/wire.server.js";
55
+ export { installPermissionUX } from "./admin-issues/install_permission_ux.server.js";
55
56
  // deny_permission helper
56
57
  export { denyPermission } from "./lib/auth/deny_permission.server.js";
57
58
  // section: oauth_preflight_exports
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_auth",
3
- "version": "10.8.1",
3
+ "version": "10.9.0",
4
4
  "description": "Zero-config authentication UI components for Next.js with RBAC, OAuth, scope-based multi-tenancy, and invitations",
5
5
  "keywords": [
6
6
  "authentication",
@@ -262,15 +262,15 @@
262
262
  "@radix-ui/react-switch": "^1.2.0",
263
263
  "@radix-ui/react-tabs": "^1.1.0",
264
264
  "@radix-ui/react-tooltip": "^1.2.0",
265
- "hazo_api": "^2.5.1",
265
+ "hazo_api": "^2.6.0",
266
266
  "hazo_config": "^2.4.1",
267
267
  "hazo_connect": "^3.9.2",
268
268
  "hazo_core": "^1.2.1",
269
269
  "hazo_logs": "^2.1.1",
270
270
  "hazo_notify": "^6.1.4",
271
- "hazo_secure": "^1.3.0",
272
- "hazo_theme": "^1.0.0",
273
- "hazo_ui": "^6.0.0",
271
+ "hazo_secure": "^1.4.0",
272
+ "hazo_theme": "^1.0.1",
273
+ "hazo_ui": "^6.1.0",
274
274
  "input-otp": "^1.4.0",
275
275
  "lucide-react": "^0.553.0",
276
276
  "next": "^14.0.0",
@@ -406,14 +406,14 @@
406
406
  "eslint": "^9.39.1",
407
407
  "eslint-config-next": "^16.0.4",
408
408
  "eslint-plugin-storybook": "^10.0.6",
409
- "hazo_api": "^2.5.1",
409
+ "hazo_api": "^2.6.0",
410
410
  "hazo_config": "^2.4.1",
411
411
  "hazo_connect": "^3.9.2",
412
412
  "hazo_core": "^1.2.1",
413
413
  "hazo_logs": "^2.1.1",
414
414
  "hazo_notify": "^6.1.4",
415
- "hazo_theme": "^1.0.0",
416
- "hazo_ui": "^6.0.0",
415
+ "hazo_theme": "^1.0.1",
416
+ "hazo_ui": "^6.1.0",
417
417
  "input-otp": "^1.4.0",
418
418
  "jest": "^30.2.0",
419
419
  "jest-environment-jsdom": "^30.0.0",
@@ -1,19 +0,0 @@
1
- export type ForgotPasswordPageProps = {
2
- alreadyLoggedInMessage?: string;
3
- showLogoutButton?: boolean;
4
- showReturnHomeButton?: boolean;
5
- returnHomeButtonLabel?: string;
6
- returnHomePath?: string;
7
- imageSrc?: string;
8
- imageAlt?: string;
9
- imageBackgroundColor?: string;
10
- };
11
- /**
12
- * Zero-config forgot password page component
13
- * Uses sensible defaults and can be customized via props
14
- * @param props - Optional configuration overrides
15
- * @returns Forgot password page component
16
- */
17
- export declare function ForgotPasswordPage({ alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, imageSrc, imageAlt, imageBackgroundColor, }?: ForgotPasswordPageProps): import("react/jsx-runtime").JSX.Element;
18
- export default ForgotPasswordPage;
19
- //# sourceMappingURL=forgot_password.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"forgot_password.d.ts","sourceRoot":"","sources":["../../src/page_components/forgot_password.tsx"],"names":[],"mappings":"AA+BA,MAAM,MAAM,uBAAuB,GAAG;IACpC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,QAA4B,EAC5B,QAA4B,EAC5B,oBAAuC,GACxC,GAAE,uBAA4B,2CAmC9B;AAED,eAAe,kBAAkB,CAAC"}
@@ -1,50 +0,0 @@
1
- // file_description: zero-config forgot password page component for hazo_auth
2
- // Consumers can use this directly without needing to configure props
3
- //
4
- // ⚠️ DEPRECATED: This client component is deprecated in hazo_auth v2.0+
5
- // Please use the new server component version instead:
6
- //
7
- // import { ForgotPasswordPage } from "hazo_auth/pages/forgot_password";
8
- //
9
- // The new version:
10
- // - Initializes on the server (no loading state)
11
- // - Works with your app's hazo_connect instance
12
- // - True zero-config "drop in and use"
13
- // - Better performance (smaller bundle)
14
- //
15
- // This file will be removed in v3.0
16
- //
17
- "use client";
18
- import { jsx as _jsx } from "react/jsx-runtime";
19
- // section: imports
20
- import { useEffect, useState } from "react";
21
- import forgot_password_layout from "../components/layouts/forgot_password/index.js";
22
- import { createLayoutDataClient } from "../components/layouts/shared/data/layout_data_client.js";
23
- import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
24
- // section: constants
25
- const DEFAULT_IMAGE_SRC = "/hazo_auth/images/forgot_password_default.jpg";
26
- const DEFAULT_IMAGE_ALT = "Illustration of a globe representing secure authentication workflows";
27
- const DEFAULT_IMAGE_BG = "#f1f5f9";
28
- // section: component
29
- /**
30
- * Zero-config forgot password page component
31
- * Uses sensible defaults and can be customized via props
32
- * @param props - Optional configuration overrides
33
- * @returns Forgot password page component
34
- */
35
- export function ForgotPasswordPage({ alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", imageSrc = DEFAULT_IMAGE_SRC, imageAlt = DEFAULT_IMAGE_ALT, imageBackgroundColor = DEFAULT_IMAGE_BG, } = {}) {
36
- const [dataClient, setDataClient] = useState(null);
37
- useEffect(() => {
38
- // Initialize hazo_connect on client side
39
- const hazoConnect = create_sqlite_hazo_connect();
40
- const client = createLayoutDataClient(hazoConnect);
41
- setDataClient(client);
42
- }, []);
43
- // Show loading state while initializing
44
- if (!dataClient) {
45
- return (_jsx("div", { className: "cls_forgot_password_page_loading flex items-center justify-center min-h-screen", children: _jsx("div", { className: "text-slate-600 animate-pulse", children: "Loading..." }) }));
46
- }
47
- const ForgotPasswordLayout = forgot_password_layout;
48
- return (_jsx(ForgotPasswordLayout, { image_src: imageSrc, image_alt: imageAlt, image_background_color: imageBackgroundColor, data_client: dataClient, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath }));
49
- }
50
- export default ForgotPasswordPage;
@@ -1,30 +0,0 @@
1
- /**
2
- * @deprecated This client component is deprecated in hazo_auth v2.0+
3
- * Use the new server component version instead: `import { LoginPage } from "hazo_auth/pages/login"`
4
- */
5
- export type LoginPageProps = {
6
- redirectRoute?: string;
7
- successMessage?: string;
8
- alreadyLoggedInMessage?: string;
9
- showLogoutButton?: boolean;
10
- showReturnHomeButton?: boolean;
11
- returnHomeButtonLabel?: string;
12
- returnHomePath?: string;
13
- forgotPasswordPath?: string;
14
- forgotPasswordLabel?: string;
15
- createAccountPath?: string;
16
- createAccountLabel?: string;
17
- urlOnLogon?: string;
18
- imageSrc?: string;
19
- imageAlt?: string;
20
- imageBackgroundColor?: string;
21
- };
22
- /**
23
- * Zero-config login page component
24
- * Uses sensible defaults and can be customized via props
25
- * @param props - Optional configuration overrides
26
- * @returns Login page component
27
- */
28
- export declare function LoginPage({ redirectRoute, successMessage, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, forgotPasswordPath, forgotPasswordLabel, createAccountPath, createAccountLabel, urlOnLogon, imageSrc, imageAlt, imageBackgroundColor, }?: LoginPageProps): import("react/jsx-runtime").JSX.Element;
29
- export default LoginPage;
30
- //# sourceMappingURL=login.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/page_components/login.tsx"],"names":[],"mappings":"AA+BA;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,aAAa,EACb,cAAyC,EACzC,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,kBAAiD,EACjD,mBAAwC,EACxC,iBAAyC,EACzC,kBAAqC,EACrC,UAAU,EACV,QAA4B,EAC5B,QAA4B,EAC5B,oBAAuC,GACxC,GAAE,cAAmB,2CA0CrB;AAED,eAAe,SAAS,CAAC"}
@@ -1,50 +0,0 @@
1
- // file_description: zero-config login page component for hazo_auth
2
- // Consumers can use this directly without needing to configure props
3
- //
4
- // ⚠️ DEPRECATED: This client component is deprecated in hazo_auth v2.0+
5
- // Please use the new server component version instead:
6
- //
7
- // import { LoginPage } from "hazo_auth/pages/login";
8
- //
9
- // The new version:
10
- // - Initializes on the server (no loading state)
11
- // - Works with your app's hazo_connect instance
12
- // - True zero-config "drop in and use"
13
- // - Better performance (smaller bundle)
14
- //
15
- // This file will be removed in v3.0
16
- //
17
- "use client";
18
- import { jsx as _jsx } from "react/jsx-runtime";
19
- // section: imports
20
- import { useEffect, useState } from "react";
21
- import login_layout from "../components/layouts/login/index.js";
22
- import { createLayoutDataClient } from "../components/layouts/shared/data/layout_data_client.js";
23
- import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
24
- // section: constants
25
- const DEFAULT_IMAGE_SRC = "/hazo_auth/images/login_default.jpg";
26
- const DEFAULT_IMAGE_ALT = "Illustration of a globe representing secure authentication workflows";
27
- const DEFAULT_IMAGE_BG = "#f1f5f9";
28
- // section: component
29
- /**
30
- * Zero-config login page component
31
- * Uses sensible defaults and can be customized via props
32
- * @param props - Optional configuration overrides
33
- * @returns Login page component
34
- */
35
- export function LoginPage({ redirectRoute, successMessage = "Successfully logged in", alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", forgotPasswordPath = "/hazo_auth/forgot_password", forgotPasswordLabel = "Forgot password?", createAccountPath = "/hazo_auth/register", createAccountLabel = "Create account", urlOnLogon, imageSrc = DEFAULT_IMAGE_SRC, imageAlt = DEFAULT_IMAGE_ALT, imageBackgroundColor = DEFAULT_IMAGE_BG, } = {}) {
36
- const [dataClient, setDataClient] = useState(null);
37
- useEffect(() => {
38
- // Initialize hazo_connect on client side
39
- const hazoConnect = create_sqlite_hazo_connect();
40
- const client = createLayoutDataClient(hazoConnect);
41
- setDataClient(client);
42
- }, []);
43
- // Show loading state while initializing
44
- if (!dataClient) {
45
- return (_jsx("div", { className: "cls_login_page_loading flex items-center justify-center min-h-screen", children: _jsx("div", { className: "text-slate-600 animate-pulse", children: "Loading..." }) }));
46
- }
47
- const LoginLayout = login_layout;
48
- return (_jsx(LoginLayout, { image_src: imageSrc, image_alt: imageAlt, image_background_color: imageBackgroundColor, data_client: dataClient, redirectRoute: redirectRoute, successMessage: successMessage, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, forgot_password_path: forgotPasswordPath, forgot_password_label: forgotPasswordLabel, create_account_path: createAccountPath, create_account_label: createAccountLabel, urlOnLogon: urlOnLogon }));
49
- }
50
- export default LoginPage;
@@ -1,25 +0,0 @@
1
- import type { PasswordRequirementOverrides } from "../components/layouts/shared/config/layout_customization";
2
- export type RegisterPageProps = {
3
- showNameField?: boolean;
4
- passwordRequirements?: PasswordRequirementOverrides;
5
- alreadyLoggedInMessage?: string;
6
- showLogoutButton?: boolean;
7
- showReturnHomeButton?: boolean;
8
- returnHomeButtonLabel?: string;
9
- returnHomePath?: string;
10
- signInPath?: string;
11
- signInLabel?: string;
12
- urlOnLogon?: string;
13
- imageSrc?: string;
14
- imageAlt?: string;
15
- imageBackgroundColor?: string;
16
- };
17
- /**
18
- * Zero-config register page component
19
- * Uses sensible defaults and can be customized via props
20
- * @param props - Optional configuration overrides
21
- * @returns Register page component
22
- */
23
- export declare function RegisterPage({ showNameField, passwordRequirements, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, signInPath, signInLabel, urlOnLogon, imageSrc, imageAlt, imageBackgroundColor, }?: RegisterPageProps): import("react/jsx-runtime").JSX.Element;
24
- export default RegisterPage;
25
- //# sourceMappingURL=register.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/page_components/register.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,0DAA0D,CAAC;AAgB7G,MAAM,MAAM,iBAAiB,GAAG;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oBAAoB,CAAC,EAAE,4BAA4B,CAAC;IACpD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAC3B,aAAoB,EACpB,oBAAoD,EACpD,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,UAA+B,EAC/B,WAAuB,EACvB,UAAU,EACV,QAA4B,EAC5B,QAA4B,EAC5B,oBAAuC,GACxC,GAAE,iBAAsB,2CAwCxB;AAED,eAAe,YAAY,CAAC"}
@@ -1,57 +0,0 @@
1
- // file_description: zero-config register page component for hazo_auth
2
- // Consumers can use this directly without needing to configure props
3
- //
4
- // ⚠️ DEPRECATED: This client component is deprecated in hazo_auth v2.0+
5
- // Please use the new server component version instead:
6
- //
7
- // import { RegisterPage } from "hazo_auth/pages/register";
8
- //
9
- // The new version:
10
- // - Initializes on the server (no loading state)
11
- // - Works with your app's hazo_connect instance
12
- // - True zero-config "drop in and use"
13
- // - Better performance (smaller bundle)
14
- //
15
- // This file will be removed in v3.0
16
- //
17
- "use client";
18
- import { jsx as _jsx } from "react/jsx-runtime";
19
- // section: imports
20
- import { useEffect, useState } from "react";
21
- import register_layout from "../components/layouts/register/index.js";
22
- import { createLayoutDataClient } from "../components/layouts/shared/data/layout_data_client.js";
23
- import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
24
- // section: constants
25
- const DEFAULT_IMAGE_SRC = "/hazo_auth/images/register_default.jpg";
26
- const DEFAULT_IMAGE_ALT = "Illustration of a globe representing secure authentication workflows";
27
- const DEFAULT_IMAGE_BG = "#e2e8f0";
28
- const DEFAULT_PASSWORD_REQUIREMENTS = {
29
- minimum_length: 8,
30
- require_uppercase: true,
31
- require_lowercase: true,
32
- require_number: true,
33
- require_special: false,
34
- };
35
- // section: component
36
- /**
37
- * Zero-config register page component
38
- * Uses sensible defaults and can be customized via props
39
- * @param props - Optional configuration overrides
40
- * @returns Register page component
41
- */
42
- export function RegisterPage({ showNameField = true, passwordRequirements = DEFAULT_PASSWORD_REQUIREMENTS, alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", signInPath = "/hazo_auth/login", signInLabel = "Sign in", urlOnLogon, imageSrc = DEFAULT_IMAGE_SRC, imageAlt = DEFAULT_IMAGE_ALT, imageBackgroundColor = DEFAULT_IMAGE_BG, } = {}) {
43
- const [dataClient, setDataClient] = useState(null);
44
- useEffect(() => {
45
- // Initialize hazo_connect on client side
46
- const hazoConnect = create_sqlite_hazo_connect();
47
- const client = createLayoutDataClient(hazoConnect);
48
- setDataClient(client);
49
- }, []);
50
- // Show loading state while initializing
51
- if (!dataClient) {
52
- return (_jsx("div", { className: "cls_register_page_loading flex items-center justify-center min-h-screen", children: _jsx("div", { className: "text-slate-600 animate-pulse", children: "Loading..." }) }));
53
- }
54
- const RegisterLayout = register_layout;
55
- return (_jsx(RegisterLayout, { image_src: imageSrc, image_alt: imageAlt, image_background_color: imageBackgroundColor, password_requirements: passwordRequirements, show_name_field: showNameField, data_client: dataClient, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, signInPath: signInPath, signInLabel: signInLabel, urlOnLogon: urlOnLogon }));
56
- }
57
- export default RegisterPage;
@@ -1,25 +0,0 @@
1
- import type { PasswordRequirementOverrides } from "../components/layouts/shared/config/layout_customization";
2
- export type ResetPasswordPageProps = {
3
- errorMessage?: string;
4
- successMessage?: string;
5
- loginPath?: string;
6
- forgotPasswordPath?: string;
7
- passwordRequirements?: PasswordRequirementOverrides;
8
- alreadyLoggedInMessage?: string;
9
- showLogoutButton?: boolean;
10
- showReturnHomeButton?: boolean;
11
- returnHomeButtonLabel?: string;
12
- returnHomePath?: string;
13
- imageSrc?: string;
14
- imageAlt?: string;
15
- imageBackgroundColor?: string;
16
- };
17
- /**
18
- * Zero-config reset password page component
19
- * Uses sensible defaults and can be customized via props
20
- * @param props - Optional configuration overrides
21
- * @returns Reset password page component
22
- */
23
- export declare function ResetPasswordPage({ errorMessage, successMessage, loginPath, forgotPasswordPath, passwordRequirements, alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, imageSrc, imageAlt, imageBackgroundColor, }?: ResetPasswordPageProps): import("react/jsx-runtime").JSX.Element;
24
- export default ResetPasswordPage;
25
- //# sourceMappingURL=reset_password.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reset_password.d.ts","sourceRoot":"","sources":["../../src/page_components/reset_password.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,0DAA0D,CAAC;AAgB7G,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,4BAA4B,CAAC;IACpD,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,YAAmE,EACnE,cAAwF,EACxF,SAA8B,EAC9B,kBAAiD,EACjD,oBAAoD,EACpD,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,QAA4B,EAC5B,QAA4B,EAC5B,oBAAuC,GACxC,GAAE,sBAA2B,2CAsC7B;AAED,eAAe,iBAAiB,CAAC"}
@@ -1,57 +0,0 @@
1
- // file_description: zero-config reset password page component for hazo_auth
2
- // Consumers can use this directly without needing to configure props
3
- //
4
- // ⚠️ DEPRECATED: This client component is deprecated in hazo_auth v2.0+
5
- // Please use the new server component version instead:
6
- //
7
- // import { ResetPasswordPage } from "hazo_auth/pages/reset_password";
8
- //
9
- // The new version:
10
- // - Initializes on the server (no loading state)
11
- // - Works with your app's hazo_connect instance
12
- // - True zero-config "drop in and use"
13
- // - Better performance (smaller bundle)
14
- //
15
- // This file will be removed in v3.0
16
- //
17
- "use client";
18
- import { jsx as _jsx } from "react/jsx-runtime";
19
- // section: imports
20
- import { useEffect, useState } from "react";
21
- import reset_password_layout from "../components/layouts/reset_password/index.js";
22
- import { createLayoutDataClient } from "../components/layouts/shared/data/layout_data_client.js";
23
- import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
24
- // section: constants
25
- const DEFAULT_IMAGE_SRC = "/hazo_auth/images/reset_password_default.jpg";
26
- const DEFAULT_IMAGE_ALT = "Illustration of a globe representing secure authentication workflows";
27
- const DEFAULT_IMAGE_BG = "#f1f5f9";
28
- const DEFAULT_PASSWORD_REQUIREMENTS = {
29
- minimum_length: 8,
30
- require_uppercase: true,
31
- require_lowercase: true,
32
- require_number: true,
33
- require_special: false,
34
- };
35
- // section: component
36
- /**
37
- * Zero-config reset password page component
38
- * Uses sensible defaults and can be customized via props
39
- * @param props - Optional configuration overrides
40
- * @returns Reset password page component
41
- */
42
- export function ResetPasswordPage({ errorMessage = "Your password reset link has expired or is invalid", successMessage = "Password reset successful! You can now log in with your new password.", loginPath = "/hazo_auth/login", forgotPasswordPath = "/hazo_auth/forgot_password", passwordRequirements = DEFAULT_PASSWORD_REQUIREMENTS, alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", imageSrc = DEFAULT_IMAGE_SRC, imageAlt = DEFAULT_IMAGE_ALT, imageBackgroundColor = DEFAULT_IMAGE_BG, } = {}) {
43
- const [dataClient, setDataClient] = useState(null);
44
- useEffect(() => {
45
- // Initialize hazo_connect on client side
46
- const hazoConnect = create_sqlite_hazo_connect();
47
- const client = createLayoutDataClient(hazoConnect);
48
- setDataClient(client);
49
- }, []);
50
- // Show loading state while initializing
51
- if (!dataClient) {
52
- return (_jsx("div", { className: "cls_reset_password_page_loading flex items-center justify-center min-h-screen", children: _jsx("div", { className: "text-slate-600 animate-pulse", children: "Loading..." }) }));
53
- }
54
- const ResetPasswordLayout = reset_password_layout;
55
- return (_jsx(ResetPasswordLayout, { image_src: imageSrc, image_alt: imageAlt, image_background_color: imageBackgroundColor, data_client: dataClient, errorMessage: errorMessage, successMessage: successMessage, password_requirements: passwordRequirements, alreadyLoggedInMessage: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath }));
56
- }
57
- export default ResetPasswordPage;
@@ -1,21 +0,0 @@
1
- export type VerifyEmailPageProps = {
2
- alreadyLoggedInMessage?: string;
3
- showLogoutButton?: boolean;
4
- showReturnHomeButton?: boolean;
5
- returnHomeButtonLabel?: string;
6
- returnHomePath?: string;
7
- redirectDelay?: number;
8
- loginPath?: string;
9
- imageSrc?: string;
10
- imageAlt?: string;
11
- imageBackgroundColor?: string;
12
- };
13
- /**
14
- * Zero-config verify email page component
15
- * Uses sensible defaults and can be customized via props
16
- * @param props - Optional configuration overrides
17
- * @returns Verify email page component
18
- */
19
- export declare function VerifyEmailPage({ alreadyLoggedInMessage, showLogoutButton, showReturnHomeButton, returnHomeButtonLabel, returnHomePath, redirectDelay, loginPath, imageSrc, imageAlt, imageBackgroundColor, }?: VerifyEmailPageProps): import("react/jsx-runtime").JSX.Element;
20
- export default VerifyEmailPage;
21
- //# sourceMappingURL=verify_email.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verify_email.d.ts","sourceRoot":"","sources":["../../src/page_components/verify_email.tsx"],"names":[],"mappings":"AA+BA,MAAM,MAAM,oBAAoB,GAAG;IACjC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAC9B,sBAAoD,EACpD,gBAAuB,EACvB,oBAA4B,EAC5B,qBAAqC,EACrC,cAAoB,EACpB,aAAoB,EACpB,SAA8B,EAC9B,QAA4B,EAC5B,QAA4B,EAC5B,oBAAuC,GACxC,GAAE,oBAAyB,2CAqC3B;AAED,eAAe,eAAe,CAAC"}
@@ -1,50 +0,0 @@
1
- // file_description: zero-config verify email page component for hazo_auth
2
- // Consumers can use this directly without needing to configure props
3
- //
4
- // ⚠️ DEPRECATED: This client component is deprecated in hazo_auth v2.0+
5
- // Please use the new server component version instead:
6
- //
7
- // import { VerifyEmailPage } from "hazo_auth/pages/verify_email";
8
- //
9
- // The new version:
10
- // - Initializes on the server (no loading state)
11
- // - Works with your app's hazo_connect instance
12
- // - True zero-config "drop in and use"
13
- // - Better performance (smaller bundle)
14
- //
15
- // This file will be removed in v3.0
16
- //
17
- "use client";
18
- import { jsx as _jsx } from "react/jsx-runtime";
19
- // section: imports
20
- import { useEffect, useState } from "react";
21
- import email_verification_layout from "../components/layouts/email_verification/index.js";
22
- import { createLayoutDataClient } from "../components/layouts/shared/data/layout_data_client.js";
23
- import { create_sqlite_hazo_connect } from "../lib/hazo_connect_setup.js";
24
- // section: constants
25
- const DEFAULT_IMAGE_SRC = "/hazo_auth/images/verify_email_default.jpg";
26
- const DEFAULT_IMAGE_ALT = "Illustration of a globe representing secure authentication workflows";
27
- const DEFAULT_IMAGE_BG = "#f1f5f9";
28
- // section: component
29
- /**
30
- * Zero-config verify email page component
31
- * Uses sensible defaults and can be customized via props
32
- * @param props - Optional configuration overrides
33
- * @returns Verify email page component
34
- */
35
- export function VerifyEmailPage({ alreadyLoggedInMessage = "You are already logged in", showLogoutButton = true, showReturnHomeButton = false, returnHomeButtonLabel = "Return home", returnHomePath = "/", redirectDelay = 3000, loginPath = "/hazo_auth/login", imageSrc = DEFAULT_IMAGE_SRC, imageAlt = DEFAULT_IMAGE_ALT, imageBackgroundColor = DEFAULT_IMAGE_BG, } = {}) {
36
- const [dataClient, setDataClient] = useState(null);
37
- useEffect(() => {
38
- // Initialize hazo_connect on client side
39
- const hazoConnect = create_sqlite_hazo_connect();
40
- const client = createLayoutDataClient(hazoConnect);
41
- setDataClient(client);
42
- }, []);
43
- // Show loading state while initializing
44
- if (!dataClient) {
45
- return (_jsx("div", { className: "cls_verify_email_page_loading flex items-center justify-center min-h-screen", children: _jsx("div", { className: "text-slate-600 animate-pulse", children: "Loading..." }) }));
46
- }
47
- const EmailVerificationLayout = email_verification_layout;
48
- return (_jsx(EmailVerificationLayout, { image_src: imageSrc, image_alt: imageAlt, image_background_color: imageBackgroundColor, data_client: dataClient, already_logged_in_message: alreadyLoggedInMessage, showLogoutButton: showLogoutButton, showReturnHomeButton: showReturnHomeButton, returnHomeButtonLabel: returnHomeButtonLabel, returnHomePath: returnHomePath, redirect_delay: redirectDelay, login_path: loginPath }));
49
- }
50
- export default VerifyEmailPage;