@enbox/dwn-sdk-js 0.1.1 → 0.2.0

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 (144) hide show
  1. package/dist/browser.mjs +7 -16
  2. package/dist/browser.mjs.map +4 -4
  3. package/dist/esm/src/utils/hd-key.js +1 -1
  4. package/dist/esm/src/utils/hd-key.js.map +1 -1
  5. package/dist/esm/src/utils/protocols.js +2 -2
  6. package/dist/esm/src/utils/protocols.js.map +1 -1
  7. package/dist/esm/tests/fuzz/arbitraries/dwn-message.arbitrary.js +72 -0
  8. package/dist/esm/tests/fuzz/arbitraries/dwn-message.arbitrary.js.map +1 -0
  9. package/dist/esm/tests/fuzz/arbitraries/filter.arbitrary.js +53 -0
  10. package/dist/esm/tests/fuzz/arbitraries/filter.arbitrary.js.map +1 -0
  11. package/dist/esm/tests/fuzz/arbitraries/jws.arbitrary.js +55 -0
  12. package/dist/esm/tests/fuzz/arbitraries/jws.arbitrary.js.map +1 -0
  13. package/dist/esm/tests/fuzz/arbitraries/protocol-definition.arbitrary.js +106 -0
  14. package/dist/esm/tests/fuzz/arbitraries/protocol-definition.arbitrary.js.map +1 -0
  15. package/dist/esm/tests/fuzz/arbitraries/store.arbitrary.js +139 -0
  16. package/dist/esm/tests/fuzz/arbitraries/store.arbitrary.js.map +1 -0
  17. package/dist/esm/tests/fuzz/cid.fuzz.spec.js +74 -0
  18. package/dist/esm/tests/fuzz/cid.fuzz.spec.js.map +1 -0
  19. package/dist/esm/tests/fuzz/compound-index.fuzz.spec.js +203 -0
  20. package/dist/esm/tests/fuzz/compound-index.fuzz.spec.js.map +1 -0
  21. package/dist/esm/tests/fuzz/data-store.fuzz.spec.js +146 -0
  22. package/dist/esm/tests/fuzz/data-store.fuzz.spec.js.map +1 -0
  23. package/dist/esm/tests/fuzz/data-stream.fuzz.spec.js +44 -0
  24. package/dist/esm/tests/fuzz/data-stream.fuzz.spec.js.map +1 -0
  25. package/dist/esm/tests/fuzz/encoder.fuzz.spec.js +76 -0
  26. package/dist/esm/tests/fuzz/encoder.fuzz.spec.js.map +1 -0
  27. package/dist/esm/tests/fuzz/encryption.fuzz.spec.js +132 -0
  28. package/dist/esm/tests/fuzz/encryption.fuzz.spec.js.map +1 -0
  29. package/dist/esm/tests/fuzz/filter.fuzz.spec.js +149 -0
  30. package/dist/esm/tests/fuzz/filter.fuzz.spec.js.map +1 -0
  31. package/dist/esm/tests/fuzz/get-rule-set-at-path.fuzz.spec.js +82 -0
  32. package/dist/esm/tests/fuzz/get-rule-set-at-path.fuzz.spec.js.map +1 -0
  33. package/dist/esm/tests/fuzz/hd-key.fuzz.spec.js +77 -0
  34. package/dist/esm/tests/fuzz/hd-key.fuzz.spec.js.map +1 -0
  35. package/dist/esm/tests/fuzz/immutable-properties.fuzz.spec.js +86 -0
  36. package/dist/esm/tests/fuzz/immutable-properties.fuzz.spec.js.map +1 -0
  37. package/dist/esm/tests/fuzz/index-level.fuzz.spec.js +195 -0
  38. package/dist/esm/tests/fuzz/index-level.fuzz.spec.js.map +1 -0
  39. package/dist/esm/tests/fuzz/jws.fuzz.spec.js +100 -0
  40. package/dist/esm/tests/fuzz/jws.fuzz.spec.js.map +1 -0
  41. package/dist/esm/tests/fuzz/message-store.fuzz.spec.js +154 -0
  42. package/dist/esm/tests/fuzz/message-store.fuzz.spec.js.map +1 -0
  43. package/dist/esm/tests/fuzz/object.fuzz.spec.js +82 -0
  44. package/dist/esm/tests/fuzz/object.fuzz.spec.js.map +1 -0
  45. package/dist/esm/tests/fuzz/process-message.fuzz.spec.js +85 -0
  46. package/dist/esm/tests/fuzz/process-message.fuzz.spec.js.map +1 -0
  47. package/dist/esm/tests/fuzz/protocol-definition.fuzz.spec.js +145 -0
  48. package/dist/esm/tests/fuzz/protocol-definition.fuzz.spec.js.map +1 -0
  49. package/dist/esm/tests/fuzz/protocol-validation.fuzz.spec.js +160 -0
  50. package/dist/esm/tests/fuzz/protocol-validation.fuzz.spec.js.map +1 -0
  51. package/dist/esm/tests/fuzz/protocols-utils.fuzz.spec.js +41 -0
  52. package/dist/esm/tests/fuzz/protocols-utils.fuzz.spec.js.map +1 -0
  53. package/dist/esm/tests/fuzz/records-utils.fuzz.spec.js +81 -0
  54. package/dist/esm/tests/fuzz/records-utils.fuzz.spec.js.map +1 -0
  55. package/dist/esm/tests/fuzz/resumable-task-store.fuzz.spec.js +106 -0
  56. package/dist/esm/tests/fuzz/resumable-task-store.fuzz.spec.js.map +1 -0
  57. package/dist/esm/tests/fuzz/schema-validation.fuzz.spec.js +126 -0
  58. package/dist/esm/tests/fuzz/schema-validation.fuzz.spec.js.map +1 -0
  59. package/dist/esm/tests/fuzz/secp256k1.fuzz.spec.js +74 -0
  60. package/dist/esm/tests/fuzz/secp256k1.fuzz.spec.js.map +1 -0
  61. package/dist/esm/tests/fuzz/secp256r1.fuzz.spec.js +60 -0
  62. package/dist/esm/tests/fuzz/secp256r1.fuzz.spec.js.map +1 -0
  63. package/dist/esm/tests/fuzz/time.fuzz.spec.js +82 -0
  64. package/dist/esm/tests/fuzz/time.fuzz.spec.js.map +1 -0
  65. package/dist/esm/tests/fuzz/url.fuzz.spec.js +118 -0
  66. package/dist/esm/tests/fuzz/url.fuzz.spec.js.map +1 -0
  67. package/dist/esm/tests/handlers/records-subscribe.spec.js +1 -1
  68. package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
  69. package/dist/esm/tests/utils/secp256k1.spec.js.map +1 -1
  70. package/dist/esm/tests/utils/secp256r1.spec.js.map +1 -1
  71. package/dist/types/generated/precompiled-validators.d.ts +0 -70
  72. package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
  73. package/dist/types/src/index.d.ts +2 -2
  74. package/dist/types/src/index.d.ts.map +1 -1
  75. package/dist/types/src/types/messages-types.d.ts +0 -4
  76. package/dist/types/src/types/messages-types.d.ts.map +1 -1
  77. package/dist/types/src/types/records-types.d.ts +0 -4
  78. package/dist/types/src/types/records-types.d.ts.map +1 -1
  79. package/dist/types/tests/fuzz/arbitraries/dwn-message.arbitrary.d.ts +31 -0
  80. package/dist/types/tests/fuzz/arbitraries/dwn-message.arbitrary.d.ts.map +1 -0
  81. package/dist/types/tests/fuzz/arbitraries/filter.arbitrary.d.ts +27 -0
  82. package/dist/types/tests/fuzz/arbitraries/filter.arbitrary.d.ts.map +1 -0
  83. package/dist/types/tests/fuzz/arbitraries/jws.arbitrary.d.ts +26 -0
  84. package/dist/types/tests/fuzz/arbitraries/jws.arbitrary.d.ts.map +1 -0
  85. package/dist/types/tests/fuzz/arbitraries/protocol-definition.arbitrary.d.ts +31 -0
  86. package/dist/types/tests/fuzz/arbitraries/protocol-definition.arbitrary.d.ts.map +1 -0
  87. package/dist/types/tests/fuzz/arbitraries/store.arbitrary.d.ts +71 -0
  88. package/dist/types/tests/fuzz/arbitraries/store.arbitrary.d.ts.map +1 -0
  89. package/dist/types/tests/fuzz/cid.fuzz.spec.d.ts +2 -0
  90. package/dist/types/tests/fuzz/cid.fuzz.spec.d.ts.map +1 -0
  91. package/dist/types/tests/fuzz/compound-index.fuzz.spec.d.ts +2 -0
  92. package/dist/types/tests/fuzz/compound-index.fuzz.spec.d.ts.map +1 -0
  93. package/dist/types/tests/fuzz/data-store.fuzz.spec.d.ts +2 -0
  94. package/dist/types/tests/fuzz/data-store.fuzz.spec.d.ts.map +1 -0
  95. package/dist/types/tests/fuzz/data-stream.fuzz.spec.d.ts +2 -0
  96. package/dist/types/tests/fuzz/data-stream.fuzz.spec.d.ts.map +1 -0
  97. package/dist/types/tests/fuzz/encoder.fuzz.spec.d.ts +2 -0
  98. package/dist/types/tests/fuzz/encoder.fuzz.spec.d.ts.map +1 -0
  99. package/dist/types/tests/fuzz/encryption.fuzz.spec.d.ts +2 -0
  100. package/dist/types/tests/fuzz/encryption.fuzz.spec.d.ts.map +1 -0
  101. package/dist/types/tests/fuzz/filter.fuzz.spec.d.ts +2 -0
  102. package/dist/types/tests/fuzz/filter.fuzz.spec.d.ts.map +1 -0
  103. package/dist/types/tests/fuzz/get-rule-set-at-path.fuzz.spec.d.ts +2 -0
  104. package/dist/types/tests/fuzz/get-rule-set-at-path.fuzz.spec.d.ts.map +1 -0
  105. package/dist/types/tests/fuzz/hd-key.fuzz.spec.d.ts +2 -0
  106. package/dist/types/tests/fuzz/hd-key.fuzz.spec.d.ts.map +1 -0
  107. package/dist/types/tests/fuzz/immutable-properties.fuzz.spec.d.ts +2 -0
  108. package/dist/types/tests/fuzz/immutable-properties.fuzz.spec.d.ts.map +1 -0
  109. package/dist/types/tests/fuzz/index-level.fuzz.spec.d.ts +2 -0
  110. package/dist/types/tests/fuzz/index-level.fuzz.spec.d.ts.map +1 -0
  111. package/dist/types/tests/fuzz/jws.fuzz.spec.d.ts +2 -0
  112. package/dist/types/tests/fuzz/jws.fuzz.spec.d.ts.map +1 -0
  113. package/dist/types/tests/fuzz/message-store.fuzz.spec.d.ts +2 -0
  114. package/dist/types/tests/fuzz/message-store.fuzz.spec.d.ts.map +1 -0
  115. package/dist/types/tests/fuzz/object.fuzz.spec.d.ts +2 -0
  116. package/dist/types/tests/fuzz/object.fuzz.spec.d.ts.map +1 -0
  117. package/dist/types/tests/fuzz/process-message.fuzz.spec.d.ts +2 -0
  118. package/dist/types/tests/fuzz/process-message.fuzz.spec.d.ts.map +1 -0
  119. package/dist/types/tests/fuzz/protocol-definition.fuzz.spec.d.ts +2 -0
  120. package/dist/types/tests/fuzz/protocol-definition.fuzz.spec.d.ts.map +1 -0
  121. package/dist/types/tests/fuzz/protocol-validation.fuzz.spec.d.ts +2 -0
  122. package/dist/types/tests/fuzz/protocol-validation.fuzz.spec.d.ts.map +1 -0
  123. package/dist/types/tests/fuzz/protocols-utils.fuzz.spec.d.ts +2 -0
  124. package/dist/types/tests/fuzz/protocols-utils.fuzz.spec.d.ts.map +1 -0
  125. package/dist/types/tests/fuzz/records-utils.fuzz.spec.d.ts +2 -0
  126. package/dist/types/tests/fuzz/records-utils.fuzz.spec.d.ts.map +1 -0
  127. package/dist/types/tests/fuzz/resumable-task-store.fuzz.spec.d.ts +2 -0
  128. package/dist/types/tests/fuzz/resumable-task-store.fuzz.spec.d.ts.map +1 -0
  129. package/dist/types/tests/fuzz/schema-validation.fuzz.spec.d.ts +2 -0
  130. package/dist/types/tests/fuzz/schema-validation.fuzz.spec.d.ts.map +1 -0
  131. package/dist/types/tests/fuzz/secp256k1.fuzz.spec.d.ts +2 -0
  132. package/dist/types/tests/fuzz/secp256k1.fuzz.spec.d.ts.map +1 -0
  133. package/dist/types/tests/fuzz/secp256r1.fuzz.spec.d.ts +2 -0
  134. package/dist/types/tests/fuzz/secp256r1.fuzz.spec.d.ts.map +1 -0
  135. package/dist/types/tests/fuzz/time.fuzz.spec.d.ts +2 -0
  136. package/dist/types/tests/fuzz/time.fuzz.spec.d.ts.map +1 -0
  137. package/dist/types/tests/fuzz/url.fuzz.spec.d.ts +2 -0
  138. package/dist/types/tests/fuzz/url.fuzz.spec.d.ts.map +1 -0
  139. package/package.json +24 -25
  140. package/src/index.ts +2 -2
  141. package/src/types/messages-types.ts +0 -5
  142. package/src/types/records-types.ts +0 -5
  143. package/src/utils/hd-key.ts +2 -2
  144. package/src/utils/protocols.ts +2 -2
@@ -0,0 +1,203 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import fc from 'fast-check';
3
+ import { SortDirection } from '../../src/types/query-types.js';
4
+ import { buildCompoundKey, buildCompoundPrefix, COMPOUND_SEGMENT_SEPARATOR, selectCompoundIndex } from '../../src/store/index-level-compound.js';
5
+ const numRuns = Number(process.env.FAST_CHECK_NUM_RUNS) || 100;
6
+ /**
7
+ * The IndexLevel.encodeValue implementation for string values:
8
+ * strings are left as-is in the real code. We use this simplified
9
+ * version since we only generate string index values.
10
+ */
11
+ function encodeValue(value) {
12
+ return String(value);
13
+ }
14
+ const DELIMITER = '\x00';
15
+ describe('Compound index — fuzz', () => {
16
+ /**
17
+ * Object.prototype property names that would collide with plain-object property lookups.
18
+ */
19
+ const prototypeNames = new Set(Object.getOwnPropertyNames(Object.prototype));
20
+ /**
21
+ * Arbitrary for a property name (no special chars that collide with separators,
22
+ * no Object.prototype names like __proto__, toString, valueOf).
23
+ */
24
+ const arbPropName = fc.string({ minLength: 1, maxLength: 10 })
25
+ .filter((s) => !s.includes('\x00') && !s.includes('\x01') && !s.includes('/') && !prototypeNames.has(s));
26
+ /**
27
+ * Arbitrary for a messageCid-like string.
28
+ */
29
+ const arbMessageCid = fc.stringMatching(/^[a-z0-9]{10,20}$/);
30
+ describe('buildCompoundKey/buildCompoundPrefix consistency', () => {
31
+ it('should produce a key that starts with the corresponding prefix', () => {
32
+ fc.assert(fc.property(fc.array(arbPropName, { minLength: 1, maxLength: 4 })
33
+ .filter((props) => new Set(props).size === props.length), arbPropName.filter((s) => s.length > 0), arbMessageCid, (properties, sortProperty, messageCid) => {
34
+ // Ensure sortProperty is not in properties
35
+ if (properties.includes(sortProperty)) {
36
+ return;
37
+ }
38
+ const compoundIndex = {
39
+ name: 'test',
40
+ properties,
41
+ sortProperty,
42
+ };
43
+ // Build indexes that satisfy all properties + sort
44
+ const indexes = {};
45
+ for (const prop of properties) {
46
+ indexes[prop] = `val_${prop}`;
47
+ }
48
+ indexes[sortProperty] = 'sortval';
49
+ // Also build a filter with the same equality values
50
+ const filter = {};
51
+ for (const prop of properties) {
52
+ filter[prop] = `val_${prop}`;
53
+ }
54
+ const key = buildCompoundKey(messageCid, indexes, compoundIndex, encodeValue, DELIMITER);
55
+ const prefix = buildCompoundPrefix(filter, compoundIndex, encodeValue);
56
+ expect(key).toBeDefined();
57
+ expect(prefix).toBeDefined();
58
+ expect(key.startsWith(prefix)).toBe(true);
59
+ }), { numRuns });
60
+ });
61
+ });
62
+ describe('buildCompoundKey — returns undefined for missing properties', () => {
63
+ it('should return undefined when a required property is missing from indexes', () => {
64
+ fc.assert(fc.property(fc.array(arbPropName, { minLength: 2, maxLength: 4 })
65
+ .filter((props) => new Set(props).size === props.length), arbPropName, arbMessageCid, fc.nat(), (properties, sortProperty, messageCid, dropSeed) => {
66
+ if (properties.includes(sortProperty)) {
67
+ return;
68
+ }
69
+ const compoundIndex = {
70
+ name: 'test',
71
+ properties,
72
+ sortProperty,
73
+ };
74
+ // Build indexes but omit one required property
75
+ const indexes = {};
76
+ const dropIndex = dropSeed % properties.length;
77
+ for (let i = 0; i < properties.length; i++) {
78
+ if (i !== dropIndex) {
79
+ indexes[properties[i]] = `val_${properties[i]}`;
80
+ }
81
+ }
82
+ indexes[sortProperty] = 'sortval';
83
+ const key = buildCompoundKey(messageCid, indexes, compoundIndex, encodeValue, DELIMITER);
84
+ expect(key).toBeUndefined();
85
+ }), { numRuns });
86
+ });
87
+ });
88
+ describe('buildCompoundPrefix — returns undefined for non-equality filters', () => {
89
+ it('should return undefined when a property has an object filter (range)', () => {
90
+ fc.assert(fc.property(fc.array(arbPropName, { minLength: 1, maxLength: 3 })
91
+ .filter((props) => new Set(props).size === props.length), arbPropName, fc.nat(), (properties, sortProperty, rangeSeed) => {
92
+ if (properties.includes(sortProperty)) {
93
+ return;
94
+ }
95
+ const compoundIndex = {
96
+ name: 'test',
97
+ properties,
98
+ sortProperty,
99
+ };
100
+ // Set one property to an object (range filter) instead of equality
101
+ const filter = {};
102
+ const rangeIndex = rangeSeed % properties.length;
103
+ for (let i = 0; i < properties.length; i++) {
104
+ if (i === rangeIndex) {
105
+ filter[properties[i]] = { gte: 'a', lte: 'z' }; // range filter
106
+ }
107
+ else {
108
+ filter[properties[i]] = `val_${properties[i]}`;
109
+ }
110
+ }
111
+ const prefix = buildCompoundPrefix(filter, compoundIndex, encodeValue);
112
+ expect(prefix).toBeUndefined();
113
+ }), { numRuns });
114
+ });
115
+ });
116
+ describe('selectCompoundIndex — correctness', () => {
117
+ it('should select the compound index with the most matching properties', () => {
118
+ fc.assert(fc.property(arbPropName, arbPropName, arbPropName, arbPropName, (prop1, prop2, prop3, sortProp) => {
119
+ // Ensure all distinct
120
+ const allNames = [prop1, prop2, prop3, sortProp];
121
+ if (new Set(allNames).size !== allNames.length) {
122
+ return;
123
+ }
124
+ const smallIndex = {
125
+ name: 'small',
126
+ properties: [prop1],
127
+ sortProperty: sortProp,
128
+ };
129
+ const largeIndex = {
130
+ name: 'large',
131
+ properties: [prop1, prop2],
132
+ sortProperty: sortProp,
133
+ };
134
+ const wrongSort = {
135
+ name: 'wrongSort',
136
+ properties: [prop1, prop2, prop3],
137
+ sortProperty: 'nonexistent_sort',
138
+ };
139
+ const filter = {
140
+ [prop1]: 'v1',
141
+ [prop2]: 'v2',
142
+ [prop3]: 'v3',
143
+ };
144
+ const queryOptions = {
145
+ sortProperty: sortProp,
146
+ sortDirection: SortDirection.Ascending,
147
+ };
148
+ const selected = selectCompoundIndex(filter, queryOptions, [smallIndex, largeIndex, wrongSort]);
149
+ expect(selected).toBe(largeIndex); // largeIndex has more matching properties
150
+ }), { numRuns });
151
+ });
152
+ it('should return undefined when no compound index matches sort property', () => {
153
+ fc.assert(fc.property(arbPropName, arbPropName, (prop, sortProp) => {
154
+ if (prop === sortProp) {
155
+ return;
156
+ }
157
+ const idx = {
158
+ name: 'idx',
159
+ properties: [prop],
160
+ sortProperty: 'other_sort',
161
+ };
162
+ const filter = { [prop]: 'val' };
163
+ const queryOptions = {
164
+ sortProperty: sortProp,
165
+ sortDirection: SortDirection.Ascending,
166
+ };
167
+ const selected = selectCompoundIndex(filter, queryOptions, [idx]);
168
+ expect(selected).toBeUndefined();
169
+ }), { numRuns });
170
+ });
171
+ });
172
+ describe('buildCompoundKey — key contains all segments in order', () => {
173
+ it('should encode property values in the compound key in definition order', () => {
174
+ fc.assert(fc.property(fc.array(arbPropName, { minLength: 1, maxLength: 4 })
175
+ .filter((props) => new Set(props).size === props.length), arbPropName, arbMessageCid, (properties, sortProperty, messageCid) => {
176
+ if (properties.includes(sortProperty)) {
177
+ return;
178
+ }
179
+ const compoundIndex = {
180
+ name: 'test',
181
+ properties,
182
+ sortProperty,
183
+ };
184
+ const indexes = {};
185
+ const values = [];
186
+ for (const prop of properties) {
187
+ const val = `v_${prop}`;
188
+ indexes[prop] = val;
189
+ values.push(val);
190
+ }
191
+ const sortVal = 'sort_val';
192
+ indexes[sortProperty] = sortVal;
193
+ const key = buildCompoundKey(messageCid, indexes, compoundIndex, encodeValue, DELIMITER);
194
+ expect(key).toBeDefined();
195
+ // Verify: key should be values joined by \x01, then \x01sortVal\x00messageCid
196
+ const expected = values.join(COMPOUND_SEGMENT_SEPARATOR) +
197
+ COMPOUND_SEGMENT_SEPARATOR + sortVal + DELIMITER + messageCid;
198
+ expect(key).toBe(expected);
199
+ }), { numRuns });
200
+ });
201
+ });
202
+ });
203
+ //# sourceMappingURL=compound-index.fuzz.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compound-index.fuzz.spec.js","sourceRoot":"","sources":["../../../../tests/fuzz/compound-index.fuzz.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ import { afterAll, afterEach, beforeAll, describe, expect, it } from 'bun:test';
2
+ import fc from 'fast-check';
3
+ import { Cid } from '../../src/utils/cid.js';
4
+ import { DataStoreLevel } from '../../src/store/data-store-level.js';
5
+ import { dataBlob, recordId, tenantDid } from './arbitraries/store.arbitrary.js';
6
+ const numRuns = Number(process.env.FAST_CHECK_NUM_RUNS) || 100;
7
+ /** Helper to create a ReadableStream from a Uint8Array. */
8
+ function streamFrom(data) {
9
+ return new ReadableStream({
10
+ start(controller) {
11
+ controller.enqueue(data);
12
+ controller.close();
13
+ }
14
+ });
15
+ }
16
+ /** Helper to read all bytes from a ReadableStream. */
17
+ async function readStream(stream) {
18
+ const reader = stream.getReader();
19
+ const chunks = [];
20
+ let done = false;
21
+ while (!done) {
22
+ const result = await reader.read();
23
+ done = result.done;
24
+ if (result.value) {
25
+ chunks.push(result.value);
26
+ }
27
+ }
28
+ const totalLength = chunks.reduce((sum, c) => sum + c.length, 0);
29
+ const result = new Uint8Array(totalLength);
30
+ let offset = 0;
31
+ for (const chunk of chunks) {
32
+ result.set(chunk, offset);
33
+ offset += chunk.length;
34
+ }
35
+ return result;
36
+ }
37
+ describe('DataStoreLevel — fuzz', () => {
38
+ let dataStore;
39
+ const testDataPath = '__TESTDATA__/fuzz-data-store';
40
+ const tenant = 'did:example:fuzz-data-tenant';
41
+ beforeAll(async () => {
42
+ dataStore = new DataStoreLevel({ blockstoreLocation: `${testDataPath}/blocks` });
43
+ await dataStore.open();
44
+ });
45
+ afterEach(async () => {
46
+ await dataStore.clear();
47
+ });
48
+ afterAll(async () => {
49
+ await dataStore.close();
50
+ });
51
+ describe('binary data roundtrip', () => {
52
+ it('should store and retrieve arbitrary binary data with correct size', async () => {
53
+ await fc.assert(fc.asyncProperty(dataBlob({ minSize: 1, maxSize: 2048 }), async (data) => {
54
+ await dataStore.clear();
55
+ const dataCid = await Cid.computeDagPbCidFromBytes(data);
56
+ const recId = 'rec_roundtrip';
57
+ const putResult = await dataStore.put(tenant, recId, dataCid, streamFrom(data));
58
+ expect(putResult.dataSize).toBe(data.length);
59
+ const getResult = await dataStore.get(tenant, recId, dataCid);
60
+ expect(getResult).toBeDefined();
61
+ expect(getResult.dataSize).toBe(data.length);
62
+ const retrieved = await readStream(getResult.dataStream);
63
+ expect(retrieved).toEqual(data);
64
+ }), { numRuns: Math.min(numRuns, 30) });
65
+ });
66
+ });
67
+ describe('get returns undefined for missing data', () => {
68
+ it('should return undefined for non-existent records', async () => {
69
+ await fc.assert(fc.asyncProperty(recordId(), async (recId) => {
70
+ const result = await dataStore.get(tenant, recId, 'bafkreinonexistent');
71
+ expect(result).toBeUndefined();
72
+ }), { numRuns: Math.min(numRuns, 30) });
73
+ });
74
+ });
75
+ describe('idempotent put', () => {
76
+ it('should return the same dataSize when putting the same data twice', async () => {
77
+ await fc.assert(fc.asyncProperty(dataBlob({ minSize: 10, maxSize: 512 }), async (data) => {
78
+ await dataStore.clear();
79
+ const dataCid = await Cid.computeDagPbCidFromBytes(data);
80
+ const recId = 'rec_idempotent';
81
+ const result1 = await dataStore.put(tenant, recId, dataCid, streamFrom(data));
82
+ const result2 = await dataStore.put(tenant, recId, dataCid, streamFrom(data));
83
+ expect(result1.dataSize).toBe(result2.dataSize);
84
+ expect(result1.dataSize).toBe(data.length);
85
+ }), { numRuns: Math.min(numRuns, 20) });
86
+ });
87
+ });
88
+ describe('tenant isolation', () => {
89
+ it('should not allow one tenant to read another tenant\'s data', async () => {
90
+ await fc.assert(fc.asyncProperty(tenantDid(), tenantDid(), dataBlob({ minSize: 10, maxSize: 256 }), async (tenant1, tenant2, data) => {
91
+ // Skip if tenants are the same
92
+ if (tenant1 === tenant2) {
93
+ return;
94
+ }
95
+ await dataStore.clear();
96
+ const dataCid = await Cid.computeDagPbCidFromBytes(data);
97
+ const recId = 'rec_isolation';
98
+ await dataStore.put(tenant1, recId, dataCid, streamFrom(data));
99
+ // Tenant 2 should not be able to get tenant 1's data
100
+ const result = await dataStore.get(tenant2, recId, dataCid);
101
+ expect(result).toBeUndefined();
102
+ }), { numRuns: Math.min(numRuns, 20) });
103
+ });
104
+ });
105
+ describe('delete removes data', () => {
106
+ it('should return undefined after deleting a record', async () => {
107
+ await fc.assert(fc.asyncProperty(dataBlob({ minSize: 10, maxSize: 512 }), async (data) => {
108
+ await dataStore.clear();
109
+ const dataCid = await Cid.computeDagPbCidFromBytes(data);
110
+ const recId = 'rec_delete';
111
+ await dataStore.put(tenant, recId, dataCid, streamFrom(data));
112
+ await dataStore.delete(tenant, recId, dataCid);
113
+ const result = await dataStore.get(tenant, recId, dataCid);
114
+ expect(result).toBeUndefined();
115
+ }), { numRuns: Math.min(numRuns, 20) });
116
+ });
117
+ });
118
+ describe('reference counting — shared blocks survive partial deletion', () => {
119
+ it('should retain data while at least one reference exists', async () => {
120
+ await fc.assert(fc.asyncProperty(dataBlob({ minSize: 10, maxSize: 256 }), fc.integer({ min: 2, max: 4 }), async (data, refCount) => {
121
+ await dataStore.clear();
122
+ const dataCid = await Cid.computeDagPbCidFromBytes(data);
123
+ // Create multiple references to the same data
124
+ const refs = [];
125
+ for (let i = 0; i < refCount; i++) {
126
+ const t = `did:example:tenant${i}`;
127
+ const r = `rec_ref${i}`;
128
+ await dataStore.put(t, r, dataCid, streamFrom(data));
129
+ refs.push({ tenant: t, recId: r });
130
+ }
131
+ // Delete all but the last reference
132
+ for (let i = 0; i < refCount - 1; i++) {
133
+ await dataStore.delete(refs[i].tenant, refs[i].recId, dataCid);
134
+ }
135
+ // The last reference should still be retrievable
136
+ const lastRef = refs[refCount - 1];
137
+ const result = await dataStore.get(lastRef.tenant, lastRef.recId, dataCid);
138
+ expect(result).toBeDefined();
139
+ expect(result.dataSize).toBe(data.length);
140
+ const retrieved = await readStream(result.dataStream);
141
+ expect(retrieved).toEqual(data);
142
+ }), { numRuns: Math.min(numRuns, 15) });
143
+ });
144
+ });
145
+ });
146
+ //# sourceMappingURL=data-store.fuzz.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-store.fuzz.spec.js","sourceRoot":"","sources":["../../../../tests/fuzz/data-store.fuzz.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import fc from 'fast-check';
3
+ import { DataStream } from '../../src/utils/data-stream.js';
4
+ const numRuns = Number(process.env.FAST_CHECK_NUM_RUNS) || 100;
5
+ describe('DataStream — fuzz', () => {
6
+ describe('fromBytes/toBytes roundtrip', () => {
7
+ it('should return identical bytes for any Uint8Array', async () => {
8
+ await fc.assert(fc.asyncProperty(fc.uint8Array({ minLength: 0, maxLength: 4096 }), async (bytes) => {
9
+ const stream = DataStream.fromBytes(bytes);
10
+ const result = await DataStream.toBytes(stream);
11
+ expect(result).toEqual(bytes);
12
+ }), { numRuns: Math.min(numRuns, 50) });
13
+ });
14
+ });
15
+ describe('duplicateDataStream — count invariant', () => {
16
+ it('should return exactly N streams for N >= 1', async () => {
17
+ await fc.assert(fc.asyncProperty(fc.uint8Array({ minLength: 1, maxLength: 256 }), fc.integer({ min: 1, max: 5 }), async (bytes, count) => {
18
+ const stream = DataStream.fromBytes(bytes);
19
+ const copies = DataStream.duplicateDataStream(stream, count);
20
+ expect(copies.length).toBe(count);
21
+ }), { numRuns: Math.min(numRuns, 30) });
22
+ });
23
+ it('should return empty array for count < 1', () => {
24
+ fc.assert(fc.property(fc.uint8Array({ minLength: 1, maxLength: 64 }), fc.integer({ min: -10, max: 0 }), (bytes, count) => {
25
+ const stream = DataStream.fromBytes(bytes);
26
+ const copies = DataStream.duplicateDataStream(stream, count);
27
+ expect(copies.length).toBe(0);
28
+ }), { numRuns: Math.min(numRuns, 20) });
29
+ });
30
+ });
31
+ describe('duplicateDataStream — content equality', () => {
32
+ it('should produce identical bytes from each duplicate', async () => {
33
+ await fc.assert(fc.asyncProperty(fc.uint8Array({ minLength: 1, maxLength: 1024 }), fc.integer({ min: 2, max: 4 }), async (bytes, count) => {
34
+ const stream = DataStream.fromBytes(bytes);
35
+ const copies = DataStream.duplicateDataStream(stream, count);
36
+ const results = await Promise.all(copies.map((s) => DataStream.toBytes(s)));
37
+ for (const result of results) {
38
+ expect(result).toEqual(bytes);
39
+ }
40
+ }), { numRuns: Math.min(numRuns, 20) });
41
+ });
42
+ });
43
+ });
44
+ //# sourceMappingURL=data-stream.fuzz.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-stream.fuzz.spec.js","sourceRoot":"","sources":["../../../../tests/fuzz/data-stream.fuzz.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import fc from 'fast-check';
3
+ import { Encoder } from '../../src/utils/encoder.js';
4
+ const numRuns = Number(process.env.FAST_CHECK_NUM_RUNS) || 200;
5
+ describe('Encoder — fuzz', () => {
6
+ describe('bytes <-> base64url roundtrip', () => {
7
+ it('should roundtrip arbitrary byte arrays through base64url encoding', () => {
8
+ fc.assert(fc.property(fc.uint8Array({ minLength: 0, maxLength: 1024 }), (bytes) => {
9
+ const encoded = Encoder.bytesToBase64Url(bytes);
10
+ const decoded = Encoder.base64UrlToBytes(encoded);
11
+ expect(decoded).toEqual(bytes);
12
+ }), { numRuns });
13
+ });
14
+ });
15
+ describe('object <-> bytes roundtrip', () => {
16
+ it('should roundtrip JSON-serializable objects through bytes encoding', () => {
17
+ fc.assert(fc.property(fc.dictionary(fc.string({ minLength: 1, maxLength: 20 }), fc.oneof(fc.string(), fc.integer(), fc.boolean(), fc.constant(null)), { minKeys: 0, maxKeys: 10 }), (obj) => {
18
+ const bytes = Encoder.objectToBytes(obj);
19
+ const decoded = Encoder.bytesToObject(bytes);
20
+ expect(decoded).toEqual(obj);
21
+ }), { numRuns });
22
+ });
23
+ });
24
+ describe('string <-> base64url roundtrip', () => {
25
+ it('should roundtrip arbitrary strings through base64url encoding', () => {
26
+ fc.assert(fc.property(fc.string({ minLength: 0, maxLength: 500 }), (str) => {
27
+ const encoded = Encoder.stringToBase64Url(str);
28
+ const bytes = Encoder.base64UrlToBytes(encoded);
29
+ const decoded = Encoder.bytesToString(bytes);
30
+ expect(decoded).toBe(str);
31
+ }), { numRuns });
32
+ });
33
+ });
34
+ describe('string <-> bytes roundtrip', () => {
35
+ it('should roundtrip arbitrary strings through bytes encoding', () => {
36
+ fc.assert(fc.property(fc.string({ minLength: 0, maxLength: 500 }), (str) => {
37
+ const bytes = Encoder.stringToBytes(str);
38
+ const decoded = Encoder.bytesToString(bytes);
39
+ expect(decoded).toBe(str);
40
+ }), { numRuns });
41
+ });
42
+ });
43
+ describe('base64UrlToObject — crash resistance', () => {
44
+ it('should throw on arbitrary non-base64url strings without crashing', () => {
45
+ fc.assert(fc.property(fc.string({ minLength: 0, maxLength: 200 }), (str) => {
46
+ try {
47
+ Encoder.base64UrlToObject(str);
48
+ // If it doesn't throw, the result should be a defined value
49
+ }
50
+ catch (error) {
51
+ // Any error is acceptable — we just verify no unhandled crash
52
+ expect(error).toBeDefined();
53
+ }
54
+ }), { numRuns });
55
+ });
56
+ });
57
+ describe('bytesToBase64Url output validity', () => {
58
+ it('should produce strings containing only base64url characters', () => {
59
+ const base64urlPattern = /^[A-Za-z0-9_-]*$/;
60
+ fc.assert(fc.property(fc.uint8Array({ minLength: 0, maxLength: 256 }), (bytes) => {
61
+ const encoded = Encoder.bytesToBase64Url(bytes);
62
+ expect(base64urlPattern.test(encoded)).toBe(true);
63
+ }), { numRuns });
64
+ });
65
+ });
66
+ describe('objectToBytes — determinism', () => {
67
+ it('should produce identical bytes for the same object', () => {
68
+ fc.assert(fc.property(fc.dictionary(fc.string({ minLength: 1, maxLength: 10 }), fc.oneof(fc.string(), fc.integer(), fc.boolean()), { minKeys: 1, maxKeys: 5 }), (obj) => {
69
+ const bytes1 = Encoder.objectToBytes(obj);
70
+ const bytes2 = Encoder.objectToBytes(obj);
71
+ expect(bytes1).toEqual(bytes2);
72
+ }), { numRuns });
73
+ });
74
+ });
75
+ });
76
+ //# sourceMappingURL=encoder.fuzz.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoder.fuzz.spec.js","sourceRoot":"","sources":["../../../../tests/fuzz/encoder.fuzz.spec.ts"],"names":[],"mappings":"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"}