@peerbit/log 1.0.2
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/LICENSE +23 -0
- package/README.md +11 -0
- package/lib/esm/change.d.ts +5 -0
- package/lib/esm/change.js +2 -0
- package/lib/esm/change.js.map +1 -0
- package/lib/esm/clock.d.ts +87 -0
- package/lib/esm/clock.js +260 -0
- package/lib/esm/clock.js.map +1 -0
- package/lib/esm/difference.d.ts +1 -0
- package/lib/esm/difference.js +20 -0
- package/lib/esm/difference.js.map +1 -0
- package/lib/esm/encoding.d.ts +7 -0
- package/lib/esm/encoding.js +20 -0
- package/lib/esm/encoding.js.map +1 -0
- package/lib/esm/entry-index.d.ts +21 -0
- package/lib/esm/entry-index.js +63 -0
- package/lib/esm/entry-index.js.map +1 -0
- package/lib/esm/entry-with-refs.d.ts +5 -0
- package/lib/esm/entry-with-refs.js +2 -0
- package/lib/esm/entry-with-refs.js.map +1 -0
- package/lib/esm/entry.d.ts +179 -0
- package/lib/esm/entry.js +591 -0
- package/lib/esm/entry.js.map +1 -0
- package/lib/esm/find-uniques.d.ts +1 -0
- package/lib/esm/find-uniques.js +12 -0
- package/lib/esm/find-uniques.js.map +1 -0
- package/lib/esm/heads-cache.d.ts +64 -0
- package/lib/esm/heads-cache.js +317 -0
- package/lib/esm/heads-cache.js.map +1 -0
- package/lib/esm/heads.d.ts +63 -0
- package/lib/esm/heads.js +143 -0
- package/lib/esm/heads.js.map +1 -0
- package/lib/esm/hrtime.d.ts +5 -0
- package/lib/esm/hrtime.js +71 -0
- package/lib/esm/hrtime.js.map +1 -0
- package/lib/esm/index.d.ts +11 -0
- package/lib/esm/index.js +11 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/is-defined.d.ts +1 -0
- package/lib/esm/is-defined.js +2 -0
- package/lib/esm/is-defined.js.map +1 -0
- package/lib/esm/log-errors.d.ts +5 -0
- package/lib/esm/log-errors.js +6 -0
- package/lib/esm/log-errors.js.map +1 -0
- package/lib/esm/log-sorting.d.ts +44 -0
- package/lib/esm/log-sorting.js +86 -0
- package/lib/esm/log-sorting.js.map +1 -0
- package/lib/esm/log.d.ts +205 -0
- package/lib/esm/log.js +1004 -0
- package/lib/esm/log.js.map +1 -0
- package/lib/esm/logger.d.ts +2 -0
- package/lib/esm/logger.js +4 -0
- package/lib/esm/logger.js.map +1 -0
- package/lib/esm/package.json +3 -0
- package/lib/esm/snapshot.d.ts +22 -0
- package/lib/esm/snapshot.js +83 -0
- package/lib/esm/snapshot.js.map +1 -0
- package/lib/esm/trim.d.ts +49 -0
- package/lib/esm/trim.js +203 -0
- package/lib/esm/trim.js.map +1 -0
- package/lib/esm/types.d.ts +6 -0
- package/lib/esm/types.js +23 -0
- package/lib/esm/types.js.map +1 -0
- package/lib/esm/utils.d.ts +2 -0
- package/lib/esm/utils.js +3 -0
- package/lib/esm/utils.js.map +1 -0
- package/lib/esm/values.d.ts +33 -0
- package/lib/esm/values.js +141 -0
- package/lib/esm/values.js.map +1 -0
- package/package.json +79 -0
- package/src/change.ts +2 -0
- package/src/clock.ts +280 -0
- package/src/difference.ts +22 -0
- package/src/encoding.ts +27 -0
- package/src/entry-index.ts +78 -0
- package/src/entry-with-refs.ts +6 -0
- package/src/entry.ts +749 -0
- package/src/find-uniques.ts +14 -0
- package/src/heads-cache.ts +400 -0
- package/src/heads.ts +208 -0
- package/src/hrtime.ts +78 -0
- package/src/index.ts +11 -0
- package/src/is-defined.ts +1 -0
- package/src/log-errors.ts +9 -0
- package/src/log-sorting.ts +108 -0
- package/src/log.ts +1262 -0
- package/src/logger.ts +3 -0
- package/src/snapshot.ts +103 -0
- package/src/trim.ts +269 -0
- package/src/types.ts +12 -0
- package/src/utils.ts +2 -0
- package/src/values.ts +193 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const BlockStoreNotDefinedError = () =>
|
|
2
|
+
new Error("Block store not defined");
|
|
3
|
+
export const LogNotDefinedError = () => new Error("Log instance not defined");
|
|
4
|
+
export const NotALogError = () =>
|
|
5
|
+
new Error("Given argument is not an instance of Log");
|
|
6
|
+
export const CannotJoinWithDifferentId = () =>
|
|
7
|
+
new Error("Can't join logs with different IDs");
|
|
8
|
+
export const LtOrLteMustBeStringOrArray = () =>
|
|
9
|
+
new Error("lt or lte must be a string or array of Entries");
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Entry } from "./entry.js";
|
|
2
|
+
import { LamportClock as Clock } from "./clock.js";
|
|
3
|
+
import { compare } from "@peerbit/uint8arrays";
|
|
4
|
+
|
|
5
|
+
const First = (a: any, b: any) => a;
|
|
6
|
+
|
|
7
|
+
export type ISortFunction = <T>(
|
|
8
|
+
a: Entry<T>,
|
|
9
|
+
b: Entry<T>,
|
|
10
|
+
resolveConflict?: (a: Entry<T>, b: Entry<T>) => number
|
|
11
|
+
) => number;
|
|
12
|
+
/**
|
|
13
|
+
* Sort two entries as Last-Write-Wins (LWW).
|
|
14
|
+
*
|
|
15
|
+
* Last Write Wins is a conflict resolution strategy for sorting elements
|
|
16
|
+
* where the element with a greater clock (latest) is chosen as the winner.
|
|
17
|
+
*
|
|
18
|
+
* @param {Entry} a First entry
|
|
19
|
+
* @param {Entry} b Second entry
|
|
20
|
+
* @returns {number} 1 if a is latest, -1 if b is latest
|
|
21
|
+
*/
|
|
22
|
+
export const LastWriteWins: ISortFunction = <T>(a: Entry<T>, b: Entry<T>) => {
|
|
23
|
+
// Ultimate conflict resolution (take the first/left arg)
|
|
24
|
+
// Sort two entries by their clock id, if the same always take the first
|
|
25
|
+
const sortById = (a: Entry<T>, b: Entry<T>) => SortByClockId(a, b, First);
|
|
26
|
+
// Sort two entries by their clock time, if concurrent,
|
|
27
|
+
// determine sorting using provided conflict resolution function
|
|
28
|
+
const sortByEntryClocks = (a: Entry<T>, b: Entry<T>) =>
|
|
29
|
+
SortByClocks(a, b, sortById);
|
|
30
|
+
// Sort entries by clock time as the primary sort criteria
|
|
31
|
+
return sortByEntryClocks(a, b);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Sort two entries by their hash.
|
|
36
|
+
*
|
|
37
|
+
* @param {Entry} a First entry
|
|
38
|
+
* @param {Entry} b Second entry
|
|
39
|
+
* @returns {number} 1 if a is latest, -1 if b is latest
|
|
40
|
+
*/
|
|
41
|
+
export const SortByEntryHash: ISortFunction = (a, b) => {
|
|
42
|
+
// Ultimate conflict resolution (compare hashes)
|
|
43
|
+
const compareHash = (a: Entry<any>, b: Entry<any>) =>
|
|
44
|
+
a.hash < b.hash ? -1 : 1;
|
|
45
|
+
// Sort two entries by their clock id, if the same then compare hashes
|
|
46
|
+
const sortById = (a: Entry<any>, b: Entry<any>) =>
|
|
47
|
+
SortByClockId(a, b, compareHash);
|
|
48
|
+
// Sort two entries by their clock time, if concurrent,
|
|
49
|
+
// determine sorting using provided conflict resolution function
|
|
50
|
+
const sortByEntryClocks = (a: Entry<any>, b: Entry<any>) =>
|
|
51
|
+
SortByClocks(a, b, sortById);
|
|
52
|
+
// Sort entries by clock time as the primary sort criteria
|
|
53
|
+
return sortByEntryClocks(a, b);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Sort two entries by their clock time.
|
|
58
|
+
* @param {Entry} a First entry to compare
|
|
59
|
+
* @param {Entry} b Second entry to compare
|
|
60
|
+
* @param {function(a, b)} resolveConflict A function to call if entries are concurrent (happened at the same time). The function should take in two entries and return 1 if the first entry should be chosen and -1 if the second entry should be chosen.
|
|
61
|
+
* @returns {number} 1 if a is greater, -1 if b is greater
|
|
62
|
+
*/
|
|
63
|
+
export const SortByClocks: ISortFunction = <T>(
|
|
64
|
+
a: Entry<T>,
|
|
65
|
+
b: Entry<T>,
|
|
66
|
+
resolveConflict?: (a: Entry<any>, b: Entry<any>) => number
|
|
67
|
+
) => {
|
|
68
|
+
// Compare the clocks
|
|
69
|
+
const diff = Clock.compare(a.metadata.clock, b.metadata.clock);
|
|
70
|
+
// If the clocks are concurrent, use the provided
|
|
71
|
+
// conflict resolution function to determine which comes first
|
|
72
|
+
return diff === 0 ? (resolveConflict || First)(a, b) : diff;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Sort two entries by their clock id.
|
|
77
|
+
* @param {Entry} a First entry to compare
|
|
78
|
+
* @param {Entry} b Second entry to compare
|
|
79
|
+
* @param {function(a, b)} resolveConflict A function to call if the clocks ids are the same. The function should take in two entries and return 1 if the first entry should be chosen and -1 if the second entry should be chosen.
|
|
80
|
+
* @returns {number} 1 if a is greater, -1 if b is greater
|
|
81
|
+
*/
|
|
82
|
+
export const SortByClockId: ISortFunction = (a, b, resolveConflict) => {
|
|
83
|
+
// Sort by ID if clocks are concurrent,
|
|
84
|
+
// take the entry with a "greater" clock id
|
|
85
|
+
const clockCompare = compare(a.metadata.clock.id, b.metadata.clock.id);
|
|
86
|
+
return clockCompare === 0 ? (resolveConflict || First)(a, b) : clockCompare;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A wrapper function to throw an error if the results of a passed function return zero
|
|
91
|
+
* @param {function(a, b)} [tiebreaker] The tiebreaker function to validate.
|
|
92
|
+
* @returns {function(a, b)} 1 if a is greater, -1 if b is greater
|
|
93
|
+
* @throws {Error} if func ever returns 0
|
|
94
|
+
*/
|
|
95
|
+
export const NoZeroes = (func: ISortFunction) => {
|
|
96
|
+
const comparator = <T>(a: Entry<T>, b: Entry<T>) => {
|
|
97
|
+
// Validate by calling the function
|
|
98
|
+
const result = func(a, b, (a, b) => -1);
|
|
99
|
+
if (result === 0) {
|
|
100
|
+
throw Error(
|
|
101
|
+
`Your log's tiebreaker function, ${func.name}, has returned zero and therefore cannot be`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return comparator;
|
|
108
|
+
};
|