@verdant-web/common 1.15.2 → 1.15.3-next.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 (163) hide show
  1. package/dist/cjs/EventSubscriber.d.ts +17 -17
  2. package/dist/cjs/EventSubscriber.js +66 -66
  3. package/dist/cjs/baseline.d.ts +5 -5
  4. package/dist/cjs/baseline.js +2 -2
  5. package/dist/cjs/batching.d.ts +42 -42
  6. package/dist/cjs/batching.js +91 -91
  7. package/dist/cjs/files.d.ts +19 -19
  8. package/dist/cjs/files.js +18 -18
  9. package/dist/cjs/files.test.d.ts +1 -0
  10. package/dist/cjs/files.test.js +81 -0
  11. package/dist/cjs/files.test.js.map +1 -0
  12. package/dist/cjs/index.d.ts +19 -18
  13. package/dist/cjs/index.js +41 -36
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/cjs/indexes.d.ts +17 -17
  16. package/dist/cjs/indexes.js +142 -142
  17. package/dist/cjs/indexes.test.d.ts +1 -1
  18. package/dist/cjs/indexes.test.js +127 -127
  19. package/dist/cjs/migration.d.ts +172 -172
  20. package/dist/cjs/migration.js +301 -301
  21. package/dist/cjs/oids.d.ts +100 -96
  22. package/dist/cjs/oids.js +457 -439
  23. package/dist/cjs/oids.js.map +1 -1
  24. package/dist/cjs/oids.test.d.ts +1 -1
  25. package/dist/cjs/oids.test.js +348 -272
  26. package/dist/cjs/oids.test.js.map +1 -1
  27. package/dist/cjs/operation.d.ts +139 -139
  28. package/dist/cjs/operation.js +545 -545
  29. package/dist/cjs/operation.test.d.ts +1 -1
  30. package/dist/cjs/operation.test.js +529 -529
  31. package/dist/cjs/patch.d.ts +26 -26
  32. package/dist/cjs/patch.js +226 -226
  33. package/dist/cjs/presence.d.ts +27 -27
  34. package/dist/cjs/presence.js +2 -2
  35. package/dist/cjs/protocol.d.ts +145 -145
  36. package/dist/cjs/protocol.js +3 -3
  37. package/dist/cjs/refs.d.ts +7 -5
  38. package/dist/cjs/refs.js +29 -21
  39. package/dist/cjs/refs.js.map +1 -1
  40. package/dist/cjs/replica.d.ts +28 -28
  41. package/dist/cjs/replica.js +28 -28
  42. package/dist/cjs/schema/defaults.d.ts +4 -0
  43. package/dist/cjs/schema/defaults.js +72 -0
  44. package/dist/cjs/schema/defaults.js.map +1 -0
  45. package/dist/cjs/schema/defaults.test.d.ts +1 -1
  46. package/dist/cjs/schema/defaults.test.js +20 -20
  47. package/dist/cjs/schema/fields.d.ts +9 -9
  48. package/dist/cjs/schema/fields.js +144 -144
  49. package/dist/cjs/schema/index.d.ts +8 -8
  50. package/dist/cjs/schema/index.js +51 -51
  51. package/dist/cjs/schema/indexFilters.d.ts +6 -6
  52. package/dist/cjs/schema/indexFilters.js +30 -30
  53. package/dist/cjs/schema/types/collection.d.ts +23 -23
  54. package/dist/cjs/schema/types/collection.js +2 -2
  55. package/dist/cjs/schema/types/compounds.d.ts +11 -11
  56. package/dist/cjs/schema/types/compounds.js +2 -2
  57. package/dist/cjs/schema/types/fields.d.ts +75 -75
  58. package/dist/cjs/schema/types/fields.js +2 -2
  59. package/dist/cjs/schema/types/filters.d.ts +29 -29
  60. package/dist/cjs/schema/types/filters.js +2 -2
  61. package/dist/cjs/schema/types/shapes.d.ts +21 -21
  62. package/dist/cjs/schema/types/shapes.js +2 -2
  63. package/dist/cjs/schema/types/synthetics.d.ts +37 -37
  64. package/dist/cjs/schema/types/synthetics.js +2 -2
  65. package/dist/cjs/schema/types.d.ts +18 -18
  66. package/dist/cjs/schema/types.js +22 -22
  67. package/dist/cjs/schema/validation.d.ts +3 -3
  68. package/dist/cjs/schema/validation.js +86 -86
  69. package/dist/cjs/timestamp.d.ts +50 -50
  70. package/dist/cjs/timestamp.js +251 -251
  71. package/dist/cjs/timestamp.test.d.ts +1 -1
  72. package/dist/cjs/timestamp.test.js +104 -104
  73. package/dist/cjs/undo.d.ts +3 -3
  74. package/dist/cjs/undo.js +198 -198
  75. package/dist/cjs/utils.d.ts +20 -20
  76. package/dist/cjs/utils.js +145 -145
  77. package/dist/cjs/utils.test.d.ts +1 -1
  78. package/dist/cjs/utils.test.js +36 -36
  79. package/dist/esm/EventSubscriber.d.ts +17 -17
  80. package/dist/esm/EventSubscriber.js +62 -62
  81. package/dist/esm/baseline.d.ts +5 -5
  82. package/dist/esm/baseline.js +1 -1
  83. package/dist/esm/batching.d.ts +42 -42
  84. package/dist/esm/batching.js +86 -86
  85. package/dist/esm/files.d.ts +19 -19
  86. package/dist/esm/files.js +12 -12
  87. package/dist/esm/files.test.d.ts +1 -0
  88. package/dist/esm/files.test.js +79 -0
  89. package/dist/esm/files.test.js.map +1 -0
  90. package/dist/esm/index.d.ts +19 -18
  91. package/dist/esm/index.js +16 -15
  92. package/dist/esm/index.js.map +1 -1
  93. package/dist/esm/indexes.d.ts +17 -17
  94. package/dist/esm/indexes.js +130 -130
  95. package/dist/esm/indexes.test.d.ts +1 -1
  96. package/dist/esm/indexes.test.js +125 -125
  97. package/dist/esm/migration.d.ts +172 -172
  98. package/dist/esm/migration.js +294 -294
  99. package/dist/esm/oids.d.ts +100 -96
  100. package/dist/esm/oids.js +422 -407
  101. package/dist/esm/oids.js.map +1 -1
  102. package/dist/esm/oids.test.d.ts +1 -1
  103. package/dist/esm/oids.test.js +346 -270
  104. package/dist/esm/oids.test.js.map +1 -1
  105. package/dist/esm/operation.d.ts +139 -139
  106. package/dist/esm/operation.js +530 -530
  107. package/dist/esm/operation.test.d.ts +1 -1
  108. package/dist/esm/operation.test.js +527 -527
  109. package/dist/esm/patch.d.ts +26 -26
  110. package/dist/esm/patch.js +222 -222
  111. package/dist/esm/presence.d.ts +27 -27
  112. package/dist/esm/presence.js +1 -1
  113. package/dist/esm/protocol.d.ts +145 -145
  114. package/dist/esm/protocol.js +2 -2
  115. package/dist/esm/refs.d.ts +7 -5
  116. package/dist/esm/refs.js +22 -16
  117. package/dist/esm/refs.js.map +1 -1
  118. package/dist/esm/replica.d.ts +28 -28
  119. package/dist/esm/replica.js +25 -25
  120. package/dist/esm/schema/defaults.d.ts +4 -0
  121. package/dist/esm/schema/defaults.js +66 -0
  122. package/dist/esm/schema/defaults.js.map +1 -0
  123. package/dist/esm/schema/defaults.test.d.ts +1 -1
  124. package/dist/esm/schema/defaults.test.js +18 -18
  125. package/dist/esm/schema/fields.d.ts +9 -9
  126. package/dist/esm/schema/fields.js +133 -133
  127. package/dist/esm/schema/index.d.ts +8 -8
  128. package/dist/esm/schema/index.js +32 -32
  129. package/dist/esm/schema/indexFilters.d.ts +6 -6
  130. package/dist/esm/schema/indexFilters.js +22 -22
  131. package/dist/esm/schema/types/collection.d.ts +23 -23
  132. package/dist/esm/schema/types/collection.js +1 -1
  133. package/dist/esm/schema/types/compounds.d.ts +11 -11
  134. package/dist/esm/schema/types/compounds.js +1 -1
  135. package/dist/esm/schema/types/fields.d.ts +75 -75
  136. package/dist/esm/schema/types/fields.js +1 -1
  137. package/dist/esm/schema/types/filters.d.ts +29 -29
  138. package/dist/esm/schema/types/filters.js +1 -1
  139. package/dist/esm/schema/types/shapes.d.ts +21 -21
  140. package/dist/esm/schema/types/shapes.js +1 -1
  141. package/dist/esm/schema/types/synthetics.d.ts +37 -37
  142. package/dist/esm/schema/types/synthetics.js +1 -1
  143. package/dist/esm/schema/types.d.ts +18 -18
  144. package/dist/esm/schema/types.js +6 -6
  145. package/dist/esm/schema/validation.d.ts +3 -3
  146. package/dist/esm/schema/validation.js +81 -81
  147. package/dist/esm/timestamp.d.ts +50 -50
  148. package/dist/esm/timestamp.js +234 -234
  149. package/dist/esm/timestamp.test.d.ts +1 -1
  150. package/dist/esm/timestamp.test.js +102 -102
  151. package/dist/esm/undo.d.ts +3 -3
  152. package/dist/esm/undo.js +194 -194
  153. package/dist/esm/utils.d.ts +20 -20
  154. package/dist/esm/utils.js +127 -127
  155. package/dist/esm/utils.test.d.ts +1 -1
  156. package/dist/esm/utils.test.js +34 -34
  157. package/dist/tsconfig-cjs.tsbuildinfo +1 -1
  158. package/dist/tsconfig.tsbuildinfo +1 -1
  159. package/package.json +1 -1
  160. package/src/index.ts +1 -0
  161. package/src/oids.test.ts +82 -0
  162. package/src/oids.ts +17 -0
  163. package/src/refs.ts +8 -0
@@ -1,50 +1,50 @@
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: (timestamp: string) => number;
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 {};
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: (timestamp: string) => number;
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 {};
@@ -1,252 +1,252 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.compareTimestampSchemaVersions = exports.getTimestampSchemaVersion = exports.OLD_deserializeHlcTimestamp = exports.OLD_serializeHlcTimestamp = exports.convertOldHlcTimestamp = exports.deserializeHlcTimestamp = exports.serializeHlcTimestamp = exports.HybridLogicalClockTimestampProvider = exports.NaiveTimestampProvider = exports.OLD_encodeVersion = exports.encodeVersion = void 0;
7
- const cuid_1 = __importDefault(require("cuid"));
8
- const VERSION_BLOCK_LENGTH = 4;
9
- const ENCODING_NUMBER_RADIX = 36;
10
- function encodeVersion(version) {
11
- return version
12
- .toString(ENCODING_NUMBER_RADIX)
13
- .padStart(VERSION_BLOCK_LENGTH, '0');
14
- }
15
- exports.encodeVersion = encodeVersion;
16
- function OLD_encodeVersion(version) {
17
- return version.toString().padStart(6, '0');
18
- }
19
- exports.OLD_encodeVersion = OLD_encodeVersion;
20
- class NaiveTimestampProvider {
21
- constructor() {
22
- this.counter = 0;
23
- this.now = (version) => {
24
- return (encodeVersion(version) + Date.now().toString() + '-' + this.counter++);
25
- };
26
- this.update = () => {
27
- this.counter = 0;
28
- };
29
- this.zero = (version) => {
30
- return encodeVersion(version) + '0' + '-' + this.counter++;
31
- };
32
- this.getWallClockTime = (timestamp) => {
33
- return parseInt(timestamp.slice(VERSION_BLOCK_LENGTH).split('-')[0], 10);
34
- };
35
- }
36
- }
37
- exports.NaiveTimestampProvider = NaiveTimestampProvider;
38
- class HybridLogicalClockTimestampProvider {
39
- constructor() {
40
- this.latest = {
41
- time: Date.now(),
42
- counter: 0,
43
- node: generateNodeId(),
44
- };
45
- this.zeroCounter = 0;
46
- this.now = (version) => {
47
- this.latest = getHlcNow(this.latest);
48
- return this.get(version, this.latest);
49
- };
50
- /**
51
- * @deprecated - use now() instead and update to latest format
52
- */
53
- this.OLD_now = (version) => {
54
- this.latest = getHlcNow(this.latest);
55
- return OLD_encodeVersion(version) + OLD_serializeHlcTimestamp(this.latest);
56
- };
57
- /** Get the current timer state. Does not increment counter. */
58
- this.timerState = () => {
59
- return this.latest;
60
- };
61
- this.update = (remoteTimestamp) => {
62
- // strip version from remote timestamp
63
- const hlcString = remoteTimestamp.slice(VERSION_BLOCK_LENGTH);
64
- this.latest = updateFromRemote(this.latest, deserializeHlcTimestamp(hlcString));
65
- };
66
- this.get = (version, raw) => {
67
- return encodeVersion(version) + serializeHlcTimestamp(raw);
68
- };
69
- this.zero = (version) => {
70
- return (encodeVersion(version) +
71
- serializeHlcTimestamp({
72
- time: 0,
73
- // to keep zero timestamps unique, we use a counter here as well
74
- counter: this.zeroCounter++,
75
- node: this.latest.node,
76
- }));
77
- };
78
- this.getWallClockTime = (timestamp) => {
79
- return deserializeHlcTimestamp(timestamp.slice(VERSION_BLOCK_LENGTH)).time;
80
- };
81
- }
82
- }
83
- exports.HybridLogicalClockTimestampProvider = HybridLogicalClockTimestampProvider;
84
- class ClockDriftError extends Error {
85
- constructor(...args) {
86
- super();
87
- this.type = 'ClockDriftError';
88
- this.message = ['maximum clock drift exceeded'].concat(args).join(' ');
89
- }
90
- }
91
- class OverflowError extends Error {
92
- constructor() {
93
- super();
94
- this.type = 'OverflowError';
95
- this.message = 'timestamp counter overflow';
96
- }
97
- }
98
- const COUNTER_BLOCK_LENGTH = 4;
99
- const NODE_BLOCK_LENGTH = 7;
100
- const MAX_CLOCK_DRIFT = 60 * 1000;
101
- // 9 base36 characters should last until the year 5000
102
- // when encoding a unix MS timestamp
103
- const TIME_BLOCK_LENGTH = 9;
104
- function generateNodeId() {
105
- return cuid_1.default
106
- .slug()
107
- .padStart(NODE_BLOCK_LENGTH, '0')
108
- .slice(0, NODE_BLOCK_LENGTH);
109
- }
110
- function serializeHlcTimestamp(ts) {
111
- // string representation of the time
112
- const dateString = new Date(ts.time)
113
- .getTime()
114
- .toString(ENCODING_NUMBER_RADIX)
115
- .padStart(TIME_BLOCK_LENGTH, '0');
116
- // counter, 336, padded to 4 characters
117
- const counter = ts.counter
118
- .toString(ENCODING_NUMBER_RADIX)
119
- .padStart(COUNTER_BLOCK_LENGTH, '0');
120
- // node id padded to 16 characters
121
- const node = ts.node.padStart(NODE_BLOCK_LENGTH, '0');
122
- return `${dateString}${counter}${node}`;
123
- }
124
- exports.serializeHlcTimestamp = serializeHlcTimestamp;
125
- function getHlcNow(prev) {
126
- const wallTime = Date.now();
127
- // pick prev's time if it's later than our local device
128
- const newWallTime = Math.max(prev.time, wallTime);
129
- // reset counter if wall time changed
130
- const newCounter = prev.time === newWallTime ? prev.counter + 1 : 0;
131
- // check for drift
132
- if (newWallTime - wallTime > MAX_CLOCK_DRIFT) {
133
- throw new ClockDriftError(newWallTime, wallTime, MAX_CLOCK_DRIFT);
134
- }
135
- // check for counter overflow (max is 4 bytes)
136
- if (newCounter > 65535) {
137
- throw new OverflowError();
138
- }
139
- return {
140
- time: newWallTime,
141
- counter: newCounter,
142
- node: prev.node,
143
- };
144
- }
145
- function updateFromRemote(local, remote) {
146
- const wallTime = Date.now();
147
- // pick remote's time if it's later than our local device
148
- const newTime = Math.max(wallTime, Math.max(local.time, remote.time));
149
- const maxCounter = Math.max(local.counter, remote.counter);
150
- let newCounter;
151
- // if all clocks are the same, increment the counter
152
- if (local.time === newTime && remote.time === newTime) {
153
- newCounter = maxCounter + 1;
154
- }
155
- // if local time is the same as new time, increment our local counter
156
- else if (local.time === newTime) {
157
- newCounter = local.counter + 1;
158
- }
159
- // if remote time is the same as new time, increment remote counter
160
- else if (remote.time === newTime) {
161
- newCounter = remote.counter + 1;
162
- }
163
- // otherwise, reset the counter
164
- else {
165
- newCounter = 0;
166
- }
167
- // check for drift
168
- if (newTime - wallTime > MAX_CLOCK_DRIFT) {
169
- throw new ClockDriftError(newTime, wallTime, MAX_CLOCK_DRIFT);
170
- }
171
- if (newCounter > 65535) {
172
- throw new OverflowError();
173
- }
174
- return {
175
- time: newTime,
176
- counter: newCounter,
177
- node: local.node,
178
- };
179
- }
180
- function deserializeHlcTimestamp(clock) {
181
- const dateString = clock.slice(0, TIME_BLOCK_LENGTH);
182
- const counter = clock.slice(TIME_BLOCK_LENGTH, TIME_BLOCK_LENGTH + COUNTER_BLOCK_LENGTH);
183
- const node = clock.slice(TIME_BLOCK_LENGTH + COUNTER_BLOCK_LENGTH);
184
- const time = parseInt(dateString, ENCODING_NUMBER_RADIX);
185
- const counterNum = parseInt(counter, ENCODING_NUMBER_RADIX);
186
- if (isNaN(time) || isNaN(counterNum)) {
187
- throw new Error('invalid clock format');
188
- }
189
- return {
190
- time,
191
- counter: counterNum,
192
- node,
193
- };
194
- }
195
- exports.deserializeHlcTimestamp = deserializeHlcTimestamp;
196
- function removeLeadingZeroes(str) {
197
- return str.replace(/^0+/, '');
198
- }
199
- /**
200
- * Below, converters for old-style timestamps are defined.
201
- * These are for migrating older clients to the new format.
202
- */
203
- /**
204
- * Converts a timestamp from the old format to the new format.
205
- */
206
- function convertOldHlcTimestamp(ts) {
207
- const versionBlock = ts.slice(0, 6);
208
- // no jokes please
209
- const clockBlock = ts.slice(6);
210
- const deserialized = OLD_deserializeHlcTimestamp(clockBlock);
211
- // version was base 10 and now is base 36
212
- const versionNumber = parseInt(versionBlock, 10);
213
- const encodedVersion = encodeVersion(versionNumber);
214
- return encodedVersion + serializeHlcTimestamp(deserialized);
215
- }
216
- exports.convertOldHlcTimestamp = convertOldHlcTimestamp;
217
- function OLD_serializeHlcTimestamp(ts) {
218
- // ISO string representation of the time
219
- const dateString = new Date(ts.time).toISOString();
220
- // counter, base16, padded to 4 characters
221
- const counter = ts.counter.toString(16).toUpperCase().padStart(4, '0');
222
- // node id padded to 16 characters
223
- const node = ts.node.padStart(16, '0');
224
- return `${dateString}-${counter}-${node}`;
225
- }
226
- exports.OLD_serializeHlcTimestamp = OLD_serializeHlcTimestamp;
227
- function OLD_deserializeHlcTimestamp(clock) {
228
- // ISO string representation of the time
229
- const dateString = clock.slice(0, 24);
230
- const counter = clock.slice(25, 25 + 4);
231
- const node = clock.slice(25 + 4 + 1);
232
- const time = new Date(dateString).getTime();
233
- const counterNum = parseInt(counter, 16);
234
- if (isNaN(time) || isNaN(counterNum)) {
235
- throw new Error('invalid clock format');
236
- }
237
- return {
238
- time,
239
- counter: counterNum,
240
- node: node.slice(node.length - 7),
241
- };
242
- }
243
- exports.OLD_deserializeHlcTimestamp = OLD_deserializeHlcTimestamp;
244
- function getTimestampSchemaVersion(timestamp) {
245
- return parseInt(timestamp.slice(0, VERSION_BLOCK_LENGTH), 36);
246
- }
247
- exports.getTimestampSchemaVersion = getTimestampSchemaVersion;
248
- function compareTimestampSchemaVersions(a, b) {
249
- return getTimestampSchemaVersion(a) - getTimestampSchemaVersion(b);
250
- }
251
- exports.compareTimestampSchemaVersions = compareTimestampSchemaVersions;
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.compareTimestampSchemaVersions = exports.getTimestampSchemaVersion = exports.OLD_deserializeHlcTimestamp = exports.OLD_serializeHlcTimestamp = exports.convertOldHlcTimestamp = exports.deserializeHlcTimestamp = exports.serializeHlcTimestamp = exports.HybridLogicalClockTimestampProvider = exports.NaiveTimestampProvider = exports.OLD_encodeVersion = exports.encodeVersion = void 0;
7
+ const cuid_1 = __importDefault(require("cuid"));
8
+ const VERSION_BLOCK_LENGTH = 4;
9
+ const ENCODING_NUMBER_RADIX = 36;
10
+ function encodeVersion(version) {
11
+ return version
12
+ .toString(ENCODING_NUMBER_RADIX)
13
+ .padStart(VERSION_BLOCK_LENGTH, '0');
14
+ }
15
+ exports.encodeVersion = encodeVersion;
16
+ function OLD_encodeVersion(version) {
17
+ return version.toString().padStart(6, '0');
18
+ }
19
+ exports.OLD_encodeVersion = OLD_encodeVersion;
20
+ class NaiveTimestampProvider {
21
+ constructor() {
22
+ this.counter = 0;
23
+ this.now = (version) => {
24
+ return (encodeVersion(version) + Date.now().toString() + '-' + this.counter++);
25
+ };
26
+ this.update = () => {
27
+ this.counter = 0;
28
+ };
29
+ this.zero = (version) => {
30
+ return encodeVersion(version) + '0' + '-' + this.counter++;
31
+ };
32
+ this.getWallClockTime = (timestamp) => {
33
+ return parseInt(timestamp.slice(VERSION_BLOCK_LENGTH).split('-')[0], 10);
34
+ };
35
+ }
36
+ }
37
+ exports.NaiveTimestampProvider = NaiveTimestampProvider;
38
+ class HybridLogicalClockTimestampProvider {
39
+ constructor() {
40
+ this.latest = {
41
+ time: Date.now(),
42
+ counter: 0,
43
+ node: generateNodeId(),
44
+ };
45
+ this.zeroCounter = 0;
46
+ this.now = (version) => {
47
+ this.latest = getHlcNow(this.latest);
48
+ return this.get(version, this.latest);
49
+ };
50
+ /**
51
+ * @deprecated - use now() instead and update to latest format
52
+ */
53
+ this.OLD_now = (version) => {
54
+ this.latest = getHlcNow(this.latest);
55
+ return OLD_encodeVersion(version) + OLD_serializeHlcTimestamp(this.latest);
56
+ };
57
+ /** Get the current timer state. Does not increment counter. */
58
+ this.timerState = () => {
59
+ return this.latest;
60
+ };
61
+ this.update = (remoteTimestamp) => {
62
+ // strip version from remote timestamp
63
+ const hlcString = remoteTimestamp.slice(VERSION_BLOCK_LENGTH);
64
+ this.latest = updateFromRemote(this.latest, deserializeHlcTimestamp(hlcString));
65
+ };
66
+ this.get = (version, raw) => {
67
+ return encodeVersion(version) + serializeHlcTimestamp(raw);
68
+ };
69
+ this.zero = (version) => {
70
+ return (encodeVersion(version) +
71
+ serializeHlcTimestamp({
72
+ time: 0,
73
+ // to keep zero timestamps unique, we use a counter here as well
74
+ counter: this.zeroCounter++,
75
+ node: this.latest.node,
76
+ }));
77
+ };
78
+ this.getWallClockTime = (timestamp) => {
79
+ return deserializeHlcTimestamp(timestamp.slice(VERSION_BLOCK_LENGTH)).time;
80
+ };
81
+ }
82
+ }
83
+ exports.HybridLogicalClockTimestampProvider = HybridLogicalClockTimestampProvider;
84
+ class ClockDriftError extends Error {
85
+ constructor(...args) {
86
+ super();
87
+ this.type = 'ClockDriftError';
88
+ this.message = ['maximum clock drift exceeded'].concat(args).join(' ');
89
+ }
90
+ }
91
+ class OverflowError extends Error {
92
+ constructor() {
93
+ super();
94
+ this.type = 'OverflowError';
95
+ this.message = 'timestamp counter overflow';
96
+ }
97
+ }
98
+ const COUNTER_BLOCK_LENGTH = 4;
99
+ const NODE_BLOCK_LENGTH = 7;
100
+ const MAX_CLOCK_DRIFT = 60 * 1000;
101
+ // 9 base36 characters should last until the year 5000
102
+ // when encoding a unix MS timestamp
103
+ const TIME_BLOCK_LENGTH = 9;
104
+ function generateNodeId() {
105
+ return cuid_1.default
106
+ .slug()
107
+ .padStart(NODE_BLOCK_LENGTH, '0')
108
+ .slice(0, NODE_BLOCK_LENGTH);
109
+ }
110
+ function serializeHlcTimestamp(ts) {
111
+ // string representation of the time
112
+ const dateString = new Date(ts.time)
113
+ .getTime()
114
+ .toString(ENCODING_NUMBER_RADIX)
115
+ .padStart(TIME_BLOCK_LENGTH, '0');
116
+ // counter, 336, padded to 4 characters
117
+ const counter = ts.counter
118
+ .toString(ENCODING_NUMBER_RADIX)
119
+ .padStart(COUNTER_BLOCK_LENGTH, '0');
120
+ // node id padded to 16 characters
121
+ const node = ts.node.padStart(NODE_BLOCK_LENGTH, '0');
122
+ return `${dateString}${counter}${node}`;
123
+ }
124
+ exports.serializeHlcTimestamp = serializeHlcTimestamp;
125
+ function getHlcNow(prev) {
126
+ const wallTime = Date.now();
127
+ // pick prev's time if it's later than our local device
128
+ const newWallTime = Math.max(prev.time, wallTime);
129
+ // reset counter if wall time changed
130
+ const newCounter = prev.time === newWallTime ? prev.counter + 1 : 0;
131
+ // check for drift
132
+ if (newWallTime - wallTime > MAX_CLOCK_DRIFT) {
133
+ throw new ClockDriftError(newWallTime, wallTime, MAX_CLOCK_DRIFT);
134
+ }
135
+ // check for counter overflow (max is 4 bytes)
136
+ if (newCounter > 65535) {
137
+ throw new OverflowError();
138
+ }
139
+ return {
140
+ time: newWallTime,
141
+ counter: newCounter,
142
+ node: prev.node,
143
+ };
144
+ }
145
+ function updateFromRemote(local, remote) {
146
+ const wallTime = Date.now();
147
+ // pick remote's time if it's later than our local device
148
+ const newTime = Math.max(wallTime, Math.max(local.time, remote.time));
149
+ const maxCounter = Math.max(local.counter, remote.counter);
150
+ let newCounter;
151
+ // if all clocks are the same, increment the counter
152
+ if (local.time === newTime && remote.time === newTime) {
153
+ newCounter = maxCounter + 1;
154
+ }
155
+ // if local time is the same as new time, increment our local counter
156
+ else if (local.time === newTime) {
157
+ newCounter = local.counter + 1;
158
+ }
159
+ // if remote time is the same as new time, increment remote counter
160
+ else if (remote.time === newTime) {
161
+ newCounter = remote.counter + 1;
162
+ }
163
+ // otherwise, reset the counter
164
+ else {
165
+ newCounter = 0;
166
+ }
167
+ // check for drift
168
+ if (newTime - wallTime > MAX_CLOCK_DRIFT) {
169
+ throw new ClockDriftError(newTime, wallTime, MAX_CLOCK_DRIFT);
170
+ }
171
+ if (newCounter > 65535) {
172
+ throw new OverflowError();
173
+ }
174
+ return {
175
+ time: newTime,
176
+ counter: newCounter,
177
+ node: local.node,
178
+ };
179
+ }
180
+ function deserializeHlcTimestamp(clock) {
181
+ const dateString = clock.slice(0, TIME_BLOCK_LENGTH);
182
+ const counter = clock.slice(TIME_BLOCK_LENGTH, TIME_BLOCK_LENGTH + COUNTER_BLOCK_LENGTH);
183
+ const node = clock.slice(TIME_BLOCK_LENGTH + COUNTER_BLOCK_LENGTH);
184
+ const time = parseInt(dateString, ENCODING_NUMBER_RADIX);
185
+ const counterNum = parseInt(counter, ENCODING_NUMBER_RADIX);
186
+ if (isNaN(time) || isNaN(counterNum)) {
187
+ throw new Error('invalid clock format');
188
+ }
189
+ return {
190
+ time,
191
+ counter: counterNum,
192
+ node,
193
+ };
194
+ }
195
+ exports.deserializeHlcTimestamp = deserializeHlcTimestamp;
196
+ function removeLeadingZeroes(str) {
197
+ return str.replace(/^0+/, '');
198
+ }
199
+ /**
200
+ * Below, converters for old-style timestamps are defined.
201
+ * These are for migrating older clients to the new format.
202
+ */
203
+ /**
204
+ * Converts a timestamp from the old format to the new format.
205
+ */
206
+ function convertOldHlcTimestamp(ts) {
207
+ const versionBlock = ts.slice(0, 6);
208
+ // no jokes please
209
+ const clockBlock = ts.slice(6);
210
+ const deserialized = OLD_deserializeHlcTimestamp(clockBlock);
211
+ // version was base 10 and now is base 36
212
+ const versionNumber = parseInt(versionBlock, 10);
213
+ const encodedVersion = encodeVersion(versionNumber);
214
+ return encodedVersion + serializeHlcTimestamp(deserialized);
215
+ }
216
+ exports.convertOldHlcTimestamp = convertOldHlcTimestamp;
217
+ function OLD_serializeHlcTimestamp(ts) {
218
+ // ISO string representation of the time
219
+ const dateString = new Date(ts.time).toISOString();
220
+ // counter, base16, padded to 4 characters
221
+ const counter = ts.counter.toString(16).toUpperCase().padStart(4, '0');
222
+ // node id padded to 16 characters
223
+ const node = ts.node.padStart(16, '0');
224
+ return `${dateString}-${counter}-${node}`;
225
+ }
226
+ exports.OLD_serializeHlcTimestamp = OLD_serializeHlcTimestamp;
227
+ function OLD_deserializeHlcTimestamp(clock) {
228
+ // ISO string representation of the time
229
+ const dateString = clock.slice(0, 24);
230
+ const counter = clock.slice(25, 25 + 4);
231
+ const node = clock.slice(25 + 4 + 1);
232
+ const time = new Date(dateString).getTime();
233
+ const counterNum = parseInt(counter, 16);
234
+ if (isNaN(time) || isNaN(counterNum)) {
235
+ throw new Error('invalid clock format');
236
+ }
237
+ return {
238
+ time,
239
+ counter: counterNum,
240
+ node: node.slice(node.length - 7),
241
+ };
242
+ }
243
+ exports.OLD_deserializeHlcTimestamp = OLD_deserializeHlcTimestamp;
244
+ function getTimestampSchemaVersion(timestamp) {
245
+ return parseInt(timestamp.slice(0, VERSION_BLOCK_LENGTH), 36);
246
+ }
247
+ exports.getTimestampSchemaVersion = getTimestampSchemaVersion;
248
+ function compareTimestampSchemaVersions(a, b) {
249
+ return getTimestampSchemaVersion(a) - getTimestampSchemaVersion(b);
250
+ }
251
+ exports.compareTimestampSchemaVersions = compareTimestampSchemaVersions;
252
252
  //# sourceMappingURL=timestamp.js.map
@@ -1 +1 @@
1
- export {};
1
+ export {};