@kispace-io/core 0.7.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/dist/api/base-classes.d.ts +7 -0
- package/dist/api/base-classes.d.ts.map +1 -0
- package/dist/api/constants.d.ts +2 -0
- package/dist/api/constants.d.ts.map +1 -0
- package/dist/api/index.d.ts +6 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +80 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/services.d.ts +27 -0
- package/dist/api/services.d.ts.map +1 -0
- package/dist/api/types.d.ts +11 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/commands/files.d.ts +2 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/global.d.ts +1 -0
- package/dist/commands/global.d.ts.map +1 -0
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/version-info.d.ts +2 -0
- package/dist/commands/version-info.d.ts.map +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/k-app-selector.d.ts +17 -0
- package/dist/components/k-app-selector.d.ts.map +1 -0
- package/dist/components/k-app-switcher.d.ts +13 -0
- package/dist/components/k-app-switcher.d.ts.map +1 -0
- package/dist/components/k-command.d.ts +31 -0
- package/dist/components/k-command.d.ts.map +1 -0
- package/dist/components/k-extensions.d.ts +32 -0
- package/dist/components/k-extensions.d.ts.map +1 -0
- package/dist/components/k-fastviews.d.ts +34 -0
- package/dist/components/k-fastviews.d.ts.map +1 -0
- package/dist/components/k-filebrowser.d.ts +40 -0
- package/dist/components/k-filebrowser.d.ts.map +1 -0
- package/dist/components/k-language-selector.d.ts +12 -0
- package/dist/components/k-language-selector.d.ts.map +1 -0
- package/dist/components/k-log-terminal.d.ts +36 -0
- package/dist/components/k-log-terminal.d.ts.map +1 -0
- package/dist/components/k-part-name.d.ts +12 -0
- package/dist/components/k-part-name.d.ts.map +1 -0
- package/dist/components/k-tasks.d.ts +13 -0
- package/dist/components/k-tasks.d.ts.map +1 -0
- package/dist/components/k-workspace-name.d.ts +14 -0
- package/dist/components/k-workspace-name.d.ts.map +1 -0
- package/dist/contributions/default-ui-contributions.d.ts +2 -0
- package/dist/contributions/default-ui-contributions.d.ts.map +1 -0
- package/dist/contributions/index.d.ts +1 -0
- package/dist/contributions/index.d.ts.map +1 -0
- package/dist/contributions/marketplace-catalog-contributions.d.ts +2 -0
- package/dist/contributions/marketplace-catalog-contributions.d.ts.map +1 -0
- package/dist/core/app-host-config.d.ts +7 -0
- package/dist/core/app-host-config.d.ts.map +1 -0
- package/dist/core/apploader.d.ts +214 -0
- package/dist/core/apploader.d.ts.map +1 -0
- package/dist/core/appstate.d.ts +12 -0
- package/dist/core/appstate.d.ts.map +1 -0
- package/dist/core/commandregistry.d.ts +79 -0
- package/dist/core/commandregistry.d.ts.map +1 -0
- package/dist/core/config.d.ts +15 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/constants.d.ts +21 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/contributionregistry.d.ts +49 -0
- package/dist/core/contributionregistry.d.ts.map +1 -0
- package/dist/core/di.d.ts +18 -0
- package/dist/core/di.d.ts.map +1 -0
- package/dist/core/dialogservice.d.ts +33 -0
- package/dist/core/dialogservice.d.ts.map +1 -0
- package/dist/core/editorregistry.d.ts +73 -0
- package/dist/core/editorregistry.d.ts.map +1 -0
- package/dist/core/esmsh-service.d.ts +40 -0
- package/dist/core/esmsh-service.d.ts.map +1 -0
- package/dist/core/events.d.ts +7 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +63 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/extensionregistry.d.ts +98 -0
- package/dist/core/extensionregistry.d.ts.map +1 -0
- package/dist/core/filesys.d.ts +139 -0
- package/dist/core/filesys.d.ts.map +1 -0
- package/dist/core/i18n.d.ts +50 -0
- package/dist/core/i18n.d.ts.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/k-utils.d.ts +2 -0
- package/dist/core/k-utils.d.ts.map +1 -0
- package/dist/core/keybindings.d.ts +67 -0
- package/dist/core/keybindings.d.ts.map +1 -0
- package/dist/core/logger.d.ts +44 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/marketplaceregistry.d.ts +25 -0
- package/dist/core/marketplaceregistry.d.ts.map +1 -0
- package/dist/core/packageinfoservice.d.ts +16 -0
- package/dist/core/packageinfoservice.d.ts.map +1 -0
- package/dist/core/persistenceservice.d.ts +6 -0
- package/dist/core/persistenceservice.d.ts.map +1 -0
- package/dist/core/settingsservice.d.ts +19 -0
- package/dist/core/settingsservice.d.ts.map +1 -0
- package/dist/core/signals.d.ts +3 -0
- package/dist/core/signals.d.ts.map +1 -0
- package/dist/core/taskservice.d.ts +20 -0
- package/dist/core/taskservice.d.ts.map +1 -0
- package/dist/core/toast.d.ts +4 -0
- package/dist/core/toast.d.ts.map +1 -0
- package/dist/core/tree-utils.d.ts +16 -0
- package/dist/core/tree-utils.d.ts.map +1 -0
- package/dist/dialogs/confirm-dialog.d.ts +14 -0
- package/dist/dialogs/confirm-dialog.d.ts.map +1 -0
- package/dist/dialogs/index.d.ts +5 -0
- package/dist/dialogs/index.d.ts.map +1 -0
- package/dist/dialogs/info-dialog.d.ts +13 -0
- package/dist/dialogs/info-dialog.d.ts.map +1 -0
- package/dist/dialogs/navigable-info-dialog.d.ts +33 -0
- package/dist/dialogs/navigable-info-dialog.d.ts.map +1 -0
- package/dist/dialogs/prompt-dialog.d.ts +21 -0
- package/dist/dialogs/prompt-dialog.d.ts.map +1 -0
- package/dist/externals/lit.d.ts +20 -0
- package/dist/externals/lit.d.ts.map +1 -0
- package/dist/externals/lit.js +15 -0
- package/dist/externals/lit.js.map +1 -0
- package/dist/externals/third-party.d.ts +7 -0
- package/dist/externals/third-party.d.ts.map +1 -0
- package/dist/externals/third-party.js +2 -0
- package/dist/externals/third-party.js.map +1 -0
- package/dist/externals/webawesome.d.ts +1 -0
- package/dist/externals/webawesome.d.ts.map +1 -0
- package/dist/externals/webawesome.js +52 -0
- package/dist/externals/webawesome.js.map +1 -0
- package/dist/i18n/extensions.json.d.ts +42 -0
- package/dist/i18n/fastviews.json.d.ts +13 -0
- package/dist/i18n/filebrowser.json.d.ts +35 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/logterminal.json.d.ts +45 -0
- package/dist/i18n/partname.json.d.ts +15 -0
- package/dist/i18n/tasks.json.d.ts +15 -0
- package/dist/i18n/workspace.json.d.ts +15 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/k-icon-BZC7dQV0.js +492 -0
- package/dist/k-icon-BZC7dQV0.js.map +1 -0
- package/dist/k-nocontent-Bh_yToGh.js +48 -0
- package/dist/k-nocontent-Bh_yToGh.js.map +1 -0
- package/dist/k-resizable-grid-Ch3iWZaL.js +3157 -0
- package/dist/k-resizable-grid-Ch3iWZaL.js.map +1 -0
- package/dist/k-standard-layout-CQ1VZoxa.js +5011 -0
- package/dist/k-standard-layout-CQ1VZoxa.js.map +1 -0
- package/dist/layouts/k-standard-layout.d.ts +16 -0
- package/dist/layouts/k-standard-layout.d.ts.map +1 -0
- package/dist/parts/index.d.ts +1 -0
- package/dist/parts/index.d.ts.map +1 -0
- package/dist/parts/index.js +53 -0
- package/dist/parts/index.js.map +1 -0
- package/dist/parts/k-app.d.ts +11 -0
- package/dist/parts/k-app.d.ts.map +1 -0
- package/dist/parts/k-container.d.ts +4 -0
- package/dist/parts/k-container.d.ts.map +1 -0
- package/dist/parts/k-contextmenu.d.ts +38 -0
- package/dist/parts/k-contextmenu.d.ts.map +1 -0
- package/dist/parts/k-dialog-content.d.ts +9 -0
- package/dist/parts/k-dialog-content.d.ts.map +1 -0
- package/dist/parts/k-element.d.ts +36 -0
- package/dist/parts/k-element.d.ts.map +1 -0
- package/dist/parts/k-part.d.ts +96 -0
- package/dist/parts/k-part.d.ts.map +1 -0
- package/dist/parts/k-resizable-grid.d.ts +31 -0
- package/dist/parts/k-resizable-grid.d.ts.map +1 -0
- package/dist/parts/k-tabs.d.ts +74 -0
- package/dist/parts/k-tabs.d.ts.map +1 -0
- package/dist/parts/k-toolbar.d.ts +21 -0
- package/dist/parts/k-toolbar.d.ts.map +1 -0
- package/dist/widgets/index.d.ts +1 -0
- package/dist/widgets/index.d.ts.map +1 -0
- package/dist/widgets/index.js +3 -0
- package/dist/widgets/index.js.map +1 -0
- package/dist/widgets/k-icon.d.ts +10 -0
- package/dist/widgets/k-icon.d.ts.map +1 -0
- package/dist/widgets/k-nocontent.d.ts +13 -0
- package/dist/widgets/k-nocontent.d.ts.map +1 -0
- package/dist/widgets/k-widget.d.ts +25 -0
- package/dist/widgets/k-widget.d.ts.map +1 -0
- package/package.json +81 -0
- package/src/api/base-classes.ts +10 -0
- package/src/api/constants.ts +3 -0
- package/src/api/index.ts +31 -0
- package/src/api/services.ts +52 -0
- package/src/api/types.ts +46 -0
- package/src/commands/files.ts +829 -0
- package/src/commands/global.ts +225 -0
- package/src/commands/index.ts +4 -0
- package/src/commands/version-info.ts +214 -0
- package/src/components/index.ts +10 -0
- package/src/components/k-app-selector.ts +233 -0
- package/src/components/k-app-switcher.ts +126 -0
- package/src/components/k-command.ts +236 -0
- package/src/components/k-extensions.ts +615 -0
- package/src/components/k-fastviews.ts +314 -0
- package/src/components/k-filebrowser.ts +442 -0
- package/src/components/k-language-selector.ts +166 -0
- package/src/components/k-log-terminal.ts +337 -0
- package/src/components/k-part-name.ts +54 -0
- package/src/components/k-tasks.ts +267 -0
- package/src/components/k-workspace-name.ts +56 -0
- package/src/contributions/default-ui-contributions.ts +51 -0
- package/src/contributions/index.ts +3 -0
- package/src/contributions/marketplace-catalog-contributions.ts +6 -0
- package/src/core/app-host-config.ts +23 -0
- package/src/core/apploader.ts +630 -0
- package/src/core/appstate.ts +15 -0
- package/src/core/commandregistry.ts +210 -0
- package/src/core/config.ts +29 -0
- package/src/core/constants.ts +27 -0
- package/src/core/contributionregistry.ts +77 -0
- package/src/core/di.ts +54 -0
- package/src/core/dialogservice.ts +266 -0
- package/src/core/editorregistry.ts +303 -0
- package/src/core/esmsh-service.ts +404 -0
- package/src/core/events.ts +68 -0
- package/src/core/extensionregistry.ts +399 -0
- package/src/core/filesys.ts +618 -0
- package/src/core/i18n.ts +221 -0
- package/src/core/index.ts +51 -0
- package/src/core/k-utils.ts +11 -0
- package/src/core/keybindings.ts +274 -0
- package/src/core/logger.ts +187 -0
- package/src/core/marketplaceregistry.ts +197 -0
- package/src/core/packageinfoservice.ts +56 -0
- package/src/core/persistenceservice.ts +15 -0
- package/src/core/settingsservice.ts +70 -0
- package/src/core/signals.ts +18 -0
- package/src/core/taskservice.ts +72 -0
- package/src/core/toast.ts +11 -0
- package/src/core/tree-utils.ts +24 -0
- package/src/dialogs/confirm-dialog.ts +72 -0
- package/src/dialogs/index.ts +4 -0
- package/src/dialogs/info-dialog.ts +67 -0
- package/src/dialogs/navigable-info-dialog.ts +256 -0
- package/src/dialogs/prompt-dialog.ts +123 -0
- package/src/externals/lit.ts +26 -0
- package/src/externals/third-party.ts +9 -0
- package/src/externals/webawesome.ts +54 -0
- package/src/i18n/extensions.json +39 -0
- package/src/i18n/fastviews.json +10 -0
- package/src/i18n/filebrowser.json +33 -0
- package/src/i18n/index.ts +25 -0
- package/src/i18n/logterminal.json +42 -0
- package/src/i18n/partname.json +12 -0
- package/src/i18n/tasks.json +12 -0
- package/src/i18n/workspace.json +12 -0
- package/src/icons/icons.txt +3 -0
- package/src/icons/js.svg +6 -0
- package/src/icons/jupyter.svg +18 -0
- package/src/icons/python.svg +15 -0
- package/src/index.ts +3 -0
- package/src/layouts/k-standard-layout.ts +174 -0
- package/src/parts/index.ts +6 -0
- package/src/parts/k-app.ts +29 -0
- package/src/parts/k-container.ts +4 -0
- package/src/parts/k-contextmenu.ts +245 -0
- package/src/parts/k-dialog-content.ts +31 -0
- package/src/parts/k-element.ts +100 -0
- package/src/parts/k-part.ts +158 -0
- package/src/parts/k-resizable-grid.ts +366 -0
- package/src/parts/k-tabs.ts +574 -0
- package/src/parts/k-toolbar.ts +158 -0
- package/src/vite-env.d.ts +2 -0
- package/src/widgets/index.ts +2 -0
- package/src/widgets/k-icon.ts +39 -0
- package/src/widgets/k-nocontent.ts +40 -0
- package/src/widgets/k-widget.ts +90 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { rootContext } from './di';
|
|
2
|
+
|
|
3
|
+
export type LogLevel = 'info' | 'warning' | 'error' | 'debug';
|
|
4
|
+
|
|
5
|
+
const LogLevelPriority: Record<LogLevel, number> = {
|
|
6
|
+
'debug': 0,
|
|
7
|
+
'info': 1,
|
|
8
|
+
'warning': 2,
|
|
9
|
+
'error': 3,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// Global log level filter
|
|
13
|
+
let globalLogLevel: LogLevel = 'debug';
|
|
14
|
+
|
|
15
|
+
// Store original console methods before any interception
|
|
16
|
+
const originalConsole = {
|
|
17
|
+
log: console.log.bind(console),
|
|
18
|
+
info: console.info.bind(console),
|
|
19
|
+
warn: console.warn.bind(console),
|
|
20
|
+
error: console.error.bind(console),
|
|
21
|
+
debug: console.debug.bind(console)
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Log handler type
|
|
25
|
+
type LogHandler = (source: string, message: string, level: LogLevel) => void;
|
|
26
|
+
|
|
27
|
+
// Registered log handler (set by UI components like k-log-terminal)
|
|
28
|
+
let logHandler: LogHandler | null = null;
|
|
29
|
+
|
|
30
|
+
// Message buffer for logs that occur before handler is registered
|
|
31
|
+
const messageBuffer: Array<{source: string, message: string, level: LogLevel}> = [];
|
|
32
|
+
|
|
33
|
+
// Format console arguments
|
|
34
|
+
function formatArg(arg: any): string {
|
|
35
|
+
if (arg === null) return 'null';
|
|
36
|
+
if (arg === undefined) return 'undefined';
|
|
37
|
+
if (typeof arg === 'string') return arg;
|
|
38
|
+
if (typeof arg === 'number' || typeof arg === 'boolean') return String(arg);
|
|
39
|
+
if (arg instanceof Error) return `${arg.name}: ${arg.message}`;
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
return JSON.stringify(arg);
|
|
43
|
+
} catch {
|
|
44
|
+
return String(arg);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Global logger utility for logging messages
|
|
50
|
+
*/
|
|
51
|
+
export class Logger {
|
|
52
|
+
constructor(private source: string) {}
|
|
53
|
+
|
|
54
|
+
info(message: string) {
|
|
55
|
+
this.log(message, 'info');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
warning(message: string) {
|
|
59
|
+
this.log(message, 'warning');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
warn(message: string) {
|
|
63
|
+
this.log(message, 'warning');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
error(message: string) {
|
|
67
|
+
this.log(message, 'error');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
debug(message: string) {
|
|
71
|
+
this.log(message, 'debug');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private log(message: string, level: LogLevel) {
|
|
75
|
+
dispatch(this.source, message, level);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Check if a log level should be displayed based on current filter
|
|
81
|
+
*/
|
|
82
|
+
function shouldLog(level: LogLevel): boolean {
|
|
83
|
+
return LogLevelPriority[level] >= LogLevelPriority[globalLogLevel];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Dispatch a log message to the registered handler (or buffer it if no handler registered)
|
|
88
|
+
*/
|
|
89
|
+
function dispatch(source: string, message: string, level: LogLevel) {
|
|
90
|
+
if (!shouldLog(level)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (logHandler) {
|
|
95
|
+
logHandler(source, message, level);
|
|
96
|
+
} else {
|
|
97
|
+
// Buffer the message until handler is registered
|
|
98
|
+
messageBuffer.push({ source, message, level });
|
|
99
|
+
// Also log to console as fallback
|
|
100
|
+
originalConsole[level === 'error' ? 'error' : level === 'warning' ? 'warn' : level === 'debug' ? 'debug' : 'log'](
|
|
101
|
+
`[${source}] ${message}`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Initialize console interception globally
|
|
108
|
+
* Note: This is called automatically when the logger module is imported
|
|
109
|
+
*/
|
|
110
|
+
export function initializeConsoleInterception() {
|
|
111
|
+
console.log = function(...args: any[]) {
|
|
112
|
+
originalConsole.log.apply(console, args);
|
|
113
|
+
dispatch('Console', args.map(a => formatArg(a)).join(' '), 'info');
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
console.info = function(...args: any[]) {
|
|
117
|
+
originalConsole.info.apply(console, args);
|
|
118
|
+
dispatch('Console', args.map(a => formatArg(a)).join(' '), 'info');
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
console.warn = function(...args: any[]) {
|
|
122
|
+
originalConsole.warn.apply(console, args);
|
|
123
|
+
dispatch('Console', args.map(a => formatArg(a)).join(' '), 'warning');
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
console.error = function(...args: any[]) {
|
|
127
|
+
originalConsole.error.apply(console, args);
|
|
128
|
+
dispatch('Console', args.map(a => formatArg(a)).join(' '), 'error');
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
console.debug = function(...args: any[]) {
|
|
132
|
+
originalConsole.debug.apply(console, args);
|
|
133
|
+
dispatch('Console', args.map(a => formatArg(a)).join(' '), 'debug');
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Auto-initialize console interception when this module is imported
|
|
138
|
+
initializeConsoleInterception();
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Register a handler to receive log messages
|
|
142
|
+
* Also flushes any buffered messages to the new handler
|
|
143
|
+
*/
|
|
144
|
+
export function registerLogHandler(handler: LogHandler) {
|
|
145
|
+
logHandler = handler;
|
|
146
|
+
|
|
147
|
+
// Flush buffered messages
|
|
148
|
+
while (messageBuffer.length > 0) {
|
|
149
|
+
const msg = messageBuffer.shift();
|
|
150
|
+
if (msg) {
|
|
151
|
+
handler(msg.source, msg.message, msg.level);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Unregister the current log handler
|
|
158
|
+
*/
|
|
159
|
+
export function unregisterLogHandler() {
|
|
160
|
+
logHandler = null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Create a logger instance for a specific source
|
|
165
|
+
*/
|
|
166
|
+
export function createLogger(source: string): Logger {
|
|
167
|
+
return new Logger(source);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Set the global log level filter
|
|
172
|
+
*/
|
|
173
|
+
export function setLogLevel(level: LogLevel) {
|
|
174
|
+
globalLogLevel = level;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Default logger instance for backward compatibility
|
|
179
|
+
* This provides a simple logger similar to the old logging.ts
|
|
180
|
+
*/
|
|
181
|
+
const defaultLogger = createLogger('System');
|
|
182
|
+
|
|
183
|
+
// Register default logger in DI container for backward compatibility
|
|
184
|
+
rootContext.put('logger', defaultLogger);
|
|
185
|
+
|
|
186
|
+
export default defaultLogger;
|
|
187
|
+
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import {appSettings} from "./settingsservice";
|
|
2
|
+
import {publish} from "./events";
|
|
3
|
+
import {createLogger} from "./logger";
|
|
4
|
+
import {extensionRegistry, Extension} from "./extensionregistry";
|
|
5
|
+
import {rootContext} from "./di";
|
|
6
|
+
|
|
7
|
+
const logger = createLogger('MarketplaceRegistry');
|
|
8
|
+
|
|
9
|
+
export const TOPIC_MARKETPLACE_CHANGED = "events/marketplaceregistry/changed";
|
|
10
|
+
|
|
11
|
+
export interface MarketplaceCatalog {
|
|
12
|
+
name?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
extensions?: Extension[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const KEY_CATALOG_URLS = "marketplace.catalogUrls";
|
|
18
|
+
|
|
19
|
+
class MarketplaceRegistry {
|
|
20
|
+
private catalogUrls: string[] = [];
|
|
21
|
+
private loadingPromises: Map<string, Promise<MarketplaceCatalog>> = new Map();
|
|
22
|
+
|
|
23
|
+
constructor() {
|
|
24
|
+
// Load catalog URLs and refresh catalogs
|
|
25
|
+
this.loadCatalogUrls().then(() => {
|
|
26
|
+
this.refreshCatalogs().catch(err => {
|
|
27
|
+
logger.error(`Failed to refresh catalogs on init: ${err.message}`);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private async loadCatalogUrls(): Promise<void> {
|
|
33
|
+
try {
|
|
34
|
+
const urls = await appSettings.get(KEY_CATALOG_URLS);
|
|
35
|
+
this.catalogUrls = Array.isArray(urls) ? urls : [];
|
|
36
|
+
logger.debug(`Loaded ${this.catalogUrls.length} catalog URLs`);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
logger.error(`Failed to load catalog URLs: ${error}`);
|
|
39
|
+
this.catalogUrls = [];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private async saveCatalogUrls(): Promise<void> {
|
|
44
|
+
await appSettings.set(KEY_CATALOG_URLS, this.catalogUrls);
|
|
45
|
+
publish(TOPIC_MARKETPLACE_CHANGED, {type: 'catalogs', urls: this.catalogUrls});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async addCatalogUrl(url: string): Promise<void> {
|
|
49
|
+
if (!this.isValidUrl(url)) {
|
|
50
|
+
throw new Error(`Invalid catalog URL: ${url}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (this.catalogUrls.includes(url)) {
|
|
54
|
+
logger.debug(`Catalog URL already exists: ${url}`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.catalogUrls.push(url);
|
|
59
|
+
await this.saveCatalogUrls();
|
|
60
|
+
logger.info(`Added catalog URL: ${url}`);
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
await this.refreshCatalogs();
|
|
64
|
+
} catch (error) {
|
|
65
|
+
logger.warn(`Failed to refresh catalogs immediately after adding: ${error}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async removeCatalogUrl(url: string): Promise<void> {
|
|
70
|
+
const index = this.catalogUrls.indexOf(url);
|
|
71
|
+
if (index === -1) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
this.catalogUrls.splice(index, 1);
|
|
76
|
+
await this.saveCatalogUrls();
|
|
77
|
+
logger.info(`Removed catalog URL: ${url}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getCatalogUrls(): string[] {
|
|
81
|
+
return [...this.catalogUrls];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private isValidUrl(url: string): boolean {
|
|
85
|
+
try {
|
|
86
|
+
const parsed = new URL(url);
|
|
87
|
+
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
|
88
|
+
} catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private async fetchCatalog(url: string): Promise<MarketplaceCatalog> {
|
|
94
|
+
const existingPromise = this.loadingPromises.get(url);
|
|
95
|
+
if (existingPromise) {
|
|
96
|
+
return existingPromise;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const fetchPromise = (async () => {
|
|
100
|
+
try {
|
|
101
|
+
logger.debug(`Fetching catalog from: ${url}`);
|
|
102
|
+
const response = await fetch(url, {
|
|
103
|
+
method: 'GET',
|
|
104
|
+
headers: {
|
|
105
|
+
'Accept': 'application/json',
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (!response.ok) {
|
|
110
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const data = await response.json() as MarketplaceCatalog;
|
|
114
|
+
|
|
115
|
+
if (!data.extensions || !Array.isArray(data.extensions)) {
|
|
116
|
+
throw new Error('Invalid catalog format: extensions array is required');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const catalog: MarketplaceCatalog = {
|
|
120
|
+
name: data.name,
|
|
121
|
+
description: data.description,
|
|
122
|
+
extensions: data.extensions || [],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const extCount = catalog.extensions?.length || 0;
|
|
126
|
+
logger.debug(`Successfully fetched catalog from ${url}: ${extCount} extensions`);
|
|
127
|
+
return catalog;
|
|
128
|
+
} catch (error) {
|
|
129
|
+
logger.error(`Failed to fetch catalog from ${url}: ${error}`);
|
|
130
|
+
throw error;
|
|
131
|
+
} finally {
|
|
132
|
+
this.loadingPromises.delete(url);
|
|
133
|
+
}
|
|
134
|
+
})();
|
|
135
|
+
|
|
136
|
+
this.loadingPromises.set(url, fetchPromise);
|
|
137
|
+
return fetchPromise;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async refreshCatalogs(): Promise<void> {
|
|
141
|
+
logger.info(`Refreshing ${this.catalogUrls.length} catalogs...`);
|
|
142
|
+
|
|
143
|
+
const promises = this.catalogUrls.map(url =>
|
|
144
|
+
this.fetchCatalog(url).catch(error => {
|
|
145
|
+
logger.warn(`Failed to refresh catalog ${url}: ${error.message}`);
|
|
146
|
+
return null;
|
|
147
|
+
})
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const catalogs = await Promise.allSettled(promises);
|
|
151
|
+
|
|
152
|
+
// Register all marketplace extensions from successfully fetched catalogs
|
|
153
|
+
// Extensions will register apps themselves when loaded
|
|
154
|
+
catalogs.forEach((result, index) => {
|
|
155
|
+
if (result.status === 'fulfilled' && result.value) {
|
|
156
|
+
const catalog = result.value;
|
|
157
|
+
|
|
158
|
+
// Register extensions
|
|
159
|
+
if (catalog.extensions) {
|
|
160
|
+
catalog.extensions.forEach(marketplaceExt => {
|
|
161
|
+
// Only register if not already registered
|
|
162
|
+
if (!extensionRegistry.getExtensions().find(e => e.id === marketplaceExt.id)) {
|
|
163
|
+
const extension: Extension = {
|
|
164
|
+
...marketplaceExt,
|
|
165
|
+
external: true
|
|
166
|
+
};
|
|
167
|
+
extensionRegistry.registerExtension(extension);
|
|
168
|
+
logger.debug(`Registered marketplace extension: ${marketplaceExt.id}`);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Publish event after registration
|
|
176
|
+
publish(TOPIC_MARKETPLACE_CHANGED, {type: 'refreshed'});
|
|
177
|
+
logger.info('Catalog refresh completed');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
getMarketplaceExtension(extensionId: string): Extension | undefined {
|
|
181
|
+
// Check if extension is registered in extensionRegistry and is external
|
|
182
|
+
const extension = extensionRegistry.getExtensions().find(e => e.id === extensionId);
|
|
183
|
+
if (extension && extension.external) {
|
|
184
|
+
return extension;
|
|
185
|
+
}
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
isMarketplaceExtension(extensionId: string): boolean {
|
|
190
|
+
const extension = extensionRegistry.getExtensions().find(e => e.id === extensionId);
|
|
191
|
+
return extension !== undefined && extension.external === true;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export const marketplaceRegistry = new MarketplaceRegistry();
|
|
196
|
+
rootContext.put("marketplaceRegistry", marketplaceRegistry);
|
|
197
|
+
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { html, TemplateResult } from "lit";
|
|
2
|
+
import { rootContext } from "./di";
|
|
3
|
+
|
|
4
|
+
export interface PackageInfo {
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
dependencies?: Record<string, string>;
|
|
8
|
+
devDependencies?: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class PackageInfoService {
|
|
12
|
+
private packages: PackageInfo[] = [];
|
|
13
|
+
|
|
14
|
+
addPackage(packageInfo: PackageInfo): void {
|
|
15
|
+
this.packages.push(packageInfo);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
hasPackages(): boolean {
|
|
19
|
+
return this.packages.length > 0 && this.packages.some(pkg =>
|
|
20
|
+
pkg.dependencies && Object.keys(pkg.dependencies).length > 0
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
renderTree(): TemplateResult {
|
|
25
|
+
if (this.packages.length === 0) {
|
|
26
|
+
return html``;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return html`
|
|
30
|
+
<wa-tree style="--indent-guide-width: 1px;">
|
|
31
|
+
${this.packages.map(pkg => {
|
|
32
|
+
const deps = pkg.dependencies || {};
|
|
33
|
+
const depEntries = Object.entries(deps);
|
|
34
|
+
|
|
35
|
+
if (depEntries.length === 0) {
|
|
36
|
+
return html``;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return html`
|
|
40
|
+
<wa-tree-item expanded>
|
|
41
|
+
<span>${pkg.name}</span>
|
|
42
|
+
${depEntries.map(([name, version]) => html`
|
|
43
|
+
<wa-tree-item>
|
|
44
|
+
<span>${name} <small>${version}</small></span>
|
|
45
|
+
</wa-tree-item>
|
|
46
|
+
`)}
|
|
47
|
+
</wa-tree-item>
|
|
48
|
+
`;
|
|
49
|
+
})}
|
|
50
|
+
</wa-tree>
|
|
51
|
+
`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const packageInfoService = new PackageInfoService();
|
|
56
|
+
rootContext.put("packageInfoService", packageInfoService);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {get, set} from 'idb-keyval';
|
|
2
|
+
import {rootContext} from "./di";
|
|
3
|
+
|
|
4
|
+
export class PersistenceService {
|
|
5
|
+
async persistObject(key: string, value: any) {
|
|
6
|
+
return set(key, value);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async getObject(key: string): Promise<any> {
|
|
10
|
+
return get(key)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const persistenceService = new PersistenceService()
|
|
15
|
+
rootContext.put("persistenceService", persistenceService)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {publish} from "./events";
|
|
2
|
+
import {persistenceService} from "./persistenceservice";
|
|
3
|
+
import {rootContext} from "./di";
|
|
4
|
+
|
|
5
|
+
export const SETTINGS_FILE_PATH = ".geospace/settings.json"
|
|
6
|
+
|
|
7
|
+
export const DIALOG_SETTINGS_KEY = "dialogSettings"
|
|
8
|
+
|
|
9
|
+
export interface AppSettings {
|
|
10
|
+
[key: string]: any;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const TOPIC_SETTINGS_CHANGED = "events/settings/changed"
|
|
14
|
+
|
|
15
|
+
class SettingsService {
|
|
16
|
+
|
|
17
|
+
private appSettings?: AppSettings;
|
|
18
|
+
|
|
19
|
+
private async checkSettings() {
|
|
20
|
+
if (!this.appSettings) {
|
|
21
|
+
this.appSettings = await persistenceService.getObject(SETTINGS_FILE_PATH)
|
|
22
|
+
if (!this.appSettings) {
|
|
23
|
+
this.appSettings = {}
|
|
24
|
+
await persistenceService.persistObject(SETTINGS_FILE_PATH, this.appSettings)
|
|
25
|
+
}
|
|
26
|
+
publish(TOPIC_SETTINGS_CHANGED, this.appSettings)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public async get(key: string) {
|
|
31
|
+
await this.checkSettings()
|
|
32
|
+
return this.appSettings![key]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public async set(key: string, value: any) {
|
|
36
|
+
await this.checkSettings()
|
|
37
|
+
this.appSettings![key] = value
|
|
38
|
+
await persistenceService.persistObject(SETTINGS_FILE_PATH, this.appSettings)
|
|
39
|
+
publish(TOPIC_SETTINGS_CHANGED, this.appSettings)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public async getAll() {
|
|
43
|
+
await this.checkSettings()
|
|
44
|
+
return this.appSettings!;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public async setAll(settings: AppSettings) {
|
|
48
|
+
this.appSettings = settings
|
|
49
|
+
await persistenceService.persistObject(SETTINGS_FILE_PATH, this.appSettings)
|
|
50
|
+
publish(TOPIC_SETTINGS_CHANGED, this.appSettings)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public async getDialogSetting(key: string) {
|
|
54
|
+
await this.checkSettings()
|
|
55
|
+
const dialogSettings = this.appSettings![DIALOG_SETTINGS_KEY] || {}
|
|
56
|
+
return dialogSettings[key]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public async setDialogSetting(key: string, value: any) {
|
|
60
|
+
await this.checkSettings()
|
|
61
|
+
const dialogSettings = this.appSettings![DIALOG_SETTINGS_KEY] || {}
|
|
62
|
+
dialogSettings[key] = value
|
|
63
|
+
this.appSettings![DIALOG_SETTINGS_KEY] = dialogSettings
|
|
64
|
+
await persistenceService.persistObject(SETTINGS_FILE_PATH, this.appSettings)
|
|
65
|
+
publish(TOPIC_SETTINGS_CHANGED, this.appSettings)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const appSettings = new SettingsService();
|
|
70
|
+
rootContext.put("appSettings", appSettings)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {Signal} from "@lit-labs/signals";
|
|
2
|
+
|
|
3
|
+
export const watchSignal = (signal: Signal.State<any> | Signal.Computed<any>, callback: (value: any) => void): (() => void) => {
|
|
4
|
+
const watcher = new Signal.subtle.Watcher(async () => {
|
|
5
|
+
try {
|
|
6
|
+
await 0;
|
|
7
|
+
callback(signal.get());
|
|
8
|
+
} finally {
|
|
9
|
+
watcher.watch(signal);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
watcher.watch(signal);
|
|
13
|
+
signal.get();
|
|
14
|
+
|
|
15
|
+
return () => {
|
|
16
|
+
watcher.unwatch(signal);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {activeTasksSignal} from "./appstate";
|
|
2
|
+
import {rootContext} from "./di";
|
|
3
|
+
|
|
4
|
+
export interface ProgressMonitor {
|
|
5
|
+
name: string
|
|
6
|
+
message: string
|
|
7
|
+
currentStep: number
|
|
8
|
+
totalSteps: number
|
|
9
|
+
progress: number // Manual progress percentage (0-100), overrides step-based calculation if >= 0
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type Task = (progressMonitor: ProgressMonitor) => any
|
|
13
|
+
export type AsyncTask = (progressMonitor: ProgressMonitor) => Promise<any>
|
|
14
|
+
|
|
15
|
+
export class TaskService {
|
|
16
|
+
private tasks: ProgressMonitor[] = []
|
|
17
|
+
private updateCounter = 0
|
|
18
|
+
|
|
19
|
+
private notifyUpdate() {
|
|
20
|
+
// Always increment counter to ensure signal value changes and triggers re-render
|
|
21
|
+
this.updateCounter++
|
|
22
|
+
activeTasksSignal.set(this.updateCounter)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public run(name: string, task: Task) {
|
|
26
|
+
const progressMonitor = this.createProgressMonitor(name)
|
|
27
|
+
try {
|
|
28
|
+
this.tasks.push(progressMonitor)
|
|
29
|
+
this.notifyUpdate()
|
|
30
|
+
task(progressMonitor)
|
|
31
|
+
} finally {
|
|
32
|
+
this.tasks.splice(this.tasks.indexOf(progressMonitor), 1)
|
|
33
|
+
this.notifyUpdate()
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public async runAsync(name: string, task: AsyncTask) {
|
|
38
|
+
const progressMonitor = this.createProgressMonitor(name)
|
|
39
|
+
this.tasks.push(progressMonitor)
|
|
40
|
+
this.notifyUpdate()
|
|
41
|
+
return task(progressMonitor).finally(() => {
|
|
42
|
+
this.tasks.splice(this.tasks.indexOf(progressMonitor), 1)
|
|
43
|
+
this.notifyUpdate()
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private createProgressMonitor(name: string): ProgressMonitor {
|
|
48
|
+
const monitor = {
|
|
49
|
+
name: name,
|
|
50
|
+
message: "",
|
|
51
|
+
currentStep: 0,
|
|
52
|
+
totalSteps: -1, // -1 indicates indefinite progress
|
|
53
|
+
progress: -1 // -1 means use step-based calculation
|
|
54
|
+
} as ProgressMonitor
|
|
55
|
+
|
|
56
|
+
// Create a proxy to detect property changes and trigger UI updates
|
|
57
|
+
return new Proxy(monitor, {
|
|
58
|
+
set: (target, prop, value) => {
|
|
59
|
+
(target as any)[prop] = value
|
|
60
|
+
this.notifyUpdate()
|
|
61
|
+
return true
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getActiveTasks() {
|
|
67
|
+
return this.tasks
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const taskService = new TaskService()
|
|
72
|
+
rootContext.put("taskService", taskService)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const toastInfo = (msg: string) => {
|
|
2
|
+
console.info("[TOAST] INFO:", msg);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export const toastError = (msg: string) => {
|
|
6
|
+
console.error("[TOAST] ERROR:", msg);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const toastWarning = (msg: string) => {
|
|
10
|
+
console.warn("[TOAST] WARNING:", msg);
|
|
11
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {Contribution} from "./contributionregistry";
|
|
2
|
+
|
|
3
|
+
export interface TreeNode {
|
|
4
|
+
data: any;
|
|
5
|
+
label: string;
|
|
6
|
+
icon?: string;
|
|
7
|
+
leaf: boolean;
|
|
8
|
+
children: TreeNode[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const treeNodeComparator = (c1: TreeNode, c2: TreeNode) => {
|
|
12
|
+
if (!c1.leaf && c2.leaf) {
|
|
13
|
+
return -1
|
|
14
|
+
}
|
|
15
|
+
if (c1.leaf && !c2.leaf) {
|
|
16
|
+
return 1
|
|
17
|
+
}
|
|
18
|
+
return c1.label.localeCompare(c2.label)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface TreeContribution extends Contribution {
|
|
22
|
+
contributionId?: string;
|
|
23
|
+
state?: { [key: string]: any }
|
|
24
|
+
}
|