@oscarpalmer/timer 0.31.0 → 0.33.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.
package/dist/timer.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { noop } from '@oscarpalmer/atoms/function';
2
+ import { stop, work } from './work.js';
2
3
 
3
4
  class Timer {
4
- constructor(type, worker, state, options, start) {
5
- this.worker = worker;
5
+ constructor(type, state, options, start) {
6
6
  this.options = options;
7
7
  this.$timer = type;
8
8
  this.state = {
@@ -58,8 +58,17 @@ class Timer {
58
58
  this.options.onAfter = noop;
59
59
  this.options.onError = noop;
60
60
  this.state.callback = noop;
61
- this.state.trace = void 0;
62
- this.#work("stop");
61
+ if (!globalThis._oscarpalmer_timer_debug) {
62
+ this.state.trace = void 0;
63
+ }
64
+ stop(
65
+ {
66
+ instance: this,
67
+ type: this.$timer
68
+ },
69
+ this.state,
70
+ this.options
71
+ );
63
72
  }
64
73
  /**
65
74
  * Pause the timer _(if it's running)_
@@ -86,7 +95,7 @@ class Timer {
86
95
  return this.#work("stop");
87
96
  }
88
97
  #work(type) {
89
- return this.worker(
98
+ return work(
90
99
  type,
91
100
  {
92
101
  instance: this,
package/dist/wait.cjs CHANGED
@@ -4,14 +4,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const constants = require('./constants.cjs');
6
6
  const get = require('./get.cjs');
7
+ require('./global.cjs');
7
8
  const models = require('./models.cjs');
8
9
  const timer = require('./timer.cjs');
9
- const work = require('./work.cjs');
10
10
 
11
11
  function wait(callback, time) {
12
12
  return new timer.Timer(
13
13
  "wait",
14
- work.work,
15
14
  {
16
15
  callback: get.getCallback(callback),
17
16
  trace: new models.TimerTrace().stack
package/dist/wait.js CHANGED
@@ -1,13 +1,12 @@
1
1
  import { milliseconds } from './constants.js';
2
2
  import { getCallback, getValidNumber } from './get.js';
3
+ import './global.js';
3
4
  import { TimerTrace } from './models.js';
4
5
  import { Timer } from './timer.js';
5
- import { work } from './work.js';
6
6
 
7
7
  function wait(callback, time) {
8
8
  return new Timer(
9
9
  "wait",
10
- work,
11
10
  {
12
11
  callback: getCallback(callback),
13
12
  trace: new TimerTrace().stack
package/dist/when.cjs CHANGED
@@ -5,13 +5,19 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5
5
  const _function = require('@oscarpalmer/atoms/function');
6
6
  const constants = require('./constants.cjs');
7
7
  const get = require('./get.cjs');
8
+ require('./global.cjs');
8
9
  const models = require('./models.cjs');
9
10
  const timer = require('./timer.cjs');
10
- const work = require('./work.cjs');
11
11
 
12
12
  class When {
13
13
  $timer = "when";
14
- state;
14
+ state = {
15
+ promise: void 0,
16
+ rejecter: void 0,
17
+ resolver: void 0,
18
+ started: false,
19
+ timer: void 0
20
+ };
15
21
  /**
16
22
  * Is the timer active?
17
23
  */
@@ -36,8 +42,47 @@ class When {
36
42
  get trace() {
37
43
  return globalThis._oscarpalmer_timer_debug ?? false ? this.state.timer?.trace : void 0;
38
44
  }
39
- constructor(state) {
40
- this.state = state;
45
+ constructor(condition, options) {
46
+ const { state } = this;
47
+ state.promise = new Promise((resolve, reject) => {
48
+ state.resolver = resolve;
49
+ state.rejecter = reject;
50
+ });
51
+ let result = false;
52
+ this.state.timer = new timer.Timer(
53
+ "when",
54
+ {
55
+ callback() {
56
+ try {
57
+ if (condition()) {
58
+ result = true;
59
+ state.timer.stop();
60
+ }
61
+ } catch {
62
+ state.timer.stop();
63
+ }
64
+ },
65
+ trace: new models.TimerTrace().stack
66
+ },
67
+ {
68
+ onAfter: () => {
69
+ if (result) {
70
+ state.resolver?.();
71
+ } else {
72
+ state.rejecter?.();
73
+ }
74
+ this.destroy();
75
+ },
76
+ onError: () => {
77
+ state.rejecter?.();
78
+ this.destroy();
79
+ },
80
+ count: get.getValidNumber(options?.count),
81
+ interval: get.getValidNumber(options?.interval, constants.milliseconds),
82
+ timeout: get.getValidNumber(options?.timeout)
83
+ },
84
+ false
85
+ );
41
86
  }
42
87
  /**
43
88
  * Continues the timer _(if it was paused)_
@@ -50,11 +95,12 @@ class When {
50
95
  * Destroys the timer _(and stops it,if it was running)_
51
96
  */
52
97
  destroy() {
53
- this.state.timer?.destroy();
54
- this.state.promise = void 0;
55
- this.state.resolver = _function.noop;
56
- this.state.rejecter = _function.noop;
57
- this.state.timer = void 0;
98
+ const { state } = this;
99
+ state.timer?.destroy();
100
+ state.promise = void 0;
101
+ state.resolver = _function.noop;
102
+ state.rejecter = _function.noop;
103
+ state.timer = void 0;
58
104
  }
59
105
  /**
60
106
  * Pauses the timer _(if it was running)_
@@ -75,63 +121,20 @@ class When {
75
121
  */
76
122
  // biome-ignore lint/suspicious/noThenProperty: returning a promise-like object, so it's ok ;)
77
123
  then(resolve, reject) {
78
- if (this.state.timer == null || this.state?.started) {
79
- throw new Error(
80
- this.state.timer == null ? constants.destroyedMessage : constants.startedMessage
81
- );
124
+ const { state } = this;
125
+ if (state.timer == null) {
126
+ throw new Error(constants.destroyedMessage);
127
+ }
128
+ if (state.started) {
129
+ throw new Error(constants.startedMessage);
82
130
  }
83
- this.state.started = true;
84
- this.state.timer.start();
85
- return this.state.promise.then(resolve ?? _function.noop, reject ?? _function.noop);
131
+ state.started = true;
132
+ state.timer.start();
133
+ return state.promise.then(resolve ?? _function.noop, reject ?? _function.noop);
86
134
  }
87
135
  }
88
136
  function when(condition, options) {
89
- let called = false;
90
- let result = false;
91
- const state = {
92
- started: false,
93
- timer: new timer.Timer(
94
- "when",
95
- work.work,
96
- {
97
- callback() {
98
- if (condition()) {
99
- result = true;
100
- state.timer.stop();
101
- }
102
- },
103
- trace: new models.TimerTrace().stack
104
- },
105
- {
106
- onAfter() {
107
- if (!(state.timer?.paused ?? false) && !called) {
108
- called = true;
109
- if (result) {
110
- state.resolver?.();
111
- } else {
112
- state.rejecter?.();
113
- }
114
- instance.destroy();
115
- }
116
- },
117
- onError() {
118
- state.rejecter?.();
119
- instance.destroy();
120
- },
121
- count: get.getValidNumber(options?.count),
122
- interval: get.getValidNumber(options?.interval, constants.milliseconds),
123
- timeout: get.getValidNumber(options?.timeout)
124
- },
125
- false
126
- )
127
- };
128
- const promise = new Promise((resolve, reject) => {
129
- state.resolver = resolve;
130
- state.rejecter = reject;
131
- });
132
- state.promise = promise;
133
- const instance = new When(state);
134
- return instance;
137
+ return new When(condition, options);
135
138
  }
136
139
 
137
140
  exports.when = when;
package/dist/when.js CHANGED
@@ -1,13 +1,19 @@
1
1
  import { noop } from '@oscarpalmer/atoms/function';
2
2
  import { milliseconds, destroyedMessage, startedMessage } from './constants.js';
3
3
  import { getValidNumber } from './get.js';
4
+ import './global.js';
4
5
  import { TimerTrace } from './models.js';
5
6
  import { Timer } from './timer.js';
6
- import { work } from './work.js';
7
7
 
8
8
  class When {
9
9
  $timer = "when";
10
- state;
10
+ state = {
11
+ promise: void 0,
12
+ rejecter: void 0,
13
+ resolver: void 0,
14
+ started: false,
15
+ timer: void 0
16
+ };
11
17
  /**
12
18
  * Is the timer active?
13
19
  */
@@ -32,8 +38,47 @@ class When {
32
38
  get trace() {
33
39
  return globalThis._oscarpalmer_timer_debug ?? false ? this.state.timer?.trace : void 0;
34
40
  }
35
- constructor(state) {
36
- this.state = state;
41
+ constructor(condition, options) {
42
+ const { state } = this;
43
+ state.promise = new Promise((resolve, reject) => {
44
+ state.resolver = resolve;
45
+ state.rejecter = reject;
46
+ });
47
+ let result = false;
48
+ this.state.timer = new Timer(
49
+ "when",
50
+ {
51
+ callback() {
52
+ try {
53
+ if (condition()) {
54
+ result = true;
55
+ state.timer.stop();
56
+ }
57
+ } catch {
58
+ state.timer.stop();
59
+ }
60
+ },
61
+ trace: new TimerTrace().stack
62
+ },
63
+ {
64
+ onAfter: () => {
65
+ if (result) {
66
+ state.resolver?.();
67
+ } else {
68
+ state.rejecter?.();
69
+ }
70
+ this.destroy();
71
+ },
72
+ onError: () => {
73
+ state.rejecter?.();
74
+ this.destroy();
75
+ },
76
+ count: getValidNumber(options?.count),
77
+ interval: getValidNumber(options?.interval, milliseconds),
78
+ timeout: getValidNumber(options?.timeout)
79
+ },
80
+ false
81
+ );
37
82
  }
38
83
  /**
39
84
  * Continues the timer _(if it was paused)_
@@ -46,11 +91,12 @@ class When {
46
91
  * Destroys the timer _(and stops it,if it was running)_
47
92
  */
48
93
  destroy() {
49
- this.state.timer?.destroy();
50
- this.state.promise = void 0;
51
- this.state.resolver = noop;
52
- this.state.rejecter = noop;
53
- this.state.timer = void 0;
94
+ const { state } = this;
95
+ state.timer?.destroy();
96
+ state.promise = void 0;
97
+ state.resolver = noop;
98
+ state.rejecter = noop;
99
+ state.timer = void 0;
54
100
  }
55
101
  /**
56
102
  * Pauses the timer _(if it was running)_
@@ -71,63 +117,20 @@ class When {
71
117
  */
72
118
  // biome-ignore lint/suspicious/noThenProperty: returning a promise-like object, so it's ok ;)
73
119
  then(resolve, reject) {
74
- if (this.state.timer == null || this.state?.started) {
75
- throw new Error(
76
- this.state.timer == null ? destroyedMessage : startedMessage
77
- );
120
+ const { state } = this;
121
+ if (state.timer == null) {
122
+ throw new Error(destroyedMessage);
123
+ }
124
+ if (state.started) {
125
+ throw new Error(startedMessage);
78
126
  }
79
- this.state.started = true;
80
- this.state.timer.start();
81
- return this.state.promise.then(resolve ?? noop, reject ?? noop);
127
+ state.started = true;
128
+ state.timer.start();
129
+ return state.promise.then(resolve ?? noop, reject ?? noop);
82
130
  }
83
131
  }
84
132
  function when(condition, options) {
85
- let called = false;
86
- let result = false;
87
- const state = {
88
- started: false,
89
- timer: new Timer(
90
- "when",
91
- work,
92
- {
93
- callback() {
94
- if (condition()) {
95
- result = true;
96
- state.timer.stop();
97
- }
98
- },
99
- trace: new TimerTrace().stack
100
- },
101
- {
102
- onAfter() {
103
- if (!(state.timer?.paused ?? false) && !called) {
104
- called = true;
105
- if (result) {
106
- state.resolver?.();
107
- } else {
108
- state.rejecter?.();
109
- }
110
- instance.destroy();
111
- }
112
- },
113
- onError() {
114
- state.rejecter?.();
115
- instance.destroy();
116
- },
117
- count: getValidNumber(options?.count),
118
- interval: getValidNumber(options?.interval, milliseconds),
119
- timeout: getValidNumber(options?.timeout)
120
- },
121
- false
122
- )
123
- };
124
- const promise = new Promise((resolve, reject) => {
125
- state.resolver = resolve;
126
- state.rejecter = reject;
127
- });
128
- state.promise = promise;
129
- const instance = new When(state);
130
- return instance;
133
+ return new When(condition, options);
131
134
  }
132
135
 
133
136
  export { when };
package/dist/work.cjs CHANGED
@@ -4,6 +4,16 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const constants = require('./constants.cjs');
6
6
 
7
+ function endOrRestart(type, timer, state, options) {
8
+ cancelAnimationFrame(state.frame);
9
+ if (type === "stop") {
10
+ options.onAfter?.(false);
11
+ }
12
+ state.active = false;
13
+ state.frame = void 0;
14
+ state.paused = type === "pause";
15
+ return type === "restart" ? work("start", timer, state, options) : timer.instance;
16
+ }
7
17
  function finish(timer, state, options, success) {
8
18
  constants.activeTimers.delete(timer.instance);
9
19
  state.active = false;
@@ -15,46 +25,29 @@ function finish(timer, state, options, success) {
15
25
  options.onAfter?.(success);
16
26
  }
17
27
  }
18
- function work(type, timer, state, options) {
19
- if (state.destroyed && type !== "stop" || (state.active ? constants.beginTypes.has(type) : constants.endTypes.has(type))) {
20
- return timer.instance;
21
- }
22
- const pausable = constants.pauseTypes.has(type);
23
- state.elapsed = pausable ? state.elapsed : 0;
24
- state.index = pausable ? state.index : 0;
25
- state.total = pausable ? state.total : 0;
26
- if (constants.endOrRestartTypes.has(type)) {
27
- constants.activeTimers.delete(timer.instance);
28
- cancelAnimationFrame(state.frame);
29
- if (type === "stop") {
30
- options.onAfter?.(false);
31
- }
32
- state.active = false;
33
- state.frame = void 0;
34
- state.paused = type === "pause";
35
- return type === "restart" ? work("start", timer, state, options) : timer.instance;
36
- }
37
- state.active = true;
38
- state.paused = false;
39
- let start;
40
- function step(now) {
28
+ function ignore(type, state) {
29
+ return state.destroyed && type !== "stop" || (state.active ? constants.beginTypes.has(type) : constants.endTypes.has(type));
30
+ }
31
+ function run(timer, state, options) {
32
+ let last;
33
+ return function step(now) {
41
34
  if (!state.active) {
42
35
  return;
43
36
  }
44
- start ??= now;
45
- const difference = now - start;
37
+ last ??= now;
38
+ const difference = now - last;
46
39
  state.elapsed += difference;
47
40
  state.total += difference;
41
+ last = now;
48
42
  if (options.timeout > 0 && state.total >= options.timeout) {
49
43
  options.onError?.();
50
44
  finish(timer, state, options, false);
51
45
  return;
52
46
  }
53
- if (options.interval === constants.milliseconds || state.elapsed >= options.interval - 5) {
47
+ if (options.interval === constants.milliseconds || state.elapsed >= options.interval - constants.intervalBuffer) {
54
48
  if (options.count > -1) {
55
49
  state.callback(state.index);
56
50
  }
57
- start = now;
58
51
  state.elapsed = 0;
59
52
  state.index += 1;
60
53
  if (options.count === -1 || options.count > 0 && state.index >= options.count) {
@@ -63,10 +56,32 @@ function work(type, timer, state, options) {
63
56
  }
64
57
  }
65
58
  state.frame = requestAnimationFrame(step);
59
+ };
60
+ }
61
+ function setState(type, state) {
62
+ const pausable = constants.pauseTypes.has(type);
63
+ state.elapsed = pausable ? state.elapsed : 0;
64
+ state.index = pausable ? state.index : 0;
65
+ state.total = pausable ? state.total : 0;
66
+ }
67
+ function stop(timer, state, options) {
68
+ endOrRestart("stop", timer, state, options);
69
+ }
70
+ function work(type, timer, state, options) {
71
+ if (ignore(type, state)) {
72
+ return timer.instance;
66
73
  }
74
+ setState(type, state);
75
+ if (constants.endOrRestartTypes.has(type)) {
76
+ return endOrRestart(type, timer, state, options);
77
+ }
78
+ state.active = true;
79
+ state.paused = false;
67
80
  constants.activeTimers.add(timer.instance);
68
- state.frame = requestAnimationFrame(step);
81
+ const runner = run(timer, state, options);
82
+ state.frame = requestAnimationFrame(runner);
69
83
  return timer.instance;
70
84
  }
71
85
 
86
+ exports.stop = stop;
72
87
  exports.work = work;
package/dist/work.js CHANGED
@@ -1,5 +1,15 @@
1
- import { beginTypes, endTypes, pauseTypes, endOrRestartTypes, activeTimers, milliseconds } from './constants.js';
1
+ import { endOrRestartTypes, activeTimers, beginTypes, endTypes, pauseTypes, milliseconds, intervalBuffer } from './constants.js';
2
2
 
3
+ function endOrRestart(type, timer, state, options) {
4
+ cancelAnimationFrame(state.frame);
5
+ if (type === "stop") {
6
+ options.onAfter?.(false);
7
+ }
8
+ state.active = false;
9
+ state.frame = void 0;
10
+ state.paused = type === "pause";
11
+ return type === "restart" ? work("start", timer, state, options) : timer.instance;
12
+ }
3
13
  function finish(timer, state, options, success) {
4
14
  activeTimers.delete(timer.instance);
5
15
  state.active = false;
@@ -11,46 +21,29 @@ function finish(timer, state, options, success) {
11
21
  options.onAfter?.(success);
12
22
  }
13
23
  }
14
- function work(type, timer, state, options) {
15
- if (state.destroyed && type !== "stop" || (state.active ? beginTypes.has(type) : endTypes.has(type))) {
16
- return timer.instance;
17
- }
18
- const pausable = pauseTypes.has(type);
19
- state.elapsed = pausable ? state.elapsed : 0;
20
- state.index = pausable ? state.index : 0;
21
- state.total = pausable ? state.total : 0;
22
- if (endOrRestartTypes.has(type)) {
23
- activeTimers.delete(timer.instance);
24
- cancelAnimationFrame(state.frame);
25
- if (type === "stop") {
26
- options.onAfter?.(false);
27
- }
28
- state.active = false;
29
- state.frame = void 0;
30
- state.paused = type === "pause";
31
- return type === "restart" ? work("start", timer, state, options) : timer.instance;
32
- }
33
- state.active = true;
34
- state.paused = false;
35
- let start;
36
- function step(now) {
24
+ function ignore(type, state) {
25
+ return state.destroyed && type !== "stop" || (state.active ? beginTypes.has(type) : endTypes.has(type));
26
+ }
27
+ function run(timer, state, options) {
28
+ let last;
29
+ return function step(now) {
37
30
  if (!state.active) {
38
31
  return;
39
32
  }
40
- start ??= now;
41
- const difference = now - start;
33
+ last ??= now;
34
+ const difference = now - last;
42
35
  state.elapsed += difference;
43
36
  state.total += difference;
37
+ last = now;
44
38
  if (options.timeout > 0 && state.total >= options.timeout) {
45
39
  options.onError?.();
46
40
  finish(timer, state, options, false);
47
41
  return;
48
42
  }
49
- if (options.interval === milliseconds || state.elapsed >= options.interval - 5) {
43
+ if (options.interval === milliseconds || state.elapsed >= options.interval - intervalBuffer) {
50
44
  if (options.count > -1) {
51
45
  state.callback(state.index);
52
46
  }
53
- start = now;
54
47
  state.elapsed = 0;
55
48
  state.index += 1;
56
49
  if (options.count === -1 || options.count > 0 && state.index >= options.count) {
@@ -59,10 +52,31 @@ function work(type, timer, state, options) {
59
52
  }
60
53
  }
61
54
  state.frame = requestAnimationFrame(step);
55
+ };
56
+ }
57
+ function setState(type, state) {
58
+ const pausable = pauseTypes.has(type);
59
+ state.elapsed = pausable ? state.elapsed : 0;
60
+ state.index = pausable ? state.index : 0;
61
+ state.total = pausable ? state.total : 0;
62
+ }
63
+ function stop(timer, state, options) {
64
+ endOrRestart("stop", timer, state, options);
65
+ }
66
+ function work(type, timer, state, options) {
67
+ if (ignore(type, state)) {
68
+ return timer.instance;
62
69
  }
70
+ setState(type, state);
71
+ if (endOrRestartTypes.has(type)) {
72
+ return endOrRestart(type, timer, state, options);
73
+ }
74
+ state.active = true;
75
+ state.paused = false;
63
76
  activeTimers.add(timer.instance);
64
- state.frame = requestAnimationFrame(step);
77
+ const runner = run(timer, state, options);
78
+ state.frame = requestAnimationFrame(runner);
65
79
  return timer.instance;
66
80
  }
67
81
 
68
- export { work };
82
+ export { stop, work };
package/package.json CHANGED
@@ -11,15 +11,15 @@
11
11
  "@biomejs/biome": "^1.9",
12
12
  "@rollup/plugin-node-resolve": "^16",
13
13
  "@rollup/plugin-typescript": "^12.1",
14
- "@types/node": "^22.15",
15
- "@vitest/coverage-istanbul": "^3.1",
14
+ "@types/node": "^24",
15
+ "@vitest/coverage-istanbul": "^3.2",
16
16
  "dts-bundle-generator": "^9.5",
17
17
  "glob": "^11",
18
18
  "jsdom": "^26.1",
19
19
  "tslib": "^2.8",
20
20
  "typescript": "^5.8",
21
21
  "vite": "^6.3",
22
- "vitest": "^3.1"
22
+ "vitest": "^3.2"
23
23
  },
24
24
  "exports": {
25
25
  ".": {
@@ -94,5 +94,5 @@
94
94
  },
95
95
  "type": "module",
96
96
  "types": "types/index.d.cts",
97
- "version": "0.31.0"
97
+ "version": "0.33.0"
98
98
  }