@fluidframework/presence 2.10.0 → 2.12.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 (91) hide show
  1. package/README.md +37 -2
  2. package/dist/alpha.d.ts +1 -1
  3. package/dist/exposedUtilityTypes.d.ts +5 -5
  4. package/dist/exposedUtilityTypes.d.ts.map +1 -1
  5. package/dist/exposedUtilityTypes.js.map +1 -1
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/latestMapValueManager.d.ts +2 -2
  10. package/dist/latestMapValueManager.d.ts.map +1 -1
  11. package/dist/latestMapValueManager.js +2 -2
  12. package/dist/latestMapValueManager.js.map +1 -1
  13. package/dist/latestValueManager.d.ts +2 -2
  14. package/dist/latestValueManager.d.ts.map +1 -1
  15. package/dist/latestValueManager.js +2 -2
  16. package/dist/latestValueManager.js.map +1 -1
  17. package/dist/notificationsManager.d.ts +28 -15
  18. package/dist/notificationsManager.d.ts.map +1 -1
  19. package/dist/notificationsManager.js +3 -5
  20. package/dist/notificationsManager.js.map +1 -1
  21. package/dist/package.json +0 -1
  22. package/dist/presence.d.ts +2 -2
  23. package/dist/presence.d.ts.map +1 -1
  24. package/dist/presence.js.map +1 -1
  25. package/dist/presenceDatastoreManager.d.ts +14 -1
  26. package/dist/presenceDatastoreManager.d.ts.map +1 -1
  27. package/dist/presenceDatastoreManager.js +96 -18
  28. package/dist/presenceDatastoreManager.js.map +1 -1
  29. package/dist/presenceManager.d.ts.map +1 -1
  30. package/dist/presenceManager.js +2 -2
  31. package/dist/presenceManager.js.map +1 -1
  32. package/dist/presenceStates.d.ts +6 -0
  33. package/dist/presenceStates.d.ts.map +1 -1
  34. package/dist/presenceStates.js +7 -1
  35. package/dist/presenceStates.js.map +1 -1
  36. package/dist/systemWorkspace.d.ts +1 -1
  37. package/dist/systemWorkspace.d.ts.map +1 -1
  38. package/dist/systemWorkspace.js.map +1 -1
  39. package/dist/timerManager.d.ts +37 -0
  40. package/dist/timerManager.d.ts.map +1 -0
  41. package/dist/timerManager.js +65 -0
  42. package/dist/timerManager.js.map +1 -0
  43. package/lib/alpha.d.ts +1 -1
  44. package/lib/exposedUtilityTypes.d.ts +5 -5
  45. package/lib/exposedUtilityTypes.d.ts.map +1 -1
  46. package/lib/exposedUtilityTypes.js.map +1 -1
  47. package/lib/index.d.ts +1 -1
  48. package/lib/index.d.ts.map +1 -1
  49. package/lib/index.js.map +1 -1
  50. package/lib/latestMapValueManager.d.ts +2 -2
  51. package/lib/latestMapValueManager.d.ts.map +1 -1
  52. package/lib/latestMapValueManager.js +1 -1
  53. package/lib/latestMapValueManager.js.map +1 -1
  54. package/lib/latestValueManager.d.ts +2 -2
  55. package/lib/latestValueManager.d.ts.map +1 -1
  56. package/lib/latestValueManager.js +1 -1
  57. package/lib/latestValueManager.js.map +1 -1
  58. package/lib/notificationsManager.d.ts +28 -15
  59. package/lib/notificationsManager.d.ts.map +1 -1
  60. package/lib/notificationsManager.js +2 -4
  61. package/lib/notificationsManager.js.map +1 -1
  62. package/lib/presence.d.ts +2 -2
  63. package/lib/presence.d.ts.map +1 -1
  64. package/lib/presence.js.map +1 -1
  65. package/lib/presenceDatastoreManager.d.ts +14 -1
  66. package/lib/presenceDatastoreManager.d.ts.map +1 -1
  67. package/lib/presenceDatastoreManager.js +97 -19
  68. package/lib/presenceDatastoreManager.js.map +1 -1
  69. package/lib/presenceManager.d.ts.map +1 -1
  70. package/lib/presenceManager.js +1 -1
  71. package/lib/presenceManager.js.map +1 -1
  72. package/lib/presenceStates.d.ts +6 -0
  73. package/lib/presenceStates.d.ts.map +1 -1
  74. package/lib/presenceStates.js +6 -1
  75. package/lib/presenceStates.js.map +1 -1
  76. package/lib/systemWorkspace.d.ts +1 -1
  77. package/lib/systemWorkspace.d.ts.map +1 -1
  78. package/lib/systemWorkspace.js.map +1 -1
  79. package/lib/timerManager.d.ts +37 -0
  80. package/lib/timerManager.d.ts.map +1 -0
  81. package/lib/timerManager.js +61 -0
  82. package/lib/timerManager.js.map +1 -0
  83. package/package.json +21 -25
  84. package/dist/events/events.d.ts +0 -198
  85. package/dist/events/events.d.ts.map +0 -1
  86. package/dist/events/events.js +0 -157
  87. package/dist/events/events.js.map +0 -1
  88. package/lib/events/events.d.ts +0 -198
  89. package/lib/events/events.d.ts.map +0 -1
  90. package/lib/events/events.js +0 -152
  91. package/lib/events/events.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"presenceStates.js","sourceRoot":"","sources":["../src/presenceStates.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { RequiredBroadcastControl } from \"./broadcastControls.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type { ClientRecord } from \"./internalTypes.js\";\nimport { brandedObjectEntries } from \"./internalTypes.js\";\nimport type { ClientSessionId, ISessionClient } from \"./presence.js\";\nimport type { LocalStateUpdateOptions, StateDatastore } from \"./stateDatastore.js\";\nimport { handleFromDatastore } from \"./stateDatastore.js\";\nimport type { PresenceStates, PresenceStatesSchema } from \"./types.js\";\nimport { unbrandIVM } from \"./valueManager.js\";\n\n/**\n * Extracts `Part` from {@link InternalTypes.ManagerFactory} return type\n * matching the {@link PresenceStatesSchema} `Keys` given.\n *\n * @remarks\n * If the `Part` is an optional property, undefined will be included in the\n * result. Applying `Required` to the return type prior to extracting `Part`\n * does not work as expected. Use Exclude\\<, undefined\\> can be used as needed.\n *\n * @internal\n */\nexport type MapSchemaElement<\n\tTSchema extends PresenceStatesSchema,\n\tPart extends keyof ReturnType<TSchema[keyof TSchema]>,\n\tKeys extends keyof TSchema = keyof TSchema,\n> = ReturnType<TSchema[Keys]>[Part];\n\n/**\n * @internal\n */\nexport interface RuntimeLocalUpdateOptions {\n\tallowableUpdateLatencyMs: number;\n\n\t/**\n\t * Special option allowed for unicast notifications.\n\t */\n\ttargetClientId?: ClientConnectionId;\n}\n\n/**\n * @internal\n */\nexport interface PresenceRuntime {\n\treadonly clientSessionId: ClientSessionId;\n\tlookupClient(clientId: ClientConnectionId): ISessionClient;\n\tlocalUpdate(\n\t\tstates: { [key: string]: ClientUpdateEntry },\n\t\toptions: RuntimeLocalUpdateOptions,\n\t): void;\n}\n\ntype PresenceSubSchemaFromWorkspaceSchema<\n\tTSchema extends PresenceStatesSchema,\n\tPart extends keyof ReturnType<TSchema[keyof TSchema]>,\n> = {\n\t[Key in keyof TSchema]: MapSchemaElement<TSchema, Part, Key>;\n};\n\ntype MapEntries<TSchema extends PresenceStatesSchema> = PresenceSubSchemaFromWorkspaceSchema<\n\tTSchema,\n\t\"manager\"\n>;\n\n/**\n * ValueElementMap is a map of key to a map of clientId to ValueState.\n * It is not restricted to the schema of the map as it may receive updates from other clients\n * with managers that have not been registered locally. Each map node is responsible for keeping\n * all session's state to be able to pick arbitrary client to rebroadcast to others.\n *\n * This generic aspect makes some typing difficult. The loose typing is not broadcast to the\n * consumers that are expected to maintain their schema over multiple versions of clients.\n *\n * @internal\n */\nexport interface ValueElementMap<_TSchema extends PresenceStatesSchema> {\n\t[key: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<unknown>>;\n}\n\n// An attempt to make the type more precise, but it is not working.\n// If the casting in support code is too much we could keep two references to the same\n// complete datastore, but with the respective types desired.\n// type ValueElementMap<TSchema extends PresenceStatesNodeSchema> =\n// \t| {\n// \t\t\t[Key in keyof TSchema & string]?: {\n// \t\t\t\t[ClientSessionId: ClientSessionId]: InternalTypes.ValueDirectoryOrState<MapSchemaElement<TSchema,\"value\",Key>>;\n// \t\t\t};\n// \t }\n// \t| {\n// \t\t\t[key: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<unknown>>;\n// \t };\n// interface ValueElementMap<TValue> {\n// \t[Id: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<TValue>>;\n// \t// Version with local packed in is convenient for map, but not for join broadcast to serialize simply.\n// \t// [Id: string]: {\n// \t// \tlocal: InternalTypes.ValueDirectoryOrState<TValue>;\n// \t// \tall: ClientRecord<InternalTypes.ValueDirectoryOrState<TValue>>;\n// \t// };\n// }\n\n/**\n * @internal\n */\nexport type ClientUpdateEntry = InternalTypes.ValueDirectoryOrState<unknown> & {\n\tignoreUnmonitored?: true;\n};\n\ntype ClientUpdateRecord = ClientRecord<ClientUpdateEntry>;\n\ninterface ValueUpdateRecord {\n\t[valueKey: string]: ClientUpdateRecord;\n}\n\n/**\n * @internal\n */\nexport interface PresenceStatesInternal {\n\tensureContent<TSchemaAdditional extends PresenceStatesSchema>(\n\t\tcontent: TSchemaAdditional,\n\t\tcontrols: BroadcastControlSettings | undefined,\n\t): PresenceStates<TSchemaAdditional>;\n\tprocessUpdate(\n\t\treceived: number,\n\t\ttimeModifier: number,\n\t\tremoteDatastore: ValueUpdateRecord,\n\t\tsenderConnectionId: ClientConnectionId,\n\t): void;\n}\n\nfunction isValueDirectory<\n\tT,\n\tTValueState extends\n\t\t| InternalTypes.ValueRequiredState<T>\n\t\t| InternalTypes.ValueOptionalState<T>,\n>(\n\tvalue: InternalTypes.ValueDirectory<T> | TValueState,\n): value is InternalTypes.ValueDirectory<T> {\n\treturn \"items\" in value;\n}\n\nfunction mergeValueDirectory<\n\tT,\n\tTValueState extends\n\t\t| InternalTypes.ValueRequiredState<T>\n\t\t| InternalTypes.ValueOptionalState<T>,\n>(\n\tbase: TValueState | InternalTypes.ValueDirectory<T> | undefined,\n\tupdate: TValueState | InternalTypes.ValueDirectory<T>,\n\ttimeDelta: number,\n): TValueState | InternalTypes.ValueDirectory<T> {\n\tif (!isValueDirectory(update)) {\n\t\tif (base === undefined || update.rev > base.rev) {\n\t\t\treturn { ...update, timestamp: update.timestamp + timeDelta };\n\t\t}\n\t\treturn base;\n\t}\n\n\tlet mergeBase: InternalTypes.ValueDirectory<T>;\n\tif (base === undefined) {\n\t\tmergeBase = { rev: update.rev, items: {} };\n\t} else {\n\t\tconst baseIsDirectory = isValueDirectory(base);\n\t\tif (base.rev >= update.rev) {\n\t\t\tif (!baseIsDirectory) {\n\t\t\t\t// base is leaf value that is more recent - nothing to do\n\t\t\t\treturn base;\n\t\t\t}\n\t\t\t// While base has more advanced revision, assume mis-ordering or\n\t\t\t// missed and catchup update needs merged in.\n\t\t\tmergeBase = base;\n\t\t} else {\n\t\t\tmergeBase = { rev: update.rev, items: baseIsDirectory ? base.items : {} };\n\t\t}\n\t}\n\tfor (const [key, value] of Object.entries(update.items)) {\n\t\tconst baseElement = mergeBase.items[key];\n\t\tmergeBase.items[key] = mergeValueDirectory(baseElement, value, timeDelta);\n\t}\n\treturn mergeBase;\n}\n\n/**\n * Updates remote state into the local [untracked] datastore.\n *\n * @param key - The key of the datastore to merge the untracked data into.\n * @param remoteAllKnownState - The remote state to merge into the datastore.\n * @param datastore - The datastore to merge the untracked data into.\n *\n * @remarks\n * In the case of ignored unmonitored data, the client entries are not stored,\n * though the value keys will be populated and often remain empty.\n *\n * @internal\n */\nexport function mergeUntrackedDatastore(\n\tkey: string,\n\tremoteAllKnownState: ClientUpdateRecord,\n\tdatastore: ValueElementMap<PresenceStatesSchema>,\n\ttimeModifier: number,\n): void {\n\tif (!(key in datastore)) {\n\t\tdatastore[key] = {};\n\t}\n\tconst localAllKnownState = datastore[key];\n\tfor (const [clientSessionId, value] of brandedObjectEntries(remoteAllKnownState)) {\n\t\tif (!(\"ignoreUnmonitored\" in value)) {\n\t\t\tlocalAllKnownState[clientSessionId] = mergeValueDirectory(\n\t\t\t\tlocalAllKnownState[clientSessionId],\n\t\t\t\tvalue,\n\t\t\t\ttimeModifier,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * The default allowable update latency for PresenceStates workspaces in milliseconds.\n */\nconst defaultAllowableUpdateLatencyMs = 60;\n\n/**\n * Produces the value type of a schema element or set of elements.\n */\ntype SchemaElementValueType<\n\tTSchema extends PresenceStatesSchema,\n\tKeys extends keyof TSchema & string,\n> = Exclude<MapSchemaElement<TSchema, \"initialData\", Keys>, undefined>[\"value\"];\n\nclass PresenceStatesImpl<TSchema extends PresenceStatesSchema>\n\timplements\n\t\tPresenceStatesInternal,\n\t\tPresenceStates<TSchema>,\n\t\tStateDatastore<\n\t\t\tkeyof TSchema & string,\n\t\t\tSchemaElementValueType<TSchema, keyof TSchema & string>\n\t\t>\n{\n\tprivate readonly nodes: MapEntries<TSchema>;\n\tpublic readonly props: PresenceStates<TSchema>[\"props\"];\n\n\tpublic readonly controls: RequiredBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly runtime: PresenceRuntime,\n\t\tprivate readonly datastore: ValueElementMap<TSchema>,\n\t\tinitialContent: TSchema,\n\t\tcontrolsSettings: BroadcastControlSettings | undefined,\n\t) {\n\t\tthis.controls = new RequiredBroadcastControl(defaultAllowableUpdateLatencyMs);\n\t\tif (controlsSettings?.allowableUpdateLatencyMs !== undefined) {\n\t\t\tthis.controls.allowableUpdateLatencyMs = controlsSettings.allowableUpdateLatencyMs;\n\t\t}\n\n\t\t// Prepare initial map content from initial state\n\t\t{\n\t\t\tconst clientSessionId = this.runtime.clientSessionId;\n\t\t\tlet anyInitialValues = false;\n\t\t\tlet cumulativeAllowableUpdateLatencyMs: number | undefined;\n\t\t\t// eslint-disable-next-line unicorn/no-array-reduce\n\t\t\tconst initial = Object.entries(initialContent).reduce(\n\t\t\t\t(acc, [key, nodeFactory]) => {\n\t\t\t\t\tconst newNodeData = nodeFactory(key, handleFromDatastore(this));\n\t\t\t\t\tacc.nodes[key as keyof TSchema] = newNodeData.manager;\n\t\t\t\t\tif (\"initialData\" in newNodeData) {\n\t\t\t\t\t\tconst { value, allowableUpdateLatencyMs } = newNodeData.initialData;\n\t\t\t\t\t\tacc.datastore[key] = acc.datastore[key] ?? {};\n\t\t\t\t\t\tacc.datastore[key][clientSessionId] = value;\n\t\t\t\t\t\tacc.newValues[key] = value;\n\t\t\t\t\t\tif (allowableUpdateLatencyMs !== undefined) {\n\t\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs =\n\t\t\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs === undefined\n\t\t\t\t\t\t\t\t\t? allowableUpdateLatencyMs\n\t\t\t\t\t\t\t\t\t: Math.min(cumulativeAllowableUpdateLatencyMs, allowableUpdateLatencyMs);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tanyInitialValues = true;\n\t\t\t\t\t}\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\t\t\tnodes: {} as MapEntries<TSchema>,\n\t\t\t\t\tdatastore,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\t\t\tnewValues: {} as { [key: string]: InternalTypes.ValueDirectoryOrState<unknown> },\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.nodes = initial.nodes;\n\t\t\t// props is the public view of nodes that limits the entries types to\n\t\t\t// the public interface of the value manager with an additional type\n\t\t\t// filter that beguiles the type system. So just reinterpret cast.\n\t\t\tthis.props = this.nodes as unknown as PresenceStates<TSchema>[\"props\"];\n\n\t\t\tif (anyInitialValues) {\n\t\t\t\tthis.runtime.localUpdate(initial.newValues, {\n\t\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic knownValues<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t): {\n\t\tself: ClientSessionId | undefined;\n\t\tstates: ClientRecord<SchemaElementValueType<TSchema, Key>>;\n\t} {\n\t\treturn {\n\t\t\tself: this.runtime.clientSessionId,\n\t\t\tstates: this.datastore[key],\n\t\t};\n\t}\n\n\tpublic localUpdate<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t\tvalue: SchemaElementValueType<TSchema, Key> & ClientUpdateEntry,\n\t\toptions: LocalStateUpdateOptions,\n\t): void {\n\t\tthis.runtime.localUpdate(\n\t\t\t{ [key]: value },\n\t\t\t{\n\t\t\t\t...options,\n\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\toptions.allowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic update<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t\tclientId: ClientSessionId,\n\t\tvalue: Exclude<MapSchemaElement<TSchema, \"initialData\", Key>, undefined>[\"value\"],\n\t): void {\n\t\tconst allKnownState = this.datastore[key];\n\t\tallKnownState[clientId] = mergeValueDirectory(allKnownState[clientId], value, 0);\n\t}\n\n\tpublic lookupClient(clientId: ClientConnectionId): ISessionClient {\n\t\treturn this.runtime.lookupClient(clientId);\n\t}\n\n\tpublic add<\n\t\tTKey extends string,\n\t\tTValue extends InternalTypes.ValueDirectoryOrState<unknown>,\n\t\tTValueManager,\n\t>(\n\t\tkey: TKey,\n\t\tnodeFactory: InternalTypes.ManagerFactory<TKey, TValue, TValueManager>,\n\t): asserts this is PresenceStates<\n\t\tTSchema & Record<TKey, InternalTypes.ManagerFactory<TKey, TValue, TValueManager>>\n\t> {\n\t\tassert(!(key in this.nodes), 0xa3c /* Already have entry for key in map */);\n\t\tconst nodeData = nodeFactory(key, handleFromDatastore(this));\n\t\tthis.nodes[key] = nodeData.manager;\n\t\tif (\"initialData\" in nodeData) {\n\t\t\tconst { value, allowableUpdateLatencyMs } = nodeData.initialData;\n\t\t\tif (key in this.datastore) {\n\t\t\t\t// Already have received state from other clients. Kept in `all`.\n\t\t\t\t// TODO: Send current `all` state to state manager.\n\t\t\t} else {\n\t\t\t\tthis.datastore[key] = {};\n\t\t\t}\n\t\t\tthis.datastore[key][this.runtime.clientSessionId] = value;\n\t\t\tthis.runtime.localUpdate(\n\t\t\t\t{ [key]: value },\n\t\t\t\t{\n\t\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\t\tallowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic ensureContent<TSchemaAdditional extends PresenceStatesSchema>(\n\t\tcontent: TSchemaAdditional,\n\t\tcontrols: BroadcastControlSettings | undefined,\n\t): PresenceStates<TSchema & TSchemaAdditional> {\n\t\tif (controls?.allowableUpdateLatencyMs !== undefined) {\n\t\t\tthis.controls.allowableUpdateLatencyMs = controls.allowableUpdateLatencyMs;\n\t\t}\n\t\tfor (const [key, nodeFactory] of Object.entries(content)) {\n\t\t\tif (key in this.nodes) {\n\t\t\t\tconst node = unbrandIVM(this.nodes[key]);\n\t\t\t\tif (!(node instanceof nodeFactory.instanceBase)) {\n\t\t\t\t\tthrow new TypeError(`State \"${key}\" previously created by different value manager.`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.add(key, nodeFactory);\n\t\t\t}\n\t\t}\n\t\treturn this as PresenceStates<TSchema & TSchemaAdditional>;\n\t}\n\n\tpublic processUpdate(\n\t\treceived: number,\n\t\ttimeModifier: number,\n\t\tremoteDatastore: ValueUpdateRecord,\n\t): void {\n\t\tfor (const [key, remoteAllKnownState] of Object.entries(remoteDatastore)) {\n\t\t\tif (key in this.nodes) {\n\t\t\t\tconst node = unbrandIVM(this.nodes[key]);\n\t\t\t\tfor (const [clientSessionId, value] of brandedObjectEntries(remoteAllKnownState)) {\n\t\t\t\t\tconst client = this.runtime.lookupClient(clientSessionId);\n\t\t\t\t\tnode.update(client, received, value);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Assume all broadcast state is meant to be kept even if not currently registered.\n\t\t\t\tmergeUntrackedDatastore(key, remoteAllKnownState, this.datastore, timeModifier);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Create a new PresenceStates using the DataStoreRuntime provided.\n * @param initialContent - The initial value managers to register.\n */\nexport function createPresenceStates<TSchema extends PresenceStatesSchema>(\n\truntime: PresenceRuntime,\n\tdatastore: ValueElementMap<PresenceStatesSchema>,\n\tinitialContent: TSchema,\n\tcontrols: BroadcastControlSettings | undefined,\n): { public: PresenceStates<TSchema>; internal: PresenceStatesInternal } {\n\tconst impl = new PresenceStatesImpl<TSchema>(runtime, datastore, initialContent, controls);\n\n\treturn {\n\t\tpublic: impl,\n\t\tinternal: impl,\n\t};\n}\n"]}
1
+ {"version":3,"file":"presenceStates.js","sourceRoot":"","sources":["../src/presenceStates.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { RequiredBroadcastControl } from \"./broadcastControls.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type { ClientRecord } from \"./internalTypes.js\";\nimport { brandedObjectEntries } from \"./internalTypes.js\";\nimport type { ClientSessionId, ISessionClient } from \"./presence.js\";\nimport type { LocalStateUpdateOptions, StateDatastore } from \"./stateDatastore.js\";\nimport { handleFromDatastore } from \"./stateDatastore.js\";\nimport type { PresenceStates, PresenceStatesSchema } from \"./types.js\";\nimport { unbrandIVM } from \"./valueManager.js\";\n\n/**\n * Extracts `Part` from {@link InternalTypes.ManagerFactory} return type\n * matching the {@link PresenceStatesSchema} `Keys` given.\n *\n * @remarks\n * If the `Part` is an optional property, undefined will be included in the\n * result. Applying `Required` to the return type prior to extracting `Part`\n * does not work as expected. Use Exclude\\<, undefined\\> can be used as needed.\n *\n * @internal\n */\nexport type MapSchemaElement<\n\tTSchema extends PresenceStatesSchema,\n\tPart extends keyof ReturnType<TSchema[keyof TSchema]>,\n\tKeys extends keyof TSchema = keyof TSchema,\n> = ReturnType<TSchema[Keys]>[Part];\n\n/**\n * @internal\n */\nexport interface RuntimeLocalUpdateOptions {\n\tallowableUpdateLatencyMs: number;\n\n\t/**\n\t * Special option allowed for unicast notifications.\n\t */\n\ttargetClientId?: ClientConnectionId;\n}\n\n/**\n * @internal\n */\nexport interface PresenceRuntime {\n\treadonly clientSessionId: ClientSessionId;\n\tlookupClient(clientId: ClientConnectionId): ISessionClient;\n\tlocalUpdate(\n\t\tstates: { [key: string]: ClientUpdateEntry },\n\t\toptions: RuntimeLocalUpdateOptions,\n\t): void;\n}\n\ntype PresenceSubSchemaFromWorkspaceSchema<\n\tTSchema extends PresenceStatesSchema,\n\tPart extends keyof ReturnType<TSchema[keyof TSchema]>,\n> = {\n\t[Key in keyof TSchema]: MapSchemaElement<TSchema, Part, Key>;\n};\n\ntype MapEntries<TSchema extends PresenceStatesSchema> = PresenceSubSchemaFromWorkspaceSchema<\n\tTSchema,\n\t\"manager\"\n>;\n\n/**\n * ValueElementMap is a map of key to a map of clientId to ValueState.\n * It is not restricted to the schema of the map as it may receive updates from other clients\n * with managers that have not been registered locally. Each map node is responsible for keeping\n * all session's state to be able to pick arbitrary client to rebroadcast to others.\n *\n * This generic aspect makes some typing difficult. The loose typing is not broadcast to the\n * consumers that are expected to maintain their schema over multiple versions of clients.\n *\n * @internal\n */\nexport interface ValueElementMap<_TSchema extends PresenceStatesSchema> {\n\t[key: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<unknown>>;\n}\n\n// An attempt to make the type more precise, but it is not working.\n// If the casting in support code is too much we could keep two references to the same\n// complete datastore, but with the respective types desired.\n// type ValueElementMap<TSchema extends PresenceStatesNodeSchema> =\n// \t| {\n// \t\t\t[Key in keyof TSchema & string]?: {\n// \t\t\t\t[ClientSessionId: ClientSessionId]: InternalTypes.ValueDirectoryOrState<MapSchemaElement<TSchema,\"value\",Key>>;\n// \t\t\t};\n// \t }\n// \t| {\n// \t\t\t[key: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<unknown>>;\n// \t };\n// interface ValueElementMap<TValue> {\n// \t[Id: string]: ClientRecord<InternalTypes.ValueDirectoryOrState<TValue>>;\n// \t// Version with local packed in is convenient for map, but not for join broadcast to serialize simply.\n// \t// [Id: string]: {\n// \t// \tlocal: InternalTypes.ValueDirectoryOrState<TValue>;\n// \t// \tall: ClientRecord<InternalTypes.ValueDirectoryOrState<TValue>>;\n// \t// };\n// }\n\n/**\n * @internal\n */\nexport type ClientUpdateEntry = InternalTypes.ValueDirectoryOrState<unknown> & {\n\tignoreUnmonitored?: true;\n};\n\ntype ClientUpdateRecord = ClientRecord<ClientUpdateEntry>;\n\ninterface ValueUpdateRecord {\n\t[valueKey: string]: ClientUpdateRecord;\n}\n\n/**\n * @internal\n */\nexport interface PresenceStatesInternal {\n\tensureContent<TSchemaAdditional extends PresenceStatesSchema>(\n\t\tcontent: TSchemaAdditional,\n\t\tcontrols: BroadcastControlSettings | undefined,\n\t): PresenceStates<TSchemaAdditional>;\n\tprocessUpdate(\n\t\treceived: number,\n\t\ttimeModifier: number,\n\t\tremoteDatastore: ValueUpdateRecord,\n\t\tsenderConnectionId: ClientConnectionId,\n\t): void;\n}\n\nfunction isValueDirectory<\n\tT,\n\tTValueState extends\n\t\t| InternalTypes.ValueRequiredState<T>\n\t\t| InternalTypes.ValueOptionalState<T>,\n>(\n\tvalue: InternalTypes.ValueDirectory<T> | TValueState,\n): value is InternalTypes.ValueDirectory<T> {\n\treturn \"items\" in value;\n}\n\n/**\n * Merge a value directory.\n *\n * @internal\n */\nexport function mergeValueDirectory<\n\tT,\n\tTValueState extends\n\t\t| InternalTypes.ValueRequiredState<T>\n\t\t| InternalTypes.ValueOptionalState<T>,\n>(\n\tbase: TValueState | InternalTypes.ValueDirectory<T> | undefined,\n\tupdate: TValueState | InternalTypes.ValueDirectory<T>,\n\ttimeDelta: number,\n): TValueState | InternalTypes.ValueDirectory<T> {\n\tif (!isValueDirectory(update)) {\n\t\tif (base === undefined || update.rev > base.rev) {\n\t\t\treturn { ...update, timestamp: update.timestamp + timeDelta };\n\t\t}\n\t\treturn base;\n\t}\n\n\tlet mergeBase: InternalTypes.ValueDirectory<T>;\n\tif (base === undefined) {\n\t\tmergeBase = { rev: update.rev, items: {} };\n\t} else {\n\t\tconst baseIsDirectory = isValueDirectory(base);\n\t\tif (base.rev >= update.rev) {\n\t\t\tif (!baseIsDirectory) {\n\t\t\t\t// base is leaf value that is more recent - nothing to do\n\t\t\t\treturn base;\n\t\t\t}\n\t\t\t// While base has more advanced revision, assume mis-ordering or\n\t\t\t// missed and catchup update needs merged in.\n\t\t\tmergeBase = base;\n\t\t} else {\n\t\t\tmergeBase = { rev: update.rev, items: baseIsDirectory ? base.items : {} };\n\t\t}\n\t}\n\tfor (const [key, value] of Object.entries(update.items)) {\n\t\tconst baseElement = mergeBase.items[key];\n\t\tmergeBase.items[key] = mergeValueDirectory(baseElement, value, timeDelta);\n\t}\n\treturn mergeBase;\n}\n\n/**\n * Updates remote state into the local [untracked] datastore.\n *\n * @param key - The key of the datastore to merge the untracked data into.\n * @param remoteAllKnownState - The remote state to merge into the datastore.\n * @param datastore - The datastore to merge the untracked data into.\n *\n * @remarks\n * In the case of ignored unmonitored data, the client entries are not stored,\n * though the value keys will be populated and often remain empty.\n *\n * @internal\n */\nexport function mergeUntrackedDatastore(\n\tkey: string,\n\tremoteAllKnownState: ClientUpdateRecord,\n\tdatastore: ValueElementMap<PresenceStatesSchema>,\n\ttimeModifier: number,\n): void {\n\tif (!(key in datastore)) {\n\t\tdatastore[key] = {};\n\t}\n\tconst localAllKnownState = datastore[key];\n\tfor (const [clientSessionId, value] of brandedObjectEntries(remoteAllKnownState)) {\n\t\tif (!(\"ignoreUnmonitored\" in value)) {\n\t\t\tlocalAllKnownState[clientSessionId] = mergeValueDirectory(\n\t\t\t\tlocalAllKnownState[clientSessionId],\n\t\t\t\tvalue,\n\t\t\t\ttimeModifier,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * The default allowable update latency for PresenceStates workspaces in milliseconds.\n */\nconst defaultAllowableUpdateLatencyMs = 60;\n\n/**\n * Produces the value type of a schema element or set of elements.\n */\ntype SchemaElementValueType<\n\tTSchema extends PresenceStatesSchema,\n\tKeys extends keyof TSchema & string,\n> = Exclude<MapSchemaElement<TSchema, \"initialData\", Keys>, undefined>[\"value\"];\n\nclass PresenceStatesImpl<TSchema extends PresenceStatesSchema>\n\timplements\n\t\tPresenceStatesInternal,\n\t\tPresenceStates<TSchema>,\n\t\tStateDatastore<\n\t\t\tkeyof TSchema & string,\n\t\t\tSchemaElementValueType<TSchema, keyof TSchema & string>\n\t\t>\n{\n\tprivate readonly nodes: MapEntries<TSchema>;\n\tpublic readonly props: PresenceStates<TSchema>[\"props\"];\n\n\tpublic readonly controls: RequiredBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly runtime: PresenceRuntime,\n\t\tprivate readonly datastore: ValueElementMap<TSchema>,\n\t\tinitialContent: TSchema,\n\t\tcontrolsSettings: BroadcastControlSettings | undefined,\n\t) {\n\t\tthis.controls = new RequiredBroadcastControl(defaultAllowableUpdateLatencyMs);\n\t\tif (controlsSettings?.allowableUpdateLatencyMs !== undefined) {\n\t\t\tthis.controls.allowableUpdateLatencyMs = controlsSettings.allowableUpdateLatencyMs;\n\t\t}\n\n\t\t// Prepare initial map content from initial state\n\t\t{\n\t\t\tconst clientSessionId = this.runtime.clientSessionId;\n\t\t\tlet anyInitialValues = false;\n\t\t\tlet cumulativeAllowableUpdateLatencyMs: number | undefined;\n\t\t\t// eslint-disable-next-line unicorn/no-array-reduce\n\t\t\tconst initial = Object.entries(initialContent).reduce(\n\t\t\t\t(acc, [key, nodeFactory]) => {\n\t\t\t\t\tconst newNodeData = nodeFactory(key, handleFromDatastore(this));\n\t\t\t\t\tacc.nodes[key as keyof TSchema] = newNodeData.manager;\n\t\t\t\t\tif (\"initialData\" in newNodeData) {\n\t\t\t\t\t\tconst { value, allowableUpdateLatencyMs } = newNodeData.initialData;\n\t\t\t\t\t\tacc.datastore[key] = acc.datastore[key] ?? {};\n\t\t\t\t\t\tacc.datastore[key][clientSessionId] = value;\n\t\t\t\t\t\tacc.newValues[key] = value;\n\t\t\t\t\t\tif (allowableUpdateLatencyMs !== undefined) {\n\t\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs =\n\t\t\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs === undefined\n\t\t\t\t\t\t\t\t\t? allowableUpdateLatencyMs\n\t\t\t\t\t\t\t\t\t: Math.min(cumulativeAllowableUpdateLatencyMs, allowableUpdateLatencyMs);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tanyInitialValues = true;\n\t\t\t\t\t}\n\t\t\t\t\treturn acc;\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\t\t\tnodes: {} as MapEntries<TSchema>,\n\t\t\t\t\tdatastore,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\t\t\tnewValues: {} as { [key: string]: InternalTypes.ValueDirectoryOrState<unknown> },\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.nodes = initial.nodes;\n\t\t\t// props is the public view of nodes that limits the entries types to\n\t\t\t// the public interface of the value manager with an additional type\n\t\t\t// filter that beguiles the type system. So just reinterpret cast.\n\t\t\tthis.props = this.nodes as unknown as PresenceStates<TSchema>[\"props\"];\n\n\t\t\tif (anyInitialValues) {\n\t\t\t\tthis.runtime.localUpdate(initial.newValues, {\n\t\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic knownValues<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t): {\n\t\tself: ClientSessionId | undefined;\n\t\tstates: ClientRecord<SchemaElementValueType<TSchema, Key>>;\n\t} {\n\t\treturn {\n\t\t\tself: this.runtime.clientSessionId,\n\t\t\tstates: this.datastore[key],\n\t\t};\n\t}\n\n\tpublic localUpdate<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t\tvalue: SchemaElementValueType<TSchema, Key> & ClientUpdateEntry,\n\t\toptions: LocalStateUpdateOptions,\n\t): void {\n\t\tthis.runtime.localUpdate(\n\t\t\t{ [key]: value },\n\t\t\t{\n\t\t\t\t...options,\n\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\toptions.allowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic update<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t\tclientId: ClientSessionId,\n\t\tvalue: Exclude<MapSchemaElement<TSchema, \"initialData\", Key>, undefined>[\"value\"],\n\t): void {\n\t\tconst allKnownState = this.datastore[key];\n\t\tallKnownState[clientId] = mergeValueDirectory(allKnownState[clientId], value, 0);\n\t}\n\n\tpublic lookupClient(clientId: ClientConnectionId): ISessionClient {\n\t\treturn this.runtime.lookupClient(clientId);\n\t}\n\n\tpublic add<\n\t\tTKey extends string,\n\t\tTValue extends InternalTypes.ValueDirectoryOrState<unknown>,\n\t\tTValueManager,\n\t>(\n\t\tkey: TKey,\n\t\tnodeFactory: InternalTypes.ManagerFactory<TKey, TValue, TValueManager>,\n\t): asserts this is PresenceStates<\n\t\tTSchema & Record<TKey, InternalTypes.ManagerFactory<TKey, TValue, TValueManager>>\n\t> {\n\t\tassert(!(key in this.nodes), 0xa3c /* Already have entry for key in map */);\n\t\tconst nodeData = nodeFactory(key, handleFromDatastore(this));\n\t\tthis.nodes[key] = nodeData.manager;\n\t\tif (\"initialData\" in nodeData) {\n\t\t\tconst { value, allowableUpdateLatencyMs } = nodeData.initialData;\n\t\t\tif (key in this.datastore) {\n\t\t\t\t// Already have received state from other clients. Kept in `all`.\n\t\t\t\t// TODO: Send current `all` state to state manager.\n\t\t\t} else {\n\t\t\t\tthis.datastore[key] = {};\n\t\t\t}\n\t\t\tthis.datastore[key][this.runtime.clientSessionId] = value;\n\t\t\tthis.runtime.localUpdate(\n\t\t\t\t{ [key]: value },\n\t\t\t\t{\n\t\t\t\t\tallowableUpdateLatencyMs:\n\t\t\t\t\t\tallowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic ensureContent<TSchemaAdditional extends PresenceStatesSchema>(\n\t\tcontent: TSchemaAdditional,\n\t\tcontrols: BroadcastControlSettings | undefined,\n\t): PresenceStates<TSchema & TSchemaAdditional> {\n\t\tif (controls?.allowableUpdateLatencyMs !== undefined) {\n\t\t\tthis.controls.allowableUpdateLatencyMs = controls.allowableUpdateLatencyMs;\n\t\t}\n\t\tfor (const [key, nodeFactory] of Object.entries(content)) {\n\t\t\tif (key in this.nodes) {\n\t\t\t\tconst node = unbrandIVM(this.nodes[key]);\n\t\t\t\tif (!(node instanceof nodeFactory.instanceBase)) {\n\t\t\t\t\tthrow new TypeError(`State \"${key}\" previously created by different value manager.`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.add(key, nodeFactory);\n\t\t\t}\n\t\t}\n\t\treturn this as PresenceStates<TSchema & TSchemaAdditional>;\n\t}\n\n\tpublic processUpdate(\n\t\treceived: number,\n\t\ttimeModifier: number,\n\t\tremoteDatastore: ValueUpdateRecord,\n\t): void {\n\t\tfor (const [key, remoteAllKnownState] of Object.entries(remoteDatastore)) {\n\t\t\tif (key in this.nodes) {\n\t\t\t\tconst node = unbrandIVM(this.nodes[key]);\n\t\t\t\tfor (const [clientSessionId, value] of brandedObjectEntries(remoteAllKnownState)) {\n\t\t\t\t\tconst client = this.runtime.lookupClient(clientSessionId);\n\t\t\t\t\tnode.update(client, received, value);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Assume all broadcast state is meant to be kept even if not currently registered.\n\t\t\t\tmergeUntrackedDatastore(key, remoteAllKnownState, this.datastore, timeModifier);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Create a new PresenceStates using the DataStoreRuntime provided.\n * @param initialContent - The initial value managers to register.\n */\nexport function createPresenceStates<TSchema extends PresenceStatesSchema>(\n\truntime: PresenceRuntime,\n\tdatastore: ValueElementMap<PresenceStatesSchema>,\n\tinitialContent: TSchema,\n\tcontrols: BroadcastControlSettings | undefined,\n): { public: PresenceStates<TSchema>; internal: PresenceStatesInternal } {\n\tconst impl = new PresenceStatesImpl<TSchema>(runtime, datastore, initialContent, controls);\n\n\treturn {\n\t\tpublic: impl,\n\t\tinternal: impl,\n\t};\n}\n"]}
@@ -3,12 +3,12 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import type { IAudience } from "@fluidframework/container-definitions";
6
+ import type { IEmitter } from "@fluidframework/core-interfaces/internal";
6
7
  import type { ClientConnectionId } from "./baseTypes.js";
7
8
  import type { InternalTypes } from "./exposedInternalTypes.js";
8
9
  import type { ClientSessionId, IPresence, PresenceEvents } from "./presence.js";
9
10
  import type { PresenceStatesInternal } from "./presenceStates.js";
10
11
  import type { PresenceStates, PresenceStatesSchema } from "./types.js";
11
- import type { IEmitter } from "@fluidframework/presence/internal/events";
12
12
  /**
13
13
  * The system workspace's datastore structure.
14
14
  *
@@ -1 +1 @@
1
- {"version":3,"file":"systemWorkspace.d.ts","sourceRoot":"","sources":["../src/systemWorkspace.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AAGvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EACX,eAAe,EACf,SAAS,EAET,cAAc,EACd,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AAEzE;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACxC,iBAAiB,EAAE;QAClB,CAAC,YAAY,EAAE,kBAAkB,GAAG,aAAa,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;KACtF,CAAC;CACF;AA0CD;;GAEG;AACH,MAAM,WAAW,eAGhB,SAAQ,IAAI,CAAC,SAAS,EAAE,cAAc,GAAG,aAAa,GAAG,WAAW,CAAC;IACrE;;;;OAIG;IACH,iBAAiB,CAAC,kBAAkB,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAEhE;;;;OAIG;IACH,wBAAwB,CAAC,kBAAkB,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACvE;AA6KD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACpC,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,wBAAwB,EACnC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC,EACxD,QAAQ,EAAE,SAAS,GACjB;IACF,SAAS,EAAE,eAAe,CAAC;IAC3B,WAAW,EAAE;QACZ,QAAQ,EAAE,sBAAsB,CAAC;QACjC,MAAM,EAAE,cAAc,CAAC,oBAAoB,CAAC,CAAC;KAC7C,CAAC;CACF,CASA"}
1
+ {"version":3,"file":"systemWorkspace.d.ts","sourceRoot":"","sources":["../src/systemWorkspace.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AAGzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EACX,eAAe,EACf,SAAS,EAET,cAAc,EACd,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvE;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACxC,iBAAiB,EAAE;QAClB,CAAC,YAAY,EAAE,kBAAkB,GAAG,aAAa,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;KACtF,CAAC;CACF;AA0CD;;GAEG;AACH,MAAM,WAAW,eAGhB,SAAQ,IAAI,CAAC,SAAS,EAAE,cAAc,GAAG,aAAa,GAAG,WAAW,CAAC;IACrE;;;;OAIG;IACH,iBAAiB,CAAC,kBAAkB,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAEhE;;;;OAIG;IACH,wBAAwB,CAAC,kBAAkB,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACvE;AA6KD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACpC,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,wBAAwB,EACnC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC,EACxD,QAAQ,EAAE,SAAS,GACjB;IACF,SAAS,EAAE,eAAe,CAAC;IAC3B,WAAW,EAAE;QACZ,QAAQ,EAAE,sBAAsB,CAAC;QACjC,MAAM,EAAE,cAAc,CAAC,oBAAoB,CAAC,CAAC;KAC7C,CAAC;CACF,CASA"}
@@ -1 +1 @@
1
- {"version":3,"file":"systemWorkspace.js","sourceRoot":"","sources":["../src/systemWorkspace.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IAudience } from \"@fluidframework/container-definitions\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type {\n\tClientSessionId,\n\tIPresence,\n\tISessionClient,\n\tPresenceEvents,\n} from \"./presence.js\";\nimport { SessionClientStatus } from \"./presence.js\";\nimport type { PresenceStatesInternal } from \"./presenceStates.js\";\nimport type { PresenceStates, PresenceStatesSchema } from \"./types.js\";\n\nimport type { IEmitter } from \"@fluidframework/presence/internal/events\";\n\n/**\n * The system workspace's datastore structure.\n *\n * @internal\n */\nexport interface SystemWorkspaceDatastore {\n\tclientToSessionId: {\n\t\t[ConnectionId: ClientConnectionId]: InternalTypes.ValueRequiredState<ClientSessionId>;\n\t};\n}\n\nclass SessionClient implements ISessionClient {\n\t/**\n\t * Order is used to track the most recent client connection\n\t * during a session.\n\t */\n\tpublic order: number = 0;\n\n\tprivate connectionStatus: SessionClientStatus;\n\n\tpublic constructor(\n\t\tpublic readonly sessionId: ClientSessionId,\n\t\tprivate connectionId: ClientConnectionId | undefined = undefined,\n\t) {\n\t\tthis.connectionStatus =\n\t\t\tconnectionId === undefined\n\t\t\t\t? SessionClientStatus.Disconnected\n\t\t\t\t: SessionClientStatus.Connected;\n\t}\n\n\tpublic getConnectionId(): ClientConnectionId {\n\t\tif (this.connectionId === undefined) {\n\t\t\tthrow new Error(\"Client has never been connected\");\n\t\t}\n\t\treturn this.connectionId;\n\t}\n\n\tpublic getConnectionStatus(): SessionClientStatus {\n\t\treturn this.connectionStatus;\n\t}\n\n\tpublic setConnectionId(connectionId: ClientConnectionId): void {\n\t\tthis.connectionId = connectionId;\n\t\tthis.connectionStatus = SessionClientStatus.Connected;\n\t}\n\n\tpublic setDisconnected(): void {\n\t\tthis.connectionStatus = SessionClientStatus.Disconnected;\n\t}\n}\n\n/**\n * @internal\n */\nexport interface SystemWorkspace\n\t// Portion of IPresence that is handled by SystemWorkspace along with\n\t// responsiblity for emitting \"attendeeJoined\" events.\n\textends Pick<IPresence, \"getAttendees\" | \"getAttendee\" | \"getMyself\"> {\n\t/**\n\t * Must be called when the current client acquires a new connection.\n\t *\n\t * @param clientConnectionId - The new client connection ID.\n\t */\n\tonConnectionAdded(clientConnectionId: ClientConnectionId): void;\n\n\t/**\n\t * Removes the client connection ID from the system workspace.\n\t *\n\t * @param clientConnectionId - The client connection ID to remove.\n\t */\n\tremoveClientConnectionId(clientConnectionId: ClientConnectionId): void;\n}\n\nclass SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace {\n\tprivate readonly selfAttendee: SessionClient;\n\t/**\n\t * `attendees` is this client's understanding of the attendees in the\n\t * session. The map covers entries for both session ids and connection\n\t * ids, which are never expected to collide, but if they did for same\n\t * client that would be fine.\n\t * An entry is for session ID if the value's `sessionId` matches the key.\n\t */\n\tprivate readonly attendees = new Map<ClientConnectionId | ClientSessionId, SessionClient>();\n\n\tpublic constructor(\n\t\tclientSessionId: ClientSessionId,\n\t\tprivate readonly datastore: SystemWorkspaceDatastore,\n\t\tprivate readonly events: IEmitter<\n\t\t\tPick<PresenceEvents, \"attendeeJoined\" | \"attendeeDisconnected\">\n\t\t>,\n\t\tprivate readonly audience: IAudience,\n\t) {\n\t\tthis.selfAttendee = new SessionClient(clientSessionId);\n\t\tthis.attendees.set(clientSessionId, this.selfAttendee);\n\t}\n\n\tpublic ensureContent<TSchemaAdditional extends PresenceStatesSchema>(\n\t\t_content: TSchemaAdditional,\n\t): never {\n\t\tthrow new Error(\"Method not implemented.\");\n\t}\n\n\tpublic processUpdate(\n\t\t_received: number,\n\t\t_timeModifier: number,\n\t\tremoteDatastore: {\n\t\t\tclientToSessionId: {\n\t\t\t\t[\n\t\t\t\t\tConnectionId: ClientConnectionId\n\t\t\t\t]: InternalTypes.ValueRequiredState<ClientSessionId> & {\n\t\t\t\t\tignoreUnmonitored?: true;\n\t\t\t\t};\n\t\t\t};\n\t\t},\n\t\tsenderConnectionId: ClientConnectionId,\n\t): void {\n\t\tconst postUpdateActions: (() => void)[] = [];\n\t\tconst audienceMembers = this.audience.getMembers();\n\t\tconst connectedAttendees = new Set<SessionClient>();\n\t\tfor (const [clientConnectionId, value] of Object.entries(\n\t\t\tremoteDatastore.clientToSessionId,\n\t\t)) {\n\t\t\tconst clientSessionId = value.value;\n\t\t\tconst { attendee, isNew } = this.ensureAttendee(\n\t\t\t\tclientSessionId,\n\t\t\t\tclientConnectionId,\n\t\t\t\t/* order */ value.rev,\n\t\t\t);\n\n\t\t\t// Check new attendee against audience to see if they're currently connected\n\t\t\tconst isAttendeeConnected = audienceMembers.has(clientConnectionId);\n\n\t\t\tif (isAttendeeConnected) {\n\t\t\t\tconnectedAttendees.add(attendee);\n\t\t\t\tif (attendee.getConnectionStatus() === SessionClientStatus.Disconnected) {\n\t\t\t\t\tattendee.setConnectionId(clientConnectionId);\n\t\t\t\t}\n\t\t\t\tif (isNew) {\n\t\t\t\t\t// If the attendee is both new and in audience (i.e. currently connected), emit an attendeeJoined event.\n\t\t\t\t\tpostUpdateActions.push(() => this.events.emit(\"attendeeJoined\", attendee));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If the attendee is not in the audience, they are considered disconnected.\n\t\t\tif (!connectedAttendees.has(attendee)) {\n\t\t\t\tattendee.setDisconnected();\n\t\t\t}\n\n\t\t\tconst knownSessionId: InternalTypes.ValueRequiredState<ClientSessionId> | undefined =\n\t\t\t\tthis.datastore.clientToSessionId[clientConnectionId];\n\t\t\tif (knownSessionId === undefined) {\n\t\t\t\tthis.datastore.clientToSessionId[clientConnectionId] = value;\n\t\t\t} else {\n\t\t\t\tassert(knownSessionId.value === value.value, 0xa5a /* Mismatched SessionId */);\n\t\t\t}\n\t\t}\n\n\t\t// TODO: reorganize processUpdate and caller to process actions after all updates are processed.\n\t\tfor (const action of postUpdateActions) {\n\t\t\taction();\n\t\t}\n\t}\n\n\tpublic onConnectionAdded(clientConnectionId: ClientConnectionId): void {\n\t\tthis.datastore.clientToSessionId[clientConnectionId] = {\n\t\t\trev: this.selfAttendee.order++,\n\t\t\ttimestamp: Date.now(),\n\t\t\tvalue: this.selfAttendee.sessionId,\n\t\t};\n\n\t\tthis.selfAttendee.setConnectionId(clientConnectionId);\n\t\tthis.attendees.set(clientConnectionId, this.selfAttendee);\n\t}\n\n\tpublic removeClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\tconst attendee = this.attendees.get(clientConnectionId);\n\t\tif (!attendee) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If the last known connectionID is different from the connection ID being removed, the attendee has reconnected,\n\t\t// therefore we should not change the attendee connection status or emit a disconnect event.\n\t\tconst attendeeReconnected = attendee.getConnectionId() !== clientConnectionId;\n\t\tconst connected = attendee.getConnectionStatus() === SessionClientStatus.Connected;\n\t\tif (!attendeeReconnected && connected) {\n\t\t\tattendee.setDisconnected();\n\t\t\tthis.events.emit(\"attendeeDisconnected\", attendee);\n\t\t}\n\t}\n\n\tpublic getAttendees(): ReadonlySet<ISessionClient> {\n\t\treturn new Set(this.attendees.values());\n\t}\n\n\tpublic getAttendee(clientId: ClientConnectionId | ClientSessionId): ISessionClient {\n\t\tconst attendee = this.attendees.get(clientId);\n\t\tif (attendee) {\n\t\t\treturn attendee;\n\t\t}\n\n\t\t// TODO: Restore option to add attendee on demand to handle internal\n\t\t// lookup cases that must come from internal data.\n\t\t// There aren't any resiliency mechanisms in place to handle a missed\n\t\t// ClientJoin right now.\n\t\tthrow new Error(\"Attendee not found\");\n\t}\n\n\tpublic getMyself(): ISessionClient {\n\t\treturn this.selfAttendee;\n\t}\n\n\t/**\n\t * Make sure the given client session and connection ID pair are represented\n\t * in the attendee map. If not present, SessionClient is created and added\n\t * to map. If present, make sure the current connection ID is updated.\n\t */\n\tprivate ensureAttendee(\n\t\tclientSessionId: ClientSessionId,\n\t\tclientConnectionId: ClientConnectionId,\n\t\torder: number,\n\t): { attendee: SessionClient; isNew: boolean } {\n\t\tlet attendee = this.attendees.get(clientSessionId);\n\t\tlet isNew = false;\n\n\t\tif (attendee === undefined) {\n\t\t\t// New attendee. Create SessionClient and add session ID based\n\t\t\t// entry to map.\n\t\t\tattendee = new SessionClient(clientSessionId, clientConnectionId);\n\t\t\tthis.attendees.set(clientSessionId, attendee);\n\t\t\tisNew = true;\n\t\t} else if (order > attendee.order) {\n\t\t\t// The given association is newer than the one we have.\n\t\t\t// Update the order and current connection ID.\n\t\t\tattendee.order = order;\n\t\t\tattendee.setConnectionId(clientConnectionId);\n\t\t\tisNew = true;\n\t\t}\n\t\t// Always update entry for the connection ID. (Okay if already set.)\n\t\tthis.attendees.set(clientConnectionId, attendee);\n\n\t\treturn { attendee, isNew };\n\t}\n}\n\n/**\n * Instantiates the system workspace.\n *\n * @internal\n */\nexport function createSystemWorkspace(\n\tclientSessionId: ClientSessionId,\n\tdatastore: SystemWorkspaceDatastore,\n\tevents: IEmitter<Pick<PresenceEvents, \"attendeeJoined\">>,\n\taudience: IAudience,\n): {\n\tworkspace: SystemWorkspace;\n\tstatesEntry: {\n\t\tinternal: PresenceStatesInternal;\n\t\tpublic: PresenceStates<PresenceStatesSchema>;\n\t};\n} {\n\tconst workspace = new SystemWorkspaceImpl(clientSessionId, datastore, events, audience);\n\treturn {\n\t\tworkspace,\n\t\tstatesEntry: {\n\t\t\tinternal: workspace,\n\t\t\tpublic: undefined as unknown as PresenceStates<PresenceStatesSchema>,\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"systemWorkspace.js","sourceRoot":"","sources":["../src/systemWorkspace.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IAudience } from \"@fluidframework/container-definitions\";\nimport type { IEmitter } from \"@fluidframework/core-interfaces/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type {\n\tClientSessionId,\n\tIPresence,\n\tISessionClient,\n\tPresenceEvents,\n} from \"./presence.js\";\nimport { SessionClientStatus } from \"./presence.js\";\nimport type { PresenceStatesInternal } from \"./presenceStates.js\";\nimport type { PresenceStates, PresenceStatesSchema } from \"./types.js\";\n\n/**\n * The system workspace's datastore structure.\n *\n * @internal\n */\nexport interface SystemWorkspaceDatastore {\n\tclientToSessionId: {\n\t\t[ConnectionId: ClientConnectionId]: InternalTypes.ValueRequiredState<ClientSessionId>;\n\t};\n}\n\nclass SessionClient implements ISessionClient {\n\t/**\n\t * Order is used to track the most recent client connection\n\t * during a session.\n\t */\n\tpublic order: number = 0;\n\n\tprivate connectionStatus: SessionClientStatus;\n\n\tpublic constructor(\n\t\tpublic readonly sessionId: ClientSessionId,\n\t\tprivate connectionId: ClientConnectionId | undefined = undefined,\n\t) {\n\t\tthis.connectionStatus =\n\t\t\tconnectionId === undefined\n\t\t\t\t? SessionClientStatus.Disconnected\n\t\t\t\t: SessionClientStatus.Connected;\n\t}\n\n\tpublic getConnectionId(): ClientConnectionId {\n\t\tif (this.connectionId === undefined) {\n\t\t\tthrow new Error(\"Client has never been connected\");\n\t\t}\n\t\treturn this.connectionId;\n\t}\n\n\tpublic getConnectionStatus(): SessionClientStatus {\n\t\treturn this.connectionStatus;\n\t}\n\n\tpublic setConnectionId(connectionId: ClientConnectionId): void {\n\t\tthis.connectionId = connectionId;\n\t\tthis.connectionStatus = SessionClientStatus.Connected;\n\t}\n\n\tpublic setDisconnected(): void {\n\t\tthis.connectionStatus = SessionClientStatus.Disconnected;\n\t}\n}\n\n/**\n * @internal\n */\nexport interface SystemWorkspace\n\t// Portion of IPresence that is handled by SystemWorkspace along with\n\t// responsiblity for emitting \"attendeeJoined\" events.\n\textends Pick<IPresence, \"getAttendees\" | \"getAttendee\" | \"getMyself\"> {\n\t/**\n\t * Must be called when the current client acquires a new connection.\n\t *\n\t * @param clientConnectionId - The new client connection ID.\n\t */\n\tonConnectionAdded(clientConnectionId: ClientConnectionId): void;\n\n\t/**\n\t * Removes the client connection ID from the system workspace.\n\t *\n\t * @param clientConnectionId - The client connection ID to remove.\n\t */\n\tremoveClientConnectionId(clientConnectionId: ClientConnectionId): void;\n}\n\nclass SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace {\n\tprivate readonly selfAttendee: SessionClient;\n\t/**\n\t * `attendees` is this client's understanding of the attendees in the\n\t * session. The map covers entries for both session ids and connection\n\t * ids, which are never expected to collide, but if they did for same\n\t * client that would be fine.\n\t * An entry is for session ID if the value's `sessionId` matches the key.\n\t */\n\tprivate readonly attendees = new Map<ClientConnectionId | ClientSessionId, SessionClient>();\n\n\tpublic constructor(\n\t\tclientSessionId: ClientSessionId,\n\t\tprivate readonly datastore: SystemWorkspaceDatastore,\n\t\tprivate readonly events: IEmitter<\n\t\t\tPick<PresenceEvents, \"attendeeJoined\" | \"attendeeDisconnected\">\n\t\t>,\n\t\tprivate readonly audience: IAudience,\n\t) {\n\t\tthis.selfAttendee = new SessionClient(clientSessionId);\n\t\tthis.attendees.set(clientSessionId, this.selfAttendee);\n\t}\n\n\tpublic ensureContent<TSchemaAdditional extends PresenceStatesSchema>(\n\t\t_content: TSchemaAdditional,\n\t): never {\n\t\tthrow new Error(\"Method not implemented.\");\n\t}\n\n\tpublic processUpdate(\n\t\t_received: number,\n\t\t_timeModifier: number,\n\t\tremoteDatastore: {\n\t\t\tclientToSessionId: {\n\t\t\t\t[\n\t\t\t\t\tConnectionId: ClientConnectionId\n\t\t\t\t]: InternalTypes.ValueRequiredState<ClientSessionId> & {\n\t\t\t\t\tignoreUnmonitored?: true;\n\t\t\t\t};\n\t\t\t};\n\t\t},\n\t\tsenderConnectionId: ClientConnectionId,\n\t): void {\n\t\tconst postUpdateActions: (() => void)[] = [];\n\t\tconst audienceMembers = this.audience.getMembers();\n\t\tconst connectedAttendees = new Set<SessionClient>();\n\t\tfor (const [clientConnectionId, value] of Object.entries(\n\t\t\tremoteDatastore.clientToSessionId,\n\t\t)) {\n\t\t\tconst clientSessionId = value.value;\n\t\t\tconst { attendee, isNew } = this.ensureAttendee(\n\t\t\t\tclientSessionId,\n\t\t\t\tclientConnectionId,\n\t\t\t\t/* order */ value.rev,\n\t\t\t);\n\n\t\t\t// Check new attendee against audience to see if they're currently connected\n\t\t\tconst isAttendeeConnected = audienceMembers.has(clientConnectionId);\n\n\t\t\tif (isAttendeeConnected) {\n\t\t\t\tconnectedAttendees.add(attendee);\n\t\t\t\tif (attendee.getConnectionStatus() === SessionClientStatus.Disconnected) {\n\t\t\t\t\tattendee.setConnectionId(clientConnectionId);\n\t\t\t\t}\n\t\t\t\tif (isNew) {\n\t\t\t\t\t// If the attendee is both new and in audience (i.e. currently connected), emit an attendeeJoined event.\n\t\t\t\t\tpostUpdateActions.push(() => this.events.emit(\"attendeeJoined\", attendee));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If the attendee is not in the audience, they are considered disconnected.\n\t\t\tif (!connectedAttendees.has(attendee)) {\n\t\t\t\tattendee.setDisconnected();\n\t\t\t}\n\n\t\t\tconst knownSessionId: InternalTypes.ValueRequiredState<ClientSessionId> | undefined =\n\t\t\t\tthis.datastore.clientToSessionId[clientConnectionId];\n\t\t\tif (knownSessionId === undefined) {\n\t\t\t\tthis.datastore.clientToSessionId[clientConnectionId] = value;\n\t\t\t} else {\n\t\t\t\tassert(knownSessionId.value === value.value, 0xa5a /* Mismatched SessionId */);\n\t\t\t}\n\t\t}\n\n\t\t// TODO: reorganize processUpdate and caller to process actions after all updates are processed.\n\t\tfor (const action of postUpdateActions) {\n\t\t\taction();\n\t\t}\n\t}\n\n\tpublic onConnectionAdded(clientConnectionId: ClientConnectionId): void {\n\t\tthis.datastore.clientToSessionId[clientConnectionId] = {\n\t\t\trev: this.selfAttendee.order++,\n\t\t\ttimestamp: Date.now(),\n\t\t\tvalue: this.selfAttendee.sessionId,\n\t\t};\n\n\t\tthis.selfAttendee.setConnectionId(clientConnectionId);\n\t\tthis.attendees.set(clientConnectionId, this.selfAttendee);\n\t}\n\n\tpublic removeClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\tconst attendee = this.attendees.get(clientConnectionId);\n\t\tif (!attendee) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If the last known connectionID is different from the connection ID being removed, the attendee has reconnected,\n\t\t// therefore we should not change the attendee connection status or emit a disconnect event.\n\t\tconst attendeeReconnected = attendee.getConnectionId() !== clientConnectionId;\n\t\tconst connected = attendee.getConnectionStatus() === SessionClientStatus.Connected;\n\t\tif (!attendeeReconnected && connected) {\n\t\t\tattendee.setDisconnected();\n\t\t\tthis.events.emit(\"attendeeDisconnected\", attendee);\n\t\t}\n\t}\n\n\tpublic getAttendees(): ReadonlySet<ISessionClient> {\n\t\treturn new Set(this.attendees.values());\n\t}\n\n\tpublic getAttendee(clientId: ClientConnectionId | ClientSessionId): ISessionClient {\n\t\tconst attendee = this.attendees.get(clientId);\n\t\tif (attendee) {\n\t\t\treturn attendee;\n\t\t}\n\n\t\t// TODO: Restore option to add attendee on demand to handle internal\n\t\t// lookup cases that must come from internal data.\n\t\t// There aren't any resiliency mechanisms in place to handle a missed\n\t\t// ClientJoin right now.\n\t\tthrow new Error(\"Attendee not found\");\n\t}\n\n\tpublic getMyself(): ISessionClient {\n\t\treturn this.selfAttendee;\n\t}\n\n\t/**\n\t * Make sure the given client session and connection ID pair are represented\n\t * in the attendee map. If not present, SessionClient is created and added\n\t * to map. If present, make sure the current connection ID is updated.\n\t */\n\tprivate ensureAttendee(\n\t\tclientSessionId: ClientSessionId,\n\t\tclientConnectionId: ClientConnectionId,\n\t\torder: number,\n\t): { attendee: SessionClient; isNew: boolean } {\n\t\tlet attendee = this.attendees.get(clientSessionId);\n\t\tlet isNew = false;\n\n\t\tif (attendee === undefined) {\n\t\t\t// New attendee. Create SessionClient and add session ID based\n\t\t\t// entry to map.\n\t\t\tattendee = new SessionClient(clientSessionId, clientConnectionId);\n\t\t\tthis.attendees.set(clientSessionId, attendee);\n\t\t\tisNew = true;\n\t\t} else if (order > attendee.order) {\n\t\t\t// The given association is newer than the one we have.\n\t\t\t// Update the order and current connection ID.\n\t\t\tattendee.order = order;\n\t\t\tattendee.setConnectionId(clientConnectionId);\n\t\t\tisNew = true;\n\t\t}\n\t\t// Always update entry for the connection ID. (Okay if already set.)\n\t\tthis.attendees.set(clientConnectionId, attendee);\n\n\t\treturn { attendee, isNew };\n\t}\n}\n\n/**\n * Instantiates the system workspace.\n *\n * @internal\n */\nexport function createSystemWorkspace(\n\tclientSessionId: ClientSessionId,\n\tdatastore: SystemWorkspaceDatastore,\n\tevents: IEmitter<Pick<PresenceEvents, \"attendeeJoined\">>,\n\taudience: IAudience,\n): {\n\tworkspace: SystemWorkspace;\n\tstatesEntry: {\n\t\tinternal: PresenceStatesInternal;\n\t\tpublic: PresenceStates<PresenceStatesSchema>;\n\t};\n} {\n\tconst workspace = new SystemWorkspaceImpl(clientSessionId, datastore, events, audience);\n\treturn {\n\t\tworkspace,\n\t\tstatesEntry: {\n\t\t\tinternal: workspace,\n\t\t\tpublic: undefined as unknown as PresenceStates<PresenceStatesSchema>,\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,37 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ /**
6
+ * Wrapper around setTimeout to track whether the timeout has expired or not.
7
+ */
8
+ export declare class TimerManager {
9
+ private _timeoutId;
10
+ private _startTime;
11
+ get startTime(): number;
12
+ private _delay;
13
+ get delay(): number;
14
+ private _expired;
15
+ /**
16
+ * Whether the timer has expired or not.
17
+ *
18
+ * @returns True if the timer has expired; false otherwise.
19
+ */
20
+ hasExpired(): boolean;
21
+ /**
22
+ * Schedules a callback to be triggered after a delay.
23
+ *
24
+ * @param callback - A callback to execute after a delay.
25
+ * @param delay - The time to wait before executing the callback, in milliseconds.
26
+ */
27
+ setTimeout(callback: () => void, delay: number): void;
28
+ /**
29
+ * Clear any pending timer. Also marks the timer as expired.
30
+ */
31
+ clearTimeout(): void;
32
+ /**
33
+ * The time when this timer will expire/trigger. If the timer has expired, returns 0.
34
+ */
35
+ get expireTime(): number;
36
+ }
37
+ //# sourceMappingURL=timerManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timerManager.d.ts","sourceRoot":"","sources":["../src/timerManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,qBAAa,YAAY;IACxB,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,UAAU,CAAK;IAEvB,IAAW,SAAS,IAAI,MAAM,CAE7B;IAED,OAAO,CAAC,MAAM,CAAa;IAE3B,IAAW,KAAK,IAAI,MAAM,CAEzB;IAED,OAAO,CAAC,QAAQ,CAAiB;IAEjC;;;;OAIG;IACI,UAAU,IAAI,OAAO;IAI5B;;;;;OAKG;IACI,UAAU,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAW5D;;OAEG;IACI,YAAY,IAAI,IAAI;IAQ3B;;OAEG;IACH,IAAW,UAAU,IAAI,MAAM,CAE9B;CACD"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ /*!
3
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
+ * Licensed under the MIT License.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.TimerManager = void 0;
8
+ /**
9
+ * Wrapper around setTimeout to track whether the timeout has expired or not.
10
+ */
11
+ class TimerManager {
12
+ constructor() {
13
+ this._startTime = 0;
14
+ this._delay = 0;
15
+ this._expired = true;
16
+ }
17
+ get startTime() {
18
+ return this._startTime;
19
+ }
20
+ get delay() {
21
+ return this._delay;
22
+ }
23
+ /**
24
+ * Whether the timer has expired or not.
25
+ *
26
+ * @returns True if the timer has expired; false otherwise.
27
+ */
28
+ hasExpired() {
29
+ return this._expired;
30
+ }
31
+ /**
32
+ * Schedules a callback to be triggered after a delay.
33
+ *
34
+ * @param callback - A callback to execute after a delay.
35
+ * @param delay - The time to wait before executing the callback, in milliseconds.
36
+ */
37
+ setTimeout(callback, delay) {
38
+ this.clearTimeout(); // Clear any existing timeout
39
+ this._startTime = Date.now();
40
+ this._delay = delay;
41
+ this._expired = false;
42
+ this._timeoutId = setTimeout(() => {
43
+ this._expired = true;
44
+ callback();
45
+ }, delay);
46
+ }
47
+ /**
48
+ * Clear any pending timer. Also marks the timer as expired.
49
+ */
50
+ clearTimeout() {
51
+ if (this._timeoutId !== undefined) {
52
+ clearTimeout(this._timeoutId);
53
+ this._timeoutId = undefined;
54
+ this._expired = true;
55
+ }
56
+ }
57
+ /**
58
+ * The time when this timer will expire/trigger. If the timer has expired, returns 0.
59
+ */
60
+ get expireTime() {
61
+ return this.hasExpired() ? 0 : this.startTime + this.delay;
62
+ }
63
+ }
64
+ exports.TimerManager = TimerManager;
65
+ //# sourceMappingURL=timerManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timerManager.js","sourceRoot":"","sources":["../src/timerManager.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH;;GAEG;AACH,MAAa,YAAY;IAAzB;QAES,eAAU,GAAG,CAAC,CAAC;QAMf,WAAM,GAAW,CAAC,CAAC;QAMnB,aAAQ,GAAY,IAAI,CAAC;IA6ClC,CAAC;IAvDA,IAAW,SAAS;QACnB,OAAO,IAAI,CAAC,UAAU,CAAC;IACxB,CAAC;IAID,IAAW,KAAK;QACf,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAID;;;;OAIG;IACI,UAAU;QAChB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACI,UAAU,CAAC,QAAoB,EAAE,KAAa;QACpD,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,6BAA6B;QAClD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE;YACjC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,QAAQ,EAAE,CAAC;QACZ,CAAC,EAAE,KAAK,CAAC,CAAC;IACX,CAAC;IAED;;OAEG;IACI,YAAY;QAClB,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACnC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;YAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACtB,CAAC;IACF,CAAC;IAED;;OAEG;IACH,IAAW,UAAU;QACpB,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC;IAC5D,CAAC;CACD;AA3DD,oCA2DC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Wrapper around setTimeout to track whether the timeout has expired or not.\n */\nexport class TimerManager {\n\tprivate _timeoutId: number | undefined;\n\tprivate _startTime = 0;\n\n\tpublic get startTime(): number {\n\t\treturn this._startTime;\n\t}\n\n\tprivate _delay: number = 0;\n\n\tpublic get delay(): number {\n\t\treturn this._delay;\n\t}\n\n\tprivate _expired: boolean = true;\n\n\t/**\n\t * Whether the timer has expired or not.\n\t *\n\t * @returns True if the timer has expired; false otherwise.\n\t */\n\tpublic hasExpired(): boolean {\n\t\treturn this._expired;\n\t}\n\n\t/**\n\t * Schedules a callback to be triggered after a delay.\n\t *\n\t * @param callback - A callback to execute after a delay.\n\t * @param delay - The time to wait before executing the callback, in milliseconds.\n\t */\n\tpublic setTimeout(callback: () => void, delay: number): void {\n\t\tthis.clearTimeout(); // Clear any existing timeout\n\t\tthis._startTime = Date.now();\n\t\tthis._delay = delay;\n\t\tthis._expired = false;\n\t\tthis._timeoutId = setTimeout(() => {\n\t\t\tthis._expired = true;\n\t\t\tcallback();\n\t\t}, delay);\n\t}\n\n\t/**\n\t * Clear any pending timer. Also marks the timer as expired.\n\t */\n\tpublic clearTimeout(): void {\n\t\tif (this._timeoutId !== undefined) {\n\t\t\tclearTimeout(this._timeoutId);\n\t\t\tthis._timeoutId = undefined;\n\t\t\tthis._expired = true;\n\t\t}\n\t}\n\n\t/**\n\t * The time when this timer will expire/trigger. If the timer has expired, returns 0.\n\t */\n\tpublic get expireTime(): number {\n\t\treturn this.hasExpired() ? 0 : this.startTime + this.delay;\n\t}\n}\n"]}
package/lib/alpha.d.ts CHANGED
@@ -39,7 +39,7 @@ export {
39
39
  LatestValueManagerEvents,
40
40
  LatestValueMetadata,
41
41
  NotificationEmitter,
42
- NotificationSubscribable,
42
+ NotificationListenable,
43
43
  NotificationSubscriptions,
44
44
  Notifications,
45
45
  NotificationsManager,
@@ -24,13 +24,13 @@ export declare namespace InternalUtilityTypes {
24
24
  *
25
25
  * @system
26
26
  */
27
- type IsNotificationEvent<Event> = Event extends (...args: infer P) => void ? CoreInternalUtilityTypes.IfSameType<P, JsonSerializable<P> & JsonDeserialized<P>, true, false> : false;
27
+ type IsNotificationListener<Event> = Event extends (...args: infer P) => void ? CoreInternalUtilityTypes.IfSameType<P, JsonSerializable<P> & JsonDeserialized<P>, true, false> : false;
28
28
  /**
29
- * Used to specify the kinds of notifications emitted by a {@link NotificationSubscribable}.
29
+ * Used to specify the kinds of notifications emitted by a {@link NotificationListenable}.
30
30
  *
31
31
  * @remarks
32
32
  *
33
- * Any object type is a valid NotificationEvents, but only the notification-like
33
+ * Any object type is a valid NotificationListeners, but only the notification-like
34
34
  * properties of that type will be included.
35
35
  *
36
36
  * @example
@@ -44,8 +44,8 @@ export declare namespace InternalUtilityTypes {
44
44
  *
45
45
  * @system
46
46
  */
47
- type NotificationEvents<E> = {
48
- [P in string & keyof E as IsNotificationEvent<E[P]> extends true ? P : never]: E[P];
47
+ type NotificationListeners<E> = {
48
+ [P in string & keyof E as IsNotificationListener<E[P]> extends true ? P : never]: E[P];
49
49
  };
50
50
  /**
51
51
  * {@link @fluidframework/core-interfaces#JsonDeserialized} version of the parameters of a function.
@@ -1 +1 @@
1
- {"version":3,"file":"exposedUtilityTypes.d.ts","sourceRoot":"","sources":["../src/exposedUtilityTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,oBAAoB,IAAI,wBAAwB,EAChD,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,mDAAmD,CAAC;AAE3D;;;;;;GAMG;AAEH,yBAAiB,oBAAoB,CAAC;IACrC;;;;OAIG;IACH,KAAY,aAAa,CAAC,CAAC,IAAI;QAC9B,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAC5C,CAAC;IAEF;;;;OAIG;IACH,KAAY,mBAAmB,CAAC,KAAK,IAAI,KAAK,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,IAAI,GAC9E,wBAAwB,CAAC,UAAU,CACnC,CAAC,EACD,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,EACzC,IAAI,EACJ,KAAK,CACL,GACA,KAAK,CAAC;IAET;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAY,kBAAkB,CAAC,CAAC,IAAI;SAClC,CAAC,IAAI,MAAM,GAAG,MAAM,CAAC,IAAI,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;KACnF,CAAC;IAEF;;;;OAIG;IACH,KAAY,0BAA0B,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,SAAS,CACnF,GAAG,IAAI,EAAE,MAAM,CAAC,KACZ,GAAG,GACL,gBAAgB,CAAC,CAAC,CAAC,GACnB,KAAK,CAAC;IAET;;;;OAIG;IACH,KAAY,0BAA0B,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,SAAS,CACnF,GAAG,IAAI,EAAE,MAAM,CAAC,KACZ,GAAG,GACL,gBAAgB,CAAC,CAAC,CAAC,GACnB,KAAK,CAAC;CACT"}
1
+ {"version":3,"file":"exposedUtilityTypes.d.ts","sourceRoot":"","sources":["../src/exposedUtilityTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,oBAAoB,IAAI,wBAAwB,EAChD,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,mDAAmD,CAAC;AAE3D;;;;;;GAMG;AAEH,yBAAiB,oBAAoB,CAAC;IACrC;;;;OAIG;IACH,KAAY,aAAa,CAAC,CAAC,IAAI;QAC9B,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAC5C,CAAC;IAEF;;;;OAIG;IACH,KAAY,sBAAsB,CAAC,KAAK,IAAI,KAAK,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,IAAI,GACjF,wBAAwB,CAAC,UAAU,CACnC,CAAC,EACD,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,EACzC,IAAI,EACJ,KAAK,CACL,GACA,KAAK,CAAC;IAET;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAY,qBAAqB,CAAC,CAAC,IAAI;SACrC,CAAC,IAAI,MAAM,GAAG,MAAM,CAAC,IAAI,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;KACtF,CAAC;IAEF;;;;OAIG;IACH,KAAY,0BAA0B,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,SAAS,CACnF,GAAG,IAAI,EAAE,MAAM,CAAC,KACZ,GAAG,GACL,gBAAgB,CAAC,CAAC,CAAC,GACnB,KAAK,CAAC;IAET;;;;OAIG;IACH,KAAY,0BAA0B,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,SAAS,CACnF,GAAG,IAAI,EAAE,MAAM,CAAC,KACZ,GAAG,GACL,gBAAgB,CAAC,CAAC,CAAC,GACnB,KAAK,CAAC;CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"exposedUtilityTypes.js","sourceRoot":"","sources":["../src/exposedUtilityTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tInternalUtilityTypes as CoreInternalUtilityTypes,\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/presence/internal/core-interfaces\";\n\n/**\n * Collection of utility types that are not intended to be used/imported\n * directly outside of this package.\n *\n * @alpha\n * @system\n */\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace InternalUtilityTypes {\n\t/**\n\t * Recursively/deeply makes all properties of a type readonly.\n\t *\n\t * @system\n\t */\n\texport type FullyReadonly<T> = {\n\t\treadonly [K in keyof T]: FullyReadonly<T[K]>;\n\t};\n\n\t/**\n\t * `true` iff the given type is an acceptable shape for a notification.\n\t *\n\t * @system\n\t */\n\texport type IsNotificationEvent<Event> = Event extends (...args: infer P) => void\n\t\t? CoreInternalUtilityTypes.IfSameType<\n\t\t\t\tP,\n\t\t\t\tJsonSerializable<P> & JsonDeserialized<P>,\n\t\t\t\ttrue,\n\t\t\t\tfalse\n\t\t\t>\n\t\t: false;\n\n\t/**\n\t * Used to specify the kinds of notifications emitted by a {@link NotificationSubscribable}.\n\t *\n\t * @remarks\n\t *\n\t * Any object type is a valid NotificationEvents, but only the notification-like\n\t * properties of that type will be included.\n\t *\n\t * @example\n\t *\n\t * ```typescript\n\t * interface MyNotifications {\n\t * load: (user: string, data: IUserData) => void;\n\t * requestPause: (period: number) => void;\n\t * }\n\t * ```\n\t *\n\t * @system\n\t */\n\texport type NotificationEvents<E> = {\n\t\t[P in string & keyof E as IsNotificationEvent<E[P]> extends true ? P : never]: E[P];\n\t};\n\n\t/**\n\t * {@link @fluidframework/core-interfaces#JsonDeserialized} version of the parameters of a function.\n\t *\n\t * @system\n\t */\n\texport type JsonDeserializedParameters<T extends (...args: any) => any> = T extends (\n\t\t...args: infer P\n\t) => any\n\t\t? JsonDeserialized<P>\n\t\t: never;\n\n\t/**\n\t * {@link @fluidframework/core-interfaces#JsonSerializable} version of the parameters of a function.\n\t *\n\t * @system\n\t */\n\texport type JsonSerializableParameters<T extends (...args: any) => any> = T extends (\n\t\t...args: infer P\n\t) => any\n\t\t? JsonSerializable<P>\n\t\t: never;\n}\n"]}
1
+ {"version":3,"file":"exposedUtilityTypes.js","sourceRoot":"","sources":["../src/exposedUtilityTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tInternalUtilityTypes as CoreInternalUtilityTypes,\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/presence/internal/core-interfaces\";\n\n/**\n * Collection of utility types that are not intended to be used/imported\n * directly outside of this package.\n *\n * @alpha\n * @system\n */\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace InternalUtilityTypes {\n\t/**\n\t * Recursively/deeply makes all properties of a type readonly.\n\t *\n\t * @system\n\t */\n\texport type FullyReadonly<T> = {\n\t\treadonly [K in keyof T]: FullyReadonly<T[K]>;\n\t};\n\n\t/**\n\t * `true` iff the given type is an acceptable shape for a notification.\n\t *\n\t * @system\n\t */\n\texport type IsNotificationListener<Event> = Event extends (...args: infer P) => void\n\t\t? CoreInternalUtilityTypes.IfSameType<\n\t\t\t\tP,\n\t\t\t\tJsonSerializable<P> & JsonDeserialized<P>,\n\t\t\t\ttrue,\n\t\t\t\tfalse\n\t\t\t>\n\t\t: false;\n\n\t/**\n\t * Used to specify the kinds of notifications emitted by a {@link NotificationListenable}.\n\t *\n\t * @remarks\n\t *\n\t * Any object type is a valid NotificationListeners, but only the notification-like\n\t * properties of that type will be included.\n\t *\n\t * @example\n\t *\n\t * ```typescript\n\t * interface MyNotifications {\n\t * load: (user: string, data: IUserData) => void;\n\t * requestPause: (period: number) => void;\n\t * }\n\t * ```\n\t *\n\t * @system\n\t */\n\texport type NotificationListeners<E> = {\n\t\t[P in string & keyof E as IsNotificationListener<E[P]> extends true ? P : never]: E[P];\n\t};\n\n\t/**\n\t * {@link @fluidframework/core-interfaces#JsonDeserialized} version of the parameters of a function.\n\t *\n\t * @system\n\t */\n\texport type JsonDeserializedParameters<T extends (...args: any) => any> = T extends (\n\t\t...args: infer P\n\t) => any\n\t\t? JsonDeserialized<P>\n\t\t: never;\n\n\t/**\n\t * {@link @fluidframework/core-interfaces#JsonSerializable} version of the parameters of a function.\n\t *\n\t * @system\n\t */\n\texport type JsonSerializableParameters<T extends (...args: any) => any> = T extends (\n\t\t...args: infer P\n\t) => any\n\t\t? JsonSerializable<P>\n\t\t: never;\n}\n"]}
package/lib/index.d.ts CHANGED
@@ -18,5 +18,5 @@ export { acquirePresenceViaDataObject, type ExperimentalPresenceDO, Experimental
18
18
  export { LatestMap, type LatestMapItemRemovedClientData, type LatestMapItemValueClientData, type LatestMapValueClientData, type LatestMapValueManager, type LatestMapValueManagerEvents, type ValueMap, } from "./latestMapValueManager.js";
19
19
  export { Latest, type LatestValueManager, type LatestValueManagerEvents, } from "./latestValueManager.js";
20
20
  export type { LatestValueClientData, LatestValueData, LatestValueMetadata, } from "./latestValueTypes.js";
21
- export { type NotificationEmitter, type NotificationSubscribable, type NotificationSubscriptions, Notifications, type NotificationsManager, type NotificationsManagerEvents, } from "./notificationsManager.js";
21
+ export { type NotificationEmitter, type NotificationListenable, type NotificationSubscriptions, Notifications, type NotificationsManager, type NotificationsManagerEvents, } from "./notificationsManager.js";
22
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AAgBH,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,YAAY,EACX,qBAAqB,EACrB,2BAA2B,EAC3B,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,sBAAsB,GACtB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACN,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,mBAAmB,GACnB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACX,iBAAiB,EACjB,wBAAwB,GACxB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EACN,4BAA4B,EAC5B,KAAK,sBAAsB,EAC3B,2BAA2B,GAC3B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EACN,SAAS,EACT,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,QAAQ,GACb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,MAAM,EACN,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,GAC7B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,qBAAqB,EACrB,eAAe,EACf,mBAAmB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACN,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,GAC/B,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AASH,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,YAAY,EACX,qBAAqB,EACrB,2BAA2B,EAC3B,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,sBAAsB,GACtB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACN,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,mBAAmB,GACnB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACX,iBAAiB,EACjB,wBAAwB,GACxB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EACN,4BAA4B,EAC5B,KAAK,sBAAsB,EAC3B,2BAA2B,GAC3B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EACN,SAAS,EACT,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,QAAQ,GACb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,MAAM,EACN,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,GAC7B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,qBAAqB,EACrB,eAAe,EACf,mBAAmB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACN,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,GAC/B,MAAM,2BAA2B,CAAC"}
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoCH,OAAO,EAKN,mBAAmB,GACnB,MAAM,eAAe,CAAC;AAOvB,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EACN,4BAA4B,EAE5B,2BAA2B,GAC3B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EACN,SAAS,GAOT,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,MAAM,GAGN,MAAM,yBAAyB,CAAC;AAOjC,OAAO,EAIN,aAAa,GAGb,MAAM,2BAA2B,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Package for client presence within a connected session.\n *\n * See {@link https://github.com/microsoft/FluidFramework/tree/main/packages/framework/presence#readme | README.md } for an overview of the package.\n *\n * @packageDocumentation\n */\n\n// If desired these are the \"required\" types from core-interfaces.\n// export type {\n// \tInternalUtilityTypes,\n// \tJsonDeserialized,\n// \tJsonSerializable,\n// } from \"@fluidframework/presence/internal/core-interfaces\";\n\n// If desired these are the \"required\" types from events.\n// export type {\n// \tEvents,\n// \tIsEvent,\n// \tISubscribable,\n// } from \"@fluidframework/presence/internal/events\";\n\nexport type { ClientConnectionId } from \"./baseTypes.js\";\n\nexport type {\n\tPresenceNotifications,\n\tPresenceNotificationsSchema,\n\tPresenceStates,\n\tPresenceStatesEntries,\n\tPresenceStatesSchema,\n\tPresenceWorkspaceAddress,\n\tPresenceWorkspaceEntry,\n} from \"./types.js\";\n\nexport {\n\ttype ClientSessionId,\n\ttype IPresence,\n\ttype ISessionClient,\n\ttype PresenceEvents,\n\tSessionClientStatus,\n} from \"./presence.js\";\n\nexport type {\n\tBroadcastControls,\n\tBroadcastControlSettings,\n} from \"./broadcastControls.js\";\n\nexport { acquirePresence } from \"./experimentalAccess.js\";\n\nexport {\n\tacquirePresenceViaDataObject,\n\ttype ExperimentalPresenceDO,\n\tExperimentalPresenceManager,\n} from \"./datastorePresenceManagerFactory.js\";\n\nexport {\n\tLatestMap,\n\ttype LatestMapItemRemovedClientData,\n\ttype LatestMapItemValueClientData,\n\ttype LatestMapValueClientData,\n\ttype LatestMapValueManager,\n\ttype LatestMapValueManagerEvents,\n\ttype ValueMap,\n} from \"./latestMapValueManager.js\";\nexport {\n\tLatest,\n\ttype LatestValueManager,\n\ttype LatestValueManagerEvents,\n} from \"./latestValueManager.js\";\nexport type {\n\tLatestValueClientData,\n\tLatestValueData,\n\tLatestValueMetadata,\n} from \"./latestValueTypes.js\";\n\nexport {\n\ttype NotificationEmitter,\n\ttype NotificationSubscribable,\n\ttype NotificationSubscriptions,\n\tNotifications,\n\ttype NotificationsManager,\n\ttype NotificationsManagerEvents,\n} from \"./notificationsManager.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6BH,OAAO,EAKN,mBAAmB,GACnB,MAAM,eAAe,CAAC;AAOvB,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EACN,4BAA4B,EAE5B,2BAA2B,GAC3B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EACN,SAAS,GAOT,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,MAAM,GAGN,MAAM,yBAAyB,CAAC;AAOjC,OAAO,EAIN,aAAa,GAGb,MAAM,2BAA2B,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Package for client presence within a connected session.\n *\n * See {@link https://github.com/microsoft/FluidFramework/tree/main/packages/framework/presence#readme | README.md } for an overview of the package.\n *\n * @packageDocumentation\n */\n\n// If desired these are the \"required\" types from core-interfaces.\n// export type {\n// \tInternalUtilityTypes,\n// \tJsonDeserialized,\n// \tJsonSerializable,\n// } from \"@fluidframework/presence/internal/core-interfaces\";\n\nexport type { ClientConnectionId } from \"./baseTypes.js\";\n\nexport type {\n\tPresenceNotifications,\n\tPresenceNotificationsSchema,\n\tPresenceStates,\n\tPresenceStatesEntries,\n\tPresenceStatesSchema,\n\tPresenceWorkspaceAddress,\n\tPresenceWorkspaceEntry,\n} from \"./types.js\";\n\nexport {\n\ttype ClientSessionId,\n\ttype IPresence,\n\ttype ISessionClient,\n\ttype PresenceEvents,\n\tSessionClientStatus,\n} from \"./presence.js\";\n\nexport type {\n\tBroadcastControls,\n\tBroadcastControlSettings,\n} from \"./broadcastControls.js\";\n\nexport { acquirePresence } from \"./experimentalAccess.js\";\n\nexport {\n\tacquirePresenceViaDataObject,\n\ttype ExperimentalPresenceDO,\n\tExperimentalPresenceManager,\n} from \"./datastorePresenceManagerFactory.js\";\n\nexport {\n\tLatestMap,\n\ttype LatestMapItemRemovedClientData,\n\ttype LatestMapItemValueClientData,\n\ttype LatestMapValueClientData,\n\ttype LatestMapValueManager,\n\ttype LatestMapValueManagerEvents,\n\ttype ValueMap,\n} from \"./latestMapValueManager.js\";\nexport {\n\tLatest,\n\ttype LatestValueManager,\n\ttype LatestValueManagerEvents,\n} from \"./latestValueManager.js\";\nexport type {\n\tLatestValueClientData,\n\tLatestValueData,\n\tLatestValueMetadata,\n} from \"./latestValueTypes.js\";\n\nexport {\n\ttype NotificationEmitter,\n\ttype NotificationListenable,\n\ttype NotificationSubscriptions,\n\tNotifications,\n\ttype NotificationsManager,\n\ttype NotificationsManagerEvents,\n} from \"./notificationsManager.js\";\n"]}
@@ -2,11 +2,11 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+ import type { Listenable } from "@fluidframework/core-interfaces";
5
6
  import type { BroadcastControls, BroadcastControlSettings } from "./broadcastControls.js";
6
7
  import type { LatestValueClientData, LatestValueData, LatestValueMetadata } from "./latestValueTypes.js";
7
8
  import type { ClientSessionId, ISessionClient } from "./presence.js";
8
9
  import type { JsonDeserialized, JsonSerializable } from "@fluidframework/presence/internal/core-interfaces";
9
- import type { ISubscribable } from "@fluidframework/presence/internal/events";
10
10
  import type { InternalTypes } from "@fluidframework/presence/internal/exposedInternalTypes";
11
11
  import type { InternalUtilityTypes } from "@fluidframework/presence/internal/exposedUtilityTypes";
12
12
  /**
@@ -149,7 +149,7 @@ export interface LatestMapValueManager<T, Keys extends string | number = string
149
149
  /**
150
150
  * Events for LatestMap value manager.
151
151
  */
152
- readonly events: ISubscribable<LatestMapValueManagerEvents<T, Keys>>;
152
+ readonly events: Listenable<LatestMapValueManagerEvents<T, Keys>>;
153
153
  /**
154
154
  * Controls for management of sending updates.
155
155
  */
@@ -1 +1 @@
1
- {"version":3,"file":"latestMapValueManager.d.ts","sourceRoot":"","sources":["../src/latestMapValueManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"latestMapValueManager.d.ts","sourceRoot":"","sources":["../src/latestMapValueManager.ts"],"names":[],"mappings":"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"}
@@ -2,10 +2,10 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+ import { createEmitter } from "@fluid-internal/client-utils";
5
6
  import { OptionalBroadcastControl } from "./broadcastControls.js";
6
7
  import { datastoreFromHandle } from "./stateDatastore.js";
7
8
  import { brandIVM } from "./valueManager.js";
8
- import { createEmitter } from "@fluidframework/presence/internal/events";
9
9
  class ValueMapImpl {
10
10
  constructor(value, localUpdate) {
11
11
  this.value = value;
@@ -1 +1 @@
1
- {"version":3,"file":"latestMapValueManager.js","sourceRoot":"","sources":["../src/latestMapValueManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { BroadcastControls, BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { OptionalBroadcastControl } from \"./broadcastControls.js\";\nimport type { ValueManager } from \"./internalTypes.js\";\nimport type {\n\tLatestValueClientData,\n\tLatestValueData,\n\tLatestValueMetadata,\n} from \"./latestValueTypes.js\";\nimport type { ClientSessionId, ISessionClient, SpecificSessionClient } from \"./presence.js\";\nimport { datastoreFromHandle, type StateDatastore } from \"./stateDatastore.js\";\nimport { brandIVM } from \"./valueManager.js\";\n\nimport type {\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/presence/internal/core-interfaces\";\nimport type { ISubscribable } from \"@fluidframework/presence/internal/events\";\nimport { createEmitter } from \"@fluidframework/presence/internal/events\";\nimport type { InternalTypes } from \"@fluidframework/presence/internal/exposedInternalTypes\";\nimport type { InternalUtilityTypes } from \"@fluidframework/presence/internal/exposedUtilityTypes\";\n\n/**\n * Collection of latest known values for a specific client.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapValueClientData<\n\tT,\n\tKeys extends string | number,\n\tSpecificSessionClientId extends ClientSessionId = ClientSessionId,\n> {\n\t/**\n\t * Associated client.\n\t */\n\tclient: ISessionClient<SpecificSessionClientId>;\n\n\t/**\n\t * @privateRemarks This could be regular map currently as no Map is\n\t * stored internally and a new instance is created for every request.\n\t */\n\titems: ReadonlyMap<Keys, LatestValueData<T>>;\n}\n\n/**\n * State of a single item value, its key, and its metadata.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapItemValueClientData<T, K extends string | number>\n\textends LatestValueClientData<T> {\n\tkey: K;\n}\n\n/**\n * Identifier and metadata for a removed item.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapItemRemovedClientData<K extends string | number> {\n\tclient: ISessionClient;\n\tkey: K;\n\tmetadata: LatestValueMetadata;\n}\n\n/**\n * @sealed\n * @alpha\n */\nexport interface LatestMapValueManagerEvents<T, K extends string | number> {\n\t/**\n\t * Raised when any item's value for remote client is updated.\n\t * @param updates - Map of one or more values updated.\n\t *\n\t * @remarks The event does not include item removals.\n\t *\n\t * @eventProperty\n\t */\n\tupdated: (updates: LatestMapValueClientData<T, K>) => void;\n\n\t/**\n\t * Raised when specific item's value is updated.\n\t * @param updatedItem - Updated item value.\n\t *\n\t * @eventProperty\n\t */\n\titemUpdated: (updatedItem: LatestMapItemValueClientData<T, K>) => void;\n\n\t/**\n\t * Raised when specific item is removed.\n\t * @param removedItem - Removed item.\n\t *\n\t * @eventProperty\n\t */\n\titemRemoved: (removedItem: LatestMapItemRemovedClientData<K>) => void;\n}\n\n/**\n * Map of local client's values. Modifications are transmitted to all other connected clients.\n *\n * @sealed\n * @alpha\n */\nexport interface ValueMap<K extends string | number, V> {\n\t/**\n\t * ${@link ValueMap.delete}s all elements in the ValueMap.\n\t * @remarks This is not yet implemented.\n\t */\n\tclear(): void;\n\n\t/**\n\t * @returns true if an element in the ValueMap existed and has been removed, or false if\n\t * the element does not exist.\n\t * @remarks No entry is fully removed. Instead an undefined placeholder is locally and\n\t * transmitted to all other clients. For better performance limit the number of deleted\n\t * entries and reuse keys when possible.\n\t * @privateRemarks In the future we may add a mechanism to remove the placeholder, at least\n\t * from transmissions after sufficient time has passed.\n\t */\n\tdelete(key: K): boolean;\n\n\t/**\n\t * Executes a provided function once per each key/value pair in the ValueMap, in arbitrary order.\n\t */\n\tforEach(\n\t\tcallbackfn: (\n\t\t\tvalue: InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>,\n\t\t\tkey: K,\n\t\t\tmap: ValueMap<K, V>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void;\n\n\t/**\n\t * Returns a specified element from the ValueMap object.\n\t * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.\n\t */\n\tget(key: K): InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>> | undefined;\n\n\t/**\n\t * @returns boolean indicating whether an element with the specified key exists or not.\n\t */\n\thas(key: K): boolean;\n\n\t/**\n\t * Adds a new element with a specified key and value to the ValueMap. If an element with the same key already exists, the element will be updated.\n\t * The value will be transmitted to all other connected clients.\n\t *\n\t * @remarks Manager assumes ownership of the value and its references.\n\t * Make a deep clone before setting, if needed. No comparison is done to detect changes; all\n\t * sets are transmitted.\n\t */\n\tset(key: K, value: JsonSerializable<V> & JsonDeserialized<V>): this;\n\n\t/**\n\t * @returns the number of elements in the ValueMap.\n\t */\n\treadonly size: number;\n\n\t/**\n\t * Returns an iterable of entries in the map.\n\t */\n\t// [Symbol.iterator](): IterableIterator<[K, InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of key, value pairs for every entry in the map.\n\t */\n\t// entries(): IterableIterator<[K, InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of keys in the map.\n\t */\n\tkeys(): IterableIterator<K>;\n\n\t/**\n\t * Returns an iterable of values in the map.\n\t */\n\t// values(): IterableIterator<InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>>;\n}\n\nclass ValueMapImpl<T, K extends string | number> implements ValueMap<K, T> {\n\tprivate countDefined: number;\n\tpublic constructor(\n\t\tprivate readonly value: InternalTypes.MapValueState<T>,\n\t\tprivate readonly localUpdate: (updates: InternalTypes.MapValueState<T>) => void,\n\t) {\n\t\t// All initial items are expected to be defined.\n\t\t// TODO assert all defined and/or update type.\n\t\tthis.countDefined = Object.keys(value.items).length;\n\t}\n\n\tprivate updateItem(key: K, value: InternalTypes.ValueOptionalState<T>[\"value\"]): void {\n\t\tthis.value.rev += 1;\n\t\tconst item = this.value.items[key];\n\t\titem.rev += 1;\n\t\titem.timestamp = Date.now();\n\t\tif (value === undefined) {\n\t\t\tdelete item.value;\n\t\t} else {\n\t\t\titem.value = value;\n\t\t}\n\t\tconst update = { rev: this.value.rev, items: { [key]: item } };\n\t\tthis.localUpdate(update);\n\t}\n\n\tpublic clear(): void {\n\t\tthrow new Error(\"Method not implemented.\");\n\t}\n\tpublic delete(key: K): boolean {\n\t\tconst { items } = this.value;\n\t\tconst hasKey = items[key]?.value !== undefined;\n\t\tif (hasKey) {\n\t\t\tthis.countDefined -= 1;\n\t\t\tthis.updateItem(key, undefined);\n\t\t}\n\t\treturn hasKey;\n\t}\n\tpublic forEach(\n\t\tcallbackfn: (\n\t\t\tvalue: InternalUtilityTypes.FullyReadonly<JsonDeserialized<T>>,\n\t\t\tkey: K,\n\t\t\tmap: ValueMap<K, T>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void {\n\t\tfor (const [key, item] of Object.entries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\t// TODO: see about typing InternalTypes.MapValueState with K\n\t\t\t\tcallbackfn(item.value, key as K, this);\n\t\t\t}\n\t\t}\n\t}\n\tpublic get(key: K): InternalUtilityTypes.FullyReadonly<JsonDeserialized<T>> | undefined {\n\t\treturn this.value.items[key]?.value;\n\t}\n\tpublic has(key: K): boolean {\n\t\treturn this.value.items[key]?.value !== undefined;\n\t}\n\tpublic set(key: K, value: JsonSerializable<T> & JsonDeserialized<T>): this {\n\t\tif (!(key in this.value.items)) {\n\t\t\tthis.countDefined += 1;\n\t\t\tthis.value.items[key] = { rev: 0, timestamp: 0, value };\n\t\t}\n\t\tthis.updateItem(key, value);\n\t\treturn this;\n\t}\n\tpublic get size(): number {\n\t\treturn this.countDefined;\n\t}\n\tpublic keys(): IterableIterator<K> {\n\t\tconst keys: K[] = [];\n\t\tfor (const [key, item] of Object.entries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tkeys.push(key as K);\n\t\t\t}\n\t\t}\n\t\treturn keys[Symbol.iterator]();\n\t}\n}\n\n/**\n * Value manager that provides a `Map` of latest known values from this client to\n * others and read access to their values.\n * Entries in the map may vary over time and by client, but all values are expected to\n * be of the same type, which may be a union type.\n *\n * @remarks Create using {@link LatestMap} registered to {@link PresenceStates}.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapValueManager<T, Keys extends string | number = string | number> {\n\t/**\n\t * Events for LatestMap value manager.\n\t */\n\treadonly events: ISubscribable<LatestMapValueManagerEvents<T, Keys>>;\n\n\t/**\n\t * Controls for management of sending updates.\n\t */\n\treadonly controls: BroadcastControls;\n\n\t/**\n\t * Current value map for this client.\n\t */\n\treadonly local: ValueMap<Keys, T>;\n\t/**\n\t * Iterable access to remote clients' map of values.\n\t */\n\tclientValues(): IterableIterator<LatestMapValueClientData<T, Keys>>;\n\t/**\n\t * Array of known clients.\n\t */\n\tclients(): ISessionClient[];\n\t/**\n\t * Access to a specific client's map of values.\n\t */\n\tclientValue(client: ISessionClient): ReadonlyMap<Keys, LatestValueData<T>>;\n}\n\nclass LatestMapValueManagerImpl<\n\tT,\n\tRegistrationKey extends string,\n\tKeys extends string | number = string | number,\n> implements\n\t\tLatestMapValueManager<T, Keys>,\n\t\tRequired<ValueManager<T, InternalTypes.MapValueState<T>>>\n{\n\tpublic readonly events = createEmitter<LatestMapValueManagerEvents<T, Keys>>();\n\tpublic readonly controls: OptionalBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly key: RegistrationKey,\n\t\tprivate readonly datastore: StateDatastore<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T>\n\t\t>,\n\t\tpublic readonly value: InternalTypes.MapValueState<T>,\n\t\tcontrolSettings: BroadcastControlSettings | undefined,\n\t) {\n\t\tthis.controls = new OptionalBroadcastControl(controlSettings);\n\n\t\tthis.local = new ValueMapImpl<T, Keys>(\n\t\t\tvalue,\n\t\t\t(updates: InternalTypes.MapValueState<T>) => {\n\t\t\t\tdatastore.localUpdate(key, updates, {\n\t\t\t\t\tallowableUpdateLatencyMs: this.controls.allowableUpdateLatencyMs,\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic readonly local: ValueMap<Keys, T>;\n\n\tpublic *clientValues(): IterableIterator<LatestMapValueClientData<T, Keys>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tfor (const clientSessionId of Object.keys(allKnownStates.states)) {\n\t\t\tif (clientSessionId !== allKnownStates.self) {\n\t\t\t\tconst client = this.datastore.lookupClient(clientSessionId);\n\t\t\t\tconst items = this.clientValue(client);\n\t\t\t\tyield { client, items };\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic clients(): ISessionClient[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\treturn Object.keys(allKnownStates.states)\n\t\t\t.filter((clientSessionId) => clientSessionId !== allKnownStates.self)\n\t\t\t.map((clientSessionId) => this.datastore.lookupClient(clientSessionId));\n\t}\n\n\tpublic clientValue(client: ISessionClient): ReadonlyMap<Keys, LatestValueData<T>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst clientSessionId = client.sessionId;\n\t\tif (!(clientSessionId in allKnownStates.states)) {\n\t\t\tthrow new Error(\"No entry for client\");\n\t\t}\n\t\tconst clientStateMap = allKnownStates.states[clientSessionId];\n\t\tconst items = new Map<Keys, LatestValueData<T>>();\n\t\tfor (const [key, item] of Object.entries(clientStateMap.items)) {\n\t\t\tconst value = item.value;\n\t\t\tif (value !== undefined) {\n\t\t\t\titems.set(key as Keys, {\n\t\t\t\t\tvalue,\n\t\t\t\t\tmetadata: { revision: item.rev, timestamp: item.timestamp },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn items;\n\t}\n\n\tpublic update<SpecificSessionClientId extends ClientSessionId>(\n\t\tclient: SpecificSessionClient<SpecificSessionClientId>,\n\t\t_received: number,\n\t\tvalue: InternalTypes.MapValueState<T>,\n\t): void {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst clientSessionId: SpecificSessionClientId = client.sessionId;\n\t\tif (!(clientSessionId in allKnownStates.states)) {\n\t\t\t// New client - prepare new client state directory\n\t\t\tallKnownStates.states[clientSessionId] = { rev: value.rev, items: {} };\n\t\t}\n\t\tconst currentState = allKnownStates.states[clientSessionId];\n\t\t// Accumulate individual update keys\n\t\tconst updatedItemKeys: Keys[] = [];\n\t\tfor (const [key, item] of Object.entries(value.items)) {\n\t\t\tif (!(key in currentState.items) || currentState.items[key].rev < item.rev) {\n\t\t\t\tupdatedItemKeys.push(key as Keys);\n\t\t\t}\n\t\t}\n\n\t\tif (updatedItemKeys.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Store updates\n\t\tif (value.rev > currentState.rev) {\n\t\t\tcurrentState.rev = value.rev;\n\t\t}\n\t\tconst allUpdates = {\n\t\t\tclient,\n\t\t\titems: new Map<Keys, LatestValueData<T>>(),\n\t\t};\n\t\tfor (const key of updatedItemKeys) {\n\t\t\tconst item = value.items[key];\n\t\t\tconst hadPriorValue = currentState.items[key]?.value;\n\t\t\tcurrentState.items[key] = item;\n\t\t\tconst metadata = { revision: item.rev, timestamp: item.timestamp };\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tthis.events.emit(\"itemUpdated\", {\n\t\t\t\t\tclient,\n\t\t\t\t\tkey,\n\t\t\t\t\tvalue: item.value,\n\t\t\t\t\tmetadata,\n\t\t\t\t});\n\t\t\t\tallUpdates.items.set(key, { value: item.value, metadata });\n\t\t\t} else if (hadPriorValue !== undefined) {\n\t\t\t\tthis.events.emit(\"itemRemoved\", {\n\t\t\t\t\tclient,\n\t\t\t\t\tkey,\n\t\t\t\t\tmetadata,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis.datastore.update(this.key, clientSessionId, currentState);\n\t\tthis.events.emit(\"updated\", allUpdates);\n\t}\n}\n\n/**\n * Factory for creating a {@link LatestMapValueManager}.\n *\n * @alpha\n */\nexport function LatestMap<\n\tT extends object,\n\tKeys extends string | number = string | number,\n\tRegistrationKey extends string = string,\n>(\n\tinitialValues?: {\n\t\t[K in Keys]: JsonSerializable<T> & JsonDeserialized<T>;\n\t},\n\tcontrols?: BroadcastControlSettings,\n): InternalTypes.ManagerFactory<\n\tRegistrationKey,\n\tInternalTypes.MapValueState<T>,\n\tLatestMapValueManager<T, Keys>\n> {\n\tconst timestamp = Date.now();\n\tconst value: InternalTypes.MapValueState<T> = { rev: 0, items: {} };\n\t// LatestMapValueManager takes ownership of values within initialValues.\n\tif (initialValues !== undefined) {\n\t\tfor (const key of Object.keys(initialValues)) {\n\t\t\tvalue.items[key] = { rev: 0, timestamp, value: initialValues[key as Keys] };\n\t\t}\n\t}\n\tconst factory = (\n\t\tkey: RegistrationKey,\n\t\tdatastoreHandle: InternalTypes.StateDatastoreHandle<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T>\n\t\t>,\n\t): {\n\t\tinitialData: { value: typeof value; allowableUpdateLatencyMs: number | undefined };\n\t\tmanager: InternalTypes.StateValue<LatestMapValueManager<T, Keys>>;\n\t} => ({\n\t\tinitialData: { value, allowableUpdateLatencyMs: controls?.allowableUpdateLatencyMs },\n\t\tmanager: brandIVM<\n\t\t\tLatestMapValueManagerImpl<T, RegistrationKey, Keys>,\n\t\t\tT,\n\t\t\tInternalTypes.MapValueState<T>\n\t\t>(\n\t\t\tnew LatestMapValueManagerImpl(\n\t\t\t\tkey,\n\t\t\t\tdatastoreFromHandle(datastoreHandle),\n\t\t\t\tvalue,\n\t\t\t\tcontrols,\n\t\t\t),\n\t\t),\n\t});\n\treturn Object.assign(factory, { instanceBase: LatestMapValueManagerImpl });\n}\n"]}
1
+ {"version":3,"file":"latestMapValueManager.js","sourceRoot":"","sources":["../src/latestMapValueManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAI7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAQlE,OAAO,EAAE,mBAAmB,EAAuB,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AA0K7C,MAAM,YAAY;IAEjB,YACkB,KAAqC,EACrC,WAA8D;QAD9D,UAAK,GAAL,KAAK,CAAgC;QACrC,gBAAW,GAAX,WAAW,CAAmD;QAE/E,gDAAgD;QAChD,8CAA8C;QAC9C,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IACrD,CAAC;IAEO,UAAU,CAAC,GAAM,EAAE,KAAmD;QAC7E,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACd,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,KAAK,CAAC;QACnB,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACpB,CAAC;QACD,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;QAC/D,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAEM,KAAK;QACX,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC5C,CAAC;IACM,MAAM,CAAC,GAAM;QACnB,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAC7B,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,SAAS,CAAC;QAC/C,IAAI,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,MAAM,CAAC;IACf,CAAC;IACM,OAAO,CACb,UAIS,EACT,OAAiB;QAEjB,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5D,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC9B,4DAA4D;gBAC5D,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,GAAQ,EAAE,IAAI,CAAC,CAAC;YACxC,CAAC;QACF,CAAC;IACF,CAAC;IACM,GAAG,CAAC,GAAM;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC;IACrC,CAAC;IACM,GAAG,CAAC,GAAM;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,SAAS,CAAC;IACnD,CAAC;IACM,GAAG,CAAC,GAAM,EAAE,KAAgD;QAClE,IAAI,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;QACzD,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAW,IAAI;QACd,OAAO,IAAI,CAAC,YAAY,CAAC;IAC1B,CAAC;IACM,IAAI;QACV,MAAM,IAAI,GAAQ,EAAE,CAAC;QACrB,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5D,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC9B,IAAI,CAAC,IAAI,CAAC,GAAQ,CAAC,CAAC;YACrB,CAAC;QACF,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;IAChC,CAAC;CACD;AA0CD,MAAM,yBAAyB;IAW9B,YACkB,GAAoB,EACpB,SAGhB,EACe,KAAqC,EACrD,eAAqD;QANpC,QAAG,GAAH,GAAG,CAAiB;QACpB,cAAS,GAAT,SAAS,CAGzB;QACe,UAAK,GAAL,KAAK,CAAgC;QATtC,WAAM,GAAG,aAAa,EAAwC,CAAC;QAY9E,IAAI,CAAC,QAAQ,GAAG,IAAI,wBAAwB,CAAC,eAAe,CAAC,CAAC;QAE9D,IAAI,CAAC,KAAK,GAAG,IAAI,YAAY,CAC5B,KAAK,EACL,CAAC,OAAuC,EAAE,EAAE;YAC3C,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE;gBACnC,wBAAwB,EAAE,IAAI,CAAC,QAAQ,CAAC,wBAAwB;aAChE,CAAC,CAAC;QACJ,CAAC,CACD,CAAC;IACH,CAAC;IAIM,CAAC,YAAY;QACnB,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5D,KAAK,MAAM,eAAe,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YAClE,IAAI,eAAe,KAAK,cAAc,CAAC,IAAI,EAAE,CAAC;gBAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;gBAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;gBACvC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;YACzB,CAAC;QACF,CAAC;IACF,CAAC;IAEM,OAAO;QACb,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5D,OAAO,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;aACvC,MAAM,CAAC,CAAC,eAAe,EAAE,EAAE,CAAC,eAAe,KAAK,cAAc,CAAC,IAAI,CAAC;aACpE,GAAG,CAAC,CAAC,eAAe,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC;IAC1E,CAAC;IAEM,WAAW,CAAC,MAAsB;QACxC,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC;QACzC,IAAI,CAAC,CAAC,eAAe,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACxC,CAAC;QACD,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAC9D,MAAM,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAC;QAClD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YAChE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACzB,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE;oBACtB,KAAK;oBACL,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;iBAC3D,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC;IAEM,MAAM,CACZ,MAAsD,EACtD,SAAiB,EACjB,KAAqC;QAErC,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5D,MAAM,eAAe,GAA4B,MAAM,CAAC,SAAS,CAAC;QAClE,IAAI,CAAC,CAAC,eAAe,IAAI,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YACjD,kDAAkD;YAClD,cAAc,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QACxE,CAAC;QACD,MAAM,YAAY,GAAG,cAAc,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAC5D,oCAAoC;QACpC,MAAM,eAAe,GAAW,EAAE,CAAC;QACnC,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACvD,IAAI,CAAC,CAAC,GAAG,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC5E,eAAe,CAAC,IAAI,CAAC,GAAW,CAAC,CAAC;YACnC,CAAC;QACF,CAAC;QAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO;QACR,CAAC;QAED,gBAAgB;QAChB,IAAI,KAAK,CAAC,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC;YAClC,YAAY,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QAC9B,CAAC;QACD,MAAM,UAAU,GAAG;YAClB,MAAM;YACN,KAAK,EAAE,IAAI,GAAG,EAA4B;SAC1C,CAAC;QACF,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC9B,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC;YACrD,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YAC/B,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;YACnE,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC9B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE;oBAC/B,MAAM;oBACN,GAAG;oBACH,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,QAAQ;iBACR,CAAC,CAAC;gBACH,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC5D,CAAC;iBAAM,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;gBACxC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE;oBAC/B,MAAM;oBACN,GAAG;oBACH,QAAQ;iBACR,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACzC,CAAC;CACD;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAKxB,aAEC,EACD,QAAmC;IAMnC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAmC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACpE,wEAAwE;IACxE,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QACjC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YAC9C,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,CAAC,GAAW,CAAC,EAAE,CAAC;QAC7E,CAAC;IACF,CAAC;IACD,MAAM,OAAO,GAAG,CACf,GAAoB,EACpB,eAGC,EAIA,EAAE,CAAC,CAAC;QACL,WAAW,EAAE,EAAE,KAAK,EAAE,wBAAwB,EAAE,QAAQ,EAAE,wBAAwB,EAAE;QACpF,OAAO,EAAE,QAAQ,CAKhB,IAAI,yBAAyB,CAC5B,GAAG,EACH,mBAAmB,CAAC,eAAe,CAAC,EACpC,KAAK,EACL,QAAQ,CACR,CACD;KACD,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,yBAAyB,EAAE,CAAC,CAAC;AAC5E,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { createEmitter } from \"@fluid-internal/client-utils\";\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\n\nimport type { BroadcastControls, BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { OptionalBroadcastControl } from \"./broadcastControls.js\";\nimport type { ValueManager } from \"./internalTypes.js\";\nimport type {\n\tLatestValueClientData,\n\tLatestValueData,\n\tLatestValueMetadata,\n} from \"./latestValueTypes.js\";\nimport type { ClientSessionId, ISessionClient, SpecificSessionClient } from \"./presence.js\";\nimport { datastoreFromHandle, type StateDatastore } from \"./stateDatastore.js\";\nimport { brandIVM } from \"./valueManager.js\";\n\nimport type {\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/presence/internal/core-interfaces\";\nimport type { InternalTypes } from \"@fluidframework/presence/internal/exposedInternalTypes\";\nimport type { InternalUtilityTypes } from \"@fluidframework/presence/internal/exposedUtilityTypes\";\n\n/**\n * Collection of latest known values for a specific client.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapValueClientData<\n\tT,\n\tKeys extends string | number,\n\tSpecificSessionClientId extends ClientSessionId = ClientSessionId,\n> {\n\t/**\n\t * Associated client.\n\t */\n\tclient: ISessionClient<SpecificSessionClientId>;\n\n\t/**\n\t * @privateRemarks This could be regular map currently as no Map is\n\t * stored internally and a new instance is created for every request.\n\t */\n\titems: ReadonlyMap<Keys, LatestValueData<T>>;\n}\n\n/**\n * State of a single item value, its key, and its metadata.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapItemValueClientData<T, K extends string | number>\n\textends LatestValueClientData<T> {\n\tkey: K;\n}\n\n/**\n * Identifier and metadata for a removed item.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapItemRemovedClientData<K extends string | number> {\n\tclient: ISessionClient;\n\tkey: K;\n\tmetadata: LatestValueMetadata;\n}\n\n/**\n * @sealed\n * @alpha\n */\nexport interface LatestMapValueManagerEvents<T, K extends string | number> {\n\t/**\n\t * Raised when any item's value for remote client is updated.\n\t * @param updates - Map of one or more values updated.\n\t *\n\t * @remarks The event does not include item removals.\n\t *\n\t * @eventProperty\n\t */\n\tupdated: (updates: LatestMapValueClientData<T, K>) => void;\n\n\t/**\n\t * Raised when specific item's value is updated.\n\t * @param updatedItem - Updated item value.\n\t *\n\t * @eventProperty\n\t */\n\titemUpdated: (updatedItem: LatestMapItemValueClientData<T, K>) => void;\n\n\t/**\n\t * Raised when specific item is removed.\n\t * @param removedItem - Removed item.\n\t *\n\t * @eventProperty\n\t */\n\titemRemoved: (removedItem: LatestMapItemRemovedClientData<K>) => void;\n}\n\n/**\n * Map of local client's values. Modifications are transmitted to all other connected clients.\n *\n * @sealed\n * @alpha\n */\nexport interface ValueMap<K extends string | number, V> {\n\t/**\n\t * ${@link ValueMap.delete}s all elements in the ValueMap.\n\t * @remarks This is not yet implemented.\n\t */\n\tclear(): void;\n\n\t/**\n\t * @returns true if an element in the ValueMap existed and has been removed, or false if\n\t * the element does not exist.\n\t * @remarks No entry is fully removed. Instead an undefined placeholder is locally and\n\t * transmitted to all other clients. For better performance limit the number of deleted\n\t * entries and reuse keys when possible.\n\t * @privateRemarks In the future we may add a mechanism to remove the placeholder, at least\n\t * from transmissions after sufficient time has passed.\n\t */\n\tdelete(key: K): boolean;\n\n\t/**\n\t * Executes a provided function once per each key/value pair in the ValueMap, in arbitrary order.\n\t */\n\tforEach(\n\t\tcallbackfn: (\n\t\t\tvalue: InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>,\n\t\t\tkey: K,\n\t\t\tmap: ValueMap<K, V>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void;\n\n\t/**\n\t * Returns a specified element from the ValueMap object.\n\t * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.\n\t */\n\tget(key: K): InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>> | undefined;\n\n\t/**\n\t * @returns boolean indicating whether an element with the specified key exists or not.\n\t */\n\thas(key: K): boolean;\n\n\t/**\n\t * Adds a new element with a specified key and value to the ValueMap. If an element with the same key already exists, the element will be updated.\n\t * The value will be transmitted to all other connected clients.\n\t *\n\t * @remarks Manager assumes ownership of the value and its references.\n\t * Make a deep clone before setting, if needed. No comparison is done to detect changes; all\n\t * sets are transmitted.\n\t */\n\tset(key: K, value: JsonSerializable<V> & JsonDeserialized<V>): this;\n\n\t/**\n\t * @returns the number of elements in the ValueMap.\n\t */\n\treadonly size: number;\n\n\t/**\n\t * Returns an iterable of entries in the map.\n\t */\n\t// [Symbol.iterator](): IterableIterator<[K, InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of key, value pairs for every entry in the map.\n\t */\n\t// entries(): IterableIterator<[K, InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>]>;\n\n\t/**\n\t * Returns an iterable of keys in the map.\n\t */\n\tkeys(): IterableIterator<K>;\n\n\t/**\n\t * Returns an iterable of values in the map.\n\t */\n\t// values(): IterableIterator<InternalUtilityTypes.FullyReadonly<JsonDeserialized<V>>>;\n}\n\nclass ValueMapImpl<T, K extends string | number> implements ValueMap<K, T> {\n\tprivate countDefined: number;\n\tpublic constructor(\n\t\tprivate readonly value: InternalTypes.MapValueState<T>,\n\t\tprivate readonly localUpdate: (updates: InternalTypes.MapValueState<T>) => void,\n\t) {\n\t\t// All initial items are expected to be defined.\n\t\t// TODO assert all defined and/or update type.\n\t\tthis.countDefined = Object.keys(value.items).length;\n\t}\n\n\tprivate updateItem(key: K, value: InternalTypes.ValueOptionalState<T>[\"value\"]): void {\n\t\tthis.value.rev += 1;\n\t\tconst item = this.value.items[key];\n\t\titem.rev += 1;\n\t\titem.timestamp = Date.now();\n\t\tif (value === undefined) {\n\t\t\tdelete item.value;\n\t\t} else {\n\t\t\titem.value = value;\n\t\t}\n\t\tconst update = { rev: this.value.rev, items: { [key]: item } };\n\t\tthis.localUpdate(update);\n\t}\n\n\tpublic clear(): void {\n\t\tthrow new Error(\"Method not implemented.\");\n\t}\n\tpublic delete(key: K): boolean {\n\t\tconst { items } = this.value;\n\t\tconst hasKey = items[key]?.value !== undefined;\n\t\tif (hasKey) {\n\t\t\tthis.countDefined -= 1;\n\t\t\tthis.updateItem(key, undefined);\n\t\t}\n\t\treturn hasKey;\n\t}\n\tpublic forEach(\n\t\tcallbackfn: (\n\t\t\tvalue: InternalUtilityTypes.FullyReadonly<JsonDeserialized<T>>,\n\t\t\tkey: K,\n\t\t\tmap: ValueMap<K, T>,\n\t\t) => void,\n\t\tthisArg?: unknown,\n\t): void {\n\t\tfor (const [key, item] of Object.entries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\t// TODO: see about typing InternalTypes.MapValueState with K\n\t\t\t\tcallbackfn(item.value, key as K, this);\n\t\t\t}\n\t\t}\n\t}\n\tpublic get(key: K): InternalUtilityTypes.FullyReadonly<JsonDeserialized<T>> | undefined {\n\t\treturn this.value.items[key]?.value;\n\t}\n\tpublic has(key: K): boolean {\n\t\treturn this.value.items[key]?.value !== undefined;\n\t}\n\tpublic set(key: K, value: JsonSerializable<T> & JsonDeserialized<T>): this {\n\t\tif (!(key in this.value.items)) {\n\t\t\tthis.countDefined += 1;\n\t\t\tthis.value.items[key] = { rev: 0, timestamp: 0, value };\n\t\t}\n\t\tthis.updateItem(key, value);\n\t\treturn this;\n\t}\n\tpublic get size(): number {\n\t\treturn this.countDefined;\n\t}\n\tpublic keys(): IterableIterator<K> {\n\t\tconst keys: K[] = [];\n\t\tfor (const [key, item] of Object.entries(this.value.items)) {\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tkeys.push(key as K);\n\t\t\t}\n\t\t}\n\t\treturn keys[Symbol.iterator]();\n\t}\n}\n\n/**\n * Value manager that provides a `Map` of latest known values from this client to\n * others and read access to their values.\n * Entries in the map may vary over time and by client, but all values are expected to\n * be of the same type, which may be a union type.\n *\n * @remarks Create using {@link LatestMap} registered to {@link PresenceStates}.\n *\n * @sealed\n * @alpha\n */\nexport interface LatestMapValueManager<T, Keys extends string | number = string | number> {\n\t/**\n\t * Events for LatestMap value manager.\n\t */\n\treadonly events: Listenable<LatestMapValueManagerEvents<T, Keys>>;\n\n\t/**\n\t * Controls for management of sending updates.\n\t */\n\treadonly controls: BroadcastControls;\n\n\t/**\n\t * Current value map for this client.\n\t */\n\treadonly local: ValueMap<Keys, T>;\n\t/**\n\t * Iterable access to remote clients' map of values.\n\t */\n\tclientValues(): IterableIterator<LatestMapValueClientData<T, Keys>>;\n\t/**\n\t * Array of known clients.\n\t */\n\tclients(): ISessionClient[];\n\t/**\n\t * Access to a specific client's map of values.\n\t */\n\tclientValue(client: ISessionClient): ReadonlyMap<Keys, LatestValueData<T>>;\n}\n\nclass LatestMapValueManagerImpl<\n\tT,\n\tRegistrationKey extends string,\n\tKeys extends string | number = string | number,\n> implements\n\t\tLatestMapValueManager<T, Keys>,\n\t\tRequired<ValueManager<T, InternalTypes.MapValueState<T>>>\n{\n\tpublic readonly events = createEmitter<LatestMapValueManagerEvents<T, Keys>>();\n\tpublic readonly controls: OptionalBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly key: RegistrationKey,\n\t\tprivate readonly datastore: StateDatastore<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T>\n\t\t>,\n\t\tpublic readonly value: InternalTypes.MapValueState<T>,\n\t\tcontrolSettings: BroadcastControlSettings | undefined,\n\t) {\n\t\tthis.controls = new OptionalBroadcastControl(controlSettings);\n\n\t\tthis.local = new ValueMapImpl<T, Keys>(\n\t\t\tvalue,\n\t\t\t(updates: InternalTypes.MapValueState<T>) => {\n\t\t\t\tdatastore.localUpdate(key, updates, {\n\t\t\t\t\tallowableUpdateLatencyMs: this.controls.allowableUpdateLatencyMs,\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic readonly local: ValueMap<Keys, T>;\n\n\tpublic *clientValues(): IterableIterator<LatestMapValueClientData<T, Keys>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tfor (const clientSessionId of Object.keys(allKnownStates.states)) {\n\t\t\tif (clientSessionId !== allKnownStates.self) {\n\t\t\t\tconst client = this.datastore.lookupClient(clientSessionId);\n\t\t\t\tconst items = this.clientValue(client);\n\t\t\t\tyield { client, items };\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic clients(): ISessionClient[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\treturn Object.keys(allKnownStates.states)\n\t\t\t.filter((clientSessionId) => clientSessionId !== allKnownStates.self)\n\t\t\t.map((clientSessionId) => this.datastore.lookupClient(clientSessionId));\n\t}\n\n\tpublic clientValue(client: ISessionClient): ReadonlyMap<Keys, LatestValueData<T>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst clientSessionId = client.sessionId;\n\t\tif (!(clientSessionId in allKnownStates.states)) {\n\t\t\tthrow new Error(\"No entry for client\");\n\t\t}\n\t\tconst clientStateMap = allKnownStates.states[clientSessionId];\n\t\tconst items = new Map<Keys, LatestValueData<T>>();\n\t\tfor (const [key, item] of Object.entries(clientStateMap.items)) {\n\t\t\tconst value = item.value;\n\t\t\tif (value !== undefined) {\n\t\t\t\titems.set(key as Keys, {\n\t\t\t\t\tvalue,\n\t\t\t\t\tmetadata: { revision: item.rev, timestamp: item.timestamp },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn items;\n\t}\n\n\tpublic update<SpecificSessionClientId extends ClientSessionId>(\n\t\tclient: SpecificSessionClient<SpecificSessionClientId>,\n\t\t_received: number,\n\t\tvalue: InternalTypes.MapValueState<T>,\n\t): void {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst clientSessionId: SpecificSessionClientId = client.sessionId;\n\t\tif (!(clientSessionId in allKnownStates.states)) {\n\t\t\t// New client - prepare new client state directory\n\t\t\tallKnownStates.states[clientSessionId] = { rev: value.rev, items: {} };\n\t\t}\n\t\tconst currentState = allKnownStates.states[clientSessionId];\n\t\t// Accumulate individual update keys\n\t\tconst updatedItemKeys: Keys[] = [];\n\t\tfor (const [key, item] of Object.entries(value.items)) {\n\t\t\tif (!(key in currentState.items) || currentState.items[key].rev < item.rev) {\n\t\t\t\tupdatedItemKeys.push(key as Keys);\n\t\t\t}\n\t\t}\n\n\t\tif (updatedItemKeys.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Store updates\n\t\tif (value.rev > currentState.rev) {\n\t\t\tcurrentState.rev = value.rev;\n\t\t}\n\t\tconst allUpdates = {\n\t\t\tclient,\n\t\t\titems: new Map<Keys, LatestValueData<T>>(),\n\t\t};\n\t\tfor (const key of updatedItemKeys) {\n\t\t\tconst item = value.items[key];\n\t\t\tconst hadPriorValue = currentState.items[key]?.value;\n\t\t\tcurrentState.items[key] = item;\n\t\t\tconst metadata = { revision: item.rev, timestamp: item.timestamp };\n\t\t\tif (item.value !== undefined) {\n\t\t\t\tthis.events.emit(\"itemUpdated\", {\n\t\t\t\t\tclient,\n\t\t\t\t\tkey,\n\t\t\t\t\tvalue: item.value,\n\t\t\t\t\tmetadata,\n\t\t\t\t});\n\t\t\t\tallUpdates.items.set(key, { value: item.value, metadata });\n\t\t\t} else if (hadPriorValue !== undefined) {\n\t\t\t\tthis.events.emit(\"itemRemoved\", {\n\t\t\t\t\tclient,\n\t\t\t\t\tkey,\n\t\t\t\t\tmetadata,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\tthis.datastore.update(this.key, clientSessionId, currentState);\n\t\tthis.events.emit(\"updated\", allUpdates);\n\t}\n}\n\n/**\n * Factory for creating a {@link LatestMapValueManager}.\n *\n * @alpha\n */\nexport function LatestMap<\n\tT extends object,\n\tKeys extends string | number = string | number,\n\tRegistrationKey extends string = string,\n>(\n\tinitialValues?: {\n\t\t[K in Keys]: JsonSerializable<T> & JsonDeserialized<T>;\n\t},\n\tcontrols?: BroadcastControlSettings,\n): InternalTypes.ManagerFactory<\n\tRegistrationKey,\n\tInternalTypes.MapValueState<T>,\n\tLatestMapValueManager<T, Keys>\n> {\n\tconst timestamp = Date.now();\n\tconst value: InternalTypes.MapValueState<T> = { rev: 0, items: {} };\n\t// LatestMapValueManager takes ownership of values within initialValues.\n\tif (initialValues !== undefined) {\n\t\tfor (const key of Object.keys(initialValues)) {\n\t\t\tvalue.items[key] = { rev: 0, timestamp, value: initialValues[key as Keys] };\n\t\t}\n\t}\n\tconst factory = (\n\t\tkey: RegistrationKey,\n\t\tdatastoreHandle: InternalTypes.StateDatastoreHandle<\n\t\t\tRegistrationKey,\n\t\t\tInternalTypes.MapValueState<T>\n\t\t>,\n\t): {\n\t\tinitialData: { value: typeof value; allowableUpdateLatencyMs: number | undefined };\n\t\tmanager: InternalTypes.StateValue<LatestMapValueManager<T, Keys>>;\n\t} => ({\n\t\tinitialData: { value, allowableUpdateLatencyMs: controls?.allowableUpdateLatencyMs },\n\t\tmanager: brandIVM<\n\t\t\tLatestMapValueManagerImpl<T, RegistrationKey, Keys>,\n\t\t\tT,\n\t\t\tInternalTypes.MapValueState<T>\n\t\t>(\n\t\t\tnew LatestMapValueManagerImpl(\n\t\t\t\tkey,\n\t\t\t\tdatastoreFromHandle(datastoreHandle),\n\t\t\t\tvalue,\n\t\t\t\tcontrols,\n\t\t\t),\n\t\t),\n\t});\n\treturn Object.assign(factory, { instanceBase: LatestMapValueManagerImpl });\n}\n"]}