diff --git a/.changeset/big-tomatoes-obey.md b/.changeset/big-tomatoes-obey.md new file mode 100644 index 000000000..87fd97452 --- /dev/null +++ b/.changeset/big-tomatoes-obey.md @@ -0,0 +1,5 @@ +--- +"@web5/api": patch +--- + +When updating a record, we must include the `parentContextId` in the create options diff --git a/packages/api/src/record.ts b/packages/api/src/record.ts index 27927df8a..0de337695 100644 --- a/packages/api/src/record.ts +++ b/packages/api/src/record.ts @@ -572,10 +572,16 @@ export class Record implements RecordModel { * @beta */ async update({ dateModified, data, ...params }: RecordUpdateParams): Promise { + + // if there is a parentId, we remove it from the descriptor and set a parentContextId + const { parentId, ...descriptor } = this._descriptor; + const parentContextId = parentId ? this._contextId.split('/').slice(0, -1).join('/') : undefined; + // Begin assembling the update message. let updateMessage: DwnMessageParams[DwnInterface.RecordsWrite] = { - ...this._descriptor, + ...descriptor, ...params, + parentContextId, messageTimestamp : dateModified, // Map Record class `dateModified` property to DWN SDK `messageTimestamp` recordId : this._recordId }; diff --git a/packages/api/tests/record.spec.ts b/packages/api/tests/record.spec.ts index 7b5a27e97..feaa544ea 100644 --- a/packages/api/tests/record.spec.ts +++ b/packages/api/tests/record.spec.ts @@ -2263,6 +2263,60 @@ describe('Record', () => { expect(updatedData).to.equal('bye'); }); + it('updates a record which has a parent reference', async () => { + // install a protocol + let { protocol, status: protocolStatus } = await dwnAlice.protocols.configure({ + message: { + definition: emailProtocolDefinition, + } + }); + expect(protocolStatus.code).to.equal(202); + expect(protocolStatus).to.exist; + + // create a parent thread + const { status: threadStatus, record: threadRecord } = await dwnAlice.records.write({ + data : 'Hello, world!', + message : { + protocol : protocol.definition.protocol, + schema : emailProtocolDefinition.types.thread.schema, + protocolPath : 'thread' + } + }); + + expect(threadStatus.code).to.equal(202); + expect(threadRecord).to.not.be.undefined; + + // create an email with the thread as a parent + const { status: emailStatus, record: emailRecord } = await dwnAlice.records.write({ + data : 'Hello, world!', + message : { + parentContextId : threadRecord.contextId, + protocol : emailProtocolDefinition.protocol, + protocolPath : 'thread/email', + schema : emailProtocolDefinition.types.email.schema + } + }); + expect(emailStatus.code).to.equal(202); + expect(emailRecord).to.not.be.undefined; + + + // update email record + const updateResult = await emailRecord!.update({ data: 'updated email record' }); + expect(updateResult.status.code).to.equal(202); + + const readResult = await dwnAlice.records.read({ + message: { + filter: { + recordId: emailRecord.id + } + } + }); + + expect(readResult.status.code).to.equal(200); + expect(readResult.record).to.not.be.undefined; + expect(await readResult.record.data.text()).to.equal('updated email record'); + }); + it('returns new dateModified after each update', async () => { // Initial write of the record. const { status, record } = await dwnAlice.records.write({