refactor: env config (#769)
parent
9d5dc1bc3d
commit
f892722220
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import buildInfo from 'virtual:build-info'
|
import { buildInfo } from 'virtual:build-info'
|
||||||
|
|
||||||
const timeAgoOptions = useTimeAgoOptions()
|
const timeAgoOptions = useTimeAgoOptions()
|
||||||
|
|
||||||
|
@ -35,10 +35,10 @@ function toggleDark() {
|
||||||
<span v-else>
|
<span v-else>
|
||||||
{{ $t('nav.built_at', [$d(buildTimeDate, 'shortDate')]) }}
|
{{ $t('nav.built_at', [$d(buildTimeDate, 'shortDate')]) }}
|
||||||
</span>
|
</span>
|
||||||
<template v-if="buildInfo.version">
|
·
|
||||||
·
|
<!-- TODO click version to show changelog -->
|
||||||
v{{ buildInfo.version }}
|
<span v-if="buildInfo.env === 'release'">v{{ buildInfo.version }}</span>
|
||||||
</template>
|
<span v-else>{{ buildInfo.env }}</span>
|
||||||
<template v-if="buildInfo.commit && buildInfo.branch !== 'release'">
|
<template v-if="buildInfo.commit && buildInfo.branch !== 'release'">
|
||||||
·
|
·
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const env = useRuntimeConfig().public.env
|
import { buildInfo } from 'virtual:build-info'
|
||||||
const sub = env === 'local' ? 'dev' : env === 'staging' ? 'preview' : 'alpha'
|
|
||||||
|
const { env } = buildInfo
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -17,7 +18,7 @@ const sub = env === 'local' ? 'dev' : env === 'staging' ? 'preview' : 'alpha'
|
||||||
>
|
>
|
||||||
<img :alt="$t('app_logo')" src="/logo.svg" shrink-0 aspect="1/1" sm:h-8 xl:h-10 class="rtl-flip">
|
<img :alt="$t('app_logo')" src="/logo.svg" shrink-0 aspect="1/1" sm:h-8 xl:h-10 class="rtl-flip">
|
||||||
<div hidden xl:block>
|
<div hidden xl:block>
|
||||||
{{ $t('app_name') }} <sup text-sm italic text-secondary mt-1>{{ sub }}</sup>
|
{{ $t('app_name') }} <sup text-sm italic text-secondary mt-1>{{ env === 'release' ? 'alpha' : env }}</sup>
|
||||||
</div>
|
</div>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
import { pwaInfo } from 'virtual:pwa-info'
|
import { pwaInfo } from 'virtual:pwa-info'
|
||||||
import type { Link } from '@unhead/schema'
|
import type { Link } from '@unhead/schema'
|
||||||
import type { Directions } from 'vue-i18n-routing'
|
import type { Directions } from 'vue-i18n-routing'
|
||||||
|
import { buildInfo } from 'virtual:build-info'
|
||||||
import { APP_NAME } from '~/constants'
|
import { APP_NAME } from '~/constants'
|
||||||
import type { LocaleObject } from '#i18n'
|
import type { LocaleObject } from '#i18n'
|
||||||
|
|
||||||
export function setupPageHeader() {
|
export function setupPageHeader() {
|
||||||
const isDev = process.dev
|
|
||||||
const isPreview = useRuntimeConfig().public.env === 'staging'
|
|
||||||
|
|
||||||
const i18n = useI18n()
|
const i18n = useI18n()
|
||||||
|
|
||||||
const link: Link[] = []
|
const link: Link[] = []
|
||||||
|
@ -42,7 +40,13 @@ export function setupPageHeader() {
|
||||||
lang: () => i18n.locale.value,
|
lang: () => i18n.locale.value,
|
||||||
dir: () => localeMap[i18n.locale.value] ?? 'auto',
|
dir: () => localeMap[i18n.locale.value] ?? 'auto',
|
||||||
},
|
},
|
||||||
titleTemplate: title => `${title ? `${title} | ` : ''}${APP_NAME}${isDev ? ' (dev)' : isPreview ? ' (preview)' : ''}`,
|
titleTemplate: (title) => {
|
||||||
|
let titleTemplate = title ? `${title} | ` : ''
|
||||||
|
titleTemplate += APP_NAME
|
||||||
|
if (buildInfo.env !== 'release')
|
||||||
|
titleTemplate += ` (${buildInfo.env})`
|
||||||
|
return titleTemplate
|
||||||
|
},
|
||||||
link,
|
link,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import Git from 'simple-git'
|
||||||
|
import { isDevelopment } from 'std-env'
|
||||||
|
|
||||||
|
export { version } from '../package.json'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Environment variable `PULL_REQUEST` provided by Netlify.
|
||||||
|
* @see {@link https://docs.netlify.com/configure-builds/environment-variables/#git-metadata}
|
||||||
|
*
|
||||||
|
* Whether triggered by a GitHub PR
|
||||||
|
*/
|
||||||
|
export const isPR = process.env.PULL_REQUEST === 'true'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Environment variable `CONTEXT` provided by Netlify.
|
||||||
|
* @see {@link https://docs.netlify.com/configure-builds/environment-variables/#build-metadata}
|
||||||
|
*
|
||||||
|
* Whether triggered by PR, `deploy-preview` or `dev`.
|
||||||
|
*/
|
||||||
|
export const isPreview = isPR || process.env.CONTEXT === 'deploy-preview' || process.env.CONTEXT === 'dev'
|
||||||
|
|
||||||
|
const git = Git()
|
||||||
|
export const getGitInfo = async () => {
|
||||||
|
const branch = await git.revparse(['--abbrev-ref', 'HEAD'])
|
||||||
|
const commit = await git.revparse(['HEAD'])
|
||||||
|
return { branch, commit }
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getEnv = async () => {
|
||||||
|
const { commit, branch } = await getGitInfo()
|
||||||
|
const env = isDevelopment
|
||||||
|
? 'dev'
|
||||||
|
: isPreview
|
||||||
|
? 'preview'
|
||||||
|
: branch === 'main'
|
||||||
|
? 'main'
|
||||||
|
: 'release'
|
||||||
|
return { commit, branch, env } as const
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
import { isCI, isDevelopment } from 'std-env'
|
import { isCI, isDevelopment } from 'std-env'
|
||||||
import type { VitePWANuxtOptions } from '../modules/pwa/types'
|
import type { VitePWANuxtOptions } from '../modules/pwa/types'
|
||||||
|
import { APP_NAME } from '../constants'
|
||||||
const isPreview = process.env.PULL_REQUEST === 'true'
|
import { getEnv } from './env'
|
||||||
|
|
||||||
export const pwa: VitePWANuxtOptions = {
|
export const pwa: VitePWANuxtOptions = {
|
||||||
mode: isCI ? 'production' : 'development',
|
mode: isCI ? 'production' : 'development',
|
||||||
|
@ -13,33 +13,37 @@ export const pwa: VitePWANuxtOptions = {
|
||||||
strategies: 'injectManifest',
|
strategies: 'injectManifest',
|
||||||
injectRegister: false,
|
injectRegister: false,
|
||||||
includeManifestIcons: false,
|
includeManifestIcons: false,
|
||||||
manifest: {
|
manifest: async () => {
|
||||||
scope: '/',
|
const { env } = await getEnv()
|
||||||
id: '/',
|
const envName = `${env !== 'release' ? '' : ` (${env})`}`
|
||||||
name: `Elk${isCI ? isPreview ? ' (preview)' : '' : ' (dev)'}`,
|
return {
|
||||||
short_name: `Elk${isCI ? isPreview ? ' (preview)' : '' : ' (dev)'}`,
|
scope: '/',
|
||||||
description: `A nimble Mastodon Web Client${isCI ? isPreview ? ' (preview)' : '' : ' (development)'}`,
|
id: '/',
|
||||||
theme_color: '#ffffff',
|
name: `${APP_NAME}${envName}`,
|
||||||
icons: [
|
short_name: `${APP_NAME}${envName}`,
|
||||||
{
|
description: `A nimble Mastodon Web Client${envName}`,
|
||||||
src: 'pwa-192x192.png',
|
theme_color: '#ffffff',
|
||||||
sizes: '192x192',
|
icons: [
|
||||||
type: 'image/png',
|
{
|
||||||
},
|
src: 'pwa-192x192.png',
|
||||||
{
|
sizes: '192x192',
|
||||||
src: 'pwa-512x512.png',
|
type: 'image/png',
|
||||||
sizes: '512x512',
|
},
|
||||||
type: 'image/png',
|
{
|
||||||
},
|
src: 'pwa-512x512.png',
|
||||||
/*
|
sizes: '512x512',
|
||||||
{
|
type: 'image/png',
|
||||||
src: 'logo.svg',
|
},
|
||||||
sizes: '250x250',
|
/*
|
||||||
type: 'image/png',
|
{
|
||||||
purpose: 'any maskable',
|
src: 'logo.svg',
|
||||||
},
|
sizes: '250x250',
|
||||||
*/
|
type: 'image/png',
|
||||||
],
|
purpose: 'any maskable',
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
],
|
||||||
|
}
|
||||||
},
|
},
|
||||||
injectManifest: {
|
injectManifest: {
|
||||||
globPatterns: ['**/*.{js,json,css,html,txt,svg,png,ico,webp,woff,woff2,ttf,eot,otf,wasm}'],
|
globPatterns: ['**/*.{js,json,css,html,txt,svg,png,ico,webp,woff,woff2,ttf,eot,otf,wasm}'],
|
||||||
|
|
|
@ -1,20 +1,23 @@
|
||||||
import { addVitePlugin, defineNuxtModule } from '@nuxt/kit'
|
import { addVitePlugin, defineNuxtModule } from '@nuxt/kit'
|
||||||
import Git from 'simple-git'
|
import { getEnv, version } from '../config/env'
|
||||||
import { version } from '../package.json'
|
|
||||||
import type { BuildInfo } from '~/types'
|
import type { BuildInfo } from '~/types'
|
||||||
|
|
||||||
export default defineNuxtModule({
|
export default defineNuxtModule({
|
||||||
meta: {
|
meta: {
|
||||||
name: 'elk:build-info',
|
name: 'elk:build-info',
|
||||||
},
|
},
|
||||||
async setup() {
|
async setup(_options, nuxt) {
|
||||||
const git = Git()
|
const { env, commit, branch } = await getEnv()
|
||||||
|
nuxt.options.runtimeConfig.public.env = env
|
||||||
|
|
||||||
const buildInfo: BuildInfo = {
|
const buildInfo: BuildInfo = {
|
||||||
version,
|
version,
|
||||||
time: +Date.now(),
|
time: +Date.now(),
|
||||||
commit: await git.revparse(['HEAD']),
|
commit,
|
||||||
branch: await git.revparse(['--abbrev-ref', 'HEAD']),
|
branch,
|
||||||
|
env,
|
||||||
}
|
}
|
||||||
|
|
||||||
addVitePlugin({
|
addVitePlugin({
|
||||||
name: 'elk:build-info',
|
name: 'elk:build-info',
|
||||||
resolveId(id) {
|
resolveId(id) {
|
||||||
|
@ -23,7 +26,7 @@ export default defineNuxtModule({
|
||||||
},
|
},
|
||||||
load(id) {
|
load(id) {
|
||||||
if (id === 'virtual:build-info')
|
if (id === 'virtual:build-info')
|
||||||
return `export default ${JSON.stringify(buildInfo, null, 2)}`
|
return `export const buildInfo = ${JSON.stringify(buildInfo, null, 2)}`
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { defineNuxtModule } from '@nuxt/kit'
|
import { defineNuxtModule } from '@nuxt/kit'
|
||||||
import type { VitePluginPWAAPI } from 'vite-plugin-pwa'
|
import type { VitePWAOptions, VitePluginPWAAPI } from 'vite-plugin-pwa'
|
||||||
import { VitePWA } from 'vite-plugin-pwa'
|
import { VitePWA } from 'vite-plugin-pwa'
|
||||||
import type { Plugin } from 'vite'
|
import type { Plugin } from 'vite'
|
||||||
import type { VitePWANuxtOptions } from './types'
|
import type { VitePWANuxtOptions } from './types'
|
||||||
|
@ -32,14 +32,17 @@ export default defineNuxtModule<VitePWANuxtOptions>({
|
||||||
if (plugin)
|
if (plugin)
|
||||||
throw new Error('Remove vite-plugin-pwa plugin from Vite Plugins entry in Nuxt config file!')
|
throw new Error('Remove vite-plugin-pwa plugin from Vite Plugins entry in Nuxt config file!')
|
||||||
})
|
})
|
||||||
nuxt.hook('vite:extendConfig', (viteInlineConfig, { isClient }) => {
|
nuxt.hook('vite:extendConfig', async (viteInlineConfig, { isClient }) => {
|
||||||
viteInlineConfig.plugins = viteInlineConfig.plugins || []
|
viteInlineConfig.plugins = viteInlineConfig.plugins || []
|
||||||
const plugin = viteInlineConfig.plugins.find(p => p && typeof p === 'object' && 'name' in p && p.name === 'vite-plugin-pwa')
|
const plugin = viteInlineConfig.plugins.find(p => p && typeof p === 'object' && 'name' in p && p.name === 'vite-plugin-pwa')
|
||||||
if (plugin)
|
if (plugin)
|
||||||
throw new Error('Remove vite-plugin-pwa plugin from Vite Plugins entry in Nuxt config file!')
|
throw new Error('Remove vite-plugin-pwa plugin from Vite Plugins entry in Nuxt config file!')
|
||||||
|
const resolvedOptions: Partial<VitePWAOptions> = {
|
||||||
configurePWAOptions(options, nuxt)
|
...options,
|
||||||
const plugins = VitePWA(options)
|
manifest: options.manifest ? await options.manifest() : undefined,
|
||||||
|
}
|
||||||
|
configurePWAOptions(resolvedOptions, nuxt)
|
||||||
|
const plugins = VitePWA(resolvedOptions)
|
||||||
viteInlineConfig.plugins.push(plugins)
|
viteInlineConfig.plugins.push(plugins)
|
||||||
if (isClient)
|
if (isClient)
|
||||||
vitePwaClientPlugin = plugins.find(p => p.name === 'vite-plugin-pwa') as Plugin
|
vitePwaClientPlugin = plugins.find(p => p.name === 'vite-plugin-pwa') as Plugin
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import type { VitePWAOptions } from 'vite-plugin-pwa'
|
import type { ManifestOptions, VitePWAOptions } from 'vite-plugin-pwa'
|
||||||
|
import type { Overwrite } from '../../types/utils'
|
||||||
|
|
||||||
export interface VitePWANuxtOptions extends Partial<VitePWAOptions> {}
|
export type VitePWANuxtOptions = Overwrite<Partial<VitePWAOptions>, {
|
||||||
|
manifest?: () => Promise<Partial<ManifestOptions>>
|
||||||
|
}>
|
||||||
|
|
||||||
declare module '@nuxt/schema' {
|
declare module '@nuxt/schema' {
|
||||||
interface NuxtConfig {
|
interface NuxtConfig {
|
||||||
|
|
|
@ -3,9 +3,9 @@ import Inspect from 'vite-plugin-inspect'
|
||||||
import { isCI, isDevelopment } from 'std-env'
|
import { isCI, isDevelopment } from 'std-env'
|
||||||
import { i18n } from './config/i18n'
|
import { i18n } from './config/i18n'
|
||||||
import { pwa } from './config/pwa'
|
import { pwa } from './config/pwa'
|
||||||
|
import { isPreview } from './config/env'
|
||||||
|
|
||||||
const { resolve } = createResolver(import.meta.url)
|
const { resolve } = createResolver(import.meta.url)
|
||||||
const isPreview = process.env.PULL_REQUEST === 'true' || process.env.CONTEXT === 'deploy-preview' || process.env.CONTEXT === 'dev'
|
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
typescript: {
|
typescript: {
|
||||||
|
@ -90,7 +90,7 @@ export default defineNuxtConfig({
|
||||||
inviteToken: '',
|
inviteToken: '',
|
||||||
},
|
},
|
||||||
public: {
|
public: {
|
||||||
env: isCI ? isPreview ? 'staging' : 'production' : 'local',
|
env: '', // set in build-info module
|
||||||
pwaEnabled: !isDevelopment || process.env.VITE_DEV_PWA === 'true',
|
pwaEnabled: !isDevelopment || process.env.VITE_DEV_PWA === 'true',
|
||||||
translateApi: '',
|
translateApi: '',
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import buildInfo from 'virtual:build-info'
|
import { buildInfo } from 'virtual:build-info'
|
||||||
|
|
||||||
let showCommit = $ref(false)
|
let showCommit = $ref(buildInfo.env !== 'release' && buildInfo.env !== 'dev')
|
||||||
const builtTime = useFormattedDateTime(buildInfo.time)
|
const builtTime = useFormattedDateTime(buildInfo.time)
|
||||||
|
|
||||||
const handleShowCommit = () => {
|
const handleShowCommit = () => {
|
||||||
|
@ -35,8 +35,8 @@ const handleShowCommit = () => {
|
||||||
>
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div font-mono>
|
<div font-mono>
|
||||||
v{{ buildInfo.version }}
|
<span>{{ buildInfo.env === 'release' ? `v${buildInfo.version}` : buildInfo.env }}</span>
|
||||||
<span v-if="showCommit">({{ buildInfo.commit.slice(0, 7) }})</span>
|
<span v-if="showCommit"> ({{ buildInfo.commit.slice(0, 7) }})</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</SettingsItem>
|
</SettingsItem>
|
||||||
|
|
|
@ -39,7 +39,7 @@ async function fetchAppInfo(origin: string, server: string) {
|
||||||
const app: AppInfo = await $fetch(`https://${server}/api/v1/apps`, {
|
const app: AppInfo = await $fetch(`https://${server}/api/v1/apps`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: {
|
body: {
|
||||||
client_name: APP_NAME + (config.public.env === 'local' ? ' (dev)' : ''),
|
client_name: APP_NAME + (config.public.env !== 'release' ? ` (${config.public.env})` : ''),
|
||||||
website: 'https://elk.zone',
|
website: 'https://elk.zone',
|
||||||
redirect_uris: getRedirectURI(origin, server),
|
redirect_uris: getRedirectURI(origin, server),
|
||||||
scopes: 'read write follow push',
|
scopes: 'read write follow push',
|
||||||
|
|
|
@ -4,6 +4,5 @@
|
||||||
|
|
||||||
declare module 'virtual:build-info' {
|
declare module 'virtual:build-info' {
|
||||||
import type { BuildInfo } from '~/types'
|
import type { BuildInfo } from '~/types'
|
||||||
const buildInfo: BuildInfo
|
export const buildInfo: BuildInfo
|
||||||
export default buildInfo
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,7 @@ export interface BuildInfo {
|
||||||
commit: string
|
commit: string
|
||||||
time: number
|
time: number
|
||||||
branch: string
|
branch: string
|
||||||
|
env: 'preview' | 'main' | 'dev' | 'release'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FontSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
export type FontSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||||
|
|
Loading…
Reference in New Issue