@stacksjs/collections 0.65.0 → 0.68.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/dist/index.js +1 -4
- package/package.json +3 -5
- package/dist/index.js.map +0 -17
- package/src/helpers/clone.ts +0 -17
- package/src/helpers/delete-keys.ts +0 -16
- package/src/helpers/index.ts +0 -6
- package/src/helpers/is.ts +0 -23
- package/src/helpers/nested-value.ts +0 -17
- package/src/helpers/values.ts +0 -19
- package/src/helpers/variadic.ts +0 -13
- package/src/index.ts +0 -2024
package/src/index.ts
DELETED
|
@@ -1,2024 +0,0 @@
|
|
|
1
|
-
/* eslint-disable ts/no-unsafe-function-type,eqeqeq,ts/no-use-before-define,unused-imports/no-unused-vars,no-prototype-builtins, no-console */
|
|
2
|
-
import process from 'node:process'
|
|
3
|
-
import { clone, deleteKeys, isArray, isFunction, isObject, nestedValue, values } from './helpers/'
|
|
4
|
-
|
|
5
|
-
type IsArray<T> = T extends any[] ? true : false
|
|
6
|
-
type CollectionAll<T> = IsArray<T> extends true ? T : { [K in keyof T]: T[K] }
|
|
7
|
-
|
|
8
|
-
export function collect<T extends object | string | number | boolean>(items: T): Collection<T> {
|
|
9
|
-
return new Collection(items)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export class Collection<T> {
|
|
13
|
-
protected items: T[] | Record<string, T>
|
|
14
|
-
|
|
15
|
-
constructor(items: T[] | Record<string | number | symbol, T> = []) {
|
|
16
|
-
this.items = items
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
[Symbol.iterator] = SymbolIterator
|
|
20
|
-
|
|
21
|
-
toJSON(): T[] {
|
|
22
|
-
return this.items as T[]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
all(): CollectionAll<T> {
|
|
26
|
-
return this.items as CollectionAll<T>
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
average(key?: string | ((item: T) => number)): number {
|
|
30
|
-
if (key === undefined) {
|
|
31
|
-
return this.sum() / Number(this.items.length)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (isFunction(key)) {
|
|
35
|
-
return (
|
|
36
|
-
Number(new (this.constructor as new (items: typeof this.items) => typeof this)(this.items).sum(key))
|
|
37
|
-
/ Number(this.items.length)
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
Number(new (this.constructor as new (items: typeof this.items) => typeof this)(this.items).pluck(key).sum())
|
|
43
|
-
/ Number(this.items.length)
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
avg: typeof this.average = this.average
|
|
48
|
-
|
|
49
|
-
chunk(size: number): Collection<T[]> {
|
|
50
|
-
const chunks = []
|
|
51
|
-
const items = Array.isArray(this.items) ? this.items : Object.values(this.items)
|
|
52
|
-
|
|
53
|
-
for (let i = 0; i < items.length; i += size) {
|
|
54
|
-
chunks.push(items.slice(i, i + size))
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return new Collection(chunks)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
collapse(): Collection<T extends any[] ? T[number] : T> {
|
|
61
|
-
return new (this.constructor as any)(([] as T[]).concat(...(this.items as any[])))
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
combine(values: any): Collection<T> {
|
|
65
|
-
if (typeof values === 'string') {
|
|
66
|
-
values = [values]
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (!Array.isArray(values)) {
|
|
70
|
-
throw new TypeError('The values must be an array or a string')
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const collection = {}
|
|
74
|
-
const keys = Array.isArray(this.items) ? this.items : Object.keys(this.items)
|
|
75
|
-
|
|
76
|
-
keys.forEach((key, index) => {
|
|
77
|
-
if (values[index] !== undefined) {
|
|
78
|
-
collection[key] = values[index]
|
|
79
|
-
}
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
return new Collection(collection)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
concat(collectionOrArrayOrObject: Collection<T> | T[] | object): Collection<T> {
|
|
86
|
-
let list = collectionOrArrayOrObject
|
|
87
|
-
|
|
88
|
-
if (collectionOrArrayOrObject instanceof this.constructor) {
|
|
89
|
-
list = collectionOrArrayOrObject.all()
|
|
90
|
-
}
|
|
91
|
-
else if (typeof collectionOrArrayOrObject === 'object') {
|
|
92
|
-
list = []
|
|
93
|
-
Object.keys(collectionOrArrayOrObject).forEach((property) => {
|
|
94
|
-
list.push(collectionOrArrayOrObject[property])
|
|
95
|
-
})
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const collection = clone(this.items)
|
|
99
|
-
|
|
100
|
-
list.forEach((item) => {
|
|
101
|
-
if (typeof item === 'object') {
|
|
102
|
-
Object.keys(item).forEach(key => collection.push(item[key]))
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
collection.push(item)
|
|
106
|
-
}
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
return new this.constructor(collection)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
contains(key: T extends (infer U)[] ? U : T | string | ((item: T, index: number) => boolean), value?: any): boolean {
|
|
113
|
-
if (typeof key === 'function') {
|
|
114
|
-
return this.items.some(key as (item: T, index: number) => boolean)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (Array.isArray(this.items)) {
|
|
118
|
-
return (this.items as any[]).includes(key as any)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (value !== undefined) {
|
|
122
|
-
if (Array.isArray(this.items)) {
|
|
123
|
-
return this.items.some(item => item[key as keyof T] !== undefined && item[key as keyof T] === value)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return (
|
|
127
|
-
(key as string | number | symbol) in this.items
|
|
128
|
-
&& (this.items as Record<keyof T, any>)[key as keyof T] === value
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (Array.isArray(this.items)) {
|
|
133
|
-
return this.items.includes(key as T extends (infer U)[] ? U : never)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return Object.values(this.items).includes(key as T extends object ? T[keyof T] : never)
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
containsOneItem(): boolean {
|
|
140
|
-
if (typeof this.items === 'string') {
|
|
141
|
-
return true
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return Object.keys(this.items).length === 1
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
count(predicate?: (item: T) => boolean): number {
|
|
148
|
-
if (predicate) {
|
|
149
|
-
return this.filter(predicate).count()
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return Object.keys(this.items).length
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
countBy(callback?: (item: T) => string | number): Collection<number> {
|
|
156
|
-
const counts: Record<string | number, number> = {}
|
|
157
|
-
this.each((item) => {
|
|
158
|
-
const key = callback ? callback(item) : item
|
|
159
|
-
counts[key] = (counts[key] || 0) + 1
|
|
160
|
-
})
|
|
161
|
-
return new Collection(counts)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
crossJoin(...values: T[]): Collection<T> {
|
|
165
|
-
function join(collection: T[], constructor: new (items: T[]) => Collection<T>, args: T[]): T[] {
|
|
166
|
-
let current = args[0]
|
|
167
|
-
|
|
168
|
-
if (current instanceof Collection) {
|
|
169
|
-
current = current.all()
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const rest = args.slice(1)
|
|
173
|
-
const last = !rest.length
|
|
174
|
-
let result = []
|
|
175
|
-
|
|
176
|
-
for (let i = 0; i < current.length; i += 1) {
|
|
177
|
-
const collectionCopy = collection.slice()
|
|
178
|
-
collectionCopy.push(current[i])
|
|
179
|
-
|
|
180
|
-
if (last) {
|
|
181
|
-
result.push(collectionCopy)
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
result = result.concat(join(collectionCopy, constructor, rest))
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return result
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return new this.constructor(join([], this.constructor, [].concat([this.items], values)))
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
dd(): void {
|
|
195
|
-
console.log(JSON.stringify(this.all(), null, 2))
|
|
196
|
-
process.exit()
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
diff(values: Collection<T> | T[]): Collection<T> {
|
|
200
|
-
let valuesToDiff
|
|
201
|
-
|
|
202
|
-
if (values instanceof this.constructor) {
|
|
203
|
-
valuesToDiff = values.all()
|
|
204
|
-
}
|
|
205
|
-
else {
|
|
206
|
-
valuesToDiff = values
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const collection = this.items.filter(item => !valuesToDiff.includes(item))
|
|
210
|
-
|
|
211
|
-
return new this.constructor(collection)
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
diffAssoc(values: Collection<T> | T[]): Collection<T> {
|
|
215
|
-
let diffValues = values
|
|
216
|
-
|
|
217
|
-
if (values instanceof this.constructor) {
|
|
218
|
-
diffValues = values.all()
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const collection = {}
|
|
222
|
-
|
|
223
|
-
Object.keys(this.items).forEach((key) => {
|
|
224
|
-
if (diffValues[key] === undefined || diffValues[key] !== this.items[key]) {
|
|
225
|
-
collection[key] = this.items[key]
|
|
226
|
-
}
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
return new this.constructor(collection)
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
diffKeys(object: Collection<T> | T[]): Collection<T> {
|
|
233
|
-
let objectToDiff
|
|
234
|
-
|
|
235
|
-
if (object instanceof this.constructor) {
|
|
236
|
-
objectToDiff = object.all()
|
|
237
|
-
}
|
|
238
|
-
else {
|
|
239
|
-
objectToDiff = object
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const objectKeys = Object.keys(objectToDiff)
|
|
243
|
-
|
|
244
|
-
const remainingKeys = Object.keys(this.items).filter(item => !objectKeys.includes(item))
|
|
245
|
-
|
|
246
|
-
return new this.constructor(this.items).only(remainingKeys)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
diffUsing(array: any[] | null, callback: (a: any, b: any) => number): Collection<T> {
|
|
250
|
-
console.log('Original collection:', this.items)
|
|
251
|
-
|
|
252
|
-
console.log('Array to compare:', array)
|
|
253
|
-
|
|
254
|
-
if (array === null) {
|
|
255
|
-
// If the input array is null, return a copy of the original collection
|
|
256
|
-
return new Collection(this.items)
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const collection = this.items.filter((item) => {
|
|
260
|
-
const index = array.findIndex((otherItem) => {
|
|
261
|
-
return callback(item, otherItem) === 0
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
return index === -1
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
return new Collection(collection)
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
doesntContain(key: string | number | symbol | ((item: T, index: number) => boolean), value?: any): boolean {
|
|
271
|
-
console.log('doesntContain called with:', { key, value })
|
|
272
|
-
|
|
273
|
-
if (typeof key === 'function') {
|
|
274
|
-
console.log('Function branch')
|
|
275
|
-
return !this.contains(key)
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
if (value !== undefined) {
|
|
279
|
-
console.log('Key-value pair branch')
|
|
280
|
-
return !this.contains((item) => {
|
|
281
|
-
console.log('Comparing:', item[key], 'with', value)
|
|
282
|
-
return item[key] === value
|
|
283
|
-
})
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
console.log('Single value branch')
|
|
287
|
-
return !this.contains(key)
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
dump(): this {
|
|
291
|
-
console.log(this.items)
|
|
292
|
-
return this
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
duplicates(): Collection<T> {
|
|
296
|
-
const occuredValues = []
|
|
297
|
-
const duplicateValues = {}
|
|
298
|
-
|
|
299
|
-
const stringifiedValue = (value: any): string => {
|
|
300
|
-
if (Array.isArray(value) || typeof value === 'object') {
|
|
301
|
-
return JSON.stringify(value)
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return value
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
if (Array.isArray(this.items)) {
|
|
308
|
-
this.items.forEach((value, index) => {
|
|
309
|
-
const valueAsString = stringifiedValue(value)
|
|
310
|
-
|
|
311
|
-
if (!occuredValues.includes(valueAsString)) {
|
|
312
|
-
occuredValues.push(valueAsString)
|
|
313
|
-
}
|
|
314
|
-
else {
|
|
315
|
-
duplicateValues[index] = value
|
|
316
|
-
}
|
|
317
|
-
})
|
|
318
|
-
}
|
|
319
|
-
else if (typeof this.items === 'object') {
|
|
320
|
-
Object.keys(this.items).forEach((key) => {
|
|
321
|
-
const valueAsString = stringifiedValue(this.items[key])
|
|
322
|
-
|
|
323
|
-
if (!occuredValues.includes(valueAsString)) {
|
|
324
|
-
occuredValues.push(valueAsString)
|
|
325
|
-
}
|
|
326
|
-
else {
|
|
327
|
-
duplicateValues[key] = this.items[key]
|
|
328
|
-
}
|
|
329
|
-
})
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
return new this.constructor(duplicateValues)
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
each(fn: (item: T, index: number | string, items: T[]) => boolean | void): Collection<T> {
|
|
336
|
-
let stop = false
|
|
337
|
-
|
|
338
|
-
if (Array.isArray(this.items)) {
|
|
339
|
-
const { length } = this.items
|
|
340
|
-
|
|
341
|
-
for (let index = 0; index < length && !stop; index += 1) {
|
|
342
|
-
stop = fn(this.items[index], index, this.items) === false
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
else {
|
|
346
|
-
const keys = Object.keys(this.items)
|
|
347
|
-
const { length } = keys
|
|
348
|
-
|
|
349
|
-
for (let index = 0; index < length && !stop; index += 1) {
|
|
350
|
-
const key = keys[index]
|
|
351
|
-
|
|
352
|
-
stop = fn(this.items[key], key, this.items) === false
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
return this
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
eachSpread(fn: (...args: any[]) => void): Collection<T> {
|
|
360
|
-
this.each((values: any, key: any) => {
|
|
361
|
-
fn(...values, key)
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
return this
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
every(fn: (value: T, key: string | number, collection: T[]) => boolean): boolean {
|
|
368
|
-
const items = values(this.items)
|
|
369
|
-
|
|
370
|
-
return items.every(fn)
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
except(keys: string | string[]): Collection<T> {
|
|
374
|
-
const result = { ...this.items }
|
|
375
|
-
const keysArray = Array.isArray(keys) ? keys : [keys]
|
|
376
|
-
keysArray.forEach(key => delete result[key])
|
|
377
|
-
return new Collection(result)
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
filter(callback?: (item: T, index: number) => boolean): Collection<T> {
|
|
381
|
-
console.log('Filter method called with callback:', callback)
|
|
382
|
-
|
|
383
|
-
console.log('Current items:', this.items)
|
|
384
|
-
|
|
385
|
-
if (typeof callback !== 'function') {
|
|
386
|
-
console.log('No callback provided, removing falsy values')
|
|
387
|
-
const filteredItems = this.items.filter((item) => {
|
|
388
|
-
console.log('Filtering item:', item)
|
|
389
|
-
return Boolean(item)
|
|
390
|
-
})
|
|
391
|
-
|
|
392
|
-
console.log('Filtered items:', filteredItems)
|
|
393
|
-
return new Collection(filteredItems)
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
const filteredItems = this.items.filter((item, index) => {
|
|
397
|
-
console.log('Filtering item:', item, 'at index:', index)
|
|
398
|
-
return callback(item, index)
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
console.log('Filtered items:', filteredItems)
|
|
402
|
-
return new Collection(filteredItems)
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
first(
|
|
406
|
-
fn?: (value: T, key: string | number, collection?: T[]) => boolean,
|
|
407
|
-
defaultValue?: T | (() => T),
|
|
408
|
-
): T | undefined {
|
|
409
|
-
if (isFunction(fn)) {
|
|
410
|
-
const keys = Object.keys(this.items)
|
|
411
|
-
|
|
412
|
-
for (let i = 0; i < keys.length; i += 1) {
|
|
413
|
-
const key = keys[i]
|
|
414
|
-
const item = this.items[key]
|
|
415
|
-
|
|
416
|
-
if (fn(item, key)) {
|
|
417
|
-
return item
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
if (isFunction(defaultValue)) {
|
|
422
|
-
return defaultValue()
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
return defaultValue
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
if ((Array.isArray(this.items) && this.items.length) || Object.keys(this.items).length) {
|
|
429
|
-
if (Array.isArray(this.items)) {
|
|
430
|
-
return this.items[0]
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
const firstKey = Object.keys(this.items)[0]
|
|
434
|
-
|
|
435
|
-
return this.items[firstKey]
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
if (isFunction(defaultValue)) {
|
|
439
|
-
return defaultValue()
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
return defaultValue
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
firstOrFail(callback?: (item: T) => boolean): T {
|
|
446
|
-
const found = this.items.find(callback || (() => true))
|
|
447
|
-
if (found === undefined) {
|
|
448
|
-
throw new Error('Item not found.')
|
|
449
|
-
}
|
|
450
|
-
return found
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
firstWhere(key: string, operator: string, value: any): T | null {
|
|
454
|
-
return this.where(key, operator, value).first() || null
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
flatMap(fn: (item: T, key: string | number) => any): Collection<any> {
|
|
458
|
-
return this.map(fn).collapse()
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
flatten(depth: number = Number.POSITIVE_INFINITY): Collection<T> {
|
|
462
|
-
const flatten = (item: any, d: number): any[] => {
|
|
463
|
-
if (!Array.isArray(item) && typeof item !== 'object') {
|
|
464
|
-
return [item]
|
|
465
|
-
}
|
|
466
|
-
return d > 0
|
|
467
|
-
? Object.values(item).reduce(
|
|
468
|
-
(acc, val) => acc.concat(Array.isArray(val) || typeof val === 'object' ? flatten(val, d - 1) : val),
|
|
469
|
-
[],
|
|
470
|
-
)
|
|
471
|
-
: Array.isArray(item)
|
|
472
|
-
? [...item]
|
|
473
|
-
: [item]
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
return new Collection(flatten(this.items, depth))
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
flip(): Collection<T> {
|
|
480
|
-
const flipped = {}
|
|
481
|
-
if (Array.isArray(this.items)) {
|
|
482
|
-
this.items.forEach((value, index) => {
|
|
483
|
-
flipped[value] = index
|
|
484
|
-
})
|
|
485
|
-
}
|
|
486
|
-
else {
|
|
487
|
-
Object.entries(this.items).forEach(([key, value]) => {
|
|
488
|
-
flipped[value] = key
|
|
489
|
-
})
|
|
490
|
-
}
|
|
491
|
-
return new this.constructor(flipped)
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
forPage(page: number, chunk: number): Collection<T> {
|
|
495
|
-
let collection = {}
|
|
496
|
-
|
|
497
|
-
if (Array.isArray(this.items)) {
|
|
498
|
-
collection = this.items.slice(page * chunk - chunk, page * chunk)
|
|
499
|
-
}
|
|
500
|
-
else {
|
|
501
|
-
Object.keys(this.items)
|
|
502
|
-
.slice(page * chunk - chunk, page * chunk)
|
|
503
|
-
.forEach((key) => {
|
|
504
|
-
collection[key] = this.items[key]
|
|
505
|
-
})
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
return new this.constructor(collection)
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
forget(key: string): Collection<T> {
|
|
512
|
-
if (Array.isArray(this.items)) {
|
|
513
|
-
this.items = this.items.filter((item, index) => index !== Number.parseInt(key, 10))
|
|
514
|
-
}
|
|
515
|
-
else if (typeof this.items === 'object' && this.items !== null) {
|
|
516
|
-
delete this.items[key]
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
return this
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
get(key: string | number, defaultValue: T | null = null): T | null {
|
|
523
|
-
if (Array.isArray(this.items)) {
|
|
524
|
-
return this.items[key as number] ?? defaultValue
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
return (this.items as Record<string, T>)[key as string] ?? defaultValue
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
groupBy(fn: ((item: T) => any) | string): Collection<Collection<T>> {
|
|
531
|
-
const groups = {}
|
|
532
|
-
this.each((item, key) => {
|
|
533
|
-
const groupKey = typeof fn === 'function' ? fn(item) : item[fn]
|
|
534
|
-
if (!(groupKey in groups)) {
|
|
535
|
-
groups[groupKey] = new Collection()
|
|
536
|
-
}
|
|
537
|
-
groups[groupKey].push(item)
|
|
538
|
-
})
|
|
539
|
-
|
|
540
|
-
return new Collection(groups)
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
has(key: string | number): boolean {
|
|
544
|
-
if (Array.isArray(this.items)) {
|
|
545
|
-
return key in this.items
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
return key in (this.items as Record<string, T>)
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
implode(key: string, glue?: string): string {
|
|
552
|
-
if (glue === undefined) {
|
|
553
|
-
return this.items.join(key)
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
return new this.constructor(this.items).pluck(key).all().join(glue)
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
includes(key: T | T[keyof T]): boolean {
|
|
560
|
-
if (Array.isArray(this.items)) {
|
|
561
|
-
return this.items.includes(key as T)
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
return Object.values(this.items).includes(key)
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
intersect(values: Collection<T> | T[]): Collection<T> {
|
|
568
|
-
let intersectValues = values
|
|
569
|
-
|
|
570
|
-
if (values instanceof this.constructor) {
|
|
571
|
-
intersectValues = values.all()
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
const collection = this.items.filter(item => intersectValues.includes(item))
|
|
575
|
-
|
|
576
|
-
return new this.constructor(collection)
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
intersectByKeys(values: Collection<T> | T[]): Collection<T> {
|
|
580
|
-
let intersectKeys = Object.keys(values)
|
|
581
|
-
|
|
582
|
-
if (values instanceof this.constructor) {
|
|
583
|
-
intersectKeys = Object.keys(values.all())
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
const collection = {}
|
|
587
|
-
|
|
588
|
-
Object.keys(this.items).forEach((key) => {
|
|
589
|
-
if (intersectKeys.includes(key)) {
|
|
590
|
-
collection[key] = this.items[key]
|
|
591
|
-
}
|
|
592
|
-
})
|
|
593
|
-
|
|
594
|
-
return new this.constructor(collection)
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
isEmpty(): boolean {
|
|
598
|
-
return this.count() === 0
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
isNotEmpty(): boolean {
|
|
602
|
-
return !this.isEmpty()
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
join(glue: string, finalGlue?: string): string {
|
|
606
|
-
const collection = this.values()
|
|
607
|
-
|
|
608
|
-
if (finalGlue === undefined) {
|
|
609
|
-
return collection.implode(glue)
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
const count = collection.count()
|
|
613
|
-
|
|
614
|
-
if (count === 0) {
|
|
615
|
-
return ''
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
if (count === 1) {
|
|
619
|
-
return collection.last()
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
const finalItem = collection.pop()
|
|
623
|
-
|
|
624
|
-
return collection.implode(glue) + finalGlue + finalItem
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
keyBy(key: string | ((item: T) => string)): Collection<T> {
|
|
628
|
-
const collection = {}
|
|
629
|
-
|
|
630
|
-
if (isFunction(key)) {
|
|
631
|
-
this.items.forEach((item) => {
|
|
632
|
-
collection[key(item)] = item
|
|
633
|
-
})
|
|
634
|
-
}
|
|
635
|
-
else {
|
|
636
|
-
this.items.forEach((item) => {
|
|
637
|
-
const keyValue = nestedValue(item, key)
|
|
638
|
-
|
|
639
|
-
collection[keyValue || ''] = item
|
|
640
|
-
})
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
return new this.constructor(collection)
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
keys(): Collection<string> {
|
|
647
|
-
return new Collection(Object.keys(this.items))
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
last(fn?: (item: T) => boolean, defaultValue?: T | (() => T)): T {
|
|
651
|
-
let { items } = this
|
|
652
|
-
|
|
653
|
-
if (isFunction(fn)) {
|
|
654
|
-
items = this.filter(fn).all()
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
if ((Array.isArray(items) && !items.length) || !Object.keys(items).length) {
|
|
658
|
-
if (isFunction(defaultValue)) {
|
|
659
|
-
return defaultValue()
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
return defaultValue
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
if (Array.isArray(items)) {
|
|
666
|
-
return items[items.length - 1]
|
|
667
|
-
}
|
|
668
|
-
const keys = Object.keys(items)
|
|
669
|
-
|
|
670
|
-
return items[keys[keys.length - 1]]
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
macro(name: string, fn: Function): void {
|
|
674
|
-
this.constructor.prototype[name] = fn
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
make(items: T[] = []): Collection<T> {
|
|
678
|
-
return new this.constructor(items)
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
map(fn: (item: T, index: number) => any): Collection<any> {
|
|
682
|
-
if (Array.isArray(this.items)) {
|
|
683
|
-
return new this.constructor(this.items.map(fn))
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
const collection = {}
|
|
687
|
-
|
|
688
|
-
Object.keys(this.items).forEach((key) => {
|
|
689
|
-
collection[key] = fn(this.items[key], Number(key))
|
|
690
|
-
})
|
|
691
|
-
|
|
692
|
-
return new this.constructor(collection)
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
mapSpread(fn: (...args: any[]) => any): Collection<any> {
|
|
696
|
-
return this.map((values, key) => fn(...values, key))
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
mapToDictionary(fn: (item: T, key: number) => [string, any]): Collection<any[]> {
|
|
700
|
-
const collection = {}
|
|
701
|
-
|
|
702
|
-
this.items.forEach((item, k) => {
|
|
703
|
-
const [key, value] = fn(item, k)
|
|
704
|
-
|
|
705
|
-
if (collection[key] === undefined) {
|
|
706
|
-
collection[key] = [value]
|
|
707
|
-
}
|
|
708
|
-
else {
|
|
709
|
-
collection[key].push(value)
|
|
710
|
-
}
|
|
711
|
-
})
|
|
712
|
-
|
|
713
|
-
return new this.constructor(collection)
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
mapInto(ClassName: new (value: T, key: number | string) => any): Collection<any> {
|
|
717
|
-
return this.map((value, key) => new ClassName(value, key))
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
mapToGroups(fn: (item: T, key: number) => [string, any]): Collection<any[]> {
|
|
721
|
-
const collection = {}
|
|
722
|
-
|
|
723
|
-
this.items.forEach((item, key) => {
|
|
724
|
-
const [keyed, value] = fn(item, key)
|
|
725
|
-
|
|
726
|
-
if (collection[keyed] === undefined) {
|
|
727
|
-
collection[keyed] = [value]
|
|
728
|
-
}
|
|
729
|
-
else {
|
|
730
|
-
collection[keyed].push(value)
|
|
731
|
-
}
|
|
732
|
-
})
|
|
733
|
-
|
|
734
|
-
return new this.constructor(collection)
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
mapWithKeys(fn: (item: T, index: number) => [string, any]): Collection<any> {
|
|
738
|
-
const collection = {}
|
|
739
|
-
|
|
740
|
-
if (Array.isArray(this.items)) {
|
|
741
|
-
this.items.forEach((item, index) => {
|
|
742
|
-
const [keyed, value] = fn(item, index)
|
|
743
|
-
collection[keyed] = value
|
|
744
|
-
})
|
|
745
|
-
}
|
|
746
|
-
else {
|
|
747
|
-
Object.keys(this.items).forEach((key) => {
|
|
748
|
-
const [keyed, value] = fn(this.items[key], Number(key))
|
|
749
|
-
collection[keyed] = value
|
|
750
|
-
})
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
return new this.constructor(collection)
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
max(key?: string): number {
|
|
757
|
-
if (typeof key === 'string') {
|
|
758
|
-
const filtered = this.items.filter(item => item[key] !== undefined)
|
|
759
|
-
|
|
760
|
-
return Math.max(...filtered.map(item => item[key]))
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
return Math.max(...this.items)
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
median(key?: string): number {
|
|
767
|
-
const { length } = this.items
|
|
768
|
-
|
|
769
|
-
if (key === undefined) {
|
|
770
|
-
if (length % 2 === 0) {
|
|
771
|
-
return (this.items[length / 2 - 1] + this.items[length / 2]) / 2
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
return this.items[Math.floor(length / 2)]
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
if (length % 2 === 0) {
|
|
778
|
-
return (this.items[length / 2 - 1][key] + this.items[length / 2][key]) / 2
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
return this.items[Math.floor(length / 2)][key]
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
merge(object: object): Collection<T> {
|
|
785
|
-
const merged = { ...this.items, ...object }
|
|
786
|
-
|
|
787
|
-
return new Collection(merged)
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
mergeRecursive(items: T | T[] | Collection<T>): Collection<T> {
|
|
791
|
-
const merge = (target: any, source: any): any => {
|
|
792
|
-
const merged = {}
|
|
793
|
-
|
|
794
|
-
const mergedKeys = Object.keys({ ...target, ...source })
|
|
795
|
-
|
|
796
|
-
mergedKeys.forEach((key) => {
|
|
797
|
-
if (target[key] === undefined && source[key] !== undefined) {
|
|
798
|
-
merged[key] = source[key]
|
|
799
|
-
}
|
|
800
|
-
else if (target[key] !== undefined && source[key] === undefined) {
|
|
801
|
-
merged[key] = target[key]
|
|
802
|
-
}
|
|
803
|
-
else if (target[key] !== undefined && source[key] !== undefined) {
|
|
804
|
-
if (target[key] === source[key]) {
|
|
805
|
-
merged[key] = target[key]
|
|
806
|
-
}
|
|
807
|
-
else if (
|
|
808
|
-
!Array.isArray(target[key])
|
|
809
|
-
&& typeof target[key] === 'object'
|
|
810
|
-
&& !Array.isArray(source[key])
|
|
811
|
-
&& typeof source[key] === 'object'
|
|
812
|
-
) {
|
|
813
|
-
merged[key] = merge(target[key], source[key])
|
|
814
|
-
}
|
|
815
|
-
else {
|
|
816
|
-
merged[key] = [].concat(target[key], source[key])
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
})
|
|
820
|
-
|
|
821
|
-
return merged
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
if (!items) {
|
|
825
|
-
return this
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
if (items.constructor.name === 'Collection') {
|
|
829
|
-
return new this.constructor(merge(this.items, items.all()))
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
return new this.constructor(merge(this.items, items))
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
min(key?: string): number {
|
|
836
|
-
if (key !== undefined) {
|
|
837
|
-
const filtered = this.items.filter(item => item[key] !== undefined)
|
|
838
|
-
|
|
839
|
-
return Math.min(...filtered.map(item => item[key]))
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
return Math.min(...this.items)
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
mode(key?: string): any[] {
|
|
846
|
-
const values = []
|
|
847
|
-
let highestCount = 1
|
|
848
|
-
|
|
849
|
-
if (!this.items.length) {
|
|
850
|
-
return null
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
this.items.forEach((item) => {
|
|
854
|
-
const tempValues = values.filter((value) => {
|
|
855
|
-
if (key !== undefined) {
|
|
856
|
-
return value.key === item[key]
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
return value.key === item
|
|
860
|
-
})
|
|
861
|
-
|
|
862
|
-
if (!tempValues.length) {
|
|
863
|
-
if (key !== undefined) {
|
|
864
|
-
values.push({ key: item[key], count: 1 })
|
|
865
|
-
}
|
|
866
|
-
else {
|
|
867
|
-
values.push({ key: item, count: 1 })
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
else {
|
|
871
|
-
tempValues[0].count += 1
|
|
872
|
-
const { count } = tempValues[0]
|
|
873
|
-
|
|
874
|
-
if (count > highestCount) {
|
|
875
|
-
highestCount = count
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
})
|
|
879
|
-
|
|
880
|
-
return values.filter(value => value.count === highestCount).map(value => value.key)
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
nth(n: number, offset = 0): Collection<T> {
|
|
884
|
-
const items = values(this.items)
|
|
885
|
-
|
|
886
|
-
const collection = items.slice(offset).filter((item, index) => index % n === 0)
|
|
887
|
-
|
|
888
|
-
return new this.constructor(collection)
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
only(keys: string[]): Collection<T> {
|
|
892
|
-
const result = {}
|
|
893
|
-
keys.forEach((key) => {
|
|
894
|
-
if (key in this.items)
|
|
895
|
-
result[key] = this.items[key]
|
|
896
|
-
})
|
|
897
|
-
return new Collection(result)
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
pad(size: number, value: T): Collection<T> {
|
|
901
|
-
const abs = Math.abs(size)
|
|
902
|
-
const count = this.count()
|
|
903
|
-
|
|
904
|
-
if (abs <= count) {
|
|
905
|
-
return this
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
let diff = abs - count
|
|
909
|
-
const items = clone(this.items)
|
|
910
|
-
const isArray = Array.isArray(this.items)
|
|
911
|
-
const prepend = size < 0
|
|
912
|
-
|
|
913
|
-
for (let iterator = 0; iterator < diff;) {
|
|
914
|
-
if (!isArray) {
|
|
915
|
-
if (items[iterator] !== undefined) {
|
|
916
|
-
diff += 1
|
|
917
|
-
}
|
|
918
|
-
else {
|
|
919
|
-
items[iterator] = value
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
else if (prepend) {
|
|
923
|
-
items.unshift(value)
|
|
924
|
-
}
|
|
925
|
-
else {
|
|
926
|
-
items.push(value)
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
iterator += 1
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
return new this.constructor(items)
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
partition(fn: (item: T) => boolean): [Collection<T>, Collection<T>] {
|
|
936
|
-
let arrays
|
|
937
|
-
|
|
938
|
-
if (Array.isArray(this.items)) {
|
|
939
|
-
arrays = [new this.constructor([]), new this.constructor([])]
|
|
940
|
-
|
|
941
|
-
this.items.forEach((item) => {
|
|
942
|
-
if (fn(item) === true) {
|
|
943
|
-
arrays[0].push(item)
|
|
944
|
-
}
|
|
945
|
-
else {
|
|
946
|
-
arrays[1].push(item)
|
|
947
|
-
}
|
|
948
|
-
})
|
|
949
|
-
}
|
|
950
|
-
else {
|
|
951
|
-
arrays = [new this.constructor({}), new this.constructor({})]
|
|
952
|
-
|
|
953
|
-
Object.keys(this.items).forEach((prop) => {
|
|
954
|
-
const value = this.items[prop]
|
|
955
|
-
|
|
956
|
-
if (fn(value) === true) {
|
|
957
|
-
arrays[0].put(prop, value)
|
|
958
|
-
}
|
|
959
|
-
else {
|
|
960
|
-
arrays[1].put(prop, value)
|
|
961
|
-
}
|
|
962
|
-
})
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
return new this.constructor(arrays)
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
pipe(fn) {
|
|
969
|
-
return fn(this)
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
pluck(value: string, key?: string) {
|
|
973
|
-
if (value.includes('*')) {
|
|
974
|
-
const keyPathMap = buildKeyPathMap(this.items)
|
|
975
|
-
const keyMatches = []
|
|
976
|
-
|
|
977
|
-
if (key !== undefined) {
|
|
978
|
-
const keyRegex = new RegExp(`0.${key}`, 'g')
|
|
979
|
-
const keyNumberOfLevels = `0.${key}`.split('.').length
|
|
980
|
-
|
|
981
|
-
Object.keys(keyPathMap).forEach((k) => {
|
|
982
|
-
const matchingKey = k.match(keyRegex)
|
|
983
|
-
|
|
984
|
-
if (matchingKey) {
|
|
985
|
-
const match = matchingKey[0]
|
|
986
|
-
|
|
987
|
-
if (match.split('.').length === keyNumberOfLevels) {
|
|
988
|
-
keyMatches.push(keyPathMap[match])
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
})
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
const valueMatches = []
|
|
995
|
-
const valueRegex = new RegExp(`0.${value}`, 'g')
|
|
996
|
-
const valueNumberOfLevels = `0.${value}`.split('.').length
|
|
997
|
-
|
|
998
|
-
Object.keys(keyPathMap).forEach((k) => {
|
|
999
|
-
const matchingValue = k.match(valueRegex)
|
|
1000
|
-
|
|
1001
|
-
if (matchingValue) {
|
|
1002
|
-
const match = matchingValue[0]
|
|
1003
|
-
|
|
1004
|
-
if (match.split('.').length === valueNumberOfLevels) {
|
|
1005
|
-
valueMatches.push(keyPathMap[match])
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
})
|
|
1009
|
-
|
|
1010
|
-
if (key !== undefined) {
|
|
1011
|
-
const collection = {}
|
|
1012
|
-
|
|
1013
|
-
this.items.forEach((item, index) => {
|
|
1014
|
-
collection[keyMatches[index] || ''] = valueMatches
|
|
1015
|
-
})
|
|
1016
|
-
|
|
1017
|
-
return new this.constructor(collection)
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
return new this.constructor([valueMatches])
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
if (key !== undefined) {
|
|
1024
|
-
const collection = {}
|
|
1025
|
-
|
|
1026
|
-
this.items.forEach((item) => {
|
|
1027
|
-
if (nestedValue(item, value) !== undefined) {
|
|
1028
|
-
collection[item[key] || ''] = nestedValue(item, value)
|
|
1029
|
-
}
|
|
1030
|
-
else {
|
|
1031
|
-
collection[item[key] || ''] = null
|
|
1032
|
-
}
|
|
1033
|
-
})
|
|
1034
|
-
|
|
1035
|
-
return new this.constructor(collection)
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
return this.map((item) => {
|
|
1039
|
-
if (nestedValue(item, value) !== undefined) {
|
|
1040
|
-
return nestedValue(item, value)
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
return null
|
|
1044
|
-
})
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
pop(count = 1) {
|
|
1048
|
-
if (this.isEmpty()) {
|
|
1049
|
-
return null
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
if (isArray(this.items)) {
|
|
1053
|
-
if (count === 1) {
|
|
1054
|
-
return this.items.pop()
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
return new this.constructor(this.items.splice(-count))
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
if (isObject(this.items)) {
|
|
1061
|
-
const keys = Object.keys(this.items)
|
|
1062
|
-
|
|
1063
|
-
if (count === 1) {
|
|
1064
|
-
const key = keys[keys.length - 1]
|
|
1065
|
-
const last = this.items[key]
|
|
1066
|
-
|
|
1067
|
-
deleteKeys(this.items, key)
|
|
1068
|
-
|
|
1069
|
-
return last
|
|
1070
|
-
}
|
|
1071
|
-
|
|
1072
|
-
const poppedKeys = keys.slice(-count)
|
|
1073
|
-
|
|
1074
|
-
const newObject = poppedKeys.reduce((acc, current) => {
|
|
1075
|
-
acc[current] = this.items[current]
|
|
1076
|
-
|
|
1077
|
-
return acc
|
|
1078
|
-
}, {})
|
|
1079
|
-
|
|
1080
|
-
deleteKeys(this.items, poppedKeys)
|
|
1081
|
-
|
|
1082
|
-
return new this.constructor(newObject)
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
return null
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
prepend(value, key) {
|
|
1089
|
-
if (key !== undefined) {
|
|
1090
|
-
return this.put(key, value)
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
this.items.unshift(value)
|
|
1094
|
-
|
|
1095
|
-
return this
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
pull(key: string | number, defaultValue: T | null = null): T | null {
|
|
1099
|
-
if (Array.isArray(this.items)) {
|
|
1100
|
-
const index = Number(key)
|
|
1101
|
-
if (Number.isNaN(index))
|
|
1102
|
-
return defaultValue
|
|
1103
|
-
const value = this.items[index]
|
|
1104
|
-
this.items.splice(index, 1)
|
|
1105
|
-
return value ?? defaultValue
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
const value = this.items[key as string]
|
|
1109
|
-
delete this.items[key as string]
|
|
1110
|
-
return value ?? defaultValue
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
push(...items: T[]): Collection<T> {
|
|
1114
|
-
this.items = [...this.items, ...items]
|
|
1115
|
-
return this
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
put(key: string, value: any): this {
|
|
1119
|
-
this.items[key] = value
|
|
1120
|
-
return this
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
random(length = null) {
|
|
1124
|
-
const items = values(this.items)
|
|
1125
|
-
|
|
1126
|
-
const collection = new this.constructor(items).shuffle()
|
|
1127
|
-
|
|
1128
|
-
// If not a length was specified
|
|
1129
|
-
if (length !== Number.parseInt(length, 10)) {
|
|
1130
|
-
return collection.first()
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
return collection.take(length)
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
reduce(fn, carry) {
|
|
1137
|
-
let reduceCarry = null
|
|
1138
|
-
|
|
1139
|
-
if (carry !== undefined) {
|
|
1140
|
-
reduceCarry = carry
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
if (Array.isArray(this.items)) {
|
|
1144
|
-
this.items.forEach((item) => {
|
|
1145
|
-
reduceCarry = fn(reduceCarry, item)
|
|
1146
|
-
})
|
|
1147
|
-
}
|
|
1148
|
-
else {
|
|
1149
|
-
Object.keys(this.items).forEach((key) => {
|
|
1150
|
-
reduceCarry = fn(reduceCarry, this.items[key], key)
|
|
1151
|
-
})
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
|
-
return reduceCarry
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
reject(fn) {
|
|
1158
|
-
return new this.constructor(this.items).filter(item => !fn(item))
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
|
-
replace(items) {
|
|
1162
|
-
if (!items) {
|
|
1163
|
-
return this
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
if (Array.isArray(items)) {
|
|
1167
|
-
const replaced = this.items.map((value, index) => items[index] || value)
|
|
1168
|
-
|
|
1169
|
-
return new this.constructor(replaced)
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
if (items.constructor.name === 'Collection') {
|
|
1173
|
-
const replaced = { ...this.items, ...items.all() }
|
|
1174
|
-
|
|
1175
|
-
return new this.constructor(replaced)
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
|
-
const replaced = { ...this.items, ...items }
|
|
1179
|
-
|
|
1180
|
-
return new this.constructor(replaced)
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
replaceRecursive(items) {
|
|
1184
|
-
const replace = (target, source) => {
|
|
1185
|
-
const replaced = { ...target }
|
|
1186
|
-
|
|
1187
|
-
const mergedKeys = Object.keys({ ...target, ...source })
|
|
1188
|
-
|
|
1189
|
-
mergedKeys.forEach((key) => {
|
|
1190
|
-
if (!Array.isArray(source[key]) && typeof source[key] === 'object') {
|
|
1191
|
-
replaced[key] = replace(target[key], source[key])
|
|
1192
|
-
}
|
|
1193
|
-
else if (target[key] === undefined && source[key] !== undefined) {
|
|
1194
|
-
if (typeof target[key] === 'object') {
|
|
1195
|
-
replaced[key] = { ...source[key] }
|
|
1196
|
-
}
|
|
1197
|
-
else {
|
|
1198
|
-
replaced[key] = source[key]
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
else if (target[key] !== undefined && source[key] === undefined) {
|
|
1202
|
-
if (typeof target[key] === 'object') {
|
|
1203
|
-
replaced[key] = { ...target[key] }
|
|
1204
|
-
}
|
|
1205
|
-
else {
|
|
1206
|
-
replaced[key] = target[key]
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
else if (target[key] !== undefined && source[key] !== undefined) {
|
|
1210
|
-
if (typeof source[key] === 'object') {
|
|
1211
|
-
replaced[key] = { ...source[key] }
|
|
1212
|
-
}
|
|
1213
|
-
else {
|
|
1214
|
-
replaced[key] = source[key]
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
})
|
|
1218
|
-
|
|
1219
|
-
return replaced
|
|
1220
|
-
}
|
|
1221
|
-
|
|
1222
|
-
if (!items) {
|
|
1223
|
-
return this
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
|
-
if (!Array.isArray(items) && typeof items !== 'object') {
|
|
1227
|
-
return new this.constructor(replace(this.items, [items]))
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
if (items.constructor.name === 'Collection') {
|
|
1231
|
-
return new this.constructor(replace(this.items, items.all()))
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
return new this.constructor(replace(this.items, items))
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
reverse() {
|
|
1238
|
-
const collection = [].concat(this.items).reverse()
|
|
1239
|
-
|
|
1240
|
-
return new this.constructor(collection)
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
search(valueOrFunction, strict) {
|
|
1244
|
-
let result
|
|
1245
|
-
|
|
1246
|
-
const find = (item, key) => {
|
|
1247
|
-
if (isFunction(valueOrFunction)) {
|
|
1248
|
-
return valueOrFunction(this.items[key], key)
|
|
1249
|
-
}
|
|
1250
|
-
|
|
1251
|
-
if (strict) {
|
|
1252
|
-
return this.items[key] === valueOrFunction
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
return this.items[key] == valueOrFunction
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
if (isArray(this.items)) {
|
|
1259
|
-
result = this.items.findIndex(find)
|
|
1260
|
-
}
|
|
1261
|
-
else if (isObject(this.items)) {
|
|
1262
|
-
result = Object.keys(this.items).find(key => find(this.items[key], key))
|
|
1263
|
-
}
|
|
1264
|
-
|
|
1265
|
-
if (result === undefined || result < 0) {
|
|
1266
|
-
return false
|
|
1267
|
-
}
|
|
1268
|
-
|
|
1269
|
-
return result
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
shift(count = 1): T | undefined | null {
|
|
1273
|
-
if (this.isEmpty()) {
|
|
1274
|
-
return null
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
if (isArray(this.items)) {
|
|
1278
|
-
if (count === 1) {
|
|
1279
|
-
return this.items.shift()
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
return new this.constructor(this.items.splice(0, count))
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
if (isObject(this.items)) {
|
|
1286
|
-
if (count === 1) {
|
|
1287
|
-
const key = Object.keys(this.items)[0]
|
|
1288
|
-
const value = this.items[key]
|
|
1289
|
-
delete this.items[key]
|
|
1290
|
-
|
|
1291
|
-
return value
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
const keys = Object.keys(this.items)
|
|
1295
|
-
const poppedKeys = keys.slice(0, count)
|
|
1296
|
-
|
|
1297
|
-
const newObject = poppedKeys.reduce((acc, current) => {
|
|
1298
|
-
acc[current] = this.items[current]
|
|
1299
|
-
|
|
1300
|
-
return acc
|
|
1301
|
-
}, {})
|
|
1302
|
-
|
|
1303
|
-
deleteKeys(this.items, poppedKeys)
|
|
1304
|
-
|
|
1305
|
-
return new this.constructor(newObject)
|
|
1306
|
-
}
|
|
1307
|
-
|
|
1308
|
-
return null
|
|
1309
|
-
}
|
|
1310
|
-
|
|
1311
|
-
shuffle(): Collection<T> {
|
|
1312
|
-
const items = values(this.items)
|
|
1313
|
-
|
|
1314
|
-
let j
|
|
1315
|
-
let x
|
|
1316
|
-
let i
|
|
1317
|
-
|
|
1318
|
-
for (i = items.length; i; i -= 1) {
|
|
1319
|
-
j = Math.floor(Math.random() * i)
|
|
1320
|
-
x = items[i - 1]
|
|
1321
|
-
items[i - 1] = items[j]
|
|
1322
|
-
items[j] = x
|
|
1323
|
-
}
|
|
1324
|
-
|
|
1325
|
-
this.items = items
|
|
1326
|
-
|
|
1327
|
-
return this
|
|
1328
|
-
}
|
|
1329
|
-
|
|
1330
|
-
skip(number: number): Collection<T> {
|
|
1331
|
-
if (isObject(this.items)) {
|
|
1332
|
-
return new this.constructor(
|
|
1333
|
-
Object.keys(this.items).reduce((accumulator, key, index) => {
|
|
1334
|
-
if (index + 1 > number) {
|
|
1335
|
-
accumulator[key] = this.items[key]
|
|
1336
|
-
}
|
|
1337
|
-
|
|
1338
|
-
return accumulator
|
|
1339
|
-
}, {}),
|
|
1340
|
-
)
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
|
-
return new this.constructor(this.items.slice(number))
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
skipUntil(valueOrFunction: any): Collection<T> {
|
|
1347
|
-
let previous = null
|
|
1348
|
-
let items
|
|
1349
|
-
|
|
1350
|
-
let callback = value => value === valueOrFunction
|
|
1351
|
-
if (isFunction(valueOrFunction)) {
|
|
1352
|
-
callback = valueOrFunction
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
if (isArray(this.items)) {
|
|
1356
|
-
items = this.items.filter((item) => {
|
|
1357
|
-
if (previous !== true) {
|
|
1358
|
-
previous = callback(item)
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
|
-
return previous
|
|
1362
|
-
})
|
|
1363
|
-
}
|
|
1364
|
-
|
|
1365
|
-
if (isObject(this.items)) {
|
|
1366
|
-
items = Object.keys(this.items).reduce((acc, key) => {
|
|
1367
|
-
if (previous !== true) {
|
|
1368
|
-
previous = callback(this.items[key])
|
|
1369
|
-
}
|
|
1370
|
-
|
|
1371
|
-
if (previous !== false) {
|
|
1372
|
-
acc[key] = this.items[key]
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
|
-
return acc
|
|
1376
|
-
}, {})
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
return new this.constructor(items)
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
skipWhile(valueOrFunction: any): Collection<T> {
|
|
1383
|
-
let previous = null
|
|
1384
|
-
let items
|
|
1385
|
-
|
|
1386
|
-
let callback = value => value === valueOrFunction
|
|
1387
|
-
if (isFunction(valueOrFunction)) {
|
|
1388
|
-
callback = valueOrFunction
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
|
-
if (isArray(this.items)) {
|
|
1392
|
-
items = this.items.filter((item) => {
|
|
1393
|
-
if (previous !== true) {
|
|
1394
|
-
previous = !callback(item)
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
return previous
|
|
1398
|
-
})
|
|
1399
|
-
}
|
|
1400
|
-
|
|
1401
|
-
if (isObject(this.items)) {
|
|
1402
|
-
items = Object.keys(this.items).reduce((acc, key) => {
|
|
1403
|
-
if (previous !== true) {
|
|
1404
|
-
previous = !callback(this.items[key])
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
if (previous !== false) {
|
|
1408
|
-
acc[key] = this.items[key]
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
return acc
|
|
1412
|
-
}, {})
|
|
1413
|
-
}
|
|
1414
|
-
|
|
1415
|
-
return new this.constructor(items)
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
slice(remove: number, limit: number): Collection<T> {
|
|
1419
|
-
let collection = this.items.slice(remove)
|
|
1420
|
-
|
|
1421
|
-
if (limit !== undefined) {
|
|
1422
|
-
collection = collection.slice(0, limit)
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
return new this.constructor(collection)
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
|
-
sole(): T {
|
|
1429
|
-
if (this.items.length !== 1) {
|
|
1430
|
-
throw new Error('Collection does not contain exactly one item.')
|
|
1431
|
-
}
|
|
1432
|
-
return this.items[0]
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
some(key: string): boolean {
|
|
1436
|
-
return this.items.some(item => item.hasOwnProperty(key))
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
|
-
sort(fn: (a: T, b: T) => number): Collection<T> {
|
|
1440
|
-
const collection = [].concat(this.items)
|
|
1441
|
-
|
|
1442
|
-
if (fn === undefined) {
|
|
1443
|
-
if (this.every(item => typeof item === 'number')) {
|
|
1444
|
-
collection.sort((a, b) => a - b)
|
|
1445
|
-
}
|
|
1446
|
-
else {
|
|
1447
|
-
collection.sort()
|
|
1448
|
-
}
|
|
1449
|
-
}
|
|
1450
|
-
else {
|
|
1451
|
-
collection.sort(fn)
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1454
|
-
return new this.constructor(collection)
|
|
1455
|
-
}
|
|
1456
|
-
|
|
1457
|
-
sortDesc(): Collection<T> {
|
|
1458
|
-
return this.sort().reverse()
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
sortBy(valueOrFunction: any): Collection<T> {
|
|
1462
|
-
const collection = [].concat(this.items)
|
|
1463
|
-
const getValue = (item) => {
|
|
1464
|
-
if (isFunction(valueOrFunction)) {
|
|
1465
|
-
return valueOrFunction(item)
|
|
1466
|
-
}
|
|
1467
|
-
|
|
1468
|
-
return nestedValue(item, valueOrFunction)
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
collection.sort((a, b) => {
|
|
1472
|
-
const valueA = getValue(a)
|
|
1473
|
-
const valueB = getValue(b)
|
|
1474
|
-
|
|
1475
|
-
if (valueA === null || valueA === undefined) {
|
|
1476
|
-
return 1
|
|
1477
|
-
}
|
|
1478
|
-
if (valueB === null || valueB === undefined) {
|
|
1479
|
-
return -1
|
|
1480
|
-
}
|
|
1481
|
-
|
|
1482
|
-
if (valueA < valueB) {
|
|
1483
|
-
return -1
|
|
1484
|
-
}
|
|
1485
|
-
if (valueA > valueB) {
|
|
1486
|
-
return 1
|
|
1487
|
-
}
|
|
1488
|
-
|
|
1489
|
-
return 0
|
|
1490
|
-
})
|
|
1491
|
-
|
|
1492
|
-
return new this.constructor(collection)
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
sortByDesc(valueOrFunction: any): Collection<T> {
|
|
1496
|
-
return this.sortBy(valueOrFunction).reverse()
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
sortKeys(): Collection<T> {
|
|
1500
|
-
const ordered = {}
|
|
1501
|
-
|
|
1502
|
-
Object.keys(this.items)
|
|
1503
|
-
.sort()
|
|
1504
|
-
.forEach((key) => {
|
|
1505
|
-
ordered[key] = this.items[key]
|
|
1506
|
-
})
|
|
1507
|
-
|
|
1508
|
-
return new this.constructor(ordered)
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
|
-
sortKeysDesc(): Collection<T> {
|
|
1512
|
-
const ordered = {}
|
|
1513
|
-
|
|
1514
|
-
Object.keys(this.items)
|
|
1515
|
-
.sort()
|
|
1516
|
-
.reverse()
|
|
1517
|
-
.forEach((key) => {
|
|
1518
|
-
ordered[key] = this.items[key]
|
|
1519
|
-
})
|
|
1520
|
-
|
|
1521
|
-
return new this.constructor(ordered)
|
|
1522
|
-
}
|
|
1523
|
-
|
|
1524
|
-
splice(index: number, limit: number, replace: any): Collection<T> {
|
|
1525
|
-
const slicedCollection = this.slice(index, limit)
|
|
1526
|
-
|
|
1527
|
-
this.items = this.diff(slicedCollection.all()).all()
|
|
1528
|
-
|
|
1529
|
-
if (Array.isArray(replace)) {
|
|
1530
|
-
for (let iterator = 0, { length } = replace; iterator < length; iterator += 1) {
|
|
1531
|
-
this.items.splice(index + iterator, 0, replace[iterator])
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
return slicedCollection
|
|
1536
|
-
}
|
|
1537
|
-
|
|
1538
|
-
split(numberOfGroups: number): Collection<T[]> {
|
|
1539
|
-
const itemsArray = this.toArray()
|
|
1540
|
-
const groups: T[][] = []
|
|
1541
|
-
const size = Math.ceil(itemsArray.length / numberOfGroups)
|
|
1542
|
-
|
|
1543
|
-
for (let i = 0; i < itemsArray.length; i += size) {
|
|
1544
|
-
groups.push(itemsArray.slice(i, i + size))
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1547
|
-
return new Collection(groups)
|
|
1548
|
-
}
|
|
1549
|
-
|
|
1550
|
-
sum(key?: string | ((item: T) => number)): number {
|
|
1551
|
-
const items = values(this.items)
|
|
1552
|
-
|
|
1553
|
-
let total = 0
|
|
1554
|
-
|
|
1555
|
-
if (key === undefined) {
|
|
1556
|
-
for (let i = 0, { length } = items; i < length; i += 1) {
|
|
1557
|
-
total += Number.parseFloat(items[i])
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
else if (isFunction(key)) {
|
|
1561
|
-
for (let i = 0, { length } = items; i < length; i += 1) {
|
|
1562
|
-
total += Number.parseFloat(key(items[i]))
|
|
1563
|
-
}
|
|
1564
|
-
}
|
|
1565
|
-
else {
|
|
1566
|
-
for (let i = 0, { length } = items; i < length; i += 1) {
|
|
1567
|
-
total += Number.parseFloat(items[i][key])
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
|
|
1571
|
-
return Number.parseFloat(total.toPrecision(12))
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
take(length: number): Collection<T> {
|
|
1575
|
-
if (!Array.isArray(this.items) && typeof this.items === 'object') {
|
|
1576
|
-
const keys = Object.keys(this.items)
|
|
1577
|
-
let slicedKeys
|
|
1578
|
-
|
|
1579
|
-
if (length < 0) {
|
|
1580
|
-
slicedKeys = keys.slice(length)
|
|
1581
|
-
}
|
|
1582
|
-
else {
|
|
1583
|
-
slicedKeys = keys.slice(0, length)
|
|
1584
|
-
}
|
|
1585
|
-
|
|
1586
|
-
const collection = {}
|
|
1587
|
-
|
|
1588
|
-
keys.forEach((prop) => {
|
|
1589
|
-
if (slicedKeys.includes(prop)) {
|
|
1590
|
-
collection[prop] = this.items[prop]
|
|
1591
|
-
}
|
|
1592
|
-
})
|
|
1593
|
-
|
|
1594
|
-
return new this.constructor(collection)
|
|
1595
|
-
}
|
|
1596
|
-
|
|
1597
|
-
if (length < 0) {
|
|
1598
|
-
return new this.constructor(this.items.slice(length))
|
|
1599
|
-
}
|
|
1600
|
-
|
|
1601
|
-
return new this.constructor(this.items.slice(0, length))
|
|
1602
|
-
}
|
|
1603
|
-
|
|
1604
|
-
takeUntil(valueOrFunction): Collection<T> {
|
|
1605
|
-
let previous = null
|
|
1606
|
-
let items
|
|
1607
|
-
|
|
1608
|
-
let callback = value => value === valueOrFunction
|
|
1609
|
-
if (isFunction(valueOrFunction)) {
|
|
1610
|
-
callback = valueOrFunction
|
|
1611
|
-
}
|
|
1612
|
-
|
|
1613
|
-
if (isArray(this.items)) {
|
|
1614
|
-
items = this.items.filter((item) => {
|
|
1615
|
-
if (previous !== false) {
|
|
1616
|
-
previous = !callback(item)
|
|
1617
|
-
}
|
|
1618
|
-
|
|
1619
|
-
return previous
|
|
1620
|
-
})
|
|
1621
|
-
}
|
|
1622
|
-
|
|
1623
|
-
if (isObject(this.items)) {
|
|
1624
|
-
items = Object.keys(this.items).reduce((acc, key) => {
|
|
1625
|
-
if (previous !== false) {
|
|
1626
|
-
previous = !callback(this.items[key])
|
|
1627
|
-
}
|
|
1628
|
-
|
|
1629
|
-
if (previous !== false) {
|
|
1630
|
-
acc[key] = this.items[key]
|
|
1631
|
-
}
|
|
1632
|
-
|
|
1633
|
-
return acc
|
|
1634
|
-
}, {})
|
|
1635
|
-
}
|
|
1636
|
-
|
|
1637
|
-
return new this.constructor(items)
|
|
1638
|
-
}
|
|
1639
|
-
|
|
1640
|
-
takeWhile(valueOrFunction: any): Collection<T> {
|
|
1641
|
-
let previous = null
|
|
1642
|
-
let items
|
|
1643
|
-
|
|
1644
|
-
let callback = value => value === valueOrFunction
|
|
1645
|
-
if (isFunction(valueOrFunction)) {
|
|
1646
|
-
callback = valueOrFunction
|
|
1647
|
-
}
|
|
1648
|
-
|
|
1649
|
-
if (isArray(this.items)) {
|
|
1650
|
-
items = this.items.filter((item) => {
|
|
1651
|
-
if (previous !== false) {
|
|
1652
|
-
previous = callback(item)
|
|
1653
|
-
}
|
|
1654
|
-
|
|
1655
|
-
return previous
|
|
1656
|
-
})
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
if (isObject(this.items)) {
|
|
1660
|
-
items = Object.keys(this.items).reduce((acc, key) => {
|
|
1661
|
-
if (previous !== false) {
|
|
1662
|
-
previous = callback(this.items[key])
|
|
1663
|
-
}
|
|
1664
|
-
|
|
1665
|
-
if (previous !== false) {
|
|
1666
|
-
acc[key] = this.items[key]
|
|
1667
|
-
}
|
|
1668
|
-
|
|
1669
|
-
return acc
|
|
1670
|
-
}, {})
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
return new this.constructor(items)
|
|
1674
|
-
}
|
|
1675
|
-
|
|
1676
|
-
tap(fn: (collection: Collection<T>) => void): Collection<T> {
|
|
1677
|
-
fn(this)
|
|
1678
|
-
|
|
1679
|
-
return this
|
|
1680
|
-
}
|
|
1681
|
-
|
|
1682
|
-
times(n: number, fn: (iterator: number) => void): Collection<T> {
|
|
1683
|
-
for (let iterator = 1; iterator <= n; iterator += 1) {
|
|
1684
|
-
this.items.push(fn(iterator))
|
|
1685
|
-
}
|
|
1686
|
-
|
|
1687
|
-
return this
|
|
1688
|
-
}
|
|
1689
|
-
|
|
1690
|
-
toArray(): T[] {
|
|
1691
|
-
return Array.isArray(this.items) ? this.items : Object.values(this.items)
|
|
1692
|
-
}
|
|
1693
|
-
|
|
1694
|
-
toJson(): string {
|
|
1695
|
-
return JSON.stringify(this.items)
|
|
1696
|
-
}
|
|
1697
|
-
|
|
1698
|
-
transform(fn: (item: T, key: string) => T): Collection<T> {
|
|
1699
|
-
if (Array.isArray(this.items)) {
|
|
1700
|
-
this.items = this.items.map(fn)
|
|
1701
|
-
}
|
|
1702
|
-
else {
|
|
1703
|
-
const collection = {}
|
|
1704
|
-
|
|
1705
|
-
Object.keys(this.items).forEach((key) => {
|
|
1706
|
-
collection[key] = fn(this.items[key], key)
|
|
1707
|
-
})
|
|
1708
|
-
|
|
1709
|
-
this.items = collection
|
|
1710
|
-
}
|
|
1711
|
-
|
|
1712
|
-
return this
|
|
1713
|
-
}
|
|
1714
|
-
|
|
1715
|
-
undot(): Collection<T> {
|
|
1716
|
-
if (Array.isArray(this.items)) {
|
|
1717
|
-
return this
|
|
1718
|
-
}
|
|
1719
|
-
|
|
1720
|
-
let collection = {}
|
|
1721
|
-
|
|
1722
|
-
Object.keys(this.items).forEach((key) => {
|
|
1723
|
-
if (key.includes('.')) {
|
|
1724
|
-
const obj = collection
|
|
1725
|
-
|
|
1726
|
-
key.split('.').reduce((acc, current, index, array) => {
|
|
1727
|
-
if (!acc[current]) {
|
|
1728
|
-
acc[current] = {}
|
|
1729
|
-
}
|
|
1730
|
-
|
|
1731
|
-
if (index === array.length - 1) {
|
|
1732
|
-
acc[current] = this.items[key]
|
|
1733
|
-
}
|
|
1734
|
-
|
|
1735
|
-
return acc[current]
|
|
1736
|
-
}, obj)
|
|
1737
|
-
|
|
1738
|
-
collection = { ...collection, ...obj }
|
|
1739
|
-
}
|
|
1740
|
-
else {
|
|
1741
|
-
collection[key] = this.items[key]
|
|
1742
|
-
}
|
|
1743
|
-
})
|
|
1744
|
-
|
|
1745
|
-
return new this.constructor(collection)
|
|
1746
|
-
}
|
|
1747
|
-
|
|
1748
|
-
unless<T>(value: any, fn: (collection: this) => T, defaultFn?: () => T): T | undefined {
|
|
1749
|
-
if (!value) {
|
|
1750
|
-
return fn(this)
|
|
1751
|
-
}
|
|
1752
|
-
|
|
1753
|
-
if (defaultFn)
|
|
1754
|
-
return defaultFn()
|
|
1755
|
-
return undefined
|
|
1756
|
-
}
|
|
1757
|
-
|
|
1758
|
-
unlessEmpty(callback: (collection: Collection<T>) => void): this {
|
|
1759
|
-
if (!this.isEmpty()) {
|
|
1760
|
-
callback(this)
|
|
1761
|
-
}
|
|
1762
|
-
|
|
1763
|
-
return this
|
|
1764
|
-
}
|
|
1765
|
-
|
|
1766
|
-
unlessNotEmpty(callback: (collection: Collection<T>) => void): Collection<T> {
|
|
1767
|
-
if (this.isEmpty()) {
|
|
1768
|
-
callback(this)
|
|
1769
|
-
}
|
|
1770
|
-
|
|
1771
|
-
return this
|
|
1772
|
-
}
|
|
1773
|
-
|
|
1774
|
-
union(object: Record<string, T>): Collection<T> {
|
|
1775
|
-
const collection = JSON.parse(JSON.stringify(this.items))
|
|
1776
|
-
|
|
1777
|
-
Object.keys(object).forEach((prop) => {
|
|
1778
|
-
if (this.items[prop] === undefined) {
|
|
1779
|
-
collection[prop] = object[prop]
|
|
1780
|
-
}
|
|
1781
|
-
})
|
|
1782
|
-
|
|
1783
|
-
return new this.constructor(collection)
|
|
1784
|
-
}
|
|
1785
|
-
|
|
1786
|
-
unique(): Collection<T> {
|
|
1787
|
-
const uniqueItems = Array.from(new Set(this.items))
|
|
1788
|
-
return new this.constructor(uniqueItems)
|
|
1789
|
-
}
|
|
1790
|
-
|
|
1791
|
-
unwrap(): T[] | Record<string, T> {
|
|
1792
|
-
return this.items
|
|
1793
|
-
}
|
|
1794
|
-
|
|
1795
|
-
values(): Collection<T> {
|
|
1796
|
-
return new Collection(Object.values(this.items))
|
|
1797
|
-
}
|
|
1798
|
-
|
|
1799
|
-
when(
|
|
1800
|
-
value: any,
|
|
1801
|
-
callback: (collection: Collection<T>, value: any) => void,
|
|
1802
|
-
defaultCallback?: () => void,
|
|
1803
|
-
): Collection<T> {
|
|
1804
|
-
if (value) {
|
|
1805
|
-
callback(this, value)
|
|
1806
|
-
}
|
|
1807
|
-
else if (defaultCallback) {
|
|
1808
|
-
defaultCallback()
|
|
1809
|
-
}
|
|
1810
|
-
return this
|
|
1811
|
-
}
|
|
1812
|
-
|
|
1813
|
-
whenEmpty(fn, defaultFn) {
|
|
1814
|
-
if (Array.isArray(this.items) && !this.items.length) {
|
|
1815
|
-
return fn(this)
|
|
1816
|
-
}
|
|
1817
|
-
if (!Object.keys(this.items).length) {
|
|
1818
|
-
return fn(this)
|
|
1819
|
-
}
|
|
1820
|
-
|
|
1821
|
-
if (defaultFn !== undefined) {
|
|
1822
|
-
if (Array.isArray(this.items) && this.items.length) {
|
|
1823
|
-
return defaultFn(this)
|
|
1824
|
-
}
|
|
1825
|
-
if (Object.keys(this.items).length) {
|
|
1826
|
-
return defaultFn(this)
|
|
1827
|
-
}
|
|
1828
|
-
}
|
|
1829
|
-
|
|
1830
|
-
return this
|
|
1831
|
-
}
|
|
1832
|
-
|
|
1833
|
-
whenNotEmpty(fn: (collection: Collection<T>) => void, defaultFn: (collection: Collection<T>) => void): Collection<T> {
|
|
1834
|
-
if (Array.isArray(this.items) && this.items.length) {
|
|
1835
|
-
return fn(this)
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
if (Object.keys(this.items).length) {
|
|
1839
|
-
return fn(this)
|
|
1840
|
-
}
|
|
1841
|
-
|
|
1842
|
-
if (defaultFn !== undefined) {
|
|
1843
|
-
if (Array.isArray(this.items) && !this.items.length) {
|
|
1844
|
-
return defaultFn(this)
|
|
1845
|
-
}
|
|
1846
|
-
if (!Object.keys(this.items).length) {
|
|
1847
|
-
return defaultFn(this)
|
|
1848
|
-
}
|
|
1849
|
-
}
|
|
1850
|
-
|
|
1851
|
-
return this
|
|
1852
|
-
}
|
|
1853
|
-
|
|
1854
|
-
where(key: string, operator?: any, value?: any): Collection<T> {
|
|
1855
|
-
// If only one argument is passed, we're checking for existence
|
|
1856
|
-
if (arguments.length === 1) {
|
|
1857
|
-
return new Collection(this.items.filter(item => item[key] !== undefined))
|
|
1858
|
-
}
|
|
1859
|
-
|
|
1860
|
-
// If two arguments are passed, the second one is the value
|
|
1861
|
-
if (arguments.length === 2) {
|
|
1862
|
-
value = operator
|
|
1863
|
-
operator = '==='
|
|
1864
|
-
}
|
|
1865
|
-
|
|
1866
|
-
const compareValues = (item: any, key: string, value: any, operator: string) => {
|
|
1867
|
-
const itemValue = item[key]
|
|
1868
|
-
|
|
1869
|
-
switch (operator) {
|
|
1870
|
-
case '===':
|
|
1871
|
-
return itemValue === value
|
|
1872
|
-
case '!==':
|
|
1873
|
-
return itemValue !== value
|
|
1874
|
-
case '<':
|
|
1875
|
-
return itemValue < value
|
|
1876
|
-
case '<=':
|
|
1877
|
-
return itemValue <= value
|
|
1878
|
-
case '>':
|
|
1879
|
-
return itemValue > value
|
|
1880
|
-
case '>=':
|
|
1881
|
-
return itemValue >= value
|
|
1882
|
-
default:
|
|
1883
|
-
return itemValue == value
|
|
1884
|
-
}
|
|
1885
|
-
}
|
|
1886
|
-
|
|
1887
|
-
return new Collection(this.items.filter(item => compareValues(item, key, value, operator)))
|
|
1888
|
-
}
|
|
1889
|
-
|
|
1890
|
-
whereBetween(key: string, values: [number, number]): Collection<T> {
|
|
1891
|
-
return this.filter((item) => {
|
|
1892
|
-
const itemValue = typeof item === 'object' ? item[key] : item
|
|
1893
|
-
return itemValue >= values[0] && itemValue <= values[1]
|
|
1894
|
-
})
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
|
-
whereIn(key: string, values: any[]): Collection<T> {
|
|
1898
|
-
return this.filter((item) => {
|
|
1899
|
-
const itemValue = typeof item === 'object' ? item[key] : item
|
|
1900
|
-
return values.includes(itemValue)
|
|
1901
|
-
})
|
|
1902
|
-
}
|
|
1903
|
-
|
|
1904
|
-
whereNotBetween(key: string, values: [number, number]): Collection<T> {
|
|
1905
|
-
return this.filter((item) => {
|
|
1906
|
-
const itemValue = typeof item === 'object' ? item[key] : item
|
|
1907
|
-
return itemValue < values[0] || itemValue > values[1]
|
|
1908
|
-
})
|
|
1909
|
-
}
|
|
1910
|
-
|
|
1911
|
-
whereNotIn(key: string, values: any[]): Collection<T> {
|
|
1912
|
-
const filteredItems = this.items.filter((item) => {
|
|
1913
|
-
const keys = key.split('.')
|
|
1914
|
-
let value = item
|
|
1915
|
-
|
|
1916
|
-
for (const k of keys) {
|
|
1917
|
-
if (value[k] === undefined)
|
|
1918
|
-
return true
|
|
1919
|
-
value = value[k]
|
|
1920
|
-
}
|
|
1921
|
-
|
|
1922
|
-
return !values.includes(value)
|
|
1923
|
-
})
|
|
1924
|
-
|
|
1925
|
-
return new Collection(filteredItems)
|
|
1926
|
-
}
|
|
1927
|
-
|
|
1928
|
-
private getNestedValue(item: any, key: string): any {
|
|
1929
|
-
const keys = key.split('.')
|
|
1930
|
-
return keys.reduce((obj, k) => (obj && obj[k] !== undefined ? obj[k] : null), item)
|
|
1931
|
-
}
|
|
1932
|
-
|
|
1933
|
-
whereInstanceOf(type: any): Collection<T> {
|
|
1934
|
-
return this.filter(item => item instanceof type)
|
|
1935
|
-
}
|
|
1936
|
-
|
|
1937
|
-
whereNotNull(key: string): Collection<T> {
|
|
1938
|
-
return this.where(key, '!==', null)
|
|
1939
|
-
}
|
|
1940
|
-
|
|
1941
|
-
whereNull(key: string): Collection<T> {
|
|
1942
|
-
return this.where(key, '===', null)
|
|
1943
|
-
}
|
|
1944
|
-
|
|
1945
|
-
static wrap<T>(value: T | T[] | Collection<T>): Collection<T> {
|
|
1946
|
-
if (value instanceof Collection)
|
|
1947
|
-
return value
|
|
1948
|
-
return new Collection(Array.isArray(value) ? value : [value])
|
|
1949
|
-
}
|
|
1950
|
-
|
|
1951
|
-
static unwrap<T extends object>(value: T | T[] | Collection<T>): T | T[] {
|
|
1952
|
-
if (value instanceof Collection) {
|
|
1953
|
-
return value.all()
|
|
1954
|
-
}
|
|
1955
|
-
|
|
1956
|
-
return value
|
|
1957
|
-
}
|
|
1958
|
-
|
|
1959
|
-
wrap(value: any): Collection<T> {
|
|
1960
|
-
if (value instanceof Collection) {
|
|
1961
|
-
return value
|
|
1962
|
-
}
|
|
1963
|
-
|
|
1964
|
-
if (typeof value === 'object') {
|
|
1965
|
-
return new Collection(value)
|
|
1966
|
-
}
|
|
1967
|
-
|
|
1968
|
-
return new Collection([value])
|
|
1969
|
-
}
|
|
1970
|
-
|
|
1971
|
-
zip(...arrays: any[]): Collection<any> {
|
|
1972
|
-
const arrayOfArrays = arrays.map(arg => this.constructor.wrap(arg).all())
|
|
1973
|
-
const zipped = this.items.map((item, index) => {
|
|
1974
|
-
const values = [item]
|
|
1975
|
-
arrayOfArrays.forEach((array) => {
|
|
1976
|
-
values.push(array[index])
|
|
1977
|
-
})
|
|
1978
|
-
return new this.constructor(values) // Wrap each zipped item in a new Collection
|
|
1979
|
-
})
|
|
1980
|
-
return new this.constructor(zipped)
|
|
1981
|
-
}
|
|
1982
|
-
}
|
|
1983
|
-
|
|
1984
|
-
const buildKeyPathMap = function buildKeyPathMap(items: any) {
|
|
1985
|
-
const keyPaths = {}
|
|
1986
|
-
|
|
1987
|
-
items.forEach((item: any, index: number) => {
|
|
1988
|
-
function buildKeyPath(val: any, keyPath: string) {
|
|
1989
|
-
if (isObject(val)) {
|
|
1990
|
-
Object.keys(val).forEach((prop) => {
|
|
1991
|
-
buildKeyPath(val[prop], `${keyPath}.${prop}`)
|
|
1992
|
-
})
|
|
1993
|
-
}
|
|
1994
|
-
else if (isArray(val)) {
|
|
1995
|
-
val.forEach((v, i) => {
|
|
1996
|
-
buildKeyPath(v, `${keyPath}.${i}`)
|
|
1997
|
-
})
|
|
1998
|
-
}
|
|
1999
|
-
|
|
2000
|
-
keyPaths[keyPath] = val
|
|
2001
|
-
}
|
|
2002
|
-
|
|
2003
|
-
buildKeyPath(item, index)
|
|
2004
|
-
})
|
|
2005
|
-
|
|
2006
|
-
return keyPaths
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
function SymbolIterator() {
|
|
2010
|
-
let index = -1
|
|
2011
|
-
|
|
2012
|
-
return {
|
|
2013
|
-
next: () => {
|
|
2014
|
-
index += 1
|
|
2015
|
-
|
|
2016
|
-
return {
|
|
2017
|
-
value: this.items[index],
|
|
2018
|
-
done: index >= this.items.length,
|
|
2019
|
-
}
|
|
2020
|
-
},
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
|
|
2024
|
-
export default collect
|