@lumjs/core 1.38.7 → 1.39.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/lib/obj/lock.js CHANGED
@@ -1,68 +1,2 @@
1
- // Import *most* required bits here.
2
- const {B, isObj, def} = require('../types');
3
-
4
- /**
5
- * Lock an object using Object.freeze()
6
- *
7
- * @param {object} obj - The object we want to lock.
8
- * @param {boolean} [clonable=true] Pass to `addClone()` first?
9
- * @param {object} [cloneOpts=null] Options for `addClone()`.
10
- * @param {boolean} [useSeal=false] Use Object.seal() instead of freeze.
11
- *
12
- * If cloneOpts is `null` then we will use the following:
13
- *
14
- * ```{mode: CLONE.DEF, addClone: true, addLock: true}```
15
- *
16
- * @return {object} The locked object.
17
- * @alias module:@lumjs/core/obj.lock
18
- */
19
- function lock(obj, clonable=true, cloneOpts=null, useSeal=false)
20
- {
21
- if (clonable)
22
- { // Add the clone method before freezing.
23
- if (!isObj(cloneOpts))
24
- {
25
- cloneOpts = {addClone: true, addLock: true};
26
- }
27
- addClone(obj, cloneOpts);
28
- }
29
-
30
- // Now freeze (or seal) the object.
31
- return (useSeal ? Object.seal(obj) : Object.freeze(obj));
32
- }
33
-
34
- exports.lock = lock;
35
-
36
- /**
37
- * Add a lock() method to an object.
38
- *
39
- * Adds a wrapper version of `lock()` to the object as a method.
40
- *
41
- * @param {object} obj - The object we're adding `lock()` to.
42
- * @param {object} [opts] - Options and defaults.
43
- * In addition to options specific to this function, any options
44
- * supported by `addClone()` may be specified here as well.
45
- * @param {object} [opts.lockDesc] Descriptor rules the `lock()` method.
46
- * @param {boolean} [opts.addClone=true] Default for `clonable` parameter.
47
- * @param {object} [opts.useSeal=false] Default for `useSeal` parameter.
48
- * @returns {object} `obj`
49
- * @alias module:@lumjs/core/obj.addLock
50
- */
51
- function addLock(obj, opts)
52
- {
53
- const defDesc = opts.lockDesc ?? {};
54
- defDesc.value = function(obj, cloneable, cloneOpts, useSeal)
55
- {
56
- if (typeof cloneable !== B) clonable = opts.addClone ?? true;
57
- if (!isObj(cloneOpts)) cloneOpts = opts; // Yup, just a raw copy.
58
- if (typeof useSeal !== B) useSeal = opts.useSeal ?? false;
59
- return lock(obj, cloneable, cloneOpts, useSeal);
60
- }
61
- return def(obj, 'lock', defDesc);
62
- }
63
-
64
- exports.addLock = addLock;
65
-
66
- // Importing addLock at the end, just because.
67
- const {addClone} = require('./clone');
68
-
1
+ // Moved to `cp` package
2
+ module.exports = require('@lumjs/cp/util');
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- const {F,S,isObj,needObj} = require('../types');
3
+ const {isObj} = require('../types/basics');
4
4
 
5
5
  const CLONE = 'clone';
6
6
  const clone = obj => Object.assign({}, obj);
@@ -48,19 +48,17 @@ const clone = obj => Object.assign({}, obj);
48
48
  * @alias module:@lumjs/core/obj.unlocked
49
49
  */
50
50
  function unlocked(obj, opts={})
51
- {
52
- needObj(obj, true, "invalid obj value");
53
-
51
+ {
54
52
  if (Object.isExtensible(obj))
55
53
  { // We're done here.
56
54
  return obj;
57
55
  }
58
56
 
59
- if (typeof opts === F)
57
+ if (typeof opts === 'function')
60
58
  {
61
59
  opts = {fn: opts}
62
60
  }
63
- else if (typeof opts === S)
61
+ else if (typeof opts === 'string')
64
62
  {
65
63
  opts = {method: opts}
66
64
  }
@@ -70,11 +68,11 @@ function unlocked(obj, opts={})
70
68
  throw new TypeError("invalid opts value");
71
69
  }
72
70
 
73
- const fn = (typeof opts.fn === F) ? opts.fn : clone;
74
- const meth = (typeof opts.method === S) ? opts.method.trim() : CLONE;
75
- const args = (Array.isArray(opts.args)) ? opts.args : [opts];
71
+ const fn = (typeof opts.fn === 'function') ? opts.fn : clone;
72
+ const meth = (typeof opts.method === 'string') ? opts.method.trim() : CLONE;
73
+ const args = (Array.isArray(opts.args)) ? opts.args : [opts];
76
74
 
77
- if (meth && typeof obj[meth] === F)
75
+ if (meth && typeof obj[meth] === 'function')
78
76
  { // Use a clone method
79
77
  return obj[meth](...args);
80
78
  }
package/lib/proxy.js ADDED
@@ -0,0 +1,417 @@
1
+ /**
2
+ * Proxy related helpers.
3
+ * @module @lumjs/core/proxy
4
+ */
5
+
6
+ const { isObj, isProperty } = require('./types/basics.js');
7
+ const { getOwnKeys, isEmptyObject } = require('./obj/keys.js');
8
+
9
+ const cp = Object.assign;
10
+ const hasItems = obj => !isEmptyObject(obj);
11
+
12
+ /**
13
+ * A class that helps build simple Proxy wrappers.
14
+ */
15
+ class ProxyManager {
16
+ /**
17
+ * Create a ProxyManager instance.
18
+ *
19
+ * @param {(object|function)} target - Target to be wrapped by Proxy.
20
+ *
21
+ * @param {object} [opts] Options; saved as `this.opts`.
22
+ *
23
+ * @param {object} [opts.handler] Additional Proxy handler hooks/traps.
24
+ *
25
+ * As ProxyManager currently only supports `get` and `set` hooks, you can
26
+ * use this option to provide further handler functions.
27
+ *
28
+ * Obviously you shouldn't specify `get` or `set` in this, as those hooks
29
+ * are built automatically during handler registration.
30
+ *
31
+ * In the future more directly-supported hooks may be added.
32
+ *
33
+ * @param {object} [opts.handlers] An alias for `opts.handler`.
34
+ *
35
+ * If for whatever reason both this and `opts.handler` are specified,
36
+ * they will both be compsed into `this.handler`. As this is the alias,
37
+ * `opts.handler` will take precedence in the case of name conflicts.
38
+ *
39
+ * @param {(string|symbol)} [opts.selfKey] Proxy property for the manager.
40
+ *
41
+ * If this option is specified, then it will be used as the name of a
42
+ * property that when accessed, returns the ProxyManager instance itself.
43
+ *
44
+ */
45
+ constructor(target, opts = {}) {
46
+ this.opts = opts;
47
+ this.target = target;
48
+ this.bound = {};
49
+ this.props = {};
50
+ this.getters = {};
51
+ this.setters = {};
52
+ this.handler = cp({}, opts.handlers, opts.handler);
53
+ }
54
+
55
+ /**
56
+ * Add various types of proxied properties using descriptor-like rules.
57
+ *
58
+ * This is a frontend method that uses descriptor objects similar to the
59
+ * ones used by `Object.defineProperties()`, but with a few extensions.
60
+ *
61
+ * @param {Object.<(string|symbol), module:@lumjs/core/proxy~Desc>} descs
62
+ * Extended property descriptors for every property you want to add.
63
+ *
64
+ * If the *value* of any property in the `descs` is **NOT** an object,
65
+ * it will be treated the same as an object with a `value` property.
66
+ * See the `test/proxy-manager.js` for an example.
67
+ *
68
+ * @returns {this}
69
+ */
70
+ add(descs) {
71
+ if (!isObj(descs)) {
72
+ console.error({ descs, pm: this });
73
+ throw new TypeError('descs must be an object');
74
+ }
75
+
76
+ let keys = getOwnKeys(descs);
77
+ let props = {};
78
+
79
+ for (let key of keys) {
80
+ let desc = descs[key];
81
+
82
+ if (!isObj(desc)) {
83
+ props[key] = desc;
84
+ }
85
+ else if (typeof desc.bind === 'function') {
86
+ let meth = { [key]: desc.bind };
87
+ this.bind(meth, desc);
88
+ }
89
+ else if (
90
+ typeof desc.get === 'function'
91
+ || typeof desc.set === 'function'
92
+ ) {
93
+ this.addAccessor(key, desc.get, desc.set);
94
+ }
95
+ else if (desc.value !== undefined) {
96
+ props[key] = desc.value;
97
+ }
98
+ else {
99
+ console.error('unsupported desc', { key, desc, descs, pm: this });
100
+ }
101
+ }
102
+
103
+ if (hasItems(props)) {
104
+ this.assign(props);
105
+ }
106
+
107
+ return this;
108
+ }
109
+
110
+ /**
111
+ * Add accessor properties (getter and/or setter functions).
112
+ * @param {(string|symbol)} key - Property name to add.
113
+ * @param {?module:@lumjs/core/proxy~GetterFun} getter
114
+ *
115
+ * Use `null` for no getter (for instance if you have a static
116
+ * value you're going to set with addValues() but still want a
117
+ * setter for whatever reason).
118
+ *
119
+ * @param {?module:@lumjs/core/proxy~SetterFun} [setter]
120
+ *
121
+ * Use `null` (or simply omit entirely) if you don't want a setter.
122
+ *
123
+ * @returns {this}
124
+ */
125
+ addAccessor(key, getter, setter) {
126
+ if (!isProperty(key)) {
127
+ console.error('addAccessor', { key, getter, setter });
128
+ throw new TypeError('Invalid property key');
129
+ }
130
+
131
+ if (typeof getter === 'function') {
132
+ this.getters[key] = getter;
133
+ }
134
+
135
+ if (typeof setter === 'function') {
136
+ this.setters[key] = setter;
137
+ }
138
+
139
+ return this;
140
+ }
141
+
142
+ /**
143
+ * Assign proxied property values.
144
+ *
145
+ * @param {object} props - Properties to add.
146
+ *
147
+ * Property values may use *any* JS type except `undefined`.
148
+ * The values will be used as-is with no descriptor parsing,
149
+ * function binding, accessor assignments, or anything else like that.
150
+ *
151
+ * Both string and symbol property keys are supported.
152
+ *
153
+ * @returns {this}
154
+ */
155
+ assign(props) {
156
+ cp(this.props, props);
157
+ return this;
158
+ }
159
+
160
+ /**
161
+ * Add bound wrapper methods.
162
+ *
163
+ * This is specifically for creating *bound* methods using `function.bind()`;
164
+ * Use `add()` or `addProps()` for regular (non-bound) methods.
165
+ *
166
+ * @param {object} methods - Methods to add.
167
+ *
168
+ * All of the functions in this object will be used to create bound methods.
169
+ *
170
+ * The default binding rules will use the ProxyManager instance as `this`,
171
+ * and pass `this.target` as the first argument. See the `opts` for details.
172
+ *
173
+ * @param {object} [opts] Options for creating bound methods.
174
+ * @param {number} [opts.passFirst] Bind the first argument?
175
+ *
176
+ * If this is `0`, it means don't use any bound argument.
177
+ *
178
+ * Any other non-zero value must be one of the `ProxyManager.BIND` values:
179
+ * - `BIND.M` → Use the ProxyManager instance.
180
+ * - `BIND.R` → Use the Proxy receiver object.
181
+ * - `BIND.T` → Use the underlying target object.
182
+ *
183
+ * Default: `BIND.R`
184
+ *
185
+ * @param {number} [opts.useThis] What to bind as `this`.
186
+ *
187
+ * Must be one of the `ProxyManager.BIND` values.
188
+ *
189
+ * Default: `BIND.M`
190
+ *
191
+ * @returns {this}
192
+ */
193
+ bind(methods, opts = {}) {
194
+ let keys = getOwnKeys(methods);
195
+
196
+ for (let key of keys) {
197
+ let fn = methods[key];
198
+ if (typeof fn === 'function') {
199
+ this.bound[key] = {fn, opts};
200
+ }
201
+ }
202
+
203
+ return this;
204
+ }
205
+
206
+ /**
207
+ * Build the Proxy.
208
+ *
209
+ * @param {object} [opts] Options.
210
+ * @param {?boolean} [opts.cache=null] Cache the Proxy?
211
+ *
212
+ * If this is `true`, then the Proxy instance will be saved as `this.proxy`,
213
+ * and future calls to this method will return the cached copy by default.
214
+ *
215
+ * If this is `false` then the Proxy will not be cached.
216
+ *
217
+ * If this is not specified (or `null`) then its default will be `true` if
218
+ * there is not already a cached proxy, or `false` if there is.
219
+ *
220
+ * @param {boolean} [opts.new=false] Always return a new Proxy instance?
221
+ *
222
+ * If this is `true` then a new Proxy instance will be created and returned,
223
+ * regardless as to if one had been cached previously. Default: `false`.
224
+ *
225
+ * @returns {Proxy}
226
+ */
227
+ build(opts = {}) {
228
+ let wantNew = opts.new ?? false;
229
+ let cacheIt = opts.cache ?? !this.proxy;
230
+
231
+ if (wantNew || !this.proxy) {
232
+ this.register();
233
+ let proxy = new Proxy(this.target, this.handler);
234
+ this.setup(proxy);
235
+ if (cacheIt) this.proxy = proxy;
236
+ return proxy;
237
+ }
238
+
239
+ return this.proxy;
240
+ }
241
+
242
+ /**
243
+ * Register our internal handler hooks (aka traps).
244
+ *
245
+ * This will create a `get` hook if *ANY* of the following are true:
246
+ * - A valid `this.opts.selfKey` value was specified.
247
+ * - The addAccessor() method registered a _getter_ function.
248
+ * - The addMethod() and/or addValues() methods were called.
249
+ * The order listed above is also the order any of the virtual
250
+ * properties will be checked for in the generated hook.
251
+ *
252
+ * This will create a `set` hook if:
253
+ * - The addAccessor() method registered a _setter_ function.
254
+ *
255
+ * The hooks created by this will **overwrite** any `get` or `set` hooks
256
+ * that may already be in the `this.handler` object.
257
+ *
258
+ * This is called by build() automatically when it creates a new Proxy.
259
+ * @protected
260
+ * @returns {this}
261
+ */
262
+ register() {
263
+ const pm = this;
264
+ const selfKey = this.opts.selfKey;
265
+ const hasSelf = isProperty(selfKey);
266
+
267
+ if (hasSelf || hasItems(pm.props) || hasItems(pm.getters)) {
268
+ pm.handler.get = function (target, prop, receiver) {
269
+ let pi = {manager: pm, op: 'get', prop, receiver, target}
270
+
271
+ if (hasSelf && prop === selfKey) {
272
+ return pm;
273
+ }
274
+
275
+ if (typeof pm.getters[prop] === 'function') {
276
+ return pm.getters[prop].call(receiver, pi);
277
+ }
278
+
279
+ if (pm.props[prop] !== undefined) {
280
+ return pm.props[prop];
281
+ }
282
+
283
+ return Reflect.get(...arguments);
284
+ }
285
+ }
286
+
287
+ if (hasItems(pm.setters)) {
288
+ pm.handler.set = function (target, prop, val, receiver) {
289
+ let pi = {manager: pm, op: 'set', prop, receiver, target}
290
+
291
+ if (typeof pm.setters[prop] === 'function') {
292
+ return (pm.setters[prop].call(receiver, val, pi) ?? true);
293
+ }
294
+
295
+ return Reflect.set(...arguments);
296
+ }
297
+ }
298
+
299
+ return this;
300
+ }
301
+
302
+ /**
303
+ * Setup that is called after the Proxy instance has been registered.
304
+ *
305
+ * This is currently used to (re-)generate any bound methods.
306
+ * It may have further uses in the future.
307
+ *
308
+ * It is called automatically by the build() method.
309
+ *
310
+ * @protected
311
+ * @param {(object|function)} proxy - The Proxy object.
312
+ * @returns {this}
313
+ */
314
+ setup(proxy) {
315
+ let ps = this.props;
316
+ let keys = getOwnKeys(this.bound);
317
+
318
+ let withThis = (opts, opt, defval) => {
319
+ let tt = opts[opt] ?? defval;
320
+ if (tt === 0) return null;
321
+ if (tt === BIND.M) return this;
322
+ if (tt === BIND.R) return proxy ?? this.proxy ?? this.target;
323
+ if (tt === BIND.T) return this.target;
324
+
325
+ console.debug('bind:withThis', {opt, defval, methods, opts});
326
+ throw new RangeError(`Invalid '${opt}' option`);
327
+ }
328
+
329
+ for (let key of keys) {
330
+ let {fn, opts} = this.bound[key];
331
+
332
+ let ctx = withThis(opts, 'useThis', BIND.M);
333
+ let args = [ctx];
334
+
335
+ ctx = withThis(opts, 'passFirst', BIND.R);
336
+ if (ctx) {
337
+ args.push(ctx);
338
+ }
339
+
340
+ ps[key] = fn.bind(...args);
341
+ }
342
+ }
343
+
344
+ }
345
+
346
+ const BIND = Object.freeze({
347
+ M: 1,
348
+ P: 2,
349
+ R: 2,
350
+ T: 3,
351
+ });
352
+
353
+ Object.defineProperty(ProxyManager, 'BIND', { value: BIND });
354
+
355
+ module.exports = { ProxyManager }
356
+
357
+ /**
358
+ * Context info for _getter_ and _setter_ functions.
359
+ * @typedef {object} module:@lumjs/core/proxy~AccessorCtx
360
+ * @prop {ProxyManager} manager - The ProxyManager instance.
361
+ * @prop {('get'|'set')} op - The accessor operation being handled.
362
+ * @prop {(string|symbol)} prop - The property name/key.
363
+ * @prop {(object|function)} receiver - The Proxy receiver object.
364
+ * @prop {(object|function)} target - The underlying target object.
365
+ */
366
+
367
+ /**
368
+ * A _getter_ function for an accessor property.
369
+ * @callback module:@lumjs/core/proxy~GetterFun
370
+ * @param {module:@lumjs/core/proxy~AccessorCtx} ctx
371
+ * @returns {*} The accessor property value.
372
+ */
373
+
374
+ /**
375
+ * A _setter_ function for an accessor property.
376
+ * @callback module:@lumjs/core/proxy~SetterFun
377
+ * @param {*} value - The value being assigned to the property.
378
+ * @param {module:@lumjs/core/proxy~AccessorCtx} ctx
379
+ * @returns {(boolean|null|undefined)}
380
+ *
381
+ * If the setter function returns `true`, it indicates success of the
382
+ * property assigment and the JS runtime will continue normally.
383
+ *
384
+ * If the setter function explicitly returns `false` then it is up to
385
+ * the JS runtime how to handle failed assignments, but many will throw
386
+ * a TypeError, so keep that in mind when writing your setter functions.
387
+ *
388
+ * If the setter function does not return a value, or explicitly returns
389
+ * `null` or `undefined`, it will be handled the same as `true`.
390
+ *
391
+ * I think in 99% of cases not returning anything is the best.
392
+ */
393
+
394
+ /**
395
+ * Extended descriptor rule.
396
+ * @typedef {object} module:@lumjs/core/proxy~Desc
397
+ * @prop {(function|undefined)} bind - A bound method handler.
398
+ *
399
+ * If this property is set, then the rest of the descriptor
400
+ * properties may be used as options for the `bind()` method.
401
+ *
402
+ * @prop {(function|undefined)} get - A getter function.
403
+ *
404
+ * If this property is set, then it will be passed to `addAccessor()`,
405
+ * along with the `set` property.
406
+ *
407
+ * @prop {(function|undefined)} set - A setter function.
408
+ *
409
+ * If this property is set, then it will be passed to `addAccessor()`,
410
+ * along with the `get` property.
411
+ *
412
+ * @prop {*} value - A direct property value.
413
+ *
414
+ * All of the direct property values will be used to build an object
415
+ * that will be passed to `addProps()`.
416
+ *
417
+ */
package/lib/state.js CHANGED
@@ -6,7 +6,7 @@ const cp = require('./obj/cp');
6
6
  const env = require('./env');
7
7
  const stateSym = Symbol('@lumjs/core/state')
8
8
  const stateData = {[stateSym]: false}
9
- const stateKey = 'LUM_JS_STATE'
9
+ const stateKey = 'LUM_JS_STATE';
10
10
  const stateOpts = env.getOpts(); // Some default opts.
11
11
 
12
12
  function getOpts(localOpts)
@@ -43,6 +43,7 @@ exports = module.exports =
43
43
  */
44
44
  load(opts)
45
45
  {
46
+ console.warn('@lumjs/core.state is deprecated, use core.env instead');
46
47
  opts = getOpts(opts);
47
48
 
48
49
  if (opts.refresh || !stateData[stateSym])
@@ -80,16 +81,18 @@ exports = module.exports =
80
81
  * It will be passed the result object from env.set() and can
81
82
  * do with it whatever is required.
82
83
  *
83
- * @returns {module:@lumjs/core/env~SetResult}
84
+ * @returns {?module:@lumjs/core/env~SetResult}
85
+ *
86
+ * Will be null if no state data has been loaded yet.
84
87
  */
85
88
  save(opts)
86
89
  {
87
- if (!stateData[stateSym]) return false;
90
+ if (!stateData[stateSym]) return null;
88
91
  opts = getOpts(opts);
89
92
  let res = env.set(stateKey, stateData);
90
93
  if (typeof opts.onSave === 'function')
91
94
  {
92
- opts.onSave.call(opts, res);
95
+ opts.onSave(res, opts);
93
96
  }
94
97
  return res;
95
98
  },
@@ -107,6 +110,34 @@ exports = module.exports =
107
110
  return ns.getObjectPath(data, path, opts);
108
111
  },
109
112
 
113
+ /**
114
+ * Look for an env key, fallback on a state path.
115
+ *
116
+ * This is meant as a way to transition from using the older
117
+ * state module to the newer env module.
118
+ *
119
+ * @param {string} key - Environment key to look for first.
120
+ * @param {(string|string[])} path - State path to fallback on.
121
+ * @param {object} [opts] Options for both `env.get()` and `state.get()`.
122
+ *
123
+ * You may specify a `default` option for `state.get()` here. It won't be
124
+ * used by `env.get()` as we define an explicit default handler for it.
125
+ *
126
+ * @returns {mixed}
127
+ */
128
+ eors(key, path, opts)
129
+ {
130
+ let so = getOpts(opts);
131
+ let eo = Object.assign({}, opts,
132
+ {
133
+ default()
134
+ {
135
+ return exports.get(path, so);
136
+ },
137
+ });
138
+ return env.get(key, eo);
139
+ },
140
+
110
141
  /**
111
142
  * Set a (nested) property value in the state data
112
143
  * @param {(string|string[])} path - Namespace path to set
package/lib/types/js.js CHANGED
@@ -10,6 +10,9 @@
10
10
  * See {@link module:@lumjs/core/types.TYPES} for a much more complete
11
11
  * list that includes special types and compound pseudo-types, etc.
12
12
  *
13
+ * NOTE: This module and these constants will be deprecated as of v2.0,
14
+ * and will be removed entirely in a future v3.0 release.
15
+ *
13
16
  * @prop {string} O - object
14
17
  * @prop {string} F - function
15
18
  * @prop {string} S - string
package/lib/types/root.js CHANGED
@@ -9,6 +9,7 @@ function no_root()
9
9
 
10
10
  /**
11
11
  * The global root object. Usually `globalThis` these days.
12
+ * @deprecated Just use globalThis now.
12
13
  * @alias module:@lumjs/core/types.root
13
14
  */
14
15
  const root
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumjs/core",
3
- "version": "1.38.7",
3
+ "version": "1.39.0",
4
4
  "main": "lib/index.js",
5
5
  "exports":
6
6
  {
@@ -20,11 +20,13 @@
20
20
  "./node/modules": "./lib/node/modules.js",
21
21
  "./obj": "./lib/obj/index.js",
22
22
  "./obj/apply": "./lib/obj/apply.js",
23
+ "./obj/basics": "./lib/obj/basics.js",
23
24
  "./obj/cp": "./lib/obj/cp.js",
24
25
  "./obj/df": "./lib/obj/df.js",
25
26
  "./observable": "./lib/observable.js",
26
27
  "./opt": "./lib/opt/index.js",
27
28
  "./opt/args": "./lib/opt/args.js",
29
+ "./proxy": "./lib/proxy.js",
28
30
  "./state": "./lib/state.js",
29
31
  "./strings": "./lib/strings.js",
30
32
  "./traits": "./lib/traits.js",
@@ -35,9 +37,10 @@
35
37
  },
36
38
  "dependencies":
37
39
  {
38
- "@lumjs/cp": "^1.0.0",
40
+ "@lumjs/cp": "^1.1.0",
39
41
  "@lumjs/describe": "^1.0.0",
40
42
  "@lumjs/events-observable": "^1.0.1",
43
+ "@lumjs/lists": "^1.0.0",
41
44
  "@lumjs/opts": "^1.0.0",
42
45
  "@lumjs/traits": "^1.0.0",
43
46
  "semver": "^7.7.3"