@owdproject/core
Version:
Nuxt Desktop module for browser desktop experiences (windows, shell, apps)
204 lines (173 loc) • 5.82 kB
text/typescript
import {
defineNuxtModule,
createResolver,
addComponentsDir,
addImportsDir,
installModule,
addPlugin,
resolvePath
} from '@nuxt/kit'
import { defu } from 'defu'
import {
assertValidDesktopUserConfig,
installDesktopPackage,
resolveDesktopConfigPath,
warnDesktopConfigKeys,
warnLegacyDesktopConfig,
} from './kit/authoring'
import pkg from './package.json'
export default defineNuxtModule({
meta: {
name: 'desktop',
configKey: 'desktop',
},
defaults: {
theme: '@owdproject/theme-nova',
apps: [],
modules: [],
},
moduleDependencies: {
'@pinia/nuxt': {},
'@nuxt/fonts': {},
'@nuxt/icon': {
defaults: {
clientBundle: {
scan: true,
sizeLimitKb: 256,
},
},
},
'@vueuse/nuxt': {},
'@nuxtjs/i18n': {},
},
async setup(_options, _nuxt) {
const { resolve } = createResolver(import.meta.url)
let resolvedNanoid: string | null = null
try {
resolvedNanoid = await resolvePath('nanoid', { url: import.meta.url })
} catch (e) {
// ignore
}
// Required for Nuxt 4 dev (playgrounds, module graphs): avoids
// "Vite Node IPC socket path not configured" when using @nuxt/kit pipelines.
_nuxt.options.experimental = {
..._nuxt.options.experimental,
viteEnvironmentApi:
_nuxt.options.experimental?.viteEnvironmentApi ?? true,
}
_nuxt.options.runtimeConfig.public.desktop = {}
// get open web desktop config (desktop.config.ts; owd.config.ts legacy)
let clientConfig
const resolvedConfig = resolveDesktopConfigPath(_nuxt.options.rootDir)
if (!resolvedConfig) {
const hint =
'Create desktop.config.ts next to your Nuxt root (e.g. desktop/desktop.config.ts), export default defineDesktopConfig({ theme, apps, modules }).'
throw new Error(`[@owdproject/core] Cannot find desktop.config.ts in ${_nuxt.options.rootDir}. ${hint}`)
}
warnLegacyDesktopConfig(resolvedConfig)
// Nuxt dev restart + ℹ log (same as nuxt.config.ts); avoid builder:watch + restart (silent / double).
_nuxt.options.watch ??= []
_nuxt.options.watch.push(resolvedConfig.path)
try {
clientConfig = (await import(resolvedConfig.path)).default
} catch (e) {
const hint =
'Export default defineDesktopConfig({ theme, apps, modules }) from desktop.config.ts.'
throw new Error(
`[@owdproject/core] Cannot load ${resolvedConfig.file}. ${hint}`,
{ cause: e },
)
}
assertValidDesktopUserConfig(clientConfig, resolvedConfig.file)
if (!clientConfig.theme) {
clientConfig.theme = '@owdproject/theme-nova'
}
const configRecord = clientConfig as Record<string, unknown>
warnDesktopConfigKeys(configRecord, resolvedConfig.file)
const desktop = defu(configRecord, { coreVersion: pkg.version }) as Record<
string,
unknown
> & {
theme?: string
apps?: string[]
modules?: string[]
}
_nuxt.options.runtimeConfig.public.desktop = desktop
{
if (desktop.theme) {
try {
await installDesktopPackage(_nuxt, desktop.theme, desktop)
} catch (e) {
const msg = e instanceof Error ? e.message : String(e)
console.warn(`[@owdproject/core] Warning: Could not load theme "${desktop.theme}". Details: ${msg}`)
}
}
if (Array.isArray(desktop.modules)) {
for (const modulePath of desktop.modules) {
try {
await installDesktopPackage(_nuxt, modulePath, desktop)
} catch (e) {
const msg = e instanceof Error ? e.message : String(e)
console.warn(`[@owdproject/core] Warning: Could not load module "${modulePath}". Details: ${msg}`)
}
}
}
if (Array.isArray(desktop.apps)) {
for (const appPath of desktop.apps) {
try {
await installDesktopPackage(_nuxt, appPath, desktop)
} catch (e) {
const msg = e instanceof Error ? e.message : String(e)
console.warn(`[@owdproject/core] Warning: Could not load app "${appPath}". Details: ${msg}`)
}
}
}
}
// assign runtimeConfig desktop prop to appConfig
// to make it overwritable by components later
// via useDesktopManager
_nuxt.options.appConfig.desktop = _nuxt.options.runtimeConfig.public.desktop
{
// configure scss for vite
_nuxt.hook('vite:extendConfig', (viteConfig) => {
viteConfig.css = viteConfig.css || {}
viteConfig.css.preprocessorOptions =
viteConfig.css.preprocessorOptions || {}
viteConfig.css.preprocessorOptions.scss = {
api: 'modern-compiler'
}
viteConfig.optimizeDeps = viteConfig.optimizeDeps || {}
viteConfig.optimizeDeps.include = viteConfig.optimizeDeps.include || []
if (resolvedNanoid && !viteConfig.optimizeDeps.include.includes(resolvedNanoid)) {
viteConfig.optimizeDeps.include.push(resolvedNanoid)
}
})
}
{
// add css
_nuxt.options.css.push('sanitize.css')
}
{
// add components
addComponentsDir({
path: resolve('./runtime/components'),
prefix: 'Desktop',
pathPrefix: false,
global: true
})
}
{
addPlugin(resolve('./runtime/plugins/resize.client.ts'))
addPlugin(
resolve('./runtime/plugins/01.desktop-shell-init.client.ts'),
)
addPlugin(
resolve('./runtime/plugins/02.desktop-register-desktop-apps.client.ts'),
)
// add other files
addImportsDir(resolve('./runtime/composables'))
addImportsDir(resolve('./runtime/stores'))
addImportsDir(resolve('./runtime/utils'))
}
}
})