@eclipse-lyra/extension-sqleditor 0.7.57 → 0.7.59
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/index.js +13 -10
- package/dist/index.js.map +1 -1
- package/dist/sqleditor-extension-MEwwujrA.js +824 -0
- package/dist/sqleditor-extension-MEwwujrA.js.map +1 -0
- package/package.json +3 -3
- package/dist/sqleditor-extension-BFAaVI-7.js +0 -920
- package/dist/sqleditor-extension-BFAaVI-7.js.map +0 -1
|
@@ -1,920 +0,0 @@
|
|
|
1
|
-
import { rootContext, taskService, toastError, LyraPart, subscribe, TOPIC_CONTRIBUTEIONS_CHANGED, contributionRegistry, confirmDialog, unsubscribe, publish, toastInfo, editorRegistry, File } from "@eclipse-lyra/core";
|
|
2
|
-
import { html as html$1 } from "@eclipse-lyra/core/externals/lit";
|
|
3
|
-
import { property, state, customElement } from "lit/decorators.js";
|
|
4
|
-
import { css, LitElement, html } from "lit";
|
|
5
|
-
import { repeat } from "lit/directives/repeat.js";
|
|
6
|
-
import { createRef, ref } from "lit/directives/ref.js";
|
|
7
|
-
var __defProp$1 = Object.defineProperty;
|
|
8
|
-
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
|
9
|
-
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
10
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
|
|
11
|
-
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
12
|
-
if (decorator = decorators[i])
|
|
13
|
-
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
14
|
-
if (kind && result) __defProp$1(target, key, result);
|
|
15
|
-
return result;
|
|
16
|
-
};
|
|
17
|
-
let LyraSqlExtensionManager = class extends LitElement {
|
|
18
|
-
constructor() {
|
|
19
|
-
super(...arguments);
|
|
20
|
-
this.open = false;
|
|
21
|
-
this.db = null;
|
|
22
|
-
this.databaseLabel = "";
|
|
23
|
-
this.extensions = [];
|
|
24
|
-
this.loading = false;
|
|
25
|
-
this.updatingId = null;
|
|
26
|
-
this.error = null;
|
|
27
|
-
this.filterText = "";
|
|
28
|
-
}
|
|
29
|
-
configure(options) {
|
|
30
|
-
this.db = options.db;
|
|
31
|
-
this.databaseLabel = options.databaseLabel;
|
|
32
|
-
this.extensions = [];
|
|
33
|
-
this.error = null;
|
|
34
|
-
void this.refreshExtensions();
|
|
35
|
-
}
|
|
36
|
-
show() {
|
|
37
|
-
if (!this.db || !this.db.listDbExtensions) return;
|
|
38
|
-
this.open = true;
|
|
39
|
-
}
|
|
40
|
-
hide() {
|
|
41
|
-
this.open = false;
|
|
42
|
-
}
|
|
43
|
-
async refreshExtensions() {
|
|
44
|
-
if (!this.db || !this.db.listDbExtensions) {
|
|
45
|
-
this.extensions = [];
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
this.loading = true;
|
|
49
|
-
this.error = null;
|
|
50
|
-
try {
|
|
51
|
-
const result = await taskService.runAsync(
|
|
52
|
-
"Loading database extensions",
|
|
53
|
-
async () => this.db.listDbExtensions()
|
|
54
|
-
);
|
|
55
|
-
this.extensions = Array.isArray(result) ? result : [];
|
|
56
|
-
} catch (err) {
|
|
57
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
58
|
-
this.error = msg;
|
|
59
|
-
toastError(msg);
|
|
60
|
-
} finally {
|
|
61
|
-
this.loading = false;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
async enableExtension(ext) {
|
|
65
|
-
if (!this.db || !this.db.enableDbExtension) return;
|
|
66
|
-
this.updatingId = ext.id;
|
|
67
|
-
this.error = null;
|
|
68
|
-
try {
|
|
69
|
-
await taskService.runAsync(
|
|
70
|
-
`Enabling extension ${ext.label || ext.id}`,
|
|
71
|
-
async () => this.db.enableDbExtension(ext.id)
|
|
72
|
-
);
|
|
73
|
-
await this.refreshExtensions();
|
|
74
|
-
} catch (err) {
|
|
75
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
76
|
-
this.error = msg;
|
|
77
|
-
toastError(msg);
|
|
78
|
-
} finally {
|
|
79
|
-
this.updatingId = null;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
async disableExtension(ext) {
|
|
83
|
-
if (!this.db || !this.db.disableDbExtension) return;
|
|
84
|
-
this.updatingId = ext.id;
|
|
85
|
-
this.error = null;
|
|
86
|
-
try {
|
|
87
|
-
await taskService.runAsync(
|
|
88
|
-
`Disabling extension ${ext.label || ext.id}`,
|
|
89
|
-
async () => this.db.disableDbExtension(ext.id)
|
|
90
|
-
);
|
|
91
|
-
await this.refreshExtensions();
|
|
92
|
-
} catch (err) {
|
|
93
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
94
|
-
this.error = msg;
|
|
95
|
-
toastError(msg);
|
|
96
|
-
} finally {
|
|
97
|
-
this.updatingId = null;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
renderExtensionRow(ext) {
|
|
101
|
-
const installed = Boolean(ext.installed);
|
|
102
|
-
const canDisable = installed && !!this.db?.disableDbExtension;
|
|
103
|
-
const isUpdating = this.updatingId === ext.id;
|
|
104
|
-
return html`
|
|
105
|
-
<div class="extension-item">
|
|
106
|
-
<div class="extension-main">
|
|
107
|
-
<div class="extension-name">${ext.label || ext.id}</div>
|
|
108
|
-
${ext.description ? html`<div class="extension-desc">${ext.description}</div>` : null}
|
|
109
|
-
</div>
|
|
110
|
-
<div class="extension-meta">
|
|
111
|
-
<span
|
|
112
|
-
class=${installed ? "badge badge-installed" : "badge badge-available"}
|
|
113
|
-
>
|
|
114
|
-
${installed ? "Installed" : "Available"}
|
|
115
|
-
</span>
|
|
116
|
-
<div class="extension-actions">
|
|
117
|
-
${installed ? html`
|
|
118
|
-
<wa-button
|
|
119
|
-
size="small"
|
|
120
|
-
appearance="plain"
|
|
121
|
-
?disabled=${!canDisable || isUpdating}
|
|
122
|
-
@click=${() => void this.disableExtension(ext)}
|
|
123
|
-
>
|
|
124
|
-
<wa-icon
|
|
125
|
-
name="circle-minus"
|
|
126
|
-
label="Disable"
|
|
127
|
-
></wa-icon>
|
|
128
|
-
</wa-button>
|
|
129
|
-
` : html`
|
|
130
|
-
<wa-button
|
|
131
|
-
size="small"
|
|
132
|
-
appearance="plain"
|
|
133
|
-
?disabled=${isUpdating}
|
|
134
|
-
@click=${() => void this.enableExtension(ext)}
|
|
135
|
-
>
|
|
136
|
-
<wa-icon
|
|
137
|
-
name="plug-circle-plus"
|
|
138
|
-
label="Enable"
|
|
139
|
-
></wa-icon>
|
|
140
|
-
</wa-button>
|
|
141
|
-
`}
|
|
142
|
-
</div>
|
|
143
|
-
</div>
|
|
144
|
-
</div>
|
|
145
|
-
`;
|
|
146
|
-
}
|
|
147
|
-
render() {
|
|
148
|
-
const hasDb = Boolean(this.db && this.db.listDbExtensions);
|
|
149
|
-
const filter = this.filterText.trim().toLowerCase();
|
|
150
|
-
const filteredExtensions = !filter ? this.extensions : this.extensions.filter((ext) => {
|
|
151
|
-
const text = `${ext.label ?? ""} ${ext.id} ${ext.description ?? ""}`.toLowerCase();
|
|
152
|
-
return text.includes(filter);
|
|
153
|
-
});
|
|
154
|
-
const hasItems = filteredExtensions.length > 0;
|
|
155
|
-
return html`
|
|
156
|
-
<wa-dialog
|
|
157
|
-
label="Database extensions"
|
|
158
|
-
?open=${this.open}
|
|
159
|
-
@wa-after-hide=${() => {
|
|
160
|
-
this.open = false;
|
|
161
|
-
this.dispatchEvent(
|
|
162
|
-
new CustomEvent("hide", { bubbles: true, composed: true })
|
|
163
|
-
);
|
|
164
|
-
}}
|
|
165
|
-
>
|
|
166
|
-
<div class="extension-manager">
|
|
167
|
-
<p class="extension-manager-description">
|
|
168
|
-
Database:
|
|
169
|
-
<strong>${this.databaseLabel || "Current connection"}</strong>
|
|
170
|
-
</p>
|
|
171
|
-
|
|
172
|
-
${!hasDb ? html`
|
|
173
|
-
<wa-alert variant="warning" open>
|
|
174
|
-
<wa-icon slot="icon" name="triangle-exclamation"></wa-icon>
|
|
175
|
-
The current SQL engine does not expose any extension information.
|
|
176
|
-
</wa-alert>
|
|
177
|
-
` : null}
|
|
178
|
-
|
|
179
|
-
${this.error ? html`
|
|
180
|
-
<wa-alert
|
|
181
|
-
variant="danger"
|
|
182
|
-
open
|
|
183
|
-
closable
|
|
184
|
-
@wa-after-hide=${() => {
|
|
185
|
-
this.error = null;
|
|
186
|
-
}}
|
|
187
|
-
>
|
|
188
|
-
<wa-icon slot="icon" name="circle-exclamation"></wa-icon>
|
|
189
|
-
${this.error}
|
|
190
|
-
</wa-alert>
|
|
191
|
-
` : null}
|
|
192
|
-
|
|
193
|
-
<wa-input
|
|
194
|
-
size="small"
|
|
195
|
-
placeholder="Filter extensions…"
|
|
196
|
-
.value=${this.filterText}
|
|
197
|
-
@input=${(event) => {
|
|
198
|
-
const target = event.target;
|
|
199
|
-
this.filterText = target?.value ?? "";
|
|
200
|
-
}}
|
|
201
|
-
@wa-clear=${() => {
|
|
202
|
-
this.filterText = "";
|
|
203
|
-
}}
|
|
204
|
-
with-clear
|
|
205
|
-
>
|
|
206
|
-
<wa-icon slot="prefix" name="magnifying-glass"></wa-icon>
|
|
207
|
-
</wa-input>
|
|
208
|
-
|
|
209
|
-
<div class="extension-list">
|
|
210
|
-
${this.loading ? html`<div class="extension-list-empty">Loading extensions…</div>` : !hasItems ? html`
|
|
211
|
-
<div class="extension-list-empty">
|
|
212
|
-
No extensions available for this connection.
|
|
213
|
-
</div>
|
|
214
|
-
` : repeat(
|
|
215
|
-
filteredExtensions,
|
|
216
|
-
(ext) => ext.id,
|
|
217
|
-
(ext) => this.renderExtensionRow(ext)
|
|
218
|
-
)}
|
|
219
|
-
</div>
|
|
220
|
-
</div>
|
|
221
|
-
<div slot="footer" class="extension-manager-footer">
|
|
222
|
-
<wa-button variant="default" @click=${() => this.hide()}>
|
|
223
|
-
Close
|
|
224
|
-
</wa-button>
|
|
225
|
-
</div>
|
|
226
|
-
</wa-dialog>
|
|
227
|
-
`;
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
LyraSqlExtensionManager.styles = css`
|
|
231
|
-
:host {
|
|
232
|
-
display: contents;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
.extension-manager {
|
|
236
|
-
display: flex;
|
|
237
|
-
flex-direction: column;
|
|
238
|
-
gap: 1rem;
|
|
239
|
-
padding: 1rem;
|
|
240
|
-
height: 420px;
|
|
241
|
-
box-sizing: border-box;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
.extension-toolbar {
|
|
245
|
-
display: flex;
|
|
246
|
-
justify-content: flex-end;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
.extension-manager-description {
|
|
250
|
-
margin: 0;
|
|
251
|
-
font-size: 0.95rem;
|
|
252
|
-
opacity: 0.9;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
.extension-list {
|
|
256
|
-
display: flex;
|
|
257
|
-
flex-direction: column;
|
|
258
|
-
gap: 0.5rem;
|
|
259
|
-
flex: 1;
|
|
260
|
-
min-height: 0;
|
|
261
|
-
max-height: 100%;
|
|
262
|
-
overflow-y: auto;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
.extension-list-empty {
|
|
266
|
-
font-size: 0.9rem;
|
|
267
|
-
opacity: 0.8;
|
|
268
|
-
padding: 0.5rem 0;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
.extension-item {
|
|
272
|
-
display: flex;
|
|
273
|
-
align-items: flex-start;
|
|
274
|
-
justify-content: space-between;
|
|
275
|
-
gap: 0.75rem;
|
|
276
|
-
padding: 0.5rem 0;
|
|
277
|
-
border-bottom: 1px solid var(--wa-color-neutral-200, #e5e7eb);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
.extension-main {
|
|
281
|
-
display: flex;
|
|
282
|
-
flex-direction: column;
|
|
283
|
-
gap: 0.15rem;
|
|
284
|
-
min-width: 0;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
.extension-name {
|
|
288
|
-
font-weight: 500;
|
|
289
|
-
font-size: 0.95rem;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
.extension-desc {
|
|
293
|
-
font-size: 0.85rem;
|
|
294
|
-
opacity: 0.8;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
.extension-meta {
|
|
298
|
-
display: flex;
|
|
299
|
-
flex-direction: column;
|
|
300
|
-
align-items: flex-end;
|
|
301
|
-
gap: 0.35rem;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
.extension-actions {
|
|
305
|
-
display: flex;
|
|
306
|
-
gap: 0.25rem;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
.badge {
|
|
310
|
-
display: inline-flex;
|
|
311
|
-
align-items: center;
|
|
312
|
-
padding: 0.15rem 0.4rem;
|
|
313
|
-
border-radius: 999px;
|
|
314
|
-
font-size: 0.75rem;
|
|
315
|
-
border: 1px solid var(--wa-color-neutral-200, #e5e7eb);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
.badge-installed {
|
|
319
|
-
background-color: var(--wa-color-success-50, #ecfdf3);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
.badge-available {
|
|
323
|
-
background-color: var(--wa-color-neutral-50, #f9fafb);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
.extension-manager-footer {
|
|
327
|
-
display: flex;
|
|
328
|
-
justify-content: flex-end;
|
|
329
|
-
padding-top: 1rem;
|
|
330
|
-
border-top: 1px solid var(--wa-color-neutral-200, #e5e7eb);
|
|
331
|
-
}
|
|
332
|
-
`;
|
|
333
|
-
__decorateClass$1([
|
|
334
|
-
property({ type: Boolean })
|
|
335
|
-
], LyraSqlExtensionManager.prototype, "open", 2);
|
|
336
|
-
__decorateClass$1([
|
|
337
|
-
property({ attribute: false })
|
|
338
|
-
], LyraSqlExtensionManager.prototype, "db", 2);
|
|
339
|
-
__decorateClass$1([
|
|
340
|
-
property()
|
|
341
|
-
], LyraSqlExtensionManager.prototype, "databaseLabel", 2);
|
|
342
|
-
__decorateClass$1([
|
|
343
|
-
state()
|
|
344
|
-
], LyraSqlExtensionManager.prototype, "extensions", 2);
|
|
345
|
-
__decorateClass$1([
|
|
346
|
-
state()
|
|
347
|
-
], LyraSqlExtensionManager.prototype, "loading", 2);
|
|
348
|
-
__decorateClass$1([
|
|
349
|
-
state()
|
|
350
|
-
], LyraSqlExtensionManager.prototype, "updatingId", 2);
|
|
351
|
-
__decorateClass$1([
|
|
352
|
-
state()
|
|
353
|
-
], LyraSqlExtensionManager.prototype, "error", 2);
|
|
354
|
-
__decorateClass$1([
|
|
355
|
-
state()
|
|
356
|
-
], LyraSqlExtensionManager.prototype, "filterText", 2);
|
|
357
|
-
LyraSqlExtensionManager = __decorateClass$1([
|
|
358
|
-
customElement("lyra-sql-extension-manager")
|
|
359
|
-
], LyraSqlExtensionManager);
|
|
360
|
-
class SqlExtensionManagerService {
|
|
361
|
-
constructor() {
|
|
362
|
-
this.managerInstance = null;
|
|
363
|
-
}
|
|
364
|
-
showExtensionManager(options) {
|
|
365
|
-
if (!options.db || !options.db.listDbExtensions) {
|
|
366
|
-
toastError("The current SQL engine does not support extensions.");
|
|
367
|
-
return null;
|
|
368
|
-
}
|
|
369
|
-
if (!this.managerInstance) {
|
|
370
|
-
this.managerInstance = document.createElement(
|
|
371
|
-
"lyra-sql-extension-manager"
|
|
372
|
-
);
|
|
373
|
-
document.body.appendChild(this.managerInstance);
|
|
374
|
-
}
|
|
375
|
-
this.managerInstance.configure(options);
|
|
376
|
-
this.managerInstance.show();
|
|
377
|
-
return this.managerInstance;
|
|
378
|
-
}
|
|
379
|
-
getManager() {
|
|
380
|
-
return this.managerInstance;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
const sqlExtensionManagerService = new SqlExtensionManagerService();
|
|
384
|
-
rootContext.put("sqlExtensionManagerService", sqlExtensionManagerService);
|
|
385
|
-
var __defProp = Object.defineProperty;
|
|
386
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
387
|
-
var __decorateClass = (decorators, target, key, kind) => {
|
|
388
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
389
|
-
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
390
|
-
if (decorator = decorators[i])
|
|
391
|
-
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
392
|
-
if (kind && result) __defProp(target, key, result);
|
|
393
|
-
return result;
|
|
394
|
-
};
|
|
395
|
-
const MAX_TAB_LABEL = 28;
|
|
396
|
-
function truncateLabel(sql) {
|
|
397
|
-
const oneLine = sql.replace(/\s+/g, " ").trim();
|
|
398
|
-
if (oneLine.length <= MAX_TAB_LABEL) return oneLine;
|
|
399
|
-
return `${oneLine.slice(0, MAX_TAB_LABEL)}…`;
|
|
400
|
-
}
|
|
401
|
-
let LyraSqlEditor = class extends LyraPart {
|
|
402
|
-
constructor() {
|
|
403
|
-
super(...arguments);
|
|
404
|
-
this.readOnly = false;
|
|
405
|
-
this.initialContent = void 0;
|
|
406
|
-
this.initialUri = void 0;
|
|
407
|
-
this.running = false;
|
|
408
|
-
this.availableAdapters = [];
|
|
409
|
-
this.selectedEngineId = null;
|
|
410
|
-
this.availableConnections = [];
|
|
411
|
-
this.selectedConnectionId = null;
|
|
412
|
-
this.widgetRef = createRef();
|
|
413
|
-
this.databases = /* @__PURE__ */ new Map();
|
|
414
|
-
this._onContentChange = () => {
|
|
415
|
-
this.markDirty(true);
|
|
416
|
-
};
|
|
417
|
-
}
|
|
418
|
-
async doInitUI() {
|
|
419
|
-
const file = this.input.data;
|
|
420
|
-
const textContents = await file.getContents();
|
|
421
|
-
this.initialContent = textContents;
|
|
422
|
-
this.initialUri = file.getWorkspacePath();
|
|
423
|
-
this.unsubscribeContributionsToken = subscribe(TOPIC_CONTRIBUTEIONS_CHANGED, (event) => {
|
|
424
|
-
if (event?.target === "system.sqladapters") {
|
|
425
|
-
void this.refreshAdapters();
|
|
426
|
-
}
|
|
427
|
-
});
|
|
428
|
-
await this.refreshAdapters();
|
|
429
|
-
this.requestUpdate();
|
|
430
|
-
}
|
|
431
|
-
async refreshAdapters() {
|
|
432
|
-
const contributions = contributionRegistry.getContributions("system.sqladapters");
|
|
433
|
-
this.availableAdapters = contributions;
|
|
434
|
-
if (!contributions.length) {
|
|
435
|
-
this.selectedEngineId = null;
|
|
436
|
-
this.availableConnections = [];
|
|
437
|
-
this.selectedConnectionId = null;
|
|
438
|
-
await this.updateComplete;
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
|
-
if (!this.selectedEngineId) {
|
|
442
|
-
const duckdbAdapter = contributions.find((c) => c.id === "duckdb");
|
|
443
|
-
this.selectedEngineId = (duckdbAdapter ?? contributions[0]).id;
|
|
444
|
-
}
|
|
445
|
-
this.requestUpdate();
|
|
446
|
-
await this.refreshConnections();
|
|
447
|
-
await this.updateComplete;
|
|
448
|
-
}
|
|
449
|
-
async getOrLoadDatabase(engineId) {
|
|
450
|
-
const cached = this.databases.get(engineId);
|
|
451
|
-
if (cached) return cached;
|
|
452
|
-
const adapter = this.availableAdapters.find((c) => c.id === engineId);
|
|
453
|
-
if (!adapter) return null;
|
|
454
|
-
try {
|
|
455
|
-
const label = adapter.label || adapter.id;
|
|
456
|
-
const database = await taskService.runAsync(`Opening ${label} database`, async (progress) => {
|
|
457
|
-
progress.message = `Connecting to ${label}…`;
|
|
458
|
-
return adapter.loader();
|
|
459
|
-
});
|
|
460
|
-
this.databases.set(engineId, database);
|
|
461
|
-
return database;
|
|
462
|
-
} catch (err) {
|
|
463
|
-
toastError(err instanceof Error ? err.message : String(err));
|
|
464
|
-
return null;
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
async refreshConnections() {
|
|
468
|
-
const engineId = this.selectedEngineId;
|
|
469
|
-
if (!engineId) {
|
|
470
|
-
this.availableConnections = [];
|
|
471
|
-
this.selectedConnectionId = null;
|
|
472
|
-
await this.updateComplete;
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
const db = await this.getOrLoadDatabase(engineId);
|
|
476
|
-
if (!db) {
|
|
477
|
-
this.availableConnections = [];
|
|
478
|
-
this.selectedConnectionId = null;
|
|
479
|
-
await this.updateComplete;
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
const infos = await db.listConnections();
|
|
483
|
-
this.availableConnections = infos;
|
|
484
|
-
const currentId = db.currentConnectionId;
|
|
485
|
-
if (currentId !== null) {
|
|
486
|
-
this.selectedConnectionId = currentId;
|
|
487
|
-
await this.updateComplete;
|
|
488
|
-
return;
|
|
489
|
-
}
|
|
490
|
-
const preferred = infos.find((info) => info.isDefault) ?? infos[0];
|
|
491
|
-
this.selectedConnectionId = preferred ? preferred.id : null;
|
|
492
|
-
if (preferred) {
|
|
493
|
-
await db.selectConnection(preferred.id ?? null);
|
|
494
|
-
}
|
|
495
|
-
await this.updateComplete;
|
|
496
|
-
}
|
|
497
|
-
async onEngineChange(e) {
|
|
498
|
-
const select = e.target;
|
|
499
|
-
const value = select?.value ?? "";
|
|
500
|
-
if (this.selectedEngineId === value) return;
|
|
501
|
-
this.selectedEngineId = value || null;
|
|
502
|
-
await this.refreshConnections();
|
|
503
|
-
this.requestUpdate();
|
|
504
|
-
}
|
|
505
|
-
async onConnectionChange(e) {
|
|
506
|
-
const select = e.target;
|
|
507
|
-
const value = select?.value ?? "";
|
|
508
|
-
const next = value === "" ? null : value;
|
|
509
|
-
if (this.selectedConnectionId === next) return;
|
|
510
|
-
this.selectedConnectionId = next;
|
|
511
|
-
const engineId = this.selectedEngineId;
|
|
512
|
-
if (!engineId) return;
|
|
513
|
-
const db = await this.getOrLoadDatabase(engineId);
|
|
514
|
-
if (!db) return;
|
|
515
|
-
await db.selectConnection(next);
|
|
516
|
-
this.requestUpdate();
|
|
517
|
-
}
|
|
518
|
-
async onEngineDropdownSelect(e) {
|
|
519
|
-
const value = e.detail?.item?.value ?? "";
|
|
520
|
-
if (this.selectedEngineId === value) return;
|
|
521
|
-
this.selectedEngineId = value || null;
|
|
522
|
-
await this.refreshConnections();
|
|
523
|
-
this.requestUpdate();
|
|
524
|
-
}
|
|
525
|
-
async onConnectionDropdownSelect(e) {
|
|
526
|
-
const value = e.detail?.item?.value ?? "";
|
|
527
|
-
const next = value === "" ? null : value;
|
|
528
|
-
if (this.selectedConnectionId === next) return;
|
|
529
|
-
this.selectedConnectionId = next;
|
|
530
|
-
const engineId = this.selectedEngineId;
|
|
531
|
-
if (!engineId) return;
|
|
532
|
-
const db = await this.getOrLoadDatabase(engineId);
|
|
533
|
-
if (!db) return;
|
|
534
|
-
await db.selectConnection(next);
|
|
535
|
-
this.requestUpdate();
|
|
536
|
-
}
|
|
537
|
-
async deleteConnectionById(e, id) {
|
|
538
|
-
e.stopPropagation();
|
|
539
|
-
e.preventDefault();
|
|
540
|
-
const engineId = this.selectedEngineId;
|
|
541
|
-
if (!engineId) return;
|
|
542
|
-
const db = await this.getOrLoadDatabase(engineId);
|
|
543
|
-
if (!db || !db.deleteConnection) return;
|
|
544
|
-
const connectionLabel = this.availableConnections.find((info) => info.id === id)?.label ?? (id === null ? "In-memory" : id ?? "Current connection");
|
|
545
|
-
const ok = await confirmDialog(`Delete connection "${connectionLabel}"?`);
|
|
546
|
-
if (!ok) return;
|
|
547
|
-
if (id !== null) {
|
|
548
|
-
await db.deleteConnection(id);
|
|
549
|
-
} else {
|
|
550
|
-
await db.selectConnection(null);
|
|
551
|
-
}
|
|
552
|
-
await this.refreshConnections();
|
|
553
|
-
this.requestUpdate();
|
|
554
|
-
}
|
|
555
|
-
save() {
|
|
556
|
-
const value = this.widgetRef.value?.getContent() ?? "";
|
|
557
|
-
this.input?.data.saveContents(value);
|
|
558
|
-
this.markDirty(false);
|
|
559
|
-
}
|
|
560
|
-
async doClose() {
|
|
561
|
-
if (this.unsubscribeContributionsToken) {
|
|
562
|
-
unsubscribe(this.unsubscribeContributionsToken);
|
|
563
|
-
this.unsubscribeContributionsToken = void 0;
|
|
564
|
-
}
|
|
565
|
-
this.widgetRef.value?.dispose();
|
|
566
|
-
for (const db of this.databases.values()) {
|
|
567
|
-
await db.close();
|
|
568
|
-
}
|
|
569
|
-
this.databases.clear();
|
|
570
|
-
}
|
|
571
|
-
getLanguage() {
|
|
572
|
-
return "sql";
|
|
573
|
-
}
|
|
574
|
-
isLanguage(lang) {
|
|
575
|
-
return lang.toLowerCase() === "sql";
|
|
576
|
-
}
|
|
577
|
-
getContent() {
|
|
578
|
-
return this.widgetRef.value?.getContent() ?? null;
|
|
579
|
-
}
|
|
580
|
-
getSelection() {
|
|
581
|
-
return this.widgetRef.value?.getSelection() ?? null;
|
|
582
|
-
}
|
|
583
|
-
getSnippet(lines = 5) {
|
|
584
|
-
return this.widgetRef.value?.getSnippet(lines) ?? null;
|
|
585
|
-
}
|
|
586
|
-
getFilePath() {
|
|
587
|
-
return this.input?.data?.getWorkspacePath() ?? null;
|
|
588
|
-
}
|
|
589
|
-
async runQuery(useSelectionOnly = false) {
|
|
590
|
-
const selection = this.getSelection()?.trim();
|
|
591
|
-
const content = this.getContent()?.trim();
|
|
592
|
-
const sql = useSelectionOnly ? selection : content;
|
|
593
|
-
if (!sql) {
|
|
594
|
-
toastError(useSelectionOnly ? "No selection to run" : "No SQL to run");
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
if (this.running) return;
|
|
598
|
-
const engineId = this.selectedEngineId;
|
|
599
|
-
if (!engineId) {
|
|
600
|
-
toastError("No SQL engine available");
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
const db = await this.getOrLoadDatabase(engineId);
|
|
604
|
-
if (!db) {
|
|
605
|
-
toastError("Could not initialize SQL engine");
|
|
606
|
-
return;
|
|
607
|
-
}
|
|
608
|
-
if (!this.selectedConnectionId && this.availableConnections.length) {
|
|
609
|
-
const preferred = this.availableConnections.find(
|
|
610
|
-
(info) => info.isDefault
|
|
611
|
-
) ?? this.availableConnections[0];
|
|
612
|
-
this.selectedConnectionId = preferred.id;
|
|
613
|
-
await db.selectConnection(preferred.id ?? null);
|
|
614
|
-
}
|
|
615
|
-
this.running = true;
|
|
616
|
-
const label = truncateLabel(sql);
|
|
617
|
-
this.requestUpdate();
|
|
618
|
-
const timeoutMs = 6e4;
|
|
619
|
-
const timeoutId = window.setTimeout(() => this.clearRunningState(), timeoutMs);
|
|
620
|
-
try {
|
|
621
|
-
const result = await db.runQuery(sql);
|
|
622
|
-
const adapter = this.availableAdapters.find((c) => c.id === engineId);
|
|
623
|
-
publish("dataview/publish", {
|
|
624
|
-
title: label,
|
|
625
|
-
data: { columns: result.columns, rows: result.rows },
|
|
626
|
-
source: adapter?.label ?? engineId
|
|
627
|
-
});
|
|
628
|
-
} catch (err) {
|
|
629
|
-
toastError(err instanceof Error ? err.message : String(err));
|
|
630
|
-
} finally {
|
|
631
|
-
window.clearTimeout(timeoutId);
|
|
632
|
-
this.running = false;
|
|
633
|
-
this.requestUpdate();
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
clearRunningState() {
|
|
637
|
-
if (!this.running) return;
|
|
638
|
-
this.running = false;
|
|
639
|
-
this.requestUpdate();
|
|
640
|
-
}
|
|
641
|
-
async createConnection() {
|
|
642
|
-
const engineId = this.selectedEngineId;
|
|
643
|
-
if (!engineId) return;
|
|
644
|
-
const db = await this.getOrLoadDatabase(engineId);
|
|
645
|
-
if (!db || !db.createConnection) return;
|
|
646
|
-
const info = await db.createConnection();
|
|
647
|
-
if (!info) return;
|
|
648
|
-
await this.refreshConnections();
|
|
649
|
-
this.selectedConnectionId = info.id;
|
|
650
|
-
await db.selectConnection(info.id ?? null);
|
|
651
|
-
toastInfo(`Connection "${info.label}" created`);
|
|
652
|
-
this.requestUpdate();
|
|
653
|
-
}
|
|
654
|
-
async deleteConnection() {
|
|
655
|
-
const engineId = this.selectedEngineId;
|
|
656
|
-
if (!engineId) return;
|
|
657
|
-
const db = await this.getOrLoadDatabase(engineId);
|
|
658
|
-
if (!db || !db.deleteConnection) return;
|
|
659
|
-
const id = this.selectedConnectionId;
|
|
660
|
-
const connectionLabel = this.availableConnections.find((info) => info.id === id)?.label ?? (id === null ? "In-memory" : id ?? "Current connection");
|
|
661
|
-
const ok = await confirmDialog(`Delete connection "${connectionLabel}"?`);
|
|
662
|
-
if (!ok) return;
|
|
663
|
-
if (id !== null) {
|
|
664
|
-
await db.deleteConnection(id);
|
|
665
|
-
} else {
|
|
666
|
-
await db.selectConnection(null);
|
|
667
|
-
}
|
|
668
|
-
await this.refreshConnections();
|
|
669
|
-
this.requestUpdate();
|
|
670
|
-
}
|
|
671
|
-
getCurrentConnectionLabel() {
|
|
672
|
-
const id = this.selectedConnectionId;
|
|
673
|
-
if (id === null) return "In-memory";
|
|
674
|
-
if (!id) return null;
|
|
675
|
-
const info = this.availableConnections.find((c) => c.id === id);
|
|
676
|
-
return info?.label ?? id;
|
|
677
|
-
}
|
|
678
|
-
async openExtensionManager() {
|
|
679
|
-
const engineId = this.selectedEngineId;
|
|
680
|
-
if (!engineId) return;
|
|
681
|
-
const db = await this.getOrLoadDatabase(engineId);
|
|
682
|
-
if (!db || !db.listDbExtensions) {
|
|
683
|
-
toastInfo("Extensions are not available for the selected SQL engine.");
|
|
684
|
-
return;
|
|
685
|
-
}
|
|
686
|
-
const adapter = this.availableAdapters.find((c) => c.id === engineId) ?? null;
|
|
687
|
-
const engineLabel = adapter?.label ?? engineId;
|
|
688
|
-
const connectionLabel = this.getCurrentConnectionLabel();
|
|
689
|
-
const databaseLabel = connectionLabel ? `${engineLabel} – ${connectionLabel}` : engineLabel;
|
|
690
|
-
sqlExtensionManagerService.showExtensionManager({
|
|
691
|
-
db,
|
|
692
|
-
databaseLabel
|
|
693
|
-
});
|
|
694
|
-
}
|
|
695
|
-
renderToolbar() {
|
|
696
|
-
const adapters = this.availableAdapters;
|
|
697
|
-
const hasEngines = adapters.length > 0;
|
|
698
|
-
const hasConnections = this.availableConnections.length > 0;
|
|
699
|
-
const engineId = this.selectedEngineId;
|
|
700
|
-
const dbForEngine = engineId ? this.databases.get(engineId) : null;
|
|
701
|
-
const supportsExtensions = Boolean(dbForEngine?.listDbExtensions);
|
|
702
|
-
return html`
|
|
703
|
-
<wa-dropdown
|
|
704
|
-
class="engine-select"
|
|
705
|
-
placement="bottom-start"
|
|
706
|
-
distance="4"
|
|
707
|
-
size="small"
|
|
708
|
-
@wa-select=${(e) => void this.onEngineDropdownSelect(e)}
|
|
709
|
-
>
|
|
710
|
-
<wa-button
|
|
711
|
-
slot="trigger"
|
|
712
|
-
appearance="plain"
|
|
713
|
-
size="small"
|
|
714
|
-
with-caret
|
|
715
|
-
title="SQL engine"
|
|
716
|
-
>
|
|
717
|
-
${this.selectedEngineId ? adapters.find((a) => a.id === this.selectedEngineId)?.label ?? this.selectedEngineId : "Select engine"}
|
|
718
|
-
</wa-button>
|
|
719
|
-
${adapters.map(
|
|
720
|
-
(adapter) => html`
|
|
721
|
-
<wa-dropdown-item
|
|
722
|
-
value=${adapter.id}
|
|
723
|
-
type="checkbox"
|
|
724
|
-
?checked=${adapter.id === this.selectedEngineId}
|
|
725
|
-
>
|
|
726
|
-
${adapter.label}
|
|
727
|
-
</wa-dropdown-item>
|
|
728
|
-
`
|
|
729
|
-
)}
|
|
730
|
-
</wa-dropdown>
|
|
731
|
-
<wa-dropdown
|
|
732
|
-
class="connection-select"
|
|
733
|
-
placement="bottom-start"
|
|
734
|
-
distance="4"
|
|
735
|
-
size="small"
|
|
736
|
-
@wa-select=${(e) => void this.onConnectionDropdownSelect(e)}
|
|
737
|
-
>
|
|
738
|
-
<wa-button
|
|
739
|
-
slot="trigger"
|
|
740
|
-
appearance="plain"
|
|
741
|
-
size="small"
|
|
742
|
-
with-caret
|
|
743
|
-
title="Connection"
|
|
744
|
-
?disabled=${!hasEngines || !hasConnections}
|
|
745
|
-
>
|
|
746
|
-
${this.selectedConnectionId === null ? "In-memory" : this.availableConnections.find(
|
|
747
|
-
(c) => c.id === this.selectedConnectionId
|
|
748
|
-
)?.label ?? "Select connection"}
|
|
749
|
-
</wa-button>
|
|
750
|
-
${this.availableConnections.map(
|
|
751
|
-
(info) => html`
|
|
752
|
-
<wa-dropdown-item
|
|
753
|
-
value=${info.id ?? ""}
|
|
754
|
-
type="checkbox"
|
|
755
|
-
?checked=${info.id === this.selectedConnectionId}
|
|
756
|
-
>
|
|
757
|
-
${info.label}
|
|
758
|
-
<wa-button
|
|
759
|
-
slot="details"
|
|
760
|
-
appearance="plain"
|
|
761
|
-
size="small"
|
|
762
|
-
title=${info.id === null ? "Reset in-memory connection" : "Delete connection"}
|
|
763
|
-
@click=${(e) => this.deleteConnectionById(e, info.id)}
|
|
764
|
-
>
|
|
765
|
-
<wa-icon
|
|
766
|
-
name=${info.id === null ? "rotate-right" : "trash"}
|
|
767
|
-
label=${info.id === null ? "Reset" : "Delete"}
|
|
768
|
-
></wa-icon>
|
|
769
|
-
</wa-button>
|
|
770
|
-
</wa-dropdown-item>
|
|
771
|
-
`
|
|
772
|
-
)}
|
|
773
|
-
</wa-dropdown>
|
|
774
|
-
<wa-button
|
|
775
|
-
size="small"
|
|
776
|
-
appearance="plain"
|
|
777
|
-
title="New connection"
|
|
778
|
-
@click=${() => void this.createConnection()}
|
|
779
|
-
>
|
|
780
|
-
<wa-icon name="plus" label="New"></wa-icon>
|
|
781
|
-
</wa-button>
|
|
782
|
-
${supportsExtensions ? html`
|
|
783
|
-
<wa-button
|
|
784
|
-
size="small"
|
|
785
|
-
appearance="plain"
|
|
786
|
-
title="Manage extensions"
|
|
787
|
-
?disabled=${!hasEngines || !hasConnections}
|
|
788
|
-
@click=${() => void this.openExtensionManager()}
|
|
789
|
-
>
|
|
790
|
-
<wa-icon name="puzzle-piece" label="Extensions"></wa-icon>
|
|
791
|
-
Extensions
|
|
792
|
-
</wa-button>
|
|
793
|
-
` : null}
|
|
794
|
-
<wa-button
|
|
795
|
-
size="small"
|
|
796
|
-
appearance="plain"
|
|
797
|
-
?disabled=${this.running}
|
|
798
|
-
@click=${() => void this.runQuery(true)}
|
|
799
|
-
title="Run selection only"
|
|
800
|
-
>
|
|
801
|
-
<wa-icon name="i-cursor" label="Run selection"></wa-icon>
|
|
802
|
-
${this.running ? "Running…" : "Run selection"}
|
|
803
|
-
</wa-button>
|
|
804
|
-
<wa-button
|
|
805
|
-
size="small"
|
|
806
|
-
appearance="plain"
|
|
807
|
-
?disabled=${this.running}
|
|
808
|
-
@click=${() => void this.runQuery(false)}
|
|
809
|
-
title="Run all SQL"
|
|
810
|
-
>
|
|
811
|
-
<wa-icon name="play" label="Run"></wa-icon>
|
|
812
|
-
${this.running ? "Running…" : "Run all"}
|
|
813
|
-
</wa-button>
|
|
814
|
-
`;
|
|
815
|
-
}
|
|
816
|
-
renderContent() {
|
|
817
|
-
if (this.initialContent === void 0) {
|
|
818
|
-
return html`<div class="editor-placeholder"></div>`;
|
|
819
|
-
}
|
|
820
|
-
return html`
|
|
821
|
-
<div class="editor-area">
|
|
822
|
-
<lyra-monaco-widget
|
|
823
|
-
.value=${this.initialContent}
|
|
824
|
-
.uri=${this.initialUri}
|
|
825
|
-
.language=${"sql"}
|
|
826
|
-
.readOnly=${this.readOnly}
|
|
827
|
-
@content-change=${this._onContentChange}
|
|
828
|
-
${ref(this.widgetRef)}
|
|
829
|
-
></lyra-monaco-widget>
|
|
830
|
-
</div>
|
|
831
|
-
`;
|
|
832
|
-
}
|
|
833
|
-
};
|
|
834
|
-
LyraSqlEditor.styles = css`
|
|
835
|
-
:host {
|
|
836
|
-
display: flex;
|
|
837
|
-
flex-direction: column;
|
|
838
|
-
position: relative;
|
|
839
|
-
width: 100%;
|
|
840
|
-
height: 100%;
|
|
841
|
-
}
|
|
842
|
-
.engine-select {
|
|
843
|
-
max-width: 10rem;
|
|
844
|
-
}
|
|
845
|
-
.connection-select {
|
|
846
|
-
max-width: 12rem;
|
|
847
|
-
}
|
|
848
|
-
.editor-area {
|
|
849
|
-
flex: 1;
|
|
850
|
-
min-height: 0;
|
|
851
|
-
height: 100%;
|
|
852
|
-
display: flex;
|
|
853
|
-
flex-direction: column;
|
|
854
|
-
overflow: hidden;
|
|
855
|
-
}
|
|
856
|
-
.editor-area lyra-monaco-widget,
|
|
857
|
-
.editor-area monaco-widget {
|
|
858
|
-
flex: 1;
|
|
859
|
-
min-height: 0;
|
|
860
|
-
}
|
|
861
|
-
.editor-placeholder {
|
|
862
|
-
flex: 1;
|
|
863
|
-
min-height: 0;
|
|
864
|
-
}
|
|
865
|
-
`;
|
|
866
|
-
__decorateClass([
|
|
867
|
-
property({ attribute: false })
|
|
868
|
-
], LyraSqlEditor.prototype, "input", 2);
|
|
869
|
-
__decorateClass([
|
|
870
|
-
property({ type: Boolean })
|
|
871
|
-
], LyraSqlEditor.prototype, "readOnly", 2);
|
|
872
|
-
__decorateClass([
|
|
873
|
-
state()
|
|
874
|
-
], LyraSqlEditor.prototype, "initialContent", 2);
|
|
875
|
-
__decorateClass([
|
|
876
|
-
state()
|
|
877
|
-
], LyraSqlEditor.prototype, "initialUri", 2);
|
|
878
|
-
__decorateClass([
|
|
879
|
-
state()
|
|
880
|
-
], LyraSqlEditor.prototype, "running", 2);
|
|
881
|
-
__decorateClass([
|
|
882
|
-
state()
|
|
883
|
-
], LyraSqlEditor.prototype, "availableAdapters", 2);
|
|
884
|
-
__decorateClass([
|
|
885
|
-
state()
|
|
886
|
-
], LyraSqlEditor.prototype, "selectedEngineId", 2);
|
|
887
|
-
__decorateClass([
|
|
888
|
-
state()
|
|
889
|
-
], LyraSqlEditor.prototype, "availableConnections", 2);
|
|
890
|
-
__decorateClass([
|
|
891
|
-
state()
|
|
892
|
-
], LyraSqlEditor.prototype, "selectedConnectionId", 2);
|
|
893
|
-
LyraSqlEditor = __decorateClass([
|
|
894
|
-
customElement("lyra-sql-editor")
|
|
895
|
-
], LyraSqlEditor);
|
|
896
|
-
function activate() {
|
|
897
|
-
editorRegistry.registerEditorInputHandler({
|
|
898
|
-
editorId: "system.sqleditor",
|
|
899
|
-
label: "SQL Editor",
|
|
900
|
-
icon: "database",
|
|
901
|
-
canHandle: (input) => input instanceof File && input.getName().toLowerCase().endsWith(".sql"),
|
|
902
|
-
ranking: 900,
|
|
903
|
-
handle: async (input) => {
|
|
904
|
-
const editorInput = {
|
|
905
|
-
title: input.getWorkspacePath(),
|
|
906
|
-
data: input,
|
|
907
|
-
key: input.getWorkspacePath(),
|
|
908
|
-
icon: "database",
|
|
909
|
-
state: {},
|
|
910
|
-
component: () => null
|
|
911
|
-
};
|
|
912
|
-
editorInput.component = (id) => html$1`<lyra-sql-editor id="${id}" .input=${editorInput}></lyra-sql-editor>`;
|
|
913
|
-
return editorInput;
|
|
914
|
-
}
|
|
915
|
-
});
|
|
916
|
-
}
|
|
917
|
-
export {
|
|
918
|
-
activate as default
|
|
919
|
-
};
|
|
920
|
-
//# sourceMappingURL=sqleditor-extension-BFAaVI-7.js.map
|