@owdproject/core 3.1.4-beta.0 → 3.2.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.
Files changed (64) hide show
  1. package/README.md +6 -6
  2. package/bin/cli.js +395 -0
  3. package/bin/desktop.js +5 -0
  4. package/bin/lib/catalog.js +293 -0
  5. package/bin/lib/config.js +109 -0
  6. package/bin/lib/desktopConfig.js +56 -0
  7. package/bin/lib/generateTemplate.js +389 -0
  8. package/bin/lib/install.js +408 -0
  9. package/bin/lib/migrateModulePlayground.config.mjs +164 -0
  10. package/bin/lib/migrateModulePlayground.mjs +313 -0
  11. package/bin/lib/npmVersions.js +124 -0
  12. package/bin/lib/playgroundContext.js +188 -0
  13. package/bin/lib/scaffold.js +197 -0
  14. package/bin/lib/status.js +289 -0
  15. package/bin/lib/validateModule.js +683 -0
  16. package/bin/lib/workspace.js +182 -0
  17. package/bin/owd.js +2 -25
  18. package/bin/tui.js +1379 -0
  19. package/dist/module.d.mts +13 -0
  20. package/dist/module.json +9 -0
  21. package/dist/module.mjs +219 -0
  22. package/dist/types.d.mts +7 -0
  23. package/module.ts +53 -19
  24. package/package.json +78 -22
  25. package/runtime/components/Core/Application/CoreApplicationRender.vue +3 -1
  26. package/runtime/components/Core/Application/CoreApplicationWindowsRender.vue +28 -7
  27. package/runtime/components/Core/Desktop/CoreDesktop.vue +11 -7
  28. package/runtime/components/Core/Window/CoreWindow.vue +45 -9
  29. package/runtime/components/Core/Window/CoreWindowNav.vue +26 -8
  30. package/runtime/composables/useApplicationEntries.ts +1 -1
  31. package/runtime/composables/useApplicationManager.ts +282 -4
  32. package/runtime/composables/useDesktopManager.ts +46 -4
  33. package/runtime/composables/useOwdDialogs.ts +13 -0
  34. package/runtime/composables/useTerminalManager.ts +62 -3
  35. package/runtime/composables/useWorkspaceOverview.ts +41 -0
  36. package/runtime/core/controllers/ApplicationController.ts +120 -30
  37. package/runtime/core/controllers/WindowController.ts +5 -10
  38. package/runtime/dialogs/owdDialogProvider.ts +81 -0
  39. package/runtime/plugins/01.owd-dialogs-fallback.ts +15 -0
  40. package/runtime/stores/storeApplicationMeta.ts +56 -12
  41. package/runtime/stores/storeDesktop.ts +79 -0
  42. package/runtime/stores/storeDesktopDefaultApps.ts +53 -0
  43. package/runtime/stores/storeDesktopExplorer.ts +74 -0
  44. package/runtime/stores/storeDesktopWorkspace.ts +14 -2
  45. package/runtime/utils/captureElementToCanvas.ts +21 -0
  46. package/runtime/utils/explorerEntryPath.ts +10 -0
  47. package/runtime/utils/resolveDesktopConfigPath.ts +52 -0
  48. package/runtime/utils/validateOwdUserConfig.ts +44 -0
  49. package/types/index.d.ts +64 -12
  50. package/CHANGELOG.md +0 -25
  51. package/project.json +0 -4
  52. package/runtime/composables/useClipboardFs.ts +0 -25
  53. package/runtime/core/managers/ApplicationManager.ts +0 -281
  54. package/runtime/core/managers/DesktopManager.ts +0 -47
  55. package/runtime/core/managers/TerminalManager.ts +0 -48
  56. package/runtime/stores/storeApplication.ts +0 -235
  57. package/test/basic.test.ts +0 -15
  58. package/test/fixtures/basic/app.vue +0 -5
  59. package/test/fixtures/basic/nuxt.config.ts +0 -5
  60. package/test/fixtures/basic/package.json +0 -5
  61. package/tsconfig.app.json +0 -31
  62. package/tsconfig.json +0 -12
  63. package/tsconfig.spec.json +0 -37
  64. package/vitest.config.ts +0 -24
package/README.md CHANGED
@@ -51,22 +51,22 @@ Thanks to Tailwind and PrimeVue, you can create custom themes from scratch and e
51
51
 
52
52
  Discover apps by searching the [owd-apps](https://github.com/topics/owd-apps) tag on GitHub.
53
53
 
54
- For example, to install the To-do app:
54
+ For example, to add the To-do app:
55
55
 
56
56
  ```bash
57
- owd install-app @owdproject/app-todo
57
+ desktop add app-todo
58
58
  ```
59
59
 
60
- This will install the package and automatically register it in your desktop configuration.
60
+ Shipped with `@owdproject/core` (`bin/desktop.js`). The `owd` binary is a deprecated alias.
61
61
 
62
62
  ### 🧩 Install a module
63
63
 
64
64
  Discover modules by searching the [owd-modules](https://github.com/topics/owd-modules) tag on GitHub.
65
65
 
66
- For example, to install the session persistence module:
66
+ For example, to add Pinia persistence backed by IndexedDB (`idb-keyval`):
67
67
 
68
68
  ```bash
69
- owd install-module @owdproject/module-pinia-localforage
69
+ desktop add module-pinia-idb
70
70
  ```
71
71
 
72
72
  ### 🖥️ Install a theme
@@ -77,7 +77,7 @@ Each theme provides a unique look and feel while maintaining consistent function
77
77
  Discover themes by searching the [owd-themes](https://github.com/topics/owd-themes) tag on GitHub.
78
78
 
79
79
  ```bash
80
- owd install-theme @owdproject/theme-gnome
80
+ desktop add theme-gnome
81
81
  ```
82
82
 
83
83
  ## Sponsors
package/bin/cli.js ADDED
@@ -0,0 +1,395 @@
1
+ import { spawn } from 'node:child_process'
2
+ import { runDevForeground } from './lib/status.js'
3
+ import { existsSync } from 'node:fs'
4
+ import { join } from 'node:path'
5
+ import getopts from 'getopts'
6
+ import {
7
+ resolveSource,
8
+ printPlan,
9
+ printNextSteps,
10
+ runWorkspaceInstall,
11
+ runNpmInstall,
12
+ } from './lib/install.js'
13
+ import { findWorkspaceRoot, inferKind } from './lib/workspace.js'
14
+ import { resolveDevTarget } from './lib/playgroundContext.js'
15
+ import { scaffoldProject } from './lib/scaffold.js'
16
+
17
+ const SCOPE = '@owdproject/'
18
+
19
+ /** @type {Record<string, { configKey: string, workspaceDir: string, nx: string, label: string }>} */
20
+ const KINDS = {
21
+ app: {
22
+ label: 'app',
23
+ configKey: 'apps',
24
+ workspaceDir: 'apps',
25
+ nx: 'desktop:install-app',
26
+ },
27
+ module: {
28
+ label: 'module',
29
+ configKey: 'modules',
30
+ workspaceDir: 'packages',
31
+ nx: 'desktop:install-module',
32
+ },
33
+ theme: {
34
+ label: 'theme',
35
+ configKey: 'theme',
36
+ workspaceDir: 'themes',
37
+ nx: 'desktop:install-theme',
38
+ },
39
+ }
40
+
41
+ const LEGACY_COMMANDS = {
42
+ 'install-app': 'app',
43
+ 'install-module': 'module',
44
+ 'install-theme': 'theme',
45
+ }
46
+
47
+ /** @type {string} */
48
+ let commandName = 'desktop'
49
+
50
+ function buildHelp(name) {
51
+ return `
52
+ ${name} — add apps, modules, and themes to your Open Web Desktop
53
+
54
+ USAGE
55
+ ${name} Open the control panel (interactive TUI)
56
+ ${name} dev [--playground] Start dev server (auto-detects module playground)
57
+
58
+ CONTROL PANEL (TUI)
59
+ m Open command menu (all actions)
60
+ s Start the Nuxt dev server
61
+ x Stop the Nuxt dev server
62
+ R Reboot the Nuxt dev server (stop + start)
63
+ w Save catalog/theme changes to desktop.config.ts
64
+ i Open in-app docs (when module-docs is installed)
65
+ d Toggle User (npm) / Dev (git clone) install mode
66
+ g Settings (GitHub username for fork clones)
67
+ r Refresh package list from GitHub
68
+ b Run pnpm run generate
69
+ q / Esc Quit
70
+ ${name} init [dir] Create a new OWD project (then opens the control panel)
71
+ ${name} add <package> [options]
72
+ ${name} add <kind> <name> [options]
73
+ ${name} validate [path...] Check Nuxt module + playground layout
74
+ ${name} template [--dry-run] [--check] Regenerate client/template/ (maintainers)
75
+
76
+ TEMPLATE (monorepo maintainers)
77
+ ${name} template Write template/ from blueprint + desktop/ + latest npm versions
78
+ ${name} template --dry-run Show planned @owdproject/* and starter versions
79
+ ${name} template --check Fail if committed template/ differs (CI)
80
+
81
+ VALIDATE
82
+ ${name} validate Validate cwd package, or all apps/themes/modules at repo root
83
+ ${name} validate . Validate explicit package directory
84
+ ${name} validate apps Validate every @owdproject/* module under apps/
85
+ --json Machine-readable output
86
+ --strict Treat warnings as failures
87
+ --smoke Run dev:prepare + nuxt build playground (slow, CI)
88
+
89
+ INSTALL MODES
90
+ User (default) npm registry — for end users and generated projects
91
+ Dev clone into apps/, packages/, or themes/ in the monorepo
92
+
93
+ EXAMPLES
94
+ pnpm ${name} # control panel
95
+ pnpm ${name} dev # monorepo desktop (from repo root)
96
+ cd apps/app-about && pnpm ${name} dev # app-about playground
97
+ pnpm ${name} dev --playground # force playground when cwd is in a module
98
+ ${name} init my-desktop # scaffold + pnpm install + control panel
99
+ ${name} add app-todo --npm
100
+ ${name} add app-todo --dev
101
+ ${name} add module-persistence --from dxlliv
102
+
103
+ KINDS (optional — inferred from the package name)
104
+ app app-* → apps/
105
+ module module-* → packages/ (kit-* and *-template are not listed in the control panel)
106
+ theme theme-* → themes/
107
+
108
+ OPTIONS
109
+ --playground Start the module playground dev server (when cwd is inside an @owdproject/* package with playground/)
110
+ --from <source> Git source (user, user/repo, or URL)
111
+ --branch <name> Git branch to clone
112
+ --npm Install from npm (default when --from is omitted)
113
+ --dev, --workspace Clone from github.com/owdproject/<package>
114
+ --dry-run Print the plan without changing anything
115
+ -h, --help Show this help
116
+
117
+ --from <source>
118
+ (omit) npm registry (default)
119
+ npm npm registry
120
+ owdproject Clone official repo (monorepo only)
121
+ <github-user> Clone github.com/<user>/<package> (your fork)
122
+ <user>/<repo> Explicit GitHub repo
123
+ <git-url> Full clone URL
124
+
125
+ LEGACY (still supported)
126
+ ${name} install-app @owdproject/app-todo
127
+ → prefer: ${name} add app-todo
128
+ `
129
+ }
130
+
131
+ async function openControlPanel(name) {
132
+ const { runTui } = await import('./tui.js')
133
+ await runTui(name)
134
+ }
135
+
136
+ function fail(message, hint) {
137
+ console.error(`\n✗ ${message}`)
138
+ if (hint) console.error(` ${hint}`)
139
+ console.error(`\nRun \`${commandName} --help\` for usage.\n`)
140
+ process.exit(1)
141
+ }
142
+
143
+ function warn(message) {
144
+ console.warn(`\n⚠ ${message}\n`)
145
+ }
146
+
147
+ /**
148
+ * @param {string} input
149
+ * @param {string | undefined} explicitKind
150
+ */
151
+ function normalizePackage(input, explicitKind) {
152
+ let raw = input.trim()
153
+ if (raw.startsWith(SCOPE)) raw = raw.slice(SCOPE.length)
154
+
155
+ if (!raw) {
156
+ fail('Package name is required.', `Example: ${commandName} add app-todo`)
157
+ }
158
+
159
+ const kind = explicitKind ?? inferKind(raw)
160
+
161
+ if (explicitKind) {
162
+ const prefixes = {
163
+ app: 'app-',
164
+ theme: 'theme-',
165
+ module: ['module-', 'kit-'],
166
+ }
167
+ const expected = prefixes[explicitKind]
168
+ const list = Array.isArray(expected) ? expected : [expected]
169
+ if (!list.some((p) => raw.startsWith(p))) {
170
+ raw = `${list[0]}${raw}`
171
+ }
172
+ }
173
+
174
+ return { pkgName: `${SCOPE}${raw}`, shortName: raw, kind }
175
+ }
176
+
177
+ function mapLegacyFlags(parsed) {
178
+ const { dev, workspace, fork, repo, branch, from, npm } = parsed
179
+ let mappedFrom = from
180
+ let mappedNpm = npm
181
+ const forceDev = dev || workspace
182
+
183
+ if (fork || repo) {
184
+ warn('`--fork` and `--repo` are deprecated — use `--from` instead.')
185
+ mappedFrom = repo || fork
186
+ }
187
+ if (forceDev && !mappedFrom && !mappedNpm) {
188
+ mappedFrom = 'owdproject'
189
+ }
190
+ if (mappedNpm) mappedFrom = 'npm'
191
+
192
+ return { from: mappedFrom, branch, npm: mappedNpm, dev: forceDev }
193
+ }
194
+
195
+ function parseAddArgs(positionals) {
196
+ const kindNames = Object.keys(KINDS)
197
+ if (positionals.length === 0) {
198
+ fail('Missing package name.', `Example: ${commandName} add app-todo`)
199
+ }
200
+
201
+ if (kindNames.includes(positionals[0])) {
202
+ const kind = positionals[0]
203
+ const name = positionals[1]
204
+ if (!name) {
205
+ fail(`Missing name for kind "${kind}".`, `Example: ${commandName} add ${kind} todo`)
206
+ }
207
+ return normalizePackage(name, kind)
208
+ }
209
+
210
+ return normalizePackage(positionals[0])
211
+ }
212
+
213
+ function parseLegacyInstall(cmd, positionals) {
214
+ const kind = LEGACY_COMMANDS[cmd]
215
+ const raw = positionals[0]
216
+ if (!raw) {
217
+ fail('Missing package name.', `Example: ${commandName} ${cmd} ${SCOPE}app-todo`)
218
+ }
219
+ warn(`\`${cmd}\` is deprecated — use \`${commandName} add …\` instead.`)
220
+ return normalizePackage(raw, kind)
221
+ }
222
+
223
+ /**
224
+ * @param {string} name CLI binary name (`desktop` or deprecated `owd`)
225
+ * @param {string[]} argv Arguments (without node and script path)
226
+ * @param {{ deprecated?: boolean }} [options]
227
+ */
228
+ export async function runCli(name, argv, options = {}) {
229
+ commandName = name
230
+
231
+ if (options.deprecated) {
232
+ warn('The `owd` command is deprecated. Use `desktop` instead.')
233
+ }
234
+
235
+ const parsed = getopts(argv, {
236
+ alias: { h: 'help', b: 'branch' },
237
+ boolean: ['help', 'npm', 'dry-run', 'dev', 'workspace', 'playground', 'json', 'strict', 'smoke', 'check'],
238
+ string: ['from', 'branch', 'fork', 'repo'],
239
+ })
240
+
241
+ const { _, help, npm: npmFlag } = parsed
242
+ const dryRun = parsed['dry-run'] === true
243
+ const { from, branch, npm: npmFromLegacy, dev: devFlag } = mapLegacyFlags(parsed)
244
+ const useNpm = npmFlag || npmFromLegacy || (!from && !devFlag)
245
+
246
+ if (help || _[0] === 'help') {
247
+ console.log(buildHelp(name))
248
+ process.exit(0)
249
+ }
250
+
251
+ const cmd = _[0]
252
+
253
+ if (cmd === 'init') {
254
+ const projectDir = (_[1] || 'owd-client').trim()
255
+ const cwd = process.cwd()
256
+
257
+ if (findWorkspaceRoot(cwd)) {
258
+ fail(
259
+ 'Already inside an OWD workspace.',
260
+ `Use \`${name}\` to manage this project, or run init from a parent directory.`,
261
+ )
262
+ }
263
+
264
+ try {
265
+ await scaffoldProject({ dir: projectDir, cwd, commandName: name })
266
+ } catch (error) {
267
+ fail(error.message ?? String(error))
268
+ }
269
+ return
270
+ }
271
+
272
+ const workspaceRoot = findWorkspaceRoot()
273
+
274
+ if (cmd === 'dev') {
275
+ if (!workspaceRoot) {
276
+ fail(
277
+ 'Not inside an OWD workspace.',
278
+ 'Run from the client repo, or try: desktop · desktop add <package>',
279
+ )
280
+ }
281
+ const forcePlayground = parsed.playground === true
282
+ const devTarget = resolveDevTarget(process.cwd(), workspaceRoot, { forcePlayground })
283
+ if (forcePlayground && !devTarget) {
284
+ fail(
285
+ 'No @owdproject module with playground/desktop.config.ts found from this directory.',
286
+ 'Run from an app/theme/module package (e.g. apps/app-about), or omit --playground for the monorepo desktop.',
287
+ )
288
+ }
289
+ runDevForeground(devTarget)
290
+ return
291
+ }
292
+
293
+ if (cmd === 'validate') {
294
+ const { runValidateCli, formatValidationReport } = await import('./lib/validateModule.js')
295
+ const strict = parsed.strict === true
296
+ const json = parsed.json === true
297
+ const smoke = parsed.smoke === true
298
+ const paths = _.slice(1).map(String)
299
+ const { exitCode, results } = runValidateCli(paths, {
300
+ workspaceRoot,
301
+ json,
302
+ strict,
303
+ smoke,
304
+ })
305
+ for (const result of results) {
306
+ console.log(formatValidationReport(result, { json }))
307
+ if (!json) console.log('')
308
+ }
309
+ process.exit(exitCode)
310
+ }
311
+
312
+ if (cmd === 'template') {
313
+ if (!workspaceRoot) {
314
+ fail(
315
+ 'Not inside an OWD workspace.',
316
+ `Run from the client monorepo root to regenerate template/.`,
317
+ )
318
+ }
319
+ const { runGenerateTemplateCli } = await import('./lib/generateTemplate.js')
320
+ await runGenerateTemplateCli({
321
+ workspaceRoot,
322
+ dryRun: parsed['dry-run'] === true,
323
+ check: parsed.check === true,
324
+ })
325
+ return
326
+ }
327
+
328
+ if (!cmd) {
329
+ if (!workspaceRoot) {
330
+ fail(
331
+ 'Not inside an OWD workspace.',
332
+ 'Run from the client repo, or try: desktop · desktop add <package>',
333
+ )
334
+ }
335
+ await openControlPanel(name)
336
+ return
337
+ }
338
+
339
+ if (cmd === 'ui') {
340
+ fail('The `ui` subcommand was removed.', `Use \`${name}\` to open the control panel.`)
341
+ }
342
+
343
+ if (!workspaceRoot) {
344
+ fail(
345
+ 'Not inside an OWD workspace.',
346
+ 'Run from the client repo (needs pnpm-workspace.yaml + nx.json), or use a generated project with the same layout.',
347
+ )
348
+ }
349
+
350
+ let pkgInfo
351
+
352
+ if (cmd === 'add') {
353
+ pkgInfo = parseAddArgs(_.slice(1))
354
+ } else if (LEGACY_COMMANDS[cmd]) {
355
+ pkgInfo = parseLegacyInstall(cmd, _.slice(1))
356
+ } else {
357
+ fail(`Unknown command: ${cmd}`, `Use \`${name}\`, \`${name} dev\`, or \`${name} add <package>\`.`)
358
+ }
359
+
360
+ const { pkgName, shortName, kind } = pkgInfo
361
+ const inMonorepo = Boolean(workspaceRoot)
362
+ const source = resolveSource(useNpm ? 'npm' : from, shortName, inMonorepo, {
363
+ npm: useNpm,
364
+ dev: devFlag,
365
+ })
366
+
367
+ if (source.mode === 'npm') {
368
+ if (dryRun) {
369
+ printPlan({
370
+ pkgName,
371
+ kind,
372
+ targetDir: '(npm → node_modules)',
373
+ source,
374
+ branch: null,
375
+ dryRun: true,
376
+ })
377
+ process.exit(0)
378
+ }
379
+ runNpmInstall(kind, pkgName, workspaceRoot)
380
+ } else {
381
+ try {
382
+ await runWorkspaceInstall({
383
+ pkgName,
384
+ shortName,
385
+ kind,
386
+ workspaceRoot,
387
+ source,
388
+ branch,
389
+ dryRun,
390
+ })
391
+ } catch (error) {
392
+ fail(error.message ?? String(error))
393
+ }
394
+ }
395
+ }
package/bin/desktop.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { runCli } from './cli.js'
4
+
5
+ await runCli('desktop', process.argv.slice(2))