@randajan/pulse 1.1.4 → 3.0.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/README.md +197 -80
- package/dist/cjs/index.cjs +445 -147
- package/dist/cjs/index.cjs.map +4 -4
- package/dist/esm/index.mjs +431 -147
- package/dist/esm/index.mjs.map +4 -4
- package/dist/types/index.d.ts +174 -0
- package/package.json +11 -8
package/dist/cjs/index.cjs
CHANGED
|
@@ -20,20 +20,20 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
var index_exports = {};
|
|
21
21
|
__export(index_exports, {
|
|
22
22
|
Pulse: () => Pulse,
|
|
23
|
+
PulseCycle: () => PulseCycle,
|
|
24
|
+
PulseError: () => PulseError,
|
|
25
|
+
PulseExecuteError: () => PulseExecuteError,
|
|
26
|
+
PulseRuntimeError: () => PulseRuntimeError,
|
|
27
|
+
PulseScheduleError: () => PulseScheduleError,
|
|
28
|
+
PulseSession: () => PulseSession,
|
|
29
|
+
PulseStartError: () => PulseStartError,
|
|
30
|
+
PulseStopError: () => PulseStopError,
|
|
23
31
|
createPulse: () => createPulse,
|
|
24
32
|
default: () => index_default,
|
|
25
|
-
|
|
33
|
+
handleError: () => handleError
|
|
26
34
|
});
|
|
27
35
|
module.exports = __toCommonJS(index_exports);
|
|
28
36
|
|
|
29
|
-
// src/Pulse.js
|
|
30
|
-
var import_props2 = require("@randajan/props");
|
|
31
|
-
|
|
32
|
-
// src/const.js
|
|
33
|
-
var _pulses = /* @__PURE__ */ new Map();
|
|
34
|
-
var blankFn = () => {
|
|
35
|
-
};
|
|
36
|
-
|
|
37
37
|
// src/tools.js
|
|
38
38
|
var is = (type, any) => typeof any === type;
|
|
39
39
|
var valid = (type, any, req = false, msg = "argument") => {
|
|
@@ -41,179 +41,477 @@ var valid = (type, any, req = false, msg = "argument") => {
|
|
|
41
41
|
if (!req) {
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
|
-
throw new Error(
|
|
44
|
+
throw new Error(`[pulse] ${msg} require typeof '${type}'`);
|
|
45
45
|
}
|
|
46
46
|
if (is(type, any)) {
|
|
47
47
|
return any;
|
|
48
48
|
}
|
|
49
|
-
throw new Error(
|
|
49
|
+
throw new Error(`[pulse] ${msg} is not typeof '${type}'`);
|
|
50
50
|
};
|
|
51
51
|
var validRange = (min, max, any, req = false, msg = "argument") => {
|
|
52
52
|
const num = valid("number", any, req, msg);
|
|
53
53
|
if (num == null) {
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
|
-
if (num < min) {
|
|
57
|
-
throw new Error(
|
|
56
|
+
if (min != null && num < min) {
|
|
57
|
+
throw new Error(`[pulse] ${msg} must be >= ${min}`);
|
|
58
58
|
}
|
|
59
|
-
if (num > max) {
|
|
60
|
-
throw new Error(
|
|
59
|
+
if (max != null && num > max) {
|
|
60
|
+
throw new Error(`[pulse] ${msg} must be <= ${max}`);
|
|
61
61
|
}
|
|
62
62
|
return num;
|
|
63
63
|
};
|
|
64
|
+
var validRangeFinite = (min, any, req = false, msg = "argument") => {
|
|
65
|
+
const num = validRange(min, null, any, req, msg);
|
|
66
|
+
if (num == null) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (!Number.isFinite(num)) {
|
|
70
|
+
throw new Error(`[pulse] ${msg} must be finite`);
|
|
71
|
+
}
|
|
72
|
+
return num;
|
|
73
|
+
};
|
|
74
|
+
var validateGetNow = (options) => {
|
|
75
|
+
const custom = valid("function", options.getNow, false, "options.getNow");
|
|
76
|
+
if (!custom) {
|
|
77
|
+
return (_) => Date.now();
|
|
78
|
+
}
|
|
79
|
+
const safe = (_) => validRangeFinite(0, custom(), true, "options.getNow result");
|
|
80
|
+
safe();
|
|
81
|
+
return safe;
|
|
82
|
+
};
|
|
64
83
|
|
|
65
|
-
// src/
|
|
66
|
-
var
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
84
|
+
// src/options.js
|
|
85
|
+
var blankFn = () => {
|
|
86
|
+
};
|
|
87
|
+
var formatOptions = (options) => {
|
|
88
|
+
const o = {};
|
|
89
|
+
if (options.noMeta != null) {
|
|
90
|
+
throw new Error("options.noMeta is obsolete");
|
|
91
|
+
}
|
|
92
|
+
if (options.maxRuns != null) {
|
|
93
|
+
throw new Error("options.maxRuns is obsolete");
|
|
94
|
+
}
|
|
95
|
+
if (options.afterPulse != null) {
|
|
96
|
+
throw new Error("options.afterPulse is obsolete");
|
|
97
|
+
}
|
|
98
|
+
o.getNow = validateGetNow(options);
|
|
99
|
+
o.align = valid("boolean", options.align, true, "options.align");
|
|
100
|
+
const minInterval = 10;
|
|
101
|
+
const maxInterval = 2147483647;
|
|
102
|
+
o.interval = validRange(minInterval, maxInterval, options.interval, true, "options.interval");
|
|
103
|
+
o.runOnStart = valid("boolean", options.runOnStart, false, "options.runOnStart") || false;
|
|
104
|
+
const offsetMsg = `options.offset (align:${o.align})`;
|
|
105
|
+
if (o.align) {
|
|
106
|
+
o.offset = validRange(0, o.interval, options.offset, false, offsetMsg) ?? 0;
|
|
107
|
+
} else if (!o.runOnStart) {
|
|
108
|
+
o.offset = validRange(-o.interval, maxInterval - o.interval, options.offset, false, offsetMsg) ?? 0;
|
|
109
|
+
} else if (options.offset != null) {
|
|
110
|
+
throw new Error(`${offsetMsg} can't be set if runOnStart:true`);
|
|
111
|
+
} else {
|
|
112
|
+
o.offset = -o.interval;
|
|
113
|
+
}
|
|
114
|
+
o.onPulse = valid("function", options.onPulse, true, "options.onPulse");
|
|
115
|
+
o.onStart = valid("function", options.onStart, false, "options.onStart") || blankFn;
|
|
116
|
+
o.onStop = valid("function", options.onStop, false, "options.onStop") || blankFn;
|
|
117
|
+
o.onError = valid("function", options.onError, false, "options.onError");
|
|
118
|
+
o.autoStart = valid("boolean", options.autoStart, false, "options.autoStart") || false;
|
|
119
|
+
return Object.freeze(o);
|
|
76
120
|
};
|
|
77
121
|
|
|
78
|
-
// src/
|
|
79
|
-
var
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
if (!noMeta) {
|
|
127
|
-
(0, import_props2.solid)(md, "ended", getNow());
|
|
128
|
-
}
|
|
129
|
-
if (errA != null) {
|
|
130
|
-
if (noMeta) {
|
|
131
|
-
onError(this, errA, md);
|
|
132
|
-
} else {
|
|
133
|
-
onError(this, md);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
try {
|
|
137
|
-
await afterPulse(this, md);
|
|
138
|
-
} catch (err) {
|
|
139
|
-
errB = err;
|
|
140
|
-
}
|
|
141
|
-
_p.last = noMeta ? result : md;
|
|
142
|
-
delete _p.metaData;
|
|
143
|
-
if (errB != null) {
|
|
144
|
-
_p.state = false;
|
|
145
|
-
throw errB;
|
|
146
|
-
}
|
|
147
|
-
_p.plan();
|
|
148
|
-
};
|
|
149
|
-
(0, import_props2.virtuals)(this, {
|
|
150
|
-
state: (_) => _p.state,
|
|
151
|
-
last: (_) => _p.last,
|
|
152
|
-
countdown: (_) => interval - getNow() % interval + offset
|
|
153
|
-
});
|
|
154
|
-
(0, import_props2.solids)(this, {
|
|
155
|
-
interval,
|
|
156
|
-
offset
|
|
157
|
-
});
|
|
158
|
-
_pulses.set(this, _p);
|
|
159
|
-
if (autoStart) {
|
|
160
|
-
this.start();
|
|
122
|
+
// src/errors.js
|
|
123
|
+
var PulseError = class extends Error {
|
|
124
|
+
constructor(type, name, cause) {
|
|
125
|
+
super(`Pulse ${type} failed`, { cause });
|
|
126
|
+
this.name = name;
|
|
127
|
+
this.pulseErrType = type;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var PulseStartError = class extends PulseError {
|
|
131
|
+
constructor(cause) {
|
|
132
|
+
super("start", "PulseStartError", cause);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
var PulseStopError = class extends PulseError {
|
|
136
|
+
constructor(cause) {
|
|
137
|
+
super("stop", "PulseStopError", cause);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var PulseScheduleError = class extends PulseError {
|
|
141
|
+
constructor(cause) {
|
|
142
|
+
super("schedule", "PulseScheduleError", cause);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
var PulseExecuteError = class extends PulseError {
|
|
146
|
+
constructor(cause) {
|
|
147
|
+
super("execute", "PulseExecuteError", cause);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
var PulseRuntimeError = class extends PulseError {
|
|
151
|
+
constructor(cause) {
|
|
152
|
+
super("runtime", "PulseRuntimeError", cause);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
var getErrType = (err) => {
|
|
156
|
+
if (err instanceof PulseError) {
|
|
157
|
+
return err.pulseErrType;
|
|
158
|
+
}
|
|
159
|
+
return "unknown";
|
|
160
|
+
};
|
|
161
|
+
var handleError = async (pulse, error, onError) => {
|
|
162
|
+
const type = getErrType(error);
|
|
163
|
+
if (!onError) {
|
|
164
|
+
console.error(`[pulse] ${type} error:`, error);
|
|
165
|
+
} else {
|
|
166
|
+
try {
|
|
167
|
+
await onError(pulse, type, error);
|
|
168
|
+
} catch (e2) {
|
|
169
|
+
console.error(`[pulse] options.onError('${type}') failed: `, e2);
|
|
161
170
|
}
|
|
162
171
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// src/class/PulseCycle.js
|
|
175
|
+
var PulseCycle = class {
|
|
176
|
+
#pulse = null;
|
|
177
|
+
#session = null;
|
|
178
|
+
#opt = null;
|
|
179
|
+
#warnings = [];
|
|
180
|
+
#ok = true;
|
|
181
|
+
#id = void 0;
|
|
182
|
+
#done = void 0;
|
|
183
|
+
#result = void 0;
|
|
184
|
+
#error = void 0;
|
|
185
|
+
#started = void 0;
|
|
186
|
+
#ended = void 0;
|
|
187
|
+
constructor(pulse, session, opt) {
|
|
188
|
+
this.#pulse = pulse;
|
|
189
|
+
this.#session = session;
|
|
190
|
+
this.#opt = opt;
|
|
191
|
+
}
|
|
192
|
+
get pulse() {
|
|
193
|
+
return this.#pulse;
|
|
194
|
+
}
|
|
195
|
+
get session() {
|
|
196
|
+
return this.#session;
|
|
197
|
+
}
|
|
198
|
+
get signal() {
|
|
199
|
+
return this.#session.signal;
|
|
200
|
+
}
|
|
201
|
+
get id() {
|
|
202
|
+
return this.#id;
|
|
203
|
+
}
|
|
204
|
+
get ok() {
|
|
205
|
+
return this.#ok;
|
|
206
|
+
}
|
|
207
|
+
get done() {
|
|
208
|
+
return this.#done;
|
|
209
|
+
}
|
|
210
|
+
get started() {
|
|
211
|
+
return this.#started;
|
|
212
|
+
}
|
|
213
|
+
get ended() {
|
|
214
|
+
return this.#ended;
|
|
215
|
+
}
|
|
216
|
+
get runtime() {
|
|
217
|
+
return (this.#done ? this.#ended : this.#opt.getNow()) - this.#started;
|
|
218
|
+
}
|
|
219
|
+
get lateBy() {
|
|
220
|
+
return Math.max(0, this.runtime - this.#opt.interval);
|
|
221
|
+
}
|
|
222
|
+
get warnings() {
|
|
223
|
+
return [...this.#warnings];
|
|
224
|
+
}
|
|
225
|
+
get result() {
|
|
226
|
+
return this.#result;
|
|
227
|
+
}
|
|
228
|
+
get error() {
|
|
229
|
+
return this.#error;
|
|
230
|
+
}
|
|
231
|
+
warn(warning) {
|
|
232
|
+
return this.#warnings.push(warning);
|
|
233
|
+
}
|
|
234
|
+
async _execute(id) {
|
|
235
|
+
if (this.#id != null) {
|
|
170
236
|
return false;
|
|
171
237
|
}
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
238
|
+
const { getNow, onPulse } = this.#opt;
|
|
239
|
+
this.#id = id;
|
|
240
|
+
this.#started = getNow();
|
|
241
|
+
try {
|
|
242
|
+
this.#result = await onPulse(this);
|
|
243
|
+
} catch (err) {
|
|
244
|
+
this.#error = err;
|
|
245
|
+
this.#ok = false;
|
|
176
246
|
}
|
|
177
|
-
|
|
178
|
-
|
|
247
|
+
this.#done = true;
|
|
248
|
+
this.#ended = getNow();
|
|
179
249
|
return true;
|
|
180
250
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
251
|
+
toJSON() {
|
|
252
|
+
const { id, ok, done, started, ended, runtime, lateBy, warnings, result, error } = this;
|
|
253
|
+
return { id, ok, done, started, ended, runtime, lateBy, warnings, result, error };
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// src/class/PulseSession.js
|
|
258
|
+
var PulseSession = class {
|
|
259
|
+
#pulse = null;
|
|
260
|
+
#opt = null;
|
|
261
|
+
#ctrl = new AbortController();
|
|
262
|
+
#state = false;
|
|
263
|
+
#timeoutId;
|
|
264
|
+
#fireAt;
|
|
265
|
+
#current = null;
|
|
266
|
+
#last;
|
|
267
|
+
#consumeNextId;
|
|
268
|
+
constructor(pulse, opt, consumeNextId) {
|
|
269
|
+
this.#pulse = pulse;
|
|
270
|
+
this.#opt = opt;
|
|
271
|
+
this.#consumeNextId = consumeNextId;
|
|
272
|
+
}
|
|
273
|
+
get pulse() {
|
|
274
|
+
return this.#pulse;
|
|
275
|
+
}
|
|
276
|
+
get signal() {
|
|
277
|
+
return this.#ctrl.signal;
|
|
278
|
+
}
|
|
279
|
+
get interval() {
|
|
280
|
+
return this.#opt.interval;
|
|
281
|
+
}
|
|
282
|
+
get offset() {
|
|
283
|
+
return this.#opt.offset;
|
|
284
|
+
}
|
|
285
|
+
get align() {
|
|
286
|
+
return this.#opt.align;
|
|
287
|
+
}
|
|
288
|
+
get state() {
|
|
289
|
+
return this.#state && !this.#ctrl.signal.aborted;
|
|
290
|
+
}
|
|
291
|
+
get current() {
|
|
292
|
+
return this.#current;
|
|
293
|
+
}
|
|
294
|
+
get last() {
|
|
295
|
+
return this.#last;
|
|
296
|
+
}
|
|
297
|
+
get countdown() {
|
|
298
|
+
return this.calculateCountdown();
|
|
299
|
+
}
|
|
300
|
+
get potential() {
|
|
301
|
+
return this.#pulse.potential;
|
|
302
|
+
}
|
|
303
|
+
get nextAt() {
|
|
304
|
+
return this.state ? this.#pulse.potential + this.#opt.getNow() : void 0;
|
|
305
|
+
}
|
|
306
|
+
get nextId() {
|
|
307
|
+
return this.#pulse.nextId;
|
|
308
|
+
}
|
|
309
|
+
calculateCountdown() {
|
|
310
|
+
if (!this.state || this.#fireAt == null) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
return Math.max(0, this.#fireAt - this.#opt.getNow());
|
|
314
|
+
}
|
|
315
|
+
start() {
|
|
316
|
+
if (this.#state) {
|
|
188
317
|
return false;
|
|
189
318
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
319
|
+
this.#state = true;
|
|
320
|
+
try {
|
|
321
|
+
this.#opt.onStart(this);
|
|
322
|
+
} catch (err) {
|
|
323
|
+
this.#state = false;
|
|
324
|
+
this.#ctrl.abort(err);
|
|
325
|
+
throw new PulseStartError(err);
|
|
195
326
|
}
|
|
196
|
-
|
|
197
|
-
return true;
|
|
327
|
+
return this.#schedule(true);
|
|
198
328
|
}
|
|
199
|
-
|
|
200
|
-
|
|
329
|
+
stop(reason) {
|
|
330
|
+
if (!this.#state) {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
if (this.#pulse.session === this) {
|
|
334
|
+
return this.#pulse.stop(reason);
|
|
335
|
+
}
|
|
336
|
+
this.#state = false;
|
|
337
|
+
clearTimeout(this.#timeoutId);
|
|
338
|
+
this.#fireAt = void 0;
|
|
339
|
+
this.#current = null;
|
|
340
|
+
this.#ctrl.abort(reason);
|
|
341
|
+
if (reason != null) {
|
|
342
|
+
this.#handleError(reason);
|
|
343
|
+
}
|
|
344
|
+
try {
|
|
345
|
+
this.#opt.onStop(this, reason);
|
|
346
|
+
} catch (err) {
|
|
347
|
+
this.#handleError(new PulseStopError(err));
|
|
348
|
+
}
|
|
201
349
|
return true;
|
|
202
350
|
}
|
|
203
|
-
|
|
204
|
-
this.
|
|
205
|
-
|
|
351
|
+
#handleError(error) {
|
|
352
|
+
return handleError(this.pulse, error, this.#opt.onError);
|
|
353
|
+
}
|
|
354
|
+
// Even a temporarily broken clock/configuration must not permanently stall scheduling.
|
|
355
|
+
#schedule(isInit) {
|
|
356
|
+
if (!this.state || this.#current != null) {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
const fireIn = this.#pulse.calculatePotential(isInit);
|
|
361
|
+
this.#fireAt = this.#opt.getNow() + fireIn;
|
|
362
|
+
this.#timeoutId = setTimeout(this.#tick, fireIn);
|
|
363
|
+
this.#timeoutId.unref?.();
|
|
364
|
+
return true;
|
|
365
|
+
} catch (err) {
|
|
366
|
+
this.stop(new PulseScheduleError(err));
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
#tick = async () => {
|
|
371
|
+
if (!this.state || this.#current != null) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
let cycle;
|
|
375
|
+
try {
|
|
376
|
+
this.#current = cycle = new PulseCycle(this.#pulse, this, this.#opt);
|
|
377
|
+
await cycle._execute(this.#consumeNextId());
|
|
378
|
+
if (!cycle.ok) {
|
|
379
|
+
this.#handleError(new PulseRuntimeError(cycle.error));
|
|
380
|
+
}
|
|
381
|
+
} catch (err) {
|
|
382
|
+
this.stop(new PulseExecuteError(err));
|
|
383
|
+
}
|
|
384
|
+
if (!this.state) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (cycle && this.#current === cycle) {
|
|
388
|
+
this.#last = cycle;
|
|
389
|
+
this.#current = null;
|
|
390
|
+
}
|
|
391
|
+
this.#schedule(false);
|
|
392
|
+
};
|
|
393
|
+
toJSON() {
|
|
394
|
+
const { interval, offset, align, state, current, last, countdown, potential, nextAt, nextId } = this;
|
|
395
|
+
return { interval, offset, align, state, current, last, countdown, potential, nextAt, nextId };
|
|
206
396
|
}
|
|
207
397
|
};
|
|
208
398
|
|
|
209
|
-
// src/
|
|
210
|
-
var
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
399
|
+
// src/class/Pulse.js
|
|
400
|
+
var Pulse = class {
|
|
401
|
+
#opt;
|
|
402
|
+
#session = null;
|
|
403
|
+
#nextId = 0;
|
|
404
|
+
#last;
|
|
405
|
+
constructor(options = {}) {
|
|
406
|
+
this.#opt = formatOptions(options);
|
|
407
|
+
if (this.#opt.autoStart) {
|
|
408
|
+
this.start();
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
get session() {
|
|
412
|
+
return this.#session;
|
|
413
|
+
}
|
|
414
|
+
get state() {
|
|
415
|
+
return this.#session?.state ?? false;
|
|
416
|
+
}
|
|
417
|
+
get current() {
|
|
418
|
+
return this.#session?.current;
|
|
419
|
+
}
|
|
420
|
+
get last() {
|
|
421
|
+
return this.#session?.last ?? this.#last;
|
|
422
|
+
}
|
|
423
|
+
get countdown() {
|
|
424
|
+
return this.#session?.countdown;
|
|
425
|
+
}
|
|
426
|
+
get potential() {
|
|
427
|
+
return this.countdown ?? this.calculatePotential();
|
|
428
|
+
}
|
|
429
|
+
get nextAt() {
|
|
430
|
+
return this.state ? this.potential + this.#opt.getNow() : void 0;
|
|
431
|
+
}
|
|
432
|
+
get nextId() {
|
|
433
|
+
return this.#nextId;
|
|
434
|
+
}
|
|
435
|
+
get interval() {
|
|
436
|
+
return this.#opt.interval;
|
|
437
|
+
}
|
|
438
|
+
get offset() {
|
|
439
|
+
return this.#opt.offset;
|
|
440
|
+
}
|
|
441
|
+
get align() {
|
|
442
|
+
return this.#opt.align;
|
|
443
|
+
}
|
|
444
|
+
calculatePotential(isInit = true) {
|
|
445
|
+
const { align, runOnStart, interval, offset, getNow } = this.#opt;
|
|
446
|
+
if (isInit && runOnStart) {
|
|
447
|
+
return 0;
|
|
448
|
+
}
|
|
449
|
+
if (!align) {
|
|
450
|
+
return isInit ? interval + offset : interval;
|
|
451
|
+
}
|
|
452
|
+
const now = getNow() - offset;
|
|
453
|
+
const rest = (now % interval + interval) % interval;
|
|
454
|
+
return rest === 0 ? interval : interval - rest;
|
|
455
|
+
}
|
|
456
|
+
#handleError(error) {
|
|
457
|
+
return handleError(this, error, this.#opt.onError);
|
|
458
|
+
}
|
|
459
|
+
#consumeNextId = () => this.#nextId++;
|
|
460
|
+
/** Start a new session. Returns false if already running. */
|
|
461
|
+
start() {
|
|
462
|
+
if (this.state) {
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
const session = new PulseSession(this, this.#opt, this.#consumeNextId);
|
|
466
|
+
this.#session = session;
|
|
467
|
+
try {
|
|
468
|
+
return session.start();
|
|
469
|
+
} catch (err) {
|
|
470
|
+
if (this.#session === session) {
|
|
471
|
+
this.#session = null;
|
|
472
|
+
}
|
|
473
|
+
this.#handleError(err);
|
|
474
|
+
throw err;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
/** Stop the current session, without cancelling a newer one. */
|
|
478
|
+
stop(reason) {
|
|
479
|
+
const session = this.#session;
|
|
480
|
+
if (!session?.state) {
|
|
481
|
+
return false;
|
|
482
|
+
}
|
|
483
|
+
this.#session = null;
|
|
484
|
+
this.#last = session.last ?? this.#last;
|
|
485
|
+
return session.stop(reason);
|
|
486
|
+
}
|
|
487
|
+
restart() {
|
|
488
|
+
this.stop();
|
|
489
|
+
return this.start();
|
|
490
|
+
}
|
|
491
|
+
toJSON() {
|
|
492
|
+
const { interval, offset, align, state, current, last, countdown, potential, nextAt, nextId } = this;
|
|
493
|
+
return { interval, offset, align, state, current, last, countdown, potential, nextAt, nextId };
|
|
494
|
+
}
|
|
495
|
+
reset() {
|
|
496
|
+
throw new Error("[pulse] reset() is obsolete");
|
|
214
497
|
}
|
|
215
498
|
};
|
|
216
499
|
|
|
217
500
|
// src/index.js
|
|
501
|
+
var createPulse = (options = {}) => new Pulse(options);
|
|
218
502
|
var index_default = createPulse;
|
|
219
|
-
|
|
503
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
504
|
+
0 && (module.exports = {
|
|
505
|
+
Pulse,
|
|
506
|
+
PulseCycle,
|
|
507
|
+
PulseError,
|
|
508
|
+
PulseExecuteError,
|
|
509
|
+
PulseRuntimeError,
|
|
510
|
+
PulseScheduleError,
|
|
511
|
+
PulseSession,
|
|
512
|
+
PulseStartError,
|
|
513
|
+
PulseStopError,
|
|
514
|
+
createPulse,
|
|
515
|
+
handleError
|
|
516
|
+
});
|
|
517
|
+
//# sourceMappingURL=index.cjs.map
|