Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ VITE_API_BASE_URL=http://127.0.0.1:4242
VITE_KEYCLOAK_URL=http://localhost:8080/
VITE_KEYCLOAK_REALM=dev
VITE_KEYCLOAK_CLIENT_ID=bff-dashboard
VITE_API_MOCKING_ENABLED=false
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ FROM nginx:1.27.5-alpine@sha256:65645c7bb6a0661892a8b03b89d0743208a18dd2f3f17a54

COPY --from=builder /app/dist /usr/share/nginx/html

COPY docker/entrypoint.d/ /docker-entrypoint.d/
RUN chmod +x /docker-entrypoint.d/*.sh

COPY docker/nginx/snippets/proxy-params.conf /etc/nginx/snippets/proxy-params.conf
# each time nginx is started it will perform variable substition in all template
# files found in `/etc/nginx/templates/*.template`, and copy the results (without
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ services:
- VITE_KEYCLOAK_URL=${VITE_KEYCLOAK_URL}
- VITE_KEYCLOAK_REALM=${VITE_KEYCLOAK_REALM}
- VITE_KEYCLOAK_CLIENT_ID=${VITE_KEYCLOAK_CLIENT_ID}
- VITE_API_MOCKING_ENABLED=${VITE_API_MOCKING_ENABLED}
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:80"]
interval: 30s
Expand Down
13 changes: 13 additions & 0 deletions docker/entrypoint.d/00-env-config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env sh
set -e

cat <<EOF > /usr/share/nginx/html/config.js
window.__ENV__ = {
VITE_API_BASE_URL: "${VITE_API_BASE_URL}",
VITE_API_MOCKING_ENABLED: "${VITE_API_MOCKING_ENABLED}",
VITE_KEYCLOAK_URL: "${VITE_KEYCLOAK_URL}",
VITE_KEYCLOAK_REALM: "${VITE_KEYCLOAK_REALM}",
VITE_KEYCLOAK_CLIENT_ID: "${VITE_KEYCLOAK_CLIENT_ID}",
VITE_BITCR_DEV_INCLUDE_CROWDIN_IN_CONTEXT_TOOLING: "${VITE_BITCR_DEV_INCLUDE_CROWDIN_IN_CONTEXT_TOOLING}"
}
EOF
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generated config.js file is placed in /usr/share/nginx/html/config.js, but there's no verification that the file was successfully created or that the jq command succeeded. Consider adding error handling to ensure the config.js file is generated correctly. For example:

if [ ! -f /usr/share/nginx/html/config.js ]; then
  echo "Error: Failed to generate config.js"
  exit 1
fi
Suggested change
EOF
EOF
if [ ! -f /usr/share/nginx/html/config.js ]; then
echo "Error: Failed to generate config.js"
exit 1
fi

Copilot uses AI. Check for mistakes.
4 changes: 4 additions & 0 deletions docker/nginx/templates/default.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ server {
add_header Cache-Control "no-store";
}

location = /config.js {
add_header Cache-Control "no-store";
}

location ~* \.(?:json)$ {
expires 1d;
add_header Cache-Control "public";
Expand Down
1 change: 1 addition & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
</head>
<body>
<div id="root"></div>
<script src="/config.js"></script>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
1 change: 1 addition & 0 deletions public/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
window.__ENV__ = window.__ENV__ || {}
10 changes: 6 additions & 4 deletions src/constants/meta.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { env } from "@/lib/env"

export default {
devModeEnabled: import.meta.env.DEV,
apiBaseUrl: import.meta.env.VITE_API_BASE_URL as string,
apiMocksEnabled: import.meta.env.VITE_API_MOCKING_ENABLED === "true",
crowdinInContextToolingEnabled: import.meta.env.VITE_BITCR_DEV_INCLUDE_CROWDIN_IN_CONTEXT_TOOLING === "true",
devModeEnabled: env.devModeEnabled,
apiBaseUrl: env.apiBaseUrl,
apiMocksEnabled: env.apiMocksEnabled,
crowdinInContextToolingEnabled: env.crowdinInContextToolingEnabled,
}
7 changes: 4 additions & 3 deletions src/keycloak.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Keycloak from "keycloak-js"
import { env } from "@/lib/env"

const keycloak = new Keycloak({
url: import.meta.env.VITE_KEYCLOAK_URL as string,
realm: import.meta.env.VITE_KEYCLOAK_REALM as string,
clientId: import.meta.env.VITE_KEYCLOAK_CLIENT_ID as string,
url: env.keycloakUrl,
realm: env.keycloakRealm,
clientId: env.keycloakClientId,
})

export const initKeycloak = async (): Promise<boolean> => {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/api-client.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { client as heyApiClient } from "@/generated/client/client.gen"
import * as sdk from "@/generated/client/sdk.gen"
import { env } from "@/lib/env"
import keycloak from "../keycloak"

heyApiClient.setConfig({
baseUrl: import.meta.env.VITE_API_BASE_URL as string,
baseUrl: env.apiBaseUrl,
})

// Add the auth token interceptor
Expand Down
34 changes: 34 additions & 0 deletions src/lib/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
type RuntimeEnv = Partial<{
VITE_API_BASE_URL: string
VITE_API_MOCKING_ENABLED: string
VITE_KEYCLOAK_URL: string
VITE_KEYCLOAK_REALM: string
VITE_KEYCLOAK_CLIENT_ID: string
VITE_BITCR_DEV_INCLUDE_CROWDIN_IN_CONTEXT_TOOLING: string
}>

const runtimeEnv: RuntimeEnv =
typeof window !== "undefined" ? (window as { __ENV__?: RuntimeEnv }).__ENV__ ?? {} : {}

const fallbackEnv = import.meta.env as ImportMetaEnv & RuntimeEnv

const getEnvValue = <K extends keyof RuntimeEnv>(key: K): RuntimeEnv[K] | undefined => {
const value = runtimeEnv[key]

if (value !== undefined && value !== null && value !== "") {
return value
}

return fallbackEnv[key]
}

export const env = {
devModeEnabled: fallbackEnv.DEV,
apiBaseUrl: getEnvValue("VITE_API_BASE_URL") as string,

Check failure on line 27 in src/lib/env.ts

View workflow job for this annotation

GitHub Actions / Validate (lint, test, build)

Use a ! assertion to more succinctly remove null and undefined from the type
apiMocksEnabled: (getEnvValue("VITE_API_MOCKING_ENABLED") ?? "false") === "true",
keycloakUrl: getEnvValue("VITE_KEYCLOAK_URL") as string,

Check failure on line 29 in src/lib/env.ts

View workflow job for this annotation

GitHub Actions / Validate (lint, test, build)

Use a ! assertion to more succinctly remove null and undefined from the type
keycloakRealm: getEnvValue("VITE_KEYCLOAK_REALM") as string,

Check failure on line 30 in src/lib/env.ts

View workflow job for this annotation

GitHub Actions / Validate (lint, test, build)

Use a ! assertion to more succinctly remove null and undefined from the type
keycloakClientId: getEnvValue("VITE_KEYCLOAK_CLIENT_ID") as string,

Check failure on line 31 in src/lib/env.ts

View workflow job for this annotation

GitHub Actions / Validate (lint, test, build)

Use a ! assertion to more succinctly remove null and undefined from the type
crowdinInContextToolingEnabled:
(getEnvValue("VITE_BITCR_DEV_INCLUDE_CROWDIN_IN_CONTEXT_TOOLING") ?? "false") === "true",
}
Loading