@enbox/dwn-sdk-js 0.4.0 → 0.4.2
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 +3 -10
- 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 +34 -89
- 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 +12 -9
- 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/protocol-tags.js +262 -0
- package/dist/esm/src/utils/protocol-tags.js.map +1 -0
- 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/protocol-tags.spec.js +96 -0
- package/dist/esm/tests/utils/protocol-tags.spec.js.map +1 -0
- 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 +14 -17
- 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/protocol-tags.d.ts +15 -0
- package/dist/types/src/utils/protocol-tags.d.ts.map +1 -0
- 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/protocol-tags.spec.d.ts +2 -0
- package/dist/types/tests/utils/protocol-tags.spec.d.ts.map +1 -0
- 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 +47 -121
- 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 +20 -10
- 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/protocol-tags.ts +366 -0
- 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,366 @@
|
|
|
1
|
+
import type { ProtocolTagSchema, ProtocolTagsDefinition } from '../types/protocols-types.js';
|
|
2
|
+
|
|
3
|
+
type TagSchema = ProtocolTagSchema | Record<string, unknown>;
|
|
4
|
+
|
|
5
|
+
type TagValidationError = {
|
|
6
|
+
instancePath: string;
|
|
7
|
+
message: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const allowedTagTypes = new Set(['string', 'number', 'integer', 'boolean', 'array']);
|
|
11
|
+
const allowedArrayItemTypes = new Set(['string', 'number', 'integer']);
|
|
12
|
+
const numericConstraintKeywords = [ 'minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum' ];
|
|
13
|
+
const stringConstraintKeywords = [ 'minLength', 'maxLength' ];
|
|
14
|
+
const arrayConstraintKeywords = [ 'minItems', 'maxItems', 'minContains', 'maxContains' ];
|
|
15
|
+
|
|
16
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
17
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function pathSegment(segment: string | number): string {
|
|
21
|
+
return String(segment).replaceAll('~', '~0').replaceAll('/', '~1');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function appendPath(path: string, segment: string | number): string {
|
|
25
|
+
return `${path}/${pathSegment(segment)}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function hasOwnProperty(value: Record<string, unknown>, property: string): boolean {
|
|
29
|
+
return Object.hasOwn(value, property);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function addError(errors: TagValidationError[], instancePath: string, message: string): void {
|
|
33
|
+
errors.push({ instancePath, message });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function isNumber(value: unknown): value is number {
|
|
37
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function valuesEqual(left: unknown, right: unknown): boolean {
|
|
41
|
+
if (Object.is(left, right)) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
46
|
+
return left.length === right.length && left.every((value, index) => valuesEqual(value, right[index]));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (isRecord(left) && isRecord(right)) {
|
|
50
|
+
const leftKeys = Object.keys(left);
|
|
51
|
+
const rightKeys = Object.keys(right);
|
|
52
|
+
|
|
53
|
+
return leftKeys.length === rightKeys.length
|
|
54
|
+
&& leftKeys.every(key => Object.hasOwn(right, key) && valuesEqual(left[key], right[key]));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function getTagSchemas(tagsDefinition: ProtocolTagsDefinition): Record<string, TagSchema> {
|
|
61
|
+
const schemas: Record<string, TagSchema> = {};
|
|
62
|
+
|
|
63
|
+
for (const [ tag, schema ] of Object.entries(tagsDefinition)) {
|
|
64
|
+
if (tag === '$requiredTags' || tag === '$allowUndefinedTags') {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
schemas[tag] = schema as TagSchema;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return schemas;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function validateSchemaConstraintTypes(
|
|
75
|
+
schema: Record<string, unknown>,
|
|
76
|
+
dataPath: string,
|
|
77
|
+
errors: TagValidationError[],
|
|
78
|
+
): void {
|
|
79
|
+
if (schema.enum !== undefined) {
|
|
80
|
+
if (!Array.isArray(schema.enum) || schema.enum.length === 0) {
|
|
81
|
+
addError(errors, appendPath(dataPath, 'enum'), 'must be non-empty array');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (const keyword of numericConstraintKeywords) {
|
|
86
|
+
if (schema[keyword] !== undefined && !isNumber(schema[keyword])) {
|
|
87
|
+
addError(errors, appendPath(dataPath, keyword), 'must be number');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
for (const keyword of [ ...stringConstraintKeywords, ...arrayConstraintKeywords ]) {
|
|
92
|
+
if (schema[keyword] !== undefined && (!Number.isInteger(schema[keyword]) || (schema[keyword] as number) < 0)) {
|
|
93
|
+
addError(errors, appendPath(dataPath, keyword), 'must be integer');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (schema.uniqueItems !== undefined && typeof schema.uniqueItems !== 'boolean') {
|
|
98
|
+
addError(errors, appendPath(dataPath, 'uniqueItems'), 'must be boolean');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function validateTagSubschemaDefinition(
|
|
103
|
+
schema: unknown,
|
|
104
|
+
dataPath: string,
|
|
105
|
+
allowedTypes: Set<string>,
|
|
106
|
+
errors: TagValidationError[],
|
|
107
|
+
): void {
|
|
108
|
+
if (!isRecord(schema)) {
|
|
109
|
+
addError(errors, dataPath, 'must be object');
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (schema.type !== undefined && (typeof schema.type !== 'string' || !allowedTypes.has(schema.type))) {
|
|
114
|
+
addError(errors, appendPath(dataPath, 'type'), 'must be equal to one of the allowed values');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
validateSchemaConstraintTypes(schema, dataPath, errors);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Validates DWN protocol tag schema definitions without invoking Ajv's runtime compiler.
|
|
122
|
+
*
|
|
123
|
+
* The broader protocol message shape is already checked by the precompiled
|
|
124
|
+
* ProtocolRuleSet validator. This function covers the tag-schema constraints
|
|
125
|
+
* that are deliberately modeled as a small DWN subset rather than arbitrary
|
|
126
|
+
* JSON Schema.
|
|
127
|
+
*/
|
|
128
|
+
export function validateProtocolTagSchemaDefinition(
|
|
129
|
+
schema: unknown,
|
|
130
|
+
dataVar: string,
|
|
131
|
+
): string | undefined {
|
|
132
|
+
const errors: TagValidationError[] = [];
|
|
133
|
+
|
|
134
|
+
validateTagSubschemaDefinition(schema, '', allowedTagTypes, errors);
|
|
135
|
+
|
|
136
|
+
if (isRecord(schema)) {
|
|
137
|
+
if (schema.items !== undefined) {
|
|
138
|
+
validateTagSubschemaDefinition(schema.items, '/items', allowedArrayItemTypes, errors);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (schema.contains !== undefined) {
|
|
142
|
+
validateTagSubschemaDefinition(schema.contains, '/contains', allowedArrayItemTypes, errors);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return formatTagValidationErrors(errors, dataVar);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function validateType(type: unknown, value: unknown, dataPath: string, errors: TagValidationError[]): boolean {
|
|
150
|
+
switch (type) {
|
|
151
|
+
case undefined:
|
|
152
|
+
return true;
|
|
153
|
+
case 'string':
|
|
154
|
+
if (typeof value === 'string') {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
addError(errors, dataPath, 'must be string');
|
|
158
|
+
return false;
|
|
159
|
+
case 'number':
|
|
160
|
+
if (isNumber(value)) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
addError(errors, dataPath, 'must be number');
|
|
164
|
+
return false;
|
|
165
|
+
case 'integer':
|
|
166
|
+
if (isNumber(value) && Number.isInteger(value)) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
addError(errors, dataPath, 'must be integer');
|
|
170
|
+
return false;
|
|
171
|
+
case 'boolean':
|
|
172
|
+
if (typeof value === 'boolean') {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
addError(errors, dataPath, 'must be boolean');
|
|
176
|
+
return false;
|
|
177
|
+
case 'array':
|
|
178
|
+
if (Array.isArray(value)) {
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
addError(errors, dataPath, 'must be array');
|
|
182
|
+
return false;
|
|
183
|
+
default:
|
|
184
|
+
addError(errors, dataPath, 'must match a supported tag schema type');
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function validateEnum(schema: Record<string, unknown>, value: unknown, dataPath: string, errors: TagValidationError[]): void {
|
|
190
|
+
if (Array.isArray(schema.enum) && !schema.enum.some(allowed => valuesEqual(allowed, value))) {
|
|
191
|
+
addError(errors, dataPath, 'must be equal to one of the allowed values');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function validateNumberConstraints(
|
|
196
|
+
schema: Record<string, unknown>,
|
|
197
|
+
value: unknown,
|
|
198
|
+
dataPath: string,
|
|
199
|
+
errors: TagValidationError[],
|
|
200
|
+
): void {
|
|
201
|
+
if (!isNumber(value)) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (isNumber(schema.minimum) && value < schema.minimum) {
|
|
206
|
+
addError(errors, dataPath, `must be >= ${schema.minimum}`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (isNumber(schema.maximum) && value > schema.maximum) {
|
|
210
|
+
addError(errors, dataPath, `must be <= ${schema.maximum}`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (isNumber(schema.exclusiveMinimum) && value <= schema.exclusiveMinimum) {
|
|
214
|
+
addError(errors, dataPath, `must be > ${schema.exclusiveMinimum}`);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (isNumber(schema.exclusiveMaximum) && value >= schema.exclusiveMaximum) {
|
|
218
|
+
addError(errors, dataPath, `must be < ${schema.exclusiveMaximum}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function validateStringConstraints(
|
|
223
|
+
schema: Record<string, unknown>,
|
|
224
|
+
value: unknown,
|
|
225
|
+
dataPath: string,
|
|
226
|
+
errors: TagValidationError[],
|
|
227
|
+
): void {
|
|
228
|
+
if (typeof value !== 'string') {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (Number.isInteger(schema.minLength) && value.length < (schema.minLength as number)) {
|
|
233
|
+
addError(errors, dataPath, `must NOT have fewer than ${schema.minLength} characters`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (Number.isInteger(schema.maxLength) && value.length > (schema.maxLength as number)) {
|
|
237
|
+
addError(errors, dataPath, `must NOT have more than ${schema.maxLength} characters`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function validateArrayConstraints(
|
|
242
|
+
schema: Record<string, unknown>,
|
|
243
|
+
value: unknown,
|
|
244
|
+
dataPath: string,
|
|
245
|
+
errors: TagValidationError[],
|
|
246
|
+
): void {
|
|
247
|
+
if (!Array.isArray(value)) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (Number.isInteger(schema.minItems) && value.length < (schema.minItems as number)) {
|
|
252
|
+
addError(errors, dataPath, `must NOT have fewer than ${schema.minItems} items`);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (Number.isInteger(schema.maxItems) && value.length > (schema.maxItems as number)) {
|
|
256
|
+
addError(errors, dataPath, `must NOT have more than ${schema.maxItems} items`);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (schema.uniqueItems === true) {
|
|
260
|
+
for (let i = 0; i < value.length; i++) {
|
|
261
|
+
for (let j = i + 1; j < value.length; j++) {
|
|
262
|
+
if (valuesEqual(value[i], value[j])) {
|
|
263
|
+
addError(errors, dataPath, 'must NOT have duplicate items');
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function validateTagValue(
|
|
272
|
+
schema: unknown,
|
|
273
|
+
value: unknown,
|
|
274
|
+
dataPath: string,
|
|
275
|
+
errors: TagValidationError[],
|
|
276
|
+
): void {
|
|
277
|
+
if (!isRecord(schema)) {
|
|
278
|
+
addError(errors, dataPath, 'must match a supported tag schema');
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const validType = validateType(schema.type, value, dataPath, errors);
|
|
283
|
+
if (!validType) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
validateEnum(schema, value, dataPath, errors);
|
|
288
|
+
validateNumberConstraints(schema, value, dataPath, errors);
|
|
289
|
+
validateStringConstraints(schema, value, dataPath, errors);
|
|
290
|
+
validateArrayConstraints(schema, value, dataPath, errors);
|
|
291
|
+
|
|
292
|
+
if (Array.isArray(value) && isRecord(schema.items)) {
|
|
293
|
+
value.forEach((item, index) => validateTagValue(schema.items, item, appendPath(dataPath, index), errors));
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (Array.isArray(value) && isRecord(schema.contains)) {
|
|
297
|
+
validateContains(schema, value, dataPath, errors);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function validateContains(
|
|
302
|
+
schema: Record<string, unknown>,
|
|
303
|
+
value: unknown[],
|
|
304
|
+
dataPath: string,
|
|
305
|
+
errors: TagValidationError[],
|
|
306
|
+
): void {
|
|
307
|
+
const minimumCount = Number.isInteger(schema.minContains) ? schema.minContains as number : 1;
|
|
308
|
+
const maximumCount = Number.isInteger(schema.maxContains) ? schema.maxContains as number : undefined;
|
|
309
|
+
const validItemCount = value.filter(item => {
|
|
310
|
+
const itemErrors: TagValidationError[] = [];
|
|
311
|
+
validateTagValue(schema.contains, item, dataPath, itemErrors);
|
|
312
|
+
return itemErrors.length === 0;
|
|
313
|
+
}).length;
|
|
314
|
+
|
|
315
|
+
if (validItemCount < minimumCount || (maximumCount !== undefined && validItemCount > maximumCount)) {
|
|
316
|
+
const message = maximumCount === undefined
|
|
317
|
+
? `must contain at least ${minimumCount} valid item(s)`
|
|
318
|
+
: `must contain at least ${minimumCount} and no more than ${maximumCount} valid item(s)`;
|
|
319
|
+
addError(errors, dataPath, message);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Validates a record's `descriptor.tags` against a protocol rule set `$tags` definition.
|
|
325
|
+
*/
|
|
326
|
+
export function validateProtocolTags(
|
|
327
|
+
tagsDefinition: ProtocolTagsDefinition,
|
|
328
|
+
tags: Record<string, unknown>,
|
|
329
|
+
dataVar: string,
|
|
330
|
+
): string | undefined {
|
|
331
|
+
const errors: TagValidationError[] = [];
|
|
332
|
+
const tagSchemas = getTagSchemas(tagsDefinition);
|
|
333
|
+
const requiredTags = Array.isArray(tagsDefinition.$requiredTags) ? tagsDefinition.$requiredTags : [];
|
|
334
|
+
|
|
335
|
+
for (const requiredTag of requiredTags) {
|
|
336
|
+
if (!hasOwnProperty(tags, requiredTag)) {
|
|
337
|
+
addError(errors, '', `must have required property '${requiredTag}'`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (tagsDefinition.$allowUndefinedTags !== true) {
|
|
342
|
+
for (const tag of Object.keys(tags)) {
|
|
343
|
+
if (tagSchemas[tag] === undefined) {
|
|
344
|
+
addError(errors, '', 'must NOT have additional properties');
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
for (const [ tag, schema ] of Object.entries(tagSchemas)) {
|
|
350
|
+
if (hasOwnProperty(tags, tag)) {
|
|
351
|
+
validateTagValue(schema, tags[tag], appendPath('', tag), errors);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return formatTagValidationErrors(errors, dataVar);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function formatTagValidationErrors(errors: TagValidationError[], dataVar: string): string | undefined {
|
|
359
|
+
if (errors.length === 0) {
|
|
360
|
+
return undefined;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return errors
|
|
364
|
+
.map(error => `${dataVar}${error.instancePath} ${error.message}`)
|
|
365
|
+
.join(', ');
|
|
366
|
+
}
|