selectic 3.0.10 → 3.0.15

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
@@ -2,6 +2,7 @@
2
2
 
3
3
  > VueJS 3.X + Typescript + JSX + Select
4
4
 
5
+ [![npm](https://img.shields.io/npm/v/selectic.svg)](https://www.npmjs.com/package/selectic)
5
6
 
6
7
  ## Introduction
7
8
 
@@ -38,10 +38,12 @@ styleInject(css_248z);
38
38
  /**
39
39
  * Clone the object and its inner properties.
40
40
  * @param obj The object to be clone.
41
+ * @param attributes list of attributes to not clone.
41
42
  * @param refs internal reference to object to avoid cyclic references
42
43
  * @returns a copy of obj
43
44
  */
44
- function deepClone(obj, refs = new WeakMap()) {
45
+ function deepClone(origObject, ignoreAttributes = [], refs = new WeakMap()) {
46
+ const obj = vue.unref(origObject);
45
47
  /* For circular references */
46
48
  if (refs.has(obj)) {
47
49
  return refs.get(obj);
@@ -54,7 +56,7 @@ function deepClone(obj, refs = new WeakMap()) {
54
56
  const ref = [];
55
57
  refs.set(obj, ref);
56
58
  obj.forEach((val, idx) => {
57
- ref[idx] = deepClone(val, refs);
59
+ ref[idx] = deepClone(val, ignoreAttributes, refs);
58
60
  });
59
61
  return ref;
60
62
  }
@@ -67,7 +69,11 @@ function deepClone(obj, refs = new WeakMap()) {
67
69
  const ref = {};
68
70
  refs.set(obj, ref);
69
71
  for (const [key, val] of Object.entries(obj)) {
70
- ref[key] = deepClone(val, refs);
72
+ if (ignoreAttributes.includes(key)) {
73
+ ref[key] = val;
74
+ continue;
75
+ }
76
+ ref[key] = deepClone(val, ignoreAttributes, refs);
71
77
  }
72
78
  return ref;
73
79
  }
@@ -294,7 +300,7 @@ class SelecticStore {
294
300
  const value = deepClone(this.props.value);
295
301
  /* set initial value for non reactive attribute */
296
302
  this.cacheRequest = new Map();
297
- const stateParam = deepClone(this.props.params);
303
+ const stateParam = deepClone(this.props.params, ['data']);
298
304
  if (stateParam.optionBehavior) {
299
305
  this.buildOptionBehavior(stateParam.optionBehavior, stateParam);
300
306
  delete stateParam.optionBehavior;
@@ -684,7 +690,7 @@ class SelecticStore {
684
690
  }
685
691
  /* This method is for the computed property listOptions */
686
692
  getListOptions() {
687
- const options = deepClone(this.props.options);
693
+ const options = deepClone(this.props.options, ['data']);
688
694
  const listOptions = [];
689
695
  if (!Array.isArray(options)) {
690
696
  return listOptions;
@@ -721,7 +727,7 @@ class SelecticStore {
721
727
  }
722
728
  /* This method is for the computed property elementOptions */
723
729
  getElementOptions() {
724
- const options = deepClone(this.props.childOptions);
730
+ const options = deepClone(this.props.childOptions, ['data']);
725
731
  const childOptions = [];
726
732
  if (!Array.isArray(options) || options.length === 0) {
727
733
  return childOptions;
@@ -2114,7 +2120,7 @@ let Selectic = class Selectic extends vtyx.Vue {
2114
2120
  }];
2115
2121
  }
2116
2122
  get hasGivenValue() {
2117
- const value = this.value;
2123
+ const value = vue.unref(this.value);
2118
2124
  return value !== null && value !== undefined;
2119
2125
  }
2120
2126
  get defaultValue() {
@@ -2259,7 +2265,7 @@ let Selectic = class Selectic extends vtyx.Vue {
2259
2265
  this.store.props.selectionIsExcluded = this.selectionIsExcluded;
2260
2266
  }
2261
2267
  onOptionsChange() {
2262
- this.store.props.options = deepClone(this.options);
2268
+ this.store.props.options = deepClone(this.options, ['data']);
2263
2269
  }
2264
2270
  onTextsChange() {
2265
2271
  const texts = this.texts;
@@ -2434,12 +2440,12 @@ let Selectic = class Selectic extends vtyx.Vue {
2434
2440
  var _a, _b, _c;
2435
2441
  this._elementsListeners = [];
2436
2442
  this.store = new SelecticStore({
2437
- options: this.options,
2438
- value: this.value,
2443
+ options: deepClone(this.options, ['data']),
2444
+ value: deepClone(this.value),
2439
2445
  selectionIsExcluded: this.selectionIsExcluded,
2440
2446
  disabled: this.disabled,
2441
2447
  texts: this.texts,
2442
- groups: this.groups,
2448
+ groups: deepClone(this.groups),
2443
2449
  keepOpenWithOtherSelectic: !!this.params.keepOpenWithOtherSelectic,
2444
2450
  params: {
2445
2451
  multiple: ((_a = this.multiple) !== null && _a !== void 0 ? _a : false) !== false,
@@ -2606,13 +2612,7 @@ __decorate([
2606
2612
  vtyx.Watch('store.state.internalValue', { deep: true })
2607
2613
  ], Selectic.prototype, "onInternalValueChange", null);
2608
2614
  __decorate([
2609
- vtyx.Emit('input'),
2610
- vtyx.Emit('change'),
2611
- vtyx.Emit('open'),
2612
- vtyx.Emit('focus'),
2613
- vtyx.Emit('close'),
2614
- vtyx.Emit('blur'),
2615
- vtyx.Emit('item:click')
2615
+ vtyx.Emits(['input', 'change', 'open', 'focus', 'close', 'blur', 'item:click'])
2616
2616
  ], Selectic.prototype, "render", null);
2617
2617
  Selectic = __decorate([
2618
2618
  vtyx.Component
@@ -1,5 +1,5 @@
1
- import { Prop, Watch, Component, Vue, h, Emit } from 'vtyx';
2
- import { reactive, computed, unref, watch } from 'vue';
1
+ import { Prop, Watch, Component, Vue, h, Emits } from 'vtyx';
2
+ import { unref, reactive, computed, watch } from 'vue';
3
3
 
4
4
  function styleInject(css, ref) {
5
5
  if ( ref === void 0 ) ref = {};
@@ -34,10 +34,12 @@ styleInject(css_248z);
34
34
  /**
35
35
  * Clone the object and its inner properties.
36
36
  * @param obj The object to be clone.
37
+ * @param attributes list of attributes to not clone.
37
38
  * @param refs internal reference to object to avoid cyclic references
38
39
  * @returns a copy of obj
39
40
  */
40
- function deepClone(obj, refs = new WeakMap()) {
41
+ function deepClone(origObject, ignoreAttributes = [], refs = new WeakMap()) {
42
+ const obj = unref(origObject);
41
43
  /* For circular references */
42
44
  if (refs.has(obj)) {
43
45
  return refs.get(obj);
@@ -50,7 +52,7 @@ function deepClone(obj, refs = new WeakMap()) {
50
52
  const ref = [];
51
53
  refs.set(obj, ref);
52
54
  obj.forEach((val, idx) => {
53
- ref[idx] = deepClone(val, refs);
55
+ ref[idx] = deepClone(val, ignoreAttributes, refs);
54
56
  });
55
57
  return ref;
56
58
  }
@@ -63,7 +65,11 @@ function deepClone(obj, refs = new WeakMap()) {
63
65
  const ref = {};
64
66
  refs.set(obj, ref);
65
67
  for (const [key, val] of Object.entries(obj)) {
66
- ref[key] = deepClone(val, refs);
68
+ if (ignoreAttributes.includes(key)) {
69
+ ref[key] = val;
70
+ continue;
71
+ }
72
+ ref[key] = deepClone(val, ignoreAttributes, refs);
67
73
  }
68
74
  return ref;
69
75
  }
@@ -290,7 +296,7 @@ class SelecticStore {
290
296
  const value = deepClone(this.props.value);
291
297
  /* set initial value for non reactive attribute */
292
298
  this.cacheRequest = new Map();
293
- const stateParam = deepClone(this.props.params);
299
+ const stateParam = deepClone(this.props.params, ['data']);
294
300
  if (stateParam.optionBehavior) {
295
301
  this.buildOptionBehavior(stateParam.optionBehavior, stateParam);
296
302
  delete stateParam.optionBehavior;
@@ -680,7 +686,7 @@ class SelecticStore {
680
686
  }
681
687
  /* This method is for the computed property listOptions */
682
688
  getListOptions() {
683
- const options = deepClone(this.props.options);
689
+ const options = deepClone(this.props.options, ['data']);
684
690
  const listOptions = [];
685
691
  if (!Array.isArray(options)) {
686
692
  return listOptions;
@@ -717,7 +723,7 @@ class SelecticStore {
717
723
  }
718
724
  /* This method is for the computed property elementOptions */
719
725
  getElementOptions() {
720
- const options = deepClone(this.props.childOptions);
726
+ const options = deepClone(this.props.childOptions, ['data']);
721
727
  const childOptions = [];
722
728
  if (!Array.isArray(options) || options.length === 0) {
723
729
  return childOptions;
@@ -2110,7 +2116,7 @@ let Selectic = class Selectic extends Vue {
2110
2116
  }];
2111
2117
  }
2112
2118
  get hasGivenValue() {
2113
- const value = this.value;
2119
+ const value = unref(this.value);
2114
2120
  return value !== null && value !== undefined;
2115
2121
  }
2116
2122
  get defaultValue() {
@@ -2255,7 +2261,7 @@ let Selectic = class Selectic extends Vue {
2255
2261
  this.store.props.selectionIsExcluded = this.selectionIsExcluded;
2256
2262
  }
2257
2263
  onOptionsChange() {
2258
- this.store.props.options = deepClone(this.options);
2264
+ this.store.props.options = deepClone(this.options, ['data']);
2259
2265
  }
2260
2266
  onTextsChange() {
2261
2267
  const texts = this.texts;
@@ -2430,12 +2436,12 @@ let Selectic = class Selectic extends Vue {
2430
2436
  var _a, _b, _c;
2431
2437
  this._elementsListeners = [];
2432
2438
  this.store = new SelecticStore({
2433
- options: this.options,
2434
- value: this.value,
2439
+ options: deepClone(this.options, ['data']),
2440
+ value: deepClone(this.value),
2435
2441
  selectionIsExcluded: this.selectionIsExcluded,
2436
2442
  disabled: this.disabled,
2437
2443
  texts: this.texts,
2438
- groups: this.groups,
2444
+ groups: deepClone(this.groups),
2439
2445
  keepOpenWithOtherSelectic: !!this.params.keepOpenWithOtherSelectic,
2440
2446
  params: {
2441
2447
  multiple: ((_a = this.multiple) !== null && _a !== void 0 ? _a : false) !== false,
@@ -2602,13 +2608,7 @@ __decorate([
2602
2608
  Watch('store.state.internalValue', { deep: true })
2603
2609
  ], Selectic.prototype, "onInternalValueChange", null);
2604
2610
  __decorate([
2605
- Emit('input'),
2606
- Emit('change'),
2607
- Emit('open'),
2608
- Emit('focus'),
2609
- Emit('close'),
2610
- Emit('blur'),
2611
- Emit('item:click')
2611
+ Emits(['input', 'change', 'open', 'focus', 'close', 'blur', 'item:click'])
2612
2612
  ], Selectic.prototype, "render", null);
2613
2613
  Selectic = __decorate([
2614
2614
  Component
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selectic",
3
- "version": "3.0.10",
3
+ "version": "3.0.15",
4
4
  "description": "Smart Select for VueJS 3.x",
5
5
  "main": "dist/selectic.common.js",
6
6
  "module": "dist/selectic.esm.js",
@@ -19,7 +19,9 @@
19
19
  "select",
20
20
  "multiselect",
21
21
  "multi-select",
22
+ "multi-select",
22
23
  "dynamic select",
24
+ "smart select",
23
25
  "vue",
24
26
  "vue.js",
25
27
  "vueJS",
@@ -36,7 +38,7 @@
36
38
  "test": "npm run build && tape test/**/*.spec.js"
37
39
  },
38
40
  "dependencies": {
39
- "vtyx": "4.0.3"
41
+ "vtyx": "4.0.5"
40
42
  },
41
43
  "devDependencies": {
42
44
  "@babel/types": "^7.16.7",
package/rollup.config.js CHANGED
@@ -30,5 +30,12 @@ export default [{
30
30
  'vtyx',
31
31
  ],
32
32
  context: 'this',
33
+ }, {
34
+ input: 'lib/tools.js',
35
+ output: [{
36
+ file: 'test/dist/tools.js',
37
+ exports: 'named',
38
+ format: 'cjs',
39
+ }],
40
+ context: 'this',
33
41
  }];
34
-
package/src/Store.tsx CHANGED
@@ -593,7 +593,7 @@ export default class SelecticStore {
593
593
  this.cacheRequest = new Map();
594
594
 
595
595
  const stateParam: SelecticStoreStateParams | SelecticStoreState =
596
- deepClone(this.props.params);
596
+ deepClone(this.props.params, ['data']);
597
597
 
598
598
  if (stateParam.optionBehavior) {
599
599
  this.buildOptionBehavior(
@@ -1060,7 +1060,7 @@ export default class SelecticStore {
1060
1060
 
1061
1061
  /* This method is for the computed property listOptions */
1062
1062
  private getListOptions(): OptionValue[] {
1063
- const options = deepClone(this.props.options);
1063
+ const options = deepClone(this.props.options, ['data']);
1064
1064
  const listOptions: OptionValue[] = [];
1065
1065
 
1066
1066
  if (!Array.isArray(options)) {
@@ -1106,7 +1106,7 @@ export default class SelecticStore {
1106
1106
 
1107
1107
  /* This method is for the computed property elementOptions */
1108
1108
  private getElementOptions(): OptionValue[] {
1109
- const options = deepClone(this.props.childOptions);
1109
+ const options = deepClone(this.props.childOptions, ['data']);
1110
1110
  const childOptions: OptionValue[] = [];
1111
1111
 
1112
1112
  if (!Array.isArray(options) || options.length === 0) {
package/src/index.tsx CHANGED
@@ -18,7 +18,8 @@
18
18
  * close [component]: triggered when the list closes.
19
19
  */
20
20
 
21
- import {Vue, Component, Emit, Prop, Watch, h} from 'vtyx';
21
+ import {Vue, Component, Emits, Prop, Watch, h} from 'vtyx';
22
+ import { unref } from 'vue';
22
23
  import './css/selectic.css';
23
24
 
24
25
  import { deepClone } from './tools';
@@ -373,7 +374,7 @@ export default class Selectic extends Vue<Props> {
373
374
  }
374
375
 
375
376
  get hasGivenValue() {
376
- const value = this.value;
377
+ const value = unref(this.value);
377
378
 
378
379
  return value !== null && value !== undefined;
379
380
  }
@@ -560,7 +561,7 @@ export default class Selectic extends Vue<Props> {
560
561
 
561
562
  @Watch('options', { deep: true })
562
563
  public onOptionsChange() {
563
- this.store.props.options = deepClone(this.options);
564
+ this.store.props.options = deepClone(this.options, ['data']);
564
565
  }
565
566
 
566
567
  @Watch('texts', { deep: true })
@@ -781,12 +782,12 @@ export default class Selectic extends Vue<Props> {
781
782
  this._elementsListeners = [];
782
783
 
783
784
  this.store = new Store({
784
- options: this.options,
785
- value: this.value,
785
+ options: deepClone(this.options, ['data']),
786
+ value: deepClone(this.value),
786
787
  selectionIsExcluded: this.selectionIsExcluded,
787
788
  disabled: this.disabled,
788
789
  texts: this.texts,
789
- groups: this.groups,
790
+ groups: deepClone(this.groups),
790
791
  keepOpenWithOtherSelectic: !!this.params.keepOpenWithOtherSelectic,
791
792
  params: {
792
793
  multiple: (this.multiple ?? false) !== false,
@@ -859,13 +860,7 @@ export default class Selectic extends Vue<Props> {
859
860
 
860
861
  /* }}} */
861
862
 
862
- @Emit('input')
863
- @Emit('change')
864
- @Emit('open')
865
- @Emit('focus')
866
- @Emit('close')
867
- @Emit('blur')
868
- @Emit('item:click')
863
+ @Emits(['input', 'change', 'open', 'focus', 'close', 'blur', 'item:click'])
869
864
  public render() {
870
865
  const id = this.id || undefined;
871
866
  const store = this.store;
package/src/tools.ts CHANGED
@@ -1,11 +1,15 @@
1
+ import { unref } from 'vue';
1
2
 
2
3
  /**
3
4
  * Clone the object and its inner properties.
4
5
  * @param obj The object to be clone.
6
+ * @param attributes list of attributes to not clone.
5
7
  * @param refs internal reference to object to avoid cyclic references
6
8
  * @returns a copy of obj
7
9
  */
8
- export function deepClone<T = any>(obj: T, refs: WeakMap<any, any> = new WeakMap()): T {
10
+ export function deepClone<T = any>(origObject: T, ignoreAttributes: string[] = [], refs: WeakMap<any, any> = new WeakMap()): T {
11
+ const obj = unref(origObject);
12
+
9
13
  /* For circular references */
10
14
  if (refs.has(obj)) {
11
15
  return refs.get(obj);
@@ -20,7 +24,7 @@ export function deepClone<T = any>(obj: T, refs: WeakMap<any, any> = new WeakMap
20
24
  const ref: any[] = [];
21
25
  refs.set(obj, ref);
22
26
  obj.forEach((val, idx) => {
23
- ref[idx] = deepClone(val, refs);
27
+ ref[idx] = deepClone(val, ignoreAttributes, refs);
24
28
  });
25
29
  return ref as unknown as T;
26
30
  }
@@ -35,7 +39,12 @@ export function deepClone<T = any>(obj: T, refs: WeakMap<any, any> = new WeakMap
35
39
  const ref: any = {};
36
40
  refs.set(obj, ref);
37
41
  for (const [key, val] of Object.entries(obj)) {
38
- ref[key] = deepClone(val, refs);
42
+ if (ignoreAttributes.includes(key)) {
43
+ ref[key] = val;
44
+ continue;
45
+ }
46
+
47
+ ref[key] = deepClone(val, ignoreAttributes, refs);
39
48
  }
40
49
  return ref as unknown as T;
41
50
  }
@@ -44,7 +53,6 @@ export function deepClone<T = any>(obj: T, refs: WeakMap<any, any> = new WeakMap
44
53
  return obj;
45
54
  }
46
55
 
47
-
48
56
  /**
49
57
  * Escape search string to consider regexp special characters as they
50
58
  * are and not like special characters.
@@ -1,16 +1,3 @@
1
- /**************************************************************************/
2
- /* */
3
- /* Copyright (C) INTERSEC SA */
4
- /* */
5
- /* Should you receive a copy of this source code, you must check you */
6
- /* have a proper, written authorization of INTERSEC to hold it. If you */
7
- /* don't have such an authorization, you must DELETE all source code */
8
- /* files in your possession, and inform INTERSEC of the fact you obtain */
9
- /* these files. Should you not comply to these terms, you can be */
10
- /* prosecuted in the extent permitted by applicable law. */
11
- /* */
12
- /**************************************************************************/
13
-
14
1
  const _ = require('../tools.js');
15
2
  const {
16
3
  getInitialState,
@@ -873,6 +860,44 @@ tape.test('Store creation', (subT) => {
873
860
  t.deepEqual(store.state.internalValue, [2, 'hello', 1, true]);
874
861
  t.end();
875
862
  });
863
+
864
+ sTest.test('should call getItemsCallback if item is not in options', async (t) => {
865
+ const spyGetItems = {};
866
+ const store = new Store({
867
+ params: {
868
+ multiple: true,
869
+ strictValue: false,
870
+ },
871
+ getItemsCallback: buildGetItemsCb({ spy: spyGetItems}),
872
+ options: getOptions(5),
873
+ value: [2, 10, 1],
874
+ });
875
+
876
+ await sleep(0);
877
+ t.true(spyGetItems.nbCall >= 1, 'fetch callback should be called at least once');
878
+
879
+ t.deepEqual(store.state.internalValue, [2, 10, 1]);
880
+
881
+ const item = store.getItem(10);
882
+
883
+ t.deepEqual(item, {
884
+ id: 10,
885
+ text: 'some text 10',
886
+ data: 'data10',
887
+ disabled: false,
888
+ selected: true,
889
+ isGroup: false,
890
+ });
891
+
892
+ const currentOptions = store.state.allOptions;
893
+ t.is(currentOptions.length, 5, 'should add fetched items');
894
+
895
+ const hasItem10 = currentOptions.some((option) => option.id === 10);
896
+
897
+ t.false(hasItem10, 'should not add the item');
898
+
899
+ t.end();
900
+ });
876
901
  });
877
902
 
878
903
  st.test('in dynamic mode', (sTest) => {
@@ -1,16 +1,3 @@
1
- /**************************************************************************/
2
- /* */
3
- /* Copyright (C) INTERSEC SA */
4
- /* */
5
- /* Should you receive a copy of this source code, you must check you */
6
- /* have a proper, written authorization of INTERSEC to hold it. If you */
7
- /* don't have such an authorization, you must DELETE all source code */
8
- /* files in your possession, and inform INTERSEC of the fact you obtain */
9
- /* these files. Should you not comply to these terms, you can be */
10
- /* prosecuted in the extent permitted by applicable law. */
11
- /* */
12
- /**************************************************************************/
13
-
14
1
  const _ = require('../tools.js');
15
2
  const {
16
3
  getInitialState,
@@ -1,16 +1,3 @@
1
- /**************************************************************************/
2
- /* */
3
- /* Copyright (C) INTERSEC SA */
4
- /* */
5
- /* Should you receive a copy of this source code, you must check you */
6
- /* have a proper, written authorization of INTERSEC to hold it. If you */
7
- /* don't have such an authorization, you must DELETE all source code */
8
- /* files in your possession, and inform INTERSEC of the fact you obtain */
9
- /* these files. Should you not comply to these terms, you can be */
10
- /* prosecuted in the extent permitted by applicable law. */
11
- /* */
12
- /**************************************************************************/
13
-
14
1
  const _ = require('../tools.js');
15
2
  const {
16
3
  buildFetchCb,
@@ -1,16 +1,3 @@
1
- /**************************************************************************/
2
- /* */
3
- /* Copyright (C) INTERSEC SA */
4
- /* */
5
- /* Should you receive a copy of this source code, you must check you */
6
- /* have a proper, written authorization of INTERSEC to hold it. If you */
7
- /* don't have such an authorization, you must DELETE all source code */
8
- /* files in your possession, and inform INTERSEC of the fact you obtain */
9
- /* these files. Should you not comply to these terms, you can be */
10
- /* prosecuted in the extent permitted by applicable law. */
11
- /* */
12
- /**************************************************************************/
13
-
14
1
  const _ = require('../tools.js');
15
2
  const {
16
3
  getOptions,
@@ -1,16 +1,3 @@
1
- /**************************************************************************/
2
- /* */
3
- /* Copyright (C) INTERSEC SA */
4
- /* */
5
- /* Should you receive a copy of this source code, you must check you */
6
- /* have a proper, written authorization of INTERSEC to hold it. If you */
7
- /* don't have such an authorization, you must DELETE all source code */
8
- /* files in your possession, and inform INTERSEC of the fact you obtain */
9
- /* these files. Should you not comply to these terms, you can be */
10
- /* prosecuted in the extent permitted by applicable law. */
11
- /* */
12
- /**************************************************************************/
13
-
14
1
  const _ = require('../tools.js');
15
2
  const {
16
3
  getOptions,
@@ -1,16 +1,3 @@
1
- /**************************************************************************/
2
- /* */
3
- /* Copyright (C) INTERSEC SA */
4
- /* */
5
- /* Should you receive a copy of this source code, you must check you */
6
- /* have a proper, written authorization of INTERSEC to hold it. If you */
7
- /* don't have such an authorization, you must DELETE all source code */
8
- /* files in your possession, and inform INTERSEC of the fact you obtain */
9
- /* these files. Should you not comply to these terms, you can be */
10
- /* prosecuted in the extent permitted by applicable law. */
11
- /* */
12
- /**************************************************************************/
13
-
14
1
  const _ = require('../tools.js');
15
2
  const {
16
3
  getOptions,
@@ -0,0 +1,404 @@
1
+ const tape = require('tape');
2
+ const toolFile = require('../dist/tools.js');
3
+
4
+ const {
5
+ assignObject,
6
+ convertToRegExp,
7
+ deepClone,
8
+ } = toolFile;
9
+
10
+ tape.test('assignObject()', (st) => {
11
+ st.test('behaves like Object.assign', (tst) => {
12
+ const deep1 = {
13
+ dp: 1,
14
+ };
15
+ const deep2 = {
16
+ dp: 2,
17
+ other: 'value',
18
+ };
19
+ const obj1 = {
20
+ a: 1,
21
+ b: 2,
22
+ c: false,
23
+ deep: deep1,
24
+ };
25
+ const obj2 = {
26
+ a: 3,
27
+ c: true,
28
+ d: false,
29
+ deep: deep2,
30
+ other: {
31
+ attr: 'str',
32
+ },
33
+ };
34
+
35
+ const result = assignObject(obj1, obj2);
36
+
37
+ tst.is(result, obj1, 'should modify first argument');
38
+ tst.deepEqual(result, {
39
+ a: 3,
40
+ b: 2,
41
+ c: true,
42
+ d: false,
43
+ deep: {
44
+ dp: 2,
45
+ other: 'value',
46
+ },
47
+ other: {
48
+ attr: 'str',
49
+ },
50
+ }, 'should merge all attributes');
51
+ tst.is(result.deep, deep2, 'should keep references');
52
+ tst.deepEqual(obj2, {
53
+ a: 3,
54
+ c: true,
55
+ d: false,
56
+ deep: deep2,
57
+ other: {
58
+ attr: 'str',
59
+ },
60
+ }, 'should not change second argument');
61
+ tst.end();
62
+ });
63
+
64
+ st.test('accept multiple arguments', (tst) => {
65
+ const obj1 = {
66
+ a: 1,
67
+ b: 2,
68
+ };
69
+ const obj2 = {
70
+ a: 2,
71
+ c: 3,
72
+ };
73
+ const obj3 = {
74
+ a: 3,
75
+ d: 4,
76
+ };
77
+ const obj4 = {
78
+ a: 4,
79
+ e: 5,
80
+ };
81
+
82
+ const result = assignObject(obj1, obj2, obj3, obj4);
83
+
84
+ tst.is(result, obj1, 'should modify first argument');
85
+ tst.deepEqual(result, {
86
+ a: 4,
87
+ b: 2,
88
+ c: 3,
89
+ d: 4,
90
+ e: 5,
91
+ }, 'should merge all attributes');
92
+ tst.deepEqual(obj2, {
93
+ a: 2,
94
+ c: 3,
95
+ }, 'should not change second argument');
96
+ tst.deepEqual(obj3, {
97
+ a: 3,
98
+ d: 4,
99
+ }, 'should not change third argument');
100
+ tst.deepEqual(obj4, {
101
+ a: 4,
102
+ e: 5,
103
+ }, 'should not change fourth argument');
104
+ tst.end();
105
+ });
106
+
107
+ st.test('ignores undefined attributes', (tst) => {
108
+ const obj1 = {
109
+ a: 1, // modified by all
110
+ b: 2, // not modified by all (undefined)
111
+ c: 3, // obj2: undefined, modified by obj3
112
+ d: 4, // modified by obj2, obj3: undefined
113
+ e: 5, // not set by obj2, obj3: undefined
114
+ f: 6, // not set by all
115
+ };
116
+ const obj2 = {
117
+ a: 'a',
118
+ b: undefined,
119
+ c: undefined,
120
+ d: 'd',
121
+ };
122
+ const obj3 = {
123
+ a: 2,
124
+ b: undefined,
125
+ c: 'c',
126
+ d: undefined,
127
+ e: undefined,
128
+ };
129
+
130
+ const result = assignObject(obj1, obj2, obj3);
131
+
132
+ tst.is(result, obj1, 'should modify first argument');
133
+ tst.deepEqual(result, {
134
+ a: 2,
135
+ b: 2,
136
+ c: 'c',
137
+ d: 'd',
138
+ e: 5,
139
+ f: 6,
140
+ }, 'should merge all attributes');
141
+ tst.deepEqual(obj2, {
142
+ a: 'a',
143
+ b: undefined,
144
+ c: undefined,
145
+ d: 'd',
146
+ }, 'should not change second argument');
147
+ tst.deepEqual(obj3, {
148
+ a: 2,
149
+ b: undefined,
150
+ c: 'c',
151
+ d: undefined,
152
+ e: undefined,
153
+ }, 'should not change third argument');
154
+ tst.end();
155
+ });
156
+ });
157
+
158
+ tape.test('convertToRegExp()', (st) => {
159
+ st.test('convert wildcard', (tst) => {
160
+ const str = '*the search*';
161
+
162
+ const result = convertToRegExp(str);
163
+
164
+ tst.is(result instanceof RegExp, true, 'should create a RegExp');
165
+
166
+ const pattern = result.source;
167
+ const flags = result.flags;
168
+
169
+ tst.is(pattern, '.*the search.*', 'should create wildcard sequence');
170
+ tst.is(flags, 'i', 'should be case insensitive by default');
171
+
172
+ tst.end();
173
+ });
174
+ st.test('escape special characters', (tst) => {
175
+ const str = '\\^$.+?(){}[]|';
176
+
177
+ const result = convertToRegExp(str);
178
+
179
+ tst.is(result instanceof RegExp, true, 'should create a RegExp');
180
+
181
+ const pattern = result.source;
182
+ const flags = result.flags;
183
+
184
+ tst.is(pattern, '\\\\\\^\\$\\.\\+\\?\\(\\)\\{\\}\\[\\]\\|', 'should escape special characters');
185
+ tst.is(flags, 'i', 'should be case insensitive by default');
186
+
187
+ tst.end();
188
+ });
189
+
190
+ st.test('allow RegExp flags', (tst) => {
191
+ const str = 'file*.*';
192
+
193
+ const result = convertToRegExp(str, 'gm');
194
+
195
+ tst.is(result instanceof RegExp, true, 'should create a RegExp');
196
+
197
+ const pattern = result.source;
198
+ const flags = result.flags;
199
+
200
+ tst.is(pattern, 'file.*\\..*', 'should convert special characters');
201
+ tst.is(flags, 'gm', 'should set flags');
202
+
203
+ tst.end();
204
+ });
205
+ });
206
+
207
+ tape.test('deepClone()', (st) => {
208
+ st.test('should copy simple object', (tst) => {
209
+ const fn = () => {};
210
+ const objRef = {
211
+ a: 1,
212
+ b: 'b',
213
+ c: false,
214
+ d: undefined,
215
+ e: null,
216
+ f: {},
217
+ g: fn,
218
+ spe1: NaN,
219
+ spe2: Infinity,
220
+ spe3: '',
221
+ spe4: [],
222
+ };
223
+
224
+ const result = deepClone(objRef);
225
+
226
+ tst.isNot(result, objRef, 'should create a copy');
227
+ tst.deepEqual(result, objRef, 'should have been similar to original');
228
+
229
+ tst.end();
230
+ });
231
+
232
+ st.test('should copy nested object', (tst) => {
233
+ const fn = () => {};
234
+ const deep1 = {
235
+ a: 1,
236
+ b: 'b',
237
+ c: false,
238
+ d: undefined,
239
+ e: null,
240
+ f: {},
241
+ g: fn,
242
+ spe1: NaN,
243
+ spe2: Infinity,
244
+ spe3: '',
245
+ spe4: [],
246
+ };
247
+ const deep2 = {
248
+ deep: deep1,
249
+ added: 'a value',
250
+ };
251
+ const objRef = {
252
+ d: deep2,
253
+ }
254
+
255
+ const result = deepClone(objRef);
256
+
257
+ tst.isNot(result, objRef, 'should create a copy');
258
+ tst.deepEqual(result, objRef, 'should have been similar to original');
259
+ tst.isNot(result.d, deep2, 'should copy nested object');
260
+ tst.isNot(result.d.deep, deep1, 'should copy deeper nested object');
261
+
262
+ tst.end();
263
+ });
264
+
265
+
266
+ st.test('with arrays', (tst) => {
267
+ const fn = () => {};
268
+ const objRef = {
269
+ a: 1,
270
+ b: 'b',
271
+ c: false,
272
+ d: undefined,
273
+ e: null,
274
+ f: {},
275
+ g: fn,
276
+ spe1: NaN,
277
+ spe2: Infinity,
278
+ spe3: '',
279
+ spe4: [],
280
+ };
281
+ const nestedArray1 = [
282
+ objRef,
283
+ { a: 'value' },
284
+ null,
285
+ undefined,
286
+ 42,
287
+ 'value',
288
+ ];
289
+ const nestedArray2 = [
290
+ objRef,
291
+ { a: 'value' },
292
+ null,
293
+ undefined,
294
+ 42,
295
+ 'value',
296
+ ];
297
+ const arrayRef = [
298
+ {
299
+ deep: nestedArray1,
300
+ },
301
+ nestedArray2,
302
+ 42, 'value', null, undefined, [[]],
303
+ ];
304
+
305
+ const result = deepClone(arrayRef);
306
+
307
+ tst.isNot(result, arrayRef, 'should create a copy');
308
+ tst.is(Array.isArray(arrayRef), true, 'should create an array');
309
+ tst.deepEqual(result, arrayRef, 'should have been similar to original');
310
+ tst.isNot(result[1], nestedArray2, 'should copy nested array');
311
+ tst.isNot(result[0].deep, nestedArray1, 'should copy deeper nested array');
312
+ tst.isNot(result[1][0], objRef, 'should copy nested object');
313
+ tst.isNot(result[0].deep[0], objRef, 'should copy deeper nested object');
314
+
315
+ tst.end();
316
+ });
317
+
318
+ st.test('with RegExp', (tst) => {
319
+ const r1 = /hello?/gi;
320
+ const r2 = /.* [aA]+?/;
321
+
322
+ const result1 = deepClone(r1);
323
+ const result2 = deepClone({rgx: r2});
324
+
325
+ tst.isNot(result1, r1, 'should copy RegExp');
326
+ tst.is(result1 instanceof RegExp, true, 'should create a RegExp');
327
+ tst.is(result1.source, 'hello?', 'should copy pattern');
328
+ tst.is(result1.flags, 'gi', 'should copy flags');
329
+
330
+ tst.isNot(result2.rgx, r2, 'should copy the RegExp');
331
+ tst.is(result2.rgx.source, '.* [aA]+?', 'should copy the attribute pattern');
332
+ tst.is(result2.rgx.flags, '', 'should copy the attribute flags');
333
+ tst.end();
334
+ });
335
+
336
+ st.test('with primitives', (tst) => {
337
+ const result1 = deepClone(1);
338
+ const result2 = deepClone('a');
339
+ const result3 = deepClone(false);
340
+ const result4 = deepClone(null);
341
+ const result5 = deepClone(undefined);
342
+
343
+ tst.is(result1, 1, 'should return number');
344
+ tst.is(result2, 'a', 'should return string');
345
+ tst.is(result3, false, 'should return boolean');
346
+ tst.is(result4, null, 'should return null');
347
+ tst.is(result5, undefined, 'should return undefined');
348
+ tst.end();
349
+ });
350
+
351
+ st.test('with circular references', (tst) => {
352
+ const obj1 = {
353
+ a: 'a',
354
+ }
355
+ const obj2 = {
356
+ b: 'b',
357
+ }
358
+ obj1.child = obj1;
359
+ obj1.sibling = obj2;
360
+ obj2.sibling = obj1;
361
+
362
+ const ref = [obj1, obj2];
363
+
364
+ const result = deepClone(ref);
365
+
366
+ tst.isNot(result, ref, 'should create a new object');
367
+ tst.isNot(result[0], obj1, 'should copy inner objects');
368
+ tst.is(result[0].child, result[0], 'should keep the circular reference');
369
+ tst.is(result[1].sibling, result[0], 'should keep similar references');
370
+ tst.is(result[0].sibling, result[1], 'should keep similar references (2)');
371
+
372
+ tst.end();
373
+ });
374
+
375
+ st.test('can ignore some attributes', (tst) => {
376
+ const noCopy1 = {
377
+ ref: 1,
378
+ };
379
+ const noCopy2 = new Set(['alpha', 'omega']);
380
+ const noCopy3 = new Map([[1, 'alpha'], [22, 'omega']]);
381
+ const deep1 = {
382
+ a: 'alpha',
383
+ noCopy: noCopy3,
384
+ };
385
+ const ref = {
386
+ id: 'ref',
387
+ noCopy: noCopy1,
388
+ nop: noCopy2,
389
+ not: 42,
390
+ deep: deep1,
391
+ };
392
+
393
+ const result = deepClone(ref, ['noCopy', 'nothing', 'nop', 'not']);
394
+
395
+ tst.isNot(result, ref, 'should create a new object');
396
+ tst.isNot(result.deep, deep1, 'should create a new object');
397
+ tst.is(result.noCopy, noCopy1, 'should keep original reference');
398
+ tst.is(result.nop, noCopy2, 'should keep original reference (2)');
399
+ tst.is(result.not, 42, 'should keep primitive');
400
+ tst.is(result.deep.noCopy, noCopy3, 'should keep nested original reference');
401
+
402
+ tst.end();
403
+ });
404
+ });
package/types/tools.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * Clone the object and its inner properties.
3
3
  * @param obj The object to be clone.
4
+ * @param attributes list of attributes to not clone.
4
5
  * @param refs internal reference to object to avoid cyclic references
5
6
  * @returns a copy of obj
6
7
  */
7
- export declare function deepClone<T = any>(obj: T, refs?: WeakMap<any, any>): T;
8
+ export declare function deepClone<T = any>(origObject: T, ignoreAttributes?: string[], refs?: WeakMap<any, any>): T;
8
9
  /**
9
10
  * Escape search string to consider regexp special characters as they
10
11
  * are and not like special characters.
package/.package.json.un~ DELETED
Binary file