@enbox/dwn-sdk-js 0.3.4 → 0.3.5
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 +8 -8
- package/dist/browser.mjs.map +3 -3
- package/dist/esm/generated/precompiled-validators.js +766 -1224
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/abstract-message.js +3 -3
- package/dist/esm/src/core/abstract-message.js.map +1 -1
- package/dist/esm/src/core/grant-authorization.js +6 -2
- package/dist/esm/src/core/grant-authorization.js.map +1 -1
- package/dist/esm/src/core/message.js +3 -3
- package/dist/esm/src/core/message.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-action.js +3 -3
- package/dist/esm/src/core/protocol-authorization-action.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-validation.js +1 -1
- package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization.js +11 -11
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/core/records-grant-authorization.js +1 -1
- package/dist/esm/src/core/records-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/resumable-task-manager.js.map +1 -1
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/event-stream/event-emitter-event-log.js +12 -12
- package/dist/esm/src/event-stream/event-emitter-event-log.js.map +1 -1
- package/dist/esm/src/handlers/messages-read.js +7 -7
- package/dist/esm/src/handlers/messages-read.js.map +1 -1
- package/dist/esm/src/handlers/messages-subscribe.js +1 -1
- package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/messages-sync.js +18 -18
- package/dist/esm/src/handlers/messages-sync.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js +1 -1
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/protocols-query.js.map +1 -1
- package/dist/esm/src/handlers/records-count.js.map +1 -1
- package/dist/esm/src/handlers/records-delete.js.map +1 -1
- package/dist/esm/src/handlers/records-query.js.map +1 -1
- package/dist/esm/src/handlers/records-read.js +6 -6
- package/dist/esm/src/handlers/records-read.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +1 -1
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +16 -16
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +2 -2
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-configure.js +9 -9
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/records-delete.js.map +1 -1
- package/dist/esm/src/interfaces/records-write.js +8 -8
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/jose/jws/general/builder.js.map +1 -1
- package/dist/esm/src/jose/jws/general/verifier.js +30 -2
- package/dist/esm/src/jose/jws/general/verifier.js.map +1 -1
- package/dist/esm/src/protocols/permissions.js +1 -1
- package/dist/esm/src/protocols/permissions.js.map +1 -1
- package/dist/esm/src/smt/smt-store-level.js.map +1 -1
- package/dist/esm/src/smt/smt-store-memory.js.map +1 -1
- package/dist/esm/src/smt/sparse-merkle-tree.js +2 -2
- package/dist/esm/src/smt/sparse-merkle-tree.js.map +1 -1
- package/dist/esm/src/state-index/state-index-level.js.map +1 -1
- package/dist/esm/src/store/index-level-compound.js +10 -10
- package/dist/esm/src/store/index-level-compound.js.map +1 -1
- package/dist/esm/src/store/index-level.js +2 -2
- package/dist/esm/src/store/index-level.js.map +1 -1
- package/dist/esm/src/store/level-wrapper.js +1 -1
- package/dist/esm/src/store/level-wrapper.js.map +1 -1
- package/dist/esm/src/store/storage-controller.js +23 -10
- package/dist/esm/src/store/storage-controller.js.map +1 -1
- package/dist/esm/src/types/permission-types.js.map +1 -1
- package/dist/esm/src/utils/memory-cache.js.map +1 -1
- package/dist/esm/src/utils/messages.js +1 -1
- package/dist/esm/src/utils/messages.js.map +1 -1
- package/dist/esm/src/utils/object.js +1 -4
- package/dist/esm/src/utils/object.js.map +1 -1
- package/dist/esm/src/utils/private-key-signer.js.map +1 -1
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/tests/core/grant-authorization.spec.js +38 -0
- package/dist/esm/tests/core/grant-authorization.spec.js.map +1 -0
- package/dist/esm/tests/features/permissions.spec.js +1 -1
- package/dist/esm/tests/features/permissions.spec.js.map +1 -1
- package/dist/esm/tests/features/records-prune-cross-protocol.spec.js +422 -0
- package/dist/esm/tests/features/records-prune-cross-protocol.spec.js.map +1 -0
- package/dist/esm/tests/handlers/messages-subscribe.spec.js +3 -26
- package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-sync.spec.js +3 -26
- package/dist/esm/tests/handlers/messages-sync.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-query.spec.js +4 -3
- package/dist/esm/tests/handlers/protocols-query.spec.js.map +1 -1
- package/dist/esm/tests/jose/jws/general.spec.js +115 -0
- package/dist/esm/tests/jose/jws/general.spec.js.map +1 -1
- package/dist/esm/tests/test-suite.js +2 -0
- package/dist/esm/tests/test-suite.js.map +1 -1
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/abstract-message.d.ts +4 -4
- package/dist/types/src/core/abstract-message.d.ts.map +1 -1
- package/dist/types/src/core/grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/resumable-task-manager.d.ts +2 -2
- package/dist/types/src/core/resumable-task-manager.d.ts.map +1 -1
- package/dist/types/src/dwn.d.ts +12 -12
- package/dist/types/src/dwn.d.ts.map +1 -1
- package/dist/types/src/event-stream/event-emitter-event-log.d.ts +5 -5
- package/dist/types/src/event-stream/event-emitter-event-log.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-read.d.ts +1 -1
- package/dist/types/src/handlers/messages-read.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-subscribe.d.ts +1 -1
- package/dist/types/src/handlers/messages-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/messages-sync.d.ts +1 -1
- package/dist/types/src/handlers/messages-sync.d.ts.map +1 -1
- package/dist/types/src/handlers/protocols-configure.d.ts +1 -1
- package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/handlers/protocols-query.d.ts +1 -1
- package/dist/types/src/handlers/protocols-query.d.ts.map +1 -1
- package/dist/types/src/handlers/records-count.d.ts +1 -1
- package/dist/types/src/handlers/records-count.d.ts.map +1 -1
- package/dist/types/src/handlers/records-delete.d.ts +1 -1
- package/dist/types/src/handlers/records-delete.d.ts.map +1 -1
- package/dist/types/src/handlers/records-query.d.ts +1 -1
- package/dist/types/src/handlers/records-query.d.ts.map +1 -1
- package/dist/types/src/handlers/records-read.d.ts +1 -1
- package/dist/types/src/handlers/records-read.d.ts.map +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/records-write.d.ts +1 -1
- package/dist/types/src/handlers/records-write.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +5 -5
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write.d.ts +2 -2
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/jose/jws/general/builder.d.ts +1 -1
- package/dist/types/src/jose/jws/general/builder.d.ts.map +1 -1
- package/dist/types/src/jose/jws/general/verifier.d.ts +13 -0
- package/dist/types/src/jose/jws/general/verifier.d.ts.map +1 -1
- package/dist/types/src/smt/smt-store-level.d.ts +1 -1
- package/dist/types/src/smt/smt-store-level.d.ts.map +1 -1
- package/dist/types/src/smt/smt-store-memory.d.ts +1 -1
- package/dist/types/src/smt/smt-store-memory.d.ts.map +1 -1
- package/dist/types/src/smt/sparse-merkle-tree.d.ts +1 -1
- package/dist/types/src/smt/sparse-merkle-tree.d.ts.map +1 -1
- package/dist/types/src/state-index/state-index-level.d.ts +3 -3
- package/dist/types/src/state-index/state-index-level.d.ts.map +1 -1
- package/dist/types/src/store/index-level.d.ts +2 -2
- package/dist/types/src/store/index-level.d.ts.map +1 -1
- package/dist/types/src/store/storage-controller.d.ts +19 -5
- package/dist/types/src/store/storage-controller.d.ts.map +1 -1
- package/dist/types/src/types/permission-types.d.ts +3 -4
- package/dist/types/src/types/permission-types.d.ts.map +1 -1
- package/dist/types/src/utils/memory-cache.d.ts +2 -2
- package/dist/types/src/utils/memory-cache.d.ts.map +1 -1
- package/dist/types/src/utils/object.d.ts.map +1 -1
- package/dist/types/src/utils/private-key-signer.d.ts +2 -2
- package/dist/types/src/utils/private-key-signer.d.ts.map +1 -1
- package/dist/types/tests/core/grant-authorization.spec.d.ts +2 -0
- package/dist/types/tests/core/grant-authorization.spec.d.ts.map +1 -0
- package/dist/types/tests/features/records-prune-cross-protocol.spec.d.ts +29 -0
- package/dist/types/tests/features/records-prune-cross-protocol.spec.d.ts.map +1 -0
- package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/messages-sync.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/protocols-query.spec.d.ts.map +1 -1
- package/dist/types/tests/test-suite.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/abstract-message.ts +8 -8
- package/src/core/grant-authorization.ts +9 -2
- package/src/core/message.ts +3 -3
- package/src/core/protocol-authorization-action.ts +3 -3
- package/src/core/protocol-authorization-validation.ts +9 -9
- package/src/core/protocol-authorization.ts +24 -24
- package/src/core/records-grant-authorization.ts +1 -1
- package/src/core/resumable-task-manager.ts +2 -2
- package/src/dwn.ts +13 -13
- package/src/event-stream/event-emitter-event-log.ts +15 -15
- package/src/handlers/messages-read.ts +7 -7
- package/src/handlers/messages-subscribe.ts +2 -2
- package/src/handlers/messages-sync.ts +19 -19
- package/src/handlers/protocols-configure.ts +2 -2
- package/src/handlers/protocols-query.ts +1 -1
- package/src/handlers/records-count.ts +1 -1
- package/src/handlers/records-delete.ts +1 -1
- package/src/handlers/records-query.ts +1 -1
- package/src/handlers/records-read.ts +6 -6
- package/src/handlers/records-subscribe.ts +2 -2
- package/src/handlers/records-write.ts +18 -18
- package/src/index.ts +5 -5
- package/src/interfaces/protocols-configure.ts +12 -12
- package/src/interfaces/records-delete.ts +1 -1
- package/src/interfaces/records-write.ts +11 -11
- package/src/jose/jws/general/builder.ts +1 -1
- package/src/jose/jws/general/verifier.ts +44 -3
- package/src/protocols/permissions.ts +1 -1
- package/src/smt/smt-store-level.ts +1 -1
- package/src/smt/smt-store-memory.ts +1 -1
- package/src/smt/sparse-merkle-tree.ts +10 -10
- package/src/state-index/state-index-level.ts +3 -3
- package/src/store/index-level-compound.ts +11 -11
- package/src/store/index-level.ts +4 -4
- package/src/store/level-wrapper.ts +1 -1
- package/src/store/storage-controller.ts +31 -16
- package/src/types/permission-types.ts +3 -4
- package/src/utils/memory-cache.ts +2 -2
- package/src/utils/messages.ts +2 -2
- package/src/utils/object.ts +1 -5
- package/src/utils/private-key-signer.ts +2 -2
- package/src/utils/records.ts +1 -1
|
@@ -20,7 +20,7 @@ import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.j
|
|
|
20
20
|
|
|
21
21
|
export class RecordsSubscribeHandler implements MethodHandler {
|
|
22
22
|
|
|
23
|
-
constructor(private deps: HandlerDependencies) { }
|
|
23
|
+
constructor(private readonly deps: HandlerDependencies) { }
|
|
24
24
|
|
|
25
25
|
public async handle({
|
|
26
26
|
tenant,
|
|
@@ -97,7 +97,7 @@ export class RecordsSubscribeHandler implements MethodHandler {
|
|
|
97
97
|
const gapInfo = (error as any).gapInfo as ProgressGapInfo | undefined;
|
|
98
98
|
return {
|
|
99
99
|
status : { code: 410, detail: 'Progress token gap' },
|
|
100
|
-
error : gapInfo
|
|
100
|
+
error : gapInfo === undefined ? undefined : { code: 'ProgressGap' as const, ...gapInfo },
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
103
|
return messageReplyFromError(error, 500);
|
|
@@ -27,7 +27,7 @@ type HandlerArgs = { tenant: string, message: RecordsWriteMessage, dataStream?:
|
|
|
27
27
|
|
|
28
28
|
export class RecordsWriteHandler implements MethodHandler {
|
|
29
29
|
|
|
30
|
-
constructor(private deps: HandlerDependencies) { }
|
|
30
|
+
constructor(private readonly deps: HandlerDependencies) { }
|
|
31
31
|
|
|
32
32
|
public async handle({
|
|
33
33
|
tenant,
|
|
@@ -106,7 +106,7 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
106
106
|
if (isInitial) {
|
|
107
107
|
const hasInlineData = !!(newestExistingMessage as any).encodedData;
|
|
108
108
|
const hasStoredData = this.deps.dataStore
|
|
109
|
-
? !!(await this.deps.dataStore.get(tenant, recordsWrite.message.recordId, message.descriptor.dataCid
|
|
109
|
+
? !!(await this.deps.dataStore.get(tenant, recordsWrite.message.recordId, message.descriptor.dataCid))
|
|
110
110
|
: false;
|
|
111
111
|
existingLacksData = !hasInlineData && !hasStoredData;
|
|
112
112
|
}
|
|
@@ -121,9 +121,9 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
121
121
|
|
|
122
122
|
// Look up the core protocol (if any) for the incoming message so that lifecycle hooks
|
|
123
123
|
// can be dispatched generically rather than checking for specific protocol URIs.
|
|
124
|
-
const coreProtocol = message.descriptor.protocol
|
|
125
|
-
?
|
|
126
|
-
:
|
|
124
|
+
const coreProtocol = message.descriptor.protocol === undefined
|
|
125
|
+
? undefined
|
|
126
|
+
: this.deps.coreProtocols?.get(message.descriptor.protocol);
|
|
127
127
|
|
|
128
128
|
try {
|
|
129
129
|
if (newestExistingMessage?.descriptor.method === DwnMethodName.Delete) {
|
|
@@ -148,11 +148,8 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
148
148
|
let isLatestBaseState = false;
|
|
149
149
|
let messageWithOptionalEncodedData = message as RecordsQueryReplyEntry;
|
|
150
150
|
|
|
151
|
-
if (dataStream
|
|
152
|
-
|
|
153
|
-
isLatestBaseState = true;
|
|
154
|
-
} else {
|
|
155
|
-
// else data stream is NOT provided
|
|
151
|
+
if (dataStream === undefined) {
|
|
152
|
+
// data stream is NOT provided
|
|
156
153
|
|
|
157
154
|
// if the incoming message is not an initial write, and no dataStream is provided, we would allow it provided it passes validation
|
|
158
155
|
// processMessageWithoutDataStream() abstracts that logic
|
|
@@ -161,6 +158,9 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
161
158
|
messageWithOptionalEncodedData = await this.processMessageWithoutDataStream(tenant, message, newestExistingWrite );
|
|
162
159
|
isLatestBaseState = true;
|
|
163
160
|
}
|
|
161
|
+
} else {
|
|
162
|
+
messageWithOptionalEncodedData = await this.processMessageWithDataStream(tenant, message, dataStream);
|
|
163
|
+
isLatestBaseState = true;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
const indexes = await recordsWrite.constructIndexes(isLatestBaseState);
|
|
@@ -252,14 +252,14 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
252
252
|
// if data is below the threshold, we store it within MessageStore
|
|
253
253
|
if (message.descriptor.dataSize <= DwnConstant.maxDataSizeAllowedToBeEncoded) {
|
|
254
254
|
// validate data integrity before setting.
|
|
255
|
-
const dataBytes = await DataStream.toBytes(dataStream
|
|
255
|
+
const dataBytes = await DataStream.toBytes(dataStream);
|
|
256
256
|
const dataCid = await Cid.computeDagPbCidFromBytes(dataBytes);
|
|
257
257
|
RecordsWriteHandler.validateDataIntegrity(message.descriptor.dataCid, message.descriptor.dataSize, dataCid, dataBytes.length);
|
|
258
258
|
|
|
259
259
|
// Dispatch schema validation to the core protocol, if applicable.
|
|
260
|
-
const coreProtocol = message.descriptor.protocol
|
|
261
|
-
?
|
|
262
|
-
:
|
|
260
|
+
const coreProtocol = message.descriptor.protocol === undefined
|
|
261
|
+
? undefined
|
|
262
|
+
: this.deps.coreProtocols?.get(message.descriptor.protocol);
|
|
263
263
|
if (coreProtocol?.validateRecord !== undefined) {
|
|
264
264
|
coreProtocol.validateRecord(message, dataBytes);
|
|
265
265
|
}
|
|
@@ -304,13 +304,13 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
304
304
|
|
|
305
305
|
if (dataSize <= DwnConstant.maxDataSizeAllowedToBeEncoded) {
|
|
306
306
|
// we encode the data from the original write if it is smaller than the data-store threshold
|
|
307
|
-
if (newestExistingWrite.encodedData
|
|
308
|
-
messageWithOptionalEncodedData.encodedData = newestExistingWrite.encodedData;
|
|
309
|
-
} else {
|
|
307
|
+
if (newestExistingWrite.encodedData === undefined) {
|
|
310
308
|
throw new DwnError(
|
|
311
309
|
DwnErrorCode.RecordsWriteMissingEncodedDataInPrevious,
|
|
312
310
|
`No dataStream was provided and unable to get data from previous message`
|
|
313
311
|
);
|
|
312
|
+
} else {
|
|
313
|
+
messageWithOptionalEncodedData.encodedData = newestExistingWrite.encodedData;
|
|
314
314
|
}
|
|
315
315
|
} else {
|
|
316
316
|
// else just make sure the data is in the data store
|
|
@@ -396,7 +396,7 @@ export class RecordsWriteHandler implements MethodHandler {
|
|
|
396
396
|
ruleSet = ruleSet[pathSegments[i]] as typeof ruleSet;
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
-
if (ruleSet
|
|
399
|
+
if (ruleSet?.$squash !== true) {
|
|
400
400
|
return;
|
|
401
401
|
}
|
|
402
402
|
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export type { DwnConfig } from './dwn.js';
|
|
3
3
|
export type { EventListener, EventLog, EventLogEntry, EventLogReadOptions, EventLogReadResult, EventLogSubscribeOptions, EventSubscription, MessageEvent, ProgressGapInfo, ProgressGapReason, ProgressToken, SubscriptionEose, 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
|
|
5
|
+
export type { MessagesFilter, MessagesReadMessage, MessagesReadReply, MessagesReadReplyEntry, MessagesReadDescriptor, MessagesSubscribeDescriptor, MessagesSubscribeMessage, MessagesSubscribeReply, MessagesSubscribeMessageOptions, MessagesSyncAction, MessagesSyncDescriptor, MessagesSyncDiffEntry, MessagesSyncMessage, MessagesSyncReply } from './types/messages-types.js';
|
|
6
6
|
export type { GT, LT, Filter, FilterValue, KeyValues, EqualFilter, OneOfFilter, RangeFilter, RangeCriterion, PaginationCursor, QueryOptions, RangeValue, StartsWithFilter } from './types/query-types.js';
|
|
7
7
|
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
8
|
export { ProtocolRecordLimitStrategy } from './types/protocols-types.js';
|
|
@@ -30,8 +30,8 @@ export { DwnConstant } from './core/dwn-constant.js';
|
|
|
30
30
|
export { DwnError, DwnErrorCode } from './core/dwn-error.js';
|
|
31
31
|
export { DwnInterfaceName, DwnMethodName } from './enums/dwn-interface-method.js';
|
|
32
32
|
export { Encoder } from './utils/encoder.js';
|
|
33
|
-
export { MessagesSubscribe
|
|
34
|
-
export type { MessagesSubscribeOptions
|
|
33
|
+
export { MessagesSubscribe } from './interfaces/messages-subscribe.js';
|
|
34
|
+
export type { MessagesSubscribeOptions } from './interfaces/messages-subscribe.js';
|
|
35
35
|
export { Encryption, ContentEncryptionAlgorithm, KeyAgreementAlgorithm } from './utils/encryption.js';
|
|
36
36
|
export type { JweEncryption, JweRecipient, JweRecipientHeader, JweProtectedHeader, JweKeyUnwrapPayload } from './utils/encryption.js';
|
|
37
37
|
export { RecordsWrite } from './interfaces/records-write.js';
|
|
@@ -40,8 +40,8 @@ export { executeUnlessAborted } from './utils/abort.js';
|
|
|
40
40
|
export { Jws } from './utils/jws.js';
|
|
41
41
|
export type { KeyMaterial, PrivateKeyJwk, PublicKeyJwk, Jwk } from './types/jose-types.js';
|
|
42
42
|
export { Message } from './core/message.js';
|
|
43
|
-
export { MessagesRead
|
|
44
|
-
export type { MessagesReadOptions
|
|
43
|
+
export { MessagesRead } from './interfaces/messages-read.js';
|
|
44
|
+
export type { MessagesReadOptions } from './interfaces/messages-read.js';
|
|
45
45
|
export { MessagesSync } from './interfaces/messages-sync.js';
|
|
46
46
|
export type { MessagesSyncOptions } from './interfaces/messages-sync.js';
|
|
47
47
|
export type { UnionMessageReply } from './core/message-reply.js';
|
|
@@ -377,16 +377,8 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
377
377
|
for (let j = i + 1; j < actionRules.length; j++) {
|
|
378
378
|
const otherActionRule = actionRules[j];
|
|
379
379
|
|
|
380
|
-
if (actionRule.who
|
|
381
|
-
|
|
382
|
-
throw new DwnError(
|
|
383
|
-
DwnErrorCode.ProtocolsConfigureDuplicateActorInRuleSet,
|
|
384
|
-
`More than one action rule per actor ${actionRule.who} of ${actionRule.of} ` +
|
|
385
|
-
`not allowed within a rule set: ${JSON.stringify(actionRule)}`
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
|
-
} else {
|
|
389
|
-
// else implicitly a role-based action rule
|
|
380
|
+
if (actionRule.who === undefined) {
|
|
381
|
+
// implicitly a role-based action rule
|
|
390
382
|
|
|
391
383
|
if (actionRule.role === otherActionRule.role) {
|
|
392
384
|
throw new DwnError(
|
|
@@ -394,6 +386,14 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
394
386
|
`More than one action rule per role ${actionRule.role} not allowed within a rule set: ${JSON.stringify(actionRule)}`
|
|
395
387
|
);
|
|
396
388
|
}
|
|
389
|
+
} else {
|
|
390
|
+
if (actionRule.who === otherActionRule.who && actionRule.of === otherActionRule.of) {
|
|
391
|
+
throw new DwnError(
|
|
392
|
+
DwnErrorCode.ProtocolsConfigureDuplicateActorInRuleSet,
|
|
393
|
+
`More than one action rule per actor ${actionRule.who} of ${actionRule.of} ` +
|
|
394
|
+
`not allowed within a rule set: ${JSON.stringify(actionRule)}`
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
399
|
}
|
|
@@ -497,7 +497,7 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
497
497
|
}
|
|
498
498
|
|
|
499
499
|
// validate alias exists in `uses`
|
|
500
|
-
if (uses
|
|
500
|
+
if (uses?.[parsed.alias] === undefined) {
|
|
501
501
|
throw new DwnError(
|
|
502
502
|
DwnErrorCode.ProtocolsConfigureInvalidRefAlias,
|
|
503
503
|
`'$ref' alias '${parsed.alias}' at protocol path '${ruleSetProtocolPath}' does not exist in the 'uses' map.`
|
|
@@ -543,7 +543,7 @@ export class ProtocolsConfigure extends AbstractMessage<ProtocolsConfigureMessag
|
|
|
543
543
|
);
|
|
544
544
|
}
|
|
545
545
|
|
|
546
|
-
if (uses
|
|
546
|
+
if (uses?.[parsed.alias] === undefined) {
|
|
547
547
|
const errorCode = fieldName === 'role'
|
|
548
548
|
? DwnErrorCode.ProtocolsConfigureInvalidCrossProtocolRole
|
|
549
549
|
: DwnErrorCode.ProtocolsConfigureInvalidCrossProtocolOf;
|
|
@@ -110,7 +110,7 @@ export class RecordsDelete extends AbstractMessage<RecordsDeleteMessage> {
|
|
|
110
110
|
* @param messageStore Used to check if the grant has been revoked.
|
|
111
111
|
*/
|
|
112
112
|
public async authorizeDelegate(recordsWriteToDelete: RecordsWriteMessage, messageStore: MessageStore): Promise<void> {
|
|
113
|
-
const delegatedGrant = PermissionGrant.parse(this.message.authorization
|
|
113
|
+
const delegatedGrant = PermissionGrant.parse(this.message.authorization.authorDelegatedGrant!);
|
|
114
114
|
await RecordsGrantAuthorization.authorizeDelete({
|
|
115
115
|
recordsDeleteMessage : this.message,
|
|
116
116
|
recordsWriteToDelete,
|
|
@@ -135,9 +135,9 @@ export type CreateFromOptions = {
|
|
|
135
135
|
* NOTE: Unable to extend `AbstractMessage` directly because the incompatible `_message` type, which is not just a generic `<M>` type.
|
|
136
136
|
*/
|
|
137
137
|
export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
|
|
138
|
-
private parentContextId: string | undefined;
|
|
138
|
+
private readonly parentContextId: string | undefined;
|
|
139
139
|
|
|
140
|
-
private _message: InternalRecordsWriteMessage;
|
|
140
|
+
private readonly _message: InternalRecordsWriteMessage;
|
|
141
141
|
/**
|
|
142
142
|
* Valid JSON message representing this RecordsWrite.
|
|
143
143
|
* @throws `DwnErrorCode.RecordsWriteMissingSigner` if the message is not signed yet.
|
|
@@ -232,10 +232,10 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
|
|
|
232
232
|
if (message.authorization.ownerSignature !== undefined) {
|
|
233
233
|
// if the message authorization contains owner delegated grant, the owner would be the grantor of the grant
|
|
234
234
|
// else the owner would be the signer of the owner signature
|
|
235
|
-
if (message.authorization.ownerDelegatedGrant
|
|
236
|
-
this._owner = Message.getSigner(message.authorization.ownerDelegatedGrant);
|
|
237
|
-
} else {
|
|
235
|
+
if (message.authorization.ownerDelegatedGrant === undefined) {
|
|
238
236
|
this._owner = Jws.getSignerDid(message.authorization.ownerSignature.signatures[0]);
|
|
237
|
+
} else {
|
|
238
|
+
this._owner = Message.getSigner(message.authorization.ownerDelegatedGrant);
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
this._ownerSignaturePayload = Jws.decodePlainObjectPayload(message.authorization.ownerSignature);
|
|
@@ -321,7 +321,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
|
|
|
321
321
|
protocol : normalizeProtocolUrl(options.protocol),
|
|
322
322
|
protocolPath : options.protocolPath,
|
|
323
323
|
recipient : options.recipient,
|
|
324
|
-
schema : options.schema
|
|
324
|
+
schema : options.schema === undefined ? undefined : normalizeSchemaUrl(options.schema),
|
|
325
325
|
tags : options.tags,
|
|
326
326
|
parentId : RecordsWrite.getRecordIdFromContextId(options.parentContextId),
|
|
327
327
|
dataCid,
|
|
@@ -524,11 +524,11 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
|
|
|
524
524
|
// compute delegated grant ID and author if delegated grant is given
|
|
525
525
|
let delegatedGrantId;
|
|
526
526
|
let authorDid;
|
|
527
|
-
if (delegatedGrant
|
|
527
|
+
if (delegatedGrant === undefined) {
|
|
528
|
+
authorDid = Jws.extractDid(signer.keyId);
|
|
529
|
+
} else {
|
|
528
530
|
delegatedGrantId = await Message.getCid(delegatedGrant);
|
|
529
531
|
authorDid = Jws.getSignerDid(delegatedGrant.authorization.signature.signatures[0]);
|
|
530
|
-
} else {
|
|
531
|
-
authorDid = Jws.extractDid(signer.keyId);
|
|
532
532
|
}
|
|
533
533
|
|
|
534
534
|
const descriptor = this._message.descriptor;
|
|
@@ -549,7 +549,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
|
|
|
549
549
|
// `signature` generation
|
|
550
550
|
const signature = await createSignerSignature({
|
|
551
551
|
recordId : this._message.recordId,
|
|
552
|
-
contextId : this._message.contextId
|
|
552
|
+
contextId : this._message.contextId, // contextId is computed just above, always defined here
|
|
553
553
|
descriptorCid,
|
|
554
554
|
attestation : this._message.attestation,
|
|
555
555
|
encryption : this._message.encryption,
|
|
@@ -872,7 +872,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
|
|
|
872
872
|
public static async fetchInitialRecordsWrite(
|
|
873
873
|
messageStore: MessageStore, tenant: string, recordId: string
|
|
874
874
|
): Promise<RecordsWrite | undefined> {
|
|
875
|
-
return fetchInitialRecordsWrite(messageStore, tenant, recordId)
|
|
875
|
+
return fetchInitialRecordsWrite(messageStore, tenant, recordId);
|
|
876
876
|
}
|
|
877
877
|
|
|
878
878
|
/** Delegate to `fetchInitialRecordsWriteMessage` in `records-write-query.ts`. */
|
|
@@ -4,7 +4,7 @@ import type { MessageSigner } from '../../../types/signer.js';
|
|
|
4
4
|
import { Encoder } from '../../../utils/encoder.js';
|
|
5
5
|
|
|
6
6
|
export class GeneralJwsBuilder {
|
|
7
|
-
private jws: GeneralJws;
|
|
7
|
+
private readonly jws: GeneralJws;
|
|
8
8
|
|
|
9
9
|
private constructor(jws: GeneralJws) {
|
|
10
10
|
this.jws = jws;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Cache } from '../../../types/cache.js';
|
|
2
2
|
import type { GeneralJws } from '../../../types/jws-types.js';
|
|
3
3
|
import type { PublicKeyJwk } from '../../../types/jose-types.js';
|
|
4
|
-
import type { DidResolver, DidVerificationMethod } from '@enbox/dids';
|
|
4
|
+
import type { DidResolutionResult, DidResolver, DidVerificationMethod } from '@enbox/dids';
|
|
5
5
|
|
|
6
6
|
import { Encoder } from '../../../utils/encoder.js';
|
|
7
7
|
import { Jws } from '../../../utils/jws.js';
|
|
@@ -89,12 +89,19 @@ export class GeneralJwsVerifier {
|
|
|
89
89
|
|
|
90
90
|
/**
|
|
91
91
|
* Gets the public key given a fully qualified key ID (`kid`) by resolving the DID to its DID Document.
|
|
92
|
+
*
|
|
93
|
+
* Throws `GeneralJwsVerifierGetPublicKeyNotFound` when the public key cannot be located.
|
|
94
|
+
* The error message distinguishes between two failure modes so callers can tell them apart:
|
|
95
|
+
* 1. DID resolution failed (network error, DID not published, method not supported, etc.).
|
|
96
|
+
* The resolution metadata error code and message are included.
|
|
97
|
+
* 2. DID resolved successfully but the requested `kid` does not match any verification
|
|
98
|
+
* method in the DID Document. The list of available verification method IDs is included.
|
|
92
99
|
*/
|
|
93
100
|
private static async getPublicKey(kid: string, didResolver: DidResolver): Promise<PublicKeyJwk> {
|
|
94
101
|
// `resolve` throws exception if DID is invalid, DID method is not supported,
|
|
95
102
|
// or resolving DID fails
|
|
96
103
|
const did = Jws.extractDid(kid);
|
|
97
|
-
const { didDocument } = await didResolver.resolve(did);
|
|
104
|
+
const { didDocument, didResolutionMetadata } = await didResolver.resolve(did);
|
|
98
105
|
const { verificationMethod: verificationMethods = [] } = didDocument || {};
|
|
99
106
|
|
|
100
107
|
let verificationMethod: DidVerificationMethod | undefined;
|
|
@@ -110,7 +117,10 @@ export class GeneralJwsVerifier {
|
|
|
110
117
|
}
|
|
111
118
|
|
|
112
119
|
if (!verificationMethod) {
|
|
113
|
-
throw new DwnError(
|
|
120
|
+
throw new DwnError(
|
|
121
|
+
DwnErrorCode.GeneralJwsVerifierGetPublicKeyNotFound,
|
|
122
|
+
GeneralJwsVerifier.buildPublicKeyNotFoundMessage(kid, did, didDocument, didResolutionMetadata, verificationMethods),
|
|
123
|
+
);
|
|
114
124
|
}
|
|
115
125
|
|
|
116
126
|
validateJsonSchema('JwkVerificationMethod', verificationMethod);
|
|
@@ -119,4 +129,35 @@ export class GeneralJwsVerifier {
|
|
|
119
129
|
|
|
120
130
|
return publicJwk as PublicKeyJwk;
|
|
121
131
|
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Builds a diagnostic error message for `GeneralJwsVerifierGetPublicKeyNotFound`.
|
|
135
|
+
* Surfaces resolution metadata or available verification methods so operators can
|
|
136
|
+
* distinguish between an unreachable DID and a `kid` mismatch.
|
|
137
|
+
*/
|
|
138
|
+
private static buildPublicKeyNotFoundMessage(
|
|
139
|
+
kid: string,
|
|
140
|
+
did: string,
|
|
141
|
+
didDocument: DidResolutionResult['didDocument'],
|
|
142
|
+
didResolutionMetadata: DidResolutionResult['didResolutionMetadata'] | undefined,
|
|
143
|
+
verificationMethods: DidVerificationMethod[],
|
|
144
|
+
): string {
|
|
145
|
+
const resolutionError = didResolutionMetadata?.error;
|
|
146
|
+
if (resolutionError !== undefined) {
|
|
147
|
+
const resolutionErrorMessage = didResolutionMetadata?.errorMessage;
|
|
148
|
+
const detail = resolutionErrorMessage ? `${resolutionError} — ${resolutionErrorMessage}` : resolutionError;
|
|
149
|
+
return `unable to resolve DID '${did}' to verify signature with kid '${kid}': ${detail}`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (didDocument === undefined || didDocument === null) {
|
|
153
|
+
return `DID Document not found for '${did}' when verifying signature with kid '${kid}'`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (verificationMethods.length === 0) {
|
|
157
|
+
return `DID Document for '${did}' has no verification methods to verify signature with kid '${kid}'`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const availableIds = verificationMethods.map((method) => method.id).join(', ');
|
|
161
|
+
return `public key for kid '${kid}' not found in DID Document for '${did}' (available verification methods: [${availableIds}])`;
|
|
162
|
+
}
|
|
122
163
|
}
|
|
@@ -605,7 +605,7 @@ export class PermissionsProtocol implements CoreProtocol {
|
|
|
605
605
|
*/
|
|
606
606
|
private static validateTags(requestOrGrant: RecordsWriteMessage, scopedProtocol: string): void {
|
|
607
607
|
// the protocol tag must be included with the record.
|
|
608
|
-
if (requestOrGrant.descriptor.tags
|
|
608
|
+
if (requestOrGrant.descriptor.tags?.protocol === undefined) {
|
|
609
609
|
throw new DwnError(
|
|
610
610
|
DwnErrorCode.PermissionsProtocolValidateScopeMissingProtocolTag,
|
|
611
611
|
'Permission grants must have a `tags` property that contains a protocol tag'
|
|
@@ -31,7 +31,7 @@ type SerializedLeafNode = {
|
|
|
31
31
|
type SerializedNode = SerializedInternalNode | SerializedLeafNode;
|
|
32
32
|
|
|
33
33
|
export class SMTStoreLevel implements SMTNodeStore {
|
|
34
|
-
private db: LevelWrapper<string>;
|
|
34
|
+
private readonly db: LevelWrapper<string>;
|
|
35
35
|
private nodesPartition!: LevelWrapper<string>;
|
|
36
36
|
private metaPartition!: LevelWrapper<string>;
|
|
37
37
|
private initialized = false;
|
|
@@ -8,7 +8,7 @@ import type { Hash, SMTNode, SMTNodeStore } from '../types/smt-types.js';
|
|
|
8
8
|
import { hashToHex } from './smt-utils.js';
|
|
9
9
|
|
|
10
10
|
export class SMTStoreMemory implements SMTNodeStore {
|
|
11
|
-
private nodes: Map<string, SMTNode> = new Map();
|
|
11
|
+
private readonly nodes: Map<string, SMTNode> = new Map();
|
|
12
12
|
private root: Hash | undefined;
|
|
13
13
|
|
|
14
14
|
async open(): Promise<void> {
|
|
@@ -19,7 +19,7 @@ import type { Hash, SMTDiffResult, SMTInternalNode, SMTLeafNode, SMTNodeStore, S
|
|
|
19
19
|
import { getBit, hashChildren, hashEquals, hashKey, hashLeaf, initDefaultHashes, SMT_DEPTH } from './smt-utils.js';
|
|
20
20
|
|
|
21
21
|
export class SparseMerkleTree {
|
|
22
|
-
private store: SMTNodeStore;
|
|
22
|
+
private readonly store: SMTNodeStore;
|
|
23
23
|
private defaultHashes!: Hash[];
|
|
24
24
|
|
|
25
25
|
constructor(store: SMTNodeStore) {
|
|
@@ -142,13 +142,13 @@ export class SparseMerkleTree {
|
|
|
142
142
|
// subtree hash would be if this leaf were pushed down to the prefix depth.
|
|
143
143
|
// For simplicity, if we've hit a leaf, the subtree at this prefix
|
|
144
144
|
// either contains this leaf or is empty.
|
|
145
|
-
if (node
|
|
145
|
+
if (node?.type === 'leaf') {
|
|
146
146
|
return this.computeSubtreeHashForLeaf(node, i, prefix);
|
|
147
147
|
}
|
|
148
148
|
return this.defaultHashes[prefix.length];
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
const internalNode = node
|
|
151
|
+
const internalNode = node;
|
|
152
152
|
if (prefix[i]) {
|
|
153
153
|
currentHash = internalNode.rightHash;
|
|
154
154
|
} else {
|
|
@@ -186,7 +186,7 @@ export class SparseMerkleTree {
|
|
|
186
186
|
return [];
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
const internalNode = node
|
|
189
|
+
const internalNode = node;
|
|
190
190
|
if (prefix[i]) {
|
|
191
191
|
currentHash = internalNode.rightHash;
|
|
192
192
|
} else {
|
|
@@ -266,7 +266,7 @@ export class SparseMerkleTree {
|
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
// Internal node — recurse into the appropriate child
|
|
269
|
-
const internalNode = node
|
|
269
|
+
const internalNode = node;
|
|
270
270
|
const goRight = getBit(keyHash, depth);
|
|
271
271
|
|
|
272
272
|
let newLeftHash: Hash;
|
|
@@ -405,7 +405,7 @@ export class SparseMerkleTree {
|
|
|
405
405
|
}
|
|
406
406
|
|
|
407
407
|
// Internal node — recurse into the appropriate child
|
|
408
|
-
const internalNode = node
|
|
408
|
+
const internalNode = node;
|
|
409
409
|
const goRight = getBit(keyHash, depth);
|
|
410
410
|
|
|
411
411
|
let newLeftHash: Hash;
|
|
@@ -433,7 +433,7 @@ export class SparseMerkleTree {
|
|
|
433
433
|
if (leftIsDefault || rightIsDefault) {
|
|
434
434
|
const survivingHash = leftIsDefault ? newRightHash : newLeftHash;
|
|
435
435
|
const survivingNode = await this.store.getNode(survivingHash);
|
|
436
|
-
if (survivingNode
|
|
436
|
+
if (survivingNode?.type === 'leaf') {
|
|
437
437
|
// Collapse: remove the internal node, return the leaf hash directly
|
|
438
438
|
await this.store.deleteNode(currentHash);
|
|
439
439
|
return survivingHash;
|
|
@@ -477,7 +477,7 @@ export class SparseMerkleTree {
|
|
|
477
477
|
return hashEquals(node.keyHash, keyHash);
|
|
478
478
|
}
|
|
479
479
|
|
|
480
|
-
const internalNode = node
|
|
480
|
+
const internalNode = node;
|
|
481
481
|
const goRight = getBit(keyHash, depth);
|
|
482
482
|
|
|
483
483
|
if (goRight) {
|
|
@@ -508,7 +508,7 @@ export class SparseMerkleTree {
|
|
|
508
508
|
return { siblings: [], leafNode: node, depth };
|
|
509
509
|
}
|
|
510
510
|
|
|
511
|
-
const internalNode = node
|
|
511
|
+
const internalNode = node;
|
|
512
512
|
const goRight = getBit(keyHash, depth);
|
|
513
513
|
|
|
514
514
|
let childHash: Hash;
|
|
@@ -578,7 +578,7 @@ export class SparseMerkleTree {
|
|
|
578
578
|
return [node.valueCid];
|
|
579
579
|
}
|
|
580
580
|
|
|
581
|
-
const internalNode = node
|
|
581
|
+
const internalNode = node;
|
|
582
582
|
const leftLeaves = await this.collectLeaves(internalNode.leftHash, depth + 1);
|
|
583
583
|
const rightLeaves = await this.collectLeaves(internalNode.rightHash, depth + 1);
|
|
584
584
|
|
|
@@ -28,7 +28,7 @@ export type StateIndexLevelConfig = {
|
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
export class StateIndexLevel implements StateIndex {
|
|
31
|
-
private config: StateIndexLevelConfig;
|
|
31
|
+
private readonly config: StateIndexLevelConfig;
|
|
32
32
|
private db!: LevelWrapper<string>;
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -36,13 +36,13 @@ export class StateIndexLevel implements StateIndex {
|
|
|
36
36
|
* Stores promises to avoid race conditions when multiple concurrent operations
|
|
37
37
|
* trigger lazy initialization of the same tenant's SMT.
|
|
38
38
|
*/
|
|
39
|
-
private globalTrees: Map<string, Promise<SparseMerkleTree>> = new Map();
|
|
39
|
+
private readonly globalTrees: Map<string, Promise<SparseMerkleTree>> = new Map();
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Cache of per-tenant, per-protocol SMTs. Key format: `{tenant}\x00{protocol}`
|
|
43
43
|
* Stores promises to avoid race conditions (same reason as globalTrees).
|
|
44
44
|
*/
|
|
45
|
-
private protocolTrees: Map<string, Promise<SparseMerkleTree>> = new Map();
|
|
45
|
+
private readonly protocolTrees: Map<string, Promise<SparseMerkleTree>> = new Map();
|
|
46
46
|
|
|
47
47
|
constructor(config?: StateIndexLevelConfig) {
|
|
48
48
|
this.config = {
|
|
@@ -203,28 +203,28 @@ export async function queryWithCompoundIndex(
|
|
|
203
203
|
// determine the iterator bounds from the prefix
|
|
204
204
|
const iteratorOptions: LevelWrapperIteratorOptions<string> = {};
|
|
205
205
|
|
|
206
|
-
if (cursor
|
|
207
|
-
// build the full compound key for the cursor position
|
|
208
|
-
const cursorSortEncoded = encodeValue(cursor.value);
|
|
209
|
-
const cursorKey = prefix + cursorSortEncoded + delimiter + cursor.messageCid;
|
|
210
|
-
|
|
206
|
+
if (cursor === undefined) {
|
|
211
207
|
if (sortDirection === SortDirection.Ascending) {
|
|
212
|
-
iteratorOptions.gt =
|
|
213
|
-
// upper bound: everything with this prefix (prefix + \xff is past all valid compound keys with this prefix)
|
|
208
|
+
iteratorOptions.gt = prefix;
|
|
214
209
|
iteratorOptions.lt = prefix + '\xff';
|
|
215
210
|
} else {
|
|
216
|
-
|
|
211
|
+
// for descending without cursor, start from the end of the prefix range
|
|
217
212
|
iteratorOptions.gt = prefix;
|
|
213
|
+
iteratorOptions.lt = prefix + '\xff';
|
|
218
214
|
iteratorOptions.reverse = true;
|
|
219
215
|
}
|
|
220
216
|
} else {
|
|
217
|
+
// build the full compound key for the cursor position
|
|
218
|
+
const cursorSortEncoded = encodeValue(cursor.value);
|
|
219
|
+
const cursorKey = prefix + cursorSortEncoded + delimiter + cursor.messageCid;
|
|
220
|
+
|
|
221
221
|
if (sortDirection === SortDirection.Ascending) {
|
|
222
|
-
iteratorOptions.gt =
|
|
222
|
+
iteratorOptions.gt = cursorKey;
|
|
223
|
+
// upper bound: everything with this prefix (prefix + \xff is past all valid compound keys with this prefix)
|
|
223
224
|
iteratorOptions.lt = prefix + '\xff';
|
|
224
225
|
} else {
|
|
225
|
-
|
|
226
|
+
iteratorOptions.lt = cursorKey;
|
|
226
227
|
iteratorOptions.gt = prefix;
|
|
227
|
-
iteratorOptions.lt = prefix + '\xff';
|
|
228
228
|
iteratorOptions.reverse = true;
|
|
229
229
|
}
|
|
230
230
|
}
|
package/src/store/index-level.ts
CHANGED
|
@@ -53,7 +53,7 @@ export interface IndexLevelOptions {
|
|
|
53
53
|
export class IndexLevel {
|
|
54
54
|
db: LevelWrapper<string>;
|
|
55
55
|
config: IndexLevelConfig;
|
|
56
|
-
private _compoundIndexes: CompoundIndexDefinition[];
|
|
56
|
+
private readonly _compoundIndexes: CompoundIndexDefinition[];
|
|
57
57
|
|
|
58
58
|
constructor(config: IndexLevelConfig) {
|
|
59
59
|
this.config = {
|
|
@@ -498,13 +498,13 @@ export class IndexLevel {
|
|
|
498
498
|
|
|
499
499
|
const sortedValues = [...matches.values()].sort((a,b) => this.sortItems(a,b, sortProperty, sortDirection));
|
|
500
500
|
|
|
501
|
-
const start = cursorStartingKey
|
|
501
|
+
const start = cursorStartingKey === undefined ? 0 : this.findCursorStartingIndex(sortedValues, sortDirection, sortProperty, cursorStartingKey);
|
|
502
502
|
if (start < 0) {
|
|
503
503
|
// if the provided cursor does not come before any of the results, we return no results
|
|
504
504
|
return [];
|
|
505
505
|
}
|
|
506
506
|
|
|
507
|
-
const end = limit
|
|
507
|
+
const end = limit === undefined ? undefined : start + limit;
|
|
508
508
|
return sortedValues.slice(start, end);
|
|
509
509
|
}
|
|
510
510
|
|
|
@@ -735,7 +735,7 @@ export class IndexLevel {
|
|
|
735
735
|
/**
|
|
736
736
|
* Joins the given values using the `\x00` (\u0000) character.
|
|
737
737
|
*/
|
|
738
|
-
private static delimiter = `\x00`;
|
|
738
|
+
private static readonly delimiter = `\x00`;
|
|
739
739
|
private static keySegmentJoin(...values: string[]): string {
|
|
740
740
|
return values.join(IndexLevel.delimiter);
|
|
741
741
|
}
|
|
@@ -183,7 +183,7 @@ export class LevelWrapper<V> {
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
async isEmpty(options?: LevelWrapperOptions): Promise<boolean> {
|
|
186
|
-
for await (const _key of this.keys(options)) {
|
|
186
|
+
for await (const _key of this.keys(options)) { // NOSONAR — intentional single-iteration check
|
|
187
187
|
return false;
|
|
188
188
|
}
|
|
189
189
|
return true;
|