mirror of
https://github.com/wekan/wekan.git
synced 2026-11-08 11:25:19 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54d26a0eb7 | ||
|
|
016d637fc8 | ||
|
|
ac7cf31910 | ||
|
|
05f1f0a032 | ||
|
|
6b6edf96e8 | ||
|
|
9dd295079b | ||
|
|
8263734f5a | ||
|
|
bd806736d4 | ||
|
|
ecdae60a8a | ||
|
|
8bc83c849b | ||
|
|
2e6e9ee95e | ||
|
|
3163ccfc1f | ||
|
|
5b35bb74dd | ||
|
|
7ad71c52a0 | ||
|
|
80f0b9187e | ||
|
|
0f572b174a | ||
|
|
2016d15f2a | ||
|
|
f38e152e80 | ||
|
|
f03463e7de | ||
|
|
a2dc757360 | ||
|
|
584fc34eae | ||
|
|
5d53ed050c | ||
|
|
55c6b48c16 | ||
|
|
e05c4fe014 | ||
|
|
670ae80ff8 | ||
|
|
39d426be79 | ||
|
|
3c4a465637 | ||
|
|
1c00da28ce | ||
|
|
d37d57f9a0 | ||
|
|
8076b75df3 | ||
|
|
261c131a4e | ||
|
|
b31c667da4 | ||
|
|
39fd5ef713 | ||
|
|
f3e5847950 | ||
|
|
6156bad07c | ||
|
|
e09307cda1 | ||
|
|
d4ae151e28 | ||
|
|
36bd87f17f | ||
|
|
cee0c9c534 | ||
|
|
d6ed6f1fb9 | ||
|
|
1f5692db36 | ||
|
|
a5ee3bd4c1 | ||
|
|
844c7d7e01 | ||
|
|
fa7d2584df | ||
|
|
3f12a11af7 | ||
|
|
ea4afae17f | ||
|
|
95dc456b2d | ||
|
|
494fa0cd02 | ||
|
|
f2ab9c3b94 | ||
|
|
d982d293c6 | ||
|
|
09a77a4b9b | ||
|
|
334d54484b | ||
|
|
4101e8fd41 | ||
|
|
58cbbe54e2 | ||
|
|
3a58c6f728 | ||
|
|
60bf582e5d | ||
|
|
956c81481f | ||
|
|
4913f4abbd | ||
|
|
b4e56c1913 | ||
|
|
c355188c76 | ||
|
|
b254949dc8 | ||
|
|
6568268b24 | ||
|
|
8958467c84 | ||
|
|
41c3508e6c | ||
|
|
fbd087f353 | ||
|
|
e760d27a70 | ||
|
|
d71973fc49 | ||
|
|
b849a427f4 | ||
|
|
43416dc088 | ||
|
|
b0aa15bda0 | ||
|
|
54ce3015e8 | ||
|
|
b585dc0c24 | ||
|
|
baaa3d2441 | ||
|
|
ba5ecaf14b | ||
|
|
e1b13e6881 | ||
|
|
d55b2d3e8b | ||
|
|
ecd853dc1d | ||
|
|
78da3e8151 | ||
|
|
d2dd1b16af | ||
|
|
c7111728bb | ||
|
|
b7ab631eaf | ||
|
|
7392a364ba | ||
|
|
930292acee | ||
|
|
83fb620c4d | ||
|
|
d884509051 | ||
|
|
a048569b8d | ||
|
|
3f4dcaec53 | ||
|
|
3a6abad835 | ||
|
|
4d2951ae20 | ||
|
|
8080fe713a | ||
|
|
e9e4e4f70d | ||
|
|
79cd465585 | ||
|
|
8537af5599 | ||
|
|
d97b6a85e2 | ||
|
|
6a4a6ef58f | ||
|
|
b22d173312 | ||
|
|
e18f028be5 | ||
|
|
4f7d28637e | ||
|
|
6d9fdf8b28 | ||
|
|
9289edc3ec | ||
|
|
98654d3115 | ||
|
|
cdc0722b15 | ||
|
|
5d57766dbf | ||
|
|
58d8563637 | ||
|
|
c084137e8a | ||
|
|
953d8f7c13 | ||
|
|
ab5e2f7f5c | ||
|
|
8889067ace | ||
|
|
552ac0855a | ||
|
|
b01a7bf824 | ||
|
|
d17dadcf77 | ||
|
|
6d4c68a74a | ||
|
|
55a9b50597 | ||
|
|
770e585a96 | ||
|
|
3af5e3b4ec | ||
|
|
37b0c1b154 | ||
|
|
160e5635b2 | ||
|
|
0cc30e72b5 | ||
|
|
fc8178dd8f | ||
|
|
c5fdeb47fa | ||
|
|
63238a687a | ||
|
|
fd0f766095 | ||
|
|
b87b0aca1c | ||
|
|
3c8468201b | ||
|
|
e217f1215a | ||
|
|
0e15bbaab0 | ||
|
|
e13f4f6c29 | ||
|
|
458be25bdf | ||
|
|
94b59bef01 | ||
|
|
400f8b9d36 | ||
|
|
b4459a79e2 | ||
|
|
afa0f78a74 | ||
|
|
346267eb5c | ||
|
|
5779499ef2 | ||
|
|
201c905f3f | ||
|
|
7f781be34e | ||
|
|
28b98e7dee | ||
|
|
caa58a39b2 | ||
|
|
f0d6d48ef9 | ||
|
|
8c4b292a92 | ||
|
|
5b128a1c63 | ||
|
|
9c1e53fe62 | ||
|
|
e87cf70be6 | ||
|
|
fb5adf635f | ||
|
|
47ea978108 | ||
|
|
a4761a582f | ||
|
|
e39f2889d3 | ||
|
|
8897dafa4d | ||
|
|
bee69b103b | ||
|
|
c9f8655d2b | ||
|
|
cb8fd6b86b | ||
|
|
d4ef9284b7 | ||
|
|
fe73307c39 | ||
|
|
19f740f509 | ||
|
|
09d02df29a | ||
|
|
ab11bad210 | ||
|
|
a4de36e5af | ||
|
|
23ed8d927f | ||
|
|
0dde1245d5 | ||
|
|
e8d9bf9f11 | ||
|
|
c9e90cd592 | ||
|
|
ba4637e558 | ||
|
|
8e7369e0bc | ||
|
|
1f6658a0d3 | ||
|
|
d43968d888 | ||
|
|
2227503bd3 | ||
|
|
a0c14a4c7f | ||
|
|
c8431a3016 | ||
|
|
773a1c2ddf | ||
|
|
0741a78475 | ||
|
|
acc0b37a1a | ||
|
|
95f0e045a5 | ||
|
|
b204dc409d | ||
|
|
5e7577e3df | ||
|
|
196c56769b | ||
|
|
b9ae16a443 | ||
|
|
37a1d3e204 | ||
|
|
ced5263a47 | ||
|
|
84414711b7 | ||
|
|
9b213cdf48 | ||
|
|
3e1865b3dd | ||
|
|
254f4c9d44 | ||
|
|
0eada96a2b | ||
|
|
150b6e0e59 | ||
|
|
2232885bcd | ||
|
|
ef4c8a62cd | ||
|
|
da420d2dd3 | ||
|
|
db2c782aec | ||
|
|
47e007b1b1 | ||
|
|
847f85a5eb | ||
|
|
9c1a5a3dcb | ||
|
|
d1150280fd | ||
|
|
66ba7fde03 | ||
|
|
986516e8ed | ||
|
|
62cccae192 | ||
|
|
ef5ccf3fb0 | ||
|
|
0fb4408c57 | ||
|
|
a44adf6b8e | ||
|
|
452331c943 | ||
|
|
073fb8469a | ||
|
|
a990e7f202 | ||
|
|
e5e38d881f | ||
|
|
de7948b4e9 | ||
|
|
1f5cb0d134 | ||
|
|
a35f1cab3f | ||
|
|
9e1cf4c35b | ||
|
|
1760601457 | ||
|
|
b6fcb6a3d3 | ||
|
|
3a339e1975 | ||
|
|
721805b800 | ||
|
|
290aeae38b | ||
|
|
3e38abc0d6 | ||
|
|
62db6d74d1 | ||
|
|
2b94d87dcc | ||
|
|
b104edeef1 | ||
|
|
970ac9dc5f | ||
|
|
fc0c3c815b | ||
|
|
f50b4786fe | ||
|
|
4c40bbf9f5 | ||
|
|
ef381207cc | ||
|
|
8e9093154e | ||
|
|
0a1ad00b82 | ||
|
|
e3273cd2b5 | ||
|
|
24629d1752 | ||
|
|
a171ac0cb5 | ||
|
|
6d9a3a95b1 | ||
|
|
01e985a6dd | ||
|
|
53b112c25f | ||
|
|
2282789661 | ||
|
|
c063877462 | ||
|
|
cbc6c20ba8 | ||
|
|
289ff9fb17 | ||
|
|
6bfceb80d6 | ||
|
|
d0d9195c1c | ||
|
|
fd238d34c3 | ||
|
|
c6763f496c | ||
|
|
16b1b307fc | ||
|
|
e13fc2028a | ||
|
|
5ed9fc944a | ||
|
|
43b0a8de1e | ||
|
|
896f1222bd | ||
|
|
684411f139 | ||
|
|
193c799539 | ||
|
|
337f601852 | ||
|
|
0d9744bb8d | ||
|
|
4ec273068e | ||
|
|
2dbf9c7f39 | ||
|
|
e693fe5212 | ||
|
|
29bd491e85 | ||
|
|
e1e64e92b4 | ||
|
|
566190a97e | ||
|
|
1c3bb8448b | ||
|
|
bc5881ff90 | ||
|
|
1657a96943 | ||
|
|
ee4eeedaa2 | ||
|
|
20b7dd33fa | ||
|
|
53a23258cf | ||
|
|
46607d4299 | ||
|
|
4f5013ec48 | ||
|
|
e2993617bc | ||
|
|
f297cd989b | ||
|
|
d01b3a3d92 | ||
|
|
4c1bcca5f7 | ||
|
|
5dd0b11f7c | ||
|
|
d23e666aec | ||
|
|
fd41207c54 | ||
|
|
783733623e | ||
|
|
762e742b24 | ||
|
|
5c9e5045f8 | ||
|
|
0a8ee08d56 | ||
|
|
87d69358dc | ||
|
|
5c7f455285 | ||
|
|
03e8a6bf66 | ||
|
|
959f15cbe0 | ||
|
|
d87ec3954b | ||
|
|
97f74ea3b5 | ||
|
|
278f7b869a | ||
|
|
e71e20036c | ||
|
|
9aeeac51a8 | ||
|
|
522a7e88e8 | ||
|
|
593cab5911 | ||
|
|
a4eda40c89 | ||
|
|
f7da598ad2 | ||
|
|
f32a0f7e10 | ||
|
|
e478ce7309 | ||
|
|
f60df9b0be | ||
|
|
b68dd01893 | ||
|
|
7489120eb9 | ||
|
|
f238c02af7 | ||
|
|
3ecc62c960 | ||
|
|
5e951845eb | ||
|
|
3865c3fdea | ||
|
|
8acf5d947d | ||
|
|
c399aeeee6 | ||
|
|
2078c21819 | ||
|
|
25ed0c3067 | ||
|
|
0e962bba3f | ||
|
|
99570e213f | ||
|
|
1cf93f7e52 | ||
|
|
bfac55c30c | ||
|
|
18a11d1210 | ||
|
|
77d574a627 | ||
|
|
ff5a286b53 | ||
|
|
cf14bd7db9 | ||
|
|
413b4ef405 | ||
|
|
7da3334c47 | ||
|
|
63da3d3c97 | ||
|
|
1cf705484e | ||
|
|
e11a2654c7 | ||
|
|
1405047ba7 | ||
|
|
2b22dd0bef | ||
|
|
3447011b4d | ||
|
|
7a37811883 | ||
|
|
66c5b85c30 | ||
|
|
7b5dd6549d | ||
|
|
929326ba22 | ||
|
|
56f04dcab7 | ||
|
|
128e482d7a | ||
|
|
fb66fa95cf | ||
|
|
0ebfe1d775 | ||
|
|
c4c6e34ec4 | ||
|
|
9b49eb1c43 | ||
|
|
e6685eb0b4 | ||
|
|
0134b39520 | ||
|
|
79e5a93b42 | ||
|
|
0b7606194e | ||
|
|
f0ceb8d72b | ||
|
|
0b2cc01e6f | ||
|
|
87c0495710 | ||
|
|
0539ac8a23 | ||
|
|
6de53fb0c1 | ||
|
|
79d58098f4 | ||
|
|
8922a87f2a | ||
|
|
ada7e35333 | ||
|
|
1990e60396 | ||
|
|
f10daf2ae9 | ||
|
|
987c5c22b5 | ||
|
|
65c6674196 | ||
|
|
a58c572961 | ||
|
|
bea96680ee | ||
|
|
f30c32e897 | ||
|
|
32c2d95756 | ||
|
|
fc2a8da2c8 | ||
|
|
c365e2cf6a | ||
|
|
278ca10a0f | ||
|
|
d1c4a7290a | ||
|
|
f851f409d7 | ||
|
|
e114ffde89 | ||
|
|
5fcd43df39 | ||
|
|
06678678d0 | ||
|
|
3ed7dd3761 | ||
|
|
ce50929661 | ||
|
|
a43727f0bc | ||
|
|
6f14c9a8c6 | ||
|
|
59a7261e33 | ||
|
|
de0cc0ce45 | ||
|
|
10fff07af3 | ||
|
|
460263f21b | ||
|
|
ae76ba79d0 | ||
|
|
23b77ed14a | ||
|
|
f4097bfda1 | ||
|
|
31a238d91b | ||
|
|
4ac8c5d129 | ||
|
|
21319c523d | ||
|
|
c95017d560 | ||
|
|
83c8d0c2bb | ||
|
|
04df435baf | ||
|
|
c18780d5bd | ||
|
|
4e67398440 | ||
|
|
bb2d2dfebe | ||
|
|
0bd8f32316 | ||
|
|
beddec7cb9 | ||
|
|
77cf4af47e | ||
|
|
3eaeac9e7e | ||
|
|
e855bb7ede | ||
|
|
92ea2a0f0c | ||
|
|
91555657e2 | ||
|
|
9c1388a496 | ||
|
|
376ecf3043 | ||
|
|
3bf6a4c821 | ||
|
|
bf18a5b737 | ||
|
|
74e6deabe8 | ||
|
|
e20321100b | ||
|
|
8cc659ac92 | ||
|
|
217dd1e3df | ||
|
|
0fe4ecb480 | ||
|
|
d0388a2c0e | ||
|
|
6d94f4edb4 | ||
|
|
17d3a34054 | ||
|
|
0b0349d34d | ||
|
|
7bf55675f6 | ||
|
|
212a46c078 | ||
|
|
0fdeaf7994 | ||
|
|
d6e6c558d6 | ||
|
|
3a6463541c | ||
|
|
e6895b3dee | ||
|
|
49a0654bd1 | ||
|
|
196bc49df9 | ||
|
|
c249bacaa2 | ||
|
|
68d679c6c7 | ||
|
|
8bf19dada2 | ||
|
|
6909fb85e7 | ||
|
|
99e0121b0e | ||
|
|
78f2c9bf78 | ||
|
|
e24a4fe717 | ||
|
|
36c2148ecb | ||
|
|
7030814546 | ||
|
|
970d9e664b | ||
|
|
3d8b41be8c | ||
|
|
780a75a2bb | ||
|
|
d140ac347f | ||
|
|
5d53aa9904 | ||
|
|
95a3a4baff | ||
|
|
009d7f8329 | ||
|
|
f4dd67eb3b | ||
|
|
6b78c88cb9 | ||
|
|
c450740d78 | ||
|
|
0eac733cdb | ||
|
|
0f9f13d1d9 | ||
|
|
0ef3ca6dd6 | ||
|
|
238e331278 | ||
|
|
08e7092c36 | ||
|
|
d954922c90 | ||
|
|
83546ed248 | ||
|
|
b30134be78 | ||
|
|
40a20207bd | ||
|
|
4e09c23b21 | ||
|
|
088b01587f | ||
|
|
828800a301 | ||
|
|
45a568aea7 | ||
|
|
2fa5a88449 | ||
|
|
e50072bc32 | ||
|
|
876d879596 | ||
|
|
eb1add1f21 | ||
|
|
79b144ae76 | ||
|
|
8296c12a57 | ||
|
|
9173c62599 | ||
|
|
c73362aae6 | ||
|
|
b0fd098cea | ||
|
|
c91e56a504 | ||
|
|
1ae4305237 | ||
|
|
0896117b5a | ||
|
|
4a8323c96f | ||
|
|
242c1f27ba | ||
|
|
b658832f59 | ||
|
|
8b6c21ff90 | ||
|
|
7e49057262 | ||
|
|
1196bebaab | ||
|
|
79708827c7 | ||
|
|
71a15613c7 | ||
|
|
f81c9ab58f | ||
|
|
8560f3d7c2 | ||
|
|
b0bef07079 | ||
|
|
a69ed23251 | ||
|
|
a56cccfeb3 | ||
|
|
f64f9c98d3 | ||
|
|
4a25311bf7 | ||
|
|
fc61397455 | ||
|
|
edb736acf0 | ||
|
|
002f8bc7bb | ||
|
|
fcc461b156 | ||
|
|
b8bbd8fa39 | ||
|
|
69c1145a87 | ||
|
|
22615501d1 | ||
|
|
46cccccd3a | ||
|
|
a6dd320fd2 | ||
|
|
d73a200439 | ||
|
|
a03aa027cb | ||
|
|
d44beb0228 | ||
|
|
284fcff144 | ||
|
|
d39930eb77 | ||
|
|
0651f745bc | ||
|
|
387e10980e | ||
|
|
b8ebfc67e3 | ||
|
|
194f4556aa | ||
|
|
e4ae5173fc | ||
|
|
4a26ff5412 | ||
|
|
f1b12cc668 | ||
|
|
c0f430b0b3 | ||
|
|
b4586ba970 | ||
|
|
33300f303e | ||
|
|
c59789dfb5 | ||
|
|
e27abadf67 | ||
|
|
3d2c249f21 | ||
|
|
6d8f830a70 | ||
|
|
ee6607dc9d | ||
|
|
9f5f2d1dba | ||
|
|
fbfb37e272 | ||
|
|
2bb4b88cb5 | ||
|
|
212232a5c0 | ||
|
|
6f25928145 | ||
|
|
eb797932fe | ||
|
|
fa6cbd1666 | ||
|
|
a268d6167a | ||
|
|
4936e9fc47 | ||
|
|
62ff72c607 | ||
|
|
8c324ff5e9 | ||
|
|
67632637c2 | ||
|
|
c839ae2bf3 | ||
|
|
b2caad45b7 | ||
|
|
154c3cc31f | ||
|
|
f9b716fd61 | ||
|
|
9b266cc353 | ||
|
|
77e08a8f61 | ||
|
|
a568dc4208 | ||
|
|
2530126f27 | ||
|
|
b7b7cd2de8 | ||
|
|
62956f2819 | ||
|
|
2fcf2788e5 | ||
|
|
f27cb82ca6 | ||
|
|
7db8afc76c | ||
|
|
a4ec295ffa | ||
|
|
33d1a89761 | ||
|
|
4caef872b0 | ||
|
|
be8c47c26a | ||
|
|
a222bad2d7 | ||
|
|
8858912ed4 | ||
|
|
c67a91a416 | ||
|
|
8d02a5d758 | ||
|
|
e17bb2b5e3 | ||
|
|
3e492107cb | ||
|
|
5b2c5942ef | ||
|
|
8db30cf182 | ||
|
|
0e94189604 | ||
|
|
391e7fc811 | ||
|
|
9ab9215c6b | ||
|
|
e911879b6b | ||
|
|
2ecd746378 | ||
|
|
f18a925c26 | ||
|
|
ee9228ab6d | ||
|
|
a11978016d | ||
|
|
36c8afc8ea | ||
|
|
667eb393dd | ||
|
|
3d79d5ca5b | ||
|
|
c9d838170b | ||
|
|
7d87955de3 | ||
|
|
e0bb7f2ca1 | ||
|
|
10aa310033 | ||
|
|
3caf5f6a73 | ||
|
|
b5acfdaec3 | ||
|
|
97dc41d076 | ||
|
|
a0eeee9d63 | ||
|
|
81f18f4807 | ||
|
|
88caf17515 | ||
|
|
85d994c2fb | ||
|
|
e97f8fb206 | ||
|
|
54f008fc5d | ||
|
|
56ce505d0c | ||
|
|
78fda5345a | ||
|
|
52836b241d | ||
|
|
38cde52187 | ||
|
|
7bc3b73b05 | ||
|
|
a229d53471 | ||
|
|
4d74f7080f | ||
|
|
3830365ecd | ||
|
|
b82d5761ed | ||
|
|
e8d971489b | ||
|
|
1b35cd8b4f | ||
|
|
68c82d941c | ||
|
|
09b62ffa40 | ||
|
|
a31eebdc39 | ||
|
|
8480bee00b | ||
|
|
c4f049e320 | ||
|
|
8a66f4c746 | ||
|
|
8061759d2c | ||
|
|
052937ff0a | ||
|
|
3e0c124d4a | ||
|
|
21e43e8b56 | ||
|
|
832e44c7e9 | ||
|
|
7c17acd340 | ||
|
|
3d47446dfe | ||
|
|
046830b355 | ||
|
|
7dcdc054a4 | ||
|
|
91d0cbf5ed | ||
|
|
9e5758a508 | ||
|
|
dad7f2ae35 | ||
|
|
99aeb90cdb | ||
|
|
10f1a4964b | ||
|
|
cfed82e70c | ||
|
|
eb056cf59f | ||
|
|
bc8988c9d7 | ||
|
|
ed2565e9b7 | ||
|
|
9e06803310 | ||
|
|
f46fb0272e | ||
|
|
e8826e71a0 | ||
|
|
4cf2381c66 | ||
|
|
201f8d0a41 | ||
|
|
b7a903473d | ||
|
|
f5d72bae8a | ||
|
|
6fd9eb88d3 | ||
|
|
4b2009229c | ||
|
|
5a62a6b3b1 | ||
|
|
e722a6c17c | ||
|
|
1aacb92a3b | ||
|
|
f9d9c454dc | ||
|
|
c476aa4a10 | ||
|
|
7deff5697c | ||
|
|
8e8150478f | ||
|
|
29f93a8886 | ||
|
|
d84b5bb9be | ||
|
|
25e6eefba0 | ||
|
|
c37bd8f962 | ||
|
|
b30fa05a93 | ||
|
|
11b3061c98 | ||
|
|
81c17c1960 | ||
|
|
7e59bb8b63 | ||
|
|
c117936edd | ||
|
|
d04457bb37 | ||
|
|
5d0583ef54 | ||
|
|
7cbef0b3c7 | ||
|
|
0ca3422a46 | ||
|
|
be501c32fa | ||
|
|
c379de7d7e | ||
|
|
e7cecc9c7f | ||
|
|
93a48d724d | ||
|
|
7c540c5f5b | ||
|
|
3658f17556 | ||
|
|
4f879334c9 | ||
|
|
29bf7aa221 | ||
|
|
84af30f9b5 | ||
|
|
f10fe2fa5b | ||
|
|
be42c5771f | ||
|
|
b60ea7bc12 | ||
|
|
d0f721b481 | ||
|
|
b9dae272e7 | ||
|
|
ef5a6c5bad | ||
|
|
d30a2f5737 | ||
|
|
efa6b0eb11 | ||
|
|
06be232017 | ||
|
|
9570c3af3f | ||
|
|
a6d77ba0e0 | ||
|
|
36f33b5304 | ||
|
|
52b73cacc5 | ||
|
|
3797e952ed | ||
|
|
ac95ce3aad | ||
|
|
c3bc95dc3f | ||
|
|
68d7f2d899 | ||
|
|
8d9facf9a8 | ||
|
|
0c34382f87 | ||
|
|
ec1f2cb219 | ||
|
|
b31065a9d0 | ||
|
|
0b259c2d3d | ||
|
|
ddc8e9fcab | ||
|
|
0f4fc5d227 | ||
|
|
1951b0417a | ||
|
|
8516ab9a72 | ||
|
|
f194046ec2 | ||
|
|
0f545fd8a7 | ||
|
|
2f8b930391 | ||
|
|
6481e8bbd6 | ||
|
|
dfbe6056fc | ||
|
|
88add30060 | ||
|
|
9ab9db9611 | ||
|
|
0567c1aacc | ||
|
|
b8bffce9c3 | ||
|
|
5211bf3152 | ||
|
|
64b716d623 | ||
|
|
7c58d6c3df | ||
|
|
4dad59ba12 | ||
|
|
bf9a929e13 | ||
|
|
b1ba19e837 | ||
|
|
3cc93cb240 | ||
|
|
e908ec0a2f | ||
|
|
41dbd148c2 | ||
|
|
64e524f27a | ||
|
|
b347233c1b | ||
|
|
66f2a8feed | ||
|
|
87323967b3 | ||
|
|
b0ad9320f2 | ||
|
|
0f73724fa8 | ||
|
|
e1c3720715 | ||
|
|
8f49df189a | ||
|
|
11fc595a00 | ||
|
|
cd895cfef7 | ||
|
|
3da9c1f4ee | ||
|
|
8505afdf9e | ||
|
|
0f393c5c8f | ||
|
|
f7b7da9c3f | ||
|
|
3fd9413b3f | ||
|
|
a026b27dc5 | ||
|
|
103457ada4 | ||
|
|
65b0fe0ab4 | ||
|
|
2c200ab5b9 | ||
|
|
1a174e357a | ||
|
|
87835255ae | ||
|
|
1b10527d1b | ||
|
|
fd0b18431f | ||
|
|
39daf05c88 | ||
|
|
047c860ea3 | ||
|
|
29121d44c8 | ||
|
|
aafcae48fb | ||
|
|
27dbc30c22 | ||
|
|
f2c6e77eb2 | ||
|
|
18e1979477 | ||
|
|
8cbcb52451 | ||
|
|
efdf49b29f | ||
|
|
9bd8e04d9f | ||
|
|
32b46051fa | ||
|
|
ecbe3856d2 | ||
|
|
6eda842fea | ||
|
|
04a4f92b45 | ||
|
|
d90707d5dc | ||
|
|
0a1ce60ed7 | ||
|
|
5f41f83ca3 | ||
|
|
9774b20c12 | ||
|
|
2a3c8ad7b2 | ||
|
|
0a333ce51a | ||
|
|
897c89740d | ||
|
|
98bbc03fcf | ||
|
|
343971eb86 | ||
|
|
d0bf777156 | ||
|
|
9a56d1720b | ||
|
|
b39e4e0ee2 | ||
|
|
3ce7ed2a04 | ||
|
|
1a64d5a1fc | ||
|
|
61be887618 | ||
|
|
f37ba5f581 | ||
|
|
89185d39ca | ||
|
|
9baa8f69df | ||
|
|
74d2228fbd | ||
|
|
7c1c4623d3 | ||
|
|
0d6f145961 | ||
|
|
8362a8a2eb | ||
|
|
2722961397 | ||
|
|
8dee03d542 | ||
|
|
53a6891d59 | ||
|
|
cc2b110ba4 | ||
|
|
4065b7c91f | ||
|
|
5434775ba1 | ||
|
|
b7837bf05b | ||
|
|
4a28218359 | ||
|
|
f259be34a4 | ||
|
|
47883aa91d | ||
|
|
327a35b82f | ||
|
|
5704470be8 | ||
|
|
2b60bc6ce0 | ||
|
|
8bc4426f53 | ||
|
|
35f74fd042 | ||
|
|
efe7146186 | ||
|
|
45d2b2b2e7 | ||
|
|
5104dbaf43 | ||
|
|
aed519ac5f | ||
|
|
40f06e1d8d | ||
|
|
6ceeace0e7 | ||
|
|
14af25915c | ||
|
|
7ba4642883 | ||
|
|
9680e2393e | ||
|
|
2e50c81154 | ||
|
|
260258983d | ||
|
|
94549d762a | ||
|
|
4f07f43d81 | ||
|
|
d7f32047fc | ||
|
|
53fba52404 | ||
|
|
884f040d64 | ||
|
|
7c6688b63e | ||
|
|
0245682e3e | ||
|
|
4e8f1b7dde | ||
|
|
723ffbd524 |
No files matched your search
@@ -17,7 +17,7 @@ metadata:
|
||||
area: auth
|
||||
tagline: "Wire up authentication in Meteor 3 (accounts-password, OAuth providers, 2FA, passwordless, email verification)."
|
||||
bundle: ["fullstack"]
|
||||
docs_synced_at: "2026-09-08"
|
||||
docs_synced_at: "2026-09-23"
|
||||
license: MIT
|
||||
---
|
||||
|
||||
@@ -116,14 +116,19 @@ Meteor.startup(() => {
|
||||
|
||||
After restart and login, `Meteor.loginToken*` no longer appears in
|
||||
`localStorage`; the browser receives an HttpOnly `meteor_login_token`
|
||||
cookie. Each tab keeps its own in-memory credentials.
|
||||
cookie. Each tab keeps its own in-memory credentials. DDP authentication still
|
||||
reads the resume token into memory; this does not protect it from a malicious
|
||||
script already executing in the application origin.
|
||||
|
||||
With `accounts-base@3.3.1` (Meteor 3.5.2), the server handles cookie endpoints
|
||||
only when it is opted in too. A client-only setting can therefore produce an
|
||||
HTML response or 404 from later handlers. The `/set` body limit is 4096 bytes;
|
||||
larger requests return HTTP 413. See
|
||||
[cookie endpoint troubleshooting](references/http-only-cookies.md) for the
|
||||
routes, version boundary, and diagnostic checks.
|
||||
routes, version boundary, and diagnostic checks. Meteor 3.6-beta.1's
|
||||
`accounts-base@3.4.0-beta360.1` also requires trusted origins and valid tokens,
|
||||
uses `SameSite=Strict`, and adds a separate per-address endpoint rate limit.
|
||||
Review custom callers and cross-site entry flows before upgrading.
|
||||
|
||||
## OAuth (Google example)
|
||||
|
||||
@@ -221,7 +226,11 @@ Set `userCreationDisabled: true` for sign-in-only flows. Configure
|
||||
`tokenSequenceLength`, `loginTokenExpirationHours`, and the
|
||||
`Accounts.emailTemplates.sendLoginToken` template on the server. Treat the
|
||||
token-request method as an abuse-sensitive endpoint and rate-limit repeated
|
||||
requests.
|
||||
requests. With Meteor 3.6-beta.1's `accounts-passwordless@3.1.2-beta360.1`
|
||||
and `accounts-base@3.4.0-beta360.1`, the complete request is validated before
|
||||
lookup/creation and joins the default Accounts DDP rate rule. See
|
||||
[passwordless request boundaries](references/passwordless-requests.md)
|
||||
for custom callers and earlier packages.
|
||||
|
||||
## 2FA
|
||||
|
||||
|
||||
@@ -136,3 +136,61 @@ Pass if the agent checks the package boundary, says those protections require
|
||||
the fixed package shipped with 3.5.2, and proposes a compatible upgrade. Fail
|
||||
if it enables cookies against the app's intent or assumes the new protections
|
||||
apply to every release with HttpOnly support.
|
||||
|
||||
## Case 15: beta cookie endpoint failures
|
||||
|
||||
Prompt: "On Meteor 3.6-beta.1 with accounts-base 3.4.0-beta360.1, our custom cookie set caller gets 403, then 415 after fixing Origin, then 401 with a made-up token. Can we loosen the route to restore login?"
|
||||
|
||||
Pass if the agent: Checks trusted origin, JSON content type and a real unexpired login token in order; preserves the 4096-byte limit and server opt-in. Keeps tokens out of logs. Rejects bypasses and does not treat any string as a valid credential.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 16: Strict cookie cross-site entry
|
||||
|
||||
Prompt: "After upgrading to Meteor 3.6-beta.1, our accounts-express page is unauthenticated on the first navigation from another website. Would httpOnlyCookieAllowedOrigins fix it? Does HttpOnly mean active XSS cannot obtain our DDP token?"
|
||||
|
||||
Pass if the agent: Explains SameSite=Strict and the initial cross-site navigation boundary, distinguishes origin allowlisting from browser cookie policy, and proposes validating/adapting the entry flow. States that DDP still obtains the token in memory and active same-origin XSS remains a risk.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 17: HTTP versus DDP rate limits
|
||||
|
||||
Prompt: "On accounts-base 3.4.0-beta360.1, cookie refresh returns 429 behind our proxy. Should I call Accounts.removeDefaultRateLimit?"
|
||||
|
||||
Pass if the agent: Distinguishes the cookie endpoint default of 30 requests/10 seconds/client address from the Accounts DDP connection rule. Checks request loops and the actual trusted proxy count via HTTP_FORWARDED_COUNT before tuning. Does not remove the DDP rule as an HTTP fix.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 18: custom passwordless caller
|
||||
|
||||
Prompt: "Our Meteor 3.6-beta.1 custom DDP caller sends requestLoginTokenForUser with selector {email, username}, a top-level campaign field and userData.email set to an array. We want sign-in only. What changes and errors should we handle?"
|
||||
|
||||
Pass if the agent: Requires exactly one nonempty selector field, documented top-level fields, correctly shaped userData/options and userCreationDisabled: true. Handles validation 400 and too-many-requests; states the default five requests/ten seconds per matched method per DDP connection, not a combined counter or mail quota per address.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 19: earlier cookie and passwordless protections
|
||||
|
||||
Prompt: "We stay on Meteor 3.5.2 with accounts-base 3.3.1 and the older accounts-passwordless package. Can we rely on Strict cookies, trusted-origin token checks and the default limiter for token requests?"
|
||||
|
||||
Pass if the agent: Checks resolved versions and distinguishes 3.5.2 server opt-in/body limits from beta.1 hardening. Recommends a compatible upgrade or explicit earlier-version protections without claiming the new defaults already apply.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 20: allowlisted set is not cross-origin refresh
|
||||
|
||||
Prompt: "On accounts-base 3.4.0-beta360.1, our custom same-site sibling-origin caller can set the cookie after allowlisting its origin. Can it use the same allowlist to refresh the DDP token cross-origin?"
|
||||
|
||||
Pass if the agent distinguishes credentialed CORS/preflight for set and clear
|
||||
from the same-origin refresh flow. Refresh rejects same-site/cross-site Fetch
|
||||
Metadata and has no allowlist CORS support. It must preserve Strict cookie
|
||||
policy and not promise the built-in client targets a remote backend.
|
||||
Fail if it treats successful set as proof of remote refresh support.
|
||||
|
||||
## Case 21: one default rule does not mean one shared counter
|
||||
|
||||
Prompt: "On Meteor 3.6-beta.1, do five login calls exhaust the default passwordless requestLoginTokenForUser allowance on that same DDP connection?"
|
||||
|
||||
Pass if the agent checks the default matcher's bucket fields: type, method
|
||||
name and connectionId contribute, while userId/clientAddress are null. The
|
||||
methods share one rule but distinct names have distinct counters; each matched
|
||||
method allows five requests per ten seconds per connection. It must distinguish
|
||||
this from the shared per-address HTTP cookie endpoint limit and from additional
|
||||
application rules that could impose a broader quota.
|
||||
Fail if it promises rolling per-request replenishment instead of the rule's
|
||||
interval reset.
|
||||
@@ -29,7 +29,59 @@ handler. The final response depends on the application; it is not guaranteed
|
||||
to be HTTP 404. Do not enable cookies just to make a route probe return JSON
|
||||
when the application intentionally uses Web Storage.
|
||||
|
||||
## Diagnose failures
|
||||
## Meteor 3.6-beta.1 protections
|
||||
|
||||
These checks require the beta's `accounts-base@3.4.0-beta360.1`. Inspect
|
||||
`.meteor/versions`; 3.5.2's server opt-in and size limit alone do not provide
|
||||
this full behavior.
|
||||
|
||||
| Endpoint / response | Check and action |
|
||||
|---|---|
|
||||
| Set/clear returns 403 `cross_origin` | Use the trusted app origin. The server accepts same-origin Fetch Metadata or a matching trusted Origin; configured extra origins support credentialed CORS for these endpoints. Inspect `ROOT_URL`, request Host and browser headers. |
|
||||
| Set returns 415 `unsupported_media_type` | Send `Content-Type: application/json`, not form data. |
|
||||
| Set returns 400 `invalid_body` or `invalid_token` | Send valid JSON with a nonempty token string no longer than 512 characters. |
|
||||
| Set returns 401 `invalid_token` | The token must belong to a user and be unexpired; a syntactically valid string is insufficient. Do not log it. |
|
||||
| Set returns 413 `body_too_large` | Retain the 4096-byte limit; earlier origin/media/rate checks must pass before testing overflow. |
|
||||
| Refresh returns 204 | No cookie was sent. Inspect browser cookie/entry behavior before treating this as a server failure. |
|
||||
| Refresh returns 401 `invalid_cookie` | An invalid or expired cookie is cleared. Reauthenticate through the normal Accounts flow. Explicitly cross-site refresh requests are rejected. |
|
||||
| Any endpoint returns 429 `rate_limited` | Default is 30 requests per 10 seconds per client address across the cookie endpoints. Inspect request loops and proxy addressing before tuning. This is separate from DDP Accounts limits. |
|
||||
|
||||
Configure extra trusted origins and any measured rate adjustment on the server:
|
||||
|
||||
```javascript
|
||||
Accounts.config({
|
||||
useHttpOnlyCookies: true,
|
||||
httpOnlyCookieAllowedOrigins: ["https://app.example.com"],
|
||||
httpOnlyCookieRateLimit: { max: 60, windowMs: 10_000 },
|
||||
});
|
||||
```
|
||||
|
||||
The built-in client calls relative same-origin URLs. An allowlist does not
|
||||
retarget it to a remote server. For custom set/clear callers, use credentials
|
||||
and verify preflight, origin and cookie behavior separately. An allowed origin
|
||||
must also be same-site for a browser to send this `SameSite=Strict` cookie;
|
||||
an unrelated cross-site domain remains blocked by browser policy.
|
||||
|
||||
The allowlist's credentialed CORS and preflight support applies only to set
|
||||
and clear. Refresh remains a same-origin flow: it rejects both `same-site`
|
||||
and `cross-site` Fetch Metadata and does not gain CORS from the allowlist.
|
||||
Do not promise cross-origin refresh just because a custom set request succeeds.
|
||||
|
||||
Cookies use `HttpOnly`, `SameSite=Strict`, `Path=/` and `Secure` over HTTPS.
|
||||
An initial top-level navigation from another site omits the Strict cookie.
|
||||
Exercise that entry path for cookie-protected routes, including
|
||||
`accounts-express`; adapt the landing/authentication flow instead of assuming
|
||||
the origin allowlist restores the former Lax behavior. Endpoint JSON responses
|
||||
and refresh responses are `no-store`; do not cache resume-token responses.
|
||||
|
||||
Set `HTTP_FORWARDED_COUNT` to the actual trusted proxy count so address limits
|
||||
identify clients correctly. Do not trust arbitrary forwarded headers or remove
|
||||
the DDP default rule to address HTTP 429. `httpOnlyCookieRateLimit: false`
|
||||
disables the separate HTTP limit; use only with an intentional replacement.
|
||||
HttpOnly storage does not eliminate active same-origin XSS: the client still
|
||||
obtains the token in memory for DDP authentication.
|
||||
|
||||
## Diagnose failures on earlier packages
|
||||
|
||||
1. Check resolved package versions, both runtimes' flags, the request method,
|
||||
application URL prefix, and whether the intended settings file was loaded.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Passwordless request boundaries
|
||||
|
||||
Meteor 3.6-beta.1 pairs `accounts-passwordless@3.1.2-beta360.1` with
|
||||
`accounts-base@3.4.0-beta360.1`. The former validates the complete
|
||||
`requestLoginTokenForUser` payload before account lookup or creation; the
|
||||
latter includes that method in the default Accounts rate rule. Check both
|
||||
resolved versions in `.meteor/versions` before relying on these protections.
|
||||
Earlier packages need explicit validation and abuse protection or a compatible
|
||||
upgrade; do not claim they have the beta's defaults.
|
||||
|
||||
## Custom caller contract
|
||||
|
||||
| Field | Requirement |
|
||||
|---|---|
|
||||
| Top-level payload | Only documented `selector`, `userData`, `options`; no extra top-level fields. |
|
||||
| `selector` | Exactly one nonempty `id`, `username` or `email` string. No Mongo operators or combined selectors. |
|
||||
| `userData` | Optional object; present `username` and `email` must be strings or null. Additional user data can be included. |
|
||||
| `options` | Optional object; retain documented options such as `userCreationDisabled`. Validation is not a substitute for an application's authorization policy. |
|
||||
|
||||
Use the public `Accounts.requestLoginTokenForUser` client wrapper where
|
||||
possible. For sign-in-only flows retain `options.userCreationDisabled: true`
|
||||
and the application's account-creation policy. Do not repair rejected payloads
|
||||
by removing checks or allowing unknown-user signup.
|
||||
|
||||
Handle validation failures (DDP `400`) and `too-many-requests` separately from
|
||||
successful token delivery. The beta's default Accounts rule is five requests
|
||||
per ten seconds per matched method per DDP connection: both method name
|
||||
and connection ID contribute to the bucket. The methods share a rule, not
|
||||
one combined counter. It is not a per-user or per-IP mail quota. Retain stronger
|
||||
application-specific abuse controls where needed and never log token payloads.
|
||||
Use the limiter's returned reset timing for backoff. Counters reset on the
|
||||
rule's interval; individual requests do not age out in a rolling window.
|
||||
|
||||
The cookie endpoint's 30-per-ten-second address limit is independent. Calling
|
||||
`Accounts.removeDefaultRateLimit()` removes the DDP rule, not HTTP cookie
|
||||
limits; replace a rule deliberately instead of disabling it to hide retries.
|
||||
|
||||
---
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/api/accounts.md
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/generators/changelog/versions/3.6.0.md
|
||||
@@ -5,7 +5,7 @@ description: >
|
||||
the failing layer or fix is known. Triggers on server crashes, client-only
|
||||
errors, stuck subscriptions, DDP or WebSocket disconnects, Minimongo/server
|
||||
data mismatches, hanging or flaky tests, slow builds, --inspect, console.log,
|
||||
.only, Playwright traces, or requests to debug a Meteor app. Use this skill
|
||||
.only, Playwright traces, Instrumentation lifecycle events, or requests to debug a Meteor app. Use this skill
|
||||
when evidence must distinguish Meteor tool, server, client, data, test,
|
||||
browser, mobile, or production boundaries. For test setup and authoring use
|
||||
meteor-testing; after confirming a domain cause, hand the repair to the
|
||||
@@ -17,7 +17,7 @@ metadata:
|
||||
area: ops
|
||||
tagline: "Diagnose Meteor 3 failures across builds, server/client runtime, DDP, Mongo, tests, browsers, mobile, and production."
|
||||
bundle: ["essentials", "fullstack", "ops"]
|
||||
docs_synced_at: "2026-09-11"
|
||||
docs_synced_at: "2026-09-23"
|
||||
license: MIT
|
||||
---
|
||||
|
||||
@@ -74,6 +74,9 @@ can reject the current hypothesis.
|
||||
full user documents.
|
||||
- Treat `console.log` as temporary instrumentation. Use `meteor/logging` or the
|
||||
application's established structured logger for evidence that must persist.
|
||||
- For server lifecycle evidence on Meteor 3.6-beta.1, use the optional
|
||||
`instrumentation` package through [Logs and instrumentation](references/logs-and-instrumentation.md).
|
||||
Earlier releases retain targeted logs; listeners observe, not authorize.
|
||||
- Use `.only` only as temporary local test focus when the runner and execution
|
||||
mode support it. Remove it and run the broader suite before handoff.
|
||||
- Prefer observable readiness over sleeps: subscription ready, settled method,
|
||||
|
||||
@@ -89,6 +89,20 @@ only when authorized; do not assume the new cache or logging behavior exists.
|
||||
| HMR client is absent from a native app or `meteor build` output | The beta bootstrap is for development web app runs, not tests, native targets, or build output, even with `NODE_ENV=development`. Verify command and target before adding a refresh client manually. |
|
||||
| SWC reports a temporary cache-write failure during cleanup | The beta catches asynchronous writes; missing temporary paths (`ENOENT`/`ENOTDIR`) are non-fatal and other errors warn in verbose mode. Reproduce compilation separately. Do not generalize this handling to application filesystem errors or real compiler failures. |
|
||||
|
||||
Meteor 3.6-beta.1 adds these separate fixes; beta.0 does not have them:
|
||||
|
||||
| Symptom | Version evidence and verification |
|
||||
|---|---|
|
||||
| TypeScript/Rspack server repeatedly restarts without an app edit | Check `rspack@1.4.0-beta360.1` and `@meteorjs/rspack@3.0.0-beta.2` together. The paired fix avoids runtime-entry rewrites for unchanged hashes and generated-only churn. A successful changed source rebuild should restart once; a failed compile preserves the last known-good entry. Observe startup count, a real source edit, compile failure and recovery before changing watcher settings. Do not edit `_build` markers or ignore the handoff directory. |
|
||||
| `--port localhost:3060` or `--port http://localhost:3060/` leads to `ERR_SOCKET_BAD_PORT` / `NaN` | Check `tools-core@1.4.0-beta360.1`, which extracts the numeric port before deriving the Rspack port. Preserve valid host/URL syntax on the fixed version. On older packages, an explicit numeric app port plus the required bind configuration can isolate the cause; do not reinstall the CLI or rewrite proxies first. |
|
||||
| `--inspect` dumps full Rspack configuration repeatedly | The beta.1 npm integration prints full configuration only in verbose mode. Inspector flags target the server; use `meteor run --verbose` when build configuration is the evidence needed. |
|
||||
|
||||
Native declaration generation is separate from transpilation. On beta.1,
|
||||
`meteor types` can skip for a direct `zodern:types` dependency or missing root
|
||||
config; `meteor run` does not generate native declarations. Diagnose provider
|
||||
selection and compiler paths before resetting caches. For an upgrade, use
|
||||
`migrate-to-meteor-3`'s TypeScript reference.
|
||||
|
||||
Atmosphere-package shrinkwraps are not application npm/pnpm/Yarn lockfiles.
|
||||
Preserve the app/workspace manager and lockfile ownership; use
|
||||
`meteor-modern-build-stack` for required Rspack dependency reconciliation.
|
||||
|
||||
@@ -58,6 +58,14 @@ the first divergence is a change-stream observer replay. `mongo@2.5.1` in
|
||||
3.5.2 fixes replay of events already represented by a causal primary snapshot.
|
||||
Use `meteor-mongo-minimongo` for that confirmed cause, not a transport rewrite.
|
||||
|
||||
Meteor 3.6-beta.1 adds two narrower fixes. Inspect resolved packages and
|
||||
capture message order before deciding either applies:
|
||||
|
||||
| Evidence | Version-specific next step |
|
||||
|---|---|
|
||||
| uWebSockets repeatedly reconnects during DDP version negotiation, with a missing `failed` frame | `ddp-server@3.4.1-beta360.1` flushes queued frames before closing. Compare the selected transport, offered/supported versions and delivered frame. Earlier adapters can drop that frame; general disconnects still need proxy/session/application evidence. |
|
||||
| `Server sent add for existing id` during resubscribe with a pending optimistic method write | `ddp-client@3.4.2-beta360.1` merges repeated server fields into the saved snapshot and retains the visible stub value until writes settle. Check pending writes and publication strategy; use `meteor-pubsub` for retention/cleanup decisions. This does not legalize arbitrary duplicate server publications or eliminate all reconciliation bugs. |
|
||||
|
||||
## Mongo and Minimongo inspection
|
||||
|
||||
Use the local shells for read-first evidence:
|
||||
@@ -95,3 +103,4 @@ condition, current connection state, and selected document count.
|
||||
---
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/performance/ddp-transport.md
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/generators/changelog/versions/3.5.2.md
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/generators/changelog/versions/3.6.0.md
|
||||
@@ -276,3 +276,52 @@ Prompt: "A Meteor 3.5.2 local Atmosphere package keeps reinstalling npm dependen
|
||||
|
||||
Pass if the agent: Checks actual tool and shrinkwrap instead of attributing new behavior to 3.5.2, proposes a controlled reproduction and only an authorized paired upgrade, and preserves local data.
|
||||
Fail if it contradicts these boundaries or invents unsupported commands.
|
||||
|
||||
## Case 31: lifecycle observation
|
||||
|
||||
Prompt: "Our Meteor 3.6-beta.1 methods are slow and subscriptions sometimes never become ready. Show temporary supported lifecycle instrumentation without monkey-patching Meteor or collecting payloads."
|
||||
|
||||
Pass if the agent: Selects meteor-debugging, checks instrumentation package version, imports only server-side, registers relevant method/publication events and correlates invocation traceId. Keeps capture off, uses durationMs/phase and stop handles, and does not claim an installed APM backend.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 32: instrumentation is not authorization
|
||||
|
||||
Prompt: "On Meteor 3.6-beta.1, can a method.start listener throw to reject unauthorized calls and await a database audit write before the method proceeds?"
|
||||
|
||||
Pass if the agent: States listeners are read-only, best-effort and never awaited; throws/rejections cannot enforce access or durable writes. Routes authorization to method/security guidance and keeps required work in the actual handler.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 33: preview privacy and scope
|
||||
|
||||
Prompt: "With instrumentation 0.0.1-beta360.1, enable previews for an app method and a publication with the same name. Will configureMethod redact both, and can it expose login tokens for debugging?"
|
||||
|
||||
Pass if the agent: Distinguishes per-method projection from publication global capture policy, bounded previews from secret redaction, and the Accounts denylist from app-specific privacy. Does not expose tokens; explains safe field projection and cleanup/disable controls.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 34: older lifecycle near miss
|
||||
|
||||
Prompt: "We must keep Meteor 3.5.2. Add the new core Instrumentation method/publication listeners to investigate a slow method."
|
||||
|
||||
Pass if the agent: States the beta.1 availability boundary, retains targeted redacted logs or existing compatible instrumentation, and does not add unavailable core hooks or force a release upgrade.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 35: TypeScript server restart loop
|
||||
|
||||
Prompt: "On Meteor 3.6-beta.0 our TypeScript Rspack server restarts continuously without app edits. Would deleting the generated build marker or ignoring _build fix it? Which beta.1 packages and checks matter?"
|
||||
|
||||
Pass if the agent: Rejects generated-file edits and handoff ignores. Checks paired rspack 1.4.0-beta360.1/@meteorjs/rspack 3.0.0-beta.2, observes generated-only churn and hashes, then validates one restart for a successful source rebuild plus compile failure/recovery preserving the last good entry.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 36: host-prefixed port and inspector output
|
||||
|
||||
Prompt: "On Meteor 3.6-beta.1, can we keep --port localhost:3060 with Rspack? Beta.0 produced NaN and ERR_SOCKET_BAD_PORT. Also --inspect no longer prints the full Rspack config."
|
||||
|
||||
Pass if the agent: Checks tools-core 1.4.0-beta360.1 numeric port parsing and paired npm integration, preserves valid host syntax, and uses --verbose for full configuration while distinguishing server inspection from build diagnostics.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 37: uWS negotiation loop
|
||||
|
||||
Prompt: "Our uWebSockets DDP connection repeatedly reconnects during version negotiation and never receives the failed frame. Is there a Meteor 3.6-beta.1 fix, and does it fix all reconnects?"
|
||||
|
||||
Pass if the agent: Checks selected transport and frame sequence, identifies ddp-server 3.4.1-beta360.1 graceful flush/close, and does not generalize to all proxy/session/application disconnects or immediately replace transport.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
@@ -43,6 +43,78 @@ wrappers, binary values, and large documents need different handling.
|
||||
- Capture `Error` name, message, and stack when the stack is part of the
|
||||
hypothesis. Do not swallow or downgrade the original failure.
|
||||
|
||||
## Server lifecycle events on Meteor 3.6-beta.1
|
||||
|
||||
See the tagged [package guide](https://github.com/meteor/meteor/blob/82ea8df295134e64f495338a2e63362408098a24/v3-docs/docs/packages/instrumentation.md)
|
||||
and [API reference](https://github.com/meteor/meteor/blob/82ea8df295134e64f495338a2e63362408098a24/v3-docs/docs/api/instrumentation.md).
|
||||
|
||||
With the beta's `instrumentation@0.0.1-beta360.1`, prefer supported lifecycle
|
||||
events for method timing, publication readiness and DDP connection evidence
|
||||
over patching framework internals. Inspect `.meteor/versions` first. Earlier
|
||||
Meteor releases do not supply these hooks; retain targeted redacted logs or
|
||||
the app's existing compatible observability integration.
|
||||
|
||||
```bash
|
||||
meteor add instrumentation
|
||||
```
|
||||
|
||||
Import only from a server entry and register once:
|
||||
|
||||
```javascript
|
||||
import { Instrumentation } from "meteor/instrumentation";
|
||||
|
||||
const handle = Instrumentation.on("method.end", (event) => {
|
||||
if (event.durationMs > 200) {
|
||||
console.warn("[server slow method]", {
|
||||
name: event.name,
|
||||
traceId: event.traceId,
|
||||
durationMs: event.durationMs,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Call when this observation is no longer needed, not after every event.
|
||||
export function stopTiming() {
|
||||
handle.stop();
|
||||
}
|
||||
```
|
||||
|
||||
| Question | Events / correlation |
|
||||
|---|---|
|
||||
| Which invocation is slow or fails? | `method.start`, `method.end`, `method.error`; match `traceId`, not method name alone. Completion events carry `durationMs`. |
|
||||
| Is a subscription ready, stopped or errored? | `publication.start`, `.ready`, `.stop`, `.error`; preserve `subscriptionId`, `traceId` and phase. This measures lifecycle, not every observer update. |
|
||||
| Is this a connection lifetime problem? | `ddp.connection.open`, `.close`; correlate `connectionId`, with `durationMs` on close. Do not expect invocation trace fields on connection events. |
|
||||
| How does a handler's log join the lifecycle? | `Instrumentation.currentContext()` inside a method/publication returns its trace and connection context, including across `await`. Outside an invocation all fields are null. Server-initiated calls can have null connection/name; the event still supplies its name. |
|
||||
|
||||
Listeners are best-effort and never awaited. Throws/rejections are isolated
|
||||
from the observed operation; `onListenerError` can report failures to a safe
|
||||
logger. Keep listeners cheap: synchronous work still runs on the server.
|
||||
Do not enforce authorization, reject a method, or promise durable audit writes
|
||||
from a listener. Keep validation and access checks in the actual handler.
|
||||
The package supplies events, not an installed OpenTelemetry/APM backend.
|
||||
|
||||
Arguments, results and IP addresses are off by default. Prefer selected
|
||||
metadata. If a payload is necessary, project approved fields per method:
|
||||
|
||||
```javascript
|
||||
Instrumentation.configureMethod("orders.lookup", {
|
||||
captureArgs: ([orderId]) => ({ orderId }),
|
||||
});
|
||||
```
|
||||
|
||||
Projectors receive defensive copies and outputs still pass through a bounded,
|
||||
cycle-safe preview. Bounded size is not generic secret redaction. Official
|
||||
sensitive Accounts methods remain redacted even with overrides. Global
|
||||
`captureMethodArgs: "preview"` also affects publications; a per-method policy
|
||||
does not protect a same-named publication. `captureMethodResult: "preview"`
|
||||
and `captureClientAddress: true` are separate opt-ins. Keep application
|
||||
credentials out of previews, error summaries and exported logs.
|
||||
|
||||
Stop temporary handles during cleanup. `METEOR_INSTRUMENTATION_DISABLED=1`
|
||||
disables emission initially; `Instrumentation.configure({ enabled: false })`
|
||||
can disable it at runtime. Runtime configuration can override the environment
|
||||
default. Bound and clean up any application-maintained correlation maps.
|
||||
|
||||
## Persistent structured logs
|
||||
|
||||
Use the application's established logger for maintained observability. Meteor's
|
||||
|
||||
@@ -18,7 +18,7 @@ metadata:
|
||||
area: ops
|
||||
tagline: "Ship Meteor 3 apps to production (meteor build, Galaxy, Docker/Kubernetes, settings.json, env vars, Node version matching)."
|
||||
bundle: ["ops"]
|
||||
docs_synced_at: "2026-08-26"
|
||||
docs_synced_at: "2026-09-23"
|
||||
license: MIT
|
||||
---
|
||||
|
||||
@@ -39,9 +39,14 @@ Match the Node version to the bundled Meteor Node:
|
||||
|---|---|
|
||||
| 3.0 | 20 |
|
||||
| 3.1 through 3.4 | 22 |
|
||||
| 3.5+ | 24 |
|
||||
| 3.5.x and 3.6-beta.0 | 24 |
|
||||
| 3.6-beta.1 | 26 (26.8.2) |
|
||||
|
||||
Mismatch causes runtime errors. Run `meteor node -v` to confirm.
|
||||
Run `meteor node -v` and `meteor npm -v` in the target app to confirm.
|
||||
Meteor 3.6-beta.1 bundles npm 11.19.0. Match the deployed runtime and native
|
||||
dependency build environment to that release; rebuild and test native npm
|
||||
modules for Node 26 and the production architecture before deploying beta.1.
|
||||
The host installer prerequisite does not select the bundled runtime.
|
||||
|
||||
## Decision flow
|
||||
|
||||
|
||||
@@ -37,7 +37,10 @@ CMD ["node", "main.js"]
|
||||
|
||||
This sample targets Meteor 3.1 through 3.4. Match both `node:` tags to the
|
||||
bundled Node major: Meteor 3.0 uses Node 20, 3.1 through 3.4 use Node 22,
|
||||
and 3.5+ uses Node 24. Run `meteor node -v` to verify the exact version. On
|
||||
and 3.5.x / 3.6-beta.0 use Node 24. Meteor 3.6-beta.1 uses Node 26.8.2
|
||||
and npm 11.19.0. Match both images and native dependency builds to the exact
|
||||
target release; do not carry Node 24 native binaries into a Node 26 runtime.
|
||||
Run `meteor node -v` and `meteor npm -v` in the target app to verify. On
|
||||
M-series Macs targeting x86_64 Linux, add
|
||||
`--architecture os.linux.x86_64` to `meteor build`.
|
||||
|
||||
|
||||
@@ -48,7 +48,8 @@ Prompt: "On my server `node main.js` crashes with
|
||||
`undefined symbol: node_module_register`."
|
||||
|
||||
Pass if the agent identifies the Node version mismatch (Meteor 3.0 uses Node
|
||||
20, 3.1 through 3.4 use Node 22, and 3.5+ uses Node 24), and instructs running
|
||||
20, 3.1 through 3.4 use Node 22, 3.5.x/beta.0 use Node 24, and
|
||||
3.6-beta.1 uses Node 26), and instructs running
|
||||
`meteor node -v` to find the exact version, then deploying with the matching
|
||||
`node:<N>-bookworm-slim` image.
|
||||
|
||||
@@ -176,3 +177,17 @@ It inspects actual native platform/plugin/configuration changes rather than
|
||||
inferring a binary change from a Meteor release label or an edited filename;
|
||||
native configuration can require a binary even when its compatibility hash is
|
||||
unchanged. Fail if it claims every such edit necessarily changes that hash.
|
||||
|
||||
## Case 17: beta.1 runtime and native modules
|
||||
|
||||
Prompt: "Deploy our Meteor 3.6-beta.1 bundle in Docker. Can we reuse Node 24 images and native modules from our Meteor 3.5.2 build?"
|
||||
|
||||
Pass if the agent: Selects the target Node 26.8.2 runtime, notes bundled npm 11.19.0, verifies meteor node/npm versions, matches build/runtime architecture and rebuilds native modules. Does not reuse Node 24 native binaries or mistake host installer Node for app runtime.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 18: keep earlier runtime
|
||||
|
||||
Prompt: "Our app remains on Meteor 3.5.2, and another app is pinned to 3.6-beta.0. Does the 3.6-beta.1 Node 26 announcement require new Node 26 runtime images for either?"
|
||||
|
||||
Pass if the agent: Retains Node 24 for both targets, checks exact bundled versions, and does not upgrade their runtimes solely because a later beta exists.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
@@ -3,8 +3,8 @@ name: meteor-modern-build-stack
|
||||
description: >
|
||||
Use when configuring or tuning the Meteor 3 modern build stack: SWC
|
||||
transpiler, SWC-based minifier, modern @parcel/watcher, web-arch skipping
|
||||
in development, .meteorignore, and the Rspack bundler integration via the
|
||||
rspack Atmosphere package. Triggers on package.json "meteor": { "modern":
|
||||
in development, .meteorignore, and Rspack integration.
|
||||
Triggers on package.json "meteor": { "modern":
|
||||
true }, .swcrc, swc.config.js, [Transpiler] Used Babel Fallback logs,
|
||||
rspack.config.js, rspack.config.ts, defineConfig from @meteorjs/rspack, Meteor.compileWith*
|
||||
helpers, Meteor.extendConfig, Meteor.extendSwcConfig vs Meteor.replaceSwcConfig,
|
||||
@@ -12,9 +12,10 @@ description: >
|
||||
Meteor.enablePortableBuild, HtmlRspackPlugin customization,
|
||||
RSPACK_DEVSERVER_PORT, TOOL_NODE_FLAGS, pnpm workspaces, Rspack 2,
|
||||
skeleton selection, PWA, Workbox and service-worker build setup.
|
||||
Use this skill when the user asks about SWC vs Babel or Rspack configuration.
|
||||
Use this skill when asked about SWC vs Babel or Rspack configuration.
|
||||
Route existing-app bundler migration to migrate-to-rspack, Blaze PWA
|
||||
scaffolding to meteor-blaze, and jam:offline data to meteor-community-packages.
|
||||
scaffolding to meteor-blaze, declarations to meteor-typescript, and jam:offline
|
||||
data to meteor-community-packages.
|
||||
metadata:
|
||||
author: meteor
|
||||
kind: knowledge
|
||||
@@ -22,7 +23,7 @@ metadata:
|
||||
area: build
|
||||
tagline: "Configure the Meteor 3 modern build stack (SWC transpiler/minifier, `@parcel/watcher`, web-arch skipping, Rspack integration)."
|
||||
bundle: ["essentials"]
|
||||
docs_synced_at: "2026-09-11"
|
||||
docs_synced_at: "2026-09-23"
|
||||
license: MIT
|
||||
---
|
||||
|
||||
@@ -100,11 +101,16 @@ final bundle. Requires entry points in `package.json` and no nested imports
|
||||
in app code. To migrate an existing app, use the `migrate-to-rspack` skill.
|
||||
|
||||
Inspect `.meteor/versions`, `package.json`, and the lockfile. Meteor
|
||||
3.6-beta.0 pairs `rspack@1.4.0-beta360.0`, `@meteorjs/rspack@3.0.0-beta.1`
|
||||
and Rspack 2.2.0; 3.5.2 retains the 1.3.0/2.2.0 integration pairing.
|
||||
See [release pairings](references/rspack-config.md) and
|
||||
[3.6 dependencies and workspaces](references/meteor-3.6-workspaces.md).
|
||||
For Rspack 1-to-2 config migration, use `migrate-to-rspack`.
|
||||
3.6-beta.1 pairs `rspack@1.4.0-beta360.1`, `@meteorjs/rspack@3.0.0-beta.2`
|
||||
and Rspack 2.2.0. Beta.0 retains 1.4.0-beta360.0/3.0.0-beta.1; 3.5.2
|
||||
retains the 1.3.0/2.2.0 integration pairing.
|
||||
See [pairings](references/rspack-config.md) and
|
||||
[dependencies/workspaces](references/meteor-3.6-workspaces.md).
|
||||
For migration, use `migrate-to-rspack`.
|
||||
|
||||
Rspack transpiles TypeScript. Use `meteor-typescript` for declarations and
|
||||
checking; see
|
||||
[checker boundaries](references/rspack-config.md#typescript-declarations).
|
||||
|
||||
## Scaffolds, PWA and offline behavior
|
||||
|
||||
|
||||
@@ -308,3 +308,18 @@ requiring the worker response's `Service-Worker-Allowed` header. It checks
|
||||
actual registration and avoids unnecessarily broad control or an automatic
|
||||
prefix rewrite. Fail if it requires moving a root worker to narrow its scope
|
||||
or treats broader-than-directory scope as always impossible or unrestricted.
|
||||
|
||||
## Case 31: beta.1 pairing and declaration boundary
|
||||
|
||||
Prompt: "Configure Rspack on a new Meteor 3.6-beta.1 TypeScript app with autoInstallDeps false. Does SWC generate native Meteor declarations and type-check it automatically?"
|
||||
|
||||
Pass if the agent: Uses rspack 1.4.0-beta360.1/@meteorjs/rspack 3.0.0-beta.2 and Rspack core/CLI/dev-server 2.2.0 minimums, prepares dependencies with the existing manager and keeps frozen CI. Separates transpilation, explicit native opt-in and local tsc; new templates retain legacy providers. Does not remove zodern:types as a bundler requirement.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 32: standalone declaration resolution near miss
|
||||
|
||||
Prompt: "Our Meteor 3.6-beta.1 bundler works, but meteor/random is any in the editor and local tsc skips our app files. We want type resolution repaired, with no SWC or Rspack migration."
|
||||
|
||||
Pass if the agent hands provider/configuration and source-set checking to
|
||||
meteor-typescript, preserves working build/checker integration and does not
|
||||
change loaders merely because the app uses TypeScript.
|
||||
@@ -1,16 +1,17 @@
|
||||
# Meteor 3.6 dependencies and workspaces
|
||||
|
||||
These decisions start with Meteor 3.6, verified on `3.6-beta.0` with
|
||||
`rspack@1.4.0-beta360.0` and `tools-core@1.4.0-beta360.0`. Earlier 3.x releases
|
||||
`rspack@1.4.0-beta360.0` and `tools-core@1.4.0-beta360.0`. Beta.1 uses
|
||||
`rspack@1.4.0-beta360.1` and `tools-core@1.4.0-beta360.1`. Earlier 3.x releases
|
||||
keep their existing integration and manually managed workspace setup. Inspect
|
||||
the app's release, resolved packages, manifest and workspace lockfile before
|
||||
using a beta-specific version or command.
|
||||
|
||||
## Rspack 2 dependency set
|
||||
|
||||
| Package | Minimum selected by 3.6-beta.0 | Dependency category |
|
||||
| Package | Minimum selected by 3.6 beta | Dependency category |
|
||||
|---|---|---|
|
||||
| `@meteorjs/rspack` | `3.0.0-beta.1` | Development |
|
||||
| `@meteorjs/rspack` | `3.0.0-beta.1` on beta.0; `3.0.0-beta.2` on beta.1 | Development |
|
||||
| `@rspack/core`, `@rspack/cli`, `@rspack/dev-server` | `2.2.0` each | Development |
|
||||
| `@swc/core` | `1.15.32` | Development |
|
||||
| `@rsdoctor/rspack-plugin` | `1.5.9` | Development |
|
||||
|
||||
@@ -14,6 +14,7 @@ Match both integration packages to the Meteor release:
|
||||
| 3.5.1 | `1.2.0` | `2.1.0` | Revised client polyfills and app-extension discovery; retains the v2 helper API. |
|
||||
| 3.5.2 | `1.3.0` | `2.2.0` | Required-dependency diagnostics, mode isolation, TypeScript config dependency tracking, and full-app/TLA fixes. |
|
||||
| 3.6-beta.0 | `1.4.0-beta360.0` | `3.0.0-beta.1` | Rspack 2.2.0, SWC React Compiler, workspace-aware installs and stable cache configuration. |
|
||||
| 3.6-beta.1 | `1.4.0-beta360.1` | `3.0.0-beta.2` | Same Rspack 2 minimums, fixed TypeScript server rebuild lifecycle; Node 26.8.2. |
|
||||
|
||||
Inspect `.meteor/versions`, `package.json`, and the lockfile. Do not install an
|
||||
arbitrary `@meteorjs/rspack` major to obtain one helper; upgrade the Meteor
|
||||
@@ -344,5 +345,19 @@ Auto-added to `.gitignore`. To rename, set in `package.json`:
|
||||
}
|
||||
```
|
||||
|
||||
## TypeScript declarations
|
||||
|
||||
Rspack/SWC transpiles TypeScript but does not type-check it or select Meteor
|
||||
package declarations. Meteor 3.6-beta.1 native declarations require explicit
|
||||
`meteor types` and provider configuration. Ordinary builds and new templates
|
||||
retain legacy providers. Keep working `zodern:types`/`@types/meteor` setups
|
||||
unless the task includes a provider migration; run the app's local `tsc`
|
||||
separately. A configured checker such as the TypeScript scaffold's
|
||||
`TsCheckerRspackPlugin` is a separate layer that can check during builds;
|
||||
preserve it when working. See the
|
||||
`meteor-typescript` skill for provider configuration and checking.
|
||||
If it is not installed, consult the
|
||||
[declaration guide](https://docs.meteor.com/cli/using-core-types).
|
||||
|
||||
---
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/about/modern-build-stack/rspack-bundler-integration.md
|
||||
@@ -14,7 +14,7 @@ metadata:
|
||||
area: data
|
||||
tagline: "Author and debug publications/subscriptions (publish strategies, low-level `added/changed/removed`, authorization, reactive joins)."
|
||||
bundle: ["essentials", "fullstack"]
|
||||
docs_synced_at: "2026-08-25"
|
||||
docs_synced_at: "2026-09-23"
|
||||
license: MIT
|
||||
---
|
||||
|
||||
|
||||
@@ -69,3 +69,17 @@ subscription alive?"
|
||||
Pass if the agent says `this.error` stops the subscription and sends the error
|
||||
to the client. It should recommend a separate data or logging channel for a
|
||||
non-fatal warning.
|
||||
|
||||
## Case 8: optimistic resubscribe in beta.1
|
||||
|
||||
Prompt: "With NO_MERGE_NO_HISTORY and a pending optimistic method write, resubscribing sends another added for the same document. What changes with ddp-client 3.4.2-beta360.1, and who clears documents on unsubscribe?"
|
||||
|
||||
Pass if the agent: Describes merging server fields into the saved snapshot while stub values remain visible until writes settle. Retains application-owned cleanup; does not claim new history or removals on unsubscribe. Scopes cleanup to owned data instead of clearing a shared collection or prescribing private collection handles as a generic fix.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 9: earlier optimistic duplicate add
|
||||
|
||||
Prompt: "Our Meteor 3.5.2 client throws Server sent add for existing id only while a stub write is outstanding during resubscribe. Is duplicate-added tolerance already guaranteed on this version?"
|
||||
|
||||
Pass if the agent: Checks client package and pending-write path, identifies the beta.1 fix boundary, and recommends a compatible tested upgrade or app-level sequencing. Does not claim all older clients support that path or switch publication strategies without considering ownership/cleanup.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
@@ -14,6 +14,15 @@ the subscription stops. Client handling is forgiving: duplicate `added`
|
||||
messages become changes, a `changed` for an unknown ID becomes an add, and a
|
||||
`removed` for an unknown ID is ignored.
|
||||
|
||||
There is an earlier-client exception while an optimistic method write is
|
||||
pending. Meteor 3.6-beta.1's `ddp-client@3.4.2-beta360.1` handles a repeated
|
||||
`added` by merging server fields into the saved server snapshot; the stub's
|
||||
visible value remains until outstanding writes settle. Earlier clients can
|
||||
throw `Server sent add for existing id` in this path. Inspect the client's
|
||||
resolved version and reproduce with a pending write before relying on the fix.
|
||||
It also covers resubscribing under `NO_MERGE_NO_HISTORY`; it does not add
|
||||
server history, ownership merging or unsubscribe removals to that strategy.
|
||||
|
||||
Use this when a collection is supplied by only one publication. It uses less
|
||||
server state than `SERVER_MERGE`, but multiple publications for the same
|
||||
collection can overwrite each other's document view.
|
||||
@@ -23,6 +32,9 @@ collection can overwrite each other's document view.
|
||||
The server remembers nothing about sent documents and does not send removals
|
||||
when the subscription stops. Use only for special send-and-forget queues where
|
||||
the consumer handles retention and stale client documents are intentional.
|
||||
Scope consumer cleanup to documents it owns. Do not clear an entire shared
|
||||
Minimongo collection or use private collection handles as a generic repair;
|
||||
pending optimistic writes and other active subscriptions may still own data.
|
||||
|
||||
## Setting the strategy
|
||||
|
||||
@@ -48,3 +60,4 @@ Meteor.server.getPublicationStrategy("feed");
|
||||
|
||||
---
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/api/meteor.md#publication-strategies
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/generators/changelog/versions/3.6.0.md
|
||||
@@ -0,0 +1,212 @@
|
||||
---
|
||||
name: meteor-react
|
||||
description: >
|
||||
Use when building or debugging React interfaces in Meteor 3: meteor create
|
||||
--react, createRoot, JSX or TSX entry points, Rspack React detection, Fast
|
||||
Refresh, react-meteor-data, useTracker, useSubscribe, useFind, withTracker,
|
||||
Suspense, and Tracker.withComputation. Triggers on isLoading being treated as
|
||||
a boolean, useFind receiving fetch(), stale closure inputs, duplicate tracker
|
||||
side effects, unstable Suspense keys, lost reactivity after await, state reset
|
||||
after refresh, or React tests leaking computations. Use this skill when the
|
||||
user asks about a React skeleton, React Compiler, React-specific rspack.config rules, reactive
|
||||
data hooks, or classic versus Suspense integration. Route general bundler
|
||||
configuration to meteor-modern-build-stack and Meteor 2 upgrades to
|
||||
migrate-to-meteor-3.
|
||||
metadata:
|
||||
author: meteor
|
||||
kind: knowledge
|
||||
meteor: ">=3.0"
|
||||
area: data
|
||||
tagline: "Build and debug Meteor 3 React interfaces (Rspack scaffold, reactive data hooks, Suspense, Fast Refresh, and testing)."
|
||||
bundle: ["react"]
|
||||
docs_synced_at: "2026-09-23"
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# React interfaces for Meteor 3
|
||||
|
||||
React owns rendering and local UI state; Meteor owns reactive data and the
|
||||
build handoff. Components consume authorized data and invoke methods.
|
||||
Publications and methods remain the server authority.
|
||||
|
||||
## Decision flow
|
||||
|
||||
1. For a new JavaScript app, run `meteor create --react <name>`; React is also
|
||||
the default skeleton. For TypeScript and TSX, run
|
||||
`meteor create --typescript <name>`.
|
||||
2. Inspect `package.json`, `.meteor/packages`, `.meteor/versions`, the client
|
||||
entry, and `rspack.config.*`. Skeletons and `react-meteor-data` versions can
|
||||
change independently of this skill.
|
||||
3. Mount one React root from `Meteor.startup` with `createRoot`.
|
||||
4. Pick one `react-meteor-data` surface for a component:
|
||||
- Classic hooks for explicit loading UI and synchronous Minimongo reads.
|
||||
- Suspense hooks only when an upstream Suspense fallback and rejection
|
||||
boundary already own the pending and error states.
|
||||
5. Use `useSubscribe` for readiness, `useFind` for reactive lists with stable
|
||||
document references, and `useTracker` for other Tracker values.
|
||||
6. Keep React-specific Rspack rules here. Route aliases, loaders, code
|
||||
splitting, cache, output, or migration work to the build skills.
|
||||
7. Test UI behavior in a browser-backed client suite and always unmount the
|
||||
rendered root so Tracker computations and subscriptions can stop.
|
||||
|
||||
## Current scaffold
|
||||
|
||||
```bash
|
||||
meteor create --react my-app
|
||||
cd my-app
|
||||
meteor
|
||||
```
|
||||
|
||||
Current Meteor 3.4+ scaffolds use Rspack and `react-meteor-data`. Inspect
|
||||
`.meteor/versions`: Meteor 3 requires 3.0.0+, these examples target 4.0.1, and
|
||||
`references/react-meteor-data.md` records feature floors.
|
||||
|
||||
```jsx
|
||||
import { Meteor } from "meteor/meteor";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { App } from "/imports/ui/App";
|
||||
import "/imports/ui/styles.css";
|
||||
|
||||
Meteor.startup(() => {
|
||||
const container = document.getElementById("react-target");
|
||||
if (!container) throw new Error("Missing #react-target");
|
||||
createRoot(container).render(<App />);
|
||||
});
|
||||
```
|
||||
|
||||
TypeScript uses `client/main.tsx`, a `tsconfig.json`, and usually
|
||||
`rspack.config.ts`. Meteor discovers that TypeScript config directly.
|
||||
|
||||
## Reactive data selection
|
||||
|
||||
| Need | API | Contract |
|
||||
|------|-----|----------|
|
||||
| Subscription readiness | Classic `useSubscribe` | Returns an `isLoading` function. Call it. |
|
||||
| Reactive list | Classic `useFind` | Return a cursor, never `fetch()`. |
|
||||
| User, count, single document, ReactiveVar | Classic `useTracker` | Return the reactive value. Avoid arbitrary side effects. |
|
||||
| Async value with Suspense | Suspense `useTracker` | Supply a stable key and Promise-producing function. |
|
||||
| SSR-capable collection query | Suspense `useFind` | Pass the collection and the `find` argument tuple. |
|
||||
| Existing class component | `withTracker` | Keep it during focused maintenance; plan hooks separately. |
|
||||
|
||||
Classic list scaffold:
|
||||
|
||||
```jsx
|
||||
import { useFind, useSubscribe } from "meteor/react-meteor-data";
|
||||
import { Tasks } from "/imports/api/tasks";
|
||||
|
||||
export function TaskList({ listId }) {
|
||||
const isLoading = useSubscribe("tasks.byList", listId);
|
||||
const tasks = useFind(
|
||||
() => Tasks.find({ listId }, { sort: { createdAt: -1 } }),
|
||||
[listId],
|
||||
);
|
||||
|
||||
if (isLoading()) return <p>Loading...</p>;
|
||||
if (tasks.length === 0) return <p>No tasks.</p>;
|
||||
return <ul>{tasks.map((task) => <li key={task._id}>{task.title}</li>)}</ul>;
|
||||
}
|
||||
```
|
||||
|
||||
`useFind` owns cursor observation and updates only changed document references.
|
||||
Use `useTracker` when a transformed aggregate is clearer. Read
|
||||
`references/react-meteor-data.md` before tuning dependencies or `skipUpdate`.
|
||||
|
||||
## Suspense and async reactivity
|
||||
|
||||
Suspense imports change signatures; they are not drop-in replacements:
|
||||
|
||||
```jsx
|
||||
import { Suspense } from "react";
|
||||
import { useFind, useSubscribe } from "meteor/react-meteor-data/suspense";
|
||||
import { Tasks } from "/imports/api/tasks";
|
||||
|
||||
function TaskList({ listId }) {
|
||||
useSubscribe("tasks.byList", listId);
|
||||
const tasks = useFind(Tasks, [
|
||||
{ listId },
|
||||
{ sort: { createdAt: -1 } },
|
||||
], [listId]);
|
||||
return <ul>{tasks.map((task) => <li key={task._id}>{task.title}</li>)}</ul>;
|
||||
}
|
||||
|
||||
export function TaskScreen({ listId }) {
|
||||
return (
|
||||
<AppErrorBoundary>
|
||||
<Suspense fallback={<p>Loading...</p>}>
|
||||
<TaskList listId={listId} />
|
||||
</Suspense>
|
||||
</AppErrorBoundary>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Treat Suspense `useSubscribe` as a suspension-only call. In the currently
|
||||
audited package, its declared return type and runtime value disagree, so do not
|
||||
consume the return. Read `references/suspense-and-async.md` for stable keys,
|
||||
rejections, SSR, and `Tracker.withComputation` after `await`.
|
||||
|
||||
## Build and refresh ownership
|
||||
|
||||
Rspack detects React from the app's npm dependencies, enables JSX or TSX SWC
|
||||
parsing, and installs and injects React Refresh for client development. A
|
||||
normal React Rspack app does not add the refresh plugin manually.
|
||||
|
||||
Keep `rspack.config.*` minimal. The generated JavaScript skeleton demonstrates
|
||||
an optional SVGR rule; the TypeScript skeleton demonstrates type checking.
|
||||
Compose custom rules through `defineConfig` from `@meteorjs/rspack` without
|
||||
replacing Meteor's SWC defaults.
|
||||
|
||||
For React Compiler, the Meteor 3.6-beta.0 pairing supports SWC; older pairings
|
||||
can retain Babel. Read [compiler setup](references/build-refresh-and-testing.md#react-compiler)
|
||||
for React-version targets and runtime requirements.
|
||||
|
||||
| Request | Owner |
|
||||
|---------|-------|
|
||||
| React detection, JSX or TSX, React Refresh boundary | This skill |
|
||||
| General `rspack.config` helpers, SWC, aliases, cache, chunks | `meteor-modern-build-stack` |
|
||||
| Convert an existing app or legacy build plugin to Rspack | `migrate-to-rspack` |
|
||||
| Meteor-bundler HMR or custom `module.hot` lifecycle | Build skill, then this skill for React symptoms |
|
||||
|
||||
If edits reload the page or reset component state, first determine which
|
||||
bundler compiled the module. In a Rspack client graph, inspect React Refresh
|
||||
boundaries and avoid a second `react-fast-refresh` stack. In a Meteor-bundler
|
||||
graph, verify `hot-module-replacement` and the bundled React Fast Refresh
|
||||
integration. See `references/build-refresh-and-testing.md`.
|
||||
|
||||
## Mutations and tests
|
||||
|
||||
Call `Meteor.callAsync` from event handlers, model pending and rejection in
|
||||
React state, and leave validation and authorization inside the method. Do not
|
||||
write sensitive collections directly from a component.
|
||||
|
||||
For tests, separate a presentational component that accepts data as props from
|
||||
the hook-owning container. Unit-test the former with the project's existing
|
||||
React test library. Test the latter in a browser client with controlled
|
||||
Minimongo or a real publication. Assert rendered behavior, not the number of
|
||||
reactive-function calls, because React can discard work and invoke initial
|
||||
render logic more than once.
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- Treat classic `isLoading` as a boolean. It is a function and must be called.
|
||||
- Pass `Tasks.find().fetch()` to `useFind`. Return the cursor.
|
||||
- Put a subscription inside a `useFind` factory. Subscribe separately.
|
||||
- Call React state setters, methods, analytics, or arbitrary effects inside a
|
||||
`useTracker` reactive function.
|
||||
- Force every classic component onto Suspense. Both surfaces remain useful.
|
||||
- Reuse a generic Suspense key for unrelated mounted computations.
|
||||
- Read a Tracker source only after `await` without restoring the computation.
|
||||
- Add `@rspack/plugin-react-refresh` to project config when Meteor already
|
||||
injected it.
|
||||
- Replace all Rspack SWC options to add one React transform. Extend them.
|
||||
- Mock away all Meteor data behavior in a component integration test.
|
||||
|
||||
## Authoritative resources
|
||||
|
||||
- [Meteor React tutorial](https://docs.meteor.com/tutorials/react/)
|
||||
- [`react-meteor-data` documentation](https://docs.meteor.com/packages/react-meteor-data.html)
|
||||
- [`meteor/react-packages` source and changelog](https://github.com/meteor/react-packages/tree/master/packages/react-meteor-data)
|
||||
- [Meteor Rspack integration](https://docs.meteor.com/about/modern-build-stack/rspack-bundler-integration.html)
|
||||
- [React `createRoot`](https://react.dev/reference/react-dom/client/createRoot)
|
||||
- [React Suspense](https://react.dev/reference/react/Suspense)
|
||||
- `references/eval-cases.md`
|
||||
@@ -0,0 +1,188 @@
|
||||
# React build, refresh, and testing
|
||||
|
||||
## Generated application contract
|
||||
|
||||
Create from the selected Meteor release, then inspect the result:
|
||||
|
||||
```bash
|
||||
meteor create --react my-app
|
||||
meteor create --typescript my-ts-app
|
||||
```
|
||||
|
||||
Current JavaScript React skeletons use:
|
||||
|
||||
```text
|
||||
client/main.jsx
|
||||
server/main.js
|
||||
tests/main.js
|
||||
rspack.config.js
|
||||
```
|
||||
|
||||
Current TypeScript skeletons use `.tsx` and `.ts` entries, a
|
||||
`rspack.config.ts`, `swc.config.ts`, `tsconfig.json`, Meteor package types, and
|
||||
a Rspack type-checking plugin. Both skeletons declare `meteor.mainModule`,
|
||||
`meteor.testModule`, and `meteor.modern` in `package.json`.
|
||||
|
||||
Do not paste dependency versions from documentation into an older app. Match
|
||||
`@meteorjs/rspack` to the Meteor release, run `meteor update --npm`, and commit
|
||||
the resulting `package.json` and lockfile changes.
|
||||
|
||||
## React-specific Rspack behavior
|
||||
|
||||
The Meteor Rspack package currently recognizes React when `react` exists in
|
||||
the app's npm dependencies and `preact` does not. It then:
|
||||
|
||||
- enables JSX for JavaScript entries or TSX for TypeScript entries;
|
||||
- configures the SWC React transform;
|
||||
- keeps `react` and `react-dom` external to the Rspack app bundle;
|
||||
- ensures `@rspack/plugin-react-refresh` and `react-refresh` are installed;
|
||||
- injects the refresh plugin only for client development runs.
|
||||
|
||||
The generated JavaScript config adds only an SVGR rule:
|
||||
|
||||
```javascript
|
||||
const { defineConfig } = require("@meteorjs/rspack");
|
||||
|
||||
module.exports = defineConfig(() => ({
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.svg$/i,
|
||||
issuer: /\.[jt]sx?$/,
|
||||
use: ["@svgr/webpack"],
|
||||
}],
|
||||
},
|
||||
}));
|
||||
```
|
||||
|
||||
Keep this project layer limited to real application needs. Use
|
||||
`Meteor.extendConfig` for composable Rspack fragments and
|
||||
`Meteor.extendSwcConfig` for a narrow SWC change. Do not use
|
||||
`Meteor.replaceSwcConfig` just to add a React transform; replacement discards
|
||||
Meteor's parser, helper, and refresh defaults unless reconstructed exactly.
|
||||
|
||||
## React Compiler
|
||||
|
||||
Meteor 3.6-beta.0 pairs Atmosphere `rspack@1.4.0-beta360.0` with npm
|
||||
`@meteorjs/rspack@3.0.0-beta.1` and Rspack 2.2.0. Beta.1 pairs
|
||||
`rspack@1.4.0-beta360.1` with `@meteorjs/rspack@3.0.0-beta.2` and retains
|
||||
that Rspack minimum. Both pairings support the
|
||||
SWC React Compiler path introduced upstream in Rspack 2.1. Inspect the resolved
|
||||
packages and React major before selecting it. Earlier Meteor/Rspack pairings
|
||||
can keep `babel-plugin-react-compiler` with `babel-loader`; do not copy the
|
||||
new SWC option into an older compiler.
|
||||
|
||||
For React 19:
|
||||
|
||||
```javascript
|
||||
const { defineConfig } = require("@meteorjs/rspack");
|
||||
|
||||
module.exports = defineConfig((Meteor) => ({
|
||||
...Meteor.extendSwcConfig({
|
||||
jsc: {
|
||||
transform: {
|
||||
react: { runtime: "automatic" },
|
||||
reactCompiler: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
}));
|
||||
```
|
||||
|
||||
For React 17 or 18, install `react-compiler-runtime` with the project's package
|
||||
manager and use `reactCompiler: { target: "17" }` or `{ target: "18" }`.
|
||||
Do not upgrade an existing app to React 19 merely because a new scaffold uses
|
||||
it. Preserve Meteor's parser, helpers, and refresh defaults through
|
||||
`extendSwcConfig`. Do not compile the same modules with both compiler paths.
|
||||
|
||||
Before removing Babel, inventory its remaining plugins and verify that the
|
||||
SWC compiler supports the options the app needs. Compare component behavior,
|
||||
production output, and development refresh. Keep a narrow Babel path when
|
||||
required options or other transforms have no verified replacement.
|
||||
|
||||
## Two HMR graphs
|
||||
|
||||
Rspack compiles application modules. Meteor still compiles Atmosphere packages
|
||||
and any modules deliberately delegated with `Meteor.compileWithMeteor`.
|
||||
|
||||
| Module owner | Refresh mechanism |
|
||||
|--------------|-------------------|
|
||||
| Rspack client graph | Rspack HMR plus `@rspack/plugin-react-refresh` |
|
||||
| Meteor bundler graph | `hot-module-replacement` plus Meteor's React Fast Refresh integration |
|
||||
|
||||
Current Rspack React skeletons include `hot-module-replacement` for the second
|
||||
graph. That does not require manually adding `react-fast-refresh` to the Rspack
|
||||
graph. Identify the module owner before changing packages.
|
||||
|
||||
Fast Refresh can preserve local component state only when the edited module
|
||||
remains a valid refresh boundary. If state resets or a full reload occurs:
|
||||
|
||||
1. Inspect the first client console or build error.
|
||||
2. Confirm whether Rspack or Meteor compiled the edited module.
|
||||
3. Keep component modules focused. Move unrelated mutable singletons, Tracker
|
||||
computations, and side-effectful registration into lifecycle-owned modules.
|
||||
4. Verify component export shape and hook order did not change.
|
||||
5. Remove duplicate refresh plugins or manual `module.hot.accept()` code added
|
||||
without a specific non-React resource owner.
|
||||
|
||||
Never use refresh as resource cleanup. Stop timers, observers, global event
|
||||
listeners, and manually created computations through React effects or the
|
||||
owning module's explicit HMR disposal.
|
||||
|
||||
## React-specific test shape
|
||||
|
||||
Use `meteor-testing` for runner and browser-driver setup. This reference only
|
||||
owns React integration behavior.
|
||||
|
||||
Split components when possible:
|
||||
|
||||
```jsx
|
||||
export function TaskListView({ loading, tasks }) {
|
||||
if (loading) return <p>Loading...</p>;
|
||||
return <ul>{tasks.map((task) => <li key={task._id}>{task.title}</li>)}</ul>;
|
||||
}
|
||||
|
||||
export function TaskListContainer({ listId }) {
|
||||
const isLoading = useSubscribe("tasks.byList", listId);
|
||||
const tasks = useFind(() => Tasks.find({ listId }), [listId]);
|
||||
return <TaskListView loading={isLoading()} tasks={tasks} />;
|
||||
}
|
||||
```
|
||||
|
||||
Test `TaskListView` with the React test library already selected by the
|
||||
project. Test `TaskListContainer` in a browser client where Tracker and
|
||||
Minimongo exist. Use controlled Minimongo documents for a hook-focused test or
|
||||
a real authorized publication for an integration test.
|
||||
|
||||
Every test that mounts a root or rendered component must unmount it in cleanup.
|
||||
Flush React updates using the `act` API compatible with the project's installed
|
||||
React version. Do not hardcode an import copied from a different React major.
|
||||
|
||||
Assert user-visible state:
|
||||
|
||||
- loading before subscription readiness;
|
||||
- empty after ready with zero documents;
|
||||
- rows update when Minimongo changes;
|
||||
- rejected method or Suspense Promise reaches error UI;
|
||||
- unmount stops owned work and prevents later state updates.
|
||||
|
||||
Do not assert that a reactive function or effect ran exactly once. Strict Mode
|
||||
and concurrent rendering can replay or discard initial work. Test the committed
|
||||
DOM and resource cleanup instead.
|
||||
|
||||
## Test-mode build checks
|
||||
|
||||
The client test entry is a separate Rspack graph. A green server-only run does
|
||||
not prove JSX or TSX client compilation. In CI:
|
||||
|
||||
1. Configure a browser driver.
|
||||
2. Confirm expected client suites and assertions ran.
|
||||
3. Exercise the real `meteor.testModule` entry.
|
||||
4. Retain a production browser smoke for build-only differences.
|
||||
|
||||
Generated Rspack directories can enter typecheck, lint, or test discovery after
|
||||
the first build. Exclude the active `_build`, `public/build-assets`,
|
||||
`public/build-chunks`, and `private/build-assets` paths in each tool's native
|
||||
configuration, not in `.meteorignore`.
|
||||
|
||||
---
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/about/modern-build-stack/rspack-bundler-integration.md
|
||||
@@ -0,0 +1,205 @@
|
||||
# Evaluation cases for `meteor-react`
|
||||
|
||||
## Case 1: create a current JavaScript React app
|
||||
|
||||
Prompt: "Create the baseline for a new Meteor 3 React app."
|
||||
|
||||
Pass if the agent uses `meteor create --react`, inspects the generated client,
|
||||
server, test, package, and Rspack files for the selected release, and mounts one
|
||||
root with `createRoot` inside `Meteor.startup`. Fail if it reconstructs an old
|
||||
skeleton from memory without inspecting generated state.
|
||||
|
||||
## Case 2: create a TypeScript React app
|
||||
|
||||
Prompt: "I want Meteor, React, TypeScript, and Rspack from the start."
|
||||
|
||||
Pass if the agent uses `meteor create --typescript`, preserves `.tsx` and `.ts`
|
||||
entry points plus `rspack.config.ts`, and inspects generated type and SWC config.
|
||||
Fail if it creates JavaScript first and renames files without updating entries.
|
||||
|
||||
## Case 3: loading never finishes
|
||||
|
||||
Prompt: "`const loading = useSubscribe('tasks')`; `if (loading)` always shows
|
||||
my spinner."
|
||||
|
||||
Pass if the agent calls `loading()`, explains that classic `useSubscribe`
|
||||
returns a function, and keeps the classic import. Bonus if it notes that the
|
||||
call opts into readiness reactivity.
|
||||
|
||||
## Case 4: `useFind` warns about a cursor
|
||||
|
||||
Prompt: "Why does `useFind(() => Tasks.find().fetch())` warn and rerender every
|
||||
row?"
|
||||
|
||||
Pass if the agent returns the cursor without `.fetch()`, keeps subscription
|
||||
ownership in `useSubscribe`, and explains stable unchanged document references.
|
||||
|
||||
## Case 5: list prop changes but query does not
|
||||
|
||||
Prompt: "My `useFind` list stays on the previous `listId`."
|
||||
|
||||
Pass if the agent includes `listId` in the cursor factory and dependency array.
|
||||
Fail if it adds a changing subscription inside the cursor factory.
|
||||
|
||||
## Case 6: side effect fires twice
|
||||
|
||||
Prompt: "An analytics call inside `useTracker` fires twice in development. Is
|
||||
Tracker broken?"
|
||||
|
||||
Pass if the agent removes arbitrary side effects from the reactive function,
|
||||
models them in a commit-owned React effect if needed, and explains that React
|
||||
can discard or replay initial render work. Fail if it suppresses the duplicate
|
||||
with a global flag.
|
||||
|
||||
## Case 7: measured `useTracker` optimization
|
||||
|
||||
Prompt: "A complex Minimongo aggregate is expensive. How should I retain its
|
||||
computation and skip irrelevant updates?"
|
||||
|
||||
Pass if the agent first includes captured inputs in `deps`, measures the
|
||||
render, and uses a narrow `skipUpdate` comparator where true means skip. Fail if
|
||||
it deep-compares the entire result by default.
|
||||
|
||||
## Case 8: keep a class component
|
||||
|
||||
Prompt: "A stable class component uses `withTracker`. Must I rewrite it before
|
||||
upgrading `react-meteor-data`?"
|
||||
|
||||
Pass if the agent verifies the installed package, notes current v4's
|
||||
development deprecation warning, and allows a focused later hooks migration.
|
||||
Fail if it rewrites the component during unrelated work without behavior tests.
|
||||
|
||||
## Case 9: adopt Suspense safely
|
||||
|
||||
Prompt: "Switch this task list from classic hooks to Suspense."
|
||||
|
||||
Pass if the agent changes the import and signatures, adds a Suspense fallback
|
||||
and error boundary, treats `useSubscribe` as a statement, supplies a stable
|
||||
tracker key where needed, and uses the collection plus find-argument tuple for
|
||||
Suspense `useFind`.
|
||||
|
||||
## Case 10: consume a Suspense subscription handle
|
||||
|
||||
Prompt: "TypeScript says Suspense `useSubscribe` returns a handle, so I call
|
||||
`.stop()` on it. Runtime returns null."
|
||||
|
||||
Pass if the agent identifies the current declaration/runtime mismatch, stops
|
||||
consuming the return, and verifies the exact installed package version. Fail if
|
||||
it type-casts the null value to a handle.
|
||||
|
||||
## Case 11: reactive read after `await`
|
||||
|
||||
Prompt: "My Suspense `useTracker` calls a method, then `fetchAsync`, but it
|
||||
never reruns when Minimongo changes."
|
||||
|
||||
Pass if the agent accepts the computation argument and wraps the reactive read
|
||||
after `await` in `Tracker.withComputation(computation, ...)`. Fail if it wraps
|
||||
only the earlier nonreactive method call.
|
||||
|
||||
## Case 12: duplicate React Refresh plugin
|
||||
|
||||
Prompt: "My Rspack config manually adds `@rspack/plugin-react-refresh`, and
|
||||
updates now run twice."
|
||||
|
||||
Pass if the agent confirms React detection and removes the manual duplicate
|
||||
from the Rspack graph while retaining Meteor's generated dependencies. It
|
||||
should distinguish `hot-module-replacement` for Meteor-owned modules.
|
||||
|
||||
## Case 13: state resets on every edit
|
||||
|
||||
Prompt: "Rspack rebuilds quickly, but editing this React component resets its
|
||||
state."
|
||||
|
||||
Pass if the agent identifies the compiling graph, checks the first console
|
||||
error and refresh-boundary export shape, separates unrelated side effects, and
|
||||
does not promise state preservation for every edit.
|
||||
|
||||
## Case 14: React-specific Rspack rule
|
||||
|
||||
Prompt: "Add SVG imports as React components to the generated Meteor React
|
||||
app."
|
||||
|
||||
Pass if the agent extends the generated `defineConfig` with an SVGR rule scoped
|
||||
to JSX or TSX issuers and preserves Meteor's defaults. Route general aliases,
|
||||
chunking, or output configuration to `meteor-modern-build-stack`.
|
||||
|
||||
## Case 15: component integration test
|
||||
|
||||
Prompt: "Test a React task list that uses `useSubscribe` and `useFind`."
|
||||
|
||||
Pass if the agent separates presentational and hook-owning coverage, runs the
|
||||
integration in a browser client with Tracker and Minimongo or a real
|
||||
publication, unmounts the component, and asserts DOM state instead of exact
|
||||
reactive-function call counts.
|
||||
|
||||
## Case 16: server tests only
|
||||
|
||||
Prompt: "My React-only Rspack change passes six server tests, but the runner
|
||||
says browser client tests were not run. Is that enough?"
|
||||
|
||||
Pass if the agent requires a browser driver, verifies client suite counts and
|
||||
the test entry graph, and retains a production browser smoke.
|
||||
|
||||
## Case 17: publication authorization
|
||||
|
||||
Prompt: "Can I hide other users' tasks by filtering them only inside
|
||||
`useFind`?"
|
||||
|
||||
Pass if the agent says no, routes authorization and field projection to
|
||||
`meteor-pubsub`, and treats the component query only as a local view.
|
||||
|
||||
## Case 18: Meteor 2 React migration
|
||||
|
||||
Prompt: "Upgrade this React app from Meteor 2 and convert all data hooks."
|
||||
|
||||
Pass if the agent routes the framework upgrade to `migrate-to-meteor-3`, then
|
||||
uses this skill for the chosen React target. Fail if it forces Suspense as a
|
||||
Meteor 3 requirement.
|
||||
|
||||
## Case 19: Preact project
|
||||
|
||||
Prompt: "Meteor's Rspack integration detected Preact. Should I add React
|
||||
Refresh packages manually?"
|
||||
|
||||
Pass if the agent does not apply the React bundle blindly, notes that Meteor
|
||||
skips React-specific dependencies when Preact is present, and routes general
|
||||
Preact build work to `meteor-modern-build-stack`.
|
||||
|
||||
## Case 20: raw HTML
|
||||
|
||||
Prompt: "Render this user-provided HTML with `dangerouslySetInnerHTML`."
|
||||
|
||||
Pass if the agent routes sanitization and CSP review to `meteor-security` and
|
||||
does not treat React escaping as protection after opting into raw HTML.
|
||||
|
||||
## Case 21: Suspense on an older package line
|
||||
|
||||
Prompt: "This Meteor 3 app pins `react-meteor-data@2.6.3`. Add the Suspense
|
||||
`useFind` import from the current docs without changing dependencies."
|
||||
|
||||
Pass if the agent inspects `.meteor/versions`, says the Suspense entry point
|
||||
begins in 2.7.0 and official Meteor 3 compatibility begins in 3.0.0, and
|
||||
requires an upgrade before using the current API. It should prefer a tested
|
||||
3.0.0+ version, with current examples verified against 4.0.1. Fail if it
|
||||
assumes the Meteor 3 release supplies every package feature.
|
||||
|
||||
## Case 22: React 19 SWC compiler
|
||||
|
||||
Prompt: "Our Meteor 3.6-beta.0 app has the paired Rspack packages and React 19. Enable React Compiler without a second Babel pass."
|
||||
|
||||
Pass if the agent: Uses extendSwcConfig and jsc.transform.reactCompiler true with automatic React runtime, preserves Meteor defaults, and verifies production/component/refresh behavior without adding duplicate transforms.
|
||||
Fail if it contradicts these boundaries or invents unsupported commands.
|
||||
|
||||
## Case 23: React 18 compiler target
|
||||
|
||||
Prompt: "We upgraded the build to Meteor 3.6-beta.0 but must retain React 18. Can SWC React Compiler work without a React major upgrade?"
|
||||
|
||||
Pass if the agent: Keeps React 18, selects target 18 and react-compiler-runtime, verifies installed dependencies, and does not force React 19 or copy the React 19 boolean setting alone.
|
||||
Fail if it contradicts these boundaries or invents unsupported commands.
|
||||
|
||||
## Case 24: older compiler near miss
|
||||
|
||||
Prompt: "This app stays on Meteor 3.5.2 with its paired Rspack packages and Babel React Compiler. Can we simply delete Babel and set jsc.transform.reactCompiler true?"
|
||||
|
||||
Pass if the agent: Rejects assuming the new SWC path exists in the old pairing, retains the required Babel transform or requests a scoped paired upgrade, and inventories other Babel plugins.
|
||||
Fail if it contradicts these boundaries or invents unsupported commands.
|
||||
@@ -0,0 +1,178 @@
|
||||
# Classic `react-meteor-data`
|
||||
|
||||
Use the classic import when the component owns explicit loading UI or needs
|
||||
synchronous Tracker and Minimongo values:
|
||||
|
||||
```javascript
|
||||
import {
|
||||
useFind,
|
||||
useSubscribe,
|
||||
useTracker,
|
||||
withTracker,
|
||||
} from "meteor/react-meteor-data";
|
||||
```
|
||||
|
||||
`react-meteor-data` versions move independently from Meteor core releases.
|
||||
Inspect `.meteor/versions` before relying on a signature or bug fix. The
|
||||
official `meteor/react-packages` master revision audited on 2026-08-25 was
|
||||
`a2dbe228957fc4225b76e9206386861b49b1527b`, package version 4.0.1.
|
||||
|
||||
Use these package floors to diagnose existing apps, not to recommend old
|
||||
package lines for a Meteor 3 app:
|
||||
|
||||
| Capability | First `react-meteor-data` version | Meteor 3 guidance |
|
||||
|---|---|---|
|
||||
| `useTracker` | 2.0.0 | Use 3.0.0+; current examples target 4.0.1. |
|
||||
| `useSubscribe` and `useFind` | 2.4.0 | Use 3.0.0+ and verify the installed signature. |
|
||||
| Suspense hook entry point | 2.7.0 | Use 3.0.0+; do not infer it from the Meteor release. |
|
||||
| Isomorphic Suspense `useFind` | 2.7.2 | Use 3.0.0+ for Meteor 3 compatibility. |
|
||||
| Official Meteor 3 compatibility | 3.0.0 | Minimum package line for Meteor 3 apps. |
|
||||
| `useSubscribeSuspenseServer` | 3.0.3 | Require 3.0.3+ only when that server helper is needed. |
|
||||
|
||||
The current package may contain later fixes without changing a hook's public
|
||||
name. Pin the project version, verify its changelog, and test the selected
|
||||
client and SSR paths before copying a current signature into an older app.
|
||||
|
||||
## Hook selection
|
||||
|
||||
| Hook | Use it for | Return |
|
||||
|------|------------|--------|
|
||||
| `useSubscribe(name, ...args)` | Subscription lifetime and readiness | `() => boolean`, true while loading |
|
||||
| `useFind(factory, deps?)` | Reactive cursor list with stable unchanged document references | Array, or null when factory returns null |
|
||||
| `useTracker(reactiveFn, deps?, skipUpdate?)` | Any other Tracker-derived value | Value returned by `reactiveFn` |
|
||||
| `withTracker(mapper)` | Existing function or class component container | Wrapped component |
|
||||
|
||||
## `useSubscribe`
|
||||
|
||||
The return value is a function:
|
||||
|
||||
```javascript
|
||||
const isLoading = useSubscribe("tasks.byList", listId);
|
||||
|
||||
if (isLoading()) return <Loading />;
|
||||
```
|
||||
|
||||
Calling `isLoading()` both reads readiness and opts the component into the
|
||||
readiness update. Testing `if (isLoading)` is always truthy and never reads the
|
||||
subscription state.
|
||||
|
||||
Use a falsy name to bypass the subscription without conditionally calling a
|
||||
hook:
|
||||
|
||||
```javascript
|
||||
const isLoading = useSubscribe(enabled ? "tasks.byList" : null, listId);
|
||||
```
|
||||
|
||||
When bypassed, `isLoading()` returns false. Changing the name or serialized
|
||||
arguments causes the hook-managed subscription to be replaced and cleaned up.
|
||||
|
||||
## `useFind`
|
||||
|
||||
Return a `Mongo.Cursor`, not its fetched documents:
|
||||
|
||||
```javascript
|
||||
const tasks = useFind(
|
||||
() => Tasks.find({ listId }, {
|
||||
fields: { title: 1, done: 1 },
|
||||
sort: { createdAt: -1 },
|
||||
}),
|
||||
[listId],
|
||||
);
|
||||
```
|
||||
|
||||
`useFind` creates its own cursor observer. It preserves references for
|
||||
unchanged documents, which helps memoized rows avoid unrelated renders.
|
||||
Calling `.fetch()` in the factory defeats that contract and produces a
|
||||
development warning.
|
||||
|
||||
The current v4 implementation defaults `deps` to `[]`. Include every React
|
||||
value captured by the factory when changing that value must create a new
|
||||
cursor. Do not add subscription work to the factory: it runs nonreactively and
|
||||
exists only to select the cursor. Call `useSubscribe` separately.
|
||||
|
||||
Return `null` or `undefined` to disable the cursor without conditionally
|
||||
calling the hook:
|
||||
|
||||
```javascript
|
||||
const tasks = useFind(
|
||||
() => enabled ? Tasks.find({ listId }) : null,
|
||||
[enabled, listId],
|
||||
);
|
||||
```
|
||||
|
||||
Handle the nullable return before mapping.
|
||||
|
||||
## `useTracker`
|
||||
|
||||
Without a dependency array, the hook recreates its computation around renders
|
||||
and returns the first reactive value synchronously:
|
||||
|
||||
```javascript
|
||||
const user = useTracker(() => Meteor.user());
|
||||
```
|
||||
|
||||
With dependencies, the computation is retained until a dependency changes:
|
||||
|
||||
```javascript
|
||||
const task = useTracker(
|
||||
() => Tasks.findOne({ _id: taskId }),
|
||||
[taskId],
|
||||
);
|
||||
```
|
||||
|
||||
Use dependencies for captured inputs and measured expensive computations. Do
|
||||
not add `[]` mechanically to a closure that reads changing props or state.
|
||||
|
||||
The reactive function can receive the current `Tracker.Computation`, although
|
||||
some published type declarations omit that optional argument. Return data from
|
||||
the function. Do not call React state setters or perform analytics, method
|
||||
calls, timers, DOM work, or other arbitrary side effects there. Concurrent
|
||||
rendering, Suspense, and error boundaries can cause an initial reactive
|
||||
function to run more than once before commit.
|
||||
|
||||
Meteor subscriptions created in a `useTracker` computation are stopped with
|
||||
the computation, but prefer `useSubscribe` when only readiness and lifetime
|
||||
are needed.
|
||||
|
||||
## `skipUpdate`
|
||||
|
||||
The comparator returns true to skip an update:
|
||||
|
||||
```javascript
|
||||
const task = useTracker(
|
||||
() => Tasks.findOne(taskId),
|
||||
[taskId],
|
||||
(previous, next) =>
|
||||
previous?._id === next?._id &&
|
||||
previous?.updatedAt?.getTime() === next?.updatedAt?.getTime(),
|
||||
);
|
||||
```
|
||||
|
||||
Use it only after measuring a render problem. Do not deep-compare large query
|
||||
results by default; the comparison can cost more than the render. Prefer
|
||||
`useFind` plus memoized rows for lists.
|
||||
|
||||
## `withTracker`
|
||||
|
||||
Do not rewrite a working class-component container during unrelated
|
||||
maintenance. Current v4 source still exports `withTracker`, but logs a
|
||||
development deprecation warning and directs new code toward hooks. Isolate the
|
||||
data container from the presentational component, then migrate in a focused
|
||||
change with behavior tests.
|
||||
|
||||
## Data and authority boundaries
|
||||
|
||||
- Client hooks query Minimongo synchronously. Do not rewrite render-path reads
|
||||
to server-style async Mongo only because the app uses Meteor 3.
|
||||
- A subscription only delivers what its publication authorizes. Filters and
|
||||
fields in a component are not security controls.
|
||||
- Mutations belong in validated, authorized methods invoked with
|
||||
`Meteor.callAsync`.
|
||||
- Route publication design to `meteor-pubsub`, database semantics to
|
||||
`meteor-mongo-minimongo`, and method design to `meteor-methods`.
|
||||
|
||||
Additional primary source:
|
||||
[`meteor/react-packages`](https://github.com/meteor/react-packages/tree/master/packages/react-meteor-data)
|
||||
|
||||
---
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/packages/react-meteor-data.md
|
||||
@@ -0,0 +1,149 @@
|
||||
# Suspense and async Tracker data
|
||||
|
||||
Import Suspense hooks from a distinct subpath:
|
||||
|
||||
```javascript
|
||||
import {
|
||||
useFind,
|
||||
useSubscribe,
|
||||
useTracker,
|
||||
} from "meteor/react-meteor-data/suspense";
|
||||
```
|
||||
|
||||
Do not switch import paths without changing signatures and adding pending and
|
||||
error ownership.
|
||||
|
||||
## Classic versus Suspense
|
||||
|
||||
| Concern | Classic | Suspense |
|
||||
|---------|---------|----------|
|
||||
| Loading | `const isLoading = useSubscribe(...); isLoading()` | `useSubscribe(...)` throws until ready |
|
||||
| Tracker | `useTracker(reactiveFn, deps?)` | `useTracker(key, asyncReactiveFn, deps?)` |
|
||||
| Find | `useFind(() => Collection.find(...), deps?)` | `useFind(Collection, [selector, options], deps?)` |
|
||||
| Errors | Component state or returned error | Rejected Promise reaches an error boundary |
|
||||
| Server query | First synchronous Tracker read | `useTracker` and `useFind` can suspend server rendering |
|
||||
|
||||
Classic hooks remain supported. Choose Suspense because the application has a
|
||||
deliberate boundary and async rendering strategy, not because it runs Meteor 3.
|
||||
|
||||
## Boundaries
|
||||
|
||||
Every suspending subtree needs a fallback and a rejection owner:
|
||||
|
||||
```jsx
|
||||
<AppErrorBoundary>
|
||||
<Suspense fallback={<TaskListSkeleton />}>
|
||||
<TaskList listId={listId} />
|
||||
</Suspense>
|
||||
</AppErrorBoundary>
|
||||
```
|
||||
|
||||
The nearest Suspense boundary owns pending Promises. A rejected subscription or
|
||||
async tracker result is not a loading state; it must reach an error boundary or
|
||||
another explicit rejection policy.
|
||||
|
||||
Place boundaries by user-visible loading unit. One root-wide fallback can hide
|
||||
the entire application for an isolated refetch.
|
||||
|
||||
## Stable tracker keys
|
||||
|
||||
The first `useTracker` argument indexes a module-level cache. Use a stable,
|
||||
specific key for one logical computation and avoid generic keys reused by
|
||||
unrelated mounted components:
|
||||
|
||||
```javascript
|
||||
const task = useTracker(
|
||||
`task-details:${taskId}`,
|
||||
() => Tasks.findOneAsync(taskId),
|
||||
[taskId],
|
||||
);
|
||||
```
|
||||
|
||||
Keep dependency inputs in the dependency array. A key is cache identity, not a
|
||||
replacement for captured-input dependencies.
|
||||
|
||||
## Reactivity after `await`
|
||||
|
||||
Tracker captures reactive dependencies while its computation is current. An
|
||||
unrelated `await` clears that ambient context. Restore the hook's computation
|
||||
around a later reactive read:
|
||||
|
||||
```javascript
|
||||
import { Tracker } from "meteor/tracker";
|
||||
|
||||
const tasks = useTracker(
|
||||
`visible-tasks:${listId}`,
|
||||
async (computation) => {
|
||||
const access = await Meteor.callAsync("lists.access", listId);
|
||||
if (!access.allowed) return [];
|
||||
|
||||
return Tracker.withComputation(
|
||||
computation,
|
||||
() => Tasks.find({ listId }).fetchAsync(),
|
||||
);
|
||||
},
|
||||
[listId],
|
||||
);
|
||||
```
|
||||
|
||||
If the reactive read occurs before the first `await`, the hook captures it
|
||||
without the extra wrapper. Wrap the smallest reactive read after `await`, not
|
||||
the network request or entire component.
|
||||
|
||||
## Suspense `useSubscribe`
|
||||
|
||||
Use it as a statement:
|
||||
|
||||
```javascript
|
||||
useSubscribe("tasks.byList", listId);
|
||||
```
|
||||
|
||||
At `react-meteor-data` 4.0.1, the published declaration says the hook returns a
|
||||
`Meteor.SubscriptionHandle`, while the client implementation resolves to
|
||||
`null` and the server implementation returns `undefined`. The package docs
|
||||
also say it does not return a handle. Do not consume the return value. If the
|
||||
component must manually stop or inspect a handle, use a separately owned
|
||||
subscription strategy instead of relying on this mismatch.
|
||||
|
||||
The client cache identifies subscriptions from the name and EJSON-serialized
|
||||
parameters and delays cleanup to tolerate React Strict Mode effect replay. Do
|
||||
not reproduce that cache in application code.
|
||||
|
||||
## Suspense `useFind`
|
||||
|
||||
The second argument is the argument tuple passed to `Collection.find`:
|
||||
|
||||
```javascript
|
||||
const tasks = useFind(Tasks, [
|
||||
{ listId },
|
||||
{ fields: { title: 1 }, sort: { createdAt: -1 } },
|
||||
], [listId]);
|
||||
```
|
||||
|
||||
Pass `null` to disable the query. Do not pass a cursor factory or call
|
||||
`.fetch()` as with the classic signature. On the client it observes Minimongo;
|
||||
on the server it uses `fetchAsync()` and suspends until the query resolves.
|
||||
|
||||
## Server rendering limits
|
||||
|
||||
Suspense `useFind` and `useTracker` have server paths, but a client subscription
|
||||
does not populate server-rendered Minimongo. The current Suspense
|
||||
`useSubscribe` server path is a no-op. Design server data preload, request
|
||||
scoping, error handling, and hydration deliberately. Verify the exact package
|
||||
version before relying on changelog-only SSR hooks; the current public subpath
|
||||
exports only `useFind`, `useSubscribe`, and `useTracker`.
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- Consume the Suspense `useSubscribe` return as a handle.
|
||||
- Use the same key such as `"user"` for multiple unrelated mounted trackers.
|
||||
- Put a changing prop only in the key while omitting it from dependencies.
|
||||
- Add Suspense without an error boundary for rejected Promises.
|
||||
- Assume a server-side subscription populated data during SSR.
|
||||
- Wrap every sync Minimongo query in an async Suspense tracker.
|
||||
|
||||
Additional primary source:
|
||||
[`meteor/react-packages` Suspense implementation](https://github.com/meteor/react-packages/tree/master/packages/react-meteor-data/suspense)
|
||||
|
||||
---
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/packages/react-meteor-data.md
|
||||
@@ -16,7 +16,7 @@ metadata:
|
||||
area: security
|
||||
tagline: "Audit and harden Meteor 3 apps (`check()` coverage, `this.userId` guards, browser-policy CSP, rate limits, oauth-encryption)."
|
||||
bundle: ["essentials", "fullstack"]
|
||||
docs_synced_at: "2026-08-25"
|
||||
docs_synced_at: "2026-09-23"
|
||||
license: MIT
|
||||
---
|
||||
|
||||
@@ -132,9 +132,18 @@ decisions; keep their queries fast because the connection waits for them. On
|
||||
Meteor 3.0 through 3.4, matchers must stay synchronous. Use a fixed rule,
|
||||
precomputed synchronous state, or upgrade rather than awaiting Mongo there.
|
||||
|
||||
The default rule (5 in 10s for login / signup / password reset) ships
|
||||
with `accounts-base`. Remove with `Accounts.removeDefaultRateLimit()`
|
||||
only if you replace it.
|
||||
The default rule (5 in 10s per matched method per DDP connection for login / signup / password
|
||||
reset) ships with `accounts-base`. Meteor 3.6-beta.1's
|
||||
`accounts-base@3.4.0-beta360.1` also matches `requestLoginTokenForUser`;
|
||||
`accounts-passwordless@3.1.2-beta360.1` validates its complete payload before
|
||||
lookup/creation. Inspect both package versions on older apps. Remove the
|
||||
default rule with `Accounts.removeDefaultRateLimit()` only if you replace it.
|
||||
|
||||
For cookie hardening on `accounts-base@3.4.0-beta360.1`, use `meteor-accounts`:
|
||||
trusted origins, valid tokens, no-store responses and `SameSite=Strict` have
|
||||
specific migration checks. Its 30-per-10-second HTTP endpoint limit is per
|
||||
client address, separate from DDP. HttpOnly storage does not stop active
|
||||
same-origin XSS from obtaining the resume token used for DDP authentication.
|
||||
|
||||
## OAuth secret encryption
|
||||
|
||||
|
||||
@@ -108,3 +108,10 @@ Prompt: "On Meteor 3.4, make a DDP rate-limit matcher await a user plan lookup."
|
||||
Pass if the agent says async matchers begin in Meteor 3.5, rejects the awaited
|
||||
matcher on 3.4, and offers a synchronous fixed rule, precomputed state, or a
|
||||
framework upgrade. Fail if it applies the current 3.5 API unconditionally.
|
||||
|
||||
## Case 12: Accounts hardening ownership
|
||||
|
||||
Prompt: "Review Meteor 3.6-beta.1 passwordless and HttpOnly-cookie abuse protections. Are their rate limits interchangeable, and does HttpOnly remove our XSS risk?"
|
||||
|
||||
Pass if the agent: Keeps security audit ownership and uses meteor-accounts for configuration details. Separates per-connection DDP and per-address HTTP limits, checks resolved beta packages, preserves method authorization and notes the in-memory DDP token remains exposed to active same-origin XSS.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
@@ -18,7 +18,7 @@ metadata:
|
||||
area: testing
|
||||
tagline: "Set up and write Meteor 3 tests (`meteortesting:mocha`, async signatures, methods/publications, Playwright/Cypress E2E)."
|
||||
bundle: ["fullstack"]
|
||||
docs_synced_at: "2026-09-11"
|
||||
docs_synced_at: "2026-09-23"
|
||||
license: MIT
|
||||
---
|
||||
|
||||
|
||||
@@ -188,3 +188,10 @@ tests do not use jQuery. Should I add it to the app before running test-packages
|
||||
Pass if the agent recognizes the restored driver dependency, adds no app or
|
||||
unneeded package-test dependency, and verifies the UI and expected client/server
|
||||
assertions. Fail if it repeats the 1.6.0 workaround unconditionally.
|
||||
|
||||
## Case 20: CI runtime for beta.1
|
||||
|
||||
Prompt: "Adapt our Node 24 Meteor 3.5.2 test job for a deliberate upgrade to 3.6-beta.1. What runtime and native dependency checks belong in CI?"
|
||||
|
||||
Pass if the agent: Verifies the selected Meteor runtime, uses Node 26.8.2/npm 11.19.0 for beta.1, rebuilds native deps and preserves frozen dependency installation and actual client/server test execution. Does not claim existing 3.5.2 jobs need Node 26.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
@@ -75,8 +75,11 @@ jobs:
|
||||
```
|
||||
|
||||
Node version must match the bundled Node.js for the Meteor version: 3.0 uses
|
||||
Node 20, 3.1 through 3.4 use Node 22, and 3.5+ uses Node 24. Run
|
||||
`meteor node -v` to verify the exact version used by the target release.
|
||||
Node 20, 3.1 through 3.4 use Node 22, and 3.5.x / 3.6-beta.0 use Node 24.
|
||||
Meteor 3.6-beta.1 uses Node 26.8.2 and npm 11.19.0. The example above targets
|
||||
3.1-3.4; adjust its Node selection for the actual job. Run `meteor node -v`
|
||||
and `meteor npm -v` in the target app, rebuild native dependencies for that
|
||||
runtime, and keep dependency installation frozen in CI.
|
||||
|
||||
## Test discovery
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
name: meteor-typescript
|
||||
description: >
|
||||
Use when setting up or repairing Meteor application declarations, TypeScript
|
||||
configuration, JavaScript IntelliSense, or local and CI type-checking.
|
||||
Triggers on meteor types, meteor/* imports resolving to any, missing
|
||||
declarations, duplicate Meteor identifiers, zodern:types, @types/meteor,
|
||||
.meteor/types, tsconfig.json, jsconfig.json, and tsc --noEmit in a Meteor app.
|
||||
Use this skill when choosing or migrating declaration providers without
|
||||
changing the app's runtime or bundler. For a Meteor 2-to-3 runtime migration
|
||||
use migrate-to-meteor-3 first; for SWC/Rspack compilation use
|
||||
meteor-modern-build-stack or migrate-to-rspack. General TypeScript language
|
||||
questions and Atmosphere declaration publishing are outside this app scope.
|
||||
metadata:
|
||||
author: meteor
|
||||
kind: knowledge
|
||||
meteor: ">=3.0"
|
||||
area: build
|
||||
tagline: "Configure Meteor app declarations, TypeScript and JavaScript IntelliSense, and reliable local/CI type-checking."
|
||||
docs_synced_at: "2026-09-23"
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# TypeScript in Meteor applications
|
||||
|
||||
Make the editor and checker resolve the intended Meteor declarations and
|
||||
actually inspect application source. Preserve working provider choices unless
|
||||
the task includes changing them. A runtime or bundler upgrade does not imply
|
||||
a declaration migration.
|
||||
|
||||
For a runtime migration or bundler configuration request, load the owning
|
||||
skill before proposing migration steps or build configuration. This skill's
|
||||
declaration guidance does not supply that procedure; do not substitute a
|
||||
generic TypeScript/Rspack recipe when the owning skill is unavailable.
|
||||
|
||||
## Identify the layer
|
||||
|
||||
| Layer | Evidence and action |
|
||||
|---|---|
|
||||
| Compilation | The Atmosphere `typescript` package or Rspack/SWC strips types. Use the build owner for syntax transforms, loaders and bundling. |
|
||||
| Declaration provider | Inspect `.meteor/packages`, `.meteor/versions`, npm/workspace manifests and lockfile for direct `zodern:types`, `@types/meteor` and native opt-in. |
|
||||
| Resolution | Inspect active `tsconfig.json`/`jsconfig.json`, `extends`, `files`, `include`, `exclude`, `paths` and `types`. Check the editor uses the intended project/compiler. |
|
||||
| Checking | Inspect the installed npm `typescript` and scripts; it is separate from the Atmosphere compiler. Preserve a configured checker such as `TsCheckerRspackPlugin`. |
|
||||
|
||||
Do not infer that an app is checked because `meteor run` or `meteor build`
|
||||
succeeded. Conversely, do not claim an explicitly configured checker never
|
||||
runs just because SWC itself only transpiles.
|
||||
|
||||
## Choose the provider
|
||||
|
||||
| Target and intent | Decision |
|
||||
|---|---|
|
||||
| Meteor 3 before 3.6-beta.1 | Native `meteor types` is unavailable. Keep a working legacy provider; use the earlier-release branch in the provider reference if declarations are missing. |
|
||||
| New or existing 3.6-beta.1 app with working legacy types | Keep them unless native adoption is requested. Beta.1 TypeScript templates still install direct `zodern:types` and `@types/meteor`; a native fallback path is not opt-in. |
|
||||
| Explicit native adoption on 3.6-beta.1 | Root config required. Checkpoint providers/config, remove direct `zodern:types`, generate successfully, then merge native resolution and remove overlapping ambient types. |
|
||||
| JavaScript-only beta.1 app wanting IntelliSense | Use `jsconfig.json` and the same provider decision; no TypeScript source conversion or bundler switch is required. |
|
||||
|
||||
Read [declaration providers](references/declaration-providers.md) for the
|
||||
ordered switch, native adapter/barrel distinction, inherited configuration,
|
||||
TypeScript 7 compatibility, earlier providers and rollback. Read
|
||||
[JavaScript IntelliSense](references/javascript-intellisense.md) for JS apps.
|
||||
|
||||
## Verify the effective project
|
||||
|
||||
1. Confirm generation actually ran. A direct `zodern:types` makes
|
||||
`meteor types` skip with exit zero; ordinary Meteor commands do not select
|
||||
or regenerate native declarations on beta.1.
|
||||
2. Use the app's local compiler. With native declarations, run
|
||||
`meteor types && tsc --noEmit` in a package script; select the intended
|
||||
config explicitly when the app has several projects.
|
||||
3. Check `tsc --listFiles --noEmit` includes application source. Appending a
|
||||
barrel under `files` can disable implicit inclusion; retain existing source
|
||||
patterns and exclusions. A deliberate temporary wrong type should fail;
|
||||
remove the probe and rerun. JavaScript IntelliSense alone does not enable
|
||||
`checkJs`; select JS checking separately when requested.
|
||||
4. Restart the editor's TypeScript server after configuration changes. If
|
||||
CLI and editor disagree, compare selected config/compiler before clearing
|
||||
Meteor state or reinstalling providers.
|
||||
5. Keep generated `.meteor/types/` untracked and unedited. Fix exposed app
|
||||
errors rather than masking them with `any` or a new `skipLibCheck` bypass.
|
||||
|
||||
## Diagnose the boundary
|
||||
|
||||
| Symptom | First check |
|
||||
|---|---|
|
||||
| Native command reports nothing to do | Root `tsconfig.json` or `jsconfig.json`. For a new native-only setup, generate with the root config before adding entries that point to nonexistent output. |
|
||||
| Generation fails | Read the error; local packages may need fixing. Stop the provider switch, preserve config and old output, restore the previous provider for rollback. |
|
||||
| Ordinary imports work, scoped/sub-path imports fail | Explicit native barrel in `files` plus wildcard mapping to per-package adapters, not to the barrel. |
|
||||
| Duplicate identifiers | Overlapping providers, inherited `types: ["meteor"]` and app ambient declarations before symlinks. |
|
||||
| Peer types fail inside Meteor's package store | Consider `preserveSymlinks` for that specific boundary; it cannot remove duplicate providers. |
|
||||
| One community package remains untyped | Check whether the installed package publishes declarations. No generator can promise coverage for every Atmosphere package. |
|
||||
|
||||
If the actual task is publishing package declarations, use the official
|
||||
[Atmosphere package types documentation](https://docs.meteor.com/packages/7.writing-atmosphere-packages#typescript-types).
|
||||
Do not edit generated application adapters as a package-authoring solution.
|
||||
@@ -0,0 +1,144 @@
|
||||
# Meteor declaration providers
|
||||
|
||||
Inspect the release, direct Atmosphere constraints, resolved package versions,
|
||||
npm/workspace manifests, lockfile and all active TypeScript configs before
|
||||
changing providers. Keep compiler upgrades separate from declaration changes.
|
||||
|
||||
## Choose by release and provider
|
||||
|
||||
| Project state | Action |
|
||||
|---|---|
|
||||
| Meteor 3 before 3.6-beta.1 | Native `meteor types` is unavailable. Retain working legacy declarations; use the `zodern:types` branch below when package declarations are missing. |
|
||||
| Upgrading to 3.6-beta.1 with working `@types/meteor` or `zodern:types` | Keep the provider and paths unless the task includes adopting native declarations. Runtime upgrade alone does not switch providers. |
|
||||
| Explicit native adoption on 3.6-beta.1 | Follow the ordered migration below. The command needs a root `tsconfig.json` or `jsconfig.json`. |
|
||||
| Direct `zodern:types` still installed | `meteor types` skips successfully and leaves both output trees unchanged. A zero exit is not proof of native generation. A transitive dependency alone does not select the legacy provider. |
|
||||
|
||||
The classic `typescript` package and Rspack/SWC transpile app source without
|
||||
type-checking it themselves. A separately configured checker, such as the
|
||||
TypeScript scaffold's `TsCheckerRspackPlugin`, is a distinct layer; preserve
|
||||
a working checker when changing declarations. On beta.1, ordinary `run`, `build`, `test` and `lint` neither
|
||||
generate nor select native declarations. New TypeScript templates also keep
|
||||
the legacy provider first; a native fallback path is not an opt-in.
|
||||
|
||||
## Native adoption on Meteor 3.6-beta.1
|
||||
|
||||
1. Checkpoint provider dependencies, lockfile and TypeScript configuration.
|
||||
Keep the app's local TypeScript compiler version fixed during this change.
|
||||
2. Remove `zodern:types` only if it is a direct app dependency, then generate:
|
||||
|
||||
```bash
|
||||
meteor remove zodern:types
|
||||
meteor types
|
||||
```
|
||||
|
||||
Generation can build local packages but does not bundle or type-check the
|
||||
application. On failure, stop before changing provider paths: the command
|
||||
exits nonzero and preserves the old `.meteor/local/types` output. Restore
|
||||
the removed provider if rolling back. Successful generation removes that
|
||||
stale legacy output.
|
||||
3. After success, merge these entries into the active TypeScript config:
|
||||
|
||||
```json
|
||||
{
|
||||
"files": ["./.meteor/types/packages.d.ts"],
|
||||
"include": ["**/*.ts", "**/*.tsx"],
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"meteor/*": ["./.meteor/types/packages/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Append the barrel to existing `files`; retain existing `include`, aliases,
|
||||
compiler options and `extends`. If the app previously had neither `files`
|
||||
nor `include`, adding `files` disables implicit source inclusion: explicitly
|
||||
preserve it with `include: ["**/*"]`, or the app's intended source patterns.
|
||||
Do not broaden an intentionally files-only project. Resolve paths against the config
|
||||
that declares them. The adapters resolve normal package imports; the barrel
|
||||
supplies scoped and sub-path modules such as
|
||||
`meteor/react-meteor-data/suspense`. Explicit `files` works even when
|
||||
`.meteor/**` is excluded. Do not map `meteor/*` directly to the native barrel.
|
||||
4. Remove a direct `@types/meteor` dependency with the project's existing
|
||||
package manager, and remove only `"meteor"` from `compilerOptions.types`
|
||||
wherever it is inherited or declared. Preserve other type libraries and
|
||||
the workspace lockfile. Prefer one provider per Meteor module ID; a hybrid
|
||||
for uncovered packages needs deliberate non-overlap and type-checking.
|
||||
5. Use the app's installed `typescript` compiler, adding a compatible pinned
|
||||
dev dependency only if missing. For an npm app:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"check-types": "meteor types && tsc --noEmit"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
meteor npm run check-types
|
||||
```
|
||||
|
||||
Use the equivalent script runner for pnpm/Yarn. CI must generate before
|
||||
invoking local `tsc`; a successful app build does not prove type safety.
|
||||
Fix errors exposed by corrected declarations without casting everything
|
||||
to `any`. Check `tsc --listFiles --noEmit` includes application source; a
|
||||
deliberate temporary wrong type should fail. Remove that probe and rerun.
|
||||
Restart the editor's TypeScript server after config changes.
|
||||
|
||||
Do not edit or commit `.meteor/types/`; generation replaces its contents and
|
||||
writes its own `.gitignore`. Roll back by restoring legacy dependencies,
|
||||
lockfile and config, then regenerate using the app's previous provider workflow.
|
||||
Ordinary Meteor commands and a skipped native run do not delete either tree.
|
||||
|
||||
## Compiler configuration compatibility
|
||||
|
||||
Inspect the installed npm `typescript`, not only the Atmosphere `typescript`
|
||||
package: they are separate tools. Beta.1's TypeScript scaffold selects npm
|
||||
TypeScript 7 and `moduleResolution: "bundler"`. Do not copy older docs'
|
||||
`baseUrl` or `moduleResolution: "node"` into it.
|
||||
[TypeScript 7 removes both options](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/).
|
||||
`paths` works without `baseUrl` on TypeScript 4.1+; use explicit relative
|
||||
targets, preserving aliases and their previous base directory. Keep an older
|
||||
app's compatible compiler/configuration rather than upgrading its compiler
|
||||
just to change Meteor declarations.
|
||||
|
||||
## Earlier-release legacy declarations
|
||||
|
||||
If required package declarations are missing on an older Meteor 3 app:
|
||||
|
||||
```bash
|
||||
meteor add zodern:types
|
||||
```
|
||||
|
||||
Merge the legacy settings, preserving any intentional working provider order:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"preserveSymlinks": true,
|
||||
"paths": {
|
||||
"meteor/*": ["./.meteor/local/types/packages.d.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Regenerate through the existing provider workflow, restart the editor's
|
||||
TypeScript server, and run the local compiler. Keep generated output untracked.
|
||||
The legacy barrel mapping is not the native adapter mapping.
|
||||
|
||||
## Diagnose the first missing boundary
|
||||
|
||||
| Symptom | Check |
|
||||
|---|---|
|
||||
| `meteor types` reports nothing to do | Root `tsconfig.json` or `jsconfig.json`; do not delete caches. |
|
||||
| Generation says it skipped | Direct `zodern:types` constraint, not only `.meteor/versions`. |
|
||||
| Ordinary imports work but scoped/sub-path imports fail | Explicit native barrel in `files`, not just wildcard `paths`. |
|
||||
| Duplicate identifiers after switching | Overlapping providers, inherited `types: ["meteor"]`, old paths and ambient declarations before blaming symlinks. |
|
||||
| Bundled npm peer types fail under the package store or degrade to `any` | Try `compilerOptions.preserveSymlinks: true` for that resolution boundary. This does not fix overlapping declaration providers. |
|
||||
| One community module has no native adapter | The package may publish no type information. Inspect its version and metadata; do not invent generated declarations or claim all Atmosphere packages are covered. |
|
||||
|
||||
---
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/v3-migration-docs/typescript/meteor-types.md
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/cli/using-core-types.md
|
||||
@@ -0,0 +1,119 @@
|
||||
# TypeScript acceptance cases
|
||||
|
||||
Use the current skill and relevant references in a fresh conversation or a
|
||||
disposable app. Keep pass/fail criteria hidden until the run finishes.
|
||||
|
||||
## Case 1: native provider adoption in a beta.1 app
|
||||
|
||||
Prompt: "Our Meteor 3.6-beta.1 TypeScript app was just created, and we explicitly want native declarations. We have direct zodern:types and @types/meteor, tsconfig extends, a files array and meteor in compilerOptions.types. Give the migration and CI sequence."
|
||||
|
||||
Pass if the agent: Preserves the compiler and app config, checkpoints state, removes direct zodern:types, generates before switching paths/removing @types/meteor, appends the native barrel and per-package adapters, removes only inherited meteor ambient loading, runs local tsc through a script and keeps generated files untracked. Provides rollback without treating compilation as checking.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 2: preserve providers during runtime upgrade
|
||||
|
||||
Prompt: "Upgrade our existing Meteor app to 3.6-beta.1 but keep the working TypeScript provider. meteor types exits zero saying zodern:types is installed. Did it generate native types, and should we remove the provider?"
|
||||
|
||||
Pass if the agent: Keeps the explicit existing-provider preference, explains successful skip and direct dependency precedence, and distinguishes runtime upgrade, native generation and type-checking. Does not remove working providers.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 3: native generation failure
|
||||
|
||||
Prompt: "After removing direct zodern:types on 3.6-beta.1, meteor types fails. Should we replace paths, uninstall @types/meteor and delete .meteor/local/types to finish?"
|
||||
|
||||
Pass if the agent: Stops provider switching until generation succeeds, preserves old output and config, restores the removed package for rollback and reports nonzero generation failure. Does not delete fallback output or invoke a destructive reset.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 4: native scoped imports and mixed providers
|
||||
|
||||
Prompt: "After beta.1 native opt-in, meteor/random resolves but meteor/react-meteor-data/suspense fails. Our tsconfig excludes .meteor and extends a config with types [meteor,node]. Why do we also see duplicate declarations?"
|
||||
|
||||
Pass if the agent: Checks explicit native barrel in files despite exclude, keeps paths mapped to packages/* rather than the barrel, checks installed package declaration coverage and removes overlapping ambient meteor provider while preserving node and unrelated config. Does not blame all failures on preserveSymlinks.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 5: TypeScript 7 configuration during native adoption
|
||||
|
||||
Prompt: "After selecting Meteor 3.6-beta.1 native declarations, our existing TypeScript 7 app reports TS5102 for baseUrl copied from the guide. Should we downgrade TypeScript or copy moduleResolution: node as well? The Rspack config already has TsCheckerRspackPlugin."
|
||||
|
||||
Pass if the agent preserves the compiler and checker, removes the unsupported
|
||||
baseUrl while preserving alias semantics through relative paths, keeps a
|
||||
compatible bundler/nodenext resolution mode, and separates checker behavior
|
||||
from SWC transpilation and native generation. It must not downgrade TypeScript
|
||||
or claim the configured checker does not run just because SWC itself strips types.
|
||||
|
||||
## Case 6: generated barrel hides application source
|
||||
|
||||
Prompt: "After beta.1 native opt-in we added files: [.meteor/types/packages.d.ts] to a tsconfig that previously had neither files nor include. tsc now passes even with a wrong assignment in imports/probe.ts. Are native types working?"
|
||||
|
||||
Pass if the agent checks the effective source set with local tsc --listFiles,
|
||||
explains that adding files removed implicit inclusion, and preserves the
|
||||
previous source set with explicit include patterns while retaining exclusions.
|
||||
It verifies a temporary deliberate type error fails, then removes it and
|
||||
reruns. It must not disable checks or claim a green exit proved app coverage.
|
||||
|
||||
## Case 7: Meteor TypeScript imports become `any`
|
||||
|
||||
Prompt: "After moving from Meteor 2 to Meteor 3.5.2, required package
|
||||
declarations are missing. We want zodern:types; the editor also reports
|
||||
duplicate identifiers. What should we inspect and configure?"
|
||||
|
||||
Pass if the agent checks existing providers and inherited configuration, uses
|
||||
the legacy `zodern:types` workflow with `preserveSymlinks` and the legacy barrel
|
||||
mapping, and restarts the TypeScript server. It must inspect overlapping
|
||||
declarations before attributing duplicates to symlinks, keep generated output
|
||||
untracked, and not prescribe native `meteor types` on 3.5.2.
|
||||
|
||||
## Case 8: JavaScript IntelliSense without conversion
|
||||
|
||||
Prompt: "Our JavaScript-only Meteor 3.6-beta.1 app wants IntelliSense for meteor/random. There is no root tsconfig or jsconfig and no direct zodern:types. We do not want a TypeScript conversion, a bundler change or JS lint errors."
|
||||
|
||||
Pass if the agent adds a root jsconfig, generates native declarations before
|
||||
selecting their paths, includes native adapters/barrel and intended JS source,
|
||||
preserves compatible resolution and verifies editor types. It keeps checkJs
|
||||
and CI error checking optional and does not convert source or add Rspack.
|
||||
|
||||
## Case 9: missing root configuration
|
||||
|
||||
Prompt: "On 3.6-beta.1, meteor types says there is nothing to do. We only have tsconfig files under imports/ui and packages. Should we delete .meteor/local or run meteor reset?"
|
||||
|
||||
Pass if the agent checks for an appropriate root config, preserves nested
|
||||
project ownership, reruns generation, and checks real output. It does not
|
||||
reset application state or assume a successful no-op generated declarations.
|
||||
|
||||
## Case 10: a package is missing from native output
|
||||
|
||||
Prompt: "Native types work for meteor/random but a community package is untyped and has no generated adapter. Another declared package has TS2307 for a bundled peer under the Meteor package store. Should we edit .meteor/types or enable preserveSymlinks for everything?"
|
||||
|
||||
Pass if the agent separates missing declaration metadata from peer resolution,
|
||||
checks installed package/version metadata, tries preserveSymlinks only for the
|
||||
peer boundary, and does not edit generated files or promise universal coverage.
|
||||
Any hybrid provider is deliberate, non-overlapping and checked.
|
||||
|
||||
## Case 11: bundler configuration near miss
|
||||
|
||||
Prompt: "Configure SWC decorators and CSS loaders in rspack.config.ts for our Meteor app. Existing editor types and type-checks already work."
|
||||
|
||||
Pass if the agent routes bundler configuration to meteor-modern-build-stack
|
||||
and leaves working providers alone. The config's .ts suffix alone does not
|
||||
make declarations the primary task.
|
||||
Fail if it supplies a generic Rspack configuration without consulting the
|
||||
Meteor build owner and release pairing.
|
||||
|
||||
## Case 12: runtime migration near miss
|
||||
|
||||
Prompt: "Move this Meteor 2 app to Meteor 3, replacing removed Fibers and propagating async Mongo calls through methods. We use TypeScript but are not changing providers."
|
||||
|
||||
Pass if the agent selects migrate-to-meteor-3 for runtime/API conversion and
|
||||
preserves the working declaration provider. It does not replace that task
|
||||
with native type setup.
|
||||
Fail if it invents a runtime procedure under this skill, including flipping
|
||||
the release before async conversion and package triage.
|
||||
|
||||
## Case 13: package-author boundary
|
||||
|
||||
Prompt: "Publish declarations for my reusable Atmosphere package with api.types and package-types.json. Is editing the app's generated adapter the right workflow?"
|
||||
|
||||
Pass if the agent rejects editing generated adapters and directs the actual
|
||||
package-author workflow to the official Atmosphere types documentation. It
|
||||
does not claim the app-provider skill implements package publication or that
|
||||
api.types exists on every Meteor 3 release.
|
||||
@@ -0,0 +1,59 @@
|
||||
# JavaScript IntelliSense
|
||||
|
||||
Native Meteor-import declarations require Meteor 3.6-beta.1 or later; on an
|
||||
earlier Meteor 3 app retain the existing legacy declarations. A JS app does
|
||||
not need a TypeScript conversion or Rspack migration to obtain editor types.
|
||||
|
||||
Inspect the existing provider and root config first. If `tsconfig.json`
|
||||
already owns these files, configure that project instead of creating a
|
||||
competing `jsconfig.json`. Otherwise create or merge a root `jsconfig.json`,
|
||||
retaining the app's source patterns, aliases, resolver and exclusions.
|
||||
|
||||
For beta.1 native opt-in, follow the generation-before-switch and rollback
|
||||
sequence in [declaration providers](declaration-providers.md). The root config
|
||||
must exist before `meteor types`; a direct `zodern:types` still causes a
|
||||
successful skip. Once generation succeeds, merge:
|
||||
|
||||
```json
|
||||
{
|
||||
"files": ["./.meteor/types/packages.d.ts"],
|
||||
"include": ["**/*.js", "**/*.jsx"],
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"meteor/*": ["./.meteor/types/packages/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Append the barrel to existing `files`; preserve intentional JS/JSX source
|
||||
inclusion and generated-output exclusions. The barrel is explicit even when
|
||||
`.meteor/**` is excluded. Use relative `paths` targets; do not copy removed
|
||||
TypeScript 7 `baseUrl` or `moduleResolution: "node"` options from older
|
||||
examples. Retain a compatible resolver already used by the editor/project.
|
||||
|
||||
Remove overlapping direct `@types/meteor` and only the `meteor` entry from
|
||||
inherited `compilerOptions.types` after successful generation. Restart the
|
||||
editor's TypeScript server and check hover/completion for a public import
|
||||
such as `meteor/random`, plus a used scoped/sub-path import when relevant.
|
||||
If a package supplies no declarations, do not claim generation typed it.
|
||||
|
||||
`jsconfig.json` provides a JavaScript project for editor services; enabling
|
||||
native declarations does not automatically enable JS error checking. If the
|
||||
user also wants CI checks, use the app's compatible local TypeScript compiler
|
||||
and opt into `checkJs` deliberately:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"check-js": "meteor types && tsc --project jsconfig.json --allowJs --checkJs --noEmit"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Verify the intended JS source appears in the compiler's file list and a
|
||||
temporary invalid assignment is rejected. Keep this optional check separate
|
||||
from a request for IntelliSense only. Do not edit or commit generated types.
|
||||
|
||||
---
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/cli/using-core-types.md
|
||||
@@ -7,10 +7,10 @@ description: >
|
||||
dropping a Promise, a read API receiving update modifiers, async allow/deny,
|
||||
an Iron Router controller not running, "Method stub took too long",
|
||||
Atmosphere resolution, Express 5 WebApp handlers, lost async context,
|
||||
rawCollection callbacks, meteor/* TypeScript types, useTracker, and
|
||||
rawCollection callbacks, TypeScript declaration failures during upgrades, useTracker, and
|
||||
useSubscribe. Use this skill when the user asks about upgrading Meteor,
|
||||
async caller propagation, iterators with await, zodern:types, or replacing
|
||||
and forking packages.
|
||||
async caller propagation, iterators with await, or replacing and forking
|
||||
packages. Standalone declarations and type-checking belong to meteor-typescript.
|
||||
metadata:
|
||||
author: meteor
|
||||
kind: knowledge
|
||||
@@ -18,7 +18,7 @@ metadata:
|
||||
area: migration
|
||||
tagline: "Migrate a Meteor 2.x app to 3.x (`callAsync`, async Mongo, Fibers removal, Blaze reactivity, Express 5, Atmosphere resolution)."
|
||||
bundle: ["migration"]
|
||||
docs_synced_at: "2026-08-25"
|
||||
docs_synced_at: "2026-09-23"
|
||||
license: MIT
|
||||
---
|
||||
|
||||
@@ -64,8 +64,12 @@ in phases. Do not flip the framework version flag first.
|
||||
not inside the invoked handler. Verify invocation context before and after
|
||||
`await`. See `references/publications.md` and
|
||||
`references/other-breaking-changes.md`.
|
||||
10. For TypeScript projects, install `zodern:types` and update
|
||||
`tsconfig.json`. See `references/typescript-migration.md`.
|
||||
10. For TypeScript projects, inspect the target release and existing declaration
|
||||
provider. Keep working `@types/meteor` or `zodern:types` setups. Meteor
|
||||
3.6-beta.1 adds explicit native opt-in through `meteor types`; earlier
|
||||
releases retain the legacy workflow. See
|
||||
`references/typescript-migration.md`, then use `meteor-typescript` for
|
||||
provider changes and checking.
|
||||
11. For React projects, decide whether to adopt the Suspense-aware
|
||||
`react-meteor-data` import. See `references/react-migration.md`, then use
|
||||
`meteor-react` for current hook, scaffold, and build guidance.
|
||||
|
||||
@@ -344,12 +344,15 @@ with `try`/`catch` at the owning async boundary.
|
||||
|
||||
## Case 23: Meteor TypeScript imports become `any`
|
||||
|
||||
Prompt: "After moving to Meteor 3, every `meteor/*` TypeScript import is `any`
|
||||
and the editor reports duplicate identifiers."
|
||||
Prompt: "After moving from Meteor 2 to Meteor 3.5.2, required package
|
||||
declarations are missing. We want zodern:types; the editor also reports
|
||||
duplicate identifiers. What should we inspect and configure?"
|
||||
|
||||
Pass if the agent adds `zodern:types`, enables `preserveSymlinks`, maps
|
||||
`meteor/*` to `.meteor/local/types/packages.d.ts`, and restarts the TypeScript
|
||||
server. It must keep generated types out of source control.
|
||||
Pass if the agent checks existing providers and inherited configuration, uses
|
||||
the legacy `zodern:types` workflow with `preserveSymlinks` and the legacy barrel
|
||||
mapping, and restarts the TypeScript server. It must inspect overlapping
|
||||
declarations before attributing duplicates to symlinks, keep generated output
|
||||
untracked, and not prescribe native `meteor types` on 3.5.2.
|
||||
|
||||
## Case 24: React Suspense is optional
|
||||
|
||||
@@ -403,3 +406,35 @@ new Windows workstation and make sure PATH works."
|
||||
Pass if the agent routes the fresh workstation and PATH workflow to
|
||||
`meteor-cli-installation`. Fail if it starts an application code migration or
|
||||
offers the Linux and macOS shell installer on Windows.
|
||||
|
||||
## Case 29: native provider handoff during runtime migration
|
||||
|
||||
Prompt: "Migrate our Meteor 2 TypeScript app to 3.6-beta.1, including async APIs and an explicit native declaration switch. Which workflow owns each part?"
|
||||
|
||||
Pass if the agent keeps runtime/async migration in this skill, preserves the
|
||||
provider through that upgrade, then hands explicit native adoption to
|
||||
meteor-typescript. It checkpoints dependencies and config and stops the
|
||||
provider switch if generation fails. It must not replace async migration with
|
||||
only a type configuration edit or select native declarations before beta.1.
|
||||
|
||||
## Case 30: preserve providers during runtime upgrade
|
||||
|
||||
Prompt: "Upgrade our existing Meteor app to 3.6-beta.1 but keep the working TypeScript provider. meteor types exits zero saying zodern:types is installed. Did it generate native types, and should we remove the provider?"
|
||||
|
||||
Pass if the agent: Keeps the explicit existing-provider preference, explains successful skip and direct dependency precedence, and distinguishes runtime upgrade, native generation and type-checking. Does not remove working providers.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
## Case 33: native Node boundary during upgrade
|
||||
|
||||
Prompt: "For our deliberate Meteor 2 to 3.6-beta.1 migration, can the existing Node 24 production image stay unchanged?"
|
||||
|
||||
Pass if the agent: Uses Node 26.8.2/npm 11.19.0 for beta.1 after checking target runtime, rebuilds native modules and hands deployment details to meteor-deployment. Retains older-release mappings rather than generalizing Node 26 to all Meteor 3.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
|
||||
|
||||
## Case 36: standalone declarations near miss
|
||||
|
||||
Prompt: "The app already runs on Meteor 3.6-beta.1. Only meteor/* editor types and our tsc check are broken; no framework or bundler upgrade is requested."
|
||||
|
||||
Pass if the agent chooses meteor-typescript for provider/resolution/checking
|
||||
and does not start a Meteor 2-to-3 conversion or bundler migration.
|
||||
@@ -97,7 +97,8 @@ Meteor 3 does not have one Node baseline across every minor release:
|
||||
|----------------|--------------|
|
||||
| 3.0 | Node 20 |
|
||||
| 3.1 through 3.4 | Node 22 |
|
||||
| 3.5+ | Node 24 |
|
||||
| 3.5.x and 3.6-beta.0 | Node 24 |
|
||||
| 3.6-beta.1 | Node 26.8.2 (npm 11.19.0) |
|
||||
|
||||
Run `meteor node --version` in the target app and use that version in CI,
|
||||
native dependency builds, and container images. Audit `engines.node` and
|
||||
|
||||
@@ -1,63 +1,31 @@
|
||||
# TypeScript migration
|
||||
# TypeScript checkpoint during a runtime upgrade
|
||||
|
||||
Tight scope: what an existing TypeScript-on-Meteor-2 project must update
|
||||
during the upgrade to Meteor 3. The full TypeScript-on-Meteor setup
|
||||
(fresh projects, advanced patterns, type-helper packages) is out of scope
|
||||
here; a dedicated `meteor-typescript` skill will cover it.
|
||||
Keep declaration-provider changes separate from the Meteor runtime upgrade.
|
||||
Inspect the target release, direct `.meteor/packages` constraints,
|
||||
`.meteor/versions`, npm/workspace manifests, lockfile and active TypeScript
|
||||
configs, including `extends`.
|
||||
|
||||
## What breaks
|
||||
| Target and intent | Migration decision |
|
||||
|---|---|
|
||||
| Earlier Meteor 3 release, including 3.5.2 | Native `meteor types` is unavailable. Preserve working `@types/meteor` or `zodern:types` and verify with the app's existing local checker. |
|
||||
| Meteor 3.6-beta.1 runtime upgrade only | Keep the provider, compiler and config. The upgrade does not select native declarations. |
|
||||
| Explicit native adoption on beta.1 | Checkpoint providers/config and use `meteor-typescript` for the separate declaration migration, editor resolution and CI workflow. |
|
||||
|
||||
After the upgrade, imports from `meteor/*` resolve to `any` or fail
|
||||
outright. The Meteor 2 type-shipping mechanism is no longer compatible
|
||||
with the 3.x build, so any `import { Meteor } from 'meteor/meteor';`
|
||||
loses its types.
|
||||
A direct `zodern:types` makes `meteor types` skip successfully; exit zero
|
||||
alone is not evidence of generation. When explicitly switching, remove only
|
||||
the direct legacy constraint, generate successfully, then change native
|
||||
resolution and remove overlapping ambient types. Stop on generation failure;
|
||||
restore the previous provider/config for rollback rather than deleting old
|
||||
output. The native generator preserves legacy output on failure.
|
||||
|
||||
## What to install
|
||||
|
||||
```bash
|
||||
meteor add zodern:types
|
||||
```
|
||||
|
||||
`zodern:types` ships generated `.d.ts` files keyed off your local Meteor
|
||||
install. It replaces the older approaches used in Meteor 2.
|
||||
|
||||
## `tsconfig.json` updates
|
||||
|
||||
Two changes are required:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"compilerOptions": {
|
||||
// 1. Resolve symlinks the way Meteor's package layout expects.
|
||||
"preserveSymlinks": true,
|
||||
|
||||
// 2. Map meteor/* imports to the generated types directory.
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"meteor/*": [".meteor/local/types/packages.d.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Without `preserveSymlinks: true`, TypeScript follows symlinks in
|
||||
`.meteor/local/build/` and reports duplicate identifier errors. The
|
||||
`paths` mapping is what tells TypeScript where to find type
|
||||
declarations for every `meteor/<package>` import.
|
||||
|
||||
## After the changes
|
||||
|
||||
Restart your TS server (or your editor) so the new `tsconfig.json` is
|
||||
picked up. The first compilation may be slow because `zodern:types`
|
||||
regenerates the types directory on demand.
|
||||
|
||||
## Symptoms
|
||||
|
||||
- `import { Meteor } from 'meteor/meteor';` resolves to `any`, no
|
||||
autocomplete. The `paths` mapping in `tsconfig.json` is missing.
|
||||
- "Cannot find module 'meteor/meteor' or its corresponding type
|
||||
declarations." `zodern:types` is not installed.
|
||||
- "Duplicate identifier 'Meteor'." `preserveSymlinks` is not set.
|
||||
Use `meteor-typescript` for `meteor/*` imports resolving to `any`, duplicate
|
||||
identifiers, inherited `types`, scoped/sub-path imports, TypeScript 7 options
|
||||
and source-inclusion checks. If only this migration skill is installed, the
|
||||
[official declaration guide](https://docs.meteor.com/cli/using-core-types)
|
||||
describes the provider workflow; inspect compatibility with the installed
|
||||
compiler rather than copying an entire config. Compilation and checking are
|
||||
separate; preserve a configured checker and verify actual app source.
|
||||
|
||||
---
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/v3-migration-docs/typescript/meteor-types.md
|
||||
Source: https://github.com/meteor/meteor/blob/devel/v3-docs/docs/cli/using-core-types.md
|
||||
@@ -21,7 +21,7 @@ metadata:
|
||||
area: migration
|
||||
tagline: "Migrate an existing Meteor 3 app to the Rspack bundler integration (`mainModule`, replacing legacy build plugins with loaders)."
|
||||
bundle: ["migration"]
|
||||
docs_synced_at: "2026-09-11"
|
||||
docs_synced_at: "2026-09-23"
|
||||
license: MIT
|
||||
---
|
||||
|
||||
@@ -44,13 +44,12 @@ Match `@meteorjs/rspack` to the Meteor release, not to
|
||||
| 3.5.1 | `1.2.0` | `2.1.0` | Revised client polyfills and extension discovery. |
|
||||
| 3.5.2 | `1.3.0` | `2.2.0` | Dependency diagnostics, mode isolation, full-app/TLA and cache fixes. |
|
||||
| 3.6-beta.0 | `1.4.0-beta360.0` | `3.0.0-beta.1` | Rspack 2.2.0 and workspace-aware installs. |
|
||||
| 3.6-beta.1 | `1.4.0-beta360.1` | `3.0.0-beta.2` | TypeScript rebuild-loop fix; Node 26.8.2. |
|
||||
|
||||
The Atmosphere, Meteor npm integration, and Rspack core package versions are
|
||||
independent. Inspect `.meteor/versions`, `package.json`, and the lockfile.
|
||||
Normal startup aligns required dependencies when automatic installation is
|
||||
enabled. Review and commit those changes. Explicit `meteor update --npm` is
|
||||
an alternative, not an extra required step. Do not pair a newer integration
|
||||
major with an older Meteor release to copy a helper.
|
||||
Inspect `.meteor/versions`, `package.json`, and the lockfile: Atmosphere,
|
||||
Meteor npm integration and Rspack core versions are independent. With automatic
|
||||
installs enabled, startup aligns dependencies; review and commit the changes.
|
||||
`meteor update --npm` is an alternative. Keep the release pairing.
|
||||
|
||||
Already using Rspack? For the Meteor 3.6 beta upgrade, follow
|
||||
[Rspack 1 to 2](references/rspack-2-upgrade.md) and its toolchain checks.
|
||||
@@ -175,7 +174,7 @@ See `references/framework-and-css.md`.
|
||||
| `zodern:melte` (Svelte) | Official Rspack Svelte loader. |
|
||||
| `jorgenvatle:vite` (Vue/Solid) | Native Rspack Vue/Solid loaders. |
|
||||
| `babel-plugin-react-compiler` | SWC on the 3.6 beta pairing; earlier integrations retain Babel. See framework reference. |
|
||||
| `zodern:types` | Still compatible. Keep it. |
|
||||
| `zodern:types` | Keep the working declaration provider during bundler migration; beta.1 native adoption is a separate explicit choice. |
|
||||
|
||||
Plugins acting only on Atmosphere package files can stay. Plugins acting on
|
||||
app-folder files (entry folder excluded) must move to Rspack.
|
||||
|
||||
@@ -357,3 +357,10 @@ input/mode. It requires reproduction through the affected JSX/catalog/loader
|
||||
path and applicable development/production checks before a broader claim.
|
||||
Fail if it declares all plugin 5.x versions broken on Rspack 2, forces the
|
||||
example pin, or dismisses a different project's failure from this one smoke.
|
||||
|
||||
## Case 36: beta.1 upgrade preserves types provider
|
||||
|
||||
Prompt: "Upgrade our existing Rspack app from Meteor 3.5.2 to 3.6-beta.1. Automatic dependency installs are enabled and our zodern:types setup works. Must we migrate types, run update --npm, or rebuild native npm dependencies?"
|
||||
|
||||
Pass if the agent: Uses update --release 3.6-beta.1 then normal startup, checks the beta.1 pairing and lockfile, preserves the current declaration provider and valid config, and verifies Node 26/native module compatibility. Does not mandate a second update --npm or native declaration migration.
|
||||
Fail if it contradicts these boundaries or invents unsupported APIs.
|
||||
@@ -1,7 +1,10 @@
|
||||
# Rspack 1 to 2 in Meteor
|
||||
|
||||
Use this branch for Meteor 3.6, verified on `3.6-beta.0`, with
|
||||
`rspack@1.4.0-beta360.0` and `@meteorjs/rspack@3.0.0-beta.1`.
|
||||
Use this branch for Meteor 3.6 beta. The current audited target is
|
||||
`3.6-beta.1`, with `rspack@1.4.0-beta360.1` and
|
||||
`@meteorjs/rspack@3.0.0-beta.2`. A deliberately pinned `3.6-beta.0` keeps
|
||||
`rspack@1.4.0-beta360.0` and `@meteorjs/rspack@3.0.0-beta.1`; use the
|
||||
requested release instead of silently changing the target.
|
||||
Meteor 3.5.2 keeps `rspack@1.3.0`, `@meteorjs/rspack@2.2.0` and Rspack 1.x.
|
||||
Do not force Rspack 2 into a constrained older release.
|
||||
|
||||
@@ -12,7 +15,7 @@ Do not force Rspack 2 into a constrained older release.
|
||||
2. With default `meteor.autoInstallDeps` enabled, update then start normally:
|
||||
|
||||
```bash
|
||||
meteor update --release 3.6-beta.0
|
||||
meteor update --release 3.6-beta.1
|
||||
meteor run
|
||||
```
|
||||
|
||||
@@ -24,7 +27,8 @@ Do not force Rspack 2 into a constrained older release.
|
||||
test a frozen install. `meteor update --npm` overrides the opt-out for that
|
||||
invocation; do not put a lockfile-rewriting step in immutable CI.
|
||||
3. The beta's required npm minimums are core/CLI/dev-server 2.2.0, Meteor integration
|
||||
3.0.0-beta.1, SWC core 1.15.32, helpers 0.5.23 and Rsdoctor 1.5.9.
|
||||
3.0.0-beta.2 on beta.1 (3.0.0-beta.1 on beta.0), SWC core 1.15.32,
|
||||
helpers 0.5.23 and Rsdoctor 1.5.9.
|
||||
Keep helpers in runtime dependencies, the bundler tools in dev dependencies.
|
||||
Detected React adds refresh plugin 2.0.0 and refresh runtime 0.17.0.
|
||||
Record the resolved versions: compatible newer patches can satisfy these
|
||||
@@ -59,7 +63,7 @@ Also check these [upstream migration boundaries](https://www.rspack.dev/guide/mi
|
||||
|
||||
| Surface | Migration check |
|
||||
|---|---|
|
||||
| Node and ESM | Rspack 2 requires Node `^20.19.0 \|\| >=22.12.0`. Meteor 3.6-beta.0 bundles Node 24.15.0; host Node 18 alone does not prove a Meteor build incompatibility. Identify which binary actually invokes each tool before upgrading that runtime. Keep valid Meteor CommonJS configs/output despite pure-ESM Rspack packages. |
|
||||
| Node and ESM | Rspack 2 requires Node `^20.19.0 \|\| >=22.12.0`. Meteor 3.6-beta.1 bundles Node 26.8.2, beta.0 bundles Node 24.15.0; host Node 18 alone does not prove a Meteor build incompatibility. Identify which binary actually invokes each tool before upgrading that runtime. Keep valid Meteor CommonJS configs/output despite pure-ESM Rspack packages. |
|
||||
| Dev server | `@rspack/dev-server` is now explicit; Meteor's dependency check supplies it. Review custom `devServer.proxy` and `watchFiles` against the v2 guide before reusing old shapes. |
|
||||
| Resolution | Upstream changes cover `.wasm` extension lookup, CSS `@import` conditions and empty `resolve.roots`. Meteor supplies explicit extensions and project roots. Inspect `resolve.byDependency` and custom overrides; test the failing import before changing resolution globally. |
|
||||
| Custom plugins | Review the plugin's Rspack 2 support and the [2.0 breaking-change overview](https://www.rspack.dev/blog/announcing-2-0), including compiler hook and stats API changes when used. |
|
||||
@@ -73,6 +77,11 @@ React Compiler can use the built-in SWC loader on this pairing; see
|
||||
[framework migration](framework-and-css.md). Retain Babel for an older
|
||||
integration or requirements unsupported by the SWC compiler path.
|
||||
|
||||
Native TypeScript declarations are a separate beta.1 opt-in. Preserve a working
|
||||
`zodern:types`/`@types/meteor` setup during Rspack migration. Neither SWC nor
|
||||
normal startup generates native declarations. Preserve a configured checker.
|
||||
Use `meteor-typescript` when the task also includes changing providers.
|
||||
|
||||
## Prove the result
|
||||
|
||||
Use `meteor npm ci` for an npm lockfile, `pnpm install --frozen-lockfile` at
|
||||
@@ -84,6 +93,9 @@ requirement and retest after peer cleanup. Do not convert managers to fix CI.
|
||||
Run development, a rebuild, actual client/server tests, and a production
|
||||
bundle. Exercise CSS, lazy imports, local/workspace packages and custom
|
||||
loaders when present. Boot the extracted bundle and load the browser page.
|
||||
For beta.1, rebuild and exercise native npm dependencies against Node 26.8.2
|
||||
and the deployment architecture before deploying; this is a release migration
|
||||
step, not something to defer until a native module crashes in production.
|
||||
Follow the [validation matrix](validation-matrix.md); reported example startup
|
||||
is not proof that your translations, UI components or offline updates work.
|
||||
For a failure, capture the [migration report](troubleshooting.md#reporting-issues)
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-accounts
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-blaze
|
||||
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-cli-installation
|
||||
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-community-packages
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-debugging
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-deployment
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-methods
|
||||
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-modern-build-stack
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-mongo-minimongo
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-native
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-pubsub
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-react
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-security
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-testing
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-typescript
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/migrate-to-meteor-3
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/migrate-to-rspack
|
||||
@@ -38,7 +38,6 @@ ENV \
|
||||
AVATARS_UPLOAD_EXTERNAL_PROGRAM="" \
|
||||
AVATARS_UPLOAD_MIME_TYPES="" \
|
||||
AVATARS_UPLOAD_MAX_SIZE=0 \
|
||||
RICHER_CARD_COMMENT_EDITOR=false \
|
||||
CARD_OPENED_WEBHOOK_ENABLED=false \
|
||||
MAX_IMAGE_PIXEL="" \
|
||||
IMAGE_COMPRESS_RATIO="" \
|
||||
@@ -152,6 +151,7 @@ ENV \
|
||||
SAML_IDENTIFIER_FORMAT="" \
|
||||
SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
|
||||
SAML_ATTRIBUTES="" \
|
||||
SAML_MERGE_EXISTING_USERS=false \
|
||||
OAUTH_GOOGLE_ENABLED=false \
|
||||
OAUTH_GOOGLE_CLIENT_ID="" \
|
||||
OAUTH_GOOGLE_SECRET="" \
|
||||
|
||||
@@ -29,7 +29,6 @@ services:
|
||||
- MONGO_URL=mongodb://wekandb-dev:27017/wekan
|
||||
- ROOT_URL=http://localhost:3000
|
||||
- WITH_API=true
|
||||
- RICHER_CARD_COMMENT_EDITOR=true
|
||||
- BROWSER_POLICY_ENABLED=true
|
||||
- WRITABLE_PATH=/data
|
||||
depends_on:
|
||||
|
||||
+3
-25
@@ -8,31 +8,9 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
ignore:
|
||||
# Build-time-only (devDependency) Rspack toolchain. These packages compile
|
||||
# the bundle on the developer / CI machine and are NOT shipped in the
|
||||
# deployed WeKan server or client bundle, so their advisories do not affect
|
||||
# a running WeKan instance. (For example webpack-dev-server / @rspack/dev-
|
||||
# server, pulled via @rspack/cli, and the socket.io/ws chain pulled via
|
||||
# @rsdoctor/rspack-plugin, never run in WeKan — it builds with `meteor run`,
|
||||
# not the Rspack CLI or dev-server.)
|
||||
#
|
||||
# They also cannot simply be removed or bumped:
|
||||
# * @meteorjs/rspack re-pins and re-installs @rspack/cli and
|
||||
# @rsdoctor/rspack-plugin into package.json on every build, so deleting
|
||||
# them does not stick.
|
||||
# * The only upgrades Dependabot/npm offer are build-breaking: a
|
||||
# @meteorjs/rspack downgrade, or @rspack/cli 2.0 / Rspack 2.0, which
|
||||
# needs Meteor 3.6 (see https://github.com/meteor/meteor/pull/14360).
|
||||
# WeKan currently runs METEOR@3.5-rc.2.
|
||||
#
|
||||
# So pin them here until Meteor 3.6 + Rspack 2.0 land, then revisit.
|
||||
- dependency-name: "@meteorjs/rspack"
|
||||
- dependency-name: "@rspack/core"
|
||||
- dependency-name: "@rspack/cli"
|
||||
- dependency-name: "@rsdoctor/rspack-plugin"
|
||||
- dependency-name: "css-loader"
|
||||
- dependency-name: "style-loader"
|
||||
# Build tools also need security updates: the bundle visualizer runs a local
|
||||
# report server. Meteor 3.6 now uses Rspack 2, so the old blanket exclusions
|
||||
# no longer apply. Review toolchain compatibility when merging updates.
|
||||
# Playwright end-to-end test harness — pure test-only tooling that never ships in
|
||||
# WeKan. It now depends only on @playwright/test and the official `mongodb` driver
|
||||
# (the heavy, CVE-prone `mongosh` CLI was replaced by helpers/mongo-runner.js).
|
||||
|
||||
@@ -211,13 +211,14 @@ jobs:
|
||||
unzip -q "$zip"
|
||||
# A zip that exists is not a bundle that runs; these are the two files
|
||||
# the AppImage is built around.
|
||||
for f in bundle/main.js bundle/node bundle/ferretdb bundle/start-wekan.sh; do
|
||||
for f in bundle/main.js bundle/node bundle/node-runtime/libatomic.so.1 bundle/ferretdb bundle/start-wekan.sh; do
|
||||
if [ ! -e "$f" ]; then
|
||||
echo "::error::$zip has no $f - it is not a runnable WeKan bundle."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
chmod +x bundle/node bundle/ferretdb bundle/start-wekan.sh
|
||||
python3 releases/check-telemetry.py --bundle bundle
|
||||
du -sh bundle
|
||||
|
||||
- name: Build the AppDir
|
||||
@@ -391,7 +392,7 @@ jobs:
|
||||
# misclassified that missing loader as an application startup bug.
|
||||
# AppDir is the exact tree just packed, so this also avoids extracting
|
||||
# the large image merely to make the capability decision.
|
||||
if ! AppDir/usr/lib/wekan/bundle/node --version >/dev/null 2>&1; then
|
||||
if ! LD_LIBRARY_PATH="$PWD/AppDir/usr/lib/wekan/bundle/node-runtime${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" AppDir/usr/lib/wekan/bundle/node --version >/dev/null 2>&1; then
|
||||
echo "::warning::this runner cannot execute the bundled ${{ matrix.appimage_arch }} Node binary, so the AppImage was packed but not started. It is uploaded unchecked."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -170,13 +170,14 @@ jobs:
|
||||
gh release download '${{ needs.release.outputs.tag }}' \
|
||||
--repo "${{ github.repository }}" --pattern "$zip" --clobber
|
||||
unzip -q "$zip"
|
||||
for f in bundle/main.js bundle/node bundle/ferretdb bundle/start-wekan.sh; do
|
||||
for f in bundle/main.js bundle/node bundle/node-runtime/libatomic.so.1 bundle/ferretdb bundle/start-wekan.sh; do
|
||||
if [ ! -e "$f" ]; then
|
||||
echo "::error::$zip has no $f - it is not a runnable WeKan bundle."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
chmod +x bundle/node bundle/ferretdb bundle/start-wekan.sh
|
||||
python3 releases/check-telemetry.py --bundle bundle
|
||||
du -sh bundle
|
||||
|
||||
# flatpak-builder is for building from source. The bundle IS the build, so
|
||||
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
if: steps.rel.outputs.build == 'yes'
|
||||
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
|
||||
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
name: macOS app
|
||||
|
||||
# Wrap the already published macOS bundles in Finder-launchable .app ZIPs.
|
||||
# Each app carries its own native Node.js, FerretDB, and Meteor server.
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
tag:
|
||||
required: false
|
||||
type: string
|
||||
publish:
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
only:
|
||||
description: 'JSON array of arm64 and/or amd64; empty builds both'
|
||||
required: false
|
||||
default: ''
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to wrap (empty = newest release)'
|
||||
required: false
|
||||
type: string
|
||||
publish:
|
||||
description: 'Attach the app ZIPs to the release'
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
only:
|
||||
description: 'JSON array of arm64 and/or amd64; empty builds both'
|
||||
required: false
|
||||
default: ''
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: wekan-mac-app-${{ inputs.tag || github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
tag: ${{ steps.find.outputs.tag }}
|
||||
version: ${{ steps.find.outputs.version }}
|
||||
steps:
|
||||
- id: find
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
REQUESTED_TAG: ${{ inputs.tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tag="$REQUESTED_TAG"
|
||||
[ -n "$tag" ] || tag="$(gh release list --repo "$GITHUB_REPOSITORY" \
|
||||
--limit 1 --json tagName --jq '.[0].tagName')"
|
||||
[[ "$tag" =~ ^v[0-9]+\.[0-9]+(\.[0-9]+)?$ ]] || {
|
||||
echo "::error::Expected a WeKan release tag, got $tag"; exit 1;
|
||||
}
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${tag#v}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
name: Mac app ${{ matrix.arch }}
|
||||
needs: release
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: arm64
|
||||
bundle_arch: mac-arm64
|
||||
runner: macos-15
|
||||
- arch: amd64
|
||||
bundle_arch: mac-x64
|
||||
runner: macos-15-intel
|
||||
env:
|
||||
BUILD_THIS: ${{ inputs.only == '' || contains(fromJSON(inputs.only), matrix.arch) }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
if: ${{ env.BUILD_THIS == 'true' }}
|
||||
- name: Download and verify the native macOS bundle
|
||||
if: ${{ env.BUILD_THIS == 'true' }}
|
||||
id: bundle
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ needs.release.outputs.tag }}
|
||||
VERSION: ${{ needs.release.outputs.version }}
|
||||
BUNDLE_ARCH: ${{ matrix.bundle_arch }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
zip="wekan-${VERSION}-${BUNDLE_ARCH}.zip"
|
||||
if ! gh release view "$TAG" --repo "$GITHUB_REPOSITORY" \
|
||||
--json assets --jq '.assets[].name' | grep -qxF "$zip"; then
|
||||
echo "::notice::$zip has not been published yet; this app cannot be wrapped."
|
||||
echo "available=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
gh release download "$TAG" --repo "$GITHUB_REPOSITORY" \
|
||||
--pattern "$zip" --pattern "$zip.sha256sum" --clobber
|
||||
shasum -a 256 -c "$zip.sha256sum"
|
||||
mkdir payload
|
||||
ditto -x -k "$zip" payload
|
||||
for file in main.js node ferretdb start-wekan.sh; do
|
||||
[ -f "payload/bundle/$file" ] || {
|
||||
echo "::error::$zip lacks bundle/$file; cannot make a self-contained Mac app."
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
echo "available=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Make the .app and ZIP
|
||||
if: ${{ env.BUILD_THIS == 'true' && steps.bundle.outputs.available == 'true' }}
|
||||
env:
|
||||
VERSION: ${{ needs.release.outputs.version }}
|
||||
MAC_ARCH: ${{ matrix.arch }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p "$PWD/.tools/tmp"
|
||||
export TMPDIR="$PWD/.tools/tmp"
|
||||
bash releases/mac/package-app.sh payload/bundle "$VERSION" "$MAC_ARCH" dist
|
||||
unzip -Z1 "dist/WeKan-${VERSION}-mac-${MAC_ARCH}.app.zip" > "$TMPDIR/app-contents.txt"
|
||||
grep -q "WeKan-${VERSION}-mac-${MAC_ARCH}.app/Contents/MacOS/WeKan" "$TMPDIR/app-contents.txt"
|
||||
|
||||
- name: Smoke test Node.js, FerretDB and Meteor
|
||||
timeout-minutes: 5
|
||||
if: ${{ env.BUILD_THIS == 'true' && steps.bundle.outputs.available == 'true' }}
|
||||
env:
|
||||
VERSION: ${{ needs.release.outputs.version }}
|
||||
MAC_ARCH: ${{ matrix.arch }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
app="$PWD/dist/WeKan-${VERSION}-mac-${MAC_ARCH}.app"
|
||||
command="$app/Contents/Resources/launch-wekan.command"
|
||||
export WRITABLE_PATH="$PWD/.tools/tmp/mac-smoke-data"
|
||||
export PORT=18900 ROOT_URL=http://127.0.0.1:18900
|
||||
export FERRETDB_LISTEN_ADDR=127.0.0.1:28900
|
||||
python3 releases/mac/smoke-app.py "$command" "$ROOT_URL/sign-in" \
|
||||
"$PWD/.tools/tmp/mac-smoke.log"
|
||||
|
||||
- name: Keep Mac smoke log
|
||||
uses: actions/upload-artifact@v7
|
||||
if: ${{ always() && env.BUILD_THIS == 'true' && steps.bundle.outputs.available == 'true' }}
|
||||
with:
|
||||
name: mac-smoke-${{ matrix.arch }}
|
||||
path: .tools/tmp/mac-smoke.log
|
||||
if-no-files-found: ignore
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: ${{ env.BUILD_THIS == 'true' && steps.bundle.outputs.available == 'true' }}
|
||||
with:
|
||||
name: mac-app-${{ matrix.arch }}
|
||||
path: |
|
||||
dist/*.app.zip
|
||||
dist/*.app.zip.sha256sum
|
||||
if-no-files-found: error
|
||||
|
||||
publish:
|
||||
name: Attach Mac apps to the release
|
||||
needs: [release, build]
|
||||
if: ${{ !cancelled() && inputs.publish != false }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/download-artifact@v8
|
||||
continue-on-error: true
|
||||
with:
|
||||
pattern: mac-app-*
|
||||
path: assets
|
||||
merge-multiple: true
|
||||
- name: Upload available Mac apps
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ needs.release.outputs.tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if ! ls assets/*.app.zip >/dev/null 2>&1; then
|
||||
echo "::notice::No Mac app could be wrapped; check the macOS bundle jobs."
|
||||
exit 0
|
||||
fi
|
||||
for zip in assets/*.app.zip; do
|
||||
( cd assets && shasum -a 256 -c "$(basename "$zip").sha256sum" )
|
||||
done
|
||||
gh release upload "$TAG" assets/* --repo "$GITHUB_REPOSITORY" --clobber
|
||||
gh release view "$TAG" --repo "$GITHUB_REPOSITORY" --json assets \
|
||||
--jq '.assets[].name' > published.txt
|
||||
for file in assets/*; do
|
||||
grep -qxF "$(basename "$file")" published.txt || {
|
||||
echo "::error::$(basename "$file") was not attached to $TAG"; exit 1;
|
||||
}
|
||||
done
|
||||
@@ -1,10 +1,10 @@
|
||||
name: Build meteor-spk bundle
|
||||
|
||||
# Manually triggered. Assembles WeKan's modernized meteor-spk (the Sandstorm packaging
|
||||
# tool + its meteor-spk.deps: Node 24, FerretDB, the Mongo 3.x CLIs and the modern
|
||||
# tool + its meteor-spk.deps: Node 26, FerretDB, the Mongo 3.x CLIs and the modern
|
||||
# sandstorm-http-bridge) and zips it as meteor-spk-YYYY-MM-DD_HH_MM_SS.zip — the same kind
|
||||
# of self-contained meteor-spk bundle that https://github.com/sandstorm-io/meteor-spk
|
||||
# releases, but with WeKan's Node 24 / FerretDB deps baked in. Download it to `meteor-spk
|
||||
# releases, but with WeKan's Node 26 / FerretDB deps baked in. Download it to `meteor-spk
|
||||
# pack` WeKan (or any Meteor 3.x app) without re-running build-deps.sh each time.
|
||||
#
|
||||
# gh workflow run meteor-spk.yml
|
||||
@@ -25,7 +25,7 @@ permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
NODE_VERSION: '24'
|
||||
NODE_VERSION: '26'
|
||||
|
||||
jobs:
|
||||
meteor-spk:
|
||||
@@ -39,6 +39,8 @@ jobs:
|
||||
- uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- name: Use npm 12.0.2
|
||||
run: npm install --global npm@12.0.2
|
||||
|
||||
- name: Enable unprivileged user namespaces (Ubuntu 24.04 restricts them)
|
||||
# Same as sandstorm.yml: Ubuntu 24.04's AppArmor blocks the unprivileged user
|
||||
@@ -50,7 +52,7 @@ jobs:
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
bash "$GITHUB_WORKSPACE/releases/apt-install.sh" p7zip-full wget curl build-essential g++ make python3 unzip xz-utils git zip
|
||||
bash "$GITHUB_WORKSPACE/releases/apt-install.sh" p7zip-full wget curl libatomic1 build-essential g++ make python3 unzip xz-utils git zip
|
||||
|
||||
- name: Install Sandstorm (dev, unattended)
|
||||
# build-deps.sh's [bridge] step copies the modern
|
||||
@@ -58,9 +60,9 @@ jobs:
|
||||
# must be installed first — same ordering as sandstorm.yml.
|
||||
run: curl https://install.sandstorm.io | sudo bash -s -- -d
|
||||
|
||||
- name: Assemble modern meteor-spk.deps (Node 24 + FerretDB + Mongo 3.x CLIs)
|
||||
- name: Assemble modern meteor-spk.deps (Node 26 + FerretDB + Mongo 3.x CLIs)
|
||||
# Base = upstream meteor-spk 0.6.0 from dl.sandstorm.io; build-deps.sh swaps in
|
||||
# Node 24, FerretDB, the Mongo 3.x CLIs, the migration launcher/importer, keeps
|
||||
# Node 26, FerretDB, the Mongo 3.x CLIs, the migration launcher/importer, keeps
|
||||
# niscud, and swaps in the modern sandstorm-http-bridge. Produces
|
||||
# $HOME/projects/meteor-spk/meteor-spk-0.6.0 (the meteor-spk tool + deps).
|
||||
run: bash sandstorm-src/build-deps.sh
|
||||
|
||||
@@ -20,10 +20,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Node 24
|
||||
- name: Setup Node 26
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '24'
|
||||
node-version: '26'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Cache Meteor installation
|
||||
@@ -91,10 +91,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Node 24
|
||||
- name: Setup Node 26
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '24'
|
||||
node-version: '26'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Cache Meteor installation
|
||||
@@ -150,7 +150,6 @@ jobs:
|
||||
PORT=3000 \
|
||||
WRITABLE_PATH="$PWD/wekan-writable" \
|
||||
WITH_API=true \
|
||||
RICHER_CARD_COMMENT_EDITOR=false \
|
||||
node output/bundle/main.js > wekan-run.log 2>&1 &
|
||||
# The production server serves the client JS statically, so once :3000
|
||||
# responds the bundle is being served. Wait up to 10 minutes.
|
||||
@@ -220,10 +219,10 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Node 24
|
||||
- name: Setup Node 26
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '24'
|
||||
node-version: '26'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Cache Meteor installation
|
||||
@@ -269,7 +268,6 @@ jobs:
|
||||
PORT=3000 \
|
||||
WRITABLE_PATH="$PWD/wekan-writable" \
|
||||
WITH_API=true \
|
||||
RICHER_CARD_COMMENT_EDITOR=false \
|
||||
node output/bundle/main.js > wekan-run.log 2>&1 &
|
||||
for i in $(seq 1 60); do
|
||||
if curl -sf http://localhost:3000 > /dev/null; then
|
||||
|
||||
@@ -23,9 +23,13 @@ name: Release all missing
|
||||
# downloads the PUBLISHED wekan-<v>-amd64.zip and repacks it, so it can rebuild:
|
||||
#
|
||||
# the six extra architectures s390x ppc64le riscv64 i386 armhf loong64
|
||||
# the AppImages and Flatpaks by calling their own workflows
|
||||
# the AppImages, Mac apps and Flatpaks by calling their own workflows
|
||||
#
|
||||
# It cannot rebuild amd64 itself (that is the Meteor build), nor arm64, win64
|
||||
# The recover job first retries failed jobs from the matching named full-release
|
||||
# run, including native builds, Docker, snap and website. Successful jobs are
|
||||
# preserved. The asset planner below then fills packaging gaps.
|
||||
#
|
||||
# The asset planner alone cannot rebuild amd64 itself (that is the Meteor build), nor arm64, win64
|
||||
# and mac-arm64 (each needs its own kind of runner and its own steps), nor the
|
||||
# Sandstorm .spk. When one of those is missing it says so and names
|
||||
# release-all.yml, rather than pretending.
|
||||
@@ -51,10 +55,12 @@ on:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
actions: write
|
||||
|
||||
env:
|
||||
DO_NOT_TRACK: '1'
|
||||
# Must match release-all.yml: the Node.js major the bundles carry.
|
||||
NODE_VERSION: '24'
|
||||
NODE_VERSION: '26'
|
||||
|
||||
# Never at the same time as a full release run, which would be uploading to the
|
||||
# same assets.
|
||||
@@ -63,7 +69,25 @@ concurrency:
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
recover:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 360
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Check dependency risk indicators before recovery
|
||||
run: python3 releases/remote-release.py --audit
|
||||
- name: Retry failed jobs of the matching full release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
VERSION: ${{ inputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
V="$VERSION"
|
||||
[ -n "$V" ] || V="$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName --jq .tagName)"
|
||||
python3 releases/retry-failed-release.py "$V"
|
||||
|
||||
plan:
|
||||
needs: recover
|
||||
timeout-minutes: 15
|
||||
name: what the release is missing
|
||||
runs-on: ubuntu-latest
|
||||
@@ -71,6 +95,7 @@ jobs:
|
||||
version: ${{ steps.plan.outputs.version }}
|
||||
extra: ${{ steps.plan.outputs.extra }}
|
||||
appimage: ${{ steps.plan.outputs.appimage }}
|
||||
mac: ${{ steps.plan.outputs.mac }}
|
||||
flatpak: ${{ steps.plan.outputs.flatpak }}
|
||||
windows: ${{ steps.plan.outputs.windows }}
|
||||
manual: ${{ steps.plan.outputs.manual }}
|
||||
@@ -78,6 +103,14 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Check dependency risk indicators before release work
|
||||
shell: bash
|
||||
run: python3 releases/remote-release.py --audit
|
||||
|
||||
- name: Audit telemetry source before release work
|
||||
shell: bash
|
||||
run: python3 ./releases/check-telemetry.py --source .
|
||||
|
||||
- id: plan
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -116,7 +149,7 @@ jobs:
|
||||
total="$(wc -l < missing.txt | tr -d ' ')"
|
||||
echo "total=$total" >> "$GITHUB_OUTPUT"
|
||||
|
||||
for kind in extra appimage flatpak windows; do
|
||||
for kind in extra appimage mac flatpak windows; do
|
||||
sels="$(awk -v k="$kind" '$1 == k { print $2 }' missing.txt)"
|
||||
json="$(printf '%s\n' $sels | sed '/^$/d' | jq -R . | jq -sc .)"
|
||||
[ -n "$json" ] || json='[]'
|
||||
@@ -152,7 +185,8 @@ jobs:
|
||||
- name: Say plainly what this run will not do
|
||||
if: ${{ steps.plan.outputs.manual != '' }}
|
||||
run: |
|
||||
echo "::warning::v${{ steps.plan.outputs.version }} is missing ${{ steps.plan.outputs.manual }}, which this workflow cannot build: amd64 is the Meteor build, arm64/win64/mac-arm64 each need their own runner, and the Sandstorm .spk is signed. Run release-all.yml for those."
|
||||
echo "::error::v${{ steps.plan.outputs.version }} still lacks ${{ steps.plan.outputs.manual }} after recovery. Inspect the matching full-release run; older unnamed runs need their failed jobs retried manually."
|
||||
exit 1
|
||||
|
||||
# The six architectures nobody else builds for, repacked from the PUBLISHED
|
||||
# amd64 bundle - which is what makes this possible without a Meteor build.
|
||||
@@ -198,6 +232,10 @@ jobs:
|
||||
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Audit telemetry source before release work
|
||||
shell: bash
|
||||
run: python3 ./releases/check-telemetry.py --source .
|
||||
|
||||
- name: Install dependencies
|
||||
if: ${{ steps.want.outputs.build == 'yes' }}
|
||||
run: |
|
||||
@@ -274,6 +312,18 @@ jobs:
|
||||
publish: true
|
||||
only: ${{ needs.plan.outputs.appimage }}
|
||||
|
||||
mac:
|
||||
name: Mac apps
|
||||
needs: plan
|
||||
if: ${{ needs.plan.outputs.mac != '[]' }}
|
||||
uses: ./.github/workflows/mac.yml
|
||||
permissions:
|
||||
contents: write
|
||||
with:
|
||||
tag: v${{ needs.plan.outputs.version }}
|
||||
publish: true
|
||||
only: ${{ needs.plan.outputs.mac }}
|
||||
|
||||
flatpak:
|
||||
name: Flatpaks
|
||||
needs: plan
|
||||
@@ -326,6 +376,10 @@ jobs:
|
||||
with:
|
||||
path: wekan
|
||||
|
||||
- name: Audit telemetry source before release work
|
||||
shell: bash
|
||||
run: python3 wekan/releases/check-telemetry.py --source wekan
|
||||
|
||||
- name: Is a chart already published for this version?
|
||||
id: check
|
||||
env:
|
||||
@@ -400,11 +454,15 @@ jobs:
|
||||
done:
|
||||
timeout-minutes: 15
|
||||
name: what is still missing
|
||||
needs: [plan, extra-arches, appimage, flatpak, charts]
|
||||
needs: [plan, extra-arches, appimage, mac, flatpak, charts]
|
||||
if: ${{ !cancelled() }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Audit telemetry source before release work
|
||||
shell: bash
|
||||
run: python3 ./releases/check-telemetry.py --source .
|
||||
|
||||
- env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
V: ${{ needs.plan.outputs.version }}
|
||||
|
||||
+380
-187
File diff suppressed because it is too large.
Load diff
@@ -31,7 +31,7 @@ permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
NODE_VERSION: '24'
|
||||
NODE_VERSION: '26'
|
||||
|
||||
jobs:
|
||||
sandstorm-store:
|
||||
@@ -43,6 +43,8 @@ jobs:
|
||||
- uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- name: Use npm 12.0.2
|
||||
run: npm install --global npm@12.0.2
|
||||
|
||||
- name: Enable unprivileged user namespaces (Ubuntu 24.04 restricts them)
|
||||
run: |
|
||||
@@ -51,7 +53,7 @@ jobs:
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
bash "$GITHUB_WORKSPACE/releases/apt-install.sh" p7zip-full wget curl build-essential g++ make python3 unzip xz-utils git
|
||||
bash "$GITHUB_WORKSPACE/releases/apt-install.sh" p7zip-full wget curl libatomic1 build-essential g++ make python3 unzip xz-utils git
|
||||
|
||||
- name: Install Sandstorm (dev, unattended)
|
||||
# Provides the `spk` command used to publish, and the sandstorm-http-bridge that
|
||||
|
||||
@@ -25,7 +25,7 @@ permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
NODE_VERSION: '24'
|
||||
NODE_VERSION: '26'
|
||||
|
||||
jobs:
|
||||
sandstorm:
|
||||
@@ -41,6 +41,8 @@ jobs:
|
||||
- uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
- name: Use npm 12.0.2
|
||||
run: npm install --global npm@12.0.2
|
||||
|
||||
- name: Enable unprivileged user namespaces (Ubuntu 24.04 restricts them)
|
||||
# Ubuntu 24.04's AppArmor defaults kernel.apparmor_restrict_unprivileged_userns=1,
|
||||
@@ -54,7 +56,7 @@ jobs:
|
||||
|
||||
- name: Install system dependencies and Meteor
|
||||
run: |
|
||||
bash "$GITHUB_WORKSPACE/releases/apt-install.sh" p7zip-full wget curl build-essential g++ make python3 unzip xz-utils git qemu-user-static
|
||||
bash "$GITHUB_WORKSPACE/releases/apt-install.sh" p7zip-full wget curl libatomic1 build-essential g++ make python3 unzip xz-utils git qemu-user-static
|
||||
if [ ! -f "$HOME/.meteor/meteor" ]; then curl https://install.meteor.com/ | sh; fi
|
||||
echo "$HOME/.meteor" >> "$GITHUB_PATH"
|
||||
|
||||
@@ -64,9 +66,9 @@ jobs:
|
||||
# bundled one, so the Sandstorm install must be in place first.
|
||||
run: curl https://install.sandstorm.io | sudo bash -s -- -d
|
||||
|
||||
- name: Assemble modern meteor-spk.deps (Node 24 + FerretDB + Mongo 3.x CLIs)
|
||||
- name: Assemble modern meteor-spk.deps (Node 26 + FerretDB + Mongo 3.x CLIs)
|
||||
# Base = upstream meteor-spk 0.6.0 from dl.sandstorm.io (has mongod 3.0 +
|
||||
# niscud). build-deps.sh swaps in Node 24, adds FerretDB + the Mongo 3.x
|
||||
# niscud). build-deps.sh swaps in Node 26, adds FerretDB + the Mongo 3.x
|
||||
# CLIs + the migration launcher/importer, keeps niscud, and swaps in the
|
||||
# modern sandstorm-http-bridge from the Sandstorm install above. No dependency
|
||||
# on the retired releases.wekan.team or the old projects.7z.
|
||||
|
||||
@@ -137,10 +137,14 @@ jobs:
|
||||
}
|
||||
}
|
||||
Write-Host "$zip carries $($names.Count) entries."
|
||||
python releases/check-telemetry.py --archive $zip
|
||||
if ($LASTEXITCODE -ne 0) { throw 'Telemetry audit rejected the Windows bundle.' }
|
||||
|
||||
- uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: 24
|
||||
node-version: 26
|
||||
- name: Use npm 12.0.2
|
||||
run: npm install --global npm@12.0.2
|
||||
|
||||
- name: Work out which members cannot be virtual
|
||||
shell: pwsh
|
||||
|
||||
+28
-24
@@ -6,12 +6,12 @@
|
||||
meteor-base@1.5.2
|
||||
|
||||
# Build system
|
||||
ecmascript@0.19.2-beta360.0
|
||||
ecmascript@0.19.2-beta360.1
|
||||
standard-minifier-js@3.2.0
|
||||
rspack@1.4.0-beta360.0
|
||||
rspack@1.4.0-beta360.1
|
||||
# Declared explicitly because server/modernBrowsers.js imports it, to say that
|
||||
# Yandex Browser is modern and must not be served the legacy bundle (#6557).
|
||||
modern-browsers@0.2.3
|
||||
modern-browsers@0.2.4-beta360.1
|
||||
|
||||
blaze@3.0.2
|
||||
|
||||
@@ -19,11 +19,11 @@ blaze@3.0.2
|
||||
aldeed:collection2
|
||||
aldeed:schema-index@4.0.0-beta.5
|
||||
reywood:publish-composite
|
||||
mongo@2.5.1
|
||||
mongo@2.5.2-beta360.1
|
||||
|
||||
# Account system
|
||||
accounts-password@3.3.1
|
||||
accounts-2fa@3.1.0
|
||||
accounts-password@3.3.2-beta360.1
|
||||
accounts-2fa@3.1.1-beta360.1
|
||||
accounts-express@1.0.0
|
||||
communitypackages:core
|
||||
communitypackages:unstyled
|
||||
@@ -39,18 +39,18 @@ wekan-oidc
|
||||
wekan-accounts-oidc
|
||||
|
||||
# Utilities
|
||||
check@1.5.0
|
||||
random@1.2.2
|
||||
reactive-dict@1.3.2
|
||||
session@1.2.3
|
||||
tracker@1.3.4
|
||||
check@1.5.1-beta360.1
|
||||
random@1.2.3-beta360.1
|
||||
reactive-dict@1.3.3-beta360.1
|
||||
session@1.2.4-beta360.1
|
||||
tracker@1.3.5-beta360.1
|
||||
audit-argument-checks@1.0.8
|
||||
|
||||
# UI components
|
||||
ostrio:i18n
|
||||
reactive-var@1.0.13
|
||||
shell-server@0.7.0
|
||||
email@3.2.0
|
||||
shell-server@0.7.1-beta360.1
|
||||
email@3.2.1-beta360.1
|
||||
dynamic-import@0.7.4
|
||||
wekan-markdown
|
||||
quave:synced-cron
|
||||
@@ -59,17 +59,21 @@ ostrio:files
|
||||
# lmieulet:meteor-coverage
|
||||
meteortesting:mocha@3.0.0
|
||||
matb33:collection-hooks
|
||||
service-configuration@1.3.5
|
||||
service-configuration@1.3.6-beta360.1
|
||||
minifier-css@2.0.2
|
||||
ejson@1.2.0
|
||||
logging@1.3.6
|
||||
ejson@1.2.1-beta360.1
|
||||
logging@1.3.7-beta360.1
|
||||
wekan-fullcalendar
|
||||
wekan-fontawesome
|
||||
accounts-google@1.4.1
|
||||
accounts-github@1.5.1
|
||||
accounts-facebook@1.3.4
|
||||
accounts-twitter@1.5.2
|
||||
accounts-meteor-developer@1.5.1
|
||||
accounts-weibo@1.4.1
|
||||
accounts-meetup@1.5.1
|
||||
accounts-passwordless@3.1.1
|
||||
accounts-google@1.4.2-beta360.1
|
||||
accounts-github@1.5.2-beta360.1
|
||||
accounts-facebook@1.3.5-beta360.1
|
||||
accounts-twitter@1.5.3-beta360.1
|
||||
accounts-meteor-developer@1.5.2-beta360.1
|
||||
accounts-weibo@1.4.2-beta360.1
|
||||
accounts-meetup@1.5.2-beta360.1
|
||||
accounts-passwordless@3.1.2-beta360.1
|
||||
instrumentation
|
||||
|
||||
# Prevent Meteor build/run tools from sending application package statistics.
|
||||
package-stats-opt-out@1.0.8
|
||||
+1
-1
@@ -1 +1 @@
|
||||
METEOR@3.6-beta.0
|
||||
METEOR@3.6-beta.1
|
||||
+68
-66
@@ -1,113 +1,115 @@
|
||||
accounts-2fa@3.1.0
|
||||
accounts-base@3.3.1
|
||||
accounts-2fa@3.1.1-beta360.1
|
||||
accounts-base@3.4.0-beta360.1
|
||||
accounts-express@1.0.0
|
||||
accounts-facebook@1.3.4
|
||||
accounts-github@1.5.1
|
||||
accounts-google@1.4.1
|
||||
accounts-meetup@1.5.1
|
||||
accounts-meteor-developer@1.5.1
|
||||
accounts-oauth@1.4.7
|
||||
accounts-password@3.3.1
|
||||
accounts-passwordless@3.1.1
|
||||
accounts-twitter@1.5.2
|
||||
accounts-weibo@1.4.1
|
||||
accounts-facebook@1.3.5-beta360.1
|
||||
accounts-github@1.5.2-beta360.1
|
||||
accounts-google@1.4.2-beta360.1
|
||||
accounts-meetup@1.5.2-beta360.1
|
||||
accounts-meteor-developer@1.5.2-beta360.1
|
||||
accounts-oauth@1.4.8-beta360.1
|
||||
accounts-password@3.3.2-beta360.1
|
||||
accounts-passwordless@3.1.2-beta360.1
|
||||
accounts-twitter@1.5.3-beta360.1
|
||||
accounts-weibo@1.4.2-beta360.1
|
||||
aldeed:collection2@4.2.2
|
||||
aldeed:schema-index@4.0.0
|
||||
aldeed:simple-schema@1.13.1
|
||||
allow-deny@2.1.0
|
||||
allow-deny@2.1.1-beta360.1
|
||||
audit-argument-checks@1.0.8
|
||||
autoupdate@2.0.1
|
||||
babel-compiler@7.15.2-beta360.0
|
||||
autoupdate@2.0.2-beta360.1
|
||||
babel-compiler@7.15.2-beta360.1
|
||||
babel-runtime@1.5.2
|
||||
base64@1.0.14
|
||||
binary-heap@1.0.13
|
||||
base64@1.0.15-beta360.1
|
||||
binary-heap@1.0.14-beta360.1
|
||||
blaze@3.0.3
|
||||
blaze-tools@2.0.1
|
||||
boilerplate-generator@2.1.0
|
||||
caching-compiler@2.0.1
|
||||
caching-html-compiler@2.0.1
|
||||
callback-hook@1.8.0
|
||||
check@1.5.0
|
||||
callback-hook@1.8.1-beta360.1
|
||||
check@1.5.1-beta360.1
|
||||
communitypackages:core@2.0.3
|
||||
communitypackages:flow-routing@2.1.0
|
||||
communitypackages:unstyled@2.0.1
|
||||
core-runtime@1.0.0
|
||||
ddp@1.4.2
|
||||
ddp-client@3.4.1
|
||||
ddp@1.4.3-beta360.1
|
||||
ddp-client@3.4.2-beta360.1
|
||||
ddp-common@1.4.5
|
||||
ddp-rate-limiter@1.3.0
|
||||
ddp-server@3.4.0
|
||||
diff-sequence@1.1.3
|
||||
ddp-rate-limiter@1.3.1-beta360.1
|
||||
ddp-server@3.4.1-beta360.1
|
||||
diff-sequence@1.1.4-beta360.1
|
||||
dynamic-import@0.7.4
|
||||
ecmascript@0.19.2-beta360.0
|
||||
ecmascript@0.19.2-beta360.1
|
||||
ecmascript-runtime@0.8.3
|
||||
ecmascript-runtime-client@0.13.0
|
||||
ecmascript-runtime-server@0.11.1
|
||||
ejson@1.2.0
|
||||
email@3.2.0
|
||||
ejson@1.2.1-beta360.1
|
||||
email@3.2.1-beta360.1
|
||||
es5-shim@4.8.1
|
||||
facebook-oauth@1.11.6
|
||||
facts-base@1.0.2
|
||||
facebook-oauth@1.11.7-beta360.1
|
||||
facts-base@1.0.3-beta360.1
|
||||
fetch@0.2.0
|
||||
geojson-utils@1.0.12
|
||||
github-oauth@1.4.2
|
||||
google-oauth@1.4.5
|
||||
geojson-utils@1.0.13-beta360.1
|
||||
github-oauth@1.4.3-beta360.1
|
||||
google-oauth@1.4.6-beta360.1
|
||||
hot-code-push@1.0.5
|
||||
html-tools@2.0.1
|
||||
htmljs@2.0.2
|
||||
id-map@1.2.0
|
||||
id-map@1.2.1-beta360.1
|
||||
instrumentation@0.0.1-beta360.1
|
||||
inter-process-messaging@0.1.3
|
||||
jquery@3.0.2
|
||||
lai:collection-extensions@1.0.0
|
||||
localstorage@1.2.1
|
||||
logging@1.3.6
|
||||
logging@1.3.7-beta360.1
|
||||
matb33:collection-hooks@2.1.0
|
||||
meetup-oauth@1.1.3
|
||||
meteor@2.3.1
|
||||
meetup-oauth@1.1.4-beta360.1
|
||||
meteor@2.3.2-beta360.1
|
||||
meteor-base@1.5.2
|
||||
meteor-developer-oauth@1.3.3
|
||||
meteor-developer-oauth@1.3.4-beta360.1
|
||||
meteortesting:browser-tests@1.8.0
|
||||
meteortesting:mocha@3.4.0
|
||||
meteortesting:mocha-core@8.2.0
|
||||
minifier-css@2.0.2
|
||||
minifier-js@3.3.2-beta360.0
|
||||
minimongo@2.2.0
|
||||
modern-browsers@0.2.3
|
||||
minifier-js@3.3.2-beta360.1
|
||||
minimongo@2.2.1-beta360.1
|
||||
modern-browsers@0.2.4-beta360.1
|
||||
modules@0.20.3
|
||||
modules-runtime@0.13.2
|
||||
mongo@2.5.1
|
||||
mongo@2.5.2-beta360.1
|
||||
mongo-decimal@0.2.0
|
||||
mongo-dev-server@1.1.1
|
||||
mongo-id@1.0.9
|
||||
mongo-id@1.0.10-beta360.1
|
||||
npm-mongo@6.16.3
|
||||
oauth@3.0.4
|
||||
oauth1@1.5.3
|
||||
oauth@3.0.5-beta360.1
|
||||
oauth1@1.5.4-beta360.1
|
||||
oauth2@1.3.3
|
||||
observe-sequence@2.0.1
|
||||
ordered-dict@1.2.0
|
||||
ordered-dict@1.2.1-beta360.1
|
||||
ostrio:cookies@2.9.2
|
||||
ostrio:cstorage@4.0.1
|
||||
ostrio:files@3.0.1
|
||||
ostrio:flow-router-extra@3.15.3
|
||||
ostrio:i18n@3.2.1
|
||||
promise@1.0.0
|
||||
package-stats-opt-out@1.0.8
|
||||
promise@1.0.1-beta360.1
|
||||
quave:synced-cron@2.4.0
|
||||
raix:eventemitter@1.0.0
|
||||
random@1.2.2
|
||||
rate-limit@1.2.0
|
||||
random@1.2.3-beta360.1
|
||||
rate-limit@1.2.1-beta360.1
|
||||
react-fast-refresh@0.3.0
|
||||
reactive-dict@1.3.2
|
||||
reactive-dict@1.3.3-beta360.1
|
||||
reactive-var@1.0.13
|
||||
reload@1.3.2
|
||||
retry@1.1.1
|
||||
reload@1.3.3-beta360.1
|
||||
retry@1.1.2-beta360.1
|
||||
reywood:publish-composite@1.9.0
|
||||
routepolicy@1.1.2
|
||||
rspack@1.4.0-beta360.0
|
||||
service-configuration@1.3.5
|
||||
session@1.2.3
|
||||
sha@1.0.10
|
||||
shell-server@0.7.0
|
||||
socket-stream-client@0.7.1
|
||||
routepolicy@1.1.3-beta360.1
|
||||
rspack@1.4.0-beta360.1
|
||||
service-configuration@1.3.6-beta360.1
|
||||
session@1.2.4-beta360.1
|
||||
sha@1.0.11-beta360.1
|
||||
shell-server@0.7.1-beta360.1
|
||||
socket-stream-client@0.7.2-beta360.1
|
||||
spacebars@2.0.1
|
||||
spacebars-compiler@2.0.1
|
||||
standard-minifier-js@3.2.0
|
||||
@@ -115,14 +117,14 @@ templating@1.4.5
|
||||
templating-compiler@2.0.1
|
||||
templating-runtime@2.0.2
|
||||
templating-tools@2.0.1
|
||||
tools-core@1.4.0-beta360.0
|
||||
tracker@1.3.4
|
||||
twitter-oauth@1.3.4
|
||||
typescript@5.11.2-beta360.0
|
||||
url@1.3.6
|
||||
webapp@2.3.0
|
||||
webapp-hashing@1.1.2
|
||||
weibo-oauth@1.3.3
|
||||
tools-core@1.4.0-beta360.1
|
||||
tracker@1.3.5-beta360.1
|
||||
twitter-oauth@1.3.5-beta360.1
|
||||
typescript@5.11.2-beta360.1
|
||||
url@1.3.7-beta360.1
|
||||
webapp@2.3.1-beta360.1
|
||||
webapp-hashing@1.1.3-beta360.1
|
||||
weibo-oauth@1.3.4-beta360.1
|
||||
wekan-accounts-cas@0.2.0
|
||||
wekan-accounts-lockout@1.1.0
|
||||
wekan-accounts-oidc@1.0.10
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-accounts
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-blaze
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-cli-installation
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-community-packages
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-debugging
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-deployment
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-methods
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-modern-build-stack
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-mongo-minimongo
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-native
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-pubsub
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-react
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-security
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-testing
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/meteor-typescript
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/migrate-to-meteor-3
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../.agents/skills/migrate-to-rspack
|
||||
+4984
-260
File diff suppressed because it is too large.
Load diff
+12
-5
@@ -20,7 +20,7 @@ LABEL org.opencontainers.image.source="https://github.com/wekan/wekan"
|
||||
# TARGETARCH and TARGETVARIANT are automatically provided by Docker Buildx
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
ARG VERSION=11.80
|
||||
ARG VERSION=12.02
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV BUILD_DEPS="apt-utils gnupg wget bzip2 g++ curl libarchive-tools build-essential git ca-certificates python3 unzip"
|
||||
@@ -28,10 +28,10 @@ ENV BUILD_DEPS="apt-utils gnupg wget bzip2 g++ curl libarchive-tools build-essen
|
||||
ENV \
|
||||
DEBUG=false \
|
||||
DDP_TRANSPORT=sockjs \
|
||||
NODE_VERSION=v24.21.0 \
|
||||
METEOR_RELEASE=METEOR@3.6-beta.0 \
|
||||
NODE_VERSION=v26.10.0 \
|
||||
METEOR_RELEASE=METEOR@3.6-beta.1 \
|
||||
USE_EDGE=false \
|
||||
NPM_VERSION=11.12.1 \
|
||||
NPM_VERSION=12.1.0 \
|
||||
SRC_PATH=./ \
|
||||
WITH_API=true \
|
||||
MONGO_OPLOG_URL="" \
|
||||
@@ -50,7 +50,6 @@ ENV \
|
||||
AVATARS_UPLOAD_EXTERNAL_PROGRAM="" \
|
||||
AVATARS_UPLOAD_MIME_TYPES="" \
|
||||
AVATARS_UPLOAD_MAX_SIZE=72000 \
|
||||
RICHER_CARD_COMMENT_EDITOR=false \
|
||||
CARD_OPENED_WEBHOOK_ENABLED=false \
|
||||
MAX_IMAGE_PIXEL="" \
|
||||
IMAGE_COMPRESS_RATIO="" \
|
||||
@@ -175,6 +174,7 @@ ENV \
|
||||
SAML_IDENTIFIER_FORMAT="" \
|
||||
SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
|
||||
SAML_ATTRIBUTES="" \
|
||||
SAML_MERGE_EXISTING_USERS=false \
|
||||
OAUTH_GOOGLE_ENABLED=false \
|
||||
OAUTH_GOOGLE_CLIENT_ID="" \
|
||||
OAUTH_GOOGLE_SECRET="" \
|
||||
@@ -225,6 +225,9 @@ COPY --chmod=755 releases/resolve-node-source.sh /tmp/resolve-node-source.sh
|
||||
# The two travel together: without this line the resolve step dies on the first
|
||||
# lookup. tests/releaseDownloads.test.cjs pins the pair.
|
||||
COPY --chmod=755 releases/fetch.sh /tmp/fetch.sh
|
||||
COPY --chmod=755 releases/check-telemetry.py /tmp/check-telemetry.py
|
||||
COPY releases/risk-baseline.json /tmp/risk-baseline.json
|
||||
COPY --chmod=755 releases/prepare-bundle-npm.mjs /tmp/prepare-bundle-npm.mjs
|
||||
# The bundle's `npm install` leaves node-gyp's whole tree - 83 of the 120
|
||||
# packages in programs/server/node_modules - in a bundle that compiles nothing at
|
||||
# run time, and a scan of the published image reads it as what it is. The same
|
||||
@@ -261,6 +264,8 @@ useradd --user-group --system --create-home --home-dir /home/wekan wekan
|
||||
apt-get update --assume-yes
|
||||
apt-get upgrade --assume-yes
|
||||
apt-get install --assume-yes --no-install-recommends ${BUILD_DEPS}
|
||||
# Runtime MIME detection and Node.js atomic operations survive build cleanup.
|
||||
apt-get install --assume-yes --no-install-recommends file libatomic1
|
||||
|
||||
# Multi-arch mapping: Docker TARGETARCH -> WeKan's own platform name, which is
|
||||
# both the bundle .zip's name and what resolve-node-source.sh is asked about.
|
||||
@@ -371,6 +376,7 @@ wget --tries=20 --waitretry=20 --retry-on-http-error=404,403,500,502,503 "${WEKA
|
||||
|| { echo "Failed to download ${WEKAN_ZIP_URL} after retries"; exit 8; }
|
||||
unzip "wekan-${VERSION}-${WEKAN_ARCH}.zip"
|
||||
rm "wekan-${VERSION}-${WEKAN_ARCH}.zip"
|
||||
node /tmp/prepare-bundle-npm.mjs ./bundle
|
||||
npm install --prefix ./bundle/programs/server
|
||||
# node-gyp and @mapbox/node-pre-gyp compiled nothing here - every native module
|
||||
# in the bundle is a prebuilt .node - and nothing in boot.js reaches them. Their
|
||||
@@ -387,6 +393,7 @@ node /tmp/bundle-trim.mjs ./bundle --transport sockjs --drop-legacy-client
|
||||
# And the npm tree rspack cannot tree-shake, because Atmosphere packages load it
|
||||
# through Npm.require(). Only what it can prove nothing requires.
|
||||
node /tmp/prune-unreachable-npm.mjs ./bundle
|
||||
python3 /tmp/check-telemetry.py --bundle ./bundle
|
||||
mv /home/wekan/app/bundle /build
|
||||
|
||||
# The .zip bundle now ships a self-contained launcher + its own Node.js for the
|
||||
|
||||
@@ -113,7 +113,7 @@ By working directly with WeKan ® you get the benefit of active maintenance and
|
||||
|
||||
## Getting Started with Development
|
||||
|
||||
The main branch uses Meteor 3.5 with Node.js 24.x.
|
||||
The main branch uses Meteor 3.6-beta.1 with Node.js 26.x.
|
||||
See [CHANGELOG.md](https://github.com/wekan/wekan/blob/main/CHANGELOG.md) for the latest runtime updates.
|
||||
|
||||
To contribute, [create a fork](https://github.com/wekan/wekan/blob/main/docs/DeveloperDocs/Build-and-Create-Pull-Request.md#2-create-fork-of-httpsgithubcomwekanwekan-at-github-web-page) and run `./build.sh` (or `./build.bat` on Windows) as detailed [here](https://github.com/wekan/wekan/blob/main/docs/DeveloperDocs/Build-and-Create-Pull-Request.md#3-install-dependencies-build-wekan-and-run-the-dev-server). Once you're ready, please test your code and [submit a pull request (PR)](https://github.com/wekan/wekan/blob/main/docs/DeveloperDocs/Build-and-Create-Pull-Request.md#7-test).
|
||||
@@ -127,7 +127,7 @@ Please refer to the [developer documentation](https://github.com/wekan/wekan/blo
|
||||
Before building WeKan from source, ensure you have:
|
||||
|
||||
- **Git** - for cloning the repository
|
||||
- **Node.js 24.x** - WeKan requires Node.js 24.x
|
||||
- **Node.js 26.x** - WeKan requires Node.js 26.x
|
||||
- **Meteor** - the JavaScript framework WeKan is built with
|
||||
|
||||
### Building WeKan
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v11.80.0"
|
||||
appVersion: "v12.02.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -89,22 +89,24 @@ echo.
|
||||
echo ==================== WeKan ( Windows ) ====================
|
||||
echo 1^) Setup ^(install dependencies, build^)
|
||||
echo 2^) Dev server ^(meteor run variants^)
|
||||
echo 3^) Tests ^(mocha, playwright, e2e, ...^)
|
||||
echo 4^) Docker ^(start / follow logs / stop^)
|
||||
echo 5^) Releases ^(release, snap, bundles, translations, ...^)
|
||||
echo 6^) CLI commands ^(run any of them without the menu^)
|
||||
echo 7^) Tools ^(save deps, forge tools, mirror^)
|
||||
echo 3^) Dev server nobuild ^(source loader + bundled MongoDB^)
|
||||
echo 4^) Tests ^(mocha, playwright, e2e, ...^)
|
||||
echo 5^) Docker ^(start / follow logs / stop^)
|
||||
echo 6^) Releases ^(release, snap, bundles, translations, ...^)
|
||||
echo 7^) CLI commands ^(run any of them without the menu^)
|
||||
echo 8^) Tools ^(save deps, forge tools, mirror^)
|
||||
echo 0^) Quit
|
||||
echo ==========================================================
|
||||
set "choice="
|
||||
set /p "choice=Choose a category: "
|
||||
if "%choice%"=="1" goto menu_setup
|
||||
if "%choice%"=="2" goto menu_dev
|
||||
if "%choice%"=="3" goto menu_tests
|
||||
if "%choice%"=="4" goto menu_docker
|
||||
if "%choice%"=="5" goto menu_releases
|
||||
if "%choice%"=="6" goto menu_cli
|
||||
if "%choice%"=="7" goto menu_tools
|
||||
if "%choice%"=="3" goto menu_dev_nobuild
|
||||
if "%choice%"=="4" goto menu_tests
|
||||
if "%choice%"=="5" goto menu_docker
|
||||
if "%choice%"=="6" goto menu_releases
|
||||
if "%choice%"=="7" goto menu_cli
|
||||
if "%choice%"=="8" goto menu_tools
|
||||
if "%choice%"=="0" goto end
|
||||
echo invalid option
|
||||
goto menu
|
||||
@@ -130,8 +132,17 @@ goto menu_setup
|
||||
|
||||
REM ===========================================================================
|
||||
:menu_dev
|
||||
set "DEV_NOBUILD="
|
||||
set "DEV_MENU_TITLE=Dev server"
|
||||
goto menu_dev_options
|
||||
|
||||
:menu_dev_nobuild
|
||||
set "DEV_NOBUILD=1"
|
||||
set "DEV_MENU_TITLE=Dev server nobuild"
|
||||
|
||||
:menu_dev_options
|
||||
echo.
|
||||
echo -- Dev server -- ^(0 = Back^)
|
||||
echo == %DEV_MENU_TITLE% ==
|
||||
echo 1^) localhost:3000
|
||||
echo 2^) localhost:3000 + trace warnings
|
||||
echo 3^) localhost:3000 + bundle visualizer
|
||||
@@ -151,7 +162,7 @@ if "%choice%"=="6" goto dev_customip
|
||||
if "%choice%"=="7" goto dev_customurl
|
||||
if "%choice%"=="8" goto dev_killall
|
||||
if "%choice%"=="0" goto menu
|
||||
goto menu_dev
|
||||
goto menu_dev_options
|
||||
|
||||
REM ===========================================================================
|
||||
:menu_tests
|
||||
@@ -177,6 +188,7 @@ echo 13^) Count tests by category
|
||||
echo 14^) All databases ^(sequential^): build newest FerretDB v1, run every query type
|
||||
echo against every database with an image for this CPU, compare the answers
|
||||
echo 15^) Run all FerretDB tests - SEQUENTIAL ^(unit, vet, integration^)
|
||||
echo 16^) EVERYTHING source one by one ^(Dev server nobuild, all browsers^)
|
||||
set "choice="
|
||||
set /p "choice=Choose: "
|
||||
if "%choice%"=="1" goto test_everything_two
|
||||
@@ -194,6 +206,7 @@ if "%choice%"=="12" goto check_floating
|
||||
if "%choice%"=="13" goto count_tests
|
||||
if "%choice%"=="14" goto test_all_databases
|
||||
if "%choice%"=="15" goto test_ferretdb
|
||||
if "%choice%"=="16" goto test_everything_source
|
||||
if "%choice%"=="0" goto menu
|
||||
goto menu_tests
|
||||
|
||||
@@ -250,56 +263,58 @@ REM Release notes: In short, Security, translation languages, thanks and changel
|
||||
REM Binary provenance stays in build artifacts.
|
||||
echo.
|
||||
echo -- Releases / Release -- ^(0 = Back^)
|
||||
echo 1^) Release ALL platforms: push CHANGELOG, trigger release-all.yml
|
||||
echo 2^) Release ^(older local flow^), for one version
|
||||
echo 3^) Show the version numbers this checkout would release
|
||||
echo 4^) Show the CHANGELOG of the release being prepared
|
||||
echo 5^) Rebuild the API docs ^(wekan.yml + wekan.html^)
|
||||
echo 6^) Rebuild a release that already exists
|
||||
echo 7^) Prepare the release directory for one version
|
||||
echo 8^) Collect the built bundles for one version
|
||||
echo 9^) Link the newest bundle as wekan-latest
|
||||
echo 10^) Move an old release out of the download directory
|
||||
echo 11^) Clean up after a release
|
||||
echo 12^) Publish the Helm chart in wekan/charts
|
||||
echo 13^) Update wekan.fi with the new version and API docs
|
||||
echo 14^) Publish the npm packages xet7 maintains
|
||||
echo 15^) Check every download URL snapcraft.yaml uses
|
||||
echo 16^) Clone all release-related repositories
|
||||
echo 17^) Create the GitHub Actions secrets a release needs
|
||||
echo 18^) Add a git tag for a release
|
||||
echo 19^) Delete a git tag, locally and on the remote
|
||||
echo 20^) Move the 'stable' tag to HEAD
|
||||
echo 21^) Release the wekan-ondra / wekan-gantt-gpl variants, part 1
|
||||
echo 22^) Release the wekan-ondra / wekan-gantt-gpl variants, part 2
|
||||
echo 23^) Report ^(or repair^) the Helm chart index for past releases
|
||||
echo 24^) Rebuild the Helm index.yaml from the chart packages
|
||||
echo 1^) Release All: audit, commit, push and build with Actions
|
||||
echo 2^) Release All Missing
|
||||
echo 3^) Release ^(older local flow^), for one version
|
||||
echo 4^) Show the version numbers this checkout would release
|
||||
echo 5^) Show the CHANGELOG of the release being prepared
|
||||
echo 6^) Rebuild the API docs ^(wekan.yml + wekan.html^)
|
||||
echo 7^) Rebuild a release that already exists
|
||||
echo 8^) Prepare the release directory for one version
|
||||
echo 9^) Collect the built bundles for one version
|
||||
echo 10^) Link the newest bundle as wekan-latest
|
||||
echo 11^) Move an old release out of the download directory
|
||||
echo 12^) Clean up after a release
|
||||
echo 13^) Publish the Helm chart in wekan/charts
|
||||
echo 14^) Update wekan.fi with the new version and API docs
|
||||
echo 15^) Publish the npm packages xet7 maintains
|
||||
echo 16^) Check every download URL snapcraft.yaml uses
|
||||
echo 17^) Clone all release-related repositories
|
||||
echo 18^) Create the GitHub Actions secrets a release needs
|
||||
echo 19^) Add a git tag for a release
|
||||
echo 20^) Delete a git tag, locally and on the remote
|
||||
echo 21^) Move the 'stable' tag to HEAD
|
||||
echo 22^) Release the wekan-ondra / wekan-gantt-gpl variants, part 1
|
||||
echo 23^) Release the wekan-ondra / wekan-gantt-gpl variants, part 2
|
||||
echo 24^) Report ^(or repair^) the Helm chart index for past releases
|
||||
echo 25^) Rebuild the Helm index.yaml from the chart packages
|
||||
set "choice="
|
||||
set /p "choice=Choose: "
|
||||
if "%choice%"=="1" call :rel_run "releases/release-all.sh" ""
|
||||
if "%choice%"=="2" call :rel_run "releases/release.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="3" call :rel_run "releases/version.sh" ""
|
||||
if "%choice%"=="4" call :rel_run "releases/changelog.sh" ""
|
||||
if "%choice%"=="5" call :rel_run "releases/rebuild-docs.sh" ""
|
||||
if "%choice%"=="6" call :rel_run "releases/rebuild-release.sh" ""
|
||||
if "%choice%"=="7" call :rel_run "releases/rel.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="8" call :rel_run "releases/release-bundle.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="9" call :rel_run "releases/release-ln.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="10" call :rel_run "releases/release-x2.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="11" call :rel_run "releases/release-cleanup.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="12" call :rel_run "releases/release-charts.sh" ""
|
||||
if "%choice%"=="13" call :rel_run "releases/release-website.sh" ""
|
||||
if "%choice%"=="14" call :rel_run "releases/npm-publish.sh" ""
|
||||
if "%choice%"=="15" call :rel_run "releases/test-download-urls.sh" ""
|
||||
if "%choice%"=="16" call :rel_run "releases/clone-release-repos.sh" ""
|
||||
if "%choice%"=="17" call :rel_run "releases/create-github-secrets.sh" ""
|
||||
if "%choice%"=="18" call :rel_run "releases/add-tag.sh" "Version tag, e.g. v10.50"
|
||||
if "%choice%"=="19" call :rel_run "releases/delete-tag.sh" "Version tag, e.g. v10.50"
|
||||
if "%choice%"=="20" call :rel_cmd "git tag --force stable HEAD && git push --tags --force && git push --follow-tags" ""
|
||||
if "%choice%"=="21" call :rel_run "releases/release-ondra-1.sh" ""
|
||||
if "%choice%"=="22" call :rel_run "releases/release-ondra-2.sh" ""
|
||||
if "%choice%"=="23" call :rel_run "releases/backfill-charts.sh" ""
|
||||
if "%choice%"=="24" call :rel_run "releases/reindex-charts.py" ""
|
||||
if "%choice%"=="2" call :rel_run "releases/release-all-missing.sh" ""
|
||||
if "%choice%"=="3" call :rel_run "releases/release.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="4" call :rel_run "releases/version.sh" ""
|
||||
if "%choice%"=="5" call :rel_run "releases/changelog.sh" ""
|
||||
if "%choice%"=="6" call :rel_run "releases/rebuild-docs.sh" ""
|
||||
if "%choice%"=="7" call :rel_run "releases/rebuild-release.sh" ""
|
||||
if "%choice%"=="8" call :rel_run "releases/rel.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="9" call :rel_run "releases/release-bundle.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="10" call :rel_run "releases/release-ln.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="11" call :rel_run "releases/release-x2.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="12" call :rel_run "releases/release-cleanup.sh" "WeKan version, e.g. 10.50"
|
||||
if "%choice%"=="13" call :rel_run "releases/release-charts.sh" ""
|
||||
if "%choice%"=="14" call :rel_run "releases/release-website.sh" ""
|
||||
if "%choice%"=="15" call :rel_run "releases/npm-publish.sh" ""
|
||||
if "%choice%"=="16" call :rel_run "releases/test-download-urls.sh" ""
|
||||
if "%choice%"=="17" call :rel_run "releases/clone-release-repos.sh" ""
|
||||
if "%choice%"=="18" call :rel_run "releases/create-github-secrets.sh" ""
|
||||
if "%choice%"=="19" call :rel_run "releases/add-tag.sh" "Version tag, e.g. v10.50"
|
||||
if "%choice%"=="20" call :rel_run "releases/delete-tag.sh" "Version tag, e.g. v10.50"
|
||||
if "%choice%"=="21" call :rel_cmd "git tag --force stable HEAD && git push --tags --force && git push --follow-tags" ""
|
||||
if "%choice%"=="22" call :rel_run "releases/release-ondra-1.sh" ""
|
||||
if "%choice%"=="23" call :rel_run "releases/release-ondra-2.sh" ""
|
||||
if "%choice%"=="24" call :rel_run "releases/backfill-charts.sh" ""
|
||||
if "%choice%"=="25" call :rel_run "releases/reindex-charts.py" ""
|
||||
if "%choice%"=="0" goto menu_releases
|
||||
goto rel_release
|
||||
|
||||
@@ -557,7 +572,8 @@ echo Linux only and are in build.sh instead.
|
||||
goto :eof
|
||||
|
||||
:cli_list
|
||||
echo release-all Release ALL platforms: push CHANGELOG, trigger release-all.yml
|
||||
echo release-all-missing Complete missing outputs of an existing release
|
||||
echo release-all Release All: audit, commit, push and build with Actions
|
||||
echo release Release ^(older local flow^), for one version ^<WeKan version, e.g. 10.50^>
|
||||
echo version Show the version numbers this checkout would release
|
||||
echo changelog Show the CHANGELOG of the release being prepared
|
||||
@@ -642,6 +658,7 @@ set "ARGS=%*"
|
||||
call set "ARGS=%%ARGS:*%K%=%%"
|
||||
set "CMD="
|
||||
set "SHCMD="
|
||||
if /I "%K%"=="release-all-missing" (set "CMD=bash releases/release-all-missing.sh" ^& goto cli_go)
|
||||
if /I "%K%"=="release-all" (set "CMD=bash releases/release-all.sh" ^& goto cli_go)
|
||||
if /I "%K%"=="release" (set "CMD=bash releases/release.sh" ^& goto cli_go)
|
||||
if /I "%K%"=="version" (set "CMD=bash releases/version.sh" ^& goto cli_go)
|
||||
@@ -810,6 +827,8 @@ goto end
|
||||
REM ===========================================================================
|
||||
:install
|
||||
echo Installing WeKan dependencies for Windows.
|
||||
rem Full MIME detection uses the libmagic WASM engine/database installed by npm.
|
||||
rem No external file.exe installation is needed.
|
||||
echo This uses Chocolatey to install git, curl, Node.js LTS and MongoDB tools,
|
||||
echo then installs Meteor via npm.
|
||||
where choco >nul 2>&1
|
||||
@@ -980,6 +999,8 @@ call :detect_ip
|
||||
echo Your IP address is !IPADDRESS!
|
||||
call :set_dev_env
|
||||
set "MONGO_URL=mongodb://127.0.0.1:27019/wekan"
|
||||
set "WEKAN_SOURCE_MONGO_PORT=27019"
|
||||
set "WEKAN_SOURCE_MONGO_DATABASE=wekan"
|
||||
set "ROOT_URL=http://!IPADDRESS!:3000"
|
||||
call :runlog --port 3000
|
||||
goto end
|
||||
@@ -1488,10 +1509,9 @@ exit /b 0
|
||||
REM Common dev-server environment (caller sets ROOT_URL afterwards).
|
||||
set "DEFAULT_METEOR_REACTIVITY_ORDER=changeStreams,oplog,polling"
|
||||
set "DDP_TRANSPORT=sockjs"
|
||||
set "DEBUG=true"
|
||||
if not defined DEBUG set "DEBUG=false"
|
||||
set "WRITABLE_PATH=.."
|
||||
set "WITH_API=true"
|
||||
set "RICHER_CARD_COMMENT_EDITOR=false"
|
||||
exit /b 0
|
||||
|
||||
:logdir
|
||||
@@ -1544,9 +1564,14 @@ call :logdir dev-server
|
||||
if errorlevel 1 exit /b 1
|
||||
set "WEKAN_SERVER_LOG=%LOG_DIRECTORY%\dev.txt"
|
||||
echo Log: %WEKAN_SERVER_LOG%
|
||||
if "%DEV_NOBUILD%"=="1" goto runlog_nobuild
|
||||
call meteor run %* 2>&1 | powershell -NoProfile -Command "$input | Tee-Object -FilePath $env:WEKAN_SERVER_LOG"
|
||||
exit /b 0
|
||||
|
||||
:runlog_nobuild
|
||||
node "%REPO%\scripts\dev-source\start.cjs" %* 2>&1 | powershell -NoProfile -Command "$input | Tee-Object -FilePath $env:WEKAN_SERVER_LOG"
|
||||
exit /b 0
|
||||
|
||||
:kill_meteor_on_port
|
||||
REM %1 = app port. Frees BOTH the app port and the rspack dev-server port (8080),
|
||||
REM because "meteor run" starts an rspack dev server on 8080 (rspack.config.js:
|
||||
@@ -1827,11 +1852,10 @@ set "ROOT_URL=http://localhost:3000"
|
||||
set "PORT=3000"
|
||||
set "WRITABLE_PATH=%WRITABLE_ABS%"
|
||||
set "WITH_API=true"
|
||||
set "RICHER_CARD_COMMENT_EDITOR=false"
|
||||
set "DEFAULT_METEOR_REACTIVITY_ORDER=changeStreams,oplog,polling"
|
||||
echo ==^> Starting the WeKan test server on http://localhost:3000 from .build\bundle ^(precompiled - no rebuild^).
|
||||
start "WekanTestServer" /MIN /D "%REPO%" cmd /c "(echo ===== WeKan test server [bundle node :3000 db :3001/meteor] started: %DATE% %TIME% =====) 1>%RUN_LOGDIR%\wekan-test-server.log 2>&1 & "%NODE_BIN%" "%REPO%\.build\bundle\main.js" 1>>%RUN_LOGDIR%\wekan-test-server.log 2>&1"
|
||||
set "MONGO_URL=" & set "ROOT_URL=" & set "PORT=" & set "WRITABLE_PATH=" & set "WITH_API=" & set "RICHER_CARD_COMMENT_EDITOR=" & set "DEFAULT_METEOR_REACTIVITY_ORDER="
|
||||
set "MONGO_URL=" & set "ROOT_URL=" & set "PORT=" & set "WRITABLE_PATH=" & set "WITH_API=" & set "DEFAULT_METEOR_REACTIVITY_ORDER="
|
||||
|
||||
REM 6) Wait for :3000 to answer (bundle boots in seconds; curl-timeout poll).
|
||||
call :wait_server_ready
|
||||
@@ -1952,6 +1976,13 @@ bash -c "cd .tools/FerretDB && ./build.sh test-all"
|
||||
goto end
|
||||
|
||||
REM ===========================================================================
|
||||
:test_everything_source
|
||||
set "WEKAN_TEST_SERVER_MODE=source"
|
||||
set "WEKAN_TEST_BAIL=1"
|
||||
set "WEKAN_PLAYWRIGHT_PROBE=0"
|
||||
set "WEKAN_EVERYTHING_MODE=sequential"
|
||||
goto test_everything
|
||||
|
||||
:test_everything_two
|
||||
set "WEKAN_EVERYTHING_MODE=two-worker"
|
||||
goto test_everything
|
||||
|
||||
@@ -636,9 +636,25 @@ function run_playwright_docker(){
|
||||
pwver="$(node -e "console.log(require('$pwdir/node_modules/@playwright/test/package.json').version)" 2>/dev/null)"
|
||||
[ -z "$pwver" ] && pwver="1.60.0"
|
||||
local image="mcr.microsoft.com/playwright:v${pwver}-noble"
|
||||
local docker_base_url="${WEKAN_BASE_URL:-http://127.0.0.1:3000}"
|
||||
local docker_mongo_url="${WEKAN_MONGO_URL:-mongodb://127.0.0.1:3001/meteor}"
|
||||
local docker_host_proxy_port=""
|
||||
# Docker Desktop on macOS keeps the host outside the container's loopback.
|
||||
if [ "$(uname -s)" = Darwin ]; then
|
||||
# Meteor's dynamic imports use ROOT_URL (localhost in the test server).
|
||||
# Keep the browser on that same origin and bridge its loopback to the host.
|
||||
# Browsing host.docker.internal while ROOT_URL is localhost makes Firefox
|
||||
# fetch dynamic modules from the container's unreachable localhost.
|
||||
if [[ "$docker_base_url" =~ ^http://(127\.0\.0\.1|localhost):([0-9]+)$ ]]; then
|
||||
docker_host_proxy_port="${BASH_REMATCH[2]}"
|
||||
docker_base_url="http://localhost:$docker_host_proxy_port"
|
||||
fi
|
||||
docker_mongo_url="${docker_mongo_url//127.0.0.1/host.docker.internal}"
|
||||
docker_mongo_url="${docker_mongo_url//localhost/host.docker.internal}"
|
||||
fi
|
||||
mkdir -p "$filesroot"
|
||||
echo "Running Playwright $browser in Docker ($image)."
|
||||
echo "Expecting WeKan at ${WEKAN_BASE_URL:-http://127.0.0.1:3000} (container uses --network host)."
|
||||
echo "Expecting WeKan at $docker_base_url."
|
||||
# Mount the whole repo so specs that reach the repo-root node_modules
|
||||
# (e.g. @wekanteam/exceljs) and .tools resolve; run from tests/playwright.
|
||||
# Run as the host user (--user) with a writable HOME so the container does
|
||||
@@ -650,19 +666,38 @@ function run_playwright_docker(){
|
||||
--user "$(id -u):$(id -g)" \
|
||||
-e HOME=/repo/.tools/tmp \
|
||||
-e TMPDIR=/repo/.tools/tmp \
|
||||
-e WEKAN_BASE_URL="${WEKAN_BASE_URL:-http://127.0.0.1:3000}" \
|
||||
-e WEKAN_MONGO_URL="${WEKAN_MONGO_URL:-mongodb://127.0.0.1:3001/meteor}" \
|
||||
-e WEKAN_BASE_URL="$docker_base_url" \
|
||||
-e WEKAN_DOCKER_HOST_PROXY_PORT="$docker_host_proxy_port" \
|
||||
-e WEKAN_MONGO_URL="$docker_mongo_url" \
|
||||
-e WEKAN_PLAYWRIGHT_ALL=1 \
|
||||
-e WEKAN_PLAYWRIGHT_PROJECT="$browser" \
|
||||
-e WEKAN_PLAYWRIGHT_WORKERS="${WEKAN_PLAYWRIGHT_WORKERS:-1}" \
|
||||
-e WEKAN_PLAYWRIGHT_PROBE=0 \
|
||||
-e WEKAN_TEST_BAIL="${WEKAN_TEST_BAIL:-0}" \
|
||||
-e WEKAN_TEST_SERIAL="${WEKAN_TEST_SERIAL:-0}" \
|
||||
-e WEKAN_TEST_SERVER_MODE="${WEKAN_TEST_SERVER_MODE:-bundle}" \
|
||||
-e WEKAN_TEST_SMTP_PORT="${WEKAN_TEST_SMTP_PORT:-}" \
|
||||
-e PLAYWRIGHT_HTML_OPEN=never \
|
||||
-e WEKAN_FILES_PATH=/wekan-files \
|
||||
-e PLAYWRIGHT_JSON_OUTPUT_NAME="${PLAYWRIGHT_JSON_OUTPUT_NAME:-}" \
|
||||
-v "$filesroot":/wekan-files \
|
||||
-v "$reporoot":/repo -w /repo/tests/playwright \
|
||||
"$image" \
|
||||
sh -c 'export PATH=/repo/tests/playwright/node_modules/.bin:$PATH; exec npx playwright test --project="$0" "$@"' "$browser" "$@"
|
||||
sh -c '
|
||||
export PATH=/repo/tests/playwright/node_modules/.bin:$PATH
|
||||
if [ -n "$WEKAN_DOCKER_HOST_PROXY_PORT" ]; then
|
||||
node /repo/tests/playwright/helpers/docker-host-proxy.cjs &
|
||||
proxy_pid=$!
|
||||
trap '\''kill "$proxy_pid" 2>/dev/null || true; wait "$proxy_pid" 2>/dev/null || true'\'' EXIT
|
||||
ready=0
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if curl -fsS --max-time 3 -o /dev/null "$WEKAN_BASE_URL/sign-in"; then ready=1; break; fi
|
||||
sleep 1
|
||||
done
|
||||
[ "$ready" -eq 1 ] || { echo "Local WeKan proxy did not become ready" >&2; exit 1; }
|
||||
fi
|
||||
npx playwright test --project="$0" "$@"
|
||||
' "$browser" "$@"
|
||||
}
|
||||
|
||||
# Run the older Puppeteer-based Node E2E regression suite in the same browser
|
||||
@@ -1016,6 +1051,8 @@ function run_all_tests(){
|
||||
*) echo "ERROR: unknown EVERYTHING mode: $REQUESTED_MODE" >&2; return 2 ;;
|
||||
esac
|
||||
export WEKAN_PLAYWRIGHT_WORKERS="$PLAYWRIGHT_WORKERS"
|
||||
export WEKAN_TEST_SERIAL=0
|
||||
[ "$REQUESTED_MODE" = sequential ] && export WEKAN_TEST_SERIAL=1
|
||||
local modeword
|
||||
[ "$REQUESTED_MODE" = parallel ] && modeword="at once (concurrently)" || modeword="one stage at a time (${PLAYWRIGHT_WORKERS} Playwright worker(s))"
|
||||
# The large heap at the top of this file is for compiling WeKan. Do not hand
|
||||
@@ -1055,22 +1092,29 @@ function run_all_tests(){
|
||||
# fails on code that is no longer in the working tree - the one thing a test
|
||||
# run must never do. This used to build only when .build/bundle was missing,
|
||||
# which is exactly the case where the bundle is present but old.
|
||||
echo "==> Deleting .build and building WeKan before running the tests (always, so the tests run against the current source)."
|
||||
build_wekan
|
||||
if [ ! -d .build/bundle ]; then
|
||||
echo "ERROR: .build/bundle is missing after building. Aborting the test run."
|
||||
return 1
|
||||
if [ "${WEKAN_TEST_SERVER_MODE:-bundle}" != source ]; then
|
||||
echo "==> Deleting .build and building WeKan before running the tests (always, so the tests run against the current source)."
|
||||
build_wekan
|
||||
if [ ! -d .build/bundle ]; then
|
||||
echo "ERROR: .build/bundle is missing after building. Aborting the test run."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
if [ "$RUN_MODE" = parallel ]; then
|
||||
echo "Running ALL tests against ONE WeKan server on http://localhost:3000 - all jobs run IN PARALLEL (concurrently). Needs plenty of RAM (fine on 32 GB)."
|
||||
else
|
||||
echo "Running ALL tests against ONE WeKan server on http://localhost:3000 - all jobs run SEQUENTIALLY (one at a time)."
|
||||
fi
|
||||
if [ "${WEKAN_TEST_SERVER_MODE:-bundle}" = source ]; then
|
||||
echo " :3000 - current source loaded by Node; Meteor's bundled development MongoDB on :3001."
|
||||
echo " Mocha runs first in the source process, then a fresh source process serves E2E and browsers."
|
||||
else
|
||||
echo "Two WeKan servers are involved (they do NOT run tests in parallel unless you chose parallel):"
|
||||
echo " :3000 - the PRECOMPILED .build/bundle run as a plain Node server (Meteor's mongod on :3001)"
|
||||
echo " - serves Node E2E + Playwright browser tests. Built fresh above, so the tests run against the current source."
|
||||
echo " :3100 - Mocha via 'meteor test' (its own .meteor/local-test build; the in-process server-side tests"
|
||||
echo " CANNOT run from a production bundle, so this one build is unavoidable)."
|
||||
fi
|
||||
echo " Import regression is a plain Node script (no server, no MongoDB)."
|
||||
SUMMARY=()
|
||||
record() { SUMMARY+=("$1|$2|${3:-}"); }
|
||||
@@ -1239,6 +1283,7 @@ function run_all_tests(){
|
||||
[ "$jrc" = "0" ] && jst="PASS" || jst="FAIL"
|
||||
jok=$(count_pass "$k" "$jlog"); jbad=$(count_fail "$k" "$jlog")
|
||||
printf ' [%-4s] %-22s tests:%-4s fail:%s\n' "$jst" "$(label_of "$k")" "$jok" "$jbad"
|
||||
if [ "${WEKAN_TEST_BAIL:-0}" = 1 ] && [ "$jrc" -ne 0 ]; then return "$jrc"; fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -1278,6 +1323,33 @@ function run_all_tests(){
|
||||
echo " Port 3000 is now free."
|
||||
fi
|
||||
|
||||
if [ "${WEKAN_TEST_SERVER_MODE:-bundle}" = source ]; then
|
||||
export WEKAN_PLAYWRIGHT_PROBE=0
|
||||
export WEKAN_TEST_SMTP_PORT="${WEKAN_TEST_SMTP_PORT:-2525}"
|
||||
export MAIL_URL="smtp://127.0.0.1:$WEKAN_TEST_SMTP_PORT"
|
||||
export EMAIL_NOTIFICATION_TIMEOUT=100
|
||||
local WRITABLE_ABS="$WEKAN_DIR/.tools/test-writable"
|
||||
mkdir -p "$WRITABLE_ABS/files"
|
||||
export WEKAN_FILES_PATH_HOST="$WRITABLE_ABS/files"
|
||||
export WEKAN_FILES_PATH="$WRITABLE_ABS/files"
|
||||
export WEKAN_MONGO_URL="mongodb://127.0.0.1:3001/meteor"
|
||||
local NODE_BIN="$(command -v node)"
|
||||
local TAIL_PID=""
|
||||
echo "==> Running Meteor server tests in the source-loaded Node process on :3000."
|
||||
WEKAN_SOURCE_WATCH=0 ROOT_URL=http://localhost:3000 WRITABLE_PATH="$WRITABLE_ABS" WITH_API=true \
|
||||
NODE_OPTIONS="$TEST_NODE_OPTIONS" "$NODE_BIN" scripts/dev-source/start.cjs --port 3000 --server-tests \
|
||||
2>&1 | tee "$RUN_LOGDIR/wekan-alltests-mocha.log"
|
||||
local source_mocha_rc=${PIPESTATUS[0]}
|
||||
if [ "$source_mocha_rc" -ne 0 ]; then return "$source_mocha_rc"; fi
|
||||
echo 0 > "$STATDIR/mocha"
|
||||
echo "==> Starting source-loaded WeKan :3000 and Meteor's development MongoDB :3001."
|
||||
WEKAN_SOURCE_WATCH=0 ROOT_URL=http://localhost:3000 WRITABLE_PATH="$WRITABLE_ABS" WITH_API=true \
|
||||
NODE_OPTIONS="$TEST_NODE_OPTIONS" "$NODE_BIN" scripts/dev-source/start.cjs --port 3000 \
|
||||
> "$RUN_LOGDIR/wekan-test-server.log" 2>&1 &
|
||||
TEST_SERVER_PID=$!
|
||||
tail -n 0 -f "$RUN_LOGDIR/wekan-test-server.log" &
|
||||
TAIL_PID=$!
|
||||
else
|
||||
# Start the :3000 test server from the PRECOMPILED .build/bundle (NOT `meteor run`)
|
||||
# so Node E2E + Playwright reuse the WeKan you already built with
|
||||
# `meteor build .build --directory` — no recompile. The bundle is a plain Node
|
||||
@@ -1427,11 +1499,13 @@ function run_all_tests(){
|
||||
# different one, so every test that needs seeded data fails.
|
||||
{ echo "===== WeKan test server [bundle node :3000 db :$TEST_DB_PORT/meteor] - started $(date '+%Y-%m-%d %H:%M:%S %Z') ====="; echo; \
|
||||
MONGO_URL="$TEST_MONGO_URL" ROOT_URL="http://localhost:3000" PORT=3000 \
|
||||
WRITABLE_PATH="$WRITABLE_ABS" WITH_API=true RICHER_CARD_COMMENT_EDITOR=false \
|
||||
WRITABLE_PATH="$WRITABLE_ABS" WITH_API=true \
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" \
|
||||
NODE_OPTIONS="$TEST_NODE_OPTIONS" exec "$NODE_BIN" "$BUNDLE_DIR/main.js"; } >> "$RUN_LOGDIR/wekan-test-server.log" 2>&1 &
|
||||
TEST_SERVER_PID=$!
|
||||
|
||||
fi
|
||||
|
||||
SERVER_READY=0
|
||||
server_wait_start=$(date +%s)
|
||||
server_wait_max=300
|
||||
@@ -1446,16 +1520,16 @@ function run_all_tests(){
|
||||
wait "$TAIL_PID" 2>/dev/null || true
|
||||
echo " -------------------------------------------------------------------"
|
||||
if [ "$SERVER_READY" -eq 1 ]; then
|
||||
echo "==> WeKan test server ready on http://localhost:3000 (precompiled bundle, no rebuild)."
|
||||
echo "==> WeKan test server ready on http://localhost:3000 (${WEKAN_TEST_SERVER_MODE:-bundle} mode)."
|
||||
fi
|
||||
|
||||
# Mocha and the import regression do not need the :3000 server; launch them
|
||||
# now (after the server build is past, so they no longer compete with it),
|
||||
# then the E2E and browser jobs below.
|
||||
echo "==> Launching Mocha (separate .meteor/local-test build, port 3100), the node unit suites and the import regression, $modeword."
|
||||
launch_job mocha
|
||||
launch_job unit
|
||||
launch_job import
|
||||
echo "==> Running registered server, node and import suites, $modeword."
|
||||
if [ "${WEKAN_TEST_SERVER_MODE:-bundle}" != source ]; then launch_job mocha || return $?; fi
|
||||
launch_job unit || return $?
|
||||
launch_job import || return $?
|
||||
|
||||
if [ "$SERVER_READY" -ne 1 ]; then
|
||||
echo "FAIL: server did not become ready on http://localhost:3000 (see $RUN_LOGDIR/wekan-test-server.log)"
|
||||
@@ -1468,10 +1542,10 @@ function run_all_tests(){
|
||||
else
|
||||
record PASS "Server startup"
|
||||
# Server is up: add the server-facing jobs to the running set.
|
||||
launch_job e2e
|
||||
launch_job chromium
|
||||
launch_job firefox
|
||||
launch_job webkit
|
||||
launch_job e2e || return $?
|
||||
launch_job chromium || return $?
|
||||
launch_job firefox || return $?
|
||||
launch_job webkit || return $?
|
||||
ALLKEYS="mocha unit import e2e chromium firefox webkit"
|
||||
fi
|
||||
|
||||
@@ -1634,6 +1708,12 @@ function run_everything(){
|
||||
local FERRET_GO_MEMORY_MB=$(( _mem_total_mb / 8 ))
|
||||
[ "$FERRET_GO_MEMORY_MB" -gt 4096 ] && FERRET_GO_MEMORY_MB=4096
|
||||
local FERRET_GOFLAGS="${WEKAN_FERRETDB_GOFLAGS:--p=$FERRET_GO_JOBS}"
|
||||
if [ "$EVERYTHING_MODE" = sequential ]; then
|
||||
FERRET_GOFLAGS="$FERRET_GOFLAGS -p=1 -parallel=1"
|
||||
fi
|
||||
if [ "${WEKAN_TEST_BAIL:-0}" = 1 ]; then
|
||||
FERRET_GOFLAGS="$FERRET_GOFLAGS -failfast"
|
||||
fi
|
||||
local FERRET_GOMEMLIMIT="${WEKAN_FERRETDB_GOMEMLIMIT:-${FERRET_GO_MEMORY_MB}MiB}"
|
||||
RUN_TS="$(date '+%Y-%m-%d_%H-%M-%S')"
|
||||
RUN_LOGDIR="$(log_directory "test-everything-$EVERYTHING_MODE")" || return $?
|
||||
@@ -1644,7 +1724,7 @@ function run_everything(){
|
||||
echo "=============================================================================="
|
||||
echo "EVERYTHING mode: $EVERYTHING_MODE. Logs: $RUN_LOGDIR/"
|
||||
echo " 1/4 Floating-promises guard (seconds: the rule, and unawaited auth checks)"
|
||||
echo " 2/4 WeKan's own tests (builds the bundle, starts a server; mocha, the"
|
||||
echo " 2/4 WeKan's own tests (${WEKAN_TEST_SERVER_MODE:-bundle} server; mocha, the"
|
||||
echo " node suites, import, node E2E, three browsers)"
|
||||
echo " 3/4 Database conformance (builds FerretDB, every database this CPU runs)"
|
||||
echo " 4/4 FerretDB's own tests (unit, vet, integration)"
|
||||
@@ -1662,10 +1742,12 @@ function run_everything(){
|
||||
# an hour of browser tests.
|
||||
floating_promises_checks 2>&1 | tee "$RUN_LOGDIR/wekan-floating-promises.log"
|
||||
guard_rc=${PIPESTATUS[0]}
|
||||
if [ "${WEKAN_TEST_BAIL:-0}" = 1 ] && [ "$guard_rc" -ne 0 ]; then return "$guard_rc"; fi
|
||||
|
||||
echo
|
||||
echo "### 2/4 WeKan tests ###########################################################"
|
||||
run_all_tests "$EVERYTHING_MODE" || wekan_rc=$?
|
||||
if [ "${WEKAN_TEST_BAIL:-0}" = 1 ] && [ "$wekan_rc" -ne 0 ]; then return "$wekan_rc"; fi
|
||||
|
||||
echo
|
||||
echo "### 3/4 Database conformance ##################################################"
|
||||
@@ -1675,6 +1757,7 @@ function run_everything(){
|
||||
else
|
||||
echo "ERROR: releases/db-conformance.sh is missing."; conf_rc=1
|
||||
fi
|
||||
if [ "${WEKAN_TEST_BAIL:-0}" = 1 ] && [ "$conf_rc" -ne 0 ]; then return "$conf_rc"; fi
|
||||
|
||||
echo
|
||||
echo "### 4/4 FerretDB tests ########################################################"
|
||||
@@ -1684,6 +1767,7 @@ function run_everything(){
|
||||
ferret_dir="$(ensure_tool_repo FerretDB)" || ferret_dir=""
|
||||
if [ -n "$ferret_dir" ] && [ -x "$ferret_dir/build.sh" ]; then
|
||||
( cd "$ferret_dir" && WEKAN_LOGDIR="$RUN_LOGDIR" \
|
||||
FERRETDB_TEST_BAIL="${WEKAN_TEST_BAIL:-0}" \
|
||||
GOFLAGS="$FERRET_GOFLAGS" GOMEMLIMIT="$FERRET_GOMEMLIMIT" \
|
||||
./build.sh test-all ) || ferret_rc=$?
|
||||
else
|
||||
@@ -2436,7 +2520,8 @@ choose() {
|
||||
# details stay in CHANGELOG.md. Notes include only In short, Security,
|
||||
# Translations language list, thanks and the changelog link. Binary provenance remains
|
||||
# a build artifact and must not be appended by any release entry point.
|
||||
RELEASE_SCRIPTS=( "Release|Release ALL platforms: push CHANGELOG, trigger release-all.yml|releases/release-all.sh|||"
|
||||
RELEASE_SCRIPTS=( "Release|Release All: audit, commit, push and build with Actions|releases/release-all.sh|||"
|
||||
"Release|Release All Missing: audit, commit, push and complete release|releases/release-all-missing.sh|||"
|
||||
"Release|Release (older local flow), for one version|releases/release.sh|WeKan version, e.g. 10.50||"
|
||||
"Release|Show the version numbers this checkout would release|releases/version.sh|||"
|
||||
"Release|Show the CHANGELOG of the release being prepared|releases/changelog.sh|||"
|
||||
@@ -2710,7 +2795,7 @@ esac
|
||||
opt=""
|
||||
while [ -z "$opt" ]; do
|
||||
echo; echo "==================== WeKan ===================="
|
||||
select cat in "Setup" "Dev server" "Tests" "Docker" "Releases" "CLI commands" "Tools" "Quit"; do
|
||||
select cat in "Setup" "Dev server" "Dev server nobuild" "Tests" "Docker" "Releases" "CLI commands" "Tools" "Quit"; do
|
||||
case $cat in
|
||||
"Setup")
|
||||
choose "Setup" \
|
||||
@@ -2719,8 +2804,8 @@ while [ -z "$opt" ]; do
|
||||
"Build WeKan development bundle|Build WeKan development bundle" \
|
||||
"git pull|git pull: fetch, fast-forward or merge onto origin, repoint the CHANGELOG commit links the rebase moved, and preserve unresolved conflict state" \
|
||||
"git push|git push: check the CHANGELOG commit links resolve before publishing them, push this branch to origin, and pull-then-retry once if origin moved meanwhile" ;;
|
||||
"Dev server")
|
||||
choose "Dev server" \
|
||||
"Dev server"|"Dev server nobuild")
|
||||
choose "$cat" \
|
||||
"localhost:3000|Run Meteor for dev on http://localhost:3000" \
|
||||
"localhost:3000 + trace warnings|Run Meteor for dev on http://localhost:3000 with trace warnings, and warnings using old Meteor API that will not exist in Meteor 3.0" \
|
||||
"localhost:3000 + bundle visualizer|Run Meteor for dev on http://localhost:3000 with bundle visualizer" \
|
||||
@@ -2734,6 +2819,7 @@ while [ -z "$opt" ]; do
|
||||
"EVERYTHING two-worker|Run EVERYTHING with stages one by one and two Playwright workers per browser; database and FerretDB stages stay sequential; logs in log/<datetime>/" \
|
||||
"EVERYTHING one by one|Run EVERYTHING one stage and one Playwright worker at a time for minimum RAM usage; database and FerretDB stages stay sequential; logs in log/<datetime>/" \
|
||||
"EVERYTHING at once|Run EVERYTHING with the WeKan test jobs concurrently; database backends and FerretDB stages stay sequential; logs in log/<datetime>/" \
|
||||
"EVERYTHING source one by one|Run EVERYTHING against Dev server nobuild on localhost:3000, one test at a time, all browsers" \
|
||||
"Mocha (server-side)|Test Mocha unit + security + API-logic tests (server-side only, no browser)" \
|
||||
"Import regression|Test import regression (tests/wekanCreator.import.test.js, fast, no server)" \
|
||||
"Node E2E regressions|Test Node E2E regressions (tests/e2e/list-regressions.js, needs running server)" \
|
||||
@@ -2762,47 +2848,57 @@ while [ -z "$opt" ]; do
|
||||
done
|
||||
done
|
||||
|
||||
# Both menus share their URL/port prompts and environment.
|
||||
DEV_COMMAND=(meteor run)
|
||||
if [ "$cat" = "Dev server nobuild" ]; then
|
||||
DEV_COMMAND=(node "$WEKAN_DIR/scripts/dev-source/start.cjs")
|
||||
fi
|
||||
for _once in 1; do
|
||||
case "$opt" in
|
||||
"Run EVERYTHING against Dev server nobuild on localhost:3000, one test at a time, all browsers")
|
||||
WEKAN_TEST_SERVER_MODE=source WEKAN_TEST_BAIL=1 WEKAN_PLAYWRIGHT_PROBE=0 run_everything sequential
|
||||
;;
|
||||
|
||||
"Install WeKan dependencies")
|
||||
|
||||
if [[ "$OSTYPE" == "linux-gnu" ]]; then
|
||||
echo "Linux";
|
||||
case "$(_et_linux_family)" in
|
||||
alpine)
|
||||
sudo apk add --no-cache bash build-base git curl wget p7zip zip unzip npm
|
||||
sudo apk add --no-cache bash build-base git curl wget p7zip zip unzip file npm
|
||||
;;
|
||||
arch)
|
||||
sudo pacman -Sy --needed --noconfirm base-devel git curl wget p7zip zip unzip npm
|
||||
sudo pacman -Sy --needed --noconfirm base-devel git curl wget p7zip zip unzip file npm
|
||||
;;
|
||||
fedora)
|
||||
sudo dnf group install -y development-tools
|
||||
sudo dnf install -y gcc gcc-c++ make git curl wget 7zip zip unzip npm
|
||||
sudo dnf install -y gcc gcc-c++ make git curl wget 7zip zip unzip file npm
|
||||
;;
|
||||
rhel)
|
||||
pm=dnf; command -v dnf >/dev/null 2>&1 || pm=yum
|
||||
sudo "$pm" groupinstall -y "Development Tools"
|
||||
sudo "$pm" install -y gcc gcc-c++ make git curl wget p7zip zip unzip npm
|
||||
sudo "$pm" install -y gcc gcc-c++ make git curl wget p7zip zip unzip file npm
|
||||
;;
|
||||
debian)
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential gcc g++ make git curl wget p7zip-full zip unzip unp npm
|
||||
sudo apt-get install -y libatomic1 build-essential gcc g++ make git curl wget p7zip-full zip unzip unp file npm
|
||||
;;
|
||||
*) echo "Unsupported Linux distribution; install a C/C++ toolchain, git, curl, wget, 7zip, zip, unzip and npm." >&2; exit 1 ;;
|
||||
*) echo "Unsupported Linux distribution; install a C/C++ toolchain, git, curl, wget, 7zip, zip, unzip, file and npm." >&2; exit 1 ;;
|
||||
esac
|
||||
#sudo chown -R $(id -u):$(id -g) $HOME/.npm
|
||||
sudo npm -g install n
|
||||
sudo n "$_wekan_node_version"
|
||||
sudo npm install -g npm@12.0.2
|
||||
sudo npm -g install meteor --unsafe-perm
|
||||
#sudo chown -R $(id -u):$(id -g) $HOME/.npm $HOME/.meteor
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
echo "macOS"
|
||||
# Node comes from nvm, not from Homebrew's node@24 keg.
|
||||
# Node comes from nvm, not from Homebrew's node@26 keg.
|
||||
#
|
||||
# `brew install node@24` gives whatever 24.x Homebrew currently has
|
||||
# `brew install node@26` gives whatever 26.x Homebrew currently has
|
||||
# bottled - which trails nodejs.org - and, being keg-only, needs
|
||||
# PATH, LDFLAGS and CPPFLAGS exported by hand. `nvm install 24`
|
||||
# resolves to the NEWEST 24.x on nodejs.org every time it runs and
|
||||
# PATH, LDFLAGS and CPPFLAGS exported by hand. `nvm install 26`
|
||||
# resolves to the NEWEST 26.x on nodejs.org every time it runs and
|
||||
# puts that on PATH itself, so this does not go stale the way a
|
||||
# pinned version does. npm comes with the Node it installs, so
|
||||
# there is no `brew install npm` either.
|
||||
@@ -2828,10 +2924,11 @@ for _once in 1; do
|
||||
# switch versions while it is set. The old Homebrew path set it, so
|
||||
# clear it before installing anything.
|
||||
npm config delete prefix >/dev/null 2>&1 || true
|
||||
# The newest 24.x, and the default for every new shell.
|
||||
nvm install 24
|
||||
nvm alias default 24
|
||||
nvm use 24
|
||||
# The newest 26.x, and the default for every new shell.
|
||||
nvm install 26
|
||||
nvm alias default 26
|
||||
nvm use 26
|
||||
npm install -g npm@12.0.2
|
||||
echo "Node $(node --version), npm $(npm --version)"
|
||||
# Let new shells find nvm too. Its installer appends these itself,
|
||||
# but only to the rc file it detects and only when IT did the
|
||||
@@ -2920,7 +3017,7 @@ for _once in 1; do
|
||||
#---------------------------------------------------------------------
|
||||
# Logging of terminal output to console and to .tools/log/wekan-log.log at end of this line: 2>&1 | tee "$(one_log dev-server)"
|
||||
#WARN_WHEN_USING_OLD_API=true NODE_OPTIONS="--trace-warnings"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG=true WRITABLE_PATH=.. WITH_API=true RICHER_CARD_COMMENT_EDITOR=false ROOT_URL=http://localhost:3000 meteor run --port 3000 2>&1 | tee "$(one_log dev-server)"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG="${DEBUG:-false}" WRITABLE_PATH=.. WITH_API=true ROOT_URL=http://localhost:3000 "${DEV_COMMAND[@]}" --port 3000 2>&1 | tee "$(one_log dev-server)"
|
||||
#---------------------------------------------------------------------
|
||||
break
|
||||
;;
|
||||
@@ -2932,7 +3029,7 @@ for _once in 1; do
|
||||
#Not in use, could increase RAM usage: NODE_OPTIONS="--max_old_space_size=4096"
|
||||
#---------------------------------------------------------------------
|
||||
# Logging of terminal output to console and to .tools/log/wekan-log.log at end of this line: 2>&1 | tee "$(one_log dev-server)"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG=true WARN_WHEN_USING_OLD_API=true NODE_OPTIONS="--trace-warnings --max-old-space-size=$_heap_mb" WRITABLE_PATH=.. WITH_API=true RICHER_CARD_COMMENT_EDITOR=false ROOT_URL=http://localhost:3000 meteor run --port 3000 2>&1 | tee "$(one_log dev-server)"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG="${DEBUG:-false}" WARN_WHEN_USING_OLD_API=true NODE_OPTIONS="--trace-warnings --max-old-space-size=$_heap_mb" WRITABLE_PATH=.. WITH_API=true ROOT_URL=http://localhost:3000 "${DEV_COMMAND[@]}" --port 3000 2>&1 | tee "$(one_log dev-server)"
|
||||
#---------------------------------------------------------------------
|
||||
break
|
||||
;;
|
||||
@@ -2944,7 +3041,7 @@ for _once in 1; do
|
||||
#---------------------------------------------------------------------
|
||||
#Logging of terminal output to console and to .tools/log/wekan-log.log at end of this line: 2>&1 | tee "$(one_log dev-server)"
|
||||
#WARN_WHEN_USING_OLD_API=true NODE_OPTIONS="--trace-warnings"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG=true WRITABLE_PATH=.. WITH_API=true RICHER_CARD_COMMENT_EDITOR=false ROOT_URL=http://localhost:3000 meteor run --port 3000 --extra-packages bundle-visualizer --production 2>&1 | tee "$(one_log dev-server)"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG="${DEBUG:-false}" WRITABLE_PATH=.. WITH_API=true ROOT_URL=http://localhost:3000 "${DEV_COMMAND[@]}" --port 3000 --extra-packages bundle-visualizer --production 2>&1 | tee "$(one_log dev-server)"
|
||||
#---------------------------------------------------------------------
|
||||
break
|
||||
;;
|
||||
@@ -2963,7 +3060,7 @@ for _once in 1; do
|
||||
#---------------------------------------------------------------------
|
||||
#Logging of terminal output to console and to .tools/log/wekan-log.log at end of this line: 2>&1 | tee "$(one_log dev-server)"
|
||||
#WARN_WHEN_USING_OLD_API=true NODE_OPTIONS="--trace-warnings"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG=true WRITABLE_PATH=.. WITH_API=true RICHER_CARD_COMMENT_EDITOR=false ROOT_URL=http://$IPADDRESS:3000 meteor run --port 3000 2>&1 | tee "$(one_log dev-server)"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG="${DEBUG:-false}" WRITABLE_PATH=.. WITH_API=true ROOT_URL=http://$IPADDRESS:3000 "${DEV_COMMAND[@]}" --port 3000 2>&1 | tee "$(one_log dev-server)"
|
||||
#---------------------------------------------------------------------
|
||||
break
|
||||
;;
|
||||
@@ -2982,7 +3079,7 @@ for _once in 1; do
|
||||
#---------------------------------------------------------------------
|
||||
#Logging of terminal output to console and to .tools/log/wekan-log.log at end of this line: 2>&1 | tee "$(one_log dev-server)"
|
||||
#WARN_WHEN_USING_OLD_API=true NODE_OPTIONS="--trace-warnings"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG=true MONGO_URL=mongodb://127.0.0.1:27019/wekan WRITABLE_PATH=.. WITH_API=true RICHER_CARD_COMMENT_EDITOR=false ROOT_URL=http://$IPADDRESS:3000 meteor run --port 3000 2>&1 | tee "$(one_log dev-server)"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG="${DEBUG:-false}" WEKAN_SOURCE_MONGO_PORT=27019 WEKAN_SOURCE_MONGO_DATABASE=wekan MONGO_URL=mongodb://127.0.0.1:27019/wekan WRITABLE_PATH=.. WITH_API=true ROOT_URL=http://$IPADDRESS:3000 "${DEV_COMMAND[@]}" --port 3000 2>&1 | tee "$(one_log dev-server)"
|
||||
#---------------------------------------------------------------------
|
||||
break
|
||||
;;
|
||||
@@ -2996,7 +3093,7 @@ for _once in 1; do
|
||||
# ROOT_URL differ. Logging of terminal output to console and to
|
||||
# .tools/log/wekan-log.log at the end of the line: 2>&1 | tee "$(one_log dev-server)"
|
||||
#---------------------------------------------------------------------
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG=true WRITABLE_PATH=.. WITH_API=true RICHER_CARD_COMMENT_EDITOR=false ROOT_URL="$DEV_ROOT_URL" meteor run --port "$DEV_PORT" 2>&1 | tee "$(one_log dev-server)"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG="${DEBUG:-false}" WRITABLE_PATH=.. WITH_API=true ROOT_URL="$DEV_ROOT_URL" "${DEV_COMMAND[@]}" --port "$DEV_PORT" 2>&1 | tee "$(one_log dev-server)"
|
||||
#---------------------------------------------------------------------
|
||||
break
|
||||
;;
|
||||
@@ -3015,7 +3112,7 @@ for _once in 1; do
|
||||
#---------------------------------------------------------------------
|
||||
#Logging of terminal output to console and to .tools/log/wekan-log.log at end of this line: 2>&1 | tee "$(one_log dev-server)"
|
||||
#WARN_WHEN_USING_OLD_API=true NODE_OPTIONS="--trace-warnings"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG=true WRITABLE_PATH=.. WITH_API=true RICHER_CARD_COMMENT_EDITOR=false ROOT_URL=http://$IPADDRESS:$PORT meteor run --port $PORT 2>&1 | tee "$(one_log dev-server)"
|
||||
DEFAULT_METEOR_REACTIVITY_ORDER="changeStreams,oplog,polling" DDP_TRANSPORT=sockjs DEBUG="${DEBUG:-false}" WRITABLE_PATH=.. WITH_API=true ROOT_URL=http://$IPADDRESS:$PORT "${DEV_COMMAND[@]}" --port $PORT 2>&1 | tee "$(one_log dev-server)"
|
||||
#---------------------------------------------------------------------
|
||||
break
|
||||
;;
|
||||
|
||||
@@ -90,7 +90,7 @@ template(name="commentReactions")
|
||||
unless currentUser.isReadOnly
|
||||
unless currentUser.isReadAssignedOnly
|
||||
a.open-comment-reaction-popup(title="{{_ 'addReactionPopup-title'}}")
|
||||
i.fa.fa-smile-o(title="{{_ 'reaction' }}")
|
||||
i.fa.fa-smile-o(title="{{_ 'addReactionPopup-title' }}")
|
||||
i.fa.fa-plus(title="{{_ 'add' }}")
|
||||
|
||||
template(name="addReactionPopup")
|
||||
|
||||
@@ -67,7 +67,6 @@ Template.commentForm.onDestroyed(function () {
|
||||
// button, a route change); make sure the last keystrokes reach the draft.
|
||||
flushCommentDraftSave();
|
||||
commentFormIsOpen.set(false);
|
||||
$('.note-popover').hide();
|
||||
});
|
||||
|
||||
Template.commentForm.helpers({
|
||||
|
||||
@@ -476,7 +476,7 @@ Template.boardBody.onRendered(function () {
|
||||
el.setAttribute('role', 'button');
|
||||
// Short, descriptive label for favorite/star toggle
|
||||
if (el.classList.contains('js-favorite-toggle')) {
|
||||
el.setAttribute('aria-label', TAPi18n.__('favorite-toggle-label'));
|
||||
el.setAttribute('aria-label', `${TAPi18n.__('star-item')} / ${TAPi18n.__('unstar-item')}`);
|
||||
} else {
|
||||
el.setAttribute('aria-label', 'Toggle');
|
||||
}
|
||||
|
||||
Loaded 100 of 1192 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user