@enbox/api 0.1.0 → 0.2.0
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 +140 -159
- 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 +84 -130
- 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 +4 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/live-query.js +154 -0
- package/dist/esm/live-query.js.map +1 -0
- 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 +20 -104
- 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 +4 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/live-query.d.ts +148 -0
- package/dist/types/live-query.d.ts.map +1 -0
- 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} +75 -76
- 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 +141 -266
- package/src/dwn-reader-api.ts +255 -0
- package/src/index.ts +4 -2
- package/src/live-query.ts +261 -0
- 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/subscription-util.js +0 -35
- package/dist/esm/subscription-util.js.map +0 -1
- package/dist/esm/typed-dwn-api.js +0 -181
- package/dist/esm/typed-dwn-api.js.map +0 -1
- package/dist/types/subscription-util.d.ts +0 -19
- package/dist/types/subscription-util.d.ts.map +0 -1
- package/dist/types/typed-dwn-api.d.ts.map +0 -1
- package/src/subscription-util.ts +0 -44
- package/src/typed-dwn-api.ts +0 -370
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NOTE: Added reference types here to avoid a `pnpm` bug during build.
|
|
3
|
+
* https://github.com/enboxorg/enbox/pull/507
|
|
4
|
+
*/
|
|
5
|
+
/// <reference types="@enbox/dwn-sdk-js" />
|
|
6
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
8
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
9
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
10
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
11
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
12
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
import { ReadOnlyRecord } from './read-only-record.js';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// DwnReaderApi
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
/**
|
|
20
|
+
* A read-only API for querying public data on remote DWNs without any identity or signing keys.
|
|
21
|
+
*
|
|
22
|
+
* This class mirrors the shape of {@link DwnApi}'s `records` and `protocols`
|
|
23
|
+
* namespaces, but restricts to read-path operations and requires a `from` DID
|
|
24
|
+
* on every call (remote-only). All messages are unsigned, so only published
|
|
25
|
+
* records and protocols are accessible.
|
|
26
|
+
*
|
|
27
|
+
* Obtain an instance via {@link Web5.anonymous | `Web5.anonymous()`}.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const { dwn } = Web5.anonymous();
|
|
32
|
+
*
|
|
33
|
+
* const { records } = await dwn.records.query({
|
|
34
|
+
* from: 'did:dht:alice...',
|
|
35
|
+
* filter: { protocol: 'https://social.example/posts', protocolPath: 'post' },
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* for (const record of records) {
|
|
39
|
+
* console.log(record.id, await record.data.text());
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @beta
|
|
44
|
+
*/
|
|
45
|
+
export class DwnReaderApi {
|
|
46
|
+
constructor(anonymousDwn) {
|
|
47
|
+
this._anonymousDwn = anonymousDwn;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* API to interact with public DWN records (query, read, count).
|
|
51
|
+
*/
|
|
52
|
+
get records() {
|
|
53
|
+
return {
|
|
54
|
+
/**
|
|
55
|
+
* Query public records from a remote DWN.
|
|
56
|
+
* Only published records are returned.
|
|
57
|
+
*/
|
|
58
|
+
query: (request) => __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
const reply = yield this._anonymousDwn.recordsQuery(request.from, {
|
|
60
|
+
filter: request.filter,
|
|
61
|
+
dateSort: request.dateSort,
|
|
62
|
+
pagination: request.pagination,
|
|
63
|
+
});
|
|
64
|
+
const { entries = [], status, cursor } = reply;
|
|
65
|
+
const records = entries.map((entry) => new ReadOnlyRecord({
|
|
66
|
+
rawMessage: entry,
|
|
67
|
+
initialWrite: entry.initialWrite,
|
|
68
|
+
encodedData: entry.encodedData,
|
|
69
|
+
remoteOrigin: request.from,
|
|
70
|
+
anonymousDwn: this._anonymousDwn,
|
|
71
|
+
}));
|
|
72
|
+
return { records, status, cursor };
|
|
73
|
+
}),
|
|
74
|
+
/**
|
|
75
|
+
* Read a specific public record from a remote DWN.
|
|
76
|
+
* Succeeds for published records and protocol records with `{ who: 'anyone', can: ['read'] }`.
|
|
77
|
+
*/
|
|
78
|
+
read: (request) => __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
const reply = yield this._anonymousDwn.recordsRead(request.from, {
|
|
80
|
+
filter: request.filter,
|
|
81
|
+
});
|
|
82
|
+
const { entry, status } = reply;
|
|
83
|
+
let record;
|
|
84
|
+
if (200 <= status.code && status.code <= 299 && (entry === null || entry === void 0 ? void 0 : entry.recordsWrite)) {
|
|
85
|
+
record = new ReadOnlyRecord({
|
|
86
|
+
rawMessage: entry.recordsWrite,
|
|
87
|
+
initialWrite: entry.initialWrite,
|
|
88
|
+
data: entry.data,
|
|
89
|
+
remoteOrigin: request.from,
|
|
90
|
+
anonymousDwn: this._anonymousDwn,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return { record, status };
|
|
94
|
+
}),
|
|
95
|
+
/**
|
|
96
|
+
* Count public records on a remote DWN.
|
|
97
|
+
* Only published records are counted.
|
|
98
|
+
*/
|
|
99
|
+
count: (request) => __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
const reply = yield this._anonymousDwn.recordsCount(request.from, {
|
|
101
|
+
filter: request.filter,
|
|
102
|
+
});
|
|
103
|
+
const { count, status } = reply;
|
|
104
|
+
return { count, status };
|
|
105
|
+
}),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* API to query published protocol definitions from remote DWNs.
|
|
110
|
+
*/
|
|
111
|
+
get protocols() {
|
|
112
|
+
return {
|
|
113
|
+
/**
|
|
114
|
+
* Query published protocols from a remote DWN.
|
|
115
|
+
* Only protocol definitions with `published: true` are returned.
|
|
116
|
+
*/
|
|
117
|
+
query: (request) => __awaiter(this, void 0, void 0, function* () {
|
|
118
|
+
const reply = yield this._anonymousDwn.protocolsQuery(request.from, {
|
|
119
|
+
filter: request.filter,
|
|
120
|
+
});
|
|
121
|
+
const { entries = [], status } = reply;
|
|
122
|
+
const protocols = entries.map((entry) => entry.descriptor.definition);
|
|
123
|
+
return { protocols, status };
|
|
124
|
+
}),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=dwn-reader-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dwn-reader-api.js","sourceRoot":"","sources":["../../src/dwn-reader-api.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/index.js
CHANGED
|
@@ -22,14 +22,16 @@
|
|
|
22
22
|
*/
|
|
23
23
|
export * from './define-protocol.js';
|
|
24
24
|
export * from './did-api.js';
|
|
25
|
-
export * from './dwn-api.js';
|
|
25
|
+
export * from './dwn-reader-api.js';
|
|
26
26
|
export * from './grant-revocation.js';
|
|
27
|
+
export * from './live-query.js';
|
|
27
28
|
export * from './permission-grant.js';
|
|
28
29
|
export * from './permission-request.js';
|
|
29
30
|
export * from './protocol.js';
|
|
30
31
|
export * from './protocol-types.js';
|
|
32
|
+
export * from './read-only-record.js';
|
|
31
33
|
export * from './record.js';
|
|
32
|
-
export * from './typed-
|
|
34
|
+
export * from './typed-web5.js';
|
|
33
35
|
export * from './vc-api.js';
|
|
34
36
|
export * from './web5.js';
|
|
35
37
|
import * as utils from './utils.js';
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAE1B,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { getRecordAuthor } from '@enbox/agent';
|
|
11
|
+
import { Record } from './record.js';
|
|
12
|
+
/**
|
|
13
|
+
* A `CustomEvent` subclass carrying a {@link RecordChange} as its `detail`.
|
|
14
|
+
*
|
|
15
|
+
* Dispatched on the {@link LiveQuery} `EventTarget` for both the specific
|
|
16
|
+
* change-type event (`create`, `update`, `delete`) and the catch-all `change`
|
|
17
|
+
* event.
|
|
18
|
+
*/
|
|
19
|
+
export class RecordChangeEvent extends CustomEvent {
|
|
20
|
+
constructor(change) {
|
|
21
|
+
super(change.type, { detail: change });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A live query that combines an initial snapshot of matching records with a
|
|
26
|
+
* real-time stream of deduplicated, semantically-typed change events.
|
|
27
|
+
*
|
|
28
|
+
* `LiveQuery` extends `EventTarget` so that standard `addEventListener` /
|
|
29
|
+
* `removeEventListener` work out of the box. For convenience, the typed
|
|
30
|
+
* {@link LiveQuery.on | `.on()`} method provides a cleaner API that returns an
|
|
31
|
+
* unsubscribe function.
|
|
32
|
+
*
|
|
33
|
+
* ### Events
|
|
34
|
+
*
|
|
35
|
+
* | Event name | `detail` type | Description |
|
|
36
|
+
* |---|---|---|
|
|
37
|
+
* | `create` | {@link RecordChange} | A new record was written |
|
|
38
|
+
* | `update` | {@link RecordChange} | An existing record was updated |
|
|
39
|
+
* | `delete` | {@link RecordChange} | A record was deleted |
|
|
40
|
+
* | `change` | {@link RecordChange} | Catch-all for any of the above |
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const { liveQuery } = await dwn.records.subscribe({
|
|
45
|
+
* message: {
|
|
46
|
+
* filter: {
|
|
47
|
+
* protocol : chatProtocol.protocol,
|
|
48
|
+
* protocolPath : 'thread/message',
|
|
49
|
+
* }
|
|
50
|
+
* }
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* // Initial state
|
|
54
|
+
* for (const record of liveQuery.records) {
|
|
55
|
+
* renderMessage(record);
|
|
56
|
+
* }
|
|
57
|
+
*
|
|
58
|
+
* // Real-time changes
|
|
59
|
+
* liveQuery.on('create', (record) => appendMessage(record));
|
|
60
|
+
* liveQuery.on('update', (record) => refreshMessage(record));
|
|
61
|
+
* liveQuery.on('delete', (record) => removeMessage(record));
|
|
62
|
+
*
|
|
63
|
+
* // Or use the catch-all
|
|
64
|
+
* liveQuery.on('change', ({ type, record }) => {
|
|
65
|
+
* console.log(`${type}: ${record.id}`);
|
|
66
|
+
* });
|
|
67
|
+
*
|
|
68
|
+
* // Cleanup
|
|
69
|
+
* await liveQuery.close();
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export class LiveQuery extends EventTarget {
|
|
73
|
+
constructor(options) {
|
|
74
|
+
super();
|
|
75
|
+
/** Whether the live query has been closed. */
|
|
76
|
+
this._closed = false;
|
|
77
|
+
const { agent, connectedDid, cursor, delegateDid, protocolRole, remoteOrigin, permissionsApi, initialEntries, subscription, } = options;
|
|
78
|
+
this._subscription = subscription;
|
|
79
|
+
this.cursor = cursor;
|
|
80
|
+
// Build Record objects from the initial snapshot entries (same logic as records.query()).
|
|
81
|
+
this.records = initialEntries.map((entry) => new Record(agent, Object.assign({ author: getRecordAuthor(entry), connectedDid,
|
|
82
|
+
remoteOrigin,
|
|
83
|
+
delegateDid,
|
|
84
|
+
protocolRole }, entry), permissionsApi));
|
|
85
|
+
// Seed the known-records map with recordId -> messageTimestamp for dedup.
|
|
86
|
+
this._knownRecords = new Map();
|
|
87
|
+
for (const record of this.records) {
|
|
88
|
+
this._knownRecords.set(record.id, record.timestamp);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Process an incoming live event from the DWN subscription.
|
|
93
|
+
* Deduplicates against the initial snapshot and classifies the change type.
|
|
94
|
+
*
|
|
95
|
+
* @internal — Called by `DwnApi.records.subscribe()` when wiring up the subscription handler.
|
|
96
|
+
*/
|
|
97
|
+
handleEvent(record) {
|
|
98
|
+
if (this._closed) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
let changeType;
|
|
102
|
+
if (record.deleted) {
|
|
103
|
+
changeType = 'delete';
|
|
104
|
+
this._knownRecords.delete(record.id);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
const knownTimestamp = this._knownRecords.get(record.id);
|
|
108
|
+
if (knownTimestamp !== undefined) {
|
|
109
|
+
// We've seen this recordId before (either from snapshot or a prior event).
|
|
110
|
+
if (record.timestamp <= knownTimestamp) {
|
|
111
|
+
// Duplicate or stale event from the overlap window — skip.
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
changeType = 'update';
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
changeType = 'create';
|
|
118
|
+
}
|
|
119
|
+
// Update the known state.
|
|
120
|
+
this._knownRecords.set(record.id, record.timestamp);
|
|
121
|
+
}
|
|
122
|
+
const change = { type: changeType, record };
|
|
123
|
+
// Dispatch the specific event (create/update/delete).
|
|
124
|
+
this.dispatchEvent(new RecordChangeEvent(change));
|
|
125
|
+
// Dispatch the catch-all change event.
|
|
126
|
+
this.dispatchEvent(new CustomEvent('change', { detail: change }));
|
|
127
|
+
}
|
|
128
|
+
on(event, handler) {
|
|
129
|
+
const wrapper = (e) => {
|
|
130
|
+
const detail = e.detail;
|
|
131
|
+
if (event === 'change') {
|
|
132
|
+
handler(detail);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
handler(detail.record);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
this.addEventListener(event, wrapper);
|
|
139
|
+
return () => { this.removeEventListener(event, wrapper); };
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Close the underlying subscription and stop dispatching events.
|
|
143
|
+
*/
|
|
144
|
+
close() {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
if (this._closed) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this._closed = true;
|
|
150
|
+
yield this._subscription.close();
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=live-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live-query.js","sourceRoot":"","sources":["../../src/live-query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NOTE: Added reference types here to avoid a `pnpm` bug during build.
|
|
3
|
+
* https://github.com/enboxorg/enbox/pull/507
|
|
4
|
+
*/
|
|
5
|
+
/// <reference types="@enbox/dwn-sdk-js" />
|
|
6
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
7
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
8
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
9
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
10
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
11
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
12
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
import { getRecordAuthor } from '@enbox/agent';
|
|
16
|
+
import { Convert, Stream } from '@enbox/common';
|
|
17
|
+
/**
|
|
18
|
+
* An immutable, read-only view of a DWN record.
|
|
19
|
+
*
|
|
20
|
+
* `ReadOnlyRecord` is returned by {@link DwnReaderApi} methods and provides
|
|
21
|
+
* access to the record's metadata and data without any mutation capabilities.
|
|
22
|
+
* There are no `update()`, `delete()`, `send()`, `store()`, or `import()`
|
|
23
|
+
* methods — the compiler prevents accidental writes.
|
|
24
|
+
*
|
|
25
|
+
* Data access works identically to the full {@link Record} class:
|
|
26
|
+
* - If the data was inlined (small payloads from query replies), it is
|
|
27
|
+
* available immediately.
|
|
28
|
+
* - If the data was not inlined, `data.stream()` / `data.text()` / etc.
|
|
29
|
+
* automatically perform an anonymous `RecordsRead` to fetch it.
|
|
30
|
+
*
|
|
31
|
+
* @beta
|
|
32
|
+
*/
|
|
33
|
+
export class ReadOnlyRecord {
|
|
34
|
+
constructor(options) {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
const { rawMessage, initialWrite, encodedData, data, remoteOrigin, anonymousDwn } = options;
|
|
37
|
+
this._anonymousDwn = anonymousDwn;
|
|
38
|
+
this._remoteOrigin = remoteOrigin;
|
|
39
|
+
// Extract the author DID from the authorization signature. The author is
|
|
40
|
+
// the DID that signed the most recent RecordsWrite message. For records
|
|
41
|
+
// returned from anonymous queries, the authorization will be present (the
|
|
42
|
+
// remote DWN always returns the full message), but we guard against
|
|
43
|
+
// malformed messages gracefully.
|
|
44
|
+
try {
|
|
45
|
+
this._author = (_a = getRecordAuthor(rawMessage)) !== null && _a !== void 0 ? _a : 'unknown';
|
|
46
|
+
}
|
|
47
|
+
catch (_c) {
|
|
48
|
+
this._author = 'unknown';
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
this._creator = initialWrite ? ((_b = getRecordAuthor(initialWrite)) !== null && _b !== void 0 ? _b : this._author) : this._author;
|
|
52
|
+
}
|
|
53
|
+
catch (_d) {
|
|
54
|
+
this._creator = this._author;
|
|
55
|
+
}
|
|
56
|
+
this._descriptor = rawMessage.descriptor;
|
|
57
|
+
this._recordId = rawMessage.recordId;
|
|
58
|
+
this._contextId = rawMessage.contextId;
|
|
59
|
+
this._initialWrite = initialWrite;
|
|
60
|
+
this._authorization = rawMessage.authorization;
|
|
61
|
+
this._attestation = rawMessage.attestation;
|
|
62
|
+
this._encryption = rawMessage.encryption;
|
|
63
|
+
if (encodedData) {
|
|
64
|
+
this._encodedData = new Blob([Convert.base64Url(encodedData).toUint8Array()], { type: this.dataFormat });
|
|
65
|
+
}
|
|
66
|
+
if (data) {
|
|
67
|
+
this._readableStream = data;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Immutable record properties
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
/** Record's unique identifier. */
|
|
74
|
+
get id() { return this._recordId; }
|
|
75
|
+
/** Record's context ID. */
|
|
76
|
+
get contextId() { return this._contextId; }
|
|
77
|
+
/** Record's creation date. */
|
|
78
|
+
get dateCreated() { return this._descriptor.dateCreated; }
|
|
79
|
+
/** Record's parent ID. */
|
|
80
|
+
get parentId() { return this._descriptor.parentId; }
|
|
81
|
+
/** Record's protocol URI. */
|
|
82
|
+
get protocol() { return this._descriptor.protocol; }
|
|
83
|
+
/** Record's protocol path. */
|
|
84
|
+
get protocolPath() { return this._descriptor.protocolPath; }
|
|
85
|
+
/** Record's recipient. */
|
|
86
|
+
get recipient() { return this._descriptor.recipient; }
|
|
87
|
+
/** Record's schema. */
|
|
88
|
+
get schema() { return this._descriptor.schema; }
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Mutable descriptor properties
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
/** Record's data format / MIME type. */
|
|
93
|
+
get dataFormat() { return this._descriptor.dataFormat; }
|
|
94
|
+
/** Record's data CID. */
|
|
95
|
+
get dataCid() { return this._descriptor.dataCid; }
|
|
96
|
+
/** Record's data size in bytes. */
|
|
97
|
+
get dataSize() { return this._descriptor.dataSize; }
|
|
98
|
+
/** Record's published date. */
|
|
99
|
+
get datePublished() { return this._descriptor.datePublished; }
|
|
100
|
+
/** Whether the record is published. */
|
|
101
|
+
get published() { return this._descriptor.published; }
|
|
102
|
+
/** Tags associated with the record. */
|
|
103
|
+
get tags() { return this._descriptor.tags; }
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
// State-dependent properties
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
/** DID that is the logical author of the record. */
|
|
108
|
+
get author() { return this._author; }
|
|
109
|
+
/** DID that originally created the record. */
|
|
110
|
+
get creator() { return this._creator; }
|
|
111
|
+
/** Record's message timestamp (time of most recent create/update). */
|
|
112
|
+
get timestamp() { return this._descriptor.messageTimestamp; }
|
|
113
|
+
/** Record's encryption metadata, if encrypted. */
|
|
114
|
+
get encryption() { return this._encryption; }
|
|
115
|
+
/** Record's authorization. */
|
|
116
|
+
get authorization() { return this._authorization; }
|
|
117
|
+
/** Record's attestation signatures. */
|
|
118
|
+
get attestation() { return this._attestation; }
|
|
119
|
+
/** The initial write message, if the record has been updated. */
|
|
120
|
+
get initialWrite() { return this._initialWrite; }
|
|
121
|
+
/** The DID of the remote DWN this record was fetched from. */
|
|
122
|
+
get remoteOrigin() { return this._remoteOrigin; }
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// Data access
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
/**
|
|
127
|
+
* Returns the data of the current record.
|
|
128
|
+
* If the data is not available in-memory, it is fetched from the remote DWN
|
|
129
|
+
* using an anonymous `RecordsRead`.
|
|
130
|
+
*
|
|
131
|
+
* @returns A data accessor with `blob()`, `bytes()`, `json()`, `text()`, and `stream()` methods.
|
|
132
|
+
*
|
|
133
|
+
* @beta
|
|
134
|
+
*/
|
|
135
|
+
get data() {
|
|
136
|
+
const self = this;
|
|
137
|
+
const dataObj = {
|
|
138
|
+
blob() {
|
|
139
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
140
|
+
return new Blob([yield Stream.consumeToBytes({ readableStream: yield this.stream() })], { type: self.dataFormat });
|
|
141
|
+
});
|
|
142
|
+
},
|
|
143
|
+
bytes() {
|
|
144
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
145
|
+
return yield Stream.consumeToBytes({ readableStream: yield this.stream() });
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
json() {
|
|
149
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
150
|
+
return yield Stream.consumeToJson({ readableStream: yield this.stream() });
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
text() {
|
|
154
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
155
|
+
return yield Stream.consumeToText({ readableStream: yield this.stream() });
|
|
156
|
+
});
|
|
157
|
+
},
|
|
158
|
+
stream() {
|
|
159
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
160
|
+
if (self._encodedData) {
|
|
161
|
+
return Stream.fromBlob(self._encodedData);
|
|
162
|
+
}
|
|
163
|
+
else if (self._readableStream) {
|
|
164
|
+
const currentStream = self._readableStream;
|
|
165
|
+
self._readableStream = undefined;
|
|
166
|
+
return currentStream;
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// Re-fetch the data from the remote DWN using an anonymous RecordsRead.
|
|
170
|
+
return yield self.readRecordData();
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
},
|
|
174
|
+
then(onFulfilled, onRejected) {
|
|
175
|
+
return this.stream().then(onFulfilled, onRejected);
|
|
176
|
+
},
|
|
177
|
+
catch(onRejected) {
|
|
178
|
+
return this.stream().catch(onRejected);
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
return dataObj;
|
|
182
|
+
}
|
|
183
|
+
// ---------------------------------------------------------------------------
|
|
184
|
+
// Serialization
|
|
185
|
+
// ---------------------------------------------------------------------------
|
|
186
|
+
/**
|
|
187
|
+
* Returns a JSON representation of the record.
|
|
188
|
+
* Called by `JSON.stringify(...)` automatically.
|
|
189
|
+
*/
|
|
190
|
+
toJSON() {
|
|
191
|
+
return {
|
|
192
|
+
attestation: this.attestation,
|
|
193
|
+
author: this.author,
|
|
194
|
+
authorization: this.authorization,
|
|
195
|
+
contextId: this.contextId,
|
|
196
|
+
dataCid: this.dataCid,
|
|
197
|
+
dataFormat: this.dataFormat,
|
|
198
|
+
dataSize: this.dataSize,
|
|
199
|
+
dateCreated: this.dateCreated,
|
|
200
|
+
datePublished: this.datePublished,
|
|
201
|
+
encryption: this.encryption,
|
|
202
|
+
parentId: this.parentId,
|
|
203
|
+
protocol: this.protocol,
|
|
204
|
+
protocolPath: this.protocolPath,
|
|
205
|
+
published: this.published,
|
|
206
|
+
recipient: this.recipient,
|
|
207
|
+
recordId: this.id,
|
|
208
|
+
schema: this.schema,
|
|
209
|
+
tags: this.tags,
|
|
210
|
+
timestamp: this.timestamp,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Convenience string representation.
|
|
215
|
+
*/
|
|
216
|
+
toString() {
|
|
217
|
+
let str = 'ReadOnlyRecord: {\n';
|
|
218
|
+
str += ` ID: ${this.id}\n`;
|
|
219
|
+
str += this.contextId ? ` Context ID: ${this.contextId}\n` : '';
|
|
220
|
+
str += this.protocol ? ` Protocol: ${this.protocol}\n` : '';
|
|
221
|
+
str += this.schema ? ` Schema: ${this.schema}\n` : '';
|
|
222
|
+
str += ` Data CID: ${this.dataCid}\n`;
|
|
223
|
+
str += ` Data Format: ${this.dataFormat}\n`;
|
|
224
|
+
str += ` Data Size: ${this.dataSize}\n`;
|
|
225
|
+
str += ` Created: ${this.dateCreated}\n`;
|
|
226
|
+
str += ` Timestamp: ${this.timestamp}\n`;
|
|
227
|
+
str += '}';
|
|
228
|
+
return str;
|
|
229
|
+
}
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
// Private helpers
|
|
232
|
+
// ---------------------------------------------------------------------------
|
|
233
|
+
/**
|
|
234
|
+
* Fetches the record's data from the remote DWN using an anonymous `RecordsRead`.
|
|
235
|
+
*/
|
|
236
|
+
readRecordData() {
|
|
237
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
238
|
+
var _a;
|
|
239
|
+
try {
|
|
240
|
+
const reply = yield this._anonymousDwn.recordsRead(this._remoteOrigin, {
|
|
241
|
+
filter: { recordId: this._recordId },
|
|
242
|
+
});
|
|
243
|
+
if (reply.status.code !== 200 || !((_a = reply.entry) === null || _a === void 0 ? void 0 : _a.data)) {
|
|
244
|
+
throw new Error(`${reply.status.code}: ${reply.status.detail}`);
|
|
245
|
+
}
|
|
246
|
+
return reply.entry.data;
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
const message = (error instanceof Error) ? error.message : 'Unknown error';
|
|
250
|
+
throw new Error(`ReadOnlyRecord: Error reading data for record '${this._recordId}': ${message}`);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=read-only-record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-only-record.js","sourceRoot":"","sources":["../../src/read-only-record.ts"],"names":[],"mappings":"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"}
|