@verdant-web/common 2.3.0-next.0 → 2.3.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.
Files changed (40) hide show
  1. package/dist/esm/EventSubscriber.d.ts +18 -0
  2. package/dist/esm/baseline.d.ts +5 -0
  3. package/dist/esm/batching.d.ts +43 -0
  4. package/dist/esm/error.d.ts +22 -0
  5. package/dist/esm/files.d.ts +20 -0
  6. package/dist/esm/index.d.ts +21 -0
  7. package/dist/esm/indexes.d.ts +17 -0
  8. package/dist/esm/indexes.test.d.ts +1 -0
  9. package/dist/esm/memo.d.ts +6 -0
  10. package/dist/esm/memo.test.d.ts +1 -0
  11. package/dist/esm/migration.d.ts +174 -0
  12. package/dist/esm/oids.d.ts +101 -0
  13. package/dist/esm/oids.test.d.ts +1 -0
  14. package/dist/esm/operation.d.ts +142 -0
  15. package/dist/esm/operation.test.d.ts +1 -0
  16. package/dist/esm/patch.d.ts +28 -0
  17. package/dist/esm/presence.d.ts +29 -0
  18. package/dist/esm/protocol.d.ts +145 -0
  19. package/dist/esm/refs.d.ts +7 -0
  20. package/dist/esm/replica.d.ts +28 -0
  21. package/dist/esm/schema/children.d.ts +2 -0
  22. package/dist/esm/schema/defaults.test.d.ts +1 -0
  23. package/dist/esm/schema/fieldHelpers.d.ts +35 -0
  24. package/dist/esm/schema/fields.d.ts +10 -0
  25. package/dist/esm/schema/index.d.ts +54 -0
  26. package/dist/esm/schema/indexFilters.d.ts +6 -0
  27. package/dist/esm/schema/types/collection.d.ts +23 -0
  28. package/dist/esm/schema/types/compounds.d.ts +11 -0
  29. package/dist/esm/schema/types/fields.d.ts +55 -0
  30. package/dist/esm/schema/types/filters.d.ts +29 -0
  31. package/dist/esm/schema/types/shapes.d.ts +25 -0
  32. package/dist/esm/schema/types/synthetics.d.ts +37 -0
  33. package/dist/esm/schema/types.d.ts +18 -0
  34. package/dist/esm/schema/validation.d.ts +14 -0
  35. package/dist/esm/timestamp.d.ts +51 -0
  36. package/dist/esm/timestamp.test.d.ts +1 -0
  37. package/dist/esm/undo.d.ts +3 -0
  38. package/dist/esm/utils.d.ts +20 -0
  39. package/dist/esm/utils.test.d.ts +1 -0
  40. package/package.json +1 -1
@@ -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,2 @@
1
+ import { StorageFieldSchema, StorageFieldsSchema } from './types.js';
2
+ export declare function getChildFieldSchema(schema: StorageFieldSchema | StorageFieldsSchema, key: string | number): StorageFieldSchema | null;
@@ -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 {};
@@ -0,0 +1,37 @@
1
+ import { StorageBooleanFieldSchema, StorageFieldsSchema, StorageNumberFieldSchema, StorageStringFieldSchema } from './fields.js';
2
+ import { ShapeFromFields } from './shapes.js';
3
+ export type StorageStringSyntheticSchema<Fields extends StorageFieldsSchema> = {
4
+ type: 'string';
5
+ compute: (value: ShapeFromFields<Fields>) => string | null;
6
+ };
7
+ export type StorageNumberSyntheticSchema<Fields extends StorageFieldsSchema> = {
8
+ type: 'number';
9
+ compute: (value: ShapeFromFields<Fields>) => number | null;
10
+ };
11
+ export type StorageBooleanSyntheticSchema<Fields extends StorageFieldsSchema> = {
12
+ type: 'boolean';
13
+ compute: (value: ShapeFromFields<Fields>) => boolean | null;
14
+ };
15
+ export type StorageStringArraySyntheticSchema<Fields extends StorageFieldsSchema> = {
16
+ type: 'string[]';
17
+ compute: (value: ShapeFromFields<Fields>) => string[];
18
+ };
19
+ export type StorageNumberArraySyntheticSchema<Fields extends StorageFieldsSchema> = {
20
+ type: 'number[]';
21
+ compute: (value: ShapeFromFields<Fields>) => number[];
22
+ };
23
+ export type StorageBooleanArraySyntheticSchema<Fields extends StorageFieldsSchema> = {
24
+ type: 'boolean[]';
25
+ compute: (value: ShapeFromFields<Fields>) => boolean[];
26
+ };
27
+ export type StorageDirectSyntheticSchema<Fields extends StorageFieldsSchema> = {
28
+ field: DirectIndexableFieldName<Fields>;
29
+ };
30
+ type DirectIndexableFields<Fields extends StorageFieldsSchema> = {
31
+ [K in keyof Fields as Fields[K] extends StorageStringFieldSchema ? K : Fields[K] extends StorageNumberFieldSchema ? K : Fields[K] extends StorageBooleanFieldSchema ? K : never]: any;
32
+ };
33
+ export type DirectIndexableFieldName<Fields extends StorageFieldsSchema> = keyof DirectIndexableFields<Fields> extends never ? string : keyof DirectIndexableFields<Fields>;
34
+ export type StorageSyntheticIndices<Fields extends StorageFieldsSchema> = Record<string, StorageSyntheticIndexSchema<Fields>>;
35
+ export type StorageSyntheticIndexSchema<Fields extends StorageFieldsSchema> = StorageStringSyntheticSchema<Fields> | StorageNumberSyntheticSchema<Fields> | StorageBooleanSyntheticSchema<Fields> | StorageStringArraySyntheticSchema<Fields> | StorageNumberArraySyntheticSchema<Fields> | StorageBooleanArraySyntheticSchema<Fields> | StorageDirectSyntheticSchema<Fields>;
36
+ export type IndexValueTag = Exclude<StorageSyntheticIndexSchema<any>, StorageDirectSyntheticSchema<any>>['type'];
37
+ export {};
@@ -0,0 +1,18 @@
1
+ import { StorageCollectionSchema } from './types/collection.js';
2
+ export * from './types/collection.js';
3
+ export * from './types/compounds.js';
4
+ export * from './types/fields.js';
5
+ export * from './types/filters.js';
6
+ export * from './types/shapes.js';
7
+ export * from './types/synthetics.js';
8
+ export type StorageSchema<Collections extends {
9
+ [k: string]: StorageCollectionSchema;
10
+ } = {
11
+ [k: string]: StorageCollectionSchema;
12
+ }> = {
13
+ version: number;
14
+ wip?: true;
15
+ collections: Collections;
16
+ };
17
+ export type SchemaCollectionName<Schema extends StorageSchema<any>> = Schema extends StorageSchema<infer Cs> ? Exclude<keyof Cs, number | symbol> : never;
18
+ export type SchemaCollection<Schema extends StorageSchema<any>, Name extends SchemaCollectionName<Schema>> = Schema extends StorageSchema<infer Cs> ? Cs[Name] : never;
@@ -0,0 +1,14 @@
1
+ import { StorageFieldSchema, StorageFieldsSchema } from './types.js';
2
+ export declare function validateEntity(schema: StorageFieldsSchema, entity: any): EntityValidationProblem | void;
3
+ export type EntityValidationProblem = {
4
+ type: 'null' | 'no-default' | 'invalid-type' | 'invalid-value' | 'invalid-key';
5
+ fieldPath: (string | number)[];
6
+ message: string;
7
+ };
8
+ export declare function validateEntityField({ field, value, fieldPath, depth, requireDefaults, }: {
9
+ field: StorageFieldSchema;
10
+ value: any;
11
+ fieldPath: (string | number)[];
12
+ depth?: number;
13
+ requireDefaults?: boolean;
14
+ }): EntityValidationProblem | undefined;
@@ -0,0 +1,51 @@
1
+ export interface TimestampProvider {
2
+ now(version: number): string;
3
+ update(remoteTimestamp: string): void;
4
+ zero(version: number): string;
5
+ getWallClockTime(timestamp: string): number;
6
+ }
7
+ export declare function encodeVersion(version: number | string): string;
8
+ export declare function OLD_encodeVersion(version: number | string): string;
9
+ export declare class NaiveTimestampProvider implements TimestampProvider {
10
+ counter: number;
11
+ now: (version: number | string) => string;
12
+ update: () => void;
13
+ zero: (version: number | string) => string;
14
+ getWallClockTime: (timestamp: string) => number;
15
+ }
16
+ export declare class HybridLogicalClockTimestampProvider implements TimestampProvider {
17
+ private latest;
18
+ private zeroCounter;
19
+ now: (version: string | number) => string;
20
+ /**
21
+ * @deprecated - use now() instead and update to latest format
22
+ */
23
+ OLD_now: (version: string | number) => string;
24
+ /** Get the current timer state. Does not increment counter. */
25
+ timerState: () => HLCTimestamp;
26
+ update: (remoteTimestamp: string) => void;
27
+ get: (version: string | number, raw: HLCTimestamp) => string;
28
+ zero: (version: string | number) => string;
29
+ getWallClockTime: typeof getWallClockTime;
30
+ }
31
+ interface HLCTimestamp {
32
+ time: number;
33
+ counter: number;
34
+ node: string;
35
+ }
36
+ export declare function serializeHlcTimestamp(ts: HLCTimestamp): string;
37
+ export declare function deserializeHlcTimestamp(clock: string): HLCTimestamp;
38
+ /**
39
+ * Below, converters for old-style timestamps are defined.
40
+ * These are for migrating older clients to the new format.
41
+ */
42
+ /**
43
+ * Converts a timestamp from the old format to the new format.
44
+ */
45
+ export declare function convertOldHlcTimestamp(ts: string): string;
46
+ export declare function OLD_serializeHlcTimestamp(ts: HLCTimestamp): string;
47
+ export declare function OLD_deserializeHlcTimestamp(clock: string): HLCTimestamp;
48
+ export declare function getTimestampSchemaVersion(timestamp: string): number;
49
+ export declare function compareTimestampSchemaVersions(a: string, b: string): number;
50
+ export declare function getWallClockTime(timestamp: string): number;
51
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { ObjectIdentifier } from './oids.js';
2
+ import { Operation } from './operation.js';
3
+ export declare function getUndoOperations(oid: ObjectIdentifier, initial: any, operations: Operation[], getNow: () => string): Operation[];
@@ -0,0 +1,20 @@
1
+ export declare function take<T extends object, Keys extends keyof T>(obj: T, keys: Keys[]): Pick<T, Keys>;
2
+ export declare function omit<T extends object, Keys extends keyof T>(obj: T, keys: Keys[]): Omit<T, Keys>;
3
+ export declare function getSortedIndex<T>(array: T[], insert: T, compare: (a: T, b: T) => number): number;
4
+ /**
5
+ * Consistently stringifies an object regardless
6
+ * of key insertion order
7
+ */
8
+ export declare function stableStringify(obj: any): string;
9
+ /**
10
+ * A version of structured cloning which preserves object identity
11
+ * references in the system.
12
+ */
13
+ export declare function cloneDeep<T>(obj: T, copyOids?: boolean): T;
14
+ export declare function hashObject(obj: any): string;
15
+ export declare function isObject(obj: any): any;
16
+ export declare function roughSizeOfObject(object: any): number;
17
+ export declare function assert(condition: any, message?: string): asserts condition;
18
+ export declare function generateId(length?: number): string;
19
+ export declare function findLastIndex<T>(array: T[], predicate: (item: T) => boolean): number;
20
+ export declare function debounce<T extends (...args: any[]) => any>(fn: T, wait: number): T;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@verdant-web/common",
3
- "version": "2.3.0-next.0",
3
+ "version": "2.3.0",
4
4
  "access": "public",
5
5
  "type": "module",
6
6
  "exports": {