teamplay 0.5.0-alpha.21 → 0.5.0-alpha.23

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.
@@ -2,7 +2,6 @@ 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
4
  import { getRoot, ROOT, ROOT_ID, getRootSignal, GLOBAL_ROOT_ID, unregisterRootFinalizer } from "../Root.js";
5
- import { isPrivateMutationForbidden } from "../connection.js";
6
5
  import { docSubscriptions } from '../Doc.js';
7
6
  import { IS_QUERY, getQuerySignal, querySubscriptions } from '../Query.js';
8
7
  import { AGGREGATIONS, IS_AGGREGATION, aggregationSubscriptions, getAggregationSignal } from '../Aggregation.js';
@@ -150,22 +149,6 @@ class SignalCompat extends Signal {
150
149
  return Signal.prototype.set.call(this, value);
151
150
  return setReplaceOnSignal(this, value);
152
151
  }
153
- async add(collectionOrValue, value) {
154
- const isRoot = this[SEGMENTS].length === 0;
155
- const isRootCollectionCall = isRoot && typeof collectionOrValue === 'string';
156
- if (isRootCollectionCall) {
157
- if (arguments.length !== 2)
158
- throw Error('Signal.add() expects (collection, object)');
159
- if (!value || typeof value !== 'object')
160
- throw Error('Signal.add() expects an object argument');
161
- const $root = getRoot(this) || this;
162
- const $collection = resolveSignal($root, [collectionOrValue]);
163
- return $collection.add(value);
164
- }
165
- if (arguments.length > 1)
166
- throw Error('Signal.add() expects a single argument');
167
- return Signal.prototype.add.call(this, collectionOrValue);
168
- }
169
152
  async setNull(value) {
170
153
  const forwarded = forwardRef(this, 'setNull', arguments);
171
154
  if (forwarded)
@@ -928,8 +911,6 @@ async function setReplaceOnSignal($signal, value) {
928
911
  }
929
912
  return result;
930
913
  }
931
- if (isPrivateMutationForbidden())
932
- throw Error(ERRORS.publicOnly);
933
914
  const result = setReplacePrivateData(getOwningRootId($signal), segments, value);
934
915
  if (shouldMirrorPrivateRefMutationLocally()) {
935
916
  mirrorRefMutationFromTarget(segments, value);
@@ -956,8 +937,6 @@ async function incrementOnSignal($signal, byNumber) {
956
937
  await _incrementPublic(segments, byNumber);
957
938
  return currentValue + byNumber;
958
939
  }
959
- if (isPrivateMutationForbidden())
960
- throw Error(ERRORS.publicOnly);
961
940
  setReplacePrivateData(getOwningRootId($signal), segments, currentValue + byNumber);
962
941
  return currentValue + byNumber;
963
942
  }
@@ -993,8 +972,6 @@ async function arrayPushOnSignal($signal, value) {
993
972
  return;
994
973
  if (isPublicCollection(segments[0]))
995
974
  return _arrayPushPublic(segments, value);
996
- if (isPrivateMutationForbidden())
997
- throw Error(ERRORS.publicOnly);
998
975
  return arrayPushPrivateData(getOwningRootId($signal), segments, value);
999
976
  }
1000
977
  async function arrayUnshiftOnSignal($signal, value) {
@@ -1004,8 +981,6 @@ async function arrayUnshiftOnSignal($signal, value) {
1004
981
  return;
1005
982
  if (isPublicCollection(segments[0]))
1006
983
  return _arrayUnshiftPublic(segments, value);
1007
- if (isPrivateMutationForbidden())
1008
- throw Error(ERRORS.publicOnly);
1009
984
  return arrayUnshiftPrivateData(getOwningRootId($signal), segments, value);
1010
985
  }
1011
986
  async function arrayInsertOnSignal($signal, index, values) {
@@ -1015,8 +990,6 @@ async function arrayInsertOnSignal($signal, index, values) {
1015
990
  return;
1016
991
  if (isPublicCollection(segments[0]))
1017
992
  return _arrayInsertPublic(segments, index, values);
1018
- if (isPrivateMutationForbidden())
1019
- throw Error(ERRORS.publicOnly);
1020
993
  return arrayInsertPrivateData(getOwningRootId($signal), segments, index, values);
1021
994
  }
1022
995
  async function arrayPopOnSignal($signal) {
@@ -1026,8 +999,6 @@ async function arrayPopOnSignal($signal) {
1026
999
  return;
1027
1000
  if (isPublicCollection(segments[0]))
1028
1001
  return _arrayPopPublic(segments);
1029
- if (isPrivateMutationForbidden())
1030
- throw Error(ERRORS.publicOnly);
1031
1002
  return arrayPopPrivateData(getOwningRootId($signal), segments);
1032
1003
  }
1033
1004
  async function arrayShiftOnSignal($signal) {
@@ -1037,8 +1008,6 @@ async function arrayShiftOnSignal($signal) {
1037
1008
  return;
1038
1009
  if (isPublicCollection(segments[0]))
1039
1010
  return _arrayShiftPublic(segments);
1040
- if (isPrivateMutationForbidden())
1041
- throw Error(ERRORS.publicOnly);
1042
1011
  return arrayShiftPrivateData(getOwningRootId($signal), segments);
1043
1012
  }
1044
1013
  async function arrayRemoveOnSignal($signal, index, howMany) {
@@ -1048,8 +1017,6 @@ async function arrayRemoveOnSignal($signal, index, howMany) {
1048
1017
  return;
1049
1018
  if (isPublicCollection(segments[0]))
1050
1019
  return _arrayRemovePublic(segments, index, howMany);
1051
- if (isPrivateMutationForbidden())
1052
- throw Error(ERRORS.publicOnly);
1053
1020
  return arrayRemovePrivateData(getOwningRootId($signal), segments, index, howMany);
1054
1021
  }
1055
1022
  async function arrayMoveOnSignal($signal, from, to, howMany) {
@@ -1059,8 +1026,6 @@ async function arrayMoveOnSignal($signal, from, to, howMany) {
1059
1026
  return;
1060
1027
  if (isPublicCollection(segments[0]))
1061
1028
  return _arrayMovePublic(segments, from, to, howMany);
1062
- if (isPrivateMutationForbidden())
1063
- throw Error(ERRORS.publicOnly);
1064
1029
  return arrayMovePrivateData(getOwningRootId($signal), segments, from, to, howMany);
1065
1030
  }
1066
1031
  async function stringInsertOnSignal($signal, index, text) {
@@ -1070,8 +1035,6 @@ async function stringInsertOnSignal($signal, index, text) {
1070
1035
  return;
1071
1036
  if (isPublicCollection(segments[0]))
1072
1037
  return _stringInsertPublic(segments, index, text);
1073
- if (isPrivateMutationForbidden())
1074
- throw Error(ERRORS.publicOnly);
1075
1038
  return stringInsertPrivateData(getOwningRootId($signal), segments, index, text);
1076
1039
  }
1077
1040
  async function stringRemoveOnSignal($signal, index, howMany) {
@@ -1081,8 +1044,6 @@ async function stringRemoveOnSignal($signal, index, howMany) {
1081
1044
  return;
1082
1045
  if (isPublicCollection(segments[0]))
1083
1046
  return _stringRemovePublic(segments, index, howMany);
1084
- if (isPrivateMutationForbidden())
1085
- throw Error(ERRORS.publicOnly);
1086
1047
  return stringRemovePrivateData(getOwningRootId($signal), segments, index, howMany);
1087
1048
  }
1088
1049
  function getOwningRootId($signal) {
@@ -1264,11 +1225,5 @@ function racerDeepCopy(value) {
1264
1225
  }
1265
1226
  return value;
1266
1227
  }
1267
- const ERRORS = {
1268
- publicOnly: `
1269
- Can't modify private collections data when 'publicOnly' is enabled.
1270
- On the server you can only work with public collections.
1271
- `
1272
- };
1273
1228
  export { SignalCompat };
1274
1229
  export default SignalCompat;
@@ -21,7 +21,6 @@ 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
23
  import { ROOT_FUNCTION, ROOT_ID, getRoot } from "./Root.js";
24
- import { isPrivateMutationForbidden } from "./connection.js";
25
24
  import { DEFAULT_ID_FIELDS, getIdFieldsForSegments, isIdFieldPath, isPlainObject, isPublicDocPath, normalizeIdFields, prepareAddPayload, resolveAddDocId } from "./idFields.js";
26
25
  import { isCompatEnv } from './compatEnv.js';
27
26
  import { resolveRefSegmentsSafe, resolveRefSignalSafe } from './Compat/refFallback.js';
@@ -83,7 +82,6 @@ const SIGNAL_READ_CONTEXT = {
83
82
  const SIGNAL_VALUE_MUTATION_CONTEXT = {
84
83
  getOwningRootId: getSignalOwningRootId,
85
84
  isPublicCollection,
86
- isPrivateMutationForbidden,
87
85
  setPublicDoc: _setPublicDoc,
88
86
  setPrivateData,
89
87
  deletePublicDoc(segments) {
@@ -308,12 +306,6 @@ export class Signal extends Function {
308
306
  }
309
307
  return;
310
308
  }
311
- if (isPrivateMutationForbidden()) {
312
- throw Error(`
313
- Can't modify private collections data when 'publicOnly' is enabled.
314
- On the server you can only work with public collections.
315
- `);
316
- }
317
309
  setReplacePrivateData(getSignalOwningRootId(this), segments, nextValue);
318
310
  }
319
311
  /** Set the current value only when it is null or undefined. */
@@ -672,12 +664,6 @@ async function deleteForDiffDeep($signal, preservePath) {
672
664
  await $signal.del();
673
665
  return;
674
666
  }
675
- if (isPrivateMutationForbidden()) {
676
- throw Error(`
677
- Can't modify private collections data when 'publicOnly' is enabled.
678
- On the server you can only work with public collections.
679
- `);
680
- }
681
667
  delPrivateData(getSignalOwningRootId($signal), segments, { preservePath });
682
668
  }
683
669
  function getChildSignal($parent, key) {
@@ -16,11 +16,18 @@ export interface TeamplayConnection {
16
16
  [key: string]: unknown;
17
17
  }
18
18
  export declare let connection: TeamplayConnection | undefined;
19
- export declare let publicOnly: boolean | undefined;
19
+ /** @deprecated Root-scoped private data made the publicOnly write guard obsolete. */
20
+ export declare const publicOnly = false;
20
21
  export declare function setConnection(_connection: TeamplayConnection | undefined): void;
21
22
  export declare function getConnection(): TeamplayConnection;
22
23
  export declare function setDefaultFetchOnly(_fetchOnly: boolean): void;
23
24
  export declare function getDefaultFetchOnly(): boolean;
24
25
  export declare function setFetchOnly(_fetchOnly: boolean): void;
26
+ /**
27
+ * @deprecated No-op kept for compatibility with older server bootstrap code.
28
+ * Private collections are root-scoped; server safety now relies on avoiding
29
+ * writes to private collections through the global root.
30
+ */
25
31
  export declare function setPublicOnly(_publicOnly: boolean): void;
32
+ /** @deprecated publicOnly no longer blocks private writes. */
26
33
  export declare function isPrivateMutationForbidden(): boolean;
@@ -1,7 +1,7 @@
1
- import { isCompatEnv } from './compatEnv.js';
2
1
  export let connection;
3
2
  let defaultFetchOnly;
4
- export let publicOnly;
3
+ /** @deprecated Root-scoped private data made the publicOnly write guard obsolete. */
4
+ export const publicOnly = false;
5
5
  export function setConnection(_connection) {
6
6
  connection = _connection;
7
7
  }
@@ -20,11 +20,16 @@ export function getDefaultFetchOnly() {
20
20
  export function setFetchOnly(_fetchOnly) {
21
21
  setDefaultFetchOnly(_fetchOnly);
22
22
  }
23
+ /**
24
+ * @deprecated No-op kept for compatibility with older server bootstrap code.
25
+ * Private collections are root-scoped; server safety now relies on avoiding
26
+ * writes to private collections through the global root.
27
+ */
23
28
  export function setPublicOnly(_publicOnly) {
24
- publicOnly = _publicOnly;
25
29
  }
30
+ /** @deprecated publicOnly no longer blocks private writes. */
26
31
  export function isPrivateMutationForbidden() {
27
- return !!publicOnly && !isCompatEnv();
32
+ return false;
28
33
  }
29
34
  const ERRORS = {
30
35
  notSet: `
@@ -1,6 +1,11 @@
1
+ import isServer from "../utils/isServer.js";
1
2
  import { getRootContext } from "./rootContext.js";
2
- import { getPrivateDataSegments, isPrivateCollectionSegments } from "./rootScope.js";
3
+ import { getPrivateDataSegments, isGlobalRootId, isPrivateCollectionSegments } from "./rootScope.js";
3
4
  import { arrayInsert as _arrayInsert, arrayMove as _arrayMove, arrayPop as _arrayPop, arrayPush as _arrayPush, arrayRemove as _arrayRemove, arrayShift as _arrayShift, arrayUnshift as _arrayUnshift, del as _del, set as _set, setReplace as _setReplace, stringInsertLocal as _stringInsertLocal, stringRemoveLocal as _stringRemoveLocal } from './dataTree.js';
5
+ const warnedGlobalRootPrivateCollections = new Set();
6
+ export function __resetPrivateDataWarningsForTests() {
7
+ warnedGlobalRootPrivateCollections.clear();
8
+ }
4
9
  export function getPrivateDataRoot(rootId, create = false) {
5
10
  return getRootContext(rootId, create)?.getPrivateDataRoot();
6
11
  }
@@ -24,6 +29,7 @@ export function setPrivateData(rootId, logicalSegments, value) {
24
29
  const context = getRootContext(rootId, true);
25
30
  if (!context)
26
31
  return;
32
+ warnGlobalRootPrivateMutation(rootId, logicalSegments);
27
33
  const segments = getPrivateDataSegments(logicalSegments);
28
34
  _set(segments, value, context.getPrivateDataRoot(), getModelEventContext(rootId, logicalSegments));
29
35
  }
@@ -34,6 +40,7 @@ export function setReplacePrivateData(rootId, logicalSegments, value) {
34
40
  const context = getRootContext(rootId, true);
35
41
  if (!context)
36
42
  return;
43
+ warnGlobalRootPrivateMutation(rootId, logicalSegments);
37
44
  const segments = getPrivateDataSegments(logicalSegments);
38
45
  _setReplace(segments, value, context.getPrivateDataRoot(), getModelEventContext(rootId, logicalSegments));
39
46
  }
@@ -43,6 +50,7 @@ export function delPrivateData(rootId, logicalSegments, options = {}) {
43
50
  const context = getRootContext(rootId, false);
44
51
  if (!context)
45
52
  return;
53
+ warnGlobalRootPrivateMutation(rootId, logicalSegments);
46
54
  const segments = getPrivateDataSegments(logicalSegments);
47
55
  _del(segments, context.getPrivateDataRoot(), getModelEventContext(rootId, logicalSegments));
48
56
  pruneEmptyPrivateParents(context.getPrivateDataRoot(), context.getPrivateDataRawRoot(), segments, options);
@@ -108,8 +116,19 @@ function getRequiredPrivateContext(rootId, logicalSegments, methodName) {
108
116
  if (!isPrivateCollectionSegments(logicalSegments)) {
109
117
  throw Error(`${methodName} expects private collection segments`);
110
118
  }
119
+ warnGlobalRootPrivateMutation(rootId, logicalSegments);
111
120
  return getRootContext(rootId, true);
112
121
  }
122
+ function warnGlobalRootPrivateMutation(rootId, logicalSegments) {
123
+ if (!isServer || !isGlobalRootId(rootId) || !isPrivateCollectionSegments(logicalSegments))
124
+ return;
125
+ const collection = String(logicalSegments[0]);
126
+ if (warnedGlobalRootPrivateCollections.has(collection))
127
+ return;
128
+ warnedGlobalRootPrivateCollections.add(collection);
129
+ console.warn(`[teamplay] Writing to private collection "${collection}" on the global server root. ` +
130
+ 'Use a request-scoped root, getRootSignal({ rootId }), or req.model for per-request private state.');
131
+ }
113
132
  function getModelEventContext(rootId, logicalSegments) {
114
133
  return {
115
134
  rootId,
@@ -3,7 +3,6 @@ type MaybePromise<TValue> = TValue | Promise<TValue>;
3
3
  export interface SignalStorageMutationContext<TSignal> {
4
4
  getOwningRootId: ($signal: TSignal) => string | undefined;
5
5
  isPublicCollection: (segment: PathSegment | undefined) => boolean;
6
- isPrivateMutationForbidden: () => boolean;
7
6
  }
8
7
  export interface SignalStorageMutationHandlers<TResult> {
9
8
  public: (segments: PathSegment[]) => MaybePromise<TResult>;
@@ -14,5 +13,4 @@ export interface SignalStorageMutationResult<TResult> {
14
13
  value: TResult | undefined;
15
14
  }
16
15
  export declare function runSignalStorageMutation<TSignal, TResult>($signal: TSignal, context: SignalStorageMutationContext<TSignal>, segments: PathSegment[], handlers: SignalStorageMutationHandlers<TResult>): Promise<SignalStorageMutationResult<TResult>>;
17
- export declare function ensurePrivateMutationAllowed<TSignal>(context: Pick<SignalStorageMutationContext<TSignal>, 'isPrivateMutationForbidden'>): void;
18
16
  export {};
@@ -10,17 +10,8 @@ export async function runSignalStorageMutation($signal, context, segments, handl
10
10
  value: await handlers.public(segments)
11
11
  };
12
12
  }
13
- ensurePrivateMutationAllowed(context);
14
13
  return {
15
14
  skipped: false,
16
15
  value: await handlers.private(context.getOwningRootId($signal), segments)
17
16
  };
18
17
  }
19
- export function ensurePrivateMutationAllowed(context) {
20
- if (!context.isPrivateMutationForbidden())
21
- return;
22
- throw Error(`
23
- Can't modify private collections data when 'publicOnly' is enabled.
24
- On the server you can only work with public collections.
25
- `);
26
- }
@@ -1,4 +1,4 @@
1
- import { type SignalStorageMutationContext } from './signalStorageMutations.js';
1
+ import type { SignalStorageMutationContext } from './signalStorageMutations.js';
2
2
  import { SEGMENTS } from './signalSymbols.js';
3
3
  import type { PathSegment } from './types/path.js';
4
4
  export interface SignalValueMutationOwner {
@@ -1,5 +1,4 @@
1
1
  import { getIdFieldsForSegments, isIdFieldPath, isPublicDocPath, normalizeIdFields } from "./idFields.js";
2
- import { ensurePrivateMutationAllowed } from "./signalStorageMutations.js";
3
2
  import { SEGMENTS } from "./signalSymbols.js";
4
3
  export async function setSignalValue($signal, context, value) {
5
4
  const segments = $signal[SEGMENTS];
@@ -15,7 +14,6 @@ export async function setSignalValue($signal, context, value) {
15
14
  await context.setPublicDoc(segments, nextValue);
16
15
  return;
17
16
  }
18
- ensurePrivateMutationAllowed(context);
19
17
  context.setPrivateData(context.getOwningRootId($signal), segments, nextValue);
20
18
  }
21
19
  export async function deleteSignalValue($signal, context) {
@@ -31,6 +29,5 @@ export async function deleteSignalValue($signal, context) {
31
29
  await context.deletePublicDoc(segments);
32
30
  return;
33
31
  }
34
- ensurePrivateMutationAllowed(context);
35
32
  context.deletePrivateData(context.getOwningRootId($signal), segments);
36
33
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teamplay",
3
- "version": "0.5.0-alpha.21",
3
+ "version": "0.5.0-alpha.23",
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": "9a68b281123d93db5af433fc3e76c6e086b09ac5"
137
+ "gitHead": "b3dcd5e4b680a5a380fe68ce41f6da93b1deeb85"
138
138
  }