@owdproject/core 3.1.2 → 3.1.4-beta.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 (50) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +9 -10
  3. package/bin/owd.js +14 -14
  4. package/index.ts +5 -2
  5. package/module.ts +64 -55
  6. package/package.json +19 -17
  7. package/project.json +4 -0
  8. package/runtime/components/Core/Application/CoreApplicationRender.vue +6 -5
  9. package/runtime/components/Core/Application/CoreApplicationWindowsRender.vue +8 -8
  10. package/runtime/components/Core/Background/CoreBackground.vue +1 -1
  11. package/runtime/components/Core/Desktop/CoreDesktop.vue +23 -20
  12. package/runtime/components/Core/Explorer/CoreExplorerFile.vue +47 -38
  13. package/runtime/components/Core/Explorer/CoreExplorerFolder.vue +0 -1
  14. package/runtime/components/Core/Time/CoreTime.vue +10 -7
  15. package/runtime/components/Core/Window/CoreWindow.vue +46 -34
  16. package/runtime/components/Core/Window/CoreWindowContent.vue +3 -5
  17. package/runtime/components/Core/Window/CoreWindowNav.vue +12 -7
  18. package/runtime/composables/useApplicationEntries.ts +51 -0
  19. package/runtime/composables/useApplicationManager.ts +3 -3
  20. package/runtime/composables/useClipboardFs.ts +11 -11
  21. package/runtime/composables/useDesktopManager.ts +2 -2
  22. package/runtime/composables/useTerminalManager.ts +3 -3
  23. package/runtime/core/controllers/ApplicationController.ts +211 -200
  24. package/runtime/core/controllers/WindowController.ts +349 -312
  25. package/runtime/core/managers/ApplicationManager.ts +240 -196
  26. package/runtime/core/managers/DesktopManager.ts +35 -25
  27. package/runtime/core/managers/TerminalManager.ts +36 -32
  28. package/runtime/plugins/resize.client.ts +4 -4
  29. package/runtime/stores/storeApplication.ts +235 -0
  30. package/runtime/stores/storeApplicationMeta.ts +12 -8
  31. package/runtime/stores/storeApplicationWindows.ts +16 -12
  32. package/runtime/stores/storeDesktop.ts +33 -29
  33. package/runtime/stores/storeDesktopVolume.ts +12 -12
  34. package/runtime/stores/storeDesktopWindow.ts +13 -13
  35. package/runtime/stores/storeDesktopWorkspace.ts +35 -31
  36. package/runtime/utils/utilApp.ts +27 -22
  37. package/runtime/utils/utilCommon.ts +43 -43
  38. package/runtime/utils/utilDebug.ts +17 -17
  39. package/runtime/utils/utilDesktop.ts +4 -4
  40. package/runtime/utils/utilTerminal.ts +6 -5
  41. package/runtime/utils/utilWindow.ts +11 -11
  42. package/test/fixtures/basic/app.vue +1 -2
  43. package/test/fixtures/basic/nuxt.config.ts +1 -3
  44. package/tsconfig.app.json +1 -1
  45. package/tsconfig.json +1 -1
  46. package/types/index.d.ts +235 -207
  47. package/vitest.config.ts +3 -3
  48. package/.editorconfig +0 -12
  49. package/eslint.config.mjs +0 -30
  50. package/runtime/composables/useAppEntries.ts +0 -36
@@ -1,237 +1,281 @@
1
- import type {Reactive} from "@vue/reactivity"
2
- import {reactive, markRaw} from "@vue/reactivity"
3
- import {ApplicationController} from "../controllers/ApplicationController";
4
- import {normalizeApplicationConfig} from "../../utils/utilApp"
5
- import {debugLog} from "../../utils/utilDebug"
1
+ import type { Reactive } from '@vue/reactivity'
2
+ import { reactive, markRaw } from '@vue/reactivity'
3
+ import { ApplicationController } from '../controllers/ApplicationController'
4
+ import { normalizeApplicationConfig } from '../../utils/utilApp'
5
+ import { debugLog } from '../../utils/utilDebug'
6
+ import * as shellwords from 'shellwords'
7
+ import yargsParser from 'yargs-parser'
6
8
 
7
9
  export class ApplicationManager implements IApplicationManager {
8
- public apps = reactive(
9
- new Map<string, IApplicationController>()
10
- )
11
-
12
- constructor() {
10
+ public apps = reactive(new Map<string, IApplicationController>())
11
+
12
+ constructor() {}
13
+
14
+ /**
15
+ * Define new application
16
+ *
17
+ * @param id
18
+ * @param config
19
+ */
20
+ public async defineApp(id: string, config: ApplicationConfig) {
21
+ if (this.isAppDefined(id)) {
22
+ debugLog(`App "${id}" is already defined`)
23
+ return this.getAppById(id)!
13
24
  }
14
25
 
15
- /**
16
- * Define new application
17
- *
18
- * @param id
19
- * @param config
20
- */
21
- public async defineApp(id: string, config: ApplicationConfig) {
22
- if (this.isAppDefined(id)) {
23
- debugLog(`App "${id}" is already defined`);
24
- return this.apps.get(id)!;
25
- }
26
-
27
- const normalizedConfig = normalizeApplicationConfig(config)
28
- const applicationConfig = markRaw(normalizedConfig)
29
-
30
- const applicationController: IApplicationController = new ApplicationController(id, applicationConfig)
31
- await applicationController.initApplication()
26
+ const normalizedConfig = normalizeApplicationConfig(config)
27
+ const applicationConfig = markRaw(normalizedConfig)
28
+
29
+ const applicationController: IApplicationController = new ApplicationController(id, applicationConfig)
30
+ await applicationController.initApplication()
31
+
32
+ this.apps.set(id, applicationController)
33
+
34
+ return applicationController
35
+ }
36
+
37
+ /**
38
+ * Check if app has been defned
39
+ *
40
+ * @param {string} id
41
+ */
42
+ public isAppDefined(id: string) {
43
+ return this.getAppById(id)
44
+ }
45
+
46
+ /**
47
+ * Retrieves an app instance by its unique identifier
48
+ *
49
+ * @param {string} id
50
+ */
51
+ public getAppById(id: string) {
52
+ return this.apps.get(id)
53
+ }
54
+
55
+ /**
56
+ * Check if app is running
57
+ *
58
+ * @param {string} id
59
+ */
60
+ public isAppRunning(id: string) {
61
+ if (!this.isAppDefined(id)) {
62
+ throw Error(`App "${id}" is not defined`)
63
+ }
32
64
 
33
- this.apps.set(id, applicationController)
65
+ const applicationController: IApplicationController = this.getAppById(id)!
34
66
 
35
- return applicationController
67
+ if (!applicationController.isRunning) {
68
+ return false
36
69
  }
37
70
 
38
- /**
39
- * Check if app has been defned
40
- *
41
- * @param id
42
- */
43
- public isAppDefined(id: string) {
44
- return this.apps.has(id)
71
+ return true
72
+ }
73
+
74
+ /**
75
+ * Launch app entry
76
+ *
77
+ * @param id
78
+ * @param entryKey
79
+ */
80
+ public async launchAppEntry(
81
+ id: string,
82
+ entryKey: string,
83
+ ): Promise<IApplicationController | undefined | void> {
84
+ if (!this.isAppDefined(id)) {
85
+ throw Error(`App "${id}" is not defined`)
45
86
  }
46
87
 
47
- /**
48
- * Check if app is running
49
- *
50
- * @param id
51
- */
52
- public isAppRunning(id: string) {
53
- if (!this.isAppDefined(id)) {
54
- throw Error(`App "${id}" is not defined`);
55
- }
88
+ const applicationController: IApplicationController = this.getAppById(id)!
56
89
 
57
- const applicationController: IApplicationController = this.apps.get(id)!
58
-
59
- if (!applicationController.isRunning) {
60
- return false
61
- }
62
-
63
- return true
90
+ if (
91
+ applicationController.config.entries &&
92
+ !applicationController.config.entries.hasOwnProperty(entryKey)
93
+ ) {
94
+ throw Error(`App entry "${entryKey}" is not defined in ${id} application`)
64
95
  }
65
96
 
66
- /**
67
- * Launch app rntry
68
- *
69
- * @param id
70
- * @param entryKey
71
- */
72
- public async launchAppEntry(id: string, entryKey: string): Promise<IApplicationController | undefined | void> {
73
- if (!this.isAppDefined(id)) {
74
- throw Error(`App "${id}" is not defined`);
75
- }
76
-
77
- const applicationController: IApplicationController = this.apps.get(id)!
97
+ const entry: ApplicationEntry = applicationController.config.entries[entryKey]!
98
+
99
+ await this.execAppCommand(applicationController.id, entry.command)
100
+ }
101
+
102
+ /**
103
+ * Run app command
104
+ *
105
+ * @param id
106
+ * @param rawCommand
107
+ */
108
+ public async execAppCommand(
109
+ id: string,
110
+ rawCommand: string,
111
+ ): Promise<CommandOutput> {
112
+ if (!this.isAppDefined(id)) {
113
+ throw Error(`App "${id}" is not defined`)
114
+ }
78
115
 
79
- if (applicationController.config.entries && !applicationController.config.entries.hasOwnProperty(entryKey)) {
80
- throw Error(`App entry "${entryKey}" is not defined in ${id} application`);
81
- }
116
+ const applicationController: IApplicationController = this.getAppById(id)!
82
117
 
83
- const entry: ApplicationEntry = applicationController.config.entries[entryKey]!
118
+ const args = shellwords.split(rawCommand)
119
+ const parsed = yargsParser(args)
120
+ const command: string = parsed._[0]
84
121
 
85
- await this.execAppCommand(applicationController.id, entry.command)
122
+ if (
123
+ applicationController.config.commands &&
124
+ !applicationController.config.commands.hasOwnProperty(command)
125
+ ) {
126
+ throw Error(
127
+ `App command "${command}" is not defined in ${id} application`,
128
+ )
86
129
  }
87
130
 
88
- /**
89
- * Run app command
90
- *
91
- * @param id
92
- * @param command
93
- */
94
- public async execAppCommand(id: string, command: string): Promise<CommandOutput> {
95
- if (!this.isAppDefined(id)) {
96
- throw Error(`App "${id}" is not defined`);
97
- }
98
-
99
- const applicationController: IApplicationController = this.apps.get(id)!
131
+ const commandFn: any = applicationController.config.commands![command]
100
132
 
101
- const commandSplit: string[] = command.split(" ")
102
- const baseCommand = commandSplit[0] as keyof typeof applicationController.config.commands
103
-
104
- if (applicationController.config.commands && !applicationController.config.commands.hasOwnProperty(baseCommand)) {
105
- throw Error(`App command "${command}" is not defined in ${id} application`);
106
- }
133
+ const commandOutput = await commandFn(
134
+ applicationController,
135
+ parsed,
136
+ )
107
137
 
108
- const commandFn: any = applicationController.config.commands![baseCommand]
109
- const commandOutput = await commandFn(applicationController, commandSplit.slice(1))
138
+ applicationController.setRunning(true)
110
139
 
111
- applicationController.setRunning(true)
140
+ return commandOutput
141
+ }
112
142
 
113
- return commandOutput;
143
+ /**
144
+ * Close application
145
+ *
146
+ * @param id
147
+ */
148
+ public closeApp(id: string) {
149
+ if (!this.isAppDefined(id)) {
150
+ throw Error(`App "${id}" is not defined`)
114
151
  }
115
152
 
116
- /**
117
- * Close application
118
- *
119
- * @param id
120
- */
121
- public closeApp(id: string) {
122
- if (!this.isAppDefined(id)) {
123
- throw Error(`App "${id}" is not defined`);
124
- }
153
+ const applicationController: IApplicationController = this.getAppById(id)!
154
+
155
+ applicationController.closeAllWindows()
156
+ applicationController.setRunning(false)
157
+ }
158
+
159
+ /**
160
+ * Array of available menu entries for system bars, docks
161
+ */
162
+ public get appsEntries() {
163
+ const entries: Reactive<ApplicationEntryWithInherited[]> = reactive([])
164
+
165
+ for (const applicationController of this.apps.values()) {
166
+ if (!applicationController.config.entries) {
167
+ continue
168
+ }
169
+
170
+ for (const entryKey of Object.keys(
171
+ applicationController.config.entries,
172
+ )) {
173
+ const entry: ApplicationEntry =
174
+ applicationController.config.entries[entryKey]!
175
+
176
+ entries.push({
177
+ application: applicationController,
178
+ title:
179
+ entry.title !== undefined
180
+ ? entry.title
181
+ : applicationController.config.title,
182
+ icon:
183
+ entry.icon !== undefined
184
+ ? entry.icon
185
+ : applicationController.config.icon,
186
+ category:
187
+ entry.category !== undefined
188
+ ? entry.category
189
+ : applicationController.config.category,
190
+ visibility: entry.visibility ?? 'primary',
191
+ command: entry.command,
192
+ })
193
+ }
194
+ }
125
195
 
126
- const applicationController: IApplicationController = this.apps.get(id)!
196
+ return entries
197
+ }
127
198
 
128
- applicationController.closeAllWindows()
129
- applicationController.setRunning(false)
130
- }
199
+ /**
200
+ * Array of opened windows for system bars, docks
201
+ */
202
+ public get windowsOpened() {
203
+ const windows: Reactive<Map<string, IWindowController>[]> = reactive([])
131
204
 
132
- /**
133
- * Array of available menu entries for system bars, docks
134
- */
135
- public get appsEntries() {
136
- const entries: Reactive<ApplicationEntryWithInherited[]> = reactive([])
137
-
138
- for (const applicationController of this.apps.values()) {
139
- if (!applicationController.config.entries) {
140
- continue
141
- }
142
-
143
- for (const entryKey of Object.keys(applicationController.config.entries)) {
144
- const entry: ApplicationEntry = applicationController.config.entries[entryKey]!
145
-
146
- entries.push({
147
- application: applicationController,
148
- title: entry.title !== undefined ? entry.title : applicationController.config.title,
149
- icon: entry.icon !== undefined ? entry.icon : applicationController.config.icon,
150
- category: entry.category !== undefined ? entry.category : applicationController.config.category,
151
- visibility: entry.visibility ?? 'primary',
152
- command: entry.command
153
- })
154
- }
155
- }
156
-
157
- return entries
205
+ for (const applicationController of this.apps.values()) {
206
+ if (applicationController.isRunning) {
207
+ windows.push(...applicationController.windows)
208
+ }
158
209
  }
159
210
 
160
- /**
161
- * Array of opened windows for system bars, docks
162
- */
163
- public get windowsOpened() {
164
- const windows: Reactive<Map<string, IWindowController>[]> = reactive([])
211
+ return windows
212
+ }
165
213
 
166
- for (const applicationController of this.apps.values()) {
167
- if (applicationController.isRunning) {
168
- windows.push(...applicationController.windows)
169
- }
170
- }
214
+ /**
215
+ * Array of opened windows for system bars, docks
216
+ */
217
+ public get appsRunning() {
218
+ const applications: Reactive<IApplicationController[]> = reactive([])
171
219
 
172
- return windows
220
+ for (const applicationController of this.apps.values()) {
221
+ if (applicationController.isRunning) {
222
+ applications.push(applicationController)
223
+ }
173
224
  }
174
225
 
175
- /**
176
- * Array of opened windows for system bars, docks
177
- */
178
- public get appsRunning() {
179
- const applications: Reactive<IApplicationController[]> = reactive([])
226
+ return applications
227
+ }
180
228
 
181
- for (const applicationController of this.apps.values()) {
182
- if (applicationController.isRunning) {
183
- applications.push(applicationController)
184
- }
185
- }
229
+ public getWindowOpenedId(windowId: string) {
230
+ const mapWindowFound: Map<string, IWindowController> | undefined =
231
+ this.windowsOpened.find((window: any) => {
232
+ return window[1].state.id === windowId
233
+ })
186
234
 
187
- return applications
235
+ if (mapWindowFound) {
236
+ // @ts-ignore
237
+ return mapWindowFound[1] as IWindowController
188
238
  }
189
-
190
- public getWindowOpenedId(windowId: string) {
191
- const mapWindowFound: Map<string, IWindowController> | undefined = this.windowsOpened.find((window: any) => {
192
- return window[1].state.id === windowId
193
- })
194
-
195
- if (mapWindowFound) {
196
- // @ts-ignore
197
- return mapWindowFound[1] as IWindowController
198
- }
239
+ }
240
+
241
+ /**
242
+ * Gets all unique categories from the installed apps
243
+ */
244
+ public get appCategories(): string[] {
245
+ const categories = new Set<string>()
246
+
247
+ for (const applicationController of this.apps.values()) {
248
+ if (applicationController.config.category) {
249
+ categories.add(applicationController.config.category)
250
+ }
199
251
  }
200
-
201
- /**
202
- * Gets all unique categories from the installed apps
203
- */
204
- public get appCategories(): string[] {
205
- const categories = new Set<string>()
206
-
207
- for (const applicationController of this.apps.values()) {
208
- if (applicationController.config.category) {
209
- categories.add(applicationController.config.category)
210
- }
211
- }
212
- return Array.from(categories).sort()
252
+ return Array.from(categories).sort()
253
+ }
254
+
255
+ /**
256
+ * Gets the apps ordered by category
257
+ */
258
+ public get appsByCategory(): {
259
+ [category: string]: IApplicationController[]
260
+ } {
261
+ const categorizedApps: {
262
+ [category: string]: IApplicationController[]
263
+ } = {}
264
+
265
+ for (const applicationController of this.apps.values()) {
266
+ const category = applicationController.config.category || 'other'
267
+ if (!categorizedApps[category]) {
268
+ categorizedApps[category] = []
269
+ }
270
+ categorizedApps[category].push(applicationController)
213
271
  }
214
272
 
215
- /**
216
- * Gets the apps ordered by category
217
- */
218
- public get appsByCategory(): { [category: string]: IApplicationController[] } {
219
- const categorizedApps: { [category: string]: IApplicationController[] } = {}
220
-
221
- for (const applicationController of this.apps.values()) {
222
- const category = applicationController.config.category || 'other'
223
- if (!categorizedApps[category]) {
224
- categorizedApps[category] = []
225
- }
226
- categorizedApps[category].push(applicationController)
227
- }
228
-
229
- for (const category in categorizedApps) {
230
- categorizedApps[category]!.sort(
231
- (a, b) => a.config.title.localeCompare(b.config.title)
232
- )
233
- }
234
-
235
- return categorizedApps
273
+ for (const category in categorizedApps) {
274
+ categorizedApps[category]!.sort((a, b) =>
275
+ a.config.title.localeCompare(b.config.title),
276
+ )
236
277
  }
278
+
279
+ return categorizedApps
280
+ }
237
281
  }
@@ -1,37 +1,47 @@
1
- import {deepMerge} from "../../utils/utilCommon"
2
-
3
1
  export class DesktopManager {
4
- public config: DesktopConfig = {} as DesktopConfig
2
+ private defaultApps: DefaultAppsConfig = {}
5
3
 
6
- private defaultApps: DefaultAppsConfig = {}
4
+ constructor() {}
7
5
 
8
- constructor() {
6
+ get config(): DesktopConfig {
7
+ const runtimeConfig = useRuntimeConfig()
9
8
 
10
- }
9
+ return runtimeConfig.public.desktop
10
+ }
11
11
 
12
- public hasFeature(featureName: string) {
13
- return this.config.features?.indexOf(featureName) !== -1
14
- }
12
+ public hasFeature(featureName: string) {
13
+ return this.config.features?.indexOf(featureName) !== -1
14
+ }
15
15
 
16
- public setConfig(config: DesktopConfig) {
17
- this.config = deepMerge(this.config, config) as DesktopConfig
18
- this.loadDefaultAppsFromConfig()
19
- }
16
+ public setConfig(config: DesktopConfig) {
17
+ const runtimeConfig = useRuntimeConfig()
20
18
 
21
- public setDefaultApp(feature: string, application: IApplicationController, entry: ApplicationEntry) {
22
- this.defaultApps[feature] = {
23
- application,
24
- entry
25
- }
26
- }
19
+ runtimeConfig.public.desktop = deepMerge(
20
+ runtimeConfig.public.desktop,
21
+ config
22
+ ) as DesktopConfig
23
+
24
+ this.loadDefaultAppsFromConfig()
25
+ }
27
26
 
28
- public getDefaultApp(feature: string): DefaultAppConfig {
29
- return this.defaultApps[feature] as DefaultAppConfig
27
+ public setDefaultApp(
28
+ feature: string,
29
+ application: IApplicationController,
30
+ command: string,
31
+ ) {
32
+ this.defaultApps[feature] = {
33
+ application,
34
+ command,
30
35
  }
36
+ }
37
+
38
+ public getDefaultApp(feature: string): DefaultAppConfig {
39
+ return this.defaultApps[feature] as DefaultAppConfig
40
+ }
31
41
 
32
- private loadDefaultAppsFromConfig() {
33
- if (this.config.defaultApps) {
34
- this.defaultApps = {...this.config.defaultApps}
35
- }
42
+ private loadDefaultAppsFromConfig() {
43
+ if (this.config.defaultApps) {
44
+ this.defaultApps = { ...this.config.defaultApps }
36
45
  }
46
+ }
37
47
  }
@@ -1,44 +1,48 @@
1
- import {useApplicationManager} from "../../composables/useApplicationManager"
2
- import {debugLog} from "../../utils/utilDebug"
1
+ import { useApplicationManager } from '../../composables/useApplicationManager'
2
+ import { debugLog } from '../../utils/utilDebug'
3
3
 
4
4
  export class TerminalManager {
5
- private commands: Map<string, TerminalCommand> = new Map()
6
-
7
- constructor() {
5
+ private commands: Map<string, TerminalCommand> = new Map()
6
+
7
+ constructor() {}
8
+
9
+ public addCommand(command: TerminalCommand) {
10
+ for (const existingCommand of this.commands.keys()) {
11
+ if (
12
+ existingCommand.startsWith(command.name) ||
13
+ command.name.startsWith(existingCommand)
14
+ ) {
15
+ throw new Error(`Command prefix conflict with "${existingCommand}"`)
16
+ }
8
17
  }
9
18
 
10
- public addCommand(command: TerminalCommand) {
11
- for (const existingCommand of this.commands.keys()) {
12
- if (existingCommand.startsWith(command.name) || command.name.startsWith(existingCommand)) {
13
- throw new Error(`Command prefix conflict with "${existingCommand}"`)
14
- }
15
- }
16
-
17
- this.commands.set(command.name, command)
18
- debugLog(`Registered terminal command: ${command.name} → ${command.applicationId}`)
19
- }
19
+ this.commands.set(command.name, command)
20
+ debugLog(
21
+ `Registered terminal command: ${command.name} → ${command.applicationId}`,
22
+ )
23
+ }
20
24
 
21
- public listCommands(): string[] {
22
- return Array.from(this.commands.keys())
23
- }
25
+ public listCommands(): string[] {
26
+ return Array.from(this.commands.keys())
27
+ }
24
28
 
25
- public async execCommand(input: string): Promise<CommandOutput | void> {
26
- const applicationManager = useApplicationManager()
29
+ public async execCommand(input: string): Promise<CommandOutput | void> {
30
+ const applicationManager = useApplicationManager()
27
31
 
28
- const [name, ...args] = input.trim().split(/\s+/)
32
+ const [name, ...args] = input.trim().split(/\s+/)
29
33
 
30
- if (!name) {
31
- return
32
- }
34
+ if (!name) {
35
+ return
36
+ }
33
37
 
34
- if (!this.commands.has(name)) {
35
- return {
36
- message: `Command "${name}" not found`
37
- }
38
- }
38
+ if (!this.commands.has(name)) {
39
+ return {
40
+ message: `Command "${name}" not found`,
41
+ }
42
+ }
39
43
 
40
- const application = this.commands.get(name)!
44
+ const application = this.commands.get(name)!
41
45
 
42
- return applicationManager.execAppCommand(application.applicationId, input)
43
- }
46
+ return applicationManager.execAppCommand(application.applicationId, input)
47
+ }
44
48
  }
@@ -1,6 +1,6 @@
1
1
  import VueResizable from 'vue-resizable/src/components/vue-resizable.vue'
2
- import {defineNuxtPlugin} from "nuxt/app"
2
+ import { defineNuxtPlugin } from 'nuxt/app'
3
3
 
4
- export default defineNuxtPlugin(nuxtApp => {
5
- nuxtApp.vueApp.component('vue-resizable', VueResizable)
6
- })
4
+ export default defineNuxtPlugin((nuxtApp) => {
5
+ nuxtApp.vueApp.component('vue-resizable', VueResizable)
6
+ })