jsql-neo 6.5.7 → 6.5.8

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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > **One engine to rule them all** — a Rust-powered embedded database that speaks your language:
4
4
  > MySQL, PostgreSQL, MongoDB, Redis, SQL, TypeScript, **and the browser**.
5
5
 
6
- > **v6.5.7** — stable release · [github.com/vexify-org/JSQL-neo](https://github.com/vexify-org/JSQL-neo) · [jsql.vexify.top](https://jsql.vexify.top)
6
+ > **v6.5.8** — stable release · [github.com/vexify-org/JSQL-neo](https://github.com/vexify-org/JSQL-neo) · [jsql.vexify.top](https://jsql.vexify.top)
7
7
 
8
8
  ![Engines](https://img.shields.io/badge/engines-Native%20%7C%20WASM%20%7C%20Pure%20JS-7ee787)
9
9
  ![MySQL](https://img.shields.io/badge/protocol-MySQL%20compatible-1f6feb)
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * JSQL-NEO v6.5.7 — Rust-Powered Embedded Database (WASM + HTTP)
2
+ * JSQL-NEO v6.5.8 — Rust-Powered Embedded Database (WASM + HTTP)
3
3
  *
4
4
  * @example
5
5
  * const jsql = require('jsql-neo');
@@ -151,6 +151,7 @@ class MongoServer {
151
151
  this.port = options.port ?? 27017;
152
152
  this.host = options.host || '127.0.0.1';
153
153
  this.dataDir = options.dataDir || null;
154
+ this.maxMessageSize = options.maxMessageSize || 48 * 1024 * 1024;
154
155
  this._engine = null;
155
156
  this._server = null;
156
157
  this._sockets = new Set();
@@ -201,6 +202,10 @@ class MongoServer {
201
202
  this._sockets.add(socket);
202
203
  socket.on('close', () => this._sockets.delete(socket));
203
204
  let buf = Buffer.isBuffer(existing) ? Buffer.from(existing) : Buffer.alloc(0);
205
+ if (buf.length > this.maxMessageSize) {
206
+ socket.destroy();
207
+ return;
208
+ }
204
209
  socket.on('error', () => {});
205
210
  let processing = false;
206
211
  let again = false;
@@ -211,7 +216,10 @@ class MongoServer {
211
216
  for (;;) {
212
217
  if (buf.length < 4) break;
213
218
  const len = buf.readInt32LE(0);
214
- if (len < 16 || len > 48 * 1024 * 1024) break;
219
+ if (len < 16 || len > this.maxMessageSize) {
220
+ socket.destroy();
221
+ return;
222
+ }
215
223
  if (buf.length < len) break;
216
224
  const msg = buf.slice(0, len);
217
225
  buf = buf.slice(len);
@@ -227,6 +235,10 @@ class MongoServer {
227
235
  }
228
236
  };
229
237
  socket.on('data', (chunk) => {
238
+ if (buf.length + chunk.length > this.maxMessageSize * 2) {
239
+ socket.destroy();
240
+ return;
241
+ }
230
242
  buf = Buffer.concat([buf, chunk]);
231
243
  processLoop();
232
244
  });
@@ -1297,11 +1297,14 @@ class MysqlServer {
1297
1297
  );
1298
1298
  friendly.code = 'EADDRINUSE';
1299
1299
  friendly.cause = err;
1300
- if (cb) cb(friendly);
1301
- else throw friendly;
1302
- } else if (cb) cb(err);
1300
+ if (typeof this.options.onError === 'function') this.options.onError(friendly);
1301
+ else if (cb) cb(friendly);
1302
+ else console.error('[jsql-neo] mysql server error:', friendly.message);
1303
+ } else if (typeof this.options.onError === 'function') this.options.onError(err);
1304
+ else if (cb) cb(err);
1305
+ else console.error('[jsql-neo] mysql server error:', err.message);
1303
1306
  });
1304
- this._server.listen(this.port, this.host, cb || (() => {}));
1307
+ this._server.listen(this.port, this.host, cb ? () => cb() : undefined);
1305
1308
  }).catch(err => {
1306
1309
  if (cb) cb(err);
1307
1310
  else throw err;
@@ -0,0 +1,53 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const { execFileSync } = require('child_process');
5
+
6
+ const MIN_NAPI_VERSION = 6;
7
+
8
+ function detectLibc(platform = process.platform) {
9
+ if (platform !== 'linux') return null;
10
+ try {
11
+ const report = process.report && typeof process.report.getReport === 'function'
12
+ ? process.report.getReport()
13
+ : null;
14
+ if (report && report.header && report.header.glibcVersionRuntime) return 'gnu';
15
+ } catch (_) { /* ignore */ }
16
+ try {
17
+ if (fs.existsSync('/etc/alpine-release')) return 'musl';
18
+ } catch (_) { /* ignore */ }
19
+ try {
20
+ const out = execFileSync('ldd', ['--version'], {
21
+ encoding: 'utf8',
22
+ stdio: ['ignore', 'pipe', 'pipe'],
23
+ });
24
+ if (/musl/i.test(out)) return 'musl';
25
+ if (/glibc|GNU libc/i.test(out)) return 'gnu';
26
+ } catch (_) { /* ignore */ }
27
+ return 'gnu';
28
+ }
29
+
30
+ function nativeTargetSuffix(platform = process.platform, arch = process.arch, libc = detectLibc(platform)) {
31
+ const p = platform === 'win32' ? 'win32' : platform === 'darwin' ? 'darwin' : 'linux';
32
+ const a = arch === 'x64' ? 'x64' : arch === 'arm64' ? 'arm64' : arch;
33
+ if (p === 'linux') return `${p}-${a}-${libc === 'musl' ? 'musl' : 'gnu'}`;
34
+ if (p === 'darwin') return `${p}-${a}`;
35
+ return `${p}-${a}-msvc`;
36
+ }
37
+
38
+ function nativeNapiVersion() {
39
+ const v = Number(process.versions && process.versions.napi);
40
+ return Number.isFinite(v) ? v : 0;
41
+ }
42
+
43
+ function supportsNativeNapi() {
44
+ return nativeNapiVersion() >= MIN_NAPI_VERSION;
45
+ }
46
+
47
+ module.exports = {
48
+ MIN_NAPI_VERSION,
49
+ detectLibc,
50
+ nativeTargetSuffix,
51
+ nativeNapiVersion,
52
+ supportsNativeNapi,
53
+ };
package/lib/pg_server.js CHANGED
@@ -845,11 +845,12 @@ class PgServer {
845
845
  this._sockets.add(socket);
846
846
  new PgConnection(socket, this);
847
847
  });
848
- this._server.listen(this.port, this.host, cb || (() => {}));
849
848
  this._server.on('error', (err) => {
850
849
  if (this.options.onError) this.options.onError(err);
851
- else throw err;
850
+ else if (cb) cb(err);
851
+ else console.error('[jsql-neo] pg server error:', err.message);
852
852
  });
853
+ this._server.listen(this.port, this.host, cb ? () => cb() : undefined);
853
854
  return this;
854
855
  }
855
856
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsql-neo",
3
- "version": "6.5.7",
3
+ "version": "6.5.8",
4
4
  "description": "JSQL-NEO \u2014 Rust-powered embedded database with WASM, REST API, B-Tree indexes, WAL, crash recovery",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
package/postinstall.js CHANGED
@@ -4,6 +4,7 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
  const http = require('http');
6
6
  const https = require('https');
7
+ const { detectLibc, nativeTargetSuffix, nativeNapiVersion, supportsNativeNapi, MIN_NAPI_VERSION } = require('./lib/native_target');
7
8
 
8
9
  const ROOT = __dirname;
9
10
  const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8'));
@@ -69,13 +70,12 @@ const REPO = (pkg.repository && pkg.repository.url)
69
70
  ? pkg.repository.url.replace(/\.git$/, '').replace(/^.*github\.com\//i, '')
70
71
  : 'vexify-org/JSQL-neo';
71
72
 
72
- // 与 .github/workflows/build-native.yml 中发布的资产命名保持一致
73
- function nativeTargetSuffix(platform = process.platform, arch = process.arch) {
74
- const p = platform === 'win32' ? 'win32' : platform === 'darwin' ? 'darwin' : 'linux';
75
- const a = arch === 'x64' ? 'x64' : arch === 'arm64' ? 'arm64' : arch;
76
- if (p === 'linux') return `${p}-${a}-gnu`;
77
- if (p === 'darwin') return `${p}-${a}`;
78
- return `${p}-${a}-msvc`;
73
+ function sameOrigin(a, b) {
74
+ try { return new URL(a).origin === new URL(b).origin; } catch (_) { return false; }
75
+ }
76
+
77
+ function safeRedirect(next) {
78
+ return /^https?:/i.test(String(next || ''));
79
79
  }
80
80
 
81
81
  function download(url, dest, headers, redirects = 0) {
@@ -89,7 +89,11 @@ function download(url, dest, headers, redirects = 0) {
89
89
  if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
90
90
  res.resume();
91
91
  const next = new URL(res.headers.location, url).toString();
92
- download(next, dest, headers, redirects + 1).then(resolve, reject);
92
+ if (!safeRedirect(next)) {
93
+ reject(new Error(`invalid redirect target for ${url}`));
94
+ return;
95
+ }
96
+ download(next, dest, sameOrigin(next, url) ? headers : undefined, redirects + 1).then(resolve, reject);
93
97
  return;
94
98
  }
95
99
  if (res.statusCode !== 200) {
@@ -145,7 +149,11 @@ function fetchText(url, headers, redirects = 0) {
145
149
  if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
146
150
  res.resume();
147
151
  const next = new URL(res.headers.location, url).toString();
148
- fetchText(next, headers, redirects + 1).then(resolve, reject);
152
+ if (!safeRedirect(next)) {
153
+ reject(new Error(`invalid redirect target for ${url}`));
154
+ return;
155
+ }
156
+ fetchText(next, sameOrigin(next, url) ? headers : undefined, redirects + 1).then(resolve, reject);
149
157
  return;
150
158
  }
151
159
  if (res.statusCode !== 200) {
@@ -262,7 +270,15 @@ function tryLoadNative() {
262
270
  }
263
271
 
264
272
  async function downloadAndVerify() {
265
- const asset = `jsql-neo-native.${nativeTargetSuffix()}.node`;
273
+ if (!supportsNativeNapi()) {
274
+ console.warn(
275
+ `[jsql-neo] Node ${process.versions.node} provides N-API ${nativeNapiVersion() || 'unknown'}, ` +
276
+ `but the native module requires N-API >= ${MIN_NAPI_VERSION}; skipping native download.`
277
+ );
278
+ return false;
279
+ }
280
+ const libc = detectLibc();
281
+ const asset = process.env.JSQL_NATIVE_ASSET || `jsql-neo-native.${nativeTargetSuffix(process.platform, process.arch, libc)}.node`;
266
282
  const raw = `https://github.com/${REPO}/releases/download/${TAG}/${asset}`;
267
283
 
268
284
  let expected = null;
@@ -274,11 +290,18 @@ async function downloadAndVerify() {
274
290
 
275
291
  const allowUnverified = process.env.JSQL_ALLOW_UNVERIFIED_NATIVE === '1';
276
292
  if (!expected && !allowUnverified) {
277
- // fail closed:拿不到 SHA256SUMS 就不下载,绝不 require 未经校验的二进制
278
- console.warn(
279
- '[jsql-neo] no SHA256SUMS available for this release; refusing to download an unverified native module.\n' +
280
- '[jsql-neo] set JSQL_NATIVE_SHA256=<64-hex> to pin a checksum, or JSQL_ALLOW_UNVERIFIED_NATIVE=1 to override (unsafe).'
281
- );
293
+ if (libc === 'musl') {
294
+ console.warn(
295
+ `[jsql-neo] musl libc detected but this release has no native asset for ${asset}; ` +
296
+ 'falling back to the WASM/JS engine. Set JSQL_NATIVE_ASSET to a compatible musl build if available.'
297
+ );
298
+ } else {
299
+ // fail closed:拿不到 SHA256SUMS 就不下载,绝不 require 未经校验的二进制
300
+ console.warn(
301
+ '[jsql-neo] no SHA256SUMS available for this release; refusing to download an unverified native module.\n' +
302
+ '[jsql-neo] set JSQL_NATIVE_SHA256=<64-hex> to pin a checksum, or JSQL_ALLOW_UNVERIFIED_NATIVE=1 to override (unsafe).'
303
+ );
304
+ }
282
305
  return false;
283
306
  }
284
307
  if (!expected) {
@@ -323,6 +346,13 @@ async function ensureNativeNode() {
323
346
  console.log('[jsql-neo] native module ready: native/jsql-neo-native.node');
324
347
  return;
325
348
  }
349
+ if (!supportsNativeNapi()) {
350
+ console.warn(
351
+ `[jsql-neo] Node ${process.versions.node} provides N-API ${nativeNapiVersion() || 'unknown'}, ` +
352
+ `but the native module requires N-API >= ${MIN_NAPI_VERSION}; using the WASM/JS engine.`
353
+ );
354
+ return;
355
+ }
326
356
  if (await downloadAndVerify()) return;
327
357
  buildNativeFromSource();
328
358
  }