@lumjs/core 1.31.0 → 1.31.1
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/lib/events/index.js +14 -2
- package/lib/events/registry.js +239 -39
- package/lib/index.js +3 -0
- package/lib/state.js +61 -0
- package/lum.build.js +9 -38
- package/package.json +2 -2
package/lib/events/index.js
CHANGED
|
@@ -23,8 +23,20 @@ exports = module.exports =
|
|
|
23
23
|
* @param {object} [opts]
|
|
24
24
|
* @returns {module:@lumjs/core/events.Registry}
|
|
25
25
|
*/
|
|
26
|
-
register()
|
|
26
|
+
register(targets, opts)
|
|
27
27
|
{
|
|
28
|
-
return new exports.Registry(
|
|
28
|
+
return new exports.Registry(targets, opts);
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Create a registry for a single target object, then return the target.
|
|
33
|
+
* @param {object} target
|
|
34
|
+
* @param {object} [opts]
|
|
35
|
+
* @returns {object} `target`
|
|
36
|
+
*/
|
|
37
|
+
extend(target, opts)
|
|
38
|
+
{
|
|
39
|
+
exports.register(target, opts);
|
|
40
|
+
return target;
|
|
29
41
|
},
|
|
30
42
|
}
|
package/lib/events/registry.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const {S,F,isObj,def,isIterable} = require('../types');
|
|
4
4
|
const Listener = require('./listener');
|
|
5
|
+
const RegSym = Symbol('@lumjs/core/events:registry');
|
|
5
6
|
|
|
6
7
|
const DEF_EXTENDS =
|
|
7
8
|
{
|
|
@@ -19,6 +20,53 @@ const DEF_OPTIONS =
|
|
|
19
20
|
wildcard: '*',
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Has a target object been registered with an event registry?
|
|
25
|
+
* @param {object} target
|
|
26
|
+
* @returns {boolean}
|
|
27
|
+
* @alias module:@lumjs/core/events.Registry.isRegistered
|
|
28
|
+
*/
|
|
29
|
+
const isRegistered = target => isObj(target[RegSym]);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get event registry metadata from a target
|
|
33
|
+
* @private
|
|
34
|
+
* @param {object} target - Object to get metadata for
|
|
35
|
+
* @param {boolean} [create=false] Create metadata if it's not found?
|
|
36
|
+
* @returns {object} metadata (TODO: schema docs)
|
|
37
|
+
* @alias module:@lumjs/core/events.Registry.getMetadata
|
|
38
|
+
*/
|
|
39
|
+
function getMetadata(target, create=false)
|
|
40
|
+
{
|
|
41
|
+
if (isRegistered(target))
|
|
42
|
+
{ // Existing registry metadata found
|
|
43
|
+
return target[RegSym];
|
|
44
|
+
}
|
|
45
|
+
else if (create)
|
|
46
|
+
{ // Create new metadata
|
|
47
|
+
const tpm =
|
|
48
|
+
{
|
|
49
|
+
r: new Map(),
|
|
50
|
+
p: {},
|
|
51
|
+
}
|
|
52
|
+
def(target, RegSym, tpm);
|
|
53
|
+
return tpm;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function targetsAre(targets)
|
|
58
|
+
{
|
|
59
|
+
const isaSet = (targets instanceof Set);
|
|
60
|
+
const isaArr = (!isaSet && Array.isArray(targets));
|
|
61
|
+
const tis =
|
|
62
|
+
{
|
|
63
|
+
set: isaSet,
|
|
64
|
+
array: isaArr,
|
|
65
|
+
handled: (isaSet || isaArr),
|
|
66
|
+
}
|
|
67
|
+
return tis;
|
|
68
|
+
}
|
|
69
|
+
|
|
22
70
|
/**
|
|
23
71
|
* A class that handles events for target objects
|
|
24
72
|
*
|
|
@@ -40,29 +88,17 @@ class LumEventRegistry
|
|
|
40
88
|
*
|
|
41
89
|
* @param {(object|module:@lumjs/core/events~GetTargets)} targets
|
|
42
90
|
*
|
|
43
|
-
* If this is a `function`, it will be called to dynamically get a
|
|
44
|
-
* list of target objects whenever an event is triggered.
|
|
45
|
-
*
|
|
46
91
|
* If this is an `object`, then any kind of `Iterable` may be used
|
|
47
92
|
* to represent multiple targets, while any non-Iterable object will
|
|
48
|
-
* be considered as single target.
|
|
93
|
+
* be considered as single target.
|
|
94
|
+
*
|
|
95
|
+
* If this is a `function`, it will be called to dynamically get a
|
|
96
|
+
* list of target objects whenever an event is triggered.
|
|
49
97
|
*
|
|
50
98
|
* @param {object} [opts] Options (saved to `options` property).
|
|
51
99
|
*
|
|
52
100
|
* @param {(RegExp|string)} [opts.delimiter=/\s+/] Used to split event names
|
|
53
101
|
*
|
|
54
|
-
* @param {boolean} [opts.multiMatch=false]
|
|
55
|
-
* If a registered listener has multiple event names, and a call
|
|
56
|
-
* to `emit()` also has multiple event names, the value of this
|
|
57
|
-
* option will determine if the same listener will have its
|
|
58
|
-
* handler function called more than once.
|
|
59
|
-
*
|
|
60
|
-
* If this is `true`, the handler will be called once for every
|
|
61
|
-
* combination of target and event name.
|
|
62
|
-
*
|
|
63
|
-
* If this is `false` (default), then only the first matching event
|
|
64
|
-
* name will be called for each target.
|
|
65
|
-
*
|
|
66
102
|
* @param {(object|boolean)} [opts.extend]
|
|
67
103
|
* This option determines the rules for adding wrapper methods and
|
|
68
104
|
* other extension properties to the target objects.
|
|
@@ -81,6 +117,18 @@ class LumEventRegistry
|
|
|
81
117
|
* @param {?string} [opts.extend.listen="on"] `listen()` proxy method
|
|
82
118
|
* @param {?string} [opts.extend.once=null] `once()` proxy method
|
|
83
119
|
* @param {?string} [opts.extend.remove=null] `remove()` proxy method
|
|
120
|
+
*
|
|
121
|
+
* @param {boolean} [opts.multiMatch=false]
|
|
122
|
+
* If a registered listener has multiple event names, and a call
|
|
123
|
+
* to `emit()` also has multiple event names, the value of this
|
|
124
|
+
* option will determine if the same listener will have its
|
|
125
|
+
* handler function called more than once.
|
|
126
|
+
*
|
|
127
|
+
* If this is `true`, the handler will be called once for every
|
|
128
|
+
* combination of target and event name.
|
|
129
|
+
*
|
|
130
|
+
* If this is `false` (default), then only the first matching event
|
|
131
|
+
* name will be called for each target.
|
|
84
132
|
*
|
|
85
133
|
* @param {boolean} [opts.overwrite=false] Overwrite existing properties?
|
|
86
134
|
*
|
|
@@ -106,55 +154,89 @@ class LumEventRegistry
|
|
|
106
154
|
let defExt; // Default opts.extend value
|
|
107
155
|
if (typeof targets === F)
|
|
108
156
|
{ // A dynamic getter method
|
|
157
|
+
this.funTargets = true;
|
|
109
158
|
this.getTargets = targets;
|
|
159
|
+
targets = this.getTargets();
|
|
110
160
|
defExt = false;
|
|
111
161
|
}
|
|
112
162
|
else
|
|
113
163
|
{ // Simple getter for a static value
|
|
114
|
-
if (!
|
|
164
|
+
if (!(targets instanceof Set))
|
|
115
165
|
{
|
|
116
|
-
|
|
166
|
+
if (!isIterable(targets))
|
|
167
|
+
targets = [targets];
|
|
168
|
+
targets = new Set(targets);
|
|
117
169
|
}
|
|
170
|
+
|
|
171
|
+
this.funTargets = false;
|
|
118
172
|
this.getTargets = () => targets;
|
|
119
173
|
defExt = true;
|
|
120
174
|
}
|
|
121
175
|
|
|
122
|
-
this.options = Object.assign({}, DEF_OPTIONS, opts);
|
|
176
|
+
this.options = Object.assign({extend: defExt}, DEF_OPTIONS, opts);
|
|
123
177
|
|
|
124
178
|
this.allListeners = new Set();
|
|
125
179
|
this.listenersFor = new Map();
|
|
126
180
|
|
|
127
|
-
|
|
128
|
-
|
|
181
|
+
this.extend(targets);
|
|
182
|
+
} // constructor()
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Add extension methods to target objects;
|
|
186
|
+
* used by `constructor` and `register()`,
|
|
187
|
+
* not meant to be called from outside code.
|
|
188
|
+
* @private
|
|
189
|
+
* @param {Iterable} targets - Targets to extend
|
|
190
|
+
* @returns {module:@lumjs/core/events.Registry} `this`
|
|
191
|
+
*/
|
|
192
|
+
extend(targets)
|
|
193
|
+
{
|
|
194
|
+
const opts = this.options;
|
|
195
|
+
const extOpts = opts.extend;
|
|
196
|
+
|
|
197
|
+
let intNames = null, extNames = null;
|
|
198
|
+
|
|
199
|
+
if (extOpts)
|
|
129
200
|
{
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
201
|
+
intNames = Object.keys(DEF_EXTENDS);
|
|
202
|
+
extNames = Object.assign({}, DEF_EXTENDS, extOpts);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
for (const target of targets)
|
|
206
|
+
{
|
|
207
|
+
const tps = {}, tpm = getMetadata(target, true);
|
|
208
|
+
tpm.r.set(this, tps);
|
|
133
209
|
|
|
134
|
-
|
|
210
|
+
if (extOpts)
|
|
135
211
|
{
|
|
136
|
-
|
|
212
|
+
for (const iname of intNames)
|
|
137
213
|
{
|
|
138
|
-
|
|
139
|
-
const value = iname === 'registry'
|
|
140
|
-
? this // The registry instance itself
|
|
141
|
-
: (...args) => this[iname](...args) // A proxy method
|
|
142
|
-
for (const target of targets)
|
|
214
|
+
if (typeof extNames[iname] === S && extNames[iname].trim() !== '')
|
|
143
215
|
{
|
|
144
|
-
|
|
216
|
+
const ename = extNames[iname];
|
|
217
|
+
const value = iname === 'registry'
|
|
218
|
+
? this // The registry instance itself
|
|
219
|
+
: (...args) => this[iname](...args) // A proxy method
|
|
220
|
+
for (const target of targets)
|
|
145
221
|
{
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
222
|
+
if (opts.overwrite || target[ename] === undefined)
|
|
223
|
+
{
|
|
224
|
+
def(target, ename, {value});
|
|
225
|
+
tps[ename] = iname;
|
|
226
|
+
tpm.p[ename] = this;
|
|
227
|
+
}
|
|
228
|
+
else
|
|
229
|
+
{
|
|
230
|
+
console.error("Won't overwrite existing property",
|
|
231
|
+
{target,iname,ename,registry: this});
|
|
232
|
+
}
|
|
152
233
|
}
|
|
153
234
|
}
|
|
154
235
|
}
|
|
155
236
|
}
|
|
156
237
|
}
|
|
157
|
-
|
|
238
|
+
return this;
|
|
239
|
+
}
|
|
158
240
|
|
|
159
241
|
/**
|
|
160
242
|
* Build a new Listener instance; used by `listen()` method.
|
|
@@ -491,6 +573,119 @@ class LumEventRegistry
|
|
|
491
573
|
return sti;
|
|
492
574
|
}
|
|
493
575
|
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* Register additional target objects
|
|
580
|
+
* @param {...object} addTargets - Target objects to register
|
|
581
|
+
* @returns {module:@lumjs/core/events.Registry} `this`
|
|
582
|
+
*/
|
|
583
|
+
register(...addTargets)
|
|
584
|
+
{
|
|
585
|
+
const allTargets = this.getTargets();
|
|
586
|
+
const tis = targetsAre(allTargets);
|
|
587
|
+
|
|
588
|
+
if (tis.handled)
|
|
589
|
+
{
|
|
590
|
+
for (const target of addTargets)
|
|
591
|
+
{
|
|
592
|
+
if (tis.set)
|
|
593
|
+
{
|
|
594
|
+
allTargets.add(target);
|
|
595
|
+
}
|
|
596
|
+
else if (tis.array)
|
|
597
|
+
{
|
|
598
|
+
if (allTargets.indexOf(target) === -1)
|
|
599
|
+
{
|
|
600
|
+
allTargets.push(target);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
else
|
|
606
|
+
{
|
|
607
|
+
if (!tis.handled)
|
|
608
|
+
{
|
|
609
|
+
console.warn("cannot add targets to collection",
|
|
610
|
+
{addTargets, allTargets, registry: this});
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
this.extend(addTargets);
|
|
615
|
+
return this;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Remove a target object from the registry.
|
|
620
|
+
*
|
|
621
|
+
* This will also remove any extension properties added to the
|
|
622
|
+
* target object by this registry instance.
|
|
623
|
+
*
|
|
624
|
+
* @param {...object} [delTargets] Targets to unregister
|
|
625
|
+
*
|
|
626
|
+
* If no targets are specified, this will unregister **ALL** targets
|
|
627
|
+
* from this registry!
|
|
628
|
+
*
|
|
629
|
+
* @returns {module:@lumjs/core/events.Registry} `this`
|
|
630
|
+
*/
|
|
631
|
+
unregister(...delTargets)
|
|
632
|
+
{
|
|
633
|
+
const allTargets = this.getTargets();
|
|
634
|
+
const tis = targetsAre(allTargets);
|
|
635
|
+
|
|
636
|
+
if (delTargets.length === 0)
|
|
637
|
+
{ // Unregister ALL targets.
|
|
638
|
+
delTargets = allTargets;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
if (!tis.handled)
|
|
642
|
+
{
|
|
643
|
+
console.warn("cannot remove targets from collection",
|
|
644
|
+
{delTargets, allTargets, registry: this});
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
for (const target of delTargets)
|
|
648
|
+
{
|
|
649
|
+
if (!isRegistered(target)) continue;
|
|
650
|
+
|
|
651
|
+
const tpm = target[RegSym];
|
|
652
|
+
const tp = tpm.r.get(this);
|
|
653
|
+
|
|
654
|
+
if (tis.set)
|
|
655
|
+
{
|
|
656
|
+
allTargets.delete(target);
|
|
657
|
+
}
|
|
658
|
+
else if (tis.array)
|
|
659
|
+
{
|
|
660
|
+
const tin = allTargets.indexOf(target);
|
|
661
|
+
if (tin !== -1)
|
|
662
|
+
{
|
|
663
|
+
allTargets.splice(tin, 1);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
if (isObj(tp))
|
|
668
|
+
{ // Remove any added extension properties
|
|
669
|
+
for (const ep in tp)
|
|
670
|
+
{
|
|
671
|
+
if (tpm.p[ep] === this)
|
|
672
|
+
{ // Remove it from the target.
|
|
673
|
+
delete target[ep];
|
|
674
|
+
delete tpm.p[ep];
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
tpm.r.delete(this);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
if (tpm.r.size === 0)
|
|
681
|
+
{ // No registries left, remove the metadata too
|
|
682
|
+
delete target[RegSym];
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
return this;
|
|
687
|
+
}
|
|
688
|
+
|
|
494
689
|
/**
|
|
495
690
|
* Get a Set of event names from various kinds of values
|
|
496
691
|
* @param {(string|Iterable)} names - Event names source
|
|
@@ -534,4 +729,9 @@ class LumEventRegistry
|
|
|
534
729
|
|
|
535
730
|
}
|
|
536
731
|
|
|
732
|
+
Object.assign(LumEventRegistry,
|
|
733
|
+
{
|
|
734
|
+
isRegistered, getMetadata, targetsAre,
|
|
735
|
+
});
|
|
736
|
+
|
|
537
737
|
module.exports = LumEventRegistry;
|
package/lib/index.js
CHANGED
package/lib/state.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {S,isObj} = require('./types')
|
|
4
|
+
const ctx = require('./context')
|
|
5
|
+
const stateSym = Symbol('@lumjs/core/state')
|
|
6
|
+
const stateData = {[stateSym]: false}
|
|
7
|
+
const stateKey = 'LUM_JS_STATE'
|
|
8
|
+
const stateOpts = {}
|
|
9
|
+
|
|
10
|
+
module.exports =
|
|
11
|
+
{
|
|
12
|
+
get(opts={})
|
|
13
|
+
{
|
|
14
|
+
if (opts.refresh || !stateData[stateSym])
|
|
15
|
+
{
|
|
16
|
+
let json;
|
|
17
|
+
if (ctx.isNode)
|
|
18
|
+
{
|
|
19
|
+
json = process.env[stateKey];
|
|
20
|
+
}
|
|
21
|
+
else if (ctx.isBrowser)
|
|
22
|
+
{
|
|
23
|
+
json = localStorage.getItem(stateKey);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (typeof json === S)
|
|
27
|
+
{
|
|
28
|
+
const revive = opts.jsonRevive ?? stateOpts.jsonRevive;
|
|
29
|
+
const storedData = JSON.parse(json, revive);
|
|
30
|
+
if (isObj(storedData))
|
|
31
|
+
{
|
|
32
|
+
Object.assign(stateData, storedData);
|
|
33
|
+
stateData[stateSym] = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return stateData;
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
save(opts={})
|
|
41
|
+
{
|
|
42
|
+
if (!stateData[stateSym]) return false;
|
|
43
|
+
|
|
44
|
+
const replace = opts.jsonReplace ?? stateOpts.jsonReplace;
|
|
45
|
+
const json = JSON.stringify(stateData, replace);
|
|
46
|
+
|
|
47
|
+
if (ctx.isBrowser)
|
|
48
|
+
{
|
|
49
|
+
localStorage.setItem(stateKey, json);
|
|
50
|
+
}
|
|
51
|
+
else if (ctx.isNode)
|
|
52
|
+
{
|
|
53
|
+
console.log("export ", stateKey, "=", json);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
opts: stateOpts,
|
|
58
|
+
|
|
59
|
+
[stateSym]: stateData,
|
|
60
|
+
$$: stateSym,
|
|
61
|
+
}
|
package/lum.build.js
CHANGED
|
@@ -1,40 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const D =
|
|
1
|
+
module.exports = function(rb)
|
|
4
2
|
{
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const dirs =
|
|
16
|
-
[
|
|
17
|
-
D.build,
|
|
18
|
-
D.api+D.changelogs,
|
|
19
|
-
]
|
|
20
|
-
|
|
21
|
-
const header = "<html><body>";
|
|
22
|
-
const footer = "</body></html>";
|
|
23
|
-
|
|
24
|
-
const files =
|
|
25
|
-
[
|
|
26
|
-
{
|
|
27
|
-
from: 'README.md',
|
|
28
|
-
to: D.build+'/README.md',
|
|
29
|
-
},
|
|
30
|
-
D.ad('docs/TODO.md'),
|
|
31
|
-
D.ad(D.changelogs+'/index.md'),
|
|
32
|
-
D.ad(D.changelogs+'/1.0-beta.md'),
|
|
33
|
-
D.ad(D.changelogs+'/1.x.md'),
|
|
34
|
-
D.ad(D.changelogs+'/2.x.md'),
|
|
35
|
-
]
|
|
36
|
-
|
|
37
|
-
module.exports =
|
|
38
|
-
{
|
|
39
|
-
dirs, files, header, footer,
|
|
3
|
+
rb.readme
|
|
4
|
+
.add('docs/TODO.md')
|
|
5
|
+
.chdir('docs/changelogs')
|
|
6
|
+
.add('index.md')
|
|
7
|
+
.add('1.0-beta.md')
|
|
8
|
+
.add('1.x.md')
|
|
9
|
+
.add('2.x.md')
|
|
10
|
+
//.set('debug', true)
|
|
40
11
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumjs/core",
|
|
3
|
-
"version": "1.31.
|
|
3
|
+
"version": "1.31.1",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"exports":
|
|
6
6
|
{
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"devDependencies":
|
|
34
34
|
{
|
|
35
|
-
"@lumjs/build": "^1.
|
|
35
|
+
"@lumjs/build": "^1.1.0",
|
|
36
36
|
"@lumjs/tests": "^2.0.0"
|
|
37
37
|
},
|
|
38
38
|
"scripts":
|