@memberjunction/global 6.2.0-edge.2 → 6.2.0-edge.4

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.
Files changed (47) hide show
  1. package/README.md +26 -0
  2. package/dist/__tests__/BinaryEncoding.test.d.ts +2 -0
  3. package/dist/__tests__/BinaryEncoding.test.d.ts.map +1 -0
  4. package/dist/__tests__/BinaryEncoding.test.js +244 -0
  5. package/dist/__tests__/BinaryEncoding.test.js.map +1 -0
  6. package/dist/__tests__/BinaryEncodingRows.test.d.ts +2 -0
  7. package/dist/__tests__/BinaryEncodingRows.test.d.ts.map +1 -0
  8. package/dist/__tests__/BinaryEncodingRows.test.js +146 -0
  9. package/dist/__tests__/BinaryEncodingRows.test.js.map +1 -0
  10. package/dist/__tests__/BinaryEncodingValidation.test.d.ts +2 -0
  11. package/dist/__tests__/BinaryEncodingValidation.test.d.ts.map +1 -0
  12. package/dist/__tests__/BinaryEncodingValidation.test.js +98 -0
  13. package/dist/__tests__/BinaryEncodingValidation.test.js.map +1 -0
  14. package/dist/__tests__/UUIDCollections.test.d.ts +2 -0
  15. package/dist/__tests__/UUIDCollections.test.d.ts.map +1 -0
  16. package/dist/__tests__/UUIDCollections.test.js +173 -0
  17. package/dist/__tests__/UUIDCollections.test.js.map +1 -0
  18. package/dist/__tests__/UUIDCompliance.test.d.ts +2 -1
  19. package/dist/__tests__/UUIDCompliance.test.d.ts.map +1 -1
  20. package/dist/__tests__/UUIDCompliance.test.js +290 -8
  21. package/dist/__tests__/UUIDCompliance.test.js.map +1 -1
  22. package/dist/__tests__/UUIDUtils.test.js +55 -0
  23. package/dist/__tests__/UUIDUtils.test.js.map +1 -1
  24. package/dist/__tests__/util.trimTrailingSlashes.test.d.ts +2 -0
  25. package/dist/__tests__/util.trimTrailingSlashes.test.d.ts.map +1 -0
  26. package/dist/__tests__/util.trimTrailingSlashes.test.js +23 -0
  27. package/dist/__tests__/util.trimTrailingSlashes.test.js.map +1 -0
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +2 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/util/BinaryEncoding.d.ts +197 -0
  33. package/dist/util/BinaryEncoding.d.ts.map +1 -0
  34. package/dist/util/BinaryEncoding.js +388 -0
  35. package/dist/util/BinaryEncoding.js.map +1 -0
  36. package/dist/util/UUIDCollections.d.ts +111 -0
  37. package/dist/util/UUIDCollections.d.ts.map +1 -0
  38. package/dist/util/UUIDCollections.js +163 -0
  39. package/dist/util/UUIDCollections.js.map +1 -0
  40. package/dist/util/UUIDUtils.d.ts.map +1 -1
  41. package/dist/util/UUIDUtils.js +58 -3
  42. package/dist/util/UUIDUtils.js.map +1 -1
  43. package/dist/util.d.ts +14 -0
  44. package/dist/util.d.ts.map +1 -1
  45. package/dist/util.js +20 -0
  46. package/dist/util.js.map +1 -1
  47. package/package.json +1 -1
package/README.md CHANGED
@@ -515,6 +515,32 @@ IsValueEncrypted('plain text'); // false
515
515
  IsEncryptedSentinel('[!ENCRYPTED$]'); // true
516
516
  ```
517
517
 
518
+ ### Binary Encoding
519
+
520
+ Above the database, MemberJunction represents a binary column (`varbinary` / `binary` / `image`, PostgreSQL `bytea`) as a **base64 string** — in `BaseEntity` fields, caches, `RunView` rows and GraphQL alike. These helpers convert and validate it. The codec is picked once per process from the fastest the host offers (native `Uint8Array.fromBase64`/`toBase64`, Node `Buffer`, then `atob`/`btoa`); every codec accepts and produces the same strings. See the [Binary Fields Guide](../../guides/BINARY_FIELDS_GUIDE.md).
521
+
522
+ | Function | Description |
523
+ |---|---|
524
+ | `BytesToBase64(bytes)` | Bytes to standard, padded base64 |
525
+ | `Base64ToBytes(b64)` | Base64 to bytes; throws on invalid input |
526
+ | `TryBase64ToBytes(b64)` | Same, but returns `null` for null/undefined or invalid input |
527
+ | `IsValidBase64(value)` | Canonical base64 only: standard alphabet, optional padding, no whitespace, data-URI prefix or URL-safe alphabet |
528
+ | `HasValidBase64Shape(value)` | Length/padding shape check only |
529
+ | `Base64DecodedByteLength(b64)` | Decoded byte count without decoding (for size checks) |
530
+ | `IsByteArray(value)` | True for a `Uint8Array` (including a Node `Buffer`) |
531
+ | `ReplaceByteArraysWithBase64(row)` | Replaces top-level byte arrays in a row with base64; copy-on-write, never mutates the input |
532
+ | `Float32VectorToBytes(values)` / `BytesToFloat32Vector(bytes)` | A vector as little-endian float32 bytes (4 per value, no header); decode returns `null` for empty or misaligned input |
533
+ | `Float32VectorToBase64(values)` / `Base64ToFloat32Vector(b64)` | The same, as the base64 value stored in a binary vector field such as `VectorBinary` |
534
+ | `GetBase64Codec()` / `Base64Codecs` | The codec in use / every available codec (diagnostics and tests) |
535
+
536
+ ```typescript
537
+ import { Float32VectorToBase64, Base64ToFloat32Vector, TryBase64ToBytes } from '@memberjunction/global';
538
+
539
+ doc.VectorBinary = Float32VectorToBase64(embedding); // write
540
+ const vector = Base64ToFloat32Vector(doc.VectorBinary); // Float32Array | null
541
+ const bytes = TryBase64ToBytes(file.Content); // Uint8Array | null
542
+ ```
543
+
518
544
  ### String and JSON Utilities
519
545
 
520
546
  A collection of utility functions for common string and JSON operations.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=BinaryEncoding.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinaryEncoding.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/BinaryEncoding.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,244 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import { BINARY_CHANGE_VALUE_PREFIX, FormatBinaryChangeValue, IsBinaryChangeValue, Base64Codecs, Base64ToBytes, Base64ToFloat32Vector, BytesToBase64, BytesToFloat32Vector, Float32VectorCodecs, Float32VectorToBase64, Float32VectorToBytes, GetBase64Codec, IsByteArray, IsValidBase64, TryBase64ToBytes, } from '../util/BinaryEncoding.js';
3
+ /** Deterministic pseudo-random bytes, so failures reproduce. */
4
+ function bytesOf(length, seed = 7) {
5
+ const out = new Uint8Array(length);
6
+ let s = seed;
7
+ for (let i = 0; i < length; i++) {
8
+ s = (s * 16807) % 2147483647;
9
+ out[i] = s & 0xff;
10
+ }
11
+ return out;
12
+ }
13
+ const [nativeCodec, nodeCodec, portableCodec] = Base64Codecs;
14
+ /**
15
+ * Installs a stand-in for the TC39 `Uint8Array.fromBase64` / `toBase64` API (absent in Node 22)
16
+ * that records how it was called, so the native implementation can be exercised.
17
+ */
18
+ function installNativeBase64() {
19
+ const calls = [];
20
+ const statics = Uint8Array;
21
+ const proto = Uint8Array.prototype;
22
+ statics.fromBase64 = (input, options) => {
23
+ calls.push(`fromBase64:${options?.lastChunkHandling ?? 'none'}`);
24
+ return new Uint8Array(Buffer.from(input, 'base64'));
25
+ };
26
+ proto.toBase64 = function () {
27
+ calls.push('toBase64');
28
+ return Buffer.from(this.buffer, this.byteOffset, this.byteLength).toString('base64');
29
+ };
30
+ return {
31
+ calls,
32
+ restore: () => {
33
+ delete statics.fromBase64;
34
+ delete proto.toBase64;
35
+ },
36
+ };
37
+ }
38
+ describe('IsValidBase64', () => {
39
+ it.each(['', 'AA==', 'AAA=', 'AAAA', 'AAAAAA', 'AQID', '+/+/', 'aGVsbG8='])('accepts %j', value => {
40
+ expect(IsValidBase64(value)).toBe(true);
41
+ });
42
+ it.each([
43
+ ['a single dangling character', 'A'],
44
+ ['five characters (one dangling)', 'AAAAA'],
45
+ ['whitespace', 'AA AA'],
46
+ ['a line break', 'AAAA\nAAAA'],
47
+ ['the URL-safe alphabet', 'AA-_'],
48
+ ['a data URI', 'data:image/png;base64,AAAA'],
49
+ ['padding before the end', 'AA=A'],
50
+ ['three padding characters', 'A==='],
51
+ ['padding on a partial quantum', 'AAAAA='],
52
+ ['non-ASCII', 'AAÀA'],
53
+ ])('rejects %s', (_label, value) => {
54
+ expect(IsValidBase64(value)).toBe(false);
55
+ });
56
+ });
57
+ describe('base64 implementations', () => {
58
+ afterEach(() => {
59
+ // Defensive: a failed test must not leave the stand-in installed for the next one.
60
+ delete Uint8Array.fromBase64;
61
+ delete Uint8Array.prototype.toBase64;
62
+ });
63
+ it('lists the native API first, then Node Buffer, then atob/btoa', () => {
64
+ expect(Base64Codecs.map(c => c.Name)).toEqual([
65
+ 'Uint8Array.fromBase64 / toBase64',
66
+ 'Node Buffer',
67
+ 'atob / btoa',
68
+ ]);
69
+ });
70
+ it('detects the native API by duck typing', () => {
71
+ expect(nativeCodec.IsAvailable()).toBe(false); // Node 22 has no Uint8Array.fromBase64
72
+ const native = installNativeBase64();
73
+ expect(nativeCodec.IsAvailable()).toBe(true);
74
+ native.restore();
75
+ expect(nativeCodec.IsAvailable()).toBe(false);
76
+ });
77
+ it('selects Node Buffer on Node, and keeps that choice for the life of the process', () => {
78
+ expect(GetBase64Codec()).toBe(nodeCodec);
79
+ const native = installNativeBase64();
80
+ expect(GetBase64Codec()).toBe(nodeCodec); // selection is cached, not re-evaluated
81
+ native.restore();
82
+ });
83
+ it('calls the native API with loose final-chunk handling, so unpadded input decodes', () => {
84
+ const native = installNativeBase64();
85
+ expect(Array.from(nativeCodec.Decode('AQI'))).toEqual([1, 2]);
86
+ expect(nativeCodec.Encode(new Uint8Array([1, 2]))).toBe('AQI=');
87
+ expect(native.calls).toEqual(['fromBase64:loose', 'toBase64']);
88
+ native.restore();
89
+ });
90
+ it.each([0, 1, 2, 3, 4, 5, 255, 256, 1536 * 4, 0x8000 - 1, 0x8000, 0x8000 + 1, 200_000])('produces identical strings and bytes in every implementation for %i bytes', length => {
91
+ const native = installNativeBase64();
92
+ const bytes = bytesOf(length, length + 1);
93
+ const expected = Buffer.from(bytes).toString('base64');
94
+ for (const codec of Base64Codecs) {
95
+ expect(codec.Encode(bytes), codec.Name).toBe(expected);
96
+ expect(Array.from(codec.Decode(expected)), codec.Name).toEqual(Array.from(bytes));
97
+ }
98
+ native.restore();
99
+ });
100
+ it('encodes only the viewed range of a subarray in every implementation', () => {
101
+ const native = installNativeBase64();
102
+ const backing = bytesOf(64);
103
+ const view = backing.subarray(5, 21);
104
+ const expected = Buffer.from(view).toString('base64');
105
+ for (const codec of Base64Codecs)
106
+ expect(codec.Encode(view), codec.Name).toBe(expected);
107
+ native.restore();
108
+ });
109
+ it('returns bytes that own their buffer from the Node implementation, never a pooled view', () => {
110
+ const decoded = nodeCodec.Decode('AQID');
111
+ expect(decoded.byteOffset).toBe(0);
112
+ expect(decoded.buffer.byteLength).toBe(3);
113
+ expect(Buffer.isBuffer(decoded)).toBe(false);
114
+ });
115
+ it('reports the portable implementation as available wherever atob and btoa exist', () => {
116
+ expect(portableCodec.IsAvailable()).toBe(true);
117
+ });
118
+ });
119
+ describe('BytesToBase64 / Base64ToBytes', () => {
120
+ it('round-trips every byte value', () => {
121
+ const all = new Uint8Array(256).map((_, i) => i);
122
+ expect(Array.from(Base64ToBytes(BytesToBase64(all)))).toEqual(Array.from(all));
123
+ });
124
+ it('maps zero bytes to the empty string and back', () => {
125
+ expect(BytesToBase64(new Uint8Array(0))).toBe('');
126
+ expect(Base64ToBytes('').length).toBe(0);
127
+ });
128
+ it('accepts a Node Buffer as input', () => {
129
+ expect(BytesToBase64(Buffer.from([1, 2, 3]))).toBe('AQID');
130
+ });
131
+ it('decodes unpadded input the same as padded input', () => {
132
+ expect(Array.from(Base64ToBytes('AQI'))).toEqual(Array.from(Base64ToBytes('AQI=')));
133
+ });
134
+ it('throws on invalid input instead of guessing, unlike a lenient Buffer.from', () => {
135
+ expect(Buffer.from('AA AA', 'base64').length).toBeGreaterThan(0); // Node alone would accept this
136
+ expect(() => Base64ToBytes('AA AA')).toThrow('Invalid base64 value (length 5)');
137
+ expect(() => Base64ToBytes('A')).toThrow('Invalid base64');
138
+ });
139
+ it('returns null from TryBase64ToBytes for missing or invalid input', () => {
140
+ expect(TryBase64ToBytes(null)).toBeNull();
141
+ expect(TryBase64ToBytes(undefined)).toBeNull();
142
+ expect(TryBase64ToBytes('not base64!')).toBeNull();
143
+ expect(TryBase64ToBytes('')?.length).toBe(0);
144
+ expect(Array.from(TryBase64ToBytes('AQID') ?? [])).toEqual([1, 2, 3]);
145
+ });
146
+ });
147
+ describe('IsByteArray', () => {
148
+ it('recognises Uint8Array and Node Buffer, and nothing else', () => {
149
+ expect(IsByteArray(new Uint8Array(1))).toBe(true);
150
+ expect(IsByteArray(Buffer.from('x'))).toBe(true);
151
+ expect(IsByteArray('AQID')).toBe(false);
152
+ expect(IsByteArray(new Uint16Array(1))).toBe(false);
153
+ expect(IsByteArray(new ArrayBuffer(4))).toBe(false);
154
+ expect(IsByteArray(null)).toBe(false);
155
+ expect(IsByteArray({ type: 'Buffer', data: [1] })).toBe(false);
156
+ });
157
+ });
158
+ describe('float32 vectors', () => {
159
+ const sample = [0, 1, -1, 0.5, -2.25, 3.4028234663852886e38, 1e-45, Math.PI];
160
+ it('writes little-endian IEEE-754 single precision, 4 bytes per value, no header', () => {
161
+ const bytes = Float32VectorToBytes([1, -2]);
162
+ // 1.0f = 0x3F800000, -2.0f = 0xC0000000, least significant byte first
163
+ expect(Array.from(bytes)).toEqual([0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0xc0]);
164
+ });
165
+ it('produces identical bytes and values in both implementations', () => {
166
+ const [typedArray, dataView] = Float32VectorCodecs;
167
+ const expected = typedArray.Encode(sample);
168
+ expect(Array.from(dataView.Encode(sample))).toEqual(Array.from(expected));
169
+ expect(Array.from(dataView.Decode(expected))).toEqual(Array.from(typedArray.Decode(expected)));
170
+ });
171
+ it('round-trips through bytes and through base64, rounding to single precision', () => {
172
+ const expected = Array.from(Float32Array.from(sample));
173
+ expect(Array.from(BytesToFloat32Vector(Float32VectorToBytes(sample)) ?? [])).toEqual(expected);
174
+ expect(Array.from(Base64ToFloat32Vector(Float32VectorToBase64(sample)) ?? [])).toEqual(expected);
175
+ expect(Base64ToFloat32Vector(Float32VectorToBase64([0.1]))?.[0]).toBe(Math.fround(0.1));
176
+ });
177
+ it('accepts a Float32Array as input', () => {
178
+ const source = Float32Array.from([1.5, 2.5]);
179
+ expect(Array.from(BytesToFloat32Vector(Float32VectorToBytes(source)) ?? [])).toEqual([1.5, 2.5]);
180
+ });
181
+ it('preserves NaN and infinities, leaving validation to the caller', () => {
182
+ const decoded = Base64ToFloat32Vector(Float32VectorToBase64([NaN, Infinity, -Infinity]));
183
+ expect(Number.isNaN(decoded?.[0])).toBe(true);
184
+ expect(decoded?.[1]).toBe(Infinity);
185
+ expect(decoded?.[2]).toBe(-Infinity);
186
+ });
187
+ it('decodes from a misaligned view, such as a pooled Node Buffer, in both implementations', () => {
188
+ const encoded = Float32VectorToBytes([1, 2, 3]);
189
+ const backing = new Uint8Array(encoded.length + 1);
190
+ backing.set(encoded, 1);
191
+ const misaligned = backing.subarray(1); // byteOffset 1: a Float32Array view over it would throw
192
+ for (const codec of Float32VectorCodecs) {
193
+ expect(Array.from(codec.Decode(misaligned)), codec.Name).toEqual([1, 2, 3]);
194
+ }
195
+ expect(Array.from(BytesToFloat32Vector(misaligned) ?? [])).toEqual([1, 2, 3]);
196
+ });
197
+ it('returns a vector that owns its memory, so later writes to the source do not leak in', () => {
198
+ const bytes = Float32VectorToBytes([1, 2]);
199
+ const decoded = BytesToFloat32Vector(bytes);
200
+ bytes.fill(0);
201
+ expect(Array.from(decoded ?? [])).toEqual([1, 2]);
202
+ });
203
+ it.each([
204
+ ['null', null],
205
+ ['undefined', undefined],
206
+ ['zero bytes', new Uint8Array(0)],
207
+ ['6 bytes (not a whole number of values)', new Uint8Array(6)],
208
+ ['1 byte', new Uint8Array(1)],
209
+ ])('returns null for %s', (_label, bytes) => {
210
+ expect(BytesToFloat32Vector(bytes)).toBeNull();
211
+ });
212
+ it('returns null for a missing, invalid or truncated base64 vector', () => {
213
+ expect(Base64ToFloat32Vector(null)).toBeNull();
214
+ expect(Base64ToFloat32Vector('')).toBeNull();
215
+ expect(Base64ToFloat32Vector('%%%%')).toBeNull();
216
+ expect(Base64ToFloat32Vector(Buffer.from([1, 2, 3, 4, 5, 6]).toString('base64'))).toBeNull();
217
+ });
218
+ it('encodes an empty vector as zero bytes', () => {
219
+ expect(Float32VectorToBytes([]).length).toBe(0);
220
+ expect(Float32VectorToBase64([])).toBe('');
221
+ });
222
+ });
223
+ describe('FormatBinaryChangeValue / IsBinaryChangeValue (change-log text for a binary value)', () => {
224
+ it('reports the decoded size with a thousands separator, never the content', () => {
225
+ expect(FormatBinaryChangeValue('AQID')).toBe('[binary: 3 bytes]');
226
+ expect(FormatBinaryChangeValue('AQIDBA==')).toBe('[binary: 4 bytes]');
227
+ expect(FormatBinaryChangeValue('A'.repeat(8192))).toBe('[binary: 6,144 bytes]');
228
+ expect(FormatBinaryChangeValue('')).toBe('[binary: 0 bytes]');
229
+ });
230
+ it('reports invalid base64 as such instead of throwing', () => {
231
+ expect(FormatBinaryChangeValue('not base64!')).toBe('[binary: invalid base64]');
232
+ expect(FormatBinaryChangeValue('data:image/png;base64,AAAA')).toBe('[binary: invalid base64]');
233
+ });
234
+ it('recognises its own output and nothing else', () => {
235
+ expect(IsBinaryChangeValue(FormatBinaryChangeValue('AQID'))).toBe(true);
236
+ expect(IsBinaryChangeValue('[binary: invalid base64]')).toBe(true);
237
+ expect(IsBinaryChangeValue('AQID')).toBe(false);
238
+ expect(IsBinaryChangeValue('[binary')).toBe(false);
239
+ expect(IsBinaryChangeValue(null)).toBe(false);
240
+ expect(IsBinaryChangeValue(42)).toBe(false);
241
+ expect(FormatBinaryChangeValue('AQID').startsWith(BINARY_CHANGE_VALUE_PREFIX)).toBe(true);
242
+ });
243
+ });
244
+ //# sourceMappingURL=BinaryEncoding.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinaryEncoding.test.js","sourceRoot":"","sources":["../../src/__tests__/BinaryEncoding.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=BinaryEncodingRows.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinaryEncodingRows.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/BinaryEncodingRows.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,146 @@
1
+ import { describe, it, expect, afterEach, vi } from 'vitest';
2
+ import { Base64DecodedByteLength, Base64ToBytes, BytesToBase64, Float32VectorCodecs, FLOAT32_VECTOR_BYTES_PER_VALUE, ReplaceByteArraysWithBase64, } from '../util/BinaryEncoding.js';
3
+ describe('Base64DecodedByteLength', () => {
4
+ it.each([
5
+ ['', 0],
6
+ ['AA==', 1],
7
+ ['AAA=', 2],
8
+ ['AAAA', 3],
9
+ ['AQID', 3],
10
+ ['AAAAAA==', 4],
11
+ ['aGVsbG8=', 5],
12
+ ])('reports %j as %i bytes', (value, expected) => {
13
+ expect(Base64DecodedByteLength(value)).toBe(expected);
14
+ });
15
+ it.each([
16
+ ['AA', 1],
17
+ ['AAA', 2],
18
+ ['AQI', 2],
19
+ ['AAAAAA', 4],
20
+ ])('handles unpadded %j as %i bytes', (value, expected) => {
21
+ expect(Base64DecodedByteLength(value)).toBe(expected);
22
+ });
23
+ it('agrees with the actual decoded length for every size 0..64, padded and unpadded', () => {
24
+ for (let length = 0; length <= 64; length++) {
25
+ const bytes = new Uint8Array(length).map((_, i) => (i * 31) & 0xff);
26
+ const padded = BytesToBase64(bytes);
27
+ const unpadded = padded.replace(/=+$/, '');
28
+ expect(Base64DecodedByteLength(padded), `padded ${length}`).toBe(length);
29
+ expect(Base64DecodedByteLength(unpadded), `unpadded ${length}`).toBe(length);
30
+ expect(Base64ToBytes(unpadded).length).toBe(length);
31
+ }
32
+ });
33
+ it('agrees with the decoded length of a large value without decoding it', () => {
34
+ const bytes = new Uint8Array(100_001);
35
+ expect(Base64DecodedByteLength(BytesToBase64(bytes))).toBe(100_001);
36
+ });
37
+ });
38
+ describe('ReplaceByteArraysWithBase64', () => {
39
+ it('returns the same object when the row has no byte arrays', () => {
40
+ const row = { ID: 'a', Name: 'x', Count: 3, Data: 'AQID', Missing: null, Nested: { inner: new Uint8Array([1]) } };
41
+ expect(ReplaceByteArraysWithBase64(row)).toBe(row);
42
+ });
43
+ it('returns the same object for an empty row', () => {
44
+ const row = {};
45
+ expect(ReplaceByteArraysWithBase64(row)).toBe(row);
46
+ });
47
+ it('replaces a Uint8Array value with base64 in a shallow copy', () => {
48
+ const bytes = new Uint8Array([1, 2, 3]);
49
+ const row = { ID: 'a', Data: bytes };
50
+ const result = ReplaceByteArraysWithBase64(row);
51
+ expect(result).not.toBe(row);
52
+ expect(result).toEqual({ ID: 'a', Data: 'AQID' });
53
+ expect(row.Data).toBe(bytes); // input untouched
54
+ });
55
+ it('replaces a Node Buffer value', () => {
56
+ const row = { Data: Buffer.from([1, 2, 3]) };
57
+ expect(ReplaceByteArraysWithBase64(row)).toEqual({ Data: 'AQID' });
58
+ });
59
+ it('replaces every byte array, copying only once, and keeps other values by reference', () => {
60
+ const nested = { a: 1 };
61
+ const row = {
62
+ First: new Uint8Array([255]),
63
+ Text: 'hello',
64
+ Nested: nested,
65
+ Second: Buffer.from([0, 0, 0]),
66
+ Empty: new Uint8Array(0),
67
+ };
68
+ const result = ReplaceByteArraysWithBase64(row);
69
+ expect(result).toEqual({ First: '/w==', Text: 'hello', Nested: nested, Second: 'AAAA', Empty: '' });
70
+ expect(result.Nested).toBe(nested);
71
+ expect(IsUint8(row.First)).toBe(true);
72
+ expect(IsUint8(row.Second)).toBe(true);
73
+ });
74
+ it('does not convert other typed arrays or ArrayBuffers', () => {
75
+ const u16 = new Uint16Array([1]);
76
+ const ab = new ArrayBuffer(2);
77
+ const row = { A: u16, B: ab };
78
+ expect(ReplaceByteArraysWithBase64(row)).toBe(row);
79
+ });
80
+ it('never mutates a frozen cache entry', () => {
81
+ const row = Object.freeze({ ID: 'x', Data: new Uint8Array([1, 2]) });
82
+ const result = ReplaceByteArraysWithBase64(row);
83
+ expect(result).toEqual({ ID: 'x', Data: 'AQI=' });
84
+ expect(Object.isFrozen(row)).toBe(true);
85
+ expect(row.Data).toBeInstanceOf(Uint8Array);
86
+ expect(Object.isFrozen(result)).toBe(false);
87
+ });
88
+ it('encodes only the viewed range of a subarray value', () => {
89
+ const backing = new Uint8Array([9, 1, 2, 3, 9]);
90
+ const row = { Data: backing.subarray(1, 4) };
91
+ expect(ReplaceByteArraysWithBase64(row).Data).toBe('AQID');
92
+ });
93
+ it('produces a value that survives JSON serialization as a string', () => {
94
+ const row = { Data: Buffer.from('hi') };
95
+ expect(JSON.parse(JSON.stringify(ReplaceByteArraysWithBase64(row)))).toEqual({ Data: 'aGk=' });
96
+ });
97
+ });
98
+ function IsUint8(value) {
99
+ return value instanceof Uint8Array;
100
+ }
101
+ describe('float32 vector codecs', () => {
102
+ it('uses 4 bytes per value', () => {
103
+ expect(FLOAT32_VECTOR_BYTES_PER_VALUE).toBe(4);
104
+ });
105
+ it('DataView implementation writes little-endian bytes explicitly', () => {
106
+ const dataView = Float32VectorCodecs[1];
107
+ expect(dataView.Name).toBe('DataView (any host)');
108
+ expect(Array.from(dataView.Encode([1, -2]))).toEqual([0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0xc0]);
109
+ expect(Array.from(dataView.Encode([]))).toEqual([]);
110
+ });
111
+ it('both implementations decode an empty-but-aligned buffer to an empty vector', () => {
112
+ for (const codec of Float32VectorCodecs) {
113
+ expect(codec.Decode(new Uint8Array(0)).length, codec.Name).toBe(0);
114
+ }
115
+ });
116
+ });
117
+ describe('GetBase64Codec selection on a bare host', () => {
118
+ afterEach(() => {
119
+ vi.unstubAllGlobals();
120
+ vi.resetModules();
121
+ });
122
+ it('falls back to atob/btoa when Buffer is absent', async () => {
123
+ vi.stubGlobal('Buffer', undefined);
124
+ vi.resetModules();
125
+ // A fresh module instance is needed because the codec choice is cached per process.
126
+ const fresh = await import('../util/BinaryEncoding.js');
127
+ expect(fresh.GetBase64Codec().Name).toBe('atob / btoa');
128
+ expect(fresh.BytesToBase64(new Uint8Array([1, 2, 3]))).toBe('AQID');
129
+ expect(Array.from(fresh.Base64ToBytes('AQI'))).toEqual([1, 2]);
130
+ expect(fresh.ReplaceByteArraysWithBase64({ D: new Uint8Array([255]) })).toEqual({ D: '/w==' });
131
+ });
132
+ it('throws when the host offers no base64 implementation', async () => {
133
+ vi.stubGlobal('Buffer', undefined);
134
+ vi.stubGlobal('atob', undefined);
135
+ vi.stubGlobal('btoa', undefined);
136
+ vi.resetModules();
137
+ const fresh = await import('../util/BinaryEncoding.js');
138
+ expect(() => fresh.GetBase64Codec()).toThrow('No base64 implementation is available on this host');
139
+ expect(() => fresh.BytesToBase64(new Uint8Array([1]))).toThrow('No base64 implementation');
140
+ // Zero bytes and invalid input never reach a codec.
141
+ expect(fresh.BytesToBase64(new Uint8Array(0))).toBe('');
142
+ expect(fresh.Base64ToBytes('').length).toBe(0);
143
+ expect(fresh.TryBase64ToBytes('!!')).toBeNull();
144
+ });
145
+ });
146
+ //# sourceMappingURL=BinaryEncodingRows.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinaryEncodingRows.test.js","sourceRoot":"","sources":["../../src/__tests__/BinaryEncodingRows.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EACH,uBAAuB,EACvB,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,8BAA8B,EAC9B,2BAA2B,GAC9B,MAAM,wBAAwB,CAAC;AAEhC,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,IAAI,CAAC;QACJ,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,CAAC,MAAM,EAAE,CAAC,CAAC;QACX,CAAC,MAAM,EAAE,CAAC,CAAC;QACX,CAAC,MAAM,EAAE,CAAC,CAAC;QACX,CAAC,MAAM,EAAE,CAAC,CAAC;QACX,CAAC,UAAU,EAAE,CAAC,CAAC;QACf,CAAC,UAAU,EAAE,CAAC,CAAC;KAClB,CAAC,CAAC,wBAAwB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC7C,MAAM,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC;QACJ,CAAC,IAAI,EAAE,CAAC,CAAC;QACT,CAAC,KAAK,EAAE,CAAC,CAAC;QACV,CAAC,KAAK,EAAE,CAAC,CAAC;QACV,CAAC,QAAQ,EAAE,CAAC,CAAC;KAChB,CAAC,CAAC,iCAAiC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QACtD,MAAM,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iFAAiF,EAAE,GAAG,EAAE;QACvF,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC;YAC1C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;YACpE,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC3C,MAAM,CAAC,uBAAuB,CAAC,MAAM,CAAC,EAAE,UAAU,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzE,MAAM,CAAC,uBAAuB,CAAC,QAAQ,CAAC,EAAE,YAAY,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7E,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxD,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC3E,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,CAAC,uBAAuB,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QAC/D,MAAM,GAAG,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAClH,MAAM,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAChD,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,MAAM,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACjE,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,KAAgB,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,2BAA2B,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAClD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,kBAAkB;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACpC,MAAM,GAAG,GAA4B,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,MAAM,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mFAAmF,EAAE,GAAG,EAAE;QACzF,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,GAA4B;YACjC,KAAK,EAAE,IAAI,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9B,KAAK,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC;SAC3B,CAAC;QACF,MAAM,MAAM,GAAG,2BAA2B,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACpG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC3D,MAAM,GAAG,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,EAAE,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,GAAG,GAA4B,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;QACvD,MAAM,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAY,EAAE,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,2BAA2B,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QACzD,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,GAAG,GAA4B,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACtE,MAAM,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACrE,MAAM,GAAG,GAA4B,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACjE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACnG,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,SAAS,OAAO,CAAC,KAAc;IAC3B,OAAO,KAAK,YAAY,UAAU,CAAC;AACvC,CAAC;AAED,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,8BAA8B,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACrE,MAAM,QAAQ,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACvG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QAClF,KAAK,MAAM,KAAK,IAAI,mBAAmB,EAAE,CAAC;YACtC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvE,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACrD,SAAS,CAAC,GAAG,EAAE;QACX,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACtB,EAAE,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC3D,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACnC,EAAE,CAAC,YAAY,EAAE,CAAC;QAClB,oFAAoF;QACpF,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/D,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,EAAE,CAAC,EAAE,IAAI,UAAU,CAAC,CAAC,GAAG,CAAC,CAAY,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9G,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QAClE,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACnC,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACjC,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACjC,EAAE,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;QACrD,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,oDAAoD,CAAC,CAAC;QACnG,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;QAC3F,oDAAoD;QACpD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACpD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=BinaryEncodingValidation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinaryEncodingValidation.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/BinaryEncodingValidation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,98 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { Base64Codecs, BytesToBase64, HasValidBase64Shape, IsValidBase64 } from '../util/BinaryEncoding.js';
3
+ /**
4
+ * Strict validation is enforced twice: by `IsValidBase64` (a character scan, used by codecs without a
5
+ * fused decoder) and by the Node codec's `TryDecode` (decode, then compare lengths — about five times
6
+ * cheaper). The two must agree on EVERY input, or the same value would be accepted on one host and
7
+ * refused on another. These tests pin that agreement, mostly by fuzzing.
8
+ */
9
+ const nodeCodec = Base64Codecs.find(c => c.Name === 'Node Buffer');
10
+ if (!nodeCodec?.TryDecode)
11
+ throw new Error('the Node Buffer codec must expose TryDecode');
12
+ const tryDecode = (value) => nodeCodec.TryDecode(value);
13
+ /** Deterministic PRNG so a failing fuzz case reproduces. */
14
+ function mulberry32(seed) {
15
+ let a = seed;
16
+ return () => {
17
+ a = (a + 0x6d2b79f5) | 0;
18
+ let t = Math.imul(a ^ (a >>> 15), 1 | a);
19
+ t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
20
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
21
+ };
22
+ }
23
+ const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
24
+ /** Characters a corrupted or foreign value might contain — URL-safe, whitespace, punctuation, non-ASCII. */
25
+ const HOSTILE = ['=', '-', '_', ' ', '\n', '\t', '\r', '.', '!', '*', '"', '\\', 'é', '€', '\u0000', '😀'];
26
+ describe('base64 validation: Node fused decode agrees with IsValidBase64', () => {
27
+ it.each([
28
+ ['', true],
29
+ ['AA==', true],
30
+ ['AAA=', true],
31
+ ['AAAA', true],
32
+ ['AAAAAA', true],
33
+ ['AAAAAAA', true],
34
+ ['A', false],
35
+ ['A===', false],
36
+ ['AA=', false],
37
+ ['=AAA', false],
38
+ ['AA==AAAA', false],
39
+ ['AA-A', false],
40
+ ['AA_A', false],
41
+ ['AA A', false],
42
+ ['AA\nA', false],
43
+ ['AAAA\n', false],
44
+ ['AAéA', false],
45
+ ['data:AAAA', false],
46
+ ])('%j → %s', (value, expected) => {
47
+ expect(IsValidBase64(value)).toBe(expected);
48
+ expect(tryDecode(value) !== null).toBe(expected);
49
+ });
50
+ it('decodes valid input to the same bytes the input encoded', () => {
51
+ const rand = mulberry32(7);
52
+ for (let n = 0; n < 300; n++) {
53
+ const bytes = Uint8Array.from({ length: n }, () => Math.floor(rand() * 256));
54
+ const encoded = BytesToBase64(bytes);
55
+ expect(Array.from(tryDecode(encoded) ?? [])).toEqual(Array.from(bytes));
56
+ expect(Array.from(tryDecode(encoded.replace(/=+$/, '')) ?? [])).toEqual(Array.from(bytes)); // unpadded
57
+ }
58
+ });
59
+ it('agrees on 20,000 random strings mixing valid and hostile characters', () => {
60
+ const rand = mulberry32(42);
61
+ let accepted = 0;
62
+ for (let n = 0; n < 20000; n++) {
63
+ const length = Math.floor(rand() * 24);
64
+ let value = '';
65
+ for (let i = 0; i < length; i++) {
66
+ value += rand() < 0.9 ? ALPHABET[Math.floor(rand() * ALPHABET.length)] : HOSTILE[Math.floor(rand() * HOSTILE.length)];
67
+ }
68
+ if (rand() < 0.3)
69
+ value += rand() < 0.5 ? '=' : '==';
70
+ const strict = IsValidBase64(value);
71
+ if (strict)
72
+ accepted++;
73
+ expect({ value, fused: tryDecode(value) !== null }).toEqual({ value, fused: strict });
74
+ }
75
+ expect(accepted).toBeGreaterThan(1000); // the corpus exercises the accept path too
76
+ });
77
+ it('agrees when one character of a valid string is corrupted, at every position', () => {
78
+ const encoded = BytesToBase64(Uint8Array.from({ length: 30 }, (_, i) => (i * 37) & 0xff));
79
+ for (let i = 0; i < encoded.length; i++) {
80
+ for (const bad of HOSTILE) {
81
+ const value = encoded.slice(0, i) + bad + encoded.slice(i + 1);
82
+ expect({ value, fused: tryDecode(value) !== null }).toEqual({ value, fused: IsValidBase64(value) });
83
+ }
84
+ }
85
+ });
86
+ });
87
+ describe('HasValidBase64Shape', () => {
88
+ it.each([
89
+ ['', true], ['AA', true], ['AAA', true], ['AAAA', true], ['AA==', true], ['AAA=', true],
90
+ ['A', false], ['AAAAA', false], ['AA=', false], ['A=', false],
91
+ ])('%j → %s (length and padding only, characters ignored)', (value, expected) => {
92
+ expect(HasValidBase64Shape(value)).toBe(expected);
93
+ });
94
+ it('does not inspect characters', () => {
95
+ expect(HasValidBase64Shape('!!!!')).toBe(true);
96
+ });
97
+ });
98
+ //# sourceMappingURL=BinaryEncodingValidation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BinaryEncodingValidation.test.js","sourceRoot":"","sources":["../../src/__tests__/BinaryEncodingValidation.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=UUIDCollections.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UUIDCollections.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/UUIDCollections.test.ts"],"names":[],"mappings":""}