@enbox/dwn-sdk-js 0.4.0 → 0.4.1
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/README.md +4 -4
- package/dist/browser.mjs +8 -8
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/generated/precompiled-validators.js +799 -885
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/dwn-constant.js +5 -0
- package/dist/esm/src/core/dwn-constant.js.map +1 -1
- package/dist/esm/src/core/dwn-error.js +12 -4
- package/dist/esm/src/core/dwn-error.js.map +1 -1
- package/dist/esm/src/core/grant-authorization.js +9 -18
- package/dist/esm/src/core/grant-authorization.js.map +1 -1
- package/dist/esm/src/core/message-reply.js.map +1 -1
- package/dist/esm/src/core/messages-grant-authorization.js +28 -45
- package/dist/esm/src/core/messages-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-action.js +25 -27
- package/dist/esm/src/core/protocol-authorization-action.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization-validation.js +30 -68
- package/dist/esm/src/core/protocol-authorization-validation.js.map +1 -1
- package/dist/esm/src/core/protocol-authorization.js +44 -118
- package/dist/esm/src/core/protocol-authorization.js.map +1 -1
- package/dist/esm/src/core/protocols-grant-authorization.js +5 -5
- package/dist/esm/src/core/protocols-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/recording-validation-state-reader.js +84 -0
- package/dist/esm/src/core/recording-validation-state-reader.js.map +1 -0
- package/dist/esm/src/core/records-grant-authorization.js +11 -11
- package/dist/esm/src/core/records-grant-authorization.js.map +1 -1
- package/dist/esm/src/core/replication-apply.js +123 -28
- package/dist/esm/src/core/replication-apply.js.map +1 -1
- package/dist/esm/src/core/resumable-task-manager.js +5 -4
- package/dist/esm/src/core/resumable-task-manager.js.map +1 -1
- package/dist/esm/src/core/validation-state-reader.js +237 -0
- package/dist/esm/src/core/validation-state-reader.js.map +1 -0
- package/dist/esm/src/dwn.js +165 -132
- package/dist/esm/src/dwn.js.map +1 -1
- package/dist/esm/src/enums/dwn-interface-method.js +0 -1
- package/dist/esm/src/enums/dwn-interface-method.js.map +1 -1
- package/dist/esm/src/event-stream/durable-event-log.js +365 -0
- package/dist/esm/src/event-stream/durable-event-log.js.map +1 -0
- package/dist/esm/src/event-stream/event-emitter-wake-publisher.js +25 -0
- package/dist/esm/src/event-stream/event-emitter-wake-publisher.js.map +1 -0
- package/dist/esm/src/handlers/messages-query.js +159 -0
- package/dist/esm/src/handlers/messages-query.js.map +1 -0
- package/dist/esm/src/handlers/messages-read.js +5 -5
- package/dist/esm/src/handlers/messages-read.js.map +1 -1
- package/dist/esm/src/handlers/messages-subscribe.js +8 -8
- package/dist/esm/src/handlers/messages-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/protocols-configure.js +30 -49
- package/dist/esm/src/handlers/protocols-configure.js.map +1 -1
- package/dist/esm/src/handlers/protocols-query.js +1 -1
- package/dist/esm/src/handlers/protocols-query.js.map +1 -1
- package/dist/esm/src/handlers/records-count.js +20 -11
- package/dist/esm/src/handlers/records-count.js.map +1 -1
- package/dist/esm/src/handlers/records-delete.js +20 -16
- package/dist/esm/src/handlers/records-delete.js.map +1 -1
- package/dist/esm/src/handlers/records-query.js +35 -11
- package/dist/esm/src/handlers/records-query.js.map +1 -1
- package/dist/esm/src/handlers/records-read.js +52 -42
- package/dist/esm/src/handlers/records-read.js.map +1 -1
- package/dist/esm/src/handlers/records-subscribe.js +107 -11
- package/dist/esm/src/handlers/records-subscribe.js.map +1 -1
- package/dist/esm/src/handlers/records-write.js +62 -116
- package/dist/esm/src/handlers/records-write.js.map +1 -1
- package/dist/esm/src/index.js +6 -7
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/interfaces/{messages-sync.js → messages-query.js} +21 -15
- package/dist/esm/src/interfaces/messages-query.js.map +1 -0
- package/dist/esm/src/interfaces/protocols-configure.js +7 -3
- package/dist/esm/src/interfaces/protocols-configure.js.map +1 -1
- package/dist/esm/src/interfaces/protocols-query.js +3 -4
- package/dist/esm/src/interfaces/protocols-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-count.js +4 -3
- package/dist/esm/src/interfaces/records-count.js.map +1 -1
- package/dist/esm/src/interfaces/records-delete.js +21 -4
- package/dist/esm/src/interfaces/records-delete.js.map +1 -1
- package/dist/esm/src/interfaces/records-query.js +4 -3
- package/dist/esm/src/interfaces/records-query.js.map +1 -1
- package/dist/esm/src/interfaces/records-read.js +3 -3
- package/dist/esm/src/interfaces/records-read.js.map +1 -1
- package/dist/esm/src/interfaces/records-subscribe.js +4 -3
- package/dist/esm/src/interfaces/records-subscribe.js.map +1 -1
- package/dist/esm/src/interfaces/records-write.js +27 -13
- package/dist/esm/src/interfaces/records-write.js.map +1 -1
- package/dist/esm/src/protocols/permissions.js +27 -34
- package/dist/esm/src/protocols/permissions.js.map +1 -1
- package/dist/esm/src/store/index-level.js +24 -9
- package/dist/esm/src/store/index-level.js.map +1 -1
- package/dist/esm/src/store/level-wrapper.js +7 -0
- package/dist/esm/src/store/level-wrapper.js.map +1 -1
- package/dist/esm/src/store/message-store-level.js +536 -42
- package/dist/esm/src/store/message-store-level.js.map +1 -1
- package/dist/esm/src/store/storage-controller.js +58 -49
- package/dist/esm/src/store/storage-controller.js.map +1 -1
- package/dist/esm/src/types/message-types.js.map +1 -1
- package/dist/esm/src/types/validation-state-reader.js +2 -0
- package/dist/esm/src/types/validation-state-reader.js.map +1 -0
- package/dist/esm/src/utils/messages.js +17 -0
- package/dist/esm/src/utils/messages.js.map +1 -1
- package/dist/esm/src/utils/record-limit-occupancy.js +244 -0
- package/dist/esm/src/utils/record-limit-occupancy.js.map +1 -0
- package/dist/esm/src/utils/records.js +50 -14
- package/dist/esm/src/utils/records.js.map +1 -1
- package/dist/esm/src/utils/replication.js +85 -0
- package/dist/esm/src/utils/replication.js.map +1 -0
- package/dist/esm/tests/core/grant-authorization.spec.js +4 -4
- package/dist/esm/tests/core/grant-authorization.spec.js.map +1 -1
- package/dist/esm/tests/core/process-message-parity.spec.js +222 -0
- package/dist/esm/tests/core/process-message-parity.spec.js.map +1 -0
- package/dist/esm/tests/core/protocol-authorization.spec.js +5 -2
- package/dist/esm/tests/core/protocol-authorization.spec.js.map +1 -1
- package/dist/esm/tests/core/records-grant-authorization.spec.js +5 -5
- package/dist/esm/tests/core/records-grant-authorization.spec.js.map +1 -1
- package/dist/esm/tests/core/replication-apply.spec.js +55 -1
- package/dist/esm/tests/core/replication-apply.spec.js.map +1 -1
- package/dist/esm/tests/core/replication-replay-property.spec.js +350 -0
- package/dist/esm/tests/core/replication-replay-property.spec.js.map +1 -0
- package/dist/esm/tests/core/validation-read-closure.spec.js +469 -0
- package/dist/esm/tests/core/validation-read-closure.spec.js.map +1 -0
- package/dist/esm/tests/core/validation-state-reader.spec.js +716 -0
- package/dist/esm/tests/core/validation-state-reader.spec.js.map +1 -0
- package/dist/esm/tests/durable-event-log.spec.js +373 -0
- package/dist/esm/tests/durable-event-log.spec.js.map +1 -0
- package/dist/esm/tests/dwn.spec.js +504 -35
- package/dist/esm/tests/dwn.spec.js.map +1 -1
- package/dist/esm/tests/features/author-delegated-grant.spec.js +9 -6
- package/dist/esm/tests/features/author-delegated-grant.spec.js.map +1 -1
- package/dist/esm/tests/features/owner-delegated-grant.spec.js +1 -4
- package/dist/esm/tests/features/owner-delegated-grant.spec.js.map +1 -1
- package/dist/esm/tests/features/owner-signature.spec.js +1 -4
- package/dist/esm/tests/features/owner-signature.spec.js.map +1 -1
- package/dist/esm/tests/features/permissions.spec.js +165 -4
- package/dist/esm/tests/features/permissions.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-composition.spec.js +8 -11
- package/dist/esm/tests/features/protocol-composition.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-create-action.spec.js +1 -4
- package/dist/esm/tests/features/protocol-create-action.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-delete-action.spec.js +3 -5
- package/dist/esm/tests/features/protocol-delete-action.spec.js.map +1 -1
- package/dist/esm/tests/features/protocol-update-action.spec.js +3 -6
- package/dist/esm/tests/features/protocol-update-action.spec.js.map +1 -1
- package/dist/esm/tests/features/records-delivery.spec.js +1 -4
- package/dist/esm/tests/features/records-delivery.spec.js.map +1 -1
- package/dist/esm/tests/features/records-immutable.spec.js +1 -4
- package/dist/esm/tests/features/records-immutable.spec.js.map +1 -1
- package/dist/esm/tests/features/records-nested-query-scope.spec.js +281 -0
- package/dist/esm/tests/features/records-nested-query-scope.spec.js.map +1 -0
- package/dist/esm/tests/features/records-prune-cross-protocol.spec.js +3 -7
- package/dist/esm/tests/features/records-prune-cross-protocol.spec.js.map +1 -1
- package/dist/esm/tests/features/records-prune.spec.js +11 -22
- package/dist/esm/tests/features/records-prune.spec.js.map +1 -1
- package/dist/esm/tests/features/records-record-limit.spec.js +441 -231
- package/dist/esm/tests/features/records-record-limit.spec.js.map +1 -1
- package/dist/esm/tests/features/records-squash.spec.js +6 -4
- package/dist/esm/tests/features/records-squash.spec.js.map +1 -1
- package/dist/esm/tests/features/records-tags.spec.js +1 -4
- package/dist/esm/tests/features/records-tags.spec.js.map +1 -1
- package/dist/esm/tests/features/resumable-tasks.spec.js +3 -5
- package/dist/esm/tests/features/resumable-tasks.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/message-store.fuzz.spec.js +1 -2
- package/dist/esm/tests/fuzz/message-store.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/process-message.fuzz.spec.js +2 -4
- package/dist/esm/tests/fuzz/process-message.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/fuzz/schema-validation.fuzz.spec.js +1 -1
- package/dist/esm/tests/fuzz/schema-validation.fuzz.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-query.spec.js +246 -0
- package/dist/esm/tests/handlers/messages-query.spec.js.map +1 -0
- package/dist/esm/tests/handlers/messages-read.spec.js +2 -5
- package/dist/esm/tests/handlers/messages-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/messages-subscribe.spec.js +3 -14
- package/dist/esm/tests/handlers/messages-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-configure.spec.js +27 -26
- package/dist/esm/tests/handlers/protocols-configure.spec.js.map +1 -1
- package/dist/esm/tests/handlers/protocols-query.spec.js +1 -4
- package/dist/esm/tests/handlers/protocols-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-count.spec.js +1 -4
- package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-delete.spec.js +312 -30
- package/dist/esm/tests/handlers/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-query.spec.js +32 -9
- package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +4 -4
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +33 -14
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-write.spec.js +82 -36
- package/dist/esm/tests/handlers/records-write.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-delete.spec.js +69 -2
- package/dist/esm/tests/interfaces/records-delete.spec.js.map +1 -1
- package/dist/esm/tests/interfaces/records-write.spec.js +4 -3
- package/dist/esm/tests/interfaces/records-write.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permissions.spec.js +55 -6
- package/dist/esm/tests/protocols/permissions.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/aggregator.spec.js +1 -4
- package/dist/esm/tests/scenarios/aggregator.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/deleted-record.spec.js +1 -4
- package/dist/esm/tests/scenarios/deleted-record.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js +1 -4
- package/dist/esm/tests/scenarios/end-to-end-tests.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/nested-roles.spec.js +1 -4
- package/dist/esm/tests/scenarios/nested-roles.spec.js.map +1 -1
- package/dist/esm/tests/scenarios/subscriptions.spec.js +1 -4
- package/dist/esm/tests/scenarios/subscriptions.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store-level.spec.js +361 -5
- package/dist/esm/tests/store/message-store-level.spec.js.map +1 -1
- package/dist/esm/tests/store/message-store.spec.js +60 -0
- package/dist/esm/tests/store/message-store.spec.js.map +1 -1
- package/dist/esm/tests/test-event-stream.js +7 -3
- package/dist/esm/tests/test-event-stream.js.map +1 -1
- package/dist/esm/tests/test-stores.js +19 -9
- package/dist/esm/tests/test-stores.js.map +1 -1
- package/dist/esm/tests/test-suite.js +4 -2
- package/dist/esm/tests/test-suite.js.map +1 -1
- package/dist/esm/tests/utils/test-data-generator.js +25 -0
- package/dist/esm/tests/utils/test-data-generator.js.map +1 -1
- package/dist/esm/tests/utils/test-stub-generator.js.map +1 -1
- package/dist/esm/tests/utils/test-validation-state-reader.js +16 -0
- package/dist/esm/tests/utils/test-validation-state-reader.js.map +1 -0
- package/dist/types/generated/precompiled-validators.d.ts +6 -6
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/core-protocol.d.ts +3 -3
- package/dist/types/src/core/core-protocol.d.ts.map +1 -1
- package/dist/types/src/core/dwn-constant.d.ts +5 -0
- package/dist/types/src/core/dwn-constant.d.ts.map +1 -1
- package/dist/types/src/core/dwn-error.d.ts +12 -4
- package/dist/types/src/core/dwn-error.d.ts.map +1 -1
- package/dist/types/src/core/grant-authorization.d.ts +5 -5
- package/dist/types/src/core/grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/message-reply.d.ts +5 -4
- package/dist/types/src/core/message-reply.d.ts.map +1 -1
- package/dist/types/src/core/messages-grant-authorization.d.ts +12 -14
- package/dist/types/src/core/messages-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization-action.d.ts +4 -5
- package/dist/types/src/core/protocol-authorization-action.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization-validation.d.ts +13 -16
- package/dist/types/src/core/protocol-authorization-validation.d.ts.map +1 -1
- package/dist/types/src/core/protocol-authorization.d.ts +8 -33
- package/dist/types/src/core/protocol-authorization.d.ts.map +1 -1
- package/dist/types/src/core/protocols-grant-authorization.d.ts +4 -4
- package/dist/types/src/core/protocols-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/recording-validation-state-reader.d.ts +75 -0
- package/dist/types/src/core/recording-validation-state-reader.d.ts.map +1 -0
- package/dist/types/src/core/records-grant-authorization.d.ts +8 -8
- package/dist/types/src/core/records-grant-authorization.d.ts.map +1 -1
- package/dist/types/src/core/replication-apply.d.ts +36 -0
- package/dist/types/src/core/replication-apply.d.ts.map +1 -1
- package/dist/types/src/core/resumable-task-manager.d.ts +1 -1
- package/dist/types/src/core/resumable-task-manager.d.ts.map +1 -1
- package/dist/types/src/core/validation-state-reader.d.ts +79 -0
- package/dist/types/src/core/validation-state-reader.d.ts.map +1 -0
- package/dist/types/src/dwn.d.ts +33 -20
- package/dist/types/src/dwn.d.ts.map +1 -1
- package/dist/types/src/enums/dwn-interface-method.d.ts +0 -1
- package/dist/types/src/enums/dwn-interface-method.d.ts.map +1 -1
- package/dist/types/src/event-stream/durable-event-log.d.ts +69 -0
- package/dist/types/src/event-stream/durable-event-log.d.ts.map +1 -0
- package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts +13 -0
- package/dist/types/src/event-stream/event-emitter-wake-publisher.d.ts.map +1 -0
- package/dist/types/src/handlers/messages-query.d.ts +20 -0
- package/dist/types/src/handlers/messages-query.d.ts.map +1 -0
- 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.map +1 -1
- package/dist/types/src/handlers/protocols-configure.d.ts +0 -5
- package/dist/types/src/handlers/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/handlers/records-count.d.ts +2 -1
- package/dist/types/src/handlers/records-count.d.ts.map +1 -1
- package/dist/types/src/handlers/records-delete.d.ts +2 -2
- 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 +2 -1
- package/dist/types/src/handlers/records-read.d.ts.map +1 -1
- package/dist/types/src/handlers/records-subscribe.d.ts +4 -5
- package/dist/types/src/handlers/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/handlers/records-write.d.ts +3 -11
- package/dist/types/src/handlers/records-write.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +14 -16
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/interfaces/messages-query.d.ts +23 -0
- package/dist/types/src/interfaces/messages-query.d.ts.map +1 -0
- package/dist/types/src/interfaces/protocols-configure.d.ts +3 -3
- package/dist/types/src/interfaces/protocols-configure.d.ts.map +1 -1
- package/dist/types/src/interfaces/protocols-query.d.ts +2 -2
- package/dist/types/src/interfaces/protocols-query.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-count.d.ts +3 -3
- package/dist/types/src/interfaces/records-count.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-delete.d.ts +11 -3
- package/dist/types/src/interfaces/records-delete.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-query.d.ts +3 -3
- package/dist/types/src/interfaces/records-query.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-read.d.ts +3 -3
- package/dist/types/src/interfaces/records-read.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-subscribe.d.ts +3 -3
- package/dist/types/src/interfaces/records-subscribe.d.ts.map +1 -1
- package/dist/types/src/interfaces/records-write.d.ts +15 -7
- package/dist/types/src/interfaces/records-write.d.ts.map +1 -1
- package/dist/types/src/protocols/permissions.d.ts +9 -12
- package/dist/types/src/protocols/permissions.d.ts.map +1 -1
- package/dist/types/src/store/index-level.d.ts +10 -1
- package/dist/types/src/store/index-level.d.ts.map +1 -1
- package/dist/types/src/store/level-wrapper.d.ts +5 -0
- package/dist/types/src/store/level-wrapper.d.ts.map +1 -1
- package/dist/types/src/store/message-store-level.d.ts +94 -14
- package/dist/types/src/store/message-store-level.d.ts.map +1 -1
- package/dist/types/src/store/storage-controller.d.ts +17 -14
- package/dist/types/src/store/storage-controller.d.ts.map +1 -1
- package/dist/types/src/types/message-store.d.ts +29 -1
- package/dist/types/src/types/message-store.d.ts.map +1 -1
- package/dist/types/src/types/message-types.d.ts +2 -0
- package/dist/types/src/types/message-types.d.ts.map +1 -1
- package/dist/types/src/types/messages-types.d.ts +21 -37
- package/dist/types/src/types/messages-types.d.ts.map +1 -1
- package/dist/types/src/types/method-handler.d.ts +2 -2
- package/dist/types/src/types/method-handler.d.ts.map +1 -1
- package/dist/types/src/types/permission-types.d.ts +1 -1
- package/dist/types/src/types/subscriptions.d.ts +50 -39
- package/dist/types/src/types/subscriptions.d.ts.map +1 -1
- package/dist/types/src/types/validation-state-reader.d.ts +116 -0
- package/dist/types/src/types/validation-state-reader.d.ts.map +1 -0
- package/dist/types/src/utils/messages.d.ts +10 -0
- package/dist/types/src/utils/messages.d.ts.map +1 -1
- package/dist/types/src/utils/record-limit-occupancy.d.ts +40 -0
- package/dist/types/src/utils/record-limit-occupancy.d.ts.map +1 -0
- package/dist/types/src/utils/records.d.ts +25 -3
- package/dist/types/src/utils/records.d.ts.map +1 -1
- package/dist/types/src/utils/replication.d.ts +22 -0
- package/dist/types/src/utils/replication.d.ts.map +1 -0
- package/dist/types/tests/core/process-message-parity.spec.d.ts +2 -0
- package/dist/types/tests/core/process-message-parity.spec.d.ts.map +1 -0
- package/dist/types/tests/core/replication-replay-property.spec.d.ts +2 -0
- package/dist/types/tests/core/replication-replay-property.spec.d.ts.map +1 -0
- package/dist/types/tests/core/validation-read-closure.spec.d.ts +2 -0
- package/dist/types/tests/core/validation-read-closure.spec.d.ts.map +1 -0
- package/dist/types/tests/core/validation-state-reader.spec.d.ts +2 -0
- package/dist/types/tests/core/validation-state-reader.spec.d.ts.map +1 -0
- package/dist/types/tests/durable-event-log.spec.d.ts +2 -0
- package/dist/types/tests/durable-event-log.spec.d.ts.map +1 -0
- package/dist/types/tests/dwn.spec.d.ts.map +1 -1
- package/dist/types/tests/features/author-delegated-grant.spec.d.ts.map +1 -1
- package/dist/types/tests/features/owner-delegated-grant.spec.d.ts.map +1 -1
- package/dist/types/tests/features/owner-signature.spec.d.ts.map +1 -1
- package/dist/types/tests/features/permissions.spec.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-composition.spec.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-create-action.spec.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-delete-action.spec.d.ts.map +1 -1
- package/dist/types/tests/features/protocol-update-action.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-delivery.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-immutable.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-nested-query-scope.spec.d.ts +2 -0
- package/dist/types/tests/features/records-nested-query-scope.spec.d.ts.map +1 -0
- package/dist/types/tests/features/records-prune-cross-protocol.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-prune.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-record-limit.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-squash.spec.d.ts.map +1 -1
- package/dist/types/tests/features/records-tags.spec.d.ts.map +1 -1
- package/dist/types/tests/features/resumable-tasks.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/messages-query.spec.d.ts +2 -0
- package/dist/types/tests/handlers/messages-query.spec.d.ts.map +1 -0
- package/dist/types/tests/handlers/messages-read.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/messages-subscribe.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/protocols-configure.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/protocols-query.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-delete.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-query.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-read.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/scenarios/deleted-record.spec.d.ts.map +1 -1
- package/dist/types/tests/scenarios/end-to-end-tests.spec.d.ts.map +1 -1
- package/dist/types/tests/scenarios/nested-roles.spec.d.ts.map +1 -1
- package/dist/types/tests/scenarios/subscriptions.spec.d.ts.map +1 -1
- package/dist/types/tests/store/message-store.spec.d.ts.map +1 -1
- package/dist/types/tests/test-event-stream.d.ts +1 -1
- package/dist/types/tests/test-event-stream.d.ts.map +1 -1
- package/dist/types/tests/test-stores.d.ts +5 -4
- package/dist/types/tests/test-stores.d.ts.map +1 -1
- package/dist/types/tests/test-suite.d.ts +1 -2
- package/dist/types/tests/test-suite.d.ts.map +1 -1
- package/dist/types/tests/utils/test-data-generator.d.ts +20 -1
- package/dist/types/tests/utils/test-data-generator.d.ts.map +1 -1
- package/dist/types/tests/utils/test-validation-state-reader.d.ts +15 -0
- package/dist/types/tests/utils/test-validation-state-reader.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/core/core-protocol.ts +3 -3
- package/src/core/dwn-constant.ts +7 -1
- package/src/core/dwn-error.ts +12 -4
- package/src/core/grant-authorization.ts +11 -20
- package/src/core/message-reply.ts +6 -5
- package/src/core/messages-grant-authorization.ts +37 -70
- package/src/core/protocol-authorization-action.ts +29 -38
- package/src/core/protocol-authorization-validation.ts +39 -96
- package/src/core/protocol-authorization.ts +56 -202
- package/src/core/protocols-grant-authorization.ts +9 -9
- package/src/core/recording-validation-state-reader.ts +130 -0
- package/src/core/records-grant-authorization.ts +16 -16
- package/src/core/replication-apply.ts +172 -32
- package/src/core/resumable-task-manager.ts +10 -8
- package/src/core/validation-state-reader.ts +350 -0
- package/src/dwn.ts +285 -192
- package/src/enums/dwn-interface-method.ts +0 -1
- package/src/event-stream/durable-event-log.ts +509 -0
- package/src/event-stream/event-emitter-wake-publisher.ts +34 -0
- package/src/handlers/messages-query.ts +203 -0
- package/src/handlers/messages-read.ts +9 -10
- package/src/handlers/messages-subscribe.ts +12 -13
- package/src/handlers/protocols-configure.ts +37 -58
- package/src/handlers/protocols-query.ts +1 -1
- package/src/handlers/records-count.ts +24 -17
- package/src/handlers/records-delete.ts +29 -27
- package/src/handlers/records-query.ts +38 -17
- package/src/handlers/records-read.ts +63 -50
- package/src/handlers/records-subscribe.ts +132 -19
- package/src/handlers/records-write.ts +77 -168
- package/src/index.ts +14 -17
- package/src/interfaces/messages-query.ts +70 -0
- package/src/interfaces/protocols-configure.ts +12 -4
- package/src/interfaces/protocols-query.ts +4 -5
- package/src/interfaces/records-count.ts +9 -4
- package/src/interfaces/records-delete.ts +25 -5
- package/src/interfaces/records-query.ts +9 -4
- package/src/interfaces/records-read.ts +4 -4
- package/src/interfaces/records-subscribe.ts +9 -4
- package/src/interfaces/records-write.ts +41 -13
- package/src/protocols/permissions.ts +32 -52
- package/src/store/index-level.ts +30 -9
- package/src/store/level-wrapper.ts +9 -1
- package/src/store/message-store-level.ts +757 -47
- package/src/store/storage-controller.ts +74 -63
- package/src/types/message-store.ts +45 -2
- package/src/types/message-types.ts +3 -1
- package/src/types/messages-types.ts +26 -45
- package/src/types/method-handler.ts +3 -3
- package/src/types/permission-types.ts +1 -1
- package/src/types/subscriptions.ts +53 -42
- package/src/types/validation-state-reader.ts +127 -0
- package/src/utils/messages.ts +25 -1
- package/src/utils/record-limit-occupancy.ts +377 -0
- package/src/utils/records.ts +69 -13
- package/src/utils/replication.ts +122 -0
- package/dist/esm/src/core/record-chain.js +0 -64
- package/dist/esm/src/core/record-chain.js.map +0 -1
- package/dist/esm/src/event-stream/event-emitter-event-log.js +0 -334
- package/dist/esm/src/event-stream/event-emitter-event-log.js.map +0 -1
- package/dist/esm/src/handlers/messages-sync.js +0 -278
- package/dist/esm/src/handlers/messages-sync.js.map +0 -1
- package/dist/esm/src/interfaces/messages-sync.js.map +0 -1
- package/dist/esm/src/smt/smt-store-level.js +0 -103
- package/dist/esm/src/smt/smt-store-level.js.map +0 -1
- package/dist/esm/src/smt/smt-store-memory.js +0 -41
- package/dist/esm/src/smt/smt-store-memory.js.map +0 -1
- package/dist/esm/src/smt/smt-utils.js +0 -129
- package/dist/esm/src/smt/smt-utils.js.map +0 -1
- package/dist/esm/src/smt/sparse-merkle-tree.js +0 -577
- package/dist/esm/src/smt/sparse-merkle-tree.js.map +0 -1
- package/dist/esm/src/state-index/state-index-level.js +0 -191
- package/dist/esm/src/state-index/state-index-level.js.map +0 -1
- package/dist/esm/src/types/smt-types.js +0 -5
- package/dist/esm/src/types/smt-types.js.map +0 -1
- package/dist/esm/src/types/state-index.js +0 -2
- package/dist/esm/src/types/state-index.js.map +0 -1
- package/dist/esm/tests/event-emitter-event-log.spec.js +0 -499
- package/dist/esm/tests/event-emitter-event-log.spec.js.map +0 -1
- package/dist/esm/tests/handlers/messages-sync.spec.js +0 -1088
- package/dist/esm/tests/handlers/messages-sync.spec.js.map +0 -1
- package/dist/esm/tests/smt/smt-store-level.spec.js +0 -132
- package/dist/esm/tests/smt/smt-store-level.spec.js.map +0 -1
- package/dist/esm/tests/smt/sparse-merkle-tree.spec.js +0 -732
- package/dist/esm/tests/smt/sparse-merkle-tree.spec.js.map +0 -1
- package/dist/esm/tests/state-index/state-index-level.spec.js +0 -245
- package/dist/esm/tests/state-index/state-index-level.spec.js.map +0 -1
- package/dist/types/src/core/record-chain.d.ts +0 -24
- package/dist/types/src/core/record-chain.d.ts.map +0 -1
- package/dist/types/src/event-stream/event-emitter-event-log.d.ts +0 -80
- package/dist/types/src/event-stream/event-emitter-event-log.d.ts.map +0 -1
- package/dist/types/src/handlers/messages-sync.d.ts +0 -39
- package/dist/types/src/handlers/messages-sync.d.ts.map +0 -1
- package/dist/types/src/interfaces/messages-sync.d.ts +0 -20
- package/dist/types/src/interfaces/messages-sync.d.ts.map +0 -1
- package/dist/types/src/smt/smt-store-level.d.ts +0 -32
- package/dist/types/src/smt/smt-store-level.d.ts.map +0 -1
- package/dist/types/src/smt/smt-store-memory.d.ts +0 -22
- package/dist/types/src/smt/smt-store-memory.d.ts.map +0 -1
- package/dist/types/src/smt/smt-utils.d.ts +0 -58
- package/dist/types/src/smt/smt-utils.d.ts.map +0 -1
- package/dist/types/src/smt/sparse-merkle-tree.d.ts +0 -124
- package/dist/types/src/smt/sparse-merkle-tree.d.ts.map +0 -1
- package/dist/types/src/state-index/state-index-level.d.ts +0 -83
- package/dist/types/src/state-index/state-index-level.d.ts.map +0 -1
- package/dist/types/src/types/smt-types.d.ts +0 -81
- package/dist/types/src/types/smt-types.d.ts.map +0 -1
- package/dist/types/src/types/state-index.d.ts +0 -90
- package/dist/types/src/types/state-index.d.ts.map +0 -1
- package/dist/types/tests/event-emitter-event-log.spec.d.ts +0 -2
- package/dist/types/tests/event-emitter-event-log.spec.d.ts.map +0 -1
- package/dist/types/tests/handlers/messages-sync.spec.d.ts +0 -2
- package/dist/types/tests/handlers/messages-sync.spec.d.ts.map +0 -1
- package/dist/types/tests/smt/smt-store-level.spec.d.ts +0 -2
- package/dist/types/tests/smt/smt-store-level.spec.d.ts.map +0 -1
- package/dist/types/tests/smt/sparse-merkle-tree.spec.d.ts +0 -2
- package/dist/types/tests/smt/sparse-merkle-tree.spec.d.ts.map +0 -1
- package/dist/types/tests/state-index/state-index-level.spec.d.ts +0 -2
- package/dist/types/tests/state-index/state-index-level.spec.d.ts.map +0 -1
- package/src/core/record-chain.ts +0 -99
- package/src/event-stream/event-emitter-event-log.ts +0 -430
- package/src/handlers/messages-sync.ts +0 -403
- package/src/interfaces/messages-sync.ts +0 -69
- package/src/smt/smt-store-level.ts +0 -143
- package/src/smt/smt-store-memory.ts +0 -53
- package/src/smt/smt-utils.ts +0 -149
- package/src/smt/sparse-merkle-tree.ts +0 -698
- package/src/state-index/state-index-level.ts +0 -239
- package/src/types/smt-types.ts +0 -95
- package/src/types/state-index.ts +0 -100
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { GenericMessage } from './message-types.js';
|
|
2
|
+
import type { PermissionGrant } from '../protocols/permission-grant.js';
|
|
3
|
+
import type { ProtocolDefinition } from './protocols-types.js';
|
|
4
|
+
import type { RecordsWrite } from '../interfaces/records-write.js';
|
|
5
|
+
import type { RecordsWriteMessage } from './records-types.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The single narrow surface through which validation logic reads state.
|
|
9
|
+
*
|
|
10
|
+
* Every validation-time state read performed during message admission routes through this
|
|
11
|
+
* interface, so the replay basis (initial writes ∪ latest states ∪ tombstones ∪ protocol-config
|
|
12
|
+
* history ∪ permission records) provably stays closed under admission's read set. Validation
|
|
13
|
+
* modules (`core/protocol-authorization*`, `protocols/permissions*`) are lint-banned from
|
|
14
|
+
* importing `MessageStore` directly; a new protocol-engine feature that needs new state must add
|
|
15
|
+
* a reader method here.
|
|
16
|
+
*/
|
|
17
|
+
export interface ValidationStateReader {
|
|
18
|
+
/**
|
|
19
|
+
* Fetches a record's initial `RecordsWrite` by entry ID, parsed.
|
|
20
|
+
* @returns the initial write, or `undefined` when no message carries the entry ID.
|
|
21
|
+
*/
|
|
22
|
+
fetchInitialRecordsWrite(tenant: string, recordId: string): Promise<RecordsWrite | undefined>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Fetches a record's initial write from among all of the record's writes.
|
|
26
|
+
* @returns the initial write message, or `undefined` when the record has no messages at all.
|
|
27
|
+
* @throws {DwnError} with `RecordsWriteGetInitialWriteNotFound` when writes exist for the
|
|
28
|
+
* record but none of them is the initial write.
|
|
29
|
+
*/
|
|
30
|
+
fetchInitialWrite(tenant: string, recordId: string): Promise<RecordsWriteMessage | undefined>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Constructs the chain of existing records from the root to the given
|
|
34
|
+
* descendant, each represented by its initial `RecordsWrite`.
|
|
35
|
+
* @returns the chain root-first; an empty array when `descendantRecordId` is `undefined`.
|
|
36
|
+
* @throws {DwnError} with `ProtocolAuthorizationParentNotFoundConstructingRecordChain` when any
|
|
37
|
+
* link in the chain is missing.
|
|
38
|
+
*/
|
|
39
|
+
constructRecordChain(tenant: string, descendantRecordId: string | undefined): Promise<RecordsWriteMessage[]>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Fetches the immediate parent record for protocolPath/contextId verification.
|
|
43
|
+
*
|
|
44
|
+
* Queries the latest-state write first — the fast path that excludes deleted parents. If no
|
|
45
|
+
* latest write exists, a retained initial write is sufficient for immutable parent facts
|
|
46
|
+
* (protocolPath/contextId) provided no local tombstone exists for that record.
|
|
47
|
+
* @returns the parent write, or `undefined` when the parent is absent (or deleted).
|
|
48
|
+
*/
|
|
49
|
+
fetchParentRecord(input: {
|
|
50
|
+
tenant: string;
|
|
51
|
+
parentProtocolUri: string;
|
|
52
|
+
parentId: string;
|
|
53
|
+
}): Promise<RecordsWriteMessage | undefined>;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Checks whether a role record matching the invoked-role selector exists.
|
|
57
|
+
* Filter-only — role validation never reads record data. The latest-state match is the fast
|
|
58
|
+
* path. If no latest match exists, a retained initial role write is sufficient for immutable
|
|
59
|
+
* role facts (recipient/path/context) provided no local tombstone exists for that role record.
|
|
60
|
+
*/
|
|
61
|
+
hasMatchingRoleRecord(input: {
|
|
62
|
+
tenant: string;
|
|
63
|
+
protocol: string;
|
|
64
|
+
protocolPath: string;
|
|
65
|
+
recipient: string;
|
|
66
|
+
contextIdPrefix?: string;
|
|
67
|
+
}): Promise<boolean>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Queries the latest-state role records matching the given
|
|
71
|
+
* selector, used to reject duplicate role assignments to the same recipient. Filter-only.
|
|
72
|
+
*/
|
|
73
|
+
queryLatestRoleRecords(input: {
|
|
74
|
+
tenant: string;
|
|
75
|
+
protocol: string;
|
|
76
|
+
protocolPath: string;
|
|
77
|
+
recipient: string;
|
|
78
|
+
contextIdPrefix?: string;
|
|
79
|
+
}): Promise<RecordsWriteMessage[]>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Fetches the permission grant with the given record ID, with its scope parsed from grant data.
|
|
83
|
+
* @throws {DwnError} with `GrantAuthorizationGrantMissing` when the grant does not exist.
|
|
84
|
+
*/
|
|
85
|
+
fetchGrant(tenant: string, permissionGrantId: string): Promise<PermissionGrant>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Fetches the oldest latest-state revocation record for the given permission grant, if any.
|
|
89
|
+
* Grant activity checks compare the oldest revocation timestamp to the incoming message timestamp.
|
|
90
|
+
*/
|
|
91
|
+
fetchOldestGrantRevocation(tenant: string, permissionGrantId: string): Promise<GenericMessage | undefined>;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Fetches the newest `RecordsWrite` associated with a record, used to authorize `Messages.Read`
|
|
95
|
+
* access to `RecordsDelete` messages by projecting the delete back to the deleted record's
|
|
96
|
+
* protocol scope.
|
|
97
|
+
* @throws {DwnError} with `RecordsWriteGetNewestWriteRecordNotFound` when no write exists.
|
|
98
|
+
*/
|
|
99
|
+
fetchNewestRecordsWrite(tenant: string, recordId: string): Promise<RecordsWriteMessage>;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Fetches the protocol definition for the given protocol URI.
|
|
103
|
+
* When `messageTimestamp` is provided, returns the definition active at that point in time —
|
|
104
|
+
* the `ProtocolsConfigure` with the greatest `messageTimestamp` that is <= the given timestamp,
|
|
105
|
+
* read from retained config history. When not provided, returns the latest definition.
|
|
106
|
+
* Core protocol definitions are returned from the registry without a store read.
|
|
107
|
+
* @throws {DwnError} with `ProtocolAuthorizationProtocolNotFound` when no definition exists.
|
|
108
|
+
*/
|
|
109
|
+
fetchProtocolDefinition(tenant: string, protocolUri: string, messageTimestamp?: string): Promise<ProtocolDefinition>;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Fetches the latest `$squash: true` record at a protocol path within the parent context.
|
|
113
|
+
* This is the temporal floor used by the squash backstop.
|
|
114
|
+
*/
|
|
115
|
+
fetchLatestSquashRecordAtScope(input: {
|
|
116
|
+
tenant: string;
|
|
117
|
+
protocol: string;
|
|
118
|
+
protocolPath: string;
|
|
119
|
+
contextIdPrefix?: string;
|
|
120
|
+
}): Promise<RecordsWriteMessage | undefined>;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Checks whether the data with the given CID is present in the `DataStore` for the given record.
|
|
124
|
+
* This is the prior-data integrity check for dataless non-initial writes.
|
|
125
|
+
*/
|
|
126
|
+
hasStoredData(tenant: string, recordId: string, dataCid: string): Promise<boolean>;
|
|
127
|
+
}
|
package/src/utils/messages.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { CoreProtocolRegistry } from '../core/core-protocol.js';
|
|
2
2
|
import type { Filter } from '../types/query-types.js';
|
|
3
|
+
import type { GenericMessage } from '../types/message-types.js';
|
|
3
4
|
import type { MessagesFilter } from '../types/messages-types.js';
|
|
4
5
|
|
|
5
6
|
import { FilterUtility } from './filter.js';
|
|
6
7
|
import { normalizeProtocolUrl } from './url.js';
|
|
8
|
+
import { Records } from './records.js';
|
|
7
9
|
import { isEmptyObject, removeUndefinedProperties } from '@enbox/common';
|
|
8
10
|
|
|
11
|
+
type StoredMessageWithEncodedData = GenericMessage & { encodedData?: string };
|
|
12
|
+
|
|
9
13
|
|
|
10
14
|
/**
|
|
11
15
|
* Class containing Messages related utility methods.
|
|
@@ -95,6 +99,22 @@ export class Messages {
|
|
|
95
99
|
return messagesQueryFilters;
|
|
96
100
|
}
|
|
97
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Returns a copy of a RecordsWrite message without inline encodedData, and the
|
|
104
|
+
* detached encodedData value for wire surfaces that carry data beside the message.
|
|
105
|
+
*/
|
|
106
|
+
public static detachEncodedData(message: GenericMessage): { message: GenericMessage; encodedData?: string } {
|
|
107
|
+
if (!Records.isRecordsWrite(message) || !Messages.hasEncodedData(message)) {
|
|
108
|
+
return { message };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const messageWithoutEncodedData: StoredMessageWithEncodedData = { ...message };
|
|
112
|
+
const { encodedData } = messageWithoutEncodedData;
|
|
113
|
+
delete messageWithoutEncodedData.encodedData;
|
|
114
|
+
|
|
115
|
+
return { message: messageWithoutEncodedData, encodedData };
|
|
116
|
+
}
|
|
117
|
+
|
|
98
118
|
/**
|
|
99
119
|
* Converts an external-facing filter model into an internal-facing filer model used by data store.
|
|
100
120
|
*/
|
|
@@ -132,4 +152,8 @@ export class Messages {
|
|
|
132
152
|
|
|
133
153
|
return filterCopy;
|
|
134
154
|
}
|
|
135
|
-
|
|
155
|
+
|
|
156
|
+
private static hasEncodedData(message: GenericMessage): message is StoredMessageWithEncodedData {
|
|
157
|
+
return 'encodedData' in message && typeof message.encodedData === 'string';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import type { MessageStore } from '../types/message-store.js';
|
|
2
|
+
import type { ProtocolRecordLimitDefinition } from '../types/protocols-types.js';
|
|
3
|
+
import type { RecordsWriteMessage } from '../types/records-types.js';
|
|
4
|
+
import type { ValidationStateReader } from '../types/validation-state-reader.js';
|
|
5
|
+
import type { Filter, PaginationCursor } from '../types/query-types.js';
|
|
6
|
+
import type { MessageSort, Pagination } from '../types/message-types.js';
|
|
7
|
+
|
|
8
|
+
import { FilterUtility } from './filter.js';
|
|
9
|
+
import { getRuleSetAtPath } from './protocols.js';
|
|
10
|
+
import { lexicographicalCompare } from './string.js';
|
|
11
|
+
import { ProtocolRecordLimitStrategy } from '../types/protocols-types.js';
|
|
12
|
+
import { Records } from './records.js';
|
|
13
|
+
import { SortDirection } from '../types/query-types.js';
|
|
14
|
+
import { DwnError, DwnErrorCode } from '../core/dwn-error.js';
|
|
15
|
+
import { DwnInterfaceName, DwnMethodName } from '../enums/dwn-interface-method.js';
|
|
16
|
+
|
|
17
|
+
type RecordLimitOccupancyDependencies = {
|
|
18
|
+
messageStore: MessageStore;
|
|
19
|
+
validationStateReader: ValidationStateReader;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type RecordLimitOccupancyQueryInput = RecordLimitOccupancyDependencies & {
|
|
23
|
+
tenant: string;
|
|
24
|
+
filters: Filter[];
|
|
25
|
+
messageTimestamp: string;
|
|
26
|
+
messageSort?: MessageSort;
|
|
27
|
+
pagination?: Pagination;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type RecordLimitScope = {
|
|
31
|
+
protocol: string;
|
|
32
|
+
protocolPath: string;
|
|
33
|
+
parentContextId: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type RecordLimitFilterResolution = {
|
|
37
|
+
projectedFilters: Filter[];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Queries records with bounded `$recordLimit` occupancy projection when every limited filter targets one concrete scope.
|
|
42
|
+
*
|
|
43
|
+
* Broad filters keep the store's native query path. Projecting those without a store-level grouping primitive would require
|
|
44
|
+
* scanning the full matching set, which is worse than leaving them unprojected until a bounded broad-query strategy exists.
|
|
45
|
+
*/
|
|
46
|
+
export async function queryRecordsWithRecordLimitOccupancy(
|
|
47
|
+
input: RecordLimitOccupancyQueryInput
|
|
48
|
+
): Promise<{ messages: RecordsWriteMessage[]; cursor?: PaginationCursor }> {
|
|
49
|
+
const filterResolution = await resolveRecordLimitFilters(input);
|
|
50
|
+
if (filterResolution === undefined) {
|
|
51
|
+
const { messages, cursor } = await input.messageStore.query(input.tenant, input.filters, input.messageSort, input.pagination);
|
|
52
|
+
return { messages: messages.filter(Records.isRecordsWrite), cursor };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (filterResolution.projectedFilters.length === 0) {
|
|
56
|
+
return { messages: [] };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const { messages, cursor } = await input.messageStore.query(
|
|
60
|
+
input.tenant,
|
|
61
|
+
filterResolution.projectedFilters,
|
|
62
|
+
input.messageSort,
|
|
63
|
+
input.pagination
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
return { messages: messages.filter(Records.isRecordsWrite), cursor };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Counts records with bounded `$recordLimit` occupancy projection when every limited filter targets one concrete scope.
|
|
71
|
+
*/
|
|
72
|
+
export async function countRecordsWithRecordLimitOccupancy(input: Omit<RecordLimitOccupancyQueryInput, 'pagination'>): Promise<number> {
|
|
73
|
+
const filterResolution = await resolveRecordLimitFilters(input);
|
|
74
|
+
if (filterResolution === undefined) {
|
|
75
|
+
return input.messageStore.count(input.tenant, input.filters, input.messageSort);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (filterResolution.projectedFilters.length === 0) {
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return input.messageStore.count(input.tenant, filterResolution.projectedFilters, input.messageSort);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Returns true when the latest RecordsWrite is visible under the `$recordLimit` projection.
|
|
87
|
+
*/
|
|
88
|
+
export async function isRecordLimitOccupant(input: RecordLimitOccupancyDependencies & {
|
|
89
|
+
tenant: string;
|
|
90
|
+
message: RecordsWriteMessage;
|
|
91
|
+
messageTimestamp: string;
|
|
92
|
+
}): Promise<boolean> {
|
|
93
|
+
const recordLimit = await getRecordLimitForMessage({
|
|
94
|
+
messageStore : input.messageStore,
|
|
95
|
+
validationStateReader : input.validationStateReader,
|
|
96
|
+
tenant : input.tenant,
|
|
97
|
+
message : input.message,
|
|
98
|
+
messageTimestamp : input.messageTimestamp,
|
|
99
|
+
recordLimitDefinitions : new Map(),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
if (recordLimit === undefined) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const occupantRecordIds = await findOccupantRecordIds({
|
|
107
|
+
messageStore : input.messageStore,
|
|
108
|
+
tenant : input.tenant,
|
|
109
|
+
scope : getRecordLimitScope(input.message),
|
|
110
|
+
recordLimit,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return occupantRecordIds.has(input.message.recordId);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function resolveRecordLimitFilters(
|
|
117
|
+
input: Omit<RecordLimitOccupancyQueryInput, 'pagination'>
|
|
118
|
+
): Promise<RecordLimitFilterResolution | undefined> {
|
|
119
|
+
const recordLimitDefinitions = new Map<string, ProtocolRecordLimitDefinition | undefined>();
|
|
120
|
+
const projectedFilters: Filter[] = [];
|
|
121
|
+
let projectionApplied = false;
|
|
122
|
+
|
|
123
|
+
for (const filter of input.filters) {
|
|
124
|
+
const recordLimit = await getRecordLimitForFilter({
|
|
125
|
+
messageStore : input.messageStore,
|
|
126
|
+
validationStateReader : input.validationStateReader,
|
|
127
|
+
tenant : input.tenant,
|
|
128
|
+
filter,
|
|
129
|
+
messageTimestamp : input.messageTimestamp,
|
|
130
|
+
recordLimitDefinitions,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (recordLimit === undefined) {
|
|
134
|
+
projectedFilters.push(filter);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const scope = getRecordLimitScopeFromFilter(filter);
|
|
139
|
+
if (scope === undefined) {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const occupantRecordIds = await findOccupantRecordIds({
|
|
144
|
+
messageStore : input.messageStore,
|
|
145
|
+
tenant : input.tenant,
|
|
146
|
+
scope,
|
|
147
|
+
recordLimit,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const projectedFilter = buildProjectedFilter(filter, occupantRecordIds);
|
|
151
|
+
if (projectedFilter !== undefined) {
|
|
152
|
+
projectedFilters.push(projectedFilter);
|
|
153
|
+
}
|
|
154
|
+
projectionApplied = true;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return projectionApplied ? { projectedFilters } : undefined;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function getRecordLimitForMessage(input: RecordLimitOccupancyDependencies & {
|
|
161
|
+
tenant: string;
|
|
162
|
+
message: RecordsWriteMessage;
|
|
163
|
+
messageTimestamp: string;
|
|
164
|
+
recordLimitDefinitions: Map<string, ProtocolRecordLimitDefinition | undefined>;
|
|
165
|
+
}): Promise<ProtocolRecordLimitDefinition | undefined> {
|
|
166
|
+
const { protocol, protocolPath } = input.message.descriptor;
|
|
167
|
+
if (protocol === undefined || protocolPath === undefined) {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return getRecordLimit({
|
|
172
|
+
validationStateReader : input.validationStateReader,
|
|
173
|
+
tenant : input.tenant,
|
|
174
|
+
protocol,
|
|
175
|
+
protocolPath,
|
|
176
|
+
messageTimestamp : input.messageTimestamp,
|
|
177
|
+
recordLimitDefinitions : input.recordLimitDefinitions,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function getRecordLimitForFilter(input: RecordLimitOccupancyDependencies & {
|
|
182
|
+
tenant: string;
|
|
183
|
+
filter: Filter;
|
|
184
|
+
messageTimestamp: string;
|
|
185
|
+
recordLimitDefinitions: Map<string, ProtocolRecordLimitDefinition | undefined>;
|
|
186
|
+
}): Promise<ProtocolRecordLimitDefinition | undefined> {
|
|
187
|
+
if (input.filter.interface !== DwnInterfaceName.Records ||
|
|
188
|
+
input.filter.method !== DwnMethodName.Write ||
|
|
189
|
+
input.filter.isLatestBaseState !== true
|
|
190
|
+
) {
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const { protocol, protocolPath } = input.filter;
|
|
195
|
+
if (typeof protocol !== 'string' || typeof protocolPath !== 'string') {
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return getRecordLimit({
|
|
200
|
+
validationStateReader : input.validationStateReader,
|
|
201
|
+
tenant : input.tenant,
|
|
202
|
+
protocol,
|
|
203
|
+
protocolPath,
|
|
204
|
+
messageTimestamp : input.messageTimestamp,
|
|
205
|
+
recordLimitDefinitions : input.recordLimitDefinitions,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function getRecordLimit(input: {
|
|
210
|
+
validationStateReader: ValidationStateReader;
|
|
211
|
+
tenant: string;
|
|
212
|
+
protocol: string;
|
|
213
|
+
protocolPath: string;
|
|
214
|
+
messageTimestamp: string;
|
|
215
|
+
recordLimitDefinitions: Map<string, ProtocolRecordLimitDefinition | undefined>;
|
|
216
|
+
}): Promise<ProtocolRecordLimitDefinition | undefined> {
|
|
217
|
+
const key = `${input.protocol}\u0000${input.protocolPath}`;
|
|
218
|
+
if (!input.recordLimitDefinitions.has(key)) {
|
|
219
|
+
let protocolDefinition;
|
|
220
|
+
try {
|
|
221
|
+
protocolDefinition = await input.validationStateReader.fetchProtocolDefinition(
|
|
222
|
+
input.tenant,
|
|
223
|
+
input.protocol,
|
|
224
|
+
input.messageTimestamp,
|
|
225
|
+
);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
if (error instanceof DwnError && error.code === DwnErrorCode.ProtocolAuthorizationProtocolNotFound) {
|
|
228
|
+
input.recordLimitDefinitions.set(key, undefined);
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
throw error;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const ruleSet = getRuleSetAtPath(input.protocolPath, protocolDefinition.structure);
|
|
235
|
+
const recordLimit = ruleSet?.$recordLimit;
|
|
236
|
+
input.recordLimitDefinitions.set(
|
|
237
|
+
key,
|
|
238
|
+
recordLimit?.strategy === ProtocolRecordLimitStrategy.Reject ? recordLimit : undefined
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return input.recordLimitDefinitions.get(key);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async function findOccupantRecordIds(input: {
|
|
246
|
+
messageStore: MessageStore;
|
|
247
|
+
tenant: string;
|
|
248
|
+
scope: RecordLimitScope;
|
|
249
|
+
recordLimit: ProtocolRecordLimitDefinition;
|
|
250
|
+
}): Promise<Set<string>> {
|
|
251
|
+
const scopeFilter = buildRecordLimitScopeFilter(input.scope);
|
|
252
|
+
const messageSort = { dateCreated: SortDirection.Ascending };
|
|
253
|
+
const { messages: firstPage } = await input.messageStore.query(
|
|
254
|
+
input.tenant,
|
|
255
|
+
[scopeFilter],
|
|
256
|
+
messageSort,
|
|
257
|
+
{ limit: input.recordLimit.max }
|
|
258
|
+
);
|
|
259
|
+
const firstPageCandidates = firstPage.filter(Records.isRecordsWrite);
|
|
260
|
+
if (firstPageCandidates.length === 0) {
|
|
261
|
+
return new Set();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const boundaryDateCreated = firstPageCandidates.at(-1)!.descriptor.dateCreated;
|
|
265
|
+
const beforeBoundary = firstPageCandidates.filter(
|
|
266
|
+
(message): boolean => message.descriptor.dateCreated < boundaryDateCreated
|
|
267
|
+
);
|
|
268
|
+
let boundaryCandidates = firstPageCandidates.filter(
|
|
269
|
+
(message): boolean => message.descriptor.dateCreated === boundaryDateCreated
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
if (firstPageCandidates.length === input.recordLimit.max) {
|
|
273
|
+
const { messages } = await input.messageStore.query(
|
|
274
|
+
input.tenant,
|
|
275
|
+
[{ ...scopeFilter, dateCreated: boundaryDateCreated }],
|
|
276
|
+
messageSort
|
|
277
|
+
);
|
|
278
|
+
boundaryCandidates = messages.filter(Records.isRecordsWrite);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
boundaryCandidates.sort(compareRecordLimitCandidates);
|
|
282
|
+
|
|
283
|
+
const rankedCandidates = [
|
|
284
|
+
...beforeBoundary,
|
|
285
|
+
...boundaryCandidates,
|
|
286
|
+
];
|
|
287
|
+
|
|
288
|
+
return new Set(
|
|
289
|
+
rankedCandidates
|
|
290
|
+
.slice(0, input.recordLimit.max)
|
|
291
|
+
.map((message): string => message.recordId)
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function buildRecordLimitScopeFilter(scope: RecordLimitScope): Filter {
|
|
296
|
+
const filter: Filter = {
|
|
297
|
+
interface : DwnInterfaceName.Records,
|
|
298
|
+
method : DwnMethodName.Write,
|
|
299
|
+
isLatestBaseState : true,
|
|
300
|
+
protocol : scope.protocol,
|
|
301
|
+
protocolPath : scope.protocolPath,
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
if (scope.parentContextId !== '') {
|
|
305
|
+
filter.contextId = FilterUtility.constructPrefixFilterAsRangeFilter(scope.parentContextId);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return filter;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function getRecordLimitScopeFromFilter(filter: Filter): RecordLimitScope | undefined {
|
|
312
|
+
const { protocol, protocolPath } = filter;
|
|
313
|
+
if (typeof protocol !== 'string' || typeof protocolPath !== 'string') {
|
|
314
|
+
return undefined;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (!protocolPath.includes('/')) {
|
|
318
|
+
return { protocol, protocolPath, parentContextId: '' };
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const parentContextId = getExactParentContextIdFromFilter(filter);
|
|
322
|
+
if (parentContextId === undefined) {
|
|
323
|
+
return undefined;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return { protocol, protocolPath, parentContextId };
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function getRecordLimitScope(message: RecordsWriteMessage): RecordLimitScope {
|
|
330
|
+
return {
|
|
331
|
+
protocol : message.descriptor.protocol,
|
|
332
|
+
protocolPath : message.descriptor.protocolPath,
|
|
333
|
+
parentContextId : Records.getParentContextFromOfContextId(message.contextId) ?? '',
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function getExactParentContextIdFromFilter(filter: Filter): string | undefined {
|
|
338
|
+
const { contextId } = filter;
|
|
339
|
+
if (contextId === undefined || !FilterUtility.isRangeFilter(contextId)) {
|
|
340
|
+
return undefined;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (typeof contextId.gte !== 'string' || contextId.lt !== `${contextId.gte}\uffff`) {
|
|
344
|
+
return undefined;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return contextId.gte;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function buildProjectedFilter(filter: Filter, occupantRecordIds: Set<string>): Filter | undefined {
|
|
351
|
+
let projectedRecordIds = Array.from(occupantRecordIds);
|
|
352
|
+
const existingRecordIdFilter = filter.recordId;
|
|
353
|
+
if (typeof existingRecordIdFilter === 'string') {
|
|
354
|
+
projectedRecordIds = occupantRecordIds.has(existingRecordIdFilter) ? [existingRecordIdFilter] : [];
|
|
355
|
+
} else if (Array.isArray(existingRecordIdFilter)) {
|
|
356
|
+
projectedRecordIds = existingRecordIdFilter
|
|
357
|
+
.filter((recordId): recordId is string => typeof recordId === 'string' && occupantRecordIds.has(recordId));
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (projectedRecordIds.length === 0) {
|
|
361
|
+
return undefined;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return {
|
|
365
|
+
...filter,
|
|
366
|
+
recordId: projectedRecordIds,
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function compareRecordLimitCandidates(left: RecordsWriteMessage, right: RecordsWriteMessage): number {
|
|
371
|
+
const dateComparison = lexicographicalCompare(left.descriptor.dateCreated, right.descriptor.dateCreated);
|
|
372
|
+
if (dateComparison !== 0) {
|
|
373
|
+
return dateComparison;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return lexicographicalCompare(left.recordId, right.recordId);
|
|
377
|
+
}
|
package/src/utils/records.ts
CHANGED
|
@@ -36,6 +36,26 @@ export class Records {
|
|
|
36
36
|
return isRecordsWrite;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Gets the newest `RecordsWrite` from the given message set.
|
|
41
|
+
*/
|
|
42
|
+
public static async getNewestRecordsWrite(messages: GenericMessage[]): Promise<RecordsWriteMessage | undefined> {
|
|
43
|
+
const recordsWriteMessages = messages.filter(Records.isRecordsWrite);
|
|
44
|
+
const newestRecordsWrite = await Message.getNewestMessage(recordsWriteMessages);
|
|
45
|
+
return newestRecordsWrite as RecordsWriteMessage | undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Gets the newest `RecordsDelete` from the given message set.
|
|
50
|
+
*/
|
|
51
|
+
public static async getNewestRecordsDelete(messages: GenericMessage[]): Promise<RecordsDeleteMessage | undefined> {
|
|
52
|
+
const recordsDeleteMessages = messages.filter((message): message is RecordsDeleteMessage =>
|
|
53
|
+
message.descriptor.interface === DwnInterfaceName.Records && message.descriptor.method === DwnMethodName.Delete
|
|
54
|
+
);
|
|
55
|
+
const newestRecordsDelete = await Message.getNewestMessage(recordsDeleteMessages);
|
|
56
|
+
return newestRecordsDelete as RecordsDeleteMessage | undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
39
59
|
/**
|
|
40
60
|
* Decrypts the encrypted data in a message reply.
|
|
41
61
|
*
|
|
@@ -285,6 +305,35 @@ export class Records {
|
|
|
285
305
|
return filterCopy;
|
|
286
306
|
}
|
|
287
307
|
|
|
308
|
+
/**
|
|
309
|
+
* Nested protocol-path queries must pin one parent context. Otherwise the same
|
|
310
|
+
* protocol type is read across every parent instance.
|
|
311
|
+
*/
|
|
312
|
+
public static validateNestedProtocolPathQueryScope(
|
|
313
|
+
filter: RecordsFilter,
|
|
314
|
+
errorCode: DwnErrorCode,
|
|
315
|
+
operationName: string,
|
|
316
|
+
): void {
|
|
317
|
+
const { contextId, protocolPath } = filter;
|
|
318
|
+
if (!protocolPath?.includes('/')) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const expectedParentDepth = protocolPath.split('/').length - 1;
|
|
323
|
+
const contextIdSegments = contextId?.split('/');
|
|
324
|
+
if (
|
|
325
|
+
contextIdSegments?.length === expectedParentDepth &&
|
|
326
|
+
contextIdSegments.every(segment => segment.length > 0)
|
|
327
|
+
) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
throw new DwnError(
|
|
332
|
+
errorCode,
|
|
333
|
+
`${operationName} for nested protocol path '${protocolPath}' must include the direct parent contextId in the filter`
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
288
337
|
|
|
289
338
|
public static isStartsWithFilter(filter: RecordsWriteTagsFilter): filter is StartsWithFilter {
|
|
290
339
|
return typeof filter === 'object' && ('startsWith' in filter && typeof filter.startsWith === 'string');
|
|
@@ -530,25 +579,32 @@ export class Records {
|
|
|
530
579
|
}
|
|
531
580
|
|
|
532
581
|
/**
|
|
533
|
-
* Checks
|
|
582
|
+
* Checks whether the given `RecordsDelete` is beaten by an existing tombstone for the record,
|
|
583
|
+
* per the tombstone lattice. A tombstone displaces any `RecordsWrite` regardless of timestamp
|
|
584
|
+
* (delete-wins). Among competing tombstones one canonical winner stands on every replica:
|
|
585
|
+
* a prune beats a plain delete regardless of timestamp — the cascade is a side effect, and a
|
|
586
|
+
* plain-newer winner would leave replicas that ran the cascade diverged from those that never
|
|
587
|
+
* would — and within the same class the newest tombstone wins, with `Message.isNewer`'s
|
|
588
|
+
* (messageTimestamp, CID) total order picking the same winner everywhere. Admission and
|
|
589
|
+
* resumable-task replay must share this predicate: state can advance between acceptance and
|
|
590
|
+
* replay, and replay must never admit a delete that admission would now reject.
|
|
534
591
|
*/
|
|
535
|
-
public static
|
|
536
|
-
|
|
592
|
+
public static async isDeleteBeatenByExistingTombstone(
|
|
593
|
+
deleteToBePerformed: RecordsDeleteMessage,
|
|
594
|
+
newestExistingMessage: GenericMessage
|
|
595
|
+
): Promise<boolean> {
|
|
596
|
+
if (newestExistingMessage.descriptor.method !== DwnMethodName.Delete) {
|
|
537
597
|
return false;
|
|
538
598
|
}
|
|
539
599
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
if (deleteToBePerformed.descriptor.prune !== true) {
|
|
545
|
-
return false;
|
|
546
|
-
} else if ((newestExistingMessage as RecordsDeleteMessage).descriptor.prune === true) {
|
|
547
|
-
return false;
|
|
548
|
-
}
|
|
600
|
+
const incomingIsPrune = deleteToBePerformed.descriptor.prune === true;
|
|
601
|
+
const existingIsPrune = (newestExistingMessage as RecordsDeleteMessage).descriptor.prune === true;
|
|
602
|
+
if (incomingIsPrune !== existingIsPrune) {
|
|
603
|
+
return existingIsPrune;
|
|
549
604
|
}
|
|
550
605
|
|
|
551
|
-
|
|
606
|
+
const incomingDeleteIsNewest = await Message.isNewer(deleteToBePerformed, newestExistingMessage);
|
|
607
|
+
return !incomingDeleteIsNewest;
|
|
552
608
|
}
|
|
553
609
|
|
|
554
610
|
/**
|