@hienlh/ppm 0.13.48 → 0.13.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +1 -1
- package/dist/web/assets/{audio-preview-BFc4v5Tx.js → audio-preview-CILFIsuu.js} +2 -2
- package/dist/web/assets/{audio-preview-BFc4v5Tx.js.map → audio-preview-CILFIsuu.js.map} +1 -1
- package/dist/web/assets/{chat-tab-x1rBGHj5.js → chat-tab-DBYwH_Aa.js} +4 -4
- package/dist/web/assets/{chat-tab-x1rBGHj5.js.map → chat-tab-DBYwH_Aa.js.map} +1 -1
- package/dist/web/assets/{code-editor-BgyAZcQX.js → code-editor-MXnkYRLp.js} +3 -3
- package/dist/web/assets/{code-editor-BgyAZcQX.js.map → code-editor-MXnkYRLp.js.map} +1 -1
- package/dist/web/assets/{conflict-editor-Dhc1lem7.js → conflict-editor-C6wH5wV6.js} +2 -2
- package/dist/web/assets/{conflict-editor-Dhc1lem7.js.map → conflict-editor-C6wH5wV6.js.map} +1 -1
- package/dist/web/assets/{database-viewer-DnnjO38W.js → database-viewer-BjUruZLv.js} +2 -2
- package/dist/web/assets/{database-viewer-DnnjO38W.js.map → database-viewer-BjUruZLv.js.map} +1 -1
- package/dist/web/assets/{diff-viewer-B6q9wXD6.js → diff-viewer-B_nU7bQi.js} +2 -2
- package/dist/web/assets/{diff-viewer-B6q9wXD6.js.map → diff-viewer-B_nU7bQi.js.map} +1 -1
- package/dist/web/assets/{extension-webview-CMBEb4FF.js → extension-webview-B56ZfvoD.js} +2 -2
- package/dist/web/assets/{extension-webview-CMBEb4FF.js.map → extension-webview-B56ZfvoD.js.map} +1 -1
- package/dist/web/assets/{glide-data-grid-BLcBAxgp.js → glide-data-grid-D-qQqqp7.js} +2 -2
- package/dist/web/assets/{glide-data-grid-BLcBAxgp.js.map → glide-data-grid-D-qQqqp7.js.map} +1 -1
- package/dist/web/assets/{image-preview-YpWk7AOb.js → image-preview-Dc6AiqYX.js} +2 -2
- package/dist/web/assets/{image-preview-YpWk7AOb.js.map → image-preview-Dc6AiqYX.js.map} +1 -1
- package/dist/web/assets/{index-hxAGD2rx.js → index-8_rE2Q1-.js} +6 -6
- package/dist/web/assets/{index-hxAGD2rx.js.map → index-8_rE2Q1-.js.map} +1 -1
- package/dist/web/assets/keybindings-store-COJD5O6M.js +1 -0
- package/dist/web/assets/{markdown-renderer-BAAmsTL9.js → markdown-renderer-CNQ8I0Dk.js} +2 -2
- package/dist/web/assets/{markdown-renderer-BAAmsTL9.js.map → markdown-renderer-CNQ8I0Dk.js.map} +1 -1
- package/dist/web/assets/notification-store-BiZaLXop.js +1 -0
- package/dist/web/assets/{panel-store-Dy8-7E_g.js → panel-store-C8wwxBpn.js} +2 -2
- package/dist/web/assets/{panel-store-Dy8-7E_g.js.map → panel-store-C8wwxBpn.js.map} +1 -1
- package/dist/web/assets/{pdf-preview-DWe7ARXI.js → pdf-preview-zs9QdgDp.js} +2 -2
- package/dist/web/assets/{pdf-preview-DWe7ARXI.js.map → pdf-preview-zs9QdgDp.js.map} +1 -1
- package/dist/web/assets/{port-forwarding-tab-R5V7zkKO.js → port-forwarding-tab-sArYx1nt.js} +2 -2
- package/dist/web/assets/{port-forwarding-tab-R5V7zkKO.js.map → port-forwarding-tab-sArYx1nt.js.map} +1 -1
- package/dist/web/assets/{postgres-viewer-AxCUyDQP.js → postgres-viewer-khk7N7cd.js} +2 -2
- package/dist/web/assets/{postgres-viewer-AxCUyDQP.js.map → postgres-viewer-khk7N7cd.js.map} +1 -1
- package/dist/web/assets/{settings-tab-CJ6w6q2s.js → settings-tab-CGWhVzQm.js} +1 -1
- package/dist/web/assets/{sql-query-editor-DhZvNbKv.js → sql-query-editor-B5Ndypxp.js} +2 -2
- package/dist/web/assets/{sql-query-editor-DhZvNbKv.js.map → sql-query-editor-B5Ndypxp.js.map} +1 -1
- package/dist/web/assets/{sqlite-viewer-Qv8TlhPb.js → sqlite-viewer-BkpONSGa.js} +2 -2
- package/dist/web/assets/{sqlite-viewer-Qv8TlhPb.js.map → sqlite-viewer-BkpONSGa.js.map} +1 -1
- package/dist/web/assets/{tab-store-Dtg1_qL0.js → tab-store-CNas5Ny8.js} +2 -2
- package/dist/web/assets/{tab-store-Dtg1_qL0.js.map → tab-store-CNas5Ny8.js.map} +1 -1
- package/dist/web/assets/{terminal-tab-9hLQtUUT.js → terminal-tab-BgMCsdeN.js} +2 -2
- package/dist/web/assets/{terminal-tab-9hLQtUUT.js.map → terminal-tab-BgMCsdeN.js.map} +1 -1
- package/dist/web/assets/{video-preview-C-tj7tok.js → video-preview-w8ZAy8av.js} +2 -2
- package/dist/web/assets/{video-preview-C-tj7tok.js.map → video-preview-w8ZAy8av.js.map} +1 -1
- package/dist/web/index.html +3 -3
- package/dist/web/sw.js +1 -1
- package/package.json +1 -1
- package/src/services/db.service.ts +28 -0
- package/src/types/extension.ts +1 -1
- package/src/web/components/settings/extension-manager-section.tsx +2 -2
- package/src/web/stores/panel-store.ts +5 -0
- package/dist/web/assets/keybindings-store-Dn9ANcCK.js +0 -1
- package/dist/web/assets/notification-store-DyVQiPv9.js +0 -1
- package/packages/ext-database/package.json +0 -48
- package/packages/ext-database/src/connection-tree.ts +0 -201
- package/packages/ext-database/src/extension.ts +0 -578
- package/packages/ext-database/src/query-panel.ts +0 -133
- package/packages/ext-database/src/table-viewer-panel.ts +0 -420
- package/packages/ext-database/tsconfig.json +0 -8
|
@@ -610,6 +610,34 @@ function runMigrations(database: Database): void {
|
|
|
610
610
|
try { database.exec("ALTER TABLE session_metadata ADD COLUMN last_known_title TEXT"); } catch { /* column exists */ }
|
|
611
611
|
database.exec("PRAGMA user_version = 23");
|
|
612
612
|
}
|
|
613
|
+
|
|
614
|
+
if (current < 25) {
|
|
615
|
+
// Re-create extension tables if missing (e.g. after accidental drop)
|
|
616
|
+
database.exec(`
|
|
617
|
+
CREATE TABLE IF NOT EXISTS extensions (
|
|
618
|
+
id TEXT PRIMARY KEY,
|
|
619
|
+
version TEXT NOT NULL,
|
|
620
|
+
display_name TEXT,
|
|
621
|
+
description TEXT,
|
|
622
|
+
icon TEXT,
|
|
623
|
+
enabled INTEGER DEFAULT 1,
|
|
624
|
+
manifest TEXT NOT NULL,
|
|
625
|
+
installed_at TEXT DEFAULT (datetime('now')),
|
|
626
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
CREATE TABLE IF NOT EXISTS extension_storage (
|
|
630
|
+
ext_id TEXT NOT NULL,
|
|
631
|
+
scope TEXT NOT NULL,
|
|
632
|
+
key TEXT NOT NULL,
|
|
633
|
+
value TEXT,
|
|
634
|
+
PRIMARY KEY (ext_id, scope, key),
|
|
635
|
+
FOREIGN KEY (ext_id) REFERENCES extensions(id) ON DELETE CASCADE
|
|
636
|
+
);
|
|
637
|
+
|
|
638
|
+
PRAGMA user_version = 25;
|
|
639
|
+
`);
|
|
640
|
+
}
|
|
613
641
|
}
|
|
614
642
|
|
|
615
643
|
// ---------------------------------------------------------------------------
|
package/src/types/extension.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Extension manifest — parsed from package.json of an installed extension */
|
|
2
2
|
export interface ExtensionManifest {
|
|
3
|
-
id: string; // npm package name, e.g. @ppm/ext-
|
|
3
|
+
id: string; // npm package name, e.g. @ppm/ext-myext
|
|
4
4
|
version: string;
|
|
5
5
|
main: string; // JS entry point relative to extension root
|
|
6
6
|
displayName?: string;
|
|
@@ -97,7 +97,7 @@ export function ExtensionManagerSection() {
|
|
|
97
97
|
value={installName}
|
|
98
98
|
onChange={(e) => setInstallName(e.target.value)}
|
|
99
99
|
onKeyDown={(e) => { if (e.key === "Enter") handleInstall(); }}
|
|
100
|
-
placeholder="npm package name (e.g. @ppm/ext-
|
|
100
|
+
placeholder="npm package name (e.g. @ppm/ext-myext)"
|
|
101
101
|
className="h-8 text-xs flex-1"
|
|
102
102
|
/>
|
|
103
103
|
<Button
|
|
@@ -122,7 +122,7 @@ export function ExtensionManagerSection() {
|
|
|
122
122
|
<Input
|
|
123
123
|
value={devPath}
|
|
124
124
|
onChange={(e) => setDevPath(e.target.value)}
|
|
125
|
-
placeholder="Local path (e.g. ./packages/ext-
|
|
125
|
+
placeholder="Local path (e.g. ./packages/ext-myext)"
|
|
126
126
|
className="h-8 text-xs flex-1"
|
|
127
127
|
/>
|
|
128
128
|
<Button
|
|
@@ -323,6 +323,11 @@ export const usePanelStore = create<PanelStore>()((set, get) => {
|
|
|
323
323
|
if (!panel) return;
|
|
324
324
|
const pid = panel.id;
|
|
325
325
|
|
|
326
|
+
// Clear persisted terminal session so reopening creates a fresh PTY
|
|
327
|
+
if (tabId.startsWith("terminal:")) {
|
|
328
|
+
try { localStorage.removeItem(`ppm:terminal-session:${tabId}`); } catch { /* */ }
|
|
329
|
+
}
|
|
330
|
+
|
|
326
331
|
set((s) => {
|
|
327
332
|
const p = s.panels[pid]!;
|
|
328
333
|
const newTabs = p.tabs.filter((t) => t.id !== tabId);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./vendor-markdown-0Mxgxy0L.js";import"./api-client-DIhJ5qVW.js";import{T as e}from"./index-hxAGD2rx.js";export{e as useKeybindingsStore};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./vendor-markdown-0Mxgxy0L.js";import"./api-client-DIhJ5qVW.js";import{j as e}from"./index-hxAGD2rx.js";export{e as useNotificationStore};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@ppm/ext-database",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"main": "src/extension.ts",
|
|
5
|
-
"engines": { "ppm": ">=0.9.0" },
|
|
6
|
-
"activationEvents": ["onCommand:ppm-db.openViewer", "onView:ppm-db.connections"],
|
|
7
|
-
"contributes": {
|
|
8
|
-
"commands": [
|
|
9
|
-
{ "command": "ppm-db.openViewer", "title": "Database: Open Viewer" },
|
|
10
|
-
{ "command": "ppm-db.runQuery", "title": "Database: Run SQL Query" },
|
|
11
|
-
{ "command": "ppm-db.refreshConnections", "title": "Database: Refresh Connections", "icon": "refresh" },
|
|
12
|
-
{ "command": "ppm-db.addConnection", "title": "Add connection", "icon": "plus" },
|
|
13
|
-
{ "command": "ppm-db.editConnection", "title": "Database: Edit Connection" },
|
|
14
|
-
{ "command": "ppm-db.deleteConnection", "title": "Database: Delete Connection" },
|
|
15
|
-
{ "command": "ppm-db.testConnection", "title": "Database: Test Connection" },
|
|
16
|
-
{ "command": "ppm-db.exportConnections", "title": "Database: Export Connections" },
|
|
17
|
-
{ "command": "ppm-db.importConnections", "title": "Database: Import Connections" }
|
|
18
|
-
],
|
|
19
|
-
"views": {
|
|
20
|
-
"sidebar": [
|
|
21
|
-
{ "id": "ppm-db.connections", "name": "DB Connections", "type": "tree" }
|
|
22
|
-
]
|
|
23
|
-
},
|
|
24
|
-
"menus": {
|
|
25
|
-
"commandPalette": [
|
|
26
|
-
{ "command": "ppm-db.openViewer" },
|
|
27
|
-
{ "command": "ppm-db.runQuery" },
|
|
28
|
-
{ "command": "ppm-db.exportConnections" },
|
|
29
|
-
{ "command": "ppm-db.importConnections" }
|
|
30
|
-
],
|
|
31
|
-
"view/title": [
|
|
32
|
-
{ "command": "ppm-db.refreshConnections", "when": "view == ppm-db.connections", "group": "navigation" },
|
|
33
|
-
{ "command": "ppm-db.addConnection", "when": "view == ppm-db.connections", "group": "navigation" }
|
|
34
|
-
]
|
|
35
|
-
},
|
|
36
|
-
"configuration": {
|
|
37
|
-
"properties": {
|
|
38
|
-
"ppm-db.maxRows": { "type": "number", "default": 100, "description": "Max rows to display" },
|
|
39
|
-
"ppm-db.autoConnect": { "type": "boolean", "default": true, "description": "Auto-connect on open" }
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
"ppm": {
|
|
44
|
-
"displayName": "Database Viewer",
|
|
45
|
-
"icon": "database",
|
|
46
|
-
"webviewDir": "webview"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TreeDataProvider for database connections → tables → columns.
|
|
3
|
-
* Fetches data from PPM REST API (/api/db/*).
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
interface ConnectionNode {
|
|
7
|
-
id: string;
|
|
8
|
-
name: string;
|
|
9
|
-
type: "connection" | "group" | "table" | "column";
|
|
10
|
-
connectionId?: number;
|
|
11
|
-
connectionName?: string;
|
|
12
|
-
connectionType?: string;
|
|
13
|
-
connectionColor?: string | null;
|
|
14
|
-
connectionReadonly?: number;
|
|
15
|
-
groupName?: string | null;
|
|
16
|
-
schemaName?: string;
|
|
17
|
-
dataType?: string;
|
|
18
|
-
rowCount?: number;
|
|
19
|
-
children?: ConnectionNode[];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface ApiConnection {
|
|
23
|
-
id: number;
|
|
24
|
-
name: string;
|
|
25
|
-
type: string;
|
|
26
|
-
color: string | null;
|
|
27
|
-
readonly: number;
|
|
28
|
-
group_name: string | null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
interface ApiTable {
|
|
32
|
-
name: string;
|
|
33
|
-
schema: string;
|
|
34
|
-
rowCount: number;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
interface ApiColumn {
|
|
38
|
-
name: string;
|
|
39
|
-
type: string;
|
|
40
|
-
nullable: boolean;
|
|
41
|
-
pk: boolean;
|
|
42
|
-
defaultValue: string | null;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export class ConnectionTreeProvider {
|
|
46
|
-
private _onDidChange: { fire: (el?: ConnectionNode) => void; event: unknown };
|
|
47
|
-
private baseUrl: string;
|
|
48
|
-
|
|
49
|
-
constructor(eventEmitter: { fire: (el?: ConnectionNode) => void; event: unknown }, baseUrl = "") {
|
|
50
|
-
this._onDidChange = eventEmitter;
|
|
51
|
-
this.baseUrl = baseUrl;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
get onDidChangeTreeData() {
|
|
55
|
-
return this._onDidChange.event;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
refresh(): void {
|
|
59
|
-
this._onDidChange.fire(undefined);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async getChildren(element?: ConnectionNode): Promise<ConnectionNode[]> {
|
|
63
|
-
if (!element) return this.getRootNodes();
|
|
64
|
-
if (element.type === "group") return element.children ?? [];
|
|
65
|
-
if (element.type === "connection") return this.getTables(element);
|
|
66
|
-
if (element.type === "table") return this.getColumns(element);
|
|
67
|
-
return [];
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
getTreeItem(element: ConnectionNode): Record<string, unknown> {
|
|
71
|
-
const isConn = element.type === "connection";
|
|
72
|
-
const isGroup = element.type === "group";
|
|
73
|
-
const isTable = element.type === "table";
|
|
74
|
-
const isCol = element.type === "column";
|
|
75
|
-
|
|
76
|
-
// Table description: row count
|
|
77
|
-
let description: string | undefined;
|
|
78
|
-
if (isCol) description = element.dataType;
|
|
79
|
-
else if (isTable && element.rowCount !== undefined) description = `${element.rowCount.toLocaleString()} rows`;
|
|
80
|
-
|
|
81
|
-
// Connection badge: type + readonly
|
|
82
|
-
let badge: string | undefined;
|
|
83
|
-
if (isConn) {
|
|
84
|
-
badge = element.connectionType === "postgres" ? "PG" : "DB";
|
|
85
|
-
if (element.connectionReadonly === 1) badge += " 🔒";
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
id: element.id,
|
|
90
|
-
label: element.name,
|
|
91
|
-
description,
|
|
92
|
-
collapsibleState: isCol ? "none" : "collapsed",
|
|
93
|
-
contextValue: element.type,
|
|
94
|
-
command: isTable ? "ppm-db.openViewer" : undefined,
|
|
95
|
-
commandArgs: isTable
|
|
96
|
-
? [element.connectionId, element.connectionName ?? "Database", element.name, element.schemaName ?? "public"]
|
|
97
|
-
: undefined,
|
|
98
|
-
color: isConn ? (element.connectionColor ?? undefined) : undefined,
|
|
99
|
-
badge,
|
|
100
|
-
actions: isConn ? [
|
|
101
|
-
{ icon: "refresh", tooltip: "Refresh tables", command: "ppm-db.refreshConnection", commandArgs: [element.connectionId] },
|
|
102
|
-
{ icon: "edit", tooltip: "Edit connection", command: "ppm-db.editConnection", commandArgs: [element.connectionId] },
|
|
103
|
-
{ icon: "trash", tooltip: "Delete connection", command: "ppm-db.deleteConnection", commandArgs: [element.connectionId, element.name] },
|
|
104
|
-
] : isGroup ? [] : undefined,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/** Build root tree: group nodes wrapping connection nodes, or flat if no groups */
|
|
109
|
-
private async getRootNodes(): Promise<ConnectionNode[]> {
|
|
110
|
-
const connections = await this.getConnections();
|
|
111
|
-
// Group by group_name
|
|
112
|
-
const groups = new Map<string, ConnectionNode[]>();
|
|
113
|
-
for (const conn of connections) {
|
|
114
|
-
const key = conn.groupName ?? "__ungrouped__";
|
|
115
|
-
const list = groups.get(key) ?? [];
|
|
116
|
-
list.push(conn);
|
|
117
|
-
groups.set(key, list);
|
|
118
|
-
}
|
|
119
|
-
// If only one group (ungrouped), return connections flat
|
|
120
|
-
if (groups.size <= 1 && groups.has("__ungrouped__")) {
|
|
121
|
-
return connections;
|
|
122
|
-
}
|
|
123
|
-
// Build group nodes
|
|
124
|
-
const result: ConnectionNode[] = [];
|
|
125
|
-
const sortedKeys = Array.from(groups.keys()).sort((a, b) => {
|
|
126
|
-
if (a === "__ungrouped__") return 1;
|
|
127
|
-
if (b === "__ungrouped__") return -1;
|
|
128
|
-
return a.localeCompare(b);
|
|
129
|
-
});
|
|
130
|
-
for (const key of sortedKeys) {
|
|
131
|
-
const label = key === "__ungrouped__" ? "Ungrouped" : key;
|
|
132
|
-
result.push({
|
|
133
|
-
id: `group:${key}`,
|
|
134
|
-
name: label,
|
|
135
|
-
type: "group",
|
|
136
|
-
children: groups.get(key) ?? [],
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
return result;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
private async getConnections(): Promise<ConnectionNode[]> {
|
|
143
|
-
try {
|
|
144
|
-
const res = await fetch(`${this.baseUrl}/api/db/connections`);
|
|
145
|
-
const json = await res.json() as { ok: boolean; data?: ApiConnection[] };
|
|
146
|
-
if (!json.ok || !json.data) return [];
|
|
147
|
-
return json.data.map((c) => ({
|
|
148
|
-
id: `conn:${c.id}`,
|
|
149
|
-
name: c.name,
|
|
150
|
-
type: "connection" as const,
|
|
151
|
-
connectionId: c.id,
|
|
152
|
-
connectionType: c.type,
|
|
153
|
-
connectionColor: c.color,
|
|
154
|
-
connectionReadonly: c.readonly,
|
|
155
|
-
groupName: c.group_name,
|
|
156
|
-
}));
|
|
157
|
-
} catch {
|
|
158
|
-
return [];
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
private async getTables(conn: ConnectionNode): Promise<ConnectionNode[]> {
|
|
163
|
-
try {
|
|
164
|
-
const res = await fetch(`${this.baseUrl}/api/db/connections/${conn.connectionId}/tables`);
|
|
165
|
-
const json = await res.json() as { ok: boolean; data?: ApiTable[] };
|
|
166
|
-
if (!json.ok || !json.data) return [];
|
|
167
|
-
return json.data.map((t) => ({
|
|
168
|
-
id: `table:${conn.connectionId}:${t.schema}.${t.name}`,
|
|
169
|
-
name: t.name,
|
|
170
|
-
type: "table" as const,
|
|
171
|
-
connectionId: conn.connectionId,
|
|
172
|
-
connectionName: conn.name,
|
|
173
|
-
connectionType: conn.connectionType,
|
|
174
|
-
schemaName: t.schema,
|
|
175
|
-
rowCount: t.rowCount,
|
|
176
|
-
}));
|
|
177
|
-
} catch {
|
|
178
|
-
return [];
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
private async getColumns(table: ConnectionNode): Promise<ConnectionNode[]> {
|
|
183
|
-
try {
|
|
184
|
-
const schema = table.schemaName ?? "public";
|
|
185
|
-
const res = await fetch(
|
|
186
|
-
`${this.baseUrl}/api/db/connections/${table.connectionId}/schema?table=${encodeURIComponent(table.name)}&schema=${schema}`,
|
|
187
|
-
);
|
|
188
|
-
const json = await res.json() as { ok: boolean; data?: ApiColumn[] };
|
|
189
|
-
if (!json.ok || !json.data) return [];
|
|
190
|
-
return json.data.map((c) => ({
|
|
191
|
-
id: `col:${table.connectionId}:${table.name}.${c.name}`,
|
|
192
|
-
name: c.name,
|
|
193
|
-
type: "column" as const,
|
|
194
|
-
connectionId: table.connectionId,
|
|
195
|
-
dataType: c.type + (c.pk ? " PK" : ""),
|
|
196
|
-
}));
|
|
197
|
-
} catch {
|
|
198
|
-
return [];
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|