hazo_auth 4.1.0 → 4.3.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 (157) hide show
  1. package/README.md +230 -0
  2. package/SETUP_CHECKLIST.md +202 -0
  3. package/bin/hazo_auth.mjs +35 -0
  4. package/cli-src/assets/images/forgot_password_default.jpg +0 -0
  5. package/cli-src/assets/images/login_default.jpg +0 -0
  6. package/cli-src/assets/images/register_default.jpg +0 -0
  7. package/cli-src/assets/images/reset_password_default.jpg +0 -0
  8. package/cli-src/assets/images/verify_email_default.jpg +0 -0
  9. package/cli-src/cli/generate.ts +276 -0
  10. package/cli-src/cli/index.ts +207 -0
  11. package/cli-src/cli/init.ts +254 -0
  12. package/cli-src/cli/init_users.ts +376 -0
  13. package/cli-src/cli/validate.ts +581 -0
  14. package/cli-src/lib/already_logged_in_config.server.ts +46 -0
  15. package/cli-src/lib/app_logger.ts +24 -0
  16. package/cli-src/lib/auth/auth_cache.ts +220 -0
  17. package/cli-src/lib/auth/auth_rate_limiter.ts +121 -0
  18. package/cli-src/lib/auth/auth_types.ts +110 -0
  19. package/cli-src/lib/auth/auth_utils.server.ts +196 -0
  20. package/cli-src/lib/auth/hazo_get_auth.server.ts +512 -0
  21. package/cli-src/lib/auth/index.ts +23 -0
  22. package/cli-src/lib/auth/nextauth_config.ts +227 -0
  23. package/cli-src/lib/auth/scope_cache.ts +233 -0
  24. package/cli-src/lib/auth/server_auth.ts +88 -0
  25. package/cli-src/lib/auth/session_token_validator.edge.ts +91 -0
  26. package/cli-src/lib/auth_utility_config.server.ts +136 -0
  27. package/cli-src/lib/config/config_loader.server.ts +164 -0
  28. package/cli-src/lib/config/default_config.ts +199 -0
  29. package/cli-src/lib/email_verification_config.server.ts +63 -0
  30. package/cli-src/lib/file_types_config.server.ts +25 -0
  31. package/cli-src/lib/forgot_password_config.server.ts +63 -0
  32. package/cli-src/lib/hazo_connect_instance.server.ts +101 -0
  33. package/cli-src/lib/hazo_connect_setup.server.ts +194 -0
  34. package/cli-src/lib/hazo_connect_setup.ts +54 -0
  35. package/cli-src/lib/index.ts +46 -0
  36. package/cli-src/lib/login_config.server.ts +106 -0
  37. package/cli-src/lib/messages_config.server.ts +45 -0
  38. package/cli-src/lib/migrations/apply_migration.ts +105 -0
  39. package/cli-src/lib/my_settings_config.server.ts +135 -0
  40. package/cli-src/lib/oauth_config.server.ts +87 -0
  41. package/cli-src/lib/password_requirements_config.server.ts +40 -0
  42. package/cli-src/lib/profile_pic_menu_config.server.ts +138 -0
  43. package/cli-src/lib/profile_picture_config.server.ts +56 -0
  44. package/cli-src/lib/register_config.server.ts +101 -0
  45. package/cli-src/lib/reset_password_config.server.ts +103 -0
  46. package/cli-src/lib/scope_hierarchy_config.server.ts +151 -0
  47. package/cli-src/lib/services/email_service.ts +587 -0
  48. package/cli-src/lib/services/email_verification_service.ts +270 -0
  49. package/cli-src/lib/services/index.ts +16 -0
  50. package/cli-src/lib/services/login_service.ts +150 -0
  51. package/cli-src/lib/services/oauth_service.ts +494 -0
  52. package/cli-src/lib/services/password_change_service.ts +154 -0
  53. package/cli-src/lib/services/password_reset_service.ts +418 -0
  54. package/cli-src/lib/services/profile_picture_remove_service.ts +120 -0
  55. package/cli-src/lib/services/profile_picture_service.ts +451 -0
  56. package/cli-src/lib/services/profile_picture_source_mapper.ts +62 -0
  57. package/cli-src/lib/services/registration_service.ts +185 -0
  58. package/cli-src/lib/services/scope_labels_service.ts +348 -0
  59. package/cli-src/lib/services/scope_service.ts +778 -0
  60. package/cli-src/lib/services/session_token_service.ts +177 -0
  61. package/cli-src/lib/services/token_service.ts +240 -0
  62. package/cli-src/lib/services/user_profiles_cache.ts +189 -0
  63. package/cli-src/lib/services/user_profiles_service.ts +264 -0
  64. package/cli-src/lib/services/user_scope_service.ts +554 -0
  65. package/cli-src/lib/services/user_update_service.ts +141 -0
  66. package/cli-src/lib/ui_shell_config.server.ts +73 -0
  67. package/cli-src/lib/ui_sizes_config.server.ts +37 -0
  68. package/cli-src/lib/user_fields_config.server.ts +31 -0
  69. package/cli-src/lib/user_management_config.server.ts +39 -0
  70. package/cli-src/lib/user_profiles_config.server.ts +55 -0
  71. package/cli-src/lib/utils/api_route_helpers.ts +60 -0
  72. package/cli-src/lib/utils/error_sanitizer.ts +75 -0
  73. package/cli-src/lib/utils/password_validator.ts +65 -0
  74. package/cli-src/lib/utils.ts +11 -0
  75. package/cli-src/server/logging/logger_service.ts +56 -0
  76. package/dist/app/api/hazo_auth/forgot_password/route.d.ts.map +1 -1
  77. package/dist/app/api/hazo_auth/forgot_password/route.js +15 -0
  78. package/dist/app/api/hazo_auth/logout/route.d.ts.map +1 -1
  79. package/dist/app/api/hazo_auth/logout/route.js +31 -0
  80. package/dist/app/api/hazo_auth/me/route.d.ts.map +1 -1
  81. package/dist/app/api/hazo_auth/me/route.js +10 -0
  82. package/dist/cli/index.js +18 -0
  83. package/dist/cli/init_users.d.ts +17 -0
  84. package/dist/cli/init_users.d.ts.map +1 -0
  85. package/dist/cli/init_users.js +307 -0
  86. package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.d.ts +2 -0
  87. package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.d.ts.map +1 -1
  88. package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.js +8 -0
  89. package/dist/components/layouts/forgot_password/index.d.ts +7 -1
  90. package/dist/components/layouts/forgot_password/index.d.ts.map +1 -1
  91. package/dist/components/layouts/forgot_password/index.js +7 -2
  92. package/dist/components/layouts/login/index.d.ts +13 -1
  93. package/dist/components/layouts/login/index.d.ts.map +1 -1
  94. package/dist/components/layouts/login/index.js +11 -2
  95. package/dist/components/layouts/my_settings/components/connected_accounts_section.d.ts +17 -0
  96. package/dist/components/layouts/my_settings/components/connected_accounts_section.d.ts.map +1 -0
  97. package/dist/components/layouts/my_settings/components/connected_accounts_section.js +17 -0
  98. package/dist/components/layouts/my_settings/components/set_password_section.d.ts +26 -0
  99. package/dist/components/layouts/my_settings/components/set_password_section.d.ts.map +1 -0
  100. package/dist/components/layouts/my_settings/components/set_password_section.js +127 -0
  101. package/dist/components/layouts/my_settings/hooks/use_my_settings.d.ts +3 -0
  102. package/dist/components/layouts/my_settings/hooks/use_my_settings.d.ts.map +1 -1
  103. package/dist/components/layouts/my_settings/hooks/use_my_settings.js +9 -0
  104. package/dist/components/layouts/my_settings/index.d.ts.map +1 -1
  105. package/dist/components/layouts/my_settings/index.js +4 -2
  106. package/dist/components/layouts/shared/components/google_icon.d.ts +12 -0
  107. package/dist/components/layouts/shared/components/google_icon.d.ts.map +1 -0
  108. package/dist/components/layouts/shared/components/google_icon.js +9 -0
  109. package/dist/components/layouts/shared/components/google_sign_in_button.d.ts +21 -0
  110. package/dist/components/layouts/shared/components/google_sign_in_button.d.ts.map +1 -0
  111. package/dist/components/layouts/shared/components/google_sign_in_button.js +50 -0
  112. package/dist/components/layouts/shared/components/oauth_divider.d.ts +13 -0
  113. package/dist/components/layouts/shared/components/oauth_divider.d.ts.map +1 -0
  114. package/dist/components/layouts/shared/components/oauth_divider.js +13 -0
  115. package/dist/components/layouts/shared/config/layout_customization.d.ts +2 -7
  116. package/dist/components/layouts/shared/config/layout_customization.d.ts.map +1 -1
  117. package/dist/components/layouts/shared/hooks/use_auth_status.d.ts +3 -0
  118. package/dist/components/layouts/shared/hooks/use_auth_status.d.ts.map +1 -1
  119. package/dist/components/layouts/shared/hooks/use_auth_status.js +4 -0
  120. package/dist/components/layouts/shared/index.d.ts +5 -0
  121. package/dist/components/layouts/shared/index.d.ts.map +1 -1
  122. package/dist/components/layouts/shared/index.js +3 -0
  123. package/dist/components/ui/button.d.ts +1 -1
  124. package/dist/lib/auth/nextauth_config.d.ts +34 -0
  125. package/dist/lib/auth/nextauth_config.d.ts.map +1 -0
  126. package/dist/lib/auth/nextauth_config.js +171 -0
  127. package/dist/lib/config/default_config.d.ts +24 -0
  128. package/dist/lib/config/default_config.d.ts.map +1 -1
  129. package/dist/lib/config/default_config.js +14 -0
  130. package/dist/lib/index.d.ts +2 -0
  131. package/dist/lib/index.d.ts.map +1 -1
  132. package/dist/lib/index.js +1 -0
  133. package/dist/lib/login_config.server.d.ts +3 -0
  134. package/dist/lib/login_config.server.d.ts.map +1 -1
  135. package/dist/lib/login_config.server.js +4 -0
  136. package/dist/lib/oauth_config.server.d.ts +29 -0
  137. package/dist/lib/oauth_config.server.d.ts.map +1 -0
  138. package/dist/lib/oauth_config.server.js +40 -0
  139. package/dist/lib/services/login_service.d.ts.map +1 -1
  140. package/dist/lib/services/login_service.js +16 -1
  141. package/dist/lib/services/oauth_service.d.ts +88 -0
  142. package/dist/lib/services/oauth_service.d.ts.map +1 -0
  143. package/dist/lib/services/oauth_service.js +376 -0
  144. package/dist/lib/services/password_reset_service.d.ts +2 -0
  145. package/dist/lib/services/password_reset_service.d.ts.map +1 -1
  146. package/dist/lib/services/password_reset_service.js +10 -0
  147. package/dist/lib/services/registration_service.d.ts.map +1 -1
  148. package/dist/lib/services/registration_service.js +1 -0
  149. package/dist/lib/utils/password_validator.d.ts +19 -0
  150. package/dist/lib/utils/password_validator.d.ts.map +1 -0
  151. package/dist/lib/utils/password_validator.js +36 -0
  152. package/dist/server_pages/login.d.ts.map +1 -1
  153. package/dist/server_pages/login.js +6 -1
  154. package/dist/server_pages/login_client_wrapper.d.ts +5 -2
  155. package/dist/server_pages/login_client_wrapper.d.ts.map +1 -1
  156. package/dist/server_pages/login_client_wrapper.js +2 -2
  157. package/package.json +6 -2
@@ -0,0 +1,276 @@
1
+ // file_description: route and page generation logic for hazo_auth
2
+ // This module creates API route files and page files in consuming projects
3
+
4
+ import * as fs from "fs";
5
+ import * as path from "path";
6
+
7
+ // section: types
8
+ type RouteDefinition = {
9
+ name: string;
10
+ path: string;
11
+ method: string;
12
+ export_name: string;
13
+ };
14
+
15
+ type PageDefinition = {
16
+ name: string;
17
+ path: string;
18
+ component_name: string;
19
+ import_path: string;
20
+ };
21
+
22
+ export type GenerateOptions = {
23
+ dir?: string;
24
+ pages?: boolean;
25
+ all?: boolean;
26
+ };
27
+
28
+ // section: constants
29
+ const ROUTES: RouteDefinition[] = [
30
+ { name: "login", path: "api/hazo_auth/login", method: "POST", export_name: "loginPOST" },
31
+ { name: "register", path: "api/hazo_auth/register", method: "POST", export_name: "registerPOST" },
32
+ { name: "logout", path: "api/hazo_auth/logout", method: "POST", export_name: "logoutPOST" },
33
+ { name: "me", path: "api/hazo_auth/me", method: "GET", export_name: "meGET" },
34
+ { name: "forgot_password", path: "api/hazo_auth/forgot_password", method: "POST", export_name: "forgotPasswordPOST" },
35
+ { name: "reset_password", path: "api/hazo_auth/reset_password", method: "POST", export_name: "resetPasswordPOST" },
36
+ { name: "verify_email", path: "api/hazo_auth/verify_email", method: "GET", export_name: "verifyEmailGET" },
37
+ { name: "resend_verification", path: "api/hazo_auth/resend_verification", method: "POST", export_name: "resendVerificationPOST" },
38
+ { name: "update_user", path: "api/hazo_auth/update_user", method: "PATCH", export_name: "updateUserPATCH" },
39
+ { name: "change_password", path: "api/hazo_auth/change_password", method: "POST", export_name: "changePasswordPOST" },
40
+ { name: "upload_profile_picture", path: "api/hazo_auth/upload_profile_picture", method: "POST", export_name: "uploadProfilePicturePOST" },
41
+ { name: "remove_profile_picture", path: "api/hazo_auth/remove_profile_picture", method: "DELETE", export_name: "removeProfilePictureDELETE" },
42
+ { name: "library_photos", path: "api/hazo_auth/library_photos", method: "GET", export_name: "libraryPhotosGET" },
43
+ { name: "library_photo", path: "api/hazo_auth/library_photo/[category]/[filename]", method: "GET", export_name: "libraryPhotoGET" },
44
+ { name: "get_auth", path: "api/hazo_auth/get_auth", method: "POST", export_name: "getAuthPOST" },
45
+ { name: "validate_reset_token", path: "api/hazo_auth/validate_reset_token", method: "GET", export_name: "validateResetTokenGET" },
46
+ { name: "profile_picture_filename", path: "api/hazo_auth/profile_picture/[filename]", method: "GET", export_name: "profilePictureFilenameGET" },
47
+ { name: "invalidate_cache", path: "api/hazo_auth/invalidate_cache", method: "POST", export_name: "invalidateCachePOST" },
48
+ // User management routes
49
+ { name: "user_management_users", path: "api/hazo_auth/user_management/users", method: "GET", export_name: "userManagementUsersGET" },
50
+ { name: "user_management_users_patch", path: "api/hazo_auth/user_management/users", method: "PATCH", export_name: "userManagementUsersPATCH" },
51
+ { name: "user_management_users_post", path: "api/hazo_auth/user_management/users", method: "POST", export_name: "userManagementUsersPOST" },
52
+ { name: "user_management_permissions", path: "api/hazo_auth/user_management/permissions", method: "GET", export_name: "userManagementPermissionsGET" },
53
+ { name: "user_management_permissions_post", path: "api/hazo_auth/user_management/permissions", method: "POST", export_name: "userManagementPermissionsPOST" },
54
+ { name: "user_management_permissions_put", path: "api/hazo_auth/user_management/permissions", method: "PUT", export_name: "userManagementPermissionsPUT" },
55
+ { name: "user_management_permissions_delete", path: "api/hazo_auth/user_management/permissions", method: "DELETE", export_name: "userManagementPermissionsDELETE" },
56
+ { name: "user_management_roles", path: "api/hazo_auth/user_management/roles", method: "GET", export_name: "userManagementRolesGET" },
57
+ { name: "user_management_roles_post", path: "api/hazo_auth/user_management/roles", method: "POST", export_name: "userManagementRolesPOST" },
58
+ { name: "user_management_roles_put", path: "api/hazo_auth/user_management/roles", method: "PUT", export_name: "userManagementRolesPUT" },
59
+ { name: "user_management_users_roles", path: "api/hazo_auth/user_management/users/roles", method: "GET", export_name: "userManagementUsersRolesGET" },
60
+ { name: "user_management_users_roles_post", path: "api/hazo_auth/user_management/users/roles", method: "POST", export_name: "userManagementUsersRolesPOST" },
61
+ { name: "user_management_users_roles_put", path: "api/hazo_auth/user_management/users/roles", method: "PUT", export_name: "userManagementUsersRolesPUT" },
62
+ ];
63
+
64
+ const PAGES: PageDefinition[] = [
65
+ { name: "login", path: "hazo_auth/login", component_name: "LoginPage", import_path: "hazo_auth/pages/login" },
66
+ { name: "register", path: "hazo_auth/register", component_name: "RegisterPage", import_path: "hazo_auth/pages/register" },
67
+ { name: "forgot_password", path: "hazo_auth/forgot_password", component_name: "ForgotPasswordPage", import_path: "hazo_auth/pages/forgot_password" },
68
+ { name: "reset_password", path: "hazo_auth/reset_password", component_name: "ResetPasswordPage", import_path: "hazo_auth/pages/reset_password" },
69
+ { name: "verify_email", path: "hazo_auth/verify_email", component_name: "VerifyEmailPage", import_path: "hazo_auth/pages/verify_email" },
70
+ { name: "my_settings", path: "hazo_auth/my_settings", component_name: "MySettingsPage", import_path: "hazo_auth/pages/my_settings" },
71
+ ];
72
+ // Note: Using barrel export "hazo_auth/pages" which maps to dist/server_pages/index.js in package.json exports
73
+
74
+ // section: helpers
75
+ function get_project_root(): string {
76
+ return process.cwd();
77
+ }
78
+
79
+ function find_app_dir(project_root: string): string | null {
80
+ const possible_dirs = [
81
+ path.join(project_root, "app"),
82
+ path.join(project_root, "src", "app"),
83
+ ];
84
+
85
+ for (const dir of possible_dirs) {
86
+ if (fs.existsSync(dir)) {
87
+ return dir;
88
+ }
89
+ }
90
+
91
+ return null;
92
+ }
93
+
94
+ function ensure_dir(dir_path: string): void {
95
+ if (!fs.existsSync(dir_path)) {
96
+ fs.mkdirSync(dir_path, { recursive: true });
97
+ }
98
+ }
99
+
100
+ function file_exists(filepath: string): boolean {
101
+ return fs.existsSync(filepath);
102
+ }
103
+
104
+ function generate_route_content(route: RouteDefinition): string {
105
+ return `// Generated by hazo_auth - do not edit manually
106
+ // Route: /${route.path}
107
+ // Method: ${route.method}
108
+ export { ${route.export_name} as ${route.method} } from "hazo_auth/server/routes";
109
+ `;
110
+ }
111
+
112
+ function generate_route_content_multi(routes: RouteDefinition[]): string {
113
+ const path = routes[0].path;
114
+ const exports = routes.map(r => `export { ${r.export_name} as ${r.method} } from "hazo_auth/server/routes";`).join("\n");
115
+ const methods = routes.map(r => r.method).join(", ");
116
+
117
+ return `// Generated by hazo_auth - do not edit manually
118
+ // Route: /${path}
119
+ // Methods: ${methods}
120
+ ${exports}
121
+ `;
122
+ }
123
+
124
+ function generate_page_content(page: PageDefinition): string {
125
+ return `// Generated by hazo_auth - do not edit manually
126
+ // Page: /${page.path}
127
+ import { ${page.component_name} } from "hazo_auth/pages";
128
+
129
+ export default ${page.component_name};
130
+ `;
131
+ }
132
+
133
+ // section: api_route_generation
134
+ function generate_api_routes(app_dir: string, project_root: string): { created: number; skipped: number; errors: number } {
135
+ let created = 0;
136
+ let skipped = 0;
137
+ let errors = 0;
138
+
139
+ console.log("\x1b[1m📡 Generating API routes...\x1b[0m\n");
140
+
141
+ // Group routes by path to handle multiple methods per path
142
+ const routes_by_path = new Map<string, RouteDefinition[]>();
143
+ for (const route of ROUTES) {
144
+ const existing = routes_by_path.get(route.path) || [];
145
+ existing.push(route);
146
+ routes_by_path.set(route.path, existing);
147
+ }
148
+
149
+ for (const [route_path, routes_for_path] of routes_by_path) {
150
+ const route_dir = path.join(app_dir, route_path);
151
+ const route_file = path.join(route_dir, "route.ts");
152
+
153
+ if (file_exists(route_file)) {
154
+ console.log(`\x1b[33m[SKIP]\x1b[0m ${route_path}/route.ts (already exists)`);
155
+ skipped++;
156
+ continue;
157
+ }
158
+
159
+ try {
160
+ ensure_dir(route_dir);
161
+
162
+ // Generate content with all methods for this path
163
+ const content = generate_route_content_multi(routes_for_path);
164
+ fs.writeFileSync(route_file, content, "utf-8");
165
+
166
+ const methods = routes_for_path.map(r => r.method).join(", ");
167
+ console.log(`\x1b[32m[CREATE]\x1b[0m ${route_path}/route.ts (${methods})`);
168
+ created++;
169
+ } catch (err) {
170
+ console.log(`\x1b[31m[ERROR]\x1b[0m ${route_path}/route.ts - ${err instanceof Error ? err.message : "Unknown error"}`);
171
+ errors++;
172
+ }
173
+ }
174
+
175
+ return { created, skipped, errors };
176
+ }
177
+
178
+ // section: page_generation
179
+ function generate_page_routes(app_dir: string, project_root: string): { created: number; skipped: number; errors: number } {
180
+ let created = 0;
181
+ let skipped = 0;
182
+ let errors = 0;
183
+
184
+ console.log("\n\x1b[1m📄 Generating page routes...\x1b[0m\n");
185
+
186
+ for (const page of PAGES) {
187
+ const page_dir = path.join(app_dir, page.path);
188
+ const page_file = path.join(page_dir, "page.tsx");
189
+
190
+ if (file_exists(page_file)) {
191
+ console.log(`\x1b[33m[SKIP]\x1b[0m ${page.path}/page.tsx (already exists)`);
192
+ skipped++;
193
+ continue;
194
+ }
195
+
196
+ try {
197
+ ensure_dir(page_dir);
198
+
199
+ const content = generate_page_content(page);
200
+ fs.writeFileSync(page_file, content, "utf-8");
201
+
202
+ console.log(`\x1b[32m[CREATE]\x1b[0m ${page.path}/page.tsx`);
203
+ created++;
204
+ } catch (err) {
205
+ console.log(`\x1b[31m[ERROR]\x1b[0m ${page.path}/page.tsx - ${err instanceof Error ? err.message : "Unknown error"}`);
206
+ errors++;
207
+ }
208
+ }
209
+
210
+ return { created, skipped, errors };
211
+ }
212
+
213
+ // section: main
214
+ export function generate_routes(options: GenerateOptions = {}): void {
215
+ const { dir, pages = false, all = false } = options;
216
+ const project_root = get_project_root();
217
+ const include_pages = pages || all;
218
+
219
+ console.log("\n\x1b[1m🐸 hazo_auth Route Generator\x1b[0m");
220
+ console.log("=".repeat(50));
221
+ console.log(`Project root: ${project_root}`);
222
+ console.log(`Mode: ${include_pages ? "API routes + Pages" : "API routes only"}\n`);
223
+
224
+ const app_dir = dir
225
+ ? path.join(project_root, dir)
226
+ : find_app_dir(project_root);
227
+
228
+ if (!app_dir) {
229
+ console.error("\x1b[31mError: Could not find app directory.\x1b[0m");
230
+ console.log("Try specifying it with: npx hazo_auth generate-routes --dir=src/app");
231
+ process.exit(1);
232
+ }
233
+
234
+ if (!fs.existsSync(app_dir)) {
235
+ console.error(`\x1b[31mError: App directory not found: ${app_dir}\x1b[0m`);
236
+ process.exit(1);
237
+ }
238
+
239
+ console.log(`App directory: ${app_dir.replace(project_root, ".")}\n`);
240
+
241
+ // Generate API routes
242
+ const api_result = generate_api_routes(app_dir, project_root);
243
+
244
+ // Generate pages if requested
245
+ let page_result = { created: 0, skipped: 0, errors: 0 };
246
+ if (include_pages) {
247
+ page_result = generate_page_routes(app_dir, project_root);
248
+ }
249
+
250
+ // Summary
251
+ const total_created = api_result.created + page_result.created;
252
+ const total_skipped = api_result.skipped + page_result.skipped;
253
+ const total_errors = api_result.errors + page_result.errors;
254
+
255
+ console.log("\n" + "=".repeat(50));
256
+ console.log("\x1b[1mSummary:\x1b[0m");
257
+ console.log(` \x1b[32m✓ Created: ${total_created}\x1b[0m (${api_result.created} routes, ${page_result.created} pages)`);
258
+ console.log(` \x1b[33m⊘ Skipped: ${total_skipped}\x1b[0m`);
259
+ if (total_errors > 0) {
260
+ console.log(` \x1b[31m✗ Errors: ${total_errors}\x1b[0m`);
261
+ }
262
+ console.log();
263
+
264
+ if (total_created > 0) {
265
+ console.log("\x1b[32m🦊 Generation complete!\x1b[0m");
266
+ console.log("\nNext steps:");
267
+ console.log(" 1. Run `npm run dev` to start your development server");
268
+ console.log(" 2. Test API: `curl http://localhost:3000/api/hazo_auth/me`");
269
+ if (include_pages) {
270
+ console.log(" 3. Visit http://localhost:3000/hazo_auth/login to test pages");
271
+ }
272
+ console.log();
273
+ } else if (total_skipped === ROUTES.length + (include_pages ? PAGES.length : 0)) {
274
+ console.log("\x1b[33m🦊 All files already exist. No changes made.\x1b[0m\n");
275
+ }
276
+ }
@@ -0,0 +1,207 @@
1
+ #!/usr/bin/env node
2
+ // file_description: main CLI entry point for hazo_auth commands
3
+ // This file is the bin entry for the hazo_auth package
4
+
5
+ // section: imports
6
+ import { run_validation } from "./validate.js";
7
+ import { generate_routes, type GenerateOptions } from "./generate.js";
8
+ import { handle_init } from "./init.js";
9
+ import { handle_init_users, show_init_users_help } from "./init_users.js";
10
+
11
+ // section: constants
12
+ const VERSION = "1.6.0";
13
+
14
+ const HELP_TEXT = `
15
+ \x1b[1m🐸 hazo_auth CLI v${VERSION}\x1b[0m
16
+
17
+ Usage: hazo_auth <command> [options]
18
+
19
+ Commands:
20
+ init Initialize hazo_auth in your project (creates directories, copies config)
21
+ init-users Initialize permissions, roles, and super user from config
22
+ validate Check your hazo_auth setup and configuration
23
+ generate-routes Generate API route files and pages in your project
24
+
25
+ Options:
26
+ --help, -h Show this help message
27
+ --version, -v Show version number
28
+
29
+ Examples:
30
+ npx hazo_auth init
31
+ npx hazo_auth init-users
32
+ npx hazo_auth validate
33
+ npx hazo_auth generate-routes
34
+ npx hazo_auth generate-routes --pages
35
+ npx hazo_auth generate-routes --all --dir=src/app
36
+
37
+ Documentation:
38
+ https://github.com/your-repo/hazo_auth/blob/main/SETUP_CHECKLIST.md
39
+
40
+ 🦊
41
+ `;
42
+
43
+ // section: helpers
44
+ function parse_args(): { command?: string; args: string[]; help?: boolean; version?: boolean } {
45
+ const argv = process.argv.slice(2);
46
+ const result: { command?: string; args: string[]; help?: boolean; version?: boolean } = { args: [] };
47
+
48
+ for (const arg of argv) {
49
+ if (arg === "--help" || arg === "-h") {
50
+ result.help = true;
51
+ } else if (arg === "--version" || arg === "-v") {
52
+ result.version = true;
53
+ } else if (!arg.startsWith("-") && !result.command) {
54
+ result.command = arg;
55
+ } else {
56
+ result.args.push(arg);
57
+ }
58
+ }
59
+
60
+ return result;
61
+ }
62
+
63
+ function show_help(): void {
64
+ console.log(HELP_TEXT);
65
+ }
66
+
67
+ function show_version(): void {
68
+ console.log(`hazo_auth v${VERSION}`);
69
+ }
70
+
71
+ // section: command_handlers
72
+ async function handle_validate(): Promise<void> {
73
+ const summary = run_validation();
74
+ process.exit(summary.failed > 0 ? 1 : 0);
75
+ }
76
+
77
+ function handle_generate_routes(args: string[]): void {
78
+ const options: GenerateOptions = {};
79
+
80
+ for (const arg of args) {
81
+ if (arg.startsWith("--dir=")) {
82
+ options.dir = arg.replace("--dir=", "");
83
+ } else if (arg === "--pages") {
84
+ options.pages = true;
85
+ } else if (arg === "--all") {
86
+ options.all = true;
87
+ } else if (arg === "--help" || arg === "-h") {
88
+ console.log(`
89
+ hazo_auth generate-routes
90
+
91
+ Generate API route files and page files in your Next.js project.
92
+
93
+ Usage:
94
+ hazo_auth generate-routes [options]
95
+
96
+ Options:
97
+ --dir=<path> Specify the app directory (default: auto-detect)
98
+ --pages Generate page routes in addition to API routes
99
+ --all Generate everything (API routes + pages)
100
+ --help, -h Show this help message
101
+
102
+ Examples:
103
+ hazo_auth generate-routes # API routes only
104
+ hazo_auth generate-routes --pages # API routes + pages
105
+ hazo_auth generate-routes --all # Same as --pages
106
+ hazo_auth generate-routes --dir=src/app # Specify app directory
107
+ `);
108
+ return;
109
+ }
110
+ }
111
+
112
+ generate_routes(options);
113
+ }
114
+
115
+ // section: main
116
+ async function main(): Promise<void> {
117
+ const { command, args, help, version } = parse_args();
118
+
119
+ if (version) {
120
+ show_version();
121
+ return;
122
+ }
123
+
124
+ // Show main help only if no command specified
125
+ if (!command) {
126
+ show_help();
127
+ return;
128
+ }
129
+
130
+ // If help is requested but command exists, pass help to command handler
131
+ // Commands can show their own help
132
+ if (help) {
133
+ args.push("--help");
134
+ }
135
+
136
+ switch (command) {
137
+ case "init":
138
+ if (help) {
139
+ console.log(`
140
+ hazo_auth init
141
+
142
+ Initialize hazo_auth in your project.
143
+
144
+ Actions:
145
+ - Creates public/profile_pictures/library/ directory
146
+ - Creates public/profile_pictures/uploads/ directory
147
+ - Creates data/ directory (for SQLite)
148
+ - Copies hazo_auth_config.ini and hazo_notify_config.ini
149
+ - Copies profile picture library images
150
+ - Creates .env.local.example template
151
+ `);
152
+ return;
153
+ }
154
+ handle_init();
155
+ break;
156
+
157
+ case "init-users": {
158
+ if (help) {
159
+ show_init_users_help();
160
+ return;
161
+ }
162
+ // Parse --email option
163
+ let email: string | undefined;
164
+ for (const arg of args) {
165
+ if (arg.startsWith("--email=")) {
166
+ email = arg.replace("--email=", "");
167
+ }
168
+ }
169
+ await handle_init_users({ email });
170
+ break;
171
+ }
172
+
173
+ case "validate":
174
+ if (help) {
175
+ console.log(`
176
+ hazo_auth validate
177
+
178
+ Check your hazo_auth setup and configuration.
179
+
180
+ This command verifies:
181
+ - Config files exist and are readable
182
+ - Required config values are set
183
+ - Environment variables are configured
184
+ - Database connection works
185
+ - Required directories exist
186
+ `);
187
+ return;
188
+ }
189
+ await handle_validate();
190
+ break;
191
+
192
+ case "generate-routes":
193
+ handle_generate_routes(args);
194
+ break;
195
+
196
+ default:
197
+ console.error(`\x1b[31mUnknown command: ${command}\x1b[0m\n`);
198
+ console.log("Run 'hazo_auth --help' for usage information.");
199
+ process.exit(1);
200
+ }
201
+ }
202
+
203
+ // Run main
204
+ main().catch((error) => {
205
+ console.error("\x1b[31mError:\x1b[0m", error.message);
206
+ process.exit(1);
207
+ });