teamplay 0.3.3 → 0.3.5

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.
@@ -50,12 +50,11 @@ export function isAggregationSignal ($signal) {
50
50
 
51
51
  // example: ['$aggregations', '{"active":true}', 42]
52
52
  // AND only if it also has either '_id' or 'id' field inside
53
- export function getAggregationDocId (segments) {
53
+ export function getAggregationDocId (segments, method = getRaw) {
54
54
  if (!(segments.length >= 3)) return
55
55
  if (!(segments[0] === AGGREGATIONS)) return
56
56
  if (!(typeof segments[2] === 'number')) return
57
- const doc = getRaw(segments.slice(0, 3))
58
- const docId = doc?._id || doc?.id
57
+ const docId = method([...segments.slice(0, 3), '_id']) || method([...segments.slice(0, 3), 'id'])
59
58
  return docId
60
59
  }
61
60
 
package/orm/Signal.js CHANGED
@@ -79,6 +79,11 @@ export default class Signal extends Function {
79
79
  getId () {
80
80
  if (this[SEGMENTS].length === 0) throw Error('Can\'t get the id of the root signal')
81
81
  if (this[SEGMENTS].length === 1) throw Error('Can\'t get the id of a collection')
82
+ if (this[SEGMENTS][0] === AGGREGATIONS && this[SEGMENTS].length === 3) {
83
+ // use get() instead of the default getRaw() to trigger observability on changes
84
+ // This is required since within aggregation array results docs can change their position
85
+ return getAggregationDocId(this[SEGMENTS], _get)
86
+ }
82
87
  return this[SEGMENTS][this[SEGMENTS].length - 1]
83
88
  }
84
89
 
package/orm/sub.js CHANGED
@@ -3,6 +3,7 @@ import Signal, { SEGMENTS, isPublicCollectionSignal, isPublicDocumentSignal } fr
3
3
  import { docSubscriptions } from './Doc.js'
4
4
  import { querySubscriptions, getQuerySignal } from './Query.js'
5
5
  import { aggregationSubscriptions, getAggregationSignal } from './Aggregation.js'
6
+ import isServer from '../utils/isServer.js'
6
7
 
7
8
  export default function sub ($signal, params) {
8
9
  // TODO: temporarily disable support for multiple subscriptions
@@ -20,9 +21,7 @@ export default function sub ($signal, params) {
20
21
  if (arguments.length !== 2) throw Error(ERRORS.subQueryArguments(...arguments))
21
22
  return query$($signal[SEGMENTS][0], params)
22
23
  } else if (isClientAggregationFunction($signal)) {
23
- params = $signal(sanitizeAggregationParams(params))
24
- if (Array.isArray(params)) params = { $aggregate: params }
25
- return aggregation$($signal.collection, params)
24
+ return getAggregationFromFunction($signal, $signal.collection, params)
26
25
  } else if (isAggregationHeader($signal)) {
27
26
  params = {
28
27
  $aggregationName: $signal.name,
@@ -30,7 +29,15 @@ export default function sub ($signal, params) {
30
29
  }
31
30
  return aggregation$($signal.collection, params)
32
31
  } else if (isAggregationFunction($signal)) {
33
- throw Error(ERRORS.gotAggregationFunction($signal))
32
+ if (isServer) {
33
+ if (!params?.$collection) throw Error(ERRORS.subServerAggregationCollection($signal, params))
34
+ params = { ...params }
35
+ const collection = params.$collection
36
+ delete params.$collection
37
+ return getAggregationFromFunction($signal, collection, params)
38
+ } else {
39
+ throw Error(ERRORS.gotAggregationFunction($signal))
40
+ }
34
41
  } else if (typeof $signal === 'function' && !($signal instanceof Signal)) {
35
42
  return api$($signal, params)
36
43
  } else {
@@ -38,6 +45,21 @@ export default function sub ($signal, params) {
38
45
  }
39
46
  }
40
47
 
48
+ function getAggregationFromFunction (fn, collection, params) {
49
+ params = sanitizeAggregationParams(params) // clones it, so mutation becomes safe
50
+ let session
51
+ if (params.$session) {
52
+ session = params.$session
53
+ delete params.$session
54
+ }
55
+ session ??= {}
56
+ // should match the context in @teamplay/backend/features/serverAggregate.js
57
+ const context = { collection, session, isServer }
58
+ params = fn(params, context)
59
+ if (Array.isArray(params)) params = { $aggregate: params }
60
+ return aggregation$(collection, params)
61
+ }
62
+
41
63
  function doc$ ($doc) {
42
64
  const promise = docSubscriptions.subscribe($doc)
43
65
  if (!promise) return $doc
@@ -104,5 +126,16 @@ const ERRORS = {
104
126
 
105
127
  Got:
106
128
  ${aggregationFn.toString()}
129
+ `,
130
+ subServerAggregationCollection: ($signal, params) => `
131
+ sub($$aggregation, params):
132
+ Server-side aggregation function must receive the collection name from the params.
133
+ Make sure you pass the collection name as $collection in the params object
134
+ when running aggregation from the server code:
135
+ sub($$aggregation, { $collection: 'collectionName', ...actualParams })
136
+
137
+ Got:
138
+ Aggregation: ${$signal}
139
+ Params: ${params}
107
140
  `
108
141
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teamplay",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "Full-stack signals ORM with multiplayer",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -23,12 +23,12 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@nx-js/observer-util": "^4.1.3",
26
- "@teamplay/backend": "^0.3.3",
27
- "@teamplay/cache": "^0.3.3",
28
- "@teamplay/channel": "^0.3.3",
29
- "@teamplay/debug": "^0.3.3",
30
- "@teamplay/schema": "^0.3.3",
31
- "@teamplay/utils": "^0.3.3",
26
+ "@teamplay/backend": "^0.3.5",
27
+ "@teamplay/cache": "^0.3.5",
28
+ "@teamplay/channel": "^0.3.5",
29
+ "@teamplay/debug": "^0.3.5",
30
+ "@teamplay/schema": "^0.3.5",
31
+ "@teamplay/utils": "^0.3.5",
32
32
  "diff-match-patch": "^1.0.5",
33
33
  "events": "^3.3.0",
34
34
  "json0-ot-diff": "^1.1.2",
@@ -63,5 +63,5 @@
63
63
  ]
64
64
  },
65
65
  "license": "MIT",
66
- "gitHead": "3cb65f144eafd59cbb646328e503f4747df98279"
66
+ "gitHead": "71a44c6607f54297e8eb37b0361fbbfc27b3a14b"
67
67
  }