teamplay 0.3.25 → 0.3.27
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/orm/Signal.js +19 -0
- package/package.json +11 -10
- package/react/wrapIntoSuspense.js +15 -1
package/orm/Signal.js
CHANGED
|
@@ -179,6 +179,25 @@ export default class Signal extends Function {
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
+
async assign (value) {
|
|
183
|
+
if (arguments.length > 1) throw Error('Signal.assign() expects a single argument')
|
|
184
|
+
if (this[SEGMENTS].length === 0) throw Error('Can\'t assign to the root signal data')
|
|
185
|
+
if (!value) return
|
|
186
|
+
if (typeof value !== 'object') throw Error('Signal.assign() expects an object argument, got: ' + typeof value)
|
|
187
|
+
const promises = []
|
|
188
|
+
// use Object.keys() to avoid setting inherited properties
|
|
189
|
+
for (const key of Object.keys(value)) {
|
|
190
|
+
let promise
|
|
191
|
+
if (value[key] != null) {
|
|
192
|
+
promise = this[key].set(value[key])
|
|
193
|
+
} else {
|
|
194
|
+
promise = this[key].del()
|
|
195
|
+
}
|
|
196
|
+
promises.push(promise)
|
|
197
|
+
}
|
|
198
|
+
await Promise.all(promises)
|
|
199
|
+
}
|
|
200
|
+
|
|
182
201
|
// TODO: implement a json0 operation for push
|
|
183
202
|
async push (value) {
|
|
184
203
|
if (arguments.length > 1) throw Error('Signal.push() expects a single argument')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "teamplay",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.27",
|
|
4
4
|
"description": "Full-stack signals ORM with multiplayer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -17,18 +17,18 @@
|
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"test": "npm run test-server && npm run test-client",
|
|
20
|
-
"test-server": "
|
|
21
|
-
"test-server-only": "
|
|
20
|
+
"test-server": "NODE_OPTIONS=\"--expose-gc\" mocha 'test/[!_]*.js'",
|
|
21
|
+
"test-server-only": "NODE_OPTIONS=\"--expose-gc\" mocha --grep '@only' 'test/[!_]*.js'",
|
|
22
22
|
"test-client": "NODE_OPTIONS=\"$NODE_OPTIONS --expose-gc --experimental-vm-modules\" jest"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@nx-js/observer-util": "^4.1.3",
|
|
26
|
-
"@teamplay/backend": "^0.3.
|
|
27
|
-
"@teamplay/cache": "^0.3.
|
|
28
|
-
"@teamplay/channel": "^0.3.
|
|
29
|
-
"@teamplay/debug": "^0.3.
|
|
30
|
-
"@teamplay/schema": "^0.3.
|
|
31
|
-
"@teamplay/utils": "^0.3.
|
|
26
|
+
"@teamplay/backend": "^0.3.27",
|
|
27
|
+
"@teamplay/cache": "^0.3.27",
|
|
28
|
+
"@teamplay/channel": "^0.3.27",
|
|
29
|
+
"@teamplay/debug": "^0.3.27",
|
|
30
|
+
"@teamplay/schema": "^0.3.27",
|
|
31
|
+
"@teamplay/utils": "^0.3.27",
|
|
32
32
|
"diff-match-patch": "^1.0.5",
|
|
33
33
|
"events": "^3.3.0",
|
|
34
34
|
"json0-ot-diff": "^1.1.2",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"@testing-library/react": "^15.0.7",
|
|
42
42
|
"jest": "^29.7.0",
|
|
43
43
|
"jest-environment-jsdom": "^29.7.0",
|
|
44
|
+
"mocha": "^11.0.1",
|
|
44
45
|
"react": "^18.3.1",
|
|
45
46
|
"react-dom": "^18.3.1"
|
|
46
47
|
},
|
|
@@ -63,5 +64,5 @@
|
|
|
63
64
|
]
|
|
64
65
|
},
|
|
65
66
|
"license": "MIT",
|
|
66
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "4a3fbec77123972874cb03bf5197983fe69f1118"
|
|
67
68
|
}
|
|
@@ -31,6 +31,7 @@ export default function wrapIntoSuspense ({
|
|
|
31
31
|
stateVersion: Symbol(), // eslint-disable-line symbol-description
|
|
32
32
|
onStoreChange: undefined,
|
|
33
33
|
scheduledUpdatePromise: undefined,
|
|
34
|
+
hasPendingUpdate: false,
|
|
34
35
|
cache: new Map(),
|
|
35
36
|
scheduleUpdate: promise => {
|
|
36
37
|
if (!promise?.then) throw Error('scheduleUpdate() expects a promise')
|
|
@@ -47,6 +48,12 @@ export default function wrapIntoSuspense ({
|
|
|
47
48
|
adm.stateVersion = Symbol() // eslint-disable-line symbol-description
|
|
48
49
|
onStoreChange()
|
|
49
50
|
}
|
|
51
|
+
// If there was a pending update before subscribe was called, trigger it asynchronously
|
|
52
|
+
// to avoid updating during the subscribe/render phase
|
|
53
|
+
if (adm.hasPendingUpdate) {
|
|
54
|
+
adm.hasPendingUpdate = false
|
|
55
|
+
queueMicrotask(() => adm.onStoreChange())
|
|
56
|
+
}
|
|
50
57
|
return () => destroyAdm(adm)
|
|
51
58
|
},
|
|
52
59
|
getSnapshot () {
|
|
@@ -64,7 +71,14 @@ export default function wrapIntoSuspense ({
|
|
|
64
71
|
componentId,
|
|
65
72
|
createdAt: Date.now(),
|
|
66
73
|
defer,
|
|
67
|
-
triggerUpdate: () =>
|
|
74
|
+
triggerUpdate: () => {
|
|
75
|
+
if (adm.onStoreChange) {
|
|
76
|
+
adm.onStoreChange()
|
|
77
|
+
} else {
|
|
78
|
+
// Save pending update - subscribe not called yet (e.g., from useEffect/useLayoutEffect)
|
|
79
|
+
adm.hasPendingUpdate = true
|
|
80
|
+
}
|
|
81
|
+
},
|
|
68
82
|
scheduleUpdate: promise => adm.scheduleUpdate?.(promise),
|
|
69
83
|
cache: {
|
|
70
84
|
get: key => adm.cache?.get(key),
|