Compare commits
1870 Commits
feature/li
...
feature/nu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be148297a2 | ||
|
|
6cf6d8c876 | ||
|
|
6a03f9a6fe | ||
|
|
bd4a52318b | ||
|
|
3978865902 | ||
|
|
c1228ee426 | ||
|
|
d0c39dc932 | ||
|
|
63a8586d7c | ||
|
|
e0a79c033e | ||
|
|
fa12f127ce | ||
|
|
10916eadd5 | ||
|
|
7f4e8e9c8f | ||
|
|
d06840f934 | ||
|
|
75f4df8b51 | ||
|
|
e9ea6d27ae | ||
|
|
48019d43c3 | ||
|
|
04dbeb633d | ||
|
|
71631865c4 | ||
|
|
d4a39cf481 | ||
|
|
3a71dfff64 | ||
|
|
d8c865b3ce | ||
|
|
71356b798c | ||
|
|
66ddd1741f | ||
|
|
8a60f3c8a7 | ||
|
|
25d2a40c50 | ||
|
|
17b389146c | ||
|
|
bd1f609b39 | ||
|
|
01e1831d57 | ||
|
|
c341baa781 | ||
|
|
995a0c33c3 | ||
|
|
75845cb42d | ||
|
|
822d6acfb0 | ||
|
|
2c4510a717 | ||
|
|
ac2391c91a | ||
|
|
e805563ce5 | ||
|
|
88fb1d920e | ||
|
|
dca60fad7a | ||
|
|
8226b05e7e | ||
|
|
0106331978 | ||
|
|
f5c0e7d2e9 | ||
|
|
4568b24351 | ||
|
|
042502f41f | ||
|
|
d342d73818 | ||
|
|
3b922216c1 | ||
|
|
10fa9b6812 | ||
|
|
33ccbf790b | ||
|
|
50b4baee4b | ||
|
|
be57a56095 | ||
|
|
f351453b9c | ||
|
|
dda67d3351 | ||
|
|
23e1e744e8 | ||
|
|
4b0affe182 | ||
|
|
ab836bc747 | ||
|
|
cf86d7e352 | ||
|
|
05a36d3878 | ||
|
|
0417084a39 | ||
|
|
cdfe39f226 | ||
|
|
b73dde3a48 | ||
|
|
0dea597226 | ||
|
|
2f38928c89 | ||
|
|
35c7b5e952 | ||
|
|
ba28b17263 | ||
|
|
51b0e004fa | ||
|
|
8cb59b02a8 | ||
|
|
38bfd130a3 | ||
|
|
369d90e057 | ||
|
|
c27cdd1734 | ||
|
|
e7e4f39311 | ||
|
|
0443a21e05 | ||
|
|
50c01886ec | ||
|
|
a9e1219f6c | ||
|
|
7bc31dde70 | ||
|
|
65f2f1d08f | ||
|
|
684027eaab | ||
|
|
1c3ec9c3bb | ||
|
|
3a8ff2c05d | ||
|
|
d5bd179c68 | ||
|
|
8b938a39cf | ||
|
|
c9610cbc39 | ||
|
|
931733d605 | ||
|
|
44e5d0e195 | ||
|
|
08b83dc3fd | ||
|
|
b7f261a836 | ||
|
|
d0b4ca33c2 | ||
|
|
160391f5a9 | ||
|
|
dfe4a96b02 | ||
|
|
a3f67eb519 | ||
|
|
0f9d52552b | ||
|
|
a217de4c39 | ||
|
|
d2d85e63f6 | ||
|
|
7a6077b5ff | ||
|
|
d48c4d9729 | ||
|
|
6d677401bf | ||
|
|
a3d4fa2f86 | ||
|
|
59e19b6a22 | ||
|
|
1a76da40d1 | ||
|
|
cb15ba01f0 | ||
|
|
78af7f136e | ||
|
|
cc6a95b579 | ||
|
|
4b3f723bdc | ||
|
|
d372e2ff76 | ||
|
|
4201d1cb1e | ||
|
|
afed70ba63 | ||
|
|
be488346c5 | ||
|
|
eeeb688439 | ||
|
|
b84ce77326 | ||
|
|
30fca423dc | ||
|
|
fabbb31572 | ||
|
|
ac76ac004e | ||
|
|
9d2051183a | ||
|
|
942fdb51d5 | ||
|
|
d2600a3168 | ||
|
|
c4248cce22 | ||
|
|
16f16f9fed | ||
|
|
d49cb976bc | ||
|
|
6fae6a9865 | ||
|
|
06f3730756 | ||
|
|
30e1333f75 | ||
|
|
0d6fa98767 | ||
|
|
ae6c9edd0d | ||
|
|
35de1f1c4e | ||
|
|
57142f4afb | ||
|
|
cd72d65b89 | ||
|
|
2199ab0513 | ||
|
|
e93f058109 | ||
|
|
b68de49cbd | ||
|
|
3f05934b6b | ||
|
|
3a5713dbb7 | ||
|
|
4c43158285 | ||
|
|
daa743b3b3 | ||
|
|
41f0ae18c4 | ||
|
|
e6b8aefe5b | ||
|
|
8b2437cb16 | ||
|
|
292495ab0d | ||
|
|
017b137d7f | ||
|
|
7969030313 | ||
|
|
c8efad4c3f | ||
|
|
7bf9d8f675 | ||
|
|
e275f15f00 | ||
|
|
30017a5217 | ||
|
|
64c5cbe8c3 | ||
|
|
b2b226573c | ||
|
|
69f796998f | ||
|
|
4d64be3ac7 | ||
|
|
4408b794d6 | ||
|
|
666da8a879 | ||
|
|
b166342579 | ||
|
|
433f5bf7d2 | ||
|
|
b8ae153ef5 | ||
|
|
bb59c2bab7 | ||
|
|
ab7c6c5118 | ||
|
|
85c1ea449e | ||
|
|
b51d679b78 | ||
|
|
2a2bc9e625 | ||
|
|
d00f059567 | ||
|
|
81a840347c | ||
|
|
e691675bf9 | ||
|
|
9cd57c3ae1 | ||
|
|
0e3310a39b | ||
|
|
447818ac2a | ||
|
|
dd0eb846b0 | ||
|
|
1b62ca4b21 | ||
|
|
97ece03853 | ||
|
|
33a72a0d9d | ||
|
|
62e61829b4 | ||
|
|
ad9d12260e | ||
|
|
fe54c9495f | ||
|
|
456afce6ca | ||
|
|
8ecbb4d4a4 | ||
|
|
92564397f4 | ||
|
|
62b2805c9d | ||
|
|
985af8b0bb | ||
|
|
58c3b180dc | ||
|
|
d260959b96 | ||
|
|
6e11197348 | ||
|
|
04d5bef4d2 | ||
|
|
1ccc5ce4e1 | ||
|
|
a94ef1db80 | ||
|
|
5513c624c3 | ||
|
|
1c493a8dc0 | ||
|
|
3fa051a6c3 | ||
|
|
876171b83d | ||
|
|
68521298ff | ||
|
|
c648926e49 | ||
|
|
1cd259a261 | ||
|
|
ef1fe07157 | ||
|
|
9ae8f7f406 | ||
|
|
363cbaac32 | ||
|
|
435b2cf23c | ||
|
|
bd1a87f5f0 | ||
|
|
c57218adb2 | ||
|
|
a56d2a3eca | ||
|
|
b324130e30 | ||
|
|
566a6e5836 | ||
|
|
bcca407a5e | ||
|
|
10c6832718 | ||
|
|
1ad8db20b4 | ||
|
|
43233747be | ||
|
|
56354afa9b | ||
|
|
7f686a817b | ||
|
|
10534ff75a | ||
|
|
da39be79a4 | ||
|
|
8a1ca80e28 | ||
|
|
ca29a3a272 | ||
|
|
1a115bda82 | ||
|
|
130e49bf1d | ||
|
|
552c84f910 | ||
|
|
d1a0111705 | ||
|
|
5bc285041b | ||
|
|
c96a522a1b | ||
|
|
def2dadca1 | ||
|
|
46a52e2b2f | ||
|
|
1835776200 | ||
|
|
efaa4893bf | ||
|
|
be8580cc4b | ||
|
|
e43bb3123b | ||
|
|
3078e3584c | ||
|
|
6689849f97 | ||
|
|
7281ee1565 | ||
|
|
4c12ee3b14 | ||
|
|
dc0ae69f65 | ||
|
|
0dba4ba653 | ||
|
|
758d8689ab | ||
|
|
f119ccf5a0 | ||
|
|
c86c6486b9 | ||
|
|
6ed5c163ba | ||
|
|
2c14530e3c | ||
|
|
6d30e1921e | ||
|
|
7ff84a9932 | ||
|
|
bcff01b0bf | ||
|
|
8cd09342e1 | ||
|
|
802e78d3b7 | ||
|
|
e6c938e5d0 | ||
|
|
7b6595124f | ||
|
|
c33408a1f7 | ||
|
|
160d53701b | ||
|
|
1f19d1925a | ||
|
|
50680a4f2e | ||
|
|
18307b2e03 | ||
|
|
b03ad80451 | ||
|
|
dedfe1f421 | ||
|
|
1cf583d197 | ||
|
|
1deaa4c30d | ||
|
|
90316f106a | ||
|
|
63693f908d | ||
|
|
6905e4a2a1 | ||
|
|
4489a54e82 | ||
|
|
6d48915945 | ||
|
|
00f3a7f4db | ||
|
|
f9c47ab233 | ||
|
|
28712b205f | ||
|
|
69b1fb1bfd | ||
|
|
8a22f9215f | ||
|
|
c5ebc01978 | ||
|
|
f29b468fc1 | ||
|
|
e796fbb990 | ||
|
|
37a122c981 | ||
|
|
4f426a73f6 | ||
|
|
1bcb74cd85 | ||
|
|
cd88c8de78 | ||
|
|
eee288b45b | ||
|
|
797cb7615d | ||
|
|
ca4667ff1e | ||
|
|
66d1143ca0 | ||
|
|
f310916c76 | ||
|
|
5d3d8ab932 | ||
|
|
07117c90d1 | ||
|
|
fd91c18460 | ||
|
|
5d92c0e85e | ||
|
|
2a12c04518 | ||
|
|
d08cae6fa3 | ||
|
|
d7f9de1881 | ||
|
|
962190cc57 | ||
|
|
4527866276 | ||
|
|
088dfcd4dc | ||
|
|
6c317b6e64 | ||
|
|
6b66c273b4 | ||
|
|
60f31008c0 | ||
|
|
078f74db97 | ||
|
|
a0b025cf59 | ||
|
|
bc695f5af9 | ||
|
|
9685e63b09 | ||
|
|
142791360c | ||
|
|
e004ed2f4b | ||
|
|
23ed487252 | ||
|
|
efefec3c20 | ||
|
|
3d2ad1cb9b | ||
|
|
90d3016938 | ||
|
|
438f9fc94d | ||
|
|
82ec88cc2f | ||
|
|
149611041e | ||
|
|
b12c79462e | ||
|
|
fbf34fb730 | ||
|
|
e1fe3eb710 | ||
|
|
76ae2e0e5a | ||
|
|
a57063adf7 | ||
|
|
ff0157e624 | ||
|
|
af9701feb8 | ||
|
|
93c1f31588 | ||
|
|
1964e54476 | ||
|
|
4682255d5f | ||
|
|
a503898b21 | ||
|
|
21352dae07 | ||
|
|
8470c7ac6b | ||
|
|
28aa86f0aa | ||
|
|
3ed214269a | ||
|
|
37b5183be2 | ||
|
|
a79896aa2e | ||
|
|
d5bd40873e | ||
|
|
52f1809d22 | ||
|
|
51d8fa7268 | ||
|
|
4d1167a6d6 | ||
|
|
8fa1459e5b | ||
|
|
baf3914be8 | ||
|
|
bd2721d3ec | ||
|
|
f30b96b360 | ||
|
|
4772c0e110 | ||
|
|
4a0af08ae5 | ||
|
|
a71129df4b | ||
|
|
de6acfa1ce | ||
|
|
ccf075dc65 | ||
|
|
1d8ac3cf86 | ||
|
|
623a23492f | ||
|
|
7a8ff89c5c | ||
|
|
eda70def2a | ||
|
|
08fd75edc7 | ||
|
|
15ea53864f | ||
|
|
056ee0d58e | ||
|
|
377cd64556 | ||
|
|
b37744d574 | ||
|
|
a7f21fe0c6 | ||
|
|
955ca99cf3 | ||
|
|
98f5bb4124 | ||
|
|
b3943f005d | ||
|
|
8d4178b984 | ||
|
|
2a88ed38c4 | ||
|
|
52dce7dfd3 | ||
|
|
6ebee92542 | ||
|
|
1b5646f526 | ||
|
|
7024e4b40d | ||
|
|
bc2e27d7da | ||
|
|
189da2bfe2 | ||
|
|
12e6afbaad | ||
|
|
142ebe3d27 | ||
|
|
7579f6e42a | ||
|
|
38c25cae74 | ||
|
|
408496eb7c | ||
|
|
4d61c74a8b | ||
|
|
190c610466 | ||
|
|
85b7e3ebe3 | ||
|
|
c6d3fc06a3 | ||
|
|
d220525ac7 | ||
|
|
5e4a631ff2 | ||
|
|
9099ce42b9 | ||
|
|
df226fea22 | ||
|
|
851d2e9151 | ||
|
|
e67ee4ffdb | ||
|
|
2baf975847 | ||
|
|
c1672ebc8e | ||
|
|
bbbd291065 | ||
|
|
0a3c1efdd4 | ||
|
|
89121a2608 | ||
|
|
23cf264d4d | ||
|
|
b3130225b5 | ||
|
|
65512defed | ||
|
|
3b1c8748f1 | ||
|
|
aba660eddb | ||
|
|
137eac7dbf | ||
|
|
fdbd08f511 | ||
|
|
ace1cec1f6 | ||
|
|
0c15e524d7 | ||
|
|
b0b5b1c30d | ||
|
|
30b4c85c5a | ||
|
|
910f9cadfe | ||
|
|
6de37ebd16 | ||
|
|
de57c4e87e | ||
|
|
b85cf66490 | ||
|
|
8e638ea9a6 | ||
|
|
b4849ec495 | ||
|
|
09c12d52ac | ||
|
|
db6a2ddd7e | ||
|
|
12ef9463ab | ||
|
|
fa5fda0c3b | ||
|
|
251609e274 | ||
|
|
a557ad177e | ||
|
|
c0287e49d8 | ||
|
|
78e838f2f0 | ||
|
|
c1f216c7c7 | ||
|
|
b75ff99e4c | ||
|
|
780dd8ade9 | ||
|
|
e1c10b7653 | ||
|
|
be9505f8fe | ||
|
|
d6bcd4f94f | ||
|
|
7d2196f4c3 | ||
|
|
0539174317 | ||
|
|
b4b52e12d5 | ||
|
|
f2e0b1cfa2 | ||
|
|
8020e2a263 | ||
|
|
6112d9b1b0 | ||
|
|
4a1fbcbd31 | ||
|
|
a02a3230f1 | ||
|
|
0218bb4990 | ||
|
|
3769c03565 | ||
|
|
d96cb10476 | ||
|
|
b6b6123434 | ||
|
|
b40877fcc1 | ||
|
|
af5ae29b73 | ||
|
|
082fceebbe | ||
|
|
f1dab80a06 | ||
|
|
cbf2fac2cf | ||
|
|
4564bd7180 | ||
|
|
d12ad7b882 | ||
|
|
f8e9f07a00 | ||
|
|
4ac3891e07 | ||
|
|
a2d55d3fdd | ||
|
|
d015a24300 | ||
|
|
be38acbede | ||
|
|
34d0cb4dc7 | ||
|
|
18d0558b19 | ||
|
|
d4469f3a2d | ||
|
|
43b760b4bf | ||
|
|
3d47932c09 | ||
|
|
7196d6e1bf | ||
|
|
ec06a7d861 | ||
|
|
ef23f0d18e | ||
|
|
e9abc5f07f | ||
|
|
6f9d6ff849 | ||
|
|
eab18d3c11 | ||
|
|
3a509a6a97 | ||
|
|
615c6f4e24 | ||
|
|
96660b4539 | ||
|
|
1be284974b | ||
|
|
790b6478dc | ||
|
|
106344b33e | ||
|
|
85a2a4b873 | ||
|
|
4ab694de0c | ||
|
|
5e193c1725 | ||
|
|
2b055c028c | ||
|
|
b341749e45 | ||
|
|
6ae381b1fd | ||
|
|
352b6cbe04 | ||
|
|
e5e6d2701e | ||
|
|
9ad1924488 | ||
|
|
2aadbfc64a | ||
|
|
1c5d652f93 | ||
|
|
b2355a3b2d | ||
|
|
4ee6d089d5 | ||
|
|
6bd81cbff5 | ||
|
|
b912190c5e | ||
|
|
43a826e2e5 | ||
|
|
8ae64a9dcf | ||
|
|
4ce9faf39b | ||
|
|
d94a67d0af | ||
|
|
d650d91d82 | ||
|
|
e14f59256d | ||
|
|
d3322a4a15 | ||
|
|
a65842e31f | ||
|
|
74fde66b51 | ||
|
|
c3ea155a7b | ||
|
|
c4b81e3d2c | ||
|
|
6f6ed1a741 | ||
|
|
311680c090 | ||
|
|
5e54aa553a | ||
|
|
6913970830 | ||
|
|
014e453e57 | ||
|
|
25b5341f76 | ||
|
|
1df51f9609 | ||
|
|
65d13189b3 | ||
|
|
0913011120 | ||
|
|
30ddc18eb1 | ||
|
|
697d755744 | ||
|
|
e3f23ddc79 | ||
|
|
094acc40e8 | ||
|
|
ebd4991de8 | ||
|
|
d04a8fad4c | ||
|
|
cb14bffc5a | ||
|
|
a4c4d17381 | ||
|
|
21eb27f6e3 | ||
|
|
abf0fc7942 | ||
|
|
c2703edfde | ||
|
|
d14b90ab20 | ||
|
|
48f4924932 | ||
|
|
765551988a | ||
|
|
4883eb0d1b | ||
|
|
06a9a93d1c | ||
|
|
c92a0e1d43 | ||
|
|
c6b5ee164b | ||
|
|
c65075f887 | ||
|
|
a1f678a3a1 | ||
|
|
fe3fefaa4e | ||
|
|
3ccebcb0d1 | ||
|
|
dbbae0eef2 | ||
|
|
f11c4881f3 | ||
|
|
6398c6d7ce | ||
|
|
973ce8c3a7 | ||
|
|
d971869283 | ||
|
|
987002b8f3 | ||
|
|
f73fe495a5 | ||
|
|
fe7b0e2bc7 | ||
|
|
23937c54e0 | ||
|
|
b3d0fd9d2f | ||
|
|
497aaf6143 | ||
|
|
9d6db3a93b | ||
|
|
8a6f3e6809 | ||
|
|
6c419716a4 | ||
|
|
d1a769205c | ||
|
|
b784e342c9 | ||
|
|
0d82fd51c7 | ||
|
|
3b4d905485 | ||
|
|
53c63f0f4b | ||
|
|
5553e3cd8d | ||
|
|
1e195e07e0 | ||
|
|
b6f0e15951 | ||
|
|
da224303fe | ||
|
|
67ee130a9e | ||
|
|
18d908fa63 | ||
|
|
c61f58854e | ||
|
|
f789ecd2f1 | ||
|
|
1fdc30804a | ||
|
|
5ba10d0acb | ||
|
|
12803d8154 | ||
|
|
36c391ccff | ||
|
|
765fb6297c | ||
|
|
66255769ad | ||
|
|
04a8d38641 | ||
|
|
859d020031 | ||
|
|
3c541117d0 | ||
|
|
80ca2e5215 | ||
|
|
19f2aa2997 | ||
|
|
ec657f30c7 | ||
|
|
7e84d495f5 | ||
|
|
c3baedd93c | ||
|
|
ae9676f744 | ||
|
|
7ec156a5d1 | ||
|
|
b80cbea1bc | ||
|
|
4600fa9f32 | ||
|
|
6e0b3e5cdc | ||
|
|
519ff87f5d | ||
|
|
d4a363e37e | ||
|
|
a3cfc45fef | ||
|
|
60602e02d9 | ||
|
|
44366f7872 | ||
|
|
2f18d8c204 | ||
|
|
08efbee52b | ||
|
|
eac8d78c5d | ||
|
|
db73673374 | ||
|
|
281cdb7264 | ||
|
|
101c80d820 | ||
|
|
1e06f65d9e | ||
|
|
eea85709ed | ||
|
|
cbca974529 | ||
|
|
fc27f57580 | ||
|
|
e50dd6606e | ||
|
|
8c9e232d65 | ||
|
|
ef98888394 | ||
|
|
e4b9ba34df | ||
|
|
169e0ec9df | ||
|
|
2779353a32 | ||
|
|
35aabb987c | ||
|
|
06f02070c7 | ||
|
|
d138d3e786 | ||
|
|
dbea68d33a | ||
|
|
72bcabf615 | ||
|
|
5db68eac24 | ||
|
|
7d9d88860e | ||
|
|
06c80ad982 | ||
|
|
c4335527f8 | ||
|
|
90d27a2ad8 | ||
|
|
93fd0a9af0 | ||
|
|
987b0aeb41 | ||
|
|
8dc5ac0b25 | ||
|
|
d310a47523 | ||
|
|
bd8fa3776d | ||
|
|
305796af53 | ||
|
|
60c10a69a3 | ||
|
|
c8aad9839f | ||
|
|
64016a1326 | ||
|
|
a489c7ad8e | ||
|
|
afb9ba7ad6 | ||
|
|
b1de5b1120 | ||
|
|
144a23e89b | ||
|
|
a6763a3e5d | ||
|
|
f047ec787a | ||
|
|
d80c368ccb | ||
|
|
9b60173b8c | ||
|
|
8556974ef1 | ||
|
|
edf9f3a2be | ||
|
|
7bb9414be8 | ||
|
|
6e439adb51 | ||
|
|
f6b783e74a | ||
|
|
171b81461c | ||
|
|
83db76aed8 | ||
|
|
e6d1bb7e5c | ||
|
|
a3d9fe76d6 | ||
|
|
0f4f154637 | ||
|
|
7d112a208f | ||
|
|
c867d39d8d | ||
|
|
83b6c939f7 | ||
|
|
e1e4eb5d6f | ||
|
|
a14c08f122 | ||
|
|
5fd50dcf45 | ||
|
|
b2ac4ee245 | ||
|
|
0ad7c0546b | ||
|
|
748381fef3 | ||
|
|
7eb9e42210 | ||
|
|
36a4b67ef4 | ||
|
|
94b35e3d5f | ||
|
|
c5aa82b76a | ||
|
|
c2920e195f | ||
|
|
92a78a419e | ||
|
|
4f27c2b852 | ||
|
|
ece5779b41 | ||
|
|
167aaa8491 | ||
|
|
de622b055b | ||
|
|
7e88b930ec | ||
|
|
c9adc2b852 | ||
|
|
91d3aba611 | ||
|
|
48bc11dcb5 | ||
|
|
9ee0b32cac | ||
|
|
4b6b74604b | ||
|
|
7ad3fc4751 | ||
|
|
e604450cfb | ||
|
|
9cfbc83896 | ||
|
|
98b2f4ec35 | ||
|
|
47e30f2daf | ||
|
|
6c21da6959 | ||
|
|
c5fe71d390 | ||
|
|
d14ffcb736 | ||
|
|
e694aca70b | ||
|
|
3c58cb1b9c | ||
|
|
dc452cdadf | ||
|
|
e855365cbb | ||
|
|
cffa288227 | ||
|
|
89ddced342 | ||
|
|
7457328b59 | ||
|
|
44ff413810 | ||
|
|
d174c2c2d8 | ||
|
|
480f4c9a8c | ||
|
|
7474cc5d8a | ||
|
|
bda5c4f5dd | ||
|
|
4f5034c167 | ||
|
|
9470db1f4d | ||
|
|
dfeb910ac9 | ||
|
|
a5745795be | ||
|
|
98f2b5dd08 | ||
|
|
f642c7570e | ||
|
|
dca9ea24d7 | ||
|
|
43fd7b6000 | ||
|
|
1553ec3bd4 | ||
|
|
37d54811e0 | ||
|
|
0f2af6eb37 | ||
|
|
91546228fa | ||
|
|
5488ff06e0 | ||
|
|
ef7f050bc5 | ||
|
|
e5c94d9698 | ||
|
|
4d3e0ac5d9 | ||
|
|
0a2f0372be | ||
|
|
e378fc3cfb | ||
|
|
75a1d74d9c | ||
|
|
1404685296 | ||
|
|
0ebed9b46f | ||
|
|
af69352361 | ||
|
|
840e3b861f | ||
|
|
a7cfe7fe04 | ||
|
|
a324cf0fcd | ||
|
|
0919f4c85b | ||
|
|
fd4cc6a1e8 | ||
|
|
d6ae3d4f16 | ||
|
|
9c1819467a | ||
|
|
08410ef209 | ||
|
|
6cd3242454 | ||
|
|
986c1a7bc8 | ||
|
|
a7703ec996 | ||
|
|
52d2eb3f59 | ||
|
|
b19fed41ef | ||
|
|
82a4b2c769 | ||
|
|
1d52cde3b3 | ||
|
|
aca4cc0ace | ||
|
|
8f9a78feb9 | ||
|
|
45484a43f1 | ||
|
|
63665e6e9c | ||
|
|
151665c880 | ||
|
|
15e475873e | ||
|
|
f846af75e8 | ||
|
|
5c7ab3793f | ||
|
|
a501f0cdef | ||
|
|
4b4c2606cd | ||
|
|
901e7581fe | ||
|
|
55fb233ce4 | ||
|
|
dd77ee4a8e | ||
|
|
a7ae6d7b47 | ||
|
|
34dfac8bb2 | ||
|
|
599f783c04 | ||
|
|
c7f82d3d46 | ||
|
|
8b346c6b44 | ||
|
|
e386764151 | ||
|
|
c0acecc6e9 | ||
|
|
a1724134ec | ||
|
|
530b830586 | ||
|
|
363a72c3ad | ||
|
|
c1a6daf9d2 | ||
|
|
8a7a73678c | ||
|
|
6cc8c7cb9d | ||
|
|
e2d1771a7a | ||
|
|
23f7dd6ee3 | ||
|
|
9884ace309 | ||
|
|
70284ac440 | ||
|
|
f24caad997 | ||
|
|
32729350f6 | ||
|
|
4929d190a5 | ||
|
|
0e211dc91b | ||
|
|
8663ab2d28 | ||
|
|
ba0ecaf70f | ||
|
|
acb4f5924e | ||
|
|
46553a80ad | ||
|
|
417334d140 | ||
|
|
e254657813 | ||
|
|
b087df8d97 | ||
|
|
47eb74d5ba | ||
|
|
f0ac047978 | ||
|
|
e57e246991 | ||
|
|
6934cdd122 | ||
|
|
aa7fb74312 | ||
|
|
0e2a77ced7 | ||
|
|
2d135d708e | ||
|
|
26d34f896b | ||
|
|
87c58cae83 | ||
|
|
8429067ae5 | ||
|
|
4d6957a6fa | ||
|
|
70c53248ae | ||
|
|
6e645cb054 | ||
|
|
28fecc6834 | ||
|
|
64c2faf538 | ||
|
|
c514a4d503 | ||
|
|
391d04b45c | ||
|
|
f974c00a63 | ||
|
|
9f0107c002 | ||
|
|
6ce82e915e | ||
|
|
864797fc99 | ||
|
|
c741434e3c | ||
|
|
60fcb1a862 | ||
|
|
18dc6a3ff5 | ||
|
|
da52dd006b | ||
|
|
ed1655ed8f | ||
|
|
516c4e32be | ||
|
|
1e222d806e | ||
|
|
bfb35b198d | ||
|
|
3a5f36155f | ||
|
|
82092fab76 | ||
|
|
a432cb886d | ||
|
|
5fff8c6ba2 | ||
|
|
e1de4f5c5f | ||
|
|
b6145d6f1e | ||
|
|
3804a87cef | ||
|
|
a7a6c664c8 | ||
|
|
f075515607 | ||
|
|
84c15bbc69 | ||
|
|
54e70d490d | ||
|
|
67c3de1f5d | ||
|
|
7281b5b1d7 | ||
|
|
966eb01f1c | ||
|
|
5bdf072cdf | ||
|
|
59c3381962 | ||
|
|
1fa4216b18 | ||
|
|
a98c953876 | ||
|
|
bf995e5861 | ||
|
|
1b8470df38 | ||
|
|
98ded8ea30 | ||
|
|
b72a50eb7e | ||
|
|
9c3f4fbb9d | ||
|
|
28c68308a9 | ||
|
|
ea3b0c15ac | ||
|
|
38ce46adb0 | ||
|
|
0a9a0103dd | ||
|
|
b7b370ff62 | ||
|
|
7b0c98ad2c | ||
|
|
bfe25e70d6 | ||
|
|
b2409df369 | ||
|
|
e1d8549730 | ||
|
|
865cc081ce | ||
|
|
867d5a9eb5 | ||
|
|
ac84b7604b | ||
|
|
8f860ad93e | ||
|
|
f3b65700d7 | ||
|
|
8ec1856206 | ||
|
|
811d2162fc | ||
|
|
5e2cdca103 | ||
|
|
23fb5852ba | ||
|
|
75cbc0d29a | ||
|
|
d08cd684c5 | ||
|
|
529b297ba6 | ||
|
|
32193eef49 | ||
|
|
1f97b90b2d | ||
|
|
0dd36260e9 | ||
|
|
3571d49987 | ||
|
|
ad3489c491 | ||
|
|
2461fa2e25 | ||
|
|
60e49ba343 | ||
|
|
a709381980 | ||
|
|
c2805c8c1c | ||
|
|
0346cbe911 | ||
|
|
74a4d4455b | ||
|
|
3659e1c91f | ||
|
|
09da5c6968 | ||
|
|
2575efd28d | ||
|
|
78c1c8d2b1 | ||
|
|
d5147f3dbb | ||
|
|
593580fbc1 | ||
|
|
67ca1cb638 | ||
|
|
bcf5b64545 | ||
|
|
e37ad663b3 | ||
|
|
4ce7582a46 | ||
|
|
1c371bb7bf | ||
|
|
17fdeb0734 | ||
|
|
5c6f0c32b3 | ||
|
|
e630280673 | ||
|
|
7c87961adf | ||
|
|
0df5ceb7d2 | ||
|
|
54342f2592 | ||
|
|
fbad558c37 | ||
|
|
b27dfb290c | ||
|
|
063c930349 | ||
|
|
c1f1e489a7 | ||
|
|
62960ed8de | ||
|
|
03305e04a7 | ||
|
|
4b294b1125 | ||
|
|
7122a21591 | ||
|
|
9682e571a2 | ||
|
|
2cefbfb8aa | ||
|
|
084062488c | ||
|
|
4dbe2b5297 | ||
|
|
0391e5bc3d | ||
|
|
bcbd96c608 | ||
|
|
6a6633e151 | ||
|
|
5c4546a54c | ||
|
|
255e328340 | ||
|
|
aaf9b085d7 | ||
|
|
c7b14c9fab | ||
|
|
0436ba78e2 | ||
|
|
1085a1c221 | ||
|
|
494b33bd7a | ||
|
|
925e3a67da | ||
|
|
78026f7fa5 | ||
|
|
9d77cac4bb | ||
|
|
6747280964 | ||
|
|
d7dbd79f7c | ||
|
|
aec692c402 | ||
|
|
113bbead4a | ||
|
|
1361c196da | ||
|
|
987995ad68 | ||
|
|
d24db7c053 | ||
|
|
25a9d52d86 | ||
|
|
946c632920 | ||
|
|
94bcbb80fd | ||
|
|
ba58965770 | ||
|
|
e50ddbf348 | ||
|
|
e95f21fa9c | ||
|
|
7026b765bd | ||
|
|
53eedd2701 | ||
|
|
9886c58681 | ||
|
|
953f6da7d7 | ||
|
|
da1efe880d | ||
|
|
bd0b6dd4d2 | ||
|
|
1c049fe1fb | ||
|
|
10b1b87d55 | ||
|
|
3ec6a3b3f2 | ||
|
|
8da919d4cd | ||
|
|
5cd59b795b | ||
|
|
e4dc30d1fb | ||
|
|
2013cee298 | ||
|
|
1f89a6304b | ||
|
|
580e0f9df7 | ||
|
|
2221c4548e | ||
|
|
e06c226e84 | ||
|
|
11a4f0ef32 | ||
|
|
ef15f299d2 | ||
|
|
1d333b9322 | ||
|
|
5302ed8653 | ||
|
|
2cf26a10c4 | ||
|
|
deda1e4251 | ||
|
|
c042bf2d15 | ||
|
|
8ced6aa205 | ||
|
|
3ca514c85b | ||
|
|
27b8e7d5ec | ||
|
|
a2d77a3917 | ||
|
|
c0549fe422 | ||
|
|
0dc8d6fd68 | ||
|
|
cd97647818 | ||
|
|
fcb5811f37 | ||
|
|
a239ba2211 | ||
|
|
e8dc96bcda | ||
|
|
096ad97a73 | ||
|
|
a5a5517555 | ||
|
|
d9b88a5d8d | ||
|
|
8493ea22eb | ||
|
|
aebb87aa20 | ||
|
|
14e97cb24f | ||
|
|
26cc15b4a2 | ||
|
|
50ce606e12 | ||
|
|
b052320f98 | ||
|
|
ecb3cebc9f | ||
|
|
4a32dfc71b | ||
|
|
c913929ff9 | ||
|
|
d7d5b29b07 | ||
|
|
111a7f72f8 | ||
|
|
149abdef9b | ||
|
|
980848f35a | ||
|
|
d1e0c86a71 | ||
|
|
d3872ca8a3 | ||
|
|
003dec269a | ||
|
|
e88092cde7 | ||
|
|
98422bd355 | ||
|
|
af83b89812 | ||
|
|
cffb1b8713 | ||
|
|
0b4895addf | ||
|
|
08646ea12a | ||
|
|
40beb7ceeb | ||
|
|
e7963aa324 | ||
|
|
d5894b9fb7 | ||
|
|
75c47a1113 | ||
|
|
97923b19bf | ||
|
|
879c89a285 | ||
|
|
718727462b | ||
|
|
63f2fd864a | ||
|
|
556dda5790 | ||
|
|
aeaa8549e3 | ||
|
|
1a8a757912 | ||
|
|
c69bb8acc9 | ||
|
|
4989d67b92 | ||
|
|
b272d342b0 | ||
|
|
251b2853e0 | ||
|
|
d381c9505f | ||
|
|
eeb3b8f939 | ||
|
|
ee40f32b0c | ||
|
|
02a69ea6d9 | ||
|
|
d47bb5ecd4 | ||
|
|
d2d6e2f554 | ||
|
|
f48b4a6c62 | ||
|
|
07f7b7df1b | ||
|
|
26486f9d63 | ||
|
|
428aa970b9 | ||
|
|
2a8c532786 | ||
|
|
4381829d16 | ||
|
|
176d75768f | ||
|
|
e28e363bd0 | ||
|
|
114ce1ea3a | ||
|
|
78215552bf | ||
|
|
fc9677f419 | ||
|
|
975a551728 | ||
|
|
be4fe6ab77 | ||
|
|
ab924f6b48 | ||
|
|
e4bf2b4c9b | ||
|
|
c49b1a46f8 | ||
|
|
6a56726734 | ||
|
|
8f6783792f | ||
|
|
b5ab1d6b33 | ||
|
|
25fe1d03a7 | ||
|
|
90546ad4a7 | ||
|
|
939bbc3f2c | ||
|
|
02ee327595 | ||
|
|
d8081277ee | ||
|
|
164a112e0c | ||
|
|
697bde7b53 | ||
|
|
2fd5244f85 | ||
|
|
354d925f94 | ||
|
|
88c74f020c | ||
|
|
9b7021b1cd | ||
|
|
30dbb23330 | ||
|
|
b1696ed1cd | ||
|
|
61f1c99791 | ||
|
|
bb9a559b80 | ||
|
|
5e20ea4975 | ||
|
|
c5d7e30bed | ||
|
|
de5f3a31ed | ||
|
|
7913c4135f | ||
|
|
d49345de9c | ||
|
|
1dbfa71bde | ||
|
|
d46b84f0d6 | ||
|
|
9d456992cf | ||
|
|
5dd62ad2aa | ||
|
|
a293eeb398 | ||
|
|
a6b6b5eb70 | ||
|
|
971af1df5f | ||
|
|
21641da0bf | ||
|
|
a8d9c145e6 | ||
|
|
bfafcb76ba | ||
|
|
52f74f1204 | ||
|
|
00c212ecb2 | ||
|
|
e77d302a49 | ||
|
|
5183f3729c | ||
|
|
e93102f105 | ||
|
|
a4652689ec | ||
|
|
ede1005087 | ||
|
|
e97c7ed32e | ||
|
|
9230a2ab73 | ||
|
|
01ee66ec4f | ||
|
|
4c12cbd3cc | ||
|
|
d8eeeaaef6 | ||
|
|
994dae2a7d | ||
|
|
51da6e928d | ||
|
|
a328ad030e | ||
|
|
ed7605eccd | ||
|
|
de43880a1c | ||
|
|
32b1a5b22d | ||
|
|
795992fb42 | ||
|
|
339eab33c8 | ||
|
|
489f3aa19d | ||
|
|
888e284f84 | ||
|
|
d151114f08 | ||
|
|
4f6a3c23ad | ||
|
|
4ed437fd4e | ||
|
|
fa0b21ba81 | ||
|
|
a96f1d0b49 | ||
|
|
ac0aebd751 | ||
|
|
781cbb4668 | ||
|
|
56ca1911a1 | ||
|
|
c20aec23a2 | ||
|
|
a9cff01579 | ||
|
|
6af56a61b8 | ||
|
|
252db191a6 | ||
|
|
5e2776f264 | ||
|
|
7ec9fb2c44 | ||
|
|
34facb6b3b | ||
|
|
5bb2a1368e | ||
|
|
85a7bbca66 | ||
|
|
2b7f27bf8f | ||
|
|
dd57945e7d | ||
|
|
fa02b4fd56 | ||
|
|
c8715eead5 | ||
|
|
37aae8c10e | ||
|
|
a97ed02e15 | ||
|
|
38ebb2d06a | ||
|
|
c765bfc946 | ||
|
|
b00ac75f33 | ||
|
|
36730168c0 | ||
|
|
4339ece6f6 | ||
|
|
041c997e59 | ||
|
|
098ebb38dc | ||
|
|
b99c38a070 | ||
|
|
07b42d8e74 | ||
|
|
062d168c97 | ||
|
|
c9be5fb125 | ||
|
|
06c6716ee1 | ||
|
|
e856d8fddf | ||
|
|
20339f70c1 | ||
|
|
c2e6cf1eb0 | ||
|
|
8dfdca97cd | ||
|
|
6e8cdc24a3 | ||
|
|
461f1e39fa | ||
|
|
4892dbce5e | ||
|
|
9da32a13de | ||
|
|
9c6908da77 | ||
|
|
ac081e6c86 | ||
|
|
cc9744156c | ||
|
|
72a874c7f4 | ||
|
|
2809324b35 | ||
|
|
58e6c45c73 | ||
|
|
43aaf192a2 | ||
|
|
c0574bc738 | ||
|
|
27e5d639ef | ||
|
|
aa9fdd4fc9 | ||
|
|
7af6d9b2ce | ||
|
|
0e06d28335 | ||
|
|
e3b86e4d41 | ||
|
|
5b1bfe7379 | ||
|
|
76d07b967e | ||
|
|
4b1932fe52 | ||
|
|
a56de91b1e | ||
|
|
6b4fb616bc | ||
|
|
d24670e14e | ||
|
|
13b3ae35ed | ||
|
|
6860e1f085 | ||
|
|
74fa1c6628 | ||
|
|
85f847a4f3 | ||
|
|
39df72d163 | ||
|
|
5ca8786802 | ||
|
|
ca145967dc | ||
|
|
06a3ce7486 | ||
|
|
9f85b6154d | ||
|
|
732763689a | ||
|
|
0ea75f25f1 | ||
|
|
eab27ce0bb | ||
|
|
29fd381989 | ||
|
|
06a845697a | ||
|
|
b12587626d | ||
|
|
b49988032e | ||
|
|
a9b4152553 | ||
|
|
63720045f1 | ||
|
|
aa7529192e | ||
|
|
a162a15a27 | ||
|
|
457a73efae | ||
|
|
91c3dd982b | ||
|
|
c171f93c93 | ||
|
|
0cf9ddb1cd | ||
|
|
2322537350 | ||
|
|
6ce50109da | ||
|
|
abe7fdf34d | ||
|
|
ecf2f5ed8c | ||
|
|
98b4934dd5 | ||
|
|
0bc7c544ad | ||
|
|
1f7ad9d418 | ||
|
|
4b9d3b3dbc | ||
|
|
571e332ed5 | ||
|
|
d78d22b188 | ||
|
|
d37638240a | ||
|
|
ae7fd3f87b | ||
|
|
e82e63b288 | ||
|
|
0149d4e27b | ||
|
|
9fc9c71b6f | ||
|
|
b264f690d1 | ||
|
|
c07e19c898 | ||
|
|
b8e50737d2 | ||
|
|
082d0aa02f | ||
|
|
ca26d0e450 | ||
|
|
8cbe021ffc | ||
|
|
7b39d8025b | ||
|
|
47bd35b151 | ||
|
|
d7add54a3c | ||
|
|
d3c937569b | ||
|
|
94ca613201 | ||
|
|
30f2f635be | ||
|
|
57f4d31c21 | ||
|
|
90e4fd7ff5 | ||
|
|
17835832f2 | ||
|
|
949817f597 | ||
|
|
23065f2c4b | ||
|
|
b623b06cf0 | ||
|
|
55c86d8ec7 | ||
|
|
e955617aa1 | ||
|
|
6304610713 | ||
|
|
47d20928e0 | ||
|
|
c9a4d02e0d | ||
|
|
6513dfb42a | ||
|
|
3f0412453f | ||
|
|
dcba319071 | ||
|
|
d19851fc0c | ||
|
|
d6eb06cb72 | ||
|
|
473080d7ee | ||
|
|
c98a6adb09 | ||
|
|
2cd56d5041 | ||
|
|
982098672e | ||
|
|
445ecea3e6 | ||
|
|
db977dfba4 | ||
|
|
a3c12ab9f5 | ||
|
|
0f7e152650 | ||
|
|
b55c7ba9a1 | ||
|
|
8256c9f7ad | ||
|
|
59727d7b0b | ||
|
|
2dd2210a73 | ||
|
|
25aafdbebc | ||
|
|
cd5717169c | ||
|
|
a38ad5a11e | ||
|
|
66d9b56976 | ||
|
|
ac40bd1e17 | ||
|
|
16d2a9bf99 | ||
|
|
b7e6838d26 | ||
|
|
21d23b5baa | ||
|
|
69a2941d57 | ||
|
|
3cc2abf8b9 | ||
|
|
6f4173650a | ||
|
|
0fcb8bdc0a | ||
|
|
c0937cf412 | ||
|
|
d9ab3aab0f | ||
|
|
c8652de78b | ||
|
|
86dc4e2bd5 | ||
|
|
1b9c56a9b9 | ||
|
|
08ab504fac | ||
|
|
21c0842fae | ||
|
|
8d10feaa68 | ||
|
|
df2171f253 | ||
|
|
f5fcd94faf | ||
|
|
15c5dbef00 | ||
|
|
79df56c096 | ||
|
|
d3fffd9530 | ||
|
|
527c9c8e6e | ||
|
|
d285be45cb | ||
|
|
0dda9c73f6 | ||
|
|
d07bf270e7 | ||
|
|
eb24dd5d9e | ||
|
|
ce693c7cd5 | ||
|
|
3198890269 | ||
|
|
eacc93de43 | ||
|
|
9795740257 | ||
|
|
4548f5d8aa | ||
|
|
8dfd2fb519 | ||
|
|
83a40f83e1 | ||
|
|
5b2fcb3c6c | ||
|
|
bcd9adb66d | ||
|
|
5e2dc114ab | ||
|
|
1ced4531be | ||
|
|
05fe39c0ae | ||
|
|
3769b2b3ea | ||
|
|
f4d5480f6f | ||
|
|
ddf3c0810b | ||
|
|
6afd6d0aa0 | ||
|
|
59fe92eb04 | ||
|
|
0550f32434 | ||
|
|
b702cad549 | ||
|
|
aa5c4d3c5e | ||
|
|
6a99445d97 | ||
|
|
c9880ef47d | ||
|
|
c16452dfcb | ||
|
|
af802c02fc | ||
|
|
8028aafeff | ||
|
|
b7469062a1 | ||
|
|
33b707aa68 | ||
|
|
cd3a1bebff | ||
|
|
794dd5a797 | ||
|
|
a1465432e8 | ||
|
|
e1f8af0909 | ||
|
|
88918be329 | ||
|
|
a3fc1dbff0 | ||
|
|
626c9825cc | ||
|
|
c10a84fc79 | ||
|
|
f14e4fe197 | ||
|
|
6eb218db5e | ||
|
|
0e77e053b0 | ||
|
|
b9a4128a3d | ||
|
|
16f480e1f3 | ||
|
|
7c42511133 | ||
|
|
1b252a84c2 | ||
|
|
bf833cadff | ||
|
|
b6f872882a | ||
|
|
a18d6fb441 | ||
|
|
922e703e81 | ||
|
|
d7f5817b8b | ||
|
|
92a8a4bfa6 | ||
|
|
b480151fc3 | ||
|
|
37bdbc1bd5 | ||
|
|
8eb669139b | ||
|
|
b485e8cacc | ||
|
|
c4bab61c47 | ||
|
|
72be417ff1 | ||
|
|
9be483d7a6 | ||
|
|
910f2cee2c | ||
|
|
1e47ace527 | ||
|
|
912b06b145 | ||
|
|
87d878e287 | ||
|
|
be886d6bce | ||
|
|
0683deb47e | ||
|
|
114bb22e27 | ||
|
|
c327ebc3df | ||
|
|
92cbd1c69c | ||
|
|
7242515e48 | ||
|
|
401d1a0ac2 | ||
|
|
863e042a37 | ||
|
|
39e6c45ec6 | ||
|
|
0d364d18c7 | ||
|
|
61444ea390 | ||
|
|
106a935efb | ||
|
|
d175d8a853 | ||
|
|
ce6d19a77a | ||
|
|
0a29273924 | ||
|
|
5ede64de58 | ||
|
|
224c6ad798 | ||
|
|
57b3a0dbe7 | ||
|
|
f381f708e0 | ||
|
|
63bf149546 | ||
|
|
cb5e671259 | ||
|
|
3e38173c4e | ||
|
|
efacb643fc | ||
|
|
1bd153ea0b | ||
|
|
bac3dc5f4c | ||
|
|
959a853d77 | ||
|
|
90bbdd563b | ||
|
|
e3c6d05a0a | ||
|
|
930b3d4538 | ||
|
|
74b78141b4 | ||
|
|
aa1108cd5b | ||
|
|
f24b1a9db3 | ||
|
|
71b191e740 | ||
|
|
8f6341b903 | ||
|
|
161586db7e | ||
|
|
052262bef9 | ||
|
|
a5a7144707 | ||
|
|
d945e0426d | ||
|
|
926970c4eb | ||
|
|
cce36e0f28 | ||
|
|
48c6dc5be5 | ||
|
|
c641830825 | ||
|
|
eba16cc15d | ||
|
|
bd88b8411e | ||
|
|
fc121e8750 | ||
|
|
d4142fe56a | ||
|
|
f76a3e72bb | ||
|
|
2d400ae7eb | ||
|
|
edf1632cab | ||
|
|
a648f1ee67 | ||
|
|
d004e6e86c | ||
|
|
fa321d3e8d | ||
|
|
e1e53d323f | ||
|
|
ccb18ca302 | ||
|
|
e170f36bc6 | ||
|
|
4bd9cc51ee | ||
|
|
43ffbda1a4 | ||
|
|
8240485fd1 | ||
|
|
7f053c0567 | ||
|
|
d2922eb0b7 | ||
|
|
fec10d453f | ||
|
|
162040545d | ||
|
|
f14577f8bf | ||
|
|
e5720bd1be | ||
|
|
6d4959bac8 | ||
|
|
d668128a34 | ||
|
|
f2af38da4c | ||
|
|
4776d18fd7 | ||
|
|
cdd0be7b78 | ||
|
|
cd505abb22 | ||
|
|
28439c010f | ||
|
|
e85f43beb1 | ||
|
|
a06cbc0840 | ||
|
|
adef9728f8 | ||
|
|
ff1b688b6e | ||
|
|
3e7574a927 | ||
|
|
f852ea90ad | ||
|
|
d8f6247c32 | ||
|
|
9dc28393a5 | ||
|
|
c442c98ecf | ||
|
|
71e0109927 | ||
|
|
9c7dd5ed1c | ||
|
|
83620848f2 | ||
|
|
d548a5b4f3 | ||
|
|
b6e5307755 | ||
|
|
4c5dc5a145 | ||
|
|
69ed9172b8 | ||
|
|
68551ae176 | ||
|
|
c97d9d35ba | ||
|
|
e86cc97cdf | ||
|
|
9bff8608c1 | ||
|
|
a10fe6994a | ||
|
|
67e6a37b59 | ||
|
|
3075a56735 | ||
|
|
7e4a862cc3 | ||
|
|
ed2078ee3b | ||
|
|
f99c23a622 | ||
|
|
41e7317764 | ||
|
|
e0a78c2399 | ||
|
|
95ad39d2d4 | ||
|
|
b831f827b1 | ||
|
|
c5d8413d9c | ||
|
|
4648ea3424 | ||
|
|
e05bd6f231 | ||
|
|
caadee7901 | ||
|
|
18c524117d | ||
|
|
ad30fb8b04 | ||
|
|
a8077965a9 | ||
|
|
532ab85ebb | ||
|
|
546227eb37 | ||
|
|
7ec3b262d3 | ||
|
|
c435000d24 | ||
|
|
eaa60c281e | ||
|
|
cd7cf63144 | ||
|
|
6a704aa079 | ||
|
|
d6b5a1cec8 | ||
|
|
9a24ad31cc | ||
|
|
9331630b54 | ||
|
|
904e869d7f | ||
|
|
307fa4f5e6 | ||
|
|
131d16d3ea | ||
|
|
dbc54c45dd | ||
|
|
a96a84d509 | ||
|
|
3eb8863f67 | ||
|
|
8737ab077b | ||
|
|
50bb6a1d19 | ||
|
|
4181b75af7 | ||
|
|
620705c87a | ||
|
|
50b7b93529 | ||
|
|
6f18f6bd5c | ||
|
|
01d256eeee | ||
|
|
a1405412a8 | ||
|
|
58589b3a15 | ||
|
|
2983266fdf | ||
|
|
e33df8f12d | ||
|
|
0e0e8e9d18 | ||
|
|
37f8b54752 | ||
|
|
e9a086ad23 | ||
|
|
7c06a8ac41 | ||
|
|
70801d958e | ||
|
|
cf3f95c952 | ||
|
|
d708616a6a | ||
|
|
17711bc5c9 | ||
|
|
1e2474921b | ||
|
|
3f37b2b728 | ||
|
|
18b11df672 | ||
|
|
c34f2d4da7 | ||
|
|
d61792581a | ||
|
|
76d9a511b8 | ||
|
|
4248326697 | ||
|
|
a540b38151 | ||
|
|
8fb5ef0c1d | ||
|
|
2da4979e59 | ||
|
|
0146e4a1dd | ||
|
|
34bdb72ffd | ||
|
|
2ef7c63047 | ||
|
|
95f5417761 | ||
|
|
4922ec4499 | ||
|
|
20d947a199 | ||
|
|
c9444c5318 | ||
|
|
871dc90ee4 | ||
|
|
d1925945b4 | ||
|
|
6625080fde | ||
|
|
1110609e39 | ||
|
|
f21d2c7253 | ||
|
|
9c1d330945 | ||
|
|
cd7800056c | ||
|
|
7ff4bec3bc | ||
|
|
d305cf2167 | ||
|
|
e77b83bd92 | ||
|
|
171d58658a | ||
|
|
a6f6bc4c0a | ||
|
|
f03cffe3f8 | ||
|
|
809dca184e | ||
|
|
ecda226949 | ||
|
|
ff1b58ebd8 | ||
|
|
5760ada3b4 | ||
|
|
b74b6b3284 | ||
|
|
e4cc4b6f58 | ||
|
|
dd90851477 | ||
|
|
da9b127468 | ||
|
|
d6b05e44cb | ||
|
|
58c1b5b98d | ||
|
|
c270cba8d6 | ||
|
|
58f1f749fc | ||
|
|
38d87a7c8f | ||
|
|
4e13598708 | ||
|
|
4177448d32 | ||
|
|
e4911a6f82 | ||
|
|
159224700f | ||
|
|
696d4e7342 | ||
|
|
ffb6cfaa4a | ||
|
|
b8899fcafa | ||
|
|
aba829c991 | ||
|
|
8f4c61c259 | ||
|
|
a19648a6e8 | ||
|
|
d5c0f7045e | ||
|
|
6f69205818 | ||
|
|
8166da548c | ||
|
|
d54f7293b7 | ||
|
|
225520a765 | ||
|
|
af1eccde8e | ||
|
|
5d37280643 | ||
|
|
80597039f5 | ||
|
|
2766aedc01 | ||
|
|
da3e12cb7e | ||
|
|
8baff1b0d2 | ||
|
|
4ff5f9204e | ||
|
|
515339bbd8 | ||
|
|
943634b0e2 | ||
|
|
212b26b960 | ||
|
|
c0b41987aa | ||
|
|
b4ef640052 | ||
|
|
db6b7f52eb | ||
|
|
55b4b9e02a | ||
|
|
4e6ae93b13 | ||
|
|
c9a5fe5676 | ||
|
|
a5adfb7c7f | ||
|
|
1794b86041 | ||
|
|
f405124ce4 | ||
|
|
25060c1477 | ||
|
|
6ad218f354 | ||
|
|
d1c52548b0 | ||
|
|
9dc847b72f | ||
|
|
5b04adb21f | ||
|
|
356d25e548 | ||
|
|
a9958af818 | ||
|
|
fb359b7f87 | ||
|
|
7f087819a6 | ||
|
|
e836fa3d38 | ||
|
|
9a69f1108d | ||
|
|
2c5c58dc90 | ||
|
|
cb50d2838a | ||
|
|
aff7125914 | ||
|
|
45d82dce04 | ||
|
|
7a3b27227a | ||
|
|
7b50a19b2c | ||
|
|
741b942dea | ||
|
|
f7ca64a49d | ||
|
|
2f7b3455e5 | ||
|
|
1568dfc183 | ||
|
|
d3a5df0007 | ||
|
|
c20cac621a | ||
|
|
74560c3289 | ||
|
|
f94bf3f8ce | ||
|
|
d26db7096d | ||
|
|
afde0a7423 | ||
|
|
cc930a3ff9 | ||
|
|
60ecdadc74 | ||
|
|
82fc1850cf | ||
|
|
88f937f73e | ||
|
|
b3497c7306 | ||
|
|
366ab2e0cd | ||
|
|
98e4fabd2e | ||
|
|
716c3573fd | ||
|
|
842d8dd780 | ||
|
|
c767dfb22e | ||
|
|
f94901c3b2 | ||
|
|
c9638aefe9 | ||
|
|
8bd4721686 | ||
|
|
808f7504c3 | ||
|
|
8ea7d3d5e8 | ||
|
|
d4931890ae | ||
|
|
f4a879a452 | ||
|
|
78521ffdb4 | ||
|
|
8ea3f80b97 | ||
|
|
0d8d87857c | ||
|
|
3a3a261d9c | ||
|
|
2e00daf63c | ||
|
|
1b8bb0c1fd | ||
|
|
5c33579544 | ||
|
|
f8081ff09e | ||
|
|
01b7eeeecf | ||
|
|
d2f4c374a9 | ||
|
|
07073eebe9 | ||
|
|
590a4ae476 | ||
|
|
b553a81d47 | ||
|
|
7d4e53e413 | ||
|
|
839b0f6f5e | ||
|
|
893c5da4ef | ||
|
|
f9b893edfa | ||
|
|
b4fadb39bf | ||
|
|
310f8bf6f7 | ||
|
|
903a26a330 | ||
|
|
41ebd39810 | ||
|
|
281de5196e | ||
|
|
a9ab864cbb | ||
|
|
f3ff910821 | ||
|
|
ba5179f1e8 | ||
|
|
05e8f6ed78 | ||
|
|
23150815a0 | ||
|
|
a50f223fe3 | ||
|
|
9329345d98 | ||
|
|
c71c32b363 | ||
|
|
5590aa7234 | ||
|
|
4a3491e0b5 | ||
|
|
e8cb87ae3d | ||
|
|
2f6427af32 | ||
|
|
5564047001 | ||
|
|
22577c5f87 | ||
|
|
4dc2627da2 | ||
|
|
05aaf0de9f | ||
|
|
951bfa23f3 | ||
|
|
7ac6cfcf25 | ||
|
|
06055a7c4c | ||
|
|
b33198d1bf | ||
|
|
f826b9eb6e | ||
|
|
2b58121552 | ||
|
|
762547d0e9 | ||
|
|
727523eb3f | ||
|
|
5bbdb66eb2 | ||
|
|
c6eff4f90d | ||
|
|
2559173c2c | ||
|
|
8adea132ef | ||
|
|
9d924f8d1c | ||
|
|
1b297fed90 | ||
|
|
2c2a93c440 | ||
|
|
bb076cce5d | ||
|
|
b16b02c3f1 | ||
|
|
3e0f834796 | ||
|
|
0af38c6e0e | ||
|
|
85f7011e03 | ||
|
|
e8d5412e14 | ||
|
|
170cf4753e | ||
|
|
660e76145e | ||
|
|
31a6f7b621 | ||
|
|
f6699ad93b | ||
|
|
6e508e4454 | ||
|
|
2b101844e9 | ||
|
|
fb036935e6 | ||
|
|
c3e09ddab0 | ||
|
|
36ae07074d | ||
|
|
a4518ce261 | ||
|
|
861ea7ef94 | ||
|
|
541af0b77e | ||
|
|
3fd3de1828 | ||
|
|
3e2840ca15 | ||
|
|
839ec9a456 | ||
|
|
bac8bd0006 | ||
|
|
8c1b51b7e9 | ||
|
|
a71c4fe7ec | ||
|
|
b9d4197b5c | ||
|
|
ce7559087e | ||
|
|
110d87e512 | ||
|
|
cd817714cd | ||
|
|
23db345756 | ||
|
|
16990bd0c3 | ||
|
|
2e3b770bea | ||
|
|
28f62623bf | ||
|
|
c9f3e8cb9f | ||
|
|
6b751eb715 | ||
|
|
5d953da267 | ||
|
|
e87ae31a51 | ||
|
|
9f029b892b | ||
|
|
40a9ced0f7 | ||
|
|
87fbd7e5da | ||
|
|
bca5514a76 | ||
|
|
62ddbb20ac | ||
|
|
9d376961f4 | ||
|
|
e77aa00bcd | ||
|
|
465330820d | ||
|
|
ec9cbba67e | ||
|
|
8961ea6fc9 | ||
|
|
ca7ca9da81 | ||
|
|
2a234f14df | ||
|
|
3ff97bf628 | ||
|
|
416d6f2aef | ||
|
|
ecaafaca69 | ||
|
|
fdb14cd49b | ||
|
|
070e955b89 | ||
|
|
9390ab3c6c | ||
|
|
f67221ee01 | ||
|
|
e09294d9aa | ||
|
|
5675acb71a | ||
|
|
0305a5dcef | ||
|
|
5f03340454 | ||
|
|
0f69ba46c5 | ||
|
|
71ecb6bd4e | ||
|
|
2b712cc808 | ||
|
|
3a68b7b554 | ||
|
|
e41727a1fc | ||
|
|
857d0f3316 | ||
|
|
1f68f62689 | ||
|
|
09b43a8e95 | ||
|
|
b8d765d229 | ||
|
|
06a919ff8d | ||
|
|
ea1e7769b1 | ||
|
|
d5e6f99819 | ||
|
|
a5ab9726dd | ||
|
|
6464fc56d8 | ||
|
|
156e1b928c | ||
|
|
edf17b8100 | ||
|
|
5ab980ce1a | ||
|
|
f1d80fadc4 | ||
|
|
d331d48ca2 | ||
|
|
e740db11ed | ||
|
|
6cff7b3c30 | ||
|
|
88cdd2fcbf | ||
|
|
55896be694 | ||
|
|
c4f17e42e1 | ||
|
|
e8b11bd42a | ||
|
|
a566fb3988 | ||
|
|
de071b37eb | ||
|
|
7b4d408733 | ||
|
|
06478d89ea | ||
|
|
7cedf4c620 | ||
|
|
ef1ea5eeee | ||
|
|
96f222db94 | ||
|
|
065eb9b878 | ||
|
|
ed583d80a3 | ||
|
|
7752db3916 | ||
|
|
e18254e4d8 | ||
|
|
555fc97e8f | ||
|
|
f135adfdba | ||
|
|
72b766f32a | ||
|
|
5278861ccd | ||
|
|
ebcf88070c | ||
|
|
273811bbb8 | ||
|
|
26b53e725d | ||
|
|
5434ec85e2 | ||
|
|
91f438aeff | ||
|
|
501f67ebe7 | ||
|
|
be52fef0bb | ||
|
|
2c0cf40a15 | ||
|
|
8566070d9b | ||
|
|
8f4118a6b8 | ||
|
|
54c53f0b56 | ||
|
|
eafcee8c67 | ||
|
|
5c8e1e0f4a | ||
|
|
76043d5876 | ||
|
|
936f3b0752 | ||
|
|
9380608781 | ||
|
|
544b75bcd5 | ||
|
|
2ae63d2323 | ||
|
|
f24717a3a3 | ||
|
|
f0f5558f3e | ||
|
|
3d8c732258 | ||
|
|
f312237bd5 | ||
|
|
952dde3fef | ||
|
|
e5387f6d06 | ||
|
|
93d6697b4e | ||
|
|
bad2f3415a | ||
|
|
d2f5d97282 | ||
|
|
f8c3fef839 | ||
|
|
14b47a929f | ||
|
|
4b3c0466eb | ||
|
|
041397b137 | ||
|
|
6548c286a6 | ||
|
|
ccf78285b6 | ||
|
|
5e9366fa92 | ||
|
|
0e30cb1439 | ||
|
|
b8d86518e7 | ||
|
|
725399ac7c | ||
|
|
ca18994092 | ||
|
|
caefc438b9 | ||
|
|
0ece8c7dec | ||
|
|
e7c42f3623 | ||
|
|
18faf89b89 | ||
|
|
3a750ae6a2 | ||
|
|
48c614d8c3 | ||
|
|
c37d502c27 | ||
|
|
3fed7a081d | ||
|
|
e75497d03b | ||
|
|
6d1421f1b7 | ||
|
|
dd210be037 | ||
|
|
7c7d6ad548 | ||
|
|
2f471c0e3f | ||
|
|
cff219674f | ||
|
|
e35f9eb75b | ||
|
|
ef1eff2ecb | ||
|
|
244ff61fb3 | ||
|
|
50e2623f19 | ||
|
|
fd0b997c13 | ||
|
|
13d057e4f7 | ||
|
|
d1a6be6ca6 | ||
|
|
edece02c13 | ||
|
|
d68cf4e44d | ||
|
|
9d85a58634 | ||
|
|
c4a4cd0957 | ||
|
|
5af7615054 | ||
|
|
a68a1334fc | ||
|
|
dd3e38355c | ||
|
|
890461bcf8 | ||
|
|
750265cb79 | ||
|
|
004de824ba | ||
|
|
fc43b35628 | ||
|
|
696653f945 | ||
|
|
157dca50e9 | ||
|
|
7d2130b229 | ||
|
|
2cc81211af | ||
|
|
ea9a5b0eb0 | ||
|
|
e60cee6a73 | ||
|
|
a3ee60a464 | ||
|
|
28595cbeb3 | ||
|
|
dbdbf5210e | ||
|
|
a4876f6f14 | ||
|
|
9835ae7e50 | ||
|
|
59f763162c | ||
|
|
a9412b418f | ||
|
|
742c5b76fe | ||
|
|
7a85fc0179 | ||
|
|
73e73ffe58 | ||
|
|
3c5523894d | ||
|
|
4b9c76d3db | ||
|
|
0a694eea8a | ||
|
|
87f48dad79 | ||
|
|
68ef50ca46 | ||
|
|
8b1da33ffe | ||
|
|
9a9b18a3ef | ||
|
|
83f69d89ff | ||
|
|
0bd7d23114 | ||
|
|
9b860a6aa6 | ||
|
|
4812519a4c | ||
|
|
f3ce6ad467 | ||
|
|
78d9b48854 | ||
|
|
b37d0eba04 | ||
|
|
5289b3f54c | ||
|
|
5c08fe0611 | ||
|
|
4bc9b70882 | ||
|
|
3f98f9ff39 | ||
|
|
e78a7bfbf1 | ||
|
|
b8b1412bf8 | ||
|
|
a81d66ace3 | ||
|
|
dcfd72b7e7 | ||
|
|
6467db4a21 | ||
|
|
f2570c97f3 | ||
|
|
98ad518b5d | ||
|
|
7a5e17a345 | ||
|
|
fde257c722 | ||
|
|
97357f082d | ||
|
|
6875bd82fc | ||
|
|
b1f6cad741 | ||
|
|
fb28fec60d | ||
|
|
500130be59 | ||
|
|
101173c87c | ||
|
|
4fb1b0dbd1 | ||
|
|
4270d5e8ec | ||
|
|
fe9f1146ce | ||
|
|
6fce43a122 | ||
|
|
a8a8f9b3e5 | ||
|
|
0dd0125e9f | ||
|
|
d3d97b5924 | ||
|
|
c8462fb50b | ||
|
|
c99ca9edcc | ||
|
|
fc7e96feb9 | ||
|
|
31dd7be296 | ||
|
|
2899373e42 | ||
|
|
7640c3d0ef | ||
|
|
af7772f617 | ||
|
|
a1670caf06 | ||
|
|
61e35b9773 | ||
|
|
e4671ffdb3 | ||
|
|
3035f923cb | ||
|
|
97e83def48 | ||
|
|
ba31deaebf | ||
|
|
bd571dc93d | ||
|
|
c1da8321ac | ||
|
|
0a1972b854 | ||
|
|
96f387e90b | ||
|
|
e034fc1019 | ||
|
|
d539912762 | ||
|
|
85b72af3bb | ||
|
|
3004f4b583 | ||
|
|
78dbd7eacd | ||
|
|
add73e6f16 | ||
|
|
2c5a7d103d | ||
|
|
f8f855d5d2 | ||
|
|
f2c109116c | ||
|
|
41c63fab96 | ||
|
|
de94651fca | ||
|
|
611c468b70 | ||
|
|
fd2207e39e | ||
|
|
10564442e2 | ||
|
|
a44307ca2d | ||
|
|
cfea2ed954 | ||
|
|
62e59605ed | ||
|
|
2644b1b7ac | ||
|
|
6e4c6d0c54 | ||
|
|
2b7d950a9f | ||
|
|
5ece8d67f9 | ||
|
|
8511b67811 | ||
|
|
a0a444e476 | ||
|
|
6fec92926d | ||
|
|
2cbefb261b | ||
|
|
4bebbb158c | ||
|
|
8fe2172c0a | ||
|
|
f52ef2d57e | ||
|
|
3f1c005548 | ||
|
|
821bd2b2d8 | ||
|
|
d8405feab3 | ||
|
|
bd94437c05 | ||
|
|
b290bdb473 | ||
|
|
f8e2af4fd4 | ||
|
|
97c8dfa5b9 | ||
|
|
37cce68e2e | ||
|
|
1f87a71b98 | ||
|
|
5511ea1887 | ||
|
|
e371081a1d | ||
|
|
70816b48e8 | ||
|
|
2c9fc7b4a7 | ||
|
|
3bb4652a49 | ||
|
|
d5f8e01dd8 | ||
|
|
27e0517f9a | ||
|
|
f59aeda28e | ||
|
|
a8a69f8c36 | ||
|
|
4ae6b8328e | ||
|
|
6d4337e4ce | ||
|
|
3df928caf4 | ||
|
|
faeb33fdc0 | ||
|
|
bacdeb20eb | ||
|
|
781c426b2f | ||
|
|
d5c9fb8dec | ||
|
|
78c372b9d8 | ||
|
|
ea31069609 | ||
|
|
3f9a3e8f64 | ||
|
|
2f02715efd | ||
|
|
c94fa64a33 | ||
|
|
e2cb666b3c | ||
|
|
9f24e0145b | ||
|
|
41413471aa | ||
|
|
f8a11166f0 | ||
|
|
27517b3b47 | ||
|
|
834c0d92b4 | ||
|
|
e04215f0e1 | ||
|
|
9fa8d98ae8 | ||
|
|
31621f273b | ||
|
|
41f158dac1 | ||
|
|
e5687f3a7c | ||
|
|
1a5b684e1f | ||
|
|
bf70c487ca | ||
|
|
4e1d34ba77 | ||
|
|
3a75ad61f3 |
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,12 +1,14 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve DbGate
|
||||
about: Create a report to help us improve DbGate (in ENGLISH)
|
||||
title: 'BUG: Say something here'
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please keep communication in ENGLISH to reach more contributors.
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/feature_request.md
vendored
4
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,12 +1,14 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for DbGate
|
||||
about: Suggest an idea for DbGate (in ENGLISH)
|
||||
title: 'FEAT: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please keep communication in ENGLISH to reach more contributors.
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/question.md
vendored
4
.github/ISSUE_TEMPLATE/question.md
vendored
@@ -1,12 +1,14 @@
|
||||
---
|
||||
name: Question
|
||||
about: Ask a question about how to do something
|
||||
about: Ask a question about how to do something (in ENGLISH)
|
||||
title: 'QUESTION: Summary of your question'
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please keep communication in ENGLISH to reach more contributors.
|
||||
|
||||
**Details:**
|
||||
Details about your question
|
||||
|
||||
|
||||
57
.github/workflows/build-app-beta.yaml
vendored
57
.github/workflows/build-app-beta.yaml
vendored
@@ -6,9 +6,13 @@ name: Electron app BETA
|
||||
push:
|
||||
tags:
|
||||
- v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: dbgate-app
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -17,6 +21,10 @@ jobs:
|
||||
- windows-2022
|
||||
- ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- run: python -m pip install --upgrade pip setuptools
|
||||
- name: Install python 3.11 (MacOS)
|
||||
if: matrix.os == 'macos-14'
|
||||
run: |
|
||||
@@ -53,12 +61,6 @@ jobs:
|
||||
run: |
|
||||
|
||||
yarn setCurrentVersion
|
||||
- name: printSecrets
|
||||
run: |
|
||||
|
||||
yarn printSecrets
|
||||
env:
|
||||
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
|
||||
- name: fillPackagedPlugins
|
||||
run: |
|
||||
|
||||
@@ -66,21 +68,53 @@ jobs:
|
||||
- name: Install Snapcraft
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
uses: samuelmeuli/action-snapcraft@v1
|
||||
- name: Publish
|
||||
- name: Publish Windows
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: |
|
||||
|
||||
yarn run build:app
|
||||
- name: Publish MacOS
|
||||
if: matrix.os == 'macos-14'
|
||||
run: |
|
||||
|
||||
yarn run build:app
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
|
||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
|
||||
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
||||
- name: Publish Linux
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: |
|
||||
|
||||
yarn run build:app
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||
- name: Azure login (OIDC)
|
||||
uses: azure/login@v2
|
||||
if: matrix.os == 'windows-2022'
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
|
||||
allow-no-subscriptions: true
|
||||
- name: Sign Windows artifacts with Azure Trusted Signing
|
||||
uses: azure/trusted-signing-action@v0
|
||||
if: matrix.os == 'windows-2022'
|
||||
with:
|
||||
endpoint: https://wus3.codesigning.azure.net/
|
||||
trusted-signing-account-name: DbGate
|
||||
certificate-profile-name: DbGate-Release
|
||||
files-folder: app/dist
|
||||
files-folder-filter: exe
|
||||
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||
timestamp-digest: SHA256
|
||||
- name: Fix YML hashes
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: |
|
||||
|
||||
yarn run fixYmlHashes
|
||||
- name: Copy artifacts
|
||||
run: |
|
||||
mkdir artifacts
|
||||
@@ -92,6 +126,7 @@ jobs:
|
||||
cp app/dist/*win*.exe artifacts/dbgate-beta.exe || true
|
||||
cp app/dist/*win_x64.zip artifacts/dbgate-windows-beta.zip || true
|
||||
cp app/dist/*win_arm64.zip artifacts/dbgate-windows-beta-arm64.zip || true
|
||||
cp app/dist/*win_arm64.exe artifacts/dbgate-windows-beta-arm64.exe || true
|
||||
cp app/dist/*-mac_universal.dmg artifacts/dbgate-beta.dmg || true
|
||||
cp app/dist/*-mac_x64.dmg artifacts/dbgate-beta-x64.dmg || true
|
||||
cp app/dist/*-mac_arm64.dmg artifacts/dbgate-beta-arm64.dmg || true
|
||||
|
||||
146
.github/workflows/build-app-check.yaml
vendored
Normal file
146
.github/workflows/build-app-check.yaml
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# This file is generated. Do not edit manually
|
||||
# --------------------------------------------------------------------------------------------
|
||||
name: Electron app check build
|
||||
'on':
|
||||
push:
|
||||
tags:
|
||||
- check-[0-9]+-[0-9]+-[0-9]+.[0-9]+
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: dbgate-app
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- macos-14
|
||||
- windows-2022
|
||||
- ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- run: python -m pip install --upgrade pip setuptools
|
||||
- name: Install python 3.11 (MacOS)
|
||||
if: matrix.os == 'macos-14'
|
||||
run: |
|
||||
brew install python@3.11
|
||||
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
|
||||
- name: Context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 22.x
|
||||
- name: adjustPackageJson
|
||||
run: |
|
||||
|
||||
node adjustPackageJson --community
|
||||
- name: yarn set timeout
|
||||
run: |
|
||||
|
||||
yarn config set network-timeout 100000
|
||||
- name: yarn install
|
||||
run: |
|
||||
|
||||
yarn install
|
||||
- name: setCurrentVersion
|
||||
run: |
|
||||
|
||||
yarn setCurrentVersion
|
||||
- name: fillPackagedPlugins
|
||||
run: |
|
||||
|
||||
yarn fillPackagedPlugins
|
||||
- name: Install Snapcraft
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
uses: samuelmeuli/action-snapcraft@v1
|
||||
- name: Publish Windows
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: |
|
||||
|
||||
yarn run build:app
|
||||
- name: Publish MacOS
|
||||
if: matrix.os == 'macos-14'
|
||||
run: |
|
||||
|
||||
yarn run build:app
|
||||
env:
|
||||
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
||||
- name: Publish Linux
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: |
|
||||
|
||||
yarn run build:app
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||
- name: Azure login (OIDC)
|
||||
uses: azure/login@v2
|
||||
if: matrix.os == 'windows-2022'
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
|
||||
allow-no-subscriptions: true
|
||||
- name: Sign Windows artifacts with Azure Trusted Signing
|
||||
uses: azure/trusted-signing-action@v0
|
||||
if: matrix.os == 'windows-2022'
|
||||
with:
|
||||
endpoint: https://wus3.codesigning.azure.net/
|
||||
trusted-signing-account-name: DbGate
|
||||
certificate-profile-name: DbGate-Release
|
||||
files-folder: app/dist
|
||||
files-folder-filter: exe
|
||||
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||
timestamp-digest: SHA256
|
||||
- name: Fix YML hashes
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: |
|
||||
|
||||
yarn run fixYmlHashes
|
||||
- name: Copy artifacts
|
||||
run: |
|
||||
mkdir artifacts
|
||||
|
||||
cp app/dist/*.deb artifacts/dbgate-check.deb || true
|
||||
cp app/dist/*x86*.AppImage artifacts/dbgate-check.AppImage || true
|
||||
cp app/dist/*arm64*.AppImage artifacts/dbgate-check-arm64.AppImage || true
|
||||
cp app/dist/*armv7l*.AppImage artifacts/dbgate-check-armv7l.AppImage || true
|
||||
cp app/dist/*win*.exe artifacts/dbgate-check.exe || true
|
||||
cp app/dist/*win_x64.zip artifacts/dbgate-windows-check.zip || true
|
||||
cp app/dist/*win_arm64.zip artifacts/dbgate-windows-check-arm64.zip || true
|
||||
cp app/dist/*win_arm64.exe artifacts/dbgate-windows-check-arm64.exe || true
|
||||
cp app/dist/*-mac_universal.dmg artifacts/dbgate-check.dmg || true
|
||||
cp app/dist/*-mac_x64.dmg artifacts/dbgate-check-x64.dmg || true
|
||||
cp app/dist/*-mac_arm64.dmg artifacts/dbgate-check-arm64.dmg || true
|
||||
mv app/dist/*.snap artifacts/dbgate-check.snap || true
|
||||
|
||||
mv app/dist/*.exe artifacts/ || true
|
||||
mv app/dist/*.zip artifacts/ || true
|
||||
mv app/dist/*.tar.gz artifacts/ || true
|
||||
mv app/dist/*.AppImage artifacts/ || true
|
||||
mv app/dist/*.deb artifacts/ || true
|
||||
mv app/dist/*.snap artifacts/ || true
|
||||
mv app/dist/*.dmg artifacts/ || true
|
||||
mv app/dist/*.blockmap artifacts/ || true
|
||||
|
||||
mv app/dist/*.yml artifacts/ || true
|
||||
rm artifacts/builder-debug.yml
|
||||
- name: Print content of notarization-error.log
|
||||
if: failure() && matrix.os == 'macos-14'
|
||||
run: |
|
||||
|
||||
find . -type f -name "notarization-error.log" -exec echo "=== Start of {} ===" \; -exec cat {} \; -exec echo "=== End of {} ===" \;
|
||||
67
.github/workflows/build-app-pro-beta.yaml
vendored
67
.github/workflows/build-app-pro-beta.yaml
vendored
@@ -6,9 +6,13 @@ name: Electron app PREMIUM BETA
|
||||
push:
|
||||
tags:
|
||||
- v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: dbgate-app
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -17,6 +21,10 @@ jobs:
|
||||
- windows-2022
|
||||
- ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- run: python -m pip install --upgrade pip setuptools
|
||||
- name: Install python 3.11 (MacOS)
|
||||
if: matrix.os == 'macos-14'
|
||||
run: |
|
||||
@@ -39,7 +47,7 @@ jobs:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: 21048330597124a88fa1b8447e0bc18666eb69c5
|
||||
ref: 3ef5290af3820e8376e2304051b439611f789a07
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
@@ -81,37 +89,67 @@ jobs:
|
||||
cd dbgate-merged
|
||||
|
||||
yarn setCurrentVersion
|
||||
- name: printSecrets
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn printSecrets
|
||||
env:
|
||||
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
|
||||
- name: fillPackagedPlugins
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn fillPackagedPlugins
|
||||
- name: Publish
|
||||
- name: Publish Windows
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn run build:app
|
||||
- name: Publish MacOS
|
||||
if: matrix.os == 'macos-14'
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn run build:app
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
|
||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
|
||||
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
||||
- name: Publish Linux
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn run build:app
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||
- name: Azure login (OIDC)
|
||||
uses: azure/login@v2
|
||||
if: matrix.os == 'windows-2022'
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
|
||||
allow-no-subscriptions: true
|
||||
- name: Sign Windows artifacts with Azure Trusted Signing
|
||||
uses: azure/trusted-signing-action@v0
|
||||
if: matrix.os == 'windows-2022'
|
||||
with:
|
||||
endpoint: https://wus3.codesigning.azure.net/
|
||||
trusted-signing-account-name: DbGate
|
||||
certificate-profile-name: DbGate-Release
|
||||
files-folder: ../dbgate-merged/app/dist
|
||||
files-folder-filter: exe
|
||||
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||
timestamp-digest: SHA256
|
||||
- name: Fix YML hashes
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn run fixYmlHashes
|
||||
- name: Copy artifacts
|
||||
run: |
|
||||
mkdir artifacts
|
||||
@@ -123,6 +161,7 @@ jobs:
|
||||
cp ../dbgate-merged/app/dist/*win*.exe artifacts/dbgate-premium-beta.exe || true
|
||||
cp ../dbgate-merged/app/dist/*win_x64.zip artifacts/dbgate-windows-premium-beta.zip || true
|
||||
cp ../dbgate-merged/app/dist/*win_arm64.zip artifacts/dbgate-windows-premium-beta-arm64.zip || true
|
||||
cp ../dbgate-merged/app/dist/*win_arm64.exe artifacts/dbgate-windows-premium-beta-arm64.exe || true
|
||||
cp ../dbgate-merged/app/dist/*-mac_universal.dmg artifacts/dbgate-premium-beta.dmg || true
|
||||
cp ../dbgate-merged/app/dist/*-mac_x64.dmg artifacts/dbgate-premium-beta-x64.dmg || true
|
||||
cp ../dbgate-merged/app/dist/*-mac_arm64.dmg artifacts/dbgate-premium-beta-arm64.dmg || true
|
||||
|
||||
67
.github/workflows/build-app-pro.yaml
vendored
67
.github/workflows/build-app-pro.yaml
vendored
@@ -6,9 +6,13 @@ name: Electron app PREMIUM
|
||||
push:
|
||||
tags:
|
||||
- v[0-9]+.[0-9]+.[0-9]+
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: dbgate-app
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -17,6 +21,10 @@ jobs:
|
||||
- windows-2022
|
||||
- ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- run: python -m pip install --upgrade pip setuptools
|
||||
- name: Install python 3.11 (MacOS)
|
||||
if: matrix.os == 'macos-14'
|
||||
run: |
|
||||
@@ -39,7 +47,7 @@ jobs:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: 21048330597124a88fa1b8447e0bc18666eb69c5
|
||||
ref: 3ef5290af3820e8376e2304051b439611f789a07
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
@@ -81,37 +89,67 @@ jobs:
|
||||
cd dbgate-merged
|
||||
|
||||
yarn setCurrentVersion
|
||||
- name: printSecrets
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn printSecrets
|
||||
env:
|
||||
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
|
||||
- name: fillPackagedPlugins
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn fillPackagedPlugins
|
||||
- name: Publish
|
||||
- name: Publish Windows
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn run build:app
|
||||
- name: Publish MacOS
|
||||
if: matrix.os == 'macos-14'
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn run build:app
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
|
||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
|
||||
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
||||
- name: Publish Linux
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn run build:app
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||
- name: Azure login (OIDC)
|
||||
uses: azure/login@v2
|
||||
if: matrix.os == 'windows-2022'
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
|
||||
allow-no-subscriptions: true
|
||||
- name: Sign Windows artifacts with Azure Trusted Signing
|
||||
uses: azure/trusted-signing-action@v0
|
||||
if: matrix.os == 'windows-2022'
|
||||
with:
|
||||
endpoint: https://wus3.codesigning.azure.net/
|
||||
trusted-signing-account-name: DbGate
|
||||
certificate-profile-name: DbGate-Release
|
||||
files-folder: ../dbgate-merged/app/dist
|
||||
files-folder-filter: exe
|
||||
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||
timestamp-digest: SHA256
|
||||
- name: Fix YML hashes
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn run fixYmlHashes
|
||||
- name: Copy artifacts
|
||||
run: |
|
||||
mkdir artifacts
|
||||
@@ -123,6 +161,7 @@ jobs:
|
||||
cp ../dbgate-merged/app/dist/*win*.exe artifacts/dbgate-premium-latest.exe || true
|
||||
cp ../dbgate-merged/app/dist/*win_x64.zip artifacts/dbgate-windows-premium-latest.zip || true
|
||||
cp ../dbgate-merged/app/dist/*win_arm64.zip artifacts/dbgate-windows-premium-latest-arm64.zip || true
|
||||
cp ../dbgate-merged/app/dist/*win_arm64.exe artifacts/dbgate-windows-premium-latest-arm64.exe || true
|
||||
cp ../dbgate-merged/app/dist/*-mac_universal.dmg artifacts/dbgate-premium-latest.dmg || true
|
||||
cp ../dbgate-merged/app/dist/*-mac_x64.dmg artifacts/dbgate-premium-latest-x64.dmg || true
|
||||
cp ../dbgate-merged/app/dist/*-mac_arm64.dmg artifacts/dbgate-premium-latest-arm64.dmg || true
|
||||
|
||||
57
.github/workflows/build-app.yaml
vendored
57
.github/workflows/build-app.yaml
vendored
@@ -6,9 +6,13 @@ name: Electron app
|
||||
push:
|
||||
tags:
|
||||
- v[0-9]+.[0-9]+.[0-9]+
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
environment: dbgate-app
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -17,6 +21,10 @@ jobs:
|
||||
- windows-2022
|
||||
- ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- run: python -m pip install --upgrade pip setuptools
|
||||
- name: Install python 3.11 (MacOS)
|
||||
if: matrix.os == 'macos-14'
|
||||
run: |
|
||||
@@ -49,12 +57,6 @@ jobs:
|
||||
run: |
|
||||
|
||||
yarn setCurrentVersion
|
||||
- name: printSecrets
|
||||
run: |
|
||||
|
||||
yarn printSecrets
|
||||
env:
|
||||
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
|
||||
- name: fillPackagedPlugins
|
||||
run: |
|
||||
|
||||
@@ -62,24 +64,56 @@ jobs:
|
||||
- name: Install Snapcraft
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
uses: samuelmeuli/action-snapcraft@v1
|
||||
- name: Publish
|
||||
- name: Publish Windows
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: |
|
||||
|
||||
yarn run build:app
|
||||
- name: Publish MacOS
|
||||
if: matrix.os == 'macos-14'
|
||||
run: |
|
||||
|
||||
yarn run build:app
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
|
||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
|
||||
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
|
||||
- name: Publish Linux
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: |
|
||||
|
||||
yarn run build:app
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
|
||||
- name: generatePadFile
|
||||
run: |
|
||||
yarn generatePadFile
|
||||
- name: Azure login (OIDC)
|
||||
uses: azure/login@v2
|
||||
if: matrix.os == 'windows-2022'
|
||||
with:
|
||||
client-id: ${{ secrets.AZURE_TC_CLIENT_ID }}
|
||||
tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }}
|
||||
allow-no-subscriptions: true
|
||||
- name: Sign Windows artifacts with Azure Trusted Signing
|
||||
uses: azure/trusted-signing-action@v0
|
||||
if: matrix.os == 'windows-2022'
|
||||
with:
|
||||
endpoint: https://wus3.codesigning.azure.net/
|
||||
trusted-signing-account-name: DbGate
|
||||
certificate-profile-name: DbGate-Release
|
||||
files-folder: app/dist
|
||||
files-folder-filter: exe
|
||||
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||
timestamp-digest: SHA256
|
||||
- name: Fix YML hashes
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: |
|
||||
|
||||
yarn run fixYmlHashes
|
||||
- name: Copy artifacts
|
||||
run: |
|
||||
mkdir artifacts
|
||||
@@ -91,6 +125,7 @@ jobs:
|
||||
cp app/dist/*win*.exe artifacts/dbgate-latest.exe || true
|
||||
cp app/dist/*win_x64.zip artifacts/dbgate-windows-latest.zip || true
|
||||
cp app/dist/*win_arm64.zip artifacts/dbgate-windows-latest-arm64.zip || true
|
||||
cp app/dist/*win_arm64.exe artifacts/dbgate-windows-latest-arm64.exe || true
|
||||
cp app/dist/*-mac_universal.dmg artifacts/dbgate-latest.dmg || true
|
||||
cp app/dist/*-mac_x64.dmg artifacts/dbgate-latest-x64.dmg || true
|
||||
cp app/dist/*-mac_arm64.dmg artifacts/dbgate-latest-arm64.dmg || true
|
||||
|
||||
13
.github/workflows/build-cloud-pro.yaml
vendored
13
.github/workflows/build-cloud-pro.yaml
vendored
@@ -22,10 +22,10 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js 18.x
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 22.x
|
||||
- name: Install jq
|
||||
run: |
|
||||
sudo apt-get install jq -y
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: 21048330597124a88fa1b8447e0bc18666eb69c5
|
||||
ref: 3ef5290af3820e8376e2304051b439611f789a07
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
@@ -66,13 +66,6 @@ jobs:
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
yarn setCurrentVersion
|
||||
- name: printSecrets
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
yarn printSecrets
|
||||
env:
|
||||
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
|
||||
- name: Prepare packer build
|
||||
run: |
|
||||
cd ..
|
||||
|
||||
10
.github/workflows/build-docker-pro.yaml
vendored
10
.github/workflows/build-docker-pro.yaml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: 21048330597124a88fa1b8447e0bc18666eb69c5
|
||||
ref: 3ef5290af3820e8376e2304051b439611f789a07
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
@@ -76,14 +76,6 @@ jobs:
|
||||
cd dbgate-merged
|
||||
|
||||
yarn setCurrentVersion
|
||||
- name: printSecrets
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
|
||||
yarn printSecrets
|
||||
env:
|
||||
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
|
||||
- name: Prepare docker image
|
||||
run: |
|
||||
cd ..
|
||||
|
||||
6
.github/workflows/build-docker.yaml
vendored
6
.github/workflows/build-docker.yaml
vendored
@@ -65,12 +65,6 @@ jobs:
|
||||
run: |
|
||||
|
||||
yarn setCurrentVersion
|
||||
- name: printSecrets
|
||||
run: |
|
||||
|
||||
yarn printSecrets
|
||||
env:
|
||||
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
|
||||
- name: Prepare docker image
|
||||
run: |
|
||||
|
||||
|
||||
43
.github/workflows/build-npm-pro.yaml
vendored
43
.github/workflows/build-npm-pro.yaml
vendored
@@ -7,6 +7,9 @@ name: NPM packages PREMIUM
|
||||
tags:
|
||||
- v[0-9]+.[0-9]+.[0-9]+
|
||||
- v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -22,17 +25,17 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js 18.x
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 22.x
|
||||
- name: Checkout dbgate/dbgate-pro
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: 21048330597124a88fa1b8447e0bc18666eb69c5
|
||||
ref: 3ef5290af3820e8376e2304051b439611f789a07
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
@@ -49,13 +52,8 @@ jobs:
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
node adjustNpmPackageJsonPremium
|
||||
- name: Configure NPM token
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
|
||||
- name: Update npm
|
||||
run: npm install -g npm@latest
|
||||
- name: Remove dbmodel - should be not published
|
||||
run: |
|
||||
cd ..
|
||||
@@ -71,30 +69,35 @@ jobs:
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
yarn setCurrentVersion
|
||||
- name: printSecrets
|
||||
- name: Compute npm dist-tag
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged
|
||||
yarn printSecrets
|
||||
env:
|
||||
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
|
||||
if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then
|
||||
echo "NPM_TAG=alpha" >> $GITHUB_ENV
|
||||
else
|
||||
echo "NPM_TAG=latest" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Publish dbgate-api-premium
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged/packages/api
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-web-premium
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged/packages/web
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-serve-premium
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged/packages/serve
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-cosmosdb
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged/plugins/dbgate-plugin-cosmosdb
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-firestore
|
||||
run: |
|
||||
cd ..
|
||||
cd dbgate-merged/plugins/dbgate-plugin-firestore
|
||||
npm publish --tag "$NPM_TAG"
|
||||
|
||||
68
.github/workflows/build-npm.yaml
vendored
68
.github/workflows/build-npm.yaml
vendored
@@ -7,6 +7,9 @@ name: NPM packages
|
||||
tags:
|
||||
- v[0-9]+.[0-9]+.[0-9]+
|
||||
- v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -22,112 +25,111 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: Use Node.js 18.x
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
- name: Configure NPM token
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: |
|
||||
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
|
||||
node-version: 22.x
|
||||
- name: Update npm
|
||||
run: npm install -g npm@latest
|
||||
- name: yarn install
|
||||
run: |
|
||||
yarn install
|
||||
- name: setCurrentVersion
|
||||
run: |
|
||||
yarn setCurrentVersion
|
||||
- name: printSecrets
|
||||
- name: Compute npm dist-tag
|
||||
run: |
|
||||
yarn printSecrets
|
||||
env:
|
||||
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
|
||||
if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then
|
||||
echo "NPM_TAG=alpha" >> $GITHUB_ENV
|
||||
else
|
||||
echo "NPM_TAG=latest" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Publish types
|
||||
working-directory: packages/types
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish tools
|
||||
working-directory: packages/tools
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish sqltree
|
||||
working-directory: packages/sqltree
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
|
||||
- name: Publish api
|
||||
working-directory: packages/api
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish datalib
|
||||
working-directory: packages/datalib
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish filterparser
|
||||
working-directory: packages/filterparser
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish web
|
||||
working-directory: packages/web
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-serve
|
||||
working-directory: packages/serve
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbmodel
|
||||
working-directory: packages/dbmodel
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-csv
|
||||
working-directory: plugins/dbgate-plugin-csv
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-xml
|
||||
working-directory: plugins/dbgate-plugin-xml
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-excel
|
||||
working-directory: plugins/dbgate-plugin-excel
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-mssql
|
||||
working-directory: plugins/dbgate-plugin-mssql
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-mysql
|
||||
working-directory: plugins/dbgate-plugin-mysql
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-mongo
|
||||
working-directory: plugins/dbgate-plugin-mongo
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-postgres
|
||||
working-directory: plugins/dbgate-plugin-postgres
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-sqlite
|
||||
working-directory: plugins/dbgate-plugin-sqlite
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-redis
|
||||
working-directory: plugins/dbgate-plugin-redis
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-oracle
|
||||
working-directory: plugins/dbgate-plugin-oracle
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-clickhouse
|
||||
working-directory: plugins/dbgate-plugin-clickhouse
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-dbf
|
||||
working-directory: plugins/dbgate-plugin-dbf
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
- name: Publish dbgate-plugin-cassandra
|
||||
working-directory: plugins/dbgate-plugin-cassandra
|
||||
run: |
|
||||
npm publish
|
||||
npm publish --tag "$NPM_TAG"
|
||||
|
||||
34
.github/workflows/e2e-pro.yaml
vendored
34
.github/workflows/e2e-pro.yaml
vendored
@@ -5,18 +5,22 @@ name: Cypress tests with screenshots PREMIUM
|
||||
'on':
|
||||
push:
|
||||
branches:
|
||||
- stable
|
||||
- master
|
||||
- develop
|
||||
- feature/**
|
||||
- hotfix/**
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
e2e-tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Use Node.js 18.x
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 22.x
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
@@ -26,7 +30,7 @@ jobs:
|
||||
repository: dbgate/dbgate-pro
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
path: dbgate-pro
|
||||
ref: 21048330597124a88fa1b8447e0bc18666eb69c5
|
||||
ref: 3ef5290af3820e8376e2304051b439611f789a07
|
||||
- name: Merge dbgate/dbgate-pro
|
||||
run: |
|
||||
mkdir ../dbgate-pro
|
||||
@@ -69,6 +73,28 @@ jobs:
|
||||
with:
|
||||
name: screenshots
|
||||
path: screenshots
|
||||
- name: Push E2E screenshots - stable
|
||||
if: ${{ github.ref_name == 'stable' }}
|
||||
run: |
|
||||
git config --global user.email "info@dbgate.info"
|
||||
git config --global user.name "GitHub Actions"
|
||||
git clone https://${{ secrets.DIFLOW_GIT_SECRET }}@github.com/dbgate/dbgate-img.git
|
||||
cp ../dbgate-merged/e2e-tests/screenshots/*.png dbgate-img/static/img
|
||||
cd dbgate-img/static/img
|
||||
git add .
|
||||
git commit --amend --no-edit
|
||||
git push --force
|
||||
- name: Push E2E screenshots - master
|
||||
if: ${{ github.ref_name == 'master' }}
|
||||
run: |
|
||||
git config --global user.email "info@dbgate.info"
|
||||
git config --global user.name "GitHub Actions"
|
||||
git clone https://${{ secrets.DIFLOW_GIT_SECRET }}@github.com/dbgate/dbgate-img.git
|
||||
cp ../dbgate-merged/e2e-tests/screenshots/*.png dbgate-img/static/img-dev
|
||||
cd dbgate-img/static/img-dev
|
||||
git add .
|
||||
git commit --amend --no-edit
|
||||
git push --force
|
||||
services:
|
||||
postgres-cypress:
|
||||
image: postgres
|
||||
@@ -96,7 +122,7 @@ jobs:
|
||||
ports:
|
||||
- '16009:5556'
|
||||
mongo:
|
||||
image: mongo:4.0.12
|
||||
image: mongo:4.4.29
|
||||
env:
|
||||
MONGO_INITDB_ROOT_USERNAME: root
|
||||
MONGO_INITDB_ROOT_PASSWORD: Pwd2020Db
|
||||
|
||||
3
.github/workflows/process-templates.yaml
vendored
3
.github/workflows/process-templates.yaml
vendored
@@ -16,6 +16,9 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.WORKFLOW_CHANGE_ACCESS_TOKEN }}
|
||||
- name: git pull
|
||||
run: |
|
||||
git pull
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
|
||||
45
.github/workflows/run-tests.yaml
vendored
45
.github/workflows/run-tests.yaml
vendored
@@ -9,14 +9,17 @@ name: Integration and unit tests
|
||||
- develop
|
||||
- feature/**
|
||||
- hotfix/**
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
all-tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Use Node.js 18.x
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18.x
|
||||
node-version: 22.x
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 1
|
||||
@@ -37,24 +40,11 @@ jobs:
|
||||
run: |
|
||||
cd packages/datalib
|
||||
yarn test:ci
|
||||
- uses: tanmen/jest-reporter@v1
|
||||
- name: Tools tests
|
||||
if: always()
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
result-file: integration-tests/result.json
|
||||
action-name: Integration tests
|
||||
- uses: tanmen/jest-reporter@v1
|
||||
if: always()
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
result-file: packages/filterparser/result.json
|
||||
action-name: Filter parser test results
|
||||
- uses: tanmen/jest-reporter@v1
|
||||
if: always()
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
result-file: packages/datalib/result.json
|
||||
action-name: Datalib (perspectives) test results
|
||||
run: |
|
||||
cd packages/tools
|
||||
yarn test:ci
|
||||
services:
|
||||
postgres-integr:
|
||||
image: postgres
|
||||
@@ -78,7 +68,7 @@ jobs:
|
||||
ports:
|
||||
- '15002:1433'
|
||||
clickhouse-integr:
|
||||
image: bitnami/clickhouse:24.8.4
|
||||
image: bitnamilegacy/clickhouse:24.8.4
|
||||
env:
|
||||
CLICKHOUSE_ADMIN_PASSWORD: Pwd2020Db
|
||||
ports:
|
||||
@@ -93,3 +83,18 @@ jobs:
|
||||
image: cassandra:5.0.2
|
||||
ports:
|
||||
- '15942:9042'
|
||||
libsql:
|
||||
image: ghcr.io/tursodatabase/libsql-server:latest
|
||||
ports:
|
||||
- '8080:8080'
|
||||
firebird:
|
||||
image: firebirdsql/firebird:latest
|
||||
env:
|
||||
FIREBIRD_DATABASE: mydatabase.fdb
|
||||
FIREBIRD_USER: dbuser
|
||||
FIREBIRD_PASSWORD: dbpassword
|
||||
ISC_PASSWORD: masterkey
|
||||
FIREBIRD_TRACE: false
|
||||
FIREBIRD_USE_LEGACY_AUTH: true
|
||||
ports:
|
||||
- '3050:3050'
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -24,6 +24,7 @@ docker/plugins
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.translation
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
|
||||
59
.vscode/launch.json
vendored
59
.vscode/launch.json
vendored
@@ -1,20 +1,41 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch API",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "${workspaceFolder}/packages/api/src/index.js",
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/**/*.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debug App",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/packages/api/src/index.js",
|
||||
"envFile": "${workspaceFolder}/packages/api/.env",
|
||||
"args": ["--listen-api"],
|
||||
"console": "integratedTerminal",
|
||||
"restart": true,
|
||||
"runtimeExecutable": "node",
|
||||
"skipFiles": ["<node_internals>/**"]
|
||||
},
|
||||
{
|
||||
"name": "Debug App (Break on Start)",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/packages/api/src/index.js",
|
||||
"args": ["--listen-api"],
|
||||
"envFile": "${workspaceFolder}/.env",
|
||||
"console": "integratedTerminal",
|
||||
"restart": true,
|
||||
"runtimeExecutable": "node",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"stopOnEntry": true
|
||||
},
|
||||
{
|
||||
"name": "Attach to Process",
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"port": 9229,
|
||||
"restart": true,
|
||||
"localRoot": "${workspaceFolder}",
|
||||
"remoteRoot": "${workspaceFolder}",
|
||||
"skipFiles": ["<node_internals>/**"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
314
CHANGELOG.md
314
CHANGELOG.md
@@ -8,6 +8,318 @@ Builds:
|
||||
- linux - application for linux
|
||||
- win - application for Windows
|
||||
|
||||
## 7.0.6
|
||||
- ADDED: Reset password for Team Premium edition
|
||||
- ADDED: Encrypting passwords sent to frontend when using SHELL_CONNECTION=1 in Docker Community edition #1357
|
||||
|
||||
## 7.0.4
|
||||
- FIXED: MS SQL server export to CSV does not convert bit FALSE to 0 #1276
|
||||
- ADDED: MySQL FULLTEXT support #1305
|
||||
- FIXED: Error messages in Chinese will display garbled characters(MS SQL over ODBC) #1321
|
||||
- FIXED: Table's Show SQL fails to display precision and scale for NUMERIC/DECIMAL types in PostgreSQL #1325
|
||||
- FIXED: Export to Excel/CSV is broken for certain data types in v7.0.0 #1327
|
||||
- ADDED: Null value with keyboard shortcut in form view #1332
|
||||
- FIXED: Clicking into active form cell discards changes #1334
|
||||
- FIXED: Remember selection after filtering #1335
|
||||
- FIXED: Unable to use 'Group By' or one of the aggregate functions on tables containing text columns #1348
|
||||
- CHANGED: Improved custom connection color palette
|
||||
|
||||
## 7.0.3
|
||||
- FIXED: Optimalized loading MySQL primary keys #1261
|
||||
- FIXED: Test connection now works for MS Entra authentication #1315
|
||||
- FIXED: SQL Server - Unable to use 'Is Empty or Null' or 'Has Not Empty Value' filters on a field with data type TEXT #1338
|
||||
- FIXED: Play triangle too large for text-wrapped queries #1337
|
||||
- FIXED: Text wraps mid-word in form view, making it illegible #1333
|
||||
- FIXED: Cell View autodetects Form instead of Map for geometry/geography #1330
|
||||
- FIXED: Search for database in cloud connection #1329
|
||||
- ADDED: Toolstrip could be configured to the bottom of the tab #1326
|
||||
- CHANGED: Upgraded node for DbGate AWS distribution
|
||||
|
||||
## 7.0.1
|
||||
- FIXED: Foreign key actions not detected on PostgreSQL #1323
|
||||
- FIXED: Vulnerabilities in bundled dependencies: axios, cross-spawn, glob #1322
|
||||
- FIXED: The JsonB field in the cell data view always displays as null. #1320
|
||||
- ADDED: Possibility to skip computed coumn in SQL generator
|
||||
- ADDED: Improved team file editing, move between team folders
|
||||
- ADDED: Korean localization
|
||||
- FIXED: Added missing localization strings
|
||||
- ADDED: Default editor theme is part of application theme now
|
||||
|
||||
## 7.0.0
|
||||
- CHANGED: New design of application, new theme system
|
||||
- ADDED: Theme AI assistant - create custom themes using AI (Premium)
|
||||
- CHANGED: Themes are now defined in JSON files, custom themes could be shared via DbGate Cloud
|
||||
- REMOVED: Custom themes are no longer part of plugins
|
||||
- CHANGED: Huge improvements of Redis support
|
||||
- ADDED: Support for Redis JSON and Stream types
|
||||
- ADDED: Editing Redis values (Strings, Hashes, Lists, Sets, Sorted Sets, JSON, Streams)
|
||||
- ADDED: Support for Team Folders (Team Premium)
|
||||
- CHANGED: Upgraded Svelte to version 4
|
||||
- ADDED: Differentiate pinned database with same name #1306
|
||||
- ADDED: Database icons/logos for faster visual recognition #1222
|
||||
- CHANGED: Reorganized left sidebar widgets
|
||||
- ADDED: Widget for currently opened tabs
|
||||
|
||||
## 6.8.2
|
||||
- FIXED: Initialize storage database from envoronment variables failed with PostgreSQL
|
||||
|
||||
## 6.8.1
|
||||
- FIXED: Won't navigate to the relevant field on click of a field in columns #1303
|
||||
|
||||
## 6.8.0
|
||||
- ADDED: Form cell view for detailed data inspection and editing in data grids, with multi-row bulk editing support
|
||||
- CHANGED: Cell data sidebar moved to right side, now is part of data grid
|
||||
- FIXED: Improved widget resizing algorithm
|
||||
- FIXED: Word wrap feature in SQL editor
|
||||
- CHANGED: Data grid keyboard navigation improvements
|
||||
- CHANGED: Improved PostgreSQL decimal type support in data grid #1214
|
||||
- ADDED: Retrieve number of databases from Redis configuration #1278
|
||||
- ADDED: Run macro context menu (Premium)
|
||||
- ADDED: Support for skip update columns in replicator
|
||||
- FIXED: UTF-8 BOM handling in CSV input
|
||||
- CHANGED: Advanced export is now part of Community edition
|
||||
- FIXED: SQLite foreign key constraint types
|
||||
- FIXED: Double drop constraint issue
|
||||
- CHANGED: Improved map view lat/lon field autodetection
|
||||
- FIXED: Alter table operations and constraint sanitization
|
||||
- ADDED: Import connections from environment variables (Team Premium)
|
||||
|
||||
## 6.7.3
|
||||
- FIXED: Fixed problem in analyser core - in PostgreSQL, after dropping table, dropped table still appeared in structure
|
||||
- FIXED: PostgreSQL numeric columns do not align right #1254
|
||||
- ADDED: Custom thousands separator #1213
|
||||
|
||||
## 6.7.2
|
||||
- CHANGED: Settings modal redesign - now is settings opened in tab instead of modal, similarily as in VSCode
|
||||
- FIXED: Fixed search in table shortcuts #1273
|
||||
- CHANGED: Improved foreign key editor UX
|
||||
- FIXED: Fixed incremental DB structure refresh for PostgreSQL, optimalized slow loading primary keys in PostgreSQL
|
||||
- CHANGED: You could now choose, how to refresh structure, added ability to disconnect or reconnect
|
||||
- ADDED: Better processing of table backups, generate table restore script #1274
|
||||
- CHANGED: Improved storage of settings, especially for Team Premium edition
|
||||
|
||||
## 6.7.1
|
||||
- ADDED: LANGUAGE environment variable for the web version. #1266
|
||||
- ADDED: New localizations (Italian, Portugese (Brazil), Japanese)
|
||||
- ADDED: Option to detect language from browser settings in web version
|
||||
- FIXED: Check updates option no longer available in 6.7.0 #1263
|
||||
- FIXED: A MERGE statement must be terminated by a semi-colon (;), but dbgate stripped it. #1257
|
||||
- ADDED: Show table size #552
|
||||
- ADDED: Sort tables by size and by row count
|
||||
- ADDED: Connect to Legacy MongoDB (Premium) #540
|
||||
- FIXED: Fixed problems in saving team files in Team Premium edition
|
||||
- CHANGED: Files are by default saved to team folders in Team Premium edition
|
||||
- ADDED: Other files types supported in Team Premium edition (diagrams, query design, perspectives, import/export jobs, shell scripts, database compare jobs)
|
||||
|
||||
## 6.7.0
|
||||
- ADDED: Added localization support, now you can use DbGate in multiple languages (French, Spanish, German, Czech, Slovak, Simplified Chinese) #347 #705 #939 #1079
|
||||
- CHANGED: Solved many issues with binary fields, huge performance improvements in binary fields processing
|
||||
- FIXED: Export to CSV produces empty file #1247
|
||||
- CHANGED: Upgraded electron to version 38 #1243
|
||||
- FIXED: PostgreSQL export to SQL and XML doesn't include bytea field contents #1228
|
||||
- FIXED: Export CSV broken #1080
|
||||
- FIXED: Inconsistent handling of hex-like strings #680
|
||||
- FIXED: Export mongodb binary cell as binary file #292
|
||||
- CHANGED: SSL is used automatically for connections to Azure databases
|
||||
- ADDED: New export formats CSV for Excel, TSV
|
||||
- FIXED: Horizontal scrolling on macOS trackpad/Magic Mouse #1250
|
||||
|
||||
## 6.6.12
|
||||
- FIXED: Cannot paste license key on Mac (special commands like copy/paste were disabled on license screen)
|
||||
|
||||
## 6.6.11
|
||||
- FIXED: Fixed theming on application startup
|
||||
- CHANGED: Improved licensing page
|
||||
|
||||
## 6.6.10
|
||||
- FIXED: License from environment variable is not refreshed #1245
|
||||
- FIXED: connection closing / reconnecting #1237
|
||||
- ADDED: retain history across multiple queries #1236
|
||||
- ADDED: load CSVs to temp tables #1235
|
||||
- FIXED: Not possible to scroll the data view horizontally by pressing shift and scroll mouse middle button on Mac #453
|
||||
- FIXED: Expired trial workflow (Premium)
|
||||
- ADDED: Column name collision resolving #1234 (MySQL)
|
||||
|
||||
## 6.6.8
|
||||
- CHANGED: Windows executable now uses Azure trusted signing certificate
|
||||
- CHANGED: NPM packages now use GitHub OIDC provenance signing for better security
|
||||
- CHANGED: Some features moved to Premium edition (master/detail views, FK lookups, column expansion, split view, advanced export/import, data archives, grouping, macros)
|
||||
|
||||
## 6.6.6
|
||||
- ADDED: Allow disable/re-enable filter #1174
|
||||
- ADDED: Close right side tabs #1219
|
||||
- ADDED: Ability disable execute current line in query editor #1209
|
||||
- ADDED: Support for Redis Cluster #1204 (Premium)
|
||||
|
||||
## 6.6.5
|
||||
- ADDED: SQL AI assistant - powered by database chat, could help you to write SQL queries (Premium)
|
||||
- ADDED: Explain SQL error (powered by AI) (Premium)
|
||||
- ADDED: Database chat (and SQL AI Assistant) now supports showing charts (Premium)
|
||||
- FIXED: Fixed editing new files and roles (Team Premium)
|
||||
- FIXED: Connection to standalone database could be now pinned
|
||||
- FIXED: Cannot open up large JSON file #1215
|
||||
|
||||
## 6.6.4
|
||||
- ADDED: AI Database chat now supports much more LLM models. (Premium)
|
||||
- ADDED: Possibility to use your own API key with OPENAI-compatible providers (OpenRouter, Antropic...)
|
||||
- ADDED: Possibility to use self-hosted own LLM (eg. Llama)
|
||||
- ADDED: Team files - save SQL files and define shared charts, assign roles and users to these objects (Team Premium)
|
||||
- FIXED: BUG: does no longer work with Cockroach DB #1202
|
||||
- FIXED: DbGate Web UI Connections do not display 'Databases' #1199
|
||||
- CHANGED: Redesign fof applications. Applications are now storted in single JSON file
|
||||
- ADDED: Application editor (Premium)
|
||||
- ADDED: Posibility to filter only tables with rows
|
||||
- FIXED: Fixed several issues with large Firebird databases
|
||||
- CHANGED: Community edition now supports shared folders in read-only mode
|
||||
|
||||
## 6.6.3
|
||||
- FIXED: Error “db.getCollection(…).renameCollection is not a function” when renaming collection in dbGate #1198
|
||||
- FIXED: Can't list databases from Azure SQL SERVER #1197
|
||||
- ADDED: Save zoom level in electron apps
|
||||
|
||||
## 6.6.2
|
||||
- ADDED: List of processes, ability to kill process (Server summary) #1178
|
||||
- ADDED: Database and table permissions (Team Premium edition)
|
||||
- ADDED: Redis search box - Scan all #1191
|
||||
- FIXED: Optimalized loading SQL server with descriptions #1187
|
||||
- CHANGED: Allow a much greater page size #1185
|
||||
- FIXED: Optimalized loading SQL server with descriptions #1187
|
||||
- FIXED: Executing queries for SQLite crash #1195
|
||||
|
||||
## 6.6.1
|
||||
- ADDED: Support for Mongo shell (Premium) - #1114
|
||||
- FIXED: Support for BLOB in Oracle #1181
|
||||
- ADDED: Connect to named SQL Server instance #340
|
||||
- ADDED: Support for SQL Server descriptions #1137
|
||||
- ADDED: Application log viewer
|
||||
- FIXED: Selecting default database in connection dialog
|
||||
- CHANGED: Improved logging system, added related database and connection to logs metadata
|
||||
|
||||
## 6.6.0
|
||||
- ADDED: Database chat - AI powered chatbot, which knows your database (Premium)
|
||||
- ADDED: Firestore support (Premium)
|
||||
- REMOVED: Query AI assistant (replaced by Database Chat) (Premium)
|
||||
- FIXED: Chart permissions were ignored (Premium)
|
||||
|
||||
## 6.5.6
|
||||
- ADDED: New object window - quick access to most common functions
|
||||
- ADDED: Possibility to disable split query by empty line #1162
|
||||
- ADDED: Possibility to opt out authentication #1152
|
||||
- FIXED: Separate schema mode now works in Team Premium edition
|
||||
- FIXED: Handled situation, when user enters expired license, which is already prolonged
|
||||
- FIXED: Fixed some minor problems of charts
|
||||
|
||||
## 6.5.5
|
||||
- ADDED: Administer cloud folder window
|
||||
- CHANGED: Cloud menu redesign
|
||||
- ADDED: Audit log (for Team Premium edition)
|
||||
- ADDED: Added new timeline chart type (line chart with time axis)
|
||||
- ADDED: Chart grouping (more measure determined from data)
|
||||
- CHANGED: Improved chart autodetection - string X axis (with bar type), COUNT as measure, split different measures
|
||||
- ADDED: Added chart data type detection
|
||||
- FIXED: Fixed chart displaying problems
|
||||
- FIXED: Fixed exporting chart to HTML
|
||||
- CHANGED: Choose COUNT measure without selecting underlying ID field (use virtual __count)
|
||||
- FIXED: Problems with authentification administration, especially for Postgres storage
|
||||
- CHANGED: Anonymous autentification (in Team Premium) is now by default disabled
|
||||
|
||||
## 6.5.3
|
||||
- CHANGED: Improved DbGate Cloud sign-in workflow
|
||||
- FIXED: Some fixes and error handling in new charts engine
|
||||
- ADDED: Charts - ability to choose aggregate function
|
||||
- CHANGED: Improved About window
|
||||
|
||||
## 6.5.2
|
||||
- CHANGED: Autodetecting charts is disabled by default #1145
|
||||
- CHANGED: Improved chart displaying workflow
|
||||
- ADDED: Ability to close chart
|
||||
|
||||
## 6.5.1
|
||||
- FIXED: DbGate Cloud e-mail sign-in method for desktop clients
|
||||
|
||||
## 6.5.0
|
||||
- ADDED: DbGate cloud - online storage for connections, SQL scripts and other objects
|
||||
- ADDED: Public knowledge base - common SQL scripts for specific DB engines (table sizes, index stats etc.)
|
||||
- ADDED: Query results could be visualised in charts (Premium)
|
||||
- REMOVED: Chart from selection, active charts - replaced by query result charts
|
||||
- ADDED: FirebirdSQL support
|
||||
- ADDED: SQL front matter - properties of SQL script
|
||||
- ADDED: Auto-execute SQL script on open (saved in SQL front matter)
|
||||
- CHANGED: Smaller widget icon panel
|
||||
- CHANGED: Applications and Single-connection mode removed from widget icon panel
|
||||
- CHANGED: Temporarily disabled MongoDB profiler support
|
||||
- FIXED: Pie chart distorted if settings change #838
|
||||
- FIXED: SQL server generated insert statement should exclude computed and timestamp columns #1111
|
||||
- ADDED: Added option "Show all columns when searching" #1118
|
||||
- ADDED: Copy cells/rows (e.g. column names) from Structure view #1119
|
||||
- ADDED: Setting "Show table aliases in code completion" #1122
|
||||
- FIXED: Vulnerability - check file paths in web version
|
||||
- FIXED: Very slow render of tables with very log cells
|
||||
|
||||
## 6.4.2
|
||||
|
||||
- ADDED: Source label to docker container #1105
|
||||
- FIXED: DbGate restart needed to take effect after trigger is created/deleted on mariadb #1112
|
||||
- ADDED: View PostgreSQL query console output #1108
|
||||
- FIXED: Single quote generete MySql error #1107
|
||||
- ADDED: Ability to limit query result count #1098
|
||||
- CHANGED: Correct processing of bigint columns #1087 #1055 #583
|
||||
- CHANGED: Improved and optimalized algorithm of loading redis keys #1062, #1034
|
||||
- FIXED: Fixed loading Redis keys with :: in key name
|
||||
|
||||
## 6.4.0
|
||||
- ADDED: DuckDB support
|
||||
- ADDED: Data deployer (Premium)
|
||||
- ADDED: Compare data between JSON lines file in archive and database table
|
||||
- CHANGED: Data Duplicator => Data Replicator (suitable for update, create and delete data, much more customizable)
|
||||
- REMOVED: Data duplicator GUI (replaced with Data Deployer)
|
||||
- ADDED: Exporting to ZIP file
|
||||
- ADDED: Download SQL and SQLite files
|
||||
- ADDED: Upload SQLite files
|
||||
- ADDED: Upload archive as ZIP folder (Premium)
|
||||
- ADDED: Compress, uncompress archive folder (Premium)
|
||||
- ADDED: Export connections and settings #357
|
||||
- ADDED: Filtering by MongoDB ObjectId works now also without ObjectId(...) wrapper
|
||||
- ADDED: Split queries using blank lines #1089
|
||||
- FIXED: JSON-to-Grid only works if there is no newline #1085
|
||||
- CHANGED: When running multiple commands in script, stop execution after first error #1070
|
||||
- FIXED: Selection rectangle remains visible after closing JSONB edit cell value form #1031
|
||||
- FIXED: Diplaying numeric FK column with right alignement #1021
|
||||
- ADDED: Additional arguments for MySQL and PostgreSQL backup #1092
|
||||
- CHANGED: Amazon and Azure instalations are not auto-upgraded by default
|
||||
|
||||
## 6.3.3
|
||||
- CHANGED: New administration UI, redesigned administration of users, connections and roles
|
||||
- ADDED: Encrypting passwords in team-premium edition
|
||||
- ADDED: Show scale bar on map #1090
|
||||
- FIXED: Fixed native backup/restore for MySQL+PostgreSQL over SSH tunnel #1092
|
||||
- CHANGED: Column mapping dialog - fixes and improvements for copying from one existing table into another
|
||||
- ADDED: Search in columns in table editor
|
||||
- ADDED: Line Wrap for JSON viewer #768
|
||||
|
||||
### 6.3.2
|
||||
- ADDED: "Use system theme" switch, use changed system theme without restart #1084
|
||||
- ADDED: "Skip SETNAME instruction" option for Redis #1077
|
||||
- FIXED: Clickhouse views are now available even for user with limited permissions #1076
|
||||
- ADDED: Multiple-token search delimited with comma (=OR) in structure search boxes
|
||||
- CHANGED: When filtering columns in data browser, data view shows only filtered columns
|
||||
- ADDED: Advanced settings for diagrams (Premium)
|
||||
- ADDED: Diagrams - zoom with Ctrl+mouse wheel
|
||||
- FIXED: Scrollable diagram exports + scroll by mouse drag
|
||||
- FIXED: Fixed many problems in diagrams when zoom is applied
|
||||
- FIXED: Correctly end connection process after succesful/unsuccesful connect
|
||||
|
||||
### 6.3.0
|
||||
- ADDED: Support for libSQL and Turso (Premium)
|
||||
- ADDED: Native backup and restore database for MySQL and PostgreSQL (Premium)
|
||||
- REMOVED: DbGate internal dump export for MySQL (replaced with call of mysqldump)
|
||||
- REMOVED: Import SQL dump with internal DbGate capabilities (replaced by calling of mysql and psql utilities)
|
||||
- FIXED: Many fixes in stream processing (imoprt/export), especialy for MongoDB
|
||||
- ADDED: Indicating progress of import/export tasks, better error reporting
|
||||
- CHANGED: #1060 - Changed shortcut for AI assistant
|
||||
- ADDED: /health endpoint with diagnostic info
|
||||
- FIXED: Linux Appimage crash => A JavaScript error occurred in the main process #1065 , #1067
|
||||
|
||||
### 6.2.1
|
||||
- ADDED: Commit/rollback and autocommit in scripts #1039
|
||||
- FIXED: Doesn't import all the records from MongoDB #1044
|
||||
@@ -18,7 +330,7 @@ Builds:
|
||||
- FIXED: Scroll in XML cell view, XML view respect themes
|
||||
- REMOVED: armv7l build for Linux (because of problems with glibc compatibility)
|
||||
- CHANGED: Upgraded to node:22 for docker builds
|
||||
- CHANGED: Upgraded SQLite engine version (better-sqlite3@11.8.1)
|
||||
- CHANGED: Upgraded SQLite engine version
|
||||
|
||||
### 6.2.0
|
||||
- ADDED: Query AI Assistant (Premium)
|
||||
|
||||
23
README.md
23
README.md
@@ -15,10 +15,10 @@ But there are also many advanced features like schema compare, visual query desi
|
||||
DbGate is licensed under GPL-3.0 license and is free to use for any purpose.
|
||||
|
||||
* Try it online - [demo.dbgate.org](https://demo.dbgate.org) - online demo application
|
||||
* **Download** application for Windows, Linux or Mac from [dbgate.org](https://dbgate.org/download/)
|
||||
* **Download** application for Windows, Linux or Mac from [dbgate.io](https://www.dbgate.io/download/)
|
||||
* Looking for DbGate Community? **Download** from [dbgate.io](https://www.dbgate.io/download-community/)
|
||||
* Run web version as [NPM package](https://www.npmjs.com/package/dbgate-serve) or as [docker image](https://hub.docker.com/r/dbgate/dbgate)
|
||||
* Use nodeJs [scripting interface](https://dbgate.org/docs/scripting) ([API documentation](https://dbgate.org/docs/apidoc))
|
||||
* [Recommend DbGate](https://testimonial.to/dbgate) | [Rate on G2](https://www.g2.com/products/dbgate/reviews)
|
||||
* Use nodeJs [scripting interface](https://docs.dbgate.io/scripting) ([API documentation](https://docs.dbgate.io/apidoc))
|
||||
|
||||
## Supported databases
|
||||
* MySQL
|
||||
@@ -34,8 +34,10 @@ DbGate is licensed under GPL-3.0 license and is free to use for any purpose.
|
||||
* CosmosDB (Premium)
|
||||
* ClickHouse
|
||||
* Apache Cassandra
|
||||
|
||||
<!-- Learn more about DbGate features at the [DbGate website](https://dbgate.org/), or try our online [demo application](https://demo.dbgate.org) -->
|
||||
* libSQL/Turso (Premium)
|
||||
* DuckDB
|
||||
* Firebird
|
||||
* Firestore (Premium)
|
||||
|
||||
|
||||
<a href="https://raw.githubusercontent.com/dbgate/dbgate/master/img/screenshot1.png">
|
||||
@@ -59,7 +61,7 @@ DbGate is licensed under GPL-3.0 license and is free to use for any purpose.
|
||||
* Edit table schema, indexes, primary and foreign keys
|
||||
* Compare and synchronize database structure
|
||||
* ER diagram
|
||||
* Light and dark theme, next themes available as plugins from github community
|
||||
* Light and dark theme, next themes available from DbGate Cloud
|
||||
* Huge support for work with related data - master/detail views, foreign key lookups, expanding columns from related tables in flat data view
|
||||
* Query designer - visual SQL query builder without writing SQL code. Complex conditions like WHERE NOT EXISTS.
|
||||
* Query perspectives – innovative nested table view over complex relational data, something like query designer on MongoDB databases
|
||||
@@ -78,6 +80,7 @@ DbGate is licensed under GPL-3.0 license and is free to use for any purpose.
|
||||
* Archives - backup your data in NDJSON files on local filesystem (or on DbGate server, when using web application)
|
||||
* NDJSON data viewer and editor - browse NDJSON data, edit data and structure directly on NDJSON files. Works also for big NDSON files
|
||||
* Charts, export chart to HTML page
|
||||
* AI powered database chat
|
||||
* Show GEO data on map, export map to HTML page
|
||||
* For detailed info, how to run DbGate in docker container, visit [docker hub](https://hub.docker.com/r/dbgate/dbgate)
|
||||
* Extensible plugin architecture
|
||||
@@ -86,11 +89,13 @@ DbGate is licensed under GPL-3.0 license and is free to use for any purpose.
|
||||
Any contributions are welcome. If you want to contribute without coding, consider following:
|
||||
|
||||
* Tell your friends about DbGate or share on social networks - when more people will use DbGate, it will grow to be better
|
||||
* Write review on [Slant.co](https://www.slant.co/improve/options/41086/~dbgate-review) or [G2](https://www.g2.com/products/dbgate/reviews)
|
||||
* Purchase a [DbGate Premium](https://www.dbgate.io/purchase/premium/) license
|
||||
* Create issue, if you find problem in app, or you have idea to new feature. If issue already exists, you could leave comment on it, to prioritise most wanted issues
|
||||
* Create some tutorial video on [youtube](https://www.youtube.com/playlist?list=PLCo7KjCVXhr0RfUSjM9wJMsp_ShL1q61A)
|
||||
* Become a backer on [GitHub sponsors](https://github.com/sponsors/dbgate) or [Open collective](https://opencollective.com/dbgate)
|
||||
* Where a small coding is acceptable for you, you could [create plugin](https://dbgate.org/docs/plugin-development). Plugins for new themes can be created actually without JS coding
|
||||
* Add a SQL script to [Public Knowledge Base](https://github.com/dbgate/dbgate-knowledge-base)
|
||||
* Where a small coding is acceptable for you, you could [create plugin](https://docs.dbgate.io/plugin-development)
|
||||
* Create a new custom theme and share it on [DbGate Cloud](https://github.com/dbgate/dbgate-knowledge-base/tree/master/folder-Themes)
|
||||
|
||||
Thank you!
|
||||
|
||||
@@ -185,4 +190,4 @@ yarn plugin # this compiles plugin and copies it into existing DbGate installati
|
||||
After restarting DbGate, you could use your new plugin from DbGate.
|
||||
|
||||
## Logging
|
||||
DbGate uses [pinomin logger](https://github.com/dbgate/pinomin). So by default, it produces JSON log messages into console and log files. If you want to see formatted logs, please use [pino-pretty](https://github.com/pinojs/pino-pretty) log formatter.
|
||||
DbGate uses [pinomin logger](https://github.com/dbgate/pinomin). So by default, it produces JSON log messages into console and log files. If you want to see formatted logs, please use [pino-pretty](https://github.com/pinojs/pino-pretty) log formatter.
|
||||
|
||||
@@ -43,6 +43,8 @@ function adjustFile(file, isApp = false) {
|
||||
|
||||
if (process.argv.includes('--community')) {
|
||||
delete json.optionalDependencies['mongodb-client-encryption'];
|
||||
delete json.dependencies['@mongosh/service-provider-node-driver'];
|
||||
delete json.dependencies['@mongosh/browser-runtime-electron'];
|
||||
}
|
||||
|
||||
if (isApp && process.argv.includes('--premium')) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dbgate",
|
||||
"version": "6.0.0-alpha.1",
|
||||
"version": "7.0.0-alpha.1",
|
||||
"private": true,
|
||||
"author": "Jan Prochazka <jenasoft.database@gmail.com>",
|
||||
"description": "Opensource database administration tool",
|
||||
@@ -117,7 +117,7 @@
|
||||
"scripts": {
|
||||
"start": "cross-env ELECTRON_START_URL=http://localhost:5001 DEVMODE=1 electron .",
|
||||
"start:local": "cross-env electron .",
|
||||
"dist": "electron-builder",
|
||||
"dist": "electron-builder --publish never",
|
||||
"build": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn dist",
|
||||
"build:local": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn predist",
|
||||
"postinstall": "yarn rebuild && patch-package",
|
||||
@@ -128,7 +128,7 @@
|
||||
"devDependencies": {
|
||||
"copyfiles": "^2.2.0",
|
||||
"cross-env": "^6.0.3",
|
||||
"electron": "30.0.2",
|
||||
"electron": "38.6.0",
|
||||
"electron-builder": "25.1.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,16 @@ let mainModule;
|
||||
let appUpdateStatus = '';
|
||||
let settingsJson = {};
|
||||
|
||||
function getTranslated(key) {
|
||||
if (typeof key === 'string' && global.TRANSLATION_DATA?.[key]) {
|
||||
return global.TRANSLATION_DATA?.[key];
|
||||
}
|
||||
if (typeof key?._transKey === 'string') {
|
||||
return global.TRANSLATION_DATA?.[key._transKey] ?? key._transOptions?.defaultMessage;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
process.on('uncaughtException', function (error) {
|
||||
console.error('uncaughtException', error);
|
||||
});
|
||||
@@ -63,6 +73,7 @@ try {
|
||||
let mainWindow;
|
||||
let mainMenu;
|
||||
let runCommandOnLoad = null;
|
||||
let mainWindowMenuSet = false;
|
||||
|
||||
log.transports.file.level = 'debug';
|
||||
autoUpdater.logger = log;
|
||||
@@ -85,17 +96,22 @@ function formatKeyText(keyText) {
|
||||
return keyText.replace('CtrlOrCommand+', 'Ctrl+');
|
||||
}
|
||||
|
||||
function commandItem(item) {
|
||||
function commandItem(item, disableAll = false) {
|
||||
const id = item.command;
|
||||
const command = commands[id];
|
||||
if (item.skipInApp) {
|
||||
return { skip: true };
|
||||
}
|
||||
if (!command) {
|
||||
return { skip: true };
|
||||
}
|
||||
return {
|
||||
id,
|
||||
label: command ? command.menuName || command.toolbarName || command.name : id,
|
||||
label: command
|
||||
? getTranslated(command.menuName) || getTranslated(command.toolbarName) || getTranslated(command.name)
|
||||
: id,
|
||||
accelerator: formatKeyText(command ? command.keyText : undefined),
|
||||
enabled: command ? command.enabled : false,
|
||||
enabled: command ? command.enabled && (!disableAll || command.systemCommand) : false,
|
||||
click() {
|
||||
if (mainWindow) {
|
||||
mainWindow.webContents.send('run-command', id);
|
||||
@@ -107,14 +123,14 @@ function commandItem(item) {
|
||||
};
|
||||
}
|
||||
|
||||
function buildMenu() {
|
||||
function buildMenu(disableAll = false) {
|
||||
let template = _cloneDeepWith(mainMenuDefinition({ editMenu: true, isMac: isMac() }), item => {
|
||||
if (item.divider) {
|
||||
return { type: 'separator' };
|
||||
}
|
||||
|
||||
if (item.command) {
|
||||
return commandItem(item);
|
||||
return commandItem(item, disableAll);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -129,7 +145,7 @@ function buildMenu() {
|
||||
{
|
||||
label: 'DbGate',
|
||||
submenu: [
|
||||
commandItem({ command: 'about.show' }),
|
||||
commandItem({ command: 'about.show' }, disableAll),
|
||||
{ role: 'services' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideOthers' },
|
||||
@@ -145,22 +161,28 @@ function buildMenu() {
|
||||
}
|
||||
|
||||
ipcMain.on('update-commands', async (event, arg) => {
|
||||
commands = JSON.parse(arg);
|
||||
const parsed = JSON.parse(arg);
|
||||
commands = parsed.commands;
|
||||
const isModalOpened = parsed.isModalOpened;
|
||||
const dbgatePage = parsed.dbgatePage;
|
||||
for (const key of Object.keys(commands)) {
|
||||
const menu = mainMenu.getMenuItemById(key);
|
||||
if (!menu) continue;
|
||||
const command = commands[key];
|
||||
|
||||
// rebuild menu
|
||||
if (menu.label != command.text || menu.accelerator != command.keyText) {
|
||||
mainMenu = buildMenu();
|
||||
if (global.TRANSLATION_DATA && (menu.label != command.text || menu.accelerator != command.keyText)) {
|
||||
mainMenu = buildMenu(isModalOpened || !!dbgatePage);
|
||||
|
||||
Menu.setApplicationMenu(mainMenu);
|
||||
// mainWindow.setMenu(mainMenu);
|
||||
if (!mainWindowMenuSet) {
|
||||
mainWindow.setMenu(mainMenu);
|
||||
mainWindowMenuSet = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
menu.enabled = command.enabled;
|
||||
menu.enabled = command.enabled && !isModalOpened && !dbgatePage;
|
||||
}
|
||||
});
|
||||
ipcMain.on('quit-app', async (event, arg) => {
|
||||
@@ -212,6 +234,10 @@ ipcMain.on('app-started', async (event, arg) => {
|
||||
autoUpdater.checkForUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
if (initialConfig['winZoomLevel'] != null) {
|
||||
mainWindow.webContents.zoomLevel = initialConfig['winZoomLevel'];
|
||||
}
|
||||
});
|
||||
ipcMain.on('window-action', async (event, arg) => {
|
||||
if (!mainWindow) {
|
||||
@@ -299,6 +325,12 @@ ipcMain.on('check-for-updates', async (event, url) => {
|
||||
autoUpdater.autoDownload = false;
|
||||
autoUpdater.checkForUpdates();
|
||||
});
|
||||
ipcMain.on('translation-data', async (event, arg) => {
|
||||
global.TRANSLATION_DATA = JSON.parse(arg);
|
||||
mainMenu = buildMenu();
|
||||
Menu.setApplicationMenu(mainMenu);
|
||||
mainWindow.setMenu(mainMenu);
|
||||
});
|
||||
|
||||
function fillMissingSettings(value) {
|
||||
const res = {
|
||||
@@ -357,6 +389,7 @@ function createWindow() {
|
||||
title: isProApp() ? 'DbGate Premium' : 'DbGate',
|
||||
frame: useNativeMenu,
|
||||
titleBarStyle: useNativeMenu ? undefined : 'hidden',
|
||||
backgroundColor: electron.nativeTheme.shouldUseDarkColors ? '#111111' : undefined,
|
||||
...bounds,
|
||||
icon: os.platform() == 'win32' ? 'icon.ico' : path.resolve(__dirname, '../icon.png'),
|
||||
partition: isProApp() ? 'persist:dbgate-premium' : 'persist:dbgate',
|
||||
@@ -374,8 +407,8 @@ function createWindow() {
|
||||
mainWindow.setFullScreen(true);
|
||||
}
|
||||
|
||||
mainMenu = buildMenu();
|
||||
mainWindow.setMenu(mainMenu);
|
||||
// mainMenu = buildMenu();
|
||||
// mainWindow.setMenu(mainMenu);
|
||||
|
||||
function loadMainWindow() {
|
||||
const startUrl =
|
||||
@@ -393,6 +426,7 @@ function createWindow() {
|
||||
JSON.stringify({
|
||||
winBounds: mainWindow.getBounds(),
|
||||
winIsMaximized: mainWindow.isMaximized(),
|
||||
winZoomLevel: mainWindow.webContents.zoomLevel,
|
||||
}),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
module.exports = ({ editMenu, isMac }) => [
|
||||
function _t(key, { defaultMessage, currentTranslations } = {}) {
|
||||
return (currentTranslations || global.TRANSLATION_DATA)?.[key] || defaultMessage;
|
||||
}
|
||||
|
||||
module.exports = ({ editMenu, isMac }, currentTranslations = null) => [
|
||||
{
|
||||
label: 'File',
|
||||
label: _t('menu.file', { defaultMessage: 'File', currentTranslations }),
|
||||
submenu: [
|
||||
{ command: 'new.connection', hideDisabled: true },
|
||||
{ command: 'new.sqliteDatabase', hideDisabled: true },
|
||||
{ command: 'new.duckdbDatabase', hideDisabled: true },
|
||||
{ divider: true },
|
||||
{ command: 'new.query', hideDisabled: true },
|
||||
{ command: 'new.queryDesign', hideDisabled: true },
|
||||
{ command: 'new.diagram', hideDisabled: true },
|
||||
{ command: 'new.perspective', hideDisabled: true },
|
||||
{ command: 'new.application', hideDisabled: true },
|
||||
{ command: 'new.shell', hideDisabled: true },
|
||||
{ command: 'new.jsonl', hideDisabled: true },
|
||||
{ command: 'new.modelTransform', hideDisabled: true },
|
||||
@@ -26,7 +32,7 @@ module.exports = ({ editMenu, isMac }) => [
|
||||
},
|
||||
editMenu
|
||||
? {
|
||||
label: 'Edit',
|
||||
label: _t('menu.edit', { defaultMessage: 'Edit', currentTranslations }),
|
||||
submenu: [
|
||||
{ command: 'edit.undo' },
|
||||
{ command: 'edit.redo' },
|
||||
@@ -51,7 +57,7 @@ module.exports = ({ editMenu, isMac }) => [
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
label: 'View',
|
||||
label: _t('menu.view', { defaultMessage: 'View', currentTranslations }),
|
||||
submenu: [
|
||||
{ command: 'app.reload', hideDisabled: true },
|
||||
{ command: 'app.toggleDevTools', hideDisabled: true },
|
||||
@@ -70,10 +76,12 @@ module.exports = ({ editMenu, isMac }) => [
|
||||
{ command: 'app.zoomIn', hideDisabled: true },
|
||||
{ command: 'app.zoomOut', hideDisabled: true },
|
||||
{ command: 'app.zoomReset', hideDisabled: true },
|
||||
{ divider: true },
|
||||
{ command: 'app.showLogs', hideDisabled: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Tools',
|
||||
label: _t('menu.tools', { defaultMessage: 'Tools', currentTranslations }),
|
||||
submenu: [
|
||||
{ command: 'database.search', hideDisabled: true },
|
||||
{ command: 'commandPalette.show', hideDisabled: true },
|
||||
@@ -85,8 +93,12 @@ module.exports = ({ editMenu, isMac }) => [
|
||||
{ divider: true },
|
||||
{ command: 'folder.showLogs', hideDisabled: true },
|
||||
{ command: 'folder.showData', hideDisabled: true },
|
||||
{ command: 'new.gist', hideDisabled: true },
|
||||
{ command: 'app.resetSettings', hideDisabled: true },
|
||||
{ divider: true },
|
||||
{ command: 'app.exportConnections', hideDisabled: true },
|
||||
{ command: 'app.importConnections', hideDisabled: true },
|
||||
{ divider: true },
|
||||
{ command: 'app.managePlugins', hideDisabled: true },
|
||||
],
|
||||
},
|
||||
...(isMac
|
||||
@@ -98,18 +110,19 @@ module.exports = ({ editMenu, isMac }) => [
|
||||
]
|
||||
: []),
|
||||
{
|
||||
label: 'Help',
|
||||
label: _t('menu.help', { defaultMessage: 'Help', currentTranslations }),
|
||||
submenu: [
|
||||
{ command: 'app.openDocs', hideDisabled: true },
|
||||
{ command: 'app.openWeb', hideDisabled: true },
|
||||
{ command: 'app.openIssue', hideDisabled: true },
|
||||
{ command: 'app.openSponsoring', hideDisabled: true },
|
||||
// { command: 'app.giveFeedback', hideDisabled: true },
|
||||
{ divider: true },
|
||||
{ command: 'settings.commands', hideDisabled: true },
|
||||
{ command: 'tabs.changelog', hideDisabled: true },
|
||||
{ command: 'about.show', hideDisabled: true },
|
||||
{ divider: true },
|
||||
{ command: 'file.checkForUpdates', hideDisabled: true },
|
||||
{ command: 'app.checkForUpdates', hideDisabled: true },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
// this file is generated automatically by script fillNativeModules.js, do not edit it manually
|
||||
const content = {};
|
||||
|
||||
content['better-sqlite3'] = () => require('better-sqlite3');
|
||||
content['oracledb'] = () => require('oracledb');
|
||||
|
||||
|
||||
module.exports = content;
|
||||
503
app/yarn.lock
503
app/yarn.lock
@@ -16,9 +16,9 @@
|
||||
ajv-keywords "^3.4.1"
|
||||
|
||||
"@electron/asar@^3.2.7":
|
||||
version "3.2.17"
|
||||
resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.2.17.tgz#91d28087aad80d1a1c8cc4e667c6476edf50f949"
|
||||
integrity sha512-OcWImUI686w8LkghQj9R2ynZ2ME693Ek6L1SiaAgqGKzBaTIZw3fHDqN82Rcl+EU1Gm9EgkJ5KLIY/q5DCRbbA==
|
||||
version "3.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.4.1.tgz#4e9196a4b54fba18c56cd8d5cac67c5bdc588065"
|
||||
integrity sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==
|
||||
dependencies:
|
||||
commander "^5.0.0"
|
||||
glob "^7.1.6"
|
||||
@@ -98,6 +98,18 @@
|
||||
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
|
||||
integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
|
||||
|
||||
"@isaacs/balanced-match@^4.0.1":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz#3081dadbc3460661b751e7591d7faea5df39dd29"
|
||||
integrity sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==
|
||||
|
||||
"@isaacs/brace-expansion@^5.0.0":
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz#4b3dabab7d8e75a429414a96bd67bf4c1d13e0f3"
|
||||
integrity sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==
|
||||
dependencies:
|
||||
"@isaacs/balanced-match" "^4.0.1"
|
||||
|
||||
"@isaacs/cliui@^8.0.2":
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
|
||||
@@ -202,16 +214,23 @@
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/ms@*":
|
||||
version "0.7.34"
|
||||
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433"
|
||||
integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78"
|
||||
integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
|
||||
|
||||
"@types/node@*", "@types/node@^20.9.0":
|
||||
version "20.12.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.10.tgz#8f0c3f12b0f075eee1fe20c1afb417e9765bef76"
|
||||
integrity sha512-Eem5pH9pmWBHoGAT8Dr5fdc5rYA+4NAovdM4EktRPVAAiJhmWWfQrA0cFhAbOsQdSfIHjAud6YdkbL69+zSKjw==
|
||||
"@types/node@*":
|
||||
version "24.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-24.10.0.tgz#6b79086b0dfc54e775a34ba8114dcc4e0221f31f"
|
||||
integrity sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
undici-types "~7.16.0"
|
||||
|
||||
"@types/node@^22.7.7":
|
||||
version "22.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.0.tgz#849606ef3920850583a4e7ee0930987c35ad80be"
|
||||
integrity sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA==
|
||||
dependencies:
|
||||
undici-types "~6.21.0"
|
||||
|
||||
"@types/plist@^3.0.1":
|
||||
version "3.0.5"
|
||||
@@ -229,9 +248,9 @@
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/verror@^1.10.3":
|
||||
version "1.10.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.10.tgz#d5a4b56abac169bfbc8b23d291363a682e6fa087"
|
||||
integrity sha512-l4MM0Jppn18hb9xmM6wwD1uTdShpf9Pn80aXTStnK1C94gtPvJcV2FrDmbOQUAQfJ1cKZHktkQUDwEqaAKXMMg==
|
||||
version "1.10.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.11.tgz#d3d6b418978c8aa202d41e5bb3483227b6ecc1bb"
|
||||
integrity sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==
|
||||
|
||||
"@types/yauzl@^2.9.1":
|
||||
version "2.10.3"
|
||||
@@ -241,9 +260,9 @@
|
||||
"@types/node" "*"
|
||||
|
||||
"@xmldom/xmldom@^0.8.8":
|
||||
version "0.8.10"
|
||||
resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99"
|
||||
integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==
|
||||
version "0.8.11"
|
||||
resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.11.tgz#b79de2d67389734c57c52595f7a7305e30c2d608"
|
||||
integrity sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==
|
||||
|
||||
"@yarnpkg/lockfile@^1.1.0":
|
||||
version "1.1.0"
|
||||
@@ -263,14 +282,14 @@ agent-base@6, agent-base@^6.0.2:
|
||||
debug "4"
|
||||
|
||||
agent-base@^7.1.0, agent-base@^7.1.2:
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1"
|
||||
integrity sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==
|
||||
version "7.1.4"
|
||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8"
|
||||
integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==
|
||||
|
||||
agentkeepalive@^4.2.1:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923"
|
||||
integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a"
|
||||
integrity sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==
|
||||
dependencies:
|
||||
humanize-ms "^1.2.1"
|
||||
|
||||
@@ -303,9 +322,9 @@ ansi-regex@^5.0.1:
|
||||
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||
|
||||
ansi-regex@^6.0.1:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654"
|
||||
integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==
|
||||
version "6.2.2"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1"
|
||||
integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==
|
||||
|
||||
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
version "4.3.0"
|
||||
@@ -315,9 +334,9 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
ansi-styles@^6.1.0:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
|
||||
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
|
||||
version "6.2.3"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041"
|
||||
integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==
|
||||
|
||||
app-builder-bin@5.0.0-alpha.10:
|
||||
version "5.0.0-alpha.10"
|
||||
@@ -363,9 +382,9 @@ app-builder-lib@25.1.8:
|
||||
temp-file "^3.4.0"
|
||||
|
||||
"aproba@^1.0.3 || ^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc"
|
||||
integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.1.0.tgz#75500a190313d95c64e871e7e4284c6ac219f0b1"
|
||||
integrity sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==
|
||||
|
||||
are-we-there-yet@^3.0.0:
|
||||
version "3.0.1"
|
||||
@@ -395,10 +414,10 @@ async-exit-hook@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/async-exit-hook/-/async-exit-hook-2.0.1.tgz#8bd8b024b0ec9b1c01cccb9af9db29bd717dfaf3"
|
||||
integrity sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==
|
||||
|
||||
async@^3.2.3:
|
||||
version "3.2.5"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66"
|
||||
integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==
|
||||
async@^3.2.6:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce"
|
||||
integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
@@ -447,33 +466,33 @@ boolean@^3.0.1:
|
||||
integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
version "1.1.12"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843"
|
||||
integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
brace-expansion@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
|
||||
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7"
|
||||
integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
|
||||
braces@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
braces@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
|
||||
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
|
||||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
fill-range "^7.1.1"
|
||||
|
||||
buffer-crc32@~0.2.3:
|
||||
version "0.2.13"
|
||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||
integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
|
||||
|
||||
buffer-equal-constant-time@1.0.1:
|
||||
buffer-equal-constant-time@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||
integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==
|
||||
@@ -499,10 +518,10 @@ builder-util-runtime@9.2.10:
|
||||
debug "^4.3.4"
|
||||
sax "^1.2.4"
|
||||
|
||||
builder-util-runtime@9.2.5:
|
||||
version "9.2.5"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.2.5.tgz#0afdffa0adb5c84c14926c7dd2cf3c6e96e9be83"
|
||||
integrity sha512-HjIDfhvqx/8B3TDN4GbABQcgpewTU4LMRTQPkVpKYV3lsuxEJoIfvg09GyWTNmfVNSUAYf+fbTN//JX4TH20pg==
|
||||
builder-util-runtime@9.3.1:
|
||||
version "9.3.1"
|
||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.3.1.tgz#0daedde0f6d381f2a00a50a407b166fe7dca1a67"
|
||||
integrity sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==
|
||||
dependencies:
|
||||
debug "^4.3.4"
|
||||
sax "^1.2.4"
|
||||
@@ -571,7 +590,15 @@ cacheable-request@^7.0.2:
|
||||
normalize-url "^6.0.1"
|
||||
responselike "^2.0.0"
|
||||
|
||||
chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2:
|
||||
call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6"
|
||||
integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
|
||||
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
@@ -744,9 +771,9 @@ cross-env@^6.0.3:
|
||||
cross-spawn "^7.0.0"
|
||||
|
||||
cross-spawn@^6.0.5:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
|
||||
version "6.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.6.tgz#30d0efa0712ddb7eb5a76e1e8721bffafa6b5d57"
|
||||
integrity sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==
|
||||
dependencies:
|
||||
nice-try "^1.0.4"
|
||||
path-key "^2.0.1"
|
||||
@@ -754,26 +781,19 @@ cross-spawn@^6.0.5:
|
||||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.3:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
|
||||
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.3, cross-spawn@^7.0.6:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
|
||||
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
|
||||
dependencies:
|
||||
path-key "^3.1.0"
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^4.3.3:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
|
||||
integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
|
||||
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4:
|
||||
version "4.4.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a"
|
||||
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
|
||||
dependencies:
|
||||
ms "^2.1.3"
|
||||
|
||||
@@ -825,9 +845,9 @@ delegates@^1.0.0:
|
||||
integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
|
||||
|
||||
detect-libc@^2.0.1:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700"
|
||||
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad"
|
||||
integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==
|
||||
|
||||
detect-node@^2.0.4:
|
||||
version "2.1.0"
|
||||
@@ -878,9 +898,18 @@ dotenv-expand@^11.0.6:
|
||||
dotenv "^16.4.5"
|
||||
|
||||
dotenv@^16.4.5:
|
||||
version "16.4.7"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
|
||||
integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==
|
||||
version "16.6.1"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020"
|
||||
integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==
|
||||
|
||||
dunder-proto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
|
||||
integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.1"
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.2.0"
|
||||
|
||||
eastasianwidth@^0.2.0:
|
||||
version "0.2.0"
|
||||
@@ -936,11 +965,11 @@ electron-publish@25.1.7:
|
||||
mime "^2.5.2"
|
||||
|
||||
electron-updater@^6.3.4:
|
||||
version "6.3.4"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-6.3.4.tgz#3934bc89875bb524c2cbbd11041114e97c0c2496"
|
||||
integrity sha512-uZUo7p1Y53G4tl6Cgw07X1yF8Jlz6zhaL7CQJDZ1fVVkOaBfE2cWtx80avwDVi8jHp+I/FWawrMgTAeCCNIfAg==
|
||||
version "6.6.2"
|
||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-6.6.2.tgz#3e65e044f1a99b00d61e200e24de8e709c69ce99"
|
||||
integrity sha512-Cr4GDOkbAUqRHP5/oeOmH/L2Bn6+FQPxVLZtPbcmKZC63a1F3uu5EefYOssgZXG3u/zBlubbJ5PJdITdMVggbw==
|
||||
dependencies:
|
||||
builder-util-runtime "9.2.5"
|
||||
builder-util-runtime "9.3.1"
|
||||
fs-extra "^10.1.0"
|
||||
js-yaml "^4.1.0"
|
||||
lazy-val "^1.0.5"
|
||||
@@ -949,13 +978,13 @@ electron-updater@^6.3.4:
|
||||
semver "^7.6.3"
|
||||
tiny-typed-emitter "^2.1.0"
|
||||
|
||||
electron@30.0.2:
|
||||
version "30.0.2"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-30.0.2.tgz#95ba019216bf8be9f3097580123e33ea37497733"
|
||||
integrity sha512-zv7T+GG89J/hyWVkQsLH4Y/rVEfqJG5M/wOBIGNaDdqd8UV9/YZPdS7CuFeaIj0H9LhCt95xkIQNpYB/3svOkQ==
|
||||
electron@38.6.0:
|
||||
version "38.6.0"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-38.6.0.tgz#c862bff41d42776e307bf5cc92503dda23612339"
|
||||
integrity sha512-68OFNxJlrEStA+t8k5atzf4frJddvRR1N1oalr49Ll8YZ0+0nEsDhw4UNhTCoZKTjSYcxFF/4rt+sco+OlnB3g==
|
||||
dependencies:
|
||||
"@electron/get" "^2.0.0"
|
||||
"@types/node" "^20.9.0"
|
||||
"@types/node" "^22.7.7"
|
||||
extract-zip "^2.0.1"
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
@@ -976,9 +1005,9 @@ encoding@^0.1.13:
|
||||
iconv-lite "^0.6.2"
|
||||
|
||||
end-of-stream@^1.1.0:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
|
||||
version "1.4.5"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c"
|
||||
integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
@@ -992,27 +1021,42 @@ err-code@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
|
||||
integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
|
||||
|
||||
es-define-property@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
|
||||
integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==
|
||||
dependencies:
|
||||
get-intrinsic "^1.2.4"
|
||||
es-define-property@^1.0.0, es-define-property@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
|
||||
integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==
|
||||
|
||||
es-errors@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||
|
||||
es-object-atoms@^1.0.0, es-object-atoms@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1"
|
||||
integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
|
||||
es-set-tostringtag@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d"
|
||||
integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.6"
|
||||
has-tostringtag "^1.0.2"
|
||||
hasown "^2.0.2"
|
||||
|
||||
es6-error@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
|
||||
integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
|
||||
integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
|
||||
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
|
||||
|
||||
escape-string-regexp@^4.0.0:
|
||||
version "4.0.0"
|
||||
@@ -1020,9 +1064,9 @@ escape-string-regexp@^4.0.0:
|
||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||
|
||||
exponential-backoff@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6"
|
||||
integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.3.tgz#51cf92c1c0493c766053f9d3abee4434c244d2f6"
|
||||
integrity sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==
|
||||
|
||||
extract-zip@^2.0.1:
|
||||
version "2.0.1"
|
||||
@@ -1064,10 +1108,10 @@ filelist@^1.0.4:
|
||||
dependencies:
|
||||
minimatch "^5.0.1"
|
||||
|
||||
fill-range@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
|
||||
fill-range@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
|
||||
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
@@ -1079,20 +1123,22 @@ find-yarn-workspace-root@^2.0.0:
|
||||
micromatch "^4.0.2"
|
||||
|
||||
foreground-child@^3.1.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77"
|
||||
integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f"
|
||||
integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.0"
|
||||
cross-spawn "^7.0.6"
|
||||
signal-exit "^4.0.1"
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4"
|
||||
integrity sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
es-set-tostringtag "^2.1.0"
|
||||
hasown "^2.0.2"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fs-extra@^10.0.0, fs-extra@^10.1.0:
|
||||
@@ -1105,9 +1151,9 @@ fs-extra@^10.0.0, fs-extra@^10.1.0:
|
||||
universalify "^2.0.0"
|
||||
|
||||
fs-extra@^11.1.1:
|
||||
version "11.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b"
|
||||
integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==
|
||||
version "11.3.2"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.2.tgz#c838aeddc6f4a8c74dd15f85e11fe5511bfe02a4"
|
||||
integrity sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
@@ -1168,16 +1214,29 @@ get-caller-file@^2.0.5:
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
get-intrinsic@^1.1.3, get-intrinsic@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
|
||||
integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
|
||||
get-intrinsic@^1.2.6:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
|
||||
integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.2"
|
||||
es-define-property "^1.0.1"
|
||||
es-errors "^1.3.0"
|
||||
es-object-atoms "^1.1.1"
|
||||
function-bind "^1.1.2"
|
||||
has-proto "^1.0.1"
|
||||
has-symbols "^1.0.3"
|
||||
hasown "^2.0.0"
|
||||
get-proto "^1.0.1"
|
||||
gopd "^1.2.0"
|
||||
has-symbols "^1.1.0"
|
||||
hasown "^2.0.2"
|
||||
math-intrinsics "^1.1.0"
|
||||
|
||||
get-proto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
|
||||
integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
|
||||
dependencies:
|
||||
dunder-proto "^1.0.1"
|
||||
es-object-atoms "^1.0.0"
|
||||
|
||||
get-stream@^5.1.0:
|
||||
version "5.2.0"
|
||||
@@ -1241,12 +1300,10 @@ globalthis@^1.0.1:
|
||||
define-properties "^1.2.1"
|
||||
gopd "^1.0.1"
|
||||
|
||||
gopd@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
|
||||
integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
|
||||
dependencies:
|
||||
get-intrinsic "^1.1.3"
|
||||
gopd@^1.0.1, gopd@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
|
||||
integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
|
||||
|
||||
got@^11.7.0, got@^11.8.5:
|
||||
version "11.8.6"
|
||||
@@ -1282,22 +1339,24 @@ has-property-descriptors@^1.0.0:
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
|
||||
has-proto@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd"
|
||||
integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==
|
||||
has-symbols@^1.0.3, has-symbols@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
|
||||
integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
|
||||
|
||||
has-symbols@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
|
||||
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
|
||||
has-tostringtag@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
|
||||
integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
|
||||
dependencies:
|
||||
has-symbols "^1.0.3"
|
||||
|
||||
has-unicode@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||
integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==
|
||||
|
||||
hasown@^2.0.0:
|
||||
hasown@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
@@ -1312,9 +1371,9 @@ hosted-git-info@^4.1.0:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
|
||||
integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz#205f4db64f8562b76a4ff9235aa5279839a09dd5"
|
||||
integrity sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==
|
||||
|
||||
http-proxy-agent@^5.0.0:
|
||||
version "5.0.0"
|
||||
@@ -1412,13 +1471,10 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1,
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
ip-address@^9.0.5:
|
||||
version "9.0.5"
|
||||
resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a"
|
||||
integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==
|
||||
dependencies:
|
||||
jsbn "1.1.0"
|
||||
sprintf-js "^1.1.3"
|
||||
ip-address@^10.0.1:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.1.0.tgz#d8dcffb34d0e02eb241427444a6e23f5b0595aa4"
|
||||
integrity sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==
|
||||
|
||||
is-ci@^2.0.0:
|
||||
version "2.0.0"
|
||||
@@ -1487,9 +1543,9 @@ isbinaryfile@^4.0.8:
|
||||
integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==
|
||||
|
||||
isbinaryfile@^5.0.0:
|
||||
version "5.0.4"
|
||||
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-5.0.4.tgz#2a2edefa76cafa66613fe4c1ea52f7f031017bdf"
|
||||
integrity sha512-YKBKVkKhty7s8rxddb40oOkuP0NbaeXrQvLin6QMHL7Ypiy2RW9LwOVrVgZRyOrhQlayMd9t+D8yDy8MKFTSDQ==
|
||||
version "5.0.6"
|
||||
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-5.0.6.tgz#01eac28867aeffaebaee7eaf21d1dd3a67d7c0c7"
|
||||
integrity sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
@@ -1506,14 +1562,13 @@ jackspeak@^3.1.2:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
jake@^10.8.5:
|
||||
version "10.9.1"
|
||||
resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.1.tgz#8dc96b7fcc41cb19aa502af506da4e1d56f5e62b"
|
||||
integrity sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w==
|
||||
version "10.9.4"
|
||||
resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.4.tgz#d626da108c63d5cfb00ab5c25fadc7e0084af8e6"
|
||||
integrity sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==
|
||||
dependencies:
|
||||
async "^3.2.3"
|
||||
chalk "^4.0.2"
|
||||
async "^3.2.6"
|
||||
filelist "^1.0.4"
|
||||
minimatch "^3.1.2"
|
||||
picocolors "^1.1.1"
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
@@ -1522,11 +1577,6 @@ js-yaml@^4.1.0:
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
jsbn@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040"
|
||||
integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==
|
||||
|
||||
json-buffer@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
|
||||
@@ -1555,9 +1605,9 @@ jsonfile@^4.0.0:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonfile@^6.0.1:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
|
||||
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.2.0.tgz#7c265bd1b65de6977478300087c99f1c84383f62"
|
||||
integrity sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==
|
||||
dependencies:
|
||||
universalify "^2.0.0"
|
||||
optionalDependencies:
|
||||
@@ -1580,11 +1630,11 @@ jsonwebtoken@^9.0.2:
|
||||
semver "^7.5.4"
|
||||
|
||||
jwa@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
|
||||
integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
|
||||
version "1.4.2"
|
||||
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.2.tgz#16011ac6db48de7b102777e57897901520eec7b9"
|
||||
integrity sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==
|
||||
dependencies:
|
||||
buffer-equal-constant-time "1.0.1"
|
||||
buffer-equal-constant-time "^1.0.1"
|
||||
ecdsa-sig-formatter "1.0.11"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
@@ -1729,12 +1779,17 @@ matcher@^3.0.0:
|
||||
dependencies:
|
||||
escape-string-regexp "^4.0.0"
|
||||
|
||||
math-intrinsics@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
|
||||
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
|
||||
|
||||
micromatch@^4.0.2:
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
|
||||
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
|
||||
integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
|
||||
dependencies:
|
||||
braces "^3.0.2"
|
||||
braces "^3.0.3"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
mime-db@1.52.0:
|
||||
@@ -1770,13 +1825,13 @@ mimic-response@^3.1.0:
|
||||
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
|
||||
|
||||
minimatch@^10.0.0:
|
||||
version "10.0.1"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b"
|
||||
integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==
|
||||
version "10.1.1"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.1.1.tgz#e6e61b9b0c1dcab116b5a7d1458e8b6ae9e73a55"
|
||||
integrity sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
"@isaacs/brace-expansion" "^5.0.0"
|
||||
|
||||
minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
@@ -1871,11 +1926,6 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
ms@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
@@ -1892,9 +1942,9 @@ nice-try@^1.0.4:
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
node-abi@^3.45.0:
|
||||
version "3.71.0"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.71.0.tgz#52d84bbcd8575efb71468fbaa1f9a49b2c242038"
|
||||
integrity sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==
|
||||
version "3.80.0"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.80.0.tgz#d7390951f27caa129cceeec01e1c20fc9f07581c"
|
||||
integrity sha512-LyPuZJcI9HVwzXK1GPxWNzrr+vr8Hp/3UqlmWxxh8p54U1ZbclOqbSog9lWHaCX+dBaiGi6n/hIX+mKu74GmPA==
|
||||
dependencies:
|
||||
semver "^7.3.5"
|
||||
|
||||
@@ -1904,9 +1954,9 @@ node-addon-api@^1.6.3:
|
||||
integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==
|
||||
|
||||
node-api-version@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/node-api-version/-/node-api-version-0.2.0.tgz#5177441da2b1046a4d4547ab9e0972eed7b1ac1d"
|
||||
integrity sha512-fthTTsi8CxaBXMaBAD7ST2uylwvsnYxh2PfaScwpMhos6KlSFajXQPcM4ogNE1q2s3Lbz9GCGqeIHC+C6OZnKg==
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/node-api-version/-/node-api-version-0.2.1.tgz#19bad54f6d65628cbee4e607a325e4488ace2de9"
|
||||
integrity sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==
|
||||
dependencies:
|
||||
semver "^7.3.5"
|
||||
|
||||
@@ -2081,6 +2131,11 @@ pend@~1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
|
||||
integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
|
||||
|
||||
picocolors@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
|
||||
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
|
||||
|
||||
picomatch@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
@@ -2119,9 +2174,9 @@ promise-retry@^2.0.1:
|
||||
retry "^0.12.0"
|
||||
|
||||
pump@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
|
||||
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d"
|
||||
integrity sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==
|
||||
dependencies:
|
||||
end-of-stream "^1.1.0"
|
||||
once "^1.3.1"
|
||||
@@ -2261,9 +2316,9 @@ sanitize-filename@^1.6.3:
|
||||
truncate-utf8-bytes "^1.0.0"
|
||||
|
||||
sax@^1.2.4:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0"
|
||||
integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.3.tgz#fcebae3b756cdc8428321805f4b70f16ec0ab5db"
|
||||
integrity sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==
|
||||
|
||||
semver-compare@^1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -2280,15 +2335,10 @@ semver@^6.2.0:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||
|
||||
semver@^7.3.2:
|
||||
version "7.6.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.1.tgz#60bfe090bf907a25aa8119a72b9f90ef7ca281b2"
|
||||
integrity sha512-f/vbBsu+fOiYt+lmwZV0rVwJScl46HppnOA1ZvIuBWKOTlllpyJ3bfVax76/OrhCH38dyxoDIA8K7uB963IYgA==
|
||||
|
||||
semver@^7.3.5, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.3:
|
||||
version "7.6.3"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
|
||||
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
||||
semver@^7.3.2, semver@^7.3.5, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.3:
|
||||
version "7.7.3"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946"
|
||||
integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==
|
||||
|
||||
serialize-error@^7.0.1:
|
||||
version "7.0.1"
|
||||
@@ -2372,11 +2422,11 @@ socks-proxy-agent@^7.0.0:
|
||||
socks "^2.6.2"
|
||||
|
||||
socks@^2.6.2:
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.3.tgz#1ebd0f09c52ba95a09750afe3f3f9f724a800cb5"
|
||||
integrity sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==
|
||||
version "2.8.7"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.7.tgz#e2fb1d9a603add75050a2067db8c381a0b5669ea"
|
||||
integrity sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==
|
||||
dependencies:
|
||||
ip-address "^9.0.5"
|
||||
ip-address "^10.0.1"
|
||||
smart-buffer "^4.2.0"
|
||||
|
||||
source-map-support@^0.5.19:
|
||||
@@ -2392,7 +2442,7 @@ source-map@^0.6.0:
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
sprintf-js@^1.1.2, sprintf-js@^1.1.3:
|
||||
sprintf-js@^1.1.2:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
|
||||
integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==
|
||||
@@ -2454,9 +2504,9 @@ string_decoder@~1.1.1:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@^7.0.1:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
|
||||
integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba"
|
||||
integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==
|
||||
dependencies:
|
||||
ansi-regex "^6.0.1"
|
||||
|
||||
@@ -2522,9 +2572,9 @@ tmp@^0.0.33:
|
||||
os-tmpdir "~1.0.2"
|
||||
|
||||
tmp@^0.2.0:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae"
|
||||
integrity sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==
|
||||
version "0.2.5"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.5.tgz#b06bcd23f0f3c8357b426891726d16015abfd8f8"
|
||||
integrity sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
@@ -2546,14 +2596,19 @@ type-fest@^0.13.1:
|
||||
integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==
|
||||
|
||||
typescript@^5.4.3:
|
||||
version "5.7.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
|
||||
integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==
|
||||
version "5.9.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
|
||||
integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
|
||||
|
||||
undici-types@~5.26.4:
|
||||
version "5.26.5"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||
undici-types@~6.21.0:
|
||||
version "6.21.0"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
|
||||
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
|
||||
|
||||
undici-types@~7.16.0:
|
||||
version "7.16.0"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46"
|
||||
integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==
|
||||
|
||||
unique-filename@^2.0.0:
|
||||
version "2.0.1"
|
||||
@@ -2592,9 +2647,9 @@ uri-js@^4.2.2:
|
||||
punycode "^2.1.0"
|
||||
|
||||
utf8-byte-length@^1.0.1:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61"
|
||||
integrity sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz#f9f63910d15536ee2b2d5dd4665389715eac5c1e"
|
||||
integrity sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
|
||||
129
common/assign-dbgm-codes.mjs
Normal file
129
common/assign-dbgm-codes.mjs
Normal file
@@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env node
|
||||
// assign-dbgm-codes.mjs
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
const PLACEHOLDER = 'DBGM-00000';
|
||||
const CODE_RE = /DBGM-(\d{5})/g;
|
||||
const JS_TS_RE = /\.(mjs|cjs|js|ts|jsx|tsx)$/i;
|
||||
|
||||
const IGNORE_DIRS = new Set([
|
||||
'node_modules',
|
||||
'.git',
|
||||
'.hg',
|
||||
'.svn',
|
||||
'dist',
|
||||
'build',
|
||||
'out',
|
||||
'.next',
|
||||
'.turbo',
|
||||
'.cache',
|
||||
]);
|
||||
const IGNORE_FILES = ['assign-dbgm-codes.mjs', 'package.json', 'README.md'];
|
||||
|
||||
// --- CLI ---
|
||||
const args = process.argv.slice(2);
|
||||
const dryRun = args.includes('--dry');
|
||||
const rootArg = args.find(a => a !== '--dry') || process.cwd();
|
||||
const root = path.resolve(rootArg);
|
||||
|
||||
// --- helpers ---
|
||||
async function* walk(dir) {
|
||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||
for (const e of entries) {
|
||||
if (e.isDirectory()) {
|
||||
if (IGNORE_DIRS.has(e.name)) continue;
|
||||
yield* walk(path.join(dir, e.name));
|
||||
} else if (e.isFile()) {
|
||||
if (JS_TS_RE.test(e.name) && !IGNORE_FILES.includes(e.name)) yield path.join(dir, e.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function formatCode(n) {
|
||||
return `DBGM-${String(n).padStart(5, '0')}`;
|
||||
}
|
||||
|
||||
// Find the smallest positive integer not in `taken`
|
||||
function makeNextCodeFn(taken) {
|
||||
let n = 1;
|
||||
// advance n to first free
|
||||
while (taken.has(n)) n++;
|
||||
return () => {
|
||||
const code = n;
|
||||
taken.add(code);
|
||||
// move n to next free for next call
|
||||
do {
|
||||
n++;
|
||||
} while (taken.has(n));
|
||||
return formatCode(code);
|
||||
};
|
||||
}
|
||||
|
||||
// --- main ---
|
||||
(async () => {
|
||||
console.log(`Scanning: ${root} ${dryRun ? '(dry run)' : ''}`);
|
||||
|
||||
// 1) Collect all taken codes across the repo
|
||||
const taken = new Set(); // numeric parts only
|
||||
const files = [];
|
||||
for await (const file of walk(root)) files.push(file);
|
||||
|
||||
await Promise.all(
|
||||
files.map(async file => {
|
||||
try {
|
||||
const text = await fs.readFile(file, 'utf8');
|
||||
for (const m of text.matchAll(CODE_RE)) {
|
||||
const num = Number(m[1]);
|
||||
if (Number.isInteger(num) && num > 0) taken.add(num);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`! Failed to read ${file}: ${err.message}`);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
console.log(`Found ${taken.size} occupied code(s).`);
|
||||
|
||||
// 2) Replace placeholders with next available unique code
|
||||
const nextCode = makeNextCodeFn(taken);
|
||||
|
||||
let filesChanged = 0;
|
||||
let placeholdersReplaced = 0;
|
||||
|
||||
for (const file of files) {
|
||||
let text;
|
||||
try {
|
||||
text = await fs.readFile(file, 'utf8');
|
||||
} catch (err) {
|
||||
console.warn(`! Failed to read ${file}: ${err.message}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!text.includes(PLACEHOLDER)) continue;
|
||||
|
||||
let countInFile = 0;
|
||||
const updated = text.replaceAll(PLACEHOLDER, () => {
|
||||
countInFile++;
|
||||
return nextCode();
|
||||
});
|
||||
|
||||
if (countInFile > 0) {
|
||||
placeholdersReplaced += countInFile;
|
||||
filesChanged++;
|
||||
console.log(`${dryRun ? '[dry]' : '[write]'} ${file} — ${countInFile} replacement(s)`);
|
||||
if (!dryRun) {
|
||||
try {
|
||||
await fs.writeFile(file, updated, 'utf8');
|
||||
} catch (err) {
|
||||
console.warn(`! Failed to write ${file}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Done. Files changed: ${filesChanged}, placeholders replaced: ${placeholdersReplaced}.`);
|
||||
})().catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
110
common/fixYmlHashes.js
Normal file
110
common/fixYmlHashes.js
Normal file
@@ -0,0 +1,110 @@
|
||||
import fs from 'node:fs/promises';
|
||||
import { createHash } from 'node:crypto';
|
||||
import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import YAML from 'yaml';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
async function sha512Base64(filePath) {
|
||||
const buf = await fs.readFile(filePath);
|
||||
const h = createHash('sha512');
|
||||
h.update(buf);
|
||||
return h.digest('base64');
|
||||
}
|
||||
|
||||
async function fileSize(filePath) {
|
||||
const st = await fs.stat(filePath);
|
||||
return st.size;
|
||||
}
|
||||
|
||||
async function fixOneYaml(ymlPath, distDir) {
|
||||
let raw;
|
||||
try {
|
||||
raw = await fs.readFile(ymlPath, 'utf8');
|
||||
} catch (e) {
|
||||
console.error(`✗ Cannot read ${ymlPath}:`, e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
let doc;
|
||||
try {
|
||||
doc = YAML.parse(raw);
|
||||
} catch (e) {
|
||||
console.error(`✗ Cannot parse YAML ${ymlPath}:`, e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!doc || !Array.isArray(doc.files)) {
|
||||
console.warn(`! ${path.basename(ymlPath)} has no 'files' array — skipped.`);
|
||||
return;
|
||||
}
|
||||
|
||||
let changed = false;
|
||||
|
||||
// Update each files[i].sha512 and files[i].size based on files[i].url
|
||||
for (const entry of doc.files) {
|
||||
if (!entry?.url) continue;
|
||||
|
||||
const target = path.resolve(distDir, entry.url);
|
||||
try {
|
||||
const [hash, size] = await Promise.all([sha512Base64(target), fileSize(target)]);
|
||||
if (entry.sha512 !== hash || entry.size !== size) {
|
||||
console.log(`• ${path.basename(ymlPath)}: refresh ${entry.url}`);
|
||||
entry.sha512 = hash;
|
||||
entry.size = size;
|
||||
changed = true;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`! Missing or unreadable file for ${entry.url} (referenced by ${path.basename(ymlPath)}): ${e.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Update top-level sha512 for the primary "path" file if present
|
||||
if (doc.path) {
|
||||
const primary = path.resolve(distDir, doc.path);
|
||||
try {
|
||||
const hash = await sha512Base64(primary);
|
||||
if (doc.sha512 !== hash) {
|
||||
console.log(`• ${path.basename(ymlPath)}: refresh top-level sha512 for path=${doc.path}`);
|
||||
doc.sha512 = hash;
|
||||
changed = true;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(`! Primary 'path' file not found for ${path.basename(ymlPath)}: ${doc.path} (${e.message})`);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
const out = YAML.stringify(doc);
|
||||
await fs.writeFile(ymlPath, out, 'utf8');
|
||||
console.log(`✓ Updated ${path.basename(ymlPath)}`);
|
||||
} else {
|
||||
console.log(`= No changes for ${path.basename(ymlPath)}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const distDir = path.resolve(process.argv[2] ?? path.join(__dirname, '..', 'app', 'dist'));
|
||||
const entries = await fs.readdir(distDir);
|
||||
const ymls = entries.filter(f => f.toLowerCase().endsWith('.yml'));
|
||||
|
||||
if (ymls.length === 0) {
|
||||
console.warn(`No .yml files found in ${distDir}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Scanning ${distDir}`);
|
||||
for (const y of ymls) {
|
||||
await fixOneYaml(path.join(distDir, y), distDir);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -6,7 +6,7 @@ const { getFiles } = require('./helpers');
|
||||
|
||||
const readFilePromise = promisify(fs.readFile);
|
||||
|
||||
const translationRegex = /_t\(\s*['"]([^'"]+)['"]\s*,\s*\{\s*defaultMessage\s*:\s*['"]([^'"]+)['"]\s*\}/g;
|
||||
const translationRegex = /_t\(\s*['"]([^'"]+)['"]\s*,\s*\{\s*defaultMessage\s*:\s*(?:'([^'\\]*(?:\\.[^'\\]*)*)'|"([^"\\]*(?:\\.[^"\\]*)*)"|\`([^`\\]*(?:\\.[^`\\]*)*(?:\{[^}]*\}[^`\\]*(?:\\.[^`\\]*)*)*)\`)(?:\s*,\s*[^}]*)*\s*\}/g;
|
||||
|
||||
/**
|
||||
* @param {string} file
|
||||
@@ -20,7 +20,8 @@ async function extractTranslationsFromFile(file) {
|
||||
let match;
|
||||
|
||||
while ((match = translationRegex.exec(content)) !== null) {
|
||||
const [_, key, defaultText] = match;
|
||||
const [_, key, singleQuotedText, doubleQuotedText, templateLiteral] = match;
|
||||
const defaultText = singleQuotedText || doubleQuotedText || templateLiteral;
|
||||
translations[key] = defaultText;
|
||||
}
|
||||
|
||||
|
||||
@@ -160,4 +160,31 @@ program
|
||||
}
|
||||
});
|
||||
|
||||
program
|
||||
.command('sort')
|
||||
.description('Sort translation files by keys')
|
||||
.action(() => {
|
||||
try {
|
||||
const languages = getAllNonDefaultLanguages();
|
||||
for (const language of languages) {
|
||||
const filePath = `./translations/${language}.json`;
|
||||
const content = fs.readFileSync(filePath, 'utf-8');
|
||||
const translations = JSON.parse(content);
|
||||
const sortedTranslations = {};
|
||||
Object.keys(translations)
|
||||
.sort()
|
||||
.forEach(key => {
|
||||
// @ts-ignore
|
||||
sortedTranslations[key] = translations[key];
|
||||
});
|
||||
fs.writeFileSync(filePath, JSON.stringify(sortedTranslations, null, 2), 'utf-8');
|
||||
console.log(`Sorted translations for language: ${language}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error('Error during sort:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = { program };
|
||||
|
||||
133
common/translations-cli/translate.js
Normal file
133
common/translations-cli/translate.js
Normal file
@@ -0,0 +1,133 @@
|
||||
require('dotenv').config({ path: '.env.translation' });
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const OpenAI = require('openai');
|
||||
|
||||
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
||||
|
||||
const translationsDir = path.join(__dirname, '../../translations');
|
||||
const enFilePath = path.join(translationsDir, 'en.json');
|
||||
|
||||
const languageNames = {
|
||||
'cs.json': 'Czech',
|
||||
'de.json': 'German',
|
||||
'es.json': 'Spanish',
|
||||
'fr.json': 'French',
|
||||
'it.json': 'Italian',
|
||||
'ja.json': 'Japanese',
|
||||
'ko.json': 'Korean',
|
||||
'pt.json': 'Portuguese',
|
||||
'sk.json': 'Slovak',
|
||||
'zh.json': 'Chinese'
|
||||
};
|
||||
|
||||
// Read source (english)
|
||||
const enTranslations = JSON.parse(fs.readFileSync(enFilePath, 'utf8'));
|
||||
const enKeys = Object.keys(enTranslations);
|
||||
|
||||
// Get all translation files
|
||||
const translationFiles = fs.readdirSync(translationsDir)
|
||||
.filter(file => file.endsWith('.json') && file !== 'en.json')
|
||||
.sort();
|
||||
|
||||
console.log(`Found ${enKeys.length} keys in en.json\n`);
|
||||
console.log('='.repeat(80));
|
||||
|
||||
async function translateMissingIds({file, translations, missingIds}){
|
||||
const languageName = languageNames[file];
|
||||
if (!languageName) {
|
||||
console.log(`No language name mapping for file: ${file}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Build object with only missing translations
|
||||
const needed = {};
|
||||
missingIds.forEach(key => {
|
||||
needed[key] = enTranslations[key];
|
||||
});
|
||||
|
||||
// Get all existing translations as style examples
|
||||
const existingTranslations = {};
|
||||
Object.keys(translations).forEach(key => {
|
||||
if (translations[key] && !translations[key].startsWith('***')) {
|
||||
existingTranslations[key] = {
|
||||
en: enTranslations[key],
|
||||
translated: translations[key]
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const prompt = `You are a professional translator for DbGate, a database management application.
|
||||
|
||||
Translate the following English UI strings to ${languageName}.
|
||||
|
||||
IMPORTANT RULES:
|
||||
1. Preserve ALL placeholders exactly as they appear: {plugin}, {columnNumber}, {0}, {1}, etc.
|
||||
2. Maintain technical terminology appropriately for database software
|
||||
3. Match the translation style, tone, and formality of the existing translations shown below
|
||||
4. Keep the same level of brevity or verbosity as the existing translations
|
||||
5. Return ONLY valid JSON - no markdown, no explanations, no code blocks
|
||||
6. Use the same keys as provided
|
||||
|
||||
EXISTING TRANSLATIONS (for style reference):
|
||||
${JSON.stringify(existingTranslations, null, 2)}
|
||||
|
||||
STRINGS TO TRANSLATE:
|
||||
${JSON.stringify(needed, null, 2)}
|
||||
|
||||
Return format: {"key": "translated value", ...}`;
|
||||
|
||||
const response = await client.chat.completions.create({
|
||||
model: 'gpt-5.1',
|
||||
messages: [
|
||||
{ role: 'system', content: 'You are a professional translator specializing in software localization. Match the style and tone of existing translations. Return only valid JSON.' },
|
||||
{ role: 'user', content: prompt }
|
||||
],
|
||||
temperature: 0.2
|
||||
});
|
||||
|
||||
let translatedJson = response.choices[0].message.content.trim();
|
||||
|
||||
// Remove markdown code blocks if present
|
||||
translatedJson = translatedJson.replace(/^```json\n?/, '').replace(/\n?```$/, '');
|
||||
|
||||
return JSON.parse(translatedJson);
|
||||
}
|
||||
|
||||
(async () => {
|
||||
for (const file of translationFiles) {
|
||||
const filePath = path.join(translationsDir, file);
|
||||
const translations = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
||||
|
||||
const missingIds = enKeys.filter(key => !translations.hasOwnProperty(key) || (typeof translations[key] === 'string' && translations[key].startsWith('***')));
|
||||
|
||||
|
||||
console.log(`\n${file.toUpperCase()}`);
|
||||
console.log('-'.repeat(80));
|
||||
|
||||
if (missingIds.length === 0) {
|
||||
console.log('✓ All translations complete!');
|
||||
continue;
|
||||
} else {
|
||||
console.log(`Found ${missingIds.length} untranslated IDs\n`);
|
||||
}
|
||||
|
||||
const newTranslations = await translateMissingIds({file, translations, missingIds});
|
||||
|
||||
if (!newTranslations) {
|
||||
console.log(`Skipping file due to translation error: ${file}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(newTranslations)) {
|
||||
translations[key] = value;
|
||||
console.log(`Translated: ${key} => ${value}`);
|
||||
}
|
||||
|
||||
fs.writeFileSync(filePath, JSON.stringify(translations, null, 2) + '\n', 'utf8');
|
||||
console.log(`\n✓ Updated translations written to ${file}`);
|
||||
}
|
||||
|
||||
console.log('\n' + '='.repeat(80));
|
||||
console.log('Translation complete!\n');
|
||||
})();
|
||||
@@ -4,6 +4,7 @@ const volatilePackages = [
|
||||
'@clickhouse/client',
|
||||
'bson', // this package is already bundled and is used in mongodb
|
||||
'mongodb',
|
||||
'mongodb-old',
|
||||
'mongodb-client-encryption',
|
||||
'tedious',
|
||||
'msnodesqlv8',
|
||||
@@ -14,12 +15,16 @@ const volatilePackages = [
|
||||
'ioredis',
|
||||
'node-redis-dump2',
|
||||
'better-sqlite3',
|
||||
'libsql',
|
||||
'@azure/cosmos',
|
||||
'@aws-sdk/rds-signer',
|
||||
'activedirectory2',
|
||||
'axios',
|
||||
'ssh2',
|
||||
'wkx',
|
||||
'@duckdb/node-api',
|
||||
'@mongosh/browser-runtime-electron',
|
||||
'@mongosh/service-provider-node-driver',
|
||||
];
|
||||
|
||||
module.exports = volatilePackages;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
FROM node:22
|
||||
|
||||
LABEL org.opencontainers.image.source="https://github.com/dbgate/dbgate"
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
iputils-ping \
|
||||
iproute2 \
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
FROM node:18-alpine
|
||||
|
||||
LABEL org.opencontainers.image.source="https://github.com/dbgate/dbgate"
|
||||
|
||||
WORKDIR /home/dbgate-docker
|
||||
|
||||
RUN apk --no-cache upgrade \
|
||||
|
||||
@@ -7,7 +7,10 @@ const path = require('path');
|
||||
|
||||
module.exports = defineConfig({
|
||||
e2e: {
|
||||
// baseUrl: 'http://localhost:3000',
|
||||
// trashAssetsBeforeRuns: false,
|
||||
chromeWebSecurity: false,
|
||||
reporter: process.env.CI ? 'mocha-reporter-gha' : 'spec',
|
||||
|
||||
setupNodeEvents(on, config) {
|
||||
// implement node event listeners here
|
||||
@@ -40,6 +43,15 @@ module.exports = defineConfig({
|
||||
case 'multi-sql':
|
||||
serverProcess = exec('yarn start:multi-sql');
|
||||
break;
|
||||
case 'cloud':
|
||||
serverProcess = exec('yarn start:cloud');
|
||||
break;
|
||||
case 'charts':
|
||||
serverProcess = exec('yarn start:charts');
|
||||
break;
|
||||
case 'redis':
|
||||
serverProcess = exec('yarn start:redis');
|
||||
break;
|
||||
}
|
||||
|
||||
await waitOn({ resources: ['http://localhost:3000'] });
|
||||
|
||||
@@ -13,16 +13,22 @@ describe('Add connection', () => {
|
||||
it('adds connection', () => {
|
||||
// cy.get('[data-testid=ConnectionList_buttonNewConnection]').click();
|
||||
cy.get('[data-testid=ConnectionDriverFields_connectionType]').select('MySQL');
|
||||
cy.themeshot('connection');
|
||||
cy.themeshot('new-connection');
|
||||
cy.get('[data-testid=ConnectionDriverFields_user]').clear().type('root');
|
||||
cy.get('[data-testid=ConnectionDriverFields_password]').clear().type('Pwd2020Db');
|
||||
cy.get('[data-testid=ConnectionDriverFields_port]').clear().type('16004');
|
||||
cy.get('[data-testid=ConnectionDriverFields_displayName]').clear().type('test-mysql-1');
|
||||
|
||||
// test connection
|
||||
cy.get('[data-testid=ConnectionTab_buttonTest]').click();
|
||||
cy.testid('ConnectionTab_buttonTest').click();
|
||||
cy.contains('Connected:');
|
||||
|
||||
cy.testid('ConnectionTab_tabSshTunnel').click();
|
||||
cy.testid('ConnectionTab_tabControlContent').themeshot('connection-sshtunnel-window', { padding: 50 });
|
||||
|
||||
cy.testid('ConnectionTab_tabSsl').click();
|
||||
cy.testid('ConnectionTab_tabControlContent').themeshot('connection-ssl-window', { padding: 50 });
|
||||
|
||||
// save and connect
|
||||
cy.get('[data-testid=ConnectionTab_buttonSave]').click();
|
||||
cy.get('[data-testid=ConnectionTab_buttonConnect]').click();
|
||||
@@ -106,4 +112,36 @@ describe('Add connection', () => {
|
||||
|
||||
cy.contains('performance_schema');
|
||||
});
|
||||
|
||||
it('Plugin tab', () => {
|
||||
cy.testid('WidgetIconPanel_menu').click();
|
||||
cy.contains('Tools').click();
|
||||
cy.contains('Manage plugins').click();
|
||||
cy.contains('dbgate-plugin-theme-total-white').click();
|
||||
// text from plugin markdown
|
||||
cy.contains('Total white theme');
|
||||
// wait for load logos
|
||||
cy.wait(2000);
|
||||
cy.themeshot('view-plugin-tab');
|
||||
});
|
||||
|
||||
it('export connections', () => {
|
||||
cy.testid('WidgetIconPanel_menu').click();
|
||||
cy.contains('Tools').click();
|
||||
cy.contains('Export connections').click();
|
||||
cy.themeshot('export-connections');
|
||||
});
|
||||
|
||||
it('configure LLM provider', () => {
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
cy.contains('Settings').click();
|
||||
cy.contains('AI').click();
|
||||
cy.testid('AiSupportedProvidersInfo_add_OpenRouter').click();
|
||||
cy.testid('AiProviderCard_apikey_OpenRouter').clear().type('xxx');
|
||||
cy.testid('AiProviderCard_testButton_OpenRouter').click();
|
||||
cy.testid('AiProviderCard_statusValid_OpenRouter').should('exist');
|
||||
cy.testid('AiProviderCard_editButton_OpenRouter').click();
|
||||
cy.wait(1000);
|
||||
cy.themeshot('llm-providers-settings');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,18 +15,23 @@ beforeEach(() => {
|
||||
describe('Data browser data', () => {
|
||||
it('Export window', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').rightclick();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Album').rightclick();
|
||||
cy.contains('Export').click();
|
||||
cy.contains('Export advanced').click();
|
||||
cy.wait(1000);
|
||||
// cy.testid('SourceTargetConfig_buttonCurrentArchive_target').click();
|
||||
cy.testid('FormTablesSelect_buttonAll_tables').click();
|
||||
// cy.testid('FormTablesSelect_buttonAll_tables').click();
|
||||
// cy.testid('SourceTargetConfig_tablesSelect_source').click();
|
||||
// cy.find('.listContainer').contains('Album').click();
|
||||
// cy.find('.listContainer').contains('Track').click();
|
||||
// cy.wait(4000);
|
||||
// cy.contains('All tables').click();
|
||||
cy.contains('Run').click();
|
||||
cy.contains('Finished job script');
|
||||
cy.contains('Album.csv');
|
||||
cy.testid('WidgetIconPanel_database').click();
|
||||
cy.themeshot('exportcsv');
|
||||
cy.themeshot('configure-export-csv');
|
||||
});
|
||||
|
||||
it('Data archive editor - macros', () => {
|
||||
@@ -37,7 +42,7 @@ describe('Data browser data', () => {
|
||||
cy.contains('Out Of Exile').click({ shiftKey: true });
|
||||
cy.contains('Change text case').click();
|
||||
cy.contains('AUDIOSLAVE');
|
||||
cy.themeshot('freetable');
|
||||
cy.themeshot('data-archive-macros');
|
||||
});
|
||||
|
||||
it('Load table data', () => {
|
||||
@@ -55,7 +60,7 @@ describe('Data browser data', () => {
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('SqlObjectList_search').clear().type('album');
|
||||
cy.contains('Tables (1/11)');
|
||||
cy.contains('347 rows, InnoDB');
|
||||
cy.contains('347 rows, 65.5 KB, InnoDB');
|
||||
cy.testid('SqlObjectList_searchMenuDropDown').click();
|
||||
cy.contains('Column name').click();
|
||||
cy.contains('Tables (2/11)');
|
||||
@@ -76,11 +81,27 @@ describe('Data browser data', () => {
|
||||
cy.contains('Aerosmith').should('not.exist');
|
||||
});
|
||||
|
||||
it('Data filter', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Album').click();
|
||||
|
||||
// hide what is not needed
|
||||
cy.testid('WidgetIconPanel_database').click();
|
||||
cy.testid('DataGrid_itemReferences').click();
|
||||
|
||||
cy.testid('DataFilterControl_input_Title').type('Rock{enter}');
|
||||
cy.contains('Rows: 7');
|
||||
cy.testid('DataFilterControl_input_AlbumId').type('>10xxx{enter}');
|
||||
cy.contains('Rows: 7');
|
||||
cy.testid('DataFilterControl_filtermenu_ArtistId').click();
|
||||
cy.themeshot('data-browser-filter');
|
||||
cy.testid('DataGridCore_button_clearFilters').click();
|
||||
cy.contains('Rows: 347');
|
||||
});
|
||||
|
||||
it('Data grid screenshots', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.window().then(win => {
|
||||
win.__changeCurrentTheme('theme-dark');
|
||||
});
|
||||
|
||||
cy.contains('MyChinook').click();
|
||||
|
||||
@@ -95,16 +116,25 @@ describe('Data browser data', () => {
|
||||
cy.contains('PgChinook').click();
|
||||
cy.contains('customer').click();
|
||||
cy.contains('Leonie').click();
|
||||
cy.themeshot('datagrid');
|
||||
cy.themeshot('common-data-browser');
|
||||
|
||||
cy.contains('invoice').click();
|
||||
cy.contains('invoice_line (invoice_id)').click();
|
||||
cy.themeshot('masterdetail');
|
||||
cy.themeshot('data-browser-master-detail');
|
||||
|
||||
cy.contains('9, Place Louis Barthou').click();
|
||||
cy.contains('Switch to form').click();
|
||||
cy.contains('Switch to table'); // test that we are in form view
|
||||
cy.themeshot('formview');
|
||||
cy.themeshot('data-browser-form-view');
|
||||
});
|
||||
|
||||
it('Column search', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Customer').click();
|
||||
cy.testid('ColumnManager_searchColumns').clear().type('name,id{enter}');
|
||||
cy.contains('Company').should('not.exist');
|
||||
cy.themeshot('data-browser-column-search');
|
||||
});
|
||||
|
||||
it('SQL Gen', () => {
|
||||
@@ -112,7 +142,7 @@ describe('Data browser data', () => {
|
||||
cy.contains('PgChinook').rightclick();
|
||||
cy.contains('SQL Generator').click();
|
||||
cy.contains('Check all').click();
|
||||
cy.themeshot('sqlgen');
|
||||
cy.themeshot('sql-generator');
|
||||
});
|
||||
|
||||
it('Macros in DB', () => {
|
||||
@@ -127,7 +157,7 @@ describe('Data browser data', () => {
|
||||
cy.testid('DataGrid_itemMacros').click();
|
||||
cy.contains('Change text case').click();
|
||||
cy.contains('NIELSEN');
|
||||
cy.themeshot('macros');
|
||||
cy.themeshot('data-browser-macros');
|
||||
});
|
||||
|
||||
it('Perspectives', () => {
|
||||
@@ -143,7 +173,7 @@ describe('Data browser data', () => {
|
||||
// check track is loaded
|
||||
cy.contains('Put The Finger On You');
|
||||
|
||||
cy.themeshot('perspective1');
|
||||
cy.themeshot('perspective-designer');
|
||||
});
|
||||
|
||||
it('Query editor - code completion', () => {
|
||||
@@ -152,27 +182,29 @@ describe('Data browser data', () => {
|
||||
cy.contains('Customer').rightclick();
|
||||
cy.contains('SQL template').click();
|
||||
cy.contains('CREATE TABLE').click();
|
||||
cy.wait(1000);
|
||||
cy.get('body').realPress('PageDown');
|
||||
cy.get('body').realType('select * from Album where Album.');
|
||||
// code completion
|
||||
cy.contains('ArtistId');
|
||||
cy.themeshot('query');
|
||||
cy.themeshot('query-editor-code-completion');
|
||||
});
|
||||
|
||||
it('Query editor - join wizard', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('TabsPanel_buttonNewQuery').click();
|
||||
cy.testid('TabsPanel_buttonNewObject').click();
|
||||
cy.testid('NewObjectModal_query').click();
|
||||
cy.wait(1000);
|
||||
cy.get('body').realType('select * from Invoice');
|
||||
cy.get('body').realPress('{enter}');
|
||||
cy.get('body').realPress(['Control', 'j']);
|
||||
// JOIN wizard
|
||||
cy.contains('INNER JOIN Customer ON Invoice.CustomerId = Customer.CustomerId');
|
||||
cy.themeshot('joinwizard');
|
||||
cy.themeshot('query-editor-join-wizard');
|
||||
});
|
||||
|
||||
it('Mongo JSON data view', () => {
|
||||
it('Mongo query JSON data view', () => {
|
||||
cy.contains('Mongo-connection').click();
|
||||
cy.contains('MgChinook').click();
|
||||
cy.contains('Customer').click();
|
||||
@@ -183,10 +215,11 @@ describe('Data browser data', () => {
|
||||
cy.contains('Open query').click();
|
||||
cy.wait(1000);
|
||||
cy.contains('Execute').click();
|
||||
cy.testid('WidgetIconPanel_cell-data').click();
|
||||
cy.testid('TabContent_1').contains('Leonie').rightclick();
|
||||
cy.contains('Show cell data').click();
|
||||
// test JSON view
|
||||
cy.contains('Country: "Brazil"');
|
||||
cy.themeshot('mongoquery');
|
||||
cy.contains('Country: "Germany"');
|
||||
cy.themeshot('mongo-query-json-view');
|
||||
});
|
||||
|
||||
it('SQL preview', () => {
|
||||
@@ -196,7 +229,7 @@ describe('Data browser data', () => {
|
||||
cy.contains('Show SQL').click();
|
||||
// index should be part of create script
|
||||
cy.contains('CREATE INDEX `IFK_CustomerSupportRepId`');
|
||||
cy.themeshot('sqlpreview');
|
||||
cy.themeshot('sql-preview-create-index');
|
||||
});
|
||||
|
||||
it('Query designer', () => {
|
||||
@@ -205,7 +238,7 @@ describe('Data browser data', () => {
|
||||
cy.testid('WidgetIconPanel_file').click();
|
||||
cy.contains('customer').click();
|
||||
// cy.contains('left join').rightclick();
|
||||
cy.themeshot('querydesigner');
|
||||
cy.themeshot('query-designer');
|
||||
});
|
||||
|
||||
it('Database diagram', () => {
|
||||
@@ -216,24 +249,24 @@ describe('Data browser data', () => {
|
||||
cy.testid('WidgetIconPanel_file').click();
|
||||
// check diagram is shown
|
||||
cy.contains('MediaTypeId');
|
||||
cy.themeshot('diagram');
|
||||
cy.themeshot('database-diagram');
|
||||
});
|
||||
|
||||
it('Charts', () => {
|
||||
cy.testid('WidgetIconPanel_file').click();
|
||||
cy.contains('pie-chart').click();
|
||||
cy.contains('line-chart').click();
|
||||
cy.testid('TabsPanel_buttonSplit').click();
|
||||
cy.testid('WidgetIconPanel_file').click();
|
||||
cy.themeshot('charts');
|
||||
});
|
||||
// it('Charts', () => {
|
||||
// cy.testid('WidgetIconPanel_file').click();
|
||||
// cy.contains('pie-chart').click();
|
||||
// cy.contains('line-chart').click();
|
||||
// cy.testid('TabsPanel_buttonSplit').click();
|
||||
// cy.testid('WidgetIconPanel_file').click();
|
||||
// cy.themeshot('view-split-charts');
|
||||
// });
|
||||
|
||||
it('Keyboard configuration', () => {
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
cy.contains('Keyboard shortcuts').click();
|
||||
cy.contains('dataForm.refresh').click();
|
||||
cy.testid('CommandModal_keyboardButton').click();
|
||||
cy.themeshot('keyboard');
|
||||
cy.themeshot('keyboard-configuration');
|
||||
});
|
||||
|
||||
it('Command palette', () => {
|
||||
@@ -244,7 +277,15 @@ describe('Data browser data', () => {
|
||||
// cy.realPress('F1');
|
||||
cy.realPress('PageDown');
|
||||
cy.realPress('PageDown');
|
||||
cy.testid('CommandPalette_main').themeshot('commandpalette', { padding: 50 });
|
||||
cy.testid('CommandPalette_main').themeshot('command-palette', { padding: 50 });
|
||||
});
|
||||
|
||||
it('About window', () => {
|
||||
cy.contains('Connections');
|
||||
cy.testid('WidgetIconPanel_menu').click();
|
||||
cy.contains('Help').click();
|
||||
cy.contains('About').click();
|
||||
cy.testid('ModalBase_window').themeshot('about-window', { padding: 50 });
|
||||
});
|
||||
|
||||
it('Show map', () => {
|
||||
@@ -255,9 +296,10 @@ describe('Data browser data', () => {
|
||||
// cy.contains('location').click();
|
||||
cy.contains('14.2').click();
|
||||
cy.contains('13.9').click({ shiftKey: true });
|
||||
cy.testid('WidgetIconPanel_cell-data').click();
|
||||
cy.testid('WidgetIconPanel_database').click();
|
||||
cy.testid('TableDataTab_toggleCellDataView').click();
|
||||
cy.wait(2000);
|
||||
cy.themeshot('map');
|
||||
cy.themeshot('cell-map-view');
|
||||
});
|
||||
|
||||
it('Search in connections', () => {
|
||||
@@ -269,17 +311,7 @@ describe('Data browser data', () => {
|
||||
cy.contains('Album').click();
|
||||
cy.testid('SqlObjectList_searchMenuDropDown').click();
|
||||
cy.contains('Column name').click();
|
||||
cy.themeshot('connsearch');
|
||||
});
|
||||
|
||||
it('Plugin tab', () => {
|
||||
cy.testid('WidgetIconPanel_plugins').click();
|
||||
cy.contains('dbgate-plugin-theme-total-white').click();
|
||||
// text from plugin markdown
|
||||
cy.contains('Total white theme');
|
||||
// wait for load logos
|
||||
cy.wait(2000);
|
||||
cy.themeshot('plugin');
|
||||
cy.themeshot('search-in-connections');
|
||||
});
|
||||
|
||||
it('Edit mongo data JSON', () => {
|
||||
@@ -306,10 +338,10 @@ describe('Data browser data', () => {
|
||||
cy.contains('Helena').rightclick();
|
||||
cy.contains('Delete document').click();
|
||||
cy.contains('Save').click();
|
||||
cy.themeshot('mongosave');
|
||||
cy.themeshot('save-changes-mongodb');
|
||||
});
|
||||
|
||||
it('Edit mongo data JSON', () => {
|
||||
it('Mongo JSON cell view', () => {
|
||||
// TODO FIX: Auto expand cell view
|
||||
cy.contains('Mongo-connection').click();
|
||||
cy.contains('MgRivers').click();
|
||||
@@ -319,8 +351,9 @@ describe('Data browser data', () => {
|
||||
cy.testid('ColumnManagerRow_checkbox_countries.1').click();
|
||||
cy.testid('ColumnManagerRow_checkbox__id').click();
|
||||
cy.testid('DataFilterControl_input_countries.1').type('EXISTS{enter}');
|
||||
cy.testid('WidgetIconPanel_cell-data').click();
|
||||
cy.themeshot('collection');
|
||||
cy.contains('Austria').click();
|
||||
cy.testid('CollectionDataTab_toggleCellDataView').click();
|
||||
cy.themeshot('mongodb-json-cell-view');
|
||||
});
|
||||
|
||||
it('Table structure editor', () => {
|
||||
@@ -329,10 +362,10 @@ describe('Data browser data', () => {
|
||||
cy.contains('Customer').rightclick();
|
||||
cy.contains('Open structure').click();
|
||||
cy.contains('varchar(40)');
|
||||
cy.themeshot('structure');
|
||||
cy.themeshot('table-structure-editor');
|
||||
cy.contains('EmployeeId').click();
|
||||
cy.contains('Ref column - Employee');
|
||||
cy.themeshot('fkeditor');
|
||||
cy.themeshot('foreign-key-editor');
|
||||
});
|
||||
|
||||
it('Compare database', () => {
|
||||
@@ -344,25 +377,10 @@ describe('Data browser data', () => {
|
||||
cy.testid('CompareModelTab_gridObjects_Customer_Customer').click();
|
||||
cy.testid('WidgetIconPanel_database').click();
|
||||
cy.testid('CompareModelTab_tabDdl').click();
|
||||
cy.themeshot('dbcompare');
|
||||
cy.themeshot('compare-database-models');
|
||||
cy.contains('Settings').click();
|
||||
cy.testid('CompareModelTab_tabOperations').click();
|
||||
cy.themeshot('comparesettings');
|
||||
});
|
||||
|
||||
it.skip('Query editor - AI assistant', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('TabsPanel_buttonNewQuery').click();
|
||||
cy.testid('QueryTab_switchAiAssistantButton').click();
|
||||
cy.testid('QueryAiAssistant_allowSendToAiServiceButton').click();
|
||||
cy.testid('ConfirmModal_okButton').click();
|
||||
cy.testid('QueryAiAssistant_promptInput').type('album names');
|
||||
cy.testid('QueryAiAssistant_queryFromQuestionButton').click();
|
||||
cy.contains('Use this').click();
|
||||
cy.testid('QueryTab_executeButton').click();
|
||||
cy.contains('Balls to the Wall');
|
||||
cy.themeshot('aiassistant');
|
||||
cy.themeshot('compare-database-settings');
|
||||
});
|
||||
|
||||
it('Modify data', () => {
|
||||
@@ -388,7 +406,7 @@ describe('Data browser data', () => {
|
||||
cy.contains('INSERT INTO `Employee`');
|
||||
cy.contains("SET `FirstName`='Jane'");
|
||||
cy.contains('DELETE FROM `Employee`');
|
||||
cy.themeshot('modifydata');
|
||||
cy.themeshot('data-browser-save-changes');
|
||||
|
||||
// cy.testid('ConfirmSqlModal_okButton').click();
|
||||
// cy.contains('Cannot delete or update a parent row')
|
||||
@@ -403,4 +421,95 @@ describe('Data browser data', () => {
|
||||
cy.contains('Novak');
|
||||
cy.contains('Rows: 8');
|
||||
});
|
||||
|
||||
it('Export menu', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Album').click();
|
||||
cy.testid('DataFilterControl_input_ArtistId').type('22{enter}');
|
||||
// cy.contains('Presence').rightclick();
|
||||
// cy.contains('Coda').rightclick();
|
||||
// cy.testid('DropDownMenu-container-0').contains('Export').click();
|
||||
cy.contains('Export').click();
|
||||
// cy.wait(1000);
|
||||
cy.themeshot('data-browser-export-menu');
|
||||
});
|
||||
|
||||
it('MySQL native backup', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').rightclick();
|
||||
cy.contains('Create database backup').click();
|
||||
cy.contains('Customer');
|
||||
cy.themeshot('mysql-backup-configuration');
|
||||
});
|
||||
|
||||
it('View table YAML model', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').rightclick();
|
||||
cy.contains('Export DB model').click();
|
||||
cy.testid('ExportDbModelModal_archiveFolder').select('(Create new)');
|
||||
cy.testid('InputTextModal_value').clear().type('test-model');
|
||||
cy.testid('InputTextModal_ok').click();
|
||||
cy.testid('ModalBase_window').themeshot('export-database-model-window', { padding: 50 });
|
||||
cy.testid('ExportDbModelModal_exportButton').click();
|
||||
cy.contains('Album').click();
|
||||
cy.contains('autoIncrement');
|
||||
cy.themeshot('database-model-table-yaml');
|
||||
});
|
||||
|
||||
it('Data replicator', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('WidgetIconPanel_archive').click();
|
||||
cy.contains('chinook-archive').rightclick();
|
||||
cy.contains('Data deployer').click();
|
||||
cy.contains('Dry run').click();
|
||||
cy.testid('TableControl_row_2_checkbox').click();
|
||||
cy.testid('TableControl_row_2').click();
|
||||
cy.testid('DataDeploySettings_find_checkbox').click();
|
||||
cy.testid('DataDeploySettings_create_checkbox').click();
|
||||
cy.testid('WidgetIconPanel_archive').click();
|
||||
cy.themeshot('data-deployer');
|
||||
cy.testid('DataDeployTab_importIntoDb').click();
|
||||
cy.testid('ConfirmDataDeployModal_okButton').click();
|
||||
cy.contains('Replicated Customer, inserted 59 rows');
|
||||
cy.contains('Finished job script');
|
||||
cy.testid('DataDeployTab_importIntoDb').click();
|
||||
cy.themeshot('data-replicator');
|
||||
});
|
||||
|
||||
it('Form cell view', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Invoice').click();
|
||||
cy.contains('Rows: 412');
|
||||
cy.get('[data-row="0"][data-col="header"]').click();
|
||||
cy.get('[data-row="1"][data-col="header"]').click();
|
||||
cy.get('[data-row="0"][data-col="header"]').click();
|
||||
cy.contains('Autodetect - Form');
|
||||
cy.themeshot('form-cell-view');
|
||||
});
|
||||
|
||||
it('Group by', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Album').click();
|
||||
cy.testid('WidgetIconPanel_database').click();
|
||||
cy.testid('ColumnHeaderControl_dropdown_ArtistId').click();
|
||||
cy.contains('Group by').click();
|
||||
cy.testid('ColumnHeaderControl_dropdown_Title').first().click();
|
||||
cy.themeshot('data-browser-group-by');
|
||||
});
|
||||
|
||||
it('Filter by expanded column', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Album').click();
|
||||
cy.testid('WidgetIconPanel_database').click();
|
||||
cy.testid('ColumnManagerRow_expand_ArtistId').click();
|
||||
cy.testid('ColumnManagerRow_checkbox_ArtistId.Name').click();
|
||||
cy.testid('ColumnManagerRow_checkbox_ArtistId').click();
|
||||
cy.testid('DataFilterControl_input_ArtistId.Name').type('mich{enter}');
|
||||
cy.themeshot('data-browser-filter-by-expanded');
|
||||
});
|
||||
});
|
||||
|
||||
285
e2e-tests/cypress/e2e/charts.cy.js
Normal file
285
e2e-tests/cypress/e2e/charts.cy.js
Normal file
@@ -0,0 +1,285 @@
|
||||
Cypress.on('uncaught:exception', (err, runnable) => {
|
||||
// if the error message matches the one about WorkerGlobalScope importScripts
|
||||
if (err.message.includes("Failed to execute 'importScripts' on 'WorkerGlobalScope'")) {
|
||||
// return false to let Cypress know we intentionally want to ignore this error
|
||||
return false;
|
||||
}
|
||||
// otherwise let Cypress throw the error
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.viewport(1250, 900);
|
||||
});
|
||||
|
||||
describe('Charts', () => {
|
||||
it('Auto detect chart', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('charts_sample').click();
|
||||
cy.testid('WidgetIconPanel_file').click();
|
||||
cy.contains('chart1').click();
|
||||
cy.contains('department_name');
|
||||
// cy.testid('QueryTab_executeButton').click();
|
||||
// cy.testid('QueryTab_openChartButton').click();
|
||||
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
|
||||
cy.themeshot('choose-detected-chart');
|
||||
});
|
||||
|
||||
it('Two line charts', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('TabsPanel_buttonNewObject').click();
|
||||
cy.testid('NewObjectModal_query').click();
|
||||
cy.wait(1000);
|
||||
cy.get('body').realType('SELECT InvoiceDate, Total from Invoice');
|
||||
cy.contains('Execute').click();
|
||||
cy.contains('Open chart').click();
|
||||
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
|
||||
cy.themeshot('two-line-charts');
|
||||
});
|
||||
|
||||
it('Invoice naive autodetection', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('TabsPanel_buttonNewObject').click();
|
||||
cy.testid('NewObjectModal_query').click();
|
||||
cy.wait(1000);
|
||||
cy.get('body').realType('SELECT * from Invoice');
|
||||
cy.contains('Execute').click();
|
||||
cy.contains('Open chart').click();
|
||||
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
|
||||
cy.themeshot('chart-naive-autodetection');
|
||||
});
|
||||
|
||||
it('Invoice by country - grouped chart', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('TabsPanel_buttonNewObject').click();
|
||||
cy.testid('NewObjectModal_query').click();
|
||||
cy.wait(1000);
|
||||
cy.get('body').realType(
|
||||
"SELECT InvoiceDate, Total, BillingCountry from Invoice where BillingCountry in ('USA', 'Canada', 'Brazil', 'France', 'Germany')"
|
||||
);
|
||||
cy.contains('Execute').click();
|
||||
cy.contains('Open chart').click();
|
||||
cy.testid('ChartSelector_chart_1').click();
|
||||
cy.testid('JslChart_customizeButton').click();
|
||||
|
||||
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
|
||||
cy.themeshot('chart-grouped-autodetected');
|
||||
|
||||
cy.testid('ChartDefinitionEditor_chartTypeSelect').select('Bar');
|
||||
cy.testid('ChartDefinitionEditor_xAxisTransformSelect').select('Date (Year)');
|
||||
|
||||
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
|
||||
cy.themeshot('chart-grouped-bars');
|
||||
});
|
||||
|
||||
it('Public Knowledge base - show chart', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('WidgetIconPanel_cloud-public').click();
|
||||
cy.testid('public-cloud-file-tag-mysql/folder-MySQL/tag-premium/top-tables-row-count.sql').click();
|
||||
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
|
||||
cy.themeshot('public-knowledge-base-tables-sizes');
|
||||
});
|
||||
|
||||
it('Auto detect chart', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Invoice').rightclick();
|
||||
cy.contains('SQL template').click();
|
||||
cy.contains('SELECT').click();
|
||||
cy.testid('QueryTab_detectChartButton').click();
|
||||
cy.testid('QueryTab_executeButton').click();
|
||||
cy.contains('Chart 1').click();
|
||||
cy.testid('ChartSelector_chart_0').click();
|
||||
cy.testid('JslChart_customizeButton').click();
|
||||
cy.testid('ChartDefinitionEditor_chartTypeSelect').select('Bar');
|
||||
cy.testid('ChartDefinitionEditor_chartTypeSelect').select('Line');
|
||||
cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/));
|
||||
cy.themeshot('query-result-chart');
|
||||
});
|
||||
|
||||
it('New object window', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Invoice').click();
|
||||
cy.testid('WidgetIconPanel_addButton').click();
|
||||
cy.contains('Compare database');
|
||||
cy.themeshot('new-object-window');
|
||||
});
|
||||
|
||||
it.skip('Database chat - charts', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('TabsPanel_buttonNewObject').click();
|
||||
cy.testid('NewObjectModal_databaseChat').click();
|
||||
cy.wait(1000);
|
||||
cy.get('body').realType('show me chart of most popular genres');
|
||||
cy.get('body').realPress('{enter}');
|
||||
cy.testid('DatabaseChatTab_executeAllQueries', { timeout: 30000 }).click();
|
||||
cy.testid('chart-canvas', { timeout: 30000 }).should($c =>
|
||||
expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/)
|
||||
);
|
||||
cy.themeshot('database-chat-chart');
|
||||
});
|
||||
|
||||
it.skip('Database chat', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('TabsPanel_buttonNewObject').click();
|
||||
cy.testid('NewObjectModal_databaseChat').click();
|
||||
cy.wait(1000);
|
||||
cy.get('body').realType('find most popular artist');
|
||||
cy.get('body').realPress('{enter}');
|
||||
cy.testid('DatabaseChatTab_executeAllQueries', { timeout: 30000 }).click();
|
||||
cy.wait(30000);
|
||||
// cy.contains('Iron Maiden');
|
||||
cy.themeshot('database-chat');
|
||||
|
||||
// cy.testid('DatabaseChatTab_promptInput').click();
|
||||
// cy.get('body').realType('I need top 10 songs with the biggest income');
|
||||
// cy.get('body').realPress('{enter}');
|
||||
// cy.contains('Hot Girl', { timeout: 20000 });
|
||||
// cy.wait(1000);
|
||||
// cy.themeshot('database-chat');
|
||||
});
|
||||
|
||||
it.skip('Explain query error', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('TabsPanel_buttonNewObject').click();
|
||||
cy.testid('NewObjectModal_query').click();
|
||||
cy.wait(1000);
|
||||
cy.get('body').realType('select * from Invoice2');
|
||||
cy.contains('Execute').click();
|
||||
cy.testid('MessageViewRow-explainErrorButton-1').click();
|
||||
cy.testid('ChatCodeRenderer_useSqlButton', { timeout: 30000 });
|
||||
cy.themeshot('explain-query-error');
|
||||
});
|
||||
|
||||
it('Switch language', () => {
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
|
||||
cy.testid('SettingsModal_languageSelect').select('Deutsch');
|
||||
cy.testid('ConfirmModal_okButton').click();
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
cy.contains('Sprache');
|
||||
cy.themeshot('switch-language-de');
|
||||
|
||||
cy.testid('SettingsModal_languageSelect').select('Français');
|
||||
cy.testid('ConfirmModal_okButton').click();
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
cy.contains('Langue');
|
||||
cy.themeshot('switch-language-fr');
|
||||
|
||||
cy.testid('SettingsModal_languageSelect').select('Español');
|
||||
cy.testid('ConfirmModal_okButton').click();
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
cy.contains('Idioma');
|
||||
cy.themeshot('switch-language-es');
|
||||
|
||||
cy.testid('SettingsModal_languageSelect').select('Čeština');
|
||||
cy.testid('ConfirmModal_okButton').click();
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
cy.contains('Jazyk');
|
||||
cy.themeshot('switch-language-cs');
|
||||
|
||||
cy.testid('SettingsModal_languageSelect').select('中文');
|
||||
cy.testid('ConfirmModal_okButton').click();
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
cy.contains('语言');
|
||||
cy.themeshot('switch-language-zh');
|
||||
|
||||
cy.testid('SettingsModal_languageSelect').select('English');
|
||||
cy.testid('ConfirmModal_okButton').click();
|
||||
cy.testid('WidgetIconPanel_settings');
|
||||
});
|
||||
|
||||
it('Settings', () => {
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
cy.themeshot('app-settings-general');
|
||||
|
||||
cy.contains('Behaviour').click();
|
||||
cy.themeshot('app-settings-behaviour');
|
||||
cy.get('[data-testid=BehaviourSettings_useTabPreviewMode]').uncheck();
|
||||
|
||||
// SQL Editor
|
||||
cy.contains('SQL Editor').click();
|
||||
cy.get('[data-testid=SQLEditorSettings_sqlCommandsCase]').select('lowerCase');
|
||||
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('charts_sample').click();
|
||||
cy.contains('employees').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Customer').rightclick();
|
||||
cy.contains('SQL template').click();
|
||||
cy.contains('CREATE TABLE').click();
|
||||
cy.contains('create table');
|
||||
|
||||
// Default Actions
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
cy.contains('Default Actions').click();
|
||||
cy.get('[data-testid=DefaultActionsSettings_useLastUsedAction]').uncheck();
|
||||
|
||||
// Themes
|
||||
cy.contains('Themes').click();
|
||||
cy.themeshot('app-settings-themes');
|
||||
cy.testid('ThemeSkeleton-Dark-built-in').click();
|
||||
cy.testid('ThemeSkeleton-Light-built-in').click();
|
||||
|
||||
// General
|
||||
cy.contains(/^General$/).click();
|
||||
cy.contains('charts_sample');
|
||||
cy.get('[data-testid=GeneralSettings_lockedDatabaseMode]').check();
|
||||
cy.contains('Connections').click();
|
||||
cy.contains('charts_sample').should('not.exist');
|
||||
|
||||
// Datagrid
|
||||
cy.contains('Data grid').click();
|
||||
cy.get('[data-testid=DataGridSettings_showHintColumns]').uncheck();
|
||||
cy.wait(500);
|
||||
cy.contains('Album').click();
|
||||
cy.contains('AC/DC').should('not.exist');
|
||||
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
cy.contains('Keyboard shortcuts').click();
|
||||
cy.themeshot('app-settings-keyboard-shortcuts');
|
||||
cy.contains('Chart').click();
|
||||
cy.testid('CommandModal_keyboardButton').click();
|
||||
cy.realPress(['Control', 'g']);
|
||||
cy.realPress('Enter');
|
||||
cy.contains('OK').click();
|
||||
cy.contains('Ctrl+G');
|
||||
|
||||
cy.contains('AI').click();
|
||||
cy.themeshot('app-settings-ai');
|
||||
cy.get('[data-testid=AISettings_addProviderButton]').click();
|
||||
cy.contains('Provider 1');
|
||||
cy.get('[data-testid=AiProviderCard_removeButton]').click();
|
||||
cy.contains('Are you sure you want to remove Provider 1 provider?');
|
||||
cy.contains('OK').click();
|
||||
cy.contains('Provider 1').should('not.exist');
|
||||
});
|
||||
|
||||
it('Custom theme', () => {
|
||||
cy.testid('WidgetIconPanel_settings').click();
|
||||
cy.contains('Themes').click();
|
||||
cy.testid('ThemeSettings-themeList').contains('Green-Sample').click();
|
||||
cy.testid('WidgetIconPanel_file').click();
|
||||
cy.themeshot('green-theme', { keepTheme: true });
|
||||
|
||||
cy.testid('ThemeSettings-themeList').contains('Solarized-light').click();
|
||||
cy.testid('WidgetIconPanel_database').click();
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.contains('MyChinook').click();
|
||||
cy.contains('Customer').click();
|
||||
cy.contains('Leonie');
|
||||
cy.testid('WidgetIconPanel_file').click();
|
||||
|
||||
cy.themeshot('solarized-theme', { keepTheme: true });
|
||||
});
|
||||
});
|
||||
56
e2e-tests/cypress/e2e/cloud.cy.js
Normal file
56
e2e-tests/cypress/e2e/cloud.cy.js
Normal file
@@ -0,0 +1,56 @@
|
||||
Cypress.on('uncaught:exception', (err, runnable) => {
|
||||
// if the error message matches the one about WorkerGlobalScope importScripts
|
||||
if (err.message.includes("Failed to execute 'importScripts' on 'WorkerGlobalScope'")) {
|
||||
// return false to let Cypress know we intentionally want to ignore this error
|
||||
return false;
|
||||
}
|
||||
// otherwise let Cypress throw the error
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.viewport(1250, 900);
|
||||
});
|
||||
|
||||
describe('Cloud tests', () => {
|
||||
it('Private cloud', () => {
|
||||
cy.testid('WidgetIconPanel_cloudAccount');
|
||||
cy.window().then(win => {
|
||||
win.__loginToCloudTest('dbgate.test@gmail.com');
|
||||
});
|
||||
cy.contains('dbgate.test@gmail.com');
|
||||
|
||||
// cy.testid('WidgetIconPanel_cloudAccount').click();
|
||||
|
||||
// cy.origin('https://identity.dbgate.io', () => {
|
||||
// cy.contains('Sign in with GitHub').click();
|
||||
// });
|
||||
|
||||
// cy.origin('https://github.com', () => {
|
||||
// cy.get('#login_field').type('dbgatetest');
|
||||
// cy.get('#password').type('Pwd2020Db');
|
||||
// cy.get('input[type="submit"]').click();
|
||||
// });
|
||||
|
||||
// cy.wait(3000);
|
||||
|
||||
// cy.location('origin').then(origin => {
|
||||
// if (origin === 'https://github.com') {
|
||||
// // Still on github.com → an authorization step is waiting
|
||||
// cy.origin('https://github.com', () => {
|
||||
// // Try once, don't wait the full default timeout
|
||||
// cy.get('button[data-octo-click="oauth_application_authorization"]', { timeout: 500, log: false }).click(); // if the button exists it will be clicked
|
||||
// // if not, the short timeout elapses and we drop out
|
||||
// });
|
||||
// } else {
|
||||
// // Already back on localhost – nothing to authorize
|
||||
// cy.log('OAuth redirect skipped the Authorize screen');
|
||||
// }
|
||||
// });
|
||||
|
||||
cy.contains('Testing Connections').rightclick();
|
||||
cy.contains('Administrate access').click();
|
||||
cy.contains('User email');
|
||||
cy.themeshot('administer-shared-folder');
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,8 @@ const { formatQueryWithoutParams } = require('dbgate-tools');
|
||||
|
||||
global.DBGATE_PACKAGES = {
|
||||
'dbgate-tools': require('dbgate-tools'),
|
||||
'dbgate-sqltree': require('dbgate-sqltree'),
|
||||
'dbgate-datalib': require('dbgate-datalib'),
|
||||
};
|
||||
|
||||
function requireEngineDriver(engine) {
|
||||
@@ -59,7 +61,8 @@ describe('Transactions', () => {
|
||||
|
||||
cy.contains(connectionName).click();
|
||||
if (databaseName) cy.contains(databaseName).click();
|
||||
cy.testid('TabsPanel_buttonNewQuery').click();
|
||||
cy.testid('TabsPanel_buttonNewObject').click();
|
||||
cy.testid('NewObjectModal_query').click();
|
||||
cy.wait(1000);
|
||||
cy.get('body').type(
|
||||
formatQueryWithoutParams(driver, "INSERT INTO ~categories (~category_id, ~category_name) VALUES (5, 'test');")
|
||||
@@ -102,13 +105,70 @@ describe('Transactions', () => {
|
||||
|
||||
describe('Backup table', () => {
|
||||
multiTest({ skipMongo: true }, (connectionName, databaseName, engine, options = {}) => {
|
||||
const implicitTransactions = options.implicitTransactions ?? false;
|
||||
|
||||
cy.contains(connectionName).click();
|
||||
if (databaseName) cy.contains(databaseName).click();
|
||||
cy.contains('customers').rightclick();
|
||||
cy.contains('addresses').rightclick();
|
||||
cy.contains('Create table backup').click();
|
||||
cy.testid('ConfirmSqlModal_okButton').click();
|
||||
cy.contains('_customers').click();
|
||||
cy.contains('Rows: 8').should('be.visible');
|
||||
cy.testid('app-object-group-items-table-backups').contains('addresses').click();
|
||||
cy.contains('Rows: 12').should('be.visible');
|
||||
cy.testid('app-object-group-items-tables').contains('addresses').click();
|
||||
|
||||
cy.contains('Ridgewood').click();
|
||||
cy.testid('TableDataTab_deleteSelectedRows').click();
|
||||
cy.contains('Rosewood').click();
|
||||
cy.testid('TableDataTab_deleteSelectedRows').click();
|
||||
|
||||
cy.contains('Vermont').click();
|
||||
cy.get('body').realType('Wermont{enter}');
|
||||
|
||||
cy.testid('TableDataTab_insertNewRow').click();
|
||||
cy.get('body').realType('Modranska{enter}');
|
||||
cy.realPress(['ArrowLeft']);
|
||||
cy.realPress(['ArrowLeft']);
|
||||
cy.get('body').realType('13{enter}');
|
||||
cy.realPress(['ArrowRight']);
|
||||
cy.get('body').realType('1{enter}');
|
||||
cy.realPress(['ArrowRight']);
|
||||
cy.realPress(['ArrowRight']);
|
||||
cy.realPress(['ArrowRight']);
|
||||
cy.get('body').realType('Prague{enter}');
|
||||
cy.realPress(['ArrowRight']);
|
||||
cy.get('body').realType('CZ{enter}');
|
||||
cy.realPress(['ArrowRight']);
|
||||
cy.get('body').realType('10000{enter}');
|
||||
cy.realPress(['ArrowRight']);
|
||||
cy.get('body').realType('111222333{enter}');
|
||||
|
||||
cy.testid('TableDataTab_save').click();
|
||||
cy.testid('ConfirmSqlModal_okButton', { timeout: 10000 }).click();
|
||||
cy.contains('Rows: 11').should('be.visible'); // wait for save
|
||||
|
||||
cy.testid('app-object-group-items-table-backups').contains('addresses').rightclick();
|
||||
cy.contains('restore script').click();
|
||||
cy.contains('UPDATE'); // wait for query
|
||||
cy.testid('QueryTab_executeButton').click();
|
||||
cy.contains('Query execution finished');
|
||||
|
||||
if (implicitTransactions) {
|
||||
cy.testid('QueryTab_commitTransactionButton').click();
|
||||
cy.contains('Commit Transaction finished');
|
||||
}
|
||||
|
||||
cy.realPress('F1');
|
||||
cy.realType('Close all');
|
||||
cy.realPress('Enter');
|
||||
// cy.testid('CloseTabModal_buttonConfirm').click();
|
||||
cy.wait(1000);
|
||||
|
||||
cy.testid('app-object-group-items-tables').contains('addresses', { timeout: 10000 }).click();
|
||||
|
||||
// check whether data was successfully restored
|
||||
cy.contains('Rows: 12').should('be.visible');
|
||||
cy.contains('Ridgewood');
|
||||
cy.contains('Vermont');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -145,13 +205,15 @@ describe('Import CSV', () => {
|
||||
cy.contains('Import').click();
|
||||
|
||||
cy.get('input[type=file]').selectFile('cypress/fixtures/customers-20.csv', { force: true });
|
||||
cy.contains('customers-20');
|
||||
cy.testid('ImportExportConfigurator_tableMappingSection').contains('customers-20');
|
||||
cy.testid('ImportExportTab_preview_content').contains('50ddd99fAdF48B3').should('be.visible');
|
||||
|
||||
cy.testid('ImportExportTab_executeButton').click();
|
||||
cy.contains('20 rows written').should('be.visible');
|
||||
cy.testid('ImportExportConfigurator_tableMappingSection').contains('20 rows written').should('be.visible');
|
||||
|
||||
cy.testid('SqlObjectList_refreshButton').click();
|
||||
cy.testid('DatabasStatusMenu_refreshFull').click();
|
||||
// cy.contains('Refresh DB structure (incremental)').click();
|
||||
cy.testid('SqlObjectList_container').contains('customers-20').click();
|
||||
cy.contains('Rows: 20').should('be.visible');
|
||||
|
||||
@@ -177,7 +239,7 @@ describe('Import CSV - source error', () => {
|
||||
cy.testid('ImportExportTab_preview_content').contains('Invalid Closing Quote').should('be.visible');
|
||||
|
||||
cy.testid('ImportExportTab_executeButton').click();
|
||||
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20-err').click();
|
||||
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20-err', { timeout: 10000 }).click();
|
||||
|
||||
cy.testid('ErrorMessageModal_message').contains('Invalid Closing Quote').should('be.visible');
|
||||
});
|
||||
@@ -196,7 +258,7 @@ describe('Import CSV - target error', () => {
|
||||
cy.contains('customers-20');
|
||||
cy.testid('ImportExportConfigurator_targetName_customers-20').clear().type('system."]`');
|
||||
cy.testid('ImportExportTab_executeButton').click();
|
||||
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20').click();
|
||||
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20', { timeout: 10000 }).click();
|
||||
cy.testid('ErrorMessageModal_message').should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -45,36 +45,36 @@ describe('Run as portal', () => {
|
||||
cy.get('[data-testid=InputTextModal_ok]').click();
|
||||
});
|
||||
|
||||
it('Import Chinook MySQL', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.contains('MySql-connection').click();
|
||||
cy.get('[data-testid=DatabaseAppObject_Chinook]').rightclick();
|
||||
cy.contains('Chinook').rightclick();
|
||||
cy.contains('Restore/import SQL dump').click();
|
||||
cy.get('#uploadFileButton').selectFile('data/chinook-mysql.sql', { force: true });
|
||||
cy.wait(500);
|
||||
cy.get('[data-testid=ImportDatabaseDumpModal_runImport]').click();
|
||||
cy.contains('Importing database');
|
||||
cy.contains('Finished job script');
|
||||
cy.get('[data-testid=RunScriptModal_close]').click();
|
||||
cy.contains('Chinook').click();
|
||||
cy.contains('Album');
|
||||
});
|
||||
// it('Import Chinook MySQL', () => {
|
||||
// cy.visit('http://localhost:3000');
|
||||
// cy.contains('MySql-connection').click();
|
||||
// cy.get('[data-testid=DatabaseAppObject_Chinook]').rightclick();
|
||||
// cy.contains('Chinook').rightclick();
|
||||
// cy.contains('Restore/import SQL dump').click();
|
||||
// cy.get('#uploadFileButton').selectFile('data/chinook-mysql.sql', { force: true });
|
||||
// cy.wait(500);
|
||||
// cy.get('[data-testid=ImportDatabaseDumpModal_runImport]').click();
|
||||
// cy.contains('Importing database');
|
||||
// cy.contains('Finished job script');
|
||||
// cy.get('[data-testid=RunScriptModal_close]').click();
|
||||
// cy.contains('Chinook').click();
|
||||
// cy.contains('Album');
|
||||
// });
|
||||
|
||||
it('Import Chinook Postgres', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.contains('Postgres-connection').click();
|
||||
cy.get('[data-testid=DatabaseAppObject_Chinook]').rightclick();
|
||||
cy.contains('Restore/import SQL dump').click();
|
||||
cy.get('#uploadFileButton').selectFile('data/chinook-postgres.sql', { force: true });
|
||||
cy.wait(500);
|
||||
cy.get('[data-testid=ImportDatabaseDumpModal_runImport]').click();
|
||||
cy.contains('Importing database');
|
||||
cy.contains('Finished job script');
|
||||
cy.get('[data-testid=RunScriptModal_close]').click();
|
||||
cy.contains('Chinook').click();
|
||||
cy.contains('album');
|
||||
});
|
||||
// it('Import Chinook Postgres', () => {
|
||||
// cy.visit('http://localhost:3000');
|
||||
// cy.contains('Postgres-connection').click();
|
||||
// cy.get('[data-testid=DatabaseAppObject_Chinook]').rightclick();
|
||||
// cy.contains('Restore/import SQL dump').click();
|
||||
// cy.get('#uploadFileButton').selectFile('data/chinook-postgres.sql', { force: true });
|
||||
// cy.wait(500);
|
||||
// cy.get('[data-testid=ImportDatabaseDumpModal_runImport]').click();
|
||||
// cy.contains('Importing database');
|
||||
// cy.contains('Finished job script');
|
||||
// cy.get('[data-testid=RunScriptModal_close]').click();
|
||||
// cy.contains('Chinook').click();
|
||||
// cy.contains('album');
|
||||
// });
|
||||
|
||||
it('Open ask pwd connection', () => {
|
||||
cy.visit('http://localhost:3000');
|
||||
@@ -83,7 +83,7 @@ describe('Run as portal', () => {
|
||||
cy.testid('DatabaseLoginModal_password').clear().type('Pwd2020Db');
|
||||
cy.testid('DatabaseLoginModal_connect').click();
|
||||
cy.contains('Chinook').click();
|
||||
cy.contains('album');
|
||||
// cy.contains('album');
|
||||
});
|
||||
|
||||
// it('import chinook DB', () => {
|
||||
|
||||
120
e2e-tests/cypress/e2e/redis.cy.js
Normal file
120
e2e-tests/cypress/e2e/redis.cy.js
Normal file
@@ -0,0 +1,120 @@
|
||||
Cypress.on('uncaught:exception', (err, runnable) => {
|
||||
// if the error message matches the one about WorkerGlobalScope importScripts
|
||||
if (err.message.includes("Failed to execute 'importScripts' on 'WorkerGlobalScope'")) {
|
||||
// return false to let Cypress know we intentionally want to ignore this error
|
||||
return false;
|
||||
}
|
||||
// otherwise let Cypress throw the error
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.viewport(1250, 900);
|
||||
});
|
||||
|
||||
describe('Redis data', () => {
|
||||
it('String test', () => {
|
||||
cy.contains('Redis-connection').click();
|
||||
cy.contains('db1').click();
|
||||
cy.contains('app').click();
|
||||
cy.contains('version').click();
|
||||
cy.testid('RedisValueDetail_AceEditor').click().realPress('Backspace').realType('1');
|
||||
cy.contains('Save').click();
|
||||
cy.contains('OK').click();
|
||||
});
|
||||
|
||||
it('Hash test', () => {
|
||||
cy.contains('Redis-connection').click();
|
||||
cy.contains('db1').click();
|
||||
cy.contains('user').click();
|
||||
cy.contains('alice').click();
|
||||
cy.testid('RedisKeyDetailTab_RenameKeyButton').click();
|
||||
cy.themeshot('redis-rename-key');
|
||||
cy.realType('3');
|
||||
cy.contains('OK').click();
|
||||
cy.contains('age').click();
|
||||
cy.testid('RedisValueHashDetail_ValueSection').click().realPress('Backspace').realType('8');
|
||||
cy.contains('Add field').click();
|
||||
cy.testid('RedisValueListLikeEdit_key').click().realType('phone');
|
||||
cy.testid('RedisValueListLikeEdit_value').click().realType('123-456-7890');
|
||||
cy.contains('Refresh').click();
|
||||
cy.themeshot('redis-hash-edit');
|
||||
cy.contains('Save').click();
|
||||
cy.themeshot('redis-hash-script-edit');
|
||||
cy.contains('OK').click();
|
||||
});
|
||||
|
||||
it('List test', () => {
|
||||
cy.contains('Redis-connection').click();
|
||||
cy.contains('db1').click();
|
||||
cy.contains('queue').click();
|
||||
cy.contains('emails').click();
|
||||
cy.contains('Add field').click();
|
||||
cy.testid('RedisValueListLikeEdit_value').click().realType('reset');
|
||||
cy.contains('Save').click();
|
||||
cy.contains('OK').click();
|
||||
});
|
||||
|
||||
it('Set test', () => {
|
||||
cy.contains('Redis-connection').click();
|
||||
cy.contains('db1').click();
|
||||
cy.contains('tags').click();
|
||||
cy.contains('Add field').click();
|
||||
cy.testid('RedisValueListLikeEdit_value').click().realType('newtag');
|
||||
cy.contains('Save').click();
|
||||
cy.contains('OK').click();
|
||||
});
|
||||
|
||||
it('ZSet test', () => {
|
||||
cy.contains('Redis-connection').click();
|
||||
cy.contains('db1').click();
|
||||
cy.contains('leaderboard').click();
|
||||
cy.contains('alice').click();
|
||||
cy.testid('RedisValueZSetDetail_score')
|
||||
.click()
|
||||
.realPress('Backspace')
|
||||
.realPress('Backspace')
|
||||
.realPress('Backspace')
|
||||
.realType('35');
|
||||
cy.contains('Save').click();
|
||||
cy.contains('OK').click();
|
||||
cy.contains('35').should('exist');
|
||||
});
|
||||
|
||||
it('JSON test', () => {
|
||||
cy.contains('Redis-connection').click();
|
||||
cy.contains('db1').click();
|
||||
cy.contains('user').click();
|
||||
cy.contains('1:*').click();
|
||||
cy.contains('json').click();
|
||||
cy.testid('RedisValueDetail_displaySelect').select('JSON view');
|
||||
cy.themeshot('redis-json-detail');
|
||||
});
|
||||
|
||||
it('Stream test', () => {
|
||||
cy.contains('Redis-connection').click();
|
||||
cy.contains('db1').click();
|
||||
cy.contains('events').click();
|
||||
cy.contains('Add field').click();
|
||||
cy.testid('RedisValueListLikeEdit_field').click().realType('message');
|
||||
cy.testid('RedisValueListLikeEdit_value').click().realType('Hello, World!');
|
||||
cy.contains('Save').click();
|
||||
cy.contains('OK').click();
|
||||
cy.themeshot('redis-stream');
|
||||
});
|
||||
|
||||
it('Add key', () => {
|
||||
cy.contains('Redis-connection').click();
|
||||
cy.contains('db1').click();
|
||||
cy.testid('RedisKeysTree_addKeyDropdown').click();
|
||||
cy.contains('String').click();
|
||||
cy.testid('NewRedisKeyTab_keyName').click().realType('newstringkey');
|
||||
cy.testid('RedisValueDetail_AceEditor').click().realType('This is a new string key.');
|
||||
cy.contains('Save').click();
|
||||
cy.contains('OK').click();
|
||||
cy.contains('newstringkey').should('exist');
|
||||
cy.testid('RedisKeysTree_addKeyDropdown').click();
|
||||
cy.contains('Hash').click();
|
||||
cy.themeshot('redis-add-hash-key');
|
||||
});
|
||||
});
|
||||
@@ -1,3 +1,12 @@
|
||||
Cypress.on('uncaught:exception', (err, runnable) => {
|
||||
// if the error message matches the one about WorkerGlobalScope importScripts
|
||||
if (err.message.includes("Failed to execute 'importScripts' on 'WorkerGlobalScope'")) {
|
||||
// return false to let Cypress know we intentionally want to ignore this error
|
||||
return false;
|
||||
}
|
||||
// otherwise let Cypress throw the error
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visit('http://localhost:3000');
|
||||
cy.viewport(1250, 900);
|
||||
@@ -11,21 +20,27 @@ describe('Team edition tests', () => {
|
||||
|
||||
cy.testid('AdminMenuWidget_itemConnections').click();
|
||||
cy.contains('New connection').click();
|
||||
cy.contains('New connection').click();
|
||||
cy.contains('New connection').click();
|
||||
cy.testid('ConnectionDriverFields_connectionType').select('PostgreSQL');
|
||||
cy.themeshot('connadmin');
|
||||
cy.contains('not granted').should('not.exist');
|
||||
cy.themeshot('connection-administration');
|
||||
|
||||
cy.testid('AdminMenuWidget_itemRoles').click();
|
||||
cy.contains('Permissions').click();
|
||||
cy.themeshot('roleadmin');
|
||||
cy.contains('logged-user').click();
|
||||
cy.contains('not granted').should('not.exist');
|
||||
cy.themeshot('role-administration');
|
||||
|
||||
cy.testid('AdminMenuWidget_itemUsers').click();
|
||||
cy.contains('New user').click();
|
||||
cy.contains('not granted').should('not.exist');
|
||||
cy.themeshot('user-administration');
|
||||
|
||||
cy.testid('AdminMenuWidget_itemAuthentication').click();
|
||||
cy.contains('Add authentication').click();
|
||||
cy.contains('Use database login').click();
|
||||
cy.contains('Add authentication').click();
|
||||
cy.contains('OAuth 2.0').click();
|
||||
cy.themeshot('authadmin');
|
||||
cy.contains('not granted').should('not.exist');
|
||||
cy.themeshot('authentication-administration');
|
||||
});
|
||||
|
||||
it('OAuth authentication', () => {
|
||||
@@ -77,6 +92,60 @@ describe('Team edition tests', () => {
|
||||
cy.testid('LoginPage_submitLogin').click();
|
||||
cy.testid('AdminMenuWidget_itemUsers').click();
|
||||
cy.contains('test@example.com');
|
||||
cy.contains('Rows: 1');
|
||||
});
|
||||
|
||||
it('Audit logging', () => {
|
||||
cy.testid('LoginPage_linkAdmin').click();
|
||||
cy.testid('LoginPage_password').type('adminpwd');
|
||||
cy.testid('LoginPage_submitLogin').click();
|
||||
|
||||
cy.testid('AdminMenuWidget_itemAuditLog').click();
|
||||
cy.contains('Audit log is not enabled');
|
||||
cy.testid('AdminMenuWidget_itemSettings').click();
|
||||
cy.testid('AdminSettingsTab_auditLogCheckbox').click();
|
||||
cy.testid('AdminMenuWidget_itemAuditLog').click();
|
||||
cy.contains('No data for selected date');
|
||||
|
||||
cy.testid('AdminMenuWidget_itemConnections').click();
|
||||
cy.contains('Open table').click();
|
||||
cy.contains('displayName');
|
||||
cy.get('.toolstrip').contains('Export').click();
|
||||
cy.contains('CSV file').click();
|
||||
|
||||
cy.testid('AdminMenuWidget_itemUsers').click();
|
||||
cy.contains('Open table').click();
|
||||
cy.contains('login');
|
||||
cy.get('.toolstrip').contains('Export').click();
|
||||
cy.contains('XML file').click();
|
||||
|
||||
cy.testid('AdminMenuWidget_itemAuditLog').click();
|
||||
cy.testid('AdminAuditLogTab_refreshButton').click();
|
||||
cy.contains('Exporting query').click();
|
||||
cy.themeshot('auditlog');
|
||||
});
|
||||
|
||||
it('Edit database permissions', () => {
|
||||
cy.testid('LoginPage_linkAdmin').click();
|
||||
cy.testid('LoginPage_password').type('adminpwd');
|
||||
cy.testid('LoginPage_submitLogin').click();
|
||||
|
||||
cy.testid('AdminMenuWidget_itemRoles').click();
|
||||
cy.testid('AdminRolesTab_table').contains('superadmin').click();
|
||||
cy.testid('AdminRolesTab_databases').click();
|
||||
|
||||
cy.testid('AdminDatabasesPermissionsGrid_addButton').click();
|
||||
cy.testid('AdminDatabasesPermissionsGrid_addButton').click();
|
||||
cy.testid('AdminDatabasesPermissionsGrid_addButton').click();
|
||||
|
||||
cy.testid('AdminListOrRegexEditor_1_regexInput').type('^Chinook[\\d]*$');
|
||||
cy.testid('AdminListOrRegexEditor_2_listSwitch').click();
|
||||
cy.testid('AdminListOrRegexEditor_2_listInput').type('Nortwind\nSales');
|
||||
cy.testid('AdminDatabasesPermissionsGrid_roleSelect_0').select('-2');
|
||||
cy.testid('AdminDatabasesPermissionsGrid_roleSelect_1').select('-3');
|
||||
cy.testid('AdminDatabasesPermissionsGrid_roleSelect_2').select('-4');
|
||||
|
||||
cy.contains('not granted').should('not.exist');
|
||||
|
||||
cy.themeshot('database-permissions');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -36,9 +36,11 @@ Cypress.Commands.add(
|
||||
prevSubject: 'optional',
|
||||
},
|
||||
(subject, file, options) => {
|
||||
cy.window().then(win => {
|
||||
win.__changeCurrentTheme('theme-dark');
|
||||
});
|
||||
if (!options?.keepTheme) {
|
||||
cy.window().then(win => {
|
||||
win.__changeCurrentTheme('dark');
|
||||
});
|
||||
}
|
||||
|
||||
// cy.screenshot(`${file}-dark`, {
|
||||
// onAfterScreenshot: (doc, props) => {
|
||||
@@ -63,9 +65,11 @@ Cypress.Commands.add(
|
||||
// });
|
||||
// });
|
||||
|
||||
cy.window().then(win => {
|
||||
win.__changeCurrentTheme('theme-light');
|
||||
});
|
||||
if (!options?.keepTheme) {
|
||||
cy.window().then(win => {
|
||||
win.__changeCurrentTheme('light');
|
||||
});
|
||||
}
|
||||
|
||||
if (subject) {
|
||||
cy.wrap(subject).screenshot(`${file}-light`, options);
|
||||
|
||||
@@ -42,3 +42,11 @@ beforeEach(() => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Cypress.Screenshot.defaults({
|
||||
// onBeforeScreenshot() {
|
||||
// if (window.Chart) {
|
||||
// Object.values(window.Chart.instances).forEach(c => c.resize());
|
||||
// }
|
||||
// },
|
||||
// });
|
||||
|
||||
6
e2e-tests/data/charts-sample/departments.jsonl
Normal file
6
e2e-tests/data/charts-sample/departments.jsonl
Normal file
@@ -0,0 +1,6 @@
|
||||
{"__isStreamHeader":true,"pureName":"departments","schemaName":"dbo","objectId":1205579333,"createDate":"2025-06-12T10:30:34.083Z","modifyDate":"2025-06-12T10:30:34.120Z","contentHash":"2025-06-12T10:30:34.120Z","columns":[{"columnName":"id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"name","dataType":"varchar(100)","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false}],"primaryKey":{"constraintName":"PK__departme__3213E83FE8E7043D","schemaName":"dbo","pureName":"departments","constraintType":"primaryKey","columns":[{"columnName":"id"}]},"foreignKeys":[],"indexes":[],"uniques":[],"engine":"mssql@dbgate-plugin-mssql"}
|
||||
{"id":1,"name":"IT"}
|
||||
{"id":2,"name":"Marketing"}
|
||||
{"id":3,"name":"Finance"}
|
||||
{"id":4,"name":"Human Resources"}
|
||||
{"id":5,"name":"Research and Development"}
|
||||
12
e2e-tests/data/charts-sample/departments.table.yaml
Normal file
12
e2e-tests/data/charts-sample/departments.table.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
name: departments
|
||||
columns:
|
||||
- name: id
|
||||
type: int
|
||||
default: null
|
||||
notNull: true
|
||||
- name: name
|
||||
type: varchar(100)
|
||||
default: null
|
||||
notNull: true
|
||||
primaryKey:
|
||||
- id
|
||||
39
e2e-tests/data/charts-sample/employee_project.jsonl
Normal file
39
e2e-tests/data/charts-sample/employee_project.jsonl
Normal file
@@ -0,0 +1,39 @@
|
||||
{"__isStreamHeader":true,"pureName":"employee_project","schemaName":"dbo","objectId":1333579789,"createDate":"2025-06-12T10:30:34.133Z","modifyDate":"2025-06-12T10:30:34.133Z","contentHash":"2025-06-12T10:30:34.133Z","columns":[{"columnName":"employee_id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"project_id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"role","dataType":"varchar(50)","notNull":false,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false}],"primaryKey":{"constraintName":"PK__employee__2EE9924949ED9668","schemaName":"dbo","pureName":"employee_project","constraintType":"primaryKey","columns":[{"columnName":"employee_id"},{"columnName":"project_id"}]},"foreignKeys":[{"constraintName":"FK__employee___emplo__5165187F","constraintType":"foreignKey","schemaName":"dbo","pureName":"employee_project","refSchemaName":"dbo","refTableName":"employees","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"employee_id","refColumnName":"id"}]},{"constraintName":"FK__employee___proje__52593CB8","constraintType":"foreignKey","schemaName":"dbo","pureName":"employee_project","refSchemaName":"dbo","refTableName":"projects","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"project_id","refColumnName":"id"}]}],"indexes":[],"uniques":[],"engine":"mssql@dbgate-plugin-mssql"}
|
||||
{"employee_id":1,"project_id":6,"role":"Manager"}
|
||||
{"employee_id":1,"project_id":8,"role":"Developer"}
|
||||
{"employee_id":2,"project_id":7,"role":"Tester"}
|
||||
{"employee_id":2,"project_id":8,"role":"Developer"}
|
||||
{"employee_id":3,"project_id":4,"role":"Analyst"}
|
||||
{"employee_id":3,"project_id":6,"role":"Developer"}
|
||||
{"employee_id":4,"project_id":2,"role":"Manager"}
|
||||
{"employee_id":4,"project_id":4,"role":"Analyst"}
|
||||
{"employee_id":4,"project_id":5,"role":"Analyst"}
|
||||
{"employee_id":5,"project_id":5,"role":"Tester"}
|
||||
{"employee_id":6,"project_id":1,"role":"Analyst"}
|
||||
{"employee_id":6,"project_id":6,"role":"Tester"}
|
||||
{"employee_id":6,"project_id":9,"role":"Manager"}
|
||||
{"employee_id":7,"project_id":8,"role":"Manager"}
|
||||
{"employee_id":8,"project_id":10,"role":"Analyst"}
|
||||
{"employee_id":9,"project_id":2,"role":"Analyst"}
|
||||
{"employee_id":9,"project_id":6,"role":"Analyst"}
|
||||
{"employee_id":9,"project_id":7,"role":"Developer"}
|
||||
{"employee_id":10,"project_id":2,"role":"Manager"}
|
||||
{"employee_id":10,"project_id":6,"role":"Analyst"}
|
||||
{"employee_id":11,"project_id":1,"role":"Tester"}
|
||||
{"employee_id":12,"project_id":4,"role":"Tester"}
|
||||
{"employee_id":13,"project_id":2,"role":"Developer"}
|
||||
{"employee_id":13,"project_id":3,"role":"Analyst"}
|
||||
{"employee_id":13,"project_id":7,"role":"Developer"}
|
||||
{"employee_id":14,"project_id":3,"role":"Developer"}
|
||||
{"employee_id":14,"project_id":9,"role":"Manager"}
|
||||
{"employee_id":15,"project_id":1,"role":"Developer"}
|
||||
{"employee_id":15,"project_id":5,"role":"Manager"}
|
||||
{"employee_id":16,"project_id":3,"role":"Tester"}
|
||||
{"employee_id":16,"project_id":5,"role":"Developer"}
|
||||
{"employee_id":17,"project_id":6,"role":"Analyst"}
|
||||
{"employee_id":18,"project_id":1,"role":"Tester"}
|
||||
{"employee_id":18,"project_id":5,"role":"Tester"}
|
||||
{"employee_id":18,"project_id":6,"role":"Manager"}
|
||||
{"employee_id":19,"project_id":6,"role":"Analyst"}
|
||||
{"employee_id":20,"project_id":2,"role":"Developer"}
|
||||
{"employee_id":20,"project_id":4,"role":"Developer"}
|
||||
18
e2e-tests/data/charts-sample/employee_project.table.yaml
Normal file
18
e2e-tests/data/charts-sample/employee_project.table.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
name: employee_project
|
||||
columns:
|
||||
- name: employee_id
|
||||
type: int
|
||||
default: null
|
||||
notNull: true
|
||||
references: employees
|
||||
- name: project_id
|
||||
type: int
|
||||
default: null
|
||||
notNull: true
|
||||
references: projects
|
||||
- name: role
|
||||
type: varchar(50)
|
||||
default: null
|
||||
primaryKey:
|
||||
- employee_id
|
||||
- project_id
|
||||
21
e2e-tests/data/charts-sample/employees.jsonl
Normal file
21
e2e-tests/data/charts-sample/employees.jsonl
Normal file
@@ -0,0 +1,21 @@
|
||||
{"__isStreamHeader":true,"pureName":"employees","schemaName":"dbo","objectId":1237579447,"createDate":"2025-06-12T10:30:34.113Z","modifyDate":"2025-06-12T12:35:22.140Z","contentHash":"2025-06-12T12:35:22.140Z","columns":[{"columnName":"id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"name","dataType":"varchar(100)","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"email","dataType":"varchar(100)","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"hire_date","dataType":"date","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"department_id","dataType":"int","notNull":false,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false}],"primaryKey":{"constraintName":"PK__employee__3213E83FE576E55A","schemaName":"dbo","pureName":"employees","constraintType":"primaryKey","columns":[{"columnName":"id"}]},"foreignKeys":[{"constraintName":"FK__employees__depar__4CA06362","constraintType":"foreignKey","schemaName":"dbo","pureName":"employees","refSchemaName":"dbo","refTableName":"departments","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"department_id","refColumnName":"id"}]}],"indexes":[],"uniques":[{"constraintName":"UQ__employee__AB6E6164E18D883F","columns":[{"columnName":"email"}]}],"engine":"mssql@dbgate-plugin-mssql"}
|
||||
{"id":1,"name":"John Smith","email":"john.smith@example.com","hire_date":"2018-07-09T00:00:00.000Z","department_id":2}
|
||||
{"id":2,"name":"Jane Garcia","email":"jane.garcia@example.com","hire_date":"2019-10-13T00:00:00.000Z","department_id":5}
|
||||
{"id":3,"name":"Grace Smith","email":"grace.smith@example.com","hire_date":"2019-03-16T00:00:00.000Z","department_id":1}
|
||||
{"id":4,"name":"Charlie Williams","email":"charlie.williams@example.com","hire_date":"2020-10-18T00:00:00.000Z","department_id":2}
|
||||
{"id":5,"name":"Eve Brown","email":"eve.brown@example.com","hire_date":"2018-04-12T00:00:00.000Z","department_id":4}
|
||||
{"id":6,"name":"Alice Moore","email":"alice.moore@example.com","hire_date":"2019-04-20T00:00:00.000Z","department_id":2}
|
||||
{"id":7,"name":"Eve Williams","email":"eve.williams@example.com","hire_date":"2020-04-26T00:00:00.000Z","department_id":4}
|
||||
{"id":8,"name":"Eve Jones","email":"eve.jones@example.com","hire_date":"2022-10-04T00:00:00.000Z","department_id":3}
|
||||
{"id":9,"name":"Diana Miller","email":"diana.miller@example.com","hire_date":"2021-03-28T00:00:00.000Z","department_id":1}
|
||||
{"id":10,"name":"Diana Smith","email":"diana.smith@example.com","hire_date":"2018-04-12T00:00:00.000Z","department_id":2}
|
||||
{"id":11,"name":"Hank Johnson","email":"hank.johnson@example.com","hire_date":"2020-09-16T00:00:00.000Z","department_id":2}
|
||||
{"id":12,"name":"Frank Miller","email":"frank.miller@example.com","hire_date":"2023-01-12T00:00:00.000Z","department_id":4}
|
||||
{"id":13,"name":"Jane Brown","email":"jane.brown@example.com","hire_date":"2023-05-07T00:00:00.000Z","department_id":3}
|
||||
{"id":14,"name":"Grace Davis","email":"grace.davis@example.com","hire_date":"2019-08-22T00:00:00.000Z","department_id":3}
|
||||
{"id":15,"name":"Jane Black","email":"jane.black@example.com","hire_date":"2019-04-28T00:00:00.000Z","department_id":2}
|
||||
{"id":16,"name":"Charlie Smith","email":"charlie.smith@example.com","hire_date":"2019-06-12T00:00:00.000Z","department_id":5}
|
||||
{"id":17,"name":"Eve Johnson","email":"eve.johnson@example.com","hire_date":"2020-11-07T00:00:00.000Z","department_id":5}
|
||||
{"id":18,"name":"Jane Johnson","email":"jane.johnson@example.com","hire_date":"2020-04-06T00:00:00.000Z","department_id":2}
|
||||
{"id":19,"name":"Hank Brown","email":"hank.brown@example.com","hire_date":"2023-05-10T00:00:00.000Z","department_id":2}
|
||||
{"id":20,"name":"Frank Jones","email":"frank.jones@example.com","hire_date":"2020-10-26T00:00:00.000Z","department_id":1}
|
||||
28
e2e-tests/data/charts-sample/employees.table.yaml
Normal file
28
e2e-tests/data/charts-sample/employees.table.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
name: employees
|
||||
columns:
|
||||
- name: id
|
||||
type: int
|
||||
default: null
|
||||
notNull: true
|
||||
- name: name
|
||||
type: varchar(100)
|
||||
default: null
|
||||
notNull: true
|
||||
- name: email
|
||||
type: varchar(100)
|
||||
default: null
|
||||
notNull: true
|
||||
- name: hire_date
|
||||
type: date
|
||||
default: null
|
||||
notNull: true
|
||||
- name: department_id
|
||||
type: int
|
||||
default: null
|
||||
references: departments
|
||||
primaryKey:
|
||||
- id
|
||||
uniques:
|
||||
- name: UQ__employee__AB6E6164E18D883F
|
||||
columns:
|
||||
- email
|
||||
141
e2e-tests/data/charts-sample/finance_reports.jsonl
Normal file
141
e2e-tests/data/charts-sample/finance_reports.jsonl
Normal file
@@ -0,0 +1,141 @@
|
||||
{"__isStreamHeader":true,"pureName":"finance_reports","schemaName":"dbo","objectId":338100245,"createDate":"2025-06-23T12:15:08.727Z","modifyDate":"2025-06-23T12:15:08.750Z","contentHash":"2025-06-23T12:15:08.750Z","columns":[{"columnName":"id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"date","dataType":"date","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"profit","dataType":"money","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false}],"foreignKeys":[{"constraintName":"project_id","constraintType":"foreignKey","schemaName":"dbo","pureName":"finance_reports","refSchemaName":"dbo","refTableName":"projects","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"id","refColumnName":"id"}]}],"indexes":[],"uniques":[],"engine":"mssql@dbgate-plugin-mssql"}
|
||||
{"id":1,"date":"2022-01-01T00:00:00.000Z","profit":73923.4}
|
||||
{"id":1,"date":"2022-01-31T00:00:00.000Z","profit":21837.75}
|
||||
{"id":1,"date":"2022-03-02T00:00:00.000Z","profit":67859.8}
|
||||
{"id":1,"date":"2022-04-01T00:00:00.000Z","profit":77403.3}
|
||||
{"id":1,"date":"2022-05-01T00:00:00.000Z","profit":84083.19}
|
||||
{"id":1,"date":"2022-05-31T00:00:00.000Z","profit":30040.55}
|
||||
{"id":1,"date":"2022-06-30T00:00:00.000Z","profit":50947.14}
|
||||
{"id":1,"date":"2022-07-30T00:00:00.000Z","profit":63345.62}
|
||||
{"id":1,"date":"2022-08-29T00:00:00.000Z","profit":23819.45}
|
||||
{"id":1,"date":"2022-09-28T00:00:00.000Z","profit":-25919.19}
|
||||
{"id":1,"date":"2022-10-28T00:00:00.000Z","profit":27967.6}
|
||||
{"id":1,"date":"2022-11-27T00:00:00.000Z","profit":-37402.36}
|
||||
{"id":1,"date":"2022-12-27T00:00:00.000Z","profit":94528.8}
|
||||
{"id":1,"date":"2023-01-26T00:00:00.000Z","profit":29491.03}
|
||||
{"id":1,"date":"2023-02-25T00:00:00.000Z","profit":81541.29}
|
||||
{"id":2,"date":"2022-01-01T00:00:00.000Z","profit":18070.94}
|
||||
{"id":2,"date":"2022-01-31T00:00:00.000Z","profit":-40609.87}
|
||||
{"id":2,"date":"2022-03-02T00:00:00.000Z","profit":42435.51}
|
||||
{"id":2,"date":"2022-04-01T00:00:00.000Z","profit":-11915.15}
|
||||
{"id":2,"date":"2022-05-01T00:00:00.000Z","profit":-37417.4}
|
||||
{"id":2,"date":"2022-05-31T00:00:00.000Z","profit":23028.66}
|
||||
{"id":2,"date":"2022-06-30T00:00:00.000Z","profit":-6895.49}
|
||||
{"id":2,"date":"2022-07-30T00:00:00.000Z","profit":63114.54}
|
||||
{"id":2,"date":"2022-08-29T00:00:00.000Z","profit":94646.99}
|
||||
{"id":2,"date":"2022-09-28T00:00:00.000Z","profit":99560.77}
|
||||
{"id":2,"date":"2022-10-28T00:00:00.000Z","profit":62216.22}
|
||||
{"id":2,"date":"2022-11-27T00:00:00.000Z","profit":85094.32}
|
||||
{"id":2,"date":"2022-12-27T00:00:00.000Z","profit":-23378.37}
|
||||
{"id":2,"date":"2023-01-26T00:00:00.000Z","profit":47635.86}
|
||||
{"id":2,"date":"2023-02-25T00:00:00.000Z","profit":33727.72}
|
||||
{"id":3,"date":"2022-01-01T00:00:00.000Z","profit":33088.03}
|
||||
{"id":3,"date":"2022-01-31T00:00:00.000Z","profit":66668.91}
|
||||
{"id":3,"date":"2022-03-02T00:00:00.000Z","profit":5344.27}
|
||||
{"id":3,"date":"2022-04-01T00:00:00.000Z","profit":22122.99}
|
||||
{"id":3,"date":"2022-05-01T00:00:00.000Z","profit":27342.01}
|
||||
{"id":3,"date":"2022-05-31T00:00:00.000Z","profit":55479.42}
|
||||
{"id":3,"date":"2022-06-30T00:00:00.000Z","profit":35956.11}
|
||||
{"id":3,"date":"2022-07-30T00:00:00.000Z","profit":9667.12}
|
||||
{"id":3,"date":"2022-08-29T00:00:00.000Z","profit":63430.18}
|
||||
{"id":3,"date":"2022-09-28T00:00:00.000Z","profit":-4883.41}
|
||||
{"id":3,"date":"2022-10-28T00:00:00.000Z","profit":38902.8}
|
||||
{"id":3,"date":"2022-11-27T00:00:00.000Z","profit":-25500.13}
|
||||
{"id":3,"date":"2022-12-27T00:00:00.000Z","profit":65074.21}
|
||||
{"id":3,"date":"2023-01-26T00:00:00.000Z","profit":12570.27}
|
||||
{"id":3,"date":"2023-02-25T00:00:00.000Z","profit":35418.36}
|
||||
{"id":4,"date":"2022-01-01T00:00:00.000Z","profit":68282.98}
|
||||
{"id":4,"date":"2022-01-31T00:00:00.000Z","profit":77778.99}
|
||||
{"id":4,"date":"2022-03-02T00:00:00.000Z","profit":95490.49}
|
||||
{"id":4,"date":"2022-04-01T00:00:00.000Z","profit":-44466.37}
|
||||
{"id":4,"date":"2022-05-01T00:00:00.000Z","profit":40215.71}
|
||||
{"id":4,"date":"2022-05-31T00:00:00.000Z","profit":-31228.87}
|
||||
{"id":4,"date":"2022-06-30T00:00:00.000Z","profit":60667.69}
|
||||
{"id":4,"date":"2022-07-30T00:00:00.000Z","profit":71439.16}
|
||||
{"id":4,"date":"2022-08-29T00:00:00.000Z","profit":-25077.4}
|
||||
{"id":4,"date":"2022-09-28T00:00:00.000Z","profit":-36128.2}
|
||||
{"id":4,"date":"2022-10-28T00:00:00.000Z","profit":36727.68}
|
||||
{"id":4,"date":"2022-11-27T00:00:00.000Z","profit":-24207.2}
|
||||
{"id":4,"date":"2022-12-27T00:00:00.000Z","profit":63846.96}
|
||||
{"id":5,"date":"2022-01-01T00:00:00.000Z","profit":21648.3}
|
||||
{"id":5,"date":"2022-01-31T00:00:00.000Z","profit":59263.22}
|
||||
{"id":5,"date":"2022-03-02T00:00:00.000Z","profit":49154.51}
|
||||
{"id":5,"date":"2022-04-01T00:00:00.000Z","profit":34787.48}
|
||||
{"id":5,"date":"2022-05-01T00:00:00.000Z","profit":-24120.19}
|
||||
{"id":5,"date":"2022-05-31T00:00:00.000Z","profit":98437.86}
|
||||
{"id":5,"date":"2022-06-30T00:00:00.000Z","profit":18614.77}
|
||||
{"id":5,"date":"2022-07-30T00:00:00.000Z","profit":17680.34}
|
||||
{"id":5,"date":"2022-08-29T00:00:00.000Z","profit":74406.86}
|
||||
{"id":5,"date":"2022-09-28T00:00:00.000Z","profit":61845.3}
|
||||
{"id":5,"date":"2022-10-28T00:00:00.000Z","profit":-37889.59}
|
||||
{"id":5,"date":"2022-11-27T00:00:00.000Z","profit":76651.05}
|
||||
{"id":5,"date":"2022-12-27T00:00:00.000Z","profit":58739.6}
|
||||
{"id":5,"date":"2023-01-26T00:00:00.000Z","profit":82605.85}
|
||||
{"id":6,"date":"2022-01-01T00:00:00.000Z","profit":-5206.8}
|
||||
{"id":6,"date":"2022-01-31T00:00:00.000Z","profit":27498.27}
|
||||
{"id":6,"date":"2022-03-02T00:00:00.000Z","profit":-2939.84}
|
||||
{"id":6,"date":"2022-04-01T00:00:00.000Z","profit":-37261.08}
|
||||
{"id":6,"date":"2022-05-01T00:00:00.000Z","profit":37069.04}
|
||||
{"id":6,"date":"2022-05-31T00:00:00.000Z","profit":524.88}
|
||||
{"id":6,"date":"2022-06-30T00:00:00.000Z","profit":-29620.85}
|
||||
{"id":6,"date":"2022-07-30T00:00:00.000Z","profit":35540.81}
|
||||
{"id":6,"date":"2022-08-29T00:00:00.000Z","profit":20608.94}
|
||||
{"id":6,"date":"2022-09-28T00:00:00.000Z","profit":34809.33}
|
||||
{"id":6,"date":"2022-10-28T00:00:00.000Z","profit":-44949.05}
|
||||
{"id":6,"date":"2022-11-27T00:00:00.000Z","profit":-22524.26}
|
||||
{"id":6,"date":"2022-12-27T00:00:00.000Z","profit":37841.58}
|
||||
{"id":7,"date":"2022-01-01T00:00:00.000Z","profit":6903.17}
|
||||
{"id":7,"date":"2022-01-31T00:00:00.000Z","profit":58480.84}
|
||||
{"id":7,"date":"2022-03-02T00:00:00.000Z","profit":48217.34}
|
||||
{"id":7,"date":"2022-04-01T00:00:00.000Z","profit":73592.44}
|
||||
{"id":7,"date":"2022-05-01T00:00:00.000Z","profit":-21831.18}
|
||||
{"id":7,"date":"2022-05-31T00:00:00.000Z","profit":-40926.16}
|
||||
{"id":7,"date":"2022-06-30T00:00:00.000Z","profit":62299.5}
|
||||
{"id":7,"date":"2022-07-30T00:00:00.000Z","profit":95376.53}
|
||||
{"id":7,"date":"2022-08-29T00:00:00.000Z","profit":-13317.36}
|
||||
{"id":7,"date":"2022-09-28T00:00:00.000Z","profit":81565.05}
|
||||
{"id":7,"date":"2022-10-28T00:00:00.000Z","profit":77420.52}
|
||||
{"id":7,"date":"2022-11-27T00:00:00.000Z","profit":-12052.47}
|
||||
{"id":7,"date":"2022-12-27T00:00:00.000Z","profit":37742.07}
|
||||
{"id":7,"date":"2023-01-26T00:00:00.000Z","profit":-8057.99}
|
||||
{"id":8,"date":"2022-01-01T00:00:00.000Z","profit":27213.73}
|
||||
{"id":8,"date":"2022-01-31T00:00:00.000Z","profit":34271.75}
|
||||
{"id":8,"date":"2022-03-02T00:00:00.000Z","profit":-44549.47}
|
||||
{"id":8,"date":"2022-04-01T00:00:00.000Z","profit":15236.34}
|
||||
{"id":8,"date":"2022-05-01T00:00:00.000Z","profit":-27759.81}
|
||||
{"id":8,"date":"2022-05-31T00:00:00.000Z","profit":7955.12}
|
||||
{"id":8,"date":"2022-06-30T00:00:00.000Z","profit":-34484.38}
|
||||
{"id":8,"date":"2022-07-30T00:00:00.000Z","profit":-49758.7}
|
||||
{"id":8,"date":"2022-08-29T00:00:00.000Z","profit":-41990.86}
|
||||
{"id":8,"date":"2022-09-28T00:00:00.000Z","profit":58123.01}
|
||||
{"id":8,"date":"2022-10-28T00:00:00.000Z","profit":30128.78}
|
||||
{"id":8,"date":"2022-11-27T00:00:00.000Z","profit":-10151.17}
|
||||
{"id":8,"date":"2022-12-27T00:00:00.000Z","profit":54048.33}
|
||||
{"id":8,"date":"2023-01-26T00:00:00.000Z","profit":-43123.17}
|
||||
{"id":9,"date":"2022-01-01T00:00:00.000Z","profit":61031.83}
|
||||
{"id":9,"date":"2022-01-31T00:00:00.000Z","profit":68577.58}
|
||||
{"id":9,"date":"2022-03-02T00:00:00.000Z","profit":88698.97}
|
||||
{"id":9,"date":"2022-04-01T00:00:00.000Z","profit":8906.03}
|
||||
{"id":9,"date":"2022-05-01T00:00:00.000Z","profit":28824.73}
|
||||
{"id":9,"date":"2022-05-31T00:00:00.000Z","profit":88280.34}
|
||||
{"id":9,"date":"2022-06-30T00:00:00.000Z","profit":35266.09}
|
||||
{"id":9,"date":"2022-07-30T00:00:00.000Z","profit":-38025.36}
|
||||
{"id":9,"date":"2022-08-29T00:00:00.000Z","profit":-12118.53}
|
||||
{"id":9,"date":"2022-09-28T00:00:00.000Z","profit":-27265.86}
|
||||
{"id":9,"date":"2022-10-28T00:00:00.000Z","profit":56870.57}
|
||||
{"id":9,"date":"2022-11-27T00:00:00.000Z","profit":88078.95}
|
||||
{"id":9,"date":"2022-12-27T00:00:00.000Z","profit":-24059.67}
|
||||
{"id":9,"date":"2023-01-26T00:00:00.000Z","profit":-13301.43}
|
||||
{"id":10,"date":"2022-01-01T00:00:00.000Z","profit":-22479.23}
|
||||
{"id":10,"date":"2022-01-31T00:00:00.000Z","profit":8106.27}
|
||||
{"id":10,"date":"2022-03-02T00:00:00.000Z","profit":69372.19}
|
||||
{"id":10,"date":"2022-04-01T00:00:00.000Z","profit":-11895.74}
|
||||
{"id":10,"date":"2022-05-01T00:00:00.000Z","profit":-33206.5}
|
||||
{"id":10,"date":"2022-05-31T00:00:00.000Z","profit":56073.34}
|
||||
{"id":10,"date":"2022-06-30T00:00:00.000Z","profit":67488.3}
|
||||
{"id":10,"date":"2022-07-30T00:00:00.000Z","profit":48529.23}
|
||||
{"id":10,"date":"2022-08-29T00:00:00.000Z","profit":28680.2}
|
||||
{"id":10,"date":"2022-09-28T00:00:00.000Z","profit":59311.16}
|
||||
{"id":10,"date":"2022-10-28T00:00:00.000Z","profit":25315.78}
|
||||
{"id":10,"date":"2022-11-27T00:00:00.000Z","profit":36116.38}
|
||||
{"id":10,"date":"2022-12-27T00:00:00.000Z","profit":-42040.4}
|
||||
15
e2e-tests/data/charts-sample/finance_reports.table.yaml
Normal file
15
e2e-tests/data/charts-sample/finance_reports.table.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
name: finance_reports
|
||||
columns:
|
||||
- name: id
|
||||
type: int
|
||||
default: null
|
||||
notNull: true
|
||||
references: projects
|
||||
- name: date
|
||||
type: date
|
||||
default: null
|
||||
notNull: true
|
||||
- name: profit
|
||||
type: money
|
||||
default: null
|
||||
notNull: true
|
||||
11
e2e-tests/data/charts-sample/projects.jsonl
Normal file
11
e2e-tests/data/charts-sample/projects.jsonl
Normal file
@@ -0,0 +1,11 @@
|
||||
{"__isStreamHeader":true,"pureName":"projects","schemaName":"dbo","objectId":1301579675,"createDate":"2025-06-12T10:30:34.127Z","modifyDate":"2025-06-23T12:15:08.750Z","contentHash":"2025-06-23T12:15:08.750Z","columns":[{"columnName":"id","dataType":"int","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"name","dataType":"varchar(100)","notNull":true,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"start_date","dataType":"date","notNull":false,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false},{"columnName":"end_date","dataType":"date","notNull":false,"autoIncrement":false,"defaultValue":null,"defaultConstraint":null,"computedExpression":null,"hasAutoValue":false}],"primaryKey":{"constraintName":"PK__projects__3213E83F26A7ED11","schemaName":"dbo","pureName":"projects","constraintType":"primaryKey","columns":[{"columnName":"id"}]},"foreignKeys":[],"indexes":[],"uniques":[],"engine":"mssql@dbgate-plugin-mssql"}
|
||||
{"id":1,"name":"Apollo Upgrade","start_date":"2020-04-27T00:00:00.000Z","end_date":"2020-10-19T00:00:00.000Z"}
|
||||
{"id":2,"name":"Market Expansion","start_date":"2022-08-04T00:00:00.000Z","end_date":"2023-06-20T00:00:00.000Z"}
|
||||
{"id":3,"name":"AI Integration","start_date":"2020-05-11T00:00:00.000Z","end_date":"2021-07-10T00:00:00.000Z"}
|
||||
{"id":4,"name":"Cost Reduction","start_date":"2022-01-08T00:00:00.000Z","end_date":"2022-07-12T00:00:00.000Z"}
|
||||
{"id":5,"name":"Cloud Migration","start_date":"2021-01-11T00:00:00.000Z","end_date":"2021-05-27T00:00:00.000Z"}
|
||||
{"id":6,"name":"Customer Portal","start_date":"2021-07-13T00:00:00.000Z","end_date":"2022-09-22T00:00:00.000Z"}
|
||||
{"id":7,"name":"Data Lake","start_date":"2021-02-25T00:00:00.000Z","end_date":"2021-08-21T00:00:00.000Z"}
|
||||
{"id":8,"name":"UX Overhaul","start_date":"2021-05-20T00:00:00.000Z","end_date":"2022-09-10T00:00:00.000Z"}
|
||||
{"id":9,"name":"Security Hardening","start_date":"2021-05-28T00:00:00.000Z","end_date":"2022-07-28T00:00:00.000Z"}
|
||||
{"id":10,"name":"Mobile App Revamp","start_date":"2021-11-17T00:00:00.000Z","end_date":"2022-06-04T00:00:00.000Z"}
|
||||
18
e2e-tests/data/charts-sample/projects.table.yaml
Normal file
18
e2e-tests/data/charts-sample/projects.table.yaml
Normal file
@@ -0,0 +1,18 @@
|
||||
name: projects
|
||||
columns:
|
||||
- name: id
|
||||
type: int
|
||||
default: null
|
||||
notNull: true
|
||||
- name: name
|
||||
type: varchar(100)
|
||||
default: null
|
||||
notNull: true
|
||||
- name: start_date
|
||||
type: date
|
||||
default: null
|
||||
- name: end_date
|
||||
type: date
|
||||
default: null
|
||||
primaryKey:
|
||||
- id
|
||||
23
e2e-tests/data/files/sql/chart1.sql
Normal file
23
e2e-tests/data/files/sql/chart1.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
-- >>>
|
||||
-- autoExecute: true
|
||||
-- splitterInitialValue: 20%
|
||||
-- selected-chart: 1
|
||||
-- <<<
|
||||
|
||||
SELECT
|
||||
d.name AS department_name,
|
||||
FORMAT(fr.date, 'yyyy-MM') AS month,
|
||||
SUM(fr.profit) AS total_monthly_profit
|
||||
FROM
|
||||
departments d
|
||||
JOIN
|
||||
employees e ON d.id = e.department_id
|
||||
JOIN
|
||||
employee_project ep ON e.id = ep.employee_id
|
||||
JOIN
|
||||
finance_reports fr ON ep.project_id = fr.id
|
||||
GROUP BY
|
||||
d.name, FORMAT(fr.date, 'yyyy-MM')
|
||||
ORDER BY
|
||||
d.name, month;
|
||||
|
||||
253
e2e-tests/data/files/themes/Green-Sample
Normal file
253
e2e-tests/data/files/themes/Green-Sample
Normal file
@@ -0,0 +1,253 @@
|
||||
{
|
||||
"themeName": "Green-Sample",
|
||||
"themeType": "light",
|
||||
"themeVariables": {
|
||||
"--theme-generic-font": "oklch(27% 0.07 130)",
|
||||
"--theme-generic-font-hover": "oklch(40% 0.15 130)",
|
||||
"--theme-generic-font-grayed": "oklch(65% 0.05 130)",
|
||||
"--theme-link-foreground": "oklch(40% 0.25 130)",
|
||||
"--theme-content-background": "oklch(95% 0.05 130)",
|
||||
"--theme-widget-panel-background": "oklch(80% 0.1 130)",
|
||||
"--theme-widget-panel-foreground": "oklch(27% 0.07 130)",
|
||||
"--theme-widget-icon-background-active": "oklch(50% 0.12 130)",
|
||||
"--theme-widget-icon-foreground-active": "white",
|
||||
"--theme-widget-icon-foreground-hover": "white",
|
||||
"--theme-widget-icon-border-active": "1px solid white",
|
||||
"--theme-scrollbar-background": "oklch(90% 0.08 130)",
|
||||
"--theme-scrollbar-thumb-background": "oklch(70% 0.12 130)",
|
||||
"--theme-scrollbar-thumb-background-hover": "oklch(40% 0.15 130)",
|
||||
"--theme-scrollbar-corner-background": "oklch(85% 0.1 130)",
|
||||
"--theme-tabs-panel-border": "1px solid oklch(95% 0.05 130)",
|
||||
"--theme-tabs-panel-foreground": "oklch(20% 0.06 130)",
|
||||
"--theme-tabs-panel-active-foreground": "oklch(10% 0.06 130)",
|
||||
"--theme-tabs-panel-background": "oklch(95.5% 0.04 130)",
|
||||
"--theme-tabs-panel-active-background": "oklch(80% 0.12 130)",
|
||||
"--theme-tabs-panel-item-background": "oklch(90% 0.1 130)",
|
||||
"--theme-tabs-panel-active-border": "1px solid oklch(50% 0.2 130)",
|
||||
"--theme-splitter-active": "oklch(50% 0.2 130)",
|
||||
"--theme-splitter-button-background": "oklch(90% 0.1 130)",
|
||||
"--theme-splitter-button-background-active": "oklch(85% 0.15 130)",
|
||||
"--theme-splitter-button-foreground": "oklch(10% 0.06 130)",
|
||||
"--theme-sidebar-background": "oklch(90% 0.1 130)",
|
||||
"--theme-sidebar-background-hover": "oklch(80% 0.12 130)",
|
||||
"--theme-sidebar-background-active": "oklch(75% 0.14 130)",
|
||||
"--theme-sidebar-background-focused": "oklch(70% 0.18 130)",
|
||||
"--theme-sidebar-foreground": "oklch(20% 0.06 130)",
|
||||
"--theme-sidebar-foreground-button": "oklch(40% 0.12 130)",
|
||||
"--theme-sidebar-foreground-grayed": "oklch(65% 0.05 130)",
|
||||
"--theme-sidebar-foreground-hover": "oklch(50% 0.25 130)",
|
||||
"--theme-sidebar-section-background": "oklch(65% 0.05 130)",
|
||||
"--theme-sidebar-section-border": "none",
|
||||
"--theme-sidebar-section-border-top": "1px solid oklch(80% 0.1 130)",
|
||||
"--theme-sidebar-section-foreground": "oklch(10% 0.06 130)",
|
||||
"--theme-sidebar-border": "none",
|
||||
"--theme-altsidebar-background": "oklch(95% 0.05 130)",
|
||||
"--theme-altsidebar-background-grayed": "oklch(97% 0.02 130)",
|
||||
"--theme-altsidebar-background-hover": "oklch(85% 0.1 130)",
|
||||
"--theme-altsidebar-background-active": "oklch(80% 0.12 130)",
|
||||
"--theme-altsidebar-background-focused": "oklch(75% 0.15 130)",
|
||||
"--theme-altsidebar-foreground": "oklch(20% 0.06 130)",
|
||||
"--theme-altsidebar-foreground-button": "oklch(40% 0.12 130)",
|
||||
"--theme-altsidebar-foreground-grayed": "oklch(65% 0.05 130)",
|
||||
"--theme-altsidebar-foreground-hover": "oklch(50% 0.25 130)",
|
||||
"--theme-altsidebar-section-background": "oklch(97% 0.02 130)",
|
||||
"--theme-altsidebar-section-border": "none",
|
||||
"--theme-altsidebar-section-border-top": "1px solid oklch(85% 0.1 130)",
|
||||
"--theme-altsidebar-section-foreground": "oklch(10% 0.06 130)",
|
||||
"--theme-altsidebar-border": "1px solid oklch(90% 0.1 130)",
|
||||
"--theme-searchbox-background": "oklch(80% 0.12 130)",
|
||||
"--theme-searchbox-placeholder": "oklch(65% 0.05 130)",
|
||||
"--theme-searchbox-border": "1px solid oklch(70% 0.15 130)",
|
||||
"--theme-searchbox-background-filtered": "oklch(95% 0.04 110)",
|
||||
"--theme-altsearchbox-background": "oklch(90% 0.1 130)",
|
||||
"--theme-altsearchbox-placeholder": "oklch(65% 0.05 130)",
|
||||
"--theme-altsearchbox-border": "1px solid oklch(80% 0.1 130)",
|
||||
"--theme-inlinebutton-foreground": "oklch(40% 0.12 130)",
|
||||
"--theme-inlinebutton-foreground-disabled": "oklch(65% 0.05 130)",
|
||||
"--theme-inlinebutton-foreground-hover": "black",
|
||||
"--theme-inlinebutton-circle-hover-background": "oklch(85% 0.1 130)",
|
||||
"--theme-inlinebutton-bordered-border": "1px solid oklch(85% 0.1 130)",
|
||||
"--theme-inlinebutton-bordered-hover-border": "1px solid oklch(70% 0.15 130)",
|
||||
"--theme-inlinebutton-bordered-background": "linear-gradient(to bottom, oklch(95% 0.04 130) 5%, oklch(90% 0.1 130) 100%)",
|
||||
"--theme-inlinebutton-bordered-hover-background": "linear-gradient(to bottom, oklch(90% 0.1 130) 5%, oklch(95% 0.04 130) 100%)",
|
||||
"--theme-datagrid-background": "oklch(95% 0.04 130)",
|
||||
"--theme-datagrid-foreground": "oklch(20% 0.06 130)",
|
||||
"--theme-datagrid-foreground-grayed": "oklch(65% 0.05 130)",
|
||||
"--theme-datagrid-border-horizontal": "1px solid oklch(90% 0.1 130)",
|
||||
"--theme-datagrid-border-vertical": "1px solid oklch(95% 0.04 130)",
|
||||
"--theme-datagrid-cell-background": "oklch(97% 0.02 130)",
|
||||
"--theme-datagrid-headercell-background": "oklch(95% 0.04 130)",
|
||||
"--theme-datagrid-cell-background-alt": "oklch(95% 0.04 130)",
|
||||
"--theme-datagrid-cell-background-alt2": "oklch(90% 0.1 130)",
|
||||
"--theme-datagrid-filter-background": "oklch(90% 0.1 130)",
|
||||
"--theme-datagrid-filter-border": "1px solid oklch(85% 0.1 130)",
|
||||
"--theme-datagrid-filter-ok-background": "oklch(95% 0.1 135)",
|
||||
"--theme-datagrid-filter-error-background": "oklch(95% 0.12 30)",
|
||||
"--theme-datagrid-modified-row-background": "oklch(95% 0.1 135)",
|
||||
"--theme-datagrid-modified-cell-background": "oklch(90% 0.15 135)",
|
||||
"--theme-datagrid-inserted-row-background": "oklch(95% 0.1 110)",
|
||||
"--theme-datagrid-deleted-row-background": "oklch(95% 0.1 25)",
|
||||
"--theme-datagrid-selected-cell-background": "oklch(80% 0.1 130)",
|
||||
"--theme-datagrid-focused-cell-background": "oklch(75% 0.15 130)",
|
||||
"--theme-datagrid-focused-cell-border-horizontal": "1px solid oklch(70% 0.2 130)",
|
||||
"--theme-datagrid-focused-cell-border-vertical": "1px solid oklch(70% 0.2 130)",
|
||||
"--theme-datagrid-selected-point-marker": "oklch(50% 0.25 130)",
|
||||
"--theme-datagrid-corner-label-background": "oklch(75% 0.15 130)",
|
||||
"--theme-datagrid-corner-label-border": "1px solid oklch(70% 0.2 130)",
|
||||
"--theme-datagrid-detail-header-background": "oklch(85% 0.05 130)",
|
||||
"--theme-datagrid-detail-header-border": "1px solid oklch(80% 0.1 130)",
|
||||
"--theme-datagrid-cell-foreground-value-green": "oklch(45% 0.2 140)",
|
||||
"--theme-checkbox-check": "oklch(90% 0.1 130)",
|
||||
"--theme-checkbox-background": "oklch(40% 0.25 130)",
|
||||
"--theme-checkbox-border": "1px solid oklch(70% 0.15 130)",
|
||||
"--theme-checkbox-mark": "white",
|
||||
"--theme-checkbox-background-disabled": "oklch(95% 0.04 130)",
|
||||
"--theme-checkbox-background-disabled-before": "oklch(70% 0.15 130)",
|
||||
"--theme-checkbox-hover-not-disabled": "oklch(65% 0.05 130)",
|
||||
"--theme-checkbox-background-inherited": "oklch(85% 0.1 130)",
|
||||
"--theme-table-border": "1px solid oklch(85% 0.1 130)",
|
||||
"--theme-table-cell-background": "oklch(97% 0.02 130)",
|
||||
"--theme-table-cell-empty-background": "oklch(95% 0.04 130)",
|
||||
"--theme-table-cell-empty-foreground": "oklch(65% 0.05 130)",
|
||||
"--theme-table-header-background": "oklch(95% 0.04 130)",
|
||||
"--theme-table-selected-background": "oklch(75% 0.15 130)",
|
||||
"--theme-table-active-background": "oklch(80% 0.1 130)",
|
||||
"--theme-table-hover-background": "oklch(95% 0.04 130)",
|
||||
"--theme-table-added-background": "oklch(95% 0.1 110)",
|
||||
"--theme-table-changed-background": "oklch(95% 0.1 135)",
|
||||
"--theme-table-deleted-background": "oklch(95% 0.1 25)",
|
||||
"--theme-cell-active-border": "2px solid oklch(50% 0.25 130)",
|
||||
"--theme-object-header-background": "oklch(95% 0.04 130)",
|
||||
"--theme-modal-background": "oklch(97% 0.02 130)",
|
||||
"--theme-modal-header-background": "oklch(85% 0.1 130)",
|
||||
"--theme-modal-footer-background": "oklch(97% 0.02 130)",
|
||||
"--theme-modal-border": "1px solid oklch(85% 0.1 130)",
|
||||
"--theme-modal-overlay-background": "color-mix(in srgb, #124012 40%, transparent)",
|
||||
"--theme-modal-shadow": "0 20px 25px -5px color-mix(in srgb, #124012 10%, transparent)",
|
||||
"--theme-modal-close-hover-background": "oklch(70% 0.15 130)",
|
||||
"--theme-formbutton-foreground": "white",
|
||||
"--theme-formbutton-border": "1px solid oklch(40% 0.25 130)",
|
||||
"--theme-formbutton-border-hover": "1px solid oklch(50% 0.3 130)",
|
||||
"--theme-formbutton-border-active": "2px solid oklch(55% 0.35 130)",
|
||||
"--theme-formbutton-background": "oklch(40% 0.25 130)",
|
||||
"--theme-formbutton-background-disabled": "oklch(85% 0.1 130)",
|
||||
"--theme-formbutton-border-disabled": "1px solid oklch(85% 0.1 130)",
|
||||
"--theme-formbutton-foreground-disabled": "oklch(65% 0.05 130)",
|
||||
"--theme-formbutton-background-hover": "oklch(35% 0.3 130)",
|
||||
"--theme-formbutton-background-active": "oklch(35% 0.3 130)",
|
||||
"--theme-outlinebutton-foreground": "oklch(10% 0.06 130)",
|
||||
"--theme-outlinebutton-border": "1px solid oklch(40% 0.25 130)",
|
||||
"--theme-outlinebutton-hover-foreground": "oklch(40% 0.25 130)",
|
||||
"--theme-outlinebutton-hover-border": "2px solid oklch(50% 0.3 130)",
|
||||
"--theme-tabs-control-background": "oklch(95% 0.04 130)",
|
||||
"--theme-tabs-control-border": "1px solid oklch(90% 0.1 130)",
|
||||
"--theme-tabs-control-selected-background": "oklch(98% 0.01 130)",
|
||||
"--theme-tabs-control-selected-border": "2px solid oklch(50% 0.25 130)",
|
||||
"--theme-inline-tabs-border": "1px solid oklch(90% 0.1 130)",
|
||||
"--theme-inline-tabs-border-active": "2px solid oklch(50% 0.25 130)",
|
||||
"--theme-toolstrip-background": "oklch(97% 0.02 130)",
|
||||
"--theme-toolstrip-border": "1px solid oklch(90% 0.1 130)",
|
||||
"--theme-toolstrip-button-foreground": "oklch(27% 0.07 130)",
|
||||
"--theme-panel-border-subtle": "1px solid color-mix(in srgb, oklch(20% 0.06 130) 5%, transparent)",
|
||||
"--theme-panel-type-label-color": "oklch(65% 0.05 130)",
|
||||
"--theme-toolstrip-button-foreground-disabled": "oklch(65% 0.05 130)",
|
||||
"--theme-toolstrip-button-foreground-icon": "oklch(40% 0.12 130)",
|
||||
"--theme-toolstrip-button-background": "oklch(97% 0.02 130)",
|
||||
"--theme-toolstrip-button-background-hover": "oklch(95% 0.04 130)",
|
||||
"--theme-toolstrip-button-background-active": "oklch(90% 0.1 130)",
|
||||
"--theme-toolstrip-button-border": "1px solid oklch(90% 0.1 130)",
|
||||
"--theme-toolstrip-button-border-hover": "1px solid oklch(85% 0.1 130)",
|
||||
"--theme-toolstrip-button-border-disabled": "1px solid oklch(90% 0.1 130)",
|
||||
"--theme-toolstrip-button-split-separator-border": "1px solid oklch(85% 0.1 130)",
|
||||
"--theme-designer-background": "oklch(97% 0.02 130)",
|
||||
"--theme-designer-item-background": "oklch(95% 0.04 130)",
|
||||
"--theme-designer-selection-marker": "oklch(35% 0.3 130)",
|
||||
"--theme-designer-item-border": "1px solid oklch(90% 0.1 130)",
|
||||
"--theme-designer-stroke-color": "oklch(65% 0.05 130)",
|
||||
"--theme-designer-arrow-color": "oklch(27% 0.07 130)",
|
||||
"--theme-designer-select-reactangle-foreground": "oklch(50% 0.25 130)",
|
||||
"--theme-designer-header-background-1": "oklch(70% 0.15 130)",
|
||||
"--theme-designer-header-background-2": "oklch(70% 0.18 180)",
|
||||
"--theme-designer-header-background-3": "oklch(68% 0.15 100)",
|
||||
"--theme-designer-header-background-grayed": "oklch(85% 0.1 130)",
|
||||
"--theme-designer-close-background": "oklch(90% 0.1 130)",
|
||||
"--theme-designer-close-background-hover": "oklch(85% 0.1 130)",
|
||||
"--theme-designer-close-background-active": "oklch(70% 0.15 130)",
|
||||
"--theme-designer-drag-column-background": "oklch(90% 0.2 110)",
|
||||
"--theme-designer-select-column-background": "oklch(90% 0.1 130)",
|
||||
"--theme-statusbar-background": "oklch(40% 0.25 130)",
|
||||
"--theme-statusbar-foreground": "oklch(95% 0.04 130)",
|
||||
"--theme-statusbar-background-hover": "oklch(35% 0.3 130)",
|
||||
"--theme-statusbar-button-background": "oklch(85% 0.1 130)",
|
||||
"--theme-statusbar-button-foreground": "oklch(27% 0.07 130)",
|
||||
"--theme-statusbar-icon-error": "oklch(80% 0.1 25)",
|
||||
"--theme-statusbar-icon-ok": "oklch(85% 0.2 130)",
|
||||
"--theme-aichat-user-background": "oklch(93% 0.06 130)",
|
||||
"--theme-aichat-assistant-background": "oklch(95% 0.04 130)",
|
||||
"--theme-applog-details-background": "oklch(98% 0.01 130)",
|
||||
"--theme-input-border": "1px solid oklch(85% 0.1 130)",
|
||||
"--theme-input-border-hover": "1px solid oklch(70% 0.15 130)",
|
||||
"--theme-input-border-hover-color": "oklch(70% 0.15 130)",
|
||||
"--theme-input-border-focus": "1px solid oklch(50% 0.25 130)",
|
||||
"--theme-input-border-focus-color": "oklch(50% 0.25 130)",
|
||||
"--theme-input-border-disabled": "1px solid oklch(90% 0.1 130)",
|
||||
"--theme-input-background": "white",
|
||||
"--theme-input-foreground": "oklch(20% 0.06 130)",
|
||||
"--theme-input-placeholder": "oklch(65% 0.05 130)",
|
||||
"--theme-input-background-disabled": "oklch(95% 0.04 130)",
|
||||
"--theme-input-foreground-disabled": "oklch(65% 0.05 130)",
|
||||
"--theme-input-focus-ring": "0 0 0 3px color-mix(in srgb, oklch(50% 0.25 130) 10%, transparent)",
|
||||
"--theme-input-multi-clear-background": "oklch(90% 0.1 130)",
|
||||
"--theme-input-multi-clear-foreground": "oklch(40% 0.12 130)",
|
||||
"--theme-input-multi-clear-hover": "oklch(85% 0.1 130)",
|
||||
"--theme-input-shadow": "0 1px 2px 0 color-mix(in srgb, oklch(20% 0.06 130) 5%, transparent)",
|
||||
"--theme-input-shadow-hover": "0 4px 6px -2px color-mix(in srgb, oklch(20% 0.06 130) 8%, transparent)",
|
||||
"--theme-input-shadow-focus": "0 1px 2px 0 color-mix(in srgb, oklch(20% 0.06 130) 5%, transparent)",
|
||||
"--theme-input-inplace-select-shadow": "0 1px 10px 1px oklch(40% 0.12 130)",
|
||||
"--theme-color-selected-border": "2px solid oklch(27% 0.07 130)",
|
||||
"--theme-new-object-button-background": "oklch(90% 0.1 130)",
|
||||
"--theme-new-object-button-background-hover": "oklch(85% 0.1 130)",
|
||||
"--theme-status-valid-background": "oklch(95% 0.1 110)",
|
||||
"--theme-status-testing-background": "oklch(95% 0.1 135)",
|
||||
"--theme-status-error-background": "oklch(95% 0.1 25)",
|
||||
"--theme-status-unconfigured-background": "oklch(95% 0.04 130)",
|
||||
"--theme-status-untested-background": "oklch(94% 0.1 65)",
|
||||
"--theme-dropdown-icon-hover": "oklch(45% 0.3 130)",
|
||||
"--theme-icon-picker-background": "oklch(90% 0.1 130)",
|
||||
"--theme-icon-picker-border": "1px solid oklch(85% 0.1 130)",
|
||||
"--theme-icon-picker-hover": "oklch(85% 0.1 130)",
|
||||
"--theme-icon-picker-selected": "oklch(80% 0.15 130)",
|
||||
"--theme-dbkey-background": "oklch(98% 0.01 130)",
|
||||
"--theme-dbkey-border": "1px solid oklch(90% 0.1 130)",
|
||||
"--theme-dbkey-icon-hover": "oklch(70% 0.15 130)",
|
||||
"--theme-chip-background": "oklch(85% 0.1 130)",
|
||||
"--theme-titlebar-background": "oklch(85% 0.1 130)",
|
||||
"--theme-titlebar-button-hover": "oklch(70% 0.15 130)",
|
||||
"--theme-card-background": "oklch(90% 0.1 130)",
|
||||
"--theme-card-border": "1px solid oklch(85% 0.1 130)",
|
||||
"--theme-content-background-hover": "oklch(95% 0.04 130)",
|
||||
"--theme-admin-menu-item-hover": "oklch(95% 0.04 130)",
|
||||
"--theme-admin-menu-item-active": "oklch(85% 0.1 130)",
|
||||
"--theme-admin-menu-background": "oklch(90% 0.1 130)",
|
||||
"--theme-admin-menu-border": "1px solid oklch(90% 0.1 130)",
|
||||
"--theme-json-tree-string-color": "oklch(45% 0.3 110)",
|
||||
"--theme-json-tree-symbol-color": "oklch(45% 0.3 110)",
|
||||
"--theme-json-tree-boolean-color": "oklch(40% 0.25 130)",
|
||||
"--theme-json-tree-function-color": "oklch(40% 0.25 130)",
|
||||
"--theme-json-tree-number-color": "oklch(50% 0.3 130)",
|
||||
"--theme-json-tree-label-color": "oklch(55% 0.3 140)",
|
||||
"--theme-json-tree-arrow-color": "oklch(65% 0.05 130)",
|
||||
"--theme-json-tree-null-color": "oklch(65% 0.05 130)",
|
||||
"--theme-json-tree-undefined-color": "oklch(65% 0.05 130)",
|
||||
"--theme-json-tree-date-color": "oklch(65% 0.05 130)",
|
||||
"--theme-json-tree-deleted-background": "oklch(95% 0.1 25)",
|
||||
"--theme-json-tree-modified-background": "oklch(95% 0.1 135)",
|
||||
"--theme-json-tree-inserted-background": "oklch(95% 0.1 110)",
|
||||
"--theme-icon-blue": "oklch(40% 0.25 130)",
|
||||
"--theme-icon-green": "oklch(45% 0.2 140)",
|
||||
"--theme-icon-red": "oklch(40% 0.3 25)",
|
||||
"--theme-icon-gold": "oklch(50% 0.2 60)",
|
||||
"--theme-icon-yellow": "oklch(50% 0.15 80)",
|
||||
"--theme-icon-magenta": "oklch(45% 0.3 135)"
|
||||
}
|
||||
}
|
||||
15
e2e-tests/data/redis-db1.redis
Normal file
15
e2e-tests/data/redis-db1.redis
Normal file
@@ -0,0 +1,15 @@
|
||||
HSET "actor:1000" "first_name" "Sandra"
|
||||
HSET "actor:1000" "last_name" "Bullock"
|
||||
HSET "actor:1000" "date_of_birth" "1964"
|
||||
|
||||
HSET "actor:1001" "first_name" "Jon"
|
||||
HSET "actor:1001" "last_name" "Hamm"
|
||||
HSET "actor:1001" "date_of_birth" "1971"
|
||||
|
||||
HSET "actor:1002" "first_name" "Allison"
|
||||
HSET "actor:1002" "last_name" "Janney"
|
||||
HSET "actor:1002" "date_of_birth" "1959"
|
||||
|
||||
HSET "actor:1003" "first_name" "Steve"
|
||||
HSET "actor:1003" "last_name" "Coogan"
|
||||
HSET "actor:1003" "date_of_birth" "1965"
|
||||
14
e2e-tests/data/redis-db2.redis
Normal file
14
e2e-tests/data/redis-db2.redis
Normal file
@@ -0,0 +1,14 @@
|
||||
SET app:name "App"
|
||||
SET app:version "1.0.0"
|
||||
SET app:env "test"
|
||||
SET user:1:json "{\"id\":1,\"name\":\"Alice\",\"email\":\"alice@app.test\",\"roles\":[\"admin\",\"user\"],\"settings\":{\"theme\":\"dark\",\"language\":\"sk\"}}"
|
||||
SET user:2:json "{\"id\":2,\"name\":\"Bob\",\"email\":\"bob@app.test\",\"roles\":[\"user\"],\"settings\":{\"theme\":\"light\",\"language\":\"en\"}}"
|
||||
RPUSH queue:emails "welcome" "reset-password" "newsletter" "promotion" "weekly-digest"
|
||||
HSET user:alice name "Alice" email "alice@app.test" active "true" age "29" country "SK"
|
||||
HSET user:bob name "Bob" email "bob@app.test" active "false" age "34" country "CZ"
|
||||
SADD tags "app" "backend" "database" "redis" "test" "production"
|
||||
ZADD leaderboard 100 "alice" 250 "bob" 180 "carol" 90 "dave" 300 "eve"
|
||||
XADD events * type "login" userId "1" ip "127.0.0.1" device "web"
|
||||
XADD events * type "update-profile" userId "1" field "email" old "alice@app.test" new "alice@new.app"
|
||||
XADD events * type "login" userId "2" ip "10.0.0.5" device "mobile"
|
||||
XADD events * type "logout" userId "1" reason "manual"
|
||||
@@ -21,8 +21,8 @@ services:
|
||||
build: containers/mysql-ssh-login
|
||||
restart: always
|
||||
ports:
|
||||
- 16005:3306
|
||||
- "16015:22"
|
||||
- 16017:3306
|
||||
- "16012:22"
|
||||
|
||||
mysql-ssh-keyfile:
|
||||
build: containers/mysql-ssh-keyfile
|
||||
@@ -37,7 +37,7 @@ services:
|
||||
- "16009:5556"
|
||||
|
||||
mongo:
|
||||
image: mongo:4.0.12
|
||||
image: mongo:4.4.29
|
||||
restart: always
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: root
|
||||
|
||||
7
e2e-tests/env/browse-data/.env
vendored
7
e2e-tests/env/browse-data/.env
vendored
@@ -1,4 +1,4 @@
|
||||
CONNECTIONS=mysql,postgres,mongo,redis
|
||||
CONNECTIONS=mysql,postgres,mongo
|
||||
|
||||
LABEL_mysql=MySql-connection
|
||||
SERVER_mysql=localhost
|
||||
@@ -22,8 +22,3 @@ USER_mongo=root
|
||||
PASSWORD_mongo=Pwd2020Db
|
||||
PORT_mongo=16010
|
||||
ENGINE_mongo=mongo@dbgate-plugin-mongo
|
||||
|
||||
LABEL_redis=Redis-connection
|
||||
SERVER_redis=localhost
|
||||
ENGINE_redis=redis@dbgate-plugin-redis
|
||||
PORT_redis=16011
|
||||
|
||||
8
e2e-tests/env/charts/.env
vendored
Normal file
8
e2e-tests/env/charts/.env
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
CONNECTIONS=mysql
|
||||
|
||||
LABEL_mysql=MySql-connection
|
||||
SERVER_mysql=localhost
|
||||
USER_mysql=root
|
||||
PASSWORD_mysql=Pwd2020Db
|
||||
PORT_mysql=16004
|
||||
ENGINE_mysql=mysql@dbgate-plugin-mysql
|
||||
2
e2e-tests/env/cloud/.env
vendored
Normal file
2
e2e-tests/env/cloud/.env
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
ALLOW_DBGATE_PRIVATE_CLOUD=1
|
||||
REDIRECT_TO_DBGATE_CLOUD_LOGIN=1
|
||||
6
e2e-tests/env/redis/.env
vendored
Normal file
6
e2e-tests/env/redis/.env
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
CONNECTIONS=redis
|
||||
|
||||
LABEL_redis=Redis-connection
|
||||
SERVER_redis=localhost
|
||||
ENGINE_redis=redis@dbgate-plugin-redis
|
||||
PORT_redis=16011
|
||||
@@ -125,46 +125,6 @@ async function initMongoDatabase(dbname, inputDirectory) {
|
||||
// });
|
||||
}
|
||||
|
||||
async function initRedisDatabase(inputDirectory) {
|
||||
await dbgateApi.executeQuery({
|
||||
connection: {
|
||||
server: process.env.SERVER_redis,
|
||||
user: process.env.USER_redis,
|
||||
password: process.env.PASSWORD_redis,
|
||||
port: process.env.PORT_redis,
|
||||
engine: 'redis@dbgate-plugin-redis',
|
||||
},
|
||||
sql: 'FLUSHALL',
|
||||
});
|
||||
|
||||
for (const file of fs.readdirSync(inputDirectory)) {
|
||||
await dbgateApi.executeQuery({
|
||||
connection: {
|
||||
server: process.env.SERVER_redis,
|
||||
user: process.env.USER_redis,
|
||||
password: process.env.PASSWORD_redis,
|
||||
port: process.env.PORT_redis,
|
||||
engine: 'redis@dbgate-plugin-redis',
|
||||
database: 0,
|
||||
},
|
||||
sqlFile: path.join(inputDirectory, file),
|
||||
// logScriptItems: true,
|
||||
});
|
||||
}
|
||||
|
||||
// await dbgateApi.importDatabase({
|
||||
// connection: {
|
||||
// server: process.env.SERVER_postgres,
|
||||
// user: process.env.USER_postgres,
|
||||
// password: process.env.PASSWORD_postgres,
|
||||
// port: process.env.PORT_postgres,
|
||||
// database: dbname,
|
||||
// engine: 'postgres@dbgate-plugin-postgres',
|
||||
// },
|
||||
// inputFile,
|
||||
// });
|
||||
}
|
||||
|
||||
const baseDir = path.join(os.homedir(), '.dbgate');
|
||||
|
||||
async function copyFolder(source, target) {
|
||||
@@ -188,13 +148,16 @@ async function run() {
|
||||
await initMongoDatabase('MgChinook', path.resolve(path.join(__dirname, '../data/chinook-jsonl')));
|
||||
await initMongoDatabase('MgRivers', path.resolve(path.join(__dirname, '../data/rivers-jsonl')));
|
||||
|
||||
await initRedisDatabase(path.resolve(path.join(__dirname, '../data/redis')));
|
||||
|
||||
await copyFolder(
|
||||
path.resolve(path.join(__dirname, '../data/chinook-jsonl')),
|
||||
path.join(baseDir, 'archive-e2etests', 'default')
|
||||
);
|
||||
|
||||
await copyFolder(
|
||||
path.resolve(path.join(__dirname, '../data/chinook-jsonl')),
|
||||
path.join(baseDir, 'archive-e2etests', 'chinook-archive')
|
||||
);
|
||||
|
||||
await copyFolder(
|
||||
path.resolve(path.join(__dirname, '../data/files/query')),
|
||||
path.join(baseDir, 'files-e2etests', 'query')
|
||||
|
||||
101
e2e-tests/init/charts.js
Normal file
101
e2e-tests/init/charts.js
Normal file
@@ -0,0 +1,101 @@
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const fs = require('fs');
|
||||
|
||||
const baseDir = path.join(os.homedir(), '.dbgate');
|
||||
|
||||
const dbgateApi = require('dbgate-api');
|
||||
dbgateApi.initializeApiEnvironment();
|
||||
const dbgatePluginMysql = require('dbgate-plugin-mysql');
|
||||
dbgateApi.registerPlugins(dbgatePluginMysql);
|
||||
|
||||
async function copyFolder(source, target) {
|
||||
if (!fs.existsSync(target)) {
|
||||
fs.mkdirSync(target, { recursive: true });
|
||||
}
|
||||
for (const file of fs.readdirSync(source)) {
|
||||
fs.copyFileSync(path.join(source, file), path.join(target, file));
|
||||
}
|
||||
}
|
||||
|
||||
async function initMySqlDatabase(dbname, inputFile) {
|
||||
await dbgateApi.executeQuery({
|
||||
connection: {
|
||||
server: process.env.SERVER_mysql,
|
||||
user: process.env.USER_mysql,
|
||||
password: process.env.PASSWORD_mysql,
|
||||
port: process.env.PORT_mysql,
|
||||
engine: 'mysql@dbgate-plugin-mysql',
|
||||
},
|
||||
sql: `drop database if exists ${dbname}`,
|
||||
});
|
||||
|
||||
await dbgateApi.executeQuery({
|
||||
connection: {
|
||||
server: process.env.SERVER_mysql,
|
||||
user: process.env.USER_mysql,
|
||||
password: process.env.PASSWORD_mysql,
|
||||
port: process.env.PORT_mysql,
|
||||
engine: 'mysql@dbgate-plugin-mysql',
|
||||
},
|
||||
sql: `create database ${dbname}`,
|
||||
});
|
||||
|
||||
await dbgateApi.importDatabase({
|
||||
connection: {
|
||||
server: process.env.SERVER_mysql,
|
||||
user: process.env.USER_mysql,
|
||||
password: process.env.PASSWORD_mysql,
|
||||
port: process.env.PORT_mysql,
|
||||
database: dbname,
|
||||
engine: 'mysql@dbgate-plugin-mysql',
|
||||
},
|
||||
inputFile,
|
||||
});
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const connection = {
|
||||
server: process.env.SERVER_mysql,
|
||||
user: process.env.USER_mysql,
|
||||
password: process.env.PASSWORD_mysql,
|
||||
port: process.env.PORT_mysql,
|
||||
engine: 'mysql@dbgate-plugin-mysql',
|
||||
};
|
||||
|
||||
try {
|
||||
await dbgateApi.executeQuery({
|
||||
connection,
|
||||
sql: 'drop database if exists charts_sample',
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Failed to drop database', err);
|
||||
}
|
||||
|
||||
await dbgateApi.executeQuery({
|
||||
connection,
|
||||
sql: 'create database charts_sample',
|
||||
});
|
||||
|
||||
await dbgateApi.importDbFromFolder({
|
||||
connection: {
|
||||
...connection,
|
||||
database: 'charts_sample',
|
||||
},
|
||||
folder: path.resolve(path.join(__dirname, '../data/charts-sample')),
|
||||
});
|
||||
|
||||
await copyFolder(
|
||||
path.resolve(path.join(__dirname, '../data/files/sql')),
|
||||
path.join(baseDir, 'files-e2etests', 'sql')
|
||||
);
|
||||
|
||||
await copyFolder(
|
||||
path.resolve(path.join(__dirname, '../data/files/themes')),
|
||||
path.join(baseDir, 'files-e2etests', 'themes')
|
||||
);
|
||||
|
||||
await initMySqlDatabase('MyChinook', path.resolve(path.join(__dirname, '../data/chinook-mysql.sql')));
|
||||
}
|
||||
|
||||
dbgateApi.runScript(run);
|
||||
55
e2e-tests/init/redis.js
Normal file
55
e2e-tests/init/redis.js
Normal file
@@ -0,0 +1,55 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const dbgateApi = require('dbgate-api');
|
||||
dbgateApi.initializeApiEnvironment();
|
||||
const dbgatePluginRedis = require('dbgate-plugin-redis');
|
||||
dbgateApi.registerPlugins(dbgatePluginRedis);
|
||||
|
||||
async function initRedisDatabase() {
|
||||
await dbgateApi.executeQuery({
|
||||
connection: {
|
||||
server: process.env.SERVER_redis,
|
||||
user: process.env.USER_redis,
|
||||
password: process.env.PASSWORD_redis,
|
||||
port: process.env.PORT_redis,
|
||||
engine: 'redis@dbgate-plugin-redis',
|
||||
},
|
||||
sql: 'FLUSHALL',
|
||||
});
|
||||
|
||||
const files = [
|
||||
{
|
||||
file: path.resolve(__dirname, '../data/redis-db1.redis'),
|
||||
database: 0,
|
||||
},
|
||||
{
|
||||
file: path.resolve(__dirname, '../data/redis-db2.redis'),
|
||||
database: 1,
|
||||
},
|
||||
];
|
||||
|
||||
for (const { file, database } of files) {
|
||||
await dbgateApi.executeQuery({
|
||||
connection: {
|
||||
server: process.env.SERVER_redis,
|
||||
user: process.env.USER_redis,
|
||||
password: process.env.PASSWORD_redis,
|
||||
port: process.env.PORT_redis,
|
||||
engine: 'redis@dbgate-plugin-redis',
|
||||
database,
|
||||
},
|
||||
sqlFile: file,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
await initRedisDatabase();
|
||||
}
|
||||
|
||||
dbgateApi.runScript(run);
|
||||
|
||||
module.exports = {
|
||||
initRedisDatabase,
|
||||
};
|
||||
@@ -10,33 +10,39 @@
|
||||
"cypress-real-events": "^1.13.0",
|
||||
"env-cmd": "^10.1.0",
|
||||
"kill-port": "^2.0.1",
|
||||
"mocha-reporter-gha": "^1.1.1",
|
||||
"start-server-and-test": "^2.0.8"
|
||||
},
|
||||
"scripts": {
|
||||
"cy:open": "cypress open --config experimentalInteractiveRunEvents=true",
|
||||
|
||||
"cy:run:add-connection": "cypress run --spec cypress/e2e/add-connection.cy.js",
|
||||
"cy:run:portal": "cypress run --spec cypress/e2e/portal.cy.js",
|
||||
"cy:run:oauth": "cypress run --spec cypress/e2e/oauth.cy.js",
|
||||
"cy:run:browse-data": "cypress run --spec cypress/e2e/browse-data.cy.js",
|
||||
"cy:run:team": "cypress run --spec cypress/e2e/team.cy.js",
|
||||
"cy:run:multi-sql": "cypress run --spec cypress/e2e/multi-sql.cy.js",
|
||||
|
||||
"cy:run:cloud": "cypress run --spec cypress/e2e/cloud.cy.js",
|
||||
"cy:run:charts": "cypress run --spec cypress/e2e/charts.cy.js",
|
||||
"cy:run:redis": "cypress run --spec cypress/e2e/redis.cy.js",
|
||||
"start:add-connection": "node clearTestingData && cd .. && node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
"start:portal": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/portal/.env node e2e-tests/init/portal.js && env-cmd -f e2e-tests/env/portal/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
"start:oauth": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/oauth/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
"start:browse-data": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/browse-data/.env node e2e-tests/init/browse-data.js && env-cmd -f e2e-tests/env/browse-data/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
"start:team": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/team/.env node e2e-tests/init/team.js && env-cmd -f e2e-tests/env/team/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
"start:multi-sql": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/multi-sql/.env node e2e-tests/init/multi-sql.js && env-cmd -f e2e-tests/env/multi-sql/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
|
||||
"start:cloud": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/cloud/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
"start:charts": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/charts/.env node e2e-tests/init/charts.js && env-cmd -f e2e-tests/env/charts/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
"start:redis": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/redis/.env node e2e-tests/init/redis.js && env-cmd -f e2e-tests/env/redis/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
|
||||
"test:add-connection": "start-server-and-test start:add-connection http://localhost:3000 cy:run:add-connection",
|
||||
"test:portal": "start-server-and-test start:portal http://localhost:3000 cy:run:portal",
|
||||
"test:oauth": "start-server-and-test start:oauth http://localhost:3000 cy:run:oauth",
|
||||
"test:browse-data": "start-server-and-test start:browse-data http://localhost:3000 cy:run:browse-data",
|
||||
"test:team": "start-server-and-test start:team http://localhost:3000 cy:run:team",
|
||||
"test:multi-sql": "start-server-and-test start:multi-sql http://localhost:3000 cy:run:multi-sql",
|
||||
|
||||
"test": "yarn test:add-connection && yarn test:portal && yarn test:oauth && yarn test:browse-data && yarn test:team && yarn test:multi-sql",
|
||||
"test:cloud": "start-server-and-test start:cloud http://localhost:3000 cy:run:cloud",
|
||||
"test:charts": "start-server-and-test start:charts http://localhost:3000 cy:run:charts",
|
||||
"test:redis": "start-server-and-test start:redis http://localhost:3000 cy:run:redis",
|
||||
"test": "yarn test:add-connection && yarn test:portal && yarn test:oauth && yarn test:browse-data && yarn test:team && yarn test:multi-sql && yarn test:cloud && yarn test:charts && yarn test:redis",
|
||||
"test:ci": "yarn test"
|
||||
},
|
||||
"dependencies": {}
|
||||
|
||||
0
e2e-tests/screenshots/.gitkeep
Normal file
0
e2e-tests/screenshots/.gitkeep
Normal file
@@ -1 +0,0 @@
|
||||
Folder with screenshots
|
||||
@@ -2,6 +2,34 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@actions/core@^1.10.1":
|
||||
version "1.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.11.1.tgz#ae683aac5112438021588030efb53b1adb86f172"
|
||||
integrity sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==
|
||||
dependencies:
|
||||
"@actions/exec" "^1.1.1"
|
||||
"@actions/http-client" "^2.0.1"
|
||||
|
||||
"@actions/exec@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@actions/exec/-/exec-1.1.1.tgz#2e43f28c54022537172819a7cf886c844221a611"
|
||||
integrity sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==
|
||||
dependencies:
|
||||
"@actions/io" "^1.0.1"
|
||||
|
||||
"@actions/http-client@^2.0.1":
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.2.3.tgz#31fc0b25c0e665754ed39a9f19a8611fc6dab674"
|
||||
integrity sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==
|
||||
dependencies:
|
||||
tunnel "^0.0.6"
|
||||
undici "^5.25.4"
|
||||
|
||||
"@actions/io@^1.0.1":
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.3.tgz#4cdb6254da7962b07473ff5c335f3da485d94d71"
|
||||
integrity sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==
|
||||
|
||||
"@colors/colors@1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
|
||||
@@ -39,6 +67,11 @@
|
||||
debug "^3.1.0"
|
||||
lodash.once "^4.1.1"
|
||||
|
||||
"@fastify/busboy@^2.0.0":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d"
|
||||
integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==
|
||||
|
||||
"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
|
||||
version "9.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
|
||||
@@ -947,6 +980,13 @@ minimist@^1.2.8:
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||
|
||||
mocha-reporter-gha@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/mocha-reporter-gha/-/mocha-reporter-gha-1.1.1.tgz#e1248abd0769f55b57b36ccd7db2b0b6573d5adf"
|
||||
integrity sha512-CFbcgM56V4yWlbF91XuwrE6a5X/IqjVXTPefO7m8cY8Es8G1UhJ2KKOrk16AcSemRzVWXp2Fdy3bWJ7j45snWw==
|
||||
dependencies:
|
||||
"@actions/core" "^1.10.1"
|
||||
|
||||
ms@^2.1.1, ms@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
@@ -1292,6 +1332,11 @@ tunnel-agent@^0.6.0:
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
tunnel@^0.0.6:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c"
|
||||
integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==
|
||||
|
||||
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||
version "0.14.5"
|
||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||
@@ -1307,6 +1352,13 @@ undici-types@~6.20.0:
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
|
||||
integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
|
||||
|
||||
undici@^5.25.4:
|
||||
version "5.29.0"
|
||||
resolved "https://registry.yarnpkg.com/undici/-/undici-5.29.0.tgz#419595449ae3f2cdcba3580a2e8903399bd1f5a3"
|
||||
integrity sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==
|
||||
dependencies:
|
||||
"@fastify/busboy" "^2.0.0"
|
||||
|
||||
universalify@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d"
|
||||
|
||||
@@ -29,7 +29,7 @@ async function testDatabaseDiff(conn, driver, mangle, createObject = null) {
|
||||
driver,
|
||||
`create table ~t2 (
|
||||
~id int not null primary key,
|
||||
~t1_id int null references ~t1(~id)
|
||||
~t1_id int ${driver.dialect.implicitNullDeclaration ? '' : 'null'} references ~t1(~id)
|
||||
)`
|
||||
);
|
||||
|
||||
@@ -52,7 +52,7 @@ async function testDatabaseDiff(conn, driver, mangle, createObject = null) {
|
||||
}
|
||||
|
||||
describe('Alter database', () => {
|
||||
test.each(engines.filter(x => !x.skipReferences).map(engine => [engine.label, engine]))(
|
||||
test.each(engines.filter(x => !x.skipReferences && !x.skipDropReferences).map(engine => [engine.label, engine]))(
|
||||
'Drop referenced table - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testDatabaseDiff(conn, driver, db => {
|
||||
|
||||
@@ -12,6 +12,7 @@ const {
|
||||
} = require('dbgate-tools');
|
||||
|
||||
function pickImportantTableInfo(engine, table) {
|
||||
if (!table) return table;
|
||||
const props = ['columnName', 'defaultValue'];
|
||||
if (!engine.skipNullability) props.push('notNull');
|
||||
if (!engine.skipAutoIncrement) props.push('autoIncrement');
|
||||
@@ -25,6 +26,15 @@ function pickImportantTableInfo(engine, table) {
|
||||
.map(props =>
|
||||
_.omitBy(props, (v, k) => k == 'defaultValue' && v == 'NULL' && engine.setNullDefaultInsteadOfDrop)
|
||||
),
|
||||
|
||||
// TODO:
|
||||
foreignKeys: table.foreignKeys
|
||||
.sort((a, b) => a.refTableName.localeCompare(b.refTableName))
|
||||
.map(fk => ({
|
||||
constraintType: fk.constraintType,
|
||||
refTableName: fk.refTableName,
|
||||
columns: fk.columns.map(col => ({ columnName: col.columnName, refColumnName: col.refColumnName })),
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,7 +43,7 @@ function checkTableStructure(engine, t1, t2) {
|
||||
expect(pickImportantTableInfo(engine, t1)).toEqual(pickImportantTableInfo(engine, t2));
|
||||
}
|
||||
|
||||
async function testTableDiff(engine, conn, driver, mangle) {
|
||||
async function testTableDiff(engine, conn, driver, mangle, changedTable = 't1') {
|
||||
const initQuery = formatQueryWithoutParams(driver, `create table ~t0 (~id int not null primary key)`);
|
||||
await driver.query(conn, transformSqlForEngine(engine, initQuery));
|
||||
|
||||
@@ -60,23 +70,47 @@ async function testTableDiff(engine, conn, driver, mangle) {
|
||||
if (!engine.skipReferences) {
|
||||
const query = formatQueryWithoutParams(
|
||||
driver,
|
||||
`create table ~t2 (~id int not null primary key, ~fkval int null references ~t1(~col_ref))`
|
||||
`create table ~t2 (~id int not null primary key, ~fkval int ${
|
||||
driver.dialect.implicitNullDeclaration ? '' : 'null'
|
||||
} references ~t1(~col_ref))`
|
||||
);
|
||||
|
||||
await driver.query(conn, transformSqlForEngine(engine, query));
|
||||
}
|
||||
|
||||
const tget = x => x.tables.find(y => y.pureName == 't1');
|
||||
const structure1 = generateDbPairingId(extendDatabaseInfo(await driver.analyseFull(conn)));
|
||||
if (!engine.skipReferences) {
|
||||
const query = formatQueryWithoutParams(
|
||||
driver,
|
||||
`create table ~t3 (~id int not null primary key, ~fkval int ${
|
||||
driver.dialect.implicitNullDeclaration ? '' : 'null'
|
||||
})`
|
||||
);
|
||||
|
||||
await driver.query(conn, transformSqlForEngine(engine, query));
|
||||
}
|
||||
|
||||
const tget = x => x?.tables?.find(y => y.pureName == changedTable);
|
||||
const structure1Source = await driver.analyseFull(conn);
|
||||
const structure1 = generateDbPairingId(extendDatabaseInfo(structure1Source));
|
||||
let structure2 = _.cloneDeep(structure1);
|
||||
mangle(tget(structure2));
|
||||
structure2 = extendDatabaseInfo(structure2);
|
||||
|
||||
const { sql } = getAlterTableScript(tget(structure1), tget(structure2), {}, structure1, structure2, driver);
|
||||
|
||||
// sleep 1s - some engines have update datetime precision only to seconds
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
console.log('RUNNING ALTER SQL', driver.engine, ':', sql);
|
||||
|
||||
await driver.script(conn, sql);
|
||||
|
||||
// TODO:
|
||||
// if (!engine.skipIncrementalAnalysis) {
|
||||
// const structure2RealIncremental = await driver.analyseIncremental(conn, structure1Source);
|
||||
// checkTableStructure(engine, tget(structure2RealIncremental), tget(structure2));
|
||||
// }
|
||||
|
||||
const structure2Real = extendDatabaseInfo(await driver.analyseFull(conn));
|
||||
|
||||
checkTableStructure(engine, tget(structure2Real), tget(structure2));
|
||||
@@ -85,12 +119,13 @@ async function testTableDiff(engine, conn, driver, mangle) {
|
||||
|
||||
const TESTED_COLUMNS = ['col_pk', 'col_std', 'col_def', 'col_fk', 'col_ref', 'col_idx', 'col_uq'];
|
||||
// const TESTED_COLUMNS = ['col_pk'];
|
||||
// const TESTED_COLUMNS = ['col_fk'];
|
||||
// const TESTED_COLUMNS = ['col_idx'];
|
||||
// const TESTED_COLUMNS = ['col_def'];
|
||||
// const TESTED_COLUMNS = ['col_std'];
|
||||
// const TESTED_COLUMNS = ['col_ref'];
|
||||
|
||||
function create_engines_columns_source(engines) {
|
||||
function createEnginesColumnsSource(engines) {
|
||||
return _.flatten(
|
||||
engines.map(engine =>
|
||||
TESTED_COLUMNS.filter(col => col.endsWith('_pk') || !engine.skipNonPkRename)
|
||||
@@ -116,52 +151,80 @@ describe('Alter table', () => {
|
||||
})
|
||||
);
|
||||
|
||||
const columnsSource = create_engines_columns_source(engines);
|
||||
const dropableColumnsSrouce = columnsSource.filter(
|
||||
([_label, col, engine]) => !engine.skipPkDrop || !col.endsWith('_pk')
|
||||
test.each(engines.filter(i => i.supportTableComments).map(engine => [engine.label, engine]))(
|
||||
'Add comment to table - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testTableDiff(engine, conn, driver, tbl => {
|
||||
tbl.objectComment = 'Added table comment';
|
||||
});
|
||||
})
|
||||
);
|
||||
const hasDropableColumns = dropableColumnsSrouce.length > 0;
|
||||
|
||||
if (hasDropableColumns) {
|
||||
test.each(dropableColumnsSrouce)(
|
||||
'Drop column - %s - %s',
|
||||
testWrapper(async (conn, driver, column, engine) => {
|
||||
await testTableDiff(
|
||||
engine,
|
||||
conn,
|
||||
driver,
|
||||
tbl => (tbl.columns = tbl.columns.filter(x => x.columnName != column))
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
test.each(engines.filter(i => i.supportColumnComments).map(engine => [engine.label, engine]))(
|
||||
'Add comment to column - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testTableDiff(engine, conn, driver, tbl => {
|
||||
tbl.columns.push({
|
||||
columnName: 'added',
|
||||
columnComment: 'Added column comment',
|
||||
dataType: 'int',
|
||||
pairingId: crypto.randomUUID(),
|
||||
notNull: false,
|
||||
autoIncrement: false,
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const hasEnginesWithNullable = engines.filter(x => !x.skipNullable).length > 0;
|
||||
test.each(
|
||||
createEnginesColumnsSource(engines.filter(x => !x.skipDropColumn)).filter(
|
||||
([_label, col, engine]) => !engine.skipPkDrop || !col.endsWith('_pk')
|
||||
)
|
||||
)(
|
||||
'Drop column - %s - %s',
|
||||
testWrapper(async (conn, driver, column, engine) => {
|
||||
await testTableDiff(engine, conn, driver,
|
||||
tbl => {
|
||||
tbl.columns = tbl.columns.filter(x => x.columnName != column);
|
||||
tbl.foreignKeys = tbl.foreignKeys
|
||||
.map(fk => ({
|
||||
...fk,
|
||||
columns: fk.columns.filter(col => col.columnName != column)
|
||||
}))
|
||||
.filter(fk => fk.columns.length > 0);
|
||||
}
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
if (hasEnginesWithNullable) {
|
||||
const source = create_engines_columns_source(engines.filter(x => !x.skipNullable));
|
||||
test.each(
|
||||
createEnginesColumnsSource(engines.filter(x => !x.skipNullability && !x.skipChangeNullability)).filter(
|
||||
([_label, col]) => !col.endsWith('_pk')
|
||||
)
|
||||
)(
|
||||
'Change nullability - %s - %s',
|
||||
testWrapper(async (conn, driver, column, engine) => {
|
||||
await testTableDiff(
|
||||
engine,
|
||||
conn,
|
||||
driver,
|
||||
tbl => (tbl.columns = tbl.columns.map(x => (x.columnName == column ? { ...x, notNull: true } : x)))
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
test.each(source)(
|
||||
'Change nullability - %s - %s',
|
||||
testWrapper(async (conn, driver, column, engine) => {
|
||||
await testTableDiff(
|
||||
engine,
|
||||
conn,
|
||||
driver,
|
||||
tbl => (tbl.columns = tbl.columns.map(x => (x.columnName == column ? { ...x, notNull: true } : x)))
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
test.each(columnsSource)(
|
||||
test.each(createEnginesColumnsSource(engines.filter(x => !x.skipRenameColumn)))(
|
||||
'Rename column - %s - %s',
|
||||
testWrapper(async (conn, driver, column, engine) => {
|
||||
await testTableDiff(
|
||||
engine,
|
||||
conn,
|
||||
driver,
|
||||
tbl => (tbl.columns = tbl.columns.map(x => (x.columnName == column ? { ...x, columnName: 'col_renamed' } : x)))
|
||||
tbl => {
|
||||
tbl.columns = tbl.columns.map(x => (x.columnName == column ? { ...x, columnName: 'col_renamed' } : x));
|
||||
tbl.foreignKeys = tbl.foreignKeys.map(fk => ({...fk, columns: fk.columns.map(col => col.columnName == column ? { ...col, columnName: 'col_renamed' } : col)
|
||||
}));
|
||||
}
|
||||
);
|
||||
})
|
||||
);
|
||||
@@ -175,37 +238,74 @@ describe('Alter table', () => {
|
||||
})
|
||||
);
|
||||
|
||||
const enginesWithDefault = engines.filter(x => !x.skipDefaultValue);
|
||||
const hasEnginesWithDefault = enginesWithDefault.length > 0;
|
||||
test.each(engines.filter(x => !x.skipDefaultValue).map(engine => [engine.label, engine]))(
|
||||
'Add default value - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testTableDiff(engine, conn, driver, tbl => {
|
||||
tbl.columns.find(x => x.columnName == 'col_std').defaultValue = '123';
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
if (hasEnginesWithDefault) {
|
||||
test.each(enginesWithDefault.map(engine => [engine.label, engine]))(
|
||||
'Add default value - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testTableDiff(engine, conn, driver, tbl => {
|
||||
tbl.columns.find(x => x.columnName == 'col_std').defaultValue = '123';
|
||||
});
|
||||
})
|
||||
);
|
||||
test.each(engines.filter(x => !x.skipDefaultValue).map(engine => [engine.label, engine]))(
|
||||
'Unset default value - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testTableDiff(engine, conn, driver, tbl => {
|
||||
tbl.columns.find(x => x.columnName == 'col_def').defaultValue = undefined;
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
test.each(enginesWithDefault.map(engine => [engine.label, engine]))(
|
||||
'Unset default value - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testTableDiff(engine, conn, driver, tbl => {
|
||||
tbl.columns.find(x => x.columnName == 'col_def').defaultValue = undefined;
|
||||
});
|
||||
})
|
||||
);
|
||||
test.each(engines.filter(x => !x.skipDefaultValue).map(engine => [engine.label, engine]))(
|
||||
'Change default value - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testTableDiff(engine, conn, driver, tbl => {
|
||||
tbl.columns.find(x => x.columnName == 'col_def').defaultValue = '567';
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
test.each(enginesWithDefault.map(engine => [engine.label, engine]))(
|
||||
'Change default value - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testTableDiff(engine, conn, driver, tbl => {
|
||||
tbl.columns.find(x => x.columnName == 'col_def').defaultValue = '567';
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
test.each(engines.filter(x => !x.skipReferences).map(engine => [engine.label, engine]))(
|
||||
'Drop FK - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testTableDiff(
|
||||
engine,
|
||||
conn,
|
||||
driver,
|
||||
tbl => {
|
||||
tbl.foreignKeys = [];
|
||||
},
|
||||
't2'
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
test.each(engines.filter(x => !x.skipReferences).map(engine => [engine.label, engine]))(
|
||||
'Create FK - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testTableDiff(
|
||||
engine,
|
||||
conn,
|
||||
driver,
|
||||
tbl => {
|
||||
tbl.foreignKeys = [
|
||||
{
|
||||
constraintType: 'foreignKey',
|
||||
pureName: 't3',
|
||||
refTableName: 't1',
|
||||
columns: [
|
||||
{
|
||||
columnName: 'fkval',
|
||||
refColumnName: 'col_ref',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
},
|
||||
't3'
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
// test.each(engines.map(engine => [engine.label, engine]))(
|
||||
// 'Change autoincrement - %s',
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
const engines = require('../engines');
|
||||
const stream = require('stream');
|
||||
const { testWrapper } = require('../tools');
|
||||
const dataDuplicator = require('dbgate-api/src/shell/dataDuplicator');
|
||||
const { runCommandOnDriver, runQueryOnDriver } = require('dbgate-tools');
|
||||
|
||||
describe('Data duplicator', () => {
|
||||
test.each(engines.filter(x => !x.skipDataDuplicator).map(engine => [engine.label, engine]))(
|
||||
'Insert simple data - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't1',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', autoIncrement: true, notNull: true },
|
||||
{ columnName: 'val', dataType: 'varchar(50)' },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
})
|
||||
);
|
||||
runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't2',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', autoIncrement: true, notNull: true },
|
||||
{ columnName: 'val', dataType: 'varchar(50)' },
|
||||
{ columnName: 'valfk', dataType: 'int', notNull: true },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
foreignKeys: [{ refTableName: 't1', columns: [{ columnName: 'valfk', refColumnName: 'id' }] }],
|
||||
})
|
||||
);
|
||||
|
||||
const gett1 = () =>
|
||||
stream.Readable.from([
|
||||
{ __isStreamHeader: true, __isDynamicStructure: true },
|
||||
{ id: 1, val: 'v1' },
|
||||
{ id: 2, val: 'v2' },
|
||||
{ id: 3, val: 'v3' },
|
||||
]);
|
||||
const gett2 = () =>
|
||||
stream.Readable.from([
|
||||
{ __isStreamHeader: true, __isDynamicStructure: true },
|
||||
{ id: 1, val: 'v1', valfk: 1 },
|
||||
{ id: 2, val: 'v2', valfk: 2 },
|
||||
{ id: 3, val: 'v3', valfk: 3 },
|
||||
]);
|
||||
|
||||
await dataDuplicator({
|
||||
systemConnection: conn,
|
||||
driver,
|
||||
items: [
|
||||
{
|
||||
name: 't1',
|
||||
operation: 'copy',
|
||||
openStream: gett1,
|
||||
},
|
||||
{
|
||||
name: 't2',
|
||||
operation: 'copy',
|
||||
openStream: gett2,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await dataDuplicator({
|
||||
systemConnection: conn,
|
||||
driver,
|
||||
items: [
|
||||
{
|
||||
name: 't1',
|
||||
operation: 'copy',
|
||||
openStream: gett1,
|
||||
},
|
||||
{
|
||||
name: 't2',
|
||||
operation: 'copy',
|
||||
openStream: gett2,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t1`));
|
||||
expect(res1.rows[0].cnt.toString()).toEqual('6');
|
||||
|
||||
const res2 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t2`));
|
||||
expect(res2.rows[0].cnt.toString()).toEqual('6');
|
||||
})
|
||||
);
|
||||
|
||||
test.each(engines.filter(x => !x.skipDataDuplicator).map(engine => [engine.label, engine]))(
|
||||
'Skip nullable weak refs - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't1',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', notNull: true },
|
||||
{ columnName: 'val', dataType: 'varchar(50)' },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
})
|
||||
);
|
||||
runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't2',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', autoIncrement: true, notNull: true },
|
||||
{ columnName: 'val', dataType: 'varchar(50)' },
|
||||
{ columnName: 'valfk', dataType: 'int', notNull: false },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
foreignKeys: [{ refTableName: 't1', columns: [{ columnName: 'valfk', refColumnName: 'id' }] }],
|
||||
})
|
||||
);
|
||||
runCommandOnDriver(conn, driver, dmp => dmp.put("insert into ~t1 (~id, ~val) values (1, 'first')"));
|
||||
|
||||
const gett2 = () =>
|
||||
stream.Readable.from([
|
||||
{ __isStreamHeader: true, __isDynamicStructure: true },
|
||||
{ id: 1, val: 'v1', valfk: 1 },
|
||||
{ id: 2, val: 'v2', valfk: 2 },
|
||||
]);
|
||||
|
||||
await dataDuplicator({
|
||||
systemConnection: conn,
|
||||
driver,
|
||||
items: [
|
||||
{
|
||||
name: 't2',
|
||||
operation: 'copy',
|
||||
openStream: gett2,
|
||||
},
|
||||
],
|
||||
options: {
|
||||
setNullForUnresolvedNullableRefs: true,
|
||||
},
|
||||
});
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t1`));
|
||||
expect(res1.rows[0].cnt.toString()).toEqual('1');
|
||||
|
||||
const res2 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t2`));
|
||||
expect(res2.rows[0].cnt.toString()).toEqual('2');
|
||||
|
||||
const res3 = await runQueryOnDriver(conn, driver, dmp =>
|
||||
dmp.put(`select count(*) as ~cnt from ~t2 where ~valfk is not null`)
|
||||
);
|
||||
expect(res3.rows[0].cnt.toString()).toEqual('1');
|
||||
})
|
||||
);
|
||||
});
|
||||
354
integration-tests/__tests__/data-replicator.spec.js
Normal file
354
integration-tests/__tests__/data-replicator.spec.js
Normal file
@@ -0,0 +1,354 @@
|
||||
const engines = require('../engines');
|
||||
const stream = require('stream');
|
||||
const { testWrapper } = require('../tools');
|
||||
const dataReplicator = require('dbgate-api/src/shell/dataReplicator');
|
||||
const deployDb = require('dbgate-api/src/shell/deployDb');
|
||||
const storageModel = require('dbgate-api/src/storageModel');
|
||||
const { runCommandOnDriver, runQueryOnDriver, adaptDatabaseInfo } = require('dbgate-tools');
|
||||
|
||||
describe('Data replicator', () => {
|
||||
test.each(engines.filter(x => !x.skipDataReplicator).map(engine => [engine.label, engine]))(
|
||||
'Insert simple data - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't1',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', autoIncrement: true, notNull: true },
|
||||
{ columnName: 'val', dataType: 'varchar(50)' },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
})
|
||||
);
|
||||
runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't2',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', autoIncrement: true, notNull: true },
|
||||
{ columnName: 'val', dataType: 'varchar(50)' },
|
||||
{ columnName: 'valfk', dataType: 'int', notNull: true },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
foreignKeys: [{ refTableName: 't1', columns: [{ columnName: 'valfk', refColumnName: 'id' }] }],
|
||||
})
|
||||
);
|
||||
|
||||
const gett1 = () =>
|
||||
stream.Readable.from([
|
||||
{ __isStreamHeader: true, __isDynamicStructure: true },
|
||||
{ id: 1, val: 'v1' },
|
||||
{ id: 2, val: 'v2' },
|
||||
{ id: 3, val: 'v3' },
|
||||
]);
|
||||
const gett2 = () =>
|
||||
stream.Readable.from([
|
||||
{ __isStreamHeader: true, __isDynamicStructure: true },
|
||||
{ id: 1, val: 'v1', valfk: 1 },
|
||||
{ id: 2, val: 'v2', valfk: 2 },
|
||||
{ id: 3, val: 'v3', valfk: 3 },
|
||||
]);
|
||||
|
||||
await dataReplicator({
|
||||
systemConnection: conn,
|
||||
driver,
|
||||
items: [
|
||||
{
|
||||
name: 't1',
|
||||
createNew: true,
|
||||
openStream: gett1,
|
||||
},
|
||||
{
|
||||
name: 't2',
|
||||
createNew: true,
|
||||
openStream: gett2,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await dataReplicator({
|
||||
systemConnection: conn,
|
||||
driver,
|
||||
items: [
|
||||
{
|
||||
name: 't1',
|
||||
createNew: true,
|
||||
openStream: gett1,
|
||||
},
|
||||
{
|
||||
name: 't2',
|
||||
createNew: true,
|
||||
openStream: gett2,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t1`));
|
||||
expect(res1.rows[0].cnt.toString()).toEqual('6');
|
||||
|
||||
const res2 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t2`));
|
||||
expect(res2.rows[0].cnt.toString()).toEqual('6');
|
||||
})
|
||||
);
|
||||
|
||||
test.each(engines.filter(x => !x.skipDataReplicator).map(engine => [engine.label, engine]))(
|
||||
'Skip nullable weak refs - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't1',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', notNull: true },
|
||||
{ columnName: 'val', dataType: 'varchar(50)' },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
})
|
||||
);
|
||||
runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't2',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', autoIncrement: true, notNull: true },
|
||||
{ columnName: 'val', dataType: 'varchar(50)' },
|
||||
{ columnName: 'valfk', dataType: 'int', notNull: false },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
foreignKeys: [{ refTableName: 't1', columns: [{ columnName: 'valfk', refColumnName: 'id' }] }],
|
||||
})
|
||||
);
|
||||
runCommandOnDriver(conn, driver, dmp => dmp.put("insert into ~t1 (~id, ~val) values (1, 'first')"));
|
||||
|
||||
await dataReplicator({
|
||||
systemConnection: conn,
|
||||
driver,
|
||||
items: [
|
||||
{
|
||||
name: 't2',
|
||||
createNew: true,
|
||||
jsonArray: [
|
||||
{ id: 1, val: 'v1', valfk: 1 },
|
||||
{ id: 2, val: 'v2', valfk: 2 },
|
||||
],
|
||||
},
|
||||
],
|
||||
options: {
|
||||
setNullForUnresolvedNullableRefs: true,
|
||||
},
|
||||
});
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t1`));
|
||||
expect(res1.rows[0].cnt.toString()).toEqual('1');
|
||||
|
||||
const res2 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t2`));
|
||||
expect(res2.rows[0].cnt.toString()).toEqual('2');
|
||||
|
||||
const res3 = await runQueryOnDriver(conn, driver, dmp =>
|
||||
dmp.put(`select count(*) as ~cnt from ~t2 where ~valfk is not null`)
|
||||
);
|
||||
expect(res3.rows[0].cnt.toString()).toEqual('1');
|
||||
})
|
||||
);
|
||||
|
||||
test.each(engines.filter(x => !x.skipDataReplicator).map(engine => [engine.label, engine]))(
|
||||
'Import storage DB - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await deployDb({
|
||||
systemConnection: conn,
|
||||
driver,
|
||||
loadedDbModel: adaptDatabaseInfo(storageModel, driver),
|
||||
targetSchema: engine.defaultSchemaName,
|
||||
});
|
||||
|
||||
async function queryValue(sql) {
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(sql));
|
||||
return res1.rows[0].val?.toString();
|
||||
}
|
||||
|
||||
expect(await queryValue(`select count(*) as ~val from ~auth_methods`)).toEqual('2');
|
||||
expect(
|
||||
await queryValue(
|
||||
`select ~is_disabled as ~val from ~auth_methods where ~amoid='790ca4d2-7f01-4800-955b-d691b890cc50'`
|
||||
)
|
||||
).toBeTruthy();
|
||||
|
||||
const DB1 = {
|
||||
auth_methods: [
|
||||
{ id: -1, name: 'Anonymous', amoid: '790ca4d2-7f01-4800-955b-d691b890cc50', is_disabled: 0 },
|
||||
{ id: 10, name: 'OAuth', amoid: '4269b660-54b6-11ef-a3aa-a9021250bf4b' },
|
||||
],
|
||||
auth_methods_config: [{ id: 20, auth_method_id: 10, key: 'oauthClient', value: 'dbgate' }],
|
||||
config: [
|
||||
{ group: 'admin', key: 'encyptKey', value: '1234' },
|
||||
{ group: 'admin', key: 'adminPasswordState', value: 'set' },
|
||||
{ group: 'license', key: 'licenseKey', value: '123467' },
|
||||
],
|
||||
roles: [
|
||||
{ id: -3, name: 'superadmin' },
|
||||
{ id: -2, name: 'logged-user' },
|
||||
{ id: -1, name: 'anonymous-user' },
|
||||
],
|
||||
role_permissions: [
|
||||
{ id: 14, role_id: -1, permission: 'perm1' },
|
||||
{ id: 29, role_id: -1, permission: 'perm2' },
|
||||
{ id: 1, role_id: -1, permission: 'perm3' },
|
||||
],
|
||||
};
|
||||
|
||||
const DB2 = {
|
||||
auth_methods: [{ id: 10, name: 'My Auth', amoid: 'myauth1' }],
|
||||
auth_methods_config: [{ id: 20, auth_method_id: 10, key: 'my authClient', value: 'mydbgate' }],
|
||||
config: [],
|
||||
roles: [{ id: 1, name: 'test' }],
|
||||
role_permissions: [{ id: 14, role_id: 1, permission: 'permxx' }],
|
||||
};
|
||||
|
||||
function createDuplConfig(db) {
|
||||
return {
|
||||
systemConnection: conn,
|
||||
driver,
|
||||
items: [
|
||||
{
|
||||
name: 'auth_methods',
|
||||
findExisting: true,
|
||||
updateExisting: true,
|
||||
createNew: true,
|
||||
matchColumns: ['amoid'],
|
||||
jsonArray: db.auth_methods,
|
||||
},
|
||||
{
|
||||
name: 'auth_methods_config',
|
||||
findExisting: true,
|
||||
updateExisting: true,
|
||||
createNew: true,
|
||||
matchColumns: ['auth_method_id', 'key'],
|
||||
jsonArray: db.auth_methods_config,
|
||||
},
|
||||
{
|
||||
name: 'config',
|
||||
findExisting: true,
|
||||
updateExisting: true,
|
||||
createNew: true,
|
||||
matchColumns: ['group', 'key'],
|
||||
jsonArray: db.config,
|
||||
},
|
||||
{
|
||||
name: 'roles',
|
||||
findExisting: true,
|
||||
updateExisting: true,
|
||||
createNew: true,
|
||||
matchColumns: ['name'],
|
||||
jsonArray: db.roles,
|
||||
},
|
||||
{
|
||||
name: 'role_permissions',
|
||||
findExisting: true,
|
||||
updateExisting: true,
|
||||
createNew: true,
|
||||
deleteMissing: true,
|
||||
matchColumns: ['role_id', 'permission'],
|
||||
deleteRestrictionColumns: ['role_id'],
|
||||
jsonArray: db.role_permissions,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
await dataReplicator(createDuplConfig(DB1));
|
||||
|
||||
expect(
|
||||
await queryValue(
|
||||
`select ~is_disabled as ~val from ~auth_methods where ~amoid='790ca4d2-7f01-4800-955b-d691b890cc50'`
|
||||
)
|
||||
).toEqual('0');
|
||||
|
||||
expect(await queryValue(`select count(*) as ~val from ~auth_methods`)).toEqual('3');
|
||||
expect(await queryValue(`select count(*) as ~val from ~auth_methods_config`)).toEqual('1');
|
||||
expect(await queryValue(`select count(*) as ~val from ~config`)).toEqual('3');
|
||||
expect(await queryValue(`select ~value as ~val from ~auth_methods_config`)).toEqual('dbgate');
|
||||
expect(
|
||||
await queryValue(`select ~value as ~val from ~config where ~group='license' and ~key='licenseKey'`)
|
||||
).toEqual('123467');
|
||||
expect(await queryValue(`select count(*) as ~val from ~role_permissions`)).toEqual('3');
|
||||
|
||||
DB1.auth_methods_config[0].value = 'dbgate2';
|
||||
DB1.config[2].value = '567';
|
||||
DB1.role_permissions.splice(2, 1);
|
||||
|
||||
await dataReplicator(createDuplConfig(DB1));
|
||||
expect(await queryValue(`select count(*) as ~val from ~auth_methods_config`)).toEqual('1');
|
||||
expect(await queryValue(`select count(*) as ~val from ~config`)).toEqual('3');
|
||||
expect(await queryValue(`select ~value as ~val from ~auth_methods_config`)).toEqual('dbgate2');
|
||||
expect(
|
||||
await queryValue(`select ~value as ~val from ~config where ~group='license' and ~key='licenseKey'`)
|
||||
).toEqual('567');
|
||||
expect(await queryValue(`select count(*) as ~val from ~role_permissions`)).toEqual('2');
|
||||
|
||||
// now add DB2
|
||||
await dataReplicator(createDuplConfig(DB2));
|
||||
|
||||
expect(await queryValue(`select count(*) as ~val from ~auth_methods`)).toEqual('4');
|
||||
expect(await queryValue(`select count(*) as ~val from ~auth_methods_config`)).toEqual('2');
|
||||
expect(await queryValue(`select count(*) as ~val from ~role_permissions`)).toEqual('3');
|
||||
|
||||
DB1.role_permissions.splice(1, 1);
|
||||
await dataReplicator(createDuplConfig(DB1));
|
||||
expect(await queryValue(`select count(*) as ~val from ~role_permissions`)).toEqual('2');
|
||||
}),
|
||||
15 * 1000
|
||||
);
|
||||
|
||||
test.each(engines.filter(x => !x.skipDataReplicator).map(engine => [engine.label, engine]))(
|
||||
'Skip columns for update - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
runCommandOnDriver(conn, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't1',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', autoIncrement: true, notNull: true },
|
||||
{ columnName: 'key', dataType: 'varchar(50)', notNull: true },
|
||||
{ columnName: 'val', dataType: 'varchar(50)' },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
const getcfg = (v1 = 'v1') => ({
|
||||
systemConnection: conn,
|
||||
driver,
|
||||
items: [
|
||||
{
|
||||
name: 't1',
|
||||
matchColumns: ['key'],
|
||||
skipUpdateColumns: ['val'],
|
||||
findExisting: true,
|
||||
updateExisting: true,
|
||||
createNew: true,
|
||||
jsonArray: [
|
||||
{ key: '1', val: v1 },
|
||||
{ key: '2', val: 'v2' },
|
||||
{ key: '3', val: 'v3' },
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await dataReplicator(getcfg('v1'));
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select ~val from ~t1 where ~key='1'`));
|
||||
expect(res1.rows[0].val).toEqual('v1');
|
||||
|
||||
await dataReplicator(getcfg('v2'));
|
||||
const res2 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select ~val from ~t1 where ~key='1'`));
|
||||
expect(res2.rows[0].val).toEqual('v1');
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -51,7 +51,8 @@ describe('DB Import/export', () => {
|
||||
await copyStream(reader, writer);
|
||||
|
||||
const res = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t1`));
|
||||
expect(res.rows[0].cnt.toString()).toEqual('6');
|
||||
const cnt = parseInt(res.rows[0].cnt.toString());
|
||||
expect(cnt).toEqual(6);
|
||||
})
|
||||
);
|
||||
|
||||
@@ -75,7 +76,8 @@ describe('DB Import/export', () => {
|
||||
await copyStream(reader, writer);
|
||||
|
||||
const res = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t1`));
|
||||
expect(res.rows[0].cnt.toString()).toEqual('6');
|
||||
const cnt = parseInt(res.rows[0].cnt.toString());
|
||||
expect(cnt).toEqual(6);
|
||||
})
|
||||
);
|
||||
|
||||
@@ -103,10 +105,12 @@ describe('DB Import/export', () => {
|
||||
await copyStream(reader2, writer2);
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t1`));
|
||||
expect(res1.rows[0].cnt.toString()).toEqual('6');
|
||||
const cnt = parseInt(res1.rows[0].cnt.toString());
|
||||
expect(cnt).toEqual(6);
|
||||
|
||||
const res2 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~t2`));
|
||||
expect(res2.rows[0].cnt.toString()).toEqual('6');
|
||||
const cnt2 = parseInt(res2.rows[0].cnt.toString());
|
||||
expect(cnt2).toEqual(6);
|
||||
})
|
||||
);
|
||||
const enginesWithDumpFile = engines.filter(x => x.dumpFile);
|
||||
@@ -192,7 +196,8 @@ describe('DB Import/export', () => {
|
||||
});
|
||||
|
||||
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~categories`));
|
||||
expect(res1.rows[0].cnt.toString()).toEqual('4');
|
||||
const cnt1 = parseInt(res1.rows[0].cnt.toString());
|
||||
expect(cnt1).toEqual(4);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@@ -106,7 +106,9 @@ async function testDatabaseDeploy(engine, conn, driver, dbModelsYaml, options) {
|
||||
|
||||
for (const loadedDbModel of dbModelsYaml) {
|
||||
if (_.isString(loadedDbModel)) {
|
||||
await driver.script(conn, formatQueryWithoutParams(driver, loadedDbModel));
|
||||
await driver.script(conn, formatQueryWithoutParams(driver, loadedDbModel), {
|
||||
useTransaction: engine.runDeployInTransaction,
|
||||
});
|
||||
} else {
|
||||
const { sql, isEmpty } = await generateDeploySql({
|
||||
systemConnection: conn.isPreparedOnly ? undefined : conn,
|
||||
@@ -131,6 +133,7 @@ async function testDatabaseDeploy(engine, conn, driver, dbModelsYaml, options) {
|
||||
driver,
|
||||
loadedDbModel: convertModelToEngine(loadedDbModel, driver),
|
||||
dbdiffOptionsExtra,
|
||||
useTransaction: engine.runDeployInTransaction,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -606,7 +609,7 @@ describe('Deploy database', () => {
|
||||
})
|
||||
);
|
||||
|
||||
test.each(engines.filter(i => !i.skipDeploy).map(engine => [engine.label, engine]))(
|
||||
test.each(engines.filter(i => !i.skipDeploy && !i.skipRenameTable).map(engine => [engine.label, engine]))(
|
||||
'Mark table removed - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testDatabaseDeploy(engine, conn, driver, [[T1], [], []], {
|
||||
@@ -822,7 +825,7 @@ describe('Deploy database', () => {
|
||||
})
|
||||
);
|
||||
|
||||
test.each(engines.filter(i => !i.skipDeploy).map(engine => [engine.label, engine]))(
|
||||
test.each(engines.filter(i => !i.skipDeploy && !i.skipRenameTable).map(engine => [engine.label, engine]))(
|
||||
'Mark table removed, one remains - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testDatabaseDeploy(engine, conn, driver, [[T1, T2], [T2], [T2]], {
|
||||
|
||||
@@ -20,7 +20,11 @@ function flatSourceParameters() {
|
||||
}
|
||||
|
||||
function flatSourceTriggers() {
|
||||
return _.flatten(engines.map(engine => (engine.triggers || []).map(trigger => [engine.label, trigger, engine])));
|
||||
return _.flatten(
|
||||
engines
|
||||
.filter(engine => !engine.skipTriggers)
|
||||
.map(engine => (engine.triggers || []).map(trigger => [engine.label, trigger, engine]))
|
||||
);
|
||||
}
|
||||
|
||||
function flatSourceSchedulerEvents() {
|
||||
|
||||
@@ -49,6 +49,32 @@ class StreamHandler {
|
||||
}
|
||||
}
|
||||
|
||||
class BinaryTestStreamHandler {
|
||||
constructor(resolve, reject, expectedValue) {
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
this.expectedValue = expectedValue;
|
||||
this.rowsReceived = [];
|
||||
}
|
||||
row(row) {
|
||||
try {
|
||||
this.rowsReceived.push(row);
|
||||
if (this.expectedValue) {
|
||||
expect(row).toEqual(this.expectedValue);
|
||||
}
|
||||
} catch (error) {
|
||||
this.reject(error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
recordset(columns) {}
|
||||
done(result) {
|
||||
this.resolve(this.rowsReceived);
|
||||
}
|
||||
info(msg) {}
|
||||
}
|
||||
|
||||
|
||||
function executeStreamItem(driver, conn, sql) {
|
||||
return new Promise(resolve => {
|
||||
const handler = new StreamHandler(resolve);
|
||||
@@ -183,12 +209,12 @@ describe('Query', () => {
|
||||
{ discardResult: true }
|
||||
);
|
||||
const res = await runQueryOnDriver(conn, driver, dmp => dmp.put('SELECT COUNT(*) AS ~cnt FROM ~t1'));
|
||||
// console.log(res);
|
||||
expect(res.rows[0].cnt == 3).toBeTruthy();
|
||||
const cnt = parseInt(res.rows[0].cnt);
|
||||
expect(cnt).toEqual(3);
|
||||
})
|
||||
);
|
||||
|
||||
test.each(engines.filter(x => !x.skipDataDuplicator).map(engine => [engine.label, engine]))(
|
||||
test.each(engines.filter(x => !x.skipDataReplicator).map(engine => [engine.label, engine]))(
|
||||
'Select scope identity - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await runCommandOnDriver(conn, driver, dmp =>
|
||||
@@ -223,4 +249,51 @@ describe('Query', () => {
|
||||
expect(row[keys[0]] == 1).toBeTruthy();
|
||||
})
|
||||
);
|
||||
|
||||
test.each(engines.filter(x => x.binaryDataType).map(engine => [engine.label, engine]))(
|
||||
'Binary - %s',
|
||||
testWrapper(async (dbhan, driver, engine) => {
|
||||
await runCommandOnDriver(dbhan, driver, dmp =>
|
||||
dmp.createTable({
|
||||
pureName: 't1',
|
||||
columns: [
|
||||
{ columnName: 'id', dataType: 'int', notNull: true, autoIncrement: true },
|
||||
{ columnName: 'val', dataType: engine.binaryDataType },
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'id' }],
|
||||
},
|
||||
})
|
||||
);
|
||||
const structure = await driver.analyseFull(dbhan);
|
||||
const table = structure.tables.find(x => x.pureName == 't1');
|
||||
|
||||
const dmp = driver.createDumper();
|
||||
dmp.putCmd("INSERT INTO ~t1 (~val) VALUES (%v)", {
|
||||
$binary: { base64: 'iVBORw0KWgo=' },
|
||||
});
|
||||
await driver.query(dbhan, dmp.s, {discardResult: true});
|
||||
|
||||
const dmp2 = driver.createDumper();
|
||||
dmp2.put('SELECT ~val FROM ~t1');
|
||||
const res = await driver.query(dbhan, dmp2.s);
|
||||
|
||||
const row = res.rows[0];
|
||||
const keys = Object.keys(row);
|
||||
expect(keys.length).toEqual(1);
|
||||
expect(row[keys[0]]).toEqual({$binary: {base64: 'iVBORw0KWgo='}});
|
||||
|
||||
const res2 = await driver.readQuery(dbhan, dmp2.s);
|
||||
const rows = await Array.fromAsync(res2);
|
||||
const rowsVal = rows.filter(r => r.val != null);
|
||||
|
||||
expect(rowsVal.length).toEqual(1);
|
||||
expect(rowsVal[0].val).toEqual({$binary: {base64: 'iVBORw0KWgo='}});
|
||||
|
||||
const res3 = await new Promise((resolve, reject) => {
|
||||
const handler = new BinaryTestStreamHandler(resolve, reject, {val: {$binary: {base64: 'iVBORw0KWgo='}}});
|
||||
driver.stream(dbhan, dmp2.s, handler);
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@@ -33,7 +33,9 @@ describe('Schema tests', () => {
|
||||
expect(schemas2.find(x => x.schemaName == 'myschema')).toBeTruthy();
|
||||
expect(schemas2.length).toEqual(count + 1);
|
||||
expect(schemas2.find(x => x.isDefault).schemaName).toEqual(engine.defaultSchemaName);
|
||||
expect(structure2).toBeNull();
|
||||
if (!engine.skipIncrementalAnalysis) {
|
||||
expect(structure2).toBeNull();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
@@ -51,7 +53,9 @@ describe('Schema tests', () => {
|
||||
const structure2 = await driver.analyseIncremental(conn, structure1);
|
||||
const schemas2 = await driver.listSchemas(conn);
|
||||
expect(schemas2.find(x => x.schemaName == 'myschema')).toBeFalsy();
|
||||
expect(structure2).toBeNull();
|
||||
if (!engine.skipIncrementalAnalysis) {
|
||||
expect(structure2).toBeNull();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -64,6 +64,40 @@ describe('Table create', () => {
|
||||
})
|
||||
);
|
||||
|
||||
test.each(
|
||||
engines.filter(i => i.supportTableComments || i.supportColumnComments).map(engine => [engine.label, engine])
|
||||
)(
|
||||
'Simple table with comment - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
await testTableCreate(engine, conn, driver, {
|
||||
...(engine.supportTableComments && {
|
||||
schemaName: 'dbo',
|
||||
objectComment: 'table comment',
|
||||
}),
|
||||
...(engine.defaultSchemaName && {
|
||||
schemaName: engine.defaultSchemaName,
|
||||
}),
|
||||
columns: [
|
||||
{
|
||||
columnName: 'col1',
|
||||
dataType: 'int',
|
||||
pureName: 'tested',
|
||||
...(engine.skipNullability ? {} : { notNull: true }),
|
||||
...(engine.supportColumnComments && {
|
||||
columnComment: 'column comment',
|
||||
}),
|
||||
...(engine.defaultSchemaName && {
|
||||
schemaName: engine.defaultSchemaName,
|
||||
}),
|
||||
},
|
||||
],
|
||||
primaryKey: {
|
||||
columns: [{ columnName: 'col1' }],
|
||||
},
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
test.each(engines.filter(x => !x.skipIndexes).map(engine => [engine.label, engine]))(
|
||||
'Table with index - %s',
|
||||
testWrapper(async (conn, driver, engine) => {
|
||||
|
||||
@@ -8,14 +8,25 @@ services:
|
||||
# ports:
|
||||
# - 15000:5432
|
||||
#
|
||||
# mariadb:
|
||||
# image: mariadb
|
||||
# command: --default-authentication-plugin=mysql_native_password
|
||||
# restart: always
|
||||
# ports:
|
||||
# - 15004:3306
|
||||
# environment:
|
||||
# - MYSQL_ROOT_PASSWORD=Pwd2020Db
|
||||
mariadb:
|
||||
image: mariadb
|
||||
command: --default-authentication-plugin=mysql_native_password
|
||||
restart: always
|
||||
ports:
|
||||
- 15004:3306
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=Pwd2020Db
|
||||
|
||||
db2:
|
||||
image: icr.io/db2_community/db2:11.5.8.0
|
||||
privileged: true
|
||||
ports:
|
||||
- "15055:50000"
|
||||
environment:
|
||||
LICENSE: accept
|
||||
DB2INST1_PASSWORD: Pwd2020Db
|
||||
DBNAME: testdb
|
||||
DB2INSTANCE: db2inst1
|
||||
|
||||
# mysql:
|
||||
# image: mysql:8.0.18
|
||||
@@ -25,7 +36,7 @@ services:
|
||||
# - 15001:3306
|
||||
# environment:
|
||||
# - MYSQL_ROOT_PASSWORD=Pwd2020Db
|
||||
#
|
||||
|
||||
|
||||
# cassandradb:
|
||||
# image: cassandra:5.0.2
|
||||
@@ -33,7 +44,7 @@ services:
|
||||
# - 15942:9042
|
||||
#
|
||||
# clickhouse:
|
||||
# image: bitnami/clickhouse:24.8.4
|
||||
# image: bitnamilegacy/clickhouse:24.8.4
|
||||
# restart: always
|
||||
# ports:
|
||||
# - 15005:8123
|
||||
@@ -81,11 +92,36 @@ services:
|
||||
# ports:
|
||||
# - 15006:1521
|
||||
|
||||
libsql:
|
||||
image: ghcr.io/tursodatabase/libsql-server:latest
|
||||
platform: linux/amd64
|
||||
# libsql:
|
||||
# image: ghcr.io/tursodatabase/libsql-server:latest
|
||||
# platform: linux/amd64
|
||||
# ports:
|
||||
# - '8080:8080'
|
||||
# - '5002:5001'
|
||||
# volumes:
|
||||
# - ./data/libsql:/var/lib/sqld
|
||||
|
||||
firebird:
|
||||
image: firebirdsql/firebird:latest
|
||||
container_name: firebird-db
|
||||
environment:
|
||||
- FIREBIRD_DATABASE=mydatabase.fdb
|
||||
- FIREBIRD_USER=dbuser
|
||||
- FIREBIRD_PASSWORD=dbpassword
|
||||
- ISC_PASSWORD=masterkey
|
||||
- FIREBIRD_TRACE=false
|
||||
- FIREBIRD_USE_LEGACY_AUTH=true
|
||||
ports:
|
||||
- '8080:8080'
|
||||
- '5002:5001'
|
||||
- '3050:3050'
|
||||
volumes:
|
||||
- ./data/libsql:/var/lib/sqld
|
||||
- firebird-data:/firebird/data
|
||||
- ./firebird.conf:/firebird/firebird.conf # Mount custom config file
|
||||
healthcheck:
|
||||
test: ['CMD', 'nc', '-z', 'localhost', '3050']
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
volumes:
|
||||
firebird-data:
|
||||
|
||||
@@ -44,6 +44,7 @@ const mysqlEngine = {
|
||||
supportRenameSqlObject: false,
|
||||
dbSnapshotBySeconds: true,
|
||||
dumpFile: 'data/chinook-mysql.sql',
|
||||
binaryDataType: 'blob',
|
||||
dumpChecks: [
|
||||
{
|
||||
sql: 'select count(*) as res from genre',
|
||||
@@ -186,6 +187,7 @@ const mariaDbEngine = {
|
||||
/** @type {import('dbgate-types').TestEngineInfo} */
|
||||
const postgreSqlEngine = {
|
||||
label: 'PostgreSQL',
|
||||
skipIncrementalAnalysis: true,
|
||||
connection: {
|
||||
engine: 'postgres@dbgate-plugin-postgres',
|
||||
password: 'Pwd2020Db',
|
||||
@@ -216,6 +218,7 @@ const postgreSqlEngine = {
|
||||
supportSchemas: true,
|
||||
supportRenameSqlObject: true,
|
||||
defaultSchemaName: 'public',
|
||||
binaryDataType: 'bytea',
|
||||
dumpFile: 'data/chinook-postgre.sql',
|
||||
dumpChecks: [
|
||||
{
|
||||
@@ -443,7 +446,10 @@ const sqlServerEngine = {
|
||||
supportSchemas: true,
|
||||
supportRenameSqlObject: true,
|
||||
defaultSchemaName: 'dbo',
|
||||
supportTableComments: true,
|
||||
supportColumnComments: true,
|
||||
// skipSeparateSchemas: true,
|
||||
binaryDataType: 'varbinary(100)',
|
||||
triggers: [
|
||||
{
|
||||
testName: 'triggers before each row',
|
||||
@@ -504,6 +510,7 @@ const sqliteEngine = {
|
||||
},
|
||||
},
|
||||
],
|
||||
binaryDataType: 'blob',
|
||||
};
|
||||
|
||||
const libsqlFileEngine = {
|
||||
@@ -551,7 +558,7 @@ const clickhouseEngine = {
|
||||
skipUnique: true,
|
||||
skipAutoIncrement: true,
|
||||
skipPkColumnTesting: true,
|
||||
skipDataDuplicator: true,
|
||||
skipDataReplicator: true,
|
||||
skipStringLength: true,
|
||||
alterTableAddColumnSyntax: true,
|
||||
dbSnapshotBySeconds: true,
|
||||
@@ -617,6 +624,7 @@ const oracleEngine = {
|
||||
},
|
||||
},
|
||||
],
|
||||
binaryDataType: 'blob',
|
||||
};
|
||||
|
||||
/** @type {import('dbgate-types').TestEngineInfo} */
|
||||
@@ -643,7 +651,7 @@ const cassandraEngine = {
|
||||
skipOrderBy: true,
|
||||
skipAutoIncrement: true,
|
||||
skipDataModifications: true,
|
||||
skipDataDuplicator: true,
|
||||
skipDataReplicator: true,
|
||||
skipDeploy: true,
|
||||
skipImportModel: true,
|
||||
|
||||
@@ -654,6 +662,82 @@ const cassandraEngine = {
|
||||
objects: [],
|
||||
};
|
||||
|
||||
/** @type {import('dbgate-types').TestEngineInfo} */
|
||||
const duckdbEngine = {
|
||||
label: 'DuckDB',
|
||||
generateDbFile: true,
|
||||
defaultSchemaName: 'main',
|
||||
connection: {
|
||||
engine: 'duckdb@dbgate-plugin-duckdb',
|
||||
},
|
||||
objects: [views],
|
||||
skipOnCI: false,
|
||||
skipChangeColumn: true,
|
||||
// skipIndexes: true,
|
||||
skipStringLength: true,
|
||||
skipTriggers: true,
|
||||
skipDataReplicator: true,
|
||||
skipAutoIncrement: true,
|
||||
skipDropColumn: true,
|
||||
skipRenameColumn: true,
|
||||
skipChangeNullability: true,
|
||||
skipDeploy: true,
|
||||
supportRenameSqlObject: true,
|
||||
skipIncrementalAnalysis: true,
|
||||
skipDefaultValue: true,
|
||||
skipDropReferences: true,
|
||||
};
|
||||
|
||||
/** @type {import('dbgate-types').TestEngineInfo} */
|
||||
const firebirdEngine = {
|
||||
label: 'Firebird',
|
||||
generateDbFile: true,
|
||||
databaseFileLocationOnServer: '/var/lib/firebird/data/',
|
||||
defaultSchemaName: 'main',
|
||||
connection: {
|
||||
engine: 'firebird@dbgate-plugin-firebird',
|
||||
server: 'localhost',
|
||||
port: 3050,
|
||||
// databaseUrl: '/var/lib/firebird/data/mydatabase.fdb',
|
||||
// databaseFile: '/var/lib/firebird/data/mydatabase.fdb',
|
||||
user: 'SYSDBA',
|
||||
password: 'masterkey',
|
||||
},
|
||||
objects: [],
|
||||
triggers: [
|
||||
{
|
||||
testName: 'triggers after each row',
|
||||
create: `CREATE OR ALTER TRIGGER ~obj1 AFTER INSERT ON ~t1 AS BEGIN END;`,
|
||||
drop: 'DROP TRIGGER ~obj1;',
|
||||
objectTypeField: 'triggers',
|
||||
expected: {
|
||||
pureName: 'obj1',
|
||||
tableName: 't1',
|
||||
eventType: 'INSERT',
|
||||
triggerTiming: 'AFTER',
|
||||
},
|
||||
},
|
||||
],
|
||||
skipOnCI: false,
|
||||
runDeployInTransaction: true,
|
||||
skipDataModifications: true,
|
||||
skipChangeColumn: true,
|
||||
// skipIndexes: true,
|
||||
// skipStringLength: true,
|
||||
// skipTriggers: true,
|
||||
skipDataReplicator: true,
|
||||
skipAutoIncrement: true,
|
||||
// skipDropColumn: true,
|
||||
skipRenameColumn: true,
|
||||
// skipChangeNullability: true,
|
||||
// skipDeploy: true,
|
||||
// supportRenameSqlObject: true,
|
||||
skipIncrementalAnalysis: true,
|
||||
skipRenameTable: true,
|
||||
// skipDefaultValue: true,
|
||||
skipDropReferences: true,
|
||||
};
|
||||
|
||||
const enginesOnCi = [
|
||||
// all engines, which would be run on GitHub actions
|
||||
mysqlEngine,
|
||||
@@ -667,6 +751,8 @@ const enginesOnCi = [
|
||||
clickhouseEngine,
|
||||
oracleEngine,
|
||||
cassandraEngine,
|
||||
duckdbEngine,
|
||||
firebirdEngine,
|
||||
];
|
||||
|
||||
const enginesOnLocal = [
|
||||
@@ -674,14 +760,16 @@ const enginesOnLocal = [
|
||||
// cassandraEngine,
|
||||
// mysqlEngine,
|
||||
// mariaDbEngine,
|
||||
// postgreSqlEngine,
|
||||
// sqlServerEngine,
|
||||
postgreSqlEngine,
|
||||
//sqlServerEngine,
|
||||
// sqliteEngine,
|
||||
// cockroachDbEngine,
|
||||
// clickhouseEngine,
|
||||
// libsqlFileEngine,
|
||||
libsqlWsEngine,
|
||||
// oracleEngine,
|
||||
// libsqlWsEngine,
|
||||
//oracleEngine,
|
||||
// duckdbEngine,
|
||||
//firebirdEngine,
|
||||
];
|
||||
|
||||
/** @type {import('dbgate-types').TestEngineInfo[] & Record<string, import('dbgate-types').TestEngineInfo>} */
|
||||
@@ -696,3 +784,7 @@ module.exports.cockroachDbEngine = cockroachDbEngine;
|
||||
module.exports.clickhouseEngine = clickhouseEngine;
|
||||
module.exports.oracleEngine = oracleEngine;
|
||||
module.exports.cassandraEngine = cassandraEngine;
|
||||
module.exports.libsqlFileEngine = libsqlFileEngine;
|
||||
module.exports.libsqlWsEngine = libsqlWsEngine;
|
||||
module.exports.duckdbEngine = duckdbEngine;
|
||||
module.exports.firebirdEngine = firebirdEngine;
|
||||
|
||||
45
integration-tests/firebird.conf
Normal file
45
integration-tests/firebird.conf
Normal file
@@ -0,0 +1,45 @@
|
||||
# Custom Firebird Configuration
|
||||
|
||||
# Wire encryption settings
|
||||
# Options: Enabled, Required, Disabled
|
||||
WireCrypt = Disabled
|
||||
|
||||
# Authentication settings
|
||||
# Add Legacy_Auth to support older clients
|
||||
AuthServer = Legacy_Auth
|
||||
|
||||
# User manager plugin
|
||||
UserManager = Legacy_UserManager
|
||||
|
||||
# Default character set
|
||||
DefaultCharSet = UTF8
|
||||
|
||||
# Buffer settings for better performance
|
||||
DefaultDbCachePages = 2048
|
||||
TempCacheLimit = 512M
|
||||
|
||||
# Connection settings
|
||||
ConnectionTimeout = 180
|
||||
DatabaseGrowthIncrement = 128M
|
||||
|
||||
# TCP Protocol settings
|
||||
TcpRemoteBufferSize = 8192
|
||||
TcpNoNagle = 1
|
||||
|
||||
# Security settings
|
||||
RemoteServiceName = gds_db
|
||||
RemoteServicePort = 3050
|
||||
RemoteAuxPort = 0
|
||||
RemotePipeName = firebird
|
||||
|
||||
# Lock settings
|
||||
LockMemSize = 1M
|
||||
LockHashSlots = 8191
|
||||
LockAcquireSpins = 0
|
||||
|
||||
# Log settings
|
||||
FileSystemCacheThreshold = 65536
|
||||
FileSystemCacheSize = 0
|
||||
|
||||
# Compatibility settings for older clients
|
||||
CompatiblityDialect = 3
|
||||
@@ -1,3 +1,4 @@
|
||||
module.exports = {
|
||||
setupFilesAfterEnv: ['<rootDir>/setupTests.js'],
|
||||
reporters: ['default', 'github-actions'],
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dbgate-integration-tests",
|
||||
"version": "6.0.0-alpha.1",
|
||||
"version": "7.0.0-alpha.1",
|
||||
"homepage": "https://dbgate.org/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -12,13 +12,13 @@
|
||||
"wait:local": "cross-env DEVMODE=1 LOCALTEST=1 node wait.js",
|
||||
"wait:ci": "cross-env DEVMODE=1 CITEST=1 node wait.js",
|
||||
"test:local": "cross-env DEVMODE=1 LOCALTEST=1 jest --testTimeout=5000",
|
||||
"test:local:path": "cross-env DEVMODE=1 LOCALTEST=1 jest --runTestsByPath __tests__/data-duplicator.spec.js",
|
||||
"test:local:path": "cross-env DEVMODE=1 LOCALTEST=1 jest --runTestsByPath __tests__/alter-database.spec.js",
|
||||
"test:ci": "cross-env DEVMODE=1 CITEST=1 jest --runInBand --json --outputFile=result.json --testLocationInResults --detectOpenHandles --forceExit --testTimeout=10000",
|
||||
"run:local": "docker-compose down && docker-compose up -d && yarn wait:local && yarn test:local"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^7.0.3",
|
||||
"jest": "^27.0.1",
|
||||
"jest": "^28.1.3",
|
||||
"pino-pretty": "^11.2.2",
|
||||
"tmp": "^0.2.3"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
global.DBGATE_PACKAGES = {
|
||||
'dbgate-tools': require('dbgate-tools'),
|
||||
'dbgate-sqltree': require('dbgate-sqltree'),
|
||||
'dbgate-datalib': require('dbgate-datalib'),
|
||||
};
|
||||
|
||||
const { prettyFactory } = require('pino-pretty');
|
||||
|
||||
@@ -5,7 +5,12 @@ const crypto = require('crypto');
|
||||
function randomDbName(dialect) {
|
||||
const generatedKey = crypto.randomBytes(6);
|
||||
const newKey = generatedKey.toString('hex');
|
||||
const res = `db${newKey}`;
|
||||
let res = `db${newKey}`;
|
||||
|
||||
if (dialect.dbFileExtension) {
|
||||
res += dialect.dbFileExtension;
|
||||
}
|
||||
|
||||
if (dialect.upperCaseAllDbObjectNames) return res.toUpperCase();
|
||||
return res;
|
||||
}
|
||||
@@ -17,7 +22,9 @@ async function connect(engine, database) {
|
||||
if (engine.generateDbFile) {
|
||||
const conn = await driver.connect({
|
||||
...connection,
|
||||
databaseFile: `dbtemp/${database}`,
|
||||
databaseFile:
|
||||
(engine.databaseFileLocationOnServer ?? (process.env.CITEST ? 'dbtemp/' : 'integration-tests/dbtemp/')) +
|
||||
database,
|
||||
});
|
||||
return conn;
|
||||
} else {
|
||||
@@ -42,7 +49,7 @@ async function prepareConnection(engine, database) {
|
||||
if (engine.generateDbFile) {
|
||||
return {
|
||||
...connection,
|
||||
databaseFile: `dbtemp/${database}`,
|
||||
databaseFile: (engine.databaseFileLocationOnServer ?? 'dbtemp/') + database,
|
||||
isPreparedOnly: true,
|
||||
};
|
||||
} else {
|
||||
|
||||
@@ -3,6 +3,7 @@ const engines = require('./engines');
|
||||
global.DBGATE_PACKAGES = {
|
||||
'dbgate-tools': require('dbgate-tools'),
|
||||
'dbgate-sqltree': require('dbgate-sqltree'),
|
||||
'dbgate-datalib': require('dbgate-datalib'),
|
||||
};
|
||||
|
||||
async function connectEngine(engine) {
|
||||
|
||||
12
package.json
12
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "6.2.2-packer-beta.4",
|
||||
"version": "7.0.6",
|
||||
"name": "dbgate-all",
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
@@ -9,6 +9,7 @@
|
||||
],
|
||||
"scripts": {
|
||||
"start:api": "yarn workspace dbgate-api start | pino-pretty",
|
||||
"start:api:watch": "nodemon --watch 'src/**' --ext 'ts,json,js' --exec yarn start:api",
|
||||
"start:api:json": "yarn workspace dbgate-api start",
|
||||
"start:app": "cd app && yarn start | pino-pretty",
|
||||
"start:app:singledb": "CONNECTIONS=con1 SERVER_con1=localhost ENGINE_con1=mysql@dbgate-plugin-mysql USER_con1=root PASSWORD_con1=Pwd2020Db SINGLE_CONNECTION=con1 SINGLE_DATABASE=Chinook yarn start:app",
|
||||
@@ -21,6 +22,7 @@
|
||||
"start:api:auth": "yarn workspace dbgate-api start:auth | pino-pretty",
|
||||
"start:api:dblogin": "yarn workspace dbgate-api start:dblogin | pino-pretty",
|
||||
"start:api:storage": "yarn workspace dbgate-api start:storage | pino-pretty",
|
||||
"start:api:sfill": "yarn workspace dbgate-api start:sfill | pino-pretty",
|
||||
"start:api:storage:built": "yarn workspace dbgate-api start:storage:built | pino-pretty",
|
||||
"start:api:azure": "yarn workspace dbgate-api start:azure | pino-pretty",
|
||||
"start:api:e2e:team": "yarn workspace dbgate-api start:e2e:team | pino-pretty",
|
||||
@@ -42,7 +44,7 @@
|
||||
"build:plugins:frontend": "workspaces-run --only=\"dbgate-plugin-*\" -- yarn build:frontend",
|
||||
"build:plugins:backend": "workspaces-run --only=\"dbgate-plugin-*\" -- yarn build:backend",
|
||||
"build:plugins:frontend:watch": "workspaces-run --parallel --only=\"dbgate-plugin-*\" -- yarn build:frontend:watch",
|
||||
"storage-json": "dbmodel model-to-json storage-db packages/api/src/storageModel.js --commonjs",
|
||||
"storage-json": "node packages/dbmodel/bin/dbmodel.js model-to-json storage-db packages/api/src/storageModel.js --commonjs",
|
||||
"plugins:copydist": "workspaces-run --only=\"dbgate-plugin-*\" -- yarn copydist",
|
||||
"build:app:local": "yarn plugins:copydist && cd app && yarn build:local",
|
||||
"start:app:local": "cd app && yarn start:local",
|
||||
@@ -51,6 +53,7 @@
|
||||
"generatePadFile": "node generatePadFile",
|
||||
"fillPackagedPlugins": "node fillPackagedPlugins",
|
||||
"resetPackagedPlugins": "node resetPackagedPlugins",
|
||||
"fixYmlHashes": "cd common && yarn init -y && yarn add yaml -W && cd .. && node common/fixYmlHashes.js app/dist",
|
||||
"prettier": "prettier --write packages/api/src && prettier --write packages/datalib/src && prettier --write packages/filterparser/src && prettier --write packages/sqltree/src && prettier --write packages/tools/src && prettier --write packages/types && prettier --write packages/web/src && prettier --write app/src",
|
||||
"copy:docker:build": "copyfiles packages/api/dist/* docker -f && copyfiles packages/web/public/* docker -u 2 && copyfiles \"packages/web/public/**/*\" docker -u 2 && copyfiles \"plugins/dist/**/*\" docker/plugins -u 2",
|
||||
"copy:packer:build": "copyfiles packages/api/dist/* packer/build -f && copyfiles packages/web/public/* packer/build -u 2 && copyfiles \"packages/web/public/**/*\" packer/build -u 2 && copyfiles \"plugins/dist/**/*\" packer/build/plugins -u 2 && copyfiles packer/install-packages.sh packer/build -f && yarn install:drivers:packer",
|
||||
@@ -71,7 +74,10 @@
|
||||
"translations:extract": "node common/translations-cli/index.js extract",
|
||||
"translations:add-missing": "node common/translations-cli/index.js add-missing",
|
||||
"translations:remove-unused": "node common/translations-cli/index.js remove-unused",
|
||||
"translations:check": "node common/translations-cli/index.js check"
|
||||
"translations:check": "node common/translations-cli/index.js check",
|
||||
"translations:sort": "node common/translations-cli/index.js sort",
|
||||
"translations:translate": "node common/translations-cli/translate.js",
|
||||
"errors": "node common/assign-dbgm-codes.mjs ."
|
||||
},
|
||||
"dependencies": {
|
||||
"concurrently": "^5.1.0",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
DEVMODE=1
|
||||
SHELL_SCRIPTING=1
|
||||
ALLOW_DBGATE_PRIVATE_CLOUD=1
|
||||
DEVWEB=1
|
||||
# LOCAL_AUTH_PROXY=1
|
||||
# LOCAL_AI_GATEWAY=true
|
||||
|
||||
# REDIRECT_TO_DBGATE_CLOUD_LOGIN=1
|
||||
# PROD_DBGATE_CLOUD=1
|
||||
# PROD_DBGATE_IDENTITY=1
|
||||
# LOCAL_DBGATE_CLOUD=1
|
||||
# LOCAL_DBGATE_IDENTITY=1
|
||||
|
||||
# CLOUD_UPGRADE_FILE=c:\test\upg\upgrade.zip
|
||||
|
||||
@@ -7,7 +17,6 @@ SHELL_SCRIPTING=1
|
||||
# DISABLE_SHELL=1
|
||||
# HIDE_APP_EDITOR=1
|
||||
|
||||
|
||||
# DEVWEB=1
|
||||
# LOGINS=admin,test
|
||||
|
||||
|
||||
54
packages/api/env/sfill/.env
vendored
Normal file
54
packages/api/env/sfill/.env
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
DEVMODE=1
|
||||
DEVWEB=1
|
||||
|
||||
# STORAGE_SERVER=localhost
|
||||
# STORAGE_USER=root
|
||||
# STORAGE_PASSWORD=Pwd2020Db
|
||||
# STORAGE_PORT=3306
|
||||
# STORAGE_DATABASE=dbgate-filled
|
||||
# STORAGE_ENGINE=mysql@dbgate-plugin-mysql
|
||||
|
||||
STORAGE_SERVER=localhost
|
||||
STORAGE_USER=postgres
|
||||
STORAGE_PASSWORD=Pwd2020Db
|
||||
STORAGE_PORT=5432
|
||||
STORAGE_DATABASE=dbgate_sfill
|
||||
STORAGE_ENGINE=postgres@dbgate-plugin-postgres
|
||||
|
||||
|
||||
CONNECTIONS=mysql,postgres,mongo,redis
|
||||
|
||||
LABEL_mysql=MySql
|
||||
SERVER_mysql=dbgatedckstage1.sprinx.cz
|
||||
USER_mysql=root
|
||||
PASSWORD_mysql=Pwd2020Db
|
||||
PORT_mysql=3306
|
||||
ENGINE_mysql=mysql@dbgate-plugin-mysql
|
||||
|
||||
LABEL_postgres=Postgres
|
||||
SERVER_postgres=dbgatedckstage1.sprinx.cz
|
||||
USER_postgres=postgres
|
||||
PASSWORD_postgres=Pwd2020Db
|
||||
PORT_postgres=5432
|
||||
ENGINE_postgres=postgres@dbgate-plugin-postgres
|
||||
|
||||
LABEL_mongo=Mongo
|
||||
SERVER_mongo=dbgatedckstage1.sprinx.cz
|
||||
USER_mongo=root
|
||||
PASSWORD_mongo=Pwd2020Db
|
||||
PORT_mongo=27017
|
||||
ENGINE_mongo=mongo@dbgate-plugin-mongo
|
||||
|
||||
LABEL_redis=Redis
|
||||
SERVER_redis=dbgatedckstage1.sprinx.cz
|
||||
ENGINE_redis=redis@dbgate-plugin-redis
|
||||
PORT_redis=6379
|
||||
|
||||
ROLE_test1_CONNECTIONS=mysql
|
||||
ROLE_test1_PERMISSIONS=widgets/*
|
||||
ROLE_test1_DATABASES_db1_CONNECTION=mysql
|
||||
ROLE_test1_DATABASES_db1_PERMISSION=run_script
|
||||
ROLE_test1_DATABASES_db1_DATABASES=db1
|
||||
ROLE_test1_DATABASES_db2_CONNECTION=redis
|
||||
ROLE_test1_DATABASES_db2_PERMISSION=run_script
|
||||
ROLE_test1_DATABASES_db2_DATABASES=db2
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "dbgate-api",
|
||||
"main": "src/index.js",
|
||||
"version": "6.0.0-alpha.1",
|
||||
"version": "7.0.0-alpha.1",
|
||||
"homepage": "https://dbgate.org/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -22,17 +22,18 @@
|
||||
"dependencies": {
|
||||
"@aws-sdk/rds-signer": "^3.665.0",
|
||||
"activedirectory2": "^2.1.0",
|
||||
"archiver": "^7.0.1",
|
||||
"async-lock": "^1.2.6",
|
||||
"axios": "^0.21.1",
|
||||
"axios": "^1.13.2",
|
||||
"body-parser": "^1.19.0",
|
||||
"byline": "^5.0.0",
|
||||
"compare-versions": "^3.6.0",
|
||||
"cors": "^2.8.5",
|
||||
"cross-env": "^6.0.3",
|
||||
"dbgate-datalib": "^6.0.0-alpha.1",
|
||||
"dbgate-query-splitter": "^4.11.3",
|
||||
"dbgate-sqltree": "^6.0.0-alpha.1",
|
||||
"dbgate-tools": "^6.0.0-alpha.1",
|
||||
"dbgate-datalib": "^7.0.0-alpha.1",
|
||||
"dbgate-query-splitter": "^4.11.9",
|
||||
"dbgate-sqltree": "^7.0.0-alpha.1",
|
||||
"dbgate-tools": "^7.0.0-alpha.1",
|
||||
"debug": "^4.3.4",
|
||||
"diff": "^5.0.0",
|
||||
"diff2html": "^3.4.13",
|
||||
@@ -55,23 +56,26 @@
|
||||
"ncp": "^2.0.0",
|
||||
"node-cron": "^2.0.3",
|
||||
"on-finished": "^2.4.1",
|
||||
"pinomin": "^1.0.4",
|
||||
"pinomin": "^1.0.5",
|
||||
"portfinder": "^1.0.28",
|
||||
"rimraf": "^3.0.0",
|
||||
"semver": "^7.6.3",
|
||||
"simple-encryptor": "^4.0.0",
|
||||
"ssh2": "^1.16.0",
|
||||
"stream-json": "^1.8.0",
|
||||
"tar": "^6.0.5"
|
||||
"tar": "^6.0.5",
|
||||
"yauzl": "^3.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "env-cmd -f .env node src/index.js --listen-api",
|
||||
"start:debug": "env-cmd -f .env node --inspect src/index.js --listen-api",
|
||||
"start:portal": "env-cmd -f env/portal/.env node src/index.js --listen-api",
|
||||
"start:singledb": "env-cmd -f env/singledb/.env node src/index.js --listen-api",
|
||||
"start:auth": "env-cmd -f env/auth/.env node src/index.js --listen-api",
|
||||
"start:dblogin": "env-cmd -f env/dblogin/.env node src/index.js --listen-api",
|
||||
"start:filedb": "env-cmd node src/index.js /home/jena/test/chinook/Chinook.db --listen-api",
|
||||
"start:storage": "env-cmd -f env/storage/.env node src/index.js --listen-api",
|
||||
"start:sfill": "env-cmd -f env/sfill/.env node src/index.js --listen-api",
|
||||
"start:storage:built": "env-cmd -f env/storage/.env cross-env DEVMODE= BUILTWEBMODE=1 node dist/bundle.js --listen-api",
|
||||
"start:singleconn": "env-cmd node src/index.js --server localhost --user root --port 3307 --engine mysql@dbgate-plugin-mysql --password test --listen-api",
|
||||
"start:azure": "env-cmd -f env/azure/.env node src/index.js --listen-api",
|
||||
@@ -83,7 +87,7 @@
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^9.0.11",
|
||||
"@types/lodash": "^4.14.149",
|
||||
"dbgate-types": "^6.0.0-alpha.1",
|
||||
"dbgate-types": "^7.0.0-alpha.1",
|
||||
"env-cmd": "^10.1.0",
|
||||
"jsdoc-to-markdown": "^9.0.5",
|
||||
"node-loader": "^1.0.2",
|
||||
|
||||
@@ -10,7 +10,13 @@ function getTokenSecret() {
|
||||
return tokenSecret;
|
||||
}
|
||||
|
||||
function getStaticTokenSecret() {
|
||||
// TODO static not fixed
|
||||
return '14813c43-a91b-4ad1-9dcd-a81bd7dbb05f';
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getTokenLifetime,
|
||||
getTokenSecret,
|
||||
getStaticTokenSecret,
|
||||
};
|
||||
|
||||
@@ -10,8 +10,9 @@ const logger = getLogger('authProvider');
|
||||
|
||||
class AuthProviderBase {
|
||||
amoid = 'none';
|
||||
skipInList = false;
|
||||
|
||||
async login(login, password, options = undefined) {
|
||||
async login(login, password, options = undefined, req = undefined) {
|
||||
return {
|
||||
accessToken: jwt.sign(
|
||||
{
|
||||
@@ -23,7 +24,7 @@ class AuthProviderBase {
|
||||
};
|
||||
}
|
||||
|
||||
oauthToken(params) {
|
||||
oauthToken(params, req) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -36,12 +37,28 @@ class AuthProviderBase {
|
||||
return !!req?.user || !!req?.auth;
|
||||
}
|
||||
|
||||
getCurrentPermissions(req) {
|
||||
async getCurrentPermissions(req) {
|
||||
const login = this.getCurrentLogin(req);
|
||||
const permissions = process.env[`LOGIN_PERMISSIONS_${login}`];
|
||||
return permissions || process.env.PERMISSIONS;
|
||||
}
|
||||
|
||||
async checkCurrentConnectionPermission(req, conid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
async getCurrentDatabasePermissions(req) {
|
||||
return [];
|
||||
}
|
||||
|
||||
async getCurrentTablePermissions(req) {
|
||||
return [];
|
||||
}
|
||||
|
||||
async getCurrentFilePermissions(req) {
|
||||
return [];
|
||||
}
|
||||
|
||||
getLoginPageConnections() {
|
||||
return null;
|
||||
}
|
||||
@@ -94,7 +111,7 @@ class OAuthProvider extends AuthProviderBase {
|
||||
payload = jwt.decode(id_token);
|
||||
}
|
||||
|
||||
logger.info({ payload }, 'User payload returned from OAUTH');
|
||||
logger.info({ payload }, 'DBGM-00002 User payload returned from OAUTH');
|
||||
|
||||
const login =
|
||||
process.env.OAUTH_LOGIN_FIELD && payload && payload[process.env.OAUTH_LOGIN_FIELD]
|
||||
|
||||
@@ -1,233 +1,99 @@
|
||||
const fs = require('fs-extra');
|
||||
const _ = require('lodash');
|
||||
const path = require('path');
|
||||
const { appdir } = require('../utility/directories');
|
||||
const { appdir, filesdir } = require('../utility/directories');
|
||||
const socket = require('../utility/socket');
|
||||
const connections = require('./connections');
|
||||
const {
|
||||
loadPermissionsFromRequest,
|
||||
loadFilePermissionsFromRequest,
|
||||
hasPermission,
|
||||
getFilePermissionRole,
|
||||
} = require('../utility/hasPermission');
|
||||
|
||||
module.exports = {
|
||||
folders_meta: true,
|
||||
async folders() {
|
||||
const folders = await fs.readdir(appdir());
|
||||
return [
|
||||
...folders.map(name => ({
|
||||
name,
|
||||
})),
|
||||
];
|
||||
},
|
||||
|
||||
createFolder_meta: true,
|
||||
async createFolder({ folder }) {
|
||||
const name = await this.getNewAppFolder({ name: folder });
|
||||
await fs.mkdir(path.join(appdir(), name));
|
||||
socket.emitChanged('app-folders-changed');
|
||||
this.emitChangedDbApp(folder);
|
||||
return name;
|
||||
},
|
||||
|
||||
files_meta: true,
|
||||
async files({ folder }) {
|
||||
if (!folder) return [];
|
||||
const dir = path.join(appdir(), folder);
|
||||
getAllApps_meta: true,
|
||||
async getAllApps({}, req) {
|
||||
const dir = path.join(filesdir(), 'apps');
|
||||
if (!(await fs.exists(dir))) return [];
|
||||
const files = await fs.readdir(dir);
|
||||
|
||||
function fileType(ext, type) {
|
||||
return files
|
||||
.filter(name => name.endsWith(ext))
|
||||
.map(name => ({
|
||||
name: name.slice(0, -ext.length),
|
||||
label: path.parse(name.slice(0, -ext.length)).base,
|
||||
type,
|
||||
}));
|
||||
}
|
||||
|
||||
return [
|
||||
...fileType('.command.sql', 'command.sql'),
|
||||
...fileType('.query.sql', 'query.sql'),
|
||||
...fileType('.config.json', 'config.json'),
|
||||
];
|
||||
},
|
||||
|
||||
async emitChangedDbApp(folder) {
|
||||
const used = await this.getUsedAppFolders();
|
||||
if (used.includes(folder)) {
|
||||
socket.emitChanged('used-apps-changed');
|
||||
}
|
||||
},
|
||||
|
||||
refreshFiles_meta: true,
|
||||
async refreshFiles({ folder }) {
|
||||
socket.emitChanged('app-files-changed', { app: folder });
|
||||
},
|
||||
|
||||
refreshFolders_meta: true,
|
||||
async refreshFolders() {
|
||||
socket.emitChanged(`app-folders-changed`);
|
||||
},
|
||||
|
||||
deleteFile_meta: true,
|
||||
async deleteFile({ folder, file, fileType }) {
|
||||
await fs.unlink(path.join(appdir(), folder, `${file}.${fileType}`));
|
||||
socket.emitChanged('app-files-changed', { app: folder });
|
||||
this.emitChangedDbApp(folder);
|
||||
},
|
||||
|
||||
renameFile_meta: true,
|
||||
async renameFile({ folder, file, newFile, fileType }) {
|
||||
await fs.rename(
|
||||
path.join(path.join(appdir(), folder), `${file}.${fileType}`),
|
||||
path.join(path.join(appdir(), folder), `${newFile}.${fileType}`)
|
||||
);
|
||||
socket.emitChanged('app-files-changed', { app: folder });
|
||||
this.emitChangedDbApp(folder);
|
||||
},
|
||||
|
||||
renameFolder_meta: true,
|
||||
async renameFolder({ folder, newFolder }) {
|
||||
const uniqueName = await this.getNewAppFolder({ name: newFolder });
|
||||
await fs.rename(path.join(appdir(), folder), path.join(appdir(), uniqueName));
|
||||
socket.emitChanged(`app-folders-changed`);
|
||||
},
|
||||
|
||||
deleteFolder_meta: true,
|
||||
async deleteFolder({ folder }) {
|
||||
if (!folder) throw new Error('Missing folder parameter');
|
||||
await fs.rmdir(path.join(appdir(), folder), { recursive: true });
|
||||
socket.emitChanged(`app-folders-changed`);
|
||||
socket.emitChanged('app-files-changed', { app: folder });
|
||||
socket.emitChanged('used-apps-changed');
|
||||
},
|
||||
|
||||
async getNewAppFolder({ name }) {
|
||||
if (!(await fs.exists(path.join(appdir(), name)))) return name;
|
||||
let index = 2;
|
||||
while (await fs.exists(path.join(appdir(), `${name}${index}`))) {
|
||||
index += 1;
|
||||
}
|
||||
return `${name}${index}`;
|
||||
},
|
||||
|
||||
getUsedAppFolders_meta: true,
|
||||
async getUsedAppFolders() {
|
||||
const list = await connections.list();
|
||||
const apps = [];
|
||||
|
||||
for (const connection of list) {
|
||||
for (const db of connection.databases || []) {
|
||||
for (const key of _.keys(db || {})) {
|
||||
if (key.startsWith('useApp:') && db[key]) {
|
||||
apps.push(key.substring('useApp:'.length));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _.intersection(_.uniq(apps), await fs.readdir(appdir()));
|
||||
},
|
||||
|
||||
getUsedApps_meta: true,
|
||||
async getUsedApps() {
|
||||
const apps = await this.getUsedAppFolders();
|
||||
const res = [];
|
||||
const loadedPermissions = await loadPermissionsFromRequest(req);
|
||||
const filePermissions = await loadFilePermissionsFromRequest(req);
|
||||
|
||||
for (const folder of apps) {
|
||||
res.push(await this.loadApp({ folder }));
|
||||
}
|
||||
return res;
|
||||
},
|
||||
|
||||
// getAppsForDb_meta: true,
|
||||
// async getAppsForDb({ conid, database }) {
|
||||
// const connection = await connections.get({ conid });
|
||||
// if (!connection) return [];
|
||||
// const db = (connection.databases || []).find(x => x.name == database);
|
||||
// const apps = [];
|
||||
// const res = [];
|
||||
// if (db) {
|
||||
// for (const key of _.keys(db || {})) {
|
||||
// if (key.startsWith('useApp:') && db[key]) {
|
||||
// apps.push(key.substring('useApp:'.length));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// for (const folder of apps) {
|
||||
// res.push(await this.loadApp({ folder }));
|
||||
// }
|
||||
// return res;
|
||||
// },
|
||||
|
||||
loadApp_meta: true,
|
||||
async loadApp({ folder }) {
|
||||
const res = {
|
||||
queries: [],
|
||||
commands: [],
|
||||
name: folder,
|
||||
};
|
||||
const dir = path.join(appdir(), folder);
|
||||
if (await fs.exists(dir)) {
|
||||
const files = await fs.readdir(dir);
|
||||
|
||||
async function processType(ext, field) {
|
||||
for (const file of files) {
|
||||
if (file.endsWith(ext)) {
|
||||
res[field].push({
|
||||
name: file.slice(0, -ext.length),
|
||||
sql: await fs.readFile(path.join(dir, file), { encoding: 'utf-8' }),
|
||||
});
|
||||
}
|
||||
}
|
||||
for (const file of await fs.readdir(dir)) {
|
||||
if (!hasPermission(`all-disk-files`, loadedPermissions)) {
|
||||
const role = getFilePermissionRole('apps', file, filePermissions);
|
||||
if (role == 'deny') continue;
|
||||
}
|
||||
const content = await fs.readFile(path.join(dir, file), { encoding: 'utf-8' });
|
||||
const appJson = JSON.parse(content);
|
||||
// const app = {
|
||||
// appid: file,
|
||||
// name: appJson.applicationName,
|
||||
// usageRules: appJson.usageRules || [],
|
||||
// icon: appJson.applicationIcon || 'img app',
|
||||
// color: appJson.applicationColor,
|
||||
// queries: Object.values(appJson.files || {})
|
||||
// .filter(x => x.type == 'query')
|
||||
// .map(x => ({
|
||||
// name: x.label,
|
||||
// sql: x.sql,
|
||||
// })),
|
||||
// commands: Object.values(appJson.files || {})
|
||||
// .filter(x => x.type == 'command')
|
||||
// .map(x => ({
|
||||
// name: x.label,
|
||||
// sql: x.sql,
|
||||
// })),
|
||||
// virtualReferences: appJson.virtualReferences,
|
||||
// dictionaryDescriptions: appJson.dictionaryDescriptions,
|
||||
// };
|
||||
const app = {
|
||||
...appJson,
|
||||
appid: file,
|
||||
};
|
||||
|
||||
await processType('.command.sql', 'commands');
|
||||
await processType('.query.sql', 'queries');
|
||||
res.push(app);
|
||||
}
|
||||
|
||||
try {
|
||||
res.virtualReferences = JSON.parse(
|
||||
await fs.readFile(path.join(dir, 'virtual-references.config.json'), { encoding: 'utf-8' })
|
||||
);
|
||||
} catch (err) {
|
||||
res.virtualReferences = [];
|
||||
}
|
||||
try {
|
||||
res.dictionaryDescriptions = JSON.parse(
|
||||
await fs.readFile(path.join(dir, 'dictionary-descriptions.config.json'), { encoding: 'utf-8' })
|
||||
);
|
||||
} catch (err) {
|
||||
res.dictionaryDescriptions = [];
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
|
||||
async saveConfigFile(appFolder, filename, filterFunc, newItem) {
|
||||
const file = path.join(appdir(), appFolder, filename);
|
||||
|
||||
let json;
|
||||
try {
|
||||
json = JSON.parse(await fs.readFile(file, { encoding: 'utf-8' }));
|
||||
} catch (err) {
|
||||
json = [];
|
||||
createAppFromDb_meta: true,
|
||||
async createAppFromDb({ appName, server, database }, req) {
|
||||
const appdir = path.join(filesdir(), 'apps');
|
||||
if (!fs.existsSync(appdir)) {
|
||||
await fs.mkdir(appdir);
|
||||
}
|
||||
|
||||
if (filterFunc) {
|
||||
json = json.filter(filterFunc);
|
||||
const appId = _.kebabCase(appName);
|
||||
let suffix = undefined;
|
||||
while (fs.existsSync(path.join(appdir, `${appId}${suffix || ''}`))) {
|
||||
if (!suffix) suffix = 2;
|
||||
else suffix++;
|
||||
}
|
||||
const finalAppId = `${appId}${suffix || ''}`;
|
||||
|
||||
json = [...json, newItem];
|
||||
const appJson = {
|
||||
applicationName: appName,
|
||||
usageRules: [
|
||||
{
|
||||
serverHostsList: server,
|
||||
databaseNamesList: database,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
await fs.writeFile(file, JSON.stringify(json, undefined, 2));
|
||||
await fs.writeFile(path.join(appdir, `${finalAppId}`), JSON.stringify(appJson, undefined, 2));
|
||||
|
||||
socket.emitChanged('app-files-changed', { app: appFolder });
|
||||
socket.emitChanged('used-apps-changed');
|
||||
socket.emitChanged(`files-changed`, { folder: 'apps' });
|
||||
|
||||
return finalAppId;
|
||||
},
|
||||
|
||||
saveVirtualReference_meta: true,
|
||||
async saveVirtualReference({ appFolder, schemaName, pureName, refSchemaName, refTableName, columns }) {
|
||||
await this.saveConfigFile(
|
||||
appFolder,
|
||||
'virtual-references.config.json',
|
||||
async saveVirtualReference({ appid, schemaName, pureName, refSchemaName, refTableName, columns }) {
|
||||
await this.saveConfigItem(
|
||||
appid,
|
||||
'virtualReferences',
|
||||
columns.length == 1
|
||||
? x =>
|
||||
!(
|
||||
@@ -245,14 +111,17 @@ module.exports = {
|
||||
columns,
|
||||
}
|
||||
);
|
||||
|
||||
socket.emitChanged(`files-changed`, { folder: 'apps' });
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
saveDictionaryDescription_meta: true,
|
||||
async saveDictionaryDescription({ appFolder, pureName, schemaName, expression, columns, delimiter }) {
|
||||
await this.saveConfigFile(
|
||||
appFolder,
|
||||
'dictionary-descriptions.config.json',
|
||||
async saveDictionaryDescription({ appid, pureName, schemaName, expression, columns, delimiter }) {
|
||||
await this.saveConfigItem(
|
||||
appid,
|
||||
'dictionaryDescriptions',
|
||||
x => !(x.schemaName == schemaName && x.pureName == pureName),
|
||||
{
|
||||
schemaName,
|
||||
@@ -263,18 +132,271 @@ module.exports = {
|
||||
}
|
||||
);
|
||||
|
||||
socket.emitChanged(`files-changed`, { folder: 'apps' });
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
createConfigFile_meta: true,
|
||||
async createConfigFile({ appFolder, fileName, content }) {
|
||||
const file = path.join(appdir(), appFolder, fileName);
|
||||
if (!(await fs.exists(file))) {
|
||||
await fs.writeFile(file, JSON.stringify(content, undefined, 2));
|
||||
socket.emitChanged('app-files-changed', { app: appFolder });
|
||||
socket.emitChanged('used-apps-changed');
|
||||
return true;
|
||||
async saveConfigItem(appid, fieldName, filterFunc, newItem) {
|
||||
const file = path.join(filesdir(), 'apps', appid);
|
||||
|
||||
const appJson = JSON.parse(await fs.readFile(file, { encoding: 'utf-8' }));
|
||||
let json = appJson[fieldName] || [];
|
||||
|
||||
if (filterFunc) {
|
||||
json = json.filter(filterFunc);
|
||||
}
|
||||
return false;
|
||||
|
||||
json = [...json, newItem];
|
||||
|
||||
await fs.writeFile(
|
||||
file,
|
||||
JSON.stringify(
|
||||
{
|
||||
...appJson,
|
||||
[fieldName]: json,
|
||||
},
|
||||
undefined,
|
||||
2
|
||||
)
|
||||
);
|
||||
|
||||
socket.emitChanged('files-changed', { folder: 'apps' });
|
||||
},
|
||||
|
||||
// folders_meta: true,
|
||||
// async folders() {
|
||||
// const folders = await fs.readdir(appdir());
|
||||
// return [
|
||||
// ...folders.map(name => ({
|
||||
// name,
|
||||
// })),
|
||||
// ];
|
||||
// },
|
||||
|
||||
// createFolder_meta: true,
|
||||
// async createFolder({ folder }) {
|
||||
// const name = await this.getNewAppFolder({ name: folder });
|
||||
// await fs.mkdir(path.join(appdir(), name));
|
||||
// socket.emitChanged('app-folders-changed');
|
||||
// this.emitChangedDbApp(folder);
|
||||
// return name;
|
||||
// },
|
||||
|
||||
// files_meta: true,
|
||||
// async files({ folder }) {
|
||||
// if (!folder) return [];
|
||||
// const dir = path.join(appdir(), folder);
|
||||
// if (!(await fs.exists(dir))) return [];
|
||||
// const files = await fs.readdir(dir);
|
||||
|
||||
// function fileType(ext, type) {
|
||||
// return files
|
||||
// .filter(name => name.endsWith(ext))
|
||||
// .map(name => ({
|
||||
// name: name.slice(0, -ext.length),
|
||||
// label: path.parse(name.slice(0, -ext.length)).base,
|
||||
// type,
|
||||
// }));
|
||||
// }
|
||||
|
||||
// return [
|
||||
// ...fileType('.command.sql', 'command.sql'),
|
||||
// ...fileType('.query.sql', 'query.sql'),
|
||||
// ...fileType('.config.json', 'config.json'),
|
||||
// ];
|
||||
// },
|
||||
|
||||
// async emitChangedDbApp(folder) {
|
||||
// const used = await this.getUsedAppFolders();
|
||||
// if (used.includes(folder)) {
|
||||
// socket.emitChanged('used-apps-changed');
|
||||
// }
|
||||
// },
|
||||
|
||||
// refreshFiles_meta: true,
|
||||
// async refreshFiles({ folder }) {
|
||||
// socket.emitChanged('app-files-changed', { app: folder });
|
||||
// },
|
||||
|
||||
// refreshFolders_meta: true,
|
||||
// async refreshFolders() {
|
||||
// socket.emitChanged(`app-folders-changed`);
|
||||
// },
|
||||
|
||||
// deleteFile_meta: true,
|
||||
// async deleteFile({ folder, file, fileType }) {
|
||||
// await fs.unlink(path.join(appdir(), folder, `${file}.${fileType}`));
|
||||
// socket.emitChanged('app-files-changed', { app: folder });
|
||||
// this.emitChangedDbApp(folder);
|
||||
// },
|
||||
|
||||
// renameFile_meta: true,
|
||||
// async renameFile({ folder, file, newFile, fileType }) {
|
||||
// await fs.rename(
|
||||
// path.join(path.join(appdir(), folder), `${file}.${fileType}`),
|
||||
// path.join(path.join(appdir(), folder), `${newFile}.${fileType}`)
|
||||
// );
|
||||
// socket.emitChanged('app-files-changed', { app: folder });
|
||||
// this.emitChangedDbApp(folder);
|
||||
// },
|
||||
|
||||
// renameFolder_meta: true,
|
||||
// async renameFolder({ folder, newFolder }) {
|
||||
// const uniqueName = await this.getNewAppFolder({ name: newFolder });
|
||||
// await fs.rename(path.join(appdir(), folder), path.join(appdir(), uniqueName));
|
||||
// socket.emitChanged(`app-folders-changed`);
|
||||
// },
|
||||
|
||||
// deleteFolder_meta: true,
|
||||
// async deleteFolder({ folder }) {
|
||||
// if (!folder) throw new Error('Missing folder parameter');
|
||||
// await fs.rmdir(path.join(appdir(), folder), { recursive: true });
|
||||
// socket.emitChanged(`app-folders-changed`);
|
||||
// socket.emitChanged('app-files-changed', { app: folder });
|
||||
// socket.emitChanged('used-apps-changed');
|
||||
// },
|
||||
|
||||
// async getNewAppFolder({ name }) {
|
||||
// if (!(await fs.exists(path.join(appdir(), name)))) return name;
|
||||
// let index = 2;
|
||||
// while (await fs.exists(path.join(appdir(), `${name}${index}`))) {
|
||||
// index += 1;
|
||||
// }
|
||||
// return `${name}${index}`;
|
||||
// },
|
||||
|
||||
// getUsedAppFolders_meta: true,
|
||||
// async getUsedAppFolders() {
|
||||
// const list = await connections.list();
|
||||
// const apps = [];
|
||||
|
||||
// for (const connection of list) {
|
||||
// for (const db of connection.databases || []) {
|
||||
// for (const key of _.keys(db || {})) {
|
||||
// if (key.startsWith('useApp:') && db[key]) {
|
||||
// apps.push(key.substring('useApp:'.length));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return _.intersection(_.uniq(apps), await fs.readdir(appdir()));
|
||||
// },
|
||||
|
||||
// // getAppsForDb_meta: true,
|
||||
// // async getAppsForDb({ conid, database }) {
|
||||
// // const connection = await connections.get({ conid });
|
||||
// // if (!connection) return [];
|
||||
// // const db = (connection.databases || []).find(x => x.name == database);
|
||||
// // const apps = [];
|
||||
// // const res = [];
|
||||
// // if (db) {
|
||||
// // for (const key of _.keys(db || {})) {
|
||||
// // if (key.startsWith('useApp:') && db[key]) {
|
||||
// // apps.push(key.substring('useApp:'.length));
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
// // for (const folder of apps) {
|
||||
// // res.push(await this.loadApp({ folder }));
|
||||
// // }
|
||||
// // return res;
|
||||
// // },
|
||||
|
||||
// loadApp_meta: true,
|
||||
// async loadApp({ folder }) {
|
||||
// const res = {
|
||||
// queries: [],
|
||||
// commands: [],
|
||||
// name: folder,
|
||||
// };
|
||||
// const dir = path.join(appdir(), folder);
|
||||
// if (await fs.exists(dir)) {
|
||||
// const files = await fs.readdir(dir);
|
||||
|
||||
// async function processType(ext, field) {
|
||||
// for (const file of files) {
|
||||
// if (file.endsWith(ext)) {
|
||||
// res[field].push({
|
||||
// name: file.slice(0, -ext.length),
|
||||
// sql: await fs.readFile(path.join(dir, file), { encoding: 'utf-8' }),
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// await processType('.command.sql', 'commands');
|
||||
// await processType('.query.sql', 'queries');
|
||||
// }
|
||||
|
||||
// try {
|
||||
// res.virtualReferences = JSON.parse(
|
||||
// await fs.readFile(path.join(dir, 'virtual-references.config.json'), { encoding: 'utf-8' })
|
||||
// );
|
||||
// } catch (err) {
|
||||
// res.virtualReferences = [];
|
||||
// }
|
||||
// try {
|
||||
// res.dictionaryDescriptions = JSON.parse(
|
||||
// await fs.readFile(path.join(dir, 'dictionary-descriptions.config.json'), { encoding: 'utf-8' })
|
||||
// );
|
||||
// } catch (err) {
|
||||
// res.dictionaryDescriptions = [];
|
||||
// }
|
||||
|
||||
// return res;
|
||||
// },
|
||||
|
||||
// async saveConfigFile(appFolder, filename, filterFunc, newItem) {
|
||||
// const file = path.join(appdir(), appFolder, filename);
|
||||
|
||||
// let json;
|
||||
// try {
|
||||
// json = JSON.parse(await fs.readFile(file, { encoding: 'utf-8' }));
|
||||
// } catch (err) {
|
||||
// json = [];
|
||||
// }
|
||||
|
||||
// if (filterFunc) {
|
||||
// json = json.filter(filterFunc);
|
||||
// }
|
||||
|
||||
// json = [...json, newItem];
|
||||
|
||||
// await fs.writeFile(file, JSON.stringify(json, undefined, 2));
|
||||
|
||||
// socket.emitChanged('app-files-changed', { app: appFolder });
|
||||
// socket.emitChanged('used-apps-changed');
|
||||
// },
|
||||
|
||||
// saveDictionaryDescription_meta: true,
|
||||
// async saveDictionaryDescription({ appFolder, pureName, schemaName, expression, columns, delimiter }) {
|
||||
// await this.saveConfigFile(
|
||||
// appFolder,
|
||||
// 'dictionary-descriptions.config.json',
|
||||
// x => !(x.schemaName == schemaName && x.pureName == pureName),
|
||||
// {
|
||||
// schemaName,
|
||||
// pureName,
|
||||
// expression,
|
||||
// columns,
|
||||
// delimiter,
|
||||
// }
|
||||
// );
|
||||
|
||||
// return true;
|
||||
// },
|
||||
|
||||
// createConfigFile_meta: true,
|
||||
// async createConfigFile({ appFolder, fileName, content }) {
|
||||
// const file = path.join(appdir(), appFolder, fileName);
|
||||
// if (!(await fs.exists(file))) {
|
||||
// await fs.writeFile(file, JSON.stringify(content, undefined, 2));
|
||||
// socket.emitChanged('app-files-changed', { app: appFolder });
|
||||
// socket.emitChanged('used-apps-changed');
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// },
|
||||
};
|
||||
|
||||
@@ -2,14 +2,20 @@ const fs = require('fs-extra');
|
||||
const readline = require('readline');
|
||||
const crypto = require('crypto');
|
||||
const path = require('path');
|
||||
const { archivedir, clearArchiveLinksCache, resolveArchiveFolder } = require('../utility/directories');
|
||||
const { archivedir, clearArchiveLinksCache, resolveArchiveFolder, uploadsdir } = require('../utility/directories');
|
||||
const socket = require('../utility/socket');
|
||||
const loadFilesRecursive = require('../utility/loadFilesRecursive');
|
||||
const getJslFileName = require('../utility/getJslFileName');
|
||||
const { getLogger, extractErrorLogData } = require('dbgate-tools');
|
||||
const { getLogger, extractErrorLogData, jsonLinesParse } = require('dbgate-tools');
|
||||
const dbgateApi = require('../shell');
|
||||
const jsldata = require('./jsldata');
|
||||
const platformInfo = require('../utility/platformInfo');
|
||||
const { isProApp } = require('../utility/checkLicense');
|
||||
const listZipEntries = require('../utility/listZipEntries');
|
||||
const unzipJsonLinesFile = require('../shell/unzipJsonLinesFile');
|
||||
const { zip } = require('lodash');
|
||||
const zipDirectory = require('../shell/zipDirectory');
|
||||
const unzipDirectory = require('../shell/unzipDirectory');
|
||||
|
||||
const logger = getLogger('archive');
|
||||
|
||||
@@ -47,9 +53,31 @@ module.exports = {
|
||||
return folder;
|
||||
},
|
||||
|
||||
async getZipFiles({ file }) {
|
||||
const entries = await listZipEntries(path.join(archivedir(), file));
|
||||
const files = entries.map(entry => {
|
||||
let name = entry.fileName;
|
||||
if (isProApp() && entry.fileName.endsWith('.jsonl')) {
|
||||
name = entry.fileName.slice(0, -6);
|
||||
}
|
||||
return {
|
||||
name: name,
|
||||
label: name,
|
||||
type: isProApp() && entry.fileName.endsWith('.jsonl') ? 'jsonl' : 'other',
|
||||
};
|
||||
});
|
||||
return files;
|
||||
},
|
||||
|
||||
files_meta: true,
|
||||
async files({ folder }) {
|
||||
try {
|
||||
if (folder.endsWith('.zip')) {
|
||||
if (await fs.exists(path.join(archivedir(), folder))) {
|
||||
return this.getZipFiles({ file: folder });
|
||||
}
|
||||
return [];
|
||||
}
|
||||
const dir = resolveArchiveFolder(folder);
|
||||
if (!(await fs.exists(dir))) return [];
|
||||
const files = await loadFilesRecursive(dir); // fs.readdir(dir);
|
||||
@@ -74,7 +102,7 @@ module.exports = {
|
||||
...fileType('.matview.sql', 'matview.sql'),
|
||||
];
|
||||
} catch (err) {
|
||||
logger.error(extractErrorLogData(err), 'Error reading archive files');
|
||||
logger.error(extractErrorLogData(err), 'DBGM-00001 Error reading archive files');
|
||||
return [];
|
||||
}
|
||||
},
|
||||
@@ -91,6 +119,16 @@ module.exports = {
|
||||
return true;
|
||||
},
|
||||
|
||||
createFile_meta: true,
|
||||
async createFile({ folder, file, fileType, tableInfo }) {
|
||||
await fs.writeFile(
|
||||
path.join(resolveArchiveFolder(folder), `${file}.${fileType}`),
|
||||
tableInfo ? JSON.stringify({ __isStreamHeader: true, tableInfo }) : ''
|
||||
);
|
||||
socket.emitChanged(`archive-files-changed`, { folder });
|
||||
return true;
|
||||
},
|
||||
|
||||
deleteFile_meta: true,
|
||||
async deleteFile({ folder, file, fileType }) {
|
||||
await fs.unlink(path.join(resolveArchiveFolder(folder), `${file}.${fileType}`));
|
||||
@@ -158,7 +196,7 @@ module.exports = {
|
||||
deleteFolder_meta: true,
|
||||
async deleteFolder({ folder }) {
|
||||
if (!folder) throw new Error('Missing folder parameter');
|
||||
if (folder.endsWith('.link')) {
|
||||
if (folder.endsWith('.link') || folder.endsWith('.zip')) {
|
||||
await fs.unlink(path.join(archivedir(), folder));
|
||||
} else {
|
||||
await fs.rmdir(path.join(archivedir(), folder), { recursive: true });
|
||||
@@ -204,9 +242,10 @@ module.exports = {
|
||||
},
|
||||
|
||||
async getNewArchiveFolder({ database }) {
|
||||
const isLink = database.endsWith(database);
|
||||
const name = isLink ? database.slice(0, -5) : database;
|
||||
const suffix = isLink ? '.link' : '';
|
||||
const isLink = database.endsWith('.link');
|
||||
const isZip = database.endsWith('.zip');
|
||||
const name = isLink ? database.slice(0, -5) : isZip ? database.slice(0, -4) : database;
|
||||
const suffix = isLink ? '.link' : isZip ? '.zip' : '';
|
||||
if (!(await fs.exists(path.join(archivedir(), database)))) return database;
|
||||
let index = 2;
|
||||
while (await fs.exists(path.join(archivedir(), `${name}${index}${suffix}`))) {
|
||||
@@ -214,4 +253,58 @@ module.exports = {
|
||||
}
|
||||
return `${name}${index}${suffix}`;
|
||||
},
|
||||
|
||||
getArchiveData_meta: true,
|
||||
async getArchiveData({ folder, file }) {
|
||||
let rows;
|
||||
if (folder.endsWith('.zip')) {
|
||||
rows = await unzipJsonLinesFile(path.join(archivedir(), folder), `${file}.jsonl`);
|
||||
} else {
|
||||
rows = jsonLinesParse(await fs.readFile(path.join(archivedir(), folder, `${file}.jsonl`), { encoding: 'utf8' }));
|
||||
}
|
||||
return rows.filter(x => !x.__isStreamHeader);
|
||||
},
|
||||
|
||||
saveUploadedZip_meta: true,
|
||||
async saveUploadedZip({ filePath, fileName }) {
|
||||
if (!fileName?.endsWith('.zip')) {
|
||||
throw new Error(`${fileName} is not a ZIP file`);
|
||||
}
|
||||
|
||||
const folder = await this.getNewArchiveFolder({ database: fileName });
|
||||
await fs.copyFile(filePath, path.join(archivedir(), folder));
|
||||
socket.emitChanged(`archive-folders-changed`);
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
zip_meta: true,
|
||||
async zip({ folder }) {
|
||||
const newFolder = await this.getNewArchiveFolder({ database: folder + '.zip' });
|
||||
await zipDirectory(path.join(archivedir(), folder), path.join(archivedir(), newFolder));
|
||||
socket.emitChanged(`archive-folders-changed`);
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
unzip_meta: true,
|
||||
async unzip({ folder }) {
|
||||
const newFolder = await this.getNewArchiveFolder({ database: folder.slice(0, -4) });
|
||||
await unzipDirectory(path.join(archivedir(), folder), path.join(archivedir(), newFolder));
|
||||
socket.emitChanged(`archive-folders-changed`);
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
getZippedPath_meta: true,
|
||||
async getZippedPath({ folder }) {
|
||||
if (folder.endsWith('.zip')) {
|
||||
return { filePath: path.join(archivedir(), folder) };
|
||||
}
|
||||
|
||||
const uploadName = crypto.randomUUID();
|
||||
const filePath = path.join(uploadsdir(), uploadName);
|
||||
await zipDirectory(path.join(archivedir(), folder), filePath);
|
||||
return { filePath };
|
||||
},
|
||||
};
|
||||
|
||||
@@ -12,6 +12,22 @@ const {
|
||||
getAuthProviderById,
|
||||
} = require('../auth/authProvider');
|
||||
const storage = require('./storage');
|
||||
const { decryptPasswordString } = require('../utility/crypting');
|
||||
const {
|
||||
createDbGateIdentitySession,
|
||||
startCloudTokenChecking,
|
||||
readCloudTokenHolder,
|
||||
readCloudTestTokenHolder,
|
||||
} = require('../utility/cloudIntf');
|
||||
const socket = require('../utility/socket');
|
||||
const { sendToAuditLog } = require('../utility/auditlog');
|
||||
const {
|
||||
isLoginLicensed,
|
||||
LOGIN_LIMIT_ERROR,
|
||||
markTokenAsLoggedIn,
|
||||
markUserAsActive,
|
||||
markLoginAsLoggedOut,
|
||||
} = require('../utility/loginchecker');
|
||||
|
||||
const logger = getLogger('auth');
|
||||
|
||||
@@ -35,20 +51,30 @@ function authMiddleware(req, res, next) {
|
||||
'/auth/oauth-token',
|
||||
'/auth/login',
|
||||
'/auth/redirect',
|
||||
'/redirect',
|
||||
'/stream',
|
||||
'/storage/get-connections-for-login-page',
|
||||
'/storage/set-admin-password',
|
||||
'/storage/request-password-reset',
|
||||
'/storage/reset-password',
|
||||
'/auth/get-providers',
|
||||
'/connections/dblogin-web',
|
||||
'/connections/dblogin-app',
|
||||
'/connections/dblogin-auth',
|
||||
'/connections/dblogin-auth-token',
|
||||
'/health',
|
||||
'/__health',
|
||||
];
|
||||
|
||||
// console.log('********************* getAuthProvider()', getAuthProvider());
|
||||
|
||||
// const isAdminPage = req.headers['x-is-admin-page'] == 'true';
|
||||
|
||||
if (process.env.SKIP_ALL_AUTH) {
|
||||
// API is not authorized for basic auth
|
||||
return next();
|
||||
}
|
||||
|
||||
if (process.env.BASIC_AUTH) {
|
||||
// API is not authorized for basic auth
|
||||
return next();
|
||||
@@ -67,6 +93,8 @@ function authMiddleware(req, res, next) {
|
||||
try {
|
||||
const decoded = jwt.verify(token, getTokenSecret());
|
||||
req.user = decoded;
|
||||
markUserAsActive(decoded.licenseUid, token);
|
||||
|
||||
return next();
|
||||
} catch (err) {
|
||||
if (skipAuth) {
|
||||
@@ -74,7 +102,7 @@ function authMiddleware(req, res, next) {
|
||||
return next();
|
||||
}
|
||||
|
||||
logger.error(extractErrorLogData(err), 'Sending invalid token error');
|
||||
logger.error(extractErrorLogData(err), 'DBGM-00098 Sending invalid token error');
|
||||
|
||||
return unauthorizedResponse(req, res, 'invalid token');
|
||||
}
|
||||
@@ -82,46 +110,75 @@ function authMiddleware(req, res, next) {
|
||||
|
||||
module.exports = {
|
||||
oauthToken_meta: true,
|
||||
async oauthToken(params) {
|
||||
async oauthToken(params, req) {
|
||||
const { amoid } = params;
|
||||
return getAuthProviderById(amoid).oauthToken(params);
|
||||
return getAuthProviderById(amoid).oauthToken(params, req);
|
||||
},
|
||||
login_meta: true,
|
||||
async login(params) {
|
||||
async login(params, req) {
|
||||
const { amoid, login, password, isAdminPage } = params;
|
||||
|
||||
if (isAdminPage) {
|
||||
let adminPassword = process.env.ADMIN_PASSWORD;
|
||||
if (!adminPassword) {
|
||||
const adminConfig = await storage.readConfig({ group: 'admin' });
|
||||
adminPassword = adminConfig?.adminPassword;
|
||||
adminPassword = decryptPasswordString(adminConfig?.adminPassword);
|
||||
}
|
||||
if (adminPassword && adminPassword == password) {
|
||||
if (!(await isLoginLicensed(req, `superadmin`))) {
|
||||
return { error: LOGIN_LIMIT_ERROR };
|
||||
}
|
||||
|
||||
sendToAuditLog(req, {
|
||||
category: 'auth',
|
||||
component: 'AuthController',
|
||||
action: 'login',
|
||||
event: 'login.admin',
|
||||
severity: 'info',
|
||||
message: 'Administration login successful',
|
||||
});
|
||||
|
||||
const licenseUid = `superadmin`;
|
||||
const accessToken = jwt.sign(
|
||||
{
|
||||
login: 'superadmin',
|
||||
roleId: -3,
|
||||
licenseUid,
|
||||
amoid: 'superadmin',
|
||||
},
|
||||
getTokenSecret(),
|
||||
{
|
||||
expiresIn: getTokenLifetime(),
|
||||
}
|
||||
);
|
||||
markTokenAsLoggedIn(licenseUid, accessToken);
|
||||
|
||||
return {
|
||||
accessToken: jwt.sign(
|
||||
{
|
||||
login: 'superadmin',
|
||||
permissions: await storage.loadSuperadminPermissions(),
|
||||
roleId: -3,
|
||||
},
|
||||
getTokenSecret(),
|
||||
{
|
||||
expiresIn: getTokenLifetime(),
|
||||
}
|
||||
),
|
||||
accessToken,
|
||||
};
|
||||
}
|
||||
|
||||
sendToAuditLog(req, {
|
||||
category: 'auth',
|
||||
component: 'AuthController',
|
||||
action: 'loginFail',
|
||||
event: 'login.adminFailed',
|
||||
severity: 'warn',
|
||||
message: 'Administraton login failed',
|
||||
});
|
||||
|
||||
return { error: 'Login failed' };
|
||||
}
|
||||
|
||||
return getAuthProviderById(amoid).login(login, password);
|
||||
return getAuthProviderById(amoid).login(login, password, undefined, req);
|
||||
},
|
||||
|
||||
getProviders_meta: true,
|
||||
getProviders() {
|
||||
return {
|
||||
providers: getAuthProviders().map(x => x.toJson()),
|
||||
providers: getAuthProviders()
|
||||
.filter(x => !x.skipInList)
|
||||
.map(x => x.toJson()),
|
||||
default: getDefaultAuthProvider()?.amoid,
|
||||
};
|
||||
},
|
||||
@@ -132,5 +189,40 @@ module.exports = {
|
||||
return getAuthProviderById(amoid).redirect(params);
|
||||
},
|
||||
|
||||
createCloudLoginSession_meta: true,
|
||||
async createCloudLoginSession({ client, redirectUri }) {
|
||||
const res = await createDbGateIdentitySession(client, redirectUri);
|
||||
startCloudTokenChecking(res.sid, tokenHolder => {
|
||||
socket.emit('got-cloud-token', tokenHolder);
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
});
|
||||
return res;
|
||||
},
|
||||
|
||||
cloudLoginRedirected_meta: true,
|
||||
async cloudLoginRedirected({ sid }) {
|
||||
const tokenHolder = await readCloudTokenHolder(sid);
|
||||
return tokenHolder;
|
||||
},
|
||||
|
||||
cloudTestLogin_meta: true,
|
||||
async cloudTestLogin({ email }) {
|
||||
const tokenHolder = await readCloudTestTokenHolder(email);
|
||||
return tokenHolder;
|
||||
},
|
||||
|
||||
logoutAdmin_meta: true,
|
||||
async logoutAdmin() {
|
||||
await markLoginAsLoggedOut('superadmin');
|
||||
return true;
|
||||
},
|
||||
|
||||
logoutUser_meta: true,
|
||||
async logoutUser({}, req) {
|
||||
await markLoginAsLoggedOut(req?.user?.licenseUid);
|
||||
return true;
|
||||
},
|
||||
|
||||
authMiddleware,
|
||||
};
|
||||
|
||||
318
packages/api/src/controllers/cloud.js
Normal file
318
packages/api/src/controllers/cloud.js
Normal file
@@ -0,0 +1,318 @@
|
||||
const {
|
||||
getPublicCloudFiles,
|
||||
getPublicFileData,
|
||||
refreshPublicFiles,
|
||||
callCloudApiGet,
|
||||
callCloudApiPost,
|
||||
getCloudFolderEncryptor,
|
||||
getCloudContent,
|
||||
putCloudContent,
|
||||
removeCloudCachedConnection,
|
||||
getPromoWidgetData,
|
||||
getPromoWidgetList,
|
||||
getPromoWidgetPreview,
|
||||
} = require('../utility/cloudIntf');
|
||||
const connections = require('./connections');
|
||||
const socket = require('../utility/socket');
|
||||
const { recryptConnection, getInternalEncryptor, encryptConnection } = require('../utility/crypting');
|
||||
const { getConnectionLabel, getLogger, extractErrorLogData } = require('dbgate-tools');
|
||||
const logger = getLogger('cloud');
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs-extra');
|
||||
const { getAiGatewayServer } = require('../utility/authProxy');
|
||||
|
||||
module.exports = {
|
||||
publicFiles_meta: true,
|
||||
async publicFiles() {
|
||||
const res = await getPublicCloudFiles();
|
||||
return res;
|
||||
},
|
||||
|
||||
publicFileData_meta: true,
|
||||
async publicFileData({ path }) {
|
||||
const res = getPublicFileData(path);
|
||||
return res;
|
||||
},
|
||||
|
||||
refreshPublicFiles_meta: true,
|
||||
async refreshPublicFiles({ isRefresh }, req) {
|
||||
await refreshPublicFiles(isRefresh, req?.headers?.['x-ui-language']);
|
||||
return {
|
||||
status: 'ok',
|
||||
};
|
||||
},
|
||||
|
||||
contentList_meta: true,
|
||||
async contentList() {
|
||||
try {
|
||||
const resp = await callCloudApiGet('content-list');
|
||||
return resp;
|
||||
} catch (err) {
|
||||
logger.error(extractErrorLogData(err), 'DBGM-00099 Error getting cloud content list');
|
||||
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
getContent_meta: true,
|
||||
async getContent({ folid, cntid }) {
|
||||
const resp = await getCloudContent(folid, cntid);
|
||||
return resp;
|
||||
},
|
||||
|
||||
putContent_meta: true,
|
||||
async putContent({ folid, cntid, content, name, type }) {
|
||||
const resp = await putCloudContent(folid, cntid, content, name, type, {});
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return resp;
|
||||
},
|
||||
|
||||
createFolder_meta: true,
|
||||
async createFolder({ name }) {
|
||||
const resp = await callCloudApiPost(`folders/create`, { name });
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return resp;
|
||||
},
|
||||
|
||||
grantFolder_meta: true,
|
||||
async grantFolder({ inviteLink }) {
|
||||
const m = inviteLink.match(/^dbgate\:\/\/folder\/v1\/([a-zA-Z0-9]+)\?mode=(read|write|admin)$/);
|
||||
if (!m) {
|
||||
throw new Error('Invalid invite link format');
|
||||
}
|
||||
const invite = m[1];
|
||||
const mode = m[2];
|
||||
|
||||
const resp = await callCloudApiPost(`folders/grant/${mode}`, { invite });
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return resp;
|
||||
},
|
||||
|
||||
renameFolder_meta: true,
|
||||
async renameFolder({ folid, name }) {
|
||||
const resp = await callCloudApiPost(`folders/rename`, { folid, name });
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return resp;
|
||||
},
|
||||
|
||||
deleteFolder_meta: true,
|
||||
async deleteFolder({ folid }) {
|
||||
const resp = await callCloudApiPost(`folders/delete`, { folid });
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return resp;
|
||||
},
|
||||
|
||||
getInviteToken_meta: true,
|
||||
async getInviteToken({ folid, role }) {
|
||||
const resp = await callCloudApiGet(`invite-token/${folid}/${role}`);
|
||||
return resp;
|
||||
},
|
||||
|
||||
refreshContent_meta: true,
|
||||
async refreshContent() {
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return {
|
||||
status: 'ok',
|
||||
};
|
||||
},
|
||||
|
||||
copyConnectionCloud_meta: true,
|
||||
async copyConnectionCloud({ conid, folid }) {
|
||||
const conn = await connections.getCore({ conid });
|
||||
const folderEncryptor = await getCloudFolderEncryptor(folid);
|
||||
const recryptedConn = recryptConnection(conn, getInternalEncryptor(), folderEncryptor);
|
||||
const connToSend = _.omit(recryptedConn, ['_id']);
|
||||
const resp = await putCloudContent(
|
||||
folid,
|
||||
undefined,
|
||||
JSON.stringify(connToSend),
|
||||
getConnectionLabel(conn),
|
||||
'connection',
|
||||
{
|
||||
connectionColor: conn.connectionColor,
|
||||
connectionEngine: conn.engine,
|
||||
}
|
||||
);
|
||||
return resp;
|
||||
},
|
||||
|
||||
saveConnection_meta: true,
|
||||
async saveConnection({ folid, connection }) {
|
||||
let cntid = undefined;
|
||||
if (connection._id) {
|
||||
const m = connection._id.match(/^cloud\:\/\/(.+)\/(.+)$/);
|
||||
if (!m) {
|
||||
throw new Error('Invalid cloud connection ID format');
|
||||
}
|
||||
folid = m[1];
|
||||
cntid = m[2];
|
||||
}
|
||||
|
||||
if (!folid) {
|
||||
throw new Error('Missing cloud folder ID');
|
||||
}
|
||||
|
||||
const folderEncryptor = await getCloudFolderEncryptor(folid);
|
||||
const recryptedConn = encryptConnection(connection, folderEncryptor);
|
||||
const resp = await putCloudContent(
|
||||
folid,
|
||||
cntid,
|
||||
JSON.stringify(recryptedConn),
|
||||
getConnectionLabel(recryptedConn),
|
||||
'connection',
|
||||
{
|
||||
connectionColor: connection.connectionColor,
|
||||
connectionEngine: connection.engine,
|
||||
}
|
||||
);
|
||||
|
||||
if (resp.apiErrorMessage) {
|
||||
return resp;
|
||||
}
|
||||
|
||||
removeCloudCachedConnection(folid, resp.cntid);
|
||||
cntid = resp.cntid;
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return {
|
||||
...recryptedConn,
|
||||
_id: `cloud://${folid}/${cntid}`,
|
||||
};
|
||||
},
|
||||
|
||||
duplicateConnection_meta: true,
|
||||
async duplicateConnection({ conid }) {
|
||||
const m = conid.match(/^cloud\:\/\/(.+)\/(.+)$/);
|
||||
if (!m) {
|
||||
throw new Error('Invalid cloud connection ID format');
|
||||
}
|
||||
const folid = m[1];
|
||||
const cntid = m[2];
|
||||
const respGet = await getCloudContent(folid, cntid);
|
||||
const conn = JSON.parse(respGet.content);
|
||||
const conn2 = {
|
||||
...conn,
|
||||
displayName: getConnectionLabel(conn) + ' - copy',
|
||||
};
|
||||
const respPut = await putCloudContent(folid, undefined, JSON.stringify(conn2), conn2.displayName, 'connection', {
|
||||
connectionColor: conn.connectionColor,
|
||||
connectionEngine: conn.engine,
|
||||
});
|
||||
return respPut;
|
||||
},
|
||||
|
||||
deleteConnection_meta: true,
|
||||
async deleteConnection({ conid }) {
|
||||
const m = conid.match(/^cloud\:\/\/(.+)\/(.+)$/);
|
||||
if (!m) {
|
||||
throw new Error('Invalid cloud connection ID format');
|
||||
}
|
||||
const folid = m[1];
|
||||
const cntid = m[2];
|
||||
const resp = await callCloudApiPost(`content/delete/${folid}/${cntid}`);
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return resp;
|
||||
},
|
||||
|
||||
deleteContent_meta: true,
|
||||
async deleteContent({ folid, cntid }) {
|
||||
const resp = await callCloudApiPost(`content/delete/${folid}/${cntid}`);
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return resp;
|
||||
},
|
||||
|
||||
renameContent_meta: true,
|
||||
async renameContent({ folid, cntid, name }) {
|
||||
const resp = await callCloudApiPost(`content/rename/${folid}/${cntid}`, { name });
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return resp;
|
||||
},
|
||||
|
||||
saveFile_meta: true,
|
||||
async saveFile({ folid, cntid, fileName, data, contentFolder, format }) {
|
||||
const resp = await putCloudContent(folid, cntid, data, fileName, 'file', { contentFolder, contentType: format });
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return resp;
|
||||
},
|
||||
|
||||
copyFile_meta: true,
|
||||
async copyFile({ folid, cntid, name }) {
|
||||
const resp = await callCloudApiPost(`content/duplicate/${folid}/${cntid}`, { name });
|
||||
socket.emitChanged('cloud-content-changed');
|
||||
socket.emit('cloud-content-updated');
|
||||
return resp;
|
||||
},
|
||||
|
||||
exportFile_meta: true,
|
||||
async exportFile({ folid, cntid, filePath }, req) {
|
||||
const { content } = await getCloudContent(folid, cntid);
|
||||
if (!content) {
|
||||
throw new Error('File not found');
|
||||
}
|
||||
await fs.writeFile(filePath, content);
|
||||
return true;
|
||||
},
|
||||
|
||||
folderUsers_meta: true,
|
||||
async folderUsers({ folid }) {
|
||||
const resp = await callCloudApiGet(`content-folders/users/${folid}`);
|
||||
return resp;
|
||||
},
|
||||
|
||||
setFolderUserRole_meta: true,
|
||||
async setFolderUserRole({ folid, email, role }) {
|
||||
const resp = await callCloudApiPost(`content-folders/set-user-role/${folid}`, { email, role });
|
||||
return resp;
|
||||
},
|
||||
|
||||
removeFolderUser_meta: true,
|
||||
async removeFolderUser({ folid, email }) {
|
||||
const resp = await callCloudApiPost(`content-folders/remove-user/${folid}`, { email });
|
||||
return resp;
|
||||
},
|
||||
|
||||
getAiGateway_meta: true,
|
||||
async getAiGateway() {
|
||||
return getAiGatewayServer();
|
||||
},
|
||||
|
||||
premiumPromoWidget_meta: true,
|
||||
async premiumPromoWidget() {
|
||||
const data = await getPromoWidgetData();
|
||||
if (data?.state != 'data') {
|
||||
return null;
|
||||
}
|
||||
if (data.validTo && new Date().getTime() > new Date(data.validTo).getTime()) {
|
||||
return null;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
promoWidgetList_meta: true,
|
||||
async promoWidgetList() {
|
||||
return getPromoWidgetList();
|
||||
},
|
||||
|
||||
promoWidgetPreview_meta: true,
|
||||
async promoWidgetPreview({ campaign, variant }) {
|
||||
return getPromoWidgetPreview(campaign, variant);
|
||||
},
|
||||
|
||||
// chatStream_meta: {
|
||||
// raw: true,
|
||||
// method: 'post',
|
||||
// },
|
||||
// chatStream(req, res) {
|
||||
// callChatStream(req.body, res);
|
||||
// },
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user