@quazardous/quarkernel 1.0.11 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,390 +0,0 @@
1
- /* eslint-disable no-plusplus */
2
- import toposort from 'toposort';
3
-
4
- class GraphNode {
5
- /**
6
- * @param {string} target
7
- * @param {string} name
8
- * @param {Array<string>} requires
9
- * @param {eventListenerCallback|async eventListenerCallback} callback
10
- */
11
- constructor(target, name, requires, callback) {
12
- /**
13
- * @type {string}
14
- */
15
- this.target = target;
16
- /**
17
- * @type {string}
18
- */
19
- this.name = name;
20
- /**
21
- * @type {Array<string>}
22
- */
23
- this.requires = requires;
24
- /**
25
- * @type {eventListenerCallback|async eventListenerCallback}
26
- */
27
- this.callback = callback;
28
- }
29
- }
30
-
31
- class GraphNodeProcessor {
32
- /**
33
- * @param {Array<GraphNode>} nodes
34
- */
35
- constructor(nodes) {
36
- /**
37
- * @type {Object.<string, {promise:Promise<QuarKernelEvent>|null,node:GraphNode}>}
38
- */
39
- this.processMap = {};
40
- /**
41
- * @type {Array<GraphNode>} nodes
42
- */
43
- this.nodes = nodes;
44
- nodes.forEach(n => {
45
- this.processMap[n.name] = {
46
- promise: null,
47
- node: n
48
- };
49
- });
50
- }
51
-
52
- /**
53
- * @param {QuarKernelEvent} e
54
- * @return {Promise<QuarKernelEvent>}
55
- * @private
56
- */
57
- processAll(e) {
58
- return Promise.all(
59
- this.nodes.map(n => this.process(n, e))
60
- ).then(() => e);
61
- }
62
-
63
- /**
64
- * @param {GraphNode} node
65
- * @param {QuarKernelEvent} e
66
- * @return {Promise<*>}
67
- * @private
68
- */
69
- process(node, e) {
70
- const process = this.processMap[node.name];
71
- if (!process.promise) {
72
- let then = null;
73
- if (node.callback.constructor.name === 'AsyncFunction') {
74
- // handle async
75
- then = () => node.callback(e, node.target);
76
- } else {
77
- then = () => new Promise((resolve) => {
78
- node.callback(e, node.target);
79
- resolve();
80
- });
81
- }
82
- process.promise = this.processDependencies(node, e).then(then);
83
- }
84
- return process.promise;
85
- }
86
-
87
- /**
88
- * @param {GraphNode} node
89
- * @param {QuarKernelEvent} e
90
- * @return {Promise<*>}
91
- * @private
92
- */
93
- processDependencies(node, e) {
94
- if (node.requires.length) {
95
- const promises = [];
96
- this.nodes.forEach(n => {
97
- if (node.requires.includes(n.target)) {
98
- promises.push(this.process(n, e));
99
- }
100
- });
101
- return Promise.all(promises);
102
- }
103
- return Promise.resolve();
104
- }
105
- }
106
-
107
- class QuarKernelEvent {
108
- /**
109
- * @param {string} type Type of the event
110
- * @param {Object} [param] Parameters for this event
111
- * @param {Object} [context] Modifiable context for this event
112
- */
113
- constructor(type, param, context) {
114
- this.type = type;
115
- this.param = param || {};
116
- this.context = context || {};
117
- }
118
- }
119
-
120
- // /**
121
- // * @typedef {Object} Person
122
- // * @property {string} name how the person is called
123
- // * @property {number} age how many years the person lived
124
- // */
125
-
126
- /**
127
- * @private
128
- */
129
- class CompositeTrigger {
130
- /**
131
- * @param {Array<string>} components
132
- * @param {*} callback
133
- */
134
- constructor(components, callback, reset) {
135
- this.components = components;
136
- this.callback = callback;
137
- this.reset = reset;
138
- /**
139
- * @type {Object.<string, Array<{e:QuarKernelEvent,p:Promise<QuarKernelEvent>}>>}
140
- */
141
- this.eventPromiseStack = {};
142
- }
143
-
144
- /**
145
- * @param {QuarKernelEvent} e
146
- * @param {Promise<*>} p
147
- * @return {Promise<*>|null}
148
- * @private
149
- */
150
- compose(e, p) {
151
- if (!this.components.includes(e.type)) {
152
- return;
153
- }
154
- if (typeof this.eventPromiseStack[e.type] === 'undefined') {
155
- this.eventPromiseStack[e.type] = [];
156
- }
157
- this.eventPromiseStack[e.type].push({e, p});
158
-
159
- let allComponents = true;
160
- this.components.forEach((type) => {
161
- if (typeof this.eventPromiseStack[e.type] === 'undefined') {
162
- allComponents = false;
163
- }
164
- });
165
-
166
- if (!allComponents) {
167
- return null;
168
- }
169
-
170
- // we got all components !
171
- const stack = this.eventPromiseStack;
172
- if (this.reset) {
173
- this.eventPromiseStack = {};
174
- }
175
- return new Promise((resolve) => {
176
- resolve(this.callback(stack));
177
- });
178
- }
179
- }
180
-
181
- /**
182
- * @callback eventListenerCallback
183
- * @param {QuarKernelEvent} [e]
184
- */
185
-
186
- /**
187
- * @callback composeTriggerCallback
188
- * @param {Object.<string, Array<{e:QuarKernelEvent,p:Promise<QuarKernelEvent>}>>} [stack] Stack of components events/promises
189
- */
190
-
191
- /**
192
- * @callback composeEventFactory
193
- * @param {Object.<string, Array<QuarKernelEvent>>} [stack] Stack of components events
194
- * @return {QuarKernelEvent}
195
- */
196
-
197
- /**
198
- * @callback eventCallback
199
- * @param {QuarKernelEvent} [e] The event
200
- * @param {string} [target] The current target
201
- */
202
-
203
- /**
204
- * @callback eventAsyncCallback
205
- * @async
206
- * @param {QuarKernelEvent} [e] The event
207
- * @param {string} [target] The current target
208
- */
209
-
210
- class QuarKernel {
211
- constructor(options = {}) {
212
- /**
213
- * For each event type, list of valid target sequences.
214
- * ie sequence [A, B] means A must be fired before B.
215
- * @type {Array<string,Array<Array<string>>>}
216
- * @private
217
- */
218
- this.seqGraph = {};
219
- /**
220
- * For each event type and target list of direct targets dependencies.
221
- * @type {Array<string,Array<string,Array<string>>>}
222
- * @private
223
- */
224
- this.dependencies = {};
225
- /**
226
- * @type {Array<string,Array<string,Array<eventCallback|eventAsyncCallback>>}
227
- * @private
228
- */
229
- this.callbacks = {};
230
- /**
231
- * @private
232
- */
233
- this.targetAutoId = 0;
234
- /**
235
- * @type {Array<CompositeTrigger>}
236
- * @private
237
- */
238
- this.compositeTriggers = [];
239
- }
240
-
241
- /**
242
- * Register for some event.
243
- *
244
- * @param {string} type Type of event to listen to
245
- * @param {eventCallback|eventAsyncCallback} callback
246
- * @param {string} [target] A unique code for the target listener
247
- * @param {string|Array<string>} [dependencies] A list of targets dependencies
248
- * In the event scope, callbacks will be fired according to dependencies
249
- */
250
- addEventListener(type, callback, target, dependencies = []) {
251
- if (!target) {
252
- target = `.auto.${this.targetAutoId}`;
253
- this.targetAutoId++;
254
- }
255
- let deps = dependencies;
256
- if (!Array.isArray(deps)) {
257
- deps = [deps];
258
- }
259
- if (typeof this.seqGraph[type] === 'undefined') {
260
- this.seqGraph[type] = [];
261
- }
262
- deps.forEach((dep) => {
263
- this.seqGraph[type].push([dep, target]);
264
- });
265
- if (typeof this.callbacks[type] === 'undefined') {
266
- this.callbacks[type] = {};
267
- }
268
- if (typeof this.callbacks[type][target] === 'undefined') {
269
- this.callbacks[type][target] = [];
270
- }
271
- this.callbacks[type][target].push(callback);
272
- }
273
-
274
- /**
275
- * Create a composite trigger.
276
- *
277
- * @param {Array<string>} components list of event types
278
- * @param {composeTriggerCallback} callback something to do
279
- */
280
- addCompositeTrigger(components, callback, reset = true) {
281
- this.compositeTriggers.push(new CompositeTrigger(components, callback, reset));
282
- }
283
-
284
- /**
285
- * Create a composite event.
286
- *
287
- * @param {Array<string>} components list of event types
288
- * @param {composeEventFactory} factory event factory
289
- */
290
- addCompositeEvent(components, factory, reset = true) {
291
- this.addCompositeTrigger(components, (stack) => {
292
- const eventStack = {};
293
- const list = [];
294
- for (const type in stack) {
295
- eventStack[type] = [];
296
- stack[type].forEach((item) => {
297
- list.push(item.p);
298
- eventStack[type].push(item.e);
299
- })
300
- }
301
- const self = this;
302
- Promise.all(list).then(() => {
303
- // dispatch after all event promises
304
- self.dispatchEvent(factory(eventStack));
305
- });
306
- }, reset);
307
- }
308
-
309
- /**
310
- * @param {QuarKernelEvent} e
311
- * @param {Promise<QuarKernelEvent>} p
312
- * @return {Promise<QuarKernelEvent>}
313
- * @private
314
- */
315
- composeTrigger(e, p) {
316
- const list = [];
317
- this.compositeTriggers.forEach((ct) => {
318
- const ctp = ct.compose(e, p);
319
- if (ctp) {
320
- list.push(ctp);
321
- }
322
- });
323
- if (list.length > 0) {
324
- p = p.then(() => Promise.all(list).then(() => e))
325
- }
326
- return p;
327
- }
328
-
329
- /**
330
- * Dispatch an event.
331
- *
332
- * @param {QuarKernelEvent} e The event
333
- * @return {Promise<QuarKernelEvent>}
334
- */
335
- dispatchEvent(e) {
336
- if (!(e instanceof QuarKernelEvent)) {
337
- throw new Error('Not a QuarKernelEvent');
338
- }
339
- if (typeof this.callbacks[e.type] === 'undefined') {
340
- // no callback registered
341
- return this.composeTrigger(e, Promise.resolve(e));
342
- }
343
- if (typeof this.seqGraph[e.type] !== 'undefined') {
344
- // using toposort to early detect dependencies loop
345
- toposort(this.seqGraph[e.type]);
346
- }
347
-
348
- const nodes = [];
349
-
350
- Object.keys(this.callbacks[e.type]).forEach((target) => {
351
- this.callbacks[e.type][target].forEach((callback, i) => {
352
- nodes.push(new GraphNode(
353
- target,
354
- `${target}.${i}`, // each callback gets a node
355
- this.getTargetDependencies(e.type, target),
356
- callback
357
- ));
358
- });
359
- });
360
-
361
- return this.composeTrigger(e, (new GraphNodeProcessor(nodes)).processAll(e));
362
- }
363
-
364
- /**
365
- * @param {string} type
366
- * @param {string} target
367
- * @return {Array<string>}
368
- * @private
369
- */
370
- getTargetDependencies(type, target) {
371
- if (typeof this.dependencies[type] === 'undefined') {
372
- this.dependencies[type] = {};
373
- }
374
- if (typeof this.dependencies[type][target] === 'undefined') {
375
- this.dependencies[type][target] = [];
376
- if (typeof this.seqGraph[type] !== 'undefined') {
377
- this.seqGraph[type].forEach((seq) => {
378
- if (seq[1] === target) {
379
- this.dependencies[type][target].push(seq[0]);
380
- }
381
- });
382
- // unique trick
383
- this.dependencies[type][target] = [...new Set(this.dependencies[type][target])];
384
- }
385
- }
386
- return this.dependencies[type][target];
387
- }
388
- }
389
-
390
- export { QuarKernel, QuarKernelEvent };
@@ -1,122 +0,0 @@
1
- export type eventListenerCallback = (e?: QuarKernelEvent) => any;
2
- export type composeTriggerCallback = (stack?: {
3
- [x: string]: Array<{
4
- e: QuarKernelEvent;
5
- p: Promise<QuarKernelEvent>;
6
- }>;
7
- }) => any;
8
- export type composeEventFactory = (stack?: {
9
- [x: string]: Array<QuarKernelEvent>;
10
- }) => QuarKernelEvent;
11
- export type eventCallback = (e?: QuarKernelEvent, target?: string) => any;
12
- export type eventAsyncCallback = () => any;
13
- /**
14
- * @callback eventListenerCallback
15
- * @param {QuarKernelEvent} [e]
16
- */
17
- /**
18
- * @callback composeTriggerCallback
19
- * @param {Object.<string, Array<{e:QuarKernelEvent,p:Promise<QuarKernelEvent>}>>} [stack] Stack of components events/promises
20
- */
21
- /**
22
- * @callback composeEventFactory
23
- * @param {Object.<string, Array<QuarKernelEvent>>} [stack] Stack of components events
24
- * @return {QuarKernelEvent}
25
- */
26
- /**
27
- * @callback eventCallback
28
- * @param {QuarKernelEvent} [e] The event
29
- * @param {string} [target] The current target
30
- */
31
- /**
32
- * @callback eventAsyncCallback
33
- * @async
34
- * @param {QuarKernelEvent} [e] The event
35
- * @param {string} [target] The current target
36
- */
37
- export class QuarKernel {
38
- constructor(options?: {});
39
- /**
40
- * For each event type, list of valid target sequences.
41
- * ie sequence [A, B] means A must be fired before B.
42
- * @type {Array<string,Array<Array<string>>>}
43
- * @private
44
- */
45
- private seqGraph;
46
- /**
47
- * For each event type and target list of direct targets dependencies.
48
- * @type {Array<string,Array<string,Array<string>>>}
49
- * @private
50
- */
51
- private dependencies;
52
- /**
53
- * @type {Array<string,Array<string,Array<eventCallback|eventAsyncCallback>>}
54
- * @private
55
- */
56
- private callbacks;
57
- /**
58
- * @private
59
- */
60
- private targetAutoId;
61
- /**
62
- * @type {Array<CompositeTrigger>}
63
- * @private
64
- */
65
- private compositeTriggers;
66
- /**
67
- * Register for some event.
68
- *
69
- * @param {string} type Type of event to listen to
70
- * @param {eventCallback|eventAsyncCallback} callback
71
- * @param {string} [target] A unique code for the target listener
72
- * @param {string|Array<string>} [dependencies] A list of targets dependencies
73
- * In the event scope, callbacks will be fired according to dependencies
74
- */
75
- addEventListener(type: string, callback: eventCallback | eventAsyncCallback, target?: string, dependencies?: string | Array<string>): void;
76
- /**
77
- * Create a composite trigger.
78
- *
79
- * @param {Array<string>} components list of event types
80
- * @param {composeTriggerCallback} callback something to do
81
- */
82
- addCompositeTrigger(components: Array<string>, callback: composeTriggerCallback, reset?: boolean): void;
83
- /**
84
- * Create a composite event.
85
- *
86
- * @param {Array<string>} components list of event types
87
- * @param {composeEventFactory} factory event factory
88
- */
89
- addCompositeEvent(components: Array<string>, factory: composeEventFactory, reset?: boolean): void;
90
- /**
91
- * @param {QuarKernelEvent} e
92
- * @param {Promise<QuarKernelEvent>} p
93
- * @return {Promise<QuarKernelEvent>}
94
- * @private
95
- */
96
- private composeTrigger;
97
- /**
98
- * Dispatch an event.
99
- *
100
- * @param {QuarKernelEvent} e The event
101
- * @return {Promise<QuarKernelEvent>}
102
- */
103
- dispatchEvent(e: QuarKernelEvent): Promise<QuarKernelEvent>;
104
- /**
105
- * @param {string} type
106
- * @param {string} target
107
- * @return {Array<string>}
108
- * @private
109
- */
110
- private getTargetDependencies;
111
- }
112
- export class QuarKernelEvent {
113
- /**
114
- * @param {string} type Type of the event
115
- * @param {Object} [param] Parameters for this event
116
- * @param {Object} [context] Modifiable context for this event
117
- */
118
- constructor(type: string, param?: any, context?: any);
119
- type: string;
120
- param: any;
121
- context: any;
122
- }