jsql-neo 5.4.1 → 5.4.2
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/index.d.ts +6 -0
- package/lib/mongo_server.js +1 -1
- package/lib/multiserver.js +1 -1
- package/lib/mysql_server.js +13 -1
- package/lib/native_client.js +12 -0
- package/lib/pg_server.js +1 -1
- package/lib/redis_server.js +1 -1
- package/lib/sql.js +19 -0
- package/lib/wasm_client.js +11 -0
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -106,6 +106,12 @@ declare namespace JSQLNeo {
|
|
|
106
106
|
hasTable(name: string): Promise<boolean>;
|
|
107
107
|
getTables(): Promise<string[]>;
|
|
108
108
|
getTableSchema(name: string): Promise<Schema | null>;
|
|
109
|
+
/**
|
|
110
|
+
* 直接执行原生 SQL(本实例即充当 engine)。
|
|
111
|
+
* @example await db.query("SELECT * FROM users WHERE age > ?", [21])
|
|
112
|
+
* @returns 单条语句返回单个结果对象(含 columns/rows),多条返回数组。
|
|
113
|
+
*/
|
|
114
|
+
query(sql: string, paramsOrOpts?: unknown[] | Record<string, unknown>, opts?: Record<string, unknown>): Promise<any>;
|
|
109
115
|
}
|
|
110
116
|
|
|
111
117
|
export class NativeJSQL extends JSQL {}
|
package/lib/mongo_server.js
CHANGED
|
@@ -148,7 +148,7 @@ function bsonReadValue(buf, pos, type, end) {
|
|
|
148
148
|
class MongoServer {
|
|
149
149
|
constructor(options = {}) {
|
|
150
150
|
this.options = options;
|
|
151
|
-
this.port = options.port
|
|
151
|
+
this.port = options.port ?? 27017;
|
|
152
152
|
this.host = options.host || '127.0.0.1';
|
|
153
153
|
this.dataDir = options.dataDir || null;
|
|
154
154
|
this._engine = null;
|
package/lib/multiserver.js
CHANGED
|
@@ -38,7 +38,7 @@ function sniffProtocol(buf) {
|
|
|
38
38
|
class MultiServer {
|
|
39
39
|
constructor(options = {}) {
|
|
40
40
|
this.options = options;
|
|
41
|
-
this.port = options.port
|
|
41
|
+
this.port = options.port ?? 5432;
|
|
42
42
|
this.host = options.host || '127.0.0.1';
|
|
43
43
|
this.dataDir = options.dataDir || null;
|
|
44
44
|
// 共享 SQL 引擎:三种 SQL 协议读写同一份数据
|
package/lib/mysql_server.js
CHANGED
|
@@ -898,7 +898,7 @@ class MysqlConnection {
|
|
|
898
898
|
class MysqlServer {
|
|
899
899
|
constructor(options = {}) {
|
|
900
900
|
this.options = options;
|
|
901
|
-
this.port = options.port
|
|
901
|
+
this.port = options.port ?? 3306;
|
|
902
902
|
this.host = options.host || '127.0.0.1';
|
|
903
903
|
this.user = options.user || null;
|
|
904
904
|
this.password = options.password || null;
|
|
@@ -1182,6 +1182,18 @@ class MysqlServer {
|
|
|
1182
1182
|
socket.on('close', () => this._sockets.delete(socket));
|
|
1183
1183
|
new MysqlConnection(socket, this);
|
|
1184
1184
|
});
|
|
1185
|
+
this._server.once('error', err => {
|
|
1186
|
+
if (err && err.code === 'EADDRINUSE') {
|
|
1187
|
+
const friendly = new Error(
|
|
1188
|
+
`MysqlServer 端口 ${this.port} 已被占用(EADDRINUSE)。` +
|
|
1189
|
+
`请换一个空闲端口,或传 port: 0 让系统分配临时端口。`
|
|
1190
|
+
);
|
|
1191
|
+
friendly.code = 'EADDRINUSE';
|
|
1192
|
+
friendly.cause = err;
|
|
1193
|
+
if (cb) cb(friendly);
|
|
1194
|
+
else throw friendly;
|
|
1195
|
+
} else if (cb) cb(err);
|
|
1196
|
+
});
|
|
1185
1197
|
this._server.listen(this.port, this.host, cb || (() => {}));
|
|
1186
1198
|
}).catch(err => {
|
|
1187
1199
|
if (cb) cb(err);
|
package/lib/native_client.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const os = require('os');
|
|
3
|
+
const { executeSQL } = require('./sql');
|
|
3
4
|
const native = require(path.join(__dirname, '..', 'native', 'jsql-neo-native.node'));
|
|
4
5
|
const INT64_TAG = 1;
|
|
5
6
|
const FLOAT_TAG = 2;
|
|
@@ -667,6 +668,17 @@ class JSQL {
|
|
|
667
668
|
return this._schemas[name] || null;
|
|
668
669
|
}
|
|
669
670
|
|
|
671
|
+
/**
|
|
672
|
+
* 直接执行原生 SQL 语句。本实例自身即充当 engine,
|
|
673
|
+
* 支持 SELECT / INSERT / UPDATE / DELETE / CREATE TABLE 等常用语句。
|
|
674
|
+
* @example
|
|
675
|
+
* const rows = await db.query("SELECT * FROM users WHERE age > ?", [21]);
|
|
676
|
+
* await db.query("UPDATE users SET age = age + 1 WHERE name = 'A'");
|
|
677
|
+
*/
|
|
678
|
+
async query(sql, paramsOrOpts, opts) {
|
|
679
|
+
return executeSQL(this, sql, paramsOrOpts, opts);
|
|
680
|
+
}
|
|
681
|
+
|
|
670
682
|
async stop() {
|
|
671
683
|
this._flushOpsNow();
|
|
672
684
|
await this._flush();
|
package/lib/pg_server.js
CHANGED
|
@@ -757,7 +757,7 @@ _pgErrorCode(e) {
|
|
|
757
757
|
class PgServer {
|
|
758
758
|
constructor(options = {}) {
|
|
759
759
|
this.options = options;
|
|
760
|
-
this.port = options.port
|
|
760
|
+
this.port = options.port ?? 5432;
|
|
761
761
|
this.host = options.host || '127.0.0.1';
|
|
762
762
|
this.auth = options.auth || null; // { user: { password, databases: [...] } }
|
|
763
763
|
this.noAuth = options.noAuth === true;
|
package/lib/redis_server.js
CHANGED
|
@@ -34,7 +34,7 @@ const TYPE_SIGNATURES = {
|
|
|
34
34
|
|
|
35
35
|
class RedisServer {
|
|
36
36
|
constructor(opts = {}) {
|
|
37
|
-
this.port = opts.port
|
|
37
|
+
this.port = opts.port ?? 6379;
|
|
38
38
|
this.host = opts.host || '127.0.0.1';
|
|
39
39
|
this.password = opts.password || null;
|
|
40
40
|
this.dataDir = opts.dataDir || null;
|
package/lib/sql.js
CHANGED
|
@@ -2870,6 +2870,25 @@ function applyParams(sql, values) {
|
|
|
2870
2870
|
}
|
|
2871
2871
|
|
|
2872
2872
|
async function executeSQL(engine, sql, paramsOrOpts, opts = {}) {
|
|
2873
|
+
// 参数守卫:engine 必须是引擎对象,sql 必须是字符串。误用时报清晰错误,
|
|
2874
|
+
// 而不是在后续像 `reading 'length'` 那样抛出令人费解的 TypeError。
|
|
2875
|
+
if (typeof engine !== 'object' || engine === null) {
|
|
2876
|
+
if (typeof engine === 'string') {
|
|
2877
|
+
throw new Error(
|
|
2878
|
+
`executeSQL(engine, sql, ...) 参数错误:第一个参数不能是 SQL 字符串,必须传 engine 引擎对象。\n` +
|
|
2879
|
+
`正确用法:await executeSQL(db, '${engine.slice(0, 40)}…'); // db 是含 hasTable/find/getTableSchema 的对象`
|
|
2880
|
+
);
|
|
2881
|
+
}
|
|
2882
|
+
throw new Error(
|
|
2883
|
+
`executeSQL(engine, sql, ...) 参数错误:缺少第一个参数 engine。\n` +
|
|
2884
|
+
`正确用法:await executeSQL(db, 'SELECT 1'); // db 需是含 hasTable/find/getTableSchema 的引擎对象`
|
|
2885
|
+
);
|
|
2886
|
+
}
|
|
2887
|
+
if (typeof sql !== 'string' || sql.length === 0) {
|
|
2888
|
+
throw new Error(
|
|
2889
|
+
`executeSQL(engine, sql, ...) 参数错误:第二个参数 sql 必须是有效的 SQL 字符串`
|
|
2890
|
+
);
|
|
2891
|
+
}
|
|
2873
2892
|
if (Array.isArray(paramsOrOpts)) {
|
|
2874
2893
|
sql = applyParams(sql, paramsOrOpts);
|
|
2875
2894
|
} else if (paramsOrOpts && typeof paramsOrOpts === 'object') {
|
package/lib/wasm_client.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
+
const { executeSQL } = require('./sql');
|
|
2
3
|
const wasmBindings = require(path.join(__dirname, '..', 'wasm', 'jsql_neo_wasm.js'));
|
|
3
4
|
|
|
4
5
|
function safeJsonParse(str) {
|
|
@@ -697,6 +698,16 @@ class JSQL {
|
|
|
697
698
|
return this._schemas[name] || null;
|
|
698
699
|
}
|
|
699
700
|
|
|
701
|
+
/**
|
|
702
|
+
* 直接执行原生 SQL 语句。本实例自身即充当 engine,
|
|
703
|
+
* 支持 SELECT / INSERT / UPDATE / DELETE / CREATE TABLE 等常用语句。
|
|
704
|
+
* @example
|
|
705
|
+
* const rows = await db.query("SELECT * FROM users WHERE age > ?", [21]);
|
|
706
|
+
*/
|
|
707
|
+
async query(sql, paramsOrOpts, opts) {
|
|
708
|
+
return executeSQL(this, sql, paramsOrOpts, opts);
|
|
709
|
+
}
|
|
710
|
+
|
|
700
711
|
async stop() {
|
|
701
712
|
await this._flush();
|
|
702
713
|
this._runHooks('onStop', []);
|