@owdproject/core
Version:
Nuxt Desktop module for browser desktop experiences (windows, shell, apps)
255 lines (250 loc) • 8.86 kB
JavaScript
import { installModule, defineNuxtModule, createResolver, resolvePath, addComponentsDir, addPlugin, addImportsDir } from '@nuxt/kit';
import { defu } from 'defu';
import { existsSync } from 'node:fs';
import { join } from 'node:path';
function assertValidDesktopUserConfig(config, configFile = "desktop.config.ts") {
if (!config || typeof config !== "object" || Array.isArray(config)) {
throw new Error(
`[@owdproject/core] ${configFile} must default-export a non-array object from defineDesktopConfig({ ... }).`
);
}
const c = config;
if (c.theme != null && typeof c.theme !== "string") {
throw new Error(
`[@owdproject/core] ${configFile}: \`theme\` must be a string (npm package name of the theme module).`
);
}
if (c.apps !== void 0) {
if (!Array.isArray(c.apps) || !c.apps.every((item) => typeof item === "string")) {
throw new Error(
`[@owdproject/core] ${configFile}: \`apps\` must be an array of strings (Nuxt module package names).`
);
}
}
if (c.modules !== void 0) {
if (!Array.isArray(c.modules) || !c.modules.every((item) => typeof item === "string")) {
throw new Error(
`[@owdproject/core] ${configFile}: \`modules\` must be an array of strings (Nuxt module package names).`
);
}
}
}
const DESKTOP_CONFIG_FILENAME = "desktop.config.ts";
const LEGACY_DESKTOP_CONFIG_FILENAME = "owd.config.ts";
const LEGACY_CONFIG_DEPRECATION = "[@owdproject/core] owd.config.ts is deprecated and kept only for backward compatibility; rename to desktop.config.ts (required from @owdproject/core 3.2).";
function resolveDesktopConfigPath(rootDir) {
const desktopPath = join(rootDir, DESKTOP_CONFIG_FILENAME);
const legacyPath = join(rootDir, LEGACY_DESKTOP_CONFIG_FILENAME);
const hasDesktop = existsSync(desktopPath);
const hasLegacy = existsSync(legacyPath);
if (hasDesktop && hasLegacy) {
console.warn(
"[@owdproject/core] Both desktop.config.ts and owd.config.ts exist; using desktop.config.ts. Remove owd.config.ts."
);
return { path: desktopPath, file: DESKTOP_CONFIG_FILENAME, legacy: false };
}
if (hasDesktop) {
return { path: desktopPath, file: DESKTOP_CONFIG_FILENAME, legacy: false };
}
if (hasLegacy) {
return {
path: legacyPath,
file: LEGACY_DESKTOP_CONFIG_FILENAME,
legacy: true
};
}
return null;
}
function warnLegacyDesktopConfig(resolved) {
if (resolved?.legacy) {
console.warn(LEGACY_CONFIG_DEPRECATION);
}
}
const NUXT_OPTION_KEYS = /* @__PURE__ */ new Set([
"ssr",
"devtools",
"vite",
"nitro",
"runtimeConfig",
"app",
"appConfig",
"css",
"plugins",
"hooks",
"extends",
"compatibilityDate",
"experimental",
"future",
"i18n",
"tailwindcss",
"primevue"
]);
function warnDesktopConfigKeys(config, configFile = "desktop.config.ts") {
for (const key of Object.keys(config)) {
if (NUXT_OPTION_KEYS.has(key)) {
console.warn(
`[@owdproject/core] ${configFile}: key "${key}" looks like a Nuxt option and is ignored for _nuxt.options. Move it to nuxt.config.ts; shell values belong under defineDesktopConfig({ systemBar, workspaces, ... }).`
);
}
}
}
function readConfigKey(mod) {
const key = mod?.meta?.configKey ?? mod?.default?.meta?.configKey;
return typeof key === "string" && key.length > 0 ? key : void 0;
}
async function loadModuleDescriptor(modulePath) {
try {
const imported = await import(modulePath);
return imported.default ?? imported;
} catch (e) {
console.warn(`[@owdproject/core] Failed to load module descriptor for "${modulePath}":`, e.message || e);
return void 0;
}
}
async function installDesktopPackage(nuxt, modulePath, desktop) {
const descriptor = await loadModuleDescriptor(modulePath);
const configKey = readConfigKey(descriptor);
if (configKey && desktop) {
const slice = desktop[configKey];
const inline = slice && typeof slice === "object" && !Array.isArray(slice) ? slice : {};
await installModule(modulePath, inline);
return;
}
await installModule(modulePath);
}
const version = "3.4.0";
const pkg = {
version: version};
const module$1 = 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 = null;
try {
resolvedNanoid = await resolvePath("nanoid", { url: import.meta.url });
} catch (e) {
}
_nuxt.options.experimental = {
..._nuxt.options.experimental,
viteEnvironmentApi: _nuxt.options.experimental?.viteEnvironmentApi ?? true
};
_nuxt.options.runtimeConfig.public.desktop = {};
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.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;
warnDesktopConfigKeys(configRecord, resolvedConfig.file);
const desktop = defu(configRecord, { coreVersion: pkg.version });
_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}`);
}
}
}
}
_nuxt.options.appConfig.desktop = _nuxt.options.runtimeConfig.public.desktop;
{
_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);
}
});
}
{
_nuxt.options.css.push("sanitize.css");
}
{
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")
);
addImportsDir(resolve("./runtime/composables"));
addImportsDir(resolve("./runtime/stores"));
addImportsDir(resolve("./runtime/utils"));
}
}
});
export { module$1 as default };