@striae-org/striae 6.1.7 → 7.0.0
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/.env.example +0 -26
- package/README.md +1 -2
- package/app/components/actions/image-manage.ts +17 -67
- package/functions/api/audit/[[path]].ts +9 -24
- package/functions/api/data/[[path]].ts +9 -24
- package/functions/api/image/[[path]].ts +14 -30
- package/functions/api/pdf/[[path]].ts +9 -24
- package/functions/api/user/[[path]].ts +20 -36
- package/package.json +143 -137
- package/scripts/deploy-all.sh +29 -10
- package/scripts/deploy-config/modules/env-utils.sh +0 -68
- package/scripts/deploy-config/modules/prompt.sh +4 -110
- package/scripts/deploy-config/modules/scaffolding.sh +5 -68
- package/scripts/deploy-config/modules/validation.sh +1 -30
- package/scripts/deploy-pages-secrets.sh +0 -9
- package/scripts/deploy-worker-secrets.sh +2 -8
- package/tsconfig.json +1 -1
- package/workers/audit-worker/package.json +2 -2
- package/workers/audit-worker/src/{audit-worker.example.ts → audit-worker.ts} +1 -17
- package/workers/audit-worker/src/config.ts +1 -6
- package/workers/audit-worker/src/types.ts +0 -1
- package/workers/audit-worker/wrangler.jsonc.example +2 -6
- package/workers/data-worker/package.json +3 -2
- package/workers/data-worker/src/config.ts +1 -6
- package/workers/data-worker/src/{data-worker.example.ts → data-worker.ts} +2 -18
- package/workers/data-worker/src/types.ts +0 -1
- package/workers/data-worker/wrangler.jsonc.example +2 -4
- package/workers/image-worker/package.json +2 -2
- package/workers/image-worker/src/handlers/delete-image.ts +0 -5
- package/workers/image-worker/src/handlers/mint-signed-url.ts +0 -5
- package/workers/image-worker/src/handlers/serve-image.ts +2 -5
- package/workers/image-worker/src/handlers/upload-image.ts +0 -5
- package/workers/image-worker/src/{image-worker.example.ts → image-worker.ts} +2 -15
- package/workers/image-worker/src/router.ts +2 -3
- package/workers/image-worker/src/security/signed-url.ts +2 -2
- package/workers/image-worker/src/types.ts +0 -1
- package/workers/image-worker/wrangler.jsonc.example +2 -1
- package/workers/pdf-worker/package.json +2 -2
- package/workers/pdf-worker/src/{pdf-worker.example.ts → pdf-worker.ts} +1 -23
- package/workers/pdf-worker/wrangler.jsonc.example +2 -1
- package/workers/user-worker/package.json +2 -2
- package/workers/user-worker/src/auth.ts +0 -7
- package/workers/user-worker/src/handlers/user-routes.ts +25 -39
- package/workers/user-worker/src/types.ts +0 -2
- package/workers/user-worker/src/{user-worker.example.ts → user-worker.ts} +15 -30
- package/workers/user-worker/wrangler.jsonc.example +2 -1
- package/wrangler.toml.example +22 -2
- package/worker-configuration.d.ts +0 -7509
- package/workers/image-worker/src/auth.ts +0 -7
package/package.json
CHANGED
|
@@ -1,138 +1,144 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@striae-org/striae",
|
|
3
|
-
"version": "
|
|
4
|
-
"private": false,
|
|
5
|
-
"description": "Striae is a specialized, cloud-native platform designed to streamline forensic firearms identification by providing an intuitive environment for digital comparison image annotation, authenticated confirmations, and automated report generation.",
|
|
6
|
-
"license": "Apache-2.0",
|
|
7
|
-
"homepage": "https://github.com/striae-org/striae/wiki",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "https://github.com/striae-org/striae.git"
|
|
11
|
-
},
|
|
12
|
-
"funding": {
|
|
13
|
-
"type": "github",
|
|
14
|
-
"url": "https://github.com/sponsors/striae-org"
|
|
15
|
-
},
|
|
16
|
-
"bugs": {
|
|
17
|
-
"url": "https://github.com/striae-org/striae/issues"
|
|
18
|
-
},
|
|
19
|
-
"keywords": [
|
|
20
|
-
"forensics",
|
|
21
|
-
"firearms",
|
|
22
|
-
"annotation",
|
|
23
|
-
"react",
|
|
24
|
-
"cloudflare-workers",
|
|
25
|
-
"authenticated",
|
|
26
|
-
"confirmations",
|
|
27
|
-
"chain-of-custody",
|
|
28
|
-
"audit-trail"
|
|
29
|
-
],
|
|
30
|
-
"publishConfig": {
|
|
31
|
-
"access": "public"
|
|
32
|
-
},
|
|
33
|
-
"files": [
|
|
34
|
-
"app/",
|
|
35
|
-
"!app/config",
|
|
36
|
-
"react-router.config.ts",
|
|
37
|
-
"load-context.ts",
|
|
38
|
-
"scripts/",
|
|
39
|
-
"functions/",
|
|
40
|
-
"public/",
|
|
41
|
-
"workers/",
|
|
42
|
-
"shared/",
|
|
43
|
-
"!workers/*/.wrangler",
|
|
44
|
-
"!workers/*/package-lock.json",
|
|
45
|
-
"!workers/*/worker-configuration.d.ts",
|
|
46
|
-
"!workers/*/wrangler.jsonc",
|
|
47
|
-
"!workers
|
|
48
|
-
"
|
|
49
|
-
"workers/pdf-worker/src/
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
".
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"build": "
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"publish:
|
|
71
|
-
"publish:
|
|
72
|
-
"publish:
|
|
73
|
-
"publish:
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"typegen": "wrangler types",
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"update-
|
|
88
|
-
"
|
|
89
|
-
"deploy-
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"deploy-
|
|
93
|
-
"deploy-
|
|
94
|
-
"deploy-
|
|
95
|
-
"deploy-
|
|
96
|
-
"deploy-
|
|
97
|
-
"deploy-
|
|
98
|
-
"deploy-workers:
|
|
99
|
-
"deploy-workers:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
"
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
"
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"@
|
|
116
|
-
"@
|
|
117
|
-
"@
|
|
118
|
-
"@
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
"eslint-plugin
|
|
122
|
-
"eslint
|
|
123
|
-
"
|
|
124
|
-
"eslint
|
|
125
|
-
"
|
|
126
|
-
"
|
|
127
|
-
"
|
|
128
|
-
"
|
|
129
|
-
"
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
"
|
|
136
|
-
},
|
|
137
|
-
"
|
|
1
|
+
{
|
|
2
|
+
"name": "@striae-org/striae",
|
|
3
|
+
"version": "7.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Striae is a specialized, cloud-native platform designed to streamline forensic firearms identification by providing an intuitive environment for digital comparison image annotation, authenticated confirmations, and automated report generation.",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"homepage": "https://github.com/striae-org/striae/wiki",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/striae-org/striae.git"
|
|
11
|
+
},
|
|
12
|
+
"funding": {
|
|
13
|
+
"type": "github",
|
|
14
|
+
"url": "https://github.com/sponsors/striae-org"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/striae-org/striae/issues"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"forensics",
|
|
21
|
+
"firearms",
|
|
22
|
+
"annotation",
|
|
23
|
+
"react",
|
|
24
|
+
"cloudflare-workers",
|
|
25
|
+
"authenticated",
|
|
26
|
+
"confirmations",
|
|
27
|
+
"chain-of-custody",
|
|
28
|
+
"audit-trail"
|
|
29
|
+
],
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"app/",
|
|
35
|
+
"!app/config",
|
|
36
|
+
"react-router.config.ts",
|
|
37
|
+
"load-context.ts",
|
|
38
|
+
"scripts/",
|
|
39
|
+
"functions/",
|
|
40
|
+
"public/",
|
|
41
|
+
"workers/",
|
|
42
|
+
"shared/",
|
|
43
|
+
"!workers/*/.wrangler",
|
|
44
|
+
"!workers/*/package-lock.json",
|
|
45
|
+
"!workers/*/worker-configuration.d.ts",
|
|
46
|
+
"!workers/*/wrangler.jsonc",
|
|
47
|
+
"!workers/pdf-worker/src/assets/**/*",
|
|
48
|
+
"workers/pdf-worker/src/assets/generated-assets.example.ts",
|
|
49
|
+
"!workers/pdf-worker/src/formats/**/*",
|
|
50
|
+
"workers/pdf-worker/src/formats/format-striae.ts",
|
|
51
|
+
".env.example",
|
|
52
|
+
"firebase.json",
|
|
53
|
+
"tsconfig.json",
|
|
54
|
+
"vite.config.ts",
|
|
55
|
+
"wrangler.toml.example",
|
|
56
|
+
"LICENSE"
|
|
57
|
+
],
|
|
58
|
+
"sideEffects": false,
|
|
59
|
+
"type": "module",
|
|
60
|
+
"scripts": {
|
|
61
|
+
"deploy:all": "bash ./scripts/deploy-all.sh",
|
|
62
|
+
"emulators": "firebase emulators:start --only auth",
|
|
63
|
+
"dev": "node ./scripts/dev.cjs && react-router dev",
|
|
64
|
+
"build": "node ./scripts/dev.cjs && react-router build",
|
|
65
|
+
"clean": "rm -rf build node_modules/.cache .cache",
|
|
66
|
+
"clean:build": "npm run clean && npm run build",
|
|
67
|
+
"deploy": "npm run build && wrangler pages deploy",
|
|
68
|
+
"publish:npm": "npm publish --access public --registry=https://registry.npmjs.org --@striae-org:registry=https://registry.npmjs.org",
|
|
69
|
+
"publish:npm:dry-run": "npm publish --dry-run --access public --registry=https://registry.npmjs.org --@striae-org:registry=https://registry.npmjs.org",
|
|
70
|
+
"publish:github": "npm publish --registry=https://npm.pkg.github.com --@striae-org:registry=https://npm.pkg.github.com",
|
|
71
|
+
"publish:github:dry-run": "npm publish --dry-run --registry=https://npm.pkg.github.com --@striae-org:registry=https://npm.pkg.github.com",
|
|
72
|
+
"publish:all": "npm run publish:npm && npm run publish:github",
|
|
73
|
+
"publish:all:dry-run": "npm run publish:npm:dry-run && npm run publish:github:dry-run",
|
|
74
|
+
"lint": "node ./scripts/run-eslint.cjs",
|
|
75
|
+
"start": "node ./scripts/dev.cjs && wrangler pages dev",
|
|
76
|
+
"typecheck": "react-router typegen && tsc",
|
|
77
|
+
"typegen": "wrangler types",
|
|
78
|
+
"preview": "npm run build && wrangler pages dev",
|
|
79
|
+
"cf-typegen": "wrangler types",
|
|
80
|
+
"test": "npm run test:app && npm run test:workers:data",
|
|
81
|
+
"test:app": "vitest run --config tests/app/vitest.config.ts",
|
|
82
|
+
"test:workers:data": "vitest run --config tests/workers/data/vitest.config.mjs",
|
|
83
|
+
"test:watch": "vitest --config tests/app/vitest.config.ts",
|
|
84
|
+
"test:coverage": "vitest run --config tests/app/vitest.config.ts --coverage",
|
|
85
|
+
"enable-totp-mfa": "node ./scripts/enable-totp-mfa.mjs",
|
|
86
|
+
"unenroll-totp-mfa": "node ./scripts/unenroll-totp-mfa.mjs",
|
|
87
|
+
"update-versions": "node ./scripts/update-markdown-versions.cjs",
|
|
88
|
+
"update-compatibility-dates": "node ./scripts/update-compatibility-dates.cjs",
|
|
89
|
+
"deploy-config": "bash ./scripts/deploy-config.sh",
|
|
90
|
+
"update-env": "bash ./scripts/deploy-config.sh --update-env",
|
|
91
|
+
"install-workers": "bash ./scripts/install-workers.sh",
|
|
92
|
+
"deploy-workers": "npm run deploy-workers:audit && npm run deploy-workers:data && npm run deploy-workers:image && npm run deploy-workers:pdf && npm run deploy-workers:user",
|
|
93
|
+
"deploy-workers:secrets": "bash ./scripts/deploy-worker-secrets.sh",
|
|
94
|
+
"deploy-pages:secrets": "bash ./scripts/deploy-pages-secrets.sh",
|
|
95
|
+
"deploy-pages": "bash ./scripts/deploy-pages.sh",
|
|
96
|
+
"deploy-primershear": "bash ./scripts/deploy-primershear-emails.sh",
|
|
97
|
+
"deploy-members": "bash ./scripts/deploy-members-emails.sh",
|
|
98
|
+
"deploy-workers:audit": "cd workers/audit-worker && npm run deploy",
|
|
99
|
+
"deploy-workers:data": "cd workers/data-worker && npm run deploy",
|
|
100
|
+
"deploy-workers:image": "cd workers/image-worker && npm run deploy",
|
|
101
|
+
"deploy-workers:pdf": "cd workers/pdf-worker && npm run deploy",
|
|
102
|
+
"deploy-workers:user": "cd workers/user-worker && npm run deploy"
|
|
103
|
+
},
|
|
104
|
+
"dependencies": {
|
|
105
|
+
"@react-router/cloudflare": "^7.14.2",
|
|
106
|
+
"firebase": "^12.12.1",
|
|
107
|
+
"isbot": "^5.1.39",
|
|
108
|
+
"jszip": "^3.10.1",
|
|
109
|
+
"qrcode": "^1.5.4",
|
|
110
|
+
"react": "^19.2.5",
|
|
111
|
+
"react-dom": "^19.2.5",
|
|
112
|
+
"react-router": "^7.14.2"
|
|
113
|
+
},
|
|
114
|
+
"devDependencies": {
|
|
115
|
+
"@cloudflare/vitest-pool-workers": "^0.14.9",
|
|
116
|
+
"@react-router/dev": "^7.14.2",
|
|
117
|
+
"@react-router/fs-routes": "^7.14.2",
|
|
118
|
+
"@types/qrcode": "^1.5.6",
|
|
119
|
+
"@types/react": "^19.2.14",
|
|
120
|
+
"@types/react-dom": "^19.2.3",
|
|
121
|
+
"@typescript-eslint/eslint-plugin": "^8.59.0",
|
|
122
|
+
"@typescript-eslint/parser": "^8.59.0",
|
|
123
|
+
"@vitest/coverage-v8": "^4.1.5",
|
|
124
|
+
"eslint": "^9.39.4",
|
|
125
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
126
|
+
"eslint-plugin-import": "^2.32.0",
|
|
127
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
128
|
+
"eslint-plugin-react": "^7.37.5",
|
|
129
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
130
|
+
"firebase-admin": "^13.8.0",
|
|
131
|
+
"modern-normalize": "^3.0.1",
|
|
132
|
+
"typescript": "^6.0.3",
|
|
133
|
+
"vite": "^8.0.9",
|
|
134
|
+
"vitest": "^4.1.5",
|
|
135
|
+
"wrangler": "^4.84.1"
|
|
136
|
+
},
|
|
137
|
+
"overrides": {
|
|
138
|
+
"@tootallnate/once": "3.0.1"
|
|
139
|
+
},
|
|
140
|
+
"engines": {
|
|
141
|
+
"node": ">=20.19.0"
|
|
142
|
+
},
|
|
143
|
+
"packageManager": "npm@11.12.0"
|
|
138
144
|
}
|
package/scripts/deploy-all.sh
CHANGED
|
@@ -79,7 +79,7 @@ echo -e "${GREEN}✅ Preflight checks passed${NC}"
|
|
|
79
79
|
echo ""
|
|
80
80
|
|
|
81
81
|
# Step 1: Configuration Setup
|
|
82
|
-
echo -e "${PURPLE}Step 1/
|
|
82
|
+
echo -e "${PURPLE}Step 1/7: Configuration Setup${NC}"
|
|
83
83
|
echo "------------------------------"
|
|
84
84
|
echo -e "${YELLOW}⚙️ Setting up configuration files and replacing placeholders...${NC}"
|
|
85
85
|
if ! bash "$SCRIPT_DIR/deploy-config.sh"; then
|
|
@@ -92,7 +92,7 @@ run_config_checkpoint
|
|
|
92
92
|
echo ""
|
|
93
93
|
|
|
94
94
|
# Step 2: Install Worker Dependencies
|
|
95
|
-
echo -e "${PURPLE}Step 2/
|
|
95
|
+
echo -e "${PURPLE}Step 2/7: Installing Worker Dependencies${NC}"
|
|
96
96
|
echo "----------------------------------------"
|
|
97
97
|
echo -e "${YELLOW}📦 Installing npm dependencies for all workers...${NC}"
|
|
98
98
|
if ! bash "$SCRIPT_DIR/install-workers.sh"; then
|
|
@@ -102,8 +102,26 @@ fi
|
|
|
102
102
|
echo -e "${GREEN}✅ All worker dependencies installed successfully${NC}"
|
|
103
103
|
echo ""
|
|
104
104
|
|
|
105
|
-
# Step 3:
|
|
106
|
-
echo -e "${PURPLE}Step 3/
|
|
105
|
+
# Step 3: Generate Wrangler Types
|
|
106
|
+
echo -e "${PURPLE}Step 3/7: Generating Wrangler Types${NC}"
|
|
107
|
+
echo "-------------------------------------"
|
|
108
|
+
echo -e "${YELLOW}📝 Running wrangler types in root and all worker directories...${NC}"
|
|
109
|
+
if ! npx wrangler types; then
|
|
110
|
+
echo -e "${RED}❌ Root wrangler types generation failed!${NC}"
|
|
111
|
+
exit 1
|
|
112
|
+
fi
|
|
113
|
+
for WORKER in audit-worker data-worker image-worker pdf-worker user-worker; do
|
|
114
|
+
echo -e "${YELLOW} → Generating types for ${WORKER}...${NC}"
|
|
115
|
+
if ! (cd "workers/$WORKER" && npx wrangler types); then
|
|
116
|
+
echo -e "${RED}❌ wrangler types failed for ${WORKER}!${NC}"
|
|
117
|
+
exit 1
|
|
118
|
+
fi
|
|
119
|
+
done
|
|
120
|
+
echo -e "${GREEN}✅ Wrangler types generated successfully${NC}"
|
|
121
|
+
echo ""
|
|
122
|
+
|
|
123
|
+
# Step 4: Deploy Workers
|
|
124
|
+
echo -e "${PURPLE}Step 4/7: Deploying Workers${NC}"
|
|
107
125
|
echo "----------------------------"
|
|
108
126
|
echo -e "${YELLOW}🔧 Deploying all 5 Cloudflare Workers...${NC}"
|
|
109
127
|
if ! npm run deploy-workers; then
|
|
@@ -113,8 +131,8 @@ fi
|
|
|
113
131
|
echo -e "${GREEN}✅ All workers deployed successfully${NC}"
|
|
114
132
|
echo ""
|
|
115
133
|
|
|
116
|
-
# Step
|
|
117
|
-
echo -e "${PURPLE}Step
|
|
134
|
+
# Step 5: Deploy Worker Secrets
|
|
135
|
+
echo -e "${PURPLE}Step 5/7: Deploying Worker Secrets${NC}"
|
|
118
136
|
echo "-----------------------------------"
|
|
119
137
|
echo -e "${YELLOW}🔐 Deploying worker environment variables...${NC}"
|
|
120
138
|
if ! bash "$SCRIPT_DIR/deploy-worker-secrets.sh"; then
|
|
@@ -124,8 +142,8 @@ fi
|
|
|
124
142
|
echo -e "${GREEN}✅ Worker secrets deployed successfully${NC}"
|
|
125
143
|
echo ""
|
|
126
144
|
|
|
127
|
-
# Step
|
|
128
|
-
echo -e "${PURPLE}Step
|
|
145
|
+
# Step 6: Deploy Pages Secrets
|
|
146
|
+
echo -e "${PURPLE}Step 6/7: Deploying Pages Secrets${NC}"
|
|
129
147
|
echo "----------------------------------"
|
|
130
148
|
echo -e "${YELLOW}🔐 Deploying Pages environment variables...${NC}"
|
|
131
149
|
if ! bash "$SCRIPT_DIR/deploy-pages-secrets.sh"; then
|
|
@@ -135,8 +153,8 @@ fi
|
|
|
135
153
|
echo -e "${GREEN}✅ Pages secrets deployed successfully${NC}"
|
|
136
154
|
echo ""
|
|
137
155
|
|
|
138
|
-
# Step
|
|
139
|
-
echo -e "${PURPLE}Step
|
|
156
|
+
# Step 7: Deploy Pages
|
|
157
|
+
echo -e "${PURPLE}Step 7/7: Deploying Pages${NC}"
|
|
140
158
|
echo "--------------------------"
|
|
141
159
|
echo -e "${YELLOW}🌐 Building and deploying Pages...${NC}"
|
|
142
160
|
if ! npm run deploy-pages; then
|
|
@@ -153,6 +171,7 @@ echo "=========================================="
|
|
|
153
171
|
echo ""
|
|
154
172
|
echo -e "${BLUE}Deployed Components:${NC}"
|
|
155
173
|
echo " ✅ Worker dependencies (npm install)"
|
|
174
|
+
echo " ✅ Wrangler types (root + all workers)"
|
|
156
175
|
echo " ✅ 5 Cloudflare Workers"
|
|
157
176
|
echo " ✅ Worker environment variables"
|
|
158
177
|
echo " ✅ Pages environment variables"
|
|
@@ -56,29 +56,12 @@ normalize_worker_label_value() {
|
|
|
56
56
|
printf '%s' "$label"
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
normalize_worker_subdomain_value() {
|
|
60
|
-
local subdomain="$1"
|
|
61
|
-
|
|
62
|
-
subdomain=$(normalize_domain_value "$subdomain")
|
|
63
|
-
subdomain="${subdomain#.}"
|
|
64
|
-
subdomain="${subdomain%.}"
|
|
65
|
-
subdomain=$(printf '%s' "$subdomain" | tr '[:upper:]' '[:lower:]')
|
|
66
|
-
|
|
67
|
-
printf '%s' "$subdomain"
|
|
68
|
-
}
|
|
69
|
-
|
|
70
59
|
is_valid_worker_label() {
|
|
71
60
|
local label="$1"
|
|
72
61
|
|
|
73
62
|
[[ "$label" =~ ^[a-z0-9-]+$ ]]
|
|
74
63
|
}
|
|
75
64
|
|
|
76
|
-
is_valid_worker_subdomain() {
|
|
77
|
-
local subdomain="$1"
|
|
78
|
-
|
|
79
|
-
[[ "$subdomain" =~ ^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$ ]]
|
|
80
|
-
}
|
|
81
|
-
|
|
82
65
|
strip_carriage_returns() {
|
|
83
66
|
printf '%s' "$1" | tr -d '\r'
|
|
84
67
|
}
|
|
@@ -196,57 +179,6 @@ confirm_key_pair_regeneration() {
|
|
|
196
179
|
return 1
|
|
197
180
|
}
|
|
198
181
|
|
|
199
|
-
generate_worker_subdomain_label() {
|
|
200
|
-
node -e "const { randomInt } = require('crypto'); const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789'; let value = ''; for (let index = 0; index < 10; index += 1) { value += alphabet[randomInt(alphabet.length)]; } process.stdout.write(value);" 2>/dev/null
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
compose_worker_domain() {
|
|
204
|
-
local worker_name=$1
|
|
205
|
-
local worker_subdomain=$2
|
|
206
|
-
|
|
207
|
-
worker_name=$(normalize_worker_label_value "$worker_name")
|
|
208
|
-
worker_subdomain=$(normalize_worker_subdomain_value "$worker_subdomain")
|
|
209
|
-
|
|
210
|
-
if [ -z "$worker_name" ] || [ -z "$worker_subdomain" ]; then
|
|
211
|
-
return 1
|
|
212
|
-
fi
|
|
213
|
-
|
|
214
|
-
if ! is_valid_worker_label "$worker_name" || ! is_valid_worker_subdomain "$worker_subdomain"; then
|
|
215
|
-
return 1
|
|
216
|
-
fi
|
|
217
|
-
|
|
218
|
-
printf '%s.%s' "$worker_name" "$worker_subdomain"
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
infer_worker_subdomain_from_domain() {
|
|
222
|
-
local worker_name=$1
|
|
223
|
-
local worker_domain=$2
|
|
224
|
-
local worker_subdomain=""
|
|
225
|
-
|
|
226
|
-
worker_name=$(normalize_worker_label_value "$worker_name")
|
|
227
|
-
worker_domain=$(normalize_domain_value "$worker_domain")
|
|
228
|
-
worker_domain=$(printf '%s' "$worker_domain" | tr '[:upper:]' '[:lower:]')
|
|
229
|
-
|
|
230
|
-
if [ -z "$worker_name" ] || [ -z "$worker_domain" ] || is_placeholder "$worker_name" || is_placeholder "$worker_domain"; then
|
|
231
|
-
printf '%s' ""
|
|
232
|
-
return 0
|
|
233
|
-
fi
|
|
234
|
-
|
|
235
|
-
case "$worker_domain" in
|
|
236
|
-
"$worker_name".*)
|
|
237
|
-
worker_subdomain="${worker_domain#${worker_name}.}"
|
|
238
|
-
worker_subdomain=$(normalize_worker_subdomain_value "$worker_subdomain")
|
|
239
|
-
|
|
240
|
-
if is_valid_worker_subdomain "$worker_subdomain"; then
|
|
241
|
-
printf '%s' "$worker_subdomain"
|
|
242
|
-
return 0
|
|
243
|
-
fi
|
|
244
|
-
;;
|
|
245
|
-
esac
|
|
246
|
-
|
|
247
|
-
printf '%s' ""
|
|
248
|
-
}
|
|
249
|
-
|
|
250
182
|
write_env_var() {
|
|
251
183
|
local var_name=$1
|
|
252
184
|
local var_value=$2
|
|
@@ -23,7 +23,7 @@ prompt_for_secrets() {
|
|
|
23
23
|
is_auto_generated_secret_var() {
|
|
24
24
|
local var_name=$1
|
|
25
25
|
case "$var_name" in
|
|
26
|
-
|
|
26
|
+
IMAGE_SIGNED_URL_SECRET)
|
|
27
27
|
return 0
|
|
28
28
|
;;
|
|
29
29
|
*)
|
|
@@ -36,18 +36,6 @@ prompt_for_secrets() {
|
|
|
36
36
|
local var_name=$1
|
|
37
37
|
local value=$2
|
|
38
38
|
case "$var_name" in
|
|
39
|
-
USER_DB_AUTH)
|
|
40
|
-
[ "$value" = "your_custom_user_db_auth_token_here" ]
|
|
41
|
-
;;
|
|
42
|
-
R2_KEY_SECRET)
|
|
43
|
-
[ "$value" = "your_custom_r2_secret_here" ]
|
|
44
|
-
;;
|
|
45
|
-
PDF_WORKER_AUTH)
|
|
46
|
-
[ "$value" = "your_custom_pdf_worker_auth_token_here" ]
|
|
47
|
-
;;
|
|
48
|
-
IMAGES_API_TOKEN)
|
|
49
|
-
[ "$value" = "your_cloudflare_images_api_token_here" ]
|
|
50
|
-
;;
|
|
51
39
|
IMAGE_SIGNED_URL_SECRET)
|
|
52
40
|
[ "$value" = "your_image_signed_url_secret_here" ]
|
|
53
41
|
;;
|
|
@@ -214,42 +202,11 @@ prompt_for_secrets() {
|
|
|
214
202
|
echo ""
|
|
215
203
|
}
|
|
216
204
|
|
|
217
|
-
set_worker_domain_from_shared_subdomain() {
|
|
218
|
-
local worker_name_var=$1
|
|
219
|
-
local worker_domain_var=$2
|
|
220
|
-
local worker_name_value="${!worker_name_var}"
|
|
221
|
-
local composed_domain=""
|
|
222
|
-
|
|
223
|
-
worker_name_value=$(normalize_worker_label_value "$worker_name_value")
|
|
224
|
-
|
|
225
|
-
if [ -z "$worker_name_value" ] || ! is_valid_worker_label "$worker_name_value"; then
|
|
226
|
-
echo -e "${RED}❌ $worker_name_var must use only lowercase letters, numbers, and dashes.${NC}"
|
|
227
|
-
exit 1
|
|
228
|
-
fi
|
|
229
|
-
|
|
230
|
-
composed_domain=$(compose_worker_domain "$worker_name_value" "$shared_worker_subdomain" || echo "")
|
|
231
|
-
|
|
232
|
-
if [ -z "$composed_domain" ]; then
|
|
233
|
-
echo -e "${RED}❌ Could not build $worker_domain_var from $worker_name_var and shared worker-subdomain.${NC}"
|
|
234
|
-
exit 1
|
|
235
|
-
fi
|
|
236
|
-
|
|
237
|
-
write_env_var "$worker_domain_var" "$composed_domain"
|
|
238
|
-
export "$worker_domain_var=$composed_domain"
|
|
239
|
-
echo -e "${GREEN}✅ $worker_domain_var set to $composed_domain${NC}"
|
|
240
|
-
}
|
|
241
|
-
|
|
242
205
|
echo -e "${BLUE}📊 CLOUDFLARE CORE CONFIGURATION${NC}"
|
|
243
206
|
echo "=================================="
|
|
244
207
|
prompt_for_var "ACCOUNT_ID" "Your Cloudflare Account ID"
|
|
245
208
|
|
|
246
|
-
echo -e "${BLUE}
|
|
247
|
-
echo "==================================="
|
|
248
|
-
prompt_for_var "USER_DB_AUTH" "Custom user database authentication token (generate with: openssl rand -hex 16)"
|
|
249
|
-
prompt_for_var "R2_KEY_SECRET" "Custom R2 storage authentication token (generate with: openssl rand -hex 16)"
|
|
250
|
-
prompt_for_var "IMAGES_API_TOKEN" "Image worker API token (shared between workers)"
|
|
251
|
-
|
|
252
|
-
echo -e "${BLUE}🔥 FIREBASE AUTH CONFIGURATION${NC}"
|
|
209
|
+
echo -e "${BLUE} FIREBASE AUTH CONFIGURATION${NC}"
|
|
253
210
|
echo "==============================="
|
|
254
211
|
prompt_for_var "API_KEY" "Firebase API key"
|
|
255
212
|
prompt_for_var "AUTH_DOMAIN" "Firebase auth domain (project-id.firebaseapp.com)"
|
|
@@ -264,77 +221,15 @@ prompt_for_secrets() {
|
|
|
264
221
|
prompt_for_var "PAGES_PROJECT_NAME" "Your Cloudflare Pages project name"
|
|
265
222
|
prompt_for_var "PAGES_CUSTOM_DOMAIN" "Your custom domain (e.g., striae.org) - DO NOT include https://"
|
|
266
223
|
|
|
267
|
-
echo -e "${BLUE}🔑 WORKER NAMES
|
|
268
|
-
echo "
|
|
224
|
+
echo -e "${BLUE}🔑 WORKER NAMES${NC}"
|
|
225
|
+
echo "==============="
|
|
269
226
|
echo -e "${YELLOW}Worker names are lowercased automatically and must use only letters, numbers, and dashes.${NC}"
|
|
270
|
-
echo -e "${YELLOW}Enter one shared worker-subdomain as a hostname (for example: team-name.workers.dev).${NC}"
|
|
271
|
-
echo -e "${YELLOW}Each worker domain is generated as {worker-name}.{worker-subdomain}.${NC}"
|
|
272
|
-
|
|
273
|
-
local shared_worker_subdomain=""
|
|
274
|
-
local shared_worker_subdomain_default=""
|
|
275
|
-
local shared_worker_subdomain_input=""
|
|
276
|
-
|
|
277
|
-
shared_worker_subdomain_default=$(infer_worker_subdomain_from_domain "$USER_WORKER_NAME" "$USER_WORKER_DOMAIN")
|
|
278
|
-
if [ -z "$shared_worker_subdomain_default" ]; then
|
|
279
|
-
shared_worker_subdomain_default=$(infer_worker_subdomain_from_domain "$DATA_WORKER_NAME" "$DATA_WORKER_DOMAIN")
|
|
280
|
-
fi
|
|
281
|
-
if [ -z "$shared_worker_subdomain_default" ]; then
|
|
282
|
-
shared_worker_subdomain_default=$(infer_worker_subdomain_from_domain "$AUDIT_WORKER_NAME" "$AUDIT_WORKER_DOMAIN")
|
|
283
|
-
fi
|
|
284
|
-
if [ -z "$shared_worker_subdomain_default" ]; then
|
|
285
|
-
shared_worker_subdomain_default=$(infer_worker_subdomain_from_domain "$IMAGES_WORKER_NAME" "$IMAGES_WORKER_DOMAIN")
|
|
286
|
-
fi
|
|
287
|
-
if [ -z "$shared_worker_subdomain_default" ]; then
|
|
288
|
-
shared_worker_subdomain_default=$(infer_worker_subdomain_from_domain "$PDF_WORKER_NAME" "$PDF_WORKER_DOMAIN")
|
|
289
|
-
fi
|
|
290
|
-
|
|
291
|
-
while true; do
|
|
292
|
-
echo -e "${BLUE}WORKER_SUBDOMAIN${NC}"
|
|
293
|
-
|
|
294
|
-
if [ "$update_env" != "true" ] && [ -n "$shared_worker_subdomain_default" ] && ! is_placeholder "$shared_worker_subdomain_default"; then
|
|
295
|
-
echo -e "${GREEN}Current value: $shared_worker_subdomain_default${NC}"
|
|
296
|
-
read -p "New value (or press Enter to keep current): " shared_worker_subdomain_input
|
|
297
|
-
shared_worker_subdomain_input=$(strip_carriage_returns "$shared_worker_subdomain_input")
|
|
298
|
-
|
|
299
|
-
if [ -z "$shared_worker_subdomain_input" ]; then
|
|
300
|
-
shared_worker_subdomain="$shared_worker_subdomain_default"
|
|
301
|
-
else
|
|
302
|
-
shared_worker_subdomain="$shared_worker_subdomain_input"
|
|
303
|
-
fi
|
|
304
|
-
else
|
|
305
|
-
read -p "Enter shared worker-subdomain (e.g., team-name.workers.dev): " shared_worker_subdomain_input
|
|
306
|
-
shared_worker_subdomain_input=$(strip_carriage_returns "$shared_worker_subdomain_input")
|
|
307
|
-
shared_worker_subdomain="$shared_worker_subdomain_input"
|
|
308
|
-
fi
|
|
309
|
-
|
|
310
|
-
if [ -z "$shared_worker_subdomain" ] || is_placeholder "$shared_worker_subdomain"; then
|
|
311
|
-
echo -e "${RED}❌ shared worker-subdomain is required and cannot be a placeholder.${NC}"
|
|
312
|
-
continue
|
|
313
|
-
fi
|
|
314
|
-
|
|
315
|
-
shared_worker_subdomain=$(normalize_worker_subdomain_value "$shared_worker_subdomain")
|
|
316
|
-
|
|
317
|
-
if [ -z "$shared_worker_subdomain" ] || ! is_valid_worker_subdomain "$shared_worker_subdomain"; then
|
|
318
|
-
echo -e "${RED}❌ shared worker-subdomain must be a valid hostname like team-name.workers.dev (letters, numbers, dashes, and dots).${NC}"
|
|
319
|
-
continue
|
|
320
|
-
fi
|
|
321
|
-
|
|
322
|
-
echo -e "${GREEN}✅ Shared worker-subdomain set to: $shared_worker_subdomain${NC}"
|
|
323
|
-
echo ""
|
|
324
|
-
break
|
|
325
|
-
done
|
|
326
227
|
|
|
327
228
|
prompt_for_var "USER_WORKER_NAME" "User worker name"
|
|
328
229
|
prompt_for_var "DATA_WORKER_NAME" "Data worker name"
|
|
329
230
|
prompt_for_var "AUDIT_WORKER_NAME" "Audit worker name"
|
|
330
231
|
prompt_for_var "IMAGES_WORKER_NAME" "Images worker name"
|
|
331
232
|
prompt_for_var "PDF_WORKER_NAME" "PDF worker name"
|
|
332
|
-
|
|
333
|
-
set_worker_domain_from_shared_subdomain "USER_WORKER_NAME" "USER_WORKER_DOMAIN"
|
|
334
|
-
set_worker_domain_from_shared_subdomain "DATA_WORKER_NAME" "DATA_WORKER_DOMAIN"
|
|
335
|
-
set_worker_domain_from_shared_subdomain "AUDIT_WORKER_NAME" "AUDIT_WORKER_DOMAIN"
|
|
336
|
-
set_worker_domain_from_shared_subdomain "IMAGES_WORKER_NAME" "IMAGES_WORKER_DOMAIN"
|
|
337
|
-
set_worker_domain_from_shared_subdomain "PDF_WORKER_NAME" "PDF_WORKER_DOMAIN"
|
|
338
233
|
echo ""
|
|
339
234
|
|
|
340
235
|
echo -e "${BLUE}🗄️ STORAGE CONFIGURATION${NC}"
|
|
@@ -346,7 +241,6 @@ prompt_for_secrets() {
|
|
|
346
241
|
|
|
347
242
|
echo -e "${BLUE}🔐 SERVICE-SPECIFIC SECRETS${NC}"
|
|
348
243
|
echo "============================"
|
|
349
|
-
prompt_for_var "PDF_WORKER_AUTH" "PDF worker authentication token (generate with: openssl rand -hex 16)"
|
|
350
244
|
prompt_for_var "IMAGE_SIGNED_URL_SECRET" "Image signed URL secret (generate with: openssl rand -base64 48 | tr '+/' '-_' | tr -d '=')"
|
|
351
245
|
|
|
352
246
|
# Auto-derive IMAGE_SIGNED_URL_BASE_URL from PAGES_CUSTOM_DOMAIN if not yet set or still
|