@striae-org/striae 3.2.0 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +3 -32
  2. package/app/components/actions/case-export/data-processing.ts +49 -9
  3. package/app/components/actions/case-export/download-handlers.ts +125 -40
  4. package/app/components/actions/case-export/metadata-helpers.ts +31 -13
  5. package/app/components/form/base-form.tsx +1 -1
  6. package/app/components/sidebar/case-export/case-export.tsx +15 -15
  7. package/app/components/sidebar/cases/case-sidebar.tsx +23 -16
  8. package/app/components/sidebar/sidebar-container.tsx +1 -1
  9. package/app/entry.client.tsx +12 -12
  10. package/app/entry.server.tsx +4 -4
  11. package/app/hooks/useInactivityTimeout.ts +1 -1
  12. package/app/root.tsx +3 -3
  13. package/app/routes/auth/emailActionHandler.tsx +1 -1
  14. package/app/routes/auth/emailVerification.tsx +1 -1
  15. package/app/routes/auth/login.tsx +1 -1
  16. package/app/routes/auth/passwordReset.tsx +1 -1
  17. package/app/routes/auth/route.ts +1 -1
  18. package/app/types/exceljs-bare.d.ts +7 -0
  19. package/functions/[[path]].ts +2 -2
  20. package/package.json +34 -19
  21. package/public/vendor/exceljs.LICENSE +22 -0
  22. package/public/vendor/exceljs.bare.min.js +45 -0
  23. package/scripts/deploy-all.sh +52 -0
  24. package/scripts/deploy-config.sh +282 -1
  25. package/tsconfig.json +18 -8
  26. package/vite.config.ts +6 -22
  27. package/workers/audit-worker/package.json +8 -4
  28. package/workers/audit-worker/wrangler.jsonc.example +1 -1
  29. package/workers/data-worker/package.json +8 -4
  30. package/workers/data-worker/wrangler.jsonc.example +1 -1
  31. package/workers/image-worker/package.json +8 -4
  32. package/workers/image-worker/wrangler.jsonc.example +1 -1
  33. package/workers/keys-worker/package.json +8 -4
  34. package/workers/keys-worker/wrangler.jsonc.example +1 -1
  35. package/workers/pdf-worker/package.json +8 -4
  36. package/workers/pdf-worker/wrangler.jsonc.example +1 -1
  37. package/workers/user-worker/package.json +8 -4
  38. package/workers/user-worker/wrangler.jsonc.example +1 -1
  39. package/wrangler.toml.example +1 -1
@@ -10,6 +10,9 @@
10
10
  # 4. Worker secrets/environment variables
11
11
  # 5. Pages (frontend)
12
12
 
13
+ set -e
14
+ set -o pipefail
15
+
13
16
  # Colors for output
14
17
  RED='\033[0;31m'
15
18
  GREEN='\033[0;32m'
@@ -24,6 +27,54 @@ echo ""
24
27
 
25
28
  # Get the script directory
26
29
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
30
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
31
+ cd "$PROJECT_ROOT"
32
+
33
+ trap 'echo -e "\n${RED}❌ deploy-all.sh failed near line ${LINENO}${NC}"' ERR
34
+
35
+ require_command() {
36
+ local cmd=$1
37
+ if ! command -v "$cmd" > /dev/null 2>&1; then
38
+ echo -e "${RED}❌ Error: required command '$cmd' is not installed or not in PATH${NC}"
39
+ exit 1
40
+ fi
41
+ }
42
+
43
+ assert_file_exists() {
44
+ local file_path=$1
45
+ if [ ! -f "$file_path" ]; then
46
+ echo -e "${RED}❌ Error: required file is missing: $file_path${NC}"
47
+ exit 1
48
+ fi
49
+ }
50
+
51
+ run_config_checkpoint() {
52
+ echo -e "${YELLOW}🧪 Running configuration checkpoint validation...${NC}"
53
+ if ! bash "$SCRIPT_DIR/deploy-config.sh" --validate-only; then
54
+ echo -e "${RED}❌ Configuration checkpoint validation failed!${NC}"
55
+ exit 1
56
+ fi
57
+ echo -e "${GREEN}✅ Configuration checkpoint validation passed${NC}"
58
+ }
59
+
60
+ echo -e "${BLUE}🔍 Running deployment preflight checks...${NC}"
61
+ require_command bash
62
+ require_command node
63
+ require_command npm
64
+ require_command wrangler
65
+
66
+ assert_file_exists "$SCRIPT_DIR/deploy-config.sh"
67
+ assert_file_exists "$SCRIPT_DIR/install-workers.sh"
68
+ assert_file_exists "$SCRIPT_DIR/deploy-worker-secrets.sh"
69
+ assert_file_exists "package.json"
70
+
71
+ if [ ! -f ".env" ] && [ ! -f ".env.example" ]; then
72
+ echo -e "${RED}❌ Error: neither .env nor .env.example was found in project root${NC}"
73
+ exit 1
74
+ fi
75
+
76
+ echo -e "${GREEN}✅ Preflight checks passed${NC}"
77
+ echo ""
27
78
 
28
79
  # Step 1: Configuration Setup
29
80
  echo -e "${PURPLE}Step 1/5: Configuration Setup${NC}"
@@ -35,6 +86,7 @@ if ! bash "$SCRIPT_DIR/deploy-config.sh"; then
35
86
  exit 1
36
87
  fi
37
88
  echo -e "${GREEN}✅ Configuration setup completed successfully${NC}"
89
+ run_config_checkpoint
38
90
  echo ""
39
91
 
40
92
  # Step 2: Install Worker Dependencies
@@ -7,6 +7,7 @@
7
7
  # Run this BEFORE installing worker dependencies to avoid wrangler validation errors
8
8
 
9
9
  set -e
10
+ set -o pipefail
10
11
 
11
12
  # Colors for output
12
13
  RED='\033[0;31m'
@@ -18,8 +19,15 @@ NC='\033[0m' # No Color
18
19
  echo -e "${BLUE}⚙️ Striae Configuration Setup Script${NC}"
19
20
  echo "====================================="
20
21
 
22
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
23
+ PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
24
+ cd "$PROJECT_ROOT"
25
+
26
+ trap 'echo -e "\n${RED}❌ deploy-config.sh failed near line ${LINENO}${NC}"' ERR
27
+
21
28
  update_env=false
22
29
  show_help=false
30
+ validate_only=false
23
31
  for arg in "$@"; do
24
32
  case "$arg" in
25
33
  -h|--help)
@@ -28,14 +36,28 @@ for arg in "$@"; do
28
36
  --update-env)
29
37
  update_env=true
30
38
  ;;
39
+ --validate-only)
40
+ validate_only=true
41
+ ;;
42
+ *)
43
+ echo -e "${RED}❌ Unknown option: $arg${NC}"
44
+ echo "Use --help to see supported options."
45
+ exit 1
46
+ ;;
31
47
  esac
32
48
  done
33
49
 
50
+ if [ "$update_env" = "true" ] && [ "$validate_only" = "true" ]; then
51
+ echo -e "${RED}❌ --update-env and --validate-only cannot be used together${NC}"
52
+ exit 1
53
+ fi
54
+
34
55
  if [ "$show_help" = "true" ]; then
35
- echo "Usage: bash ./scripts/deploy-config.sh [--update-env]"
56
+ echo "Usage: bash ./scripts/deploy-config.sh [--update-env] [--validate-only]"
36
57
  echo ""
37
58
  echo "Options:"
38
59
  echo " --update-env Reset .env from .env.example and overwrite configs"
60
+ echo " --validate-only Validate current .env and generated config files without modifying them"
39
61
  echo " -h, --help Show this help message"
40
62
  exit 0
41
63
  fi
@@ -44,6 +66,19 @@ if [ "$update_env" = "true" ]; then
44
66
  echo -e "${YELLOW}⚠️ Update-env mode: overwriting configs and regenerating .env values${NC}"
45
67
  fi
46
68
 
69
+ require_command() {
70
+ local cmd=$1
71
+ if ! command -v "$cmd" > /dev/null 2>&1; then
72
+ echo -e "${RED}❌ Error: required command '$cmd' is not installed or not in PATH${NC}"
73
+ exit 1
74
+ fi
75
+ }
76
+
77
+ require_command node
78
+ require_command sed
79
+ require_command awk
80
+ require_command grep
81
+
47
82
  is_placeholder() {
48
83
  local value="$1"
49
84
  local normalized=$(echo "$value" | tr '[:upper:]' '[:lower:]')
@@ -79,6 +114,12 @@ if [ "$update_env" = "true" ]; then
79
114
  exit 1
80
115
  fi
81
116
  elif [ ! -f ".env" ]; then
117
+ if [ "$validate_only" = "true" ]; then
118
+ echo -e "${RED}❌ Error: .env file not found. --validate-only does not create files.${NC}"
119
+ echo -e "${YELLOW}Run deploy-config without --validate-only first to generate and populate .env.${NC}"
120
+ exit 1
121
+ fi
122
+
82
123
  echo -e "${YELLOW}📄 .env file not found, copying from .env.example...${NC}"
83
124
  if [ -f ".env.example" ]; then
84
125
  cp ".env.example" ".env"
@@ -521,6 +562,243 @@ validate_required_vars() {
521
562
  echo -e "${GREEN}✅ All required variables found${NC}"
522
563
  }
523
564
 
565
+ assert_file_exists() {
566
+ local file_path=$1
567
+
568
+ if [ ! -f "$file_path" ]; then
569
+ echo -e "${RED}❌ Error: required file is missing: $file_path${NC}"
570
+ exit 1
571
+ fi
572
+ }
573
+
574
+ assert_contains_literal() {
575
+ local file_path=$1
576
+ local literal=$2
577
+ local description=$3
578
+
579
+ if ! grep -Fq "$literal" "$file_path"; then
580
+ echo -e "${RED}❌ Error: ${description}${NC}"
581
+ echo -e "${YELLOW} Expected to find '$literal' in $file_path${NC}"
582
+ exit 1
583
+ fi
584
+ }
585
+
586
+ assert_no_match_in_file() {
587
+ local file_path=$1
588
+ local pattern=$2
589
+ local description=$3
590
+ local matches
591
+
592
+ matches=$(grep -En "$pattern" "$file_path" | head -n 3 || true)
593
+ if [ -n "$matches" ]; then
594
+ echo -e "${RED}❌ Error: ${description}${NC}"
595
+ echo -e "${YELLOW} First matching lines in $file_path:${NC}"
596
+ echo "$matches"
597
+ exit 1
598
+ fi
599
+ }
600
+
601
+ validate_json_file() {
602
+ local file_path=$1
603
+
604
+ if ! node -e "const fs=require('fs'); JSON.parse(fs.readFileSync(process.argv[1], 'utf8'));" "$file_path" > /dev/null 2>&1; then
605
+ echo -e "${RED}❌ Error: invalid JSON in $file_path${NC}"
606
+ exit 1
607
+ fi
608
+ }
609
+
610
+ validate_domain_var() {
611
+ local var_name=$1
612
+ local value="${!var_name}"
613
+ local normalized
614
+
615
+ value=$(strip_carriage_returns "$value")
616
+ normalized=$(normalize_domain_value "$value")
617
+
618
+ if [ -z "$value" ] || is_placeholder "$value"; then
619
+ echo -e "${RED}❌ Error: $var_name is missing or placeholder${NC}"
620
+ exit 1
621
+ fi
622
+
623
+ if [ "$value" != "$normalized" ]; then
624
+ echo -e "${RED}❌ Error: $var_name must not include protocol, trailing slash, or surrounding whitespace${NC}"
625
+ echo -e "${YELLOW} Use '$normalized' instead${NC}"
626
+ exit 1
627
+ fi
628
+
629
+ if [[ "$value" == */* ]]; then
630
+ echo -e "${RED}❌ Error: $var_name must be a bare domain (no path segments)${NC}"
631
+ exit 1
632
+ fi
633
+ }
634
+
635
+ validate_env_value_formats() {
636
+ echo -e "${YELLOW}🔍 Validating environment value formats...${NC}"
637
+
638
+ validate_domain_var "PAGES_CUSTOM_DOMAIN"
639
+ validate_domain_var "KEYS_WORKER_DOMAIN"
640
+ validate_domain_var "USER_WORKER_DOMAIN"
641
+ validate_domain_var "DATA_WORKER_DOMAIN"
642
+ validate_domain_var "AUDIT_WORKER_DOMAIN"
643
+ validate_domain_var "IMAGES_WORKER_DOMAIN"
644
+ validate_domain_var "PDF_WORKER_DOMAIN"
645
+
646
+ if ! [[ "$KV_STORE_ID" =~ ^([0-9a-fA-F]{32}|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$ ]]; then
647
+ echo -e "${RED}❌ Error: KV_STORE_ID must be a 32-character hex namespace ID (or UUID format)${NC}"
648
+ exit 1
649
+ fi
650
+
651
+ if [[ "$ACCOUNT_ID" =~ [[:space:]] ]]; then
652
+ echo -e "${RED}❌ Error: ACCOUNT_ID must not contain whitespace${NC}"
653
+ exit 1
654
+ fi
655
+
656
+ echo -e "${GREEN}✅ Environment value formats look valid${NC}"
657
+ }
658
+
659
+ validate_env_file_entries() {
660
+ local var_name
661
+ local escaped_var_name
662
+ local count
663
+
664
+ echo -e "${YELLOW}🔍 Verifying required .env entries...${NC}"
665
+ for var_name in "${required_vars[@]}"; do
666
+ escaped_var_name=$(escape_for_sed_pattern "$var_name")
667
+ count=$(grep -c "^$escaped_var_name=" .env || true)
668
+
669
+ if [ "$count" -lt 1 ]; then
670
+ echo -e "${RED}❌ Error: missing .env entry for $var_name${NC}"
671
+ exit 1
672
+ fi
673
+ done
674
+ echo -e "${GREEN}✅ Required .env entries found${NC}"
675
+ }
676
+
677
+ validate_generated_configs() {
678
+ echo -e "${YELLOW}🔍 Running generated configuration checkpoint validations...${NC}"
679
+
680
+ local required_files=(
681
+ "wrangler.toml"
682
+ "app/config/config.json"
683
+ "app/config/firebase.ts"
684
+ "app/config/admin-service.json"
685
+ "workers/audit-worker/wrangler.jsonc"
686
+ "workers/data-worker/wrangler.jsonc"
687
+ "workers/image-worker/wrangler.jsonc"
688
+ "workers/keys-worker/wrangler.jsonc"
689
+ "workers/pdf-worker/wrangler.jsonc"
690
+ "workers/user-worker/wrangler.jsonc"
691
+ "workers/audit-worker/src/audit-worker.ts"
692
+ "workers/data-worker/src/data-worker.ts"
693
+ "workers/image-worker/src/image-worker.ts"
694
+ "workers/keys-worker/src/keys.ts"
695
+ "workers/pdf-worker/src/pdf-worker.ts"
696
+ "workers/user-worker/src/user-worker.ts"
697
+ )
698
+
699
+ local file_path
700
+ for file_path in "${required_files[@]}"; do
701
+ assert_file_exists "$file_path"
702
+ done
703
+
704
+ validate_json_file "app/config/config.json"
705
+ validate_json_file "app/config/admin-service.json"
706
+
707
+ assert_contains_literal "wrangler.toml" "\"$PAGES_PROJECT_NAME\"" "PAGES_PROJECT_NAME was not applied to wrangler.toml"
708
+
709
+ assert_contains_literal "workers/keys-worker/wrangler.jsonc" "$KEYS_WORKER_NAME" "KEYS_WORKER_NAME was not applied"
710
+ assert_contains_literal "workers/user-worker/wrangler.jsonc" "$USER_WORKER_NAME" "USER_WORKER_NAME was not applied"
711
+ assert_contains_literal "workers/data-worker/wrangler.jsonc" "$DATA_WORKER_NAME" "DATA_WORKER_NAME was not applied"
712
+ assert_contains_literal "workers/audit-worker/wrangler.jsonc" "$AUDIT_WORKER_NAME" "AUDIT_WORKER_NAME was not applied"
713
+ assert_contains_literal "workers/image-worker/wrangler.jsonc" "$IMAGES_WORKER_NAME" "IMAGES_WORKER_NAME was not applied"
714
+ assert_contains_literal "workers/pdf-worker/wrangler.jsonc" "$PDF_WORKER_NAME" "PDF_WORKER_NAME was not applied"
715
+
716
+ assert_contains_literal "workers/keys-worker/wrangler.jsonc" "$ACCOUNT_ID" "ACCOUNT_ID missing in keys worker config"
717
+ assert_contains_literal "workers/user-worker/wrangler.jsonc" "$ACCOUNT_ID" "ACCOUNT_ID missing in user worker config"
718
+ assert_contains_literal "workers/data-worker/wrangler.jsonc" "$ACCOUNT_ID" "ACCOUNT_ID missing in data worker config"
719
+ assert_contains_literal "workers/audit-worker/wrangler.jsonc" "$ACCOUNT_ID" "ACCOUNT_ID missing in audit worker config"
720
+ assert_contains_literal "workers/image-worker/wrangler.jsonc" "$ACCOUNT_ID" "ACCOUNT_ID missing in image worker config"
721
+ assert_contains_literal "workers/pdf-worker/wrangler.jsonc" "$ACCOUNT_ID" "ACCOUNT_ID missing in pdf worker config"
722
+
723
+ assert_contains_literal "workers/keys-worker/wrangler.jsonc" "$KEYS_WORKER_DOMAIN" "KEYS_WORKER_DOMAIN missing in keys worker config"
724
+ assert_contains_literal "workers/user-worker/wrangler.jsonc" "$USER_WORKER_DOMAIN" "USER_WORKER_DOMAIN missing in user worker config"
725
+ assert_contains_literal "workers/data-worker/wrangler.jsonc" "$DATA_WORKER_DOMAIN" "DATA_WORKER_DOMAIN missing in data worker config"
726
+ assert_contains_literal "workers/audit-worker/wrangler.jsonc" "$AUDIT_WORKER_DOMAIN" "AUDIT_WORKER_DOMAIN missing in audit worker config"
727
+ assert_contains_literal "workers/image-worker/wrangler.jsonc" "$IMAGES_WORKER_DOMAIN" "IMAGES_WORKER_DOMAIN missing in image worker config"
728
+ assert_contains_literal "workers/pdf-worker/wrangler.jsonc" "$PDF_WORKER_DOMAIN" "PDF_WORKER_DOMAIN missing in pdf worker config"
729
+
730
+ assert_contains_literal "workers/data-worker/wrangler.jsonc" "$DATA_BUCKET_NAME" "DATA_BUCKET_NAME missing in data worker config"
731
+ assert_contains_literal "workers/audit-worker/wrangler.jsonc" "$AUDIT_BUCKET_NAME" "AUDIT_BUCKET_NAME missing in audit worker config"
732
+ assert_contains_literal "workers/user-worker/wrangler.jsonc" "$KV_STORE_ID" "KV_STORE_ID missing in user worker config"
733
+
734
+ assert_contains_literal "app/config/config.json" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in app/config/config.json"
735
+ assert_contains_literal "app/config/config.json" "https://$DATA_WORKER_DOMAIN" "DATA_WORKER_DOMAIN missing in app/config/config.json"
736
+ assert_contains_literal "app/config/config.json" "https://$AUDIT_WORKER_DOMAIN" "AUDIT_WORKER_DOMAIN missing in app/config/config.json"
737
+ assert_contains_literal "app/config/config.json" "https://$KEYS_WORKER_DOMAIN" "KEYS_WORKER_DOMAIN missing in app/config/config.json"
738
+ assert_contains_literal "app/config/config.json" "https://$IMAGES_WORKER_DOMAIN" "IMAGES_WORKER_DOMAIN missing in app/config/config.json"
739
+ assert_contains_literal "app/config/config.json" "https://$USER_WORKER_DOMAIN" "USER_WORKER_DOMAIN missing in app/config/config.json"
740
+ assert_contains_literal "app/config/config.json" "https://$PDF_WORKER_DOMAIN" "PDF_WORKER_DOMAIN missing in app/config/config.json"
741
+ assert_contains_literal "app/config/config.json" "$KEYS_AUTH" "KEYS_AUTH missing in app/config/config.json"
742
+
743
+ assert_contains_literal "app/config/firebase.ts" "$API_KEY" "API_KEY missing in app/config/firebase.ts"
744
+ assert_contains_literal "app/config/firebase.ts" "$AUTH_DOMAIN" "AUTH_DOMAIN missing in app/config/firebase.ts"
745
+ assert_contains_literal "app/config/firebase.ts" "$PROJECT_ID" "PROJECT_ID missing in app/config/firebase.ts"
746
+ assert_contains_literal "app/config/firebase.ts" "$STORAGE_BUCKET" "STORAGE_BUCKET missing in app/config/firebase.ts"
747
+ assert_contains_literal "app/config/firebase.ts" "$MESSAGING_SENDER_ID" "MESSAGING_SENDER_ID missing in app/config/firebase.ts"
748
+ assert_contains_literal "app/config/firebase.ts" "$APP_ID" "APP_ID missing in app/config/firebase.ts"
749
+ assert_contains_literal "app/config/firebase.ts" "$MEASUREMENT_ID" "MEASUREMENT_ID missing in app/config/firebase.ts"
750
+
751
+ assert_contains_literal "workers/audit-worker/src/audit-worker.ts" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in audit-worker source"
752
+ assert_contains_literal "workers/data-worker/src/data-worker.ts" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in data-worker source"
753
+ assert_contains_literal "workers/image-worker/src/image-worker.ts" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in image-worker source"
754
+ assert_contains_literal "workers/keys-worker/src/keys.ts" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in keys-worker source"
755
+ assert_contains_literal "workers/pdf-worker/src/pdf-worker.ts" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in pdf-worker source"
756
+ assert_contains_literal "workers/user-worker/src/user-worker.ts" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in user-worker source"
757
+ assert_contains_literal "workers/user-worker/src/user-worker.ts" "https://$DATA_WORKER_DOMAIN" "DATA_WORKER_DOMAIN missing in user-worker source"
758
+ assert_contains_literal "workers/user-worker/src/user-worker.ts" "https://$IMAGES_WORKER_DOMAIN" "IMAGES_WORKER_DOMAIN missing in user-worker source"
759
+
760
+ local placeholder_pattern
761
+ placeholder_pattern="(\"(ACCOUNT_ID|PAGES_PROJECT_NAME|PAGES_CUSTOM_DOMAIN|KEYS_WORKER_NAME|USER_WORKER_NAME|DATA_WORKER_NAME|AUDIT_WORKER_NAME|IMAGES_WORKER_NAME|PDF_WORKER_NAME|KEYS_WORKER_DOMAIN|USER_WORKER_DOMAIN|DATA_WORKER_DOMAIN|AUDIT_WORKER_DOMAIN|IMAGES_WORKER_DOMAIN|PDF_WORKER_DOMAIN|DATA_BUCKET_NAME|AUDIT_BUCKET_NAME|KV_STORE_ID|DATA_WORKER_CUSTOM_DOMAIN|AUDIT_WORKER_CUSTOM_DOMAIN|KEYS_WORKER_CUSTOM_DOMAIN|IMAGE_WORKER_CUSTOM_DOMAIN|USER_WORKER_CUSTOM_DOMAIN|PDF_WORKER_CUSTOM_DOMAIN|YOUR_KEYS_AUTH_TOKEN|MANIFEST_SIGNING_KEY_ID|MANIFEST_SIGNING_PUBLIC_KEY|YOUR_FIREBASE_API_KEY|YOUR_FIREBASE_AUTH_DOMAIN|YOUR_FIREBASE_PROJECT_ID|YOUR_FIREBASE_STORAGE_BUCKET|YOUR_FIREBASE_MESSAGING_SENDER_ID|YOUR_FIREBASE_APP_ID|YOUR_FIREBASE_MEASUREMENT_ID)\"|'(PAGES_CUSTOM_DOMAIN|DATA_WORKER_DOMAIN|IMAGES_WORKER_DOMAIN)')"
762
+
763
+ local files_to_scan=(
764
+ "wrangler.toml"
765
+ "workers/audit-worker/wrangler.jsonc"
766
+ "workers/data-worker/wrangler.jsonc"
767
+ "workers/image-worker/wrangler.jsonc"
768
+ "workers/keys-worker/wrangler.jsonc"
769
+ "workers/pdf-worker/wrangler.jsonc"
770
+ "workers/user-worker/wrangler.jsonc"
771
+ "workers/audit-worker/src/audit-worker.ts"
772
+ "workers/data-worker/src/data-worker.ts"
773
+ "workers/image-worker/src/image-worker.ts"
774
+ "workers/keys-worker/src/keys.ts"
775
+ "workers/pdf-worker/src/pdf-worker.ts"
776
+ "workers/user-worker/src/user-worker.ts"
777
+ "app/config/config.json"
778
+ "app/config/firebase.ts"
779
+ )
780
+
781
+ for file_path in "${files_to_scan[@]}"; do
782
+ assert_no_match_in_file "$file_path" "$placeholder_pattern" "Unresolved placeholder token found after config update"
783
+ done
784
+
785
+ echo -e "${GREEN}✅ Generated configuration checkpoint validation passed${NC}"
786
+ }
787
+
788
+ run_validation_checkpoint() {
789
+ validate_required_vars
790
+ validate_env_value_formats
791
+ validate_env_file_entries
792
+ validate_generated_configs
793
+ }
794
+
795
+ if [ "$validate_only" = "true" ]; then
796
+ echo -e "\n${BLUE}🧪 Validate-only mode enabled${NC}"
797
+ run_validation_checkpoint
798
+ echo -e "\n${GREEN}🎉 Configuration validation completed successfully!${NC}"
799
+ exit 0
800
+ fi
801
+
524
802
  # Function to copy example configuration files
525
803
  copy_example_configs() {
526
804
  echo -e "\n${BLUE}📋 Copying example configuration files...${NC}"
@@ -1148,6 +1426,9 @@ update_wrangler_configs() {
1148
1426
  # Update wrangler configurations
1149
1427
  update_wrangler_configs
1150
1428
 
1429
+ # Validate generated files and values after replacements
1430
+ run_validation_checkpoint
1431
+
1151
1432
  echo -e "\n${GREEN}🎉 Configuration setup completed!${NC}"
1152
1433
  echo -e "${BLUE}📝 Next Steps:${NC}"
1153
1434
  echo " 1. Install worker dependencies"
package/tsconfig.json CHANGED
@@ -5,14 +5,19 @@
5
5
  "**/.server/**/*.ts",
6
6
  "**/.server/**/*.tsx",
7
7
  "**/.client/**/*.ts",
8
- "**/.client/**/*.tsx"
8
+ "**/.client/**/*.tsx",
9
+ ".react-router/types/**/*"
9
10
  ],
10
11
  "compilerOptions": {
11
- "lib": ["DOM", "DOM.Iterable", "ES2022"],
12
+ "lib": [
13
+ "DOM",
14
+ "DOM.Iterable",
15
+ "ES2022"
16
+ ],
12
17
  "types": [
13
- "@remix-run/cloudflare",
14
- "vite/client"
15
- ],
18
+ "@react-router/cloudflare",
19
+ "vite/client"
20
+ ],
16
21
  "isolatedModules": true,
17
22
  "esModuleInterop": true,
18
23
  "jsx": "react-jsx",
@@ -25,9 +30,14 @@
25
30
  "skipLibCheck": true,
26
31
  "forceConsistentCasingInFileNames": true,
27
32
  "paths": {
28
- "~/*": ["./app/*"]
33
+ "~/*": [
34
+ "./app/*"
35
+ ]
29
36
  },
30
-
37
+ "rootDirs": [
38
+ ".",
39
+ "./.react-router/types"
40
+ ],
31
41
  "noEmit": true
32
42
  }
33
- }
43
+ }
package/vite.config.ts CHANGED
@@ -1,35 +1,19 @@
1
- import {
2
- vitePlugin as remix,
3
- cloudflareDevProxyVitePlugin as remixCloudflareDevProxy,
4
- } from "@remix-run/dev";
1
+ import { reactRouter } from "@react-router/dev/vite";
2
+ import { cloudflareDevProxy } from "@react-router/dev/vite/cloudflare";
5
3
  import { defineConfig } from "vite";
6
4
  import tsconfigPaths from "vite-tsconfig-paths";
7
5
 
8
- declare module "@remix-run/cloudflare" {
9
- interface Future {
10
- v3_singleFetch: true;
11
- }
12
- }
13
-
14
6
  export default defineConfig({
15
7
  server: {
16
8
  port: 7777,
17
9
  },
18
- build: {
10
+ build: {
19
11
  chunkSizeWarningLimit: 500,
20
12
  minify: true,
21
13
  },
22
14
  plugins: [
23
- remixCloudflareDevProxy(),
24
- remix({
25
- future: {
26
- v3_fetcherPersist: true,
27
- v3_relativeSplatPath: true,
28
- v3_throwAbortReason: true,
29
- v3_singleFetch: true,
30
- v3_lazyRouteDiscovery: true,
31
- },
32
- }),
33
- tsconfigPaths()
15
+ cloudflareDevProxy(),
16
+ reactRouter(),
17
+ tsconfigPaths(),
34
18
  ],
35
19
  });
@@ -9,9 +9,13 @@
9
9
  "test": "vitest"
10
10
  },
11
11
  "devDependencies": {
12
- "@cloudflare/puppeteer": "^1.0.4",
13
- "@cloudflare/vitest-pool-workers": "^0.12.9",
14
- "vitest": "~3.2.0",
15
- "wrangler": "^4.69.0"
12
+ "@cloudflare/puppeteer": "^1.0.6",
13
+ "@cloudflare/vitest-pool-workers": "^0.13.0",
14
+ "vitest": "~4.1.0",
15
+ "wrangler": "^4.73.0"
16
+ },
17
+ "overrides": {
18
+ "undici": "7.24.1",
19
+ "yauzl": "3.2.1"
16
20
  }
17
21
  }
@@ -2,7 +2,7 @@
2
2
  "name": "AUDIT_WORKER_NAME",
3
3
  "account_id": "ACCOUNT_ID",
4
4
  "main": "src/audit-worker.ts",
5
- "compatibility_date": "2026-03-13",
5
+ "compatibility_date": "2026-03-14",
6
6
  "compatibility_flags": [
7
7
  "nodejs_compat"
8
8
  ],
@@ -9,9 +9,13 @@
9
9
  "test": "vitest"
10
10
  },
11
11
  "devDependencies": {
12
- "@cloudflare/puppeteer": "^1.0.4",
13
- "@cloudflare/vitest-pool-workers": "^0.12.9",
14
- "vitest": "~3.2.0",
15
- "wrangler": "^4.69.0"
12
+ "@cloudflare/puppeteer": "^1.0.6",
13
+ "@cloudflare/vitest-pool-workers": "^0.13.0",
14
+ "vitest": "~4.1.0",
15
+ "wrangler": "^4.73.0"
16
+ },
17
+ "overrides": {
18
+ "undici": "7.24.1",
19
+ "yauzl": "3.2.1"
16
20
  }
17
21
  }
@@ -3,7 +3,7 @@
3
3
  "name": "DATA_WORKER_NAME",
4
4
  "account_id": "ACCOUNT_ID",
5
5
  "main": "src/data-worker.ts",
6
- "compatibility_date": "2026-03-13",
6
+ "compatibility_date": "2026-03-14",
7
7
  "compatibility_flags": [
8
8
  "nodejs_compat"
9
9
  ],
@@ -9,9 +9,13 @@
9
9
  "test": "vitest"
10
10
  },
11
11
  "devDependencies": {
12
- "@cloudflare/puppeteer": "^1.0.4",
13
- "@cloudflare/vitest-pool-workers": "^0.12.9",
14
- "vitest": "~3.2.0",
15
- "wrangler": "^4.69.0"
12
+ "@cloudflare/puppeteer": "^1.0.6",
13
+ "@cloudflare/vitest-pool-workers": "^0.13.0",
14
+ "vitest": "~4.1.0",
15
+ "wrangler": "^4.73.0"
16
+ },
17
+ "overrides": {
18
+ "undici": "7.24.1",
19
+ "yauzl": "3.2.1"
16
20
  }
17
21
  }
@@ -2,7 +2,7 @@
2
2
  "name": "IMAGES_WORKER_NAME",
3
3
  "account_id": "ACCOUNT_ID",
4
4
  "main": "src/image-worker.ts",
5
- "compatibility_date": "2026-03-13",
5
+ "compatibility_date": "2026-03-14",
6
6
  "compatibility_flags": [
7
7
  "nodejs_compat"
8
8
  ],
@@ -9,9 +9,13 @@
9
9
  "test": "vitest"
10
10
  },
11
11
  "devDependencies": {
12
- "@cloudflare/puppeteer": "^1.0.4",
13
- "@cloudflare/vitest-pool-workers": "^0.12.9",
14
- "vitest": "~3.2.0",
15
- "wrangler": "^4.69.0"
12
+ "@cloudflare/puppeteer": "^1.0.6",
13
+ "@cloudflare/vitest-pool-workers": "^0.13.0",
14
+ "vitest": "~4.1.0",
15
+ "wrangler": "^4.73.0"
16
+ },
17
+ "overrides": {
18
+ "undici": "7.24.1",
19
+ "yauzl": "3.2.1"
16
20
  }
17
21
  }
@@ -2,7 +2,7 @@
2
2
  "name": "KEYS_WORKER_NAME",
3
3
  "account_id": "ACCOUNT_ID",
4
4
  "main": "src/keys.ts",
5
- "compatibility_date": "2026-03-13",
5
+ "compatibility_date": "2026-03-14",
6
6
  "compatibility_flags": [
7
7
  "nodejs_compat"
8
8
  ],
@@ -10,9 +10,13 @@
10
10
  "test": "vitest"
11
11
  },
12
12
  "devDependencies": {
13
- "@cloudflare/puppeteer": "^1.0.4",
14
- "@cloudflare/vitest-pool-workers": "^0.12.9",
15
- "vitest": "~3.2.0",
16
- "wrangler": "^4.69.0"
13
+ "@cloudflare/puppeteer": "^1.0.6",
14
+ "@cloudflare/vitest-pool-workers": "^0.13.0",
15
+ "vitest": "~4.1.0",
16
+ "wrangler": "^4.73.0"
17
+ },
18
+ "overrides": {
19
+ "undici": "7.24.1",
20
+ "yauzl": "3.2.1"
17
21
  }
18
22
  }
@@ -2,7 +2,7 @@
2
2
  "name": "PDF_WORKER_NAME",
3
3
  "account_id": "ACCOUNT_ID",
4
4
  "main": "src/pdf-worker.ts",
5
- "compatibility_date": "2026-03-13",
5
+ "compatibility_date": "2026-03-14",
6
6
  "compatibility_flags": [
7
7
  "nodejs_compat"
8
8
  ],
@@ -9,9 +9,13 @@
9
9
  "test": "vitest"
10
10
  },
11
11
  "devDependencies": {
12
- "@cloudflare/puppeteer": "^1.0.4",
13
- "@cloudflare/vitest-pool-workers": "^0.12.9",
14
- "vitest": "~3.2.0",
15
- "wrangler": "^4.69.0"
12
+ "@cloudflare/puppeteer": "^1.0.6",
13
+ "@cloudflare/vitest-pool-workers": "^0.13.0",
14
+ "vitest": "~4.1.0",
15
+ "wrangler": "^4.73.0"
16
+ },
17
+ "overrides": {
18
+ "undici": "7.24.1",
19
+ "yauzl": "3.2.1"
16
20
  }
17
21
  }