collect-your-stuff 1.2.9 → 1.3.2

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.
Files changed (49) hide show
  1. package/README.md +802 -77
  2. package/dist/collections/arrayable/ArrayElement.d.ts +2 -0
  3. package/dist/collections/arrayable/ArrayElement.js +4 -2
  4. package/dist/collections/arrayable/ArrayElement.min.js +1 -1
  5. package/dist/collections/arrayable/Arrayable.d.ts +25 -11
  6. package/dist/collections/arrayable/Arrayable.js +37 -12
  7. package/dist/collections/arrayable/Arrayable.min.js +1 -1
  8. package/dist/collections/doubly-linked-list/DoubleLinker.d.ts +5 -1
  9. package/dist/collections/doubly-linked-list/DoubleLinker.js +5 -1
  10. package/dist/collections/doubly-linked-list/DoublyLinkedList.d.ts +11 -5
  11. package/dist/collections/doubly-linked-list/DoublyLinkedList.js +43 -25
  12. package/dist/collections/doubly-linked-list/DoublyLinkedList.min.js +1 -1
  13. package/dist/collections/linked-list/LinkedList.d.ts +13 -7
  14. package/dist/collections/linked-list/LinkedList.js +42 -23
  15. package/dist/collections/linked-list/LinkedList.min.js +1 -1
  16. package/dist/collections/linked-list/Linker.d.ts +5 -2
  17. package/dist/collections/linked-list/Linker.js +9 -5
  18. package/dist/collections/linked-list/Linker.min.js +1 -1
  19. package/dist/collections/linked-tree-list/LinkedTreeList.d.ts +7 -1
  20. package/dist/collections/linked-tree-list/LinkedTreeList.js +6 -1
  21. package/dist/collections/linked-tree-list/TreeLinker.d.ts +7 -1
  22. package/dist/collections/linked-tree-list/TreeLinker.js +7 -1
  23. package/dist/collections/queue/Queue.d.ts +6 -3
  24. package/dist/collections/queue/Queue.js +23 -18
  25. package/dist/collections/queue/Queue.min.js +1 -1
  26. package/dist/collections/queue/Queueable.d.ts +10 -4
  27. package/dist/collections/queue/Queueable.js +11 -6
  28. package/dist/collections/queue/Queueable.min.js +1 -1
  29. package/dist/collections/stack/Stack.d.ts +4 -3
  30. package/dist/collections/stack/Stack.js +4 -4
  31. package/dist/collections/stack/Stack.min.js +1 -1
  32. package/dist/collections/stack/Stackable.d.ts +4 -1
  33. package/dist/collections/stack/Stackable.js +7 -5
  34. package/dist/collections/stack/Stackable.min.js +1 -1
  35. package/dist/main.d.ts +26 -3
  36. package/dist/main.js +101 -1
  37. package/dist/main.min.js +1 -1
  38. package/dist/recipes/ArrayIterator.d.ts +10 -0
  39. package/dist/recipes/ArrayIterator.js +10 -0
  40. package/dist/recipes/DoubleLinkerIterator.d.ts +9 -0
  41. package/dist/recipes/DoubleLinkerIterator.js +9 -0
  42. package/dist/recipes/LinkerIterator.d.ts +9 -0
  43. package/dist/recipes/LinkerIterator.js +9 -0
  44. package/dist/recipes/Runnable.d.ts +3 -2
  45. package/dist/recipes/Runnable.js +3 -2
  46. package/dist/recipes/TreeLinkerIterator.d.ts +9 -0
  47. package/dist/recipes/TreeLinkerIterator.js +9 -0
  48. package/dist/services/services.d.ts +2 -2
  49. package/package.json +2 -1
@@ -14,10 +14,14 @@ var _Arrayable = require('../arrayable/Arrayable')
14
14
  class LinkedList {
15
15
  /**
16
16
  * Create the new LinkedList instance.
17
+ * @param {Linker} [linkerClass=Linker] The class used to wrap given data as linkers.
17
18
  */
18
19
  constructor (linkerClass = _Linker.Linker) {
20
+ /** The class used to create this instance, so that it can be recognized as valid without an instanceof check. */
19
21
  this.classType = LinkedList
22
+ /** The first linker of the list (null when the list is empty), from which the whole list is reached. */
20
23
  this.innerList = null
24
+ /** Whether the inner list has been initialized (it can only be initialized once). */
21
25
  this.initialized = false
22
26
  this.linkerClass = linkerClass
23
27
  }
@@ -28,11 +32,12 @@ class LinkedList {
28
32
  * @return {LinkedList}
29
33
  */
30
34
  initialize (initialList) {
35
+ // Borrowed from Arrayable, which types its return as an Arrayable although it returns whatever list called it
31
36
  return _Arrayable.Arrayable.prototype.initialize.call(this, initialList)
32
37
  }
33
38
 
34
39
  /**
35
- * Retrieve a copy of the innerList used.
40
+ * Retrieve the innerList used (the list itself, not a copy).
36
41
  * @returns {Linker}
37
42
  */
38
43
  get list () {
@@ -80,45 +85,55 @@ class LinkedList {
80
85
 
81
86
  /**
82
87
  * Insert a new node (or data) after a node.
83
- * @param {Linker|*} node The existing node as reference
88
+ * @param {Linker|*} node The existing node as reference, or null to insert at the start of the list
84
89
  * @param {Linker|*} newNode The new node to go after the existing node
85
90
  * @returns {LinkedList}
86
91
  */
87
92
  insertAfter (node, newNode) {
88
- newNode = this.linkerClass.make(newNode)
89
- if (node !== null) {
90
- // Ensure the next reference of this node is assigned to the new node
91
- newNode.next = node.next
92
- // Then set this node's next reference to the new node
93
- node.next = newNode
94
- }
95
- if (!this.length) {
93
+ newNode = this.linkerClass.make(newNode, this.linkerClass)
94
+ if (node === null || typeof node === 'undefined') {
95
+ // After nothing means at the start of the list
96
+ newNode.next = this.innerList
96
97
  this.innerList = newNode
98
+ return this
97
99
  }
100
+ newNode.next = node.next
101
+ node.next = newNode
98
102
  return this
99
103
  }
100
104
 
101
105
  /**
102
106
  * Insert a new node (or data) before a node.
103
- * @param {Linker|*} node The existing node as reference
107
+ * @param {Linker|*} node The existing node as reference, or null to insert at the end of the list
104
108
  * @param {Linker|*} newNode The new node to go before the existing node
105
109
  * @returns {LinkedList}
110
+ * @throws {Error} When the reference node is not in this list
106
111
  */
107
112
  insertBefore (node, newNode) {
108
- newNode = this.linkerClass.make(newNode)
113
+ newNode = this.linkerClass.make(newNode, this.linkerClass)
114
+ if (node === null || typeof node === 'undefined') {
115
+ // Before nothing means at the end of the list
116
+ const tail = this.last
117
+ if (tail === null) {
118
+ this.innerList = newNode
119
+ } else {
120
+ tail.next = newNode
121
+ }
122
+ return this
123
+ }
109
124
  let prevNode = null
110
125
  let currentNode = this.first
111
- while (currentNode !== node) {
126
+ while (currentNode !== null && currentNode !== node) {
112
127
  prevNode = currentNode
113
128
  currentNode = currentNode.next
114
129
  }
115
- // The new node will reference this node as next
130
+ if (currentNode === null) {
131
+ throw new Error('The reference node is not in this list.')
132
+ }
116
133
  newNode.next = node
117
134
  if (prevNode) {
118
- // Ensure the next reference of the previous node is assigned to the new node
119
135
  prevNode.next = newNode
120
- }
121
- if (node === this.first || node === null) {
136
+ } else {
122
137
  this.innerList = newNode
123
138
  }
124
139
  return this
@@ -147,21 +162,25 @@ class LinkedList {
147
162
  /**
148
163
  * Remove a linker from this linked list.
149
164
  * @param {Linker} node The node we wish to remove (and it will be returned after removal)
150
- * @return {Linker}
165
+ * @return {Linker|null} The removed node, or null when it was not in this list (nothing is removed)
151
166
  */
152
167
  remove (node) {
168
+ if (node === null || typeof node === 'undefined') {
169
+ return null
170
+ }
153
171
  let prevNode = null
154
172
  let currentNode = this.first
155
- while (currentNode !== node) {
173
+ while (currentNode !== null && currentNode !== node) {
156
174
  prevNode = currentNode
157
175
  currentNode = currentNode.next
158
176
  }
177
+ if (currentNode === null) {
178
+ // The node is not in this list, so there is nothing to remove
179
+ return null
180
+ }
159
181
  if (prevNode) {
160
- // Ensure the next reference of the previous node skips over the removed node
161
182
  prevNode.next = node.next
162
- }
163
- if (node === this.first && node !== null) {
164
- // Update list head to point to next if it was this node
183
+ } else {
165
184
  this.innerList = node.next
166
185
  }
167
186
  return node
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.LinkedList=void 0;var _Linker=require("./Linker"),_LinkerIterator=require("../../recipes/LinkerIterator"),_Arrayable=require("../arrayable/Arrayable");class LinkedList{constructor(t=_Linker.Linker){this.classType=LinkedList,this.innerList=null,this.initialized=!1,this.linkerClass=t}initialize(t){return _Arrayable.Arrayable.prototype.initialize.call(this,t)}get list(){return this.innerList}get first(){return this.innerList}get last(){let t=this.innerList;if(null===t)return null;let e=t.next;for(;null!==e;)t=e,e=t.next;return t}get length(){let t=this.first,e=0;for(;null!==t;)++e,t=t.next;return e}insertAfter(t,e){return e=this.linkerClass.make(e),null!==t&&(e.next=t.next,t.next=e),this.length||(this.innerList=e),this}insertBefore(t,e){e=this.linkerClass.make(e);let r=null,i=this.first;for(;i!==t;)r=i,i=i.next;return e.next=t,r&&(r.next=e),t!==this.first&&null!==t||(this.innerList=e),this}append(t,e=this.last){return this.insertAfter(e,t)}prepend(t,e=this.first){return this.insertBefore(e,t)}remove(t){let e=null,r=this.first;for(;r!==t;)e=r,r=r.next;return e&&(e.next=t.next),t===this.first&&null!==t&&(this.innerList=t.next),t}item(t){if(t>=0){let e=this.first,r=-1;for(;++r<t&&null!==e;)e=e.next;return r===t?e:null}let e=this.first,r=0;const i=this.length+t;if(i<0)return null;for(;r<i&&null!==e;)e=e.next,++r;return r===i?e:null}forEach(t,e=this){let r=0,i=e.first;for(;null!==i;)t(i,r,e),i=i.next,++r;return e}[Symbol.iterator](){return new _LinkerIterator.LinkerIterator(this.first)}}exports.LinkedList=LinkedList,LinkedList.fromArray=(t=[],e=_Linker.Linker,r=LinkedList)=>new r(e).initialize(e.fromArray(t).head);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.LinkedList=void 0;var _Linker=require("./Linker"),_LinkerIterator=require("../../recipes/LinkerIterator"),_Arrayable=require("../arrayable/Arrayable");class LinkedList{constructor(t=_Linker.Linker){this.classType=LinkedList,this.innerList=null,this.initialized=!1,this.linkerClass=t}initialize(t){return _Arrayable.Arrayable.prototype.initialize.call(this,t)}get list(){return this.innerList}get first(){return this.innerList}get last(){let t=this.innerList;if(null===t)return null;let e=t.next;for(;null!==e;)t=e,e=t.next;return t}get length(){let t=this.first,e=0;for(;null!==t;)++e,t=t.next;return e}insertAfter(t,e){return e=this.linkerClass.make(e,this.linkerClass),null==t?(e.next=this.innerList,this.innerList=e,this):(e.next=t.next,t.next=e,this)}insertBefore(t,e){if(e=this.linkerClass.make(e,this.linkerClass),null==t){const t=this.last;return null===t?this.innerList=e:t.next=e,this}let r=null,i=this.first;for(;null!==i&&i!==t;)r=i,i=i.next;if(null===i)throw new Error("The reference node is not in this list.");return e.next=t,r?r.next=e:this.innerList=e,this}append(t,e=this.last){return this.insertAfter(e,t)}prepend(t,e=this.first){return this.insertBefore(e,t)}remove(t){if(null==t)return null;let e=null,r=this.first;for(;null!==r&&r!==t;)e=r,r=r.next;return null===r?null:(e?e.next=t.next:this.innerList=t.next,t)}item(t){if(t>=0){let e=this.first,r=-1;for(;++r<t&&null!==e;)e=e.next;return r===t?e:null}let e=this.first,r=0;const i=this.length+t;if(i<0)return null;for(;r<i&&null!==e;)e=e.next,++r;return r===i?e:null}forEach(t,e=this){let r=0,i=e.first;for(;null!==i;)t(i,r,e),i=i.next,++r;return e}[Symbol.iterator](){return new _LinkerIterator.LinkerIterator(this.first)}}exports.LinkedList=LinkedList,LinkedList.fromArray=(t=[],e=_Linker.Linker,r=LinkedList)=>new r(e).initialize(e.fromArray(t).head);
@@ -10,12 +10,15 @@ import { IsLinker } from '../../recipes/IsLinker';
10
10
  * @extends ArrayElement
11
11
  */
12
12
  export declare class Linker implements IsLinker {
13
+ /** The class used to create this instance, so that it can be recognized as valid without an instanceof check. */
13
14
  readonly classType: typeof Linker;
15
+ /** The data stored in this linker. */
14
16
  data: any;
17
+ /** The linker after this one, or null when this is the last. */
15
18
  next: Linker | null;
16
19
  /**
17
20
  * Create the new Linker instance, provide the data and optionally give the next Linker.
18
- * @param {Object} [nodeData={}]
21
+ * @param {Object} [nodeData={}] The settings for the new linker.
19
22
  * @param {*} [nodeData.data=null] The data to be stored in this linker
20
23
  * @param {Linker|null} [nodeData.next=null] The reference to the next linker if any
21
24
  */
@@ -36,7 +39,7 @@ export declare class Linker implements IsLinker {
36
39
  * @param {IsLinker} [classType=Linker] Provide the type of IsLinker to use.
37
40
  * @returns {{head: Linker, tail: Linker}}
38
41
  */
39
- static fromArray: (values: Array<any>, classType?: any) => {
42
+ static fromArray: (values?: Array<any>, classType?: any) => {
40
43
  head: IsLinker;
41
44
  tail: IsLinker;
42
45
  };
@@ -14,7 +14,7 @@ var _ArrayElement = require('../arrayable/ArrayElement')
14
14
  class Linker {
15
15
  /**
16
16
  * Create the new Linker instance, provide the data and optionally give the next Linker.
17
- * @param {Object} [nodeData={}]
17
+ * @param {Object} [nodeData={}] The settings for the new linker.
18
18
  * @param {*} [nodeData.data=null] The data to be stored in this linker
19
19
  * @param {Linker|null} [nodeData.next=null] The reference to the next linker if any
20
20
  */
@@ -22,8 +22,11 @@ class Linker {
22
22
  data = null,
23
23
  next = null
24
24
  } = {}) {
25
+ /** The class used to create this instance, so that it can be recognized as valid without an instanceof check. */
25
26
  this.classType = Linker
27
+ /** The data stored in this linker. */
26
28
  this.data = null
29
+ /** The linker after this one, or null when this is the last. */
27
30
  this.next = null
28
31
  this.data = data
29
32
  this.next = next
@@ -37,8 +40,8 @@ class Linker {
37
40
  */
38
41
  exports.Linker = Linker
39
42
  Linker.make = (linker, classType = Linker) => {
40
- if (typeof linker !== 'object') {
41
- // It is not an object, so instantiate the Linker with element as the data
43
+ if (linker === null || typeof linker !== 'object') {
44
+ // It is not an object (or it is null), so instantiate the Linker with element as the data
42
45
  return new classType({
43
46
  data: linker
44
47
  })
@@ -47,7 +50,8 @@ Linker.make = (linker, classType = Linker) => {
47
50
  // Already valid Linker, return as-is
48
51
  return linker
49
52
  }
50
- if (!linker.data) {
53
+ if (!('data' in linker)) {
54
+ // Not the settings for a linker (which would have data, even if it is falsy), so it is the data itself
51
55
  linker = {
52
56
  data: linker
53
57
  }
@@ -61,7 +65,7 @@ Linker.make = (linker, classType = Linker) => {
61
65
  * @param {IsLinker} [classType=Linker] Provide the type of IsLinker to use.
62
66
  * @returns {{head: Linker, tail: Linker}}
63
67
  */
64
- Linker.fromArray = (values, classType = Linker) => values.reduce((references, linker) => {
68
+ Linker.fromArray = (values = [], classType = Linker) => values.reduce((references, linker) => {
65
69
  const newLinker = classType.make(linker, classType)
66
70
  if (references.head === null) {
67
71
  // Initialize the head and tail with the new node
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Linker=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.reduce.js");var _ArrayElement=require("../arrayable/ArrayElement");class Linker{constructor({data:e=null,next:r=null}={}){this.classType=Linker,this.data=null,this.next=null,this.data=e,this.next=r}}exports.Linker=Linker,Linker.make=(e,r=Linker)=>"object"!=typeof e?new r({data:e}):e.classType?e:(e.data||(e={data:e}),_ArrayElement.ArrayElement.make(e,r)),Linker.fromArray=(e,r=Linker)=>e.reduce(((e,t)=>{const a=r.make(t,r);return null===e.head?{head:a,tail:a}:(e.tail.next=a,e.tail=a,e)}),{head:null,tail:null});
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Linker=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.reduce.js");var _ArrayElement=require("../arrayable/ArrayElement");class Linker{constructor({data:e=null,next:r=null}={}){this.classType=Linker,this.data=null,this.next=null,this.data=e,this.next=r}}exports.Linker=Linker,Linker.make=(e,r=Linker)=>null===e||"object"!=typeof e?new r({data:e}):e.classType?e:("data"in e||(e={data:e}),_ArrayElement.ArrayElement.make(e,r)),Linker.fromArray=(e=[],r=Linker)=>e.reduce(((e,t)=>{const a=r.make(t,r);return null===e.head?{head:a,tail:a}:(e.tail.next=a,e.tail=a,e)}),{head:null,tail:null});
@@ -13,12 +13,17 @@ import { IsTreeNode } from '../../recipes/IsTreeNode';
13
13
  * @extends DoublyLinkedList
14
14
  */
15
15
  export declare class LinkedTreeList implements IsTree, Iterable<TreeLinker> {
16
+ /** The class used to create this instance, so that it can be recognized as valid without an instanceof check. */
16
17
  readonly classType: typeof LinkedTreeList;
18
+ /** A linker of the list (null when the list is empty); the head is found by walking back from it. */
17
19
  innerList: IsTreeNode | any;
20
+ /** Whether the inner list has been initialized (it can only be initialized once). */
18
21
  initialized: boolean;
22
+ /** The class used to wrap the data given to this list as tree linkers. */
19
23
  linkerClass: typeof TreeLinker;
20
24
  /**
21
25
  * Create the new LinkedTreeList instance, configure the list class.
26
+ * @param {TreeLinker} [linkerClass=TreeLinker] The class used to wrap given data as tree linkers.
22
27
  */
23
28
  constructor(linkerClass?: typeof TreeLinker);
24
29
  /**
@@ -28,7 +33,7 @@ export declare class LinkedTreeList implements IsTree, Iterable<TreeLinker> {
28
33
  */
29
34
  initialize(initialList: TreeLinker): LinkedTreeList;
30
35
  /**
31
- * Retrieve a copy of the innerList used.
36
+ * Retrieve the innerList used (the list itself, not a copy).
32
37
  * @returns {TreeLinker}
33
38
  */
34
39
  get list(): TreeLinker;
@@ -117,6 +122,7 @@ export declare class LinkedTreeList implements IsTree, Iterable<TreeLinker> {
117
122
  * Be able to run forEach on this LinkedTreeList to iterate over the TreeLinker Items.
118
123
  * @param {forEachCallback} callback The function to call for-each tree node
119
124
  * @param {LinkedTreeList} thisArg Optional, 'this' reference
125
+ * @return {LinkedTreeList} The list which was iterated.
120
126
  */
121
127
  forEach(callback: forEachCallback, thisArg?: LinkedTreeList): LinkedTreeList;
122
128
  /**
@@ -21,10 +21,14 @@ var _DoublyLinkedList = require('../doubly-linked-list/DoublyLinkedList')
21
21
  class LinkedTreeList {
22
22
  /**
23
23
  * Create the new LinkedTreeList instance, configure the list class.
24
+ * @param {TreeLinker} [linkerClass=TreeLinker] The class used to wrap given data as tree linkers.
24
25
  */
25
26
  constructor (linkerClass = _TreeLinker.TreeLinker) {
27
+ /** The class used to create this instance, so that it can be recognized as valid without an instanceof check. */
26
28
  this.classType = LinkedTreeList
29
+ /** A linker of the list (null when the list is empty); the head is found by walking back from it. */
27
30
  this.innerList = null
31
+ /** Whether the inner list has been initialized (it can only be initialized once). */
28
32
  this.initialized = false
29
33
  this.linkerClass = linkerClass
30
34
  }
@@ -45,7 +49,7 @@ class LinkedTreeList {
45
49
  }
46
50
 
47
51
  /**
48
- * Retrieve a copy of the innerList used.
52
+ * Retrieve the innerList used (the list itself, not a copy).
49
53
  * @returns {TreeLinker}
50
54
  */
51
55
  get list () {
@@ -217,6 +221,7 @@ class LinkedTreeList {
217
221
  * Be able to run forEach on this LinkedTreeList to iterate over the TreeLinker Items.
218
222
  * @param {forEachCallback} callback The function to call for-each tree node
219
223
  * @param {LinkedTreeList} thisArg Optional, 'this' reference
224
+ * @return {LinkedTreeList} The list which was iterated.
220
225
  */
221
226
  forEach (callback, thisArg = this) {
222
227
  let index = 0
@@ -12,15 +12,21 @@ import { IsTree } from '../../recipes/IsTree';
12
12
  * @extends DoubleLinker
13
13
  */
14
14
  export declare class TreeLinker implements IsTreeNode {
15
+ /** The class used to create this instance, so that it can be recognized as valid without an instanceof check. */
15
16
  readonly classType: typeof TreeLinker;
17
+ /** The data stored in this tree node. */
16
18
  data: any;
19
+ /** The sibling after this node, or null when this is the last child. */
17
20
  next: IsTreeNode | null;
21
+ /** The sibling before this node, or null when this is the first child. */
18
22
  prev: IsTreeNode | null;
23
+ /** The node this node is a child of, or null for a root node. */
19
24
  parent: IsTreeNode;
25
+ /** The list of the children of this node, or null when it has none. */
20
26
  children: IsArrayable<IsTreeNode>;
21
27
  /**
22
28
  * Create the new TreeLinker instance, provide the data and optionally set references for next, prev, parent, or children.
23
- * @param {Object} [settings={}]
29
+ * @param {Object} [settings={}] The settings for the new tree node.
24
30
  * @param {*} [settings.data=null] The data to be stored in this tree node
25
31
  * @param {TreeLinker} [settings.next=null] The reference to the next linker if any
26
32
  * @param {TreeLinker} [settings.prev=null] The reference to the previous linker if any
@@ -15,7 +15,7 @@ var _LinkedTreeList = require('./LinkedTreeList')
15
15
  class TreeLinker {
16
16
  /**
17
17
  * Create the new TreeLinker instance, provide the data and optionally set references for next, prev, parent, or children.
18
- * @param {Object} [settings={}]
18
+ * @param {Object} [settings={}] The settings for the new tree node.
19
19
  * @param {*} [settings.data=null] The data to be stored in this tree node
20
20
  * @param {TreeLinker} [settings.next=null] The reference to the next linker if any
21
21
  * @param {TreeLinker} [settings.prev=null] The reference to the previous linker if any
@@ -31,11 +31,17 @@ class TreeLinker {
31
31
  parent = null,
32
32
  listClass = _LinkedTreeList.LinkedTreeList
33
33
  } = {}) {
34
+ /** The class used to create this instance, so that it can be recognized as valid without an instanceof check. */
34
35
  this.classType = TreeLinker
36
+ /** The data stored in this tree node. */
35
37
  this.data = null
38
+ /** The sibling after this node, or null when this is the last child. */
36
39
  this.next = null
40
+ /** The sibling before this node, or null when this is the first child. */
37
41
  this.prev = null
42
+ /** The node this node is a child of, or null for a root node. */
38
43
  this.parent = null
44
+ /** The list of the children of this node, or null when it has none. */
39
45
  this.children = null
40
46
  this.data = data
41
47
  this.next = next
@@ -12,18 +12,21 @@ import { completeResponse } from '../../recipes/Runnable';
12
12
  * Maintain a series of queued items.
13
13
  */
14
14
  export declare class Queue {
15
+ /** The list which stores the queueables, the first is next to be dequeued. */
15
16
  queuedList: IsArrayable<any>;
16
17
  private listClass;
17
18
  private queueableClass;
18
19
  /**
19
20
  * Instantiate the queue with the given queue list.
20
21
  * @param {Iterable|LinkedList} queuedList Give the list of queueables to start in this queue.
21
- * @param {IsArrayable} listClass
22
- * @param {Queueable} queueableClass
22
+ * @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given.
23
+ * @param {Queueable} [queueableClass=Queueable] The class used to wrap queued items.
23
24
  */
24
25
  constructor(queuedList?: IsArrayable<any>, listClass?: any, queueableClass?: typeof Queueable);
25
26
  /**
26
- * Take a queued task from the front of the queue and run it if ready.
27
+ * Take a queued task from the front of the queue and run it if ready. A task which is not ready yet is kept in the
28
+ * queue (never dropped), a task which is still running is reported as blocking and left to finish on its own, and
29
+ * completed tasks are discarded.
27
30
  * @return {completeResponse|*}
28
31
  */
29
32
  dequeue(): completeResponse | any;
@@ -20,8 +20,8 @@ class Queue {
20
20
  /**
21
21
  * Instantiate the queue with the given queue list.
22
22
  * @param {Iterable|LinkedList} queuedList Give the list of queueables to start in this queue.
23
- * @param {IsArrayable} listClass
24
- * @param {Queueable} queueableClass
23
+ * @param {IsArrayable} [listClass=LinkedList] The type of list to create when no queued list is given.
24
+ * @param {Queueable} [queueableClass=Queueable] The class used to wrap queued items.
25
25
  */
26
26
  constructor (queuedList = null, listClass = _LinkedList.LinkedList, queueableClass = _Queueable.Queueable) {
27
27
  this.listClass = listClass
@@ -33,11 +33,17 @@ class Queue {
33
33
  }
34
34
 
35
35
  /**
36
- * Take a queued task from the front of the queue and run it if ready.
36
+ * Take a queued task from the front of the queue and run it if ready. A task which is not ready yet is kept in the
37
+ * queue (never dropped), a task which is still running is reported as blocking and left to finish on its own, and
38
+ * completed tasks are discarded.
37
39
  * @return {completeResponse|*}
38
40
  */
39
41
  dequeue () {
40
- const next = this.remove()
42
+ let next = this.remove()
43
+ // Tasks which already completed are discarded when they reach the front of the queue
44
+ while (next && next.complete) {
45
+ next = this.remove()
46
+ }
41
47
  if (!next) {
42
48
  return {
43
49
  success: 'No more queueable tasks in the queue',
@@ -45,31 +51,30 @@ class Queue {
45
51
  context: this.queuedList
46
52
  }
47
53
  }
48
- if (next.complete) {
49
- // Previously ran queued, run next
50
- return this.dequeue()
51
- }
52
54
  if (next.running) {
55
+ // The unfinished task reports back through its own complete callback, so it is not kept in the queue
53
56
  return {
54
57
  success: false,
55
58
  error: 'The queue has been blocked by an unfinished task.',
56
59
  context: next
57
60
  }
58
61
  }
62
+ if (!next.isReady) {
63
+ // Keep the task (at the back, so the next dequeue can try the other tasks) rather than losing it
64
+ this.enqueue(next)
65
+ // We could go check the next in queue here but if we end up in a state where nothing is ready it would infinite loop
66
+ // Also, we want the loop handled externally
67
+ return {
68
+ success: false,
69
+ error: 'Unable to find ready task.',
70
+ context: next
71
+ }
72
+ }
59
73
  if (!this.empty()) {
60
74
  // Place back in queue to be checked once again next time, only if the queue will not be empty
61
75
  this.enqueue(next)
62
76
  }
63
- if (next.isReady) {
64
- return next.run.call(next)
65
- }
66
- // We could go check the next in queue here but if we end up in a state where nothing is ready it would infinite loop
67
- // Also, we want the loop handled externally
68
- return {
69
- success: false,
70
- error: 'Unable to find ready task.',
71
- context: next
72
- }
77
+ return next.run.call(next)
73
78
  }
74
79
 
75
80
  /**
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Queue=void 0;var _Queueable=require("./Queueable"),_LinkedList=require("../linked-list/LinkedList");class Queue{constructor(e=null,u=_LinkedList.LinkedList,t=_Queueable.Queueable){this.listClass=u,this.queueableClass=t,null===e&&(e=new u(t)),this.queuedList=e}dequeue(){const e=this.remove();return e?e.complete?this.dequeue():e.running?{success:!1,error:"The queue has been blocked by an unfinished task.",context:e}:(this.empty()||this.enqueue(e),e.isReady?e.run.call(e):{success:!1,error:"Unable to find ready task.",context:e}):{success:"No more queueable tasks in the queue",error:!1,context:this.queuedList}}empty(){return this.size()<=0}enqueue(e){this.queuedList.append(e)}peek(){return this.queuedList.first}remove(){return this.empty()?null:this.queuedList.remove(this.queuedList.first)}size(){return this.queuedList.length}}exports.Queue=Queue,Queue.fromArray=(e=[],u=_Queueable.Queueable,t=_LinkedList.LinkedList)=>{const s=new t(u);return s.initialize(u.fromArray(e,u).head),new Queue(s,t,u)};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Queue=void 0;var _Queueable=require("./Queueable"),_LinkedList=require("../linked-list/LinkedList");class Queue{constructor(e=null,u=_LinkedList.LinkedList,t=_Queueable.Queueable){this.listClass=u,this.queueableClass=t,null===e&&(e=new u(t)),this.queuedList=e}dequeue(){let e=this.remove();for(;e&&e.complete;)e=this.remove();return e?e.running?{success:!1,error:"The queue has been blocked by an unfinished task.",context:e}:e.isReady?(this.empty()||this.enqueue(e),e.run.call(e)):(this.enqueue(e),{success:!1,error:"Unable to find ready task.",context:e}):{success:"No more queueable tasks in the queue",error:!1,context:this.queuedList}}empty(){return this.size()<=0}enqueue(e){this.queuedList.append(e)}peek(){return this.queuedList.first}remove(){return this.empty()?null:this.queuedList.remove(this.queuedList.first)}size(){return this.queuedList.length}}exports.Queue=Queue,Queue.fromArray=(e=[],u=_Queueable.Queueable,t=_LinkedList.LinkedList)=>{const s=new t(u);return s.initialize(u.fromArray(e,u).head),new Queue(s,t,u)};
@@ -11,15 +11,21 @@ import { IsLinker } from '../../recipes/IsLinker';
11
11
  * @extends Linker
12
12
  */
13
13
  export declare class Queueable implements IsLinker, IsRunnable {
14
+ /** The class used to create this instance, so that it can be recognized as valid without an instanceof check. */
14
15
  readonly classType: typeof Queueable;
16
+ /** The task (or data) this queueable holds. */
15
17
  data: any;
18
+ /** The queueable after this one, or null when this is the last. */
16
19
  next: Queueable | null;
20
+ /** Whether this queueable has been run to completion. */
17
21
  complete: boolean;
22
+ /** Whether this queueable may run, or a function which answers that when asked. */
18
23
  ready: Function | boolean;
24
+ /** Whether this queueable is running right now. */
19
25
  running: boolean;
20
26
  /**
21
27
  * Create a queueable item that can be used in a queue.
22
- * @param {Object} [queueableData={}]
28
+ * @param {Object} [queueableData={}] The settings for the new queueable.
23
29
  * @param {*} [queueableData.task=null] The data to be stored in this queueable
24
30
  * @param {Queueable|null} [queueableData.next=null] The reference to the next queueable if any
25
31
  * @param {boolean|Function} [queueableData.ready=false] Indicate if the queueable is ready to run
@@ -27,7 +33,7 @@ export declare class Queueable implements IsLinker, IsRunnable {
27
33
  constructor({ task, next, ready }?: {
28
34
  task?: any;
29
35
  next?: Queueable | null;
30
- ready?: boolean;
36
+ ready?: boolean | Function;
31
37
  });
32
38
  /**
33
39
  * Check ready state.
@@ -41,7 +47,7 @@ export declare class Queueable implements IsLinker, IsRunnable {
41
47
  get task(): any;
42
48
  /**
43
49
  * Set this queueable as completed.
44
- * @param {Object} completeResponse
50
+ * @param {Object} [completeResponse={}] The result to report for the task.
45
51
  * @param {*} [completeResponse.success=true] Indicate when the task failed (use false) or give a success message
46
52
  * @param {*} [completeResponse.error=false] Indicate a task was error-free (use false) or give an error message
47
53
  * @param {*} [completeResponse.context=null] Provide additional data in the response
@@ -70,7 +76,7 @@ export declare class Queueable implements IsLinker, IsRunnable {
70
76
  * @param {IsLinker} [classType=Queueable] Provide the type of IsLinker to use.
71
77
  * @returns {{head: Queueable, tail: Queueable}}
72
78
  */
73
- static fromArray: (values: Array<any>, classType?: any) => {
79
+ static fromArray: (values?: Array<any>, classType?: any) => {
74
80
  head: IsLinker;
75
81
  tail: IsLinker;
76
82
  };
@@ -12,7 +12,7 @@ var _Linker = require('../linked-list/Linker')
12
12
  class Queueable {
13
13
  /**
14
14
  * Create a queueable item that can be used in a queue.
15
- * @param {Object} [queueableData={}]
15
+ * @param {Object} [queueableData={}] The settings for the new queueable.
16
16
  * @param {*} [queueableData.task=null] The data to be stored in this queueable
17
17
  * @param {Queueable|null} [queueableData.next=null] The reference to the next queueable if any
18
18
  * @param {boolean|Function} [queueableData.ready=false] Indicate if the queueable is ready to run
@@ -22,10 +22,15 @@ class Queueable {
22
22
  next = null,
23
23
  ready = false
24
24
  } = {}) {
25
+ /** The task (or data) this queueable holds. */
25
26
  this.data = null
27
+ /** The queueable after this one, or null when this is the last. */
26
28
  this.next = null
29
+ /** Whether this queueable has been run to completion. */
27
30
  this.complete = false
31
+ /** Whether this queueable may run, or a function which answers that when asked. */
28
32
  this.ready = false
33
+ /** Whether this queueable is running right now. */
29
34
  this.running = false
30
35
  this.classType = Queueable
31
36
  this.data = task
@@ -58,7 +63,7 @@ class Queueable {
58
63
 
59
64
  /**
60
65
  * Set this queueable as completed.
61
- * @param {Object} completeResponse
66
+ * @param {Object} [completeResponse={}] The result to report for the task.
62
67
  * @param {*} [completeResponse.success=true] Indicate when the task failed (use false) or give a success message
63
68
  * @param {*} [completeResponse.error=false] Indicate a task was error-free (use false) or give an error message
64
69
  * @param {*} [completeResponse.context=null] Provide additional data in the response
@@ -112,8 +117,8 @@ class Queueable {
112
117
  */
113
118
  exports.Queueable = Queueable
114
119
  Queueable.make = (queueable, classType = Queueable) => {
115
- if (typeof queueable !== 'object') {
116
- // It is not an object, so instantiate the Queueable with an element as the data
120
+ if (queueable === null || typeof queueable !== 'object') {
121
+ // It is not an object (or it is null), so instantiate the Queueable with an element as the data
117
122
  return new classType({
118
123
  task: queueable,
119
124
  ready: true
@@ -123,7 +128,7 @@ Queueable.make = (queueable, classType = Queueable) => {
123
128
  // Already valid Queueable, return as-is
124
129
  return queueable
125
130
  }
126
- if (!queueable.task) {
131
+ if (!('task' in queueable)) {
127
132
  queueable = {
128
133
  task: queueable,
129
134
  ready: true
@@ -138,4 +143,4 @@ Queueable.make = (queueable, classType = Queueable) => {
138
143
  * @param {IsLinker} [classType=Queueable] Provide the type of IsLinker to use.
139
144
  * @returns {{head: Queueable, tail: Queueable}}
140
145
  */
141
- Queueable.fromArray = (values, classType = Queueable) => _Linker.Linker.fromArray(values, classType)
146
+ Queueable.fromArray = (values = [], classType = Queueable) => _Linker.Linker.fromArray(values, classType)
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Queueable=void 0;var _Linker=require("../linked-list/Linker");class Queueable{constructor({task:e=null,next:t=null,ready:s=!1}={}){this.data=null,this.next=null,this.complete=!1,this.ready=!1,this.running=!1,this.classType=Queueable,this.data=e,this.next=t,this.complete=!1,this.ready=s,this.running=!1}get isReady(){return"function"==typeof this.ready?this.ready():this.ready}get task(){return"function"==typeof this.data?this.data:e=>"function"==typeof e?e({context:this.data}).context:this.data}markCompleted({success:e=!0,error:t=!1,context:s=null}={}){return this.complete=!0,this.running=!1,{success:e,error:t,context:s}}run(){return this.isReady?this.running?{success:!1,error:"Queued task is already running, possible missing 'complete' callback",context:this.data}:(this.running=!0,this.task(this.markCompleted.bind(this))):{success:!1,error:"Task is not ready",context:this.data}}}exports.Queueable=Queueable,Queueable.make=(e,t=Queueable)=>"object"!=typeof e?new t({task:e,ready:!0}):e.classType?e:(e.task||(e={task:e,ready:!0}),new t(e)),Queueable.fromArray=(e,t=Queueable)=>_Linker.Linker.fromArray(e,t);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Queueable=void 0;var _Linker=require("../linked-list/Linker");class Queueable{constructor({task:e=null,next:t=null,ready:s=!1}={}){this.data=null,this.next=null,this.complete=!1,this.ready=!1,this.running=!1,this.classType=Queueable,this.data=e,this.next=t,this.complete=!1,this.ready=s,this.running=!1}get isReady(){return"function"==typeof this.ready?this.ready():this.ready}get task(){return"function"==typeof this.data?this.data:e=>"function"==typeof e?e({context:this.data}).context:this.data}markCompleted({success:e=!0,error:t=!1,context:s=null}={}){return this.complete=!0,this.running=!1,{success:e,error:t,context:s}}run(){return this.isReady?this.running?{success:!1,error:"Queued task is already running, possible missing 'complete' callback",context:this.data}:(this.running=!0,this.task(this.markCompleted.bind(this))):{success:!1,error:"Task is not ready",context:this.data}}}exports.Queueable=Queueable,Queueable.make=(e,t=Queueable)=>null===e||"object"!=typeof e?new t({task:e,ready:!0}):e.classType?e:("task"in e||(e={task:e,ready:!0}),new t(e)),Queueable.fromArray=(e=[],t=Queueable)=>_Linker.Linker.fromArray(e,t);
@@ -12,14 +12,15 @@ import { completeResponse } from '../../recipes/Runnable';
12
12
  * Store a collection of items which can only be inserted and removed from the top.
13
13
  */
14
14
  export declare class Stack {
15
+ /** The list which stores the stackables, the first is the top of the stack. */
15
16
  stackedList: IsArrayable<any>;
16
17
  private listClass;
17
18
  private stackableClass;
18
19
  /**
19
20
  * Instantiate the state with the starter stacked list.
20
- * @param {Iterable|LinkedList} stackedList
21
- * @param {IsArrayable} listClass
22
- * @param {Stackable} stackableClass
21
+ * @param {Iterable|LinkedList} [stackedList=null] The list of stackables to start in this stack.
22
+ * @param {IsArrayable} [listClass=LinkedList] The type of list to create when no stacked list is given.
23
+ * @param {Stackable} [stackableClass=Stackable] The class used to wrap stacked items.
23
24
  */
24
25
  constructor(stackedList?: IsArrayable<any>, listClass?: any, stackableClass?: typeof Stackable);
25
26
  /**
@@ -19,9 +19,9 @@ var _LinkedList = require('../linked-list/LinkedList')
19
19
  class Stack {
20
20
  /**
21
21
  * Instantiate the state with the starter stacked list.
22
- * @param {Iterable|LinkedList} stackedList
23
- * @param {IsArrayable} listClass
24
- * @param {Stackable} stackableClass
22
+ * @param {Iterable|LinkedList} [stackedList=null] The list of stackables to start in this stack.
23
+ * @param {IsArrayable} [listClass=LinkedList] The type of list to create when no stacked list is given.
24
+ * @param {Stackable} [stackableClass=Stackable] The class used to wrap stacked items.
25
25
  */
26
26
  constructor (stackedList = null, listClass = _LinkedList.LinkedList, stackableClass = _Stackable.Stackable) {
27
27
  this.listClass = listClass
@@ -102,5 +102,5 @@ exports.Stack = Stack
102
102
  Stack.fromArray = (values = [], stackableClass = _Stackable.Stackable, listClass = _LinkedList.LinkedList) => {
103
103
  const list = new listClass(stackableClass)
104
104
  list.initialize(stackableClass.fromArray(values, stackableClass).head)
105
- return new Stack(list)
105
+ return new Stack(list, listClass, stackableClass)
106
106
  }
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Stack=void 0;var _Stackable=require("./Stackable"),_LinkedList=require("../linked-list/LinkedList");class Stack{constructor(t=null,e=_LinkedList.LinkedList,s=_Stackable.Stackable){this.listClass=e,this.stackableClass=s,null===t&&(t=new e(s)),this.stackedList=t}empty(){return this.size()<=0}top(){return this.stackedList.first}pop(){const t=this.remove();return t?t.run():{success:"No more stackable tasks in the stack",error:!1,context:this.stackedList}}push(t){this.stackedList.prepend(t)}remove(){return this.empty()?null:this.stackedList.remove(this.stackedList.first)}size(){return this.stackedList.length}}exports.Stack=Stack,Stack.fromArray=(t=[],e=_Stackable.Stackable,s=_LinkedList.LinkedList)=>{const i=new s(e);return i.initialize(e.fromArray(t,e).head),new Stack(i)};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Stack=void 0;var _Stackable=require("./Stackable"),_LinkedList=require("../linked-list/LinkedList");class Stack{constructor(t=null,e=_LinkedList.LinkedList,s=_Stackable.Stackable){this.listClass=e,this.stackableClass=s,null===t&&(t=new e(s)),this.stackedList=t}empty(){return this.size()<=0}top(){return this.stackedList.first}pop(){const t=this.remove();return t?t.run():{success:"No more stackable tasks in the stack",error:!1,context:this.stackedList}}push(t){this.stackedList.prepend(t)}remove(){return this.empty()?null:this.stackedList.remove(this.stackedList.first)}size(){return this.stackedList.length}}exports.Stack=Stack,Stack.fromArray=(t=[],e=_Stackable.Stackable,s=_LinkedList.LinkedList)=>{const i=new s(e);return i.initialize(e.fromArray(t,e).head),new Stack(i,s,e)};
@@ -11,12 +11,15 @@ import { IsLinker } from '../../recipes/IsLinker';
11
11
  * @extends Linker
12
12
  */
13
13
  export declare class Stackable implements IsLinker, IsRunnable {
14
+ /** The class used to create this instance, so that it can be recognized as valid without an instanceof check. */
14
15
  readonly classType: typeof Stackable;
16
+ /** The task (or data) this stackable holds. */
15
17
  data: any;
18
+ /** The stackable below this one, or null when this is the bottom. */
16
19
  next: Stackable | null;
17
20
  /**
18
21
  * Create a stackable item that can be used in a stack.
19
- * @param {Object} [stackData={}]
22
+ * @param {Object} [stackData={}] The settings for the new stackable.
20
23
  * @param {*} [stackData.task=null] The data to be stored in this stackable
21
24
  * @param {Stackable|null} [stackData.next=null] The reference to the next stackable if any
22
25
  * @param {boolean|Function} [stackData.ready=false] Indicate if the stackable is ready to run