teamplay 0.5.0-alpha.26 → 0.5.0-alpha.28

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.
@@ -1,10 +1,10 @@
1
1
  import { raw, observe, unobserve } from '@nx-js/observer-util';
2
2
  import arrayDiff from 'arraydiff';
3
3
  import { Signal, GETTERS, DEFAULT_GETTERS, SEGMENTS, isPublicCollection, isPublicCollectionSignal, isPublicDocumentSignal } from "../SignalBase.js";
4
- import { getRoot, ROOT, ROOT_ID, getRootSignal, GLOBAL_ROOT_ID, unregisterRootFinalizer } from "../Root.js";
4
+ import { getRoot, ROOT, ROOT_ID, getRootSignal, GLOBAL_ROOT_ID } from "../Root.js";
5
5
  import { docSubscriptions } from '../Doc.js';
6
- import { IS_QUERY, getQuerySignal, querySubscriptions } from '../Query.js';
7
- import { AGGREGATIONS, IS_AGGREGATION, aggregationSubscriptions, getAggregationSignal } from '../Aggregation.js';
6
+ import { IS_QUERY, querySubscriptions } from '../Query.js';
7
+ import { AGGREGATIONS, IS_AGGREGATION, aggregationSubscriptions } from '../Aggregation.js';
8
8
  import { getIdFieldsForSegments, isIdFieldPath, isPublicDocPath, normalizeIdFields, isPlainObject } from "../idFields.js";
9
9
  import { incrementPublic as _incrementPublic, arrayPushPublic as _arrayPushPublic, arrayUnshiftPublic as _arrayUnshiftPublic, arrayInsertPublic as _arrayInsertPublic, arrayPopPublic as _arrayPopPublic, arrayShiftPublic as _arrayShiftPublic, arrayRemovePublic as _arrayRemovePublic, arrayMovePublic as _arrayMovePublic, setPublicDocReplace as _setPublicDocReplace, stringInsertPublic as _stringInsertPublic, stringRemovePublic as _stringRemovePublic } from '../dataTree.js';
10
10
  import { on as onCustomEvent, removeListener as removeCustomEventListener } from './eventsCompat.js';
@@ -16,7 +16,6 @@ import { runInBatch } from '../batchScheduler.js';
16
16
  import { runInSilentContext, runInModelEventsSilentContext, isSilentContextActive } from './silentContext.js';
17
17
  import universal$ from "../../react/universal$.js";
18
18
  import { getRootContext } from "../rootContext.js";
19
- import disposeRootContext from "../disposeRootContext.js";
20
19
  import { arrayInsertPrivateData, arrayMovePrivateData, arrayPopPrivateData, arrayPushPrivateData, arrayRemovePrivateData, arrayShiftPrivateData, arrayUnshiftPrivateData, delPrivateData, setReplacePrivateData, stringInsertPrivateData, stringRemovePrivateData } from '../privateData.js';
21
20
  class SignalCompat extends Signal {
22
21
  static ID_FIELDS = ['_id', 'id'];
@@ -50,38 +49,15 @@ class SignalCompat extends Signal {
50
49
  throw Error('Signal.getDeepCopy() does not accept any arguments');
51
50
  return deepCopy(this.get());
52
51
  }
53
- query(collection, params, options) {
54
- if (arguments.length < 1 || arguments.length > 3)
55
- throw Error('Signal.query() expects one to three arguments');
56
- if (typeof collection !== 'string')
57
- throw Error('Signal.query() expects collection to be a string');
58
- const normalized = normalizeQueryParams(collection, params);
59
- const root = getRoot(this) || (this[ROOT_ID] ? this : undefined);
60
- const scopedOptions = withQueryScopeOptions(options, root);
61
- if (isAggregationParams(normalized)) {
62
- return getAggregationSignal(collection, normalized, scopedOptions);
63
- }
64
- return getQuerySignal(collection, normalized, scopedOptions);
65
- }
66
- subscribe(...items) {
67
- if (items.length > 0)
68
- return subscribeMany(items, 'subscribe');
69
- return subscribeSelf(this);
70
- }
71
- unsubscribe(...items) {
72
- if (items.length > 0)
73
- return subscribeMany(items, 'unsubscribe');
74
- return unsubscribeSelf(this);
75
- }
76
52
  fetch(...items) {
77
53
  if (items.length > 0)
78
- return subscribeMany(items, 'subscribe', 'fetch');
79
- return subscribeSelf(this, 'fetch');
54
+ return subscribeMany(items, 'subscribe', 'fetch', 'fetch');
55
+ return subscribeSelf(this, 'fetch', 'fetch');
80
56
  }
81
57
  unfetch(...items) {
82
58
  if (items.length > 0)
83
- return subscribeMany(items, 'unsubscribe', 'fetch');
84
- return unsubscribeSelf(this, 'fetch');
59
+ return subscribeMany(items, 'unsubscribe', 'fetch', 'unfetch');
60
+ return unsubscribeSelf(this, 'fetch', 'unfetch');
85
61
  }
86
62
  getExtra() {
87
63
  if (arguments.length > 0)
@@ -92,24 +68,6 @@ class SignalCompat extends Signal {
92
68
  return this.extra.get();
93
69
  return undefined;
94
70
  }
95
- close(callback) {
96
- if (arguments.length > 1)
97
- throw Error('Signal.close() expects zero or one argument');
98
- if (callback != null && typeof callback !== 'function') {
99
- throw Error('Signal.close() expects callback to be a function');
100
- }
101
- const $root = getRoot(this) || this;
102
- const rootId = $root?.[ROOT_ID];
103
- unregisterRootFinalizer($root);
104
- disposeRootContext(rootId)
105
- .then(() => callback?.())
106
- .catch(err => {
107
- if (callback)
108
- callback(err);
109
- else
110
- console.error(err);
111
- });
112
- }
113
71
  silent(value) {
114
72
  if (arguments.length > 1)
115
73
  throw Error('Signal.silent() expects zero or one argument');
@@ -1068,53 +1026,18 @@ function deepCopy(value) {
1068
1026
  }
1069
1027
  return racerDeepCopy(rawValue);
1070
1028
  }
1071
- function normalizeQueryParams(collection, params) {
1072
- if (params == null) {
1073
- console.warn(`
1074
- [Signal.query] Query is undefined. Got:
1075
- ${collection}, ${params}
1076
- Falling back to {_id: '__NON_EXISTENT__'} query to prevent critical crash.
1077
- You should prevent situations when the \`query\` is undefined.
1078
- `);
1079
- return { _id: '__NON_EXISTENT__' };
1080
- }
1081
- if (Array.isArray(params)) {
1082
- return { _id: { $in: params.slice() } };
1083
- }
1084
- if (typeof params === 'string' || typeof params === 'number') {
1085
- return { _id: params };
1086
- }
1087
- if (typeof params !== 'object') {
1088
- throw Error(`Signal.query() expects params to be an object, array, or id. Got: ${params}`);
1089
- }
1090
- return params;
1091
- }
1092
- function isAggregationParams(params) {
1093
- return Boolean(params?.$aggregate || params?.$aggregationName);
1094
- }
1095
- function withQueryScopeOptions(options, $root) {
1096
- if (!options || typeof options !== 'object') {
1097
- if (!$root)
1098
- return options;
1099
- return { root: $root };
1100
- }
1101
- const nextOptions = { ...options };
1102
- if (nextOptions.root == null && $root)
1103
- nextOptions.root = $root;
1104
- return nextOptions;
1105
- }
1106
- function subscribeMany(items, action, intent = 'subscribe') {
1029
+ function subscribeMany(items, action, intent = 'subscribe', methodName = action) {
1107
1030
  const targets = flattenItems(items);
1108
1031
  const promises = [];
1109
1032
  for (const target of targets) {
1110
1033
  if (!target)
1111
1034
  continue;
1112
1035
  if (!(target instanceof Signal)) {
1113
- throw Error(`Signal.${action}() accepts only Signal instances. Got: ${target}`);
1036
+ throw Error(`Signal.${methodName}() accepts only Signal instances. Got: ${target}`);
1114
1037
  }
1115
1038
  const result = action === 'subscribe'
1116
- ? subscribeSelf(target, intent)
1117
- : unsubscribeSelf(target, intent);
1039
+ ? subscribeSelf(target, intent, methodName)
1040
+ : unsubscribeSelf(target, intent, methodName);
1118
1041
  if (result?.then)
1119
1042
  promises.push(result);
1120
1043
  }
@@ -1134,7 +1057,7 @@ function flattenItems(items, result = []) {
1134
1057
  }
1135
1058
  return result;
1136
1059
  }
1137
- function subscribeSelf($signal, intent = 'subscribe') {
1060
+ function subscribeSelf($signal, intent = 'subscribe', methodName = 'subscribe') {
1138
1061
  if ($signal[IS_QUERY]) {
1139
1062
  return (async () => {
1140
1063
  await querySubscriptions.subscribe($signal, { intent });
@@ -1150,14 +1073,14 @@ function subscribeSelf($signal, intent = 'subscribe') {
1150
1073
  if (isPublicDocumentSignal($signal))
1151
1074
  return docSubscriptions.subscribe($signal, { intent });
1152
1075
  if (isPublicCollectionSignal($signal)) {
1153
- throw Error('Signal.subscribe() expects a query signal. Use .query() for collections.');
1076
+ throw Error(`Signal.${methodName}() expects a document or query signal. Use sub($collection, params, { mode: 'fetch' }) for collection fetches.`);
1154
1077
  }
1155
1078
  if ($signal[SEGMENTS].length === 0) {
1156
- throw Error('Signal.subscribe() cannot be called on the root signal');
1079
+ throw Error(`Signal.${methodName}() cannot be called on the root signal`);
1157
1080
  }
1158
- throw Error('Signal.subscribe() expects a document or query signal');
1081
+ throw Error(`Signal.${methodName}() expects a document or query signal`);
1159
1082
  }
1160
- function unsubscribeSelf($signal, intent = 'subscribe') {
1083
+ function unsubscribeSelf($signal, intent = 'subscribe', methodName = 'unsubscribe') {
1161
1084
  if ($signal[IS_QUERY])
1162
1085
  return querySubscriptions.unsubscribe($signal, { intent });
1163
1086
  if ($signal[IS_AGGREGATION])
@@ -1165,12 +1088,12 @@ function unsubscribeSelf($signal, intent = 'subscribe') {
1165
1088
  if (isPublicDocumentSignal($signal))
1166
1089
  return docSubscriptions.unsubscribe($signal, { intent });
1167
1090
  if (isPublicCollectionSignal($signal)) {
1168
- throw Error('Signal.unsubscribe() expects a query signal. Use .query() for collections.');
1091
+ throw Error(`Signal.${methodName}() expects a document or query signal`);
1169
1092
  }
1170
1093
  if ($signal[SEGMENTS].length === 0) {
1171
- throw Error('Signal.unsubscribe() cannot be called on the root signal');
1094
+ throw Error(`Signal.${methodName}() cannot be called on the root signal`);
1172
1095
  }
1173
- throw Error('Signal.unsubscribe() expects a document or query signal');
1096
+ throw Error(`Signal.${methodName}() expects a document or query signal`);
1174
1097
  }
1175
1098
  // Racer-style deep copy:
1176
1099
  // - Preserves prototypes by instantiating via `new value.constructor()`
@@ -14,8 +14,12 @@ export type RootSignalRuntime = SignalBaseInstance & {
14
14
  [ROOT]?: RootSignalRuntime;
15
15
  [ROOT_ID]?: string;
16
16
  };
17
+ export type RootCloseCallback = (err?: unknown) => void;
17
18
  export declare function getRootSignal({ rootFunction, fetchOnly, rootId, ...options }?: RootSignalOptions): RootSignalRuntime;
18
19
  export declare function getRoot(signal: RootSignalRuntime | undefined): RootSignalRuntime | undefined;
20
+ export declare function closeRootSignalAsync(signal: RootSignalRuntime | undefined): Promise<void>;
21
+ export declare function closeRootSignal(signal: RootSignalRuntime | undefined): Promise<void>;
22
+ export declare function closeRootSignal(signal: RootSignalRuntime | undefined, callback?: RootCloseCallback): void;
19
23
  export declare function getRootFetchOnly(rootOrRootId: RootSignalRuntime | string | undefined): boolean;
20
24
  export declare function getRootTransportMode(rootOrRootId: RootSignalRuntime | string | undefined, intent?: RootTransportIntent): RootTransportIntent;
21
25
  export declare function registerRootFinalizer($root: RootSignalRuntime | undefined): void;
package/dist/orm/Root.js CHANGED
@@ -43,6 +43,22 @@ export function getRoot(signal) {
43
43
  else
44
44
  return undefined;
45
45
  }
46
+ export function closeRootSignalAsync(signal) {
47
+ const $root = getRoot(signal) || signal;
48
+ const rootId = $root?.[ROOT_ID];
49
+ unregisterRootFinalizer($root);
50
+ return disposeRootContext(rootId);
51
+ }
52
+ export function closeRootSignal(signal, callback) {
53
+ const promise = closeRootSignalAsync(signal);
54
+ if (!callback)
55
+ return promise;
56
+ promise
57
+ .then(() => callback?.())
58
+ .catch(err => {
59
+ callback(err);
60
+ });
61
+ }
46
62
  export function getRootFetchOnly(rootOrRootId) {
47
63
  const $root = typeof rootOrRootId === 'string'
48
64
  ? undefined
@@ -45,6 +45,8 @@ export declare class Signal<TValue = unknown> extends Function {
45
45
  * @param fn Function to execute inside the batch.
46
46
  */
47
47
  batch<TResult>(fn: () => TResult): TResult;
48
+ close(): Promise<void>;
49
+ close(callback: (err?: unknown) => void): void;
48
50
  /**
49
51
  * Internal read hook used by `.get()` and `.peek()`.
50
52
  * @param method Storage read function to use for the current signal path.
@@ -20,7 +20,7 @@ import getSignal, { rawSignal } from "./getSignal.js";
20
20
  import { docSubscriptions } from './Doc.js';
21
21
  import { IS_QUERY, HASH, QUERIES } from './Query.js';
22
22
  import { AGGREGATIONS, IS_AGGREGATION, getAggregationCollectionName, getAggregationDocId } from './Aggregation.js';
23
- import { ROOT_FUNCTION, ROOT_ID, getRoot } from "./Root.js";
23
+ import { ROOT_FUNCTION, ROOT_ID, closeRootSignal, getRoot } from "./Root.js";
24
24
  import { DEFAULT_ID_FIELDS, getIdFieldsForSegments, isIdFieldPath, isPlainObject, isPublicDocPath, normalizeIdFields, prepareAddPayload, resolveAddDocId } from "./idFields.js";
25
25
  import { isCompatEnv } from './compatEnv.js';
26
26
  import { resolveRefSegmentsSafe, resolveRefSignalSafe } from './Compat/refFallback.js';
@@ -181,6 +181,14 @@ export class Signal extends Function {
181
181
  throw Error('Signal.batch() expects a function argument');
182
182
  return runInBatch(fn);
183
183
  }
184
+ close(callback) {
185
+ if (arguments.length > 1)
186
+ throw Error('Signal.close() expects zero or one argument');
187
+ if (callback != null && typeof callback !== 'function') {
188
+ throw Error('Signal.close() expects callback to be a function');
189
+ }
190
+ return callback ? closeRootSignal(this, callback) : closeRootSignal(this);
191
+ }
184
192
  /**
185
193
  * Internal read hook used by `.get()` and `.peek()`.
186
194
  * @param method Storage read function to use for the current signal path.
@@ -769,8 +777,8 @@ export const regularBindings = {
769
777
  return Reflect.apply(extremelyLateBindings.get, this, arguments);
770
778
  }
771
779
  };
772
- const QUERY_METHODS = ['map', 'reduce', 'find', 'get', 'getIds', 'getExtra', 'subscribe', 'unsubscribe', 'fetch', 'unfetch'];
773
- const AGGREGATION_ALLOWED_METHODS = ['subscribe', 'unsubscribe', 'fetch', 'unfetch', 'ref', 'removeRef', 'refExtra', 'refIds'];
780
+ const QUERY_METHODS = ['map', 'reduce', 'find', 'get', 'getIds', 'getExtra', 'fetch', 'unfetch'];
781
+ const AGGREGATION_ALLOWED_METHODS = ['fetch', 'unfetch', 'ref', 'removeRef', 'refExtra', 'refIds'];
774
782
  // dot syntax always returns a child signal even if such method or property exists.
775
783
  // The method is only called when the signal is explicitly called as a function,
776
784
  // in which case we get the original method from the raw (non-proxied) parent signal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teamplay",
3
- "version": "0.5.0-alpha.26",
3
+ "version": "0.5.0-alpha.28",
4
4
  "description": "Full-stack signals ORM with multiplayer",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -134,5 +134,5 @@
134
134
  ]
135
135
  },
136
136
  "license": "MIT",
137
- "gitHead": "a432e1c1dc272cfe2b87e3820557db4721a0f38b"
137
+ "gitHead": "3b775365e270ca2f93918780d3be4d03c4e56d51"
138
138
  }