+41
CLAUDE_NOTES.md
+41
CLAUDE_NOTES.md
···
2
2
3
3
## Session 1: Initial Setup & Renaming Posts to Blips
4
4
5
+
## Session 2: Web Interface with del.icio.us Aesthetic
6
+
7
+
### Why This Step
8
+
- User wanted a web interface inspired by del.icio.us
9
+
- del.icio.us was perfect inspiration: minimalist, content-focused, tag-based
10
+
- Fits the "vibe radar" concept with simple signal transmission
11
+
12
+
### Implementation Details
13
+
- Express server with EJS templating
14
+
- Minimalist CSS mimicking del.icio.us style:
15
+
- Signature blue (#3366cc) accent color
16
+
- Verdana 11px font for that classic 2000s web feel
17
+
- Clean list-based layout
18
+
- Tag system for categorization
19
+
- Routes:
20
+
- `/` - Recent blips list
21
+
- `/submit` - Transmit new blips
22
+
- `/tag/:tag` - Filter by tag
23
+
- Added tags to BlonkBlip schema
24
+
- "Transmit" instead of "Submit" for radar theme
25
+
26
+
### Thoughts So Far
27
+
**Going Well:**
28
+
- The del.icio.us aesthetic works perfectly with the radar concept
29
+
- Tag system adds discoverability without complexity
30
+
- Clean separation between AT Protocol layer and web layer
31
+
32
+
**Potential Pitfalls:**
33
+
1. **Multi-user**: Currently only shows blips from the configured account. Need to aggregate from multiple users.
34
+
2. **Real-time updates**: No websockets yet, requires page refresh
35
+
3. **Fluff interactions**: Can display fluff count but can't vote yet
36
+
4. **Performance**: Loading all blips then filtering in memory won't scale
37
+
38
+
**Ideas for Next Steps:**
39
+
- Add fluff (upvote) functionality with AJAX
40
+
- User profiles showing their blip history
41
+
- Popular/trending radar view based on fluff velocity
42
+
- Tag clouds showing popular topics
43
+
- RSS feeds for tags
44
+
- Bookmarklet for quick blip submission (very del.icio.us!)
45
+
5
46
### Renaming Complete ✅
6
47
Successfully renamed all terminology:
7
48
- Posts → Blips
+1159
package-lock.json
+1159
package-lock.json
···
11
11
"dependencies": {
12
12
"@atproto/api": "^0.15.16",
13
13
"@atproto/lexicon": "^0.4.11",
14
+
"@types/express": "^5.0.3",
15
+
"@types/express-session": "^1.18.2",
14
16
"@types/node": "^24.0.3",
15
17
"dotenv": "^16.5.0",
18
+
"ejs": "^3.1.10",
19
+
"express": "^5.1.0",
20
+
"express-ejs-layouts": "^2.5.1",
21
+
"express-session": "^1.18.1",
16
22
"tsx": "^4.20.3",
17
23
"typescript": "^5.8.3"
18
24
}
···
474
480
"node": ">=18"
475
481
}
476
482
},
483
+
"node_modules/@types/body-parser": {
484
+
"version": "1.19.6",
485
+
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
486
+
"integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
487
+
"license": "MIT",
488
+
"dependencies": {
489
+
"@types/connect": "*",
490
+
"@types/node": "*"
491
+
}
492
+
},
493
+
"node_modules/@types/connect": {
494
+
"version": "3.4.38",
495
+
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
496
+
"integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
497
+
"license": "MIT",
498
+
"dependencies": {
499
+
"@types/node": "*"
500
+
}
501
+
},
502
+
"node_modules/@types/express": {
503
+
"version": "5.0.3",
504
+
"resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz",
505
+
"integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==",
506
+
"license": "MIT",
507
+
"dependencies": {
508
+
"@types/body-parser": "*",
509
+
"@types/express-serve-static-core": "^5.0.0",
510
+
"@types/serve-static": "*"
511
+
}
512
+
},
513
+
"node_modules/@types/express-serve-static-core": {
514
+
"version": "5.0.6",
515
+
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz",
516
+
"integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==",
517
+
"license": "MIT",
518
+
"dependencies": {
519
+
"@types/node": "*",
520
+
"@types/qs": "*",
521
+
"@types/range-parser": "*",
522
+
"@types/send": "*"
523
+
}
524
+
},
525
+
"node_modules/@types/express-session": {
526
+
"version": "1.18.2",
527
+
"resolved": "https://registry.npmjs.org/@types/express-session/-/express-session-1.18.2.tgz",
528
+
"integrity": "sha512-k+I0BxwVXsnEU2hV77cCobC08kIsn4y44C3gC0b46uxZVMaXA04lSPgRLR/bSL2w0t0ShJiG8o4jPzRG/nscFg==",
529
+
"license": "MIT",
530
+
"dependencies": {
531
+
"@types/express": "*"
532
+
}
533
+
},
534
+
"node_modules/@types/http-errors": {
535
+
"version": "2.0.5",
536
+
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
537
+
"integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
538
+
"license": "MIT"
539
+
},
540
+
"node_modules/@types/mime": {
541
+
"version": "1.3.5",
542
+
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
543
+
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
544
+
"license": "MIT"
545
+
},
477
546
"node_modules/@types/node": {
478
547
"version": "24.0.3",
479
548
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.3.tgz",
···
483
552
"undici-types": "~7.8.0"
484
553
}
485
554
},
555
+
"node_modules/@types/qs": {
556
+
"version": "6.14.0",
557
+
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
558
+
"integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
559
+
"license": "MIT"
560
+
},
561
+
"node_modules/@types/range-parser": {
562
+
"version": "1.2.7",
563
+
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
564
+
"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
565
+
"license": "MIT"
566
+
},
567
+
"node_modules/@types/send": {
568
+
"version": "0.17.5",
569
+
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz",
570
+
"integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==",
571
+
"license": "MIT",
572
+
"dependencies": {
573
+
"@types/mime": "^1",
574
+
"@types/node": "*"
575
+
}
576
+
},
577
+
"node_modules/@types/serve-static": {
578
+
"version": "1.15.8",
579
+
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz",
580
+
"integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==",
581
+
"license": "MIT",
582
+
"dependencies": {
583
+
"@types/http-errors": "*",
584
+
"@types/node": "*",
585
+
"@types/send": "*"
586
+
}
587
+
},
588
+
"node_modules/accepts": {
589
+
"version": "2.0.0",
590
+
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
591
+
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
592
+
"license": "MIT",
593
+
"dependencies": {
594
+
"mime-types": "^3.0.0",
595
+
"negotiator": "^1.0.0"
596
+
},
597
+
"engines": {
598
+
"node": ">= 0.6"
599
+
}
600
+
},
601
+
"node_modules/ansi-styles": {
602
+
"version": "4.3.0",
603
+
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
604
+
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
605
+
"license": "MIT",
606
+
"dependencies": {
607
+
"color-convert": "^2.0.1"
608
+
},
609
+
"engines": {
610
+
"node": ">=8"
611
+
},
612
+
"funding": {
613
+
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
614
+
}
615
+
},
616
+
"node_modules/async": {
617
+
"version": "3.2.6",
618
+
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
619
+
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
620
+
"license": "MIT"
621
+
},
486
622
"node_modules/await-lock": {
487
623
"version": "2.2.2",
488
624
"resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz",
489
625
"integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==",
490
626
"license": "MIT"
491
627
},
628
+
"node_modules/balanced-match": {
629
+
"version": "1.0.2",
630
+
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
631
+
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
632
+
"license": "MIT"
633
+
},
634
+
"node_modules/body-parser": {
635
+
"version": "2.2.0",
636
+
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
637
+
"integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
638
+
"license": "MIT",
639
+
"dependencies": {
640
+
"bytes": "^3.1.2",
641
+
"content-type": "^1.0.5",
642
+
"debug": "^4.4.0",
643
+
"http-errors": "^2.0.0",
644
+
"iconv-lite": "^0.6.3",
645
+
"on-finished": "^2.4.1",
646
+
"qs": "^6.14.0",
647
+
"raw-body": "^3.0.0",
648
+
"type-is": "^2.0.0"
649
+
},
650
+
"engines": {
651
+
"node": ">=18"
652
+
}
653
+
},
654
+
"node_modules/brace-expansion": {
655
+
"version": "1.1.12",
656
+
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
657
+
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
658
+
"license": "MIT",
659
+
"dependencies": {
660
+
"balanced-match": "^1.0.0",
661
+
"concat-map": "0.0.1"
662
+
}
663
+
},
664
+
"node_modules/bytes": {
665
+
"version": "3.1.2",
666
+
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
667
+
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
668
+
"license": "MIT",
669
+
"engines": {
670
+
"node": ">= 0.8"
671
+
}
672
+
},
673
+
"node_modules/call-bind-apply-helpers": {
674
+
"version": "1.0.2",
675
+
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
676
+
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
677
+
"license": "MIT",
678
+
"dependencies": {
679
+
"es-errors": "^1.3.0",
680
+
"function-bind": "^1.1.2"
681
+
},
682
+
"engines": {
683
+
"node": ">= 0.4"
684
+
}
685
+
},
686
+
"node_modules/call-bound": {
687
+
"version": "1.0.4",
688
+
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
689
+
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
690
+
"license": "MIT",
691
+
"dependencies": {
692
+
"call-bind-apply-helpers": "^1.0.2",
693
+
"get-intrinsic": "^1.3.0"
694
+
},
695
+
"engines": {
696
+
"node": ">= 0.4"
697
+
},
698
+
"funding": {
699
+
"url": "https://github.com/sponsors/ljharb"
700
+
}
701
+
},
702
+
"node_modules/chalk": {
703
+
"version": "4.1.2",
704
+
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
705
+
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
706
+
"license": "MIT",
707
+
"dependencies": {
708
+
"ansi-styles": "^4.1.0",
709
+
"supports-color": "^7.1.0"
710
+
},
711
+
"engines": {
712
+
"node": ">=10"
713
+
},
714
+
"funding": {
715
+
"url": "https://github.com/chalk/chalk?sponsor=1"
716
+
}
717
+
},
718
+
"node_modules/color-convert": {
719
+
"version": "2.0.1",
720
+
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
721
+
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
722
+
"license": "MIT",
723
+
"dependencies": {
724
+
"color-name": "~1.1.4"
725
+
},
726
+
"engines": {
727
+
"node": ">=7.0.0"
728
+
}
729
+
},
730
+
"node_modules/color-name": {
731
+
"version": "1.1.4",
732
+
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
733
+
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
734
+
"license": "MIT"
735
+
},
736
+
"node_modules/concat-map": {
737
+
"version": "0.0.1",
738
+
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
739
+
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
740
+
"license": "MIT"
741
+
},
742
+
"node_modules/content-disposition": {
743
+
"version": "1.0.0",
744
+
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz",
745
+
"integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
746
+
"license": "MIT",
747
+
"dependencies": {
748
+
"safe-buffer": "5.2.1"
749
+
},
750
+
"engines": {
751
+
"node": ">= 0.6"
752
+
}
753
+
},
754
+
"node_modules/content-type": {
755
+
"version": "1.0.5",
756
+
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
757
+
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
758
+
"license": "MIT",
759
+
"engines": {
760
+
"node": ">= 0.6"
761
+
}
762
+
},
763
+
"node_modules/cookie": {
764
+
"version": "0.7.2",
765
+
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
766
+
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
767
+
"license": "MIT",
768
+
"engines": {
769
+
"node": ">= 0.6"
770
+
}
771
+
},
772
+
"node_modules/cookie-signature": {
773
+
"version": "1.2.2",
774
+
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
775
+
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
776
+
"license": "MIT",
777
+
"engines": {
778
+
"node": ">=6.6.0"
779
+
}
780
+
},
781
+
"node_modules/debug": {
782
+
"version": "4.4.1",
783
+
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
784
+
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
785
+
"license": "MIT",
786
+
"dependencies": {
787
+
"ms": "^2.1.3"
788
+
},
789
+
"engines": {
790
+
"node": ">=6.0"
791
+
},
792
+
"peerDependenciesMeta": {
793
+
"supports-color": {
794
+
"optional": true
795
+
}
796
+
}
797
+
},
798
+
"node_modules/depd": {
799
+
"version": "2.0.0",
800
+
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
801
+
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
802
+
"license": "MIT",
803
+
"engines": {
804
+
"node": ">= 0.8"
805
+
}
806
+
},
492
807
"node_modules/dotenv": {
493
808
"version": "16.5.0",
494
809
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz",
···
501
816
"url": "https://dotenvx.com"
502
817
}
503
818
},
819
+
"node_modules/dunder-proto": {
820
+
"version": "1.0.1",
821
+
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
822
+
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
823
+
"license": "MIT",
824
+
"dependencies": {
825
+
"call-bind-apply-helpers": "^1.0.1",
826
+
"es-errors": "^1.3.0",
827
+
"gopd": "^1.2.0"
828
+
},
829
+
"engines": {
830
+
"node": ">= 0.4"
831
+
}
832
+
},
833
+
"node_modules/ee-first": {
834
+
"version": "1.1.1",
835
+
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
836
+
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
837
+
"license": "MIT"
838
+
},
839
+
"node_modules/ejs": {
840
+
"version": "3.1.10",
841
+
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
842
+
"integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
843
+
"license": "Apache-2.0",
844
+
"dependencies": {
845
+
"jake": "^10.8.5"
846
+
},
847
+
"bin": {
848
+
"ejs": "bin/cli.js"
849
+
},
850
+
"engines": {
851
+
"node": ">=0.10.0"
852
+
}
853
+
},
854
+
"node_modules/encodeurl": {
855
+
"version": "2.0.0",
856
+
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
857
+
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
858
+
"license": "MIT",
859
+
"engines": {
860
+
"node": ">= 0.8"
861
+
}
862
+
},
863
+
"node_modules/es-define-property": {
864
+
"version": "1.0.1",
865
+
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
866
+
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
867
+
"license": "MIT",
868
+
"engines": {
869
+
"node": ">= 0.4"
870
+
}
871
+
},
872
+
"node_modules/es-errors": {
873
+
"version": "1.3.0",
874
+
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
875
+
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
876
+
"license": "MIT",
877
+
"engines": {
878
+
"node": ">= 0.4"
879
+
}
880
+
},
881
+
"node_modules/es-object-atoms": {
882
+
"version": "1.1.1",
883
+
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
884
+
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
885
+
"license": "MIT",
886
+
"dependencies": {
887
+
"es-errors": "^1.3.0"
888
+
},
889
+
"engines": {
890
+
"node": ">= 0.4"
891
+
}
892
+
},
504
893
"node_modules/esbuild": {
505
894
"version": "0.25.5",
506
895
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz",
···
541
930
"@esbuild/win32-x64": "0.25.5"
542
931
}
543
932
},
933
+
"node_modules/escape-html": {
934
+
"version": "1.0.3",
935
+
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
936
+
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
937
+
"license": "MIT"
938
+
},
939
+
"node_modules/etag": {
940
+
"version": "1.8.1",
941
+
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
942
+
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
943
+
"license": "MIT",
944
+
"engines": {
945
+
"node": ">= 0.6"
946
+
}
947
+
},
948
+
"node_modules/express": {
949
+
"version": "5.1.0",
950
+
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
951
+
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
952
+
"license": "MIT",
953
+
"dependencies": {
954
+
"accepts": "^2.0.0",
955
+
"body-parser": "^2.2.0",
956
+
"content-disposition": "^1.0.0",
957
+
"content-type": "^1.0.5",
958
+
"cookie": "^0.7.1",
959
+
"cookie-signature": "^1.2.1",
960
+
"debug": "^4.4.0",
961
+
"encodeurl": "^2.0.0",
962
+
"escape-html": "^1.0.3",
963
+
"etag": "^1.8.1",
964
+
"finalhandler": "^2.1.0",
965
+
"fresh": "^2.0.0",
966
+
"http-errors": "^2.0.0",
967
+
"merge-descriptors": "^2.0.0",
968
+
"mime-types": "^3.0.0",
969
+
"on-finished": "^2.4.1",
970
+
"once": "^1.4.0",
971
+
"parseurl": "^1.3.3",
972
+
"proxy-addr": "^2.0.7",
973
+
"qs": "^6.14.0",
974
+
"range-parser": "^1.2.1",
975
+
"router": "^2.2.0",
976
+
"send": "^1.1.0",
977
+
"serve-static": "^2.2.0",
978
+
"statuses": "^2.0.1",
979
+
"type-is": "^2.0.1",
980
+
"vary": "^1.1.2"
981
+
},
982
+
"engines": {
983
+
"node": ">= 18"
984
+
},
985
+
"funding": {
986
+
"type": "opencollective",
987
+
"url": "https://opencollective.com/express"
988
+
}
989
+
},
990
+
"node_modules/express-ejs-layouts": {
991
+
"version": "2.5.1",
992
+
"resolved": "https://registry.npmjs.org/express-ejs-layouts/-/express-ejs-layouts-2.5.1.tgz",
993
+
"integrity": "sha512-IXROv9n3xKga7FowT06n1Qn927JR8ZWDn5Dc9CJQoiiaaDqbhW5PDmWShzbpAa2wjWT1vJqaIM1S6vJwwX11gA=="
994
+
},
995
+
"node_modules/express-session": {
996
+
"version": "1.18.1",
997
+
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.1.tgz",
998
+
"integrity": "sha512-a5mtTqEaZvBCL9A9aqkrtfz+3SMDhOVUnjafjo+s7A9Txkq+SVX2DLvSp1Zrv4uCXa3lMSK3viWnh9Gg07PBUA==",
999
+
"license": "MIT",
1000
+
"dependencies": {
1001
+
"cookie": "0.7.2",
1002
+
"cookie-signature": "1.0.7",
1003
+
"debug": "2.6.9",
1004
+
"depd": "~2.0.0",
1005
+
"on-headers": "~1.0.2",
1006
+
"parseurl": "~1.3.3",
1007
+
"safe-buffer": "5.2.1",
1008
+
"uid-safe": "~2.1.5"
1009
+
},
1010
+
"engines": {
1011
+
"node": ">= 0.8.0"
1012
+
}
1013
+
},
1014
+
"node_modules/express-session/node_modules/cookie-signature": {
1015
+
"version": "1.0.7",
1016
+
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
1017
+
"integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
1018
+
"license": "MIT"
1019
+
},
1020
+
"node_modules/express-session/node_modules/debug": {
1021
+
"version": "2.6.9",
1022
+
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
1023
+
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
1024
+
"license": "MIT",
1025
+
"dependencies": {
1026
+
"ms": "2.0.0"
1027
+
}
1028
+
},
1029
+
"node_modules/express-session/node_modules/ms": {
1030
+
"version": "2.0.0",
1031
+
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1032
+
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
1033
+
"license": "MIT"
1034
+
},
1035
+
"node_modules/filelist": {
1036
+
"version": "1.0.4",
1037
+
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
1038
+
"integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
1039
+
"license": "Apache-2.0",
1040
+
"dependencies": {
1041
+
"minimatch": "^5.0.1"
1042
+
}
1043
+
},
1044
+
"node_modules/filelist/node_modules/brace-expansion": {
1045
+
"version": "2.0.2",
1046
+
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
1047
+
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
1048
+
"license": "MIT",
1049
+
"dependencies": {
1050
+
"balanced-match": "^1.0.0"
1051
+
}
1052
+
},
1053
+
"node_modules/filelist/node_modules/minimatch": {
1054
+
"version": "5.1.6",
1055
+
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
1056
+
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
1057
+
"license": "ISC",
1058
+
"dependencies": {
1059
+
"brace-expansion": "^2.0.1"
1060
+
},
1061
+
"engines": {
1062
+
"node": ">=10"
1063
+
}
1064
+
},
1065
+
"node_modules/finalhandler": {
1066
+
"version": "2.1.0",
1067
+
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
1068
+
"integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
1069
+
"license": "MIT",
1070
+
"dependencies": {
1071
+
"debug": "^4.4.0",
1072
+
"encodeurl": "^2.0.0",
1073
+
"escape-html": "^1.0.3",
1074
+
"on-finished": "^2.4.1",
1075
+
"parseurl": "^1.3.3",
1076
+
"statuses": "^2.0.1"
1077
+
},
1078
+
"engines": {
1079
+
"node": ">= 0.8"
1080
+
}
1081
+
},
1082
+
"node_modules/forwarded": {
1083
+
"version": "0.2.0",
1084
+
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
1085
+
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
1086
+
"license": "MIT",
1087
+
"engines": {
1088
+
"node": ">= 0.6"
1089
+
}
1090
+
},
1091
+
"node_modules/fresh": {
1092
+
"version": "2.0.0",
1093
+
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
1094
+
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
1095
+
"license": "MIT",
1096
+
"engines": {
1097
+
"node": ">= 0.8"
1098
+
}
1099
+
},
544
1100
"node_modules/fsevents": {
545
1101
"version": "2.3.3",
546
1102
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
···
555
1111
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
556
1112
}
557
1113
},
1114
+
"node_modules/function-bind": {
1115
+
"version": "1.1.2",
1116
+
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
1117
+
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
1118
+
"license": "MIT",
1119
+
"funding": {
1120
+
"url": "https://github.com/sponsors/ljharb"
1121
+
}
1122
+
},
1123
+
"node_modules/get-intrinsic": {
1124
+
"version": "1.3.0",
1125
+
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
1126
+
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
1127
+
"license": "MIT",
1128
+
"dependencies": {
1129
+
"call-bind-apply-helpers": "^1.0.2",
1130
+
"es-define-property": "^1.0.1",
1131
+
"es-errors": "^1.3.0",
1132
+
"es-object-atoms": "^1.1.1",
1133
+
"function-bind": "^1.1.2",
1134
+
"get-proto": "^1.0.1",
1135
+
"gopd": "^1.2.0",
1136
+
"has-symbols": "^1.1.0",
1137
+
"hasown": "^2.0.2",
1138
+
"math-intrinsics": "^1.1.0"
1139
+
},
1140
+
"engines": {
1141
+
"node": ">= 0.4"
1142
+
},
1143
+
"funding": {
1144
+
"url": "https://github.com/sponsors/ljharb"
1145
+
}
1146
+
},
1147
+
"node_modules/get-proto": {
1148
+
"version": "1.0.1",
1149
+
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
1150
+
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
1151
+
"license": "MIT",
1152
+
"dependencies": {
1153
+
"dunder-proto": "^1.0.1",
1154
+
"es-object-atoms": "^1.0.0"
1155
+
},
1156
+
"engines": {
1157
+
"node": ">= 0.4"
1158
+
}
1159
+
},
558
1160
"node_modules/get-tsconfig": {
559
1161
"version": "4.10.1",
560
1162
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz",
···
567
1169
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
568
1170
}
569
1171
},
1172
+
"node_modules/gopd": {
1173
+
"version": "1.2.0",
1174
+
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
1175
+
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
1176
+
"license": "MIT",
1177
+
"engines": {
1178
+
"node": ">= 0.4"
1179
+
},
1180
+
"funding": {
1181
+
"url": "https://github.com/sponsors/ljharb"
1182
+
}
1183
+
},
570
1184
"node_modules/graphemer": {
571
1185
"version": "1.4.0",
572
1186
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
573
1187
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
574
1188
"license": "MIT"
575
1189
},
1190
+
"node_modules/has-flag": {
1191
+
"version": "4.0.0",
1192
+
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1193
+
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1194
+
"license": "MIT",
1195
+
"engines": {
1196
+
"node": ">=8"
1197
+
}
1198
+
},
1199
+
"node_modules/has-symbols": {
1200
+
"version": "1.1.0",
1201
+
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
1202
+
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
1203
+
"license": "MIT",
1204
+
"engines": {
1205
+
"node": ">= 0.4"
1206
+
},
1207
+
"funding": {
1208
+
"url": "https://github.com/sponsors/ljharb"
1209
+
}
1210
+
},
1211
+
"node_modules/hasown": {
1212
+
"version": "2.0.2",
1213
+
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
1214
+
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
1215
+
"license": "MIT",
1216
+
"dependencies": {
1217
+
"function-bind": "^1.1.2"
1218
+
},
1219
+
"engines": {
1220
+
"node": ">= 0.4"
1221
+
}
1222
+
},
1223
+
"node_modules/http-errors": {
1224
+
"version": "2.0.0",
1225
+
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
1226
+
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
1227
+
"license": "MIT",
1228
+
"dependencies": {
1229
+
"depd": "2.0.0",
1230
+
"inherits": "2.0.4",
1231
+
"setprototypeof": "1.2.0",
1232
+
"statuses": "2.0.1",
1233
+
"toidentifier": "1.0.1"
1234
+
},
1235
+
"engines": {
1236
+
"node": ">= 0.8"
1237
+
}
1238
+
},
1239
+
"node_modules/http-errors/node_modules/statuses": {
1240
+
"version": "2.0.1",
1241
+
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
1242
+
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
1243
+
"license": "MIT",
1244
+
"engines": {
1245
+
"node": ">= 0.8"
1246
+
}
1247
+
},
1248
+
"node_modules/iconv-lite": {
1249
+
"version": "0.6.3",
1250
+
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
1251
+
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
1252
+
"license": "MIT",
1253
+
"dependencies": {
1254
+
"safer-buffer": ">= 2.1.2 < 3.0.0"
1255
+
},
1256
+
"engines": {
1257
+
"node": ">=0.10.0"
1258
+
}
1259
+
},
1260
+
"node_modules/inherits": {
1261
+
"version": "2.0.4",
1262
+
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1263
+
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1264
+
"license": "ISC"
1265
+
},
1266
+
"node_modules/ipaddr.js": {
1267
+
"version": "1.9.1",
1268
+
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
1269
+
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
1270
+
"license": "MIT",
1271
+
"engines": {
1272
+
"node": ">= 0.10"
1273
+
}
1274
+
},
1275
+
"node_modules/is-promise": {
1276
+
"version": "4.0.0",
1277
+
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
1278
+
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
1279
+
"license": "MIT"
1280
+
},
576
1281
"node_modules/iso-datestring-validator": {
577
1282
"version": "2.2.2",
578
1283
"resolved": "https://registry.npmjs.org/iso-datestring-validator/-/iso-datestring-validator-2.2.2.tgz",
579
1284
"integrity": "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA==",
580
1285
"license": "MIT"
581
1286
},
1287
+
"node_modules/jake": {
1288
+
"version": "10.9.2",
1289
+
"resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
1290
+
"integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==",
1291
+
"license": "Apache-2.0",
1292
+
"dependencies": {
1293
+
"async": "^3.2.3",
1294
+
"chalk": "^4.0.2",
1295
+
"filelist": "^1.0.4",
1296
+
"minimatch": "^3.1.2"
1297
+
},
1298
+
"bin": {
1299
+
"jake": "bin/cli.js"
1300
+
},
1301
+
"engines": {
1302
+
"node": ">=10"
1303
+
}
1304
+
},
1305
+
"node_modules/math-intrinsics": {
1306
+
"version": "1.1.0",
1307
+
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
1308
+
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
1309
+
"license": "MIT",
1310
+
"engines": {
1311
+
"node": ">= 0.4"
1312
+
}
1313
+
},
1314
+
"node_modules/media-typer": {
1315
+
"version": "1.1.0",
1316
+
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
1317
+
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
1318
+
"license": "MIT",
1319
+
"engines": {
1320
+
"node": ">= 0.8"
1321
+
}
1322
+
},
1323
+
"node_modules/merge-descriptors": {
1324
+
"version": "2.0.0",
1325
+
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
1326
+
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
1327
+
"license": "MIT",
1328
+
"engines": {
1329
+
"node": ">=18"
1330
+
},
1331
+
"funding": {
1332
+
"url": "https://github.com/sponsors/sindresorhus"
1333
+
}
1334
+
},
1335
+
"node_modules/mime-db": {
1336
+
"version": "1.54.0",
1337
+
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
1338
+
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
1339
+
"license": "MIT",
1340
+
"engines": {
1341
+
"node": ">= 0.6"
1342
+
}
1343
+
},
1344
+
"node_modules/mime-types": {
1345
+
"version": "3.0.1",
1346
+
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
1347
+
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
1348
+
"license": "MIT",
1349
+
"dependencies": {
1350
+
"mime-db": "^1.54.0"
1351
+
},
1352
+
"engines": {
1353
+
"node": ">= 0.6"
1354
+
}
1355
+
},
1356
+
"node_modules/minimatch": {
1357
+
"version": "3.1.2",
1358
+
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1359
+
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1360
+
"license": "ISC",
1361
+
"dependencies": {
1362
+
"brace-expansion": "^1.1.7"
1363
+
},
1364
+
"engines": {
1365
+
"node": "*"
1366
+
}
1367
+
},
1368
+
"node_modules/ms": {
1369
+
"version": "2.1.3",
1370
+
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1371
+
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1372
+
"license": "MIT"
1373
+
},
582
1374
"node_modules/multiformats": {
583
1375
"version": "9.9.0",
584
1376
"resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz",
585
1377
"integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==",
586
1378
"license": "(Apache-2.0 AND MIT)"
587
1379
},
1380
+
"node_modules/negotiator": {
1381
+
"version": "1.0.0",
1382
+
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
1383
+
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
1384
+
"license": "MIT",
1385
+
"engines": {
1386
+
"node": ">= 0.6"
1387
+
}
1388
+
},
1389
+
"node_modules/object-inspect": {
1390
+
"version": "1.13.4",
1391
+
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
1392
+
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
1393
+
"license": "MIT",
1394
+
"engines": {
1395
+
"node": ">= 0.4"
1396
+
},
1397
+
"funding": {
1398
+
"url": "https://github.com/sponsors/ljharb"
1399
+
}
1400
+
},
1401
+
"node_modules/on-finished": {
1402
+
"version": "2.4.1",
1403
+
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
1404
+
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
1405
+
"license": "MIT",
1406
+
"dependencies": {
1407
+
"ee-first": "1.1.1"
1408
+
},
1409
+
"engines": {
1410
+
"node": ">= 0.8"
1411
+
}
1412
+
},
1413
+
"node_modules/on-headers": {
1414
+
"version": "1.0.2",
1415
+
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
1416
+
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
1417
+
"license": "MIT",
1418
+
"engines": {
1419
+
"node": ">= 0.8"
1420
+
}
1421
+
},
1422
+
"node_modules/once": {
1423
+
"version": "1.4.0",
1424
+
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1425
+
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1426
+
"license": "ISC",
1427
+
"dependencies": {
1428
+
"wrappy": "1"
1429
+
}
1430
+
},
1431
+
"node_modules/parseurl": {
1432
+
"version": "1.3.3",
1433
+
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
1434
+
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
1435
+
"license": "MIT",
1436
+
"engines": {
1437
+
"node": ">= 0.8"
1438
+
}
1439
+
},
1440
+
"node_modules/path-to-regexp": {
1441
+
"version": "8.2.0",
1442
+
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
1443
+
"integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
1444
+
"license": "MIT",
1445
+
"engines": {
1446
+
"node": ">=16"
1447
+
}
1448
+
},
1449
+
"node_modules/proxy-addr": {
1450
+
"version": "2.0.7",
1451
+
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
1452
+
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
1453
+
"license": "MIT",
1454
+
"dependencies": {
1455
+
"forwarded": "0.2.0",
1456
+
"ipaddr.js": "1.9.1"
1457
+
},
1458
+
"engines": {
1459
+
"node": ">= 0.10"
1460
+
}
1461
+
},
1462
+
"node_modules/qs": {
1463
+
"version": "6.14.0",
1464
+
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
1465
+
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
1466
+
"license": "BSD-3-Clause",
1467
+
"dependencies": {
1468
+
"side-channel": "^1.1.0"
1469
+
},
1470
+
"engines": {
1471
+
"node": ">=0.6"
1472
+
},
1473
+
"funding": {
1474
+
"url": "https://github.com/sponsors/ljharb"
1475
+
}
1476
+
},
1477
+
"node_modules/random-bytes": {
1478
+
"version": "1.0.0",
1479
+
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
1480
+
"integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==",
1481
+
"license": "MIT",
1482
+
"engines": {
1483
+
"node": ">= 0.8"
1484
+
}
1485
+
},
1486
+
"node_modules/range-parser": {
1487
+
"version": "1.2.1",
1488
+
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1489
+
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
1490
+
"license": "MIT",
1491
+
"engines": {
1492
+
"node": ">= 0.6"
1493
+
}
1494
+
},
1495
+
"node_modules/raw-body": {
1496
+
"version": "3.0.0",
1497
+
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
1498
+
"integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
1499
+
"license": "MIT",
1500
+
"dependencies": {
1501
+
"bytes": "3.1.2",
1502
+
"http-errors": "2.0.0",
1503
+
"iconv-lite": "0.6.3",
1504
+
"unpipe": "1.0.0"
1505
+
},
1506
+
"engines": {
1507
+
"node": ">= 0.8"
1508
+
}
1509
+
},
588
1510
"node_modules/resolve-pkg-maps": {
589
1511
"version": "1.0.0",
590
1512
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
···
594
1516
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
595
1517
}
596
1518
},
1519
+
"node_modules/router": {
1520
+
"version": "2.2.0",
1521
+
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
1522
+
"integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
1523
+
"license": "MIT",
1524
+
"dependencies": {
1525
+
"debug": "^4.4.0",
1526
+
"depd": "^2.0.0",
1527
+
"is-promise": "^4.0.0",
1528
+
"parseurl": "^1.3.3",
1529
+
"path-to-regexp": "^8.0.0"
1530
+
},
1531
+
"engines": {
1532
+
"node": ">= 18"
1533
+
}
1534
+
},
1535
+
"node_modules/safe-buffer": {
1536
+
"version": "5.2.1",
1537
+
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1538
+
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1539
+
"funding": [
1540
+
{
1541
+
"type": "github",
1542
+
"url": "https://github.com/sponsors/feross"
1543
+
},
1544
+
{
1545
+
"type": "patreon",
1546
+
"url": "https://www.patreon.com/feross"
1547
+
},
1548
+
{
1549
+
"type": "consulting",
1550
+
"url": "https://feross.org/support"
1551
+
}
1552
+
],
1553
+
"license": "MIT"
1554
+
},
1555
+
"node_modules/safer-buffer": {
1556
+
"version": "2.1.2",
1557
+
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1558
+
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
1559
+
"license": "MIT"
1560
+
},
1561
+
"node_modules/send": {
1562
+
"version": "1.2.0",
1563
+
"resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
1564
+
"integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
1565
+
"license": "MIT",
1566
+
"dependencies": {
1567
+
"debug": "^4.3.5",
1568
+
"encodeurl": "^2.0.0",
1569
+
"escape-html": "^1.0.3",
1570
+
"etag": "^1.8.1",
1571
+
"fresh": "^2.0.0",
1572
+
"http-errors": "^2.0.0",
1573
+
"mime-types": "^3.0.1",
1574
+
"ms": "^2.1.3",
1575
+
"on-finished": "^2.4.1",
1576
+
"range-parser": "^1.2.1",
1577
+
"statuses": "^2.0.1"
1578
+
},
1579
+
"engines": {
1580
+
"node": ">= 18"
1581
+
}
1582
+
},
1583
+
"node_modules/serve-static": {
1584
+
"version": "2.2.0",
1585
+
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",
1586
+
"integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
1587
+
"license": "MIT",
1588
+
"dependencies": {
1589
+
"encodeurl": "^2.0.0",
1590
+
"escape-html": "^1.0.3",
1591
+
"parseurl": "^1.3.3",
1592
+
"send": "^1.2.0"
1593
+
},
1594
+
"engines": {
1595
+
"node": ">= 18"
1596
+
}
1597
+
},
1598
+
"node_modules/setprototypeof": {
1599
+
"version": "1.2.0",
1600
+
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
1601
+
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
1602
+
"license": "ISC"
1603
+
},
1604
+
"node_modules/side-channel": {
1605
+
"version": "1.1.0",
1606
+
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
1607
+
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
1608
+
"license": "MIT",
1609
+
"dependencies": {
1610
+
"es-errors": "^1.3.0",
1611
+
"object-inspect": "^1.13.3",
1612
+
"side-channel-list": "^1.0.0",
1613
+
"side-channel-map": "^1.0.1",
1614
+
"side-channel-weakmap": "^1.0.2"
1615
+
},
1616
+
"engines": {
1617
+
"node": ">= 0.4"
1618
+
},
1619
+
"funding": {
1620
+
"url": "https://github.com/sponsors/ljharb"
1621
+
}
1622
+
},
1623
+
"node_modules/side-channel-list": {
1624
+
"version": "1.0.0",
1625
+
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
1626
+
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
1627
+
"license": "MIT",
1628
+
"dependencies": {
1629
+
"es-errors": "^1.3.0",
1630
+
"object-inspect": "^1.13.3"
1631
+
},
1632
+
"engines": {
1633
+
"node": ">= 0.4"
1634
+
},
1635
+
"funding": {
1636
+
"url": "https://github.com/sponsors/ljharb"
1637
+
}
1638
+
},
1639
+
"node_modules/side-channel-map": {
1640
+
"version": "1.0.1",
1641
+
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
1642
+
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
1643
+
"license": "MIT",
1644
+
"dependencies": {
1645
+
"call-bound": "^1.0.2",
1646
+
"es-errors": "^1.3.0",
1647
+
"get-intrinsic": "^1.2.5",
1648
+
"object-inspect": "^1.13.3"
1649
+
},
1650
+
"engines": {
1651
+
"node": ">= 0.4"
1652
+
},
1653
+
"funding": {
1654
+
"url": "https://github.com/sponsors/ljharb"
1655
+
}
1656
+
},
1657
+
"node_modules/side-channel-weakmap": {
1658
+
"version": "1.0.2",
1659
+
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
1660
+
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
1661
+
"license": "MIT",
1662
+
"dependencies": {
1663
+
"call-bound": "^1.0.2",
1664
+
"es-errors": "^1.3.0",
1665
+
"get-intrinsic": "^1.2.5",
1666
+
"object-inspect": "^1.13.3",
1667
+
"side-channel-map": "^1.0.1"
1668
+
},
1669
+
"engines": {
1670
+
"node": ">= 0.4"
1671
+
},
1672
+
"funding": {
1673
+
"url": "https://github.com/sponsors/ljharb"
1674
+
}
1675
+
},
1676
+
"node_modules/statuses": {
1677
+
"version": "2.0.2",
1678
+
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
1679
+
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
1680
+
"license": "MIT",
1681
+
"engines": {
1682
+
"node": ">= 0.8"
1683
+
}
1684
+
},
1685
+
"node_modules/supports-color": {
1686
+
"version": "7.2.0",
1687
+
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1688
+
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1689
+
"license": "MIT",
1690
+
"dependencies": {
1691
+
"has-flag": "^4.0.0"
1692
+
},
1693
+
"engines": {
1694
+
"node": ">=8"
1695
+
}
1696
+
},
597
1697
"node_modules/tlds": {
598
1698
"version": "1.259.0",
599
1699
"resolved": "https://registry.npmjs.org/tlds/-/tlds-1.259.0.tgz",
···
603
1703
"tlds": "bin.js"
604
1704
}
605
1705
},
1706
+
"node_modules/toidentifier": {
1707
+
"version": "1.0.1",
1708
+
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
1709
+
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
1710
+
"license": "MIT",
1711
+
"engines": {
1712
+
"node": ">=0.6"
1713
+
}
1714
+
},
606
1715
"node_modules/tsx": {
607
1716
"version": "4.20.3",
608
1717
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz",
···
620
1729
},
621
1730
"optionalDependencies": {
622
1731
"fsevents": "~2.3.3"
1732
+
}
1733
+
},
1734
+
"node_modules/type-is": {
1735
+
"version": "2.0.1",
1736
+
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
1737
+
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
1738
+
"license": "MIT",
1739
+
"dependencies": {
1740
+
"content-type": "^1.0.5",
1741
+
"media-typer": "^1.1.0",
1742
+
"mime-types": "^3.0.0"
1743
+
},
1744
+
"engines": {
1745
+
"node": ">= 0.6"
623
1746
}
624
1747
},
625
1748
"node_modules/typescript": {
···
635
1758
"node": ">=14.17"
636
1759
}
637
1760
},
1761
+
"node_modules/uid-safe": {
1762
+
"version": "2.1.5",
1763
+
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
1764
+
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
1765
+
"license": "MIT",
1766
+
"dependencies": {
1767
+
"random-bytes": "~1.0.0"
1768
+
},
1769
+
"engines": {
1770
+
"node": ">= 0.8"
1771
+
}
1772
+
},
638
1773
"node_modules/uint8arrays": {
639
1774
"version": "3.0.0",
640
1775
"resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz",
···
649
1784
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
650
1785
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
651
1786
"license": "MIT"
1787
+
},
1788
+
"node_modules/unpipe": {
1789
+
"version": "1.0.0",
1790
+
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1791
+
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
1792
+
"license": "MIT",
1793
+
"engines": {
1794
+
"node": ">= 0.8"
1795
+
}
1796
+
},
1797
+
"node_modules/vary": {
1798
+
"version": "1.1.2",
1799
+
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1800
+
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
1801
+
"license": "MIT",
1802
+
"engines": {
1803
+
"node": ">= 0.8"
1804
+
}
1805
+
},
1806
+
"node_modules/wrappy": {
1807
+
"version": "1.0.2",
1808
+
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1809
+
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
1810
+
"license": "ISC"
652
1811
},
653
1812
"node_modules/zod": {
654
1813
"version": "3.25.67",
+7
package.json
+7
package.json
···
4
4
"main": "index.js",
5
5
"scripts": {
6
6
"dev": "tsx watch src/index.ts",
7
+
"web": "tsx watch src/server.ts",
7
8
"build": "tsc",
8
9
"start": "node dist/index.js",
9
10
"test": "echo \"Error: no test specified\" && exit 1"
···
15
16
"dependencies": {
16
17
"@atproto/api": "^0.15.16",
17
18
"@atproto/lexicon": "^0.4.11",
19
+
"@types/express": "^5.0.3",
20
+
"@types/express-session": "^1.18.2",
18
21
"@types/node": "^24.0.3",
19
22
"dotenv": "^16.5.0",
23
+
"ejs": "^3.1.10",
24
+
"express": "^5.1.0",
25
+
"express-ejs-layouts": "^2.5.1",
26
+
"express-session": "^1.18.1",
20
27
"tsx": "^4.20.3",
21
28
"typescript": "^5.8.3"
22
29
}
+203
public/css/style.css
+203
public/css/style.css
···
1
+
:root {
2
+
--blonk-blue: #3366cc;
3
+
--blonk-light-blue: #6699ff;
4
+
--blonk-gray: #666666;
5
+
--blonk-light-gray: #cccccc;
6
+
--blonk-bg: #f8f8f8;
7
+
--blonk-white: #ffffff;
8
+
}
9
+
10
+
* {
11
+
margin: 0;
12
+
padding: 0;
13
+
box-sizing: border-box;
14
+
}
15
+
16
+
body {
17
+
font-family: Verdana, Arial, sans-serif;
18
+
font-size: 11px;
19
+
line-height: 1.4;
20
+
color: #333;
21
+
background-color: var(--blonk-bg);
22
+
}
23
+
24
+
.container {
25
+
max-width: 800px;
26
+
margin: 0 auto;
27
+
padding: 20px;
28
+
}
29
+
30
+
header {
31
+
background-color: var(--blonk-blue);
32
+
color: var(--blonk-white);
33
+
padding: 10px 0;
34
+
margin-bottom: 20px;
35
+
}
36
+
37
+
header .container {
38
+
display: flex;
39
+
justify-content: space-between;
40
+
align-items: center;
41
+
padding: 0 20px;
42
+
}
43
+
44
+
header h1 {
45
+
font-size: 24px;
46
+
font-weight: normal;
47
+
letter-spacing: -1px;
48
+
}
49
+
50
+
header nav a {
51
+
color: var(--blonk-white);
52
+
text-decoration: none;
53
+
margin-left: 15px;
54
+
font-size: 12px;
55
+
}
56
+
57
+
header nav a:hover {
58
+
text-decoration: underline;
59
+
}
60
+
61
+
.blip-list {
62
+
background-color: var(--blonk-white);
63
+
border: 1px solid var(--blonk-light-gray);
64
+
}
65
+
66
+
.blip-item {
67
+
padding: 8px 10px;
68
+
border-bottom: 1px solid #f0f0f0;
69
+
display: flex;
70
+
align-items: start;
71
+
gap: 10px;
72
+
}
73
+
74
+
.blip-item:last-child {
75
+
border-bottom: none;
76
+
}
77
+
78
+
.blip-fluffs {
79
+
color: var(--blonk-gray);
80
+
font-size: 10px;
81
+
min-width: 30px;
82
+
text-align: right;
83
+
padding-top: 2px;
84
+
}
85
+
86
+
.blip-content {
87
+
flex: 1;
88
+
}
89
+
90
+
.blip-title {
91
+
color: var(--blonk-blue);
92
+
text-decoration: none;
93
+
font-size: 12px;
94
+
font-weight: normal;
95
+
}
96
+
97
+
.blip-title:hover {
98
+
text-decoration: underline;
99
+
}
100
+
101
+
.blip-meta {
102
+
color: var(--blonk-gray);
103
+
font-size: 10px;
104
+
margin-top: 2px;
105
+
}
106
+
107
+
.blip-tags {
108
+
display: inline;
109
+
margin-left: 5px;
110
+
}
111
+
112
+
.tag {
113
+
color: var(--blonk-gray);
114
+
text-decoration: none;
115
+
margin-right: 5px;
116
+
font-size: 10px;
117
+
}
118
+
119
+
.tag:hover {
120
+
color: var(--blonk-blue);
121
+
text-decoration: underline;
122
+
}
123
+
124
+
.tag:before {
125
+
content: '';
126
+
}
127
+
128
+
.submit-form {
129
+
background-color: var(--blonk-white);
130
+
border: 1px solid var(--blonk-light-gray);
131
+
padding: 20px;
132
+
margin-top: 20px;
133
+
}
134
+
135
+
.form-group {
136
+
margin-bottom: 15px;
137
+
}
138
+
139
+
.form-group label {
140
+
display: block;
141
+
color: var(--blonk-gray);
142
+
margin-bottom: 3px;
143
+
font-size: 11px;
144
+
}
145
+
146
+
.form-group input[type="text"],
147
+
.form-group input[type="url"],
148
+
.form-group textarea {
149
+
width: 100%;
150
+
padding: 4px 6px;
151
+
border: 1px solid var(--blonk-light-gray);
152
+
font-family: Verdana, Arial, sans-serif;
153
+
font-size: 11px;
154
+
}
155
+
156
+
.form-group textarea {
157
+
height: 60px;
158
+
resize: vertical;
159
+
}
160
+
161
+
.form-note {
162
+
color: var(--blonk-gray);
163
+
font-size: 10px;
164
+
margin-top: 2px;
165
+
}
166
+
167
+
.submit-button {
168
+
background-color: var(--blonk-blue);
169
+
color: var(--blonk-white);
170
+
border: none;
171
+
padding: 5px 15px;
172
+
font-size: 11px;
173
+
cursor: pointer;
174
+
}
175
+
176
+
.submit-button:hover {
177
+
background-color: var(--blonk-light-blue);
178
+
}
179
+
180
+
.page-title {
181
+
font-size: 16px;
182
+
color: var(--blonk-gray);
183
+
margin-bottom: 15px;
184
+
font-weight: normal;
185
+
}
186
+
187
+
.empty-state {
188
+
text-align: center;
189
+
padding: 40px;
190
+
color: var(--blonk-gray);
191
+
}
192
+
193
+
.radar-icon {
194
+
display: inline-block;
195
+
animation: pulse 2s infinite;
196
+
margin-right: 5px;
197
+
}
198
+
199
+
@keyframes pulse {
200
+
0% { opacity: 1; }
201
+
50% { opacity: 0.5; }
202
+
100% { opacity: 1; }
203
+
}
+2
-1
src/blips.ts
+2
-1
src/blips.ts
···
4
4
export class BlipManager {
5
5
constructor(private agent: BskyAgent) {}
6
6
7
-
async createBlip(title: string, body?: string, url?: string): Promise<string> {
7
+
async createBlip(title: string, body?: string, url?: string, tags?: string[]): Promise<string> {
8
8
const blip: BlonkBlip = {
9
9
title,
10
10
body,
11
11
url,
12
+
tags,
12
13
createdAt: new Date().toISOString(),
13
14
fluffs: 0,
14
15
};
+2
-1
src/index.ts
+2
-1
src/index.ts
···
16
16
const blipUri = await blipManager.createBlip(
17
17
'Welcome to the Blonk Vibe Radar!',
18
18
'This is the first blip on Blonk, where vibes are tracked on the radar.',
19
-
'https://atproto.com'
19
+
'https://atproto.com',
20
+
['welcome', 'atproto', 'blonk']
20
21
);
21
22
console.log(`Blip transmitted with URI: ${blipUri}\n`);
22
23
+1
src/schemas.ts
+1
src/schemas.ts
+85
src/server.ts
+85
src/server.ts
···
1
+
import express from 'express';
2
+
import session from 'express-session';
3
+
import expressLayouts from 'express-ejs-layouts';
4
+
import path from 'path';
5
+
import { BlonkAgent } from './agent';
6
+
import { BlipManager } from './blips';
7
+
import * as dotenv from 'dotenv';
8
+
9
+
dotenv.config();
10
+
11
+
const app = express();
12
+
const PORT = process.env.PORT || 3000;
13
+
14
+
app.set('view engine', 'ejs');
15
+
app.set('views', path.join(__dirname, '../views'));
16
+
app.use(expressLayouts);
17
+
app.set('layout', 'layout');
18
+
app.use(express.static(path.join(__dirname, '../public')));
19
+
app.use(express.urlencoded({ extended: true }));
20
+
app.use(express.json());
21
+
22
+
app.use(session({
23
+
secret: process.env.SESSION_SECRET || 'blonk-secret-key',
24
+
resave: false,
25
+
saveUninitialized: true,
26
+
}));
27
+
28
+
let agent: BlonkAgent;
29
+
let blipManager: BlipManager;
30
+
31
+
async function initializeAgent() {
32
+
agent = new BlonkAgent();
33
+
await agent.login();
34
+
blipManager = new BlipManager(agent.getAgent());
35
+
console.log('✅ Connected to AT Protocol');
36
+
}
37
+
38
+
app.get('/', async (req, res) => {
39
+
try {
40
+
const blips = await blipManager.getBlips(50);
41
+
res.render('index', { blips, user: req.session.user });
42
+
} catch (error) {
43
+
console.error('Error fetching blips:', error);
44
+
res.render('index', { blips: [], user: req.session.user });
45
+
}
46
+
});
47
+
48
+
app.get('/submit', (req, res) => {
49
+
res.render('submit', { user: req.session.user });
50
+
});
51
+
52
+
app.post('/submit', async (req, res) => {
53
+
try {
54
+
const { title, url, body, tags } = req.body;
55
+
const tagArray = tags ? tags.split(' ').filter((t: string) => t.length > 0) : [];
56
+
57
+
await blipManager.createBlip(title, body, url, tagArray);
58
+
res.redirect('/');
59
+
} catch (error) {
60
+
console.error('Error creating blip:', error);
61
+
res.render('submit', { error: 'Failed to create blip', user: req.session.user });
62
+
}
63
+
});
64
+
65
+
app.get('/tag/:tag', async (req, res) => {
66
+
try {
67
+
const allBlips = await blipManager.getBlips(100);
68
+
const taggedBlips = allBlips.filter(blip =>
69
+
blip.tags?.includes(req.params.tag)
70
+
);
71
+
res.render('tag', { blips: taggedBlips, tag: req.params.tag, user: req.session.user });
72
+
} catch (error) {
73
+
console.error('Error fetching tagged blips:', error);
74
+
res.render('tag', { blips: [], tag: req.params.tag, user: req.session.user });
75
+
}
76
+
});
77
+
78
+
initializeAgent().then(() => {
79
+
app.listen(PORT, () => {
80
+
console.log(`🌐 Blonk server running at http://localhost:${PORT}`);
81
+
});
82
+
}).catch(error => {
83
+
console.error('Failed to initialize:', error);
84
+
process.exit(1);
85
+
});
+42
views/index.ejs
+42
views/index.ejs
···
1
+
<h2 class="page-title">recent blips on the radar</h2>
2
+
3
+
<div class="blip-list">
4
+
<% if (blips.length === 0) { %>
5
+
<div class="empty-state">
6
+
<p>No blips detected on the radar yet.</p>
7
+
<p><a href="/submit">Transmit the first blip</a></p>
8
+
</div>
9
+
<% } else { %>
10
+
<% blips.forEach(blip => { %>
11
+
<div class="blip-item">
12
+
<div class="blip-fluffs">
13
+
<%= blip.fluffs %>
14
+
</div>
15
+
<div class="blip-content">
16
+
<% if (blip.url) { %>
17
+
<a href="<%= blip.url %>" class="blip-title" target="_blank"><%= blip.title %></a>
18
+
<% } else { %>
19
+
<span class="blip-title"><%= blip.title %></span>
20
+
<% } %>
21
+
22
+
<% if (blip.body) { %>
23
+
<div style="color: #666; font-size: 10px; margin-top: 2px;">
24
+
<%= blip.body.substring(0, 200) %><%= blip.body.length > 200 ? '...' : '' %>
25
+
</div>
26
+
<% } %>
27
+
28
+
<div class="blip-meta">
29
+
<span><%= new Date(blip.createdAt).toLocaleString() %></span>
30
+
<% if (blip.tags && blip.tags.length > 0) { %>
31
+
<span class="blip-tags">
32
+
<% blip.tags.forEach(tag => { %>
33
+
<a href="/tag/<%= tag %>" class="tag"><%= tag %></a>
34
+
<% }) %>
35
+
</span>
36
+
<% } %>
37
+
</div>
38
+
</div>
39
+
</div>
40
+
<% }) %>
41
+
<% } %>
42
+
</div>
+24
views/layout.ejs
+24
views/layout.ejs
···
1
+
<!DOCTYPE html>
2
+
<html lang="en">
3
+
<head>
4
+
<meta charset="UTF-8">
5
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+
<title>blonk / vibe radar</title>
7
+
<link rel="stylesheet" href="/css/style.css">
8
+
</head>
9
+
<body>
10
+
<header>
11
+
<div class="container">
12
+
<h1><span class="radar-icon">📡</span>blonk</h1>
13
+
<nav>
14
+
<a href="/">radar</a>
15
+
<a href="/submit">transmit</a>
16
+
</nav>
17
+
</div>
18
+
</header>
19
+
20
+
<div class="container">
21
+
<%- body %>
22
+
</div>
23
+
</body>
24
+
</html>
+31
views/submit.ejs
+31
views/submit.ejs
···
1
+
<h2 class="page-title">transmit a new blip</h2>
2
+
3
+
<form action="/submit" method="POST" class="submit-form">
4
+
<div class="form-group">
5
+
<label for="title">signal</label>
6
+
<input type="text" id="title" name="title" required placeholder="What's on the radar?">
7
+
</div>
8
+
9
+
<div class="form-group">
10
+
<label for="url">frequency (optional)</label>
11
+
<input type="url" id="url" name="url" placeholder="https://...">
12
+
<div class="form-note">link to external content</div>
13
+
</div>
14
+
15
+
<div class="form-group">
16
+
<label for="body">transmission details (optional)</label>
17
+
<textarea id="body" name="body" placeholder="Additional context or thoughts..."></textarea>
18
+
</div>
19
+
20
+
<div class="form-group">
21
+
<label for="tags">tags</label>
22
+
<input type="text" id="tags" name="tags" placeholder="space separated tags">
23
+
<div class="form-note">e.g., programming atproto bluesky</div>
24
+
</div>
25
+
26
+
<% if (locals.error) { %>
27
+
<div style="color: red; margin-bottom: 10px;"><%= error %></div>
28
+
<% } %>
29
+
30
+
<button type="submit" class="submit-button">transmit blip</button>
31
+
</form>
+42
views/tag.ejs
+42
views/tag.ejs
···
1
+
<h2 class="page-title">blips tagged: <%= tag %></h2>
2
+
3
+
<div class="blip-list">
4
+
<% if (blips.length === 0) { %>
5
+
<div class="empty-state">
6
+
<p>No blips with this tag detected.</p>
7
+
<p><a href="/">Back to all blips</a></p>
8
+
</div>
9
+
<% } else { %>
10
+
<% blips.forEach(blip => { %>
11
+
<div class="blip-item">
12
+
<div class="blip-fluffs">
13
+
<%= blip.fluffs %>
14
+
</div>
15
+
<div class="blip-content">
16
+
<% if (blip.url) { %>
17
+
<a href="<%= blip.url %>" class="blip-title" target="_blank"><%= blip.title %></a>
18
+
<% } else { %>
19
+
<span class="blip-title"><%= blip.title %></span>
20
+
<% } %>
21
+
22
+
<% if (blip.body) { %>
23
+
<div style="color: #666; font-size: 10px; margin-top: 2px;">
24
+
<%= blip.body.substring(0, 200) %><%= blip.body.length > 200 ? '...' : '' %>
25
+
</div>
26
+
<% } %>
27
+
28
+
<div class="blip-meta">
29
+
<span><%= new Date(blip.createdAt).toLocaleString() %></span>
30
+
<% if (blip.tags && blip.tags.length > 0) { %>
31
+
<span class="blip-tags">
32
+
<% blip.tags.forEach(tag => { %>
33
+
<a href="/tag/<%= tag %>" class="tag"><%= tag %></a>
34
+
<% }) %>
35
+
</span>
36
+
<% } %>
37
+
</div>
38
+
</div>
39
+
</div>
40
+
<% }) %>
41
+
<% } %>
42
+
</div>