Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

fix(nitro, nuxi): add runtimeConfig types (for #config and useRuntimeConfig()) #1783

Merged
merged 14 commits into from
Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
108 changes: 108 additions & 0 deletions docs/content/3.docs/1.usage/5.runtime-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Runtime Config

Nuxt provides a runtime config API to share within App and API routes.

## Exposing runtime config

To expose config and environment variables to the rest of your app, you will need to define runtime configuration in your `nuxt.config` file, using either the [`publicRuntimeConfig` or `privateRuntimeConfig` options](/docs/directory-structure/nuxt.config#privateruntimeconfig). Based on whether you want it to be accessible on the client-side part of your app or not.

**Example:**

```ts [nuxt.config.ts]
export default defineNuxtConfig({
publicRuntimeConfig: {
API_BASE: '/api'
},
privateRunimeConfig: {
API_SECRET: '123'
}
})
```

When adding `API_BASE` to the `publicRuntimeConfig`, Nuxt adds it to the pages payload. This way we can universally access `API_BASE` in both server and browser.

### Environment Variables

The most common way to provide configuration, is using [Environment Variables](https://medium.com/chingu/an-introduction-to-environment-variables-and-how-to-use-them-f602f66d15fa).
Nuxt CLI has built-in [dotenv](https://github.com/motdotla/dotenv) support.

In addition to any process environment variables, if you have a `.env` file in your project root directory, it will be automatically loaded into `process.env` and accessible within your `nuxt.config` file and Modules.

**Example:**

```sh [.env]
BASE_URL=https://nuxtjs.org
API_SECRET=api_secret_token
```

```ts [nuxt.config.ts]
export default defineNuxtConfig({
publicRuntimeConfig: {
BASE_URL: process.env.BASE_URL
},
privateRuntimeConfig: {
API_SECRET: process.env.API_SECRET
}
})
```

**πŸ’‘ Tip:** While it is not necessary, by using identical runtime config names as env variables, you can easily override them in production using platform environment variables.

## Accessing runtime config

### Vue app

Within the Vue part of your Nuxt app, you will need to call `useRuntimeConfig()` to access the runtime config.

**Note:** Behavior is different between client side and server side:

- On Client-Side, only `publicRuntimeConfig` is available and object is writable + reactive
- On Server-Side, both `publicRuntimeConfig` and `privateRuntimeConfig` are merged and object is readonly to avoid context sharing

```vue
<template>
<div>
<div>Token: {{ config.API_AUTH_TOKEN }}</div>
</div>
</template>

<script setup>
const config = useRuntimeConfig()
</script>
```

**πŸ›‘ Security note:** Never use example above if `API_AUTH_TOKEN` is a private config. Even if you use `privateRuntimeConfig`, you have to be still careful you do not expose such config to either payload or html!

### API routes

Within the API routes, you can access runtime config by directly importing from virtual `#config`.

```ts
import config from '#config'

export default async () => {
const result = await $fetch('https://my.api.com/test', {
headers: {
Authorization: `Bearer ${config.API_AUTH_TOKEN}`
}
})
return result
}
```

### Typing runtime config

Currently it is possible to manually type your runtime config.

```ts [index.d.ts]
declare module '@nuxt/kit' {
interface PublicRuntimeConfig {
testConfig: string
}
interface PrivateRuntimeConfig {
token: string
}
}
// It is always important to ensure you import/export something when augmenting a type
export {}
```
5 changes: 0 additions & 5 deletions packages/bridge/src/nitro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,6 @@ export function setupNitroBridge () {
// Add typed route responses
nuxt.hook('prepare:types', (opts) => {
opts.references.push({ path: resolve(nuxt.options.buildDir, 'nitro.d.ts') })

for (const stub of ['#storage', '#assets']) {
// The `@nuxt/nitro` types will be overwritten by packages/nitro/types/shims.d.ts
opts.tsConfig.compilerOptions.paths[stub] = ['@nuxt/nitro']
}
})

// nuxt build/dev
Expand Down
3 changes: 2 additions & 1 deletion packages/bridge/src/runtime/composables.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { reactive, toRef, isReactive, Ref } from '@vue/composition-api'
import type VueRouter from 'vue-router'
import type { Route } from 'vue-router'
import type { RuntimeConfig } from '@nuxt/kit'
import { useNuxtApp } from './app'

export * from '@vue/composition-api'
Expand All @@ -16,7 +17,7 @@ export const useRuntimeConfig = () => {
if (!nuxtApp.$config) {
nuxtApp.$config = reactive(nuxtApp.nuxt2Context.app.$config)
}
return nuxtApp.$config
return nuxtApp.$config as RuntimeConfig
}

// Auto-import equivalents for `vue-router`
Expand Down
1 change: 1 addition & 0 deletions packages/kit/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ export * from './types/module'
export * from './types/nuxt'
export * from './types/components'
export * from './types/imports'
export * from './types/runtime-config'
5 changes: 5 additions & 0 deletions packages/kit/src/types/runtime-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface PublicRuntimeConfig extends Record<string, any> { }
export interface PrivateRuntimeConfig extends PublicRuntimeConfig { }

type _RuntimeConfig = PublicRuntimeConfig & Partial<PrivateRuntimeConfig>
export interface RuntimeConfig extends _RuntimeConfig { }
8 changes: 8 additions & 0 deletions packages/nitro/types/shims.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,11 @@ declare module '#assets' {
export function statAsset (id: string): Promise<AssetMeta>
export function getKeys() : Promise<string[]>
}

declare module '#config' {
import type { PublicRuntimeConfig, PrivateRuntimeConfig } from '@nuxt/kit'
export const privateConfig: PrivateRuntimeConfig
export const publicConfig: PublicRuntimeConfig
const runtimeConfig: PrivateRuntimeConfig & PublicRuntimeConfig
export default runtimeConfig
}
1 change: 1 addition & 0 deletions packages/nuxi/src/utils/prepare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const writeTypes = async (nuxt: Nuxt) => {
...nuxt.options.alias,
'#build': nuxt.options.buildDir,
// The `@nuxt/nitro` types will be overwritten by packages/nitro/types/shims.d.ts
'#config': '@nuxt/nitro',
'#storage': '@nuxt/nitro',
'#assets': '@nuxt/nitro'
}
Expand Down
3 changes: 2 additions & 1 deletion packages/nuxt3/src/app/nuxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { getCurrentInstance, reactive } from 'vue'
import type { App, VNode } from 'vue'
import { createHooks, Hookable } from 'hookable'
import type { RuntimeConfig } from '@nuxt/kit'
import { legacyPlugin, LegacyContext } from './legacy'

type NuxtMeta = {
Expand Down Expand Up @@ -192,7 +193,7 @@ export function useNuxtApp (): NuxtApp {
return vm.appContext.app.$nuxt
}

export function useRuntimeConfig (): Record<string, any> {
export function useRuntimeConfig (): RuntimeConfig {
return useNuxtApp().$config
}

Expand Down