fix: v0.7.1 API 修复与防御统一 — static create / 未 open 防护 / 原型污染 / lint 清零
- MetonaSqlark.create 静态工厂(README 示例在 ESM/Node 下此前 TypeError), 独立 create 函数委托静态实现 - close 未初始化防御(engine undefined 不再崩溃) - AriaEngine hasTable/getTableNames/getTableSchema 统一 ensureOpen - 事务回滚失败不掩盖原始错误 - __proto__ 列名防护:Executor 列映射 Object.create(null) + schema 校验拒绝 - lint 清零(移除 5 处未使用导入) 测试 1147 → 1155(73 套件);行覆盖率 89.8%;版本 0.7.1
This commit is contained in:
Vendored
+35
-8
@@ -34,7 +34,7 @@ class DatabaseError extends Error {
|
||||
// ---------------------------------------------------------------------------
|
||||
// 版本
|
||||
// ---------------------------------------------------------------------------
|
||||
const VERSION = '0.7.0';
|
||||
const VERSION = '0.7.1';
|
||||
|
||||
/**
|
||||
* metona-sqlark Shared WHERE Matcher — 统一的条件匹配逻辑
|
||||
@@ -2456,6 +2456,11 @@ function validateColumns(columns) {
|
||||
}
|
||||
let primaryKeyCount = 0;
|
||||
for (const [colName, colDef] of Object.entries(columns)) {
|
||||
// v0.7.1: '__proto__' 作为列名会触发对象原型 setter(列静默丢失);
|
||||
// 显式拒绝避免原型污染类攻击面
|
||||
if (colName === '__proto__') {
|
||||
throw new DatabaseError('Column name "__proto__" is not allowed', 'SCHEMA_ERROR');
|
||||
}
|
||||
// 类型校验
|
||||
if (!FIELD_TYPES.includes(colDef.type)) {
|
||||
throw new DatabaseError(`Invalid type "${colDef.type}" for column "${colName}". Valid types: ${FIELD_TYPES.join(', ')}`, 'SCHEMA_ERROR');
|
||||
@@ -6699,12 +6704,16 @@ class AriaEngine {
|
||||
}
|
||||
}
|
||||
async hasTable(tableName) {
|
||||
// v0.7.1: 未 open 防护统一(此前与 KVStoreEngine 不一致:返回空而非报错)
|
||||
this.ensureOpen();
|
||||
return this.schemas.has(tableName);
|
||||
}
|
||||
async getTableNames() {
|
||||
this.ensureOpen();
|
||||
return Array.from(this.schemas.keys());
|
||||
}
|
||||
async getTableSchema(tableName) {
|
||||
this.ensureOpen();
|
||||
return this.schemas.get(tableName) ?? null;
|
||||
}
|
||||
// =======================================================================
|
||||
@@ -10961,7 +10970,9 @@ class QueryExecutor {
|
||||
if (exists)
|
||||
return;
|
||||
}
|
||||
const columns = {};
|
||||
// v0.7.1: Object.create(null) —— 防止 '__proto__' 列名触发原型 setter 静默丢列
|
||||
// (createSchema 校验会显式拒绝该列名)
|
||||
const columns = Object.create(null);
|
||||
for (const col of stmt.columns)
|
||||
columns[col.name] = astColumnToColumnDef(col);
|
||||
return this.engine.createTable(createSchema(stmt.name, columns));
|
||||
@@ -11739,8 +11750,12 @@ class TransactionManager {
|
||||
return result;
|
||||
}
|
||||
catch (error) {
|
||||
// 失败 → 回滚
|
||||
await this.engine.rollbackTransaction();
|
||||
// 失败 → 回滚。v0.7.1: 回滚自身失败不掩盖原始事务错误
|
||||
// (此前 rollback 抛错会替换掉真正导致失败的异常,定位困难)
|
||||
try {
|
||||
await this.engine.rollbackTransaction();
|
||||
}
|
||||
catch { /* 回滚失败保留原始错误 */ }
|
||||
if (error instanceof DatabaseError)
|
||||
throw error;
|
||||
throw new DatabaseError(`Transaction failed: ${error.message}`, 'TRANSACTION_ERROR', error);
|
||||
@@ -11838,6 +11853,16 @@ class PluginManager {
|
||||
// MetonaSqlark
|
||||
// ---------------------------------------------------------------------------
|
||||
class MetonaSqlark {
|
||||
/**
|
||||
* v0.7.1: 静态工厂(与 connect/disconnect 同一入口风格)。
|
||||
* 此前 create 仅存在于 api 对象 / window 挂载 —— README/站点示例的
|
||||
* `MetonaSqlark.create({...})` 在 ESM/Node 下是 undefined(TypeError)。
|
||||
*/
|
||||
static async create(config) {
|
||||
const db = new MetonaSqlark(config);
|
||||
await db.init();
|
||||
return db;
|
||||
}
|
||||
/** 获取版本号 */
|
||||
get version() { return this._version; }
|
||||
/** 查询结果行数上限 */
|
||||
@@ -12285,7 +12310,10 @@ class MetonaSqlark {
|
||||
this.channel = null;
|
||||
}
|
||||
this.pluginManager.destroy();
|
||||
await this.engine.close();
|
||||
// v0.7.1: init 失败/未调用时 close 不应崩溃(此前 this.engine undefined → TypeError)
|
||||
if (this.engine) {
|
||||
await this.engine.close();
|
||||
}
|
||||
this.tableCache.clear();
|
||||
this.ready = false;
|
||||
}
|
||||
@@ -12479,9 +12507,8 @@ M.getActiveConnections = () => manager.getActiveConnections();
|
||||
* ```
|
||||
*/
|
||||
async function create(config) {
|
||||
const db = new MetonaSqlark(config);
|
||||
await db.init();
|
||||
return db;
|
||||
// v0.7.1: 委托静态 create(类与独立函数行为一致,README 两种写法均可)
|
||||
return MetonaSqlark.create(config);
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
// 全局 API
|
||||
|
||||
Reference in New Issue
Block a user