blackcat.js-database 1.0.6 → 1.0.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/dist/index.cjs +362 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +320 -22
- package/dist/index.d.ts +320 -22
- package/dist/index.mjs +362 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -343,9 +343,7 @@ var Database = class {
|
|
|
343
343
|
const data = await this.get(key);
|
|
344
344
|
if (!query) return data;
|
|
345
345
|
if (!Array.isArray(data)) return null;
|
|
346
|
-
const result = data.find((item) =>
|
|
347
|
-
return Object.entries(query).every(([k, v]) => item[k] == v);
|
|
348
|
-
});
|
|
346
|
+
const result = data.find((item) => Object.entries(query).every(([k, v]) => item[k] == v));
|
|
349
347
|
return result ?? null;
|
|
350
348
|
}
|
|
351
349
|
/**
|
|
@@ -416,23 +414,69 @@ var Database = class {
|
|
|
416
414
|
await this.driver.set(allDatabase);
|
|
417
415
|
}
|
|
418
416
|
/**
|
|
419
|
-
*
|
|
417
|
+
* Đảm bảo một key tồn tại với giá trị mặc định.
|
|
418
|
+
* Nếu key đã tồn tại → giữ nguyên và trả về giá trị hiện tại.
|
|
419
|
+
* Nếu chưa tồn tại → set giá trị default và trả về default đó.
|
|
420
|
+
*
|
|
421
|
+
* Khác với `set()` — không bao giờ ghi đè dữ liệu đã có.
|
|
422
|
+
*
|
|
423
|
+
* @template P Key path trong database.
|
|
424
|
+
*
|
|
425
|
+
* @param key Đường dẫn cần đảm bảo tồn tại.
|
|
426
|
+
* @param defaultValue Giá trị mặc định nếu key chưa có.
|
|
427
|
+
*
|
|
428
|
+
* @returns Giá trị tại key sau khi ensure (current hoặc default).
|
|
429
|
+
*
|
|
430
|
+
* @example
|
|
431
|
+
* // "config.maxRetries" chưa tồn tại → set về 3, trả về 3
|
|
432
|
+
* const retries = await db.ensure("config.maxRetries", 3);
|
|
433
|
+
*
|
|
434
|
+
* @example
|
|
435
|
+
* // "config.maxRetries" đã là 10 → không đổi, trả về 10
|
|
436
|
+
* const retries = await db.ensure("config.maxRetries", 3);
|
|
420
437
|
*
|
|
421
|
-
*
|
|
438
|
+
* @example
|
|
439
|
+
* // Dùng với object — đảm bảo cấu trúc user tồn tại
|
|
440
|
+
* const user = await db.ensure("users.123", {
|
|
441
|
+
* balance: 0,
|
|
442
|
+
* level: 1,
|
|
443
|
+
* joinedAt: Date.now(),
|
|
444
|
+
* });
|
|
445
|
+
*/
|
|
446
|
+
async ensure(key, defaultValue) {
|
|
447
|
+
const current = await this.get(key);
|
|
448
|
+
if (current !== null && current !== void 0) return current;
|
|
449
|
+
await this.set(key, defaultValue);
|
|
450
|
+
return defaultValue;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Xóa dữ liệu khỏi database.
|
|
454
|
+
* Hỗ trợ truy cập dữ liệu lồng nhau bằng dot notation.
|
|
455
|
+
* Nếu key không tồn tại hoặc đường dẫn không hợp lệ, hàm sẽ trả về `false`.
|
|
422
456
|
*
|
|
423
457
|
* @typeParam P - Path của object.
|
|
424
458
|
*
|
|
425
|
-
* @param key - Đường dẫn
|
|
459
|
+
* @param key - Đường dẫn dữ liệu cần xóa.
|
|
426
460
|
*
|
|
427
461
|
* @returns
|
|
428
|
-
* - `true` nếu xóa thành công
|
|
429
|
-
* - `false` nếu key không tồn tại
|
|
462
|
+
* - `true` nếu xóa thành công.
|
|
463
|
+
* - `false` nếu key không tồn tại hoặc đường dẫn không hợp lệ.
|
|
430
464
|
*
|
|
431
465
|
* @throws BlackCatError
|
|
432
|
-
* - INVALID_TYPE nếu key không phải
|
|
466
|
+
* - INVALID_TYPE nếu `key` không phải là chuỗi.
|
|
433
467
|
*
|
|
434
468
|
* @example
|
|
469
|
+
* // Xóa một thuộc tính
|
|
435
470
|
* await db.delete("user.name");
|
|
471
|
+
*
|
|
472
|
+
* @example
|
|
473
|
+
* // Xóa object lồng nhau
|
|
474
|
+
* await db.delete("users.0.profile");
|
|
475
|
+
*
|
|
476
|
+
* @example
|
|
477
|
+
* // Key không tồn tại
|
|
478
|
+
* const deleted = await db.delete("user.address");
|
|
479
|
+
* console.log(deleted); // false
|
|
436
480
|
*/
|
|
437
481
|
async delete(key) {
|
|
438
482
|
if (typeof key !== "string") {
|
|
@@ -464,8 +508,8 @@ var Database = class {
|
|
|
464
508
|
* await db.deleteAll();
|
|
465
509
|
*/
|
|
466
510
|
async deleteAll() {
|
|
467
|
-
await this.driver.delete();
|
|
468
|
-
return
|
|
511
|
+
const result = await this.driver.delete();
|
|
512
|
+
return result;
|
|
469
513
|
}
|
|
470
514
|
/**
|
|
471
515
|
* Xóa nhiều bản ghi trong một mảng dữ liệu dựa trên điều kiện truy vấn.
|
|
@@ -521,25 +565,57 @@ var Database = class {
|
|
|
521
565
|
return originalLength - filtered.length;
|
|
522
566
|
}
|
|
523
567
|
/**
|
|
524
|
-
* Cập nhật dữ liệu trong database theo đường dẫn key.
|
|
568
|
+
* Cập nhật dữ liệu trong database theo đường dẫn (`key`).
|
|
569
|
+
*
|
|
570
|
+
* ## Chức năng
|
|
571
|
+
* - Cập nhật giá trị tại một key hoặc nested key trong database.
|
|
572
|
+
* - Tự động tạo object trung gian nếu đường dẫn chưa tồn tại.
|
|
573
|
+
* - Hỗ trợ gộp dữ liệu (merge) đối với object và mảng nhằm hạn chế ghi đè dữ liệu đã có.
|
|
574
|
+
*
|
|
575
|
+
* ## Mô tả hoạt động
|
|
576
|
+
* Hàm sẽ đọc toàn bộ dữ liệu database, tìm đến vị trí tương ứng với `key`
|
|
577
|
+
* và cập nhật giá trị mới theo các quy tắc sau:
|
|
578
|
+
*
|
|
579
|
+
* - **Đối với Array**
|
|
580
|
+
* - Nếu cả giá trị hiện tại và giá trị mới đều là mảng thì sẽ **không ghi đè**.
|
|
581
|
+
* - Các phần tử mới sẽ được thêm vào cuối mảng.
|
|
582
|
+
* - Chỉ thêm những phần tử chưa tồn tại ví dụ dựa trên cặp thuộc tính:
|
|
583
|
+
* - `username`
|
|
584
|
+
* - `guild`
|
|
585
|
+
* - Điều này giúp tránh lưu trùng dữ liệu thành viên giữa nhiều lần cập nhật.
|
|
586
|
+
*
|
|
587
|
+
* - **Đối với Object**
|
|
588
|
+
* - Nếu cả hai đều là object sẽ thực hiện **shallow merge** (`...old, ...new`).
|
|
589
|
+
* - Các thuộc tính mới sẽ ghi đè thuộc tính cùng tên.
|
|
590
|
+
* - Những thuộc tính khác vẫn được giữ nguyên.
|
|
525
591
|
*
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
* **shallow merge** thay vì ghi đè toàn bộ object.
|
|
592
|
+
* - **Các kiểu dữ liệu khác**
|
|
593
|
+
* - Giá trị mới sẽ ghi đè hoàn toàn giá trị cũ.
|
|
529
594
|
*
|
|
530
|
-
*
|
|
595
|
+
* Sau khi cập nhật xong, toàn bộ database sẽ được ghi lại thông qua driver.
|
|
531
596
|
*
|
|
532
|
-
* @template P
|
|
597
|
+
* @template P
|
|
598
|
+
* Đường dẫn hợp lệ của object trong database.
|
|
533
599
|
*
|
|
534
|
-
* @param key
|
|
535
|
-
*
|
|
600
|
+
* @param key
|
|
601
|
+
* Đường dẫn cần cập nhật.
|
|
536
602
|
*
|
|
537
|
-
*
|
|
603
|
+
* Hỗ trợ nested path:
|
|
604
|
+
* ```ts
|
|
605
|
+
* "guilds.123.settings.prefix"
|
|
606
|
+
* "users.456.profile.name"
|
|
607
|
+
* ```
|
|
608
|
+
*
|
|
609
|
+
* @param value
|
|
610
|
+
* Giá trị mới cần cập nhật.
|
|
538
611
|
*
|
|
539
612
|
* @returns
|
|
540
|
-
* Trả về giá trị cuối cùng sau khi
|
|
613
|
+
* Trả về giá trị cuối cùng sau khi được lưu vào database.
|
|
614
|
+
*
|
|
615
|
+
* ## Cách sử dụng
|
|
616
|
+
*
|
|
617
|
+
* ### Ví dụ 1 - Cập nhật object
|
|
541
618
|
*
|
|
542
|
-
* @example
|
|
543
619
|
* Database ban đầu:
|
|
544
620
|
* ```json
|
|
545
621
|
* {
|
|
@@ -551,10 +627,9 @@ var Database = class {
|
|
|
551
627
|
* }
|
|
552
628
|
* ```
|
|
553
629
|
*
|
|
554
|
-
* Cập nhật:
|
|
555
630
|
* ```ts
|
|
556
631
|
* await db.update("123", {
|
|
557
|
-
*
|
|
632
|
+
* history: [1, 2, 3]
|
|
558
633
|
* });
|
|
559
634
|
* ```
|
|
560
635
|
*
|
|
@@ -564,14 +639,120 @@ var Database = class {
|
|
|
564
639
|
* "123": {
|
|
565
640
|
* "guildID": "123",
|
|
566
641
|
* "guildName": "BlackCat",
|
|
567
|
-
* "history": [1,2,3]
|
|
642
|
+
* "history": [1, 2, 3]
|
|
568
643
|
* }
|
|
569
644
|
* }
|
|
570
645
|
* ```
|
|
571
646
|
*
|
|
647
|
+
* ---
|
|
648
|
+
*
|
|
649
|
+
* ### Ví dụ 2 - Cập nhật nested key
|
|
650
|
+
*
|
|
651
|
+
* ```ts
|
|
652
|
+
* await db.update("guilds.123.settings.prefix", "!");
|
|
653
|
+
* ```
|
|
654
|
+
*
|
|
655
|
+
* Nếu đường dẫn chưa tồn tại:
|
|
656
|
+
*
|
|
657
|
+
* ```json
|
|
658
|
+
* {}
|
|
659
|
+
* ```
|
|
660
|
+
*
|
|
661
|
+
* Sau khi cập nhật:
|
|
662
|
+
*
|
|
663
|
+
* ```json
|
|
664
|
+
* {
|
|
665
|
+
* "guilds": {
|
|
666
|
+
* "123": {
|
|
667
|
+
* "settings": {
|
|
668
|
+
* "prefix": "!"
|
|
669
|
+
* }
|
|
670
|
+
* }
|
|
671
|
+
* }
|
|
672
|
+
* }
|
|
673
|
+
* ```
|
|
674
|
+
*
|
|
675
|
+
* ---
|
|
676
|
+
*
|
|
677
|
+
* ### Ví dụ 3 - Merge object
|
|
678
|
+
*
|
|
679
|
+
* Giá trị hiện tại:
|
|
680
|
+
*
|
|
681
|
+
* ```json
|
|
682
|
+
* {
|
|
683
|
+
* "name": "BlackCat",
|
|
684
|
+
* "language": "vi",
|
|
685
|
+
* "prefix": "!"
|
|
686
|
+
* }
|
|
687
|
+
* ```
|
|
688
|
+
*
|
|
689
|
+
* ```ts
|
|
690
|
+
* await db.update("config", {
|
|
691
|
+
* prefix: "?",
|
|
692
|
+
* color: "#5865F2"
|
|
693
|
+
* });
|
|
694
|
+
* ```
|
|
695
|
+
*
|
|
696
|
+
* Kết quả:
|
|
697
|
+
*
|
|
698
|
+
* ```json
|
|
699
|
+
* {
|
|
700
|
+
* "name": "BlackCat",
|
|
701
|
+
* "language": "vi",
|
|
702
|
+
* "prefix": "?",
|
|
703
|
+
* "color": "#5865F2"
|
|
704
|
+
* }
|
|
705
|
+
* ```
|
|
706
|
+
*
|
|
707
|
+
* ---
|
|
708
|
+
*
|
|
709
|
+
* ### Ví dụ 4 - Merge mảng và loại bỏ phần tử trùng
|
|
710
|
+
*
|
|
711
|
+
* Giá trị hiện tại:
|
|
712
|
+
*
|
|
713
|
+
* ```json
|
|
714
|
+
* [
|
|
715
|
+
* {
|
|
716
|
+
* "username": "Alice",
|
|
717
|
+
* "guild": "123"
|
|
718
|
+
* }
|
|
719
|
+
* ]
|
|
720
|
+
* ```
|
|
721
|
+
*
|
|
722
|
+
* ```ts
|
|
723
|
+
* await db.update("history", [
|
|
724
|
+
* {
|
|
725
|
+
* username: "Alice",
|
|
726
|
+
* guild: "123"
|
|
727
|
+
* },
|
|
728
|
+
* {
|
|
729
|
+
* username: "Bob",
|
|
730
|
+
* guild: "123"
|
|
731
|
+
* }
|
|
732
|
+
* ]);
|
|
733
|
+
* ```
|
|
734
|
+
*
|
|
735
|
+
* Kết quả:
|
|
736
|
+
*
|
|
737
|
+
* ```json
|
|
738
|
+
* [
|
|
739
|
+
* {
|
|
740
|
+
* "username": "Alice",
|
|
741
|
+
* "guild": "123"
|
|
742
|
+
* },
|
|
743
|
+
* {
|
|
744
|
+
* "username": "Bob",
|
|
745
|
+
* "guild": "123"
|
|
746
|
+
* }
|
|
747
|
+
* ]
|
|
748
|
+
* ```
|
|
749
|
+
*
|
|
750
|
+
* Phần tử `"Alice"` sẽ không được thêm lần nữa vì đã tồn tại với cùng
|
|
751
|
+
* `username` và `guild`.
|
|
752
|
+
*
|
|
572
753
|
* @throws {BlackCatError}
|
|
573
|
-
* - `REQUIRED_PARAMETER_MISSING` nếu
|
|
574
|
-
* - `INVALID_TYPE` nếu key không phải string
|
|
754
|
+
* - `REQUIRED_PARAMETER_MISSING` nếu không truyền `key`.
|
|
755
|
+
* - `INVALID_TYPE` nếu `key` không phải kiểu `string`.
|
|
575
756
|
*/
|
|
576
757
|
async update(key, value) {
|
|
577
758
|
if (!key) {
|
|
@@ -591,9 +772,13 @@ var Database = class {
|
|
|
591
772
|
current = current[part];
|
|
592
773
|
}
|
|
593
774
|
const lastKey = keys[keys.length - 1];
|
|
594
|
-
|
|
775
|
+
const currentValue = current[lastKey];
|
|
776
|
+
if (Array.isArray(value) && Array.isArray(currentValue)) {
|
|
777
|
+
const unique = value.filter((item) => !currentValue.some((existing) => existing.username === item.username && existing.guild === item.guild));
|
|
778
|
+
current[lastKey] = [...currentValue, ...unique];
|
|
779
|
+
} else if (isObject(value) && isObject(currentValue)) {
|
|
595
780
|
current[lastKey] = {
|
|
596
|
-
...
|
|
781
|
+
...currentValue,
|
|
597
782
|
...value
|
|
598
783
|
};
|
|
599
784
|
} else {
|
|
@@ -602,6 +787,114 @@ var Database = class {
|
|
|
602
787
|
await this.driver.set(allDatabase);
|
|
603
788
|
return current[lastKey];
|
|
604
789
|
}
|
|
790
|
+
/**
|
|
791
|
+
* ## Đồng bộ dữ liệu với cơ sở dữ liệu
|
|
792
|
+
*
|
|
793
|
+
* ### Chức năng
|
|
794
|
+
* Đồng bộ dữ liệu tại một đường dẫn (`keys`) với giá trị mới (`value`).
|
|
795
|
+
*
|
|
796
|
+
* Hàm sẽ tự động:
|
|
797
|
+
* - Tạo mới dữ liệu nếu chưa tồn tại.
|
|
798
|
+
* - So sánh dữ liệu cũ và mới.
|
|
799
|
+
* - Chỉ cập nhật các trường thực sự thay đổi đối với Object.
|
|
800
|
+
* - Không thực hiện ghi nếu dữ liệu không thay đổi.
|
|
801
|
+
*
|
|
802
|
+
* Điều này giúp giảm số lần ghi xuống cơ sở dữ liệu và tối ưu hiệu năng.
|
|
803
|
+
*
|
|
804
|
+
* ---
|
|
805
|
+
*
|
|
806
|
+
* ### Cơ chế hoạt động
|
|
807
|
+
*
|
|
808
|
+
* 1. Lấy dữ liệu hiện tại bằng `get()`.
|
|
809
|
+
* 2. Nếu chưa tồn tại (`undefined` hoặc `null`)
|
|
810
|
+
* → gọi `set()` để tạo mới.
|
|
811
|
+
* 3. Nếu truyền hàm `compare` và hàm này trả về `true`
|
|
812
|
+
* → bỏ qua đồng bộ.
|
|
813
|
+
* 4. Nếu dữ liệu không phải Object (hoặc là Array)
|
|
814
|
+
* → so sánh bằng `Object.is()`, nếu khác thì gọi `update()`.
|
|
815
|
+
* 5. Nếu dữ liệu là Object
|
|
816
|
+
* → chỉ lấy các thuộc tính thay đổi và cập nhật đúng các trường đó.
|
|
817
|
+
* 6. Nếu không có trường nào thay đổi thì không ghi dữ liệu.
|
|
818
|
+
*
|
|
819
|
+
* ---
|
|
820
|
+
*
|
|
821
|
+
* ### Giá trị trả về
|
|
822
|
+
*
|
|
823
|
+
* - `undefined`
|
|
824
|
+
* - Khi tạo mới dữ liệu.
|
|
825
|
+
* - Khi không có thay đổi.
|
|
826
|
+
* - Khi dữ liệu nguyên thủy được cập nhật.
|
|
827
|
+
* - `Partial<ObjectValue<V, P>>`
|
|
828
|
+
* - Trả về object chỉ chứa các trường đã được cập nhật khi đồng bộ Object.
|
|
829
|
+
*
|
|
830
|
+
* ---
|
|
831
|
+
*
|
|
832
|
+
* ### Ví dụ
|
|
833
|
+
*
|
|
834
|
+
* ```ts
|
|
835
|
+
* // Tạo mới nếu chưa tồn tại
|
|
836
|
+
* await db.syncDatabase({
|
|
837
|
+
* keys: "users.1",
|
|
838
|
+
* value: {
|
|
839
|
+
* name: "BlackCat",
|
|
840
|
+
* age: 20
|
|
841
|
+
* }
|
|
842
|
+
* });
|
|
843
|
+
*
|
|
844
|
+
* // Chỉ cập nhật trường age
|
|
845
|
+
* await db.syncDatabase({
|
|
846
|
+
* keys: "users.1",
|
|
847
|
+
* value: {
|
|
848
|
+
* name: "BlackCat",
|
|
849
|
+
* age: 21
|
|
850
|
+
* }
|
|
851
|
+
* });
|
|
852
|
+
*
|
|
853
|
+
* // Sử dụng compare để bỏ qua đồng bộ
|
|
854
|
+
* await db.syncDatabase({
|
|
855
|
+
* keys: "users.1",
|
|
856
|
+
* value: newData,
|
|
857
|
+
* compare(oldData, newData) {
|
|
858
|
+
* return oldData.version >= newData.version;
|
|
859
|
+
* }
|
|
860
|
+
* });
|
|
861
|
+
* ```
|
|
862
|
+
*
|
|
863
|
+
* @template P Đường dẫn tới dữ liệu trong cơ sở dữ liệu.
|
|
864
|
+
*
|
|
865
|
+
* @param options Thông tin đồng bộ.
|
|
866
|
+
* @param options.keys Đường dẫn của dữ liệu cần đồng bộ.
|
|
867
|
+
* @param options.value Giá trị mới cần ghi.
|
|
868
|
+
* @param options.compare Hàm so sánh tùy chỉnh. Nếu trả về `true` thì sẽ không thực hiện đồng bộ.
|
|
869
|
+
*
|
|
870
|
+
* @returns
|
|
871
|
+
* - `undefined` nếu không có thay đổi hoặc dữ liệu được tạo mới.
|
|
872
|
+
* - `Partial<ObjectValue<V, P>>` chứa các trường đã thay đổi khi cập nhật Object.
|
|
873
|
+
*/
|
|
874
|
+
async syncDatabase({ keys, value, compare }) {
|
|
875
|
+
const oldValue = await this.get(keys);
|
|
876
|
+
if (oldValue === void 0 || oldValue === null) {
|
|
877
|
+
await this.set(keys, value);
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
if (compare?.(oldValue, value)) return;
|
|
881
|
+
if (!isObject(oldValue) || !isObject(value) || Array.isArray(oldValue) || Array.isArray(value)) {
|
|
882
|
+
if (!Object.is(oldValue, value)) {
|
|
883
|
+
await this.update(keys, value);
|
|
884
|
+
}
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
const changed = {};
|
|
888
|
+
for (const k in value) {
|
|
889
|
+
const field = k;
|
|
890
|
+
if (!Object.is(oldValue[field], value[field])) {
|
|
891
|
+
changed[field] = value[field];
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
if (Object.keys(changed).length === 0) return;
|
|
895
|
+
await this.update(keys, changed);
|
|
896
|
+
return changed;
|
|
897
|
+
}
|
|
605
898
|
/**
|
|
606
899
|
* Cộng thêm giá trị vào một key dạng number.
|
|
607
900
|
*
|
|
@@ -664,6 +957,46 @@ var Database = class {
|
|
|
664
957
|
await this.set(key, targetNumber - numberToSubtract);
|
|
665
958
|
return targetNumber - numberToSubtract;
|
|
666
959
|
}
|
|
960
|
+
/**
|
|
961
|
+
* Thêm một hoặc nhiều phần tử vào đầu array.
|
|
962
|
+
*
|
|
963
|
+
* Chỉ thêm những phần tử chưa tồn tại trong array.
|
|
964
|
+
*
|
|
965
|
+
* @typeParam P - Path trỏ tới array.
|
|
966
|
+
*
|
|
967
|
+
* @param key - Đường dẫn array.
|
|
968
|
+
* @param values - Một hoặc nhiều phần tử cần thêm.
|
|
969
|
+
*
|
|
970
|
+
* @returns Array sau khi thêm.
|
|
971
|
+
*
|
|
972
|
+
* @example
|
|
973
|
+
* await db.unshift("users", newUser);
|
|
974
|
+
*/
|
|
975
|
+
async unshift(key, ...values) {
|
|
976
|
+
if (!values.length) {
|
|
977
|
+
throw new BlackCatError("REQUIRED_PARAMETER_MISSING", "values");
|
|
978
|
+
}
|
|
979
|
+
const root = await this.all();
|
|
980
|
+
const pathParts = key.split(".");
|
|
981
|
+
let target = root;
|
|
982
|
+
for (let i = 0; i < pathParts.length; i++) {
|
|
983
|
+
const part = pathParts[i];
|
|
984
|
+
if (!(part in target)) {
|
|
985
|
+
throw new BlackCatError("INVALID_KEY", key);
|
|
986
|
+
}
|
|
987
|
+
if (i === pathParts.length - 1) {
|
|
988
|
+
if (!Array.isArray(target[part])) {
|
|
989
|
+
throw new BlackCatError("INVALID_TARGET", "array", typeOf(target[part]));
|
|
990
|
+
}
|
|
991
|
+
const uniqueValues = values.filter((v) => !target[part].includes(v));
|
|
992
|
+
target[part].unshift(...uniqueValues);
|
|
993
|
+
} else {
|
|
994
|
+
target = target[part];
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
await this.set(pathParts[0], root[pathParts[0]]);
|
|
998
|
+
return target[pathParts[pathParts.length - 1]];
|
|
999
|
+
}
|
|
667
1000
|
/**
|
|
668
1001
|
* Thêm một hoặc nhiều phần tử vào cuối array tại key-path.
|
|
669
1002
|
*
|