Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a96be4175 | ||
|
|
594bb606b8 | ||
|
|
1c088f65c5 | ||
|
|
7d7a429780 | ||
|
|
d3228441aa | ||
|
|
21d6bf1fca | ||
|
|
a4134aa5a3 | ||
|
|
61397e5184 | ||
|
|
6143cd60e5 | ||
|
|
ac821f6b13 | ||
|
|
2bce38fd2a | ||
|
|
390ee79134 | ||
|
|
cfc9f0bfc3 | ||
|
|
58d5f2a17c | ||
|
|
37f271bd74 | ||
|
|
d770cfc65e | ||
|
|
ab8556790e | ||
|
|
3d89b37cc6 | ||
|
|
78b213321c | ||
|
|
276ba1179f | ||
|
|
0109d166a1 | ||
|
|
779c014256 | ||
|
|
073faf9e10 | ||
|
|
d0e39cf2dd | ||
|
|
f9488a1866 | ||
|
|
d4a3894a9e | ||
|
|
91288b41cd | ||
|
|
1aa2f68e73 | ||
|
|
ad707b0ee4 | ||
|
|
49a2f4d4f7 | ||
|
|
f576979345 | ||
|
|
b45399ab78 | ||
|
|
306dc5e4fb | ||
|
|
605304b93b | ||
|
|
d6a17b2b1e | ||
|
|
4bee875a8c | ||
|
|
fe4ae3ae62 | ||
|
|
a245578ff2 | ||
|
|
f5ec696e15 | ||
|
|
ec9384858b | ||
|
|
47613f796e | ||
|
|
446c780d85 | ||
|
|
615968c640 | ||
|
|
fc89436b6a | ||
|
|
3c1015cb11 | ||
|
|
46c513330c | ||
|
|
ef1598faeb | ||
|
|
42a6903057 | ||
|
|
0f0c2b8b92 | ||
|
|
c400c36306 | ||
|
|
6410bd2eaf | ||
|
|
2ddc5317b8 | ||
|
|
6fffe3377d | ||
|
|
eedef35d02 | ||
|
|
08d232a816 | ||
|
|
d9b3f8657f | ||
|
|
99dc5837f5 | ||
|
|
5a35540522 | ||
|
|
c01fc08f67 | ||
|
|
7397722eb3 | ||
|
|
d51e03b14b | ||
|
|
c4af180a5b | ||
|
|
ee5f1dc879 | ||
|
|
15b43176ff | ||
|
|
03240709dc | ||
|
|
7ee451ca02 | ||
|
|
55b066c475 | ||
|
|
c52bbc4be3 | ||
|
|
31b1f31d82 | ||
|
|
ab1c1bb015 | ||
|
|
45219f4736 | ||
|
|
3296255f80 | ||
|
|
81b4651d6e | ||
|
|
e3bd90c4f2 | ||
|
|
17f1932467 | ||
|
|
1b04fe82a7 | ||
|
|
ffb36509ff | ||
|
|
dc361f7879 | ||
|
|
0b59a5d184 | ||
|
|
54c17eb827 | ||
|
|
bd1142ea7a | ||
|
|
26051833cf | ||
|
|
1d8bc6ca49 | ||
|
|
fbe8cf8223 | ||
|
|
ef8b3e83ac | ||
|
|
9d228a1d96 | ||
|
|
57df25505d | ||
|
|
31cbea0e23 | ||
|
|
edd80c056c | ||
|
|
6ebf0db389 | ||
|
|
6f4e51b859 | ||
|
|
4f5d0db792 | ||
|
|
8733bcaf7a | ||
|
|
5aaca2b7aa | ||
|
|
eacd05bf3b | ||
|
|
d51e0182b5 | ||
|
|
220897ba86 | ||
|
|
78c0203a45 | ||
|
|
720fd90066 | ||
|
|
ca8ee749a2 | ||
|
|
ce2d3a4b00 | ||
|
|
2923684c7c | ||
|
|
879ae597be | ||
|
|
d21f7ccbc8 | ||
|
|
4cc1bc6746 | ||
|
|
49a2c60212 | ||
|
|
7dfbb42ced | ||
|
|
41fafb9e5e | ||
|
|
6815f2f9c7 | ||
|
|
91ab27e070 | ||
|
|
396ccb1cd2 | ||
|
|
4e8d5cebca | ||
|
|
80f2e61189 | ||
|
|
d844fd6ef7 | ||
|
|
513f54f4fe | ||
|
|
2e6d71f493 | ||
|
|
55488c39f4 | ||
|
|
c0e123a917 | ||
|
|
ec88f16f1f | ||
|
|
a957c15062 | ||
|
|
b32b31ccdc | ||
|
|
e29f6af540 | ||
|
|
c6cb3423fa | ||
|
|
45904c07bc | ||
|
|
0623887ff8 | ||
|
|
f31c45a153 | ||
|
|
f5217caef2 | ||
|
|
e1beec0487 | ||
|
|
6bbf263981 | ||
|
|
d86a28bf7f | ||
|
|
c00e8cfa54 | ||
|
|
e82cc328d3 | ||
|
|
7dbfc1b2e0 | ||
|
|
02fb7c0ae0 | ||
|
|
9004dcb93b | ||
|
|
cf83b0a236 | ||
|
|
7f02464fed | ||
|
|
2371253cb5 | ||
|
|
859e7f1c88 | ||
|
|
f1e8481878 | ||
|
|
acf3a7c54e | ||
|
|
f163e4638b | ||
|
|
9dab915ddd | ||
|
|
8fca8f3910 | ||
|
|
1638465607 | ||
|
|
ab7eb7f4b1 | ||
|
|
0592badd56 | ||
|
|
7e82b8fa86 | ||
|
|
7dfb71ca30 | ||
|
|
d99ecde0e2 | ||
|
|
d81b905ad7 | ||
|
|
46c6582328 | ||
|
|
396811b954 | ||
|
|
f6c7d8d97f | ||
|
|
930165b6e8 | ||
|
|
a77bd7bbe0 | ||
|
|
51212cdacf | ||
|
|
3731b1ef3d | ||
|
|
f631c4aa79 | ||
|
|
95cd76e732 | ||
|
|
7e525779b7 | ||
|
|
f176ebf1da | ||
|
|
5058e0e750 | ||
|
|
dc409e1c5a | ||
|
|
89b5d1ebc3 | ||
|
|
0d24664a72 | ||
|
|
69efc26f36 | ||
|
|
95c48ac805 | ||
|
|
59ab38db98 | ||
|
|
11a41e0e39 | ||
|
|
880fe151c0 | ||
|
|
603f106389 | ||
|
|
5c7f1aebb2 | ||
|
|
a8fe3a6466 | ||
|
|
8974f8f9de | ||
|
|
a11c2cc52c | ||
|
|
14d319f992 | ||
|
|
49f0759f31 | ||
|
|
cae8470350 | ||
|
|
a82d616b79 | ||
|
|
515f3263e0 | ||
|
|
aebbc50ba6 | ||
|
|
7cdc78d02d | ||
|
|
df55dec553 | ||
|
|
398ad22868 | ||
|
|
7ef1050946 | ||
|
|
7b8bbaaa86 | ||
|
|
ddfd3fda70 | ||
|
|
5972a6f77f | ||
|
|
9bc703a437 | ||
|
|
15aaf7f51b | ||
|
|
c89a1877ae | ||
|
|
15d2c0f858 | ||
|
|
43a6663230 | ||
|
|
58315e96c9 | ||
|
|
3e466022b8 | ||
|
|
68c036cd0a | ||
|
|
77b656024a | ||
|
|
89772a0dac | ||
|
|
381c462660 | ||
|
|
417acdaacb | ||
|
|
1584dd3179 | ||
|
|
d66f983f56 | ||
|
|
b1f50fe22d | ||
|
|
ce995c39f2 | ||
|
|
b99ea16b31 | ||
|
|
574d8882f4 | ||
|
|
b73f7f4a28 | ||
|
|
e4ebe25626 | ||
|
|
7b6999831a | ||
|
|
0386723ae8 | ||
|
|
6615b885d1 | ||
|
|
254a2e310b | ||
|
|
1934c96353 | ||
|
|
a43437b1d6 | ||
|
|
d25094a152 | ||
|
|
70d29ab6fa | ||
|
|
65abf4edc6 | ||
|
|
ad4aeee45b | ||
|
|
40a2ec8ab3 | ||
|
|
2b7a87a34c | ||
|
|
b15060e306 | ||
|
|
bdf3935704 | ||
|
|
7952cfc9e9 | ||
|
|
4383d23d4c | ||
|
|
027cad2cfd | ||
|
|
b17b5a169f | ||
|
|
9eb1fe06e3 | ||
|
|
007349a180 | ||
|
|
46f979ba6d | ||
|
|
d4eb8e4b3a | ||
|
|
9d0afbd6f3 | ||
|
|
821bd37b37 | ||
|
|
2ab34004a2 | ||
|
|
3ee8032538 | ||
|
|
9838488068 | ||
|
|
1c365dee38 | ||
|
|
a77ee7aaa2 | ||
|
|
07d8a39829 | ||
|
|
10fa080b7f | ||
|
|
eb19edfa8f | ||
|
|
3719bb3762 | ||
|
|
c43c5a0604 | ||
|
|
1467b0b768 | ||
|
|
d3d4a90776 | ||
|
|
5ae50f8670 | ||
|
|
a3642a5594 | ||
|
|
96bfb19769 | ||
|
|
5935cf7f1b | ||
|
|
70eff63529 | ||
|
|
3d02df3b08 | ||
|
|
b9b12256fa | ||
|
|
1b051d102c | ||
|
|
76a820f3ca | ||
|
|
b3d5a6edca | ||
|
|
4753bd785a | ||
|
|
1f634b7ca0 | ||
|
|
2e0f4d3176 | ||
|
|
c2fd990504 | ||
|
|
ea3f4fedb0 | ||
|
|
2db4222ffe | ||
|
|
1dc5cd4d41 | ||
|
|
35d54ff223 | ||
|
|
e4c46e3387 | ||
|
|
77d1a873a9 | ||
|
|
54d98e73a2 | ||
|
|
134086f229 | ||
|
|
e9b5aa6f22 | ||
|
|
3908a6cd6f | ||
|
|
886028c400 | ||
|
|
703e20a43a | ||
|
|
b6aedb830b | ||
|
|
46c7afade6 | ||
|
|
5c7d7579ee | ||
|
|
d158a1e007 | ||
|
|
1fb4147940 | ||
|
|
9cf76cbb2f | ||
|
|
6b00167657 | ||
|
|
592f44eb32 | ||
|
|
00afafb550 | ||
|
|
089941553e | ||
|
|
2dc83a1c55 | ||
|
|
5bfb6fc148 | ||
|
|
31ccdba203 | ||
|
|
82fb5272c8 | ||
|
|
e86ad03cde | ||
|
|
1953402f81 | ||
|
|
d6a086c9c7 | ||
|
|
9a517a89b6 | ||
|
|
19f2197eef | ||
|
|
3d583678cf | ||
|
|
ddde762f9b | ||
|
|
9332eba5d7 | ||
|
|
46d1823ccc | ||
|
|
277da187d0 | ||
|
|
7c6b055cd1 | ||
|
|
97308ebf1c | ||
|
|
c2cf55f10c | ||
|
|
3867ff6874 | ||
|
|
0e1c4e53d8 | ||
|
|
3834e69100 | ||
|
|
a05935cdf6 | ||
|
|
19a0f968ca | ||
|
|
3b945ba439 | ||
|
|
7a47eacb34 | ||
|
|
da853958f7 | ||
|
|
d63d15b7b2 | ||
|
|
6bc040b7bb | ||
|
|
0465c639e6 | ||
|
|
8d59c2fc16 | ||
|
|
cb365117b3 | ||
|
|
7c9aae7eaf | ||
|
|
1e7453edcd | ||
|
|
f353fdf252 | ||
|
|
feff588603 | ||
|
|
8ae5d32fe5 | ||
|
|
9600ab6085 | ||
|
|
417a612aa3 | ||
|
|
4db3c592e5 | ||
|
|
d99db25dca | ||
|
|
ba423e1061 | ||
|
|
d5ca11b27b | ||
|
|
25534f721a | ||
|
|
fad5497363 | ||
|
|
563b31b7d0 | ||
|
|
8c9eb18463 | ||
|
|
0965fad72a | ||
|
|
e76bb37f78 | ||
|
|
b0a85a5637 | ||
|
|
82f374d84c | ||
|
|
9ac037c524 | ||
|
|
f5750f3933 | ||
|
|
8f2cb0522d | ||
|
|
4cd8dbbab4 | ||
|
|
1fb778ae78 | ||
|
|
bc9d76e7da | ||
|
|
af51ce1890 | ||
|
|
75c79f76c8 | ||
|
|
b5b4134b75 | ||
|
|
01ca2ca3de | ||
|
|
f94e80558a | ||
|
|
a5c15e6517 | ||
|
|
aaa39cccf8 | ||
|
|
d24a93962f | ||
|
|
1d9d52ecf8 | ||
|
|
f1a832921a | ||
|
|
af1633db28 | ||
|
|
7353b6a604 | ||
|
|
dab0b4a4d8 | ||
|
|
3711e01a77 | ||
|
|
63c9cb6b92 | ||
|
|
f039e116d7 | ||
|
|
93621baea5 | ||
|
|
eaa17fa48d | ||
|
|
9ce94fbbfc | ||
|
|
69548e6ed0 | ||
|
|
5cd2ba1362 | ||
|
|
f15d347804 | ||
|
|
c95118715a | ||
|
|
21e7ac3cbe | ||
|
|
81de95bd28 | ||
|
|
d80ed07093 | ||
|
|
b2ac86c759 | ||
|
|
295cf40c6e | ||
|
|
92827b2c9d | ||
|
|
e1076690c1 | ||
|
|
70dd9b9c2c | ||
|
|
71bfd17f81 | ||
|
|
5b08b9f11f | ||
|
|
3456477012 | ||
|
|
c654795a3e | ||
|
|
a7b1981cf1 | ||
|
|
48016e0f3e | ||
|
|
30367cd5f3 | ||
|
|
47d822a092 | ||
|
|
b597dad450 | ||
|
|
e67e073f04 | ||
|
|
17f493a488 | ||
|
|
96fcf7beec | ||
|
|
c0aa97178c | ||
|
|
fc8ff2d4ae | ||
|
|
c1a6ccc260 | ||
|
|
b17f47236e | ||
|
|
236fd967ad | ||
|
|
7f5534b340 | ||
|
|
50bacf6ea2 | ||
|
|
0d1adcca58 | ||
|
|
81962efb2e | ||
|
|
da47168941 | ||
|
|
2aa583bb6d | ||
|
|
ea250febbc | ||
|
|
f062014952 | ||
|
|
88961a1c67 | ||
|
|
cd952dc93c | ||
|
|
b0ed1fd5e6 | ||
|
|
be883aac02 | ||
|
|
2ab4e8b40a | ||
|
|
6bd11009a8 | ||
|
|
099c534daa | ||
|
|
7aa1d8035c | ||
|
|
596e9b4e5a | ||
|
|
d04f10e7d1 | ||
|
|
0fec74a7fe | ||
|
|
d927662dd7 | ||
|
|
e1c001baff | ||
|
|
122af4538d | ||
|
|
e215786afb | ||
|
|
f699fd1732 | ||
|
|
a9ddea9184 | ||
|
|
d4edd30a07 | ||
|
|
f98a3c9b69 | ||
|
|
dcc079773b | ||
|
|
2a2e2871a8 | ||
|
|
0befc6431f | ||
|
|
35c363f75c | ||
|
|
ad6d5a01f8 | ||
|
|
11ae957d97 | ||
|
|
c21094ab0a | ||
|
|
9b952fd922 | ||
|
|
ecd85cd15a | ||
|
|
0772e1d168 | ||
|
|
d131d58b19 | ||
|
|
8a18e167e9 | ||
|
|
c7c2c03f6a | ||
|
|
a183b31269 | ||
|
|
bec8bf2eaa | ||
|
|
1789aef7d3 | ||
|
|
7b9dabfa17 | ||
|
|
3ecc9319c7 | ||
|
|
214528ffa8 | ||
|
|
7f79779bf8 | ||
|
|
ed0f8fe0e7 | ||
|
|
273fc544e7 | ||
|
|
f24e8d12f0 | ||
|
|
19712f62e3 | ||
|
|
0ec701f9e6 | ||
|
|
e4cfaa56f0 | ||
|
|
c7641f852f | ||
|
|
e2597fbcd2 | ||
|
|
ce88018ecc | ||
|
|
0eb4e6c7d4 | ||
|
|
10c9c63ad8 | ||
|
|
a18defaa36 | ||
|
|
f9ee907245 | ||
|
|
eac6b12e91 | ||
|
|
1dc63e0df7 | ||
|
|
96cd3f7b2f | ||
|
|
7943a83e7d | ||
|
|
01c16ad150 | ||
|
|
42807481c1 | ||
|
|
032c41fefd | ||
|
|
41041226b4 | ||
|
|
56ab4e8415 | ||
|
|
8ee6d2befa | ||
|
|
9cd133ff10 | ||
|
|
6df473c5fb | ||
|
|
4606fc6ace | ||
|
|
78ddf71823 | ||
|
|
15cb687307 | ||
|
|
c0ecfcd910 | ||
|
|
2e86f8404f | ||
|
|
b94b16316f | ||
|
|
f80b780aae | ||
|
|
00dc467f25 | ||
|
|
d644c09bac | ||
|
|
5d9c7bfde9 | ||
|
|
cfd1c5dfe3 | ||
|
|
d7e5a8e588 | ||
|
|
3b992fa9bd | ||
|
|
8ad442f2be | ||
|
|
695a4d7a59 | ||
|
|
9bcea0fa01 | ||
|
|
9a4c8c147b | ||
|
|
a48ad2219f | ||
|
|
55a97b71c8 | ||
|
|
b1b8b0135e | ||
|
|
08d4c800e9 | ||
|
|
efeb0a8f41 | ||
|
|
207147f5ff | ||
|
|
6bb8a7c6a9 | ||
|
|
aa7f9719c9 | ||
|
|
e045dcff11 | ||
|
|
80eb6daf1f | ||
|
|
b0bf274896 | ||
|
|
4762d475cb | ||
|
|
c7d9c63390 | ||
|
|
853f9bc436 | ||
|
|
ca19aa00c1 | ||
|
|
467c979aa7 | ||
|
|
9f9bf10040 | ||
|
|
8102192987 | ||
|
|
232f9d288c | ||
|
|
7dab100382 | ||
|
|
91d4f1c219 | ||
|
|
a64e7f9c2a | ||
|
|
3c1297aa72 | ||
|
|
96f7a01c5f | ||
|
|
a4a05878ef | ||
|
|
352d68ae1c | ||
|
|
ffd034679c | ||
|
|
d64ae3c901 | ||
|
|
7250e22257 | ||
|
|
f459e5d9c4 | ||
|
|
30bb0f1383 | ||
|
|
24c993a3d2 | ||
|
|
aa4276be5b | ||
|
|
413aba6e52 | ||
|
|
c2547acb3d | ||
|
|
cc1b6bac4a | ||
|
|
d5d90a8b87 | ||
|
|
40333c81c5 | ||
|
|
ff92979311 | ||
|
|
f63edef48d | ||
|
|
37e56ebbf9 | ||
|
|
07c38f1f33 | ||
|
|
192238f4bf | ||
|
|
94a26031a8 | ||
|
|
e9f20b1a0b | ||
|
|
7cb9e2b99b | ||
|
|
dd45d8cdbc | ||
|
|
3a181f1dac | ||
|
|
c3abfa51ba | ||
|
|
6498af167a | ||
|
|
30dce7bacd | ||
|
|
3be9e1bd38 | ||
|
|
db52f44293 | ||
|
|
20d6eb5200 | ||
|
|
424d94f16d | ||
|
|
73e7d6f986 | ||
|
|
145001d26e | ||
|
|
5d2d7ce979 | ||
|
|
4dc21ab2b0 | ||
|
|
df6ee73e05 | ||
|
|
587af33179 | ||
|
|
3b381b037c | ||
|
|
0968fc56eb | ||
|
|
13044cb5b0 | ||
|
|
580b03f2b9 | ||
|
|
543d4bb6b3 | ||
|
|
21d87d5a80 | ||
|
|
194719e7ba | ||
|
|
dc666fc770 | ||
|
|
50a76e6b27 | ||
|
|
be4d3170db | ||
|
|
7b97002230 | ||
|
|
6319d63e1f | ||
|
|
2e18478b5c | ||
|
|
0ef93edd56 | ||
|
|
d6a3661e58 | ||
|
|
be404436d7 | ||
|
|
b1ebefb854 | ||
|
|
f8aa2701b6 | ||
|
|
034dfc8e6b | ||
|
|
a6b6898697 | ||
|
|
0e5a0bfa7b | ||
|
|
6c01f5eace | ||
|
|
ef2c34c55f | ||
|
|
7c1582c06f | ||
|
|
367e2666c6 | ||
|
|
209a401113 | ||
|
|
837349e3d3 | ||
|
|
e66602aa5c | ||
|
|
082f8e1b04 | ||
|
|
07716474d3 | ||
|
|
f335cc4269 | ||
|
|
f19750cfaf | ||
|
|
46810f69ca | ||
|
|
a7247c594b | ||
|
|
8de7876f72 | ||
|
|
49f75f5070 | ||
|
|
4ff543efc7 | ||
|
|
8af5145b56 | ||
|
|
a31242cdc5 | ||
|
|
e20df1e7aa | ||
|
|
960a368175 | ||
|
|
49cb86dfe9 | ||
|
|
b644ec58af | ||
|
|
bd92b89bf0 | ||
|
|
495ac74255 | ||
|
|
c3d35fd8c8 | ||
|
|
87bc8d649a | ||
|
|
1e9f3a8060 | ||
|
|
bc1d73e9fe | ||
|
|
eca01be58c | ||
|
|
4ad1127184 | ||
|
|
76b9b9b0fe | ||
|
|
ff5c6de5da | ||
|
|
eafb61f515 | ||
|
|
d0ca0dab53 | ||
|
|
e6f561c3d7 | ||
|
|
b7c5cfcf02 | ||
|
|
b1bcbe9dfb | ||
|
|
19e1714794 | ||
|
|
e3e624464d | ||
|
|
dc3c7b43bf | ||
|
|
83736785b7 | ||
|
|
83b6b7caf9 | ||
|
|
6fc3ca539b | ||
|
|
9d58d21e85 | ||
|
|
43f6db194e | ||
|
|
43156fa4d7 | ||
|
|
7eee2728a2 | ||
|
|
861e3aa24f | ||
|
|
517d509321 | ||
|
|
2f9a853023 | ||
|
|
b0125e1a05 | ||
|
|
4daad2ac08 | ||
|
|
9d28f5574d | ||
|
|
be525a27df | ||
|
|
df037b008f | ||
|
|
8fb4df4b8c | ||
|
|
6758654796 | ||
|
|
1e86f1046b | ||
|
|
d3775cd920 | ||
|
|
3ab053bf17 | ||
|
|
4a4bee7140 | ||
|
|
9ba85ea0b2 | ||
|
|
d1d1472f3e | ||
|
|
8d18b3da38 | ||
|
|
631c5f7c53 | ||
|
|
f2ca2bdc83 | ||
|
|
bb36807689 | ||
|
|
7ed32d3c77 | ||
|
|
5d84179345 | ||
|
|
cb437231ad | ||
|
|
d47a5be659 | ||
|
|
e89211782c | ||
|
|
fd454061e7 | ||
|
|
277ce1c244 | ||
|
|
1848cd55b1 | ||
|
|
b0e3cc4dd2 | ||
|
|
b3e344d226 | ||
|
|
810f3b834c | ||
|
|
bf1eacfd9b | ||
|
|
c5c654c879 | ||
|
|
d1ce04edc1 | ||
|
|
1f1862e526 | ||
|
|
63dfc3376c | ||
|
|
3166db9bcf | ||
|
|
f8af9dc17e | ||
|
|
ae659b5176 | ||
|
|
33226f268d | ||
|
|
7e2a0d1a1b | ||
|
|
a385bd4d5f | ||
|
|
4b4bc28f1d | ||
|
|
316fba908b | ||
|
|
d40d282912 | ||
|
|
e81df6fdeb | ||
|
|
76420411b9 | ||
|
|
7ec1617dc2 | ||
|
|
870cadd81f | ||
|
|
04c581a25e | ||
|
|
5ef131333d | ||
|
|
c262220f0f | ||
|
|
b5e08ea80f | ||
|
|
00ee1ef441 | ||
|
|
6cdc9c9f59 | ||
|
|
56d1998f0f | ||
|
|
d59fdf21fd | ||
|
|
1a96149ce3 | ||
|
|
d2bc81758c | ||
|
|
0565e23818 | ||
|
|
34cff214dd | ||
|
|
f7af19b7cb | ||
|
|
6849638b1f | ||
|
|
07969f5287 | ||
|
|
44a6ceff3f | ||
|
|
0e4309777b | ||
|
|
b8f0741923 | ||
|
|
ba1ede2e31 | ||
|
|
b74a49f31d | ||
|
|
31cd77345d | ||
|
|
2be9ff7622 | ||
|
|
96a5abe6c3 | ||
|
|
4cdb8f3bae | ||
|
|
1b111c8add | ||
|
|
be1377e9af | ||
|
|
7226370427 | ||
|
|
524c0d81a7 | ||
|
|
f008a28499 | ||
|
|
381f2781a3 | ||
|
|
6f62c6ad5d | ||
|
|
1545a8ec82 | ||
|
|
58d7e59b38 | ||
|
|
d79a5c3adf | ||
|
|
340b5ab061 | ||
|
|
fa58fe6563 | ||
|
|
251121a76f | ||
|
|
75627cb097 | ||
|
|
f9780fbbd2 | ||
|
|
13649d3bf3 | ||
|
|
65898f29eb | ||
|
|
11267e9359 | ||
|
|
d38b35b626 | ||
|
|
fff521e171 | ||
|
|
fd6666ebad | ||
|
|
f2fa1248eb | ||
|
|
7a9ddf2194 | ||
|
|
a39b5e47a7 | ||
|
|
ae8180e7c2 | ||
|
|
72832354e6 | ||
|
|
df598bf281 | ||
|
|
a3ce957f00 | ||
|
|
7701edb0bb | ||
|
|
efd427831d | ||
|
|
bec83b2342 | ||
|
|
5a6a13b954 | ||
|
|
340f15fea5 | ||
|
|
f572a2b9c2 | ||
|
|
ee9c73476b | ||
|
|
78d06c6d01 | ||
|
|
3d3a9c0dfb | ||
|
|
ed06050fda | ||
|
|
fd6effa6ff | ||
|
|
2889893804 | ||
|
|
3c035ab636 | ||
|
|
c1ccd62f98 | ||
|
|
0e5775a087 | ||
|
|
7e83f1a59a | ||
|
|
12724ef894 | ||
|
|
6244b5a2c0 | ||
|
|
615ef93572 | ||
|
|
22f1060ed6 | ||
|
|
51a39571aa | ||
|
|
7180eb067a | ||
|
|
1cfd94d293 | ||
|
|
4bab8c2c32 | ||
|
|
c4beef609b | ||
|
|
be77ac133c | ||
|
|
2d915a1c51 | ||
|
|
ba4986a333 | ||
|
|
a2cf9ef633 | ||
|
|
610e6e8e88 | ||
|
|
cbd8525c39 | ||
|
|
2600a6c3d5 | ||
|
|
5adbe4b570 | ||
|
|
564c84dade |
+35
-11
@@ -17,6 +17,7 @@
|
||||
#
|
||||
|
||||
# To enable enterprise-only features please add your environment variable to the .env file then make your way to /auth/setup to select your license and follow instructions.
|
||||
|
||||
CALCOM_LICENSE_KEY=
|
||||
# Signature token for the Cal.com License API (used for self-hosted integrations)
|
||||
# We will give you a token when we provide you with a license key this ensure you and only you can communicate with the Cal.com License API for your license key
|
||||
@@ -116,6 +117,11 @@ NEXT_PUBLIC_PLAIN_CHAT_ID=
|
||||
PLAIN_CHAT_HMAC_SECRET_KEY=
|
||||
NEXT_PUBLIC_PLAIN_CHAT_EXCLUDED_PATHS=
|
||||
|
||||
|
||||
# Dub Config
|
||||
DUB_API_KEY=
|
||||
NEXT_PUBLIC_DUB_PROGRAM_ID=
|
||||
|
||||
# Zendesk Config
|
||||
NEXT_PUBLIC_ZENDESK_KEY=
|
||||
|
||||
@@ -181,6 +187,7 @@ TWILIO_WHATSAPP_PHONE_NUMBER=
|
||||
# For NEXT_PUBLIC_SENDER_ID only letters, numbers and spaces are allowed (max. 11 characters)
|
||||
NEXT_PUBLIC_SENDER_ID=
|
||||
TWILIO_VERIFY_SID=
|
||||
TWILIO_OPT_OUT_ENABLED=
|
||||
|
||||
# Set it to "1" if you need to run E2E tests locally.
|
||||
NEXT_PUBLIC_IS_E2E=
|
||||
@@ -192,7 +199,10 @@ NEXT_PUBLIC_IS_PREMIUM_NEW_PLAN=0
|
||||
NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE=
|
||||
STRIPE_TEAM_MONTHLY_PRICE_ID=
|
||||
STRIPE_TEAM_PRODUCT_ID=
|
||||
# It is a price ID in the product with id STRIPE_ORG_PRODUCT_ID
|
||||
STRIPE_ORG_MONTHLY_PRICE_ID=
|
||||
STRIPE_ORG_PRODUCT_ID=
|
||||
|
||||
STRIPE_WEBHOOK_SECRET=
|
||||
STRIPE_WEBHOOK_SECRET_APPS=
|
||||
STRIPE_PRIVATE_KEY=
|
||||
@@ -285,7 +295,7 @@ NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL=
|
||||
# use organizations
|
||||
ORGANIZATIONS_ENABLED=
|
||||
NEXT_PUBLIC_ORGANIZATIONS_MIN_SELF_SERVE_SEATS=30
|
||||
NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE=3700 # $37.00 per seat
|
||||
NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE_NEW=37 # $37.00 per seat
|
||||
|
||||
# This variable should only be set to 1 or true if you want to autolink external provider sign-ups with
|
||||
# existing organizations based on email domain address
|
||||
@@ -353,13 +363,6 @@ E2E_TEST_OIDC_USER_PASSWORD=
|
||||
|
||||
# ***********************************************************************************************************
|
||||
|
||||
# provide a value between 0 and 100 to ensure the percentage of traffic
|
||||
# redirected from the legacy to the future pages
|
||||
AB_TEST_BUCKET_PROBABILITY=50
|
||||
APP_ROUTER_APPS_SLUG_SETUP_ENABLED=0
|
||||
APP_ROUTER_APPS_ENABLED=0
|
||||
APP_ROUTER_TEAM_ENABLED=0
|
||||
|
||||
# disable setry server source maps
|
||||
SENTRY_DISABLE_SERVER_WEBPACK_PLUGIN=1
|
||||
|
||||
@@ -402,8 +405,17 @@ NEXT_PUBLIC_WEBSITE_TERMS_URL=
|
||||
# [0: silly & upwards, 1: trace & upwards, 2: debug & upwards, 3: info & upwards, 4: warn & upwards, 5: error & fatal, 6: fatal]
|
||||
NEXT_PUBLIC_LOGGER_LEVEL=
|
||||
|
||||
# Used to use Replexica SDK, a tool for real-time AI-powered localization
|
||||
REPLEXICA_API_KEY=
|
||||
# For storing Daily Video recordings on S3 Bucket
|
||||
CAL_VIDEO_BUCKET_NAME=
|
||||
CAL_VIDEO_BUCKET_REGION=
|
||||
CAL_VIDEO_ASSUME_ROLE_ARN=
|
||||
|
||||
# For local testing of Daily Video
|
||||
# Set this to the link of a working Daily Video meeting link
|
||||
CAL_VIDEO_MEETING_LINK_FOR_TESTING=
|
||||
|
||||
# Used to use lingo.dev SDK, a tool for real-time AI-powered localization
|
||||
LINGO_DOT_DEV_API_KEY=
|
||||
|
||||
# Comma-separated list of DSyncData.directoryId to log SCIM API requests for. It can be enabled temporarily for debugging the requests being sent to SCIM server.
|
||||
DIRECTORY_IDS_TO_LOG=
|
||||
@@ -413,6 +425,8 @@ DIRECTORY_IDS_TO_LOG=
|
||||
# Read more about it in the README.md
|
||||
NEXT_PUBLIC_SINGLE_ORG_SLUG=
|
||||
|
||||
AKISMET_API_KEY=
|
||||
|
||||
## Env variables related to avoiding booking failures
|
||||
# Request for checking reservation would be attempted to send every these seconds if the request is stale at that time
|
||||
NEXT_PUBLIC_QUERY_RESERVATION_INTERVAL_SECONDS=
|
||||
@@ -423,4 +437,14 @@ NEXT_PUBLIC_QUERY_AVAILABLE_SLOTS_INTERVAL_SECONDS=
|
||||
# Used to invalidate available slots when navigating to booking form
|
||||
NEXT_PUBLIC_INVALIDATE_AVAILABLE_SLOTS_ON_BOOKING_FORM=0
|
||||
# Used to enable quick availability checks for x% of all visitors
|
||||
NEXT_PUBLIC_QUICK_AVAILABILITY_ROLLOUT=10
|
||||
NEXT_PUBLIC_QUICK_AVAILABILITY_ROLLOUT=10
|
||||
|
||||
# Deprecated. Use NEXT_PUBLIC_BODY_SCRIPTS instead. NEXT_PUBLIC_HEAD_SCRIPTS are now injected into the body only.
|
||||
NEXT_PUBLIC_HEAD_SCRIPTS=
|
||||
NEXT_PUBLIC_BODY_SCRIPTS=
|
||||
|
||||
DATABASE_CHUNK_SIZE=
|
||||
|
||||
# Service Account Encryption Key for encrypting/decrypting service account keys
|
||||
# You can use: `openssl rand -base64 24` to generate one
|
||||
CALCOM_SERVICE_ACCOUNT_ENCRYPTION_KEY=
|
||||
|
||||
+14
-5
@@ -1,4 +1,11 @@
|
||||
/apps/api/**/* @calcom/Platform
|
||||
/**/package.json @calcom/Foundation
|
||||
/apps/api/**/* @calcom/Platform @calcom/Foundation
|
||||
/apps/ui-playground/**/* @calcom/Consumer @calcom/Foundation
|
||||
/apps/web/components/**/* @calcom/Consumer @calcom/Foundation
|
||||
/apps/web/modules/**/* @calcom/Consumer @calcom/Foundation
|
||||
/apps/web/**/layout.tsx @calcom/Consumer @calcom/Foundation
|
||||
/apps/web/lib/**/* @calcom/Foundation
|
||||
/apps/web/middleware.ts @calcom/Foundation
|
||||
/deploy/**/* @calcom/Foundation
|
||||
/infra/**/* @calcom/Foundation
|
||||
/packages/app-store/applecalendar/**/* @calcom/Foundation
|
||||
@@ -12,12 +19,14 @@
|
||||
/packages/app-store/larkcalendar/**/* @calcom/Foundation
|
||||
/packages/app-store/office365calendar/**/* @calcom/Foundation
|
||||
/packages/app-store/zohocalendar/**/* @calcom/Foundation
|
||||
/packages/core/getAggregatedAvailability/index.ts @calcom/Foundation
|
||||
/packages/core/getAggregateWorkingHours.ts @calcom/Foundation
|
||||
/packages/core/getUserAvailability.ts @calcom/Foundation
|
||||
/packages/features/bookings/lib/**/* @calcom/Foundation
|
||||
/packages/lib/getAggregatedAvailability.ts @calcom/Foundation
|
||||
/packages/lib/getUserAvailability.ts @calcom/Foundation
|
||||
/packages/lib/server/getLuckyUser.ts @calcom/Foundation
|
||||
/packages/lib/slots.ts @calcom/Foundation
|
||||
/packages/platform/**/* @calcom/Platform
|
||||
/packages/platform/**/* @calcom/Platform @calcom/Foundation
|
||||
/packages/prisma/**/* @calcom/Foundation
|
||||
/packages/trpc/server/routers/viewer/bookings/confirm.handler.ts @calcom/Foundation
|
||||
/packages/trpc/server/routers/viewer/bookings/get.handler.ts @calcom/Foundation
|
||||
/packages/trpc/server/routers/viewer/slots/**/* @calcom/Foundation
|
||||
/packages/ui/**/* @calcom/Consumer @calcom/Foundation
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
name: Cal.com/platform request
|
||||
about: Suggest a feature or bug report for cal.com/platform
|
||||
title: ""
|
||||
labels: ["platform", "🚨 needs approval"]
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
### Is your proposal related to a problem?
|
||||
|
||||
<!--
|
||||
Provide a clear and concise description of what the problem is.
|
||||
For example, "I'm always frustrated when..."
|
||||
-->
|
||||
|
||||
(Write your answer here.)
|
||||
|
||||
### Describe the solution you'd like
|
||||
|
||||
<!--
|
||||
Provide a clear and concise description of what you want to happen.
|
||||
-->
|
||||
|
||||
(Describe your proposed solution here.)
|
||||
|
||||
### Describe alternatives you've considered
|
||||
|
||||
<!--
|
||||
Let us know about other solutions you've tried or researched.
|
||||
-->
|
||||
|
||||
(Write your answer here.)
|
||||
|
||||
### Additional context
|
||||
|
||||
<!--
|
||||
Is there anything else you can add about the proposal?
|
||||
You might want to link to related issues here, if you haven't already.
|
||||
-->
|
||||
|
||||
(Write your answer here.)
|
||||
|
||||
### Requirement/Document
|
||||
|
||||
<!--
|
||||
Is there any type of document that could support that feature?
|
||||
-->
|
||||
|
||||
(Share it here.)
|
||||
|
||||
---
|
||||
|
||||
##### House rules
|
||||
|
||||
- If this issue has a `🚨 needs approval` label, don't start coding yet. Wait until a core member approves feature request by removing this label, then you can start coding.
|
||||
- For clarity: Non-core member issues automatically get the `🚨 needs approval` label.
|
||||
- Your feature ideas are invaluable to us! However, they undergo review to ensure alignment with the product's direction.
|
||||
- Follow Best Practices lined out in our [Contributor Docs](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
|
||||
@@ -14,7 +14,7 @@ description: "Run yarn install with node_modules linker and cache enabled"
|
||||
inputs:
|
||||
node_version:
|
||||
required: false
|
||||
default: v18.x
|
||||
default: v20.x
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
on:
|
||||
workflow_call:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
jobs:
|
||||
cleanup-report:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout GitHub Pages Branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: calcom/test-results
|
||||
ref: gh-pages
|
||||
token: ${{ secrets.GH_ACCESS_TOKEN }}
|
||||
|
||||
- name: Set Git User
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Cleanup HTML reports on PR close/merge
|
||||
env:
|
||||
BRANCH_REPORTS_DIR: reports/${{ github.event.pull_request.head.ref }}
|
||||
run: |
|
||||
if [ -d "$BRANCH_REPORTS_DIR" ]; then
|
||||
rm -rf "$BRANCH_REPORTS_DIR"
|
||||
git add .
|
||||
git commit -m "workflow: remove all reports for branch ${{ github.event.pull_request.head.ref }} (PR closed/merged)"
|
||||
git push
|
||||
else
|
||||
echo "No reports found for branch ${{ github.event.pull_request.head.ref }}. Nothing to clean up."
|
||||
fi
|
||||
@@ -1,3 +1,5 @@
|
||||
# deprecated - use smtp with tasker instead */
|
||||
|
||||
name: Cron - scheduleEmailReminders
|
||||
|
||||
on:
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
working-directory: docs
|
||||
run: |
|
||||
export NODE_OPTIONS="--max_old_space_size=8192"
|
||||
npm install -g mintlify
|
||||
npm install -g mintlify@4.0.436
|
||||
mintlify dev &
|
||||
sleep 5 # Let it run for 5 seconds
|
||||
kill $!
|
||||
|
||||
@@ -17,7 +17,7 @@ env:
|
||||
NEXTAUTH_URL: ${{ secrets.CI_NEXTAUTH_URL }}
|
||||
NODE_OPTIONS: --max-old-space-size=29000
|
||||
REDIS_URL: "redis://localhost:6379"
|
||||
REPLEXICA_API_KEY: ${{ secrets.CI_REPLEXICA_API_KEY }}
|
||||
LINGO_DOT_DEV_API_KEY: ${{ secrets.CI_LINGO_DOT_DEV_API_KEY }}
|
||||
STRIPE_PRIVATE_KEY: ${{ secrets.CI_STRIPE_PRIVATE_KEY }}
|
||||
STRIPE_API_KEY: ${{ secrets.CI_STRIPE_PRIVATE_KEY }}
|
||||
STRIPE_CLIENT_ID: ${{ secrets.CI_STRIPE_CLIENT_ID }}
|
||||
|
||||
@@ -21,5 +21,5 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }}
|
||||
with:
|
||||
api-key: ${{ secrets.CI_REPLEXICA_API_KEY }}
|
||||
api-key: ${{ secrets.CI_LINGO_DOT_DEV_API_KEY }}
|
||||
pull-request: true
|
||||
|
||||
@@ -219,6 +219,17 @@ jobs:
|
||||
uses: ./.github/workflows/publish-report.yml
|
||||
secrets: inherit
|
||||
|
||||
cleanup-report:
|
||||
name: Cleanup HTML report
|
||||
if: ${{ !cancelled() && needs.check-label.outputs.run-e2e == 'true' && (github.event.pull_request.merged == true || github.event.pull_request.state == 'closed') }}
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
needs: [changes, check-label, publish-report]
|
||||
uses: ./.github/workflows/cleanup-report.yml
|
||||
secrets: inherit
|
||||
|
||||
required:
|
||||
needs:
|
||||
[
|
||||
|
||||
@@ -2,7 +2,7 @@ name: Unit
|
||||
on:
|
||||
workflow_call:
|
||||
env:
|
||||
REPLEXICA_API_KEY: ${{ secrets.CI_REPLEXICA_API_KEY }}
|
||||
LINGO_DOT_DEV_API_KEY: ${{ secrets.CI_LINGO_DOT_DEV_API_KEY }}
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
Vendored
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
Vendored
Vendored
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
undecided:
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
Vendored
Vendored
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- "@calcom/prisma"
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- "@calcom/prisma"
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
undecided:
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- "@calcom/prisma"
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- "@calcom/prisma"
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
undecided:
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/prisma"
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- "@calcom/prisma"
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
Vendored
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- "@calcom/prisma"
|
||||
Vendored
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/prisma"
|
||||
Vendored
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/prisma"
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/api-v2"
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
undecided:
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
undecided:
|
||||
- calcom-monorepo
|
||||
- "@calcom/app-store-cli"
|
||||
- "@calcom/platform-constants"
|
||||
- "@calcom/platform-enums"
|
||||
- "@calcom/platform-types"
|
||||
- "@calcom/platform-utils"
|
||||
- "@calcom/prisma"
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
undecided:
|
||||
- "@calcom/prisma"
|
||||
+69
-156
@@ -1,43 +1,76 @@
|
||||
# Contributing to Cal.com
|
||||
|
||||
Contributions are what makes the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
|
||||
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
|
||||
|
||||
## House rules
|
||||
## House Rules (for PRs and Issues)
|
||||
|
||||
- Before submitting a new issue or PR, check if it already exists in [issues](https://github.com/calcom/cal.com/issues) or [PRs](https://github.com/calcom/cal.com/pulls).
|
||||
- GitHub issues: take note of the `🚨 needs approval` label.
|
||||
- **For Contributors**:
|
||||
- Feature Requests: Wait for a core member to approve and remove the `🚨 needs approval` label before you start coding or submit a PR.
|
||||
- Bugs, Security, Performance, Documentation, etc.: You can start coding immediately, even if the `🚨 needs approval` label is present. This label mainly concerns feature requests.
|
||||
- **Our Process**:
|
||||
- Issues from non-core members automatically receive the `🚨 needs approval` label.
|
||||
- We greatly value new feature ideas. To ensure consistency in the product's direction, they undergo review and approval.
|
||||
### 👥 Prevent Work Duplication
|
||||
|
||||
Before submitting a new issue or PR, check if it already exists in the [Issues](https://github.com/calcom/cal.com/issues) or [Pull Requests](https://github.com/calcom/cal.com/pulls).
|
||||
|
||||
### ✅ Work Only on Approved Issues
|
||||
|
||||
For feature requests, please wait for a core team member to approve and remove the `🚨 needs approval` label before you start coding or submitting a PR.
|
||||
|
||||
For bugs, security, performance, documentation, etc., you can start coding immediately—even if the `🚨 needs approval` label is present.
|
||||
|
||||
We highly value new feature ideas, but to maintain consistency in the product direction, they must go through a review and approval process.
|
||||
|
||||
### 🚫 Don’t Just Drop a Link
|
||||
|
||||
Avoid posting third-party links (e.g., Slack threads or Linear tickets) without context. A GitHub issue or PR should stand on its own—reviewers shouldn’t have to chase information across multiple tools to understand the context.
|
||||
|
||||
### 👀 Think Like a Reviewer
|
||||
|
||||
Put yourself in the reviewer’s shoes. What would you want to know if reading this for the first time? Are there key decisions, goals, or constraints that need clarification? Does the PR assume knowledge that isn’t obvious? Are there related issues or previous PRs that should be linked?
|
||||
|
||||
### 🧵 Bring in Context from Private Channels
|
||||
|
||||
If the task originated from a private conversation (e.g., Slack), take a moment to extract the relevant details and include them in the GitHub issue or PR. Avoid sharing sensitive information, but make sure important reasoning is captured.
|
||||
|
||||
> Example:
|
||||
> “A user requested feature X to solve problem Y. I considered approaches A, B, and C, but chose C for the following reasons…”
|
||||
|
||||
### 📚 Treat It Like Documentation
|
||||
|
||||
GitHub is a shared source of truth. Every issue and PR contributes to the long-term understanding of the codebase. Write clearly enough that someone—possibly you—can revisit it months later and still understand what happened and why.
|
||||
|
||||
### ✅ Summarize Your PR at the Top
|
||||
|
||||
Even if the code changes are minor or self-explanatory, a short written summary helps reviewers quickly understand the intent. You can use GitHub Copilot’s auto-summarize feature, but make sure to verify it for accuracy and relevance.
|
||||
|
||||
### 🔗 Use GitHub Keywords to Auto-Link Issues
|
||||
|
||||
Use phrases like “Closes #123” or “Fixes #456” in your PR descriptions. This automatically links your PR to the related issue and closes it once merged—keeping everything traceable and organized.
|
||||
|
||||
### 🧪 Mention What Was Tested (and How)
|
||||
|
||||
Explain how you validated your changes. It doesn’t need to be exhaustive—just enough to give reviewers confidence that things were tested and work as expected.
|
||||
|
||||
> Example:
|
||||
> “Tested locally with mock data and confirmed the flow works on staging.”
|
||||
|
||||
### 🧠 Assume Future-You Won’t Remember
|
||||
|
||||
Write with the future in mind. If there are trade-offs, edge cases, or temporary workarounds, document them clearly so they don’t get lost or misinterpreted later.
|
||||
|
||||
## Priorities
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
Type of Issue
|
||||
</td>
|
||||
<td>
|
||||
Priority
|
||||
</td>
|
||||
<td><strong>Type of Issue</strong></td>
|
||||
<td><strong>Priority</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Minor improvements, non-core feature requests
|
||||
</td>
|
||||
<td>Minor improvements, non-core feature requests</td>
|
||||
<td>
|
||||
<a href="https://github.com/calcom/cal.com/issues?q=is:issue+is:open+sort:updated-desc+label:%22Low+priority%22">
|
||||
<img src="https://img.shields.io/badge/-Low%20Priority-green">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Confusing UX (... but working)
|
||||
</td>
|
||||
<tr>
|
||||
<td>Confusing UX (but still functional)</td>
|
||||
<td>
|
||||
<a href="https://github.com/calcom/cal.com/issues?q=is:issue+is:open+sort:updated-desc+label:%22Medium+priority%22">
|
||||
<img src="https://img.shields.io/badge/-Medium%20Priority-yellow">
|
||||
@@ -45,9 +78,7 @@ Contributions are what makes the open source community such an amazing place to
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Core Features (Booking page, availability, timezone calculation)
|
||||
</td>
|
||||
<td>Core Features (Booking page, availability, timezone calculation)</td>
|
||||
<td>
|
||||
<a href="https://github.com/calcom/cal.com/issues?q=is:issue+is:open+sort:updated-desc+label:%22High+priority%22">
|
||||
<img src="https://img.shields.io/badge/-High%20Priority-orange">
|
||||
@@ -55,9 +86,7 @@ Contributions are what makes the open source community such an amazing place to
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Core Bugs (Login, Booking page, Emails are not working)
|
||||
</td>
|
||||
<td>Core Bugs (Login, Booking page, Emails not working)</td>
|
||||
<td>
|
||||
<a href="https://github.com/calcom/cal.com/issues?q=is:issue+is:open+sort:updated-desc+label:Urgent">
|
||||
<img src="https://img.shields.io/badge/-Urgent-red">
|
||||
@@ -68,59 +97,7 @@ Contributions are what makes the open source community such an amazing place to
|
||||
|
||||
## Developing
|
||||
|
||||
The development branch is `main`. This is the branch that all pull
|
||||
requests should be made against. The changes on the `main`
|
||||
branch are tagged into a release monthly.
|
||||
|
||||
To develop locally:
|
||||
|
||||
1. [Fork](https://github.com/calcom/cal.com/fork/) this repository to your
|
||||
own GitHub account and then
|
||||
[clone](https://help.github.com/articles/cloning-a-repository/) it to your local device.
|
||||
2. Create a new branch:
|
||||
|
||||
```sh
|
||||
git checkout -b MY_BRANCH_NAME
|
||||
```
|
||||
|
||||
3. Install yarn:
|
||||
|
||||
```sh
|
||||
npm install -g yarn
|
||||
```
|
||||
|
||||
4. Install the dependencies with:
|
||||
|
||||
```sh
|
||||
yarn
|
||||
```
|
||||
|
||||
5. Set up your `.env` file:
|
||||
|
||||
- Duplicate `.env.example` to `.env`.
|
||||
- Use `openssl rand -base64 32` to generate a key and add it under `NEXTAUTH_SECRET` in the `.env` file.
|
||||
- Use `openssl rand -base64 32` to generate a key and add it under `CALENDSO_ENCRYPTION_KEY` in the `.env` file.
|
||||
|
||||
6. Setup Node
|
||||
If your Node version does not meet the project's requirements as instructed by the docs, "nvm" (Node Version Manager) allows using Node at the version required by the project:
|
||||
|
||||
```sh
|
||||
nvm use
|
||||
```
|
||||
|
||||
You first might need to install the specific version:
|
||||
|
||||
```sh
|
||||
nvm install
|
||||
```
|
||||
|
||||
You can install nvm from [here](https://github.com/nvm-sh/nvm).
|
||||
|
||||
7. Start developing and watch for code changes:
|
||||
|
||||
```sh
|
||||
yarn dev
|
||||
```
|
||||
[See README](https://github.com/calcom/cal.com#development)
|
||||
|
||||
## Building
|
||||
|
||||
@@ -130,23 +107,19 @@ You can build the project with:
|
||||
yarn build
|
||||
```
|
||||
|
||||
Please be sure that you can make a full production build before pushing code.
|
||||
Please ensure that you can make a full production build before pushing code.
|
||||
|
||||
## Testing
|
||||
|
||||
More info on how to add new tests coming soon.
|
||||
|
||||
### Running tests
|
||||
### Running Tests
|
||||
|
||||
This will run and test all flows in multiple Chromium windows to verify that no critical flow breaks:
|
||||
[See README](https://github.com/calcom/cal.com#e2e-testing)
|
||||
|
||||
```sh
|
||||
yarn test-e2e
|
||||
```
|
||||
#### Resolving Issues
|
||||
|
||||
#### Resolving issues
|
||||
|
||||
##### E2E test browsers not installed
|
||||
##### E2E Test Browsers Not Installed
|
||||
|
||||
Run `npx playwright install` to download test browsers and resolve the error below when running `yarn test-e2e`:
|
||||
|
||||
@@ -166,68 +139,8 @@ If you get errors, be sure to fix them before committing.
|
||||
|
||||
## Making a Pull Request
|
||||
|
||||
- Be sure to [check the "Allow edits from maintainers" option](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) while creating your PR.
|
||||
- If your PR refers to or fixes an issue, be sure to add `refs #XXX` or `fixes #XXX` to the PR description. Replacing `XXX` with the respective issue number. See more about [Linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
|
||||
- Be sure to fill the PR Template accordingly.
|
||||
- Review [App Contribution Guidelines](./packages/app-store/CONTRIBUTING.md) when building integrations
|
||||
|
||||
## Guidelines for committing yarn lockfile
|
||||
|
||||
Do not commit your `yarn.lock` unless you've made changes to the `package.json`. If you've already committed `yarn.lock` unintentionally, follow these steps to undo:
|
||||
|
||||
If your last commit has the `yarn.lock` file alongside other files and you only wish to uncommit the `yarn.lock`:
|
||||
|
||||
```bash
|
||||
git checkout HEAD~1 yarn.lock
|
||||
git commit -m "Revert yarn.lock changes"
|
||||
```
|
||||
|
||||
_NB_: You may have to bypass the pre-commit hook with by appending `--no-verify` to the git commit
|
||||
If you've pushed the commit with the `yarn.lock`:
|
||||
|
||||
1. Correct the commit locally using the above method.
|
||||
2. Carefully force push:
|
||||
|
||||
```bash
|
||||
git push origin <your-branch-name> --force
|
||||
```
|
||||
|
||||
If `yarn.lock` was committed a while ago and there have been several commits since, you can use the following steps to revert just the `yarn.lock` changes without impacting the subsequent changes:
|
||||
|
||||
1. **Checkout a Previous Version**:
|
||||
|
||||
- Find the commit hash before the `yarn.lock` was unintentionally committed. You can do this by viewing the Git log:
|
||||
|
||||
```bash
|
||||
git log yarn.lock
|
||||
```
|
||||
|
||||
- Once you have identified the commit hash, use it to checkout the previous version of `yarn.lock`:
|
||||
|
||||
```bash
|
||||
git checkout <commit_hash> yarn.lock
|
||||
```
|
||||
|
||||
2. **Commit the Reverted Version**:
|
||||
|
||||
- After checking out the previous version of the `yarn.lock`, commit this change:
|
||||
|
||||
```bash
|
||||
git commit -m "Revert yarn.lock to its state before unintended changes"
|
||||
```
|
||||
|
||||
3. **Proceed with Caution**:
|
||||
|
||||
- If you need to push this change, first pull the latest changes from your remote branch to ensure you're not overwriting other recent changes:
|
||||
|
||||
```bash
|
||||
git pull origin <your-branch-name>
|
||||
```
|
||||
|
||||
- Then push the updated branch:
|
||||
|
||||
```bash
|
||||
git push origin <your-branch-name>
|
||||
```
|
||||
|
||||
Lastly, make sure to keep the branches updated (e.g. click the `Update branch` button on GitHub PR).
|
||||
- Be sure to [check the "Allow edits from maintainers" option](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) when creating your PR. (This option isn't available if you're [contributing from a fork belonging to an organization](https://github.com/orgs/community/discussions/5634))
|
||||
- If your PR refers to or fixes an issue, add `refs #XXX` or `fixes #XXX` to the PR description. Replace `XXX` with the respective issue number. See more about [linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue).
|
||||
- Fill out the PR template accordingly.
|
||||
- Review the [App Contribution Guidelines](./packages/app-store/CONTRIBUTING.md) when building integrations.
|
||||
- Lastly, make sure to keep your branches updated (e.g., click the `Update branch` button on the GitHub PR page).
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
Possible issue:
|
||||
- We won't be able to use already built calendar-cache when Delegation Credential is enabled because existing CalendarCache entries don't have userId set.
|
||||
|
||||
## Approach of always using SelectedCalendar.credentialId for CalendarCache even for DelegationCredentials
|
||||
- Delete Credentials when DelegationCredential is disabled
|
||||
|
||||
|
||||
TO Test
|
||||
- New members beyond the batch size are processed
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.producthunt.com/products/cal-com"><img src="https://img.shields.io/badge/Product%20Hunt-%231%20Product%20of%20the%20Month-%23DA552E" alt="Product Hunt"></a>
|
||||
<img src="https://api.checklyhq.com/v1/badges/groups/1120718?style=flat&theme=default" alt="Checkly QA">
|
||||
<a href="https://status.cal.com"><img height="20px" src="https://betteruptime.com/status-badges/v1/monitor/a9kf.svg" alt="Uptime"></a>
|
||||
<a href="https://github.com/calcom/cal.com/stargazers"><img src="https://img.shields.io/github/stars/calcom/cal.com" alt="Github Stars"></a>
|
||||
<a href="https://news.ycombinator.com/item?id=34507672"><img src="https://img.shields.io/badge/Hacker%20News-%231-%23FF6600" alt="Hacker News"></a>
|
||||
@@ -172,24 +173,25 @@ yarn dx
|
||||
```
|
||||
|
||||
#### Development tip
|
||||
1. Add `export NODE_OPTIONS=“--max-old-space-size=16384”` to your shell script to increase the memory limit for the node process. Alternatively, you can run this in your terminal before running the app. Replace 16384 with the amount of RAM you want to allocate to the node process.
|
||||
|
||||
Add `NEXT_PUBLIC_LOGGER_LEVEL={level}` to your .env file to control the logging verbosity for all tRPC queries and mutations.\
|
||||
Where {level} can be one of the following:
|
||||
2. Add `NEXT_PUBLIC_LOGGER_LEVEL={level}` to your .env file to control the logging verbosity for all tRPC queries and mutations.\
|
||||
Where {level} can be one of the following:
|
||||
|
||||
`0` for silly \
|
||||
`1` for trace \
|
||||
`2` for debug \
|
||||
`3` for info \
|
||||
`4` for warn \
|
||||
`5` for error \
|
||||
`6` for fatal
|
||||
`0` for silly \
|
||||
`1` for trace \
|
||||
`2` for debug \
|
||||
`3` for info \
|
||||
`4` for warn \
|
||||
`5` for error \
|
||||
`6` for fatal
|
||||
|
||||
When you set `NEXT_PUBLIC_LOGGER_LEVEL={level}` in your .env file, it enables logging at that level and higher. Here's how it works:
|
||||
When you set `NEXT_PUBLIC_LOGGER_LEVEL={level}` in your .env file, it enables logging at that level and higher. Here's how it works:
|
||||
|
||||
The logger will include all logs that are at the specified level or higher. For example: \
|
||||
The logger will include all logs that are at the specified level or higher. For example: \
|
||||
|
||||
- If you set `NEXT_PUBLIC_LOGGER_LEVEL=2`, it will log from level 2 (debug) upwards, meaning levels 2 (debug), 3 (info), 4 (warn), 5 (error), and (fatal) will be logged. \
|
||||
- If you set `NEXT_PUBLIC_LOGGER_LEVEL=3`, it will log from level 3 (info) upwards, meaning levels 3 (info), 4 (warn), 5 (error), and 6 (fatal) will be logged, but level 2 (debug) and level 1 (trace) will be ignored. \
|
||||
- If you set `NEXT_PUBLIC_LOGGER_LEVEL=2`, it will log from level 2 (debug) upwards, meaning levels 2 (debug), 3 (info), 4 (warn), 5 (error), and (fatal) will be logged. \
|
||||
- If you set `NEXT_PUBLIC_LOGGER_LEVEL=3`, it will log from level 3 (info) upwards, meaning levels 3 (info), 4 (warn), 5 (error), and 6 (fatal) will be logged, but level 2 (debug) and level 1 (trace) will be ignored. \
|
||||
|
||||
```sh
|
||||
echo 'NEXT_PUBLIC_LOGGER_LEVEL=3' >> .env
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { Page } from "@playwright/test";
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test.describe("Org", () => {
|
||||
@@ -8,14 +7,16 @@ test.describe("Org", () => {
|
||||
const response = await page.goto("https://i.cal.com/embed");
|
||||
expect(response?.status()).toBe(200);
|
||||
await page.screenshot({ path: "screenshot.jpg" });
|
||||
await expectPageToBeRenderedWithEmbedSsr(page);
|
||||
const body = await response?.text();
|
||||
await expectPageToBeRenderedWithEmbedSsr(body);
|
||||
});
|
||||
|
||||
test("Org User(Rick) Page should be embeddable", async ({ page }) => {
|
||||
const response = await page.goto("https://i.cal.com/team-rick/embed");
|
||||
expect(response?.status()).toBe(200);
|
||||
await expect(page.locator("text=Used by Checkly")).toBeVisible();
|
||||
await expectPageToBeRenderedWithEmbedSsr(page);
|
||||
const body = await response?.text();
|
||||
await expectPageToBeRenderedWithEmbedSsr(body);
|
||||
});
|
||||
|
||||
test("Org User Event(/team-rick/test-event) Page should be embeddable", async ({ page }) => {
|
||||
@@ -23,14 +24,16 @@ test.describe("Org", () => {
|
||||
expect(response?.status()).toBe(200);
|
||||
await expect(page.locator('[data-testid="decrementMonth"]')).toBeVisible();
|
||||
await expect(page.locator('[data-testid="incrementMonth"]')).toBeVisible();
|
||||
await expectPageToBeRenderedWithEmbedSsr(page);
|
||||
const body = await response?.text();
|
||||
await expectPageToBeRenderedWithEmbedSsr(body);
|
||||
});
|
||||
|
||||
test("Org Team Profile(/sales) page should be embeddable", async ({ page }) => {
|
||||
const response = await page.goto("https://i.cal.com/sales/embed");
|
||||
expect(response?.status()).toBe(200);
|
||||
await expect(page.locator("text=Cal.com Sales")).toBeVisible();
|
||||
await expectPageToBeRenderedWithEmbedSsr(page);
|
||||
const body = await response?.text();
|
||||
await expectPageToBeRenderedWithEmbedSsr(body);
|
||||
});
|
||||
|
||||
test("Org Team Event page(/sales/hippa) should be embeddable", async ({ page }) => {
|
||||
@@ -38,7 +41,8 @@ test.describe("Org", () => {
|
||||
expect(response?.status()).toBe(200);
|
||||
await expect(page.locator('[data-testid="decrementMonth"]')).toBeVisible();
|
||||
await expect(page.locator('[data-testid="incrementMonth"]')).toBeVisible();
|
||||
await expectPageToBeRenderedWithEmbedSsr(page);
|
||||
const body = await response?.text();
|
||||
await expectPageToBeRenderedWithEmbedSsr(body);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -68,7 +72,8 @@ test.describe("Org", () => {
|
||||
test("Organization Homepage - Has Engineering and Marketing Teams", async ({ page }) => {
|
||||
const response = await page.goto("https://i.cal.com");
|
||||
expect(response?.status()).toBe(200);
|
||||
await expect(page.locator("text=Cal.com")).toBeVisible();
|
||||
// Somehow there are two Cal.com text momentarily, but shouldn't be the concern of this check
|
||||
await expect(page.locator("text=Cal.com").first()).toBeVisible();
|
||||
await expect(page.locator("text=Engineering")).toBeVisible();
|
||||
await expect(page.locator("text=Marketing")).toBeVisible();
|
||||
});
|
||||
@@ -95,11 +100,6 @@ test.describe("Org", () => {
|
||||
});
|
||||
|
||||
// This ensures that the route is actually mapped to a page that is using withEmbedSsr
|
||||
async function expectPageToBeRenderedWithEmbedSsr(page: Page) {
|
||||
expect(
|
||||
await page.evaluate(() => {
|
||||
//@ts-expect-error - __NEXT_DATA__ is a global variable defined by Next.js
|
||||
return window.__NEXT_DATA__.props.pageProps.isEmbed;
|
||||
})
|
||||
).toBe(true);
|
||||
async function expectPageToBeRenderedWithEmbedSsr(responseText: string | undefined) {
|
||||
expect(responseText).toContain('\\"isEmbed\\":true');
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ We use it in several ways, but mainly, we first import the auto-generated schema
|
||||
|
||||
We have some shared validations which several resources require, like baseApiParams which parses apiKey in all requests, or querIdAsString or TransformParseInt which deal with the id's coming from req.query.
|
||||
|
||||
- **[*]BaseBodyParams** that omits any values from the model that are too sensitive or we don't want to pick when creating a new resource like id, userId, etc.. (those are gotten from context or elswhere)
|
||||
- **[*]BaseBodyParams** that omits any values from the model that are too sensitive or we don't want to pick when creating a new resource like id, userId, etc.. (those are gotten from context or elsewhere)
|
||||
|
||||
- **[*]Public** that also omits any values that we don't want to expose when returning the model as a response, which we parse against before returning all resources.
|
||||
|
||||
@@ -208,7 +208,7 @@ Add this command: `./scripts/vercel-deploy.sh`
|
||||
|
||||
See `scripts/vercel-deploy.sh` for more info on how the deployment is done.
|
||||
|
||||
> _❗ IMORTANT: If you're forking the API repo you will need to update the URLs in both the main repo [`.gitmodules`](https://github.com/calcom/cal.com/blob/main/.gitmodules#L7) and this repo [`./scripts/vercel-deploy.sh`](https://github.com/calcom/api/blob/main/scripts/vercel-deploy.sh#L3) ❗_
|
||||
> _❗ IMPORTANT: If you're forking the API repo you will need to update the URLs in both the main repo [`.gitmodules`](https://github.com/calcom/cal.com/blob/main/.gitmodules#L7) and this repo [`./scripts/vercel-deploy.sh`](https://github.com/calcom/api/blob/main/scripts/vercel-deploy.sh#L3) ❗_
|
||||
|
||||
## Environment variables
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { setUser as SentrySetUser } from "@sentry/nextjs";
|
||||
import type { NextMiddleware } from "next-api-middleware";
|
||||
|
||||
export const captureUserId: NextMiddleware = async (req, res, next) => {
|
||||
if (req.userId) SentrySetUser({ id: req.userId });
|
||||
|
||||
await next();
|
||||
};
|
||||
@@ -2,15 +2,16 @@ import { label } from "next-api-middleware";
|
||||
|
||||
import { addRequestId } from "./addRequestid";
|
||||
import { captureErrors } from "./captureErrors";
|
||||
import { captureUserId } from "./captureUserId";
|
||||
import { checkIsInMaintenanceMode } from "./checkIsInMaintenanceMode";
|
||||
import { extendRequest } from "./extendRequest";
|
||||
import {
|
||||
HTTP_POST,
|
||||
HTTP_DELETE,
|
||||
HTTP_PATCH,
|
||||
HTTP_GET,
|
||||
HTTP_GET_OR_POST,
|
||||
HTTP_GET_DELETE_PATCH,
|
||||
HTTP_GET_OR_POST,
|
||||
HTTP_PATCH,
|
||||
HTTP_POST,
|
||||
} from "./httpMethods";
|
||||
import { rateLimitApiKey } from "./rateLimitApiKey";
|
||||
import { verifyApiKey } from "./verifyApiKey";
|
||||
@@ -31,6 +32,7 @@ const middleware = {
|
||||
extendRequest,
|
||||
pagination: withPagination,
|
||||
captureErrors,
|
||||
captureUserId,
|
||||
verifyCredentialSyncEnabled,
|
||||
};
|
||||
|
||||
@@ -44,8 +46,9 @@ const middlewareOrder = [
|
||||
"verifyApiKey",
|
||||
"rateLimitApiKey",
|
||||
"addRequestId",
|
||||
"captureUserId",
|
||||
] as Middleware[]; // <-- Provide a list of middleware to call automatically
|
||||
|
||||
const withMiddleware = label(middleware, middlewareOrder);
|
||||
|
||||
export { withMiddleware, middleware, middlewareOrder };
|
||||
export { middleware, middlewareOrder, withMiddleware };
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Constructs the WHERE clause for Prisma booking findMany operation.
|
||||
*
|
||||
* @param userId - The ID of the user making the request. This is used to filter bookings where the user is either the host or an attendee.
|
||||
* @param attendeeEmails - An array of emails provided in the request for filtering bookings by attendee emails, used in case of Admin calls.
|
||||
* @param userIds - An array of user IDs to be included in the filter. Defaults to an empty array, and an array of user IDs in case of Admin call containing it.
|
||||
* @param userEmails - An array of user emails to be included in the filter if it is an Admin call and contains userId in query parameter. Defaults to an empty array.
|
||||
*
|
||||
* @returns An object that represents the WHERE clause for the findMany/findUnique operation.
|
||||
*/
|
||||
export function buildWhereClause(userId: number | null, attendeeEmails: string[], userIds: number[] = []) {
|
||||
const filterByAttendeeEmails = attendeeEmails.length > 0;
|
||||
const userFilter = userIds.length > 0 ? { userId: { in: userIds } } : !!userId ? { userId } : {};
|
||||
|
||||
let whereClause = {};
|
||||
|
||||
if (filterByAttendeeEmails) {
|
||||
whereClause = {
|
||||
AND: [
|
||||
userFilter,
|
||||
{
|
||||
attendees: {
|
||||
some: {
|
||||
email: { in: attendeeEmails },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
} else {
|
||||
whereClause = {
|
||||
...userFilter,
|
||||
};
|
||||
}
|
||||
|
||||
return whereClause;
|
||||
}
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
_TeamModel,
|
||||
_UserModel,
|
||||
} from "@calcom/prisma/zod";
|
||||
import { extendedBookingCreateBody, iso8601 } from "@calcom/prisma/zod-utils";
|
||||
import { iso8601 } from "@calcom/prisma/zod-utils";
|
||||
import { extendedBookingCreateBody } from "@calcom/prisma/zod/custom/booking";
|
||||
|
||||
import { schemaQueryUserId } from "./shared/queryUserId";
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { MAX_SEATS_PER_TIME_SLOT } from "@calcom/lib/constants";
|
||||
import slugify from "@calcom/lib/slugify";
|
||||
import { _EventTypeModel as EventType, _HostModel } from "@calcom/prisma/zod";
|
||||
import { customInputSchema, eventTypeBookingFields } from "@calcom/prisma/zod-utils";
|
||||
@@ -22,6 +23,7 @@ const recurringEventInputSchema = z.object({
|
||||
const hostSchema = _HostModel.pick({
|
||||
isFixed: true,
|
||||
userId: true,
|
||||
scheduleId: true,
|
||||
});
|
||||
|
||||
export const childrenSchema = z.object({
|
||||
@@ -102,7 +104,7 @@ const schemaEventTypeEditParams = z
|
||||
.transform((s) => slugify(s))
|
||||
.optional(),
|
||||
length: z.number().int().optional(),
|
||||
seatsPerTimeSlot: z.number().optional(),
|
||||
seatsPerTimeSlot: z.number().min(1).max(MAX_SEATS_PER_TIME_SLOT).nullable().optional(),
|
||||
seatsShowAttendees: z.boolean().optional(),
|
||||
seatsShowAvailabilityCount: z.boolean().optional(),
|
||||
bookingFields: eventTypeBookingFields.optional(),
|
||||
|
||||
@@ -113,7 +113,7 @@ const schemaUserEditParams = z.object({
|
||||
});
|
||||
|
||||
// @note: These are the values that are editable via PATCH method on the user Model,
|
||||
// merging both BaseBodyParams with RequiredParams, and omiting whatever we want at the end.
|
||||
// merging both BaseBodyParams with RequiredParams, and omitting whatever we want at the end.
|
||||
|
||||
const schemaUserCreateParams = z.object({
|
||||
email: emailSchema.toLowerCase(),
|
||||
@@ -137,7 +137,7 @@ const schemaUserCreateParams = z.object({
|
||||
});
|
||||
|
||||
// @note: These are the values that are editable via PATCH method on the user Model,
|
||||
// merging both BaseBodyParams with RequiredParams, and omiting whatever we want at the end.
|
||||
// merging both BaseBodyParams with RequiredParams, and omitting whatever we want at the end.
|
||||
export const schemaUserEditBodyParams = schemaUserBaseBodyParams
|
||||
.merge(schemaUserEditParams)
|
||||
.omit({})
|
||||
|
||||
@@ -10,7 +10,6 @@ const nextConfig = {
|
||||
},
|
||||
transpilePackages: [
|
||||
"@calcom/app-store",
|
||||
"@calcom/core",
|
||||
"@calcom/dayjs",
|
||||
"@calcom/emails",
|
||||
"@calcom/features",
|
||||
@@ -47,7 +46,7 @@ const nextConfig = {
|
||||
async rewrites() {
|
||||
return {
|
||||
afterFiles: [
|
||||
// This redirects requests recieved at / the root to the /api/ folder.
|
||||
// This redirects requests received at / the root to the /api/ folder.
|
||||
{
|
||||
source: "/v:version/:rest*",
|
||||
destination: "/api/v:version/:rest*",
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@calcom/app-store": "*",
|
||||
"@calcom/core": "*",
|
||||
"@calcom/dayjs": "*",
|
||||
"@calcom/emails": "*",
|
||||
"@calcom/features": "*",
|
||||
@@ -34,7 +33,7 @@
|
||||
"@sentry/nextjs": "^8.8.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"memory-cache": "^0.2.0",
|
||||
"next": "^13.5.6",
|
||||
"next": "^13.5.9",
|
||||
"next-api-middleware": "^1.0.1",
|
||||
"next-axiom": "^0.17.0",
|
||||
"next-swagger-doc": "^0.3.6",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getUserAvailability } from "@calcom/core/getUserAvailability";
|
||||
import { getUserAvailability } from "@calcom/lib/getUserAvailability";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
@@ -38,6 +38,12 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* schema:
|
||||
* type: string
|
||||
* description: The reason for cancellation of the booking
|
||||
* - in: query
|
||||
* name: cancelledBy
|
||||
* required: false
|
||||
* schema:
|
||||
* type: string
|
||||
* description: The email of who cancelled the booking
|
||||
* tags:
|
||||
* - bookings
|
||||
* responses:
|
||||
@@ -64,16 +70,19 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: User not found
|
||||
*/
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { id, allRemainingBookings, cancellationReason } = schemaQueryIdParseInt
|
||||
.merge(bookingCancelSchema.pick({ allRemainingBookings: true, cancellationReason: true }))
|
||||
const { id, allRemainingBookings, cancellationReason, cancelledBy } = schemaQueryIdParseInt
|
||||
.merge(
|
||||
bookingCancelSchema.pick({ allRemainingBookings: true, cancellationReason: true, cancelledBy: true })
|
||||
)
|
||||
.parse({
|
||||
...req.query,
|
||||
allRemainingBookings: req.query.allRemainingBookings === "true",
|
||||
});
|
||||
|
||||
// Normalizing for universal handler
|
||||
req.body = { id, allRemainingBookings, cancellationReason };
|
||||
return await handleCancelBooking(req);
|
||||
return await handleCancelBooking({
|
||||
bookingData: { id, allRemainingBookings, cancellationReason, cancelledBy },
|
||||
userId: req.userId,
|
||||
});
|
||||
}
|
||||
|
||||
export default defaultResponder(handler);
|
||||
|
||||
@@ -112,7 +112,7 @@ export async function patchHandler(req: NextApiRequest) {
|
||||
async function checkPermissions(req: NextApiRequest, body: z.infer<typeof schemaBookingEditBodyParams>) {
|
||||
const { userId, isSystemWideAdmin, isOrganizationOwnerOrAdmin } = req;
|
||||
if (body.userId && !isSystemWideAdmin && !isOrganizationOwnerOrAdmin) {
|
||||
// Organizer has to be a cal user and we can't allow a booking to be transfered to some other cal user's name
|
||||
// Organizer has to be a cal user and we can't allow a booking to be transferred to some other cal user's name
|
||||
throw new HttpError({
|
||||
statusCode: 403,
|
||||
message: "Only admin can change the organizer of a booking",
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { getRecordingsOfCalVideoByRoomName } from "@calcom/core/videoClient";
|
||||
import { getDownloadLinkOfCalVideoByRecordingId } from "@calcom/core/videoClient";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import {
|
||||
getRecordingsOfCalVideoByRoomName,
|
||||
getDownloadLinkOfCalVideoByRecordingId,
|
||||
} from "@calcom/lib/videoClient";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { RecordingItemSchema } from "@calcom/prisma/zod-utils";
|
||||
import type { PartialReference } from "@calcom/types/EventManager";
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import {
|
||||
getTranscriptsAccessLinkFromRecordingId,
|
||||
checkIfRoomNameMatchesInRecording,
|
||||
} from "@calcom/core/videoClient";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
} from "@calcom/lib/videoClient";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { PartialReference } from "@calcom/types/EventManager";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { getAllTranscriptsAccessLinkFromRoomName } from "@calcom/core/videoClient";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import { getAllTranscriptsAccessLinkFromRoomName } from "@calcom/lib/videoClient";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { PartialReference } from "@calcom/types/EventManager";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import type { Prisma, Booking } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
@@ -6,6 +6,7 @@ import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "~/lib/helpers/withMiddleware";
|
||||
import { buildWhereClause } from "~/lib/utils/bookings/get/buildWhereClause";
|
||||
import {
|
||||
getAccessibleUsers,
|
||||
retrieveOrgScopedAccessibleUsers,
|
||||
@@ -151,58 +152,6 @@ type GetAdminArgsType = {
|
||||
userId: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs the WHERE clause for Prisma booking findMany operation.
|
||||
*
|
||||
* @param userId - The ID of the user making the request. This is used to filter bookings where the user is either the host or an attendee.
|
||||
* @param attendeeEmails - An array of emails provided in the request for filtering bookings by attendee emails, used in case of Admin calls.
|
||||
* @param userIds - An array of user IDs to be included in the filter. Defaults to an empty array, and an array of user IDs in case of Admin call containing it.
|
||||
* @param userEmails - An array of user emails to be included in the filter if it is an Admin call and contains userId in query parameter. Defaults to an empty array.
|
||||
*
|
||||
* @returns An object that represents the WHERE clause for the findMany/findUnique operation.
|
||||
*/
|
||||
function buildWhereClause(
|
||||
userId: number | null,
|
||||
attendeeEmails: string[],
|
||||
userIds: number[] = [],
|
||||
userEmails: string[] = []
|
||||
) {
|
||||
const filterByAttendeeEmails = attendeeEmails.length > 0;
|
||||
const userFilter = userIds.length > 0 ? { userId: { in: userIds } } : !!userId ? { userId } : {};
|
||||
|
||||
let whereClause = {};
|
||||
|
||||
if (filterByAttendeeEmails) {
|
||||
whereClause = {
|
||||
AND: [
|
||||
userFilter,
|
||||
{
|
||||
attendees: {
|
||||
some: {
|
||||
email: { in: attendeeEmails },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
} else {
|
||||
whereClause = {
|
||||
OR: [
|
||||
userFilter,
|
||||
{
|
||||
attendees: {
|
||||
some: {
|
||||
email: { in: userEmails },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return whereClause;
|
||||
}
|
||||
|
||||
export async function handler(req: NextApiRequest) {
|
||||
const {
|
||||
userId,
|
||||
@@ -238,6 +187,7 @@ export async function handler(req: NextApiRequest) {
|
||||
? [queryFilterForAttendeeEmails.attendeeEmail]
|
||||
: [];
|
||||
const filterByAttendeeEmails = attendeeEmails.length > 0;
|
||||
let userEmailsToFilterBy: string[] = [];
|
||||
|
||||
/** Only admins can query other users */
|
||||
if (isSystemWideAdmin) {
|
||||
@@ -251,7 +201,8 @@ export async function handler(req: NextApiRequest) {
|
||||
userId,
|
||||
};
|
||||
const { userId: argUserId, userIds, userEmails } = await handleSystemWideAdminArgs(systemWideAdminArgs);
|
||||
args.where = buildWhereClause(argUserId, attendeeEmails, userIds, userEmails);
|
||||
userEmailsToFilterBy = userEmails;
|
||||
args.where = buildWhereClause(argUserId, attendeeEmails, userIds);
|
||||
}
|
||||
} else if (isOrganizationOwnerOrAdmin) {
|
||||
let requestedUserIds = [userId];
|
||||
@@ -265,7 +216,8 @@ export async function handler(req: NextApiRequest) {
|
||||
userId,
|
||||
};
|
||||
const { userId: argUserId, userIds, userEmails } = await handleOrgWideAdminArgs(orgWideAdminArgs);
|
||||
args.where = buildWhereClause(argUserId, attendeeEmails, userIds, userEmails);
|
||||
userEmailsToFilterBy = userEmails;
|
||||
args.where = buildWhereClause(argUserId, attendeeEmails, userIds);
|
||||
} else {
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
@@ -276,7 +228,7 @@ export async function handler(req: NextApiRequest) {
|
||||
if (!user) {
|
||||
throw new HttpError({ message: "User not found", statusCode: 404 });
|
||||
}
|
||||
args.where = buildWhereClause(userId, attendeeEmails, [], []);
|
||||
args.where = buildWhereClause(userId, attendeeEmails, []);
|
||||
}
|
||||
|
||||
if (dateFrom) {
|
||||
@@ -317,7 +269,77 @@ export async function handler(req: NextApiRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
const data = await prisma.booking.findMany(args);
|
||||
let data: Booking[] = [];
|
||||
|
||||
if (!filterByAttendeeEmails && userEmailsToFilterBy.length > 0) {
|
||||
const queryOne = prisma.booking.findMany(args);
|
||||
|
||||
const whereClauseForQueryTwo: Prisma.BookingWhereInput = {
|
||||
attendees: {
|
||||
some: {
|
||||
email: { in: userEmailsToFilterBy },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (dateFrom) {
|
||||
whereClauseForQueryTwo.startTime = { gte: dateFrom };
|
||||
}
|
||||
if (dateTo) {
|
||||
whereClauseForQueryTwo.endTime = { lte: dateTo };
|
||||
}
|
||||
if (status === "upcoming") {
|
||||
whereClauseForQueryTwo.startTime = { gte: new Date().toISOString() };
|
||||
}
|
||||
|
||||
const argsForQueryTwo: Prisma.BookingFindManyArgs = {
|
||||
...args,
|
||||
where: whereClauseForQueryTwo,
|
||||
};
|
||||
|
||||
const queryTwo = prisma.booking.findMany(argsForQueryTwo);
|
||||
|
||||
const [resultOne, resultTwo] = await Promise.all([queryOne, queryTwo]);
|
||||
|
||||
const bookingMap = new Map();
|
||||
[...resultOne, ...resultTwo].forEach((booking) => {
|
||||
bookingMap.set(booking.id, booking);
|
||||
});
|
||||
|
||||
const dedupedResults = Array.from(bookingMap.values());
|
||||
|
||||
if (args.orderBy) {
|
||||
let sortField: keyof Booking;
|
||||
let sortDirection: "asc" | "desc" = "asc";
|
||||
|
||||
if (typeof args.orderBy === "object" && !Array.isArray(args.orderBy)) {
|
||||
const orderByKey = Object.keys(args.orderBy)[0] as keyof typeof args.orderBy;
|
||||
sortField = orderByKey as keyof Booking;
|
||||
sortDirection = args.orderBy[orderByKey] as "asc" | "desc";
|
||||
} else {
|
||||
sortField = "id";
|
||||
}
|
||||
|
||||
const sortOrder = sortDirection === "desc" ? -1 : 1;
|
||||
|
||||
dedupedResults.sort((a, b) => {
|
||||
const aValue = a[sortField];
|
||||
const bValue = b[sortField];
|
||||
|
||||
if (aValue < bValue) return -1 * sortOrder;
|
||||
if (aValue > bValue) return 1 * sortOrder;
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
if (args.take !== undefined && args.skip !== undefined) {
|
||||
data = dedupedResults.slice(args.skip, args.skip + args.take);
|
||||
} else {
|
||||
data = dedupedResults;
|
||||
}
|
||||
} else {
|
||||
data = await prisma.booking.findMany(args);
|
||||
}
|
||||
return { bookings: data.map((booking) => schemaBookingReadPublic.parse(booking)) };
|
||||
}
|
||||
|
||||
|
||||
@@ -213,12 +213,14 @@ import { getAccessibleUsers } from "~/lib/utils/retrieveScopedAccessibleUsers";
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { userId, isSystemWideAdmin, isOrganizationOwnerOrAdmin } = req;
|
||||
const { isSystemWideAdmin, isOrganizationOwnerOrAdmin } = req;
|
||||
let userId = req.userId;
|
||||
|
||||
req.body = {
|
||||
...req.body,
|
||||
creationSource: CreationSource.API_V1,
|
||||
};
|
||||
if (isSystemWideAdmin) req.userId = req.body.userId || userId;
|
||||
if (isSystemWideAdmin) userId = req.body.userId || userId;
|
||||
|
||||
if (isOrganizationOwnerOrAdmin) {
|
||||
const accessibleUsersIds = await getAccessibleUsers({
|
||||
@@ -226,11 +228,19 @@ async function handler(req: NextApiRequest) {
|
||||
memberUserIds: [req.body.userId || userId],
|
||||
});
|
||||
const [requestedUserId] = accessibleUsersIds;
|
||||
req.userId = requestedUserId || userId;
|
||||
userId = requestedUserId || userId;
|
||||
}
|
||||
|
||||
try {
|
||||
return await handleNewBooking(req, getBookingDataSchemaForApi);
|
||||
return await handleNewBooking(
|
||||
{
|
||||
bookingData: req.body,
|
||||
userId,
|
||||
hostname: req.headers.host || "",
|
||||
forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
|
||||
},
|
||||
getBookingDataSchemaForApi
|
||||
);
|
||||
} catch (error: unknown) {
|
||||
const knownError = error as Error;
|
||||
if (knownError?.message === ErrorCode.NoAvailableUsersFound) {
|
||||
|
||||
@@ -108,7 +108,7 @@ async function handler(req: NextApiRequest) {
|
||||
// ^ Workaround for the select in `create` not working
|
||||
|
||||
if (createCalendarResources) {
|
||||
const calendar = await getCalendar(credential);
|
||||
const calendar = await getCalendar({ ...credential, delegatedTo: null });
|
||||
if (!calendar) throw new HttpError({ message: "Calendar missing for credential", statusCode: 500 });
|
||||
const calendars = await calendar.listCalendars();
|
||||
const calendarToCreate = calendars.find((calendar) => calendar.primary) || calendars[0];
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
import type { z } from "zod";
|
||||
|
||||
import { getCalendarCredentials, getConnectedCalendars } from "@calcom/core/CalendarManager";
|
||||
import { getCalendarCredentialsWithoutDelegation, getConnectedCalendars } from "@calcom/lib/CalendarManager";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
@@ -185,7 +185,12 @@ async function verifyCredentialsAndGetId({
|
||||
currentCredentialId: number | null;
|
||||
}) {
|
||||
if (parsedBody.integration && parsedBody.externalId) {
|
||||
const calendarCredentials = getCalendarCredentials(userCredentials);
|
||||
const calendarCredentials = getCalendarCredentialsWithoutDelegation(
|
||||
userCredentials.map((cred) => ({
|
||||
...cred,
|
||||
delegationCredentialId: null,
|
||||
}))
|
||||
);
|
||||
|
||||
const { connectedCalendars } = await getConnectedCalendars(
|
||||
calendarCredentials,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { getCalendarCredentials, getConnectedCalendars } from "@calcom/core/CalendarManager";
|
||||
import { getCalendarCredentialsWithoutDelegation, getConnectedCalendars } from "@calcom/lib/CalendarManager";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import prisma from "@calcom/prisma";
|
||||
@@ -82,7 +82,7 @@ async function postHandler(req: NextApiRequest) {
|
||||
message: "Bad request, credential id invalid",
|
||||
});
|
||||
|
||||
const calendarCredentials = getCalendarCredentials(userCredentials);
|
||||
const calendarCredentials = getCalendarCredentialsWithoutDelegation(userCredentials);
|
||||
|
||||
const { connectedCalendars } = await getConnectedCalendars(calendarCredentials, [], parsedBody.externalId);
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ async function defaultScheduleId<T extends DefaultScheduleIdEventTypeBase>({
|
||||
}, {} as { [x: number]: number | null });
|
||||
|
||||
return eventTypes.map((eventType) => {
|
||||
// realistically never happens, userId should't be null on personal event types.
|
||||
// realistically never happens, userId shouldn't be null on personal event types.
|
||||
if (!eventType.userId) return eventType;
|
||||
return {
|
||||
...eventType,
|
||||
|
||||
@@ -8,6 +8,7 @@ import { createContext } from "@calcom/trpc/server/createContext";
|
||||
import { viewerTeamsRouter } from "@calcom/trpc/server/routers/viewer/teams/_router";
|
||||
import type { TInviteMemberInputSchema } from "@calcom/trpc/server/routers/viewer/teams/inviteMember/inviteMember.schema";
|
||||
import { ZInviteMemberInputSchema } from "@calcom/trpc/server/routers/viewer/teams/inviteMember/inviteMember.schema";
|
||||
import { createCallerFactory } from "@calcom/trpc/server/trpc";
|
||||
import type { UserProfile } from "@calcom/types/UserProfile";
|
||||
|
||||
import { TRPCError } from "@trpc/server";
|
||||
@@ -38,7 +39,8 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
const ctx = await createContext({ req, res }, sessionGetter);
|
||||
try {
|
||||
const caller = viewerTeamsRouter.createCaller(ctx);
|
||||
const createCaller = createCallerFactory(viewerTeamsRouter);
|
||||
const caller = createCaller(ctx);
|
||||
await caller.inviteMember({
|
||||
role: data.role,
|
||||
language: data.language,
|
||||
|
||||
@@ -28,7 +28,7 @@ import { membershipIdSchema } from "~/lib/validations/membership";
|
||||
* - memberships
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, membership removed successfuly
|
||||
* description: OK, membership removed successfully
|
||||
* 400:
|
||||
* description: Bad request. Membership id is invalid.
|
||||
* 401:
|
||||
|
||||
@@ -24,7 +24,12 @@ import { membershipCreateBodySchema, schemaMembershipPublic } from "~/lib/valida
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const data = membershipCreateBodySchema.parse(req.body);
|
||||
const args: Prisma.MembershipCreateArgs = { data };
|
||||
const args: Prisma.MembershipCreateArgs = {
|
||||
data: {
|
||||
createdAt: new Date(),
|
||||
...data,
|
||||
},
|
||||
};
|
||||
|
||||
await checkPermissions(req);
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@ import utc from "dayjs/plugin/utc";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||||
import { isSupportedTimeZone } from "@calcom/lib/date-fns";
|
||||
import { isSupportedTimeZone } from "@calcom/lib/dayjs";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import { createContext } from "@calcom/trpc/server/createContext";
|
||||
@@ -18,15 +17,8 @@ import { getHTTPStatusCodeFromError } from "@trpc/server/http";
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
|
||||
let isColdStart = true;
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
if (isColdStart && IS_PRODUCTION) {
|
||||
console.log("Cold start of /v1/slots detected");
|
||||
isColdStart = false;
|
||||
}
|
||||
|
||||
const { usernameList, isTeamEvent, ...rest } = req.query;
|
||||
const parsedIsTeamEvent = String(isTeamEvent).toLowerCase() === "true";
|
||||
let slugs = usernameList;
|
||||
|
||||
@@ -6,6 +6,7 @@ import { defaultResponder } from "@calcom/lib/server/defaultResponder";
|
||||
import { MembershipRole, UserPermissionRole } from "@calcom/prisma/enums";
|
||||
import { createContext } from "@calcom/trpc/server/createContext";
|
||||
import { viewerTeamsRouter } from "@calcom/trpc/server/routers/viewer/teams/_router";
|
||||
import { createCallerFactory } from "@calcom/trpc/server/trpc";
|
||||
import type { UserProfile } from "@calcom/types/UserProfile";
|
||||
|
||||
import { TRPCError } from "@trpc/server";
|
||||
@@ -39,7 +40,8 @@ const patchHandler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
/** @see https://trpc.io/docs/server-side-calls */
|
||||
const ctx = await createContext({ req, res }, sessionGetter);
|
||||
try {
|
||||
const caller = viewerTeamsRouter.createCaller(ctx);
|
||||
const createCaller = createCallerFactory(viewerTeamsRouter);
|
||||
const caller = createCaller(ctx);
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return await caller.publish(req.query as any /* Let tRPC handle this */);
|
||||
} catch (cause) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { getStripeCustomerIdFromUserId } from "@calcom/app-store/stripepayment/lib/customer";
|
||||
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import { getDubCustomer } from "@calcom/features/auth/lib/dub";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||||
import { IS_TEAM_BILLING_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
|
||||
@@ -31,7 +31,7 @@ import { schemaQueryUserId } from "~/lib/validations/shared/queryUserId";
|
||||
* - users
|
||||
* responses:
|
||||
* 201:
|
||||
* description: OK, user removed successfuly
|
||||
* description: OK, user removed successfully
|
||||
* 400:
|
||||
* description: Bad request. User id is invalid.
|
||||
* 401:
|
||||
|
||||
@@ -5,11 +5,11 @@ import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { createMocks } from "node-mocks-http";
|
||||
import { describe, expect, test, vi, afterEach } from "vitest";
|
||||
|
||||
import { buildBooking } from "@calcom/lib/test/builder";
|
||||
import {
|
||||
getRecordingsOfCalVideoByRoomName,
|
||||
getDownloadLinkOfCalVideoByRecordingId,
|
||||
} from "@calcom/core/videoClient";
|
||||
import { buildBooking } from "@calcom/lib/test/builder";
|
||||
} from "@calcom/lib/videoClient";
|
||||
|
||||
import { getAccessibleUsers } from "~/lib/utils/retrieveScopedAccessibleUsers";
|
||||
|
||||
@@ -22,7 +22,7 @@ type CustomNextApiResponse = NextApiResponse & Response;
|
||||
const adminUserId = 1;
|
||||
const memberUserId = 10;
|
||||
|
||||
vi.mock("@calcom/core/videoClient", () => {
|
||||
vi.mock("@calcom/lib/videoClient", () => {
|
||||
return {
|
||||
getRecordingsOfCalVideoByRoomName: vi.fn(),
|
||||
getDownloadLinkOfCalVideoByRecordingId: vi.fn(),
|
||||
|
||||
@@ -5,11 +5,11 @@ import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { createMocks } from "node-mocks-http";
|
||||
import { describe, expect, test, vi, afterEach } from "vitest";
|
||||
|
||||
import { buildBooking } from "@calcom/lib/test/builder";
|
||||
import {
|
||||
getTranscriptsAccessLinkFromRecordingId,
|
||||
checkIfRoomNameMatchesInRecording,
|
||||
} from "@calcom/core/videoClient";
|
||||
import { buildBooking } from "@calcom/lib/test/builder";
|
||||
} from "@calcom/lib/videoClient";
|
||||
|
||||
import { getAccessibleUsers } from "~/lib/utils/retrieveScopedAccessibleUsers";
|
||||
|
||||
@@ -19,7 +19,7 @@ import handler from "../../../../../../pages/api/bookings/[id]/transcripts/[reco
|
||||
type CustomNextApiRequest = NextApiRequest & Request;
|
||||
type CustomNextApiResponse = NextApiResponse & Response;
|
||||
|
||||
vi.mock("@calcom/core/videoClient", () => {
|
||||
vi.mock("@calcom/lib/videoClient", () => {
|
||||
return {
|
||||
getTranscriptsAccessLinkFromRecordingId: vi.fn(),
|
||||
checkIfRoomNameMatchesInRecording: vi.fn(),
|
||||
|
||||
@@ -5,8 +5,8 @@ import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { createMocks } from "node-mocks-http";
|
||||
import { describe, expect, test, vi, afterEach } from "vitest";
|
||||
|
||||
import { getAllTranscriptsAccessLinkFromRoomName } from "@calcom/core/videoClient";
|
||||
import { buildBooking } from "@calcom/lib/test/builder";
|
||||
import { getAllTranscriptsAccessLinkFromRoomName } from "@calcom/lib/videoClient";
|
||||
|
||||
import { getAccessibleUsers } from "~/lib/utils/retrieveScopedAccessibleUsers";
|
||||
|
||||
@@ -16,7 +16,7 @@ import handler from "../../../../../pages/api/bookings/[id]/transcripts/_get";
|
||||
type CustomNextApiRequest = NextApiRequest & Request;
|
||||
type CustomNextApiResponse = NextApiResponse & Response;
|
||||
|
||||
vi.mock("@calcom/core/videoClient", () => {
|
||||
vi.mock("@calcom/lib/videoClient", () => {
|
||||
return {
|
||||
getAllTranscriptsAccessLinkFromRoomName: vi.fn(),
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Request, Response } from "express";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { createMocks } from "node-mocks-http";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { ZodError } from "zod";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
@@ -206,8 +207,155 @@ describe("GET /api/bookings", async () => {
|
||||
console.log("bookings=>", responseData.bookings);
|
||||
responseData.bookings.forEach((booking) => {
|
||||
if (booking.id === 31) expect(booking.eventType?.team?.slug).toBe("team1");
|
||||
if (booking.id === 19) expect(booking.eventType?.team).toBe(null);
|
||||
if (booking.id === 19) {
|
||||
// The team field can be either null or undefined due to nullish() in the schema
|
||||
expect(booking.eventType?.team === null || booking.eventType?.team === undefined).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Date filtering", () => {
|
||||
it("filters bookings by dateFrom", async () => {
|
||||
const { req } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
method: "GET",
|
||||
query: {
|
||||
dateFrom: "2023-01-01T00:00:00Z",
|
||||
},
|
||||
pagination: DefaultPagination,
|
||||
});
|
||||
|
||||
req.userId = proUser.id;
|
||||
|
||||
const responseData = await handler(req);
|
||||
responseData.bookings.forEach((booking) => {
|
||||
expect(new Date(booking.startTime).getTime()).toBeGreaterThanOrEqual(
|
||||
new Date("2023-01-01T00:00:00Z").getTime()
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("filters bookings by dateTo", async () => {
|
||||
const { req } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
method: "GET",
|
||||
query: {
|
||||
dateTo: "2024-12-31T23:59:59Z",
|
||||
},
|
||||
pagination: DefaultPagination,
|
||||
});
|
||||
|
||||
req.userId = proUser.id;
|
||||
|
||||
const responseData = await handler(req);
|
||||
responseData.bookings.forEach((booking) => {
|
||||
expect(new Date(booking.endTime).getTime()).toBeLessThanOrEqual(
|
||||
new Date("2024-12-31T23:59:59Z").getTime()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Sorting and ordering", () => {
|
||||
it("sorts bookings by createdAt in descending order", async () => {
|
||||
const { req } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
method: "GET",
|
||||
query: {
|
||||
sortBy: "createdAt",
|
||||
order: "desc",
|
||||
},
|
||||
pagination: DefaultPagination,
|
||||
});
|
||||
|
||||
req.userId = proUser.id;
|
||||
|
||||
const responseData = await handler(req);
|
||||
const timestamps = responseData.bookings.map((b) => new Date(b.createdAt).getTime());
|
||||
expect(timestamps).toEqual([...timestamps].sort((a, b) => b - a));
|
||||
});
|
||||
});
|
||||
|
||||
describe("Multiple attendee email filtering", () => {
|
||||
it("filters bookings by multiple attendee emails", async () => {
|
||||
const attendeeEmails = ["test1@example.com", "test2@example.com"];
|
||||
const { req } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
method: "GET",
|
||||
query: {
|
||||
attendeeEmail: attendeeEmails,
|
||||
},
|
||||
pagination: DefaultPagination,
|
||||
});
|
||||
|
||||
req.userId = proUser.id;
|
||||
|
||||
const responseData = await handler(req);
|
||||
responseData.bookings.forEach((booking) => {
|
||||
const bookingAttendeeEmails = booking.attendees?.map((a) => a.email);
|
||||
expect(bookingAttendeeEmails?.some((email) => attendeeEmails.includes(email))).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Error cases", () => {
|
||||
it("throws error for invalid status parameter", async () => {
|
||||
const { req } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
method: "GET",
|
||||
query: {
|
||||
status: "invalid_status",
|
||||
},
|
||||
pagination: DefaultPagination,
|
||||
});
|
||||
|
||||
req.userId = proUser.id;
|
||||
|
||||
await expect(handler(req)).rejects.toThrow(ZodError);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Result merging", () => {
|
||||
it("does not return duplicate bookings when merging results from multiple queries", async () => {
|
||||
const adminUser = await prisma.user.findFirstOrThrow({ where: { email: "owner1-acme@example.com" } });
|
||||
|
||||
const testUser = await prisma.user.findFirstOrThrow({ where: { email: "pro@example.com" } });
|
||||
|
||||
const testUserBooking = await prisma.booking.findFirstOrThrow({
|
||||
where: { userId: testUser.id },
|
||||
include: { attendees: true },
|
||||
});
|
||||
|
||||
const { req } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
|
||||
method: "GET",
|
||||
query: {
|
||||
userId: testUser.id, // This will make userEmailsToFilterBy contain the test user's email
|
||||
},
|
||||
pagination: {
|
||||
take: 100,
|
||||
skip: 0,
|
||||
},
|
||||
});
|
||||
|
||||
req.isSystemWideAdmin = true;
|
||||
req.userId = adminUser.id;
|
||||
|
||||
const responseData = await handler(req);
|
||||
|
||||
const bookingIds = responseData.bookings.map((booking) => booking.id);
|
||||
|
||||
const uniqueBookingIds = new Set(bookingIds);
|
||||
|
||||
expect(uniqueBookingIds.size).toBe(bookingIds.length);
|
||||
|
||||
if (uniqueBookingIds.size !== bookingIds.length) {
|
||||
const counts = bookingIds.reduce((acc, id) => {
|
||||
acc[id] = (acc[id] || 0) + 1;
|
||||
return acc;
|
||||
}, {} as Record<number, number>);
|
||||
|
||||
const duplicates = Object.entries(counts)
|
||||
.filter(([_, count]) => count > 1)
|
||||
.map(([id]) => id);
|
||||
|
||||
console.log(`Found duplicate booking IDs: ${duplicates.join(", ")}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
import { buildWhereClause } from "~/lib/utils/bookings/get/buildWhereClause";
|
||||
|
||||
describe("buildWhereClause", () => {
|
||||
it("should return empty object when no filters are provided", () => {
|
||||
const result = buildWhereClause(null, [], []);
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
it("should filter by userId when only userId is provided", () => {
|
||||
const userId = 123;
|
||||
const result = buildWhereClause(userId, [], []);
|
||||
expect(result).toEqual({ userId: 123 });
|
||||
});
|
||||
|
||||
it("should filter by userIds when userIds array is provided", () => {
|
||||
const userIds = [1, 2, 3];
|
||||
const result = buildWhereClause(null, [], userIds);
|
||||
expect(result).toEqual({ userId: { in: [1, 2, 3] } });
|
||||
});
|
||||
|
||||
it("should filter by attendee emails when provided", () => {
|
||||
const attendeeEmails = ["test@example.com", "user@example.com"];
|
||||
const result = buildWhereClause(null, attendeeEmails, []);
|
||||
expect(result).toEqual({
|
||||
AND: [
|
||||
{},
|
||||
{
|
||||
attendees: {
|
||||
some: {
|
||||
email: { in: ["test@example.com", "user@example.com"] },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should combine userId and attendee email filters", () => {
|
||||
const userId = 123;
|
||||
const attendeeEmails = ["test@example.com"];
|
||||
const result = buildWhereClause(userId, attendeeEmails, []);
|
||||
expect(result).toEqual({
|
||||
AND: [
|
||||
{ userId: 123 },
|
||||
{
|
||||
attendees: {
|
||||
some: {
|
||||
email: { in: ["test@example.com"] },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("should combine userIds and attendee email filters", () => {
|
||||
const userIds = [1, 2, 3];
|
||||
const attendeeEmails = ["test@example.com"];
|
||||
const result = buildWhereClause(null, attendeeEmails, userIds);
|
||||
expect(result).toEqual({
|
||||
AND: [
|
||||
{ userId: { in: [1, 2, 3] } },
|
||||
{
|
||||
attendees: {
|
||||
some: {
|
||||
email: { in: ["test@example.com"] },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -81,6 +81,7 @@ describe("POST /api/selected-calendars", () => {
|
||||
userId: 444444,
|
||||
id: "xxx-xxx",
|
||||
eventTypeId: null,
|
||||
delegationCredentialId: null,
|
||||
domainWideDelegationCredentialId: null,
|
||||
googleChannelId: null,
|
||||
googleChannelKind: null,
|
||||
@@ -123,6 +124,7 @@ describe("POST /api/selected-calendars", () => {
|
||||
googleChannelResourceId: null,
|
||||
googleChannelResourceUri: null,
|
||||
googleChannelExpiration: null,
|
||||
delegationCredentialId: null,
|
||||
domainWideDelegationCredentialId: null,
|
||||
eventTypeId: null,
|
||||
error: null,
|
||||
|
||||
@@ -18,5 +18,5 @@
|
||||
"../../../packages/types/*.d.ts",
|
||||
"../../../packages/types/next-auth.d.ts"
|
||||
],
|
||||
"exclude": ["node_modules", "templates", "auth"]
|
||||
"exclude": ["**/node_modules/**", "templates", "auth"]
|
||||
}
|
||||
|
||||
@@ -32,3 +32,9 @@ DOCS_URL=
|
||||
# Axiom logging
|
||||
AXIOM_DATASET=
|
||||
AXIOM_TOKEN=
|
||||
|
||||
# DEBUG: 0
|
||||
# INFO: 1
|
||||
# WARN: 2
|
||||
# ERROR: 3
|
||||
LOGGER_BRIDGE_LOG_LEVEL="1"
|
||||
@@ -0,0 +1,12 @@
|
||||
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
||||
version: v1.25.1
|
||||
ignore: {}
|
||||
# patches apply the minimum changes required to fix a vulnerability
|
||||
patch:
|
||||
'npm:semver:20150403':
|
||||
- '@calcom/platform-libraries-0.0.2 > @calcom/features > @calcom/atoms > rollup-plugin-node-builtins > browserify-fs > levelup > semver':
|
||||
patched: '2025-03-05T12:50:30.654Z'
|
||||
id: 'npm:semver:20150403'
|
||||
path: >-
|
||||
@calcom/platform-libraries-0.0.2 > @calcom/features > @calcom/atoms >
|
||||
rollup-plugin-node-builtins > browserify-fs > levelup > semver
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user