lieko-express 0.0.3 → 0.0.5

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 CHANGED
@@ -311,7 +311,7 @@ app.use((req, res, next) => {
311
311
  next();
312
312
  });
313
313
 
314
- // CORS middleware
314
+ // CORS middleware (native, but you can use app.cors())
315
315
  app.use((req, res, next) => {
316
316
  res.set('Access-Control-Allow-Origin', '*');
317
317
  res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
@@ -382,6 +382,380 @@ app.use(async (req, res, next) => {
382
382
  });
383
383
  ```
384
384
 
385
+ # **CORS**
386
+
387
+
388
+ Lieko-Express includes a **fully built-in, high-performance CORS engine**, with:
389
+
390
+ * Global CORS (`app.cors()`)
391
+ * Route-level CORS (`app.get("/test", { cors: {...} }, handler)`—coming soon if you want it)
392
+ * Wildcard origins (`https://*.example.com`)
393
+ * Multiple allowed origins
394
+ * Strict mode (reject unknown origins)
395
+ * Credential support
396
+ * Private Network Access (Chrome PNA)
397
+ * Debug logging
398
+ * Full OPTIONS preflight support
399
+
400
+ ---
401
+
402
+ # **Enable CORS Globally**
403
+
404
+ ```js
405
+ app.cors();
406
+ ```
407
+
408
+ This enables default permissive CORS:
409
+
410
+ | Option | Default |
411
+ | --------------------- | ----------------------------- |
412
+ | `origin` | `"*"` |
413
+ | `methods` | all standard methods |
414
+ | `headers` | `Content-Type, Authorization` |
415
+ | `credentials` | false |
416
+ | `maxAge` | 86400 (24h) |
417
+ | `exposedHeaders` | none |
418
+ | `strictOrigin` | false |
419
+ | `allowPrivateNetwork` | false |
420
+
421
+ ---
422
+
423
+ # **Custom Global CORS Options**
424
+
425
+ ```js
426
+ app.cors({
427
+ origin: ["https://example.com", "https://api.example.com"],
428
+ methods: ["GET", "POST"],
429
+ headers: ["Content-Type", "Authorization", "X-Custom"],
430
+ credentials: true,
431
+ maxAge: 3600,
432
+ exposedHeaders: ["X-RateLimit-Remaining"],
433
+ });
434
+ ```
435
+
436
+ ---
437
+
438
+ # **Allow All Origins (Standard Mode)**
439
+
440
+ ```js
441
+ app.cors({
442
+ origin: "*"
443
+ });
444
+ ```
445
+
446
+ ⚠️ If you also set `credentials: true`, browsers will **reject** `*`.
447
+ Lieko will still output `*` because that's the correct spec behavior.
448
+
449
+ ---
450
+
451
+ # **Strict Origin Mode**
452
+
453
+ Strict mode ensures the incoming `Origin` header **must match exactly** one of your allowed origins.
454
+
455
+ ```js
456
+ app.cors({
457
+ origin: ["https://myapp.com"],
458
+ strictOrigin: true
459
+ });
460
+ ```
461
+
462
+ If the request comes from an unauthorized origin:
463
+
464
+ ```json
465
+ HTTP 403
466
+ {
467
+ "success": false,
468
+ "error": "Origin Forbidden",
469
+ "message": "Origin \"https://evil.com\" is not allowed"
470
+ }
471
+ ```
472
+
473
+ ---
474
+
475
+ # **Wildcard Origins**
476
+
477
+ Lieko-Express supports Express-style wildcard patterns:
478
+
479
+ ### Allow any subdomain
480
+
481
+ ```js
482
+ app.cors({
483
+ origin: "https://*.example.com"
484
+ });
485
+ ```
486
+
487
+ Matches:
488
+
489
+ * `https://api.example.com`
490
+ * `https://dashboard.example.com`
491
+
492
+ Does not match:
493
+
494
+ * `http://example.com`
495
+ * `https://example.net`
496
+
497
+ ---
498
+
499
+ # **Allow Private Network Access (Chrome PNA)**
500
+
501
+ ```js
502
+ app.cors({
503
+ allowPrivateNetwork: true
504
+ });
505
+ ```
506
+
507
+ When Chrome sends:
508
+
509
+ ```
510
+ Access-Control-Request-Private-Network: true
511
+ ```
512
+
513
+ Lieko automatically responds:
514
+
515
+ ```
516
+ Access-Control-Allow-Private-Network: true
517
+ ```
518
+
519
+ # Route-Level CORS
520
+
521
+ Lieko-Express allows each route to override or extend the global CORS settings using a `cors` property in the route options.
522
+ This gives you fine-grained control over cross-origin behavior on a per-endpoint basis.
523
+
524
+ Route-level CORS:
525
+
526
+ * Overrides global CORS
527
+ * Supports wildcards (`https://*.example.com`)
528
+ * Supports strict mode
529
+ * Sends its own preflight response
530
+ * Automatically merges with the global configuration
531
+ * Does **not** affect other routes
532
+
533
+ ---
534
+
535
+ ## Basic Example
536
+
537
+ ```js
538
+ app.get("/public", {
539
+ cors: { origin: "*" }
540
+ }, (req, res) => {
541
+ res.ok("Public endpoint with open CORS");
542
+ });
543
+ ```
544
+
545
+ This route allows requests from **any origin**, even if global CORS is configured differently.
546
+
547
+ ---
548
+
549
+ ## 🔒 Restrict a Sensitive Route
550
+
551
+ ```js
552
+ app.post("/admin/login", {
553
+ cors: {
554
+ origin: "https://dashboard.myapp.com",
555
+ credentials: true,
556
+ strictOrigin: true
557
+ }
558
+ }, (req, res) => {
559
+ res.ok("Login OK");
560
+ });
561
+ ```
562
+
563
+ ### Result:
564
+
565
+ * Only `https://dashboard.myapp.com` is allowed
566
+ * Cookies / sessions allowed
567
+ * Any other origin receives:
568
+
569
+ ```json
570
+ {
571
+ "success": false,
572
+ "error": "Origin Forbidden",
573
+ "message": "Origin \"https://evil.com\" is not allowed"
574
+ }
575
+ ```
576
+
577
+ Status: **403 Forbidden**
578
+
579
+ ---
580
+
581
+ ## ✨ Wildcard Origins on a Route
582
+
583
+ ```js
584
+ app.get("/api/data", {
585
+ cors: {
586
+ origin: "https://*.example.com"
587
+ }
588
+ }, (req, res) => {
589
+ res.ok({ data: 123 });
590
+ });
591
+ ```
592
+
593
+ Matches:
594
+
595
+ * `https://api.example.com`
596
+ * `https://dashboard.example.com`
597
+
598
+ ---
599
+
600
+ ## ⚙️ Full Route-Level CORS Example
601
+
602
+ ```js
603
+ app.get("/user/profile", {
604
+ cors: {
605
+ origin: [
606
+ "https://app.example.com",
607
+ "https://*.trusted.dev"
608
+ ],
609
+ methods: ["GET", "PATCH"],
610
+ headers: ["Content-Type", "Authorization"],
611
+ exposedHeaders: ["X-User-Id"],
612
+ credentials: true,
613
+ maxAge: 600,
614
+ strictOrigin: true,
615
+ allowPrivateNetwork: true,
616
+ debug: true
617
+ }
618
+ }, (req, res) => {
619
+ res.ok({ profile: "OK" });
620
+ });
621
+ ```
622
+
623
+ ---
624
+
625
+ ## 📌 How Route-Level CORS Works Internally
626
+
627
+ When a request hits a route:
628
+
629
+ 1. If global CORS is enabled → apply it.
630
+ 2. If the route defines `cors` → merge with global config.
631
+ 3. Route CORS **overrides** global CORS.
632
+ 4. If request is `OPTIONS` (preflight) → return automatic CORS response.
633
+ 5. Otherwise → run route handler.
634
+
635
+ This ensures predictable behavior.
636
+
637
+ ---
638
+
639
+ ## 📘 Route-Level CORS Options
640
+
641
+ | Option | Type | Description | |
642
+ | --------------------- | ---------- | ---------------------------------------- | ---------------------------------------- |
643
+ | `origin` | `string | string[]` | Allowed origins (`*`, domain, wildcard). |
644
+ | `methods` | `string[]` | Allowed HTTP methods. | |
645
+ | `headers` | `string[]` | Allowed request headers. | |
646
+ | `exposedHeaders` | `string[]` | Response headers exposed to the browser. | |
647
+ | `credentials` | `boolean` | Allow cookies/sessions. | |
648
+ | `maxAge` | `number` | Preflight cache lifetime (seconds). | |
649
+ | `strictOrigin` | `boolean` | Reject non-matching origins with 403. | |
650
+ | `allowPrivateNetwork` | `boolean` | Enables Chrome Private Network Access. | |
651
+ | `debug` | `boolean` | Logs detailed CORS decisions. | |
652
+
653
+ ---
654
+
655
+ ## 🧩 Interaction with Global CORS
656
+
657
+ | Feature | Global | Route |
658
+ | ------------------ | ------ | ------------- |
659
+ | Origin | ✔ | ✔ (overrides) |
660
+ | Wildcards | ✔ | ✔ |
661
+ | Credentials | ✔ | ✔ |
662
+ | Strict Origin | ✔ | ✔ |
663
+ | Private Network | ✔ | ✔ |
664
+ | Debug Logging | ✔ | ✔ |
665
+ | Preflight Handling | ✔ | ✔ |
666
+ | Overrides Global | ❌ | ✔ |
667
+
668
+
669
+
670
+
671
+ # **Enable CORS Debug Logging**
672
+
673
+ ```js
674
+ app.cors({
675
+ debug: true
676
+ });
677
+ ```
678
+
679
+ Console output example:
680
+
681
+ ```
682
+ [CORS DEBUG]
683
+ Request: GET /users
684
+ Origin: https://app.example.com
685
+ Applied CORS Policy:
686
+ - Access-Control-Allow-Origin: https://app.example.com
687
+ - Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
688
+ - Access-Control-Allow-Headers: Content-Type, Authorization
689
+ - Max-Age: 86400
690
+ Simple request handled normally
691
+ ```
692
+
693
+ ---
694
+
695
+ # **Preflight Handling (OPTIONS)**
696
+
697
+ Lieko-Express automatically handles it:
698
+
699
+ ### Request:
700
+
701
+ ```
702
+ OPTIONS /login
703
+ Access-Control-Request-Method: POST
704
+ Access-Control-Request-Headers: Content-Type
705
+ ```
706
+
707
+ ### Lieko Response:
708
+
709
+ ```
710
+ 204 No Content
711
+ Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
712
+ Access-Control-Allow-Headers: Content-Type, Authorization
713
+ Access-Control-Max-Age: 86400
714
+ ```
715
+
716
+ ---
717
+
718
+ # **Credentials Support**
719
+
720
+ ```js
721
+ app.cors({
722
+ credentials: true,
723
+ origin: "https://myapp.com"
724
+ });
725
+ ```
726
+
727
+ Response contains:
728
+
729
+ ```
730
+ Access-Control-Allow-Credentials: true
731
+ ```
732
+
733
+ ---
734
+
735
+
736
+ # **Disable CORS**
737
+
738
+ Just don’t call `app.cors()`.
739
+ CORS stays fully disabled.
740
+
741
+ ---
742
+
743
+ # **Default CORS Configuration**
744
+
745
+ ```js
746
+ this.corsOptions = {
747
+ enabled: false,
748
+ origin: "*",
749
+ strictOrigin: false,
750
+ allowPrivateNetwork: false,
751
+ methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"],
752
+ headers: ["Content-Type", "Authorization"],
753
+ credentials: false,
754
+ maxAge: 86400,
755
+ exposedHeaders: [],
756
+ debug: false
757
+ };
758
+ ```
385
759
 
386
760
  # 🔍 Request Object
387
761
 
@@ -514,15 +888,83 @@ res.paginated(items, page, limit, total);
514
888
  * Error code → HTTP mapping
515
889
  * String errors also supported (`res.error("Invalid user")`)
516
890
 
517
- # 📦 Body Parsing
891
+ ---
892
+ # Body Parsing (JSON, URL-encoded, Multipart) — 100% Native, Zero Dependencies
893
+
894
+ Lieko Express ships with a **fast, secure, and fully native body parser** — no external packages, not even `body-parser`.
895
+
896
+ As soon as you create your app, body parsing is **automatically enabled**:
897
+
898
+ ```js
899
+ const app = Lieko(); // Ready to handle JSON, form-data, files, etc.
900
+ ```
901
+
902
+ ### Default Limits
903
+
904
+ | Content-Type | Default Limit | Bytes |
905
+ |---------------------------------------|---------------|-------------------|
906
+ | `application/json` | **1mb** | ~1,048,576 bytes |
907
+ | `application/x-www-form-urlencoded` | **1mb** | ~1,048,576 bytes |
908
+ | `multipart/form-data` (file uploads) | **10mb** | ~10,485,760 bytes |
909
+
910
+ That’s already **10× more generous** than Express’s default 100kb!
911
+
912
+ ### Change Limits — Three Super-Simple Ways
913
+
914
+ #### 1. Per content-type (most common)
915
+
916
+ ```js
917
+ app.json({ limit: '100mb' }); // JSON payloads only
918
+ app.urlencoded({ limit: '50mb' }); // Classic HTML forms
919
+ ```
920
+
921
+ #### 2. Global limit (JSON + urlencoded at once)
922
+
923
+ ```js
924
+ app.bodyParser({ limit: '50mb' });
925
+ // Applies 50mb to both JSON and urlencoded bodies
926
+ ```
927
+
928
+ #### 3. File upload limit (multipart/form-data)
929
+
930
+ ```js
931
+ app.multipart({ limit: '500mb' }); // For very large file uploads
932
+ ```
933
+
934
+ You can freely combine them:
935
+
936
+ ```js
937
+ const app = Lieko();
938
+
939
+ app.json({ limit: '10mb' }); // Small, fast JSON APIs
940
+ app.urlencoded({ limit: '5mb' });
941
+ app.multipart({ limit: '1gb' }); // Allow huge file uploads
942
+ ```
943
+
944
+ ### Real-world Example
945
+
946
+ ```js
947
+ const Lieko = require('lieko-express');
948
+ const app = Lieko();
949
+
950
+ // Accept reasonably large JSON payloads
951
+ app.json({ limit: '25mb' });
952
+
953
+ // Accept classic forms
954
+ app.urlencoded({ limit: '10mb' });
518
955
 
519
- Lieko supports:
956
+ // Allow big file uploads (photos, videos, etc.)
957
+ app.multipart({ limit: '500mb' });
520
958
 
521
- ### JSON
959
+ app.post('/upload', (req, res) => {
960
+ console.log('JSON body size :', Buffer.byteLength(JSON.stringify(req.body)), 'bytes');
961
+ console.log('Uploaded files :', Object.keys(req.files || {}));
522
962
 
523
- ### URL-encoded
963
+ res.ok({ received: true, files: req.files });
964
+ });
524
965
 
525
- ### ✔ Multipart form-data (files)
966
+ app.listen(3000);
967
+ ```
526
968
 
527
969
  Uploads end up in:
528
970
 
@@ -546,6 +988,12 @@ Query & body fields are **auto converted**:
546
988
  "null" → null
547
989
  ```
548
990
 
991
+
992
+ **No `app.use(express.json())`, no `app.use(express.urlencoded())`, no extra dependencies** — everything works out of the box, blazing fast, and fully configurable in one line.
993
+
994
+ That’s the Lieko philosophy: **less boilerplate, more power**.
995
+
996
+
549
997
  ### Response Methods
550
998
 
551
999
  ```javascript
@@ -1577,6 +2025,7 @@ DEBUG REQUEST
1577
2025
  → Params: {"id":"42"}
1578
2026
  → Query: {"page":2,"active":true}
1579
2027
  → Body: {}
2028
+ → Body Size: 0 bytes
1580
2029
  → Files:
1581
2030
  ---------------------------------------------
1582
2031
  ```
@@ -1649,9 +2098,9 @@ You can configure:
1649
2098
  ```js
1650
2099
  app.set('trust proxy', value);
1651
2100
  app.set('debug', boolean);
1652
- app.set('x-powered-by', false);
1653
- app.set('strictTrailingSlash', false);
1654
- app.set('allowTrailingSlash', true);
2101
+ app.set('x-powered-by', boolean);
2102
+ app.set('strictTrailingSlash', boolean);
2103
+ app.set('allowTrailingSlash', boolean);
1655
2104
  ```
1656
2105
 
1657
2106
  # 🌐 Trust Proxy & IP Parsing
@@ -1761,15 +2210,6 @@ function myPlugin(app) {
1761
2210
 
1762
2211
  myPlugin(app);
1763
2212
  ```
1764
-
1765
- ## 🚀 Deploying Lieko Express
1766
-
1767
- ### Node.js (PM2)
1768
-
1769
- ```bash
1770
- pm2 start app.js
1771
- ```
1772
-
1773
2213
  ## 📦 API Reference
1774
2214
 
1775
2215
  ### `Lieko()`