@connecttomahdi/rxdb 17.1.0 → 17.1.1
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/cjs/plugins/storage-dexie/rx-storage-instance-dexie.js +10 -10
- package/dist/cjs/plugins/storage-dexie/rx-storage-instance-dexie.js.map +1 -1
- package/dist/cjs/plugins/utils/utils-premium.js +4 -4
- package/dist/cjs/plugins/utils/utils-premium.js.map +1 -1
- package/dist/esm/package.json +1 -0
- package/dist/esm/plugins/storage-dexie/rx-storage-instance-dexie.js +10 -10
- package/dist/esm/plugins/storage-dexie/rx-storage-instance-dexie.js.map +1 -1
- package/dist/esm/plugins/utils/utils-premium.js +4 -4
- package/dist/esm/plugins/utils/utils-premium.js.map +1 -1
- package/dist/types/index.d.ts +26 -25
- package/dist/types/types/conflict-handling.d.ts +48 -0
- package/dist/types/types/couchdb.d.ts +293 -0
- package/dist/types/types/index.d.ts +32 -0
- package/dist/types/types/modules/index.d.ts +0 -0
- package/dist/types/types/modules/mocha.parallel.d.ts +1 -0
- package/dist/types/types/plugins/backup.d.ts +35 -0
- package/dist/types/types/plugins/cleanup.d.ts +38 -0
- package/dist/types/types/plugins/crdt.d.ts +76 -0
- package/dist/types/types/plugins/dexie.d.ts +30 -0
- package/dist/types/types/plugins/local-documents.d.ts +49 -0
- package/dist/types/types/plugins/migration.d.ts +14 -0
- package/dist/types/types/plugins/reactivity.d.ts +40 -0
- package/dist/types/types/plugins/replication-graphql.d.ts +98 -0
- package/dist/types/types/plugins/replication.d.ts +175 -0
- package/dist/types/types/plugins/state.d.ts +4 -0
- package/dist/types/types/plugins/update.d.ts +23 -0
- package/dist/types/types/plugins/webmcp.d.ts +40 -0
- package/dist/types/types/query-planner.d.ts +47 -0
- package/dist/types/types/replication-protocol.d.ts +296 -0
- package/dist/types/types/rx-attachment.d.ts +46 -0
- package/dist/types/types/rx-change-event.d.ts +85 -0
- package/dist/types/types/rx-collection.d.ts +117 -0
- package/dist/types/types/rx-database-internal-store.d.ts +54 -0
- package/dist/types/types/rx-database.d.ts +124 -0
- package/dist/types/types/rx-document.d.ts +160 -0
- package/dist/types/types/rx-error.d.ts +225 -0
- package/dist/types/types/rx-plugin.d.ts +167 -0
- package/dist/types/types/rx-query.d.ts +144 -0
- package/dist/types/types/rx-schema.d.ts +214 -0
- package/dist/types/types/rx-storage.d.ts +347 -0
- package/dist/types/types/rx-storage.interface.d.ts +312 -0
- package/dist/types/types/util.d.ts +180 -0
- package/package.json +732 -732
- package/scripts/copy-path.mjs +20 -0
- package/scripts/fix-types.mjs +15 -8
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { ClientOptions } from 'graphql-ws';
|
|
2
|
+
import { RxReplicationWriteToMasterRow } from '../replication-protocol.ts';
|
|
3
|
+
import { ById, MaybePromise } from '../util.ts';
|
|
4
|
+
import {
|
|
5
|
+
ReplicationOptions,
|
|
6
|
+
ReplicationPullHandlerResult,
|
|
7
|
+
ReplicationPullOptions,
|
|
8
|
+
ReplicationPushHandlerResult,
|
|
9
|
+
ReplicationPushOptions
|
|
10
|
+
} from './replication.ts';
|
|
11
|
+
|
|
12
|
+
export interface RxGraphQLReplicationQueryBuilderResponseObject {
|
|
13
|
+
query: string;
|
|
14
|
+
operationName?: string;
|
|
15
|
+
variables: any;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type RxGraphQLReplicationClientState = {
|
|
19
|
+
headers: ById<string>;
|
|
20
|
+
credentials: RequestCredentials | undefined;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type RxGraphQLReplicationQueryBuilderResponse =
|
|
24
|
+
RxGraphQLReplicationQueryBuilderResponseObject |
|
|
25
|
+
Promise<RxGraphQLReplicationQueryBuilderResponseObject>;
|
|
26
|
+
export type RxGraphQLReplicationPushQueryBuilder = (
|
|
27
|
+
// typed 'any' because the data might be modified by the push.modifier.
|
|
28
|
+
rows: RxReplicationWriteToMasterRow<any>[]
|
|
29
|
+
) => RxGraphQLReplicationQueryBuilderResponse;
|
|
30
|
+
|
|
31
|
+
export type RxGraphQLPullWSOptions = Omit<ClientOptions, 'url' | 'shouldRetry' | 'webSocketImpl'>;
|
|
32
|
+
|
|
33
|
+
export type RxGraphQLReplicationPullQueryBuilder<CheckpointType> = (
|
|
34
|
+
latestPulledCheckpoint: CheckpointType | undefined,
|
|
35
|
+
limit: number
|
|
36
|
+
) => RxGraphQLReplicationQueryBuilderResponse;
|
|
37
|
+
export type GraphQLSyncPullOptions<RxDocType, CheckpointType> = Omit<
|
|
38
|
+
ReplicationPullOptions<RxDocType, CheckpointType>,
|
|
39
|
+
'handler' | 'stream$'
|
|
40
|
+
> & {
|
|
41
|
+
queryBuilder: RxGraphQLReplicationPullQueryBuilder<CheckpointType>;
|
|
42
|
+
streamQueryBuilder?: RxGraphQLReplicationPullStreamQueryBuilder;
|
|
43
|
+
/**
|
|
44
|
+
* The path to the data in the GraphQL response.
|
|
45
|
+
* If set, the data will be taken from the response at this path.
|
|
46
|
+
* @example ['data', 'foo', 'bar'] or 'data.foo.bar'
|
|
47
|
+
*/
|
|
48
|
+
dataPath?: string | string[];
|
|
49
|
+
responseModifier?: RxGraphQLPullResponseModifier<RxDocType, CheckpointType>;
|
|
50
|
+
includeWsHeaders?: boolean;
|
|
51
|
+
wsOptions?: RxGraphQLPullWSOptions;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type RxGraphQLPullResponseModifier<RxDocType, CheckpointType> = (
|
|
55
|
+
// the exact response that was returned from the server
|
|
56
|
+
plainResponse: ReplicationPullHandlerResult<RxDocType, CheckpointType> | any,
|
|
57
|
+
// either 'handler' if it came from the pull.handler, or 'stream' if it came from the pull.stream
|
|
58
|
+
origin: 'handler' | 'stream',
|
|
59
|
+
requestCheckpoint?: CheckpointType
|
|
60
|
+
) => MaybePromise<ReplicationPullHandlerResult<RxDocType, CheckpointType>>;
|
|
61
|
+
|
|
62
|
+
export type RxGraphQLPushResponseModifier<RxDocType> = (
|
|
63
|
+
// the exact response that was returned from the server
|
|
64
|
+
plainResponse: ReplicationPushHandlerResult<RxDocType> | any,
|
|
65
|
+
) => MaybePromise<ReplicationPushHandlerResult<RxDocType>>;
|
|
66
|
+
|
|
67
|
+
export type RxGraphQLReplicationPullStreamQueryBuilder = (headers: { [k: string]: string; }) => RxGraphQLReplicationQueryBuilderResponse;
|
|
68
|
+
|
|
69
|
+
export type GraphQLSyncPushOptions<RxDocType> = Omit<
|
|
70
|
+
ReplicationPushOptions<RxDocType>,
|
|
71
|
+
'handler'
|
|
72
|
+
> & {
|
|
73
|
+
queryBuilder: RxGraphQLReplicationPushQueryBuilder;
|
|
74
|
+
/**
|
|
75
|
+
* The path to the data in the GraphQL response.
|
|
76
|
+
* If set, the data will be taken from the response at this path.
|
|
77
|
+
* @example ['data', 'foo', 'bar'] or 'data.foo.bar'
|
|
78
|
+
*/
|
|
79
|
+
dataPath?: string | string[];
|
|
80
|
+
responseModifier?: RxGraphQLPushResponseModifier<RxDocType>;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type GraphQLServerUrl = {
|
|
84
|
+
http?: string;
|
|
85
|
+
ws?: string;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export type SyncOptionsGraphQL<RxDocType, CheckpointType> = Omit<
|
|
89
|
+
ReplicationOptions<RxDocType, CheckpointType>,
|
|
90
|
+
'pull' | 'push'
|
|
91
|
+
> & {
|
|
92
|
+
url: GraphQLServerUrl;
|
|
93
|
+
fetch?: WindowOrWorkerGlobalScope['fetch'];
|
|
94
|
+
headers?: { [k: string]: string; }; // send with all requests to the endpoint
|
|
95
|
+
credentials?: RequestCredentials;
|
|
96
|
+
pull?: GraphQLSyncPullOptions<RxDocType, CheckpointType>;
|
|
97
|
+
push?: GraphQLSyncPushOptions<RxDocType>;
|
|
98
|
+
};
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import type {
|
|
3
|
+
InternalStoreDocType,
|
|
4
|
+
MaybePromise,
|
|
5
|
+
RxCollection,
|
|
6
|
+
RxDocumentData,
|
|
7
|
+
RxReplicationPullStreamItem,
|
|
8
|
+
RxReplicationWriteToMasterRow,
|
|
9
|
+
WithDeleted
|
|
10
|
+
} from '../../types/index.d.ts';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export type InternalStoreReplicationPushDocType = InternalStoreDocType<{
|
|
14
|
+
checkpoint: any;
|
|
15
|
+
}>;
|
|
16
|
+
export type InternalStoreReplicationPullDocType<RxDocType> = InternalStoreDocType<{
|
|
17
|
+
lastPulledDoc: RxDocumentData<RxDocType>;
|
|
18
|
+
}>;
|
|
19
|
+
|
|
20
|
+
export type ReplicationPullHandlerResult<RxDocType, CheckpointType> = {
|
|
21
|
+
checkpoint: CheckpointType | undefined;
|
|
22
|
+
documents: WithDeleted<RxDocType>[];
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type ReplicationPushHandlerResult<RxDocType> = RxDocType[];
|
|
26
|
+
|
|
27
|
+
export type ReplicationPullHandler<RxDocType, CheckpointType> = (
|
|
28
|
+
lastPulledCheckpoint: CheckpointType | undefined,
|
|
29
|
+
batchSize: number
|
|
30
|
+
) => Promise<ReplicationPullHandlerResult<RxDocType, CheckpointType>>;
|
|
31
|
+
|
|
32
|
+
export type ReplicationPullOptions<RxDocType, CheckpointType> = {
|
|
33
|
+
/**
|
|
34
|
+
* A handler that pulls the new remote changes
|
|
35
|
+
* from the remote actor.
|
|
36
|
+
*/
|
|
37
|
+
handler: ReplicationPullHandler<RxDocType, CheckpointType>;
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* An observable that streams all document changes
|
|
42
|
+
* that are happening on the backend.
|
|
43
|
+
* Emits an document bulk together with the latest checkpoint of these documents.
|
|
44
|
+
* Also can emit a 'RESYNC' event when the client was offline and is online again.
|
|
45
|
+
*
|
|
46
|
+
* Not required for non-live replication.
|
|
47
|
+
*/
|
|
48
|
+
stream$?: Observable<RxReplicationPullStreamItem<RxDocType, CheckpointType>>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Amount of documents that the remote will send in one request.
|
|
52
|
+
* If the response contains less then [batchSize] documents,
|
|
53
|
+
* RxDB will assume there are no more changes on the backend
|
|
54
|
+
* that are not replicated.
|
|
55
|
+
* [default=100]
|
|
56
|
+
*/
|
|
57
|
+
batchSize?: number;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* A modifier that runs on all documents that are pulled,
|
|
61
|
+
* before they are used by RxDB.
|
|
62
|
+
* - the ones from the pull handler
|
|
63
|
+
* - the ones from the pull stream
|
|
64
|
+
*/
|
|
65
|
+
modifier?: (docData: any) => MaybePromise<WithDeleted<RxDocType>>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* If set, the push replication
|
|
69
|
+
* will start from the given checkpoint.
|
|
70
|
+
*/
|
|
71
|
+
initialCheckpoint?: any;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Gets the new write rows.
|
|
76
|
+
* Returns the current master state of all conflicting writes,
|
|
77
|
+
* so that they can be resolved on the client.
|
|
78
|
+
*/
|
|
79
|
+
export type ReplicationPushHandler<RxDocType> = (
|
|
80
|
+
docs: RxReplicationWriteToMasterRow<RxDocType>[]
|
|
81
|
+
) => Promise<WithDeleted<RxDocType>[]>;
|
|
82
|
+
export type ReplicationPushOptions<RxDocType> = {
|
|
83
|
+
/**
|
|
84
|
+
* A handler that sends the new local changes
|
|
85
|
+
* to the remote actor.
|
|
86
|
+
* On error, all documents are send again at later time.
|
|
87
|
+
*/
|
|
88
|
+
handler: ReplicationPushHandler<RxDocType>;
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* A modifier that runs on all pushed documents before
|
|
93
|
+
* they are send into the push handler.
|
|
94
|
+
*/
|
|
95
|
+
modifier?: (docData: WithDeleted<RxDocType>) => MaybePromise<any | null>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* How many local changes to process at once.
|
|
99
|
+
*/
|
|
100
|
+
batchSize?: number;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* If set, the push replication
|
|
104
|
+
* will start from the given checkpoint.
|
|
105
|
+
*/
|
|
106
|
+
initialCheckpoint?: any;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* When a local write happens, normally the replication will directly try to persist
|
|
110
|
+
* the change upstream.
|
|
111
|
+
*
|
|
112
|
+
* By providing a function here that returns a promise, the replication will wait until
|
|
113
|
+
* that promise resolves before running the next upstream persist cycle. This can be
|
|
114
|
+
* used to batch writes across multiple collections into a single push or to defer
|
|
115
|
+
* pushing until the CPU is idle (e.g. via requestIdleCallback).
|
|
116
|
+
*
|
|
117
|
+
* NOTE: The longer you wait here, the higher the risk of losing writes if the
|
|
118
|
+
* replication is closed unexpectedly.
|
|
119
|
+
*/
|
|
120
|
+
waitBeforePersist?: () => Promise<any>;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
export type ReplicationOptions<RxDocType, CheckpointType> = {
|
|
125
|
+
/**
|
|
126
|
+
* An id for the replication to identify it
|
|
127
|
+
* and so that RxDB is able to resume the replication on app reload.
|
|
128
|
+
* If you replicate with a remote server, it is recommended to put the
|
|
129
|
+
* server url into the replicationIdentifier.
|
|
130
|
+
* Like 'my-rest-replication-to-https://example.com/api/sync'
|
|
131
|
+
*/
|
|
132
|
+
replicationIdentifier: string;
|
|
133
|
+
collection: RxCollection<RxDocType, unknown, unknown, unknown>;
|
|
134
|
+
/**
|
|
135
|
+
* Define a custom property that is used
|
|
136
|
+
* to flag a document as being deleted.
|
|
137
|
+
* @default '_deleted'
|
|
138
|
+
*/
|
|
139
|
+
deletedField?: '_deleted' | string;
|
|
140
|
+
pull?: ReplicationPullOptions<RxDocType, CheckpointType>;
|
|
141
|
+
push?: ReplicationPushOptions<RxDocType>;
|
|
142
|
+
/**
|
|
143
|
+
* By default it will do an ongoing realtime replication.
|
|
144
|
+
* By settings live: false the replication will run once until the local state
|
|
145
|
+
* is in sync with the remote state, then it will cancel itself.
|
|
146
|
+
* @default true
|
|
147
|
+
*/
|
|
148
|
+
live?: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Time in milliseconds after when a failed backend request
|
|
151
|
+
* has to be retried.
|
|
152
|
+
* This time will be skipped if a offline->online switch is detected
|
|
153
|
+
* via `navigator.onLine`
|
|
154
|
+
* @default 5000
|
|
155
|
+
*/
|
|
156
|
+
retryTime?: number;
|
|
157
|
+
/**
|
|
158
|
+
* When multiInstance is `true`, like when you use RxDB in multiple browser tabs,
|
|
159
|
+
* the replication should always run in only one of the open browser tabs.
|
|
160
|
+
* If waitForLeadership is `true`, it will wait until the current instance is leader.
|
|
161
|
+
* If waitForLeadership is `false`, it will start replicating, even if it is not leader.
|
|
162
|
+
* @default true
|
|
163
|
+
*/
|
|
164
|
+
waitForLeadership?: boolean;
|
|
165
|
+
|
|
166
|
+
toggleOnDocumentVisible?: boolean;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* If this is set to `false`,
|
|
170
|
+
* the replication will not start automatically
|
|
171
|
+
* but will wait for `replicationState.start()` being called.
|
|
172
|
+
* @default true
|
|
173
|
+
*/
|
|
174
|
+
autoStart?: boolean;
|
|
175
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RxStateBase } from '../../plugins/state/rx-state';
|
|
2
|
+
import type { ExtendObservables, ExtendReactivity } from '../rx-document';
|
|
3
|
+
|
|
4
|
+
export type RxState<T, Reactivity = unknown> = RxStateBase<T, Reactivity> & T & ExtendObservables<Required<T>> & ExtendReactivity<Required<T>, Reactivity>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AnyKeys, AnyObject } from '../util.d.ts';
|
|
2
|
+
|
|
3
|
+
// import type {
|
|
4
|
+
// UpdateExpression
|
|
5
|
+
// } from 'mingo/updater';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* We use an own type here, copied from mongoose
|
|
9
|
+
* @link https://github.com/Automattic/mongoose/blob/eb292d2c4cc98ee315f118d6199a83938f06d901/types/index.d.ts#L466
|
|
10
|
+
* When the mingo library implements a schema-based type for UpdateExpression, we can use these typings instead.
|
|
11
|
+
*/
|
|
12
|
+
export type UpdateQuery<TSchema> = {
|
|
13
|
+
$min?: AnyKeys<TSchema> & AnyObject;
|
|
14
|
+
$max?: AnyKeys<TSchema> & AnyObject;
|
|
15
|
+
$inc?: AnyKeys<TSchema> & AnyObject;
|
|
16
|
+
$set?: AnyKeys<TSchema> & AnyObject;
|
|
17
|
+
$unset?: AnyKeys<TSchema> & AnyObject;
|
|
18
|
+
$push?: AnyKeys<TSchema> & AnyObject;
|
|
19
|
+
$addToSet?: AnyKeys<TSchema> & AnyObject;
|
|
20
|
+
$pop?: AnyKeys<TSchema> & AnyObject;
|
|
21
|
+
$pullAll?: AnyKeys<TSchema> & AnyObject;
|
|
22
|
+
$rename?: Record<string, string>;
|
|
23
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RxDatabase,
|
|
3
|
+
RxCollection
|
|
4
|
+
} from '../../index.d.ts';
|
|
5
|
+
|
|
6
|
+
import type { Observable } from 'rxjs';
|
|
7
|
+
|
|
8
|
+
export interface WebMCPOptions {
|
|
9
|
+
/**
|
|
10
|
+
* If true, modifier tools (insert, upsert, delete) will not be registered
|
|
11
|
+
* for this database or collection.
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
readOnly?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* If true, delays queries until all replication states of the collection
|
|
17
|
+
* are in sync.
|
|
18
|
+
* @default true
|
|
19
|
+
*/
|
|
20
|
+
awaitReplicationsInSync?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface WebMCPLogEvent {
|
|
24
|
+
collectionName: string;
|
|
25
|
+
databaseName: string;
|
|
26
|
+
toolName: string;
|
|
27
|
+
args: any;
|
|
28
|
+
result?: any;
|
|
29
|
+
error?: any;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface RxWebMCPPlugin {
|
|
33
|
+
name: 'webmcp';
|
|
34
|
+
rxdb: true;
|
|
35
|
+
prototypes: {
|
|
36
|
+
RxDatabase: (proto: any) => void;
|
|
37
|
+
RxCollection: (proto: any) => void;
|
|
38
|
+
};
|
|
39
|
+
hooks?: any;
|
|
40
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export type RxQueryPlanKey = string | number | undefined;
|
|
2
|
+
|
|
3
|
+
export type RxQueryPlanerOpts = {
|
|
4
|
+
startKey: RxQueryPlanKey;
|
|
5
|
+
endKey: RxQueryPlanKey;
|
|
6
|
+
/**
|
|
7
|
+
* True if the first matching document
|
|
8
|
+
* must also be included into the result set.
|
|
9
|
+
*/
|
|
10
|
+
inclusiveStart: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* True if the last matching document
|
|
13
|
+
* must also be included into the result set.
|
|
14
|
+
*/
|
|
15
|
+
inclusiveEnd: boolean;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type RxQueryPlan = {
|
|
19
|
+
index: string[];
|
|
20
|
+
/**
|
|
21
|
+
* If the index does not match the sort params,
|
|
22
|
+
* we have to resort the query results manually
|
|
23
|
+
* after fetching them from the index.
|
|
24
|
+
*/
|
|
25
|
+
sortSatisfiedByIndex: boolean;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* If the whole selector matching is satisfied
|
|
29
|
+
* by the index, we do not have to run a does-document-data-match-query
|
|
30
|
+
* stuff.
|
|
31
|
+
*/
|
|
32
|
+
selectorSatisfiedByIndex: boolean;
|
|
33
|
+
|
|
34
|
+
startKeys: RxQueryPlanKey[];
|
|
35
|
+
endKeys: RxQueryPlanKey[];
|
|
36
|
+
/**
|
|
37
|
+
* True if the first matching document
|
|
38
|
+
* must also be included into the result set.
|
|
39
|
+
*/
|
|
40
|
+
inclusiveStart: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* True if the last matching document
|
|
43
|
+
* must also be included into the result set.
|
|
44
|
+
*/
|
|
45
|
+
inclusiveEnd: boolean;
|
|
46
|
+
|
|
47
|
+
};
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
|
2
|
+
import type {
|
|
3
|
+
RxConflictHandler,
|
|
4
|
+
RxConflictHandlerInput
|
|
5
|
+
} from './conflict-handling.d.ts';
|
|
6
|
+
import type { RxError, RxTypeError } from './rx-error.d.ts';
|
|
7
|
+
import type {
|
|
8
|
+
BulkWriteRow,
|
|
9
|
+
RxDocumentData,
|
|
10
|
+
WithDeleted,
|
|
11
|
+
WithDeletedAndAttachments
|
|
12
|
+
} from './rx-storage.d.ts';
|
|
13
|
+
import type {
|
|
14
|
+
RxStorageInstance
|
|
15
|
+
} from './rx-storage.interface.d.ts';
|
|
16
|
+
import type { HashFunction } from './util.d.ts';
|
|
17
|
+
|
|
18
|
+
export type RxStorageReplicationMeta<RxDocType, CheckpointType> = {
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Combined primary key consisting
|
|
22
|
+
* of: [replicationId, itemId, isCheckpoint]
|
|
23
|
+
* so that the same RxStorageInstance
|
|
24
|
+
* can be used for multiple replication states.
|
|
25
|
+
*/
|
|
26
|
+
id: string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Either the document primaryKey
|
|
30
|
+
* or the id of the replication checkpoint.
|
|
31
|
+
*/
|
|
32
|
+
itemId: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* True if the doc data is about a checkpoint,
|
|
36
|
+
* False if it is about a document state from the master.
|
|
37
|
+
* Stored as a string so it can be used
|
|
38
|
+
* in the combined primary key 'id'
|
|
39
|
+
*/
|
|
40
|
+
isCheckpoint: '0' | '1';
|
|
41
|
+
checkpointData?: CheckpointType;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* the document state of the master
|
|
45
|
+
* only set if not checkpoint.
|
|
46
|
+
*/
|
|
47
|
+
docData?: RxDocType | RxDocumentData<RxDocType> | any;
|
|
48
|
+
/**
|
|
49
|
+
* If the current assumed master was written while
|
|
50
|
+
* resolving a conflict, this field contains
|
|
51
|
+
* the revision of the conflict-solution that
|
|
52
|
+
* is stored in the forkInstance.
|
|
53
|
+
*/
|
|
54
|
+
isResolvedConflict?: string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export type RxReplicationWriteToMasterRow<RxDocType> = {
|
|
58
|
+
assumedMasterState?: WithDeletedAndAttachments<RxDocType>;
|
|
59
|
+
newDocumentState: WithDeletedAndAttachments<RxDocType>;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
export type DocumentsWithCheckpoint<RxDocType, CheckpointType> = {
|
|
64
|
+
documents: WithDeletedAndAttachments<RxDocType>[];
|
|
65
|
+
checkpoint: CheckpointType;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
export type RxReplicationPullStreamItem<RxDocType, MasterCheckpointType> = DocumentsWithCheckpoint<RxDocType, MasterCheckpointType> |
|
|
70
|
+
/**
|
|
71
|
+
* Emit this when the masterChangeStream$ might have missed out
|
|
72
|
+
* some events because the fork lost the connection to the master.
|
|
73
|
+
* Like when the user went offline and reconnects.
|
|
74
|
+
*/
|
|
75
|
+
'RESYNC';
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The replication handler contains all logic
|
|
79
|
+
* that is required by the replication protocol
|
|
80
|
+
* to interact with the master instance.
|
|
81
|
+
* This is an abstraction so that we can use different
|
|
82
|
+
* handlers for GraphQL, REST or any other transportation layer.
|
|
83
|
+
* Even a RxStorageInstance can be wrapped in a way to represent a replication handler.
|
|
84
|
+
*
|
|
85
|
+
* The RxStorage instance of the master branch that is
|
|
86
|
+
* replicated with the fork branch.
|
|
87
|
+
* The replication algorithm is made to make
|
|
88
|
+
* as less writes on the master as possible.
|
|
89
|
+
* The master instance is always 'the truth' which
|
|
90
|
+
* does never contain conflicting document states.
|
|
91
|
+
* All conflicts are handled on the fork branch
|
|
92
|
+
* before being replicated to the master.
|
|
93
|
+
*/
|
|
94
|
+
export type RxReplicationHandler<RxDocType, MasterCheckpointType> = {
|
|
95
|
+
masterChangeStream$: Observable<RxReplicationPullStreamItem<RxDocType, MasterCheckpointType>>;
|
|
96
|
+
masterChangesSince(
|
|
97
|
+
checkpoint: MasterCheckpointType | undefined,
|
|
98
|
+
batchSize: number
|
|
99
|
+
): Promise<DocumentsWithCheckpoint<RxDocType, MasterCheckpointType | undefined>>;
|
|
100
|
+
/**
|
|
101
|
+
* Writes the fork changes to the master.
|
|
102
|
+
* Only returns the conflicts if there are any.
|
|
103
|
+
* (otherwise returns an empty array.)
|
|
104
|
+
*/
|
|
105
|
+
masterWrite(
|
|
106
|
+
rows: RxReplicationWriteToMasterRow<RxDocType>[]
|
|
107
|
+
): Promise<WithDeleted<RxDocType>[]>;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export type RxStorageInstanceReplicationInput<RxDocType> = {
|
|
111
|
+
/**
|
|
112
|
+
* A string that uniquely identifies
|
|
113
|
+
* the replication.
|
|
114
|
+
* Ensures that checkpoint are not
|
|
115
|
+
* mixed with other replications.
|
|
116
|
+
*/
|
|
117
|
+
identifier: string;
|
|
118
|
+
pullBatchSize: number;
|
|
119
|
+
pushBatchSize: number;
|
|
120
|
+
replicationHandler: RxReplicationHandler<RxDocType, any>;
|
|
121
|
+
conflictHandler: RxConflictHandler<RxDocType>;
|
|
122
|
+
|
|
123
|
+
// can be set to also replicate the _meta field of the document.
|
|
124
|
+
keepMeta?: boolean;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The fork is the one that contains the forked chain of document writes.
|
|
128
|
+
* All conflicts are solved on the fork and only resolved correct document data
|
|
129
|
+
* is written back to the parent.
|
|
130
|
+
*/
|
|
131
|
+
forkInstance: RxStorageInstance<RxDocType, any, any>;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The replication needs to store some meta data
|
|
135
|
+
* for documents to know which state is at the master
|
|
136
|
+
* and how/if it diverges from the fork.
|
|
137
|
+
* In the past this was stored in the _meta field of
|
|
138
|
+
* the forkInstance documents but that was not a good design decision
|
|
139
|
+
* because it required additional writes on the forkInstance
|
|
140
|
+
* to know which documents have been upstream replicated
|
|
141
|
+
* to not cause conflicts.
|
|
142
|
+
* Using the metaInstance instead leads to better overall performance
|
|
143
|
+
* because RxDB will not re-emit query results or document state
|
|
144
|
+
* when replication meta data is written.
|
|
145
|
+
*
|
|
146
|
+
* In addition to per-document meta data,
|
|
147
|
+
* the replication checkpoints are also stored in this instance.
|
|
148
|
+
*
|
|
149
|
+
*/
|
|
150
|
+
metaInstance: RxStorageInstance<RxStorageReplicationMeta<RxDocType, any>, any, any>;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* When a write happens to the fork,
|
|
154
|
+
* normally the replication will directly try to persist.
|
|
155
|
+
*
|
|
156
|
+
* For many use cases, it is better to await the next event loop tick
|
|
157
|
+
* or to wait until the RxDatabase is idle or requestIdleCallback() calls
|
|
158
|
+
* to ensure the CPU is idle.
|
|
159
|
+
* This can improve performance because the persistence will not affect UI
|
|
160
|
+
* renders.
|
|
161
|
+
*
|
|
162
|
+
* But: The longer you wait here, the higher is the risk of losing fork
|
|
163
|
+
* writes when the replication is closed unexpected.
|
|
164
|
+
*/
|
|
165
|
+
waitBeforePersist?: () => Promise<any>;
|
|
166
|
+
|
|
167
|
+
hashFunction: HashFunction;
|
|
168
|
+
skipStoringPullMeta: boolean;
|
|
169
|
+
|
|
170
|
+
initialCheckpoint?: {
|
|
171
|
+
upstream?: any;
|
|
172
|
+
downstream?: any;
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export type RxStorageInstanceReplicationState<RxDocType> = {
|
|
177
|
+
// store the primaryPath here for better reuse and performance.
|
|
178
|
+
primaryPath: string;
|
|
179
|
+
hasAttachments: boolean;
|
|
180
|
+
input: RxStorageInstanceReplicationInput<RxDocType>;
|
|
181
|
+
events: {
|
|
182
|
+
/**
|
|
183
|
+
* Streams all document writes that have successfully
|
|
184
|
+
* been written in one direction.
|
|
185
|
+
*/
|
|
186
|
+
processed: {
|
|
187
|
+
up: Subject<RxReplicationWriteToMasterRow<RxDocType>>;
|
|
188
|
+
down: Subject<BulkWriteRow<RxDocType>>;
|
|
189
|
+
};
|
|
190
|
+
resolvedConflicts: Subject<{
|
|
191
|
+
input: RxConflictHandlerInput<RxDocType>;
|
|
192
|
+
output: WithDeleted<RxDocType>;
|
|
193
|
+
}>;
|
|
194
|
+
/**
|
|
195
|
+
* Contains the cancel state.
|
|
196
|
+
* Emit true here to cancel the replication.
|
|
197
|
+
*/
|
|
198
|
+
canceled: BehaviorSubject<boolean>;
|
|
199
|
+
/**
|
|
200
|
+
* Contains the pause state.
|
|
201
|
+
* Emit true here to pause the replication.
|
|
202
|
+
*/
|
|
203
|
+
paused: BehaviorSubject<boolean>;
|
|
204
|
+
/**
|
|
205
|
+
* Contains true if the replication is doing something
|
|
206
|
+
* at this point in time.
|
|
207
|
+
* If this is false, it means that the replication
|
|
208
|
+
* is idle AND in sync.
|
|
209
|
+
*/
|
|
210
|
+
active: {
|
|
211
|
+
[direction in RxStorageReplicationDirection]: BehaviorSubject<boolean>;
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* All errors that would otherwise be unhandled,
|
|
215
|
+
* get emitted here.
|
|
216
|
+
*/
|
|
217
|
+
error: Subject<RxError | RxTypeError>;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Contains counters that can be used in tests
|
|
223
|
+
* or to debug problems.
|
|
224
|
+
*/
|
|
225
|
+
stats: {
|
|
226
|
+
down: {
|
|
227
|
+
addNewTask: number;
|
|
228
|
+
downstreamResyncOnce: number;
|
|
229
|
+
downstreamProcessChanges: number;
|
|
230
|
+
masterChangeStreamEmit: number;
|
|
231
|
+
persistFromMaster: number;
|
|
232
|
+
};
|
|
233
|
+
up: {
|
|
234
|
+
upstreamInitialSync: number;
|
|
235
|
+
forkChangeStreamEmit: number;
|
|
236
|
+
processTasks: number;
|
|
237
|
+
persistToMaster: number;
|
|
238
|
+
persistToMasterHadConflicts: number;
|
|
239
|
+
persistToMasterConflictWrites: number;
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Used in checkpoints and ._meta fields
|
|
245
|
+
* to ensure we do not mix up meta data of
|
|
246
|
+
* different replications.
|
|
247
|
+
* We have to use the promise because the key is hashed which runs async.
|
|
248
|
+
*/
|
|
249
|
+
checkpointKey: Promise<string>;
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Storage.bulkWrites() that are initialized from the
|
|
253
|
+
* downstream, get this flag as context-param
|
|
254
|
+
* so that the emitted event bulk can be identified
|
|
255
|
+
* to be sourced from the downstream and it will not try
|
|
256
|
+
* to upstream these documents again.
|
|
257
|
+
*/
|
|
258
|
+
downstreamBulkWriteFlag: Promise<string>;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* If this is set to true, we do not store the documents
|
|
262
|
+
* assumed server state. This is set on pull-only replications
|
|
263
|
+
* we because when we do not push anyway, we do not have to store
|
|
264
|
+
* the server state of any document.
|
|
265
|
+
*/
|
|
266
|
+
skipStoringPullMeta: boolean;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Tracks if the streams have been in sync
|
|
270
|
+
* for at least one time.
|
|
271
|
+
*/
|
|
272
|
+
firstSyncDone: {
|
|
273
|
+
[direction in RxStorageReplicationDirection]: BehaviorSubject<boolean>;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Can be used to detect if the replication is doing something
|
|
278
|
+
* or if it is in an idle state.
|
|
279
|
+
*/
|
|
280
|
+
streamQueue: {
|
|
281
|
+
[direction in RxStorageReplicationDirection]: Promise<any>;
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
checkpointQueue: Promise<any>;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* For better performance we store the last known checkpoint
|
|
288
|
+
* document so that we can likely do checkpoint storing without
|
|
289
|
+
* conflicts.
|
|
290
|
+
*/
|
|
291
|
+
lastCheckpointDoc: {
|
|
292
|
+
[direction in RxStorageReplicationDirection]?: RxDocumentData<RxStorageReplicationMeta<RxDocType, any>>;
|
|
293
|
+
};
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
export type RxStorageReplicationDirection = 'up' | 'down';
|