@muspellheim/shared 0.6.0 → 0.7.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/LICENSE.txt +1 -1
- package/README.md +11 -13
- package/dist/shared.d.ts +423 -0
- package/dist/shared.js +535 -0
- package/dist/shared.umd.cjs +1 -0
- package/package.json +27 -23
- package/.prettierignore +0 -3
- package/.prettierrc +0 -5
- package/deno.json +0 -15
- package/deno.mk +0 -68
- package/eslint.config.js +0 -23
- package/lib/assert.js +0 -15
- package/lib/browser/components.js +0 -165
- package/lib/browser/index.js +0 -3
- package/lib/color.js +0 -137
- package/lib/configurable-responses.js +0 -69
- package/lib/feature-toggle.js +0 -9
- package/lib/health.js +0 -510
- package/lib/index.js +0 -23
- package/lib/lang.js +0 -100
- package/lib/logging.js +0 -599
- package/lib/long-polling-client.js +0 -186
- package/lib/message-client.js +0 -68
- package/lib/messages.js +0 -68
- package/lib/metrics.js +0 -120
- package/lib/node/actuator-controller.js +0 -102
- package/lib/node/configuration-properties.js +0 -291
- package/lib/node/handler.js +0 -25
- package/lib/node/index.js +0 -9
- package/lib/node/logging.js +0 -60
- package/lib/node/long-polling.js +0 -83
- package/lib/node/sse-emitter.js +0 -104
- package/lib/node/static-files-controller.js +0 -15
- package/lib/output-tracker.js +0 -89
- package/lib/service-locator.js +0 -44
- package/lib/sse-client.js +0 -163
- package/lib/stop-watch.js +0 -54
- package/lib/store.js +0 -129
- package/lib/time.js +0 -445
- package/lib/util.js +0 -380
- package/lib/validation.js +0 -290
- package/lib/vector.js +0 -194
- package/lib/vitest/equality-testers.js +0 -19
- package/lib/vitest/index.js +0 -1
- package/lib/web-socket-client.js +0 -262
- package/tsconfig.json +0 -13
package/lib/service-locator.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2023-2024 Falko Schumann. All rights reserved. MIT license.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A central place to register and resolve services.
|
|
5
|
-
*/
|
|
6
|
-
export class ServiceLocator {
|
|
7
|
-
static #instance = new ServiceLocator();
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Gets the default service locator.
|
|
11
|
-
*
|
|
12
|
-
* @return {ServiceLocator} The default service locator.
|
|
13
|
-
*/
|
|
14
|
-
static getDefault() {
|
|
15
|
-
return ServiceLocator.#instance;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
#services = new Map();
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Registers a service with name.
|
|
22
|
-
*
|
|
23
|
-
* @param {string} name The name of the service.
|
|
24
|
-
* @param {object|Function} service The service object or constructor.
|
|
25
|
-
*/
|
|
26
|
-
register(name, service) {
|
|
27
|
-
this.#services.set(name, service);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Resolves a service by name.
|
|
32
|
-
*
|
|
33
|
-
* @param {string} name The name of the service.
|
|
34
|
-
* @return {object} The service object.
|
|
35
|
-
*/
|
|
36
|
-
resolve(name) {
|
|
37
|
-
const service = this.#services.get(name);
|
|
38
|
-
if (service == null) {
|
|
39
|
-
throw new Error(`Service not found: ${name}.`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return typeof service === 'function' ? service() : service;
|
|
43
|
-
}
|
|
44
|
-
}
|
package/lib/sse-client.js
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2023-2024 Falko Schumann. All rights reserved. MIT license.
|
|
2
|
-
|
|
3
|
-
import { MessageClient } from './message-client.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @ignore @typedef {typeof EventSource} EventSourceConstructor
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* A client for the server-sent events protocol.
|
|
11
|
-
*
|
|
12
|
-
* @implements {MessageClient}
|
|
13
|
-
*/
|
|
14
|
-
export class SseClient extends MessageClient {
|
|
15
|
-
/**
|
|
16
|
-
* Creates a SSE client.
|
|
17
|
-
*
|
|
18
|
-
* @return {SseClient} A new SSE client.
|
|
19
|
-
*/
|
|
20
|
-
static create() {
|
|
21
|
-
return new SseClient(EventSource);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Creates a nulled SSE client.
|
|
26
|
-
*
|
|
27
|
-
* @return {SseClient} A new SSE client.
|
|
28
|
-
*/
|
|
29
|
-
static createNull() {
|
|
30
|
-
return new SseClient(EventSourceStub);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
#eventSourceConstructor;
|
|
34
|
-
/** @type {EventSource} */ #eventSource;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* The constructor is for internal use. Use the factory methods instead.
|
|
38
|
-
*
|
|
39
|
-
* @param {EventSourceConstructor} eventSourceConstructor
|
|
40
|
-
* @see SseClient.create
|
|
41
|
-
* @see SseClient.createNull
|
|
42
|
-
*/
|
|
43
|
-
constructor(eventSourceConstructor) {
|
|
44
|
-
super();
|
|
45
|
-
this.#eventSourceConstructor = eventSourceConstructor;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @override
|
|
50
|
-
*/
|
|
51
|
-
get isConnected() {
|
|
52
|
-
return this.#eventSource?.readyState === this.#eventSourceConstructor.OPEN;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @override
|
|
57
|
-
*/
|
|
58
|
-
get url() {
|
|
59
|
-
return this.#eventSource?.url;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Connects to the server.
|
|
64
|
-
* @param {URL | string} url The server URL to connect to.
|
|
65
|
-
* @param {string} [eventName] The optional event type to listen to.
|
|
66
|
-
* @override
|
|
67
|
-
*/
|
|
68
|
-
async connect(url, eventName = 'message') {
|
|
69
|
-
await new Promise((resolve, reject) => {
|
|
70
|
-
if (this.isConnected) {
|
|
71
|
-
reject(new Error('Already connected.'));
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
this.#eventSource = new this.#eventSourceConstructor(url);
|
|
77
|
-
this.#eventSource.addEventListener('open', (e) => {
|
|
78
|
-
this.#handleOpen(e);
|
|
79
|
-
resolve();
|
|
80
|
-
});
|
|
81
|
-
this.#eventSource.addEventListener(eventName, (e) =>
|
|
82
|
-
this.#handleMessage(e),
|
|
83
|
-
);
|
|
84
|
-
this.#eventSource.addEventListener('error', (e) =>
|
|
85
|
-
this.#handleError(e),
|
|
86
|
-
);
|
|
87
|
-
} catch (error) {
|
|
88
|
-
reject(error);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* @override
|
|
95
|
-
*/
|
|
96
|
-
async close() {
|
|
97
|
-
await new Promise((resolve, reject) => {
|
|
98
|
-
if (!this.isConnected) {
|
|
99
|
-
resolve();
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
this.#eventSource.close();
|
|
105
|
-
resolve();
|
|
106
|
-
} catch (error) {
|
|
107
|
-
reject(error);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Simulates a message event from the server.
|
|
114
|
-
*
|
|
115
|
-
* @param {string} message The message to receive.
|
|
116
|
-
* @param {string} [eventName=message] The optional event type.
|
|
117
|
-
* @param {string} [lastEventId] The optional last event ID.
|
|
118
|
-
*/
|
|
119
|
-
simulateMessage(message, eventName = 'message', lastEventId = undefined) {
|
|
120
|
-
this.#handleMessage(
|
|
121
|
-
new MessageEvent(eventName, { data: message, lastEventId }),
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Simulates an error event.
|
|
127
|
-
*/
|
|
128
|
-
simulateError() {
|
|
129
|
-
this.#handleError(new Event('error'));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
#handleOpen(event) {
|
|
133
|
-
this.dispatchEvent(new event.constructor(event.type, event));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
#handleMessage(event) {
|
|
137
|
-
this.dispatchEvent(new event.constructor(event.type, event));
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
#handleError(event) {
|
|
141
|
-
this.dispatchEvent(new event.constructor(event.type, event));
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
class EventSourceStub extends EventTarget {
|
|
146
|
-
// The constants have to be defined here because JSDOM is missing EventSource.
|
|
147
|
-
static CONNECTING = 0;
|
|
148
|
-
static OPEN = 1;
|
|
149
|
-
static CLOSED = 2;
|
|
150
|
-
|
|
151
|
-
constructor(url) {
|
|
152
|
-
super();
|
|
153
|
-
this.url = url;
|
|
154
|
-
setTimeout(() => {
|
|
155
|
-
this.readyState = EventSourceStub.OPEN;
|
|
156
|
-
this.dispatchEvent(new Event('open'));
|
|
157
|
-
}, 0);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
close() {
|
|
161
|
-
this.readyState = EventSourceStub.CLOSED;
|
|
162
|
-
}
|
|
163
|
-
}
|
package/lib/stop-watch.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2023-2024 Falko Schumann. All rights reserved. MIT license.
|
|
2
|
-
|
|
3
|
-
import { Clock } from './time.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* A simple stop watch.
|
|
7
|
-
*/
|
|
8
|
-
export class StopWatch {
|
|
9
|
-
#clock;
|
|
10
|
-
#startTime;
|
|
11
|
-
#stopTime;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Creates a new stop watch.
|
|
15
|
-
*
|
|
16
|
-
* @param {Clock} [clock=Clock.system()] The clock to use for time
|
|
17
|
-
* measurement.
|
|
18
|
-
*/
|
|
19
|
-
constructor(clock = Clock.system()) {
|
|
20
|
-
this.#clock = clock;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Starts an unnamed task.
|
|
25
|
-
*/
|
|
26
|
-
start() {
|
|
27
|
-
this.#startTime = this.#clock.millis();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Stops the current task.
|
|
32
|
-
*/
|
|
33
|
-
stop() {
|
|
34
|
-
this.#stopTime = this.#clock.millis();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Gets the total time in milliseconds.
|
|
39
|
-
*
|
|
40
|
-
* @return {number} The total time in milliseconds.
|
|
41
|
-
*/
|
|
42
|
-
getTotalTimeMillis() {
|
|
43
|
-
return this.#stopTime - this.#startTime;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Gets the total time in seconds.
|
|
48
|
-
*
|
|
49
|
-
* @return {number} The total time in seconds.
|
|
50
|
-
*/
|
|
51
|
-
getTotalTimeSeconds() {
|
|
52
|
-
return this.getTotalTimeMillis() / 1000;
|
|
53
|
-
}
|
|
54
|
-
}
|
package/lib/store.js
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2023-2024 Falko Schumann. All rights reserved. MIT license.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Simple global state management with store and reducer.
|
|
5
|
-
*
|
|
6
|
-
* This implementation is compatible with [Redux](https://redux.js.org). It is
|
|
7
|
-
* intended to replace it with Redux if necessary, for example if the
|
|
8
|
-
* application grows.
|
|
9
|
-
*
|
|
10
|
-
* @module
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* A reducer is a function that changes the state of the application based on an
|
|
15
|
-
* action.
|
|
16
|
-
*
|
|
17
|
-
* @callback ReducerType
|
|
18
|
-
* @param {StateType} state The current state of the application.
|
|
19
|
-
* @param {ActionType} action The action to handle.
|
|
20
|
-
* @return {StateType} The next state of the application or the initial state
|
|
21
|
-
* if the state parameter is `undefined`.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* The application state can be any object.
|
|
26
|
-
*
|
|
27
|
-
* @typedef {object} StateType
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* An action describe an command or an event that changes the state of the
|
|
32
|
-
* application.
|
|
33
|
-
*
|
|
34
|
-
* An action can have any properties, but it should have a `type` property.
|
|
35
|
-
*
|
|
36
|
-
* @typedef {object} ActionType
|
|
37
|
-
* @property {string} type A string that identifies the action.
|
|
38
|
-
*/
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* A listener is a function that is called when the state of the store changes.
|
|
42
|
-
*
|
|
43
|
-
* @callback ListenerType
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* An unsubscriber is a function that removes a listener from the store.
|
|
48
|
-
*
|
|
49
|
-
* @callback UnsubscriberType
|
|
50
|
-
*/
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Creates a new store with the given reducer and optional preloaded state.
|
|
54
|
-
*
|
|
55
|
-
* @param {ReducerType} reducer The reducer function.
|
|
56
|
-
* @param {StateType} [preloadedState] The optional initial state of the store.
|
|
57
|
-
* @return {Store} The new store.
|
|
58
|
-
*/
|
|
59
|
-
export function createStore(reducer, preloadedState) {
|
|
60
|
-
const initialState = preloadedState || reducer(undefined, { type: '@@INIT' });
|
|
61
|
-
return new Store(reducer, initialState);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* A simple store compatible with [Redux](https://redux.js.org/api/store).
|
|
66
|
-
*/
|
|
67
|
-
export class Store {
|
|
68
|
-
#reducer;
|
|
69
|
-
#state;
|
|
70
|
-
#listeners = [];
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Creates a new store with the given reducer and initial state.
|
|
74
|
-
*
|
|
75
|
-
* @param {ReducerType} reducer
|
|
76
|
-
* @param {StateType} initialState
|
|
77
|
-
*/
|
|
78
|
-
constructor(reducer, initialState) {
|
|
79
|
-
this.#reducer = reducer;
|
|
80
|
-
this.#state = initialState;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Returns the current state of the store.
|
|
85
|
-
*
|
|
86
|
-
* @return {StateType} The current state of the store.
|
|
87
|
-
*/
|
|
88
|
-
getState() {
|
|
89
|
-
return this.#state;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Updates the state of the store by dispatching an action to the reducer.
|
|
94
|
-
*
|
|
95
|
-
* @param {ActionType} action The action to dispatch.
|
|
96
|
-
*/
|
|
97
|
-
dispatch(action) {
|
|
98
|
-
const oldState = this.#state;
|
|
99
|
-
this.#state = this.#reducer(this.#state, action);
|
|
100
|
-
if (oldState !== this.#state) {
|
|
101
|
-
this.#emitChange();
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Subscribes a listener to store changes.
|
|
107
|
-
*
|
|
108
|
-
* @param {ListenerType} listener The listener to subscribe.
|
|
109
|
-
* @return {UnsubscriberType} A function that unsubscribes the listener.
|
|
110
|
-
*/
|
|
111
|
-
subscribe(listener) {
|
|
112
|
-
this.#listeners.push(listener);
|
|
113
|
-
return () => this.#unsubscribe(listener);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
#emitChange() {
|
|
117
|
-
this.#listeners.forEach((listener) => {
|
|
118
|
-
// Unsubscribe replace listeners array with a new array, so we must double
|
|
119
|
-
// check if listener is still subscribed.
|
|
120
|
-
if (this.#listeners.includes(listener)) {
|
|
121
|
-
listener();
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
#unsubscribe(listener) {
|
|
127
|
-
this.#listeners = this.#listeners.filter((l) => l !== listener);
|
|
128
|
-
}
|
|
129
|
-
}
|