@orieljs/framework 0.1.0-alpha.6 → 0.1.0-alpha.7
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/NOTICE +4 -0
- package/README.md +10 -1
- package/TRADEMARKS.md +33 -0
- package/dist/{chunk-ZOEPKBVF.js → chunk-4MWG3B7G.js} +1347 -428
- package/dist/chunk-4MWG3B7G.js.map +1 -0
- package/dist/{chunk-POEP4B2M.js → chunk-7ZQZYDOC.js} +745 -105
- package/dist/chunk-7ZQZYDOC.js.map +1 -0
- package/dist/{chunk-I63ZFMX6.js → chunk-GVNLZZTN.js} +1 -1
- package/dist/chunk-GVNLZZTN.js.map +1 -0
- package/dist/{chunk-MFTZQMZM.js → chunk-VOYW3R5J.js} +4 -4
- package/dist/chunk-VOYW3R5J.js.map +1 -0
- package/dist/contracts.d.ts +515 -17
- package/dist/contracts.js +1 -1
- package/dist/index.d-WQpfdIbG.d.ts +630 -0
- package/dist/index.d.ts +964 -152
- package/dist/index.js +4279 -866
- package/dist/index.js.map +1 -1
- package/dist/{jsx-runtime-CBZQYYDS.d.ts → jsx-runtime-6um4Mwfb.d.ts} +96 -5
- package/dist/jsx-runtime.d.ts +2 -2
- package/dist/jsx-runtime.js +3 -3
- package/dist/{testing-BM481Hdz.d.ts → testing-CKwfWJGn.d.ts} +180 -15
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +3 -3
- package/docs/authentication.md +487 -0
- package/docs/authorization.md +435 -0
- package/docs/cache.md +647 -0
- package/docs/collections.md +2270 -0
- package/docs/configuration.md +334 -0
- package/docs/console.md +651 -0
- package/docs/container.md +430 -0
- package/docs/controllers.md +406 -0
- package/docs/csrf.md +126 -0
- package/docs/database-testing.md +144 -0
- package/docs/database.md +236 -0
- package/docs/deployment.md +276 -0
- package/docs/eloquent-collections.md +218 -0
- package/docs/eloquent-factories.md +255 -0
- package/docs/eloquent-mutators.md +254 -0
- package/docs/eloquent-observers.md +145 -0
- package/docs/eloquent-relationships.md +557 -0
- package/docs/eloquent.md +494 -0
- package/docs/encryption.md +104 -0
- package/docs/errors.md +318 -0
- package/docs/events.md +336 -0
- package/docs/facades.md +278 -0
- package/docs/hashing.md +118 -0
- package/docs/helpers.md +1281 -0
- package/docs/http-tests.md +386 -0
- package/docs/inertia.md +485 -0
- package/docs/installation.md +209 -0
- package/docs/lifecycle.md +234 -0
- package/docs/live-tests.md +226 -0
- package/docs/live.md +910 -0
- package/docs/logging.md +255 -0
- package/docs/mail.md +619 -0
- package/docs/middleware.md +384 -0
- package/docs/migrations.md +416 -0
- package/docs/mocking.md +264 -0
- package/docs/navigation.json +273 -0
- package/docs/notifications.md +225 -0
- package/docs/pagination.md +247 -0
- package/docs/passwords.md +207 -0
- package/docs/providers.md +187 -0
- package/docs/queries.md +600 -0
- package/docs/queues.md +330 -0
- package/docs/requests.md +533 -0
- package/docs/responses.md +444 -0
- package/docs/routing.md +738 -0
- package/docs/scheduling.md +277 -0
- package/docs/seeding.md +122 -0
- package/docs/session.md +409 -0
- package/docs/starter-kits.md +396 -0
- package/docs/storage.md +192 -0
- package/docs/structure.md +264 -0
- package/docs/testing.md +165 -0
- package/docs/time-travel.md +138 -0
- package/docs/validation.md +1792 -0
- package/docs/verification.md +152 -0
- package/docs/views.md +566 -0
- package/docs/vite.md +322 -0
- package/package.json +34 -32
- package/dist/chunk-I63ZFMX6.js.map +0 -1
- package/dist/chunk-MFTZQMZM.js.map +0 -1
- package/dist/chunk-POEP4B2M.js.map +0 -1
- package/dist/chunk-ZOEPKBVF.js.map +0 -1
- package/dist/index.d-BJyJx6U1.d.ts +0 -319
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
Application,
|
|
3
3
|
ConfigRepository,
|
|
4
4
|
Container
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-GVNLZZTN.js";
|
|
6
6
|
|
|
7
7
|
// ../Container/dist/index.js
|
|
8
8
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -226,9 +226,138 @@ function ascending(a, b) {
|
|
|
226
226
|
if (a instanceof Date && b instanceof Date) return a.getTime() - b.getTime();
|
|
227
227
|
return String(a).localeCompare(String(b));
|
|
228
228
|
}
|
|
229
|
+
var ItemNotFoundError = class extends Error {
|
|
230
|
+
name = "ItemNotFoundError";
|
|
231
|
+
constructor() {
|
|
232
|
+
super("Item not found.");
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
var MultipleItemsFoundError = class extends Error {
|
|
236
|
+
constructor(count) {
|
|
237
|
+
super(`${count} items were found.`);
|
|
238
|
+
this.count = count;
|
|
239
|
+
}
|
|
240
|
+
count;
|
|
241
|
+
name = "MultipleItemsFoundError";
|
|
242
|
+
};
|
|
243
|
+
var LazyCollection = class _LazyCollection {
|
|
244
|
+
constructor(source) {
|
|
245
|
+
this.source = source;
|
|
246
|
+
}
|
|
247
|
+
source;
|
|
248
|
+
static make(source) {
|
|
249
|
+
return new _LazyCollection(source);
|
|
250
|
+
}
|
|
251
|
+
async *[Symbol.asyncIterator]() {
|
|
252
|
+
yield* this.source();
|
|
253
|
+
}
|
|
254
|
+
map(callback) {
|
|
255
|
+
const self = this;
|
|
256
|
+
return new _LazyCollection(async function* () {
|
|
257
|
+
let i = 0;
|
|
258
|
+
for await (const item of self) yield await callback(item, i++);
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
filter(callback) {
|
|
262
|
+
const self = this;
|
|
263
|
+
return new _LazyCollection(async function* () {
|
|
264
|
+
let i = 0;
|
|
265
|
+
for await (const item of self) if (await callback(item, i++)) yield item;
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
take(count) {
|
|
269
|
+
const self = this;
|
|
270
|
+
return new _LazyCollection(async function* () {
|
|
271
|
+
if (count <= 0) return;
|
|
272
|
+
let taken = 0;
|
|
273
|
+
for await (const item of self) {
|
|
274
|
+
yield item;
|
|
275
|
+
if (++taken >= count) return;
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
chunk(size) {
|
|
280
|
+
const self = this;
|
|
281
|
+
return new _LazyCollection(async function* () {
|
|
282
|
+
if (size <= 0) return;
|
|
283
|
+
let buffer = [];
|
|
284
|
+
for await (const item of self) {
|
|
285
|
+
buffer.push(item);
|
|
286
|
+
if (buffer.length === size) {
|
|
287
|
+
yield new Collection(buffer);
|
|
288
|
+
buffer = [];
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (buffer.length) yield new Collection(buffer);
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
/** Return false from the callback to stop. */
|
|
295
|
+
async each(callback) {
|
|
296
|
+
let i = 0;
|
|
297
|
+
for await (const item of this) if (await callback(item, i++) === false) return;
|
|
298
|
+
}
|
|
299
|
+
async first(callback) {
|
|
300
|
+
for await (const item of this) if (!callback || await callback(item)) return item;
|
|
301
|
+
return void 0;
|
|
302
|
+
}
|
|
303
|
+
async count() {
|
|
304
|
+
let n = 0;
|
|
305
|
+
for await (const item of this) {
|
|
306
|
+
void item;
|
|
307
|
+
n++;
|
|
308
|
+
}
|
|
309
|
+
return n;
|
|
310
|
+
}
|
|
311
|
+
async collect() {
|
|
312
|
+
const items = [];
|
|
313
|
+
for await (const item of this) items.push(item);
|
|
314
|
+
return new Collection(items);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
229
317
|
var read = (item, getter) => typeof getter === "function" ? getter(item) : item?.[getter];
|
|
230
318
|
var isArrayable = (v) => typeof v === "object" && v !== null && typeof v.toArray === "function";
|
|
231
319
|
var numbers = (items, getter) => items.map((item) => getter === void 0 ? item : read(item, getter)).filter((v) => typeof v === "number" && !Number.isNaN(v));
|
|
320
|
+
var isNil = (value2) => value2 === null || value2 === void 0;
|
|
321
|
+
var predicateFor = (value2) => typeof value2 === "function" ? value2 : (item) => item === value2;
|
|
322
|
+
var roundTo = (value2, precision) => Number(`${Math.round(Number(`${value2}e${precision}`))}e-${precision}`);
|
|
323
|
+
var typeNameOf = (value2) => {
|
|
324
|
+
if (value2 === null) return "null";
|
|
325
|
+
if (Array.isArray(value2)) return "array";
|
|
326
|
+
if (typeof value2 === "object") return value2.constructor?.name ?? "object";
|
|
327
|
+
return typeof value2;
|
|
328
|
+
};
|
|
329
|
+
var isIndex = (index, length) => Number.isInteger(index) && index >= 0 && index < length;
|
|
330
|
+
function compareBy(a, b, key, direction) {
|
|
331
|
+
const left = read(a, key);
|
|
332
|
+
const right = read(b, key);
|
|
333
|
+
const leftNil = isNil(left);
|
|
334
|
+
const rightNil = isNil(right);
|
|
335
|
+
if (leftNil || rightNil) return leftNil === rightNil ? 0 : leftNil ? 1 : -1;
|
|
336
|
+
return (direction === "asc" ? 1 : -1) * ascending(left, right);
|
|
337
|
+
}
|
|
338
|
+
function flattenItems(items, depth) {
|
|
339
|
+
const result = [];
|
|
340
|
+
for (const value2 of items) {
|
|
341
|
+
const item = value2 instanceof Collection ? value2.all() : value2;
|
|
342
|
+
if (!Array.isArray(item)) result.push(item);
|
|
343
|
+
else if (depth <= 1) result.push(...item);
|
|
344
|
+
else result.push(...flattenItems(item, depth - 1));
|
|
345
|
+
}
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
function whereCondition(args) {
|
|
349
|
+
const [key, operatorOrValue, value2] = args;
|
|
350
|
+
if (args.length === 1) return (item) => Boolean(read(item, key));
|
|
351
|
+
if (args.length === 2) return (item) => compare(read(item, key), "=", operatorOrValue);
|
|
352
|
+
return (item) => compare(read(item, key), operatorOrValue, value2);
|
|
353
|
+
}
|
|
354
|
+
function uniqueWith(values, equal) {
|
|
355
|
+
const result = [];
|
|
356
|
+
for (const value2 of values) if (!result.some((seen) => equal(seen, value2))) result.push(value2);
|
|
357
|
+
return result;
|
|
358
|
+
}
|
|
359
|
+
var loose = (a, b) => a == b;
|
|
360
|
+
var strict = (a, b) => a === b;
|
|
232
361
|
var Collection = class _Collection {
|
|
233
362
|
items;
|
|
234
363
|
constructor(items = []) {
|
|
@@ -241,6 +370,34 @@ var Collection = class _Collection {
|
|
|
241
370
|
static times(count, callback) {
|
|
242
371
|
return new _Collection(Array.from({ length: Math.max(0, count) }, (_, i) => callback(i + 1)));
|
|
243
372
|
}
|
|
373
|
+
/** The numbers from `from` to `to`, inclusive, counting up or down by `step` (PHP's range()). */
|
|
374
|
+
static range(from, to, step = 1) {
|
|
375
|
+
if (step === 0) throw new RangeError("range(): Argument #3 ($step) cannot be 0");
|
|
376
|
+
const size = Math.abs(step);
|
|
377
|
+
const numbers2 = [];
|
|
378
|
+
if (from <= to) for (let n = from; n <= to; n += size) numbers2.push(n);
|
|
379
|
+
else for (let n = from; n >= to; n -= size) numbers2.push(n);
|
|
380
|
+
return new _Collection(numbers2);
|
|
381
|
+
}
|
|
382
|
+
static wrap(value2) {
|
|
383
|
+
if (value2 instanceof _Collection) return new _Collection(value2.all());
|
|
384
|
+
if (Array.isArray(value2)) return new _Collection(value2);
|
|
385
|
+
return new _Collection(isNil(value2) ? [] : [value2]);
|
|
386
|
+
}
|
|
387
|
+
static unwrap(value2) {
|
|
388
|
+
return value2 instanceof _Collection ? value2.all() : value2;
|
|
389
|
+
}
|
|
390
|
+
static empty() {
|
|
391
|
+
return new _Collection();
|
|
392
|
+
}
|
|
393
|
+
/** The decoded JSON: an array's items, nothing for null, else the one value. */
|
|
394
|
+
static fromJson(json) {
|
|
395
|
+
return _Collection.wrap(JSON.parse(json));
|
|
396
|
+
}
|
|
397
|
+
/** A new collection of the receiver's class (a subclass keeps its class through filter(), sortBy(), …). */
|
|
398
|
+
newInstance(items = []) {
|
|
399
|
+
return new this.constructor(items);
|
|
400
|
+
}
|
|
244
401
|
[Symbol.iterator]() {
|
|
245
402
|
return this.items[Symbol.iterator]();
|
|
246
403
|
}
|
|
@@ -265,6 +422,81 @@ var Collection = class _Collection {
|
|
|
265
422
|
toJson() {
|
|
266
423
|
return JSON.stringify(this);
|
|
267
424
|
}
|
|
425
|
+
get(index, defaultValue) {
|
|
426
|
+
if (Number.isInteger(index) && index >= 0 && index < this.items.length) return this.items[index];
|
|
427
|
+
return typeof defaultValue === "function" ? defaultValue() : defaultValue;
|
|
428
|
+
}
|
|
429
|
+
/** Whether every given index exists. */
|
|
430
|
+
has(...indexes) {
|
|
431
|
+
return indexes.flat().every((index) => Number.isInteger(index) && index >= 0 && index < this.items.length);
|
|
432
|
+
}
|
|
433
|
+
/** Whether any of the given indexes exists. */
|
|
434
|
+
hasAny(...indexes) {
|
|
435
|
+
if (this.isEmpty()) return false;
|
|
436
|
+
return indexes.flat().some((index) => this.has(index));
|
|
437
|
+
}
|
|
438
|
+
search(value2, strict2 = false) {
|
|
439
|
+
const index = typeof value2 === "function" ? this.items.findIndex(value2) : this.items.findIndex((item) => strict2 ? item === value2 : item == value2);
|
|
440
|
+
return index === -1 ? false : index;
|
|
441
|
+
}
|
|
442
|
+
before(value2, strict2 = false) {
|
|
443
|
+
const index = this.search(value2, strict2);
|
|
444
|
+
return index === false || index === 0 ? void 0 : this.items[index - 1];
|
|
445
|
+
}
|
|
446
|
+
after(value2, strict2 = false) {
|
|
447
|
+
const index = this.search(value2, strict2);
|
|
448
|
+
return index === false ? void 0 : this.items[index + 1];
|
|
449
|
+
}
|
|
450
|
+
value(key, defaultValue) {
|
|
451
|
+
const item = this.items.find((candidate) => Boolean(read(candidate, key)));
|
|
452
|
+
if (item !== void 0) return read(item, key);
|
|
453
|
+
return typeof defaultValue === "function" ? defaultValue() : defaultValue;
|
|
454
|
+
}
|
|
455
|
+
every(...args) {
|
|
456
|
+
if (args.length === 1 && typeof args[0] === "function") return this.items.every(args[0]);
|
|
457
|
+
const condition = whereCondition(args);
|
|
458
|
+
return this.items.every((item) => condition(item));
|
|
459
|
+
}
|
|
460
|
+
contains(keyOrValue, operatorOrValue, value2) {
|
|
461
|
+
if (arguments.length === 3) return this.items.some(whereCondition([keyOrValue, operatorOrValue, value2]));
|
|
462
|
+
if (arguments.length === 2) return this.items.some((item) => read(item, keyOrValue) === operatorOrValue);
|
|
463
|
+
if (typeof keyOrValue === "function") return this.items.some(keyOrValue);
|
|
464
|
+
return this.items.includes(keyOrValue);
|
|
465
|
+
}
|
|
466
|
+
some(...args) {
|
|
467
|
+
return Reflect.apply(this.contains, this, args);
|
|
468
|
+
}
|
|
469
|
+
containsStrict(...args) {
|
|
470
|
+
return Reflect.apply(this.contains, this, args);
|
|
471
|
+
}
|
|
472
|
+
doesntContain(...args) {
|
|
473
|
+
return !Reflect.apply(this.contains, this, args);
|
|
474
|
+
}
|
|
475
|
+
doesntContainStrict(...args) {
|
|
476
|
+
return !Reflect.apply(this.contains, this, args);
|
|
477
|
+
}
|
|
478
|
+
/** Whether there is exactly one item (that passes the callback). */
|
|
479
|
+
containsOneItem(callback) {
|
|
480
|
+
return (callback ? this.items.filter(callback) : this.items).length === 1;
|
|
481
|
+
}
|
|
482
|
+
sole(...args) {
|
|
483
|
+
const items = this.matching(args);
|
|
484
|
+
if (items.length === 0) throw new ItemNotFoundError();
|
|
485
|
+
if (items.length > 1) throw new MultipleItemsFoundError(items.length);
|
|
486
|
+
return items[0];
|
|
487
|
+
}
|
|
488
|
+
firstOrFail(...args) {
|
|
489
|
+
const items = this.matching(args);
|
|
490
|
+
if (items.length === 0) throw new ItemNotFoundError();
|
|
491
|
+
return items[0];
|
|
492
|
+
}
|
|
493
|
+
/** The items a callback or a where condition (sole(), firstOrFail()) selects; every item without arguments. */
|
|
494
|
+
matching(args) {
|
|
495
|
+
if (args.length === 0 || args[0] === void 0) return this.items;
|
|
496
|
+
if (args.length === 1) return this.items.filter(args[0]);
|
|
497
|
+
return this.items.filter(whereCondition(args));
|
|
498
|
+
}
|
|
499
|
+
// ---------------------------------------------------------------- transforming
|
|
268
500
|
map(callback) {
|
|
269
501
|
return new _Collection(this.items.map(callback));
|
|
270
502
|
}
|
|
@@ -277,10 +509,10 @@ var Collection = class _Collection {
|
|
|
277
509
|
);
|
|
278
510
|
}
|
|
279
511
|
filter(callback) {
|
|
280
|
-
return
|
|
512
|
+
return this.newInstance(this.items.filter(callback ?? ((item) => Boolean(item))));
|
|
281
513
|
}
|
|
282
514
|
reject(callback) {
|
|
283
|
-
return
|
|
515
|
+
return this.newInstance(this.items.filter((item, i) => !callback(item, i)));
|
|
284
516
|
}
|
|
285
517
|
/** Return false from the callback to stop. */
|
|
286
518
|
each(callback) {
|
|
@@ -300,22 +532,53 @@ var Collection = class _Collection {
|
|
|
300
532
|
const index = this.items.findLastIndex(callback);
|
|
301
533
|
return index === -1 ? defaultValue : this.items[index];
|
|
302
534
|
}
|
|
303
|
-
where(
|
|
304
|
-
|
|
305
|
-
|
|
535
|
+
where(...args) {
|
|
536
|
+
return this.filter(whereCondition(args));
|
|
537
|
+
}
|
|
538
|
+
/** where() with strict comparison (===). */
|
|
539
|
+
whereStrict(key, value2) {
|
|
540
|
+
return this.filter((item) => read(item, key) === value2);
|
|
306
541
|
}
|
|
307
|
-
firstWhere(
|
|
308
|
-
|
|
309
|
-
return this.items.find((item) => compare(read(item, key), op, expected));
|
|
542
|
+
firstWhere(...args) {
|
|
543
|
+
return this.items.find(whereCondition(args));
|
|
310
544
|
}
|
|
311
545
|
whereIn(key, values) {
|
|
312
546
|
const set = new Set(values);
|
|
313
547
|
return this.filter((item) => set.has(read(item, key)));
|
|
314
548
|
}
|
|
549
|
+
/** whereIn() under Laravel's strict name (whereIn() already compares strictly). */
|
|
550
|
+
whereInStrict(key, values) {
|
|
551
|
+
return this.whereIn(key, values);
|
|
552
|
+
}
|
|
315
553
|
whereNotIn(key, values) {
|
|
316
554
|
const set = new Set(values);
|
|
317
555
|
return this.filter((item) => !set.has(read(item, key)));
|
|
318
556
|
}
|
|
557
|
+
whereNotInStrict(key, values) {
|
|
558
|
+
return this.whereNotIn(key, values);
|
|
559
|
+
}
|
|
560
|
+
/** Items whose key (or the item itself) is null or undefined (a missing key counts as null). */
|
|
561
|
+
whereNull(key) {
|
|
562
|
+
return this.filter((item) => isNil(key === void 0 ? item : read(item, key)));
|
|
563
|
+
}
|
|
564
|
+
whereNotNull(key) {
|
|
565
|
+
return this.filter((item) => !isNil(key === void 0 ? item : read(item, key)));
|
|
566
|
+
}
|
|
567
|
+
/** Items whose key is within the first and last values, inclusive. */
|
|
568
|
+
whereBetween(key, values) {
|
|
569
|
+
return this.where(key, ">=", values[0]).where(key, "<=", values.at(-1));
|
|
570
|
+
}
|
|
571
|
+
whereNotBetween(key, values) {
|
|
572
|
+
return this.filter((item) => {
|
|
573
|
+
const value2 = read(item, key);
|
|
574
|
+
return value2 < values[0] || value2 > values.at(-1);
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
/** Items that are instances of the class (or of any of the classes). */
|
|
578
|
+
whereInstanceOf(type2) {
|
|
579
|
+
const types = [type2].flat();
|
|
580
|
+
return this.filter((item) => types.some((cls) => item instanceof cls));
|
|
581
|
+
}
|
|
319
582
|
pluck(key) {
|
|
320
583
|
return this.map((item) => read(item, key));
|
|
321
584
|
}
|
|
@@ -323,21 +586,74 @@ var Collection = class _Collection {
|
|
|
323
586
|
return Object.fromEntries(this.items.map((item) => [String(read(item, key)), item]));
|
|
324
587
|
}
|
|
325
588
|
groupBy(key) {
|
|
326
|
-
const groups =
|
|
327
|
-
for (const item of this.items)
|
|
328
|
-
|
|
589
|
+
const groups = /* @__PURE__ */ new Map();
|
|
590
|
+
for (const item of this.items) {
|
|
591
|
+
const name = String(read(item, key));
|
|
592
|
+
groups.set(name, (groups.get(name) ?? this.newInstance()).push(item));
|
|
593
|
+
}
|
|
594
|
+
return Object.fromEntries(groups);
|
|
329
595
|
}
|
|
330
596
|
mapWithKeys(callback) {
|
|
331
597
|
return Object.fromEntries(this.items.map(callback));
|
|
332
598
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
599
|
+
duplicates(key) {
|
|
600
|
+
return this.repeated(key, loose);
|
|
601
|
+
}
|
|
602
|
+
duplicatesStrict(key) {
|
|
603
|
+
return this.repeated(key, strict);
|
|
604
|
+
}
|
|
605
|
+
/** Laravel's duplicates(): each value after the first of its kind. */
|
|
606
|
+
repeated(key, equal) {
|
|
607
|
+
const values = this.items.map((item) => key === void 0 ? item : read(item, key));
|
|
608
|
+
const unique = uniqueWith(values, equal);
|
|
609
|
+
const duplicates = [];
|
|
610
|
+
for (const value2 of values) {
|
|
611
|
+
if (unique.length && equal(value2, unique[0])) unique.shift();
|
|
612
|
+
else duplicates.push(value2);
|
|
613
|
+
}
|
|
614
|
+
return new _Collection(duplicates);
|
|
615
|
+
}
|
|
616
|
+
/** The items that aren't in the given items (strict comparison). */
|
|
617
|
+
diff(items) {
|
|
618
|
+
const other = new Set(items);
|
|
619
|
+
return this.filter((item) => !other.has(item));
|
|
620
|
+
}
|
|
621
|
+
/** diff() with a comparator that returns 0 for equal items. */
|
|
622
|
+
diffUsing(items, callback) {
|
|
623
|
+
const other = [...items];
|
|
624
|
+
return this.filter((item) => !other.some((candidate) => callback(item, candidate) === 0));
|
|
625
|
+
}
|
|
626
|
+
/** The items that are also in the given items (strict comparison). */
|
|
627
|
+
intersect(items) {
|
|
628
|
+
const other = new Set(items);
|
|
629
|
+
return this.filter((item) => other.has(item));
|
|
630
|
+
}
|
|
631
|
+
intersectUsing(items, callback) {
|
|
632
|
+
const other = [...items];
|
|
633
|
+
return this.filter((item) => other.some((candidate) => callback(item, candidate) === 0));
|
|
634
|
+
}
|
|
635
|
+
// ---------------------------------------------------------------- ordering and slicing
|
|
636
|
+
/** Sorted with the default ascending order (numbers, dates, then strings), or by a comparator. */
|
|
637
|
+
sort(callback) {
|
|
638
|
+
return this.newInstance([...this.items].sort(callback ?? ((a, b) => ascending(a, b))));
|
|
639
|
+
}
|
|
640
|
+
sortDesc() {
|
|
641
|
+
return this.newInstance([...this.items].sort((a, b) => ascending(b, a)));
|
|
642
|
+
}
|
|
643
|
+
sortBy(keyOrSteps, direction = "asc") {
|
|
644
|
+
const steps = Array.isArray(keyOrSteps) ? keyOrSteps : [[keyOrSteps, direction]];
|
|
645
|
+
const comparators = steps.map((step) => {
|
|
646
|
+
if (typeof step === "function" && step.length >= 2) return step;
|
|
647
|
+
const [key, order = "asc"] = Array.isArray(step) ? step : [step];
|
|
648
|
+
return (a, b) => compareBy(a, b, key, order);
|
|
649
|
+
});
|
|
650
|
+
return this.newInstance(
|
|
651
|
+
this.items.map((item, index) => ({ item, index })).sort((a, b) => {
|
|
652
|
+
for (const comparator of comparators) {
|
|
653
|
+
const result = comparator(a.item, b.item);
|
|
654
|
+
if (result) return result;
|
|
655
|
+
}
|
|
656
|
+
return a.index - b.index;
|
|
341
657
|
}).map((x) => x.item)
|
|
342
658
|
);
|
|
343
659
|
}
|
|
@@ -359,6 +675,81 @@ var Collection = class _Collection {
|
|
|
359
675
|
const values = numbers(this.items, key);
|
|
360
676
|
return values.length ? Math.max(...values) : void 0;
|
|
361
677
|
}
|
|
678
|
+
/** avg() under Laravel's other name. */
|
|
679
|
+
average(key) {
|
|
680
|
+
return this.avg(key);
|
|
681
|
+
}
|
|
682
|
+
/** The middle number (the mean of the two middle ones for an even count), ignoring null and non-numbers. */
|
|
683
|
+
median(key) {
|
|
684
|
+
const values = numbers(this.items, key).sort((a, b) => a - b);
|
|
685
|
+
if (!values.length) return void 0;
|
|
686
|
+
const middle = Math.floor(values.length / 2);
|
|
687
|
+
return values.length % 2 ? values[middle] : (values[middle - 1] + values[middle]) / 2;
|
|
688
|
+
}
|
|
689
|
+
mode(key) {
|
|
690
|
+
if (this.isEmpty()) return void 0;
|
|
691
|
+
const counts = /* @__PURE__ */ new Map();
|
|
692
|
+
for (const item of this.items) {
|
|
693
|
+
const value2 = key === void 0 ? item : read(item, key);
|
|
694
|
+
counts.set(value2, (counts.get(value2) ?? 0) + 1);
|
|
695
|
+
}
|
|
696
|
+
const highest = Math.max(...counts.values());
|
|
697
|
+
return [...counts].filter(([, count]) => count === highest).map(([value2]) => value2);
|
|
698
|
+
}
|
|
699
|
+
/** The share of items that pass the callback, as a percentage rounded to `precision` places; undefined when empty. */
|
|
700
|
+
percentage(callback, precision = 2) {
|
|
701
|
+
if (this.isEmpty()) return void 0;
|
|
702
|
+
return roundTo(this.items.filter(callback).length / this.items.length * 100, precision);
|
|
703
|
+
}
|
|
704
|
+
/** How many items have each value, key value or callback result: [1, 2, 2].countBy() → { 1: 1, 2: 2 }. */
|
|
705
|
+
countBy(key) {
|
|
706
|
+
const counts = /* @__PURE__ */ new Map();
|
|
707
|
+
for (const item of this.items) {
|
|
708
|
+
const value2 = String(key === void 0 ? item : read(item, key));
|
|
709
|
+
counts.set(value2, (counts.get(value2) ?? 0) + 1);
|
|
710
|
+
}
|
|
711
|
+
return Object.fromEntries(counts);
|
|
712
|
+
}
|
|
713
|
+
/** Groups the callback's [key, value] pairs: values under the same key are collected in arrays. */
|
|
714
|
+
mapToDictionary(callback) {
|
|
715
|
+
const dictionary = /* @__PURE__ */ new Map();
|
|
716
|
+
this.items.forEach((item, index) => {
|
|
717
|
+
const [key, value2] = callback(item, index);
|
|
718
|
+
const name = String(key);
|
|
719
|
+
const values = dictionary.get(name) ?? [];
|
|
720
|
+
values.push(value2);
|
|
721
|
+
dictionary.set(name, values);
|
|
722
|
+
});
|
|
723
|
+
return Object.fromEntries(dictionary);
|
|
724
|
+
}
|
|
725
|
+
/** mapToDictionary() with each group as a collection. */
|
|
726
|
+
mapToGroups(callback) {
|
|
727
|
+
return Object.fromEntries(Object.entries(this.mapToDictionary(callback)).map(([key, values]) => [key, new _Collection(values)]));
|
|
728
|
+
}
|
|
729
|
+
/** A new instance of the class for each item: new cls(item, index). */
|
|
730
|
+
mapInto(cls) {
|
|
731
|
+
return this.map((item, index) => new cls(item, index));
|
|
732
|
+
}
|
|
733
|
+
/** Maps nested arrays (or collections) with their items as the arguments, then the index. */
|
|
734
|
+
mapSpread(callback) {
|
|
735
|
+
return this.map((chunk, index) => callback(...[...chunk instanceof _Collection ? chunk.all() : chunk, index]));
|
|
736
|
+
}
|
|
737
|
+
/** each() with the nested items as the arguments, then the index. Return false to stop. */
|
|
738
|
+
eachSpread(callback) {
|
|
739
|
+
return this.each((chunk, index) => callback(...[...chunk instanceof _Collection ? chunk.all() : chunk, index]));
|
|
740
|
+
}
|
|
741
|
+
/** reduce() with several carried values: the reducer gets them, then the item and index, and returns them as an array. */
|
|
742
|
+
reduceSpread(callback, ...initial) {
|
|
743
|
+
let result = initial;
|
|
744
|
+
this.items.forEach((item, index) => {
|
|
745
|
+
result = callback(...result, item, index);
|
|
746
|
+
if (!Array.isArray(result)) {
|
|
747
|
+
throw new TypeError(`${this.constructor.name}::reduceSpread expects reducer to return an array, but got a '${typeNameOf(result)}' instead.`);
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
return result;
|
|
751
|
+
}
|
|
752
|
+
/** The first item of each value (strict comparison), or of each key or callback value. */
|
|
362
753
|
unique(key) {
|
|
363
754
|
const seen = /* @__PURE__ */ new Set();
|
|
364
755
|
return this.filter((item) => {
|
|
@@ -368,29 +759,32 @@ var Collection = class _Collection {
|
|
|
368
759
|
return true;
|
|
369
760
|
});
|
|
370
761
|
}
|
|
762
|
+
/** unique() under Laravel's strict name (unique() already compares strictly). */
|
|
763
|
+
uniqueStrict(key) {
|
|
764
|
+
return this.unique(key);
|
|
765
|
+
}
|
|
371
766
|
chunk(size) {
|
|
372
767
|
if (size <= 0) return new _Collection();
|
|
373
768
|
const chunks = [];
|
|
374
|
-
for (let i = 0; i < this.items.length; i += size) chunks.push(
|
|
769
|
+
for (let i = 0; i < this.items.length; i += size) chunks.push(this.newInstance(this.items.slice(i, i + size)));
|
|
375
770
|
return new _Collection(chunks);
|
|
376
771
|
}
|
|
377
772
|
/** Negative count takes from the end. */
|
|
378
773
|
take(count) {
|
|
379
|
-
return
|
|
774
|
+
return this.newInstance(count < 0 ? this.items.slice(count) : this.items.slice(0, count));
|
|
380
775
|
}
|
|
381
776
|
skip(count) {
|
|
382
|
-
return
|
|
777
|
+
return this.newInstance(this.items.slice(count));
|
|
383
778
|
}
|
|
779
|
+
/** PHP's array_slice(): a negative offset counts from the end; a negative length leaves that many off the end. */
|
|
384
780
|
slice(offset, length) {
|
|
385
|
-
|
|
781
|
+
const size = this.items.length;
|
|
782
|
+
const start = offset < 0 ? Math.max(0, size + offset) : Math.min(offset, size);
|
|
783
|
+
const end = length === void 0 ? size : length < 0 ? size + length : start + length;
|
|
784
|
+
return this.newInstance(this.items.slice(start, Math.max(start, end)));
|
|
386
785
|
}
|
|
387
786
|
values() {
|
|
388
|
-
return
|
|
389
|
-
}
|
|
390
|
-
contains(keyOrValue, value2) {
|
|
391
|
-
if (arguments.length === 2) return this.items.some((item) => read(item, keyOrValue) === value2);
|
|
392
|
-
if (typeof keyOrValue === "function") return this.items.some(keyOrValue);
|
|
393
|
-
return this.items.includes(keyOrValue);
|
|
787
|
+
return this.newInstance(this.items);
|
|
394
788
|
}
|
|
395
789
|
/** Mutates, like Laravel. */
|
|
396
790
|
push(...values) {
|
|
@@ -398,103 +792,347 @@ var Collection = class _Collection {
|
|
|
398
792
|
return this;
|
|
399
793
|
}
|
|
400
794
|
concat(values) {
|
|
401
|
-
return
|
|
795
|
+
return this.newInstance([...this.items, ...values]);
|
|
402
796
|
}
|
|
403
797
|
partition(callback) {
|
|
404
798
|
return [this.filter(callback), this.reject(callback)];
|
|
405
799
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
return this.items.map((item) => read(item, keyOrGlue)).join(glue);
|
|
800
|
+
reverse() {
|
|
801
|
+
return this.newInstance([...this.items].reverse());
|
|
409
802
|
}
|
|
410
|
-
|
|
411
|
-
|
|
803
|
+
shuffle() {
|
|
804
|
+
const items = [...this.items];
|
|
805
|
+
for (let i = items.length - 1; i > 0; i--) {
|
|
806
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
807
|
+
[items[i], items[j]] = [items[j], items[i]];
|
|
808
|
+
}
|
|
809
|
+
return this.newInstance(items);
|
|
412
810
|
}
|
|
413
|
-
|
|
414
|
-
|
|
811
|
+
random(count) {
|
|
812
|
+
const requested = typeof count === "function" ? count(this) : count;
|
|
813
|
+
const wanted = requested ?? 1;
|
|
814
|
+
if (wanted > this.items.length) {
|
|
815
|
+
throw new RangeError(`You requested ${wanted} items, but there are only ${this.items.length} items available.`);
|
|
816
|
+
}
|
|
817
|
+
if (requested === void 0) return this.items[Math.floor(Math.random() * this.items.length)];
|
|
818
|
+
const indexes = [...this.items.keys()];
|
|
819
|
+
for (let i = indexes.length - 1; i > 0; i--) {
|
|
820
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
821
|
+
[indexes[i], indexes[j]] = [indexes[j], indexes[i]];
|
|
822
|
+
}
|
|
823
|
+
return this.newInstance(indexes.slice(0, Math.max(0, wanted)).sort((a, b) => a - b).map((index) => this.items[index]));
|
|
824
|
+
}
|
|
825
|
+
/** Every step-th item, starting at offset. */
|
|
826
|
+
nth(step, offset = 0) {
|
|
827
|
+
return this.newInstance(this.items.slice(offset).filter((_, position) => position % step === 0));
|
|
828
|
+
}
|
|
829
|
+
/** Pads to `size` items with the value; a negative size pads at the start (PHP's array_pad()). */
|
|
830
|
+
pad(size, value2) {
|
|
831
|
+
const missing = Math.abs(size) - this.items.length;
|
|
832
|
+
if (missing <= 0) return new _Collection(this.items);
|
|
833
|
+
const padding = Array.from({ length: missing }, () => value2);
|
|
834
|
+
return new _Collection(size < 0 ? [...padding, ...this.items] : [...this.items, ...padding]);
|
|
835
|
+
}
|
|
836
|
+
/** The items of one page: forPage(2, 15). */
|
|
837
|
+
forPage(page, perPage) {
|
|
838
|
+
return this.slice(Math.max(0, (page - 1) * perPage), perPage);
|
|
839
|
+
}
|
|
840
|
+
/** `count` groups of nearly equal size, the first ones larger. */
|
|
841
|
+
split(count) {
|
|
842
|
+
const groups = [];
|
|
843
|
+
if (this.isEmpty()) return new _Collection(groups);
|
|
844
|
+
const size = Math.floor(this.items.length / count);
|
|
845
|
+
const remain = this.items.length % count;
|
|
846
|
+
let start = 0;
|
|
847
|
+
for (let i = 0; i < count; i++) {
|
|
848
|
+
const length = size + (i < remain ? 1 : 0);
|
|
849
|
+
if (!length) continue;
|
|
850
|
+
groups.push(this.newInstance(this.items.slice(start, start + length)));
|
|
851
|
+
start += length;
|
|
852
|
+
}
|
|
853
|
+
return new _Collection(groups);
|
|
415
854
|
}
|
|
416
|
-
|
|
417
|
-
|
|
855
|
+
/** `count` groups, every group full except the last. */
|
|
856
|
+
splitIn(count) {
|
|
857
|
+
return this.chunk(Math.ceil(this.items.length / count));
|
|
858
|
+
}
|
|
859
|
+
/** Overlapping windows of `size` items, `step` apart: [1, 2, 3].sliding(2) → [[1, 2], [2, 3]]. */
|
|
860
|
+
sliding(size = 2, step = 1) {
|
|
861
|
+
const windows = Math.floor((this.items.length - size) / step) + 1;
|
|
862
|
+
return _Collection.times(windows, (number) => this.slice((number - 1) * step, size));
|
|
863
|
+
}
|
|
864
|
+
/** Chunks that grow while the callback (value, index, the current chunk) returns true. */
|
|
865
|
+
chunkWhile(callback) {
|
|
866
|
+
const chunks = [];
|
|
867
|
+
let chunk = this.newInstance();
|
|
868
|
+
this.items.forEach((item, index) => {
|
|
869
|
+
if (index > 0 && !callback(item, index, chunk)) {
|
|
870
|
+
chunks.push(chunk);
|
|
871
|
+
chunk = this.newInstance();
|
|
872
|
+
}
|
|
873
|
+
chunk.push(item);
|
|
874
|
+
});
|
|
875
|
+
if (chunk.isNotEmpty()) chunks.push(chunk);
|
|
876
|
+
return new _Collection(chunks);
|
|
877
|
+
}
|
|
878
|
+
takeUntil(value2) {
|
|
879
|
+
const stop = this.items.findIndex(predicateFor(value2));
|
|
880
|
+
return this.newInstance(stop === -1 ? this.items : this.items.slice(0, stop));
|
|
881
|
+
}
|
|
882
|
+
takeWhile(value2) {
|
|
883
|
+
const keep = predicateFor(value2);
|
|
884
|
+
const stop = this.items.findIndex((item, index) => !keep(item, index));
|
|
885
|
+
return this.newInstance(stop === -1 ? this.items : this.items.slice(0, stop));
|
|
886
|
+
}
|
|
887
|
+
skipUntil(value2) {
|
|
888
|
+
const start = this.items.findIndex(predicateFor(value2));
|
|
889
|
+
return this.newInstance(start === -1 ? [] : this.items.slice(start));
|
|
890
|
+
}
|
|
891
|
+
skipWhile(value2) {
|
|
892
|
+
const skip = predicateFor(value2);
|
|
893
|
+
const start = this.items.findIndex((item, index) => !skip(item, index));
|
|
894
|
+
return this.newInstance(start === -1 ? [] : this.items.slice(start));
|
|
895
|
+
}
|
|
896
|
+
/** The items at the given indexes, in collection order. */
|
|
897
|
+
only(...indexes) {
|
|
898
|
+
const wanted = new Set(indexes.flat());
|
|
899
|
+
return this.newInstance(this.items.filter((_, index) => wanted.has(index)));
|
|
900
|
+
}
|
|
901
|
+
/** The items except those at the given indexes. */
|
|
902
|
+
except(...indexes) {
|
|
903
|
+
const unwanted = new Set(indexes.flat());
|
|
904
|
+
return this.newInstance(this.items.filter((_, index) => !unwanted.has(index)));
|
|
905
|
+
}
|
|
906
|
+
/** The indexes: 0, 1, 2, … */
|
|
907
|
+
keys() {
|
|
908
|
+
return new _Collection(this.items.keys());
|
|
909
|
+
}
|
|
910
|
+
pop(count) {
|
|
911
|
+
if (count === void 0) return this.items.pop();
|
|
912
|
+
const removed = [];
|
|
913
|
+
while (removed.length < count && this.items.length) removed.push(this.items.pop());
|
|
914
|
+
return this.newInstance(removed);
|
|
915
|
+
}
|
|
916
|
+
shift(count) {
|
|
917
|
+
if (count !== void 0 && count < 0) throw new RangeError("Number of shifted items may not be less than zero.");
|
|
918
|
+
if (count === void 0) return this.items.shift();
|
|
919
|
+
return this.newInstance(this.items.splice(0, count));
|
|
920
|
+
}
|
|
921
|
+
/** Adds an item at the start (mutates). */
|
|
922
|
+
prepend(value2) {
|
|
923
|
+
this.items.unshift(value2);
|
|
418
924
|
return this;
|
|
419
925
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
var LazyCollection = class _LazyCollection {
|
|
425
|
-
constructor(source) {
|
|
426
|
-
this.source = source;
|
|
926
|
+
/** Adds items at the start, in the given order (mutates). */
|
|
927
|
+
unshift(...values) {
|
|
928
|
+
this.items.unshift(...values);
|
|
929
|
+
return this;
|
|
427
930
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
931
|
+
/** Adds one item at the end (mutates). */
|
|
932
|
+
add(item) {
|
|
933
|
+
this.items.push(item);
|
|
934
|
+
return this;
|
|
431
935
|
}
|
|
432
|
-
|
|
433
|
-
|
|
936
|
+
/** Sets the item at an index (mutates); an index at or past the end appends. */
|
|
937
|
+
put(index, value2) {
|
|
938
|
+
if (!Number.isInteger(index) || index < 0) throw new RangeError(`Invalid collection index [${index}].`);
|
|
939
|
+
if (index < this.items.length) this.items[index] = value2;
|
|
940
|
+
else this.items.push(value2);
|
|
941
|
+
return this;
|
|
434
942
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
return
|
|
438
|
-
let i = 0;
|
|
439
|
-
for await (const item of self) yield await callback(item, i++);
|
|
440
|
-
});
|
|
943
|
+
pull(index, defaultValue) {
|
|
944
|
+
if (isIndex(index, this.items.length)) return this.items.splice(index, 1)[0];
|
|
945
|
+
return typeof defaultValue === "function" ? defaultValue() : defaultValue;
|
|
441
946
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
});
|
|
947
|
+
/** Removes the items at the given indexes (mutates); the later items move up. */
|
|
948
|
+
forget(...indexes) {
|
|
949
|
+
const remove = [...new Set(indexes.flat())].filter((index) => isIndex(index, this.items.length)).sort((a, b) => b - a);
|
|
950
|
+
for (const index of remove) this.items.splice(index, 1);
|
|
951
|
+
return this;
|
|
448
952
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
953
|
+
/**
|
|
954
|
+
* Removes `length` items from `offset` (mutates), inserting the replacement there, and returns the removed items
|
|
955
|
+
* (PHP's array_splice(): a negative offset counts from the end; a negative length leaves that many at the end).
|
|
956
|
+
*/
|
|
957
|
+
splice(offset, length, replacement = []) {
|
|
958
|
+
const size = this.items.length;
|
|
959
|
+
const start = offset < 0 ? Math.max(0, size + offset) : Math.min(offset, size);
|
|
960
|
+
const count = length === void 0 ? size - start : length < 0 ? Math.max(0, size + length - start) : length;
|
|
961
|
+
return this.newInstance(this.items.splice(start, count, ...replacement));
|
|
962
|
+
}
|
|
963
|
+
/** Replaces every item with the callback's result (mutates) and returns this collection, typed with the new items. */
|
|
964
|
+
transform(callback) {
|
|
965
|
+
const items = this.items;
|
|
966
|
+
items.forEach((item, index) => {
|
|
967
|
+
items[index] = callback(item, index);
|
|
458
968
|
});
|
|
969
|
+
return this;
|
|
459
970
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
971
|
+
/**
|
|
972
|
+
* A copy with items replaced by index: an array from index 0, or { index: value }; past the end appends, and a
|
|
973
|
+
* negative or fractional index throws a RangeError, as put() does.
|
|
974
|
+
*/
|
|
975
|
+
replace(items) {
|
|
976
|
+
const copy = this.newInstance(this.items);
|
|
977
|
+
const entries = Symbol.iterator in items ? [...items].map((value2, index) => [index, value2]) : Object.entries(items).map(([index, value2]) => [Number(index), value2]);
|
|
978
|
+
for (const [index, value2] of [...entries].sort((a, b) => a[0] - b[0])) copy.put(index, value2);
|
|
979
|
+
return copy;
|
|
980
|
+
}
|
|
981
|
+
// ---------------------------------------------------------------- building collections
|
|
982
|
+
/** One level of nested arrays and collections, merged (other items are dropped). */
|
|
983
|
+
collapse() {
|
|
984
|
+
const result = [];
|
|
985
|
+
for (const item of this.items) {
|
|
986
|
+
if (item instanceof _Collection) result.push(...item.all());
|
|
987
|
+
else if (Array.isArray(item)) result.push(...item);
|
|
988
|
+
}
|
|
989
|
+
return new _Collection(result);
|
|
990
|
+
}
|
|
991
|
+
flatten(depth = Infinity) {
|
|
992
|
+
return new _Collection(flattenItems(this.items, depth));
|
|
993
|
+
}
|
|
994
|
+
/** Every combination of the items with the lists' items: [1, 2] × ['a'] → [[1, 'a'], [2, 'a']]. */
|
|
995
|
+
crossJoin(...lists) {
|
|
996
|
+
let rows = this.items.map((item) => [item]);
|
|
997
|
+
for (const list of lists) {
|
|
998
|
+
const values = [...list];
|
|
999
|
+
rows = rows.flatMap((row) => values.map((value2) => [...row, value2]));
|
|
1000
|
+
}
|
|
1001
|
+
return new _Collection(rows);
|
|
1002
|
+
}
|
|
1003
|
+
/** Pairs items by index with the lists' items, as collections; the shorter lists give undefined. */
|
|
1004
|
+
zip(...lists) {
|
|
1005
|
+
const arrays = lists.map((list) => [...list]);
|
|
1006
|
+
const length = Math.max(this.items.length, ...arrays.map((array) => array.length));
|
|
1007
|
+
return _Collection.times(length, (number) => new _Collection([this.items[number - 1], ...arrays.map((array) => array[number - 1])]));
|
|
1008
|
+
}
|
|
1009
|
+
/** The items as keys for the values: ['name', 'age'].combine(['George', 29]) → { name: 'George', age: 29 }. */
|
|
1010
|
+
combine(values) {
|
|
1011
|
+
const list = [...values];
|
|
1012
|
+
if (list.length !== this.items.length) {
|
|
1013
|
+
throw new RangeError("combine(): the keys and the values must have the same number of items.");
|
|
1014
|
+
}
|
|
1015
|
+
return Object.fromEntries(this.items.map((key, index) => [String(key), list[index]]));
|
|
1016
|
+
}
|
|
1017
|
+
/** Each item as a key for its index: ['a', 'b'] → { a: 0, b: 1 }. */
|
|
1018
|
+
flip() {
|
|
1019
|
+
return Object.fromEntries(this.items.map((item, index) => [String(item), index]));
|
|
1020
|
+
}
|
|
1021
|
+
/** The items followed by the given ones (a list merges by appending). */
|
|
1022
|
+
merge(items) {
|
|
1023
|
+
return this.concat(items);
|
|
1024
|
+
}
|
|
1025
|
+
/** The items repeated `multiplier` times. */
|
|
1026
|
+
multiply(multiplier) {
|
|
1027
|
+
return this.newInstance(Array.from({ length: Math.max(0, multiplier) }, () => this.items).flat());
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* Each item reduced to the given keys it has: select(['name', 'role']). An item has a key when `key in item` or
|
|
1031
|
+
* reading it gives a value, so a model's attributes, which its proxy serves on read, are kept.
|
|
1032
|
+
*/
|
|
1033
|
+
select(...keys) {
|
|
1034
|
+
const names = keys.flat();
|
|
1035
|
+
return this.map((item) => {
|
|
1036
|
+
const picked = {};
|
|
1037
|
+
if (typeof item !== "object" || item === null) return picked;
|
|
1038
|
+
for (const key of names) {
|
|
1039
|
+
const value2 = item[key];
|
|
1040
|
+
if (key in item || value2 !== void 0) picked[key] = value2;
|
|
471
1041
|
}
|
|
472
|
-
|
|
1042
|
+
return picked;
|
|
473
1043
|
});
|
|
474
1044
|
}
|
|
475
|
-
/**
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
1045
|
+
/** A LazyCollection over a copy of the items: later changes to this collection don't reach it. */
|
|
1046
|
+
lazy() {
|
|
1047
|
+
const items = this.all();
|
|
1048
|
+
return LazyCollection.make(() => items);
|
|
479
1049
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
return
|
|
1050
|
+
/** A base collection with the same items. */
|
|
1051
|
+
collect() {
|
|
1052
|
+
return new _Collection(this.items);
|
|
483
1053
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
n++;
|
|
489
|
-
}
|
|
490
|
-
return n;
|
|
1054
|
+
implode(keyOrGlue, glue) {
|
|
1055
|
+
if (typeof keyOrGlue === "function") return this.items.map(keyOrGlue).join(glue);
|
|
1056
|
+
if (glue === void 0) return this.items.join(keyOrGlue);
|
|
1057
|
+
return this.items.map((item) => read(item, keyOrGlue)).join(glue);
|
|
491
1058
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
return
|
|
1059
|
+
/** implode() with a different glue before the last item: join(', ', ' and ') → 'a, b and c'. */
|
|
1060
|
+
join(glue, finalGlue = "") {
|
|
1061
|
+
if (finalGlue === "" || this.items.length < 2) return this.implode(glue);
|
|
1062
|
+
return `${this.items.slice(0, -1).join(glue)}${finalGlue}${String(this.items.at(-1))}`;
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Runs the callback (collection, value) when the value is truthy, else the default; a function value is called with
|
|
1066
|
+
* the collection first. Returns what the callback returns, or the collection when it returns nothing.
|
|
1067
|
+
*/
|
|
1068
|
+
when(value2, callback, otherwise) {
|
|
1069
|
+
const resolved = typeof value2 === "function" ? value2(this) : value2;
|
|
1070
|
+
const result = resolved ? callback(this, resolved) : otherwise?.(this, resolved);
|
|
1071
|
+
return result ?? this;
|
|
1072
|
+
}
|
|
1073
|
+
/** when() with the condition reversed. */
|
|
1074
|
+
unless(value2, callback, otherwise) {
|
|
1075
|
+
const resolved = typeof value2 === "function" ? value2(this) : value2;
|
|
1076
|
+
const result = !resolved ? callback(this, resolved) : otherwise?.(this, resolved);
|
|
1077
|
+
return result ?? this;
|
|
1078
|
+
}
|
|
1079
|
+
whenEmpty(callback, otherwise) {
|
|
1080
|
+
return this.when(this.isEmpty(), (collection) => callback(collection), otherwise && ((collection) => otherwise(collection)));
|
|
1081
|
+
}
|
|
1082
|
+
whenNotEmpty(callback, otherwise) {
|
|
1083
|
+
return this.when(this.isNotEmpty(), (collection) => callback(collection), otherwise && ((collection) => otherwise(collection)));
|
|
1084
|
+
}
|
|
1085
|
+
/** whenNotEmpty() under Laravel's other name. */
|
|
1086
|
+
unlessEmpty(callback, otherwise) {
|
|
1087
|
+
return this.whenNotEmpty(callback, otherwise);
|
|
1088
|
+
}
|
|
1089
|
+
/** whenEmpty() under Laravel's other name. */
|
|
1090
|
+
unlessNotEmpty(callback, otherwise) {
|
|
1091
|
+
return this.whenEmpty(callback, otherwise);
|
|
1092
|
+
}
|
|
1093
|
+
pipe(callback) {
|
|
1094
|
+
return callback(this);
|
|
1095
|
+
}
|
|
1096
|
+
/** new cls(collection). */
|
|
1097
|
+
pipeInto(cls) {
|
|
1098
|
+
return new cls(this);
|
|
1099
|
+
}
|
|
1100
|
+
pipeThrough(callbacks) {
|
|
1101
|
+
return callbacks.reduce((carry, callback) => callback(carry), this);
|
|
1102
|
+
}
|
|
1103
|
+
tap(callback) {
|
|
1104
|
+
callback(this);
|
|
1105
|
+
return this;
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* Throws a TypeError unless every item is an instance of one of the classes or of one of the type names (typeof's,
|
|
1109
|
+
* plus 'null' and 'array'), with Laravel's message. Returns the collection, typed with the checked items.
|
|
1110
|
+
*/
|
|
1111
|
+
ensure(type2) {
|
|
1112
|
+
const allowed = [type2].flat();
|
|
1113
|
+
this.items.forEach((item, index) => {
|
|
1114
|
+
const name = typeNameOf(item);
|
|
1115
|
+
const ok = allowed.some((entry) => typeof entry === "string" ? entry === name || entry === "object" && typeof item === "object" && item !== null && !Array.isArray(item) : item instanceof entry);
|
|
1116
|
+
if (!ok) {
|
|
1117
|
+
const names = allowed.map((entry) => typeof entry === "string" ? entry : entry.name).join(", ");
|
|
1118
|
+
throw new TypeError(`Collection should only include [${names}] items, but '${name}' found at position ${index}.`);
|
|
1119
|
+
}
|
|
1120
|
+
});
|
|
1121
|
+
return this;
|
|
1122
|
+
}
|
|
1123
|
+
/** Logs the items (and any extra values) with console.log and returns the collection. */
|
|
1124
|
+
dump(...values) {
|
|
1125
|
+
console.log(this.all(), ...values);
|
|
1126
|
+
return this;
|
|
1127
|
+
}
|
|
1128
|
+
/** JSON with four-space indentation (PHP's JSON_PRETTY_PRINT). */
|
|
1129
|
+
toPrettyJson() {
|
|
1130
|
+
return JSON.stringify(this, null, 4);
|
|
496
1131
|
}
|
|
497
1132
|
};
|
|
1133
|
+
function collect(items = []) {
|
|
1134
|
+
return new Collection(items);
|
|
1135
|
+
}
|
|
498
1136
|
|
|
499
1137
|
// ../Support/dist/index.js
|
|
500
1138
|
import { randomBytes, randomUUID } from "crypto";
|
|
@@ -2572,9 +3210,11 @@ export {
|
|
|
2572
3210
|
currentContainer,
|
|
2573
3211
|
inject,
|
|
2574
3212
|
Container2 as Container,
|
|
3213
|
+
ItemNotFoundError,
|
|
3214
|
+
MultipleItemsFoundError,
|
|
3215
|
+
LazyCollection,
|
|
2575
3216
|
Collection,
|
|
2576
3217
|
collect,
|
|
2577
|
-
LazyCollection,
|
|
2578
3218
|
Stringable,
|
|
2579
3219
|
Str,
|
|
2580
3220
|
Arr,
|
|
@@ -2610,4 +3250,4 @@ export {
|
|
|
2610
3250
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
2611
3251
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
2612
3252
|
*/
|
|
2613
|
-
//# sourceMappingURL=chunk-
|
|
3253
|
+
//# sourceMappingURL=chunk-7ZQZYDOC.js.map
|