teamplay 0.4.0 → 0.5.0-alpha.1

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 (237) hide show
  1. package/babel-loader.cjs +1 -0
  2. package/babel.cjs +1 -0
  3. package/dist/connect/index.d.ts +1 -0
  4. package/dist/connect/index.js +9 -0
  5. package/dist/connect/lib/sharedb-crosstab-pubsub.d.cts +10 -0
  6. package/dist/connect/offline/index.d.ts +1 -0
  7. package/dist/connect/offline/index.js +126 -0
  8. package/dist/connect/offline/react-native.d.ts +10 -0
  9. package/dist/connect/offline/react-native.js +25 -0
  10. package/dist/connect/offline/web.d.ts +9 -0
  11. package/dist/connect/offline/web.js +12 -0
  12. package/dist/connect/sharedbConnection.d.cts +2 -0
  13. package/dist/connect/test.d.ts +1 -0
  14. package/dist/connect/test.js +12 -0
  15. package/dist/index.d.ts +66 -0
  16. package/dist/index.js +74 -0
  17. package/dist/orm/$.d.ts +9 -0
  18. package/dist/orm/$.js +34 -0
  19. package/dist/orm/Aggregation.d.ts +17 -0
  20. package/dist/orm/Aggregation.js +115 -0
  21. package/dist/orm/Cache.d.ts +9 -0
  22. package/dist/orm/Cache.js +32 -0
  23. package/dist/orm/Compat/SignalCompat.d.ts +3 -0
  24. package/dist/orm/Compat/SignalCompat.js +1542 -0
  25. package/dist/orm/Compat/eventsCompat.d.ts +3 -0
  26. package/dist/orm/Compat/eventsCompat.js +73 -0
  27. package/dist/orm/Compat/hooksCompat.d.ts +33 -0
  28. package/dist/orm/Compat/hooksCompat.js +360 -0
  29. package/dist/orm/Compat/modelEvents.d.ts +6 -0
  30. package/dist/orm/Compat/modelEvents.js +228 -0
  31. package/dist/orm/Compat/queryReadiness.d.ts +5 -0
  32. package/dist/orm/Compat/queryReadiness.js +185 -0
  33. package/dist/orm/Compat/refFallback.d.ts +13 -0
  34. package/dist/orm/Compat/refFallback.js +65 -0
  35. package/dist/orm/Compat/refRegistry.d.ts +6 -0
  36. package/dist/orm/Compat/refRegistry.js +54 -0
  37. package/dist/orm/Compat/silentContext.d.ts +5 -0
  38. package/dist/orm/Compat/silentContext.js +48 -0
  39. package/dist/orm/Compat/startStopCompat.d.ts +3 -0
  40. package/dist/orm/Compat/startStopCompat.js +217 -0
  41. package/dist/orm/Doc.d.ts +96 -0
  42. package/dist/orm/Doc.js +966 -0
  43. package/dist/orm/Query.d.ts +117 -0
  44. package/dist/orm/Query.js +1111 -0
  45. package/dist/orm/Reaction.d.ts +10 -0
  46. package/dist/orm/Reaction.js +41 -0
  47. package/dist/orm/Root.d.ts +22 -0
  48. package/dist/orm/Root.js +85 -0
  49. package/dist/orm/Signal.d.ts +12 -0
  50. package/dist/orm/Signal.js +7 -0
  51. package/dist/orm/SignalBase.d.ts +168 -0
  52. package/dist/orm/SignalBase.js +625 -0
  53. package/dist/orm/SubscriptionState.d.ts +17 -0
  54. package/dist/orm/SubscriptionState.js +123 -0
  55. package/dist/orm/Value.d.ts +9 -0
  56. package/dist/orm/Value.js +25 -0
  57. package/dist/orm/addModel.d.ts +6 -0
  58. package/dist/orm/addModel.js +39 -0
  59. package/dist/orm/associations.d.ts +18 -0
  60. package/dist/orm/associations.js +70 -0
  61. package/dist/orm/batchScheduler.d.ts +7 -0
  62. package/dist/orm/batchScheduler.js +62 -0
  63. package/dist/orm/compatEnv.d.ts +1 -0
  64. package/dist/orm/compatEnv.js +4 -0
  65. package/dist/orm/connection.d.ts +26 -0
  66. package/dist/orm/connection.js +38 -0
  67. package/dist/orm/dataTree.d.ts +34 -0
  68. package/dist/orm/dataTree.js +880 -0
  69. package/dist/orm/disposeRootContext.d.ts +4 -0
  70. package/dist/orm/disposeRootContext.js +59 -0
  71. package/dist/orm/getSignal.d.ts +16 -0
  72. package/dist/orm/getSignal.js +133 -0
  73. package/dist/orm/idFields.d.ts +14 -0
  74. package/dist/orm/idFields.js +95 -0
  75. package/dist/orm/index.d.ts +7 -0
  76. package/dist/orm/index.js +6 -0
  77. package/dist/orm/initModels.d.ts +5 -0
  78. package/dist/orm/initModels.js +74 -0
  79. package/dist/orm/missingDoc.d.ts +1 -0
  80. package/dist/orm/missingDoc.js +3 -0
  81. package/dist/orm/pluralize.d.ts +12 -0
  82. package/dist/orm/privateData.d.ts +22 -0
  83. package/dist/orm/privateData.js +170 -0
  84. package/dist/orm/rootContext.d.ts +78 -0
  85. package/dist/orm/rootContext.js +297 -0
  86. package/dist/orm/rootScope.d.ts +12 -0
  87. package/dist/orm/rootScope.js +46 -0
  88. package/dist/orm/signalArrayReaders.d.ts +22 -0
  89. package/dist/orm/signalArrayReaders.js +42 -0
  90. package/dist/orm/signalMetadata.d.ts +17 -0
  91. package/dist/orm/signalMetadata.js +56 -0
  92. package/dist/orm/signalMutationGuards.d.ts +4 -0
  93. package/dist/orm/signalMutationGuards.js +14 -0
  94. package/dist/orm/signalPathKind.d.ts +2 -0
  95. package/dist/orm/signalPathKind.js +10 -0
  96. package/dist/orm/signalPathRules.d.ts +6 -0
  97. package/dist/orm/signalPathRules.js +28 -0
  98. package/dist/orm/signalReads.d.ts +26 -0
  99. package/dist/orm/signalReads.js +64 -0
  100. package/dist/orm/signalRuntimeAccess.d.ts +16 -0
  101. package/dist/orm/signalRuntimeAccess.js +24 -0
  102. package/dist/orm/signalRuntimeDescriptor.d.ts +19 -0
  103. package/dist/orm/signalRuntimeDescriptor.js +97 -0
  104. package/dist/orm/signalStorageMutations.d.ts +18 -0
  105. package/dist/orm/signalStorageMutations.js +26 -0
  106. package/dist/orm/signalSymbols.d.ts +5 -0
  107. package/dist/orm/signalSymbols.js +5 -0
  108. package/dist/orm/signalValueMutations.d.ts +14 -0
  109. package/dist/orm/signalValueMutations.js +36 -0
  110. package/dist/orm/sub.d.ts +37 -0
  111. package/dist/orm/sub.js +187 -0
  112. package/dist/orm/subscriptionGcDelay.d.ts +4 -0
  113. package/dist/orm/subscriptionGcDelay.js +26 -0
  114. package/dist/orm/types/baseMethods.d.ts +43 -0
  115. package/dist/orm/types/baseMethods.js +1 -0
  116. package/dist/orm/types/jsonSchema.d.ts +75 -0
  117. package/dist/orm/types/jsonSchema.js +1 -0
  118. package/dist/orm/types/modelManifest.d.ts +37 -0
  119. package/dist/orm/types/modelManifest.js +1 -0
  120. package/dist/orm/types/path.d.ts +8 -0
  121. package/dist/orm/types/path.js +1 -0
  122. package/dist/orm/types/query.d.ts +29 -0
  123. package/dist/orm/types/query.js +1 -0
  124. package/dist/orm/types/signal.d.ts +132 -0
  125. package/dist/orm/types/signal.js +1 -0
  126. package/dist/react/compatComponentRegistry.d.ts +4 -0
  127. package/dist/react/compatComponentRegistry.js +19 -0
  128. package/dist/react/convertToObserver.d.ts +26 -0
  129. package/dist/react/convertToObserver.js +114 -0
  130. package/dist/react/executionContextTracker.d.ts +11 -0
  131. package/dist/react/executionContextTracker.js +28 -0
  132. package/dist/react/helpers.d.ts +34 -0
  133. package/dist/react/helpers.js +134 -0
  134. package/dist/react/observer.d.ts +22 -0
  135. package/dist/react/observer.js +8 -0
  136. package/dist/react/promiseBatcher.d.ts +13 -0
  137. package/dist/react/promiseBatcher.js +118 -0
  138. package/dist/react/renderAttemptDestroyer.d.ts +19 -0
  139. package/dist/react/renderAttemptDestroyer.js +46 -0
  140. package/dist/react/trapRender.d.ts +6 -0
  141. package/dist/react/trapRender.js +48 -0
  142. package/dist/react/universal$.d.ts +1 -0
  143. package/dist/react/universal$.js +18 -0
  144. package/dist/react/universalSub.d.ts +1 -0
  145. package/dist/react/universalSub.js +22 -0
  146. package/dist/react/useApi.d.ts +13 -0
  147. package/dist/react/useApi.js +67 -0
  148. package/dist/react/useSub.d.ts +102 -0
  149. package/dist/react/useSub.js +189 -0
  150. package/dist/react/useSuspendMemo.d.ts +3 -0
  151. package/dist/react/useSuspendMemo.js +102 -0
  152. package/dist/react/wrapIntoSuspense.d.ts +9 -0
  153. package/dist/react/wrapIntoSuspense.js +102 -0
  154. package/dist/server.d.ts +11 -0
  155. package/dist/server.js +28 -0
  156. package/dist/utils/MockFinalizationRegistry.d.ts +37 -0
  157. package/dist/utils/MockFinalizationRegistry.js +85 -0
  158. package/dist/utils/MockWeakRef.d.ts +12 -0
  159. package/dist/utils/MockWeakRef.js +23 -0
  160. package/dist/utils/isServer.d.ts +3 -0
  161. package/dist/utils/isServer.js +18 -0
  162. package/dist/utils/setDiffDeep.d.ts +1 -0
  163. package/dist/utils/setDiffDeep.js +61 -0
  164. package/dist/utils/useIsomorphicLayoutEffect.d.ts +3 -0
  165. package/dist/utils/useIsomorphicLayoutEffect.js +3 -0
  166. package/file-based-models.js +3 -0
  167. package/file-based-models.node.js +6 -0
  168. package/package.json +77 -32
  169. package/teamplay.models.auto-init.virtual.js +1 -0
  170. package/teamplay.models.virtual.js +1 -0
  171. package/connect/index.js +0 -9
  172. package/connect/offline/index.js +0 -124
  173. package/connect/offline/react-native.js +0 -28
  174. package/connect/offline/web.js +0 -15
  175. package/connect/test.js +0 -12
  176. package/index.d.ts +0 -106
  177. package/index.js +0 -125
  178. package/orm/$.js +0 -38
  179. package/orm/Aggregation.js +0 -117
  180. package/orm/Cache.js +0 -46
  181. package/orm/Compat/README.md +0 -1064
  182. package/orm/Compat/SignalCompat.js +0 -1479
  183. package/orm/Compat/eventsCompat.js +0 -79
  184. package/orm/Compat/hooksCompat.js +0 -374
  185. package/orm/Compat/modelEvents.js +0 -225
  186. package/orm/Compat/queryReadiness.js +0 -191
  187. package/orm/Compat/refFallback.js +0 -62
  188. package/orm/Compat/refRegistry.js +0 -61
  189. package/orm/Compat/silentContext.js +0 -51
  190. package/orm/Compat/startStopCompat.js +0 -207
  191. package/orm/Doc.js +0 -969
  192. package/orm/Query.js +0 -1127
  193. package/orm/Reaction.js +0 -48
  194. package/orm/Root.js +0 -88
  195. package/orm/Signal.js +0 -22
  196. package/orm/SignalBase.js +0 -696
  197. package/orm/SubscriptionState.js +0 -138
  198. package/orm/Value.js +0 -30
  199. package/orm/addModel.js +0 -31
  200. package/orm/associations.js +0 -97
  201. package/orm/batchScheduler.js +0 -62
  202. package/orm/compatEnv.js +0 -4
  203. package/orm/connection.js +0 -46
  204. package/orm/dataTree.js +0 -869
  205. package/orm/disposeRootContext.js +0 -68
  206. package/orm/getSignal.js +0 -130
  207. package/orm/idFields.js +0 -88
  208. package/orm/index.d.ts +0 -6
  209. package/orm/index.js +0 -5
  210. package/orm/missingDoc.js +0 -3
  211. package/orm/privateData.js +0 -181
  212. package/orm/rootContext.js +0 -313
  213. package/orm/rootScope.js +0 -51
  214. package/orm/sub.js +0 -151
  215. package/orm/subscriptionGcDelay.js +0 -32
  216. package/react/compatComponentRegistry.js +0 -20
  217. package/react/convertToObserver.js +0 -117
  218. package/react/executionContextTracker.js +0 -32
  219. package/react/helpers.js +0 -141
  220. package/react/observer.js +0 -9
  221. package/react/promiseBatcher.js +0 -115
  222. package/react/renderAttemptDestroyer.js +0 -47
  223. package/react/trapRender.js +0 -50
  224. package/react/universal$.js +0 -18
  225. package/react/universalSub.js +0 -21
  226. package/react/useApi.js +0 -63
  227. package/react/useSub.js +0 -169
  228. package/react/useSuspendMemo.js +0 -96
  229. package/react/wrapIntoSuspense.js +0 -119
  230. package/server.js +0 -31
  231. package/utils/MockFinalizationRegistry.js +0 -94
  232. package/utils/MockWeakRef.js +0 -25
  233. package/utils/isServer.js +0 -17
  234. package/utils/setDiffDeep.js +0 -58
  235. package/utils/useIsomorphicLayoutEffect.js +0 -4
  236. /package/{connect → dist/connect}/lib/sharedb-crosstab-pubsub.cjs +0 -0
  237. /package/{connect → dist/connect}/sharedbConnection.cjs +0 -0
@@ -1,313 +0,0 @@
1
- import { observable } from '@nx-js/observer-util'
2
- import { normalizeRootId } from './rootScope.js'
3
- import { getDefaultFetchOnly } from './connection.js'
4
-
5
- const ROOT_CONTEXTS = new Map()
6
- const CLOSED_ROOT_CONTEXTS = new Set()
7
- const EMPTY_SET = new Set()
8
- const EMPTY_MAP = new Map()
9
- const RUNTIME_KIND_QUERY = 'query'
10
- const RUNTIME_KIND_AGGREGATION = 'aggregation'
11
-
12
- export default class RootContext {
13
- constructor (rootId, { fetchOnly } = {}) {
14
- this.rootId = normalizeRootId(rootId)
15
- this.fetchOnly = fetchOnly == null ? getDefaultFetchOnly() : !!fetchOnly
16
- this.privateDataRaw = {}
17
- this.privateData = observable(this.privateDataRaw)
18
- this.refLinks = new Map()
19
- this.activeRefs = new Map()
20
- this.modelListeners = {
21
- change: new Map(),
22
- all: new Map()
23
- }
24
- this.queryRuntimeHashes = new Set()
25
- this.aggregationRuntimeHashes = new Set()
26
- this.signalHashes = new Set()
27
- this.directDocSubscriptions = new Map()
28
- }
29
-
30
- getModelEventStore (eventName, create = false) {
31
- let store = this.modelListeners[eventName]
32
- if (!store && create) {
33
- store = new Map()
34
- this.modelListeners[eventName] = store
35
- }
36
- return store
37
- }
38
-
39
- getFetchOnly () {
40
- return !!this.fetchOnly
41
- }
42
-
43
- setFetchOnly (value) {
44
- this.fetchOnly = !!value
45
- }
46
-
47
- getPrivateDataRoot () {
48
- return this.privateData
49
- }
50
-
51
- getPrivateDataRawRoot () {
52
- return this.privateDataRaw
53
- }
54
-
55
- getPrivateDataAt (segments) {
56
- return getPath(segments, this.privateData)
57
- }
58
-
59
- getPrivateDataRawAt (segments) {
60
- return getPath(segments, this.privateDataRaw)
61
- }
62
-
63
- setPrivateDataAt (segments, value) {
64
- setPath(segments, value, this.privateData)
65
- }
66
-
67
- delPrivateDataAt (segments) {
68
- delPath(segments, this.privateData)
69
- }
70
-
71
- getRuntimeHashes (kind) {
72
- switch (kind) {
73
- case RUNTIME_KIND_QUERY:
74
- return this.queryRuntimeHashes
75
- case RUNTIME_KIND_AGGREGATION:
76
- return this.aggregationRuntimeHashes
77
- default:
78
- throw Error(`Unsupported root-owned runtime kind: ${kind}`)
79
- }
80
- }
81
-
82
- registerRuntime (kind, runtimeHash) {
83
- if (runtimeHash == null) return
84
- this.getRuntimeHashes(kind).add(runtimeHash)
85
- }
86
-
87
- unregisterRuntime (kind, runtimeHash) {
88
- if (runtimeHash == null) return
89
- this.getRuntimeHashes(kind).delete(runtimeHash)
90
- }
91
-
92
- registerSignalHash (signalHash) {
93
- if (signalHash == null) return
94
- this.signalHashes.add(signalHash)
95
- }
96
-
97
- unregisterSignalHash (signalHash) {
98
- if (signalHash == null) return
99
- this.signalHashes.delete(signalHash)
100
- }
101
-
102
- registerDirectDocSubscription (hash, segments, token) {
103
- if (hash == null) return
104
- let entry = this.directDocSubscriptions.get(hash)
105
- if (!entry) {
106
- entry = {
107
- segments: [...segments],
108
- count: 0,
109
- tokenCounts: new Map()
110
- }
111
- this.directDocSubscriptions.set(hash, entry)
112
- }
113
- entry.count += 1
114
- if (token != null) {
115
- entry.tokenCounts.set(token, (entry.tokenCounts.get(token) || 0) + 1)
116
- }
117
- }
118
-
119
- unregisterDirectDocSubscription (hash, token) {
120
- const entry = this.directDocSubscriptions.get(hash)
121
- if (!entry) return
122
- entry.count = Math.max(entry.count - 1, 0)
123
- if (token != null) {
124
- const nextTokenCount = (entry.tokenCounts.get(token) || 0) - 1
125
- if (nextTokenCount > 0) entry.tokenCounts.set(token, nextTokenCount)
126
- else entry.tokenCounts.delete(token)
127
- }
128
- if (entry.count === 0) this.directDocSubscriptions.delete(hash)
129
- }
130
-
131
- resetRefs () {
132
- this.refLinks.clear()
133
- }
134
-
135
- resetActiveRefs () {
136
- this.activeRefs.clear()
137
- }
138
-
139
- resetModelListeners () {
140
- for (const store of Object.values(this.modelListeners)) {
141
- store.clear()
142
- }
143
- }
144
-
145
- resetRuntimeHashes () {
146
- this.queryRuntimeHashes.clear()
147
- this.aggregationRuntimeHashes.clear()
148
- }
149
-
150
- resetPrivateData () {
151
- this.privateDataRaw = {}
152
- this.privateData = observable(this.privateDataRaw)
153
- }
154
-
155
- resetSignalHashes () {
156
- this.signalHashes.clear()
157
- }
158
-
159
- resetDirectDocSubscriptions () {
160
- this.directDocSubscriptions.clear()
161
- }
162
-
163
- isRuntimeEmpty () {
164
- return (
165
- isPlainObjectEmpty(this.privateData) &&
166
- this.refLinks.size === 0 &&
167
- this.activeRefs.size === 0 &&
168
- Object.values(this.modelListeners).every(store => store.size === 0) &&
169
- this.queryRuntimeHashes.size === 0 &&
170
- this.aggregationRuntimeHashes.size === 0 &&
171
- this.signalHashes.size === 0 &&
172
- this.directDocSubscriptions.size === 0
173
- )
174
- }
175
- }
176
-
177
- export function getRootContext (rootId, create = true, options = {}) {
178
- const normalizedRootId = normalizeRootId(rootId)
179
- if (create && CLOSED_ROOT_CONTEXTS.has(normalizedRootId)) return undefined
180
- let context = ROOT_CONTEXTS.get(normalizedRootId)
181
- if (!context && create) {
182
- context = new RootContext(normalizedRootId, options)
183
- ROOT_CONTEXTS.set(normalizedRootId, context)
184
- }
185
- return context
186
- }
187
-
188
- export function getRootContexts () {
189
- return ROOT_CONTEXTS.values()
190
- }
191
-
192
- export function registerRootOwnedRuntime (rootId, kind, runtimeHash) {
193
- getRootContext(rootId, true).registerRuntime(kind, runtimeHash)
194
- }
195
-
196
- export function unregisterRootOwnedRuntime (rootId, kind, runtimeHash) {
197
- const context = getRootContext(rootId, false)
198
- if (!context) return
199
- context.unregisterRuntime(kind, runtimeHash)
200
- }
201
-
202
- export function getRootOwnedRuntimeHashes (rootId, kind) {
203
- const context = getRootContext(rootId, false)
204
- if (!context) return EMPTY_SET
205
- return context.getRuntimeHashes(kind)
206
- }
207
-
208
- export function registerRootOwnedSignalHash (rootId, signalHash) {
209
- getRootContext(rootId, true).registerSignalHash(signalHash)
210
- }
211
-
212
- export function getRootOwnedSignalHashes (rootId) {
213
- const context = getRootContext(rootId, false)
214
- if (!context) return EMPTY_SET
215
- return context.signalHashes
216
- }
217
-
218
- export function clearRootOwnedSignalHashes (rootId) {
219
- const context = getRootContext(rootId, false)
220
- if (!context) return
221
- context.resetSignalHashes()
222
- }
223
-
224
- export function registerRootOwnedDirectDocSubscription (rootId, hash, segments, token) {
225
- getRootContext(rootId, true).registerDirectDocSubscription(hash, segments, token)
226
- }
227
-
228
- export function unregisterRootOwnedDirectDocSubscription (rootId, hash, token) {
229
- const context = getRootContext(rootId, false)
230
- if (!context) return
231
- context.unregisterDirectDocSubscription(hash, token)
232
- }
233
-
234
- export function getRootOwnedDirectDocSubscriptions (rootId) {
235
- const context = getRootContext(rootId, false)
236
- if (!context) return EMPTY_MAP
237
- return context.directDocSubscriptions
238
- }
239
-
240
- export function clearRootOwnedDirectDocSubscriptions (rootId) {
241
- const context = getRootContext(rootId, false)
242
- if (!context) return
243
- context.resetDirectDocSubscriptions()
244
- }
245
-
246
- export function deleteRootContext (rootId) {
247
- const normalizedRootId = normalizeRootId(rootId)
248
- ROOT_CONTEXTS.delete(normalizedRootId)
249
- CLOSED_ROOT_CONTEXTS.add(normalizedRootId)
250
- }
251
-
252
- export function reviveRootContext (rootId) {
253
- CLOSED_ROOT_CONTEXTS.delete(normalizeRootId(rootId))
254
- }
255
-
256
- export function isRootContextClosed (rootId) {
257
- return CLOSED_ROOT_CONTEXTS.has(normalizeRootId(rootId))
258
- }
259
-
260
- export function __getRootContextForTests (rootId) {
261
- return getRootContext(rootId, false)
262
- }
263
-
264
- export function __resetRootContextsForTests () {
265
- ROOT_CONTEXTS.clear()
266
- CLOSED_ROOT_CONTEXTS.clear()
267
- }
268
-
269
- function getPath (segments, dataNode) {
270
- for (const segment of segments) {
271
- if (dataNode == null) return dataNode
272
- dataNode = dataNode[segment]
273
- }
274
- return dataNode
275
- }
276
-
277
- function setPath (segments, value, tree) {
278
- if (!Array.isArray(segments) || segments.length === 0) {
279
- throw Error('setPrivateDataAt requires a non-empty segments array')
280
- }
281
- let dataNode = tree
282
- for (let i = 0; i < segments.length - 1; i++) {
283
- const segment = segments[i]
284
- const next = dataNode[segment]
285
- if (next == null || typeof next !== 'object') {
286
- dataNode[segment] = {}
287
- }
288
- dataNode = dataNode[segment]
289
- }
290
- dataNode[segments[segments.length - 1]] = value
291
- }
292
-
293
- function delPath (segments, tree) {
294
- if (!Array.isArray(segments) || segments.length === 0) return
295
- const parents = []
296
- let dataNode = tree
297
- for (let i = 0; i < segments.length - 1; i++) {
298
- if (dataNode == null) return
299
- parents.push([dataNode, segments[i]])
300
- dataNode = dataNode[segments[i]]
301
- }
302
- if (dataNode == null) return
303
- delete dataNode[segments[segments.length - 1]]
304
- for (let i = parents.length - 1; i >= 0; i--) {
305
- const [parent, segment] = parents[i]
306
- if (!isPlainObjectEmpty(parent[segment])) break
307
- delete parent[segment]
308
- }
309
- }
310
-
311
- function isPlainObjectEmpty (value) {
312
- return value != null && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length === 0
313
- }
package/orm/rootScope.js DELETED
@@ -1,51 +0,0 @@
1
- import { GLOBAL_ROOT_ID } from './Root.js'
2
-
3
- const REGEX_PRIVATE_COLLECTION = /^[_$]/
4
-
5
- export function normalizeRootId (rootId) {
6
- return rootId ?? GLOBAL_ROOT_ID
7
- }
8
-
9
- export function isGlobalRootId (rootId) {
10
- return normalizeRootId(rootId) === GLOBAL_ROOT_ID
11
- }
12
-
13
- export function isPrivateCollectionSegments (segments) {
14
- return Array.isArray(segments) &&
15
- segments.length > 0 &&
16
- REGEX_PRIVATE_COLLECTION.test(String(segments[0]))
17
- }
18
-
19
- export function getPrivateDataSegments (logicalSegments) {
20
- if (!isPrivateCollectionSegments(logicalSegments)) return logicalSegments
21
- return [...logicalSegments]
22
- }
23
-
24
- export function getLogicalRootSnapshot (rootId, tree, privateDataRoot) {
25
- const snapshot = {}
26
- for (const key of Object.keys(tree)) {
27
- snapshot[key] = tree[key]
28
- }
29
- if (!privateDataRoot || typeof privateDataRoot !== 'object') return snapshot
30
- for (const key of Object.keys(privateDataRoot)) {
31
- snapshot[key] = privateDataRoot[key]
32
- }
33
- return snapshot
34
- }
35
-
36
- export function getSignalIdentityHash (rootId, segments) {
37
- const normalizedRootId = normalizeRootId(rootId)
38
- if (segments.length === 0) return JSON.stringify({ root: normalizedRootId })
39
- if (isPrivateCollectionSegments(segments)) {
40
- return JSON.stringify({ private: [normalizedRootId, segments] })
41
- }
42
- return JSON.stringify({ public: [normalizedRootId, segments] })
43
- }
44
-
45
- export function getScopedSignalHash (rootId, transportHash, kind = 'querySignal') {
46
- return JSON.stringify({ [kind]: [normalizeRootId(rootId), transportHash] })
47
- }
48
-
49
- export function getRootScopedRegistryKey (rootId, key) {
50
- return JSON.stringify([normalizeRootId(rootId), key])
51
- }
package/orm/sub.js DELETED
@@ -1,151 +0,0 @@
1
- import { isAggregationHeader, isAggregationFunction, isClientAggregationFunction } from '@teamplay/utils/aggregation'
2
- import Signal, { SEGMENTS, isPublicCollectionSignal, isPublicDocumentSignal } from './Signal.js'
3
- import { docSubscriptions } from './Doc.js'
4
- import { querySubscriptions, getQuerySignal } from './Query.js'
5
- import { aggregationSubscriptions, getAggregationSignal } from './Aggregation.js'
6
- import { getRoot } from './Root.js'
7
- import isServer from '../utils/isServer.js'
8
-
9
- export default function sub ($signal, params) {
10
- // TODO: temporarily disable support for multiple subscriptions
11
- // since this has to be properly cached using useDeferredSignal() in useSub()
12
- // if (Array.isArray($signal)) {
13
- // const res = $signal.map(args => Array.isArray(args) ? sub(...args) : sub(args))
14
- // if (res.some($s => $s.then)) return Promise.all(res)
15
- // return res
16
- // }
17
- if (Array.isArray($signal)) throw Error('sub() does not support multiple subscriptions yet')
18
- if (isPublicDocumentSignal($signal)) {
19
- if (arguments.length > 1) throw Error(ERRORS.subDocArguments(...arguments))
20
- return doc$($signal)
21
- } else if (isPublicCollectionSignal($signal)) {
22
- if (arguments.length !== 2) throw Error(ERRORS.subQueryArguments(...arguments))
23
- return query$($signal, params)
24
- } else if (isClientAggregationFunction($signal)) {
25
- return getAggregationFromFunction($signal, $signal.collection, params)
26
- } else if (isAggregationHeader($signal)) {
27
- params = {
28
- $aggregationName: $signal.name,
29
- $params: sanitizeAggregationParams(params)
30
- }
31
- return aggregation$($signal.collection, params)
32
- } else if (isAggregationFunction($signal)) {
33
- if (isServer) {
34
- if (!params?.$collection) throw Error(ERRORS.subServerAggregationCollection($signal, params))
35
- params = { ...params }
36
- const collection = params.$collection
37
- delete params.$collection
38
- return getAggregationFromFunction($signal, collection, params)
39
- } else {
40
- throw Error(ERRORS.gotAggregationFunction($signal))
41
- }
42
- } else if (typeof $signal === 'function' && !($signal instanceof Signal)) {
43
- return api$($signal, params)
44
- } else {
45
- throw Error('Invalid args passed for sub()')
46
- }
47
- }
48
-
49
- function getAggregationFromFunction (fn, collection, params) {
50
- params = sanitizeAggregationParams(params) // clones it, so mutation becomes safe
51
- let session
52
- if (params.$session) {
53
- session = params.$session
54
- delete params.$session
55
- }
56
- session ??= {}
57
- // should match the context in @teamplay/backend/features/serverAggregate.js
58
- const context = { collection, session, isServer }
59
- params = fn(params, context)
60
- if (Array.isArray(params)) params = { $aggregate: params }
61
- return aggregation$(collection, params)
62
- }
63
-
64
- function doc$ ($doc) {
65
- const promise = docSubscriptions.subscribe($doc)
66
- if (!promise) return $doc
67
- return new Promise(resolve => promise.then(() => resolve($doc)))
68
- }
69
-
70
- function query$ ($collection, params) {
71
- const collectionName = $collection[SEGMENTS][0]
72
- if (typeof params !== 'object') throw Error(ERRORS.queryParamsObject(collectionName, params))
73
- const signalOptions = getQuerySignalOptions($collection)
74
- if (params?.$aggregate || params?.$aggregationName) return aggregation$(collectionName, params, signalOptions)
75
- const $query = getQuerySignal(collectionName, params, signalOptions)
76
- const promise = querySubscriptions.subscribe($query)
77
- if (!promise) return $query
78
- return new Promise(resolve => promise.then(() => resolve($query)))
79
- }
80
-
81
- function aggregation$ (collectionName, params, signalOptions) {
82
- const $aggregationQuery = getAggregationSignal(collectionName, params, signalOptions)
83
- const promise = aggregationSubscriptions.subscribe($aggregationQuery)
84
- if (!promise) return $aggregationQuery
85
- return new Promise(resolve => promise.then(() => resolve($aggregationQuery)))
86
- }
87
-
88
- function api$ (fn, args) {
89
- throw Error('sub() for async functions is not implemented yet')
90
- }
91
-
92
- // aggregation params get transferred to the server
93
- // and while doing so if some value is 'undefined', it actually gets transferred as 'null'
94
- // which breaks logic of setting default values in the aggregation function.
95
- // That's why we have to explicitly remove 'undefined' values from the aggregation params.
96
- // This can be easily done by serializing and deserializing it to JSON.
97
- function sanitizeAggregationParams (params) {
98
- return JSON.parse(JSON.stringify(params))
99
- }
100
-
101
- function getQuerySignalOptions ($collection) {
102
- const $root = getRoot($collection)
103
- if (!$root) return undefined
104
- return { root: $root }
105
- }
106
-
107
- const ERRORS = {
108
- subDocArguments: ($signal, ...args) => `
109
- sub($doc) accepts only 1 argument - the document signal to subscribe to
110
- Doc: ${$signal[SEGMENTS]}
111
- Got args: ${[$signal, ...args]}
112
- `,
113
- subQueryArguments: ($signal, params, ...args) => `
114
- sub($collection, params) accepts 2 arguments - the collection signal and an object with query params.
115
- If you want to subscribe to all documents in a collection, pass an empty object: sub($collection, {}).
116
- Collection: ${$signal[SEGMENTS]}
117
- Params: ${params}
118
- Got args: ${[$signal, params, ...args]}
119
- `,
120
- queryParamsObject: (collectionName, params) => `
121
- sub($collection, params):
122
- Params must be an object.
123
- If you want to subscribe to all documents in a collection, pass an empty object: sub($collection, {}).
124
-
125
- Got:
126
- collectionName: ${collectionName}
127
- params: ${params}
128
- `,
129
- gotAggregationFunction: aggregationFn => `
130
- sub($$aggregation, params):
131
- Got aggregation function itself instead of the aggregation header.
132
- Looks like client-side code transformation did not work properly and your
133
- aggregation() function was not transformed into an __aggregationHeader().
134
- Make sure you only use aggregation() function inside project's 'model' folder using
135
- import { aggregation } from 'startupjs'
136
-
137
- Got:
138
- ${aggregationFn.toString()}
139
- `,
140
- subServerAggregationCollection: ($signal, params) => `
141
- sub($$aggregation, params):
142
- Server-side aggregation function must receive the collection name from the params.
143
- Make sure you pass the collection name as $collection in the params object
144
- when running aggregation from the server code:
145
- sub($$aggregation, { $collection: 'collectionName', ...actualParams })
146
-
147
- Got:
148
- Aggregation: ${$signal}
149
- Params: ${params}
150
- `
151
- }
@@ -1,32 +0,0 @@
1
- import { isCompatEnv } from './compatEnv.js'
2
-
3
- const DEFAULT_COMPAT_SUBSCRIPTION_GC_DELAY = 3000
4
- const DEFAULT_SUBSCRIPTION_GC_DELAY = 0
5
-
6
- let subscriptionGcDelay = getDefaultSubscriptionGcDelay()
7
-
8
- export function getSubscriptionGcDelay () {
9
- return subscriptionGcDelay
10
- }
11
-
12
- export function setSubscriptionGcDelay (ms) {
13
- if (ms == null) {
14
- subscriptionGcDelay = getDefaultSubscriptionGcDelay()
15
- return subscriptionGcDelay
16
- }
17
- if (typeof ms !== 'number' || !Number.isFinite(ms) || ms < 0) {
18
- throw Error('setSubscriptionGcDelay() expects a non-negative finite number')
19
- }
20
- subscriptionGcDelay = ms
21
- return subscriptionGcDelay
22
- }
23
-
24
- export function getDefaultSubscriptionGcDelay () {
25
- return isCompatEnv()
26
- ? DEFAULT_COMPAT_SUBSCRIPTION_GC_DELAY
27
- : DEFAULT_SUBSCRIPTION_GC_DELAY
28
- }
29
-
30
- export function __resetSubscriptionGcDelayForTests () {
31
- subscriptionGcDelay = getDefaultSubscriptionGcDelay()
32
- }
@@ -1,20 +0,0 @@
1
- const compatComponentIds = new Set()
2
-
3
- export function markCompatComponent (componentId) {
4
- if (!componentId) return
5
- compatComponentIds.add(componentId)
6
- }
7
-
8
- export function unmarkCompatComponent (componentId) {
9
- if (!componentId) return
10
- compatComponentIds.delete(componentId)
11
- }
12
-
13
- export function isCompatComponent (componentId) {
14
- if (!componentId) return false
15
- return compatComponentIds.has(componentId)
16
- }
17
-
18
- export function __resetCompatComponentRegistryForTests () {
19
- compatComponentIds.clear()
20
- }
@@ -1,117 +0,0 @@
1
- import { forwardRef as _forwardRef, useRef } from 'react'
2
- import { observe, unobserve } from '@nx-js/observer-util'
3
- import _throttle from 'lodash/throttle.js'
4
- import { createCaches, getDummyCache } from '@teamplay/cache'
5
- import { __increment, __decrement } from '@teamplay/debug'
6
- import executionContextTracker from './executionContextTracker.js'
7
- import { pipeComponentMeta, useUnmount, useId, useTriggerUpdate } from './helpers.js'
8
- import trapRender from './trapRender.js'
9
- import { scheduleReaction } from '../orm/batchScheduler.js'
10
- import { isCompatComponent, unmarkCompatComponent } from './compatComponentRegistry.js'
11
-
12
- const DEFAULT_THROTTLE_TIMEOUT = 100
13
-
14
- export default function convertToObserver (BaseComponent, {
15
- forwardRef,
16
- cache: enableCache = true,
17
- throttle,
18
- ...options
19
- } = {}) {
20
- throttle = normalizeThrottle(throttle)
21
- // MAGIC. This fixes hot-reloading. TODO: figure out WHY it fixes it
22
- // const random = Math.random()
23
-
24
- // memo; we are not intested in deep updates
25
- // in props; we assume that if deep objects are changed,
26
- // this is in observables, which would have been tracked anyway
27
- let Component = (...args) => {
28
- const [cache, destroyCache] = useCreateCacheRef(enableCache)
29
- const componentId = useId()
30
- const triggerUpdate = useTriggerUpdate()
31
-
32
- // wrap the BaseComponent into an observe decorator once.
33
- // This way it will track any observable changes and will trigger rerender
34
- const reactionRef = useRef()
35
- const destroyRef = useRef()
36
- if (!reactionRef.current) {
37
- let hasDeferredUpdateAfterExecutionContext = false
38
- let update = () => {
39
- // It's important to block updates caused by rendering itself
40
- // (when the sync rendering is in progress).
41
- if (!executionContextTracker.isActive()) {
42
- hasDeferredUpdateAfterExecutionContext = false
43
- triggerUpdate()
44
- } else if (isCompatComponent(componentId)) {
45
- if (hasDeferredUpdateAfterExecutionContext) return
46
- hasDeferredUpdateAfterExecutionContext = true
47
- queueMicrotask(() => {
48
- if (!hasDeferredUpdateAfterExecutionContext) return
49
- if (executionContextTracker.isActive()) return
50
- hasDeferredUpdateAfterExecutionContext = false
51
- update()
52
- })
53
- }
54
- }
55
- if (throttle) update = _throttle(update, throttle)
56
- destroyRef.current = (where) => {
57
- if (!reactionRef.current) throw Error(`NO REACTION REF - ${where}`)
58
- destroyRef.current = undefined
59
- unmarkCompatComponent(componentId)
60
- unobserve(reactionRef.current)
61
- reactionRef.current = undefined
62
- destroyCache(where)
63
- }
64
- const trappedRender = trapRender({
65
- render: BaseComponent,
66
- cache,
67
- destroy: destroyRef.current,
68
- componentId
69
- })
70
- reactionRef.current = observe(trappedRender, {
71
- scheduler: () => scheduleReaction(update),
72
- lazy: true
73
- })
74
- }
75
-
76
- // clean up observer on unmount
77
- useUnmount(() => {
78
- unmarkCompatComponent(componentId)
79
- destroyRef.current?.('useUnmount()')
80
- })
81
-
82
- return reactionRef.current(...args)
83
- }
84
-
85
- if (forwardRef) Component = _forwardRef(Component)
86
- pipeComponentMeta(BaseComponent, Component)
87
-
88
- return { Component, forwardRef, ...options }
89
- }
90
-
91
- function normalizeThrottle (throttle) {
92
- if (typeof throttle === 'boolean') {
93
- if (throttle) return DEFAULT_THROTTLE_TIMEOUT
94
- else return undefined
95
- }
96
- if (typeof throttle === 'number') return throttle
97
- if (throttle == null) return undefined
98
- throw Error('observer(): throttle can be either boolean or number (milliseconds)')
99
- }
100
-
101
- function useCreateCacheRef (enableCache) {
102
- const cacheRef = useRef()
103
- const destroyCacheRef = useRef()
104
- if (!cacheRef.current) {
105
- __increment('ObserverWrapper.cache')
106
- const _createCaches = enableCache ? createCaches : getDummyCache
107
- cacheRef.current = _createCaches(['styles', 'model'])
108
- destroyCacheRef.current = (where) => {
109
- if (!cacheRef.current) throw Error(`NO CACHE REF - ${where}`)
110
- __decrement('ObserverWrapper.cache')
111
- cacheRef.current.clear()
112
- cacheRef.current = undefined
113
- destroyCacheRef.current = undefined
114
- }
115
- }
116
- return [cacheRef.current, destroyCacheRef.current]
117
- }