orchid-orm 1.3.0 → 1.3.3

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.
@@ -5,6 +5,7 @@ import {
5
5
  expectSql,
6
6
  profileData,
7
7
  userData,
8
+ useRelationCallback,
8
9
  useTestDatabase,
9
10
  } from '../test-utils/test-utils';
10
11
  import { User, Profile, Model } from '../test-utils/test-models';
@@ -414,6 +415,46 @@ describe('hasOne', () => {
414
415
  bio: 'profile 2',
415
416
  });
416
417
  });
418
+
419
+ describe('relation callbacks', () => {
420
+ const { beforeCreate, afterCreate, resetMocks } = useRelationCallback(
421
+ db.user.relations.profile,
422
+ );
423
+
424
+ it('should invoke callbacks', async () => {
425
+ await db.user.create({
426
+ ...userData,
427
+ profile: {
428
+ create: profileData,
429
+ },
430
+ });
431
+
432
+ expect(beforeCreate).toHaveBeenCalledTimes(1);
433
+ expect(afterCreate).toHaveBeenCalledTimes(1);
434
+ });
435
+
436
+ it('should invoke callbacks in a batch create', async () => {
437
+ resetMocks();
438
+
439
+ await db.user.createMany([
440
+ {
441
+ ...userData,
442
+ profile: {
443
+ create: profileData,
444
+ },
445
+ },
446
+ {
447
+ ...userData,
448
+ profile: {
449
+ create: profileData,
450
+ },
451
+ },
452
+ ]);
453
+
454
+ expect(beforeCreate).toHaveBeenCalledTimes(1);
455
+ expect(afterCreate).toHaveBeenCalledTimes(1);
456
+ });
457
+ });
417
458
  });
418
459
 
419
460
  describe('nested connect', () => {
@@ -502,6 +543,52 @@ describe('hasOne', () => {
502
543
  bio: 'profile 2',
503
544
  });
504
545
  });
546
+
547
+ describe('relation callbacks', () => {
548
+ const { beforeUpdate, afterUpdate, resetMocks } = useRelationCallback(
549
+ db.user.relations.profile,
550
+ );
551
+
552
+ it('should invoke callbacks', async () => {
553
+ const profileId = await db.profile.get('id').create(profileData);
554
+
555
+ await db.user.create({
556
+ ...userData,
557
+ profile: {
558
+ connect: { id: profileId },
559
+ },
560
+ });
561
+
562
+ expect(beforeUpdate).toHaveBeenCalledTimes(1);
563
+ expect(afterUpdate).toHaveBeenCalledTimes(1);
564
+ });
565
+
566
+ it('should invoke callbacks in a batch create', async () => {
567
+ resetMocks();
568
+
569
+ const ids = await db.profile
570
+ .pluck('id')
571
+ .createMany([profileData, profileData]);
572
+
573
+ await db.user.createMany([
574
+ {
575
+ ...userData,
576
+ profile: {
577
+ connect: { id: ids[0] },
578
+ },
579
+ },
580
+ {
581
+ ...userData,
582
+ profile: {
583
+ connect: { id: ids[1] },
584
+ },
585
+ },
586
+ ]);
587
+
588
+ expect(beforeUpdate).toHaveBeenCalledTimes(2);
589
+ expect(afterUpdate).toHaveBeenCalledTimes(2);
590
+ });
591
+ });
505
592
  });
506
593
 
507
594
  describe('connect or create', () => {
@@ -610,6 +697,80 @@ describe('hasOne', () => {
610
697
  });
611
698
  });
612
699
  });
700
+
701
+ describe('relation callbacks', () => {
702
+ const {
703
+ beforeUpdate,
704
+ afterUpdate,
705
+ beforeCreate,
706
+ afterCreate,
707
+ resetMocks,
708
+ } = useRelationCallback(db.user.relations.profile);
709
+
710
+ it('should invoke callbacks when connecting', async () => {
711
+ const id = await db.profile.get('id').create(profileData);
712
+
713
+ await db.user.create({
714
+ ...userData,
715
+ profile: {
716
+ connectOrCreate: {
717
+ where: { id },
718
+ create: profileData,
719
+ },
720
+ },
721
+ });
722
+
723
+ expect(beforeUpdate).toHaveBeenCalledTimes(1);
724
+ expect(afterUpdate).toHaveBeenCalledTimes(1);
725
+ });
726
+
727
+ it('should invoke callbacks when creating', async () => {
728
+ await db.user.create({
729
+ ...userData,
730
+ profile: {
731
+ connectOrCreate: {
732
+ where: { id: 0 },
733
+ create: profileData,
734
+ },
735
+ },
736
+ });
737
+
738
+ expect(beforeCreate).toHaveBeenCalledTimes(1);
739
+ expect(afterCreate).toHaveBeenCalledTimes(1);
740
+ });
741
+
742
+ it('should invoke callbacks in a batch create', async () => {
743
+ resetMocks();
744
+
745
+ const id = await db.profile.get('id').create(profileData);
746
+
747
+ await db.user.createMany([
748
+ {
749
+ ...userData,
750
+ profile: {
751
+ connectOrCreate: {
752
+ where: { id: 0 },
753
+ create: profileData,
754
+ },
755
+ },
756
+ },
757
+ {
758
+ ...userData,
759
+ profile: {
760
+ connectOrCreate: {
761
+ where: { id },
762
+ create: profileData,
763
+ },
764
+ },
765
+ },
766
+ ]);
767
+
768
+ expect(beforeUpdate).toHaveBeenCalledTimes(2);
769
+ expect(afterUpdate).toHaveBeenCalledTimes(2);
770
+ expect(beforeCreate).toHaveBeenCalledTimes(1);
771
+ expect(afterCreate).toHaveBeenCalledTimes(1);
772
+ });
773
+ });
613
774
  });
614
775
 
615
776
  describe('update', () => {
@@ -656,6 +817,52 @@ describe('hasOne', () => {
656
817
  .where({ id: { in: profileIds } });
657
818
  expect(updatedUserIds).toEqual([null, null]);
658
819
  });
820
+
821
+ describe('relation callbacks', () => {
822
+ const { beforeUpdate, afterUpdate, resetMocks } = useRelationCallback(
823
+ db.user.relations.profile,
824
+ );
825
+
826
+ it('should invoke callbacks', async () => {
827
+ const id = await db.user.get('id').create({
828
+ ...userData,
829
+ profile: { create: profileData },
830
+ });
831
+
832
+ await db.user.find(id).update({
833
+ profile: {
834
+ disconnect: true,
835
+ },
836
+ });
837
+
838
+ expect(beforeUpdate).toHaveBeenCalledTimes(1);
839
+ expect(afterUpdate).toHaveBeenCalledTimes(1);
840
+ });
841
+
842
+ it('should invoke callbacks in a batch update', async () => {
843
+ resetMocks();
844
+
845
+ const ids = await db.user.pluck('id').createMany([
846
+ {
847
+ ...userData,
848
+ profile: { create: profileData },
849
+ },
850
+ {
851
+ ...userData,
852
+ profile: { create: profileData },
853
+ },
854
+ ]);
855
+
856
+ await db.user.where({ id: { in: ids } }).update({
857
+ profile: {
858
+ disconnect: true,
859
+ },
860
+ });
861
+
862
+ expect(beforeUpdate).toHaveBeenCalledTimes(1);
863
+ expect(afterUpdate).toHaveBeenCalledTimes(1);
864
+ });
865
+ });
659
866
  });
660
867
 
661
868
  describe('set', () => {
@@ -689,6 +896,28 @@ describe('hasOne', () => {
689
896
 
690
897
  await expect(query).rejects.toThrow();
691
898
  });
899
+
900
+ describe('relation callbacks', () => {
901
+ const { beforeUpdate, afterUpdate } = useRelationCallback(
902
+ db.user.relations.profile,
903
+ );
904
+
905
+ it('should invoke callbacks', async () => {
906
+ const userId = await db.user
907
+ .get('id')
908
+ .create({ ...userData, profile: { create: profileData } });
909
+ const profileId = await db.profile.get('id').create(profileData);
910
+
911
+ await db.user.find(userId).update({
912
+ profile: {
913
+ set: { id: profileId },
914
+ },
915
+ });
916
+
917
+ expect(beforeUpdate).toHaveBeenCalledTimes(2);
918
+ expect(afterUpdate).toHaveBeenCalledTimes(2);
919
+ });
920
+ });
692
921
  });
693
922
 
694
923
  describe('delete', () => {
@@ -727,6 +956,45 @@ describe('hasOne', () => {
727
956
  const count = await db.profile.count();
728
957
  expect(count).toBe(0);
729
958
  });
959
+
960
+ describe('relation callbacks', () => {
961
+ const { beforeDelete, afterDelete, resetMocks } = useRelationCallback(
962
+ db.user.relations.profile,
963
+ );
964
+
965
+ it('should invoke callbacks', async () => {
966
+ const id = await db.user
967
+ .get('id')
968
+ .create({ ...userData, profile: { create: profileData } });
969
+
970
+ await db.user.find(id).update({
971
+ profile: {
972
+ delete: true,
973
+ },
974
+ });
975
+
976
+ expect(beforeDelete).toHaveBeenCalledTimes(1);
977
+ expect(afterDelete).toHaveBeenCalledTimes(1);
978
+ });
979
+
980
+ it('should invoke callbacks in a batch update', async () => {
981
+ resetMocks();
982
+
983
+ const ids = await db.user.pluck('id').createMany([
984
+ { ...userData, profile: { create: profileData } },
985
+ { ...userData, profile: { create: profileData } },
986
+ ]);
987
+
988
+ await db.user.where({ id: { in: ids } }).update({
989
+ profile: {
990
+ delete: true,
991
+ },
992
+ });
993
+
994
+ expect(beforeDelete).toHaveBeenCalledTimes(1);
995
+ expect(afterDelete).toHaveBeenCalledTimes(1);
996
+ });
997
+ });
730
998
  });
731
999
 
732
1000
  describe('nested update', () => {
@@ -764,6 +1032,49 @@ describe('hasOne', () => {
764
1032
  const bios = await db.profile.pluck('bio');
765
1033
  expect(bios).toEqual(['updated', 'updated']);
766
1034
  });
1035
+
1036
+ describe('relation callbacks', () => {
1037
+ const { beforeUpdate, afterUpdate, resetMocks } = useRelationCallback(
1038
+ db.user.relations.profile,
1039
+ );
1040
+
1041
+ it('should invoke callbacks', async () => {
1042
+ const id = await db.user
1043
+ .get('id')
1044
+ .create({ ...userData, profile: { create: profileData } });
1045
+
1046
+ await db.user.find(id).update({
1047
+ profile: {
1048
+ update: {
1049
+ bio: 'updated',
1050
+ },
1051
+ },
1052
+ });
1053
+
1054
+ expect(beforeUpdate).toHaveBeenCalledTimes(1);
1055
+ expect(afterUpdate).toHaveBeenCalledTimes(1);
1056
+ });
1057
+
1058
+ it('should invoke callbacks in a batch update', async () => {
1059
+ resetMocks();
1060
+
1061
+ const ids = await db.user.pluck('id').createMany([
1062
+ { ...userData, profile: { create: profileData } },
1063
+ { ...userData, profile: { create: profileData } },
1064
+ ]);
1065
+
1066
+ await db.user.where({ id: { in: ids } }).update({
1067
+ profile: {
1068
+ update: {
1069
+ bio: 'updated',
1070
+ },
1071
+ },
1072
+ });
1073
+
1074
+ expect(beforeUpdate).toHaveBeenCalledTimes(1);
1075
+ expect(afterUpdate).toHaveBeenCalledTimes(1);
1076
+ });
1077
+ });
767
1078
  });
768
1079
 
769
1080
  describe('nested upsert', () => {
@@ -827,6 +1138,56 @@ describe('hasOne', () => {
827
1138
 
828
1139
  await expect(query).rejects.toThrow();
829
1140
  });
1141
+
1142
+ describe('relation callbacks', () => {
1143
+ const {
1144
+ beforeUpdate,
1145
+ afterUpdate,
1146
+ beforeCreate,
1147
+ afterCreate,
1148
+ resetMocks,
1149
+ } = useRelationCallback(db.user.relations.profile);
1150
+
1151
+ it('should invoke callbacks when connecting', async () => {
1152
+ const userId = await db.user
1153
+ .get('id')
1154
+ .create({ ...userData, profile: { create: profileData } });
1155
+
1156
+ await db.user.find(userId).update({
1157
+ profile: {
1158
+ upsert: {
1159
+ update: {
1160
+ bio: 'updated',
1161
+ },
1162
+ create: profileData,
1163
+ },
1164
+ },
1165
+ });
1166
+
1167
+ expect(beforeUpdate).toHaveBeenCalledTimes(1);
1168
+ expect(afterUpdate).toHaveBeenCalledTimes(1);
1169
+ });
1170
+
1171
+ it('should invoke callbacks when creating', async () => {
1172
+ resetMocks();
1173
+
1174
+ const userId = await db.user.get('id').create(userData);
1175
+
1176
+ await db.user.find(userId).update({
1177
+ profile: {
1178
+ upsert: {
1179
+ update: {
1180
+ bio: 'updated',
1181
+ },
1182
+ create: profileData,
1183
+ },
1184
+ },
1185
+ });
1186
+
1187
+ expect(beforeCreate).toHaveBeenCalledTimes(1);
1188
+ expect(afterCreate).toHaveBeenCalledTimes(1);
1189
+ });
1190
+ });
830
1191
  });
831
1192
 
832
1193
  describe('nested create', () => {
@@ -868,6 +1229,35 @@ describe('hasOne', () => {
868
1229
 
869
1230
  await expect(query).rejects.toThrow();
870
1231
  });
1232
+
1233
+ describe('relation callbacks', () => {
1234
+ const {
1235
+ beforeUpdate,
1236
+ afterUpdate,
1237
+ beforeCreate,
1238
+ afterCreate,
1239
+ resetMocks,
1240
+ } = useRelationCallback(db.user.relations.profile);
1241
+
1242
+ it('should invoke callbacks to disconnect previous and create new', async () => {
1243
+ const id = await db.user
1244
+ .get('id')
1245
+ .create({ ...userData, profile: { create: profileData } });
1246
+
1247
+ resetMocks();
1248
+
1249
+ await db.user.find(id).update({
1250
+ profile: {
1251
+ create: profileData,
1252
+ },
1253
+ });
1254
+
1255
+ expect(beforeUpdate).toHaveBeenCalledTimes(1);
1256
+ expect(afterUpdate).toHaveBeenCalledTimes(1);
1257
+ expect(beforeCreate).toHaveBeenCalledTimes(1);
1258
+ expect(afterCreate).toHaveBeenCalledTimes(1);
1259
+ });
1260
+ });
871
1261
  });
872
1262
  });
873
1263
  });
@@ -918,6 +1308,7 @@ describe('hasOne through', () => {
918
1308
  columns = this.setColumns((t) => ({
919
1309
  postId: t.integer().foreignKey(() => Post, 'id'),
920
1310
  tagId: t.integer().foreignKey(() => Tag, 'id'),
1311
+ ...t.primaryKey(['postId', 'tagId']),
921
1312
  }));
922
1313
 
923
1314
  relations = {
@@ -4,6 +4,7 @@ import {
4
4
  startTransaction,
5
5
  } from 'pg-transactional-tests';
6
6
  import { db } from './test-db';
7
+ import { DeleteQueryData, InsertQueryData, Query, UpdateQueryData } from 'pqb';
7
8
 
8
9
  type AssertEqual<T, Expected> = [T] extends [Expected]
9
10
  ? [Expected] extends [T]
@@ -67,3 +68,52 @@ export const useTestDatabase = () => {
67
68
  await db.$close();
68
69
  });
69
70
  };
71
+
72
+ export const useRelationCallback = (rel: { query: Query }) => {
73
+ const beforeCreate = jest.fn();
74
+ const afterCreate = jest.fn();
75
+ const beforeUpdate = jest.fn();
76
+ const afterUpdate = jest.fn();
77
+ const beforeDelete = jest.fn();
78
+ const afterDelete = jest.fn();
79
+ const relQuery = rel.query;
80
+
81
+ beforeAll(() => {
82
+ relQuery._beforeCreate(beforeCreate);
83
+ relQuery._afterCreate(afterCreate);
84
+ relQuery._beforeUpdate(beforeUpdate);
85
+ relQuery._afterUpdate(afterUpdate);
86
+ relQuery._beforeDelete(beforeDelete);
87
+ relQuery._afterDelete(afterDelete);
88
+ });
89
+
90
+ afterAll(() => {
91
+ let q;
92
+ q = relQuery.query as InsertQueryData;
93
+ q.beforeCreate?.pop();
94
+ q.afterCreate?.pop();
95
+ q = relQuery.query as UpdateQueryData;
96
+ q.beforeUpdate?.pop();
97
+ q.afterUpdate?.pop();
98
+ q = relQuery.query as DeleteQueryData;
99
+ q.beforeDelete?.pop();
100
+ q.afterDelete?.pop();
101
+ });
102
+
103
+ return {
104
+ beforeCreate,
105
+ afterCreate,
106
+ beforeUpdate,
107
+ afterUpdate,
108
+ beforeDelete,
109
+ afterDelete,
110
+ resetMocks() {
111
+ beforeCreate.mockReset();
112
+ afterCreate.mockReset();
113
+ beforeUpdate.mockReset();
114
+ afterUpdate.mockReset();
115
+ beforeDelete.mockReset();
116
+ afterDelete.mockReset();
117
+ },
118
+ };
119
+ };