@quazardous/quarkernel 1.0.12 → 2.2.3

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