@lumjs/core 1.38.4 → 1.38.5

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.
@@ -4,14 +4,22 @@ const
4
4
  B, S,
5
5
  root, isObj, needObj, def, nonEmptyArray, isNil,
6
6
  doesDescriptorTemplate,
7
- } = require('../types');
7
+ } = require('../../types');
8
8
 
9
- const {df} = require('./df');
9
+ const {df} = require('../df');
10
10
  const cp = Object.assign;
11
11
 
12
+ const NS = exports.NS = require('./formats');
13
+ const {isFormat} = NS;
14
+
15
+ // TODO: use the new formats!
16
+
12
17
  /**
13
- * Need a String or Array
18
+ * [INTERNAL] Generate an error message for nsString/nsArray functions.
14
19
  * @alias module:@lumjs/core/obj.SOA
20
+ * @param {?string} [name] Name to prefix to error message.
21
+ * @param {boolean} [err=true] Return an error instance?
22
+ * @returns {(TypeError|string)} Depends on `err` argument.
15
23
  */
16
24
  function SOA(name, err=true)
17
25
  {
@@ -21,61 +29,170 @@ function SOA(name, err=true)
21
29
  return err ? (new TypeError(msg)) : msg;
22
30
  }
23
31
  SOA.message = "must be a string or non-empty array";
24
- def(SOA, 'toString', function() { return this.message; });
32
+ df(SOA, 'toString', function() { return this.message; });
25
33
 
26
34
  exports.SOA = SOA;
27
35
 
28
36
  /**
29
- * Get a namespace path string.
37
+ * Get a namespace path array.
30
38
  *
31
- * If it's already a string, return it as is.
32
- * If it's an array of strings, join the elements with a `.` character.
39
+ * If it's already an array, return it as is.
40
+ * If it's a string, split it into an array, with the `.` delimiter.
33
41
  *
34
42
  * @param {(string|string[])} ns - A dotted string, or array of paths.
35
- * @param {*} name - Name to use in the SOA error
36
- * @returns {string}
37
- * @alias module:@lumjs/core/obj.nsString
43
+ * @param {(object|string)} [opts] Options.
44
+ *
45
+ * If this is a string it will be used as `opts.name`.
46
+ *
47
+ * @param {string} [opts.name="Namespace"] Name to use in the SOA error.
48
+ * @param {(module:@lumjs/core/obj.NS~Format|Array)} [opts.format] Format.
49
+ *
50
+ * You can specify a single format, or an array of formats, in which case
51
+ * the canStringify() method will be called on each of them and the first one
52
+ * that returns true will be used. If none return true, the last one listed
53
+ * will be used.
54
+ *
55
+ * If this is not specified, then we will call the canParse() method on
56
+ * Pointer, JSPath, and Simple (in that order) and use the first one that
57
+ * returns true (or the last one regardless).
58
+ *
59
+ * @returns {string[]}
60
+ * @alias module:@lumjs/core/obj.nsArray
38
61
  */
39
- function nsString(ns, name='Namespace')
62
+ function nsArray(ns, opts={})
40
63
  {
41
- if (nonEmptyArray(ns))
64
+ if (typeof opts === S) opts = {name: opts};
65
+
66
+ if (typeof ns === S)
42
67
  {
43
- return ns.join('.');
68
+ let format;
69
+
70
+ if (isFormat(opts.format) || Array.isArray(opts.format))
71
+ {
72
+ format = opts.format;
73
+ }
74
+ else
75
+ {
76
+ format = NS.Defaults;
77
+ }
78
+
79
+ if (Array.isArray(format))
80
+ {
81
+ let formats = format;
82
+ for (format of formats)
83
+ {
84
+ if (isFormat(format) && format.canParse(ns))
85
+ {
86
+ break;
87
+ }
88
+ }
89
+ }
90
+
91
+ if (!isFormat(format))
92
+ { // This shouldn't normally happen, but...
93
+ throw new TypeError("No valid format found");
94
+ }
95
+
96
+ return format.parse(ns);
44
97
  }
45
- else if (typeof ns !== S)
98
+ else if (!nonEmptyArray(ns))
46
99
  {
47
- throw SOA(name);
100
+ throw SOA(opts.name ?? 'Namespace');
48
101
  }
49
102
  return ns;
50
103
  }
51
104
 
52
- exports.nsString = nsString;
105
+ exports.nsArray = nsArray;
53
106
 
54
107
  /**
55
- * Get a namespace path array.
108
+ * Get a namespace path string.
56
109
  *
57
- * If it's already an array, return it as is.
58
- * If it's a string, split it into an array, with the `.` delimiter.
110
+ * If it's already a string, return it as is.
111
+ * If it's an array of strings, join the elements with a delimiter.
59
112
  *
60
113
  * @param {(string|string[])} ns - A dotted string, or array of paths.
61
- * @param {*} name - Name to use in the SOA error
62
- * @returns {string[]}
63
- * @alias module:@lumjs/core/obj.nsArray
114
+ * @param {(object|string)} [opts] Options.
115
+ *
116
+ * If this is a string, it will be used as `opts.name`.
117
+ *
118
+ * @param {string} [opts.name="Namespace"] Name to use in the SOA error.
119
+ * @param {(module:@lumjs/core/obj.NS~Format|Array)} [opts.format] Format.
120
+ *
121
+ * You can specify a single format, or an array of formats, in which case
122
+ * the canStringify() method will be called on each of them and the first one
123
+ * that returns true will be used. If none return true, the last one listed
124
+ * will be used.
125
+ *
126
+ * If this is not specified, then we will check for the legacy `opts.join`
127
+ * and/or `opts.prefix` options. If at least one of them was found an ad-hoc
128
+ * format using NS.Simple as a template will be created, composing the `opts`
129
+ * as overridden format object properties. As making a custom format is
130
+ * quite simple, both of the legacy options are deprecated.
131
+ *
132
+ * If neither this option nor any of the legacy options were specified,
133
+ * we will call the canStringify() method on Simple, JSPath, and Pointer
134
+ * (in that order), and use the first one that returns true.
135
+ *
136
+ * @param {string} [opts.join] Custom format delimiter character(s).
137
+ *
138
+ * This is **DEPRECATED** and will be removed in v2.x.
139
+ *
140
+ * @param {string} [opts.prefix] Custom format prefix.
141
+ *
142
+ * This is **DEPRECATED** and will be removed in v2.x.
143
+ *
144
+ * @returns {string}
145
+ * @throws {TypeError} If `ns` was not a valid value.
146
+ * @alias module:@lumjs/core/obj.nsString
64
147
  */
65
- function nsArray(ns, name='Namespace')
148
+ function nsString(ns, opts={})
66
149
  {
67
- if (typeof ns === S)
150
+ if (typeof opts === S) opts = {name: opts};
151
+
152
+ if (nonEmptyArray(ns))
68
153
  {
69
- return ns.split('.');
154
+ let format;
155
+
156
+ if (isFormat(opts.format) || Array.isArray(opts.format))
157
+ {
158
+ format = opts.format;
159
+ }
160
+ else if (typeof opts.join === S || typeof opts.prefix === S)
161
+ {
162
+ format = cp({}, NS.Simple, opts);
163
+ }
164
+ else
165
+ {
166
+ format = NS.Defaults.slice().reverse();
167
+ }
168
+
169
+ if (Array.isArray(format))
170
+ {
171
+ let formats = format;
172
+ for (format of formats)
173
+ {
174
+ if (isFormat(format) && format.canStringify(ns))
175
+ {
176
+ break;
177
+ }
178
+ }
179
+ }
180
+
181
+ if (!isFormat(format))
182
+ { // This shouldn't normally happen, but...
183
+ throw new TypeError("No valid format found");
184
+ }
185
+
186
+ return format.stringify(ns);
70
187
  }
71
- else if (!nonEmptyArray(ns))
188
+ else if (typeof ns !== S)
72
189
  {
73
- throw SOA(name);
190
+ throw SOA(opts.name ?? 'Namespace');
74
191
  }
75
192
  return ns;
76
193
  }
77
194
 
78
- exports.nsArray = nsArray;
195
+ exports.nsString = nsString;
79
196
 
80
197
  /**
81
198
  * Get a (nested) property from an object with a given path.
@@ -87,7 +204,10 @@ exports.nsArray = nsArray;
87
204
  *
88
205
  * @param {(object|boolean)} [opts] Options changing the behaviours.
89
206
  *
90
- * If this is a `boolean` it's assumed to be the `opts.log` option.
207
+ * If this is a `boolean` it's assumed to be the `opts.log` option;
208
+ * using a boolean is deprecated and will be removed in v2.x.
209
+ *
210
+ * Any options supported by nsArray() may also be specified here.
91
211
  *
92
212
  * @param {boolean} [opts.log=false] Log errors for missing namespaces?
93
213
  * @param {boolean} [opts.allowFun=true] Allow `obj` to be a `function` ?
@@ -109,7 +229,7 @@ function getObjectPath(obj, proppath, opts={})
109
229
 
110
230
  needObj(obj, (opts.allowFun ?? true));
111
231
 
112
- proppath = nsArray(proppath);
232
+ proppath = nsArray(proppath, opts);
113
233
 
114
234
  for (let p = 0; p < proppath.length; p++)
115
235
  {
@@ -138,7 +258,10 @@ exports.getObjectPath = getObjectPath;
138
258
  * @param {(string|Array)} proppath - Property path to create.
139
259
  * @param {(object|boolean)} [opts] Options changing the behaviours.
140
260
  *
141
- * If this is a `boolean` it's assumed to be the `opts.overwrite` option.
261
+ * If this is a `boolean` it's assumed to be the `opts.overwrite` option;
262
+ * using a boolean is deprecated and will be removed in v2.x.
263
+ *
264
+ * Any options supported by nsArray() may also be specified here.
142
265
  *
143
266
  * @param {*} [opts.value] A value to assign to the last property path.
144
267
  * @param {boolean} [opts.overwrite=false] Allow overwriting property paths.
@@ -181,7 +304,7 @@ function setObjectPath(obj, proppath, opts={})
181
304
  const setprop = opts.df ? df : def;
182
305
  const propopts = cp({}, opts.def, opts.df);
183
306
 
184
- proppath = nsArray(proppath);
307
+ proppath = nsArray(proppath, opts);
185
308
 
186
309
  let assign;
187
310
  if (opts.assign)
@@ -259,13 +382,13 @@ exports.setObjectPath = setObjectPath;
259
382
  * The last property name in the path will be the one that is deleted
260
383
  * from its parent object.
261
384
  *
262
- * @param {object} [opts] Options for `getObjectPath()`
385
+ * @param {object} [opts] Options for getObjectPath() and nsArray().
263
386
  * @returns {*} The value that was removed; or `undefined` if the
264
387
  * proppath didn't resolve to a defined value.
265
388
  */
266
389
  function delObjectPath(obj, proppath, opts={})
267
390
  {
268
- proppath = nsArray(proppath);
391
+ proppath = nsArray(proppath, opts);
269
392
  const rmProp = proppath.pop();
270
393
  const rmFrom = proppath.length
271
394
  ? getObjectPath(obj, proppath, opts)
@@ -286,9 +409,9 @@ exports.delObjectPath = delObjectPath;
286
409
  /**
287
410
  * Build a simple factory object for working with property paths.
288
411
  *
289
- * @param {(object|function)} value - The target object
290
- * @param {object} [opts] Default options for the *ObjectPath() functions
291
- * @returns {object} A frozen factory object
412
+ * @param {(object|function)} value - The target object.
413
+ * @param {object} [opts] Default options for the *ObjectPath() functions.
414
+ * @returns {object} A frozen factory object.
292
415
  *
293
416
  * Has `get(path,opts)`, `set(path,opts)`, and `del(path,opts)` methods,
294
417
  * which are wrappers for getObjectPath(), setObjectPath(),