jfather 0.3.0 → 0.4.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/LICENSE +1 -1
- package/README.md +276 -227
- package/package.json +26 -28
- package/src/jfather.js +12 -9
- package/types/jfather.d.ts +2 -3
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -5,17 +5,21 @@
|
|
|
5
5
|
<!-- markdownlint-disable-next-line no-inline-html-->
|
|
6
6
|
<img src="asset/logo.svg" align="right" alt="">
|
|
7
7
|
|
|
8
|
-
[![npm][img-npm]][link-npm]
|
|
9
|
-
[![
|
|
10
|
-
[![coverage][img-coverage]][link-coverage]
|
|
11
|
-
[![semver][img-semver]][link-semver]
|
|
8
|
+
[![npm][img-npm]][link-npm] [![build][img-build]][link-build]
|
|
9
|
+
[![coverage][img-coverage]][link-coverage] [![semver][img-semver]][link-semver]
|
|
12
10
|
|
|
13
11
|
> _Boys use JSON; Men use JFather._
|
|
14
12
|
|
|
15
13
|
## Overview
|
|
16
14
|
|
|
17
|
-
JFather is a
|
|
18
|
-
[JSON](https://www.json.org/json-en.html "JavaScript Object Notation")
|
|
15
|
+
JFather is a
|
|
16
|
+
[JSON](https://www.json.org/json-en.html "JavaScript Object Notation") utility
|
|
17
|
+
library to:
|
|
18
|
+
|
|
19
|
+
- [**merge**](#merge) deeply two JSON objects.
|
|
20
|
+
- [**extend**](#extend) a JSON objects with `"$extends"` property.
|
|
21
|
+
- [**override**](#override) an array with `"$foo[0]"` (replace a value) or
|
|
22
|
+
`"$foo[]"` (append values) properties.
|
|
19
23
|
|
|
20
24
|
<!-- prettier-ignore-start -->
|
|
21
25
|
```javascript
|
|
@@ -48,8 +52,8 @@ console.log(extended);
|
|
|
48
52
|
// "quote": "With great fist comes great KO"
|
|
49
53
|
// }
|
|
50
54
|
|
|
51
|
-
// Override an object.
|
|
52
|
-
const overridden =
|
|
55
|
+
// Override arrays of an object.
|
|
56
|
+
const overridden = JFather.merge(
|
|
53
57
|
{ "foo": ["a", "alpha"] },
|
|
54
58
|
{ "$foo[0]": "A", "$foo[]": ["BETA"] }
|
|
55
59
|
);
|
|
@@ -88,8 +92,8 @@ console.log(allIn);
|
|
|
88
92
|
JFather is published on [npm][link-npm] (its CDN:
|
|
89
93
|
[esm.sh](https://esm.sh/jfather),
|
|
90
94
|
[jsDelivr](https://www.jsdelivr.com/package/npm/jfather),
|
|
91
|
-
[UNPKG](https://unpkg.com/browse/jfather/))
|
|
92
|
-
[Deno](https://deno.land/x/jfather).
|
|
95
|
+
[UNPKG](https://unpkg.com/browse/jfather/)),
|
|
96
|
+
[JSR](https://jsr.io/@regseb/jfather) and [Deno](https://deno.land/x/jfather).
|
|
93
97
|
|
|
94
98
|
```javascript
|
|
95
99
|
// Node.js and Bun (after `npm install jfather`):
|
|
@@ -100,263 +104,308 @@ import JFather from "https://esm.sh/jfather@0";
|
|
|
100
104
|
import JFather from "https://cdn.jsdelivr.net/npm/jfather@0";
|
|
101
105
|
import JFather from "https://unpkg.com/jfather@0";
|
|
102
106
|
|
|
103
|
-
// Deno:
|
|
104
|
-
import JFather from "
|
|
107
|
+
// Deno (after `deno add jsr:@regseb/jfather`):
|
|
108
|
+
import JFather from "jsr:@regseb/jfather";
|
|
105
109
|
```
|
|
106
110
|
|
|
107
111
|
## Features
|
|
108
112
|
|
|
109
113
|
### Merge
|
|
110
114
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
"baz": "BETA"
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
"
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
"foo":
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
115
|
+
With any two variable types (except objects), merge returns the value of the
|
|
116
|
+
child. The following example shows how to use it with numbers: the result is `2`
|
|
117
|
+
(retrieved from the child value).
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
const parent = 1;
|
|
121
|
+
const child = 2;
|
|
122
|
+
console.log(JFather.merge(parent, child));
|
|
123
|
+
// 2
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
If both variables are objects, the object properties are merged one by one. In
|
|
127
|
+
this example, the `"foo"` property overwrites that of the parent. The properties
|
|
128
|
+
`"bar"` and `"baz"` are simply copied, as they are only in either the parent or
|
|
129
|
+
the child.
|
|
130
|
+
|
|
131
|
+
<!-- prettier-ignore-start -->
|
|
132
|
+
```javascript
|
|
133
|
+
const parent = { "foo": "alpha", "bar": "ALPHA" };
|
|
134
|
+
const child = { "foo": "beta", "baz": "BETA" };
|
|
135
|
+
console.log(JFather.merge(parent, child));
|
|
136
|
+
// { "foo": "beta", "bar": "ALPHA", "baz": "BETA" }
|
|
137
|
+
```
|
|
138
|
+
<!-- prettier-ignore-end -->
|
|
139
|
+
|
|
140
|
+
Merging is done recursively. The following example shows the merging of two
|
|
141
|
+
objects, which in turn contains the merging of the `"foo"` sub-objects.
|
|
142
|
+
|
|
143
|
+
<!-- prettier-ignore-start -->
|
|
144
|
+
```javascript
|
|
145
|
+
const parent = {
|
|
146
|
+
"foo": { "bar": 1, "baz": 2 },
|
|
147
|
+
"qux": "a"
|
|
148
|
+
};
|
|
149
|
+
const child = {
|
|
150
|
+
"foo": { "bar": 10, "quux": 20 },
|
|
151
|
+
"corge": "b"
|
|
152
|
+
};
|
|
153
|
+
console.log(JFather.merge(parent, child));
|
|
154
|
+
// {
|
|
155
|
+
// "foo": { "bar": 10, "baz": 2, "quux": 20 },
|
|
156
|
+
// "qux": "a",
|
|
157
|
+
// "corge": "b"
|
|
158
|
+
// }
|
|
159
|
+
```
|
|
160
|
+
<!-- prettier-ignore-end -->
|
|
161
|
+
|
|
162
|
+
Arrays are processed like any other type: the value of the child overrides that
|
|
163
|
+
of the parent. For more detailed merging, see the [_Override_](#override)
|
|
164
|
+
chapter, which shows how to merge arrays.
|
|
165
|
+
|
|
166
|
+
<!-- prettier-ignore-start -->
|
|
167
|
+
```javascript
|
|
168
|
+
const parent = { "foo": [1, 10, 11] };
|
|
169
|
+
const child = { "foo": [2, 20, 22] };
|
|
170
|
+
console.log(JFather.merge(parent, child));
|
|
171
|
+
// { "foo": [2, 20, 22] }
|
|
172
|
+
```
|
|
173
|
+
<!-- prettier-ignore-end -->
|
|
151
174
|
|
|
152
175
|
### Extend
|
|
153
176
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
"
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
<td><pre lang="json"><code>{
|
|
202
|
-
"quux": {
|
|
203
|
-
"$extends": "https://foo.bar/parent.json",
|
|
204
|
-
"corge": "grault"
|
|
205
|
-
}
|
|
206
|
-
}</code></pre></td>
|
|
207
|
-
<td><pre lang="json"><code>{
|
|
208
|
-
"quux": {
|
|
209
|
-
"baz": "qux",
|
|
210
|
-
"corge": "grault"
|
|
177
|
+
You can extend an object using the `"$extends"` property, which must link to a
|
|
178
|
+
JSON file. The remote JSON file and the current object will be merged.
|
|
179
|
+
|
|
180
|
+
In this example, the child object is empty (except for the `"$extends"`
|
|
181
|
+
property). The result therefore contains the parent object.
|
|
182
|
+
|
|
183
|
+
<!-- prettier-ignore-start -->
|
|
184
|
+
```javascript
|
|
185
|
+
// https://example.com/parent.json
|
|
186
|
+
// { "foo": 42 }
|
|
187
|
+
|
|
188
|
+
const obj = { "$extends": "https://example.com/parent.json" };
|
|
189
|
+
console.log(await JFather.extend(obj));
|
|
190
|
+
// { "foo": 42 }
|
|
191
|
+
```
|
|
192
|
+
<!-- prettier-ignore-end -->
|
|
193
|
+
|
|
194
|
+
As with merge, if a property is in both parent and child, the child's value is
|
|
195
|
+
used. Otherwise, both parent and child properties are added to the result.
|
|
196
|
+
|
|
197
|
+
<!-- prettier-ignore-start -->
|
|
198
|
+
```javascript
|
|
199
|
+
// https://example.com/parent.json
|
|
200
|
+
// { "foo": "A", "bar": "Alpha" }
|
|
201
|
+
|
|
202
|
+
const obj = {
|
|
203
|
+
"$extends": "https://example.com/parent.json",
|
|
204
|
+
"foo": "B",
|
|
205
|
+
"baz": "Beta"
|
|
206
|
+
};
|
|
207
|
+
console.log(await JFather.extend(obj));
|
|
208
|
+
// { "foo": "B", "bar": "Alpha", "baz": "Beta" }
|
|
209
|
+
```
|
|
210
|
+
<!-- prettier-ignore-end -->
|
|
211
|
+
|
|
212
|
+
It is possible to extend a child's sub-object. In the example below, the parent
|
|
213
|
+
is merged with the child's `"bar"` sub-object.
|
|
214
|
+
|
|
215
|
+
<!-- prettier-ignore-start -->
|
|
216
|
+
```javascript
|
|
217
|
+
// https://example.com/parent.json
|
|
218
|
+
// { "foo": 42 }
|
|
219
|
+
|
|
220
|
+
const obj = {
|
|
221
|
+
"bar": {
|
|
222
|
+
"$extends": "https://example.com/parent.json",
|
|
223
|
+
"baz": 3.14
|
|
211
224
|
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
225
|
+
};
|
|
226
|
+
console.log(await JFather.extend(obj));
|
|
227
|
+
// {
|
|
228
|
+
// "bar": { "foo": 42, "baz": 3.14 }
|
|
229
|
+
// }
|
|
230
|
+
```
|
|
231
|
+
<!-- prettier-ignore-end -->
|
|
232
|
+
|
|
233
|
+
In the parent link, you can define a path to retrieve a sub-object from the
|
|
234
|
+
parent. The path is set in the URL hash:
|
|
235
|
+
|
|
236
|
+
- `#foo`: the value of the `"foo"` property;
|
|
237
|
+
- `#foo.bar`: the value of the `"bar"` sub-property in the `"foo"` property;
|
|
238
|
+
- `#foo[42]`: the value of the forty-third array element in the `"foo"`
|
|
239
|
+
property;
|
|
240
|
+
- `#foo[0].bar`: the value of the sub-property `"bar"` in the first element of
|
|
241
|
+
the array in the property `"foo"`.
|
|
242
|
+
|
|
243
|
+
This example merges the `"foo"` property of the parent with the child.
|
|
244
|
+
|
|
245
|
+
<!-- prettier-ignore-start -->
|
|
246
|
+
```javascript
|
|
247
|
+
// https://example.com/parent.json
|
|
248
|
+
// {
|
|
249
|
+
// "foo": { "bar": [1, 2], "baz": "a" },
|
|
250
|
+
// "qux": true
|
|
251
|
+
// }
|
|
252
|
+
|
|
253
|
+
const obj = { "$extends": "https://example.com/parent.json#foo" };
|
|
254
|
+
console.log(await JFather.extend(obj));
|
|
255
|
+
// { "bar": [1, 2], "baz": "a" }
|
|
256
|
+
```
|
|
257
|
+
<!-- prettier-ignore-end -->
|
|
232
258
|
|
|
233
259
|
### Override
|
|
234
260
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
261
|
+
If an object has arrays, the merge overwrites the parent's array with the
|
|
262
|
+
child's. With the properties `"$foo[42]"` and `"$foo[]"`, you can refine the
|
|
263
|
+
merge.
|
|
264
|
+
|
|
265
|
+
In this example, the array `"foo"` is not overwritten. The first value of the
|
|
266
|
+
`"foo"` array is merged with the value of the child's `"$foo[0]"` property. And
|
|
267
|
+
the second value of `"foo"` is copied into the result.
|
|
268
|
+
|
|
269
|
+
<!-- prettier-ignore-start -->
|
|
270
|
+
```javascript
|
|
271
|
+
const parent = { "foo": ["a", "Alpha"] };
|
|
272
|
+
const child = { "$foo[0]": "B" };
|
|
273
|
+
console.log(JFather.merge(parent, child));
|
|
274
|
+
// { "foo": ["B", "Alpha"] }
|
|
275
|
+
```
|
|
276
|
+
<!-- prettier-ignore-end -->
|
|
277
|
+
|
|
278
|
+
With `"$foo[]"`, the child's values are added to those of the parent. In the
|
|
279
|
+
example below, the values `"b"` and `"Beta"` are added to the array of the
|
|
280
|
+
`"foo"` property.
|
|
281
|
+
|
|
282
|
+
<!-- prettier-ignore-start -->
|
|
283
|
+
```javascript
|
|
284
|
+
const parent = { "foo": ["a", "Alpha"] };
|
|
285
|
+
const child = { "$foo[]": ["b", "Beta"] };
|
|
286
|
+
console.log(JFather.merge(parent, child));
|
|
287
|
+
// { "foo": ["a", "Alpha", "b", "Beta"] }
|
|
288
|
+
```
|
|
289
|
+
<!-- prettier-ignore-end -->
|
|
290
|
+
|
|
291
|
+
You can combine the two overloads to, for example:
|
|
292
|
+
|
|
293
|
+
- merge the first value of the parent's `"foo"` array with the value of the
|
|
294
|
+
child's `"$foo[0]"` property;
|
|
295
|
+
- add the values `"b"` and `"c"` to the array of the sub-property `"bar"`.
|
|
296
|
+
|
|
297
|
+
<!-- prettier-ignore-start -->
|
|
298
|
+
```javascript
|
|
299
|
+
const parent = {
|
|
266
300
|
"foo": [{
|
|
267
301
|
"bar": ["a"]
|
|
268
302
|
}]
|
|
269
|
-
}
|
|
270
|
-
|
|
303
|
+
};
|
|
304
|
+
const child = {
|
|
271
305
|
"$foo[0]": {
|
|
272
306
|
"$bar[]": ["b", "c"]
|
|
273
307
|
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
<!--
|
|
308
|
+
};
|
|
309
|
+
console.log(JFather.merge(parent, child));
|
|
310
|
+
// {
|
|
311
|
+
// "foo": [{
|
|
312
|
+
// "bar": ["a", "b", "c"]
|
|
313
|
+
// }]
|
|
314
|
+
// }
|
|
315
|
+
```
|
|
316
|
+
<!-- prettier-ignore-end -->
|
|
317
|
+
|
|
318
|
+
If the child overloads a property that does not exist in the parent, the
|
|
319
|
+
overload is ignored. The overload is also ignored if the parent object is not an
|
|
320
|
+
array. In the following example, the child has two overloads which are ignored:
|
|
321
|
+
the overload on the property `"bar"` which is not an array, and the overload on
|
|
322
|
+
`"baz"` which does not exist in the parent.
|
|
323
|
+
|
|
324
|
+
<!-- prettier-ignore-start -->
|
|
325
|
+
```javascript
|
|
326
|
+
const parent = { "foo": ["a", "A"], "bar": 42 };
|
|
327
|
+
const child = { "$bar[0]": 3.14, "$baz[]": ["beta"] };
|
|
328
|
+
console.log(JFather.merge(parent, child));
|
|
329
|
+
// { "foo": ["a", "A"], "bar": 42 }
|
|
330
|
+
```
|
|
331
|
+
<!-- prettier-ignore-end -->
|
|
283
332
|
|
|
284
333
|
## API
|
|
285
334
|
|
|
286
|
-
- [`merge()`](#
|
|
287
|
-
- [`extend()`](#
|
|
288
|
-
- [`load()`](#
|
|
289
|
-
- [`parse()`](#
|
|
335
|
+
- [`JFather.merge(parent, child)`](#jfathermergeparent-child)
|
|
336
|
+
- [`JFather.extend(obj, [options])`](#jfatherextendobj-options)
|
|
337
|
+
- [`JFather.load(url, [options])`](#jfatherloadurl-options)
|
|
338
|
+
- [`JFather.parse(text, [options])`](#jfatherparsetext-options)
|
|
290
339
|
|
|
291
|
-
### `merge()`
|
|
340
|
+
### `JFather.merge(parent, child)`
|
|
292
341
|
|
|
293
342
|
Merge and override `parent` with `child`.
|
|
294
343
|
|
|
295
|
-
```javascript
|
|
296
|
-
JFather.merge(parent, child);
|
|
297
|
-
```
|
|
298
|
-
|
|
299
344
|
- Parameters:
|
|
300
|
-
- `parent
|
|
301
|
-
- `child
|
|
302
|
-
- Returns: The merged object.
|
|
345
|
+
- `parent` [`<any>`][mdn-any] The parent object.
|
|
346
|
+
- `child` [`<any>`][mdn-any] The child object.
|
|
347
|
+
- Returns: [`<any>`][mdn-any] The merged object.
|
|
303
348
|
|
|
304
|
-
### `extend()`
|
|
349
|
+
### `JFather.extend(obj, [options])`
|
|
305
350
|
|
|
306
351
|
Extend `obj`, merge and override.
|
|
307
352
|
|
|
308
|
-
```javascript
|
|
309
|
-
JFather.extend(obj, [options]);
|
|
310
|
-
```
|
|
311
|
-
|
|
312
353
|
- Parameter:
|
|
313
|
-
- `obj
|
|
314
|
-
- `options
|
|
315
|
-
- `request
|
|
316
|
-
the object is got with
|
|
317
|
-
[`
|
|
318
|
-
|
|
319
|
-
- Returns: A promise with the extended object.
|
|
354
|
+
- `obj` [`<any>`][mdn-any] The object with any `$extends` properties.
|
|
355
|
+
- `options` [`<Object>`][mdn-object]
|
|
356
|
+
- `request` [`<Function>`][mdn-function] The function for getting a JSON
|
|
357
|
+
object remotely. By default, the object is got with [`fetch()`][mdn-fetch]
|
|
358
|
+
and [`Response.json()`][mdn-response-json].
|
|
359
|
+
- Returns: [`<Promise>`][mdn-promise] A promise with the extended object.
|
|
320
360
|
|
|
321
|
-
### `load()`
|
|
361
|
+
### `JFather.load(url, [options])`
|
|
322
362
|
|
|
323
|
-
Load from
|
|
324
|
-
|
|
325
|
-
```javascript
|
|
326
|
-
JFather.load(url, [options]);
|
|
327
|
-
```
|
|
363
|
+
Load from an `url`, extend, merge and override.
|
|
328
364
|
|
|
329
365
|
- Parameter:
|
|
330
|
-
- `url
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
[`fetch()`]
|
|
335
|
-
[`Response.json()`]
|
|
336
|
-
- Returns: A promise with the loaded object.
|
|
366
|
+
- `url` [`<String>`][mdn-string] | [`<URL>`][mdn-url] The string containing
|
|
367
|
+
the URL of a JSON file.
|
|
368
|
+
- `options` [`<Object>`][mdn-object]
|
|
369
|
+
- `request` [`<Function>`][mdn-function] The function for getting a JSON
|
|
370
|
+
object remotely. By default, the object is got with [`fetch()`][mdn-fetch]
|
|
371
|
+
and [`Response.json()`][mdn-response-json].
|
|
372
|
+
- Returns: [`<Promise>`][mdn-promise] A promise with the loaded object.
|
|
337
373
|
|
|
338
|
-
### `parse()`
|
|
374
|
+
### `JFather.parse(text, [options])`
|
|
339
375
|
|
|
340
376
|
Parse a `text`, extend, merge and override.
|
|
341
377
|
|
|
342
|
-
```javascript
|
|
343
|
-
JFather.parse(text, [options]);
|
|
344
|
-
```
|
|
345
|
-
|
|
346
378
|
- Parameter:
|
|
347
|
-
- `text
|
|
348
|
-
- `options
|
|
349
|
-
- `request
|
|
350
|
-
the object is got with
|
|
351
|
-
[`
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
[
|
|
356
|
-
|
|
357
|
-
[
|
|
358
|
-
|
|
379
|
+
- `text` [`<String>`][mdn-string] The string containing a JSON object.
|
|
380
|
+
- `options` [`<Object>`][mdn-object]
|
|
381
|
+
- `request` [`<Function>`][mdn-function] The function for getting a JSON
|
|
382
|
+
object remotely. By default, the object is got with [`fetch()`][mdn-fetch]
|
|
383
|
+
and [`Response.json()`][mdn-response-json].
|
|
384
|
+
- Returns: [`<Promise>`][mdn-promise] A promise with the parsed object.
|
|
385
|
+
|
|
386
|
+
[mdn-any]: https://developer.mozilla.org/Web/JavaScript/Data_structures
|
|
387
|
+
[mdn-function]:
|
|
388
|
+
https://developer.mozilla.org/JavaScript/Reference/Global_Objects/Function
|
|
389
|
+
[mdn-object]:
|
|
390
|
+
https://developer.mozilla.org/JavaScript/Reference/Global_Objects/Object
|
|
391
|
+
[mdn-promise]:
|
|
392
|
+
https://developer.mozilla.org/JavaScript/Reference/Global_Objects/Promise
|
|
393
|
+
[mdn-string]:
|
|
394
|
+
https://developer.mozilla.org/JavaScript/Reference/Global_Objects/String
|
|
395
|
+
[mdn-fetch]: https://developer.mozilla.org/Web/API/fetch
|
|
396
|
+
[mdn-response-json]: https://developer.mozilla.org/Web/API/Response/json
|
|
397
|
+
[mdn-url]: https://developer.mozilla.org/Web/API/URL
|
|
398
|
+
[img-npm]:
|
|
399
|
+
https://img.shields.io/npm/dm/jfather?label=npm&logo=npm&logoColor=whitesmoke
|
|
400
|
+
[img-build]:
|
|
401
|
+
https://img.shields.io/github/actions/workflow/status/regseb/jfather/ci.yml?branch=main&logo=github&logoColor=whitesmoke
|
|
402
|
+
[img-coverage]:
|
|
403
|
+
https://img.shields.io/endpoint?label=coverage&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fregseb%2Fjfather%2Fmain
|
|
404
|
+
[img-semver]:
|
|
405
|
+
https://img.shields.io/badge/semver-2.0.0-blue?logo=semver&logoColor=whitesmoke
|
|
359
406
|
[link-npm]: https://www.npmjs.com/package/jfather
|
|
360
|
-
[link-build]:
|
|
361
|
-
|
|
407
|
+
[link-build]:
|
|
408
|
+
https://github.com/regseb/jfather/actions/workflows/ci.yml?query=branch%3Amain
|
|
409
|
+
[link-coverage]:
|
|
410
|
+
https://dashboard.stryker-mutator.io/reports/github.com/regseb/jfather/main
|
|
362
411
|
[link-semver]: https://semver.org/spec/v2.0.0.html "Semantic Versioning 2.0.0"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jfather",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "JSON with merge, extend and override.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jfather",
|
|
@@ -42,43 +42,41 @@
|
|
|
42
42
|
"lint:fix": "metalint --fix",
|
|
43
43
|
"lint:types": "tsc --project .tsconfig_lint.json",
|
|
44
44
|
"test": "npm run test:coverage",
|
|
45
|
-
"test:unit": "
|
|
45
|
+
"test:unit": "node --test",
|
|
46
46
|
"test:coverage": "stryker run",
|
|
47
47
|
"jsdocs": "typedoc --tsconfig .tsconfig_jsdocs.json",
|
|
48
48
|
"prepare": "tsc --project .tsconfig_types.json",
|
|
49
49
|
"clean": "node .script/clean.js"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@prantlf/jsonlint": "
|
|
52
|
+
"@prantlf/jsonlint": "16.0.0",
|
|
53
53
|
"@prettier/plugin-xml": "3.4.1",
|
|
54
|
-
"@stryker-mutator/core": "8.
|
|
55
|
-
"@stryker-mutator/
|
|
56
|
-
"@types/mocha": "10.0
|
|
57
|
-
"@types/node": "
|
|
58
|
-
"
|
|
59
|
-
"eslint": "
|
|
60
|
-
"eslint-plugin-array-func": "4.0.0",
|
|
54
|
+
"@stryker-mutator/core": "8.7.1",
|
|
55
|
+
"@stryker-mutator/tap-runner": "8.7.1",
|
|
56
|
+
"@types/eslint-plugin-mocha": "10.4.0",
|
|
57
|
+
"@types/node": "22.10.5",
|
|
58
|
+
"eslint": "9.17.0",
|
|
59
|
+
"eslint-plugin-array-func": "5.0.2",
|
|
61
60
|
"eslint-plugin-eslint-comments": "3.2.0",
|
|
62
|
-
"eslint-plugin-import": "2.
|
|
63
|
-
"eslint-plugin-jsdoc": "
|
|
64
|
-
"eslint-plugin-mocha": "10.
|
|
65
|
-
"eslint-plugin-n": "17.
|
|
66
|
-
"eslint-plugin-no-unsanitized": "4.
|
|
67
|
-
"eslint-plugin-promise": "
|
|
68
|
-
"eslint-plugin-regexp": "2.
|
|
69
|
-
"eslint-plugin-unicorn": "
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"npm-package-json-lint": "
|
|
74
|
-
"prettier": "3.2
|
|
75
|
-
"publint": "0.2.
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"typescript": "5.4.5",
|
|
61
|
+
"eslint-plugin-import": "2.31.0",
|
|
62
|
+
"eslint-plugin-jsdoc": "50.6.1",
|
|
63
|
+
"eslint-plugin-mocha": "10.5.0",
|
|
64
|
+
"eslint-plugin-n": "17.15.1",
|
|
65
|
+
"eslint-plugin-no-unsanitized": "4.1.2",
|
|
66
|
+
"eslint-plugin-promise": "7.2.1",
|
|
67
|
+
"eslint-plugin-regexp": "2.7.0",
|
|
68
|
+
"eslint-plugin-unicorn": "56.0.1",
|
|
69
|
+
"globals": "15.14.0",
|
|
70
|
+
"markdownlint": "0.37.3",
|
|
71
|
+
"metalint": "0.19.0",
|
|
72
|
+
"npm-package-json-lint": "8.0.0",
|
|
73
|
+
"prettier": "3.4.2",
|
|
74
|
+
"publint": "0.2.12",
|
|
75
|
+
"typedoc": "0.27.6",
|
|
76
|
+
"typescript": "5.7.2",
|
|
79
77
|
"yaml-lint": "1.7.0"
|
|
80
78
|
},
|
|
81
79
|
"engines": {
|
|
82
|
-
"node": ">=20.
|
|
80
|
+
"node": ">=20.18"
|
|
83
81
|
}
|
|
84
82
|
}
|
package/src/jfather.js
CHANGED
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
* @typedef {Object} Options
|
|
11
11
|
* @prop {Function} [request] La fonction pour récupérer un objet JSON à
|
|
12
12
|
* distance. Par défaut, l'objet est récupéré avec
|
|
13
|
-
*
|
|
14
|
-
* <code>Response.prototype.json()</code>
|
|
13
|
+
* `fetch()` et `Response.json()`.
|
|
15
14
|
*/
|
|
16
15
|
|
|
17
16
|
/**
|
|
@@ -90,11 +89,11 @@ export const query = function (obj, chain) {
|
|
|
90
89
|
return obj;
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
const re = /^\.(?<prop>\w+)|^\[(?<index>\d+)\]/
|
|
92
|
+
const re = /^\.(?<prop>\w+)|^\[(?<index>\d+)\]/v;
|
|
94
93
|
const sub = {
|
|
95
94
|
obj,
|
|
96
95
|
// Préfixer le chemin avec un point si nécessaire.
|
|
97
|
-
chain: /^[
|
|
96
|
+
chain: /^[.\[]/v.test(chain) ? chain : "." + chain,
|
|
98
97
|
};
|
|
99
98
|
while (0 !== sub.chain.length) {
|
|
100
99
|
const result = re.exec(sub.chain);
|
|
@@ -119,7 +118,11 @@ export const query = function (obj, chain) {
|
|
|
119
118
|
* @returns {any} La fusion des deux objets.
|
|
120
119
|
*/
|
|
121
120
|
export const merge = function (parent, child) {
|
|
122
|
-
if (
|
|
121
|
+
if (
|
|
122
|
+
child === parent ||
|
|
123
|
+
Object !== parent?.constructor ||
|
|
124
|
+
Object !== child?.constructor
|
|
125
|
+
) {
|
|
123
126
|
return clone(child);
|
|
124
127
|
}
|
|
125
128
|
|
|
@@ -150,7 +153,7 @@ export const merge = function (parent, child) {
|
|
|
150
153
|
if (Array.isArray(overridden[key])) {
|
|
151
154
|
const overelemRegex = new RegExp(
|
|
152
155
|
`^\\$${key}\\[(?<index>\\d*)\\]$`,
|
|
153
|
-
"
|
|
156
|
+
"v",
|
|
154
157
|
);
|
|
155
158
|
const overelems = Object.entries(child)
|
|
156
159
|
.map(([k, v]) => [overelemRegex.exec(k)?.groups?.index, v])
|
|
@@ -171,7 +174,7 @@ export const merge = function (parent, child) {
|
|
|
171
174
|
};
|
|
172
175
|
|
|
173
176
|
/**
|
|
174
|
-
* Étendre un objet JSON en utilisant
|
|
177
|
+
* Étendre un objet JSON en utilisant la propriété `"$extends"`.
|
|
175
178
|
*
|
|
176
179
|
* @param {Record<string, any>} obj L'objet qui sera étendu.
|
|
177
180
|
* @param {Options} [options] Les options.
|
|
@@ -201,8 +204,8 @@ export const extend = function (obj, options) {
|
|
|
201
204
|
/**
|
|
202
205
|
* Charge un objet JSON depuis une URL.
|
|
203
206
|
*
|
|
204
|
-
* @param {string}
|
|
205
|
-
* @param {Options}
|
|
207
|
+
* @param {string|URL} url L'URL du fichier JSON.
|
|
208
|
+
* @param {Options} [options] Les options.
|
|
206
209
|
* @returns {Promise<any>} Une promesse contenant l'objet.
|
|
207
210
|
*/
|
|
208
211
|
export const load = async function (url, options) {
|
package/types/jfather.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export function query(obj: Record<string, any>, chain: string): any;
|
|
|
5
5
|
export function merge(parent: any, child: any): any;
|
|
6
6
|
export function inherit(obj: Record<string, any>, options?: Options): Promise<Record<string, any>>;
|
|
7
7
|
export function extend(obj: any, options?: Options): Promise<any>;
|
|
8
|
-
export function load(url: string, options?: Options): Promise<any>;
|
|
8
|
+
export function load(url: string | URL, options?: Options): Promise<any>;
|
|
9
9
|
export function parse(text: string, options?: Options): Promise<any>;
|
|
10
10
|
/**
|
|
11
11
|
* Les options des fonctions de JFather.
|
|
@@ -14,8 +14,7 @@ export type Options = {
|
|
|
14
14
|
/**
|
|
15
15
|
* La fonction pour récupérer un objet JSON à
|
|
16
16
|
* distance. Par défaut, l'objet est récupéré avec
|
|
17
|
-
*
|
|
18
|
-
* <code>Response.prototype.json()</code>
|
|
17
|
+
* `fetch()` et `Response.json()`.
|
|
19
18
|
*/
|
|
20
19
|
request?: Function;
|
|
21
20
|
};
|