@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.
- package/README.md +505 -138
- package/dist/browser.mjs +23 -13
- package/dist/browser.mjs.map +4 -4
- package/dist/esm/advanced.js +11 -0
- package/dist/esm/advanced.js.map +1 -0
- package/dist/esm/define-protocol.js +3 -3
- package/dist/esm/dwn-api.js +56 -114
- package/dist/esm/dwn-api.js.map +1 -1
- package/dist/esm/dwn-reader-api.js +128 -0
- package/dist/esm/dwn-reader-api.js.map +1 -0
- package/dist/esm/index.js +3 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/live-query.js +5 -4
- package/dist/esm/live-query.js.map +1 -1
- package/dist/esm/read-only-record.js +255 -0
- package/dist/esm/read-only-record.js.map +1 -0
- package/dist/esm/record.js +46 -57
- package/dist/esm/record.js.map +1 -1
- package/dist/esm/typed-web5.js +242 -0
- package/dist/esm/typed-web5.js.map +1 -0
- package/dist/esm/web5.js +71 -3
- package/dist/esm/web5.js.map +1 -1
- package/dist/types/advanced.d.ts +12 -0
- package/dist/types/advanced.d.ts.map +1 -0
- package/dist/types/define-protocol.d.ts +3 -3
- package/dist/types/dwn-api.d.ts +13 -92
- package/dist/types/dwn-api.d.ts.map +1 -1
- package/dist/types/dwn-reader-api.d.ts +138 -0
- package/dist/types/dwn-reader-api.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/live-query.d.ts +13 -1
- package/dist/types/live-query.d.ts.map +1 -1
- package/dist/types/protocol-types.d.ts +2 -2
- package/dist/types/read-only-record.d.ts +133 -0
- package/dist/types/read-only-record.d.ts.map +1 -0
- package/dist/types/record.d.ts +37 -17
- package/dist/types/record.d.ts.map +1 -1
- package/dist/types/{typed-dwn-api.d.ts → typed-web5.d.ts} +70 -73
- package/dist/types/typed-web5.d.ts.map +1 -0
- package/dist/types/web5.d.ts +79 -3
- package/dist/types/web5.d.ts.map +1 -1
- package/package.json +10 -6
- package/src/advanced.ts +29 -0
- package/src/define-protocol.ts +3 -3
- package/src/dwn-api.ts +91 -232
- package/src/dwn-reader-api.ts +255 -0
- package/src/index.ts +3 -2
- package/src/live-query.ts +20 -4
- package/src/protocol-types.ts +2 -2
- package/src/read-only-record.ts +328 -0
- package/src/record.ts +116 -86
- package/src/typed-web5.ts +445 -0
- package/src/web5.ts +104 -5
- package/dist/esm/typed-dwn-api.js +0 -182
- package/dist/esm/typed-dwn-api.js.map +0 -1
- package/dist/types/typed-dwn-api.d.ts.map +0 -1
- 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
|
-
*
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
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 {
|
|
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
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
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 :
|
|
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
|
|
520
|
-
messageParams
|
|
521
|
-
messageType
|
|
522
|
-
target
|
|
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 :
|
|
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 (
|
|
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.
|
|
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
|
|
640
|
-
messageParams
|
|
641
|
-
messageType
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
690
|
-
messageParams
|
|
691
|
-
messageType
|
|
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
|
|
698
|
-
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:
|
|
706
|
-
//
|
|
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 :
|
|
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 (
|
|
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 :
|
|
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
|
|
783
|
-
messageParams
|
|
784
|
-
messageType
|
|
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
|
|
791
|
-
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:
|
|
798
|
-
//
|
|
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
|
|
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 (
|
|
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 :
|
|
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 =
|
|
878
|
-
const 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
|
|
902
|
-
messageParams
|
|
903
|
-
messageType
|
|
904
|
-
target
|
|
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:
|
|
913
|
-
//
|
|
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 :
|
|
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 (
|
|
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 {
|
|
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
|
|
977
|
-
messageType
|
|
978
|
-
messageParams
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
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 :
|
|
852
|
+
protocol : messageParams.protocol,
|
|
994
853
|
delegate : true,
|
|
995
854
|
cached : true,
|
|
996
855
|
messageType : dwnRequestParams.messageType
|