import { assert } from "@fluidframework/common-utils" ; import { ISequencedDocumentMessage , MessageType } from "@fluidframework/protocol-definitions" ; import { IChannelAttributes , IFluidDataStoreRuntime , IChannelStorageService , IChannelFactory , Serializable , } from "@fluidframework/datastore-definitions" ; import { ISummaryTreeWithStats } from "@fluidframework/runtime-definitions" ; import { readAndParse } from "@fluidframework/driver-utils" ; import { createSingleBlobSummary , IFluidSerializer , SharedObject } from "@fluidframework/shared-object-base" ; import { CellFactory } from "./cellFactory" ; import { ISharedCell , ISharedCellEvents } from "./interfaces" ; /**
 * Description of a cell delta operation
 */ type ICellOperation = ISetCellOperation | IDeleteCellOperation ; interface ISetCellOperation { type : "setCell" ; value : ICellValue ; } interface IDeleteCellOperation { type : "deleteCell" ; } interface ICellValue { value : any ; } const snapshotFileName = "header" ; remarks export class SharedCell < T = any > extends SharedObject < ISharedCellEvents < T > > implements ISharedCell < T > { param runtime param id returns public static create ( runtime , id ? ) { return runtime . createChannel ( id , CellFactory . Type ) as SharedCell ; } returns public static getFactory ( ) { return new CellFactory ( ) ; } /**
     * The data held by this cell.
     */ private data : Serializable < T > | undefined ; /**
     * This is used to assign a unique id to outgoing messages. It is used to track messages until
     * they are ack'd.
     */ private messageId : number = - 1 ; /**
     * This keeps track of the messageId of messages that have been ack'd. It is updated every time
     * we a message is ack'd with it's messageId.
     */ private messageIdObserved : number = - 1 ; param runtime param id constructor ( id , runtime , attributes ) { super ( id , runtime , attributes ) ; } /**
     * {@inheritDoc ISharedCell.get}
     */ public get ( ) { return this . data ; } /**
     * {@inheritDoc ISharedCell.set}
     */ public set ( value ) { if ( SharedObject . is ( value ) ) { throw new Error ( "SharedObject sets are no longer supported. Instead set the SharedObject handle." ) ; } const operationValue = { value : this . serializer . encode ( value , this . handle ) } ; this . setCore ( value ) ; if ( ! this . isAttached ( ) ) { return ; } const op = { type : "setCell" , value : operationValue } ; this . submitLocalMessage ( op , ++ this . messageId ) ; } /**
     * {@inheritDoc ISharedCell.delete}
     */ public delete ( ) { this . deleteCore ( ) ; if ( ! this . isAttached ( ) ) { return ; } const op = { type : "deleteCell" } ; this . submitLocalMessage ( op , ++ this . messageId ) ; } /**
     * {@inheritDoc ISharedCell.empty}
     */ public empty ( ) { return this . data === undefined ; } returns protected summarizeCore ( serializer ) { const content = { value : this . data } ; return createSingleBlobSummary ( snapshotFileName , serializer . stringify ( content , this . handle ) ) ; } /**
     * {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}
     */ protected async loadCore ( storage ) { const content = await readAndParse < ICellValue > ( storage , snapshotFileName ) ; this . data = this . decode ( content ) ; } /**
     * Initialize a local instance of cell
     */ protected initializeLocalCore ( ) { this . data = undefined ; } /**
     * Process the cell value on register
     */ protected registerCore ( ) { if ( SharedObject . is ( this . data ) ) { this . data . bindToContext ( ) ; } } /**
     * Call back on disconnect
     */ protected onDisconnect ( ) { } param message param local param localOpMetadata protected processCore ( message , local , localOpMetadata ) { if ( this . messageId !== this . messageIdObserved ) { if ( local ) { const messageIdReceived = localOpMetadata as number ; assert ( messageIdReceived !== undefined && messageIdReceived <= this . messageId , 0x00c ) ; this . messageIdObserved = localOpMetadata as number ; } return ; } if ( message . type === MessageType . Operation && ! local ) { const op = message . contents as ICellOperation ; switch ( op . type ) { case "setCell" : this . setCore ( this . decode ( op . value ) ) ; break ; case "deleteCell" : this . deleteCore ( ) ; break ; default : throw new Error ( "Unknown operation" ) ; } } } private setCore ( value ) { this . data = value ; this . emit ( "valueChanged" , value ) ; } private deleteCore ( ) { this . data = undefined ; this . emit ( "delete" ) ; } private decode ( cellValue ) { const value = cellValue . value ; return this . serializer . decode ( value ) ; } protected applyStashedOp ( ) { throw new Error ( "not implemented" ) ; } }