@keeex/utils 7.1.0 → 7.2.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 +15 -4
- package/lib/cron/scheduledtask.d.ts +8 -53
- package/lib/cron/scheduledtask.js +56 -77
- package/lib/cron/types.d.ts +0 -1
- package/lib/cron.d.ts +3 -2
- package/lib/cron.js +3 -4
- package/lib/{cron/logger.d.ts → linebuffer.d.ts} +13 -5
- package/{web/cron/logger.d.ts → lib/linebuffer.js} +30 -5
- package/package.json +1 -1
- package/web/cron/scheduledtask.d.ts +8 -53
- package/web/cron/scheduledtask.js +56 -78
- package/web/cron/types.d.ts +0 -1
- package/web/cron.d.ts +3 -2
- package/web/cron.js +3 -4
- package/{lib/cron/logger.js → web/linebuffer.d.ts} +13 -14
- package/web/{cron/logger.js → linebuffer.js} +29 -12
package/README.md
CHANGED
|
@@ -9,13 +9,19 @@ This is a general feature list overview.
|
|
|
9
9
|
|
|
10
10
|
## Async utility
|
|
11
11
|
|
|
12
|
+
Stuff related to promises and async operations.
|
|
13
|
+
|
|
12
14
|
- `AsyncTrigger`, for easy debouncing
|
|
13
15
|
- `DeferredPromise` to manipulate the usual `resolve()` and `reject()` functions outside of a
|
|
14
16
|
promise block
|
|
15
17
|
- `KeyCache` to create a basic key-value cache with asynchronous fetch
|
|
18
|
+
- `Queues` to create parallel queues of tasks
|
|
16
19
|
- `TimeCache` to create a cache that keeps a value for a given amount of time and can automatically
|
|
17
20
|
refresh it
|
|
18
|
-
|
|
21
|
+
|
|
22
|
+
## CRON
|
|
23
|
+
|
|
24
|
+
Time-based task scheduling.
|
|
19
25
|
|
|
20
26
|
## Marshalling
|
|
21
27
|
|
|
@@ -50,6 +56,7 @@ Helper wrapping JavaScript DataView into convenient functions.
|
|
|
50
56
|
## dict
|
|
51
57
|
|
|
52
58
|
Functions to copy records with primitive types (deep copy).
|
|
59
|
+
These functions can probably be replaced with `Object.assign()` or custom code.
|
|
53
60
|
|
|
54
61
|
## error
|
|
55
62
|
|
|
@@ -60,6 +67,10 @@ Coerce anything (`unknown`) into an `Error` object for easier error handling.
|
|
|
60
67
|
Functions to use a JavaScript environment "global" dataset.
|
|
61
68
|
Handles multiple environment somewhat gracefully.
|
|
62
69
|
|
|
70
|
+
## hex
|
|
71
|
+
|
|
72
|
+
Hex string manipulation.
|
|
73
|
+
|
|
63
74
|
## idx
|
|
64
75
|
|
|
65
76
|
IDX check and manipulation functions
|
|
@@ -69,10 +80,9 @@ IDX check and manipulation functions
|
|
|
69
80
|
JSON parsing with type safety.
|
|
70
81
|
Also, a "canonical" JSON encoder that ensure property order is consistent.
|
|
71
82
|
|
|
72
|
-
##
|
|
83
|
+
## line buffer
|
|
73
84
|
|
|
74
|
-
|
|
75
|
-
Supports various log level, timestamping, error chaining, stacktrace stripping.
|
|
85
|
+
Buffer string inputs and output full lines only.
|
|
76
86
|
|
|
77
87
|
## number
|
|
78
88
|
|
|
@@ -90,6 +100,7 @@ Helpers around promises.
|
|
|
90
100
|
- controlled async delay
|
|
91
101
|
- retry a promise until it succeed (with max tries)
|
|
92
102
|
- run an array of promise, stop at the first that succeed
|
|
103
|
+
- silently drop a promise without crashing the VM
|
|
93
104
|
|
|
94
105
|
## starttime
|
|
95
106
|
|
|
@@ -13,59 +13,14 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
import
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*/
|
|
16
|
+
import * as log from "@keeex/log";
|
|
17
|
+
import * as types from "./types.js";
|
|
18
|
+
/** Manage a single scheduled task */
|
|
20
19
|
export default class ScheduledTask {
|
|
21
|
-
private
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Indicate that the task missed a previous tick
|
|
26
|
-
*/
|
|
27
|
-
private readonly _restartImmediate;
|
|
28
|
-
/**
|
|
29
|
-
* If the task is canceled (prevent looping)
|
|
30
|
-
*/
|
|
31
|
-
private _canceled;
|
|
32
|
-
/**
|
|
33
|
-
* Timeout handler
|
|
34
|
-
*/
|
|
35
|
-
private _timeoutHandler;
|
|
36
|
-
/**
|
|
37
|
-
* Last run time (timestamp)
|
|
38
|
-
*/
|
|
39
|
-
private _lastRun;
|
|
40
|
-
constructor(cronDefinition: string, func: TaskFunction, opts: CompleteTaskOptions);
|
|
41
|
-
/**
|
|
42
|
-
* Determine if the task should be running right now
|
|
43
|
-
*/
|
|
20
|
+
#private;
|
|
21
|
+
constructor(cronDefinition: string, func: types.TaskFunction, opts: types.CompleteTaskOptions, logger?: log.Logger);
|
|
22
|
+
/** Determine if the task should be running right now */
|
|
44
23
|
get runnable(): boolean;
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
*/
|
|
48
|
-
cancel(): void;
|
|
49
|
-
/**
|
|
50
|
-
* Run the task
|
|
51
|
-
*
|
|
52
|
-
* All special cases are handled there (task already running).
|
|
53
|
-
* Updating the next value is also handled here.
|
|
54
|
-
*/
|
|
55
|
-
private _run;
|
|
56
|
-
/**
|
|
57
|
-
* Reschedule the task for the next occurrence
|
|
58
|
-
*/
|
|
59
|
-
private _reschedule;
|
|
60
|
-
/**
|
|
61
|
-
* Return the timeout delay before the next task scheduling.
|
|
62
|
-
*
|
|
63
|
-
* This can return a lower value if the task is scheduled in the distant
|
|
64
|
-
* future.
|
|
65
|
-
*/
|
|
66
|
-
private _getTimeoutDelay;
|
|
67
|
-
/**
|
|
68
|
-
* Return the next scheduled time starting from the given point in time
|
|
69
|
-
*/
|
|
70
|
-
private _getNextSchedule;
|
|
24
|
+
/** Cancel the task from the scheduling */
|
|
25
|
+
cancel: () => void;
|
|
71
26
|
}
|
|
@@ -13,125 +13,104 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
+
import * as log from "@keeex/log";
|
|
16
17
|
import { CronExpressionParser } from "cron-parser";
|
|
18
|
+
import { asError } from "../error.js";
|
|
17
19
|
import { dropPromise } from "../promise.js";
|
|
18
|
-
import
|
|
19
|
-
import { Overrun } from "./types.js";
|
|
20
|
+
import * as types from "./types.js";
|
|
20
21
|
/**
|
|
21
22
|
* Maximum delay for a timeout.
|
|
22
23
|
* Done because setTimeout() sometimes can only accept a 32bit integer
|
|
23
24
|
*/
|
|
24
25
|
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
25
26
|
const maxTimeoutDelay = 2 ** 31;
|
|
26
|
-
/**
|
|
27
|
-
* Manage a single scheduled task
|
|
28
|
-
*/
|
|
27
|
+
/** Manage a single scheduled task */
|
|
29
28
|
export default class ScheduledTask {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
*/
|
|
48
|
-
_lastRun;
|
|
49
|
-
constructor(cronDefinition, func, opts) {
|
|
50
|
-
this._cronDefinition = cronDefinition;
|
|
51
|
-
this._func = func;
|
|
52
|
-
this._opts = opts;
|
|
53
|
-
this._lastRun = Date.now();
|
|
54
|
-
this._timeoutHandler = setTimeout(() => dropPromise(this._run()), Math.max(0, this._getTimeoutDelay()));
|
|
29
|
+
#cronDefinition;
|
|
30
|
+
#func;
|
|
31
|
+
#opts;
|
|
32
|
+
/** If the task is canceled (prevent looping) */
|
|
33
|
+
#canceled = false;
|
|
34
|
+
/** Timeout handler */
|
|
35
|
+
#timeoutHandler;
|
|
36
|
+
/** Last run time (timestamp) */
|
|
37
|
+
#lastRun;
|
|
38
|
+
#logger;
|
|
39
|
+
constructor(cronDefinition, func, opts, logger = log.logger) {
|
|
40
|
+
this.#logger = logger;
|
|
41
|
+
this.#cronDefinition = cronDefinition;
|
|
42
|
+
this.#func = func;
|
|
43
|
+
this.#opts = opts;
|
|
44
|
+
this.#lastRun = Date.now();
|
|
45
|
+
this.#timeoutHandler = setTimeout(() => dropPromise(this.#run()), Math.max(0, this.#getTimeoutDelay()));
|
|
55
46
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Determine if the task should be running right now
|
|
58
|
-
*/
|
|
47
|
+
/** Determine if the task should be running right now */
|
|
59
48
|
get runnable() {
|
|
60
|
-
return this
|
|
49
|
+
return this.#getNextSchedule() <= Date.now();
|
|
61
50
|
}
|
|
62
|
-
/**
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
clearTimeout(this._timeoutHandler);
|
|
68
|
-
this._timeoutHandler = null;
|
|
51
|
+
/** Cancel the task from the scheduling */
|
|
52
|
+
cancel = () => {
|
|
53
|
+
if (this.#timeoutHandler) {
|
|
54
|
+
clearTimeout(this.#timeoutHandler);
|
|
55
|
+
this.#timeoutHandler = null;
|
|
69
56
|
}
|
|
70
|
-
this
|
|
71
|
-
}
|
|
57
|
+
this.#canceled = true;
|
|
58
|
+
};
|
|
72
59
|
/**
|
|
73
60
|
* Run the task
|
|
74
61
|
*
|
|
75
62
|
* All special cases are handled there (task already running).
|
|
76
63
|
* Updating the next value is also handled here.
|
|
77
64
|
*/
|
|
78
|
-
async
|
|
79
|
-
this
|
|
65
|
+
#run = async () => {
|
|
66
|
+
this.#timeoutHandler = null;
|
|
80
67
|
if (this.runnable) {
|
|
81
|
-
this
|
|
68
|
+
this.#lastRun = Date.now();
|
|
82
69
|
try {
|
|
83
|
-
await this
|
|
70
|
+
await this.#func();
|
|
84
71
|
}
|
|
85
72
|
catch (error) {
|
|
86
|
-
|
|
87
|
-
logError(error);
|
|
88
|
-
}
|
|
89
|
-
logError(new Error(`Unknown error: ${error.toString()}`));
|
|
73
|
+
this.#logger.error(asError(error));
|
|
90
74
|
}
|
|
91
75
|
}
|
|
92
|
-
this
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
_reschedule() {
|
|
98
|
-
if (this._canceled) {
|
|
76
|
+
this.#reschedule();
|
|
77
|
+
};
|
|
78
|
+
/** Reschedule the task for the next occurrence */
|
|
79
|
+
#reschedule = () => {
|
|
80
|
+
if (this.#canceled)
|
|
99
81
|
return;
|
|
100
|
-
|
|
101
|
-
let nextDelay = this._getTimeoutDelay();
|
|
82
|
+
let nextDelay = this.#getTimeoutDelay();
|
|
102
83
|
if (nextDelay < 0) {
|
|
103
84
|
// We overshot
|
|
104
|
-
switch (this.
|
|
105
|
-
case Overrun.AFTER:
|
|
85
|
+
switch (this.#opts.overrun) {
|
|
86
|
+
case types.Overrun.AFTER:
|
|
106
87
|
// Reschedule immediately
|
|
107
88
|
nextDelay = 0;
|
|
108
89
|
break;
|
|
109
|
-
case Overrun.SKIP:
|
|
90
|
+
case types.Overrun.SKIP:
|
|
110
91
|
// Reschedule for the next time slot
|
|
111
|
-
this
|
|
112
|
-
nextDelay = this
|
|
92
|
+
this.#lastRun = Date.now();
|
|
93
|
+
nextDelay = this.#getTimeoutDelay();
|
|
113
94
|
}
|
|
114
95
|
}
|
|
115
|
-
this
|
|
116
|
-
}
|
|
96
|
+
this.#timeoutHandler = setTimeout(() => dropPromise(this.#run()), Math.max(0, nextDelay));
|
|
97
|
+
};
|
|
117
98
|
/**
|
|
118
99
|
* Return the timeout delay before the next task scheduling.
|
|
119
100
|
*
|
|
120
101
|
* This can return a lower value if the task is scheduled in the distant
|
|
121
102
|
* future.
|
|
122
103
|
*/
|
|
123
|
-
|
|
104
|
+
#getTimeoutDelay = () => {
|
|
124
105
|
const current = Date.now();
|
|
125
|
-
const next = this
|
|
106
|
+
const next = this.#getNextSchedule();
|
|
126
107
|
return Math.min(next - current, maxTimeoutDelay);
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const nextOccurrence = CronExpressionParser.parse(this._cronDefinition, {
|
|
133
|
-
currentDate: this._lastRun,
|
|
108
|
+
};
|
|
109
|
+
/** Return the next scheduled time starting from the given point in time */
|
|
110
|
+
#getNextSchedule = () => {
|
|
111
|
+
const nextOccurrence = CronExpressionParser.parse(this.#cronDefinition, {
|
|
112
|
+
currentDate: this.#lastRun,
|
|
134
113
|
}).next();
|
|
135
114
|
return nextOccurrence.getTime();
|
|
136
|
-
}
|
|
115
|
+
};
|
|
137
116
|
}
|
package/lib/cron/types.d.ts
CHANGED
package/lib/cron.d.ts
CHANGED
|
@@ -13,17 +13,18 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
+
import { Logger } from "@keeex/log";
|
|
16
17
|
import ScheduledTask from "./cron/scheduledtask.js";
|
|
17
18
|
import { TaskFunction, TaskOptions, Overrun, CompleteTaskOptions } from "./cron/types.js";
|
|
18
19
|
export { Overrun };
|
|
19
20
|
export type { ScheduledTask, TaskFunction, TaskOptions, CompleteTaskOptions };
|
|
20
|
-
export declare const setLoggerFunction: (logFunc?: import("./cron/types.js").LoggerFunction) => void;
|
|
21
21
|
/**
|
|
22
22
|
* Schedule a task for execution
|
|
23
23
|
*
|
|
24
24
|
* @param cronDefinition - CRON timing for the task
|
|
25
25
|
* @param task - The task function to run at the scheduled time
|
|
26
26
|
* @param taskOptions - The behavior of the task
|
|
27
|
+
* @param logger - Logger for errors
|
|
27
28
|
*/
|
|
28
|
-
export declare const schedule: (cronDefinition: string, task: TaskFunction, taskOptions?: TaskOptions) => ScheduledTask;
|
|
29
|
+
export declare const schedule: (cronDefinition: string, task: TaskFunction, taskOptions?: TaskOptions, logger?: Logger) => ScheduledTask;
|
|
29
30
|
export declare const stop: () => void;
|
package/lib/cron.js
CHANGED
|
@@ -13,12 +13,10 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
import { setLoggerFunction as bitsSetLoggerFunction } from "./cron/logger.js";
|
|
17
16
|
import ScheduledTask from "./cron/scheduledtask.js";
|
|
18
17
|
import { Overrun } from "./cron/types.js";
|
|
19
18
|
const scheduledTasks = [];
|
|
20
19
|
export { Overrun };
|
|
21
|
-
export const setLoggerFunction = bitsSetLoggerFunction;
|
|
22
20
|
/**
|
|
23
21
|
* Set default values for task options
|
|
24
22
|
*/
|
|
@@ -35,9 +33,10 @@ const getDefaultTaskOptions = (taskOptions) => {
|
|
|
35
33
|
* @param cronDefinition - CRON timing for the task
|
|
36
34
|
* @param task - The task function to run at the scheduled time
|
|
37
35
|
* @param taskOptions - The behavior of the task
|
|
36
|
+
* @param logger - Logger for errors
|
|
38
37
|
*/
|
|
39
|
-
export const schedule = (cronDefinition, task, taskOptions) => {
|
|
40
|
-
const newTask = new ScheduledTask(cronDefinition, task, getDefaultTaskOptions(taskOptions));
|
|
38
|
+
export const schedule = (cronDefinition, task, taskOptions, logger) => {
|
|
39
|
+
const newTask = new ScheduledTask(cronDefinition, task, getDefaultTaskOptions(taskOptions), logger);
|
|
41
40
|
scheduledTasks.push(newTask);
|
|
42
41
|
return newTask;
|
|
43
42
|
};
|
|
@@ -13,10 +13,18 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
/** Callback called on each line from `LineBuffer` */
|
|
17
|
+
export type OutputCallback = (msg: string) => void;
|
|
17
18
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
19
|
+
* Bufferize input and produce output on newlines.
|
|
20
|
+
*
|
|
21
|
+
* The provided callback will be called on all lines, but will not get the newline character.
|
|
20
22
|
*/
|
|
21
|
-
export declare
|
|
22
|
-
|
|
23
|
+
export declare class LineBuffer {
|
|
24
|
+
#private;
|
|
25
|
+
constructor(cb: OutputCallback, separator?: string);
|
|
26
|
+
/** Call this method to add data to the buffer, and output all complete lines */
|
|
27
|
+
feed: (msg: string) => void;
|
|
28
|
+
/** Call this method to purge all currently buffered data */
|
|
29
|
+
purge: () => void;
|
|
30
|
+
}
|
|
@@ -13,10 +13,35 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
import type { LoggerFunction } from "./types.js";
|
|
17
16
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* Bufferize input and produce output on newlines.
|
|
18
|
+
*
|
|
19
|
+
* The provided callback will be called on all lines, but will not get the newline character.
|
|
20
20
|
*/
|
|
21
|
-
export
|
|
22
|
-
|
|
21
|
+
export class LineBuffer {
|
|
22
|
+
#bufferedInput = "";
|
|
23
|
+
#callback;
|
|
24
|
+
#separator;
|
|
25
|
+
constructor(cb, separator = "\n") {
|
|
26
|
+
this.#callback = cb;
|
|
27
|
+
this.#separator = separator;
|
|
28
|
+
}
|
|
29
|
+
/** Call this method to add data to the buffer, and output all complete lines */
|
|
30
|
+
feed = (msg) => {
|
|
31
|
+
this.#bufferedInput += msg;
|
|
32
|
+
this.#processInput();
|
|
33
|
+
};
|
|
34
|
+
/** Call this method to purge all currently buffered data */
|
|
35
|
+
purge = () => {
|
|
36
|
+
this.#callback(this.#bufferedInput);
|
|
37
|
+
this.#bufferedInput = "";
|
|
38
|
+
};
|
|
39
|
+
/** Filter the buffer, and output all full lines */
|
|
40
|
+
#processInput = () => {
|
|
41
|
+
for (let i = this.#bufferedInput.indexOf(this.#separator); i !== -1; i = this.#bufferedInput.indexOf(this.#separator)) {
|
|
42
|
+
const line = this.#bufferedInput.substring(0, i);
|
|
43
|
+
this.#callback(line);
|
|
44
|
+
this.#bufferedInput = this.#bufferedInput.substring(i + this.#separator.length);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@keeex/utils","version":"7.
|
|
1
|
+
{"name":"@keeex/utils","version":"7.2.0","description":"Various utility functions for pure JavaScript","scripts":{},"author":"KeeeX SAS","contributors":[{"name":"Gabriel Paul \"Cley Faye\" Risterucci","email":"gabriel@keeex.net"}],"homepage":"https://keeex.me/oss","keywords":["utility"],"type":"module","license":"MIT","dependencies":{"@keeex/bubble_babble":"^3.0.1","@keeex/log":"^1.7.1","base64-arraybuffer":"^1.0.2","cron-parser":"^5.2.0","ms":"^2.1.3","text-encoding-shim":"^1.0.5"},"exports":{"./units.js":{"node":"./lib/units.js","browser":"./web/units.js","default":"./lib/units.js"},"./uint8array.js":{"node":"./lib/uint8array.js","browser":"./web/uint8array.js","default":"./lib/uint8array.js"},"./string.js":{"node":"./lib/string.js","browser":"./web/string.js","default":"./lib/string.js"},"./starttime.js":{"node":"./lib/starttime.js","browser":"./web/starttime.js","default":"./lib/starttime.js"},"./promise.js":{"node":"./lib/promise.js","browser":"./web/promise.js","default":"./lib/promise.js"},"./path.js":{"node":"./lib/path.js","browser":"./web/path.js","default":"./lib/path.js"},"./number.js":{"node":"./lib/number.js","browser":"./web/number.js","default":"./lib/number.js"},"./linebuffer.js":{"node":"./lib/linebuffer.js","browser":"./web/linebuffer.js","default":"./lib/linebuffer.js"},"./json.js":{"node":"./lib/json.js","browser":"./web/json.js","default":"./lib/json.js"},"./idx.js":{"node":"./lib/idx.js","browser":"./web/idx.js","default":"./lib/idx.js"},"./hex.js":{"node":"./lib/hex.js","browser":"./web/hex.js","default":"./lib/hex.js"},"./global.js":{"node":"./lib/global.js","browser":"./web/global.js","default":"./lib/global.js"},"./error.js":{"node":"./lib/error.js","browser":"./web/error.js","default":"./lib/error.js"},"./dict.js":{"node":"./lib/dict.js","browser":"./web/dict.js","default":"./lib/dict.js"},"./cron.js":{"node":"./lib/cron.js","browser":"./web/cron.js","default":"./lib/cron.js"},"./consts.js":{"node":"./lib/consts.js","browser":"./web/consts.js","default":"./lib/consts.js"},"./bytebuffer.js":{"node":"./lib/bytebuffer.js","browser":"./web/bytebuffer.js","default":"./lib/bytebuffer.js"},"./benchmark.js":{"node":"./lib/benchmark.js","browser":"./web/benchmark.js","default":"./lib/benchmark.js"},"./base64.js":{"node":"./lib/base64.js","browser":"./web/base64.js","default":"./lib/base64.js"},"./base58.js":{"node":"./lib/base58.js","browser":"./web/base58.js","default":"./lib/base58.js"},"./arraybuffer.js":{"node":"./lib/arraybuffer.js","browser":"./web/arraybuffer.js","default":"./lib/arraybuffer.js"},"./array.js":{"node":"./lib/array.js","browser":"./web/array.js","default":"./lib/array.js"},"./types/utils.js":{"node":"./lib/types/utils.js","browser":"./web/types/utils.js","default":"./lib/types/utils.js"},"./types/types.js":{"node":"./lib/types/types.js","browser":"./web/types/types.js","default":"./lib/types/types.js"},"./types/record.js":{"node":"./lib/types/record.js","browser":"./web/types/record.js","default":"./lib/types/record.js"},"./types/primitive.js":{"node":"./lib/types/primitive.js","browser":"./web/types/primitive.js","default":"./lib/types/primitive.js"},"./types/predicateerror.js":{"node":"./lib/types/predicateerror.js","browser":"./web/types/predicateerror.js","default":"./lib/types/predicateerror.js"},"./types/enum.js":{"node":"./lib/types/enum.js","browser":"./web/types/enum.js","default":"./lib/types/enum.js"},"./types/array.js":{"node":"./lib/types/array.js","browser":"./web/types/array.js","default":"./lib/types/array.js"},"./marshalling/unmarshaller.js":{"node":"./lib/marshalling/unmarshaller.js","browser":"./web/marshalling/unmarshaller.js","default":"./lib/marshalling/unmarshaller.js"},"./marshalling/marshaller.js":{"node":"./lib/marshalling/marshaller.js","browser":"./web/marshalling/marshaller.js","default":"./lib/marshalling/marshaller.js"},"./async/timecache.js":{"node":"./lib/async/timecache.js","browser":"./web/async/timecache.js","default":"./lib/async/timecache.js"},"./async/queues.js":{"node":"./lib/async/queues.js","browser":"./web/async/queues.js","default":"./lib/async/queues.js"},"./async/keycache.js":{"node":"./lib/async/keycache.js","browser":"./web/async/keycache.js","default":"./lib/async/keycache.js"},"./async/deferredpromise.js":{"node":"./lib/async/deferredpromise.js","browser":"./web/async/deferredpromise.js","default":"./lib/async/deferredpromise.js"},"./async/asynctrigger.js":{"node":"./lib/async/asynctrigger.js","browser":"./web/async/asynctrigger.js","default":"./lib/async/asynctrigger.js"}},"files":["/lib","/web"]}
|
|
@@ -13,59 +13,14 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
import
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*/
|
|
16
|
+
import * as log from "@keeex/log";
|
|
17
|
+
import * as types from "./types.js";
|
|
18
|
+
/** Manage a single scheduled task */
|
|
20
19
|
export default class ScheduledTask {
|
|
21
|
-
private
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Indicate that the task missed a previous tick
|
|
26
|
-
*/
|
|
27
|
-
private readonly _restartImmediate;
|
|
28
|
-
/**
|
|
29
|
-
* If the task is canceled (prevent looping)
|
|
30
|
-
*/
|
|
31
|
-
private _canceled;
|
|
32
|
-
/**
|
|
33
|
-
* Timeout handler
|
|
34
|
-
*/
|
|
35
|
-
private _timeoutHandler;
|
|
36
|
-
/**
|
|
37
|
-
* Last run time (timestamp)
|
|
38
|
-
*/
|
|
39
|
-
private _lastRun;
|
|
40
|
-
constructor(cronDefinition: string, func: TaskFunction, opts: CompleteTaskOptions);
|
|
41
|
-
/**
|
|
42
|
-
* Determine if the task should be running right now
|
|
43
|
-
*/
|
|
20
|
+
#private;
|
|
21
|
+
constructor(cronDefinition: string, func: types.TaskFunction, opts: types.CompleteTaskOptions, logger?: log.Logger);
|
|
22
|
+
/** Determine if the task should be running right now */
|
|
44
23
|
get runnable(): boolean;
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
*/
|
|
48
|
-
cancel(): void;
|
|
49
|
-
/**
|
|
50
|
-
* Run the task
|
|
51
|
-
*
|
|
52
|
-
* All special cases are handled there (task already running).
|
|
53
|
-
* Updating the next value is also handled here.
|
|
54
|
-
*/
|
|
55
|
-
private _run;
|
|
56
|
-
/**
|
|
57
|
-
* Reschedule the task for the next occurrence
|
|
58
|
-
*/
|
|
59
|
-
private _reschedule;
|
|
60
|
-
/**
|
|
61
|
-
* Return the timeout delay before the next task scheduling.
|
|
62
|
-
*
|
|
63
|
-
* This can return a lower value if the task is scheduled in the distant
|
|
64
|
-
* future.
|
|
65
|
-
*/
|
|
66
|
-
private _getTimeoutDelay;
|
|
67
|
-
/**
|
|
68
|
-
* Return the next scheduled time starting from the given point in time
|
|
69
|
-
*/
|
|
70
|
-
private _getNextSchedule;
|
|
24
|
+
/** Cancel the task from the scheduling */
|
|
25
|
+
cancel: () => void;
|
|
71
26
|
}
|
|
@@ -13,124 +13,102 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
+
import * as log from "@keeex/log";
|
|
16
17
|
import { CronExpressionParser } from "cron-parser";
|
|
18
|
+
import { asError } from "../error.js";
|
|
17
19
|
import { dropPromise } from "../promise.js";
|
|
18
|
-
import
|
|
19
|
-
import { Overrun } from "./types.js";
|
|
20
|
+
import * as types from "./types.js";
|
|
20
21
|
/**
|
|
21
22
|
* Maximum delay for a timeout.
|
|
22
23
|
* Done because setTimeout() sometimes can only accept a 32bit integer
|
|
23
24
|
*/
|
|
24
25
|
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
25
26
|
const maxTimeoutDelay = 2 ** 31;
|
|
26
|
-
/**
|
|
27
|
-
* Manage a single scheduled task
|
|
28
|
-
*/
|
|
27
|
+
/** Manage a single scheduled task */
|
|
29
28
|
export default class ScheduledTask {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
*/
|
|
48
|
-
_lastRun;
|
|
49
|
-
constructor(cronDefinition, func, opts) {
|
|
50
|
-
this._cronDefinition = cronDefinition;
|
|
51
|
-
this._func = func;
|
|
52
|
-
this._opts = opts;
|
|
53
|
-
this._lastRun = Date.now();
|
|
54
|
-
this._timeoutHandler = setTimeout(() => dropPromise(this._run()), Math.max(0, this._getTimeoutDelay()));
|
|
29
|
+
#cronDefinition;
|
|
30
|
+
#func;
|
|
31
|
+
#opts;
|
|
32
|
+
/** If the task is canceled (prevent looping) */
|
|
33
|
+
#canceled = false;
|
|
34
|
+
/** Timeout handler */
|
|
35
|
+
#timeoutHandler;
|
|
36
|
+
/** Last run time (timestamp) */
|
|
37
|
+
#lastRun;
|
|
38
|
+
#logger;
|
|
39
|
+
constructor(cronDefinition, func, opts, logger = log.logger) {
|
|
40
|
+
this.#logger = logger;
|
|
41
|
+
this.#cronDefinition = cronDefinition;
|
|
42
|
+
this.#func = func;
|
|
43
|
+
this.#opts = opts;
|
|
44
|
+
this.#lastRun = Date.now();
|
|
45
|
+
this.#timeoutHandler = setTimeout(() => dropPromise(this.#run()), Math.max(0, this.#getTimeoutDelay()));
|
|
55
46
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Determine if the task should be running right now
|
|
58
|
-
*/
|
|
47
|
+
/** Determine if the task should be running right now */
|
|
59
48
|
get runnable() {
|
|
60
|
-
return this
|
|
49
|
+
return this.#getNextSchedule() <= Date.now();
|
|
61
50
|
}
|
|
62
|
-
/**
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
clearTimeout(this._timeoutHandler);
|
|
68
|
-
this._timeoutHandler = null;
|
|
51
|
+
/** Cancel the task from the scheduling */
|
|
52
|
+
cancel = () => {
|
|
53
|
+
if (this.#timeoutHandler) {
|
|
54
|
+
clearTimeout(this.#timeoutHandler);
|
|
55
|
+
this.#timeoutHandler = null;
|
|
69
56
|
}
|
|
70
|
-
this
|
|
71
|
-
}
|
|
57
|
+
this.#canceled = true;
|
|
58
|
+
};
|
|
72
59
|
/**
|
|
73
60
|
* Run the task
|
|
74
61
|
*
|
|
75
62
|
* All special cases are handled there (task already running).
|
|
76
63
|
* Updating the next value is also handled here.
|
|
77
64
|
*/
|
|
78
|
-
async
|
|
79
|
-
this
|
|
65
|
+
#run = async () => {
|
|
66
|
+
this.#timeoutHandler = null;
|
|
80
67
|
if (this.runnable) {
|
|
81
|
-
this
|
|
68
|
+
this.#lastRun = Date.now();
|
|
82
69
|
try {
|
|
83
|
-
await this
|
|
70
|
+
await this.#func();
|
|
84
71
|
} catch (error) {
|
|
85
|
-
|
|
86
|
-
logError(error);
|
|
87
|
-
}
|
|
88
|
-
logError(new Error(`Unknown error: ${error.toString()}`));
|
|
72
|
+
this.#logger.error(asError(error));
|
|
89
73
|
}
|
|
90
74
|
}
|
|
91
|
-
this
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (this._canceled) {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
let nextDelay = this._getTimeoutDelay();
|
|
75
|
+
this.#reschedule();
|
|
76
|
+
};
|
|
77
|
+
/** Reschedule the task for the next occurrence */
|
|
78
|
+
#reschedule = () => {
|
|
79
|
+
if (this.#canceled) return;
|
|
80
|
+
let nextDelay = this.#getTimeoutDelay();
|
|
101
81
|
if (nextDelay < 0) {
|
|
102
82
|
// We overshot
|
|
103
|
-
switch (this.
|
|
104
|
-
case Overrun.AFTER:
|
|
83
|
+
switch (this.#opts.overrun) {
|
|
84
|
+
case types.Overrun.AFTER:
|
|
105
85
|
// Reschedule immediately
|
|
106
86
|
nextDelay = 0;
|
|
107
87
|
break;
|
|
108
|
-
case Overrun.SKIP:
|
|
88
|
+
case types.Overrun.SKIP:
|
|
109
89
|
// Reschedule for the next time slot
|
|
110
|
-
this
|
|
111
|
-
nextDelay = this
|
|
90
|
+
this.#lastRun = Date.now();
|
|
91
|
+
nextDelay = this.#getTimeoutDelay();
|
|
112
92
|
}
|
|
113
93
|
}
|
|
114
|
-
this
|
|
115
|
-
}
|
|
94
|
+
this.#timeoutHandler = setTimeout(() => dropPromise(this.#run()), Math.max(0, nextDelay));
|
|
95
|
+
};
|
|
116
96
|
/**
|
|
117
97
|
* Return the timeout delay before the next task scheduling.
|
|
118
98
|
*
|
|
119
99
|
* This can return a lower value if the task is scheduled in the distant
|
|
120
100
|
* future.
|
|
121
101
|
*/
|
|
122
|
-
|
|
102
|
+
#getTimeoutDelay = () => {
|
|
123
103
|
const current = Date.now();
|
|
124
|
-
const next = this
|
|
104
|
+
const next = this.#getNextSchedule();
|
|
125
105
|
return Math.min(next - current, maxTimeoutDelay);
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const nextOccurrence = CronExpressionParser.parse(this._cronDefinition, {
|
|
132
|
-
currentDate: this._lastRun
|
|
106
|
+
};
|
|
107
|
+
/** Return the next scheduled time starting from the given point in time */
|
|
108
|
+
#getNextSchedule = () => {
|
|
109
|
+
const nextOccurrence = CronExpressionParser.parse(this.#cronDefinition, {
|
|
110
|
+
currentDate: this.#lastRun
|
|
133
111
|
}).next();
|
|
134
112
|
return nextOccurrence.getTime();
|
|
135
|
-
}
|
|
113
|
+
};
|
|
136
114
|
}
|
package/web/cron/types.d.ts
CHANGED
package/web/cron.d.ts
CHANGED
|
@@ -13,17 +13,18 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
+
import { Logger } from "@keeex/log";
|
|
16
17
|
import ScheduledTask from "./cron/scheduledtask.js";
|
|
17
18
|
import { TaskFunction, TaskOptions, Overrun, CompleteTaskOptions } from "./cron/types.js";
|
|
18
19
|
export { Overrun };
|
|
19
20
|
export type { ScheduledTask, TaskFunction, TaskOptions, CompleteTaskOptions };
|
|
20
|
-
export declare const setLoggerFunction: (logFunc?: import("./cron/types.js").LoggerFunction) => void;
|
|
21
21
|
/**
|
|
22
22
|
* Schedule a task for execution
|
|
23
23
|
*
|
|
24
24
|
* @param cronDefinition - CRON timing for the task
|
|
25
25
|
* @param task - The task function to run at the scheduled time
|
|
26
26
|
* @param taskOptions - The behavior of the task
|
|
27
|
+
* @param logger - Logger for errors
|
|
27
28
|
*/
|
|
28
|
-
export declare const schedule: (cronDefinition: string, task: TaskFunction, taskOptions?: TaskOptions) => ScheduledTask;
|
|
29
|
+
export declare const schedule: (cronDefinition: string, task: TaskFunction, taskOptions?: TaskOptions, logger?: Logger) => ScheduledTask;
|
|
29
30
|
export declare const stop: () => void;
|
package/web/cron.js
CHANGED
|
@@ -13,12 +13,10 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
import { setLoggerFunction as bitsSetLoggerFunction } from "./cron/logger.js";
|
|
17
16
|
import ScheduledTask from "./cron/scheduledtask.js";
|
|
18
17
|
import { Overrun } from "./cron/types.js";
|
|
19
18
|
const scheduledTasks = [];
|
|
20
19
|
export { Overrun };
|
|
21
|
-
export const setLoggerFunction = bitsSetLoggerFunction;
|
|
22
20
|
/**
|
|
23
21
|
* Set default values for task options
|
|
24
22
|
*/
|
|
@@ -35,9 +33,10 @@ const getDefaultTaskOptions = taskOptions => {
|
|
|
35
33
|
* @param cronDefinition - CRON timing for the task
|
|
36
34
|
* @param task - The task function to run at the scheduled time
|
|
37
35
|
* @param taskOptions - The behavior of the task
|
|
36
|
+
* @param logger - Logger for errors
|
|
38
37
|
*/
|
|
39
|
-
export const schedule = (cronDefinition, task, taskOptions) => {
|
|
40
|
-
const newTask = new ScheduledTask(cronDefinition, task, getDefaultTaskOptions(taskOptions));
|
|
38
|
+
export const schedule = (cronDefinition, task, taskOptions, logger) => {
|
|
39
|
+
const newTask = new ScheduledTask(cronDefinition, task, getDefaultTaskOptions(taskOptions), logger);
|
|
41
40
|
scheduledTasks.push(newTask);
|
|
42
41
|
return newTask;
|
|
43
42
|
};
|
|
@@ -13,19 +13,18 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
/** Callback called on each line from `LineBuffer` */
|
|
17
|
+
export type OutputCallback = (msg: string) => void;
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* Bufferize input and produce output on newlines.
|
|
20
|
+
*
|
|
21
|
+
* The provided callback will be called on all lines, but will not get the newline character.
|
|
21
22
|
*/
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
};
|
|
31
|
-
export const logError = (error) => loggerFunction(error);
|
|
23
|
+
export declare class LineBuffer {
|
|
24
|
+
#private;
|
|
25
|
+
constructor(cb: OutputCallback, separator?: string);
|
|
26
|
+
/** Call this method to add data to the buffer, and output all complete lines */
|
|
27
|
+
feed: (msg: string) => void;
|
|
28
|
+
/** Call this method to purge all currently buffered data */
|
|
29
|
+
purge: () => void;
|
|
30
|
+
}
|
|
@@ -13,18 +13,35 @@
|
|
|
13
13
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
14
14
|
*
|
|
15
15
|
*/
|
|
16
|
-
// eslint-disable-next-line no-console
|
|
17
|
-
let loggerFunction = console.error;
|
|
18
16
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* Bufferize input and produce output on newlines.
|
|
18
|
+
*
|
|
19
|
+
* The provided callback will be called on all lines, but will not get the newline character.
|
|
21
20
|
*/
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
export class LineBuffer {
|
|
22
|
+
#bufferedInput = "";
|
|
23
|
+
#callback;
|
|
24
|
+
#separator;
|
|
25
|
+
constructor(cb, separator = "\n") {
|
|
26
|
+
this.#callback = cb;
|
|
27
|
+
this.#separator = separator;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
/** Call this method to add data to the buffer, and output all complete lines */
|
|
30
|
+
feed = msg => {
|
|
31
|
+
this.#bufferedInput += msg;
|
|
32
|
+
this.#processInput();
|
|
33
|
+
};
|
|
34
|
+
/** Call this method to purge all currently buffered data */
|
|
35
|
+
purge = () => {
|
|
36
|
+
this.#callback(this.#bufferedInput);
|
|
37
|
+
this.#bufferedInput = "";
|
|
38
|
+
};
|
|
39
|
+
/** Filter the buffer, and output all full lines */
|
|
40
|
+
#processInput = () => {
|
|
41
|
+
for (let i = this.#bufferedInput.indexOf(this.#separator); i !== -1; i = this.#bufferedInput.indexOf(this.#separator)) {
|
|
42
|
+
const line = this.#bufferedInput.substring(0, i);
|
|
43
|
+
this.#callback(line);
|
|
44
|
+
this.#bufferedInput = this.#bufferedInput.substring(i + this.#separator.length);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|