mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 20:38:52 +00:00
Compare commits
2827 Commits
v0.0.1-alp
...
v0.6.0-can
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
627d8ef787 | ||
|
|
5563823a7a | ||
|
|
d6804bb0fd | ||
|
|
1350633690 | ||
|
|
50196d8fde | ||
|
|
2e0ccb53ec | ||
|
|
1498ee405b | ||
|
|
cb863c4afa | ||
|
|
2629d39501 | ||
|
|
38305cd984 | ||
|
|
93116c24f2 | ||
|
|
017b9c8615 | ||
|
|
9ce3a96862 | ||
|
|
a0ff520ba4 | ||
|
|
a8b8986d89 | ||
|
|
8ffc096fee | ||
|
|
7e457f7b4c | ||
|
|
aedf2d339e | ||
|
|
ffd5ae52b3 | ||
|
|
3093194da8 | ||
|
|
68b4f792f0 | ||
|
|
e2c6e4f9fc | ||
|
|
9ff7dbffb7 | ||
|
|
0c561da061 | ||
|
|
06951319a6 | ||
|
|
0bfcab4067 | ||
|
|
2c4db4fa16 | ||
|
|
23b4f9ee12 | ||
|
|
e5330b1917 | ||
|
|
183611a556 | ||
|
|
7786456ba4 | ||
|
|
f4bf7e3ddf | ||
|
|
05d88215d1 | ||
|
|
b240a70e51 | ||
|
|
00fd468e9b | ||
|
|
b5a7f8b7eb | ||
|
|
f03277fd17 | ||
|
|
ee93071149 | ||
|
|
21fdced2bd | ||
|
|
10b4558947 | ||
|
|
0fbed5d9d6 | ||
|
|
8d117123d7 | ||
|
|
063ffda09d | ||
|
|
39c83bd25b | ||
|
|
4444c3d1a6 | ||
|
|
717dd93f37 | ||
|
|
c58673c55f | ||
|
|
768e55072d | ||
|
|
8c84daec2b | ||
|
|
e54a5b6128 | ||
|
|
ee1e50f391 | ||
|
|
268636c440 | ||
|
|
06fa0cdb60 | ||
|
|
73dbb39009 | ||
|
|
47848cb5da | ||
|
|
eff6a03a51 | ||
|
|
08f6a41ef4 | ||
|
|
6d1345ffe5 | ||
|
|
689f615b11 | ||
|
|
f82ea5d9c4 | ||
|
|
dc4979a80c | ||
|
|
1f48bc4301 | ||
|
|
beabd1e050 | ||
|
|
19e20a6a20 | ||
|
|
e4f13ddae4 | ||
|
|
752d0545ca | ||
|
|
08341d3d6c | ||
|
|
ef665df330 | ||
|
|
b38017cd23 | ||
|
|
0c550a2827 | ||
|
|
87ffdad862 | ||
|
|
c6e8024e16 | ||
|
|
4200b3c3e5 | ||
|
|
10976a9257 | ||
|
|
b81b5439ae | ||
|
|
a84ca43ce2 | ||
|
|
b978bb171a | ||
|
|
b937c1b5f6 | ||
|
|
3c97e01513 | ||
|
|
7c2574b1ca | ||
|
|
5432aae85c | ||
|
|
be41c99602 | ||
|
|
c41718e80d | ||
|
|
242e074ae6 | ||
|
|
793b689b81 | ||
|
|
53db6a6e9d | ||
|
|
cba3293326 | ||
|
|
11d1d773ff | ||
|
|
f071361347 | ||
|
|
2c18fadb2d | ||
|
|
1e8c5a4482 | ||
|
|
4f99ad2db4 | ||
|
|
95bc5cac49 | ||
|
|
3a6be4510b | ||
|
|
41d4af1dc1 | ||
|
|
d1457075b3 | ||
|
|
d040a7fb50 | ||
|
|
f1c3d575ad | ||
|
|
a942add87a | ||
|
|
d408a8bbb1 | ||
|
|
4298ff7c7c | ||
|
|
c55bfcc1fc | ||
|
|
d795fb6b37 | ||
|
|
29cbbf5c97 | ||
|
|
aaa4b4f0cb | ||
|
|
10cd000822 | ||
|
|
496225a92e | ||
|
|
1ef408c9ad | ||
|
|
8d8119b39b | ||
|
|
80c1f9e546 | ||
|
|
dbd3249ae5 | ||
|
|
fbbcb4bad9 | ||
|
|
33069c87d0 | ||
|
|
637b8203d3 | ||
|
|
92859bf8b9 | ||
|
|
8a617f91e6 | ||
|
|
84b36c1d35 | ||
|
|
2c49c774af | ||
|
|
de0b300aca | ||
|
|
4a50fe584c | ||
|
|
f7d1d922fa | ||
|
|
1b12972afd | ||
|
|
33c48eed79 | ||
|
|
9631c99f7b | ||
|
|
097cce34b5 | ||
|
|
52b9734a7b | ||
|
|
6d7f06c1c3 | ||
|
|
238f69b4e7 | ||
|
|
3d43e61087 | ||
|
|
66c3b09c67 | ||
|
|
1e84ad1484 | ||
|
|
b3a3911cea | ||
|
|
86988bd6e8 | ||
|
|
9096ac2960 | ||
|
|
ec39c23fb7 | ||
|
|
b036fe8502 | ||
|
|
71142a3f1d | ||
|
|
aace740df5 | ||
|
|
f42d656cfa | ||
|
|
88124994e1 | ||
|
|
5a881ec223 | ||
|
|
12b61d34c3 | ||
|
|
4eff5f3c38 | ||
|
|
648fad65e0 | ||
|
|
a2844e54d2 | ||
|
|
850cfe1187 | ||
|
|
9030767d16 | ||
|
|
a4e7d0d0c3 | ||
|
|
99898b2260 | ||
|
|
1031fbc7ec | ||
|
|
31cccafb40 | ||
|
|
73a7c01580 | ||
|
|
f9b012cac9 | ||
|
|
101cd18067 | ||
|
|
2c466617de | ||
|
|
2ff5ef9d5d | ||
|
|
903b6eaf30 | ||
|
|
fd4b664e4f | ||
|
|
51a4bdc5e4 | ||
|
|
ee695bbcb9 | ||
|
|
ef0521fa2a | ||
|
|
73d5b2081a | ||
|
|
70fbbb39c1 | ||
|
|
b6ca2aa063 | ||
|
|
b3c1434055 | ||
|
|
4599a9a601 | ||
|
|
549dddc65f | ||
|
|
9f8b38f9f3 | ||
|
|
3a5a66a5a3 | ||
|
|
b4bb57b2a5 | ||
|
|
3df3498523 | ||
|
|
567092a1ff | ||
|
|
f3e1c1eb08 | ||
|
|
a04cfe2b68 | ||
|
|
c1a65b6b76 | ||
|
|
f3cbe54625 | ||
|
|
dcf7e83eec | ||
|
|
50006efb57 | ||
|
|
606f6652ac | ||
|
|
afff15c435 | ||
|
|
f7b8797bb2 | ||
|
|
2b05a1254b | ||
|
|
40e7074475 | ||
|
|
e1ad3e38b9 | ||
|
|
f03fdde770 | ||
|
|
d2eba54550 | ||
|
|
fa7baaf5c1 | ||
|
|
a4d8b65eef | ||
|
|
83dafa149c | ||
|
|
3a25f13734 | ||
|
|
db52c63d25 | ||
|
|
80f4578f76 | ||
|
|
15a7e93058 | ||
|
|
1c41731b4e | ||
|
|
a807647639 | ||
|
|
3f1293ca3c | ||
|
|
ad58b4d1e9 | ||
|
|
7e61708850 | ||
|
|
5c673a8ffc | ||
|
|
4528df07a5 | ||
|
|
b6eb017bd4 | ||
|
|
9d3b9e9848 | ||
|
|
04fc619f52 | ||
|
|
06ef6da370 | ||
|
|
d3ce90e721 | ||
|
|
9c94d05dd8 | ||
|
|
ef8dea8cb2 | ||
|
|
c27c241482 | ||
|
|
b73e9189ef | ||
|
|
c95b8e9d71 | ||
|
|
ab8669882a | ||
|
|
7ff12a6d0f | ||
|
|
339b133e3f | ||
|
|
be9095ec19 | ||
|
|
33261558f6 | ||
|
|
2ad1b770d0 | ||
|
|
74e21311dc | ||
|
|
bf83bfcf63 | ||
|
|
70d8f9a0a7 | ||
|
|
7d246f87e7 | ||
|
|
1ca9fb8ff4 | ||
|
|
2c95a0a757 | ||
|
|
a49d5ea1e2 | ||
|
|
84e2710e87 | ||
|
|
044e6da00d | ||
|
|
023cbc30ea | ||
|
|
7094385d8b | ||
|
|
f66d402cf7 | ||
|
|
971e256cd3 | ||
|
|
88a297c3c1 | ||
|
|
4bb50e8c25 | ||
|
|
acc5afdd4f | ||
|
|
9ec6768272 | ||
|
|
5a124831b8 | ||
|
|
01115f8957 | ||
|
|
a5a6203a95 | ||
|
|
4a473f5518 | ||
|
|
6cddacb953 | ||
|
|
00f44c72ce | ||
|
|
44011b4695 | ||
|
|
e0cd2e780b | ||
|
|
985bb55d82 | ||
|
|
66d0640042 | ||
|
|
e399682cad | ||
|
|
c4e90f2d8b | ||
|
|
b38b01fc98 | ||
|
|
0a0f825a15 | ||
|
|
d24c43e750 | ||
|
|
90b51031d2 | ||
|
|
1e771131b0 | ||
|
|
4d7a3e5bf1 | ||
|
|
92b1244fd7 | ||
|
|
d6b1b9f6cf | ||
|
|
b2e93433e1 | ||
|
|
97b1a31f8d | ||
|
|
4a1c15c1e9 | ||
|
|
f8d1513bb6 | ||
|
|
372377dd6b | ||
|
|
63f7b2556e | ||
|
|
c08c587efb | ||
|
|
65c1bee7f0 | ||
|
|
227f59cadc | ||
|
|
031ab2cfa2 | ||
|
|
9f33e73429 | ||
|
|
f1670af15d | ||
|
|
0d7f65ab36 | ||
|
|
3a053af50c | ||
|
|
c6be29f944 | ||
|
|
9ffe45102b | ||
|
|
6448b6a515 | ||
|
|
ba462fb79b | ||
|
|
f36d415c3d | ||
|
|
f6fb049ff2 | ||
|
|
94063352f5 | ||
|
|
c895c18deb | ||
|
|
346484ed44 | ||
|
|
18223c22ef | ||
|
|
ea9861bfa0 | ||
|
|
7be96a2e41 | ||
|
|
91c3040db7 | ||
|
|
a92d0fff4a | ||
|
|
64e5d65eb3 | ||
|
|
11de3a681f | ||
|
|
54a30bbf20 | ||
|
|
6c77006bcc | ||
|
|
143a55a6e8 | ||
|
|
19894aad5a | ||
|
|
f534e4a6dd | ||
|
|
3d70a36dd3 | ||
|
|
9c517907eb | ||
|
|
4cb6b8fdc8 | ||
|
|
134e1e8668 | ||
|
|
c76bbeab67 | ||
|
|
ec50d721ea | ||
|
|
7bbe67af43 | ||
|
|
caa292e097 | ||
|
|
73b8b805c6 | ||
|
|
084d4e043a | ||
|
|
69a9c34f11 | ||
|
|
d742cab1d5 | ||
|
|
8b3c1fb363 | ||
|
|
ec445207d6 | ||
|
|
49281e68a6 | ||
|
|
a918d6e14c | ||
|
|
7cf7187893 | ||
|
|
2383165470 | ||
|
|
43a96fe8e3 | ||
|
|
b771a2504b | ||
|
|
8d2fefb5f8 | ||
|
|
c71e5f1c96 | ||
|
|
5b96fb0db3 | ||
|
|
46cd0c5c9a | ||
|
|
261a41f8da | ||
|
|
bd387f6551 | ||
|
|
5335118e93 | ||
|
|
70313eb5ee | ||
|
|
ccd2b79d20 | ||
|
|
5ca94db5d2 | ||
|
|
d58f9db289 | ||
|
|
93e78c315c | ||
|
|
3954f309aa | ||
|
|
f902d0c324 | ||
|
|
e79fb1ae3a | ||
|
|
08d67b316c | ||
|
|
d12c00d5cb | ||
|
|
68bb538dd1 | ||
|
|
b394764b1c | ||
|
|
01a686dc28 | ||
|
|
32b206a137 | ||
|
|
42756045bb | ||
|
|
934e242116 | ||
|
|
6571ec2df6 | ||
|
|
7d64815aca | ||
|
|
f20a151e57 | ||
|
|
6180a4c3cb | ||
|
|
2bcda973d3 | ||
|
|
1162bffb30 | ||
|
|
2a2d682211 | ||
|
|
8f53043100 | ||
|
|
6d5b101bb3 | ||
|
|
8bcef957fc | ||
|
|
d9c4fc3a9e | ||
|
|
407c72ba2c | ||
|
|
95aa86cdf0 | ||
|
|
25d7f7c848 | ||
|
|
23e33a6061 | ||
|
|
f647fb6070 | ||
|
|
af04c1b889 | ||
|
|
ba4a2fc9d2 | ||
|
|
fb0d2992c2 | ||
|
|
ea00c208e6 | ||
|
|
6ce270bffd | ||
|
|
9dcb96839b | ||
|
|
5535440c55 | ||
|
|
db8fe4e09a | ||
|
|
07a11ed767 | ||
|
|
a06113d48c | ||
|
|
2e823c2fee | ||
|
|
f3af128baf | ||
|
|
a599364218 | ||
|
|
c0669359ed | ||
|
|
024c469a2c | ||
|
|
f5e51bb471 | ||
|
|
778f76dfed | ||
|
|
b2ff6e379c | ||
|
|
cc4e48e5bb | ||
|
|
7afc61ac36 | ||
|
|
537200c064 | ||
|
|
d95dbd5af4 | ||
|
|
7fea55d81f | ||
|
|
ea2a146c82 | ||
|
|
9acbba7016 | ||
|
|
401cad799e | ||
|
|
d9e42d6a0f | ||
|
|
73a1a979f9 | ||
|
|
626b906bc0 | ||
|
|
889503d1cc | ||
|
|
20e56cc474 | ||
|
|
e50bf9fbfe | ||
|
|
d4b2b9ab44 | ||
|
|
ea06df4386 | ||
|
|
fd34a99665 | ||
|
|
5a1e8b0c93 | ||
|
|
74657c2fa1 | ||
|
|
7d55d0ea0b | ||
|
|
efe5444816 | ||
|
|
5ac36b6f0a | ||
|
|
b6bdf257e4 | ||
|
|
773554bbac | ||
|
|
2e354ae59e | ||
|
|
999796f988 | ||
|
|
17fa77e5ae | ||
|
|
2601b26c16 | ||
|
|
1ad4b0fc89 | ||
|
|
0577298344 | ||
|
|
88447b438b | ||
|
|
0956b5ccc7 | ||
|
|
69cc0f5cb9 | ||
|
|
fe60318d7a | ||
|
|
d8931db300 | ||
|
|
c209aa1d15 | ||
|
|
164d357487 | ||
|
|
ee8f6a760e | ||
|
|
76c0d01640 | ||
|
|
0c87bf36ca | ||
|
|
116caff3c7 | ||
|
|
ae4339ea28 | ||
|
|
a24b747ee8 | ||
|
|
3e3386d24a | ||
|
|
89f53190db | ||
|
|
37169ae37d | ||
|
|
02a8daad5f | ||
|
|
69cd22a3b8 | ||
|
|
5bd3aa4a80 | ||
|
|
c023d0a2b8 | ||
|
|
5129ab3db8 | ||
|
|
67a5d1520d | ||
|
|
215bb24ec4 | ||
|
|
2f3a13c439 | ||
|
|
9a20f50b05 | ||
|
|
dbcadbaf60 | ||
|
|
5c46c7d9fc | ||
|
|
cd089ed64a | ||
|
|
b1618e9ce1 | ||
|
|
b36588714e | ||
|
|
83000fa832 | ||
|
|
5dbbabae57 | ||
|
|
196b9f2dbb | ||
|
|
fcf5d5602d | ||
|
|
89c1e4c205 | ||
|
|
06a69b0767 | ||
|
|
2cf8ab434e | ||
|
|
487ef35563 | ||
|
|
95879cc1d0 | ||
|
|
e0eecffb2f | ||
|
|
fa150a93a0 | ||
|
|
20a7a35e96 | ||
|
|
ed8f07f102 | ||
|
|
f5574c68fe | ||
|
|
60324b8967 | ||
|
|
5e56728dbc | ||
|
|
e02ab36aae | ||
|
|
cf56fc9551 | ||
|
|
676a5793e2 | ||
|
|
7299efe16a | ||
|
|
fd65dd66a1 | ||
|
|
b0d13fbabe | ||
|
|
5717d126ee | ||
|
|
bd67554f5e | ||
|
|
c55d61a641 | ||
|
|
bdb1264f09 | ||
|
|
acac585eb2 | ||
|
|
f935bbaf5d | ||
|
|
bb1224f9ee | ||
|
|
3fa7d17dca | ||
|
|
c9bd4e34b3 | ||
|
|
91c32b6715 | ||
|
|
b6ded30770 | ||
|
|
4dd1490eef | ||
|
|
d8d965b9b8 | ||
|
|
14f073c8ea | ||
|
|
94d284d841 | ||
|
|
79128a3c3e | ||
|
|
127e9bdba2 | ||
|
|
3180d961dd | ||
|
|
926bf49b26 | ||
|
|
5500b3b1ed | ||
|
|
68144fb2dc | ||
|
|
9cd59d9146 | ||
|
|
8a03f9ff1f | ||
|
|
9c6fb82c82 | ||
|
|
c1e8818db4 | ||
|
|
eb33289f98 | ||
|
|
998587b3b8 | ||
|
|
62955e7de4 | ||
|
|
f18127dfd6 | ||
|
|
6917d2100f | ||
|
|
5faa2760cd | ||
|
|
f9811c85bc | ||
|
|
c9318d3790 | ||
|
|
c87aad436f | ||
|
|
e19c32aa5d | ||
|
|
dbbc05e5f0 | ||
|
|
751ad9716f | ||
|
|
99be6183e6 | ||
|
|
abdee7fac2 | ||
|
|
7d3ae9a0c9 | ||
|
|
600adb3dd7 | ||
|
|
995504d1f6 | ||
|
|
595de24cfd | ||
|
|
69b13aa30f | ||
|
|
edf7913e12 | ||
|
|
5a508b1fe4 | ||
|
|
26b030ecda | ||
|
|
f478c9ce9e | ||
|
|
3e10f49fc7 | ||
|
|
316223b784 | ||
|
|
4c6505cdf2 | ||
|
|
7fb5b1f65b | ||
|
|
79fc59248f | ||
|
|
8578ff9714 | ||
|
|
f00eda2568 | ||
|
|
bf85db1952 | ||
|
|
bdc29fc5f8 | ||
|
|
c9ea53c2d5 | ||
|
|
1f005bba9b | ||
|
|
427a5e7545 | ||
|
|
2fba1fa7c8 | ||
|
|
93fd8aedb3 | ||
|
|
dc768e0ba9 | ||
|
|
d780e90d88 | ||
|
|
a1600a3671 | ||
|
|
ed29c5fbd9 | ||
|
|
021bf6534b | ||
|
|
628ce08d8d | ||
|
|
c2b1a9b118 | ||
|
|
449ffbc73f | ||
|
|
66dec34209 | ||
|
|
b01deaa786 | ||
|
|
0968a26a84 | ||
|
|
d8e48ef6aa | ||
|
|
6d13716e97 | ||
|
|
40903a9070 | ||
|
|
3c04588110 | ||
|
|
bb1f197d1c | ||
|
|
3e299b97c3 | ||
|
|
9eec8d0f1e | ||
|
|
56acb2bdeb | ||
|
|
a415e4aa5c | ||
|
|
3eba199aca | ||
|
|
dd3f9709c2 | ||
|
|
5a7a59afea | ||
|
|
d13174cedf | ||
|
|
e75750d587 | ||
|
|
1886606f96 | ||
|
|
69721f2a61 | ||
|
|
84d27e939d | ||
|
|
4aea39fb94 | ||
|
|
6be94ca906 | ||
|
|
6a7b5601aa | ||
|
|
2551785451 | ||
|
|
059d9e5de2 | ||
|
|
35d4560e9f | ||
|
|
8ed40bfae9 | ||
|
|
e8b7ff527c | ||
|
|
17e29f50ab | ||
|
|
cc8c069f57 | ||
|
|
237756ddc5 | ||
|
|
156edb1d4b | ||
|
|
ba2295c426 | ||
|
|
40e167aecc | ||
|
|
80b04fe97f | ||
|
|
e2395af827 | ||
|
|
180382daf5 | ||
|
|
eb7d5fd7a1 | ||
|
|
215db27cd6 | ||
|
|
64dac7cc1c | ||
|
|
7ccde4b272 | ||
|
|
12c6b67f68 | ||
|
|
9c9021cbbc | ||
|
|
45260543e1 | ||
|
|
e7d6bda7a5 | ||
|
|
a8540cceae | ||
|
|
33320bd38e | ||
|
|
6a0209dde2 | ||
|
|
a558d0c868 | ||
|
|
05ac48b693 | ||
|
|
ee8303e5f0 | ||
|
|
0e52d8ca2b | ||
|
|
1ba750d89c | ||
|
|
b3206b1682 | ||
|
|
a8ca92e34a | ||
|
|
82fa9b1d81 | ||
|
|
3aec87b02d | ||
|
|
45761f0250 | ||
|
|
cf3230c1ff | ||
|
|
fe2d244460 | ||
|
|
f6c1423361 | ||
|
|
4e7ff3862f | ||
|
|
1bbb0aee4b | ||
|
|
c00d39f929 | ||
|
|
bb5916ae02 | ||
|
|
f428c7e251 | ||
|
|
56ce99a5dd | ||
|
|
473076b603 | ||
|
|
37a135d49e | ||
|
|
74fc43020a | ||
|
|
b6407f99c4 | ||
|
|
94d535f72b | ||
|
|
110cec7bf6 | ||
|
|
d1722bc235 | ||
|
|
5a9498fe9b | ||
|
|
953188e76b | ||
|
|
88f662e6f6 | ||
|
|
6ae06d5609 | ||
|
|
1a0abbf76e | ||
|
|
efcf1fcaa0 | ||
|
|
6ab2f83e13 | ||
|
|
bc32b07bf0 | ||
|
|
5ac6632276 | ||
|
|
45ab08b459 | ||
|
|
3961f9f3e0 | ||
|
|
06f97b5139 | ||
|
|
c746fa8c79 | ||
|
|
546ea6b5ad | ||
|
|
98138e1e3b | ||
|
|
757025f2cb | ||
|
|
aae10d44e8 | ||
|
|
d4006f0693 | ||
|
|
e5173d04ab | ||
|
|
4e0fd93a28 | ||
|
|
2502ff7e32 | ||
|
|
d32cdb881c | ||
|
|
49ed15f82a | ||
|
|
9161f2da3d | ||
|
|
9a04a1e34f | ||
|
|
a795000363 | ||
|
|
1c89841d6f | ||
|
|
f47a23b0b5 | ||
|
|
21bfec3402 | ||
|
|
1239957446 | ||
|
|
9043081b8d | ||
|
|
a3ed8f6774 | ||
|
|
f54e0567d6 | ||
|
|
e578721cce | ||
|
|
93e0d5ce3b | ||
|
|
bd98746557 | ||
|
|
a20368c491 | ||
|
|
5e73f02b43 | ||
|
|
3b4966b7b8 | ||
|
|
d60120ddf1 | ||
|
|
16cbf85bf4 | ||
|
|
b6a9366684 | ||
|
|
eb0d6ee08e | ||
|
|
b20be2a747 | ||
|
|
7eeff9d470 | ||
|
|
afd113b1f1 | ||
|
|
3ef8e2db83 | ||
|
|
7a54e97823 | ||
|
|
fd6abfa8ce | ||
|
|
356181881b | ||
|
|
81641ed7a7 | ||
|
|
74dd5e8afc | ||
|
|
d9bae4a853 | ||
|
|
a0fd890def | ||
|
|
047adde310 | ||
|
|
d0c1b4508e | ||
|
|
87a4874df3 | ||
|
|
1a7a7ab6ba | ||
|
|
ca603336b2 | ||
|
|
cebdcfa7ed | ||
|
|
921061eeb6 | ||
|
|
31d2e522eb | ||
|
|
b3659d6a95 | ||
|
|
423ca95298 | ||
|
|
33dee8daf7 | ||
|
|
11f6525c0e | ||
|
|
10d54b0c7b | ||
|
|
373953b8ae | ||
|
|
6594d2d47b | ||
|
|
7671361485 | ||
|
|
016dcf22e0 | ||
|
|
ce37b5a8c3 | ||
|
|
6b533c44be | ||
|
|
b23547f4bd | ||
|
|
ce8539b414 | ||
|
|
a7a8ac0882 | ||
|
|
8168a09d6f | ||
|
|
1011088248 | ||
|
|
0f11b73d93 | ||
|
|
f459b07fa2 | ||
|
|
0c811f1420 | ||
|
|
8dc022c808 | ||
|
|
7f77619515 | ||
|
|
0db7868a6a | ||
|
|
867ea9cf2b | ||
|
|
dc319f664f | ||
|
|
ac9adcb7b2 | ||
|
|
049d6dd83f | ||
|
|
75a7e2339c | ||
|
|
6d435398e3 | ||
|
|
6281122394 | ||
|
|
b8e45d059c | ||
|
|
f172831733 | ||
|
|
88967a1dbe | ||
|
|
b976ac8084 | ||
|
|
e5e3dceee8 | ||
|
|
e90d06edfa | ||
|
|
d565f71939 | ||
|
|
1362584880 | ||
|
|
3b8f7536f3 | ||
|
|
b7b946f002 | ||
|
|
3fba384ef5 | ||
|
|
af6efbed7a | ||
|
|
83e1cd9274 | ||
|
|
bc9d470d08 | ||
|
|
e0dd94ae41 | ||
|
|
33fb20e5cb | ||
|
|
7ae8cfc0f5 | ||
|
|
76a83fd60b | ||
|
|
0f82851766 | ||
|
|
98ccf17196 | ||
|
|
a3e825c216 | ||
|
|
776d30613f | ||
|
|
2a08e0b704 | ||
|
|
5760c41cd0 | ||
|
|
78fdaf140d | ||
|
|
b8904a0aec | ||
|
|
061ceaa9fe | ||
|
|
d9b5744148 | ||
|
|
45630669c7 | ||
|
|
e8cde2c3cc | ||
|
|
bf6d4e1fed | ||
|
|
e8dc9809e2 | ||
|
|
3a55f5f798 | ||
|
|
dd1842647a | ||
|
|
5b75d32a8a | ||
|
|
bd4977e94e | ||
|
|
3e131603dd | ||
|
|
1e11f727fd | ||
|
|
f63d54a9de | ||
|
|
9a199eb9a1 | ||
|
|
dd6bee68cb | ||
|
|
28f0027de6 | ||
|
|
c6b48dd3ef | ||
|
|
ff3cabaf17 | ||
|
|
392867781f | ||
|
|
8ce4fa85f7 | ||
|
|
4e9f0c97a1 | ||
|
|
fe0d78b2d6 | ||
|
|
693e7b204b | ||
|
|
b6480bf8a6 | ||
|
|
205092180b | ||
|
|
50ff9b0c5c | ||
|
|
296cd215c1 | ||
|
|
fd510834ed | ||
|
|
4d8d128539 | ||
|
|
2a955d1391 | ||
|
|
1e2f91fe21 | ||
|
|
9d46b358d4 | ||
|
|
0507300a29 | ||
|
|
67c0d84d97 | ||
|
|
ec5d8ca179 | ||
|
|
6c4def18a6 | ||
|
|
a61bb4f8bc | ||
|
|
eeb636e81c | ||
|
|
32a1b7b8a3 | ||
|
|
205b4a5d54 | ||
|
|
6138fefa9e | ||
|
|
a4892e5992 | ||
|
|
855588ca8b | ||
|
|
68b33cbdbd | ||
|
|
f34a64a82a | ||
|
|
e5a6fd8f6c | ||
|
|
e67411aea4 | ||
|
|
1a72640a9b | ||
|
|
a099ed5f29 | ||
|
|
1abab690af | ||
|
|
71a0951c77 | ||
|
|
5cda4a5ebc | ||
|
|
3afecc8ee7 | ||
|
|
f817d41d1c | ||
|
|
6128338adb | ||
|
|
c79651ee90 | ||
|
|
0df288ba2c | ||
|
|
f888a9e6e0 | ||
|
|
f6a620e0ac | ||
|
|
e0481d29ad | ||
|
|
2dcccc772c | ||
|
|
1c0a0cf803 | ||
|
|
8ff37afe28 | ||
|
|
b575094f4b | ||
|
|
c096fa156b | ||
|
|
c81a24224e | ||
|
|
138dd98c0c | ||
|
|
b6cb52f702 | ||
|
|
b41c8130bf | ||
|
|
1e4d475327 | ||
|
|
f2ce1ae662 | ||
|
|
da1d00d9bf | ||
|
|
28a6c46605 | ||
|
|
d84b47f226 | ||
|
|
8ee5d422cb | ||
|
|
dcd11aa782 | ||
|
|
6908298fcc | ||
|
|
7163ea6c4b | ||
|
|
0b072da346 | ||
|
|
86346b284e | ||
|
|
11ade8aeaf | ||
|
|
41aec24f9b | ||
|
|
fd47fe3fc1 | ||
|
|
1731db833d | ||
|
|
edd8f347bc | ||
|
|
ed4d1e8bcd | ||
|
|
8c492d2a83 | ||
|
|
6ce877bd94 | ||
|
|
6806702e29 | ||
|
|
1c8622432b | ||
|
|
e583725cd2 | ||
|
|
54963842ed | ||
|
|
497e8570db | ||
|
|
ae4105e961 | ||
|
|
aa1de57d96 | ||
|
|
736fbff41a | ||
|
|
b1298c4d3e | ||
|
|
d7bbb0978f | ||
|
|
4aebdfc81a | ||
|
|
47f9ae2e11 | ||
|
|
8335cd7423 | ||
|
|
5812100fc6 | ||
|
|
9d21c3efbb | ||
|
|
af28418e61 | ||
|
|
462a859afe | ||
|
|
6378547a0e | ||
|
|
5f0015f522 | ||
|
|
4647d44972 | ||
|
|
7849254785 | ||
|
|
67fe1871da | ||
|
|
5e6366ba44 | ||
|
|
191c36c6fb | ||
|
|
590ff6ffa7 | ||
|
|
25ac0f700b | ||
|
|
b6906467be | ||
|
|
5aa835deb6 | ||
|
|
cbdc751be1 | ||
|
|
0d1590f251 | ||
|
|
cc1323f5cc | ||
|
|
f68b4934c6 | ||
|
|
6f6921079e | ||
|
|
1d0bf58109 | ||
|
|
6fa04622ce | ||
|
|
c69637fe98 | ||
|
|
121ac152fa | ||
|
|
50352e0f82 | ||
|
|
9db80fde37 | ||
|
|
07401d1810 | ||
|
|
27b1196111 | ||
|
|
657681e5e1 | ||
|
|
88a690a7d1 | ||
|
|
b94c0df49e | ||
|
|
714665a202 | ||
|
|
13e2537dfb | ||
|
|
1034b6d517 | ||
|
|
f6378e8c3b | ||
|
|
fe8831f7ae | ||
|
|
520076b31d | ||
|
|
e2b17bc310 | ||
|
|
8774df46f9 | ||
|
|
cdc2b449a9 | ||
|
|
a4d0813354 | ||
|
|
6e2161277c | ||
|
|
7d096ba90e | ||
|
|
9a1123239f | ||
|
|
8b617abead | ||
|
|
8ead48a6d8 | ||
|
|
a360e30073 | ||
|
|
4b92ad6a22 | ||
|
|
885e99ddad | ||
|
|
8ed62d7692 | ||
|
|
ed26ae088a | ||
|
|
d40bdb9699 | ||
|
|
c65adc5e25 | ||
|
|
34a3a99d62 | ||
|
|
eb1d4fe1f6 | ||
|
|
ce24174971 | ||
|
|
6a8aff9e56 | ||
|
|
2b3ec1240a | ||
|
|
6906d6ba7a | ||
|
|
5c505807b4 | ||
|
|
5a0e4895cd | ||
|
|
6c0db247b7 | ||
|
|
5f4071652f | ||
|
|
78c164463f | ||
|
|
3b9caadaac | ||
|
|
61fc9bc222 | ||
|
|
5a3e6aa041 | ||
|
|
0370ec67df | ||
|
|
2196379798 | ||
|
|
8dac464b61 | ||
|
|
6fd1ad7434 | ||
|
|
79506f1ce2 | ||
|
|
b69eb3437b | ||
|
|
36e6da52a5 | ||
|
|
a47b612a2c | ||
|
|
2fdbb1909d | ||
|
|
3792b05741 | ||
|
|
db68fe8f46 | ||
|
|
dbf6dd5a6c | ||
|
|
c0813156a1 | ||
|
|
b8f550f069 | ||
|
|
6faaae8728 | ||
|
|
9495432714 | ||
|
|
b38fc8d7e5 | ||
|
|
298f2c1feb | ||
|
|
98ceb082fc | ||
|
|
49e60737a8 | ||
|
|
6e2f1070b9 | ||
|
|
d5f4c4210d | ||
|
|
8a7393a961 | ||
|
|
cb118149f3 | ||
|
|
7890219e29 | ||
|
|
5847599112 | ||
|
|
2962b9e256 | ||
|
|
69f19886fb | ||
|
|
525b8b5007 | ||
|
|
31878d7fe0 | ||
|
|
6296cb0910 | ||
|
|
ed1a917dc1 | ||
|
|
d060e77cfa | ||
|
|
6057c5637c | ||
|
|
a6a8493c35 | ||
|
|
be27b30b01 | ||
|
|
8615d4b3af | ||
|
|
944c455c3d | ||
|
|
094e73b7fb | ||
|
|
323d7c96f7 | ||
|
|
26c308147c | ||
|
|
7bd69809e9 | ||
|
|
02aea468ca | ||
|
|
1824ce1e80 | ||
|
|
d524fe3c6c | ||
|
|
9b427efb88 | ||
|
|
385e9afba6 | ||
|
|
ee2e1687df | ||
|
|
f412a453f2 | ||
|
|
5acc9388cc | ||
|
|
69805faa17 | ||
|
|
6b31af0854 | ||
|
|
9bd6bcaf65 | ||
|
|
d1f2b3f8af | ||
|
|
85431de42b | ||
|
|
9df5b553b2 | ||
|
|
cee05b13e8 | ||
|
|
ca060dbf7a | ||
|
|
483d1d67c6 | ||
|
|
fccf7e2f12 | ||
|
|
42f8247599 | ||
|
|
5d40c93db7 | ||
|
|
3d78301805 | ||
|
|
18e1eecefc | ||
|
|
a5216bf01c | ||
|
|
a3eb4a4279 | ||
|
|
7ab0040810 | ||
|
|
3d6d8694ba | ||
|
|
5a93b26cc3 | ||
|
|
718322ec65 | ||
|
|
2fd4dc5201 | ||
|
|
b9544e1022 | ||
|
|
044eb8976a | ||
|
|
1777b4f91e | ||
|
|
233793cecb | ||
|
|
eb47794e98 | ||
|
|
f47d1c2f7b | ||
|
|
6327b5864d | ||
|
|
2bde086e28 | ||
|
|
c129c92e39 | ||
|
|
c3dc92d920 | ||
|
|
cc605251a8 | ||
|
|
0984c37cad | ||
|
|
0ccaf2bc45 | ||
|
|
5323f659c8 | ||
|
|
c61b689d1b | ||
|
|
8297259f7e | ||
|
|
c29b2975c5 | ||
|
|
9d350059d9 | ||
|
|
4735fdbd2b | ||
|
|
53d60a13b2 | ||
|
|
7583205011 | ||
|
|
75435e1c69 | ||
|
|
4d689529b9 | ||
|
|
eba1962cd5 | ||
|
|
5176d57d28 | ||
|
|
e111d5e6ef | ||
|
|
f01e0cd733 | ||
|
|
23ff52b93d | ||
|
|
f8995e8a87 | ||
|
|
a3a94a9d0f | ||
|
|
7ff63cfb5f | ||
|
|
2ec5f6fb60 | ||
|
|
6fa0820734 | ||
|
|
6d28081afa | ||
|
|
4e1f812160 | ||
|
|
0c21ccb04b | ||
|
|
9c2c8aed6c | ||
|
|
2405744566 | ||
|
|
b1943aaad9 | ||
|
|
ef4a25d82b | ||
|
|
731deda1e1 | ||
|
|
d9d60197f2 | ||
|
|
84906e1ff8 | ||
|
|
028fdae8b1 | ||
|
|
d135bcb2fd | ||
|
|
40b74a8e66 | ||
|
|
a0f5d089d1 | ||
|
|
0566c07e39 | ||
|
|
38b4ab41a5 | ||
|
|
72d28867aa | ||
|
|
aac9cb8b23 | ||
|
|
8f2d6b2160 | ||
|
|
28d2fd13d5 | ||
|
|
94c16b6380 | ||
|
|
de963fe13b | ||
|
|
036e514eb5 | ||
|
|
e1f4b6f8f2 | ||
|
|
285b535a54 | ||
|
|
0441c17e1d | ||
|
|
ab059fcb2b | ||
|
|
18f63443e3 | ||
|
|
3750c8ef8d | ||
|
|
9e15f1add9 | ||
|
|
1ea0e29d93 | ||
|
|
9807f9af1d | ||
|
|
a6100a6ae2 | ||
|
|
8589a8c718 | ||
|
|
1455bb8555 | ||
|
|
285651fba8 | ||
|
|
3c5a98ff7c | ||
|
|
8e7e25829b | ||
|
|
3b8c4db8fb | ||
|
|
e559ae3490 | ||
|
|
10c082b8e3 | ||
|
|
fd72f69303 | ||
|
|
d7cb1b5c0a | ||
|
|
a54bc69d46 | ||
|
|
b52f6ed63b | ||
|
|
c0e0629659 | ||
|
|
c0a36d36cc | ||
|
|
6072de82ff | ||
|
|
4d5213608b | ||
|
|
a220e63184 | ||
|
|
c953e82234 | ||
|
|
e2df32724a | ||
|
|
e207aa1cb5 | ||
|
|
79a9f0ee46 | ||
|
|
fdaefccdb0 | ||
|
|
d2e672ae92 | ||
|
|
b0bbe0eff3 | ||
|
|
aaaca538d1 | ||
|
|
dc72b2ea11 | ||
|
|
ad3e18cb1a | ||
|
|
392c9cc0d6 | ||
|
|
e397fe09c7 | ||
|
|
efb5e8a504 | ||
|
|
4fed0de502 | ||
|
|
9548cc1ed1 | ||
|
|
3daf8c00a4 | ||
|
|
274505590c | ||
|
|
1379094f4d | ||
|
|
801fc4e00c | ||
|
|
ab4feb04ba | ||
|
|
6bdaee66cf | ||
|
|
22ba80c95d | ||
|
|
b28668d947 | ||
|
|
759ec6707a | ||
|
|
de43f3f0e2 | ||
|
|
dd127bc68d | ||
|
|
a11e400fca | ||
|
|
a5e0fbae9e | ||
|
|
be3158d529 | ||
|
|
0e5ef7844c | ||
|
|
66d2033cda | ||
|
|
56f10bbf50 | ||
|
|
6f71198f04 | ||
|
|
b0e586d02b | ||
|
|
f47af2d546 | ||
|
|
dd19c947a9 | ||
|
|
ebca34c9e5 | ||
|
|
010c7b68d4 | ||
|
|
2a17c32779 | ||
|
|
a013de8adf | ||
|
|
d359823f8e | ||
|
|
952de71601 | ||
|
|
497dfa3fb5 | ||
|
|
21c9725f62 | ||
|
|
1d1f211d37 | ||
|
|
e4905b317a | ||
|
|
3e5b135ceb | ||
|
|
65652d0d06 | ||
|
|
c4d34ddfea | ||
|
|
dd9d30de37 | ||
|
|
6f0bded0a2 | ||
|
|
35ca8a8fb0 | ||
|
|
1a2f7b8478 | ||
|
|
675e51f906 | ||
|
|
89663bc72a | ||
|
|
e3011c3aa6 | ||
|
|
a0b30db810 | ||
|
|
1dcc6ac613 | ||
|
|
d67ddc37b4 | ||
|
|
9a315ed994 | ||
|
|
b102e234e3 | ||
|
|
3f794a959b | ||
|
|
7522b76089 | ||
|
|
540048eadf | ||
|
|
115a13a6fa | ||
|
|
18c4abca2e | ||
|
|
5e6f5d5df9 | ||
|
|
76d52bd2fd | ||
|
|
7a7a339938 | ||
|
|
58f8a93ae1 | ||
|
|
61c5ddea5e | ||
|
|
32d6c07450 | ||
|
|
189f51df25 | ||
|
|
181786eeea | ||
|
|
efddd3ddb5 | ||
|
|
2c84f3979d | ||
|
|
c61be05944 | ||
|
|
765cd983fc | ||
|
|
4a963321b1 | ||
|
|
081bf2cc25 | ||
|
|
5af42d3784 | ||
|
|
e306408b56 | ||
|
|
8141ef1f91 | ||
|
|
cf65f0ad0d | ||
|
|
19b2794e2d | ||
|
|
fca165c672 | ||
|
|
82c261767f | ||
|
|
6cc39171eb | ||
|
|
a507e9aa6d | ||
|
|
4c94730bff | ||
|
|
299a17a874 | ||
|
|
5763baf8cd | ||
|
|
55f9a8bd63 | ||
|
|
d067250a04 | ||
|
|
8287733263 | ||
|
|
fe261388a3 | ||
|
|
cb2e6f97d0 | ||
|
|
af6381314c | ||
|
|
c0b410a1b2 | ||
|
|
5261ef960e | ||
|
|
57f3cd652a | ||
|
|
48d9aec4fb | ||
|
|
cf2767c568 | ||
|
|
2fb7217f03 | ||
|
|
9f69acc990 | ||
|
|
bbaabfeea4 | ||
|
|
6068d995af | ||
|
|
2a400a103a | ||
|
|
a2ce1dd924 | ||
|
|
01310e1650 | ||
|
|
20ffbe348a | ||
|
|
720aa6e6b0 | ||
|
|
c4c6844fbe | ||
|
|
c064006c02 | ||
|
|
97994b81c6 | ||
|
|
a3aac7fe86 | ||
|
|
88203a8d60 | ||
|
|
44d9fbf264 | ||
|
|
4545c4b56f | ||
|
|
5fb22d5b65 | ||
|
|
38d66fb529 | ||
|
|
08ce7d5322 | ||
|
|
a9bbaed22c | ||
|
|
d7e3d524e5 | ||
|
|
94bebdc491 | ||
|
|
9f900f0cd2 | ||
|
|
79f1ca494d | ||
|
|
65935eb8a1 | ||
|
|
b3be064432 | ||
|
|
e501026d28 | ||
|
|
65f4f05c04 | ||
|
|
2413e47d41 | ||
|
|
822b6c9bb1 | ||
|
|
be4135f6ba | ||
|
|
f5521eb91a | ||
|
|
2f5724578f | ||
|
|
c11f257943 | ||
|
|
0e115b9296 | ||
|
|
44d569ca66 | ||
|
|
24b1bd3f39 | ||
|
|
9e1edc9cee | ||
|
|
61b8299e3e | ||
|
|
9ee78221a7 | ||
|
|
5bd95f68c2 | ||
|
|
fec1944fa9 | ||
|
|
4b0ed65f45 | ||
|
|
2dba0927ef | ||
|
|
056c657721 | ||
|
|
0636622158 | ||
|
|
bf6545af7a | ||
|
|
56d43fb88a | ||
|
|
42fb945d02 | ||
|
|
be35e2beac | ||
|
|
05aa532d58 | ||
|
|
980786c821 | ||
|
|
8574ba596b | ||
|
|
f28a1df624 | ||
|
|
e69eafdd50 | ||
|
|
152093e7d8 | ||
|
|
23b9ff1ce6 | ||
|
|
7b6addbe28 | ||
|
|
1d4be5a290 | ||
|
|
bef1c78879 | ||
|
|
1f63662960 | ||
|
|
a36588f75c | ||
|
|
401a2ed076 | ||
|
|
5c8041a8d4 | ||
|
|
9c9ce0280f | ||
|
|
60f8366f00 | ||
|
|
3325a1bfe2 | ||
|
|
746a6d9ab5 | ||
|
|
d5503a2298 | ||
|
|
bccb0cc5ff | ||
|
|
77b1dff68b | ||
|
|
9a717f7ed2 | ||
|
|
0fa44f82dd | ||
|
|
6d41090e27 | ||
|
|
ba7a4378ad | ||
|
|
7e23aa4618 | ||
|
|
e53119fc20 | ||
|
|
f67d0011d2 | ||
|
|
ab73745ec0 | ||
|
|
e8a472a1fe | ||
|
|
b39acf42e6 | ||
|
|
72b5dcb930 | ||
|
|
e352dc7f61 | ||
|
|
9702e9e380 | ||
|
|
09fb0f8dfc | ||
|
|
5006c2360a | ||
|
|
48ac7aad60 | ||
|
|
74d7b7ab9d | ||
|
|
69b396b9d4 | ||
|
|
4401f083f2 | ||
|
|
32babd8026 | ||
|
|
68dc20cd2e | ||
|
|
e8a5d9b784 | ||
|
|
de9248b784 | ||
|
|
d64ae51c94 | ||
|
|
21f9f87cb2 | ||
|
|
84dd82aa96 | ||
|
|
cc00f2cb2d | ||
|
|
d9ad8ee608 | ||
|
|
743c7212fe | ||
|
|
c7c8ea7103 | ||
|
|
af23591541 | ||
|
|
e629aac0ad | ||
|
|
7de8ac53d1 | ||
|
|
49a8be3ce6 | ||
|
|
cd2495e4e0 | ||
|
|
2870972b49 | ||
|
|
9415f46ce5 | ||
|
|
863ebf8360 | ||
|
|
772a5adbc9 | ||
|
|
d6007a54e7 | ||
|
|
e1234df141 | ||
|
|
b8efa9aa25 | ||
|
|
a739c1f773 | ||
|
|
911cc3e217 | ||
|
|
c95667eafb | ||
|
|
2c1eee1194 | ||
|
|
c045c35842 | ||
|
|
e3332b8f19 | ||
|
|
fabd76edbe | ||
|
|
21d24ad542 | ||
|
|
ba9a57d4ae | ||
|
|
7fb5aae8b5 | ||
|
|
03ff4c3e3d | ||
|
|
3efc4b554b | ||
|
|
94cad8b080 | ||
|
|
693a59c446 | ||
|
|
d1c9a40705 | ||
|
|
b57d8d3529 | ||
|
|
8f38504009 | ||
|
|
5988777baf | ||
|
|
fd853a7b0c | ||
|
|
f892af6dcd | ||
|
|
d9278fcc16 | ||
|
|
3ab34de1e1 | ||
|
|
048beb60c2 | ||
|
|
cea3d13805 | ||
|
|
5df735db48 | ||
|
|
d09d70abfe | ||
|
|
c8fb986888 | ||
|
|
475566fa20 | ||
|
|
32a5788504 | ||
|
|
e909141759 | ||
|
|
826a4bf381 | ||
|
|
cf47098631 | ||
|
|
f78ee0670e | ||
|
|
cf6b1731b0 | ||
|
|
dedf03ae50 | ||
|
|
532d7c8a72 | ||
|
|
0b623a522b | ||
|
|
d6a589b766 | ||
|
|
c5a0643448 | ||
|
|
a0c9f9a49c | ||
|
|
03a827e759 | ||
|
|
9a2b48541b | ||
|
|
1b3bdda061 | ||
|
|
f9654ce31c | ||
|
|
9088ab03a3 | ||
|
|
11edef1bbd | ||
|
|
251cfc2340 | ||
|
|
20e4686851 | ||
|
|
1a82fdb8b3 | ||
|
|
6a9b3b2fd3 | ||
|
|
4fe2febda3 | ||
|
|
69e30ba888 | ||
|
|
d8a580dfae | ||
|
|
06be432b5a | ||
|
|
921561eade | ||
|
|
235bfe646d | ||
|
|
a45040a956 | ||
|
|
4be968c421 | ||
|
|
ede7a6bdaa | ||
|
|
819ab74178 | ||
|
|
da1926e1ab | ||
|
|
9ae9bb8092 | ||
|
|
3d6361ba3d | ||
|
|
13de557d24 | ||
|
|
14c665757e | ||
|
|
082894d08c | ||
|
|
1eb3553504 | ||
|
|
bb3ff8edc7 | ||
|
|
b855f71ebf | ||
|
|
b2f44f9fab | ||
|
|
2867cb07c5 | ||
|
|
45f4c9e0e9 | ||
|
|
89866378ef | ||
|
|
034e460701 | ||
|
|
1b544463c2 | ||
|
|
48d355ee72 | ||
|
|
ae6fc7bb18 | ||
|
|
1d3dd8aa77 | ||
|
|
c28cca1a13 | ||
|
|
ac1ddba094 | ||
|
|
c014818114 | ||
|
|
753c59b534 | ||
|
|
c7f974ed77 | ||
|
|
8e4585495f | ||
|
|
d979acbba7 | ||
|
|
2fe58960f3 | ||
|
|
79b0bb9de9 | ||
|
|
0325f3f041 | ||
|
|
1e8a704261 | ||
|
|
9d431dbc18 | ||
|
|
004a13576a | ||
|
|
d438b77a1b | ||
|
|
49eff042fe | ||
|
|
0f982ef4ba | ||
|
|
af93c6e6c0 | ||
|
|
2caa0fcb95 | ||
|
|
0152172dd1 | ||
|
|
932f5f02c4 | ||
|
|
fc2a5879bd | ||
|
|
a0b9ae538a | ||
|
|
15bdd2f31e | ||
|
|
2d1fd3a083 | ||
|
|
179de80c83 | ||
|
|
bda94bb865 | ||
|
|
a4284d56f8 | ||
|
|
362b6f4238 | ||
|
|
cb7d16fe1f | ||
|
|
ca9f66ce99 | ||
|
|
8b757f538e | ||
|
|
7831a65cbe | ||
|
|
af4262020b | ||
|
|
af92417c81 | ||
|
|
257744f98b | ||
|
|
107419cb8d | ||
|
|
51db32c29b | ||
|
|
2c06dbf2aa | ||
|
|
5749b5f711 | ||
|
|
8cdfb2edba | ||
|
|
724ad7dee6 | ||
|
|
3357c3d43b | ||
|
|
0b2ab4f9a4 | ||
|
|
fdee279150 | ||
|
|
fe189e383b | ||
|
|
a7e6d16930 | ||
|
|
66a208ebaf | ||
|
|
7e77175679 | ||
|
|
2c32d4614f | ||
|
|
18ecf52f62 | ||
|
|
0be59eef60 | ||
|
|
62826f7ab7 | ||
|
|
e2a9c6c552 | ||
|
|
60246f3a23 | ||
|
|
9c2afb2a7b | ||
|
|
6459faeeb9 | ||
|
|
4e25fa3054 | ||
|
|
423f0e8e96 | ||
|
|
b6b1ae0224 | ||
|
|
926bb7fd14 | ||
|
|
e3469b435f | ||
|
|
8e8e18fdf9 | ||
|
|
93ef92e15b | ||
|
|
abc7494586 | ||
|
|
ad73c41483 | ||
|
|
250ac0e2ea | ||
|
|
1395506b69 | ||
|
|
41174c74d7 | ||
|
|
e9b38a2380 | ||
|
|
bad5dda67e | ||
|
|
98692ba790 | ||
|
|
a11f411f6c | ||
|
|
7e608e48ec | ||
|
|
0023593128 | ||
|
|
8e091a37e2 | ||
|
|
c3d68a44ce | ||
|
|
4f56cc9ec9 | ||
|
|
db74706eca | ||
|
|
122cce042c | ||
|
|
cb86e8b801 | ||
|
|
e3dc089d51 | ||
|
|
27754833cf | ||
|
|
97b8456eac | ||
|
|
b837126cea | ||
|
|
a0c333f823 | ||
|
|
3159d6ff1b | ||
|
|
dae7f99fe8 | ||
|
|
635216194f | ||
|
|
807762cf1a | ||
|
|
3f6af0a964 | ||
|
|
57b204b6e2 | ||
|
|
65f767e35a | ||
|
|
b49a32c9c7 | ||
|
|
48264edf91 | ||
|
|
cdc196322c | ||
|
|
ee6138134d | ||
|
|
6aa679365a | ||
|
|
eef467558e | ||
|
|
cdf07fd7c2 | ||
|
|
eab86dffb8 | ||
|
|
d7e6654965 | ||
|
|
30679763ab | ||
|
|
ad5e7cb2f4 | ||
|
|
412d5205c8 | ||
|
|
c4a484bbce | ||
|
|
8fcb24a6ba | ||
|
|
1bf7a4a4fe | ||
|
|
2780beddbb | ||
|
|
7909e03cef | ||
|
|
ed46eb58fd | ||
|
|
b86a03642a | ||
|
|
7e60b750d1 | ||
|
|
b111c411bd | ||
|
|
104693916f | ||
|
|
f1ea2ee691 | ||
|
|
3be4e4015e | ||
|
|
55d160afd6 | ||
|
|
16611b9934 | ||
|
|
e8431122c9 | ||
|
|
6c792d0e61 | ||
|
|
33400f1c5a | ||
|
|
c8ac8c5738 | ||
|
|
5189086c1b | ||
|
|
7860c563c7 | ||
|
|
d0d0955c0e | ||
|
|
b3e703b656 | ||
|
|
005d3bbaa9 | ||
|
|
b4571539ac | ||
|
|
e13d27ad9c | ||
|
|
b2fe31dc02 | ||
|
|
2260696675 | ||
|
|
6645e98a1b | ||
|
|
c28407f77d | ||
|
|
abc895c6b2 | ||
|
|
d0da2a16c3 | ||
|
|
dc4a69593b | ||
|
|
09e900b1f7 | ||
|
|
8f18048254 | ||
|
|
c723c18086 | ||
|
|
5723117cb8 | ||
|
|
876f3d235e | ||
|
|
60b379fcad | ||
|
|
209184327b | ||
|
|
255e09480a | ||
|
|
0f2af25249 | ||
|
|
a76fadb1bc | ||
|
|
bfcd53f39f | ||
|
|
fe3c7b446f | ||
|
|
223f08c439 | ||
|
|
49dd21de57 | ||
|
|
16cb413ace | ||
|
|
c474775982 | ||
|
|
469931a61f | ||
|
|
31d3a012f9 | ||
|
|
890e353dc7 | ||
|
|
64e90640b9 | ||
|
|
ecec2d6efe | ||
|
|
51e6f4344a | ||
|
|
6c784184b1 | ||
|
|
42261a7f41 | ||
|
|
ff63de2aa5 | ||
|
|
a9f258a199 | ||
|
|
aeb1b1688d | ||
|
|
5774956175 | ||
|
|
145dd71f97 | ||
|
|
9fe4b066f9 | ||
|
|
b281b86c84 | ||
|
|
9395b8989d | ||
|
|
2cc83e1032 | ||
|
|
67c5a622ec | ||
|
|
e208ab6033 | ||
|
|
f251ae7437 | ||
|
|
84b62e474a | ||
|
|
8c1636f1a2 | ||
|
|
44e20cec3c | ||
|
|
7a0e205ff8 | ||
|
|
710d740f30 | ||
|
|
b0d68dadcb | ||
|
|
a80e15042a | ||
|
|
2da463b501 | ||
|
|
779463dada | ||
|
|
39f0b1b252 | ||
|
|
dcfe8237ef | ||
|
|
d3012de9d6 | ||
|
|
9b875d19d2 | ||
|
|
030ec9fa88 | ||
|
|
d9e339c3c0 | ||
|
|
c819d1f87c | ||
|
|
76a039c885 | ||
|
|
4b39acbba2 | ||
|
|
76af339b12 | ||
|
|
eea6662d7f | ||
|
|
e91ea0d34b | ||
|
|
e410b3e961 | ||
|
|
b1f14c0f71 | ||
|
|
833df7be3c | ||
|
|
c1261e7977 | ||
|
|
319a5e4dc1 | ||
|
|
bc6cf648f6 | ||
|
|
5cda71f433 | ||
|
|
550e7f765f | ||
|
|
1e5e61ab51 | ||
|
|
f547e5f314 | ||
|
|
79a760a042 | ||
|
|
f4eb4740d8 | ||
|
|
48940b746e | ||
|
|
8360e14b01 | ||
|
|
f6826d73fa | ||
|
|
8b95f13076 | ||
|
|
054e1f78e1 | ||
|
|
ab4d4c0a96 | ||
|
|
10072148d1 | ||
|
|
0a4a9fcdb1 | ||
|
|
a6f81e2359 | ||
|
|
72a39f67c0 | ||
|
|
93866e56d2 | ||
|
|
9ef0fe9d06 | ||
|
|
36a10ebfa9 | ||
|
|
ee8da42c41 | ||
|
|
9316bb4222 | ||
|
|
bcb8b9f211 | ||
|
|
bf61fbc057 | ||
|
|
d83693af93 | ||
|
|
bd5f0ad7c1 | ||
|
|
5687fa211e | ||
|
|
5095e2f27d | ||
|
|
d10affb413 | ||
|
|
740500716e | ||
|
|
d6640e0793 | ||
|
|
0b5cc1beda | ||
|
|
dacfdfa57f | ||
|
|
4400871959 | ||
|
|
f7ff8f29b8 | ||
|
|
15f06fe85e | ||
|
|
3e9304fb05 | ||
|
|
7437a7f849 | ||
|
|
28b2943dc6 | ||
|
|
e9ee729b5d | ||
|
|
dee6355b29 | ||
|
|
a409009d65 | ||
|
|
efb23968e8 | ||
|
|
b4ea9ae02c | ||
|
|
ce9dc37217 | ||
|
|
707bc1f6ed | ||
|
|
b46a7fc8ce | ||
|
|
36a96b23e6 | ||
|
|
b663e92be8 | ||
|
|
51a427496c | ||
|
|
13cb76321d | ||
|
|
5513cbf724 | ||
|
|
5daae7e3eb | ||
|
|
270c3f5a6a | ||
|
|
761345a226 | ||
|
|
047537101c | ||
|
|
6c6eb619ea | ||
|
|
51129bf14d | ||
|
|
ae88dbd717 | ||
|
|
20e2984c04 | ||
|
|
20cef6e54a | ||
|
|
a3deb954af | ||
|
|
da983b5006 | ||
|
|
c4df4da082 | ||
|
|
da36e20301 | ||
|
|
57591ff6ca | ||
|
|
2ff46fa831 | ||
|
|
92d5f8f7c9 | ||
|
|
1cb83e4bdb | ||
|
|
7f8a577bd2 | ||
|
|
4c2bca1404 | ||
|
|
72bb172b6c | ||
|
|
1caaa79878 | ||
|
|
6544d41188 | ||
|
|
84bea54916 | ||
|
|
79d247ca04 | ||
|
|
c7409bef84 | ||
|
|
b531ee1bf6 | ||
|
|
05f14d0010 | ||
|
|
225dc61521 | ||
|
|
7a5786f2a2 | ||
|
|
974fabb2af | ||
|
|
e46cf6c543 | ||
|
|
c8dde3b3ca | ||
|
|
0179ad567e | ||
|
|
28a50aed6b | ||
|
|
9e1fc9a3b8 | ||
|
|
cc5c16623a | ||
|
|
4684548ad8 | ||
|
|
e45f271671 | ||
|
|
316e6f8c74 | ||
|
|
dd529f8035 | ||
|
|
bf3621eaef | ||
|
|
1124d14055 | ||
|
|
928d878240 | ||
|
|
c8101dfa4c | ||
|
|
59fc773174 | ||
|
|
e1e1d0c964 | ||
|
|
055b63382b | ||
|
|
090890a94d | ||
|
|
231615b134 | ||
|
|
e0d31659d9 | ||
|
|
d75e5fff92 | ||
|
|
17c79eebe4 | ||
|
|
375b5197da | ||
|
|
512c0a791e | ||
|
|
d154a28ad1 | ||
|
|
153150cd3b | ||
|
|
7140d41296 | ||
|
|
aed2b482ea | ||
|
|
6518aaccc2 | ||
|
|
462e86b9a0 | ||
|
|
f99bf74499 | ||
|
|
4e3af83bbf | ||
|
|
8fa9669aa8 | ||
|
|
2b8b1c1f38 | ||
|
|
6e8f33dc2c | ||
|
|
0cf010d1c1 | ||
|
|
bc767ed526 | ||
|
|
9b278d29d5 | ||
|
|
3e76a94730 | ||
|
|
78facb2fe6 | ||
|
|
82c4a35648 | ||
|
|
726c8c54ab | ||
|
|
49fdaf4a18 | ||
|
|
0346b22bdd | ||
|
|
03419fc27a | ||
|
|
8d9838614e | ||
|
|
274075d774 | ||
|
|
b1a39fa2e7 | ||
|
|
2c4cefff97 | ||
|
|
df25adad70 | ||
|
|
f01c6e12d2 | ||
|
|
12804b0dea | ||
|
|
3d5f239e4e | ||
|
|
e0e42895dc | ||
|
|
75c07d9d46 | ||
|
|
2a7e1839da | ||
|
|
d43bdb7aa9 | ||
|
|
e6abaf7aa4 | ||
|
|
97567e2e1f | ||
|
|
cc13bf8265 | ||
|
|
449b08c9c2 | ||
|
|
e7564b2e71 | ||
|
|
2b8c975e6c | ||
|
|
614199a981 | ||
|
|
334aaa2d87 | ||
|
|
f4b7e5f474 | ||
|
|
e49d7eda04 | ||
|
|
d62cfbf1d3 | ||
|
|
7bbf1d28ea | ||
|
|
6891e586bc | ||
|
|
74900b1341 | ||
|
|
8b9dccd887 | ||
|
|
5e6c4872c2 | ||
|
|
57067b43b3 | ||
|
|
67ef5099dd | ||
|
|
fb292b5423 | ||
|
|
40d0935792 | ||
|
|
eb2d3d5d40 | ||
|
|
900d95fa87 | ||
|
|
76f75faf6c | ||
|
|
8ebed0b92e | ||
|
|
1da1293789 | ||
|
|
e2293ffc44 | ||
|
|
dd149474d9 | ||
|
|
27aaf2de1a | ||
|
|
c0c167fea8 | ||
|
|
46792e5757 | ||
|
|
6df0e3b946 | ||
|
|
6ebd13cb28 | ||
|
|
b9c0669a15 | ||
|
|
c83537aac6 | ||
|
|
e3c1e6a5da | ||
|
|
c6d6a09abf | ||
|
|
b6542b0245 | ||
|
|
45ce9875b7 | ||
|
|
9424cfb865 | ||
|
|
2773b3e489 | ||
|
|
855ad54fe1 | ||
|
|
955558b0d0 | ||
|
|
92ea3ee2a8 | ||
|
|
070e8d191e | ||
|
|
646fcea816 | ||
|
|
b53f61483d | ||
|
|
27b7c4e8fb | ||
|
|
1c19611add | ||
|
|
08beb6fa95 | ||
|
|
3cb91c0f68 | ||
|
|
3d2da085e7 | ||
|
|
55dbc8ad3b | ||
|
|
4dc61165b2 | ||
|
|
1cd17ea31b | ||
|
|
d6dfd9b6ac | ||
|
|
55f8f910fa | ||
|
|
20002785e9 | ||
|
|
39a2da8ca8 | ||
|
|
f7eb92fa9b | ||
|
|
14507d0fc0 | ||
|
|
8b8665df6b | ||
|
|
00dd7e9621 | ||
|
|
5f729464a2 | ||
|
|
151a2a4311 | ||
|
|
c732520182 | ||
|
|
cf56292484 | ||
|
|
4adf4f886f | ||
|
|
fae43e90da | ||
|
|
ef9d017572 | ||
|
|
2bf5824aa3 | ||
|
|
64ca6a6b35 | ||
|
|
87451a19bb | ||
|
|
c6657e7a9b | ||
|
|
59b084c6a6 | ||
|
|
1e27b2a619 | ||
|
|
0b61f4a2a0 | ||
|
|
1bc2dcd661 | ||
|
|
ae94c901b3 | ||
|
|
1dc475632a | ||
|
|
68c152d4c6 | ||
|
|
c287380067 | ||
|
|
38178022f7 | ||
|
|
4b464e89af | ||
|
|
dba26f52f4 | ||
|
|
be21e856cf | ||
|
|
ebdb3172e5 | ||
|
|
f340a046c2 | ||
|
|
765c39b5d2 | ||
|
|
f257dcf388 | ||
|
|
43e52fffe7 | ||
|
|
038dc7f923 | ||
|
|
069d2f7c28 | ||
|
|
187eb19452 | ||
|
|
50f19663d4 | ||
|
|
749f618488 | ||
|
|
4b5e209ecc | ||
|
|
2ee99a37fb | ||
|
|
b6993ca3ba | ||
|
|
72d38f1e70 | ||
|
|
f3b4ca7a3e | ||
|
|
8b827c2f37 | ||
|
|
10087761c8 | ||
|
|
570ebe7923 | ||
|
|
f4a4350f68 | ||
|
|
0110efc340 | ||
|
|
b105eaf9a6 | ||
|
|
2913da11a0 | ||
|
|
e2ec21df11 | ||
|
|
0c7b9f0935 | ||
|
|
c0626cf8ac | ||
|
|
7fea77b64f | ||
|
|
b01703b836 | ||
|
|
7b34ea010c | ||
|
|
3aca098bee | ||
|
|
6ed2d467b7 | ||
|
|
2bf6bf7ed8 | ||
|
|
e6e4c775a8 | ||
|
|
0d79f183c5 | ||
|
|
8e1bf90ebd | ||
|
|
c840251886 | ||
|
|
7cb0e944cb | ||
|
|
6dbbcd393c | ||
|
|
75725beaf3 | ||
|
|
b54bbb0aa1 | ||
|
|
ead6aaa866 | ||
|
|
dfb72b60ab | ||
|
|
5cd8b38bdd | ||
|
|
ca5bde9730 | ||
|
|
42ac45fe15 | ||
|
|
c93a3ec5e1 | ||
|
|
bc1b3fbf22 | ||
|
|
fe47ab6063 | ||
|
|
b309e2670d | ||
|
|
796d078a15 | ||
|
|
582aed8744 | ||
|
|
ddf3305bc1 | ||
|
|
75a63d15ff | ||
|
|
9c25b304bf | ||
|
|
6c2c7dcd48 | ||
|
|
cc790dcbc2 | ||
|
|
eeb2be8664 | ||
|
|
bfe7aa094f | ||
|
|
3a13f3e9a2 | ||
|
|
3c582b03d7 | ||
|
|
0240feb7f1 | ||
|
|
4acf6c99a7 | ||
|
|
e435dbd2cb | ||
|
|
eab0d6dc6e | ||
|
|
8f3ac5d186 | ||
|
|
c62e5f2985 | ||
|
|
7719f7a86e | ||
|
|
56074417c4 | ||
|
|
62740262ec | ||
|
|
5cf088fd92 | ||
|
|
ebe029adad | ||
|
|
48fa14ed38 | ||
|
|
f2907141c3 | ||
|
|
ea5a805405 | ||
|
|
75750872bd | ||
|
|
3981445734 | ||
|
|
783a610a75 | ||
|
|
bb7a216bda | ||
|
|
b59b010dec | ||
|
|
11266c632f | ||
|
|
850ed4d825 | ||
|
|
f10237d207 | ||
|
|
5eb7830c13 | ||
|
|
7392a9bfc5 | ||
|
|
eacbdf9bb5 | ||
|
|
a40637f9e5 | ||
|
|
14f50cd821 | ||
|
|
eaea6472e0 | ||
|
|
b58c3fd8fb | ||
|
|
4516f99fb9 | ||
|
|
a5a5b56c6e | ||
|
|
caa80bc857 | ||
|
|
f4abea2bb6 | ||
|
|
3b830e4c4a | ||
|
|
1ccc46ec72 | ||
|
|
8ace999ce8 | ||
|
|
523f3f273c | ||
|
|
75f05cb399 | ||
|
|
d9205bb405 | ||
|
|
4b3cf86027 | ||
|
|
e9b0160c5d | ||
|
|
ace578a6ca | ||
|
|
8fb4b69e27 | ||
|
|
0a57e29f2b | ||
|
|
4171874767 | ||
|
|
e1ffcf243b | ||
|
|
1a5f1bd378 | ||
|
|
75052c7c99 | ||
|
|
9d91338b08 | ||
|
|
75999d4e06 | ||
|
|
de77cabd59 | ||
|
|
d7be74e0f4 | ||
|
|
404edececa | ||
|
|
00db944192 | ||
|
|
325c8941b1 | ||
|
|
8722454776 | ||
|
|
44f5c9d664 | ||
|
|
04ff4a3763 | ||
|
|
5abd2cca78 | ||
|
|
0baaf5aed8 | ||
|
|
795cd8e98f | ||
|
|
a11306bf89 | ||
|
|
1bf6546144 | ||
|
|
3d7c075f30 | ||
|
|
d7661a4eca | ||
|
|
5841e52fa9 | ||
|
|
aa640777d7 | ||
|
|
27fe97a994 | ||
|
|
95f98fb385 | ||
|
|
24ce511b59 | ||
|
|
b06f89b356 | ||
|
|
e729effcd8 | ||
|
|
659e83befd | ||
|
|
a7897f3313 | ||
|
|
dc72c24a6c | ||
|
|
1e6d6a3f88 | ||
|
|
e665762c7f | ||
|
|
757b705e2b | ||
|
|
03cb962182 | ||
|
|
1c86bb5c73 | ||
|
|
1c26c0b836 | ||
|
|
8210b7666c | ||
|
|
30ce3c0435 | ||
|
|
04c413e8e1 | ||
|
|
94d7543db5 | ||
|
|
43e1efd79e | ||
|
|
da30e50e14 | ||
|
|
7c6a474929 | ||
|
|
f0414efc79 | ||
|
|
d94a6956b2 | ||
|
|
344483e436 | ||
|
|
6bd740b0a7 | ||
|
|
8c6d11e6cd | ||
|
|
fb7257e19d | ||
|
|
f304ac07f4 | ||
|
|
9c77d0c7a7 | ||
|
|
baa5a9a015 | ||
|
|
cee5fb4740 | ||
|
|
a910ab738b | ||
|
|
e0ee1c4ee4 | ||
|
|
aa6fb31f68 | ||
|
|
a942b8b9f1 | ||
|
|
3b517ea130 | ||
|
|
77fc3de072 | ||
|
|
59633ec460 | ||
|
|
dd0513e592 | ||
|
|
d6bf2d2d71 | ||
|
|
729530a862 | ||
|
|
01a01d971f | ||
|
|
4772ed170b | ||
|
|
9542d5b030 | ||
|
|
23661b42b7 | ||
|
|
edaa0a5125 | ||
|
|
8a0a294fc9 | ||
|
|
52e2f3854f | ||
|
|
cd6a930939 | ||
|
|
5a9a60688c | ||
|
|
2dba052b9f | ||
|
|
a02d7d70c5 | ||
|
|
f3f530feda | ||
|
|
ae342773da | ||
|
|
37e4de3e97 | ||
|
|
2caeacd322 | ||
|
|
caf4d4dc35 | ||
|
|
6c32b1c970 | ||
|
|
fb4387ddbb | ||
|
|
66763e20e6 | ||
|
|
422678dfdf | ||
|
|
4b94694a26 | ||
|
|
572f29e3cd | ||
|
|
541b895d15 | ||
|
|
839285485a | ||
|
|
1b794907da | ||
|
|
c9a7007542 | ||
|
|
6497691b90 | ||
|
|
8489d57b26 | ||
|
|
ca0a216795 | ||
|
|
f30657f9e1 | ||
|
|
ded62eaee9 | ||
|
|
03cb7a0c6f | ||
|
|
62aaf25f8a | ||
|
|
e1d780f33e | ||
|
|
415ca606fd | ||
|
|
0115d08973 | ||
|
|
094947d3d4 | ||
|
|
15e66270f2 | ||
|
|
15590e539a | ||
|
|
743e3dd9ac | ||
|
|
96ca1cf618 | ||
|
|
454335d677 | ||
|
|
dda503a967 | ||
|
|
055c548338 | ||
|
|
8a2a3e2c4c | ||
|
|
c47c7d2c4a | ||
|
|
a5ba09c797 | ||
|
|
27eba96f20 | ||
|
|
c98fe3413e | ||
|
|
99f2d4a602 | ||
|
|
3dad133db8 | ||
|
|
5948634a9c | ||
|
|
09dd7dd9a2 | ||
|
|
06657596ff | ||
|
|
1c3fb798de | ||
|
|
1c09b79cf8 | ||
|
|
e13aeda5b2 | ||
|
|
16491864f9 | ||
|
|
20ad0c3e86 | ||
|
|
53d8db2f04 | ||
|
|
66dd6f625f | ||
|
|
4d16bb14f3 | ||
|
|
4aff2ae71d | ||
|
|
c405523a81 | ||
|
|
bb156cc8da | ||
|
|
4656401ac1 | ||
|
|
46ed75fe02 | ||
|
|
cb39531712 | ||
|
|
e59a859bed | ||
|
|
2fda9c39e9 | ||
|
|
88c8a408b5 | ||
|
|
96baeacc26 | ||
|
|
2647453e16 | ||
|
|
0712391c7f | ||
|
|
b5f0e5b045 | ||
|
|
0219ca8311 | ||
|
|
25dc407781 | ||
|
|
0a4c262b50 | ||
|
|
f13e01d927 | ||
|
|
3503309327 | ||
|
|
90dba82a59 | ||
|
|
2b13a63848 | ||
|
|
f279b32109 | ||
|
|
c8c2b2de00 | ||
|
|
6a37b6682a | ||
|
|
2a65c051e6 | ||
|
|
5d268c71a2 | ||
|
|
02d85c893b | ||
|
|
d7c6f7e8d5 | ||
|
|
249b5ab0f1 | ||
|
|
73d7709e54 | ||
|
|
5f968ac51d | ||
|
|
7eb1bbb5e9 | ||
|
|
43e547f712 | ||
|
|
91a4544ab6 | ||
|
|
9db0b21e35 | ||
|
|
cea62ed831 | ||
|
|
116ddc9213 | ||
|
|
cf99129205 | ||
|
|
a8d580d46a | ||
|
|
1dc37ac221 | ||
|
|
46097060f2 | ||
|
|
643cb1603c | ||
|
|
3ab4ef6840 | ||
|
|
1a423b6dde | ||
|
|
f3e4742ede | ||
|
|
dde59f2a18 | ||
|
|
2f70a75bac | ||
|
|
5020738143 | ||
|
|
d9b10feb88 | ||
|
|
6ddec7906b | ||
|
|
8396778459 | ||
|
|
88bc397816 | ||
|
|
e26d10f4d0 | ||
|
|
0279dc44b7 | ||
|
|
66c432174f | ||
|
|
7f9e7efb67 | ||
|
|
d7d8519976 | ||
|
|
7eb6cdddb2 | ||
|
|
73665c3926 | ||
|
|
055a9f910c | ||
|
|
bad8673865 | ||
|
|
8d7f87bb7b | ||
|
|
c2aeccc98e | ||
|
|
d5ef2adf16 | ||
|
|
fe370d6f4f | ||
|
|
5320993d7a | ||
|
|
701e2bf8b1 | ||
|
|
8caaccbdf8 | ||
|
|
32ef16518c | ||
|
|
cf3e13911b | ||
|
|
a2ad080c51 | ||
|
|
379ded3fb4 | ||
|
|
006ec35637 | ||
|
|
22dc66eeba | ||
|
|
7f2d6aacee | ||
|
|
7124e18e96 | ||
|
|
17386a4ad7 | ||
|
|
5c5a0c77df | ||
|
|
56196a5bb3 | ||
|
|
2f0c76ff0e | ||
|
|
596964fddf | ||
|
|
54e64edb57 | ||
|
|
9674229e8e | ||
|
|
c74b03da9a | ||
|
|
f351c91e48 | ||
|
|
db44f619f2 | ||
|
|
19ce4a1d56 | ||
|
|
57e37221dc | ||
|
|
f647905279 | ||
|
|
09dea80a08 | ||
|
|
c245d4ea20 | ||
|
|
ab78245eb4 | ||
|
|
144eca1299 | ||
|
|
8f9b45f632 | ||
|
|
3ae1e44d8e | ||
|
|
c8c7804a18 | ||
|
|
e711384e22 | ||
|
|
8cee02ebaf | ||
|
|
525dd680f3 | ||
|
|
bf16dcc6ef | ||
|
|
18532f0e54 | ||
|
|
595880d021 | ||
|
|
04ff5d8ea1 | ||
|
|
33fc67bad6 | ||
|
|
12c5e80dba | ||
|
|
214da734e5 | ||
|
|
183c1bf80e | ||
|
|
23f7577e3a | ||
|
|
b398e2e184 | ||
|
|
b317c595c6 | ||
|
|
71e60bc3a5 | ||
|
|
df20253335 | ||
|
|
ab22ac6957 | ||
|
|
f5b7f1c7ce | ||
|
|
2a107c73e9 | ||
|
|
a6abd42c43 | ||
|
|
9245ecd627 | ||
|
|
1e0614ff56 | ||
|
|
68ab7d3968 | ||
|
|
a924b0e8e2 | ||
|
|
d8f2a748fb | ||
|
|
b5898c2e67 | ||
|
|
4815ec474b | ||
|
|
e69884f5e9 | ||
|
|
5ad5c4879d | ||
|
|
cb432a8892 | ||
|
|
0662b5f7a7 | ||
|
|
dec69d4f44 | ||
|
|
b9bc2d167e | ||
|
|
7c5de7b20c | ||
|
|
287e6ff1c4 | ||
|
|
008c0d83e3 | ||
|
|
fb828c9cf4 | ||
|
|
a47913a9d8 | ||
|
|
3d27b42f09 | ||
|
|
163f6cea08 | ||
|
|
892f15f78c | ||
|
|
a94765913b | ||
|
|
b13e7ed5f3 | ||
|
|
ccd4128ad2 | ||
|
|
d43670615d | ||
|
|
76f74effdb | ||
|
|
b236aa6366 | ||
|
|
cd7656394a | ||
|
|
5ac0f91efc | ||
|
|
62d4b0a32d | ||
|
|
e4a76ed058 | ||
|
|
c0ad7721ef | ||
|
|
771d3d6eb5 | ||
|
|
e0792e9b59 | ||
|
|
1b1a4ebc94 | ||
|
|
fe7725c907 | ||
|
|
2d53b4f280 | ||
|
|
9d1f9cfd1f | ||
|
|
30596d182c | ||
|
|
0a8780a9d4 | ||
|
|
3324d992f3 | ||
|
|
08a19ae240 | ||
|
|
7a7afd4daf | ||
|
|
c0b6ee9245 | ||
|
|
054664ef6f | ||
|
|
1158bc9304 | ||
|
|
d3f2b25fa0 | ||
|
|
47bbf187a5 | ||
|
|
b3b933f708 | ||
|
|
8f3ee925ec | ||
|
|
92630082a3 | ||
|
|
74850fad4d | ||
|
|
06e344b0e3 | ||
|
|
ef707b95ef | ||
|
|
22b9427818 | ||
|
|
124891b2b5 | ||
|
|
ea207d299b | ||
|
|
7b77e4d7d8 | ||
|
|
eb052d62b0 | ||
|
|
37ff79fa11 | ||
|
|
be4d66b203 | ||
|
|
17cdb34c9e | ||
|
|
b97e17643c | ||
|
|
10889052bd | ||
|
|
56cbd3ed5d | ||
|
|
5e18fc5d42 | ||
|
|
f15288222f | ||
|
|
faccbd9eb2 | ||
|
|
74a9f1330b | ||
|
|
32387f53e7 | ||
|
|
4162c0f3e0 | ||
|
|
b265759b05 | ||
|
|
bc1de9079d | ||
|
|
b7fc902d6f | ||
|
|
048a0dda1e | ||
|
|
870b2dd449 | ||
|
|
320e4a1f4d | ||
|
|
c010e05023 | ||
|
|
0a11edefcd | ||
|
|
d2bd896367 | ||
|
|
6ce3a7f705 | ||
|
|
81c7ab8b48 | ||
|
|
b7b79b5494 | ||
|
|
068b6a07b9 | ||
|
|
74b1caf01d | ||
|
|
4a2f01b924 | ||
|
|
d26841d34e | ||
|
|
56b278f40b | ||
|
|
3bf25a43b0 | ||
|
|
b591436e00 | ||
|
|
c5a6e94a71 | ||
|
|
063c253ac6 | ||
|
|
52e0e3e794 | ||
|
|
d2f2080147 | ||
|
|
3ab0564272 | ||
|
|
05f763651e | ||
|
|
8984bedec9 | ||
|
|
59ea8b7add | ||
|
|
5b3ba70d91 | ||
|
|
5fb3c6b050 | ||
|
|
85a2f1d6d6 | ||
|
|
19690536c9 | ||
|
|
66aafeca8a | ||
|
|
91aa894a58 | ||
|
|
22b39bad5d | ||
|
|
a12983305d | ||
|
|
bf45591e6c | ||
|
|
f8544fedd4 | ||
|
|
3ff0dbe781 | ||
|
|
bece04d7fd | ||
|
|
914f5ad436 | ||
|
|
d8ee771ea0 | ||
|
|
8e1b260ec3 | ||
|
|
ee821db39b | ||
|
|
42142e4562 | ||
|
|
2b141851a0 | ||
|
|
f48e414d3d | ||
|
|
3ba616dddc | ||
|
|
2f782b9dc5 | ||
|
|
88639ea8bb | ||
|
|
19ca0c77ef | ||
|
|
255527fa95 | ||
|
|
33f4f9c160 | ||
|
|
925673ec1c | ||
|
|
527c92b975 | ||
|
|
142e0c7645 | ||
|
|
f81459d4c0 | ||
|
|
20e0ee50c1 | ||
|
|
fc1b3f345c | ||
|
|
e3d6e59d44 | ||
|
|
11f1b22d6f | ||
|
|
cfe5dda80b | ||
|
|
023c070cfe | ||
|
|
fde0016abc | ||
|
|
1ec1c01f4c | ||
|
|
30d975dac0 | ||
|
|
491c0bdf90 | ||
|
|
303212fa54 | ||
|
|
01e60e478b | ||
|
|
02be488271 | ||
|
|
e7ca1a7a25 | ||
|
|
b54f2d0451 | ||
|
|
08d331e56e | ||
|
|
8b9c937f30 | ||
|
|
7225ed9243 | ||
|
|
bc53d0a6bd | ||
|
|
d77052ee1b | ||
|
|
326c34717f | ||
|
|
d6e408a4be | ||
|
|
ff1cb4da84 | ||
|
|
a26ff35a7b | ||
|
|
cbe508664d | ||
|
|
1018149ca4 | ||
|
|
54f1db6fdc | ||
|
|
2faa87213d | ||
|
|
5985d53625 | ||
|
|
c1e1f0b0b9 | ||
|
|
b35c9b2c14 | ||
|
|
8cc88395d7 | ||
|
|
bd2668335c | ||
|
|
fed2c8dd90 | ||
|
|
16ff72d367 | ||
|
|
f16698a543 | ||
|
|
4c3ef6f5fa | ||
|
|
281c3f6c44 | ||
|
|
9442c023e5 | ||
|
|
61c266057a | ||
|
|
5551c3c737 | ||
|
|
e6d05fefaa | ||
|
|
06ca68d4ab | ||
|
|
9dc1716905 | ||
|
|
373d39c2d0 | ||
|
|
7398d318cd | ||
|
|
3b06d4bff5 | ||
|
|
715b235fea | ||
|
|
5b7e1a06ba | ||
|
|
aaca0798e3 | ||
|
|
c734480f38 | ||
|
|
917b4b64f4 | ||
|
|
dfb7d8571f | ||
|
|
04065bd6bd | ||
|
|
db77a7f3d3 | ||
|
|
09bb198db7 | ||
|
|
b90ce50c0f | ||
|
|
e9fcbe24b4 | ||
|
|
d5878d60c0 | ||
|
|
2a17f9235c | ||
|
|
d966a7d7d7 | ||
|
|
f9483f7e08 | ||
|
|
4625d8463e | ||
|
|
46295a1e83 | ||
|
|
08408bf51d | ||
|
|
d03b4fae25 | ||
|
|
857e2d82d1 | ||
|
|
54f3cd0373 | ||
|
|
f3f8fd78de | ||
|
|
b48d2c1393 | ||
|
|
956727bc3b | ||
|
|
7c28ebe914 | ||
|
|
2867973ee6 | ||
|
|
08ec766353 | ||
|
|
0989628b0d | ||
|
|
69cf2a157e | ||
|
|
9a0a2a590a | ||
|
|
a79f2e0abe | ||
|
|
9c619ea22f | ||
|
|
e52ee910c3 | ||
|
|
bb30bb8ce5 | ||
|
|
5e6ed47d6f | ||
|
|
8387fa4cf7 | ||
|
|
0a79e30c54 | ||
|
|
a3b52a825f | ||
|
|
c8c87c3c8b | ||
|
|
950e6bce45 | ||
|
|
c5360daa66 | ||
|
|
f8b6ece0fe | ||
|
|
8c2bb2a5fb | ||
|
|
97007f3bb5 | ||
|
|
3a9aa99ee9 | ||
|
|
560a5dce42 | ||
|
|
707277744b | ||
|
|
1dce377b5d | ||
|
|
3118ab4326 | ||
|
|
50f404c60f | ||
|
|
4655cd1f17 | ||
|
|
a89d5847df | ||
|
|
ec99dca594 | ||
|
|
3b1263447f | ||
|
|
67698a7e3e | ||
|
|
14a3cdff41 | ||
|
|
9b54ffdb64 | ||
|
|
01d4aac968 | ||
|
|
1e68c9c090 | ||
|
|
e186957e55 | ||
|
|
8adc00a944 | ||
|
|
e7d11f20bb | ||
|
|
0c727545db | ||
|
|
b7dd879a27 | ||
|
|
061175c103 | ||
|
|
83e3583f59 | ||
|
|
670c5a56d6 | ||
|
|
e737c86692 | ||
|
|
f9bd53aaca | ||
|
|
6397c3ef3f | ||
|
|
266e139f72 | ||
|
|
f4e2bead89 | ||
|
|
a02582cc90 | ||
|
|
93e5eacd56 | ||
|
|
317fdb35a8 | ||
|
|
e18a35989f | ||
|
|
e5d74deb98 | ||
|
|
02c3469ec7 | ||
|
|
6e879e8eb3 | ||
|
|
3bc9c595a4 | ||
|
|
5e767e187f | ||
|
|
e4411f36ac | ||
|
|
838113941e | ||
|
|
6b373642e7 | ||
|
|
f475599f2f | ||
|
|
6c7a49688b | ||
|
|
e656941084 | ||
|
|
0bda0feb83 | ||
|
|
0baf02e80f | ||
|
|
73d6e34c5d | ||
|
|
d0c55f5081 | ||
|
|
db5a72f94f | ||
|
|
3c79d66946 | ||
|
|
2f11620221 | ||
|
|
bd9796bd25 | ||
|
|
7d6b552dbd | ||
|
|
f0808ff54b | ||
|
|
fd4f99bd83 | ||
|
|
c0a4107449 | ||
|
|
6b6e70f02c | ||
|
|
e4bef12718 | ||
|
|
f44c876915 | ||
|
|
aac9eee6e2 | ||
|
|
8df4ac7f14 | ||
|
|
374d9d94ef | ||
|
|
12afd6be68 | ||
|
|
7eff19509f | ||
|
|
3e0d076899 | ||
|
|
77e3513d6d | ||
|
|
6d770dbfa6 | ||
|
|
306af8b208 | ||
|
|
f46c39dd99 | ||
|
|
02f8f8bcec | ||
|
|
2fd6921fe1 | ||
|
|
827e7425c5 | ||
|
|
a713d9d649 | ||
|
|
4c2be53a22 | ||
|
|
047368130e | ||
|
|
b2d1968492 | ||
|
|
d6009e5e48 | ||
|
|
d98e44bfc9 | ||
|
|
797652d66c | ||
|
|
876a875576 | ||
|
|
aa62599d13 | ||
|
|
9633ebd486 | ||
|
|
aa5dfaf36f | ||
|
|
55da0596e6 | ||
|
|
84685c1693 | ||
|
|
637a03ae1d | ||
|
|
03c01985c2 | ||
|
|
308b806173 | ||
|
|
16a99c7507 | ||
|
|
2e2d0b121b | ||
|
|
280fb4d8c7 | ||
|
|
13fe35ad61 | ||
|
|
9169421460 | ||
|
|
ae19fd9b00 | ||
|
|
e19470397e | ||
|
|
6ac1f618f0 | ||
|
|
712566ca84 | ||
|
|
c20288ce76 | ||
|
|
dad12b2a79 | ||
|
|
ce0c021c5e | ||
|
|
012c0441d0 | ||
|
|
617e9a0612 | ||
|
|
f2a21e6c3b | ||
|
|
15055bc7c6 | ||
|
|
c4de1a6061 | ||
|
|
86d4449db4 | ||
|
|
123091c1aa | ||
|
|
a4dc7bf127 | ||
|
|
dd24711f21 | ||
|
|
eb02e62a0e | ||
|
|
a6848dda51 | ||
|
|
a07c865161 | ||
|
|
ab1fe668b4 | ||
|
|
85838c77a1 | ||
|
|
a81456450f | ||
|
|
595a29db74 | ||
|
|
e13f52ad7c | ||
|
|
b96d6c37f7 | ||
|
|
8a95f6e05b | ||
|
|
a706c073a8 | ||
|
|
6df2676c88 | ||
|
|
eedb4864df | ||
|
|
a13e2a59d3 | ||
|
|
ab070daa7e | ||
|
|
7d35303395 | ||
|
|
7b4999225a | ||
|
|
6f1833ded3 | ||
|
|
4b904ef762 | ||
|
|
e61b3ce4e4 | ||
|
|
065f833564 | ||
|
|
17e454b1e6 | ||
|
|
e7420f921a | ||
|
|
96b3a2c0d5 | ||
|
|
aae030671b | ||
|
|
7822c4a0fd | ||
|
|
5fb79f4a34 | ||
|
|
7c117e5f8f | ||
|
|
f7b8f74fea | ||
|
|
945b5ff5ad | ||
|
|
78184741a2 | ||
|
|
3d961fd951 | ||
|
|
6846f23e7d | ||
|
|
4eb1c51be5 | ||
|
|
8de387295a | ||
|
|
e1dece0595 | ||
|
|
27a35ea6a2 | ||
|
|
01339fc77d | ||
|
|
396e47abfb | ||
|
|
b53581aae5 | ||
|
|
6bc78b35ec | ||
|
|
63634e2057 | ||
|
|
3570aab4e8 | ||
|
|
f29ad0f840 | ||
|
|
581d01feab | ||
|
|
2eaf26c40f | ||
|
|
60059ea00a | ||
|
|
33d8b551d4 | ||
|
|
c67d961d66 | ||
|
|
9411422faf | ||
|
|
2406f9556f | ||
|
|
ad0738083a | ||
|
|
22883de54e | ||
|
|
dd1b160ef4 | ||
|
|
1820135f3a | ||
|
|
f0f60654e8 | ||
|
|
438d814d49 | ||
|
|
a58825dd2f | ||
|
|
fdafde8ad1 | ||
|
|
66a36481e1 | ||
|
|
59cd2af918 | ||
|
|
61f15ba843 | ||
|
|
4724aee96e | ||
|
|
6915c9c2a5 | ||
|
|
d1835e8cad | ||
|
|
42cc6e9042 | ||
|
|
0d89fa1026 | ||
|
|
06d442a8c1 | ||
|
|
05361e75a4 | ||
|
|
d300b039ad | ||
|
|
4a99080860 | ||
|
|
dcdc7f8862 | ||
|
|
407ee4d8f0 | ||
|
|
6bdb7b4876 | ||
|
|
fa1d011135 | ||
|
|
d9c123a9b9 | ||
|
|
faf654fbc5 | ||
|
|
b25016b893 | ||
|
|
a528984479 | ||
|
|
919e0d08d5 | ||
|
|
41bb7368ff | ||
|
|
879a208034 | ||
|
|
68cadca5ca | ||
|
|
16a6cca015 | ||
|
|
5959c08873 | ||
|
|
5d32d656d5 | ||
|
|
990a59b444 | ||
|
|
41e7ff0ba2 | ||
|
|
c7cd558c3b | ||
|
|
3c8b04d91a | ||
|
|
bcf3a04500 | ||
|
|
8801c30bb7 | ||
|
|
64d5f781b6 | ||
|
|
3a4bc73d38 | ||
|
|
a7213d1a4d | ||
|
|
e8f82ddc55 | ||
|
|
67f0a2516b | ||
|
|
91fa616942 | ||
|
|
46727d367c | ||
|
|
59d4cda1cc | ||
|
|
8ccc997062 | ||
|
|
1d3a285681 | ||
|
|
f269990f9b | ||
|
|
aace2cb788 | ||
|
|
52819e2f81 | ||
|
|
251ea4f84e | ||
|
|
1b3ef42ef6 | ||
|
|
405e65e4aa | ||
|
|
d432b836a9 | ||
|
|
7d459631e6 | ||
|
|
eb20ce01b9 | ||
|
|
bb9495e69c | ||
|
|
7ef92ffa78 | ||
|
|
42f3dcaa8c | ||
|
|
fcabeb919e | ||
|
|
1deae12641 | ||
|
|
137f48c338 | ||
|
|
2f17534394 | ||
|
|
fd9ed2862f | ||
|
|
a17ec1c5f9 | ||
|
|
8864593882 | ||
|
|
f54274442c | ||
|
|
3964ac7a38 | ||
|
|
b6c895e90f | ||
|
|
62d23ce1dd | ||
|
|
dfa0fdfa3d | ||
|
|
9da25b801e | ||
|
|
643cc6d84a | ||
|
|
c697f06b9b | ||
|
|
ecbd7f37c0 | ||
|
|
84cf334c54 | ||
|
|
02613e08b8 | ||
|
|
b682e55596 | ||
|
|
aa877b6491 | ||
|
|
bd59871c22 | ||
|
|
64952806b9 | ||
|
|
42f02aed5c | ||
|
|
cc3dc1716d | ||
|
|
6e58dff088 | ||
|
|
6884451324 | ||
|
|
de0c53b1b2 | ||
|
|
bdc61ed02e | ||
|
|
81345ffcba | ||
|
|
82c34618c9 | ||
|
|
94e8903d16 | ||
|
|
2fdfdedd7b | ||
|
|
16072240e0 | ||
|
|
5e97efab3a | ||
|
|
9276e5eeba | ||
|
|
2ff02426c0 | ||
|
|
7fcdbaf924 | ||
|
|
8e413c96c7 | ||
|
|
95424fa114 | ||
|
|
011a969a53 | ||
|
|
13deca1ef6 | ||
|
|
8c1be1f001 | ||
|
|
4add6d9732 | ||
|
|
1ce12aabfe | ||
|
|
0c09bd2b8c | ||
|
|
4c4e98d885 | ||
|
|
8875919986 | ||
|
|
72868bec31 | ||
|
|
4c3e54cd30 | ||
|
|
4fdc8796f8 | ||
|
|
8f2706d3e2 | ||
|
|
520467b3d6 | ||
|
|
6514efb430 | ||
|
|
d60e58245e | ||
|
|
eadf98ed88 | ||
|
|
2560c7b074 | ||
|
|
754b2581cd | ||
|
|
5462b1707f | ||
|
|
617f9b9bfc | ||
|
|
7a43efa9da | ||
|
|
4178005ebc | ||
|
|
09dcca1b8d | ||
|
|
5cec5a363d | ||
|
|
ee797c929e | ||
|
|
a72ce30654 | ||
|
|
b61a34e48c | ||
|
|
40d77568af | ||
|
|
012fa82684 | ||
|
|
2c865132d9 | ||
|
|
8b239cd292 | ||
|
|
8358c66702 | ||
|
|
3f49c7e509 | ||
|
|
8b7d8dc348 | ||
|
|
ebed12dbec | ||
|
|
043389524a | ||
|
|
451e490dfd | ||
|
|
d32b380fc3 | ||
|
|
c9a5fe3d25 | ||
|
|
6368485cf3 | ||
|
|
ea865eb0aa | ||
|
|
4944887d4a | ||
|
|
f16bfecab8 | ||
|
|
b2b111f65e | ||
|
|
3461b19c70 | ||
|
|
308d2c4445 | ||
|
|
c67a033f8a | ||
|
|
feda6d390e | ||
|
|
2cc091c708 | ||
|
|
dc98d4042b | ||
|
|
c0c042dac0 | ||
|
|
a8e1de079c | ||
|
|
21986b331c | ||
|
|
06d4dbc99b | ||
|
|
ce0590449a | ||
|
|
edfa95057b | ||
|
|
57b8263acd | ||
|
|
174779bb28 | ||
|
|
e47268bb8b | ||
|
|
29c2d8b1a2 | ||
|
|
82c3d773d6 | ||
|
|
7e3df042ec | ||
|
|
dd0e69d6ec | ||
|
|
551ddf5f94 | ||
|
|
ac84c16a4a | ||
|
|
9be0735207 | ||
|
|
7177e62517 | ||
|
|
7dd66e6737 | ||
|
|
41352107f9 | ||
|
|
7024b7f11a | ||
|
|
41980188cf | ||
|
|
dbd16f33a9 | ||
|
|
ccf59da754 | ||
|
|
b9e69ec833 | ||
|
|
495d9ccc0c | ||
|
|
6d3c08f3eb | ||
|
|
d3b4906da9 | ||
|
|
40b617c429 | ||
|
|
b4f56cda59 | ||
|
|
f81c600aaf | ||
|
|
09b8c9c8bc | ||
|
|
66fbdf7e74 | ||
|
|
e4533e6601 | ||
|
|
8d6ded2fcc | ||
|
|
d8b176a329 | ||
|
|
7d101edf71 | ||
|
|
0674a48854 | ||
|
|
0682bc1b06 | ||
|
|
6ad94242c4 | ||
|
|
f57aaf7e80 | ||
|
|
322fb098a4 | ||
|
|
b3f1ba6ca0 | ||
|
|
a527e745d1 | ||
|
|
bb0219c5ed | ||
|
|
76fa003189 | ||
|
|
b2bac25a92 | ||
|
|
4a75946baf | ||
|
|
f7925fca5a | ||
|
|
7211dd026f | ||
|
|
f20b795322 | ||
|
|
b53204a765 | ||
|
|
eb929eb99e | ||
|
|
42c4f10000 | ||
|
|
d7a41cd68d | ||
|
|
5a23f67d31 | ||
|
|
11c7e3ad83 | ||
|
|
5e3f914182 | ||
|
|
6060a81cc3 | ||
|
|
9935556947 | ||
|
|
0a265f9981 | ||
|
|
7c96f46e0e | ||
|
|
2d18e8f558 | ||
|
|
de4b40605a | ||
|
|
716c9ea34c | ||
|
|
b4724f3ae0 | ||
|
|
9ad7332b30 | ||
|
|
9b0f608b6b | ||
|
|
137d6a1923 | ||
|
|
011aac0bfc | ||
|
|
52a59d8dfd | ||
|
|
4dd76949c4 | ||
|
|
7c15f704e0 | ||
|
|
85d53c8986 | ||
|
|
94dbd89d8f | ||
|
|
083d74c904 | ||
|
|
e9447cdcfe | ||
|
|
a32abb43c5 | ||
|
|
86090be4a3 | ||
|
|
89191290e4 | ||
|
|
a5d71d2dfa | ||
|
|
a5a8b32a25 | ||
|
|
d7ddffe3f8 | ||
|
|
696a7785e0 | ||
|
|
b1602b2b1a | ||
|
|
7c076ea567 | ||
|
|
ddcbed4761 | ||
|
|
46f903583b | ||
|
|
00f5f239b2 | ||
|
|
f87d4e3d18 | ||
|
|
ffdf247517 | ||
|
|
56cdcf8622 | ||
|
|
f381de0d8b | ||
|
|
62bc987697 | ||
|
|
1a9a5d99fa | ||
|
|
90b5602eb8 | ||
|
|
8183552011 | ||
|
|
4c9f04bc1c | ||
|
|
b5ae4e9a64 | ||
|
|
4c57486d79 | ||
|
|
ff468baf49 | ||
|
|
0f49444c05 | ||
|
|
fa458f06a4 | ||
|
|
32be658e96 | ||
|
|
22f325fbff | ||
|
|
14d7085ec3 | ||
|
|
8d34618849 | ||
|
|
c2abb78612 | ||
|
|
52572d28b3 | ||
|
|
e44b86c94c | ||
|
|
b2ff15266e | ||
|
|
8d1da35b56 | ||
|
|
50270f87ed | ||
|
|
109977c6bb | ||
|
|
b5d4410dca | ||
|
|
0083b7445a | ||
|
|
e795655bd9 | ||
|
|
4522e0a56c | ||
|
|
1b337e9766 | ||
|
|
36ad39237b | ||
|
|
73d7d4e1a8 | ||
|
|
76c08eb189 | ||
|
|
36f971bb7e | ||
|
|
0d33006da2 | ||
|
|
f0788e0b4b | ||
|
|
f413d4ce0e | ||
|
|
9fa914c6d0 | ||
|
|
5fdbd90877 | ||
|
|
a22aeae644 | ||
|
|
75083f1c75 | ||
|
|
f9ce24579d | ||
|
|
81867d85e3 | ||
|
|
1bb1938e0b | ||
|
|
c2edd93c72 | ||
|
|
2bb4f5088b | ||
|
|
849bf813b4 | ||
|
|
3fbeaf09ea | ||
|
|
808a31f19e | ||
|
|
3274d3aaff | ||
|
|
e50502417b | ||
|
|
2310b4306f | ||
|
|
b3b4a587c9 | ||
|
|
b56199c69d | ||
|
|
c5d2525086 | ||
|
|
eb2ad57c5a | ||
|
|
4f0232cbbf | ||
|
|
a383e557ff | ||
|
|
eff461891d | ||
|
|
de9e8e36d4 | ||
|
|
4f01af87a4 | ||
|
|
f3a4df52b0 | ||
|
|
fdeae3d432 | ||
|
|
07e6e9fe98 | ||
|
|
7596132e02 | ||
|
|
c5e8b0a251 | ||
|
|
ed941a02aa | ||
|
|
7bbfa1843b | ||
|
|
f92f472c95 | ||
|
|
5c83c5a562 | ||
|
|
0d5377cae0 | ||
|
|
9dd693e873 | ||
|
|
a2ff21bd82 | ||
|
|
45763aa4e3 | ||
|
|
d5f62c0df0 | ||
|
|
578eeb3928 | ||
|
|
7ac160a368 | ||
|
|
9b9d007e0d | ||
|
|
82adc1d426 | ||
|
|
c2e73a493a | ||
|
|
63e1989d4b | ||
|
|
5c26c4094d | ||
|
|
6b17c6b854 | ||
|
|
450a54bcb9 | ||
|
|
af40927b0a | ||
|
|
574fb6d393 | ||
|
|
1e94bd5bcf | ||
|
|
23528d52f8 | ||
|
|
568865dbae | ||
|
|
1ad0c44dd4 | ||
|
|
0a31d455da | ||
|
|
5528ed683b | ||
|
|
7042a04212 | ||
|
|
fb81d1f8ff | ||
|
|
998025104b | ||
|
|
53453b81b8 | ||
|
|
1ee5379022 | ||
|
|
34d30d9e43 | ||
|
|
696aa96fd9 | ||
|
|
16756e770e | ||
|
|
05fce1a61e | ||
|
|
478e3d79d3 | ||
|
|
78b497e551 | ||
|
|
9e9b8f78f0 | ||
|
|
b183506c13 | ||
|
|
a53a340d16 | ||
|
|
15d908626e | ||
|
|
93c460f6a5 | ||
|
|
78ef250ee1 | ||
|
|
1920921ee7 | ||
|
|
833fcae116 | ||
|
|
d86247d627 | ||
|
|
5c51457761 | ||
|
|
812af254aa | ||
|
|
eee90f1a5c | ||
|
|
c46c55312e | ||
|
|
82480600a4 | ||
|
|
7e2ae9e45b | ||
|
|
45691c025d | ||
|
|
3722dde811 |
@@ -1,125 +1,641 @@
|
||||
{
|
||||
"projectName": "toeverything",
|
||||
"projectOwner": "toeverything",
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com",
|
||||
"files": [
|
||||
"README.md"
|
||||
],
|
||||
"imageSize": 100,
|
||||
"commit": false,
|
||||
"commitConvention": "angular",
|
||||
"contributorsPerLine": 7,
|
||||
"contributors": [
|
||||
{
|
||||
"login": "darkskygit",
|
||||
"name": "DarkSky",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/25152247?v=4",
|
||||
"profile": "https://darksky.eu.org/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "tzhangchi",
|
||||
"name": "Chi Zhang",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5910926?v=4",
|
||||
"profile": "http://zhangchi.page/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "alt1o",
|
||||
"name": "wang xinglong",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/21084335?v=4",
|
||||
"profile": "https://github.com/alt1o",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "DiamondThree",
|
||||
"name": "DiamondThree",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/24630517?v=4",
|
||||
"profile": "https://github.com/DiamondThree",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lawvs",
|
||||
"name": "Whitewater",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/18554747?v=4",
|
||||
"profile": "https://lawvs.github.io/profile/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "zuoxiaodong0815",
|
||||
"name": "xiaodong zuo",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/53252747?v=4",
|
||||
"profile": "https://github.com/zuoxiaodong0815",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "SaikaSakura",
|
||||
"name": "MingLIang Wang",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11530942?v=4",
|
||||
"profile": "https://github.com/SaikaSakura",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "QiShaoXuan",
|
||||
"name": "Qi",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/22772830?v=4",
|
||||
"profile": "https://github.com/QiShaoXuan",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mitsuhatu",
|
||||
"name": "mitsuhatu",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/110213079?v=4",
|
||||
"profile": "https://github.com/mitsuhatu",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Austaras",
|
||||
"name": "Austaras",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/15013925?v=4",
|
||||
"profile": "https://shockwave.me/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "uptonking",
|
||||
"name": "Jin Yao",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11391549?v=4",
|
||||
"profile": "https://github.com/uptonking?tab=repositories&type=source",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
}
|
||||
]
|
||||
"projectName": "AFFiNE",
|
||||
"projectOwner": "toeverything",
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com",
|
||||
"files": [
|
||||
"README.md"
|
||||
],
|
||||
"imageSize": 50,
|
||||
"commit": false,
|
||||
"commitConvention": "angular",
|
||||
"contributorsPerLine": 7,
|
||||
"badgeTemplate": "\n[all-contributors-badge]: https://img.shields.io/badge/all_contributors-<%= contributors.length %>-orange.svg?style=flat-square\n",
|
||||
"contributors": [
|
||||
{
|
||||
"login": "doodlewind",
|
||||
"name": "Yifeng Wang",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/7312949?v=4",
|
||||
"profile": "https://github.com/doodlewind",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "darkskygit",
|
||||
"name": "DarkSky",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/25152247?v=4",
|
||||
"profile": "https://darksky.eu.org/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "tzhangchi",
|
||||
"name": "Chi Zhang",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5910926?v=4",
|
||||
"profile": "http://zhangchi.page/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "alt1o",
|
||||
"name": "wang xinglong",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/21084335?v=4",
|
||||
"profile": "https://github.com/alt1o",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Brooooooklyn",
|
||||
"name": "LongYinan",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3468483?v=4",
|
||||
"profile": "https://github.com/Brooooooklyn",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "hwangdev97",
|
||||
"name": "Hwang",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/24713927?v=4",
|
||||
"profile": "https://github.com/hwangdev97",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "kobeshanks",
|
||||
"name": "kobeshanks",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/82570088?v=4",
|
||||
"profile": "https://github.com/kobeshanks",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "pengx17",
|
||||
"name": "Peng Xiao",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/584378?v=4",
|
||||
"profile": "https://pengx17.vercel.app/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Saul-Mirone",
|
||||
"name": "Mirone",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/10047788?v=4",
|
||||
"profile": "https://mirone.me/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "zqran",
|
||||
"name": "zqran",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/15389209?v=4",
|
||||
"profile": "https://github.com/zqran",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "SuneBear",
|
||||
"name": "Shule Hsiung",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/7693264?v=4",
|
||||
"profile": "https://sunebear.com/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "fundon",
|
||||
"name": "Fangdun Tsai",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/27926?v=4",
|
||||
"profile": "https://fundon.viz.rs/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lawvs",
|
||||
"name": "Whitewater",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/18554747?v=4",
|
||||
"profile": "https://lawvs.github.io/profile/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "zuoxiaodong0815",
|
||||
"name": "xiaodong zuo",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/53252747?v=4",
|
||||
"profile": "https://github.com/zuoxiaodong0815",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Himself65",
|
||||
"name": "Himself65",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/14026360?v=4",
|
||||
"profile": "https://github.com/Himself65",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "DiamondThree",
|
||||
"name": "DiamondThree",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/24630517?v=4",
|
||||
"profile": "https://github.com/DiamondThree",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "QiShaoXuan",
|
||||
"name": "Qi",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/22772830?v=4",
|
||||
"profile": "https://github.com/QiShaoXuan",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "colelawrence",
|
||||
"name": "Cole Lawrence",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2925395?v=4",
|
||||
"profile": "https://colelawrence.com/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "linonetwo",
|
||||
"name": "lin onetwo",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3746270?v=4",
|
||||
"profile": "https://onetwo.ren/wiki",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "thorseraq",
|
||||
"name": "x1a0t",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/20554850?v=4",
|
||||
"profile": "https://github.com/thorseraq",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "HeJiachen-PM",
|
||||
"name": "HeJiachen-PM",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/79301703?v=4",
|
||||
"profile": "https://github.com/HeJiachen-PM",
|
||||
"contributions": [
|
||||
"research",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "joebeijing",
|
||||
"name": "houjoe",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/22443345?v=4",
|
||||
"profile": "https://www.notion.so/houjoe/Joe-2a85f5be01004cd2b6a5ad26fbb948b1",
|
||||
"contributions": [
|
||||
"research",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Yipei-Operation",
|
||||
"name": "Yipei Wei",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/79373028?v=4",
|
||||
"profile": "https://github.com/Yipei-Operation",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "VelikaHF",
|
||||
"name": "Velika",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/121547898?v=4",
|
||||
"profile": "https://github.com/VelikaHF",
|
||||
"contributions": [
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Svaney-ssman",
|
||||
"name": "Svaney",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/110808979?v=4",
|
||||
"profile": "https://github.com/Svaney-ssman",
|
||||
"contributions": [
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "xell",
|
||||
"name": "Guozhu Liu",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/132558?v=4",
|
||||
"profile": "http://xell.me/",
|
||||
"contributions": [
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "fyZheng07",
|
||||
"name": "fyZheng07",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/63830919?v=4",
|
||||
"profile": "https://github.com/fyZheng07",
|
||||
"contributions": [
|
||||
"eventOrganizing",
|
||||
"userTesting"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "CJSS",
|
||||
"name": "CJSS",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/4605025?v=4",
|
||||
"profile": "https://github.com/CJSS",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "JimmFly",
|
||||
"name": "JimmFly",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/102217452?v=4",
|
||||
"profile": "https://github.com/JimmFly",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mitsuhatu",
|
||||
"name": "mitsuhatu",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/110213079?v=4",
|
||||
"profile": "https://github.com/mitsuhatu",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Austaras",
|
||||
"name": "Austaras",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/15013925?v=4",
|
||||
"profile": "https://shockwave.me/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "uptonking",
|
||||
"name": "Jin Yao",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11391549?v=4",
|
||||
"profile": "https://github.com/uptonking",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "CarlosZoft",
|
||||
"name": "Carlos Rafael ",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/62192072?v=4",
|
||||
"profile": "https://github.com/CarlosZoft",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "caleboleary",
|
||||
"name": "Caleb OLeary",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/12816579?v=4",
|
||||
"profile": "https://github.com/caleboleary",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "westongraham",
|
||||
"name": "Weston Graham",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/89493023?v=4",
|
||||
"profile": "https://github.com/westongraham",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "SaikaSakura",
|
||||
"name": "MingLIang Wang",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11530942?v=4",
|
||||
"profile": "https://github.com/SaikaSakura",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "fanjing22",
|
||||
"name": "fanjing22",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/109729699?v=4",
|
||||
"profile": "https://github.com/fanjing22",
|
||||
"contributions": [
|
||||
"design"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "pointmax",
|
||||
"name": "pointmax",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/49361135?v=4",
|
||||
"profile": "https://github.com/pointmax",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "liby",
|
||||
"name": "Bryan Lee",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/38807139?v=4",
|
||||
"profile": "https://liby.github.io/notes",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "chenmoonmo",
|
||||
"name": "Simon Li",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/36295999?v=4",
|
||||
"profile": "https://github.com/chenmoonmo",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "githbq",
|
||||
"name": "Bob Hu",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/10009709?v=4",
|
||||
"profile": "https://github.com/githbq",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lucky-chap",
|
||||
"name": "Quavo",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/67266933?v=4",
|
||||
"profile": "https://quavo.vercel.app/",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "LuciNyan",
|
||||
"name": "子瞻 Luci",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/22126563?v=4",
|
||||
"profile": "https://github.com/LuciNyan",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "m1911star",
|
||||
"name": "Horus",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/4948120?v=4",
|
||||
"profile": "http://blog.ipili.me/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"platform"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "fanshyiis",
|
||||
"name": "Super.x",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/15103283?v=4",
|
||||
"profile": "https://segmentfault.com/u/qzuser_584786517d31a",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "wangyu-1999",
|
||||
"name": "Wang Yu",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/80874770?v=4",
|
||||
"profile": "https://wangyu-1999.github.io/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "felixonmars",
|
||||
"name": "Felix Yan",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1006477?v=4",
|
||||
"profile": "https://felixc.at/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lynettelopez",
|
||||
"name": "Lynette Lopez",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/32908859?v=4",
|
||||
"profile": "https://github.com/lynettelopez",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Zheaoli",
|
||||
"name": "Manjusaka",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/7054676?v=4",
|
||||
"profile": "http://manjusaka.itscoder.com/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "sudongyuer",
|
||||
"name": "Frozen FIsh",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/76603360?v=4",
|
||||
"profile": "https://juejin.cn/user/2867982785579102/posts?sort=popular",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "MuhammedFaraz",
|
||||
"name": "Mohammed Faraz",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/92734739?v=4",
|
||||
"profile": "https://github.com/MuhammedFaraz",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Pranav4399",
|
||||
"name": "Pranav Sriram ",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/28348429?v=4",
|
||||
"profile": "https://pranavsriram.dev/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Reson-a",
|
||||
"name": "Reson-a",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/20806266?v=4",
|
||||
"profile": "https://github.com/Reson-a",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "hezhizhen",
|
||||
"name": "Zhizhen He",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/7611700?v=4",
|
||||
"profile": "https://t.me/littlepoint",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "AkaraChen",
|
||||
"name": "AkaraChen",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/85140972?v=4",
|
||||
"profile": "https://akr.moe/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "suyanhanx",
|
||||
"name": "Suyan",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/24221472?v=4",
|
||||
"profile": "https://github.com/suyanhanx",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "hehex9",
|
||||
"name": "hehe",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/9209882?v=4",
|
||||
"profile": "https://github.com/hehex9",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "albertodlc",
|
||||
"name": "Alberto de la Cruz",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/32411964?v=4",
|
||||
"profile": "https://github.com/albertodlc",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "AlessioGr",
|
||||
"name": "Alessio Gravili",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/70709113?v=4",
|
||||
"profile": "https://github.com/AlessioGr",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lzlme",
|
||||
"name": "Zhilin Liu",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/117659326?v=4",
|
||||
"profile": "https://github.com/lzlme",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "suica",
|
||||
"name": "Sg",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/8041462?v=4",
|
||||
"profile": "https://github.com/suica",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "sinchang",
|
||||
"name": "Jeff Wen",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3297859?v=4",
|
||||
"profile": "https://sinchang.me/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "m1212e",
|
||||
"name": "m1212e",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/14091540?v=4",
|
||||
"profile": "https://m1212e.github.io/portfolio/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "adityash1",
|
||||
"name": "Aditya Sharma",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/65771169?v=4",
|
||||
"profile": "https://adityash1.github.io/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "sheben404",
|
||||
"name": "Kehan Wang",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/61317160?v=4",
|
||||
"profile": "https://github.com/sheben404",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "VictorNanka",
|
||||
"name": "VictorNanka",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/30154366?v=4",
|
||||
"profile": "https://github.com/VictorNanka",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
28
.commitlintrc.json
Normal file
28
.commitlintrc.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"extends": ["@commitlint/config-conventional"],
|
||||
"rules": {
|
||||
"scope-enum": [
|
||||
2,
|
||||
"always",
|
||||
[
|
||||
"electron",
|
||||
"server",
|
||||
"web",
|
||||
"docs",
|
||||
"component",
|
||||
"workspace",
|
||||
"env",
|
||||
"graphql",
|
||||
"cli",
|
||||
"hooks",
|
||||
"i18n",
|
||||
"jotai",
|
||||
"native",
|
||||
"templates",
|
||||
"y-indexeddb",
|
||||
"debug",
|
||||
"theme"
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
module.exports = {
|
||||
types: [
|
||||
{ value: 'feat', name: 'feat 🍄: add new features' },
|
||||
{ value: 'fix', name: 'fix 🐛: fix bug' },
|
||||
{ value: 'docs', name: 'docs 📄: modify documentation, comments' },
|
||||
{
|
||||
value: 'refactor',
|
||||
name: 'refactor 🎸: code refactoring, pay attention to distinguish it from features and fixes',
|
||||
},
|
||||
{ value: 'perf', name: 'perf ⚡: improve performance' },
|
||||
{ value: 'test', name: 'test 👀: add a test' },
|
||||
{
|
||||
value: 'tool',
|
||||
name: 'tool 🚗: Development tool changes (build, scaffolding tools, etc.)',
|
||||
},
|
||||
{
|
||||
value: 'style',
|
||||
name: 'style ✂: Modifications to code formatting do not affect logic',
|
||||
},
|
||||
{ value: 'revert', name: 'revert 🌝: version rollback' },
|
||||
{
|
||||
value: 'editor',
|
||||
name: 'editor 🔧: editor configuration modification',
|
||||
},
|
||||
{ value: 'update', name: 'update ⬆: third-party library upgrade' },
|
||||
],
|
||||
scopes: [
|
||||
{ name: 'selection' },
|
||||
{ name: 'whiteboard' },
|
||||
{ name: 'point' },
|
||||
{ name: 'group' },
|
||||
{ name: 'page' },
|
||||
{ name: 'component' },
|
||||
{ name: 'config' },
|
||||
{ name: 'others' },
|
||||
],
|
||||
|
||||
// it needs to match the value for field type. Eg.: 'fix'
|
||||
/*
|
||||
scopeOverrides: {
|
||||
fix: [
|
||||
{name: 'merge'},
|
||||
{name: 'style'}
|
||||
]
|
||||
|
||||
},
|
||||
*/
|
||||
// override the messages, de faults are as follows
|
||||
messages: {
|
||||
type: 'Choose a type of your submission:',
|
||||
scope: 'Choose a scope (optional):',
|
||||
// used if allowCustomScopes is true
|
||||
customScope: 'Denote the SCOPE of this change:',
|
||||
subject: 'Brief description:\n',
|
||||
body: 'Detailed description, use "|" newline (optional):\n',
|
||||
breaking: 'Incompatibility specification (optional):\n',
|
||||
footer: 'Associate closed issues, for example: #31, #34 (optional):\n',
|
||||
confirmCommit: 'Are you sure to commit?',
|
||||
},
|
||||
|
||||
allowCustomScopes: true,
|
||||
allowBreakingChanges: ['Added', 'Repair'],
|
||||
|
||||
// limit subject length
|
||||
subjectLimit: 100,
|
||||
};
|
||||
@@ -4,7 +4,7 @@ root = true
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
|
||||
4
.env
4
.env
@@ -1,4 +0,0 @@
|
||||
# use for download icon from figma
|
||||
FIGMA_TOKEN
|
||||
NODE_ENV
|
||||
AFFINE_FEATURE_FLAG_TOKEN
|
||||
@@ -1 +0,0 @@
|
||||
NX_LOCAL=true
|
||||
@@ -1,4 +1,7 @@
|
||||
**/webpack.config.js
|
||||
**/jest.config.js
|
||||
**/node_modules/**
|
||||
.github/**
|
||||
node_modules
|
||||
dist
|
||||
.next
|
||||
out
|
||||
storybook-static
|
||||
affine-out
|
||||
_next
|
||||
|
||||
102
.eslintrc.js
Normal file
102
.eslintrc.js
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @type {import('eslint').Linter.Config}
|
||||
*/
|
||||
const config = {
|
||||
root: true,
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect',
|
||||
},
|
||||
next: {
|
||||
rootDir: 'apps/web',
|
||||
},
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
'plugin:react/recommended',
|
||||
'plugin:react/jsx-runtime',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
globalReturn: false,
|
||||
impliedStrict: true,
|
||||
jsx: true,
|
||||
},
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: [
|
||||
'react',
|
||||
'@typescript-eslint',
|
||||
'simple-import-sort',
|
||||
'import',
|
||||
'unused-imports',
|
||||
'unicorn',
|
||||
],
|
||||
rules: {
|
||||
'no-undef': 'off',
|
||||
'no-empty': 'off',
|
||||
'no-func-assign': 'off',
|
||||
'no-cond-assign': 'off',
|
||||
'react/prop-types': 'off',
|
||||
'@typescript-eslint/consistent-type-imports': 'error',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
varsIgnorePattern: '^_',
|
||||
argsIgnorePattern: '^_',
|
||||
caughtErrorsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'unused-imports/no-unused-imports': 'error',
|
||||
'simple-import-sort/imports': 'error',
|
||||
'simple-import-sort/exports': 'error',
|
||||
'@typescript-eslint/ban-ts-comment': 0,
|
||||
'@typescript-eslint/no-restricted-imports': [
|
||||
'error',
|
||||
{
|
||||
patterns: [
|
||||
{
|
||||
group: ['**/dist'],
|
||||
message: "Don't import from dist",
|
||||
allowTypeImports: false,
|
||||
},
|
||||
{
|
||||
group: ['**/src'],
|
||||
message: "Don't import from src",
|
||||
allowTypeImports: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
'unicorn/filename-case': [
|
||||
'error',
|
||||
{
|
||||
case: 'kebabCase',
|
||||
ignore: ['^\\[[a-zA-Z0-9-_]+\\]\\.tsx$'],
|
||||
},
|
||||
],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: 'apps/server/**/*.ts',
|
||||
rules: {
|
||||
'@typescript-eslint/consistent-type-imports': 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
files: '*.cjs',
|
||||
rules: {
|
||||
'@typescript-eslint/no-var-requires': 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
288
.eslintrc.json
288
.eslintrc.json
@@ -1,288 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"ignorePatterns": ["**/*"],
|
||||
"plugins": ["@nrwl/nx", "react", "filename-rules", "import", "prettier"],
|
||||
"parserOptions": {
|
||||
"project": ["./tsconfig.base.json"]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {
|
||||
"prettier/prettier": "warn",
|
||||
"@nrwl/nx/enforce-module-boundaries": [
|
||||
"error",
|
||||
{
|
||||
"enforceBuildableLibDependency": true,
|
||||
"allow": [],
|
||||
"depConstraints": [
|
||||
{
|
||||
"sourceTag": "library:utils",
|
||||
"onlyDependOnLibsWithTags": ["library:utils"]
|
||||
},
|
||||
{
|
||||
"sourceTag": "datasource:jwt",
|
||||
"onlyDependOnLibsWithTags": [
|
||||
"library:utils",
|
||||
"datasource:remote-kv",
|
||||
"datasource:jwt-rpc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sourceTag": "datasource:db-services",
|
||||
"onlyDependOnLibsWithTags": [
|
||||
"library:utils",
|
||||
"datasource:jwt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sourceTag": "datasource:hooks",
|
||||
"onlyDependOnLibsWithTags": [
|
||||
"library:utils",
|
||||
"datasource:jwt",
|
||||
"datasource:db-services"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sourceTag": "datasource:http",
|
||||
"onlyDependOnLibsWithTags": ["library:utils"]
|
||||
},
|
||||
{
|
||||
"sourceTag": "datasource:state",
|
||||
"onlyDependOnLibsWithTags": [
|
||||
"library:utils",
|
||||
"library:feature-flags",
|
||||
"datasource:http",
|
||||
"datasource:jwt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sourceTag": "components:common",
|
||||
"onlyDependOnLibsWithTags": [
|
||||
"library:utils",
|
||||
"components:icons",
|
||||
"components:ui",
|
||||
"library:feature-flags"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sourceTag": "components:editor-core",
|
||||
"onlyDependOnLibsWithTags": [
|
||||
"library:utils",
|
||||
"library:feature-flags",
|
||||
"datasource:db-services",
|
||||
"datasource:state",
|
||||
"datasource:commands",
|
||||
"datasource:jwt",
|
||||
"components:ui",
|
||||
"components:common",
|
||||
"components:icons"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sourceTag": "components:editor-blocks",
|
||||
"onlyDependOnLibsWithTags": [
|
||||
"library:utils",
|
||||
"library:feature-flags",
|
||||
"components:common",
|
||||
"components:editor-core",
|
||||
"framework:editor",
|
||||
"datasource:db-services",
|
||||
"components:ui",
|
||||
"components:icons"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sourceTag": "components:editor-plugins",
|
||||
"onlyDependOnLibsWithTags": [
|
||||
"library:utils",
|
||||
"components:common",
|
||||
"components:editor-core",
|
||||
"framework:editor",
|
||||
"components:editor-blocks",
|
||||
"datasource:db-services",
|
||||
"components:ui",
|
||||
"components:icons",
|
||||
"library:feature-flags"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sourceTag": "components:ui",
|
||||
"onlyDependOnLibsWithTags": [
|
||||
"components:icons",
|
||||
"library:utils"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sourceTag": "framework:editor",
|
||||
"onlyDependOnLibsWithTags": [
|
||||
"components:editor-core"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sourceTag": "*",
|
||||
"onlyDependOnLibsWithTags": ["*"]
|
||||
}
|
||||
],
|
||||
"allowCircularSelfDependency": false
|
||||
}
|
||||
],
|
||||
"filename-rules/match": [
|
||||
"warn",
|
||||
{
|
||||
".tsx": "PascalCase",
|
||||
".ts": "kebab-case",
|
||||
".json": "kebab-case",
|
||||
"": "kebab-case"
|
||||
}
|
||||
],
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"patterns": [
|
||||
{
|
||||
"group": ["lodash"],
|
||||
"message": "Forbid direct import of lodash, use @toeverything/utils"
|
||||
},
|
||||
{
|
||||
"group": ["lodash-es"],
|
||||
"message": "Forbid direct import of lodash-es, use @toeverything/utils"
|
||||
},
|
||||
{
|
||||
"group": ["@mui/material", "@mui/material/*"],
|
||||
"message": "Forbid direct import of @mui/material, use @toeverything/components/ui"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/naming-convention": [
|
||||
"warn",
|
||||
{
|
||||
"selector": [
|
||||
"property",
|
||||
"parameterProperty",
|
||||
"accessor",
|
||||
"enumMember"
|
||||
],
|
||||
"format": ["strictCamelCase"]
|
||||
},
|
||||
{
|
||||
"selector": ["property", "accessor"],
|
||||
"modifiers": ["private"],
|
||||
"format": ["strictCamelCase"],
|
||||
"leadingUnderscore": "require"
|
||||
},
|
||||
{
|
||||
"selector": ["method"],
|
||||
"modifiers": ["public"],
|
||||
"format": ["strictCamelCase"]
|
||||
},
|
||||
// Private methods
|
||||
{
|
||||
"selector": ["method"],
|
||||
"modifiers": ["private"],
|
||||
"format": ["strictCamelCase"],
|
||||
"leadingUnderscore": "require"
|
||||
},
|
||||
{
|
||||
"selector": ["method"],
|
||||
"modifiers": ["protected"],
|
||||
"format": ["strictCamelCase"],
|
||||
"leadingUnderscore": "require"
|
||||
},
|
||||
// Top Level Methods
|
||||
// const func: Function
|
||||
// allow PascalCase for react components
|
||||
{
|
||||
"selector": ["variable"],
|
||||
"modifiers": ["global"],
|
||||
"types": ["function"],
|
||||
"format": ["strictCamelCase", "StrictPascalCase"],
|
||||
"leadingUnderscore": "allow"
|
||||
},
|
||||
// function something() { }
|
||||
{
|
||||
"selector": ["function"],
|
||||
"modifiers": ["global"],
|
||||
"format": ["strictCamelCase"],
|
||||
"leadingUnderscore": "require"
|
||||
},
|
||||
// export const func: Function
|
||||
{
|
||||
"selector": ["variable"],
|
||||
"modifiers": ["exported"],
|
||||
"types": ["function"],
|
||||
"format": ["strictCamelCase", "StrictPascalCase"],
|
||||
"leadingUnderscore": "forbid"
|
||||
},
|
||||
// export function something() { }
|
||||
{
|
||||
"selector": ["function"],
|
||||
"modifiers": ["exported"],
|
||||
"format": ["strictCamelCase", "StrictPascalCase"],
|
||||
"leadingUnderscore": "forbid"
|
||||
},
|
||||
// Top Level Variables
|
||||
{
|
||||
"selector": ["variable"],
|
||||
"modifiers": ["global", "const"],
|
||||
"types": ["boolean", "string", "number"],
|
||||
"format": ["UPPER_CASE"]
|
||||
},
|
||||
{
|
||||
"selector": ["variable"],
|
||||
"modifiers": ["global"],
|
||||
"format": ["strictCamelCase"],
|
||||
"leadingUnderscore": "require"
|
||||
},
|
||||
{
|
||||
"selector": ["variable"],
|
||||
"modifiers": ["exported"],
|
||||
"format": ["strictCamelCase"]
|
||||
},
|
||||
// types, enums
|
||||
{
|
||||
"selector": "typeLike",
|
||||
"format": ["PascalCase"]
|
||||
},
|
||||
{
|
||||
"selector": "variableLike",
|
||||
"format": ["strictCamelCase"]
|
||||
}
|
||||
],
|
||||
"react/self-closing-comp": "warn",
|
||||
"no-restricted-syntax": [
|
||||
"warn",
|
||||
{
|
||||
"selector": ":matches(PropertyDefinition)[accessibility!='private'][accessibility!='protected'][key.name!='constructor']",
|
||||
"message": "Use private instead, please implement getter or setXxx for external read and write requirements"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"extends": ["plugin:@nrwl/nx/typescript"],
|
||||
"rules": {
|
||||
"prefer-const": "warn",
|
||||
"no-console": ["warn", { "allow": ["warn", "error"] }],
|
||||
"@typescript-eslint/ban-ts-comment": "warn",
|
||||
"@typescript-eslint/no-empty-interface": "warn",
|
||||
"@typescript-eslint/no-empty-function": "warn",
|
||||
// https://github.com/nrwl/nx/issues/10445
|
||||
"react/jsx-key": "error",
|
||||
"import/no-default-export": "warn",
|
||||
"import/no-duplicates": "warn",
|
||||
"max-lines": [
|
||||
"warn",
|
||||
{ "max": 300, "skipComments": true, "skipBlankLines": true }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"extends": ["plugin:@nrwl/nx/javascript"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
20
.gitattributes
vendored
Normal file
20
.gitattributes
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
* text=auto eol=lf
|
||||
|
||||
# These files are binary and should be left untouched
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.gif binary
|
||||
*.ico binary
|
||||
*.mov binary
|
||||
*.mp4 binary
|
||||
*.mp3 binary
|
||||
*.ttf binary
|
||||
*.otf binary
|
||||
*.eot binary
|
||||
*.woff binary
|
||||
*.woff2 binary
|
||||
*.pdf binary
|
||||
*.tar.gz binary
|
||||
*.zip binary
|
||||
*.7z binary
|
||||
60
.github/CLA.md
vendored
Normal file
60
.github/CLA.md
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<!-- To indicate your agreement, simply edit this file and submit a pull request. -->
|
||||
|
||||
# AFFiNE Contributor License Agreement
|
||||
|
||||
To clarify the intellectual property license granted with contributions from any person or entity, AFFiNE must have on file a signed Contributor License Agreement ("CLA") from each contributor, indicating agreement with the license terms below. This agreement is for your protection as a contributor as well as the protection of the AFFiNE and its users; it does not change your rights to use your own contributions for any other purpose.
|
||||
|
||||
You accept and agree to the following terms and conditions for your past, present and future contributions submitted to AFFiNE. You should sign this agreement before submitting your first contribution. Except for the license granted herein to AFFiNE and recipients of software distributed by AFFiNE, You reserve all right, title, and interest in and to Your Contributions.
|
||||
|
||||
1. Parties.
|
||||
|
||||
(a) "AFFiNE" refers to the project's operator, TOEVERYTHING PTE. LTD registered in Republic of Singapore.
|
||||
|
||||
(b) "You" (or "Your") means the copyright owner or legal entity authorized by the copyright owner that is making this Agreement with AFFiNE.
|
||||
|
||||
2. Definitions. "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is intentionally submitted by You to AFFiNE for inclusion in, or documentation of, any of the products owned or managed by AFFiNE (the "Work"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to AFFiNE or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, AFFiNE for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution".
|
||||
|
||||
3. Grant of Copyright License. Subject to the terms and conditions of this Agreement, You hereby grant to AFFiNE and to recipients of software distributed by AFFiNE a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to use, copy, reproduce, prepare derivative works of, distribute, sublicense, and publicly perform and display the Contribution and such derivative works on any licensing terms, including without limitation open source licenses and binary, proprietary, or commercial licenses.
|
||||
|
||||
4. Grant of Patent License. Subject to the terms and conditions of this Agreement, You hereby grant to AFFiNE and to recipients of software distributed by AFFiNE a perpetual, irrevocable, non-exclusive, worldwide, no-charge, royalty-free patent license to make, have made, use, sell, offer to sell, import, and otherwise transfer your Contribution in whole or in part, alone or in combination with or included in any product, work or materials arising out of the project to which your contribution was submitted, and to sublicense these same rights to third parties through multiple levels of sublicensees or other licensing arrangements.
|
||||
|
||||
5. Except as set out above, You keep all right, title, and interest in your contribution. The rights that you grant to AFFiNE under these terms are effective on the date you first submitted a contribution to AFFiNE, even if your submission took place before the date you sign these terms.
|
||||
|
||||
6. You promise that:
|
||||
|
||||
- Each of Your Contributions is Your original work and that you are legally entitled to grant the above license.
|
||||
- Each of Your Contributions does not to the best of your knowledge violate any third party's copyrights, trademarks, patents, or other intellectual property rights;
|
||||
- Your Contribution submissions include complete details of any third-party license or other restriction (including, but not limited to, related patents and trademarks) of which you are personally aware and which are associated with any part of Your Contributions.
|
||||
- If You are an individual and if your employer(s) has rights to intellectual property that you create that includes your Contributions, you represent that you have received permission to make Contributions on behalf of that employer, that your employer has waived such rights for your Contributions to AFFiNE, or that your employer has executed a separate Corporate CLA with AFFiNE.
|
||||
|
||||
7. You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
8. You agree to notify AFFiNE of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect.
|
||||
|
||||
9. This Agreement will be governed by the laws of Republic of Singapore without reference to conflict of laws principles.
|
||||
|
||||
## List of Contributors
|
||||
|
||||
The below-signed are contributors to a code repository that is part of the project named "AFFiNE". Each below-signed contributor has read, understand and agrees to the terms above in the section within this document entitled "AFFiNE Contributor License Agreement" as of the date beside their real name (or entity name) and GitHub account name.
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Example:
|
||||
|
||||
- Dark Sky, @darkskygit, 2022/07/22
|
||||
-->
|
||||
|
||||
- Dark Sky, @darkskygit, 2022/07/22
|
||||
- Lin Onetwo, @linonetwo, 2022/02/14
|
||||
- zqran, @zqran, 2023/02/17
|
||||
- Alessio Gravili, @AlessioGr, 2023/03/04
|
||||
- Victor Nanka, @victornanka, 2023/03/09
|
||||
- Aditya Sharma, @adityash1, 2023/03/21
|
||||
- Fangdun Tsai, @fundon, 2023/03/21
|
||||
- Zhilin Liu, @lzlme, 2023/04/09
|
||||
- Skye Sun, @skyesun, 2023/04/14
|
||||
- Jordy Delgado, @Jdelgad8, 2023/04/17
|
||||
- Howard Do, @howarddo2208, 2023/04/20
|
||||
- 三咲智子 Kevin Deng, @sxzz, 2023/04/21
|
||||
- Moeyua, @moeyua, 2023/04/22
|
||||
48
.github/CODEOWNERS
vendored
48
.github/CODEOWNERS
vendored
@@ -1,47 +1 @@
|
||||
# About code owners
|
||||
|
||||
# You can use a CODEOWNERS file to define individuals or teams that are responsible for code in a repository.
|
||||
|
||||
# See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
|
||||
|
||||
|
||||
# =================
|
||||
# configs
|
||||
# =================
|
||||
|
||||
.* @darkskygit
|
||||
babel.config.json @darkskygit
|
||||
nx.json @darkskygit
|
||||
tsconfig.base.json @darkskygit
|
||||
**/project.json @darkskygit
|
||||
**/tsconfig.json @darkskygit
|
||||
**/tsconfig.*.json @darkskygit
|
||||
**/.babelrc @darkskygit
|
||||
**/babel.config.js @darkskygit
|
||||
**/.* @darkskygit
|
||||
|
||||
# =================
|
||||
# components
|
||||
# =================
|
||||
|
||||
# editor-core
|
||||
libs/components/editor-core @lawvs
|
||||
|
||||
# editor-blocks
|
||||
|
||||
# group block
|
||||
libs/components/editor-blocks/src/blocks/group @lawvs
|
||||
# todo block
|
||||
libs/components/editor-blocks/src/blocks/todo @lawvs
|
||||
|
||||
libs/framework/virgo @SaikaSakura
|
||||
|
||||
# =================
|
||||
# datasource
|
||||
# =================
|
||||
|
||||
# feature flags
|
||||
libs/datasource/feature-flags @lawvs
|
||||
|
||||
# jwt
|
||||
libs/datasource/jwt @darkskygit
|
||||
**/en.json @JimmFly
|
||||
|
||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
github: [toeverything]
|
||||
63
.github/ISSUE_TEMPLATE/BUG-REPORT.yml
vendored
Normal file
63
.github/ISSUE_TEMPLATE/BUG-REPORT.yml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
name: Bug Report
|
||||
description: File a bug report
|
||||
title: "\u200b"
|
||||
labels: ['bug']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen?
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of our software are you running?
|
||||
options:
|
||||
- app.affine.pro
|
||||
- stage.affine.pro
|
||||
- dev.affine.live
|
||||
- affine-preview.vercel.app
|
||||
- macOS x64
|
||||
- macOS ARM 64
|
||||
- Windows x64
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: browsers
|
||||
attributes:
|
||||
label: What browsers are you seeing the problem on?
|
||||
multiple: true
|
||||
options:
|
||||
- Chrome
|
||||
- Microsoft Edge
|
||||
- Firefox
|
||||
- Safari
|
||||
- Other
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: |
|
||||
Links? References? Anything that will give us more context about the issue you are encountering!
|
||||
Tip: You can attach images here
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Are you willing to submit a PR?
|
||||
description: >
|
||||
(Optional) We encourage you to submit a [Pull Request](https://github.com/toeverything/affine/pulls) (PR) to help improve AFFiNE for everyone, especially if you have a good understanding of how to implement a fix or feature.
|
||||
See the AFFiNE [Contributing Guide](https://github.com/toeverything/affine/blob/master/CONTRIBUTING.md) to get started.
|
||||
options:
|
||||
- label: Yes I'd like to help by submitting a PR!
|
||||
36
.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
vendored
Normal file
36
.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Feature Request
|
||||
description: Suggest a feature or improvement
|
||||
title: "\u200b"
|
||||
labels: ['feat', 'story']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this feature suggestion!
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: What would you like to see added to AFFiNE?
|
||||
placeholder: Please explain in details the feature and improvements you'd like to see.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Use case
|
||||
description: |
|
||||
How might this feature be used and who might use it.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: |
|
||||
Links? References? Anything that will give us more context about the idea you have!
|
||||
Tip: You can attach images here
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Are you willing to submit a PR?
|
||||
description: >
|
||||
(Optional) We encourage you to submit a [Pull Request](https://github.com/toeverything/affine/pulls) (PR) to help improve AFFiNE for everyone, especially if you have a good understanding of how to implement a fix or feature.
|
||||
See the AFFiNE [Contributing Guide](https://github.com/toeverything/affine/blob/master/CONTRIBUTING.md) to get started.
|
||||
options:
|
||||
- label: Yes I'd like to help by submitting a PR!
|
||||
46
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
46
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -1,46 +0,0 @@
|
||||
name: 🐛 Bug report
|
||||
description: Report a reproducible bug or regression
|
||||
title: "[bug]: "
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thanks for taking the time to fill out this bug report!
|
||||
- type: input
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
placeholder: A clear and concise description of what the bug is.
|
||||
- type: textarea
|
||||
id: reproduce
|
||||
attributes:
|
||||
label: To Reproduce
|
||||
placeholder: "Steps to reproduce the behavior\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
attributes:
|
||||
label: Screenshots
|
||||
placeholder: If applicable, add screenshots to help explain your problem.
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
placeholder: A clear and concise description of what you expected to happen.
|
||||
- type: input
|
||||
id: platform
|
||||
attributes:
|
||||
label: Platform
|
||||
placeholder: e.g. MacOS, Windows10...
|
||||
- type: input
|
||||
id: browser
|
||||
attributes:
|
||||
label: Browser
|
||||
placeholder: e.g. Chrome, Safari
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional context
|
||||
placeholder: Add any other context about the problem here.
|
||||
|
||||
17
.github/ISSUE_TEMPLATE/config.yml
vendored
17
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,11 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: 💭 Questions and Help - Reddit
|
||||
url: https://www.reddit.com/r/Affine/
|
||||
about: Please ask and answer questions here.
|
||||
- name: 💬 Questions and Help - Telegram
|
||||
url: https://t.me/affineworkos
|
||||
about: Please ask and answer questions here.
|
||||
- name: 🗯 Questions and Help - Discord
|
||||
url: https://discord.gg/yz6tGVsf5p
|
||||
about: Please ask and answer questions here.
|
||||
- name: Something else?
|
||||
url: https://github.com/toeverything/AFFiNE/discussions
|
||||
about: Feel free to ask and answer questions over in GitHub Discussions
|
||||
- name: AFFiNE Community Support
|
||||
url: https://community.affine.pro
|
||||
about: AFFiNE Community - a place to ask, learn and engage with others
|
||||
|
||||
31
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
31
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@@ -1,31 +0,0 @@
|
||||
name: ✨ Feature request
|
||||
description: An idea or request for new functionality
|
||||
title: "[feature]: "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thanks for taking the time to fill out this feature request!
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: 1~3 main use cases of the proposed feature
|
||||
description: e.g. As a ..., I have many tasks scattered across documents, and I want to have a unified entry to view these tasks.
|
||||
placeholder: e.g. As a ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Ideas for solution
|
||||
placeholder: e.g. A task view can be added to view all tasks.
|
||||
- type: input
|
||||
id: userType
|
||||
attributes:
|
||||
label: what types of users can benefit from using your proposed feature
|
||||
placeholder: busy student
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional context
|
||||
placeholder: Add any other context or screenshots about the feature request here.
|
||||
31
.github/ISSUE_TEMPLATE/improvement-request.yml
vendored
31
.github/ISSUE_TEMPLATE/improvement-request.yml
vendored
@@ -1,31 +0,0 @@
|
||||
name: 🪄 Improvement request
|
||||
description: An improvement to existing functionality
|
||||
title: "[improvement]: "
|
||||
labels: ["improvement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thanks for taking the time to fill out this improvement request!
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: 1~3 main use cases of the proposed improvement
|
||||
description: e.g. As a ..., I have many tasks scattered across documents, and I want to have a unified entry to view these tasks.
|
||||
placeholder: e.g. As a ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: solution
|
||||
attributes:
|
||||
label: Ideas for solution
|
||||
placeholder: e.g. A task view can be added to view all tasks.
|
||||
- type: input
|
||||
id: userType
|
||||
attributes:
|
||||
label: what types of users can benefit from using your proposed improvement
|
||||
placeholder: busy student
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional context
|
||||
placeholder: Add any other context or screenshots about the improvement request here.
|
||||
49
.github/actions/build-rust/action.yml
vendored
Normal file
49
.github/actions/build-rust/action.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
name: 'AFFiNE Rust build'
|
||||
description: 'Rust build setup, including cache configuration'
|
||||
inputs:
|
||||
target:
|
||||
description: 'Cargo target'
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Setup Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: stable
|
||||
targets: ${{ inputs.target }}
|
||||
|
||||
- name: Cache cargo
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
.cargo-cache
|
||||
target/${{ inputs.target }}
|
||||
key: stable-${{ inputs.target }}-cargo-cache
|
||||
|
||||
- name: Build
|
||||
if: ${{ inputs.target != 'x86_64-unknown-linux-gnu' && inputs.target != 'aarch64-unknown-linux-gnu' }}
|
||||
shell: bash
|
||||
run: yarn workspace @affine/native build --target ${{ inputs.target }}
|
||||
env:
|
||||
CARGO_BUILD_INCREMENTAL: 'false'
|
||||
|
||||
- name: Build
|
||||
if: ${{ inputs.target == 'x86_64-unknown-linux-gnu' }}
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
|
||||
options: --user 0:0 -e CARGO_BUILD_INCREMENTAL=false -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build
|
||||
run: yarn workspace @affine/native build --target ${{ inputs.target }}
|
||||
|
||||
- name: Build
|
||||
if: ${{ inputs.target == 'aarch64-unknown-linux-gnu' }}
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64
|
||||
options: --user 0:0 -e CARGO_BUILD_INCREMENTAL=false -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build
|
||||
run: yarn workspace @affine/native build --target ${{ inputs.target }}
|
||||
115
.github/actions/setup-node/action.yml
vendored
Normal file
115
.github/actions/setup-node/action.yml
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
name: 'AFFiNE Node.js Setup'
|
||||
description: 'Node.js setup for CI, including cache configuration'
|
||||
inputs:
|
||||
extra-flags:
|
||||
description: 'Extra flags to pass to the yarn install.'
|
||||
required: false
|
||||
default: '--immutable --inline-builds'
|
||||
package-install:
|
||||
description: 'Run the install step.'
|
||||
required: false
|
||||
default: 'true'
|
||||
playwright-install:
|
||||
description: 'Run the install step for Playwright.'
|
||||
required: false
|
||||
default: 'false'
|
||||
npm-token:
|
||||
description: 'The NPM token to use for private packages.'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
registry-url: https://npm.pkg.github.com
|
||||
scope: '@toeverything'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Expose yarn config as "$GITHUB_OUTPUT"
|
||||
id: yarn-config
|
||||
shell: bash
|
||||
run: |
|
||||
echo "CACHE_FOLDER=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Restore yarn cache
|
||||
uses: actions/cache@v3
|
||||
id: yarn-download-cache
|
||||
with:
|
||||
path: ${{ steps.yarn-config.outputs.CACHE_FOLDER }}
|
||||
key: yarn-download-cache-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
yarn-download-cache-
|
||||
|
||||
- name: Restore node_modules cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
|
||||
|
||||
- name: Restore yarn install state
|
||||
id: yarn-install-state-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .yarn/ci-cache/
|
||||
key: ${{ runner.os }}-yarn-install-state-cache-${{ hashFiles('yarn.lock', '.yarnrc.yml') }}
|
||||
|
||||
- name: yarn install
|
||||
if: ${{ inputs.package-install == 'true' }}
|
||||
continue-on-error: true
|
||||
shell: bash
|
||||
run: yarn install ${{ inputs.extra-flags }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ inputs.npm-token }}
|
||||
YARN_ENABLE_GLOBAL_CACHE: 'false'
|
||||
YARN_INSTALL_STATE_PATH: .yarn/ci-cache/install-state.gz
|
||||
HUSKY: '0'
|
||||
|
||||
- name: yarn install (try again)
|
||||
if: ${{ steps.install.outcome == 'failure' }}
|
||||
shell: bash
|
||||
run: yarn install ${{ inputs.extra-flags }}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ inputs.npm-token }}
|
||||
YARN_ENABLE_GLOBAL_CACHE: 'false'
|
||||
YARN_INSTALL_STATE_PATH: .yarn/ci-cache/install-state.gz
|
||||
HUSKY: '0'
|
||||
|
||||
- name: Get installed Playwright version
|
||||
id: playwright-version
|
||||
if: ${{ inputs.playwright-install == 'true' }}
|
||||
shell: bash
|
||||
run: echo "version=$(yarn why --json @playwright/test | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://')" >> $GITHUB_OUTPUT
|
||||
|
||||
# Attempt to restore the correct Playwright browser binaries based on the
|
||||
# currently installed version of Playwright (The browser binary versions
|
||||
# may change with Playwright versions).
|
||||
# Note: Playwright's cache directory is hard coded because that's what it
|
||||
# says to do in the docs. There doesn't appear to be a command that prints
|
||||
# it out for us.
|
||||
- uses: actions/cache@v3
|
||||
id: playwright-cache
|
||||
if: ${{ inputs.playwright-install == 'true' }}
|
||||
with:
|
||||
path: '~/.cache/ms-playwright'
|
||||
key: '${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.version }}'
|
||||
# As a fallback, if the Playwright version has changed, try use the
|
||||
# most recently cached version. There's a good chance that at least one
|
||||
# of the browser binary versions haven't been updated, so Playwright can
|
||||
# skip installing that in the next step.
|
||||
# Note: When falling back to an old cache, `cache-hit` (used below)
|
||||
# will be `false`. This allows us to restore the potentially out of
|
||||
# date cache, but still let Playwright decide if it needs to download
|
||||
# new binaries or not.
|
||||
restore-keys: |
|
||||
${{ runner.os }}-playwright-
|
||||
|
||||
# If the Playwright browser binaries weren't able to be restored, we tell
|
||||
# paywright to install everything for us.
|
||||
- name: Install Playwright's dependencies
|
||||
shell: bash
|
||||
if: inputs.playwright-install == 'true' && steps.playwright-cache.outputs.cache-hit != 'true'
|
||||
run: yarn playwright install --with-deps
|
||||
10
.github/auto_assign.yml
vendored
Normal file
10
.github/auto_assign.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# This is used for tracking in GitHub project.
|
||||
# See https://github.com/marketplace/actions/auto-assign-action
|
||||
|
||||
# Set to true to add reviewers to pull requests
|
||||
addReviewers: false
|
||||
|
||||
# Set to true to add assignees to pull requests
|
||||
addAssignees: author
|
||||
|
||||
runOnDraft: true
|
||||
40
.github/deployment/Caddyfile
vendored
Normal file
40
.github/deployment/Caddyfile
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
:80 {
|
||||
root /* ./dist
|
||||
|
||||
file_server {
|
||||
# precompressed br
|
||||
}
|
||||
|
||||
encode {
|
||||
zstd
|
||||
gzip 9
|
||||
}
|
||||
|
||||
header {
|
||||
# 7 days
|
||||
Cache-Control "public, max-age=86400, must-revalidate"
|
||||
}
|
||||
|
||||
handle /api/* {
|
||||
reverse_proxy {$API_SERVER} {
|
||||
health_uri /api/healthz
|
||||
@error status 500 502 503 503
|
||||
handle_response @error {
|
||||
root * /dist
|
||||
rewrite * /50x.html
|
||||
file_server
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@notStatic {
|
||||
not path /_next/static/*
|
||||
}
|
||||
|
||||
handle @notStatic {
|
||||
header {
|
||||
Cache-Control "no-cache, no-store, must-revalidate"
|
||||
}
|
||||
try_files {path} /index.html
|
||||
}
|
||||
}
|
||||
28
.github/deployment/Caddyfile-affine
vendored
28
.github/deployment/Caddyfile-affine
vendored
@@ -1,28 +0,0 @@
|
||||
:3000 {
|
||||
root /* ./dist
|
||||
|
||||
file_server {
|
||||
precompressed br
|
||||
}
|
||||
|
||||
encode {
|
||||
zstd
|
||||
gzip 9
|
||||
}
|
||||
|
||||
@notStatic {
|
||||
not path /*.css
|
||||
not path /*.js
|
||||
not path /*.png
|
||||
not path /*.jpg
|
||||
not path /*.svg
|
||||
not path /*.ttf
|
||||
not path /*.eot
|
||||
not path /*.woff
|
||||
not path /*.woff2
|
||||
}
|
||||
|
||||
handle @notStatic {
|
||||
try_files {path} /index.html
|
||||
}
|
||||
}
|
||||
39
.github/deployment/Caddyfile-lisa
vendored
39
.github/deployment/Caddyfile-lisa
vendored
@@ -1,39 +0,0 @@
|
||||
:80 {
|
||||
reverse_proxy /api/* keck:3001
|
||||
@websockets {
|
||||
path /collaboration/*
|
||||
}
|
||||
reverse_proxy @websockets keck:3000
|
||||
reverse_proxy /* lisa:3001 {
|
||||
header_up Host lisa:3001
|
||||
}
|
||||
}
|
||||
|
||||
http://lisa:3001 {
|
||||
root /* ./dist
|
||||
|
||||
file_server {
|
||||
precompressed br
|
||||
}
|
||||
|
||||
encode {
|
||||
zstd
|
||||
gzip 9
|
||||
}
|
||||
|
||||
@notStatic {
|
||||
not path /*.css
|
||||
not path /*.js
|
||||
not path /*.png
|
||||
not path /*.jpg
|
||||
not path /*.svg
|
||||
not path /*.ttf
|
||||
not path /*.eot
|
||||
not path /*.woff
|
||||
not path /*.woff2
|
||||
}
|
||||
|
||||
handle @notStatic {
|
||||
try_files {path} /index.html
|
||||
}
|
||||
}
|
||||
28
.github/deployment/Caddyfile-venus
vendored
28
.github/deployment/Caddyfile-venus
vendored
@@ -1,28 +0,0 @@
|
||||
:80 {
|
||||
root /* ./dist
|
||||
|
||||
file_server {
|
||||
precompressed br
|
||||
}
|
||||
|
||||
encode {
|
||||
zstd
|
||||
gzip 9
|
||||
}
|
||||
|
||||
@notStatic {
|
||||
not path /*.css
|
||||
not path /*.js
|
||||
not path /*.png
|
||||
not path /*.jpg
|
||||
not path /*.svg
|
||||
not path /*.ttf
|
||||
not path /*.eot
|
||||
not path /*.woff
|
||||
not path /*.woff2
|
||||
}
|
||||
|
||||
handle @notStatic {
|
||||
try_files {path} /index.html
|
||||
}
|
||||
}
|
||||
13
.github/deployment/Dockerfile
vendored
Normal file
13
.github/deployment/Dockerfile
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM node:16-alpine as relocate
|
||||
WORKDIR /app
|
||||
COPY ./apps/web/out ./dist
|
||||
COPY ./.github/deployment/Caddyfile ./Caddyfile
|
||||
|
||||
FROM caddy:2.6.2-alpine
|
||||
ARG API_SERVER
|
||||
WORKDIR /app
|
||||
COPY --from=relocate /app .
|
||||
|
||||
EXPOSE 80
|
||||
ENV API_SERVER=$API_SERVER
|
||||
CMD ["caddy", "run"]
|
||||
21
.github/deployment/Dockerfile-affine
vendored
21
.github/deployment/Dockerfile-affine
vendored
@@ -1,21 +0,0 @@
|
||||
FROM node:16-alpine as builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN apk add g++ make python3 git libpng-dev
|
||||
RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store && pnpm run build:local
|
||||
|
||||
FROM node:16-alpine as relocate
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/dist/apps/ligo-virgo ./dist
|
||||
COPY --from=builder /app/.github/deployment/Caddyfile-affine ./Caddyfile
|
||||
RUN rm ./dist/*.txt
|
||||
|
||||
# =============
|
||||
# AFFiNE image
|
||||
# =============
|
||||
FROM caddy:2.4.6-alpine as AFFiNE
|
||||
WORKDIR /app
|
||||
COPY --from=relocate /app .
|
||||
|
||||
EXPOSE 3000
|
||||
CMD ["caddy", "run"]
|
||||
33
.github/deployment/Dockerfile-keck
vendored
33
.github/deployment/Dockerfile-keck
vendored
@@ -1,33 +0,0 @@
|
||||
FROM node:16-alpine as builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN apk add g++ make python3 git libpng-dev
|
||||
RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store && pnpm run build:keck
|
||||
|
||||
FROM node:16-alpine as node_modules
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/dist/apps/keck .
|
||||
COPY --from=builder /app/apps/keck/package.prod.json ./package.json
|
||||
RUN npm i
|
||||
|
||||
# =============
|
||||
# keck image
|
||||
# =============
|
||||
FROM node:16-alpine as keck
|
||||
WORKDIR /app
|
||||
COPY --from=node_modules /app .
|
||||
|
||||
ENV FIREBASE_ACCOUNT=
|
||||
ENV FIREBASE_CERT=
|
||||
ENV FIREBASE_PROJECT=
|
||||
ENV HOST=0.0.0.0
|
||||
ENV PORT=3000
|
||||
|
||||
# coding
|
||||
ENV TZ 'Asia/Shanghai'
|
||||
ENV LANG en_US.UTF-8
|
||||
ENV LANGUAGE en_US:en
|
||||
ENV LC_ALL en_US.UTF-8
|
||||
|
||||
EXPOSE 3000
|
||||
CMD ["node", "main.js"]
|
||||
21
.github/deployment/Dockerfile-lisa
vendored
21
.github/deployment/Dockerfile-lisa
vendored
@@ -1,21 +0,0 @@
|
||||
FROM node:16-alpine as builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN apk add g++ make python3 git libpng-dev
|
||||
RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store && pnpm run build
|
||||
|
||||
FROM node:16-alpine as relocate
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/dist/apps/ligo-virgo ./dist
|
||||
COPY --from=builder /app/.github/deployment/Caddyfile-lisa ./Caddyfile
|
||||
RUN rm ./dist/*.txt
|
||||
|
||||
# =============
|
||||
# lisa image
|
||||
# =============
|
||||
FROM caddy:2.4.6-alpine as lisa
|
||||
WORKDIR /app
|
||||
COPY --from=relocate /app .
|
||||
|
||||
EXPOSE 3000
|
||||
CMD ["caddy", "run"]
|
||||
21
.github/deployment/Dockerfile-venus
vendored
21
.github/deployment/Dockerfile-venus
vendored
@@ -1,21 +0,0 @@
|
||||
FROM node:16-alpine as builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN apk add g++ make python3 git libpng-dev
|
||||
RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store && pnpm run build:venus
|
||||
|
||||
FROM node:16-alpine as relocate
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/dist/apps/venus ./dist
|
||||
COPY --from=builder /app/.github/deployment/Caddyfile-venus ./Caddyfile
|
||||
RUN rm ./dist/*.txt
|
||||
|
||||
# =============
|
||||
# venus image
|
||||
# =============
|
||||
FROM caddy:2.4.6-alpine as venus
|
||||
WORKDIR /app
|
||||
COPY --from=relocate /app .
|
||||
|
||||
EXPOSE 80
|
||||
CMD ["caddy", "run"]
|
||||
44
.github/labeler.yml
vendored
Normal file
44
.github/labeler.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
docs:
|
||||
- 'docs/**/*'
|
||||
- '**/README.md'
|
||||
- 'packages/templates/**/*'
|
||||
|
||||
test:
|
||||
- 'tests/**/*'
|
||||
- '**/tests/**/*'
|
||||
- '**/__tests__/**/*'
|
||||
|
||||
mod:dev:
|
||||
- 'scripts/**/*'
|
||||
- 'packages/cli/**/*'
|
||||
- 'packages/debug/**/*'
|
||||
|
||||
mod:workspace: 'packages/workspace/**/*'
|
||||
|
||||
mod:i18n: 'packages/i18n/**/*'
|
||||
|
||||
mod:env: 'packages/env/**/*'
|
||||
|
||||
mod:hooks: 'packages/hooks/**/*'
|
||||
|
||||
mod:component: 'packages/component/**/*'
|
||||
|
||||
mod:store:
|
||||
- 'packages/jotai/**/*'
|
||||
- '**/atoms/**/*'
|
||||
|
||||
rust:
|
||||
- '**/*.rs'
|
||||
- '**/Cargo.toml'
|
||||
- '**/Cargo.lock'
|
||||
- '**/rust-toolchain'
|
||||
- '**/rust-toolchain.toml'
|
||||
- '**/rustfmt.toml'
|
||||
|
||||
package:y-indexeddb: 'packages/y-indexeddb/**/*'
|
||||
|
||||
app:web: 'apps/web/**/*'
|
||||
|
||||
app:electron: 'apps/electron/**/*'
|
||||
|
||||
app:server: 'apps/server/**/*'
|
||||
24
.github/workflows/add-to-project.yml
vendored
Normal file
24
.github/workflows/add-to-project.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Add to GitHub projects
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
|
||||
jobs:
|
||||
add-to-project:
|
||||
name: Add issues and pull requests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/add-to-project@v0.4.0
|
||||
with:
|
||||
# You can target a repository in a different organization
|
||||
# to the issue
|
||||
project-url: https://github.com/orgs/toeverything/projects/10
|
||||
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
|
||||
# labeled: bug, needs-triage
|
||||
# label-operator: OR
|
||||
57
.github/workflows/affine.yml
vendored
57
.github/workflows/affine.yml
vendored
@@ -1,57 +0,0 @@
|
||||
name: Build AFFiNE-Local
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
# Cancels all previous workflow runs for pull requests that have not completed.
|
||||
# See https://docs.github.com/en/actions/using-jobs/using-concurrency
|
||||
concurrency:
|
||||
# The concurrency group contains the workflow name and the branch name for
|
||||
# pull requests or the commit hash for any other events.
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
NAMESPACE: toeverything
|
||||
AFFINE_IMAGE_NAME: AFFiNE
|
||||
IMAGE_TAG_LATEST: nightly-latest
|
||||
|
||||
jobs:
|
||||
ligo-virgo:
|
||||
runs-on: self-hosted
|
||||
environment: development
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker (AFFiNE-Local)
|
||||
id: meta_affine
|
||||
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.AFFINE_IMAGE_NAME }}
|
||||
tags: ${{ env.IMAGE_TAG_LATEST }}
|
||||
|
||||
- name: Build and push Docker image (AFFINE-Local)
|
||||
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
|
||||
with:
|
||||
context: .
|
||||
file: ./.github/deployment/Dockerfile-affine
|
||||
push: ${{ github.ref == 'refs/heads/master' && true || false }}
|
||||
tags: ${{ steps.meta_affine.outputs.tags }}
|
||||
labels: ${{ steps.meta_affine.outputs.labels }}
|
||||
target: AFFiNE
|
||||
12
.github/workflows/auto-labeler.yml
vendored
Normal file
12
.github/workflows/auto-labeler.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
name: 'Pull Request Labeler'
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v4
|
||||
405
.github/workflows/build.yml
vendored
Normal file
405
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,405 @@
|
||||
name: Build & Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- v[0-9]+.[0-9]+.x-staging
|
||||
- v[0-9]+.[0-9]+.x
|
||||
paths-ignore:
|
||||
- README.md
|
||||
- .github/**
|
||||
- '!.github/workflows/build.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- v[0-9]+.[0-9]+.x-staging
|
||||
- v[0-9]+.[0-9]+.x
|
||||
paths-ignore:
|
||||
- README.md
|
||||
- .github/**
|
||||
- '!.github/workflows/build.yml'
|
||||
|
||||
env:
|
||||
DEBUG: napi:*
|
||||
APP_NAME: affine
|
||||
MACOSX_DEPLOYMENT_TARGET: '10.13'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
environment: development
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
- run: yarn lint --max-warnings=0
|
||||
|
||||
build-storybook:
|
||||
name: Build Storybook
|
||||
runs-on: ubuntu-latest
|
||||
environment: development
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
- run: yarn build:storybook
|
||||
- name: Upload storybook artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: storybook
|
||||
path: ./packages/component/storybook-static
|
||||
if-no-files-found: error
|
||||
|
||||
build:
|
||||
name: Build @affine/web
|
||||
runs-on: ubuntu-latest
|
||||
environment: development
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
- name: Cache Next.js
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/apps/web/.next/cache
|
||||
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-nextjs-${{ hashFiles('**/yarn.lock') }}-
|
||||
- name: Build
|
||||
run: yarn build
|
||||
env:
|
||||
NEXT_PUBLIC_FIREBASE_API_KEY: ${{ secrets.NEXT_PUBLIC_FIREBASE_API_KEY }}
|
||||
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: ${{ secrets.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN }}
|
||||
NEXT_PUBLIC_FIREBASE_PROJECT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_PROJECT_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: ${{ secrets.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET }}
|
||||
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_APP_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_APP_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID }}
|
||||
API_SERVER_PROFILE: local
|
||||
ENABLE_DEBUG_PAGE: true
|
||||
ENABLE_LEGACY_PROVIDER: true
|
||||
COVERAGE: true
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: next-js
|
||||
path: ./apps/web/.next
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Build @affine/web for desktop
|
||||
run: yarn build
|
||||
env:
|
||||
NEXT_PUBLIC_FIREBASE_API_KEY: ${{ secrets.NEXT_PUBLIC_FIREBASE_API_KEY }}
|
||||
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: ${{ secrets.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN }}
|
||||
NEXT_PUBLIC_FIREBASE_PROJECT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_PROJECT_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: ${{ secrets.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET }}
|
||||
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_APP_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_APP_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID }}
|
||||
API_SERVER_PROFILE: affine
|
||||
ENABLE_DEBUG_PAGE: true
|
||||
ENABLE_LEGACY_PROVIDER: false
|
||||
COVERAGE: true
|
||||
|
||||
- name: Export static resources
|
||||
run: yarn export
|
||||
working-directory: apps/web
|
||||
|
||||
- name: Upload static resources artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: next-js-static
|
||||
path: ./apps/web/out
|
||||
if-no-files-found: error
|
||||
|
||||
server-test:
|
||||
name: Server Test
|
||||
runs-on: ubuntu-latest
|
||||
environment: development
|
||||
services:
|
||||
postgres:
|
||||
image: postgres
|
||||
env:
|
||||
POSTGRES_PASSWORD: affine
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
ports:
|
||||
- 5432:5432
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
- name: Initialize database
|
||||
run: |
|
||||
psql -h localhost -U postgres -c "CREATE DATABASE affine;"
|
||||
psql -h localhost -U postgres -c "CREATE USER affine WITH PASSWORD 'affine';"
|
||||
psql -h localhost -U postgres -c "ALTER USER affine WITH SUPERUSER;"
|
||||
env:
|
||||
PGPASSWORD: affine
|
||||
- name: Generate prisma client
|
||||
run: |
|
||||
yarn exec prisma generate
|
||||
yarn exec prisma db push
|
||||
working-directory: apps/server
|
||||
env:
|
||||
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
|
||||
- name: Run init-db script
|
||||
run: yarn exec ts-node-esm ./scripts/init-db.ts
|
||||
working-directory: apps/server
|
||||
env:
|
||||
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
|
||||
- name: Run server tests
|
||||
run: yarn test:coverage
|
||||
working-directory: apps/server
|
||||
env:
|
||||
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
|
||||
- name: Upload server test coverage results
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./apps/server/.coverage/lcov.info
|
||||
flags: server-test
|
||||
name: affine
|
||||
fail_ci_if_error: true
|
||||
|
||||
storybook-test:
|
||||
name: Storybook Test
|
||||
runs-on: ubuntu-latest
|
||||
environment: development
|
||||
needs: [build-storybook]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
with:
|
||||
playwright-install: true
|
||||
- name: Download storybook artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: storybook
|
||||
path: ./packages/component/storybook-static
|
||||
- name: Run storybook tests
|
||||
working-directory: ./packages/component
|
||||
run: |
|
||||
yarn exec concurrently -k -s first -n "SB,TEST" -c "magenta,blue" "yarn exec serve ./storybook-static -l 6006" "yarn exec wait-on tcp:6006 && yarn test-storybook --coverage"
|
||||
- name: Upload storybook test coverage results
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/component/coverage/storybook/coverage-storybook.json
|
||||
flags: storybook-test
|
||||
name: affine
|
||||
fail_ci_if_error: true
|
||||
|
||||
e2e-test:
|
||||
name: E2E Test
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
shard: [1, 2, 3, 4]
|
||||
environment: development
|
||||
needs: [build, build-storybook]
|
||||
services:
|
||||
octobase:
|
||||
image: ghcr.io/toeverything/cloud-self-hosted:nightly-latest
|
||||
ports:
|
||||
- 3000:3000
|
||||
env:
|
||||
SIGN_KEY: 'test123'
|
||||
RUST_LOG: 'debug'
|
||||
JWST_DEV: '1'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
with:
|
||||
playwright-install: true
|
||||
- name: Download artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: next-js
|
||||
path: ./apps/web/.next
|
||||
|
||||
- name: Download storybook artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: storybook
|
||||
path: ./packages/component/storybook-static
|
||||
|
||||
- name: Wait for Octobase Ready
|
||||
run: |
|
||||
node ./scripts/wait-3000-healthz.mjs
|
||||
|
||||
- name: Run playwright tests
|
||||
run: yarn test --forbid-only --shard=${{ matrix.shard }}/${{ strategy.job-total }}
|
||||
env:
|
||||
COVERAGE: true
|
||||
|
||||
- name: Collect code coverage report
|
||||
run: yarn exec nyc report -t .nyc_output --report-dir .coverage --reporter=lcov
|
||||
|
||||
- name: Upload e2e test coverage results
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./.coverage/lcov.info
|
||||
flags: e2etest
|
||||
name: affine
|
||||
fail_ci_if_error: true
|
||||
|
||||
- name: Upload test results
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: test-results-e2e-${{ matrix.shard }}
|
||||
path: ./test-results
|
||||
if-no-files-found: ignore
|
||||
|
||||
dekstop-test:
|
||||
name: Desktop Test
|
||||
runs-on: ${{ matrix.spec.os }}
|
||||
environment: development
|
||||
strategy:
|
||||
fail-fast: false
|
||||
# all combinations: macos-latest x64, macos-latest arm64, windows-latest x64, ubuntu-latest x64
|
||||
matrix:
|
||||
spec:
|
||||
- {
|
||||
os: macos-latest,
|
||||
platform: macos,
|
||||
arch: x64,
|
||||
target: x86_64-apple-darwin,
|
||||
test: true,
|
||||
}
|
||||
- {
|
||||
os: macos-latest,
|
||||
platform: macos,
|
||||
arch: arm64,
|
||||
target: aarch64-apple-darwin,
|
||||
test: false,
|
||||
}
|
||||
- {
|
||||
os: ubuntu-latest,
|
||||
platform: linux,
|
||||
arch: x64,
|
||||
target: x86_64-unknown-linux-gnu,
|
||||
test: true,
|
||||
}
|
||||
- {
|
||||
os: windows-latest,
|
||||
platform: windows,
|
||||
arch: x64,
|
||||
target: x86_64-pc-windows-msvc,
|
||||
test: true,
|
||||
}
|
||||
needs: [build]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
with:
|
||||
playwright-install: true
|
||||
- name: Build AFFiNE native
|
||||
uses: ./.github/actions/build-rust
|
||||
with:
|
||||
target: ${{ matrix.spec.target }}
|
||||
- name: Run unit tests
|
||||
if: ${{ matrix.spec.test }}
|
||||
shell: bash
|
||||
run: |
|
||||
rm -rf apps/electron/node_modules/better-sqlite3/build
|
||||
yarn --cwd apps/electron/node_modules/better-sqlite3 run install
|
||||
yarn test:unit
|
||||
env:
|
||||
NATIVE_TEST: 'true'
|
||||
- name: Build layers
|
||||
run: yarn workspace @affine/electron build-layers
|
||||
|
||||
- name: Download static resource artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: next-js-static
|
||||
path: ./apps/electron/resources/web-static
|
||||
|
||||
- name: Rebuild Electron dependences
|
||||
shell: bash
|
||||
run: |
|
||||
rm -rf apps/electron/node_modules/better-sqlite3/build
|
||||
yarn workspace @affine/electron rebuild:for-electron --arch=${{ matrix.spec.arch }}
|
||||
|
||||
- name: Run desktop tests
|
||||
if: ${{ matrix.spec.test && matrix.spec.os == 'ubuntu-latest' }}
|
||||
run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn workspace @affine/electron test
|
||||
env:
|
||||
COVERAGE: true
|
||||
|
||||
- name: Run desktop tests
|
||||
if: ${{ matrix.spec.test && matrix.spec.os != 'ubuntu-latest' }}
|
||||
run: yarn workspace @affine/electron test
|
||||
env:
|
||||
COVERAGE: true
|
||||
|
||||
- name: Collect code coverage report
|
||||
if: ${{ matrix.spec.test }}
|
||||
run: yarn exec nyc report -t .nyc_output --report-dir .coverage --reporter=lcov
|
||||
|
||||
- name: Upload e2e test coverage results
|
||||
if: ${{ matrix.spec.test }}
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./.coverage/lcov.info
|
||||
flags: e2etest-${{ matrix.spec.os }}-${{ matrix.spec.arch }}
|
||||
name: affine
|
||||
fail_ci_if_error: true
|
||||
|
||||
- name: Upload test results
|
||||
if: ${{ failure() }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: test-results-e2e-${{ matrix.spec.os }}-${{ matrix.spec.arch }}
|
||||
path: ./test-results
|
||||
if-no-files-found: ignore
|
||||
|
||||
unit-test:
|
||||
name: Unit Test
|
||||
runs-on: ubuntu-latest
|
||||
environment: development
|
||||
services:
|
||||
octobase:
|
||||
image: ghcr.io/toeverything/cloud-self-hosted:nightly-latest
|
||||
ports:
|
||||
- 3000:3000
|
||||
env:
|
||||
SIGN_KEY: 'test123'
|
||||
RUST_LOG: 'debug'
|
||||
JWST_DEV: '1'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
|
||||
- name: Unit Test
|
||||
run: yarn run test:unit:coverage
|
||||
|
||||
- name: Upload unit test coverage results
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./.coverage/store/lcov.info
|
||||
flags: unittest
|
||||
name: affine
|
||||
fail_ci_if_error: true
|
||||
36
.github/workflows/cache-cleanup.yml
vendored
Normal file
36
.github/workflows/cache-cleanup.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries
|
||||
name: Cleanup caches for closed branches
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
|
||||
REPO=${{ github.repository }}
|
||||
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
|
||||
|
||||
echo "Fetching list of cache key"
|
||||
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
|
||||
|
||||
## Setting this to not fail the workflow while deleting cache keys.
|
||||
set +e
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeysForPR
|
||||
do
|
||||
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
||||
done
|
||||
echo "Done"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
69
.github/workflows/codeql.yml
vendored
Normal file
69
.github/workflows/codeql.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: 'CodeQL'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ['javascript']
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
69
.github/workflows/keck.yml
vendored
69
.github/workflows/keck.yml
vendored
@@ -1,69 +0,0 @@
|
||||
name: Build Keck
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'apps/keck/**'
|
||||
- '.github/deployment'
|
||||
- '.github/workflows/keck.yml'
|
||||
pull_request:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'apps/keck/**'
|
||||
- '.github/deployment'
|
||||
- '.github/workflows/keck.yml'
|
||||
|
||||
# Cancels all previous workflow runs for pull requests that have not completed.
|
||||
# See https://docs.github.com/en/actions/using-jobs/using-concurrency
|
||||
concurrency:
|
||||
# The concurrency group contains the workflow name and the branch name for
|
||||
# pull requests or the commit hash for any other events.
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
NAMESPACE: toeverything
|
||||
KECK_IMAGE_NAME: keck
|
||||
IMAGE_TAG: canary-${{ github.sha }}
|
||||
IMAGE_TAG_LATEST: nightly-latest
|
||||
|
||||
jobs:
|
||||
ligo-virgo:
|
||||
runs-on: self-hosted
|
||||
environment: development
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker (keck)
|
||||
id: meta_keck
|
||||
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.KECK_IMAGE_NAME }}
|
||||
tags: |
|
||||
${{ env.IMAGE_TAG }}
|
||||
${{ env.IMAGE_TAG_LATEST }}
|
||||
|
||||
- name: Build and push Docker image (keck)
|
||||
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
|
||||
with:
|
||||
context: .
|
||||
file: ./.github/deployment/Dockerfile-keck
|
||||
push: ${{ github.ref == 'refs/heads/field' && true || false }}
|
||||
tags: ${{ steps.meta_keck.outputs.tags }}
|
||||
labels: ${{ steps.meta_keck.outputs.labels }}
|
||||
target: keck
|
||||
19
.github/workflows/label-checker.yml
vendored
Normal file
19
.github/workflows/label-checker.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Label Checker
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- labeled
|
||||
- unlabeled
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
check_labels:
|
||||
name: PR should not have a blocked label
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: docker://agilepathway/pull-request-label-checker:latest
|
||||
with:
|
||||
none_of: blocked
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
43
.github/workflows/languages-sync.yml
vendored
Normal file
43
.github/workflows/languages-sync.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
name: Languages Sync
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ['master']
|
||||
paths:
|
||||
- 'packages/i18n/**'
|
||||
- '.github/workflows/languages-sync.yml'
|
||||
pull_request_target:
|
||||
branches: ['master']
|
||||
paths:
|
||||
- 'packages/i18n/**'
|
||||
- '.github/workflows/languages-sync.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
# Cancels all previous workflow runs for pull requests that have not completed.
|
||||
# See https://docs.github.com/en/actions/using-jobs/using-concurrency
|
||||
concurrency:
|
||||
# The concurrency group contains the workflow name and the branch name for
|
||||
# pull requests or the commit hash for any other events.
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
- name: Check Language Key
|
||||
if: github.ref != 'refs/heads/master'
|
||||
working-directory: ./packages/i18n
|
||||
run: yarn run sync-languages:check
|
||||
env:
|
||||
TOLGEE_API_KEY: ${{ secrets.TOLGEE_API_KEY }}
|
||||
|
||||
- name: Sync Languages
|
||||
if: github.ref == 'refs/heads/master'
|
||||
working-directory: ./packages/i18n
|
||||
run: yarn run sync-languages
|
||||
env:
|
||||
TOLGEE_API_KEY: ${{ secrets.TOLGEE_API_KEY }}
|
||||
62
.github/workflows/lint.yml
vendored
62
.github/workflows/lint.yml
vendored
@@ -1,62 +0,0 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
# Cancels all previous workflow runs for pull requests that have not completed.
|
||||
# See https://docs.github.com/en/actions/using-jobs/using-concurrency
|
||||
concurrency:
|
||||
# The concurrency group contains the workflow name and the branch name for
|
||||
# pull requests or the commit hash for any other events.
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
main:
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16]
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
# TODO Remove the next line after cleaning all errors
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Use pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 7
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
# https://github.com/actions/setup-node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install node modules
|
||||
run: pnpm install
|
||||
|
||||
- name: Lint
|
||||
if: always()
|
||||
run: pnpm run lint:with-cache
|
||||
|
||||
# - name: Check
|
||||
# if: always()
|
||||
# run: pnpm run check
|
||||
|
||||
# - name: Format Check
|
||||
# if: always()
|
||||
# run: pnpm run format:ci
|
||||
|
||||
# - name: Build
|
||||
# run: pnpm run build
|
||||
|
||||
# - name: Test
|
||||
# run: pnpm run test
|
||||
60
.github/workflows/lisa.yml
vendored
60
.github/workflows/lisa.yml
vendored
@@ -1,60 +0,0 @@
|
||||
name: Build Lisa
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
# Cancels all previous workflow runs for pull requests that have not completed.
|
||||
# See https://docs.github.com/en/actions/using-jobs/using-concurrency
|
||||
concurrency:
|
||||
# The concurrency group contains the workflow name and the branch name for
|
||||
# pull requests or the commit hash for any other events.
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
NAMESPACE: toeverything
|
||||
LISA_IMAGE_NAME: lisa
|
||||
IMAGE_TAG: canary-${{ github.sha }}
|
||||
IMAGE_TAG_LATEST: nightly-latest
|
||||
|
||||
jobs:
|
||||
ligo-virgo:
|
||||
runs-on: self-hosted
|
||||
environment: development
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker (lisa)
|
||||
id: meta_lisa
|
||||
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.LISA_IMAGE_NAME }}
|
||||
tags: |
|
||||
${{ env.IMAGE_TAG }}
|
||||
${{ env.IMAGE_TAG_LATEST }}
|
||||
|
||||
- name: Build and push Docker image (lisa)
|
||||
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
|
||||
with:
|
||||
context: .
|
||||
file: ./.github/deployment/Dockerfile-lisa
|
||||
push: ${{ github.ref == 'refs/heads/master' && true || false }}
|
||||
tags: ${{ steps.meta_lisa.outputs.tags }}
|
||||
labels: ${{ steps.meta_lisa.outputs.labels }}
|
||||
target: lisa
|
||||
231
.github/workflows/nightly-build.yml
vendored
Normal file
231
.github/workflows/nightly-build.yml
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
name: Build Canary Desktop App on Staging Branch
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- v[0-9]+.[0-9]+.x-staging
|
||||
paths-ignore:
|
||||
- README.md
|
||||
- .github/**
|
||||
- '!.github/workflows/nightly-build.yml'
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
contents: write
|
||||
security-events: write
|
||||
|
||||
concurrency:
|
||||
# The concurrency group contains the workflow name and the branch name for
|
||||
# pull requests or the commit hash for any other events.
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
BUILD_TYPE: internal
|
||||
|
||||
jobs:
|
||||
set-build-version:
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
outputs:
|
||||
version: 0.0.0-${{ steps.version.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: toeverything/set-build-version@latest
|
||||
- id: version
|
||||
run: echo ::set-output name=version::${{ env.BUILD_VERSION }}
|
||||
|
||||
before-make:
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
needs:
|
||||
- set-build-version
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
- name: Replace Version
|
||||
run: ./scripts/set-version.sh ${{ needs.set-build-version.outputs.version }}
|
||||
- name: generate-assets
|
||||
working-directory: apps/electron
|
||||
run: yarn generate-assets
|
||||
env:
|
||||
NEXT_PUBLIC_FIREBASE_API_KEY: ${{ secrets.NEXT_PUBLIC_FIREBASE_API_KEY }}
|
||||
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: ${{ secrets.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN }}
|
||||
NEXT_PUBLIC_FIREBASE_PROJECT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_PROJECT_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: ${{ secrets.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET }}
|
||||
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_APP_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_APP_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID }}
|
||||
AFFINE_GOOGLE_CLIENT_ID: ${{ secrets.AFFINE_GOOGLE_CLIENT_ID }}
|
||||
AFFINE_GOOGLE_CLIENT_SECRET: ${{ secrets.AFFINE_GOOGLE_CLIENT_SECRET }}
|
||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||
NEXT_PUBLIC_SENTRY_DSN: ${{ secrets.NEXT_PUBLIC_SENTRY_DSN }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
API_SERVER_PROFILE: prod
|
||||
ENABLE_TEST_PROPERTIES: false
|
||||
ENABLE_IMAGE_PREVIEW_MODAL: false
|
||||
|
||||
- name: Upload Artifact (web-static)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: before-make-web-static
|
||||
path: apps/electron/resources/web-static
|
||||
|
||||
make-distribution:
|
||||
environment: production
|
||||
strategy:
|
||||
# all combinations: macos-latest x64, macos-latest arm64, windows-latest x64, ubuntu-latest x64
|
||||
matrix:
|
||||
spec:
|
||||
- {
|
||||
os: macos-latest,
|
||||
platform: darwin,
|
||||
arch: x64,
|
||||
target: x86_64-apple-darwin,
|
||||
}
|
||||
- {
|
||||
os: macos-latest,
|
||||
platform: darwin,
|
||||
arch: arm64,
|
||||
target: aarch64-apple-darwin,
|
||||
}
|
||||
- {
|
||||
os: ubuntu-latest,
|
||||
platform: linux,
|
||||
arch: x64,
|
||||
target: x86_64-unknown-linux-gnu,
|
||||
}
|
||||
- {
|
||||
os: windows-latest,
|
||||
platform: win32,
|
||||
arch: x64,
|
||||
target: x86_64-pc-windows-msvc,
|
||||
}
|
||||
runs-on: ${{ matrix.spec.os }}
|
||||
needs:
|
||||
- before-make
|
||||
- set-build-version
|
||||
env:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
SKIP_GENERATE_ASSETS: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
- name: Build AFFiNE native
|
||||
uses: ./.github/actions/build-rust
|
||||
with:
|
||||
target: ${{ matrix.spec.target }}
|
||||
- name: Replace Version
|
||||
run: ./scripts/set-version.sh ${{ needs.set-build-version.outputs.version }}
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: before-make-web-static
|
||||
path: apps/electron/resources/web-static
|
||||
- name: Rebuild Electron dependences
|
||||
shell: bash
|
||||
run: |
|
||||
rm -rf apps/electron/node_modules/better-sqlite3/build
|
||||
yarn workspace @affine/electron rebuild:for-electron --arch=${{ matrix.spec.arch }}
|
||||
|
||||
- name: Build layers
|
||||
run: yarn workspace @affine/electron build-layers
|
||||
|
||||
- name: Signing By Apple Developer ID
|
||||
if: ${{ matrix.spec.platform == 'darwin' }}
|
||||
uses: apple-actions/import-codesign-certs@v2
|
||||
with:
|
||||
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
|
||||
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
|
||||
|
||||
- name: make
|
||||
run: yarn workspace @affine/electron make --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
|
||||
|
||||
- name: Save artifacts (mac)
|
||||
if: ${{ matrix.spec.platform == 'darwin' }}
|
||||
run: |
|
||||
mkdir -p builds
|
||||
mv apps/electron/out/*/make/*.dmg ./builds/affine-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.dmg
|
||||
mv apps/electron/out/*/make/zip/darwin/${{ matrix.spec.arch }}/*.zip ./builds/affine-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.zip
|
||||
- name: Save artifacts (windows)
|
||||
if: ${{ matrix.spec.platform == 'win32' }}
|
||||
run: |
|
||||
mkdir -p builds
|
||||
mv apps/electron/out/*/make/zip/win32/x64/AFFiNE*-win32-x64-*.zip ./builds/affine-${{ env.BUILD_TYPE }}-windows-x64.zip
|
||||
mv apps/electron/out/*/make/squirrel.windows/x64/*.exe ./builds/affine-${{ env.BUILD_TYPE }}-windows-x64.exe
|
||||
mv apps/electron/out/*/make/squirrel.windows/x64/*.msi ./builds/affine-${{ env.BUILD_TYPE }}-windows-x64.msi
|
||||
mv apps/electron/out/*/make/squirrel.windows/x64/*.nupkg ./builds/affine-${{ env.BUILD_TYPE }}-windows-x64.nupkg
|
||||
|
||||
- name: Save artifacts (linux)
|
||||
if: ${{ matrix.spec.platform == 'linux' }}
|
||||
run: |
|
||||
mkdir -p builds
|
||||
mv apps/electron/out/*/make/zip/linux/x64/*.zip ./builds/affine-${{ env.BUILD_TYPE }}-linux-x64.zip
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: affine-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}-builds
|
||||
path: builds
|
||||
|
||||
release:
|
||||
needs:
|
||||
- make-distribution
|
||||
- set-build-version
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Download Artifacts (macos-x64)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: affine-darwin-x64-builds
|
||||
path: ./
|
||||
- name: Download Artifacts (macos-arm64)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: affine-darwin-arm64-builds
|
||||
path: ./
|
||||
- name: Download Artifacts (windows-x64)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: affine-win32-x64-builds
|
||||
path: ./
|
||||
- name: Download Artifacts (linux-x64)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: affine-linux-x64-builds
|
||||
path: ./
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Generate Release yml
|
||||
run: |
|
||||
cp ./apps/electron/scripts/generate-yml.js .
|
||||
node generate-yml.js
|
||||
env:
|
||||
RELEASE_VERSION: ${{ needs.set-build-version.outputs.version }}
|
||||
- name: Create Release Draft
|
||||
uses: softprops/action-gh-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
with:
|
||||
repository: 'toeverything/AFFiNE-Releases'
|
||||
name: ${{ needs.set-build-version.outputs.version }}
|
||||
tag_name: ${{ needs.set-build-version.outputs.version }}
|
||||
prerelease: true
|
||||
files: |
|
||||
./VERSION
|
||||
./*.zip
|
||||
./*.dmg
|
||||
./*.exe
|
||||
./*.nupkg
|
||||
./RELEASES
|
||||
./*.AppImage
|
||||
./*.apk
|
||||
./*.yml
|
||||
12
.github/workflows/pr-auto-assign.yml
vendored
Normal file
12
.github/workflows/pr-auto-assign.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
name: Pull request auto assign
|
||||
|
||||
# on: pull_request
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
add-reviews:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: kentaro-m/auto-assign-action@v1.2.4
|
||||
23
.github/workflows/pr-title-lint.yml
vendored
Normal file
23
.github/workflows/pr-title-lint.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: PR Title Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
branches:
|
||||
- master
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-pull-request-title:
|
||||
name: Check pull request title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
- run: echo "${{ github.event.pull_request.title }}" | npx commitlint -g ./.commitlintrc.json
|
||||
226
.github/workflows/release-desktop-app.yml
vendored
Normal file
226
.github/workflows/release-desktop-app.yml
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
name: Release Desktop App
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: App Version
|
||||
required: true
|
||||
default: 0.0.0
|
||||
is-draft:
|
||||
description: 'Draft Release?'
|
||||
type: boolean
|
||||
required: true
|
||||
default: true
|
||||
is-pre-release:
|
||||
description: 'Pre Release? (labeled as "PreRelease")'
|
||||
type: boolean
|
||||
required: true
|
||||
default: true
|
||||
build-type:
|
||||
description: 'Build Type (canary, beta or stable)'
|
||||
type: string
|
||||
required: true
|
||||
default: canary
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
contents: write
|
||||
security-events: write
|
||||
|
||||
concurrency:
|
||||
# The concurrency group contains the workflow name and the branch name for
|
||||
# pull requests or the commit hash for any other events.
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
BUILD_TYPE: ${{ github.event.inputs.build-type }}
|
||||
DEBUG: napi:*
|
||||
APP_NAME: affine
|
||||
MACOSX_DEPLOYMENT_TARGET: '10.13'
|
||||
|
||||
jobs:
|
||||
before-make:
|
||||
runs-on: ubuntu-latest
|
||||
environment: ${{ github.ref_name == 'master' && 'production' || 'development' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
- name: generate-assets
|
||||
run: yarn workspace @affine/electron generate-assets
|
||||
env:
|
||||
NEXT_PUBLIC_FIREBASE_API_KEY: ${{ secrets.NEXT_PUBLIC_FIREBASE_API_KEY }}
|
||||
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN: ${{ secrets.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN }}
|
||||
NEXT_PUBLIC_FIREBASE_PROJECT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_PROJECT_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET: ${{ secrets.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET }}
|
||||
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_APP_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_APP_ID }}
|
||||
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID: ${{ secrets.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID }}
|
||||
AFFINE_GOOGLE_CLIENT_ID: ${{ secrets.AFFINE_GOOGLE_CLIENT_ID }}
|
||||
AFFINE_GOOGLE_CLIENT_SECRET: ${{ secrets.AFFINE_GOOGLE_CLIENT_SECRET }}
|
||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||
NEXT_PUBLIC_SENTRY_DSN: ${{ secrets.NEXT_PUBLIC_SENTRY_DSN }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
API_SERVER_PROFILE: prod
|
||||
ENABLE_TEST_PROPERTIES: false
|
||||
ENABLE_IMAGE_PREVIEW_MODAL: false
|
||||
|
||||
- name: Upload Artifact (web-static)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: before-make-web-static
|
||||
path: apps/electron/resources/web-static
|
||||
|
||||
make-distribution:
|
||||
environment: ${{ github.ref_name == 'master' && 'production' || 'development' }}
|
||||
strategy:
|
||||
# all combinations: macos-latest x64, macos-latest arm64, windows-latest x64, ubuntu-latest x64
|
||||
matrix:
|
||||
spec:
|
||||
- {
|
||||
os: macos-latest,
|
||||
platform: darwin,
|
||||
arch: x64,
|
||||
target: x86_64-apple-darwin,
|
||||
}
|
||||
- {
|
||||
os: macos-latest,
|
||||
platform: darwin,
|
||||
arch: arm64,
|
||||
target: aarch64-apple-darwin,
|
||||
}
|
||||
- {
|
||||
os: ubuntu-latest,
|
||||
platform: linux,
|
||||
arch: x64,
|
||||
target: x86_64-unknown-linux-gnu,
|
||||
}
|
||||
- {
|
||||
os: windows-latest,
|
||||
platform: win32,
|
||||
arch: x64,
|
||||
target: x86_64-pc-windows-msvc,
|
||||
}
|
||||
runs-on: ${{ matrix.spec.os }}
|
||||
needs: before-make
|
||||
env:
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
SKIP_GENERATE_ASSETS: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
- name: Build AFFiNE native
|
||||
uses: ./.github/actions/build-rust
|
||||
with:
|
||||
target: ${{ matrix.spec.target }}
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: before-make-web-static
|
||||
path: apps/electron/resources/web-static
|
||||
|
||||
- name: Rebuild Electron dependences
|
||||
shell: bash
|
||||
run: |
|
||||
rm -rf apps/electron/node_modules/better-sqlite3/build
|
||||
yarn workspace @affine/electron rebuild:for-electron --arch=${{ matrix.spec.arch }}
|
||||
|
||||
- name: Build layers
|
||||
run: yarn workspace @affine/electron build-layers
|
||||
|
||||
- name: Signing By Apple Developer ID
|
||||
if: ${{ matrix.spec.platform == 'darwin' }}
|
||||
uses: apple-actions/import-codesign-certs@v2
|
||||
with:
|
||||
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
|
||||
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
|
||||
|
||||
- name: make
|
||||
run: yarn workspace @affine/electron make --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
|
||||
|
||||
- name: Save artifacts (mac)
|
||||
if: ${{ matrix.spec.platform == 'darwin' }}
|
||||
run: |
|
||||
mkdir -p builds
|
||||
mv apps/electron/out/*/make/*.dmg ./builds/affine-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.dmg
|
||||
mv apps/electron/out/*/make/zip/darwin/${{ matrix.spec.arch }}/*.zip ./builds/affine-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.zip
|
||||
- name: Save artifacts (windows)
|
||||
if: ${{ matrix.spec.platform == 'win32' }}
|
||||
run: |
|
||||
mkdir -p builds
|
||||
mv apps/electron/out/*/make/zip/win32/x64/AFFiNE*-win32-x64-*.zip ./builds/affine-${{ env.BUILD_TYPE }}-windows-x64.zip
|
||||
mv apps/electron/out/*/make/squirrel.windows/x64/*.exe ./builds/affine-${{ env.BUILD_TYPE }}-windows-x64.exe
|
||||
mv apps/electron/out/*/make/squirrel.windows/x64/*.msi ./builds/affine-${{ env.BUILD_TYPE }}-windows-x64.msi
|
||||
mv apps/electron/out/*/make/squirrel.windows/x64/*.nupkg ./builds/affine-${{ env.BUILD_TYPE }}-windows-x64.nupkg
|
||||
|
||||
- name: Save artifacts (linux)
|
||||
if: ${{ matrix.spec.platform == 'linux' }}
|
||||
run: |
|
||||
mkdir -p builds
|
||||
mv apps/electron/out/*/make/zip/linux/x64/*.zip ./builds/affine-${{ env.BUILD_TYPE }}-linux-x64.zip
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: affine-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}-builds
|
||||
path: builds
|
||||
|
||||
release:
|
||||
needs: make-distribution
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Download Artifacts (macos-x64)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: affine-darwin-x64-builds
|
||||
path: ./
|
||||
- name: Download Artifacts (macos-arm64)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: affine-darwin-arm64-builds
|
||||
path: ./
|
||||
- name: Download Artifacts (windows-x64)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: affine-win32-x64-builds
|
||||
path: ./
|
||||
- name: Download Artifacts (linux-x64)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: affine-linux-x64-builds
|
||||
path: ./
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Generate Release yml
|
||||
run: |
|
||||
cp ./apps/electron/scripts/generate-yml.js .
|
||||
node generate-yml.js
|
||||
env:
|
||||
RELEASE_VERSION: ${{ github.event.inputs.version }}
|
||||
- name: Create Release Draft
|
||||
uses: softprops/action-gh-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
with:
|
||||
name: Desktop APP ${{ github.event.inputs.version }}
|
||||
body: 'TODO: Add release notes here'
|
||||
draft: ${{ github.event.inputs.is-draft }}
|
||||
prerelease: ${{ github.event.inputs.is-pre-release }}
|
||||
files: |
|
||||
./VERSION
|
||||
./*.zip
|
||||
./*.dmg
|
||||
./*.exe
|
||||
./*.nupkg
|
||||
./RELEASES
|
||||
./*.AppImage
|
||||
./*.apk
|
||||
./*.yml
|
||||
19
.github/workflows/release.yml
vendored
Normal file
19
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Try publishing npm@latest release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js
|
||||
uses: ./.github/actions/setup-node
|
||||
- name: Try publishing to NPM
|
||||
run: ./scripts/publish.sh
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
67
.github/workflows/venus.yml
vendored
67
.github/workflows/venus.yml
vendored
@@ -1,67 +0,0 @@
|
||||
name: Build Venus
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'apps/venus/**'
|
||||
- '.github/deployment'
|
||||
- '.github/workflows/venus.yml'
|
||||
pull_request:
|
||||
branches: [master]
|
||||
paths:
|
||||
- 'apps/venus/**'
|
||||
- '.github/workflows/venus.yml'
|
||||
|
||||
# Cancels all previous workflow runs for pull requests that have not completed.
|
||||
# See https://docs.github.com/en/actions/using-jobs/using-concurrency
|
||||
concurrency:
|
||||
# The concurrency group contains the workflow name and the branch name for
|
||||
# pull requests or the commit hash for any other events.
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
NAMESPACE: toeverything
|
||||
VENUS_IMAGE_NAME: venus
|
||||
IMAGE_TAG: canary-${{ github.sha }}
|
||||
IMAGE_TAG_LATEST: nightly-latest
|
||||
|
||||
jobs:
|
||||
ligo-virgo:
|
||||
runs-on: self-hosted
|
||||
environment: development
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker (venus)
|
||||
id: meta_venus
|
||||
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.VENUS_IMAGE_NAME }}
|
||||
tags: |
|
||||
${{ env.IMAGE_TAG }}
|
||||
${{ env.IMAGE_TAG_LATEST }}
|
||||
|
||||
- name: Build and push Docker image (venus)
|
||||
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
|
||||
with:
|
||||
context: .
|
||||
file: ./.github/deployment/Dockerfile-venus
|
||||
push: ${{ github.ref == 'refs/heads/master' && true || false }}
|
||||
tags: ${{ steps.meta_venus.outputs.tags }}
|
||||
labels: ${{ steps.meta_venus.outputs.labels }}
|
||||
target: venus
|
||||
29
.gitignore
vendored
29
.gitignore
vendored
@@ -1,9 +1,18 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
.yarn/versions
|
||||
|
||||
# compiled output
|
||||
*dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
.nyc_output
|
||||
.coverage
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
@@ -27,13 +36,14 @@ node_modules
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
.pnpm-debug.log
|
||||
/typings
|
||||
tsconfig.tsbuildinfo
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
@@ -43,3 +53,20 @@ Thumbs.db
|
||||
*.env.local
|
||||
*.local.env
|
||||
.history
|
||||
|
||||
.next
|
||||
out/
|
||||
storybook-static
|
||||
i18n-generated.ts
|
||||
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
|
||||
# Cache
|
||||
.eslintcache
|
||||
next-env.d.ts
|
||||
|
||||
# Rust
|
||||
target
|
||||
*.node
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
# npx lint-staged
|
||||
# check lockfile is up to date
|
||||
yarn install
|
||||
|
||||
pnpm run lint:with-cache
|
||||
pnpm run check
|
||||
pnpm run format:ci
|
||||
# lint staged files
|
||||
yarn exec lint-staged
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
# Show just the current branch in Git
|
||||
# See https://stackoverflow.com/questions/1417957/show-just-the-current-branch-in-git/1418022#1418022
|
||||
current_branch=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
default_branch="master"
|
||||
|
||||
if test $current_branch != $default_branch; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
npm run type:check
|
||||
21
.i18n-codegen.json
Normal file
21
.i18n-codegen.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "./node_modules/@magic-works/i18n-codegen/schema.json",
|
||||
"version": 1,
|
||||
"list": [
|
||||
{
|
||||
"input": "./packages/i18n/src/resources/en.json",
|
||||
"output": "./packages/i18n/src/i18n-generated",
|
||||
"parser": {
|
||||
"type": "i18next",
|
||||
"contextSeparator": "$",
|
||||
"pluralSeparator": "_"
|
||||
},
|
||||
"generator": {
|
||||
"type": "i18next/react-hooks",
|
||||
"hooks": "useAFFiNEI18N",
|
||||
"emitTS": true,
|
||||
"shouldUnescape": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
5
.npmrc
5
.npmrc
@@ -1,3 +1,2 @@
|
||||
registry=https://registry.npmjs.org
|
||||
engine-strict=true
|
||||
auto-install-peers=true
|
||||
shell-emulator=true
|
||||
electron_mirror="https://cdn.npmmirror.com/binaries/electron/"
|
||||
|
||||
@@ -1,13 +1 @@
|
||||
# Add files here to ignore them from prettier formatting
|
||||
|
||||
/dist
|
||||
/coverage
|
||||
pnpm-lock.yaml
|
||||
|
||||
|
||||
# Automatically generated from Figma
|
||||
libs/components/icons/src/auto-icons
|
||||
libs/components/common/src/lib/icon
|
||||
|
||||
# DevOps
|
||||
.github/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 4,
|
||||
"arrowParens": "avoid"
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
|
||||
9
.taplo.toml
Normal file
9
.taplo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
exclude = ["node_modules/**/*.toml"]
|
||||
|
||||
[[rule]]
|
||||
keys = ["dependencies", "*-dependencies"]
|
||||
|
||||
[rule.formatting]
|
||||
align_entries = true
|
||||
indent_tables = true
|
||||
reorder_keys = true
|
||||
15
.vscode/extensions.json
vendored
15
.vscode/extensions.json
vendored
@@ -1,11 +1,8 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"mikestead.dotenv",
|
||||
"esbenp.prettier-vscode",
|
||||
"visualstudioexptteam.vscodeintellicode",
|
||||
"nrwl.angular-console",
|
||||
"firsttris.vscode-jest-runner",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"streetsidesoftware.code-spell-checker"
|
||||
]
|
||||
"recommendations": [
|
||||
"ms-playwright.playwright",
|
||||
"esbenp.prettier-vscode",
|
||||
"deepscan.vscode-deepscan",
|
||||
"streetsidesoftware.code-spell-checker"
|
||||
]
|
||||
}
|
||||
|
||||
11
.vscode/launch.json
vendored
Normal file
11
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "yarn run dev",
|
||||
"name": "Run Dev",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
79
.vscode/settings.json
vendored
79
.vscode/settings.json
vendored
@@ -1,41 +1,42 @@
|
||||
{
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSaveMode": "file",
|
||||
"prettier.prettierPath": "./node_modules/prettier",
|
||||
"cSpell.words": [
|
||||
"Backlinks",
|
||||
"blockdb",
|
||||
"booktitle",
|
||||
"Cascader",
|
||||
"clsx",
|
||||
"cssmodule",
|
||||
"datasource",
|
||||
"fflate",
|
||||
"groq",
|
||||
"howpublished",
|
||||
"immer",
|
||||
"inbook",
|
||||
"incollection",
|
||||
"inproceedings",
|
||||
"Kanban",
|
||||
"keyval",
|
||||
"ligo",
|
||||
"lozad",
|
||||
"mastersthesis",
|
||||
"nrwl",
|
||||
"phdthesis",
|
||||
"pnpm",
|
||||
"reindex",
|
||||
"ROOTNODE",
|
||||
"techreport",
|
||||
"tldr",
|
||||
"tldraw",
|
||||
"tldtaw",
|
||||
"toeverything",
|
||||
"Unstyled",
|
||||
"unversioned",
|
||||
"uuidv",
|
||||
"webm"
|
||||
]
|
||||
"eslint.packageManager": "yarn",
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSaveMode": "file",
|
||||
"cSpell.words": [
|
||||
"blocksuite",
|
||||
"livedemo",
|
||||
"yarn",
|
||||
"jwst",
|
||||
"testid",
|
||||
"octobase",
|
||||
"selfhosted",
|
||||
"testid",
|
||||
"schemars"
|
||||
],
|
||||
"explorer.fileNesting.patterns": {
|
||||
"*.js": "${capture}.js.map, ${capture}.min.js, ${capture}.d.ts, ${capture}.d.ts.map",
|
||||
"package.json": ".browserslist*, .circleci*, .codecov, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lighthouserc.*, .lintstagedrc*, .markdownlint*, .mocha*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, api-extractor.json, apollo.config.*, appveyor*, ava.config.*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, cypress.*, dangerfile*, dlint.json, dprint.json, firebase.json, grunt*, gulp*, histoire.config.*, jasmine.*, jenkins*, jest.config.*, jsconfig.*, karma*, lerna*, lighthouserc.*, lint-staged*, nest-cli.*, netlify*, nodemon*, nx.*, package-lock.json, package.nls*.json, phpcs.xml, playwright.config.*, pm2.*, pnpm*, prettier*, pullapprove*, puppeteer.config.*, pyrightconfig.json, release-tasks.sh, renovate*, rollup.config.*, stylelint*, tsconfig.*, tsdoc.*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, vitest.config.*, webpack*, workspace.json, xo.config.*, yarn*, babel.*, .babelrc, project.json",
|
||||
"Cargo.toml": "Cargo.lock",
|
||||
"README.md": "LICENSE, CHANGELOG.md, CODE_OF_CONDUCT.md, CONTRIBUTING.md"
|
||||
},
|
||||
"[rust]": {
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
||||
},
|
||||
"[toml]": {
|
||||
"editor.defaultFormatter": "tamasfe.even-better-toml"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"vitest.include": [
|
||||
"packages/**/*.spec.ts",
|
||||
"packages/**/*.spec.tsx",
|
||||
"apps/web/**/*.spec.ts",
|
||||
"apps/web/**/*.spec.tsx",
|
||||
"apps/electron/layers/**/*.spec.ts",
|
||||
"tests/unit/**/*.spec.ts",
|
||||
"tests/unit/**/*.spec.tsx"
|
||||
],
|
||||
"deepscan.enable": true
|
||||
}
|
||||
|
||||
541
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
Normal file
541
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
Normal file
File diff suppressed because one or more lines are too long
550
.yarn/plugins/@yarnpkg/plugin-version.cjs
vendored
Normal file
550
.yarn/plugins/@yarnpkg/plugin-version.cjs
vendored
Normal file
File diff suppressed because one or more lines are too long
28
.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
vendored
Normal file
28
.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
vendored
Normal file
File diff suppressed because one or more lines are too long
873
.yarn/releases/yarn-3.5.0.cjs
vendored
Executable file
873
.yarn/releases/yarn-3.5.0.cjs
vendored
Executable file
File diff suppressed because one or more lines are too long
19
.yarnrc.yml
Normal file
19
.yarnrc.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
nmMode: hardlinks-local
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
npmAuthToken: '${NPM_TOKEN:-NONE}'
|
||||
|
||||
npmPublishAccess: public
|
||||
|
||||
npmPublishRegistry: 'https://registry.npmjs.org'
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||
spec: '@yarnpkg/plugin-interactive-tools'
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
|
||||
spec: '@yarnpkg/plugin-version'
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
|
||||
spec: '@yarnpkg/plugin-workspace-tools'
|
||||
|
||||
yarnPath: .yarn/releases/yarn-3.5.0.cjs
|
||||
5
CHANGELOG.md
Normal file
5
CHANGELOG.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
See the [AFFiNE CHANGELOG](https://affine.pro/blog?tag=Release%20Note)
|
||||
|
||||
---
|
||||
800
Cargo.lock
generated
Normal file
800
Cargo.lock
generated
Normal file
@@ -0,0 +1,800 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "affine_native"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"napi",
|
||||
"napi-build",
|
||||
"napi-derive",
|
||||
"notify",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd4056f63fce3b82d852c3da92b08ea59959890813a7f4ce9c0ff85b10cf301b"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fsevent-sys"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify-sys"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
|
||||
[[package]]
|
||||
name = "kqueue"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
|
||||
dependencies = [
|
||||
"kqueue-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kqueue-sys"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.144"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi"
|
||||
version = "2.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49ac8112fe5998579b22e29903c7b277fc7f91c7860c0236f35792caf8156e18"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.2.1",
|
||||
"ctor",
|
||||
"napi-derive",
|
||||
"napi-sys",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi-build"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e"
|
||||
|
||||
[[package]]
|
||||
name = "napi-derive"
|
||||
version = "2.12.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c47e0f395207c062e680a158f0624ec456c1dfb3c96a8cb888e0401506d50ae9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"convert_case",
|
||||
"napi-derive-backend",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi-derive-backend"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a83afae5b4ba6f98ed6e33a52da343fdeb66474f1162a38cde5a3d46eb054e7"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"semver",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "napi-sys"
|
||||
version = "2.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "166b5ef52a3ab5575047a9fe8d4a030cdd0f63c96f071cd6907674453b07bae3"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "5.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"crossbeam-channel",
|
||||
"filetime",
|
||||
"fsevent-sys",
|
||||
"inotify",
|
||||
"kqueue",
|
||||
"libc",
|
||||
"mio",
|
||||
"serde",
|
||||
"walkdir",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.162"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.162"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.96"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"rand",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.42.2",
|
||||
"windows_aarch64_msvc 0.42.2",
|
||||
"windows_i686_gnu 0.42.2",
|
||||
"windows_i686_msvc 0.42.2",
|
||||
"windows_x86_64_gnu 0.42.2",
|
||||
"windows_x86_64_gnullvm 0.42.2",
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.0",
|
||||
"windows_aarch64_msvc 0.48.0",
|
||||
"windows_i686_gnu 0.48.0",
|
||||
"windows_i686_msvc 0.48.0",
|
||||
"windows_x86_64_gnu 0.48.0",
|
||||
"windows_x86_64_gnullvm 0.48.0",
|
||||
"windows_x86_64_msvc 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
[workspace]
|
||||
members = ["./packages/native"]
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
opt-level = 3
|
||||
strip = "symbols"
|
||||
397
LICENSE
397
LICENSE
@@ -1,21 +1,384 @@
|
||||
MIT License
|
||||
# Mozilla Public License Version 2.0
|
||||
|
||||
Copyright (c) Toeverything Technology (Hangzhou) Co., Ltd. and its affiliates.
|
||||
Copyright (c) TOEVERYTHING PTE. LTD. and its affiliates.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
1. Definitions
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
---
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
|
||||
---
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
|
||||
---
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
|
||||
---
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
|
||||
---
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
---
|
||||
|
||||
- *
|
||||
- 6. Disclaimer of Warranty \*
|
||||
- ------------------------- \*
|
||||
- *
|
||||
- Covered Software is provided under this License on an "as is" \*
|
||||
- basis, without warranty of any kind, either expressed, implied, or \*
|
||||
- statutory, including, without limitation, warranties that the \*
|
||||
- Covered Software is free of defects, merchantable, fit for a \*
|
||||
- particular purpose or non-infringing. The entire risk as to the \*
|
||||
- quality and performance of the Covered Software is with You. \*
|
||||
- Should any Covered Software prove defective in any respect, You \*
|
||||
- (not any Contributor) assume the cost of any necessary servicing, \*
|
||||
- repair, or correction. This disclaimer of warranty constitutes an \*
|
||||
- essential part of this License. No use of any Covered Software is \*
|
||||
- authorized under this License except under this disclaimer. \*
|
||||
- *
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
- *
|
||||
- 7. Limitation of Liability \*
|
||||
- -------------------------- \*
|
||||
- *
|
||||
- Under no circumstances and under no legal theory, whether tort \*
|
||||
- (including negligence), contract, or otherwise, shall any \*
|
||||
- Contributor, or anyone who distributes Covered Software as \*
|
||||
- permitted above, be liable to You for any direct, indirect, \*
|
||||
- special, incidental, or consequential damages of any character \*
|
||||
- including, without limitation, damages for lost profits, loss of \*
|
||||
- goodwill, work stoppage, computer failure or malfunction, or any \*
|
||||
- and all other commercial damages or losses, even if such party \*
|
||||
- shall have been informed of the possibility of such damages. This \*
|
||||
- limitation of liability shall not apply to liability for death or \*
|
||||
- personal injury resulting from such party's negligence to the \*
|
||||
- extent applicable law prohibits such limitation. Some \*
|
||||
- jurisdictions do not allow the exclusion or limitation of \*
|
||||
- incidental or consequential damages, so this exclusion and \*
|
||||
- limitation may not apply to You. \*
|
||||
- *
|
||||
|
||||
---
|
||||
|
||||
8. Litigation
|
||||
|
||||
---
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
|
||||
---
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
|
||||
---
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
## Exhibit A - Source Code Form License Notice
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
## Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
|
||||
282
README.md
282
README.md
@@ -1,200 +1,192 @@
|
||||
<h1 align="center" style="border-bottom: none">
|
||||
<b>
|
||||
<a href="https://affine.pro">AFFiNE.PRO</a><br>
|
||||
</b>
|
||||
The Next-Gen Knowledge Base to Replace Notion & Miro.
|
||||
<div align="center">
|
||||
|
||||
<h1 style="border-bottom: none">
|
||||
<b><a href="https://affine.pro">AFFiNE.PRO</a></b><br />
|
||||
The Next-Gen Collaborative Knowledge Base
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
Planning, Sorting and Creating all Together. Open-source, Privacy-First, and Free to use.
|
||||
<p>
|
||||
AFFiNE is a next-gen knowledge base that brings planning, sorting and creating all together.<br />
|
||||
Privacy first, open-source, customizable and ready to use - a free replacement for Notion & Miro. <br />
|
||||
</p>
|
||||
|
||||
<div align="center">
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
<!--
|
||||
Make New Badge Pattern badges inline
|
||||
See https://github.com/all-?/all-contributors/issues/361#issuecomment-637166066
|
||||
-->
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
|
||||
[all-contributors-badge]: https://img.shields.io/badge/all_contributors-11-orange.svg?style=flat-square
|
||||
[all-contributors-badge]: https://img.shields.io/badge/all_contributors-66-orange.svg?style=flat-square
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
[?style=flat-square&logoColor=white&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAADAAAAAwAEwd99eAAABjElEQVRYhe1W0U3DMBB9RfyTDeoNyAYNG2QDOgJsECYgGxA26AZ4hIxgJqCZ4PjIGV+tUxK7raqiPsmKdXe5e3fOs7IiIlwSdxetfiNw7QRKAD0Ax/ssrI5QgQOw5v03AJOTJHcCL1x84LVmWzJyJlBg7P4BwCvb3pmIAbBPykZEqaulEU7YHNva1HypxUsKqIS9EvbynASs0n3ss+ciUIsuO8VvhL9emjdFBa3YO8XvALwpsZNYSqBB0PwUWgRZNksSL5GhlN0ngGd+dkpsD6AG8IGlslxwTh2fa09EBc3Dir32rRysuQlUAL54/wTAcpePPAXHPsOTGXhSEv69rAlYpZOt6DSO29J4D/TRRLJk6AvtaZSY9PkCFYVLqI9i/NF5YkkECgrXa6P4fVEn4iolrhNxRQqBZu7FqMNdZiMqAUPj2KdGZyicu1dHzlGqBHxn2sdTR53bmeJ+ebJd7LtXhGH4uQEwd0ttAPzMxGi5/6BdxTuMej41Bs59gGP+CU+Cq/4tvxH4HwR+Ab3Uqr/VGbqEAAAAAElFTkSuQmCC>)](https://app.affine.pro)
|
||||
[](https://affine.pro/download)
|
||||
[](https://affine.pro/download)
|
||||
[](https://affine.pro/download)
|
||||
[](https://affine.pro/download)
|
||||
|
||||
[![stars-icon]](https://github.com/toeverything/AFFiNE)
|
||||
[![All Contributors][all-contributors-badge]](#contributors)
|
||||
[](https://www.typescriptlang.org/)
|
||||
[](https://www.typescriptlang.org/)
|
||||
[](https://reactjs.org/)
|
||||
[](https://www.rust-lang.org/)
|
||||
[![codecov]](https://codecov.io/gh/toeverything/AFFiNE)
|
||||
[![Node-version-icon]](https://nodejs.org/)
|
||||
[![TypeScript-version-icon]](https://www.typescriptlang.org/)
|
||||
[![React-version-icon]](https://reactjs.org/)
|
||||
[![blocksuite-icon]](https://github.com/toeverything/blocksuite)
|
||||
[![Rust-version-icon]](https://www.rust-lang.org/)
|
||||
|
||||
</div>
|
||||
|
||||
<p align="center">
|
||||
<a href="http://affine.pro"><b>Website</b></a> •
|
||||
<a href="https://discord.com/invite/yz6tGVsf5p"><b>Discord</b></a> •
|
||||
<a href="https://twitter.com/AffineOfficial"><b>Twitter</b></a> •
|
||||
<a href="https://medium.com/@affineworkos"><b>Medium</b></a> •
|
||||
<a href="https://t.me/affineworkos"><b>Telegram</b></a>
|
||||
</p>
|
||||
---
|
||||
|
||||
<p align="center"><img width="1920" alt="affine_screen" src="https://user-images.githubusercontent.com/21084335/182552060-972cac0e-6258-4ccb-85bd-3bb466c30ccd.png"><p/>
|
||||
<div align="center">
|
||||
<a href="http://affine.pro"><img src="https://img.shields.io/badge/-AFFiNE-06449d?style=social&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAMAAAAPkIrYAAAAP1BMVEU8b9w8b9w+b947cNw7b9w6b908b909b9w8b9w7b9w8b9w7cN08b9w7b908b9w7b9w8b907cNw8b9w8b91HcEx3NJCJAAAAFXRSTlP/3QWSgA+lHPlu6Di4XtIrxk/xRADGudUoAAAB9UlEQVR42tWYwbKjIBREG0GJKkRj/v9bZ1ZvRC99rzib11tTB9qqnKoW3/+X38vy7ifzQ1b/wk/8Q1bCv3y6Z6wFh2x2llIRGB6xRhzz6p+wVhRJD1gRZZYHrADYSyqsjFPGZtYbuFESesUysZXlcMnYyJpxTW5keQh5N7G6CUJCE2uHFNfEGiBmbmB1H4jxDawNcqbuPmtAJTtj6RZ0lpIwiR5jNmgfNtHHwLXPWfFYcS2NMdxkjac/dNaNCJPo3yf9pFuseHbDrBsRFguGs8te8Q4rXzTjVSPCIHp3FePKWbzi30xE+4zlBMmoJaGLfpLUmAmLiN4Xyibahy76WZRQMLJ2WX27on2oFvQVac8yi4p+J2forA0V8W1c++AVS1f1H6p9KKLHxk9RWKmsyB+VLC76gV65DLjokdg5KmsEMXsiDwXWSmTc9ezSoKJHoi9zUVihbMHfQOSsXB7Mrz1S1huKPde69sEsiKgNt8hYTjiWlAyENeu7IFe1D15RSEBN+yCiXw17K1RZm/w7UtJVWYN8f1ZyLlkVb2bT4vIVVrINH1dqX2YttkHmIWsfVWs646wcRFYis6fIVGpfYq1kjpGSW8kSRD+xYSmXRM0Ang9eSZioVdy/5pWaLqzIRyIpuVxYozvGf1m67I7pf/s3UXv+AP61NI2Y+BbSAAAAAElFTkSuQmCC" height=25></a>
|
||||
|
||||
<a href="https://community.affine.pro"><img src="https://img.shields.io/badge/-Community-424549?style=social&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAXNJREFUWEftlitLRUEURtdVEVExWUx2qxgNVouoXYtNDP4Tw20WtftAsItZrHaTYBJREZ98MAc248wcZxi4CGfSeezHmm/23kyPAa/egPPTAXQK/FsFBP7ldVDRZoqcgO9I+2bHy3ZIJBfTCPCZM1tqAxwBmzUBrNQNbEx+5b0B5oEN4NCBrAMnMaiUAuPAs3HU82TLEZwBqwGbaJ4UgKQ8CFR6SoEl4LIWwCJwZQCegKkWBWLHVKSActvdzgG3DqitDf3/VQBskBDALrDnAKXUo3ueAF5KinAf2DKOmnzD7l214bdbA6hC1XHZNQa8hSBC0hwDa57xDHDvvvWB7ciOZoE79+8CWPbsBGc769eFxJdWIKcuyIdRoG3W7AAC1dJkHDIOo8B78+4rEBo8r4AkLFk6Jk3HaeDBBTgHVmIAfpJUz+cAFXVBreQCvQYW/lqEjV1NAMUMqpAaxQMHyDnjYtuS+0BxstwaqJooFqxToFPgB5FuPCEB6XK2AAAAAElFTkSuQmCC" height=25></a>
|
||||
|
||||
<a href="https://discord.com/invite/yz6tGVsf5p"><img src="https://img.shields.io/badge/-Discord-424549?style=social&logo=discord" height=25></a>
|
||||
|
||||
<a href="https://t.me/affineworkos"><img src="https://img.shields.io/badge/-Telegram-red?style=social&logo=telegram" height=25></a>
|
||||
|
||||
<a href="https://twitter.com/AffineOfficial"><img src="https://img.shields.io/badge/-Twitter-red?style=social&logo=twitter" height=25></a>
|
||||
|
||||
<a href="https://medium.com/@affineworkos"><img src="https://img.shields.io/badge/-Medium-red?style=social&logo=medium" height=25></a>
|
||||
</div>
|
||||
|
||||
# Stay Up-to-Date and Support Us
|
||||
<br />
|
||||
<div align="center">
|
||||
<em>See docs, canvas and tables are hyper merged with AFFiNE - just like the word affine (əˈfʌɪn | a-fine).</em>
|
||||
</div>
|
||||
<br />
|
||||
|
||||

|
||||

|
||||
|
||||
# How to use
|
||||
## Join our community
|
||||
|
||||
If you have experience in front-end development, please [refer to here](https://affine.gitbook.io/affine/basic-documentation/contribute-to-affine); if you want to experience our latest version, please wait a moment, we will launch a web version in the near future.
|
||||
And, thanks to Lee who [made a desktop build with Tauri](https://github.com/m1911star/affine-client) for you to try out.
|
||||
Please notice that AFFiNE is still under Alpha stage and is not ready for production use.
|
||||
Before we tell you how to get started with AFFiNE, we'd like to shamelessly plug our awesome user and developer communities across [official social platforms](https://community.affine.pro/c/start-here/)! Once you’re familiar with using the software, maybe you will share your wisdom with others and even consider joining the [AFFiNE Ambassador program](https://community.affine.pro/c/start-here/affine-ambassador) to help spread AFFiNE to the world.
|
||||
|
||||
# Table of contents
|
||||
## Getting started & Stay tunned with us.
|
||||
|
||||
- [Stay Up-to-Date and Support Us](#stay-up-to-date-and-support-us)
|
||||
- [How to Use](#how-to-use)
|
||||
- [Table of contents](#table-of-contents)
|
||||
- [Shape your page](#shape-your-page)
|
||||
- [Plan your task](#plan-your-task)
|
||||
- [Sort your knowledge](#sort-your-knowledge)
|
||||
- [Create your story](#create-your-story)
|
||||
- [Documentation](#documentation)
|
||||
- [Getting Started with development](#getting-started-with-development)
|
||||
- [Roadmap](#roadmap)
|
||||
- [Releases](#releases)
|
||||
- [Feature requests](#feature-requests)
|
||||
- [FAQ](#faq)
|
||||
- [The Philosophy of AFFiNE](#the-philosophy-of-affine)
|
||||
- [Community](#community)
|
||||
- [Contributors](#contributors)
|
||||
- [Acknowledgments](#acknowledgments)
|
||||
- [License](#license)
|
||||
⚠️ Please note that AFFiNE is still under active development and is not yet ready for production use. ⚠️
|
||||
|
||||
## Shape your page
|
||||
[](https://app.affine.pro) No installation or registration required! Head over to our website and try it out now.
|
||||
|
||||

|
||||
[](https://community.affine.pro) Our wonderful community, where you can meet and engage with the team, developers and other like-minded enthusiastic user of AFFiNE.
|
||||
|
||||
## Plan your task
|
||||
Star us, and you will receive all releases notifications from GitHub without any delay!
|
||||

|
||||
|
||||

|
||||
## Features
|
||||
|
||||
## Sort your knowledge
|
||||
- **Hyper merged** — Write, draw and plan all at once. Assemble any blocks you love on any canvas you like to enjoy seamless transitions bewtween workflows with AFFiNE.
|
||||
- **Privacy focussed** — AFFiNE is built with your privacy in mind and is one of our key concerns. We want you to keep control of your data, allowing you to store it as you like, where you like while still being able to freely edit and view your data on-demand.
|
||||
- **Offline-first** - With your privacy in mind we also decided to go offline-first. This means that AFFiNE can be used offline, whether you want to view or edit, with support for conflict-free merging when you are back online.
|
||||
- **Clean, intuitive design** — With AFFiNE you can concentrate on editing with a clean and modern interface. Which is responsive, so it looks great on tablets too, and mobile support is coming in the future.
|
||||
- **Modern Block Editor with Markdown support** — A modern block editor can help you not only for docs, but slides and tables as well. When you write in AFFiNE you can use Markdown syntax which helps create an easier editing experience, that can be experienced with just a keyboard. And this allows you to export your data cleanly into Markdown.
|
||||
- **Collaboration** — Whether you want to collaborate with yourself across multiple devices, or work together with others, support for collaboration and multiplayer is out-of-the-box, which makes it easy for teams to get started with AFFiNE.
|
||||
- **Choice of multiple languages** — Thanks to community contributions AFFiNE offers support for multiple languages. If you don't find your language or would like to suggest some changes we welcome your contributions.
|
||||
|
||||

|
||||

|
||||
|
||||
## Create your story
|
||||
## Contributing
|
||||
|
||||
We want your data always to be yours, and we don't want to make any sacrifice to your accessibility. Your data is always local-stored first, yet we support real-time collaboration on a peer-to-peer basis. We don't think "privacy-first" is a good excuse for not supporting modern web features.
|
||||
Collaboration isn't only necessary for teams -- you may take and insert pics on your phone, then edit them on your desktop, and share them with your collaborators.
|
||||
Affine is fully built with web technologies so that consistency and accessibility are always guaranteed on Mac, Windows and Linux. The local file system support will be available when version 0.0.1beta is released.
|
||||
| Bug Reports | Feature Requests | Questions/Discussions | AFFiNE Community |
|
||||
| --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------- |
|
||||
| [Create a bug report](https://github.com/toeverything/AFFiNE/issues/new?assignees=&labels=bug%2Cproduct-review&template=BUG-REPORT.yml&title=TITLE) | [Submit a feature request](https://github.com/toeverything/AFFiNE/issues/new?assignees=&labels=feat%2Cproduct-review&template=FEATURE-REQUEST.yml&title=TITLE) | [Check GitHub Discussion](https://github.com/toeverything/AFFiNE/discussions) | [Vist the AFFiNE Community](https://community.affine.pro) |
|
||||
| Something isn't working as expected | An idea for a new feature, or improvements | Discuss and ask questions | A place to ask, learn and engage with others |
|
||||
|
||||
# Documentation
|
||||
Calling all developers, testers, tech writers and more! Contributions of all types are more than welcome, you can read more in [docs/types-of-contributions.md](docs/types-of-contributions.md). If you are interested in contributing code, read our [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) and feel free to check out our GitHub issues to get stuck in to show us what you’re made of.
|
||||
|
||||
AFFiNE is not yet ready for production use. To install, you may check how to build or depoly the AFFiNE in [quick-start](https://affine.gitbook.io/affine/basic-documentation/contribute-to-affine/quick-start). For the full documentation, please view it [here](https://affine.gitbook.io/affine/).
|
||||
**Before you start contributing, please make sure you have read and accepted our [Contributor License Agreement]. To indicate your agreement, simply edit this file and submit a pull request.**
|
||||
|
||||
## Getting Started with development
|
||||
For **bug reports**, **feature requests** and other **suggestions** you can also [create a new issue](https://github.com/toeverything/AFFiNE/issues/new/choose) and choose the most appropriate template for your feedback.
|
||||
|
||||
Please view the path Contribute-to-AFFiNE/Software-Contributions/Quick-Start in documentation.
|
||||
For **translation** and **language support** you can visit our [i18n General Space](https://community.affine.pro/c/i18n-general).
|
||||
|
||||
# Roadmap
|
||||
Looking for **others ways to contribute** and wondering where to start? Check out the [AFFiNE Ambassador program](https://community.affine.pro/c/start-here/affine-ambassador), we work closely with passionate community members and provide them with a wide-range of support and resources.
|
||||
|
||||
Coming Soon...
|
||||
If you have questions, you are welcome to contact us. One of the best places to get more info and learn more is in the [AFFiNE Community](https://community.affine.pro) where you can engage with other like-minded individuals.
|
||||
|
||||
# Releases
|
||||
## Ecosystem
|
||||
|
||||
Get our latest [release notes](https://github.com/toeverything/AFFiNE/wiki) from here.
|
||||
| Name | | |
|
||||
| --------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [@affine/component](https://affine-storybook.vercel.app/) | AFFiNE Component Resources | [](https://affine-storybook.vercel.app/) |
|
||||
| [@toeverything/y-indexeddb](packages/y-indexeddb) | IndexedDB database adapter for Yjs | [](https://www.npmjs.com/package/@toeverything/y-indexeddb) |
|
||||
| [@toeverything/theme](packages/theme) | AFFiNE theme | [](https://www.npmjs.com/package/@toeverything/theme) |
|
||||
|
||||
# Feature requests
|
||||
## Thanks
|
||||
|
||||
Please go to [Feature request](https://github.com/toeverything/AFFiNE/issues).
|
||||
We would also like to give thanks to open-source projects that make AFFiNE possible:
|
||||
|
||||
# FAQ
|
||||
|
||||
Get quick help on [Telegram](https://t.me/affineworkos) and [Discord](https://discord.gg/yz6tGVsf5p) along with other developers and contributors.
|
||||
|
||||
Latest news and technology sharing on [Twitter](https://twitter.com/AffineOfficial), [Medium](https://medium.com/@affineworkos) and [AFFiNE Blog](https://blog.affine.pro/).
|
||||
|
||||
# The Philosophy of AFFiNE
|
||||
|
||||
Timothy Berners-Lee once taught us about the idea of the semantic web, where all the data can be interpreted in any form while the "truth" is kept. This gives our best image of an ideal knowledge base by far, that sorting of information, planning of project and goals as well as creating of knowledge can be all together.
|
||||
We have witnessed waves of paradigm shift so many times. At first, everything was noted on office-like apps or DSL like LaTeX, then we found todo-list apps and WYSIWYG markdown editors better for writing and planning. Finally, here comes Notion and Miro, who take advantage of the idea of blocks to further liberate our creativity.
|
||||
It is all perfect... If there are not so many waste operations and redundant information. And, we insist that privacy first should always be given by default.
|
||||
That's why we are making AFFiNE. Some of the most important features are:
|
||||
|
||||
- Transformable
|
||||
- Every block can be transformed equally well as a database
|
||||
- e.g. you can now set up a to-do with MarkDown in text view and edit it in kanban view.
|
||||
- Every doc can be turned into a whiteboard
|
||||
- An always good-to-read, structured docs-form page is the best for your notes, but a boundless doodle surface is better for collaboration and creativity.
|
||||
- Atomic
|
||||
- The basic element of affine are blocks, not pages.
|
||||
- Blocks can be directly reuse and synced between pages.
|
||||
- Pages and blocks are searched and organized on the basis of connected graphs, not tree-like paths.
|
||||
- Dual-link and semantic search are fully supported.
|
||||
- Collaborative and privacy-first
|
||||
- Data is always stored locally by default
|
||||
- CRDTs are applied so that peer-to-peer collaboration is possible.
|
||||
|
||||
We really appreciate the idea of Monday, airtable and notion database. They inspired what we think is right for task management. But we don't like the repeated works -- we don't want to set a todo easily with markdown but end up re-write it again in kanban or other databases.
|
||||
With AFFiNE, every block group has infinite views, for you to keep your single source of truth.
|
||||
|
||||
We would like to give special thanks to the innovators and pioneers who greatly inspired us:
|
||||
|
||||
- Quip & Notion -- that docs can be organized as blocks
|
||||
- Taskade & Monday -- brillant multi-demensional tables
|
||||
- Height & Linear -- beautiful task management tool
|
||||
|
||||
We would also like to give thanks to open-source projects that make affine possible:
|
||||
|
||||
- [Yjs](https://github.com/yjs/yjs) & [Yrs](https://github.com/y-crdt/y-crdt) -- Fundamental support of CRDTs for our implements on state management and data sync.
|
||||
- [React](https://github.com/facebook/react) -- View layer support and web GUI framework.
|
||||
- [Rust](https://github.com/rust-lang/rust) -- High performance language that extends the ability and availability of our real-time backend, JWST.
|
||||
- [Fossil](https://www2.fossil-scm.org/home/doc/trunk/www/index.wiki) -- Source code management tool made with CRDTs which inspired our design on block data structure.
|
||||
- [slatejs](https://github.com/ianstormtaylor/slate) -- Customizable rich-text editor.
|
||||
- [Jotai](https://github.com/pmndrs/jotai) -- Minimal state management tool for frontend.
|
||||
- [Tldraw](https://github.com/tldraw/tldraw) -- Excellent drawing board.
|
||||
- [MUI](https://github.com/mui/material-ui) -- Our most used graphic UI component library.
|
||||
- Other [dependancies](https://github.com/toeverything/AFFiNE/network/dependencies)
|
||||
- [BlockSuite](https://github.com/toeverything/BlockSuite) - 💠 BlockSuite is the open-source collaborative editor project behind AFFiNE.
|
||||
- [OctoBase](https://github.com/toeverything/OctoBase) - 🐙 OctoBase is the open-source database behind AFFiNE, local-first, yet collaborative. A light-weight, scalable, data engine written in Rust.
|
||||
- [Yjs](https://github.com/yjs/yjs) & [Yrs](https://github.com/y-crdt/y-crdt) - Fundamental support of CRDTs for our implementation on state management and data sync.
|
||||
- [Next.js](https://github.com/vercel/next.js) - The React Framework.
|
||||
- [React](https://github.com/facebook/react) - View layer support and web GUI framework.
|
||||
- [Rust](https://github.com/rust-lang/rust) - High performance language that extends the ability and availability of our real-time backend, OctoBase.
|
||||
- [Jotai](https://github.com/pmndrs/jotai) - Primitive and flexible state management for React.
|
||||
- [MUI](https://github.com/mui/material-ui) - Our most used graphic UI component library.
|
||||
- Other upstream [dependencies](https://github.com/toeverything/AFFiNE/network/dependencies).
|
||||
|
||||
Thanks a lot to the community for providing such powerful and simple libraries, so that we can focus more on the implementation of the product logic, and we hope that in the future our projects will also provide a more easy-to-use knowledge base for everyone.
|
||||
|
||||
# Community
|
||||
|
||||
For help, discussion about best practices, or any other conversation that would benefit from being searchable:
|
||||
|
||||
[Discuss AFFiNE on GitHub](https://github.com/toeverything/AFFiNE/discussions)
|
||||
|
||||
# Contributors
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://darksky.eu.org/"><img src="https://avatars.githubusercontent.com/u/25152247?v=4?s=100" width="100px;" alt=""/><br /><sub><b>DarkSky</b></sub></a><br /><a href="https://github.com/toeverything/AFFiNE/commits?author=darkskygit" title="Code">💻</a> <a href="https://github.com/toeverything/AFFiNE/commits?author=darkskygit" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://zhangchi.page/"><img src="https://avatars.githubusercontent.com/u/5910926?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chi Zhang</b></sub></a><br /><a href="https://github.com/toeverything/AFFiNE/commits?author=tzhangchi" title="Code">💻</a> <a href="https://github.com/toeverything/AFFiNE/commits?author=tzhangchi" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/alt1o"><img src="https://avatars.githubusercontent.com/u/21084335?v=4?s=100" width="100px;" alt=""/><br /><sub><b>wang xinglong</b></sub></a><br /><a href="https://github.com/toeverything/AFFiNE/commits?author=alt1o" title="Code">💻</a> <a href="https://github.com/toeverything/AFFiNE/commits?author=alt1o" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/DiamondThree"><img src="https://avatars.githubusercontent.com/u/24630517?v=4?s=100" width="100px;" alt=""/><br /><sub><b>DiamondThree</b></sub></a><br /><a href="https://github.com/toeverything/AFFiNE/commits?author=DiamondThree" title="Code">💻</a> <a href="https://github.com/toeverything/AFFiNE/commits?author=DiamondThree" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://lawvs.github.io/profile/"><img src="https://avatars.githubusercontent.com/u/18554747?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Whitewater</b></sub></a><br /><a href="https://github.com/toeverything/AFFiNE/commits?author=lawvs" title="Code">💻</a> <a href="https://github.com/toeverything/AFFiNE/commits?author=lawvs" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/zuoxiaodong0815"><img src="https://avatars.githubusercontent.com/u/53252747?v=4?s=100" width="100px;" alt=""/><br /><sub><b>xiaodong zuo</b></sub></a><br /><a href="https://github.com/toeverything/AFFiNE/commits?author=zuoxiaodong0815" title="Code">💻</a> <a href="https://github.com/toeverything/AFFiNE/commits?author=zuoxiaodong0815" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/SaikaSakura"><img src="https://avatars.githubusercontent.com/u/11530942?v=4?s=100" width="100px;" alt=""/><br /><sub><b>MingLIang Wang</b></sub></a><br /><a href="https://github.com/toeverything/AFFiNE/commits?author=SaikaSakura" title="Code">💻</a> <a href="https://github.com/toeverything/AFFiNE/commits?author=SaikaSakura" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/QiShaoXuan"><img src="https://avatars.githubusercontent.com/u/22772830?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Qi</b></sub></a><br /><a href="https://github.com/toeverything/AFFiNE/commits?author=QiShaoXuan" title="Code">💻</a> <a href="https://github.com/toeverything/AFFiNE/commits?author=QiShaoXuan" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/mitsuhatu"><img src="https://avatars.githubusercontent.com/u/110213079?v=4?s=100" width="100px;" alt=""/><br /><sub><b>mitsuhatu</b></sub></a><br /><a href="https://github.com/toeverything/AFFiNE/commits?author=mitsuhatu" title="Code">💻</a> <a href="https://github.com/toeverything/AFFiNE/commits?author=mitsuhatu" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://shockwave.me/"><img src="https://avatars.githubusercontent.com/u/15013925?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Austaras</b></sub></a><br /><a href="https://github.com/toeverything/AFFiNE/commits?author=Austaras" title="Code">💻</a> <a href="https://github.com/toeverything/AFFiNE/commits?author=Austaras" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/uptonking?tab=repositories&type=source"><img src="https://avatars.githubusercontent.com/u/11391549?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jin Yao</b></sub></a><br /><a href="https://github.com/toeverything/AFFiNE/commits?author=uptonking" title="Code">💻</a> <a href="https://github.com/toeverything/AFFiNE/commits?author=uptonking" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
We would like to express our gratitude to all the individuals who have already contributed to AFFiNE! If you have any AFFiNE-related project, documentation, tool or template, please feel free to contribute it by submitting a pull request to our curated list on GitHub: [awesome-affine](https://github.com/toeverything/awesome-affine).
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
<a href="https://github.com/toeverything/affine/graphs/contributors">
|
||||
<img src="https://user-images.githubusercontent.com/5910926/237263745-36bb975d-83d6-4a7c-a152-d9ad020e5023.png" />
|
||||
</a>
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
## Self-Host
|
||||
|
||||
# License
|
||||
Get started with Docker and deploy your own feature-rich, restriction-free deployment of AFFiNE - check the [latest packages].
|
||||
|
||||
AFFiNE is distributed under the terms of MIT license.
|
||||
## Hiring
|
||||
|
||||
See LICENSE for details.
|
||||
Some amazing companies including AFFiNE are looking for developers! Are you interested in helping build with AFFiNE and/or its partners? Check out some of the latest [jobs available].
|
||||
|
||||
## Upgrading
|
||||
|
||||
For upgrading information please see our [update page].
|
||||
|
||||
## Feature Request
|
||||
|
||||
For feature request please see [community.affine.pro](https://community.affine.pro/c/feature-requests/).
|
||||
|
||||
## Is it awesome?
|
||||
|
||||
[These people] seem to like it.
|
||||
|
||||
## Building
|
||||
|
||||
See [BUILDING.md] for instructions on how to build AFFiNE from source code.
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions from everyone.
|
||||
See [docs/contributing/tutorial.md](./docs/contributing/tutorial.md) for details.
|
||||
|
||||
## License
|
||||
|
||||
See [LICENSE] for details.
|
||||
|
||||
[license]: ./LICENSE
|
||||
[building.md]: ./docs/BUILDING.md
|
||||
[these people]: https://twitter.com/AffineOfficial/followers
|
||||
[update page]: https://affine.pro/blog?tag=Release%20Note
|
||||
[jobs available]: ./docs/jobs.md
|
||||
[latest packages]: https://github.com/toeverything/AFFiNE/pkgs/container/affine-self-hosted
|
||||
[contributor license agreement]: https://github.com/toeverything/affine/edit/master/.github/CLA.md
|
||||
[rust-version-icon]: https://img.shields.io/badge/Rust-1.70.0-dea584
|
||||
[stars-icon]: https://img.shields.io/github/stars/toeverything/AFFiNE.svg?style=flat&logo=github&colorB=red&label=stars
|
||||
[codecov]: https://codecov.io/gh/toeverything/affine/branch/master/graphs/badge.svg?branch=master
|
||||
[node-version-icon]: https://img.shields.io/badge/node-%3E=18.16.0-success
|
||||
[typescript-version-icon]: https://img.shields.io/github/package-json/dependency-version/toeverything/affine/dev/typescript
|
||||
[react-version-icon]: https://img.shields.io/github/package-json/dependency-version/toeverything/affine/dev/react?color=rgb%2897%2C%20218%2C%20251%29
|
||||
[blocksuite-icon]: https://img.shields.io/github/package-json/dependency-version/toeverything/AFFiNE/@blocksuite/store?color=6880ff&filename=apps%2Fweb%2Fpackage.json&label=blocksuite
|
||||
|
||||
14
apps/electron/.gitignore
vendored
Normal file
14
apps/electron/.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
*.autogen.*
|
||||
dist
|
||||
|
||||
resources/web-static
|
||||
|
||||
# yarn (3)
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
dev.json
|
||||
41
apps/electron/README.md
Normal file
41
apps/electron/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# AFFiNE Electron App
|
||||
|
||||
## Development
|
||||
|
||||
To run AFFiNE Desktop Client Application locally, run the following commands:
|
||||
|
||||
```sh
|
||||
# in repo root
|
||||
yarn install
|
||||
yarn dev
|
||||
|
||||
# in apps/electron
|
||||
yarn generate-assets
|
||||
yarn dev # or yarn prod for production build
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### better-sqlite3 error
|
||||
|
||||
When running tests or starting electron, you may encounter the following error:
|
||||
|
||||
> Error: The module 'apps/electron/node_modules/better-sqlite3/build/Release/better_sqlite3.node'
|
||||
|
||||
This is due to the fact that the `better-sqlite3` package is built for the Node.js version in Electron & in your machine. To fix this, run the following command based on different cases:
|
||||
|
||||
```sh
|
||||
# for running unit tests, we are not using Electron's node:
|
||||
yarn rebuild better-sqlite3
|
||||
|
||||
# for running Electron, we are using Electron's node:
|
||||
yarn postinstall
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
Most of the boilerplate code is generously borrowed from the following
|
||||
|
||||
- [vite-electron-builder](https://github.com/cawa-93/vite-electron-builder)
|
||||
- [Turborepo basic example](https://github.com/vercel/turborepo/tree/main/examples/basic)
|
||||
- [yerba](https://github.com/t3dotgg/yerba)
|
||||
4
apps/electron/dev-app-update.yml
Normal file
4
apps/electron/dev-app-update.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
owner: toeverything
|
||||
repo: AFFiNE
|
||||
provider: github
|
||||
private: false
|
||||
131
apps/electron/forge.config.js
Normal file
131
apps/electron/forge.config.js
Normal file
@@ -0,0 +1,131 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const { z } = require('zod');
|
||||
|
||||
const {
|
||||
utils: { fromBuildIdentifier },
|
||||
} = require('@electron-forge/core');
|
||||
|
||||
const path = require('node:path');
|
||||
|
||||
const ReleaseTypeSchema = z.enum(['stable', 'beta', 'canary', 'internal']);
|
||||
|
||||
const envBuildType = (process.env.BUILD_TYPE || 'canary').trim().toLowerCase();
|
||||
const buildType = ReleaseTypeSchema.parse(envBuildType);
|
||||
const stableBuild = buildType === 'stable';
|
||||
const productName = !stableBuild ? `AFFiNE-${buildType}` : 'AFFiNE';
|
||||
const icoPath = !stableBuild
|
||||
? `./resources/icons/icon_${buildType}.ico`
|
||||
: './resources/icons/icon.ico';
|
||||
const icnsPath = !stableBuild
|
||||
? `./resources/icons/icon_${buildType}.icns`
|
||||
: './resources/icons/icon.icns';
|
||||
|
||||
const arch =
|
||||
process.argv.indexOf('--arch') > 0
|
||||
? process.argv[process.argv.indexOf('--arch') + 1]
|
||||
: process.arch;
|
||||
|
||||
/**
|
||||
* @type {import('@electron-forge/shared-types').ForgeConfig}
|
||||
*/
|
||||
module.exports = {
|
||||
buildIdentifier: buildType,
|
||||
packagerConfig: {
|
||||
name: productName,
|
||||
appBundleId: fromBuildIdentifier({
|
||||
internal: 'pro.affine.internal',
|
||||
canary: 'pro.affine.canary',
|
||||
beta: 'pro.affine.beta',
|
||||
stable: 'pro.affine.app',
|
||||
}),
|
||||
icon: icnsPath,
|
||||
osxSign: {
|
||||
identity: 'Developer ID Application: TOEVERYTHING PTE. LTD.',
|
||||
'hardened-runtime': true,
|
||||
},
|
||||
osxNotarize: process.env.APPLE_ID
|
||||
? {
|
||||
tool: 'notarytool',
|
||||
appleId: process.env.APPLE_ID,
|
||||
appleIdPassword: process.env.APPLE_PASSWORD,
|
||||
teamId: process.env.APPLE_TEAM_ID,
|
||||
}
|
||||
: undefined,
|
||||
// do we need the following line?
|
||||
extraResource: ['./resources/app-update.yml'],
|
||||
},
|
||||
makers: [
|
||||
{
|
||||
name: '@electron-forge/maker-dmg',
|
||||
config: {
|
||||
format: 'ULFO',
|
||||
icon: icnsPath,
|
||||
name: 'AFFiNE',
|
||||
'icon-size': 128,
|
||||
background: './resources/icons/dmg-background.png',
|
||||
contents: [
|
||||
{
|
||||
x: 176,
|
||||
y: 192,
|
||||
type: 'file',
|
||||
path: path.resolve(
|
||||
__dirname,
|
||||
'out',
|
||||
buildType,
|
||||
`${productName}-darwin-${arch}`,
|
||||
`${productName}.app`
|
||||
),
|
||||
},
|
||||
{ x: 432, y: 192, type: 'link', path: '/Applications' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@electron-forge/maker-zip',
|
||||
config: {
|
||||
name: 'affine',
|
||||
iconUrl: icoPath,
|
||||
setupIcon: icoPath,
|
||||
platforms: ['darwin', 'linux', 'win32'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@electron-forge/maker-squirrel',
|
||||
config: {
|
||||
name: 'AFFiNE',
|
||||
setupIcon: icoPath,
|
||||
// loadingGif: './resources/icons/loading.gif',
|
||||
},
|
||||
},
|
||||
],
|
||||
hooks: {
|
||||
readPackageJson: async (_, packageJson) => {
|
||||
// we want different package name for canary build
|
||||
// so stable and canary will not share the same app data
|
||||
packageJson.productName = productName;
|
||||
},
|
||||
generateAssets: async (_, platform, arch) => {
|
||||
if (process.env.SKIP_GENERATE_ASSETS) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { $ } = await import('zx');
|
||||
|
||||
// TODO: right now we do not need the following
|
||||
// it is for octobase-node, but we dont use it for now.
|
||||
if (platform === 'darwin' && arch === 'arm64') {
|
||||
// In GitHub Actions runner, MacOS is always x64
|
||||
// we need to manually set TARGET to aarch64-apple-darwin
|
||||
process.env.TARGET = 'aarch64-apple-darwin';
|
||||
}
|
||||
|
||||
if (platform === 'win32') {
|
||||
$.shell = 'powershell.exe';
|
||||
$.prefix = '';
|
||||
}
|
||||
|
||||
// run yarn generate-assets
|
||||
await $`yarn generate-assets`;
|
||||
},
|
||||
},
|
||||
};
|
||||
7
apps/electron/layers/constraints.ts
Normal file
7
apps/electron/layers/constraints.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/consistent-type-imports */
|
||||
// This file contains the main process events
|
||||
// It will guide preload and main process on the correct event types and payloads
|
||||
|
||||
export type MainIPCHandlerMap = typeof import('./main/src/exposed').handlers;
|
||||
|
||||
export type MainIPCEventMap = typeof import('./main/src/exposed').events;
|
||||
135
apps/electron/layers/main/src/application-menu.ts
Normal file
135
apps/electron/layers/main/src/application-menu.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { app, Menu } from 'electron';
|
||||
|
||||
import { isMacOS } from '../../utils';
|
||||
import { subjects } from './events';
|
||||
import { checkForUpdatesAndNotify } from './handlers/updater';
|
||||
|
||||
// Unique id for menuitems
|
||||
const MENUITEM_NEW_PAGE = 'affine:new-page';
|
||||
|
||||
export function createApplicationMenu() {
|
||||
const isMac = isMacOS();
|
||||
|
||||
// Electron menu cannot be modified
|
||||
// You have to copy the complete default menu template event if you want to add a single custom item
|
||||
// See https://www.electronjs.org/docs/latest/api/menu#examples
|
||||
const template = [
|
||||
// { role: 'appMenu' }
|
||||
...(isMac
|
||||
? [
|
||||
{
|
||||
label: app.name,
|
||||
submenu: [
|
||||
{ role: 'about' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'services' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideOthers' },
|
||||
{ role: 'unhide' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'quit' },
|
||||
],
|
||||
},
|
||||
]
|
||||
: []),
|
||||
// { role: 'fileMenu' }
|
||||
{
|
||||
label: 'File',
|
||||
submenu: [
|
||||
{
|
||||
id: MENUITEM_NEW_PAGE,
|
||||
label: 'New Page',
|
||||
accelerator: isMac ? 'Cmd+N' : 'Ctrl+N',
|
||||
click: () => {
|
||||
subjects.applicationMenu.newPageAction.next();
|
||||
},
|
||||
},
|
||||
{ type: 'separator' },
|
||||
isMac ? { role: 'close' } : { role: 'quit' },
|
||||
],
|
||||
},
|
||||
// { role: 'editMenu' }
|
||||
{
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
{ role: 'undo' },
|
||||
{ role: 'redo' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'cut' },
|
||||
{ role: 'copy' },
|
||||
{ role: 'paste' },
|
||||
...(isMac
|
||||
? [
|
||||
{ role: 'pasteAndMatchStyle' },
|
||||
{ role: 'delete' },
|
||||
{ role: 'selectAll' },
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: 'Speech',
|
||||
submenu: [{ role: 'startSpeaking' }, { role: 'stopSpeaking' }],
|
||||
},
|
||||
]
|
||||
: [{ role: 'delete' }, { type: 'separator' }, { role: 'selectAll' }]),
|
||||
],
|
||||
},
|
||||
// { role: 'viewMenu' }
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{ role: 'reload' },
|
||||
{ role: 'forceReload' },
|
||||
{ role: 'toggleDevTools' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'resetZoom' },
|
||||
{ role: 'zoomIn' },
|
||||
{ role: 'zoomOut' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'togglefullscreen' },
|
||||
],
|
||||
},
|
||||
// { role: 'windowMenu' }
|
||||
{
|
||||
label: 'Window',
|
||||
submenu: [
|
||||
{ role: 'minimize' },
|
||||
{ role: 'zoom' },
|
||||
...(isMac
|
||||
? [
|
||||
{ type: 'separator' },
|
||||
{ role: 'front' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'window' },
|
||||
]
|
||||
: [{ role: 'close' }]),
|
||||
],
|
||||
},
|
||||
{
|
||||
role: 'help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { shell } = require('electron');
|
||||
await shell.openExternal('https://affine.pro/');
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Check for Updates',
|
||||
click: async () => {
|
||||
await checkForUpdatesAndNotify(true);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// @ts-ignore The snippet is copied from Electron official docs.
|
||||
// It's working as expected. No idea why it contains type errors.
|
||||
// Just ignore for now.
|
||||
const menu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(menu);
|
||||
|
||||
return menu;
|
||||
}
|
||||
12
apps/electron/layers/main/src/context.ts
Normal file
12
apps/electron/layers/main/src/context.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { app } from 'electron';
|
||||
|
||||
export const appContext = {
|
||||
get appName() {
|
||||
return app.name;
|
||||
},
|
||||
get appDataPath() {
|
||||
return app.getPath('sessionData');
|
||||
},
|
||||
};
|
||||
|
||||
export type AppContext = typeof appContext;
|
||||
22
apps/electron/layers/main/src/events/application-menu.ts
Normal file
22
apps/electron/layers/main/src/events/application-menu.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import type { MainEventListener } from './type';
|
||||
|
||||
export const applicationMenuSubjects = {
|
||||
newPageAction: new Subject<void>(),
|
||||
};
|
||||
|
||||
/**
|
||||
* Events triggered by application menu
|
||||
*/
|
||||
export const applicationMenuEvents = {
|
||||
/**
|
||||
* File -> New Page
|
||||
*/
|
||||
onNewPageAction: (fn: () => void) => {
|
||||
const sub = applicationMenuSubjects.newPageAction.subscribe(fn);
|
||||
return () => {
|
||||
sub.unsubscribe();
|
||||
};
|
||||
},
|
||||
} satisfies Record<string, MainEventListener>;
|
||||
38
apps/electron/layers/main/src/events/db.ts
Normal file
38
apps/electron/layers/main/src/events/db.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import type { MainEventListener } from './type';
|
||||
|
||||
interface DBFilePathMeta {
|
||||
workspaceId: string;
|
||||
path: string;
|
||||
realPath: string;
|
||||
}
|
||||
|
||||
export const dbSubjects = {
|
||||
// emit workspace ids
|
||||
dbFileMissing: new Subject<string>(),
|
||||
// emit workspace ids
|
||||
dbFileUpdate: new Subject<string>(),
|
||||
dbFilePathChange: new Subject<DBFilePathMeta>(),
|
||||
};
|
||||
|
||||
export const dbEvents = {
|
||||
onDBFileMissing: (fn: (workspaceId: string) => void) => {
|
||||
const sub = dbSubjects.dbFileMissing.subscribe(fn);
|
||||
return () => {
|
||||
sub.unsubscribe();
|
||||
};
|
||||
},
|
||||
onDBFileUpdate: (fn: (workspaceId: string) => void) => {
|
||||
const sub = dbSubjects.dbFileUpdate.subscribe(fn);
|
||||
return () => {
|
||||
sub.unsubscribe();
|
||||
};
|
||||
},
|
||||
onDBFilePathChange: (fn: (meta: DBFilePathMeta) => void) => {
|
||||
const sub = dbSubjects.dbFilePathChange.subscribe(fn);
|
||||
return () => {
|
||||
sub.unsubscribe();
|
||||
};
|
||||
},
|
||||
} satisfies Record<string, MainEventListener>;
|
||||
9
apps/electron/layers/main/src/events/index.ts
Normal file
9
apps/electron/layers/main/src/events/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export * from './register';
|
||||
|
||||
import { applicationMenuSubjects } from './application-menu';
|
||||
import { dbSubjects } from './db';
|
||||
|
||||
export const subjects = {
|
||||
db: dbSubjects,
|
||||
applicationMenu: applicationMenuSubjects,
|
||||
};
|
||||
32
apps/electron/layers/main/src/events/register.ts
Normal file
32
apps/electron/layers/main/src/events/register.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { app, BrowserWindow } from 'electron';
|
||||
|
||||
import { logger } from '../logger';
|
||||
import { applicationMenuEvents } from './application-menu';
|
||||
import { dbEvents } from './db';
|
||||
import { updaterEvents } from './updater';
|
||||
|
||||
export const allEvents = {
|
||||
db: dbEvents,
|
||||
updater: updaterEvents,
|
||||
applicationMenu: applicationMenuEvents,
|
||||
};
|
||||
|
||||
function getActiveWindows() {
|
||||
return BrowserWindow.getAllWindows().filter(win => !win.isDestroyed());
|
||||
}
|
||||
|
||||
export function registerEvents() {
|
||||
// register events
|
||||
for (const [namespace, namespaceEvents] of Object.entries(allEvents)) {
|
||||
for (const [key, eventRegister] of Object.entries(namespaceEvents)) {
|
||||
const subscription = eventRegister((...args: any) => {
|
||||
const chan = `${namespace}:${key}`;
|
||||
logger.info('[ipc-event]', chan, args);
|
||||
getActiveWindows().forEach(win => win.webContents.send(chan, ...args));
|
||||
});
|
||||
app.on('before-quit', () => {
|
||||
subscription();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
1
apps/electron/layers/main/src/events/type.ts
Normal file
1
apps/electron/layers/main/src/events/type.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type MainEventListener = (...args: any[]) => () => void;
|
||||
36
apps/electron/layers/main/src/events/updater.ts
Normal file
36
apps/electron/layers/main/src/events/updater.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
|
||||
import type { MainEventListener } from './type';
|
||||
|
||||
interface UpdateMeta {
|
||||
version: string;
|
||||
allowAutoUpdate: boolean;
|
||||
}
|
||||
|
||||
export const updaterSubjects = {
|
||||
// means it is ready for restart and install the new version
|
||||
updateAvailable: new Subject<UpdateMeta>(),
|
||||
updateReady: new Subject<UpdateMeta>(),
|
||||
downloadProgress: new BehaviorSubject<number>(0),
|
||||
};
|
||||
|
||||
export const updaterEvents = {
|
||||
onUpdateAvailable: (fn: (versionMeta: UpdateMeta) => void) => {
|
||||
const sub = updaterSubjects.updateAvailable.subscribe(fn);
|
||||
return () => {
|
||||
sub.unsubscribe();
|
||||
};
|
||||
},
|
||||
onUpdateReady: (fn: (versionMeta: UpdateMeta) => void) => {
|
||||
const sub = updaterSubjects.updateReady.subscribe(fn);
|
||||
return () => {
|
||||
sub.unsubscribe();
|
||||
};
|
||||
},
|
||||
onDownloadProgress: (fn: (progress: number) => void) => {
|
||||
const sub = updaterSubjects.downloadProgress.subscribe(fn);
|
||||
return () => {
|
||||
sub.unsubscribe();
|
||||
};
|
||||
},
|
||||
} satisfies Record<string, MainEventListener>;
|
||||
5
apps/electron/layers/main/src/exposed.ts
Normal file
5
apps/electron/layers/main/src/exposed.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { allEvents as events } from './events';
|
||||
import { allHandlers as handlers } from './handlers';
|
||||
|
||||
// this will be used by preload script to expose all handlers and events to the renderer process
|
||||
export { events, handlers };
|
||||
1
apps/electron/layers/main/src/handlers/__tests__/.gitignore
vendored
Normal file
1
apps/electron/layers/main/src/handlers/__tests__/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
tmp
|
||||
@@ -0,0 +1,501 @@
|
||||
import assert from 'node:assert';
|
||||
import path from 'node:path';
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import type { Subscription } from 'rxjs';
|
||||
import { v4 } from 'uuid';
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import type { MainIPCHandlerMap } from '../../../../constraints';
|
||||
|
||||
const registeredHandlers = new Map<
|
||||
string,
|
||||
((...args: any[]) => Promise<any>)[]
|
||||
>();
|
||||
|
||||
const delay = (ms: number) => new Promise(r => setTimeout(r, ms));
|
||||
|
||||
type WithoutFirstParameter<T> = T extends (_: any, ...args: infer P) => infer R
|
||||
? (...args: P) => R
|
||||
: T;
|
||||
|
||||
// common mock dispatcher for ipcMain.handle AND app.on
|
||||
// alternatively, we can use single parameter for T & F, eg, dispatch('workspace:list'),
|
||||
// however this is too hard to be typed correctly
|
||||
async function dispatch<
|
||||
T extends keyof MainIPCHandlerMap,
|
||||
F extends keyof MainIPCHandlerMap[T]
|
||||
>(
|
||||
namespace: T,
|
||||
functionName: F,
|
||||
// @ts-ignore
|
||||
...args: Parameters<WithoutFirstParameter<MainIPCHandlerMap[T][F]>>
|
||||
): // @ts-ignore
|
||||
ReturnType<MainIPCHandlerMap[T][F]> {
|
||||
// @ts-ignore
|
||||
const handlers = registeredHandlers.get(namespace + ':' + functionName);
|
||||
assert(handlers);
|
||||
|
||||
// we only care about the first handler here
|
||||
return await handlers[0](null, ...args);
|
||||
}
|
||||
|
||||
const SESSION_DATA_PATH = path.join(__dirname, './tmp', 'affine-test');
|
||||
|
||||
const browserWindow = {
|
||||
isDestroyed: () => {
|
||||
return false;
|
||||
},
|
||||
setWindowButtonVisibility: (_v: boolean) => {
|
||||
// will be stubbed later
|
||||
},
|
||||
webContents: {
|
||||
send: (_type: string, ..._args: any[]) => {
|
||||
// will be stubbed later
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const ipcMain = {
|
||||
handle: (key: string, callback: (...args: any[]) => Promise<any>) => {
|
||||
const handlers = registeredHandlers.get(key) || [];
|
||||
handlers.push(callback);
|
||||
registeredHandlers.set(key, handlers);
|
||||
},
|
||||
setMaxListeners: (_n: number) => {
|
||||
// noop
|
||||
},
|
||||
};
|
||||
|
||||
const nativeTheme = {
|
||||
themeSource: 'light',
|
||||
};
|
||||
|
||||
function compareBuffer(a: Uint8Array | null, b: Uint8Array | null) {
|
||||
if (
|
||||
(a === null && b === null) ||
|
||||
a === null ||
|
||||
b === null ||
|
||||
a.length !== b.length
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const electronModule = {
|
||||
app: {
|
||||
getPath: (name: string) => {
|
||||
assert(name === 'sessionData');
|
||||
return SESSION_DATA_PATH;
|
||||
},
|
||||
name: 'affine-test',
|
||||
on: (name: string, callback: (...args: any[]) => any) => {
|
||||
const handlers = registeredHandlers.get(name) || [];
|
||||
handlers.push(callback);
|
||||
registeredHandlers.set(name, handlers);
|
||||
},
|
||||
addEventListener: (...args: any[]) => {
|
||||
// @ts-ignore
|
||||
electronModule.app.on(...args);
|
||||
},
|
||||
removeEventListener: () => {},
|
||||
},
|
||||
BrowserWindow: {
|
||||
getAllWindows: () => {
|
||||
return [browserWindow];
|
||||
},
|
||||
},
|
||||
nativeTheme: nativeTheme,
|
||||
ipcMain,
|
||||
shell: {} as Partial<Electron.Shell>,
|
||||
dialog: {} as Partial<Electron.Dialog>,
|
||||
};
|
||||
|
||||
// dynamically import handlers so that we can inject local variables to mocks
|
||||
vi.doMock('electron', () => {
|
||||
return electronModule;
|
||||
});
|
||||
|
||||
let connectableSubscription: Subscription;
|
||||
|
||||
beforeEach(async () => {
|
||||
const { registerHandlers } = await import('../register');
|
||||
registerHandlers();
|
||||
|
||||
// should also register events
|
||||
const { registerEvents } = await import('../../events');
|
||||
registerEvents();
|
||||
await fs.mkdirp(SESSION_DATA_PATH);
|
||||
const { database$ } = await import('../db/ensure-db');
|
||||
|
||||
connectableSubscription = database$.connect();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// reset registered handlers
|
||||
registeredHandlers.get('before-quit')?.forEach(fn => fn());
|
||||
|
||||
connectableSubscription.unsubscribe();
|
||||
|
||||
await fs.remove(SESSION_DATA_PATH);
|
||||
});
|
||||
|
||||
describe('ensureSQLiteDB', () => {
|
||||
test('should create db file on connection if it does not exist', async () => {
|
||||
const id = v4();
|
||||
const { ensureSQLiteDB } = await import('../db/ensure-db');
|
||||
const workspaceDB = await ensureSQLiteDB(id);
|
||||
const file = workspaceDB.path;
|
||||
const fileExists = await fs.pathExists(file);
|
||||
expect(fileExists).toBe(true);
|
||||
});
|
||||
|
||||
test('when db file is removed', async () => {
|
||||
// stub webContents.send
|
||||
const sendSpy = vi.spyOn(browserWindow.webContents, 'send');
|
||||
const id = v4();
|
||||
const { ensureSQLiteDB } = await import('../db/ensure-db');
|
||||
let workspaceDB = await ensureSQLiteDB(id);
|
||||
const file = workspaceDB.path;
|
||||
const fileExists = await fs.pathExists(file);
|
||||
expect(fileExists).toBe(true);
|
||||
|
||||
// Can't remove file on Windows, because the sqlite is still holding the file handle
|
||||
if (process.platform === 'win32') {
|
||||
return;
|
||||
}
|
||||
|
||||
await fs.remove(file);
|
||||
|
||||
// wait for 2000ms for file watcher to detect file removal
|
||||
await delay(2000);
|
||||
|
||||
expect(sendSpy).toBeCalledWith('db:onDBFileMissing', id);
|
||||
|
||||
// ensureSQLiteDB should recreate the db file
|
||||
workspaceDB = await ensureSQLiteDB(id);
|
||||
const fileExists2 = await fs.pathExists(file);
|
||||
expect(fileExists2).toBe(true);
|
||||
sendSpy.mockRestore();
|
||||
});
|
||||
|
||||
test('when db file is updated', async () => {
|
||||
const id = v4();
|
||||
const { ensureSQLiteDB } = await import('../db/ensure-db');
|
||||
const { dbSubjects } = await import('../../events/db');
|
||||
const workspaceDB = await ensureSQLiteDB(id);
|
||||
const file = workspaceDB.path;
|
||||
const fileExists = await fs.pathExists(file);
|
||||
expect(fileExists).toBe(true);
|
||||
const dbUpdateSpy = vi.spyOn(dbSubjects.dbFileUpdate, 'next');
|
||||
await delay(100);
|
||||
// writes some data to the db file
|
||||
await fs.appendFile(file, 'random-data', { encoding: 'binary' });
|
||||
// write again
|
||||
await fs.appendFile(file, 'random-data', { encoding: 'binary' });
|
||||
|
||||
// wait for 2000ms for file watcher to detect file change
|
||||
await delay(2000);
|
||||
|
||||
expect(dbUpdateSpy).toBeCalledWith(id);
|
||||
dbUpdateSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
|
||||
describe('workspace handlers', () => {
|
||||
test('list all workspace ids', async () => {
|
||||
const ids = [v4(), v4()];
|
||||
const { ensureSQLiteDB } = await import('../db/ensure-db');
|
||||
await Promise.all(ids.map(id => ensureSQLiteDB(id)));
|
||||
const list = await dispatch('workspace', 'list');
|
||||
expect(list.map(([id]) => id).sort()).toEqual(ids.sort());
|
||||
});
|
||||
|
||||
test('delete workspace', async () => {
|
||||
// @TODO dispatch is hanging on Windows
|
||||
if (process.platform === 'win32') {
|
||||
return;
|
||||
}
|
||||
const ids = [v4(), v4()];
|
||||
const { ensureSQLiteDB } = await import('../db/ensure-db');
|
||||
await Promise.all(ids.map(id => ensureSQLiteDB(id)));
|
||||
await dispatch('workspace', 'delete', ids[1]);
|
||||
const list = await dispatch('workspace', 'list');
|
||||
expect(list.map(([id]) => id)).toEqual([ids[0]]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('UI handlers', () => {
|
||||
test('theme-change', async () => {
|
||||
await dispatch('ui', 'handleThemeChange', 'dark');
|
||||
expect(nativeTheme.themeSource).toBe('dark');
|
||||
await dispatch('ui', 'handleThemeChange', 'light');
|
||||
expect(nativeTheme.themeSource).toBe('light');
|
||||
});
|
||||
|
||||
test('sidebar-visibility-change (macOS)', async () => {
|
||||
vi.stubGlobal('process', { platform: 'darwin' });
|
||||
const setWindowButtonVisibility = vi.fn();
|
||||
browserWindow.setWindowButtonVisibility = setWindowButtonVisibility;
|
||||
await dispatch('ui', 'handleSidebarVisibilityChange', true);
|
||||
expect(setWindowButtonVisibility).toBeCalledWith(true);
|
||||
await dispatch('ui', 'handleSidebarVisibilityChange', false);
|
||||
expect(setWindowButtonVisibility).toBeCalledWith(false);
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
test('sidebar-visibility-change (non-macOS)', async () => {
|
||||
vi.stubGlobal('process', { platform: 'linux' });
|
||||
const setWindowButtonVisibility = vi.fn();
|
||||
browserWindow.setWindowButtonVisibility = setWindowButtonVisibility;
|
||||
await dispatch('ui', 'handleSidebarVisibilityChange', true);
|
||||
expect(setWindowButtonVisibility).not.toBeCalled();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
});
|
||||
|
||||
describe('db handlers', () => {
|
||||
test('apply doc and get doc updates', async () => {
|
||||
const workspaceId = v4();
|
||||
const bin = await dispatch('db', 'getDocAsUpdates', workspaceId);
|
||||
// ? is this a good test?
|
||||
expect(bin.every((byte: number) => byte === 0)).toBe(true);
|
||||
|
||||
const ydoc = new Y.Doc();
|
||||
const ytext = ydoc.getText('test');
|
||||
ytext.insert(0, 'hello world');
|
||||
const bin2 = Y.encodeStateAsUpdate(ydoc);
|
||||
|
||||
await dispatch('db', 'applyDocUpdate', workspaceId, bin2);
|
||||
|
||||
const bin3 = await dispatch('db', 'getDocAsUpdates', workspaceId);
|
||||
const ydoc2 = new Y.Doc();
|
||||
Y.applyUpdate(ydoc2, bin3);
|
||||
const ytext2 = ydoc2.getText('test');
|
||||
expect(ytext2.toString()).toBe('hello world');
|
||||
});
|
||||
|
||||
test('get non existent blob', async () => {
|
||||
const workspaceId = v4();
|
||||
const bin = await dispatch('db', 'getBlob', workspaceId, 'non-existent-id');
|
||||
expect(bin).toBeNull();
|
||||
});
|
||||
|
||||
test('list blobs (empty)', async () => {
|
||||
const workspaceId = v4();
|
||||
const list = await dispatch('db', 'getPersistedBlobs', workspaceId);
|
||||
expect(list).toEqual([]);
|
||||
});
|
||||
|
||||
test('CRUD blobs', async () => {
|
||||
const testBin = new Uint8Array([1, 2, 3, 4, 5]);
|
||||
const testBin2 = new Uint8Array([6, 7, 8, 9, 10]);
|
||||
const workspaceId = 'test-workspace-id';
|
||||
|
||||
// add blob
|
||||
await dispatch('db', 'addBlob', workspaceId, 'testBin', testBin);
|
||||
|
||||
// get blob
|
||||
expect(
|
||||
compareBuffer(
|
||||
await dispatch('db', 'getBlob', workspaceId, 'testBin'),
|
||||
testBin
|
||||
)
|
||||
).toBe(true);
|
||||
|
||||
// add another blob
|
||||
await dispatch('db', 'addBlob', workspaceId, 'testBin2', testBin2);
|
||||
expect(
|
||||
compareBuffer(
|
||||
await dispatch('db', 'getBlob', workspaceId, 'testBin2'),
|
||||
testBin2
|
||||
)
|
||||
).toBe(true);
|
||||
|
||||
// list blobs
|
||||
let lists = await dispatch('db', 'getPersistedBlobs', workspaceId);
|
||||
expect(lists).toHaveLength(2);
|
||||
expect(lists).toContain('testBin');
|
||||
expect(lists).toContain('testBin2');
|
||||
|
||||
// delete blob
|
||||
await dispatch('db', 'deleteBlob', workspaceId, 'testBin');
|
||||
lists = await dispatch('db', 'getPersistedBlobs', workspaceId);
|
||||
expect(lists).toEqual(['testBin2']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('dialog handlers', () => {
|
||||
test('revealDBFile', async () => {
|
||||
const mockShowItemInFolder = vi.fn();
|
||||
electronModule.shell.showItemInFolder = mockShowItemInFolder;
|
||||
|
||||
const id = v4();
|
||||
const { ensureSQLiteDB } = await import('../db/ensure-db');
|
||||
const db = await ensureSQLiteDB(id);
|
||||
|
||||
await dispatch('dialog', 'revealDBFile', id);
|
||||
expect(mockShowItemInFolder).toBeCalledWith(db.path);
|
||||
});
|
||||
|
||||
test('saveDBFileAs (skipped)', async () => {
|
||||
const mockShowSaveDialog = vi.fn(() => {
|
||||
return { filePath: undefined };
|
||||
}) as any;
|
||||
const mockShowItemInFolder = vi.fn();
|
||||
electronModule.dialog.showSaveDialog = mockShowSaveDialog;
|
||||
electronModule.shell.showItemInFolder = mockShowItemInFolder;
|
||||
|
||||
const id = v4();
|
||||
const { ensureSQLiteDB } = await import('../db/ensure-db');
|
||||
await ensureSQLiteDB(id);
|
||||
|
||||
await dispatch('dialog', 'saveDBFileAs', id);
|
||||
expect(mockShowSaveDialog).toBeCalled();
|
||||
expect(mockShowItemInFolder).not.toBeCalled();
|
||||
electronModule.dialog = {};
|
||||
electronModule.shell = {};
|
||||
});
|
||||
|
||||
test('saveDBFileAs', async () => {
|
||||
const newSavedPath = path.join(SESSION_DATA_PATH, 'saved-to');
|
||||
const mockShowSaveDialog = vi.fn(() => {
|
||||
return { filePath: newSavedPath };
|
||||
}) as any;
|
||||
const mockShowItemInFolder = vi.fn();
|
||||
electronModule.dialog.showSaveDialog = mockShowSaveDialog;
|
||||
electronModule.shell.showItemInFolder = mockShowItemInFolder;
|
||||
|
||||
const id = v4();
|
||||
const { ensureSQLiteDB } = await import('../db/ensure-db');
|
||||
await ensureSQLiteDB(id);
|
||||
|
||||
await dispatch('dialog', 'saveDBFileAs', id);
|
||||
expect(mockShowSaveDialog).toBeCalled();
|
||||
expect(mockShowItemInFolder).toBeCalledWith(newSavedPath);
|
||||
|
||||
// check if file is saved to new path
|
||||
expect(await fs.exists(newSavedPath)).toBe(true);
|
||||
});
|
||||
|
||||
test('loadDBFile (skipped)', async () => {
|
||||
const mockShowOpenDialog = vi.fn(() => {
|
||||
return { filePaths: undefined };
|
||||
}) as any;
|
||||
electronModule.dialog.showOpenDialog = mockShowOpenDialog;
|
||||
|
||||
const res = await dispatch('dialog', 'loadDBFile');
|
||||
expect(mockShowOpenDialog).toBeCalled();
|
||||
expect(res.canceled).toBe(true);
|
||||
});
|
||||
|
||||
test('loadDBFile (error, in app-data)', async () => {
|
||||
const mockShowOpenDialog = vi.fn(() => {
|
||||
return {
|
||||
filePaths: [path.join(SESSION_DATA_PATH, 'workspaces')],
|
||||
};
|
||||
}) as any;
|
||||
electronModule.dialog.showOpenDialog = mockShowOpenDialog;
|
||||
|
||||
const res = await dispatch('dialog', 'loadDBFile');
|
||||
expect(mockShowOpenDialog).toBeCalled();
|
||||
expect(res.error).toBe('DB_FILE_PATH_INVALID');
|
||||
});
|
||||
|
||||
test('loadDBFile (error, not a valid db file)', async () => {
|
||||
// create a random db file
|
||||
const basePath = path.join(SESSION_DATA_PATH, 'random-path');
|
||||
const dbPath = path.join(basePath, 'xxx.db');
|
||||
await fs.ensureDir(basePath);
|
||||
await fs.writeFile(dbPath, 'hello world');
|
||||
|
||||
const mockShowOpenDialog = vi.fn(() => {
|
||||
return { filePaths: [dbPath] };
|
||||
}) as any;
|
||||
electronModule.dialog.showOpenDialog = mockShowOpenDialog;
|
||||
|
||||
const res = await dispatch('dialog', 'loadDBFile');
|
||||
expect(mockShowOpenDialog).toBeCalled();
|
||||
expect(res.error).toBe('DB_FILE_INVALID');
|
||||
|
||||
electronModule.dialog = {};
|
||||
});
|
||||
|
||||
test('loadDBFile', async () => {
|
||||
// we use ensureSQLiteDB to create a valid db file
|
||||
const id = v4();
|
||||
const { ensureSQLiteDB } = await import('../db/ensure-db');
|
||||
const db = await ensureSQLiteDB(id);
|
||||
|
||||
// copy db file to dbPath
|
||||
const basePath = path.join(SESSION_DATA_PATH, 'random-path');
|
||||
const originDBFilePath = path.join(basePath, 'xxx.db');
|
||||
await fs.ensureDir(basePath);
|
||||
await fs.copyFile(db.path, originDBFilePath);
|
||||
|
||||
// on Windows, we skip this test because we can't delete the db file
|
||||
if (process.platform === 'win32') {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove db
|
||||
await fs.remove(db.path);
|
||||
|
||||
// try load originDBFilePath
|
||||
const mockShowOpenDialog = vi.fn(() => {
|
||||
return { filePaths: [originDBFilePath] };
|
||||
}) as any;
|
||||
electronModule.dialog.showOpenDialog = mockShowOpenDialog;
|
||||
|
||||
const res = await dispatch('dialog', 'loadDBFile');
|
||||
expect(mockShowOpenDialog).toBeCalled();
|
||||
expect(res.workspaceId).not.toBeUndefined();
|
||||
|
||||
const importedDb = await ensureSQLiteDB(res.workspaceId!);
|
||||
expect(await fs.realpath(importedDb.path)).toBe(originDBFilePath);
|
||||
expect(importedDb.path).not.toBe(originDBFilePath);
|
||||
|
||||
// try load it again, will trigger error (db file already loaded)
|
||||
const res2 = await dispatch('dialog', 'loadDBFile');
|
||||
expect(res2.error).toBe('DB_FILE_ALREADY_LOADED');
|
||||
});
|
||||
|
||||
test('moveDBFile', async () => {
|
||||
const newPath = path.join(SESSION_DATA_PATH, 'xxx');
|
||||
const mockShowSaveDialog = vi.fn(() => {
|
||||
return { filePath: newPath };
|
||||
}) as any;
|
||||
electronModule.dialog.showSaveDialog = mockShowSaveDialog;
|
||||
|
||||
const id = v4();
|
||||
const { ensureSQLiteDB } = await import('../db/ensure-db');
|
||||
await ensureSQLiteDB(id);
|
||||
const res = await dispatch('dialog', 'moveDBFile', id);
|
||||
expect(mockShowSaveDialog).toBeCalled();
|
||||
expect(res.filePath).toBe(newPath);
|
||||
electronModule.dialog = {};
|
||||
});
|
||||
|
||||
test('moveDBFile (skipped)', async () => {
|
||||
const mockShowSaveDialog = vi.fn(() => {
|
||||
return { filePath: null };
|
||||
}) as any;
|
||||
electronModule.dialog.showSaveDialog = mockShowSaveDialog;
|
||||
|
||||
const id = v4();
|
||||
const { ensureSQLiteDB } = await import('../db/ensure-db');
|
||||
await ensureSQLiteDB(id);
|
||||
|
||||
const res = await dispatch('dialog', 'moveDBFile', id);
|
||||
expect(mockShowSaveDialog).toBeCalled();
|
||||
expect(res.filePath).toBe(undefined);
|
||||
electronModule.dialog = {};
|
||||
});
|
||||
});
|
||||
160
apps/electron/layers/main/src/handlers/db/ensure-db.ts
Normal file
160
apps/electron/layers/main/src/handlers/db/ensure-db.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import type { NotifyEvent } from '@affine/native/event';
|
||||
import { createFSWatcher } from '@affine/native/fs-watcher';
|
||||
import { app } from 'electron';
|
||||
import {
|
||||
connectable,
|
||||
defer,
|
||||
from,
|
||||
fromEvent,
|
||||
identity,
|
||||
lastValueFrom,
|
||||
Observable,
|
||||
ReplaySubject,
|
||||
Subject,
|
||||
} from 'rxjs';
|
||||
import {
|
||||
debounceTime,
|
||||
exhaustMap,
|
||||
filter,
|
||||
groupBy,
|
||||
ignoreElements,
|
||||
mergeMap,
|
||||
shareReplay,
|
||||
startWith,
|
||||
switchMap,
|
||||
take,
|
||||
takeUntil,
|
||||
tap,
|
||||
} from 'rxjs/operators';
|
||||
|
||||
import { appContext } from '../../context';
|
||||
import { subjects } from '../../events';
|
||||
import { logger } from '../../logger';
|
||||
import { ts } from '../../utils';
|
||||
import type { WorkspaceSQLiteDB } from './sqlite';
|
||||
import { openWorkspaceDatabase } from './sqlite';
|
||||
|
||||
const databaseInput$ = new Subject<string>();
|
||||
export const databaseConnector$ = new ReplaySubject<WorkspaceSQLiteDB>();
|
||||
|
||||
const groupedDatabaseInput$ = databaseInput$.pipe(groupBy(identity));
|
||||
|
||||
export const database$ = connectable(
|
||||
groupedDatabaseInput$.pipe(
|
||||
mergeMap(workspaceDatabase$ =>
|
||||
workspaceDatabase$.pipe(
|
||||
// only open the first db with the same workspaceId, and emit it to the downstream
|
||||
exhaustMap(workspaceId => {
|
||||
logger.info('[ensureSQLiteDB] open db connection', workspaceId);
|
||||
return from(openWorkspaceDatabase(appContext, workspaceId)).pipe(
|
||||
switchMap(db => {
|
||||
return startWatchingDBFile(db).pipe(
|
||||
// ignore all events and only emit the db to the downstream
|
||||
ignoreElements(),
|
||||
startWith(db)
|
||||
);
|
||||
})
|
||||
);
|
||||
}),
|
||||
shareReplay(1)
|
||||
)
|
||||
),
|
||||
tap({
|
||||
complete: () => {
|
||||
logger.info('[FSWatcher] close all watchers');
|
||||
createFSWatcher().close();
|
||||
},
|
||||
})
|
||||
),
|
||||
{
|
||||
connector: () => databaseConnector$,
|
||||
resetOnDisconnect: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const databaseConnectableSubscription = database$.connect();
|
||||
|
||||
// 1. File delete
|
||||
// 2. File move
|
||||
// - on Linux, it's `type: { modify: { kind: 'rename', mode: 'from' } }`
|
||||
// - on Windows, it's `type: { remove: { kind: 'any' } }`
|
||||
// - on macOS, it's `type: { modify: { kind: 'rename', mode: 'any' } }`
|
||||
export function isRemoveOrMoveEvent(event: NotifyEvent) {
|
||||
return (
|
||||
typeof event.type === 'object' &&
|
||||
('remove' in event.type ||
|
||||
('modify' in event.type &&
|
||||
event.type.modify.kind === 'rename' &&
|
||||
(event.type.modify.mode === 'from' ||
|
||||
event.type.modify.mode === 'any')))
|
||||
);
|
||||
}
|
||||
|
||||
// if we removed the file, we will stop watching it
|
||||
function startWatchingDBFile(db: WorkspaceSQLiteDB) {
|
||||
const FSWatcher = createFSWatcher();
|
||||
return new Observable<NotifyEvent>(subscriber => {
|
||||
logger.info('[FSWatcher] start watching db file', db.workspaceId);
|
||||
const subscription = FSWatcher.watch(db.path, {
|
||||
recursive: false,
|
||||
}).subscribe(
|
||||
event => {
|
||||
logger.info('[FSWatcher]', event);
|
||||
subscriber.next(event);
|
||||
// remove file or move file, complete the observable and close db
|
||||
if (isRemoveOrMoveEvent(event)) {
|
||||
subscriber.complete();
|
||||
}
|
||||
},
|
||||
err => {
|
||||
subscriber.error(err);
|
||||
}
|
||||
);
|
||||
return () => {
|
||||
// destroy on unsubscribe
|
||||
logger.info('[FSWatcher] cleanup db file watcher', db.workspaceId);
|
||||
db.destroy();
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}).pipe(
|
||||
debounceTime(1000),
|
||||
filter(event => !isRemoveOrMoveEvent(event)),
|
||||
tap({
|
||||
next: () => {
|
||||
logger.info(
|
||||
'[FSWatcher] db file changed on disk',
|
||||
db.workspaceId,
|
||||
ts() - db.lastUpdateTime,
|
||||
'ms'
|
||||
);
|
||||
db.reconnectDB();
|
||||
subjects.db.dbFileUpdate.next(db.workspaceId);
|
||||
},
|
||||
complete: () => {
|
||||
// todo: there is still a possibility that the file is deleted
|
||||
// but we didn't get the event soon enough and another event tries to
|
||||
// access the db
|
||||
logger.info('[FSWatcher] db file missing', db.workspaceId);
|
||||
subjects.db.dbFileMissing.next(db.workspaceId);
|
||||
db.destroy();
|
||||
},
|
||||
}),
|
||||
takeUntil(defer(() => fromEvent(app, 'before-quit')))
|
||||
);
|
||||
}
|
||||
|
||||
export function ensureSQLiteDB(id: string) {
|
||||
const deferValue = lastValueFrom(
|
||||
database$.pipe(
|
||||
filter(db => db.workspaceId === id && db.db.open),
|
||||
take(1),
|
||||
tap({
|
||||
error: err => {
|
||||
logger.error('[ensureSQLiteDB] error', err);
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
databaseInput$.next(id);
|
||||
return deferValue;
|
||||
}
|
||||
42
apps/electron/layers/main/src/handlers/db/index.ts
Normal file
42
apps/electron/layers/main/src/handlers/db/index.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import fs from 'fs-extra';
|
||||
|
||||
import { appContext } from '../../context';
|
||||
import type { NamespaceHandlers } from '../type';
|
||||
import { ensureSQLiteDB } from './ensure-db';
|
||||
|
||||
export const dbHandlers = {
|
||||
getDocAsUpdates: async (_, id: string) => {
|
||||
const workspaceDB = await ensureSQLiteDB(id);
|
||||
return workspaceDB.getDocAsUpdates();
|
||||
},
|
||||
applyDocUpdate: async (_, id: string, update: Uint8Array) => {
|
||||
const workspaceDB = await ensureSQLiteDB(id);
|
||||
return workspaceDB.applyUpdate(update);
|
||||
},
|
||||
addBlob: async (_, workspaceId: string, key: string, data: Uint8Array) => {
|
||||
const workspaceDB = await ensureSQLiteDB(workspaceId);
|
||||
return workspaceDB.addBlob(key, data);
|
||||
},
|
||||
getBlob: async (_, workspaceId: string, key: string) => {
|
||||
const workspaceDB = await ensureSQLiteDB(workspaceId);
|
||||
return workspaceDB.getBlob(key);
|
||||
},
|
||||
deleteBlob: async (_, workspaceId: string, key: string) => {
|
||||
const workspaceDB = await ensureSQLiteDB(workspaceId);
|
||||
return workspaceDB.deleteBlob(key);
|
||||
},
|
||||
getPersistedBlobs: async (_, workspaceId: string) => {
|
||||
const workspaceDB = await ensureSQLiteDB(workspaceId);
|
||||
return workspaceDB.getPersistentBlobKeys();
|
||||
},
|
||||
getDefaultStorageLocation: async () => {
|
||||
return appContext.appDataPath;
|
||||
},
|
||||
getDBFilePath: async (_, workspaceId: string) => {
|
||||
const workspaceDB = await ensureSQLiteDB(workspaceId);
|
||||
return {
|
||||
path: workspaceDB.path,
|
||||
realPath: await fs.realpath(workspaceDB.path),
|
||||
};
|
||||
},
|
||||
} satisfies NamespaceHandlers;
|
||||
247
apps/electron/layers/main/src/handlers/db/sqlite.ts
Normal file
247
apps/electron/layers/main/src/handlers/db/sqlite.ts
Normal file
@@ -0,0 +1,247 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import type { Database } from 'better-sqlite3';
|
||||
import sqlite from 'better-sqlite3';
|
||||
import fs from 'fs-extra';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import type { AppContext } from '../../context';
|
||||
import { dbSubjects } from '../../events/db';
|
||||
import { logger } from '../../logger';
|
||||
import { ts } from '../../utils';
|
||||
|
||||
const schemas = [
|
||||
`CREATE TABLE IF NOT EXISTS "updates" (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
data BLOB NOT NULL,
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS "blobs" (
|
||||
key TEXT PRIMARY KEY NOT NULL,
|
||||
data BLOB NOT NULL,
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
|
||||
)`,
|
||||
];
|
||||
|
||||
interface UpdateRow {
|
||||
id: number;
|
||||
data: Buffer;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
interface BlobRow {
|
||||
key: string;
|
||||
data: Buffer;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
const SQLITE_ORIGIN = Symbol('sqlite-origin');
|
||||
|
||||
export class WorkspaceSQLiteDB {
|
||||
db: Database;
|
||||
ydoc = new Y.Doc();
|
||||
firstConnect = false;
|
||||
lastUpdateTime = ts();
|
||||
destroyed = false;
|
||||
|
||||
constructor(public path: string, public workspaceId: string) {
|
||||
this.db = this.reconnectDB();
|
||||
}
|
||||
|
||||
// release resources
|
||||
destroy = () => {
|
||||
this.db?.close();
|
||||
this.ydoc.destroy();
|
||||
};
|
||||
|
||||
getWorkspaceName = () => {
|
||||
return this.ydoc.getMap('space:meta').get('name') as string;
|
||||
};
|
||||
|
||||
reconnectDB = () => {
|
||||
logger.log('[WorkspaceSQLiteDB] open db', this.workspaceId);
|
||||
if (this.db) {
|
||||
this.db.close();
|
||||
}
|
||||
|
||||
fs.realpath(this.path)
|
||||
.then(realPath => {
|
||||
dbSubjects.dbFilePathChange.next({
|
||||
workspaceId: this.workspaceId,
|
||||
path: this.path,
|
||||
realPath,
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
// skip error
|
||||
});
|
||||
|
||||
// use cached version?
|
||||
const db = (this.db = sqlite(this.path));
|
||||
db.exec(schemas.join(';'));
|
||||
|
||||
if (!this.firstConnect) {
|
||||
this.ydoc.on('update', (update: Uint8Array, origin) => {
|
||||
if (origin !== SQLITE_ORIGIN) {
|
||||
this.addUpdateToSQLite(update);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Y.transact(this.ydoc, () => {
|
||||
const updates = this.getUpdates();
|
||||
updates.forEach(update => {
|
||||
// give SQLITE_ORIGIN to skip self update
|
||||
Y.applyUpdate(this.ydoc, update.data, SQLITE_ORIGIN);
|
||||
});
|
||||
});
|
||||
|
||||
this.lastUpdateTime = ts();
|
||||
|
||||
if (this.firstConnect) {
|
||||
logger.info('db reconnected', this.workspaceId);
|
||||
} else {
|
||||
logger.info('db connected', this.workspaceId);
|
||||
}
|
||||
|
||||
this.firstConnect = true;
|
||||
|
||||
return db;
|
||||
};
|
||||
|
||||
getDocAsUpdates = () => {
|
||||
return Y.encodeStateAsUpdate(this.ydoc);
|
||||
};
|
||||
|
||||
// non-blocking and use yDoc to validate the update
|
||||
// after that, the update is added to the db
|
||||
applyUpdate = (data: Uint8Array) => {
|
||||
Y.applyUpdate(this.ydoc, data);
|
||||
|
||||
// todo: trim the updates when the number of records is too large
|
||||
// 1. store the current ydoc state in the db
|
||||
// 2. then delete the old updates
|
||||
// yjs-idb will always trim the db for the first time after DB is loaded
|
||||
this.lastUpdateTime = ts();
|
||||
logger.debug('applyUpdate', this.workspaceId, this.lastUpdateTime);
|
||||
};
|
||||
|
||||
addBlob = (key: string, data: Uint8Array) => {
|
||||
this.lastUpdateTime = ts();
|
||||
try {
|
||||
const statement = this.db.prepare(
|
||||
'INSERT INTO blobs (key, data) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET data = ?'
|
||||
);
|
||||
statement.run(key, data, data);
|
||||
return key;
|
||||
} catch (error) {
|
||||
logger.error('addBlob', error);
|
||||
}
|
||||
};
|
||||
|
||||
getBlob = (key: string) => {
|
||||
try {
|
||||
const statement = this.db.prepare('SELECT data FROM blobs WHERE key = ?');
|
||||
const row = statement.get(key) as BlobRow;
|
||||
if (!row) {
|
||||
return null;
|
||||
}
|
||||
return row.data;
|
||||
} catch (error) {
|
||||
logger.error('getBlob', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
deleteBlob = (key: string) => {
|
||||
this.lastUpdateTime = ts();
|
||||
try {
|
||||
const statement = this.db.prepare('DELETE FROM blobs WHERE key = ?');
|
||||
statement.run(key);
|
||||
} catch (error) {
|
||||
logger.error('deleteBlob', error);
|
||||
}
|
||||
};
|
||||
|
||||
getPersistentBlobKeys = () => {
|
||||
try {
|
||||
const statement = this.db.prepare('SELECT key FROM blobs');
|
||||
const rows = statement.all() as BlobRow[];
|
||||
return rows.map(row => row.key);
|
||||
} catch (error) {
|
||||
logger.error('getPersistentBlobKeys', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
private getUpdates = () => {
|
||||
try {
|
||||
const statement = this.db.prepare('SELECT * FROM updates');
|
||||
const rows = statement.all() as UpdateRow[];
|
||||
return rows;
|
||||
} catch (error) {
|
||||
logger.error('getUpdates', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
// batch write instead write per key stroke?
|
||||
private addUpdateToSQLite = (data: Uint8Array) => {
|
||||
try {
|
||||
const start = performance.now();
|
||||
const statement = this.db.prepare(
|
||||
'INSERT INTO updates (data) VALUES (?)'
|
||||
);
|
||||
statement.run(data);
|
||||
logger.debug(
|
||||
'addUpdateToSQLite',
|
||||
this.workspaceId,
|
||||
'length:',
|
||||
data.length,
|
||||
performance.now() - start,
|
||||
'ms'
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error('addUpdateToSQLite', error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export async function getWorkspaceDBPath(
|
||||
context: AppContext,
|
||||
workspaceId: string
|
||||
) {
|
||||
const basePath = path.join(context.appDataPath, 'workspaces', workspaceId);
|
||||
await fs.ensureDir(basePath);
|
||||
return path.join(basePath, 'storage.db');
|
||||
}
|
||||
|
||||
export async function openWorkspaceDatabase(
|
||||
context: AppContext,
|
||||
workspaceId: string
|
||||
) {
|
||||
const dbPath = await getWorkspaceDBPath(context, workspaceId);
|
||||
return new WorkspaceSQLiteDB(dbPath, workspaceId);
|
||||
}
|
||||
|
||||
export function isValidDBFile(path: string) {
|
||||
let db: Database | null = null;
|
||||
try {
|
||||
db = sqlite(path);
|
||||
// check if db has two tables, one for updates and onefor blobs
|
||||
const statement = db.prepare(
|
||||
`SELECT name FROM sqlite_schema WHERE type='table'`
|
||||
);
|
||||
const rows = statement.all() as { name: string }[];
|
||||
const tableNames = rows.map(row => row.name);
|
||||
if (!tableNames.includes('updates') || !tableNames.includes('blobs')) {
|
||||
return false;
|
||||
}
|
||||
db.close();
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.error('isValidDBFile', error);
|
||||
db?.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
323
apps/electron/layers/main/src/handlers/dialog/dialog.ts
Normal file
323
apps/electron/layers/main/src/handlers/dialog/dialog.ts
Normal file
@@ -0,0 +1,323 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import { dialog, shell } from 'electron';
|
||||
import fs from 'fs-extra';
|
||||
import { nanoid } from 'nanoid';
|
||||
|
||||
import { appContext } from '../../context';
|
||||
import { logger } from '../../logger';
|
||||
import { ensureSQLiteDB, isRemoveOrMoveEvent } from '../db/ensure-db';
|
||||
import type { WorkspaceSQLiteDB } from '../db/sqlite';
|
||||
import { getWorkspaceDBPath, isValidDBFile } from '../db/sqlite';
|
||||
import { listWorkspaces } from '../workspace/workspace';
|
||||
|
||||
// NOTE:
|
||||
// we are using native dialogs because HTML dialogs do not give full file paths
|
||||
|
||||
export async function revealDBFile(workspaceId: string) {
|
||||
const workspaceDB = await ensureSQLiteDB(workspaceId);
|
||||
shell.showItemInFolder(await fs.realpath(workspaceDB.path));
|
||||
}
|
||||
|
||||
// provide a backdoor to set dialog path for testing in playwright
|
||||
interface FakeDialogResult {
|
||||
canceled?: boolean;
|
||||
filePath?: string;
|
||||
filePaths?: string[];
|
||||
}
|
||||
|
||||
// result will be used in the next call to showOpenDialog
|
||||
// if it is being read once, it will be reset to undefined
|
||||
let fakeDialogResult: FakeDialogResult | undefined = undefined;
|
||||
|
||||
function getFakedResult() {
|
||||
const result = fakeDialogResult;
|
||||
fakeDialogResult = undefined;
|
||||
return result;
|
||||
}
|
||||
|
||||
export function setFakeDialogResult(result: FakeDialogResult | undefined) {
|
||||
fakeDialogResult = result;
|
||||
// for convenience, we will fill filePaths with filePath if it is not set
|
||||
if (result?.filePaths === undefined && result?.filePath !== undefined) {
|
||||
result.filePaths = [result.filePath];
|
||||
}
|
||||
}
|
||||
|
||||
const ErrorMessages = [
|
||||
'DB_FILE_ALREADY_LOADED',
|
||||
'DB_FILE_PATH_INVALID',
|
||||
'DB_FILE_INVALID',
|
||||
'FILE_ALREADY_EXISTS',
|
||||
'UNKNOWN_ERROR',
|
||||
] as const;
|
||||
|
||||
type ErrorMessage = (typeof ErrorMessages)[number];
|
||||
|
||||
interface SaveDBFileResult {
|
||||
filePath?: string;
|
||||
canceled?: boolean;
|
||||
error?: ErrorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when the user clicks the "Save" button in the "Save Workspace" dialog.
|
||||
*
|
||||
* It will just copy the file to the given path
|
||||
*/
|
||||
export async function saveDBFileAs(
|
||||
workspaceId: string
|
||||
): Promise<SaveDBFileResult> {
|
||||
try {
|
||||
const db = await ensureSQLiteDB(workspaceId);
|
||||
const ret =
|
||||
getFakedResult() ??
|
||||
(await dialog.showSaveDialog({
|
||||
properties: ['showOverwriteConfirmation'],
|
||||
title: 'Save Workspace',
|
||||
showsTagField: false,
|
||||
buttonLabel: 'Save',
|
||||
defaultPath: `${db.getWorkspaceName()}_${workspaceId}.db`,
|
||||
message: 'Save Workspace as a SQLite Database file',
|
||||
}));
|
||||
const filePath = ret.filePath;
|
||||
if (ret.canceled || !filePath) {
|
||||
return {
|
||||
canceled: true,
|
||||
};
|
||||
}
|
||||
|
||||
await fs.copyFile(db.path, filePath);
|
||||
logger.log('saved', filePath);
|
||||
shell.showItemInFolder(filePath);
|
||||
return { filePath };
|
||||
} catch (err) {
|
||||
logger.error('saveDBFileAs', err);
|
||||
return {
|
||||
error: 'UNKNOWN_ERROR',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
interface SelectDBFileLocationResult {
|
||||
filePath?: string;
|
||||
error?: ErrorMessage;
|
||||
canceled?: boolean;
|
||||
}
|
||||
|
||||
export async function selectDBFileLocation(): Promise<SelectDBFileLocationResult> {
|
||||
try {
|
||||
const ret =
|
||||
getFakedResult() ??
|
||||
(await dialog.showSaveDialog({
|
||||
properties: ['showOverwriteConfirmation'],
|
||||
title: 'Set database location',
|
||||
showsTagField: false,
|
||||
buttonLabel: 'Select',
|
||||
defaultPath: `workspace-storage.db`,
|
||||
message: "Select a location to store the workspace's database file",
|
||||
}));
|
||||
const filePath = ret.filePath;
|
||||
if (ret.canceled || !filePath) {
|
||||
return {
|
||||
canceled: true,
|
||||
};
|
||||
}
|
||||
// the same db file cannot be loaded twice
|
||||
if (await dbFileAlreadyLoaded(filePath)) {
|
||||
return {
|
||||
error: 'DB_FILE_ALREADY_LOADED',
|
||||
};
|
||||
}
|
||||
return { filePath };
|
||||
} catch (err) {
|
||||
logger.error('selectDBFileLocation', err);
|
||||
return {
|
||||
error: (err as any).message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
interface LoadDBFileResult {
|
||||
workspaceId?: string;
|
||||
error?: ErrorMessage;
|
||||
canceled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when the user clicks the "Load" button in the "Load Workspace" dialog.
|
||||
*
|
||||
* It will
|
||||
* - symlink the source db file to a new workspace id to app-data
|
||||
* - return the new workspace id
|
||||
*
|
||||
* eg, it will create a new folder in app-data:
|
||||
* <app-data>/<app-name>/workspaces/<workspace-id>/storage.db
|
||||
*
|
||||
* On the renderer side, after the UI got a new workspace id, it will
|
||||
* update the local workspace id list and then connect to it.
|
||||
*
|
||||
*/
|
||||
export async function loadDBFile(): Promise<LoadDBFileResult> {
|
||||
try {
|
||||
const ret =
|
||||
getFakedResult() ??
|
||||
(await dialog.showOpenDialog({
|
||||
properties: ['openFile'],
|
||||
title: 'Load Workspace',
|
||||
buttonLabel: 'Load',
|
||||
filters: [
|
||||
{
|
||||
name: 'SQLite Database',
|
||||
// do we want to support other file format?
|
||||
extensions: ['db'],
|
||||
},
|
||||
],
|
||||
message: 'Load Workspace from a SQLite Database file',
|
||||
}));
|
||||
const filePath = ret.filePaths?.[0];
|
||||
if (ret.canceled || !filePath) {
|
||||
logger.info('loadDBFile canceled');
|
||||
return { canceled: true };
|
||||
}
|
||||
|
||||
// the imported file should not be in app data dir
|
||||
if (filePath.startsWith(path.join(appContext.appDataPath, 'workspaces'))) {
|
||||
logger.warn('loadDBFile: db file in app data dir');
|
||||
return { error: 'DB_FILE_PATH_INVALID' };
|
||||
}
|
||||
|
||||
if (await dbFileAlreadyLoaded(filePath)) {
|
||||
logger.warn('loadDBFile: db file already loaded');
|
||||
return { error: 'DB_FILE_ALREADY_LOADED' };
|
||||
}
|
||||
|
||||
if (!isValidDBFile(filePath)) {
|
||||
// TODO: report invalid db file error?
|
||||
return { error: 'DB_FILE_INVALID' }; // invalid db file
|
||||
}
|
||||
|
||||
// symlink the db file to a new workspace id
|
||||
const workspaceId = nanoid(10);
|
||||
const linkedFilePath = await getWorkspaceDBPath(appContext, workspaceId);
|
||||
|
||||
await fs.ensureDir(path.join(appContext.appDataPath, 'workspaces'));
|
||||
|
||||
await fs.symlink(filePath, linkedFilePath, 'file');
|
||||
logger.info(`loadDBFile, symlink: ${filePath} -> ${linkedFilePath}`);
|
||||
|
||||
return { workspaceId };
|
||||
} catch (err) {
|
||||
logger.error('loadDBFile', err);
|
||||
return {
|
||||
error: 'UNKNOWN_ERROR',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
interface MoveDBFileResult {
|
||||
filePath?: string;
|
||||
error?: ErrorMessage;
|
||||
canceled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when the user clicks the "Move" button in the "Move Workspace Storage" setting.
|
||||
*
|
||||
* It will
|
||||
* - move the source db file to a new location
|
||||
* - symlink the new location to the old db file
|
||||
* - return the new file path
|
||||
*/
|
||||
export async function moveDBFile(
|
||||
workspaceId: string,
|
||||
dbFileLocation?: string
|
||||
): Promise<MoveDBFileResult> {
|
||||
let db: WorkspaceSQLiteDB | null = null;
|
||||
try {
|
||||
const { moveFile, FsWatcher } = await import('@affine/native');
|
||||
db = await ensureSQLiteDB(workspaceId);
|
||||
// get the real file path of db
|
||||
const realpath = await fs.realpath(db.path);
|
||||
const isLink = realpath !== db.path;
|
||||
const watcher = FsWatcher.watch(realpath, { recursive: false });
|
||||
const waitForRemove = new Promise<void>(resolve => {
|
||||
const subscription = watcher.subscribe(event => {
|
||||
if (isRemoveOrMoveEvent(event)) {
|
||||
subscription.unsubscribe();
|
||||
// resolve after FSWatcher in `database$` is fired
|
||||
setImmediate(() => {
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
const newFilePath =
|
||||
dbFileLocation ??
|
||||
(
|
||||
getFakedResult() ??
|
||||
(await dialog.showSaveDialog({
|
||||
properties: ['showOverwriteConfirmation'],
|
||||
title: 'Move Workspace Storage',
|
||||
showsTagField: false,
|
||||
buttonLabel: 'Save',
|
||||
defaultPath: realpath,
|
||||
message: 'Move Workspace storage file',
|
||||
}))
|
||||
).filePath;
|
||||
|
||||
// skips if
|
||||
// - user canceled the dialog
|
||||
// - user selected the same file
|
||||
// - user selected the same file in the link file in app data dir
|
||||
if (!newFilePath || newFilePath === realpath || db.path === newFilePath) {
|
||||
return {
|
||||
canceled: true,
|
||||
};
|
||||
}
|
||||
|
||||
db.db.close();
|
||||
|
||||
if (await fs.pathExists(newFilePath)) {
|
||||
return {
|
||||
error: 'FILE_ALREADY_EXISTS',
|
||||
};
|
||||
}
|
||||
|
||||
if (isLink) {
|
||||
// remove the old link to unblock new link
|
||||
await fs.unlink(db.path);
|
||||
}
|
||||
|
||||
logger.info(`[moveDBFile] move ${realpath} -> ${newFilePath}`);
|
||||
|
||||
await moveFile(realpath, newFilePath);
|
||||
|
||||
await fs.ensureSymlink(newFilePath, db.path, 'file');
|
||||
logger.info(`[moveDBFile] symlink: ${realpath} -> ${newFilePath}`);
|
||||
// wait for the file move event emits to the FileWatcher in database$ in ensure-db.ts
|
||||
// so that the db will be destroyed and we can call the `ensureSQLiteDB` in the next step
|
||||
// or the FileWatcher will continue listen on the `realpath` and emit file change events
|
||||
// then the database will reload while receiving these events; and the moved database file will be recreated while reloading database
|
||||
await waitForRemove;
|
||||
logger.info(`removed`);
|
||||
await ensureSQLiteDB(workspaceId);
|
||||
|
||||
return {
|
||||
filePath: newFilePath,
|
||||
};
|
||||
} catch (err) {
|
||||
db?.destroy();
|
||||
logger.error('[moveDBFile]', err);
|
||||
return {
|
||||
error: 'UNKNOWN_ERROR',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function dbFileAlreadyLoaded(path: string) {
|
||||
const meta = await listWorkspaces(appContext);
|
||||
const realpath = await fs.realpath(path);
|
||||
const paths = meta.map(m => m[1].realpath);
|
||||
return paths.includes(realpath);
|
||||
}
|
||||
33
apps/electron/layers/main/src/handlers/dialog/index.ts
Normal file
33
apps/electron/layers/main/src/handlers/dialog/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { NamespaceHandlers } from '../type';
|
||||
import {
|
||||
loadDBFile,
|
||||
moveDBFile,
|
||||
revealDBFile,
|
||||
saveDBFileAs,
|
||||
selectDBFileLocation,
|
||||
setFakeDialogResult,
|
||||
} from './dialog';
|
||||
|
||||
export const dialogHandlers = {
|
||||
revealDBFile: async (_, workspaceId: string) => {
|
||||
return revealDBFile(workspaceId);
|
||||
},
|
||||
loadDBFile: async () => {
|
||||
return loadDBFile();
|
||||
},
|
||||
saveDBFileAs: async (_, workspaceId: string) => {
|
||||
return saveDBFileAs(workspaceId);
|
||||
},
|
||||
moveDBFile: (_, workspaceId: string, dbFileLocation?: string) => {
|
||||
return moveDBFile(workspaceId, dbFileLocation);
|
||||
},
|
||||
selectDBFileLocation: async () => {
|
||||
return selectDBFileLocation();
|
||||
},
|
||||
setFakeDialogResult: async (
|
||||
_,
|
||||
result: Parameters<typeof setFakeDialogResult>[0]
|
||||
) => {
|
||||
return setFakeDialogResult(result);
|
||||
},
|
||||
} satisfies NamespaceHandlers;
|
||||
1
apps/electron/layers/main/src/handlers/index.ts
Normal file
1
apps/electron/layers/main/src/handlers/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './register';
|
||||
65
apps/electron/layers/main/src/handlers/register.ts
Normal file
65
apps/electron/layers/main/src/handlers/register.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { ipcMain } from 'electron';
|
||||
|
||||
import { getLogFilePath, logger, revealLogFile } from '../logger';
|
||||
import { dbHandlers } from './db';
|
||||
import { dialogHandlers } from './dialog';
|
||||
import { uiHandlers } from './ui';
|
||||
import { updaterHandlers } from './updater';
|
||||
import { workspaceHandlers } from './workspace';
|
||||
|
||||
type IsomorphicHandler = (
|
||||
e: Electron.IpcMainInvokeEvent,
|
||||
...args: any[]
|
||||
) => Promise<any>;
|
||||
|
||||
type NamespaceHandlers = {
|
||||
[key: string]: IsomorphicHandler;
|
||||
};
|
||||
|
||||
export const debugHandlers = {
|
||||
revealLogFile: async () => {
|
||||
return revealLogFile();
|
||||
},
|
||||
logFilePath: async () => {
|
||||
return getLogFilePath();
|
||||
},
|
||||
};
|
||||
|
||||
// Note: all of these handlers will be the single-source-of-truth for the apis exposed to the renderer process
|
||||
export const allHandlers = {
|
||||
workspace: workspaceHandlers,
|
||||
ui: uiHandlers,
|
||||
db: dbHandlers,
|
||||
dialog: dialogHandlers,
|
||||
debug: debugHandlers,
|
||||
updater: updaterHandlers,
|
||||
} satisfies Record<string, NamespaceHandlers>;
|
||||
|
||||
export const registerHandlers = () => {
|
||||
// TODO: listen to namespace instead of individual event types
|
||||
ipcMain.setMaxListeners(100);
|
||||
for (const [namespace, namespaceHandlers] of Object.entries(allHandlers)) {
|
||||
for (const [key, handler] of Object.entries(namespaceHandlers)) {
|
||||
const chan = `${namespace}:${key}`;
|
||||
ipcMain.handle(chan, async (e, ...args) => {
|
||||
const start = performance.now();
|
||||
try {
|
||||
const result = await handler(e, ...args);
|
||||
logger.info(
|
||||
'[ipc-api]',
|
||||
chan,
|
||||
args.filter(
|
||||
arg => typeof arg !== 'function' && typeof arg !== 'object'
|
||||
),
|
||||
'-',
|
||||
(performance.now() - start).toFixed(2),
|
||||
'ms'
|
||||
);
|
||||
return result;
|
||||
} catch (error) {
|
||||
logger.error('[ipc]', chan, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
8
apps/electron/layers/main/src/handlers/type.ts
Normal file
8
apps/electron/layers/main/src/handlers/type.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export type IsomorphicHandler = (
|
||||
e: Electron.IpcMainInvokeEvent,
|
||||
...args: any[]
|
||||
) => Promise<any>;
|
||||
|
||||
export type NamespaceHandlers = {
|
||||
[key: string]: IsomorphicHandler;
|
||||
};
|
||||
58
apps/electron/layers/main/src/handlers/ui/google-auth.ts
Normal file
58
apps/electron/layers/main/src/handlers/ui/google-auth.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { app, BrowserWindow, shell } from 'electron';
|
||||
import { parse } from 'url';
|
||||
|
||||
import { logger } from '../../logger';
|
||||
|
||||
const redirectUri = 'https://affine.pro/client/auth-callback';
|
||||
|
||||
export const oauthEndpoint = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${process.env.AFFINE_GOOGLE_CLIENT_ID}&redirect_uri=${redirectUri}&response_type=code&scope=openid https://www.googleapis.com/auth/userinfo.email profile&access_type=offline&customParameters={"prompt":"select_account"}`;
|
||||
|
||||
const tokenEndpoint = 'https://oauth2.googleapis.com/token';
|
||||
|
||||
export const getExchangeTokenParams = (code: string) => {
|
||||
const postData = {
|
||||
code,
|
||||
client_id: process.env.AFFINE_GOOGLE_CLIENT_ID || '',
|
||||
client_secret: process.env.AFFINE_GOOGLE_CLIENT_SECRET || '',
|
||||
redirect_uri: redirectUri,
|
||||
grant_type: 'authorization_code',
|
||||
};
|
||||
const requestInit: RequestInit = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams(postData).toString(),
|
||||
};
|
||||
return { requestInit, url: tokenEndpoint };
|
||||
};
|
||||
|
||||
export function getGoogleOauthCode() {
|
||||
shell.openExternal(oauthEndpoint);
|
||||
|
||||
return new Promise<ReturnType<typeof getExchangeTokenParams>>(
|
||||
(resolve, reject) => {
|
||||
const handleOpenUrl = async (_: any, url: string) => {
|
||||
const mainWindow = BrowserWindow.getAllWindows().find(
|
||||
w => !w.isDestroyed()
|
||||
);
|
||||
const urlObj = parse(url.replace('??', '?'), true);
|
||||
if (!mainWindow || !url.startsWith('affine://auth-callback')) return;
|
||||
const code = urlObj.query['code'] as string;
|
||||
if (!code) return;
|
||||
|
||||
logger.info('google sign in code received from callback', code);
|
||||
|
||||
app.removeListener('open-url', handleOpenUrl);
|
||||
resolve(getExchangeTokenParams(code));
|
||||
};
|
||||
|
||||
app.on('open-url', handleOpenUrl);
|
||||
|
||||
setTimeout(() => {
|
||||
reject(new Error('Timed out'));
|
||||
app.removeListener('open-url', handleOpenUrl);
|
||||
}, 30000);
|
||||
}
|
||||
);
|
||||
}
|
||||
42
apps/electron/layers/main/src/handlers/ui/index.ts
Normal file
42
apps/electron/layers/main/src/handlers/ui/index.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { app, BrowserWindow, nativeTheme } from 'electron';
|
||||
|
||||
import { isMacOS } from '../../../../utils';
|
||||
import type { NamespaceHandlers } from '../type';
|
||||
import { getGoogleOauthCode } from './google-auth';
|
||||
|
||||
export const uiHandlers = {
|
||||
handleThemeChange: async (_, theme: (typeof nativeTheme)['themeSource']) => {
|
||||
nativeTheme.themeSource = theme;
|
||||
},
|
||||
handleSidebarVisibilityChange: async (_, visible: boolean) => {
|
||||
if (isMacOS()) {
|
||||
const windows = BrowserWindow.getAllWindows();
|
||||
windows.forEach(w => {
|
||||
// hide window buttons when sidebar is not visible
|
||||
w.setWindowButtonVisibility(visible);
|
||||
});
|
||||
}
|
||||
},
|
||||
handleMinimizeApp: async () => {
|
||||
const windows = BrowserWindow.getAllWindows();
|
||||
windows.forEach(w => {
|
||||
w.minimize();
|
||||
});
|
||||
},
|
||||
handleMaximizeApp: async () => {
|
||||
const windows = BrowserWindow.getAllWindows();
|
||||
windows.forEach(w => {
|
||||
if (w.isMaximized()) {
|
||||
w.unmaximize();
|
||||
} else {
|
||||
w.maximize();
|
||||
}
|
||||
});
|
||||
},
|
||||
handleCloseApp: async () => {
|
||||
app.quit();
|
||||
},
|
||||
getGoogleOauthCode: async () => {
|
||||
return getGoogleOauthCode();
|
||||
},
|
||||
} satisfies NamespaceHandlers;
|
||||
18
apps/electron/layers/main/src/handlers/updater/index.ts
Normal file
18
apps/electron/layers/main/src/handlers/updater/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { app } from 'electron';
|
||||
|
||||
import type { NamespaceHandlers } from '../type';
|
||||
import { checkForUpdatesAndNotify, quitAndInstall } from './updater';
|
||||
|
||||
export const updaterHandlers = {
|
||||
currentVersion: async () => {
|
||||
return app.getVersion();
|
||||
},
|
||||
quitAndInstall: async () => {
|
||||
return quitAndInstall();
|
||||
},
|
||||
checkForUpdatesAndNotify: async () => {
|
||||
return checkForUpdatesAndNotify(true);
|
||||
},
|
||||
} satisfies NamespaceHandlers;
|
||||
|
||||
export * from './updater';
|
||||
100
apps/electron/layers/main/src/handlers/updater/updater.ts
Normal file
100
apps/electron/layers/main/src/handlers/updater/updater.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { app } from 'electron';
|
||||
import type { AppUpdater } from 'electron-updater';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { isMacOS } from '../../../../utils';
|
||||
import { updaterSubjects } from '../../events/updater';
|
||||
import { logger } from '../../logger';
|
||||
|
||||
export const ReleaseTypeSchema = z.enum([
|
||||
'stable',
|
||||
'beta',
|
||||
'canary',
|
||||
'internal',
|
||||
]);
|
||||
|
||||
export const envBuildType = (process.env.BUILD_TYPE || 'canary')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
export const buildType = ReleaseTypeSchema.parse(envBuildType);
|
||||
const mode = process.env.NODE_ENV;
|
||||
const isDev = mode === 'development';
|
||||
|
||||
let _autoUpdater: AppUpdater | null = null;
|
||||
|
||||
export const quitAndInstall = async () => {
|
||||
_autoUpdater?.quitAndInstall();
|
||||
};
|
||||
|
||||
let lastCheckTime = 0;
|
||||
export const checkForUpdatesAndNotify = async (force = true) => {
|
||||
if (!_autoUpdater) {
|
||||
return; // ?
|
||||
}
|
||||
// check every 30 minutes (1800 seconds) at most
|
||||
if (force || lastCheckTime + 1000 * 1800 < Date.now()) {
|
||||
lastCheckTime = Date.now();
|
||||
return _autoUpdater.checkForUpdatesAndNotify();
|
||||
}
|
||||
};
|
||||
|
||||
export const registerUpdater = async () => {
|
||||
// require it will cause some side effects and will break generate-main-exposed-meta,
|
||||
// so we wrap it in a function
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const { autoUpdater } = require('electron-updater');
|
||||
|
||||
_autoUpdater = autoUpdater;
|
||||
|
||||
if (!_autoUpdater) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: support auto update on windows and linux
|
||||
const allowAutoUpdate = isMacOS();
|
||||
|
||||
_autoUpdater.autoDownload = false;
|
||||
_autoUpdater.allowPrerelease = buildType !== 'stable';
|
||||
_autoUpdater.autoInstallOnAppQuit = false;
|
||||
_autoUpdater.autoRunAppAfterInstall = true;
|
||||
_autoUpdater.setFeedURL({
|
||||
channel: buildType,
|
||||
provider: 'github',
|
||||
repo: buildType !== 'internal' ? 'AFFiNE' : 'AFFiNE-Releases',
|
||||
owner: 'toeverything',
|
||||
releaseType: buildType === 'stable' ? 'release' : 'prerelease',
|
||||
});
|
||||
|
||||
// register events for checkForUpdatesAndNotify
|
||||
_autoUpdater.on('update-available', info => {
|
||||
if (allowAutoUpdate) {
|
||||
_autoUpdater!.downloadUpdate();
|
||||
logger.info('Update available, downloading...', info);
|
||||
}
|
||||
updaterSubjects.updateAvailable.next({
|
||||
version: info.version,
|
||||
allowAutoUpdate,
|
||||
});
|
||||
});
|
||||
_autoUpdater.on('download-progress', e => {
|
||||
logger.info(`Download progress: ${e.percent}`);
|
||||
updaterSubjects.downloadProgress.next(e.percent);
|
||||
});
|
||||
_autoUpdater.on('update-downloaded', e => {
|
||||
updaterSubjects.updateReady.next({
|
||||
version: e.version,
|
||||
allowAutoUpdate,
|
||||
});
|
||||
// I guess we can skip it?
|
||||
// updaterSubjects.clientDownloadProgress.next(100);
|
||||
logger.info('Update downloaded, ready to install');
|
||||
});
|
||||
_autoUpdater.on('error', e => {
|
||||
logger.error('Error while updating client', e);
|
||||
});
|
||||
_autoUpdater.forceDevUpdateConfig = isDev;
|
||||
|
||||
app.on('activate', async () => {
|
||||
await checkForUpdatesAndNotify(false);
|
||||
});
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user