@owdproject/core 3.3.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +98 -0
- package/DESKTOP_KERNEL.md +232 -0
- package/MIGRATION_3.3.2.md +23 -0
- package/MIGRATION_3.4.md +126 -0
- package/PLAYGROUND.md +91 -0
- package/README.md +13 -80
- package/dist/module.d.mts +2 -2
- package/dist/module.json +3 -3
- package/dist/module.mjs +86 -99
- package/index.ts +6 -3
- package/kit/authoring.ts +340 -0
- package/kit/defineDesktopApp.ts +56 -0
- package/module.ts +76 -108
- package/package.json +70 -40
- package/runtime/components/{Desktop/Application/DesktopApplicationRender.vue → Application/DesktopCoreApplicationRender.vue} +2 -2
- package/runtime/components/{Desktop/Application/DesktopApplicationWindowsRender.vue → Application/DesktopCoreApplicationWindowsRender.vue} +1 -1
- package/runtime/components/core/DesktopCore.vue +43 -0
- package/runtime/components/{Desktop/Window/DesktopWindow.vue → window/DesktopCoreWindow.vue} +17 -6
- package/runtime/components/window/DesktopCoreWindowSnapHintsBase.vue +74 -0
- package/runtime/components/workspace/DesktopCoreWorkspaceEdgeHintsBase.vue +84 -0
- package/runtime/composables/useBlockNonInputContextMenu.ts +30 -0
- package/runtime/composables/useDesktopConfig.ts +8 -0
- package/runtime/composables/useDesktopDialogs.ts +16 -0
- package/runtime/composables/useDesktopExtension.ts +8 -0
- package/runtime/composables/useDesktopManager.ts +2 -0
- package/runtime/composables/useDesktopManifest.ts +17 -0
- package/runtime/composables/useDesktopSession.ts +27 -0
- package/runtime/composables/useDesktopShellIdentity.ts +99 -0
- package/runtime/composables/useDesktopShellOptions.ts +36 -0
- package/runtime/composables/useDesktopShellReady.ts +7 -0
- package/runtime/composables/useDesktopWorkArea.ts +93 -0
- package/runtime/composables/useTerminalManager.ts +102 -9
- package/runtime/composables/useToggleWindowMaximize.ts +35 -0
- package/runtime/composables/useWindowDragHandlers.ts +47 -0
- package/runtime/composables/useWindowSnapDrop.ts +112 -0
- package/runtime/composables/useWorkspaceEdgeDrop.ts +176 -0
- package/runtime/composables/useWorkspaceManager.ts +26 -0
- package/runtime/composables/useWorkspaceOverviewCapture.ts +92 -0
- package/runtime/composables/useWorkspaceOverviewLiveScale.ts +151 -0
- package/runtime/constants/desktopShellKeys.ts +12 -0
- package/runtime/constants/shellLayout.ts +5 -0
- package/runtime/dialogs/desktopDialogProvider.ts +73 -0
- package/runtime/internal/controllers/ApplicationController.ts +8 -2
- package/runtime/internal/controllers/WindowController.ts +93 -8
- package/runtime/plugins/01.desktop-shell-init.client.ts +28 -0
- package/runtime/plugins/02.desktop-register-desktop-apps.client.ts +2 -6
- package/runtime/stores/storeApplicationMeta.ts +2 -1
- package/runtime/stores/storeApplicationWindows.ts +2 -1
- package/runtime/stores/storeDesktop.ts +17 -57
- package/runtime/stores/storeDesktopDefaultApps.ts +2 -1
- package/runtime/stores/storeDesktopVolume.ts +2 -1
- package/runtime/stores/storeDesktopWindow.ts +20 -2
- package/runtime/stores/storeDesktopWorkspace.ts +31 -1
- package/runtime/stores/storeIds.ts +35 -0
- package/runtime/types/desktopMenu.ts +10 -0
- package/runtime/utils/initDesktopShell.ts +80 -0
- package/runtime/utils/migratePersistedStoreIds.ts +57 -0
- package/runtime/utils/utilApp.ts +0 -12
- package/runtime/utils/{captureElementToCanvas.ts → utilCaptureElementToCanvas.ts} +1 -1
- package/runtime/utils/utilDetectSnapZone.ts +57 -0
- package/runtime/utils/utilWindowLayout.ts +82 -0
- package/runtime/utils/utilWindowMaximizeLayout.ts +44 -0
- package/runtime/utils/utilWorkspaceWindows.ts +33 -0
- package/types/index.d.ts +125 -14
- package/bin/cli.js +0 -395
- package/bin/desktop.js +0 -5
- package/bin/lib/catalog.js +0 -293
- package/bin/lib/config.js +0 -109
- package/bin/lib/desktopConfig.js +0 -56
- package/bin/lib/generateTemplate.js +0 -389
- package/bin/lib/install.js +0 -408
- package/bin/lib/migrateModulePlayground.config.mjs +0 -164
- package/bin/lib/migrateModulePlayground.mjs +0 -313
- package/bin/lib/npmVersions.js +0 -124
- package/bin/lib/playgroundContext.js +0 -188
- package/bin/lib/scaffold.js +0 -197
- package/bin/lib/status.js +0 -289
- package/bin/lib/validateModule.js +0 -697
- package/bin/lib/workspace.js +0 -182
- package/bin/owd.js +0 -5
- package/bin/tui.js +0 -1379
- package/runtime/components/Desktop/Core/DesktopCore.vue +0 -90
- package/runtime/utils/explorerEntryPath.ts +0 -10
- package/runtime/utils/resolveDesktopConfigPath.ts +0 -52
- package/runtime/utils/splitDesktopUserConfig.ts +0 -85
- package/runtime/utils/utilDesktop.ts +0 -35
- package/runtime/utils/validateDesktopUserConfig.ts +0 -44
- /package/runtime/components/{Desktop/Background/DesktopBackground.vue → background/DesktopCoreBackground.vue} +0 -0
- /package/runtime/components/{Desktop/Time/DesktopTime.vue → time/DesktopCoreTime.vue} +0 -0
- /package/runtime/components/{Desktop/Window/DesktopWindowContent.vue → window/DesktopCoreWindowContent.vue} +0 -0
- /package/runtime/components/{Desktop/Window/DesktopWindowNav.vue → window/DesktopCoreWindowNav.vue} +0 -0
- /package/runtime/utils/{utilWindow.ts → utilWindowControllerAdapter.ts} +0 -0
package/kit/authoring.ts
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
defineNuxtModule,
|
|
6
|
+
installModule,
|
|
7
|
+
type NuxtModule,
|
|
8
|
+
} from '@nuxt/kit'
|
|
9
|
+
import type { Nuxt } from '@nuxt/schema'
|
|
10
|
+
import { defu } from 'defu'
|
|
11
|
+
|
|
12
|
+
/** Root `desktop.config.ts` helper — keep this file free of `import.meta` for jiti. */
|
|
13
|
+
export function defineDesktopConfig(config: DesktopConfig) {
|
|
14
|
+
return config
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Runtime validation for the object exported from `desktop.config.ts`
|
|
19
|
+
* (or legacy `owd.config.ts`).
|
|
20
|
+
*/
|
|
21
|
+
export function assertValidDesktopUserConfig(
|
|
22
|
+
config: unknown,
|
|
23
|
+
configFile = 'desktop.config.ts',
|
|
24
|
+
): void {
|
|
25
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`[@owdproject/core] ${configFile} must default-export a non-array object from defineDesktopConfig({ ... }).`,
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const c = config as Record<string, unknown>
|
|
32
|
+
|
|
33
|
+
if (c.theme != null && typeof c.theme !== 'string') {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`[@owdproject/core] ${configFile}: \`theme\` must be a string (npm package name of the theme module).`,
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (c.apps !== undefined) {
|
|
40
|
+
if (
|
|
41
|
+
!Array.isArray(c.apps) ||
|
|
42
|
+
!(c.apps as unknown[]).every((item) => typeof item === 'string')
|
|
43
|
+
) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`[@owdproject/core] ${configFile}: \`apps\` must be an array of strings (Nuxt module package names).`,
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (c.modules !== undefined) {
|
|
51
|
+
if (
|
|
52
|
+
!Array.isArray(c.modules) ||
|
|
53
|
+
!(c.modules as unknown[]).every((item) => typeof item === 'string')
|
|
54
|
+
) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`[@owdproject/core] ${configFile}: \`modules\` must be an array of strings (Nuxt module package names).`,
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const DESKTOP_CONFIG_FILENAME = 'desktop.config.ts'
|
|
63
|
+
export const LEGACY_DESKTOP_CONFIG_FILENAME = 'owd.config.ts'
|
|
64
|
+
|
|
65
|
+
export const LEGACY_CONFIG_DEPRECATION =
|
|
66
|
+
'[@owdproject/core] owd.config.ts is deprecated and kept only for backward compatibility; rename to desktop.config.ts (required from @owdproject/core 3.2).'
|
|
67
|
+
|
|
68
|
+
export type ResolvedDesktopConfigPath = {
|
|
69
|
+
path: string
|
|
70
|
+
file: string
|
|
71
|
+
legacy: boolean
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function resolveDesktopConfigPath(
|
|
75
|
+
rootDir: string,
|
|
76
|
+
): ResolvedDesktopConfigPath | null {
|
|
77
|
+
const desktopPath = join(rootDir, DESKTOP_CONFIG_FILENAME)
|
|
78
|
+
const legacyPath = join(rootDir, LEGACY_DESKTOP_CONFIG_FILENAME)
|
|
79
|
+
const hasDesktop = existsSync(desktopPath)
|
|
80
|
+
const hasLegacy = existsSync(legacyPath)
|
|
81
|
+
|
|
82
|
+
if (hasDesktop && hasLegacy) {
|
|
83
|
+
console.warn(
|
|
84
|
+
'[@owdproject/core] Both desktop.config.ts and owd.config.ts exist; using desktop.config.ts. Remove owd.config.ts.',
|
|
85
|
+
)
|
|
86
|
+
return { path: desktopPath, file: DESKTOP_CONFIG_FILENAME, legacy: false }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (hasDesktop) {
|
|
90
|
+
return { path: desktopPath, file: DESKTOP_CONFIG_FILENAME, legacy: false }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (hasLegacy) {
|
|
94
|
+
return {
|
|
95
|
+
path: legacyPath,
|
|
96
|
+
file: LEGACY_DESKTOP_CONFIG_FILENAME,
|
|
97
|
+
legacy: true,
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return null
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function warnLegacyDesktopConfig(
|
|
105
|
+
resolved: ResolvedDesktopConfigPath | null | undefined,
|
|
106
|
+
): void {
|
|
107
|
+
if (resolved?.legacy) {
|
|
108
|
+
console.warn(LEGACY_CONFIG_DEPRECATION)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Path used when creating or updating config from the CLI (always the new filename). */
|
|
113
|
+
export function desktopConfigWritePath(desktopDir: string): string {
|
|
114
|
+
return join(desktopDir, DESKTOP_CONFIG_FILENAME)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Nuxt top-level option names — warn if present in desktop.config (likely misconfiguration). */
|
|
118
|
+
const NUXT_OPTION_KEYS = new Set([
|
|
119
|
+
'ssr',
|
|
120
|
+
'devtools',
|
|
121
|
+
'vite',
|
|
122
|
+
'nitro',
|
|
123
|
+
'runtimeConfig',
|
|
124
|
+
'app',
|
|
125
|
+
'appConfig',
|
|
126
|
+
'css',
|
|
127
|
+
'plugins',
|
|
128
|
+
'hooks',
|
|
129
|
+
'extends',
|
|
130
|
+
'compatibilityDate',
|
|
131
|
+
'experimental',
|
|
132
|
+
'future',
|
|
133
|
+
'i18n',
|
|
134
|
+
'tailwindcss',
|
|
135
|
+
'primevue',
|
|
136
|
+
])
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Warn when desktop.config.ts contains keys that look like Nuxt options.
|
|
140
|
+
* Extension keys (fs, terminal, custom app namespaces) are intentionally not validated here.
|
|
141
|
+
*/
|
|
142
|
+
export function warnDesktopConfigKeys(
|
|
143
|
+
config: Record<string, unknown>,
|
|
144
|
+
configFile = 'desktop.config.ts',
|
|
145
|
+
): void {
|
|
146
|
+
for (const key of Object.keys(config)) {
|
|
147
|
+
if (NUXT_OPTION_KEYS.has(key)) {
|
|
148
|
+
console.warn(
|
|
149
|
+
`[@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, ... }).`,
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Writes a resolved extension namespace to `runtimeConfig.public.desktop[configKey]`.
|
|
157
|
+
* Used by {@link defineDesktopModule} after Nuxt merges inline options with module defaults.
|
|
158
|
+
*/
|
|
159
|
+
export function setDesktopExtensionConfig(
|
|
160
|
+
nuxt: Nuxt,
|
|
161
|
+
configKey: string,
|
|
162
|
+
resolved: Record<string, unknown>,
|
|
163
|
+
): void {
|
|
164
|
+
const pub = (nuxt.options.runtimeConfig.public ??= {}) as {
|
|
165
|
+
desktop?: Record<string, unknown>
|
|
166
|
+
}
|
|
167
|
+
const desktop = (pub.desktop ??= {})
|
|
168
|
+
desktop[configKey] = resolved
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Merges theme or module defaults into an extension namespace on `public.desktop`.
|
|
173
|
+
* User values from desktop.config win over `partial` (defu: partial fills undefined only).
|
|
174
|
+
*/
|
|
175
|
+
export function mergeDesktopExtensionConfig(
|
|
176
|
+
nuxt: Nuxt,
|
|
177
|
+
configKey: string,
|
|
178
|
+
partial: Record<string, unknown>,
|
|
179
|
+
): void {
|
|
180
|
+
const pub = (nuxt.options.runtimeConfig.public ??= {}) as {
|
|
181
|
+
desktop?: Record<string, unknown>
|
|
182
|
+
}
|
|
183
|
+
const desktop = (pub.desktop ??= {})
|
|
184
|
+
const existing = desktop[configKey]
|
|
185
|
+
const base =
|
|
186
|
+
existing && typeof existing === 'object' && !Array.isArray(existing)
|
|
187
|
+
? (existing as Record<string, unknown>)
|
|
188
|
+
: {}
|
|
189
|
+
desktop[configKey] = defu(partial, base)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
type ModuleLike = {
|
|
193
|
+
meta?: { configKey?: string }
|
|
194
|
+
default?: { meta?: { configKey?: string } }
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function readConfigKey(mod: ModuleLike | undefined): string | undefined {
|
|
198
|
+
const key = mod?.meta?.configKey ?? mod?.default?.meta?.configKey
|
|
199
|
+
return typeof key === 'string' && key.length > 0 ? key : undefined
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async function loadModuleDescriptor(
|
|
203
|
+
modulePath: string,
|
|
204
|
+
): Promise<ModuleLike | undefined> {
|
|
205
|
+
try {
|
|
206
|
+
const imported = await import(modulePath)
|
|
207
|
+
return (imported as { default?: ModuleLike }).default ?? imported
|
|
208
|
+
} catch (e: any) {
|
|
209
|
+
console.warn(`[@owdproject/core] Failed to load module descriptor for "${modulePath}":`, e.message || e)
|
|
210
|
+
return undefined
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Installs a desktop theme, module, or app package.
|
|
216
|
+
* When the package exposes `meta.configKey`, passes `desktop[configKey]` to `installModule`
|
|
217
|
+
* so Nuxt merges desktop.config with module defaults.
|
|
218
|
+
*/
|
|
219
|
+
export async function installDesktopPackage(
|
|
220
|
+
nuxt: Nuxt,
|
|
221
|
+
modulePath: string,
|
|
222
|
+
desktop?: Record<string, unknown>,
|
|
223
|
+
): Promise<void> {
|
|
224
|
+
const descriptor = await loadModuleDescriptor(modulePath)
|
|
225
|
+
const configKey = readConfigKey(descriptor)
|
|
226
|
+
|
|
227
|
+
if (configKey && desktop) {
|
|
228
|
+
const slice = desktop[configKey]
|
|
229
|
+
const inline =
|
|
230
|
+
slice && typeof slice === 'object' && !Array.isArray(slice)
|
|
231
|
+
? (slice as Record<string, unknown>)
|
|
232
|
+
: {}
|
|
233
|
+
await installModule(modulePath, inline)
|
|
234
|
+
return
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
await installModule(modulePath)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
type DesktopModuleMeta = {
|
|
241
|
+
name: string
|
|
242
|
+
configKey: string
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
type DesktopModuleDefinition = NuxtModule<
|
|
246
|
+
Record<string, unknown>,
|
|
247
|
+
Record<string, unknown>,
|
|
248
|
+
false
|
|
249
|
+
> & {
|
|
250
|
+
meta: DesktopModuleMeta
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Nuxt module wrapper for desktop apps and extension modules (`configKey` → desktop.config namespace).
|
|
255
|
+
* Publishes merged options to `runtimeConfig.public.desktop[configKey]` after setup runs.
|
|
256
|
+
*/
|
|
257
|
+
export function defineDesktopModule(
|
|
258
|
+
definition: DesktopModuleDefinition,
|
|
259
|
+
): ReturnType<typeof defineNuxtModule> {
|
|
260
|
+
const configKey = definition.meta.configKey
|
|
261
|
+
if (!configKey) {
|
|
262
|
+
throw new Error(
|
|
263
|
+
'[@owdproject/core] defineDesktopModule requires meta.configKey (e.g. "terminal", "fs").',
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const userSetup = definition.setup
|
|
268
|
+
|
|
269
|
+
return defineNuxtModule({
|
|
270
|
+
...definition,
|
|
271
|
+
async setup(options, nuxt) {
|
|
272
|
+
const pub = (nuxt.options.runtimeConfig.public ??= {}) as {
|
|
273
|
+
desktop?: Record<string, unknown>
|
|
274
|
+
}
|
|
275
|
+
const desktop = (pub.desktop ??= {})
|
|
276
|
+
const userConfig = desktop[configKey]
|
|
277
|
+
|
|
278
|
+
// Merge userConfig (wins) with options (defaults / inline)
|
|
279
|
+
const merged = defu(
|
|
280
|
+
userConfig && typeof userConfig === 'object' ? userConfig : {},
|
|
281
|
+
options as Record<string, unknown>,
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
// Mutate options in place so userSetup receives the fully merged options
|
|
285
|
+
Object.assign(options, merged)
|
|
286
|
+
|
|
287
|
+
// Set/update the merged config on public.desktop
|
|
288
|
+
desktop[configKey] = options
|
|
289
|
+
|
|
290
|
+
if (typeof userSetup === 'function') {
|
|
291
|
+
return userSetup(options, nuxt)
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
} as NuxtModule)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
type DesktopThemeDefinition = NuxtModule<
|
|
298
|
+
Record<string, unknown>,
|
|
299
|
+
Record<string, unknown>,
|
|
300
|
+
false
|
|
301
|
+
>
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Nuxt module wrapper for desktop themes.
|
|
305
|
+
* Merges theme shell defaults into `runtimeConfig.public.desktop` (user desktop.config wins).
|
|
306
|
+
*
|
|
307
|
+
* Tailwind content for theme Vue templates is registered via
|
|
308
|
+
* `@owdproject/kit-primevue/kit/registerTailwindPath` after installing kit-primevue.
|
|
309
|
+
*/
|
|
310
|
+
export function defineDesktopTheme(
|
|
311
|
+
definition: DesktopThemeDefinition,
|
|
312
|
+
): ReturnType<typeof defineNuxtModule> {
|
|
313
|
+
const userSetup = definition.setup
|
|
314
|
+
|
|
315
|
+
return defineNuxtModule({
|
|
316
|
+
...definition,
|
|
317
|
+
meta: {
|
|
318
|
+
...definition.meta,
|
|
319
|
+
configKey: 'desktop',
|
|
320
|
+
},
|
|
321
|
+
async setup(options, nuxt) {
|
|
322
|
+
const pub = (nuxt.options.runtimeConfig.public ??= {}) as {
|
|
323
|
+
desktop?: Record<string, unknown>
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Automatically merge userConfig (pub.desktop) with theme defaults (options)
|
|
327
|
+
pub.desktop = defu(
|
|
328
|
+
(pub.desktop ?? {}) as Record<string, unknown>,
|
|
329
|
+
options as Record<string, unknown>,
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
// Mutate options in place so userSetup receives the fully merged options
|
|
333
|
+
Object.assign(options, pub.desktop)
|
|
334
|
+
|
|
335
|
+
if (typeof userSetup === 'function') {
|
|
336
|
+
return userSetup(options, nuxt)
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
} as NuxtModule)
|
|
340
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { getActivePinia, setActivePinia } from 'pinia'
|
|
2
|
+
import type { Pinia } from 'pinia'
|
|
3
|
+
import { useApplicationManager } from '../runtime/composables/useApplicationManager'
|
|
4
|
+
|
|
5
|
+
const pendingDesktopApps: ApplicationConfig[] = []
|
|
6
|
+
|
|
7
|
+
let pluginPiniaInstance: Pinia | undefined
|
|
8
|
+
|
|
9
|
+
/** Set by desktop-shell-init; avoids importing nuxt/app during jiti config load. */
|
|
10
|
+
export function registerDesktopPluginPinia(pinia: Pinia | undefined) {
|
|
11
|
+
pluginPiniaInstance = pinia
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function resolveActivePinia() {
|
|
15
|
+
const active = getActivePinia()
|
|
16
|
+
if (active) return active
|
|
17
|
+
|
|
18
|
+
if (pluginPiniaInstance) {
|
|
19
|
+
setActivePinia(pluginPiniaInstance)
|
|
20
|
+
return pluginPiniaInstance
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return undefined
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let isBooted = false
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Register a desktop app. Queues until Pinia is active when theme/app plugins
|
|
30
|
+
* run before shell-init (legacy published apps using synchronous setup).
|
|
31
|
+
*/
|
|
32
|
+
export async function defineDesktopApp(config: ApplicationConfig) {
|
|
33
|
+
if (import.meta.server) return undefined
|
|
34
|
+
|
|
35
|
+
if (isBooted && resolveActivePinia()) {
|
|
36
|
+
const applicationManager = useApplicationManager()
|
|
37
|
+
return applicationManager.defineApp(config.id, config)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
pendingDesktopApps.push(config)
|
|
41
|
+
return undefined
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function flushPendingDesktopApps() {
|
|
45
|
+
isBooted = true
|
|
46
|
+
if (pendingDesktopApps.length === 0) return
|
|
47
|
+
|
|
48
|
+
if (!resolveActivePinia()) return
|
|
49
|
+
|
|
50
|
+
const queue = pendingDesktopApps.splice(0, pendingDesktopApps.length)
|
|
51
|
+
const applicationManager = useApplicationManager()
|
|
52
|
+
|
|
53
|
+
for (const config of queue) {
|
|
54
|
+
await applicationManager.defineApp(config.id, config)
|
|
55
|
+
}
|
|
56
|
+
}
|
package/module.ts
CHANGED
|
@@ -4,30 +4,53 @@ import {
|
|
|
4
4
|
addComponentsDir,
|
|
5
5
|
addImportsDir,
|
|
6
6
|
installModule,
|
|
7
|
-
addPlugin
|
|
7
|
+
addPlugin,
|
|
8
|
+
resolvePath
|
|
8
9
|
} from '@nuxt/kit'
|
|
9
10
|
import { defu } from 'defu'
|
|
10
|
-
import { assertValidDesktopUserConfig } from './runtime/utils/validateDesktopUserConfig'
|
|
11
11
|
import {
|
|
12
|
+
assertValidDesktopUserConfig,
|
|
13
|
+
installDesktopPackage,
|
|
12
14
|
resolveDesktopConfigPath,
|
|
15
|
+
warnDesktopConfigKeys,
|
|
13
16
|
warnLegacyDesktopConfig,
|
|
14
|
-
} from './
|
|
15
|
-
import { splitDesktopUserConfig } from './runtime/utils/splitDesktopUserConfig'
|
|
17
|
+
} from './kit/authoring'
|
|
16
18
|
import pkg from './package.json'
|
|
17
19
|
|
|
18
20
|
export default defineNuxtModule({
|
|
19
21
|
meta: {
|
|
20
22
|
name: 'desktop',
|
|
21
|
-
configKey: '
|
|
23
|
+
configKey: 'desktop',
|
|
22
24
|
},
|
|
23
25
|
defaults: {
|
|
24
26
|
theme: '@owdproject/theme-nova',
|
|
25
27
|
apps: [],
|
|
26
28
|
modules: [],
|
|
27
29
|
},
|
|
30
|
+
moduleDependencies: {
|
|
31
|
+
'@pinia/nuxt': {},
|
|
32
|
+
'@nuxt/fonts': {},
|
|
33
|
+
'@nuxt/icon': {
|
|
34
|
+
defaults: {
|
|
35
|
+
clientBundle: {
|
|
36
|
+
scan: true,
|
|
37
|
+
sizeLimitKb: 256,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
'@vueuse/nuxt': {},
|
|
42
|
+
'@nuxtjs/i18n': {},
|
|
43
|
+
},
|
|
28
44
|
async setup(_options, _nuxt) {
|
|
29
45
|
const { resolve } = createResolver(import.meta.url)
|
|
30
46
|
|
|
47
|
+
let resolvedNanoid: string | null = null
|
|
48
|
+
try {
|
|
49
|
+
resolvedNanoid = await resolvePath('nanoid', { url: import.meta.url })
|
|
50
|
+
} catch (e) {
|
|
51
|
+
// ignore
|
|
52
|
+
}
|
|
53
|
+
|
|
31
54
|
// Required for Nuxt 4 dev (playgrounds, module graphs): avoids
|
|
32
55
|
// "Vite Node IPC socket path not configured" when using @nuxt/kit pipelines.
|
|
33
56
|
_nuxt.options.experimental = {
|
|
@@ -52,6 +75,10 @@ export default defineNuxtModule({
|
|
|
52
75
|
|
|
53
76
|
warnLegacyDesktopConfig(resolvedConfig)
|
|
54
77
|
|
|
78
|
+
// Nuxt dev restart + ℹ log (same as nuxt.config.ts); avoid builder:watch + restart (silent / double).
|
|
79
|
+
_nuxt.options.watch ??= []
|
|
80
|
+
_nuxt.options.watch.push(resolvedConfig.path)
|
|
81
|
+
|
|
55
82
|
try {
|
|
56
83
|
clientConfig = (await import(resolvedConfig.path)).default
|
|
57
84
|
} catch (e) {
|
|
@@ -69,54 +96,51 @@ export default defineNuxtModule({
|
|
|
69
96
|
clientConfig.theme = '@owdproject/theme-nova'
|
|
70
97
|
}
|
|
71
98
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
apps: configApps,
|
|
75
|
-
modules: configModules,
|
|
76
|
-
desktopRuntime,
|
|
77
|
-
} = splitDesktopUserConfig(
|
|
78
|
-
clientConfig as Record<string, unknown>,
|
|
79
|
-
resolvedConfig.file,
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
clientConfig.theme = configTheme ?? clientConfig.theme
|
|
83
|
-
if (configApps) clientConfig.apps = configApps
|
|
84
|
-
if (configModules) clientConfig.modules = configModules
|
|
99
|
+
const configRecord = clientConfig as Record<string, unknown>
|
|
100
|
+
warnDesktopConfigKeys(configRecord, resolvedConfig.file)
|
|
85
101
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
102
|
+
const desktop = defu(configRecord, { coreVersion: pkg.version }) as Record<
|
|
103
|
+
string,
|
|
104
|
+
unknown
|
|
105
|
+
> & {
|
|
106
|
+
theme?: string
|
|
107
|
+
apps?: string[]
|
|
108
|
+
modules?: string[]
|
|
109
|
+
}
|
|
92
110
|
|
|
93
|
-
|
|
94
|
-
// published app plugins register on app:created.
|
|
95
|
-
await installModule('@pinia/nuxt')
|
|
111
|
+
_nuxt.options.runtimeConfig.public.desktop = desktop
|
|
96
112
|
|
|
97
113
|
{
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
114
|
+
if (desktop.theme) {
|
|
115
|
+
try {
|
|
116
|
+
await installDesktopPackage(_nuxt, desktop.theme, desktop)
|
|
117
|
+
} catch (e) {
|
|
118
|
+
const msg = e instanceof Error ? e.message : String(e)
|
|
119
|
+
console.warn(`[@owdproject/core] Warning: Could not load theme "${desktop.theme}". Details: ${msg}`)
|
|
120
|
+
}
|
|
102
121
|
}
|
|
103
122
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
123
|
+
if (Array.isArray(desktop.modules)) {
|
|
124
|
+
for (const modulePath of desktop.modules) {
|
|
125
|
+
try {
|
|
126
|
+
await installDesktopPackage(_nuxt, modulePath, desktop)
|
|
127
|
+
} catch (e) {
|
|
128
|
+
const msg = e instanceof Error ? e.message : String(e)
|
|
129
|
+
console.warn(`[@owdproject/core] Warning: Could not load module "${modulePath}". Details: ${msg}`)
|
|
130
|
+
}
|
|
109
131
|
}
|
|
110
132
|
}
|
|
111
133
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
134
|
+
if (Array.isArray(desktop.apps)) {
|
|
135
|
+
for (const appPath of desktop.apps) {
|
|
136
|
+
try {
|
|
137
|
+
await installDesktopPackage(_nuxt, appPath, desktop)
|
|
138
|
+
} catch (e) {
|
|
139
|
+
const msg = e instanceof Error ? e.message : String(e)
|
|
140
|
+
console.warn(`[@owdproject/core] Warning: Could not load app "${appPath}". Details: ${msg}`)
|
|
141
|
+
}
|
|
117
142
|
}
|
|
118
143
|
}
|
|
119
|
-
|
|
120
144
|
}
|
|
121
145
|
|
|
122
146
|
// assign runtimeConfig desktop prop to appConfig
|
|
@@ -124,71 +148,6 @@ export default defineNuxtModule({
|
|
|
124
148
|
// via useDesktopManager
|
|
125
149
|
_nuxt.options.appConfig.desktop = _nuxt.options.runtimeConfig.public.desktop
|
|
126
150
|
|
|
127
|
-
{
|
|
128
|
-
// install primevue
|
|
129
|
-
|
|
130
|
-
_nuxt.options.primevue = _nuxt.options.primevue || {}
|
|
131
|
-
_nuxt.options.primevue.options = _nuxt.options.primevue.options || {}
|
|
132
|
-
_nuxt.options.primevue.options.theme =
|
|
133
|
-
_nuxt.options.primevue.options.theme || {}
|
|
134
|
-
_nuxt.options.primevue.components =
|
|
135
|
-
_nuxt.options.primevue.components || {}
|
|
136
|
-
const include = _nuxt.options.primevue.components.include
|
|
137
|
-
if (include && include !== '*' && Array.isArray(include)) {
|
|
138
|
-
if (!include.includes('ConfirmDialog')) {
|
|
139
|
-
include.push('ConfirmDialog')
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
await installModule('@primevue/nuxt-module')
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
{
|
|
147
|
-
// install tailwind
|
|
148
|
-
|
|
149
|
-
const tailwindPaths =
|
|
150
|
-
_nuxt.options.runtimeConfig.app.owd?.tailwindPaths || []
|
|
151
|
-
tailwindPaths.push('./runtime/components/**/*.{vue,mjs,ts}') // Aggiungi sempre questo al core
|
|
152
|
-
|
|
153
|
-
_nuxt.options.tailwindcss = _nuxt.options.tailwindcss || {}
|
|
154
|
-
_nuxt.options.tailwindcss.config = _nuxt.options.tailwindcss.config || {}
|
|
155
|
-
// @ts-ignore
|
|
156
|
-
_nuxt.options.tailwindcss.config.content = tailwindPaths
|
|
157
|
-
|
|
158
|
-
await installModule('@nuxtjs/tailwindcss', {
|
|
159
|
-
viewer: false
|
|
160
|
-
})
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
{
|
|
164
|
-
// install @nuxt/fonts
|
|
165
|
-
|
|
166
|
-
await installModule('@nuxt/fonts')
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
{
|
|
170
|
-
// install @nuxt/icon
|
|
171
|
-
|
|
172
|
-
await installModule('@nuxt/icon', {
|
|
173
|
-
clientBundle: {
|
|
174
|
-
scan: true,
|
|
175
|
-
sizeLimitKb: 256
|
|
176
|
-
}
|
|
177
|
-
})
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
{
|
|
181
|
-
// install @vueuse/nuxt
|
|
182
|
-
|
|
183
|
-
await installModule('@vueuse/nuxt')
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
{
|
|
187
|
-
// install @nuxtjs/i18n
|
|
188
|
-
|
|
189
|
-
await installModule('@nuxtjs/i18n')
|
|
190
|
-
}
|
|
191
|
-
|
|
192
151
|
{
|
|
193
152
|
// configure scss for vite
|
|
194
153
|
|
|
@@ -199,6 +158,12 @@ export default defineNuxtModule({
|
|
|
199
158
|
viteConfig.css.preprocessorOptions.scss = {
|
|
200
159
|
api: 'modern-compiler'
|
|
201
160
|
}
|
|
161
|
+
|
|
162
|
+
viteConfig.optimizeDeps = viteConfig.optimizeDeps || {}
|
|
163
|
+
viteConfig.optimizeDeps.include = viteConfig.optimizeDeps.include || []
|
|
164
|
+
if (resolvedNanoid && !viteConfig.optimizeDeps.include.includes(resolvedNanoid)) {
|
|
165
|
+
viteConfig.optimizeDeps.include.push(resolvedNanoid)
|
|
166
|
+
}
|
|
202
167
|
})
|
|
203
168
|
}
|
|
204
169
|
|
|
@@ -213,7 +178,7 @@ export default defineNuxtModule({
|
|
|
213
178
|
|
|
214
179
|
addComponentsDir({
|
|
215
180
|
path: resolve('./runtime/components'),
|
|
216
|
-
prefix: '',
|
|
181
|
+
prefix: 'Desktop',
|
|
217
182
|
pathPrefix: false,
|
|
218
183
|
global: true
|
|
219
184
|
})
|
|
@@ -221,6 +186,9 @@ export default defineNuxtModule({
|
|
|
221
186
|
|
|
222
187
|
{
|
|
223
188
|
addPlugin(resolve('./runtime/plugins/resize.client.ts'))
|
|
189
|
+
addPlugin(
|
|
190
|
+
resolve('./runtime/plugins/01.desktop-shell-init.client.ts'),
|
|
191
|
+
)
|
|
224
192
|
addPlugin(
|
|
225
193
|
resolve('./runtime/plugins/02.desktop-register-desktop-apps.client.ts'),
|
|
226
194
|
)
|