teamplay 0.5.0-alpha.21 → 0.5.0-alpha.22

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';
@@ -928,8 +927,6 @@ async function setReplaceOnSignal($signal, value) {
928
927
  }
929
928
  return result;
930
929
  }
931
- if (isPrivateMutationForbidden())
932
- throw Error(ERRORS.publicOnly);
933
930
  const result = setReplacePrivateData(getOwningRootId($signal), segments, value);
934
931
  if (shouldMirrorPrivateRefMutationLocally()) {
935
932
  mirrorRefMutationFromTarget(segments, value);
@@ -956,8 +953,6 @@ async function incrementOnSignal($signal, byNumber) {
956
953
  await _incrementPublic(segments, byNumber);
957
954
  return currentValue + byNumber;
958
955
  }
959
- if (isPrivateMutationForbidden())
960
- throw Error(ERRORS.publicOnly);
961
956
  setReplacePrivateData(getOwningRootId($signal), segments, currentValue + byNumber);
962
957
  return currentValue + byNumber;
963
958
  }
@@ -993,8 +988,6 @@ async function arrayPushOnSignal($signal, value) {
993
988
  return;
994
989
  if (isPublicCollection(segments[0]))
995
990
  return _arrayPushPublic(segments, value);
996
- if (isPrivateMutationForbidden())
997
- throw Error(ERRORS.publicOnly);
998
991
  return arrayPushPrivateData(getOwningRootId($signal), segments, value);
999
992
  }
1000
993
  async function arrayUnshiftOnSignal($signal, value) {
@@ -1004,8 +997,6 @@ async function arrayUnshiftOnSignal($signal, value) {
1004
997
  return;
1005
998
  if (isPublicCollection(segments[0]))
1006
999
  return _arrayUnshiftPublic(segments, value);
1007
- if (isPrivateMutationForbidden())
1008
- throw Error(ERRORS.publicOnly);
1009
1000
  return arrayUnshiftPrivateData(getOwningRootId($signal), segments, value);
1010
1001
  }
1011
1002
  async function arrayInsertOnSignal($signal, index, values) {
@@ -1015,8 +1006,6 @@ async function arrayInsertOnSignal($signal, index, values) {
1015
1006
  return;
1016
1007
  if (isPublicCollection(segments[0]))
1017
1008
  return _arrayInsertPublic(segments, index, values);
1018
- if (isPrivateMutationForbidden())
1019
- throw Error(ERRORS.publicOnly);
1020
1009
  return arrayInsertPrivateData(getOwningRootId($signal), segments, index, values);
1021
1010
  }
1022
1011
  async function arrayPopOnSignal($signal) {
@@ -1026,8 +1015,6 @@ async function arrayPopOnSignal($signal) {
1026
1015
  return;
1027
1016
  if (isPublicCollection(segments[0]))
1028
1017
  return _arrayPopPublic(segments);
1029
- if (isPrivateMutationForbidden())
1030
- throw Error(ERRORS.publicOnly);
1031
1018
  return arrayPopPrivateData(getOwningRootId($signal), segments);
1032
1019
  }
1033
1020
  async function arrayShiftOnSignal($signal) {
@@ -1037,8 +1024,6 @@ async function arrayShiftOnSignal($signal) {
1037
1024
  return;
1038
1025
  if (isPublicCollection(segments[0]))
1039
1026
  return _arrayShiftPublic(segments);
1040
- if (isPrivateMutationForbidden())
1041
- throw Error(ERRORS.publicOnly);
1042
1027
  return arrayShiftPrivateData(getOwningRootId($signal), segments);
1043
1028
  }
1044
1029
  async function arrayRemoveOnSignal($signal, index, howMany) {
@@ -1048,8 +1033,6 @@ async function arrayRemoveOnSignal($signal, index, howMany) {
1048
1033
  return;
1049
1034
  if (isPublicCollection(segments[0]))
1050
1035
  return _arrayRemovePublic(segments, index, howMany);
1051
- if (isPrivateMutationForbidden())
1052
- throw Error(ERRORS.publicOnly);
1053
1036
  return arrayRemovePrivateData(getOwningRootId($signal), segments, index, howMany);
1054
1037
  }
1055
1038
  async function arrayMoveOnSignal($signal, from, to, howMany) {
@@ -1059,8 +1042,6 @@ async function arrayMoveOnSignal($signal, from, to, howMany) {
1059
1042
  return;
1060
1043
  if (isPublicCollection(segments[0]))
1061
1044
  return _arrayMovePublic(segments, from, to, howMany);
1062
- if (isPrivateMutationForbidden())
1063
- throw Error(ERRORS.publicOnly);
1064
1045
  return arrayMovePrivateData(getOwningRootId($signal), segments, from, to, howMany);
1065
1046
  }
1066
1047
  async function stringInsertOnSignal($signal, index, text) {
@@ -1070,8 +1051,6 @@ async function stringInsertOnSignal($signal, index, text) {
1070
1051
  return;
1071
1052
  if (isPublicCollection(segments[0]))
1072
1053
  return _stringInsertPublic(segments, index, text);
1073
- if (isPrivateMutationForbidden())
1074
- throw Error(ERRORS.publicOnly);
1075
1054
  return stringInsertPrivateData(getOwningRootId($signal), segments, index, text);
1076
1055
  }
1077
1056
  async function stringRemoveOnSignal($signal, index, howMany) {
@@ -1081,8 +1060,6 @@ async function stringRemoveOnSignal($signal, index, howMany) {
1081
1060
  return;
1082
1061
  if (isPublicCollection(segments[0]))
1083
1062
  return _stringRemovePublic(segments, index, howMany);
1084
- if (isPrivateMutationForbidden())
1085
- throw Error(ERRORS.publicOnly);
1086
1063
  return stringRemovePrivateData(getOwningRootId($signal), segments, index, howMany);
1087
1064
  }
1088
1065
  function getOwningRootId($signal) {
@@ -1264,11 +1241,5 @@ function racerDeepCopy(value) {
1264
1241
  }
1265
1242
  return value;
1266
1243
  }
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
1244
  export { SignalCompat };
1274
1245
  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.22",
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": "9d05517747e59a37bc34e7579d3637efff9c1d69"
138
138
  }