@lumjs/core 1.18.0 → 1.20.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.
@@ -1,5 +1,5 @@
1
- const def = require('./def');
2
- const {F} = require('./js');
1
+ const def = require('./types/def');
2
+ const {F} = require('./types/js');
3
3
 
4
4
  /**
5
5
  * A super simple singleton wrapper around the Javascript console.
@@ -7,7 +7,7 @@ const {F} = require('./js');
7
7
  * By default includes `info`, `log`, `warn`, and `error` methods.
8
8
  * It may be expanded further using the `addMethod` method.
9
9
  *
10
- * @exports module:@lumjs/core/types/console
10
+ * @exports module:@lumjs/core/console
11
11
  */
12
12
  const LC =
13
13
  {
@@ -80,7 +80,7 @@ const LC =
80
80
 
81
81
  /**
82
82
  * A reference to the real console object.
83
- * @alias module:@lumjs/core/types/console.real
83
+ * @alias module:@lumjs/core/console.real
84
84
  */
85
85
  const RC = globalThis.console;
86
86
  def(LC, 'real', RC);
@@ -97,14 +97,14 @@ const HANDLER_OPTIONS =
97
97
  /**
98
98
  * Add a wrapper method to the console wrapper object.
99
99
  * @param {string} method - The console method to wrap.
100
- * @alias module:@lumjs/core/types/console.addMethod
100
+ * @alias module:@lumjs/core/console.addMethod
101
101
  */
102
102
  function addMethod(method)
103
103
  {
104
104
  def(LC, method, function(...args)
105
105
  {
106
106
  if (typeof LC.trigger === F)
107
- { // Support for core.observable(core.types.console);
107
+ { // Support for core.observable(core.console);
108
108
  LC.trigger(method, ...args);
109
109
  }
110
110
 
package/lib/index.js CHANGED
@@ -79,6 +79,13 @@ lazy(exports, 'flags', () => require('./flags'));
79
79
  */
80
80
  lazy(exports, 'obj', () => require('./obj'));
81
81
 
82
+ /**
83
+ * A wrapper around the Javascript console.
84
+ * @name module:@lumjs/core.console
85
+ * @type {module:@lumjs/core/console}
86
+ */
87
+ lazy(exports, 'console', () => require('./console'));
88
+
82
89
  /**
83
90
  * Functions for getting values and properties with fallback defaults «Lazy»
84
91
  * @name module:@lumjs/core.opt
@@ -6,92 +6,92 @@ const {O, F, S, SY} = require('./js');
6
6
  * @returns {boolean}
7
7
  * @alias module:@lumjs/core/types.isObj
8
8
  */
9
- function isObj(v) { return (typeof v === O && v !== null); }
10
-
11
- /**
12
- * See if a value is *complex* (i.e. either `object` or `function`).
13
- * Like `isObj()`, `null` does not count as an `object`.
14
- * @param {*} v - The value we're testing.
15
- * @returns {boolean}
16
- * @alias module:@lumjs/core/types.isComplex
17
- */
18
- function isComplex(v) { return (typeof v === F || isObj(v)); }
19
-
20
- /**
21
- * See if a value is *nil* (i.e. either `null` or `undefined`).
22
- * @param {*} v - The value we're testing.
23
- * @returns {boolean}
24
- * @alias module:@lumjs/core/types.isNil
25
- */
26
- function isNil(v) { return (v === undefined || v === null); }
27
-
28
- /**
29
- * See if a value is not *nil* (i.e. neither `null` nor `undefined`).
30
- * @param {*} v - The value we're testing.
31
- * @returns {boolean}
32
- * @alias module:@lumjs/core/types.notNil
33
- */
34
- function notNil(v) { return (v !== undefined && v !== null); }
35
-
36
- /**
37
- * See if a value is a scalar.
38
- * For the purposes of this, a scalar is any value which
39
- * is neither *nil* nor *complex*.
40
- * @param {*} v - The value we're testing.
41
- * @returns {boolean}
42
- * @alias module:@lumjs/core/types.isScalar
43
- */
44
- function isScalar(v) { return (notNil(v) && !isComplex(v)); }
45
-
46
- /**
47
- * See if a value is an `Array` object.
48
- * This is literally just a copy of `Array.isArray`.
49
- * @function
50
- * @param {*} v - The value we're testing.
51
- * @returns {boolean}
52
- * @alias module:@lumjs/core/types.isArray
53
- */
54
- const isArray = Array.isArray;
55
-
56
- /**
57
- * See if a value is a `TypedArray` object.
58
- * @param {*} v - The value we're testing.
59
- * @returns {boolean}
60
- * @alias module:@lumjs/core/types.isTypedArray
61
- */
62
- function isTypedArray(v)
63
- {
64
- return (ArrayBuffer.isView(v) && !(v instanceof DataView));
65
- }
66
-
67
- /**
68
- * See if a value is a non-empty Array.
69
- * @param {*} v - The value we're testing.
70
- * @param {boolean} [typed=false] If `true` we want a `TypedArray`.
71
- * If `false` (default) we want a regular `Array`.
72
- * @returns {boolean}
73
- * @alias module:@lumjs/core/types.nonEmptyArray
74
- */
75
- function nonEmptyArray(v, typed=false)
76
- {
77
- if (typed)
78
- return (isTypedArray(v) && v.length > 0);
79
- else
80
- return (isArray(v) && v.length > 0);
81
- }
82
-
83
- /**
84
- * See if a value is an `arguments` object.
85
- * @param {*} v - The value we're testing.
86
- * @returns {boolean}
87
- * @alias module:@lumjs/core/types.isArguments
88
- */
89
- function isArguments(v)
90
- {
91
- return Object.prototype.toString.call(v) === '[object Arguments]';
92
- }
93
-
94
- /**
9
+ function isObj(v) { return (typeof v === O && v !== null); }
10
+
11
+ /**
12
+ * See if a value is *complex* (i.e. either `object` or `function`).
13
+ * Like `isObj()`, `null` does not count as an `object`.
14
+ * @param {*} v - The value we're testing.
15
+ * @returns {boolean}
16
+ * @alias module:@lumjs/core/types.isComplex
17
+ */
18
+ function isComplex(v) { return (typeof v === F || isObj(v)); }
19
+
20
+ /**
21
+ * See if a value is *nil* (i.e. either `null` or `undefined`).
22
+ * @param {*} v - The value we're testing.
23
+ * @returns {boolean}
24
+ * @alias module:@lumjs/core/types.isNil
25
+ */
26
+ function isNil(v) { return (v === undefined || v === null); }
27
+
28
+ /**
29
+ * See if a value is not *nil* (i.e. neither `null` nor `undefined`).
30
+ * @param {*} v - The value we're testing.
31
+ * @returns {boolean}
32
+ * @alias module:@lumjs/core/types.notNil
33
+ */
34
+ function notNil(v) { return (v !== undefined && v !== null); }
35
+
36
+ /**
37
+ * See if a value is a scalar.
38
+ * For the purposes of this, a scalar is any value which
39
+ * is neither *nil* nor *complex*.
40
+ * @param {*} v - The value we're testing.
41
+ * @returns {boolean}
42
+ * @alias module:@lumjs/core/types.isScalar
43
+ */
44
+ function isScalar(v) { return (notNil(v) && !isComplex(v)); }
45
+
46
+ /**
47
+ * See if a value is an `Array` object.
48
+ * This is literally just a copy of `Array.isArray`.
49
+ * @function
50
+ * @param {*} v - The value we're testing.
51
+ * @returns {boolean}
52
+ * @alias module:@lumjs/core/types.isArray
53
+ */
54
+ const isArray = Array.isArray;
55
+
56
+ /**
57
+ * See if a value is a `TypedArray` object.
58
+ * @param {*} v - The value we're testing.
59
+ * @returns {boolean}
60
+ * @alias module:@lumjs/core/types.isTypedArray
61
+ */
62
+ function isTypedArray(v)
63
+ {
64
+ return (ArrayBuffer.isView(v) && !(v instanceof DataView));
65
+ }
66
+
67
+ /**
68
+ * See if a value is a non-empty Array.
69
+ * @param {*} v - The value we're testing.
70
+ * @param {boolean} [typed=false] If `true` we want a `TypedArray`.
71
+ * If `false` (default) we want a regular `Array`.
72
+ * @returns {boolean}
73
+ * @alias module:@lumjs/core/types.nonEmptyArray
74
+ */
75
+ function nonEmptyArray(v, typed=false)
76
+ {
77
+ if (typed)
78
+ return (isTypedArray(v) && v.length > 0);
79
+ else
80
+ return (isArray(v) && v.length > 0);
81
+ }
82
+
83
+ /**
84
+ * See if a value is an `arguments` object.
85
+ * @param {*} v - The value we're testing.
86
+ * @returns {boolean}
87
+ * @alias module:@lumjs/core/types.isArguments
88
+ */
89
+ function isArguments(v)
90
+ {
91
+ return Object.prototype.toString.call(v) === '[object Arguments]';
92
+ }
93
+
94
+ /**
95
95
  * See if a value is a Property name.
96
96
  * @param {*} v - The value we're testing.
97
97
  * @returns {boolean}
@@ -122,28 +122,28 @@ function isProperty(v)
122
122
  * @returns {boolean} - Is the object a valid descriptor?
123
123
  * @alias module:@lumjs/core/types.doesDescriptor
124
124
  */
125
- function doesDescriptor(obj)
126
- {
127
- if (isObj(obj))
128
- {
129
- const hasValue = (obj.value !== undefined);
130
- const hasGetter = (typeof obj.get === F);
131
- const hasSetter = (typeof obj.set === F);
132
- const hasWritable = (obj.writable !== undefined);
133
-
134
- if (hasValue && !hasGetter && !hasSetter)
135
- { // We have a value, and no getter or setter.
136
- return true;
137
- }
138
- else if ((hasGetter || hasSetter) && !hasValue && !hasWritable)
139
- { // We have a getter or setter, and no value or writable properties.
140
- return true;
141
- }
142
- }
143
-
144
- // Nothing matched, not a valid descriptor rule.
145
- return false;
146
- }
125
+ function doesDescriptor(obj)
126
+ {
127
+ if (isObj(obj))
128
+ {
129
+ const hasValue = (obj.value !== undefined);
130
+ const hasGetter = (typeof obj.get === F);
131
+ const hasSetter = (typeof obj.set === F);
132
+ const hasWritable = (obj.writable !== undefined);
133
+
134
+ if (hasValue && !hasGetter && !hasSetter)
135
+ { // We have a value, and no getter or setter.
136
+ return true;
137
+ }
138
+ else if ((hasGetter || hasSetter) && !hasValue && !hasWritable)
139
+ { // We have a getter or setter, and no value or writable properties.
140
+ return true;
141
+ }
142
+ }
143
+
144
+ // Nothing matched, not a valid descriptor rule.
145
+ return false;
146
+ }
147
147
 
148
148
  /**
149
149
  * See if an object can be used as a valid *descriptor template*.
@@ -195,6 +195,6 @@ function doesDescriptorTemplate(obj, accessor=false, strict=true)
195
195
  // Now export those.
196
196
  module.exports =
197
197
  {
198
- isObj, isComplex, isNil, notNil, isScalar, isArray, isTypedArray,
199
- nonEmptyArray, isArguments, isProperty, doesDescriptor, doesDescriptorTemplate,
198
+ isObj, isComplex, isNil, notNil, isScalar, isArray, isTypedArray,
199
+ nonEmptyArray, isArguments, isProperty, doesDescriptor, doesDescriptorTemplate,
200
200
  }
@@ -31,7 +31,7 @@ const
31
31
  const {root, unbound} = require('./root');
32
32
 
33
33
  // Advanced type checks.
34
- const {isInstance, isType, isa} = require('./isa');
34
+ const {isInstance, isType, isArrayOf, isa} = require('./isa');
35
35
 
36
36
  // Error-throwing type checks.
37
37
  const {needObj, needType, needs} = require('./needs');
@@ -42,8 +42,10 @@ const def = require('./def');
42
42
  const lazy = require('./lazy');
43
43
  const TYPES = require('./typelist');
44
44
  const stringify = require('./stringify');
45
+ const ownCount = require('./owncount');
45
46
 
46
- const console = require('./console');
47
+ // An alias for legacy reasons.
48
+ const console = require('../console');
47
49
 
48
50
  // Okay, add all those to our exports.
49
51
  // Further tests can be added by `TYPES.add()` later.
@@ -53,7 +55,8 @@ module.exports =
53
55
  isObj, isComplex, isNil, notNil, isScalar, isArray, isTypedArray,
54
56
  nonEmptyArray, isArguments, isProperty, doesDescriptor,
55
57
  isInstance, isType, isa, needObj, needType, needs, stringify,
56
- doesDescriptorTemplate, console,
58
+ doesDescriptorTemplate, ownCount, isArrayOf,
59
+ console,
57
60
  }
58
61
 
59
62
  // Last but not least, this will be the module for TYPES.add()
package/lib/types/isa.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const {O, F, S} = require('./js');
2
- const {isObj} = require('./basics');
2
+ const {isObj,isArray} = require('./basics');
3
3
  const TYPES = require('./typelist');
4
4
 
5
5
  /**
@@ -126,8 +126,8 @@ function processOptions(type, v)
126
126
  * @param {*} v - The value we're testing.
127
127
  * @param {...any} types - The types the value should be one of.
128
128
  *
129
- * For each of the `types`, if it is a `string` we test with `isType()`,
130
- * if it is a `function` we test with `isInstance()`.
129
+ * For each of the `types`, by default if it is a `string`
130
+ * we test with `isType()`, if it is a `function` we test with `isInstance()`.
131
131
  *
132
132
  * If it is an `object` and has an `is()` method, use that as the test.
133
133
  *
@@ -139,7 +139,9 @@ function processOptions(type, v)
139
139
  * - `parsers: function`, Add another options parser function.
140
140
  * - `process: function`, A one-time set-up function.
141
141
  * - `test: function`, Pass the `v` to this test and return `true` if it passes.
142
- * - Anything else will be set as an option.
142
+ * - `typeof: boolean`, If `true` use `typeof` instead of `isType()` for tests.
143
+ * - `instanceof: boolean`, If `true` use `instanceof` instead of `isInstance()`.
144
+ * - Anything else will be set as an option that may be used by other parsers.
143
145
  *
144
146
  * Any other type value will only match if `v === type`
145
147
  *
@@ -154,6 +156,8 @@ function isa(v, ...types)
154
156
  needProto: false,
155
157
  parsers: [DEFAULT_ISA_PARSER],
156
158
  process: processOptions,
159
+ typeof: false,
160
+ instanceof: false,
157
161
  }
158
162
 
159
163
  for (const type of types)
@@ -164,10 +168,12 @@ function isa(v, ...types)
164
168
  // With that out of the way, let's go!
165
169
  if (typeof type === S)
166
170
  { // A string is passed to isType()
171
+ if (opts.typeof && typeof v === type) return true;
167
172
  if (isType(type, v)) return true;
168
173
  }
169
174
  else if (typeof type === F)
170
175
  { // A function is passed to isInstance()
176
+ if (opts.instanceof && v instanceof type) return true;
171
177
  if (isInstance(v, type, opts.needProto)) return true;
172
178
  }
173
179
  else if (isObj(type))
@@ -181,3 +187,130 @@ function isa(v, ...types)
181
187
  }
182
188
 
183
189
  exports.isa = isa;
190
+
191
+ /**
192
+ * Extended return value from `isArrayOf()`.
193
+ *
194
+ * Used if the `opts.details` option was `true`.
195
+ *
196
+ * @typedef module:@lumjs/core/types~IsArrayOfResult
197
+ *
198
+ * @prop {boolean} pass - Did the `isArrayOf()` test pass?
199
+ * @prop {boolean} empty - Was the array empty?
200
+ *
201
+ * @prop {object} [failed] Failure information;
202
+ * Only addedd if `pass` is false.
203
+ *
204
+ * @prop {number} failed.index - Index of item that caused the failure.
205
+ * Will be set to `-1` if the `opts.value` argument is not an Array,
206
+ * or if the array is empty and `opts.empty` was not set to `true`.
207
+ *
208
+ * @prop {mixed} failed.value - The item that caused the failure.
209
+ * Will be the `opts.value` itself if `failed.index` is `-1`.
210
+ *
211
+ */
212
+
213
+ /**
214
+ * See if every item in an Array passes an `isa()` test.
215
+ *
216
+ * @param {(object|Array)} opts - Options for this test function.
217
+ *
218
+ * If this argument is an `Array` it is assumed to be the
219
+ * `opts.value` named option.
220
+ *
221
+ * @param {Array} opts.value - The actual Array value to test.
222
+ * @param {boolean} [opts.details=false] Return detailed test results?
223
+ * @param {boolean} [opts.empty=false] Does an empty array pass the test?
224
+ *
225
+ * @param {...any} types - See {@link module:@lumjs/core/types.isa}.
226
+ *
227
+ * All arguments other than `opts` are passed to `isa()` with each item
228
+ * from the `opts.value` array as the subject of the test.
229
+ *
230
+ * @returns {(boolean|object)} Results of the test.
231
+ *
232
+ * If `opts.details` was `true` this will be a
233
+ * {@link module:@lumjs/core/types~IsArrayOfResult} object.
234
+ *
235
+ * Otherwise it will be a simple `boolean` value indicating
236
+ * if the test passed or failed.
237
+ *
238
+ * @alias module:@lumjs/core/types.isArrayOf
239
+ */
240
+ function isArrayOf(opts, ...types)
241
+ {
242
+ if (!isObj(opts)) return false; // Failure right off the bat!
243
+
244
+ if (Array.isArray(opts))
245
+ { // The array subject was passed.
246
+ opts = {value: opts};
247
+ }
248
+
249
+ let res; // Format depends on the options.
250
+
251
+ if (opts.details)
252
+ {
253
+ res =
254
+ {
255
+ pass: false,
256
+ empty: false,
257
+ failed:
258
+ {
259
+ index: -1,
260
+ value: val,
261
+ }
262
+ }
263
+ }
264
+ else
265
+ {
266
+ res = false;
267
+ }
268
+
269
+ if (!isArray(opts.value)) return res;
270
+
271
+ if (opts.value.length === 0)
272
+ { // An empty array.
273
+ if (opts.details)
274
+ {
275
+ res.empty = true;
276
+ }
277
+
278
+ if (!opts.empty)
279
+ { // Empty arrays are failure unless `opts.empty` is true.
280
+ return res;
281
+ }
282
+ }
283
+ else
284
+ { // Run the tests on each item.
285
+ for (let i=0; i < opts.value.length; i++)
286
+ {
287
+ const vi = opts.value[i];
288
+
289
+ if (opts.details)
290
+ {
291
+ res.failed.index = i;
292
+ res.failed.value = vi;
293
+ }
294
+
295
+ if (!isa(vi, ...types))
296
+ { // An item did not pass the test.
297
+ return res;
298
+ }
299
+ }
300
+ }
301
+
302
+ // If we made it here, we passed.
303
+ if (opts.details)
304
+ {
305
+ res.pass = true;
306
+ delete res.failed;
307
+ }
308
+ else
309
+ {
310
+ res = true;
311
+ }
312
+
313
+ return res;
314
+ }
315
+
316
+ exports.isArrayOf = isArrayOf;
@@ -1,7 +1,7 @@
1
1
  const {F, S, B} = require('./js');
2
2
  const {isType, isa} = require('./isa');
3
3
  const {isObj, isComplex} = require('./basics');
4
- const console = require('./console');
4
+ const console = require('../console');
5
5
 
6
6
  /**
7
7
  * If a value is not an object, throw an error.
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Return the number of _local_ properties in an object.
3
+ *
4
+ * @param {(object|function)} v - The value we want the property count of.
5
+ *
6
+ * This can be any kind of `object`, or it can be a `function` that has
7
+ * a `prototype` property which is a `object`. Anything else is invalid.
8
+ *
9
+ * @param {number} [level=0] Determine which properties to count.
10
+ *
11
+ * - `== 0` : Counts only enumerable properties.
12
+ * - `> 0` : Includes all properties with string names.
13
+ * - `> 1` : Also includes symbol properties.
14
+ *
15
+ * @returns {number} The number of matching properties.
16
+ *
17
+ * If `v` was an invalid value, this will return `-1`.
18
+ *
19
+ * @alias module:@lumjs/core/types.ownCount
20
+ */
21
+ function ownCount(v, level=0)
22
+ {
23
+ if (typeof v === F && isObj(v.prototype))
24
+ { // If a class constructor is passed, we use the prototype.
25
+ v = v.prototype;
26
+ }
27
+
28
+ if (!isObj(v))
29
+ { // Nothing more to do here.
30
+ return -1;
31
+ }
32
+
33
+ if (level == 0)
34
+ { // Enumerable properties only.
35
+ return Object.keys(v).length;
36
+ }
37
+
38
+ // Include all properties with string names.
39
+
40
+ let count = Object.getOwnPropertyNames(v).length;
41
+
42
+ if (level > 1)
43
+ { // Also include symbol properties.
44
+ count += Object.getOwnPropertySymbols(v).length;
45
+ }
46
+
47
+ return count;
48
+ }
49
+
50
+ module.exports = ownCount;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumjs/core",
3
- "version": "1.18.0",
3
+ "version": "1.20.0",
4
4
  "main": "lib/index.js",
5
5
  "exports":
6
6
  {