@enbox/dwn-sdk-js 0.3.9 → 0.4.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 (71) hide show
  1. package/dist/browser.mjs +11 -11
  2. package/dist/browser.mjs.map +4 -4
  3. package/dist/esm/generated/precompiled-validators.js +175 -512
  4. package/dist/esm/generated/precompiled-validators.js.map +1 -1
  5. package/dist/esm/src/core/dwn-error.js +1 -3
  6. package/dist/esm/src/core/dwn-error.js.map +1 -1
  7. package/dist/esm/src/core/messages-grant-authorization.js +1 -17
  8. package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
  9. package/dist/esm/src/core/protocol-authorization-validation.js +1 -1
  10. package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
  11. package/dist/esm/src/core/replication-apply.js +200 -0
  12. package/dist/esm/src/core/replication-apply.js.map +1 -0
  13. package/dist/esm/src/dwn.js +212 -0
  14. package/dist/esm/src/dwn.js.map +1 -1
  15. package/dist/esm/src/handlers/messages-sync.js +66 -369
  16. package/dist/esm/src/handlers/messages-sync.js.map +1 -1
  17. package/dist/esm/src/index.js +1 -1
  18. package/dist/esm/src/index.js.map +1 -1
  19. package/dist/esm/src/interfaces/messages-sync.js +0 -11
  20. package/dist/esm/src/interfaces/messages-sync.js.map +1 -1
  21. package/dist/esm/tests/core/replication-apply.spec.js +220 -0
  22. package/dist/esm/tests/core/replication-apply.spec.js.map +1 -0
  23. package/dist/esm/tests/dwn.spec.js +139 -2
  24. package/dist/esm/tests/dwn.spec.js.map +1 -1
  25. package/dist/esm/tests/handlers/messages-sync.spec.js +1 -684
  26. package/dist/esm/tests/handlers/messages-sync.spec.js.map +1 -1
  27. package/dist/esm/tests/handlers/records-write.spec.js +2 -2
  28. package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
  29. package/dist/esm/tests/test-suite.js +0 -2
  30. package/dist/esm/tests/test-suite.js.map +1 -1
  31. package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
  32. package/dist/types/src/core/dwn-error.d.ts +1 -3
  33. package/dist/types/src/core/dwn-error.d.ts.map +1 -1
  34. package/dist/types/src/core/messages-grant-authorization.d.ts +0 -1
  35. package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
  36. package/dist/types/src/core/replication-apply.d.ts +93 -0
  37. package/dist/types/src/core/replication-apply.d.ts.map +1 -0
  38. package/dist/types/src/dwn.d.ts +22 -1
  39. package/dist/types/src/dwn.d.ts.map +1 -1
  40. package/dist/types/src/handlers/messages-sync.d.ts +10 -54
  41. package/dist/types/src/handlers/messages-sync.d.ts.map +1 -1
  42. package/dist/types/src/index.d.ts +3 -3
  43. package/dist/types/src/index.d.ts.map +1 -1
  44. package/dist/types/src/interfaces/messages-sync.d.ts +0 -3
  45. package/dist/types/src/interfaces/messages-sync.d.ts.map +1 -1
  46. package/dist/types/src/types/messages-types.d.ts +0 -18
  47. package/dist/types/src/types/messages-types.d.ts.map +1 -1
  48. package/dist/types/tests/core/replication-apply.spec.d.ts +2 -0
  49. package/dist/types/tests/core/replication-apply.spec.d.ts.map +1 -0
  50. package/dist/types/tests/dwn.spec.d.ts.map +1 -1
  51. package/dist/types/tests/handlers/messages-sync.spec.d.ts.map +1 -1
  52. package/dist/types/tests/test-suite.d.ts.map +1 -1
  53. package/package.json +1 -1
  54. package/src/core/dwn-error.ts +1 -3
  55. package/src/core/messages-grant-authorization.ts +1 -31
  56. package/src/core/protocol-authorization-validation.ts +2 -2
  57. package/src/core/replication-apply.ts +272 -0
  58. package/src/dwn.ts +296 -2
  59. package/src/handlers/messages-sync.ts +92 -585
  60. package/src/index.ts +3 -4
  61. package/src/interfaces/messages-sync.ts +8 -25
  62. package/src/types/messages-types.ts +0 -20
  63. package/dist/esm/src/sync/records-projection.js +0 -228
  64. package/dist/esm/src/sync/records-projection.js.map +0 -1
  65. package/dist/esm/tests/sync/records-projection.spec.js +0 -245
  66. package/dist/esm/tests/sync/records-projection.spec.js.map +0 -1
  67. package/dist/types/src/sync/records-projection.d.ts +0 -98
  68. package/dist/types/src/sync/records-projection.d.ts.map +0 -1
  69. package/dist/types/tests/sync/records-projection.spec.d.ts +0 -2
  70. package/dist/types/tests/sync/records-projection.spec.d.ts.map +0 -1
  71. package/src/sync/records-projection.ts +0 -328
package/src/index.ts CHANGED
@@ -2,7 +2,9 @@
2
2
  export type { DwnConfig } from './dwn.js';
3
3
  export type { EventListener, EventLog, EventLogEntry, EventLogReadOptions, EventLogReadResult, EventLogSubscribeOptions, EventSubscription, MessageEvent, ProgressGapInfo, ProgressGapReason, ProgressToken, SubscriptionEose, SubscriptionError, SubscriptionEvent, SubscriptionListener, SubscriptionMessage, SubscriptionReply } from './types/subscriptions.js';
4
4
  export type { AuthorizationModel, Descriptor, DelegatedGrantRecordsWriteMessage, GenericMessage, GenericMessageReply, GenericSignaturePayload, MessageSort, MessageSubscription, Pagination, QueryResultEntry, Status } from './types/message-types.js';
5
- export type { MessagesFilter, MessagesReadMessage, MessagesReadReply, MessagesReadReplyEntry, MessagesReadDescriptor, MessagesSubscribeDescriptor, MessagesSubscribeMessage, MessagesSubscribeReply, MessagesSubscribeMessageOptions, MessagesSyncAction, MessagesSyncDependencyClass, MessagesSyncDependencyEntry, MessagesSyncDescriptor, MessagesSyncDiffEntry, MessagesSyncMessage, MessagesSyncReply } from './types/messages-types.js';
5
+ export type { DependencyRef, ReplicationApplyOptions, ReplicationApplyResult, ReplicationApplyResultContext } from './core/replication-apply.js';
6
+ export { replicationApplyResultFromReply } from './core/replication-apply.js';
7
+ export type { MessagesFilter, MessagesReadMessage, MessagesReadReply, MessagesReadReplyEntry, MessagesReadDescriptor, MessagesSubscribeDescriptor, MessagesSubscribeMessage, MessagesSubscribeReply, MessagesSubscribeMessageOptions, MessagesSyncAction, MessagesSyncDescriptor, MessagesSyncDiffEntry, MessagesSyncMessage, MessagesSyncReply } from './types/messages-types.js';
6
8
  export type { GT, LT, Filter, FilterValue, KeyValues, EqualFilter, OneOfFilter, RangeFilter, RangeCriterion, PaginationCursor, QueryOptions, RangeValue, StartsWithFilter } from './types/query-types.js';
7
9
  export type { ProtocolsConfigureDescriptor, ProtocolDefinition, ProtocolTypes, ProtocolRuleSet, ProtocolsQueryFilter, ProtocolsConfigureMessage, ProtocolsQueryMessage, ProtocolsQueryReply, ProtocolActionRule, ProtocolDeliveryStrategy, ProtocolPathEncryption, ProtocolsQueryDescriptor, ProtocolRecordLimitDefinition, ProtocolSizeDefinition, ProtocolTagsDefinition, ProtocolTagSchema, ProtocolType, ProtocolUses } from './types/protocols-types.js';
8
10
  export { ProtocolRecordLimitStrategy } from './types/protocols-types.js';
@@ -103,9 +105,6 @@ export { SMTStoreLevel } from './smt/smt-store-level.js';
103
105
  export { SMTStoreMemory } from './smt/smt-store-memory.js';
104
106
  export type { Hash, SMTNode, SMTInternalNode, SMTLeafNode, SMTProof, SMTDiffResult, SMTNodeStore } from './types/smt-types.js';
105
107
  export { hashChildren, hashEquals, hashKey, hashLeaf, hashToHex, hexToHash, getBit, initDefaultHashes, getDefaultHashes, SMT_DEPTH, ZERO_HASH } from './smt/smt-utils.js';
106
- export { RECORDS_PROJECTION_ROOT_VERSION, RecordsProjection } from './sync/records-projection.js';
107
- export type { NormalizedRecordsProjectionScope, RecordsProjectionInput, RecordsProjectionScope, RecordsProjectionSnapshot, RecordsProjectionTreeInput } from './sync/records-projection.js';
108
-
109
108
  // test library exports
110
109
  export type { GenerateFromRecordsWriteInput, GenerateFromRecordsWriteOut, GenerateGrantCreateInput, GenerateGrantCreateOutput, GenerateMessagesReadInput, GenerateMessagesReadOutput, GenerateMessagesSubscribeInput, GenerateMessagesSubscribeOutput, GenerateProtocolsConfigureInput, GenerateProtocolsConfigureOutput, GenerateProtocolsQueryInput, GenerateProtocolsQueryOutput, GenerateRecordsCountInput, GenerateRecordsCountOutput, GenerateRecordsDeleteInput, GenerateRecordsDeleteOutput, GenerateRecordsQueryInput, GenerateRecordsQueryOutput, GenerateRecordsSubscribeInput, GenerateRecordsSubscribeOutput, GenerateRecordsWriteInput, GenerateRecordsWriteOutput, Persona } from '../tests/utils/test-data-generator.js';
111
110
  export { TestDataGenerator } from '../tests/utils/test-data-generator.js';
@@ -1,22 +1,17 @@
1
1
  import type { MessageSigner } from '../types/signer.js';
2
- import type { RecordsProjectionScope } from '../sync/records-projection.js';
3
2
  import type { MessagesSyncAction, MessagesSyncDescriptor, MessagesSyncMessage } from '../types/messages-types.js';
4
3
 
5
4
  import { AbstractMessage } from '../core/abstract-message.js';
6
5
  import { Message } from '../core/message.js';
7
- import { RECORDS_PROJECTION_ROOT_VERSION } from '../sync/records-projection.js';
8
6
  import { removeUndefinedProperties } from '@enbox/common';
9
7
  import { Time } from '../utils/time.js';
10
8
  import { validateProtocolUrlNormalized } from '../utils/url.js';
11
- import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
12
9
  import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
13
10
 
14
11
  export type MessagesSyncOptions = {
15
12
  signer : MessageSigner;
16
13
  action : MessagesSyncAction;
17
14
  protocol? : string;
18
- projectionRootVersion?: string;
19
- projectionScopes?: RecordsProjectionScope[];
20
15
  prefix? : string;
21
16
  messageTimestamp? : string;
22
17
  permissionGrantIds? : string[];
@@ -35,16 +30,6 @@ export class MessagesSync extends AbstractMessage<MessagesSyncMessage> {
35
30
  if (message.descriptor.protocol !== undefined) {
36
31
  validateProtocolUrlNormalized(message.descriptor.protocol);
37
32
  }
38
- if (message.descriptor.projectionRootVersion !== undefined &&
39
- message.descriptor.projectionRootVersion !== RECORDS_PROJECTION_ROOT_VERSION) {
40
- throw new DwnError(
41
- DwnErrorCode.MessagesSyncUnsupportedProjectionRootVersion,
42
- `Unsupported projection root version ${message.descriptor.projectionRootVersion}`
43
- );
44
- }
45
- for (const scope of message.descriptor.projectionScopes ?? []) {
46
- validateProtocolUrlNormalized(scope.protocol);
47
- }
48
33
 
49
34
  return new MessagesSync(message);
50
35
  }
@@ -55,16 +40,14 @@ export class MessagesSync extends AbstractMessage<MessagesSyncMessage> {
55
40
  });
56
41
 
57
42
  const descriptor: MessagesSyncDescriptor = {
58
- interface : DwnInterfaceName.Messages,
59
- method : DwnMethodName.Sync,
60
- messageTimestamp : options.messageTimestamp ?? Time.getCurrentTimestamp(),
61
- action : options.action,
62
- protocol : options.protocol,
63
- projectionRootVersion : options.projectionRootVersion,
64
- projectionScopes : options.projectionScopes,
65
- prefix : options.prefix,
66
- hashes : options.hashes,
67
- depth : options.depth,
43
+ interface : DwnInterfaceName.Messages,
44
+ method : DwnMethodName.Sync,
45
+ messageTimestamp : options.messageTimestamp ?? Time.getCurrentTimestamp(),
46
+ action : options.action,
47
+ protocol : options.protocol,
48
+ prefix : options.prefix,
49
+ hashes : options.hashes,
50
+ depth : options.depth,
68
51
  ...permissionGrantInvocation,
69
52
  };
70
53
 
@@ -50,12 +50,6 @@ export type MessagesSyncDescriptor = {
50
50
  messageTimestamp : string;
51
51
  action : MessagesSyncAction;
52
52
  protocol? : string; // optional protocol scope
53
- projectionRootVersion?: string;
54
- projectionScopes?: {
55
- protocol: string;
56
- protocolPath?: string;
57
- contextId?: string;
58
- }[];
59
53
  prefix? : string; // bit path for subtree/leaves (e.g. "0110101...")
60
54
  permissionGrantIds? : string[];
61
55
  /**
@@ -91,18 +85,6 @@ export type MessagesSyncDiffEntry = {
91
85
  encodedData? : string;
92
86
  };
93
87
 
94
- export type MessagesSyncDependencyClass = 'protocolsConfigure' | 'recordsInitialWrite';
95
-
96
- /**
97
- * Advisory dependency hint returned with projected diff responses. Dependency
98
- * entries are not part of the projected root; clients must rederive that the
99
- * dependency is required by the referenced primary before applying it.
100
- */
101
- export type MessagesSyncDependencyEntry = MessagesSyncDiffEntry & {
102
- dependencyClass: MessagesSyncDependencyClass;
103
- rootMessageCid: string;
104
- };
105
-
106
88
  export type MessagesSyncReply = GenericMessageReply & {
107
89
  root? : string; // hex-encoded root hash (for 'root' action)
108
90
  hash? : string; // hex-encoded subtree hash (for 'subtree' action)
@@ -111,8 +93,6 @@ export type MessagesSyncReply = GenericMessageReply & {
111
93
  onlyRemote? : MessagesSyncDiffEntry[];
112
94
  /** For 'diff' action: bit prefixes where the client has entries the server doesn't. */
113
95
  onlyLocal? : string[];
114
- /** Advisory dependency messages needed to apply projected `onlyRemote` primary entries. */
115
- dependencies? : MessagesSyncDependencyEntry[];
116
96
  };
117
97
 
118
98
  export type MessagesSubscribeMessageOptions = {
@@ -1,228 +0,0 @@
1
- import { DwnInterfaceName } from '../enums/dwn-interface-method.js';
2
- import { FilterUtility } from '../utils/filter.js';
3
- import { hashToHex } from '../smt/smt-utils.js';
4
- import { isRecordsPrimaryProjectionExcludedProtocol } from '../core/constants.js';
5
- import { lexicographicalCompare } from '../utils/string.js';
6
- import { Message } from '../core/message.js';
7
- import { SMTStoreMemory } from '../smt/smt-store-memory.js';
8
- import { SparseMerkleTree } from '../smt/sparse-merkle-tree.js';
9
- /**
10
- * Projection-root algorithm for record-primary scoped subsets.
11
- *
12
- * This version builds an on-demand SMT over latest Records primary message CIDs
13
- * selected by protocol plus optional exact protocolPath or context subtree.
14
- * Dependency records, protocol configs, and record data payloads are not part
15
- * of this root.
16
- */
17
- export const RECORDS_PROJECTION_ROOT_VERSION = 'records-primary-scope-root-v1';
18
- /**
19
- * Computes deterministic on-demand roots for Records projections.
20
- *
21
- * The snapshot API performs one store enumeration and serves tree operations
22
- * from that in-memory view. A future store-level snapshot/high-watermark can be
23
- * threaded through the `options` input without changing the projection shape.
24
- */
25
- export class RecordsProjection {
26
- /**
27
- * Returns the sorted latest Records primary message CIDs covered by a scope union.
28
- */
29
- static async getPrimaryMessageCids({ tenant, messageStore, scopes, options, }) {
30
- const filters = RecordsProjection.normalizeScopes(scopes)
31
- .filter(scope => !isRecordsPrimaryProjectionExcludedProtocol(scope.protocol))
32
- .flatMap(scope => RecordsProjection.constructFilters(scope));
33
- if (filters.length === 0) {
34
- return [];
35
- }
36
- const { messages } = await messageStore.query(tenant, filters, undefined, undefined, options);
37
- const messageCids = await Promise.all(messages.map(message => Message.getCid(message)));
38
- return [...new Set(messageCids)].sort(lexicographicalCompare); // NOSONAR — projection IDs require locale-independent bytewise ordering.
39
- }
40
- /**
41
- * Returns the projection root hash.
42
- */
43
- static async getRoot(input) {
44
- return RecordsProjection.withTree(input, tree => tree.getRoot());
45
- }
46
- /**
47
- * Returns the projection root hash encoded as lowercase hex.
48
- */
49
- static async getRootHex(input) {
50
- return hashToHex(await RecordsProjection.getRoot(input));
51
- }
52
- /**
53
- * Returns the subtree hash for a bit prefix within this projection.
54
- */
55
- static async getSubtreeHash(input) {
56
- return RecordsProjection.withTree(input, tree => tree.getSubtreeHash(input.prefix));
57
- }
58
- /**
59
- * Returns the message CIDs under a bit prefix within this projection.
60
- */
61
- static async getLeaves(input) {
62
- return RecordsProjection.withTree(input, tree => tree.getLeaves(input.prefix));
63
- }
64
- /**
65
- * Builds an in-memory projection tree from one primary-CID enumeration.
66
- */
67
- static async createSnapshot(input) {
68
- const tree = await RecordsProjection.createTree(input);
69
- return {
70
- close: () => tree.close(),
71
- getLeaves: (prefix) => tree.getLeaves(prefix),
72
- getRoot: () => tree.getRoot(),
73
- getRootHex: async () => hashToHex(await tree.getRoot()),
74
- getSubtreeHash: (prefix) => tree.getSubtreeHash(prefix),
75
- };
76
- }
77
- /**
78
- * Normalizes a scope union into sorted, duplicate-free, subsumption-reduced entries.
79
- */
80
- static normalizeScopes(scopes) {
81
- if (scopes.length === 0) {
82
- throw new Error('RecordsProjection: scopes must contain at least one scope.');
83
- }
84
- const normalized = scopes.map(scope => RecordsProjection.normalizeScope(scope));
85
- const deduped = new Map();
86
- for (const scope of normalized) {
87
- deduped.set(RecordsProjection.scopeKey(scope), scope);
88
- }
89
- const uniqueScopes = [...deduped.values()];
90
- const protocolWide = new Set(uniqueScopes
91
- .filter(scope => RecordsProjection.isProtocolWideScope(scope))
92
- .map(scope => scope.protocol));
93
- const reduced = uniqueScopes.filter(scope => {
94
- if (protocolWide.has(scope.protocol)) {
95
- return RecordsProjection.isProtocolWideScope(scope);
96
- }
97
- if (RecordsProjection.isContextScope(scope)) {
98
- return !uniqueScopes.some(candidate => candidate !== scope &&
99
- RecordsProjection.isContextScope(candidate) &&
100
- candidate.protocol === scope.protocol &&
101
- RecordsProjection.contextIdSubsumes(candidate.contextId, scope.contextId));
102
- }
103
- return true;
104
- });
105
- const result = reduced.sort(RecordsProjection.compareScopes);
106
- return result;
107
- }
108
- static async withTree(input, fn) {
109
- const tree = await RecordsProjection.createTree(input);
110
- try {
111
- return await fn(tree);
112
- }
113
- finally {
114
- await tree.close();
115
- }
116
- }
117
- static async createTree(input) {
118
- const tree = new SparseMerkleTree(new SMTStoreMemory());
119
- await tree.initialize();
120
- try {
121
- const messageCids = await RecordsProjection.getPrimaryMessageCids(input);
122
- for (const messageCid of messageCids) {
123
- await tree.insert(messageCid);
124
- }
125
- return tree;
126
- }
127
- catch (error) {
128
- await tree.close();
129
- throw error;
130
- }
131
- }
132
- static normalizeScope(scope) {
133
- const protocol = RecordsProjection.requireNonEmptyString(scope.protocol, 'protocol');
134
- if (scope.protocolPath !== undefined && scope.contextId !== undefined) {
135
- throw new Error('RecordsProjection: protocolPath and contextId scopes are mutually exclusive.');
136
- }
137
- if (scope.protocolPath !== undefined) {
138
- return {
139
- protocol,
140
- protocolPath: RecordsProjection.requireNonEmptyString(scope.protocolPath, 'protocolPath'),
141
- };
142
- }
143
- if (scope.contextId !== undefined) {
144
- return {
145
- protocol,
146
- contextId: RecordsProjection.requireNonEmptyString(scope.contextId, 'contextId'),
147
- };
148
- }
149
- return { protocol };
150
- }
151
- static constructFilters(scope) {
152
- const baseFilter = {
153
- interface: DwnInterfaceName.Records,
154
- isLatestBaseState: true,
155
- protocol: scope.protocol,
156
- };
157
- if ('protocolPath' in scope) {
158
- return [{ ...baseFilter, protocolPath: scope.protocolPath }];
159
- }
160
- if ('contextId' in scope) {
161
- const childContextPrefix = `${scope.contextId}/`;
162
- return [
163
- { ...baseFilter, contextId: scope.contextId },
164
- {
165
- ...baseFilter,
166
- contextId: FilterUtility.constructPrefixFilterAsRangeFilter(childContextPrefix),
167
- },
168
- ];
169
- }
170
- return [baseFilter];
171
- }
172
- static requireNonEmptyString(value, field) {
173
- if (typeof value !== 'string' || value.length === 0) {
174
- throw new Error(`RecordsProjection: ${field} must be a non-empty string.`);
175
- }
176
- return value;
177
- }
178
- static scopeKey(scope) {
179
- if ('protocolPath' in scope) {
180
- return `${scope.protocol}\u001fprotocolPath\u001f${scope.protocolPath}`;
181
- }
182
- if ('contextId' in scope) {
183
- return `${scope.protocol}\u001fcontextId\u001f${scope.contextId}`;
184
- }
185
- return `${scope.protocol}\u001fprotocol`;
186
- }
187
- static isProtocolWideScope(scope) {
188
- return !('protocolPath' in scope) && !('contextId' in scope);
189
- }
190
- static isContextScope(scope) {
191
- return 'contextId' in scope;
192
- }
193
- static contextIdSubsumes(parentContextId, childContextId) {
194
- return childContextId === parentContextId ||
195
- childContextId.startsWith(`${parentContextId}/`);
196
- }
197
- static compareScopes(a, b) {
198
- const protocolCompare = lexicographicalCompare(a.protocol, b.protocol);
199
- if (protocolCompare !== 0) {
200
- return protocolCompare;
201
- }
202
- const aRank = RecordsProjection.scopeRank(a);
203
- const bRank = RecordsProjection.scopeRank(b);
204
- if (aRank !== bRank) {
205
- return aRank - bRank;
206
- }
207
- return lexicographicalCompare(RecordsProjection.scopeValue(a), RecordsProjection.scopeValue(b));
208
- }
209
- static scopeRank(scope) {
210
- if ('protocolPath' in scope) {
211
- return 1;
212
- }
213
- if ('contextId' in scope) {
214
- return 2;
215
- }
216
- return 0;
217
- }
218
- static scopeValue(scope) {
219
- if ('protocolPath' in scope) {
220
- return scope.protocolPath;
221
- }
222
- if ('contextId' in scope) {
223
- return scope.contextId;
224
- }
225
- return '';
226
- }
227
- }
228
- //# sourceMappingURL=records-projection.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"records-projection.js","sourceRoot":"","sources":["../../../../src/sync/records-projection.ts"],"names":[],"mappings":"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"}
@@ -1,245 +0,0 @@
1
- import { afterAll, beforeAll, beforeEach, describe, expect, it, spyOn } from 'bun:test';
2
- import { lexicographicalCompare } from '../../src/utils/string.js';
3
- import { TestDataGenerator } from '../utils/test-data-generator.js';
4
- import { TestStores } from '../test-stores.js';
5
- import { getBit, hashKey, hashToHex, Jws, Message, RecordsDelete, RecordsProjection, SMTStoreMemory, SparseMerkleTree } from '../../src/index.js';
6
- export function testRecordsProjection() {
7
- describe('RecordsProjection', () => {
8
- let messageStore;
9
- let alice;
10
- const tenant = () => alice.did;
11
- beforeAll(async () => {
12
- messageStore = TestStores.get().messageStore;
13
- await messageStore.open();
14
- });
15
- beforeEach(async () => {
16
- alice = await TestDataGenerator.generatePersona();
17
- await messageStore.clear();
18
- });
19
- afterAll(async () => {
20
- await messageStore.close();
21
- });
22
- it('normalizes duplicate and covered scopes deterministically', () => {
23
- const scopes = RecordsProjection.normalizeScopes([
24
- { protocol: 'https://example.com/b', protocolPath: 'note' },
25
- { protocol: 'https://example.com/a', contextId: 'root' },
26
- { protocol: 'https://example.com/b' },
27
- { protocol: 'https://example.com/b', protocolPath: 'note' },
28
- ]);
29
- expect(scopes).toEqual([
30
- { protocol: 'https://example.com/a', contextId: 'root' },
31
- { protocol: 'https://example.com/b' },
32
- ]);
33
- });
34
- it('normalizes covered context subtree scopes to the broader context', () => {
35
- const scopes = RecordsProjection.normalizeScopes([
36
- { protocol: 'https://example.com/a', contextId: 'root/child' },
37
- { protocol: 'https://example.com/a', contextId: 'root/child/grandchild' },
38
- { protocol: 'https://example.com/a', contextId: 'root' },
39
- { protocol: 'https://example.com/a', contextId: 'rootEVIL' },
40
- { protocol: 'https://example.com/b', contextId: 'root/child' },
41
- { protocol: 'https://example.com/b', contextId: 'root' },
42
- ]);
43
- expect(scopes).toEqual([
44
- { protocol: 'https://example.com/a', contextId: 'root' },
45
- { protocol: 'https://example.com/a', contextId: 'rootEVIL' },
46
- { protocol: 'https://example.com/b', contextId: 'root' },
47
- ]);
48
- });
49
- it('rejects scopes that specify both protocolPath and contextId', () => {
50
- expect(() => RecordsProjection.normalizeScopes([
51
- { protocol: 'https://example.com/a', protocolPath: 'note', contextId: 'root' },
52
- ])).toThrow('protocolPath and contextId scopes are mutually exclusive');
53
- });
54
- it('returns primary message CIDs in bytewise order', async () => {
55
- const messages = [
56
- createGenericMessage('2026-06-05T00:00:00.000000Z'),
57
- createGenericMessage('2026-06-05T00:00:01.000000Z'),
58
- createGenericMessage('2026-06-05T00:00:02.000000Z'),
59
- ];
60
- const cidByMessage = new Map([
61
- [messages[0], 'bafyZ'],
62
- [messages[1], 'bafya'],
63
- [messages[2], 'bafyB'],
64
- ]);
65
- const getCidSpy = spyOn(Message, 'getCid').mockImplementation(async (message) => cidByMessage.get(message));
66
- try {
67
- const projectedCids = await RecordsProjection.getPrimaryMessageCids({
68
- tenant: tenant(),
69
- messageStore: createQueryOnlyMessageStore(messages),
70
- scopes: [{ protocol: 'https://example.com/chat' }],
71
- });
72
- expect(projectedCids).toEqual([...cidByMessage.values()].sort(lexicographicalCompare));
73
- }
74
- finally {
75
- getCidSpy.mockRestore();
76
- }
77
- });
78
- it('projects protocolPath scopes by exact path, not prefix', async () => {
79
- const protocol = 'https://example.com/chat';
80
- const root = await createWrite({ protocol, protocolPath: 'thread' });
81
- const child = await createWrite({
82
- protocol,
83
- protocolPath: 'thread/message',
84
- parentContextId: root.message.contextId,
85
- });
86
- const siblingType = await createWrite({
87
- protocol,
88
- protocolPath: 'thread/messageAttachment',
89
- parentContextId: root.message.contextId,
90
- });
91
- const rootCid = await putWrite(root);
92
- const childCid = await putWrite(child);
93
- await putWrite(siblingType);
94
- const rootPathCids = await RecordsProjection.getPrimaryMessageCids({
95
- tenant: tenant(),
96
- messageStore,
97
- scopes: [{ protocol, protocolPath: 'thread' }],
98
- });
99
- expect(rootPathCids).toEqual([rootCid]);
100
- const childPathCids = await RecordsProjection.getPrimaryMessageCids({
101
- tenant: tenant(),
102
- messageStore,
103
- scopes: [{ protocol, protocolPath: 'thread/message' }],
104
- });
105
- expect(childPathCids).toEqual([childCid]);
106
- });
107
- it('projects contextId scopes by context subtree boundary', async () => {
108
- const protocol = 'https://example.com/chat';
109
- const root = await createWrite({ protocol, protocolPath: 'thread' });
110
- const child = await createWrite({
111
- protocol,
112
- protocolPath: 'thread/message',
113
- parentContextId: root.message.contextId,
114
- });
115
- const falsePrefix = await createWrite({ protocol, protocolPath: 'thread' });
116
- const rootCid = await putWrite(root);
117
- const childCid = await putWrite(child);
118
- await putWrite(falsePrefix, true, { contextId: `${root.message.contextId}EVIL` });
119
- const projectedCids = await RecordsProjection.getPrimaryMessageCids({
120
- tenant: tenant(),
121
- messageStore,
122
- scopes: [{ protocol, contextId: root.message.contextId }],
123
- });
124
- expect(projectedCids).toEqual([childCid, rootCid].sort(lexicographicalCompare));
125
- });
126
- it('includes RecordsDelete tombstones by indexed initial-write projection metadata', async () => {
127
- const protocol = 'https://example.com/chat';
128
- const write = await createWrite({ protocol, protocolPath: 'thread/message' });
129
- const deleteRecord = await RecordsDelete.create({
130
- recordId: write.message.recordId,
131
- signer: Jws.createSigner(alice),
132
- });
133
- await putWrite(write, false);
134
- const deleteCid = await putDelete(deleteRecord, write.message);
135
- const projectedCids = await RecordsProjection.getPrimaryMessageCids({
136
- tenant: tenant(),
137
- messageStore,
138
- scopes: [{ protocol, protocolPath: 'thread/message' }],
139
- });
140
- expect(projectedCids).toEqual([deleteCid]);
141
- });
142
- it('computes the same SMT root, subtree hash, and leaves as the projected CID set', async () => {
143
- const protocol = 'https://example.com/chat';
144
- const root = await createWrite({ protocol, protocolPath: 'thread' });
145
- const child = await createWrite({
146
- protocol,
147
- protocolPath: 'thread/message',
148
- parentContextId: root.message.contextId,
149
- });
150
- const otherProtocol = await createWrite({
151
- protocol: 'https://example.com/notes',
152
- protocolPath: 'note',
153
- });
154
- const rootCid = await putWrite(root);
155
- const childCid = await putWrite(child);
156
- await putWrite(otherProtocol);
157
- const scopes = [{ protocol }];
158
- const expectedCids = [childCid, rootCid].sort(lexicographicalCompare);
159
- const prefix = await firstBitPrefix(rootCid);
160
- const expectedTree = await treeValuesFromCids(expectedCids, prefix);
161
- const rootHex = await RecordsProjection.getRootHex({
162
- tenant: tenant(),
163
- messageStore,
164
- scopes,
165
- });
166
- const subtreeHash = await RecordsProjection.getSubtreeHash({
167
- tenant: tenant(),
168
- messageStore,
169
- scopes,
170
- prefix,
171
- });
172
- const leaves = await RecordsProjection.getLeaves({
173
- tenant: tenant(),
174
- messageStore,
175
- scopes,
176
- prefix,
177
- });
178
- expect(rootHex).toBe(expectedTree.rootHex);
179
- expect(hashToHex(subtreeHash)).toBe(expectedTree.subtreeHex);
180
- expect(leaves.sort(lexicographicalCompare)).toEqual(expectedTree.leaves);
181
- });
182
- async function createWrite(input) {
183
- return TestDataGenerator.generateRecordsWrite({
184
- author: alice,
185
- ...input,
186
- });
187
- }
188
- async function putWrite(write, isLatestBaseState = true, indexOverrides = {}) {
189
- const indexes = {
190
- ...await write.recordsWrite.constructIndexes(isLatestBaseState),
191
- ...indexOverrides,
192
- };
193
- await messageStore.put(tenant(), write.message, indexes);
194
- return Message.getCid(write.message);
195
- }
196
- async function putDelete(recordsDelete, initialWrite) {
197
- await messageStore.put(tenant(), recordsDelete.message, recordsDelete.constructIndexes(initialWrite));
198
- return Message.getCid(recordsDelete.message);
199
- }
200
- });
201
- }
202
- function createGenericMessage(messageTimestamp) {
203
- return {
204
- descriptor: {
205
- interface: 'Records',
206
- method: 'Write',
207
- messageTimestamp,
208
- },
209
- };
210
- }
211
- function createQueryOnlyMessageStore(messages) {
212
- return {
213
- clear: async () => { },
214
- close: async () => { },
215
- count: async () => messages.length,
216
- delete: async () => { },
217
- get: async () => undefined,
218
- open: async () => { },
219
- put: async () => { },
220
- query: async () => ({ messages }),
221
- };
222
- }
223
- async function firstBitPrefix(messageCid) {
224
- const keyHash = await hashKey(messageCid);
225
- return [getBit(keyHash, 0)];
226
- }
227
- async function treeValuesFromCids(messageCids, prefix) {
228
- const tree = new SparseMerkleTree(new SMTStoreMemory());
229
- await tree.initialize();
230
- try {
231
- for (const messageCid of messageCids) {
232
- await tree.insert(messageCid);
233
- }
234
- const leaves = await tree.getLeaves(prefix);
235
- return {
236
- rootHex: hashToHex(await tree.getRoot()),
237
- subtreeHex: hashToHex(await tree.getSubtreeHash(prefix)),
238
- leaves: leaves.sort(lexicographicalCompare),
239
- };
240
- }
241
- finally {
242
- await tree.close();
243
- }
244
- }
245
- //# sourceMappingURL=records-projection.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"records-projection.spec.js","sourceRoot":"","sources":["../../../../tests/sync/records-projection.spec.ts"],"names":[],"mappings":"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"}