teamplay 0.5.0-alpha.9 → 0.5.0
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/README.md +3 -3
- package/dist/config.d.ts +2 -0
- package/dist/config.js +1 -0
- package/dist/connect/index.d.ts +1 -1
- package/dist/connect/index.js +6 -2
- package/dist/connect/offline/index.d.ts +1 -1
- package/dist/connect/offline/index.js +8 -4
- package/dist/connect/offline/react-native.d.ts +1 -1
- package/dist/connect/offline/web.d.ts +1 -1
- package/dist/connect/test.d.ts +1 -1
- package/dist/connect/test.js +5 -1
- package/dist/index.d.ts +9 -5
- package/dist/index.js +6 -5
- package/dist/orm/$.js +1 -1
- package/dist/orm/Aggregation.d.ts +5 -3
- package/dist/orm/Aggregation.js +39 -15
- package/dist/orm/Doc.js +0 -55
- package/dist/orm/Query.d.ts +1 -0
- package/dist/orm/Query.js +25 -82
- package/dist/orm/Root.d.ts +4 -0
- package/dist/orm/Root.js +16 -0
- package/dist/orm/Signal.d.ts +0 -2
- package/dist/orm/Signal.js +1 -4
- package/dist/orm/SignalBase.d.ts +21 -1
- package/dist/orm/SignalBase.js +259 -56
- package/dist/orm/batchScheduler.d.ts +7 -7
- package/dist/orm/connection.d.ts +0 -4
- package/dist/orm/connection.js +0 -12
- package/dist/orm/dataTree.d.ts +12 -12
- package/dist/orm/dataTree.js +55 -107
- package/dist/orm/disposeRootContext.js +0 -14
- package/dist/orm/events.d.ts +6 -0
- package/dist/orm/events.js +48 -0
- package/dist/orm/getSignal.d.ts +1 -1
- package/dist/orm/getSignal.js +4 -33
- package/dist/orm/idFields.d.ts +10 -1
- package/dist/orm/idFields.js +102 -14
- package/dist/orm/index.d.ts +2 -0
- package/dist/orm/index.js +1 -0
- package/dist/orm/initModels.js +1 -1
- package/dist/orm/privateData.d.ts +7 -22
- package/dist/orm/privateData.js +20 -1
- package/dist/orm/queryReadiness.d.ts +13 -0
- package/dist/orm/{Compat/queryReadiness.js → queryReadiness.js} +10 -10
- package/dist/orm/reaction.d.ts +11 -0
- package/dist/orm/reaction.js +47 -0
- package/dist/orm/rootContext.d.ts +0 -16
- package/dist/orm/rootContext.js +0 -28
- package/dist/orm/signalMetadata.js +3 -3
- package/dist/orm/signalReads.js +3 -9
- package/dist/orm/signalStorageMutations.d.ts +0 -2
- package/dist/orm/signalStorageMutations.js +0 -9
- package/dist/orm/signalSymbols.js +1 -1
- package/dist/orm/signalValueMutations.d.ts +1 -1
- package/dist/orm/signalValueMutations.js +0 -3
- package/dist/orm/sub.d.ts +12 -7
- package/dist/orm/sub.js +87 -30
- package/dist/orm/subscriptionGcDelay.js +2 -6
- package/dist/react/convertToObserver.js +1 -4
- package/dist/react/promiseBatcher.js +1 -1
- package/dist/react/renderAttemptDestroyer.d.ts +0 -8
- package/dist/react/renderAttemptDestroyer.js +2 -28
- package/dist/react/trapRender.js +3 -3
- package/dist/react/useSub.d.ts +86 -5
- package/dist/react/useSub.js +191 -32
- package/dist/react/useSuspendMemo.js +1 -5
- package/dist/server.d.ts +1 -2
- package/dist/server.js +5 -3
- package/package.json +15 -13
- package/dist/orm/Compat/SignalCompat.d.ts +0 -3
- package/dist/orm/Compat/SignalCompat.js +0 -1267
- package/dist/orm/Compat/eventsCompat.d.ts +0 -3
- package/dist/orm/Compat/eventsCompat.js +0 -73
- package/dist/orm/Compat/hooksCompat.d.ts +0 -33
- package/dist/orm/Compat/hooksCompat.js +0 -360
- package/dist/orm/Compat/modelEvents.d.ts +0 -6
- package/dist/orm/Compat/modelEvents.js +0 -228
- package/dist/orm/Compat/queryReadiness.d.ts +0 -5
- package/dist/orm/Compat/refFallback.d.ts +0 -13
- package/dist/orm/Compat/refFallback.js +0 -65
- package/dist/orm/Compat/refRegistry.d.ts +0 -6
- package/dist/orm/Compat/refRegistry.js +0 -54
- package/dist/orm/Compat/silentContext.d.ts +0 -5
- package/dist/orm/Compat/silentContext.js +0 -48
- package/dist/orm/Compat/startStopCompat.d.ts +0 -3
- package/dist/orm/Compat/startStopCompat.js +0 -217
- package/dist/orm/compatEnv.d.ts +0 -1
- package/dist/orm/compatEnv.js +0 -4
- package/dist/react/compatComponentRegistry.d.ts +0 -4
- package/dist/react/compatComponentRegistry.js +0 -19
- /package/dist/orm/{Reaction.d.ts → reactionSubscriptions.d.ts} +0 -0
- /package/dist/orm/{Reaction.js → reactionSubscriptions.js} +0 -0
package/README.md
CHANGED
|
@@ -13,16 +13,16 @@ Features:
|
|
|
13
13
|
|
|
14
14
|
> __*__ deep signals -- with support for objects and arrays\
|
|
15
15
|
> __**__ concurrent changes to the same data are auto-merged using [OT](https://en.wikipedia.org/wiki/Operational_transformation)\
|
|
16
|
-
> __***__ similar to Firebase but with your own MongoDB
|
|
16
|
+
> __***__ similar to Firebase but with your own MongoDB database
|
|
17
17
|
|
|
18
18
|
## Installation
|
|
19
19
|
|
|
20
20
|
For installation and documentation see [teamplay.dev](https://teamplay.dev)
|
|
21
21
|
|
|
22
|
-
## ORM
|
|
22
|
+
## ORM Helpers
|
|
23
23
|
|
|
24
24
|
For legacy Racer-style model mixins (for example versioning libraries which call
|
|
25
|
-
`getAssociations()`), use ORM
|
|
25
|
+
`getAssociations()`), use ORM helpers from the `teamplay/orm` subpath:
|
|
26
26
|
|
|
27
27
|
```js
|
|
28
28
|
import BaseModel, { hasMany, hasOne, belongsTo } from 'teamplay/orm'
|
package/dist/config.d.ts
ADDED
package/dist/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { TEAMPLAY_RUNTIME_CONFIG_SYMBOL, configureTeamplay, getTeamplayConfig, getDefaultIdFields, setDefaultIdFields } from "./orm/idFields.js";
|
package/dist/connect/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default function connect(options
|
|
1
|
+
export default function connect(options?: {}): void;
|
package/dist/connect/index.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import Socket from '@teamplay/channel';
|
|
2
2
|
import Connection from './sharedbConnection.cjs';
|
|
3
3
|
import { connection, setConnection } from "../orm/connection.js";
|
|
4
|
-
|
|
4
|
+
import { configureTeamplay } from "../config.js";
|
|
5
|
+
export default function connect(options = {}) {
|
|
6
|
+
const { idFields, ...socketOptions } = options || {};
|
|
7
|
+
if (idFields !== undefined)
|
|
8
|
+
configureTeamplay({ idFields });
|
|
5
9
|
if (connection)
|
|
6
10
|
return;
|
|
7
|
-
const socket = new Socket(
|
|
11
|
+
const socket = new Socket(socketOptions);
|
|
8
12
|
setConnection(new Connection(socket));
|
|
9
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export default function createConnectWithPersistence({ storage, createPubsub }?: {}): () => Promise<void>;
|
|
1
|
+
export default function createConnectWithPersistence({ storage, createPubsub }?: {}): (options?: {}) => Promise<void>;
|
|
@@ -3,21 +3,25 @@
|
|
|
3
3
|
import ShareDbMingo from '@startupjs/sharedb-mingo-memory';
|
|
4
4
|
import ShareBackend from 'sharedb';
|
|
5
5
|
import { connection, setConnection } from "../../orm/connection.js";
|
|
6
|
+
import { configureTeamplay } from "../../config.js";
|
|
6
7
|
const STORAGE_NAMESPACE = 'teamplay-offline';
|
|
7
8
|
const DOCS_PREFIX = `${STORAGE_NAMESPACE}:docs:`;
|
|
8
9
|
const LAST_OP_PREFIX = `${STORAGE_NAMESPACE}:last-op:`;
|
|
9
10
|
export default function createConnectWithPersistence({ storage, createPubsub } = {}) {
|
|
10
11
|
if (!storage)
|
|
11
12
|
throw new Error('[connect-offline] storage is required');
|
|
12
|
-
return async function connect() {
|
|
13
|
+
return async function connect(options = {}) {
|
|
14
|
+
const { idFields } = options || {};
|
|
15
|
+
if (idFields !== undefined)
|
|
16
|
+
configureTeamplay({ idFields });
|
|
13
17
|
if (connection)
|
|
14
18
|
return;
|
|
15
19
|
const db = new ShareDbMingo();
|
|
16
|
-
const
|
|
20
|
+
const backendOptions = { db };
|
|
17
21
|
const { pubsub } = (await init(db, storage, createPubsub)) || {};
|
|
18
22
|
if (pubsub)
|
|
19
|
-
|
|
20
|
-
const backend = new ShareBackend(
|
|
23
|
+
backendOptions.pubsub = pubsub;
|
|
24
|
+
const backend = new ShareBackend(backendOptions);
|
|
21
25
|
setConnection(backend.connect());
|
|
22
26
|
};
|
|
23
27
|
}
|
|
@@ -3,7 +3,7 @@ export namespace storage {
|
|
|
3
3
|
export { setItem };
|
|
4
4
|
export { iterate };
|
|
5
5
|
}
|
|
6
|
-
declare const _default: () => Promise<void>;
|
|
6
|
+
declare const _default: (options?: {}) => Promise<void>;
|
|
7
7
|
export default _default;
|
|
8
8
|
declare function getItem(key: any): Promise<any>;
|
|
9
9
|
declare function setItem(key: any, value: any): Promise<any>;
|
|
@@ -4,6 +4,6 @@ export namespace storage {
|
|
|
4
4
|
function setItem(key: any, value: any): Promise<any>;
|
|
5
5
|
function iterate(iterator: any): Promise<any>;
|
|
6
6
|
}
|
|
7
|
-
declare const _default: () => Promise<void>;
|
|
7
|
+
declare const _default: (options?: {}) => Promise<void>;
|
|
8
8
|
export default _default;
|
|
9
9
|
import SharedbCrosstabPubsub from '../lib/sharedb-crosstab-pubsub.cjs';
|
package/dist/connect/test.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default function connect(): void;
|
|
1
|
+
export default function connect(options?: {}): void;
|
package/dist/connect/test.js
CHANGED
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
import ShareDbMingo from '@startupjs/sharedb-mingo-memory';
|
|
5
5
|
import ShareBackend from 'sharedb';
|
|
6
6
|
import { connection, setConnection } from "../orm/connection.js";
|
|
7
|
-
|
|
7
|
+
import { configureTeamplay } from "../config.js";
|
|
8
|
+
export default function connect(options = {}) {
|
|
9
|
+
const { idFields } = options || {};
|
|
10
|
+
if (idFields !== undefined)
|
|
11
|
+
configureTeamplay({ idFields });
|
|
8
12
|
if (connection)
|
|
9
13
|
return;
|
|
10
14
|
const backend = new ShareBackend({ db: new ShareDbMingo() });
|
package/dist/index.d.ts
CHANGED
|
@@ -53,15 +53,19 @@ export { default as signal } from './orm/getSignal.js';
|
|
|
53
53
|
export { GLOBAL_ROOT_ID } from './orm/Root.js';
|
|
54
54
|
export declare const $: RootSignal;
|
|
55
55
|
export default $;
|
|
56
|
-
export { default as sub } from './orm/sub.js';
|
|
57
|
-
export {
|
|
56
|
+
export { default as sub, unsub } from './orm/sub.js';
|
|
57
|
+
export type { SubMode, SubOptions } from './orm/sub.js';
|
|
58
|
+
export { default as useSub, useAsyncSub, useBatchSub, setUseDeferredValue as __setUseDeferredValue, setDefaultDefer as __setDefaultDefer } from './react/useSub.js';
|
|
58
59
|
export { default as useSuspendMemo, useSuspendMemoByKey } from './react/useSuspendMemo.js';
|
|
59
60
|
export declare const observer: ObserverFunction;
|
|
60
|
-
export {
|
|
61
|
-
export {
|
|
61
|
+
export { emit, useOn, useEmit } from './orm/events.js';
|
|
62
|
+
export { default as reaction } from './orm/reaction.js';
|
|
63
|
+
export type { ReactionHandle, ReactionOptions } from './orm/reaction.js';
|
|
62
64
|
export { useDidUpdate, useOnce, useSyncEffect } from './react/helpers.js';
|
|
63
|
-
export { connection, setConnection, getConnection, getDefaultFetchOnly, setDefaultFetchOnly
|
|
65
|
+
export { connection, setConnection, getConnection, getDefaultFetchOnly, setDefaultFetchOnly } from './orm/connection.js';
|
|
64
66
|
export type { TeamplayConnection, TeamplayShareDoc } from './orm/connection.js';
|
|
67
|
+
export { TEAMPLAY_RUNTIME_CONFIG_SYMBOL, configureTeamplay, getTeamplayConfig, getDefaultIdFields, setDefaultIdFields } from './config.js';
|
|
68
|
+
export type { IdField, IdFields, TeamplayRuntimeConfig } from './config.js';
|
|
65
69
|
export { getSubscriptionGcDelay, setSubscriptionGcDelay } from './orm/subscriptionGcDelay.js';
|
|
66
70
|
export { useId, useNow, useScheduleUpdate, useTriggerUpdate } from './react/helpers.js';
|
|
67
71
|
export { GUID_PATTERN, defineSchema, hasMany, hasOne, hasManyFlags, belongsTo, pickFormFields } from '@teamplay/schema';
|
package/dist/index.js
CHANGED
|
@@ -14,14 +14,15 @@ export { GLOBAL_ROOT_ID } from "./orm/Root.js";
|
|
|
14
14
|
const getRuntimeRootSignal = _getRootSignal;
|
|
15
15
|
export const $ = getRuntimeRootSignal({ rootId: GLOBAL_ROOT_ID, rootFunction: universal$ });
|
|
16
16
|
export default $;
|
|
17
|
-
export { default as sub } from "./orm/sub.js";
|
|
18
|
-
export { default as useSub, useAsyncSub, setUseDeferredValue as __setUseDeferredValue, setDefaultDefer as __setDefaultDefer } from "./react/useSub.js";
|
|
17
|
+
export { default as sub, unsub } from "./orm/sub.js";
|
|
18
|
+
export { default as useSub, useAsyncSub, useBatchSub, setUseDeferredValue as __setUseDeferredValue, setDefaultDefer as __setDefaultDefer } from "./react/useSub.js";
|
|
19
19
|
export { default as useSuspendMemo, useSuspendMemoByKey } from "./react/useSuspendMemo.js";
|
|
20
20
|
export const observer = runtimeObserver;
|
|
21
|
-
export {
|
|
22
|
-
export {
|
|
21
|
+
export { emit, useOn, useEmit } from './orm/events.js';
|
|
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
|
|
24
|
+
export { connection, setConnection, getConnection, getDefaultFetchOnly, setDefaultFetchOnly } from "./orm/connection.js";
|
|
25
|
+
export { TEAMPLAY_RUNTIME_CONFIG_SYMBOL, configureTeamplay, getTeamplayConfig, getDefaultIdFields, setDefaultIdFields } from "./config.js";
|
|
25
26
|
export { getSubscriptionGcDelay, setSubscriptionGcDelay } from "./orm/subscriptionGcDelay.js";
|
|
26
27
|
export { useId, useNow, useScheduleUpdate, useTriggerUpdate } from "./react/helpers.js";
|
|
27
28
|
export { GUID_PATTERN, defineSchema, hasMany, hasOne, hasManyFlags, belongsTo, pickFormFields } from '@teamplay/schema';
|
package/dist/orm/$.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import getSignal from "./getSignal.js";
|
|
5
5
|
import Signal from "./Signal.js";
|
|
6
6
|
import { LOCAL, valueSubscriptions } from './Value.js';
|
|
7
|
-
import { reactionSubscriptions } from './
|
|
7
|
+
import { reactionSubscriptions } from './reactionSubscriptions.js';
|
|
8
8
|
export { LOCAL } from './Value.js';
|
|
9
9
|
let counter = 0;
|
|
10
10
|
function newIncrementalId() {
|
|
@@ -3,15 +3,17 @@ import type {
|
|
|
3
3
|
QuerySubscriptions,
|
|
4
4
|
QuerySignalOptions
|
|
5
5
|
} from './Query.js'
|
|
6
|
+
import type { PathSegment } from './types/path.js'
|
|
6
7
|
|
|
7
8
|
export const IS_AGGREGATION: unique symbol
|
|
8
9
|
export const AGGREGATIONS: '$aggregations'
|
|
9
10
|
export const aggregationSubscriptions: QuerySubscriptions
|
|
10
11
|
export function getAggregationSignal (collectionName: string, params: unknown, options?: QuerySignalOptions): Signal
|
|
11
12
|
export function isAggregationSignal ($signal: unknown): boolean | undefined
|
|
13
|
+
export function getAggregationRowId (row: unknown, collectionName?: string): string | undefined
|
|
12
14
|
export function getAggregationDocId (
|
|
13
|
-
segments: readonly
|
|
15
|
+
segments: readonly PathSegment[],
|
|
14
16
|
rootId?: string,
|
|
15
|
-
method?: (path:
|
|
17
|
+
method?: (path: PathSegment[]) => unknown
|
|
16
18
|
): string | undefined
|
|
17
|
-
export function getAggregationCollectionName (segments: readonly
|
|
19
|
+
export function getAggregationCollectionName (segments: readonly PathSegment[]): string | undefined
|
package/dist/orm/Aggregation.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { raw } from '@nx-js/observer-util';
|
|
2
2
|
import { getRaw } from './dataTree.js';
|
|
3
3
|
import getSignal from "./getSignal.js";
|
|
4
|
-
import { QuerySubscriptions, hashQuery, Query, HASH, PARAMS, COLLECTION_NAME, parseQueryHash } from './Query.js';
|
|
4
|
+
import { QuerySubscriptions, hashQuery, Query, cloneQueryParams, HASH, PARAMS, COLLECTION_NAME, parseQueryHash } from './Query.js';
|
|
5
5
|
import Signal, { SEGMENTS } from "./Signal.js";
|
|
6
6
|
import { getIdFieldsForSegments, isPlainObject } from "./idFields.js";
|
|
7
7
|
import { delPrivateData, getPrivateData, setPrivateData } from './privateData.js';
|
|
8
8
|
import { setSignalRuntimeDescriptor } from "./signalRuntimeDescriptor.js";
|
|
9
9
|
export const IS_AGGREGATION = Symbol('is aggregation signal');
|
|
10
10
|
export const AGGREGATIONS = '$aggregations';
|
|
11
|
+
const DEFAULT_AGGREGATION_ID_FIELDS = ['_id', 'id'];
|
|
11
12
|
class Aggregation extends Query {
|
|
12
13
|
_initData() {
|
|
13
14
|
this._syncAllRootsData();
|
|
@@ -39,21 +40,31 @@ aggregationSubscriptions.runtimeKind = 'aggregation';
|
|
|
39
40
|
function injectAggregationIds(extra, collectionName) {
|
|
40
41
|
if (!Array.isArray(extra))
|
|
41
42
|
return;
|
|
42
|
-
const idFields =
|
|
43
|
+
const idFields = getCollectionIdFields(collectionName);
|
|
43
44
|
for (const doc of extra) {
|
|
44
45
|
if (!isPlainObject(doc))
|
|
45
46
|
continue;
|
|
46
|
-
const docId = doc
|
|
47
|
+
const docId = getAggregationRowId(doc, collectionName);
|
|
47
48
|
if (docId == null)
|
|
48
49
|
continue;
|
|
49
|
-
|
|
50
|
-
doc
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
for (const field of idFields) {
|
|
51
|
+
if (doc[field] !== docId)
|
|
52
|
+
doc[field] = docId;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function getAggregationRowId(row, collectionName) {
|
|
57
|
+
if (!isPlainObject(row))
|
|
58
|
+
return;
|
|
59
|
+
const idFields = getAggregationIdFields(collectionName);
|
|
60
|
+
for (const field of idFields) {
|
|
61
|
+
const value = row[field];
|
|
62
|
+
if (typeof value === 'string')
|
|
63
|
+
return value;
|
|
53
64
|
}
|
|
54
65
|
}
|
|
55
66
|
export function getAggregationSignal(collectionName, params, options) {
|
|
56
|
-
params =
|
|
67
|
+
params = cloneQueryParams(collectionName, params);
|
|
57
68
|
const transportHash = hashQuery(collectionName, params);
|
|
58
69
|
const { root, signalOptions } = parseAggregationSignalOptions(options);
|
|
59
70
|
const $aggregation = getSignal(root, [AGGREGATIONS, transportHash], signalOptions);
|
|
@@ -80,7 +91,7 @@ export function isAggregationSignal($signal) {
|
|
|
80
91
|
return true;
|
|
81
92
|
}
|
|
82
93
|
// example: ['$aggregations', '{"active":true}', 42]
|
|
83
|
-
// AND only if
|
|
94
|
+
// AND only if the aggregation row carries a source document id field
|
|
84
95
|
export function getAggregationDocId(segments, rootId, method) {
|
|
85
96
|
if (!(segments.length >= 3))
|
|
86
97
|
return;
|
|
@@ -88,15 +99,16 @@ export function getAggregationDocId(segments, rootId, method) {
|
|
|
88
99
|
return;
|
|
89
100
|
if (!(typeof segments[2] === 'number'))
|
|
90
101
|
return;
|
|
102
|
+
const collectionName = getAggregationCollectionName(segments);
|
|
103
|
+
const idFields = getAggregationIdFields(collectionName);
|
|
91
104
|
if (typeof method !== 'function') {
|
|
92
105
|
method = path => rootId == null ? getRaw(path) : getPrivateData(rootId, path);
|
|
93
106
|
}
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return id;
|
|
107
|
+
for (const field of idFields) {
|
|
108
|
+
const id = method([...segments.slice(0, 3), field]);
|
|
109
|
+
if (typeof id === 'string')
|
|
110
|
+
return id;
|
|
111
|
+
}
|
|
100
112
|
}
|
|
101
113
|
export function getAggregationCollectionName(segments) {
|
|
102
114
|
if (!(segments.length >= 2))
|
|
@@ -117,3 +129,15 @@ function parseAggregationSignalOptions(options) {
|
|
|
117
129
|
const { root, ...signalOptions } = options;
|
|
118
130
|
return { root, signalOptions };
|
|
119
131
|
}
|
|
132
|
+
function getAggregationIdFields(collectionName) {
|
|
133
|
+
const idFields = getCollectionIdFields(collectionName);
|
|
134
|
+
return uniq(idFields.concat(DEFAULT_AGGREGATION_ID_FIELDS));
|
|
135
|
+
}
|
|
136
|
+
function getCollectionIdFields(collectionName) {
|
|
137
|
+
return collectionName
|
|
138
|
+
? getIdFieldsForSegments([collectionName, ''])
|
|
139
|
+
: [];
|
|
140
|
+
}
|
|
141
|
+
function uniq(values) {
|
|
142
|
+
return Array.from(new Set(values));
|
|
143
|
+
}
|
package/dist/orm/Doc.js
CHANGED
|
@@ -5,7 +5,6 @@ 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";
|
|
@@ -148,9 +147,6 @@ class Doc {
|
|
|
148
147
|
doc.on('load', () => this._refData());
|
|
149
148
|
doc.on('create', () => this._refData());
|
|
150
149
|
doc.on('del', () => this._refMissingData());
|
|
151
|
-
if (isModelEventsEnabled()) {
|
|
152
|
-
doc.on('op', op => emitDocOp(this.collection, this.docId, op));
|
|
153
|
-
}
|
|
154
150
|
}
|
|
155
151
|
_refMissingData() {
|
|
156
152
|
_del([this.collection, this.docId]);
|
|
@@ -870,57 +866,6 @@ function createPendingDestroyEntry() {
|
|
|
870
866
|
reject: rejectPending
|
|
871
867
|
};
|
|
872
868
|
}
|
|
873
|
-
function emitDocOp(collection, docId, op) {
|
|
874
|
-
if (!isModelEventsEnabled())
|
|
875
|
-
return;
|
|
876
|
-
const ops = Array.isArray(op) ? op : [op];
|
|
877
|
-
for (const component of ops) {
|
|
878
|
-
if (!component || !component.p)
|
|
879
|
-
continue;
|
|
880
|
-
const baseSegments = [collection, docId];
|
|
881
|
-
let pathSegments = baseSegments.concat(component.p);
|
|
882
|
-
const meta = {};
|
|
883
|
-
let value;
|
|
884
|
-
let prevValue;
|
|
885
|
-
if (has(component, 'si') || has(component, 'sd')) {
|
|
886
|
-
const index = component.p[component.p.length - 1];
|
|
887
|
-
meta.op = has(component, 'si') ? 'stringInsert' : 'stringRemove';
|
|
888
|
-
meta.index = index;
|
|
889
|
-
pathSegments = baseSegments.concat(component.p.slice(0, -1));
|
|
890
|
-
value = _getRaw(pathSegments);
|
|
891
|
-
prevValue = component.sd;
|
|
892
|
-
}
|
|
893
|
-
else if (has(component, 'lm')) {
|
|
894
|
-
meta.op = 'arrayMove';
|
|
895
|
-
meta.from = component.p[component.p.length - 1];
|
|
896
|
-
meta.to = component.lm;
|
|
897
|
-
pathSegments = baseSegments.concat(component.p.slice(0, -1));
|
|
898
|
-
value = _getRaw(pathSegments);
|
|
899
|
-
}
|
|
900
|
-
else if (has(component, 'li') || has(component, 'ld')) {
|
|
901
|
-
meta.op = has(component, 'li') ? 'arrayInsert' : 'arrayRemove';
|
|
902
|
-
meta.index = component.p[component.p.length - 1];
|
|
903
|
-
value = _getRaw(pathSegments);
|
|
904
|
-
prevValue = component.ld;
|
|
905
|
-
}
|
|
906
|
-
else if (has(component, 'na')) {
|
|
907
|
-
meta.op = 'increment';
|
|
908
|
-
meta.by = component.na;
|
|
909
|
-
value = _getRaw(pathSegments);
|
|
910
|
-
if (typeof value === 'number')
|
|
911
|
-
prevValue = value - component.na;
|
|
912
|
-
}
|
|
913
|
-
else {
|
|
914
|
-
meta.op = 'set';
|
|
915
|
-
value = has(component, 'oi') ? component.oi : _getRaw(pathSegments);
|
|
916
|
-
prevValue = component.od;
|
|
917
|
-
}
|
|
918
|
-
emitModelChange(pathSegments, value, prevValue, meta);
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
function has(obj, key) {
|
|
922
|
-
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
923
|
-
}
|
|
924
869
|
const ERRORS = {
|
|
925
870
|
notSubscribed: $doc => Error('trying to unsubscribe when not subscribed. Doc: ' + $doc.path())
|
|
926
871
|
};
|
package/dist/orm/Query.d.ts
CHANGED
|
@@ -113,5 +113,6 @@ export class QuerySubscriptions {
|
|
|
113
113
|
|
|
114
114
|
export const querySubscriptions: QuerySubscriptions
|
|
115
115
|
export function getQuerySignal (collectionName: string, params: unknown, options?: QuerySignalOptions): Signal
|
|
116
|
+
export function materializeQueryDataDocsToCollection (collectionName: string, docs: unknown): void
|
|
116
117
|
export function hashQuery (collectionName: string, params: unknown): string
|
|
117
118
|
export function parseQueryHash (hash: string): QueryHashParts
|
package/dist/orm/Query.js
CHANGED
|
@@ -2,8 +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
|
-
import { isCompatEnv } from './compatEnv.js';
|
|
7
5
|
import { docSubscriptions } from './Doc.js';
|
|
8
6
|
import FinalizationRegistry from "../utils/MockFinalizationRegistry.js";
|
|
9
7
|
import SubscriptionState from './SubscriptionState.js';
|
|
@@ -127,22 +125,6 @@ export class Query {
|
|
|
127
125
|
return;
|
|
128
126
|
docs.splice(index, 0, ...newDocs);
|
|
129
127
|
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
128
|
});
|
|
147
129
|
});
|
|
148
130
|
this.shareQuery.on('move', (shareDocs, from, to) => {
|
|
@@ -153,26 +135,10 @@ export class Query {
|
|
|
153
135
|
const ids = getPrivateData(rootId, [QUERIES, this.hash, 'ids']);
|
|
154
136
|
if (!Array.isArray(docs) || !Array.isArray(ids))
|
|
155
137
|
return;
|
|
156
|
-
const prevDocs = isModelEventsEnabled() ? docs.slice() : undefined;
|
|
157
138
|
docs.splice(from, shareDocs.length);
|
|
158
139
|
docs.splice(to, 0, ...movedDocs);
|
|
159
|
-
const prevIds = isModelEventsEnabled() ? ids.slice() : undefined;
|
|
160
140
|
ids.splice(from, shareDocs.length);
|
|
161
141
|
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
142
|
});
|
|
177
143
|
});
|
|
178
144
|
this.shareQuery.on('remove', (shareDocs, index) => {
|
|
@@ -187,26 +153,8 @@ export class Query {
|
|
|
187
153
|
const ids = getPrivateData(rootId, [QUERIES, this.hash, 'ids']);
|
|
188
154
|
if (!Array.isArray(docs) || !Array.isArray(ids))
|
|
189
155
|
return;
|
|
190
|
-
const removedDocs = isModelEventsEnabled() ? docs.slice(index, index + shareDocs.length) : undefined;
|
|
191
156
|
docs.splice(index, shareDocs.length);
|
|
192
|
-
const removedIds = isModelEventsEnabled() ? ids.slice(index, index + docIds.length) : undefined;
|
|
193
157
|
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
158
|
});
|
|
211
159
|
});
|
|
212
160
|
this.shareQuery.on('extra', extra => {
|
|
@@ -465,7 +413,7 @@ export class QuerySubscriptions {
|
|
|
465
413
|
}
|
|
466
414
|
subscribe($query, { intent = 'subscribe' } = {}) {
|
|
467
415
|
const collectionName = $query[COLLECTION_NAME];
|
|
468
|
-
const params = cloneQueryParams($query[PARAMS]);
|
|
416
|
+
const params = cloneQueryParams(collectionName, $query[PARAMS]);
|
|
469
417
|
const transportHash = $query[HASH];
|
|
470
418
|
const rootId = getOwningRootId($query);
|
|
471
419
|
const ownerKey = getQueryOwnerKey(rootId, transportHash);
|
|
@@ -887,8 +835,6 @@ export class QuerySubscriptions {
|
|
|
887
835
|
}
|
|
888
836
|
export const querySubscriptions = new QuerySubscriptions();
|
|
889
837
|
function maybeMaterializeQueryDocsToCollection(collectionName, shareDocs) {
|
|
890
|
-
if (!isCompatEnv())
|
|
891
|
-
return;
|
|
892
838
|
for (const doc of shareDocs) {
|
|
893
839
|
if (!doc?.id || doc.data == null)
|
|
894
840
|
continue;
|
|
@@ -901,8 +847,26 @@ function maybeMaterializeQueryDocsToCollection(collectionName, shareDocs) {
|
|
|
901
847
|
_set([collectionName, doc.id], raw(doc.data));
|
|
902
848
|
}
|
|
903
849
|
}
|
|
850
|
+
export function materializeQueryDataDocsToCollection(collectionName, docs) {
|
|
851
|
+
if (!Array.isArray(docs))
|
|
852
|
+
return;
|
|
853
|
+
for (const doc of docs) {
|
|
854
|
+
const rawDoc = raw(doc);
|
|
855
|
+
if (!isPlainObject(rawDoc))
|
|
856
|
+
continue;
|
|
857
|
+
const docId = rawDoc._id ?? rawDoc.id;
|
|
858
|
+
if (docId == null)
|
|
859
|
+
continue;
|
|
860
|
+
const existing = getRaw([collectionName, docId]);
|
|
861
|
+
if (existing != null)
|
|
862
|
+
continue;
|
|
863
|
+
const idFields = getIdFieldsForSegments([collectionName, docId]);
|
|
864
|
+
injectIdFields(rawDoc, idFields, docId);
|
|
865
|
+
_set([collectionName, docId], rawDoc);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
904
868
|
export function hashQuery(collectionName, params) {
|
|
905
|
-
params = normalizeQueryParamsForHash(params);
|
|
869
|
+
params = normalizeQueryParamsForHash(collectionName, params);
|
|
906
870
|
// TODO: probably makes sense to use fast-stable-json-stringify for this because of the params
|
|
907
871
|
return JSON.stringify({ query: [collectionName, params] });
|
|
908
872
|
}
|
|
@@ -916,7 +880,7 @@ export function parseQueryHash(hash) {
|
|
|
916
880
|
}
|
|
917
881
|
}
|
|
918
882
|
export function getQuerySignal(collectionName, params, options) {
|
|
919
|
-
params = cloneQueryParams(params);
|
|
883
|
+
params = cloneQueryParams(collectionName, params);
|
|
920
884
|
const transportHash = hashQuery(collectionName, params);
|
|
921
885
|
const { root, signalOptions } = parseQuerySignalOptions(options);
|
|
922
886
|
const signalHash = getScopedSignalHash(root?.[ROOT_ID] ?? signalOptions.rootId, transportHash, 'querySignal');
|
|
@@ -969,10 +933,8 @@ function getOwningRootId($query) {
|
|
|
969
933
|
function getQueryOwnerKey(rootId, transportHash) {
|
|
970
934
|
return getScopedSignalHash(rootId, transportHash, 'queryOwner');
|
|
971
935
|
}
|
|
972
|
-
function cloneQueryParams(params) {
|
|
973
|
-
|
|
974
|
-
return JSON.parse(JSON.stringify(params));
|
|
975
|
-
return cloneQueryParamsCompat(params);
|
|
936
|
+
export function cloneQueryParams(collectionName, params) {
|
|
937
|
+
return JSON.parse(JSON.stringify(params));
|
|
976
938
|
}
|
|
977
939
|
function parseQuerySignalOptions(options) {
|
|
978
940
|
if (!options || typeof options !== 'object') {
|
|
@@ -984,27 +946,8 @@ function parseQuerySignalOptions(options) {
|
|
|
984
946
|
const { root, ...signalOptions } = options;
|
|
985
947
|
return { root, signalOptions };
|
|
986
948
|
}
|
|
987
|
-
function normalizeQueryParamsForHash(params) {
|
|
988
|
-
|
|
989
|
-
return params;
|
|
990
|
-
return cloneQueryParamsCompat(params);
|
|
991
|
-
}
|
|
992
|
-
// Racer compat: keep query keys with undefined values by normalizing them to null
|
|
993
|
-
// instead of dropping them via JSON serialization.
|
|
994
|
-
function cloneQueryParamsCompat(value) {
|
|
995
|
-
if (value === undefined)
|
|
996
|
-
return null;
|
|
997
|
-
if (value == null || typeof value !== 'object')
|
|
998
|
-
return value;
|
|
999
|
-
if (Array.isArray(value))
|
|
1000
|
-
return value.map(item => cloneQueryParamsCompat(item));
|
|
1001
|
-
const object = {};
|
|
1002
|
-
for (const key in value) {
|
|
1003
|
-
if (Object.prototype.hasOwnProperty.call(value, key)) {
|
|
1004
|
-
object[key] = cloneQueryParamsCompat(value[key]);
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
return object;
|
|
949
|
+
function normalizeQueryParamsForHash(collectionName, params) {
|
|
950
|
+
return params;
|
|
1008
951
|
}
|
|
1009
952
|
function createPendingDestroyEntry() {
|
|
1010
953
|
let resolvePending;
|
package/dist/orm/Root.d.ts
CHANGED
|
@@ -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
|
package/dist/orm/Signal.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import SignalCompat from './Compat/SignalCompat.js';
|
|
2
1
|
import type { SignalConstructor } from './types/signal.js';
|
|
3
2
|
export type { FromJsonSchema, InferZodSchema, JsonSchema, JsonSchemaObject, ZodLikeSchema } from './types/jsonSchema.js';
|
|
4
3
|
export type { ComputedQueryParamsInput, QueryParams, QueryParamsInput } from './types/query.js';
|
|
@@ -7,6 +6,5 @@ export type { AppendPath, JoinPath, PathSegment, SignalPath, WildcardPathSegment
|
|
|
7
6
|
export type { AggregationSignal, AnySignal, ArraySignal, CollectionAggregationSignal, CollectionDocument, CollectionDocumentModel, CollectionQuerySignal, CollectionSignal, CollectionSignalFromSpec, CollectionSpec, DocumentSignal, JsonSchemaSpec, MaybePromise, MaybePromiseSubResult, PublicSignal, LocalSignalFactory, RegisteredAggregationInput, RuntimeSignalConstructor, RuntimeSignalInstance, QuerySignal, RootCollections, RootSignal, SignalBaseInstance, SignalChild, SignalChildren, SignalClass, SignalConstructor, SignalForKind, SignalKind, SignalInstance, SignalModelConstructor, PrivateSignalFromSpec, RootPrivateCollections, SubResult, TypedAggregationInput, TypedAggregationSignal, TypedSignal, ZodSchemaSpec } from './types/signal.js';
|
|
8
7
|
export type { CollectionsFromManifest, ModelEntry, ModelManifest, PathModelsFromManifest, PrivateCollectionsFromManifest } from './types/modelManifest.js';
|
|
9
8
|
export { Signal, SEGMENTS, ARRAY_METHOD, GET, GETTERS, DEFAULT_GETTERS, regularBindings, extremelyLateBindings, isPublicCollectionSignal, isPublicDocumentSignal, isPublicCollection, isPrivateCollection } from './SignalBase.js';
|
|
10
|
-
export { SignalCompat };
|
|
11
9
|
declare const DefaultSignal: SignalConstructor;
|
|
12
10
|
export default DefaultSignal;
|
package/dist/orm/Signal.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import { Signal } from "./SignalBase.js";
|
|
2
|
-
import SignalCompat from './Compat/SignalCompat.js';
|
|
3
|
-
import { isCompatEnv } from './compatEnv.js';
|
|
4
2
|
export { Signal, SEGMENTS, ARRAY_METHOD, GET, GETTERS, DEFAULT_GETTERS, regularBindings, extremelyLateBindings, isPublicCollectionSignal, isPublicDocumentSignal, isPublicCollection, isPrivateCollection } from "./SignalBase.js";
|
|
5
|
-
|
|
6
|
-
const DefaultSignal = (isCompatEnv() ? SignalCompat : Signal);
|
|
3
|
+
const DefaultSignal = Signal;
|
|
7
4
|
export default DefaultSignal;
|