Skip to content

Commit 67bf79a

Browse files
committed
feat(config): implement runtime configuration via json file
Signed-off-by: Zacharias Fragkiadakis <[email protected]>
1 parent 6c277ac commit 67bf79a

File tree

9 files changed

+75
-37
lines changed

9 files changed

+75
-37
lines changed

README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ feature set and not require its own database.
4141
You will need two domains, one for the Radicle Planning Boards and another for the Radicle Explorer.
4242

4343
1. Deploy the `radicle-planning-boards` repository
44-
- Set the `NUXT_PUBLIC_PARENT_ORIGIN` environment variable to your Radicle Explorer domain
44+
- Set the `NUXT_PUBLIC_HOST_APP_ORIGIN` environment variable to your Radicle Explorer domain
4545
2. Deploy the [radicle-interface-with-planning-boards](https://github.com/maninak/radicle-interface-with-planning-boards)
4646
repository
4747
- Update `src/config.json` with your Radicle Planning Boards domain e.g.
@@ -60,6 +60,23 @@ repository
6060
}
6161
```
6262

63+
### Configuring at runtime
64+
65+
You can overwrite `NUXT_PUBLIC_HOST_APP_ORIGIN` at runtime by creating a `config.json`
66+
file:
67+
68+
- inside the `.output` directory during deployment,
69+
- or the `public` directory during development
70+
71+
Example:
72+
73+
```json
74+
// config.json
75+
{
76+
"hostAppOrigin": "http://localhost:3080"
77+
}
78+
```
79+
6380
## Contributing
6481

6582
Please refer to the [Contribution Guide](CONTRIBUTING.md).

components/ColumnIssueCard.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const status = computed<ColumnCardStatus>(() => ({
2121
icon: statusIconMap[props.issue.state.status],
2222
}))
2323
24-
const hostAppBaseUrl = useHostAppBaseUrl()
24+
const hostAppOrigin = useHostAppOrigin()
2525
const isDebugging = useIsDebugging()
2626
2727
// TODO: zac reduce duplication between ColumnIssueCard and ColumnPatchCard
@@ -53,7 +53,7 @@ const highlights = computed(() => {
5353
const href = computed(() =>
5454
new URL(
5555
`/nodes/${route.params.node}/${route.params.rid}/issues/${props.issue.id}`,
56-
hostAppBaseUrl,
56+
hostAppOrigin,
5757
).toString(),
5858
)
5959
</script>

components/ColumnPatchCard.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const status = computed<ColumnCardStatus>(() => ({
2626
icon: statusIconMap[props.patch.state.status],
2727
}))
2828
29-
const hostAppBaseUrl = useHostAppBaseUrl()
29+
const hostAppOrigin = useHostAppOrigin()
3030
const isDebugging = useIsDebugging()
3131
3232
// TODO: zac reduce duplication between ColumnIssueCard and ColumnPatchCard
@@ -58,7 +58,7 @@ const highlights = computed(() => {
5858
const href = computed(() =>
5959
new URL(
6060
`/nodes/${route.params.node}/${route.params.rid}/patches/${props.patch.id}`,
61-
hostAppBaseUrl,
61+
hostAppOrigin,
6262
).toString(),
6363
)
6464
</script>

composables/use-host-app-base-url.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

composables/use-host-app-messaging.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,13 @@ const messageFromHostApp = v.union([
3131
export type MessageFromHostApp = v.InferInput<typeof messageFromHostApp>
3232

3333
export function useHostAppMessaging() {
34-
const { parentOrigin } = useRuntimeConfig().public
35-
3634
function onHostAppMessage<MessageType extends MessageFromHostApp['type']>(
3735
type: MessageType,
3836
callback: (message: Extract<MessageFromHostApp, { type: MessageType }>) => void,
3937
): void {
40-
useEventListener('message', (event) => {
41-
if (event.origin !== parentOrigin) {
38+
useEventListener('message', async (event) => {
39+
const { hostAppOrigin } = await resolveConfig()
40+
if (event.origin !== hostAppOrigin) {
4241
return
4342
}
4443

@@ -51,8 +50,9 @@ export function useHostAppMessaging() {
5150
})
5251
}
5352

54-
function notifyHostApp(message: MessageToHostApp): void {
55-
globalThis.window.parent.postMessage(message, parentOrigin)
53+
async function notifyHostApp(message: MessageToHostApp): Promise<void> {
54+
const { hostAppOrigin } = await resolveConfig()
55+
globalThis.window.parent.postMessage(message, hostAppOrigin)
5656
}
5757

5858
return {

composables/use-host-app-origin.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { defaultHostAppOrigin } from '~/constants/config'
2+
3+
export function useHostAppOrigin(): string {
4+
const { data: hostAppOrigin } = useAsyncData('config', resolveConfig, {
5+
transform: (config) => config.hostAppOrigin,
6+
})
7+
8+
return hostAppOrigin.value ?? defaultHostAppOrigin
9+
}

constants/config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
*/
66
export const defaultRadicleExplorerBaseUrl = 'https://explorer.radicle.gr/'
77

8+
/**
9+
* The default origin for the app hosting the iframe for this app
10+
*
11+
* Used for linking to the host app
12+
*/
13+
export const defaultHostAppOrigin = 'http://localhost:3080'
14+
815
/**
916
* The length of the hash value to keep when shortening it.
1017
*

nuxt.config.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import process from 'node:process'
2-
3-
const defaultParentOrigin = 'http://localhost:3080'
2+
import { defaultHostAppOrigin } from './constants/config'
43

54
// https://nuxt.com/docs/api/configuration/nuxt-config
65
export default defineNuxtConfig({
@@ -20,11 +19,7 @@ export default defineNuxtConfig({
2019
],
2120
experimental: { typedPages: true },
2221
devtools: { enabled: true },
23-
runtimeConfig: {
24-
public: {
25-
parentOrigin: defaultParentOrigin,
26-
},
27-
},
22+
runtimeConfig: { public: { hostAppOrigin: defaultHostAppOrigin } },
2823
app: {
2924
head: {
3025
bodyAttrs: {
@@ -40,7 +35,7 @@ export default defineNuxtConfig({
4035
contentSecurityPolicy: {
4136
'frame-ancestors': [
4237
"'self'",
43-
process.env?.['NUXT_PUBLIC_PARENT_ORIGIN'] ?? defaultParentOrigin,
38+
process.env?.['NUXT_PUBLIC_HOST_APP_ORIGIN'] ?? defaultHostAppOrigin,
4439
],
4540
},
4641
xFrameOptions: false,

utils/config.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import * as v from 'valibot'
2+
3+
interface Config {
4+
hostAppOrigin: string
5+
}
6+
7+
const jsonConfigSchema = v.object({ hostAppOrigin: v.optional(v.string()) })
8+
9+
let config: Config | undefined
10+
11+
export async function resolveConfig(): Promise<Config> {
12+
if (config) {
13+
return config
14+
}
15+
16+
const { hostAppOrigin: publicHostAppOrigin } = useRuntimeConfig().public
17+
const jsonConfig = await $fetch('/config.json').catch(() => undefined)
18+
const parseResult = v.safeParse(jsonConfigSchema, jsonConfig)
19+
20+
if (parseResult.success) {
21+
const hostAppOrigin = parseResult.output.hostAppOrigin ?? publicHostAppOrigin
22+
config = { hostAppOrigin }
23+
} else {
24+
config = { hostAppOrigin: publicHostAppOrigin }
25+
}
26+
27+
return config
28+
}

0 commit comments

Comments
 (0)