mirror of
https://github.com/luxfi/bridge.git
synced 2026-09-24 00:26:46 +00:00
merge: runtime env shim (window.__ENV + nginx docker-entrypoint)
# Conflicts: # app/bridge/src/bridge.config.ts
This commit is contained in:
+12
-3
@@ -1,8 +1,15 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
#
|
||||
# bridge.lux.network — Vite SPA served by ghcr.io/hanzoai/spa.
|
||||
# bridge.lux.network — Vite SPA.
|
||||
#
|
||||
# Build context: repo root (pnpm workspace so @luxfi/bridge resolves
|
||||
# to the sibling pkg/bridge package).
|
||||
#
|
||||
# Runtime config: nginx serves the static bundle and a templated
|
||||
# /__ENV.js generated at container boot from BRIDGE_* env vars. The
|
||||
# bundle's bridge.config.ts reads window.__ENV (populated by
|
||||
# /__ENV.js) before falling back to Vite's build-time import.meta.env.
|
||||
# This makes the image env-agnostic: one tag deployed to N envs.
|
||||
|
||||
FROM node:22-alpine AS build
|
||||
RUN apk add --no-cache libc6-compat python3 make g++ git
|
||||
@@ -12,5 +19,7 @@ COPY . .
|
||||
RUN pnpm install --frozen-lockfile || pnpm install
|
||||
RUN pnpm -C app/bridge build
|
||||
|
||||
FROM ghcr.io/hanzoai/spa
|
||||
COPY --from=build /app/app/bridge/dist /public
|
||||
FROM nginx:alpine
|
||||
COPY --from=build /app/app/bridge/dist /usr/share/nginx/html
|
||||
COPY app/bridge/docker-entrypoint.sh /docker-entrypoint.d/40-render-env.sh
|
||||
RUN chmod +x /docker-entrypoint.d/40-render-env.sh
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
# Generate /__ENV.js from container env at boot. Lets one image serve N envs.
|
||||
#
|
||||
# nginx:alpine looks in /docker-entrypoint.d/ for *.sh files and runs them
|
||||
# before starting nginx. This file lands at /docker-entrypoint.d/40-render-env.sh
|
||||
# via the Dockerfile.
|
||||
#
|
||||
# The SDK reads window.__ENV from /__ENV.js before falling back to
|
||||
# build-time import.meta.env (see app/bridge/src/bridge.config.ts).
|
||||
#
|
||||
# Tenants (zoo, lux-mci, ...) copy this script verbatim — only the env
|
||||
# var names need to match the keys the tenant's bridge.config.ts looks up.
|
||||
|
||||
set -eu
|
||||
|
||||
cat > /usr/share/nginx/html/__ENV.js <<EOF
|
||||
window.__ENV = {
|
||||
BRIDGE_API_HOST: '${BRIDGE_API_HOST:-}',
|
||||
BRIDGE_ENV: '${BRIDGE_ENV:-}',
|
||||
BRIDGE_CLIENT_ID: '${BRIDGE_CLIENT_ID:-}',
|
||||
BRIDGE_IAM_ORG: '${BRIDGE_IAM_ORG:-}',
|
||||
BRIDGE_LOGO_URL: '${BRIDGE_LOGO_URL:-}',
|
||||
WC_PROJECT_ID: '${WC_PROJECT_ID:-}',
|
||||
}
|
||||
EOF
|
||||
@@ -6,6 +6,18 @@
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='6' fill='%235b8def'/></svg>" />
|
||||
<title>Lux Bridge</title>
|
||||
<meta name="description" content="Cross-chain bridge for the Lux Network." />
|
||||
<!--
|
||||
Runtime env: /__ENV.js sets window.__ENV before the main bundle
|
||||
loads. Serving image templates this file at boot from BRIDGE_*
|
||||
env vars; bridge.config.ts reads window.__ENV first, then falls
|
||||
back to Vite's import.meta.env. One image, N envs.
|
||||
|
||||
Placed in <head> (and before the module script) so the synchronous
|
||||
parser-blocking load happens before any deferred module executes —
|
||||
the ordering is unambiguous regardless of how Vite reorganises
|
||||
the bundle.
|
||||
-->
|
||||
<script src="/__ENV.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bridge-root"></div>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// Runtime env for the bridge SPA. Overwritten at container boot by the
|
||||
// serving image's docker-entrypoint, or baked at build time.
|
||||
//
|
||||
// The SDK's bridge.config.ts reads window.__ENV before falling back to
|
||||
// Vite's build-time import.meta.env. This decouples the deployable image
|
||||
// from the environment it runs in: one image, N envs.
|
||||
window.__ENV = window.__ENV || {
|
||||
BRIDGE_API_HOST: '',
|
||||
BRIDGE_ENV: '',
|
||||
BRIDGE_CLIENT_ID: '',
|
||||
BRIDGE_IAM_ORG: '',
|
||||
BRIDGE_LOGO_URL: '',
|
||||
WC_PROJECT_ID: '',
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
// Lux-specific text/logos/colors live in the build.
|
||||
//
|
||||
// Source of truth for the Lux brand block: @luxfi/brand
|
||||
// (https://github.com/luxfi/brand). We read every Lux value from the
|
||||
// (https://github.com/luxfi/brand). Every Lux value is read from the
|
||||
// package's brand.json so a brand bump in the package propagates here
|
||||
// on the next install — no string copies, no drift. The JSON subpath
|
||||
// is used because the npm-published @luxfi/[email protected] omits its .d.ts
|
||||
@@ -13,21 +13,48 @@
|
||||
// literal types from it under `resolveJsonModule`.
|
||||
//
|
||||
// Logo source of truth: @luxfi/logo (https://github.com/luxfi/logo).
|
||||
// We import the canonical SVG generator and inline it as a data URL so
|
||||
// the build artifact has zero external dependencies for the brand mark.
|
||||
// The canonical SVG generator is inlined as a data URL so the build
|
||||
// artifact has zero external dependencies for the brand mark.
|
||||
//
|
||||
// Env resolution order (per key):
|
||||
// 1. window.__ENV — runtime, set by /__ENV.js at page load. One
|
||||
// image, N envs. Serving container templates
|
||||
// /__ENV.js from real env at boot.
|
||||
// 2. import.meta.env — build-time Vite fallback, used in dev and as
|
||||
// a safety net if the serving image fails to
|
||||
// template /__ENV.js.
|
||||
// 3. @luxfi/brand defaults — final fallback to the canonical Lux brand
|
||||
// package's brand.json values.
|
||||
|
||||
import type { BridgeConfig } from '@luxfi/bridge'
|
||||
import luxBrandJson from '@luxfi/brand/brand.json'
|
||||
import { getColorSVG } from '@luxfi/logo'
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
__ENV?: Partial<Record<string, string>>
|
||||
}
|
||||
}
|
||||
|
||||
const luxBrand = luxBrandJson.brand
|
||||
|
||||
const luxLogoDataUrl = `data:image/svg+xml;utf8,${encodeURIComponent(getColorSVG())}`
|
||||
const runtime: Partial<Record<string, string>> =
|
||||
(typeof window !== 'undefined' && window.__ENV) || {}
|
||||
const build = import.meta.env
|
||||
|
||||
// `import.meta.env` is Vite's standard env namespace; missing values fall back
|
||||
// to values read from @luxfi/brand (which in turn defaults to the production
|
||||
// Lux network).
|
||||
const env = import.meta.env
|
||||
/**
|
||||
* Look up a config value by key. Tries runtime (`window.__ENV`) first,
|
||||
* then build-time (`import.meta.env.VITE_*`), then the supplied fallback.
|
||||
*/
|
||||
const env = (key: string, fallback?: string): string | undefined => {
|
||||
const r = runtime[key]
|
||||
if (r) return r
|
||||
const b = build[`VITE_${key}`]
|
||||
if (b) return b
|
||||
return fallback
|
||||
}
|
||||
|
||||
const luxLogoDataUrl = `data:image/svg+xml;utf8,${encodeURIComponent(getColorSVG())}`
|
||||
|
||||
const fallbackApiHost = luxBrand.appDomain
|
||||
? `https://api.bridge.${luxBrand.appDomain}`
|
||||
@@ -37,13 +64,13 @@ const fallbackDocsUrl = luxBrand.docsDomain
|
||||
: 'https://docs.lux.network/bridge'
|
||||
|
||||
export const bridgeConfig: BridgeConfig = {
|
||||
apiHost: env.VITE_BRIDGE_API_HOST ?? fallbackApiHost,
|
||||
env: env.VITE_BRIDGE_ENV ?? 'mainnet',
|
||||
clientId: env.VITE_BRIDGE_CLIENT_ID,
|
||||
iamOrg: env.VITE_BRIDGE_IAM_ORG ?? 'lux',
|
||||
apiHost: env('BRIDGE_API_HOST', fallbackApiHost)!,
|
||||
env: env('BRIDGE_ENV', 'mainnet')!,
|
||||
clientId: env('BRIDGE_CLIENT_ID'),
|
||||
iamOrg: env('BRIDGE_IAM_ORG', 'lux'),
|
||||
brand: {
|
||||
name: `${luxBrand.shortName ?? 'Lux'} Bridge`,
|
||||
logoUrl: env.VITE_BRIDGE_LOGO_URL ?? luxLogoDataUrl,
|
||||
logoUrl: env('BRIDGE_LOGO_URL') || luxLogoDataUrl,
|
||||
primaryColor: luxBrand.primaryColor ?? '#000000',
|
||||
secondaryColor:
|
||||
luxBrand.theme?.dark?.accent1 ?? luxBrand.theme?.light?.accent1,
|
||||
|
||||
Vendored
+6
@@ -1,11 +1,17 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
// Build-time Vite envs. These are the fallback for the runtime
|
||||
// window.__ENV mechanism (see src/bridge.config.ts). Vite inlines
|
||||
// `import.meta.env.VITE_*` at build, so changing one after the
|
||||
// bundle is built does nothing — that's why we layer window.__ENV
|
||||
// (templated by the serving image at boot) on top.
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_BRIDGE_API_HOST?: string
|
||||
readonly VITE_BRIDGE_ENV?: string
|
||||
readonly VITE_BRIDGE_CLIENT_ID?: string
|
||||
readonly VITE_BRIDGE_IAM_ORG?: string
|
||||
readonly VITE_BRIDGE_LOGO_URL?: string
|
||||
readonly VITE_WC_PROJECT_ID?: string
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
|
||||
Reference in New Issue
Block a user