Compare commits
702 Commits
AUT-1020
...
test-cover
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f36155f3a5 | ||
![]() |
09335fcd79 | ||
![]() |
823a2c8b73 | ||
![]() |
741866e742 | ||
![]() |
41622678b0 | ||
![]() |
449b953401 | ||
![]() |
6345ce5195 | ||
![]() |
95651f6163 | ||
![]() |
b02c1545b7 | ||
![]() |
2deaab9b24 | ||
![]() |
f0d4853533 | ||
![]() |
af81ae812f | ||
![]() |
bae76064e5 | ||
![]() |
07d9198cc8 | ||
![]() |
a2e07ea2f7 | ||
![]() |
864c762fe2 | ||
![]() |
167bb4e8a0 | ||
![]() |
4cf64ede74 | ||
![]() |
bb309fea6f | ||
![]() |
1133362028 | ||
![]() |
eb9226bd4a | ||
![]() |
a9abdcc37e | ||
![]() |
6ace93bdbf | ||
![]() |
b89197939a | ||
![]() |
da788106af | ||
![]() |
49e92e6f1d | ||
![]() |
a6c3276104 | ||
![]() |
6388bfc714 | ||
![]() |
bebc3b181d | ||
![]() |
5a6d561c1a | ||
![]() |
5ba575fdfd | ||
![]() |
dcf8bbd804 | ||
![]() |
ff93ffd0b1 | ||
![]() |
395c09df92 | ||
![]() |
4c903cd08b | ||
![]() |
64cb98717c | ||
![]() |
b0e4ce54fb | ||
![]() |
d67a37002f | ||
![]() |
965ff8bc3f | ||
![]() |
400a495ad2 | ||
![]() |
09d0822a8d | ||
![]() |
7016c20ccc | ||
![]() |
df54895805 | ||
![]() |
62d5e6fe51 | ||
![]() |
4615a0b7ea | ||
![]() |
280d603b14 | ||
![]() |
36271f0749 | ||
![]() |
579638f932 | ||
![]() |
48871c82a6 | ||
![]() |
14056c42ef | ||
![]() |
90fe1576de | ||
![]() |
d61cf13985 | ||
![]() |
dfe6dfd0c6 | ||
![]() |
c138c7d0e9 | ||
![]() |
d542be947e | ||
![]() |
c76366e72e | ||
![]() |
75abfda783 | ||
![]() |
f3d8d7d4ad | ||
![]() |
7255eccb22 | ||
![]() |
a0decb70cc | ||
![]() |
532f562495 | ||
![]() |
27e58ae925 | ||
![]() |
abf30dfc1a | ||
![]() |
218b8ce86e | ||
![]() |
4867ffcb4b | ||
![]() |
e34c3b411d | ||
![]() |
c91b8be1a6 | ||
![]() |
9cb41644a1 | ||
![]() |
8c01cea147 | ||
![]() |
58eb55e90a | ||
![]() |
bb05e82e15 | ||
![]() |
5ab95ea175 | ||
![]() |
a25c4f1d1e | ||
![]() |
15287de8af | ||
![]() |
49b4d6b511 | ||
![]() |
d5b4a5d4ac | ||
![]() |
de480b491c | ||
![]() |
a949fda1fc | ||
![]() |
3e28af670c | ||
![]() |
b5310afb90 | ||
![]() |
da81ecf915 | ||
![]() |
f597066d16 | ||
![]() |
ec30606b24 | ||
![]() |
20dce14f17 | ||
![]() |
821742de85 | ||
![]() |
74dc108f62 | ||
![]() |
a05fe856bb | ||
![]() |
d13f51a32d | ||
![]() |
3dbe599cb3 | ||
![]() |
cf966dd83c | ||
![]() |
4e62f3654f | ||
![]() |
970d926563 | ||
![]() |
ff49c747ba | ||
![]() |
c46b8a5f4f | ||
![]() |
485324e204 | ||
![]() |
4696a03db1 | ||
![]() |
7885de36a9 | ||
![]() |
fac4339207 | ||
![]() |
9c70519021 | ||
![]() |
9ae77ecd5d | ||
![]() |
1c8e6f278d | ||
![]() |
c0a190a9f2 | ||
![]() |
e29e2a62f0 | ||
![]() |
1580640a35 | ||
![]() |
33c84b7fcc | ||
![]() |
9773ce75b0 | ||
![]() |
c310e8d152 | ||
![]() |
af251c7b81 | ||
![]() |
122483de0c | ||
![]() |
42c2131144 | ||
![]() |
71bc7a62c2 | ||
![]() |
87bfff07db | ||
![]() |
1cb5b780d2 | ||
![]() |
2f6acd4d6e | ||
![]() |
c2e2351505 | ||
![]() |
d847b5480b | ||
![]() |
32749ee58e | ||
![]() |
a531b8b5fe | ||
![]() |
148a0c5bb0 | ||
![]() |
39f9a58200 | ||
![]() |
edd113d344 | ||
![]() |
c641e8729b | ||
![]() |
2c4b13e4b5 | ||
![]() |
48fcf4dda7 | ||
![]() |
acfd980d4f | ||
![]() |
db9bfab812 | ||
![]() |
d32820ee09 | ||
![]() |
0f823fd19e | ||
![]() |
4308ed5850 | ||
![]() |
b9cd7c3983 | ||
![]() |
fa607aa961 | ||
![]() |
6900b71841 | ||
![]() |
bb230d67e8 | ||
![]() |
4f076ec3e3 | ||
![]() |
96a6cbfb95 | ||
![]() |
5bdc5aed72 | ||
![]() |
d38b0f088b | ||
![]() |
892710f705 | ||
![]() |
fbf898be64 | ||
![]() |
e3e2ecc1e1 | ||
![]() |
b59807d221 | ||
![]() |
163ad52285 | ||
![]() |
4023a6d1cc | ||
![]() |
ec827e5dc0 | ||
![]() |
a8f4fb7c22 | ||
![]() |
bc195ed452 | ||
![]() |
41568904ab | ||
![]() |
79050af391 | ||
![]() |
2e5b44c424 | ||
![]() |
7a437660d1 | ||
![]() |
47510e24d5 | ||
![]() |
91c9ef3068 | ||
![]() |
240854e4ac | ||
![]() |
0e4fc7efbc | ||
![]() |
b47e859225 | ||
![]() |
62a1072682 | ||
![]() |
c6f2a97591 | ||
![]() |
d66be231b3 | ||
![]() |
f73ffc8711 | ||
![]() |
e4c17c1bc7 | ||
![]() |
997e729535 | ||
![]() |
e0e313b8d1 | ||
![]() |
f0bd763e72 | ||
![]() |
6a7a90536b | ||
![]() |
ac8ddedfb5 | ||
![]() |
6fcd126ff8 | ||
![]() |
55d0966d48 | ||
![]() |
2583e08f7a | ||
![]() |
de72e62470 | ||
![]() |
91993dbb07 | ||
![]() |
d87ee4daa3 | ||
![]() |
6791e002ff | ||
![]() |
4ca84aa515 | ||
![]() |
8189cbc171 | ||
![]() |
73edb45ff7 | ||
![]() |
0bbe362660 | ||
![]() |
a76bee51fc | ||
![]() |
6e42b52414 | ||
![]() |
aed61209fa | ||
![]() |
f5d796ea77 | ||
![]() |
ecb04b4ba9 | ||
![]() |
dabb01e237 | ||
![]() |
c2d27d0fd4 | ||
![]() |
e62bd75fdf | ||
![]() |
2e917bd62b | ||
![]() |
e0492c4264 | ||
![]() |
7db68e2f96 | ||
![]() |
e9b05a37d1 | ||
![]() |
5613259536 | ||
![]() |
3209ff16ac | ||
![]() |
a49c8602d1 | ||
![]() |
7caa055e00 | ||
![]() |
0d62bc6c78 | ||
![]() |
bc0861fd9e | ||
![]() |
f280052d93 | ||
![]() |
21da49f79d | ||
![]() |
19a5ccf942 | ||
![]() |
0234b4ad81 | ||
![]() |
59ee9c21f3 | ||
![]() |
00317fed24 | ||
![]() |
42f6311ca8 | ||
![]() |
0f77a1ec03 | ||
![]() |
8268cd4d09 | ||
![]() |
c868070337 | ||
![]() |
2981fa5946 | ||
![]() |
623ec66a79 | ||
![]() |
b51bae14ec | ||
![]() |
05a3016557 | ||
![]() |
9250456e7b | ||
![]() |
163d6a7a28 | ||
![]() |
4ce9976dbc | ||
![]() |
f6490990de | ||
![]() |
f24ff606ac | ||
![]() |
3ff53744b5 | ||
![]() |
0b33c10ed8 | ||
![]() |
3fa87701ed | ||
![]() |
e5e0c6fa2a | ||
![]() |
0b38a0b6af | ||
![]() |
44b228777a | ||
![]() |
dd4f658d14 | ||
![]() |
9c66f47bca | ||
![]() |
138a34d6a4 | ||
![]() |
8f2af2e863 | ||
![]() |
c732fe16b3 | ||
![]() |
9be75e56e7 | ||
![]() |
e7d1f26034 | ||
![]() |
c554fff048 | ||
![]() |
0268521aaa | ||
![]() |
89b1cb9353 | ||
![]() |
8a17c5eaab | ||
![]() |
f4a1ad6c8c | ||
![]() |
93d76d8d79 | ||
![]() |
0b956a71b9 | ||
![]() |
26be72f76d | ||
![]() |
737391c721 | ||
![]() |
9c1d21fd1b | ||
![]() |
ef4a4c8611 | ||
![]() |
13c0a8ceaa | ||
![]() |
c2976080f6 | ||
![]() |
0a1b6931af | ||
![]() |
5009319f91 | ||
![]() |
4db8683bd6 | ||
![]() |
d35cf8d31e | ||
![]() |
5fef16131a | ||
![]() |
8b2235ee26 | ||
![]() |
2d8faf849e | ||
![]() |
c9de9fa185 | ||
![]() |
0618877d58 | ||
![]() |
f6b4e7eef8 | ||
![]() |
7abe44da19 | ||
![]() |
9006a0c25f | ||
![]() |
f8389ff8ab | ||
![]() |
894afe8f92 | ||
![]() |
115394ac8c | ||
![]() |
de42eda65f | ||
![]() |
0b7591edce | ||
![]() |
a043a044ca | ||
![]() |
b1f2727beb | ||
![]() |
d6e78a48a0 | ||
![]() |
589fe0f5f3 | ||
![]() |
244eeeb816 | ||
![]() |
4d5fc50f1a | ||
![]() |
dc0273148c | ||
![]() |
5e6f4bfb88 | ||
![]() |
bc0e18d074 | ||
![]() |
24d09fda4c | ||
![]() |
5e20ac07d1 | ||
![]() |
37c78e6bbd | ||
![]() |
7dcfb1081b | ||
![]() |
01407cf040 | ||
![]() |
eb814c2fb0 | ||
![]() |
d3caadf4af | ||
![]() |
5769c82fca | ||
![]() |
3754783ce2 | ||
![]() |
55ebe2cc0b | ||
![]() |
23c1a42163 | ||
![]() |
c879ffa768 | ||
![]() |
32f7bbfbab | ||
![]() |
84d5b3b158 | ||
![]() |
c8dae9ea9a | ||
![]() |
cbfb5dd8a6 | ||
![]() |
09b2b7350c | ||
![]() |
e146793d32 | ||
![]() |
0bad2ead10 | ||
![]() |
25176884e7 | ||
![]() |
266d4cddb0 | ||
![]() |
6e529a4205 | ||
![]() |
d2cce278bd | ||
![]() |
b774a62f8c | ||
![]() |
66c12e1a92 | ||
![]() |
184d748890 | ||
![]() |
8cc732c8d1 | ||
![]() |
c688d67e4b | ||
![]() |
3408be2840 | ||
![]() |
e126066132 | ||
![]() |
cfec447d8a | ||
![]() |
805d1fdd52 | ||
![]() |
9299948072 | ||
![]() |
b02960a5ec | ||
![]() |
8134b6db6a | ||
![]() |
cd16a3cc15 | ||
![]() |
074e7828f3 | ||
![]() |
5f7d1f9219 | ||
![]() |
b29c6105a1 | ||
![]() |
1297f5d43c | ||
![]() |
f94a5385d7 | ||
![]() |
8ef2000e45 | ||
![]() |
30d496076b | ||
![]() |
5de06d4482 | ||
![]() |
97fa983305 | ||
![]() |
dccc3c5bc1 | ||
![]() |
ed12465975 | ||
![]() |
b78be222d7 | ||
![]() |
342990e1bf | ||
![]() |
2e5dfdbb0d | ||
![]() |
1790ef0ee6 | ||
![]() |
712a5756e2 | ||
![]() |
bf6ff6b0f7 | ||
![]() |
c6003b6695 | ||
![]() |
8352540fcb | ||
![]() |
22299868fa | ||
![]() |
0d126a8e2b | ||
![]() |
776d027dfa | ||
![]() |
fa9b6d1006 | ||
![]() |
89aa7ffc73 | ||
![]() |
fd971449ca | ||
![]() |
f7cd57e549 | ||
![]() |
34aadbfb09 | ||
![]() |
167195a01c | ||
![]() |
b0abf94191 | ||
![]() |
1009c71e72 | ||
![]() |
29b1695159 | ||
![]() |
44f782221f | ||
![]() |
bab25c51d9 | ||
![]() |
89277e1665 | ||
![]() |
1e9c5a1682 | ||
![]() |
0c75486c7a | ||
![]() |
8c39739880 | ||
![]() |
ace1f84094 | ||
![]() |
2cfd6739ca | ||
![]() |
e0d6f0d653 | ||
![]() |
a4d3b387d0 | ||
![]() |
7394aca02d | ||
![]() |
e812725182 | ||
![]() |
bb76bfcd8b | ||
![]() |
6ff6d0a7dc | ||
![]() |
ddc9867058 | ||
![]() |
ba0d46c6cd | ||
![]() |
369f04fdbc | ||
![]() |
09dd8abe23 | ||
![]() |
8c692758ae | ||
![]() |
32d39b88bd | ||
![]() |
8bd66da511 | ||
![]() |
f86799e494 | ||
![]() |
8d10f26f56 | ||
![]() |
297543f9dd | ||
![]() |
0c53ee8460 | ||
![]() |
862842e3e1 | ||
![]() |
a4fad360df | ||
![]() |
3ba4c8b3bf | ||
![]() |
2992236be4 | ||
![]() |
82161f028e | ||
![]() |
1bcaec144b | ||
![]() |
852d4bba0a | ||
![]() |
af56fa2830 | ||
![]() |
813646e392 | ||
![]() |
1ce31eefc6 | ||
![]() |
fdf53844e1 | ||
![]() |
be57a82302 | ||
![]() |
fb82e863e0 | ||
![]() |
101483409f | ||
![]() |
6fe863eec1 | ||
![]() |
fbb6526aac | ||
![]() |
5556aea913 | ||
![]() |
95dc5fb849 | ||
![]() |
062199d0e3 | ||
![]() |
53ce327516 | ||
![]() |
61a1ce57c2 | ||
![]() |
687295f772 | ||
![]() |
e5366534ed | ||
![]() |
66fe84e126 | ||
![]() |
0b6c28422c | ||
![]() |
ea667bb6a9 | ||
![]() |
c9ba219de1 | ||
![]() |
9df1b29d70 | ||
![]() |
3e34359fa9 | ||
![]() |
1818930d2f | ||
![]() |
c03e674001 | ||
![]() |
10a25b82e0 | ||
![]() |
3b2489d738 | ||
![]() |
5c4ca3c84f | ||
![]() |
06c4b7ed2e | ||
![]() |
5591f6ccc9 | ||
![]() |
63dfb6947e | ||
![]() |
b089069b8e | ||
![]() |
e76a99fd68 | ||
![]() |
a4ea6c1fad | ||
![]() |
64ebdce1b2 | ||
![]() |
2709491d59 | ||
![]() |
81beedede6 | ||
![]() |
33a2386d74 | ||
![]() |
0df5e5283e | ||
![]() |
560407b972 | ||
![]() |
f8c25ae508 | ||
![]() |
c524277665 | ||
![]() |
a70fb009c7 | ||
![]() |
11e67f2ea3 | ||
![]() |
e7118ffe15 | ||
![]() |
79e9455244 | ||
![]() |
6ca8e8958a | ||
![]() |
d3dc207166 | ||
![]() |
51e200533b | ||
![]() |
b8a25b87d8 | ||
![]() |
f4fe0a0d4f | ||
![]() |
1d4f829d29 | ||
![]() |
4afa79fca4 | ||
![]() |
ec22184087 | ||
![]() |
413f3db5b4 | ||
![]() |
8ddfcce787 | ||
![]() |
562341adfe | ||
![]() |
9519ec53ef | ||
![]() |
35bada360d | ||
![]() |
1f39765efe | ||
![]() |
cce5b3b533 | ||
![]() |
e77a03b855 | ||
![]() |
7a54ff212e | ||
![]() |
01340f4597 | ||
![]() |
af6fa80d20 | ||
![]() |
e7474dcb9e | ||
![]() |
0eb906d5df | ||
![]() |
c7babf227c | ||
![]() |
d5c81c14f5 | ||
![]() |
59278378e5 | ||
![]() |
990e69143d | ||
![]() |
c413ae06dc | ||
![]() |
456f8a30cc | ||
![]() |
19c4561feb | ||
![]() |
1392fed023 | ||
![]() |
ca81e14d63 | ||
![]() |
8e7a8a02ec | ||
![]() |
e45dfa94ed | ||
![]() |
a153787ae6 | ||
![]() |
cf37c43bc7 | ||
![]() |
d0aa2bca69 | ||
![]() |
7b3811e6ee | ||
![]() |
4054f551d4 | ||
![]() |
4eeda10f3f | ||
![]() |
4231784ed2 | ||
![]() |
61ff6986d3 | ||
![]() |
09bc0bba1e | ||
![]() |
b2bda8479e | ||
![]() |
09b255f99e | ||
![]() |
0800642a2a | ||
![]() |
48b2b006c0 | ||
![]() |
af4c1f08ec | ||
![]() |
87b26b6342 | ||
![]() |
706fb8d82f | ||
![]() |
f7ca59bd5f | ||
![]() |
6540d0ea53 | ||
![]() |
5995038e21 | ||
![]() |
337ba6ea87 | ||
![]() |
04c6183752 | ||
![]() |
0b63922f46 | ||
![]() |
81c39d7d93 | ||
![]() |
164d31dfbc | ||
![]() |
1a833aad52 | ||
![]() |
77246c1fde | ||
![]() |
56c08a3587 | ||
![]() |
ce6214dc0f | ||
![]() |
22002d50ac | ||
![]() |
ab4e94695d | ||
![]() |
47a01cec7e | ||
![]() |
0cf9bc1a32 | ||
![]() |
6552ebcd3c | ||
![]() |
5af1d94fc0 | ||
![]() |
a4ec7b3047 | ||
![]() |
66f5003d91 | ||
![]() |
0c754e4b4b | ||
![]() |
e008087c4a | ||
![]() |
53f63996bd | ||
![]() |
4fedf77991 | ||
![]() |
34331d8763 | ||
![]() |
2c21b7762c | ||
![]() |
7f9c2b687f | ||
![]() |
b452ed648c | ||
![]() |
98e4b843ea | ||
![]() |
da2884d53c | ||
![]() |
7f2937400a | ||
![]() |
a3a4a8e431 | ||
![]() |
3249c954d3 | ||
![]() |
7395d2a74e | ||
![]() |
2060b7b49d | ||
![]() |
d263726c19 | ||
![]() |
7e3325e959 | ||
![]() |
ec075f05c5 | ||
![]() |
200e483574 | ||
![]() |
6c11bfe93d | ||
![]() |
b4cc7f4d81 | ||
![]() |
26fc63c52c | ||
![]() |
116bf59b68 | ||
![]() |
566f9dd5cc | ||
![]() |
ec740c07fa | ||
![]() |
7506bf186b | ||
![]() |
27c36b644d | ||
![]() |
ed2b1029f6 | ||
![]() |
530a920517 | ||
![]() |
42f8e635ed | ||
![]() |
7ace67f906 | ||
![]() |
1b437778dc | ||
![]() |
43b0c65aab | ||
![]() |
3f6a319ebe | ||
![]() |
4cbd342e17 | ||
![]() |
273f04128c | ||
![]() |
9a5cef08d6 | ||
![]() |
bbecfdb718 | ||
![]() |
cbed79fbf1 | ||
![]() |
c4cbc024e6 | ||
![]() |
2db8dbd5a3 | ||
![]() |
13b995c9f2 | ||
![]() |
a0944193b6 | ||
![]() |
c7f343020a | ||
![]() |
7a48ccc4f4 | ||
![]() |
cc1218b7a3 | ||
![]() |
385e640a92 | ||
![]() |
b40a59cbef | ||
![]() |
1a45ce5ea4 | ||
![]() |
ab05048409 | ||
![]() |
47aabbe9c5 | ||
![]() |
58cd2c522e | ||
![]() |
1fe0cd9f84 | ||
![]() |
eeee1ba1a3 | ||
![]() |
3cb8880c5c | ||
![]() |
80cec86225 | ||
![]() |
cc65ed8fb0 | ||
![]() |
0c3f1f4a5d | ||
![]() |
76375941ca | ||
![]() |
d2a0415def | ||
![]() |
815c0834b2 | ||
![]() |
7e1e1e2524 | ||
![]() |
957d2793cb | ||
![]() |
6ab86b7574 | ||
![]() |
1c75b7226d | ||
![]() |
db22d8e2c9 | ||
![]() |
7838b9609c | ||
![]() |
2a1a0421b6 | ||
![]() |
125ea0457e | ||
![]() |
c1f5f0632b | ||
![]() |
8c84ab29c6 | ||
![]() |
2767af11b2 | ||
![]() |
59bbc4c182 | ||
![]() |
a755ee8dc1 | ||
![]() |
4b1e66add3 | ||
![]() |
4f6727810b | ||
![]() |
60fdfc2b48 | ||
![]() |
268d8c8b7d | ||
![]() |
49d4071928 | ||
![]() |
c99b9dbe0a | ||
![]() |
09d3a06b27 | ||
![]() |
0d49bc003f | ||
![]() |
86a5569bf7 | ||
![]() |
ad9fe7dec6 | ||
![]() |
24bf07e068 | ||
![]() |
bae234827f | ||
![]() |
81c698f45b | ||
![]() |
c9fecec575 | ||
![]() |
2f42dfdc51 | ||
![]() |
5bac68b0de | ||
![]() |
5afd500c26 | ||
![]() |
03f3e5f6ab | ||
![]() |
50d91405a9 | ||
![]() |
69eed65c9b | ||
![]() |
f1355cd0ab | ||
![]() |
cc1a924c8b | ||
![]() |
02005a3f09 | ||
![]() |
d9219a5a48 | ||
![]() |
dffbdf544c | ||
![]() |
e2dbf1a215 | ||
![]() |
66f9cb8d25 | ||
![]() |
c1396b97f0 | ||
![]() |
920a711c00 | ||
![]() |
02a872a376 | ||
![]() |
be4493710f | ||
![]() |
52c0c5e0c5 | ||
![]() |
4c639f170e | ||
![]() |
509a414151 | ||
![]() |
8f3c793a69 | ||
![]() |
a2dd9cf1b8 | ||
![]() |
42285a5879 | ||
![]() |
5d63fce6f0 | ||
![]() |
46a4c8faec | ||
![]() |
ba14481151 | ||
![]() |
bdd8da98c4 | ||
![]() |
5a4207414d | ||
![]() |
730fdd32b1 | ||
![]() |
aa7f6694fc | ||
![]() |
8fba6704df | ||
![]() |
37d02eba02 | ||
![]() |
75a87cf070 | ||
![]() |
8acdc5853d | ||
![]() |
1aa1f441b3 | ||
![]() |
0e26032ac3 | ||
![]() |
871f25c6d9 | ||
![]() |
d8199e7ba7 | ||
![]() |
52b938eabe | ||
![]() |
94fddf3d9b | ||
![]() |
02c98c1ece | ||
![]() |
6ba77667e9 | ||
![]() |
e201a5b806 | ||
![]() |
adac68c407 | ||
![]() |
d051275e54 | ||
![]() |
2afc00364a | ||
![]() |
0a1461231b | ||
![]() |
129327f40d | ||
![]() |
58819aad94 | ||
![]() |
949a2543f5 | ||
![]() |
0f9d732667 | ||
![]() |
b7df175950 | ||
![]() |
4f7ce9874f | ||
![]() |
f63cc80383 | ||
![]() |
dd0a1328e8 | ||
![]() |
27610c002c | ||
![]() |
46ec9b5229 | ||
![]() |
778559d537 | ||
![]() |
1e64b8a903 | ||
![]() |
0e000693d6 | ||
![]() |
cf9e09ea7a | ||
![]() |
eac2f729a5 | ||
![]() |
9578cd27dd | ||
![]() |
9304ffffc9 | ||
![]() |
3fd628cb05 | ||
![]() |
fe68b70bd9 | ||
![]() |
ec2863d218 | ||
![]() |
dc56e7f883 | ||
![]() |
2f1f537e00 | ||
![]() |
b7b3a3025b | ||
![]() |
edb9526538 | ||
![]() |
62117ece06 | ||
![]() |
913a2a0ac1 | ||
![]() |
92ec3d07a3 | ||
![]() |
67ee7899fd | ||
![]() |
b0ceb3fe7e | ||
![]() |
ba6b4c6854 | ||
![]() |
61e90aed60 | ||
![]() |
45b7a399f2 | ||
![]() |
673ed25598 | ||
![]() |
14fc460174 | ||
![]() |
211b4537f9 | ||
![]() |
a683e059aa | ||
![]() |
d2d2cea567 | ||
![]() |
e5bda65a35 | ||
![]() |
6aaef9df4b | ||
![]() |
7fba4d72b0 | ||
![]() |
a6dc2ed4ba | ||
![]() |
20a40eb2f6 | ||
![]() |
ec4ac9d075 | ||
![]() |
b2c14f4226 | ||
![]() |
099dfbd0b0 | ||
![]() |
a9f5736c12 | ||
![]() |
2bd4dd3ab0 | ||
![]() |
186850c256 | ||
![]() |
9922033d33 | ||
![]() |
3c3e6e4144 | ||
![]() |
0e4ac3b7f3 | ||
![]() |
c9813e0316 | ||
![]() |
577c0cfab9 | ||
![]() |
0966f9d715 | ||
![]() |
3f5df118a0 | ||
![]() |
e05c1b26f1 | ||
![]() |
725b38c697 | ||
![]() |
402a0fdf3b | ||
![]() |
078364ffa1 | ||
![]() |
f64d5ec4fc | ||
![]() |
0666174501 | ||
![]() |
12194a50e1 | ||
![]() |
82ee592699 | ||
![]() |
1b4fb2ce6e | ||
![]() |
ebea8d12d1 | ||
![]() |
f842dd77df | ||
![]() |
a6ec7a6c99 | ||
![]() |
369c72282c | ||
![]() |
6f30c1a509 | ||
![]() |
abfd1116c7 | ||
![]() |
017854955d | ||
![]() |
1405cddea1 | ||
![]() |
00dd3164c9 | ||
![]() |
d5cbc0f611 | ||
![]() |
5d2e9ccc67 | ||
![]() |
017a881494 | ||
![]() |
52994970e6 | ||
![]() |
ebae629e5c | ||
![]() |
0dea5150a0 | ||
![]() |
c99e8d270d | ||
![]() |
4d79220b0c | ||
![]() |
96fba7fbb8 | ||
![]() |
e0d610071d | ||
![]() |
ab0966c005 | ||
![]() |
145172f486 | ||
![]() |
e2c5d843df | ||
![]() |
557ea55ddf | ||
![]() |
1591a4edd2 | ||
![]() |
b30b5024a8 | ||
![]() |
8ef2bd3b8d |
@@ -5,8 +5,11 @@ BACKEND_PORT=3000
|
|||||||
WEB_PORT=3001
|
WEB_PORT=3001
|
||||||
|
|
||||||
echo "Configuring backend environment variables..."
|
echo "Configuring backend environment variables..."
|
||||||
|
|
||||||
cd packages/backend
|
cd packages/backend
|
||||||
|
|
||||||
rm -rf .env
|
rm -rf .env
|
||||||
|
|
||||||
echo "
|
echo "
|
||||||
PORT=$BACKEND_PORT
|
PORT=$BACKEND_PORT
|
||||||
WEB_APP_URL=http://localhost:$WEB_PORT
|
WEB_APP_URL=http://localhost:$WEB_PORT
|
||||||
@@ -21,24 +24,35 @@ WEBHOOK_SECRET_KEY=sample_webhook_secret_key
|
|||||||
APP_SECRET_KEY=sample_app_secret_key
|
APP_SECRET_KEY=sample_app_secret_key
|
||||||
REDIS_HOST=redis
|
REDIS_HOST=redis
|
||||||
SERVE_WEB_APP_SEPARATELY=true" >> .env
|
SERVE_WEB_APP_SEPARATELY=true" >> .env
|
||||||
|
|
||||||
|
echo "Installing backend dependencies..."
|
||||||
|
|
||||||
|
yarn
|
||||||
|
|
||||||
cd $CURRENT_DIR
|
cd $CURRENT_DIR
|
||||||
|
|
||||||
echo "Configuring web environment variables..."
|
echo "Configuring web environment variables..."
|
||||||
|
|
||||||
cd packages/web
|
cd packages/web
|
||||||
|
|
||||||
rm -rf .env
|
rm -rf .env
|
||||||
|
|
||||||
echo "
|
echo "
|
||||||
PORT=$WEB_PORT
|
PORT=$WEB_PORT
|
||||||
REACT_APP_BACKEND_URL=http://localhost:$BACKEND_PORT
|
REACT_APP_BACKEND_URL=http://localhost:$BACKEND_PORT
|
||||||
" >> .env
|
" >> .env
|
||||||
|
|
||||||
|
echo "Installing web dependencies..."
|
||||||
|
|
||||||
|
yarn
|
||||||
|
|
||||||
cd $CURRENT_DIR
|
cd $CURRENT_DIR
|
||||||
|
|
||||||
echo "Installing and linking dependencies..."
|
|
||||||
yarn
|
|
||||||
yarn lerna bootstrap
|
|
||||||
|
|
||||||
echo "Migrating database..."
|
echo "Migrating database..."
|
||||||
|
|
||||||
cd packages/backend
|
cd packages/backend
|
||||||
|
|
||||||
yarn db:migrate
|
yarn db:migrate
|
||||||
yarn db:seed:user
|
yarn db:seed:user
|
||||||
|
|
||||||
echo "Done!"
|
echo "Done!"
|
||||||
|
9
.github/workflows/backend.yml
vendored
9
.github/workflows/backend.yml
vendored
@@ -41,8 +41,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: cd packages/backend && yarn
|
run: yarn
|
||||||
|
working-directory: packages/backend
|
||||||
- name: Copy .env-example.test file to .env.test
|
- name: Copy .env-example.test file to .env.test
|
||||||
run: cd packages/backend && cp .env-example.test .env.test
|
run: cp .env-example.test .env.test
|
||||||
|
working-directory: packages/backend
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cd packages/backend && yarn test
|
run: yarn test:coverage
|
||||||
|
working-directory: packages/backend
|
||||||
|
30
.github/workflows/ci.yml
vendored
30
.github/workflows/ci.yml
vendored
@@ -18,11 +18,13 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
cache-dependency-path: yarn.lock
|
cache-dependency-path: packages/backend/yarn.lock
|
||||||
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
||||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
||||||
- run: yarn --frozen-lockfile
|
- run: yarn --frozen-lockfile
|
||||||
- run: cd packages/backend && yarn lint
|
working-directory: packages/backend
|
||||||
|
- run: yarn lint
|
||||||
|
working-directory: packages/backend
|
||||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||||
start-backend-server:
|
start-backend-server:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -35,11 +37,13 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
cache-dependency-path: yarn.lock
|
cache-dependency-path: packages/backend/yarn.lock
|
||||||
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
||||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
||||||
- run: yarn --frozen-lockfile && yarn lerna bootstrap
|
- run: yarn --frozen-lockfile
|
||||||
- run: cd packages/backend && yarn start
|
working-directory: packages/backend
|
||||||
|
- run: yarn start
|
||||||
|
working-directory: packages/backend
|
||||||
env:
|
env:
|
||||||
ENCRYPTION_KEY: sample_encryption_key
|
ENCRYPTION_KEY: sample_encryption_key
|
||||||
WEBHOOK_SECRET_KEY: sample_webhook_secret_key
|
WEBHOOK_SECRET_KEY: sample_webhook_secret_key
|
||||||
@@ -55,11 +59,13 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
cache-dependency-path: yarn.lock
|
cache-dependency-path: packages/backend/yarn.lock
|
||||||
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
||||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
||||||
- run: yarn --frozen-lockfile && yarn lerna bootstrap
|
- run: yarn --frozen-lockfile
|
||||||
- run: cd packages/backend && yarn start:worker
|
working-directory: packages/backend
|
||||||
|
- run: yarn start:worker
|
||||||
|
working-directory: packages/backend
|
||||||
env:
|
env:
|
||||||
ENCRYPTION_KEY: sample_encryption_key
|
ENCRYPTION_KEY: sample_encryption_key
|
||||||
WEBHOOK_SECRET_KEY: sample_webhook_secret_key
|
WEBHOOK_SECRET_KEY: sample_webhook_secret_key
|
||||||
@@ -75,11 +81,13 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
cache-dependency-path: yarn.lock
|
cache-dependency-path: packages/web/yarn.lock
|
||||||
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
|
||||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
||||||
- run: yarn --frozen-lockfile && yarn lerna bootstrap
|
- run: yarn --frozen-lockfile
|
||||||
- run: cd packages/web && yarn build
|
working-directory: packages/web
|
||||||
|
- run: yarn build
|
||||||
|
working-directory: packages/web
|
||||||
env:
|
env:
|
||||||
CI: false
|
CI: false
|
||||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||||
|
17
.github/workflows/playwright.yml
vendored
17
.github/workflows/playwright.yml
vendored
@@ -58,22 +58,27 @@ jobs:
|
|||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
- name: Install dependencies
|
- name: Install web dependencies
|
||||||
run: yarn && yarn lerna bootstrap
|
run: yarn
|
||||||
|
working-directory: ./packages/web
|
||||||
|
- name: Install backend dependencies
|
||||||
|
run: yarn
|
||||||
|
working-directory: ./packages/backend
|
||||||
|
- name: Install e2e-tests dependencies
|
||||||
|
run: yarn
|
||||||
|
working-directory: ./packages/e2e-tests
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
run: yarn playwright install --with-deps
|
run: yarn playwright install --with-deps
|
||||||
|
working-directory: ./packages/e2e-tests
|
||||||
- name: Build Automatisch web
|
- name: Build Automatisch web
|
||||||
working-directory: ./packages/web
|
|
||||||
run: yarn build
|
run: yarn build
|
||||||
|
working-directory: ./packages/web
|
||||||
env:
|
env:
|
||||||
# Keep this until we clean up warnings in build processes
|
# Keep this until we clean up warnings in build processes
|
||||||
CI: false
|
CI: false
|
||||||
- name: Migrate database
|
- name: Migrate database
|
||||||
working-directory: ./packages/backend
|
working-directory: ./packages/backend
|
||||||
run: yarn db:migrate
|
run: yarn db:migrate
|
||||||
- name: Seed user
|
|
||||||
working-directory: ./packages/backend
|
|
||||||
run: yarn db:seed:user &
|
|
||||||
- name: Install certutils
|
- name: Install certutils
|
||||||
run: sudo apt install -y libnss3-tools
|
run: sudo apt install -y libnss3-tools
|
||||||
- name: Install mkcert
|
- name: Install mkcert
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,7 +4,6 @@ logs
|
|||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
lerna-debug.log*
|
|
||||||
.pnpm-debug.log*
|
.pnpm-debug.log*
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
@@ -1,20 +1,22 @@
|
|||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
FROM node:18-alpine
|
FROM node:18-alpine
|
||||||
|
|
||||||
ENV PORT 3000
|
ENV PORT=3000
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
apk --no-cache add --virtual build-dependencies python3 build-base git
|
apk --no-cache add --virtual build-dependencies python3 build-base git make g++
|
||||||
|
|
||||||
WORKDIR /automatisch
|
WORKDIR /automatisch
|
||||||
|
|
||||||
# copy the app, note .dockerignore
|
# copy the app, note .dockerignore
|
||||||
COPY . /automatisch
|
COPY . /automatisch
|
||||||
|
|
||||||
RUN yarn
|
RUN cd packages/web && yarn
|
||||||
|
|
||||||
RUN cd packages/web && yarn build
|
RUN cd packages/web && yarn build
|
||||||
|
|
||||||
|
RUN cd packages/backend && yarn --production
|
||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
rm -rf /usr/local/share/.cache/ && \
|
rm -rf /usr/local/share/.cache/ && \
|
||||||
apk del build-dependencies
|
apk del build-dependencies
|
||||||
|
13
lerna.json
13
lerna.json
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"packages": [
|
|
||||||
"packages/*"
|
|
||||||
],
|
|
||||||
"version": "0.10.0",
|
|
||||||
"npmClient": "yarn",
|
|
||||||
"useWorkspaces": true,
|
|
||||||
"command": {
|
|
||||||
"add": {
|
|
||||||
"exact": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
32
package.json
32
package.json
@@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@automatisch/root",
|
|
||||||
"license": "See LICENSE file",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"start": "lerna run --stream --parallel --scope=@*/{web,backend} dev",
|
|
||||||
"start:web": "lerna run --stream --scope=@*/web dev",
|
|
||||||
"start:backend": "lerna run --stream --scope=@*/backend dev",
|
|
||||||
"build:docs": "cd ./packages/docs && yarn install && yarn build"
|
|
||||||
},
|
|
||||||
"workspaces": {
|
|
||||||
"packages": [
|
|
||||||
"packages/*"
|
|
||||||
],
|
|
||||||
"nohoist": [
|
|
||||||
"**/babel-loader",
|
|
||||||
"**/webpack",
|
|
||||||
"**/@automatisch/web",
|
|
||||||
"**/ajv"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"eslint": "^8.13.0",
|
|
||||||
"eslint-config-prettier": "^8.3.0",
|
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
|
||||||
"lerna": "^4.0.0",
|
|
||||||
"prettier": "^2.5.1"
|
|
||||||
},
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
}
|
|
||||||
}
|
|
@@ -10,7 +10,7 @@ import process from 'process';
|
|||||||
async function fetchAdminRole() {
|
async function fetchAdminRole() {
|
||||||
const role = await Role.query()
|
const role = await Role.query()
|
||||||
.where({
|
.where({
|
||||||
key: 'admin',
|
name: 'Admin',
|
||||||
})
|
})
|
||||||
.limit(1)
|
.limit(1)
|
||||||
.first();
|
.first();
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { knexSnakeCaseMappers } from 'objection';
|
import { knexSnakeCaseMappers } from 'objection';
|
||||||
import appConfig from './src/config/app.js';
|
import appConfig from './src/config/app.js';
|
||||||
import path from 'path';
|
import path, { join } from 'path';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
const fileExtension = 'js';
|
const fileExtension = 'js';
|
||||||
@@ -20,12 +20,12 @@ const knexConfig = {
|
|||||||
searchPath: [appConfig.postgresSchema],
|
searchPath: [appConfig.postgresSchema],
|
||||||
pool: { min: 0, max: 20 },
|
pool: { min: 0, max: 20 },
|
||||||
migrations: {
|
migrations: {
|
||||||
directory: __dirname + '/src/db/migrations',
|
directory: join(__dirname, '/src/db/migrations'),
|
||||||
extension: fileExtension,
|
extension: fileExtension,
|
||||||
loadExtensions: [`.${fileExtension}`],
|
loadExtensions: [`.${fileExtension}`],
|
||||||
},
|
},
|
||||||
seeds: {
|
seeds: {
|
||||||
directory: __dirname + '/src/db/seeds',
|
directory: join(__dirname, '/src/db/seeds'),
|
||||||
},
|
},
|
||||||
...(appConfig.isTest ? knexSnakeCaseMappers() : {}),
|
...(appConfig.isTest ? knexSnakeCaseMappers() : {}),
|
||||||
};
|
};
|
||||||
|
@@ -5,12 +5,14 @@
|
|||||||
"description": "The open source Zapier alternative. Build workflow automation without spending time and money.",
|
"description": "The open source Zapier alternative. Build workflow automation without spending time and money.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nodemon --watch 'src/**/*.js' --exec 'node' src/server.js",
|
"dev": "nodemon --exec node src/server.js",
|
||||||
"worker": "nodemon --watch 'src/**/*.js' --exec 'node' src/worker.js",
|
"worker": "nodemon --exec node src/worker.js",
|
||||||
"start": "node src/server.js",
|
"start": "node src/server.js",
|
||||||
"start:worker": "node src/worker.js",
|
"start:worker": "node src/worker.js",
|
||||||
"pretest": "APP_ENV=test node ./test/setup/prepare-test-env.js",
|
"pretest": "APP_ENV=test node ./test/setup/prepare-test-env.js",
|
||||||
"test": "APP_ENV=test vitest run",
|
"test": "APP_ENV=test vitest run",
|
||||||
|
"test:watch": "APP_ENV=test vitest watch",
|
||||||
|
"test:coverage": "yarn test --coverage",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"db:create": "node ./bin/database/create.js",
|
"db:create": "node ./bin/database/create.js",
|
||||||
"db:seed:user": "node ./bin/database/seed-user.js",
|
"db:seed:user": "node ./bin/database/seed-user.js",
|
||||||
@@ -22,8 +24,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bull-board/express": "^3.10.1",
|
"@bull-board/express": "^3.10.1",
|
||||||
"@casl/ability": "^6.5.0",
|
"@casl/ability": "^6.5.0",
|
||||||
"@graphql-tools/graphql-file-loader": "^7.3.4",
|
"@faker-js/faker": "^9.2.0",
|
||||||
"@graphql-tools/load": "^7.5.2",
|
|
||||||
"@node-saml/passport-saml": "^4.0.4",
|
"@node-saml/passport-saml": "^4.0.4",
|
||||||
"@rudderstack/rudder-sdk-node": "^1.1.2",
|
"@rudderstack/rudder-sdk-node": "^1.1.2",
|
||||||
"@sentry/node": "^7.42.0",
|
"@sentry/node": "^7.42.0",
|
||||||
@@ -37,18 +38,18 @@
|
|||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"debug": "~2.6.9",
|
"debug": "~2.6.9",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
|
"eslint": "^8.13.0",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"express": "~4.18.2",
|
"express": "~4.18.2",
|
||||||
"express-async-handler": "^1.2.0",
|
"express-async-errors": "^3.1.1",
|
||||||
"express-basic-auth": "^1.2.1",
|
"express-basic-auth": "^1.2.1",
|
||||||
"express-graphql": "^0.12.0",
|
|
||||||
"fast-xml-parser": "^4.0.11",
|
"fast-xml-parser": "^4.0.11",
|
||||||
"graphql-middleware": "^6.1.15",
|
|
||||||
"graphql-shield": "^7.5.0",
|
|
||||||
"graphql-tools": "^8.2.0",
|
|
||||||
"handlebars": "^4.7.7",
|
"handlebars": "^4.7.7",
|
||||||
"http-errors": "~1.6.3",
|
"http-errors": "~1.6.3",
|
||||||
"http-proxy-agent": "^7.0.0",
|
"http-proxy-agent": "^7.0.0",
|
||||||
"https-proxy-agent": "^7.0.1",
|
"https-proxy-agent": "^7.0.1",
|
||||||
|
"isolated-vm": "^5.0.1",
|
||||||
"jsonwebtoken": "^9.0.0",
|
"jsonwebtoken": "^9.0.0",
|
||||||
"knex": "^2.4.0",
|
"knex": "^2.4.0",
|
||||||
"libphonenumber-js": "^1.10.48",
|
"libphonenumber-js": "^1.10.48",
|
||||||
@@ -65,6 +66,7 @@
|
|||||||
"pg": "^8.7.1",
|
"pg": "^8.7.1",
|
||||||
"php-serialize": "^4.0.2",
|
"php-serialize": "^4.0.2",
|
||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
|
"prettier": "^2.5.1",
|
||||||
"raw-body": "^2.5.2",
|
"raw-body": "^2.5.2",
|
||||||
"showdown": "^2.1.0",
|
"showdown": "^2.1.0",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
@@ -96,12 +98,19 @@
|
|||||||
"url": "https://github.com/automatisch/automatisch/issues"
|
"url": "https://github.com/automatisch/automatisch/issues"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@vitest/coverage-v8": "^2.1.5",
|
||||||
"node-gyp": "^10.1.0",
|
"node-gyp": "^10.1.0",
|
||||||
"nodemon": "^2.0.13",
|
"nodemon": "^2.0.13",
|
||||||
"supertest": "^6.3.3",
|
"supertest": "^6.3.3",
|
||||||
"vitest": "^1.1.3"
|
"vitest": "^2.1.5"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
},
|
||||||
|
"nodemonConfig": {
|
||||||
|
"watch": [
|
||||||
|
"src/"
|
||||||
|
],
|
||||||
|
"ext": "js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import createError from 'http-errors';
|
import createError from 'http-errors';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
|
import 'express-async-errors';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
|
|
||||||
import appConfig from './config/app.js';
|
import appConfig from './config/app.js';
|
||||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://api.airtable.com',
|
apiBaseUrl: 'https://api.airtable.com',
|
||||||
iconUrl: '{BASE_URL}/apps/airtable/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/airtable/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/airtable/connection',
|
authDocUrl: '{DOCS_URL}/apps/airtable/connection',
|
||||||
primaryColor: 'FFBF00',
|
primaryColor: '#FFBF00',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://cloud.appwrite.io',
|
apiBaseUrl: 'https://cloud.appwrite.io',
|
||||||
iconUrl: '{BASE_URL}/apps/appwrite/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/appwrite/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/appwrite/connection',
|
authDocUrl: '{DOCS_URL}/apps/appwrite/connection',
|
||||||
primaryColor: 'FD366E',
|
primaryColor: '#FD366E',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
iconUrl: '{BASE_URL}/apps/azure-openai/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/azure-openai/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/azure-openai/connection',
|
authDocUrl: '{DOCS_URL}/apps/azure-openai/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -7,7 +7,7 @@ export default defineAction({
|
|||||||
'Creates an attachment of a specified object by given parent ID.',
|
'Creates an attachment of a specified object by given parent ID.',
|
||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
label: 'Templete Data',
|
label: 'Template Data',
|
||||||
key: 'templateData',
|
key: 'templateData',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: true,
|
required: true,
|
||||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://carbone.io',
|
baseUrl: 'https://carbone.io',
|
||||||
apiBaseUrl: 'https://api.carbone.io',
|
apiBaseUrl: 'https://api.carbone.io',
|
||||||
primaryColor: '6f42c1',
|
primaryColor: '#6f42c1',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
@@ -0,0 +1,72 @@
|
|||||||
|
import defineAction from '../../../../helpers/define-action.js';
|
||||||
|
|
||||||
|
export default defineAction({
|
||||||
|
name: 'Create folder',
|
||||||
|
key: 'createFolder',
|
||||||
|
description: 'Creates a new folder.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Workspace',
|
||||||
|
key: 'workspaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listWorkspaces',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Space',
|
||||||
|
key: 'spaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
dependsOn: ['parameters.workspaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listSpaces',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.workspaceId',
|
||||||
|
value: '{parameters.workspaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Folder Name',
|
||||||
|
key: 'folderName',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const { spaceId, folderName } = $.step.parameters;
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
name: folderName,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data } = await $.http.post(`/v2/space/${spaceId}/folder`, body);
|
||||||
|
|
||||||
|
$.setActionItem({
|
||||||
|
raw: data,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
135
packages/backend/src/apps/clickup/actions/create-list/index.js
Normal file
135
packages/backend/src/apps/clickup/actions/create-list/index.js
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import defineAction from '../../../../helpers/define-action.js';
|
||||||
|
|
||||||
|
export default defineAction({
|
||||||
|
name: 'Create list',
|
||||||
|
key: 'createList',
|
||||||
|
description: 'Creates a new list.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Workspace',
|
||||||
|
key: 'workspaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listWorkspaces',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Space',
|
||||||
|
key: 'spaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
dependsOn: ['parameters.workspaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listSpaces',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.workspaceId',
|
||||||
|
value: '{parameters.workspaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Folder',
|
||||||
|
key: 'folderId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
dependsOn: ['parameters.spaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listFolders',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.spaceId',
|
||||||
|
value: '{parameters.spaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'List Name',
|
||||||
|
key: 'listName',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'List Info',
|
||||||
|
key: 'listInfo',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Priority',
|
||||||
|
key: 'priority',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
options: [
|
||||||
|
{ label: 'Urgent', value: 1 },
|
||||||
|
{ label: 'High', value: 2 },
|
||||||
|
{ label: 'Normal', value: 3 },
|
||||||
|
{ label: 'Low', value: 4 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Due Date',
|
||||||
|
key: 'dueDate',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
description: 'format: integer <int64>',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const { folderId, listName, listInfo, priority, dueDate } =
|
||||||
|
$.step.parameters;
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
name: listName,
|
||||||
|
content: listInfo,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (priority) {
|
||||||
|
body.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dueDate) {
|
||||||
|
body.due_date = dueDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.post(`/v2/folder/${folderId}/list`, body);
|
||||||
|
|
||||||
|
$.setActionItem({
|
||||||
|
raw: data,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
294
packages/backend/src/apps/clickup/actions/create-task/index.js
Normal file
294
packages/backend/src/apps/clickup/actions/create-task/index.js
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
import defineAction from '../../../../helpers/define-action.js';
|
||||||
|
|
||||||
|
export default defineAction({
|
||||||
|
name: 'Create task',
|
||||||
|
key: 'createTask',
|
||||||
|
description: 'Creates a new task.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Workspace',
|
||||||
|
key: 'workspaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listWorkspaces',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Space',
|
||||||
|
key: 'spaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
dependsOn: ['parameters.workspaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listSpaces',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.workspaceId',
|
||||||
|
value: '{parameters.workspaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Folder',
|
||||||
|
key: 'folderId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
dependsOn: ['parameters.spaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listFolders',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.spaceId',
|
||||||
|
value: '{parameters.spaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'List',
|
||||||
|
key: 'listId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
dependsOn: ['parameters.folderId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listLists',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.folderId',
|
||||||
|
value: '{parameters.folderId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Task Name',
|
||||||
|
key: 'taskName',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Task Description',
|
||||||
|
key: 'taskDescription',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Markdown Content',
|
||||||
|
key: 'markdownContent',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
options: [
|
||||||
|
{ label: 'False', value: 'false' },
|
||||||
|
{ label: 'True', value: 'true' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Assignees',
|
||||||
|
key: 'assigneeIds',
|
||||||
|
type: 'dynamic',
|
||||||
|
required: false,
|
||||||
|
description: '',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
label: 'Assignee',
|
||||||
|
key: 'assigneeId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.listId'],
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listAssignees',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.listId',
|
||||||
|
value: '{parameters.listId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Task Status',
|
||||||
|
key: 'taskStatus',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.listId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listStatuses',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.listId',
|
||||||
|
value: '{parameters.listId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Tags',
|
||||||
|
key: 'tagIds',
|
||||||
|
type: 'dynamic',
|
||||||
|
required: false,
|
||||||
|
description: '',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
label: 'tag',
|
||||||
|
key: 'tagId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listTags',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Priority',
|
||||||
|
key: 'priority',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
options: [
|
||||||
|
{ label: 'Urgent', value: 1 },
|
||||||
|
{ label: 'High', value: 2 },
|
||||||
|
{ label: 'Normal', value: 3 },
|
||||||
|
{ label: 'Low', value: 4 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Due Date',
|
||||||
|
key: 'dueDate',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
description: 'format: integer <int64>',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Start Date',
|
||||||
|
key: 'startDate',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
description: 'format: integer <int64>',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const {
|
||||||
|
listId,
|
||||||
|
taskName,
|
||||||
|
taskDescription,
|
||||||
|
markdownContent,
|
||||||
|
assigneeIds,
|
||||||
|
taskStatus,
|
||||||
|
tagIds,
|
||||||
|
priority,
|
||||||
|
dueDate,
|
||||||
|
startDate,
|
||||||
|
} = $.step.parameters;
|
||||||
|
|
||||||
|
const tags = tagIds.map((tag) => tag.tagId);
|
||||||
|
const assignees = assigneeIds.map((assignee) =>
|
||||||
|
Number(assignee.assigneeId)
|
||||||
|
);
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
name: taskName,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (assignees.length) {
|
||||||
|
body.assignees = assignees;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taskStatus) {
|
||||||
|
body.status = taskStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tags.length) {
|
||||||
|
body.tags = tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priority) {
|
||||||
|
body.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dueDate) {
|
||||||
|
body.due_date = dueDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startDate) {
|
||||||
|
body.start_date = startDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (markdownContent) {
|
||||||
|
body.markdown_description = taskDescription;
|
||||||
|
} else {
|
||||||
|
body.description = taskDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.post(`/v2/list/${listId}/task`, body);
|
||||||
|
|
||||||
|
$.setActionItem({
|
||||||
|
raw: data,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
@@ -0,0 +1,82 @@
|
|||||||
|
import defineAction from '../../../../helpers/define-action.js';
|
||||||
|
|
||||||
|
export default defineAction({
|
||||||
|
name: 'Find task by id',
|
||||||
|
key: 'findTaskById',
|
||||||
|
description: 'Finds a task using id.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Task ID',
|
||||||
|
key: 'taskId',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Use Custom ID',
|
||||||
|
key: 'useCustomId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'True',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'False',
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
additionalFields: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicFields',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listFieldsWhenUsingCustomId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.useCustomId',
|
||||||
|
value: '{parameters.useCustomId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Include Subtasks?',
|
||||||
|
key: 'includeSubtasks',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'True',
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'False',
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const { taskId, useCustomId, includeSubtasks } = $.step.parameters;
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
custom_task_ids: useCustomId || false,
|
||||||
|
include_subtasks: includeSubtasks,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data } = await $.http.get(`/v2/task/${taskId}`, { params });
|
||||||
|
|
||||||
|
$.setActionItem({
|
||||||
|
raw: data,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
6
packages/backend/src/apps/clickup/actions/index.js
Normal file
6
packages/backend/src/apps/clickup/actions/index.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import createFolder from './create-folder/index.js';
|
||||||
|
import createList from './create-list/index.js';
|
||||||
|
import createTask from './create-task/index.js';
|
||||||
|
import findTaskById from './find-task-by-id/index.js';
|
||||||
|
|
||||||
|
export default [createFolder, createList, createTask, findTaskById];
|
27
packages/backend/src/apps/clickup/assets/favicon.svg
Normal file
27
packages/backend/src/apps/clickup/assets/favicon.svg
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<svg width="185" height="185" viewBox="0 0 185 185" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g filter="url(#filter0_d)">
|
||||||
|
<rect x="30" y="20" width="125" height="125" rx="62.5" fill="white"/>
|
||||||
|
<rect x="30" y="20" width="125" height="125" rx="62.5" fill="white"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M55.8789 105.714L69.3974 95.3593C76.5762 104.732 84.1998 109.051 92.6948 109.051C101.143 109.051 108.557 104.781 115.414 95.4832L129.119 105.59C119.232 118.996 106.932 126.079 92.6948 126.079C78.5049 126.079 66.0907 119.046 55.8789 105.714Z" fill="url(#paint0_linear)"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M92.6491 60.7078L68.5883 81.4406L57.4727 68.5407L92.6969 38.1885L127.647 68.5644L116.477 81.417L92.6491 60.7078Z" fill="url(#paint1_linear)"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<filter id="filter0_d" x="0" y="0" width="185" height="185" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||||
|
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||||
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||||
|
<feOffset dy="10"/>
|
||||||
|
<feGaussianBlur stdDeviation="15"/>
|
||||||
|
<feColorMatrix type="matrix" values="0 0 0 0 0.0627451 0 0 0 0 0.117647 0 0 0 0 0.211765 0 0 0 0.1 0"/>
|
||||||
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||||
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
|
||||||
|
</filter>
|
||||||
|
<linearGradient id="paint0_linear" x1="55.8789" y1="116.251" x2="129.119" y2="116.251" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#8930FD"/>
|
||||||
|
<stop offset="1" stop-color="#49CCF9"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear" x1="57.4727" y1="67.6025" x2="127.647" y2="67.6025" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#FF02F0"/>
|
||||||
|
<stop offset="1" stop-color="#FFC800"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
21
packages/backend/src/apps/clickup/auth/generate-auth-url.js
Normal file
21
packages/backend/src/apps/clickup/auth/generate-auth-url.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { URLSearchParams } from 'url';
|
||||||
|
|
||||||
|
export default async function generateAuthUrl($) {
|
||||||
|
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||||
|
(field) => field.key == 'oAuthRedirectUrl'
|
||||||
|
);
|
||||||
|
const redirectUri = oauthRedirectUrlField.value;
|
||||||
|
const state = Math.random().toString();
|
||||||
|
const searchParams = new URLSearchParams({
|
||||||
|
client_id: $.auth.data.clientId,
|
||||||
|
redirect_uri: redirectUri,
|
||||||
|
state,
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = `https://app.clickup.com/api?${searchParams.toString()}`;
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
url,
|
||||||
|
originalState: state,
|
||||||
|
});
|
||||||
|
}
|
46
packages/backend/src/apps/clickup/auth/index.js
Normal file
46
packages/backend/src/apps/clickup/auth/index.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import generateAuthUrl from './generate-auth-url.js';
|
||||||
|
import verifyCredentials from './verify-credentials.js';
|
||||||
|
import isStillVerified from './is-still-verified.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
key: 'oAuthRedirectUrl',
|
||||||
|
label: 'OAuth Redirect URL',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: true,
|
||||||
|
value: '{WEB_APP_URL}/app/clickup/connections/add',
|
||||||
|
placeholder: null,
|
||||||
|
description:
|
||||||
|
'When asked to input a redirect URL in ClickUp, enter the URL above.',
|
||||||
|
clickToCopy: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'clientId',
|
||||||
|
label: 'Client ID',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
description: null,
|
||||||
|
clickToCopy: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'clientSecret',
|
||||||
|
label: 'Client Secret',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
description: null,
|
||||||
|
clickToCopy: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
generateAuthUrl,
|
||||||
|
verifyCredentials,
|
||||||
|
isStillVerified,
|
||||||
|
};
|
@@ -0,0 +1,8 @@
|
|||||||
|
import getCurrentUser from '../common/get-current-user.js';
|
||||||
|
|
||||||
|
const isStillVerified = async ($) => {
|
||||||
|
const currentUser = await getCurrentUser($);
|
||||||
|
return !!currentUser.id;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default isStillVerified;
|
31
packages/backend/src/apps/clickup/auth/verify-credentials.js
Normal file
31
packages/backend/src/apps/clickup/auth/verify-credentials.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import getCurrentUser from '../common/get-current-user.js';
|
||||||
|
|
||||||
|
const verifyCredentials = async ($) => {
|
||||||
|
if ($.auth.data.originalState !== $.auth.data.state) {
|
||||||
|
throw new Error(`The 'state' parameter does not match.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.post('/v2/oauth/token', {
|
||||||
|
client_id: $.auth.data.clientId,
|
||||||
|
client_secret: $.auth.data.clientSecret,
|
||||||
|
code: $.auth.data.code,
|
||||||
|
});
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
accessToken: data.access_token,
|
||||||
|
tokenType: data.token_type,
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentUser = await getCurrentUser($);
|
||||||
|
const screenName = [currentUser.username, currentUser.email]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' @ ');
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
clientId: $.auth.data.clientId,
|
||||||
|
clientSecret: $.auth.data.clientSecret,
|
||||||
|
screenName,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default verifyCredentials;
|
@@ -0,0 +1,9 @@
|
|||||||
|
const addAuthHeader = ($, requestConfig) => {
|
||||||
|
if ($.auth.data?.accessToken) {
|
||||||
|
requestConfig.headers.Authorization = `${$.auth.data.tokenType} ${$.auth.data.accessToken}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default addAuthHeader;
|
@@ -0,0 +1,6 @@
|
|||||||
|
const getCurrentUser = async ($) => {
|
||||||
|
const { data } = await $.http.get('/v2/user');
|
||||||
|
return data.user;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getCurrentUser;
|
19
packages/backend/src/apps/clickup/dynamic-data/index.js
Normal file
19
packages/backend/src/apps/clickup/dynamic-data/index.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import listAssignees from './list-assignees/index.js';
|
||||||
|
import listFolders from './list-folders/index.js';
|
||||||
|
import listLists from './list-lists/index.js';
|
||||||
|
import listSpaces from './list-spaces/index.js';
|
||||||
|
import listStatuses from './list-statuses/index.js';
|
||||||
|
import listTags from './list-tags/index.js';
|
||||||
|
import listTasks from './list-tasks/index.js';
|
||||||
|
import listWorkspaces from './list-workspaces/index.js';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
listAssignees,
|
||||||
|
listFolders,
|
||||||
|
listLists,
|
||||||
|
listSpaces,
|
||||||
|
listStatuses,
|
||||||
|
listTags,
|
||||||
|
listTasks,
|
||||||
|
listWorkspaces,
|
||||||
|
];
|
@@ -0,0 +1,28 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List assignees',
|
||||||
|
key: 'listAssignees',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const assignees = {
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
const listId = $.step.parameters.listId;
|
||||||
|
|
||||||
|
if (!listId) {
|
||||||
|
return assignees;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.get(`/v2/list/${listId}/member`);
|
||||||
|
|
||||||
|
if (data.members) {
|
||||||
|
for (const member of data.members) {
|
||||||
|
assignees.data.push({
|
||||||
|
value: member.id,
|
||||||
|
name: member.username,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return assignees;
|
||||||
|
},
|
||||||
|
};
|
@@ -0,0 +1,28 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List folders',
|
||||||
|
key: 'listFolders',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const folders = {
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
const spaceId = $.step.parameters.spaceId;
|
||||||
|
|
||||||
|
if (!spaceId) {
|
||||||
|
return folders;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.get(`/v2/space/${spaceId}/folder`);
|
||||||
|
|
||||||
|
if (data.folders) {
|
||||||
|
for (const folder of data.folders) {
|
||||||
|
folders.data.push({
|
||||||
|
value: folder.id,
|
||||||
|
name: folder.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return folders;
|
||||||
|
},
|
||||||
|
};
|
@@ -0,0 +1,28 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List lists',
|
||||||
|
key: 'listLists',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const lists = {
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
const folderId = $.step.parameters.folderId;
|
||||||
|
|
||||||
|
if (!folderId) {
|
||||||
|
return lists;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.get(`/v2/folder/${folderId}/list`);
|
||||||
|
|
||||||
|
if (data.lists) {
|
||||||
|
for (const list of data.lists) {
|
||||||
|
lists.data.push({
|
||||||
|
value: list.id,
|
||||||
|
name: list.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lists;
|
||||||
|
},
|
||||||
|
};
|
@@ -0,0 +1,28 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List spaces',
|
||||||
|
key: 'listSpaces',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const spaces = {
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
const workspaceId = $.step.parameters.workspaceId;
|
||||||
|
|
||||||
|
if (!workspaceId) {
|
||||||
|
return spaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.get(`/v2/team/${workspaceId}/space`);
|
||||||
|
|
||||||
|
if (data.spaces) {
|
||||||
|
for (const space of data.spaces) {
|
||||||
|
spaces.data.push({
|
||||||
|
value: space.id,
|
||||||
|
name: space.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return spaces;
|
||||||
|
},
|
||||||
|
};
|
@@ -0,0 +1,28 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List statuses',
|
||||||
|
key: 'listStatuses',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const statuses = {
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
const listId = $.step.parameters.listId;
|
||||||
|
|
||||||
|
if (!listId) {
|
||||||
|
return statuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.get(`/v2/list/${listId}`);
|
||||||
|
|
||||||
|
if (data.statuses) {
|
||||||
|
for (const status of data.statuses) {
|
||||||
|
statuses.data.push({
|
||||||
|
value: status.status,
|
||||||
|
name: status.status,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return statuses;
|
||||||
|
},
|
||||||
|
};
|
@@ -0,0 +1,28 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List tags',
|
||||||
|
key: 'listTags',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const tags = {
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
const spaceId = $.step.parameters.spaceId;
|
||||||
|
|
||||||
|
if (!spaceId) {
|
||||||
|
return spaceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.get(`v2/space/${spaceId}/tag`);
|
||||||
|
|
||||||
|
if (data.tags) {
|
||||||
|
for (const tag of data.tags) {
|
||||||
|
tags.data.push({
|
||||||
|
value: tag.name,
|
||||||
|
name: tag.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags;
|
||||||
|
},
|
||||||
|
};
|
@@ -0,0 +1,41 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List tasks',
|
||||||
|
key: 'listTasks',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const tasks = {
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
const listId = $.step.parameters.listId;
|
||||||
|
let next = false;
|
||||||
|
|
||||||
|
if (!listId) {
|
||||||
|
return tasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
order_by: 'created',
|
||||||
|
reverse: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
do {
|
||||||
|
const { data } = await $.http.get(`/v2/list/${listId}/task`, { params });
|
||||||
|
if (data.last_page) {
|
||||||
|
next = false;
|
||||||
|
} else {
|
||||||
|
next = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.tasks) {
|
||||||
|
for (const task of data.tasks) {
|
||||||
|
tasks.data.push({
|
||||||
|
value: task.id,
|
||||||
|
name: task.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (next);
|
||||||
|
|
||||||
|
return tasks;
|
||||||
|
},
|
||||||
|
};
|
@@ -0,0 +1,23 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List workspaces',
|
||||||
|
key: 'listWorkspaces',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const workspaces = {
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data } = await $.http.get('/v2/team');
|
||||||
|
|
||||||
|
if (data.teams) {
|
||||||
|
for (const workspace of data.teams) {
|
||||||
|
workspaces.data.push({
|
||||||
|
value: workspace.id,
|
||||||
|
name: workspace.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return workspaces;
|
||||||
|
},
|
||||||
|
};
|
@@ -0,0 +1,3 @@
|
|||||||
|
import useCustomId from './use-custom-id/index.js';
|
||||||
|
|
||||||
|
export default [useCustomId];
|
@@ -0,0 +1,29 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List workspaces when using custom id',
|
||||||
|
key: 'listFieldsWhenUsingCustomId',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
if ($.step.parameters.useCustomId) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: 'Workspace',
|
||||||
|
key: 'workspaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listWorkspaces',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
24
packages/backend/src/apps/clickup/index.js
Normal file
24
packages/backend/src/apps/clickup/index.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import defineApp from '../../helpers/define-app.js';
|
||||||
|
import addAuthHeader from './common/add-auth-header.js';
|
||||||
|
import auth from './auth/index.js';
|
||||||
|
import triggers from './triggers/index.js';
|
||||||
|
import dynamicData from './dynamic-data/index.js';
|
||||||
|
import actions from './actions/index.js';
|
||||||
|
import dynamicFields from './dynamic-fields/index.js';
|
||||||
|
|
||||||
|
export default defineApp({
|
||||||
|
name: 'ClickUp',
|
||||||
|
key: 'clickup',
|
||||||
|
baseUrl: 'https://clickup.com',
|
||||||
|
apiBaseUrl: 'https://api.clickup.com/api',
|
||||||
|
iconUrl: '{BASE_URL}/apps/clickup/assets/favicon.svg',
|
||||||
|
authDocUrl: '{DOCS_URL}/apps/clickup/connection',
|
||||||
|
primaryColor: '#FD71AF',
|
||||||
|
supportsConnections: true,
|
||||||
|
beforeRequest: [addAuthHeader],
|
||||||
|
auth,
|
||||||
|
triggers,
|
||||||
|
dynamicData,
|
||||||
|
actions,
|
||||||
|
dynamicFields,
|
||||||
|
});
|
6
packages/backend/src/apps/clickup/triggers/index.js
Normal file
6
packages/backend/src/apps/clickup/triggers/index.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import newFolders from './new-folders/index.js';
|
||||||
|
import newLists from './new-lists/index.js';
|
||||||
|
import newTasks from './new-tasks/index.js';
|
||||||
|
import updatedTask from './updated-task/index.js';
|
||||||
|
|
||||||
|
export default [newFolders, newLists, newTasks, updatedTask];
|
105
packages/backend/src/apps/clickup/triggers/new-folders/index.js
Normal file
105
packages/backend/src/apps/clickup/triggers/new-folders/index.js
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import Crypto from 'crypto';
|
||||||
|
import defineTrigger from '../../../../helpers/define-trigger.js';
|
||||||
|
|
||||||
|
export default defineTrigger({
|
||||||
|
name: 'New folders',
|
||||||
|
key: 'newFolder',
|
||||||
|
type: 'webhook',
|
||||||
|
description: 'Triggers when a new folder is created.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Workspace',
|
||||||
|
key: 'workspaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listWorkspaces',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Space',
|
||||||
|
key: 'spaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.workspaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listSpaces',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.workspaceId',
|
||||||
|
value: '{parameters.workspaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const dataItem = {
|
||||||
|
raw: $.request.body,
|
||||||
|
meta: {
|
||||||
|
internalId: $.request.body.folder_id,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
$.pushTriggerItem(dataItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
async testRun($) {
|
||||||
|
const sampleEventData = {
|
||||||
|
event: 'folderCreated',
|
||||||
|
folder_id: '90180382912',
|
||||||
|
webhook_id: Crypto.randomUUID(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const dataItem = {
|
||||||
|
raw: sampleEventData,
|
||||||
|
meta: {
|
||||||
|
internalId: '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
$.pushTriggerItem(dataItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
async registerHook($) {
|
||||||
|
const { workspaceId, spaceId } = $.step.parameters;
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
name: $.flow.id,
|
||||||
|
endpoint: $.webhookUrl,
|
||||||
|
events: ['folderCreated'],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (spaceId) {
|
||||||
|
payload.space_id = spaceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.post(
|
||||||
|
`/v2/team/${workspaceId}/webhook`,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
|
||||||
|
await $.flow.setRemoteWebhookId(data.id);
|
||||||
|
},
|
||||||
|
|
||||||
|
async unregisterHook($) {
|
||||||
|
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
|
||||||
|
},
|
||||||
|
});
|
129
packages/backend/src/apps/clickup/triggers/new-lists/index.js
Normal file
129
packages/backend/src/apps/clickup/triggers/new-lists/index.js
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import Crypto from 'crypto';
|
||||||
|
import defineTrigger from '../../../../helpers/define-trigger.js';
|
||||||
|
|
||||||
|
export default defineTrigger({
|
||||||
|
name: 'New lists',
|
||||||
|
key: 'newLists',
|
||||||
|
type: 'webhook',
|
||||||
|
description: 'Triggers when a new list is created.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Workspace',
|
||||||
|
key: 'workspaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listWorkspaces',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Space',
|
||||||
|
key: 'spaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.workspaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listSpaces',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.workspaceId',
|
||||||
|
value: '{parameters.workspaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Folder',
|
||||||
|
key: 'folderId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.spaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listFolders',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.spaceId',
|
||||||
|
value: '{parameters.spaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const dataItem = {
|
||||||
|
raw: $.request.body,
|
||||||
|
meta: {
|
||||||
|
internalId: $.request.body.list_id,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
$.pushTriggerItem(dataItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
async testRun($) {
|
||||||
|
const sampleEventData = {
|
||||||
|
event: 'listCreated',
|
||||||
|
list_id: '901800588812',
|
||||||
|
webhook_id: Crypto.randomUUID(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const dataItem = {
|
||||||
|
raw: sampleEventData,
|
||||||
|
meta: {
|
||||||
|
internalId: sampleEventData.webhook_id,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
$.pushTriggerItem(dataItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
async registerHook($) {
|
||||||
|
const { workspaceId, spaceId, folderId } = $.step.parameters;
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
name: $.flow.id,
|
||||||
|
endpoint: $.webhookUrl,
|
||||||
|
events: ['listCreated'],
|
||||||
|
space_id: spaceId,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (folderId) {
|
||||||
|
payload.folder_id = folderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.post(
|
||||||
|
`/v2/team/${workspaceId}/webhook`,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
|
||||||
|
await $.flow.setRemoteWebhookId(data.id);
|
||||||
|
},
|
||||||
|
|
||||||
|
async unregisterHook($) {
|
||||||
|
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
|
||||||
|
},
|
||||||
|
});
|
186
packages/backend/src/apps/clickup/triggers/new-tasks/index.js
Normal file
186
packages/backend/src/apps/clickup/triggers/new-tasks/index.js
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
import Crypto from 'crypto';
|
||||||
|
import defineTrigger from '../../../../helpers/define-trigger.js';
|
||||||
|
|
||||||
|
export default defineTrigger({
|
||||||
|
name: 'New tasks',
|
||||||
|
key: 'newTasks',
|
||||||
|
type: 'webhook',
|
||||||
|
description: 'Triggers when a new task is created.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Workspace',
|
||||||
|
key: 'workspaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listWorkspaces',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Space',
|
||||||
|
key: 'spaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.workspaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listSpaces',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.workspaceId',
|
||||||
|
value: '{parameters.workspaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Folder',
|
||||||
|
key: 'folderId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.spaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listFolders',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.spaceId',
|
||||||
|
value: '{parameters.spaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'List',
|
||||||
|
key: 'listId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.folderId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listLists',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.folderId',
|
||||||
|
value: '{parameters.folderId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Task',
|
||||||
|
key: 'taskId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.listId'],
|
||||||
|
description:
|
||||||
|
'Choose an optional task to determine when this flow should be activated. In this scenario, only subtasks will initiate this flow.',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listTasks',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.listId',
|
||||||
|
value: '{parameters.listId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const dataItem = {
|
||||||
|
raw: $.request.body,
|
||||||
|
meta: {
|
||||||
|
internalId: $.request.body.task_id,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
$.pushTriggerItem(dataItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
async testRun($) {
|
||||||
|
const sampleEventData = {
|
||||||
|
event: 'taskCreated',
|
||||||
|
task_id: '86enn7pg7',
|
||||||
|
webhook_id: Crypto.randomUUID(),
|
||||||
|
history_items: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const dataItem = {
|
||||||
|
raw: sampleEventData,
|
||||||
|
meta: {
|
||||||
|
internalId: sampleEventData.webhook_id,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
$.pushTriggerItem(dataItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
async registerHook($) {
|
||||||
|
const { workspaceId, spaceId, folderId, listId, taskId } =
|
||||||
|
$.step.parameters;
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
name: $.flow.id,
|
||||||
|
endpoint: $.webhookUrl,
|
||||||
|
events: ['taskCreated'],
|
||||||
|
space_id: spaceId,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (folderId) {
|
||||||
|
payload.folder_id = folderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listId) {
|
||||||
|
payload.list_id = listId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taskId) {
|
||||||
|
payload.task_id = taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.post(
|
||||||
|
`/v2/team/${workspaceId}/webhook`,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
|
||||||
|
await $.flow.setRemoteWebhookId(data.id);
|
||||||
|
},
|
||||||
|
|
||||||
|
async unregisterHook($) {
|
||||||
|
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
|
||||||
|
},
|
||||||
|
});
|
172
packages/backend/src/apps/clickup/triggers/updated-task/index.js
Normal file
172
packages/backend/src/apps/clickup/triggers/updated-task/index.js
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
import Crypto from 'crypto';
|
||||||
|
import defineTrigger from '../../../../helpers/define-trigger.js';
|
||||||
|
|
||||||
|
export default defineTrigger({
|
||||||
|
name: 'Updated task',
|
||||||
|
key: 'updatedTask',
|
||||||
|
type: 'webhook',
|
||||||
|
description: 'Triggers when a task is updated.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Workspace',
|
||||||
|
key: 'workspaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listWorkspaces',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Space',
|
||||||
|
key: 'spaceId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.workspaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listSpaces',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.workspaceId',
|
||||||
|
value: '{parameters.workspaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Folder',
|
||||||
|
key: 'folderId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.spaceId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listFolders',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.spaceId',
|
||||||
|
value: '{parameters.spaceId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'List',
|
||||||
|
key: 'listId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
dependsOn: ['parameters.folderId'],
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listLists',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.folderId',
|
||||||
|
value: '{parameters.folderId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'What Changed?',
|
||||||
|
key: 'whatChanged',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
variables: true,
|
||||||
|
options: [
|
||||||
|
{ label: 'Status', value: 'taskStatusUpdated' },
|
||||||
|
{ label: 'Assignee Added', value: 'taskAssigneeUpdated' },
|
||||||
|
{ label: 'Priority', value: 'taskPriorityUpdated' },
|
||||||
|
{ label: 'Tag Added', value: 'taskTagUpdated' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const dataItem = {
|
||||||
|
raw: $.request.body,
|
||||||
|
meta: {
|
||||||
|
internalId: Crypto.randomUUID(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
$.pushTriggerItem(dataItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
async testRun($) {
|
||||||
|
const sampleEventData = {
|
||||||
|
event: 'taskUpdated',
|
||||||
|
task_id: '86enn7pg7',
|
||||||
|
webhook_id: Crypto.randomUUID(),
|
||||||
|
history_items: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const dataItem = {
|
||||||
|
raw: sampleEventData,
|
||||||
|
meta: {
|
||||||
|
internalId: sampleEventData.webhook_id,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
$.pushTriggerItem(dataItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
async registerHook($) {
|
||||||
|
const { workspaceId, spaceId, folderId, listId, whatChanged } =
|
||||||
|
$.step.parameters;
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
name: $.flow.id,
|
||||||
|
endpoint: $.webhookUrl,
|
||||||
|
space_id: spaceId,
|
||||||
|
};
|
||||||
|
|
||||||
|
payload.events = [whatChanged || 'taskUpdated'];
|
||||||
|
|
||||||
|
if (folderId) {
|
||||||
|
payload.folder_id = folderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listId) {
|
||||||
|
payload.list_id = listId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await $.http.post(
|
||||||
|
`/v2/team/${workspaceId}/webhook`,
|
||||||
|
payload
|
||||||
|
);
|
||||||
|
|
||||||
|
await $.flow.setRemoteWebhookId(data.id);
|
||||||
|
},
|
||||||
|
|
||||||
|
async unregisterHook($) {
|
||||||
|
await $.http.delete(`/v2/webhook/${$.flow.remoteWebhookId}`);
|
||||||
|
},
|
||||||
|
});
|
3
packages/backend/src/apps/code/actions/index.js
Normal file
3
packages/backend/src/apps/code/actions/index.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import runJavascript from './run-javascript/index.js';
|
||||||
|
|
||||||
|
export default [runJavascript];
|
@@ -0,0 +1,84 @@
|
|||||||
|
import defineAction from '../../../../helpers/define-action.js';
|
||||||
|
|
||||||
|
export default defineAction({
|
||||||
|
name: 'Run Javascript',
|
||||||
|
key: 'runJavascript',
|
||||||
|
description:
|
||||||
|
'Run browser Javascript code. You can not use NodeJS specific features and npm packages.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Inputs',
|
||||||
|
key: 'inputs',
|
||||||
|
type: 'dynamic',
|
||||||
|
required: false,
|
||||||
|
description:
|
||||||
|
'To be able to use data from previous steps, you need to expose them as input entries. You can access these input values in your code by using the `inputs` argument.',
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
key: '',
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
label: 'Key',
|
||||||
|
key: 'key',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Value',
|
||||||
|
key: 'value',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
variables: true,
|
||||||
|
valueType: 'parse',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Code Snippet',
|
||||||
|
key: 'codeSnippet',
|
||||||
|
type: 'code',
|
||||||
|
required: true,
|
||||||
|
variables: false,
|
||||||
|
value:
|
||||||
|
'const code = async (inputs) => { \n // E.g. if you have an input called username,\n // you can access its value by calling inputs.username\n // Return value will be used as output of this step.\n\n return true;\n};',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const { inputs = [], codeSnippet } = $.step.parameters;
|
||||||
|
|
||||||
|
const objectifiedInput = {};
|
||||||
|
for (const input of inputs) {
|
||||||
|
if (input.key) {
|
||||||
|
objectifiedInput[input.key] = input.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ivm = (await import('isolated-vm')).default;
|
||||||
|
const isolate = new ivm.Isolate({ memoryLimit: 128 });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const context = await isolate.createContext();
|
||||||
|
await context.global.set(
|
||||||
|
'inputs',
|
||||||
|
new ivm.ExternalCopy(objectifiedInput).copyInto()
|
||||||
|
);
|
||||||
|
|
||||||
|
const compiledCodeSnippet = await isolate.compileScript(
|
||||||
|
`${codeSnippet}; code(inputs);`
|
||||||
|
);
|
||||||
|
const codeFunction = await compiledCodeSnippet.run(context, {
|
||||||
|
reference: true,
|
||||||
|
promise: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
$.setActionItem({ raw: { output: await codeFunction.copy() } });
|
||||||
|
} finally {
|
||||||
|
isolate.dispose();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
5
packages/backend/src/apps/code/assets/favicon.svg
Normal file
5
packages/backend/src/apps/code/assets/favicon.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="800px" height="800px" viewBox="0 0 512 512">
|
||||||
|
<polyline points="160 368 32 256 160 144" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
|
||||||
|
<polyline points="352 368 480 256 352 144" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
|
||||||
|
<line x1="304" y1="96" x2="208" y2="416" style="fill:none;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:32px"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 519 B |
14
packages/backend/src/apps/code/index.js
Normal file
14
packages/backend/src/apps/code/index.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import defineApp from '../../helpers/define-app.js';
|
||||||
|
import actions from './actions/index.js';
|
||||||
|
|
||||||
|
export default defineApp({
|
||||||
|
name: 'Code',
|
||||||
|
key: 'code',
|
||||||
|
baseUrl: '',
|
||||||
|
apiBaseUrl: '',
|
||||||
|
iconUrl: '{BASE_URL}/apps/code/assets/favicon.svg',
|
||||||
|
authDocUrl: '{DOCS_URL}/apps/code/connection',
|
||||||
|
primaryColor: '#000000',
|
||||||
|
supportsConnections: false,
|
||||||
|
actions,
|
||||||
|
});
|
@@ -0,0 +1,64 @@
|
|||||||
|
import { createHmac } from 'node:crypto';
|
||||||
|
import defineAction from '../../../../helpers/define-action.js';
|
||||||
|
|
||||||
|
export default defineAction({
|
||||||
|
name: 'Create HMAC',
|
||||||
|
key: 'createHmac',
|
||||||
|
description: 'Create a Hash-based Message Authentication Code (HMAC) using the specified algorithm, secret key, and message.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Algorithm',
|
||||||
|
key: 'algorithm',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
value: 'sha256',
|
||||||
|
description: 'Specifies the cryptographic hash function to use for HMAC generation.',
|
||||||
|
options: [
|
||||||
|
{ label: 'SHA-256', value: 'sha256' },
|
||||||
|
],
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Message',
|
||||||
|
key: 'message',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'The input message to be hashed. This is the value that will be processed to generate the HMAC.',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Secret Key',
|
||||||
|
key: 'secretKey',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'The secret key used to create the HMAC.',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Output Encoding',
|
||||||
|
key: 'outputEncoding',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
value: 'hex',
|
||||||
|
description: 'Specifies the encoding format for the HMAC digest output.',
|
||||||
|
options: [
|
||||||
|
{ label: 'base64', value: 'base64' },
|
||||||
|
{ label: 'base64url', value: 'base64url' },
|
||||||
|
{ label: 'hex', value: 'hex' },
|
||||||
|
],
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const hash = createHmac($.step.parameters.algorithm, $.step.parameters.secretKey)
|
||||||
|
.update($.step.parameters.message)
|
||||||
|
.digest($.step.parameters.outputEncoding);
|
||||||
|
|
||||||
|
$.setActionItem({
|
||||||
|
raw: {
|
||||||
|
hash
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
@@ -0,0 +1,65 @@
|
|||||||
|
import crypto from 'node:crypto';
|
||||||
|
import defineAction from '../../../../helpers/define-action.js';
|
||||||
|
|
||||||
|
export default defineAction({
|
||||||
|
name: 'Create Signature',
|
||||||
|
key: 'createSignature',
|
||||||
|
description: 'Create a digital signature using the specified algorithm, secret key, and message.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Algorithm',
|
||||||
|
key: 'algorithm',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
value: 'RSA-SHA256',
|
||||||
|
description: 'Specifies the cryptographic hash function to use for HMAC generation.',
|
||||||
|
options: [
|
||||||
|
{ label: 'RSA-SHA256', value: 'RSA-SHA256' },
|
||||||
|
],
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Message',
|
||||||
|
key: 'message',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'The input message to be signed.',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Private Key',
|
||||||
|
key: 'privateKey',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'The RSA private key in PEM format used for signing.',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Output Encoding',
|
||||||
|
key: 'outputEncoding',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
value: 'hex',
|
||||||
|
description: 'Specifies the encoding format for the digital signature output. This determines how the generated signature will be represented as a string.',
|
||||||
|
options: [
|
||||||
|
{ label: 'base64', value: 'base64' },
|
||||||
|
{ label: 'base64url', value: 'base64url' },
|
||||||
|
{ label: 'hex', value: 'hex' },
|
||||||
|
],
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const signer = crypto.createSign($.step.parameters.algorithm);
|
||||||
|
signer.update($.step.parameters.message);
|
||||||
|
signer.end();
|
||||||
|
const signature = signer.sign($.step.parameters.privateKey, $.step.parameters.outputEncoding);
|
||||||
|
|
||||||
|
$.setActionItem({
|
||||||
|
raw: {
|
||||||
|
signature
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
4
packages/backend/src/apps/cryptography/actions/index.js
Normal file
4
packages/backend/src/apps/cryptography/actions/index.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import createHmac from './create-hmac/index.js';
|
||||||
|
import createRsaSha256Signature from './create-rsa-sha256-signature/index.js';
|
||||||
|
|
||||||
|
export default [createHmac, createRsaSha256Signature];
|
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="100pt" height="100pt" version="1.1" viewBox="0 0 100 100">
|
||||||
|
<path d="m66.012 33h-3.0117v-11c0-7.1719-5.8281-13-13-13s-13 5.8281-13 13v11h-3.0117c-2.75 0-4.9883 2.2383-4.9883 4.9883v28.012c0 2.75 2.2383 4.9883 4.9883 4.9883h32.012c2.75 0 4.9883-2.2383 4.9883-4.9883v-28.012c0.011719-2.75-2.2266-4.9883-4.9766-4.9883zm-27.012-11c0-6.0703 4.9297-11 11-11s11 4.9297 11 11v11h-22zm30 44.012c0 1.6484-1.3398 2.9883-2.9883 2.9883h-32.023c-1.6484 0-2.9883-1.3398-2.9883-2.9883v-28.023c0-1.6484 1.3398-2.9883 2.9883-2.9883h32.023c1.6484 0 2.9883 1.3398 2.9883 2.9883zm-18 9.9883v14c0 0.55078-0.44922 1-1 1s-1-0.44922-1-1v-14c0-0.55078 0.44922-1 1-1s1 0.44922 1 1zm20 8c0 0.55078-0.44922 1-1 1h-8c-0.55078 0-1-0.44922-1-1v-8c0-0.55078 0.44922-1 1-1s1 0.44922 1 1v7h7c0.55078 0 1 0.44922 1 1zm-32-8v8c0 0.55078-0.44922 1-1 1h-8c-0.55078 0-1-0.44922-1-1s0.44922-1 1-1h7v-7c0-0.55078 0.44922-1 1-1s1 0.44922 1 1zm-14-26c0 0.55078-0.44922 1-1 1h-14c-0.55078 0-1-0.44922-1-1s0.44922-1 1-1h14c0.55078 0 1 0.44922 1 1zm0-12c0 0.55078-0.44922 1-1 1h-8c-0.55078 0-1-0.44922-1-1v-8c0-0.55078 0.44922-1 1-1s1 0.44922 1 1v7h7c0.55078 0 1 0.44922 1 1zm0 24c0 0.55078-0.44922 1-1 1h-7v7c0 0.55078-0.44922 1-1 1s-1-0.44922-1-1v-8c0-0.55078 0.44922-1 1-1h8c0.55078 0 1 0.44922 1 1zm66-12c0 0.55078-0.44922 1-1 1h-14c-0.55078 0-1-0.44922-1-1s0.44922-1 1-1h14c0.55078 0 1 0.44922 1 1zm-16-12c0-0.55078 0.44922-1 1-1h7v-7c0-0.55078 0.44922-1 1-1s1 0.44922 1 1v8c0 0.55078-0.44922 1-1 1h-8c-0.55078 0-1-0.44922-1-1zm10 24v8c0 0.55078-0.44922 1-1 1s-1-0.44922-1-1v-7h-7c-0.55078 0-1-0.44922-1-1s0.44922-1 1-1h8c0.55078 0 1 0.44922 1 1zm-35-17c-2.7617 0-5 2.2383-5 5 0 2.4102 1.7188 4.4297 4 4.8984v5.1016c0 0.55078 0.44922 1 1 1s1-0.44922 1-1v-5.1016c2.2812-0.46094 4-2.4805 4-4.8984 0-2.7617-2.2383-5-5-5zm0 8c-1.6484 0-3-1.3516-3-3s1.3516-3 3-3 3 1.3516 3 3-1.3516 3-3 3z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
14
packages/backend/src/apps/cryptography/index.js
Normal file
14
packages/backend/src/apps/cryptography/index.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import defineApp from '../../helpers/define-app.js';
|
||||||
|
import actions from './actions/index.js';
|
||||||
|
|
||||||
|
export default defineApp({
|
||||||
|
name: 'Cryptography',
|
||||||
|
key: 'cryptography',
|
||||||
|
iconUrl: '{BASE_URL}/apps/cryptography/assets/favicon.svg',
|
||||||
|
authDocUrl: '{DOCS_URL}/apps/cryptography/connection',
|
||||||
|
supportsConnections: false,
|
||||||
|
baseUrl: '',
|
||||||
|
apiBaseUrl: '',
|
||||||
|
primaryColor: '#001F52',
|
||||||
|
actions,
|
||||||
|
});
|
@@ -9,6 +9,6 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '001F52',
|
primaryColor: '#001F52',
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://deepl.com',
|
baseUrl: 'https://deepl.com',
|
||||||
apiBaseUrl: 'https://api.deepl.com',
|
apiBaseUrl: 'https://api.deepl.com',
|
||||||
primaryColor: '0d2d45',
|
primaryColor: '#0d2d45',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
@@ -9,6 +9,6 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '001F52',
|
primaryColor: '#001F52',
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
@@ -14,7 +14,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://discord.com',
|
baseUrl: 'https://discord.com',
|
||||||
apiBaseUrl: 'https://discord.com/api',
|
apiBaseUrl: 'https://discord.com/api',
|
||||||
primaryColor: '5865f2',
|
primaryColor: '#5865f2',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
dynamicData,
|
dynamicData,
|
||||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://disqus.com/api',
|
apiBaseUrl: 'https://disqus.com/api',
|
||||||
iconUrl: '{BASE_URL}/apps/disqus/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/disqus/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/disqus/connection',
|
authDocUrl: '{DOCS_URL}/apps/disqus/connection',
|
||||||
primaryColor: '2E9FFF',
|
primaryColor: '#2E9FFF',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://dropbox.com',
|
baseUrl: 'https://dropbox.com',
|
||||||
apiBaseUrl: 'https://api.dropboxapi.com',
|
apiBaseUrl: 'https://api.dropboxapi.com',
|
||||||
primaryColor: '0061ff',
|
primaryColor: '#0061ff',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
@@ -9,6 +9,6 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '001F52',
|
primaryColor: '#001F52',
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
@@ -10,7 +10,7 @@ export default defineApp({
|
|||||||
iconUrl: '{BASE_URL}/apps/flickr/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/flickr/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/flickr/connection',
|
authDocUrl: '{DOCS_URL}/apps/flickr/connection',
|
||||||
docUrl: 'https://automatisch.io/docs/flickr',
|
docUrl: 'https://automatisch.io/docs/flickr',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://www.flickr.com/',
|
baseUrl: 'https://www.flickr.com/',
|
||||||
apiBaseUrl: 'https://www.flickr.com/services',
|
apiBaseUrl: 'https://www.flickr.com/services',
|
||||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://flowers-software.com',
|
baseUrl: 'https://flowers-software.com',
|
||||||
apiBaseUrl: 'https://webapp.flowers-software.com/api',
|
apiBaseUrl: 'https://webapp.flowers-software.com/api',
|
||||||
primaryColor: '02AFC7',
|
primaryColor: '#02AFC7',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
import defineAction from '../../../../helpers/define-action.js';
|
import defineAction from '../../../../helpers/define-action.js';
|
||||||
import formatDateTime from './transformers/format-date-time.js';
|
import formatDateTime from './transformers/format-date-time.js';
|
||||||
|
import getCurrentTimestamp from './transformers/get-current-timestamp.js';
|
||||||
|
|
||||||
const transformers = {
|
const transformers = {
|
||||||
formatDateTime,
|
formatDateTime,
|
||||||
|
getCurrentTimestamp,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default defineAction({
|
export default defineAction({
|
||||||
@@ -16,7 +18,16 @@ export default defineAction({
|
|||||||
type: 'dropdown',
|
type: 'dropdown',
|
||||||
required: true,
|
required: true,
|
||||||
variables: true,
|
variables: true,
|
||||||
options: [{ label: 'Format Date / Time', value: 'formatDateTime' }],
|
options: [
|
||||||
|
{
|
||||||
|
label: 'Get current timestamp',
|
||||||
|
value: 'getCurrentTimestamp',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Format Date / Time',
|
||||||
|
value: 'formatDateTime',
|
||||||
|
},
|
||||||
|
],
|
||||||
additionalFields: {
|
additionalFields: {
|
||||||
type: 'query',
|
type: 'query',
|
||||||
name: 'getDynamicFields',
|
name: 'getDynamicFields',
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
const getCurrentTimestamp = () => {
|
||||||
|
return Date.now();
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getCurrentTimestamp;
|
@@ -14,6 +14,8 @@ import stringToBase64 from './transformers/string-to-base64.js';
|
|||||||
import encodeUri from './transformers/encode-uri.js';
|
import encodeUri from './transformers/encode-uri.js';
|
||||||
import trimWhitespace from './transformers/trim-whitespace.js';
|
import trimWhitespace from './transformers/trim-whitespace.js';
|
||||||
import useDefaultValue from './transformers/use-default-value.js';
|
import useDefaultValue from './transformers/use-default-value.js';
|
||||||
|
import parseStringifiedJson from './transformers/parse-stringified-json.js';
|
||||||
|
import createUuid from './transformers/create-uuid.js';
|
||||||
|
|
||||||
const transformers = {
|
const transformers = {
|
||||||
base64ToString,
|
base64ToString,
|
||||||
@@ -30,6 +32,8 @@ const transformers = {
|
|||||||
encodeUri,
|
encodeUri,
|
||||||
trimWhitespace,
|
trimWhitespace,
|
||||||
useDefaultValue,
|
useDefaultValue,
|
||||||
|
parseStringifiedJson,
|
||||||
|
createUuid,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default defineAction({
|
export default defineAction({
|
||||||
@@ -47,19 +51,21 @@ export default defineAction({
|
|||||||
options: [
|
options: [
|
||||||
{ label: 'Base64 to String', value: 'base64ToString' },
|
{ label: 'Base64 to String', value: 'base64ToString' },
|
||||||
{ label: 'Capitalize', value: 'capitalize' },
|
{ label: 'Capitalize', value: 'capitalize' },
|
||||||
|
{ label: 'Convert HTML to Markdown', value: 'htmlToMarkdown' },
|
||||||
|
{ label: 'Convert Markdown to HTML', value: 'markdownToHtml' },
|
||||||
|
{ label: 'Create UUID', value: 'createUuid' },
|
||||||
|
{ label: 'Encode URI', value: 'encodeUri' },
|
||||||
{
|
{
|
||||||
label: 'Encode URI Component',
|
label: 'Encode URI Component',
|
||||||
value: 'encodeUriComponent',
|
value: 'encodeUriComponent',
|
||||||
},
|
},
|
||||||
{ label: 'Convert HTML to Markdown', value: 'htmlToMarkdown' },
|
|
||||||
{ label: 'Convert Markdown to HTML', value: 'markdownToHtml' },
|
|
||||||
{ label: 'Extract Email Address', value: 'extractEmailAddress' },
|
{ label: 'Extract Email Address', value: 'extractEmailAddress' },
|
||||||
{ label: 'Extract Number', value: 'extractNumber' },
|
{ label: 'Extract Number', value: 'extractNumber' },
|
||||||
{ label: 'Lowercase', value: 'lowercase' },
|
{ label: 'Lowercase', value: 'lowercase' },
|
||||||
|
{ label: 'Parse stringified JSON', value: 'parseStringifiedJson' },
|
||||||
{ label: 'Pluralize', value: 'pluralize' },
|
{ label: 'Pluralize', value: 'pluralize' },
|
||||||
{ label: 'Replace', value: 'replace' },
|
{ label: 'Replace', value: 'replace' },
|
||||||
{ label: 'String to Base64', value: 'stringToBase64' },
|
{ label: 'String to Base64', value: 'stringToBase64' },
|
||||||
{ label: 'Encode URI', value: 'encodeUri' },
|
|
||||||
{ label: 'Trim Whitespace', value: 'trimWhitespace' },
|
{ label: 'Trim Whitespace', value: 'trimWhitespace' },
|
||||||
{ label: 'Use Default Value', value: 'useDefaultValue' },
|
{ label: 'Use Default Value', value: 'useDefaultValue' },
|
||||||
],
|
],
|
||||||
|
@@ -0,0 +1,7 @@
|
|||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
const createUuidV4 = () => {
|
||||||
|
return uuidv4();
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createUuidV4;
|
@@ -0,0 +1,7 @@
|
|||||||
|
const parseStringifiedJson = ($) => {
|
||||||
|
const input = $.step.parameters.input;
|
||||||
|
|
||||||
|
return JSON.parse(input);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default parseStringifiedJson;
|
@@ -1,8 +1,26 @@
|
|||||||
const replace = ($) => {
|
const replace = ($) => {
|
||||||
const input = $.step.parameters.input;
|
const input = $.step.parameters.input;
|
||||||
|
|
||||||
const find = $.step.parameters.find;
|
const find = $.step.parameters.find;
|
||||||
const replace = $.step.parameters.replace;
|
const replace = $.step.parameters.replace;
|
||||||
|
const useRegex = $.step.parameters.useRegex;
|
||||||
|
|
||||||
|
if (useRegex) {
|
||||||
|
const ignoreCase = $.step.parameters.ignoreCase;
|
||||||
|
|
||||||
|
const flags = [ignoreCase && 'i', 'g'].filter(Boolean).join('');
|
||||||
|
|
||||||
|
const timeoutId = setTimeout(() => {
|
||||||
|
$.execution.exit();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
const regex = new RegExp(find, flags);
|
||||||
|
|
||||||
|
const replacedValue = input.replaceAll(regex, replace);
|
||||||
|
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
|
||||||
|
return replacedValue;
|
||||||
|
}
|
||||||
|
|
||||||
return input.replaceAll(find, replace);
|
return input.replaceAll(find, replace);
|
||||||
};
|
};
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
import listTransformOptions from './list-transform-options/index.js';
|
import listTransformOptions from './list-transform-options/index.js';
|
||||||
|
import listReplaceRegexOptions from './list-replace-regex-options/index.js';
|
||||||
|
|
||||||
export default [listTransformOptions];
|
export default [listTransformOptions, listReplaceRegexOptions];
|
||||||
|
@@ -0,0 +1,23 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List replace regex options',
|
||||||
|
key: 'listReplaceRegexOptions',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
if (!$.step.parameters.useRegex) return [];
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: 'Ignore case',
|
||||||
|
key: 'ignoreCase',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
description: 'Ignore case sensitivity.',
|
||||||
|
variables: true,
|
||||||
|
options: [
|
||||||
|
{ label: 'Yes', value: true },
|
||||||
|
{ label: 'No', value: false },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
};
|
@@ -12,6 +12,7 @@ import stringToBase64 from './text/string-to-base64.js';
|
|||||||
import encodeUri from './text/encode-uri.js';
|
import encodeUri from './text/encode-uri.js';
|
||||||
import trimWhitespace from './text/trim-whitespace.js';
|
import trimWhitespace from './text/trim-whitespace.js';
|
||||||
import useDefaultValue from './text/use-default-value.js';
|
import useDefaultValue from './text/use-default-value.js';
|
||||||
|
import parseStringifiedJson from './text/parse-stringified-json.js';
|
||||||
import performMathOperation from './numbers/perform-math-operation.js';
|
import performMathOperation from './numbers/perform-math-operation.js';
|
||||||
import randomNumber from './numbers/random-number.js';
|
import randomNumber from './numbers/random-number.js';
|
||||||
import formatNumber from './numbers/format-number.js';
|
import formatNumber from './numbers/format-number.js';
|
||||||
@@ -38,6 +39,7 @@ const options = {
|
|||||||
formatNumber,
|
formatNumber,
|
||||||
formatPhoneNumber,
|
formatPhoneNumber,
|
||||||
formatDateTime,
|
formatDateTime,
|
||||||
|
parseStringifiedJson,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@@ -0,0 +1,12 @@
|
|||||||
|
const useDefaultValue = [
|
||||||
|
{
|
||||||
|
label: 'Input',
|
||||||
|
key: 'input',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description: 'Stringified JSON you want to parse.',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default useDefaultValue;
|
@@ -23,6 +23,33 @@ const replace = [
|
|||||||
description: 'Text that will replace the found text.',
|
description: 'Text that will replace the found text.',
|
||||||
variables: true,
|
variables: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'Use Regular Expression',
|
||||||
|
key: 'useRegex',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
description: 'Use regex to search values.',
|
||||||
|
variables: true,
|
||||||
|
value: false,
|
||||||
|
options: [
|
||||||
|
{ label: 'Yes', value: true },
|
||||||
|
{ label: 'No', value: false },
|
||||||
|
],
|
||||||
|
additionalFields: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicFields',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listReplaceRegexOptions',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.useRegex',
|
||||||
|
value: '{parameters.useRegex}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default replace;
|
export default replace;
|
||||||
|
@@ -10,7 +10,7 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '001F52',
|
primaryColor: '#001F52',
|
||||||
actions,
|
actions,
|
||||||
dynamicFields,
|
dynamicFields,
|
||||||
});
|
});
|
||||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
iconUrl: '{BASE_URL}/apps/ghost/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/ghost/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/ghost/connection',
|
authDocUrl: '{DOCS_URL}/apps/ghost/connection',
|
||||||
primaryColor: '15171A',
|
primaryColor: '#15171A',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -10,7 +10,7 @@ export default defineAction({
|
|||||||
label: 'Repo',
|
label: 'Repo',
|
||||||
key: 'repo',
|
key: 'repo',
|
||||||
type: 'dropdown',
|
type: 'dropdown',
|
||||||
required: false,
|
required: true,
|
||||||
variables: true,
|
variables: true,
|
||||||
source: {
|
source: {
|
||||||
type: 'query',
|
type: 'query',
|
||||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://api.github.com',
|
apiBaseUrl: 'https://api.github.com',
|
||||||
iconUrl: '{BASE_URL}/apps/github/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/github/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/github/connection',
|
authDocUrl: '{DOCS_URL}/apps/github/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://gitlab.com',
|
apiBaseUrl: 'https://gitlab.com',
|
||||||
iconUrl: '{BASE_URL}/apps/gitlab/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/gitlab/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/gitlab/connection',
|
authDocUrl: '{DOCS_URL}/apps/gitlab/connection',
|
||||||
primaryColor: 'FC6D26',
|
primaryColor: '#FC6D26',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://www.googleapis.com/calendar',
|
apiBaseUrl: 'https://www.googleapis.com/calendar',
|
||||||
iconUrl: '{BASE_URL}/apps/google-calendar/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/google-calendar/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/google-calendar/connection',
|
authDocUrl: '{DOCS_URL}/apps/google-calendar/connection',
|
||||||
primaryColor: '448AFF',
|
primaryColor: '#448AFF',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://www.googleapis.com/drive',
|
apiBaseUrl: 'https://www.googleapis.com/drive',
|
||||||
iconUrl: '{BASE_URL}/apps/google-drive/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/google-drive/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/google-drive/connection',
|
authDocUrl: '{DOCS_URL}/apps/google-drive/connection',
|
||||||
primaryColor: '1FA463',
|
primaryColor: '#1FA463',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://forms.googleapis.com',
|
apiBaseUrl: 'https://forms.googleapis.com',
|
||||||
iconUrl: '{BASE_URL}/apps/google-forms/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/google-forms/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/google-forms/connection',
|
authDocUrl: '{DOCS_URL}/apps/google-forms/connection',
|
||||||
primaryColor: '673AB7',
|
primaryColor: '#673AB7',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -0,0 +1,175 @@
|
|||||||
|
import defineAction from '../../../../helpers/define-action.js';
|
||||||
|
|
||||||
|
export default defineAction({
|
||||||
|
name: 'Find worksheet',
|
||||||
|
key: 'findWorksheet',
|
||||||
|
description:
|
||||||
|
'Finds a worksheet by title. Optionally, create a worksheet if none are found.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Drive',
|
||||||
|
key: 'driveId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
description:
|
||||||
|
'The Google Drive where your spreadsheet resides. If nothing is selected, then your personal Google Drive will be used.',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listDrives',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Spreadsheet',
|
||||||
|
key: 'spreadsheetId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
dependsOn: ['parameters.driveId'],
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listSpreadsheets',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.driveId',
|
||||||
|
value: '{parameters.driveId}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Title',
|
||||||
|
key: 'title',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
description:
|
||||||
|
'The worksheet title needs to match exactly, and the search is case-sensitive.',
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Create worksheet if none are found.',
|
||||||
|
key: 'createWorksheet',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: false,
|
||||||
|
options: [
|
||||||
|
{ label: 'Yes', value: true },
|
||||||
|
{ label: 'No', value: false },
|
||||||
|
],
|
||||||
|
additionalFields: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicFields',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listCreateWorksheetFields',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'parameters.createWorksheet',
|
||||||
|
value: '{parameters.createWorksheet}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const createWorksheet = $.step.parameters.createWorksheet;
|
||||||
|
|
||||||
|
async function findWorksheet() {
|
||||||
|
const {
|
||||||
|
data: { sheets },
|
||||||
|
} = await $.http.get(`/v4/spreadsheets/${$.step.parameters.spreadsheetId}`);
|
||||||
|
|
||||||
|
const selectedSheet = sheets.find(
|
||||||
|
(sheet) => sheet.properties.title === $.step.parameters.title
|
||||||
|
);
|
||||||
|
|
||||||
|
return selectedSheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedSheet = await findWorksheet();
|
||||||
|
|
||||||
|
if (selectedSheet) {
|
||||||
|
$.setActionItem({
|
||||||
|
raw: selectedSheet,
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createWorksheet) {
|
||||||
|
const headers = $.step.parameters.headers;
|
||||||
|
const headerValues = headers.map((entry) => entry.header);
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
requests: [
|
||||||
|
{
|
||||||
|
addSheet: {
|
||||||
|
properties: {
|
||||||
|
title: $.step.parameters.title,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data } = await $.http.post(
|
||||||
|
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}:batchUpdate`,
|
||||||
|
body
|
||||||
|
);
|
||||||
|
|
||||||
|
if (headerValues.length) {
|
||||||
|
const body = {
|
||||||
|
requests: [
|
||||||
|
{
|
||||||
|
updateCells: {
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
values: headerValues.map((header) => ({
|
||||||
|
userEnteredValue: { stringValue: header },
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
fields: '*',
|
||||||
|
start: {
|
||||||
|
sheetId:
|
||||||
|
data.replies[data.replies.length - 1].addSheet.properties
|
||||||
|
.sheetId,
|
||||||
|
rowIndex: 0,
|
||||||
|
columnIndex: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
await $.http.post(
|
||||||
|
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}:batchUpdate`,
|
||||||
|
body
|
||||||
|
);
|
||||||
|
|
||||||
|
const createdSheet = await findWorksheet();
|
||||||
|
|
||||||
|
$.setActionItem({
|
||||||
|
raw: createdSheet,
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$.setActionItem({
|
||||||
|
raw: null,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
@@ -1,5 +1,11 @@
|
|||||||
import createSpreadsheet from './create-spreadsheet/index.js';
|
import createSpreadsheet from './create-spreadsheet/index.js';
|
||||||
import createSpreadsheetRow from './create-spreadsheet-row/index.js';
|
import createSpreadsheetRow from './create-spreadsheet-row/index.js';
|
||||||
import createWorksheet from './create-worksheet/index.js';
|
import createWorksheet from './create-worksheet/index.js';
|
||||||
|
import findWorksheet from './find-worksheet/index.js';
|
||||||
|
|
||||||
export default [createSpreadsheet, createSpreadsheetRow, createWorksheet];
|
export default [
|
||||||
|
createSpreadsheet,
|
||||||
|
createSpreadsheetRow,
|
||||||
|
createWorksheet,
|
||||||
|
findWorksheet,
|
||||||
|
];
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
import listSheetHeaders from './list-sheet-headers/index.js';
|
import listSheetHeaders from './list-sheet-headers/index.js';
|
||||||
|
import listCreateWorksheetFields from './list-create-worksheet-fields/index.js';
|
||||||
|
|
||||||
export default [listSheetHeaders];
|
export default [listSheetHeaders, listCreateWorksheetFields];
|
||||||
|
@@ -0,0 +1,26 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List create worksheet fields',
|
||||||
|
key: 'listCreateWorksheetFields',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
if ($.step.parameters.createWorksheet) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: 'Headers',
|
||||||
|
key: 'headers',
|
||||||
|
type: 'dynamic',
|
||||||
|
required: false,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
label: 'Header',
|
||||||
|
key: 'header',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
variables: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://sheets.googleapis.com',
|
apiBaseUrl: 'https://sheets.googleapis.com',
|
||||||
iconUrl: '{BASE_URL}/apps/google-sheets/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/google-sheets/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/google-sheets/connection',
|
authDocUrl: '{DOCS_URL}/apps/google-sheets/connection',
|
||||||
primaryColor: '0F9D58',
|
primaryColor: '#0F9D58',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -12,7 +12,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://tasks.googleapis.com',
|
apiBaseUrl: 'https://tasks.googleapis.com',
|
||||||
iconUrl: '{BASE_URL}/apps/google-tasks/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/google-tasks/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/google-tasks/connection',
|
authDocUrl: '{DOCS_URL}/apps/google-tasks/connection',
|
||||||
primaryColor: '0066DA',
|
primaryColor: '#0066DA',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://app.tryhelix.ai',
|
apiBaseUrl: 'https://app.tryhelix.ai',
|
||||||
iconUrl: '{BASE_URL}/apps/helix/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/helix/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/helix/connection',
|
authDocUrl: '{DOCS_URL}/apps/helix/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
@@ -145,6 +145,13 @@ export default defineAction({
|
|||||||
responseData = Buffer.from(responseData).toString('base64');
|
responseData = Buffer.from(responseData).toString('base64');
|
||||||
}
|
}
|
||||||
|
|
||||||
$.setActionItem({ raw: { data: responseData } });
|
$.setActionItem({
|
||||||
|
raw: {
|
||||||
|
data: responseData,
|
||||||
|
headers: response.headers,
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@@ -9,6 +9,6 @@ export default defineApp({
|
|||||||
supportsConnections: false,
|
supportsConnections: false,
|
||||||
baseUrl: '',
|
baseUrl: '',
|
||||||
apiBaseUrl: '',
|
apiBaseUrl: '',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
@@ -11,7 +11,7 @@ export default defineApp({
|
|||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://www.hubspot.com',
|
baseUrl: 'https://www.hubspot.com',
|
||||||
apiBaseUrl: 'https://api.hubapi.com',
|
apiBaseUrl: 'https://api.hubapi.com',
|
||||||
primaryColor: 'F95C35',
|
primaryColor: '#F95C35',
|
||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
actions,
|
actions,
|
||||||
|
@@ -13,7 +13,7 @@ export default defineApp({
|
|||||||
apiBaseUrl: 'https://invoicing.co/api',
|
apiBaseUrl: 'https://invoicing.co/api',
|
||||||
iconUrl: '{BASE_URL}/apps/invoice-ninja/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/invoice-ninja/assets/favicon.svg',
|
||||||
authDocUrl: '{DOCS_URL}/apps/invoice-ninja/connection',
|
authDocUrl: '{DOCS_URL}/apps/invoice-ninja/connection',
|
||||||
primaryColor: '000000',
|
primaryColor: '#000000',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
|
1
packages/backend/src/apps/jotform/assets/favicon.svg
Normal file
1
packages/backend/src/apps/jotform/assets/favicon.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns:xlink="http://www.w3.org/1999/xlink" class="jff-logo-img" width="53" height="59" viewBox="0 0 53 59" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M14.4509 55.1332C15.5462 56.1951 14.7721 58.0143 13.2168 58.0143H3.4831C1.56265 58.0143 0 56.4995 0 54.6377V45.2017C0 43.6939 1.87664 42.9436 2.97195 44.0054L14.4509 55.1332Z" fill="#0A1551"></path><path d="M29.6655 55.8676C26.7843 53.0052 26.7843 48.3642 29.6655 45.5018L40.0638 35.1713C42.945 32.3089 47.6164 32.3089 50.4976 35.1713C53.3788 38.0338 53.3788 42.6747 50.4976 45.5371L40.0993 55.8676C37.2181 58.73 32.5468 58.73 29.6655 55.8676Z" fill="#FFB629"></path><path d="M2.1968 29.9101C-0.684414 27.0476 -0.684413 22.4067 2.1968 19.5443L19.696 2.14685C22.5772 -0.71559 27.2486 -0.715594 30.1298 2.14685C33.011 5.00929 33.011 9.65022 30.1298 12.5127L12.6306 29.9101C9.74937 32.7725 5.078 32.7725 2.1968 29.9101Z" fill="#0099FF"></path><path d="M16.5015 42.3095C13.6203 39.4471 13.6203 34.8062 16.5015 31.9437L40.1461 8.45322C43.0273 5.59079 47.6986 5.59079 50.5798 8.45322C53.4611 11.3157 53.4611 15.9566 50.5798 18.819L26.9353 42.3095C24.0541 45.1719 19.3827 45.1719 16.5015 42.3095Z" fill="#FF6100"></path></svg>
|
After Width: | Height: | Size: 1.2 KiB |
30
packages/backend/src/apps/jotform/auth/index.js
Normal file
30
packages/backend/src/apps/jotform/auth/index.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import verifyCredentials from './verify-credentials.js';
|
||||||
|
import isStillVerified from './is-still-verified.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
key: 'apiUrl',
|
||||||
|
label: 'API URL',
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
readOnly: false,
|
||||||
|
value: 'https://api.jotform.com',
|
||||||
|
placeholder: 'https://${subdomain}.jotform.com/api',
|
||||||
|
clickToCopy: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'apiKey',
|
||||||
|
label: 'API Key',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
clickToCopy: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
verifyCredentials,
|
||||||
|
isStillVerified,
|
||||||
|
};
|
@@ -0,0 +1,8 @@
|
|||||||
|
import getCurrentUser from '../common/get-current-user.js';
|
||||||
|
|
||||||
|
const isStillVerified = async ($) => {
|
||||||
|
const user = await getCurrentUser($);
|
||||||
|
return !!user.username;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default isStillVerified;
|
12
packages/backend/src/apps/jotform/auth/verify-credentials.js
Normal file
12
packages/backend/src/apps/jotform/auth/verify-credentials.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import getCurrentUser from '../common/get-current-user.js';
|
||||||
|
|
||||||
|
const verifyCredentials = async ($) => {
|
||||||
|
const user = await getCurrentUser($);
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
screenName: user.name,
|
||||||
|
apiKey: $.auth.data.apiKey,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default verifyCredentials;
|
@@ -0,0 +1,9 @@
|
|||||||
|
const addAuthHeader = ($, requestConfig) => {
|
||||||
|
if ($.auth.data?.apiKey) {
|
||||||
|
requestConfig.headers['APIKEY'] = `${$.auth.data.apiKey}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default addAuthHeader;
|
@@ -0,0 +1,7 @@
|
|||||||
|
const getCurrentUser = async ($) => {
|
||||||
|
const response = await $.http.get('/user');
|
||||||
|
const currentUser = response.data.content;
|
||||||
|
return currentUser;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getCurrentUser;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user