大改,整理项目结构,完成rust ffi调用,写好tcp接口

This commit is contained in:
LIm1tZz7 committed 2026-10-02 15:07:38 +08:00
1 parent df6d348995
commit 9758439b82
118 files changed
+8103 -6321

No files matched your search

+32 -2
View File
@@ -1,12 +1,14 @@
// REST 数据源:与 chusql-web 的 /api/* 一一对应。
// 所有请求带 X-ChuSQL-Database 头(服务端不保存 USE 状态);401 时广播登录事件。
// 请求都带 X-ChuSQL-Database 头;401 时广播登录事件。
export const AUTH_EVENT = 'chusql-auth-required';
// 是否是普通对象。
function isObject(value) {
return value !== null && typeof value === 'object' && !Array.isArray(value);
}
// 发一次请求并处理错误。
async function request(url, init, database) {
const headers = new Headers(init && init.headers ? init.headers : undefined);
if (database) headers.set('X-ChuSQL-Database', database);
@@ -34,6 +36,7 @@ async function request(url, init, database) {
return body;
}
// 组装 JSON 请求参数。
function jsonInit(method, body) {
return {
method,
@@ -44,12 +47,14 @@ function jsonInit(method, body) {
const identifier = /^[A-Za-z_][A-Za-z0-9_]{0,63}$/;
// 校验数据库名格式。
function checkDatabaseName(name) {
if (!identifier.test(String(name))) throw new Error('数据库名只能是字母、数字与下划线,且以字母或下划线开头。');
}
// ---------------------------------------------------------------- 会话
// 读取当前会话。
export async function currentSession() {
const body = await request('/api/session');
if (!isObject(body) || typeof body.user !== 'string') throw new Error('服务器返回的会话信息无法识别。');
@@ -60,16 +65,19 @@ export async function currentSession() {
};
}
// 提交登录。
export async function login(user, password) {
await request('/api/login', jsonInit('POST', { user, password }));
}
// 退出登录。
export async function logout() {
await request('/api/logout', jsonInit('POST', {}));
}
// ---------------------------------------------------------------- 数据库
// 列出数据库。
export async function listDatabases() {
const body = await request('/api/databases');
if (!Array.isArray(body) || !body.every((name) => typeof name === 'string')) {
@@ -78,16 +86,18 @@ export async function listDatabases() {
return body;
}
// 新建数据库。
export async function createDatabase(name, database) {
checkDatabaseName(name);
await request('/api/databases', jsonInit('POST', { name }), database);
}
// 删除数据库。
export async function dropDatabase(name, database) {
await request(`/api/databases/${encodeURIComponent(name)}`, jsonInit('DELETE'), database);
}
// 切换当前库:走一条 USE 语句,服务端在响应里回带新的库名。
// 切换当前库(发 USE 语句)。
export async function useDatabase(name, database) {
checkDatabaseName(name);
return query(`USE ${name}`, database);
@@ -95,12 +105,14 @@ export async function useDatabase(name, database) {
// ---------------------------------------------------------------- 表结构
// 取类型基名(去掉参数)。
function columnKind(type) {
return String(type).split('(')[0].trim().toLowerCase();
}
const knownTypes = ['int', 'bigint', 'smallint', 'str', 'text', 'varchar', 'char', 'float', 'double', 'decimal', 'numeric', 'bool', 'date', 'timestamp', 'blob'];
// 校验并规整列描述。
function asColumns(value) {
if (!Array.isArray(value)) throw new Error('服务器返回的列清单无法识别。');
return value.map((entry) => {
@@ -112,6 +124,7 @@ function asColumns(value) {
});
}
// 校验并规整表描述。
function asTable(value) {
if (!isObject(value) || typeof value.table !== 'string' || typeof value.rowCount !== 'number') {
throw new Error('服务器返回的表描述无法识别。');
@@ -125,38 +138,46 @@ function asTable(value) {
};
}
// 列出表。
export async function listTables(database) {
const body = await request('/api/tables', undefined, database);
if (!Array.isArray(body)) throw new Error('服务器返回的表清单无法识别。');
return body.map(asTable);
}
// 取单表结构。
export async function getTable(database, table) {
return asTable(await request(`/api/tables/${encodeURIComponent(table)}`, undefined, database));
}
// 新建表。
export async function createTable(database, name, columns) {
await request('/api/tables', jsonInit('POST', { name, columns }), database);
}
// 删除表。
export async function dropTable(database, table) {
await request(`/api/tables/${encodeURIComponent(table)}`, jsonInit('DELETE'), database);
}
// 建索引。
export async function createIndex(database, table, column) {
await request(`/api/tables/${encodeURIComponent(table)}/indexes`, jsonInit('POST', { column }), database);
}
// 删索引。
export async function dropIndex(database, table, column) {
await request(`/api/tables/${encodeURIComponent(table)}/indexes/${encodeURIComponent(column)}`, jsonInit('DELETE'), database);
}
// 删列。
export async function dropColumn(database, table, column) {
await request(`/api/tables/${encodeURIComponent(table)}/columns/${encodeURIComponent(column)}`, jsonInit('DELETE'), database);
}
// ---------------------------------------------------------------- 行
// 分页取表数据。
export async function fetchRows({ database, table, limit, offset, sort, dir, filters }) {
const params = new URLSearchParams({ limit: String(limit), offset: String(offset) });
if (sort) {
@@ -179,14 +200,17 @@ export async function fetchRows({ database, table, limit, offset, sort, dir, fil
return { columns, rows, total: body.total };
}
// 插入一行。
export async function insertRow(database, table, values) {
await request(`/api/tables/${encodeURIComponent(table)}/rows`, jsonInit('POST', { values }), database);
}
// 更新一行。
export async function updateRow(database, table, id, values) {
await request(`/api/tables/${encodeURIComponent(table)}/rows/${encodeURIComponent(id)}`, jsonInit('PATCH', { values }), database);
}
// 删除一行。
export async function deleteRow(database, table, id) {
await request(`/api/tables/${encodeURIComponent(table)}/rows/${encodeURIComponent(id)}`, jsonInit('DELETE'), database);
}
@@ -209,6 +233,7 @@ export async function commitChanges(database, changes) {
// ---------------------------------------------------------------- 查询
// 执行 SQL 并规整结果。
export async function query(sql, database) {
const started = performance.now();
try {
@@ -231,27 +256,32 @@ export async function query(sql, database) {
}
}
// 灌演示数据。
export async function seedDemoData(database) {
return request('/api/demo-data', jsonInit('POST', {}), database);
}
// ---------------------------------------------------------------- 设置
// 读取服务器设置。
export async function loadServerSettings() {
const body = await request('/api/settings');
if (!isObject(body) || !Array.isArray(body.items)) throw new Error('服务器返回的设置清单无法识别。');
return body;
}
// 保存服务器设置。
export async function saveServerSettings(values) {
const body = await request('/api/settings', jsonInit('PUT', { values }));
return isObject(body) ? body : { ok: true };
}
// 读取 IDE 设置。
export async function loadUiSettings() {
return request('/api/ui-settings');
}
// 保存 IDE 设置。
export async function saveUiSettings(settings) {
await request('/api/ui-settings', jsonInit('PUT', settings));
}