From e983cd86c91f6088aab45706164804d05ce9ccc0 Mon Sep 17 00:00:00 2001 From: Henry Tsai Date: Mon, 7 Oct 2024 18:25:07 -0700 Subject: [PATCH] Further restructuring of RecordsReadReply & corrected UnionMessageReply type for downstream consumption (#821) --- package-lock.json | 4 +- package.json | 2 +- src/core/message-reply.ts | 27 ++----- src/handlers/records-read.ts | 18 +++-- src/index.ts | 3 +- src/types/records-types.ts | 11 +++ tests/features/author-delegated-grant.spec.ts | 2 +- tests/features/owner-signature.spec.ts | 22 +++--- tests/features/permissions.spec.ts | 2 +- tests/features/protocol-update-action.spec.ts | 16 ++--- tests/features/records-tags.spec.ts | 12 ++-- tests/features/resumable-tasks.spec.ts | 4 +- tests/handlers/records-delete.spec.ts | 4 +- tests/handlers/records-read.spec.ts | 72 +++++++++---------- tests/handlers/records-write.spec.ts | 22 +++--- tests/scenarios/deleted-record.spec.ts | 8 +-- tests/scenarios/end-to-end-tests.spec.ts | 18 ++--- tests/scenarios/nested-roles.spec.ts | 4 +- 18 files changed, 126 insertions(+), 125 deletions(-) diff --git a/package-lock.json b/package-lock.json index 41bc9df0d..713c5625a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@tbd54566975/dwn-sdk-js", - "version": "0.5.0", + "version": "0.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tbd54566975/dwn-sdk-js", - "version": "0.5.0", + "version": "0.5.1", "license": "Apache-2.0", "dependencies": { "@ipld/dag-cbor": "9.0.3", diff --git a/package.json b/package.json index 41d2fdf4c..4b7330ec6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tbd54566975/dwn-sdk-js", - "version": "0.5.0", + "version": "0.5.1", "description": "A reference implementation of https://identity.foundation/decentralized-web-node/spec/", "repository": { "type": "git", diff --git a/src/core/message-reply.ts b/src/core/message-reply.ts index 2a6a93233..b1f443318 100644 --- a/src/core/message-reply.ts +++ b/src/core/message-reply.ts @@ -1,8 +1,7 @@ import type { MessagesReadReplyEntry } from '../types/messages-types.js'; import type { PaginationCursor } from '../types/query-types.js'; import type { ProtocolsConfigureMessage } from '../types/protocols-types.js'; -import type { Readable } from 'readable-stream'; -import type { RecordsWriteMessage } from '../types/records-types.js'; +import type { RecordsReadReplyEntry } from '../types/records-types.js'; import type { GenericMessageReply, MessageSubscription, QueryResultEntry } from '../types/message-types.js'; export function messageReplyFromError(e: unknown, code: number): GenericMessageReply { @@ -16,6 +15,12 @@ export function messageReplyFromError(e: unknown, code: number): GenericMessageR * Catch-all message reply type. It is recommended to use GenericMessageReply or a message-specific reply type wherever possible. */ export type UnionMessageReply = GenericMessageReply & { + /** + * A container for the data returned from a `RecordsRead` or `MessagesRead`. + * Mutually exclusive with (`entries` + `cursor`) and `subscription`. + */ + entry?: MessagesReadReplyEntry & RecordsReadReplyEntry; + /** * Resulting message entries or events returned from the invocation of the corresponding message. * e.g. the resulting messages from a RecordsQuery, or array of messageCid strings for MessagesQuery @@ -23,24 +28,6 @@ export type UnionMessageReply = GenericMessageReply & { */ entries?: QueryResultEntry[] | ProtocolsConfigureMessage[] | string[]; - /** - * A single message entry if applicable (e.g. MessagesRead). - * Mutually exclusive with `record`, `entries` and `cursor`. - */ - entry?: MessagesReadReplyEntry; - - /** - * Record corresponding to the message received if applicable (e.g. RecordsRead). - * Mutually exclusive with `entries` and `cursor`. - */ - record?: RecordsWriteMessage & { - /** - * The initial write of the record if the returned RecordsWrite message itself is not the initial write. - */ - initialWrite?: RecordsWriteMessage; - data: Readable; - }; - /** * A cursor for pagination if applicable (e.g. RecordsQuery). * Mutually exclusive with `record`. diff --git a/src/handlers/records-read.ts b/src/handlers/records-read.ts index 2e8540553..ad10e0eb1 100644 --- a/src/handlers/records-read.ts +++ b/src/handlers/records-read.ts @@ -72,9 +72,11 @@ export class RecordsReadHandler implements MethodHandler { const recordsDeleteMessage = matchedMessage as RecordsDeleteMessage; const initialWrite = await RecordsWrite.fetchInitialRecordsWriteMessage(this.messageStore, tenant, recordsDeleteMessage.descriptor.recordId); return { - status : { code: 404, detail: 'Not Found' }, - recordsDelete : recordsDeleteMessage, - initialWrite + status : { code: 404, detail: 'Not Found' }, + entry : { + recordsDelete: recordsDeleteMessage, + initialWrite + } }; } @@ -103,9 +105,11 @@ export class RecordsReadHandler implements MethodHandler { } const recordsReadReply: RecordsReadReply = { - status : { code: 200, detail: 'OK' }, - recordsWrite : matchedRecordsWrite, - data + status : { code: 200, detail: 'OK' }, + entry : { + recordsWrite: matchedRecordsWrite, + data + } }; // attach initial write if latest RecordsWrite is not initial write @@ -116,7 +120,7 @@ export class RecordsReadHandler implements MethodHandler { ); const initialWrite = initialWriteQueryResult.messages[0] as RecordsQueryReplyEntry; delete initialWrite.encodedData; // just defensive because technically should already be deleted when a later RecordsWrite is written - recordsReadReply.initialWrite = initialWrite; + recordsReadReply.entry!.initialWrite = initialWrite; } return recordsReadReply; diff --git a/src/index.ts b/src/index.ts index 7a939196f..5cb4faa9a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,7 +6,6 @@ export type { GenericMessage, GenericMessageReply, MessageSort, MessageSubscript export type { MessagesFilter, MessagesReadMessage as MessagesReadMessage, MessagesReadReply as MessagesReadReply, MessagesReadReplyEntry as MessagesReadReplyEntry, MessagesQueryMessage, MessagesQueryReply, MessagesSubscribeDescriptor, MessagesSubscribeMessage, MessagesSubscribeReply, MessageSubscriptionHandler } from './types/messages-types.js'; export type { Filter, EqualFilter, OneOfFilter, RangeFilter, RangeCriterion, PaginationCursor, QueryOptions } from './types/query-types.js'; export type { ProtocolsConfigureDescriptor, ProtocolDefinition, ProtocolTypes, ProtocolRuleSet, ProtocolsQueryFilter, ProtocolsConfigureMessage, ProtocolsQueryMessage, ProtocolsQueryReply } from './types/protocols-types.js'; -export type { DataEncodedRecordsWriteMessage, EncryptionProperty, RecordsDeleteMessage, RecordsQueryMessage, RecordsQueryReply, RecordsQueryReplyEntry, RecordsReadMessage, RecordsReadReply, RecordsSubscribeDescriptor, RecordsSubscribeMessage, RecordsSubscribeReply, RecordSubscriptionHandler, RecordsWriteDescriptor, RecordsWriteTags, RecordsWriteTagValue, RecordsWriteMessage } from './types/records-types.js'; export { authenticate } from './core/auth.js'; export { ActiveTenantCheckResult, AllowAllTenantGate, TenantGate } from './core/tenant-gate.js'; export { Cid } from './utils/cid.js'; @@ -14,7 +13,6 @@ export { RecordsQuery, RecordsQueryOptions } from './interfaces/records-query.js export { DataStore, DataStorePutResult, DataStoreGetResult } from './types/data-store.js'; export { ResumableTaskStore, ManagedResumableTask } from './types/resumable-task-store.js'; export { DataStream } from './utils/data-stream.js'; -export { DateSort } from './types/records-types.js'; export { DerivedPrivateJwk, HdKey, KeyDerivationScheme } from './utils/hd-key.js'; export { Dwn } from './dwn.js'; export { DwnConstant } from './core/dwn-constant.js'; @@ -49,6 +47,7 @@ export { Signer } from './types/signer.js'; export { SortDirection } from './types/query-types.js'; export { Time } from './utils/time.js'; export * from './types/permission-types.js'; +export * from './types/records-types.js'; // concrete implementations of stores and event stream export { DataStoreLevel } from './store/data-store-level.js'; diff --git a/src/types/records-types.ts b/src/types/records-types.ts index 14ffb3071..e7d3812a3 100644 --- a/src/types/records-types.ts +++ b/src/types/records-types.ts @@ -206,6 +206,17 @@ export type RecordsReadMessage = { * The reply to a RecordsRead message. */ export type RecordsReadReply = GenericMessageReply & { + /** + * A container for the data returned from a `RecordsRead`. + * `undefined` if no data needs to be returned. + */ + entry?: RecordsReadReplyEntry; +}; + +/** + * The structure of the `entry` container property in `RecordsReadReplyEntry`. + */ +export type RecordsReadReplyEntry = { /** * The latest RecordsWrite message of the record if record exists (not deleted). */ diff --git a/tests/features/author-delegated-grant.spec.ts b/tests/features/author-delegated-grant.spec.ts index 60fc9117b..c04c69307 100644 --- a/tests/features/author-delegated-grant.spec.ts +++ b/tests/features/author-delegated-grant.spec.ts @@ -505,7 +505,7 @@ export function testAuthorDelegatedGrant(): void { }); const deviceXRecordsReadReply = await dwn.processMessage(bob.did, recordsReadByDeviceX.message); expect(deviceXRecordsReadReply.status.code).to.equal(200); - expect(deviceXRecordsReadReply.recordsWrite?.recordId).to.equal(chatRecord.message.recordId); + expect(deviceXRecordsReadReply.entry!.recordsWrite?.recordId).to.equal(chatRecord.message.recordId); // Verify that Carol cannot query as Alice by invoking the delegated grant granted to Device X const recordsQueryByCarol = await RecordsQuery.create({ diff --git a/tests/features/owner-signature.spec.ts b/tests/features/owner-signature.spec.ts index 1d3978e41..8a221b2e8 100644 --- a/tests/features/owner-signature.spec.ts +++ b/tests/features/owner-signature.spec.ts @@ -78,26 +78,26 @@ export function testOwnerSignature(): void { const readReply = await dwn.processMessage(bob.did, recordsRead.message); expect(readReply.status.code).to.equal(200); - expect(readReply.recordsWrite).to.exist; - expect(readReply.recordsWrite?.descriptor).to.exist; + expect(readReply.entry!.recordsWrite).to.exist; + expect(readReply.entry!.recordsWrite?.descriptor).to.exist; // Alice augments Bob's message as an external owner - const { recordsWrite } = readReply; // remove data from message - const ownerSignedMessage = await RecordsWrite.parse(recordsWrite!); + const { entry } = readReply; // remove data from message + const ownerSignedMessage = await RecordsWrite.parse(entry!.recordsWrite!); await ownerSignedMessage.signAsOwner(Jws.createSigner(alice)); // Test that Alice can successfully retain/write Bob's message to her DWN - const aliceDataStream = readReply.data!; + const aliceDataStream = readReply.entry!.data!; const aliceWriteReply = await dwn.processMessage(alice.did, ownerSignedMessage.message, { dataStream: aliceDataStream }); expect(aliceWriteReply.status.code).to.equal(202); // Test that Bob's message can be read from Alice's DWN const readReply2 = await dwn.processMessage(alice.did, recordsRead.message); expect(readReply2.status.code).to.equal(200); - expect(readReply2.recordsWrite).to.exist; - expect(readReply2.recordsWrite?.descriptor).to.exist; + expect(readReply2.entry!.recordsWrite).to.exist; + expect(readReply2.entry!.recordsWrite?.descriptor).to.exist; - const dataFetched = await DataStream.toBytes(readReply2.data!); + const dataFetched = await DataStream.toBytes(readReply2.entry!.data!); expect(ArrayUtility.byteArraysEqual(dataFetched, dataBytes!)).to.be.true; }); @@ -144,10 +144,10 @@ export function testOwnerSignature(): void { }); const readReply = await dwn.processMessage(alice.did, recordsRead.message); expect(readReply.status.code).to.equal(200); - expect(readReply.recordsWrite).to.exist; - expect(readReply.recordsWrite?.descriptor).to.exist; + expect(readReply.entry!.recordsWrite).to.exist; + expect(readReply.entry!.recordsWrite?.descriptor).to.exist; - const dataFetched = await DataStream.toBytes(readReply.data!); + const dataFetched = await DataStream.toBytes(readReply.entry!.data!); expect(ArrayUtility.byteArraysEqual(dataFetched, bobRecordsWrite.dataBytes!)).to.be.true; }); diff --git a/tests/features/permissions.spec.ts b/tests/features/permissions.spec.ts index 694c8ffb9..ca44560e3 100644 --- a/tests/features/permissions.spec.ts +++ b/tests/features/permissions.spec.ts @@ -345,7 +345,7 @@ export function testPermissions(): void { // 9. Verify that any third-party can fetch the revocation status of the permission grant const revocationReadReply2 = await dwn.processMessage(alice.did, revocationRead.message); expect(revocationReadReply2.status.code).to.equal(200); - expect(revocationReadReply2.recordsWrite?.recordId).to.equal(revokeWrite.recordsWrite.message.recordId); + expect(revocationReadReply2.entry!.recordsWrite?.recordId).to.equal(revokeWrite.recordsWrite.message.recordId); }); it('should fail if a RecordsPermissionScope in a Request or Grant record is created without a protocol', async () => { diff --git a/tests/features/protocol-update-action.spec.ts b/tests/features/protocol-update-action.spec.ts index 2559a40e3..e7ab90555 100644 --- a/tests/features/protocol-update-action.spec.ts +++ b/tests/features/protocol-update-action.spec.ts @@ -165,8 +165,8 @@ export function testProtocolUpdateAction(): void { }); const recordsReadReply = await dwn.processMessage(alice.did, recordsRead.message); expect(recordsReadReply.status.code).to.equal(200); - expect(recordsReadReply.data).to.exist; - const dataFromReply = await DataStream.toBytes(recordsReadReply.data!); + expect(recordsReadReply.entry!.data).to.exist; + const dataFromReply = await DataStream.toBytes(recordsReadReply.entry!.data!); expect(dataFromReply).to.eql(bobFooNewBytes); // 5. Carol creates a `foo` by invoking the user role. @@ -350,8 +350,8 @@ export function testProtocolUpdateAction(): void { }); const bobBarReadReply = await dwn.processMessage(alice.did, bobBarRead.message); expect(bobBarReadReply.status.code).to.equal(200); - expect(bobBarReadReply.data).to.exist; - const dataFromBobBarRead = await DataStream.toBytes(bobBarReadReply.data!); + expect(bobBarReadReply.entry!.data).to.exist; + const dataFromBobBarRead = await DataStream.toBytes(bobBarReadReply.entry!.data!); expect(dataFromBobBarRead).to.eql(bobBarNewBytes); // 7. Verify that Bob cannot update Carol's `bar`. @@ -423,8 +423,8 @@ export function testProtocolUpdateAction(): void { }); const bobBazReadReply = await dwn.processMessage(alice.did, bobBazRead.message); expect(bobBazReadReply.status.code).to.equal(200); - expect(bobBazReadReply.data).to.exist; - const dataFromBobBazRead = await DataStream.toBytes(bobBazReadReply.data!); + expect(bobBazReadReply.entry!.data).to.exist; + const dataFromBobBazRead = await DataStream.toBytes(bobBazReadReply.entry!.data!); expect(dataFromBobBazRead).to.eql(bobBazNewBytes); // 11. Verify that Bob cannot update Carol's `baz` @@ -534,8 +534,8 @@ export function testProtocolUpdateAction(): void { }); const bobFooReadReply = await dwn.processMessage(alice.did, bobBarRead.message); expect(bobFooReadReply.status.code).to.equal(200); - expect(bobFooReadReply.data).to.exist; - const dataFromBobFooRead = await DataStream.toBytes(bobFooReadReply.data!); + expect(bobFooReadReply.entry!.data).to.exist; + const dataFromBobFooRead = await DataStream.toBytes(bobFooReadReply.entry!.data!); expect(dataFromBobFooRead).to.eql(bobFooNewBytes); // 5. Verify that Bob cannot update Carol's `foo`. diff --git a/tests/features/records-tags.spec.ts b/tests/features/records-tags.spec.ts index 05d5bcaa3..5f314c6af 100644 --- a/tests/features/records-tags.spec.ts +++ b/tests/features/records-tags.spec.ts @@ -2079,8 +2079,8 @@ export function testRecordsTags(): void { const tagsRecord1ReadReply = await dwn.processMessage(alice.did, tagsRecord1Read.message); expect(tagsRecord1ReadReply.status.code).to.equal(200); - expect(tagsRecord1ReadReply.recordsWrite).to.not.be.undefined; - expect(tagsRecord1ReadReply.recordsWrite!.descriptor.tags) + expect(tagsRecord1ReadReply.entry!.recordsWrite).to.not.be.undefined; + expect(tagsRecord1ReadReply.entry!.recordsWrite!.descriptor.tags) .to.deep.equal({ stringTag, numberTag, booleanTag, stringArrayTag, numberArrayTag }); }); @@ -2114,8 +2114,8 @@ export function testRecordsTags(): void { const tagsRecord1ReadReply = await dwn.processMessage(alice.did, tagsRecord1Read.message); expect(tagsRecord1ReadReply.status.code).to.equal(200); - expect(tagsRecord1ReadReply.recordsWrite).to.not.be.undefined; - expect(tagsRecord1ReadReply.recordsWrite!.descriptor.tags).to.deep.equal({ + expect(tagsRecord1ReadReply.entry!.recordsWrite).to.not.be.undefined; + expect(tagsRecord1ReadReply.entry!.recordsWrite!.descriptor.tags).to.deep.equal({ stringTag : 'string-value', numberTag : 54566975, booleanTag : false, @@ -2149,8 +2149,8 @@ export function testRecordsTags(): void { const updatedRecordReadReply = await dwn.processMessage(alice.did, tagsRecord1Read.message); expect(updatedRecordReadReply.status.code).to.equal(200); - expect(updatedRecordReadReply.recordsWrite).to.exist; - expect(updatedRecordReadReply.recordsWrite!.descriptor.tags).to.deep.equal({ newTag: 'new-value' }); + expect(updatedRecordReadReply.entry!.recordsWrite).to.exist; + expect(updatedRecordReadReply.entry!.recordsWrite!.descriptor.tags).to.deep.equal({ newTag: 'new-value' }); // Sanity: Query for the old tag value should return no results const tagsQueryMatchReply2 = await dwn.processMessage(alice.did, tagsQueryMatch.message); diff --git a/tests/features/resumable-tasks.spec.ts b/tests/features/resumable-tasks.spec.ts index b47419fda..e0248823a 100644 --- a/tests/features/resumable-tasks.spec.ts +++ b/tests/features/resumable-tasks.spec.ts @@ -138,7 +138,7 @@ export function testResumableTasks(): void { const readReply = await dwn.processMessage(alice.did, recordsRead.message); expect(readReply.status.code).to.equal(200); - expect(readReply.recordsWrite).to.exist; + expect(readReply.entry!.recordsWrite).to.exist; // 3. Restart the DWN to trigger the resumable task to be resumed. await dwn.close(); @@ -147,7 +147,7 @@ export function testResumableTasks(): void { // 4. Verify that the record is deleted. const readReply2 = await dwn.processMessage(alice.did, recordsRead.message); expect(readReply2.status.code).to.equal(404); - expect(readReply2.recordsWrite).to.be.undefined; + expect(readReply2.entry!.recordsWrite).to.be.undefined; }); it('should only resume tasks that are timed-out up to the batch size when DWN starts', async () => { diff --git a/tests/handlers/records-delete.spec.ts b/tests/handlers/records-delete.spec.ts index 33692d323..a2ec48629 100644 --- a/tests/handlers/records-delete.spec.ts +++ b/tests/handlers/records-delete.spec.ts @@ -168,7 +168,7 @@ export function testRecordsDeleteHandler(): void { const aliceRead1Reply = await dwn.processMessage(alice.did, aliceRead1.message); expect(aliceRead1Reply.status.code).to.equal(200); - const aliceDataFetched = await DataStream.toBytes(aliceRead1Reply.data!); + const aliceDataFetched = await DataStream.toBytes(aliceRead1Reply.entry!.data!); expect(ArrayUtility.byteArraysEqual(aliceDataFetched, data)).to.be.true; // alice deletes the other record @@ -194,7 +194,7 @@ export function testRecordsDeleteHandler(): void { const bobRead1Reply = await dwn.processMessage(bob.did, bobRead1.message); expect(bobRead1Reply.status.code).to.equal(200); - const bobDataFetched = await DataStream.toBytes(bobRead1Reply.data!); + const bobDataFetched = await DataStream.toBytes(bobRead1Reply.entry!.data!); expect(ArrayUtility.byteArraysEqual(bobDataFetched, data)).to.be.true; }); diff --git a/tests/handlers/records-read.spec.ts b/tests/handlers/records-read.spec.ts index 0230ce60e..62f5dba51 100644 --- a/tests/handlers/records-read.spec.ts +++ b/tests/handlers/records-read.spec.ts @@ -98,11 +98,11 @@ export function testRecordsReadHandler(): void { const readReply = await dwn.processMessage(alice.did, recordsRead.message); expect(readReply.status.code).to.equal(200); - expect(readReply.recordsWrite).to.exist; - expect(readReply.recordsWrite?.authorization).to.deep.equal(message.authorization); - expect(readReply.recordsWrite?.descriptor).to.deep.equal(message.descriptor); + expect(readReply.entry!.recordsWrite).to.exist; + expect(readReply.entry!.recordsWrite?.authorization).to.deep.equal(message.authorization); + expect(readReply.entry!.recordsWrite?.descriptor).to.deep.equal(message.descriptor); - const dataFetched = await DataStream.toBytes(readReply.data!); + const dataFetched = await DataStream.toBytes(readReply.entry!.data!); expect(ArrayUtility.byteArraysEqual(dataFetched, dataBytes!)).to.be.true; }); @@ -147,7 +147,7 @@ export function testRecordsReadHandler(): void { const readReply = await dwn.processMessage(alice.did, recordsRead.message); expect(readReply.status.code).to.equal(200); - const dataFetched = await DataStream.toBytes(readReply.data!); + const dataFetched = await DataStream.toBytes(readReply.entry!.data!); expect(ArrayUtility.byteArraysEqual(dataFetched, dataBytes!)).to.be.true; }); @@ -172,7 +172,7 @@ export function testRecordsReadHandler(): void { const readReply = await dwn.processMessage(alice.did, recordsRead.message); expect(readReply.status.code).to.equal(200); - const dataFetched = await DataStream.toBytes(readReply.data!); + const dataFetched = await DataStream.toBytes(readReply.entry!.data!); expect(ArrayUtility.byteArraysEqual(dataFetched, dataBytes!)).to.be.true; }); @@ -198,10 +198,10 @@ export function testRecordsReadHandler(): void { const readReply = await dwn.processMessage(alice.did, recordsRead.message); expect(readReply.status.code).to.equal(200); - expect(readReply.recordsWrite).to.exist; - expect(readReply.recordsWrite?.descriptor).to.exist; + expect(readReply.entry!.recordsWrite).to.exist; + expect(readReply.entry!.recordsWrite?.descriptor).to.exist; - const dataFetched = await DataStream.toBytes(readReply.data!); + const dataFetched = await DataStream.toBytes(readReply.entry!.data!); expect(ArrayUtility.byteArraysEqual(dataFetched, dataBytes!)).to.be.true; }); @@ -253,10 +253,10 @@ export function testRecordsReadHandler(): void { const readReply = await dwn.processMessage(alice.did, recordsRead.message); expect(readReply.status.code).to.equal(200); - expect(readReply.recordsWrite).to.exist; - expect(readReply.recordsWrite?.descriptor).to.exist; + expect(readReply.entry!.recordsWrite).to.exist; + expect(readReply.entry!.recordsWrite?.descriptor).to.exist; - const dataFetched = await DataStream.toBytes(readReply.data!); + const dataFetched = await DataStream.toBytes(readReply.entry!.data!); expect(ArrayUtility.byteArraysEqual(dataFetched, dataBytes!)).to.be.true; // carol attempts to read Bob's record @@ -288,8 +288,8 @@ export function testRecordsReadHandler(): void { const reply = await dwn.processMessage(alice.did, messageData.message); expect(reply.status.code).to.equal(200); - expect(reply.initialWrite).to.exist; - expect(reply.initialWrite?.recordId).to.equal(write.message.recordId); + expect(reply.entry!.initialWrite).to.exist; + expect(reply.entry!.initialWrite?.recordId).to.equal(write.message.recordId); }); @@ -520,7 +520,7 @@ export function testRecordsReadHandler(): void { const fooPathReply = await dwn.processMessage(alice.did, fooPathRead.message); expect(fooPathReply.status.code).to.equal(200); - expect(fooPathReply.recordsWrite!.recordId).to.equal(foo1Write.message.recordId); + expect(fooPathReply.entry!.recordsWrite!.recordId).to.equal(foo1Write.message.recordId); }); it('should throw if requested filter has more than a single result', async () => { @@ -768,7 +768,7 @@ export function testRecordsReadHandler(): void { const threadRead = await RecordsRead.create({ signer : Jws.createSigner(bob), filter : { - recordId: participantReadReply.recordsWrite!.descriptor.parentId, + recordId: participantReadReply.entry!.recordsWrite!.descriptor.parentId, }, protocolRole: 'thread/participant' }); @@ -1436,11 +1436,11 @@ export function testRecordsReadHandler(): void { const recordsReadResponse = await dwn.processMessage(alice.did, recordRead.message); expect(recordsReadResponse.status.code).to.equal(200); - expect(recordsReadResponse.recordsWrite).to.exist; - expect(recordsReadResponse.data!).to.exist; + expect(recordsReadResponse.entry!.recordsWrite).to.exist; + expect(recordsReadResponse.entry!.data!).to.exist; sinon.assert.notCalled(dataStoreGet); - const readData = await DataStream.toBytes(recordsReadResponse.data!); + const readData = await DataStream.toBytes(recordsReadResponse.entry!.data!); expect(readData).to.eql(dataBytes); }); @@ -1467,11 +1467,11 @@ export function testRecordsReadHandler(): void { const recordsReadResponse = await dwn.processMessage(alice.did, recordRead.message); expect(recordsReadResponse.status.code).to.equal(200); - expect(recordsReadResponse.recordsWrite).to.exist; - expect(recordsReadResponse.data!).to.exist; + expect(recordsReadResponse.entry!.recordsWrite).to.exist; + expect(recordsReadResponse.entry!.data!).to.exist; sinon.assert.calledOnce(dataStoreGet); - const readData = await DataStream.toBytes(recordsReadResponse.data!); + const readData = await DataStream.toBytes(recordsReadResponse.entry!.data!); expect(readData).to.eql(dataBytes); }); }); @@ -1550,8 +1550,8 @@ export function testRecordsReadHandler(): void { // test able to derive correct key using `schemas` scheme from root key to decrypt the message const readReply = await dwn.processMessage(alice.did, recordsRead.message); expect(readReply.status.code).to.equal(200); - const recordsWriteMessage = readReply.recordsWrite!; - const cipherStream = readReply.data!; + const recordsWriteMessage = readReply.entry!.recordsWrite!; + const cipherStream = readReply.entry!.data!; const plaintextDataStream = await Records.decrypt(recordsWriteMessage, schemaDerivedPrivateKey, cipherStream); const plaintextBytes = await DataStream.toBytes(plaintextDataStream); @@ -1561,7 +1561,7 @@ export function testRecordsReadHandler(): void { // test able to derive correct key using `dataFormat` scheme from root key to decrypt the message const readReply2 = await dwn.processMessage(alice.did, recordsRead.message); // send the same read message to get a new cipher stream expect(readReply2.status.code).to.equal(200); - const cipherStream2 = readReply2.data!; + const cipherStream2 = readReply2.entry!.data!; const plaintextDataStream2 = await Records.decrypt(recordsWriteMessage, rootPrivateKeyWithDataFormatsScheme, cipherStream2); const plaintextBytes2 = await DataStream.toBytes(plaintextDataStream2); @@ -1571,7 +1571,7 @@ export function testRecordsReadHandler(): void { // test unable to decrypt the message if dataFormat-derived key is derived without taking `schema` as input to derivation path const readReply3 = await dwn.processMessage(alice.did, recordsRead.message); // process the same read message to get a new cipher stream expect(readReply3.status.code).to.equal(200); - const cipherStream3 = readReply3.data!; + const cipherStream3 = readReply3.entry!.data!; const invalidDerivationPath = [KeyDerivationScheme.DataFormats, message.descriptor.dataFormat]; const inValidDescendantPrivateKey: DerivedPrivateJwk @@ -1639,8 +1639,8 @@ export function testRecordsReadHandler(): void { // test able to derive correct key using `dataFormat` scheme from root key to decrypt the message const readReply = await dwn.processMessage(alice.did, recordsRead.message); // send the same read message to get a new cipher stream expect(readReply.status.code).to.equal(200); - const cipherStream = readReply.data!; - const recordsWriteMessage = readReply.recordsWrite!; + const cipherStream = readReply.entry!.data!; + const recordsWriteMessage = readReply.entry!.recordsWrite!; const plaintextDataStream = await Records.decrypt(recordsWriteMessage, rootPrivateKeyWithDataFormatsScheme, cipherStream); const plaintextBytes = await DataStream.toBytes(plaintextDataStream); @@ -1756,8 +1756,8 @@ export function testRecordsReadHandler(): void { const readReply = await dwn.processMessage(alice.did, recordsRead.message); expect(readReply.status.code).to.equal(200); - const fetchedRecordsWrite = readReply.recordsWrite!; - const cipherStream = readReply.data!; + const fetchedRecordsWrite = readReply.entry!.recordsWrite!; + const cipherStream = readReply.entry!.data!; const derivationPathFromReadContext = Records.constructKeyDerivationPathUsingProtocolContextScheme(fetchedRecordsWrite.contextId); const protocolContextDerivedPrivateJwk = await HdKey.derivePrivateKey(bobRootPrivateKey, derivationPathFromReadContext); @@ -1799,8 +1799,8 @@ export function testRecordsReadHandler(): void { const readByBobReply = await dwn.processMessage(bob.did, recordsReadByBob.message); expect(readByBobReply.status.code).to.equal(200); - const fetchedRecordsWrite2 = readByBobReply.recordsWrite!; - const cipherStream2 = readByBobReply.data!; + const fetchedRecordsWrite2 = readByBobReply.entry!.recordsWrite!; + const cipherStream2 = readByBobReply.entry!.data!; const plaintextDataStream2 = await Records.decrypt(fetchedRecordsWrite2, protocolContextDerivedPrivateJwk, cipherStream2); const plaintextBytes2 = await DataStream.toBytes(plaintextDataStream2); @@ -1897,8 +1897,8 @@ export function testRecordsReadHandler(): void { derivedPrivateKey : alice.keyPair.privateJwk }; - const fetchedRecordsWrite = readReply.recordsWrite!; - const cipherStream = readReply.data!; + const fetchedRecordsWrite = readReply.entry!.recordsWrite!; + const cipherStream = readReply.entry!.data!; const plaintextDataStream = await Records.decrypt(fetchedRecordsWrite, rootPrivateKey, cipherStream); const plaintextBytes = await DataStream.toBytes(plaintextDataStream); @@ -1911,8 +1911,8 @@ export function testRecordsReadHandler(): void { const relativeDescendantDerivationPath = Records.constructKeyDerivationPath(KeyDerivationScheme.ProtocolPath, fetchedRecordsWrite); const derivedPrivateKey: DerivedPrivateJwk = await HdKey.derivePrivateKey(rootPrivateKey, relativeDescendantDerivationPath); - const fetchedRecordsWrite2 = readReply2.recordsWrite!; - const cipherStream2 = readReply2.data!; + const fetchedRecordsWrite2 = readReply2.entry!.recordsWrite!; + const cipherStream2 = readReply2.entry!.data!; const plaintextDataStream2 = await Records.decrypt(fetchedRecordsWrite2, derivedPrivateKey, cipherStream2); const plaintextBytes2 = await DataStream.toBytes(plaintextDataStream2); expect(ArrayUtility.byteArraysEqual(plaintextBytes2, bobMessageBytes)).to.be.true; diff --git a/tests/handlers/records-write.spec.ts b/tests/handlers/records-write.spec.ts index 8fbd4b7e2..86d7827e8 100644 --- a/tests/handlers/records-write.spec.ts +++ b/tests/handlers/records-write.spec.ts @@ -287,7 +287,7 @@ export function testRecordsWriteHandler(): void { }); const recordsReadReply = await dwn.processMessage(tenant, recordsRead.message); expect(recordsReadReply.status.code).to.equal(200); - expect(recordsReadReply.recordsWrite?.descriptor.dataFormat).to.equal(newDataFormat); + expect(recordsReadReply.entry!.recordsWrite?.descriptor.dataFormat).to.equal(newDataFormat); }); it('should not allow changes to immutable properties', async () => { @@ -359,8 +359,8 @@ export function testRecordsWriteHandler(): void { const readMessageReply = await dwn.processMessage(tenant, readMessage.message); expect(readMessageReply.status.code).to.equal(200); - expect(readMessageReply.recordsWrite).to.exist; - const data = await DataStream.toBytes(readMessageReply.data!); + expect(readMessageReply.entry!.recordsWrite).to.exist; + const data = await DataStream.toBytes(readMessageReply.entry!.data!); expect(data).to.eql(dataBytes); }); @@ -478,8 +478,8 @@ export function testRecordsWriteHandler(): void { const readMessageReply = await dwn.processMessage(tenant, readMessage.message); expect(readMessageReply.status.code).to.equal(200); - expect(readMessageReply.recordsWrite).to.exist; - const data = await DataStream.toBytes(readMessageReply.data!); + expect(readMessageReply.entry!.recordsWrite).to.exist; + const data = await DataStream.toBytes(readMessageReply.entry!.data!); expect(data).to.eql(dataBytes); }); @@ -511,8 +511,8 @@ export function testRecordsWriteHandler(): void { const readMessageReply = await dwn.processMessage(tenant, readMessage.message); expect(readMessageReply.status.code).to.equal(200); - expect(readMessageReply.recordsWrite).to.exist; - const data = await DataStream.toBytes(readMessageReply.data!); + expect(readMessageReply.entry!.recordsWrite).to.exist; + const data = await DataStream.toBytes(readMessageReply.entry!.data!); expect(data).to.eql(dataBytes); }); }); @@ -736,7 +736,7 @@ export function testRecordsWriteHandler(): void { const readReply = await dwn.processMessage(alice.did, read.message); expect(readReply.status.code).to.equal(200); - const readDataBytes = await DataStream.toBytes(readReply.data!); + const readDataBytes = await DataStream.toBytes(readReply.entry!.data!); expect(ArrayUtility.byteArraysEqual(readDataBytes, write2.dataBytes!)).to.be.true; }); @@ -790,7 +790,7 @@ export function testRecordsWriteHandler(): void { const readReply = await dwn.processMessage(alice.did, read.message); expect(readReply.status.code).to.equal(200); - const readDataBytes = await DataStream.toBytes(readReply.data!); + const readDataBytes = await DataStream.toBytes(readReply.entry!.data!); expect(ArrayUtility.byteArraysEqual(readDataBytes, write2.dataBytes!)).to.be.true; }); @@ -2505,7 +2505,7 @@ export function testRecordsWriteHandler(): void { }); const recordsReadReply = await dwn.processMessage(alice.did, recordsRead.message); expect(recordsReadReply.status.code).to.equal(200); - expect(recordsReadReply.recordsWrite?.descriptor.dataFormat).to.equal(protocolDefinition.types.image.dataFormats[1]); + expect(recordsReadReply.entry!.recordsWrite?.descriptor.dataFormat).to.equal(protocolDefinition.types.image.dataFormats[1]); }); it('#690 - should allow any data format for a record if protocol definition does not explicitly specify the list of allowed data formats', async () => { @@ -2557,7 +2557,7 @@ export function testRecordsWriteHandler(): void { }); const recordsReadReply = await dwn.processMessage(alice.did, recordsRead.message); expect(recordsReadReply.status.code).to.equal(200); - expect(recordsReadReply.recordsWrite?.descriptor.dataFormat).to.equal(newDataFormat); + expect(recordsReadReply.entry!.recordsWrite?.descriptor.dataFormat).to.equal(newDataFormat); }); it('should fail authorization if record schema is not allowed at the hierarchical level attempted for the RecordsWrite', async () => { diff --git a/tests/scenarios/deleted-record.spec.ts b/tests/scenarios/deleted-record.spec.ts index 69c25c405..08590156f 100644 --- a/tests/scenarios/deleted-record.spec.ts +++ b/tests/scenarios/deleted-record.spec.ts @@ -108,10 +108,10 @@ export function testDeletedRecordScenarios(): void { // Expected outcome: Alice should get a 404 error with the reply containing the deleted record and the initial write of the record. expect(readReply.status.code).to.equal(404); - expect(readReply.recordsDelete).to.exist; - expect(readReply.recordsDelete).to.deep.equal(recordsDelete.message); - expect(readReply.initialWrite).to.exist; - expect(readReply.initialWrite).to.deep.equal(recordsWriteMessage); + expect(readReply.entry!.recordsDelete).to.exist; + expect(readReply.entry!.recordsDelete).to.deep.equal(recordsDelete.message); + expect(readReply.entry!.initialWrite).to.exist; + expect(readReply.entry!.initialWrite).to.deep.equal(recordsWriteMessage); }); }); } \ No newline at end of file diff --git a/tests/scenarios/end-to-end-tests.spec.ts b/tests/scenarios/end-to-end-tests.spec.ts index ac9d0b5f4..7081e9a68 100644 --- a/tests/scenarios/end-to-end-tests.spec.ts +++ b/tests/scenarios/end-to-end-tests.spec.ts @@ -201,7 +201,7 @@ export function testEndToEndScenarios(): void { }); const threadReadReply = await dwn.processMessage(alice.did, threadRead.message) as RecordsReadReply; expect(threadReadReply.status.code).to.equal(200); - expect(threadReadReply.recordsWrite).to.exist; + expect(threadReadReply.entry!.recordsWrite).to.exist; // Test Bob can invoke his 'participant' role to read the chat message // TODO: #555 - We currently lack role-authorized RecordsQuery for a realistic scenario (https://github.com/TBD54566975/dwn-sdk-js/issues/555) @@ -215,7 +215,7 @@ export function testEndToEndScenarios(): void { }); const chatReadReply = await dwn.processMessage(alice.did, chatRead.message) as RecordsReadReply; expect(chatReadReply.status.code).to.equal(200); - expect(chatReadReply.recordsWrite).to.exist; + expect(chatReadReply.entry!.recordsWrite).to.exist; // 7. Bob is able to decrypt all thread content // Bob decrypts the participant message to obtain the context-derived private key @@ -224,8 +224,8 @@ export function testEndToEndScenarios(): void { derivationScheme : KeyDerivationScheme.ProtocolPath, derivedPrivateKey : bob.keyPair.privateJwk }; - const participantRecordWriteFetched = participantReadReply.recordsWrite!; - const encryptedContextDerivedPrivateKeyBytes = await DataStream.toBytes(participantReadReply.data!); // to create streams for testing + const participantRecordWriteFetched = participantReadReply.entry!.recordsWrite!; + const encryptedContextDerivedPrivateKeyBytes = await DataStream.toBytes(participantReadReply.entry!.data!); // to create streams for testing const derivationPathFromProtocolPath = Records.constructKeyDerivationPathUsingProtocolPathScheme(participantRecordWriteFetched.descriptor); const bobProtocolPathDerivedPrivateKey = await HdKey.derivePrivateKey(bobRootKey, derivationPathFromProtocolPath); const decryptedContextDerivedKeyStream = await Records.decrypt( @@ -247,16 +247,16 @@ export function testEndToEndScenarios(): void { // Verify that Bob can now decrypt Alice's chat thread record using the decrypted context-derived key const decryptedChatThread = await Records.decrypt( - threadReadReply.recordsWrite!, + threadReadReply.entry!.recordsWrite!, decryptedContextDerivedPrivateKey, - threadReadReply.data! + threadReadReply.entry!.data! ); expect(await DataStream.toBytes(decryptedChatThread)).to.deep.equal(threadBytes); // Verify that Bob can now decrypt Alice's chat message using the decrypted context-derived key - const encryptedChatMessageBytes = await DataStream.toBytes(chatReadReply.data!); // to create streams for testing + const encryptedChatMessageBytes = await DataStream.toBytes(chatReadReply.entry!.data!); // to create streams for testing const decryptedChatMessage = await Records.decrypt( - chatReadReply.recordsWrite!, + chatReadReply.entry!.recordsWrite!, decryptedContextDerivedPrivateKey, DataStream.fromBytes(encryptedChatMessageBytes) ); @@ -264,7 +264,7 @@ export function testEndToEndScenarios(): void { // Arguably unrelated to the scenario, but let's also sanity check that Alice's root key can also decrypt the encrypted chat message const decryptedChatMessageStream2 = await Records.decrypt( - chatReadReply.recordsWrite!, + chatReadReply.entry!.recordsWrite!, aliceRootKey, DataStream.fromBytes(encryptedChatMessageBytes) ); diff --git a/tests/scenarios/nested-roles.spec.ts b/tests/scenarios/nested-roles.spec.ts index 62e59975c..59a01095a 100644 --- a/tests/scenarios/nested-roles.spec.ts +++ b/tests/scenarios/nested-roles.spec.ts @@ -129,7 +129,7 @@ export function testNestedRoleScenarios(): void { }); const bobCommunityReadReply = await dwn.processMessage(alice.did, bobCommunityRead.message); expect(bobCommunityReadReply.status.code).to.equal(200); - expect(bobCommunityReadReply.recordsWrite?.recordId).to.equal(communityRecord.message.recordId); + expect(bobCommunityReadReply.entry!.recordsWrite?.recordId).to.equal(communityRecord.message.recordId); // 4b. Bob can create gated-channels 1 & 2 in the community const channel1Record = await TestDataGenerator.generateRecordsWrite({ @@ -225,7 +225,7 @@ export function testNestedRoleScenarios(): void { }); const carolReadReply = await dwn.processMessage(alice.did, carolRead.message); expect(carolReadReply.status.code).to.equal(200); - expect(carolReadReply.recordsWrite?.recordId).to.equal(channel1Record.message.recordId); + expect(carolReadReply.entry!.recordsWrite?.recordId).to.equal(channel1Record.message.recordId); // 7. Carol CANNOT add anyone as a participant in the gated-channel 2 since she is not a participant in the channel const participantCarolRecord = await TestDataGenerator.generateRecordsWrite({