@seliseblocks/cli-os 0.2.1 → 0.2.2
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.
|
@@ -8,6 +8,14 @@ export async function writeRootFiles(root, options) {
|
|
|
8
8
|
type: "module",
|
|
9
9
|
scripts: {
|
|
10
10
|
build: "vite build",
|
|
11
|
+
"build:dev": "vite build --mode dev && node scripts/write-release-env.mjs dev",
|
|
12
|
+
"build:test": "vite build --mode test && node scripts/write-release-env.mjs test",
|
|
13
|
+
"build:stg": "vite build --mode stg && node scripts/write-release-env.mjs stg",
|
|
14
|
+
"build:iat": "vite build --mode iat && node scripts/write-release-env.mjs iat",
|
|
15
|
+
"build:uat": "vite build --mode uat && node scripts/write-release-env.mjs uat",
|
|
16
|
+
"build:preprod": "vite build --mode preprod && node scripts/write-release-env.mjs preprod",
|
|
17
|
+
"build:prodshadow": "vite build --mode prodshadow && node scripts/write-release-env.mjs prodshadow",
|
|
18
|
+
"build:prod": "vite build --mode prod && node scripts/write-release-env.mjs prod",
|
|
11
19
|
cert: "node scripts/generate-cert.mjs",
|
|
12
20
|
dev: "vite",
|
|
13
21
|
lint: "tsc --noEmit",
|
|
@@ -74,9 +82,76 @@ export async function writeRootFiles(root, options) {
|
|
|
74
82
|
".env",
|
|
75
83
|
".env.local",
|
|
76
84
|
".env.*.local",
|
|
85
|
+
"env.*",
|
|
77
86
|
".cert/",
|
|
78
87
|
""
|
|
79
88
|
].join("\n"));
|
|
89
|
+
await write(root, "nginx.conf", [
|
|
90
|
+
"server {",
|
|
91
|
+
" listen 8080;",
|
|
92
|
+
" root /usr/share/nginx/html/;",
|
|
93
|
+
" server_tokens off;",
|
|
94
|
+
" client_max_body_size 200m;",
|
|
95
|
+
"",
|
|
96
|
+
" gzip on;",
|
|
97
|
+
" gzip_comp_level 6;",
|
|
98
|
+
" gzip_min_length 1000;",
|
|
99
|
+
" gzip_proxied expired no-cache no-store private auth;",
|
|
100
|
+
" gzip_types text/plain application/x-javascript text/xml text/css application/xml text/javascript application/javascript application/json application/font-woff application/font-woff2 application/vnd.ms-fontobject application/x-font-ttf font/opentype;",
|
|
101
|
+
"",
|
|
102
|
+
" location / {",
|
|
103
|
+
" try_files $uri $uri/ /index.html;",
|
|
104
|
+
" }",
|
|
105
|
+
"}",
|
|
106
|
+
""
|
|
107
|
+
].join("\n"));
|
|
108
|
+
await write(root, "Dockerfile", [
|
|
109
|
+
"FROM node:22-alpine AS builder",
|
|
110
|
+
"",
|
|
111
|
+
"WORKDIR /app",
|
|
112
|
+
"",
|
|
113
|
+
"COPY package*.json ./",
|
|
114
|
+
"",
|
|
115
|
+
"RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi",
|
|
116
|
+
"",
|
|
117
|
+
"COPY . .",
|
|
118
|
+
"",
|
|
119
|
+
"ARG ci_build=dev",
|
|
120
|
+
"ARG VITE_BLOCKS_API_URL",
|
|
121
|
+
"ARG VITE_BLOCKS_PROJECT_KEY",
|
|
122
|
+
"ARG VITE_BLOCKS_X_BLOCKS_KEY",
|
|
123
|
+
"ARG VITE_BLOCKS_APP_DOMAIN",
|
|
124
|
+
"ARG VITE_BLOCKS_OIDC_URL=https://iam.seliseblocks.com",
|
|
125
|
+
"ARG VITE_BLOCKS_OIDC_CLIENT_ID",
|
|
126
|
+
"ARG VITE_BLOCKS_OIDC_SCOPE=\"openid profile\"",
|
|
127
|
+
"ARG VITE_BLOCKS_REDIRECT_URI",
|
|
128
|
+
"ARG VITE_BLOCKS_HOSTED_LOGIN=true",
|
|
129
|
+
"",
|
|
130
|
+
"ENV VITE_BLOCKS_API_URL=${VITE_BLOCKS_API_URL}",
|
|
131
|
+
"ENV VITE_BLOCKS_PROJECT_KEY=${VITE_BLOCKS_PROJECT_KEY}",
|
|
132
|
+
"ENV VITE_BLOCKS_X_BLOCKS_KEY=${VITE_BLOCKS_X_BLOCKS_KEY}",
|
|
133
|
+
"ENV VITE_BLOCKS_APP_DOMAIN=${VITE_BLOCKS_APP_DOMAIN}",
|
|
134
|
+
"ENV VITE_BLOCKS_OIDC_URL=${VITE_BLOCKS_OIDC_URL}",
|
|
135
|
+
"ENV VITE_BLOCKS_OIDC_CLIENT_ID=${VITE_BLOCKS_OIDC_CLIENT_ID}",
|
|
136
|
+
"ENV VITE_BLOCKS_OIDC_SCOPE=${VITE_BLOCKS_OIDC_SCOPE}",
|
|
137
|
+
"ENV VITE_BLOCKS_REDIRECT_URI=${VITE_BLOCKS_REDIRECT_URI}",
|
|
138
|
+
"ENV VITE_BLOCKS_HOSTED_LOGIN=${VITE_BLOCKS_HOSTED_LOGIN}",
|
|
139
|
+
"",
|
|
140
|
+
"RUN NODE_OPTIONS=\"--max-old-space-size=4096\" npx vite build --mode \"${ci_build}\" \\",
|
|
141
|
+
" && node scripts/write-release-env.mjs \"${ci_build}\"",
|
|
142
|
+
"",
|
|
143
|
+
"FROM nginxinc/nginx-unprivileged:1.29-alpine",
|
|
144
|
+
"",
|
|
145
|
+
"COPY --from=builder /app/dist /usr/share/nginx/html",
|
|
146
|
+
"",
|
|
147
|
+
"COPY nginx.conf /etc/nginx/conf.d/default.conf",
|
|
148
|
+
"",
|
|
149
|
+
"EXPOSE 8080",
|
|
150
|
+
"",
|
|
151
|
+
"# HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \\",
|
|
152
|
+
"# CMD wget -qO- http://localhost:8080/ || exit 1",
|
|
153
|
+
""
|
|
154
|
+
].join("\n"));
|
|
80
155
|
await write(root, "README.md", [
|
|
81
156
|
`# ${options.name}`,
|
|
82
157
|
"",
|
|
@@ -116,6 +191,12 @@ export async function writeRootFiles(root, options) {
|
|
|
116
191
|
"",
|
|
117
192
|
"`.cert/` is gitignored — each developer generates and trusts their own cert.",
|
|
118
193
|
"",
|
|
194
|
+
"## Blocks Release deployment",
|
|
195
|
+
"",
|
|
196
|
+
"The scaffold includes `Dockerfile` and `nginx.conf` for Blocks Release. The Release service must pass Docker build arg `ci_build=<environment>` plus the public `VITE_BLOCKS_*` build args documented in the Dockerfile. The generated `package.json` also provides `build:dev`, `build:test`, `build:stg`, `build:iat`, `build:uat`, `build:preprod`, `build:prodshadow`, and `build:prod` scripts for local checks.",
|
|
197
|
+
"",
|
|
198
|
+
"During each environment build, `scripts/write-release-env.mjs` writes `dist/env.<environment>` from client-safe Docker build args or local `.env` files. Root `.env` remains gitignored and must not be committed.",
|
|
199
|
+
"",
|
|
119
200
|
"## What's included",
|
|
120
201
|
"",
|
|
121
202
|
"- `/login` — login page (redirects to Blocks IAM).",
|
|
@@ -275,4 +356,81 @@ export async function writeRootFiles(root, options) {
|
|
|
275
356
|
"}",
|
|
276
357
|
""
|
|
277
358
|
].join("\n"));
|
|
359
|
+
await write(root, "scripts/write-release-env.mjs", [
|
|
360
|
+
"#!/usr/bin/env node",
|
|
361
|
+
"// Writes the client-safe Blocks env snapshot into dist for release artifacts.",
|
|
362
|
+
"import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";",
|
|
363
|
+
"import { join } from \"node:path\";",
|
|
364
|
+
"",
|
|
365
|
+
"const mode = (process.argv[2] || \"dev\").trim();",
|
|
366
|
+
"if (!mode) {",
|
|
367
|
+
" console.error(\"Usage: node scripts/write-release-env.mjs <environment>\");",
|
|
368
|
+
" process.exit(1);",
|
|
369
|
+
"}",
|
|
370
|
+
"",
|
|
371
|
+
"const env = readEnv(mode);",
|
|
372
|
+
"const appDomain = env.VITE_BLOCKS_APP_DOMAIN || \"\";",
|
|
373
|
+
"const redirectUri = env.VITE_BLOCKS_REDIRECT_URI || callbackUri(appDomain);",
|
|
374
|
+
"const projectKey = env.VITE_BLOCKS_X_BLOCKS_KEY || env.VITE_BLOCKS_PROJECT_KEY || \"\";",
|
|
375
|
+
"",
|
|
376
|
+
"const output = [",
|
|
377
|
+
" \"# SELISE Blocks production/default configuration.\",",
|
|
378
|
+
" \"# Only client-safe values belong here. Never put passwords, PTOKs, JWTs,\",",
|
|
379
|
+
" \"# refresh tokens, cookies, or client secrets in VITE_-prefixed variables.\",",
|
|
380
|
+
" \"\",",
|
|
381
|
+
" `VITE_BLOCKS_API_URL=${env.VITE_BLOCKS_API_URL || \"\"}`,",
|
|
382
|
+
" `VITE_BLOCKS_PROJECT_KEY=${projectKey}`,",
|
|
383
|
+
" `VITE_BLOCKS_X_BLOCKS_KEY=${projectKey}`,",
|
|
384
|
+
" `VITE_BLOCKS_APP_DOMAIN=${appDomain}`,",
|
|
385
|
+
" `VITE_BLOCKS_OIDC_URL=${env.VITE_BLOCKS_OIDC_URL || \"\"}`,",
|
|
386
|
+
" `VITE_BLOCKS_OIDC_CLIENT_ID=${env.VITE_BLOCKS_OIDC_CLIENT_ID || \"\"}`,",
|
|
387
|
+
" `VITE_BLOCKS_OIDC_SCOPE=${env.VITE_BLOCKS_OIDC_SCOPE || \"openid profile\"}`,",
|
|
388
|
+
" `VITE_BLOCKS_REDIRECT_URI=${redirectUri}`,",
|
|
389
|
+
" \"VITE_BLOCKS_HOSTED_LOGIN=true\",",
|
|
390
|
+
" \"\"",
|
|
391
|
+
"].join(\"\\n\");",
|
|
392
|
+
"",
|
|
393
|
+
"mkdirSync(\"dist\", { recursive: true });",
|
|
394
|
+
"writeFileSync(join(\"dist\", `env.${mode}`), output);",
|
|
395
|
+
"console.log(`Wrote dist/env.${mode}`);",
|
|
396
|
+
"",
|
|
397
|
+
"function readEnv(mode) {",
|
|
398
|
+
" const result = {};",
|
|
399
|
+
" for (const file of [\".env\", `.env.${mode}`, \".env.local\", `.env.${mode}.local`]) {",
|
|
400
|
+
" if (!existsSync(file)) continue;",
|
|
401
|
+
" Object.assign(result, parseEnv(readFileSync(file, \"utf8\")));",
|
|
402
|
+
" }",
|
|
403
|
+
" for (const [key, value] of Object.entries(process.env)) {",
|
|
404
|
+
" if (!key.startsWith(\"VITE_BLOCKS_\") || value === undefined) continue;",
|
|
405
|
+
" result[key] = value;",
|
|
406
|
+
" }",
|
|
407
|
+
" return result;",
|
|
408
|
+
"}",
|
|
409
|
+
"",
|
|
410
|
+
"function parseEnv(content) {",
|
|
411
|
+
" const values = {};",
|
|
412
|
+
" for (const rawLine of content.split(/\\r?\\n/)) {",
|
|
413
|
+
" const line = rawLine.trim();",
|
|
414
|
+
" if (!line || line.startsWith(\"#\")) continue;",
|
|
415
|
+
" const equals = line.indexOf(\"=\");",
|
|
416
|
+
" if (equals < 1) continue;",
|
|
417
|
+
" const key = line.slice(0, equals).trim();",
|
|
418
|
+
" let value = line.slice(equals + 1).trim();",
|
|
419
|
+
" if ((value.startsWith(\"\\\"\") && value.endsWith(\"\\\"\")) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {",
|
|
420
|
+
" value = value.slice(1, -1);",
|
|
421
|
+
" }",
|
|
422
|
+
" values[key] = value;",
|
|
423
|
+
" }",
|
|
424
|
+
" return values;",
|
|
425
|
+
"}",
|
|
426
|
+
"",
|
|
427
|
+
"function callbackUri(appDomain) {",
|
|
428
|
+
" if (!appDomain) return \"\";",
|
|
429
|
+
" const origin = appDomain.startsWith(\"http://\") || appDomain.startsWith(\"https://\")",
|
|
430
|
+
" ? appDomain.replace(/\\/+$/, \"\")",
|
|
431
|
+
" : `https://${appDomain.replace(/\\/+$/, \"\")}`;",
|
|
432
|
+
" return `${origin}/login/callback`;",
|
|
433
|
+
"}",
|
|
434
|
+
""
|
|
435
|
+
].join("\n"));
|
|
278
436
|
}
|