@lumjs/core 1.38.4 → 1.38.6

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/index.js CHANGED
@@ -14,44 +14,38 @@
14
14
 
15
15
  const types = require('./types');
16
16
  const {df,lazy} = require('./obj/df');
17
+ const meta = require('./meta');
17
18
 
18
- // Get a bunch of properties from a submodule.
19
- function from(submod)
19
+ exports = module.exports =
20
20
  {
21
- for (const key in submod)
22
- {
23
- df(exports, key, submod[key]);
24
- }
21
+ context: require('./context'),
22
+ def: types.def, // ← TODO: nix in 2.x
23
+ df,
24
+ Enum: require('./enum'),
25
+ env: require('./env'),
26
+ flags: require('./flags'),
27
+ lazy,
28
+ maps: require('./maps'),
29
+ meta,
30
+ ...(meta), // ← TODO: nix in 2.x
31
+ ...(require('./objectid')),
32
+ // obj: require('./obj'), // ← TODO: uncomment in 2.x
33
+ opt: require('./opt'),
34
+ state: require('./state'),
35
+ strings: require('./strings'),
36
+ types,
25
37
  }
26
38
 
27
- df(exports, 'types', types);
28
- df(exports, 'def', types.def);
29
- df(exports, 'df', df);
30
- df(exports, 'lazy', lazy);
31
-
32
- df(exports, 'context', require('./context'));
33
- df(exports, 'state', {value: require('./state')});
39
+ // TODO: nix everything below here in 2.x
34
40
 
35
- // ObjectID stuff is imported directly without registering a sub-module.
36
- from(require('./objectid'));
37
-
38
- // These are exported directly, but a meta sub-module also exists.
39
- const meta = require('./meta');
40
- from(meta);
41
- df(exports, 'meta', meta);
42
41
  df(exports, 'AbstractClass',
43
42
  {
44
43
  get() { return meta.AbstractClass; }
45
44
  });
46
45
 
47
46
  lazy(exports, 'arrays', () => require('./arrays'));
48
- lazy(exports, 'maps', () => require('./maps'));
49
- lazy(exports, 'strings', () => require('./strings'));
50
- lazy(exports, 'flags', () => require('./flags'));
51
47
  lazy(exports, 'obj', () => require('./obj'));
52
48
  lazy(exports, 'console', () => require('./console'));
53
49
  lazy(exports, 'traits', () => require('./traits'));
54
- lazy(exports, 'opt', () => require('./opt'), {df:{autoDesc: false}});
55
- lazy(exports, 'Enum', () => require('./enum'));
56
50
  lazy(exports, 'observable', () => require('./observable'));
57
51
  lazy(exports, 'events', () => require('./events'));
package/lib/meta.js CHANGED
@@ -1,22 +1,16 @@
1
- "use strict";
2
1
  /**
3
- * Meta-programming helpers
4
- *
5
- * All of the function exported by this module are also available
6
- * in the main {@link module:@lumjs/core core object} itself.
7
- *
2
+ * Meta-programming helpers.
8
3
  * @module @lumjs/core/meta
9
4
  */
10
-
11
- const {F} = require('./types/js');
5
+ 'use strict';
12
6
 
13
7
  /**
14
- * Get a stacktrace. Differs from browser to browser.
8
+ * Get a stacktrace.
15
9
  *
16
10
  * Uses the `stack` property of an `Error` object as the source.
17
- * This is a super simplistic hack. For a more complete solution, try
18
- * the `stacktrace-js` library, which will be used in the new `@lumjs/debug`
19
- * library as a dependency.
11
+ * Every runtime differs greatly in what is contained in the `stack` text,
12
+ * so this may not be particularly useful. For a more complete solution,
13
+ * try the `stacktrace-js` library.
20
14
  *
21
15
  * @param {string} [msg] - A message for the Error object.
22
16
  *
@@ -186,9 +180,9 @@ exports.deprecated = deprecated;
186
180
  */
187
181
  function wrapDepr(obj,prop,spec)
188
182
  {
189
- if (typeof spec === F)
183
+ if (typeof spec === 'function')
190
184
  spec = {get: spec};
191
- if (typeof spec.get !== F)
185
+ if (typeof spec.get !== 'function')
192
186
  throw new TypeError("invalid init");
193
187
 
194
188
  return df(obj, prop,
@@ -0,0 +1,14 @@
1
+ /**
2
+ * A module namespace for NodeJS specific features.
3
+ *
4
+ * This is currently mostly a placeholder for future development.
5
+ *
6
+ * @module @lumjs/core/node
7
+ */
8
+ 'use strict';
9
+
10
+ module.exports =
11
+ {
12
+ modules: require('./modules'),
13
+ Package: require('./package'),
14
+ }
@@ -1,11 +1,36 @@
1
1
  /**
2
2
  * Module helpers.
3
- * @module @lumjs/core/modules
3
+ *
4
+ * `@lumjs/core/modules` is a deprecated alias to this.
5
+ *
6
+ * @module @lumjs/core/node/modules
4
7
  */
5
8
 
6
9
  const path = require('path');
7
- const {S,isObj} = require('./types');
8
- const replace = require('./strings').replaceItems;
10
+ const {S,isObj} = require('../types');
11
+ const replace = require('../strings').replaceItems;
12
+
13
+ /**
14
+ * Test if a passed value is a CommonJS `module` object.
15
+ * @param {*} mod - Value to test.
16
+ * @returns {boolean}
17
+ * @alias module:@lumjs/core/node/modules.isCJS
18
+ */
19
+ const isCJS = (mod) => (isObj(mod)
20
+ && typeof mod.id === 'string'
21
+ && typeof mod.require === 'function'
22
+ );
23
+
24
+ /**
25
+ * Test if a passed value is an ES Module `import.meta` object.
26
+ * @param {*} mod - Value to test.
27
+ * @returns {boolean}
28
+ * @alias module:@lumjs/core/node/modules.isESM
29
+ */
30
+ const isESM = (mod) => (isObj(mod)
31
+ && typeof mod.url === 'string'
32
+ && typeof mod.resolve === 'function'
33
+ );
9
34
 
10
35
  /**
11
36
  * Get the name of a module.
@@ -41,9 +66,13 @@ function name(module, opts={})
41
66
  { // Going to assume a string is the filename.
42
67
  filename = module;
43
68
  }
44
- else if (isObj(module) && typeof module.filename === S)
69
+ else if (isCJS(module))
45
70
  { // It's a CommonJS module context object.
46
- filename = module.filename;
71
+ filename = module.filename ?? module.id;
72
+ }
73
+ else if (isESM(module))
74
+ { // It's an ES Module metadata (import.meta) object.
75
+ filename = module.filename ?? path.basename(module.url);
47
76
  }
48
77
  else
49
78
  { // Sorry, we don't support that.
@@ -110,4 +139,4 @@ function name(module, opts={})
110
139
  return filename;
111
140
  }
112
141
 
113
- exports.name = name;
142
+ module.exports = { name, isCJS, isESM }
@@ -0,0 +1,107 @@
1
+ 'use strict';
2
+
3
+ const semver = require('semver');
4
+ const PKGJSON = '/package.json';
5
+
6
+ function validate(pkgid, autoAppend)
7
+ {
8
+ if (typeof pkgid !== 'string')
9
+ {
10
+ throw new TypeError("package id must be a string");
11
+ }
12
+
13
+ if (autoAppend && !pkgid.endsWith(PKGJSON))
14
+ {
15
+ pkgid += PKGJSON;
16
+ }
17
+
18
+ return pkgid;
19
+ }
20
+
21
+ /**
22
+ * A wrapper class around package.json data that provides some version
23
+ * related helper methods.
24
+ * @exports @lumjs/core/node.Package
25
+ */
26
+ class Package
27
+ {
28
+ /**
29
+ * Build a Package instance.
30
+ *
31
+ * This requires that you've already loaded and parsed a package.json file.
32
+ * See the require() and import() static methods which take a package name,
33
+ * and expect that the package has a `/package.json` export defined.
34
+ *
35
+ * @param {object} pkginfo - Data parsed from a package.json file.
36
+ */
37
+ constructor(pkginfo)
38
+ {
39
+ /**
40
+ * The package.json data.
41
+ * @type {object}
42
+ */
43
+ this.info = pkginfo;
44
+
45
+ /**
46
+ * A `SemVer` instance (from the `semver` package) parsed from
47
+ * the `version` property of the package.json data.
48
+ * @type {object}
49
+ */
50
+ this.version = semver.parse(this.info.version);
51
+ }
52
+
53
+ /**
54
+ * See if the package version satisfies a range statement.
55
+ * @param {string} range - A semver range statement.
56
+ * @param {object} [options] Options; see semver documentation.
57
+ */
58
+ satisfies(range, options)
59
+ {
60
+ return semver.satisfies(this.version, range, options);
61
+ }
62
+
63
+ /**
64
+ * Build a Package instance using require() to load a package.json file.
65
+ *
66
+ * @param {string} pkgid - Package id.
67
+ *
68
+ * Assuming the package exports it's package.json as `/package.json` you
69
+ * can simply pass the plain package name here (e.g. `@lumjs/core`).
70
+ *
71
+ * @param {boolean} [autoAppend=true] Auto-append `/package.json` to pkgid?
72
+ *
73
+ * If this is true (it is by default) and `pkgid` does NOT end in
74
+ * `/package.json`, it will be automatically appended before passing
75
+ * to require(). If for whatever reason the actual sub-module breaks the
76
+ * expected naming convention, you'll need to pass the full sub-module
77
+ * path as the `pkgid` and set this argument to false.
78
+ *
79
+ * @returns {module:@lumjs/core/node.Package}
80
+ * @throws {TypeError} If `pkgid` is not a string.
81
+ * @throws {Error} If the package.json can not be loaded.
82
+ */
83
+ static require(pkgid, autoAppend=true)
84
+ {
85
+ let pkginfo = require(validate(pkgid, autoAppend));
86
+ return new this(pkginfo);
87
+ }
88
+
89
+ /**
90
+ * Build a Package instance using import() to load a package.json file.
91
+ *
92
+ * All arguments are handled exactly the same as the require() method.
93
+ * The only difference is import() is asynchronous, so this will return
94
+ * a Promise that will resolve to the new Package instance.
95
+ *
96
+ * @param {string} pkgid
97
+ * @param {boolean} [autoAppend=true]
98
+ * @returns {Promise<module:@lumjs/core/node.Package>}
99
+ */
100
+ static async import(pkgid, autoAppend=true)
101
+ {
102
+ let pkginfo = await import(validate(pkgid, autoAppend));
103
+ return new this(pkginfo);
104
+ }
105
+ }
106
+
107
+ module.exports = Package;
package/lib/obj/apply.js CHANGED
@@ -1,52 +1,260 @@
1
- const {F,isObj} = require('../types');
2
- const copyProps = require('./copyprops');
1
+ const {F} = require('../types');
3
2
 
4
3
  /**
5
- * Apply functions to an object
6
- *
7
- * In addition to the parameters passed, we'll also define:
4
+ * ApplyInfo objects will have a property with this Symbol
5
+ * as its key and boolean `true` as its value.
8
6
  *
9
- * - `cp` will be a `CopyProps` instance via `copyProps.cache.into(obj)`;
10
- * - `args` will be an array of `[obj, opts]`;
11
- * - `opts` will be an object of `{obj, cp, args}`;
7
+ * The `apply.Info` property is an alias to this.
12
8
  *
13
- * @param {(object|function)} obj - The target we're applying to.
9
+ * @type {Symbol}
10
+ * @name module:@lumjs/core/obj.ApplyInfo
11
+ */
12
+ const ApplyInfo = Symbol('@lumjs/core/obj.ApplyInfo');
13
+
14
+ /**
15
+ * ApplyOpts objects will have a property with this Symbol
16
+ * as its key and boolean `true` as its value.
14
17
  *
15
- * @param {...(function|object)} fns - Values we are applying.
18
+ * The `apply.Opts` property is an alias to this.
19
+ *
20
+ * @type {Symbol}
21
+ * @name module:@lumjs/core/obj.ApplyOpts
22
+ */
23
+ const ApplyOpts = Symbol('@lumjs/core/obj.ApplyOpts');
24
+
25
+ /**
26
+ * Options for apply() functions and value handlers.
27
+ * @typedef {object} module:@lumjs/core/obj~ApplyOpts
28
+ * @prop {(object|function)} target - Target object.
29
+ * @prop {(object|function)} obj - DEPRECATED alias of `target`.
30
+ * @prop {(object|function)} ctx - Context (`this`) for functions.
31
+ * Set to `target` when opts are initially created.
32
+ * @prop {Set<module:@lumjs/core/obj~ApplyHandler>} handlers
33
+ * Registered value handlers.
34
+ * @prop {Array} args - Arguments passed to `function` values.
16
35
  *
17
- * For each value of `fns` as `fn`:
36
+ * In v1.x this defaults to `[target, opts]`.
37
+ * In v2.x this will default to `[opts]`.
38
+ */
39
+
40
+ /**
41
+ * Info for apply() value handlers.
42
+ * @typedef {object} module:@lumjs/core/obj~ApplyInfo
43
+ * @prop {mixed} value - The value that needs to be handled.
44
+ * @prop {object} opts - The current apply() options.
45
+ * @prop {boolean} ok - If a handler can handle `value` it must set
46
+ * this to `true` indicating the value has been handled.
47
+ * Otherwise apply() will throw a TypeError if every handler has
48
+ * been called and none can handle the value.
49
+ * @prop {boolean} done - If a handler has handled a value it may
50
+ * set this to `true` to indicate that no further handlers need
51
+ * to be called for that value. If this property is true then
52
+ * the `ok` property will automatically be considered true as well.
53
+ */
54
+
55
+ /**
56
+ * An apply() value handler.
18
57
  *
19
- * - If a `function` we'll call `fn.apply(obj, args)`;
20
- * - If an `object` we'll call `cp.from(fn)`.
58
+ * In order to add a handler it must be added to `opts.handlers` using a
59
+ * registration function. You can make a handler that can register itself
60
+ * by checking the argument(s) for the `ApplyInfo` or `ApplyOpts` properties.
61
+ *
62
+ * An example for the upcoming v2.x default arguments:
63
+ *
64
+ * ```js
65
+ * const {apply} = require('@lumjs/core/obj');
66
+ * function myHandler(info)
67
+ * {
68
+ * if (info[apply.Opts])
69
+ * { // Registration (info is opts).
70
+ * info.handlers.add(myHandler);
71
+ * }
72
+ * else if (info[apply.Info])
73
+ * { // Handler call.
74
+ * if (someTest(info.value))
75
+ * { // Code to handle the value would be here.
76
+ * info.ok = true;
77
+ * }
78
+ * }
79
+ * }
80
+ *
81
+ * // Then to use the handler:
82
+ * apply(myObj, myHandler, ...valuesToApply);
83
+ * ```
84
+ *
85
+ * Support for the v1.x default arguments (or even custom arguments),
86
+ * and dealing with invalid arguments is left up to your imagination.
87
+ *
88
+ * @callback module:@lumjs/core/obj~ApplyHandler
89
+ * @param {module:@lumjs/core/obj~ApplyHandlerInfo} info
90
+ * @returns {void} No return value is required or used.
91
+ */
92
+
93
+ /**
94
+ * Some pre-defined value handlers and registration functions.
95
+ * @type {object}
96
+ * @alias module:@lumjs/core/obj.ApplyWith
97
+ */
98
+ const ApplyWith =
99
+ {
100
+ /**
101
+ * A value handler for obj.apply() that uses `cp` to handle objects.
102
+ *
103
+ * This is a self-registering handler designed for @lumjs/core v2.x.
104
+ * Just pass it as a function value to apply() and it will add itself to
105
+ * `opts.handlers`, set `opts.cp` to `copyProps.cache.into(opts.target)`,
106
+ * and `opts.cp.applyDone` to `true`.
107
+ *
108
+ * This is automatically registered in v1.x. No need to manually add it.
109
+ *
110
+ * For any `object` value passed to apply() after registering this handler,
111
+ * it will call: `opts.cp.from(value)` to merge the value's properties into
112
+ * the target object. Finally it will set `info.ok` to `true` (fixed value),
113
+ * and `info.done` to `opts.cp.applyDone`.
114
+ *
115
+ * It does not handle anything other than `object` values.
116
+ *
117
+ * NOTE: As of v1.38.5 this is an alias to `@lumjs/cp/apply.Handler`
118
+ *
119
+ * @function module:@lumjs/obj.ApplyWith.cpHandler
120
+ */
121
+
122
+ /**
123
+ * A helper for registration functions that may have the `opts`
124
+ * passed in different argument positions.
125
+ * @param {Iterable} args - Arguments passed to function.
126
+ * @param {mixed} ctx - The value of `this` in the function.
127
+ * In case `opts.ctx`
128
+ * @returns {?module:@lumjs/core/obj~ApplyOpts}
129
+ * Will be null if no ApplyOpts object could be found in the arguments.
130
+ */
131
+ getOpts(args)
132
+ {
133
+ for (let arg of args)
134
+ {
135
+ if (arg && arg[ApplyOpts]) return arg;
136
+ }
137
+ // No opts found.
138
+ return null;
139
+ },
140
+
141
+ /**
142
+ * A registration function that sets `opts.args` to `[opts.target, opts]`
143
+ * which is the default arguments for @lumjs/core v1.x.
144
+ */
145
+ v1Args()
146
+ {
147
+ let opts = ApplyInfo.getOpts(arguments);
148
+ if (opts)
149
+ {
150
+ opts.args = [opts.target, opts];
151
+ }
152
+ },
153
+
154
+ /**
155
+ * A registration function that sets `opts.args` to `[opts]`
156
+ * which is the default arguments for @lumjs/core v2.x.
157
+ */
158
+ v2Args()
159
+ {
160
+ let opts = ApplyInfo.getOpts(arguments);
161
+ if (opts)
162
+ {
163
+ opts.args = [opts];
164
+ }
165
+ },
166
+ }
167
+
168
+ /**
169
+ * Apply functions (and other values) to an object.
170
+ *
171
+ * NOTE: For the duration of the v1.x releases, the `ApplyWith.cpHandler`
172
+ * function will be registered automatically. That will be removed in v2.x,
173
+ * and you'll have to add it manually from the `@lumjs/cp` package.
174
+ *
175
+ * @param {(object|function)} target - The target we're applying to.
176
+ * @param {...(function|object)} values - Values we are applying.
177
+ *
178
+ * For each `value` of the `values`:
179
+ *
180
+ * - If it's a `function` this will do `value.apply(obj, opts.args)`;
181
+ * - For any other kind of value:
182
+ * - Create an {@link module:@lumjs/core/obj~ApplyInfo} object.
183
+ * - For each handler in `opts.handlers` do `handler.call(obj, info)`;
184
+ * - If none of the handlers set `info.ok` or `info.done` to true,
185
+ * then a TypeError will be thrown, indicating an unhandled value.
21
186
  *
22
187
  * @returns {object} `obj`
23
- * @throws {TypeError} If a `fns` value is not valid.
188
+ * @throws {TypeError} If a value could not be handled.
24
189
  * @alias module:@lumjs/core/obj.apply
25
190
  */
26
- function apply(obj, ...fns)
191
+ function apply(target, ...values)
27
192
  {
28
- const cp = copyProps.cache.into(obj);
29
- const opts = {obj, cp};
30
- const args = [obj, opts];
31
- opts.args = args;
193
+ const opts =
194
+ {
195
+ [ApplyOpts]: true,
196
+ target,
197
+ obj: target, // DEPRECATED: use target
198
+ copyProps: true, // Change to false in v2.x
199
+ ctx: target,
200
+ handlers: new Set(),
201
+ };
202
+
203
+ // TODO: change this to `[opts]` in v2.x
204
+ opts.args = [target, opts];
32
205
 
33
- for (const fn of fns)
206
+ // TODO: remove this line in v2.x
207
+ ApplyWith.cpHandler(opts);
208
+
209
+ for (let value of values)
34
210
  {
35
- if (typeof fn === F)
211
+ if (typeof value === F)
36
212
  {
37
- fn.apply(obj, args);
38
- }
39
- else if (isObj(fn))
40
- {
41
- cp.from(fn);
213
+ value.apply(opts.ctx, opts.args);
42
214
  }
43
215
  else
44
216
  {
45
- throw new TypeError("invalid parameter value");
217
+ let info =
218
+ {
219
+ [ApplyInfo]: true,
220
+ value,
221
+ opts,
222
+ ok: false,
223
+ done: false
224
+ };
225
+
226
+ for (let handler of opts.handlers)
227
+ {
228
+ handler.call(opts.ctx, info);
229
+ if (info.done)
230
+ {
231
+ info.ok = true;
232
+ break;
233
+ }
234
+ }
235
+
236
+ if (!info.ok)
237
+ {
238
+ throw new TypeError("invalid parameter value");
239
+ }
46
240
  }
47
241
  }
48
242
 
49
- return obj;
243
+ return target;
50
244
  }
51
245
 
52
- module.exports = apply;
246
+ // Make aliases to the symbols.
247
+ Object.defineProperties(apply,
248
+ {
249
+ Info: { value: ApplyInfo },
250
+ Opts: { value: ApplyOpts },
251
+ });
252
+
253
+ module.exports = {apply, ApplyInfo, ApplyOpts, ApplyWith};
254
+
255
+ const cpApply = require('@lumjs/cp/apply');
256
+ Object.assign(ApplyWith,
257
+ {
258
+ cpInit: cpApply.init,
259
+ cpHandler: cpApply.Handler,
260
+ });
@@ -6,21 +6,11 @@
6
6
  *
7
7
  * Use `copyProps`, or `mergeNested` for more robust versions.
8
8
  *
9
- * @alias module:@lumjs/core/obj.copyAll
10
- * @deprecated Use `Object.assign()` instead.
9
+ * NOTE: As of v1.38.5 this is an alias of @lumjs/cp/fun.copyAll
10
+ *
11
+ * @name module:@lumjs/core/obj.copyAll
12
+ * @deprecated Moved to @lumjs/cp package.
11
13
  */
12
- function copyAll(target, ...sources)
13
- {
14
- for (const source of sources)
15
- {
16
- for (const name in source)
17
- {
18
- target[name] = source[name];
19
- }
20
- }
21
- return target;
22
- }
23
- exports.copyAll = copyAll;
24
14
 
25
15
  /**
26
16
  * Make a (shallow) copy of a single object using `copyAll`.
@@ -29,12 +19,13 @@ exports.copyAll = copyAll;
29
19
  *
30
20
  * Alias: `copyAll.clone`
31
21
  *
32
- * @alias module:@lumjs/core/obj.duplicateOne
22
+ * NOTE: As of v1.38.5 this is an alias of @lumjs/cp/fun.duplicateOne
23
+ *
24
+ * @name module:@lumjs/core/obj.duplicateOne
33
25
  * @param {object} obj - The object to duplicate.
34
26
  * @returns {object} A clone of the object.
35
- * @deprecated Use `clone()` or `Object.assign()` depending on needs.
27
+ * @deprecated Moved to @lumjs/cp package.
36
28
  */
37
- exports.duplicateOne = copyAll.clone = obj => copyAll({}, obj);
38
29
 
39
30
  /**
40
31
  * Make a new object containing properties from other objects using `copyAll`.
@@ -43,9 +34,12 @@ exports.duplicateOne = copyAll.clone = obj => copyAll({}, obj);
43
34
  *
44
35
  * Alias: `copyAll.duplicate`
45
36
  *
46
- * @alias module:@lumjs/core/obj.duplicateOne
37
+ * NOTE: As of v1.38.5 this is an alias of @lumjs/cp/fun.duplicateAll
38
+ *
39
+ * @name module:@lumjs/core/obj.duplicateAll
47
40
  * @param {object} obj - The object to duplicate.
48
41
  * @returns {object} A clone of the object.
49
- * @deprecated Use `Object.assign()`
42
+ * @deprecated Moved to @lumjs/cp package.
50
43
  */
51
- exports.duplicateAll = copyAll.duplicate = () => copyAll({}, ...arguments);
44
+
45
+ module.exports = require('@lumjs/cp/fun');