mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-10-18 19:30:27 +08:00
Allow overriding configuration at run-time
This commit is contained in:
@@ -42,24 +42,54 @@ There are several ways to deploy the UI publicly. Here are two common options:
|
||||
1. Fork this repository to create your own version
|
||||
2. Configure your Vercel account to deploy the forked repository
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
There's two ways to configure the UI:
|
||||
There are two ways to configure the UI: **at build time** and **at run time**.
|
||||
|
||||
**Create a `local.json` config file**
|
||||
### Build-Time Configuration
|
||||
|
||||
1. Copy [default.json][def] to a new file in the same folder called
|
||||
This method is recommended when deploying to static hosting platforms such
|
||||
as Vercel.
|
||||
|
||||
#### Option 1: Create a `local.json` file
|
||||
|
||||
1. Copy [`default.json`][def] to a new file in the same directory called
|
||||
`local.json`.
|
||||
2. Modify the properties in `local.json` to your preference.
|
||||
2. Modify the properties in `local.json` to suit your setup.
|
||||
|
||||
**Environment variables**
|
||||
#### Option 2: Use environment variables
|
||||
|
||||
1. Check [custom-environment-variables.json][env] for all available environment
|
||||
variables.
|
||||
2. Set the desired environment variables when building the UI.
|
||||
1. Refer to [`custom-environment-variables.json`][env] for a list of supported
|
||||
environment variables.
|
||||
2. Set the desired variables in your environment before building the UI.
|
||||
|
||||
> For advanced configuration options, refer to the [`node-config`][nco]
|
||||
> documentation.
|
||||
|
||||
|
||||
### Run-Time Configuration
|
||||
|
||||
This method is useful when the app is distributed as a precompiled static
|
||||
JS/HTML bundle, such as when installed via a package manager.
|
||||
|
||||
You can build the app in a mode that loads configuration dynamically from the
|
||||
server it's deployed to, instead of bundling it at build time.
|
||||
|
||||
To enable this behavior, set the environment variable `VITE_RUNTIME_CONFIG=true`
|
||||
during the build:
|
||||
|
||||
```bash
|
||||
VITE_RUNTIME_CONFIG=true npm run build
|
||||
```
|
||||
|
||||
This will inject a blocking script into the `index.html` that attempts to load
|
||||
the configuration from a pre-defined location (`/config.json`) on the server.
|
||||
|
||||
The config file must be served as static content and must be publicly accessible.
|
||||
The structure of the runtime `config.json` must match the shape of the
|
||||
application's base configuration defined in `config/default.json`.
|
||||
|
||||
> For advanced configuration options, have a look at the [`node-config`][nco]
|
||||
> package.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
import type { Config } from "./module.d.ts";
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line no-var, @typescript-eslint/naming-convention
|
||||
var __CONFIG__: Config;
|
||||
}
|
||||
|
||||
export {};
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import type { ZodIssue, ZodType, TypeOf } from "zod";
|
||||
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
import { satisfies } from "compare-versions";
|
||||
|
||||
export interface BaseUrl {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import type { ComponentProps } from "svelte";
|
||||
import type { ErrorParam } from "@app/lib/router/definitions";
|
||||
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
import Command from "./Command.svelte";
|
||||
import ExternalLink from "./ExternalLink.svelte";
|
||||
import IconLarge from "./IconLarge.svelte";
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import buildTimeConfig from "virtual:config";
|
||||
import mergeWith from "lodash/mergeWith";
|
||||
import { isArray } from "lodash";
|
||||
|
||||
const customMerge = <T>(objValue: T, srcValue: T): T | undefined => {
|
||||
if (isArray(objValue)) {
|
||||
return srcValue;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const config = mergeWith(
|
||||
{},
|
||||
buildTimeConfig,
|
||||
globalThis.__CONFIG__ || {},
|
||||
customMerge,
|
||||
) as typeof buildTimeConfig;
|
||||
|
||||
export default config;
|
||||
+1
-1
@@ -5,7 +5,7 @@ import { get, writable } from "svelte/store";
|
||||
|
||||
import * as mutexExecutor from "@app/lib/mutexExecutor";
|
||||
import * as utils from "@app/lib/utils";
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
import {
|
||||
repoRouteToPath,
|
||||
repoTitle,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
|
||||
import Command from "@app/components/Command.svelte";
|
||||
import ExternalLink from "@app/components/ExternalLink.svelte";
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import isEqual from "lodash/isEqual";
|
||||
import some from "lodash/some";
|
||||
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
import { HttpdClient } from "@http-client";
|
||||
import {
|
||||
addBookmark,
|
||||
|
||||
@@ -5,7 +5,7 @@ import storedWritable from "@app/lib/localStore";
|
||||
import { array, number, string, object } from "zod";
|
||||
import { get } from "svelte/store";
|
||||
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
|
||||
const seedSchema = object({
|
||||
hostname: string(),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { BaseUrl, Node, NodeStats } from "@http-client";
|
||||
import type { ErrorRoute, NotFoundRoute } from "@app/lib/router/definitions";
|
||||
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
import { HttpdClient } from "@http-client";
|
||||
import { ResponseError, ResponseParseError } from "@http-client/lib/fetcher";
|
||||
import { baseUrlToString, isLocal } from "@app/lib/utils";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { BaseUrl } from "@http-client";
|
||||
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
import { parseRepositoryId } from "@app/lib/utils";
|
||||
|
||||
import Button from "@app/components/Button.svelte";
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
} from "@http-client";
|
||||
import type { RepoRoute } from "./router";
|
||||
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
import { HttpdClient } from "@http-client";
|
||||
import { baseUrlToString } from "@app/lib/utils";
|
||||
import { groupCommits } from "@app/lib/commit";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
import debounce from "lodash/debounce";
|
||||
import { toClipboard } from "@app/lib/utils";
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import type {
|
||||
} from "@http-client";
|
||||
|
||||
import * as Syntax from "@app/lib/syntax";
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
import { HttpdClient } from "@http-client";
|
||||
import { ResponseError, ResponseParseError } from "@http-client/lib/fetcher";
|
||||
import { cached } from "@app/lib/cache";
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { BaseUrl, NodeIdentity, NodeStats } from "@http-client";
|
||||
import type { ErrorRoute, NotFoundRoute } from "@app/lib/router/definitions";
|
||||
|
||||
import * as utils from "@app/lib/utils";
|
||||
import config from "virtual:config";
|
||||
import config from "@app/lib/config";
|
||||
import { HttpdClient } from "@http-client";
|
||||
import { ResponseError, ResponseParseError } from "@http-client/lib/fetcher";
|
||||
import { handleError } from "@app/views/nodes/error";
|
||||
|
||||
@@ -27,6 +27,32 @@ export default defineConfig({
|
||||
},
|
||||
compilerOptions: { dev: process.env.NODE_ENV !== "production" },
|
||||
}),
|
||||
{
|
||||
name: "inject-config-loader",
|
||||
transformIndexHtml() {
|
||||
if (process.env.VITE_RUNTIME_CONFIG === "true") {
|
||||
return [
|
||||
{
|
||||
tag: "script",
|
||||
attrs: {
|
||||
type: "text/javascript",
|
||||
},
|
||||
children: `
|
||||
try {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "/config.json", false);
|
||||
xhr.send(null);
|
||||
window.__CONFIG__ = JSON.parse(xhr.responseText);
|
||||
} catch {
|
||||
console.warn("Couldn't load config.json from the server, using built-in fallback config.");
|
||||
}
|
||||
`,
|
||||
injectTo: "head-prepend",
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
server: {
|
||||
host: "localhost",
|
||||
|
||||
Reference in New Issue
Block a user