@verdant-web/common 2.3.0-next.0 → 2.3.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/esm/EventSubscriber.d.ts +18 -0
- package/dist/esm/baseline.d.ts +5 -0
- package/dist/esm/batching.d.ts +43 -0
- package/dist/esm/error.d.ts +22 -0
- package/dist/esm/files.d.ts +20 -0
- package/dist/esm/index.d.ts +21 -0
- package/dist/esm/indexes.d.ts +17 -0
- package/dist/esm/indexes.test.d.ts +1 -0
- package/dist/esm/memo.d.ts +6 -0
- package/dist/esm/memo.test.d.ts +1 -0
- package/dist/esm/migration.d.ts +174 -0
- package/dist/esm/oids.d.ts +95 -0
- package/dist/esm/oids.js +4 -4
- package/dist/esm/oids.js.map +1 -1
- package/dist/esm/oids.test.d.ts +1 -0
- package/dist/esm/operation.d.ts +142 -0
- package/dist/esm/operation.test.d.ts +1 -0
- package/dist/esm/patch.d.ts +28 -0
- package/dist/esm/presence.d.ts +29 -0
- package/dist/esm/protocol.d.ts +145 -0
- package/dist/esm/refs.d.ts +7 -0
- package/dist/esm/replica.d.ts +28 -0
- package/dist/esm/schema/children.d.ts +2 -0
- package/dist/esm/schema/defaults.test.d.ts +1 -0
- package/dist/esm/schema/fieldHelpers.d.ts +35 -0
- package/dist/esm/schema/fields.d.ts +10 -0
- package/dist/esm/schema/index.d.ts +54 -0
- package/dist/esm/schema/indexFilters.d.ts +6 -0
- package/dist/esm/schema/types/collection.d.ts +23 -0
- package/dist/esm/schema/types/compounds.d.ts +11 -0
- package/dist/esm/schema/types/fields.d.ts +55 -0
- package/dist/esm/schema/types/filters.d.ts +29 -0
- package/dist/esm/schema/types/shapes.d.ts +25 -0
- package/dist/esm/schema/types/synthetics.d.ts +37 -0
- package/dist/esm/schema/types.d.ts +18 -0
- package/dist/esm/schema/validation.d.ts +14 -0
- package/dist/esm/timestamp.d.ts +51 -0
- package/dist/esm/timestamp.test.d.ts +1 -0
- package/dist/esm/undo.d.ts +3 -0
- package/dist/esm/utils.d.ts +20 -0
- package/dist/esm/utils.test.d.ts +1 -0
- package/package.json +1 -1
- package/src/oids.ts +6 -12
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { DocumentBaseline } from './baseline.js';
|
|
2
|
+
import { FileRef } from './files.js';
|
|
3
|
+
import { ObjectIdentifier } from './oids.js';
|
|
4
|
+
export type ObjectRef = {
|
|
5
|
+
'@@type': 'ref';
|
|
6
|
+
id: ObjectIdentifier;
|
|
7
|
+
};
|
|
8
|
+
export declare function isObjectRef(obj: any): obj is ObjectRef;
|
|
9
|
+
export type Normalized<T> = {
|
|
10
|
+
[key in keyof T]: T[key] extends Object ? ObjectRef : T[key];
|
|
11
|
+
};
|
|
12
|
+
export type PropertyName = string | number;
|
|
13
|
+
/**
|
|
14
|
+
* List patches can target a particular child list or
|
|
15
|
+
* nested lists. The first path item is the property path
|
|
16
|
+
* of the first child list, any subsequent values are nested
|
|
17
|
+
* list indices.
|
|
18
|
+
*/
|
|
19
|
+
export type PropertyValue = string | number | boolean | null | undefined | ObjectRef | FileRef;
|
|
20
|
+
interface BaseOperationPatch {
|
|
21
|
+
}
|
|
22
|
+
export interface OperationPatchInitialize extends BaseOperationPatch {
|
|
23
|
+
op: 'initialize';
|
|
24
|
+
value: any;
|
|
25
|
+
}
|
|
26
|
+
export interface OperationPatchSet extends BaseOperationPatch {
|
|
27
|
+
op: 'set';
|
|
28
|
+
name: PropertyName;
|
|
29
|
+
value: PropertyValue;
|
|
30
|
+
}
|
|
31
|
+
export interface OperationPatchRemove extends BaseOperationPatch {
|
|
32
|
+
op: 'remove';
|
|
33
|
+
name: PropertyName;
|
|
34
|
+
}
|
|
35
|
+
export interface OperationPatchListPush extends BaseOperationPatch {
|
|
36
|
+
op: 'list-push';
|
|
37
|
+
value: PropertyValue;
|
|
38
|
+
}
|
|
39
|
+
export interface OperationPatchListInsert extends BaseOperationPatch {
|
|
40
|
+
op: 'list-insert';
|
|
41
|
+
index: number;
|
|
42
|
+
value?: PropertyValue;
|
|
43
|
+
values?: PropertyValue[];
|
|
44
|
+
}
|
|
45
|
+
export interface OperationPatchListDelete extends BaseOperationPatch {
|
|
46
|
+
op: 'list-delete';
|
|
47
|
+
index: number;
|
|
48
|
+
count: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Optimal for lists of object references. Moves
|
|
52
|
+
* the selected item to the target index even if it
|
|
53
|
+
* is not at the original index anymore.
|
|
54
|
+
*/
|
|
55
|
+
export interface OperationPatchListMoveByRef extends BaseOperationPatch {
|
|
56
|
+
op: 'list-move-by-ref';
|
|
57
|
+
value: ObjectRef | FileRef;
|
|
58
|
+
index: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Suitable for any list move, whether object lists
|
|
62
|
+
* or primitive lists.
|
|
63
|
+
*/
|
|
64
|
+
export interface OperationPatchListMoveByIndex extends BaseOperationPatch {
|
|
65
|
+
op: 'list-move-by-index';
|
|
66
|
+
from: number;
|
|
67
|
+
to: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Removes all instances of the value from
|
|
71
|
+
* the list. Good for set behavior or removing
|
|
72
|
+
* a specific item even if it changes index
|
|
73
|
+
* from conflicts.
|
|
74
|
+
*/
|
|
75
|
+
export interface OperationPatchListRemove extends BaseOperationPatch {
|
|
76
|
+
op: 'list-remove';
|
|
77
|
+
value: PropertyValue;
|
|
78
|
+
only?: 'first' | 'last';
|
|
79
|
+
}
|
|
80
|
+
export interface OperationPatchListAdd extends BaseOperationPatch {
|
|
81
|
+
op: 'list-add';
|
|
82
|
+
value: PropertyValue;
|
|
83
|
+
}
|
|
84
|
+
export interface OperationPatchDelete extends BaseOperationPatch {
|
|
85
|
+
op: 'delete';
|
|
86
|
+
}
|
|
87
|
+
export interface OperationPatchTouch extends BaseOperationPatch {
|
|
88
|
+
op: 'touch';
|
|
89
|
+
}
|
|
90
|
+
export type OperationPatch = OperationPatchInitialize | OperationPatchSet | OperationPatchRemove | OperationPatchListPush | OperationPatchListInsert | OperationPatchListDelete | OperationPatchListMoveByRef | OperationPatchListMoveByIndex | OperationPatchListRemove | OperationPatchDelete | OperationPatchListAdd | OperationPatchTouch;
|
|
91
|
+
export type Operation = {
|
|
92
|
+
oid: ObjectIdentifier;
|
|
93
|
+
timestamp: string;
|
|
94
|
+
data: OperationPatch;
|
|
95
|
+
};
|
|
96
|
+
export declare function diffToPatches<T extends {
|
|
97
|
+
[key: string]: any;
|
|
98
|
+
} | any[]>(from: T, to: T, getNow: () => string, createSubId?: () => string, patches?: Operation[], options?: {
|
|
99
|
+
/**
|
|
100
|
+
* If an object is merged with another and the new one does not
|
|
101
|
+
* have an OID assigned, assume it is the same identity as previous
|
|
102
|
+
*/
|
|
103
|
+
mergeUnknownObjects?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* If an incoming value is not assigned on the new object, use the previous value.
|
|
106
|
+
* If false, undefined properties will erase the previous value.
|
|
107
|
+
*/
|
|
108
|
+
defaultUndefined?: boolean;
|
|
109
|
+
}): Operation[];
|
|
110
|
+
export declare function shallowDiffToPatches(from: any, to: any, getNow: () => string, patches?: Operation[]): Operation[];
|
|
111
|
+
/**
|
|
112
|
+
* Takes a basic object and constructs a patch list to create it and
|
|
113
|
+
* all of its nested objects.
|
|
114
|
+
*/
|
|
115
|
+
export declare function initialToPatches(initial: any, rootOid: ObjectIdentifier, getNow: () => string, createSubId?: () => string, patches?: Operation[]): Operation[];
|
|
116
|
+
export declare function shallowInitialToPatches(initial: any, rootOid: ObjectIdentifier, getNow: () => string, patches?: Operation[]): Operation[];
|
|
117
|
+
export declare function groupPatchesByOid(patches: Operation[]): Record<string, Operation[]>;
|
|
118
|
+
export declare function groupPatchesByRootOid(patches: Operation[]): Record<string, Operation[]>;
|
|
119
|
+
export declare function groupBaselinesByRootOid(baselines: DocumentBaseline[]): Record<string, DocumentBaseline[]>;
|
|
120
|
+
export type NormalizedObject = {
|
|
121
|
+
[key: PropertyName]: PropertyValue;
|
|
122
|
+
} | Array<PropertyValue>;
|
|
123
|
+
/**
|
|
124
|
+
* The incoming object should already be normalized!
|
|
125
|
+
* This function will mutate the base object.
|
|
126
|
+
*/
|
|
127
|
+
export declare function applyPatch<T extends NormalizedObject>(base: T | undefined, patch: OperationPatch,
|
|
128
|
+
/**
|
|
129
|
+
* Optionally supply a list to which any refs which
|
|
130
|
+
* are removed during the patch will be appended.
|
|
131
|
+
*/
|
|
132
|
+
deletedRefs?: (FileRef | ObjectRef)[]): T | undefined;
|
|
133
|
+
export declare function applyOperations<T extends NormalizedObject>(base: T | undefined, operations: Operation[], deletedRefs?: (ObjectRef | FileRef)[]): T | undefined;
|
|
134
|
+
/**
|
|
135
|
+
* Mutates the original object in place. Returns all referenced
|
|
136
|
+
* objects oids.
|
|
137
|
+
*/
|
|
138
|
+
export declare function substituteRefsWithObjects(base: any, refs: Map<ObjectIdentifier, any>, used?: ObjectIdentifier[]): ObjectIdentifier[];
|
|
139
|
+
export declare function substituteFirstLevelObjectsWithRefs<Base extends {
|
|
140
|
+
[key: string]: any;
|
|
141
|
+
} | any[]>(base: Base, refObjects?: Map<ObjectIdentifier, any>): Map<ObjectIdentifier, any>;
|
|
142
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level patch creation for use with complex nested objects.
|
|
3
|
+
*/
|
|
4
|
+
import { FileRef } from './files.js';
|
|
5
|
+
import { ObjectIdentifier } from './oids.js';
|
|
6
|
+
import { ObjectRef, Operation, PropertyName } from './operation.js';
|
|
7
|
+
export declare class PatchCreator {
|
|
8
|
+
private getNow;
|
|
9
|
+
private createSubId?;
|
|
10
|
+
constructor(getNow: () => string, createSubId?: (() => string) | undefined);
|
|
11
|
+
isPrimitive: (value: any) => boolean;
|
|
12
|
+
createDiff: (from: any, to: any, options?: {
|
|
13
|
+
mergeUnknownObjects?: boolean;
|
|
14
|
+
defaultUndefined?: boolean;
|
|
15
|
+
}) => Operation[];
|
|
16
|
+
createInitialize: (obj: any, oid: ObjectIdentifier) => Operation[];
|
|
17
|
+
createSet: (oid: ObjectIdentifier, key: PropertyName, value: any) => Operation[];
|
|
18
|
+
createRemove: (oid: ObjectIdentifier, key: PropertyName) => Operation[];
|
|
19
|
+
createListPush: (oid: ObjectIdentifier, value: any) => Operation[];
|
|
20
|
+
createListAdd: (oid: ObjectIdentifier, value: any) => Operation[];
|
|
21
|
+
createListInsert: (oid: ObjectIdentifier, index: number, value: any) => Operation[];
|
|
22
|
+
createListRemove: (oid: ObjectIdentifier, value: any, only?: 'first' | 'last') => Operation[];
|
|
23
|
+
createListDelete: (oid: ObjectIdentifier, index: number, count?: number) => Operation[];
|
|
24
|
+
createListMoveByRef: (oid: ObjectIdentifier, value: ObjectRef | FileRef, index: number) => Operation[];
|
|
25
|
+
createListMoveByIndex: (oid: ObjectIdentifier, fromIndex: number, toIndex: number) => Operation[];
|
|
26
|
+
createDelete: (oid: ObjectIdentifier) => Operation[];
|
|
27
|
+
createDeleteAll: (oids: ObjectIdentifier[]) => Operation[];
|
|
28
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface UserInfo<Profile, Presence> {
|
|
2
|
+
/**
|
|
3
|
+
* @deprecated - include the ID in your Profile data instead.
|
|
4
|
+
*
|
|
5
|
+
* This is the ID representing the user who is utilizing a
|
|
6
|
+
* replica client to connect to the storage network.
|
|
7
|
+
* One user may have multiple replica clients active at once,
|
|
8
|
+
* but their presence will only reflect the most recent
|
|
9
|
+
* replica used.
|
|
10
|
+
*/
|
|
11
|
+
id: string;
|
|
12
|
+
/**
|
|
13
|
+
* This is the ID representing the replica client that is
|
|
14
|
+
* connected to the storage network. This is used to
|
|
15
|
+
* identify the client when sending messages to it.
|
|
16
|
+
*/
|
|
17
|
+
replicaId: string;
|
|
18
|
+
/**
|
|
19
|
+
* This is the user's server profile. This data is associated
|
|
20
|
+
* with the logged in user of the app and cannot be modified
|
|
21
|
+
* by the local replica directly.
|
|
22
|
+
*/
|
|
23
|
+
profile: Profile;
|
|
24
|
+
/**
|
|
25
|
+
* Presence info which can update frequently as a replica
|
|
26
|
+
* makes changes. The shape of presence is up to you.
|
|
27
|
+
*/
|
|
28
|
+
presence: Presence;
|
|
29
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { DocumentBaseline } from './baseline.js';
|
|
2
|
+
import { Operation } from './operation.js';
|
|
3
|
+
import { UserInfo } from './presence.js';
|
|
4
|
+
export type HeartbeatMessage = {
|
|
5
|
+
type: 'heartbeat';
|
|
6
|
+
timestamp: string;
|
|
7
|
+
replicaId: string;
|
|
8
|
+
};
|
|
9
|
+
export type HeartbeatResponseMessage = {
|
|
10
|
+
type: 'heartbeat-response';
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Used by clients to indicate they have
|
|
14
|
+
* successfully applied all operations from the
|
|
15
|
+
* server up to this one. Uses the nonce from the
|
|
16
|
+
* operation rebroadcast message as the ack.
|
|
17
|
+
*/
|
|
18
|
+
export type AckMessage = {
|
|
19
|
+
type: 'ack';
|
|
20
|
+
replicaId: string;
|
|
21
|
+
timestamp?: string;
|
|
22
|
+
nonce?: string;
|
|
23
|
+
};
|
|
24
|
+
export type OperationMessage = {
|
|
25
|
+
type: 'op';
|
|
26
|
+
replicaId: string;
|
|
27
|
+
operations: Operation[];
|
|
28
|
+
timestamp: string;
|
|
29
|
+
};
|
|
30
|
+
export type OperationRebroadcastMessage = {
|
|
31
|
+
type: 'op-re';
|
|
32
|
+
operations: Operation[];
|
|
33
|
+
baselines?: DocumentBaseline[];
|
|
34
|
+
replicaId: string;
|
|
35
|
+
globalAckTimestamp: string | undefined;
|
|
36
|
+
ackThisNonce?: string;
|
|
37
|
+
};
|
|
38
|
+
export type SyncMessage = {
|
|
39
|
+
type: 'sync';
|
|
40
|
+
/** This client's replica ID */
|
|
41
|
+
replicaId: string;
|
|
42
|
+
/** the logical time this message was sent */
|
|
43
|
+
timestamp: string;
|
|
44
|
+
/** Any new operations created since the requested time */
|
|
45
|
+
operations: Operation[];
|
|
46
|
+
/** Any new baselines created since the requested time */
|
|
47
|
+
baselines: DocumentBaseline[];
|
|
48
|
+
/** the schema version known by this client */
|
|
49
|
+
schemaVersion: number;
|
|
50
|
+
/**
|
|
51
|
+
* the client may have lost its local data, in which
|
|
52
|
+
* case it may set this flag to be treated as a new client
|
|
53
|
+
* and receive a full baseline
|
|
54
|
+
*/
|
|
55
|
+
resyncAll?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* timestamp of when the replica changes began. null means
|
|
58
|
+
* full changeset from start of time
|
|
59
|
+
*/
|
|
60
|
+
since: string | null;
|
|
61
|
+
};
|
|
62
|
+
export type SyncResponseMessage = {
|
|
63
|
+
type: 'sync-resp';
|
|
64
|
+
operations: Operation[];
|
|
65
|
+
baselines: DocumentBaseline[];
|
|
66
|
+
/**
|
|
67
|
+
* If this flag is set, the client should discard local data
|
|
68
|
+
* and reset to incoming data only. Used when a client requested
|
|
69
|
+
* resyncAll in its sync message, or for clients which have been
|
|
70
|
+
* offline for too long. When specified true, provideChangesSince
|
|
71
|
+
* should be ignored.
|
|
72
|
+
*/
|
|
73
|
+
overwriteLocalData: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Update client on the global ack
|
|
76
|
+
*/
|
|
77
|
+
globalAckTimestamp: string | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* A map of connected clients' presences values
|
|
80
|
+
*/
|
|
81
|
+
peerPresence: Record<string, UserInfo<any, any>>;
|
|
82
|
+
/**
|
|
83
|
+
* The timestamp sent in the original sync message -
|
|
84
|
+
* this confirms the server has received the client's
|
|
85
|
+
* state up to this point. Subsequent syncs should not
|
|
86
|
+
* include operations or baselines older than this timestamp.
|
|
87
|
+
*/
|
|
88
|
+
ackedTimestamp: string;
|
|
89
|
+
/**
|
|
90
|
+
* The client should respond with a sync-ack containing
|
|
91
|
+
* this nonce to confirm it has received this message if
|
|
92
|
+
* it is not undefined
|
|
93
|
+
*/
|
|
94
|
+
ackThisNonce?: string;
|
|
95
|
+
};
|
|
96
|
+
/** @deprecated use ack */
|
|
97
|
+
export type SyncAckMessage = {
|
|
98
|
+
type: 'sync-ack';
|
|
99
|
+
/** The client's replica ID */
|
|
100
|
+
replicaId: string;
|
|
101
|
+
/** the logical time this message was sent */
|
|
102
|
+
timestamp: string;
|
|
103
|
+
/** the nonce sent in the sync-resp message */
|
|
104
|
+
nonce: string;
|
|
105
|
+
};
|
|
106
|
+
export type PresenceUpdateMessage = {
|
|
107
|
+
type: 'presence-update';
|
|
108
|
+
/** The client's replica ID */
|
|
109
|
+
replicaId: string;
|
|
110
|
+
/** new presence value */
|
|
111
|
+
presence: any;
|
|
112
|
+
};
|
|
113
|
+
export type PresenceChangedMessage = {
|
|
114
|
+
type: 'presence-changed';
|
|
115
|
+
/** The client's replica ID */
|
|
116
|
+
replicaId: string;
|
|
117
|
+
userInfo: UserInfo<any, any>;
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* This is only emitted when all of a user's replicas
|
|
121
|
+
* go offline.
|
|
122
|
+
*/
|
|
123
|
+
export type PresenceOfflineMessage = {
|
|
124
|
+
type: 'presence-offline';
|
|
125
|
+
userId: string;
|
|
126
|
+
/** The last replicaID seen by the server before the user was offline */
|
|
127
|
+
replicaId: string;
|
|
128
|
+
};
|
|
129
|
+
export type GlobalAckMessage = {
|
|
130
|
+
type: 'global-ack';
|
|
131
|
+
timestamp: string;
|
|
132
|
+
};
|
|
133
|
+
export type ForbiddenMessage = {
|
|
134
|
+
type: 'forbidden';
|
|
135
|
+
};
|
|
136
|
+
export type ServerAckMessage = {
|
|
137
|
+
type: 'server-ack';
|
|
138
|
+
timestamp: string;
|
|
139
|
+
};
|
|
140
|
+
export type ServerNeedSinceMessage = {
|
|
141
|
+
type: 'need-since';
|
|
142
|
+
since: string | null;
|
|
143
|
+
};
|
|
144
|
+
export type ClientMessage = HeartbeatMessage | SyncMessage | OperationMessage | AckMessage | SyncAckMessage | PresenceUpdateMessage;
|
|
145
|
+
export type ServerMessage = HeartbeatResponseMessage | SyncResponseMessage | OperationRebroadcastMessage | PresenceChangedMessage | PresenceOfflineMessage | GlobalAckMessage | ForbiddenMessage | ServerAckMessage | ServerNeedSinceMessage;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FileRef } from './files.js';
|
|
2
|
+
import { ObjectRef } from './operation.js';
|
|
3
|
+
export declare function isRef(obj: any): obj is ObjectRef | FileRef;
|
|
4
|
+
export declare function compareRefs(a: any, b: any): boolean;
|
|
5
|
+
export type Ref = ObjectRef | FileRef;
|
|
6
|
+
export declare function makeObjectRef(oid: string): ObjectRef;
|
|
7
|
+
export declare function makeFileRef(oid: string): FileRef;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface ReplicaInfo {
|
|
2
|
+
id: string;
|
|
3
|
+
ackedLogicalTime: string | null;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Different token types allow different replica client behaviors.
|
|
7
|
+
* - Realtime: allows the client to subscribe to realtime events.
|
|
8
|
+
* - Push: allows the client to push and pull data with HTTP, but not use realtime.
|
|
9
|
+
* - PassivePush: allows the client to push and pull data with HTTP, but offline changes
|
|
10
|
+
* will be discarded on reconnect.
|
|
11
|
+
* - PassiveRealtime: allows the client to subscribe to realtime events, but offline changes
|
|
12
|
+
* will be discarded on reconnect.
|
|
13
|
+
* - ReadOnlyPull: the client may only pull changes using HTTP. It may not subscribe
|
|
14
|
+
* to realtime events or push changes.
|
|
15
|
+
* - ReadOnlyRealtime: the client may only subscribe to realtime events or pull from HTTP.
|
|
16
|
+
* It may not push changes.
|
|
17
|
+
*
|
|
18
|
+
* Choosing the right token type can optimize client storage metrics significantly when
|
|
19
|
+
* many replicas are connecting to a library.
|
|
20
|
+
*/
|
|
21
|
+
export declare enum ReplicaType {
|
|
22
|
+
Realtime = 0,
|
|
23
|
+
Push = 1,
|
|
24
|
+
PassiveRealtime = 2,
|
|
25
|
+
PassivePush = 3,
|
|
26
|
+
ReadOnlyPull = 4,
|
|
27
|
+
ReadOnlyRealtime = 5
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ShapeFromFieldsWithDefaults, StorageAnyFieldSchema, StorageArrayFieldSchema, StorageBooleanFieldSchema, StorageFieldSchema, StorageFieldsSchema, StorageFileFieldSchema, StorageMapFieldSchema, StorageNumberFieldSchema, StorageObjectFieldSchema, StorageStringFieldSchema } from './types.js';
|
|
2
|
+
export declare const fields: {
|
|
3
|
+
object: <Props extends StorageFieldsSchema>(args: {
|
|
4
|
+
properties: Props;
|
|
5
|
+
nullable?: boolean;
|
|
6
|
+
default?: ShapeFromFieldsWithDefaults<Props> | (() => ShapeFromFieldsWithDefaults<Props>);
|
|
7
|
+
}) => StorageObjectFieldSchema<Props>;
|
|
8
|
+
array: <T extends StorageFieldSchema>(args: {
|
|
9
|
+
items: T;
|
|
10
|
+
nullable?: boolean;
|
|
11
|
+
}) => StorageArrayFieldSchema<T>;
|
|
12
|
+
string: (args?: {
|
|
13
|
+
nullable?: boolean;
|
|
14
|
+
default?: string | (() => string);
|
|
15
|
+
options?: string[];
|
|
16
|
+
}) => StorageStringFieldSchema;
|
|
17
|
+
number: (args?: {
|
|
18
|
+
nullable?: boolean;
|
|
19
|
+
default?: number | (() => number);
|
|
20
|
+
}) => StorageNumberFieldSchema;
|
|
21
|
+
boolean: (args?: {
|
|
22
|
+
nullable?: boolean;
|
|
23
|
+
default?: boolean | (() => boolean);
|
|
24
|
+
}) => StorageBooleanFieldSchema;
|
|
25
|
+
any: <TShape>(args?: {
|
|
26
|
+
default?: TShape;
|
|
27
|
+
}) => StorageAnyFieldSchema<TShape>;
|
|
28
|
+
map: <T_1 extends StorageFieldSchema>(args: {
|
|
29
|
+
values: T_1;
|
|
30
|
+
}) => StorageMapFieldSchema<T_1>;
|
|
31
|
+
file: (args?: {
|
|
32
|
+
nullable?: boolean;
|
|
33
|
+
downloadRemote?: boolean;
|
|
34
|
+
}) => StorageFileFieldSchema;
|
|
35
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { StorageFieldSchema, StorageCollectionSchema } from './types.js';
|
|
2
|
+
export declare function isNullable(field: StorageFieldSchema): boolean | undefined;
|
|
3
|
+
export declare function hasDefault(field: StorageFieldSchema | undefined): boolean;
|
|
4
|
+
export declare function getDefault(field: StorageFieldSchema | undefined): any;
|
|
5
|
+
export declare function isPrunePoint(field: StorageFieldSchema): boolean;
|
|
6
|
+
export declare function addFieldDefaults(collection: StorageCollectionSchema, value: any): any;
|
|
7
|
+
export declare function traverseCollectionFieldsAndApplyDefaults(value: any, field: StorageFieldSchema): any;
|
|
8
|
+
export declare function getFieldDefault(field: StorageFieldSchema): any;
|
|
9
|
+
export declare function removeExtraProperties(collection: StorageCollectionSchema, value: any): any;
|
|
10
|
+
export declare function traverseCollectionFieldsAndRemoveExtraProperties(value: any, field: StorageFieldSchema): void;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { CollectionCompoundIndices, StorageCollectionSchema, StorageFieldsSchema, StorageSchema, StorageSyntheticIndices } from './types.js';
|
|
2
|
+
export declare function collection<Fields extends StorageFieldsSchema, Synthetics extends StorageSyntheticIndices<Fields>, Compounds extends CollectionCompoundIndices<Fields, Synthetics>>({ synthetics, indexes, ...input }: StorageCollectionSchema<Fields, Synthetics, Compounds>): StorageCollectionSchema<Fields, Synthetics, Compounds>;
|
|
3
|
+
export declare function schema<Schema extends StorageSchema<{
|
|
4
|
+
[key: string]: StorageCollectionSchema<any, any, any>;
|
|
5
|
+
}>>(input: Schema): StorageSchema;
|
|
6
|
+
export declare namespace schema {
|
|
7
|
+
var collection: typeof import("./index.js").collection;
|
|
8
|
+
var fields: {
|
|
9
|
+
object: <Props extends StorageFieldsSchema>(args: {
|
|
10
|
+
properties: Props;
|
|
11
|
+
nullable?: boolean | undefined;
|
|
12
|
+
default?: import("./types.js").ShapeFromFieldsWithDefaults<Props> | (() => import("./types.js").ShapeFromFieldsWithDefaults<Props>) | undefined;
|
|
13
|
+
}) => import("./types.js").StorageObjectFieldSchema<Props>;
|
|
14
|
+
array: <T extends import("./types.js").StorageFieldSchema>(args: {
|
|
15
|
+
items: T;
|
|
16
|
+
nullable?: boolean | undefined;
|
|
17
|
+
}) => import("./types.js").StorageArrayFieldSchema<T>;
|
|
18
|
+
string: (args?: {
|
|
19
|
+
nullable?: boolean | undefined;
|
|
20
|
+
default?: string | (() => string) | undefined;
|
|
21
|
+
options?: string[] | undefined;
|
|
22
|
+
} | undefined) => import("./types.js").StorageStringFieldSchema;
|
|
23
|
+
number: (args?: {
|
|
24
|
+
nullable?: boolean | undefined;
|
|
25
|
+
default?: number | (() => number) | undefined;
|
|
26
|
+
} | undefined) => import("./types.js").StorageNumberFieldSchema;
|
|
27
|
+
boolean: (args?: {
|
|
28
|
+
nullable?: boolean | undefined;
|
|
29
|
+
default?: boolean | (() => boolean) | undefined;
|
|
30
|
+
} | undefined) => import("./types.js").StorageBooleanFieldSchema;
|
|
31
|
+
any: <TShape>(args?: {
|
|
32
|
+
default?: TShape | undefined;
|
|
33
|
+
} | undefined) => import("./types.js").StorageAnyFieldSchema<TShape>;
|
|
34
|
+
map: <T_1 extends import("./types.js").StorageFieldSchema>(args: {
|
|
35
|
+
values: T_1;
|
|
36
|
+
}) => import("./types.js").StorageMapFieldSchema<T_1>;
|
|
37
|
+
file: (args?: {
|
|
38
|
+
nullable?: boolean | undefined;
|
|
39
|
+
downloadRemote?: boolean | undefined;
|
|
40
|
+
} | undefined) => import("./types.js").StorageFileFieldSchema;
|
|
41
|
+
};
|
|
42
|
+
var generated: {
|
|
43
|
+
id: (() => string) & {
|
|
44
|
+
slug: () => string;
|
|
45
|
+
isCuid: (cuid: string) => boolean;
|
|
46
|
+
isSlug: (slug: string) => boolean;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export * from './types.js';
|
|
51
|
+
export * from './indexFilters.js';
|
|
52
|
+
export * from './fields.js';
|
|
53
|
+
export * from './validation.js';
|
|
54
|
+
export * from './children.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CollectionCompoundIndexFilter, CollectionFilter, MatchCollectionIndexFilter, RangeCollectionIndexFilter, SortIndexFilter, StartsWithIndexFilter } from './types.js';
|
|
2
|
+
export declare function isMatchIndexFilter(filter: CollectionFilter): filter is MatchCollectionIndexFilter;
|
|
3
|
+
export declare function isRangeIndexFilter(filter: CollectionFilter): filter is RangeCollectionIndexFilter;
|
|
4
|
+
export declare function isCompoundIndexFilter(filter: CollectionFilter): filter is CollectionCompoundIndexFilter;
|
|
5
|
+
export declare function isStartsWithIndexFilter(filter: CollectionFilter): filter is StartsWithIndexFilter;
|
|
6
|
+
export declare function isSortIndexFilter(filter: CollectionFilter): filter is SortIndexFilter;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CollectionCompoundIndices } from './compounds.js';
|
|
2
|
+
import { StorageFieldsSchema } from './fields.js';
|
|
3
|
+
import { DirectIndexableFieldName, StorageSyntheticIndices } from './synthetics.js';
|
|
4
|
+
/**
|
|
5
|
+
* The main collection schema
|
|
6
|
+
*/
|
|
7
|
+
export type StorageCollectionSchema<Fields extends StorageFieldsSchema = StorageFieldsSchema, Synthetics extends StorageSyntheticIndices<Fields> = StorageSyntheticIndices<Fields>, Compounds extends CollectionCompoundIndices<Fields, Synthetics> = CollectionCompoundIndices<Fields, Synthetics>> = {
|
|
8
|
+
name: string;
|
|
9
|
+
/**
|
|
10
|
+
* Your primary key must be a string, number, or boolean field. It must also
|
|
11
|
+
* not be rewritten.
|
|
12
|
+
*/
|
|
13
|
+
primaryKey: DirectIndexableFieldName<Fields>;
|
|
14
|
+
fields: Fields;
|
|
15
|
+
indexes?: Synthetics;
|
|
16
|
+
compounds?: Compounds;
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated - plural name is the key used to index this collection in the schema. this field is no longer used.
|
|
19
|
+
*/
|
|
20
|
+
pluralName?: string;
|
|
21
|
+
/** @deprecated - use "indexes" */
|
|
22
|
+
synthetics?: Synthetics;
|
|
23
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StorageArrayFieldSchema, StorageBooleanFieldSchema, StorageFieldsSchema, StorageNumberFieldSchema, StorageStringFieldSchema } from './fields.js';
|
|
2
|
+
import { DirectIndexableFieldName, StorageSyntheticIndices } from './synthetics.js';
|
|
3
|
+
type PrimitiveArrayFields<Fields extends StorageFieldsSchema> = {
|
|
4
|
+
[K in keyof Fields as Fields[K] extends StorageArrayFieldSchema<infer U> ? U extends StorageStringFieldSchema | StorageNumberFieldSchema | StorageBooleanFieldSchema ? K : never : never]: Fields[K];
|
|
5
|
+
};
|
|
6
|
+
type PrimitiveArrayFieldName<Fields extends StorageFieldsSchema> = Extract<keyof PrimitiveArrayFields<Fields>, string>;
|
|
7
|
+
export type CollectionCompoundIndex<Fields extends StorageFieldsSchema, Synthetics extends StorageSyntheticIndices<Fields>> = {
|
|
8
|
+
of: (DirectIndexableFieldName<Fields> | PrimitiveArrayFieldName<Fields> | Extract<keyof Synthetics, string>)[];
|
|
9
|
+
};
|
|
10
|
+
export type CollectionCompoundIndices<Fields extends StorageFieldsSchema, Synthetics extends StorageSyntheticIndices<Fields>> = Record<string, CollectionCompoundIndex<Fields, Synthetics>>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export type StorageStringFieldSchema = {
|
|
2
|
+
type: 'string';
|
|
3
|
+
nullable?: boolean;
|
|
4
|
+
default?: string | (() => string);
|
|
5
|
+
/** Limit the values to a certain set of options */
|
|
6
|
+
options?: string[];
|
|
7
|
+
};
|
|
8
|
+
export type StorageNumberFieldSchema = {
|
|
9
|
+
type: 'number';
|
|
10
|
+
nullable?: boolean;
|
|
11
|
+
default?: number | (() => number);
|
|
12
|
+
};
|
|
13
|
+
export type StorageBooleanFieldSchema = {
|
|
14
|
+
type: 'boolean';
|
|
15
|
+
nullable?: boolean;
|
|
16
|
+
default?: boolean | (() => boolean);
|
|
17
|
+
};
|
|
18
|
+
export type StorageArrayFieldSchema<TItems extends StorageFieldSchema> = {
|
|
19
|
+
type: 'array';
|
|
20
|
+
items: TItems;
|
|
21
|
+
nullable?: boolean;
|
|
22
|
+
};
|
|
23
|
+
export type StorageObjectFieldSchema<Props extends StorageFieldsSchema> = {
|
|
24
|
+
type: 'object';
|
|
25
|
+
properties: Props;
|
|
26
|
+
nullable?: boolean;
|
|
27
|
+
default?: Record<string, any> | (() => Record<string, any>);
|
|
28
|
+
};
|
|
29
|
+
export type StorageAnyFieldSchema<TShape = any> = {
|
|
30
|
+
type: 'any';
|
|
31
|
+
default?: TShape;
|
|
32
|
+
};
|
|
33
|
+
export type StorageMapFieldSchema<V extends StorageFieldSchema> = {
|
|
34
|
+
type: 'map';
|
|
35
|
+
values: V;
|
|
36
|
+
};
|
|
37
|
+
export type StorageFileFieldSchema = {
|
|
38
|
+
type: 'file';
|
|
39
|
+
nullable?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Instructs the client to download synced files to local storage on first request for offline use.
|
|
42
|
+
* Leave this false to save storage space on the client, at the cost of requiring a network
|
|
43
|
+
* connection to use files created by other devices.
|
|
44
|
+
*/
|
|
45
|
+
downloadRemote?: boolean;
|
|
46
|
+
};
|
|
47
|
+
export type StorageFieldSchema = StorageStringFieldSchema | StorageNumberFieldSchema | StorageBooleanFieldSchema | StorageArrayFieldSchema<any> | StorageObjectFieldSchema<any> | StorageAnyFieldSchema | StorageMapFieldSchema<any> | StorageFileFieldSchema;
|
|
48
|
+
export type StorageFieldsSchema = {
|
|
49
|
+
[key: string]: StorageFieldSchema;
|
|
50
|
+
};
|
|
51
|
+
export type StorageIndexableFields<Fields extends StorageFieldsSchema> = {
|
|
52
|
+
[K in keyof Fields]: Fields[K] extends {
|
|
53
|
+
indexed: boolean;
|
|
54
|
+
} ? K : never;
|
|
55
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type MatchCollectionIndexFilter = {
|
|
2
|
+
where: string;
|
|
3
|
+
equals: any;
|
|
4
|
+
order?: 'asc' | 'desc';
|
|
5
|
+
};
|
|
6
|
+
export type RangeCollectionIndexFilter = {
|
|
7
|
+
where: string;
|
|
8
|
+
gte?: any;
|
|
9
|
+
lte?: any;
|
|
10
|
+
gt?: any;
|
|
11
|
+
lt?: any;
|
|
12
|
+
order?: 'asc' | 'desc';
|
|
13
|
+
};
|
|
14
|
+
export type CollectionCompoundIndexFilter = {
|
|
15
|
+
where: string;
|
|
16
|
+
match: Record<string, any>;
|
|
17
|
+
order: 'asc' | 'desc';
|
|
18
|
+
};
|
|
19
|
+
export type SortIndexFilter = {
|
|
20
|
+
where: string;
|
|
21
|
+
order: 'asc' | 'desc';
|
|
22
|
+
};
|
|
23
|
+
export type StartsWithIndexFilter = {
|
|
24
|
+
where: string;
|
|
25
|
+
startsWith: string;
|
|
26
|
+
order?: 'asc' | 'desc';
|
|
27
|
+
};
|
|
28
|
+
export type CollectionIndexFilter = MatchCollectionIndexFilter | RangeCollectionIndexFilter | CollectionCompoundIndexFilter | StartsWithIndexFilter | SortIndexFilter;
|
|
29
|
+
export type CollectionFilter = CollectionIndexFilter;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import { StorageCollectionSchema } from './collection.js';
|
|
3
|
+
import { StorageArrayFieldSchema, StorageFieldSchema, StorageFieldsSchema, StorageMapFieldSchema, StorageObjectFieldSchema } from './fields.js';
|
|
4
|
+
type StoragePropertyIsNullable<T extends StorageFieldSchema> = T extends {
|
|
5
|
+
nullable?: boolean;
|
|
6
|
+
} ? T['nullable'] extends boolean ? true : false : T['type'] extends 'any' ? true : false;
|
|
7
|
+
export type BaseShapeFromProperty<T extends StorageFieldSchema> = T['type'] extends 'string' ? string : T['type'] extends 'number' ? number : T['type'] extends 'boolean' ? boolean : T extends StorageArrayFieldSchema<infer U> ? ShapeFromProperty<U>[] : T extends StorageObjectFieldSchema<infer U> ? ShapeFromFields<U> : T extends StorageMapFieldSchema<any> ? Record<string, ShapeFromProperty<T['values']>> : T['type'] extends 'any' ? any : T['type'] extends 'file' ? File : never;
|
|
8
|
+
export type ShapeFromProperty<T extends StorageFieldSchema> = StoragePropertyIsNullable<T> extends true ? BaseShapeFromProperty<T> | null : BaseShapeFromProperty<T>;
|
|
9
|
+
export type ShapeFromFields<T extends StorageFieldsSchema> = {
|
|
10
|
+
[K in keyof T]: ShapeFromProperty<T[K]>;
|
|
11
|
+
};
|
|
12
|
+
export type StorageDocument<Collection extends StorageCollectionSchema<any, any, any>> = ShapeFromFields<Collection['fields']>;
|
|
13
|
+
type StoragePropertyIsOptional<T extends StorageFieldSchema> = StoragePropertyIsNullable<T> extends true ? true : T extends {
|
|
14
|
+
default?: any;
|
|
15
|
+
} ? true : T['type'] extends 'any' ? true : T['type'] extends 'array' ? true : T['type'] extends 'map' ? true : false;
|
|
16
|
+
export type ShapeFromFieldsWithDefaults<T extends StorageFieldsSchema> = {
|
|
17
|
+
[K in keyof T as StoragePropertyIsOptional<T[K]> extends true ? K : never]?: ShapeFromProperty<T[K]>;
|
|
18
|
+
} & {
|
|
19
|
+
[K in keyof T as StoragePropertyIsOptional<T[K]> extends true ? never : K]: ShapeFromProperty<T[K]>;
|
|
20
|
+
};
|
|
21
|
+
export type StorageDocumentInit<Collection extends StorageCollectionSchema<any, any, any>> = ShapeFromFieldsWithDefaults<Collection['fields']>;
|
|
22
|
+
export type FieldsFromShape<Shape extends Record<string, unknown>> = {
|
|
23
|
+
[K in keyof Shape]: StorageFieldSchema;
|
|
24
|
+
};
|
|
25
|
+
export {};
|