@enormora/clock 0.0.1 → 0.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 +21 -0
- package/README.md +311 -0
- package/clock.d.ts +21 -0
- package/clock.d.ts.map +1 -0
- package/clock.entry-point.d.ts +6 -0
- package/clock.entry-point.d.ts.map +1 -0
- package/clock.entry-point.js +26 -0
- package/clock.entry-point.js.map +1 -0
- package/clock.js +28 -0
- package/clock.js.map +1 -0
- package/deterministic-clock.d.ts +11 -0
- package/deterministic-clock.d.ts.map +1 -0
- package/deterministic-clock.js +170 -0
- package/deterministic-clock.js.map +1 -0
- package/index.d.ts +6 -0
- package/index.d.ts.map +1 -0
- package/index.js +4 -0
- package/index.js.map +1 -0
- package/package.json +33 -6
- package/sbom.cdx.json +30 -0
- package/temporal-clock.entry-point.d.ts +3 -0
- package/temporal-clock.entry-point.d.ts.map +1 -0
- package/temporal-clock.entry-point.js +29 -0
- package/temporal-clock.entry-point.js.map +1 -0
- package/temporal-clock.js +29 -0
- package/temporal-clock.js.map +1 -0
- package/timer-delay.js +18 -0
- package/timer-delay.js.map +1 -0
- package/readme.md +0 -7
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Christian Rackerseder
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# @enormora/clock
|
|
2
|
+
|
|
3
|
+
Explicit time and timer access for TypeScript applications.
|
|
4
|
+
|
|
5
|
+
`@enormora/clock` provides a small dependency-injection boundary around time-related side effects:
|
|
6
|
+
|
|
7
|
+
- reading wall time as `Date`, Unix epoch milliseconds, or Unix epoch microseconds
|
|
8
|
+
- reading monotonic time and its Unix epoch origin
|
|
9
|
+
- scheduling and clearing timeouts
|
|
10
|
+
- scheduling and clearing intervals
|
|
11
|
+
- replacing real time with a deterministic clock in tests
|
|
12
|
+
|
|
13
|
+
It is not a date-time utility library or a general scheduler framework. The package keeps time access explicit so
|
|
14
|
+
application code does not need to call `Date.now()`, `new Date()`, `performance.now()`, `setTimeout`, or `setInterval`
|
|
15
|
+
directly.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm install @enormora/clock
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The package is ESM-only and requires Node.js `^24.15.0 || ^26.0.0`.
|
|
24
|
+
|
|
25
|
+
The root export keeps all clocks available from one import. Prefer explicit module subpaths when code only needs one
|
|
26
|
+
clock:
|
|
27
|
+
|
|
28
|
+
- `@enormora/clock/clock`
|
|
29
|
+
- `@enormora/clock/temporal-clock`
|
|
30
|
+
- `@enormora/clock/deterministic-clock`
|
|
31
|
+
|
|
32
|
+
## Real Clock
|
|
33
|
+
|
|
34
|
+
Use `createClock()` at the application boundary and pass the resulting `Clock` into code that needs time.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { createClock } from '@enormora/clock/clock';
|
|
38
|
+
|
|
39
|
+
const clock = createClock();
|
|
40
|
+
|
|
41
|
+
console.log(clock.currentUnixEpochMilliseconds);
|
|
42
|
+
console.log(clock.currentUnixEpochMicroseconds);
|
|
43
|
+
console.log(clock.currentDate.toISOString());
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The real clock delegates to the runtime:
|
|
47
|
+
|
|
48
|
+
- `currentDate` returns a new `Date`
|
|
49
|
+
- `currentUnixEpochMilliseconds` uses `Date.now()`
|
|
50
|
+
- `currentUnixEpochMicroseconds` uses `Date.now() * 1000n`
|
|
51
|
+
- `monotonicTimeOriginUnixEpochMicroseconds` uses `performance.timeOrigin`
|
|
52
|
+
- `currentMonotonicMicroseconds` uses `performance.now()`
|
|
53
|
+
- timer functions call `globalThis`
|
|
54
|
+
|
|
55
|
+
`currentUnixEpochMicroseconds` communicates the unit, not a guaranteed resolution. Date-backed clocks expose
|
|
56
|
+
millisecond-resolution wall time in microseconds.
|
|
57
|
+
|
|
58
|
+
## Temporal Clock
|
|
59
|
+
|
|
60
|
+
Use `createTemporalClock()` when the runtime provides `Temporal`.
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import { createTemporalClock } from '@enormora/clock/temporal-clock';
|
|
64
|
+
|
|
65
|
+
const clock = createTemporalClock();
|
|
66
|
+
|
|
67
|
+
console.log(clock.currentUnixEpochMicroseconds);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The Temporal clock implements the same `Clock` interface. It uses `Temporal.Now.instant()` for wall time and
|
|
71
|
+
`performance` for monotonic time. Importing the module works without Temporal, but calling `createTemporalClock()`
|
|
72
|
+
throws when `globalThis.Temporal` is unavailable.
|
|
73
|
+
|
|
74
|
+
## Dependency Injection
|
|
75
|
+
|
|
76
|
+
Prefer accepting a `Clock` as an explicit dependency for code that depends on time.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import type { Clock } from '@enormora/clock/clock';
|
|
80
|
+
|
|
81
|
+
type Session = {
|
|
82
|
+
readonly expiresAtUnixEpochMilliseconds: number;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export function isSessionExpired(clock: Clock, session: Session): boolean {
|
|
86
|
+
return clock.currentUnixEpochMilliseconds >= session.expiresAtUnixEpochMilliseconds;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Use wall time for calendar time, storage, and user-facing timestamps. Use monotonic values for elapsed time and
|
|
91
|
+
durations.
|
|
92
|
+
|
|
93
|
+
## Deterministic Clock
|
|
94
|
+
|
|
95
|
+
Use `createDeterministicClock()` in tests or deterministic environments.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { createDeterministicClock } from '@enormora/clock/deterministic-clock';
|
|
99
|
+
|
|
100
|
+
const clock = createDeterministicClock({
|
|
101
|
+
initialUnixEpochMicroseconds: 1_704_067_200_000_000n
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
console.log(clock.currentDate.toISOString());
|
|
105
|
+
|
|
106
|
+
clock.advanceByMilliseconds(1000);
|
|
107
|
+
|
|
108
|
+
console.log(clock.currentUnixEpochMilliseconds);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The deterministic clock implements the same `Clock` interface and adds:
|
|
112
|
+
|
|
113
|
+
- `setCurrentUnixEpochMicroseconds(nextUnixEpochMicroseconds)`
|
|
114
|
+
- `advanceByMicroseconds(delayInMicroseconds)`
|
|
115
|
+
- `advanceByMilliseconds(delayInMilliseconds)`
|
|
116
|
+
|
|
117
|
+
Wall time and monotonic time are stored in microseconds. Timers are scheduled against monotonic time, so setting wall
|
|
118
|
+
time does not run or delay timers.
|
|
119
|
+
|
|
120
|
+
## Testing Timers
|
|
121
|
+
|
|
122
|
+
The deterministic clock runs scheduled callbacks when monotonic time is advanced far enough.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import assert from 'node:assert';
|
|
126
|
+
import { createDeterministicClock } from '@enormora/clock/deterministic-clock';
|
|
127
|
+
|
|
128
|
+
const clock = createDeterministicClock({
|
|
129
|
+
initialUnixEpochMicroseconds: 0n
|
|
130
|
+
});
|
|
131
|
+
const calls: string[] = [];
|
|
132
|
+
|
|
133
|
+
clock.setTimeout(
|
|
134
|
+
(value) => {
|
|
135
|
+
calls.push(value);
|
|
136
|
+
},
|
|
137
|
+
100,
|
|
138
|
+
'done'
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
clock.advanceByMilliseconds(99);
|
|
142
|
+
assert.deepStrictEqual(calls, []);
|
|
143
|
+
|
|
144
|
+
clock.advanceByMilliseconds(1);
|
|
145
|
+
assert.deepStrictEqual(calls, [ 'done' ]);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Intervals run once for each elapsed interval.
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
import assert from 'node:assert';
|
|
152
|
+
import { createDeterministicClock } from '@enormora/clock/deterministic-clock';
|
|
153
|
+
|
|
154
|
+
const clock = createDeterministicClock({
|
|
155
|
+
initialUnixEpochMicroseconds: 0n
|
|
156
|
+
});
|
|
157
|
+
let count = 0;
|
|
158
|
+
|
|
159
|
+
const intervalIdentifier = clock.setInterval(() => {
|
|
160
|
+
count += 1;
|
|
161
|
+
}, 100);
|
|
162
|
+
|
|
163
|
+
clock.advanceByMilliseconds(250);
|
|
164
|
+
assert.strictEqual(count, 2);
|
|
165
|
+
|
|
166
|
+
clock.clearInterval(intervalIdentifier);
|
|
167
|
+
clock.advanceByMilliseconds(500);
|
|
168
|
+
assert.strictEqual(count, 2);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Timer Behavior
|
|
172
|
+
|
|
173
|
+
Timeouts:
|
|
174
|
+
|
|
175
|
+
- execute once
|
|
176
|
+
- execute only after the clock reaches their scheduled monotonic time
|
|
177
|
+
- execute in scheduled monotonic time order
|
|
178
|
+
- execute in registration order when multiple timeouts share the same scheduled time
|
|
179
|
+
- can use a delay of `0`
|
|
180
|
+
- reject negative and non-finite delays
|
|
181
|
+
|
|
182
|
+
Intervals:
|
|
183
|
+
|
|
184
|
+
- execute repeatedly
|
|
185
|
+
- execute once per elapsed interval when time advances
|
|
186
|
+
- stop after `clearInterval`
|
|
187
|
+
- reject `0`, negative, non-finite, and sub-microsecond delays
|
|
188
|
+
|
|
189
|
+
The deterministic clock rejects intervals that would round down to zero microseconds because they cannot advance safely.
|
|
190
|
+
|
|
191
|
+
## API
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
declare const timeoutIdentifierBrand: unique symbol;
|
|
195
|
+
declare const intervalIdentifierBrand: unique symbol;
|
|
196
|
+
|
|
197
|
+
export type TimeoutIdentifier = {
|
|
198
|
+
readonly [timeoutIdentifierBrand]: 'TimeoutIdentifier';
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
export type IntervalIdentifier = {
|
|
202
|
+
readonly [intervalIdentifierBrand]: 'IntervalIdentifier';
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export type Clock = {
|
|
206
|
+
readonly currentDate: Date;
|
|
207
|
+
readonly currentUnixEpochMilliseconds: number;
|
|
208
|
+
readonly currentUnixEpochMicroseconds: bigint;
|
|
209
|
+
readonly monotonicTimeOriginUnixEpochMicroseconds: bigint;
|
|
210
|
+
readonly currentMonotonicMicroseconds: bigint;
|
|
211
|
+
readonly setTimeout: <HandlerArguments extends readonly unknown[]>(
|
|
212
|
+
handler: (...handlerArguments: HandlerArguments) => void,
|
|
213
|
+
delayInMilliseconds: number,
|
|
214
|
+
...handlerArguments: HandlerArguments
|
|
215
|
+
) => TimeoutIdentifier;
|
|
216
|
+
readonly clearTimeout: (timeoutIdentifier: TimeoutIdentifier) => void;
|
|
217
|
+
readonly setInterval: <HandlerArguments extends readonly unknown[]>(
|
|
218
|
+
handler: (...handlerArguments: HandlerArguments) => void,
|
|
219
|
+
delayInMilliseconds: number,
|
|
220
|
+
...handlerArguments: HandlerArguments
|
|
221
|
+
) => IntervalIdentifier;
|
|
222
|
+
readonly clearInterval: (intervalIdentifier: IntervalIdentifier) => void;
|
|
223
|
+
};
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
export type DeterministicClock = Clock & {
|
|
228
|
+
readonly setCurrentUnixEpochMicroseconds: (nextUnixEpochMicroseconds: bigint) => void;
|
|
229
|
+
readonly advanceByMicroseconds: (delayInMicroseconds: bigint) => void;
|
|
230
|
+
readonly advanceByMilliseconds: (delayInMilliseconds: number) => void;
|
|
231
|
+
};
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
export function createClock(): Clock;
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
export function createTemporalClock(): Clock;
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
export function createDeterministicClock(options: {
|
|
244
|
+
readonly initialUnixEpochMicroseconds: bigint;
|
|
245
|
+
}): DeterministicClock;
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Development
|
|
249
|
+
|
|
250
|
+
Install dependencies:
|
|
251
|
+
|
|
252
|
+
```sh
|
|
253
|
+
npm clean-install
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Compile:
|
|
257
|
+
|
|
258
|
+
```sh
|
|
259
|
+
just compile
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Run lint checks:
|
|
263
|
+
|
|
264
|
+
```sh
|
|
265
|
+
just lint
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Run tests:
|
|
269
|
+
|
|
270
|
+
```sh
|
|
271
|
+
just test
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Run a Packtory dry-run:
|
|
275
|
+
|
|
276
|
+
```sh
|
|
277
|
+
just packtory-dry-run
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Publishing
|
|
281
|
+
|
|
282
|
+
Pull requests that should appear in the changelog need exactly one changelog label. Supported labels:
|
|
283
|
+
|
|
284
|
+
- `breaking`
|
|
285
|
+
- `bug`
|
|
286
|
+
- `feature`
|
|
287
|
+
- `enhancement`
|
|
288
|
+
- `documentation`
|
|
289
|
+
- `upgrade`
|
|
290
|
+
- `refactor`
|
|
291
|
+
- `build`
|
|
292
|
+
|
|
293
|
+
The package is released through a release pull request:
|
|
294
|
+
|
|
295
|
+
1. Go to GitHub Actions -> Release -> Run workflow.
|
|
296
|
+
2. The workflow creates or updates a `Prepare release` pull request with the generated `CHANGELOG.md` changes.
|
|
297
|
+
3. Review and merge the release pull request through the normal merge queue.
|
|
298
|
+
4. After the release pull request is merged, the publish workflow publishes to npm, pushes the package tag, and creates
|
|
299
|
+
the GitHub Release.
|
|
300
|
+
|
|
301
|
+
The dry-run command validates the package shape without publishing.
|
|
302
|
+
|
|
303
|
+
```sh
|
|
304
|
+
just packtory-dry-run
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Inspect the next release plan:
|
|
308
|
+
|
|
309
|
+
```sh
|
|
310
|
+
just release-plan
|
|
311
|
+
```
|
package/clock.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
declare const timeoutIdentifierBrand: unique symbol;
|
|
2
|
+
declare const intervalIdentifierBrand: unique symbol;
|
|
3
|
+
export type TimeoutIdentifier = {
|
|
4
|
+
readonly [timeoutIdentifierBrand]: 'TimeoutIdentifier';
|
|
5
|
+
};
|
|
6
|
+
export type IntervalIdentifier = {
|
|
7
|
+
readonly [intervalIdentifierBrand]: 'IntervalIdentifier';
|
|
8
|
+
};
|
|
9
|
+
export type Clock = {
|
|
10
|
+
readonly currentDate: Date;
|
|
11
|
+
readonly currentUnixEpochMilliseconds: number;
|
|
12
|
+
readonly currentUnixEpochMicroseconds: bigint;
|
|
13
|
+
readonly monotonicTimeOriginUnixEpochMicroseconds: bigint;
|
|
14
|
+
readonly currentMonotonicMicroseconds: bigint;
|
|
15
|
+
readonly setTimeout: <HandlerArguments extends readonly unknown[]>(handler: (...handlerArguments: HandlerArguments) => void, delayInMilliseconds: number, ...handlerArguments: HandlerArguments) => TimeoutIdentifier;
|
|
16
|
+
readonly clearTimeout: (timeoutIdentifier: TimeoutIdentifier) => void;
|
|
17
|
+
readonly setInterval: <HandlerArguments extends readonly unknown[]>(handler: (...handlerArguments: HandlerArguments) => void, delayInMilliseconds: number, ...handlerArguments: HandlerArguments) => IntervalIdentifier;
|
|
18
|
+
readonly clearInterval: (intervalIdentifier: IntervalIdentifier) => void;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=clock.d.ts.map
|
package/clock.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../../source/clock.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,sBAAsB,EAAE,OAAO,MAAM,CAAC;AACpD,OAAO,CAAC,MAAM,uBAAuB,EAAE,OAAO,MAAM,CAAC;AAErD,MAAM,MAAM,iBAAiB,GAAG;IAC5B,QAAQ,CAAC,CAAC,sBAAsB,CAAC,EAAE,mBAAmB,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC7B,QAAQ,CAAC,CAAC,uBAAuB,CAAC,EAAE,oBAAoB,CAAC;CAC5D,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAChB,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,4BAA4B,EAAE,MAAM,CAAC;IAC9C,QAAQ,CAAC,4BAA4B,EAAE,MAAM,CAAC;IAC9C,QAAQ,CAAC,wCAAwC,EAAE,MAAM,CAAC;IAC1D,QAAQ,CAAC,4BAA4B,EAAE,MAAM,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,CAAC,gBAAgB,SAAS,SAAS,OAAO,EAAE,EAC7D,OAAO,EAAE,CAAC,GAAG,gBAAgB,EAAE,gBAAgB,KAAK,IAAI,EACxD,mBAAmB,EAAE,MAAM,EAC3B,GAAG,gBAAgB,EAAE,gBAAgB,KACpC,iBAAiB,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,CAAC,iBAAiB,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACtE,QAAQ,CAAC,WAAW,EAAE,CAAC,gBAAgB,SAAS,SAAS,OAAO,EAAE,EAC9D,OAAO,EAAE,CAAC,GAAG,gBAAgB,EAAE,gBAAgB,KAAK,IAAI,EACxD,mBAAmB,EAAE,MAAM,EAC3B,GAAG,gBAAgB,EAAE,gBAAgB,KACpC,kBAAkB,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,CAAC,kBAAkB,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC5E,CAAC;AAEF,MAAM,CAA0B,EAS/B,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Clock as RuntimeClock, type IntervalIdentifier as RuntimeIntervalIdentifier, type TimeoutIdentifier as RuntimeTimeoutIdentifier } from './clock.ts';
|
|
2
|
+
export type Clock = RuntimeClock;
|
|
3
|
+
export type TimeoutIdentifier = RuntimeTimeoutIdentifier;
|
|
4
|
+
export type IntervalIdentifier = RuntimeIntervalIdentifier;
|
|
5
|
+
export declare function createClock(): RuntimeClock;
|
|
6
|
+
//# sourceMappingURL=clock.entry-point.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.entry-point.d.ts","sourceRoot":"","sources":["../../../source/clock.entry-point.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,KAAK,IAAI,YAAY,EAC1B,KAAK,kBAAkB,IAAI,yBAAyB,EACpD,KAAK,iBAAiB,IAAI,wBAAwB,EACrD,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,KAAK,GAAG,YAAY,CAAC;AACjC,MAAM,MAAM,iBAAiB,GAAG,wBAAwB,CAAC;AACzD,MAAM,MAAM,kBAAkB,GAAG,yBAAyB,CAAC;AAE3D,wBAAgB,WAAW,IAAI,YAAY,CA+B1C"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createClock as createClockFromDependencies } from "./clock.js";
|
|
2
|
+
export function createClock() {
|
|
3
|
+
return createClockFromDependencies({
|
|
4
|
+
currentDate() {
|
|
5
|
+
return new Date();
|
|
6
|
+
},
|
|
7
|
+
currentUnixEpochMilliseconds() {
|
|
8
|
+
return Date.now();
|
|
9
|
+
},
|
|
10
|
+
monotonicTimeOriginMilliseconds: globalThis.performance.timeOrigin,
|
|
11
|
+
currentMonotonicMilliseconds: globalThis.performance.now.bind(globalThis.performance),
|
|
12
|
+
setTimeout(handler, delayInMilliseconds, ...handlerArguments) {
|
|
13
|
+
return globalThis.setTimeout(handler, delayInMilliseconds, ...handlerArguments);
|
|
14
|
+
},
|
|
15
|
+
clearTimeout(timeoutIdentifier) {
|
|
16
|
+
globalThis.clearTimeout(timeoutIdentifier);
|
|
17
|
+
},
|
|
18
|
+
setInterval(handler, delayInMilliseconds, ...handlerArguments) {
|
|
19
|
+
return globalThis.setInterval(handler, delayInMilliseconds, ...handlerArguments);
|
|
20
|
+
},
|
|
21
|
+
clearInterval(intervalIdentifier) {
|
|
22
|
+
globalThis.clearInterval(intervalIdentifier);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=clock.entry-point.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.entry-point.js","sourceRoot":"","sources":["../../../source/clock.entry-point.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,WAAW,IAAI,2BAA2B,EAI7C,MAAM,YAAY,CAAC;AAMpB,MAAM,UAAU,WAAW;IACvB,OAAO,2BAA2B,CAAC;QAC/B,WAAW;YACP,OAAO,IAAI,IAAI,EAAE,CAAC;QACtB,CAAC;QACD,4BAA4B;YACxB,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;QACtB,CAAC;QACD,+BAA+B,EAAE,UAAU,CAAC,WAAW,CAAC,UAAU;QAClE,4BAA4B,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QACrF,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,gBAAgB;YACxD,OAAO,UAAU,CAAC,UAAU,CACxB,OAAO,EACP,mBAAmB,EACnB,GAAG,gBAAgB,CACiB,CAAC;QAC7C,CAAC;QACD,YAAY,CAAC,iBAAiB;YAC1B,UAAU,CAAC,YAAY,CAAC,iBAAwE,CAAC,CAAC;QACtG,CAAC;QACD,WAAW,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,gBAAgB;YACzD,OAAO,UAAU,CAAC,WAAW,CACzB,OAAO,EACP,mBAAmB,EACnB,GAAG,gBAAgB,CACkB,CAAC;QAC9C,CAAC;QACD,aAAa,CAAC,kBAAkB;YAC5B,UAAU,CAAC,aAAa,CAAC,kBAA0E,CAAC,CAAC;QACzG,CAAC;KACJ,CAAC,CAAC;AACP,CAAC"}
|
package/clock.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const microsecondsPerMillisecond = 1000n;
|
|
2
|
+
function millisecondsToMicroseconds(milliseconds) {
|
|
3
|
+
return BigInt(Math.floor(milliseconds * Number(microsecondsPerMillisecond)));
|
|
4
|
+
}
|
|
5
|
+
export function createClock(dependencies) {
|
|
6
|
+
return {
|
|
7
|
+
get currentDate() {
|
|
8
|
+
return dependencies.currentDate();
|
|
9
|
+
},
|
|
10
|
+
get currentUnixEpochMilliseconds() {
|
|
11
|
+
return dependencies.currentUnixEpochMilliseconds();
|
|
12
|
+
},
|
|
13
|
+
get currentUnixEpochMicroseconds() {
|
|
14
|
+
return millisecondsToMicroseconds(dependencies.currentUnixEpochMilliseconds());
|
|
15
|
+
},
|
|
16
|
+
get monotonicTimeOriginUnixEpochMicroseconds() {
|
|
17
|
+
return millisecondsToMicroseconds(dependencies.monotonicTimeOriginMilliseconds);
|
|
18
|
+
},
|
|
19
|
+
get currentMonotonicMicroseconds() {
|
|
20
|
+
return millisecondsToMicroseconds(dependencies.currentMonotonicMilliseconds());
|
|
21
|
+
},
|
|
22
|
+
setTimeout: dependencies.setTimeout,
|
|
23
|
+
clearTimeout: dependencies.clearTimeout,
|
|
24
|
+
setInterval: dependencies.setInterval,
|
|
25
|
+
clearInterval: dependencies.clearInterval
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=clock.js.map
|
package/clock.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.js","sourceRoot":"","sources":["../../../source/clock.ts"],"names":[],"mappings":"AAAA,MAAM,0BAA0B,GAAG,KAAK,CAAC;AA4CzC,SAAS,0BAA0B,CAAC,YAAoB;IACpD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,YAA+B;IACvD,OAAO;QACH,IAAI,WAAW;YACX,OAAO,YAAY,CAAC,WAAW,EAAE,CAAC;QACtC,CAAC;QAED,IAAI,4BAA4B;YAC5B,OAAO,YAAY,CAAC,4BAA4B,EAAE,CAAC;QACvD,CAAC;QAED,IAAI,4BAA4B;YAC5B,OAAO,0BAA0B,CAAC,YAAY,CAAC,4BAA4B,EAAE,CAAC,CAAC;QACnF,CAAC;QAED,IAAI,wCAAwC;YACxC,OAAO,0BAA0B,CAAC,YAAY,CAAC,+BAA+B,CAAC,CAAC;QACpF,CAAC;QAED,IAAI,4BAA4B;YAC5B,OAAO,0BAA0B,CAAC,YAAY,CAAC,4BAA4B,EAAE,CAAC,CAAC;QACnF,CAAC;QAED,UAAU,EAAE,YAAY,CAAC,UAAU;QAEnC,YAAY,EAAE,YAAY,CAAC,YAAY;QAEvC,WAAW,EAAE,YAAY,CAAC,WAAW;QAErC,aAAa,EAAE,YAAY,CAAC,aAAa;KAC5C,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Clock } from './clock.ts';
|
|
2
|
+
export type DeterministicClock = Clock & {
|
|
3
|
+
readonly setCurrentUnixEpochMicroseconds: (nextUnixEpochMicroseconds: bigint) => void;
|
|
4
|
+
readonly advanceByMicroseconds: (delayInMicroseconds: bigint) => void;
|
|
5
|
+
readonly advanceByMilliseconds: (delayInMilliseconds: number) => void;
|
|
6
|
+
};
|
|
7
|
+
export type DeterministicClockOptions = {
|
|
8
|
+
readonly initialUnixEpochMicroseconds: bigint;
|
|
9
|
+
};
|
|
10
|
+
export declare function createDeterministicClock(options: DeterministicClockOptions): DeterministicClock;
|
|
11
|
+
//# sourceMappingURL=deterministic-clock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deterministic-clock.d.ts","sourceRoot":"","sources":["../../../source/deterministic-clock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGxC,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG;IACrC,QAAQ,CAAC,+BAA+B,EAAE,CAAC,yBAAyB,EAAE,MAAM,KAAK,IAAI,CAAC;IACtF,QAAQ,CAAC,qBAAqB,EAAE,CAAC,mBAAmB,EAAE,MAAM,KAAK,IAAI,CAAC;IACtE,QAAQ,CAAC,qBAAqB,EAAE,CAAC,mBAAmB,EAAE,MAAM,KAAK,IAAI,CAAC;CACzE,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG;IACpC,QAAQ,CAAC,4BAA4B,EAAE,MAAM,CAAC;CACjD,CAAC;AA4LF,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,yBAAyB,GAAG,kBAAkB,CAkE/F"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { validateIntervalDelayInMilliseconds, validateTimeoutDelayInMilliseconds } from "./timer-delay.js";
|
|
2
|
+
const microsecondsPerMillisecond = 1000n;
|
|
3
|
+
const minimumDelayInMicroseconds = 0n;
|
|
4
|
+
function compareMicroseconds(firstMicroseconds, secondMicroseconds) {
|
|
5
|
+
if (firstMicroseconds < secondMicroseconds) {
|
|
6
|
+
return -1;
|
|
7
|
+
}
|
|
8
|
+
if (firstMicroseconds > secondMicroseconds) {
|
|
9
|
+
return 1;
|
|
10
|
+
}
|
|
11
|
+
return 0;
|
|
12
|
+
}
|
|
13
|
+
function compareTimeoutEntries(firstTimeoutEntry, secondTimeoutEntry) {
|
|
14
|
+
const [firstTimeoutIdentifier, firstTimeoutRegistration] = firstTimeoutEntry;
|
|
15
|
+
const [secondTimeoutIdentifier, secondTimeoutRegistration] = secondTimeoutEntry;
|
|
16
|
+
const timeoutExecutionOrder = compareMicroseconds(firstTimeoutRegistration.executionMonotonicMicroseconds, secondTimeoutRegistration.executionMonotonicMicroseconds);
|
|
17
|
+
if (timeoutExecutionOrder !== 0) {
|
|
18
|
+
return timeoutExecutionOrder;
|
|
19
|
+
}
|
|
20
|
+
return firstTimeoutIdentifier - secondTimeoutIdentifier;
|
|
21
|
+
}
|
|
22
|
+
function millisecondsToMicroseconds(milliseconds) {
|
|
23
|
+
return BigInt(Math.floor(milliseconds * Number(microsecondsPerMillisecond)));
|
|
24
|
+
}
|
|
25
|
+
function unixEpochMillisecondsFromMicroseconds(unixEpochMicroseconds) {
|
|
26
|
+
return Number(unixEpochMicroseconds / microsecondsPerMillisecond);
|
|
27
|
+
}
|
|
28
|
+
function ensureValidDateUnixEpochMicroseconds(unixEpochMicroseconds) {
|
|
29
|
+
const unixEpochMilliseconds = unixEpochMillisecondsFromMicroseconds(unixEpochMicroseconds);
|
|
30
|
+
const date = new Date(unixEpochMilliseconds);
|
|
31
|
+
if (Number.isNaN(date.getTime())) {
|
|
32
|
+
throw new RangeError('Invalid Unix epoch microseconds, must be representable as a Date');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function validateDelayInMicroseconds(delayInMicroseconds) {
|
|
36
|
+
if (delayInMicroseconds < minimumDelayInMicroseconds) {
|
|
37
|
+
throw new RangeError(`Invalid delay ${delayInMicroseconds.toString()}, must be greater than or equal to 0`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function createTimeoutController(currentMonotonicMicroseconds) {
|
|
41
|
+
let nextTimeoutIdentifier = 0;
|
|
42
|
+
const timeoutRegistrations = new Map();
|
|
43
|
+
function runDueTimeoutRegistrations() {
|
|
44
|
+
const dueTimeoutEntries = Array
|
|
45
|
+
.from(timeoutRegistrations)
|
|
46
|
+
.filter(function ([, timeoutRegistration]) {
|
|
47
|
+
return timeoutRegistration.executionMonotonicMicroseconds <= currentMonotonicMicroseconds();
|
|
48
|
+
})
|
|
49
|
+
.toSorted(compareTimeoutEntries);
|
|
50
|
+
dueTimeoutEntries.forEach(function ([timeoutIdentifier, timeoutRegistration]) {
|
|
51
|
+
timeoutRegistrations.delete(timeoutIdentifier);
|
|
52
|
+
timeoutRegistration.execute();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
runDueTimeoutRegistrations,
|
|
57
|
+
setTimeout(handler, delayInMilliseconds, ...handlerArguments) {
|
|
58
|
+
validateTimeoutDelayInMilliseconds(delayInMilliseconds);
|
|
59
|
+
const timeoutIdentifier = nextTimeoutIdentifier;
|
|
60
|
+
nextTimeoutIdentifier += 1;
|
|
61
|
+
const delayInMicroseconds = millisecondsToMicroseconds(delayInMilliseconds);
|
|
62
|
+
timeoutRegistrations.set(timeoutIdentifier, {
|
|
63
|
+
execute() {
|
|
64
|
+
handler(...handlerArguments);
|
|
65
|
+
},
|
|
66
|
+
executionMonotonicMicroseconds: currentMonotonicMicroseconds() + delayInMicroseconds
|
|
67
|
+
});
|
|
68
|
+
return timeoutIdentifier;
|
|
69
|
+
},
|
|
70
|
+
clearTimeout(timeoutIdentifier) {
|
|
71
|
+
timeoutRegistrations.delete(timeoutIdentifier);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function createIntervalController(currentMonotonicMicroseconds) {
|
|
76
|
+
let nextIntervalIdentifier = 0;
|
|
77
|
+
const intervalRegistrations = new Map();
|
|
78
|
+
function runDueIntervalRegistrations() {
|
|
79
|
+
intervalRegistrations.forEach(function (intervalRegistration, intervalIdentifier) {
|
|
80
|
+
const { delayInMicroseconds, execute } = intervalRegistration;
|
|
81
|
+
let { nextExecutionMonotonicMicroseconds } = intervalRegistration;
|
|
82
|
+
while (nextExecutionMonotonicMicroseconds <= currentMonotonicMicroseconds()) {
|
|
83
|
+
execute();
|
|
84
|
+
if (!intervalRegistrations.has(intervalIdentifier)) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
nextExecutionMonotonicMicroseconds += delayInMicroseconds;
|
|
88
|
+
intervalRegistrations.set(intervalIdentifier, {
|
|
89
|
+
delayInMicroseconds,
|
|
90
|
+
execute,
|
|
91
|
+
nextExecutionMonotonicMicroseconds
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
runDueIntervalRegistrations,
|
|
98
|
+
setInterval(handler, delayInMilliseconds, ...handlerArguments) {
|
|
99
|
+
validateIntervalDelayInMilliseconds(delayInMilliseconds);
|
|
100
|
+
const intervalIdentifier = nextIntervalIdentifier;
|
|
101
|
+
nextIntervalIdentifier += 1;
|
|
102
|
+
const delayInMicroseconds = millisecondsToMicroseconds(delayInMilliseconds);
|
|
103
|
+
if (delayInMicroseconds <= minimumDelayInMicroseconds) {
|
|
104
|
+
throw new RangeError(`Invalid interval delay ${delayInMilliseconds}, must be at least 1 microsecond`);
|
|
105
|
+
}
|
|
106
|
+
intervalRegistrations.set(intervalIdentifier, {
|
|
107
|
+
delayInMicroseconds,
|
|
108
|
+
execute() {
|
|
109
|
+
handler(...handlerArguments);
|
|
110
|
+
},
|
|
111
|
+
nextExecutionMonotonicMicroseconds: currentMonotonicMicroseconds() + delayInMicroseconds
|
|
112
|
+
});
|
|
113
|
+
return intervalIdentifier;
|
|
114
|
+
},
|
|
115
|
+
clearInterval(intervalIdentifier) {
|
|
116
|
+
intervalRegistrations.delete(intervalIdentifier);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
export function createDeterministicClock(options) {
|
|
121
|
+
const { initialUnixEpochMicroseconds } = options;
|
|
122
|
+
ensureValidDateUnixEpochMicroseconds(initialUnixEpochMicroseconds);
|
|
123
|
+
let currentUnixEpochMicroseconds = initialUnixEpochMicroseconds;
|
|
124
|
+
let currentMonotonicMicroseconds = minimumDelayInMicroseconds;
|
|
125
|
+
function currentMonotonicMicrosecondsReader() {
|
|
126
|
+
return currentMonotonicMicroseconds;
|
|
127
|
+
}
|
|
128
|
+
const timeoutController = createTimeoutController(currentMonotonicMicrosecondsReader);
|
|
129
|
+
const intervalController = createIntervalController(currentMonotonicMicrosecondsReader);
|
|
130
|
+
function advanceClockByMicroseconds(delayInMicroseconds) {
|
|
131
|
+
validateDelayInMicroseconds(delayInMicroseconds);
|
|
132
|
+
const nextUnixEpochMicroseconds = currentUnixEpochMicroseconds + delayInMicroseconds;
|
|
133
|
+
ensureValidDateUnixEpochMicroseconds(nextUnixEpochMicroseconds);
|
|
134
|
+
currentUnixEpochMicroseconds = nextUnixEpochMicroseconds;
|
|
135
|
+
currentMonotonicMicroseconds += delayInMicroseconds;
|
|
136
|
+
intervalController.runDueIntervalRegistrations();
|
|
137
|
+
timeoutController.runDueTimeoutRegistrations();
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
get currentDate() {
|
|
141
|
+
return new Date(unixEpochMillisecondsFromMicroseconds(currentUnixEpochMicroseconds));
|
|
142
|
+
},
|
|
143
|
+
get currentUnixEpochMilliseconds() {
|
|
144
|
+
return unixEpochMillisecondsFromMicroseconds(currentUnixEpochMicroseconds);
|
|
145
|
+
},
|
|
146
|
+
get currentUnixEpochMicroseconds() {
|
|
147
|
+
return currentUnixEpochMicroseconds;
|
|
148
|
+
},
|
|
149
|
+
get monotonicTimeOriginUnixEpochMicroseconds() {
|
|
150
|
+
return initialUnixEpochMicroseconds;
|
|
151
|
+
},
|
|
152
|
+
get currentMonotonicMicroseconds() {
|
|
153
|
+
return currentMonotonicMicroseconds;
|
|
154
|
+
},
|
|
155
|
+
setCurrentUnixEpochMicroseconds(nextUnixEpochMicroseconds) {
|
|
156
|
+
ensureValidDateUnixEpochMicroseconds(nextUnixEpochMicroseconds);
|
|
157
|
+
currentUnixEpochMicroseconds = nextUnixEpochMicroseconds;
|
|
158
|
+
},
|
|
159
|
+
advanceByMicroseconds: advanceClockByMicroseconds,
|
|
160
|
+
advanceByMilliseconds(delayInMilliseconds) {
|
|
161
|
+
validateTimeoutDelayInMilliseconds(delayInMilliseconds);
|
|
162
|
+
advanceClockByMicroseconds(millisecondsToMicroseconds(delayInMilliseconds));
|
|
163
|
+
},
|
|
164
|
+
setTimeout: timeoutController.setTimeout,
|
|
165
|
+
clearTimeout: timeoutController.clearTimeout,
|
|
166
|
+
setInterval: intervalController.setInterval,
|
|
167
|
+
clearInterval: intervalController.clearInterval
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=deterministic-clock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deterministic-clock.js","sourceRoot":"","sources":["../../../source/deterministic-clock.ts"],"names":[],"mappings":"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"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createClock } from './clock.entry-point.ts';
|
|
2
|
+
export type { Clock, IntervalIdentifier, TimeoutIdentifier } from './clock.entry-point.ts';
|
|
3
|
+
export { createTemporalClock } from './temporal-clock.entry-point.ts';
|
|
4
|
+
export { createDeterministicClock } from './deterministic-clock.ts';
|
|
5
|
+
export type { DeterministicClock, DeterministicClockOptions } from './deterministic-clock.ts';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
package/index.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../source/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,YAAY,EAAE,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,YAAY,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/index.js
ADDED
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../source/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,34 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
"author": "Christian Rackerseder <git@echooff.de>",
|
|
3
|
+
"description": "Explicit time and timer access for TypeScript applications",
|
|
4
|
+
"engines": {
|
|
5
|
+
"node": "^24.15.0 || ^26.0.0"
|
|
6
|
+
},
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./index.js",
|
|
10
|
+
"types": "./index.d.ts"
|
|
11
|
+
},
|
|
12
|
+
"./clock": {
|
|
13
|
+
"import": "./clock.entry-point.js",
|
|
14
|
+
"types": "./clock.entry-point.d.ts"
|
|
15
|
+
},
|
|
16
|
+
"./deterministic-clock": {
|
|
17
|
+
"import": "./deterministic-clock.js",
|
|
18
|
+
"types": "./deterministic-clock.d.ts"
|
|
19
|
+
},
|
|
20
|
+
"./temporal-clock": {
|
|
21
|
+
"import": "./temporal-clock.entry-point.js",
|
|
22
|
+
"types": "./temporal-clock.entry-point.d.ts"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"name": "@enormora/clock",
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+ssh://git@github.com/enormora/clock.git"
|
|
30
|
+
},
|
|
31
|
+
"sideEffects": false,
|
|
32
|
+
"type": "module",
|
|
33
|
+
"version": "0.0.2"
|
|
34
|
+
}
|
package/sbom.cdx.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
|
|
3
|
+
"bomFormat": "CycloneDX",
|
|
4
|
+
"specVersion": "1.6",
|
|
5
|
+
"version": 1,
|
|
6
|
+
"metadata": {
|
|
7
|
+
"tools": {
|
|
8
|
+
"components": [
|
|
9
|
+
{
|
|
10
|
+
"type": "application",
|
|
11
|
+
"name": "packtory",
|
|
12
|
+
"version": "0.0.114"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
"component": {
|
|
17
|
+
"type": "library",
|
|
18
|
+
"name": "@enormora/clock",
|
|
19
|
+
"version": "0.0.2",
|
|
20
|
+
"bom-ref": "pkg:npm/@enormora/clock@0.0.2",
|
|
21
|
+
"purl": "pkg:npm/@enormora/clock@0.0.2"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"components": [],
|
|
25
|
+
"dependencies": [
|
|
26
|
+
{
|
|
27
|
+
"ref": "pkg:npm/@enormora/clock@0.0.2"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temporal-clock.entry-point.d.ts","sourceRoot":"","sources":["../../../source/temporal-clock.entry-point.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACR,KAAK,EAGR,MAAM,YAAY,CAAC;AA2BpB,wBAAgB,mBAAmB,IAAI,KAAK,CA4B3C"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createTemporalClock as createTemporalClockFromDependencies } from "./temporal-clock.js";
|
|
2
|
+
function readTemporalClockApi() {
|
|
3
|
+
const temporalClockApi = globalThis.Temporal;
|
|
4
|
+
if (temporalClockApi === undefined) {
|
|
5
|
+
throw new ReferenceError('Temporal is not available');
|
|
6
|
+
}
|
|
7
|
+
return temporalClockApi;
|
|
8
|
+
}
|
|
9
|
+
export function createTemporalClock() {
|
|
10
|
+
const temporalClockApi = readTemporalClockApi();
|
|
11
|
+
return createTemporalClockFromDependencies({
|
|
12
|
+
currentInstant: temporalClockApi.Now.instant.bind(temporalClockApi.Now),
|
|
13
|
+
monotonicTimeOriginMilliseconds: globalThis.performance.timeOrigin,
|
|
14
|
+
currentMonotonicMilliseconds: globalThis.performance.now.bind(globalThis.performance),
|
|
15
|
+
setTimeout(handler, delayInMilliseconds, ...handlerArguments) {
|
|
16
|
+
return globalThis.setTimeout(handler, delayInMilliseconds, ...handlerArguments);
|
|
17
|
+
},
|
|
18
|
+
clearTimeout(timeoutIdentifier) {
|
|
19
|
+
globalThis.clearTimeout(timeoutIdentifier);
|
|
20
|
+
},
|
|
21
|
+
setInterval(handler, delayInMilliseconds, ...handlerArguments) {
|
|
22
|
+
return globalThis.setInterval(handler, delayInMilliseconds, ...handlerArguments);
|
|
23
|
+
},
|
|
24
|
+
clearInterval(intervalIdentifier) {
|
|
25
|
+
globalThis.clearInterval(intervalIdentifier);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=temporal-clock.entry-point.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temporal-clock.entry-point.js","sourceRoot":"","sources":["../../../source/temporal-clock.entry-point.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,IAAI,mCAAmC,EAAE,MAAM,qBAAqB,CAAC;AAsBjG,SAAS,oBAAoB;IACzB,MAAM,gBAAgB,GAAI,UAAoC,CAAC,QAAQ,CAAC;IAExE,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,IAAI,cAAc,CAAC,2BAA2B,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,mBAAmB;IAC/B,MAAM,gBAAgB,GAAG,oBAAoB,EAAE,CAAC;IAEhD,OAAO,mCAAmC,CAAC;QACvC,cAAc,EAAE,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC;QACvE,+BAA+B,EAAE,UAAU,CAAC,WAAW,CAAC,UAAU;QAClE,4BAA4B,EAAE,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QACrF,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,gBAAgB;YACxD,OAAO,UAAU,CAAC,UAAU,CACxB,OAAO,EACP,mBAAmB,EACnB,GAAG,gBAAgB,CACiB,CAAC;QAC7C,CAAC;QACD,YAAY,CAAC,iBAAiB;YAC1B,UAAU,CAAC,YAAY,CAAC,iBAAwE,CAAC,CAAC;QACtG,CAAC;QACD,WAAW,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,gBAAgB;YACzD,OAAO,UAAU,CAAC,WAAW,CACzB,OAAO,EACP,mBAAmB,EACnB,GAAG,gBAAgB,CACkB,CAAC;QAC9C,CAAC;QACD,aAAa,CAAC,kBAAkB;YAC5B,UAAU,CAAC,aAAa,CAAC,kBAA0E,CAAC,CAAC;QACzG,CAAC;KACJ,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const microsecondsPerMillisecond = 1000;
|
|
2
|
+
const nanosecondsPerMicrosecond = 1000n;
|
|
3
|
+
function millisecondsToMicroseconds(milliseconds) {
|
|
4
|
+
return BigInt(Math.floor(milliseconds * microsecondsPerMillisecond));
|
|
5
|
+
}
|
|
6
|
+
export function createTemporalClock(dependencies) {
|
|
7
|
+
return {
|
|
8
|
+
get currentDate() {
|
|
9
|
+
return new Date(dependencies.currentInstant().epochMilliseconds);
|
|
10
|
+
},
|
|
11
|
+
get currentUnixEpochMilliseconds() {
|
|
12
|
+
return dependencies.currentInstant().epochMilliseconds;
|
|
13
|
+
},
|
|
14
|
+
get currentUnixEpochMicroseconds() {
|
|
15
|
+
return dependencies.currentInstant().epochNanoseconds / nanosecondsPerMicrosecond;
|
|
16
|
+
},
|
|
17
|
+
get monotonicTimeOriginUnixEpochMicroseconds() {
|
|
18
|
+
return millisecondsToMicroseconds(dependencies.monotonicTimeOriginMilliseconds);
|
|
19
|
+
},
|
|
20
|
+
get currentMonotonicMicroseconds() {
|
|
21
|
+
return millisecondsToMicroseconds(dependencies.currentMonotonicMilliseconds());
|
|
22
|
+
},
|
|
23
|
+
setTimeout: dependencies.setTimeout,
|
|
24
|
+
clearTimeout: dependencies.clearTimeout,
|
|
25
|
+
setInterval: dependencies.setInterval,
|
|
26
|
+
clearInterval: dependencies.clearInterval
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=temporal-clock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temporal-clock.js","sourceRoot":"","sources":["../../../source/temporal-clock.ts"],"names":[],"mappings":"AAiBA,MAAM,0BAA0B,GAAG,IAAI,CAAC;AACxC,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAExC,SAAS,0BAA0B,CAAC,YAAoB;IACpD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,0BAA0B,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,YAAuC;IACvE,OAAO;QACH,IAAI,WAAW;YACX,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC,iBAAiB,CAAC,CAAC;QACrE,CAAC;QAED,IAAI,4BAA4B;YAC5B,OAAO,YAAY,CAAC,cAAc,EAAE,CAAC,iBAAiB,CAAC;QAC3D,CAAC;QAED,IAAI,4BAA4B;YAC5B,OAAO,YAAY,CAAC,cAAc,EAAE,CAAC,gBAAgB,GAAG,yBAAyB,CAAC;QACtF,CAAC;QAED,IAAI,wCAAwC;YACxC,OAAO,0BAA0B,CAAC,YAAY,CAAC,+BAA+B,CAAC,CAAC;QACpF,CAAC;QAED,IAAI,4BAA4B;YAC5B,OAAO,0BAA0B,CAAC,YAAY,CAAC,4BAA4B,EAAE,CAAC,CAAC;QACnF,CAAC;QAED,UAAU,EAAE,YAAY,CAAC,UAAU;QAEnC,YAAY,EAAE,YAAY,CAAC,YAAY;QAEvC,WAAW,EAAE,YAAY,CAAC,WAAW;QAErC,aAAa,EAAE,YAAY,CAAC,aAAa;KAC5C,CAAC;AACN,CAAC"}
|
package/timer-delay.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function validateFiniteDelayInMilliseconds(delayInMilliseconds) {
|
|
2
|
+
if (!Number.isFinite(delayInMilliseconds)) {
|
|
3
|
+
throw new TypeError('Invalid delay, must be a finite number');
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
export function validateTimeoutDelayInMilliseconds(delayInMilliseconds) {
|
|
7
|
+
validateFiniteDelayInMilliseconds(delayInMilliseconds);
|
|
8
|
+
if (delayInMilliseconds < 0) {
|
|
9
|
+
throw new RangeError(`Invalid timeout delay ${delayInMilliseconds}, must be greater than or equal to 0`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function validateIntervalDelayInMilliseconds(delayInMilliseconds) {
|
|
13
|
+
validateFiniteDelayInMilliseconds(delayInMilliseconds);
|
|
14
|
+
if (delayInMilliseconds <= 0) {
|
|
15
|
+
throw new RangeError(`Invalid interval delay ${delayInMilliseconds}, must be greater than 0`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=timer-delay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timer-delay.js","sourceRoot":"","sources":["../../../source/timer-delay.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,iCAAiC,CAAC,mBAA2B;IACzE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAC;IAClE,CAAC;AACL,CAAC;AAED,MAAM,UAAU,kCAAkC,CAAC,mBAA2B;IAC1E,iCAAiC,CAAC,mBAAmB,CAAC,CAAC;IAEvD,IAAI,mBAAmB,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,UAAU,CAAC,yBAAyB,mBAAmB,sCAAsC,CAAC,CAAC;IAC7G,CAAC;AACL,CAAC;AAED,MAAM,UAAU,mCAAmC,CAAC,mBAA2B;IAC3E,iCAAiC,CAAC,mBAAmB,CAAC,CAAC;IAEvD,IAAI,mBAAmB,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CAAC,0BAA0B,mBAAmB,0BAA0B,CAAC,CAAC;IAClG,CAAC;AACL,CAAC"}
|
package/readme.md
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
# @enormora/clock
|
|
2
|
-
|
|
3
|
-
This version is a placeholder published only to claim the npm name `@enormora/clock` so a Trusted Publisher
|
|
4
|
-
can subsequently be configured for it. It contains no real package content and is published already
|
|
5
|
-
deprecated.
|
|
6
|
-
|
|
7
|
-
Workaround context: https://github.com/npm/cli/issues/8544
|