hazo_auth 1.0.5 → 1.2.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 (31) hide show
  1. package/README.md +341 -0
  2. package/hazo_auth_config.example.ini +41 -0
  3. package/instrumentation.ts +2 -2
  4. package/package.json +2 -1
  5. package/scripts/init_users.ts +378 -0
  6. package/src/app/api/hazo_auth/login/route.ts +27 -1
  7. package/src/app/api/hazo_auth/register/route.ts +13 -10
  8. package/src/app/hazo_auth/forgot_password/page.tsx +3 -3
  9. package/src/app/hazo_auth/login/login_page_client.tsx +15 -0
  10. package/src/app/hazo_auth/login/page.tsx +16 -4
  11. package/src/app/hazo_auth/my_settings/page.tsx +3 -3
  12. package/src/app/hazo_auth/register/page.tsx +14 -4
  13. package/src/app/hazo_auth/register/register_page_client.tsx +9 -0
  14. package/src/app/hazo_auth/reset_password/page.tsx +3 -3
  15. package/src/app/hazo_auth/user_management/page.tsx +3 -3
  16. package/src/app/hazo_auth/verify_email/page.tsx +3 -3
  17. package/src/components/layouts/login/hooks/use_login_form.ts +13 -8
  18. package/src/components/layouts/login/index.tsx +28 -0
  19. package/src/components/layouts/register/hooks/use_register_form.ts +4 -1
  20. package/src/components/layouts/register/index.tsx +18 -0
  21. package/src/components/layouts/shared/components/auth_page_shell.tsx +36 -0
  22. package/src/components/layouts/shared/components/standalone_layout_wrapper.tsx +53 -0
  23. package/src/lib/config/config_loader.server.ts +20 -5
  24. package/src/lib/login_config.server.ts +25 -0
  25. package/src/lib/register_config.server.ts +17 -1
  26. package/src/lib/services/login_service.ts +19 -3
  27. package/src/lib/services/registration_service.ts +25 -4
  28. package/src/lib/services/user_profiles_service.ts +143 -0
  29. package/src/lib/services/user_update_service.ts +16 -3
  30. package/src/lib/ui_shell_config.server.ts +73 -0
  31. package/src/lib/utils/error_sanitizer.ts +75 -0
package/README.md CHANGED
@@ -29,6 +29,215 @@ After installing the package, you need to set up configuration files in your pro
29
29
 
30
30
  **Important:** The configuration files must be located in your project root directory (where `process.cwd()` points to), not inside `node_modules`. The package reads configuration from `process.cwd()` at runtime, so storing them elsewhere (including `node_modules/hazo_auth`) will break runtime access.
31
31
 
32
+ ### Database Setup
33
+
34
+ Before using `hazo_auth`, you need to create the required database tables. Run the following SQL scripts in your PostgreSQL database:
35
+
36
+ #### 1. Create the Profile Source Enum Type
37
+
38
+ ```sql
39
+ -- Enum type for profile picture source
40
+ CREATE TYPE hazo_enum_profile_source_enum AS ENUM ('gravatar', 'custom', 'predefined');
41
+ ```
42
+
43
+ #### 2. Create the Users Table
44
+
45
+ ```sql
46
+ -- Main users table
47
+ CREATE TABLE hazo_users (
48
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
49
+ email_address TEXT NOT NULL UNIQUE,
50
+ password_hash TEXT NOT NULL,
51
+ name TEXT,
52
+ email_verified BOOLEAN NOT NULL DEFAULT FALSE,
53
+ is_active BOOLEAN NOT NULL DEFAULT TRUE,
54
+ login_attempts INTEGER NOT NULL DEFAULT 0,
55
+ last_logon TIMESTAMP WITH TIME ZONE,
56
+ profile_picture_url TEXT,
57
+ profile_source hazo_enum_profile_source_enum,
58
+ mfa_secret TEXT,
59
+ url_on_logon TEXT,
60
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
61
+ changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
62
+ );
63
+
64
+ -- Index for email lookups
65
+ CREATE INDEX idx_hazo_users_email ON hazo_users(email_address);
66
+ ```
67
+
68
+ #### 3. Create the Refresh Tokens Table
69
+
70
+ ```sql
71
+ -- Refresh tokens table (used for password reset, email verification, etc.)
72
+ CREATE TABLE hazo_refresh_tokens (
73
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
74
+ user_id UUID NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,
75
+ token_hash TEXT NOT NULL,
76
+ token_type TEXT NOT NULL,
77
+ expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
78
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
79
+ );
80
+
81
+ -- Index for token lookups
82
+ CREATE INDEX idx_hazo_refresh_tokens_user_id ON hazo_refresh_tokens(user_id);
83
+ CREATE INDEX idx_hazo_refresh_tokens_token_type ON hazo_refresh_tokens(token_type);
84
+ ```
85
+
86
+ #### 4. Create the Permissions Table
87
+
88
+ ```sql
89
+ -- Permissions table for RBAC
90
+ CREATE TABLE hazo_permissions (
91
+ id SERIAL PRIMARY KEY,
92
+ permission_name TEXT NOT NULL UNIQUE,
93
+ description TEXT,
94
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
95
+ changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
96
+ );
97
+ ```
98
+
99
+ #### 5. Create the Roles Table
100
+
101
+ ```sql
102
+ -- Roles table for RBAC
103
+ CREATE TABLE hazo_roles (
104
+ id SERIAL PRIMARY KEY,
105
+ role_name TEXT NOT NULL UNIQUE,
106
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
107
+ changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
108
+ );
109
+ ```
110
+
111
+ #### 6. Create the Role-Permissions Junction Table
112
+
113
+ ```sql
114
+ -- Junction table linking roles to permissions
115
+ CREATE TABLE hazo_role_permissions (
116
+ role_id INTEGER NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
117
+ permission_id INTEGER NOT NULL REFERENCES hazo_permissions(id) ON DELETE CASCADE,
118
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
119
+ changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
120
+ PRIMARY KEY (role_id, permission_id)
121
+ );
122
+
123
+ -- Indexes for lookups
124
+ CREATE INDEX idx_hazo_role_permissions_role_id ON hazo_role_permissions(role_id);
125
+ CREATE INDEX idx_hazo_role_permissions_permission_id ON hazo_role_permissions(permission_id);
126
+ ```
127
+
128
+ #### 7. Create the User-Roles Junction Table
129
+
130
+ ```sql
131
+ -- Junction table linking users to roles
132
+ CREATE TABLE hazo_user_roles (
133
+ user_id UUID NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,
134
+ role_id INTEGER NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
135
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
136
+ changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
137
+ PRIMARY KEY (user_id, role_id)
138
+ );
139
+
140
+ -- Indexes for lookups
141
+ CREATE INDEX idx_hazo_user_roles_user_id ON hazo_user_roles(user_id);
142
+ CREATE INDEX idx_hazo_user_roles_role_id ON hazo_user_roles(role_id);
143
+ ```
144
+
145
+ #### Complete Setup Script
146
+
147
+ For convenience, here's the complete SQL script to create all tables at once:
148
+
149
+ ```sql
150
+ -- ============================================
151
+ -- hazo_auth Database Setup Script
152
+ -- ============================================
153
+
154
+ -- 1. Create enum type
155
+ CREATE TYPE hazo_enum_profile_source_enum AS ENUM ('gravatar', 'custom', 'predefined');
156
+
157
+ -- 2. Create users table
158
+ CREATE TABLE hazo_users (
159
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
160
+ email_address TEXT NOT NULL UNIQUE,
161
+ password_hash TEXT NOT NULL,
162
+ name TEXT,
163
+ email_verified BOOLEAN NOT NULL DEFAULT FALSE,
164
+ is_active BOOLEAN NOT NULL DEFAULT TRUE,
165
+ login_attempts INTEGER NOT NULL DEFAULT 0,
166
+ last_logon TIMESTAMP WITH TIME ZONE,
167
+ profile_picture_url TEXT,
168
+ profile_source hazo_enum_profile_source_enum,
169
+ mfa_secret TEXT,
170
+ url_on_logon TEXT,
171
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
172
+ changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
173
+ );
174
+ CREATE INDEX idx_hazo_users_email ON hazo_users(email_address);
175
+
176
+ -- 3. Create refresh tokens table
177
+ CREATE TABLE hazo_refresh_tokens (
178
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
179
+ user_id UUID NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,
180
+ token_hash TEXT NOT NULL,
181
+ token_type TEXT NOT NULL,
182
+ expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
183
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
184
+ );
185
+ CREATE INDEX idx_hazo_refresh_tokens_user_id ON hazo_refresh_tokens(user_id);
186
+ CREATE INDEX idx_hazo_refresh_tokens_token_type ON hazo_refresh_tokens(token_type);
187
+
188
+ -- 4. Create permissions table
189
+ CREATE TABLE hazo_permissions (
190
+ id SERIAL PRIMARY KEY,
191
+ permission_name TEXT NOT NULL UNIQUE,
192
+ description TEXT,
193
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
194
+ changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
195
+ );
196
+
197
+ -- 5. Create roles table
198
+ CREATE TABLE hazo_roles (
199
+ id SERIAL PRIMARY KEY,
200
+ role_name TEXT NOT NULL UNIQUE,
201
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
202
+ changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
203
+ );
204
+
205
+ -- 6. Create role-permissions junction table
206
+ CREATE TABLE hazo_role_permissions (
207
+ role_id INTEGER NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
208
+ permission_id INTEGER NOT NULL REFERENCES hazo_permissions(id) ON DELETE CASCADE,
209
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
210
+ changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
211
+ PRIMARY KEY (role_id, permission_id)
212
+ );
213
+ CREATE INDEX idx_hazo_role_permissions_role_id ON hazo_role_permissions(role_id);
214
+ CREATE INDEX idx_hazo_role_permissions_permission_id ON hazo_role_permissions(permission_id);
215
+
216
+ -- 7. Create user-roles junction table
217
+ CREATE TABLE hazo_user_roles (
218
+ user_id UUID NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,
219
+ role_id INTEGER NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
220
+ created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
221
+ changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
222
+ PRIMARY KEY (user_id, role_id)
223
+ );
224
+ CREATE INDEX idx_hazo_user_roles_user_id ON hazo_user_roles(user_id);
225
+ CREATE INDEX idx_hazo_user_roles_role_id ON hazo_user_roles(role_id);
226
+ ```
227
+
228
+ #### Initialize Default Permissions and Super User
229
+
230
+ After creating the tables, you can use the `init-users` script to set up default permissions and a super user:
231
+
232
+ ```bash
233
+ npm run init-users
234
+ ```
235
+
236
+ This script reads from `hazo_auth_config.ini` and:
237
+ 1. Creates default permissions from `application_permission_list_defaults`
238
+ 2. Creates a `default_super_user_role` role with all permissions
239
+ 3. Assigns the role to the user specified in `default_super_user_email`
240
+
32
241
  ### Expose hazo_auth Routes in the Consumer App
33
242
 
34
243
  Because `src/app/hazo_auth` (pages) and `src/app/api/hazo_auth` (API routes) need to be part of the consuming Next.js app’s routing tree, make sure they exist in your project’s `src/app` directory. Two recommended approaches:
@@ -50,6 +259,56 @@ Because `src/app/hazo_auth` (pages) and `src/app/api/hazo_auth` (API routes) nee
50
259
 
51
260
  > The package expects these routes to live at `src/app/api/hazo_auth` and `src/app/hazo_auth` inside the consumer project. Without copying or linking them, Next.js won’t mount the auth pages or APIs.
52
261
 
262
+ ### Choose the UI Shell (Test Sidebar vs Standalone)
263
+
264
+ By default, the pages render inside the “test workspace” sidebar so you can quickly preview every flow. When you reuse the routes inside another project you’ll usually want a clean, standalone wrapper instead. Set this in `hazo_auth_config.ini`:
265
+
266
+ ```ini
267
+ [hazo_auth__ui_shell]
268
+ # Options: test_sidebar | standalone
269
+ layout_mode = standalone
270
+ # Optional tweaks for the standalone header wrapper/classes:
271
+ # standalone_heading = Welcome back
272
+ # standalone_description = Your description here
273
+ # standalone_wrapper_class = min-h-screen bg-background py-8
274
+ # standalone_content_class = mx-auto w-full max-w-4xl rounded-2xl border bg-card
275
+ ```
276
+
277
+ - `test_sidebar`: keeps the developer sidebar (perfect for the demo workspace or Storybook screenshots).
278
+ - `standalone`: renders the page body directly so it inherits your own app shell, layout, and theme tokens.
279
+ - The wrapper and content class overrides let you align spacing/borders with your design system without editing package code.
280
+
281
+ Every route (`/hazo_auth/login`, `/hazo_auth/register`, etc.) automatically looks at this config, so switching modes is instant.
282
+
283
+ ### Using Just the Layout Components
284
+
285
+ Prefer to drop the forms into your own routes without copying the provided pages? Import the layouts directly and feed them a `data_client` plus any label/button overrides:
286
+
287
+ ```tsx
288
+ // app/(auth)/login/page.tsx in your project
289
+ import login_layout from "hazo_auth/components/layouts/login";
290
+ import { createLayoutDataClient } from "hazo_auth/components/layouts/shared/data/layout_data_client";
291
+ import { create_sqlite_hazo_connect } from "hazo_auth/lib/hazo_connect_setup";
292
+
293
+ export default async function LoginPage() {
294
+ const hazoConnect = create_sqlite_hazo_connect();
295
+ const dataClient = createLayoutDataClient(hazoConnect);
296
+ const LoginLayout = login_layout;
297
+
298
+ return (
299
+ <div className="my-app-shell">
300
+ <LoginLayout
301
+ image_src="/marketing/login-hero.svg"
302
+ data_client={dataClient}
303
+ redirectRoute="/dashboard"
304
+ />
305
+ </div>
306
+ );
307
+ }
308
+ ```
309
+
310
+ The same import pattern works for every layout under `components/layouts/*`, so you can mix-and-match pieces (profile picture dialog, password field, etc.) wherever you need them.
311
+
53
312
  ## Authentication Service
54
313
 
55
314
  The `hazo_auth` package provides a comprehensive authentication and authorization system with role-based access control (RBAC). The main authentication utility is `hazo_get_auth`, which provides user details, permissions, and permission checking with built-in caching and rate limiting.
@@ -959,6 +1218,88 @@ Example custom styling:
959
1218
  }
960
1219
  ```
961
1220
 
1221
+ ## User Profile Service
1222
+
1223
+ The `hazo_auth` package provides a batch user profile retrieval service for applications that need basic user information, such as chat applications or user lists.
1224
+
1225
+ ### `hazo_get_user_profiles`
1226
+
1227
+ Retrieves basic profile information for multiple users in a single batch call.
1228
+
1229
+ **Location:** `src/lib/services/user_profiles_service.ts`
1230
+
1231
+ **Function Signature:**
1232
+ ```typescript
1233
+ import { hazo_get_user_profiles } from "hazo_auth/lib/services/user_profiles_service";
1234
+ import type { GetProfilesResult, UserProfileInfo } from "hazo_auth/lib/services/user_profiles_service";
1235
+
1236
+ async function hazo_get_user_profiles(
1237
+ adapter: HazoConnectAdapter,
1238
+ user_ids: string[],
1239
+ ): Promise<GetProfilesResult>
1240
+ ```
1241
+
1242
+ **Return Type:**
1243
+ ```typescript
1244
+ type UserProfileInfo = {
1245
+ user_id: string;
1246
+ profile_picture_url: string | null;
1247
+ email: string;
1248
+ name: string | null;
1249
+ days_since_created: number;
1250
+ };
1251
+
1252
+ type GetProfilesResult = {
1253
+ success: boolean;
1254
+ profiles: UserProfileInfo[];
1255
+ not_found_ids: string[];
1256
+ error?: string;
1257
+ };
1258
+ ```
1259
+
1260
+ **Features:**
1261
+ - **Batch Retrieval:** Fetches multiple user profiles in a single database query
1262
+ - **Deduplication:** Automatically removes duplicate user IDs from input
1263
+ - **Not Found Tracking:** Returns list of user IDs that were not found in the database
1264
+ - **Profile Picture:** Returns the resolved profile picture URL (Gravatar, library, or uploaded)
1265
+ - **Account Age:** Calculates days since account creation
1266
+
1267
+ **Example Usage:**
1268
+
1269
+ ```typescript
1270
+ // In an API route or server component
1271
+ import { hazo_get_user_profiles } from "hazo_auth/lib/services/user_profiles_service";
1272
+ import { get_hazo_connect_instance } from "hazo_auth/lib/hazo_connect_instance.server";
1273
+
1274
+ export async function GET(request: NextRequest) {
1275
+ const adapter = get_hazo_connect_instance();
1276
+
1277
+ // Get profiles for multiple users (e.g., chat participants)
1278
+ const result = await hazo_get_user_profiles(adapter, [
1279
+ "user-id-1",
1280
+ "user-id-2",
1281
+ "user-id-3",
1282
+ ]);
1283
+
1284
+ if (!result.success) {
1285
+ return NextResponse.json({ error: result.error }, { status: 500 });
1286
+ }
1287
+
1288
+ // result.profiles contains found user profiles
1289
+ // result.not_found_ids contains IDs that weren't found
1290
+ return NextResponse.json({
1291
+ profiles: result.profiles,
1292
+ not_found: result.not_found_ids,
1293
+ });
1294
+ }
1295
+ ```
1296
+
1297
+ **Use Cases:**
1298
+ - Chat applications displaying participant information
1299
+ - User lists with profile pictures and names
1300
+ - Activity feeds showing user details
1301
+ - Any feature requiring batch user profile lookups
1302
+
962
1303
  ### Local Development (for package contributors)
963
1304
 
964
1305
  - `npm install` to install dependencies.
@@ -7,6 +7,31 @@
7
7
  # Database type: sqlite, postgrest, supabase, or file
8
8
  type = sqlite
9
9
 
10
+ # UI shell controls whether pages render inside the developer sidebar or a minimal wrapper.
11
+ [hazo_auth__ui_shell]
12
+ # layout_mode = test_sidebar
13
+ # Options:
14
+ # - test_sidebar: keeps the demo sidebar for quick testing in the package workspace.
15
+ # - standalone: renders pages in a minimal wrapper so consumers inherit their own shell/theme.
16
+ #
17
+ # Heading shown above standalone layouts
18
+ # standalone_heading = Welcome to hazo auth
19
+ #
20
+ # Description beneath the heading for standalone layouts
21
+ # standalone_description = Reuse the packaged authentication flows while inheriting your existing app shell styles.
22
+ #
23
+ # Tailwind utility classes applied to the standalone wrapper div
24
+ # standalone_wrapper_class = cls_standalone_shell flex min-h-screen w-full items-center justify-center bg-background px-4 py-10
25
+ #
26
+ # Tailwind utility classes applied to the standalone inner content div
27
+ # standalone_content_class = cls_standalone_shell_content w-full max-w-5xl shadow-xl rounded-2xl border bg-card
28
+ #
29
+ # Show/hide heading in standalone mode (true/false, default: true)
30
+ # standalone_show_heading = true
31
+ #
32
+ # Show/hide description in standalone mode (true/false, default: true)
33
+ # standalone_show_description = true
34
+
10
35
  # SQLite database configuration
11
36
  # Path to SQLite database file (relative to process.cwd() or absolute)
12
37
  sqlite_path = ./data/hazo_auth.sqlite
@@ -57,6 +82,10 @@ enable_admin_ui = true
57
82
  # Show name field (true/false)
58
83
  # Note: This is now deprecated, use hazo_auth__user_fields section instead
59
84
  # show_name_field = false
85
+ #
86
+ # Sign in link shown below register button
87
+ # sign_in_path = /hazo_auth/login
88
+ # sign_in_label = Sign in
60
89
 
61
90
  [hazo_auth__user_fields]
62
91
  # Shared user fields configuration used by register and my_settings layouts
@@ -104,6 +133,12 @@ enable_admin_ui = true
104
133
  # Redirect on successful login (leave empty to show success message instead)
105
134
  # redirect_route_on_successful_login = /
106
135
 
136
+ # Forgot password + sign up links shown under login button
137
+ # forgot_password_path = /hazo_auth/forgot_password
138
+ # forgot_password_label = Forgot password?
139
+ # create_account_path = /hazo_auth/register
140
+ # create_account_label = Create account
141
+
107
142
  # Success message (shown when no redirect route is provided)
108
143
  # success_message = Successfully logged in
109
144
 
@@ -263,6 +298,12 @@ enable_admin_ui = true
263
298
  # Example: application_permission_list_defaults = PERM_ONE,PERM_TWO,PERM_THREE
264
299
  # application_permission_list_defaults =
265
300
 
301
+ [hazo_auth__initial_setup]
302
+ # Initial setup configuration for initializing users, roles, and permissions
303
+ # Email address of the super user to assign the default_super_user_role
304
+ # This user will receive all permissions from application_permission_list_defaults
305
+ # default_super_user_email = admin@example.com
306
+
266
307
  [hazo_auth__auth_utility]
267
308
  # Authentication utility configuration
268
309
 
@@ -9,13 +9,13 @@ export async function register() {
9
9
  const hazo_notify_module = await import("hazo_notify");
10
10
 
11
11
  // Step 2: Load hazo_notify emailer configuration
12
- // This reads from hazo_notify_config.ini in the project root (same location as hazo_auth_config.ini)
12
+ // This reads from hazo_notify_config.ini in the ui_component directory (same location as hazo_auth_config.ini)
13
13
  const { load_emailer_config } = hazo_notify_module;
14
14
  const notify_config = load_emailer_config();
15
15
 
16
16
  // Step 3: Pass the initialized configuration to hazo_auth email service
17
17
  // This allows the email service to reuse the same configuration instance
18
- const { set_hazo_notify_instance } = await import("@/lib/services/email_service");
18
+ const { set_hazo_notify_instance } = await import("./src/lib/services/email_service");
19
19
  set_hazo_notify_instance(notify_config);
20
20
 
21
21
  // Log successful initialization
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_auth",
3
- "version": "1.0.5",
3
+ "version": "1.2.0",
4
4
  "files": [
5
5
  "src/**/*",
6
6
  "public/file.svg",
@@ -31,6 +31,7 @@
31
31
  "build-storybook": "storybook build",
32
32
  "dev:server": "tsx src/server/index.ts",
33
33
  "migrate": "tsx scripts/apply_migration.ts",
34
+ "init-users": "tsx scripts/init_users.ts init_users",
34
35
  "test": "cross-env NODE_ENV=test POSTGREST_URL=http://209.38.26.241:4402 POSTGREST_API_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYXBpX3VzZXIifQ.zBoUGymrxTUk1DNYIGUCtQU4HFaWEHlbE9_8Y3hUaTw jest --runInBand",
35
36
  "test:watch": "cross-env NODE_ENV=test POSTGREST_URL=http://209.38.26.241:4402 POSTGREST_API_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYXBpX3VzZXIifQ.zBoUGymrxTUk1DNYIGUCtQU4HFaWEHlbE9_8Y3hUaTw jest --watch"
36
37
  },