@lumjs/core 1.26.0 → 1.31.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/types/def.js CHANGED
@@ -2,29 +2,27 @@
2
2
  const unbound = require('./root').unbound;
3
3
  const {F, B} = require('./js');
4
4
  const {isObj, isNil, isProperty, doesDescriptor} = require('./basics');
5
- const {copy, duplicateOne: clone} = require('../obj/copyall');
5
+ const clone = (...args) => Object.assign({}, ...args);
6
6
 
7
7
  /**
8
- * A wrapper around `Object.defineProperty()`.
9
- *
10
- * This has a few features that makes adding properties a lot nicer.
11
- * It replaces the `prop()` method from the old Lum.js v4.
8
+ * A wrapper around `Object.defineProperty()` with added flair!
12
9
  *
13
10
  * @param {(object|function)} obj - The object to add a property to.
11
+ *
14
12
  * @param {?(string|symbol|boolean|object)} name
15
13
  * If a `string` or `symbol`, it's the property name.
16
14
  *
17
15
  * If this is `null` or `undefined` then the `value` is ignored entirely,
18
16
  * and instead a bound version of this function is created with the
19
- * `obj` already passed as the first parameter, and any of the options from
20
- * `opts` added to a new default set of options bound to the function.
21
- * Can be useful if you need to add a lot of properties to the same object.
17
+ * `obj` already passed as the first parameter. It will generate context
18
+ * options which will compose the enumerable properties of `opts` if
19
+ * that argument is passed.
22
20
  *
23
21
  * If this is a `boolean`, then the same logic as if it was `null` or
24
22
  * `undefined` will apply, except that an `enumerable` property with this
25
23
  * value will also be added to the descriptors.
26
24
  *
27
- * If this is an `object`, we also ignore `value` entirely, as each of
25
+ * If this is an `object`, the `value` will be ignored, as each of
28
26
  * the keys of this object will be used as the name of a property,
29
27
  * and the value associated with the key will be the value to assign it.
30
28
  *
@@ -101,6 +99,40 @@ function def(obj, name, value, opts)
101
99
  = !unbound(this, true, true)
102
100
  && typeof this.bound === F;
103
101
 
102
+ if (isNil(name) || typeof name === B)
103
+ { // Binding of Isaac?
104
+ const bindOpts = (to) =>
105
+ {
106
+ Object.assign(to, opts);
107
+ if (typeof name === B) to.enumerable = name;
108
+ return to;
109
+ }
110
+
111
+ if (isBound)
112
+ { // Already bound, update options and return.
113
+ return bindOpts(this).bound;
114
+ }
115
+
116
+ const V = (value) => ({value, configurable: false});
117
+
118
+ // Create a fresh binding context for the bound function.
119
+ const bind = bindOpts({});
120
+ // Create a bound function.
121
+ const bound = def.bind(bind, obj);
122
+ // Add a reference to the function in the binding context.
123
+ def(bind, 'bound', V(bound));
124
+ // And a reference to the binding options from the function.
125
+ def(bound, '$this', V(bind));
126
+
127
+ if (value)
128
+ { // Add DescriptorTemplate magic properties.
129
+ const dopts = clone(value, {desc: bind});
130
+ DT.addInstance(bound, dopts);
131
+ }
132
+
133
+ return bound;
134
+ }
135
+
104
136
  // When we're finished, return this value.
105
137
  const done = () =>
106
138
  {
@@ -114,9 +146,12 @@ function def(obj, name, value, opts)
114
146
  }
115
147
  }
116
148
 
117
- if (isBound && isNil(opts))
118
- { // We'll use `this` as the options.
119
- opts = this;
149
+ if (isBound)
150
+ { // Assign `this` options.
151
+ if (isNil(opts))
152
+ opts = this;
153
+ else if (isObj(opts))
154
+ opts = clone(this, opts);
120
155
  }
121
156
 
122
157
  if (isObj(name))
@@ -128,29 +163,6 @@ function def(obj, name, value, opts)
128
163
  // Okay, we're done now.
129
164
  return done();
130
165
  }
131
- else if (isNil(name) || typeof name === B)
132
- { // Create a fresh binding context for the bound function.
133
- const bind = {};
134
-
135
- if (isObj(opts))
136
- { // Copy our existing options as defaults.
137
- copy(bind, opts);
138
- }
139
-
140
- if (typeof name === B)
141
- { // A boolean `name` overrides the enumerable option.
142
- bind.enumerable = name;
143
- }
144
-
145
- // Create a bound function.
146
- const bound = def.bind(bind, obj);
147
- // Add a reference to the function in the binding context.
148
- bind.bound = bound;
149
- // And a reference to the binding options from the function.
150
- bound.$this = bind;
151
-
152
- return bound;
153
- }
154
166
  else if (!isProperty(name))
155
167
  { // That's not valid.
156
168
  throw new TypeError("Property name must be a string or a Symbol");
@@ -225,4 +237,5 @@ module.exports = def;
225
237
 
226
238
  // Now we'll setup the descriptor template accessors.
227
239
  const DT = require('./dt');
228
- DT.addTo(def);
240
+ DT.addInit(def);
241
+ def.DT = DT;
package/lib/types/dt.js CHANGED
@@ -1,16 +1,65 @@
1
1
  const def = require('./def');
2
+ const {F} = require('./js');
3
+ const {isObj,isProperty} = require('./basics');
4
+
5
+ const V = Symbol('@lumjs/core/types~dt:V');
6
+ const A = Object.freeze(
7
+ {
8
+ i: 'is',
9
+ n: 'not',
10
+ e: 'e',
11
+ c: 'c',
12
+ w: 'w',
13
+ v: 'val',
14
+ g: 'getter',
15
+ s: 'setter',
16
+ d: 'desc',
17
+ p: 'dt',
18
+ });
19
+ const P = Object.freeze(
20
+ {
21
+ e: 'enumerable',
22
+ c: 'configurable',
23
+ w: 'writable',
24
+ g: 'get',
25
+ s: 'set',
26
+ v: 'value',
27
+ });
2
28
 
3
29
  /**
4
30
  * Build a descriptor template using a simple property syntax.
5
31
  *
6
- * TODO: document this further.
32
+ * Generally used via magic properties on the `def` function:
33
+ *
34
+ * ```js
35
+ * def(o1, 'p1', val1, def.e); // Add 'enumerable' property.
36
+ * def(o2, 'p2', val2, def.not.c); // Remove 'configurable' status.
37
+ * ```
38
+ *
39
+ * The supported magic properties are:
40
+ *
41
+ * | Prop | Description |
42
+ * | ----- | --------------------------------------------------------- |
43
+ * | `is` | Make subsequent rule accessors set their value to `true` |
44
+ * | `not` | Make subsequent rule accessors set their value to `false` |
45
+ * | `c` | Accessor that sets `configurable` descriptor rule value |
46
+ * | `e` | Accessor that sets `enumerable` descriptor rule value |
47
+ * | `w` | Accessor that sets `writable` descriptor rule value |
7
48
  *
49
+ * Similar magic properties may be added to bound instances of `def`;
50
+ * I'll add further docs for that later. Look at the tests for examples.
51
+ *
52
+ * The constructor function is also available via `def.DT`,
53
+ * but using the built-in properties is easier.
54
+ *
55
+ * @class
8
56
  * @alias module:@lumjs/core/types~DescriptorTemplate
9
57
  */
10
- function DescriptorTemplate()
58
+ function DescriptorTemplate(opts={})
11
59
  {
12
- if (!new.target) return new DescriptorTemplate();
13
- def(this, '_v', true);
60
+ if (!new.target) return new DescriptorTemplate(opts);
61
+ def(this, V, true);
62
+ def(this, A.d, {value: (isObj(opts.desc) ? opts.desc : this)});
14
63
  }
15
64
 
16
65
  const dp = DescriptorTemplate.prototype;
@@ -21,7 +70,7 @@ function pa(prop)
21
70
  {
22
71
  get()
23
72
  { // Set a regular, enumerable, writable value.
24
- this[prop] = this._v;
73
+ this[A.d][prop] = this[V];
25
74
  return this;
26
75
  }
27
76
  });
@@ -33,38 +82,118 @@ function va(value)
33
82
  {
34
83
  get()
35
84
  { // Set a hidden, but configurable value.
36
- def(this, '_v', value);
85
+ def(this, V, value);
37
86
  return this;
38
87
  }
39
88
  });
40
89
  }
41
90
 
42
- def(dp, 'is', va(true));
43
- def(dp, 'not', va(false));
44
- def(dp, 'e', pa('enumerable'));
45
- def(dp, 'c', pa('configurable'));
46
- def(dp, 'w', pa('writable'));
91
+ function af(p)
92
+ {
93
+ return function(fn)
94
+ {
95
+ const d = this[A.d];
96
+ delete d[P.v];
97
+ delete d[P.w];
98
+ d[p] = fn;
99
+ return this;
100
+ }
101
+ }
47
102
 
48
- function na(accessor)
103
+ def(dp)
104
+ (A.i, va(true))
105
+ (A.n, va(false))
106
+ (A.e, pa(P.e))
107
+ (A.c, pa(P.c))
108
+ (A.w, pa(P.w))
109
+ (A.g, af(P.g))
110
+ (A.s, af(P.s))
111
+ (A.v, function(v1, v2)
112
+ { // A function to set a value with.
113
+ const d = this[A.d];
114
+ if (typeof v2 === F && typeof v1 === F)
115
+ {
116
+ delete d[P.v];
117
+ delete d[P.w];
118
+ d.get = v1;
119
+ d.set = v2;
120
+ }
121
+ else
122
+ {
123
+ delete d.get;
124
+ delete d.set;
125
+ d.value = v1;
126
+ }
127
+ return this;
128
+ })
129
+ ; // def(dp)
130
+
131
+ // for addInit()
132
+ function na(dp, opts)
49
133
  {
50
134
  return(
51
135
  {
52
136
  get()
53
- {
54
- const dt = new DescriptorTemplate();
55
- return dt[accessor];
137
+ {
138
+ const dt = new DescriptorTemplate(opts);
139
+ return dt[dp];
56
140
  }
57
141
  });
58
142
  }
59
143
 
60
- const DTA = ['is','not','e','c','w'];
144
+ // For addInstance()
145
+ function ni(ip, dp)
146
+ {
147
+ return(
148
+ {
149
+ get()
150
+ {
151
+ this[ip][dp];
152
+ return this;
153
+ }
154
+ });
155
+ }
61
156
 
62
- DescriptorTemplate.addTo = function(target)
157
+ const DTA = [A.i,A.n,A.e,A.c,A.w];
158
+
159
+ DescriptorTemplate.addInit = function(target, opts={})
63
160
  {
64
161
  for (const a of DTA)
65
162
  {
66
- def(target, a, na(a));
163
+ def(target, a, na(a, opts));
164
+ }
165
+ }
166
+
167
+ DescriptorTemplate.addInstance = function(target, opts={})
168
+ {
169
+ const prop = isProperty(opts.prop) ? opts.prop : A.p;
170
+ const dt = new DescriptorTemplate(opts);
171
+
172
+ def(target, prop, {value: dt});
173
+
174
+ for (const a of DTA)
175
+ {
176
+ def(target, a, ni(prop, a));
67
177
  }
178
+
179
+ return target;
68
180
  }
69
181
 
70
182
  module.exports = DescriptorTemplate;
183
+
184
+ /**
185
+ * Set a data value or accessor getter/setter combo.
186
+ *
187
+ * @function module:@lumjs/core/types~DescriptorTemplate#val
188
+ *
189
+ * @param {mixed} v1 - Value to assign, or Getter function
190
+ *
191
+ * This is used as a Getter is if `v2` is also a `function`.
192
+ * In any other case this will assign a data `value` property.
193
+ *
194
+ * @param {function} [v2] - Setter function
195
+ *
196
+ * This is only used if `v1` is also a `function`.
197
+ *
198
+ * @returns {object} `this`
199
+ */
@@ -1,71 +1,44 @@
1
+ "use strict";
2
+
1
3
  /**
2
- * Fundamental Types sub-module.
4
+ * The complete `types` module.
3
5
  *
4
6
  * As `@lumjs/core` is the foundation for all my JS libraries,
5
- * this sub-module is the foundation for `@lumjs/core`.
6
- * Everything else is built upon this.
7
+ * this module is the foundation for `@lumjs/core`.
7
8
  *
8
9
  * @module @lumjs/core/types
9
- * @property {string} O - "object"
10
- * @property {string} F - "function"
11
- * @property {string} S - "string"
12
- * @property {string} B - "binary"
13
- * @property {string} N - "number"
14
- * @property {string} U - "undefined"
15
- * @property {string} SY - "symbol"
16
- * @property {string} BI - "bigint"
17
10
  */
18
11
 
19
- // Constants representing core Javascript types.
20
- const {O, F, S, B, N, U, SY, BI} = require('./js');
21
-
22
- // Basic type check functions.
23
- const
24
- {
25
- isObj, isComplex, isNil, notNil, isScalar, isArray, isTypedArray,
26
- nonEmptyArray, isArguments, isProperty, doesDescriptor, isIterable,
27
- isConstructor, doesDescriptorTemplate,
28
- } = require('./basics');
29
-
30
- // Root namespace helpers.
31
- const {root, unbound} = require('./root');
32
-
33
- // Advanced type checks.
34
- const
35
- {
36
- isInstance, isType, isa,
37
- isArrayOf, isListOf, isMapOf, isObjOf, OfTest,
38
- } = require('./isa');
39
-
40
- // Error-throwing type checks.
41
- const {needObj, needType, needs} = require('./needs');
42
-
43
- // A few standalone items.
44
-
45
- const def = require('./def');
46
- const lazy = require('./lazy');
47
- const TYPES = require('./typelist');
48
- const stringify = require('./stringify');
49
- const ownCount = require('./owncount');
50
-
51
- // An alias for legacy reasons.
52
- const console = require('../console');
53
-
54
- // Okay, add all those to our exports.
55
- // Further tests can be added by `TYPES.add()` later.
56
- module.exports =
12
+ const def = require('./def'), lazy = require('./lazy');
13
+
14
+ // Compose in sub-modules.
15
+ Object.assign(exports,
16
+ require('./basics'),
17
+ require('./root'),
18
+ require('./isa'),
19
+ require('./needs'),
20
+ { // A few standalone exports.
21
+ def, lazy,
22
+ TYPES: require('./typelist'),
23
+ stringify: require('./stringify'),
24
+ ownCount: require('./owncount'),
25
+ },
26
+ );
27
+
28
+ // Replace the configurable constant props with readonly ones
29
+ exports.JS.addTo(exports);
30
+
31
+ // Deprecated alias for `console` module, lazy-loaded if requested.
32
+ const {wrapDepr} = require('../meta');
33
+ wrapDepr(exports, 'console',
57
34
  {
58
- O, F, S, B, N, U, SY, BI, TYPES, root, unbound, def, lazy,
59
- isObj, isComplex, isNil, notNil, isScalar, isArray, isTypedArray,
60
- nonEmptyArray, isArguments, isProperty, doesDescriptor,
61
- isInstance, isType, isa, needObj, needType, needs, stringify,
62
- doesDescriptorTemplate, ownCount, isIterable, isConstructor,
63
- isArrayOf, isListOf, isMapOf, isObjOf, OfTest,
64
- console,
65
- }
35
+ dep: 'core.types.console',
36
+ rep: 'core.console',
37
+ get: () => require('../console'),
38
+ });
66
39
 
67
40
  // This will be the module for TYPES.add()
68
- def(TYPES, '$module', module);
41
+ def(exports.TYPES, '$module', module);
69
42
 
70
43
  // Extend `unbound` with add() and remove() methods.
71
- require('./unbound/extend')(unbound);
44
+ require('./unbound/extend')(exports.unbound);
package/lib/types/isa.js CHANGED
@@ -16,6 +16,7 @@ const def = require('./def');
16
16
  */
17
17
  function isInstance(v, f, needProto=false)
18
18
  {
19
+ deprecated('types.isInstace','instanceof');
19
20
  if (!isObj(v)) return false; // Not an object.
20
21
  if (needProto && (typeof v.prototype !== O || v.prototype === null))
21
22
  { // Has no prototype.
@@ -909,3 +910,6 @@ def(isPlainObjectOf, 'rules', function()
909
910
  });
910
911
 
911
912
  exports.isObjOf = isPlainObjectOf;
913
+
914
+ // Just in case let's load this down here.
915
+ const {deprecated} = require('../meta');
package/lib/types/js.js CHANGED
@@ -1,12 +1,48 @@
1
- // Fundamental core types.
2
- const O='object', F='function', S='string', B='boolean', N='number',
3
- U='undefined', SY='symbol', BI='bigint';
1
+ "use strict";
4
2
 
5
3
  /**
6
- * One or two character identifiers for the core JS type names.
4
+ * An absolutely minimal map of one or two letter string constants
5
+ * representing all of the fundamental JS types.
6
+ *
7
+ * This object is *frozen* and cannot be modified in any way!
7
8
  *
8
9
  * These are only the strings returned by the `typeof` operator.
9
- * See the `TYPES` object (defined in `typelist.js`) for a list
10
- * that includes special types and compound pseudo-types, etc.
10
+ * See {@link module:@lumjs/core/types.TYPES} for a much more complete
11
+ * list that includes special types and compound pseudo-types, etc.
12
+ *
13
+ * @prop {string} O - object
14
+ * @prop {string} F - function
15
+ * @prop {string} S - string
16
+ * @prop {string} B - boolean
17
+ * @prop {string} N - number
18
+ * @prop {string} U - undefined
19
+ * @prop {string} SY - symbol
20
+ * @prop {string} BI - bigint
21
+ *
22
+ * @memberof module:@lumjs/core/types/basics
11
23
  */
12
- module.exports = {O, F, S, B, N, U, SY, BI};
24
+ const JS =
25
+ {
26
+ O: 'object',
27
+ F: 'function',
28
+ S: 'string',
29
+ B: 'boolean',
30
+ N: 'number',
31
+ U: 'undefined',
32
+ SY: 'symbol',
33
+ BI: 'bigint',
34
+ }
35
+
36
+ function addTo(target)
37
+ {
38
+ for (const key in this)
39
+ {
40
+ const value = this[key];
41
+ const desc = {value, enumerable: true};
42
+ Object.defineProperty(target, key, desc);
43
+ }
44
+ }
45
+
46
+ Object.defineProperty(JS, 'addTo', {value: addTo});
47
+
48
+ module.exports = Object.freeze(JS);
package/lib/types/lazy.js CHANGED
@@ -41,6 +41,7 @@ const {doesDescriptor} = require('./basics');
41
41
  * A function to generate the property value.
42
42
  *
43
43
  * @callback module:@lumjs/core/types~LazyGetter
44
+ * @param {module:@lumjs/core/types~LazyDef} info - A metadata object
44
45
  * @returns {*} The generated *value* of the property
45
46
  *
46
47
  * By default if this is `undefined` the value will **not** be
@@ -60,7 +61,7 @@ const {doesDescriptor} = require('./basics');
60
61
  * Regardless of the value of `this.assign`, this value will
61
62
  * be *returned* as the property value.
62
63
  *
63
- * @this {module:@lumjs/core/types~LazyDef} A metadata object.
64
+ * @this {module:@lumjs/core/types~LazyDef} The `info` metadata object
64
65
  */
65
66
 
66
67
  /**
@@ -194,7 +195,7 @@ function lazy(target, name, initfunc, opts={})
194
195
 
195
196
  desc.get = function()
196
197
  {
197
- return defval(initfunc.call(context));
198
+ return defval(initfunc.call(context,context));
198
199
  }
199
200
 
200
201
  if (typeof opts.set === F)
@@ -1,7 +1,6 @@
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');
5
4
 
6
5
  /**
7
6
  * If a value is not an object, throw an error.
@@ -9,12 +9,14 @@ const
9
9
  /**
10
10
  * A map of **Types**, including *special* and *union* types.
11
11
  *
12
- * Contains the same `O, F, S, B, N, U, SY, BI` properties as also
13
- * found in the top-level {@link module:@lumjs/core/types} module.
14
- * While most of the core JS types simply use `typeof` as their
12
+ * Contains the constants from {@link module:@lumjs/core/types/basics.JS},
13
+ * plus a whole bunch of _special types_ that require tests other than
14
+ * `typeof` to determine if a given value matches that type.
15
+ *
16
+ * Also, while MOST of the core JS types simply use `typeof` as their
15
17
  * test, this maps the `O` (`object`) type to the `isObj` test.
16
18
  *
17
- * Will also contain a few helper functions, and a map of tests
19
+ * It also contain a few helper functions, and a map of tests
18
20
  * that are used by `isType`, `isa`, `needType`, and `needs`.
19
21
  * Any one of these properties may be passed to those functions as
20
22
  * the desired *type* a desired value must be.
package/lum.build.js ADDED
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ const D =
4
+ {
5
+ build: 'docs/build',
6
+ api: 'docs/api/',
7
+ changelogs: 'docs/changelogs',
8
+ ad(from)
9
+ {
10
+ const to = D.api+from.replace(/\.md/, '.html');
11
+ return {from,to}
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,
40
+ }
package/package.json CHANGED
@@ -1,41 +1,51 @@
1
1
  {
2
2
  "name": "@lumjs/core",
3
- "version": "1.26.0",
3
+ "version": "1.31.0",
4
4
  "main": "lib/index.js",
5
- "exports":
5
+ "exports":
6
6
  {
7
7
  ".": "./lib/index.js",
8
-
9
8
  "./arrays": "./lib/arrays/index.js",
10
9
  "./console": "./lib/console.js",
11
10
  "./context": "./lib/context.js",
12
11
  "./enum": "./lib/enum.js",
12
+ "./events": "./lib/events/index.js",
13
13
  "./flags": "./lib/flags.js",
14
14
  "./maps": "./lib/maps.js",
15
15
  "./meta": "./lib/meta.js",
16
16
  "./modules": "./lib/modules.js",
17
17
  "./obj": "./lib/obj/index.js",
18
+ "./obj/cp": "./lib/obj/cp.js",
18
19
  "./observable": "./lib/observable.js",
19
- "./opt": "./lib/opt.js",
20
+ "./opt": "./lib/opt/index.js",
21
+ "./opt/args": "./lib/opt/args.js",
20
22
  "./strings": "./lib/strings.js",
21
23
  "./traits": "./lib/traits.js",
22
24
  "./types": "./lib/types/index.js",
23
-
25
+ "./types/basics": "./lib/types/basics.js",
26
+ "./types/def": "./lib/types/def.js",
24
27
  "./package.json": "./package.json"
25
28
  },
26
- "license": "MIT",
27
- "repository":
29
+ "dependencies":
28
30
  {
29
- "type": "git",
30
- "url": "https://github.com/supernovus/lum.core.js.git"
31
+ "@lumjs/opts": "^1.0.0"
31
32
  },
32
- "devDependencies":
33
+ "devDependencies":
33
34
  {
34
- "@lumjs/tests": "^1.8.0"
35
+ "@lumjs/build": "^1.0.0",
36
+ "@lumjs/tests": "^2.0.0"
35
37
  },
36
- "scripts":
38
+ "scripts":
37
39
  {
38
40
  "test": "lumtest.js",
39
- "build-docs": "jsdoc -c ./jsdoc.json"
40
- }
41
+ "build-meta": "lum-build",
42
+ "build-jsdoc": "jsdoc -c ./jsdoc.js",
43
+ "build-docs": "npm run build-meta && npm run build-jsdoc"
44
+ },
45
+ "repository":
46
+ {
47
+ "type": "git",
48
+ "url": "https://github.com/supernovus/lum.core.js.git"
49
+ },
50
+ "license": "MIT"
41
51
  }