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.
- package/README.md +65 -19
- package/SETUP_CHECKLIST.md +136 -65
- package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts +9 -0
- package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.d.ts.map +1 -0
- package/dist/app/api/hazo_auth/library_photo/[category]/[filename]/route.js +82 -0
- package/dist/app/api/hazo_auth/library_photos/route.d.ts +9 -0
- package/dist/app/api/hazo_auth/library_photos/route.d.ts.map +1 -1
- package/dist/app/api/hazo_auth/library_photos/route.js +31 -6
- package/dist/cli/generate.d.ts +6 -1
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +101 -34
- package/dist/cli/index.js +64 -11
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +201 -0
- package/dist/lib/services/profile_picture_service.d.ts +34 -2
- package/dist/lib/services/profile_picture_service.d.ts.map +1 -1
- package/dist/lib/services/profile_picture_service.js +157 -15
- package/dist/page_components/forgot_password.d.ts +19 -0
- package/dist/page_components/forgot_password.d.ts.map +1 -0
- package/dist/page_components/forgot_password.js +36 -0
- package/dist/page_components/index.d.ts +7 -0
- package/dist/page_components/index.d.ts.map +1 -0
- package/dist/page_components/index.js +9 -0
- package/dist/page_components/login.d.ts +26 -0
- package/dist/page_components/login.d.ts.map +1 -0
- package/dist/page_components/login.js +40 -0
- package/dist/page_components/my_settings.d.ts +64 -0
- package/dist/page_components/my_settings.d.ts.map +1 -0
- package/dist/page_components/my_settings.js +67 -0
- package/dist/page_components/register.d.ts +25 -0
- package/dist/page_components/register.d.ts.map +1 -0
- package/dist/page_components/register.js +43 -0
- package/dist/page_components/reset_password.d.ts +25 -0
- package/dist/page_components/reset_password.d.ts.map +1 -0
- package/dist/page_components/reset_password.js +43 -0
- package/dist/page_components/verify_email.d.ts +21 -0
- package/dist/page_components/verify_email.d.ts.map +1 -0
- package/dist/page_components/verify_email.js +36 -0
- package/dist/server/routes/index.d.ts +1 -0
- package/dist/server/routes/index.d.ts.map +1 -1
- package/dist/server/routes/index.js +1 -0
- package/dist/server/routes/library_photo.d.ts +2 -0
- package/dist/server/routes/library_photo.d.ts.map +1 -0
- package/dist/server/routes/library_photo.js +3 -0
- package/package.json +29 -1
package/README.md
CHANGED
|
@@ -26,32 +26,61 @@ npm install hazo_auth
|
|
|
26
26
|
|
|
27
27
|
## Quick Start
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
The fastest way to get started is using the CLI commands:
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
+
# 1. Install the package
|
|
32
33
|
npm install hazo_auth
|
|
34
|
+
|
|
35
|
+
# 2. Initialize your project (creates directories, copies config files)
|
|
36
|
+
npx hazo_auth init
|
|
37
|
+
|
|
38
|
+
# 3. Generate API routes and pages
|
|
39
|
+
npx hazo_auth generate-routes --pages
|
|
40
|
+
|
|
41
|
+
# 4. Set up environment variables
|
|
42
|
+
cp .env.local.example .env.local
|
|
43
|
+
# Edit .env.local and add your ZEPTOMAIL_API_KEY
|
|
44
|
+
|
|
45
|
+
# 5. Start your dev server
|
|
46
|
+
npm run dev
|
|
33
47
|
```
|
|
34
48
|
|
|
35
|
-
|
|
49
|
+
That's it! Visit `http://localhost:3000/hazo_auth/login` to see the login page.
|
|
50
|
+
|
|
51
|
+
### CLI Commands
|
|
36
52
|
|
|
37
53
|
```bash
|
|
38
|
-
|
|
39
|
-
|
|
54
|
+
npx hazo_auth init # Initialize project (creates dirs, copies config)
|
|
55
|
+
npx hazo_auth generate-routes # Generate API routes only
|
|
56
|
+
npx hazo_auth generate-routes --pages # Generate API routes + pages
|
|
57
|
+
npx hazo_auth validate # Check your setup and configuration
|
|
58
|
+
npx hazo_auth --help # Show all commands
|
|
40
59
|
```
|
|
41
60
|
|
|
42
|
-
###
|
|
61
|
+
### Using Zero-Config Page Components
|
|
43
62
|
|
|
44
|
-
|
|
63
|
+
The generated pages import from `hazo_auth/pages/*` which provides zero-config components:
|
|
45
64
|
|
|
46
|
-
```
|
|
47
|
-
|
|
65
|
+
```typescript
|
|
66
|
+
// Generated app/hazo_auth/login/page.tsx
|
|
67
|
+
import { LoginPage } from "hazo_auth/pages/login";
|
|
68
|
+
export default LoginPage;
|
|
48
69
|
```
|
|
49
70
|
|
|
50
|
-
|
|
71
|
+
Available zero-config pages:
|
|
72
|
+
- `LoginPage` - Login form with sensible defaults
|
|
73
|
+
- `RegisterPage` - Registration with password requirements
|
|
74
|
+
- `ForgotPasswordPage` - Password reset request
|
|
75
|
+
- `ResetPasswordPage` - Set new password
|
|
76
|
+
- `VerifyEmailPage` - Email verification
|
|
77
|
+
- `MySettingsPage` - User profile and settings
|
|
51
78
|
|
|
52
|
-
|
|
79
|
+
All pages work out-of-the-box with no props required!
|
|
53
80
|
|
|
54
|
-
###
|
|
81
|
+
### Manual Setup (Advanced)
|
|
82
|
+
|
|
83
|
+
If you prefer manual control, you can use the layout components directly:
|
|
55
84
|
|
|
56
85
|
```typescript
|
|
57
86
|
// Import layout components
|
|
@@ -415,7 +444,25 @@ The package exports components through these paths:
|
|
|
415
444
|
// Main entry point - exports all public APIs
|
|
416
445
|
import { ... } from "hazo_auth";
|
|
417
446
|
|
|
418
|
-
//
|
|
447
|
+
// Zero-config page components (recommended for quick setup)
|
|
448
|
+
import { LoginPage } from "hazo_auth/pages/login";
|
|
449
|
+
import { RegisterPage } from "hazo_auth/pages/register";
|
|
450
|
+
import { ForgotPasswordPage } from "hazo_auth/pages/forgot_password";
|
|
451
|
+
import { ResetPasswordPage } from "hazo_auth/pages/reset_password";
|
|
452
|
+
import { VerifyEmailPage } from "hazo_auth/pages/verify_email";
|
|
453
|
+
import { MySettingsPage } from "hazo_auth/pages/my_settings";
|
|
454
|
+
|
|
455
|
+
// Or import all pages at once
|
|
456
|
+
import {
|
|
457
|
+
LoginPage,
|
|
458
|
+
RegisterPage,
|
|
459
|
+
ForgotPasswordPage,
|
|
460
|
+
ResetPasswordPage,
|
|
461
|
+
VerifyEmailPage,
|
|
462
|
+
MySettingsPage
|
|
463
|
+
} from "hazo_auth/pages";
|
|
464
|
+
|
|
465
|
+
// Layout components - for custom implementations
|
|
419
466
|
import { LoginLayout } from "hazo_auth/components/layouts/login";
|
|
420
467
|
import { RegisterLayout } from "hazo_auth/components/layouts/register";
|
|
421
468
|
import { ForgotPasswordLayout } from "hazo_auth/components/layouts/forgot_password";
|
|
@@ -903,22 +950,21 @@ This compiles the `src/` directory to `dist/` with:
|
|
|
903
950
|
|
|
904
951
|
### Package Exports
|
|
905
952
|
|
|
906
|
-
The `package.json` exports field defines the public API
|
|
953
|
+
The `package.json` exports field defines the public API:
|
|
907
954
|
|
|
908
955
|
```json
|
|
909
956
|
{
|
|
910
957
|
"exports": {
|
|
911
958
|
".": "./dist/index.js",
|
|
959
|
+
"./pages": "./dist/page_components/index.js",
|
|
960
|
+
"./pages/login": "./dist/page_components/login.js",
|
|
961
|
+
"./pages/register": "./dist/page_components/register.js",
|
|
912
962
|
"./components/layouts/login": "./dist/components/layouts/login/index.js",
|
|
913
963
|
"./components/layouts/register": "./dist/components/layouts/register/index.js",
|
|
914
|
-
"./components/layouts/forgot_password": "./dist/components/layouts/forgot_password/index.js",
|
|
915
|
-
"./components/layouts/reset_password": "./dist/components/layouts/reset_password/index.js",
|
|
916
|
-
"./components/layouts/email_verification": "./dist/components/layouts/email_verification/index.js",
|
|
917
|
-
"./components/layouts/my_settings": "./dist/components/layouts/my_settings/index.js",
|
|
918
|
-
"./components/layouts/user_management": "./dist/components/layouts/user_management/index.js",
|
|
919
964
|
"./components/layouts/shared": "./dist/components/layouts/shared/index.js",
|
|
920
965
|
"./lib/auth/hazo_get_auth.server": "./dist/lib/auth/hazo_get_auth.server.js",
|
|
921
|
-
"./server": "./dist/server/index.js"
|
|
966
|
+
"./server": "./dist/server/index.js",
|
|
967
|
+
"./server/routes": "./dist/server/routes/index.js"
|
|
922
968
|
}
|
|
923
969
|
}
|
|
924
970
|
```
|
package/SETUP_CHECKLIST.md
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
This checklist provides step-by-step instructions for setting up the `hazo_auth` package in your Next.js project. AI assistants can follow this guide to ensure complete and correct setup.
|
|
4
4
|
|
|
5
|
+
## Quick Start (Recommended)
|
|
6
|
+
|
|
7
|
+
The fastest way to set up hazo_auth:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 1. Install the package
|
|
11
|
+
npm install hazo_auth
|
|
12
|
+
|
|
13
|
+
# 2. Initialize project (creates directories, copies config files)
|
|
14
|
+
npx hazo_auth init
|
|
15
|
+
|
|
16
|
+
# 3. Generate API routes and pages
|
|
17
|
+
npx hazo_auth generate-routes --pages
|
|
18
|
+
|
|
19
|
+
# 4. Set up environment variables
|
|
20
|
+
cp .env.local.example .env.local
|
|
21
|
+
# Edit .env.local and add ZEPTOMAIL_API_KEY
|
|
22
|
+
|
|
23
|
+
# 5. Start dev server and test
|
|
24
|
+
npm run dev
|
|
25
|
+
# Visit http://localhost:3000/hazo_auth/login
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
If this works, skip to [Phase 6: Verification Tests](#phase-6-verification-tests).
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
5
32
|
## Pre-flight Checks
|
|
6
33
|
|
|
7
34
|
Before starting, verify your project meets these requirements:
|
|
@@ -33,7 +60,25 @@ ls node_modules/hazo_auth/package.json
|
|
|
33
60
|
# Expected: file exists
|
|
34
61
|
```
|
|
35
62
|
|
|
36
|
-
### Step 1.2:
|
|
63
|
+
### Step 1.2: Initialize project (Recommended)
|
|
64
|
+
|
|
65
|
+
Use the CLI to automatically set up directories and copy config files:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx hazo_auth init
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This command:
|
|
72
|
+
- Creates `public/profile_pictures/library/` directory
|
|
73
|
+
- Creates `public/profile_pictures/uploads/` directory
|
|
74
|
+
- Creates `data/` directory (for SQLite database)
|
|
75
|
+
- Copies `hazo_auth_config.ini` and `hazo_notify_config.ini`
|
|
76
|
+
- Copies profile picture library images
|
|
77
|
+
- Creates `.env.local.example` template
|
|
78
|
+
|
|
79
|
+
### Step 1.2b: Manual config setup (Alternative)
|
|
80
|
+
|
|
81
|
+
If you prefer manual setup:
|
|
37
82
|
|
|
38
83
|
```bash
|
|
39
84
|
cp node_modules/hazo_auth/hazo_auth_config.example.ini ./hazo_auth_config.ini
|
|
@@ -424,86 +469,92 @@ export { GET } from "hazo_auth/server/routes/profile_picture_filename";
|
|
|
424
469
|
|
|
425
470
|
Create page files for each auth flow.
|
|
426
471
|
|
|
427
|
-
### Step 5.1:
|
|
472
|
+
### Step 5.1: Generate pages automatically (Recommended)
|
|
428
473
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
import { LoginLayout } from "hazo_auth/components/layouts/login";
|
|
432
|
-
|
|
433
|
-
export default function LoginPage() {
|
|
434
|
-
return <LoginLayout />;
|
|
435
|
-
}
|
|
474
|
+
```bash
|
|
475
|
+
npx hazo_auth generate-routes --pages
|
|
436
476
|
```
|
|
437
477
|
|
|
438
|
-
|
|
439
|
-
```typescript
|
|
440
|
-
import { RegisterLayout } from "hazo_auth/components/layouts/register";
|
|
478
|
+
This generates both API routes and page routes. The generated pages use zero-config components that work out of the box.
|
|
441
479
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
480
|
+
**Generated pages:**
|
|
481
|
+
```
|
|
482
|
+
app/hazo_auth/
|
|
483
|
+
├── login/page.tsx
|
|
484
|
+
├── register/page.tsx
|
|
485
|
+
├── forgot_password/page.tsx
|
|
486
|
+
├── reset_password/page.tsx
|
|
487
|
+
├── verify_email/page.tsx
|
|
488
|
+
└── my_settings/page.tsx
|
|
445
489
|
```
|
|
446
490
|
|
|
447
|
-
|
|
448
|
-
```typescript
|
|
449
|
-
import { ForgotPasswordLayout } from "hazo_auth/components/layouts/forgot_password";
|
|
491
|
+
### Step 5.2: Manual page creation (Alternative)
|
|
450
492
|
|
|
451
|
-
|
|
452
|
-
return <ForgotPasswordLayout />;
|
|
453
|
-
}
|
|
454
|
-
```
|
|
493
|
+
If you prefer manual setup or need custom paths, create these files:
|
|
455
494
|
|
|
456
|
-
**
|
|
495
|
+
**Login page** - `app/hazo_auth/login/page.tsx`:
|
|
457
496
|
```typescript
|
|
458
|
-
import {
|
|
497
|
+
import { LoginPage } from "hazo_auth/pages/login";
|
|
498
|
+
export default LoginPage;
|
|
499
|
+
```
|
|
459
500
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
}
|
|
501
|
+
**Register page** - `app/hazo_auth/register/page.tsx`:
|
|
502
|
+
```typescript
|
|
503
|
+
import { RegisterPage } from "hazo_auth/pages/register";
|
|
504
|
+
export default RegisterPage;
|
|
463
505
|
```
|
|
464
506
|
|
|
465
|
-
**
|
|
507
|
+
**Forgot password page** - `app/hazo_auth/forgot_password/page.tsx`:
|
|
466
508
|
```typescript
|
|
467
|
-
import {
|
|
509
|
+
import { ForgotPasswordPage } from "hazo_auth/pages/forgot_password";
|
|
510
|
+
export default ForgotPasswordPage;
|
|
511
|
+
```
|
|
468
512
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
}
|
|
513
|
+
**Reset password page** - `app/hazo_auth/reset_password/page.tsx`:
|
|
514
|
+
```typescript
|
|
515
|
+
import { ResetPasswordPage } from "hazo_auth/pages/reset_password";
|
|
516
|
+
export default ResetPasswordPage;
|
|
472
517
|
```
|
|
473
518
|
|
|
474
|
-
**
|
|
519
|
+
**Email verification page** - `app/hazo_auth/verify_email/page.tsx`:
|
|
475
520
|
```typescript
|
|
476
|
-
import {
|
|
521
|
+
import { VerifyEmailPage } from "hazo_auth/pages/verify_email";
|
|
522
|
+
export default VerifyEmailPage;
|
|
523
|
+
```
|
|
477
524
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
}
|
|
525
|
+
**My settings page** - `app/hazo_auth/my_settings/page.tsx`:
|
|
526
|
+
```typescript
|
|
527
|
+
import { MySettingsPage } from "hazo_auth/pages/my_settings";
|
|
528
|
+
export default MySettingsPage;
|
|
481
529
|
```
|
|
482
530
|
|
|
483
|
-
### Step 5.
|
|
531
|
+
### Step 5.3: Custom page routes (Advanced)
|
|
532
|
+
|
|
533
|
+
If you need custom paths or want to wrap pages with your own layout:
|
|
484
534
|
|
|
485
|
-
`app/(auth)/layout.tsx`:
|
|
486
535
|
```typescript
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
}) {
|
|
536
|
+
// app/(auth)/login/page.tsx
|
|
537
|
+
import { LoginPage } from "hazo_auth/pages/login";
|
|
538
|
+
|
|
539
|
+
export default function CustomLoginPage() {
|
|
492
540
|
return (
|
|
493
|
-
<div className="min-h-screen flex items-center justify-center
|
|
494
|
-
|
|
541
|
+
<div className="min-h-screen flex items-center justify-center">
|
|
542
|
+
<LoginPage
|
|
543
|
+
redirectRoute="/dashboard"
|
|
544
|
+
successMessage="Welcome back!"
|
|
545
|
+
/>
|
|
495
546
|
</div>
|
|
496
547
|
);
|
|
497
548
|
}
|
|
498
549
|
```
|
|
499
550
|
|
|
500
551
|
**Checklist:**
|
|
501
|
-
- [ ] Login page created (`/login`)
|
|
502
|
-
- [ ] Register page created (`/register`)
|
|
503
|
-
- [ ] Forgot password page created (`/
|
|
504
|
-
- [ ] Reset password page created (`/
|
|
505
|
-
- [ ] Email verification page created (`/
|
|
506
|
-
- [ ] My settings page created (`/
|
|
552
|
+
- [ ] Login page created (`/hazo_auth/login`)
|
|
553
|
+
- [ ] Register page created (`/hazo_auth/register`)
|
|
554
|
+
- [ ] Forgot password page created (`/hazo_auth/forgot_password`)
|
|
555
|
+
- [ ] Reset password page created (`/hazo_auth/reset_password`)
|
|
556
|
+
- [ ] Email verification page created (`/hazo_auth/verify_email`)
|
|
557
|
+
- [ ] My settings page created (`/hazo_auth/my_settings`)
|
|
507
558
|
|
|
508
559
|
---
|
|
509
560
|
|
|
@@ -578,15 +629,22 @@ curl -s http://localhost:3000/api/hazo_auth/library_photos | jq
|
|
|
578
629
|
**Expected response:**
|
|
579
630
|
```json
|
|
580
631
|
{
|
|
581
|
-
"
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
]
|
|
632
|
+
"success": true,
|
|
633
|
+
"categories": ["Cars", "Young Cartoons"],
|
|
634
|
+
"source": "project"
|
|
585
635
|
}
|
|
586
636
|
```
|
|
587
637
|
|
|
588
|
-
|
|
589
|
-
-
|
|
638
|
+
The `source` field indicates where photos are served from:
|
|
639
|
+
- `"project"` - Photos are in your project's `public/profile_pictures/library/`
|
|
640
|
+
- `"node_modules"` - Photos are served from `node_modules/hazo_auth/public/` via API route
|
|
641
|
+
|
|
642
|
+
**Test paginated photos:**
|
|
643
|
+
```bash
|
|
644
|
+
curl -s "http://localhost:3000/api/hazo_auth/library_photos?category=Cars&page=1&page_size=5" | jq
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
**Note:** Library photos work automatically whether they're copied to your project or still in node_modules. The API will serve them from node_modules as a fallback.
|
|
590
648
|
|
|
591
649
|
### Test 6: Visit Pages in Browser
|
|
592
650
|
|
|
@@ -596,10 +654,10 @@ npm run dev
|
|
|
596
654
|
```
|
|
597
655
|
|
|
598
656
|
Visit each page and verify it loads:
|
|
599
|
-
- [ ] `http://localhost:3000/login` - Login form displays
|
|
600
|
-
- [ ] `http://localhost:3000/register` - Registration form displays
|
|
601
|
-
- [ ] `http://localhost:3000/
|
|
602
|
-
- [ ] `http://localhost:3000/
|
|
657
|
+
- [ ] `http://localhost:3000/hazo_auth/login` - Login form displays
|
|
658
|
+
- [ ] `http://localhost:3000/hazo_auth/register` - Registration form displays
|
|
659
|
+
- [ ] `http://localhost:3000/hazo_auth/forgot_password` - Forgot password form displays
|
|
660
|
+
- [ ] `http://localhost:3000/hazo_auth/my_settings` - Settings page displays (after login)
|
|
603
661
|
|
|
604
662
|
---
|
|
605
663
|
|
|
@@ -620,13 +678,26 @@ Visit each page and verify it loads:
|
|
|
620
678
|
**Symptoms:** Avatar shows fallback initials, library photos empty.
|
|
621
679
|
|
|
622
680
|
**Solutions:**
|
|
623
|
-
1.
|
|
681
|
+
1. **Run init command** (copies library photos automatically):
|
|
682
|
+
```bash
|
|
683
|
+
npx hazo_auth init
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
2. **Or manually copy library photos:**
|
|
624
687
|
```bash
|
|
625
688
|
mkdir -p public/profile_pictures/library
|
|
626
689
|
cp -r node_modules/hazo_auth/public/profile_pictures/library/* public/profile_pictures/library/
|
|
627
690
|
```
|
|
628
|
-
|
|
629
|
-
3. Check
|
|
691
|
+
|
|
692
|
+
3. **Check API response source:**
|
|
693
|
+
```bash
|
|
694
|
+
curl -s http://localhost:3000/api/hazo_auth/library_photos | jq '.source'
|
|
695
|
+
```
|
|
696
|
+
- If `"node_modules"` - Photos are being served from the package (slower but works)
|
|
697
|
+
- If `"project"` - Photos are in your public folder (optimal)
|
|
698
|
+
|
|
699
|
+
4. Verify `library_photos` and `library_photo` API routes exist
|
|
700
|
+
5. Check file permissions on `public/profile_pictures/`
|
|
630
701
|
|
|
631
702
|
### Issue: Database connection failed
|
|
632
703
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
export declare const dynamic = "force-dynamic";
|
|
3
|
+
export declare function GET(request: NextRequest, { params }: {
|
|
4
|
+
params: {
|
|
5
|
+
category: string;
|
|
6
|
+
filename: string;
|
|
7
|
+
};
|
|
8
|
+
}): Promise<NextResponse<unknown>>;
|
|
9
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/app/api/hazo_auth/library_photo/[category]/[filename]/route.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AASxD,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAevC,wBAAsB,GAAG,CACvB,OAAO,EAAE,WAAW,EACpB,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,kCA4E/D"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// file_description: API route to serve library photos from node_modules fallback
|
|
2
|
+
// This route is used when library photos haven't been copied to the project's public folder
|
|
3
|
+
// section: imports
|
|
4
|
+
import { NextResponse } from "next/server";
|
|
5
|
+
import { get_library_photo_path } from "../../../../../../lib/services/profile_picture_service";
|
|
6
|
+
import { create_app_logger } from "../../../../../../lib/app_logger";
|
|
7
|
+
import { get_filename, get_line_number } from "../../../../../../lib/utils/api_route_helpers";
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
import path from "path";
|
|
10
|
+
// section: route_config
|
|
11
|
+
// Cache library photos for 1 hour (they don't change)
|
|
12
|
+
export const dynamic = 'force-dynamic';
|
|
13
|
+
// section: constants
|
|
14
|
+
const MIME_TYPES = {
|
|
15
|
+
".jpg": "image/jpeg",
|
|
16
|
+
".jpeg": "image/jpeg",
|
|
17
|
+
".png": "image/png",
|
|
18
|
+
".gif": "image/gif",
|
|
19
|
+
".webp": "image/webp",
|
|
20
|
+
".svg": "image/svg+xml",
|
|
21
|
+
};
|
|
22
|
+
const CACHE_MAX_AGE = 3600; // 1 hour in seconds
|
|
23
|
+
// section: api_handler
|
|
24
|
+
export async function GET(request, { params }) {
|
|
25
|
+
const logger = create_app_logger();
|
|
26
|
+
const { category, filename } = params;
|
|
27
|
+
try {
|
|
28
|
+
// Validate inputs to prevent path traversal
|
|
29
|
+
if (category.includes("..") ||
|
|
30
|
+
category.includes("/") ||
|
|
31
|
+
category.includes("\\") ||
|
|
32
|
+
filename.includes("..") ||
|
|
33
|
+
filename.includes("/") ||
|
|
34
|
+
filename.includes("\\")) {
|
|
35
|
+
logger.warn("library_photo_invalid_path", {
|
|
36
|
+
filename: get_filename(),
|
|
37
|
+
line_number: get_line_number(),
|
|
38
|
+
category,
|
|
39
|
+
requested_filename: filename,
|
|
40
|
+
});
|
|
41
|
+
return NextResponse.json({ error: "Invalid path" }, { status: 400 });
|
|
42
|
+
}
|
|
43
|
+
// Get the physical file path
|
|
44
|
+
const photo_path = get_library_photo_path(category, filename);
|
|
45
|
+
if (!photo_path) {
|
|
46
|
+
logger.warn("library_photo_not_found", {
|
|
47
|
+
filename: get_filename(),
|
|
48
|
+
line_number: get_line_number(),
|
|
49
|
+
category,
|
|
50
|
+
requested_filename: filename,
|
|
51
|
+
});
|
|
52
|
+
return NextResponse.json({ error: "Photo not found" }, { status: 404 });
|
|
53
|
+
}
|
|
54
|
+
// Read the file
|
|
55
|
+
const file_buffer = fs.readFileSync(photo_path);
|
|
56
|
+
const ext = path.extname(filename).toLowerCase();
|
|
57
|
+
const content_type = MIME_TYPES[ext] || "application/octet-stream";
|
|
58
|
+
// Return the image with caching headers
|
|
59
|
+
return new NextResponse(file_buffer, {
|
|
60
|
+
status: 200,
|
|
61
|
+
headers: {
|
|
62
|
+
"Content-Type": content_type,
|
|
63
|
+
"Content-Length": file_buffer.length.toString(),
|
|
64
|
+
"Cache-Control": `public, max-age=${CACHE_MAX_AGE}, immutable`,
|
|
65
|
+
"X-Library-Source": "node_modules",
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
const error_message = error instanceof Error ? error.message : "Unknown error";
|
|
71
|
+
const error_stack = error instanceof Error ? error.stack : undefined;
|
|
72
|
+
logger.error("library_photo_error", {
|
|
73
|
+
filename: get_filename(),
|
|
74
|
+
line_number: get_line_number(),
|
|
75
|
+
category,
|
|
76
|
+
requested_filename: filename,
|
|
77
|
+
error_message,
|
|
78
|
+
error_stack,
|
|
79
|
+
});
|
|
80
|
+
return NextResponse.json({ error: "Failed to serve photo" }, { status: 500 });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -4,9 +4,18 @@ export declare function GET(request: NextRequest): Promise<NextResponse<{
|
|
|
4
4
|
success: boolean;
|
|
5
5
|
category: string;
|
|
6
6
|
photos: string[];
|
|
7
|
+
pagination: {
|
|
8
|
+
page: number;
|
|
9
|
+
page_size: number;
|
|
10
|
+
total: number;
|
|
11
|
+
has_more: boolean;
|
|
12
|
+
total_pages: number;
|
|
13
|
+
};
|
|
14
|
+
source: "project" | "node_modules";
|
|
7
15
|
}> | NextResponse<{
|
|
8
16
|
success: boolean;
|
|
9
17
|
categories: string[];
|
|
18
|
+
source: "project" | "node_modules" | null;
|
|
10
19
|
}> | NextResponse<{
|
|
11
20
|
error: string;
|
|
12
21
|
}>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/hazo_auth/library_photos/route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../src/app/api/hazo_auth/library_photos/route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAUxD,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAOvC,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;;;;;;;;;IAmF7C"}
|
|
@@ -1,43 +1,68 @@
|
|
|
1
|
-
// file_description: API route for listing library photo categories and photos in categories
|
|
1
|
+
// file_description: API route for listing library photo categories and photos in categories with pagination support
|
|
2
2
|
// section: imports
|
|
3
3
|
import { NextResponse } from "next/server";
|
|
4
|
-
import { get_library_categories,
|
|
4
|
+
import { get_library_categories, get_library_photos_paginated, get_library_source } from "../../../../lib/services/profile_picture_service";
|
|
5
5
|
import { create_app_logger } from "../../../../lib/app_logger";
|
|
6
6
|
import { get_filename, get_line_number } from "../../../../lib/utils/api_route_helpers";
|
|
7
7
|
// section: route_config
|
|
8
8
|
export const dynamic = 'force-dynamic';
|
|
9
|
+
// section: constants
|
|
10
|
+
const DEFAULT_PAGE_SIZE = 20;
|
|
11
|
+
const MAX_PAGE_SIZE = 100;
|
|
9
12
|
// section: api_handler
|
|
10
13
|
export async function GET(request) {
|
|
11
14
|
const logger = create_app_logger();
|
|
12
15
|
try {
|
|
13
16
|
const { searchParams } = new URL(request.url);
|
|
14
17
|
const category = searchParams.get("category");
|
|
18
|
+
const page_param = searchParams.get("page");
|
|
19
|
+
const page_size_param = searchParams.get("page_size");
|
|
20
|
+
// Parse pagination parameters
|
|
21
|
+
const page = page_param ? Math.max(1, parseInt(page_param, 10) || 1) : 1;
|
|
22
|
+
const page_size = page_size_param
|
|
23
|
+
? Math.min(MAX_PAGE_SIZE, Math.max(1, parseInt(page_size_param, 10) || DEFAULT_PAGE_SIZE))
|
|
24
|
+
: DEFAULT_PAGE_SIZE;
|
|
15
25
|
if (category) {
|
|
16
|
-
// Return photos in the specified category
|
|
17
|
-
const
|
|
26
|
+
// Return photos in the specified category with pagination
|
|
27
|
+
const result = get_library_photos_paginated(category, page, page_size);
|
|
18
28
|
logger.info("library_photos_category_requested", {
|
|
19
29
|
filename: get_filename(),
|
|
20
30
|
line_number: get_line_number(),
|
|
21
31
|
category,
|
|
22
|
-
|
|
32
|
+
page,
|
|
33
|
+
page_size,
|
|
34
|
+
total: result.total,
|
|
35
|
+
returned: result.photos.length,
|
|
36
|
+
source: result.source,
|
|
23
37
|
});
|
|
24
38
|
return NextResponse.json({
|
|
25
39
|
success: true,
|
|
26
40
|
category,
|
|
27
|
-
photos,
|
|
41
|
+
photos: result.photos,
|
|
42
|
+
pagination: {
|
|
43
|
+
page: result.page,
|
|
44
|
+
page_size: result.page_size,
|
|
45
|
+
total: result.total,
|
|
46
|
+
has_more: result.has_more,
|
|
47
|
+
total_pages: Math.ceil(result.total / result.page_size),
|
|
48
|
+
},
|
|
49
|
+
source: result.source,
|
|
28
50
|
}, { status: 200 });
|
|
29
51
|
}
|
|
30
52
|
else {
|
|
31
53
|
// Return list of categories
|
|
32
54
|
const categories = get_library_categories();
|
|
55
|
+
const source = get_library_source();
|
|
33
56
|
logger.info("library_categories_requested", {
|
|
34
57
|
filename: get_filename(),
|
|
35
58
|
line_number: get_line_number(),
|
|
36
59
|
categoryCount: categories.length,
|
|
60
|
+
source,
|
|
37
61
|
});
|
|
38
62
|
return NextResponse.json({
|
|
39
63
|
success: true,
|
|
40
64
|
categories,
|
|
65
|
+
source,
|
|
41
66
|
}, { status: 200 });
|
|
42
67
|
}
|
|
43
68
|
}
|
package/dist/cli/generate.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type GenerateOptions = {
|
|
2
|
+
dir?: string;
|
|
3
|
+
pages?: boolean;
|
|
4
|
+
all?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare function generate_routes(options?: GenerateOptions): void;
|
|
2
7
|
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/cli/generate.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAwJF,wBAAgB,eAAe,CAAC,OAAO,GAAE,eAAoB,GAAG,IAAI,CA8DnE"}
|