teamplay 0.4.0-alpha.77 → 0.4.0-alpha.79
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/Compat/SignalCompat.js +3 -3
- package/orm/SignalBase.js +12 -19
- package/orm/dataTree.js +13 -6
- package/orm/idFields.js +33 -2
- package/package.json +2 -2
|
@@ -13,7 +13,7 @@ import { publicOnly, fetchOnly, setFetchOnly } from '../connection.js'
|
|
|
13
13
|
import { docSubscriptions } from '../Doc.js'
|
|
14
14
|
import { IS_QUERY, getQuerySignal, querySubscriptions } from '../Query.js'
|
|
15
15
|
import { IS_AGGREGATION, aggregationSubscriptions, getAggregationSignal } from '../Aggregation.js'
|
|
16
|
-
import { getIdFieldsForSegments, isIdFieldPath, normalizeIdFields, isPlainObject } from '../idFields.js'
|
|
16
|
+
import { getIdFieldsForSegments, isIdFieldPath, isPublicDocPath, normalizeIdFields, isPlainObject } from '../idFields.js'
|
|
17
17
|
import {
|
|
18
18
|
del as _del,
|
|
19
19
|
setReplace as _setReplace,
|
|
@@ -1015,7 +1015,7 @@ function setReplacePrivateCompatSync ($signal, value) {
|
|
|
1015
1015
|
if (segments.length === 0) throw Error('Can\'t set the root signal data')
|
|
1016
1016
|
const idFields = getIdFieldsForSegments(segments)
|
|
1017
1017
|
if (isIdFieldPath(segments, idFields)) return
|
|
1018
|
-
if (segments
|
|
1018
|
+
if (isPublicDocPath(segments)) {
|
|
1019
1019
|
value = normalizeIdFields(value, idFields, segments[1])
|
|
1020
1020
|
}
|
|
1021
1021
|
_setReplace(segments, value)
|
|
@@ -1065,7 +1065,7 @@ async function setReplaceOnSignal ($signal, value) {
|
|
|
1065
1065
|
if (segments.length === 0) throw Error('Can\'t set the root signal data')
|
|
1066
1066
|
const idFields = getIdFieldsForSegments(segments)
|
|
1067
1067
|
if (isIdFieldPath(segments, idFields)) return
|
|
1068
|
-
if (segments
|
|
1068
|
+
if (isPublicDocPath(segments)) {
|
|
1069
1069
|
value = normalizeIdFields(value, idFields, segments[1])
|
|
1070
1070
|
}
|
|
1071
1071
|
if (isPublicCollection(segments[0])) {
|
package/orm/SignalBase.js
CHANGED
|
@@ -45,7 +45,15 @@ import { IS_QUERY, HASH, QUERIES } from './Query.js'
|
|
|
45
45
|
import { AGGREGATIONS, IS_AGGREGATION, getAggregationCollectionName, getAggregationDocId } from './Aggregation.js'
|
|
46
46
|
import { ROOT_FUNCTION, getRoot } from './Root.js'
|
|
47
47
|
import { publicOnly } from './connection.js'
|
|
48
|
-
import {
|
|
48
|
+
import {
|
|
49
|
+
DEFAULT_ID_FIELDS,
|
|
50
|
+
getIdFieldsForSegments,
|
|
51
|
+
isIdFieldPath,
|
|
52
|
+
isPublicDocPath,
|
|
53
|
+
normalizeIdFields,
|
|
54
|
+
prepareAddPayload,
|
|
55
|
+
resolveAddDocId
|
|
56
|
+
} from './idFields.js'
|
|
49
57
|
import { isCompatEnv } from './compatEnv.js'
|
|
50
58
|
import { resolveRefSegmentsSafe, resolveRefSignalSafe } from './Compat/refFallback.js'
|
|
51
59
|
import { compatStartOnRoot, compatStopOnRoot, joinScopePath } from './Compat/startStopCompat.js'
|
|
@@ -262,7 +270,7 @@ export class Signal extends Function {
|
|
|
262
270
|
if (this[SEGMENTS].length === 0) throw Error('Can\'t set the root signal data')
|
|
263
271
|
const idFields = getIdFieldsForSegments(this[SEGMENTS])
|
|
264
272
|
if (isIdFieldPath(this[SEGMENTS], idFields)) return
|
|
265
|
-
if (this[SEGMENTS]
|
|
273
|
+
if (isPublicDocPath(this[SEGMENTS])) {
|
|
266
274
|
value = normalizeIdFields(value, idFields, this[SEGMENTS][1])
|
|
267
275
|
}
|
|
268
276
|
if (isPublicCollection(this[SEGMENTS][0])) {
|
|
@@ -424,24 +432,9 @@ export class Signal extends Function {
|
|
|
424
432
|
|
|
425
433
|
async add (value) {
|
|
426
434
|
if (arguments.length > 1) throw Error('Signal.add() expects a single argument')
|
|
427
|
-
|
|
428
|
-
const hasId = value.id != null
|
|
429
|
-
const hasUnderscoreId = value._id != null
|
|
430
|
-
if (hasId && hasUnderscoreId && value.id !== value._id) {
|
|
431
|
-
throw Error(
|
|
432
|
-
`Signal.add() got conflicting "id" (${JSON.stringify(value.id)}) and "_id" (${JSON.stringify(value._id)})`
|
|
433
|
-
)
|
|
434
|
-
}
|
|
435
|
-
let id = value.id ?? value._id
|
|
436
|
-
id ??= uuid()
|
|
435
|
+
const id = resolveAddDocId(value, uuid)
|
|
437
436
|
const idFields = getIdFieldsForSegments([this[SEGMENTS][0], id])
|
|
438
|
-
|
|
439
|
-
if (idFields.includes('id')) {
|
|
440
|
-
value.id = id
|
|
441
|
-
} else if (value.id === id) {
|
|
442
|
-
delete value.id
|
|
443
|
-
}
|
|
444
|
-
await this[id].set(value)
|
|
437
|
+
await this[id].set(prepareAddPayload(value, idFields, id))
|
|
445
438
|
return id
|
|
446
439
|
}
|
|
447
440
|
|
package/orm/dataTree.js
CHANGED
|
@@ -3,7 +3,7 @@ import jsonDiff from 'json0-ot-diff'
|
|
|
3
3
|
import diffMatchPatch from 'diff-match-patch'
|
|
4
4
|
import { getConnection } from './connection.js'
|
|
5
5
|
import setDiffDeep from '../utils/setDiffDeep.js'
|
|
6
|
-
import { getIdFieldsForSegments, injectIdFields, stripIdFields, isPlainObject } from './idFields.js'
|
|
6
|
+
import { getIdFieldsForSegments, injectIdFields, stripIdFields, isPlainObject, isIdFieldPath } from './idFields.js'
|
|
7
7
|
import { emitModelChange, isModelEventsEnabled } from './Compat/modelEvents.js'
|
|
8
8
|
import { isSilentContextActive } from './Compat/silentContext.js'
|
|
9
9
|
import { isCompatEnv } from './compatEnv.js'
|
|
@@ -158,7 +158,7 @@ export async function setPublicDoc (segments, value, deleteValue = false) {
|
|
|
158
158
|
if (docId === 'undefined') throw Error(ERRORS.publicDocIdUndefined(segments))
|
|
159
159
|
if (!(collection && docId)) throw Error(ERRORS.publicDoc(segments))
|
|
160
160
|
const idFields = getIdFieldsForSegments([collection, docId])
|
|
161
|
-
if (segments
|
|
161
|
+
if (isIdFieldPath(segments, idFields)) return
|
|
162
162
|
const doc = getConnection().get(collection, docId)
|
|
163
163
|
let docState = resolvePublicDocState({ collection, docId, doc, idFields, hydrateCompatDocData: true })
|
|
164
164
|
if (!docState.exists && segments.length > 2) {
|
|
@@ -177,7 +177,10 @@ export async function setPublicDoc (segments, value, deleteValue = false) {
|
|
|
177
177
|
value = undefined
|
|
178
178
|
} else {
|
|
179
179
|
value = JSON.parse(JSON.stringify(value))
|
|
180
|
-
|
|
180
|
+
// Only strip doc identity fields when writing the whole doc.
|
|
181
|
+
// Nested payloads like `fields.fieldId.media = { id: ... }` must preserve
|
|
182
|
+
// their own `id/_id` keys.
|
|
183
|
+
if (segments.length === 2) value = stripIdFields(value, idFields)
|
|
181
184
|
}
|
|
182
185
|
if (segments.length === 2 && !docState.exists) {
|
|
183
186
|
// > create a new doc. Full doc data is provided
|
|
@@ -247,7 +250,7 @@ export async function setPublicDocReplace (segments, value) {
|
|
|
247
250
|
if (docId === 'undefined') throw Error(ERRORS.publicDocIdUndefined(segments))
|
|
248
251
|
if (!(collection && docId)) throw Error(ERRORS.publicDoc(segments))
|
|
249
252
|
const idFields = getIdFieldsForSegments([collection, docId])
|
|
250
|
-
if (segments
|
|
253
|
+
if (isIdFieldPath(segments, idFields)) return
|
|
251
254
|
const doc = getConnection().get(collection, docId)
|
|
252
255
|
let docState = resolvePublicDocState({ collection, docId, doc, idFields, hydrateCompatDocData: true })
|
|
253
256
|
if (!docState.exists && segments.length > 2) {
|
|
@@ -263,7 +266,9 @@ export async function setPublicDocReplace (segments, value) {
|
|
|
263
266
|
value = raw(value)
|
|
264
267
|
if (value != null) {
|
|
265
268
|
value = JSON.parse(JSON.stringify(value))
|
|
266
|
-
|
|
269
|
+
// Same contract as setPublicDoc(): only doc-root writes should strip the
|
|
270
|
+
// identity fields of the target document itself.
|
|
271
|
+
if (segments.length === 2) value = stripIdFields(value, idFields)
|
|
267
272
|
}
|
|
268
273
|
|
|
269
274
|
if (!docState.exists) {
|
|
@@ -296,7 +301,9 @@ export async function setPublicDocReplace (segments, value) {
|
|
|
296
301
|
|
|
297
302
|
const relativePath = segments.slice(2)
|
|
298
303
|
const previous = getRaw(segments)
|
|
299
|
-
const normalizedPrevious = normalizeUndefined(
|
|
304
|
+
const normalizedPrevious = normalizeUndefined(
|
|
305
|
+
relativePath.length === 0 ? stripIdFields(previous, idFields) : previous
|
|
306
|
+
)
|
|
300
307
|
const normalizedValue = normalizeUndefined(value)
|
|
301
308
|
let op
|
|
302
309
|
if (relativePath.length === 0) {
|
package/orm/idFields.js
CHANGED
|
@@ -50,8 +50,39 @@ export function stripIdFields (value, idFields) {
|
|
|
50
50
|
return next
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
export function resolveAddDocId (value, getDefaultId) {
|
|
54
|
+
if (!value || typeof value !== 'object') throw Error('Signal.add() expects an object argument')
|
|
55
|
+
const hasId = value.id != null
|
|
56
|
+
const hasUnderscoreId = value._id != null
|
|
57
|
+
if (hasId && hasUnderscoreId && value.id !== value._id) {
|
|
58
|
+
throw Error(
|
|
59
|
+
`Signal.add() got conflicting "id" (${JSON.stringify(value.id)}) and "_id" (${JSON.stringify(value._id)})`
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
return value.id ?? value._id ?? getDefaultId()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function prepareAddPayload (value, idFields, docId) {
|
|
66
|
+
if (idFields.includes('_id')) value._id = docId
|
|
67
|
+
if (idFields.includes('id')) {
|
|
68
|
+
value.id = docId
|
|
69
|
+
} else if (value.id === docId) {
|
|
70
|
+
delete value.id
|
|
71
|
+
}
|
|
72
|
+
return value
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function isPublicDocPath (segments) {
|
|
76
|
+
if (!Array.isArray(segments) || segments.length !== 2) return false
|
|
77
|
+
const [collection, docId] = segments
|
|
78
|
+
if (typeof collection !== 'string' || !collection) return false
|
|
79
|
+
if (collection[0] === '_' || collection[0] === '$') return false
|
|
80
|
+
return docId != null
|
|
81
|
+
}
|
|
82
|
+
|
|
53
83
|
export function isIdFieldPath (segments, idFields) {
|
|
54
|
-
if (segments.length
|
|
55
|
-
|
|
84
|
+
if (!Array.isArray(segments) || segments.length !== 3) return false
|
|
85
|
+
if (!isPublicDocPath(segments.slice(0, 2))) return false
|
|
86
|
+
const last = segments[2]
|
|
56
87
|
return idFields.includes(last)
|
|
57
88
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "teamplay",
|
|
3
|
-
"version": "0.4.0-alpha.
|
|
3
|
+
"version": "0.4.0-alpha.79",
|
|
4
4
|
"description": "Full-stack signals ORM with multiplayer",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
]
|
|
84
84
|
},
|
|
85
85
|
"license": "MIT",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "d01896f3f43e3ef7a96a514ae7b870041fee2ed4"
|
|
87
87
|
}
|