@enbox/api 0.3.2 → 0.4.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.
Files changed (102) hide show
  1. package/README.md +63 -0
  2. package/dist/browser.mjs +11 -28
  3. package/dist/browser.mjs.map +4 -4
  4. package/dist/esm/advanced.js +1 -1
  5. package/dist/esm/define-protocol.js +3 -3
  6. package/dist/esm/did-api.js +1 -1
  7. package/dist/esm/did-api.js.map +1 -1
  8. package/dist/esm/dwn-api.js +6 -6
  9. package/dist/esm/dwn-api.js.map +1 -1
  10. package/dist/esm/dwn-reader-api.js +2 -2
  11. package/dist/esm/enbox.js +205 -0
  12. package/dist/esm/enbox.js.map +1 -0
  13. package/dist/esm/index.js +16 -15
  14. package/dist/esm/index.js.map +1 -1
  15. package/dist/esm/protocol.js +2 -2
  16. package/dist/esm/protocol.js.map +1 -1
  17. package/dist/esm/record-data.js +79 -5
  18. package/dist/esm/record-data.js.map +1 -1
  19. package/dist/esm/record.js +49 -10
  20. package/dist/esm/record.js.map +1 -1
  21. package/dist/esm/repository.js +7 -7
  22. package/dist/esm/repository.js.map +1 -1
  23. package/dist/esm/typed-enbox.js +583 -0
  24. package/dist/esm/typed-enbox.js.map +1 -0
  25. package/dist/esm/typed-live-query.js +1 -1
  26. package/dist/esm/typed-record.js +370 -46
  27. package/dist/esm/typed-record.js.map +1 -1
  28. package/dist/esm/utils.js +25 -0
  29. package/dist/esm/utils.js.map +1 -1
  30. package/dist/esm/vc-api.js.map +1 -1
  31. package/dist/types/advanced.d.ts +1 -1
  32. package/dist/types/define-protocol.d.ts +3 -3
  33. package/dist/types/did-api.d.ts +4 -4
  34. package/dist/types/did-api.d.ts.map +1 -1
  35. package/dist/types/dwn-api.d.ts +12 -7
  36. package/dist/types/dwn-api.d.ts.map +1 -1
  37. package/dist/types/dwn-reader-api.d.ts +2 -2
  38. package/dist/types/enbox.d.ts +202 -0
  39. package/dist/types/enbox.d.ts.map +1 -0
  40. package/dist/types/grant-revocation.d.ts +2 -2
  41. package/dist/types/grant-revocation.d.ts.map +1 -1
  42. package/dist/types/index.d.ts +16 -15
  43. package/dist/types/index.d.ts.map +1 -1
  44. package/dist/types/live-query.d.ts +2 -2
  45. package/dist/types/live-query.d.ts.map +1 -1
  46. package/dist/types/permission-grant.d.ts +2 -2
  47. package/dist/types/permission-grant.d.ts.map +1 -1
  48. package/dist/types/permission-request.d.ts +2 -2
  49. package/dist/types/permission-request.d.ts.map +1 -1
  50. package/dist/types/protocol-types.d.ts +2 -2
  51. package/dist/types/protocol.d.ts +7 -7
  52. package/dist/types/protocol.d.ts.map +1 -1
  53. package/dist/types/record-data.d.ts +17 -0
  54. package/dist/types/record-data.d.ts.map +1 -1
  55. package/dist/types/record.d.ts +24 -10
  56. package/dist/types/record.d.ts.map +1 -1
  57. package/dist/types/repository-types.d.ts +19 -11
  58. package/dist/types/repository-types.d.ts.map +1 -1
  59. package/dist/types/repository.d.ts +7 -7
  60. package/dist/types/repository.d.ts.map +1 -1
  61. package/dist/types/typed-enbox.d.ts +613 -0
  62. package/dist/types/typed-enbox.d.ts.map +1 -0
  63. package/dist/types/typed-live-query.d.ts +1 -1
  64. package/dist/types/typed-record.d.ts +427 -53
  65. package/dist/types/typed-record.d.ts.map +1 -1
  66. package/dist/types/utils.d.ts +23 -0
  67. package/dist/types/utils.d.ts.map +1 -1
  68. package/dist/types/vc-api.d.ts +3 -3
  69. package/dist/types/vc-api.d.ts.map +1 -1
  70. package/package.json +12 -11
  71. package/src/advanced.ts +1 -1
  72. package/src/define-protocol.ts +3 -3
  73. package/src/did-api.ts +5 -5
  74. package/src/dwn-api.ts +22 -17
  75. package/src/dwn-reader-api.ts +2 -2
  76. package/src/enbox.ts +281 -0
  77. package/src/grant-revocation.ts +3 -3
  78. package/src/index.ts +17 -16
  79. package/src/live-query.ts +2 -2
  80. package/src/permission-grant.ts +4 -4
  81. package/src/permission-request.ts +3 -3
  82. package/src/protocol-types.ts +2 -2
  83. package/src/protocol.ts +8 -8
  84. package/src/record-data.ts +86 -5
  85. package/src/record.ts +54 -13
  86. package/src/repository-types.ts +19 -7
  87. package/src/repository.ts +15 -15
  88. package/src/typed-enbox.ts +1169 -0
  89. package/src/typed-live-query.ts +1 -1
  90. package/src/typed-record.ts +431 -53
  91. package/src/utils.ts +27 -0
  92. package/src/vc-api.ts +4 -4
  93. package/dist/esm/typed-web5.js +0 -339
  94. package/dist/esm/typed-web5.js.map +0 -1
  95. package/dist/esm/web5.js +0 -410
  96. package/dist/esm/web5.js.map +0 -1
  97. package/dist/types/typed-web5.d.ts +0 -221
  98. package/dist/types/typed-web5.d.ts.map +0 -1
  99. package/dist/types/web5.d.ts +0 -351
  100. package/dist/types/web5.d.ts.map +0 -1
  101. package/src/typed-web5.ts +0 -598
  102. package/src/web5.ts +0 -762
@@ -60,7 +60,7 @@ export type TypedRecordChange<T> = {
60
60
  * A type-safe wrapper around {@link LiveQuery} that preserves the data type `T`
61
61
  * through the initial snapshot and all subsequent change events.
62
62
  *
63
- * Obtain instances through `TypedWeb5.records.subscribe()` — never construct
63
+ * Obtain instances through `TypedEnbox.records.subscribe()` — never construct
64
64
  * directly.
65
65
  */
66
66
  export class TypedLiveQuery<T> {
@@ -11,14 +11,29 @@
11
11
  * - `.data.json()` returns `Promise<T>` instead of `Promise<unknown>`.
12
12
  * - `.update({ data })` accepts `Partial<T>` for the data payload.
13
13
  *
14
+ * You never construct `TypedRecord` directly — instances are returned by
15
+ * {@link TypedEnbox} methods such as `records.create()`, `records.query()`,
16
+ * `records.read()`, and `records.subscribe()`.
17
+ *
18
+ * @typeParam T - The TypeScript type of the record's data payload, resolved
19
+ * from the protocol's schema map at the given protocol path.
20
+ *
14
21
  * @example
15
22
  * ```ts
16
- * const { record } = await typed.records.write('friend', {
23
+ * const { record } = await proto.records.create('friend', {
17
24
  * data: { did: 'did:example:alice', alias: 'Alice' },
18
25
  * });
19
26
  *
20
27
  * // record is TypedRecord<FriendData>
21
28
  * const data = await record.data.json(); // FriendData — no manual cast
29
+ *
30
+ * // Update preserves the type
31
+ * const { record: updated } = await record.update({
32
+ * data: { alias: 'Ali' }, // Partial<FriendData>
33
+ * });
34
+ *
35
+ * // Send to the remote DWN
36
+ * await updated.send();
22
37
  * ```
23
38
  */
24
39
 
@@ -39,9 +54,28 @@ import type { DwnInterface } from '@enbox/agent';
39
54
  *
40
55
  * All other methods (`blob`, `bytes`, `text`, `stream`, `then`, `catch`)
41
56
  * are forwarded unchanged from the underlying {@link RecordData}.
57
+ *
58
+ * @typeParam T - The TypeScript type returned by {@link TypedRecordData.json | json()}.
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * const { record } = await proto.records.read('notebook', {
63
+ * filter: { recordId: notebookId },
64
+ * });
65
+ *
66
+ * const payload = await record.data.json(); // Promise<NotebookData>
67
+ * const raw = await record.data.text(); // Promise<string>
68
+ * const blob = await record.data.blob(); // Promise<Blob>
69
+ * const stream = await record.data.stream(); // Promise<ReadableStream>
70
+ * ```
42
71
  */
43
72
  export type TypedRecordData<T> = Omit<RecordData, 'json'> & {
44
- /** Parse the data as JSON, returning the typed data shape `T`. */
73
+ /**
74
+ * Parse the record's data as JSON, returning the typed data shape `T`.
75
+ *
76
+ * @returns A promise resolving to the record's data payload typed as `T`.
77
+ * @throws If the data is not valid JSON or the record has been deleted.
78
+ */
45
79
  json: () => Promise<T>;
46
80
  };
47
81
 
@@ -52,11 +86,25 @@ export type TypedRecordData<T> = Omit<RecordData, 'json'> & {
52
86
  /**
53
87
  * Update parameters for a {@link TypedRecord}.
54
88
  *
55
- * Extends the base `RecordUpdateParams` but narrows `data` from `unknown`
56
- * to `Partial<T>`.
89
+ * Extends the base {@link RecordUpdateParams} but narrows `data` from
90
+ * `unknown` to `Partial<T>`, providing compile-time type safety when
91
+ * updating record payloads.
92
+ *
93
+ * @typeParam T - The full data type of the record being updated.
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * await record.update({
98
+ * data: { title: 'Updated title' }, // Partial<NotebookData>
99
+ * tags: { category: 'work' },
100
+ * });
101
+ * ```
57
102
  */
58
103
  export type TypedRecordUpdateParams<T> = Omit<RecordUpdateParams, 'data'> & {
59
- /** The new data for the record. Type-checked against the schema map. */
104
+ /**
105
+ * The new data for the record. Type-checked against the schema map as
106
+ * `Partial<T>`, so you only need to supply the fields you want to change.
107
+ */
60
108
  data?: Partial<T>;
61
109
  };
62
110
 
@@ -66,17 +114,38 @@ export type TypedRecordUpdateParams<T> = Omit<RecordUpdateParams, 'data'> & {
66
114
 
67
115
  /**
68
116
  * Result of a {@link TypedRecord.update} operation.
117
+ *
118
+ * Includes the DWN response status (`status.code` / `status.detail`) and
119
+ * the updated record, which carries the same type parameter `T` so
120
+ * subsequent reads remain type-safe.
121
+ *
122
+ * @typeParam T - The data type of the record.
69
123
  */
70
124
  export type TypedRecordUpdateResult<T> = DwnResponseStatus & {
71
- /** The updated record, carrying the same type parameter. */
125
+ /**
126
+ * The updated record, carrying the same type parameter `T`.
127
+ *
128
+ * This is a **new** {@link TypedRecord} instance reflecting the post-update
129
+ * state. The original record instance is also mutated in-place, so both
130
+ * references see the updated data.
131
+ */
72
132
  record: TypedRecord<T>;
73
133
  };
74
134
 
75
135
  /**
76
136
  * Result of a {@link TypedRecord.delete} operation.
137
+ *
138
+ * Includes the DWN response status and the record in its deleted state.
139
+ * The original record instance is also mutated in-place, so both
140
+ * references reflect the deletion.
141
+ *
142
+ * @typeParam T - The data type of the record.
77
143
  */
78
144
  export type TypedRecordDeleteResult<T> = DwnResponseStatus & {
79
- /** The deleted record, carrying the same type parameter. */
145
+ /**
146
+ * The record in its deleted state. The {@link TypedRecord.deleted} getter
147
+ * will return `true`, and data accessors will throw.
148
+ */
80
149
  record: TypedRecord<T>;
81
150
  };
82
151
 
@@ -87,13 +156,45 @@ export type TypedRecordDeleteResult<T> = DwnResponseStatus & {
87
156
  /**
88
157
  * A type-safe wrapper around {@link Record} that preserves the data type `T`.
89
158
  *
90
- * Obtain instances through `TypedWeb5.records.write()`, `.query()`, `.read()`,
91
- * or `.subscribe()` — never construct directly.
159
+ * Obtain instances through {@link TypedEnbox} methods — `records.create()`,
160
+ * `records.query()`, `records.read()`, or `records.subscribe()` — never
161
+ * construct directly.
162
+ *
163
+ * @typeParam T - The TypeScript type of the record's data payload. This type
164
+ * is inferred automatically from the protocol's schema map and the protocol
165
+ * path used when creating or querying the record.
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * // TypedRecord instances are returned by TypedEnbox methods:
170
+ * const { record } = await proto.records.create('notebook', {
171
+ * data: { name: 'My Notebook' },
172
+ * });
173
+ *
174
+ * // Access metadata
175
+ * console.log(record.id); // unique record ID
176
+ * console.log(record.contextId); // context ID for hierarchical grouping
177
+ * console.log(record.dateCreated); // ISO 8601 creation timestamp
178
+ * console.log(record.timestamp); // ISO 8601 last-update timestamp
179
+ * console.log(record.tags); // key-value metadata tags
180
+ *
181
+ * // Type-safe data access
182
+ * const data = await record.data.json(); // NotebookData
183
+ *
184
+ * // Lifecycle
185
+ * await record.send(); // push to remote DWN
186
+ * await record.update({ data: { name: 'Renamed' } });
187
+ * await record.delete();
188
+ * ```
92
189
  */
93
190
  export class TypedRecord<T> {
94
- /** The underlying untyped Record instance. */
191
+ /** @internal The underlying untyped Record instance. */
95
192
  private _record: Record;
96
193
 
194
+ /**
195
+ * @internal Wrap an untyped {@link Record} in a type-safe shell.
196
+ * @param record - The underlying `Record` instance to wrap.
197
+ */
97
198
  constructor(record: Record) {
98
199
  this._record = record;
99
200
  }
@@ -102,7 +203,14 @@ export class TypedRecord<T> {
102
203
  // Escape hatch
103
204
  // -------------------------------------------------------------------------
104
205
 
105
- /** Access the underlying untyped {@link Record} for advanced use cases. */
206
+ /**
207
+ * Access the underlying untyped {@link Record} for advanced use cases.
208
+ *
209
+ * Use this escape hatch when you need to call `Record` methods or access
210
+ * properties that are not surfaced by the typed wrapper.
211
+ *
212
+ * @returns The wrapped {@link Record} instance.
213
+ */
106
214
  public get rawRecord(): Record {
107
215
  return this._record;
108
216
  }
@@ -112,11 +220,32 @@ export class TypedRecord<T> {
112
220
  // -------------------------------------------------------------------------
113
221
 
114
222
  /**
115
- * Returns the data of the current record with type-safe accessors.
223
+ * Returns the record's data with type-safe accessors.
116
224
  *
117
- * The `json()` method returns `Promise<T>` no manual generic needed.
225
+ * The returned object provides multiple ways to consume the data:
118
226
  *
227
+ * | Method | Return type | Description |
228
+ * |------------|--------------------------|--------------------------------------|
229
+ * | `json()` | `Promise<T>` | Parse as JSON with full type safety |
230
+ * | `text()` | `Promise<string>` | Raw UTF-8 text |
231
+ * | `blob()` | `Promise<Blob>` | Binary blob (respects `dataFormat`) |
232
+ * | `bytes()` | `Promise<Uint8Array>` | Raw bytes |
233
+ * | `stream()` | `Promise<ReadableStream>`| Web `ReadableStream` for streaming |
234
+ *
235
+ * The object is also directly awaitable (returns the stream).
236
+ *
237
+ * @returns A {@link TypedRecordData} accessor whose `json()` returns `Promise<T>`.
119
238
  * @throws `Error` if the record has been deleted.
239
+ *
240
+ * @example
241
+ * ```ts
242
+ * const { record } = await proto.records.read('notebook', {
243
+ * filter: { recordId },
244
+ * });
245
+ *
246
+ * const notebook = await record.data.json(); // NotebookData
247
+ * const raw = await record.data.text(); // string
248
+ * ```
120
249
  */
121
250
  public get data(): TypedRecordData<T> {
122
251
  const underlying = this._record.data;
@@ -136,22 +265,62 @@ export class TypedRecord<T> {
136
265
  // -------------------------------------------------------------------------
137
266
 
138
267
  /**
139
- * Update the current record on the DWN.
268
+ * Update the current record's data and/or metadata on the DWN.
269
+ *
270
+ * The `data` field accepts `Partial<T>`, so you only need to provide
271
+ * the fields you want to change. A new {@link TypedRecord} is returned
272
+ * **and** the original instance is mutated in-place, so both the returned
273
+ * record and the original reference reflect the updated state.
140
274
  *
141
- * @param params - Parameters including the typed `data` payload.
142
- * @returns The status and an updated {@link TypedRecord}.
275
+ * @param params - Update parameters. `data` is type-checked as `Partial<T>`.
276
+ * Other fields like `tags`, `published`, and `datePublished` can also be
277
+ * updated.
278
+ * @returns A {@link TypedRecordUpdateResult} containing the DWN response
279
+ * `status` and the updated {@link TypedRecord}.
143
280
  * @throws `Error` if the record has been deleted.
281
+ *
282
+ * @example
283
+ * ```ts
284
+ * const { status, record: updated } = await record.update({
285
+ * data: { title: 'New Title' }, // Partial<PageData>
286
+ * tags: { priority: 'high' },
287
+ * });
288
+ *
289
+ * if (status.code === 202) {
290
+ * await updated.send(); // push update to remote
291
+ * }
292
+ * ```
144
293
  */
145
294
  public async update(params: TypedRecordUpdateParams<T>): Promise<TypedRecordUpdateResult<T>> {
146
295
  const { status, record } = await this._record.update(params as RecordUpdateParams);
296
+ // The underlying Record.update() now also mutates `this._record` in-place,
297
+ // so the original TypedRecord reference already reflects the new data.
298
+ // We still return a new TypedRecord wrapping the returned record for callers
299
+ // that use the destructured result.
147
300
  return { status, record: new TypedRecord<T>(record) };
148
301
  }
149
302
 
150
303
  /**
151
- * Delete the current record on the DWN.
304
+ * Delete the current record from the DWN.
305
+ *
306
+ * After deletion, **both** the returned record and the original instance's
307
+ * {@link TypedRecord.deleted | deleted} property will be `true`, and
308
+ * calling data accessors on either will throw.
309
+ *
310
+ * @param params - Optional delete parameters:
311
+ * - `store` — whether to persist the delete message (defaults to `true`).
312
+ * - `prune` — whether to also delete child records.
313
+ * - `signAsOwner` — sign the delete as the DWN owner (for imports).
314
+ * @returns A {@link TypedRecordDeleteResult} containing the DWN response
315
+ * `status` and the record in its deleted state.
152
316
  *
153
- * @param params - Delete parameters.
154
- * @returns The status and a {@link TypedRecord} reflecting the deleted state.
317
+ * @example
318
+ * ```ts
319
+ * const { status } = await record.delete({ prune: true });
320
+ * if (status.code === 202) {
321
+ * console.log('Record and children deleted');
322
+ * }
323
+ * ```
155
324
  */
156
325
  public async delete(params?: RecordDeleteParams): Promise<TypedRecordDeleteResult<T>> {
157
326
  const { status, record } = await this._record.delete(params);
@@ -163,49 +332,95 @@ export class TypedRecord<T> {
163
332
  // -------------------------------------------------------------------------
164
333
 
165
334
  /**
166
- * Stores the current record state to the owner's DWN.
335
+ * Stores the current record state to the local DWN.
167
336
  *
168
- * @param importRecord - If true, sign as owner before storing. Defaults to false.
337
+ * Call this after creating a record with `store: false` or after
338
+ * receiving a record from a remote DWN that you want to persist locally.
339
+ *
340
+ * @param importRecord - If `true`, sign the record as the DWN owner
341
+ * before storing (useful for importing records authored by others).
342
+ * Defaults to `false`.
343
+ * @returns The DWN response status.
169
344
  */
170
345
  public async store(importRecord: boolean = false): Promise<DwnResponseStatus> {
171
346
  return this._record.store(importRecord);
172
347
  }
173
348
 
174
349
  /**
175
- * Signs and optionally stores the record to the owner's DWN.
176
- * Useful when importing a record signed by someone else.
350
+ * Signs the record as the DWN owner and optionally stores it.
351
+ *
352
+ * Use this when importing a record authored/signed by another DID into
353
+ * your own DWN. The record will be re-signed under your identity.
177
354
  *
178
- * @param store - If true, store after signing. Defaults to true.
355
+ * @param store - If `true`, persist the record after signing.
356
+ * Defaults to `true`.
357
+ * @returns The DWN response status.
179
358
  */
180
359
  public async import(store: boolean = true): Promise<DwnResponseStatus> {
181
360
  return this._record.import(store);
182
361
  }
183
362
 
184
363
  /**
185
- * Send the current record to a remote DWN.
364
+ * Push the current record to a remote DWN.
365
+ *
366
+ * This sends the record (including its data) to the specified remote
367
+ * DWN. Use this after `create`, `update`, or `delete` to sync changes
368
+ * with the remote node.
369
+ *
370
+ * @param target - The DID of the remote DWN to send to. If omitted,
371
+ * defaults to the DID of the currently connected identity.
372
+ * @returns The DWN response status from the remote node.
373
+ *
374
+ * @example
375
+ * ```ts
376
+ * const { record } = await proto.records.create('notebook', {
377
+ * data: { name: 'Travel Notes' },
378
+ * });
186
379
  *
187
- * @param target - Optional DID of the target DWN. Defaults to the connected DID.
380
+ * // Push to your own remote DWN
381
+ * await record.send();
382
+ *
383
+ * // Or push to another user's DWN
384
+ * await record.send('did:example:bob');
385
+ * ```
188
386
  */
189
387
  public async send(target?: string): Promise<DwnResponseStatus> {
190
388
  return this._record.send(target);
191
389
  }
192
390
 
193
391
  /**
194
- * Returns a JSON representation of the Record instance.
392
+ * Returns a JSON-serializable representation of the record's metadata.
393
+ *
394
+ * Useful for logging, debugging, or serializing the record's state.
395
+ * Does **not** include the record's data payload — use {@link TypedRecord.data | data}
396
+ * accessors for that.
397
+ *
398
+ * @returns A {@link RecordModel} containing the record's metadata fields.
195
399
  */
196
400
  public toJSON(): RecordModel {
197
401
  return this._record.toJSON();
198
402
  }
199
403
 
200
404
  /**
201
- * Returns a string representation of the Record instance.
405
+ * Returns a human-readable string representation of the record.
406
+ *
407
+ * @returns A string summary of the record (delegates to the underlying Record).
202
408
  */
203
409
  public toString(): string {
204
410
  return this._record.toString();
205
411
  }
206
412
 
207
413
  /**
208
- * Returns a pagination cursor for the current record given a sort order.
414
+ * Returns a pagination cursor anchored at this record for the given sort
415
+ * order.
416
+ *
417
+ * Pass the returned cursor to a subsequent `query()` call's
418
+ * `pagination.cursor` to resume pagination from this record.
419
+ *
420
+ * @param sort - The date-sort order to use for cursor positioning
421
+ * (e.g. `DateSort.CreatedAscending`).
422
+ * @returns A pagination cursor, or `undefined` if the record cannot
423
+ * produce one.
209
424
  */
210
425
  public async paginationCursor(sort: DwnDateSort): Promise<DwnPaginationCursor | undefined> {
211
426
  return this._record.paginationCursor(sort);
@@ -215,50 +430,149 @@ export class TypedRecord<T> {
215
430
  // Forwarded immutable property getters
216
431
  // -------------------------------------------------------------------------
217
432
 
218
- /** Record's ID. */
433
+ /**
434
+ * The record's unique identifier.
435
+ *
436
+ * This is a stable, globally unique ID assigned when the record is first
437
+ * created. It does not change across updates or deletes.
438
+ */
219
439
  public get id(): string { return this._record.id; }
220
440
 
221
- /** Record's context ID. */
441
+ /**
442
+ * The context ID used to group hierarchical records.
443
+ *
444
+ * When a record is created as a child (using `parentContextId`), the DWN
445
+ * assigns a `contextId` that links all records in the same hierarchy.
446
+ * Use this value as the `parentContextId` when creating child records,
447
+ * or as a `parentId` filter when querying for children.
448
+ *
449
+ * @returns The context ID string, or `undefined` if the record is not
450
+ * part of a hierarchical context.
451
+ *
452
+ * @example
453
+ * ```ts
454
+ * const { record: notebook } = await proto.records.create('notebook', {
455
+ * data: { name: 'My Notebook' },
456
+ * });
457
+ *
458
+ * // Create a child page under the notebook's context
459
+ * const { record: page } = await proto.records.create('notebook/page', {
460
+ * data: { title: 'Page 1' },
461
+ * parentContextId: notebook.contextId,
462
+ * });
463
+ * ```
464
+ */
222
465
  public get contextId(): string | undefined { return this._record.contextId; }
223
466
 
224
- /** Record's creation date. */
467
+ /**
468
+ * ISO 8601 timestamp of when the record was first created.
469
+ *
470
+ * This value is immutable and never changes, even when the record is
471
+ * updated or deleted. For the timestamp of the most recent mutation,
472
+ * use {@link TypedRecord.timestamp | timestamp}.
473
+ */
225
474
  public get dateCreated(): string { return this._record.dateCreated; }
226
475
 
227
- /** Record's parent ID. */
476
+ /**
477
+ * The parent record's ID, if this record was created as a child.
478
+ *
479
+ * @returns The parent's record ID, or `undefined` for top-level records.
480
+ */
228
481
  public get parentId(): string | undefined { return this._record.parentId; }
229
482
 
230
- /** Record's protocol. */
483
+ /**
484
+ * The protocol URI this record belongs to.
485
+ *
486
+ * @returns The protocol URI string (e.g. `'https://example.com/social'`),
487
+ * or `undefined` if the record is not protocol-scoped.
488
+ */
231
489
  public get protocol(): string | undefined { return this._record.protocol; }
232
490
 
233
- /** Record's protocol path. */
491
+ /**
492
+ * The protocol path of this record within the protocol's structure.
493
+ *
494
+ * For example, `'notebook'` or `'notebook/page'`. This identifies which
495
+ * type definition in the protocol structure governs this record.
496
+ */
234
497
  public get protocolPath(): string | undefined { return this._record.protocolPath; }
235
498
 
236
- /** Record's recipient. */
499
+ /**
500
+ * The DID of the intended recipient of this record.
501
+ *
502
+ * @returns The recipient's DID string, or `undefined` if no specific
503
+ * recipient was set.
504
+ */
237
505
  public get recipient(): string | undefined { return this._record.recipient; }
238
506
 
239
- /** Record's schema. */
507
+ /**
508
+ * The schema URI associated with this record's type in the protocol
509
+ * definition.
510
+ *
511
+ * @returns The schema URI string, or `undefined` if the type has no schema.
512
+ */
240
513
  public get schema(): string | undefined { return this._record.schema; }
241
514
 
242
515
  // -------------------------------------------------------------------------
243
516
  // Forwarded mutable property getters
244
517
  // -------------------------------------------------------------------------
245
518
 
246
- /** Record's data format. */
519
+ /**
520
+ * The MIME type / data format of the record's payload.
521
+ *
522
+ * Typically `'application/json'` for structured data, but can be any
523
+ * MIME type supported by the protocol definition's `dataFormats` array.
524
+ */
247
525
  public get dataFormat(): string | undefined { return this._record.dataFormat; }
248
526
 
249
- /** Record's data CID. */
527
+ /**
528
+ * The Content Identifier (CID) of the record's data.
529
+ *
530
+ * This is a content-addressable hash of the data payload, useful for
531
+ * verifying data integrity.
532
+ */
250
533
  public get dataCid(): string | undefined { return this._record.dataCid; }
251
534
 
252
- /** Record's data size. */
535
+ /**
536
+ * The size of the record's data payload in bytes.
537
+ */
253
538
  public get dataSize(): number | undefined { return this._record.dataSize; }
254
539
 
255
- /** Record's published date. */
540
+ /**
541
+ * ISO 8601 timestamp of when the record was published.
542
+ *
543
+ * Only present if the record has been explicitly published
544
+ * (i.e. `published: true` was set during create or update).
545
+ */
256
546
  public get datePublished(): string | undefined { return this._record.datePublished; }
257
547
 
258
- /** Record's published status. */
548
+ /**
549
+ * Whether the record is publicly published.
550
+ *
551
+ * Published records can be read by anyone without authorization.
552
+ * `undefined` if the published state was never explicitly set.
553
+ */
259
554
  public get published(): boolean | undefined { return this._record.published; }
260
555
 
261
- /** Tags of the record. */
556
+ /**
557
+ * Key-value metadata tags attached to the record.
558
+ *
559
+ * Tags are indexed by the DWN and can be used in query filters for
560
+ * efficient lookups. Values can be strings, numbers, booleans, or
561
+ * arrays of strings/numbers.
562
+ *
563
+ * @returns The tags object, or `undefined` if no tags are set.
564
+ *
565
+ * @example
566
+ * ```ts
567
+ * // Query records by tag
568
+ * const { records } = await proto.records.query('notebook', {
569
+ * filter: { tags: { category: 'work' } },
570
+ * });
571
+ *
572
+ * // Read tags from a record
573
+ * const tags = record.tags; // { category: 'work', priority: 1 }
574
+ * ```
575
+ */
262
576
  public get tags(): DwnMessage[DwnInterface.RecordsWrite]['descriptor']['tags'] | undefined {
263
577
  return this._record.tags;
264
578
  }
@@ -267,42 +581,106 @@ export class TypedRecord<T> {
267
581
  // Forwarded state-dependent property getters
268
582
  // -------------------------------------------------------------------------
269
583
 
270
- /** DID that is the logical author of the Record. */
584
+ /**
585
+ * The DID of the logical author of this record.
586
+ *
587
+ * For records you create, this is your own DID. For records written by
588
+ * others (e.g. received via a protocol role), this is the signer's DID.
589
+ */
271
590
  public get author(): string { return this._record.author; }
272
591
 
273
- /** DID that is the original creator of the Record. */
592
+ /**
593
+ * The DID of the original creator of this record.
594
+ *
595
+ * Unlike {@link TypedRecord.author | author}, which reflects the current
596
+ * message signer (and may change on updates), `creator` always refers
597
+ * to the DID that authored the initial write.
598
+ */
274
599
  public get creator(): string { return this._record.creator; }
275
600
 
276
- /** Record's message timestamp. */
601
+ /**
602
+ * ISO 8601 timestamp of the record's most recent message (create, update,
603
+ * or delete).
604
+ *
605
+ * This value changes with every mutation. For the original creation time,
606
+ * use {@link TypedRecord.dateCreated | dateCreated}.
607
+ *
608
+ * **Note:** There is no `.dateModified` property — use `timestamp` to
609
+ * determine when the record was last changed.
610
+ */
277
611
  public get timestamp(): string { return this._record.timestamp; }
278
612
 
279
- /** Record's encryption details. */
613
+ /**
614
+ * Encryption metadata for the record, if it was encrypted.
615
+ *
616
+ * Contains the algorithm, key encryption details, and initialization
617
+ * vectors used to encrypt the record's data. `undefined` for
618
+ * unencrypted records.
619
+ */
280
620
  public get encryption(): DwnMessage[DwnInterface.RecordsWrite]['encryption'] {
281
621
  return this._record.encryption;
282
622
  }
283
623
 
284
- /** Record's authorization. */
624
+ /**
625
+ * The authorization signature(s) for the current record message.
626
+ *
627
+ * Contains the JWS (JSON Web Signature) proving the message was
628
+ * authorized by the author.
629
+ */
285
630
  public get authorization(): DwnMessage[DwnInterface.RecordsWrite | DwnInterface.RecordsDelete]['authorization'] {
286
631
  return this._record.authorization;
287
632
  }
288
633
 
289
- /** Record's attestation. */
634
+ /**
635
+ * Optional attestation signature(s) for the record.
636
+ *
637
+ * Attestations are additional signatures (beyond the author's
638
+ * authorization) that vouch for the record's content.
639
+ *
640
+ * @returns The attestation JWS, or `undefined` if none is present.
641
+ */
290
642
  public get attestation(): DwnMessage[DwnInterface.RecordsWrite]['attestation'] | undefined {
291
643
  return this._record.attestation;
292
644
  }
293
645
 
294
- /** Role under which the author is writing the record. */
646
+ /**
647
+ * The protocol role under which this record was written.
648
+ *
649
+ * When a record is created with a `protocolRole`, the DWN checks that
650
+ * the author is authorized to write under that role per the protocol's
651
+ * `$actions` rules.
652
+ *
653
+ * @returns The role string (e.g. `'admin'`, `'member'`), or `undefined`
654
+ * if no role was specified.
655
+ */
295
656
  public get protocolRole(): string | undefined { return this._record.protocolRole; }
296
657
 
297
- /** Record's deleted state. */
658
+ /**
659
+ * Whether the record has been deleted.
660
+ *
661
+ * Once `true`, data accessors (`data.json()`, etc.) will throw. The
662
+ * record's metadata (ID, timestamps, etc.) remains accessible.
663
+ */
298
664
  public get deleted(): boolean { return this._record.deleted; }
299
665
 
300
- /** Record's initial write if the record has been updated. */
666
+ /**
667
+ * The initial `RecordsWrite` message for this record, if it has been
668
+ * updated at least once.
669
+ *
670
+ * The DWN preserves the initial write message to allow other nodes to
671
+ * verify the full history chain. For records that have never been
672
+ * updated, this is `undefined`.
673
+ */
301
674
  public get initialWrite(): DwnMessage[DwnInterface.RecordsWrite] | undefined {
302
675
  return this._record.initialWrite;
303
676
  }
304
677
 
305
- /** The raw DWN message backing this record. */
678
+ /**
679
+ * The raw DWN message backing this record's current state.
680
+ *
681
+ * This is the full, unprocessed DWN message — either a `RecordsWrite`
682
+ * or `RecordsDelete` message depending on the record's state.
683
+ */
306
684
  public get rawMessage(): DwnMessage[DwnInterface.RecordsWrite] | DwnMessage[DwnInterface.RecordsDelete] {
307
685
  return this._record.rawMessage;
308
686
  }