@enbox/api 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +505 -138
  2. package/dist/browser.mjs +23 -13
  3. package/dist/browser.mjs.map +4 -4
  4. package/dist/esm/advanced.js +11 -0
  5. package/dist/esm/advanced.js.map +1 -0
  6. package/dist/esm/define-protocol.js +3 -3
  7. package/dist/esm/dwn-api.js +56 -114
  8. package/dist/esm/dwn-api.js.map +1 -1
  9. package/dist/esm/dwn-reader-api.js +128 -0
  10. package/dist/esm/dwn-reader-api.js.map +1 -0
  11. package/dist/esm/index.js +3 -2
  12. package/dist/esm/index.js.map +1 -1
  13. package/dist/esm/live-query.js +5 -4
  14. package/dist/esm/live-query.js.map +1 -1
  15. package/dist/esm/read-only-record.js +255 -0
  16. package/dist/esm/read-only-record.js.map +1 -0
  17. package/dist/esm/record.js +46 -57
  18. package/dist/esm/record.js.map +1 -1
  19. package/dist/esm/typed-web5.js +242 -0
  20. package/dist/esm/typed-web5.js.map +1 -0
  21. package/dist/esm/web5.js +71 -3
  22. package/dist/esm/web5.js.map +1 -1
  23. package/dist/types/advanced.d.ts +12 -0
  24. package/dist/types/advanced.d.ts.map +1 -0
  25. package/dist/types/define-protocol.d.ts +3 -3
  26. package/dist/types/dwn-api.d.ts +13 -92
  27. package/dist/types/dwn-api.d.ts.map +1 -1
  28. package/dist/types/dwn-reader-api.d.ts +138 -0
  29. package/dist/types/dwn-reader-api.d.ts.map +1 -0
  30. package/dist/types/index.d.ts +3 -2
  31. package/dist/types/index.d.ts.map +1 -1
  32. package/dist/types/live-query.d.ts +13 -1
  33. package/dist/types/live-query.d.ts.map +1 -1
  34. package/dist/types/protocol-types.d.ts +2 -2
  35. package/dist/types/read-only-record.d.ts +133 -0
  36. package/dist/types/read-only-record.d.ts.map +1 -0
  37. package/dist/types/record.d.ts +37 -17
  38. package/dist/types/record.d.ts.map +1 -1
  39. package/dist/types/{typed-dwn-api.d.ts → typed-web5.d.ts} +70 -73
  40. package/dist/types/typed-web5.d.ts.map +1 -0
  41. package/dist/types/web5.d.ts +79 -3
  42. package/dist/types/web5.d.ts.map +1 -1
  43. package/package.json +10 -6
  44. package/src/advanced.ts +29 -0
  45. package/src/define-protocol.ts +3 -3
  46. package/src/dwn-api.ts +91 -232
  47. package/src/dwn-reader-api.ts +255 -0
  48. package/src/index.ts +3 -2
  49. package/src/live-query.ts +20 -4
  50. package/src/protocol-types.ts +2 -2
  51. package/src/read-only-record.ts +328 -0
  52. package/src/record.ts +116 -86
  53. package/src/typed-web5.ts +445 -0
  54. package/src/web5.ts +104 -5
  55. package/dist/esm/typed-dwn-api.js +0 -182
  56. package/dist/esm/typed-dwn-api.js.map +0 -1
  57. package/dist/types/typed-dwn-api.d.ts.map +0 -1
  58. package/src/typed-dwn-api.ts +0 -370
package/src/dwn-api.ts CHANGED
@@ -21,20 +21,14 @@ import {
21
21
  AgentPermissionsApi,
22
22
  } from '@enbox/agent';
23
23
 
24
- import { isEmptyObject } from '@enbox/common';
25
24
  import { DwnInterface, getRecordAuthor } from '@enbox/agent';
26
25
 
27
- import type { ProtocolDefinition } from '@enbox/dwn-sdk-js';
28
-
29
- import type { SchemaMap, TypedProtocol } from './protocol-types.js';
30
-
31
26
  import { dataToBlob } from './utils.js';
32
27
  import { LiveQuery } from './live-query.js';
33
28
  import { PermissionGrant } from './permission-grant.js';
34
29
  import { PermissionRequest } from './permission-request.js';
35
30
  import { Protocol } from './protocol.js';
36
31
  import { Record } from './record.js';
37
- import { TypedDwnApi } from './typed-dwn-api.js';
38
32
 
39
33
  /**
40
34
  * Represents the request payload for fetching permission requests from a Decentralized Web Node (DWN).
@@ -50,13 +44,11 @@ export type FetchRequestsRequest = Omit<FetchPermissionRequestParams, 'author' |
50
44
  * Represents the request payload for fetching permission grants from a Decentralized Web Node (DWN).
51
45
  *
52
46
  * Optionally, specify a remote DWN target in the `from` property to fetch requests from.
53
- * Optionally, specify whether to check if the grant is revoked in the `checkRevoked` property.
47
+ * Revoked grants are filtered out by default; set `checkRevoked: false` to include them.
54
48
  */
55
49
  export type FetchGrantsRequest = Omit<FetchPermissionsParams, 'author' | 'target' | 'remote'> & {
56
50
  /** Optional DID specifying the remote target DWN tenant to be queried. */
57
51
  from?: string;
58
- /** Optionally check if the grant has been revoked. */
59
- checkRevoked?: boolean;
60
52
  };
61
53
 
62
54
  /**
@@ -64,9 +56,7 @@ export type FetchGrantsRequest = Omit<FetchPermissionsParams, 'author' | 'target
64
56
  *
65
57
  * This request type is used to specify the configuration options for the protocol.
66
58
  */
67
- export type ProtocolsConfigureRequest = {
68
- /** Configuration options for the protocol. */
69
- message: Omit<DwnMessageParams[DwnInterface.ProtocolsConfigure], 'signer'>;
59
+ export type ProtocolsConfigureRequest = Omit<DwnMessageParams[DwnInterface.ProtocolsConfigure], 'signer'> & {
70
60
  /** When true, derives and injects $encryption public keys into the protocol definition. */
71
61
  encryption?: boolean;
72
62
  };
@@ -92,12 +82,9 @@ export type ProtocolsConfigureResponse = DwnResponseStatus & {
92
82
  * target the local DWN. If the `from` property is provided, the query will target the specified
93
83
  * remote DWN.
94
84
  */
95
- export type ProtocolsQueryRequest = {
85
+ export type ProtocolsQueryRequest = Omit<DwnMessageParams[DwnInterface.ProtocolsQuery], 'signer'> & {
96
86
  /** Optional DID specifying the remote target DWN tenant to be queried. */
97
87
  from?: string;
98
-
99
- /** Query filters and options that influence the results returned. */
100
- message: Omit<DwnMessageParams[DwnInterface.ProtocolsQuery], 'signer'>
101
88
  };
102
89
 
103
90
  /**
@@ -109,40 +96,6 @@ export type ProtocolsQueryResponse = DwnResponseStatus & {
109
96
  protocols: Protocol[];
110
97
  };
111
98
 
112
- /**
113
- * Type alias for {@link RecordsWriteRequest}
114
- */
115
- export type RecordsCreateRequest = RecordsWriteRequest;
116
-
117
- /**
118
- * Type alias for {@link RecordsWriteResponse}
119
- */
120
- export type RecordsCreateResponse = RecordsWriteResponse;
121
-
122
- /**
123
- * Represents a request to create a new record based on an existing one.
124
- *
125
- * This request type allows specifying the new data for the record, along with any additional
126
- * message parameters required for the write operation.
127
- */
128
- export type RecordsCreateFromRequest = {
129
- /** The DID of the entity authoring the record. */
130
- author: string;
131
- /** The new data for the record. */
132
- data: unknown;
133
- /** Optional additional parameters for the record write operation */
134
- message?: Omit<DwnMessageParams[DwnInterface.RecordsWrite], 'signer'>;
135
- /** The existing record instance that is being used as a basis for the new record. */
136
- record: Record;
137
- /**
138
- * Controls whether the new record should be auto-encrypted.
139
- *
140
- * If omitted, auto-detected from the source record: if the source record was
141
- * encrypted, the new record is automatically encrypted with a fresh DEK.
142
- */
143
- encryption?: boolean;
144
- };
145
-
146
99
  /**
147
100
  * Defines a request to delete a record from the Decentralized Web Node (DWN).
148
101
  *
@@ -150,15 +103,12 @@ export type RecordsCreateFromRequest = {
150
103
  * message parameters for the delete operation. If the `from` property is not provided, the record
151
104
  * will be deleted from the local DWN.
152
105
  */
153
- export type RecordsDeleteRequest = {
106
+ export type RecordsDeleteRequest = Omit<DwnMessageParams[DwnInterface.RecordsDelete], 'signer'> & {
154
107
  /** Optional DID specifying the remote target DWN tenant the record will be deleted from. */
155
108
  from?: string;
156
109
 
157
- /** Records must be scoped to a specific protocol */
110
+ /** Protocol URI for permission grant resolution. */
158
111
  protocol?: string;
159
-
160
- /** The parameters for the delete operation. */
161
- message: Omit<DwnMessageParams[DwnInterface.RecordsDelete], 'signer'>;
162
112
  };
163
113
 
164
114
  /**
@@ -168,16 +118,10 @@ export type RecordsDeleteRequest = {
168
118
  * parameters, and optionally the target DWN to query from. If the `from` property is not provided,
169
119
  * the query will target the local DWN.
170
120
  */
171
- export type RecordsQueryRequest = {
121
+ export type RecordsQueryRequest = Omit<DwnMessageParams[DwnInterface.RecordsQuery], 'signer'> & {
172
122
  /** Optional DID specifying the remote target DWN tenant to query from and return results. */
173
123
  from?: string;
174
124
 
175
- /** Records must be scoped to a specific protocol */
176
- protocol?: string;
177
-
178
- /** The parameters for the query operation, detailing the criteria for selecting records. */
179
- message: Omit<DwnMessageParams[DwnInterface.RecordsQuery], 'signer'>;
180
-
181
125
  /** When true, automatically decrypts encrypted records in the query results. */
182
126
  encryption?: boolean;
183
127
  };
@@ -188,7 +132,7 @@ export type RecordsQueryRequest = {
188
132
  */
189
133
  export type RecordsQueryResponse = DwnResponseStatus & {
190
134
  /** Array of records matching the query. */
191
- records?: Record[]
135
+ records: Record[];
192
136
 
193
137
  /** If there are additional results, the messageCid of the last record will be returned as a pagination cursor. */
194
138
  cursor?: DwnPaginationCursor;
@@ -201,16 +145,13 @@ export type RecordsQueryResponse = DwnResponseStatus & {
201
145
  * additional parameters for the read operation. It's useful for fetching the details of a single
202
146
  * record by its identifier or other criteria.
203
147
  */
204
- export type RecordsReadRequest = {
148
+ export type RecordsReadRequest = Omit<DwnMessageParams[DwnInterface.RecordsRead], 'signer'> & {
205
149
  /** Optional DID specifying the remote target DWN tenant the record will be read from. */
206
150
  from?: string;
207
151
 
208
- /** Records must be scoped to a specific protocol */
152
+ /** Protocol URI for permission grant resolution. */
209
153
  protocol?: string;
210
154
 
211
- /** The parameters for the read operation, detailing the criteria for selecting the record. */
212
- message: Omit<DwnMessageParams[DwnInterface.RecordsRead], 'signer'>;
213
-
214
155
  /** When true, automatically decrypts the encrypted record data. */
215
156
  encryption?: boolean;
216
157
  };
@@ -231,15 +172,9 @@ export type RecordsReadResponse = DwnResponseStatus & {
231
172
  * matching records alongside a real-time stream of deduplicated, semantically-
232
173
  * typed change events (`create`, `update`, `delete`).
233
174
  */
234
- export type RecordsSubscribeRequest = {
175
+ export type RecordsSubscribeRequest = Omit<DwnMessageParams[DwnInterface.RecordsSubscribe], 'signer'> & {
235
176
  /** Optional DID specifying the remote target DWN tenant to subscribe from. */
236
177
  from?: string;
237
-
238
- /** Records must be scoped to a specific protocol. */
239
- protocol?: string;
240
-
241
- /** The parameters for the subscription operation, detailing the criteria for the subscription filter. */
242
- message: Omit<DwnMessageParams[DwnInterface.RecordsSubscribe], 'signer'>;
243
178
  };
244
179
 
245
180
  /** Encapsulates the response from a DWN RecordsSubscribeRequest. */
@@ -254,18 +189,12 @@ export type RecordsSubscribeResponse = DwnResponseStatus & {
254
189
  * This request type allows specifying the data for the new or updated record, along with any
255
190
  * additional message parameters required for the write operation, and an optional flag to indicate
256
191
  * whether the record should be immediately stored.
257
- *
258
- * @param data -
259
- * @param message - , excluding the signer.
260
- * @param store -
261
192
  */
262
- export type RecordsWriteRequest = {
193
+ export type RecordsWriteRequest = Omit<Partial<DwnMessageParams[DwnInterface.RecordsWrite]>, 'signer' | 'data' | 'protocol' | 'protocolPath'> &
194
+ Pick<DwnMessageParams[DwnInterface.RecordsWrite], 'protocol' | 'protocolPath'> & {
263
195
  /** The data payload for the record, which can be of any type. */
264
196
  data: unknown;
265
197
 
266
- /** Optional additional parameters for the record write operation. */
267
- message?: Omit<Partial<DwnMessageParams[DwnInterface.RecordsWrite]>, 'signer'>;
268
-
269
198
  /**
270
199
  * Optional flag indicating whether the record should be immediately stored. If true, the record
271
200
  * is persisted in the DWN as part of the write operation. If false, the record is created,
@@ -294,7 +223,7 @@ export type RecordsWriteResponse = DwnResponseStatus & {
294
223
  * The `Record` instance representing the record that was successfully written to the
295
224
  * DWN as a result of the write operation.
296
225
  */
297
- record?: Record
226
+ record: Record;
298
227
  };
299
228
 
300
229
  /**
@@ -323,30 +252,6 @@ export class DwnApi {
323
252
  this.permissionsApi = new AgentPermissionsApi({ agent: this.agent });
324
253
  }
325
254
 
326
- /**
327
- * Returns a {@link TypedDwnApi} scoped to the given typed protocol.
328
- *
329
- * The returned API provides path autocompletion, typed data payloads,
330
- * and automatically injects the protocol URI and protocolPath into every
331
- * DWN operation.
332
- *
333
- * @param protocol - A typed protocol created via `defineProtocol()`.
334
- * @returns A `TypedDwnApi` instance bound to the given protocol.
335
- *
336
- * @example
337
- * ```ts
338
- * const social = dwn.using(SocialGraphProtocol);
339
- * const { record } = await social.write('friend', {
340
- * data: { did: 'did:example:alice' },
341
- * });
342
- * ```
343
- */
344
- public using<D extends ProtocolDefinition, M extends SchemaMap>(
345
- protocol: TypedProtocol<D, M>,
346
- ): TypedDwnApi<D, M> {
347
- return new TypedDwnApi<D, M>(this, protocol);
348
- }
349
-
350
255
  /**
351
256
  * API to interact with Grants
352
257
  *
@@ -427,7 +332,7 @@ export class DwnApi {
427
332
  * Query permission grants. You can filter by grantee, grantor, protocol and specify if you want to query a remote DWN.
428
333
  */
429
334
  queryGrants: async(request: FetchGrantsRequest = {}): Promise<PermissionGrant[]> => {
430
- const { checkRevoked, from, ...params } = request;
335
+ const { from, ...params } = request;
431
336
  const remote = from !== undefined;
432
337
  const author = this.delegateDid ?? this.connectedDid;
433
338
  const target = from ?? this.delegateDid ?? this.connectedDid;
@@ -446,12 +351,6 @@ export class DwnApi {
446
351
  message : permission.message,
447
352
  };
448
353
 
449
- if (checkRevoked) {
450
- const grantRecordId = permission.grant.id;
451
- if (await this.permissionsApi.isGrantRevoked({ author, target, grantRecordId, remote })) {
452
- continue;
453
- }
454
- }
455
354
  grants.push(await PermissionGrant.parse(grantParams));
456
355
  }
457
356
 
@@ -472,20 +371,21 @@ export class DwnApi {
472
371
  * Configure method, used to setup a new protocol (or update) with the passed definitions
473
372
  */
474
373
  configure: async (request: ProtocolsConfigureRequest): Promise<ProtocolsConfigureResponse> => {
475
-
476
- const agentRequest:ProcessDwnRequest<DwnInterface.ProtocolsConfigure> = {
477
- author : this.connectedDid,
478
- messageParams : request.message,
479
- messageType : DwnInterface.ProtocolsConfigure,
480
- target : this.connectedDid,
481
- encryption : request.encryption,
374
+ const { encryption, ...messageParams } = request;
375
+
376
+ const agentRequest: ProcessDwnRequest<DwnInterface.ProtocolsConfigure> = {
377
+ author : this.connectedDid,
378
+ messageParams,
379
+ messageType : DwnInterface.ProtocolsConfigure,
380
+ target : this.connectedDid,
381
+ encryption,
482
382
  };
483
383
 
484
384
  if (this.delegateDid) {
485
385
  const { message: delegatedGrant } = await this.permissionsApi.getPermissionForRequest({
486
386
  connectedDid : this.connectedDid,
487
387
  delegateDid : this.delegateDid,
488
- protocol : request.message.definition.protocol,
388
+ protocol : messageParams.definition.protocol,
489
389
  delegate : true,
490
390
  cached : true,
491
391
  messageType : agentRequest.messageType
@@ -515,11 +415,13 @@ export class DwnApi {
515
415
  * Query the available protocols
516
416
  */
517
417
  query: async (request: ProtocolsQueryRequest): Promise<ProtocolsQueryResponse> => {
418
+ const { from, ...messageParams } = request;
419
+
518
420
  const agentRequest: ProcessDwnRequest<DwnInterface.ProtocolsQuery> = {
519
- author : this.connectedDid,
520
- messageParams : request.message,
521
- messageType : DwnInterface.ProtocolsQuery,
522
- target : request.from || this.connectedDid
421
+ author : this.connectedDid,
422
+ messageParams,
423
+ messageType : DwnInterface.ProtocolsQuery,
424
+ target : from || this.connectedDid,
523
425
  };
524
426
 
525
427
  if (this.delegateDid) {
@@ -530,7 +432,7 @@ export class DwnApi {
530
432
  const { grant: { id: permissionGrantId } } = await this.permissionsApi.getPermissionForRequest({
531
433
  connectedDid : this.connectedDid,
532
434
  delegateDid : this.delegateDid,
533
- protocol : request.message.filter.protocol,
435
+ protocol : messageParams.filter.protocol,
534
436
  cached : true,
535
437
  messageType : agentRequest.messageType
536
438
  });
@@ -548,7 +450,7 @@ export class DwnApi {
548
450
 
549
451
  let agentResponse: DwnResponse<DwnInterface.ProtocolsQuery>;
550
452
 
551
- if (request.from) {
453
+ if (from) {
552
454
  agentResponse = await this.agent.sendDwnRequest(agentRequest);
553
455
  } else {
554
456
  agentResponse = await this.agent.processDwnRequest(agentRequest);
@@ -568,11 +470,9 @@ export class DwnApi {
568
470
  }
569
471
 
570
472
  /**
571
- * API to interact with DWN records (e.g., `dwn.records.create()`).
473
+ * API to interact with DWN records (e.g., `dwn.records.write()`).
572
474
  */
573
475
  get records(): {
574
- create: (request: RecordsCreateRequest) => Promise<RecordsCreateResponse>;
575
- createFrom: (request: RecordsCreateFromRequest) => Promise<RecordsWriteResponse>;
576
476
  delete: (request: RecordsDeleteRequest) => Promise<DwnResponseStatus>;
577
477
  query: (request: RecordsQueryRequest) => Promise<RecordsQueryResponse>;
578
478
  read: (request: RecordsReadRequest) => Promise<RecordsReadResponse>;
@@ -581,77 +481,33 @@ export class DwnApi {
581
481
  } {
582
482
 
583
483
  return {
584
- /**
585
- * Alias for the `write` method
586
- */
587
- create: async (request: RecordsCreateRequest): Promise<RecordsCreateResponse> => {
588
- return this.records.write(request);
589
- },
590
-
591
- /**
592
- * Write a record based on an existing one (useful for updating an existing record)
593
- */
594
- createFrom: async (request: RecordsCreateFromRequest): Promise<RecordsWriteResponse> => {
595
- const { author: inheritedAuthor, ...inheritedProperties } = request.record.toJSON();
596
-
597
- // If `data` is being updated then `dataCid` and `dataSize` must not be present.
598
- if (request.data !== undefined) {
599
- delete inheritedProperties.dataCid;
600
- delete inheritedProperties.dataSize;
601
- }
602
-
603
- // If `published` is set to false, ensure that `datePublished` is undefined. Otherwise, DWN SDK's schema validation
604
- // will throw an error if `published` is false but `datePublished` is set.
605
- if (request.message?.published === false && inheritedProperties.datePublished !== undefined) {
606
- delete inheritedProperties.datePublished;
607
- delete inheritedProperties.published;
608
- }
609
-
610
- // If the request changes the `author` or message `descriptor` then the deterministic `recordId` will change.
611
- // As a result, we will discard the `recordId` if either of these changes occur.
612
- if (!isEmptyObject(request.message) || (request.author && request.author !== inheritedAuthor)) {
613
- delete inheritedProperties.recordId;
614
- }
615
-
616
- // Auto-detect encryption from the source record if not explicitly set.
617
- const shouldEncrypt = request.encryption
618
- ?? (request.record.encryption !== undefined);
619
-
620
- return this.records.write({
621
- data : request.data,
622
- message : {
623
- ...inheritedProperties,
624
- ...request.message,
625
- },
626
- encryption: shouldEncrypt || undefined,
627
- });
628
- },
629
-
630
484
  /**
631
485
  * Delete a record
632
486
  */
633
487
  delete: async (request: RecordsDeleteRequest): Promise<DwnResponseStatus> => {
488
+ const { from, protocol, ...messageParams } = request;
489
+
634
490
  const agentRequest: ProcessDwnRequest<DwnInterface.RecordsDelete> = {
635
491
  /**
636
492
  * The `author` is the DID that will sign the message and must be the DID the Web5 app is
637
493
  * connected with and is authorized to access the signing private key of.
638
494
  */
639
- author : this.connectedDid,
640
- messageParams : request.message,
641
- messageType : DwnInterface.RecordsDelete,
495
+ author : this.connectedDid,
496
+ messageParams,
497
+ messageType : DwnInterface.RecordsDelete,
642
498
  /**
643
499
  * The `target` is the DID of the DWN tenant under which the delete will be executed.
644
500
  * If `from` is provided, the delete operation will be executed on a remote DWN.
645
501
  * Otherwise, the record will be deleted on the local DWN.
646
502
  */
647
- target : request.from || this.connectedDid
503
+ target : from || this.connectedDid,
648
504
  };
649
505
 
650
506
  if (this.delegateDid) {
651
507
  const { message: delegatedGrant } = await this.permissionsApi.getPermissionForRequest({
652
508
  connectedDid : this.connectedDid,
653
509
  delegateDid : this.delegateDid,
654
- protocol : request.protocol,
510
+ protocol,
655
511
  delegate : true,
656
512
  cached : true,
657
513
  messageType : agentRequest.messageType
@@ -666,7 +522,7 @@ export class DwnApi {
666
522
 
667
523
  let agentResponse: DwnResponse<DwnInterface.RecordsDelete>;
668
524
 
669
- if (request.from) {
525
+ if (from) {
670
526
  agentResponse = await this.agent.sendDwnRequest(agentRequest);
671
527
  } else {
672
528
  agentResponse = await this.agent.processDwnRequest(agentRequest);
@@ -681,35 +537,36 @@ export class DwnApi {
681
537
  * Query a single or multiple records based on the given filter
682
538
  */
683
539
  query: async (request: RecordsQueryRequest): Promise<RecordsQueryResponse> => {
540
+ const { from, encryption, ...messageParams } = request;
541
+
684
542
  const agentRequest: ProcessDwnRequest<DwnInterface.RecordsQuery> = {
685
543
  /**
686
544
  * The `author` is the DID that will sign the message and must be the DID the Web5 app is
687
545
  * connected with and is authorized to access the signing private key of.
688
546
  */
689
- author : this.connectedDid,
690
- messageParams : request.message,
691
- messageType : DwnInterface.RecordsQuery,
547
+ author : this.connectedDid,
548
+ messageParams,
549
+ messageType : DwnInterface.RecordsQuery,
692
550
  /**
693
551
  * The `target` is the DID of the DWN tenant under which the query will be executed.
694
552
  * If `from` is provided, the query operation will be executed on a remote DWN.
695
553
  * Otherwise, the local DWN will be queried.
696
554
  */
697
- target : request.from || this.connectedDid,
698
- encryption : request.encryption,
555
+ target : from || this.connectedDid,
556
+ encryption,
699
557
  };
700
558
 
701
559
  if (this.delegateDid) {
702
560
  // if we don't find a delegated grant, we will attempt to query signing as the delegated DID
703
561
  // This is to allow the API caller to query public records without needing to impersonate the delegate.
704
562
  //
705
- // NOTE: When a read-only DwnApi is implemented, callers should use that instead when they don't have an explicit permission.
706
- // This should fail if a permission is not found.
707
- // TODO: https://github.com/enboxorg/enbox/issues/898
563
+ // NOTE: For anonymous/public queries without explicit permissions, callers can use `DwnReaderApi` via `Web5.anonymous()`.
564
+ // See: https://github.com/enboxorg/enbox/issues/898
708
565
  try {
709
566
  const { message: delegatedGrant } = await this.permissionsApi.getPermissionForRequest({
710
567
  connectedDid : this.connectedDid,
711
568
  delegateDid : this.delegateDid,
712
- protocol : request.protocol,
569
+ protocol : messageParams.filter?.protocol,
713
570
  delegate : true,
714
571
  cached : true,
715
572
  messageType : agentRequest.messageType
@@ -726,10 +583,9 @@ export class DwnApi {
726
583
  }
727
584
  }
728
585
 
729
-
730
586
  let agentResponse: DwnResponse<DwnInterface.RecordsQuery>;
731
587
 
732
- if (request.from) {
588
+ if (from) {
733
589
  agentResponse = await this.agent.sendDwnRequest(agentRequest);
734
590
  } else {
735
591
  agentResponse = await this.agent.processDwnRequest(agentRequest);
@@ -739,7 +595,6 @@ export class DwnApi {
739
595
  const { entries = [], status, cursor } = reply;
740
596
 
741
597
  const records = entries.map((entry) => {
742
-
743
598
  const recordOptions = {
744
599
  /**
745
600
  * Extract the `author` DID from the record entry since records may be signed by the
@@ -758,7 +613,7 @@ export class DwnApi {
758
613
  * to determine which DWN to send subsequent read requests to in the event the data
759
614
  * payload exceeds the threshold for being returned with queries.
760
615
  */
761
- remoteOrigin : request.from,
616
+ remoteOrigin : from,
762
617
  delegateDid : this.delegateDid,
763
618
  protocolRole : agentRequest.messageParams.protocolRole,
764
619
  ...entry as DwnMessage[DwnInterface.RecordsWrite]
@@ -774,35 +629,37 @@ export class DwnApi {
774
629
  * Read a single record based on the given filter
775
630
  */
776
631
  read: async (request: RecordsReadRequest): Promise<RecordsReadResponse> => {
632
+ const { from, protocol, encryption, ...messageParams } = request;
633
+
777
634
  const agentRequest: ProcessDwnRequest<DwnInterface.RecordsRead> = {
778
635
  /**
779
636
  * The `author` is the DID that will sign the message and must be the DID the Web5 app is
780
637
  * connected with and is authorized to access the signing private key of.
781
638
  */
782
- author : this.connectedDid,
783
- messageParams : request.message,
784
- messageType : DwnInterface.RecordsRead,
639
+ author : this.connectedDid,
640
+ messageParams,
641
+ messageType : DwnInterface.RecordsRead,
785
642
  /**
786
643
  * The `target` is the DID of the DWN tenant under which the read will be executed.
787
644
  * If `from` is provided, the read operation will be executed on a remote DWN.
788
645
  * Otherwise, the read will occur on the local DWN.
789
646
  */
790
- target : request.from || this.connectedDid,
791
- encryption : request.encryption,
647
+ target : from || this.connectedDid,
648
+ encryption,
792
649
  };
650
+
793
651
  if (this.delegateDid) {
794
652
  // if we don't find a delegated grant, we will attempt to read signing as the delegated DID
795
653
  // This is to allow the API caller to read public records without needing to impersonate the delegate.
796
654
  //
797
- // NOTE: When a read-only DwnApi is implemented, callers should use that instead when they don't have an explicit permission.
798
- // This should fail if a permission is not found.
799
- // TODO: https://github.com/enboxorg/enbox/issues/898
655
+ // NOTE: For anonymous/public reads without explicit permissions, callers can use `DwnReaderApi` via `Web5.anonymous()`.
656
+ // See: https://github.com/enboxorg/enbox/issues/898
800
657
 
801
658
  try {
802
659
  const { message: delegatedGrant } = await this.permissionsApi.getPermissionForRequest({
803
660
  connectedDid : this.connectedDid,
804
661
  delegateDid : this.delegateDid,
805
- protocol : request.protocol,
662
+ protocol,
806
663
  delegate : true,
807
664
  cached : true,
808
665
  messageType : agentRequest.messageType
@@ -821,7 +678,7 @@ export class DwnApi {
821
678
 
822
679
  let agentResponse: DwnResponse<DwnInterface.RecordsRead>;
823
680
 
824
- if (request.from) {
681
+ if (from) {
825
682
  agentResponse = await this.agent.sendDwnRequest(agentRequest);
826
683
  } else {
827
684
  agentResponse = await this.agent.processDwnRequest(agentRequest);
@@ -849,7 +706,7 @@ export class DwnApi {
849
706
  * to determine which DWN to send subsequent read requests to in the event the data
850
707
  * payload must be read again (e.g., if the data stream is consumed).
851
708
  */
852
- remoteOrigin : request.from,
709
+ remoteOrigin : from,
853
710
  delegateDid : this.delegateDid,
854
711
  data : entry.data,
855
712
  initialWrite : entry.initialWrite,
@@ -870,12 +727,14 @@ export class DwnApi {
870
727
  * typed change events (`create`, `update`, `delete`).
871
728
  */
872
729
  subscribe: async (request: RecordsSubscribeRequest): Promise<RecordsSubscribeResponse> => {
730
+ const { from, ...messageParams } = request;
731
+
873
732
  // Build a DWN-level subscription handler that wraps raw RecordEvents
874
733
  // into Record objects and feeds them into the LiveQuery.
875
734
  let liveQuery: LiveQuery | undefined;
876
735
 
877
- const remoteOrigin = request.from;
878
- const protocolRole = request.message.protocolRole;
736
+ const remoteOrigin = from;
737
+ const protocolRole = messageParams.protocolRole;
879
738
 
880
739
  type RecordEvent = {
881
740
  message: DwnMessage[DwnInterface.RecordsWrite];
@@ -898,10 +757,10 @@ export class DwnApi {
898
757
  };
899
758
 
900
759
  const agentRequest: ProcessDwnRequest<DwnInterface.RecordsSubscribe> = {
901
- author : this.connectedDid,
902
- messageParams : request.message,
903
- messageType : DwnInterface.RecordsSubscribe,
904
- target : request.from || this.connectedDid,
760
+ author : this.connectedDid,
761
+ messageParams,
762
+ messageType : DwnInterface.RecordsSubscribe,
763
+ target : from || this.connectedDid,
905
764
  subscriptionHandler,
906
765
  };
907
766
 
@@ -909,14 +768,13 @@ export class DwnApi {
909
768
  // if we don't find a delegated grant, we will attempt to subscribe signing as the delegated DID
910
769
  // This is to allow the API caller to subscribe to public records without needing to impersonate the delegate.
911
770
  //
912
- // NOTE: When a read-only DwnApi is implemented, callers should use that instead when they don't have an explicit permission.
913
- // This should fail if a permission is not found.
914
- // TODO: https://github.com/enboxorg/enbox/issues/898
771
+ // NOTE: For anonymous/public subscriptions without explicit permissions, callers can use `DwnReaderApi` via `Web5.anonymous()`.
772
+ // See: https://github.com/enboxorg/enbox/issues/898
915
773
  try {
916
774
  const { message: delegatedGrant } = await this.permissionsApi.getPermissionForRequest({
917
775
  connectedDid : this.connectedDid,
918
776
  delegateDid : this.delegateDid,
919
- protocol : request.protocol,
777
+ protocol : messageParams.filter?.protocol,
920
778
  delegate : true,
921
779
  cached : true,
922
780
  messageType : agentRequest.messageType
@@ -935,14 +793,14 @@ export class DwnApi {
935
793
 
936
794
  let agentResponse: DwnResponse<DwnInterface.RecordsSubscribe>;
937
795
 
938
- if (request.from) {
796
+ if (from) {
939
797
  agentResponse = await this.agent.sendDwnRequest(agentRequest);
940
798
  } else {
941
799
  agentResponse = await this.agent.processDwnRequest(agentRequest);
942
800
  }
943
801
 
944
802
  const reply = agentResponse.reply;
945
- const { status, subscription, entries = [] } = reply;
803
+ const { status, subscription, entries = [], cursor } = reply;
946
804
 
947
805
  if (subscription) {
948
806
  liveQuery = new LiveQuery({
@@ -953,6 +811,7 @@ export class DwnApi {
953
811
  remoteOrigin,
954
812
  permissionsApi : this.permissionsApi,
955
813
  initialEntries : entries,
814
+ cursor,
956
815
  subscription,
957
816
  });
958
817
  }
@@ -970,19 +829,19 @@ export class DwnApi {
970
829
  * requires fetching from the DWN datastore.
971
830
  */
972
831
  write: async (request: RecordsWriteRequest): Promise<RecordsWriteResponse> => {
973
- const { dataBlob, dataFormat } = dataToBlob(request.data, request.message?.dataFormat);
832
+ const { data, store, encryption, ...restParams } = request;
833
+ const { dataBlob, dataFormat } = dataToBlob(data, restParams.dataFormat);
834
+
835
+ const messageParams = { ...restParams, dataFormat };
974
836
 
975
837
  const dwnRequestParams: ProcessDwnRequest<DwnInterface.RecordsWrite> = {
976
- store : request.store,
977
- messageType : DwnInterface.RecordsWrite,
978
- messageParams : {
979
- ...request.message,
980
- dataFormat
981
- },
982
- author : this.connectedDid,
983
- target : this.connectedDid,
984
- dataStream : dataBlob,
985
- encryption : request.encryption,
838
+ store,
839
+ messageType : DwnInterface.RecordsWrite,
840
+ messageParams,
841
+ author : this.connectedDid,
842
+ target : this.connectedDid,
843
+ dataStream : dataBlob,
844
+ encryption,
986
845
  };
987
846
 
988
847
  // if impersonation is enabled, fetch the delegated grant to use with the write operation
@@ -990,7 +849,7 @@ export class DwnApi {
990
849
  const { message: delegatedGrant } = await this.permissionsApi.getPermissionForRequest({
991
850
  connectedDid : this.connectedDid,
992
851
  delegateDid : this.delegateDid,
993
- protocol : request.message.protocol,
852
+ protocol : messageParams.protocol,
994
853
  delegate : true,
995
854
  cached : true,
996
855
  messageType : dwnRequestParams.messageType