teamplay 0.5.0-alpha.35 → 0.5.0-alpha.36

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/dist/index.d.ts CHANGED
@@ -62,7 +62,7 @@ export { emit, useOn, useEmit } from './orm/events.js';
62
62
  export { default as reaction } from './orm/reaction.js';
63
63
  export type { ReactionHandle, ReactionOptions } from './orm/reaction.js';
64
64
  export { useDidUpdate, useOnce, useSyncEffect } from './react/helpers.js';
65
- export { connection, setConnection, getConnection, getDefaultFetchOnly, setDefaultFetchOnly, publicOnly, setPublicOnly } from './orm/connection.js';
65
+ export { connection, setConnection, getConnection, getDefaultFetchOnly, setDefaultFetchOnly } from './orm/connection.js';
66
66
  export type { TeamplayConnection, TeamplayShareDoc } from './orm/connection.js';
67
67
  export { TEAMPLAY_RUNTIME_CONFIG_SYMBOL, configureTeamplay, getTeamplayConfig, getDefaultIdFields, setDefaultIdFields } from './config.js';
68
68
  export type { IdField, IdFields, TeamplayRuntimeConfig } from './config.js';
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ export const observer = runtimeObserver;
21
21
  export { emit, useOn, useEmit } from './orm/events.js';
22
22
  export { default as reaction } from "./orm/reaction.js";
23
23
  export { useDidUpdate, useOnce, useSyncEffect } from "./react/helpers.js";
24
- export { connection, setConnection, getConnection, getDefaultFetchOnly, setDefaultFetchOnly, publicOnly, setPublicOnly } from "./orm/connection.js";
24
+ export { connection, setConnection, getConnection, getDefaultFetchOnly, setDefaultFetchOnly } from "./orm/connection.js";
25
25
  export { TEAMPLAY_RUNTIME_CONFIG_SYMBOL, configureTeamplay, getTeamplayConfig, getDefaultIdFields, setDefaultIdFields } from "./config.js";
26
26
  export { getSubscriptionGcDelay, setSubscriptionGcDelay } from "./orm/subscriptionGcDelay.js";
27
27
  export { useId, useNow, useScheduleUpdate, useTriggerUpdate } from "./react/helpers.js";
@@ -1,14 +1,12 @@
1
1
  import { raw } from '@nx-js/observer-util';
2
2
  import arrayDiff from 'arraydiff';
3
- import { Signal, GETTERS, DEFAULT_GETTERS, SEGMENTS, isPublicCollection, isPublicCollectionSignal, isPublicDocumentSignal } from "../SignalBase.js";
3
+ import { Signal, GETTERS, DEFAULT_GETTERS, SEGMENTS, isPublicCollection } from "../SignalBase.js";
4
4
  import { getRoot, ROOT, ROOT_ID } from "../Root.js";
5
- import { docSubscriptions } from '../Doc.js';
6
- import { IS_QUERY, querySubscriptions } from '../Query.js';
7
- import { AGGREGATIONS, IS_AGGREGATION, aggregationSubscriptions } from '../Aggregation.js';
5
+ import { IS_QUERY } from '../Query.js';
6
+ import { AGGREGATIONS, IS_AGGREGATION } from '../Aggregation.js';
8
7
  import { getIdFieldsForSegments, isIdFieldPath, isPublicDocPath, normalizeIdFields, isPlainObject } from "../idFields.js";
9
8
  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
9
  import { on as onCustomEvent, removeListener as removeCustomEventListener } from '../events.js';
11
- import { waitForImperativeQueryReady } from '../queryReadiness.js';
12
10
  import { runInBatch } from '../batchScheduler.js';
13
11
  import { arrayInsertPrivateData, arrayMovePrivateData, arrayPopPrivateData, arrayPushPrivateData, arrayRemovePrivateData, arrayShiftPrivateData, arrayUnshiftPrivateData, delPrivateData, setReplacePrivateData, stringInsertPrivateData, stringRemovePrivateData } from '../privateData.js';
14
12
  class SignalCompat extends Signal {
@@ -36,16 +34,6 @@ class SignalCompat extends Signal {
36
34
  throw Error('Signal.getDeepCopy() does not accept any arguments');
37
35
  return deepCopy(this.get());
38
36
  }
39
- fetch(...items) {
40
- if (items.length > 0)
41
- return subscribeMany(items, 'subscribe', 'fetch', 'fetch');
42
- return subscribeSelf(this, 'fetch', 'fetch');
43
- }
44
- unfetch(...items) {
45
- if (items.length > 0)
46
- return subscribeMany(items, 'unsubscribe', 'fetch', 'unfetch');
47
- return unsubscribeSelf(this, 'fetch', 'unfetch');
48
- }
49
37
  getExtra() {
50
38
  if (arguments.length > 0)
51
39
  throw Error('Signal.getExtra() does not accept any arguments');
@@ -68,9 +56,7 @@ class SignalCompat extends Signal {
68
56
  async set(value) {
69
57
  if (arguments.length > 1)
70
58
  throw Error('Signal.set() expects a single argument');
71
- if (value === undefined)
72
- return Signal.prototype.set.call(this, value);
73
- return setReplaceOnSignal(this, value);
59
+ return Signal.prototype.set.call(this, value);
74
60
  }
75
61
  async setReplace(value) {
76
62
  if (arguments.length > 1)
@@ -621,75 +607,6 @@ function deepCopy(value) {
621
607
  }
622
608
  return racerDeepCopy(rawValue);
623
609
  }
624
- function subscribeMany(items, action, intent = 'subscribe', methodName = action) {
625
- const targets = flattenItems(items);
626
- const promises = [];
627
- for (const target of targets) {
628
- if (!target)
629
- continue;
630
- if (!(target instanceof Signal)) {
631
- throw Error(`Signal.${methodName}() accepts only Signal instances. Got: ${target}`);
632
- }
633
- const result = action === 'subscribe'
634
- ? subscribeSelf(target, intent, methodName)
635
- : unsubscribeSelf(target, intent, methodName);
636
- if (result?.then)
637
- promises.push(result);
638
- }
639
- if (promises.length)
640
- return Promise.all(promises);
641
- }
642
- function flattenItems(items, result = []) {
643
- for (const item of items) {
644
- if (!item)
645
- continue;
646
- if (Array.isArray(item)) {
647
- flattenItems(item, result);
648
- }
649
- else {
650
- result.push(item);
651
- }
652
- }
653
- return result;
654
- }
655
- function subscribeSelf($signal, intent = 'subscribe', methodName = 'subscribe') {
656
- if ($signal[IS_QUERY]) {
657
- return (async () => {
658
- await querySubscriptions.subscribe($signal, { intent });
659
- await waitForImperativeQueryReady($signal);
660
- })();
661
- }
662
- if ($signal[IS_AGGREGATION]) {
663
- return (async () => {
664
- await aggregationSubscriptions.subscribe($signal, { intent });
665
- await waitForImperativeQueryReady($signal);
666
- })();
667
- }
668
- if (isPublicDocumentSignal($signal))
669
- return docSubscriptions.subscribe($signal, { intent });
670
- if (isPublicCollectionSignal($signal)) {
671
- throw Error(`Signal.${methodName}() expects a document or query signal. Use sub($collection, params, { mode: 'fetch' }) for collection fetches.`);
672
- }
673
- if ($signal[SEGMENTS].length === 0) {
674
- throw Error(`Signal.${methodName}() cannot be called on the root signal`);
675
- }
676
- throw Error(`Signal.${methodName}() expects a document or query signal`);
677
- }
678
- function unsubscribeSelf($signal, intent = 'subscribe', methodName = 'unsubscribe') {
679
- if ($signal[IS_QUERY])
680
- return querySubscriptions.unsubscribe($signal, { intent });
681
- if ($signal[IS_AGGREGATION])
682
- return aggregationSubscriptions.unsubscribe($signal, { intent });
683
- if (isPublicDocumentSignal($signal))
684
- return docSubscriptions.unsubscribe($signal, { intent });
685
- if (isPublicCollectionSignal($signal)) {
686
- throw Error(`Signal.${methodName}() expects a document or query signal`);
687
- }
688
- if ($signal[SEGMENTS].length === 0) {
689
- throw Error(`Signal.${methodName}() cannot be called on the root signal`);
690
- }
691
- throw Error(`Signal.${methodName}() expects a document or query signal`);
692
- }
693
610
  // Racer-style deep copy:
694
611
  // - Preserves prototypes by instantiating via `new value.constructor()`
695
612
  // - Copies own enumerable props recursively
package/dist/orm/Doc.js CHANGED
@@ -5,50 +5,12 @@ import { getConnection } from "./connection.js";
5
5
  import FinalizationRegistry from "../utils/MockFinalizationRegistry.js";
6
6
  import SubscriptionState from './SubscriptionState.js';
7
7
  import { getIdFieldsForSegments, injectIdFields, isPlainObject } from "./idFields.js";
8
- import { emitModelChange, isModelEventsEnabled } from './Compat/modelEvents.js';
9
8
  import { getSubscriptionGcDelay } from "./subscriptionGcDelay.js";
10
9
  import { isMissingShareDoc } from './missingDoc.js';
11
10
  import { getRoot, ROOT_ID, GLOBAL_ROOT_ID, getRootTransportMode } from "./Root.js";
12
11
  import { registerRootOwnedDirectDocSubscription, unregisterRootOwnedDirectDocSubscription, getRootOwnedDirectDocSubscriptions, clearRootOwnedDirectDocSubscriptions } from "./rootContext.js";
13
12
  const ERROR_ON_EXCESSIVE_UNSUBSCRIBES = false;
14
13
  const DOC_FINALIZATION_TOKENS = new WeakMap();
15
- const RECENT_DOC_OP_CONTEXT_TTL = 100;
16
- const ACTIVE_DOC_OP_CONTEXTS = [];
17
- let recentDocOpContext;
18
- export function getActiveDocOpContext() {
19
- return ACTIVE_DOC_OP_CONTEXTS[ACTIVE_DOC_OP_CONTEXTS.length - 1] || recentDocOpContext;
20
- }
21
- function pushActiveDocOpContext(collection, docId, source) {
22
- const context = { collection, docId, source };
23
- ACTIVE_DOC_OP_CONTEXTS.push(context);
24
- recentDocOpContext = context;
25
- }
26
- function popActiveDocOpContext(collection, docId, source) {
27
- const current = ACTIVE_DOC_OP_CONTEXTS[ACTIVE_DOC_OP_CONTEXTS.length - 1];
28
- if (current?.collection === collection && current?.docId === docId && current?.source === source) {
29
- ACTIVE_DOC_OP_CONTEXTS.pop();
30
- clearRecentDocOpContext(current);
31
- return;
32
- }
33
- let index = -1;
34
- for (let i = ACTIVE_DOC_OP_CONTEXTS.length - 1; i >= 0; i--) {
35
- const context = ACTIVE_DOC_OP_CONTEXTS[i];
36
- if (context.collection === collection && context.docId === docId && context.source === source) {
37
- index = i;
38
- break;
39
- }
40
- }
41
- if (index === -1)
42
- return;
43
- const [context] = ACTIVE_DOC_OP_CONTEXTS.splice(index, 1);
44
- clearRecentDocOpContext(context);
45
- }
46
- function clearRecentDocOpContext(context) {
47
- setTimeout(() => {
48
- if (recentDocOpContext === context)
49
- recentDocOpContext = undefined;
50
- }, RECENT_DOC_OP_CONTEXT_TTL);
51
- }
52
14
  function getDocFinalizationToken($doc) {
53
15
  let token = DOC_FINALIZATION_TOKENS.get($doc);
54
16
  if (!token) {
@@ -185,17 +147,6 @@ class Doc {
185
147
  doc.on('load', () => this._refData());
186
148
  doc.on('create', () => this._refData());
187
149
  doc.on('del', () => this._refMissingData());
188
- if (isModelEventsEnabled()) {
189
- doc.on('before op', (_op, source) => pushActiveDocOpContext(this.collection, this.docId, source));
190
- doc.on('op', (op, source) => {
191
- try {
192
- emitDocOp(this.collection, this.docId, op, source);
193
- }
194
- finally {
195
- popActiveDocOpContext(this.collection, this.docId, source);
196
- }
197
- });
198
- }
199
150
  }
200
151
  _refMissingData() {
201
152
  _del([this.collection, this.docId]);
@@ -915,57 +866,6 @@ function createPendingDestroyEntry() {
915
866
  reject: rejectPending
916
867
  };
917
868
  }
918
- function emitDocOp(collection, docId, op, source) {
919
- if (!isModelEventsEnabled())
920
- return;
921
- const ops = Array.isArray(op) ? op : [op];
922
- for (const component of ops) {
923
- if (!component || !component.p)
924
- continue;
925
- const baseSegments = [collection, docId];
926
- let pathSegments = baseSegments.concat(component.p);
927
- const meta = { source };
928
- let value;
929
- let prevValue;
930
- if (has(component, 'si') || has(component, 'sd')) {
931
- const index = component.p[component.p.length - 1];
932
- meta.op = has(component, 'si') ? 'stringInsert' : 'stringRemove';
933
- meta.index = index;
934
- pathSegments = baseSegments.concat(component.p.slice(0, -1));
935
- value = _getRaw(pathSegments);
936
- prevValue = component.sd;
937
- }
938
- else if (has(component, 'lm')) {
939
- meta.op = 'arrayMove';
940
- meta.from = component.p[component.p.length - 1];
941
- meta.to = component.lm;
942
- pathSegments = baseSegments.concat(component.p.slice(0, -1));
943
- value = _getRaw(pathSegments);
944
- }
945
- else if (has(component, 'li') || has(component, 'ld')) {
946
- meta.op = has(component, 'li') ? 'arrayInsert' : 'arrayRemove';
947
- meta.index = component.p[component.p.length - 1];
948
- value = _getRaw(pathSegments);
949
- prevValue = component.ld;
950
- }
951
- else if (has(component, 'na')) {
952
- meta.op = 'increment';
953
- meta.by = component.na;
954
- value = _getRaw(pathSegments);
955
- if (typeof value === 'number')
956
- prevValue = value - component.na;
957
- }
958
- else {
959
- meta.op = 'set';
960
- value = has(component, 'oi') ? component.oi : _getRaw(pathSegments);
961
- prevValue = component.od;
962
- }
963
- emitModelChange(pathSegments, value, prevValue, meta);
964
- }
965
- }
966
- function has(obj, key) {
967
- return Object.prototype.hasOwnProperty.call(obj, key);
968
- }
969
869
  const ERRORS = {
970
870
  notSubscribed: $doc => Error('trying to unsubscribe when not subscribed. Doc: ' + $doc.path())
971
871
  };
package/dist/orm/Query.js CHANGED
@@ -2,7 +2,6 @@ import { raw } from '@nx-js/observer-util';
2
2
  import { set as _set, getRaw } from './dataTree.js';
3
3
  import getSignal from "./getSignal.js";
4
4
  import { getConnection } from "./connection.js";
5
- import { emitModelChange, isModelEventsEnabled } from './Compat/modelEvents.js';
6
5
  import { isCompatEnv } from './compatEnv.js';
7
6
  import { docSubscriptions } from './Doc.js';
8
7
  import FinalizationRegistry from "../utils/MockFinalizationRegistry.js";
@@ -127,22 +126,6 @@ export class Query {
127
126
  return;
128
127
  docs.splice(index, 0, ...newDocs);
129
128
  idsState.splice(index, 0, ...ids);
130
- if (!isModelEventsEnabled())
131
- return;
132
- const docsPath = [QUERIES, this.hash, 'docs'];
133
- const idsPath = [QUERIES, this.hash, 'ids'];
134
- for (let i = 0; i < newDocs.length; i++) {
135
- emitModelChange(rootId, docsPath.concat(index + i), newDocs[i], undefined, {
136
- op: 'queryInsert',
137
- index: index + i
138
- });
139
- }
140
- for (let i = 0; i < ids.length; i++) {
141
- emitModelChange(rootId, idsPath.concat(index + i), ids[i], undefined, {
142
- op: 'queryInsert',
143
- index: index + i
144
- });
145
- }
146
129
  });
147
130
  });
148
131
  this.shareQuery.on('move', (shareDocs, from, to) => {
@@ -153,26 +136,10 @@ export class Query {
153
136
  const ids = getPrivateData(rootId, [QUERIES, this.hash, 'ids']);
154
137
  if (!Array.isArray(docs) || !Array.isArray(ids))
155
138
  return;
156
- const prevDocs = isModelEventsEnabled() ? docs.slice() : undefined;
157
139
  docs.splice(from, shareDocs.length);
158
140
  docs.splice(to, 0, ...movedDocs);
159
- const prevIds = isModelEventsEnabled() ? ids.slice() : undefined;
160
141
  ids.splice(from, shareDocs.length);
161
142
  ids.splice(to, 0, ...movedIds);
162
- if (!isModelEventsEnabled())
163
- return;
164
- emitModelChange(rootId, [QUERIES, this.hash, 'docs'], docs, prevDocs, {
165
- op: 'queryMove',
166
- from,
167
- to,
168
- howMany: shareDocs.length
169
- });
170
- emitModelChange(rootId, [QUERIES, this.hash, 'ids'], ids, prevIds, {
171
- op: 'queryMove',
172
- from,
173
- to,
174
- howMany: shareDocs.length
175
- });
176
143
  });
177
144
  });
178
145
  this.shareQuery.on('remove', (shareDocs, index) => {
@@ -187,26 +154,8 @@ export class Query {
187
154
  const ids = getPrivateData(rootId, [QUERIES, this.hash, 'ids']);
188
155
  if (!Array.isArray(docs) || !Array.isArray(ids))
189
156
  return;
190
- const removedDocs = isModelEventsEnabled() ? docs.slice(index, index + shareDocs.length) : undefined;
191
157
  docs.splice(index, shareDocs.length);
192
- const removedIds = isModelEventsEnabled() ? ids.slice(index, index + docIds.length) : undefined;
193
158
  ids.splice(index, docIds.length);
194
- if (!isModelEventsEnabled())
195
- return;
196
- const docsPath = [QUERIES, this.hash, 'docs'];
197
- const idsPath = [QUERIES, this.hash, 'ids'];
198
- for (let i = 0; i < removedDocs.length; i++) {
199
- emitModelChange(rootId, docsPath.concat(index + i), undefined, removedDocs[i], {
200
- op: 'queryRemove',
201
- index: index + i
202
- });
203
- }
204
- for (let i = 0; i < removedIds.length; i++) {
205
- emitModelChange(rootId, idsPath.concat(index + i), undefined, removedIds[i], {
206
- op: 'queryRemove',
207
- index: index + i
208
- });
209
- }
210
159
  });
211
160
  });
212
161
  this.shareQuery.on('extra', extra => {
@@ -778,8 +778,7 @@ export const regularBindings = {
778
778
  return Reflect.apply(extremelyLateBindings.get, this, arguments);
779
779
  }
780
780
  };
781
- const QUERY_METHODS = ['map', 'reduce', 'find', 'get', 'getIds', 'getExtra', 'fetch', 'unfetch'];
782
- const AGGREGATION_ALLOWED_METHODS = ['fetch', 'unfetch'];
781
+ const QUERY_METHODS = ['map', 'reduce', 'find', 'get', 'getIds', 'getExtra'];
783
782
  // dot syntax always returns a child signal even if such method or property exists.
784
783
  // The method is only called when the signal is explicitly called as a function,
785
784
  // in which case we get the original method from the raw (non-proxied) parent signal
@@ -824,7 +823,7 @@ export const extremelyLateBindings = {
824
823
  });
825
824
  }
826
825
  }
827
- else if (!DEFAULT_GETTERS.includes(key) && !AGGREGATION_ALLOWED_METHODS.includes(key)) {
826
+ else if (!DEFAULT_GETTERS.includes(key)) {
828
827
  throw Error(ERRORS.aggregationSetter(segments, key));
829
828
  }
830
829
  }
@@ -16,18 +16,7 @@ export interface TeamplayConnection {
16
16
  [key: string]: unknown;
17
17
  }
18
18
  export declare let connection: TeamplayConnection | undefined;
19
- /** @deprecated Root-scoped private data made the publicOnly write guard obsolete. */
20
- export declare const publicOnly = false;
21
19
  export declare function setConnection(_connection: TeamplayConnection | undefined): void;
22
20
  export declare function getConnection(): TeamplayConnection;
23
21
  export declare function setDefaultFetchOnly(_fetchOnly: boolean): void;
24
22
  export declare function getDefaultFetchOnly(): boolean;
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
- */
31
- export declare function setPublicOnly(_publicOnly: boolean): void;
32
- /** @deprecated publicOnly no longer blocks private writes. */
33
- export declare function isPrivateMutationForbidden(): boolean;
@@ -1,7 +1,5 @@
1
1
  export let connection;
2
2
  let defaultFetchOnly;
3
- /** @deprecated Root-scoped private data made the publicOnly write guard obsolete. */
4
- export const publicOnly = false;
5
3
  export function setConnection(_connection) {
6
4
  connection = _connection;
7
5
  }
@@ -16,21 +14,6 @@ export function setDefaultFetchOnly(_fetchOnly) {
16
14
  export function getDefaultFetchOnly() {
17
15
  return !!defaultFetchOnly;
18
16
  }
19
- // Deprecated alias kept for internal transition.
20
- export function setFetchOnly(_fetchOnly) {
21
- setDefaultFetchOnly(_fetchOnly);
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
- */
28
- export function setPublicOnly(_publicOnly) {
29
- }
30
- /** @deprecated publicOnly no longer blocks private writes. */
31
- export function isPrivateMutationForbidden() {
32
- return false;
33
- }
34
17
  const ERRORS = {
35
18
  notSet: `
36
19
  Connection is not set.
@@ -4,18 +4,18 @@ export function getLogicalRootSnapshot(rootId: any, tree?: {}): {
4
4
  };
5
5
  export function get(segments: any, tree?: {}): {};
6
6
  export function getRaw(segments: any): {};
7
- export function set(segments: any, value: any, tree: {} | undefined, eventContext: any): void;
8
- export function setReplace(segments: any, value: any, tree: {} | undefined, eventContext: any): void;
9
- export function del(segments: any, tree: {} | undefined, eventContext: any): void;
7
+ export function set(segments: any, value: any, tree?: {}): void;
8
+ export function setReplace(segments: any, value: any, tree?: {}): void;
9
+ export function del(segments: any, tree?: {}): void;
10
10
  export function setPublicDoc(segments: any, value: any, deleteValue?: boolean): Promise<any>;
11
11
  export function setPublicDocReplace(segments: any, value: any): Promise<any>;
12
- export function arrayPush(segments: any, value: any, tree: {} | undefined, eventContext: any): number;
13
- export function arrayUnshift(segments: any, value: any, tree: {} | undefined, eventContext: any): number;
14
- export function arrayInsert(segments: any, index: any, values: any, tree: {} | undefined, eventContext: any): number;
15
- export function arrayPop(segments: any, tree: {} | undefined, eventContext: any): any;
16
- export function arrayShift(segments: any, tree: {} | undefined, eventContext: any): any;
17
- export function arrayRemove(segments: any, index: any, howMany: number | undefined, tree: {} | undefined, eventContext: any): any[];
18
- export function arrayMove(segments: any, from: any, to: any, howMany: number | undefined, tree: {} | undefined, eventContext: any): any[];
12
+ export function arrayPush(segments: any, value: any, tree?: {}): number;
13
+ export function arrayUnshift(segments: any, value: any, tree?: {}): number;
14
+ export function arrayInsert(segments: any, index: any, values: any, tree?: {}): number;
15
+ export function arrayPop(segments: any, tree?: {}): any;
16
+ export function arrayShift(segments: any, tree?: {}): any;
17
+ export function arrayRemove(segments: any, index: any, howMany?: number, tree?: {}): any[];
18
+ export function arrayMove(segments: any, from: any, to: any, howMany?: number, tree?: {}): any[];
19
19
  export function incrementPublic(segments: any, byNumber: any): Promise<any>;
20
20
  export function arrayPushPublic(segments: any, value: any): Promise<any>;
21
21
  export function arrayUnshiftPublic(segments: any, value: any): Promise<any>;
@@ -24,8 +24,8 @@ export function arrayPopPublic(segments: any): Promise<any>;
24
24
  export function arrayShiftPublic(segments: any): Promise<any>;
25
25
  export function arrayRemovePublic(segments: any, index: any, howMany?: number): Promise<any>;
26
26
  export function arrayMovePublic(segments: any, from: any, to: any, howMany?: number): Promise<any>;
27
- export function stringInsertLocal(segments: any, index: any, text: any, tree: {} | undefined, eventContext: any): any;
28
- export function stringRemoveLocal(segments: any, index: any, howMany: any, tree: {} | undefined, eventContext: any): any;
27
+ export function stringInsertLocal(segments: any, index: any, text: any, tree?: {}): any;
28
+ export function stringRemoveLocal(segments: any, index: any, howMany: any, tree?: {}): any;
29
29
  export function stringInsertPublic(segments: any, index: any, text: any): Promise<any>;
30
30
  export function stringRemovePublic(segments: any, index: any, howMany: any): Promise<any>;
31
31
  export { isPrivateCollectionSegments } from "./rootScope.js";
@@ -4,8 +4,6 @@ import diffMatchPatch from 'diff-match-patch';
4
4
  import { getConnection } from "./connection.js";
5
5
  import setDiffDeep from '../utils/setDiffDeep.js';
6
6
  import { getIdFieldsForSegments, injectIdFields, stripIdFields, isPlainObject, isIdFieldPath } from "./idFields.js";
7
- import { emitModelChange, isModelEventsEnabled } from './Compat/modelEvents.js';
8
- import { isSilentContextActive } from './Compat/silentContext.js';
9
7
  import { isCompatEnv } from './compatEnv.js';
10
8
  import { isMissingShareDoc } from './missingDoc.js';
11
9
  import { getLogicalRootSnapshot as getLogicalRootSnapshotFromTree } from "./rootScope.js";
@@ -15,8 +13,6 @@ const ALLOW_PARTIAL_DOC_CREATION = false;
15
13
  export const dataTreeRaw = {};
16
14
  const dataTree = observable(dataTreeRaw);
17
15
  function getWritableTree(tree) {
18
- if (isSilentContextActive())
19
- return getTreeRaw(tree);
20
16
  return tree;
21
17
  }
22
18
  function getTreeRaw(tree) {
@@ -24,22 +20,6 @@ function getTreeRaw(tree) {
24
20
  return dataTreeRaw;
25
21
  return raw(tree) || tree;
26
22
  }
27
- function shouldEmitModelEvents(tree, eventContext) {
28
- return (tree === dataTree || eventContext?.rootId != null) &&
29
- isModelEventsEnabled() &&
30
- !isSilentContextActive();
31
- }
32
- function emitModelEvent(segments, prevValue, meta, tree = dataTree, eventContext) {
33
- if (!shouldEmitModelEvents(tree, eventContext))
34
- return;
35
- const treeRaw = getTreeRaw(tree);
36
- const value = get(segments, treeRaw);
37
- const logicalSegments = eventContext?.logicalSegments || segments;
38
- const modelEventMeta = eventContext?.rootId != null
39
- ? { ...meta, rootId: eventContext.rootId }
40
- : meta;
41
- emitModelChange(logicalSegments, value, prevValue, modelEventMeta);
42
- }
43
23
  export function resolveStorageSegments(rootId, logicalSegments) {
44
24
  return logicalSegments;
45
25
  }
@@ -59,10 +39,8 @@ export function get(segments, tree = dataTree) {
59
39
  export function getRaw(segments) {
60
40
  return get(segments, dataTreeRaw);
61
41
  }
62
- export function set(segments, value, tree = dataTree, eventContext) {
42
+ export function set(segments, value, tree = dataTree) {
63
43
  const writableTree = getWritableTree(tree);
64
- const shouldEmit = shouldEmitModelEvents(tree, eventContext);
65
- const prevValue = shouldEmit ? get(segments, getTreeRaw(tree)) : undefined;
66
44
  let dataNode = writableTree;
67
45
  let dataNodeRaw = getTreeRaw(writableTree);
68
46
  for (let i = 0; i < segments.length - 1; i++) {
@@ -87,7 +65,6 @@ export function set(segments, value, tree = dataTree, eventContext) {
87
65
  return;
88
66
  if (value == null || typeof value !== 'object') {
89
67
  dataNode[key] = value;
90
- emitModelEvent(segments, prevValue, { op: 'set' }, tree, eventContext);
91
68
  return;
92
69
  }
93
70
  // instead of just setting the new value `dataNode[key] = value` we want
@@ -97,7 +74,6 @@ export function set(segments, value, tree = dataTree, eventContext) {
97
74
  // (we just set it to this value)
98
75
  if (dataNode[key] !== newValue)
99
76
  dataNode[key] = newValue;
100
- emitModelEvent(segments, prevValue, { op: 'set' }, tree, eventContext);
101
77
  }
102
78
  function hasOwnDataKey(node, key) {
103
79
  if (node == null)
@@ -107,10 +83,8 @@ function hasOwnDataKey(node, key) {
107
83
  return Object.prototype.hasOwnProperty.call(node, key);
108
84
  }
109
85
  // Like set(), but always assigns the value without equality checks or delete-on-null behavior
110
- export function setReplace(segments, value, tree = dataTree, eventContext) {
86
+ export function setReplace(segments, value, tree = dataTree) {
111
87
  const writableTree = getWritableTree(tree);
112
- const shouldEmit = shouldEmitModelEvents(tree, eventContext);
113
- const prevValue = shouldEmit ? get(segments, getTreeRaw(tree)) : undefined;
114
88
  let dataNode = writableTree;
115
89
  for (let i = 0; i < segments.length - 1; i++) {
116
90
  const segment = segments[i];
@@ -127,12 +101,9 @@ export function setReplace(segments, value, tree = dataTree, eventContext) {
127
101
  }
128
102
  const key = segments[segments.length - 1];
129
103
  dataNode[key] = value;
130
- emitModelEvent(segments, prevValue, { op: 'setReplace' }, tree, eventContext);
131
104
  }
132
- export function del(segments, tree = dataTree, eventContext) {
105
+ export function del(segments, tree = dataTree) {
133
106
  const writableTree = getWritableTree(tree);
134
- const shouldEmit = shouldEmitModelEvents(tree, eventContext);
135
- const prevValue = shouldEmit ? get(segments, getTreeRaw(tree)) : undefined;
136
107
  let dataNode = writableTree;
137
108
  for (let i = 0; i < segments.length - 1; i++) {
138
109
  const segment = segments[i];
@@ -154,7 +125,6 @@ export function del(segments, tree = dataTree, eventContext) {
154
125
  return;
155
126
  delete dataNode[key];
156
127
  }
157
- emitModelEvent(segments, prevValue, { op: 'del' }, tree, eventContext);
158
128
  }
159
129
  export async function setPublicDoc(segments, value, deleteValue = false) {
160
130
  if (segments.length === 0)
@@ -506,56 +476,38 @@ function getArrayNode(segments, tree = dataTree, create = true) {
506
476
  }
507
477
  return dataNode;
508
478
  }
509
- export function arrayPush(segments, value, tree = dataTree, eventContext) {
479
+ export function arrayPush(segments, value, tree = dataTree) {
510
480
  const arr = getArrayNode(segments, tree, true);
511
- const index = arr.length;
512
- const result = arr.push(value);
513
- emitModelEvent(segments.concat(index), undefined, { op: 'arrayPush', index }, tree, eventContext);
514
- return result;
481
+ return arr.push(value);
515
482
  }
516
- export function arrayUnshift(segments, value, tree = dataTree, eventContext) {
483
+ export function arrayUnshift(segments, value, tree = dataTree) {
517
484
  const arr = getArrayNode(segments, tree, true);
518
- const result = arr.unshift(value);
519
- emitModelEvent(segments.concat(0), undefined, { op: 'arrayUnshift', index: 0 }, tree, eventContext);
520
- return result;
485
+ return arr.unshift(value);
521
486
  }
522
- export function arrayInsert(segments, index, values, tree = dataTree, eventContext) {
487
+ export function arrayInsert(segments, index, values, tree = dataTree) {
523
488
  const arr = getArrayNode(segments, tree, true);
524
489
  const inserted = Array.isArray(values) ? values : [values];
525
490
  arr.splice(index, 0, ...inserted);
526
- for (let i = 0; i < inserted.length; i++) {
527
- emitModelEvent(segments.concat(index + i), undefined, { op: 'arrayInsert', index: index + i }, tree, eventContext);
528
- }
529
491
  return arr.length;
530
492
  }
531
- export function arrayPop(segments, tree = dataTree, eventContext) {
493
+ export function arrayPop(segments, tree = dataTree) {
532
494
  const arr = getArrayNode(segments, tree, true);
533
495
  if (!arr.length)
534
496
  return;
535
- const index = arr.length - 1;
536
- const previous = arr.pop();
537
- emitModelEvent(segments.concat(index), previous, { op: 'arrayPop', index }, tree, eventContext);
538
- return previous;
497
+ return arr.pop();
539
498
  }
540
- export function arrayShift(segments, tree = dataTree, eventContext) {
499
+ export function arrayShift(segments, tree = dataTree) {
541
500
  const arr = getArrayNode(segments, tree, true);
542
501
  if (!arr.length)
543
502
  return;
544
- const previous = arr.shift();
545
- emitModelEvent(segments.concat(0), previous, { op: 'arrayShift', index: 0 }, tree, eventContext);
546
- return previous;
503
+ return arr.shift();
547
504
  }
548
- export function arrayRemove(segments, index, howMany = 1, tree = dataTree, eventContext) {
505
+ export function arrayRemove(segments, index, howMany = 1, tree = dataTree) {
549
506
  const arr = getArrayNode(segments, tree, true);
550
- const removed = arr.splice(index, howMany);
551
- for (let i = 0; i < removed.length; i++) {
552
- emitModelEvent(segments.concat(index + i), removed[i], { op: 'arrayRemove', index: index + i, howMany }, tree, eventContext);
553
- }
554
- return removed;
507
+ return arr.splice(index, howMany);
555
508
  }
556
- export function arrayMove(segments, from, to, howMany = 1, tree = dataTree, eventContext) {
509
+ export function arrayMove(segments, from, to, howMany = 1, tree = dataTree) {
557
510
  const arr = getArrayNode(segments, tree, true);
558
- const prevValue = shouldEmitModelEvents(tree, eventContext) ? arr.slice() : undefined;
559
511
  const len = arr.length;
560
512
  if (from < 0)
561
513
  from += len;
@@ -563,7 +515,6 @@ export function arrayMove(segments, from, to, howMany = 1, tree = dataTree, even
563
515
  to += len;
564
516
  const moved = arr.splice(from, howMany);
565
517
  arr.splice(to, 0, ...moved);
566
- emitModelEvent(segments, prevValue, { op: 'arrayMove', from, to, howMany }, tree, eventContext);
567
518
  return moved;
568
519
  }
569
520
  export async function incrementPublic(segments, byNumber) {
@@ -732,7 +683,7 @@ export async function arrayMovePublic(segments, from, to, howMany = 1) {
732
683
  doc.submitOp(op, err => err ? reject(err) : resolve(moved));
733
684
  });
734
685
  }
735
- export function stringInsertLocal(segments, index, text, tree = dataTree, eventContext) {
686
+ export function stringInsertLocal(segments, index, text, tree = dataTree) {
736
687
  let dataNode = getWritableTree(tree);
737
688
  for (let i = 0; i < segments.length - 1; i++) {
738
689
  const segment = segments[i];
@@ -745,17 +696,15 @@ export function stringInsertLocal(segments, index, text, tree = dataTree, eventC
745
696
  const previous = dataNode[key];
746
697
  if (previous == null) {
747
698
  dataNode[key] = text;
748
- emitModelEvent(segments, previous, { op: 'stringInsert', index }, tree, eventContext);
749
699
  return previous;
750
700
  }
751
701
  if (typeof previous !== 'string') {
752
702
  throw Error(`Expected string at ${segments.join('.')}`);
753
703
  }
754
704
  dataNode[key] = previous.slice(0, index) + text + previous.slice(index);
755
- emitModelEvent(segments, previous, { op: 'stringInsert', index }, tree, eventContext);
756
705
  return previous;
757
706
  }
758
- export function stringRemoveLocal(segments, index, howMany, tree = dataTree, eventContext) {
707
+ export function stringRemoveLocal(segments, index, howMany, tree = dataTree) {
759
708
  let dataNode = getWritableTree(tree);
760
709
  for (let i = 0; i < segments.length - 1; i++) {
761
710
  const segment = segments[i];
@@ -771,7 +720,6 @@ export function stringRemoveLocal(segments, index, howMany, tree = dataTree, eve
771
720
  throw Error(`Expected string at ${segments.join('.')}`);
772
721
  }
773
722
  dataNode[key] = previous.slice(0, index) + previous.slice(index + howMany);
774
- emitModelEvent(segments, previous, { op: 'stringRemove', index, howMany }, tree, eventContext);
775
723
  return previous;
776
724
  }
777
725
  export async function stringInsertPublic(segments, index, text) {
@@ -27,7 +27,6 @@ async function runDispose(rootId) {
27
27
  const context = getRootContext(rootId, false);
28
28
  if (!context)
29
29
  return;
30
- context.resetModelListeners();
31
30
  for (const transportHash of Array.from(context.queryRuntimeHashes)) {
32
31
  await querySubscriptions.destroyByRuntimeHash(transportHash, { rootId, force: true });
33
32
  }
@@ -2,15 +2,9 @@ import type { PathSegment } from './types/path.js';
2
2
  type RootId = string | null | undefined;
3
3
  type DataTree = Record<string | number, unknown>;
4
4
  type RuntimeKind = 'query' | 'aggregation';
5
- type ModelEventStore = Map<string, unknown>;
6
5
  interface RootContextOptions {
7
6
  fetchOnly?: boolean;
8
7
  }
9
- interface ModelListeners {
10
- change: ModelEventStore;
11
- all: ModelEventStore;
12
- [eventName: string]: ModelEventStore;
13
- }
14
8
  export interface DirectDocSubscriptionEntry {
15
9
  segments: PathSegment[];
16
10
  count: number;
@@ -21,13 +15,11 @@ export default class RootContext {
21
15
  fetchOnly: boolean;
22
16
  privateDataRaw: DataTree;
23
17
  privateData: DataTree;
24
- readonly modelListeners: ModelListeners;
25
18
  readonly queryRuntimeHashes: Set<string>;
26
19
  readonly aggregationRuntimeHashes: Set<string>;
27
20
  readonly signalHashes: Set<string>;
28
21
  readonly directDocSubscriptions: Map<string, DirectDocSubscriptionEntry>;
29
22
  constructor(rootId: RootId, { fetchOnly }?: RootContextOptions);
30
- getModelEventStore(eventName: string, create?: boolean): ModelEventStore;
31
23
  getFetchOnly(): boolean;
32
24
  setFetchOnly(value: boolean): void;
33
25
  getPrivateDataRoot(): DataTree;
@@ -43,7 +35,6 @@ export default class RootContext {
43
35
  unregisterSignalHash(signalHash: string | null | undefined): void;
44
36
  registerDirectDocSubscription(hash: string | null | undefined, segments: readonly PathSegment[], token?: unknown): void;
45
37
  unregisterDirectDocSubscription(hash: string | null | undefined, token?: unknown): void;
46
- resetModelListeners(): void;
47
38
  resetRuntimeHashes(): void;
48
39
  resetPrivateData(): void;
49
40
  resetSignalHashes(): void;
@@ -12,10 +12,6 @@ export default class RootContext {
12
12
  fetchOnly;
13
13
  privateDataRaw;
14
14
  privateData;
15
- modelListeners = {
16
- change: new Map(),
17
- all: new Map()
18
- };
19
15
  queryRuntimeHashes = new Set();
20
16
  aggregationRuntimeHashes = new Set();
21
17
  signalHashes = new Set();
@@ -26,14 +22,6 @@ export default class RootContext {
26
22
  this.privateDataRaw = {};
27
23
  this.privateData = observable(this.privateDataRaw);
28
24
  }
29
- getModelEventStore(eventName, create = false) {
30
- let store = this.modelListeners[eventName];
31
- if (!store && create) {
32
- store = new Map();
33
- this.modelListeners[eventName] = store;
34
- }
35
- return store;
36
- }
37
25
  getFetchOnly() {
38
26
  return !!this.fetchOnly;
39
27
  }
@@ -122,11 +110,6 @@ export default class RootContext {
122
110
  if (entry.count === 0)
123
111
  this.directDocSubscriptions.delete(hash);
124
112
  }
125
- resetModelListeners() {
126
- for (const store of Object.values(this.modelListeners)) {
127
- store.clear();
128
- }
129
- }
130
113
  resetRuntimeHashes() {
131
114
  this.queryRuntimeHashes.clear();
132
115
  this.aggregationRuntimeHashes.clear();
@@ -143,7 +126,6 @@ export default class RootContext {
143
126
  }
144
127
  isRuntimeEmpty() {
145
128
  return (isPlainObjectEmpty(this.privateData) &&
146
- Object.values(this.modelListeners).every(store => store.size === 0) &&
147
129
  this.queryRuntimeHashes.size === 0 &&
148
130
  this.aggregationRuntimeHashes.size === 0 &&
149
131
  this.signalHashes.size === 0 &&
package/dist/server.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  export function createBackend(options?: {}): any;
2
- export function initConnection(backend: any, { fetchOnly, publicOnly, idFields, ...options }?: {
2
+ export function initConnection(backend: any, { fetchOnly, idFields, ...options }?: {
3
3
  fetchOnly?: boolean | undefined;
4
- publicOnly?: boolean | undefined;
5
4
  }): {
6
5
  middleware: (req: any, res: any, next: any) => Promise<any>;
7
6
  upgrade: (req: any, socket: any, upgradeHead: any) => Promise<void>;
package/dist/server.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import createChannel from '@teamplay/channel/server';
2
2
  import backendCreateBackend from '@teamplay/backend';
3
3
  import { getModels } from "./orm/initModels.js";
4
- import { connection, setConnection, setDefaultFetchOnly, setPublicOnly } from "./orm/connection.js";
4
+ import { connection, setConnection, setDefaultFetchOnly } from "./orm/connection.js";
5
5
  import { configureTeamplay } from "./config.js";
6
6
  export { default as ShareDB } from 'sharedb';
7
7
  export { mongo, mongoClient, createMongoIndex, redis, redlock, sqlite, getRedis, Redis, getRedisOptions, redisPrefix, generateRedisPrefix } from '@teamplay/backend';
@@ -17,7 +17,7 @@ export function createBackend(options = {}) {
17
17
  return backendCreateBackend(nextOptions);
18
18
  }
19
19
  export default createBackend;
20
- export function initConnection(backend, { fetchOnly = true, publicOnly = true, idFields, ...options } = {}) {
20
+ export function initConnection(backend, { fetchOnly = true, idFields, ...options } = {}) {
21
21
  if (!backend)
22
22
  throw Error('backend is required');
23
23
  if (connection)
@@ -26,6 +26,5 @@ export function initConnection(backend, { fetchOnly = true, publicOnly = true, i
26
26
  configureTeamplay({ idFields });
27
27
  setConnection(backend.connect());
28
28
  setDefaultFetchOnly(fetchOnly);
29
- setPublicOnly(publicOnly);
30
29
  return createChannel(backend, options);
31
30
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teamplay",
3
- "version": "0.5.0-alpha.35",
3
+ "version": "0.5.0-alpha.36",
4
4
  "description": "Full-stack signals ORM with multiplayer",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -138,5 +138,6 @@
138
138
  "<rootDir>/test_client/helpers"
139
139
  ]
140
140
  },
141
- "license": "MIT"
141
+ "license": "MIT",
142
+ "gitHead": "c83e516afe64e94e7703529d04aed73ac3b27bfa"
142
143
  }
@@ -1,6 +0,0 @@
1
- export function isModelEventsEnabled(): boolean;
2
- export function normalizePattern(pattern: any, methodName: any): string | null;
3
- export function onModelEvent(rootId: any, eventName: any, pattern: any, handler: any): any;
4
- export function removeModelListener(rootId: any, eventName: any, handler: any): void;
5
- export function emitModelChange(path: any, value: any, prevValue: any, meta: any): void;
6
- export function __resetModelEventsForTests(): void;
@@ -1,143 +0,0 @@
1
- import { isCompatEnv } from '../compatEnv.js';
2
- import { isSilentContextActive, isModelEventsSilentContextActive } from './silentContext.js';
3
- import { normalizeRootId } from "../rootScope.js";
4
- import { getRootContext, getRootContexts } from "../rootContext.js";
5
- const MODEL_EVENT_NAMES = ['change', 'all'];
6
- export function isModelEventsEnabled() {
7
- return isCompatEnv();
8
- }
9
- export function normalizePattern(pattern, methodName) {
10
- if (pattern && typeof pattern.path === 'function')
11
- pattern = pattern.path();
12
- if (pattern == null || typeof pattern !== 'string') {
13
- if (methodName)
14
- throw Error(`${methodName} expects a string path or a signal`);
15
- return null;
16
- }
17
- return pattern.split('.').filter(Boolean).join('.');
18
- }
19
- export function onModelEvent(rootId, eventName, pattern, handler) {
20
- if (typeof handler !== 'function')
21
- throw Error('Model event handler must be a function');
22
- if (!MODEL_EVENT_NAMES.includes(eventName))
23
- throw Error(`Unsupported model event: ${eventName}`);
24
- const store = getModelEventRootStore(eventName, rootId, true);
25
- const normalized = normalizePattern(pattern);
26
- let entry = store.get(normalized);
27
- if (!entry) {
28
- entry = {
29
- pattern: normalized,
30
- segments: splitPattern(normalized),
31
- handlers: new Set()
32
- };
33
- store.set(normalized, entry);
34
- }
35
- entry.handlers.add(handler);
36
- return handler;
37
- }
38
- export function removeModelListener(rootId, eventName, handler) {
39
- const store = getModelEventRootStore(eventName, rootId);
40
- if (!store)
41
- return;
42
- for (const [pattern, entry] of store) {
43
- entry.handlers.delete(handler);
44
- if (!entry.handlers.size)
45
- store.delete(pattern);
46
- }
47
- }
48
- export function emitModelChange(path, value, prevValue, meta) {
49
- if (!isModelEventsEnabled())
50
- return;
51
- if (isSilentContextActive() || isModelEventsSilentContextActive())
52
- return;
53
- const initialSegments = splitPath(path);
54
- const eventName = meta?.eventName || 'change';
55
- const rootIds = getTargetRootIds(meta?.rootId);
56
- for (const rootId of rootIds) {
57
- emitForEvent(rootId, 'change', initialSegments, value, prevValue, meta);
58
- emitForEvent(rootId, 'all', initialSegments, value, prevValue, meta, eventName);
59
- }
60
- }
61
- export function __resetModelEventsForTests() {
62
- for (const context of getRootContexts()) {
63
- context.resetModelListeners();
64
- }
65
- }
66
- function emitForEvent(rootId, eventName, pathSegments, value, prevValue, meta, resolvedEventName = eventName) {
67
- const store = getModelEventRootStore(eventName, rootId);
68
- if (!store || store.size === 0)
69
- return;
70
- for (const entry of store.values()) {
71
- const captures = matchPattern(entry.segments, pathSegments);
72
- if (!captures)
73
- continue;
74
- for (const handler of entry.handlers) {
75
- if (eventName === 'all') {
76
- handler(...captures, resolvedEventName, value, prevValue, meta);
77
- }
78
- else {
79
- handler(...captures, value, prevValue, meta);
80
- }
81
- }
82
- }
83
- }
84
- function splitPattern(pattern) {
85
- if (!pattern)
86
- return [];
87
- return pattern.split('.').filter(Boolean);
88
- }
89
- function getModelEventRootStore(eventName, rootId, create = false) {
90
- return getRootContext(normalizeRootId(rootId), create)?.getModelEventStore(eventName, create);
91
- }
92
- function getModelEventRootIds() {
93
- const rootIds = new Set();
94
- for (const context of getRootContexts()) {
95
- for (const store of Object.values(context.modelListeners)) {
96
- if (store.size)
97
- rootIds.add(context.rootId);
98
- }
99
- }
100
- return rootIds;
101
- }
102
- function getTargetRootIds(rootId) {
103
- if (rootId != null)
104
- return [normalizeRootId(rootId)];
105
- return getModelEventRootIds();
106
- }
107
- function splitPath(path) {
108
- if (Array.isArray(path))
109
- return path.map(segment => String(segment));
110
- if (!path)
111
- return [];
112
- return String(path).split('.').filter(Boolean);
113
- }
114
- function matchPattern(patternSegments, pathSegments) {
115
- function walk(patternIndex, pathIndex) {
116
- if (patternIndex === patternSegments.length) {
117
- return pathIndex === pathSegments.length ? [] : null;
118
- }
119
- const segment = patternSegments[patternIndex];
120
- if (segment === '**') {
121
- for (let i = pathIndex; i <= pathSegments.length; i++) {
122
- const rest = walk(patternIndex + 1, i);
123
- if (rest !== null) {
124
- const capture = pathSegments.slice(pathIndex, i).join('.');
125
- return [capture, ...rest];
126
- }
127
- }
128
- return null;
129
- }
130
- if (pathIndex >= pathSegments.length)
131
- return null;
132
- if (segment === '*') {
133
- const rest = walk(patternIndex + 1, pathIndex + 1);
134
- if (rest === null)
135
- return null;
136
- return [pathSegments[pathIndex], ...rest];
137
- }
138
- if (segment !== pathSegments[pathIndex])
139
- return null;
140
- return walk(patternIndex + 1, pathIndex + 1);
141
- }
142
- return walk(0, 0);
143
- }
@@ -1,4 +0,0 @@
1
- export function isSilentContextActive(): boolean;
2
- export function isModelEventsSilentContextActive(): boolean;
3
- export function runInModelEventsSilentContext(fn: any): any;
4
- export function __resetSilentContextForTests(): void;
@@ -1,19 +0,0 @@
1
- let modelEventsSilentDepth = 0;
2
- export function isSilentContextActive() {
3
- return false;
4
- }
5
- export function isModelEventsSilentContextActive() {
6
- return modelEventsSilentDepth > 0;
7
- }
8
- export function runInModelEventsSilentContext(fn) {
9
- modelEventsSilentDepth += 1;
10
- try {
11
- return fn();
12
- }
13
- finally {
14
- modelEventsSilentDepth -= 1;
15
- }
16
- }
17
- export function __resetSilentContextForTests() {
18
- modelEventsSilentDepth = 0;
19
- }