@@ -7,14 +7,16 @@ export type MaterializationSource = {
77 *
88 * `replica` is a low-level CRDT replica id, not an auth/user identity.
99 */
10- operation : {
10+ operation ? : {
1111 id : {
1212 replica : Uint8Array ;
1313 counter : number ;
1414 } ;
1515 /** Lamport timestamp assigned to the operation. */
1616 lamport : number ;
1717 } ;
18+ /** Local write ids supplied to the append/local write API that produced this visible change. */
19+ writeIds ?: string [ ] ;
1820 /** Future auth metadata for the operation signer, when available. */
1921 signer ?: {
2022 publicKey : Uint8Array ;
@@ -23,10 +25,10 @@ export type MaterializationSource = {
2325
2426type ChangeSource = {
2527 /**
26- * Operation source metadata when the materializer can attribute the visible change to one exact op .
28+ * Source metadata for the visible change.
2729 *
28- * Conservative catch-up/rebuild paths may omit this when a visible change is derived from rebuilt
29- * state instead of a single operation.
30+ * Conservative catch-up/rebuild paths may omit operation metadata when a visible change is derived
31+ * from rebuilt state instead of a single operation.
3032 */
3133 source ?: MaterializationSource ;
3234} ;
@@ -70,11 +72,9 @@ export function emptyMaterializationOutcome(headSeq = 0): MaterializationOutcome
7072
7173/**
7274 * Event emitted after write-path materialization, or after read-path recovery advances a pending
73- * materialization frontier. `writeIds` echoes optional ids supplied to append APIs .
75+ * materialization frontier. Local write ids are echoed on each affected change's `source.writeIds` .
7476 */
75- export type MaterializationEvent = MaterializationOutcome & {
76- writeIds ?: string [ ] ;
77- } ;
77+ export type MaterializationEvent = MaterializationOutcome ;
7878
7979export type MaterializationListener = ( event : MaterializationEvent ) => void ;
8080
@@ -94,10 +94,7 @@ export function createMaterializationDispatcher(): MaterializationDispatcher {
9494
9595 const emitOutcome = ( outcome : MaterializationOutcome , writeId ?: string ) => {
9696 if ( outcome . changes . length === 0 ) return ;
97- emitEvent ( {
98- ...outcome ,
99- ...( writeId ? { writeIds : [ writeId ] } : { } ) ,
100- } ) ;
97+ emitEvent ( addMaterializationWriteId ( outcome , writeId ) ) ;
10198 } ;
10299
103100 const onMaterialized = ( listener : MaterializationListener ) => {
@@ -110,6 +107,23 @@ export function createMaterializationDispatcher(): MaterializationDispatcher {
110107 return { emitEvent, emitOutcome, onMaterialized } ;
111108}
112109
110+ export function addMaterializationWriteId (
111+ outcome : MaterializationOutcome ,
112+ writeId ?: string ,
113+ ) : MaterializationEvent {
114+ if ( ! writeId ) return { ...outcome } ;
115+ return {
116+ ...outcome ,
117+ changes : outcome . changes . map ( ( change ) => ( {
118+ ...change ,
119+ source : {
120+ ...change . source ,
121+ writeIds : [ ...( change . source ?. writeIds ?? [ ] ) , writeId ] ,
122+ } ,
123+ } ) ) ,
124+ } ;
125+ }
126+
113127export type WriteOptions = {
114128 writeId ?: string ;
115129} ;
@@ -119,7 +133,7 @@ export type LocalWriteAuthSession = {
119133} ;
120134
121135export type LocalWriteOptions = {
122- /** Echoed on the materialization event emitted by this local write. */
136+ /** Echoed on each materialized change emitted by this local write. */
123137 writeId ?: string ;
124138
125139 /**
0 commit comments