jfather 0.2.0 → 0.3.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/README.md CHANGED
@@ -15,9 +15,10 @@
15
15
  ## Overview
16
16
 
17
17
  JFather is a utility library to **merge**, **extend** and **override**
18
- [JSON](https://www.json.org/json-fr.html "JavaScript Object Notation") objects.
18
+ [JSON](https://www.json.org/json-en.html "JavaScript Object Notation") objects.
19
19
 
20
- ```JavaScript
20
+ <!-- prettier-ignore-start -->
21
+ ```javascript
21
22
  import JFather from "jfather";
22
23
 
23
24
  // Merge two objects.
@@ -80,6 +81,7 @@ console.log(allIn);
80
81
  // "quote": "I'm no God. I'm not even a man. I'm just Molecule Man."
81
82
  // }
82
83
  ```
84
+ <!-- prettier-ignore-end -->
83
85
 
84
86
  ## Installation
85
87
 
@@ -89,7 +91,7 @@ JFather is published on [npm][link-npm] (its CDN:
89
91
  [UNPKG](https://unpkg.com/browse/jfather/)) and
90
92
  [Deno](https://deno.land/x/jfather).
91
93
 
92
- ```JavaScript
94
+ ```javascript
93
95
  // Node.js and Bun (after `npm install jfather`):
94
96
  import JFather from "jfather";
95
97
 
@@ -114,33 +116,33 @@ import JFather from "https://deno.land/x/jfather/mod.js";
114
116
  <th><code>JFather.merge(parent, child)</code></th>
115
117
  </tr>
116
118
  <tr>
117
- <td><pre lang="JSON"><code>1</code></pre></td>
118
- <td><pre lang="JSON"><code>2</code></pre></td>
119
- <td><pre lang="JSON"><code>2</code></pre></td>
119
+ <td><pre lang="json"><code>1</code></pre></td>
120
+ <td><pre lang="json"><code>2</code></pre></td>
121
+ <td><pre lang="json"><code>2</code></pre></td>
120
122
  </tr>
121
123
  <tr>
122
- <td><pre lang="JSON"><code>{
124
+ <td><pre lang="json"><code>{
123
125
  "foo": "alpha",
124
126
  "bar": "ALPHA"
125
127
  }</code></pre></td>
126
- <td><pre lang="JSON"><code>{
128
+ <td><pre lang="json"><code>{
127
129
  "foo": "beta",
128
130
  "baz": "BETA"
129
131
  }</code></pre></td>
130
- <td><pre lang="JSON"><code>{
132
+ <td><pre lang="json"><code>{
131
133
  "foo": "beta",
132
134
  "bar": "ALPHA",
133
135
  "baz": "BETA"
134
136
  }</code></pre></td>
135
137
  </tr>
136
138
  <tr>
137
- <td><pre lang="JSON"><code>{
139
+ <td><pre lang="json"><code>{
138
140
  "foo": [1, 10, 11]
139
141
  }</code></pre></td>
140
- <td><pre lang="JSON"><code>{
142
+ <td><pre lang="json"><code>{
141
143
  "foo": [2, 20, 22]
142
144
  }</code></pre></td>
143
- <td><pre lang="JSON"><code>{
145
+ <td><pre lang="json"><code>{
144
146
  "foo": [2, 20, 22]
145
147
  }</code></pre></td>
146
148
  </tr>
@@ -157,52 +159,52 @@ import JFather from "https://deno.land/x/jfather/mod.js";
157
159
  <th><code>await JFather.extend(child)</code></th>
158
160
  </tr>
159
161
  <tr>
160
- <td><pre lang="JSON"><code>{
162
+ <td><pre lang="json"><code>{
161
163
  "baz": "qux"
162
164
  }</code></pre></td>
163
- <td><pre lang="JSON"><code>{
165
+ <td><pre lang="json"><code>{
164
166
  "$extends": "https://foo.bar/parent.json"
165
167
  }</code></pre></td>
166
- <td><pre lang="JSON"><code>{
168
+ <td><pre lang="json"><code>{
167
169
  "baz": "qux"
168
170
  }</code></pre></td>
169
171
  </tr>
170
172
  <tr>
171
- <td><pre lang="JSON"><code>{
173
+ <td><pre lang="json"><code>{
172
174
  "baz": "qux"
173
175
  }</code></pre></td>
174
- <td><pre lang="JSON"><code>{
176
+ <td><pre lang="json"><code>{
175
177
  "$extends": "https://foo.bar/parent.json",
176
178
  "baz": "quux"
177
179
  }</code></pre></td>
178
- <td><pre lang="JSON"><code>{
180
+ <td><pre lang="json"><code>{
179
181
  "baz": "quux"
180
182
  }</code></pre></td>
181
183
  </tr>
182
184
  <tr>
183
- <td><pre lang="JSON"><code>{
185
+ <td><pre lang="json"><code>{
184
186
  "baz": "qux"
185
187
  }</code></pre></td>
186
- <td><pre lang="JSON"><code>{
188
+ <td><pre lang="json"><code>{
187
189
  "$extends": "https://foo.bar/parent.json",
188
190
  "quux": "corge"
189
191
  }</code></pre></td>
190
- <td><pre lang="JSON"><code>{
192
+ <td><pre lang="json"><code>{
191
193
  "baz": "qux",
192
194
  "quux": "corge"
193
195
  }</code></pre></td>
194
196
  </tr>
195
197
  <tr>
196
- <td><pre lang="JSON"><code>{
198
+ <td><pre lang="json"><code>{
197
199
  "baz": "qux"
198
200
  }</code></pre></td>
199
- <td><pre lang="JSON"><code>{
201
+ <td><pre lang="json"><code>{
200
202
  "quux": {
201
203
  "$extends": "https://foo.bar/parent.json",
202
204
  "corge": "grault"
203
205
  }
204
206
  }</code></pre></td>
205
- <td><pre lang="JSON"><code>{
207
+ <td><pre lang="json"><code>{
206
208
  "quux": {
207
209
  "baz": "qux",
208
210
  "corge": "grault"
@@ -210,17 +212,17 @@ import JFather from "https://deno.land/x/jfather/mod.js";
210
212
  }</code></pre></td>
211
213
  </tr>
212
214
  <tr>
213
- <td><pre lang="JSON"><code>{
215
+ <td><pre lang="json"><code>{
214
216
  "baz": {
215
217
  "qux": [1, 2],
216
218
  "quux": "a"
217
219
  },
218
220
  "corge": true
219
221
  }</code></pre></td>
220
- <td><pre lang="JSON"><code>{
222
+ <td><pre lang="json"><code>{
221
223
  "$extends": "https://foo.bar/parent.json#baz"
222
224
  }</code></pre></td>
223
- <td><pre lang="JSON"><code>{
225
+ <td><pre lang="json"><code>{
224
226
  "qux": [1, 2],
225
227
  "quux": "a"
226
228
  }</code></pre></td>
@@ -238,36 +240,42 @@ import JFather from "https://deno.land/x/jfather/mod.js";
238
240
  <th><code>JFather.merge(parent, child)</code></th>
239
241
  </tr>
240
242
  <tr>
241
- <td><pre lang="JSON"><code>{
243
+ <td><pre lang="json"><code>{
242
244
  "foo": ["a", "Alpha"]
243
245
  }</code></pre></td>
244
- <td><pre lang="JSON"><code>{
246
+ <td><pre lang="json"><code>{
245
247
  "$foo[]": ["b", "Beta"]
246
248
  }</code></pre></td>
247
- <td><pre lang="JSON"><code>{
249
+ <td><pre lang="json"><code>{
248
250
  "foo": ["a", "Alpha", "b", "Beta"]
249
251
  }</code></pre></td>
250
252
  </tr>
251
253
  <tr>
252
- <td><pre lang="JSON"><code>{
254
+ <td><pre lang="json"><code>{
253
255
  "foo": ["a", "Alpha"]
254
256
  }</code></pre></td>
255
- <td><pre lang="JSON"><code>{
257
+ <td><pre lang="json"><code>{
256
258
  "$foo[0]": "A"
257
259
  }</code></pre></td>
258
- <td><pre lang="JSON"><code>{
260
+ <td><pre lang="json"><code>{
259
261
  "foo": ["A", "Alpha"]
260
262
  }</code></pre></td>
261
263
  </tr>
262
264
  <tr>
263
- <td><pre lang="JSON"><code>{
264
- "foo": [{ "bar": ["a"] }]
265
+ <td><pre lang="json"><code>{
266
+ "foo": [{
267
+ "bar": ["a"]
268
+ }]
265
269
  }</code></pre></td>
266
- <td><pre lang="JSON"><code>{
267
- "$foo[0]": { "$bar[]": ["b", "c"] }
270
+ <td><pre lang="json"><code>{
271
+ "$foo[0]": {
272
+ "$bar[]": ["b", "c"]
273
+ }
268
274
  }</code></pre></td>
269
- <td><pre lang="JSON"><code>{
270
- "foo": [{ "bar": ["a", "b", "c"] }]
275
+ <td><pre lang="json"><code>{
276
+ "foo": [{
277
+ "bar": ["a", "b", "c"]
278
+ }]
271
279
  }</code></pre></td>
272
280
  </tr>
273
281
  </table>
@@ -284,7 +292,7 @@ import JFather from "https://deno.land/x/jfather/mod.js";
284
292
 
285
293
  Merge and override `parent` with `child`.
286
294
 
287
- ```JavaScript
295
+ ```javascript
288
296
  JFather.merge(parent, child);
289
297
  ```
290
298
 
@@ -297,41 +305,56 @@ JFather.merge(parent, child);
297
305
 
298
306
  Extend `obj`, merge and override.
299
307
 
300
- ```JavaScript
301
- JFather.extend(obj);
308
+ ```javascript
309
+ JFather.extend(obj, [options]);
302
310
  ```
303
311
 
304
312
  - Parameter:
305
313
  - `obj`: The object with any `$extends` properties.
314
+ - `options`:
315
+ - `request`: The function for getting a JSON object remotely. By default,
316
+ the object is got with
317
+ [`fetch()`](https://developer.mozilla.org/Web/API/fetch) and
318
+ [`Response.json()`](https://developer.mozilla.org/Web/API/Response/json).
306
319
  - Returns: A promise with the extended object.
307
320
 
308
321
  ### `load()`
309
322
 
310
323
  Load from a `url`, extend, merge and override.
311
324
 
312
- ```JavaScript
313
- JFather.load(url);
325
+ ```javascript
326
+ JFather.load(url, [options]);
314
327
  ```
315
328
 
316
329
  - Parameter:
317
330
  - `url`: The string containing the URL of a JSON file.
331
+ - `options`:
332
+ - `request`: The function for getting a JSON object remotely. By default,
333
+ the object is got with
334
+ [`fetch()`](https://developer.mozilla.org/Web/API/fetch) and
335
+ [`Response.json()`](https://developer.mozilla.org/Web/API/Response/json).
318
336
  - Returns: A promise with the loaded object.
319
337
 
320
338
  ### `parse()`
321
339
 
322
340
  Parse a `text`, extend, merge and override.
323
341
 
324
- ```JavaScript
325
- JFather.parse(text);
342
+ ```javascript
343
+ JFather.parse(text, [options]);
326
344
  ```
327
345
 
328
346
  - Parameter:
329
347
  - `text`: The string containing a JSON object.
348
+ - `options`:
349
+ - `request`: The function for getting a JSON object remotely. By default,
350
+ the object is got with
351
+ [`fetch()`](https://developer.mozilla.org/Web/API/fetch) and
352
+ [`Response.json()`](https://developer.mozilla.org/Web/API/Response/json).
330
353
  - Returns: A promise with the parsed object.
331
354
 
332
355
  [img-npm]: https://img.shields.io/npm/dm/jfather?label=npm&logo=npm&logoColor=whitesmoke
333
356
  [img-build]: https://img.shields.io/github/actions/workflow/status/regseb/jfather/ci.yml?branch=main&logo=github&logoColor=whitesmoke
334
- [img-coverage]: https://img.shields.io/endpoint?label=coverage&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fregseb%2Fjfather%2Fmain&logo=stryker&logoColor=whitesmoke
357
+ [img-coverage]: https://img.shields.io/endpoint?label=coverage&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fregseb%2Fjfather%2Fmain
335
358
  [img-semver]: https://img.shields.io/badge/semver-2.0.0-blue?logo=semver&logoColor=whitesmoke
336
359
  [link-npm]: https://www.npmjs.com/package/jfather
337
360
  [link-build]: https://github.com/regseb/jfather/actions/workflows/ci.yml?query=branch%3Amain
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jfather",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "JSON with merge, extend and override.",
5
5
  "keywords": [
6
6
  "jfather",
@@ -18,7 +18,10 @@
18
18
  },
19
19
  "license": "MIT",
20
20
  "author": "Sébastien Règne <regseb@gmail.com> (https://github.com/regseb)",
21
- "funding": "https://www.paypal.me/sebastienregne",
21
+ "funding": [
22
+ "https://buymeacoffee.com/regseb",
23
+ "https://www.paypal.me/sebastienregne"
24
+ ],
22
25
  "files": [
23
26
  "./src/",
24
27
  "./types/"
@@ -47,31 +50,32 @@
47
50
  },
48
51
  "devDependencies": {
49
52
  "@prantlf/jsonlint": "14.0.3",
50
- "@prettier/plugin-xml": "3.3.1",
53
+ "@prettier/plugin-xml": "3.4.1",
51
54
  "@stryker-mutator/core": "8.2.6",
52
55
  "@stryker-mutator/mocha-runner": "8.2.6",
53
56
  "@types/mocha": "10.0.6",
54
- "@types/node": "20.11.24",
57
+ "@types/node": "20.12.12",
55
58
  "@types/sinon": "17.0.3",
56
59
  "eslint": "8.57.0",
57
60
  "eslint-plugin-array-func": "4.0.0",
58
61
  "eslint-plugin-eslint-comments": "3.2.0",
59
62
  "eslint-plugin-import": "2.29.1",
60
- "eslint-plugin-jsdoc": "48.2.0",
61
- "eslint-plugin-mocha": "10.3.0",
62
- "eslint-plugin-n": "16.6.2",
63
+ "eslint-plugin-jsdoc": "48.2.5",
64
+ "eslint-plugin-mocha": "10.4.3",
65
+ "eslint-plugin-n": "17.7.0",
63
66
  "eslint-plugin-no-unsanitized": "4.0.2",
64
67
  "eslint-plugin-promise": "6.1.1",
65
- "eslint-plugin-regexp": "2.2.0",
66
- "eslint-plugin-unicorn": "51.0.1",
67
- "markdownlint": "0.33.0",
68
- "metalint": "0.15.0",
69
- "mocha": "10.3.0",
68
+ "eslint-plugin-regexp": "2.6.0",
69
+ "eslint-plugin-unicorn": "53.0.0",
70
+ "markdownlint": "0.34.0",
71
+ "metalint": "0.17.0",
72
+ "mocha": "10.4.0",
70
73
  "npm-package-json-lint": "7.1.0",
71
74
  "prettier": "3.2.5",
72
- "sinon": "17.0.1",
73
- "typedoc": "0.25.10",
74
- "typescript": "5.3.3",
75
+ "publint": "0.2.8",
76
+ "sinon": "18.0.0",
77
+ "typedoc": "0.25.13",
78
+ "typescript": "5.4.5",
75
79
  "yaml-lint": "1.7.0"
76
80
  },
77
81
  "engines": {
package/src/jfather.js CHANGED
@@ -4,6 +4,16 @@
4
4
  * @author Sébastien Règne
5
5
  */
6
6
 
7
+ /**
8
+ * Les options des fonctions de JFather.
9
+ *
10
+ * @typedef {Object} Options
11
+ * @prop {Function} [request] La fonction pour récupérer un objet JSON à
12
+ * distance. Par défaut, l'objet est récupéré avec
13
+ * <code>fetch()</code> et
14
+ * <code>Response.prototype.json()</code>
15
+ */
16
+
7
17
  /**
8
18
  * Exécute une fonction sur un objet et tous ses sous-objets (en partant des
9
19
  * objets les plus profonds).
@@ -163,48 +173,57 @@ export const merge = function (parent, child) {
163
173
  /**
164
174
  * Étendre un objet JSON en utilisant les propriétés <code>"$extends"</code>.
165
175
  *
166
- * @param {Record<string, any>} obj L'objet qui sera étendu.
176
+ * @param {Record<string, any>} obj L'objet qui sera étendu.
177
+ * @param {Options} [options] Les options.
167
178
  * @returns {Promise<Record<string, any>>} Une promesse contenant l'objet
168
179
  * étendu.
169
180
  */
170
- export const inherit = async function (obj) {
181
+ export const inherit = async function (obj, options) {
171
182
  if (undefined === obj.$extends) {
172
183
  return obj;
173
184
  }
174
185
 
175
186
  // eslint-disable-next-line no-use-before-define
176
- return merge(await load(obj.$extends), obj);
187
+ return merge(await load(obj.$extends, options), obj);
177
188
  };
178
189
 
179
190
  /**
180
191
  * Étendre un objet récursivement.
181
192
  *
182
- * @param {any} obj L'objet qui sera étendu.
193
+ * @param {any} obj L'objet qui sera étendu.
194
+ * @param {Options} [options] Les options.
183
195
  * @returns {Promise<any>} Une promesse contenant l'objet étendu.
184
196
  */
185
- export const extend = function (obj) {
186
- return walkAsync(obj, inherit);
197
+ export const extend = function (obj, options) {
198
+ return walkAsync(obj, (/** @type {any} */ v) => inherit(v, options));
187
199
  };
188
200
 
189
201
  /**
190
202
  * Charge un objet JSON depuis une URL.
191
203
  *
192
- * @param {string} url L'URL du fichier JSON.
204
+ * @param {string} url L'URL du fichier JSON.
205
+ * @param {Options} [options] Les options.
193
206
  * @returns {Promise<any>} Une promesse contenant l'objet.
194
207
  */
195
- export const load = async function (url) {
196
- const response = await fetch(url);
197
- const json = await response.json();
208
+ export const load = async function (url, options) {
209
+ let json;
210
+ if (undefined === options?.request) {
211
+ const response = await fetch(url);
212
+ json = await response.json();
213
+ } else {
214
+ json = await options.request(url);
215
+ }
198
216
  // Enlever le "#" dans le hash de l'URL.
199
- return await extend(query(json, new URL(url).hash.slice(1)));
217
+ return await extend(query(json, new URL(url).hash.slice(1)), options);
200
218
  };
201
219
 
202
220
  /**
203
221
  * Parse une chaine de caractères.
204
222
  *
205
- * @param {string} text La chaine de caractères qui sera parsée.
223
+ * @param {string} text La chaine de caractères qui sera parsée.
224
+ * @param {Options} [options] Les options.
206
225
  * @returns {Promise<any>} L'objet.
207
226
  */
208
- export const parse = function (text) {
209
- return extend(JSON.parse(text));
227
+ export const parse = function (text, options) {
228
+ return extend(JSON.parse(text), options);
210
229
  };
@@ -3,7 +3,19 @@ export function walkAsync(obj: any, fn: Function): Promise<any>;
3
3
  export function clone(obj: any): any;
4
4
  export function query(obj: Record<string, any>, chain: string): any;
5
5
  export function merge(parent: any, child: any): any;
6
- export function inherit(obj: Record<string, any>): Promise<Record<string, any>>;
7
- export function extend(obj: any): Promise<any>;
8
- export function load(url: string): Promise<any>;
9
- export function parse(text: string): Promise<any>;
6
+ export function inherit(obj: Record<string, any>, options?: Options): Promise<Record<string, any>>;
7
+ export function extend(obj: any, options?: Options): Promise<any>;
8
+ export function load(url: string, options?: Options): Promise<any>;
9
+ export function parse(text: string, options?: Options): Promise<any>;
10
+ /**
11
+ * Les options des fonctions de JFather.
12
+ */
13
+ export type Options = {
14
+ /**
15
+ * La fonction pour récupérer un objet JSON à
16
+ * distance. Par défaut, l'objet est récupéré avec
17
+ * <code>fetch()</code> et
18
+ * <code>Response.prototype.json()</code>
19
+ */
20
+ request?: Function;
21
+ };