@palantir/pack.document-schema.model-types 0.1.0-beta.3 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/.turbo/turbo-lint.log +2 -2
  2. package/.turbo/turbo-transpileBrowser.log +1 -1
  3. package/.turbo/turbo-transpileCjs.log +1 -1
  4. package/.turbo/turbo-transpileEsm.log +1 -1
  5. package/.turbo/turbo-transpileTypes.log +1 -1
  6. package/.turbo/turbo-typecheck.log +1 -1
  7. package/CHANGELOG.md +27 -0
  8. package/build/browser/index.js +29 -5
  9. package/build/browser/index.js.map +1 -1
  10. package/build/cjs/index.cjs +30 -4
  11. package/build/cjs/index.cjs.map +1 -1
  12. package/build/cjs/index.d.cts +517 -39
  13. package/build/esm/index.js +29 -5
  14. package/build/esm/index.js.map +1 -1
  15. package/build/types/__tests__/Metadata.test.d.ts +1 -0
  16. package/build/types/__tests__/Metadata.test.d.ts.map +1 -0
  17. package/build/types/index.d.ts +6 -2
  18. package/build/types/index.d.ts.map +1 -1
  19. package/build/types/types/ActivityEvent.d.ts +64 -0
  20. package/build/types/types/ActivityEvent.d.ts.map +1 -0
  21. package/build/types/types/DocumentRef.d.ts +199 -5
  22. package/build/types/types/DocumentRef.d.ts.map +1 -1
  23. package/build/types/types/DocumentSchema.d.ts +6 -0
  24. package/build/types/types/DocumentSchema.d.ts.map +1 -1
  25. package/build/types/types/Model.d.ts +13 -0
  26. package/build/types/types/Model.d.ts.map +1 -1
  27. package/build/types/types/PresenceEvent.d.ts +73 -0
  28. package/build/types/types/PresenceEvent.d.ts.map +1 -0
  29. package/build/types/types/RecordCollectionRef.d.ts +54 -0
  30. package/build/types/types/RecordCollectionRef.d.ts.map +1 -1
  31. package/build/types/types/RecordRef.d.ts +71 -0
  32. package/build/types/types/RecordRef.d.ts.map +1 -1
  33. package/build/types/types/Unsubscribe.d.ts +3 -0
  34. package/build/types/types/Unsubscribe.d.ts.map +1 -1
  35. package/build/types/types/UserRef.d.ts +5 -0
  36. package/build/types/types/UserRef.d.ts.map +1 -1
  37. package/package.json +5 -5
  38. package/src/__tests__/Metadata.test.ts +43 -0
  39. package/src/index.ts +19 -2
  40. package/src/types/ActivityEvent.ts +88 -0
  41. package/src/types/DocumentRef.ts +218 -8
  42. package/src/types/DocumentSchema.ts +6 -0
  43. package/src/types/Metadata.ts +20 -5
  44. package/src/types/Model.ts +14 -0
  45. package/src/types/PresenceEvent.ts +102 -0
  46. package/src/types/RecordCollectionRef.ts +54 -0
  47. package/src/types/RecordRef.ts +74 -0
  48. package/src/types/Unsubscribe.ts +3 -0
  49. package/src/types/UserRef.ts +5 -0
@@ -1,6 +1,122 @@
1
1
  import { Flavored } from '@palantir/pack.core';
2
2
  import { ZodType } from 'zod';
3
3
 
4
+ declare const Metadata: symbol;
5
+ interface WithMetadata<T> {
6
+ readonly [Metadata]: T;
7
+ }
8
+ declare function getMetadata<T>(obj: WithMetadata<T>): T;
9
+
10
+ /**
11
+ * A Model defines the structure of a document record or union.
12
+ *
13
+ * It includes a zod schema for validation and type information.
14
+ */
15
+ interface Model<T = unknown, Z extends ZodType<T> = ZodType<T>> extends WithMetadata<ModelMetadata<T>> {
16
+ readonly __type: T;
17
+ readonly zodSchema: Readonly<Z>;
18
+ }
19
+ type ModelData<M extends Model> = M["__type"];
20
+ /**
21
+ * Describes an edit made to a document.
22
+ */
23
+ interface EditDescription<M extends Model = Model> {
24
+ readonly data: ModelData<M>;
25
+ readonly model: M;
26
+ }
27
+ declare const ExternalRefType: {
28
+ readonly DOC_REF: "docRef";
29
+ readonly MEDIA_REF: "mediaRef";
30
+ readonly OBJECT_REF: "objectRef";
31
+ readonly USER_REF: "userRef";
32
+ };
33
+ type ExternalRefType = typeof ExternalRefType[keyof typeof ExternalRefType];
34
+ interface ModelMetadata<T = unknown> {
35
+ /**
36
+ * Which fields in the model are external references (e.g. UserRef, DocumentRef, etc).
37
+ */
38
+ readonly externalRefFieldTypes?: Readonly<Record<keyof T, ExternalRefType>>;
39
+ /**
40
+ * The name of the model (should match the typescript symbol).
41
+ */
42
+ readonly name: string;
43
+ }
44
+
45
+ type UserId = Flavored<"pack:UserId">;
46
+ declare const UserRefBrand: unique symbol;
47
+ /**
48
+ * A reference providing an API to interact with a user.
49
+ *
50
+ * @experimental
51
+ */
52
+ interface UserRef {
53
+ readonly userId: UserId;
54
+ readonly [UserRefBrand]: typeof UserRefBrand;
55
+ readonly get: (force?: boolean) => Promise<unknown>;
56
+ }
57
+
58
+ type ActivityEventId = Flavored<"pack:EventId">;
59
+ declare const ActivityEventDataType: {
60
+ readonly CUSTOM_EVENT: "customEvent";
61
+ readonly UNKNOWN: "unknown";
62
+ };
63
+ /**
64
+ * Application specific custom activity event data, as described in a transaction edit,
65
+ * using an application sdk's generated model types.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * const unsubscribe = docRef.onActivity((docRef, event) => {
70
+ * console.log("Activity event:", event);
71
+ * });
72
+ * // Submit an edit with a description to generate an activity event.
73
+ * docRef.withTransaction(() => {
74
+ * // make some edits to the document here
75
+ * }, {
76
+ * model: MyEventModel,
77
+ * data: {
78
+ * myDataField: "some value",
79
+ * foo: 42,
80
+ * },
81
+ * });
82
+ * ```
83
+ */
84
+ interface ActivityEventDataCustom<M extends Model = Model> {
85
+ readonly type: typeof ActivityEventDataType.CUSTOM_EVENT;
86
+ readonly model: M;
87
+ readonly eventData: ModelData<M>;
88
+ }
89
+ /**
90
+ * Fallback for unrecognized activity event types.
91
+ *
92
+ * This allows some flexibility with new event types added to the platform.
93
+ * Likely unknown events represent a new platform event type and will be handled
94
+ * in a future release of pack libraries and can be safely ignored by
95
+ * applications.
96
+ */
97
+ interface ActivityEventDataUnknown {
98
+ readonly type: "unknown";
99
+ readonly rawType: string;
100
+ readonly rawData: unknown;
101
+ }
102
+ type ActivityEventData = ActivityEventDataCustom | ActivityEventDataUnknown;
103
+ /**
104
+ * An event representing an activity that has occurred on a document. This
105
+ * includes standard document events as well as custom application-specific
106
+ * events describing document edits.
107
+ *
108
+ * ActivityEvents are useful for building activity feeds, or notifications.
109
+ */
110
+ interface ActivityEvent {
111
+ /** Multiple events with the same aggregationKey may be collapsed. */
112
+ readonly aggregationKey: string;
113
+ readonly createdBy: UserId;
114
+ readonly createdInstant: number;
115
+ readonly eventData: ActivityEventData;
116
+ readonly eventId: ActivityEventId;
117
+ readonly isRead: boolean;
118
+ }
119
+
4
120
  interface DiscretionaryPrincipal_All {
5
121
  "all": Record<string, never>;
6
122
  "type": "all";
@@ -31,37 +147,15 @@ interface DocumentMetadata {
31
147
  };
32
148
  }
33
149
 
34
- declare const Metadata: symbol;
35
- interface WithMetadata<T> {
36
- readonly [Metadata]: T;
37
- }
38
- declare function getMetadata<T>(obj: WithMetadata<T>): T;
39
-
40
150
  /**
41
- * A Model defines the structure of a document record or union.
42
- *
43
- * It includes a zod schema for validation and type information.
151
+ * The base type for an application sdk's generated document schema.
44
152
  */
45
- interface Model<T = unknown, Z extends ZodType<T> = ZodType<T>> extends WithMetadata<ModelMetadata<T>> {
46
- readonly __type: T;
47
- readonly zodSchema: Readonly<Z>;
48
- }
49
- type ModelData<M extends Model> = M["__type"];
50
- declare const ExternalRefType: {
51
- readonly DOC_REF: "docRef";
52
- readonly MEDIA_REF: "mediaRef";
53
- readonly OBJECT_REF: "objectRef";
54
- readonly USER_REF: "userRef";
55
- };
56
- type ExternalRefType = typeof ExternalRefType[keyof typeof ExternalRefType];
57
- interface ModelMetadata<T = unknown> {
58
- readonly externalRefFieldTypes?: Readonly<Record<keyof T, ExternalRefType>>;
59
- readonly name: string;
60
- }
61
-
62
153
  interface DocumentSchema extends WithMetadata<DocumentSchemaMetadata> {
63
154
  readonly [modelName: string]: Model;
64
155
  }
156
+ /**
157
+ * The plain object representation of the state of a document.
158
+ */
65
159
  type DocumentState<S extends DocumentSchema> = {
66
160
  readonly [K in Exclude<keyof S, symbol>]: {
67
161
  readonly [key: string]: ModelData<S[K]>;
@@ -71,47 +165,439 @@ interface DocumentSchemaMetadata {
71
165
  readonly version: number;
72
166
  }
73
167
 
168
+ declare const PresenceEventDataType: {
169
+ readonly ARRIVED: "presenceArrived";
170
+ readonly DEPARTED: "presenceDeparted";
171
+ readonly CUSTOM_EVENT: "customEvent";
172
+ readonly UNKNOWN: "unknown";
173
+ };
174
+ type PresenceEventDataType = typeof PresenceEventDataType[keyof typeof PresenceEventDataType];
175
+ /**
176
+ * Any client that subscribes to presence events via `DocumentRef.onPresence` will
177
+ * be considered 'present' on the document, and trigger an 'arrived' presence event.
178
+ * When they disconnect or unsubscribe from presence events, a 'departed' presence event
179
+ * will be triggered.
180
+ */
181
+ interface PresenceEventDataArrived {
182
+ readonly type: typeof PresenceEventDataType.ARRIVED;
183
+ }
184
+ /**
185
+ * Any client that subscribes to presence events via `DocumentRef.onPresence` will
186
+ * be considered 'present' on the document, and trigger an 'arrived' presence event.
187
+ * When they disconnect or unsubscribe from presence events, a 'departed' presence event
188
+ * will be triggered.
189
+ */
190
+ interface PresenceEventDataDeparted {
191
+ readonly type: typeof PresenceEventDataType.DEPARTED;
192
+ }
193
+ /**
194
+ * Application specific custom presence event data.
195
+ *
196
+ * Each different model type used for presence is expected to update the latest
197
+ * 'presence state' for that model type.
198
+ *
199
+ * For example, your app may have need to broadcast user cursor positions and
200
+ * selection ranges as presence data. You could define your schema to include a
201
+ * `CursorPosition` and `SelectionRange` record types, and set them
202
+ * independently via `{@link DocumentRef.updateCustomPresence}`. Each model type
203
+ * sent as a custom presence event should be considered a separate 'channel' of
204
+ * presence data on this document.
205
+ */
206
+ interface PresenceEventDataCustom<M extends Model = Model> {
207
+ readonly type: typeof PresenceEventDataType.CUSTOM_EVENT;
208
+ readonly eventData: ModelData<M>;
209
+ readonly model: M;
210
+ }
211
+ /**
212
+ * Fallback for unrecognized activity event types.
213
+ *
214
+ * This allows some flexibility with new event types added to the platform.
215
+ * Likely unknown events represent a new platform event type and will be handled
216
+ * in a future release of pack libraries and can be safely ignored by
217
+ * applications.
218
+ */
219
+ interface PresenceEventUnknown {
220
+ readonly type: "unknown";
221
+ readonly rawType: string;
222
+ readonly rawData: unknown;
223
+ }
224
+ type PresenceEventData = PresenceEventDataArrived | PresenceEventDataDeparted | PresenceEventDataCustom | PresenceEventUnknown;
225
+ /**
226
+ * An event representing a transient awareness or presence change for a user on this document.
227
+ * The presence channel is intended for ephemeral data such as user cursors, selections, or
228
+ * other live collaboration indicators.
229
+ *
230
+ * PresenceEvents are not persisted in document history.
231
+ *
232
+ * When a client goes offline, its presence is considered departed and any presence events
233
+ * associated with that user should be considered stale and / or cleared.
234
+ */
235
+ interface PresenceEvent {
236
+ readonly userId: UserId;
237
+ readonly eventData: PresenceEventData;
238
+ }
239
+
240
+ /**
241
+ * A function that can be called to unsubscribe from a previously subscribed event interface.
242
+ */
74
243
  type Unsubscribe = () => void;
75
244
 
76
245
  type RecordId = Flavored<"RecordId">;
77
246
  declare const RecordRefBrand: unique symbol;
247
+ /**
248
+ * A reference providing an API to interact with a specific record in a
249
+ * document. This is the main interface for accessing and updating individual
250
+ * records.
251
+ *
252
+ * These will be created by docRef or recordCollectionRef APIs for example and
253
+ * should not be created manually. RecordRefs are stable objects that can be
254
+ * used for reference equality checks.
255
+ *
256
+ * @example
257
+ * ```ts
258
+ * import { DocumentRef, DocumentSchema, MyModel } from "@myapp/schema";
259
+ * import { app } from "./appInstance";
260
+ *
261
+ * const docRef = app.getDocRef<DocumentSchema>(someDocumentId);
262
+ *
263
+ * const recordRef = docRef.getRecords(MyModel).set("my-record-id", { myFieldName: "some value", foo: 42 });
264
+ *
265
+ * // Or get a specific record.
266
+ * const recordRef = docRef.getRecords(MyModel).get("my-record-id");
267
+ */
78
268
  interface RecordRef<M extends Model = Model> {
79
269
  readonly docRef: DocumentRef;
80
270
  readonly id: RecordId;
81
271
  readonly model: M;
82
272
  readonly [RecordRefBrand]: typeof RecordRefBrand;
273
+ /**
274
+ * Get the current state of the record in a plain object.
275
+ * If there is an active subscription to the document this is the current state of the record in memory.
276
+ * Otherwise, this will fetch the latest state from the server.
277
+ */
83
278
  getSnapshot(): Promise<ModelData<M>>;
279
+ /**
280
+ * Subscribe to changes in the record.
281
+ * @param callback The callback to invoke when the record changes.
282
+ * @returns An unsubscribe function.
283
+ *
284
+ * @example
285
+ * ```ts
286
+ * // Subscribe to changes
287
+ * recordRef.onChange((newSnapshot, recordRef) => {
288
+ * console.log("Record changed:", newSnapshot);
289
+ * });
290
+ *
291
+ * // Submit a change
292
+ * recordRef.set({ myFieldName: "new value" });
293
+ * ```
294
+ */
84
295
  onChange(callback: (snapshot: ModelData<M>, recordRef: RecordRef<M>) => void): Unsubscribe;
296
+ /**
297
+ * Subscribe to deletion of the record.
298
+ * @param callback The callback to invoke when the record is deleted.
299
+ * @returns An unsubscribe function.
300
+ *
301
+ * @example
302
+ * ```ts
303
+ * // Subscribe to deletion
304
+ * recordRef.onDeleted((recordRef) => {
305
+ * console.log("Record deleted:", recordRef.id);
306
+ * });
307
+ *
308
+ * // Trigger the deletion
309
+ * docRef.getRecords(MyModel).delete(recordRef.id);
310
+ * ```
311
+ */
85
312
  onDeleted(callback: (recordRef: RecordRef<M>) => void): Unsubscribe;
313
+ /**
314
+ * Set the data for the record (creating it if it doesn't exist).
315
+ *
316
+ * @see {onChange} to subscribe to changes to the record.
317
+ *
318
+ * @param record - The plain object data to set for the record, corresponding to the model's schema.
319
+ * @returns An ignorable promise that resolves when the record is published.
320
+ *
321
+ * @example
322
+ * ```ts
323
+ * await recordRef.set({ field: "value" });
324
+ * ```
325
+ */
86
326
  set(record: ModelData<M>): Promise<void>;
87
327
  }
88
328
 
89
329
  declare const RecordCollectionRefBrand: unique symbol;
330
+ /**
331
+ * A reference providing an API to interact with a collection of records in a document.
332
+ */
90
333
  interface RecordCollectionRef<M extends Model = Model> {
91
334
  readonly docRef: DocumentRef;
92
335
  readonly model: M;
93
336
  readonly [RecordCollectionRefBrand]: typeof RecordCollectionRefBrand;
337
+ /**
338
+ * Delete a record from the collection (and the document).
339
+ *
340
+ * @param id - The ID of the record to delete.
341
+ * @returns A promise that resolves when the record is deleted.
342
+ */
94
343
  delete(id: RecordId): Promise<void>;
344
+ /**
345
+ * Get a {@link RecordRef} from the collection. This provides the main API for
346
+ * accessing and updating individual records in a document.
347
+ *
348
+ * @param id - The ID of the record to get.
349
+ * @returns The record reference, or undefined if it doesn't exist. The
350
+ * recordRef is a stable object and can be used for reference equality checks.
351
+ */
95
352
  get(id: RecordId): RecordRef<M> | undefined;
353
+ /**
354
+ * Check if a record exists in the collection.
355
+ *
356
+ * @param id - The ID of the record to check.
357
+ * @returns True if the record exists, false otherwise.
358
+ */
96
359
  has(id: RecordId): boolean;
360
+ /**
361
+ * Set the data for a record in the collection (creating it if it doesn't exist).
362
+ *
363
+ * @param id - The ID of the record to set.
364
+ * @param state - The data to set for the record.
365
+ * @returns A promise that resolves when the record is set.
366
+ *
367
+ * @example
368
+ * ```ts
369
+ * const recordCollection = docRef.getRecords(MyModel);
370
+ * await recordCollection.set("record-id", { field: "value" });
371
+ * ```
372
+ */
97
373
  set(id: RecordId, state: ModelData<M>): Promise<void>;
98
374
  readonly size: number;
99
375
  [Symbol.iterator](): Iterator<RecordRef<M>>;
376
+ /**
377
+ * Subscribe to added items in the collection.
378
+ *
379
+ * @param callback - The callback to invoke when items are added.
380
+ * @returns An unsubscribe function.
381
+ */
100
382
  readonly onItemsAdded: (callback: (items: readonly RecordRef<M>[]) => void) => () => void;
383
+ /**
384
+ * Subscribe to changed items in the collection.
385
+ *
386
+ * @param callback - The callback to invoke when items are changed.
387
+ * @returns An unsubscribe function.
388
+ */
101
389
  readonly onItemsChanged: (callback: (items: readonly RecordRef<M>[]) => void) => () => void;
390
+ /**
391
+ * Subscribe to deleted items in the collection.
392
+ *
393
+ * @param callback - The callback to invoke when items are deleted.
394
+ * @returns An unsubscribe function.
395
+ */
102
396
  readonly onItemsDeleted: (callback: (items: readonly RecordRef<M>[]) => void) => () => void;
103
397
  }
104
398
 
105
399
  type DocumentId = Flavored<"DocumentId">;
400
+ /**
401
+ * Options for subscribing to presence events on a document.
402
+ */
403
+ interface PresenceSubscriptionOptions {
404
+ /**
405
+ * If true, presence events originating from the local user will be ignored.
406
+ *
407
+ * @default true
408
+ */
409
+ readonly ignoreSelfUpdates?: boolean;
410
+ }
106
411
  declare const DocumentRefBrand: unique symbol;
412
+ /**
413
+ * A reference to a document in the Pack system.
414
+ *
415
+ * A documentRef returned by various interfaces from the pack app instance or
416
+ * utilities such as react hooks from @palantir/pack.state.react provides
417
+ * methods to interact with the document, such as subscribing to & making
418
+ * changes to the document state and also related activity or presence events.
419
+ *
420
+ * A stable documentRef object is guaranteed for the same document id within the
421
+ * same app instance.
422
+ */
107
423
  interface DocumentRef<D extends DocumentSchema = DocumentSchema> {
108
424
  readonly id: DocumentId;
109
425
  readonly schema: D;
110
426
  readonly [DocumentRefBrand]: typeof DocumentRefBrand;
111
- readonly getDocSnapshot: () => Promise<DocumentState<D>>;
112
- readonly getRecords: <R extends Model>(model: R) => RecordCollectionRef<R>;
113
- readonly onMetadataChange: (callback: (docId: DocumentRef<D>, metadata: DocumentMetadata) => void) => Unsubscribe;
114
- readonly onStateChange: (callback: (docRef: DocumentRef<D>) => void) => Unsubscribe;
427
+ /**
428
+ * Get a snapshot of the current document state.
429
+ *
430
+ * This is largely for debugging and dumps a json view of the whole document state.
431
+ *
432
+ * @experimental
433
+ */
434
+ getDocSnapshot(): Promise<DocumentState<D>>;
435
+ /**
436
+ * Get or create a ref to the collection of all records for the specified
437
+ * model in this document.
438
+ *
439
+ * @param model The model type from the application's generated schema.
440
+ * @returns A stable {@link RecordCollectionRef} object providing an interface
441
+ * to interact with the records of the specified model type in this document.
442
+ *
443
+ * @example
444
+ * ```ts
445
+ * import { DocumentModel, MyModel } from "@myapp/schema";
446
+ * import { app } from "./appInstance";
447
+ *
448
+ * const docRef = app.state.createDocRef(DocumentModel, someDocumentId);
449
+ * const myRecordCollection = docRef.getRecords(MyModel);
450
+ *
451
+ * myRecordCollection.onItemsAdded((items) => {
452
+ * console.log("New records added:", items);
453
+ * })
454
+ * ```
455
+ */
456
+ getRecords<R extends Model>(model: R): RecordCollectionRef<R>;
457
+ /**
458
+ * Subscribe to activity events for the document.
459
+ *
460
+ * Activity is used by applications to describe changes to the document, for
461
+ * populating activity feeds, change histories, notifications and similar
462
+ * features.
463
+ *
464
+ * @see {withTransaction} for making edits that generate activity events.
465
+ *
466
+ * @returns An unsubscribe function.
467
+ * @example
468
+ * ```ts
469
+ * const unsubscribe = docRef.onActivity((docRef, event) => {
470
+ * console.log("Activity event:", event);
471
+ * });
472
+ *
473
+ * // Submit an edit with a description to generate an activity event.
474
+ * docRef.withTransaction(() => {
475
+ * // make some edits to the document here
476
+ * }, {
477
+ * model: MyEventModel,
478
+ * data: {
479
+ * myDataField: "some value",
480
+ * foo: 42,
481
+ * },
482
+ * });
483
+ *
484
+ * // Later, to unsubscribe:
485
+ * unsubscribe();
486
+ * ```
487
+ */
488
+ onActivity(callback: (docRef: DocumentRef<D>, event: ActivityEvent) => void): Unsubscribe;
489
+ /**
490
+ * Subscribe to metadata changes for the document.
491
+ *
492
+ * @returns An unsubscribe function.
493
+ * @example
494
+ * ```ts
495
+ * const unsubscribe = docRef.onMetadataChange((docRef, metadata) => {
496
+ * console.log("Metadata changed:", metadata);
497
+ * });
498
+ *
499
+ * // Later, to unsubscribe:
500
+ * unsubscribe();
501
+ * ```
502
+ */
503
+ onMetadataChange(callback: (docRef: DocumentRef<D>, metadata: DocumentMetadata) => void): Unsubscribe;
504
+ /**
505
+ * Subscribe to presence events for the document.
506
+ *
507
+ * Presence events are a way to broadcast and receive non-persisted awareness
508
+ * and presence events. For example, a user moving their cursor in a
509
+ * collaborative editor could be broadcast via custom presence events.
510
+ *
511
+ * @see {@link updateCustomPresence} to publish custom presence updates.
512
+ *
513
+ * @param callback The callback to invoke on presence events.
514
+ * @param options Options for the presence subscription.
515
+ * @returns An unsubscribe function.
516
+ * @example
517
+ * ```ts
518
+ * const unsubscribe = docRef.onPresence((docRef, event) => {
519
+ * console.log("Presence event:", event);
520
+ * if (event.model === MyPresenceModel) {
521
+ * updateCursor((event.eventData as ModelData<MyPresenceModel>).cursorPosition);
522
+ * }
523
+ * }, { ignoreSelfUpdates: true });
524
+ *
525
+ * // Broadcast a presence update
526
+ * docRef.updateCustomPresence(MyPresenceModel, {
527
+ * cursorPosition: [42, 7],
528
+ * });
529
+ *
530
+ * // Later, to unsubscribe:
531
+ * unsubscribe();
532
+ * ```
533
+ */
534
+ onPresence(callback: (docRef: DocumentRef<D>, event: PresenceEvent) => void, options?: PresenceSubscriptionOptions): Unsubscribe;
535
+ /**
536
+ * Subscribe to be notified any time the document state changes.
537
+ * This is largely for testing purposes.
538
+ *
539
+ * @experimental
540
+ *
541
+ * @param callback The callback to invoke on state changes.
542
+ * @returns An unsubscribe function.
543
+ * @example
544
+ * ```ts
545
+ * const unsubscribe = docRef.onStateChange((docRef) => {
546
+ * console.log("Document state changed:", docRef);
547
+ * });
548
+ *
549
+ * // Later, to unsubscribe:
550
+ * unsubscribe();
551
+ * ```
552
+ */
553
+ onStateChange(callback: (docRef: DocumentRef<D>) => void): Unsubscribe;
554
+ /**
555
+ * Broadcasts an update for the specified model as presence data to other
556
+ * subscribers.
557
+ *
558
+ * Presence data is ephemeral and not stored as part of the document state. It
559
+ * is intended for broadcasting transient user presence and awareness
560
+ * information. Each different model type used for presence is expected to
561
+ * update the latest 'presence state' for that model type.
562
+ *
563
+ * @see {@link onPresence} to subscribe to presence updates.
564
+ *
565
+ * @param model The model type to update presence for.
566
+ * @param eventData The new presence data for the model.
567
+ */
568
+ updateCustomPresence<M extends Model = Model>(model: M, eventData: ModelData<M>): void;
569
+ /**
570
+ * Execute one or more document edits within a transaction, optionally providing
571
+ * a description of the edit for activity tracking.
572
+ *
573
+ * All edits made within the provided function will be treated as a single
574
+ * atomic edit operation. If a description is provided, an activity event will
575
+ * be generated for the edit.
576
+ *
577
+ * If this is called within an existing transaction, the inner edits will be
578
+ * included in the outer transaction only, and the inner descriptions will be
579
+ * discarded.
580
+ *
581
+ * @see {@link onActivity} to subscribe to activity events on this document.
582
+ *
583
+ * @param fn A lambda including some document edits.
584
+ * @param description Optional description of the edit for activity tracking.
585
+ *
586
+ * @example
587
+ * ```ts
588
+ * docRef.withTransaction(() => {
589
+ * const myRecords = docRef.getRecords(MyModel);
590
+ * myRecords.set("record-1", { field: "new value" });
591
+ * myRecords.delete("record-2");
592
+ * }, {
593
+ * model: MyEditEventModel,
594
+ * data: {
595
+ * summary: "Updated record-1 and deleted record-2",
596
+ * },
597
+ * });
598
+ * ```
599
+ */
600
+ withTransaction(fn: () => void, description?: EditDescription): void;
115
601
  }
116
602
 
117
603
  type MediaId = Flavored<"MediaId">;
@@ -136,12 +622,4 @@ interface ObjectRef {
136
622
  readonly subscribe?: (callback: unknown) => unknown;
137
623
  }
138
624
 
139
- type UserId = Flavored<"pack:UserId">;
140
- declare const UserRefBrand: unique symbol;
141
- interface UserRef {
142
- readonly userId: UserId;
143
- readonly [UserRefBrand]: typeof UserRefBrand;
144
- readonly get: (force?: boolean) => Promise<unknown>;
145
- }
146
-
147
- export { type DiscretionaryPrincipal, type DiscretionaryPrincipal_All, type DiscretionaryPrincipal_GroupId, type DiscretionaryPrincipal_UserId, type DocumentId, type DocumentMetadata, type DocumentRef, DocumentRefBrand, type DocumentSchema, type DocumentSchemaMetadata, type DocumentState, ExternalRefType, type MediaId, type MediaRef, MediaRefBrand, Metadata, type Model, type ModelData, type ModelMetadata, type ObjectId, type ObjectRef, ObjectRefBrand, type RecordCollectionRef, RecordCollectionRefBrand, type RecordId, type RecordRef, RecordRefBrand, type Unsubscribe, type UserId, type UserRef, UserRefBrand, type WithMetadata, getMetadata };
625
+ export { type ActivityEvent, type ActivityEventData, type ActivityEventDataCustom, ActivityEventDataType, type ActivityEventDataUnknown, type ActivityEventId, type DiscretionaryPrincipal, type DiscretionaryPrincipal_All, type DiscretionaryPrincipal_GroupId, type DiscretionaryPrincipal_UserId, type DocumentId, type DocumentMetadata, type DocumentRef, DocumentRefBrand, type DocumentSchema, type DocumentSchemaMetadata, type DocumentState, type EditDescription, ExternalRefType, type MediaId, type MediaRef, MediaRefBrand, Metadata, type Model, type ModelData, type ModelMetadata, type ObjectId, type ObjectRef, ObjectRefBrand, type PresenceEvent, type PresenceEventData, type PresenceEventDataArrived, type PresenceEventDataCustom, type PresenceEventDataDeparted, PresenceEventDataType, type PresenceEventUnknown, type PresenceSubscriptionOptions, type RecordCollectionRef, RecordCollectionRefBrand, type RecordId, type RecordRef, RecordRefBrand, type Unsubscribe, type UserId, type UserRef, UserRefBrand, type WithMetadata, getMetadata };
@@ -1,3 +1,9 @@
1
+ // src/types/ActivityEvent.ts
2
+ var ActivityEventDataType = {
3
+ CUSTOM_EVENT: "customEvent",
4
+ UNKNOWN: "unknown"
5
+ };
6
+
1
7
  // src/types/DocumentRef.ts
2
8
  var DocumentRefBrand = Symbol("pack:DocumentRef");
3
9
 
@@ -7,11 +13,21 @@ var MediaRefBrand = Symbol("pack:MediaRef");
7
13
  // src/types/Metadata.ts
8
14
  var Metadata = Symbol("@palantir/pack.document-schema/metadata");
9
15
  function getMetadata(obj) {
10
- const metadata = obj[Metadata];
11
- if (metadata == null) {
12
- throw new Error("Object does not have metadata");
16
+ const directMetadata = obj[Metadata];
17
+ if (directMetadata != null) {
18
+ return directMetadata;
19
+ }
20
+ const metadataString = Metadata.toString();
21
+ const symbolKeys = Object.getOwnPropertySymbols(obj);
22
+ for (const symbolKey of symbolKeys) {
23
+ if (symbolKey.toString() === metadataString) {
24
+ const fallbackMetadata = obj[symbolKey];
25
+ if (fallbackMetadata != null) {
26
+ return fallbackMetadata;
27
+ }
28
+ }
13
29
  }
14
- return metadata;
30
+ throw new Error("Object does not have metadata");
15
31
  }
16
32
 
17
33
  // src/types/Model.ts
@@ -25,6 +41,14 @@ var ExternalRefType = {
25
41
  // src/types/ObjectRef.ts
26
42
  var ObjectRefBrand = Symbol("pack:ObjectRef");
27
43
 
44
+ // src/types/PresenceEvent.ts
45
+ var PresenceEventDataType = {
46
+ ARRIVED: "presenceArrived",
47
+ DEPARTED: "presenceDeparted",
48
+ CUSTOM_EVENT: "customEvent",
49
+ UNKNOWN: "unknown"
50
+ };
51
+
28
52
  // src/types/RecordCollectionRef.ts
29
53
  var RecordCollectionRefBrand = Symbol("pack:RecordCollectionRef");
30
54
 
@@ -34,6 +58,6 @@ var RecordRefBrand = Symbol("pack:RecordRef");
34
58
  // src/types/UserRef.ts
35
59
  var UserRefBrand = Symbol("pack:UserRef");
36
60
 
37
- export { DocumentRefBrand, ExternalRefType, MediaRefBrand, Metadata, ObjectRefBrand, RecordCollectionRefBrand, RecordRefBrand, UserRefBrand, getMetadata };
61
+ export { ActivityEventDataType, DocumentRefBrand, ExternalRefType, MediaRefBrand, Metadata, ObjectRefBrand, PresenceEventDataType, RecordCollectionRefBrand, RecordRefBrand, UserRefBrand, getMetadata };
38
62
  //# sourceMappingURL=index.js.map
39
63
  //# sourceMappingURL=index.js.map