feat: add TableList component with styles and functionality for displaying database tables

feat: implement NewConnectionDialog component for creating and editing database connections with form validation

chore: generate TypeScript definitions and JavaScript bindings for app functions

chore: add models for configuration, connection requests, and database entities
This commit is contained in:
loveuer
2026-04-06 21:45:28 +08:00
parent 9874561410
commit 347ecd0f1b
22 changed files with 2475 additions and 315 deletions

45
frontend/wailsjs/go/app/App.d.ts vendored Executable file
View File

@@ -0,0 +1,45 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
import {models} from '../models';
import {config} from '../models';
import {services} from '../models';
import {handler} from '../models';
import {context} from '../models';
export function CreateConnection(arg1:models.CreateConnectionRequest):Promise<string>;
export function CreateSavedQuery(arg1:models.CreateSavedQueryRequest):Promise<models.SavedQuery|string>;
export function DeleteConnection(arg1:string):Promise<string>;
export function DeleteSavedQuery(arg1:number):Promise<string>;
export function DisconnectConnection(arg1:string):Promise<string>;
export function ExecuteQuery(arg1:string,arg2:string):Promise<models.QueryResult|string>;
export function GetConnections():Promise<Array<models.UserConnection>>;
export function GetQueryHistory(arg1:string,arg2:number,arg3:number):Promise<Array<models.QueryHistory>>;
export function GetSavedQueries(arg1:string):Promise<Array<models.SavedQuery>|string>;
export function GetTableData(arg1:string,arg2:string,arg3:number,arg4:number):Promise<models.QueryResult|string>;
export function GetTableStructure(arg1:string,arg2:string):Promise<models.TableStructure|string>;
export function GetTables(arg1:string):Promise<Array<models.Table>|string>;
export function Initialize(arg1:config.Config,arg2:services.ConnectionService,arg3:services.QueryService,arg4:handler.HTTPServer):Promise<void>;
export function OnStartup(arg1:context.Context):Promise<void>;
export function Shutdown():Promise<void>;
export function StartHTTPServer():Promise<string>;
export function TestConnection(arg1:string):Promise<boolean|string>;
export function UpdateConnection(arg1:models.UserConnection):Promise<string>;
export function UpdateSavedQuery(arg1:number,arg2:models.UpdateSavedQueryRequest):Promise<models.SavedQuery|string>;

79
frontend/wailsjs/go/app/App.js Executable file
View File

@@ -0,0 +1,79 @@
// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
export function CreateConnection(arg1) {
return window['go']['app']['App']['CreateConnection'](arg1);
}
export function CreateSavedQuery(arg1) {
return window['go']['app']['App']['CreateSavedQuery'](arg1);
}
export function DeleteConnection(arg1) {
return window['go']['app']['App']['DeleteConnection'](arg1);
}
export function DeleteSavedQuery(arg1) {
return window['go']['app']['App']['DeleteSavedQuery'](arg1);
}
export function DisconnectConnection(arg1) {
return window['go']['app']['App']['DisconnectConnection'](arg1);
}
export function ExecuteQuery(arg1, arg2) {
return window['go']['app']['App']['ExecuteQuery'](arg1, arg2);
}
export function GetConnections() {
return window['go']['app']['App']['GetConnections']();
}
export function GetQueryHistory(arg1, arg2, arg3) {
return window['go']['app']['App']['GetQueryHistory'](arg1, arg2, arg3);
}
export function GetSavedQueries(arg1) {
return window['go']['app']['App']['GetSavedQueries'](arg1);
}
export function GetTableData(arg1, arg2, arg3, arg4) {
return window['go']['app']['App']['GetTableData'](arg1, arg2, arg3, arg4);
}
export function GetTableStructure(arg1, arg2) {
return window['go']['app']['App']['GetTableStructure'](arg1, arg2);
}
export function GetTables(arg1) {
return window['go']['app']['App']['GetTables'](arg1);
}
export function Initialize(arg1, arg2, arg3, arg4) {
return window['go']['app']['App']['Initialize'](arg1, arg2, arg3, arg4);
}
export function OnStartup(arg1) {
return window['go']['app']['App']['OnStartup'](arg1);
}
export function Shutdown() {
return window['go']['app']['App']['Shutdown']();
}
export function StartHTTPServer() {
return window['go']['app']['App']['StartHTTPServer']();
}
export function TestConnection(arg1) {
return window['go']['app']['App']['TestConnection'](arg1);
}
export function UpdateConnection(arg1) {
return window['go']['app']['App']['UpdateConnection'](arg1);
}
export function UpdateSavedQuery(arg1, arg2) {
return window['go']['app']['App']['UpdateSavedQuery'](arg1, arg2);
}

View File

@@ -1,4 +0,0 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
export function Greet(arg1:string):Promise<string>;

View File

@@ -1,7 +0,0 @@
// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
export function Greet(arg1) {
return window['go']['main']['App']['Greet'](arg1);
}

529
frontend/wailsjs/go/models.ts Executable file
View File

@@ -0,0 +1,529 @@
export namespace config {
export class APIConfig {
enabled: boolean;
port: string;
static createFrom(source: any = {}) {
return new APIConfig(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.enabled = source["enabled"];
this.port = source["port"];
}
}
export class LoggerConfig {
level: string;
format: string;
output_path: string;
static createFrom(source: any = {}) {
return new LoggerConfig(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.level = source["level"];
this.format = source["format"];
this.output_path = source["output_path"];
}
}
export class EncryptionConfig {
key_file: string;
static createFrom(source: any = {}) {
return new EncryptionConfig(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.key_file = source["key_file"];
}
}
export class DatabaseConfig {
sqlite_path: string;
max_open_conns: number;
max_idle_conns: number;
max_lifetime: number;
static createFrom(source: any = {}) {
return new DatabaseConfig(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.sqlite_path = source["sqlite_path"];
this.max_open_conns = source["max_open_conns"];
this.max_idle_conns = source["max_idle_conns"];
this.max_lifetime = source["max_lifetime"];
}
}
export class Config {
app_name: string;
version: string;
environment: string;
database: DatabaseConfig;
encryption: EncryptionConfig;
logger: LoggerConfig;
api: APIConfig;
static createFrom(source: any = {}) {
return new Config(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.app_name = source["app_name"];
this.version = source["version"];
this.environment = source["environment"];
this.database = this.convertValues(source["database"], DatabaseConfig);
this.encryption = this.convertValues(source["encryption"], EncryptionConfig);
this.logger = this.convertValues(source["logger"], LoggerConfig);
this.api = this.convertValues(source["api"], APIConfig);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
}
export namespace handler {
export class HTTPServer {
static createFrom(source: any = {}) {
return new HTTPServer(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
}
}
}
export namespace models {
export class CreateConnectionRequest {
name: string;
type: string;
host: string;
port: number;
username: string;
password: string;
database: string;
ssl_mode: string;
timeout: number;
static createFrom(source: any = {}) {
return new CreateConnectionRequest(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.name = source["name"];
this.type = source["type"];
this.host = source["host"];
this.port = source["port"];
this.username = source["username"];
this.password = source["password"];
this.database = source["database"];
this.ssl_mode = source["ssl_mode"];
this.timeout = source["timeout"];
}
}
export class CreateSavedQueryRequest {
name: string;
description: string;
sql: string;
connection_id: string;
tags: string;
static createFrom(source: any = {}) {
return new CreateSavedQueryRequest(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.name = source["name"];
this.description = source["description"];
this.sql = source["sql"];
this.connection_id = source["connection_id"];
this.tags = source["tags"];
}
}
export class ForeignKey {
name: string;
columns: string[];
referenced_table: string;
referenced_columns: string[];
on_delete?: string;
on_update?: string;
static createFrom(source: any = {}) {
return new ForeignKey(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.name = source["name"];
this.columns = source["columns"];
this.referenced_table = source["referenced_table"];
this.referenced_columns = source["referenced_columns"];
this.on_delete = source["on_delete"];
this.on_update = source["on_update"];
}
}
export class QueryHistory {
id: number;
connection_id: string;
sql: string;
duration_ms: number;
// Go type: time
executed_at: any;
rows_affected: number;
error?: string;
success: boolean;
result_preview?: string;
static createFrom(source: any = {}) {
return new QueryHistory(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.connection_id = source["connection_id"];
this.sql = source["sql"];
this.duration_ms = source["duration_ms"];
this.executed_at = this.convertValues(source["executed_at"], null);
this.rows_affected = source["rows_affected"];
this.error = source["error"];
this.success = source["success"];
this.result_preview = source["result_preview"];
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class QueryResult {
columns: string[];
rows: any[][];
row_count: number;
affected_rows: number;
duration_ms: number;
success: boolean;
error?: string;
static createFrom(source: any = {}) {
return new QueryResult(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.columns = source["columns"];
this.rows = source["rows"];
this.row_count = source["row_count"];
this.affected_rows = source["affected_rows"];
this.duration_ms = source["duration_ms"];
this.success = source["success"];
this.error = source["error"];
}
}
export class SavedQuery {
id: number;
name: string;
description: string;
sql: string;
connection_id: string;
tags: string;
// Go type: time
created_at: any;
// Go type: time
updated_at: any;
static createFrom(source: any = {}) {
return new SavedQuery(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.name = source["name"];
this.description = source["description"];
this.sql = source["sql"];
this.connection_id = source["connection_id"];
this.tags = source["tags"];
this.created_at = this.convertValues(source["created_at"], null);
this.updated_at = this.convertValues(source["updated_at"], null);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class Table {
name: string;
schema?: string;
type: string;
row_count?: number;
description?: string;
static createFrom(source: any = {}) {
return new Table(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.name = source["name"];
this.schema = source["schema"];
this.type = source["type"];
this.row_count = source["row_count"];
this.description = source["description"];
}
}
export class TableColumn {
name: string;
data_type: string;
nullable: boolean;
default?: string;
is_primary: boolean;
is_unique: boolean;
auto_increment: boolean;
length?: number;
scale?: number;
comment?: string;
static createFrom(source: any = {}) {
return new TableColumn(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.name = source["name"];
this.data_type = source["data_type"];
this.nullable = source["nullable"];
this.default = source["default"];
this.is_primary = source["is_primary"];
this.is_unique = source["is_unique"];
this.auto_increment = source["auto_increment"];
this.length = source["length"];
this.scale = source["scale"];
this.comment = source["comment"];
}
}
export class TableIndex {
name: string;
columns: string[];
is_unique: boolean;
is_primary: boolean;
type?: string;
static createFrom(source: any = {}) {
return new TableIndex(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.name = source["name"];
this.columns = source["columns"];
this.is_unique = source["is_unique"];
this.is_primary = source["is_primary"];
this.type = source["type"];
}
}
export class TableStructure {
table_name: string;
schema?: string;
columns: TableColumn[];
indexes?: TableIndex[];
foreign_keys?: ForeignKey[];
static createFrom(source: any = {}) {
return new TableStructure(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.table_name = source["table_name"];
this.schema = source["schema"];
this.columns = this.convertValues(source["columns"], TableColumn);
this.indexes = this.convertValues(source["indexes"], TableIndex);
this.foreign_keys = this.convertValues(source["foreign_keys"], ForeignKey);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class UpdateSavedQueryRequest {
name: string;
description: string;
sql: string;
connection_id: string;
tags: string;
static createFrom(source: any = {}) {
return new UpdateSavedQueryRequest(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.name = source["name"];
this.description = source["description"];
this.sql = source["sql"];
this.connection_id = source["connection_id"];
this.tags = source["tags"];
}
}
export class UserConnection {
id: string;
name: string;
type: string;
host?: string;
port?: number;
username?: string;
password: string;
database: string;
ssl_mode?: string;
timeout: number;
// Go type: time
created_at: any;
// Go type: time
updated_at: any;
static createFrom(source: any = {}) {
return new UserConnection(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.name = source["name"];
this.type = source["type"];
this.host = source["host"];
this.port = source["port"];
this.username = source["username"];
this.password = source["password"];
this.database = source["database"];
this.ssl_mode = source["ssl_mode"];
this.timeout = source["timeout"];
this.created_at = this.convertValues(source["created_at"], null);
this.updated_at = this.convertValues(source["updated_at"], null);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
}
export namespace services {
export class ConnectionService {
static createFrom(source: any = {}) {
return new ConnectionService(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
}
}
export class QueryService {
static createFrom(source: any = {}) {
return new QueryService(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
}
}
}