@fluidframework/presence 2.41.0 → 2.43.0-343119
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.
- package/dist/broadcastControls.d.ts +2 -3
- package/dist/broadcastControls.d.ts.map +1 -1
- package/dist/broadcastControls.js +2 -3
- package/dist/broadcastControls.js.map +1 -1
- package/dist/datastorePresenceManagerFactory.d.ts.map +1 -1
- package/dist/datastorePresenceManagerFactory.js +1 -0
- package/dist/datastorePresenceManagerFactory.js.map +1 -1
- package/dist/datastoreSupport.d.ts +7 -2
- package/dist/datastoreSupport.d.ts.map +1 -1
- package/dist/datastoreSupport.js +6 -4
- package/dist/datastoreSupport.js.map +1 -1
- package/dist/exposedInternalTypes.d.ts +22 -4
- package/dist/exposedInternalTypes.d.ts.map +1 -1
- package/dist/exposedInternalTypes.js.map +1 -1
- package/dist/exposedUtilityTypes.d.ts +6 -5
- package/dist/exposedUtilityTypes.d.ts.map +1 -1
- package/dist/exposedUtilityTypes.js.map +1 -1
- package/dist/internalTypes.d.ts +11 -9
- package/dist/internalTypes.d.ts.map +1 -1
- package/dist/internalTypes.js.map +1 -1
- package/dist/internalUtils.d.ts +26 -8
- package/dist/internalUtils.d.ts.map +1 -1
- package/dist/internalUtils.js +35 -8
- package/dist/internalUtils.js.map +1 -1
- package/dist/latestMapValueManager.d.ts +28 -7
- package/dist/latestMapValueManager.d.ts.map +1 -1
- package/dist/latestMapValueManager.js +10 -9
- package/dist/latestMapValueManager.js.map +1 -1
- package/dist/latestValueManager.d.ts +17 -3
- package/dist/latestValueManager.d.ts.map +1 -1
- package/dist/latestValueManager.js +20 -9
- package/dist/latestValueManager.js.map +1 -1
- package/dist/latestValueTypes.d.ts +11 -1
- package/dist/latestValueTypes.d.ts.map +1 -1
- package/dist/latestValueTypes.js.map +1 -1
- package/dist/notificationsManager.d.ts +2 -2
- package/dist/notificationsManager.d.ts.map +1 -1
- package/dist/notificationsManager.js +14 -7
- package/dist/notificationsManager.js.map +1 -1
- package/dist/presence.d.ts +7 -5
- package/dist/presence.d.ts.map +1 -1
- package/dist/presence.js.map +1 -1
- package/dist/presenceDatastoreManager.d.ts +5 -6
- package/dist/presenceDatastoreManager.d.ts.map +1 -1
- package/dist/presenceDatastoreManager.js +19 -7
- package/dist/presenceDatastoreManager.js.map +1 -1
- package/dist/presenceManager.d.ts +0 -4
- package/dist/presenceManager.d.ts.map +1 -1
- package/dist/presenceManager.js +1 -3
- package/dist/presenceManager.js.map +1 -1
- package/dist/presenceStates.d.ts +9 -14
- package/dist/presenceStates.d.ts.map +1 -1
- package/dist/presenceStates.js +1 -8
- package/dist/presenceStates.js.map +1 -1
- package/dist/protocol.d.ts +37 -12
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +7 -3
- package/dist/protocol.js.map +1 -1
- package/dist/stateDatastore.d.ts +9 -8
- package/dist/stateDatastore.d.ts.map +1 -1
- package/dist/stateDatastore.js +0 -4
- package/dist/stateDatastore.js.map +1 -1
- package/dist/systemWorkspace.d.ts +12 -6
- package/dist/systemWorkspace.d.ts.map +1 -1
- package/dist/systemWorkspace.js +14 -4
- package/dist/systemWorkspace.js.map +1 -1
- package/dist/types.d.ts +3 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/valueManager.d.ts +0 -4
- package/dist/valueManager.d.ts.map +1 -1
- package/dist/valueManager.js +0 -4
- package/dist/valueManager.js.map +1 -1
- package/lib/broadcastControls.d.ts +2 -3
- package/lib/broadcastControls.d.ts.map +1 -1
- package/lib/broadcastControls.js +2 -3
- package/lib/broadcastControls.js.map +1 -1
- package/lib/datastorePresenceManagerFactory.d.ts.map +1 -1
- package/lib/datastorePresenceManagerFactory.js +1 -0
- package/lib/datastorePresenceManagerFactory.js.map +1 -1
- package/lib/datastoreSupport.d.ts +7 -2
- package/lib/datastoreSupport.d.ts.map +1 -1
- package/lib/datastoreSupport.js +6 -4
- package/lib/datastoreSupport.js.map +1 -1
- package/lib/exposedInternalTypes.d.ts +22 -4
- package/lib/exposedInternalTypes.d.ts.map +1 -1
- package/lib/exposedInternalTypes.js.map +1 -1
- package/lib/exposedUtilityTypes.d.ts +6 -5
- package/lib/exposedUtilityTypes.d.ts.map +1 -1
- package/lib/exposedUtilityTypes.js.map +1 -1
- package/lib/internalTypes.d.ts +11 -9
- package/lib/internalTypes.d.ts.map +1 -1
- package/lib/internalTypes.js.map +1 -1
- package/lib/internalUtils.d.ts +26 -8
- package/lib/internalUtils.d.ts.map +1 -1
- package/lib/internalUtils.js +31 -7
- package/lib/internalUtils.js.map +1 -1
- package/lib/latestMapValueManager.d.ts +28 -7
- package/lib/latestMapValueManager.d.ts.map +1 -1
- package/lib/latestMapValueManager.js +11 -10
- package/lib/latestMapValueManager.js.map +1 -1
- package/lib/latestValueManager.d.ts +17 -3
- package/lib/latestValueManager.d.ts.map +1 -1
- package/lib/latestValueManager.js +19 -9
- package/lib/latestValueManager.js.map +1 -1
- package/lib/latestValueTypes.d.ts +11 -1
- package/lib/latestValueTypes.d.ts.map +1 -1
- package/lib/latestValueTypes.js.map +1 -1
- package/lib/notificationsManager.d.ts +2 -2
- package/lib/notificationsManager.d.ts.map +1 -1
- package/lib/notificationsManager.js +14 -7
- package/lib/notificationsManager.js.map +1 -1
- package/lib/presence.d.ts +7 -5
- package/lib/presence.d.ts.map +1 -1
- package/lib/presence.js.map +1 -1
- package/lib/presenceDatastoreManager.d.ts +5 -6
- package/lib/presenceDatastoreManager.d.ts.map +1 -1
- package/lib/presenceDatastoreManager.js +20 -8
- package/lib/presenceDatastoreManager.js.map +1 -1
- package/lib/presenceManager.d.ts +0 -4
- package/lib/presenceManager.d.ts.map +1 -1
- package/lib/presenceManager.js +1 -3
- package/lib/presenceManager.js.map +1 -1
- package/lib/presenceStates.d.ts +9 -14
- package/lib/presenceStates.d.ts.map +1 -1
- package/lib/presenceStates.js +1 -8
- package/lib/presenceStates.js.map +1 -1
- package/lib/protocol.d.ts +37 -12
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +6 -2
- package/lib/protocol.js.map +1 -1
- package/lib/stateDatastore.d.ts +9 -8
- package/lib/stateDatastore.d.ts.map +1 -1
- package/lib/stateDatastore.js +0 -4
- package/lib/stateDatastore.js.map +1 -1
- package/lib/systemWorkspace.d.ts +12 -6
- package/lib/systemWorkspace.d.ts.map +1 -1
- package/lib/systemWorkspace.js +14 -4
- package/lib/systemWorkspace.js.map +1 -1
- package/lib/types.d.ts +3 -2
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/valueManager.d.ts +0 -4
- package/lib/valueManager.d.ts.map +1 -1
- package/lib/valueManager.js +0 -4
- package/lib/valueManager.js.map +1 -1
- package/package.json +17 -17
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"latestValueManager.js","sourceRoot":"","sources":["../src/latestValueManager.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 { createEmitter } from \"@fluid-internal/client-utils\";\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type {\n\tDeepReadonly,\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\nimport { shallowCloneObject } from \"@fluidframework/core-utils/internal\";\n\nimport type { BroadcastControls, BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { OptionalBroadcastControl } from \"./broadcastControls.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type { PostUpdateAction, ValueManager } from \"./internalTypes.js\";\nimport { asDeeplyReadonly, objectEntries } from \"./internalUtils.js\";\nimport type { LatestClientData, LatestData } from \"./latestValueTypes.js\";\nimport type { Attendee, Presence } from \"./presence.js\";\nimport { datastoreFromHandle, type StateDatastore } from \"./stateDatastore.js\";\nimport { brandIVM } from \"./valueManager.js\";\n\n/**\n * @sealed\n * @beta\n */\nexport interface LatestRawEvents<T> {\n\t/**\n\t * Raised when remote client's value is updated, which may be the same value.\n\t *\n\t * @eventProperty\n\t */\n\tremoteUpdated: (update: LatestClientData<T>) => void;\n\n\t/**\n\t * Raised when local client's value is updated, which may be the same value.\n\t *\n\t * @eventProperty\n\t */\n\tlocalUpdated: (update: {\n\t\tvalue: DeepReadonly<JsonSerializable<T> & JsonDeserialized<T>>;\n\t}) => void;\n}\n\n/**\n * State that provides the latest known value from this client to others and read access to their values.\n * All participant clients must provide a value.\n *\n * @remarks Create using {@link StateFactory.latest} registered to {@link StatesWorkspace}.\n *\n * @sealed\n * @beta\n */\nexport interface LatestRaw<T> {\n\t/**\n\t * Containing {@link Presence}\n\t */\n\treadonly presence: Presence;\n\n\t/**\n\t * Events for LatestRaw.\n\t */\n\treadonly events: Listenable<LatestRawEvents<T>>;\n\n\t/**\n\t * Controls for management of sending updates.\n\t */\n\treadonly controls: BroadcastControls;\n\n\t/**\n\t * Current state for this client.\n\t * State for this client that will be transmitted to all other connected clients.\n\t * @remarks Manager assumes ownership of the value and its references. Make a deep clone before\n\t * setting, if needed. No comparison is done to detect changes; all sets are transmitted.\n\t */\n\tget local(): DeepReadonly<JsonDeserialized<T>>;\n\tset local(value: JsonSerializable<T> & JsonDeserialized<T>);\n\n\t/**\n\t * Iterable access to remote clients' values.\n\t */\n\tgetRemotes(): IterableIterator<LatestClientData<T>>;\n\t/**\n\t * Array of {@link Attendee}s that have provided states.\n\t */\n\tgetStateAttendees(): Attendee[];\n\t/**\n\t * Access to a specific attendee's value.\n\t */\n\tgetRemote(attendee: Attendee): LatestData<T>;\n}\n\nclass LatestValueManagerImpl<T, Key extends string>\n\timplements LatestRaw<T>, Required<ValueManager<T, InternalTypes.ValueRequiredState<T>>>\n{\n\tpublic readonly events = createEmitter<LatestRawEvents<T>>();\n\tpublic readonly controls: OptionalBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly key: Key,\n\t\tprivate readonly datastore: StateDatastore<Key, InternalTypes.ValueRequiredState<T>>,\n\t\tpublic readonly value: InternalTypes.ValueRequiredState<T>,\n\t\tcontrolSettings: BroadcastControlSettings | undefined,\n\t) {\n\t\tthis.controls = new OptionalBroadcastControl(controlSettings);\n\t}\n\n\tpublic get presence(): Presence {\n\t\treturn this.datastore.presence;\n\t}\n\n\tpublic get local(): DeepReadonly<JsonDeserialized<T>> {\n\t\treturn asDeeplyReadonly(this.value.value);\n\t}\n\n\tpublic set local(value: JsonSerializable<T> & JsonDeserialized<T>) {\n\t\tthis.value.rev += 1;\n\t\tthis.value.timestamp = Date.now();\n\t\tthis.value.value = value;\n\t\tthis.datastore.localUpdate(this.key, this.value, {\n\t\t\tallowableUpdateLatencyMs: this.controls.allowableUpdateLatencyMs,\n\t\t});\n\n\t\tthis.events.emit(\"localUpdated\", { value: asDeeplyReadonly(value) });\n\t}\n\n\tpublic *getRemotes(): IterableIterator<LatestClientData<T>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tfor (const [attendeeId, value] of objectEntries(allKnownStates.states)) {\n\t\t\tif (attendeeId !== allKnownStates.self) {\n\t\t\t\tyield {\n\t\t\t\t\tattendee: this.datastore.lookupClient(attendeeId),\n\t\t\t\t\tvalue: asDeeplyReadonly(value.value),\n\t\t\t\t\tmetadata: { revision: value.rev, timestamp: value.timestamp },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic getStateAttendees(): Attendee[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\treturn Object.keys(allKnownStates.states)\n\t\t\t.filter((attendeeId) => attendeeId !== allKnownStates.self)\n\t\t\t.map((attendeeId) => this.datastore.lookupClient(attendeeId));\n\t}\n\n\tpublic getRemote(attendee: Attendee): LatestData<T> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst clientState = allKnownStates.states[attendee.attendeeId];\n\t\tif (clientState === undefined) {\n\t\t\tthrow new Error(\"No entry for clientId\");\n\t\t}\n\t\treturn {\n\t\t\tvalue: asDeeplyReadonly(clientState.value),\n\t\t\tmetadata: { revision: clientState.rev, timestamp: Date.now() },\n\t\t};\n\t}\n\n\tpublic update(\n\t\tattendee: Attendee,\n\t\t_received: number,\n\t\tvalue: InternalTypes.ValueRequiredState<T>,\n\t): PostUpdateAction[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst attendeeId = attendee.attendeeId;\n\t\tconst currentState = allKnownStates.states[attendeeId];\n\t\tif (currentState !== undefined && currentState.rev >= value.rev) {\n\t\t\treturn [];\n\t\t}\n\t\tthis.datastore.update(this.key, attendeeId, value);\n\t\treturn [\n\t\t\t() =>\n\t\t\t\tthis.events.emit(\"remoteUpdated\", {\n\t\t\t\t\tattendee,\n\t\t\t\t\tvalue: asDeeplyReadonly(value.value),\n\t\t\t\t\tmetadata: { revision: value.rev, timestamp: value.timestamp },\n\t\t\t\t}),\n\t\t];\n\t}\n}\n\n/**\n * Arguments that are passed to the {@link StateFactory.latest} function.\n *\n * @beta\n */\nexport interface LatestArguments<T extends object | null> {\n\t/**\n\t * The initial value of the local state.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tlocal: JsonSerializable<T> & JsonDeserialized<T> & (object | null);\n\n\t/**\n\t * See {@link BroadcastControlSettings}.\n\t */\n\tsettings?: BroadcastControlSettings | undefined;\n}\n\n/**\n * Factory for creating a {@link LatestRaw} State object.\n *\n * @beta\n */\nexport function latest<T extends object | null, Key extends string = string>(\n\targs: LatestArguments<T>,\n): InternalTypes.ManagerFactory<Key, InternalTypes.ValueRequiredState<T>, LatestRaw<T>> {\n\tconst { local, settings } = args;\n\n\t// Latest takes ownership of the initial local value but makes a shallow\n\t// copy for basic protection.\n\tconst value: InternalTypes.ValueRequiredState<T> = {\n\t\trev: 0,\n\t\ttimestamp: Date.now(),\n\t\tvalue: local === null ? local : shallowCloneObject(local),\n\t};\n\tconst factory = (\n\t\tkey: Key,\n\t\tdatastoreHandle: InternalTypes.StateDatastoreHandle<\n\t\t\tKey,\n\t\t\tInternalTypes.ValueRequiredState<T>\n\t\t>,\n\t): {\n\t\tinitialData: { value: typeof value; allowableUpdateLatencyMs: number | undefined };\n\t\tmanager: InternalTypes.StateValue<LatestRaw<T>>;\n\t} => ({\n\t\tinitialData: { value, allowableUpdateLatencyMs: settings?.allowableUpdateLatencyMs },\n\t\tmanager: brandIVM<LatestValueManagerImpl<T, Key>, T, InternalTypes.ValueRequiredState<T>>(\n\t\t\tnew LatestValueManagerImpl(key, datastoreFromHandle(datastoreHandle), value, settings),\n\t\t),\n\t});\n\treturn Object.assign(factory, { instanceBase: LatestValueManagerImpl });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"latestValueManager.js","sourceRoot":"","sources":["../src/latestValueManager.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 { createEmitter } from \"@fluid-internal/client-utils\";\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type {\n\tDeepReadonly,\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\nimport { shallowCloneObject } from \"@fluidframework/core-utils/internal\";\n\nimport type { BroadcastControls, BroadcastControlSettings } from \"./broadcastControls.js\";\nimport { OptionalBroadcastControl } from \"./broadcastControls.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type { PostUpdateAction, ValueManager } from \"./internalTypes.js\";\nimport {\n\tasDeeplyReadonly,\n\tasDeeplyReadonlyDeserializedJson,\n\tobjectEntries,\n\ttoOpaqueJson,\n} from \"./internalUtils.js\";\nimport type { LatestClientData, LatestData } from \"./latestValueTypes.js\";\nimport type { Attendee, Presence } from \"./presence.js\";\nimport { datastoreFromHandle, type StateDatastore } from \"./stateDatastore.js\";\nimport { brandIVM } from \"./valueManager.js\";\n\n/**\n * Events from {@link LatestRaw}.\n *\n * @sealed\n * @beta\n */\nexport interface LatestRawEvents<T> {\n\t/**\n\t * Raised when remote client's value is updated, which may be the same value.\n\t *\n\t * @eventProperty\n\t */\n\tremoteUpdated: (update: LatestClientData<T>) => void;\n\n\t/**\n\t * Raised when local client's value is updated, which may be the same value.\n\t *\n\t * @eventProperty\n\t */\n\tlocalUpdated: (update: {\n\t\tvalue: DeepReadonly<JsonSerializable<T>>;\n\t}) => void;\n}\n\n/**\n * State that provides the latest known value from this client to others and read access to their values.\n * All participant clients must provide a value.\n *\n * @remarks Create using {@link StateFactory.latest} registered to {@link StatesWorkspace}.\n *\n * @sealed\n * @beta\n */\nexport interface LatestRaw<T> {\n\t/**\n\t * Containing {@link Presence}\n\t */\n\treadonly presence: Presence;\n\n\t/**\n\t * Events for LatestRaw.\n\t */\n\treadonly events: Listenable<LatestRawEvents<T>>;\n\n\t/**\n\t * Controls for management of sending updates.\n\t */\n\treadonly controls: BroadcastControls;\n\n\t/**\n\t * Current state for this client.\n\t * State for this client that will be transmitted to all other connected clients.\n\t * @remarks Manager assumes ownership of the value and its references. Make a deep clone before\n\t * setting, if needed. No comparison is done to detect changes; all sets are transmitted.\n\t */\n\tget local(): DeepReadonly<JsonDeserialized<T>>;\n\tset local(value: JsonSerializable<T>);\n\n\t/**\n\t * Iterable access to remote clients' values.\n\t */\n\tgetRemotes(): IterableIterator<LatestClientData<T>>;\n\t/**\n\t * Array of {@link Attendee}s that have provided states.\n\t */\n\tgetStateAttendees(): Attendee[];\n\t/**\n\t * Access to a specific attendee's value.\n\t */\n\tgetRemote(attendee: Attendee): LatestData<T>;\n}\n\nclass LatestValueManagerImpl<T, Key extends string>\n\timplements LatestRaw<T>, Required<ValueManager<T, InternalTypes.ValueRequiredState<T>>>\n{\n\tpublic readonly events = createEmitter<LatestRawEvents<T>>();\n\tpublic readonly controls: OptionalBroadcastControl;\n\n\tpublic constructor(\n\t\tprivate readonly key: Key,\n\t\tprivate readonly datastore: StateDatastore<Key, InternalTypes.ValueRequiredState<T>>,\n\t\tpublic readonly value: InternalTypes.ValueRequiredState<T>,\n\t\tcontrolSettings: BroadcastControlSettings | undefined,\n\t) {\n\t\tthis.controls = new OptionalBroadcastControl(controlSettings);\n\t}\n\n\tpublic get presence(): Presence {\n\t\treturn this.datastore.presence;\n\t}\n\n\tpublic get local(): DeepReadonly<JsonDeserialized<T>> {\n\t\treturn asDeeplyReadonlyDeserializedJson(this.value.value);\n\t}\n\n\tpublic set local(value: JsonSerializable<T>) {\n\t\tthis.value.rev += 1;\n\t\tthis.value.timestamp = Date.now();\n\t\tthis.value.value = toOpaqueJson<T>(value);\n\t\tthis.datastore.localUpdate(this.key, this.value, {\n\t\t\tallowableUpdateLatencyMs: this.controls.allowableUpdateLatencyMs,\n\t\t});\n\n\t\tthis.events.emit(\"localUpdated\", { value: asDeeplyReadonly(value) });\n\t}\n\n\tpublic *getRemotes(): IterableIterator<LatestClientData<T>> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tfor (const [attendeeId, value] of objectEntries(allKnownStates.states)) {\n\t\t\tif (attendeeId !== allKnownStates.self) {\n\t\t\t\tyield {\n\t\t\t\t\tattendee: this.datastore.presence.attendees.getAttendee(attendeeId),\n\t\t\t\t\tvalue: asDeeplyReadonlyDeserializedJson(value.value),\n\t\t\t\t\tmetadata: { revision: value.rev, timestamp: value.timestamp },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic getStateAttendees(): Attendee[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\treturn Object.keys(allKnownStates.states)\n\t\t\t.filter((attendeeId) => attendeeId !== allKnownStates.self)\n\t\t\t.map((attendeeId) => this.datastore.presence.attendees.getAttendee(attendeeId));\n\t}\n\n\tpublic getRemote(attendee: Attendee): LatestData<T> {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst clientState = allKnownStates.states[attendee.attendeeId];\n\t\tif (clientState === undefined) {\n\t\t\tthrow new Error(\"No entry for clientId\");\n\t\t}\n\t\treturn {\n\t\t\tvalue: asDeeplyReadonlyDeserializedJson(clientState.value),\n\t\t\tmetadata: { revision: clientState.rev, timestamp: Date.now() },\n\t\t};\n\t}\n\n\tpublic update(\n\t\tattendee: Attendee,\n\t\t_received: number,\n\t\tvalue: InternalTypes.ValueRequiredState<T>,\n\t): PostUpdateAction[] {\n\t\tconst allKnownStates = this.datastore.knownValues(this.key);\n\t\tconst attendeeId = attendee.attendeeId;\n\t\tconst currentState = allKnownStates.states[attendeeId];\n\t\tif (currentState !== undefined && currentState.rev >= value.rev) {\n\t\t\treturn [];\n\t\t}\n\t\tthis.datastore.update(this.key, attendeeId, value);\n\t\treturn [\n\t\t\t() =>\n\t\t\t\tthis.events.emit(\"remoteUpdated\", {\n\t\t\t\t\tattendee,\n\t\t\t\t\tvalue: asDeeplyReadonlyDeserializedJson(value.value),\n\t\t\t\t\tmetadata: { revision: value.rev, timestamp: value.timestamp },\n\t\t\t\t}),\n\t\t];\n\t}\n}\n\n/**\n * Shallow clone an object that might be null.\n *\n * @param value - The object to clone\n * @returns A shallow clone of the input value\n */\nexport function shallowCloneNullableObject<T extends object | null>(value: T): T {\n\treturn value === null ? value : shallowCloneObject(value);\n}\n\n/**\n * Arguments that are passed to the {@link StateFactory.latest} function.\n *\n * @input\n * @beta\n */\nexport interface LatestArguments<T extends object | null> {\n\t/**\n\t * The initial value of the local state.\n\t *\n\t * @remarks\n\t * `latest` assumes ownership of the value and its references.\n\t * Make a deep clone before passing, if needed.\n\t */\n\tlocal: JsonSerializable<T>;\n\n\t/**\n\t * See {@link BroadcastControlSettings}.\n\t */\n\tsettings?: BroadcastControlSettings | undefined;\n}\n\n/**\n * Factory for creating a {@link LatestRaw} State object.\n *\n * @beta\n */\nexport function latest<T extends object | null, Key extends string = string>(\n\targs: LatestArguments<T>,\n): InternalTypes.ManagerFactory<Key, InternalTypes.ValueRequiredState<T>, LatestRaw<T>> {\n\tconst { local, settings } = args;\n\n\t// Latest takes ownership of the initial local value but makes a shallow\n\t// copy for basic protection.\n\tconst opaqueLocal = toOpaqueJson<T>(local);\n\tconst value: InternalTypes.ValueRequiredState<T> = {\n\t\trev: 0,\n\t\ttimestamp: Date.now(),\n\t\tvalue: shallowCloneNullableObject(opaqueLocal),\n\t};\n\tconst factory = (\n\t\tkey: Key,\n\t\tdatastoreHandle: InternalTypes.StateDatastoreHandle<\n\t\t\tKey,\n\t\t\tInternalTypes.ValueRequiredState<T>\n\t\t>,\n\t): {\n\t\tinitialData: { value: typeof value; allowableUpdateLatencyMs: number | undefined };\n\t\tmanager: InternalTypes.StateValue<LatestRaw<T>>;\n\t} => ({\n\t\tinitialData: { value, allowableUpdateLatencyMs: settings?.allowableUpdateLatencyMs },\n\t\tmanager: brandIVM<LatestValueManagerImpl<T, Key>, T, InternalTypes.ValueRequiredState<T>>(\n\t\t\tnew LatestValueManagerImpl(key, datastoreFromHandle(datastoreHandle), value, settings),\n\t\t),\n\t});\n\treturn Object.assign(factory, { instanceBase: LatestValueManagerImpl });\n}\n"]}
|
|
@@ -28,16 +28,26 @@ export interface LatestMetadata {
|
|
|
28
28
|
* @beta
|
|
29
29
|
*/
|
|
30
30
|
export interface LatestData<T> {
|
|
31
|
+
/**
|
|
32
|
+
* The value of the state.
|
|
33
|
+
* @remarks This is a deeply readonly value, meaning it cannot be modified.
|
|
34
|
+
*/
|
|
31
35
|
value: DeepReadonly<JsonDeserialized<T>>;
|
|
36
|
+
/**
|
|
37
|
+
* Metadata associated with the value.
|
|
38
|
+
*/
|
|
32
39
|
metadata: LatestMetadata;
|
|
33
40
|
}
|
|
34
41
|
/**
|
|
35
|
-
* State of a specific
|
|
42
|
+
* State of a specific {@link Attendee}'s value and its metadata.
|
|
36
43
|
*
|
|
37
44
|
* @sealed
|
|
38
45
|
* @beta
|
|
39
46
|
*/
|
|
40
47
|
export interface LatestClientData<T> extends LatestData<T> {
|
|
48
|
+
/**
|
|
49
|
+
* Associated {@link Attendee}.
|
|
50
|
+
*/
|
|
41
51
|
attendee: Attendee;
|
|
42
52
|
}
|
|
43
53
|
//# sourceMappingURL=latestValueTypes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"latestValueTypes.d.ts","sourceRoot":"","sources":["../src/latestValueTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,YAAY,EACZ,gBAAgB,EAChB,MAAM,8DAA8D,CAAC;AAEtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC9B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC5B,KAAK,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"latestValueTypes.d.ts","sourceRoot":"","sources":["../src/latestValueTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,YAAY,EACZ,gBAAgB,EAChB,MAAM,8DAA8D,CAAC;AAEtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC9B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC5B;;;OAGG;IACH,KAAK,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzC;;OAEG;IACH,QAAQ,EAAE,cAAc,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,CAAC,CAAC;IACzD;;OAEG;IACH,QAAQ,EAAE,QAAQ,CAAC;CACnB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"latestValueTypes.js","sourceRoot":"","sources":["../src/latestValueTypes.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\tDeepReadonly,\n\tJsonDeserialized,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\n\nimport type { Attendee } from \"./presence.js\";\n\n/**\n * Metadata for the value state.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMetadata {\n\t/**\n\t * The revision number for value that increases as value is changed.\n\t */\n\trevision: number;\n\t/**\n\t * Local time when the value was last updated.\n\t * @remarks Currently this is a placeholder for future implementation.\n\t */\n\ttimestamp: number;\n}\n\n/**\n * State of a value and its metadata.\n *\n * @sealed\n * @beta\n */\nexport interface LatestData<T> {\n\tvalue: DeepReadonly<JsonDeserialized<T>>;\n\tmetadata: LatestMetadata;\n}\n\n/**\n * State of a specific
|
|
1
|
+
{"version":3,"file":"latestValueTypes.js","sourceRoot":"","sources":["../src/latestValueTypes.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\tDeepReadonly,\n\tJsonDeserialized,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\n\nimport type { Attendee } from \"./presence.js\";\n\n/**\n * Metadata for the value state.\n *\n * @sealed\n * @beta\n */\nexport interface LatestMetadata {\n\t/**\n\t * The revision number for value that increases as value is changed.\n\t */\n\trevision: number;\n\t/**\n\t * Local time when the value was last updated.\n\t * @remarks Currently this is a placeholder for future implementation.\n\t */\n\ttimestamp: number;\n}\n\n/**\n * State of a value and its metadata.\n *\n * @sealed\n * @beta\n */\nexport interface LatestData<T> {\n\t/**\n\t * The value of the state.\n\t * @remarks This is a deeply readonly value, meaning it cannot be modified.\n\t */\n\tvalue: DeepReadonly<JsonDeserialized<T>>;\n\n\t/**\n\t * Metadata associated with the value.\n\t */\n\tmetadata: LatestMetadata;\n}\n\n/**\n * State of a specific {@link Attendee}'s value and its metadata.\n *\n * @sealed\n * @beta\n */\nexport interface LatestClientData<T> extends LatestData<T> {\n\t/**\n\t * Associated {@link Attendee}.\n\t */\n\tattendee: Attendee;\n}\n"]}
|
|
@@ -69,14 +69,14 @@ export interface NotificationEmitter<E extends InternalUtilityTypes.Notification
|
|
|
69
69
|
* @param notificationName - the name of the notification to fire
|
|
70
70
|
* @param args - the arguments sent with the notification
|
|
71
71
|
*/
|
|
72
|
-
broadcast<K extends
|
|
72
|
+
broadcast<K extends keyof InternalUtilityTypes.NotificationListeners<E>>(notificationName: K, ...args: Parameters<E[K]>): void;
|
|
73
73
|
/**
|
|
74
74
|
* Emits a notification with the specified name and arguments, notifying a single attendee.
|
|
75
75
|
* @param notificationName - the name of the notification to fire
|
|
76
76
|
* @param targetAttendee - the single attendee to notify
|
|
77
77
|
* @param args - the arguments sent with the notification
|
|
78
78
|
*/
|
|
79
|
-
unicast<K extends
|
|
79
|
+
unicast<K extends keyof InternalUtilityTypes.NotificationListeners<E>>(notificationName: K, targetAttendee: Attendee, ...args: Parameters<E[K]>): void;
|
|
80
80
|
}
|
|
81
81
|
/**
|
|
82
82
|
* Provides notifications from this client to others and subscription
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notificationsManager.d.ts","sourceRoot":"","sources":["../src/notificationsManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAa,UAAU,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAC;AAGlF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"notificationsManager.d.ts","sourceRoot":"","sources":["../src/notificationsManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.Notifications = void 0;
|
|
8
8
|
const client_utils_1 = require("@fluid-internal/client-utils");
|
|
9
|
+
const internalUtils_js_1 = require("./internalUtils.js");
|
|
9
10
|
const stateDatastore_js_1 = require("./stateDatastore.js");
|
|
10
11
|
const valueManager_js_1 = require("./valueManager.js");
|
|
11
12
|
/**
|
|
@@ -23,7 +24,10 @@ class NotificationsManagerImpl {
|
|
|
23
24
|
this.datastore.localUpdate(this.key, {
|
|
24
25
|
rev: 0,
|
|
25
26
|
timestamp: 0,
|
|
26
|
-
value:
|
|
27
|
+
value: (0, internalUtils_js_1.toOpaqueJson)({
|
|
28
|
+
name,
|
|
29
|
+
args: [...args],
|
|
30
|
+
}),
|
|
27
31
|
ignoreUnmonitored: true,
|
|
28
32
|
},
|
|
29
33
|
// This is a notification, so we want to send it immediately.
|
|
@@ -33,7 +37,10 @@ class NotificationsManagerImpl {
|
|
|
33
37
|
this.datastore.localUpdate(this.key, {
|
|
34
38
|
rev: 0,
|
|
35
39
|
timestamp: 0,
|
|
36
|
-
value:
|
|
40
|
+
value: (0, internalUtils_js_1.toOpaqueJson)({
|
|
41
|
+
name,
|
|
42
|
+
args: [...args],
|
|
43
|
+
}),
|
|
37
44
|
ignoreUnmonitored: true,
|
|
38
45
|
},
|
|
39
46
|
// This is a notification, so we want to send it immediately.
|
|
@@ -42,7 +49,6 @@ class NotificationsManagerImpl {
|
|
|
42
49
|
};
|
|
43
50
|
// Workaround for types
|
|
44
51
|
this.notificationsInternal = (0, client_utils_1.createEmitter)();
|
|
45
|
-
// @ts-expect-error TODO
|
|
46
52
|
this.notifications = this.notificationsInternal;
|
|
47
53
|
// Add event listeners provided at instantiation
|
|
48
54
|
for (const subscriptionName of recordKeys(initialSubscriptions)) {
|
|
@@ -61,17 +67,18 @@ class NotificationsManagerImpl {
|
|
|
61
67
|
get presence() {
|
|
62
68
|
return this.datastore.presence;
|
|
63
69
|
}
|
|
64
|
-
update(attendee, _received,
|
|
70
|
+
update(attendee, _received, updateValue) {
|
|
65
71
|
const postUpdateActions = [];
|
|
66
|
-
const
|
|
72
|
+
const value = (0, internalUtils_js_1.revealOpaqueJson)(updateValue.value);
|
|
73
|
+
const eventName = value.name;
|
|
67
74
|
if (this.notificationsInternal.hasListeners(eventName)) {
|
|
68
75
|
// Without schema validation, we don't know that the args are the correct type.
|
|
69
76
|
// For now we assume the user is sending the correct types and there is no corruption along the way.
|
|
70
|
-
const args = [attendee, ...value.
|
|
77
|
+
const args = [attendee, ...value.args];
|
|
71
78
|
postUpdateActions.push(() => this.notificationsInternal.emit(eventName, ...args));
|
|
72
79
|
}
|
|
73
80
|
else {
|
|
74
|
-
postUpdateActions.push(() => this.events.emit("unattendedNotification", value.
|
|
81
|
+
postUpdateActions.push(() => this.events.emit("unattendedNotification", value.name, attendee, ...value.args));
|
|
75
82
|
}
|
|
76
83
|
return postUpdateActions;
|
|
77
84
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notificationsManager.js","sourceRoot":"","sources":["../src/notificationsManager.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 { createEmitter } from \"@fluid-internal/client-utils\";\nimport type { Listeners, Listenable, Off } from \"@fluidframework/core-interfaces\";\nimport type { JsonTypeWith } from \"@fluidframework/core-interfaces/internal\";\n\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type { InternalUtilityTypes } from \"./exposedUtilityTypes.js\";\nimport type { PostUpdateAction, ValueManager } from \"./internalTypes.js\";\nimport type { Attendee, PresenceWithNotifications as Presence } from \"./presence.js\";\nimport { datastoreFromHandle, type StateDatastore } from \"./stateDatastore.js\";\nimport { brandIVM } from \"./valueManager.js\";\n\n/**\n * @sealed\n * @alpha\n */\nexport interface NotificationsManagerEvents {\n\t/**\n\t * Raised when notification is received, but no subscribers were found.\n\t *\n\t * @eventProperty\n\t */\n\tunattendedNotification: (name: string, sender: Attendee, ...content: unknown[]) => void;\n}\n\n/**\n * An object which allows the registration of listeners so that subscribers can be\n * notified when a notification happens.\n *\n * @sealed\n * @alpha\n */\nexport interface NotificationListenable<\n\tTListeners extends InternalUtilityTypes.NotificationListeners<TListeners>,\n> {\n\t/**\n\t * Register a notification listener.\n\t * @param notificationName - the name of the notification\n\t * @param listener - The listener function to run when the notification is fired.\n\t * @returns A {@link @fluidframework/core-interfaces#Off | function} which will deregister the listener when called.\n\t * Calling the deregistration function more than once will have no effect.\n\t *\n\t * Listeners may also be deregistered by passing the listener to {@link NotificationListenable.off | off()}.\n\t * @remarks Registering the exact same `listener` object for the same notification more than once will throw an error.\n\t * If registering the same listener for the same notification multiple times is desired, consider using a wrapper function for the second subscription.\n\t */\n\ton<K extends keyof InternalUtilityTypes.NotificationListeners<TListeners>>(\n\t\tnotificationName: K,\n\t\tlistener: (\n\t\t\tsender: Attendee,\n\t\t\t...args: InternalUtilityTypes.JsonDeserializedParameters<TListeners[K]>\n\t\t) => void,\n\t): Off;\n\n\t/**\n\t * Deregister notification listener.\n\t * @param notificationName - The name of the notification.\n\t * @param listener - The listener function to remove from the current set of notification listeners.\n\t * @remarks If `listener` is not currently registered, this method will have no effect.\n\t *\n\t * Listeners may also be deregistered by calling the {@link @fluidframework/core-interfaces#Off | deregistration function} returned when they are {@link NotificationListenable.on | registered}.\n\t */\n\toff<K extends keyof InternalUtilityTypes.NotificationListeners<TListeners>>(\n\t\tnotificationName: K,\n\t\tlistener: (\n\t\t\tsender: Attendee,\n\t\t\t...args: InternalUtilityTypes.JsonDeserializedParameters<TListeners[K]>\n\t\t) => void,\n\t): void;\n}\n\n/**\n * Record of notification subscriptions.\n *\n * @sealed\n * @alpha\n */\nexport type NotificationSubscriptions<\n\tE extends InternalUtilityTypes.NotificationListeners<E>,\n> = {\n\t[K in string & keyof InternalUtilityTypes.NotificationListeners<E>]: (\n\t\tsender: Attendee,\n\t\t...args: InternalUtilityTypes.JsonDeserializedParameters<E[K]>\n\t) => void;\n};\n\n/**\n * Interface for a notification emitter that can send typed notification to other clients.\n *\n * @sealed\n * @alpha\n */\nexport interface NotificationEmitter<E extends InternalUtilityTypes.NotificationListeners<E>> {\n\t/**\n\t * Emits a notification with the specified name and arguments, notifying all clients.\n\t * @param notificationName - the name of the notification to fire\n\t * @param args - the arguments sent with the notification\n\t */\n\tbroadcast<K extends string & keyof InternalUtilityTypes.NotificationListeners<E>>(\n\t\tnotificationName: K,\n\t\t...args: Parameters<E[K]>\n\t): void;\n\n\t/**\n\t * Emits a notification with the specified name and arguments, notifying a single attendee.\n\t * @param notificationName - the name of the notification to fire\n\t * @param targetAttendee - the single attendee to notify\n\t * @param args - the arguments sent with the notification\n\t */\n\tunicast<K extends string & keyof InternalUtilityTypes.NotificationListeners<E>>(\n\t\tnotificationName: K,\n\t\ttargetAttendee: Attendee,\n\t\t...args: Parameters<E[K]>\n\t): void;\n}\n\n/**\n * Provides notifications from this client to others and subscription\n * to their notifications.\n *\n * @remarks Create using {@link Notifications} registered to\n * {@link NotificationsWorkspace} or {@link StatesWorkspace}.\n *\n * @sealed\n * @alpha\n */\nexport interface NotificationsManager<\n\tT extends InternalUtilityTypes.NotificationListeners<T>,\n> {\n\t/**\n\t * Containing {@link Presence}\n\t */\n\treadonly presence: Presence;\n\n\t/**\n\t * Events for Notifications manager.\n\t */\n\treadonly events: Listenable<NotificationsManagerEvents>;\n\n\t/**\n\t * Send notifications to other clients.\n\t */\n\treadonly emit: NotificationEmitter<T>;\n\n\t/**\n\t * Provides subscription to notifications from other clients.\n\t */\n\treadonly notifications: NotificationListenable<T>;\n}\n\n/**\n * Object.keys retyped to support specific records keys and\n * branded string-based keys.\n */\nconst recordKeys = Object.keys as <K extends string>(o: Partial<Record<K, unknown>>) => K[];\n\nclass NotificationsManagerImpl<\n\tT extends InternalUtilityTypes.NotificationListeners<T>,\n\tKey extends string,\n> implements\n\t\tNotificationsManager<T>,\n\t\tValueManager<\n\t\t\tInternalTypes.NotificationType,\n\t\t\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>\n\t\t>\n{\n\tpublic readonly events = createEmitter<NotificationsManagerEvents>();\n\n\tpublic readonly emit: NotificationEmitter<T> = {\n\t\tbroadcast: (name, ...args) => {\n\t\t\tthis.datastore.localUpdate(\n\t\t\t\tthis.key,\n\t\t\t\t{\n\t\t\t\t\trev: 0,\n\t\t\t\t\ttimestamp: 0,\n\t\t\t\t\tvalue: { name, args: [...(args as JsonTypeWith<never>[])] },\n\t\t\t\t\tignoreUnmonitored: true,\n\t\t\t\t},\n\t\t\t\t// This is a notification, so we want to send it immediately.\n\t\t\t\t{ allowableUpdateLatencyMs: 0 },\n\t\t\t);\n\t\t},\n\t\tunicast: (name, targetAttendee, ...args) => {\n\t\t\tthis.datastore.localUpdate(\n\t\t\t\tthis.key,\n\t\t\t\t{\n\t\t\t\t\trev: 0,\n\t\t\t\t\ttimestamp: 0,\n\t\t\t\t\tvalue: { name, args: [...(args as JsonTypeWith<never>[])] },\n\t\t\t\t\tignoreUnmonitored: true,\n\t\t\t\t},\n\t\t\t\t// This is a notification, so we want to send it immediately.\n\t\t\t\t{ allowableUpdateLatencyMs: 0, targetClientId: targetAttendee.getConnectionId() },\n\t\t\t);\n\t\t},\n\t};\n\n\t// Workaround for types\n\tprivate readonly notificationsInternal = createEmitter<NotificationSubscriptions<T>>();\n\n\t// @ts-expect-error TODO\n\tpublic readonly notifications: NotificationListenable<T> = this.notificationsInternal;\n\n\tpublic constructor(\n\t\tprivate readonly key: Key,\n\t\tprivate readonly datastore: StateDatastore<\n\t\t\tKey,\n\t\t\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>\n\t\t>,\n\t\tinitialSubscriptions: Partial<NotificationSubscriptions<T>>,\n\t) {\n\t\t// Add event listeners provided at instantiation\n\t\tfor (const subscriptionName of recordKeys(initialSubscriptions)) {\n\t\t\t// Lingering Event typing issues with Notifications specialization requires\n\t\t\t// this cast. The only thing that really matters is that name is a string.\n\t\t\tconst name = subscriptionName as keyof Listeners<NotificationSubscriptions<T>>;\n\t\t\tconst value = initialSubscriptions[subscriptionName];\n\t\t\t// This check should not be needed while using exactOptionalPropertyTypes, but\n\t\t\t// typescript appears to ignore that with Partial<>. Good to be defensive\n\t\t\t// against callers sending `undefined` anyway.\n\t\t\tif (value !== undefined) {\n\t\t\t\tthis.notificationsInternal.on(name, value);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic get presence(): Presence {\n\t\treturn this.datastore.presence;\n\t}\n\n\tpublic update(\n\t\tattendee: Attendee,\n\t\t_received: number,\n\t\tvalue: InternalTypes.ValueRequiredState<InternalTypes.NotificationType>,\n\t): PostUpdateAction[] {\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tconst eventName = value.value.name as keyof Listeners<NotificationSubscriptions<T>>;\n\t\tif (this.notificationsInternal.hasListeners(eventName)) {\n\t\t\t// Without schema validation, we don't know that the args are the correct type.\n\t\t\t// For now we assume the user is sending the correct types and there is no corruption along the way.\n\t\t\tconst args = [attendee, ...value.value.args] as Parameters<\n\t\t\t\tNotificationSubscriptions<T>[typeof eventName]\n\t\t\t>;\n\t\t\tpostUpdateActions.push(() => this.notificationsInternal.emit(eventName, ...args));\n\t\t} else {\n\t\t\tpostUpdateActions.push(() =>\n\t\t\t\tthis.events.emit(\n\t\t\t\t\t\"unattendedNotification\",\n\t\t\t\t\tvalue.value.name,\n\t\t\t\t\tattendee,\n\t\t\t\t\t...value.value.args,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn postUpdateActions;\n\t}\n}\n\n/**\n * Factory for creating a {@link NotificationsManager}.\n *\n * @remarks\n * Typescript inference for `Notifications` is not working correctly yet.\n * Explicitly specify generics to make result types usable.\n *\n * @alpha\n */\nexport function Notifications<\n\tT extends InternalUtilityTypes.NotificationListeners<T>,\n\tKey extends string = string,\n>(\n\tinitialSubscriptions: Partial<NotificationSubscriptions<T>>,\n): InternalTypes.ManagerFactory<\n\tKey,\n\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>,\n\tNotificationsManager<T>\n> {\n\tconst factory = (\n\t\tkey: Key,\n\t\tdatastoreHandle: InternalTypes.StateDatastoreHandle<\n\t\t\tKey,\n\t\t\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>\n\t\t>,\n\t): {\n\t\tmanager: InternalTypes.StateValue<NotificationsManager<T>>;\n\t} => ({\n\t\tmanager: brandIVM<\n\t\t\tNotificationsManagerImpl<T, Key>,\n\t\t\tInternalTypes.NotificationType,\n\t\t\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>\n\t\t>(\n\t\t\tnew NotificationsManagerImpl(\n\t\t\t\tkey,\n\t\t\t\tdatastoreFromHandle(datastoreHandle),\n\t\t\t\tinitialSubscriptions,\n\t\t\t),\n\t\t),\n\t});\n\treturn Object.assign(factory, { instanceBase: NotificationsManagerImpl });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"notificationsManager.js","sourceRoot":"","sources":["../src/notificationsManager.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAA6D;AAO7D,yDAAoE;AAEpE,2DAA+E;AAC/E,uDAA6C;AA4I7C;;;GAGG;AACH,MAAM,UAAU,GAAG,MAAM,CAAC,IAAiE,CAAC;AAE5F,MAAM,wBAAwB;IAoD7B,YACkB,GAAQ,EACR,SAGhB,EACD,oBAA2D;QAL1C,QAAG,GAAH,GAAG,CAAK;QACR,cAAS,GAAT,SAAS,CAGzB;QA/Cc,WAAM,GAAG,IAAA,4BAAa,GAA8B,CAAC;QAErD,SAAI,GAA2B;YAC9C,SAAS,EAAE,CAAC,IAAY,EAAE,GAAG,IAAI,EAAE,EAAE;gBACpC,IAAI,CAAC,SAAS,CAAC,WAAW,CACzB,IAAI,CAAC,GAAG,EACR;oBACC,GAAG,EAAE,CAAC;oBACN,SAAS,EAAE,CAAC;oBACZ,KAAK,EAAE,IAAA,+BAAY,EAAC;wBACnB,IAAI;wBACJ,IAAI,EAAE,CAAC,GAAI,IAA8B,CAAC;qBAC1C,CAAC;oBACF,iBAAiB,EAAE,IAAI;iBACvB;gBACD,6DAA6D;gBAC7D,EAAE,wBAAwB,EAAE,CAAC,EAAE,CAC/B,CAAC;YACH,CAAC;YACD,OAAO,EAAE,CAAC,IAAY,EAAE,cAAc,EAAE,GAAG,IAAI,EAAE,EAAE;gBAClD,IAAI,CAAC,SAAS,CAAC,WAAW,CACzB,IAAI,CAAC,GAAG,EACR;oBACC,GAAG,EAAE,CAAC;oBACN,SAAS,EAAE,CAAC;oBACZ,KAAK,EAAE,IAAA,+BAAY,EAAC;wBACnB,IAAI;wBACJ,IAAI,EAAE,CAAC,GAAI,IAA8B,CAAC;qBAC1C,CAAC;oBACF,iBAAiB,EAAE,IAAI;iBACvB;gBACD,6DAA6D;gBAC7D,EAAE,wBAAwB,EAAE,CAAC,EAAE,cAAc,EAAE,cAAc,CAAC,eAAe,EAAE,EAAE,CACjF,CAAC;YACH,CAAC;SACD,CAAC;QAEF,uBAAuB;QACN,0BAAqB,GAAG,IAAA,4BAAa,GAAgC,CAAC;QAEvE,kBAAa,GAA8B,IAAI,CAAC,qBAAqB,CAAC;QAUrF,gDAAgD;QAChD,KAAK,MAAM,gBAAgB,IAAI,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACjE,2EAA2E;YAC3E,0EAA0E;YAC1E,MAAM,IAAI,GAAG,gBAAiE,CAAC;YAC/E,MAAM,KAAK,GAAG,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;YACrD,8EAA8E;YAC9E,yEAAyE;YACzE,8CAA8C;YAC9C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACzB,IAAI,CAAC,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC5C,CAAC;QACF,CAAC;IACF,CAAC;IAED,IAAW,QAAQ;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;IAChC,CAAC;IAEM,MAAM,CACZ,QAAkB,EAClB,SAAiB,EACjB,WAA6E;QAE7E,MAAM,iBAAiB,GAAuB,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,IAAA,mCAAgB,EAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAqD,CAAC;QAC9E,IAAI,IAAI,CAAC,qBAAqB,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;YACxD,+EAA+E;YAC/E,oGAAoG;YACpG,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,IAAI,CAEpC,CAAC;YACF,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;QACnF,CAAC;aAAM,CAAC;YACP,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,CAC3B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,CAC/E,CAAC;QACH,CAAC;QACD,OAAO,iBAAiB,CAAC;IAC1B,CAAC;CACD;AAED;;;;;;;;GAQG;AACH,SAAgB,aAAa,CAI5B,oBAA2D;IAM3D,MAAM,OAAO,GAAG,CACf,GAAQ,EACR,eAGC,EAGA,EAAE,CAAC,CAAC;QACL,OAAO,EAAE,IAAA,0BAAQ,EAKhB,IAAI,wBAAwB,CAC3B,GAAG,EACH,IAAA,uCAAmB,EAAC,eAAe,CAAC,EACpC,oBAAoB,CACpB,CACD;KACD,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,wBAAwB,EAAE,CAAC,CAAC;AAC3E,CAAC;AAhCD,sCAgCC","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 { Listeners, Listenable, Off } from \"@fluidframework/core-interfaces\";\nimport type { JsonTypeWith } from \"@fluidframework/core-interfaces/internal\";\n\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type { InternalUtilityTypes } from \"./exposedUtilityTypes.js\";\nimport type { PostUpdateAction, ValueManager } from \"./internalTypes.js\";\nimport { revealOpaqueJson, toOpaqueJson } from \"./internalUtils.js\";\nimport type { Attendee, PresenceWithNotifications as Presence } from \"./presence.js\";\nimport { datastoreFromHandle, type StateDatastore } from \"./stateDatastore.js\";\nimport { brandIVM } from \"./valueManager.js\";\n\n/**\n * @sealed\n * @alpha\n */\nexport interface NotificationsManagerEvents {\n\t/**\n\t * Raised when notification is received, but no subscribers were found.\n\t *\n\t * @eventProperty\n\t */\n\tunattendedNotification: (name: string, sender: Attendee, ...content: unknown[]) => void;\n}\n\n/**\n * An object which allows the registration of listeners so that subscribers can be\n * notified when a notification happens.\n *\n * @sealed\n * @alpha\n */\nexport interface NotificationListenable<\n\tTListeners extends InternalUtilityTypes.NotificationListeners<TListeners>,\n> {\n\t/**\n\t * Register a notification listener.\n\t * @param notificationName - the name of the notification\n\t * @param listener - The listener function to run when the notification is fired.\n\t * @returns A {@link @fluidframework/core-interfaces#Off | function} which will deregister the listener when called.\n\t * Calling the deregistration function more than once will have no effect.\n\t *\n\t * Listeners may also be deregistered by passing the listener to {@link NotificationListenable.off | off()}.\n\t * @remarks Registering the exact same `listener` object for the same notification more than once will throw an error.\n\t * If registering the same listener for the same notification multiple times is desired, consider using a wrapper function for the second subscription.\n\t */\n\ton<K extends keyof InternalUtilityTypes.NotificationListeners<TListeners>>(\n\t\tnotificationName: K,\n\t\tlistener: (\n\t\t\tsender: Attendee,\n\t\t\t...args: InternalUtilityTypes.JsonDeserializedParameters<TListeners[K]>\n\t\t) => void,\n\t): Off;\n\n\t/**\n\t * Deregister notification listener.\n\t * @param notificationName - The name of the notification.\n\t * @param listener - The listener function to remove from the current set of notification listeners.\n\t * @remarks If `listener` is not currently registered, this method will have no effect.\n\t *\n\t * Listeners may also be deregistered by calling the {@link @fluidframework/core-interfaces#Off | deregistration function} returned when they are {@link NotificationListenable.on | registered}.\n\t */\n\toff<K extends keyof InternalUtilityTypes.NotificationListeners<TListeners>>(\n\t\tnotificationName: K,\n\t\tlistener: (\n\t\t\tsender: Attendee,\n\t\t\t...args: InternalUtilityTypes.JsonDeserializedParameters<TListeners[K]>\n\t\t) => void,\n\t): void;\n}\n\n/**\n * Record of notification subscriptions.\n *\n * @sealed\n * @alpha\n */\nexport type NotificationSubscriptions<\n\tE extends InternalUtilityTypes.NotificationListeners<E>,\n> = {\n\t[K in string & keyof InternalUtilityTypes.NotificationListeners<E>]: (\n\t\tsender: Attendee,\n\t\t...args: InternalUtilityTypes.JsonDeserializedParameters<E[K]>\n\t) => void;\n};\n\n/**\n * Interface for a notification emitter that can send typed notification to other clients.\n *\n * @sealed\n * @alpha\n */\nexport interface NotificationEmitter<E extends InternalUtilityTypes.NotificationListeners<E>> {\n\t/**\n\t * Emits a notification with the specified name and arguments, notifying all clients.\n\t * @param notificationName - the name of the notification to fire\n\t * @param args - the arguments sent with the notification\n\t */\n\tbroadcast<K extends keyof InternalUtilityTypes.NotificationListeners<E>>(\n\t\tnotificationName: K,\n\t\t...args: Parameters<E[K]>\n\t): void;\n\n\t/**\n\t * Emits a notification with the specified name and arguments, notifying a single attendee.\n\t * @param notificationName - the name of the notification to fire\n\t * @param targetAttendee - the single attendee to notify\n\t * @param args - the arguments sent with the notification\n\t */\n\tunicast<K extends keyof InternalUtilityTypes.NotificationListeners<E>>(\n\t\tnotificationName: K,\n\t\ttargetAttendee: Attendee,\n\t\t...args: Parameters<E[K]>\n\t): void;\n}\n\n/**\n * Provides notifications from this client to others and subscription\n * to their notifications.\n *\n * @remarks Create using {@link Notifications} registered to\n * {@link NotificationsWorkspace} or {@link StatesWorkspace}.\n *\n * @sealed\n * @alpha\n */\nexport interface NotificationsManager<\n\tT extends InternalUtilityTypes.NotificationListeners<T>,\n> {\n\t/**\n\t * Containing {@link Presence}\n\t */\n\treadonly presence: Presence;\n\n\t/**\n\t * Events for Notifications manager.\n\t */\n\treadonly events: Listenable<NotificationsManagerEvents>;\n\n\t/**\n\t * Send notifications to other clients.\n\t */\n\treadonly emit: NotificationEmitter<T>;\n\n\t/**\n\t * Provides subscription to notifications from other clients.\n\t */\n\treadonly notifications: NotificationListenable<T>;\n}\n\n/**\n * Object.keys retyped to support specific records keys and\n * branded string-based keys.\n */\nconst recordKeys = Object.keys as <K extends string>(o: Partial<Record<K, unknown>>) => K[];\n\nclass NotificationsManagerImpl<\n\tT extends InternalUtilityTypes.NotificationListeners<T>,\n\tKey extends string,\n> implements\n\t\tNotificationsManager<T>,\n\t\tValueManager<\n\t\t\tInternalTypes.NotificationType,\n\t\t\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>\n\t\t>\n{\n\tpublic readonly events = createEmitter<NotificationsManagerEvents>();\n\n\tpublic readonly emit: NotificationEmitter<T> = {\n\t\tbroadcast: (name: string, ...args) => {\n\t\t\tthis.datastore.localUpdate(\n\t\t\t\tthis.key,\n\t\t\t\t{\n\t\t\t\t\trev: 0,\n\t\t\t\t\ttimestamp: 0,\n\t\t\t\t\tvalue: toOpaqueJson({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\targs: [...(args as JsonTypeWith<never>[])],\n\t\t\t\t\t}),\n\t\t\t\t\tignoreUnmonitored: true,\n\t\t\t\t},\n\t\t\t\t// This is a notification, so we want to send it immediately.\n\t\t\t\t{ allowableUpdateLatencyMs: 0 },\n\t\t\t);\n\t\t},\n\t\tunicast: (name: string, targetAttendee, ...args) => {\n\t\t\tthis.datastore.localUpdate(\n\t\t\t\tthis.key,\n\t\t\t\t{\n\t\t\t\t\trev: 0,\n\t\t\t\t\ttimestamp: 0,\n\t\t\t\t\tvalue: toOpaqueJson({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\targs: [...(args as JsonTypeWith<never>[])],\n\t\t\t\t\t}),\n\t\t\t\t\tignoreUnmonitored: true,\n\t\t\t\t},\n\t\t\t\t// This is a notification, so we want to send it immediately.\n\t\t\t\t{ allowableUpdateLatencyMs: 0, targetClientId: targetAttendee.getConnectionId() },\n\t\t\t);\n\t\t},\n\t};\n\n\t// Workaround for types\n\tprivate readonly notificationsInternal = createEmitter<NotificationSubscriptions<T>>();\n\n\tpublic readonly notifications: NotificationListenable<T> = this.notificationsInternal;\n\n\tpublic constructor(\n\t\tprivate readonly key: Key,\n\t\tprivate readonly datastore: StateDatastore<\n\t\t\tKey,\n\t\t\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>\n\t\t>,\n\t\tinitialSubscriptions: Partial<NotificationSubscriptions<T>>,\n\t) {\n\t\t// Add event listeners provided at instantiation\n\t\tfor (const subscriptionName of recordKeys(initialSubscriptions)) {\n\t\t\t// Lingering Event typing issues with Notifications specialization requires\n\t\t\t// this cast. The only thing that really matters is that name is a string.\n\t\t\tconst name = subscriptionName as keyof Listeners<NotificationSubscriptions<T>>;\n\t\t\tconst value = initialSubscriptions[subscriptionName];\n\t\t\t// This check should not be needed while using exactOptionalPropertyTypes, but\n\t\t\t// typescript appears to ignore that with Partial<>. Good to be defensive\n\t\t\t// against callers sending `undefined` anyway.\n\t\t\tif (value !== undefined) {\n\t\t\t\tthis.notificationsInternal.on(name, value);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic get presence(): Presence {\n\t\treturn this.datastore.presence;\n\t}\n\n\tpublic update(\n\t\tattendee: Attendee,\n\t\t_received: number,\n\t\tupdateValue: InternalTypes.ValueRequiredState<InternalTypes.NotificationType>,\n\t): PostUpdateAction[] {\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tconst value = revealOpaqueJson(updateValue.value);\n\t\tconst eventName = value.name as keyof Listeners<NotificationSubscriptions<T>>;\n\t\tif (this.notificationsInternal.hasListeners(eventName)) {\n\t\t\t// Without schema validation, we don't know that the args are the correct type.\n\t\t\t// For now we assume the user is sending the correct types and there is no corruption along the way.\n\t\t\tconst args = [attendee, ...value.args] as Parameters<\n\t\t\t\tNotificationSubscriptions<T>[typeof eventName]\n\t\t\t>;\n\t\t\tpostUpdateActions.push(() => this.notificationsInternal.emit(eventName, ...args));\n\t\t} else {\n\t\t\tpostUpdateActions.push(() =>\n\t\t\t\tthis.events.emit(\"unattendedNotification\", value.name, attendee, ...value.args),\n\t\t\t);\n\t\t}\n\t\treturn postUpdateActions;\n\t}\n}\n\n/**\n * Factory for creating a {@link NotificationsManager}.\n *\n * @remarks\n * Typescript inference for `Notifications` is not working correctly yet.\n * Explicitly specify generics to make result types usable.\n *\n * @alpha\n */\nexport function Notifications<\n\tT extends InternalUtilityTypes.NotificationListeners<T>,\n\tKey extends string = string,\n>(\n\tinitialSubscriptions: Partial<NotificationSubscriptions<T>>,\n): InternalTypes.ManagerFactory<\n\tKey,\n\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>,\n\tNotificationsManager<T>\n> {\n\tconst factory = (\n\t\tkey: Key,\n\t\tdatastoreHandle: InternalTypes.StateDatastoreHandle<\n\t\t\tKey,\n\t\t\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>\n\t\t>,\n\t): {\n\t\tmanager: InternalTypes.StateValue<NotificationsManager<T>>;\n\t} => ({\n\t\tmanager: brandIVM<\n\t\t\tNotificationsManagerImpl<T, Key>,\n\t\t\tInternalTypes.NotificationType,\n\t\t\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>\n\t\t>(\n\t\t\tnew NotificationsManagerImpl(\n\t\t\t\tkey,\n\t\t\t\tdatastoreFromHandle(datastoreHandle),\n\t\t\t\tinitialSubscriptions,\n\t\t\t),\n\t\t),\n\t});\n\treturn Object.assign(factory, { instanceBase: NotificationsManagerImpl });\n}\n"]}
|
package/dist/presence.d.ts
CHANGED
|
@@ -95,11 +95,11 @@ export interface Attendee<SpecificAttendeeId extends AttendeeId = AttendeeId> {
|
|
|
95
95
|
/**
|
|
96
96
|
* Utility type limiting to a specific attendee. (A attendee with
|
|
97
97
|
* a specific session ID - not just any session ID.)
|
|
98
|
-
*
|
|
99
|
-
* @internal
|
|
100
98
|
*/
|
|
101
99
|
export type SpecificAttendee<SpecificAttendeeId extends AttendeeId> = string extends SpecificAttendeeId ? never : Attendee<SpecificAttendeeId>;
|
|
102
100
|
/**
|
|
101
|
+
* Events from {@link Presence.attendees}.
|
|
102
|
+
*
|
|
103
103
|
* @sealed
|
|
104
104
|
* @beta
|
|
105
105
|
*/
|
|
@@ -118,6 +118,8 @@ export interface AttendeesEvents {
|
|
|
118
118
|
attendeeDisconnected: (attendee: Attendee) => void;
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
121
|
+
* Events from {@link Presence}.
|
|
122
|
+
*
|
|
121
123
|
* @sealed
|
|
122
124
|
* @beta
|
|
123
125
|
*/
|
|
@@ -175,12 +177,12 @@ export interface Presence {
|
|
|
175
177
|
};
|
|
176
178
|
readonly states: {
|
|
177
179
|
/**
|
|
178
|
-
* Acquires a StatesWorkspace from store or adds new one.
|
|
180
|
+
* Acquires a {@link StatesWorkspace} from store or adds new one.
|
|
179
181
|
*
|
|
180
|
-
* @param workspaceAddress - Address of the requested StatesWorkspace
|
|
182
|
+
* @param workspaceAddress - Address of the requested {@link StatesWorkspace}
|
|
181
183
|
* @param requestedStates - Requested states for the workspace
|
|
182
184
|
* @param controls - Optional settings for default broadcast controls
|
|
183
|
-
* @returns A StatesWorkspace
|
|
185
|
+
* @returns A {@link StatesWorkspace}
|
|
184
186
|
*/
|
|
185
187
|
getWorkspace<StatesSchema extends StatesWorkspaceSchema>(workspaceAddress: WorkspaceAddress, requestedStates: StatesSchema, controls?: BroadcastControlSettings): StatesWorkspace<StatesSchema>;
|
|
186
188
|
};
|
package/dist/presence.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EACX,sBAAsB,EACtB,4BAA4B,EAC5B,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3E;;;;GAIG;AACH,eAAO,MAAM,cAAc;IAC1B;;OAEG;;IAGH;;OAEG;;CAEM,CAAC;AAEX;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAElF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,QAAQ,CAAC,kBAAkB,SAAS,UAAU,GAAG,UAAU;IAC3E;;OAEG;IACH,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IAExC;;;;;;;;;OASG;IACH,eAAe,IAAI,kBAAkB,CAAC;IAEtC;;;;;OAKG;IACH,mBAAmB,IAAI,cAAc,CAAC;CACtC;AAED
|
|
1
|
+
{"version":3,"file":"presence.d.ts","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":"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"}
|
package/dist/presence.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA6BH;;;;GAIG;AACU,QAAA,cAAc,GAAG;IAC7B;;OAEG;IACH,SAAS,EAAE,WAAW;IAEtB;;OAEG;IACH,YAAY,EAAE,cAAc;CACnB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type { SessionId } from \"@fluidframework/id-compressor\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type {\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"./types.js\";\n\n/**\n * A Fluid client session identifier.\n *\n * @remarks\n * Each client once connected to a session is given a unique identifier for the\n * duration of the session. If a client disconnects and reconnects, it will\n * retain its identifier. Prefer use of {@link Attendee} as a way to\n * identify clients in a session. {@link Attendee.attendeeId} will provide\n * the session ID.\n *\n * @beta\n */\nexport type AttendeeId = SessionId & { readonly AttendeeId: \"AttendeeId\" };\n\n/**\n * The connection status of the {@link Attendee}.\n *\n * @beta\n */\nexport const AttendeeStatus = {\n\t/**\n\t * The {@link Attendee} is connected to the Fluid service.\n\t */\n\tConnected: \"Connected\",\n\n\t/**\n\t * The {@link Attendee} is not connected to the Fluid service.\n\t */\n\tDisconnected: \"Disconnected\",\n} as const;\n\n/**\n * Represents the connection status of an {@link Attendee}.\n *\n * This type can be either `'Connected'` or `'Disconnected'`, indicating whether\n * the attendee is currently connected to the Fluid service.\n *\n * When `'Disconnected'`:\n * - State changes are kept locally and communicated to others upon reconnect.\n * - Notification requests are discarded (silently).\n *\n * @beta\n */\nexport type AttendeeStatus = (typeof AttendeeStatus)[keyof typeof AttendeeStatus];\n\n/**\n * A client within a Fluid session (period of container connectivity to service).\n *\n * @remarks\n * Note: This is very preliminary attendee representation.\n *\n * {@link Attendee} should be used as key to distinguish between different\n * clients as they join, rejoin, and disconnect from a session. While a\n * client's {@link ClientConnectionId} from {@link Attendee.getConnectionStatus}\n * may change over time, `Attendee` will be fixed.\n *\n * @privateRemarks\n * As this is evolved, pay attention to how this relates to Audience, Service\n * Audience, and Quorum representations of clients and users.\n *\n * @sealed\n * @beta\n */\nexport interface Attendee<SpecificAttendeeId extends AttendeeId = AttendeeId> {\n\t/**\n\t * The session ID of the client that is stable over all connections.\n\t */\n\treadonly attendeeId: SpecificAttendeeId;\n\n\t/**\n\t * Get current client connection ID.\n\t *\n\t * @returns Current client connection ID.\n\t *\n\t * @remarks\n\t * Connection ID will change on reconnect.\n\t *\n\t * If {@link Attendee.getConnectionStatus} is {@link (AttendeeStatus:variable).Disconnected}, this will represent the last known connection ID.\n\t */\n\tgetConnectionId(): ClientConnectionId;\n\n\t/**\n\t * Get connection status of attendee.\n\t *\n\t * @returns Connection status of attendee.\n\t *\n\t */\n\tgetConnectionStatus(): AttendeeStatus;\n}\n\n/**\n * Utility type limiting to a specific attendee. (A attendee with\n * a specific session ID - not just any session ID.)\n
|
|
1
|
+
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA6BH;;;;GAIG;AACU,QAAA,cAAc,GAAG;IAC7B;;OAEG;IACH,SAAS,EAAE,WAAW;IAEtB;;OAEG;IACH,YAAY,EAAE,cAAc;CACnB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type { SessionId } from \"@fluidframework/id-compressor\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type {\n\tNotificationsWorkspace,\n\tNotificationsWorkspaceSchema,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n\tWorkspaceAddress,\n} from \"./types.js\";\n\n/**\n * A Fluid client session identifier.\n *\n * @remarks\n * Each client once connected to a session is given a unique identifier for the\n * duration of the session. If a client disconnects and reconnects, it will\n * retain its identifier. Prefer use of {@link Attendee} as a way to\n * identify clients in a session. {@link Attendee.attendeeId} will provide\n * the session ID.\n *\n * @beta\n */\nexport type AttendeeId = SessionId & { readonly AttendeeId: \"AttendeeId\" };\n\n/**\n * The connection status of the {@link Attendee}.\n *\n * @beta\n */\nexport const AttendeeStatus = {\n\t/**\n\t * The {@link Attendee} is connected to the Fluid service.\n\t */\n\tConnected: \"Connected\",\n\n\t/**\n\t * The {@link Attendee} is not connected to the Fluid service.\n\t */\n\tDisconnected: \"Disconnected\",\n} as const;\n\n/**\n * Represents the connection status of an {@link Attendee}.\n *\n * This type can be either `'Connected'` or `'Disconnected'`, indicating whether\n * the attendee is currently connected to the Fluid service.\n *\n * When `'Disconnected'`:\n * - State changes are kept locally and communicated to others upon reconnect.\n * - Notification requests are discarded (silently).\n *\n * @beta\n */\nexport type AttendeeStatus = (typeof AttendeeStatus)[keyof typeof AttendeeStatus];\n\n/**\n * A client within a Fluid session (period of container connectivity to service).\n *\n * @remarks\n * Note: This is very preliminary attendee representation.\n *\n * {@link Attendee} should be used as key to distinguish between different\n * clients as they join, rejoin, and disconnect from a session. While a\n * client's {@link ClientConnectionId} from {@link Attendee.getConnectionStatus}\n * may change over time, `Attendee` will be fixed.\n *\n * @privateRemarks\n * As this is evolved, pay attention to how this relates to Audience, Service\n * Audience, and Quorum representations of clients and users.\n *\n * @sealed\n * @beta\n */\nexport interface Attendee<SpecificAttendeeId extends AttendeeId = AttendeeId> {\n\t/**\n\t * The session ID of the client that is stable over all connections.\n\t */\n\treadonly attendeeId: SpecificAttendeeId;\n\n\t/**\n\t * Get current client connection ID.\n\t *\n\t * @returns Current client connection ID.\n\t *\n\t * @remarks\n\t * Connection ID will change on reconnect.\n\t *\n\t * If {@link Attendee.getConnectionStatus} is {@link (AttendeeStatus:variable).Disconnected}, this will represent the last known connection ID.\n\t */\n\tgetConnectionId(): ClientConnectionId;\n\n\t/**\n\t * Get connection status of attendee.\n\t *\n\t * @returns Connection status of attendee.\n\t *\n\t */\n\tgetConnectionStatus(): AttendeeStatus;\n}\n\n/**\n * Utility type limiting to a specific attendee. (A attendee with\n * a specific session ID - not just any session ID.)\n */\nexport type SpecificAttendee<SpecificAttendeeId extends AttendeeId> =\n\tstring extends SpecificAttendeeId ? never : Attendee<SpecificAttendeeId>;\n\n/**\n * Events from {@link Presence.attendees}.\n *\n * @sealed\n * @beta\n */\nexport interface AttendeesEvents {\n\t/**\n\t * Raised when new client joins session.\n\t *\n\t * @eventProperty\n\t */\n\tattendeeConnected: (attendee: Attendee) => void;\n\n\t/**\n\t * Raised when client appears disconnected from session.\n\t *\n\t * @eventProperty\n\t */\n\tattendeeDisconnected: (attendee: Attendee) => void;\n}\n\n/**\n * Events from {@link Presence}.\n *\n * @sealed\n * @beta\n */\nexport interface PresenceEvents {\n\t/**\n\t * Raised when a workspace is activated within the session.\n\t *\n\t * \"Activated\" means that a workspace is being used by a client and this\n\t * client is seeing information for the first time.\n\t *\n\t * @remarks\n\t * Local workspaces may be passively acquired/registered when this event\n\t * is raised. For a notifications workspace, that lazy registration must\n\t * be done before the event handler returns to ensure no notifications\n\t * are missed.\n\t */\n\tworkspaceActivated: (\n\t\tworkspaceAddress: WorkspaceAddress,\n\t\ttype: \"States\" | \"Notifications\" | \"Unknown\",\n\t) => void;\n}\n\n/**\n * Presence represents known clients within a session and their custom states.\n *\n * @sealed\n * @beta\n */\nexport interface Presence {\n\t/**\n\t * Events for Presence.\n\t */\n\treadonly events: Listenable<PresenceEvents>;\n\n\treadonly attendees: {\n\t\t/**\n\t\t * Events for {@link Attendee}s.\n\t\t */\n\t\treadonly events: Listenable<AttendeesEvents>;\n\n\t\t/**\n\t\t * Get all {@link Attendee}s in the session.\n\t\t *\n\t\t * @remarks\n\t\t * Attendee states are dynamic and will change as clients join and leave\n\t\t * the session.\n\t\t */\n\t\tgetAttendees(): ReadonlySet<Attendee>;\n\n\t\t/**\n\t\t * Lookup a specific {@link Attendee} in the session.\n\t\t *\n\t\t * @param clientId - Client connection or session ID\n\t\t */\n\t\tgetAttendee(clientId: ClientConnectionId | AttendeeId): Attendee;\n\n\t\t/**\n\t\t * Get this client's {@link Attendee}.\n\t\t *\n\t\t * @returns This client's attendee.\n\t\t */\n\t\tgetMyself(): Attendee;\n\t};\n\n\treadonly states: {\n\t\t/**\n\t\t * Acquires a {@link StatesWorkspace} from store or adds new one.\n\t\t *\n\t\t * @param workspaceAddress - Address of the requested {@link StatesWorkspace}\n\t\t * @param requestedStates - Requested states for the workspace\n\t\t * @param controls - Optional settings for default broadcast controls\n\t\t * @returns A {@link StatesWorkspace}\n\t\t */\n\t\tgetWorkspace<StatesSchema extends StatesWorkspaceSchema>(\n\t\t\tworkspaceAddress: WorkspaceAddress,\n\t\t\trequestedStates: StatesSchema,\n\t\t\tcontrols?: BroadcastControlSettings,\n\t\t): StatesWorkspace<StatesSchema>;\n\t};\n}\n\n/**\n * Presence represents known clients within a session and their custom states and notifications.\n *\n * @remarks\n * To access this alpha API, cast any `{@link Presence}` to `PresenceWithNotifications`.\n *\n * @sealed\n * @alpha\n */\nexport interface PresenceWithNotifications extends Presence {\n\treadonly notifications: {\n\t\t/**\n\t\t * Acquires a Notifications workspace from store or adds new one.\n\t\t *\n\t\t * @param workspaceAddress - Address of the requested Notifications Workspace\n\t\t * @param requestedNotifications - Requested notifications for the workspace\n\t\t * @returns A Notifications workspace\n\t\t */\n\t\tgetWorkspace<NotificationsSchema extends NotificationsWorkspaceSchema>(\n\t\t\tnotificationsId: WorkspaceAddress,\n\t\t\trequestedNotifications: NotificationsSchema,\n\t\t): NotificationsWorkspace<NotificationsSchema>;\n\t};\n}\n"]}
|
|
@@ -8,18 +8,17 @@ import type { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/intern
|
|
|
8
8
|
import type { ClientConnectionId } from "./baseTypes.js";
|
|
9
9
|
import type { BroadcastControlSettings } from "./broadcastControls.js";
|
|
10
10
|
import type { IEphemeralRuntime } from "./internalTypes.js";
|
|
11
|
-
import type { AttendeeId,
|
|
11
|
+
import type { AttendeeId, PresenceWithNotifications as Presence, PresenceEvents } from "./presence.js";
|
|
12
12
|
import type { PresenceStatesInternal } from "./presenceStates.js";
|
|
13
|
-
import type { SignalMessages } from "./protocol.js";
|
|
13
|
+
import type { InternalWorkspaceAddress, SignalMessages } from "./protocol.js";
|
|
14
14
|
import type { SystemWorkspaceDatastore } from "./systemWorkspace.js";
|
|
15
15
|
import type { AnyWorkspace, NotificationsWorkspace, NotificationsWorkspaceSchema, StatesWorkspace, StatesWorkspaceSchema, WorkspaceAddress } from "./types.js";
|
|
16
16
|
interface AnyWorkspaceEntry<TSchema extends StatesWorkspaceSchema> {
|
|
17
17
|
public: AnyWorkspace<TSchema>;
|
|
18
18
|
internal: PresenceStatesInternal;
|
|
19
19
|
}
|
|
20
|
-
type InternalWorkspaceAddress = `${"s" | "n"}:${WorkspaceAddress}`;
|
|
21
20
|
/**
|
|
22
|
-
*
|
|
21
|
+
* High-level contract for manager of singleton Presence datastore
|
|
23
22
|
*/
|
|
24
23
|
export interface PresenceDatastoreManager {
|
|
25
24
|
joinSession(clientId: ClientConnectionId): void;
|
|
@@ -33,7 +32,6 @@ export interface PresenceDatastoreManager {
|
|
|
33
32
|
export declare class PresenceDatastoreManagerImpl implements PresenceDatastoreManager {
|
|
34
33
|
private readonly attendeeId;
|
|
35
34
|
private readonly runtime;
|
|
36
|
-
private readonly lookupClient;
|
|
37
35
|
private readonly logger;
|
|
38
36
|
private readonly events;
|
|
39
37
|
private readonly presence;
|
|
@@ -43,7 +41,8 @@ export declare class PresenceDatastoreManagerImpl implements PresenceDatastoreMa
|
|
|
43
41
|
private refreshBroadcastRequested;
|
|
44
42
|
private readonly timer;
|
|
45
43
|
private readonly workspaces;
|
|
46
|
-
|
|
44
|
+
private readonly targetedSignalSupport;
|
|
45
|
+
constructor(attendeeId: AttendeeId, runtime: IEphemeralRuntime, logger: ITelemetryLoggerExt | undefined, events: IEmitter<PresenceEvents>, presence: Presence, systemWorkspaceDatastore: SystemWorkspaceDatastore, systemWorkspace: AnyWorkspaceEntry<StatesWorkspaceSchema>);
|
|
47
46
|
joinSession(clientId: ClientConnectionId): void;
|
|
48
47
|
getWorkspace<TSchema extends StatesWorkspaceSchema>(internalWorkspaceAddress: InternalWorkspaceAddress, requestedContent: TSchema, controls?: BroadcastControlSettings): AnyWorkspace<TSchema>;
|
|
49
48
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presenceDatastoreManager.d.ts","sourceRoot":"","sources":["../src/presenceDatastoreManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wDAAwD,CAAC;AACtG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AAEzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAEpF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAoB,MAAM,oBAAoB,CAAC;AAE9E,OAAO,KAAK,EACX,UAAU,EACV,
|
|
1
|
+
{"version":3,"file":"presenceDatastoreManager.d.ts","sourceRoot":"","sources":["../src/presenceDatastoreManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wDAAwD,CAAC;AACtG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0CAA0C,CAAC;AAEzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAEpF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAoB,MAAM,oBAAoB,CAAC;AAE9E,OAAO,KAAK,EACX,UAAU,EACV,yBAAyB,IAAI,QAAQ,EACrC,cAAc,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAGX,sBAAsB,EAEtB,MAAM,qBAAqB,CAAC;AAM7B,OAAO,KAAK,EAIX,wBAAwB,EAExB,cAAc,EAEd,MAAM,eAAe,CAAC;AAMvB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAErE,OAAO,KAAK,EACX,YAAY,EACZ,sBAAsB,EACtB,4BAA4B,EAC5B,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAEpB,UAAU,iBAAiB,CAAC,OAAO,SAAS,qBAAqB;IAChE,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,sBAAsB,CAAC;CACjC;AAsBD;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACxC,WAAW,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAChD,YAAY,CAAC,OAAO,SAAS,qBAAqB,EACjD,wBAAwB,EAAE,KAAK,gBAAgB,EAAE,EACjD,gBAAgB,EAAE,OAAO,EACzB,QAAQ,CAAC,EAAE,wBAAwB,GACjC,eAAe,CAAC,OAAO,CAAC,CAAC;IAC5B,YAAY,CAAC,OAAO,SAAS,4BAA4B,EACxD,wBAAwB,EAAE,KAAK,gBAAgB,EAAE,EACjD,gBAAgB,EAAE,OAAO,GACvB,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACnC,aAAa,CACZ,OAAO,EAAE,uBAAuB,CAAC,cAAc,CAAC,EAChD,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,OAAO,GACf,IAAI,CAAC;CACR;AAqCD;;GAEG;AACH,qBAAa,4BAA6B,YAAW,wBAAwB;IAU3E,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAb1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,yBAAyB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsB;IAC5C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA+D;IAC1F,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAU;gBAG9B,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,mBAAmB,GAAG,SAAS,EACvC,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,EAChC,QAAQ,EAAE,QAAQ,EACnC,wBAAwB,EAAE,wBAAwB,EAClD,eAAe,EAAE,iBAAiB,CAAC,qBAAqB,CAAC;IAQnD,WAAW,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAqB/C,YAAY,CAAC,OAAO,SAAS,qBAAqB,EACxD,wBAAwB,EAAE,wBAAwB,EAClD,gBAAgB,EAAE,OAAO,EACzB,QAAQ,CAAC,EAAE,wBAAwB,GACjC,YAAY,CAAC,OAAO,CAAC;IAiDxB;;OAEG;IACH,OAAO,CAAC,UAAU,CAA6C;IAE/D;;;OAGG;IACH,OAAO,CAAC,cAAc;IAuCtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA2CzB,OAAO,CAAC,sBAAsB;IAavB,aAAa,CACnB,OAAO,EAAE,uBAAuB,CAAC,cAAc,CAAC,EAChD,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,OAAO,GACf,IAAI;IA+GP;;;;;;;;;;OAUG;IACH,OAAO,CAAC,mBAAmB;CAgE3B"}
|
|
@@ -14,7 +14,11 @@ const internalWorkspaceTypes = {
|
|
|
14
14
|
s: "States",
|
|
15
15
|
n: "Notifications",
|
|
16
16
|
};
|
|
17
|
-
const knownMessageTypes = new Set([
|
|
17
|
+
const knownMessageTypes = new Set([
|
|
18
|
+
protocol_js_1.joinMessageType,
|
|
19
|
+
protocol_js_1.datastoreUpdateMessageType,
|
|
20
|
+
protocol_js_1.acknowledgementMessageType,
|
|
21
|
+
]);
|
|
18
22
|
function isPresenceMessage(message) {
|
|
19
23
|
return knownMessageTypes.has(message.type);
|
|
20
24
|
}
|
|
@@ -23,7 +27,7 @@ function mergeGeneralDatastoreMessageContent(base, newData) {
|
|
|
23
27
|
const queueDatastore = base ?? {};
|
|
24
28
|
// Merge the current data with the existing data, if any exists.
|
|
25
29
|
// Iterate over the current message data; individual items are workspaces.
|
|
26
|
-
for (const [workspaceName, workspaceData] of
|
|
30
|
+
for (const [workspaceName, workspaceData] of (0, internalUtils_js_1.objectEntries)(newData)) {
|
|
27
31
|
// Initialize the merged data as the queued datastore entry for the workspace.
|
|
28
32
|
// Since the key might not exist, create an empty object in that case. It will
|
|
29
33
|
// be set explicitly after the loop.
|
|
@@ -46,10 +50,9 @@ function mergeGeneralDatastoreMessageContent(base, newData) {
|
|
|
46
50
|
* Manages singleton datastore for all Presence.
|
|
47
51
|
*/
|
|
48
52
|
class PresenceDatastoreManagerImpl {
|
|
49
|
-
constructor(attendeeId, runtime,
|
|
53
|
+
constructor(attendeeId, runtime, logger, events, presence, systemWorkspaceDatastore, systemWorkspace) {
|
|
50
54
|
this.attendeeId = attendeeId;
|
|
51
55
|
this.runtime = runtime;
|
|
52
|
-
this.lookupClient = lookupClient;
|
|
53
56
|
this.logger = logger;
|
|
54
57
|
this.events = events;
|
|
55
58
|
this.presence = presence;
|
|
@@ -61,6 +64,7 @@ class PresenceDatastoreManagerImpl {
|
|
|
61
64
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
62
65
|
this.datastore = { "system:presence": systemWorkspaceDatastore };
|
|
63
66
|
this.workspaces.set("system:presence", systemWorkspace);
|
|
67
|
+
this.targetedSignalSupport = this.runtime.supportedFeatures.has("submit_signals_v2");
|
|
64
68
|
}
|
|
65
69
|
joinSession(clientId) {
|
|
66
70
|
// Broadcast join message to all clients
|
|
@@ -105,7 +109,6 @@ class PresenceDatastoreManagerImpl {
|
|
|
105
109
|
const entry = (0, presenceStates_js_1.createPresenceStates)({
|
|
106
110
|
presence: this.presence,
|
|
107
111
|
attendeeId: this.attendeeId,
|
|
108
|
-
lookupClient: this.lookupClient,
|
|
109
112
|
localUpdate,
|
|
110
113
|
}, workspaceDatastore, requestedContent, controls);
|
|
111
114
|
this.workspaces.set(internalWorkspaceAddress, entry);
|
|
@@ -233,9 +236,18 @@ class PresenceDatastoreManagerImpl {
|
|
|
233
236
|
if (message.content.isComplete) {
|
|
234
237
|
this.refreshBroadcastRequested = false;
|
|
235
238
|
}
|
|
239
|
+
// If the message requests an acknowledgement, we will send a targeted acknowledgement message back to just the requestor.
|
|
240
|
+
if (message.content.acknowledgementId !== undefined) {
|
|
241
|
+
(0, internal_1.assert)(this.targetedSignalSupport, "Acknowledgment message was requested while targeted signal capability is not supported");
|
|
242
|
+
this.runtime.submitSignal({
|
|
243
|
+
type: protocol_js_1.acknowledgementMessageType,
|
|
244
|
+
content: { id: message.content.acknowledgementId },
|
|
245
|
+
targetClientId: message.clientId,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
236
248
|
}
|
|
237
249
|
// Handle activation of unregistered workspaces before processing updates.
|
|
238
|
-
for (const [workspaceAddress] of
|
|
250
|
+
for (const [workspaceAddress] of (0, internalUtils_js_1.objectEntries)(message.content.data)) {
|
|
239
251
|
// The first part of OR condition checks if workspace is already registered.
|
|
240
252
|
// The second part checks if the workspace has already been seen before.
|
|
241
253
|
// In either case we can skip emitting 'workspaceActivated' event.
|
|
@@ -256,7 +268,7 @@ class PresenceDatastoreManagerImpl {
|
|
|
256
268
|
// While the system workspace is processed here too, it is declared as
|
|
257
269
|
// conforming to the general schema. So drop its override.
|
|
258
270
|
const data = message.content.data;
|
|
259
|
-
for (const [workspaceAddress, remoteDatastore] of
|
|
271
|
+
for (const [workspaceAddress, remoteDatastore] of (0, internalUtils_js_1.objectEntries)(data)) {
|
|
260
272
|
// Direct to the appropriate Presence Workspace, if present.
|
|
261
273
|
const workspace = this.workspaces.get(workspaceAddress);
|
|
262
274
|
if (workspace) {
|