hazo_auth 1.6.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +65 -19
  2. package/SETUP_CHECKLIST.md +136 -65
  3. package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts +9 -0
  4. package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts.map +1 -0
  5. package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.js +82 -0
  6. package/dist/app/api/hazo_auth/library_photos/route.d.ts +9 -0
  7. package/dist/app/api/hazo_auth/library_photos/route.d.ts.map +1 -1
  8. package/dist/app/api/hazo_auth/library_photos/route.js +31 -6
  9. package/dist/cli/generate.d.ts +6 -1
  10. package/dist/cli/generate.d.ts.map +1 -1
  11. package/dist/cli/generate.js +101 -34
  12. package/dist/cli/index.js +64 -11
  13. package/dist/cli/init.d.ts +2 -0
  14. package/dist/cli/init.d.ts.map +1 -0
  15. package/dist/cli/init.js +201 -0
  16. package/dist/lib/services/profile_picture_service.d.ts +34 -2
  17. package/dist/lib/services/profile_picture_service.d.ts.map +1 -1
  18. package/dist/lib/services/profile_picture_service.js +157 -15
  19. package/dist/page_components/forgot_password.d.ts +19 -0
  20. package/dist/page_components/forgot_password.d.ts.map +1 -0
  21. package/dist/page_components/forgot_password.js +36 -0
  22. package/dist/page_components/index.d.ts +7 -0
  23. package/dist/page_components/index.d.ts.map +1 -0
  24. package/dist/page_components/index.js +9 -0
  25. package/dist/page_components/login.d.ts +26 -0
  26. package/dist/page_components/login.d.ts.map +1 -0
  27. package/dist/page_components/login.js +40 -0
  28. package/dist/page_components/my_settings.d.ts +64 -0
  29. package/dist/page_components/my_settings.d.ts.map +1 -0
  30. package/dist/page_components/my_settings.js +67 -0
  31. package/dist/page_components/register.d.ts +25 -0
  32. package/dist/page_components/register.d.ts.map +1 -0
  33. package/dist/page_components/register.js +43 -0
  34. package/dist/page_components/reset_password.d.ts +25 -0
  35. package/dist/page_components/reset_password.d.ts.map +1 -0
  36. package/dist/page_components/reset_password.js +43 -0
  37. package/dist/page_components/verify_email.d.ts +21 -0
  38. package/dist/page_components/verify_email.d.ts.map +1 -0
  39. package/dist/page_components/verify_email.js +36 -0
  40. package/dist/server/routes/index.d.ts +1 -0
  41. package/dist/server/routes/index.d.ts.map +1 -1
  42. package/dist/server/routes/index.js +1 -0
  43. package/dist/server/routes/library_photo.d.ts +2 -0
  44. package/dist/server/routes/library_photo.d.ts.map +1 -0
  45. package/dist/server/routes/library_photo.js +3 -0
  46. package/package.json +29 -1
@@ -1,5 +1,5 @@
1
- // file_description: route generation logic for hazo_auth
2
- // This module creates API route files in consuming projects
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
3
  import * as fs from "fs";
4
4
  import * as path from "path";
5
5
  // section: constants
@@ -17,11 +17,21 @@ const ROUTES = [
17
17
  { name: "upload_profile_picture", path: "api/hazo_auth/upload_profile_picture", method: "POST", export_name: "uploadProfilePicturePOST" },
18
18
  { name: "remove_profile_picture", path: "api/hazo_auth/remove_profile_picture", method: "DELETE", export_name: "removeProfilePictureDELETE" },
19
19
  { name: "library_photos", path: "api/hazo_auth/library_photos", method: "GET", export_name: "libraryPhotosGET" },
20
+ { name: "library_photo", path: "api/hazo_auth/library_photo/[category]/[filename]", method: "GET", export_name: "libraryPhotoGET" },
20
21
  { name: "get_auth", path: "api/hazo_auth/get_auth", method: "POST", export_name: "getAuthPOST" },
21
22
  { name: "validate_reset_token", path: "api/hazo_auth/validate_reset_token", method: "GET", export_name: "validateResetTokenGET" },
22
23
  { name: "profile_picture_filename", path: "api/hazo_auth/profile_picture/[filename]", method: "GET", export_name: "profilePictureFilenameGET" },
23
24
  { name: "invalidate_cache", path: "api/hazo_auth/invalidate_cache", method: "POST", export_name: "invalidateCachePOST" },
24
25
  ];
26
+ const PAGES = [
27
+ { name: "login", path: "hazo_auth/login", component_name: "LoginPage", import_path: "hazo_auth/pages/login" },
28
+ { name: "register", path: "hazo_auth/register", component_name: "RegisterPage", import_path: "hazo_auth/pages/register" },
29
+ { name: "forgot_password", path: "hazo_auth/forgot_password", component_name: "ForgotPasswordPage", import_path: "hazo_auth/pages/forgot_password" },
30
+ { name: "reset_password", path: "hazo_auth/reset_password", component_name: "ResetPasswordPage", import_path: "hazo_auth/pages/reset_password" },
31
+ { name: "verify_email", path: "hazo_auth/verify_email", component_name: "VerifyEmailPage", import_path: "hazo_auth/pages/verify_email" },
32
+ { name: "my_settings", path: "hazo_auth/my_settings", component_name: "MySettingsPage", import_path: "hazo_auth/pages/my_settings" },
33
+ ];
34
+ // Note: The import_path uses "hazo_auth/pages/*" which maps to dist/page_components/* in package.json exports
25
35
  // section: helpers
26
36
  function get_project_root() {
27
37
  return process.cwd();
@@ -43,6 +53,9 @@ function ensure_dir(dir_path) {
43
53
  fs.mkdirSync(dir_path, { recursive: true });
44
54
  }
45
55
  }
56
+ function file_exists(filepath) {
57
+ return fs.existsSync(filepath);
58
+ }
46
59
  function generate_route_content(route) {
47
60
  return `// Generated by hazo_auth - do not edit manually
48
61
  // Route: /${route.path}
@@ -50,32 +63,20 @@ function generate_route_content(route) {
50
63
  export { ${route.export_name} as ${route.method} } from "hazo_auth/server/routes";
51
64
  `;
52
65
  }
53
- function file_exists(filepath) {
54
- return fs.existsSync(filepath);
66
+ function generate_page_content(page) {
67
+ return `// Generated by hazo_auth - do not edit manually
68
+ // Page: /${page.path}
69
+ import { ${page.component_name} } from "${page.import_path}";
70
+
71
+ export default ${page.component_name};
72
+ `;
55
73
  }
56
- // section: main
57
- export function generate_routes(custom_app_dir) {
58
- const project_root = get_project_root();
59
- console.log("\n\x1b[1m🐸 hazo_auth Route Generator\x1b[0m");
60
- console.log("=".repeat(50));
61
- console.log(`Project root: ${project_root}\n`);
62
- let app_dir = custom_app_dir
63
- ? path.join(project_root, custom_app_dir)
64
- : find_app_dir(project_root);
65
- if (!app_dir) {
66
- console.error("\x1b[31mError: Could not find app directory.\x1b[0m");
67
- console.log("Try specifying it with: npx hazo_auth generate-routes --dir=src/app");
68
- process.exit(1);
69
- }
70
- if (!fs.existsSync(app_dir)) {
71
- console.error(`\x1b[31mError: App directory not found: ${app_dir}\x1b[0m`);
72
- process.exit(1);
73
- }
74
- console.log(`App directory: ${app_dir.replace(project_root, ".")}\n`);
74
+ // section: api_route_generation
75
+ function generate_api_routes(app_dir, project_root) {
75
76
  let created = 0;
76
77
  let skipped = 0;
77
78
  let errors = 0;
78
- console.log("\x1b[1mGenerating routes...\x1b[0m\n");
79
+ console.log("\x1b[1m📡 Generating API routes...\x1b[0m\n");
79
80
  for (const route of ROUTES) {
80
81
  const route_dir = path.join(app_dir, route.path);
81
82
  const route_file = path.join(route_dir, "route.ts");
@@ -96,22 +97,88 @@ export function generate_routes(custom_app_dir) {
96
97
  errors++;
97
98
  }
98
99
  }
100
+ return { created, skipped, errors };
101
+ }
102
+ // section: page_generation
103
+ function generate_page_routes(app_dir, project_root) {
104
+ let created = 0;
105
+ let skipped = 0;
106
+ let errors = 0;
107
+ console.log("\n\x1b[1m📄 Generating page routes...\x1b[0m\n");
108
+ for (const page of PAGES) {
109
+ const page_dir = path.join(app_dir, page.path);
110
+ const page_file = path.join(page_dir, "page.tsx");
111
+ if (file_exists(page_file)) {
112
+ console.log(`\x1b[33m[SKIP]\x1b[0m ${page.path}/page.tsx (already exists)`);
113
+ skipped++;
114
+ continue;
115
+ }
116
+ try {
117
+ ensure_dir(page_dir);
118
+ const content = generate_page_content(page);
119
+ fs.writeFileSync(page_file, content, "utf-8");
120
+ console.log(`\x1b[32m[CREATE]\x1b[0m ${page.path}/page.tsx`);
121
+ created++;
122
+ }
123
+ catch (err) {
124
+ console.log(`\x1b[31m[ERROR]\x1b[0m ${page.path}/page.tsx - ${err instanceof Error ? err.message : "Unknown error"}`);
125
+ errors++;
126
+ }
127
+ }
128
+ return { created, skipped, errors };
129
+ }
130
+ // section: main
131
+ export function generate_routes(options = {}) {
132
+ const { dir, pages = false, all = false } = options;
133
+ const project_root = get_project_root();
134
+ const include_pages = pages || all;
135
+ console.log("\n\x1b[1m🐸 hazo_auth Route Generator\x1b[0m");
136
+ console.log("=".repeat(50));
137
+ console.log(`Project root: ${project_root}`);
138
+ console.log(`Mode: ${include_pages ? "API routes + Pages" : "API routes only"}\n`);
139
+ const app_dir = dir
140
+ ? path.join(project_root, dir)
141
+ : find_app_dir(project_root);
142
+ if (!app_dir) {
143
+ console.error("\x1b[31mError: Could not find app directory.\x1b[0m");
144
+ console.log("Try specifying it with: npx hazo_auth generate-routes --dir=src/app");
145
+ process.exit(1);
146
+ }
147
+ if (!fs.existsSync(app_dir)) {
148
+ console.error(`\x1b[31mError: App directory not found: ${app_dir}\x1b[0m`);
149
+ process.exit(1);
150
+ }
151
+ console.log(`App directory: ${app_dir.replace(project_root, ".")}\n`);
152
+ // Generate API routes
153
+ const api_result = generate_api_routes(app_dir, project_root);
154
+ // Generate pages if requested
155
+ let page_result = { created: 0, skipped: 0, errors: 0 };
156
+ if (include_pages) {
157
+ page_result = generate_page_routes(app_dir, project_root);
158
+ }
159
+ // Summary
160
+ const total_created = api_result.created + page_result.created;
161
+ const total_skipped = api_result.skipped + page_result.skipped;
162
+ const total_errors = api_result.errors + page_result.errors;
99
163
  console.log("\n" + "=".repeat(50));
100
164
  console.log("\x1b[1mSummary:\x1b[0m");
101
- console.log(` \x1b[32m✓ Created: ${created}\x1b[0m`);
102
- console.log(` \x1b[33m⊘ Skipped: ${skipped}\x1b[0m`);
103
- if (errors > 0) {
104
- console.log(` \x1b[31m✗ Errors: ${errors}\x1b[0m`);
165
+ console.log(` \x1b[32m✓ Created: ${total_created}\x1b[0m (${api_result.created} routes, ${page_result.created} pages)`);
166
+ console.log(` \x1b[33m⊘ Skipped: ${total_skipped}\x1b[0m`);
167
+ if (total_errors > 0) {
168
+ console.log(` \x1b[31m✗ Errors: ${total_errors}\x1b[0m`);
105
169
  }
106
170
  console.log();
107
- if (created > 0) {
108
- console.log("\x1b[32m🦊 Routes generated successfully!\x1b[0m");
171
+ if (total_created > 0) {
172
+ console.log("\x1b[32m🦊 Generation complete!\x1b[0m");
109
173
  console.log("\nNext steps:");
110
174
  console.log(" 1. Run `npm run dev` to start your development server");
111
- console.log(" 2. Test the routes with `curl http://localhost:3000/api/hazo_auth/me`");
112
- console.log(" 3. Visit http://localhost:3000/api/hazo_auth/health to check setup status\n");
175
+ console.log(" 2. Test API: `curl http://localhost:3000/api/hazo_auth/me`");
176
+ if (include_pages) {
177
+ console.log(" 3. Visit http://localhost:3000/hazo_auth/login to test pages");
178
+ }
179
+ console.log();
113
180
  }
114
- else if (skipped === ROUTES.length) {
115
- console.log("\x1b[33m🦊 All routes already exist. No changes made.\x1b[0m\n");
181
+ else if (total_skipped === ROUTES.length + (include_pages ? PAGES.length : 0)) {
182
+ console.log("\x1b[33m🦊 All files already exist. No changes made.\x1b[0m\n");
116
183
  }
117
184
  }
package/dist/cli/index.js CHANGED
@@ -4,25 +4,29 @@
4
4
  // section: imports
5
5
  import { run_validation } from "./validate.js";
6
6
  import { generate_routes } from "./generate.js";
7
+ import { handle_init } from "./init.js";
7
8
  // section: constants
8
- const VERSION = "1.5.0";
9
+ const VERSION = "1.6.0";
9
10
  const HELP_TEXT = `
10
11
  \x1b[1m🐸 hazo_auth CLI v${VERSION}\x1b[0m
11
12
 
12
13
  Usage: hazo_auth <command> [options]
13
14
 
14
15
  Commands:
16
+ init Initialize hazo_auth in your project (creates directories, copies config)
15
17
  validate Check your hazo_auth setup and configuration
16
- generate-routes Generate API route files in your project
18
+ generate-routes Generate API route files and pages in your project
17
19
 
18
20
  Options:
19
21
  --help, -h Show this help message
20
22
  --version, -v Show version number
21
23
 
22
24
  Examples:
25
+ npx hazo_auth init
23
26
  npx hazo_auth validate
24
27
  npx hazo_auth generate-routes
25
- npx hazo_auth generate-routes --dir=src/app
28
+ npx hazo_auth generate-routes --pages
29
+ npx hazo_auth generate-routes --all --dir=src/app
26
30
 
27
31
  Documentation:
28
32
  https://github.com/your-repo/hazo_auth/blob/main/SETUP_CHECKLIST.md
@@ -61,33 +65,42 @@ async function handle_validate() {
61
65
  process.exit(summary.failed > 0 ? 1 : 0);
62
66
  }
63
67
  function handle_generate_routes(args) {
64
- // Parse --dir argument
65
- let dir;
68
+ const options = {};
66
69
  for (const arg of args) {
67
70
  if (arg.startsWith("--dir=")) {
68
- dir = arg.replace("--dir=", "");
71
+ options.dir = arg.replace("--dir=", "");
72
+ }
73
+ else if (arg === "--pages") {
74
+ options.pages = true;
75
+ }
76
+ else if (arg === "--all") {
77
+ options.all = true;
69
78
  }
70
79
  else if (arg === "--help" || arg === "-h") {
71
80
  console.log(`
72
81
  hazo_auth generate-routes
73
82
 
74
- Generate API route files in your Next.js project.
83
+ Generate API route files and page files in your Next.js project.
75
84
 
76
85
  Usage:
77
86
  hazo_auth generate-routes [options]
78
87
 
79
88
  Options:
80
89
  --dir=<path> Specify the app directory (default: auto-detect)
90
+ --pages Generate page routes in addition to API routes
91
+ --all Generate everything (API routes + pages)
81
92
  --help, -h Show this help message
82
93
 
83
94
  Examples:
84
- hazo_auth generate-routes
85
- hazo_auth generate-routes --dir=src/app
95
+ hazo_auth generate-routes # API routes only
96
+ hazo_auth generate-routes --pages # API routes + pages
97
+ hazo_auth generate-routes --all # Same as --pages
98
+ hazo_auth generate-routes --dir=src/app # Specify app directory
86
99
  `);
87
100
  return;
88
101
  }
89
102
  }
90
- generate_routes(dir);
103
+ generate_routes(options);
91
104
  }
92
105
  // section: main
93
106
  async function main() {
@@ -96,12 +109,52 @@ async function main() {
96
109
  show_version();
97
110
  return;
98
111
  }
99
- if (help || !command) {
112
+ // Show main help only if no command specified
113
+ if (!command) {
100
114
  show_help();
101
115
  return;
102
116
  }
117
+ // If help is requested but command exists, pass help to command handler
118
+ // Commands can show their own help
119
+ if (help) {
120
+ args.push("--help");
121
+ }
103
122
  switch (command) {
123
+ case "init":
124
+ if (help) {
125
+ console.log(`
126
+ hazo_auth init
127
+
128
+ Initialize hazo_auth in your project.
129
+
130
+ Actions:
131
+ - Creates public/profile_pictures/library/ directory
132
+ - Creates public/profile_pictures/uploads/ directory
133
+ - Creates data/ directory (for SQLite)
134
+ - Copies hazo_auth_config.ini and hazo_notify_config.ini
135
+ - Copies profile picture library images
136
+ - Creates .env.local.example template
137
+ `);
138
+ return;
139
+ }
140
+ handle_init();
141
+ break;
104
142
  case "validate":
143
+ if (help) {
144
+ console.log(`
145
+ hazo_auth validate
146
+
147
+ Check your hazo_auth setup and configuration.
148
+
149
+ This command verifies:
150
+ - Config files exist and are readable
151
+ - Required config values are set
152
+ - Environment variables are configured
153
+ - Database connection works
154
+ - Required directories exist
155
+ `);
156
+ return;
157
+ }
105
158
  await handle_validate();
106
159
  break;
107
160
  case "generate-routes":
@@ -0,0 +1,2 @@
1
+ export declare function handle_init(): void;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAqIA,wBAAgB,WAAW,IAAI,IAAI,CAkHlC"}
@@ -0,0 +1,201 @@
1
+ // file_description: init command for hazo_auth
2
+ // Creates directories and copies config files to consuming projects
3
+ import * as fs from "fs";
4
+ import * as path from "path";
5
+ // section: constants
6
+ const REQUIRED_DIRECTORIES = [
7
+ "public/profile_pictures/library",
8
+ "public/profile_pictures/uploads",
9
+ "data",
10
+ ];
11
+ const CONFIG_FILES = [
12
+ { source: "hazo_auth_config.example.ini", target: "hazo_auth_config.ini" },
13
+ { source: "hazo_notify_config.example.ini", target: "hazo_notify_config.ini" },
14
+ ];
15
+ // section: helpers
16
+ function get_project_root() {
17
+ return process.cwd();
18
+ }
19
+ function get_package_root() {
20
+ // When running from node_modules, we need to find the hazo_auth package root
21
+ // When running in development, use the current directory
22
+ // Check if we're in node_modules
23
+ const parts = __dirname.split(path.sep);
24
+ const node_modules_index = parts.lastIndexOf("node_modules");
25
+ if (node_modules_index !== -1) {
26
+ // We're in node_modules/hazo_auth/dist/cli
27
+ return parts.slice(0, node_modules_index + 2).join(path.sep);
28
+ }
29
+ // Development mode - go up from src/cli or dist/cli
30
+ return path.resolve(__dirname, "..", "..");
31
+ }
32
+ function ensure_dir(dir_path) {
33
+ if (!fs.existsSync(dir_path)) {
34
+ fs.mkdirSync(dir_path, { recursive: true });
35
+ return true;
36
+ }
37
+ return false;
38
+ }
39
+ function copy_file_if_not_exists(source, target) {
40
+ if (fs.existsSync(target)) {
41
+ return "skipped";
42
+ }
43
+ if (!fs.existsSync(source)) {
44
+ return "error";
45
+ }
46
+ try {
47
+ fs.copyFileSync(source, target);
48
+ return "created";
49
+ }
50
+ catch (_a) {
51
+ return "error";
52
+ }
53
+ }
54
+ function copy_directory(source, target) {
55
+ let copied = 0;
56
+ if (!fs.existsSync(source)) {
57
+ return 0;
58
+ }
59
+ ensure_dir(target);
60
+ const items = fs.readdirSync(source);
61
+ for (const item of items) {
62
+ const source_path = path.join(source, item);
63
+ const target_path = path.join(target, item);
64
+ const stat = fs.statSync(source_path);
65
+ if (stat.isDirectory()) {
66
+ copied += copy_directory(source_path, target_path);
67
+ }
68
+ else if (!fs.existsSync(target_path)) {
69
+ fs.copyFileSync(source_path, target_path);
70
+ copied++;
71
+ }
72
+ }
73
+ return copied;
74
+ }
75
+ function create_gitkeep(dir_path) {
76
+ const gitkeep_path = path.join(dir_path, ".gitkeep");
77
+ if (!fs.existsSync(gitkeep_path)) {
78
+ const files = fs.readdirSync(dir_path);
79
+ if (files.length === 0) {
80
+ fs.writeFileSync(gitkeep_path, "# This file keeps the empty directory in git\n");
81
+ }
82
+ }
83
+ }
84
+ function create_env_template(project_root) {
85
+ const env_example_path = path.join(project_root, ".env.local.example");
86
+ if (fs.existsSync(env_example_path)) {
87
+ return false;
88
+ }
89
+ const content = `# hazo_auth environment variables
90
+ # Copy this file to .env.local and fill in the values
91
+
92
+ # Required for email functionality (email verification, password reset)
93
+ ZEPTOMAIL_API_KEY=your_zeptomail_api_key_here
94
+
95
+ # Optional: Database path (defaults to data/hazo_auth.sqlite)
96
+ # HAZO_AUTH_DB_PATH=./data/hazo_auth.sqlite
97
+ `;
98
+ fs.writeFileSync(env_example_path, content);
99
+ return true;
100
+ }
101
+ // section: main
102
+ export function handle_init() {
103
+ const project_root = get_project_root();
104
+ const package_root = get_package_root();
105
+ console.log("\n\x1b[1m🐸 hazo_auth Initialization\x1b[0m");
106
+ console.log("=".repeat(50));
107
+ console.log(`Project root: ${project_root}`);
108
+ console.log(`Package root: ${package_root}\n`);
109
+ const result = {
110
+ directories_created: [],
111
+ files_copied: [],
112
+ skipped: [],
113
+ errors: [],
114
+ };
115
+ // Step 1: Create directories
116
+ console.log("\x1b[1m📁 Creating directories...\x1b[0m\n");
117
+ for (const dir of REQUIRED_DIRECTORIES) {
118
+ const full_path = path.join(project_root, dir);
119
+ if (ensure_dir(full_path)) {
120
+ console.log(`\x1b[32m[CREATE]\x1b[0m ${dir}/`);
121
+ result.directories_created.push(dir);
122
+ }
123
+ else {
124
+ console.log(`\x1b[33m[EXISTS]\x1b[0m ${dir}/`);
125
+ result.skipped.push(dir);
126
+ }
127
+ }
128
+ // Step 2: Copy config files
129
+ console.log("\n\x1b[1m📄 Copying config files...\x1b[0m\n");
130
+ for (const config of CONFIG_FILES) {
131
+ const source_path = path.join(package_root, config.source);
132
+ const target_path = path.join(project_root, config.target);
133
+ const status = copy_file_if_not_exists(source_path, target_path);
134
+ if (status === "created") {
135
+ console.log(`\x1b[32m[CREATE]\x1b[0m ${config.target}`);
136
+ result.files_copied.push(config.target);
137
+ }
138
+ else if (status === "skipped") {
139
+ console.log(`\x1b[33m[EXISTS]\x1b[0m ${config.target}`);
140
+ result.skipped.push(config.target);
141
+ }
142
+ else {
143
+ console.log(`\x1b[31m[ERROR]\x1b[0m ${config.target} - source not found: ${source_path}`);
144
+ result.errors.push(config.target);
145
+ }
146
+ }
147
+ // Step 3: Copy profile picture library
148
+ console.log("\n\x1b[1m🖼️ Copying profile picture library...\x1b[0m\n");
149
+ const library_source = path.join(package_root, "public", "profile_pictures", "library");
150
+ const library_target = path.join(project_root, "public", "profile_pictures", "library");
151
+ if (fs.existsSync(library_source)) {
152
+ const copied_count = copy_directory(library_source, library_target);
153
+ if (copied_count > 0) {
154
+ console.log(`\x1b[32m[COPY]\x1b[0m ${copied_count} library images`);
155
+ result.files_copied.push(`${copied_count} library images`);
156
+ }
157
+ else {
158
+ console.log(`\x1b[33m[EXISTS]\x1b[0m Library images already present`);
159
+ result.skipped.push("library images");
160
+ }
161
+ }
162
+ else {
163
+ console.log(`\x1b[33m[SKIP]\x1b[0m Library not found at: ${library_source}`);
164
+ result.skipped.push("library images (source not found)");
165
+ }
166
+ // Step 4: Create .gitkeep files for empty directories
167
+ console.log("\n\x1b[1m📌 Creating .gitkeep files...\x1b[0m\n");
168
+ const empty_dirs = ["public/profile_pictures/uploads", "data"];
169
+ for (const dir of empty_dirs) {
170
+ const full_path = path.join(project_root, dir);
171
+ if (fs.existsSync(full_path)) {
172
+ create_gitkeep(full_path);
173
+ console.log(`\x1b[32m[CREATE]\x1b[0m ${dir}/.gitkeep`);
174
+ }
175
+ }
176
+ // Step 5: Create .env.local.example template
177
+ console.log("\n\x1b[1m🔑 Creating environment template...\x1b[0m\n");
178
+ if (create_env_template(project_root)) {
179
+ console.log(`\x1b[32m[CREATE]\x1b[0m .env.local.example`);
180
+ result.files_copied.push(".env.local.example");
181
+ }
182
+ else {
183
+ console.log(`\x1b[33m[EXISTS]\x1b[0m .env.local.example`);
184
+ result.skipped.push(".env.local.example");
185
+ }
186
+ // Summary
187
+ console.log("\n" + "=".repeat(50));
188
+ console.log("\x1b[1mSummary:\x1b[0m");
189
+ console.log(` \x1b[32m✓ Created:\x1b[0m ${result.directories_created.length} directories, ${result.files_copied.length} files`);
190
+ console.log(` \x1b[33m⊘ Skipped:\x1b[0m ${result.skipped.length} items`);
191
+ if (result.errors.length > 0) {
192
+ console.log(` \x1b[31m✗ Errors:\x1b[0m ${result.errors.length}`);
193
+ }
194
+ console.log("\n\x1b[32m🦊 Initialization complete!\x1b[0m");
195
+ console.log("\nNext steps:");
196
+ console.log(" 1. Edit \x1b[36mhazo_auth_config.ini\x1b[0m with your settings");
197
+ console.log(" 2. Copy \x1b[36m.env.local.example\x1b[0m to \x1b[36m.env.local\x1b[0m and add your API keys");
198
+ console.log(" 3. Run \x1b[36mnpx hazo_auth generate-routes --pages\x1b[0m to generate routes and pages");
199
+ console.log(" 4. Run \x1b[36mnpx hazo_auth validate\x1b[0m to check your setup");
200
+ console.log();
201
+ }
@@ -5,6 +5,14 @@ export type DefaultProfilePictureResult = {
5
5
  profile_picture_url: string;
6
6
  profile_source: ProfilePictureSource;
7
7
  };
8
+ export type LibraryPhotosResult = {
9
+ photos: string[];
10
+ total: number;
11
+ page: number;
12
+ page_size: number;
13
+ has_more: boolean;
14
+ source: "project" | "node_modules";
15
+ };
8
16
  /**
9
17
  * Generates Gravatar URL from email address
10
18
  * @param email - User's email address
@@ -18,11 +26,35 @@ export declare function get_gravatar_url(email: string, size?: number): string;
18
26
  */
19
27
  export declare function get_library_categories(): string[];
20
28
  /**
21
- * Gets photos in a specific library category
29
+ * Gets photos in a specific library category with pagination support
30
+ * @param category - Category name
31
+ * @param page - Page number (1-indexed, default 1)
32
+ * @param page_size - Number of photos per page (default 20, max 100)
33
+ * @returns Object with photos array and pagination info
34
+ */
35
+ export declare function get_library_photos_paginated(category: string, page?: number, page_size?: number): LibraryPhotosResult;
36
+ /**
37
+ * Gets photos in a specific library category (legacy non-paginated version)
22
38
  * @param category - Category name
23
- * @returns Array of photo URLs (relative to public directory)
39
+ * @returns Array of photo URLs (relative to public directory or API route)
24
40
  */
25
41
  export declare function get_library_photos(category: string): string[];
42
+ /**
43
+ * Gets the physical file path for a library photo (used for serving from node_modules)
44
+ * @param category - Category name
45
+ * @param filename - Photo filename
46
+ * @returns Full file path or null if not found
47
+ */
48
+ export declare function get_library_photo_path(category: string, filename: string): string | null;
49
+ /**
50
+ * Gets the source of library photos (for diagnostic purposes)
51
+ * @returns Source type or null if no library found
52
+ */
53
+ export declare function get_library_source(): "project" | "node_modules" | null;
54
+ /**
55
+ * Clears the library path cache (useful for testing or after copying files)
56
+ */
57
+ export declare function clear_library_cache(): void;
26
58
  /**
27
59
  * Gets default profile picture based on configuration priority
28
60
  * @param user_email - User's email address
@@ -1 +1 @@
1
- {"version":3,"file":"profile_picture_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/profile_picture_service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASvD,OAAO,EAAuB,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGnG,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAE1D,MAAM,MAAM,2BAA2B,GAAG;IACxC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,oBAAoB,CAAC;CACtC,CAAC;AAGF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAOrE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAyBjD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAiC7D;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,2BAA2B,GAAG,IAAI,CA2DpC;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,EACf,mBAAmB,EAAE,MAAM,EAC3B,cAAc,EAAE,oBAAoB,GACnC,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAsB/C"}
1
+ {"version":3,"file":"profile_picture_service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/profile_picture_service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASvD,OAAO,EAAuB,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGnG,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAE1D,MAAM,MAAM,2BAA2B,GAAG;IACxC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,oBAAoB,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,cAAc,CAAC;CACpC,CAAC;AA2DF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAOrE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAyBjD;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,MAAU,EAChB,SAAS,GAAE,MAAW,GACrB,mBAAmB,CA6FrB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAI7D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcxF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,GAAG,cAAc,GAAG,IAAI,CAGtE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAG1C;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,2BAA2B,GAAG,IAAI,CA2DpC;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,MAAM,EACf,mBAAmB,EAAE,MAAM,EAC3B,cAAc,EAAE,oBAAoB,GACnC,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAsB/C"}