emberflow 1.4.30 → 1.4.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/lib/index-utils.d.ts +12 -10
- package/lib/index-utils.js +92 -25
- package/lib/index-utils.js.map +1 -1
- package/lib/index.d.ts +10 -7
- package/lib/index.js +59 -60
- package/lib/index.js.map +1 -1
- package/lib/init-db-structure.js +24 -32
- package/lib/init-db-structure.js.map +1 -1
- package/lib/logics/patch-logics.d.ts +9 -0
- package/lib/logics/patch-logics.js +126 -0
- package/lib/logics/patch-logics.js.map +1 -0
- package/lib/logics/view-logics.d.ts +1 -1
- package/lib/logics/view-logics.js +6 -5
- package/lib/logics/view-logics.js.map +1 -1
- package/lib/sample-custom/business-logics.js +1 -0
- package/lib/sample-custom/business-logics.js.map +1 -1
- package/lib/sample-custom/patch-logics.d.ts +2 -0
- package/lib/sample-custom/patch-logics.js +57 -0
- package/lib/sample-custom/patch-logics.js.map +1 -0
- package/lib/sample-custom/security.d.ts +1 -1
- package/lib/sample-custom/security.js +18 -7
- package/lib/sample-custom/security.js.map +1 -1
- package/lib/sample-custom/validators.d.ts +1 -2
- package/lib/sample-custom/validators.js +28 -7
- package/lib/sample-custom/validators.js.map +1 -1
- package/lib/tests/index-utils.test.js +312 -70
- package/lib/tests/index-utils.test.js.map +1 -1
- package/lib/tests/index.test.js +109 -55
- package/lib/tests/index.test.js.map +1 -1
- package/lib/tests/init-db-structure.test.js +32 -16
- package/lib/tests/init-db-structure.test.js.map +1 -1
- package/lib/tests/logics/patch-logis.test.d.ts +1 -0
- package/lib/tests/logics/patch-logis.test.js +347 -0
- package/lib/tests/logics/patch-logis.test.js.map +1 -0
- package/lib/tests/logics/view-logics.test.js +18 -5
- package/lib/tests/logics/view-logics.test.js.map +1 -1
- package/lib/tests/utils/db-structure.test.js +23 -25
- package/lib/tests/utils/db-structure.test.js.map +1 -1
- package/lib/tests/utils/distribution.test.js +28 -10
- package/lib/tests/utils/distribution.test.js.map +1 -1
- package/lib/tests/utils/forms.test.js +4 -3
- package/lib/tests/utils/forms.test.js.map +1 -1
- package/lib/tests/utils/misc.test.js +2 -1
- package/lib/tests/utils/misc.test.js.map +1 -1
- package/lib/tests/utils/paths.test.js +1 -1
- package/lib/tests/utils/paths.test.js.map +1 -1
- package/lib/tests/utils/pubsub.test.js +1 -1
- package/lib/tests/utils/pubsub.test.js.map +1 -1
- package/lib/types.d.ts +21 -2
- package/lib/utils/db-structure.d.ts +4 -2
- package/lib/utils/db-structure.js +14 -4
- package/lib/utils/db-structure.js.map +1 -1
- package/lib/utils/distribution.d.ts +1 -1
- package/lib/utils/distribution.js +9 -6
- package/lib/utils/distribution.js.map +1 -1
- package/lib/utils/forms.js +3 -1
- package/lib/utils/forms.js.map +1 -1
- package/lib/utils/misc.d.ts +0 -3
- package/lib/utils/misc.js +1 -48
- package/lib/utils/misc.js.map +1 -1
- package/package.json +2 -2
- package/src/sample-custom/business-logics.ts +1 -0
- package/src/sample-custom/patch-logics.ts +36 -0
- package/src/sample-custom/security.ts +17 -6
- package/src/sample-custom/validators.ts +27 -6
|
@@ -38,6 +38,7 @@ const forms = __importStar(require("../utils/forms"));
|
|
|
38
38
|
const misc = __importStar(require("../utils/misc"));
|
|
39
39
|
const index_utils_1 = require("../index-utils");
|
|
40
40
|
const viewLogics = __importStar(require("../logics/view-logics"));
|
|
41
|
+
const patch_logics_1 = require("../sample-custom/patch-logics");
|
|
41
42
|
// should mock when using initializeEmberFlow and testing db.doc() calls count
|
|
42
43
|
jest.spyOn(indexUtils, "createMetricLogicDoc").mockResolvedValue();
|
|
43
44
|
jest.spyOn(console, "log").mockImplementation();
|
|
@@ -479,7 +480,7 @@ describe("distribute", () => {
|
|
|
479
480
|
dstPath: "/users/test-user-id/documents/test-doc-id",
|
|
480
481
|
}],
|
|
481
482
|
]]);
|
|
482
|
-
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.
|
|
483
|
+
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfigs, validators_1.validatorConfigs, [], patch_logics_1.patchLogicConfigs);
|
|
483
484
|
await indexUtils.distributeFnNonTransactional(userDocsByDstPath);
|
|
484
485
|
expect(admin.firestore().doc).toHaveBeenCalledTimes(1);
|
|
485
486
|
expect(admin.firestore().doc).toHaveBeenCalledWith("/users/test-user-id/documents/test-doc-id");
|
|
@@ -516,7 +517,7 @@ describe("distribute", () => {
|
|
|
516
517
|
describe("distributeLater", () => {
|
|
517
518
|
let queueForDistributionLaterSpy;
|
|
518
519
|
beforeEach(() => {
|
|
519
|
-
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.
|
|
520
|
+
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfigs, validators_1.validatorConfigs, [], patch_logics_1.patchLogicConfigs);
|
|
520
521
|
queueForDistributionLaterSpy = jest.spyOn(distribution, "queueForDistributionLater").mockResolvedValue();
|
|
521
522
|
});
|
|
522
523
|
afterEach(() => {
|
|
@@ -539,38 +540,128 @@ describe("distributeLater", () => {
|
|
|
539
540
|
["/users/test-user-id/documents/doc1", [doc1]],
|
|
540
541
|
["/users/test-user-id/documents/doc2", [doc2]],
|
|
541
542
|
]);
|
|
542
|
-
|
|
543
|
+
const targetVersion = "1.0.0";
|
|
544
|
+
await indexUtils.distributeLater(usersDocsByDstPath, targetVersion);
|
|
543
545
|
expect(queueForDistributionLaterSpy).toHaveBeenCalledTimes(1);
|
|
544
|
-
expect(queueForDistributionLaterSpy).toHaveBeenCalledWith(doc1, doc2);
|
|
546
|
+
expect(queueForDistributionLaterSpy).toHaveBeenCalledWith(targetVersion, doc1, doc2);
|
|
545
547
|
});
|
|
546
548
|
});
|
|
547
549
|
describe("validateForm", () => {
|
|
548
550
|
beforeEach(() => {
|
|
549
|
-
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.
|
|
551
|
+
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfigs, validators_1.validatorConfigs, [], patch_logics_1.patchLogicConfigs);
|
|
552
|
+
});
|
|
553
|
+
const targetVersion = "2.5";
|
|
554
|
+
const entity = "user";
|
|
555
|
+
it("should call the appropriate version of validator", async () => {
|
|
556
|
+
const userValidation = jest.fn().mockResolvedValue({});
|
|
557
|
+
const userValidationV2 = jest.fn().mockResolvedValue({});
|
|
558
|
+
const userValidationV3 = jest.fn().mockResolvedValue({});
|
|
559
|
+
const feedValidation = jest.fn().mockResolvedValue({});
|
|
560
|
+
const feedValidationV2 = jest.fn().mockResolvedValue({});
|
|
561
|
+
const validatorConfigs = [
|
|
562
|
+
{
|
|
563
|
+
entity: db_structure_1.Entity.User,
|
|
564
|
+
validatorFn: userValidation,
|
|
565
|
+
version: "01",
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
entity: db_structure_1.Entity.User,
|
|
569
|
+
validatorFn: userValidationV2,
|
|
570
|
+
version: "02.04.06",
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
entity: db_structure_1.Entity.User,
|
|
574
|
+
validatorFn: userValidationV3,
|
|
575
|
+
version: "03",
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
entity: db_structure_1.Entity.Feed,
|
|
579
|
+
validatorFn: feedValidation,
|
|
580
|
+
version: "01",
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
entity: db_structure_1.Entity.Feed,
|
|
584
|
+
validatorFn: feedValidationV2,
|
|
585
|
+
version: "02.04.06",
|
|
586
|
+
},
|
|
587
|
+
];
|
|
588
|
+
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfigs, validatorConfigs, [], patch_logics_1.patchLogicConfigs);
|
|
589
|
+
const document = {
|
|
590
|
+
name: "John Doe",
|
|
591
|
+
email: "johndoe@example.com",
|
|
592
|
+
password: "abc123",
|
|
593
|
+
};
|
|
594
|
+
await indexUtils.validateForm(entity, document, targetVersion);
|
|
595
|
+
expect(userValidation).not.toHaveBeenCalled();
|
|
596
|
+
expect(userValidationV2).toHaveBeenCalledTimes(1);
|
|
597
|
+
expect(userValidationV3).not.toHaveBeenCalled();
|
|
598
|
+
expect(feedValidation).not.toHaveBeenCalled();
|
|
599
|
+
expect(feedValidationV2).not.toHaveBeenCalled();
|
|
550
600
|
});
|
|
551
601
|
it("returns an object with empty validationResult when document is valid", async () => {
|
|
552
|
-
const entity = "user";
|
|
553
602
|
const document = {
|
|
554
603
|
name: "John Doe",
|
|
555
604
|
email: "johndoe@example.com",
|
|
556
605
|
password: "abc123",
|
|
557
606
|
};
|
|
558
|
-
const [hasValidationError, validationResult] = await indexUtils.validateForm(entity, document);
|
|
607
|
+
const [hasValidationError, validationResult] = await indexUtils.validateForm(entity, document, targetVersion);
|
|
559
608
|
expect(hasValidationError).toBe(false);
|
|
560
609
|
expect(validationResult).toEqual({});
|
|
561
610
|
});
|
|
562
611
|
it("returns an object with validation errors when document is invalid", async () => {
|
|
563
|
-
const entity = "user";
|
|
564
612
|
const document = {
|
|
565
613
|
name: "",
|
|
566
614
|
email: "johndoe@example.com",
|
|
567
615
|
password: "abc",
|
|
568
616
|
};
|
|
569
|
-
const [hasValidationError, validationResult] = await indexUtils.validateForm(entity, document);
|
|
617
|
+
const [hasValidationError, validationResult] = await indexUtils.validateForm(entity, document, targetVersion);
|
|
570
618
|
expect(hasValidationError).toBe(true);
|
|
571
619
|
expect(validationResult).toEqual({ name: ["Name is required"] });
|
|
572
620
|
});
|
|
573
621
|
});
|
|
622
|
+
describe("getSecurityFn", () => {
|
|
623
|
+
it("should return the appropriate version of security function", async () => {
|
|
624
|
+
const userSecurityFn = jest.fn().mockResolvedValue({});
|
|
625
|
+
const userSecurityFnV2 = jest.fn().mockResolvedValue({
|
|
626
|
+
status: "allowed",
|
|
627
|
+
});
|
|
628
|
+
const userSecurityFnV3 = jest.fn().mockResolvedValue({});
|
|
629
|
+
const feedSecurityFn = jest.fn().mockResolvedValue({});
|
|
630
|
+
const feedSecurityFnV2 = jest.fn().mockResolvedValue({});
|
|
631
|
+
const targetVersion = "2.5";
|
|
632
|
+
const entity = "user";
|
|
633
|
+
const securityConfigs = [
|
|
634
|
+
{
|
|
635
|
+
entity: db_structure_1.Entity.User,
|
|
636
|
+
securityFn: userSecurityFn,
|
|
637
|
+
version: "01",
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
entity: db_structure_1.Entity.User,
|
|
641
|
+
securityFn: userSecurityFnV2,
|
|
642
|
+
version: "02.04.06",
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
entity: db_structure_1.Entity.User,
|
|
646
|
+
securityFn: userSecurityFnV3,
|
|
647
|
+
version: "03",
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
entity: db_structure_1.Entity.Feed,
|
|
651
|
+
securityFn: feedSecurityFn,
|
|
652
|
+
version: "01",
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
entity: db_structure_1.Entity.Feed,
|
|
656
|
+
securityFn: feedSecurityFnV2,
|
|
657
|
+
version: "02.04.06",
|
|
658
|
+
},
|
|
659
|
+
];
|
|
660
|
+
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, securityConfigs, validators_1.validatorConfigs, [], patch_logics_1.patchLogicConfigs);
|
|
661
|
+
const result = await indexUtils.getSecurityFn(entity, targetVersion);
|
|
662
|
+
expect(result).toEqual(userSecurityFnV2);
|
|
663
|
+
});
|
|
664
|
+
});
|
|
574
665
|
describe("getFormModifiedFields", () => {
|
|
575
666
|
it("should return an empty object when there are no form fields", () => {
|
|
576
667
|
const document = { name: "John Doe", age: 30 };
|
|
@@ -622,6 +713,34 @@ describe("delayFormSubmissionAndCheckIfCancelled", () => {
|
|
|
622
713
|
expect(formResponseRef.get).toHaveBeenCalledWith();
|
|
623
714
|
});
|
|
624
715
|
});
|
|
716
|
+
describe("groupDocsByTargetDocPath", () => {
|
|
717
|
+
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, [], [], [], []);
|
|
718
|
+
const docsByDstPath = new Map([
|
|
719
|
+
["users/user123/document1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1", doc: { field1: "value1", field2: "value2" } }]],
|
|
720
|
+
["users/user123/document1/threads/thread1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1/threads/thread1", doc: { field3: "value3", field6: "value6" } }]],
|
|
721
|
+
["users/user123/document1/messages/message1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1/messages/message1", doc: { field4: "value4" } }]],
|
|
722
|
+
["users/user123/document1/images/image1", [{ action: "merge", priority: "low", dstPath: "users/user123/document1/images/image1", doc: { field7: "value7" } }]],
|
|
723
|
+
["othercollection/document2", [{ action: "merge", priority: "normal", dstPath: "othercollection/document2", doc: { field5: "value5" } }]],
|
|
724
|
+
["othercollection/document3", [{ action: "delete", priority: "normal", dstPath: "othercollection/document3" }]],
|
|
725
|
+
]);
|
|
726
|
+
it("should group documents by docPath", () => {
|
|
727
|
+
const docPath = "users/user123/document1";
|
|
728
|
+
const expectedResults = {
|
|
729
|
+
docsByDocPath: new Map([
|
|
730
|
+
["users/user123/document1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1", doc: { field1: "value1", field2: "value2" } }]],
|
|
731
|
+
["users/user123/document1/threads/thread1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1/threads/thread1", doc: { field3: "value3", field6: "value6" } }]],
|
|
732
|
+
["users/user123/document1/messages/message1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1/messages/message1", doc: { field4: "value4" } }]],
|
|
733
|
+
["users/user123/document1/images/image1", [{ action: "merge", priority: "low", dstPath: "users/user123/document1/images/image1", doc: { field7: "value7" } }]],
|
|
734
|
+
]),
|
|
735
|
+
otherDocsByDocPath: new Map([
|
|
736
|
+
["othercollection/document2", [{ action: "merge", priority: "normal", dstPath: "othercollection/document2", doc: { field5: "value5" } }]],
|
|
737
|
+
["othercollection/document3", [{ action: "delete", priority: "normal", dstPath: "othercollection/document3" }]],
|
|
738
|
+
]),
|
|
739
|
+
};
|
|
740
|
+
const results = indexUtils.groupDocsByTargetDocPath(docsByDstPath, docPath);
|
|
741
|
+
expect(results).toEqual(expectedResults);
|
|
742
|
+
});
|
|
743
|
+
});
|
|
625
744
|
describe("runBusinessLogics", () => {
|
|
626
745
|
const actionType = "create";
|
|
627
746
|
const formModifiedFields = { field1: "value1", field2: "value2" };
|
|
@@ -630,7 +749,6 @@ describe("runBusinessLogics", () => {
|
|
|
630
749
|
id: "user123",
|
|
631
750
|
name: "John Doe",
|
|
632
751
|
};
|
|
633
|
-
const metadata = { version: "1.0" };
|
|
634
752
|
const action = {
|
|
635
753
|
user,
|
|
636
754
|
eventContext: {
|
|
@@ -650,7 +768,8 @@ describe("runBusinessLogics", () => {
|
|
|
650
768
|
status: "processing",
|
|
651
769
|
timeCreated: firebase_admin_1.firestore.Timestamp.now(),
|
|
652
770
|
modifiedFields: formModifiedFields,
|
|
653
|
-
metadata,
|
|
771
|
+
metadata: {},
|
|
772
|
+
appVersion: "1.0.0",
|
|
654
773
|
};
|
|
655
774
|
let distributeFn;
|
|
656
775
|
let logicFn1;
|
|
@@ -699,7 +818,7 @@ describe("runBusinessLogics", () => {
|
|
|
699
818
|
distributeFn.mockRestore();
|
|
700
819
|
dbSpy.mockRestore();
|
|
701
820
|
});
|
|
702
|
-
it("should call all matching logics
|
|
821
|
+
it("should call all matching logics then pass their results to distributeFn", async () => {
|
|
703
822
|
const logics = [
|
|
704
823
|
{
|
|
705
824
|
name: "Logic 1",
|
|
@@ -707,6 +826,7 @@ describe("runBusinessLogics", () => {
|
|
|
707
826
|
modifiedFields: ["field1"],
|
|
708
827
|
entities: ["user"],
|
|
709
828
|
logicFn: logicFn1,
|
|
829
|
+
version: "1",
|
|
710
830
|
},
|
|
711
831
|
{
|
|
712
832
|
name: "Logic 2",
|
|
@@ -714,6 +834,7 @@ describe("runBusinessLogics", () => {
|
|
|
714
834
|
modifiedFields: ["field2"],
|
|
715
835
|
entities: ["user"],
|
|
716
836
|
logicFn: logicFn2,
|
|
837
|
+
version: "1",
|
|
717
838
|
},
|
|
718
839
|
{
|
|
719
840
|
name: "Logic 3",
|
|
@@ -721,57 +842,173 @@ describe("runBusinessLogics", () => {
|
|
|
721
842
|
modifiedFields: ["field3"],
|
|
722
843
|
entities: ["user"],
|
|
723
844
|
logicFn: logicFn3,
|
|
845
|
+
version: "1",
|
|
724
846
|
},
|
|
847
|
+
];
|
|
848
|
+
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfigs, validators_1.validatorConfigs, logics, patch_logics_1.patchLogicConfigs);
|
|
849
|
+
const runStatus = await indexUtils.runBusinessLogics(txnGet, action, "2");
|
|
850
|
+
expect(logicFn1).toHaveBeenCalledWith(txnGet, action, new Map());
|
|
851
|
+
expect(logicFn2).toHaveBeenCalledWith(txnGet, action, new Map());
|
|
852
|
+
expect(logicFn3).not.toHaveBeenCalled();
|
|
853
|
+
expect(runStatus).toEqual({
|
|
854
|
+
status: "done",
|
|
855
|
+
logicResults: [{
|
|
856
|
+
status: "finished",
|
|
857
|
+
execTime: expect.any(Number),
|
|
858
|
+
timeFinished: expect.any(Timestamp),
|
|
859
|
+
}, {
|
|
860
|
+
status: "finished",
|
|
861
|
+
execTime: expect.any(Number),
|
|
862
|
+
timeFinished: expect.any(Timestamp),
|
|
863
|
+
}],
|
|
864
|
+
});
|
|
865
|
+
});
|
|
866
|
+
it("should call all matching logics with passing addtnlFilters then pass their results " +
|
|
867
|
+
"to distributeFn", async () => {
|
|
868
|
+
const logics = [
|
|
725
869
|
{
|
|
726
870
|
name: "Logic 4",
|
|
727
871
|
actionTypes: ["create"],
|
|
728
|
-
modifiedFields: ["
|
|
872
|
+
modifiedFields: ["shouldRun"],
|
|
729
873
|
entities: ["user"],
|
|
730
874
|
logicFn: logicFn4,
|
|
731
|
-
addtlFilterFn(
|
|
732
|
-
return
|
|
875
|
+
addtlFilterFn(_, modifiedFields) {
|
|
876
|
+
return modifiedFields.shouldRun;
|
|
733
877
|
},
|
|
878
|
+
version: "1",
|
|
734
879
|
},
|
|
735
880
|
{
|
|
736
881
|
name: "Logic 5",
|
|
737
882
|
actionTypes: ["create"],
|
|
738
|
-
modifiedFields: ["
|
|
883
|
+
modifiedFields: ["shouldRun"],
|
|
739
884
|
entities: ["user"],
|
|
740
885
|
logicFn: logicFn5,
|
|
741
|
-
addtlFilterFn(
|
|
742
|
-
return !
|
|
886
|
+
addtlFilterFn(_, modifiedFields) {
|
|
887
|
+
return !modifiedFields.shouldRun;
|
|
743
888
|
},
|
|
889
|
+
version: "1",
|
|
744
890
|
},
|
|
745
891
|
{
|
|
746
892
|
name: "Logic 6",
|
|
747
|
-
actionTypes: ["
|
|
748
|
-
modifiedFields: ["
|
|
893
|
+
actionTypes: ["update"],
|
|
894
|
+
modifiedFields: ["shouldRun"],
|
|
749
895
|
entities: ["user"],
|
|
750
896
|
logicFn: logicFn6,
|
|
751
|
-
addtlFilterFn(
|
|
752
|
-
return
|
|
897
|
+
addtlFilterFn(_, modifiedFields) {
|
|
898
|
+
return modifiedFields.shouldRun;
|
|
753
899
|
},
|
|
900
|
+
version: "1",
|
|
754
901
|
},
|
|
755
902
|
{
|
|
756
903
|
name: "Logic 7",
|
|
757
904
|
actionTypes: ["create"],
|
|
758
|
-
modifiedFields: ["
|
|
905
|
+
modifiedFields: ["all"],
|
|
759
906
|
entities: ["user"],
|
|
760
907
|
logicFn: logicFn7,
|
|
761
908
|
addtlFilterFn(actionType, modifiedFields, document, entity, metadata) {
|
|
762
909
|
return metadata.version === "2.0";
|
|
763
910
|
},
|
|
911
|
+
version: "1",
|
|
764
912
|
},
|
|
765
913
|
];
|
|
766
|
-
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.
|
|
767
|
-
const
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
expect(logicFn4).
|
|
914
|
+
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfigs, validators_1.validatorConfigs, logics, []);
|
|
915
|
+
const newAction = Object.assign(Object.assign({}, action), { modifiedFields: {
|
|
916
|
+
shouldRun: true,
|
|
917
|
+
} });
|
|
918
|
+
const runStatus = await indexUtils.runBusinessLogics(txnGet, newAction, "1");
|
|
919
|
+
expect(logicFn4).toHaveBeenCalledWith(txnGet, newAction, new Map());
|
|
772
920
|
expect(logicFn5).not.toHaveBeenCalled();
|
|
773
921
|
expect(logicFn6).not.toHaveBeenCalled();
|
|
774
922
|
expect(logicFn7).not.toHaveBeenCalled();
|
|
923
|
+
expect(runStatus).toEqual({
|
|
924
|
+
status: "done",
|
|
925
|
+
logicResults: [{
|
|
926
|
+
status: "finished",
|
|
927
|
+
execTime: expect.any(Number),
|
|
928
|
+
timeFinished: expect.any(Timestamp),
|
|
929
|
+
}],
|
|
930
|
+
});
|
|
931
|
+
});
|
|
932
|
+
it("should call all matching logics nearest to the target version then pass their results " +
|
|
933
|
+
"to distributeFn", async () => {
|
|
934
|
+
const logicFn1 = jest.fn().mockResolvedValue({ status: "finished" });
|
|
935
|
+
const logicFn1V2 = jest.fn().mockResolvedValue({ status: "finished" });
|
|
936
|
+
const logicFn1V3 = jest.fn().mockResolvedValue({ status: "finished" });
|
|
937
|
+
const logicFn2 = jest.fn().mockResolvedValue({ status: "finished" });
|
|
938
|
+
const logicFn2V2 = jest.fn().mockResolvedValue({ status: "finished" });
|
|
939
|
+
const logicFn3 = jest.fn().mockResolvedValue({ status: "finished" });
|
|
940
|
+
const logicFn3V2 = jest.fn().mockResolvedValue({ status: "error", message: "Error message" });
|
|
941
|
+
const logics = [
|
|
942
|
+
{
|
|
943
|
+
name: "Logic1",
|
|
944
|
+
actionTypes: ["create"],
|
|
945
|
+
modifiedFields: "all",
|
|
946
|
+
entities: ["user"],
|
|
947
|
+
logicFn: logicFn1,
|
|
948
|
+
version: "1.2.3",
|
|
949
|
+
},
|
|
950
|
+
{
|
|
951
|
+
name: "Logic1",
|
|
952
|
+
actionTypes: ["create"],
|
|
953
|
+
modifiedFields: "all",
|
|
954
|
+
entities: ["user"],
|
|
955
|
+
logicFn: logicFn1V2,
|
|
956
|
+
version: "2.4.6",
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
name: "Logic1",
|
|
960
|
+
actionTypes: ["update"],
|
|
961
|
+
modifiedFields: "all",
|
|
962
|
+
entities: ["user"],
|
|
963
|
+
logicFn: logicFn1V3,
|
|
964
|
+
version: "3.0.0",
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
name: "Logic2",
|
|
968
|
+
actionTypes: ["create"],
|
|
969
|
+
modifiedFields: ["field1"],
|
|
970
|
+
entities: ["user"],
|
|
971
|
+
logicFn: logicFn2,
|
|
972
|
+
version: "1.2.3",
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
name: "Logic2",
|
|
976
|
+
actionTypes: ["create"],
|
|
977
|
+
modifiedFields: ["field1"],
|
|
978
|
+
entities: ["user"],
|
|
979
|
+
logicFn: logicFn2V2,
|
|
980
|
+
version: "2.4.6",
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
name: "Logic3",
|
|
984
|
+
actionTypes: ["update"],
|
|
985
|
+
modifiedFields: ["field2"],
|
|
986
|
+
entities: ["user"],
|
|
987
|
+
logicFn: logicFn3,
|
|
988
|
+
version: "1.2.3",
|
|
989
|
+
},
|
|
990
|
+
{
|
|
991
|
+
name: "Logic3",
|
|
992
|
+
actionTypes: ["update"],
|
|
993
|
+
modifiedFields: ["field2"],
|
|
994
|
+
entities: ["user"],
|
|
995
|
+
logicFn: logicFn3V2,
|
|
996
|
+
version: "2.4.6",
|
|
997
|
+
},
|
|
998
|
+
];
|
|
999
|
+
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfigs, validators_1.validatorConfigs, logics, []);
|
|
1000
|
+
const newAction = Object.assign(Object.assign({}, action), { modifiedFields: {
|
|
1001
|
+
field1: true,
|
|
1002
|
+
} });
|
|
1003
|
+
const targetVersion = "2.5";
|
|
1004
|
+
const runStatus = await indexUtils.runBusinessLogics(txnGet, newAction, targetVersion);
|
|
1005
|
+
expect(logicFn1).not.toHaveBeenCalled();
|
|
1006
|
+
expect(logicFn1V2).toHaveBeenCalledWith(txnGet, newAction, new Map());
|
|
1007
|
+
expect(logicFn1V3).not.toHaveBeenCalled();
|
|
1008
|
+
expect(logicFn2).not.toHaveBeenCalled();
|
|
1009
|
+
expect(logicFn2V2).toHaveBeenCalledWith(txnGet, newAction, new Map());
|
|
1010
|
+
expect(logicFn3).not.toHaveBeenCalled();
|
|
1011
|
+
expect(logicFn3V2).not.toHaveBeenCalled();
|
|
775
1012
|
expect(runStatus).toEqual({
|
|
776
1013
|
status: "done",
|
|
777
1014
|
logicResults: [{
|
|
@@ -794,6 +1031,7 @@ describe("runBusinessLogics", () => {
|
|
|
794
1031
|
modifiedFields: ["field1"],
|
|
795
1032
|
entities: ["customentity"],
|
|
796
1033
|
logicFn: logicFn1,
|
|
1034
|
+
version: "1",
|
|
797
1035
|
},
|
|
798
1036
|
{
|
|
799
1037
|
name: "Logic 2",
|
|
@@ -801,6 +1039,7 @@ describe("runBusinessLogics", () => {
|
|
|
801
1039
|
modifiedFields: ["field2"],
|
|
802
1040
|
entities: ["customentity"],
|
|
803
1041
|
logicFn: logicFn2,
|
|
1042
|
+
version: "1",
|
|
804
1043
|
},
|
|
805
1044
|
{
|
|
806
1045
|
name: "Logic 3",
|
|
@@ -808,10 +1047,11 @@ describe("runBusinessLogics", () => {
|
|
|
808
1047
|
modifiedFields: ["field3"],
|
|
809
1048
|
entities: ["customentity"],
|
|
810
1049
|
logicFn: logicFn3,
|
|
1050
|
+
version: "1",
|
|
811
1051
|
},
|
|
812
1052
|
];
|
|
813
|
-
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.
|
|
814
|
-
const runStatus = await indexUtils.runBusinessLogics(txnGet, action);
|
|
1053
|
+
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfigs, validators_1.validatorConfigs, logics, []);
|
|
1054
|
+
const runStatus = await indexUtils.runBusinessLogics(txnGet, action, "1");
|
|
815
1055
|
expect(logicFn1).not.toHaveBeenCalled();
|
|
816
1056
|
expect(logicFn2).not.toHaveBeenCalled();
|
|
817
1057
|
expect(logicFn3).not.toHaveBeenCalled();
|
|
@@ -845,6 +1085,7 @@ describe("runBusinessLogics", () => {
|
|
|
845
1085
|
modifiedFields: ["field1"],
|
|
846
1086
|
entities: ["user"],
|
|
847
1087
|
logicFn: logicFn1,
|
|
1088
|
+
version: "1",
|
|
848
1089
|
},
|
|
849
1090
|
{
|
|
850
1091
|
name: "Logic 2",
|
|
@@ -852,6 +1093,7 @@ describe("runBusinessLogics", () => {
|
|
|
852
1093
|
modifiedFields: ["field2"],
|
|
853
1094
|
entities: ["user"],
|
|
854
1095
|
logicFn: logicFn2,
|
|
1096
|
+
version: "1",
|
|
855
1097
|
},
|
|
856
1098
|
{
|
|
857
1099
|
name: "Logic 3",
|
|
@@ -859,10 +1101,11 @@ describe("runBusinessLogics", () => {
|
|
|
859
1101
|
modifiedFields: ["field2"],
|
|
860
1102
|
entities: ["user"],
|
|
861
1103
|
logicFn: logicFn3,
|
|
1104
|
+
version: "1",
|
|
862
1105
|
},
|
|
863
1106
|
];
|
|
864
|
-
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.
|
|
865
|
-
const runStatus = await indexUtils.runBusinessLogics(txnGet, action);
|
|
1107
|
+
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, security_1.securityConfigs, validators_1.validatorConfigs, logics, []);
|
|
1108
|
+
const runStatus = await indexUtils.runBusinessLogics(txnGet, action, "1");
|
|
866
1109
|
expect(logicFn1).toHaveBeenCalledWith(txnGet, action, expectedSharedMap);
|
|
867
1110
|
expect(logicFn2).toHaveBeenCalledWith(txnGet, action, expectedSharedMap);
|
|
868
1111
|
expect(logicFn3).toHaveBeenCalledWith(txnGet, action, expectedSharedMap);
|
|
@@ -874,34 +1117,6 @@ describe("runBusinessLogics", () => {
|
|
|
874
1117
|
expect(logicResults[2].status).toEqual("finished");
|
|
875
1118
|
});
|
|
876
1119
|
});
|
|
877
|
-
describe("groupDocsByTargetDocPath", () => {
|
|
878
|
-
(0, index_1.initializeEmberFlow)(projectConfig, admin, db_structure_1.dbStructure, db_structure_1.Entity, {}, {}, []);
|
|
879
|
-
const docsByDstPath = new Map([
|
|
880
|
-
["users/user123/document1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1", doc: { field1: "value1", field2: "value2" } }]],
|
|
881
|
-
["users/user123/document1/threads/thread1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1/threads/thread1", doc: { field3: "value3", field6: "value6" } }]],
|
|
882
|
-
["users/user123/document1/messages/message1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1/messages/message1", doc: { field4: "value4" } }]],
|
|
883
|
-
["users/user123/document1/images/image1", [{ action: "merge", priority: "low", dstPath: "users/user123/document1/images/image1", doc: { field7: "value7" } }]],
|
|
884
|
-
["othercollection/document2", [{ action: "merge", priority: "normal", dstPath: "othercollection/document2", doc: { field5: "value5" } }]],
|
|
885
|
-
["othercollection/document3", [{ action: "delete", priority: "normal", dstPath: "othercollection/document3" }]],
|
|
886
|
-
]);
|
|
887
|
-
it("should group documents by docPath", () => {
|
|
888
|
-
const docPath = "users/user123/document1";
|
|
889
|
-
const expectedResults = {
|
|
890
|
-
docsByDocPath: new Map([
|
|
891
|
-
["users/user123/document1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1", doc: { field1: "value1", field2: "value2" } }]],
|
|
892
|
-
["users/user123/document1/threads/thread1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1/threads/thread1", doc: { field3: "value3", field6: "value6" } }]],
|
|
893
|
-
["users/user123/document1/messages/message1", [{ action: "merge", priority: "normal", dstPath: "users/user123/document1/messages/message1", doc: { field4: "value4" } }]],
|
|
894
|
-
["users/user123/document1/images/image1", [{ action: "merge", priority: "low", dstPath: "users/user123/document1/images/image1", doc: { field7: "value7" } }]],
|
|
895
|
-
]),
|
|
896
|
-
otherDocsByDocPath: new Map([
|
|
897
|
-
["othercollection/document2", [{ action: "merge", priority: "normal", dstPath: "othercollection/document2", doc: { field5: "value5" } }]],
|
|
898
|
-
["othercollection/document3", [{ action: "delete", priority: "normal", dstPath: "othercollection/document3" }]],
|
|
899
|
-
]),
|
|
900
|
-
};
|
|
901
|
-
const results = indexUtils.groupDocsByTargetDocPath(docsByDstPath, docPath);
|
|
902
|
-
expect(results).toEqual(expectedResults);
|
|
903
|
-
});
|
|
904
|
-
});
|
|
905
1120
|
describe("expandConsolidateAndGroupByDstPath", () => {
|
|
906
1121
|
let dbSpy;
|
|
907
1122
|
let consoleWarnSpy;
|
|
@@ -1209,15 +1424,40 @@ describe("expandConsolidateAndGroupByDstPath", () => {
|
|
|
1209
1424
|
});
|
|
1210
1425
|
describe("runViewLogics", () => {
|
|
1211
1426
|
// Define mock functions
|
|
1212
|
-
const viewLogicFn1 = jest.fn();
|
|
1213
1427
|
const viewLogicFn2 = jest.fn();
|
|
1428
|
+
const viewLogicFn1V2Point5 = jest.fn();
|
|
1214
1429
|
const customViewLogicsConfig = [
|
|
1215
1430
|
{
|
|
1216
1431
|
name: "logic 1",
|
|
1217
1432
|
entity: "user",
|
|
1218
1433
|
actionTypes: ["merge", "delete"],
|
|
1219
1434
|
modifiedFields: ["sampleField1", "sampleField2"],
|
|
1220
|
-
viewLogicFn:
|
|
1435
|
+
viewLogicFn: jest.fn(),
|
|
1436
|
+
version: "1.0.0",
|
|
1437
|
+
},
|
|
1438
|
+
{
|
|
1439
|
+
name: "logic 1",
|
|
1440
|
+
entity: "user",
|
|
1441
|
+
actionTypes: ["merge", "delete"],
|
|
1442
|
+
modifiedFields: ["sampleField1", "sampleField2"],
|
|
1443
|
+
viewLogicFn: jest.fn(),
|
|
1444
|
+
version: "2.0.0",
|
|
1445
|
+
},
|
|
1446
|
+
{
|
|
1447
|
+
name: "logic 1",
|
|
1448
|
+
entity: "user",
|
|
1449
|
+
actionTypes: ["merge", "delete"],
|
|
1450
|
+
modifiedFields: ["sampleField1", "sampleField2"],
|
|
1451
|
+
viewLogicFn: viewLogicFn1V2Point5,
|
|
1452
|
+
version: "2.5.0",
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
name: "logic 1",
|
|
1456
|
+
entity: "user",
|
|
1457
|
+
actionTypes: ["merge", "delete"],
|
|
1458
|
+
modifiedFields: ["sampleField1", "sampleField2"],
|
|
1459
|
+
viewLogicFn: jest.fn(),
|
|
1460
|
+
version: "3.0.0",
|
|
1221
1461
|
},
|
|
1222
1462
|
{
|
|
1223
1463
|
name: "logic 2",
|
|
@@ -1225,12 +1465,14 @@ describe("runViewLogics", () => {
|
|
|
1225
1465
|
actionTypes: ["merge", "delete"],
|
|
1226
1466
|
modifiedFields: ["sampleField3"],
|
|
1227
1467
|
viewLogicFn: viewLogicFn2,
|
|
1468
|
+
version: "1.0.0",
|
|
1228
1469
|
},
|
|
1229
1470
|
];
|
|
1230
1471
|
beforeEach(() => {
|
|
1231
|
-
jest.spyOn(indexUtils._mockable, "
|
|
1472
|
+
jest.spyOn(indexUtils._mockable, "getViewLogicConfigs").mockReturnValue(customViewLogicsConfig);
|
|
1232
1473
|
});
|
|
1233
1474
|
it("should run view logics properly", async () => {
|
|
1475
|
+
const targetVersion = "2.9.0";
|
|
1234
1476
|
const logicResult1 = {
|
|
1235
1477
|
action: "merge",
|
|
1236
1478
|
priority: "normal",
|
|
@@ -1242,14 +1484,14 @@ describe("runViewLogics", () => {
|
|
|
1242
1484
|
priority: "normal",
|
|
1243
1485
|
dstPath: "users/user124",
|
|
1244
1486
|
};
|
|
1245
|
-
|
|
1487
|
+
viewLogicFn1V2Point5.mockResolvedValue({});
|
|
1246
1488
|
viewLogicFn2.mockResolvedValue({});
|
|
1247
|
-
const results1 = await indexUtils.runViewLogics(logicResult1);
|
|
1248
|
-
const results2 = await indexUtils.runViewLogics(logicResult2);
|
|
1489
|
+
const results1 = await indexUtils.runViewLogics(logicResult1, targetVersion);
|
|
1490
|
+
const results2 = await indexUtils.runViewLogics(logicResult2, targetVersion);
|
|
1249
1491
|
const results = [...results1, ...results2];
|
|
1250
|
-
expect(
|
|
1251
|
-
expect(
|
|
1252
|
-
expect(
|
|
1492
|
+
expect(viewLogicFn1V2Point5).toHaveBeenCalledTimes(2);
|
|
1493
|
+
expect(viewLogicFn1V2Point5.mock.calls[0][0]).toBe(logicResult1);
|
|
1494
|
+
expect(viewLogicFn1V2Point5.mock.calls[1][0]).toBe(logicResult2);
|
|
1253
1495
|
expect(viewLogicFn2).toHaveBeenCalledTimes(1);
|
|
1254
1496
|
expect(viewLogicFn2).toHaveBeenCalledWith(logicResult2);
|
|
1255
1497
|
expect(results).toHaveLength(3);
|