@fluid-internal/presence-runtime 2.93.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 (264) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +72 -0
  3. package/dist/package.json +4 -0
  4. package/dist/packageVersion.d.ts +9 -0
  5. package/dist/packageVersion.d.ts.map +1 -0
  6. package/dist/packageVersion.js +12 -0
  7. package/dist/packageVersion.js.map +1 -0
  8. package/dist/runtime/extension/containerPresence.d.ts +53 -0
  9. package/dist/runtime/extension/containerPresence.d.ts.map +1 -0
  10. package/dist/runtime/extension/containerPresence.js +90 -0
  11. package/dist/runtime/extension/containerPresence.js.map +1 -0
  12. package/dist/runtime/extension/index.d.ts +6 -0
  13. package/dist/runtime/extension/index.d.ts.map +1 -0
  14. package/dist/runtime/extension/index.js +11 -0
  15. package/dist/runtime/extension/index.js.map +1 -0
  16. package/dist/runtime/presenceDatastoreManager.d.ts +146 -0
  17. package/dist/runtime/presenceDatastoreManager.d.ts.map +1 -0
  18. package/dist/runtime/presenceDatastoreManager.js +666 -0
  19. package/dist/runtime/presenceDatastoreManager.js.map +1 -0
  20. package/dist/runtime/presenceManager.d.ts +16 -0
  21. package/dist/runtime/presenceManager.d.ts.map +1 -0
  22. package/dist/runtime/presenceManager.js +140 -0
  23. package/dist/runtime/presenceManager.js.map +1 -0
  24. package/dist/runtime/protocol.d.ts +126 -0
  25. package/dist/runtime/protocol.d.ts.map +1 -0
  26. package/dist/runtime/protocol.js +20 -0
  27. package/dist/runtime/protocol.js.map +1 -0
  28. package/dist/runtime/runtimeTypes.d.ts +26 -0
  29. package/dist/runtime/runtimeTypes.d.ts.map +1 -0
  30. package/dist/runtime/runtimeTypes.js +7 -0
  31. package/dist/runtime/runtimeTypes.js.map +1 -0
  32. package/dist/runtime/systemWorkspace.d.ts +39 -0
  33. package/dist/runtime/systemWorkspace.d.ts.map +1 -0
  34. package/dist/runtime/systemWorkspace.js +264 -0
  35. package/dist/runtime/systemWorkspace.js.map +1 -0
  36. package/dist/runtime/test/presenceDatastoreManager.spec.js +618 -0
  37. package/dist/runtime/test/presenceDatastoreManager.spec.js.map +1 -0
  38. package/dist/runtime/test/presenceManager.spec.js +651 -0
  39. package/dist/runtime/test/presenceManager.spec.js.map +1 -0
  40. package/dist/runtime/test.d.ts +12 -0
  41. package/dist/runtime/test.d.ts.map +1 -0
  42. package/dist/runtime/test.js +15 -0
  43. package/dist/runtime/test.js.map +1 -0
  44. package/dist/states/index.d.ts +7 -0
  45. package/dist/states/index.d.ts.map +1 -0
  46. package/dist/states/index.js +12 -0
  47. package/dist/states/index.js.map +1 -0
  48. package/dist/states/latestMapValueManager.d.ts +10 -0
  49. package/dist/states/latestMapValueManager.d.ts.map +1 -0
  50. package/dist/states/latestMapValueManager.js +248 -0
  51. package/dist/states/latestMapValueManager.js.map +1 -0
  52. package/dist/states/latestValueManager.d.ts +10 -0
  53. package/dist/states/latestValueManager.d.ts.map +1 -0
  54. package/dist/states/latestValueManager.js +115 -0
  55. package/dist/states/latestValueManager.js.map +1 -0
  56. package/dist/states/notificationsManager.d.ts +26 -0
  57. package/dist/states/notificationsManager.d.ts.map +1 -0
  58. package/dist/states/notificationsManager.js +97 -0
  59. package/dist/states/notificationsManager.js.map +1 -0
  60. package/dist/states/presence.d.ts +11 -0
  61. package/dist/states/presence.d.ts.map +1 -0
  62. package/dist/states/presence.js +7 -0
  63. package/dist/states/presence.js.map +1 -0
  64. package/dist/states/stateFactory.d.ts +18 -0
  65. package/dist/states/stateFactory.d.ts.map +1 -0
  66. package/dist/states/stateFactory.js +23 -0
  67. package/dist/states/stateFactory.js.map +1 -0
  68. package/dist/states/test/batching.spec.js +843 -0
  69. package/dist/states/test/batching.spec.js.map +1 -0
  70. package/dist/states/test/broadcastControlsTests.js +60 -0
  71. package/dist/states/test/broadcastControlsTests.js.map +1 -0
  72. package/dist/states/test/eventing.spec.js +576 -0
  73. package/dist/states/test/eventing.spec.js.map +1 -0
  74. package/dist/states/test/latestMapValueManager.spec.js +210 -0
  75. package/dist/states/test/latestMapValueManager.spec.js.map +1 -0
  76. package/dist/states/test/latestValueManager.spec.js +193 -0
  77. package/dist/states/test/latestValueManager.spec.js.map +1 -0
  78. package/dist/states/test/mockEphemeralRuntime.js +11 -0
  79. package/dist/states/test/mockEphemeralRuntime.js.map +1 -0
  80. package/dist/states/test/notificationsManager.spec.js +460 -0
  81. package/dist/states/test/notificationsManager.spec.js.map +1 -0
  82. package/dist/states/test/presenceStates.spec.js +73 -0
  83. package/dist/states/test/presenceStates.spec.js.map +1 -0
  84. package/dist/states/test/schemaValidation/protocol.spec.js +246 -0
  85. package/dist/states/test/schemaValidation/protocol.spec.js.map +1 -0
  86. package/dist/states/test/schemaValidation/valueManagers.spec.js +784 -0
  87. package/dist/states/test/schemaValidation/valueManagers.spec.js.map +1 -0
  88. package/dist/states/test/testUtils.js +21 -0
  89. package/dist/states/test/testUtils.js.map +1 -0
  90. package/dist/states/validatedGetter.d.ts +18 -0
  91. package/dist/states/validatedGetter.d.ts.map +1 -0
  92. package/dist/states/validatedGetter.js +43 -0
  93. package/dist/states/validatedGetter.js.map +1 -0
  94. package/dist/test/mockEphemeralRuntime.js +175 -0
  95. package/dist/test/mockEphemeralRuntime.js.map +1 -0
  96. package/dist/test/testUtils.js +262 -0
  97. package/dist/test/testUtils.js.map +1 -0
  98. package/dist/test/utils/index.js +27 -0
  99. package/dist/test/utils/index.js.map +1 -0
  100. package/dist/utils/broadcastControls.d.ts +37 -0
  101. package/dist/utils/broadcastControls.d.ts.map +1 -0
  102. package/dist/utils/broadcastControls.js +60 -0
  103. package/dist/utils/broadcastControls.js.map +1 -0
  104. package/dist/utils/index.d.ts +9 -0
  105. package/dist/utils/index.d.ts.map +1 -0
  106. package/dist/utils/index.js +26 -0
  107. package/dist/utils/index.js.map +1 -0
  108. package/dist/utils/internalUtils.d.ts +125 -0
  109. package/dist/utils/internalUtils.d.ts.map +1 -0
  110. package/dist/utils/internalUtils.js +99 -0
  111. package/dist/utils/internalUtils.js.map +1 -0
  112. package/dist/utils/test/timerManager.spec.js +93 -0
  113. package/dist/utils/test/timerManager.spec.js.map +1 -0
  114. package/dist/utils/timerManager.d.ts +37 -0
  115. package/dist/utils/timerManager.d.ts.map +1 -0
  116. package/dist/utils/timerManager.js +65 -0
  117. package/dist/utils/timerManager.js.map +1 -0
  118. package/dist/utils/valueManager.d.ts +14 -0
  119. package/dist/utils/valueManager.d.ts.map +1 -0
  120. package/dist/utils/valueManager.js +22 -0
  121. package/dist/utils/valueManager.js.map +1 -0
  122. package/dist/workspace/index.d.ts +7 -0
  123. package/dist/workspace/index.d.ts.map +1 -0
  124. package/dist/workspace/index.js +14 -0
  125. package/dist/workspace/index.js.map +1 -0
  126. package/dist/workspace/presenceStates.d.ts +61 -0
  127. package/dist/workspace/presenceStates.d.ts.map +1 -0
  128. package/dist/workspace/presenceStates.js +235 -0
  129. package/dist/workspace/presenceStates.js.map +1 -0
  130. package/dist/workspace/stateDatastore.d.ts +17 -0
  131. package/dist/workspace/stateDatastore.d.ts.map +1 -0
  132. package/dist/workspace/stateDatastore.js +24 -0
  133. package/dist/workspace/stateDatastore.js.map +1 -0
  134. package/lib/packageVersion.d.ts +9 -0
  135. package/lib/packageVersion.d.ts.map +1 -0
  136. package/lib/packageVersion.js +9 -0
  137. package/lib/packageVersion.js.map +1 -0
  138. package/lib/runtime/extension/containerPresence.d.ts +53 -0
  139. package/lib/runtime/extension/containerPresence.d.ts.map +1 -0
  140. package/lib/runtime/extension/containerPresence.js +87 -0
  141. package/lib/runtime/extension/containerPresence.js.map +1 -0
  142. package/lib/runtime/extension/index.d.ts +6 -0
  143. package/lib/runtime/extension/index.d.ts.map +1 -0
  144. package/lib/runtime/extension/index.js +6 -0
  145. package/lib/runtime/extension/index.js.map +1 -0
  146. package/lib/runtime/presenceDatastoreManager.d.ts +146 -0
  147. package/lib/runtime/presenceDatastoreManager.d.ts.map +1 -0
  148. package/lib/runtime/presenceDatastoreManager.js +662 -0
  149. package/lib/runtime/presenceDatastoreManager.js.map +1 -0
  150. package/lib/runtime/presenceManager.d.ts +16 -0
  151. package/lib/runtime/presenceManager.d.ts.map +1 -0
  152. package/lib/runtime/presenceManager.js +136 -0
  153. package/lib/runtime/presenceManager.js.map +1 -0
  154. package/lib/runtime/protocol.d.ts +126 -0
  155. package/lib/runtime/protocol.d.ts.map +1 -0
  156. package/lib/runtime/protocol.js +17 -0
  157. package/lib/runtime/protocol.js.map +1 -0
  158. package/lib/runtime/runtimeTypes.d.ts +26 -0
  159. package/lib/runtime/runtimeTypes.d.ts.map +1 -0
  160. package/lib/runtime/runtimeTypes.js +6 -0
  161. package/lib/runtime/runtimeTypes.js.map +1 -0
  162. package/lib/runtime/systemWorkspace.d.ts +39 -0
  163. package/lib/runtime/systemWorkspace.d.ts.map +1 -0
  164. package/lib/runtime/systemWorkspace.js +260 -0
  165. package/lib/runtime/systemWorkspace.js.map +1 -0
  166. package/lib/runtime/test/presenceDatastoreManager.spec.js +616 -0
  167. package/lib/runtime/test/presenceDatastoreManager.spec.js.map +1 -0
  168. package/lib/runtime/test/presenceManager.spec.js +649 -0
  169. package/lib/runtime/test/presenceManager.spec.js.map +1 -0
  170. package/lib/runtime/test.d.ts +12 -0
  171. package/lib/runtime/test.d.ts.map +1 -0
  172. package/lib/runtime/test.js +10 -0
  173. package/lib/runtime/test.js.map +1 -0
  174. package/lib/states/index.d.ts +7 -0
  175. package/lib/states/index.d.ts.map +1 -0
  176. package/lib/states/index.js +7 -0
  177. package/lib/states/index.js.map +1 -0
  178. package/lib/states/latestMapValueManager.d.ts +10 -0
  179. package/lib/states/latestMapValueManager.d.ts.map +1 -0
  180. package/lib/states/latestMapValueManager.js +244 -0
  181. package/lib/states/latestMapValueManager.js.map +1 -0
  182. package/lib/states/latestValueManager.d.ts +10 -0
  183. package/lib/states/latestValueManager.d.ts.map +1 -0
  184. package/lib/states/latestValueManager.js +111 -0
  185. package/lib/states/latestValueManager.js.map +1 -0
  186. package/lib/states/notificationsManager.d.ts +26 -0
  187. package/lib/states/notificationsManager.d.ts.map +1 -0
  188. package/lib/states/notificationsManager.js +93 -0
  189. package/lib/states/notificationsManager.js.map +1 -0
  190. package/lib/states/presence.d.ts +11 -0
  191. package/lib/states/presence.d.ts.map +1 -0
  192. package/lib/states/presence.js +6 -0
  193. package/lib/states/presence.js.map +1 -0
  194. package/lib/states/stateFactory.d.ts +18 -0
  195. package/lib/states/stateFactory.d.ts.map +1 -0
  196. package/lib/states/stateFactory.js +20 -0
  197. package/lib/states/stateFactory.js.map +1 -0
  198. package/lib/states/test/batching.spec.js +841 -0
  199. package/lib/states/test/batching.spec.js.map +1 -0
  200. package/lib/states/test/broadcastControlsTests.js +56 -0
  201. package/lib/states/test/broadcastControlsTests.js.map +1 -0
  202. package/lib/states/test/eventing.spec.js +574 -0
  203. package/lib/states/test/eventing.spec.js.map +1 -0
  204. package/lib/states/test/latestMapValueManager.spec.js +206 -0
  205. package/lib/states/test/latestMapValueManager.spec.js.map +1 -0
  206. package/lib/states/test/latestValueManager.spec.js +189 -0
  207. package/lib/states/test/latestValueManager.spec.js.map +1 -0
  208. package/lib/states/test/mockEphemeralRuntime.js +6 -0
  209. package/lib/states/test/mockEphemeralRuntime.js.map +1 -0
  210. package/lib/states/test/notificationsManager.spec.js +456 -0
  211. package/lib/states/test/notificationsManager.spec.js.map +1 -0
  212. package/lib/states/test/presenceStates.spec.js +69 -0
  213. package/lib/states/test/presenceStates.spec.js.map +1 -0
  214. package/lib/states/test/schemaValidation/protocol.spec.js +244 -0
  215. package/lib/states/test/schemaValidation/protocol.spec.js.map +1 -0
  216. package/lib/states/test/schemaValidation/valueManagers.spec.js +782 -0
  217. package/lib/states/test/schemaValidation/valueManagers.spec.js.map +1 -0
  218. package/lib/states/test/testUtils.js +6 -0
  219. package/lib/states/test/testUtils.js.map +1 -0
  220. package/lib/states/validatedGetter.d.ts +18 -0
  221. package/lib/states/validatedGetter.d.ts.map +1 -0
  222. package/lib/states/validatedGetter.js +39 -0
  223. package/lib/states/validatedGetter.js.map +1 -0
  224. package/lib/test/mockEphemeralRuntime.js +171 -0
  225. package/lib/test/mockEphemeralRuntime.js.map +1 -0
  226. package/lib/test/testUtils.js +251 -0
  227. package/lib/test/testUtils.js.map +1 -0
  228. package/lib/test/utils/index.js +8 -0
  229. package/lib/test/utils/index.js.map +1 -0
  230. package/lib/utils/broadcastControls.d.ts +37 -0
  231. package/lib/utils/broadcastControls.d.ts.map +1 -0
  232. package/lib/utils/broadcastControls.js +55 -0
  233. package/lib/utils/broadcastControls.js.map +1 -0
  234. package/lib/utils/index.d.ts +9 -0
  235. package/lib/utils/index.d.ts.map +1 -0
  236. package/lib/utils/index.js +9 -0
  237. package/lib/utils/index.js.map +1 -0
  238. package/lib/utils/internalUtils.d.ts +125 -0
  239. package/lib/utils/internalUtils.d.ts.map +1 -0
  240. package/lib/utils/internalUtils.js +90 -0
  241. package/lib/utils/internalUtils.js.map +1 -0
  242. package/lib/utils/test/timerManager.spec.js +91 -0
  243. package/lib/utils/test/timerManager.spec.js.map +1 -0
  244. package/lib/utils/timerManager.d.ts +37 -0
  245. package/lib/utils/timerManager.d.ts.map +1 -0
  246. package/lib/utils/timerManager.js +61 -0
  247. package/lib/utils/timerManager.js.map +1 -0
  248. package/lib/utils/valueManager.d.ts +14 -0
  249. package/lib/utils/valueManager.d.ts.map +1 -0
  250. package/lib/utils/valueManager.js +17 -0
  251. package/lib/utils/valueManager.js.map +1 -0
  252. package/lib/workspace/index.d.ts +7 -0
  253. package/lib/workspace/index.d.ts.map +1 -0
  254. package/lib/workspace/index.js +7 -0
  255. package/lib/workspace/index.js.map +1 -0
  256. package/lib/workspace/presenceStates.d.ts +61 -0
  257. package/lib/workspace/presenceStates.d.ts.map +1 -0
  258. package/lib/workspace/presenceStates.js +229 -0
  259. package/lib/workspace/presenceStates.js.map +1 -0
  260. package/lib/workspace/stateDatastore.d.ts +17 -0
  261. package/lib/workspace/stateDatastore.d.ts.map +1 -0
  262. package/lib/workspace/stateDatastore.js +19 -0
  263. package/lib/workspace/stateDatastore.js.map +1 -0
  264. package/package.json +158 -0
@@ -0,0 +1,229 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { assert } from "@fluidframework/core-utils/internal";
6
+ import { getOrCreateRecord, objectEntries, RequiredBroadcastControl, unbrandIVM, } from "@fluid-internal/presence-runtime/utils";
7
+ import { handleFromDatastore } from "./stateDatastore.js";
8
+ function isValueDirectory(value) {
9
+ return "items" in value;
10
+ }
11
+ /**
12
+ * Merge a value directory.
13
+ *
14
+ * @privateRemarks
15
+ * This implementation uses the InternalTypes set of Value types but it is
16
+ * agnostic so long as the validatable versions don't start requiring
17
+ * properties.
18
+ *
19
+ * @internal
20
+ */
21
+ export function mergeValueDirectory(base, update, timeDelta) {
22
+ if (!isValueDirectory(update)) {
23
+ if (base === undefined || update.rev > base.rev) {
24
+ return { ...update, timestamp: update.timestamp + timeDelta };
25
+ }
26
+ return base;
27
+ }
28
+ let mergeBase;
29
+ if (base === undefined) {
30
+ mergeBase = { rev: update.rev, items: {} };
31
+ }
32
+ else {
33
+ const baseIsDirectory = isValueDirectory(base);
34
+ if (base.rev >= update.rev) {
35
+ if (!baseIsDirectory) {
36
+ // base is leaf value that is more recent - nothing to do
37
+ return base;
38
+ }
39
+ // While base has more advanced revision, assume mis-ordering or
40
+ // missed and catchup update needs merged in.
41
+ mergeBase = base;
42
+ }
43
+ else {
44
+ mergeBase = { rev: update.rev, items: baseIsDirectory ? base.items : {} };
45
+ }
46
+ }
47
+ for (const [key, value] of Object.entries(update.items)) {
48
+ const baseElement = mergeBase.items[key];
49
+ mergeBase.items[key] = mergeValueDirectory(baseElement, value, timeDelta);
50
+ }
51
+ return mergeBase;
52
+ }
53
+ /**
54
+ * Updates remote state into the local [untracked] datastore.
55
+ *
56
+ * @param key - The key of the datastore to merge the untracked data into.
57
+ * @param remoteAllKnownState - The remote state to merge into the datastore.
58
+ * @param datastore - The datastore to merge the untracked data into.
59
+ *
60
+ * @remarks
61
+ * In the case of ignored unmonitored data, the client entries are not stored,
62
+ * though the value keys will be populated and often remain empty.
63
+ *
64
+ * @internal
65
+ */
66
+ export function mergeUntrackedDatastore(key, remoteAllKnownState, datastore, timeModifier) {
67
+ const localAllKnownState = getOrCreateRecord(datastore, key, () => ({}));
68
+ for (const [attendeeId, value] of objectEntries(remoteAllKnownState)) {
69
+ if (!("ignoreUnmonitored" in value)) {
70
+ localAllKnownState[attendeeId] = mergeValueDirectory(localAllKnownState[attendeeId], value, timeModifier);
71
+ }
72
+ }
73
+ }
74
+ /**
75
+ * The default allowable update latency for StatesWorkspace in milliseconds.
76
+ */
77
+ const defaultAllowableUpdateLatencyMs = 60;
78
+ /**
79
+ * No-runtime-effect helper to protect cast from unknown datastore to specific
80
+ * schema record type. (It is up to consumer to check that record conforms to
81
+ * expectations.)
82
+ */
83
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
84
+ function castUnknownRecordToSchemaRecord(record) {
85
+ return record;
86
+ }
87
+ class PresenceStatesImpl {
88
+ constructor(runtime, datastore, initialContent, controlsSettings) {
89
+ this.runtime = runtime;
90
+ this.datastore = datastore;
91
+ this.controls = new RequiredBroadcastControl(defaultAllowableUpdateLatencyMs);
92
+ if (controlsSettings?.allowableUpdateLatencyMs !== undefined) {
93
+ this.controls.allowableUpdateLatencyMs = controlsSettings.allowableUpdateLatencyMs;
94
+ }
95
+ // Prepare initial map content from initial state
96
+ {
97
+ const attendeeId = this.runtime.attendeeId;
98
+ // Empty record does not satisfy the type, but nodes will post loop.
99
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
100
+ const nodes = {};
101
+ let anyInitialValues = false;
102
+ const newValues = {};
103
+ let cumulativeAllowableUpdateLatencyMs;
104
+ for (const [key, nodeFactory] of Object.entries(initialContent)) {
105
+ const newNodeData = nodeFactory(key, handleFromDatastore(this));
106
+ nodes[key] = newNodeData.manager;
107
+ if ("initialData" in newNodeData) {
108
+ const { value, allowableUpdateLatencyMs } = newNodeData.initialData;
109
+ (datastore[key] ??= {})[attendeeId] = value;
110
+ newValues[key] = value;
111
+ if (allowableUpdateLatencyMs !== undefined) {
112
+ cumulativeAllowableUpdateLatencyMs =
113
+ cumulativeAllowableUpdateLatencyMs === undefined
114
+ ? allowableUpdateLatencyMs
115
+ : Math.min(cumulativeAllowableUpdateLatencyMs, allowableUpdateLatencyMs);
116
+ }
117
+ anyInitialValues = true;
118
+ }
119
+ }
120
+ this.nodes = nodes;
121
+ // states and notifications are the public view of nodes that limits the entries
122
+ // types to the public interface of State objects with an additional type
123
+ // filter that beguiles the type system. So just reinterpret cast.
124
+ const properties = nodes;
125
+ // `AnyWorkspace` support comes from defining both `states` for
126
+ // `StatesWorkspace` and `notifications` for `NotificationsWorkspace`.
127
+ // `notifications` is always a subset of what `states` can be; so the same.
128
+ this.notifications = this.states = properties;
129
+ if (anyInitialValues) {
130
+ this.runtime.localUpdate(newValues, {
131
+ allowableUpdateLatencyMs: cumulativeAllowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,
132
+ });
133
+ }
134
+ }
135
+ }
136
+ get presence() {
137
+ return this.runtime.presence;
138
+ }
139
+ knownValues(key) {
140
+ return {
141
+ self: this.runtime.attendeeId,
142
+ // Caller must only use `key`s that are part of `this.datastore`.
143
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
144
+ states: castUnknownRecordToSchemaRecord(this.datastore[key]),
145
+ };
146
+ }
147
+ localUpdate(key, value, options) {
148
+ this.runtime.localUpdate({ [key]: value }, {
149
+ ...options,
150
+ allowableUpdateLatencyMs: options.allowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,
151
+ });
152
+ }
153
+ update(key, clientId, value) {
154
+ // Callers my only use `key`s that are part of `this.datastore`.
155
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
156
+ const allKnownState = this.datastore[key];
157
+ allKnownState[clientId] = mergeValueDirectory(allKnownState[clientId], value, 0);
158
+ }
159
+ add(key, nodeFactory) {
160
+ assert(!(key in this.nodes), 0xa3c /* Already have entry for key in map */);
161
+ const nodeData = nodeFactory(key, handleFromDatastore(this));
162
+ this.nodes[key] = nodeData.manager;
163
+ if ("initialData" in nodeData) {
164
+ const { value, allowableUpdateLatencyMs } = nodeData.initialData;
165
+ let datastoreValue = this.datastore[key];
166
+ if (datastoreValue === undefined) {
167
+ datastoreValue = this.datastore[key] = {};
168
+ }
169
+ else {
170
+ // Already have received state from other clients. Kept in `all`.
171
+ // TODO: Send current `all` state to state manager.
172
+ }
173
+ datastoreValue[this.runtime.attendeeId] = value;
174
+ this.runtime.localUpdate({ [key]: value }, {
175
+ allowableUpdateLatencyMs: allowableUpdateLatencyMs ?? this.controls.allowableUpdateLatencyMs,
176
+ });
177
+ }
178
+ }
179
+ ensureContent(content, controls) {
180
+ if (controls?.allowableUpdateLatencyMs !== undefined) {
181
+ this.controls.allowableUpdateLatencyMs = controls.allowableUpdateLatencyMs;
182
+ }
183
+ for (const [key, nodeFactory] of Object.entries(content)) {
184
+ const brandedIVM = this.nodes[key];
185
+ if (brandedIVM === undefined) {
186
+ this.add(key, nodeFactory);
187
+ }
188
+ else {
189
+ const node = unbrandIVM(brandedIVM);
190
+ if (!(node instanceof nodeFactory.instanceBase)) {
191
+ throw new TypeError(`State "${key}" previously created by different State object.`);
192
+ }
193
+ }
194
+ }
195
+ return this;
196
+ }
197
+ processUpdate(received, timeModifier, remoteDatastore) {
198
+ const postUpdateActions = [];
199
+ for (const [key, remoteAllKnownState] of Object.entries(remoteDatastore)) {
200
+ const brandedIVM = this.nodes[key];
201
+ if (brandedIVM === undefined) {
202
+ // Assume all broadcast state is meant to be kept even if not currently registered.
203
+ mergeUntrackedDatastore(key, remoteAllKnownState, this.datastore, timeModifier);
204
+ }
205
+ else {
206
+ const node = unbrandIVM(brandedIVM);
207
+ for (const [attendeeId, value] of objectEntries(remoteAllKnownState)) {
208
+ const client = this.runtime.presence.attendees.getAttendee(attendeeId);
209
+ postUpdateActions.push(...node.update(client, received, value));
210
+ }
211
+ }
212
+ }
213
+ return postUpdateActions;
214
+ }
215
+ }
216
+ /**
217
+ * Create a new Workspace using the DataStoreRuntime provided.
218
+ * @param initialContent - The initial State objects to register.
219
+ *
220
+ * @internal
221
+ */
222
+ export function createPresenceStates(runtime, datastore, initialContent, controls) {
223
+ const impl = new PresenceStatesImpl(runtime, datastore, initialContent, controls);
224
+ return {
225
+ public: impl,
226
+ internal: impl,
227
+ };
228
+ }
229
+ //# sourceMappingURL=presenceStates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presenceStates.js","sourceRoot":"","sources":["../../src/workspace/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 type {\n\tAttendeeId,\n\tBroadcastControlSettings,\n\tPresenceWithNotifications as Presence,\n\tStatesWorkspace,\n\tStatesWorkspaceSchema,\n} from \"@fluid-internal/presence-definitions\";\nimport type {\n\tAnyWorkspace,\n\tInternalTypes,\n\tPostUpdateAction,\n\tValidatableOptionalState,\n\tValidatableRequiredState,\n\tValidatableValueDirectory,\n\tValidatableValueDirectoryOrState,\n\tValidatableValueStructure,\n} from \"@fluid-internal/presence-definitions/internal\";\nimport type { ClientRecord } from \"@fluid-internal/presence-definitions/internal/workspace\";\nimport type {\n\tClientUpdateEntry,\n\tPresenceStatesInternal,\n\tRuntimeLocalUpdateOptions,\n\tValueElementMap,\n\tValueUpdateRecord,\n} from \"@fluid-internal/presence-definitions/internal/workspace-runtime\";\nimport type {\n\tLocalStateUpdateOptions,\n\tStateDatastore,\n} from \"@fluid-internal/presence-definitions/internal/workspace-states\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\n\nimport type { RecordEntryTypes } from \"@fluid-internal/presence-runtime/utils\";\nimport {\n\tgetOrCreateRecord,\n\tobjectEntries,\n\tRequiredBroadcastControl,\n\tunbrandIVM,\n} from \"@fluid-internal/presence-runtime/utils\";\n\nimport { handleFromDatastore } from \"./stateDatastore.js\";\n\n/**\n * Extracts `Part` from {@link InternalTypes.ManagerFactory} return type\n * matching the {@link StatesWorkspaceSchema} `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. Exclude\\<, undefined\\> can be used as needed.\n */\ntype MapSchemaElement<\n\tTSchema extends StatesWorkspaceSchema,\n\tPart extends keyof ReturnType<TSchema[keyof TSchema]>,\n\tKeys extends keyof TSchema = keyof TSchema,\n> = ReturnType<TSchema[Keys]>[Part];\n\n/**\n * Contract for `PresenceDatastoreManager` as required by States Workspaces ({@link PresenceStatesImpl}).\n */\ninterface PresenceRuntime {\n\treadonly presence: Presence;\n\treadonly attendeeId: AttendeeId;\n\tlocalUpdate(\n\t\tstates: { [key: string]: ClientUpdateEntry },\n\t\toptions: RuntimeLocalUpdateOptions,\n\t): void;\n}\n\ntype PresenceSubSchemaFromWorkspaceSchema<\n\tTSchema extends StatesWorkspaceSchema,\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 StatesWorkspaceSchema> = PresenceSubSchemaFromWorkspaceSchema<\n\tTSchema,\n\t\"manager\"\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// function overloads\n/**\n * Non-validatable types\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/**\n * Validatable base type with non-validatable update types\n *\n * @internal\n */\nexport function mergeValueDirectory<\n\tT,\n\tTBaseState extends ValidatableRequiredState<T> | ValidatableOptionalState<T>,\n\tTUpdateState extends\n\t\t| InternalTypes.ValueRequiredState<T>\n\t\t| InternalTypes.ValueOptionalState<T>,\n>(\n\tbase: TBaseState | ValidatableValueDirectory<T> | undefined,\n\tupdate: TUpdateState | InternalTypes.ValueDirectory<T>,\n\ttimeDelta: number,\n): TBaseState | ValidatableValueDirectory<T>;\n/**\n * Fully validatable types\n *\n * @internal\n */\nexport function mergeValueDirectory<\n\tT,\n\tTValueState extends ValidatableRequiredState<T> | ValidatableOptionalState<T>,\n>(\n\tbase: TValueState | ValidatableValueDirectory<T> | undefined,\n\tupdate: TValueState | ValidatableValueDirectory<T>,\n\ttimeDelta: number,\n): TValueState | ValidatableValueDirectory<T>;\n/**\n * Merge a value directory.\n *\n * @privateRemarks\n * This implementation uses the InternalTypes set of Value types but it is\n * agnostic so long as the validatable versions don't start requiring\n * properties.\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: ValueUpdateRecord[string],\n\tdatastore: ValueElementMap<StatesWorkspaceSchema>,\n\ttimeModifier: number,\n): void {\n\tconst localAllKnownState = getOrCreateRecord(\n\t\tdatastore,\n\t\tkey,\n\t\t(): RecordEntryTypes<typeof datastore> => ({}),\n\t);\n\tfor (const [attendeeId, value] of objectEntries(remoteAllKnownState)) {\n\t\tif (!(\"ignoreUnmonitored\" in value)) {\n\t\t\tlocalAllKnownState[attendeeId] = mergeValueDirectory(\n\t\t\t\tlocalAllKnownState[attendeeId],\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 StatesWorkspace 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 StatesWorkspaceSchema,\n\tKeys extends keyof TSchema,\n> = Exclude<MapSchemaElement<TSchema, \"initialData\", Keys>, undefined>[\"value\"];\n\n/**\n * No-runtime-effect helper to protect cast from unknown datastore to specific\n * schema record type. (It is up to consumer to check that record conforms to\n * expectations.)\n */\n// eslint-disable-next-line @typescript-eslint/explicit-function-return-type\nfunction castUnknownRecordToSchemaRecord<\n\tTSchema extends StatesWorkspaceSchema,\n\tKey extends keyof TSchema & string,\n>(record: ClientRecord<ValidatableValueDirectoryOrState<unknown>>) {\n\treturn record as ClientRecord<\n\t\tValidatableValueStructure<SchemaElementValueType<TSchema, Key>>\n\t>;\n}\n\nclass PresenceStatesImpl<TSchema extends StatesWorkspaceSchema>\n\timplements\n\t\tPresenceStatesInternal,\n\t\tAnyWorkspace<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 states: StatesWorkspace<TSchema>[\"states\"];\n\tpublic readonly notifications: AnyWorkspace<TSchema>[\"notifications\"];\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 attendeeId = this.runtime.attendeeId;\n\t\t\t// Empty record does not satisfy the type, but nodes will post loop.\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\tconst nodes = {} as MapEntries<TSchema>;\n\t\t\tlet anyInitialValues = false;\n\t\t\tconst newValues: { [key: string]: InternalTypes.ValueDirectoryOrState<unknown> } = {};\n\t\t\tlet cumulativeAllowableUpdateLatencyMs: number | undefined;\n\t\t\tfor (const [key, nodeFactory] of Object.entries(initialContent)) {\n\t\t\t\tconst newNodeData = nodeFactory(key, handleFromDatastore(this));\n\t\t\t\tnodes[key as keyof TSchema] = newNodeData.manager;\n\t\t\t\tif (\"initialData\" in newNodeData) {\n\t\t\t\t\tconst { value, allowableUpdateLatencyMs } = newNodeData.initialData;\n\t\t\t\t\t(datastore[key] ??= {})[attendeeId] = value;\n\t\t\t\t\tnewValues[key] = value;\n\t\t\t\t\tif (allowableUpdateLatencyMs !== undefined) {\n\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs =\n\t\t\t\t\t\t\tcumulativeAllowableUpdateLatencyMs === undefined\n\t\t\t\t\t\t\t\t? allowableUpdateLatencyMs\n\t\t\t\t\t\t\t\t: Math.min(cumulativeAllowableUpdateLatencyMs, allowableUpdateLatencyMs);\n\t\t\t\t\t}\n\t\t\t\t\tanyInitialValues = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.nodes = nodes;\n\t\t\t// states and notifications are the public view of nodes that limits the entries\n\t\t\t// types to the public interface of State objects with an additional type\n\t\t\t// filter that beguiles the type system. So just reinterpret cast.\n\t\t\tconst properties = nodes as unknown as AnyWorkspace<TSchema>[\"states\"];\n\t\t\t// `AnyWorkspace` support comes from defining both `states` for\n\t\t\t// `StatesWorkspace` and `notifications` for `NotificationsWorkspace`.\n\t\t\t// `notifications` is always a subset of what `states` can be; so the same.\n\t\t\tthis.notifications = this.states = properties;\n\n\t\t\tif (anyInitialValues) {\n\t\t\t\tthis.runtime.localUpdate(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 get presence(): Presence {\n\t\treturn this.runtime.presence;\n\t}\n\n\tpublic knownValues<Key extends keyof TSchema & string>(\n\t\tkey: Key,\n\t): {\n\t\tself: AttendeeId | undefined;\n\t\tstates: ClientRecord<ValidatableValueStructure<SchemaElementValueType<TSchema, Key>>>;\n\t} {\n\t\treturn {\n\t\t\tself: this.runtime.attendeeId,\n\t\t\t// Caller must only use `key`s that are part of `this.datastore`.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tstates: castUnknownRecordToSchemaRecord(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: AttendeeId,\n\t\tvalue: ValidatableValueDirectoryOrState<unknown>,\n\t): void {\n\t\t// Callers my only use `key`s that are part of `this.datastore`.\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst allKnownState = this.datastore[key]!;\n\t\tallKnownState[clientId] = mergeValueDirectory<unknown, ValidatableRequiredState<unknown>>(\n\t\t\tallKnownState[clientId],\n\t\t\tvalue,\n\t\t\t0,\n\t\t);\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 StatesWorkspace<\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\tlet datastoreValue = this.datastore[key];\n\t\t\tif (datastoreValue === undefined) {\n\t\t\t\tdatastoreValue = this.datastore[key] = {};\n\t\t\t} else {\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}\n\t\t\tdatastoreValue[this.runtime.attendeeId] = 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 StatesWorkspaceSchema>(\n\t\tcontent: TSchemaAdditional,\n\t\tcontrols: BroadcastControlSettings | undefined,\n\t): AnyWorkspace<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\tconst brandedIVM = this.nodes[key];\n\t\t\tif (brandedIVM === undefined) {\n\t\t\t\tthis.add(key, nodeFactory);\n\t\t\t} else {\n\t\t\t\tconst node = unbrandIVM(brandedIVM);\n\t\t\t\tif (!(node instanceof nodeFactory.instanceBase)) {\n\t\t\t\t\tthrow new TypeError(`State \"${key}\" previously created by different State object.`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn this as AnyWorkspace<TSchema & TSchemaAdditional>;\n\t}\n\n\tpublic processUpdate(\n\t\treceived: number,\n\t\ttimeModifier: number,\n\t\tremoteDatastore: ValueUpdateRecord,\n\t): PostUpdateAction[] {\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tfor (const [key, remoteAllKnownState] of Object.entries(remoteDatastore)) {\n\t\t\tconst brandedIVM = this.nodes[key];\n\t\t\tif (brandedIVM === undefined) {\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} else {\n\t\t\t\tconst node = unbrandIVM(brandedIVM);\n\t\t\t\tfor (const [attendeeId, value] of objectEntries(remoteAllKnownState)) {\n\t\t\t\t\tconst client = this.runtime.presence.attendees.getAttendee(attendeeId);\n\t\t\t\t\tpostUpdateActions.push(...node.update(client, received, value));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn postUpdateActions;\n\t}\n}\n\n/**\n * Create a new Workspace using the DataStoreRuntime provided.\n * @param initialContent - The initial State objects to register.\n *\n * @internal\n */\nexport function createPresenceStates<TSchema extends StatesWorkspaceSchema>(\n\truntime: PresenceRuntime,\n\tdatastore: ValueElementMap<StatesWorkspaceSchema>,\n\tinitialContent: TSchema,\n\tcontrols: BroadcastControlSettings | undefined,\n): { public: AnyWorkspace<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"]}
@@ -0,0 +1,17 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import type { InternalTypes } from "@fluid-internal/presence-definitions/internal";
6
+ import type { StateDatastore } from "@fluid-internal/presence-definitions/internal/workspace-states";
7
+ /**
8
+ * Helper to get a handle from a datastore.
9
+ */
10
+ export declare function handleFromDatastore<TKey extends string, TValue extends InternalTypes.ValueDirectoryOrState<unknown>>(datastore: StateDatastore<TKey, TValue>): InternalTypes.StateDatastoreHandle<TKey, Exclude<TValue, undefined>>;
11
+ /**
12
+ * Helper to get the datastore back from its handle.
13
+ *
14
+ * @internal
15
+ */
16
+ export declare function datastoreFromHandle<TKey extends string, TValue extends InternalTypes.ValueDirectoryOrState<unknown>>(handle: InternalTypes.StateDatastoreHandle<TKey, TValue>): StateDatastore<TKey, TValue>;
17
+ //# sourceMappingURL=stateDatastore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateDatastore.d.ts","sourceRoot":"","sources":["../../src/workspace/stateDatastore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+CAA+C,CAAC;AACnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gEAAgE,CAAC;AAErG;;GAEG;AACH,wBAAgB,mBAAmB,CAIlC,IAAI,SAAS,MAAM,EACnB,MAAM,SAAS,aAAa,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAE3D,SAAS,EAAE,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,GACrC,aAAa,CAAC,oBAAoB,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAKtE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAClC,IAAI,SAAS,MAAM,EACnB,MAAM,SAAS,aAAa,CAAC,qBAAqB,CAAC,OAAO,CAAC,EAC1D,MAAM,EAAE,aAAa,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAExF"}
@@ -0,0 +1,19 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ /**
6
+ * Helper to get a handle from a datastore.
7
+ */
8
+ export function handleFromDatastore(datastore) {
9
+ return datastore;
10
+ }
11
+ /**
12
+ * Helper to get the datastore back from its handle.
13
+ *
14
+ * @internal
15
+ */
16
+ export function datastoreFromHandle(handle) {
17
+ return handle;
18
+ }
19
+ //# sourceMappingURL=stateDatastore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateDatastore.js","sourceRoot":"","sources":["../../src/workspace/stateDatastore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAOlC,SAAuC;IAEvC,OAAO,SAGN,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAGjC,MAAwD;IACzD,OAAO,MAAiD,CAAC;AAC1D,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { InternalTypes } from \"@fluid-internal/presence-definitions/internal\";\nimport type { StateDatastore } from \"@fluid-internal/presence-definitions/internal/workspace-states\";\n\n/**\n * Helper to get a handle from a datastore.\n */\nexport function handleFromDatastore<\n\t// Constraining TSchema would be great, but it seems nested types (at least with undefined) cause trouble.\n\t// TSchema as `unknown` still provides some type safety.\n\t// TSchema extends StateDatastoreSchema,\n\tTKey extends string /* & keyof TSchema */,\n\tTValue extends InternalTypes.ValueDirectoryOrState<unknown>,\n>(\n\tdatastore: StateDatastore<TKey, TValue>,\n): InternalTypes.StateDatastoreHandle<TKey, Exclude<TValue, undefined>> {\n\treturn datastore as unknown as InternalTypes.StateDatastoreHandle<\n\t\tTKey,\n\t\tExclude<TValue, undefined>\n\t>;\n}\n\n/**\n * Helper to get the datastore back from its handle.\n *\n * @internal\n */\nexport function datastoreFromHandle<\n\tTKey extends string,\n\tTValue extends InternalTypes.ValueDirectoryOrState<unknown>,\n>(handle: InternalTypes.StateDatastoreHandle<TKey, TValue>): StateDatastore<TKey, TValue> {\n\treturn handle as unknown as StateDatastore<TKey, TValue>;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,158 @@
1
+ {
2
+ "name": "@fluid-internal/presence-runtime",
3
+ "version": "2.93.0",
4
+ "description": "Core runtime implementation for Fluid Framework presence",
5
+ "homepage": "https://fluidframework.com",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/microsoft/FluidFramework.git",
9
+ "directory": "packages/framework/presence-runtime"
10
+ },
11
+ "license": "MIT",
12
+ "author": "Microsoft and contributors",
13
+ "sideEffects": false,
14
+ "type": "module",
15
+ "exports": {
16
+ "./states": {
17
+ "import": {
18
+ "types": "./lib/states/index.d.ts",
19
+ "default": "./lib/states/index.js"
20
+ },
21
+ "require": {
22
+ "types": "./dist/states/index.d.ts",
23
+ "default": "./dist/states/index.js"
24
+ }
25
+ },
26
+ "./extension": {
27
+ "import": "./lib/runtime/extension/index.js",
28
+ "require": "./dist/runtime/extension/index.js"
29
+ },
30
+ "./utils": {
31
+ "import": "./lib/utils/index.js",
32
+ "require": "./dist/utils/index.js"
33
+ },
34
+ "./workspace": {
35
+ "import": "./lib/workspace/index.js",
36
+ "require": "./dist/workspace/index.js"
37
+ },
38
+ "./internal/protocol": {
39
+ "allow-ff-test-exports": {
40
+ "types": {
41
+ "import": "./lib/runtime/protocol.d.ts",
42
+ "require": "./dist/runtime/protocol.d.ts"
43
+ }
44
+ }
45
+ },
46
+ "./internal/test": {
47
+ "allow-ff-test-exports": {
48
+ "import": "./lib/runtime/test.js",
49
+ "require": "./dist/runtime/test.js"
50
+ }
51
+ },
52
+ "./internal/test-utils": {
53
+ "allow-ff-test-exports": {
54
+ "import": "./lib/test/utils/index.js",
55
+ "require": "./dist/test/utils/index.js"
56
+ }
57
+ }
58
+ },
59
+ "files": [
60
+ "dist/**/*",
61
+ "lib/**/*",
62
+ "!**/test/**/*"
63
+ ],
64
+ "c8": {
65
+ "all": true,
66
+ "cache-dir": "nyc/.cache",
67
+ "exclude": [
68
+ "src/**/test/**/*.*ts",
69
+ "dist/**/test/**/*.*js",
70
+ "lib/**/test/**/*.*js"
71
+ ],
72
+ "exclude-after-remap": false,
73
+ "include": [
74
+ "src/**/*.*ts",
75
+ "dist/**/*.*js",
76
+ "lib/**/*.*js"
77
+ ],
78
+ "report-dir": "nyc/report",
79
+ "reporter": [
80
+ "cobertura",
81
+ "html",
82
+ "text"
83
+ ],
84
+ "temp-directory": "nyc/.nyc_output"
85
+ },
86
+ "dependencies": {
87
+ "@fluid-internal/client-utils": "~2.93.0",
88
+ "@fluid-internal/presence-definitions": "~2.93.0",
89
+ "@fluidframework/container-definitions": "~2.93.0",
90
+ "@fluidframework/container-runtime-definitions": "~2.93.0",
91
+ "@fluidframework/core-interfaces": "~2.93.0",
92
+ "@fluidframework/core-utils": "~2.93.0",
93
+ "@fluidframework/id-compressor": "~2.93.0",
94
+ "@fluidframework/runtime-definitions": "~2.93.0",
95
+ "@fluidframework/telemetry-utils": "~2.93.0"
96
+ },
97
+ "devDependencies": {
98
+ "@arethetypeswrong/cli": "^0.18.2",
99
+ "@biomejs/biome": "~2.4.5",
100
+ "@fluid-internal/mocha-test-setup": "~2.93.0",
101
+ "@fluid-tools/build-cli": "^0.64.0",
102
+ "@fluidframework/build-common": "^2.0.3",
103
+ "@fluidframework/build-tools": "^0.64.0",
104
+ "@fluidframework/driver-definitions": "~2.93.0",
105
+ "@fluidframework/eslint-config-fluid": "^9.0.0",
106
+ "@fluidframework/test-runtime-utils": "~2.93.0",
107
+ "@fluidframework/test-utils": "~2.93.0",
108
+ "@microsoft/api-extractor": "7.58.1",
109
+ "@types/mocha": "^10.0.10",
110
+ "@types/node": "~22.19.17",
111
+ "@types/sinon": "^17.0.3",
112
+ "c8": "^10.1.3",
113
+ "concurrently": "^9.2.1",
114
+ "copyfiles": "^2.4.1",
115
+ "cross-env": "^10.1.0",
116
+ "eslint": "~9.39.1",
117
+ "jiti": "^2.6.1",
118
+ "mocha": "^11.7.5",
119
+ "mocha-multi-reporters": "^1.5.1",
120
+ "rimraf": "^6.1.3",
121
+ "sinon": "^18.0.1",
122
+ "typescript": "~5.4.5"
123
+ },
124
+ "typeValidation": {
125
+ "disabled": true
126
+ },
127
+ "scripts": {
128
+ "build": "fluid-build . --task build",
129
+ "build:commonjs": "fluid-build . --task commonjs",
130
+ "build:compile": "fluid-build . --task compile",
131
+ "build:esnext": "tsc --project ./tsconfig.esm.json",
132
+ "build:genver": "gen-version",
133
+ "build:test": "npm run build:test:esm && npm run build:test:cjs",
134
+ "build:test:cjs": "fluid-tsc commonjs --project ./tsconfig.test.cjs.json",
135
+ "build:test:esm": "tsc --project ./tsconfig.test.esm.json",
136
+ "check:are-the-types-wrong": "attw --pack . --profile node16 --exclude-entrypoints ./internal/protocol ./internal/test ./internal/test-utils",
137
+ "check:biome": "biome check .",
138
+ "check:exports": "concurrently \"npm:check:exports:*\"",
139
+ "check:exports:states:bundle-release-tags": "api-extractor run --config api-extractor/api-extractor-lint-states-bundle.json",
140
+ "check:exports:states:cjs": "api-extractor run --config api-extractor/api-extractor-lint-states.cjs.json",
141
+ "check:exports:states:esm": "api-extractor run --config api-extractor/api-extractor-lint-states.esm.json",
142
+ "check:format": "npm run check:biome",
143
+ "clean": "rimraf --glob dist lib \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
144
+ "eslint": "eslint --quiet --format stylish src",
145
+ "eslint:fix": "eslint --quiet --format stylish src --fix --fix-type problem,suggestion,layout",
146
+ "format": "npm run format:biome",
147
+ "format:biome": "biome check . --write",
148
+ "lint": "fluid-build . --task lint",
149
+ "lint:fix": "fluid-build . --task eslint:fix --task format",
150
+ "test": "npm run test:mocha",
151
+ "test:coverage": "c8 npm test",
152
+ "test:mocha": "npm run test:mocha:esm && echo skipping cjs to avoid overhead - npm run test:mocha:cjs",
153
+ "test:mocha:cjs": "cross-env FLUID_TEST_MODULE_SYSTEM=CJS \"MOCHA_SPEC=dist/**/*.spec.*js\" mocha",
154
+ "test:mocha:esm": "cross-env \"MOCHA_SPEC=lib/**/*.spec.*js\" mocha",
155
+ "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
156
+ "tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json && copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist"
157
+ }
158
+ }