flatsql 0.4.2 → 0.4.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flatsql",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "SQL queries over raw FlatBuffer storage - zero conversion, real-time indexing, pure streaming",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -84,7 +84,7 @@
84
84
  "author": "Digital Arsenal <tj@digitalarsenal.io>",
85
85
  "license": "Apache-2.0",
86
86
  "dependencies": {
87
- "flatc-wasm": "^26.1.31",
87
+ "flatc-wasm": "^26.1.32",
88
88
  "sql.js": "^1.10.0"
89
89
  },
90
90
  "devDependencies": {
package/wasm/index.d.ts CHANGED
@@ -312,6 +312,16 @@ export interface InitOptions {
312
312
  */
313
313
  requireIntegrity?: boolean;
314
314
 
315
+ /**
316
+ * SHA-384 digest provider used for browser integrity verification.
317
+ * Browser WebCrypto is intentionally not used; browser callers that require
318
+ * integrity verification must pass a WASM/native-backed provider.
319
+ * The result may be a base64 digest string or raw digest bytes.
320
+ */
321
+ computeSHA384?: (
322
+ data: ArrayBuffer
323
+ ) => Promise<string | Uint8Array | ArrayBuffer> | string | Uint8Array | ArrayBuffer;
324
+
315
325
  /**
316
326
  * Custom Emscripten module factory function
317
327
  * Default: built-in FlatSQLModule
package/wasm/index.js CHANGED
@@ -9,30 +9,60 @@ let api = null;
9
9
  // Security: Track if integrity was verified
10
10
  let integrityVerified = false;
11
11
 
12
+ function toBase64(bytes) {
13
+ if (typeof Buffer !== 'undefined') {
14
+ return Buffer.from(bytes).toString('base64');
15
+ }
16
+ let binary = '';
17
+ for (let offset = 0; offset < bytes.length; offset += 0x8000) {
18
+ binary += String.fromCharCode(...bytes.subarray(offset, offset + 0x8000));
19
+ }
20
+ return btoa(binary);
21
+ }
22
+
23
+ function normalizeHashResult(value) {
24
+ if (typeof value === 'string') {
25
+ return value;
26
+ }
27
+ if (value instanceof Uint8Array) {
28
+ return toBase64(value);
29
+ }
30
+ if (ArrayBuffer.isView(value)) {
31
+ return toBase64(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
32
+ }
33
+ if (value instanceof ArrayBuffer) {
34
+ return toBase64(new Uint8Array(value));
35
+ }
36
+ throw new Error('SHA-384 provider must return a base64 string or binary digest');
37
+ }
38
+
39
+ function hasNodeProcess() {
40
+ return typeof process !== 'undefined' &&
41
+ process.versions !== undefined &&
42
+ typeof process.versions.node === 'string';
43
+ }
44
+
12
45
  /**
13
- * Compute SHA-384 hash of data and return as base64
14
- * Works in both Node.js and browser environments
46
+ * Compute SHA-384 hash of data and return as base64.
47
+ * Browser WebCrypto is intentionally not used; browser callers that require
48
+ * integrity verification must pass computeSHA384 backed by WASM/native crypto.
15
49
  * @param {ArrayBuffer} data
50
+ * @param {(data: ArrayBuffer) => Promise<string|Uint8Array|ArrayBuffer>|string|Uint8Array|ArrayBuffer} [provider]
16
51
  * @returns {Promise<string>}
17
52
  */
18
- async function computeSHA384(data) {
19
- if (typeof crypto !== 'undefined' && crypto.subtle) {
20
- // Browser or Node.js 18+
21
- const hashBuffer = await crypto.subtle.digest('SHA-384', data);
22
- const hashArray = new Uint8Array(hashBuffer);
23
- // Convert to base64
24
- if (typeof btoa !== 'undefined') {
25
- return btoa(String.fromCharCode(...hashArray));
26
- } else {
27
- return Buffer.from(hashArray).toString('base64');
28
- }
29
- } else {
30
- // Node.js fallback using dynamic import
31
- const cryptoModule = await import('crypto');
53
+ async function computeSHA384(data, provider) {
54
+ if (typeof provider === 'function') {
55
+ return normalizeHashResult(await provider(data));
56
+ }
57
+ if (hasNodeProcess()) {
58
+ const cryptoModule = await import('node:crypto');
32
59
  const hash = cryptoModule.createHash('sha384');
33
60
  hash.update(Buffer.from(data));
34
61
  return hash.digest('base64');
35
62
  }
63
+ throw new Error(
64
+ 'WASM integrity verification requires a computeSHA384 option backed by WASM/native crypto; browser WebCrypto is intentionally not used.'
65
+ );
36
66
  }
37
67
 
38
68
  /**
@@ -41,8 +71,8 @@ async function computeSHA384(data) {
41
71
  * @param {string} expectedHash - Expected SHA-384 hash (base64)
42
72
  * @returns {Promise<boolean>}
43
73
  */
44
- async function verifyWASMIntegrity(wasmBinary, expectedHash) {
45
- const computedHash = await computeSHA384(wasmBinary);
74
+ async function verifyWASMIntegrity(wasmBinary, expectedHash, options = {}) {
75
+ const computedHash = await computeSHA384(wasmBinary, options.computeSHA384);
46
76
  return computedHash === expectedHash;
47
77
  }
48
78
 
@@ -177,7 +207,7 @@ export async function initFlatSQL(moduleFactoryOrOptions) {
177
207
  }
178
208
 
179
209
  // Verify integrity
180
- const isValid = await verifyWASMIntegrity(wasmBinary, expectedIntegrity);
210
+ const isValid = await verifyWASMIntegrity(wasmBinary, expectedIntegrity, options);
181
211
  if (!isValid) {
182
212
  throw new Error(
183
213
  'WASM integrity check failed: hash mismatch. ' +