@enbox/dwn-sdk-js 0.4.16 → 0.4.18
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/dist/browser.mjs +1 -1
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/generated/precompiled-validators.js +978 -840
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/json-schemas/definitions.json +5 -0
- package/dist/esm/src/core/dwn-constant.js +2 -2
- package/dist/esm/src/core/dwn-error.js +0 -1
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-validation.js +1 -24
- package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization.js +1 -5
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/core/validation-state-reader.js +2 -3
- package/dist/esm/src/core/validation-state-reader.js.map +1 -1
- package/dist/esm/src/handlers/records-collection.js +200 -0
- package/dist/esm/src/handlers/records-collection.js.map +1 -0
- package/dist/esm/src/handlers/records-count.js +26 -195
- package/dist/esm/src/handlers/records-count.js.map +1 -1
- package/dist/esm/src/handlers/records-query.js +19 -373
- package/dist/esm/src/handlers/records-query.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +21 -338
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +8 -26
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +1 -1
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-configure.js +4 -9
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/records-count.js +1 -1
- package/dist/esm/src/interfaces/records-count.js.map +1 -1
- package/dist/esm/src/interfaces/records-query.js +1 -1
- package/dist/esm/src/interfaces/records-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-subscribe.js +3 -1
- package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
- package/dist/esm/src/store/index-level.js +210 -21
- package/dist/esm/src/store/index-level.js.map +1 -1
- package/dist/esm/src/store/message-store-level.js +192 -21
- package/dist/esm/src/store/message-store-level.js.map +1 -1
- package/dist/esm/src/store/storage-controller.js +1 -3
- package/dist/esm/src/store/storage-controller.js.map +1 -1
- package/dist/esm/src/types/protocols-types.js +0 -10
- package/dist/esm/src/types/protocols-types.js.map +1 -1
- package/dist/esm/src/utils/filter.js +35 -1
- package/dist/esm/src/utils/filter.js.map +1 -1
- package/dist/esm/src/utils/grant-key-coverage.js +4 -6
- package/dist/esm/src/utils/grant-key-coverage.js.map +1 -1
- package/dist/esm/src/utils/messages.js +4 -14
- package/dist/esm/src/utils/messages.js.map +1 -1
- package/dist/esm/src/utils/permission-scope.js +3 -9
- package/dist/esm/src/utils/permission-scope.js.map +1 -1
- package/dist/esm/src/utils/record-limit-occupancy.js +73 -202
- package/dist/esm/src/utils/record-limit-occupancy.js.map +1 -1
- package/dist/esm/src/utils/records.js +19 -52
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/tests/core/records-grant-authorization.spec.js +13 -0
- package/dist/esm/tests/core/records-grant-authorization.spec.js.map +1 -1
- package/dist/esm/tests/core/replication-replay-property.spec.js +2 -2
- package/dist/esm/tests/core/replication-replay-property.spec.js.map +1 -1
- package/dist/esm/tests/core/validation-read-closure.spec.js +1 -1
- package/dist/esm/tests/core/validation-read-closure.spec.js.map +1 -1
- package/dist/esm/tests/dwn.spec.js +2 -2
- package/dist/esm/tests/dwn.spec.js.map +1 -1
- package/dist/esm/tests/features/records-delivery.spec.js +2 -5
- package/dist/esm/tests/features/records-delivery.spec.js.map +1 -1
- package/dist/esm/tests/features/records-nested-query-scope.spec.js +149 -70
- package/dist/esm/tests/features/records-nested-query-scope.spec.js.map +1 -1
- package/dist/esm/tests/features/records-record-limit.spec.js +380 -95
- package/dist/esm/tests/features/records-record-limit.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/filter.fuzz.spec.js +19 -4
- package/dist/esm/tests/fuzz/filter.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-count.spec.js +52 -1
- package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +76 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +57 -3
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/store/index-level.spec.js +208 -1
- package/dist/esm/tests/store/index-level.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store-cross-context.spec.js +46 -0
- package/dist/esm/tests/store/message-store-cross-context.spec.js.map +1 -0
- package/dist/esm/tests/store/message-store-level.spec.js +76 -1
- package/dist/esm/tests/store/message-store-level.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store.spec.js +81 -0
- package/dist/esm/tests/store/message-store.spec.js.map +1 -1
- package/dist/esm/tests/utils/filters.spec.js +25 -4
- package/dist/esm/tests/utils/filters.spec.js.map +1 -1
- package/dist/esm/tests/utils/permission-scope.spec.js +4 -0
- package/dist/esm/tests/utils/permission-scope.spec.js.map +1 -1
- package/dist/esm/tests/utils/records.spec.js +12 -0
- package/dist/esm/tests/utils/records.spec.js.map +1 -1
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js +3 -1
- package/dist/esm/tests/validation/json-schemas/records/records-write.spec.js.map +1 -1
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/dwn-constant.d.ts +2 -2
- package/dist/types/src/core/dwn-error.d.ts +0 -1
- package/dist/types/src/core/dwn-error.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization-validation.d.ts +0 -10
- package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
- package/dist/types/src/core/validation-state-reader.d.ts.map +1 -1
- package/dist/types/src/handlers/records-collection.d.ts +32 -0
- package/dist/types/src/handlers/records-collection.d.ts.map +1 -0
- package/dist/types/src/handlers/records-count.d.ts +0 -34
- package/dist/types/src/handlers/records-count.d.ts.map +1 -1
- package/dist/types/src/handlers/records-query.d.ts +0 -61
- package/dist/types/src/handlers/records-query.d.ts.map +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts +1 -37
- package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/records-write.d.ts +3 -0
- package/dist/types/src/handlers/records-write.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/store/index-level.d.ts +61 -0
- package/dist/types/src/store/index-level.d.ts.map +1 -1
- package/dist/types/src/store/message-store-level.d.ts +24 -6
- package/dist/types/src/store/message-store-level.d.ts.map +1 -1
- package/dist/types/src/store/storage-controller.d.ts.map +1 -1
- package/dist/types/src/types/message-store.d.ts +28 -2
- package/dist/types/src/types/message-store.d.ts.map +1 -1
- package/dist/types/src/types/protocols-types.d.ts +7 -24
- package/dist/types/src/types/protocols-types.d.ts.map +1 -1
- package/dist/types/src/types/query-types.d.ts +8 -1
- package/dist/types/src/types/query-types.d.ts.map +1 -1
- package/dist/types/src/types/records-types.d.ts +3 -2
- package/dist/types/src/types/records-types.d.ts.map +1 -1
- package/dist/types/src/utils/filter.d.ts +14 -1
- package/dist/types/src/utils/filter.d.ts.map +1 -1
- package/dist/types/src/utils/grant-key-coverage.d.ts.map +1 -1
- package/dist/types/src/utils/messages.d.ts.map +1 -1
- package/dist/types/src/utils/permission-scope.d.ts +0 -2
- package/dist/types/src/utils/permission-scope.d.ts.map +1 -1
- package/dist/types/src/utils/record-limit-occupancy.d.ts +25 -12
- package/dist/types/src/utils/record-limit-occupancy.d.ts.map +1 -1
- package/dist/types/src/utils/records.d.ts +6 -24
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/tests/features/records-delivery.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-nested-query-scope.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-record-limit.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-count.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-write.spec.d.ts.map +1 -1
- package/dist/types/tests/store/message-store-cross-context.spec.d.ts +2 -0
- package/dist/types/tests/store/message-store-cross-context.spec.d.ts.map +1 -0
- package/dist/types/tests/store/message-store.spec.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/core/dwn-constant.ts +2 -2
- package/src/core/dwn-error.ts +0 -2
- package/src/core/protocol-authorization-validation.ts +1 -33
- package/src/core/protocol-authorization.ts +0 -7
- package/src/core/validation-state-reader.ts +2 -3
- package/src/handlers/records-collection.ts +269 -0
- package/src/handlers/records-count.ts +38 -232
- package/src/handlers/records-query.ts +22 -444
- package/src/handlers/records-subscribe.ts +26 -397
- package/src/handlers/records-write.ts +17 -32
- package/src/index.ts +3 -3
- package/src/interfaces/protocols-configure.ts +4 -13
- package/src/interfaces/records-count.ts +1 -1
- package/src/interfaces/records-query.ts +1 -1
- package/src/interfaces/records-subscribe.ts +5 -2
- package/src/store/index-level.ts +323 -28
- package/src/store/message-store-level.ts +251 -25
- package/src/store/storage-controller.ts +1 -3
- package/src/types/message-store.ts +30 -2
- package/src/types/protocols-types.ts +7 -26
- package/src/types/query-types.ts +10 -2
- package/src/types/records-types.ts +3 -2
- package/src/utils/filter.ts +40 -3
- package/src/utils/grant-key-coverage.ts +4 -7
- package/src/utils/messages.ts +4 -14
- package/src/utils/permission-scope.ts +4 -11
- package/src/utils/record-limit-occupancy.ts +108 -293
- package/src/utils/records.ts +22 -57
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import sinon from 'sinon';
|
|
2
1
|
import { DataStream } from '../../src/utils/data-stream.js';
|
|
2
|
+
import { DateSort } from '../../src/types/records-types.js';
|
|
3
3
|
import { DidKey } from '@enbox/dids';
|
|
4
4
|
import { Dwn } from '../../src/dwn.js';
|
|
5
5
|
import { DwnConstant } from '../../src/core/dwn-constant.js';
|
|
6
6
|
import { DwnErrorCode } from '../../src/core/dwn-error.js';
|
|
7
7
|
import { Jws } from '../../src/utils/jws.js';
|
|
8
|
+
import { Poller } from '../utils/poller.js';
|
|
8
9
|
import { ProtocolsConfigure } from '../../src/interfaces/protocols-configure.js';
|
|
9
10
|
import { RecordsRead } from '../../src/interfaces/records-read.js';
|
|
10
11
|
import { sleep } from '@enbox/common';
|
|
@@ -16,6 +17,7 @@ import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'bun:test'
|
|
|
16
17
|
import { DataStoreLevel, MessageStoreLevel, ResumableTaskStoreLevel } from '../../src/store/level.js';
|
|
17
18
|
export function testRecordsRecordLimit() {
|
|
18
19
|
describe('Records $recordLimit', () => {
|
|
20
|
+
const roomTitlePath = 'room/title';
|
|
19
21
|
let didResolver;
|
|
20
22
|
let messageStore;
|
|
21
23
|
let dataStore;
|
|
@@ -34,7 +36,6 @@ export function testRecordsRecordLimit() {
|
|
|
34
36
|
dwn = await Dwn.create({ didResolver, messageStore, dataStore, eventLog, resumableTaskStore });
|
|
35
37
|
});
|
|
36
38
|
beforeEach(async () => {
|
|
37
|
-
sinon.restore();
|
|
38
39
|
await messageStore.clear();
|
|
39
40
|
await dataStore.clear();
|
|
40
41
|
await resumableTaskStore.clear();
|
|
@@ -58,6 +59,7 @@ export function testRecordsRecordLimit() {
|
|
|
58
59
|
protocol: input.protocol,
|
|
59
60
|
protocolPath: input.protocolPath,
|
|
60
61
|
parentContextId: input.parentContextId,
|
|
62
|
+
published: input.published,
|
|
61
63
|
dateCreated: input.dateCreated,
|
|
62
64
|
messageTimestamp: input.dateCreated,
|
|
63
65
|
});
|
|
@@ -72,7 +74,9 @@ export function testRecordsRecordLimit() {
|
|
|
72
74
|
protocol: input.protocol,
|
|
73
75
|
protocolPath: input.protocolPath,
|
|
74
76
|
...(input.contextId === undefined ? {} : { contextId: input.contextId }),
|
|
77
|
+
...(input.parentId === undefined ? {} : { parentId: input.parentId }),
|
|
75
78
|
},
|
|
79
|
+
dateSort: input.dateSort,
|
|
76
80
|
pagination: input.pagination,
|
|
77
81
|
});
|
|
78
82
|
const reply = await (input.targetDwn ?? dwn).processMessage(input.author.did, recordsQuery.message);
|
|
@@ -89,6 +93,7 @@ export function testRecordsRecordLimit() {
|
|
|
89
93
|
protocol: input.protocol,
|
|
90
94
|
protocolPath: input.protocolPath,
|
|
91
95
|
...(input.contextId === undefined ? {} : { contextId: input.contextId }),
|
|
96
|
+
...(input.parentId === undefined ? {} : { parentId: input.parentId }),
|
|
92
97
|
},
|
|
93
98
|
});
|
|
94
99
|
const reply = await (input.targetDwn ?? dwn).processMessage(input.author.did, recordsCount.message);
|
|
@@ -108,7 +113,10 @@ export function testRecordsRecordLimit() {
|
|
|
108
113
|
filter: {
|
|
109
114
|
protocol: input.protocol,
|
|
110
115
|
protocolPath: input.protocolPath,
|
|
116
|
+
...(input.contextId === undefined ? {} : { contextId: input.contextId }),
|
|
117
|
+
...(input.parentId === undefined ? {} : { parentId: input.parentId }),
|
|
111
118
|
},
|
|
119
|
+
pagination: input.pagination,
|
|
112
120
|
});
|
|
113
121
|
const reply = await (input.targetDwn ?? dwn).processMessage(input.author.did, recordsSubscribe.message, { subscriptionHandler: () => { } });
|
|
114
122
|
expect(reply.status.code).toBe(200);
|
|
@@ -124,7 +132,7 @@ export function testRecordsRecordLimit() {
|
|
|
124
132
|
}
|
|
125
133
|
}
|
|
126
134
|
describe('ProtocolsConfigure validation', () => {
|
|
127
|
-
it('should allow $recordLimit with valid max
|
|
135
|
+
it('should allow $recordLimit with a valid max', async () => {
|
|
128
136
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
129
137
|
const definition = {
|
|
130
138
|
protocol: 'http://example.com/record-limit',
|
|
@@ -132,7 +140,7 @@ export function testRecordsRecordLimit() {
|
|
|
132
140
|
types: { message: {} },
|
|
133
141
|
structure: {
|
|
134
142
|
message: {
|
|
135
|
-
$recordLimit: { max: 5
|
|
143
|
+
$recordLimit: { max: 5 },
|
|
136
144
|
}
|
|
137
145
|
}
|
|
138
146
|
};
|
|
@@ -141,10 +149,7 @@ export function testRecordsRecordLimit() {
|
|
|
141
149
|
definition,
|
|
142
150
|
});
|
|
143
151
|
expect(protocolsConfigure.message.descriptor.definition).toBeDefined();
|
|
144
|
-
expect(protocolsConfigure.message.descriptor.definition.structure.message.$recordLimit).toEqual({
|
|
145
|
-
max: 5,
|
|
146
|
-
strategy: 'reject',
|
|
147
|
-
});
|
|
152
|
+
expect(protocolsConfigure.message.descriptor.definition.structure.message.$recordLimit).toEqual({ max: 5 });
|
|
148
153
|
});
|
|
149
154
|
it('should allow $recordLimit with max of 1', async () => {
|
|
150
155
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
@@ -154,7 +159,7 @@ export function testRecordsRecordLimit() {
|
|
|
154
159
|
types: { profile: {} },
|
|
155
160
|
structure: {
|
|
156
161
|
profile: {
|
|
157
|
-
$recordLimit: { max: 1
|
|
162
|
+
$recordLimit: { max: 1 },
|
|
158
163
|
}
|
|
159
164
|
}
|
|
160
165
|
};
|
|
@@ -162,10 +167,7 @@ export function testRecordsRecordLimit() {
|
|
|
162
167
|
signer: Jws.createSigner(alice),
|
|
163
168
|
definition,
|
|
164
169
|
});
|
|
165
|
-
expect(protocolsConfigure.message.descriptor.definition.structure.profile.$recordLimit).toEqual({
|
|
166
|
-
max: 1,
|
|
167
|
-
strategy: 'reject',
|
|
168
|
-
});
|
|
170
|
+
expect(protocolsConfigure.message.descriptor.definition.structure.profile.$recordLimit).toEqual({ max: 1 });
|
|
169
171
|
});
|
|
170
172
|
it('should reject $recordLimit above the supported max', async () => {
|
|
171
173
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
@@ -175,7 +177,7 @@ export function testRecordsRecordLimit() {
|
|
|
175
177
|
types: { message: {} },
|
|
176
178
|
structure: {
|
|
177
179
|
message: {
|
|
178
|
-
$recordLimit: { max: DwnConstant.maxRecordLimit + 1
|
|
180
|
+
$recordLimit: { max: DwnConstant.maxRecordLimit + 1 },
|
|
179
181
|
}
|
|
180
182
|
}
|
|
181
183
|
};
|
|
@@ -185,27 +187,6 @@ export function testRecordsRecordLimit() {
|
|
|
185
187
|
});
|
|
186
188
|
await expect(promise).rejects.toThrow(DwnErrorCode.ProtocolsConfigureInvalidRecordLimit);
|
|
187
189
|
});
|
|
188
|
-
it('should allow $recordLimit with purgeOldest strategy (schema validation only)', async () => {
|
|
189
|
-
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
190
|
-
const definition = {
|
|
191
|
-
protocol: 'http://example.com/record-limit',
|
|
192
|
-
published: true,
|
|
193
|
-
types: { status: {} },
|
|
194
|
-
structure: {
|
|
195
|
-
status: {
|
|
196
|
-
$recordLimit: { max: 10, strategy: 'purgeOldest' },
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
const protocolsConfigure = await ProtocolsConfigure.create({
|
|
201
|
-
signer: Jws.createSigner(alice),
|
|
202
|
-
definition,
|
|
203
|
-
});
|
|
204
|
-
expect(protocolsConfigure.message.descriptor.definition.structure.status.$recordLimit).toEqual({
|
|
205
|
-
max: 10,
|
|
206
|
-
strategy: 'purgeOldest',
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
190
|
it('should reject $recordLimit with max less than 1', async () => {
|
|
210
191
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
211
192
|
const definition = {
|
|
@@ -214,7 +195,7 @@ export function testRecordsRecordLimit() {
|
|
|
214
195
|
types: { message: {} },
|
|
215
196
|
structure: {
|
|
216
197
|
message: {
|
|
217
|
-
$recordLimit: { max: 0
|
|
198
|
+
$recordLimit: { max: 0 },
|
|
218
199
|
}
|
|
219
200
|
}
|
|
220
201
|
};
|
|
@@ -232,7 +213,7 @@ export function testRecordsRecordLimit() {
|
|
|
232
213
|
types: { message: {} },
|
|
233
214
|
structure: {
|
|
234
215
|
message: {
|
|
235
|
-
$recordLimit: { max: 2.5
|
|
216
|
+
$recordLimit: { max: 2.5 },
|
|
236
217
|
}
|
|
237
218
|
}
|
|
238
219
|
};
|
|
@@ -242,7 +223,7 @@ export function testRecordsRecordLimit() {
|
|
|
242
223
|
});
|
|
243
224
|
await expect(promise).rejects.toThrow('SchemaValidator');
|
|
244
225
|
});
|
|
245
|
-
it('should reject $recordLimit
|
|
226
|
+
it('should reject the removed $recordLimit strategy property', async () => {
|
|
246
227
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
247
228
|
const definition = {
|
|
248
229
|
protocol: 'http://example.com/record-limit',
|
|
@@ -250,25 +231,7 @@ export function testRecordsRecordLimit() {
|
|
|
250
231
|
types: { message: {} },
|
|
251
232
|
structure: {
|
|
252
233
|
message: {
|
|
253
|
-
$recordLimit: { max: 5 },
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
const promise = ProtocolsConfigure.create({
|
|
258
|
-
signer: Jws.createSigner(alice),
|
|
259
|
-
definition,
|
|
260
|
-
});
|
|
261
|
-
await expect(promise).rejects.toThrow('SchemaValidator');
|
|
262
|
-
});
|
|
263
|
-
it('should reject $recordLimit with invalid strategy', async () => {
|
|
264
|
-
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
265
|
-
const definition = {
|
|
266
|
-
protocol: 'http://example.com/record-limit',
|
|
267
|
-
published: true,
|
|
268
|
-
types: { message: {} },
|
|
269
|
-
structure: {
|
|
270
|
-
message: {
|
|
271
|
-
$recordLimit: { max: 5, strategy: 'invalidStrategy' },
|
|
234
|
+
$recordLimit: { max: 5, strategy: 'reject' },
|
|
272
235
|
}
|
|
273
236
|
}
|
|
274
237
|
};
|
|
@@ -290,7 +253,7 @@ export function testRecordsRecordLimit() {
|
|
|
290
253
|
structure: {
|
|
291
254
|
room: {
|
|
292
255
|
message: {
|
|
293
|
-
$recordLimit: { max: 100
|
|
256
|
+
$recordLimit: { max: 100 },
|
|
294
257
|
}
|
|
295
258
|
}
|
|
296
259
|
}
|
|
@@ -300,13 +263,10 @@ export function testRecordsRecordLimit() {
|
|
|
300
263
|
definition,
|
|
301
264
|
});
|
|
302
265
|
const roomRuleSet = protocolsConfigure.message.descriptor.definition.structure.room;
|
|
303
|
-
expect(roomRuleSet.message.$recordLimit).toEqual({
|
|
304
|
-
max: 100,
|
|
305
|
-
strategy: 'reject',
|
|
306
|
-
});
|
|
266
|
+
expect(roomRuleSet.message.$recordLimit).toEqual({ max: 100 });
|
|
307
267
|
});
|
|
308
268
|
});
|
|
309
|
-
describe('read-time occupancy projection
|
|
269
|
+
describe('read-time occupancy projection', () => {
|
|
310
270
|
it('should admit candidates and project Query, Read, and Count to top-ranked occupants', async () => {
|
|
311
271
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
312
272
|
const protocolDefinition = {
|
|
@@ -315,7 +275,7 @@ export function testRecordsRecordLimit() {
|
|
|
315
275
|
types: { blob: {} },
|
|
316
276
|
structure: {
|
|
317
277
|
blob: {
|
|
318
|
-
$recordLimit: { max: 2
|
|
278
|
+
$recordLimit: { max: 2 },
|
|
319
279
|
}
|
|
320
280
|
}
|
|
321
281
|
};
|
|
@@ -362,7 +322,7 @@ export function testRecordsRecordLimit() {
|
|
|
362
322
|
types: { profile: {} },
|
|
363
323
|
structure: {
|
|
364
324
|
profile: {
|
|
365
|
-
$recordLimit: { max: 1
|
|
325
|
+
$recordLimit: { max: 1 },
|
|
366
326
|
}
|
|
367
327
|
}
|
|
368
328
|
};
|
|
@@ -406,7 +366,7 @@ export function testRecordsRecordLimit() {
|
|
|
406
366
|
structure: {
|
|
407
367
|
room: {
|
|
408
368
|
message: {
|
|
409
|
-
$recordLimit: { max: 2
|
|
369
|
+
$recordLimit: { max: 2 },
|
|
410
370
|
}
|
|
411
371
|
}
|
|
412
372
|
}
|
|
@@ -489,6 +449,30 @@ export function testRecordsRecordLimit() {
|
|
|
489
449
|
room2Messages[0].message.recordId,
|
|
490
450
|
room2Messages[1].message.recordId,
|
|
491
451
|
]);
|
|
452
|
+
expect((await queryProtocolRecordIds({
|
|
453
|
+
author: alice,
|
|
454
|
+
protocol,
|
|
455
|
+
protocolPath: 'room/message',
|
|
456
|
+
contextId: room1Messages[0].message.contextId,
|
|
457
|
+
})).recordIds).toEqual([room1Messages[0].message.recordId]);
|
|
458
|
+
expect(await countProtocolRecords({
|
|
459
|
+
author: alice,
|
|
460
|
+
protocol,
|
|
461
|
+
protocolPath: 'room/message',
|
|
462
|
+
contextId: room1Messages[0].message.contextId,
|
|
463
|
+
})).toBe(1);
|
|
464
|
+
expect((await queryProtocolRecordIds({
|
|
465
|
+
author: alice,
|
|
466
|
+
protocol,
|
|
467
|
+
protocolPath: 'room/message',
|
|
468
|
+
contextId: room1Messages[2].message.contextId,
|
|
469
|
+
})).recordIds).toEqual([]);
|
|
470
|
+
expect(await countProtocolRecords({
|
|
471
|
+
author: alice,
|
|
472
|
+
protocol,
|
|
473
|
+
protocolPath: 'room/message',
|
|
474
|
+
contextId: room1Messages[2].message.contextId,
|
|
475
|
+
})).toBe(0);
|
|
492
476
|
const broadQuery = await TestDataGenerator.generateRecordsQuery({
|
|
493
477
|
author: alice,
|
|
494
478
|
filter: {
|
|
@@ -500,6 +484,331 @@ export function testRecordsRecordLimit() {
|
|
|
500
484
|
expect(broadReply.status.code).toBe(400);
|
|
501
485
|
expect(broadReply.status.detail).toContain(DwnErrorCode.RecordsQueryNestedProtocolPathContextIdInvalid);
|
|
502
486
|
});
|
|
487
|
+
it('should project selected direct-parent groups independently in one request', async () => {
|
|
488
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
489
|
+
const protocolDefinition = {
|
|
490
|
+
protocol: `http://record-limit-${TestDataGenerator.randomString(12)}.xyz`,
|
|
491
|
+
published: true,
|
|
492
|
+
types: {
|
|
493
|
+
room: {},
|
|
494
|
+
title: {},
|
|
495
|
+
},
|
|
496
|
+
structure: {
|
|
497
|
+
room: {
|
|
498
|
+
title: {
|
|
499
|
+
$recordLimit: { max: 1 },
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
};
|
|
504
|
+
const protocol = protocolDefinition.protocol;
|
|
505
|
+
await installProtocol({ author: alice, definition: protocolDefinition });
|
|
506
|
+
const room1 = await writeProtocolRecord({
|
|
507
|
+
author: alice,
|
|
508
|
+
protocol,
|
|
509
|
+
protocolPath: 'room',
|
|
510
|
+
dateCreated: '2025-01-01T00:00:00.000000Z',
|
|
511
|
+
});
|
|
512
|
+
const room2 = await writeProtocolRecord({
|
|
513
|
+
author: alice,
|
|
514
|
+
protocol,
|
|
515
|
+
protocolPath: 'room',
|
|
516
|
+
dateCreated: '2025-01-02T00:00:00.000000Z',
|
|
517
|
+
});
|
|
518
|
+
const room1Title = await writeProtocolRecord({
|
|
519
|
+
author: alice,
|
|
520
|
+
protocol,
|
|
521
|
+
protocolPath: roomTitlePath,
|
|
522
|
+
parentContextId: room1.message.contextId,
|
|
523
|
+
dateCreated: '2025-02-01T00:00:00.000000Z',
|
|
524
|
+
});
|
|
525
|
+
const room2Title = await writeProtocolRecord({
|
|
526
|
+
author: alice,
|
|
527
|
+
protocol,
|
|
528
|
+
protocolPath: roomTitlePath,
|
|
529
|
+
parentContextId: room2.message.contextId,
|
|
530
|
+
dateCreated: '2025-02-02T00:00:00.000000Z',
|
|
531
|
+
});
|
|
532
|
+
await writeProtocolRecord({
|
|
533
|
+
author: alice,
|
|
534
|
+
protocol,
|
|
535
|
+
protocolPath: roomTitlePath,
|
|
536
|
+
parentContextId: room1.message.contextId,
|
|
537
|
+
dateCreated: '2025-02-03T00:00:00.000000Z',
|
|
538
|
+
});
|
|
539
|
+
await writeProtocolRecord({
|
|
540
|
+
author: alice,
|
|
541
|
+
protocol,
|
|
542
|
+
protocolPath: roomTitlePath,
|
|
543
|
+
parentContextId: room2.message.contextId,
|
|
544
|
+
dateCreated: '2025-02-04T00:00:00.000000Z',
|
|
545
|
+
});
|
|
546
|
+
const parentIds = [room1.message.recordId, room2.message.recordId];
|
|
547
|
+
const expectedRecordIds = [room1Title.message.recordId, room2Title.message.recordId];
|
|
548
|
+
const queryInput = {
|
|
549
|
+
author: alice,
|
|
550
|
+
protocol,
|
|
551
|
+
protocolPath: roomTitlePath,
|
|
552
|
+
parentId: parentIds,
|
|
553
|
+
};
|
|
554
|
+
expect((await queryProtocolRecordIds(queryInput)).recordIds).toEqual(expectedRecordIds);
|
|
555
|
+
expect(await countProtocolRecords(queryInput)).toBe(expectedRecordIds.length);
|
|
556
|
+
expect(await subscribeSnapshotRecordIds(queryInput)).toEqual(expectedRecordIds);
|
|
557
|
+
expect(await subscribeSnapshotRecordIds({
|
|
558
|
+
author: alice,
|
|
559
|
+
protocol,
|
|
560
|
+
protocolPath: roomTitlePath,
|
|
561
|
+
pagination: { limit: 2 },
|
|
562
|
+
})).toEqual(expectedRecordIds);
|
|
563
|
+
expect((await queryProtocolRecordIds({
|
|
564
|
+
...queryInput,
|
|
565
|
+
parentId: room2.message.recordId,
|
|
566
|
+
})).recordIds).toEqual([room2Title.message.recordId]);
|
|
567
|
+
const scopedInput = {
|
|
568
|
+
...queryInput,
|
|
569
|
+
contextId: room1.message.contextId,
|
|
570
|
+
};
|
|
571
|
+
expect((await queryProtocolRecordIds(scopedInput)).recordIds).toEqual([room1Title.message.recordId]);
|
|
572
|
+
expect(await countProtocolRecords(scopedInput)).toBe(1);
|
|
573
|
+
expect(await subscribeSnapshotRecordIds(scopedInput)).toEqual([room1Title.message.recordId]);
|
|
574
|
+
});
|
|
575
|
+
it('should reject empty and duplicate parentId arrays', async () => {
|
|
576
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
577
|
+
const filter = {
|
|
578
|
+
protocol: 'http://record-limit-parent-filter.xyz',
|
|
579
|
+
protocolPath: roomTitlePath,
|
|
580
|
+
parentId: [],
|
|
581
|
+
};
|
|
582
|
+
await expect(TestDataGenerator.generateRecordsQuery({ author: alice, filter })).rejects.toThrow('SchemaValidatorFailure');
|
|
583
|
+
await expect(TestDataGenerator.generateRecordsCount({ author: alice, filter })).rejects.toThrow('SchemaValidatorFailure');
|
|
584
|
+
await expect(TestDataGenerator.generateRecordsSubscribe({ author: alice, filter })).rejects.toThrow('SchemaValidatorFailure');
|
|
585
|
+
await expect(TestDataGenerator.generateRecordsQuery({
|
|
586
|
+
author: alice,
|
|
587
|
+
filter: { ...filter, parentId: ['same-parent', 'same-parent'] },
|
|
588
|
+
})).rejects.toThrow('SchemaValidatorFailure');
|
|
589
|
+
await expect(TestDataGenerator.generateRecordsCount({
|
|
590
|
+
author: alice,
|
|
591
|
+
filter: { ...filter, parentId: '' },
|
|
592
|
+
})).rejects.toThrow('SchemaValidatorFailure');
|
|
593
|
+
await expect(TestDataGenerator.generateRecordsSubscribe({
|
|
594
|
+
author: alice,
|
|
595
|
+
filter: { ...filter, parentId: [''] },
|
|
596
|
+
})).rejects.toThrow('SchemaValidatorFailure');
|
|
597
|
+
});
|
|
598
|
+
it('should project ancestor queries independently across parent contexts', async () => {
|
|
599
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
600
|
+
const protocolDefinition = {
|
|
601
|
+
protocol: `http://record-limit-${TestDataGenerator.randomString(12)}.xyz`,
|
|
602
|
+
published: true,
|
|
603
|
+
types: {
|
|
604
|
+
channel: {},
|
|
605
|
+
community: {},
|
|
606
|
+
message: {},
|
|
607
|
+
},
|
|
608
|
+
structure: {
|
|
609
|
+
community: {
|
|
610
|
+
channel: {
|
|
611
|
+
message: {
|
|
612
|
+
$recordLimit: { max: 2 },
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
};
|
|
618
|
+
const protocol = protocolDefinition.protocol;
|
|
619
|
+
await installProtocol({ author: alice, definition: protocolDefinition });
|
|
620
|
+
const community = await writeProtocolRecord({
|
|
621
|
+
author: alice,
|
|
622
|
+
protocol,
|
|
623
|
+
protocolPath: 'community',
|
|
624
|
+
dateCreated: '2025-01-01T00:00:00.000000Z',
|
|
625
|
+
});
|
|
626
|
+
const channel1 = await writeProtocolRecord({
|
|
627
|
+
author: alice,
|
|
628
|
+
protocol,
|
|
629
|
+
protocolPath: 'community/channel',
|
|
630
|
+
parentContextId: community.message.contextId,
|
|
631
|
+
dateCreated: '2025-01-02T00:00:00.000000Z',
|
|
632
|
+
});
|
|
633
|
+
const channel2 = await writeProtocolRecord({
|
|
634
|
+
author: alice,
|
|
635
|
+
protocol,
|
|
636
|
+
protocolPath: 'community/channel',
|
|
637
|
+
parentContextId: community.message.contextId,
|
|
638
|
+
dateCreated: '2025-01-03T00:00:00.000000Z',
|
|
639
|
+
});
|
|
640
|
+
const { cursor: cursorBeforeMessages } = await eventLog.read(alice.did);
|
|
641
|
+
// Creation times are interleaved across channels so pagination proves
|
|
642
|
+
// that projection happens per direct parent before global ordering.
|
|
643
|
+
// Channel 2 arrives newest-first to prove occupancy ignores arrival order.
|
|
644
|
+
const channel1Messages = [
|
|
645
|
+
await writeProtocolRecord({
|
|
646
|
+
author: alice,
|
|
647
|
+
protocol,
|
|
648
|
+
protocolPath: 'community/channel/message',
|
|
649
|
+
parentContextId: channel1.message.contextId,
|
|
650
|
+
dateCreated: '2025-02-01T00:00:00.000000Z',
|
|
651
|
+
}),
|
|
652
|
+
await writeProtocolRecord({
|
|
653
|
+
author: alice,
|
|
654
|
+
protocol,
|
|
655
|
+
protocolPath: 'community/channel/message',
|
|
656
|
+
parentContextId: channel1.message.contextId,
|
|
657
|
+
published: true,
|
|
658
|
+
dateCreated: '2025-02-04T00:00:00.000000Z',
|
|
659
|
+
}),
|
|
660
|
+
await writeProtocolRecord({
|
|
661
|
+
author: alice,
|
|
662
|
+
protocol,
|
|
663
|
+
protocolPath: 'community/channel/message',
|
|
664
|
+
parentContextId: channel1.message.contextId,
|
|
665
|
+
published: true,
|
|
666
|
+
dateCreated: '2025-02-06T00:00:00.000000Z',
|
|
667
|
+
}),
|
|
668
|
+
];
|
|
669
|
+
const channel2Tie1 = await writeProtocolRecord({
|
|
670
|
+
author: alice,
|
|
671
|
+
protocol,
|
|
672
|
+
protocolPath: 'community/channel/message',
|
|
673
|
+
parentContextId: channel2.message.contextId,
|
|
674
|
+
published: true,
|
|
675
|
+
dateCreated: '2025-02-03T00:00:00.000000Z',
|
|
676
|
+
});
|
|
677
|
+
const channel2Tie2 = await writeProtocolRecord({
|
|
678
|
+
author: alice,
|
|
679
|
+
protocol,
|
|
680
|
+
protocolPath: 'community/channel/message',
|
|
681
|
+
parentContextId: channel2.message.contextId,
|
|
682
|
+
published: true,
|
|
683
|
+
dateCreated: '2025-02-03T00:00:00.000000Z',
|
|
684
|
+
});
|
|
685
|
+
const channel2Oldest = await writeProtocolRecord({
|
|
686
|
+
author: alice,
|
|
687
|
+
protocol,
|
|
688
|
+
protocolPath: 'community/channel/message',
|
|
689
|
+
parentContextId: channel2.message.contextId,
|
|
690
|
+
published: true,
|
|
691
|
+
dateCreated: '2025-02-02T00:00:00.000000Z',
|
|
692
|
+
});
|
|
693
|
+
const channel2Messages = [channel2Oldest, channel2Tie1, channel2Tie2];
|
|
694
|
+
const channel2BoundaryOccupant = channel2Messages[1].message.recordId < channel2Messages[2].message.recordId
|
|
695
|
+
? channel2Messages[1]
|
|
696
|
+
: channel2Messages[2];
|
|
697
|
+
const expectedRecordIds = [
|
|
698
|
+
channel1Messages[0].message.recordId,
|
|
699
|
+
channel2Messages[0].message.recordId,
|
|
700
|
+
channel2BoundaryOccupant.message.recordId,
|
|
701
|
+
channel1Messages[1].message.recordId,
|
|
702
|
+
];
|
|
703
|
+
const queryInput = {
|
|
704
|
+
author: alice,
|
|
705
|
+
protocol,
|
|
706
|
+
protocolPath: 'community/channel/message',
|
|
707
|
+
contextId: community.message.contextId,
|
|
708
|
+
};
|
|
709
|
+
expect((await queryProtocolRecordIds(queryInput)).recordIds).toEqual(expectedRecordIds);
|
|
710
|
+
expect((await queryProtocolRecordIds({
|
|
711
|
+
...queryInput,
|
|
712
|
+
dateSort: DateSort.CreatedDescending,
|
|
713
|
+
})).recordIds).toEqual([...expectedRecordIds].reverse());
|
|
714
|
+
expect(await countProtocolRecords(queryInput)).toBe(expectedRecordIds.length);
|
|
715
|
+
expect(await subscribeSnapshotRecordIds(queryInput)).toEqual(expectedRecordIds);
|
|
716
|
+
const page1 = await queryProtocolRecordIds({ ...queryInput, pagination: { limit: 2 } });
|
|
717
|
+
expect(page1.recordIds).toEqual(expectedRecordIds.slice(0, 2));
|
|
718
|
+
expect(page1.cursor).toBeDefined();
|
|
719
|
+
const page2 = await queryProtocolRecordIds({
|
|
720
|
+
...queryInput,
|
|
721
|
+
pagination: { limit: 2, cursor: page1.cursor },
|
|
722
|
+
});
|
|
723
|
+
expect(page2.recordIds).toEqual(expectedRecordIds.slice(2));
|
|
724
|
+
expect(page2.cursor).toBeUndefined();
|
|
725
|
+
const descendingPage1 = await queryProtocolRecordIds({
|
|
726
|
+
...queryInput,
|
|
727
|
+
dateSort: DateSort.CreatedDescending,
|
|
728
|
+
pagination: { limit: 2 },
|
|
729
|
+
});
|
|
730
|
+
expect(descendingPage1.recordIds).toEqual([...expectedRecordIds].reverse().slice(0, 2));
|
|
731
|
+
expect(descendingPage1.cursor).toBeDefined();
|
|
732
|
+
const descendingPage2 = await queryProtocolRecordIds({
|
|
733
|
+
...queryInput,
|
|
734
|
+
dateSort: DateSort.CreatedDescending,
|
|
735
|
+
pagination: { limit: 2, cursor: descendingPage1.cursor },
|
|
736
|
+
});
|
|
737
|
+
expect(descendingPage2.recordIds).toEqual([...expectedRecordIds].reverse().slice(2));
|
|
738
|
+
expect(descendingPage2.cursor).toBeUndefined();
|
|
739
|
+
// Occupancy is ranked before requester visibility. The unpublished
|
|
740
|
+
// first channel-1 occupant still consumes a slot, so the later
|
|
741
|
+
// published over-limit candidate must remain hidden anonymously.
|
|
742
|
+
const publishedFilter = {
|
|
743
|
+
contextId: community.message.contextId,
|
|
744
|
+
protocol,
|
|
745
|
+
protocolPath: 'community/channel/message',
|
|
746
|
+
published: true,
|
|
747
|
+
};
|
|
748
|
+
const anonymousQuery = await TestDataGenerator.generateRecordsQuery({
|
|
749
|
+
anonymous: true,
|
|
750
|
+
filter: publishedFilter,
|
|
751
|
+
});
|
|
752
|
+
const anonymousReply = await dwn.processMessage(alice.did, anonymousQuery.message);
|
|
753
|
+
expect(anonymousReply.status.code).toBe(200);
|
|
754
|
+
expect(anonymousReply.entries?.map((entry) => entry.recordId)).toEqual([
|
|
755
|
+
channel2Messages[0].message.recordId,
|
|
756
|
+
channel2BoundaryOccupant.message.recordId,
|
|
757
|
+
channel1Messages[1].message.recordId,
|
|
758
|
+
]);
|
|
759
|
+
const anonymousCount = await TestDataGenerator.generateRecordsCount({
|
|
760
|
+
anonymous: true,
|
|
761
|
+
filter: publishedFilter,
|
|
762
|
+
});
|
|
763
|
+
const anonymousCountReply = await dwn.processMessage(alice.did, anonymousCount.message);
|
|
764
|
+
expect(anonymousCountReply.status.code).toBe(200);
|
|
765
|
+
expect(anonymousCountReply.count).toBe(3);
|
|
766
|
+
const replayedRecordIds = [];
|
|
767
|
+
const cursorSubscribe = await TestDataGenerator.generateRecordsSubscribe({
|
|
768
|
+
author: alice,
|
|
769
|
+
cursor: cursorBeforeMessages,
|
|
770
|
+
filter: {
|
|
771
|
+
contextId: community.message.contextId,
|
|
772
|
+
protocol,
|
|
773
|
+
protocolPath: 'community/channel/message',
|
|
774
|
+
},
|
|
775
|
+
});
|
|
776
|
+
const cursorSubscribeReply = await dwn.processMessage(alice.did, cursorSubscribe.message, {
|
|
777
|
+
subscriptionHandler: (subscriptionMessage) => {
|
|
778
|
+
if (subscriptionMessage.type === 'event' && subscriptionMessage.event.message.descriptor.method === 'Write') {
|
|
779
|
+
replayedRecordIds.push(subscriptionMessage.event.message.recordId);
|
|
780
|
+
}
|
|
781
|
+
},
|
|
782
|
+
});
|
|
783
|
+
expect(cursorSubscribeReply.status.code).toBe(200);
|
|
784
|
+
await Poller.pollUntilSuccessOrTimeout(async () => {
|
|
785
|
+
expect(replayedRecordIds).toHaveLength(expectedRecordIds.length);
|
|
786
|
+
});
|
|
787
|
+
expect([...replayedRecordIds].sort()).toEqual([...expectedRecordIds].sort());
|
|
788
|
+
await cursorSubscribeReply.subscription?.close();
|
|
789
|
+
const deleteChannel1Occupant = await TestDataGenerator.generateRecordsDelete({
|
|
790
|
+
author: alice,
|
|
791
|
+
recordId: channel1Messages[0].message.recordId,
|
|
792
|
+
});
|
|
793
|
+
const deleteReply = await dwn.processMessage(alice.did, deleteChannel1Occupant.message);
|
|
794
|
+
expect(deleteReply.status.code).toBe(202);
|
|
795
|
+
const expectedAfterPromotion = [
|
|
796
|
+
channel2Messages[0].message.recordId,
|
|
797
|
+
channel2BoundaryOccupant.message.recordId,
|
|
798
|
+
channel1Messages[1].message.recordId,
|
|
799
|
+
channel1Messages[2].message.recordId,
|
|
800
|
+
];
|
|
801
|
+
expect((await queryProtocolRecordIds(queryInput)).recordIds).toEqual(expectedAfterPromotion);
|
|
802
|
+
expect((await queryProtocolRecordIds({
|
|
803
|
+
author: alice,
|
|
804
|
+
protocol,
|
|
805
|
+
protocolPath: 'community/channel/message',
|
|
806
|
+
contextId: channel2.message.contextId,
|
|
807
|
+
})).recordIds).toEqual([
|
|
808
|
+
channel2Messages[0].message.recordId,
|
|
809
|
+
channel2BoundaryOccupant.message.recordId,
|
|
810
|
+
]);
|
|
811
|
+
});
|
|
503
812
|
it('should paginate over the projected occupant set for max:N scopes', async () => {
|
|
504
813
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
505
814
|
const protocolDefinition = {
|
|
@@ -508,7 +817,7 @@ export function testRecordsRecordLimit() {
|
|
|
508
817
|
types: { item: {} },
|
|
509
818
|
structure: {
|
|
510
819
|
item: {
|
|
511
|
-
$recordLimit: { max: 3
|
|
820
|
+
$recordLimit: { max: 3 },
|
|
512
821
|
}
|
|
513
822
|
}
|
|
514
823
|
};
|
|
@@ -551,7 +860,7 @@ export function testRecordsRecordLimit() {
|
|
|
551
860
|
types: { status: {} },
|
|
552
861
|
structure: {
|
|
553
862
|
status: {
|
|
554
|
-
$recordLimit: { max: 1
|
|
863
|
+
$recordLimit: { max: 1 },
|
|
555
864
|
}
|
|
556
865
|
}
|
|
557
866
|
};
|
|
@@ -633,10 +942,10 @@ export function testRecordsRecordLimit() {
|
|
|
633
942
|
},
|
|
634
943
|
structure: {
|
|
635
944
|
note: {
|
|
636
|
-
$recordLimit: { max: 2
|
|
945
|
+
$recordLimit: { max: 2 },
|
|
637
946
|
},
|
|
638
947
|
profile: {
|
|
639
|
-
$recordLimit: { max: 1
|
|
948
|
+
$recordLimit: { max: 1 },
|
|
640
949
|
}
|
|
641
950
|
}
|
|
642
951
|
};
|
|
@@ -712,7 +1021,7 @@ export function testRecordsRecordLimit() {
|
|
|
712
1021
|
types: { blob: {} },
|
|
713
1022
|
structure: {
|
|
714
1023
|
blob: {
|
|
715
|
-
$recordLimit: { max: 1
|
|
1024
|
+
$recordLimit: { max: 1 },
|
|
716
1025
|
}
|
|
717
1026
|
}
|
|
718
1027
|
};
|
|
@@ -734,30 +1043,6 @@ export function testRecordsRecordLimit() {
|
|
|
734
1043
|
record.message.recordId,
|
|
735
1044
|
]);
|
|
736
1045
|
});
|
|
737
|
-
it('should reject purgeOldest strategy at write time with not-implemented error', async () => {
|
|
738
|
-
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
739
|
-
const protocolDefinition = {
|
|
740
|
-
protocol: `http://record-limit-${TestDataGenerator.randomString(12)}.xyz`,
|
|
741
|
-
published: true,
|
|
742
|
-
types: { blob: {} },
|
|
743
|
-
structure: {
|
|
744
|
-
blob: {
|
|
745
|
-
$recordLimit: { max: 1, strategy: 'purgeOldest' },
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
};
|
|
749
|
-
const protocol = protocolDefinition.protocol;
|
|
750
|
-
await installProtocol({ author: alice, definition: protocolDefinition });
|
|
751
|
-
const record = await TestDataGenerator.generateRecordsWrite({
|
|
752
|
-
author: alice,
|
|
753
|
-
recipient: alice.did,
|
|
754
|
-
protocol,
|
|
755
|
-
protocolPath: 'blob',
|
|
756
|
-
});
|
|
757
|
-
const reply = await dwn.processMessage(alice.did, record.message, { dataStream: record.dataStream });
|
|
758
|
-
expect(reply.status.code).toBe(400);
|
|
759
|
-
expect(reply.status.detail).toContain(DwnErrorCode.ProtocolAuthorizationRecordLimitStrategyNotImplemented);
|
|
760
|
-
});
|
|
761
1046
|
});
|
|
762
1047
|
});
|
|
763
1048
|
}
|