@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,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,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
package/src/oids.ts
CHANGED
|
@@ -12,22 +12,16 @@ import { isObject, assert } from './utils.js';
|
|
|
12
12
|
* on its own and associating it back to its parent.
|
|
13
13
|
*
|
|
14
14
|
* An OID is structured as such:
|
|
15
|
-
* <collection>/<root id
|
|
15
|
+
* <collection>/<root id>:<random>
|
|
16
16
|
*
|
|
17
17
|
* OIDs have a few characteristics:
|
|
18
18
|
* - They include the collection name of the parent document
|
|
19
19
|
* - They include the primary key of the parent document
|
|
20
|
-
* - They include
|
|
21
|
-
* - They include a random sequence to identify different objects which
|
|
22
|
-
* exist at the same key path
|
|
20
|
+
* - They may include a random sequence to identify sub-objects
|
|
23
21
|
*
|
|
24
22
|
* Collection name and document key are used to link any isolated
|
|
25
23
|
* object back to its parent document.
|
|
26
24
|
*
|
|
27
|
-
* The key path is used for authorization - to associate the object
|
|
28
|
-
* (or an operation related to it by OID) with the field it inhabits
|
|
29
|
-
* to utilize authorization rules from that field in the schema.
|
|
30
|
-
*
|
|
31
25
|
* The random sequence allows the application to encode different
|
|
32
26
|
* identities for objects at the same position in a document for
|
|
33
27
|
* conflict resolution purposes
|
|
@@ -127,7 +121,7 @@ export function ensureCompatibleOid(
|
|
|
127
121
|
}
|
|
128
122
|
}
|
|
129
123
|
|
|
130
|
-
const
|
|
124
|
+
const SANITIZE_PLACEHOLDERS = {
|
|
131
125
|
'.': '˙',
|
|
132
126
|
'/': '&slash;',
|
|
133
127
|
':': ':',
|
|
@@ -135,9 +129,9 @@ const SANTIIZE_PLACEHOLDERS = {
|
|
|
135
129
|
function sanitizeFragment(id: string) {
|
|
136
130
|
// replaces separator characters with placeholders
|
|
137
131
|
return id
|
|
138
|
-
.replace(/[/]/g,
|
|
139
|
-
.replace(/[:]/g,
|
|
140
|
-
.replace(/[.]/g,
|
|
132
|
+
.replace(/[/]/g, SANITIZE_PLACEHOLDERS['/'])
|
|
133
|
+
.replace(/[:]/g, SANITIZE_PLACEHOLDERS[':'])
|
|
134
|
+
.replace(/[.]/g, SANITIZE_PLACEHOLDERS['.']);
|
|
141
135
|
}
|
|
142
136
|
function unsanitizeFragment(id: string) {
|
|
143
137
|
// replaces placeholders with separator characters
|