teamplay 0.3.1 → 0.3.4

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/connect/test.js CHANGED
@@ -7,6 +7,18 @@ import { connection, setConnection } from '../orm/connection.js'
7
7
 
8
8
  export default function connect () {
9
9
  if (connection) return
10
+ patchSharedbMingoAggregations()
10
11
  const backend = new ShareBackend({ db: new ShareDbMingo() })
11
12
  setConnection(backend.connect())
12
13
  }
14
+
15
+ let patched
16
+ function patchSharedbMingoAggregations () {
17
+ if (patched) return
18
+ patched = true
19
+ const oldCanPollDoc = ShareDbMingo.prototype.canPollDoc
20
+ ShareDbMingo.prototype.canPollDoc = function (collection, query) {
21
+ if (query.hasOwnProperty('$aggregate')) return false // eslint-disable-line no-prototype-builtins
22
+ return oldCanPollDoc.call(this, collection, query)
23
+ }
24
+ }
@@ -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)
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
@@ -16,7 +16,7 @@ import { get as _get, set as _set, del as _del, setPublicDoc as _setPublicDoc, g
16
16
  import getSignal, { rawSignal } from './getSignal.js'
17
17
  import { docSubscriptions } from './Doc.js'
18
18
  import { IS_QUERY, HASH, QUERIES } from './Query.js'
19
- import { AGGREGATIONS, getAggregationCollectionName, getAggregationDocId } from './Aggregation.js'
19
+ import { AGGREGATIONS, IS_AGGREGATION, getAggregationCollectionName, getAggregationDocId } from './Aggregation.js'
20
20
  import { ROOT_FUNCTION, getRoot } from './Root.js'
21
21
  import { publicOnly } from './connection.js'
22
22
 
@@ -24,7 +24,7 @@ export const SEGMENTS = Symbol('path segments targeting the particular node in t
24
24
  export const ARRAY_METHOD = Symbol('run array method on the signal')
25
25
  export const GET = Symbol('get the value of the signal - either observed or raw')
26
26
  export const GETTERS = Symbol('get the list of this signal\'s getters')
27
- const DEFAULT_GETTERS = ['path', 'id', 'get', 'peek', 'getId', 'map', 'reduce', 'find']
27
+ const DEFAULT_GETTERS = ['path', 'id', 'get', 'peek', 'getId', 'map', 'reduce', 'find', 'getIds']
28
28
 
29
29
  export default class Signal extends Function {
30
30
  static [GETTERS] = DEFAULT_GETTERS
@@ -58,6 +58,19 @@ export default class Signal extends Function {
58
58
  return this[GET](_get)
59
59
  }
60
60
 
61
+ getIds () {
62
+ if (arguments.length > 0) throw Error('Signal.getIds() does not accept any arguments')
63
+ if (this[IS_QUERY]) {
64
+ return _get([QUERIES, this[HASH], 'ids'])
65
+ } else if (this[IS_AGGREGATION]) {
66
+ const docs = _get(this[SEGMENTS])
67
+ if (!Array.isArray(docs)) return []
68
+ return docs.map(doc => doc._id || doc.id)
69
+ } else {
70
+ throw Error('Signal.getIds() can only be used on query signals or aggregation signals')
71
+ }
72
+ }
73
+
61
74
  peek () {
62
75
  if (arguments.length > 0) throw Error('Signal.peek() does not accept any arguments')
63
76
  return this[GET](getRaw)
@@ -66,6 +79,11 @@ export default class Signal extends Function {
66
79
  getId () {
67
80
  if (this[SEGMENTS].length === 0) throw Error('Can\'t get the id of the root signal')
68
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
+ }
69
87
  return this[SEGMENTS][this[SEGMENTS].length - 1]
70
88
  }
71
89
 
@@ -212,7 +230,7 @@ export const regularBindings = {
212
230
  }
213
231
  }
214
232
 
215
- const QUERY_METHODS = ['map', 'reduce', 'find', 'get']
233
+ const QUERY_METHODS = ['map', 'reduce', 'find', 'get', 'getIds']
216
234
 
217
235
  // dot syntax always returns a child signal even if such method or property exists.
218
236
  // The method is only called when the signal is explicitly called as a function,
package/orm/sub.js CHANGED
@@ -1,4 +1,4 @@
1
- import { isAggregationHeader, isAggregationFunction } from '@teamplay/utils/aggregation'
1
+ import { isAggregationHeader, isAggregationFunction, isClientAggregationFunction } from '@teamplay/utils/aggregation'
2
2
  import Signal, { SEGMENTS, isPublicCollectionSignal, isPublicDocumentSignal } from './Signal.js'
3
3
  import { docSubscriptions } from './Doc.js'
4
4
  import { querySubscriptions, getQuerySignal } from './Query.js'
@@ -19,8 +19,10 @@ export default function sub ($signal, params) {
19
19
  } else if (isPublicCollectionSignal($signal)) {
20
20
  if (arguments.length !== 2) throw Error(ERRORS.subQueryArguments(...arguments))
21
21
  return query$($signal[SEGMENTS][0], params)
22
- } else if (typeof $signal === 'function' && !($signal instanceof Signal)) {
23
- return api$($signal, params)
22
+ } else if (isClientAggregationFunction($signal)) {
23
+ params = $signal(sanitizeAggregationParams(params))
24
+ if (Array.isArray(params)) params = { $aggregate: params }
25
+ return aggregation$($signal.collection, params)
24
26
  } else if (isAggregationHeader($signal)) {
25
27
  params = {
26
28
  $aggregationName: $signal.name,
@@ -29,6 +31,8 @@ export default function sub ($signal, params) {
29
31
  return aggregation$($signal.collection, params)
30
32
  } else if (isAggregationFunction($signal)) {
31
33
  throw Error(ERRORS.gotAggregationFunction($signal))
34
+ } else if (typeof $signal === 'function' && !($signal instanceof Signal)) {
35
+ return api$($signal, params)
32
36
  } else {
33
37
  throw Error('Invalid args passed for sub()')
34
38
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teamplay",
3
- "version": "0.3.1",
3
+ "version": "0.3.4",
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.1",
27
- "@teamplay/cache": "^0.3.1",
28
- "@teamplay/channel": "^0.3.1",
29
- "@teamplay/debug": "^0.3.1",
30
- "@teamplay/schema": "^0.3.1",
31
- "@teamplay/utils": "^0.3.1",
26
+ "@teamplay/backend": "^0.3.4",
27
+ "@teamplay/cache": "^0.3.4",
28
+ "@teamplay/channel": "^0.3.4",
29
+ "@teamplay/debug": "^0.3.4",
30
+ "@teamplay/schema": "^0.3.4",
31
+ "@teamplay/utils": "^0.3.4",
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": "cc2715ccbfdf6213abc607aceaae76c331a7738d"
66
+ "gitHead": "108c0d37aea7cbe37686fafaf129e941937d7707"
67
67
  }