Compare commits
1259 Commits
v1.14.0
...
db-postgre
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76d6c88261 | ||
|
|
10ebd76fcf | ||
|
|
36d6eb0a69 | ||
|
|
cd1f8dc332 | ||
|
|
e4275aa228 | ||
|
|
ddfcb2f12e | ||
|
|
09f33eae2c | ||
|
|
d3b7c9feec | ||
|
|
5fd3d43000 | ||
|
|
7767679caa | ||
|
|
fdf2e32005 | ||
|
|
773be8744d | ||
|
|
40d5bc0c4a | ||
|
|
fd33c790f2 | ||
|
|
ae7aac7639 | ||
|
|
05cc2873b4 | ||
|
|
171ee121e9 | ||
|
|
4af1d7d812 | ||
|
|
d229fc391a | ||
|
|
46a24a9822 | ||
|
|
06a51b3c9b | ||
|
|
1d4142ccc0 | ||
|
|
f1741beba2 | ||
|
|
9103277a10 | ||
|
|
d84673f400 | ||
|
|
15e23a3adc | ||
|
|
565929adcf | ||
|
|
8bbac60e60 | ||
|
|
15c7f0dbf3 | ||
|
|
05eba56d7d | ||
|
|
ab984b3ea9 | ||
|
|
a54638eb47 | ||
|
|
69af8d9c83 | ||
|
|
64864686c4 | ||
|
|
32c0bef05e | ||
|
|
a77513e94f | ||
|
|
aaf883909c | ||
|
|
cc56da11d6 | ||
|
|
41d9c28073 | ||
|
|
a071b97607 | ||
|
|
cfd9231403 | ||
|
|
71dce62646 | ||
|
|
db376f24ba | ||
|
|
2752483ac7 | ||
|
|
860f867c62 | ||
|
|
5b0adbe9c3 | ||
|
|
fb7d1be2f3 | ||
|
|
687a2e85d0 | ||
|
|
df80483afe | ||
|
|
8781770d83 | ||
|
|
ed1d5a60f7 | ||
|
|
50a0965561 | ||
|
|
c31fa5dd83 | ||
|
|
440eb8d9c6 | ||
|
|
1523b2be41 | ||
|
|
68f55c4064 | ||
|
|
0d3544ea04 | ||
|
|
f152f451dc | ||
|
|
5d92436e39 | ||
|
|
63edecddd8 | ||
|
|
65cdf6bfd0 | ||
|
|
9e831a6a00 | ||
|
|
0b64c5fb66 | ||
|
|
40426a25df | ||
|
|
c91b1e8310 | ||
|
|
06e2fa9d11 | ||
|
|
72249d1ecd | ||
|
|
dc22496103 | ||
|
|
c6925ec29f | ||
|
|
8f46b31249 | ||
|
|
af1c2e924e | ||
|
|
1487250752 | ||
|
|
e3c776523a | ||
|
|
c09e9d96cf | ||
|
|
aabc0650f8 | ||
|
|
4dd4e9aaae | ||
|
|
3b63b7fc3c | ||
|
|
f0e2e78b82 | ||
|
|
a154adf066 | ||
|
|
d86bcc1495 | ||
|
|
2b7043c6e6 | ||
|
|
e0afeeca97 | ||
|
|
76e306ddd8 | ||
|
|
cfc78ed4f5 | ||
|
|
64b0db5a7a | ||
|
|
48600f0c66 | ||
|
|
6d2dd5849d | ||
|
|
6d9353b53f | ||
|
|
1914be75aa | ||
|
|
b17f627e02 | ||
|
|
bef79621ee | ||
|
|
af892ecb0e | ||
|
|
a42e84bbb2 | ||
|
|
470bdb72ff | ||
|
|
5c36be949c | ||
|
|
eb97acd408 | ||
|
|
2567ac58ba | ||
|
|
9ff014bbfe | ||
|
|
e6f0d35985 | ||
|
|
b1e449e005 | ||
|
|
9ae585d23c | ||
|
|
9de3320933 | ||
|
|
5d429fa7ae | ||
|
|
dc8f1925f0 | ||
|
|
15f650afde | ||
|
|
c945384d63 | ||
|
|
dfada1b238 | ||
|
|
229bdda2c1 | ||
|
|
a1d51fb410 | ||
|
|
46430f5598 | ||
|
|
e41899cd27 | ||
|
|
890af8be05 | ||
|
|
8bfae6b932 | ||
|
|
ace3e577f6 | ||
|
|
9198245ad9 | ||
|
|
f0095937ba | ||
|
|
0bbd7137cd | ||
|
|
ffed34cf27 | ||
|
|
040f3a34d1 | ||
|
|
0985825b08 | ||
|
|
c18d3b5f0e | ||
|
|
e9e25ceac9 | ||
|
|
35aed59a1a | ||
|
|
26002173b1 | ||
|
|
41d968771e | ||
|
|
26c34541d2 | ||
|
|
263d40d169 | ||
|
|
6ced11d44d | ||
|
|
be049cea00 | ||
|
|
491e50c236 | ||
|
|
ad253db691 | ||
|
|
aff5fdff8a | ||
|
|
aa97bebbd4 | ||
|
|
a2410ea9fc | ||
|
|
de20ef1e8d | ||
|
|
08f7497040 | ||
|
|
74e99ce251 | ||
|
|
b5c56efb4b | ||
|
|
4ff6d63c94 | ||
|
|
c90d1faa7f | ||
|
|
1848b120ce | ||
|
|
62679baa91 | ||
|
|
2de36550ae | ||
|
|
61ea5becbb | ||
|
|
5d9384f530 | ||
|
|
d75ffa0ea7 | ||
|
|
26967fb924 | ||
|
|
830d9867b6 | ||
|
|
2f86c196e1 | ||
|
|
86a35ed441 | ||
|
|
70e068b182 | ||
|
|
4ac01a7fa3 | ||
|
|
8058a6d800 | ||
|
|
252b04097f | ||
|
|
23066aec71 | ||
|
|
b9a595b00c | ||
|
|
ea49d74941 | ||
|
|
f5f41f929e | ||
|
|
61151c9c5d | ||
|
|
c12c1a7472 | ||
|
|
7afa1e999d | ||
|
|
71c41dbe03 | ||
|
|
a161dc7bb6 | ||
|
|
6c17222a6a | ||
|
|
63bf7d9303 | ||
|
|
f878135e8b | ||
|
|
11a77ae489 | ||
|
|
e5d6a75449 | ||
|
|
3cb0d9c2ca | ||
|
|
229149a5a6 | ||
|
|
9006643102 | ||
|
|
25ae4a24f2 | ||
|
|
501ec4464f | ||
|
|
961505366a | ||
|
|
c54fb304e7 | ||
|
|
7679e3f0aa | ||
|
|
f7c35df6de | ||
|
|
ca97f692c3 | ||
|
|
9244a2d25d | ||
|
|
24f1965f69 | ||
|
|
d0c352cc62 | ||
|
|
c56e61023d | ||
|
|
ae03501753 | ||
|
|
7b94fb75bb | ||
|
|
e842c6624a | ||
|
|
2ddf15ce9a | ||
|
|
7df1256bf6 | ||
|
|
1ebb9f3915 | ||
|
|
eab04d9b4d | ||
|
|
c6e6f99868 | ||
|
|
fbbc0a3c67 | ||
|
|
ef24f430a2 | ||
|
|
617ab76a22 | ||
|
|
9d9918e0fd | ||
|
|
e515712fcd | ||
|
|
0ce08aab99 | ||
|
|
e398044442 | ||
|
|
7e5d322d6b | ||
|
|
b04f6b2b5b | ||
|
|
36225d1455 | ||
|
|
c9fdcebb9e | ||
|
|
1758b6c449 | ||
|
|
5e6bec773f | ||
|
|
5ebe375743 | ||
|
|
bca1be8cb6 | ||
|
|
1e197933dd | ||
|
|
25d20cf87b | ||
|
|
b32b156f9f | ||
|
|
fd38fa8209 | ||
|
|
33bf4491a9 | ||
|
|
7ad9d777a2 | ||
|
|
92fdfbe333 | ||
|
|
27ba1fc79e | ||
|
|
bdbfc8c9af | ||
|
|
8c097ccaa7 | ||
|
|
4eb929d57c | ||
|
|
198209c2a4 | ||
|
|
54f19ce1e3 | ||
|
|
d32f3ade1b | ||
|
|
87d66dceb1 | ||
|
|
256fc6d178 | ||
|
|
74f8923922 | ||
|
|
d9d4df22e5 | ||
|
|
3161d3e552 | ||
|
|
0acffa38eb | ||
|
|
4503ce39fa | ||
|
|
0e407e05d7 | ||
|
|
d50049878d | ||
|
|
26d56de572 | ||
|
|
73f434e394 | ||
|
|
bf189abc91 | ||
|
|
13bc3e3681 | ||
|
|
b398c44bfe | ||
|
|
aa443d9050 | ||
|
|
f39ba60b08 | ||
|
|
791f2051f3 | ||
|
|
a37798b80d | ||
|
|
077bd7fad3 | ||
|
|
8255088f39 | ||
|
|
5a969a2c4d | ||
|
|
7c7e841af7 | ||
|
|
13332f04ab | ||
|
|
c1d28a7a07 | ||
|
|
69a379e49f | ||
|
|
493fc3ed68 | ||
|
|
138e495e1a | ||
|
|
4eaa76a314 | ||
|
|
8f98eff0d7 | ||
|
|
f8dce28904 | ||
|
|
09ee95087b | ||
|
|
190a1ab5a0 | ||
|
|
5e8b11b5d3 | ||
|
|
436250d594 | ||
|
|
09c94609b4 | ||
|
|
6d012bff68 | ||
|
|
f0af24d066 | ||
|
|
360291c407 | ||
|
|
d8f6f86228 | ||
|
|
a0645bbae5 | ||
|
|
999f2fba04 | ||
|
|
6009b18f75 | ||
|
|
f968b92968 | ||
|
|
b51987d4ac | ||
|
|
2639d29b91 | ||
|
|
3668f053b3 | ||
|
|
18da607f5b | ||
|
|
8e4cede62c | ||
|
|
e0af6fea99 | ||
|
|
27f861d725 | ||
|
|
bb0c997a87 | ||
|
|
eb58d9e877 | ||
|
|
c9387eba27 | ||
|
|
1c577d1d0c | ||
|
|
86802dd531 | ||
|
|
1c3d969ef1 | ||
|
|
b9aa4d96a3 | ||
|
|
6c866773b2 | ||
|
|
1020b08fd1 | ||
|
|
b5b451464c | ||
|
|
b90796f48a | ||
|
|
0e67ac9b6b | ||
|
|
de79dca08f | ||
|
|
74972cf4c9 | ||
|
|
595ba1b241 | ||
|
|
022ef85d8c | ||
|
|
8e0c3602f9 | ||
|
|
70d41407a8 | ||
|
|
be618ba79e | ||
|
|
8f2cec2535 | ||
|
|
ad896e377b | ||
|
|
9574444b57 | ||
|
|
450a648e7e | ||
|
|
940174f446 | ||
|
|
3600dbb3ab | ||
|
|
a41a3c5ee7 | ||
|
|
6c0eef3ec2 | ||
|
|
3a16eb90b6 | ||
|
|
2f8d5dc628 | ||
|
|
e1f092410e | ||
|
|
654561cf30 | ||
|
|
77bb42d672 | ||
|
|
cdbe61875e | ||
|
|
e5d3821a9e | ||
|
|
f70837ab11 | ||
|
|
0dbcc2725e | ||
|
|
6efedc174a | ||
|
|
c4f2a65e49 | ||
|
|
5d1444e1bd | ||
|
|
8fe619a221 | ||
|
|
5195a80dba | ||
|
|
909cf90fa2 | ||
|
|
03c9a91ea9 | ||
|
|
f3d2060d8d | ||
|
|
c1d1a00d4a | ||
|
|
ae68093f35 | ||
|
|
0f2f355a01 | ||
|
|
0101aa60d9 | ||
|
|
eb069e4253 | ||
|
|
27deeccd50 | ||
|
|
59bd6abfc3 | ||
|
|
ad7c25685e | ||
|
|
7e9c7707ba | ||
|
|
acfda5d8d4 | ||
|
|
b6de427f04 | ||
|
|
88c84ad8d6 | ||
|
|
00543f5e25 | ||
|
|
d2415a5af4 | ||
|
|
75ae2456a8 | ||
|
|
ace393ca46 | ||
|
|
3fce97a6d2 | ||
|
|
e55ec6329c | ||
|
|
fb07308dca | ||
|
|
5bc81031d1 | ||
|
|
03538c0901 | ||
|
|
960fe42b93 | ||
|
|
64c405d0fc | ||
|
|
75ec46ad63 | ||
|
|
345c606895 | ||
|
|
06fe3f4ac8 | ||
|
|
6afdaefdcd | ||
|
|
4d4db8065e | ||
|
|
1ce9b28dce | ||
|
|
6a74173789 | ||
|
|
877576119a | ||
|
|
50dd03853a | ||
|
|
163cf631e8 | ||
|
|
7690fa1b55 | ||
|
|
11b51bca75 | ||
|
|
85e64c9209 | ||
|
|
4ad8a9f5bb | ||
|
|
ba4656b966 | ||
|
|
8df9d57a69 | ||
|
|
ae436673cb | ||
|
|
7c1b3b9de3 | ||
|
|
83d6b3f652 | ||
|
|
ae49403c45 | ||
|
|
c8b843c819 | ||
|
|
48db3027c9 | ||
|
|
5f4c38ce21 | ||
|
|
4a91be1d62 | ||
|
|
ca5dbb5cd4 | ||
|
|
a8ff06a134 | ||
|
|
01891bb8bc | ||
|
|
0d2fe860e5 | ||
|
|
542dcb3226 | ||
|
|
4e973c9389 | ||
|
|
2b831a67b4 | ||
|
|
a423c7fd60 | ||
|
|
c3b2b19dbe | ||
|
|
272f62f032 | ||
|
|
d063c93394 | ||
|
|
d73596a670 | ||
|
|
78d6643950 | ||
|
|
c823ee07cd | ||
|
|
1f12f9b480 | ||
|
|
ec31ab3a2c | ||
|
|
a7bea35d69 | ||
|
|
64a4f19539 | ||
|
|
c35661e16e | ||
|
|
69b6179521 | ||
|
|
3d2e167e78 | ||
|
|
aa1955221c | ||
|
|
7a9b11e2c4 | ||
|
|
a82c0d0e50 | ||
|
|
35a6daa10d | ||
|
|
bf5db4e44a | ||
|
|
a87e8aa82b | ||
|
|
e00d87a791 | ||
|
|
b61babca73 | ||
|
|
e403a0492e | ||
|
|
54a76e1401 | ||
|
|
cffb5663aa | ||
|
|
91f6e36420 | ||
|
|
02c165b71f | ||
|
|
783072ef7c | ||
|
|
72fe24b69e | ||
|
|
81ed355bbc | ||
|
|
08a114e0e0 | ||
|
|
c49bb14414 | ||
|
|
2411cfbe13 | ||
|
|
c1439ae7da | ||
|
|
36e7e1d946 | ||
|
|
63bae989bb | ||
|
|
528150c3f7 | ||
|
|
fa91d45ae6 | ||
|
|
b545f62574 | ||
|
|
b6a778196d | ||
|
|
9acc1e4c99 | ||
|
|
dfd5151c4f | ||
|
|
605ba73c30 | ||
|
|
c4e4a5a3f7 | ||
|
|
82d9dd8a28 | ||
|
|
8a2045e3e4 | ||
|
|
cddde3e488 | ||
|
|
986ceea246 | ||
|
|
d638408399 | ||
|
|
a46a80bd52 | ||
|
|
c2a99c8edc | ||
|
|
2fe7818f29 | ||
|
|
0bb11ecf8b | ||
|
|
eafeea4dd8 | ||
|
|
bbd410bcbe | ||
|
|
d2fa65cb4f | ||
|
|
18472d0178 | ||
|
|
7ee41b6a65 | ||
|
|
0a895eee80 | ||
|
|
74d6ef0c31 | ||
|
|
f77c41978b | ||
|
|
9e74fe558f | ||
|
|
ac8bcfac23 | ||
|
|
3538c2132d | ||
|
|
fd9d98da9f | ||
|
|
1c22459107 | ||
|
|
2d084e19d3 | ||
|
|
80f2d417f2 | ||
|
|
cfb77e2f27 | ||
|
|
deb5be5a9b | ||
|
|
9880880384 | ||
|
|
618ee991dc | ||
|
|
374fb99571 | ||
|
|
183414e6e8 | ||
|
|
91b0a691ed | ||
|
|
3ced6ec2a0 | ||
|
|
650fe159ee | ||
|
|
b7d983f30a | ||
|
|
b92657fb39 | ||
|
|
617ca9f85f | ||
|
|
47206f9e6a | ||
|
|
131157ba29 | ||
|
|
db28547a51 | ||
|
|
f0689d403d | ||
|
|
c46ffbd7ae | ||
|
|
f935a54107 | ||
|
|
bfa16e418f | ||
|
|
6dbe80be2e | ||
|
|
302185e473 | ||
|
|
7d8ac3e6f2 | ||
|
|
001b87a8c6 | ||
|
|
cd49a7a940 | ||
|
|
9da6506622 | ||
|
|
0ac36069bd | ||
|
|
f989e02a85 | ||
|
|
15e6401d4e | ||
|
|
3d61445cd0 | ||
|
|
20a99ff2c7 | ||
|
|
27ef3a01f8 | ||
|
|
0bc4276d87 | ||
|
|
ab34f08169 | ||
|
|
0c57c89d83 | ||
|
|
12bf78f41b | ||
|
|
10bd20904a | ||
|
|
c3abaf5f1d | ||
|
|
9ecef40ee7 | ||
|
|
76c2fad94f | ||
|
|
aff983f5a2 | ||
|
|
bf2cd5aac4 | ||
|
|
9baf7e9a70 | ||
|
|
e64928f03a | ||
|
|
33c3a7a50a | ||
|
|
1cce3ebce9 | ||
|
|
1e71776f22 | ||
|
|
6a5ddd32ab | ||
|
|
4e8d4797e1 | ||
|
|
3ce9c9ef03 | ||
|
|
d1cbe4aa4e | ||
|
|
84702d8e31 | ||
|
|
9d1bda070f | ||
|
|
b6b1a8e65d | ||
|
|
ffc16f08b9 | ||
|
|
4e97621619 | ||
|
|
3d0b125e0a | ||
|
|
029d031974 | ||
|
|
812d1806f5 | ||
|
|
fc364b2d02 | ||
|
|
a6880207cd | ||
|
|
98b6108eab | ||
|
|
aa3a997d4d | ||
|
|
5c5b661412 | ||
|
|
823681cc42 | ||
|
|
6226368841 | ||
|
|
1107a1d7d1 | ||
|
|
394c2bc23a | ||
|
|
825f9521bb | ||
|
|
c161f019af | ||
|
|
f80dc6a668 | ||
|
|
df69441a6a | ||
|
|
25672f5975 | ||
|
|
99a5e78a66 | ||
|
|
d48f0c1567 | ||
|
|
bb385280cc | ||
|
|
cb3029583c | ||
|
|
d5ab5e2afe | ||
|
|
46774b80f0 | ||
|
|
299c29019f | ||
|
|
3092fd0843 | ||
|
|
715ae79727 | ||
|
|
2e0c0d0224 | ||
|
|
5f28bcc25a | ||
|
|
81a1ad288d | ||
|
|
cbc1f3b3f1 | ||
|
|
fdbb61fc43 | ||
|
|
f5d7ff2eee | ||
|
|
3c63f5148b | ||
|
|
2ad94e48f7 | ||
|
|
cf26155995 | ||
|
|
7349c82e28 | ||
|
|
f94e20942b | ||
|
|
fdcdabd3ed | ||
|
|
8ba1274e2f | ||
|
|
baf2b6de30 | ||
|
|
426efcaa08 | ||
|
|
4f405bbee6 | ||
|
|
0c977511f6 | ||
|
|
7abb2450ef | ||
|
|
85bcf150a7 | ||
|
|
05116dd667 | ||
|
|
8e0b57ea59 | ||
|
|
1286ed4706 | ||
|
|
51b2ce9fe9 | ||
|
|
0c6bea7388 | ||
|
|
29aa6e1449 | ||
|
|
2938ce0d09 | ||
|
|
a52ebf5596 | ||
|
|
dfac7395fe | ||
|
|
5b3fd4f6ab | ||
|
|
5ea06c9ad0 | ||
|
|
e7aac41672 | ||
|
|
c1861eecc8 | ||
|
|
63177b5d55 | ||
|
|
5464966d1a | ||
|
|
a53cbd146f | ||
|
|
ec0f5a77b7 | ||
|
|
316702c253 | ||
|
|
029da71a83 | ||
|
|
e5a95755da | ||
|
|
eb988f1f19 | ||
|
|
45f23367c8 | ||
|
|
30e9ba67ed | ||
|
|
6d014cf748 | ||
|
|
2e480d4c99 | ||
|
|
42ceafb942 | ||
|
|
fa4821adef | ||
|
|
5d6b82a2b4 | ||
|
|
e913d5c400 | ||
|
|
9a6d650a13 | ||
|
|
6aaa22b2b4 | ||
|
|
0de816591b | ||
|
|
fd9ca519d7 | ||
|
|
dbdd317af7 | ||
|
|
71b372211f | ||
|
|
ddc6cb927b | ||
|
|
85c81c3efe | ||
|
|
bb9b4c9fa0 | ||
|
|
237fa50255 | ||
|
|
556620a94e | ||
|
|
8f837f99ae | ||
|
|
32e30ca678 | ||
|
|
6e07aee59a | ||
|
|
44b10cc9b4 | ||
|
|
2649ceaac6 | ||
|
|
ee22a488c0 | ||
|
|
40f4014920 | ||
|
|
317104bb9f | ||
|
|
eed2b699c8 | ||
|
|
48591aa24c | ||
|
|
f8d456d762 | ||
|
|
e6a0ed5e1c | ||
|
|
9308c792e1 | ||
|
|
8f14cd2c59 | ||
|
|
4ac9f339e6 | ||
|
|
fd146fb9ac | ||
|
|
4debc50c36 | ||
|
|
a73246f85b | ||
|
|
7bccd40a95 | ||
|
|
b990e98b89 | ||
|
|
5767e5d61c | ||
|
|
34e2dc8a79 | ||
|
|
244db8d621 | ||
|
|
9d9d20efd9 | ||
|
|
96844a5185 | ||
|
|
973b4edba9 | ||
|
|
4ae40f4a12 | ||
|
|
07f713f8e9 | ||
|
|
1ca5c70ed6 | ||
|
|
6fa5866f99 | ||
|
|
f723b0e0e9 | ||
|
|
33aac93c6e | ||
|
|
719dd1f2ba | ||
|
|
b8c36ea8c5 | ||
|
|
706f2b469f | ||
|
|
806dc9c098 | ||
|
|
be09b9bbe6 | ||
|
|
0c943be3be | ||
|
|
796469f7cc | ||
|
|
8ea63421f0 | ||
|
|
5d0bd25267 | ||
|
|
5be49e1484 | ||
|
|
a73625edb9 | ||
|
|
20da1c4a13 | ||
|
|
506f82127b | ||
|
|
6ed6c5b5b0 | ||
|
|
43daa8640a | ||
|
|
97352f7ceb | ||
|
|
09883ee78c | ||
|
|
aa94c00bc6 | ||
|
|
d61eef23d1 | ||
|
|
6e81fa68e8 | ||
|
|
8e8ba82c6d | ||
|
|
74605e471d | ||
|
|
4593d37815 | ||
|
|
6f5561e14f | ||
|
|
db38499d41 | ||
|
|
a5f162e883 | ||
|
|
65e080671d | ||
|
|
c5c15c4463 | ||
|
|
5572c69741 | ||
|
|
eac4605c99 | ||
|
|
a48d000b54 | ||
|
|
88030616d7 | ||
|
|
826c8671c6 | ||
|
|
81d294b065 | ||
|
|
b214d7b7d3 | ||
|
|
9c0aadd046 | ||
|
|
a9f1dc02ca | ||
|
|
07dd353432 | ||
|
|
6a6094c1a7 | ||
|
|
beb7647bc7 | ||
|
|
af3baee927 | ||
|
|
7f7d914b4e | ||
|
|
43064f4900 | ||
|
|
6fd3a896a1 | ||
|
|
8e6e576cd0 | ||
|
|
ba4cd2b599 | ||
|
|
ad24a17bd5 | ||
|
|
4df19cbdf6 | ||
|
|
67103a7059 | ||
|
|
4ba5d723f5 | ||
|
|
8155902476 | ||
|
|
bf745d19ed | ||
|
|
ef51e0855f | ||
|
|
e437b41950 | ||
|
|
220e7a590d | ||
|
|
bb7feddbff | ||
|
|
74fcf2fc1f | ||
|
|
a458375934 | ||
|
|
e5ef842839 | ||
|
|
0fbb8d1a32 | ||
|
|
1c2e74f0c9 | ||
|
|
e6e8ab6630 | ||
|
|
d3bfb76783 | ||
|
|
64e7c395ce | ||
|
|
d886af32d9 | ||
|
|
ee0bddf85b | ||
|
|
7ea4fcde2c | ||
|
|
0f6f26e4d1 | ||
|
|
82d2d2350f | ||
|
|
1377f56f26 | ||
|
|
a112b98597 | ||
|
|
95e428223f | ||
|
|
5abd9e3372 | ||
|
|
0c0a11debb | ||
|
|
528fb47b0b | ||
|
|
0d68216c4b | ||
|
|
6ee15c3571 | ||
|
|
575bd9436a | ||
|
|
f3415bb13e | ||
|
|
8b715a8127 | ||
|
|
ad82b99dc6 | ||
|
|
6aaaeaff98 | ||
|
|
edf9dd7983 | ||
|
|
9eca30f281 | ||
|
|
67b347aaa3 | ||
|
|
c02dc385cb | ||
|
|
44a2b1a98f | ||
|
|
c0dfeb4918 | ||
|
|
17132b72ad | ||
|
|
1191a2851c | ||
|
|
caa56e6ef6 | ||
|
|
62421da6ad | ||
|
|
cec16abea0 | ||
|
|
25be3a3c6f | ||
|
|
4dd98396a7 | ||
|
|
0c101cd713 | ||
|
|
2a282c7257 | ||
|
|
bbcdf32a90 | ||
|
|
db4aa1e8b6 | ||
|
|
7159bf2ff3 | ||
|
|
07aaacaa55 | ||
|
|
274d062d6d | ||
|
|
53572bf933 | ||
|
|
7b6fd62895 | ||
|
|
32fb5e66f8 | ||
|
|
92275f909f | ||
|
|
3cfc51ecf4 | ||
|
|
1ed8dad92d | ||
|
|
81df72b5c2 | ||
|
|
7b38bd1e52 | ||
|
|
b1ec1f5f3f | ||
|
|
1b3419cd12 | ||
|
|
c3a357f893 | ||
|
|
5f0207d617 | ||
|
|
5bc8b29e79 | ||
|
|
7fdf77cf3e | ||
|
|
463a39e822 | ||
|
|
6338471287 | ||
|
|
c356b96913 | ||
|
|
fbe5f36b29 | ||
|
|
cdaa0acd61 | ||
|
|
4f68b722dc | ||
|
|
a81401cf77 | ||
|
|
835efdf400 | ||
|
|
7725c1fdc9 | ||
|
|
1efab0b6a3 | ||
|
|
53a80be6a0 | ||
|
|
05eabc7a9d | ||
|
|
43451a629a | ||
|
|
8ab24a4513 | ||
|
|
75a428ddc4 | ||
|
|
b271936b64 | ||
|
|
c7744c5bf0 | ||
|
|
320e4a47cd | ||
|
|
66859f4073 | ||
|
|
321e59705d | ||
|
|
029e319c7b | ||
|
|
2442144c98 | ||
|
|
a8418bffa2 | ||
|
|
025d647bf7 | ||
|
|
718f51d8d8 | ||
|
|
3c92c55ca9 | ||
|
|
128fe0119e | ||
|
|
9bd8f14ba8 | ||
|
|
998eb99003 | ||
|
|
6abe7f2569 | ||
|
|
9efd7c9ed2 | ||
|
|
d46e1837a1 | ||
|
|
16a4de2df7 | ||
|
|
649cf57ea8 | ||
|
|
5aa67cf98d | ||
|
|
4df942529a | ||
|
|
dbaa1f7319 | ||
|
|
85c8e4dc65 | ||
|
|
055c65f229 | ||
|
|
270ee3687b | ||
|
|
5292f41a3b | ||
|
|
5a56e18e7d | ||
|
|
26955bb331 | ||
|
|
b8f831fd05 | ||
|
|
81010311f9 | ||
|
|
4b514d4c94 | ||
|
|
92b4490257 | ||
|
|
2a9946f788 | ||
|
|
dd0514bd2c | ||
|
|
a28b266716 | ||
|
|
09a455bb7b | ||
|
|
2c61ae8452 | ||
|
|
0347d6a211 | ||
|
|
b21b4719fc | ||
|
|
1fa636417f | ||
|
|
577f54fcf3 | ||
|
|
abab0abca8 | ||
|
|
8df2c888fe | ||
|
|
a838274ae7 | ||
|
|
16d314ff49 | ||
|
|
79f9ef2481 | ||
|
|
9575ec5319 | ||
|
|
11c8804886 | ||
|
|
488c6651d9 | ||
|
|
744de9c706 | ||
|
|
1f1082c068 | ||
|
|
33e50f7d6b | ||
|
|
bb16ce965c | ||
|
|
8d98dea1b8 | ||
|
|
7cdda26e5d | ||
|
|
cc1966020a | ||
|
|
48398db28c | ||
|
|
33c15afa79 | ||
|
|
2b7d776b26 | ||
|
|
61098f96a8 | ||
|
|
8e16d825ff | ||
|
|
9f4fdc5bc4 | ||
|
|
2ff41f7a50 | ||
|
|
aad2389a20 | ||
|
|
58589021cc | ||
|
|
56a02975d1 | ||
|
|
41347bef5f | ||
|
|
73fe11baf3 | ||
|
|
af6b7592a1 | ||
|
|
1fc9ca1709 | ||
|
|
754efe00f6 | ||
|
|
df33323bc8 | ||
|
|
e2df74bbff | ||
|
|
4aad563f58 | ||
|
|
1f7b52497c | ||
|
|
595173327e | ||
|
|
abd983f421 | ||
|
|
1092ae6f98 | ||
|
|
d52e265117 | ||
|
|
1fbda85cd0 | ||
|
|
9e4474be60 | ||
|
|
a51b5970dc | ||
|
|
fd2290d6f7 | ||
|
|
4e9b2b4b5e | ||
|
|
bf673096e3 | ||
|
|
2e086d95d9 | ||
|
|
d07394d197 | ||
|
|
17dbe066c1 | ||
|
|
5acc88ee9a | ||
|
|
8093eb46b3 | ||
|
|
dbfcaded16 | ||
|
|
4c5673be23 | ||
|
|
d33cff94e0 | ||
|
|
5b620e77f4 | ||
|
|
59fe015239 | ||
|
|
73e2a03b6d | ||
|
|
eea371b336 | ||
|
|
bd7bd8faec | ||
|
|
16c1ac8d9a | ||
|
|
f97da2a9b4 | ||
|
|
b93d2d89c7 | ||
|
|
0f3b364e46 | ||
|
|
893ca87225 | ||
|
|
934bae2d24 | ||
|
|
63d18beb10 | ||
|
|
c48f6a298c | ||
|
|
cacae16678 | ||
|
|
3444525428 | ||
|
|
ae7d6f97d2 | ||
|
|
5d7aa0d009 | ||
|
|
5f7673d735 | ||
|
|
c3c13627f1 | ||
|
|
373e89a6ba | ||
|
|
6ba79de560 | ||
|
|
ba2f6ed9c3 | ||
|
|
f0ce57169d | ||
|
|
d4983af3fc | ||
|
|
6f2dcfd44e | ||
|
|
ee89693691 | ||
|
|
e9b6db6559 | ||
|
|
a19ccbb359 | ||
|
|
09260df134 | ||
|
|
00874a4406 | ||
|
|
2a99e6b72a | ||
|
|
126f7f1a5a | ||
|
|
55a996af19 | ||
|
|
bf79211163 | ||
|
|
fe0487b336 | ||
|
|
62e37802ca | ||
|
|
4dd29bf4e8 | ||
|
|
1ca81ac726 | ||
|
|
7b72f887d1 | ||
|
|
53526490f8 | ||
|
|
28eaafd9c7 | ||
|
|
27c02abacd | ||
|
|
e350c72342 | ||
|
|
f631e5bef3 | ||
|
|
6f22b662ec | ||
|
|
61e675dd7b | ||
|
|
4c345d18ff | ||
|
|
1a8ab3b7cd | ||
|
|
7a90a440a9 | ||
|
|
2fdbf1d212 | ||
|
|
7a72e99896 | ||
|
|
1acc6f2adc | ||
|
|
36f0f63d3e | ||
|
|
759d36049d | ||
|
|
97fac77fa3 | ||
|
|
d7a89d4098 | ||
|
|
370e38ae30 | ||
|
|
2d2d9fa673 | ||
|
|
4ee83881cc | ||
|
|
57e8c0756e | ||
|
|
2d97d3bcb1 | ||
|
|
65a22082d6 | ||
|
|
004f2ed045 | ||
|
|
b8b9d7b7a1 | ||
|
|
52820d0111 | ||
|
|
6fdd854cab | ||
|
|
b5bca5412a | ||
|
|
a67278b29f | ||
|
|
e24ad67168 | ||
|
|
25a182f407 | ||
|
|
b4578c10a4 | ||
|
|
bb3dd62b4e | ||
|
|
48d51fbf08 | ||
|
|
9467074fb9 | ||
|
|
659d4e77b9 | ||
|
|
f911257cd9 | ||
|
|
0296c51324 | ||
|
|
b29b83315d | ||
|
|
0732f00490 | ||
|
|
e22ca1beff | ||
|
|
635b2e9963 | ||
|
|
ddc692a966 | ||
|
|
640fd2843f | ||
|
|
af13924d3f | ||
|
|
7c4dd5ec5e | ||
|
|
3df6435353 | ||
|
|
3ef03364be | ||
|
|
5396af9bfc | ||
|
|
56eddf3a93 | ||
|
|
6dd900e6b9 | ||
|
|
e73cd26f10 | ||
|
|
24aa1f27c1 | ||
|
|
791ed3be50 | ||
|
|
7345fa8fcd | ||
|
|
589fbba5aa | ||
|
|
237a91f0cc | ||
|
|
f8e6914f44 | ||
|
|
cd447f1a9d | ||
|
|
2f8549f331 | ||
|
|
4f7d7a4d1b | ||
|
|
a7ad9903d7 | ||
|
|
9d7f88c8f7 | ||
|
|
0447dd3a33 | ||
|
|
5bac50bca9 | ||
|
|
353e851b29 | ||
|
|
e25b77b411 | ||
|
|
84207d1e3b | ||
|
|
7e5f091e3a | ||
|
|
2f3f830de0 | ||
|
|
9500d94add | ||
|
|
eea3cca28b | ||
|
|
f6379e2117 | ||
|
|
57e25689a7 | ||
|
|
8ec4a70aa8 | ||
|
|
8685ca6e94 | ||
|
|
72efd56302 | ||
|
|
89f759fa84 | ||
|
|
6192c8623f | ||
|
|
cd322beba1 | ||
|
|
e120d08282 | ||
|
|
a9c4263646 | ||
|
|
fd51903f02 | ||
|
|
221636027c | ||
|
|
672e7e6ff3 | ||
|
|
9022c8e22e | ||
|
|
bd464990ea | ||
|
|
3ccdcc5c29 | ||
|
|
dffb88e947 | ||
|
|
a1388630d0 | ||
|
|
93352dd35e | ||
|
|
ee8f691073 | ||
|
|
6355d732be | ||
|
|
71758b68f7 | ||
|
|
b3b1146fe1 | ||
|
|
55ae20654c | ||
|
|
3a5851d28a | ||
|
|
af302e19ee | ||
|
|
8d265ee368 | ||
|
|
872b38d378 | ||
|
|
affd55f84e | ||
|
|
561f29454b | ||
|
|
5763870938 | ||
|
|
f057e25ec7 | ||
|
|
aa7bad41e4 | ||
|
|
e70754f417 | ||
|
|
be61f8ab96 | ||
|
|
948dae5b63 | ||
|
|
a2e635d75c | ||
|
|
1c2a5bc342 | ||
|
|
028872261b | ||
|
|
487eb00402 | ||
|
|
832c1069f1 | ||
|
|
f69e5949e1 | ||
|
|
441a26b79c | ||
|
|
471d5ca17f | ||
|
|
536f995ab4 | ||
|
|
f7ff894df4 | ||
|
|
9050493c61 | ||
|
|
06b1fe88ca | ||
|
|
20179ba77b | ||
|
|
bb3c97828e | ||
|
|
c4d32d5418 | ||
|
|
8522fd9f27 | ||
|
|
f11ae6a162 | ||
|
|
8cfc2141cc | ||
|
|
cf83237a51 | ||
|
|
8a681450d1 | ||
|
|
ee93118688 | ||
|
|
47f9b89175 | ||
|
|
891fc55e25 | ||
|
|
988755f202 | ||
|
|
c8c22dad06 | ||
|
|
b5483a46f6 | ||
|
|
f1e23b1cd0 | ||
|
|
bac63f5204 | ||
|
|
fc1f4c494f | ||
|
|
2198445df9 | ||
|
|
04fd2d6e82 | ||
|
|
4cdc7cf3c4 | ||
|
|
fbaa1028e6 | ||
|
|
df26e19c16 | ||
|
|
756fe197c2 | ||
|
|
23ea91ebe1 | ||
|
|
ed82135d0d | ||
|
|
190cf2ddc9 | ||
|
|
2c43db9461 | ||
|
|
f85ba4a4a7 | ||
|
|
98501cf4c0 | ||
|
|
d0ac142871 | ||
|
|
d60c66ebd6 | ||
|
|
b9417a7e19 | ||
|
|
682f8ecae4 | ||
|
|
b4c049c745 | ||
|
|
bc5aeb7840 | ||
|
|
696a215dd0 | ||
|
|
b0b30f5aef | ||
|
|
a515bdae56 | ||
|
|
cc40853903 | ||
|
|
7a0e085a1f | ||
|
|
121d69faf9 | ||
|
|
0a2d7c858a | ||
|
|
0962e1e563 | ||
|
|
3863959c53 | ||
|
|
c60886fe3e | ||
|
|
c7f40dd860 | ||
|
|
832c19c1f7 | ||
|
|
25151ee191 | ||
|
|
504f5190d5 | ||
|
|
6aabdd05be | ||
|
|
87ba8b1f58 | ||
|
|
5433560f8d | ||
|
|
05ed6d9721 | ||
|
|
f74ff8f6bf | ||
|
|
41acf71013 | ||
|
|
03c004f3d8 | ||
|
|
2be33a0fca | ||
|
|
5762d80945 | ||
|
|
a72d6fcb13 | ||
|
|
4073c63cec | ||
|
|
2737fd400f | ||
|
|
e020e7598a | ||
|
|
cecea07b4d | ||
|
|
8ca3f3c53c | ||
|
|
4e617abf08 | ||
|
|
e2cba16698 | ||
|
|
49eac7368e | ||
|
|
8908ac4646 | ||
|
|
47fd704630 | ||
|
|
38d1a98193 | ||
|
|
aa848eef90 | ||
|
|
12e9cd5db1 | ||
|
|
23dddc2e04 | ||
|
|
1ea83f6349 | ||
|
|
07a5801798 | ||
|
|
db71774fc2 | ||
|
|
2b80ad2bb4 | ||
|
|
a324768b3f | ||
|
|
0973ee512e | ||
|
|
f74e492448 | ||
|
|
e567627809 | ||
|
|
56965bc0ed | ||
|
|
e43d6520c5 | ||
|
|
1123909960 | ||
|
|
bc1853c2e7 | ||
|
|
318b734f96 | ||
|
|
2734b1d54a | ||
|
|
82510c1574 | ||
|
|
0a2b02f206 | ||
|
|
41ee127de8 | ||
|
|
9ddec59ddd | ||
|
|
b72b22c628 | ||
|
|
a685f30245 | ||
|
|
173ec6f0f8 | ||
|
|
349ab5343e | ||
|
|
cf97adab7c | ||
|
|
b6fc940f18 | ||
|
|
2fb685c0fe | ||
|
|
54be5847f7 | ||
|
|
bf4f37b514 | ||
|
|
9e577e7214 | ||
|
|
69185c06c2 | ||
|
|
e561016d07 | ||
|
|
9db4dadce3 | ||
|
|
fa40d511c2 | ||
|
|
ebfb86866f | ||
|
|
be853a0657 | ||
|
|
c880342099 | ||
|
|
d09bbd2171 | ||
|
|
c1823f719a | ||
|
|
39686e3f05 | ||
|
|
482973559d | ||
|
|
600dbd72f4 | ||
|
|
785337dc5d | ||
|
|
14a35f35c3 | ||
|
|
ed2e176285 | ||
|
|
2d79280999 | ||
|
|
8b5084ab43 | ||
|
|
b19356597b | ||
|
|
0bd412edbd | ||
|
|
1a6ba25e5d | ||
|
|
26d0cd18a1 | ||
|
|
31653fe76e | ||
|
|
a6d52223d5 | ||
|
|
1bf7c4084c | ||
|
|
419a3eef53 | ||
|
|
f62531bafd | ||
|
|
dc815dad14 | ||
|
|
bde2ce9b53 | ||
|
|
041af0100c | ||
|
|
2e18c5b8cf | ||
|
|
53f0c526f7 | ||
|
|
dc5c4eced0 | ||
|
|
0d8b6d03ed | ||
|
|
cfa364280f | ||
|
|
7a293563fb | ||
|
|
9359954233 | ||
|
|
9fcc05676e | ||
|
|
1e95f5de49 | ||
|
|
f8983e9e5c | ||
|
|
aab71f03b3 | ||
|
|
447d88bf82 | ||
|
|
897e94f2f4 | ||
|
|
87936e5b52 | ||
|
|
5e02762715 | ||
|
|
0785820539 | ||
|
|
bb6d545aae | ||
|
|
4cdc94d92f | ||
|
|
c28dca6fc0 | ||
|
|
95e630201a | ||
|
|
84100be7eb | ||
|
|
0c7007ae9a | ||
|
|
3e7e3669fe | ||
|
|
1d3bb9c287 | ||
|
|
cacc624f5a | ||
|
|
04dd824f0a | ||
|
|
dc929732b1 | ||
|
|
a47fd23199 | ||
|
|
d205da0aa4 | ||
|
|
c414f12527 | ||
|
|
d9418c9fe3 | ||
|
|
65e2ba9bd0 | ||
|
|
b3f808644f | ||
|
|
1e30435525 | ||
|
|
156d25741b | ||
|
|
de3ee812cd | ||
|
|
234fb33864 | ||
|
|
c168bb5201 | ||
|
|
0ce5d774cb | ||
|
|
d2c2bbd711 | ||
|
|
88193adebb | ||
|
|
eac44f9496 | ||
|
|
6400095f1f | ||
|
|
b57267e60a | ||
|
|
79541b6ba7 | ||
|
|
0420098e94 | ||
|
|
9f80634be4 | ||
|
|
25ecb27aed | ||
|
|
2ff2efd4b2 | ||
|
|
ff7a29179d | ||
|
|
8403f8ac2a | ||
|
|
df0d4fa726 | ||
|
|
2a4bb5a11d | ||
|
|
2b6c5e42b5 | ||
|
|
a1a4765a94 | ||
|
|
64d0bc7a16 | ||
|
|
b1fb43baf5 | ||
|
|
bb309ca843 | ||
|
|
760662263f | ||
|
|
bce5205cf1 | ||
|
|
0b21726af6 | ||
|
|
04a7d256c5 | ||
|
|
8a9915b58a | ||
|
|
820e867804 | ||
|
|
699314a781 | ||
|
|
86552e62ff | ||
|
|
13769d3cdc | ||
|
|
158ae0de30 | ||
|
|
04056513d7 | ||
|
|
2b7e6dda2f | ||
|
|
b11464542a | ||
|
|
b97568f394 | ||
|
|
18e8839b8c | ||
|
|
f5e5bfae81 | ||
|
|
b27ab75e07 | ||
|
|
5799e4015f | ||
|
|
2f72ed78e1 | ||
|
|
5f3f038a6b | ||
|
|
5b29852c0a | ||
|
|
9616e43035 | ||
|
|
b918425e72 | ||
|
|
9ed5f5b6fc | ||
|
|
1721d118a8 | ||
|
|
8dc400c65a | ||
|
|
a5ac793443 | ||
|
|
8d6d995d78 | ||
|
|
4652255d4f | ||
|
|
a274f2e5ca | ||
|
|
ed4528096a | ||
|
|
f7946af404 | ||
|
|
26ead270a2 | ||
|
|
c45c784c58 | ||
|
|
6b6977cc00 | ||
|
|
41a6abd2e4 | ||
|
|
d59ccc0f34 | ||
|
|
870946d01b | ||
|
|
3bf68ef9d4 | ||
|
|
60d7d51a0a | ||
|
|
61deb2c873 | ||
|
|
0ae27d4212 | ||
|
|
3c96622313 | ||
|
|
8066ce6f49 | ||
|
|
b7f9ffc51a | ||
|
|
4a873a5ae3 | ||
|
|
c080deb0b8 | ||
|
|
8cefa8181c | ||
|
|
a34dd651b1 | ||
|
|
a86041836f | ||
|
|
6dbd760a2e | ||
|
|
4181a84e9b | ||
|
|
b4d5168409 | ||
|
|
74756c0703 | ||
|
|
dce57d6fdd | ||
|
|
d55df67642 | ||
|
|
769d9063d5 | ||
|
|
8f95a23df9 | ||
|
|
9816c33015 | ||
|
|
1d14c976f2 | ||
|
|
63c436e0ac | ||
|
|
a4700d7a9d | ||
|
|
e5a1fe0771 | ||
|
|
b101ff86a9 | ||
|
|
0c5a6044a0 | ||
|
|
6fc7c0b9ad | ||
|
|
9459e82161 | ||
|
|
62501eb3b8 | ||
|
|
df000b7508 | ||
|
|
c04bde6725 | ||
|
|
1fe8ae39cb | ||
|
|
e2049b9564 | ||
|
|
49d9836ab4 | ||
|
|
4ed38575bf | ||
|
|
ef166cd70d | ||
|
|
d45665f092 | ||
|
|
10bae6dab7 | ||
|
|
ad25c86fdd | ||
|
|
f064ff35f3 | ||
|
|
55b44b41bf | ||
|
|
1f3e9b22f4 |
@@ -19,3 +19,7 @@ indent_size = 2
|
||||
[*.mdx]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
10
.eslintignore
Normal file
10
.eslintignore
Normal file
@@ -0,0 +1,10 @@
|
||||
.tmp
|
||||
**/.git
|
||||
**/.hg
|
||||
**/.pnp.*
|
||||
**/.svn
|
||||
**/.yarn/**
|
||||
**/build
|
||||
**/dist/**
|
||||
**/node_modules
|
||||
**/temp
|
||||
38
.eslintrc.cjs
Normal file
38
.eslintrc.cjs
Normal file
@@ -0,0 +1,38 @@
|
||||
module.exports = {
|
||||
extends: ['@payloadcms'],
|
||||
overrides: [
|
||||
{
|
||||
extends: ['plugin:@typescript-eslint/disable-type-checked'],
|
||||
files: ['*.js', '*.cjs', '*.json', '*.md', '*.yml', '*.yaml'],
|
||||
},
|
||||
{
|
||||
files: ['packages/eslint-config-payload/**'],
|
||||
rules: {
|
||||
'perfectionist/sort-objects': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['package.json', 'tsconfig.json'],
|
||||
rules: {
|
||||
'perfectionist/sort-array-includes': 'off',
|
||||
'perfectionist/sort-astro-attributes': 'off',
|
||||
'perfectionist/sort-classes': 'off',
|
||||
'perfectionist/sort-enums': 'off',
|
||||
'perfectionist/sort-exports': 'off',
|
||||
'perfectionist/sort-imports': 'off',
|
||||
'perfectionist/sort-interfaces': 'off',
|
||||
'perfectionist/sort-jsx-props': 'off',
|
||||
'perfectionist/sort-keys': 'off',
|
||||
'perfectionist/sort-maps': 'off',
|
||||
'perfectionist/sort-named-exports': 'off',
|
||||
'perfectionist/sort-named-imports': 'off',
|
||||
'perfectionist/sort-object-types': 'off',
|
||||
'perfectionist/sort-objects': 'off',
|
||||
'perfectionist/sort-svelte-attributes': 'off',
|
||||
'perfectionist/sort-union-types': 'off',
|
||||
'perfectionist/sort-vue-attributes': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
root: true,
|
||||
}
|
||||
104
.eslintrc.js
104
.eslintrc.js
@@ -1,104 +0,0 @@
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
],
|
||||
extends: [
|
||||
'./eslint-config',
|
||||
],
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||
},
|
||||
},
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['test/**/int.spec.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'@typescript-eslint/consistent-type-imports': 'warn',
|
||||
'jest/prefer-strict-equal': 'off',
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['test/**/e2e.spec.ts'],
|
||||
extends: [
|
||||
'plugin:playwright/playwright-test'
|
||||
],
|
||||
rules: {
|
||||
'jest/consistent-test-it': 'off',
|
||||
'jest/require-top-level-describe': 'off',
|
||||
'jest/no-test-callback': 'off',
|
||||
'jest/prefer-strict-equal': 'off',
|
||||
'jest/expect-expect': 'off',
|
||||
'jest-dom/prefer-to-have-attribute': 'off',
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
],
|
||||
rules: {
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': ['error'],
|
||||
'import/no-unresolved': [
|
||||
2,
|
||||
{
|
||||
ignore: [
|
||||
'payload-config',
|
||||
'payload/generated-types',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.spec.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.e2e.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'jest/expect-expect': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
'import/no-extraneous-dependencies': ['error', { packageDir: './' }],
|
||||
'react/jsx-filename-extension': [2, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }],
|
||||
'import/prefer-default-export': 'off',
|
||||
'react/prop-types': 'off',
|
||||
'react/require-default-props': 'off',
|
||||
'react/no-unused-prop-types': 'off',
|
||||
'no-console': 'warn',
|
||||
'no-sparse-arrays': 'off',
|
||||
'no-underscore-dangle': 'off',
|
||||
'no-use-before-define': 'off',
|
||||
'arrow-body-style': 0,
|
||||
'@typescript-eslint/no-use-before-define': 'off',
|
||||
'import/extensions': [
|
||||
'error',
|
||||
'ignorePackages',
|
||||
{
|
||||
js: 'never',
|
||||
jsx: 'never',
|
||||
ts: 'never',
|
||||
tsx: 'never',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
18
.git-blame-ignore-revs
Normal file
18
.git-blame-ignore-revs
Normal file
@@ -0,0 +1,18 @@
|
||||
# lint and format
|
||||
ae7d6f97d205491390f15850e5104c7abded1550
|
||||
1fbda85cd04a774cb978778b0f813001664c53dd
|
||||
|
||||
# prettier all templates
|
||||
75a428ddc4672903455998eaba7ae9f9d710bf85
|
||||
|
||||
# re-run prettier and eslint everywhere again
|
||||
cdaa0acd61d3001407609915bd573b78565d5571
|
||||
|
||||
# prettier write again
|
||||
dfac7395fed95fc5d8ebca21b786ce70821942bb
|
||||
|
||||
# lint and format plugin-cloud
|
||||
fb7d1be2f3325d076b7c967b1730afcef37922c2
|
||||
|
||||
# lint and format create-payload-app
|
||||
5fd3d430001efe86515262ded5e26f00c1451181
|
||||
9
.github/ISSUE_TEMPLATE/1.bug_report.yml
vendored
9
.github/ISSUE_TEMPLATE/1.bug_report.yml
vendored
@@ -1,6 +1,6 @@
|
||||
name: Bug Report
|
||||
description: Create a bug report for Payload
|
||||
labels: ["possible-bug"]
|
||||
labels: ['possible-bug']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
@@ -10,7 +10,7 @@ body:
|
||||
id: reproduction-link
|
||||
attributes:
|
||||
label: Link to reproduction
|
||||
description: Please add a link to a reproduction. See the fork [reproduction-guide](https://github.com/payloadcms/payload/blob/master/.github/reproduction-guide.md) for more information.
|
||||
description: Please add a link to a reproduction. See the fork [reproduction-guide](https://github.com/payloadcms/payload/blob/main/.github/reproduction-guide.md) for more information.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
@@ -31,6 +31,11 @@ body:
|
||||
description: What version of Payload are you running?
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: adapters-plugins
|
||||
attributes:
|
||||
label: Adapters and Plugins
|
||||
description: What adapters and plugins are you using? ie. db-mongodb, db-postgres, bundler-webpack, etc.
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Before submitting the issue, go through the steps you've written down to make sure the steps provided are detailed and clear.
|
||||
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -2,7 +2,7 @@
|
||||
|
||||
<!-- Please include a summary of the pull request and any related issues it fixes. Please also include relevant motivation and context. -->
|
||||
|
||||
- [ ] I have read and understand the [CONTRIBUTING.md](../CONTRIBUTING.md) document in this repository.
|
||||
- [ ] I have read and understand the [CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md) document in this repository.
|
||||
|
||||
## Type of change
|
||||
|
||||
|
||||
11
.github/reproduction-guide.md
vendored
11
.github/reproduction-guide.md
vendored
@@ -9,6 +9,7 @@
|
||||
**NOTE:** The goal is to isolate the problem by reducing the number of `collections/globals/fields` you add to the `test/_community` folder. This folder is _not_ meant for you to copy your project into, but rather recreate the issue you are experiencing with minimal config.
|
||||
|
||||
## Example test directory file tree
|
||||
|
||||
```text
|
||||
.
|
||||
├── config.ts
|
||||
@@ -27,16 +28,18 @@ The directory split up in this way specifically to reduce friction when creating
|
||||
<br />
|
||||
|
||||
## Testing is optional but encouraged
|
||||
|
||||
An issue does not need to have failing tests — reproduction steps with your forked repo are enough at this point. Some people like to dive deeper and we want to give you the guidance/tools to do so. Read more below:
|
||||
|
||||
### Running integration tests (Payload API tests)
|
||||
|
||||
First install [Jest Runner for VSVode](https://marketplace.visualstudio.com/items?itemName=firsttris.vscode-jest-runner).
|
||||
|
||||
There are a couple ways run integration tests:
|
||||
|
||||
- **Granularly** - you can run individual tests in vscode by installing the Jest Runner plugin and using that to run individual tests. Clicking the `debug` button will run the test in debug mode allowing you to set break points.
|
||||
|
||||
<img src="https://raw.githubusercontent.com/payloadcms/payload/master/src/admin/assets/images/github/int-debug.png" />
|
||||
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/admin/assets/images/github/int-debug.png" />
|
||||
|
||||
- **Manually** - you can run all int tests in the `/test/_community/int.spec.ts` file by running the following command:
|
||||
|
||||
@@ -45,14 +48,16 @@ There are a couple ways run integration tests:
|
||||
```
|
||||
|
||||
### Running E2E tests (Admin Panel UI tests)
|
||||
|
||||
The easiest way to run E2E tests is to install
|
||||
|
||||
- [Playwright Test for VSCode](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright)
|
||||
- [Playwright Runner](https://marketplace.visualstudio.com/items?itemName=ortoni.ortoni)
|
||||
|
||||
Once they are installed you can open the `testing` tab in vscode sidebar and drill down to the test you want to run, i.e. `/test/_community/e2e.spec.ts`
|
||||
|
||||
<img src="https://raw.githubusercontent.com/payloadcms/payload/master/src/admin/assets/images/github/e2e-debug.png" />
|
||||
|
||||
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/packages/payload/src/admin/assets/images/github/e2e-debug.png" />
|
||||
|
||||
#### Notes
|
||||
|
||||
- It is recommended to add the test credentials (located in `test/credentials.ts`) to your autofill for `localhost:3000/admin` as this will be required on every nodemon restart. The default credentials are `dev@payloadcms.com` as email and `test` as password.
|
||||
|
||||
242
.github/workflows/main.yml
vendored
Normal file
242
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
name: build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
push:
|
||||
branches: ['main']
|
||||
|
||||
jobs:
|
||||
core-build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 25
|
||||
|
||||
- name: Use Node.js 18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ env.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
|
||||
- run: pnpm install
|
||||
- run: pnpm run build
|
||||
|
||||
- name: Cache build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
needs: core-build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
database: [mongoose, postgres]
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: payloadtests
|
||||
|
||||
steps:
|
||||
- name: Use Node.js 18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Restore build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
- name: Start PostgreSQL
|
||||
uses: CasperWA/postgresql-action@v1.2
|
||||
with:
|
||||
postgresql version: '14' # See https://hub.docker.com/_/postgres for available versions
|
||||
postgresql db: ${{ env.POSTGRES_DB }}
|
||||
postgresql user: ${{ env.POSTGRES_USER }}
|
||||
postgresql password: ${{ env.POSTGRES_PASSWORD }}
|
||||
if: matrix.database == 'postgres'
|
||||
|
||||
- run: sleep 30
|
||||
- name: Configure PostgreSQL
|
||||
run: |
|
||||
psql "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" -c "CREATE ROLE runner SUPERUSER LOGIN;"
|
||||
psql "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" -c "SELECT version();"
|
||||
echo "POSTGRES_URL=postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" >> $GITHUB_ENV
|
||||
if: matrix.database == 'postgres'
|
||||
|
||||
- name: Component Tests
|
||||
run: pnpm test:components
|
||||
|
||||
- name: Integration Tests
|
||||
run: pnpm test:int
|
||||
env:
|
||||
PAYLOAD_DATABASE: ${{ matrix.database }}
|
||||
POSTGRES_URL: ${{ env.POSTGRES_URL }}
|
||||
|
||||
tests-e2e:
|
||||
runs-on: ubuntu-latest
|
||||
needs: core-build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
part: [1/4, 2/4, 3/4, 4/4]
|
||||
|
||||
steps:
|
||||
- name: Use Node.js 18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Restore build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
- name: E2E Tests
|
||||
run: pnpm test:e2e --part ${{ matrix.part }} --bail
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: test-results
|
||||
path: test-results/
|
||||
retention-days: 1
|
||||
|
||||
tests-type-generation:
|
||||
runs-on: ubuntu-latest
|
||||
needs: core-build
|
||||
|
||||
steps:
|
||||
- name: Use Node.js 18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Restore build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
- name: Generate Payload Types
|
||||
run: pnpm dev:generate-types fields
|
||||
|
||||
- name: Generate GraphQL schema file
|
||||
run: pnpm dev:generate-graphql-schema graphql-schema-gen
|
||||
|
||||
build-packages:
|
||||
runs-on: ubuntu-latest
|
||||
needs: core-build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pkg:
|
||||
- db-mongodb
|
||||
- db-postgres
|
||||
- bundler-webpack
|
||||
- bundler-vite
|
||||
- richtext-slate
|
||||
- richtext-lexical
|
||||
- live-preview
|
||||
- live-preview-react
|
||||
|
||||
steps:
|
||||
- name: Use Node.js 18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Restore build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
- name: Build ${{ matrix.pkg }}
|
||||
run: pnpm turbo run build --filter=${{ matrix.pkg }}
|
||||
|
||||
plugins:
|
||||
runs-on: ubuntu-latest
|
||||
needs: core-build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pkg:
|
||||
- plugin-cloud
|
||||
- create-payload-app
|
||||
|
||||
steps:
|
||||
- name: Use Node.js 18
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Restore build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
|
||||
- name: Build ${{ matrix.pkg }}
|
||||
run: pnpm turbo run build --filter=${{ matrix.pkg }}
|
||||
|
||||
- name: Test ${{ matrix.pkg }}
|
||||
run: pnpm --filter ${{ matrix.pkg }} run test
|
||||
if: matrix.pkg != 'create-payload-app' # degit doesn't work within GitHub Actions
|
||||
88
.github/workflows/tests.yml
vendored
88
.github/workflows/tests.yml
vendored
@@ -1,88 +0,0 @@
|
||||
name: build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
push:
|
||||
branches: ["master"]
|
||||
|
||||
jobs:
|
||||
build_yarn:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x, 18.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org
|
||||
scope: "@payloadcms"
|
||||
always-auth: true
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: yarn
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- run: yarn build
|
||||
|
||||
- name: Component Tests
|
||||
run: yarn test:components
|
||||
- name: Integration Tests
|
||||
run: yarn test:int
|
||||
|
||||
- name: Generate Payload Types
|
||||
run: yarn dev:generate-types fields
|
||||
|
||||
- name: Generate GraphQL schema file
|
||||
run: yarn dev:generate-graphql-schema graphql-schema-gen
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright install --with-deps
|
||||
- name: E2E Tests
|
||||
run: yarn test:e2e --bail
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: test-results
|
||||
path: test-results/
|
||||
retention-days: 30
|
||||
|
||||
install_npm:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
registry-url: https://registry.npmjs.org
|
||||
scope: "@payloadcms"
|
||||
always-auth: true
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-npm-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-${{ env.cache-name }}-
|
||||
${{ runner.os }}-npm-
|
||||
${{ runner.os }}-
|
||||
- run: npm install
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
236
.gitignore
vendored
236
.gitignore
vendored
@@ -3,11 +3,15 @@ package-lock.json
|
||||
dist
|
||||
.idea
|
||||
test-results
|
||||
.devcontainer
|
||||
/migrations
|
||||
|
||||
# Created by https://www.gitignore.io/api/node,macos,windows,webstorm,sublimetext,visualstudiocode
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/node,macos,windows,webstorm,sublimetext,visualstudiocode
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=node,macos,windows,webstorm,sublimetext,visualstudiocode
|
||||
|
||||
### macOS ###
|
||||
*.DS_Store
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
@@ -30,6 +34,10 @@ Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### macOS Patch ###
|
||||
# iCloud generated files
|
||||
*.icloud
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
@@ -37,6 +45,11 @@ logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
@@ -49,11 +62,12 @@ lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
@@ -62,15 +76,18 @@ bower_components
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
@@ -78,6 +95,15 @@ typings/
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
@@ -87,34 +113,87 @@ typings/
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# Yarn Berry
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
### Node Patch ###
|
||||
# Serverless Webpack directories
|
||||
.webpack/
|
||||
|
||||
# Optional stylelint cache
|
||||
|
||||
# SvelteKit build / generate output
|
||||
.svelte-kit
|
||||
|
||||
### SublimeText ###
|
||||
# cache files for sublime text
|
||||
# Cache files for Sublime Text
|
||||
*.tmlanguage.cache
|
||||
*.tmPreferences.cache
|
||||
*.stTheme.cache
|
||||
|
||||
# workspace files are user-specific
|
||||
# Workspace files are user-specific
|
||||
*.sublime-workspace
|
||||
|
||||
# project files should be checked into the repository, unless a significant
|
||||
# proportion of contributors will probably not be using SublimeText
|
||||
# Project files should be checked into the repository, unless a significant
|
||||
# proportion of contributors will probably not be using Sublime Text
|
||||
# *.sublime-project
|
||||
|
||||
# sftp configuration file
|
||||
# SFTP configuration file
|
||||
sftp-config.json
|
||||
sftp-config-alt*.json
|
||||
|
||||
# Package control specific files
|
||||
Package Control.last-run
|
||||
@@ -134,46 +213,77 @@ GitHub.sublime-settings
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
|
||||
### WebStorm ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff:
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/dictionaries
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.xml
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle:
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# CMake
|
||||
cmake-build-debug/
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# MongoDB Explorer plugin:
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
/out/
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
@@ -184,8 +294,8 @@ atlassian-ide-plugin.xml
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Ruby plugin and RubyMine
|
||||
/.rakeTasks
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
@@ -193,6 +303,12 @@ crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### WebStorm Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
@@ -202,16 +318,43 @@ fabric.properties
|
||||
# *.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/sonarlint
|
||||
# https://plugins.jetbrains.com/plugin/7973-sonarlint
|
||||
.idea/**/sonarlint/
|
||||
|
||||
# SonarQube Plugin
|
||||
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
|
||||
.idea/**/sonarIssues.xml
|
||||
|
||||
# Markdown Navigator plugin
|
||||
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
|
||||
.idea/**/markdown-navigator.xml
|
||||
.idea/**/markdown-navigator-enh.xml
|
||||
.idea/**/markdown-navigator/
|
||||
|
||||
# Cache file creation bug
|
||||
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
||||
.idea/$CACHE_FILE$
|
||||
|
||||
# CodeStream plugin
|
||||
# https://plugins.jetbrains.com/plugin/12206-codestream
|
||||
.idea/codestream.xml
|
||||
|
||||
# Azure Toolkit for IntelliJ plugin
|
||||
# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
|
||||
.idea/**/azureSettings.xml
|
||||
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
@@ -219,26 +362,13 @@ $RECYCLE.BIN/
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# End of https://www.gitignore.io/api/node,macos,windows,webstorm,sublimetext,visualstudiocode
|
||||
# End of https://www.toptal.com/developers/gitignore/api/node,macos,windows,webstorm,sublimetext,visualstudiocode
|
||||
|
||||
# Ignore all uploads
|
||||
demo/upload
|
||||
demo/media
|
||||
demo/files
|
||||
|
||||
# Ignore build folder
|
||||
build
|
||||
|
||||
# Ignore built components
|
||||
components/index.js
|
||||
components/styles.css
|
||||
|
||||
# Ignore generated
|
||||
demo/generated-types.ts
|
||||
demo/generated-schema.graphql
|
||||
/build
|
||||
4
.husky/pre-commit
Executable file
4
.husky/pre-commit
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
pnpm run lint-staged --quiet
|
||||
@@ -1 +1 @@
|
||||
v16.14.2
|
||||
v18.17.1
|
||||
|
||||
2
.npmrc
Normal file
2
.npmrc
Normal file
@@ -0,0 +1,2 @@
|
||||
symlink=true
|
||||
node-linker=isolated # due to a typescript bug, isolated mode requires @types/express-serve-static-core, terser and monaco-editor to be installed https://github.com/microsoft/TypeScript/issues/47663#issuecomment-1519138189 along with two other changes in the code which I've marked with (tsbugisolatedmode) in the code
|
||||
11
.prettierignore
Normal file
11
.prettierignore
Normal file
@@ -0,0 +1,11 @@
|
||||
.tmp
|
||||
**/.git
|
||||
**/.hg
|
||||
**/.pnp.*
|
||||
**/.svn
|
||||
**/.yarn/**
|
||||
**/build
|
||||
**/dist/**
|
||||
**/node_modules
|
||||
**/temp
|
||||
**/docs/**
|
||||
6
.prettierrc.json
Normal file
6
.prettierrc.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100,
|
||||
"semi": false
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
"skipChecks": true
|
||||
},
|
||||
"hooks": {
|
||||
"before:init": ["yarn", "yarn clean", "yarn test"]
|
||||
"before:init": ["pnpm i", "pnpm clean", "pnpm test"]
|
||||
},
|
||||
"plugins": {
|
||||
"@release-it/conventional-changelog": {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"tag": "canary"
|
||||
},
|
||||
"hooks": {
|
||||
"before:init": ["yarn", "yarn clean", "yarn test"]
|
||||
"before:init": ["pnpm i", "pnpm clean", "pnpm test"]
|
||||
},
|
||||
"plugins": {
|
||||
"@release-it/conventional-changelog": {
|
||||
|
||||
3
.vscode/extensions.json
vendored
Normal file
3
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"]
|
||||
}
|
||||
142
.vscode/launch.json
vendored
142
.vscode/launch.json
vendored
@@ -1,22 +1,146 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "yarn run dev _community",
|
||||
"command": "pnpm run dev _community",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Community",
|
||||
"request": "launch",
|
||||
"type": "node-terminal",
|
||||
"cwd": "${workspaceFolder}"
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "yarn run dev fields",
|
||||
"command": "pnpm run dev fields",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Fields",
|
||||
"request": "launch",
|
||||
"type": "node-terminal",
|
||||
"cwd": "${workspaceFolder}"
|
||||
"type": "node-terminal"
|
||||
},
|
||||
]
|
||||
{
|
||||
"command": "pnpm run dev:postgres fields",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Postgres",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm run dev versions",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Versions",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "PAYLOAD_BUNDLER=vite pnpm run dev fields",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Fields (Vite)",
|
||||
"request": "launch",
|
||||
"type": "node-terminal",
|
||||
"env": {
|
||||
"NODE_ENV": "production"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "ts-node ./packages/payload/src/bin/index.ts build",
|
||||
"env": {
|
||||
"PAYLOAD_CONFIG_PATH": "test/fields/config.ts",
|
||||
"PAYLOAD_BUNDLER": "vite",
|
||||
"DISABLE_SWC": "true" // SWC messes up debugging the bin scripts
|
||||
},
|
||||
"name": "Build CLI - Vite",
|
||||
"outputCapture": "std",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "ts-node ./packages/payload/src/bin/index.ts build",
|
||||
"env": {
|
||||
"PAYLOAD_CONFIG_PATH": "test/fields/config.ts",
|
||||
"PAYLOAD_ANALYZE_BUNDLE": "true",
|
||||
"DISABLE_SWC": "true" // SWC messes up debugging the bin scripts
|
||||
},
|
||||
"name": "Build CLI - Webpack",
|
||||
"outputCapture": "std",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "ts-node ./packages/payload/src/bin/index.ts generate:types",
|
||||
"env": {
|
||||
"PAYLOAD_CONFIG_PATH": "test/_community/config.ts",
|
||||
"DISABLE_SWC": "true" // SWC messes up debugging the bin scripts
|
||||
},
|
||||
"name": "Generate Types CLI",
|
||||
"outputCapture": "std",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "ts-node ./packages/payload/src/bin/index.ts migrate:status",
|
||||
"env": {
|
||||
"PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts",
|
||||
"PAYLOAD_DATABASE": "postgres",
|
||||
"DISABLE_SWC": "true" // SWC messes up debugging the bin scripts
|
||||
// "PAYLOAD_DROP_DATABASE": "true",
|
||||
},
|
||||
"name": "Migrate CLI - status",
|
||||
"outputCapture": "std",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "ts-node ./packages/payload/src/bin/index.ts migrate:create yass",
|
||||
"env": {
|
||||
"PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts",
|
||||
"PAYLOAD_DATABASE": "postgres",
|
||||
"DISABLE_SWC": "true" // SWC messes up debugging the bin scripts
|
||||
// "PAYLOAD_DROP_DATABASE": "true",
|
||||
},
|
||||
"name": "Migrate CLI - create",
|
||||
"outputCapture": "std",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "ts-node ./packages/payload/src/bin/index.ts migrate:down",
|
||||
"env": {
|
||||
"PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts",
|
||||
"PAYLOAD_DATABASE": "mongoose",
|
||||
"DISABLE_SWC": "true" // SWC messes up debugging the bin scripts
|
||||
// "PAYLOAD_DROP_DATABASE": "true",
|
||||
},
|
||||
"name": "Migrate CLI - down",
|
||||
"outputCapture": "std",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "ts-node ./packages/payload/src/bin/index.ts migrate:reset",
|
||||
"env": {
|
||||
"PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts",
|
||||
"PAYLOAD_DATABASE": "mongoose",
|
||||
"DISABLE_SWC": "true" // SWC messes up debugging the bin scripts
|
||||
// "PAYLOAD_DROP_DATABASE": "true",
|
||||
},
|
||||
"name": "Migrate CLI - reset",
|
||||
"outputCapture": "std",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "ts-node ./packages/payload/src/bin/index.ts migrate:refresh",
|
||||
"env": {
|
||||
"PAYLOAD_CONFIG_PATH": "test/migrations-cli/config.ts",
|
||||
"PAYLOAD_DATABASE": "mongoose",
|
||||
"DISABLE_SWC": "true" // SWC messes up debugging the bin scripts
|
||||
// "PAYLOAD_DROP_DATABASE": "true",
|
||||
},
|
||||
"name": "Migrate CLI - refresh",
|
||||
"outputCapture": "std",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
],
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0"
|
||||
}
|
||||
|
||||
39
.vscode/settings.json
vendored
Normal file
39
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"npm.packageManager": "pnpm",
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
}
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
}
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
}
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"editor.formatOnSaveMode": "file",
|
||||
// All ESLint rules to 'warn' to differentate from TypeScript's 'error' level
|
||||
"eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }],
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
// Load .git-blame-ignore-revs file
|
||||
"gitlens.advanced.blame.customArguments": ["--ignore-revs-file", ".git-blame-ignore-revs"]
|
||||
}
|
||||
767
CHANGELOG.md
767
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,12 @@ Payload documentation can be found directly within its codebase and you can feel
|
||||
|
||||
If you're an incredibly awesome person and want to help us make Payload even better through new features or additions, we would be thrilled to work with you.
|
||||
|
||||
## Design Contributions
|
||||
|
||||
When it comes to design-related changes or additions, it's crucial for us to ensure a cohesive user experience and alignment with our broader design vision. Before embarking on any implementation that would affect the design or UI/UX, we ask that you **first share your design proposal** with us for review and approval.
|
||||
|
||||
Our design review ensures that proposed changes fit seamlessly with other components, both existing and planned. This step is meant to prevent unintentional design inconsistencies and to save you from investing time in implementing features that might need significant design alterations later.
|
||||
|
||||
### Before Starting
|
||||
|
||||
To help us work on new features, you can create a new feature request post in [GitHub Discussion](https://github.com/payloadcms/payload/discussions) or discuss it in our [Discord](https://discord.com/invite/payload). New functionality often has large implications across the entire Payload repo, so it is best to discuss the architecture and approach before starting work on a pull request.
|
||||
@@ -43,13 +49,13 @@ A typical directory with `test/` will be structured like this:
|
||||
- `config.ts` - This is the _granular_ Payload config for testing. It should be as lightweight as possible. Reference existing configs for an example
|
||||
- `int.spec.ts` - This is the test file run by jest. Any test file must have a `*int.spec.ts` suffix.
|
||||
- `e2e.spec.ts` - This is the end-to-end test file that will load up the admin UI using the above config and run Playwright tests. These tests are typically only needed if a large change is being made to the Admin UI.
|
||||
- `payload-types.ts` - Generated types from `config.ts`. Generate this file by running `yarn dev:generate-types my-test-dir`.
|
||||
- `payload-types.ts` - Generated types from `config.ts`. Generate this file by running `pnpm dev:generate-types my-test-dir`.
|
||||
|
||||
The directory split up in this way specifically to reduce friction when creating tests and to add the ability to boot up Payload with that specific config.
|
||||
|
||||
The following command will start Payload with your config: `yarn dev my-test-dir`. This command will start up Payload using your config and refresh a test database on every restart.
|
||||
The following command will start Payload with your config: `pnpm dev my-test-dir`. This command will start up Payload using your config and refresh a test database on every restart.
|
||||
|
||||
By default, it will automatically log you in with the default credentials. To disable that, you can either pass in the --no-auto-login flag (example: `yarn dev my-test-dir --no-auto-login`) or set the `PAYLOAD_PUBLIC_DISABLE_AUTO_LOGIN` environment variable to `false`.
|
||||
By default, it will automatically log you in with the default credentials. To disable that, you can either pass in the --no-auto-login flag (example: `pnpm dev my-test-dir --no-auto-login`) or set the `PAYLOAD_PUBLIC_DISABLE_AUTO_LOGIN` environment variable to `false`.
|
||||
|
||||
If you wish to use to your own Mongo database for the `test` directory instead of using the in memory database, all you need to do is add the following env vars to the `test/dev.ts` file:
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@ To report an issue, please follow the steps below:
|
||||
2. Add necessary collections/globals/fields to the `test/_community` directory to recreate the issue you are experiencing
|
||||
3. Create an issue and add a link to your forked repo
|
||||
|
||||
**The goal is to isolate the problem by reducing the number of fields/collections you add to the test/_community folder. This folder is not meant for you to copy your project into, but to recreate the issue you are experiencing with minimal config.**
|
||||
**The goal is to isolate the problem by reducing the number of fields/collections you add to the test/\_community folder. This folder is not meant for you to copy your project into, but to recreate the issue you are experiencing with minimal config.**
|
||||
|
||||
## Test directory file tree explanation
|
||||
|
||||
```text
|
||||
.
|
||||
├── config.ts
|
||||
@@ -20,45 +21,49 @@ To report an issue, please follow the steps below:
|
||||
- `config.ts` - This is the _granular_ Payload config for testing. It should be as lightweight as possible. Reference existing configs for an example
|
||||
- `int.spec.ts` [Optional] - This is the test file run by jest. Any test file must have a `*int.spec.ts` suffix.
|
||||
- `e2e.spec.ts` [Optional] - This is the end-to-end test file that will load up the admin UI using the above config and run Playwright tests.
|
||||
- `payload-types.ts` - Generated types from `config.ts`. Generate this file by running `yarn dev:generate-types _community`.
|
||||
- `payload-types.ts` - Generated types from `config.ts`. Generate this file by running `pnpm dev:generate-types _community`.
|
||||
|
||||
The directory split up in this way specifically to reduce friction when creating tests and to add the ability to boot up Payload with that specific config. You should modify the files in `test/_community` to get started.
|
||||
|
||||
## How to start test collection admin UI
|
||||
|
||||
To start the admin panel so you can manually recreate your issue, you can run the following command:
|
||||
|
||||
```bash
|
||||
# This command will start up Payload using your config
|
||||
# NOTE: it will wipe the test database on restart
|
||||
yarn dev _community
|
||||
```
|
||||
|
||||
```bash
|
||||
# This command will start up Payload using your config
|
||||
# NOTE: it will wipe the test database on restart
|
||||
pnpm dev _community
|
||||
```
|
||||
|
||||
## Testing is optional but encouraged
|
||||
|
||||
An issue does not need to have failing tests — reproduction steps with your forked repo are enough at this point. Some people like to dive deeper and we want to give you the guidance/tools to do so. Read more below.
|
||||
|
||||
### How to run integration tests (Payload API tests)
|
||||
|
||||
There are a couple ways to do this:
|
||||
|
||||
- **Granularly** - you can run individual tests in vscode by installing the Jest Runner plugin and using that to run individual tests. Clicking the `debug` button will run the test in debug mode allowing you to set break points.
|
||||
|
||||
<img src="https://raw.githubusercontent.com/payloadcms/payload/master/src/admin/assets/images/github/int-debug.png" />
|
||||
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/src/admin/assets/images/github/int-debug.png" />
|
||||
|
||||
- **Manually** - you can run all int tests in the `/test/_community/int.spec.ts` file by running the following command:
|
||||
|
||||
```bash
|
||||
yarn test:int _community
|
||||
pnpm test:int _community
|
||||
```
|
||||
|
||||
### How to run E2E tests (Admin Panel UI tests)
|
||||
|
||||
The easiest way to run E2E tests is to install
|
||||
|
||||
- [Playwright Test for VSCode](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright)
|
||||
- [Playwright Runner](https://marketplace.visualstudio.com/items?itemName=ortoni.ortoni)
|
||||
|
||||
Once they are installed you can open the `testing` tab in vscode sidebar and drill down to the test you want to run, i.e. `/test/_community/e2e.spec.ts`
|
||||
|
||||
<img src="https://raw.githubusercontent.com/payloadcms/payload/master/src/admin/assets/images/github/e2e-debug.png" />
|
||||
|
||||
<img src="https://raw.githubusercontent.com/payloadcms/payload/main/src/admin/assets/images/github/e2e-debug.png" />
|
||||
|
||||
#### Notes
|
||||
|
||||
- It is recommended to add the test credentials (located in `test/credentials.ts`) to your autofill for `localhost:3000/admin` as this will be required on every nodemon restart. The default credentials are `dev@payloadcms.com` as email and `test` as password.
|
||||
|
||||
36
README.md
36
README.md
@@ -1,11 +1,11 @@
|
||||
<a href="https://payloadcms.com">
|
||||
<img width="100%" src="src/admin/assets/images/github-banner-alt.jpg" alt="Payload headless CMS Admin panel built with React" />
|
||||
<img width="100%" src="https://github.com/payloadcms/payload/blob/main/packages/payload/src/admin/assets/images/github-banner-alt.jpg?raw=true" alt="Payload headless CMS Admin panel built with React" />
|
||||
</a>
|
||||
<br />
|
||||
<br />
|
||||
<p align="left">
|
||||
<a href="https://github.com/payloadcms/payload/actions">
|
||||
<img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/payloadcms/payload/tests.yml?style=flat-square">
|
||||
<img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/payloadcms/payload/main.yml?style=flat-square">
|
||||
</a>
|
||||
|
||||
<a href="https://discord.gg/payload">
|
||||
@@ -25,6 +25,10 @@
|
||||
<a target="_blank" href="https://payloadcms.com/docs/getting-started/what-is-payload" rel="dofollow"><strong>Explore the Docs</strong></a> · <a target="_blank" href="https://payloadcms.com/community-help" rel="dofollow"><strong>Community Help</strong></a> · <a target="_blank" href="https://demo.payloadcms.com/" rel="dofollow"><strong>Try Live Demo</strong></a> · <a target="_blank" href="https://github.com/payloadcms/payload/discussions/1539" rel="dofollow"><strong>Roadmap</strong></a> · <a target="_blank" href="https://www.g2.com/products/payload-cms/reviews#reviews" rel="dofollow"><strong>View G2 Reviews</strong></a>
|
||||
</h4>
|
||||
<hr/>
|
||||
|
||||
> [!IMPORTANT]
|
||||
> 🎉 <strong>Payload 2.0 is now available!<strong> Read more in the <a target="_blank" href="https://payloadcms.com/blog/payload-2-0" rel="dofollow"><strong>announcement post</strong></a>.
|
||||
|
||||
<h3>Benefits over a regular CMS</h3>
|
||||
<ul>
|
||||
<li>Don’t hit some third-party SaaS API, hit your own API</li>
|
||||
@@ -39,6 +43,7 @@
|
||||
</ul>
|
||||
|
||||
## ☁️ Deploy instantly with Payload Cloud.
|
||||
|
||||
Create a cloud account, connect your GitHub, and [deploy in minutes](https://payloadcms.com/new).
|
||||
|
||||
## 🚀 Get started by self-hosting completely free, forever.
|
||||
@@ -52,12 +57,21 @@ npx create-payload-app
|
||||
Alternatively, it only takes about five minutes to [create an app from scratch](https://payloadcms.com/docs/getting-started/installation#from-scratch).
|
||||
|
||||
## 🖱️ One-click templates
|
||||
### 🛒 [E-Commerce](https://github.com/payloadcms/payload/tree/master/templates/ecommerce)
|
||||
Eliminate the need to combine Shopify and a CMS, and instead do it all with Payload + Stripe. Best of all, you can extend it as much as you need.
|
||||
|
||||
[All Official Templates](https://github.com/orgs/payloadcms/repositories?q=topic%3Apayload-template) · [Community Templates](https://github.com/topics/payload-template)
|
||||
Jumpstart your next project by starting with a pre-made template. These are production-ready, end-to-end solutions designed to get you to market as fast as possible.
|
||||
|
||||
**If you maintain your own template, consider adding the `payload-template` topic to your GitHub repository for others to find.**
|
||||
### [🛒 E-Commerce](https://github.com/payloadcms/payload/tree/main/templates/ecommerce)
|
||||
|
||||
Eliminate the need to combine Shopify and a CMS, and instead do it all with Payload + Stripe. Comes with a beautiful, fully functional front-end complete with shopping cart, checkout, orders, and much more.
|
||||
|
||||
### [🌐 Website](https://github.com/payloadcms/payload/tree/main/templates/website)
|
||||
|
||||
Build any kind of website, blog, or portfolio from small to enterprise. Comes with a beautiful, fully functional front-end complete with posts, projects, comments, and much more.
|
||||
|
||||
We're constantly adding more templates to our [Templates Directory](https://github.com/payloadcms/payload/tree/main/templates). If you maintain your own template, consider adding the `payload-template` topic to your GitHub repository for others to find.
|
||||
|
||||
- [Official Templates](https://github.com/payloadcms/payload/tree/main/templates)
|
||||
- [Community Templates](https://github.com/topics/payload-template)
|
||||
|
||||
## ✨ Features
|
||||
|
||||
@@ -85,15 +99,19 @@ Eliminate the need to combine Shopify and a CMS, and instead do it all with Payl
|
||||
|
||||
Check out the [Payload website](https://payloadcms.com/docs/getting-started/what-is-payload) to find in-depth documentation for everything that Payload offers.
|
||||
|
||||
Migrating from v1 to v2? Check out the [2.0 Release Notes](https://github.com/payloadcms/payload/releases/tag/v2.0.0) on how to do it.
|
||||
|
||||
## 🙋 Contributing
|
||||
|
||||
If you want to add contributions to this repository, please follow the instructions in [contributing.md](./contributing.md).
|
||||
If you want to add contributions to this repository, please follow the instructions in [contributing.md](./CONTRIBUTING.md).
|
||||
|
||||
## 📚 Examples
|
||||
|
||||
The examples directory is a great resource for learning how to setup Payload in a variety of different ways.
|
||||
The [Examples Directory](./examples) is a great resource for learning how to setup Payload in a variety of different ways, but you can also find great examples in our blog and throughout our social media.
|
||||
|
||||
[Examples Directory](./examples)
|
||||
- [Examples Directory](./examples)
|
||||
- [Payload Blog](https://payloadcms.com/blog)
|
||||
- [Payload YouTube](https://www.youtube.com/@payloadcms)
|
||||
|
||||
## 🔌 Plugins
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
exports.Button = require('../dist/admin/components/elements/Button').default;
|
||||
exports.Card = require('../dist/admin/components/elements/Card').default;
|
||||
exports.Eyebrow = require('../dist/admin/components/elements/Eyebrow').default;
|
||||
exports.Nav = require('../dist/admin/components/elements/Nav').default;
|
||||
exports.Gutter = require('../dist/admin/components/elements/Gutter').Gutter;
|
||||
@@ -1,5 +0,0 @@
|
||||
export { default as Button } from '../dist/admin/components/elements/Button';
|
||||
export { default as Card } from '../dist/admin/components/elements/Card';
|
||||
export { default as Eyebrow } from '../dist/admin/components/elements/Eyebrow';
|
||||
export { default as Nav } from '../dist/admin/components/elements/Nav';
|
||||
export { Gutter } from '../dist/admin/components/elements/Gutter';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Array/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Blocks/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/views/collections/List/Cell/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Checkbox/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Code/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/DateTime/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Email/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Group/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/JSON/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Number/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Password/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../../dist/admin/components/forms/field-types/RadioGroup/RadioInput/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../../dist/admin/components/forms/field-types/RadioGroup/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props, Option, ValueWithRelation } from '../../dist/admin/components/forms/field-types/Relationship/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/RichText/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Row/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Select/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Text/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Textarea/types';
|
||||
@@ -1 +0,0 @@
|
||||
export type { Props } from '../../dist/admin/components/forms/field-types/Upload/types';
|
||||
@@ -1,42 +0,0 @@
|
||||
exports.useForm = require('../dist/admin/components/forms/Form/context').useForm;
|
||||
|
||||
/**
|
||||
* @deprecated useWatchForm is no longer preferred. If you need all form fields, prefer `useAllFormFields`.
|
||||
*/
|
||||
exports.useWatchForm = require('../dist/admin/components/forms/Form/context').useWatchForm;
|
||||
|
||||
exports.useFormFields = require('../dist/admin/components/forms/Form/context').useFormFields;
|
||||
|
||||
exports.useAllFormFields = require('../dist/admin/components/forms/Form/context').useAllFormFields;
|
||||
|
||||
exports.useFormSubmitted = require('../dist/admin/components/forms/Form/context').useFormSubmitted;
|
||||
|
||||
exports.useFormProcessing = require('../dist/admin/components/forms/Form/context').useFormProcessing;
|
||||
|
||||
exports.useFormModified = require('../dist/admin/components/forms/Form/context').useFormModified;
|
||||
|
||||
exports.useField = require('../dist/admin/components/forms/useField').default;
|
||||
|
||||
/**
|
||||
* @deprecated This method is now called useField. The useFieldType alias will be removed in an upcoming version.
|
||||
*/
|
||||
exports.useFieldType = require('../dist/admin/components/forms/useField').default;
|
||||
|
||||
exports.Form = require('../dist/admin/components/forms/Form').default;
|
||||
|
||||
exports.Text = require('../dist/admin/components/forms/field-types/Text').default;
|
||||
exports.TextInput = require('../dist/admin/components/forms/field-types/Text/Input').default;
|
||||
|
||||
exports.Group = require('../dist/admin/components/forms/field-types/Group').default;
|
||||
|
||||
exports.Select = require('../dist/admin/components/forms/field-types/Select').default;
|
||||
exports.SelectInput = require('../dist/admin/components/forms/field-types/Select/Input').default;
|
||||
|
||||
exports.Checkbox = require('../dist/admin/components/forms/field-types/Checkbox').default;
|
||||
exports.Submit = require('../dist/admin/components/forms/Submit').default;
|
||||
exports.Label = require('../dist/admin/components/forms/Label').default;
|
||||
|
||||
exports.reduceFieldsToValues = require('../dist/admin/components/forms/Form/reduceFieldsToValues').default;
|
||||
exports.getSiblingData = require('../dist/admin/components/forms/Form/getSiblingData').default;
|
||||
|
||||
exports.withCondition = require('../dist/admin/components/forms/withCondition').default;
|
||||
@@ -1,38 +0,0 @@
|
||||
export {
|
||||
useForm,
|
||||
/**
|
||||
* @deprecated useWatchForm is no longer preferred. If you need all form fields, prefer `useAllFormFields`.
|
||||
*/
|
||||
useWatchForm,
|
||||
useFormFields,
|
||||
useAllFormFields,
|
||||
useFormSubmitted,
|
||||
useFormProcessing,
|
||||
useFormModified,
|
||||
} from '../dist/admin/components/forms/Form/context';
|
||||
|
||||
export { default as useField } from '../dist/admin/components/forms/useField';
|
||||
|
||||
/**
|
||||
* @deprecated This method is now called useField. The useFieldType alias will be removed in an upcoming version.
|
||||
*/
|
||||
export { default as useFieldType } from '../dist/admin/components/forms/useField';
|
||||
|
||||
export { default as Form } from '../dist/admin/components/forms/Form';
|
||||
|
||||
export { default as Text } from '../dist/admin/components/forms/field-types/Text';
|
||||
export { default as TextInput } from '../dist/admin/components/forms/field-types/Text/Input';
|
||||
|
||||
export { default as Group } from '../dist/admin/components/forms/field-types/Group';
|
||||
|
||||
export { default as Select } from '../dist/admin/components/forms/field-types/Select';
|
||||
export { default as SelectInput } from '../dist/admin/components/forms/field-types/Select/Input';
|
||||
|
||||
export { default as Checkbox } from '../dist/admin/components/forms/field-types/Checkbox';
|
||||
export { default as Submit } from '../dist/admin/components/forms/Submit';
|
||||
export { default as Label } from '../dist/admin/components/forms/Label';
|
||||
|
||||
export { default as reduceFieldsToValues } from '../dist/admin/components/forms/Form/reduceFieldsToValues';
|
||||
export { default as getSiblingData } from '../dist/admin/components/forms/Form/getSiblingData';
|
||||
|
||||
export { default as withCondition } from '../dist/admin/components/forms/withCondition';
|
||||
@@ -1 +0,0 @@
|
||||
exports.useStepNav = require('../dist/admin/components/elements/StepNav').useStepNav;
|
||||
@@ -1 +0,0 @@
|
||||
export { useStepNav } from '../dist/admin/components/elements/StepNav';
|
||||
@@ -1,2 +0,0 @@
|
||||
exports.Chevron = require('../dist/admin/components/icons/Chevron').default;
|
||||
exports.X = require('../dist/admin/components/icons/X').default;
|
||||
@@ -1,2 +0,0 @@
|
||||
export { default as Chevron } from '../dist/admin/components/icons/Chevron';
|
||||
export { default as X } from '../dist/admin/components/icons/X';
|
||||
@@ -1 +0,0 @@
|
||||
export * from '../dist/admin/components';
|
||||
@@ -1 +0,0 @@
|
||||
exports.usePreferences = require('../dist/admin/components/utilities/Preferences').usePreferences;
|
||||
@@ -1 +0,0 @@
|
||||
export { usePreferences } from '../dist/admin/components/utilities/Preferences';
|
||||
@@ -1,3 +0,0 @@
|
||||
exports.LeafButton = require('../dist/admin/components/forms/field-types/RichText/leaves/Button').default;
|
||||
exports.ElementButton = require('../dist/admin/components/forms/field-types/RichText/elements/Button').default;
|
||||
exports.toggleElement = require('../dist/admin/components/forms/field-types/RichText/elements/toggle').default;
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as LeafButton } from '../dist/admin/components/forms/field-types/RichText/leaves/Button';
|
||||
export { default as ElementButton } from '../dist/admin/components/forms/field-types/RichText/elements/Button';
|
||||
export { default as toggleElement } from '../dist/admin/components/forms/field-types/RichText/elements/toggle';
|
||||
@@ -1,2 +0,0 @@
|
||||
exports.DefaultTemplate = require('../dist/admin/components/templates/Default').default;
|
||||
exports.MinimalTemplate = require('../dist/admin/components/templates/Minimal').default;
|
||||
@@ -1,2 +0,0 @@
|
||||
export { default as DefaultTemplate } from '../dist/admin/components/templates/Default';
|
||||
export { default as MinimalTemplate } from '../dist/admin/components/templates/Minimal';
|
||||
@@ -1,7 +0,0 @@
|
||||
exports.Meta = require('../dist/admin/components/utilities/Meta').default;
|
||||
exports.useLocale = require('../dist/admin/components/utilities/Locale').useLocale;
|
||||
exports.useDocumentInfo = require('../dist/admin/components/utilities/DocumentInfo').useDocumentInfo;
|
||||
exports.useConfig = require('../dist/admin/components/utilities/Config').useConfig;
|
||||
exports.useAuth = require('../dist/admin/components/utilities/Auth').useAuth;
|
||||
exports.useEditDepth = require('../dist/admin/components/utilities/EditDepth').useEditDepth;
|
||||
exports.useTheme = require('../dist/admin/components/utilities/Theme').useTheme;
|
||||
@@ -1,6 +0,0 @@
|
||||
export { default as Meta } from '../dist/admin/components/utilities/Meta';
|
||||
export { useLocale } from '../dist/admin/components/utilities/Locale';
|
||||
export { useDocumentInfo } from '../dist/admin/components/utilities/DocumentInfo';
|
||||
export { useConfig } from '../dist/admin/components/utilities/Config';
|
||||
export { useAuth } from '../dist/admin/components/utilities/Auth';
|
||||
export { useEditDepth } from '../dist/admin/components/utilities/EditDepth';
|
||||
@@ -1 +0,0 @@
|
||||
exports.Cell = require('../../dist/admin/components/views/collections/List/Cell').default;
|
||||
@@ -1,2 +0,0 @@
|
||||
export { default as Cell } from '../../dist/admin/components/views/collections/List/Cell';
|
||||
export type { Props } from '../../dist/admin/components/views/collections/List/Cell/types';
|
||||
@@ -1 +0,0 @@
|
||||
exports.Dashboard = required('../../dist/admin/components/views/Dashboard/Default').default;
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as Dashboard } from '../../dist/admin/components/views/Dashboard/Default';
|
||||
|
||||
export type { Props } from '../../dist/admin/components/views/Dashboard/types';
|
||||
@@ -1 +0,0 @@
|
||||
exports.Edit = require('../../dist/admin/components/views/collections/Edit/Default').default;
|
||||
@@ -1,2 +0,0 @@
|
||||
export { default as Edit } from '../../dist/admin/components/views/collections/Edit/Default';
|
||||
export type { Props } from '../../dist/admin/components/views/collections/Edit/types';
|
||||
@@ -1 +0,0 @@
|
||||
exports.List = require('../../dist/admin/components/views/collections/List/Default').default;
|
||||
@@ -1,2 +0,0 @@
|
||||
export { default as List } from '../../dist/admin/components/views/collections/List/Default';
|
||||
export type { Props } from '../../dist/admin/components/views/collections/List/types';
|
||||
2
config.d.ts
vendored
2
config.d.ts
vendored
@@ -1,2 +0,0 @@
|
||||
export { buildConfig } from './dist/config/build';
|
||||
export * from './dist/config/types';
|
||||
@@ -1 +0,0 @@
|
||||
exports.buildConfig = require('./dist/config/build').buildConfig;
|
||||
@@ -10,23 +10,24 @@ You can define Collection-level Access Control within each Collection's `access`
|
||||
|
||||
## Available Controls
|
||||
|
||||
| Function | Allows/Denies Access |
|
||||
| ------------------------ | -------------------- |
|
||||
| **[`create`](#create)** | Used in the `create` operation |
|
||||
| **[`read`](#read)** | Used in the `find` and `findByID` operations |
|
||||
| **[`update`](#update)** | Used in the `update` operation |
|
||||
| **[`delete`](#delete)** | Used in the `delete` operation |
|
||||
| Function | Allows/Denies Access |
|
||||
| ----------------------- | -------------------------------------------- |
|
||||
| **[`create`](#create)** | Used in the `create` operation |
|
||||
| **[`read`](#read)** | Used in the `find` and `findByID` operations |
|
||||
| **[`update`](#update)** | Used in the `update` operation |
|
||||
| **[`delete`](#delete)** | Used in the `delete` operation |
|
||||
|
||||
#### Auth-enabled Controls
|
||||
|
||||
If a Collection supports [`Authentication`](/docs/authentication/overview), the following Access Controls become available:
|
||||
|
||||
| Function | Allows/Denies Access |
|
||||
| ----------------------- | -------------------- |
|
||||
| **[`admin`](#admin)** | Used to restrict access to the Payload Admin panel |
|
||||
| Function | Allows/Denies Access |
|
||||
| ----------------------- | -------------------------------------------------------------- |
|
||||
| **[`admin`](#admin)** | Used to restrict access to the Payload Admin panel |
|
||||
| **[`unlock`](#unlock)** | Used to restrict which users can access the `unlock` operation |
|
||||
|
||||
**Example Collection config:**
|
||||
|
||||
```ts
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
|
||||
@@ -50,10 +51,10 @@ Returns a boolean which allows/denies access to the `create` request.
|
||||
|
||||
**Available argument properties:**
|
||||
|
||||
| Option | Description |
|
||||
| ---------- | ----------- |
|
||||
| Option | Description |
|
||||
| ---------- | -------------------------------------------------------------------------- |
|
||||
| **`req`** | The Express `request` object containing the currently authenticated `user` |
|
||||
| **`data`** | The data passed to create the document with. |
|
||||
| **`data`** | The data passed to create the document with. |
|
||||
|
||||
**Example:**
|
||||
|
||||
@@ -77,20 +78,20 @@ Read access functions can return a boolean result or optionally return a [query
|
||||
|
||||
**Available argument properties:**
|
||||
|
||||
| Option | Description |
|
||||
| --------- | ----------- |
|
||||
| Option | Description |
|
||||
| --------- | -------------------------------------------------------------------------- |
|
||||
| **`req`** | The Express `request` object containing the currently authenticated `user` |
|
||||
| **`id`** | `id` of document requested, if within `findByID` |
|
||||
| **`id`** | `id` of document requested, if within `findByID` |
|
||||
|
||||
**Example:**
|
||||
|
||||
```ts
|
||||
import { Access } from 'payload/config';
|
||||
import { Access } from 'payload/config'
|
||||
|
||||
const canReadPage: Access = ({ req: { user } }) => {
|
||||
// allow authenticated users
|
||||
if (user) {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
// using a query constraint, guest users can access when a field named 'isPublic' is set to true
|
||||
return {
|
||||
@@ -99,7 +100,7 @@ const canReadPage: Access = ({ req: { user } }) => {
|
||||
equals: true,
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Update
|
||||
@@ -108,25 +109,25 @@ Update access functions can return a boolean result or optionally return a [quer
|
||||
|
||||
**Available argument properties:**
|
||||
|
||||
| Option | Description |
|
||||
| ---------- | ----------- |
|
||||
| Option | Description |
|
||||
| ---------- | -------------------------------------------------------------------------- |
|
||||
| **`req`** | The Express `request` object containing the currently authenticated `user` |
|
||||
| **`id`** | `id` of document requested to update |
|
||||
| **`data`** | The data passed to update the document with |
|
||||
| **`id`** | `id` of document requested to update |
|
||||
| **`data`** | The data passed to update the document with |
|
||||
|
||||
**Example:**
|
||||
|
||||
```ts
|
||||
import { Access } from 'payload/config';
|
||||
import { Access } from 'payload/config'
|
||||
|
||||
const canUpdateUser: Access = ({ req: { user }, id }) => {
|
||||
// allow users with a role of 'admin'
|
||||
if (user.roles && user.roles.some(role => role === 'admin')) {
|
||||
return true;
|
||||
if (user.roles && user.roles.some((role) => role === 'admin')) {
|
||||
return true
|
||||
}
|
||||
// allow any other users to update only oneself
|
||||
return user.id === id;
|
||||
};
|
||||
return user.id === id
|
||||
}
|
||||
```
|
||||
|
||||
### Delete
|
||||
@@ -135,10 +136,10 @@ Similarly to the Update function, returns a boolean or a [query constraint](/doc
|
||||
|
||||
**Available argument properties:**
|
||||
|
||||
| Option | Description |
|
||||
| --------- | ----------- |
|
||||
| Option | Description |
|
||||
| --------- | --------------------------------------------------------------------------------------------------- |
|
||||
| **`req`** | The Express `request` object with additional `user` property, which is the currently logged in user |
|
||||
| **`id`** | `id` of document requested to delete |
|
||||
| **`id`** | `id` of document requested to delete |
|
||||
|
||||
**Example:**
|
||||
|
||||
@@ -148,7 +149,7 @@ import { Access } from 'payload/config'
|
||||
const canDeleteCustomer: Access = async ({ req, id }) => {
|
||||
if (!id) {
|
||||
// allow the admin UI to show controls to delete since it is indeterminate without the id
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
// query another collection using the id
|
||||
const result = await req.payload.find({
|
||||
@@ -158,10 +159,10 @@ const canDeleteCustomer: Access = async ({ req, id }) => {
|
||||
where: {
|
||||
customer: { equals: id },
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
return result.totalDocs === 0;
|
||||
};
|
||||
return result.totalDocs === 0
|
||||
}
|
||||
```
|
||||
|
||||
### Admin
|
||||
@@ -170,8 +171,8 @@ If the Collection is [used to access the Payload Admin panel](/docs/admin/overvi
|
||||
|
||||
**Available argument properties:**
|
||||
|
||||
| Option | Description |
|
||||
| --------- | ----------- |
|
||||
| Option | Description |
|
||||
| --------- | -------------------------------------------------------------------------- |
|
||||
| **`req`** | The Express `request` object containing the currently authenticated `user` |
|
||||
|
||||
### Unlock
|
||||
@@ -180,6 +181,6 @@ Determines which users can [unlock](/docs/authentication/operations#unlock) othe
|
||||
|
||||
**Available argument properties:**
|
||||
|
||||
| Option | Description |
|
||||
| --------- | ----------- |
|
||||
| Option | Description |
|
||||
| --------- | -------------------------------------------------------------------------- |
|
||||
| **`req`** | The Express `request` object containing the currently authenticated `user` |
|
||||
|
||||
@@ -10,13 +10,14 @@ Field Access Control is specified with functions inside a field's config. All fi
|
||||
|
||||
## Available Controls
|
||||
|
||||
| Function | Purpose |
|
||||
| ------------------------ | ------- |
|
||||
| **[`create`](#create)** | Allows or denies the ability to set a field's value when creating a new document |
|
||||
| **[`read`](#read)** | Allows or denies the ability to read a field's value |
|
||||
| **[`update`](#update)** | Allows or denies the ability to update a field's value |
|
||||
| Function | Purpose |
|
||||
| ----------------------- | -------------------------------------------------------------------------------- |
|
||||
| **[`create`](#create)** | Allows or denies the ability to set a field's value when creating a new document |
|
||||
| **[`read`](#read)** | Allows or denies the ability to read a field's value |
|
||||
| **[`update`](#update)** | Allows or denies the ability to update a field's value |
|
||||
|
||||
**Example Collection config:**
|
||||
|
||||
```ts
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
|
||||
@@ -44,11 +45,11 @@ Returns a boolean which allows or denies the ability to set a field's value when
|
||||
|
||||
**Available argument properties:**
|
||||
|
||||
| Option | Description |
|
||||
| ----------------- | ----------- |
|
||||
| Option | Description |
|
||||
| ----------------- | -------------------------------------------------------------------------- |
|
||||
| **`req`** | The Express `request` object containing the currently authenticated `user` |
|
||||
| **`data`** | The full data passed to create the document. |
|
||||
| **`siblingData`** | Immediately adjacent field data passed to create the document. |
|
||||
| **`data`** | The full data passed to create the document. |
|
||||
| **`siblingData`** | Immediately adjacent field data passed to create the document. |
|
||||
|
||||
### Read
|
||||
|
||||
@@ -56,12 +57,12 @@ Returns a boolean which allows or denies the ability to read a field's value. If
|
||||
|
||||
**Available argument properties:**
|
||||
|
||||
| Option | Description |
|
||||
| ----------------- | ----------- |
|
||||
| Option | Description |
|
||||
| ----------------- | -------------------------------------------------------------------------- |
|
||||
| **`req`** | The Express `request` object containing the currently authenticated `user` |
|
||||
| **`id`** | `id` of the document being read |
|
||||
| **`doc`** | The full document data. |
|
||||
| **`siblingData`** | Immediately adjacent field data of the document being read. |
|
||||
| **`id`** | `id` of the document being read |
|
||||
| **`doc`** | The full document data. |
|
||||
| **`siblingData`** | Immediately adjacent field data of the document being read. |
|
||||
|
||||
### Update
|
||||
|
||||
@@ -71,10 +72,10 @@ If `false` is returned and you attempt to update the field's value, the operatio
|
||||
|
||||
**Available argument properties:**
|
||||
|
||||
| Option | Description |
|
||||
| ----------------- | ----------- |
|
||||
| Option | Description |
|
||||
| ----------------- | -------------------------------------------------------------------------- |
|
||||
| **`req`** | The Express `request` object containing the currently authenticated `user` |
|
||||
| **`id`** | `id` of the document being updated |
|
||||
| **`data`** | The full data passed to update the document. |
|
||||
| **`siblingData`** | Immediately adjacent field data passed to update the document with. |
|
||||
| **`doc`** | The full document data, before the update is applied. |
|
||||
| **`id`** | `id` of the document being updated |
|
||||
| **`data`** | The full data passed to update the document. |
|
||||
| **`siblingData`** | Immediately adjacent field data passed to update the document with. |
|
||||
| **`doc`** | The full document data, before the update is applied. |
|
||||
|
||||
@@ -8,30 +8,35 @@ keywords: globals, access control, permissions, documentation, Content Managemen
|
||||
|
||||
You can define Global-level Access Control within each Global's `access` property. All Access Control functions accept one `args` argument.
|
||||
|
||||
**Available argument properties:
|
||||
\*\*Available argument properties:
|
||||
|
||||
## Available Controls
|
||||
|
||||
| Function | Allows/Denies Access |
|
||||
| ------------------------ | -------------------- |
|
||||
| **[`read`](#read)** | Used in the `findOne` Global operation |
|
||||
| **[`update`](#update)** | Used in the `update` Global operation |
|
||||
| Function | Allows/Denies Access |
|
||||
| ----------------------- | -------------------------------------- |
|
||||
| **[`read`](#read)** | Used in the `findOne` Global operation |
|
||||
| **[`update`](#update)** | Used in the `update` Global operation |
|
||||
|
||||
**Example Global config:**
|
||||
|
||||
```ts
|
||||
import { GlobalConfig } from 'payload/types';
|
||||
import { GlobalConfig } from 'payload/types'
|
||||
|
||||
const Header: GlobalConfig = {
|
||||
slug: "header",
|
||||
slug: 'header',
|
||||
// highlight-start
|
||||
access: {
|
||||
read: ({ req: { user } }) => { /* */ },
|
||||
update: ({ req: { user } }) => { /* */ },
|
||||
read: ({ req: { user } }) => {
|
||||
/* */
|
||||
},
|
||||
update: ({ req: { user } }) => {
|
||||
/* */
|
||||
},
|
||||
},
|
||||
// highlight-end
|
||||
};
|
||||
}
|
||||
|
||||
export default Header;
|
||||
export default Header
|
||||
```
|
||||
|
||||
### Read
|
||||
@@ -40,8 +45,8 @@ Returns a boolean result or optionally a [query constraint](/docs/queries/overvi
|
||||
|
||||
**Available argument properties:**
|
||||
|
||||
| Option | Description |
|
||||
| --------- | ----------- |
|
||||
| Option | Description |
|
||||
| --------- | -------------------------------------------------------------------------- |
|
||||
| **`req`** | The Express `request` object containing the currently authenticated `user` |
|
||||
|
||||
### Update
|
||||
@@ -50,7 +55,7 @@ Returns a boolean result or optionally a [query constraint](/docs/queries/overvi
|
||||
|
||||
**Available argument properties:**
|
||||
|
||||
| Option | Description |
|
||||
| ---------- | ----------- |
|
||||
| Option | Description |
|
||||
| ---------- | -------------------------------------------------------------------------- |
|
||||
| **`req`** | The Express `request` object containing the currently authenticated `user` |
|
||||
| **`data`** | The data passed to update the global with. |
|
||||
| **`data`** | The data passed to update the global with. |
|
||||
|
||||
@@ -8,10 +8,7 @@ keywords: overview, access control, permissions, documentation, Content Manageme
|
||||
|
||||
Access control within Payload is extremely powerful while remaining easy and intuitive to manage. Declaring who should have access to what documents is no more complex than writing a simple JavaScript function that either returns a `boolean` or a [`query`](/docs/queries/overview) constraint to restrict which documents users can interact with.
|
||||
|
||||
<YouTube
|
||||
id="DoPLyXG26Dg"
|
||||
title="Overview of Payload Access Control"
|
||||
/>
|
||||
<YouTube id="DoPLyXG26Dg" title="Overview of Payload Access Control" />
|
||||
|
||||
**Example use cases:**
|
||||
|
||||
@@ -32,13 +29,18 @@ Access control within Payload is extremely powerful while remaining easy and int
|
||||
const defaultPayloadAccess = ({ req: { user } }) => {
|
||||
// Return `true` if a user is found
|
||||
// and `false` if it is undefined or null
|
||||
return Boolean(user);
|
||||
return Boolean(user)
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
<strong>Note:</strong><br/>
|
||||
In the Local API, all Access Control functions are skipped by default, allowing your server to do whatever it needs. But, you can opt back in by setting the option <strong>overrideAccess</strong> to <strong>false</strong>.
|
||||
<strong>Note:</strong>
|
||||
<br />
|
||||
In the Local API, all Access Control functions are skipped by default, allowing your server to do
|
||||
whatever it needs. But, you can opt back in by setting the option <strong>
|
||||
overrideAccess
|
||||
</strong>{' '}
|
||||
to <strong>false</strong>.
|
||||
</Banner>
|
||||
|
||||
### Access Control Types
|
||||
@@ -49,12 +51,13 @@ You can manage access within Payload on three different levels:
|
||||
- [Fields](/docs/access-control/fields)
|
||||
- [Globals](/docs/access-control/globals)
|
||||
|
||||
|
||||
### When Access Control is Executed
|
||||
|
||||
<Banner type="success">
|
||||
<strong>Note:</strong><br/>
|
||||
Access control functions are utilized in two places. It's important to understand how and when your access control is executed.
|
||||
<strong>Note:</strong>
|
||||
<br />
|
||||
Access control functions are utilized in two places. It's important to understand how and when
|
||||
your access control is executed.
|
||||
</Banner>
|
||||
|
||||
#### As you execute operations
|
||||
@@ -70,8 +73,11 @@ To accomplish this, Payload ships with an `Access` operation, which is executed
|
||||
### Argument Availability
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Important:</strong><br/>
|
||||
When your access control functions are executed via the <strong>access</strong> operation, the <strong>id</strong> and <strong>data</strong> arguments will be <strong>undefined</strong>, because Payload is executing your functions without referencing a specific document.
|
||||
<strong>Important:</strong>
|
||||
<br />
|
||||
When your access control functions are executed via the <strong>access</strong> operation, the{' '}
|
||||
<strong>id</strong> and <strong>data</strong> arguments will be <strong>undefined</strong>,
|
||||
because Payload is executing your functions without referencing a specific document.
|
||||
</Banner>
|
||||
|
||||
If you use `id` or `data` within your access control functions, make sure to check that they are defined first. If they are not, then you can assume that your access control is being executed via the `access` operation, to determine solely what the user can do within the Admin UI.
|
||||
|
||||
54
docs/admin/bundlers.mdx
Normal file
54
docs/admin/bundlers.mdx
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Bundlers
|
||||
label: Bundlers
|
||||
order: 60
|
||||
desc: Bundlers are used to bundle the code that serves Payload's Admin Panel.
|
||||
---
|
||||
|
||||
Payload has two official bundlers, the [Webpack Bundler](/docs/admin/webpack) and the [Vite Bundler](/docs/admin/vite). You must install a bundler to use the admin panel.
|
||||
|
||||
##### Install a bundler
|
||||
|
||||
Webpack (recommended):
|
||||
|
||||
```text
|
||||
yarn add @payloadcms/bundler-webpack
|
||||
```
|
||||
|
||||
Vite (beta):
|
||||
|
||||
```text
|
||||
yarn add @payloadcms/bundler-vite
|
||||
```
|
||||
|
||||
##### Configure the bundler
|
||||
|
||||
```ts
|
||||
// payload.config.ts
|
||||
|
||||
import { buildConfig } from 'payload/config'
|
||||
import { webpackBundler } from '@payloadcms/bundler-webpack'
|
||||
// import { viteBundler } from '@payloadcms/bundler-vite'
|
||||
|
||||
export default buildConfig({
|
||||
// highlight-start
|
||||
admin: {
|
||||
bundler: webpackBundler() // or viteBundler()
|
||||
},
|
||||
// highlight-end
|
||||
})
|
||||
```
|
||||
|
||||
### What are bundlers?
|
||||
|
||||
At their core, a bundler's main goal is to take a bunch of files and turn them into a few optimized files that you ship to the browser. The admin UI has a root `index.html` entry point, and from there the bundler traverses the dependency tree, bundling all of the files that are required from that point on.
|
||||
|
||||
Since the bundled file is sent to the browser, it can't include any server-only code. You will need to remove any server-only code from your admin UI before bundling it. You can learn more about [excluding server code](/docs/admin/excluding-server-code) section.
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Using environment variables in the admin UI</strong>
|
||||
<br />
|
||||
Bundles should not contain sensitive information. By default, Payload
|
||||
excludes env variables from the bundle. If you need to use env variables in your payload config,
|
||||
you need to prefix them with `PAYLOAD_PUBLIC_` to make them available to the client-side code.
|
||||
</Banner>
|
||||
@@ -6,13 +6,15 @@ desc: Fully customize your Admin Panel by swapping in your own React components.
|
||||
keywords: admin, components, custom, documentation, Content Management System, cms, headless, javascript, node, react, express
|
||||
---
|
||||
|
||||
While designing the Payload Admin panel, we determined it should be as minimal and straightforward as possible to allow easy customization and control. There are many times where you may want to completely control how a whole view or a field works. You might even want to add in your own routes entirely. In order for Payload to support that level of customization without introducing versioning / future-proofing issues, Payload provides for a pattern to supply your own React components via your Payload config.
|
||||
While designing the Payload Admin panel, we determined it should be as minimal and straightforward as possible to allow easy customization and control. There are many times where you may want to completely control how a whole view or a field works. You might even want to add in new views entirely. In order for Payload to support this level of customization without introducing versioning / future-proofing issues, Payload provides for a pattern to supply your own React components via your Payload config.
|
||||
|
||||
To swap in your own React component, first, consult the list of available component overrides below. Determine the scope that corresponds to what you are trying to accomplish, and then author your React component accordingly.
|
||||
|
||||
<Banner type="success">
|
||||
<strong>Tip:</strong><br />
|
||||
Custom components will automatically be provided with all props that the default component would accept.
|
||||
<strong>Tip:</strong>
|
||||
<br />
|
||||
Custom components will automatically be provided with all props that the default component normally
|
||||
accepts.
|
||||
</Banner>
|
||||
|
||||
### Base Component Overrides
|
||||
@@ -21,27 +23,26 @@ You can override a set of admin panel-wide components by providing a component t
|
||||
|
||||
| Path | Description |
|
||||
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`Nav`** | Contains the sidebar and mobile Nav in its entirety. |
|
||||
| **`logout.Button`** | A custom React component. |
|
||||
| **`BeforeDashboard`** | Array of components to inject into the built-in Dashboard, _before_ the default dashboard contents. |
|
||||
| **`AfterDashboard`** | Array of components to inject into the built-in Dashboard, _after_ the default dashboard contents. [Demo](https://github.com/payloadcms/payload/tree/master/test/admin/components/AfterDashboard/index.tsx) |
|
||||
| **`BeforeLogin`** | Array of components to inject into the built-in Login, _before_ the default login form. |
|
||||
| **`AfterLogin`** | Array of components to inject into the built-in Login, _after_ the default login form. |
|
||||
| **`Nav`** | Contains the sidebar / mobile menu in its entirety. |
|
||||
| **`BeforeNavLinks`** | Array of components to inject into the built-in Nav, _before_ the links themselves. |
|
||||
| **`AfterNavLinks`** | Array of components to inject into the built-in Nav, _after_ the links. |
|
||||
| **`views.Account`** | The Account view is used to show the currently logged in user's Account page. |
|
||||
| **`views.Dashboard`** | The main landing page of the Admin panel. |
|
||||
| **`BeforeDashboard`** | Array of components to inject into the built-in Dashboard, _before_ the default dashboard contents. |
|
||||
| **`AfterDashboard`** | Array of components to inject into the built-in Dashboard, _after_ the default dashboard contents. [Demo](https://github.com/payloadcms/payload/tree/main/test/admin/components/AfterDashboard/index.tsx) |
|
||||
| **`BeforeLogin`** | Array of components to inject into the built-in Login, _before_ the default login form. |
|
||||
| **`AfterLogin`** | Array of components to inject into the built-in Login, _after_ the default login form. |
|
||||
| **`logout.Button`** | A custom React component. |
|
||||
| **`graphics.Icon`** | Used as a graphic within the `Nav` component. Often represents a condensed version of a full logo. |
|
||||
| **`graphics.Logo`** | The full logo to be used in contexts like the `Login` view. |
|
||||
| **`routes`** | Define your own routes to add to the Payload Admin UI. [More](#custom-routes) |
|
||||
| **`providers`** | Define your own provider components that will wrap the Payload Admin UI. [More](#custom-providers) |
|
||||
| **`views`** | Override or create new views within the Payload Admin UI. [More](#views) |
|
||||
|
||||
#### Full example:
|
||||
Here is a full example showing how to swap some of these components for your own.
|
||||
|
||||
`payload.config.js`
|
||||
|
||||
```ts
|
||||
import { buildConfig } from "payload/config";
|
||||
import { buildConfig } from 'payload/config'
|
||||
|
||||
import {
|
||||
MyCustomNav,
|
||||
MyCustomLogo,
|
||||
@@ -49,7 +50,7 @@ import {
|
||||
MyCustomAccount,
|
||||
MyCustomDashboard,
|
||||
MyProvider,
|
||||
} from "./customComponents";
|
||||
} from './customComponents'
|
||||
|
||||
export default buildConfig({
|
||||
admin: {
|
||||
@@ -66,47 +67,105 @@ export default buildConfig({
|
||||
providers: [MyProvider],
|
||||
},
|
||||
},
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
#### Views
|
||||
|
||||
You can easily swap entire views with your own by using the `admin.components.views` property. At the root level, Payload renders the following views dy default, all of which can be overridden:
|
||||
|
||||
| Property | Description |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`Account`** | The Account view is used to show the currently logged in user's Account page. |
|
||||
| **`Dashboard`** | The main landing page of the Admin panel. |
|
||||
|
||||
To swap out any of these views, simply pass in your custom component to the `admin.components.views` property of your Payload config. For example:
|
||||
|
||||
```ts
|
||||
// payload.config.ts
|
||||
{
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
Account: MyCustomAccountView,
|
||||
Dashboard: MyCustomDashboardView,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
For more granular control, pass a configuration object instead. Payload exposes all of the properties of `<Route />` component in [React Router v5](https://v5.reactrouter.com):
|
||||
|
||||
| Property | Description |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`Component`** \* | Pass in the component that should be rendered when a user navigates to this route. |
|
||||
| **`path`** \* | React Router `path`. [See the React Router docs](https://v5.reactrouter.com/web/api/Route/path-string-string) for more info. |
|
||||
| **`exact`** | React Router `exact` property. [More](https://v5.reactrouter.com/web/api/Route/exact-bool) |
|
||||
| **`strict`** | React Router `strict` property. [More](https://v5.reactrouter.com/web/api/Route/strict-bool) |
|
||||
| **`sensitive`** | React Router `sensitive` property. [More](https://v5.reactrouter.com/web/api/Route/sensitive-bool) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
#### Adding new views
|
||||
|
||||
To add a _new_ view to the Admin Panel, simply add another key to the `views` object with at least a `path` and `Component` property. For example:
|
||||
|
||||
```ts
|
||||
// payload.config.ts
|
||||
{
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
MyCustomView: {
|
||||
Component: MyCustomView,
|
||||
path: '/my-custom-view',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
_For more examples regarding how to customize components, look at the following [examples](https://github.com/payloadcms/payload/tree/master/test/admin/components)._
|
||||
|
||||
For help on how to build your own custom view components, see [building a custom view component](#building-a-custom-view-component).
|
||||
|
||||
### Collections
|
||||
|
||||
You can override components on a Collection-by-Collection basis via each Collection's `admin` property.
|
||||
You can override components on a collection-by-collection basis via their `admin` property.
|
||||
|
||||
| Path | Description |
|
||||
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`views.Edit`** | Used while a document within this Collection is being edited. |
|
||||
| **`views.List`** | The `List` view is used to render a paginated, filterable table of Documents in this Collection. |
|
||||
| **`BeforeList`** | Array of components to inject _before_ the built-in List view |
|
||||
| **`BeforeListTable`** | Array of components to inject _before_ the built-in List view's table |
|
||||
| **`AfterList`** | Array of components to inject _after_ the built-in List view |
|
||||
| **`AfterListTable`** | Array of components to inject _after_ the built-in List view's table |
|
||||
| **`edit.SaveButton`** | Replace the default `Save` button with a custom component. Drafts must be disabled |
|
||||
| **`edit.SaveDraftButton`** | Replace the default `Save Draft` button with a custom component. Drafts must be enabled and autosave must be disabled. |
|
||||
| **`edit.PublishButton`** | Replace the default `Publish` button with a custom component. Drafts must be enabled. |
|
||||
| **`edit.PreviewButton`** | Replace the default `Preview` button with a custom component. |
|
||||
| **`BeforeList`** | Array of components to inject _before_ the built-in List view |
|
||||
| **`BeforeListTable`** | Array of components to inject _before_ the built-in List view's table |
|
||||
| **`AfterListTable`** | Array of components to inject _after_ the built-in List view's table |
|
||||
| **`AfterList`** | Array of components to inject _after_ the built-in List view |
|
||||
| **`views`** | Override or create new views within the Payload Admin UI. [More](#collection-views) |
|
||||
|
||||
#### Examples
|
||||
Here is a full example showing how to swap some of these components for your own:
|
||||
|
||||
`Collection.ts`
|
||||
|
||||
```tsx
|
||||
// Custom Buttons
|
||||
import * as React from 'react'
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
CustomSaveButtonProps,
|
||||
CustomSaveDraftButtonProps,
|
||||
CustomPublishButtonProps,
|
||||
CustomPreviewButtonProps,
|
||||
} from "payload/types";
|
||||
} from 'payload/types'
|
||||
|
||||
export const CustomSaveButton: CustomSaveButtonProps = ({
|
||||
DefaultButton,
|
||||
label,
|
||||
}) => {
|
||||
return <DefaultButton label={label} />;
|
||||
};
|
||||
export const CustomSaveButton: CustomSaveButtonProps = ({ DefaultButton, label }) => {
|
||||
return <DefaultButton label={label} />
|
||||
}
|
||||
|
||||
export const CustomSaveDraftButton: CustomSaveDraftButtonProps = ({
|
||||
DefaultButton,
|
||||
@@ -114,10 +173,8 @@ export const CustomSaveDraftButton: CustomSaveDraftButtonProps = ({
|
||||
label,
|
||||
saveDraft,
|
||||
}) => {
|
||||
return (
|
||||
<DefaultButton label={label} disabled={disabled} saveDraft={saveDraft} />
|
||||
);
|
||||
};
|
||||
return <DefaultButton label={label} disabled={disabled} saveDraft={saveDraft} />
|
||||
}
|
||||
|
||||
export const CustomPublishButton: CustomPublishButtonProps = ({
|
||||
DefaultButton,
|
||||
@@ -125,8 +182,8 @@ export const CustomPublishButton: CustomPublishButtonProps = ({
|
||||
label,
|
||||
publish,
|
||||
}) => {
|
||||
return <DefaultButton label={label} disabled={disabled} publish={publish} />;
|
||||
};
|
||||
return <DefaultButton label={label} disabled={disabled} publish={publish} />
|
||||
}
|
||||
|
||||
export const CustomPreviewButton: CustomPreviewButtonProps = ({
|
||||
DefaultButton,
|
||||
@@ -134,58 +191,220 @@ export const CustomPreviewButton: CustomPreviewButtonProps = ({
|
||||
label,
|
||||
preview,
|
||||
}) => {
|
||||
return <DefaultButton label={label} disabled={disabled} preview={preview} />;
|
||||
};
|
||||
return <DefaultButton label={label} disabled={disabled} preview={preview} />
|
||||
}
|
||||
|
||||
export const MyCollection: SanitizedCollectionConfig = {
|
||||
slug: 'my-collection',
|
||||
admin: {
|
||||
components: {
|
||||
edit: {
|
||||
SaveButton: CustomSaveButton,
|
||||
SaveDraftButton: CustomSaveDraftButton,
|
||||
PublishButton: CustomPublishButton,
|
||||
PreviewButton: CustomPreviewButton,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### Custom Collection List View Example
|
||||
#### Collection views
|
||||
|
||||
Collection.ts
|
||||
To swap out entire views on collections, you can use the `admin.components.views` property on the collection's config. Payload renders the following views dy default, all of which can be overridden:
|
||||
|
||||
```tsx
|
||||
import { MyListComponent } from './MyListComponent';
|
||||
export const MyCollection: CollectionConfig = {
|
||||
slug: 'mycollection',
|
||||
| Property | Description |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`Edit`** | The Edit view is used to edit a single document for a given collection. |
|
||||
| **`List`** | The List view is used to show a list of documents for a given collection. |
|
||||
|
||||
To swap out any of these views, simply pass in your custom component to the `admin.components.views` property of your Payload config. This will replace the entire view, including the page breadcrumbs, title, tabs, etc, _as well as all nested routes_.
|
||||
|
||||
```ts
|
||||
// Collection.ts
|
||||
{
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
List: MyListComponent,
|
||||
Edit: MyCustomEditView,
|
||||
List: MyCustomListView,
|
||||
},
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
...
|
||||
],
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
MyListComponent.tsx
|
||||
_For help on how to build your own custom view components, see [building a custom view component](#building-a-custom-view-component)._
|
||||
|
||||
```tsx
|
||||
import React from "react";
|
||||
import { List, type Props } from "payload/components/views/List"; // Payload's default List view component and its props
|
||||
export const MyListComponent: React.FC<Props> = (props) => (
|
||||
<div>
|
||||
<p>
|
||||
Some text before the default list view component. If you just want to do
|
||||
that, you can also use the admin.components.list.BeforeList hook
|
||||
</p>
|
||||
<List {...props} />
|
||||
</div>
|
||||
);
|
||||
To swap specific _nested_ views within the parent `Edit` view, you can use the `admin.components.views.Edit` property on the globals's config. This will only replace the nested view, leaving the page breadcrumbs, title, tabs, etc intact.
|
||||
|
||||
```ts
|
||||
// Collection.ts
|
||||
{
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
Edit: {
|
||||
Default: MyCustomDefaultTab,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
You can also add _new_ tabs to the `Edit` view by adding another key to the `components.views.Edit[key]` object with a `path` and `Component` property. See [Custom Tabs](#custom-tabs) for more information.
|
||||
|
||||
### Globals
|
||||
|
||||
As with Collections, You can override components on a global-by-global basis via their `admin` property.
|
||||
As with Collections, you can override components on a global-by-global basis via their `admin` property.
|
||||
|
||||
| Path | Description |
|
||||
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`views.Edit`** | Used while this Global is being edited. |
|
||||
| **`edit.SaveButton`** | Replace the default `Save` button with a custom component. Drafts must be disabled |
|
||||
| **`edit.SaveDraftButton`** | Replace the default `Save Draft` button with a custom component. Drafts must be enabled and autosave must be disabled. |
|
||||
| **`edit.PublishButton`** | Replace the default `Publish` button with a custom component. Drafts must be enabled. |
|
||||
| **`edit.PreviewButton`** | Replace the default `Preview` button with a custom component. |
|
||||
| **`views`** | Override or create new views within the Payload Admin UI. [More](#global-views) |
|
||||
|
||||
#### Global views
|
||||
|
||||
To swap out views for globals, you can use the `admin.components.views` property on the global's config. Payload renders the following views dy default, all of which can be overridden:
|
||||
|
||||
| Property | Description |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`Edit`** | The Edit view is used to edit a single document for a given Global. |
|
||||
|
||||
To swap out any of these views, simply pass in your custom component to the `admin.components.views` property of your Payload config. This will replace the entire view, including the page breadcrumbs, title, and tabs, _as well as all nested views_.
|
||||
|
||||
```ts
|
||||
// Global.ts
|
||||
{
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
Edit: MyCustomEditView,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
_For help on how to build your own custom view components, see [building a custom view component](#building-a-custom-view-component)._
|
||||
|
||||
To swap specific _nested_ views within the parent `Edit` view, you can use the `admin.components.views.Edit` property on the globals's config. This will only replace the nested view, leaving the page breadcrumbs, title, and tabs intact.
|
||||
|
||||
```ts
|
||||
// Global.ts
|
||||
{
|
||||
// ...
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
Edit: {
|
||||
Default: MyCustomDefaultTab,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
You can also add _new_ tabs to the `Edit` view by adding another key to the `components.views.Edit[key]` object with a `path` and `Component` property. See [Custom Tabs](#custom-tabs) for more information.
|
||||
|
||||
### Custom Tabs
|
||||
|
||||
You can easily swap individual collection or global edit views. To do this, pass an _object_ to the `admin.components.views.Edit` property of the config. Payload renders the following views dy default, all of which can be overridden:
|
||||
|
||||
| Property | Description |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`Default`** | The Default view is the primary view in which your document is edited. |
|
||||
| **`Versions`** | The Versions view is used to view the version history of a single document. [More details](../versions) |
|
||||
| **`Version`** | The Version view is used to view a single version of a single document for a given collection. [More details](../versions). |
|
||||
| **`API`** | The API view is used to display the REST API JSON response for a given document. |
|
||||
| **`LivePreview`** | The LivePreview view is used to display the Live Preview interface. [More details](../live-preview) |
|
||||
|
||||
Here is an example:
|
||||
|
||||
```ts
|
||||
// Collection.ts or Global.ts
|
||||
export const MyCollection: SanitizedCollectionConfig = {
|
||||
slug: 'my-collection',
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
Edit: { // You can also define `components.views.Edit` as a component, this will override _all_ nested views
|
||||
Default: MyCustomDefaultTab,
|
||||
Versions: MyCustomVersionsTab,
|
||||
Version: MyCustomVersionTab,
|
||||
API: MyCustomAPITab,
|
||||
LivePreview: MyCustomLivePreviewTab,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
To add a _new_ tab to the `Edit` view, simply add another key to `components.views.Edit[key]` with at least a `path` and `Component` property. For example:
|
||||
|
||||
```ts
|
||||
// `Collection.ts` or `Global.ts`
|
||||
export const MyCollection: SanitizedCollectionConfig = {
|
||||
slug: 'my-collection',
|
||||
admin: {
|
||||
components: {
|
||||
views: {
|
||||
Edit: {
|
||||
MyCustomTab: {
|
||||
Component: MyCustomTab,
|
||||
path: '/my-custom-tab',
|
||||
// You an swap the entire tab component out for your own
|
||||
Tab: MyCustomTab
|
||||
},
|
||||
AnotherCustomView: {
|
||||
Component: AnotherCustomView,
|
||||
path: '/another-custom-view',
|
||||
// Or you can use the default tab component and just pass in your own label and href
|
||||
Tab: {
|
||||
label: 'Another Custom View',
|
||||
href: '/another-custom-view',
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Building a custom view component
|
||||
|
||||
Your custom view components will be given all the props that a React Router `<Route />` typically would receive, as well as two props from Payload:
|
||||
|
||||
| Prop | Description |
|
||||
| ----------------------- | ---------------------------------------------------------------------------- |
|
||||
| **`user`** | The currently logged in user. Will be `null` if no user is logged in. |
|
||||
| **`canAccessAdmin`** \* | If the currently logged in user is allowed to access the admin panel or not. |
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Note:</strong>
|
||||
<br />
|
||||
It's up to you to secure your custom views. If your view requires a user to be logged in or to
|
||||
have certain access rights, you should handle that within your view component yourself.
|
||||
</Banner>
|
||||
|
||||
#### Example
|
||||
|
||||
You can find examples of custom views in the [Payload source code `/test/admin/components/views` folder](https://github.com/payloadcms/payload/tree/master/test/admin/components/views). There, you'll find two custom views:
|
||||
|
||||
1. A custom view that uses the `DefaultTemplate`, which is the built-in Payload template that displays the sidebar and "eyebrow nav"
|
||||
1. A custom view that uses the `MinimalTemplate` - which is just a centered template used for things like logging in or out
|
||||
|
||||
To see how to pass in your custom views to create custom views of your own, take a look at the `admin.components.views` property of the [Payload test admin config](https://github.com/payloadcms/payload/blob/master/test/admin/config.ts).
|
||||
|
||||
### Fields
|
||||
|
||||
@@ -194,10 +413,9 @@ All Payload fields support the ability to swap in your own React components. So,
|
||||
<Banner type="success">
|
||||
<strong>Tip:</strong>
|
||||
<br />
|
||||
Don't see a built-in field type that you need? Build it! Using a combination
|
||||
of custom validation and custom components, you can override the entirety of
|
||||
how a component functions within the admin panel and effectively create your
|
||||
own field type.
|
||||
Don't see a built-in field type that you need? Build it! Using a combination of custom validation
|
||||
and custom components, you can override the entirety of how a component functions within the admin
|
||||
panel and effectively create your own field type.
|
||||
</Banner>
|
||||
|
||||
**Fields support the following custom components:**
|
||||
@@ -223,15 +441,15 @@ These are the props that will be passed to your custom Cell to use in your own c
|
||||
#### Example
|
||||
|
||||
```tsx
|
||||
import React from "react";
|
||||
import "./index.scss";
|
||||
const baseClass = "custom-cell";
|
||||
import React from 'react'
|
||||
import './index.scss'
|
||||
const baseClass = 'custom-cell'
|
||||
|
||||
const CustomCell: React.FC<Props> = (props) => {
|
||||
const { field, colIndex, collection, cellData, rowData } = props;
|
||||
const { field, colIndex, collection, cellData, rowData } = props
|
||||
|
||||
return <span className={baseClass}>{cellData}</span>;
|
||||
};
|
||||
return <span className={baseClass}>{cellData}</span>
|
||||
}
|
||||
```
|
||||
|
||||
## Field Component
|
||||
@@ -243,76 +461,31 @@ When writing your own custom components you can make use of a number of hooks to
|
||||
When swapping out the `Field` component, you'll be responsible for sending and receiving the field's `value` from the form itself. To do so, import the `useField` hook as follows:
|
||||
|
||||
```tsx
|
||||
import { useField } from "payload/components/forms";
|
||||
import { useField } from 'payload/components/forms'
|
||||
|
||||
type Props = { path: string };
|
||||
type Props = { path: string }
|
||||
|
||||
const CustomTextField: React.FC<Props> = ({ path }) => {
|
||||
// highlight-start
|
||||
const { value, setValue } = useField<Props>({ path });
|
||||
const { value, setValue } = useField<Props>({ path })
|
||||
// highlight-end
|
||||
|
||||
return (
|
||||
<input onChange={(e) => setValue(e.target.value)} value={value.path} />
|
||||
);
|
||||
};
|
||||
return <input onChange={(e) => setValue(e.target.value)} value={value.path} />
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
For more information regarding the hooks that are available to you while you
|
||||
build custom components, including the <strong>useField</strong> hook, [click
|
||||
here](/docs/admin/hooks).
|
||||
For more information regarding the hooks that are available to you while you build custom
|
||||
components, including the <strong>useField</strong> hook, [click here](/docs/admin/hooks).
|
||||
</Banner>
|
||||
|
||||
## Custom routes
|
||||
|
||||
You can easily add your own custom routes to the Payload Admin panel using the `admin.components.routes` property. Payload currently uses the extremely powerful React Router v5.x and custom routes support all the properties of the React Router `<Route />` component.
|
||||
|
||||
**Custom routes support the following properties:**
|
||||
|
||||
| Property | Description |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`Component`** \* | Pass in the component that should be rendered when a user navigates to this route. |
|
||||
| **`path`** \* | React Router `path`. [See the React Router docs](https://v5.reactrouter.com/web/api/Route/path-string-string) for more info. |
|
||||
| **`exact`** | React Router `exact` property. [More](https://v5.reactrouter.com/web/api/Route/exact-bool) |
|
||||
| **`strict`** | React Router `strict` property. [More](https://v5.reactrouter.com/web/api/Route/strict-bool) |
|
||||
| **`sensitive`** | React Router `sensitive` property. [More](https://v5.reactrouter.com/web/api/Route/sensitive-bool) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
#### Custom route components
|
||||
|
||||
Your custom route components will be given all the props that a React Router `<Route />` typically would receive, as well as two props from Payload:
|
||||
|
||||
| Prop | Description |
|
||||
| ----------------------- | ---------------------------------------------------------------------------- |
|
||||
| **`user`** | The currently logged in user. Will be `null` if no user is logged in. |
|
||||
| **`canAccessAdmin`** \* | If the currently logged in user is allowed to access the admin panel or not. |
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Note:</strong>
|
||||
<br />
|
||||
It's up to you to secure your custom routes. If your route requires a user to
|
||||
be logged in or to have certain access rights, you should handle that within
|
||||
your route component yourself.
|
||||
</Banner>
|
||||
|
||||
#### Example
|
||||
|
||||
You can find examples of custom route views in the [Payload source code `/test/admin/components/views` folder](https://github.com/payloadcms/payload/tree/master/test/admin/components/views). There, you'll find two custom routes:
|
||||
|
||||
1. A custom view that uses the `DefaultTemplate`, which is the built-in Payload template that displays the sidebar and "eyebrow nav"
|
||||
1. A custom view that uses the `MinimalTemplate` - which is just a centered template used for things like logging in or out
|
||||
|
||||
To see how to pass in your custom views to create custom routes of your own, take a look at the `admin.components.routes` property of the [Payload test admin config](https://github.com/payloadcms/payload/blob/master/test/admin/config.ts).
|
||||
|
||||
## Custom providers
|
||||
|
||||
As your admin customizations gets more complex you may want to share state between fields or other components. You can add custom providers to do add your own context to any Payload app for use in other custom components within the admin panel. Within your config add `admin.components.providers`, these can be used to share context or provide other custom functionality. Read the [React context](https://reactjs.org/docs/context.html) docs to learn more.
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Reminder:</strong> Don't forget to pass the **children** prop through
|
||||
the provider component for the admin UI to show
|
||||
<strong>Reminder:</strong> Don't forget to pass the **children** prop through the provider
|
||||
component for the admin UI to show
|
||||
</Banner>
|
||||
|
||||
### Styling Custom Components
|
||||
@@ -332,40 +505,40 @@ When developing custom components you can support multiple languages to be consi
|
||||
For example:
|
||||
|
||||
```tsx
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
const CustomComponent: React.FC = () => {
|
||||
// highlight-start
|
||||
const { t, i18n } = useTranslation("namespace1");
|
||||
const { t, i18n } = useTranslation('namespace1')
|
||||
// highlight-end
|
||||
|
||||
return (
|
||||
<ul>
|
||||
<li>{t("key", { variable: "value" })}</li>
|
||||
<li>{t("namespace2:key", { variable: "value" })}</li>
|
||||
<li>{t('key', { variable: 'value' })}</li>
|
||||
<li>{t('namespace2:key', { variable: 'value' })}</li>
|
||||
<li>{i18n.language}</li>
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Getting the current locale
|
||||
|
||||
In any custom component you can get the selected locale with the `useLocale` hook. Here is a simple example:
|
||||
In any custom component you can get the selected locale with `useLocale` hook. `useLocale` returns the full locale object, consisting of a `label`, `rtl`(right-to-left) property, and then `code`. Here is a simple example:
|
||||
|
||||
```tsx
|
||||
import { useLocale } from "payload/components/utilities";
|
||||
import { useLocale } from 'payload/components/utilities'
|
||||
|
||||
const Greeting: React.FC = () => {
|
||||
// highlight-start
|
||||
const locale = useLocale();
|
||||
const locale = useLocale()
|
||||
// highlight-end
|
||||
|
||||
const trans = {
|
||||
en: "Hello",
|
||||
es: "Hola",
|
||||
};
|
||||
en: 'Hello',
|
||||
es: 'Hola',
|
||||
}
|
||||
|
||||
return <span> {trans[locale]} </span>;
|
||||
};
|
||||
return <span> {trans[locale.code]} </span>
|
||||
}
|
||||
```
|
||||
|
||||
@@ -13,15 +13,16 @@ You can add your own CSS by providing your base Payload config with a path to yo
|
||||
To do so, provide your base Payload config with a path to your own stylesheet. It can be either a CSS or SCSS file.
|
||||
|
||||
**Example in payload.config.js:**
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload/config';
|
||||
import path from 'path';
|
||||
import { buildConfig } from 'payload/config'
|
||||
import path from 'path'
|
||||
|
||||
const config = buildConfig({
|
||||
admin: {
|
||||
css: path.resolve(__dirname, 'relative/path/to/stylesheet.scss'),
|
||||
},
|
||||
});
|
||||
admin: {
|
||||
css: path.resolve(__dirname, 'relative/path/to/stylesheet.scss'),
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### Overriding built-in styles
|
||||
@@ -30,7 +31,7 @@ To make it as easy as possible for you to override our styles, Payload uses [BEM
|
||||
|
||||
In addition to adding your own style definitions, you can also override Payload's built-in CSS variables. We use as much as possible behind the scenes, and you can override any of them that you'd like to.
|
||||
|
||||
You can find the built-in Payload CSS variables within [`./src/admin/scss/app.scss`](https://github.com/payloadcms/payload/blob/master/src/admin/scss/app.scss) and [`./src/admin/scss/colors.scss`](https://github.com/payloadcms/payload/blob/master/src/admin/scss/colors.scss). The following variables are defined and can be overridden:
|
||||
You can find the built-in Payload CSS variables within [`./src/admin/scss/app.scss`](https://github.com/payloadcms/payload/blob/main/packages/payload/src/admin/scss/app.scss) and [`./src/admin/scss/colors.scss`](https://github.com/payloadcms/payload/blob/main/packages/payload/src/admin/scss/colors.scss). The following variables are defined and can be overridden:
|
||||
|
||||
- Breakpoints
|
||||
- Base color shades (white to black by default)
|
||||
@@ -43,7 +44,8 @@ You can find the built-in Payload CSS variables within [`./src/admin/scss/app.sc
|
||||
#### Dark mode
|
||||
|
||||
<Banner type="warning">
|
||||
If you're overriding colors or theme elevations, make sure to consider how your changes will affect dark mode.
|
||||
If you're overriding colors or theme elevations, make sure to consider how your changes will
|
||||
affect dark mode.
|
||||
</Banner>
|
||||
|
||||
By default, Payload automatically overrides all `--theme-elevation`s and inverts all success / warning / error shades to suit dark mode. We also update some base theme variables like `--theme-bg`, `--theme-text`, etc.
|
||||
|
||||
27
docs/admin/environment-vars.mdx
Normal file
27
docs/admin/environment-vars.mdx
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
title: Environment Variables in Admin UI
|
||||
label: Environment Variables
|
||||
order: 100
|
||||
desc: NEEDS TO BE WRITTEN
|
||||
---
|
||||
|
||||
## Admin environment vars
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Important:</strong>
|
||||
<br />
|
||||
Be careful about what variables you provide to your client-side code. Analyze every single one to
|
||||
make sure that you're not accidentally leaking anything that an attacker could exploit. Only keys
|
||||
that are safe for anyone to read in plain text should be provided to your Admin panel.
|
||||
</Banner>
|
||||
|
||||
By default, `env` variables are **not** provided to the Admin panel for security and safety reasons.
|
||||
But, Payload provides you with a way to still provide `env` vars to your frontend code.
|
||||
|
||||
**Payload will automatically supply any present `env` variables that are prefixed with `PAYLOAD_PUBLIC_` directly to the Admin panel.**
|
||||
|
||||
For example, if you've got the following environment variable:
|
||||
|
||||
`PAYLOAD_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_XXXXXXXXXXXXXXXXXX`
|
||||
|
||||
This key will automatically be made available to the Payload bundle and can be referenced in your Admin component code as `process.env.PAYLOAD_PUBLIC_STRIPE_PUBLISHABLE_KEY`.
|
||||
131
docs/admin/excluding-server-code.mdx
Normal file
131
docs/admin/excluding-server-code.mdx
Normal file
@@ -0,0 +1,131 @@
|
||||
---
|
||||
title: Excluding server-only code from admin UI
|
||||
label: Excluding server code
|
||||
order: 70
|
||||
desc: Learn how to exclude server-only code from the Payload Admin UI bundle
|
||||
---
|
||||
|
||||
Because the Admin Panel browser bundle includes your Payload Config file, files using server-only modules need to be excluded.
|
||||
It's common for your config to rely on server only modules to perform logic in access control functions, hooks, and other contexts.
|
||||
|
||||
Any file that imports a server-only module such as `fs`, `stripe`, `authorizenet`, `nodemailer`, etc. **cannot** be included in the browser bundle.
|
||||
|
||||
#### Example Scenario
|
||||
|
||||
Say we have a collection called `Subscriptions` that has a `beforeChange` hook that creates a Stripe subscription whenever a Subscription document is created in Payload.
|
||||
|
||||
**Collection config**:
|
||||
|
||||
```ts
|
||||
// collections/Subscriptions/index.ts
|
||||
|
||||
import { CollectionConfig } from 'payload/types'
|
||||
import createStripeSubscription from './hooks/createStripeSubscription'
|
||||
|
||||
export const Subscription: CollectionConfig = {
|
||||
slug: 'subscriptions',
|
||||
hooks: {
|
||||
beforeChange: [createStripeSubscription],
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'stripeSubscriptionID',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
**Collection hook**:
|
||||
|
||||
```ts
|
||||
// collections/Subscriptions/hooks/createStripeSubscription.ts
|
||||
|
||||
// highlight-start
|
||||
import Stripe from 'stripe' // <-- server-only module
|
||||
// highlight-end
|
||||
|
||||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY)
|
||||
|
||||
export const createStripeSubscription = async ({ data, operation }) => {
|
||||
if (operation === 'create') {
|
||||
const dataWithStripeID = { ...data }
|
||||
|
||||
// use Stripe to create a Stripe subscription
|
||||
const subscription = await stripe.subscriptions.create({
|
||||
// Configure the subscription accordingly
|
||||
})
|
||||
|
||||
// Automatically add the Stripe subscription ID
|
||||
// to the data that will be saved to this Subscription doc
|
||||
dataWithStripeID.stripeSubscriptionID = subscription.id
|
||||
|
||||
return dataWithStripeID
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="error">
|
||||
<strong>Warning:</strong>
|
||||
<br />
|
||||
The above code is NOT production-ready and should not be referenced to create Stripe
|
||||
subscriptions. Although creating a beforeChange hook is a completely valid spot to do things like
|
||||
create subscriptions, the code above is incomplete and insecure, meant for explanation purposes
|
||||
only.
|
||||
</Banner>
|
||||
|
||||
**As-is, this collection will prevent your Admin panel from bundling or loading correctly, because Stripe relies on some Node-only packages.**
|
||||
|
||||
#### How to fix this
|
||||
|
||||
You need to make sure that you use `alias`es to tell your bundler to import "safe" files vs. attempting to import any server-side code that you need to get rid of. Depending on your bundler (Webpack, Vite, etc.) the steps involved may be slightly different.
|
||||
|
||||
The basic idea is to create a file that exports an empty object, and then alias import paths of any files that import server-only modules to that empty object file.
|
||||
|
||||
This way when your bundler goes to import a file that contains server-only modules, it will instead import the empty object file, which will not break the browser bundle.
|
||||
|
||||
### Aliasing server-only modules
|
||||
|
||||
To remove files that contain server-only modules from your bundle, you can use an `alias`.
|
||||
|
||||
First create new file that exports an empty object:
|
||||
```js
|
||||
// mocks/emptyObject.js
|
||||
|
||||
export default {}
|
||||
```
|
||||
|
||||
Then, in your Payload config, you can alias the file containing the server-only module to the mock module. For example, here's how you'd do this in Webpack:
|
||||
|
||||
```ts
|
||||
// payload.config.ts
|
||||
|
||||
import { buildConfig } from 'payload/config'
|
||||
import { webpackBundler } from '@payloadcms/bundler-webpack'
|
||||
|
||||
const mockModulePath = path.resolve(__dirname, 'mocks/emptyObject.js')
|
||||
const pathToFileWithServerOnlyModule = path.resolve(__dirname, 'hooks/syncStripeCustomer.ts')
|
||||
|
||||
export default buildConfig({
|
||||
admin: {
|
||||
bundler: webpackBundler(),
|
||||
webpack: (config) => {
|
||||
return {
|
||||
...config,
|
||||
resolve: {
|
||||
...config.resolve,
|
||||
// highlight-start
|
||||
alias: {
|
||||
...config.resolve.alias,
|
||||
[pathToFileWithServerOnlyModule]: mockModulePath,
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
@@ -24,7 +24,7 @@ const CustomTextField: React.FC<Props> = ({ path }) => {
|
||||
const { value, setValue } = useField<string>({ path })
|
||||
// highlight-end
|
||||
|
||||
return <input onChange={e => setValue(e.target.value)} value={value.path} />
|
||||
return <input onChange={(e) => setValue(e.target.value)} value={value.path} />
|
||||
}
|
||||
```
|
||||
|
||||
@@ -57,7 +57,8 @@ const {
|
||||
There are times when a custom field component needs to have access to data from other fields, and you have a few options to do so. The `useFormFields` hook is a powerful and highly performant way to retrieve a form's field state, as well as to retrieve the `dispatchFields` method, which can be helpful for setting other fields' form states from anywhere within a form.
|
||||
|
||||
<Banner type="success">
|
||||
<strong>This hook is great for retrieving only certain fields from form state</strong> because it ensures that it will only cause a rerender when the items that you ask for change.
|
||||
<strong>This hook is great for retrieving only certain fields from form state</strong> because it
|
||||
ensures that it will only cause a rerender when the items that you ask for change.
|
||||
</Banner>
|
||||
|
||||
Thanks to the awesome package [`use-context-selector`](https://github.com/dai-shi/use-context-selector), you can retrieve a specific field's state easily. This is ideal because you can ensure you have an up-to-date field state, and your component will only re-render when _that field's state_ changes.
|
||||
@@ -65,21 +66,19 @@ Thanks to the awesome package [`use-context-selector`](https://github.com/dai-sh
|
||||
You can pass a Redux-like selector into the hook, which will ensure that you retrieve only the field that you want. The selector takes an argument with type of `[fields: Fields, dispatch: React.Dispatch<Action>]]`.
|
||||
|
||||
```tsx
|
||||
import { useFormFields } from 'payload/components/forms';
|
||||
import { useFormFields } from 'payload/components/forms'
|
||||
|
||||
const MyComponent: React.FC = () => {
|
||||
// Get only the `amount` field state, and only cause a rerender when that field changes
|
||||
const amount = useFormFields(([fields, dispatch]) => fields.amount);
|
||||
const amount = useFormFields(([fields, dispatch]) => fields.amount)
|
||||
|
||||
// Do the same thing as above, but to the `feePercentage` field
|
||||
const feePercentage = useFormFields(([fields, dispatch]) => fields.feePercentage);
|
||||
const feePercentage = useFormFields(([fields, dispatch]) => fields.feePercentage)
|
||||
|
||||
if (typeof amount?.value !== 'undefined' && typeof feePercentage?.value !== 'undefined') {
|
||||
return (
|
||||
<span>The fee is ${(amount.value * feePercentage.value) / 100}</span>
|
||||
);
|
||||
return <span>The fee is ${(amount.value * feePercentage.value) / 100}</span>
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### useAllFormFields
|
||||
@@ -117,7 +116,7 @@ If you are building a custom component, then you should use `setValue` which is
|
||||
You can send the following actions to the `dispatchFields` function.
|
||||
|
||||
| Action | Description |
|
||||
|------------------------|----------------------------------------------------------------------------|
|
||||
| ---------------------- | -------------------------------------------------------------------------- |
|
||||
| **`ADD_ROW`** | Adds a row of data (useful in array / block field data) |
|
||||
| **`DUPLICATE_ROW`** | Duplicates a row of data (useful in array / block field data) |
|
||||
| **`MODIFY_CONDITION`** | Updates a field's conditional logic result (true / false) |
|
||||
@@ -127,15 +126,19 @@ You can send the following actions to the `dispatchFields` function.
|
||||
| **`REPLACE_STATE`** | Completely replaces form state |
|
||||
| **`UPDATE`** | Update any property of a specific field's state |
|
||||
|
||||
To see types for each action supported within the `dispatchFields` hook, check out the Form types [here](https://github.com/payloadcms/payload/blob/master/src/admin/components/forms/Form/types.ts).
|
||||
To see types for each action supported within the `dispatchFields` hook, check out the Form types [here](https://github.com/payloadcms/payload/blob/main/packages/payload/src/admin/components/forms/Form/types.ts).
|
||||
|
||||
### useForm
|
||||
|
||||
The `useForm` hook can be used to interact with the form itself, and sends back many methods that can be used to reactively fetch form state without causing rerenders within your components each time a field is changed. This is useful if you have action-based callbacks that your components fire, and need to interact with form state _based on a user action_.
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Warning:</strong><br/>
|
||||
This hook is optimized to avoid causing rerenders when fields change, and as such, its `fields` property will be out of date. You should only leverage this hook if you need to perform actions against the form in response to your users' actions. Do not rely on its returned "fields" as being up-to-date. They will be removed from this hook's response in an upcoming version.
|
||||
<strong>Warning:</strong>
|
||||
<br />
|
||||
This hook is optimized to avoid causing rerenders when fields change, and as such, its `fields`
|
||||
property will be out of date. You should only leverage this hook if you need to perform actions
|
||||
against the form in response to your users' actions. Do not rely on its returned "fields" as being
|
||||
up-to-date. They will be removed from this hook's response in an upcoming version.
|
||||
</Banner>
|
||||
|
||||
The `useForm` hook returns an object with the following properties: |
|
||||
@@ -344,7 +347,7 @@ The `useForm` hook returns an object with the following properties: |
|
||||
value: <strong><code>rowIndex</code></strong>,
|
||||
},
|
||||
{
|
||||
value: "The index of the row to add",
|
||||
value: "The index of the row to add. If omitted, the row will be added to the end of the array.",
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -358,10 +361,14 @@ The `useForm` hook returns an object with the following properties: |
|
||||
]}
|
||||
/>
|
||||
|
||||
<br />
|
||||
{' '}
|
||||
|
||||
<pre>
|
||||
{`import { useForm } from "payload/components/forms";
|
||||
<br />
|
||||
|
||||
{' '}
|
||||
|
||||
<pre>
|
||||
{`import { useForm } from "payload/components/forms";
|
||||
|
||||
export const CustomArrayManager = () => {
|
||||
const { addFieldRow } = useForm()
|
||||
@@ -385,7 +392,7 @@ export const CustomArrayManager = () => {
|
||||
</button>
|
||||
)
|
||||
}`}
|
||||
</pre>
|
||||
</pre>
|
||||
|
||||
<p>An example config to go along with the custom component</p>
|
||||
<pre>
|
||||
@@ -456,10 +463,14 @@ export const CustomArrayManager = () => {
|
||||
]}
|
||||
/>
|
||||
|
||||
<br />
|
||||
{' '}
|
||||
|
||||
<pre>
|
||||
{`import { useForm } from "payload/components/forms";
|
||||
<br />
|
||||
|
||||
{' '}
|
||||
|
||||
<pre>
|
||||
{`import { useForm } from "payload/components/forms";
|
||||
|
||||
export const CustomArrayManager = () => {
|
||||
const { removeFieldRow } = useForm()
|
||||
@@ -478,7 +489,7 @@ export const CustomArrayManager = () => {
|
||||
</button>
|
||||
)
|
||||
}`}
|
||||
</pre>
|
||||
</pre>
|
||||
|
||||
<p>An example config to go along with the custom component</p>
|
||||
<pre>
|
||||
@@ -557,10 +568,14 @@ export const CustomArrayManager = () => {
|
||||
]}
|
||||
/>
|
||||
|
||||
<br />
|
||||
{' '}
|
||||
|
||||
<pre>
|
||||
{`import { useForm } from "payload/components/forms";
|
||||
<br />
|
||||
|
||||
{' '}
|
||||
|
||||
<pre>
|
||||
{`import { useForm } from "payload/components/forms";
|
||||
|
||||
export const CustomArrayManager = () => {
|
||||
const { replaceFieldRow } = useForm()
|
||||
@@ -584,7 +599,7 @@ export const CustomArrayManager = () => {
|
||||
</button>
|
||||
)
|
||||
}`}
|
||||
</pre>
|
||||
</pre>
|
||||
|
||||
<p>An example config to go along with the custom component</p>
|
||||
<pre>
|
||||
@@ -625,7 +640,7 @@ export const CustomArrayManager = () => {
|
||||
The `useDocumentInfo` hook provides lots of information about the document currently being edited, including the following:
|
||||
|
||||
| Property | Description |
|
||||
|---------------------------|--------------------------------------------------------------------------------------------------------------------| |
|
||||
|---------------------------|--------------------------------------------------------------------------------------------------------------------|
|
||||
| **`collection`** | If the doc is a collection, its collection config will be returned |
|
||||
| **`global`** | If the doc is a global, its global config will be returned |
|
||||
| **`id`** | If the doc is a collection, its ID will be returned |
|
||||
@@ -640,47 +655,45 @@ The `useDocumentInfo` hook provides lots of information about the document curre
|
||||
**Example:**
|
||||
|
||||
```tsx
|
||||
import { useDocumentInfo } from 'payload/components/utilities';
|
||||
import { useDocumentInfo } from 'payload/components/utilities'
|
||||
|
||||
const LinkFromCategoryToPosts: React.FC = () => {
|
||||
// highlight-start
|
||||
const { id } = useDocumentInfo();
|
||||
const { id } = useDocumentInfo()
|
||||
// highlight-end
|
||||
|
||||
// id will be undefined on the create form
|
||||
if (!id) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<a href={`/admin/collections/posts?where[or][0][and][0][category][in][0]=[${id}]`} >
|
||||
<a href={`/admin/collections/posts?where[or][0][and][0][category][in][0]=[${id}]`}>
|
||||
View posts
|
||||
</a>
|
||||
)
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### useLocale
|
||||
|
||||
In any custom component you can get the selected locale with the `useLocale` hook. Here is a simple example:
|
||||
In any custom component you can get the selected locale object with the `useLocale` hook. `useLocale`gives you the full locale object, consisting of a `label`, `rtl`(right-to-left) property, and then `code`. Here is a simple example:
|
||||
|
||||
```tsx
|
||||
import { useLocale } from 'payload/components/utilities';
|
||||
import { useLocale } from 'payload/components/utilities'
|
||||
|
||||
const Greeting: React.FC = () => {
|
||||
// highlight-start
|
||||
const locale = useLocale();
|
||||
const locale = useLocale()
|
||||
// highlight-end
|
||||
|
||||
const trans = {
|
||||
en: 'Hello',
|
||||
es: 'Hola',
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<span> { trans[locale] } </span>
|
||||
);
|
||||
};
|
||||
return <span> {trans[locale.code]} </span>
|
||||
}
|
||||
```
|
||||
|
||||
### useAuth
|
||||
@@ -688,7 +701,7 @@ const Greeting: React.FC = () => {
|
||||
Useful to retrieve info about the currently logged in user as well as methods for interacting with it. It sends back an object with the following properties:
|
||||
|
||||
| Property | Description |
|
||||
|--------------------------|-----------------------------------------------------------------------------------------|
|
||||
| ------------------------ | --------------------------------------------------------------------------------------- |
|
||||
| **`user`** | The currently logged in user |
|
||||
| **`logOut`** | A method to log out the currently logged in user |
|
||||
| **`refreshCookie`** | A method to trigger the silent refreshing of a user's auth token |
|
||||
@@ -698,18 +711,16 @@ Useful to retrieve info about the currently logged in user as well as methods fo
|
||||
| **`permissions`** | The permissions of the current user |
|
||||
|
||||
```tsx
|
||||
import { useAuth } from 'payload/components/utilities';
|
||||
import { User } from '../payload-types.ts';
|
||||
import { useAuth } from 'payload/components/utilities'
|
||||
import { User } from '../payload-types.ts'
|
||||
|
||||
const Greeting: React.FC = () => {
|
||||
// highlight-start
|
||||
const { user } = useAuth<User>();
|
||||
const { user } = useAuth<User>()
|
||||
// highlight-end
|
||||
|
||||
return (
|
||||
<span>Hi, {user.email}!</span>
|
||||
);
|
||||
};
|
||||
return <span>Hi, {user.email}!</span>
|
||||
}
|
||||
```
|
||||
|
||||
### useConfig
|
||||
@@ -717,17 +728,15 @@ const Greeting: React.FC = () => {
|
||||
Used to easily fetch the full Payload config.
|
||||
|
||||
```tsx
|
||||
import { useConfig } from 'payload/components/utilities';
|
||||
import { useConfig } from 'payload/components/utilities'
|
||||
|
||||
const MyComponent: React.FC = () => {
|
||||
// highlight-start
|
||||
const config = useConfig();
|
||||
const config = useConfig()
|
||||
// highlight-end
|
||||
|
||||
return (
|
||||
<span>{config.serverURL}</span>
|
||||
);
|
||||
};
|
||||
return <span>{config.serverURL}</span>
|
||||
}
|
||||
```
|
||||
|
||||
### useEditDepth
|
||||
@@ -735,16 +744,14 @@ const MyComponent: React.FC = () => {
|
||||
Sends back how many editing levels "deep" the current component is. Edit depth is relevant while adding new documents / editing documents in modal windows and other cases.
|
||||
|
||||
```tsx
|
||||
import { useEditDepth } from 'payload/components/utilities';
|
||||
import { useEditDepth } from 'payload/components/utilities'
|
||||
|
||||
const MyComponent: React.FC = () => {
|
||||
// highlight-start
|
||||
const editDepth = useEditDepth();
|
||||
const editDepth = useEditDepth()
|
||||
// highlight-end
|
||||
|
||||
return (
|
||||
<span>My component is {editDepth} levels deep</span>
|
||||
)
|
||||
return <span>My component is {editDepth} levels deep</span>
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -8,38 +8,45 @@ keywords: admin, components, custom, customize, documentation, Content Managemen
|
||||
|
||||
Payload dynamically generates a beautiful, fully functional React admin panel to manage your data. It's extremely powerful and can be customized / extended upon easily by swapping in your own React components. You can add additional views, modify how built-in views look / work, swap out Payload branding for your client's, build your own field types and much more.
|
||||
|
||||
The Payload Admin panel is built with Webpack, code-split, highly performant (even with 100+ fields), and written fully in TypeScript.
|
||||
The Payload Admin panel can be bundled with our officially supported [Vite](/docs/admin/vite) and [webpack](/docs/admin/webpack) bundlers or you can integrate another bundler following our adapter pattern approach.
|
||||
When bundled, it is code-split, highly performant (even with 100+ fields), and written fully in TypeScript.
|
||||
|
||||
<Banner type="success">
|
||||
The Admin panel is meant to be simple enough to give you a starting point but
|
||||
not bring too much complexity, so that you can easily customize it to suit the
|
||||
needs of your application and your editors.
|
||||
The Admin panel is meant to be simple enough to give you a starting point but not bring too much
|
||||
complexity, so that you can easily customize it to suit the needs of your application and your
|
||||
editors.
|
||||
</Banner>
|
||||
|
||||

|
||||
|
||||
_Screenshot of the Admin panel while editing a document from an example `AllFields` collection_
|
||||
<LightDarkImage
|
||||
srcLight="https://payloadcms.com/images/docs/admin.jpg"
|
||||
srcDark="https://payloadcms.com/images/docs/admin-dark.jpg"
|
||||
alt="Admin panel with collapsible sidebar"
|
||||
caption="Redesigned admin panel with a collapsible sidebar that's open by default, providing greater extensibility and enhanced horizontal real estate."
|
||||
/>
|
||||
|
||||
## Admin Options
|
||||
|
||||
All options for the Admin panel are defined in your base Payload config file.
|
||||
|
||||
| Option | Description |
|
||||
|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `user` | The `slug` of a Collection that you want be used to log in to the Admin dashboard. [More](/docs/admin/overview#the-admin-user-collection) |
|
||||
| `buildPath` | Specify an absolute path for where to store the built Admin panel bundle used in production. Defaults to `path.resolve(process.cwd(), 'build')`. |
|
||||
| `meta` | Base meta data to use for the Admin panel. Included properties are `titleSuffix`, `ogImage`, and `favicon`. |
|
||||
| `disable` | If set to `true`, the entire Admin panel will be disabled. |
|
||||
| `indexHTML` | Optionally replace the entirety of the `index.html` file used by the Admin panel. Reference the [base index.html file](https://github.com/payloadcms/payload/blob/master/src/admin/index.html) to ensure your replacement has the appropriate HTML elements. |
|
||||
| `css` | Absolute path to a stylesheet that you can use to override / customize the Admin panel styling. [More](/docs/admin/customizing-css). |
|
||||
| `scss` | Absolute path to a Sass variables / mixins stylesheet meant to override Payload styles to make for an easy re-skinning of the Admin panel. [More](/docs/admin/customizing-css#overriding-scss-variables). |
|
||||
| `dateFormat` | Global date format that will be used for all dates in the Admin panel. Any valid [date-fns](https://date-fns.org/) format pattern can be used. |
|
||||
| `avatar` | Set account profile picture. Options: `gravatar`, `default` or a custom React component. |
|
||||
| `autoLogin` | Used to automate admin log-in for dev and demonstration convenience. [More](/docs/authentication/config). |
|
||||
| `components` | Component overrides that affect the entirety of the Admin panel. [More](/docs/admin/components) |
|
||||
| `webpack` | Customize the Webpack config that's used to generate the Admin panel. [More](/docs/admin/webpack) |
|
||||
| **`logoutRoute`** | The route for the `logout` page. |
|
||||
| **`inactivityRoute`** | The route for the `logout` inactivity page. |
|
||||
| Option | Description |
|
||||
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `bundler` | The bundler that you would like to use to bundle the admin panel. Officially supported bundlers: [Webpack](/docs/admin/webpack) and [Vite](/docs/admin/vite). |
|
||||
| `user` | The `slug` of a Collection that you want be used to log in to the Admin dashboard. [More](/docs/admin/overview#the-admin-user-collection) |
|
||||
| `buildPath` | Specify an absolute path for where to store the built Admin panel bundle used in production. Defaults to `path.resolve(process.cwd(), 'build')`. |
|
||||
| `meta` | Base meta data to use for the Admin panel. Included properties are `titleSuffix`, `ogImage`, and `favicon`. |
|
||||
| `disable` | If set to `true`, the entire Admin panel will be disabled. |
|
||||
| `indexHTML` | Optionally replace the entirety of the `index.html` file used by the Admin panel. Reference the [base index.html file](https://github.com/payloadcms/payload/blob/main/packages/payload/src/admin/index.html) to ensure your replacement has the appropriate HTML elements. |
|
||||
| `css` | Absolute path to a stylesheet that you can use to override / customize the Admin panel styling. [More](/docs/admin/customizing-css). |
|
||||
| `scss` | Absolute path to a Sass variables / mixins stylesheet meant to override Payload styles to make for an easy re-skinning of the Admin panel. [More](/docs/admin/customizing-css#overriding-scss-variables). |
|
||||
| `dateFormat` | Global date format that will be used for all dates in the Admin panel. Any valid [date-fns](https://date-fns.org/) format pattern can be used. |
|
||||
| `avatar` | Set account profile picture. Options: `gravatar`, `default` or a custom React component. |
|
||||
| `autoLogin` | Used to automate admin log-in for dev and demonstration convenience. [More](/docs/authentication/config). |
|
||||
| `livePreview` | Enable real-time editing for instant visual feedback of your front-end application. [More](/docs/live-preview/overview). |
|
||||
| `components` | Component overrides that affect the entirety of the Admin panel. [More](/docs/admin/components) |
|
||||
| `webpack` | Customize the Webpack config that's used to generate the Admin panel. [More](/docs/admin/webpack) |
|
||||
| `vite` | Customize the Vite config that's used to generate the Admin panel. [More](/docs/admin/vite) |
|
||||
| `logoutRoute` | The route for the `logout` page. |
|
||||
| `inactivityRoute` | The route for the `logout` inactivity page. |
|
||||
|
||||
### The Admin User Collection
|
||||
|
||||
@@ -55,13 +62,13 @@ To specify which Collection to use to log in to the Admin panel, pass the `admin
|
||||
`payload.config.js`:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from "payload/config";
|
||||
import { buildConfig } from 'payload/config'
|
||||
|
||||
const config = buildConfig({
|
||||
admin: {
|
||||
user: "admins", // highlight-line
|
||||
user: 'admins', // highlight-line
|
||||
},
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
By default, if you have not specified a Collection, Payload will automatically provide you with a `User` Collection which will be used to access the Admin panel. You can customize or override the fields and settings of the default `User` Collection by passing your own collection using `users` as its `slug` to Payload. When this is done, Payload will use your provided `User` Collection instead of its default version.
|
||||
|
||||
@@ -15,8 +15,10 @@ Out of the box, Payload handles the persistence of your users' preferences in a
|
||||
1. The "collapsed" state of blocks, on a document level, as users edit or interact with documents
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Important:</strong><br/>
|
||||
All preferences are stored on an individual user basis. Payload automatically recognizes the user that is reading or setting a preference via all provided authentication methods.
|
||||
<strong>Important:</strong>
|
||||
<br />
|
||||
All preferences are stored on an individual user basis. Payload automatically recognizes the user
|
||||
that is reading or setting a preference via all provided authentication methods.
|
||||
</Banner>
|
||||
|
||||
### Use cases
|
||||
@@ -30,17 +32,17 @@ This API is used significantly for internal operations of the Admin panel, as me
|
||||
|
||||
### Database
|
||||
|
||||
Payload automatically creates an internally used `_preferences` collection that stores user preferences. Each document in the `_preferences` collection contains the following shape:
|
||||
Payload automatically creates an internally used `payload-preferences` collection that stores user preferences. Each document in the `payload-preferences` collection contains the following shape:
|
||||
|
||||
| Key | Value |
|
||||
| -------------------- | -------------|
|
||||
| `id` | A unique ID for each preference stored. |
|
||||
| `key` | A unique `key` that corresponds to the preference. |
|
||||
| `user` | The ID of the `user` that is storing its preference. |
|
||||
| `userCollection` | The `slug` of the collection that the `user` is logged in as. |
|
||||
| `value` | The value of the preference. Can be any data shape that you need. |
|
||||
| `createdAt` | A timestamp of when the preference was created. |
|
||||
| `updatedAt` | A timestamp set to the last time the preference was updated.
|
||||
| Key | Value |
|
||||
| ----------------- | ----------------------------------------------------------------- |
|
||||
| `id` | A unique ID for each preference stored. |
|
||||
| `key` | A unique `key` that corresponds to the preference. |
|
||||
| `user.value` | The ID of the `user` that is storing its preference. |
|
||||
| `user.relationTo` | The `slug` of the collection that the `user` is logged in as. |
|
||||
| `value` | The value of the preference. Can be any data shape that you need. |
|
||||
| `createdAt` | A timestamp of when the preference was created. |
|
||||
| `updatedAt` | A timestamp set to the last time the preference was updated. |
|
||||
|
||||
### APIs
|
||||
|
||||
|
||||
82
docs/admin/vite.mdx
Normal file
82
docs/admin/vite.mdx
Normal file
@@ -0,0 +1,82 @@
|
||||
---
|
||||
title: Vite
|
||||
label: Vite
|
||||
order: 90
|
||||
desc: NEEDS TO BE WRITTEN
|
||||
---
|
||||
|
||||
Payload has a Vite bundler that you can install and bundle the Admin Panel with. This is an alternative to the [Webpack](/docs/admin/webpack) bundler and might give some performance boosts to your development workflow.
|
||||
|
||||
To use Vite as your bundler, first you need to install the package:
|
||||
|
||||
```bash
|
||||
yarn add @payloadcms/bundler-vite
|
||||
```
|
||||
|
||||
<Banner>
|
||||
The Vite bundler is currently in beta. If you would like to help us test this package, we'd love to hear if you find any bugs or issues!
|
||||
</Banner>
|
||||
|
||||
Vite works fundamentally differently than Webpack. In development mode, it will first pre-bundle any of your dependencies that are CommonJS-only, and then it'll leverage ESM directly in your browser for a better HMR experience.
|
||||
|
||||
It then uses Rollup to create production builds of your admin UI. With Vite, you should see a decent performance boost—especially after your first cold start. However, that first cold start might take a few more seconds.
|
||||
|
||||
<Banner type="warning">
|
||||
In most cases, Vite should work out of the box. But existing Payload plugins may need to make compatibility changes to support Vite.
|
||||
</Banner>
|
||||
|
||||
This is because Vite aliases work fundamentally differently than Webpack aliases, and Payload relies on aliasing server-only code out of the Payload config to ensure that the bundled admin JS works within your browser.
|
||||
|
||||
Here are the main differences between how Vite aliases work and how Webpack aliases work.
|
||||
|
||||
**Vite aliases do not work with absolute paths.**
|
||||
|
||||
In Vite, an alias will only match if the `find` property _exactly matches_ how you are importing your server-only file. So if you are importing a file with a relative path, i.e. `'../../my-module'`, and your alias is absolute, your alias will not work.
|
||||
|
||||
|
||||
**Vite aliases do not get applied to pre-bundled dependencies.**
|
||||
|
||||
This especially affects plugins, as plugins will be pre-bundled by Vite using `esbuild`. To get around this and support Vite, plugin authors need to configure an alias to their plugin at the top level, so that the alias will work accordingly.
|
||||
|
||||
Here's an example. Say your plugin is called `payload-plugin-cool`. It's imported as follows:
|
||||
|
||||
```ts
|
||||
import { myCoolPlugin } from 'payload-plugin-cool'
|
||||
```
|
||||
|
||||
That plugin should create an alias to support Vite as follows:
|
||||
|
||||
```ts
|
||||
{
|
||||
// aliases go here
|
||||
'payload-plugin-cool': path.resolve(__dirname, './my-admin-plugin.js')
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
This will effectively alias the entire plugin and work with Vite. If the plugin requires admin-specific code, then the `./my-admin-plugin.js` alias target file should reflect any changes necessary to the admin UI that the main server-side plugin performs.
|
||||
|
||||
### Extending the Vite config
|
||||
|
||||
The Payload config supports a new property for plugins to be able to extend the Vite config specifically. That property exists on the main Payload config under `admin.vite`.
|
||||
|
||||
It's a function that takes a Vite config, and returns an updated Vite config. Here's an example:
|
||||
|
||||
```ts
|
||||
export const buildConfig({
|
||||
collections: [],
|
||||
admin: {
|
||||
vite: (incomingViteConfig) => ({
|
||||
...incomingViteConfig,
|
||||
resolve: {
|
||||
...incomingViteConfig.resolve,
|
||||
// Do whatever you need here
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Even though there is a new property for Vite configs specifically, we have implemented some "compatibility" between Webpack and Vite out-of-the-box.
|
||||
|
||||
If your config specifies Webpack aliases, we attempt to leverage them automatically within the Vite config. They are merged into the Vite alias configuration seamlessly and may work out-of-the-box.
|
||||
@@ -1,176 +1,67 @@
|
||||
---
|
||||
title: Webpack
|
||||
label: Webpack
|
||||
order: 60
|
||||
order: 80
|
||||
desc: The Payload admin panel uses Webpack 5 and supports many common functionalities such as SCSS and Typescript out of the box to give you more freedom.
|
||||
keywords: admin, webpack, documentation, Content Management System, cms, headless, javascript, node, react, express
|
||||
---
|
||||
|
||||
Payload uses Webpack 5 to build the Admin panel. It comes with support for many common functionalities such as SCSS and Typescript out of the box, but there are many cases where you may need to add support for additional functionalities.
|
||||
Payload has a Webpack (v5) bundler that you can build the Admin panel with. For now, we recommended using it because it is stable. If you are feeling a bit more adventurous you can give the [Vite](/docs/admin/vite) bundler a shot.
|
||||
|
||||
To extend the Webpack config, add the `webpack` key to your base Payload config, and provide a function that accepts the default Webpack config as its only argument:
|
||||
Out of the box, the Webpack bundler supports common functionalities such as SCSS and Typescript, but there are many cases where you may need to add support for additional functionalities.
|
||||
|
||||
#### Installation
|
||||
|
||||
```bash
|
||||
yarn add @payloadcms/bundler-webpack
|
||||
```
|
||||
|
||||
#### Import the bundler
|
||||
|
||||
`payload.config.ts`
|
||||
```ts
|
||||
import { buildConfig } from 'payload/config';
|
||||
// payload.config.ts
|
||||
|
||||
import { buildConfig } from 'payload/config'
|
||||
import { webpackBundler } from '@payloadcms/bundler-webpack'
|
||||
|
||||
export default buildConfig({
|
||||
admin: {
|
||||
// highlight-start
|
||||
webpack: (config) => {
|
||||
// Do something with the config here
|
||||
|
||||
return config;
|
||||
}
|
||||
// highlight-end
|
||||
}
|
||||
});
|
||||
// highlight-start
|
||||
admin: {
|
||||
bundler: webpackBundler()
|
||||
},
|
||||
// highlight-end
|
||||
})
|
||||
```
|
||||
|
||||
### Aliasing server-only modules
|
||||
### Extending Webpack
|
||||
|
||||
A common use case for extending the Payload config is to alias server-only modules, thus preventing them from inclusion into the browser JavaScript bundle.
|
||||
If you need to extend the Webpack config, you can do so by passing a function to the `admin.webpack` property on your Payload config.
|
||||
The function will receive the Webpack config as an argument and should return the modified config.
|
||||
|
||||
As the Payload config is used in both server **and** client contexts, you may find yourself writing code in your Payload config that may be incompatible with browser environments.
|
||||
|
||||
Examples of **non** browser-friendly packages:
|
||||
|
||||
- `fs`
|
||||
- `stripe`
|
||||
- `authorizenet`
|
||||
- `nodemailer`
|
||||
|
||||
You may rely on server-only packages such as the above to perform logic in access control functions, hooks, and other contexts (which is great!) but when you boot up your Payload app and try to view it in the browser, you'll likely run into missing dependency issues or other general incompatibilities.
|
||||
|
||||
<Banner type="success">
|
||||
<strong>Tip:</strong><br/>
|
||||
To avoid problems with server code making it to your Webpack bundle, you can use the <strong>alias</strong> Webpack feature to tell Webpack to avoid importing the modules you want to restrict to server-only.
|
||||
</Banner>
|
||||
|
||||
<strong>For example, let's say that you have a Collection called `Subscriptions` which relies on Stripe:</strong>
|
||||
|
||||
<br/><br/>
|
||||
|
||||
`collections/Subscriptions/index.js`
|
||||
```ts
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
import createStripeSubscription from './hooks/createStripeSubscription';
|
||||
// payload.config.ts
|
||||
|
||||
export const Subscription: CollectionConfig = {
|
||||
slug: 'subscriptions',
|
||||
hooks: {
|
||||
beforeChange: [
|
||||
createStripeSubscription,
|
||||
]
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'stripeSubscriptionID',
|
||||
type: 'text',
|
||||
required: true,
|
||||
}
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
The collection above features a `beforeChange` hook that creates a Stripe subscription whenever a Subscription document is created in Payload.
|
||||
|
||||
<strong>That hook might look something like this:</strong>
|
||||
|
||||
<br/><br/>
|
||||
|
||||
`collections/Subscriptions/hooks/createStripeSubscription.js`
|
||||
```js
|
||||
import Stripe from 'stripe';
|
||||
|
||||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
||||
|
||||
const createStripeSubscription = async ({ data, operation }) => {
|
||||
if (operation === 'create') {
|
||||
const dataWithStripeID = {...data};
|
||||
|
||||
// use Stripe to create a Stripe subscription
|
||||
const subscription = await stripe.subscriptions.create({
|
||||
// Configure the subscription accordingly
|
||||
});
|
||||
|
||||
// Automatically add the Stripe subscription ID
|
||||
// to the data that will be saved to this Subscription doc
|
||||
dataWithStripeID.stripeSubscriptionID = subscription.id;
|
||||
|
||||
return dataWithStripeID
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export default createStripeSubscription;
|
||||
```
|
||||
|
||||
<Banner type="error">
|
||||
<strong>Warning:</strong><br/>
|
||||
The above code is NOT production-ready and should not be referenced to create Stripe subscriptions. Although creating a beforeChange hook is a completely valid spot to do things like create subscriptions, the code above is incomplete and insecure, meant for explanation purposes only.
|
||||
</Banner>
|
||||
|
||||
**As-is, this collection will prevent your Admin panel from bundling or loading correctly, because Stripe relies on some Node-only packages.**
|
||||
|
||||
To remedy this issue you can extend the Payload Webpack config to alias your entire `createStripeSubscription` hook to a separate, empty mock file.
|
||||
|
||||
Example in `payload.config.js`:
|
||||
```js
|
||||
import { buildConfig } from 'payload/config';
|
||||
import path from 'path';
|
||||
import Subscription from './collections/Subscription';
|
||||
|
||||
const createStripeSubscriptionPath = path.resolve(__dirname, 'collections/Subscription/hooks/createStripeSubscription.js');
|
||||
const mockModulePath = path.resolve(__dirname, 'mocks/emptyObject.js');
|
||||
import { buildConfig } from 'payload/config'
|
||||
import { webpackBundler } from '@payloadcms/bundler-webpack'
|
||||
|
||||
export default buildConfig({
|
||||
collections: [
|
||||
Subscription
|
||||
],
|
||||
admin: {
|
||||
webpack: (config) => ({
|
||||
...config,
|
||||
resolve: {
|
||||
...config.resolve,
|
||||
alias: {
|
||||
...config.resolve.alias,
|
||||
[createStripeSubscriptionPath]: mockModulePath,
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
admin: {
|
||||
bundler: webpackBundler()
|
||||
// highlight-start
|
||||
webpack: (config) => {
|
||||
// full control of the Webpack config
|
||||
|
||||
return config
|
||||
},
|
||||
// highlight-end
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
The above code will alias the file at path `createStripeSubscriptionPath` to a mocked module, which might look like this:
|
||||
|
||||
`mocks/emptyObject.js`
|
||||
```js
|
||||
export default {};
|
||||
```
|
||||
|
||||
Now, when Webpack sees that you're attempting to import your `createStripeSubscriptionPath` file, it'll disregard that actual file and load your mock file instead. Not only will your Admin panel now bundle successfully, you will have optimized its filesize by removing unnecessary code! And you might have learned something about Webpack, too.
|
||||
|
||||
<Banner type="success">
|
||||
<strong>Tip:</strong><br/>
|
||||
If changes to your Webpack aliases are not surfacing, they might be [cached](https://webpack.js.org/configuration/cache/) in `node_modules/.cache/webpack`. Try deleting that folder and restarting your server.
|
||||
<strong>Tip:</strong>
|
||||
<br />
|
||||
If changes to your Webpack aliases are not surfacing, they might be
|
||||
[cached](https://webpack.js.org/configuration/cache/) in `node_modules/.cache/webpack`. Try
|
||||
deleting that folder and restarting your server.
|
||||
</Banner>
|
||||
|
||||
## Admin environment vars
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Important:</strong><br />
|
||||
Be careful about what variables you provide to your client-side code. Analyze every single one to make sure that you're not accidentally leaking anything that an attacker could exploit. Only keys that are safe to be available to everyone in plain text should be provided to your Admin panel.
|
||||
</Banner>
|
||||
|
||||
By default, `env` variables are **not** provided to the Admin panel for security and safety reasons. But, Payload provides you with a way to still provide `env` vars to your frontend code.
|
||||
|
||||
**Payload will automatically supply any present `env` variables that are prefixed with `PAYLOAD_PUBLIC_` directly to the Admin panel.**
|
||||
|
||||
For example, if you've got the following environment variable:
|
||||
|
||||
`PAYLOAD_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_XXXXXXXXXXXXXXXXXX`
|
||||
|
||||
This key will automatically be made available to the Payload bundle and can be referenced in your Admin component code as `process.env.PAYLOAD_PUBLIC_STRIPE_PUBLISHABLE_KEY`.
|
||||
|
||||
@@ -41,8 +41,8 @@ Technically, both of these options will work for third-party integrations but th
|
||||
To enable API keys on a collection, set the `useAPIKey` auth option to `true`. From there, a new interface will appear in the Admin panel for each document within the collection that allows you to generate an API key for each user in the Collection.
|
||||
|
||||
<Banner type="success">
|
||||
User API keys are encrypted within the database, meaning that if your database
|
||||
is compromised, your API keys will not be.
|
||||
User API keys are encrypted within the database, meaning that if your database is compromised,
|
||||
your API keys will not be.
|
||||
</Banner>
|
||||
|
||||
#### Authenticating via API Key
|
||||
@@ -52,31 +52,31 @@ To authenticate REST or GraphQL API requests using an API key, set the `Authoriz
|
||||
**For example, using Fetch:**
|
||||
|
||||
```ts
|
||||
import User from '../collections/User';
|
||||
import User from '../collections/User'
|
||||
|
||||
const response = await fetch("http://localhost:3000/api/pages", {
|
||||
const response = await fetch('http://localhost:3000/api/pages', {
|
||||
headers: {
|
||||
Authorization: `${User.slug} API-Key ${YOUR_API_KEY}`,
|
||||
},
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
Payload ensures that the same, uniform access control is used across all authentication strategies. This enables you to utilize your existing access control configurations with both API keys and the standard email/password authentication. This consistency can aid in maintaining granular control over your API keys.
|
||||
|
||||
#### API Key *Only* Authentication
|
||||
#### API Key _Only_ Authentication
|
||||
|
||||
If you want to use API keys as the only authentication method for a collection, you can disable the default local strategy by setting `disableLocalStrategy` to `true` on the collection's `auth` property. This will disable the ability to authenticate with email and password, and will only allow for authentication via API key.
|
||||
|
||||
```ts
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
import { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Customers: CollectionConfig = {
|
||||
slug: 'customers',
|
||||
auth: {
|
||||
useAPIKey: true,
|
||||
disableLocalStrategy: true,
|
||||
}
|
||||
};
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Forgot Password
|
||||
@@ -90,17 +90,16 @@ Function that accepts one argument, containing `{ req, token, user }`, that allo
|
||||
<Banner type="success">
|
||||
<strong>Tip:</strong>
|
||||
<br />
|
||||
HTML templating can be used to create custom email templates, inline CSS
|
||||
automatically, and more. You can make a reusable function that standardizes
|
||||
all email sent from Payload, which makes sending custom emails more DRY.
|
||||
Payload doesn't ship with an HTML templating engine, so you are free to choose
|
||||
your own.
|
||||
HTML templating can be used to create custom email templates, inline CSS automatically, and more.
|
||||
You can make a reusable function that standardizes all email sent from Payload, which makes
|
||||
sending custom emails more DRY. Payload doesn't ship with an HTML templating engine, so you are
|
||||
free to choose your own.
|
||||
</Banner>
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
import { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Customers: CollectionConfig = {
|
||||
slug: 'customers',
|
||||
@@ -109,7 +108,7 @@ export const Customers: CollectionConfig = {
|
||||
// highlight-start
|
||||
generateEmailHTML: ({ req, token, user }) => {
|
||||
// Use the token provided to allow your user to reset their password
|
||||
const resetPasswordURL = `https://yourfrontend.com/reset-password?token=${token}`;
|
||||
const resetPasswordURL = `https://yourfrontend.com/reset-password?token=${token}`
|
||||
|
||||
return `
|
||||
<!doctype html>
|
||||
@@ -123,22 +122,21 @@ export const Customers: CollectionConfig = {
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
}
|
||||
`
|
||||
},
|
||||
// highlight-end
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Important:</strong>
|
||||
<br />
|
||||
If you specify a different URL to send your users to for resetting their
|
||||
password, such as a page on the frontend of your app or similar, you need to
|
||||
handle making the call to the Payload REST or GraphQL reset-password operation
|
||||
yourself on your frontend, using the token that was provided for you. Above,
|
||||
it was passed via query parameter.
|
||||
If you specify a different URL to send your users to for resetting their password, such as a page
|
||||
on the frontend of your app or similar, you need to handle making the call to the Payload REST or
|
||||
GraphQL reset-password operation yourself on your frontend, using the token that was provided for
|
||||
you. Above, it was passed via query parameter.
|
||||
</Banner>
|
||||
|
||||
**`generateEmailSubject`**
|
||||
@@ -173,8 +171,7 @@ Function that accepts one argument, containing `{ req, token, user }`, that allo
|
||||
Example:
|
||||
|
||||
```ts
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
|
||||
import { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Customers: CollectionConfig = {
|
||||
slug: 'customers',
|
||||
@@ -183,24 +180,23 @@ export const Customers: CollectionConfig = {
|
||||
// highlight-start
|
||||
generateEmailHTML: ({ req, token, user }) => {
|
||||
// Use the token provided to allow your user to verify their account
|
||||
const url = `https://yourfrontend.com/verify?token=${token}`;
|
||||
const url = `https://yourfrontend.com/verify?token=${token}`
|
||||
|
||||
return `Hey ${user.email}, verify your email by clicking here: ${url}`;
|
||||
}
|
||||
return `Hey ${user.email}, verify your email by clicking here: ${url}`
|
||||
},
|
||||
// highlight-end
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Important:</strong>
|
||||
<br />
|
||||
If you specify a different URL to send your users to for email verification,
|
||||
such as a page on the frontend of your app or similar, you need to handle
|
||||
making the call to the Payload REST or GraphQL verification operation yourself
|
||||
on your frontend, using the token that was provided for you. Above, it was
|
||||
passed via query parameter.
|
||||
If you specify a different URL to send your users to for email verification, such as a page on the
|
||||
frontend of your app or similar, you need to handle making the call to the Payload REST or GraphQL
|
||||
verification operation yourself on your frontend, using the token that was provided for you.
|
||||
Above, it was passed via query parameter.
|
||||
</Banner>
|
||||
|
||||
**`generateEmailSubject`**
|
||||
@@ -231,9 +227,8 @@ As of Payload `1.0.0`, you can add additional authentication strategies to Paylo
|
||||
Behind the scenes, Payload uses PassportJS to power its local authentication strategy, so most strategies listed on the PassportJS website will work seamlessly. Combined with adding custom components to the admin panel's `Login` view, you can create advanced authentication strategies directly within Payload.
|
||||
|
||||
<Banner type="warning">
|
||||
This is an advanced feature, so only attempt this if you are an experienced
|
||||
developer. Otherwise, just let Payload's built-in authentication handle user
|
||||
auth for you.
|
||||
This is an advanced feature, so only attempt this if you are an experienced developer. Otherwise,
|
||||
just let Payload's built-in authentication handle user auth for you.
|
||||
</Banner>
|
||||
|
||||
The `strategies` property is an array that takes objects with the following properties:
|
||||
@@ -250,7 +245,6 @@ However, if you pass a function to `strategy`, `name` is a required property.
|
||||
|
||||
In either case, Payload will prefix the strategy name with the collection `slug` that the strategy is passed to.
|
||||
|
||||
|
||||
### Admin autologin
|
||||
|
||||
For testing and demo purposes you may want to skip forcing the admin user to login in order to access the panel.
|
||||
@@ -259,29 +253,33 @@ The default is that all users will have to login and this should not be enabled
|
||||
|
||||
#### autoLogin Options
|
||||
|
||||
| Option | Description |
|
||||
| -------------------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **`email`** | The email address of the user to login as |
|
||||
| **`password`** | The password of the user to login as |
|
||||
| **`prefillOnly`** | If set to true, the login credentials will be prefilled but the user will still need to click the login button. |
|
||||
| Option | Description |
|
||||
| ----------------- | --------------------------------------------------------------------------------------------------------------- |
|
||||
| **`email`** | The email address of the user to login as |
|
||||
| **`password`** | The password of the user to login as |
|
||||
| **`prefillOnly`** | If set to true, the login credentials will be prefilled but the user will still need to click the login button. |
|
||||
|
||||
The recommended way to use this feature is behind an environment variable to ensure it is disabled when in production.
|
||||
|
||||
**Example:**
|
||||
|
||||
```ts
|
||||
|
||||
export default buildConfig({
|
||||
admin: {
|
||||
user: 'users',
|
||||
// highlight-start
|
||||
autoLogin: process.env.PAYLOAD_PUBLIC_ENABLE_AUTOLOGIN === 'true' ? {
|
||||
email: 'test@example.com',
|
||||
password: 'test',
|
||||
prefillOnly: true,
|
||||
} : false,
|
||||
autoLogin:
|
||||
process.env.PAYLOAD_PUBLIC_ENABLE_AUTOLOGIN === 'true'
|
||||
? {
|
||||
email: 'test@example.com',
|
||||
password: 'test',
|
||||
prefillOnly: true,
|
||||
}
|
||||
: false,
|
||||
// highlight-end
|
||||
},
|
||||
collections: [ /** */],
|
||||
collections: [
|
||||
/** */
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
@@ -17,6 +17,7 @@ The Access operation returns what a logged in user can and can't do with the col
|
||||
`GET http://localhost:3000/api/access`
|
||||
|
||||
Example response:
|
||||
|
||||
```ts
|
||||
{
|
||||
canAccessAdmin: true,
|
||||
@@ -77,6 +78,7 @@ Returns either a logged in user with token or null when there is no logged in us
|
||||
`GET http://localhost:3000/api/[collection-slug]/me`
|
||||
|
||||
Example response:
|
||||
|
||||
```ts
|
||||
{
|
||||
user: { // The JWT "payload" ;) from the logged in user
|
||||
@@ -108,6 +110,7 @@ query {
|
||||
Accepts an `email` and `password`. On success, it will return the logged in user as well as a token that can be used to authenticate. In the GraphQL and REST APIs, this operation also automatically sets an HTTP-only cookie including the user's token. If you pass an Express `res` to the Local API operation, Payload will set a cookie there as well.
|
||||
|
||||
**Example REST API login**:
|
||||
|
||||
```ts
|
||||
const res = await fetch('http://localhost:3000/api/[collection-slug]/login', {
|
||||
method: 'POST',
|
||||
@@ -117,10 +120,10 @@ const res = await fetch('http://localhost:3000/api/[collection-slug]/login', {
|
||||
body: JSON.stringify({
|
||||
email: 'dev@payloadcms.com',
|
||||
password: 'this-is-not-our-password...or-is-it?',
|
||||
})
|
||||
}),
|
||||
})
|
||||
|
||||
const json = await res.json();
|
||||
const json = await res.json()
|
||||
|
||||
// JSON will be equal to the following:
|
||||
/*
|
||||
@@ -168,6 +171,7 @@ const result = await payload.login({
|
||||
As Payload sets HTTP-only cookies, logging out cannot be done by just removing a cookie in JavaScript, as HTTP-only cookies are inaccessible by JS within the browser. So, Payload exposes a `logout` operation to delete the token in a safe way.
|
||||
|
||||
**Example REST API logout**:
|
||||
|
||||
```ts
|
||||
const res = await fetch('http://localhost:3000/api/[collection-slug]/logout', {
|
||||
method: 'POST',
|
||||
@@ -194,6 +198,7 @@ This operation requires a non-expired token to send back a new one. If the user'
|
||||
If successful, this operation will automatically renew the user's HTTP-only cookie and will send back the updated token in JSON.
|
||||
|
||||
**Example REST API token refresh**:
|
||||
|
||||
```ts
|
||||
const res = await fetch('http://localhost:3000/api/[collection-slug]/refresh-token', {
|
||||
method: 'POST',
|
||||
@@ -202,7 +207,7 @@ const res = await fetch('http://localhost:3000/api/[collection-slug]/refresh-tok
|
||||
},
|
||||
})
|
||||
|
||||
const json = await res.json();
|
||||
const json = await res.json()
|
||||
|
||||
// JSON will be equal to the following:
|
||||
/*
|
||||
@@ -233,7 +238,10 @@ mutation {
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
The Refresh operation will automatically find the user's token in either a JWT header or the HTTP-only cookie. But, you can specify the token you're looking to refresh by providing the REST API with a `token` within the JSON body of the request, or by providing the GraphQL resolver a `token` arg.
|
||||
The Refresh operation will automatically find the user's token in either a JWT header or the
|
||||
HTTP-only cookie. But, you can specify the token you're looking to refresh by providing the REST
|
||||
API with a `token` within the JSON body of the request, or by providing the GraphQL resolver a
|
||||
`token` arg.
|
||||
</Banner>
|
||||
|
||||
### Verify by Email
|
||||
@@ -241,13 +249,14 @@ mutation {
|
||||
If your collection supports email verification, the Verify operation will be exposed which accepts a verification token and sets the user's `_verified` property to `true`, thereby allowing the user to authenticate with the Payload API.
|
||||
|
||||
**Example REST API user verification**:
|
||||
|
||||
```ts
|
||||
const res = await fetch(`http://localhost:3000/api/[collection-slug]/verify/${TOKEN_HERE}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
**Example GraphQL Mutation**:
|
||||
@@ -274,6 +283,7 @@ If a user locks themselves out and you wish to deliberately unlock them, you can
|
||||
To restrict who is allowed to unlock users, you can utilize the [`unlock`](/docs/access-control/overview#unlock) access control function.
|
||||
|
||||
**Example REST API unlock**:
|
||||
|
||||
```ts
|
||||
const res = await fetch(`http://localhost:3000/api/[collection-slug]/unlock`, {
|
||||
method: 'POST',
|
||||
@@ -308,6 +318,7 @@ The link to reset the user's password contains a token which is what allows the
|
||||
By default, the Forgot Password operations send users to the Payload Admin panel to reset their password, but you can customize the generated email to send users to the frontend of your app instead by [overriding the email HTML](/docs/authentication/config#forgot-password).
|
||||
|
||||
**Example REST API Forgot Password**:
|
||||
|
||||
```ts
|
||||
const res = await fetch(`http://localhost:3000/api/[collection-slug]/forgot-password`, {
|
||||
method: 'POST',
|
||||
@@ -317,7 +328,7 @@ const res = await fetch(`http://localhost:3000/api/[collection-slug]/forgot-pass
|
||||
body: JSON.stringify({
|
||||
email: 'dev@payloadcms.com',
|
||||
}),
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
**Example GraphQL Mutation**:
|
||||
@@ -336,13 +347,18 @@ const token = await payload.forgotPassword({
|
||||
data: {
|
||||
email: 'dev@payloadcms.com',
|
||||
},
|
||||
disableEmail: false // you can disable the auto-generation of email via local API
|
||||
});
|
||||
disableEmail: false, // you can disable the auto-generation of email via local API
|
||||
})
|
||||
```
|
||||
|
||||
<Banner type="success">
|
||||
<strong>Tip:</strong><br/>
|
||||
You can stop the reset-password email from being sent via using the local API. This is helpful if you need to create user accounts programmatically, but not set their password for them. This effectively generates a reset password token which you can then use to send to a page you create, allowing a user to "complete" their account by setting their password. In the background, you'd use the token to "reset" their password.
|
||||
<strong>Tip:</strong>
|
||||
<br />
|
||||
You can stop the reset-password email from being sent via using the local API. This is helpful if
|
||||
you need to create user accounts programmatically, but not set their password for them. This
|
||||
effectively generates a reset password token which you can then use to send to a page you create,
|
||||
allowing a user to "complete" their account by setting their password. In the background, you'd
|
||||
use the token to "reset" their password.
|
||||
</Banner>
|
||||
|
||||
### Reset Password
|
||||
@@ -350,6 +366,7 @@ const token = await payload.forgotPassword({
|
||||
After a user has "forgotten" their password and a token is generated, that token can be used to send to the reset password operation along with a new password which will allow the user to reset their password securely.
|
||||
|
||||
**Example REST API Reset Password**:
|
||||
|
||||
```ts
|
||||
const res = await fetch(`http://localhost:3000/api/[collection-slug]/reset-password`, {
|
||||
method: 'POST',
|
||||
|
||||
@@ -12,13 +12,14 @@ keywords: authentication, config, configuration, overview, documentation, Conten
|
||||
/>
|
||||
|
||||
<Banner>
|
||||
Payload provides for highly secure and customizable user Authentication out of the box, which allows for users to identify themselves to Payload.
|
||||
Payload provides for highly secure and customizable user Authentication out of the box, which
|
||||
allows for users to identify themselves to Payload.
|
||||
</Banner>
|
||||
|
||||
Authentication is used within the Payload Admin panel itself as well as throughout your app(s) themselves however you determine necessary.
|
||||
|
||||

|
||||
*Admin panel screenshot depicting an Admins Collection with Auth enabled*
|
||||
_Admin panel screenshot depicting an Admins Collection with Auth enabled_
|
||||
|
||||
**Here are some common use cases of Authentication outside of Payload's dashboard itself:**
|
||||
|
||||
@@ -38,7 +39,7 @@ Every Payload Collection can opt-in to supporting Authentication by specifying t
|
||||
Simple example collection:
|
||||
|
||||
```ts
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
import { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Admins: CollectionConfig = {
|
||||
slug: 'admins',
|
||||
@@ -62,7 +63,7 @@ export const Admins: CollectionConfig = {
|
||||
'editor',
|
||||
'developer',
|
||||
],
|
||||
}
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
@@ -86,8 +87,11 @@ Successfully logging in returns a `JWT` (JSON web token) which is how a user wil
|
||||
You can specify what data gets encoded to the JWT token by setting `saveToJWT` to true in your auth collection fields. If you wish to use a different key other than the field `name`, you can provide it to `saveToJWT` as a string. It is also possible to use `saveToJWT` on fields that are nested in inside groups and tabs. If a group has a `saveToJWT` set it will include the object with all sub-fields in the token. You can set `saveToJWT: false` for any fields you wish to omit. If a field inside a group has `saveToJWT` set, but the group does not, the field will be included at the top level of the token.
|
||||
|
||||
<Banner type="success">
|
||||
<strong>Tip:</strong><br/>
|
||||
You can access the logged-in user from access control functions and hooks via the Express <strong>req</strong>. The logged-in user is automatically added as the <strong>user</strong> property.
|
||||
<strong>Tip:</strong>
|
||||
<br />
|
||||
You can access the logged-in user from access control functions and hooks via the Express{' '}
|
||||
<strong>req</strong>. The logged-in user is automatically added as the <strong>user</strong>{' '}
|
||||
property.
|
||||
</Banner>
|
||||
|
||||
### HTTP-only cookies
|
||||
@@ -107,16 +111,19 @@ Fetch example, including credentials:
|
||||
```ts
|
||||
const response = await fetch('http://localhost:3000/api/pages', {
|
||||
credentials: 'include',
|
||||
});
|
||||
})
|
||||
|
||||
const pages = await response.json();
|
||||
const pages = await response.json()
|
||||
```
|
||||
|
||||
For more about how to automatically include cookies in requests from your app to your Payload API, [click here](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Sending_a_request_with_credentials_included).
|
||||
|
||||
<Banner type="success">
|
||||
<strong>Tip:</strong><br/>
|
||||
To make sure you have a Payload cookie set properly in your browser after logging in, you can use Chrome's Developer Tools - Application - Cookies - [your-domain-here]. The Chrome Developer tools will still show HTTP-only cookies, even when JavaScript running on the page can't.
|
||||
<strong>Tip:</strong>
|
||||
<br />
|
||||
To make sure you have a Payload cookie set properly in your browser after logging in, you can use
|
||||
Chrome's Developer Tools - Application - Cookies - [your-domain-here]. The Chrome Developer tools
|
||||
will still show HTTP-only cookies, even when JavaScript running on the page can't.
|
||||
</Banner>
|
||||
|
||||
### CSRF Protection
|
||||
@@ -128,28 +135,33 @@ For example, let's say you have a very popular app running at coolsite.com. This
|
||||
So, if a user of coolsite.com is logged in and just browsing around on the internet, they might stumble onto a page with bad intentions. That bad page might automatically make requests to all sorts of sites to see if they can find one that they can log into - and coolsite.com might be on their list. If your user was logged in while they visited that evil site, the attacker could do whatever they wanted as if they were your coolsite.com user by just sending requests to the coolsite API (which would automatically include the auth cookie). They could send themselves a bunch of money from your user's account, change the user's password, etc. This is what a CSRF attack is.
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>To protect against CSRF attacks, Payload only accepts cookie-based authentication from domains that you explicitly whitelist.</strong>
|
||||
<strong>
|
||||
To protect against CSRF attacks, Payload only accepts cookie-based authentication from domains
|
||||
that you explicitly whitelist.
|
||||
</strong>
|
||||
</Banner>
|
||||
|
||||
To define domains that should allow users to identify themselves via the Payload HTTP-only cookie, use the `csrf` option on the base Payload config to whitelist domains that you trust.
|
||||
|
||||
`payload.config.ts`:
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload/config';
|
||||
import { buildConfig } from 'payload/config'
|
||||
|
||||
const config = buildConfig({
|
||||
collections: [
|
||||
// collections here
|
||||
],
|
||||
// highlight-start
|
||||
csrf: [ // whitelist of domains to allow cookie auth from
|
||||
csrf: [
|
||||
// whitelist of domains to allow cookie auth from
|
||||
'https://your-frontend-app.com',
|
||||
'https://your-other-frontend-app.com',
|
||||
],
|
||||
// highlight-end
|
||||
});
|
||||
})
|
||||
|
||||
export default config;
|
||||
export default config
|
||||
```
|
||||
|
||||
### Identifying users via the Authorization Header
|
||||
@@ -157,11 +169,12 @@ export default config;
|
||||
In addition to authenticating via an HTTP-only cookie, you can also identify users via the `Authorization` header on an HTTP request.
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
const request = await fetch('http://localhost:3000', {
|
||||
headers: {
|
||||
Authorization: `JWT ${token}`
|
||||
}
|
||||
Authorization: `JWT ${token}`,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
@@ -11,48 +11,46 @@ Because Payload uses your existing Express server, you are free to add whatever
|
||||
This approach has a ton of benefits - it's great for isolation of concerns and limiting scope, but it also means that your additional routes won't have access to Payload's user authentication.
|
||||
|
||||
<Banner type="success">
|
||||
You can make full use of Payload's built-in authentication within your own
|
||||
custom Express endpoints by adding Payload's authentication middleware.
|
||||
You can make full use of Payload's built-in authentication within your own custom Express
|
||||
endpoints by adding Payload's authentication middleware.
|
||||
</Banner>
|
||||
|
||||
<Banner type="warning">
|
||||
Payload must be initialized before the `payload.authenticate` middleware can
|
||||
be used. This is done by calling `payload.init()` prior to adding the
|
||||
middleware.
|
||||
Payload must be initialized before the `payload.authenticate` middleware can be used. This is done
|
||||
by calling `payload.init()` prior to adding the middleware.
|
||||
</Banner>
|
||||
|
||||
Example in `server.js`:
|
||||
|
||||
```ts
|
||||
import express from "express";
|
||||
import payload from "payload";
|
||||
import express from 'express'
|
||||
import payload from 'payload'
|
||||
|
||||
const app = express();
|
||||
const app = express()
|
||||
|
||||
const start = async () => {
|
||||
await payload.init({
|
||||
secret: "PAYLOAD_SECRET_KEY",
|
||||
mongoURL: "mongodb://localhost/payload",
|
||||
secret: 'PAYLOAD_SECRET_KEY',
|
||||
express: app,
|
||||
});
|
||||
})
|
||||
|
||||
const router = express.Router();
|
||||
const router = express.Router()
|
||||
|
||||
// Note: Payload must be initialized before the `payload.authenticate` middleware can be used
|
||||
router.use(payload.authenticate); // highlight-line
|
||||
router.use(payload.authenticate) // highlight-line
|
||||
|
||||
router.get("/", (req, res) => {
|
||||
router.get('/', (req, res) => {
|
||||
if (req.user) {
|
||||
return res.send(`Authenticated successfully as ${req.user.email}.`);
|
||||
return res.send(`Authenticated successfully as ${req.user.email}.`)
|
||||
}
|
||||
|
||||
return res.send("Not authenticated");
|
||||
});
|
||||
return res.send('Not authenticated')
|
||||
})
|
||||
|
||||
app.use("/some-route-here", router);
|
||||
app.use('/some-route-here', router)
|
||||
|
||||
app.listen(3000);
|
||||
};
|
||||
app.listen(3000)
|
||||
}
|
||||
|
||||
start();
|
||||
start()
|
||||
```
|
||||
|
||||
@@ -11,10 +11,10 @@ keywords: configuration, config, settings, project, cloud, payload cloud, deploy
|
||||
Once you have created a project, you will need to select your plan. This will determine the resources that are allocated to your project and the features that are available to you.
|
||||
|
||||
<Banner type="success">
|
||||
Note: All Payload Cloud teams that deploy a project require a card on file.
|
||||
This helps us prevent fraud and abuse on our platform. If you select a plan
|
||||
with a free trial, you will not be charged until your trial period is over.
|
||||
We’ll remind you 7 days before your trial ends and you can cancel anytime.
|
||||
Note: All Payload Cloud teams that deploy a project require a card on file. This helps us prevent
|
||||
fraud and abuse on our platform. If you select a plan with a free trial, you will not be charged
|
||||
until your trial period is over. We’ll remind you 7 days before your trial ends and you can cancel
|
||||
anytime.
|
||||
</Banner>
|
||||
|
||||
### Project Details
|
||||
@@ -44,8 +44,8 @@ If you are deploying a new project from a template, the following settings will
|
||||
Any of the features in Payload Cloud that require environment variables will automatically be provided to your application. If your app requires any custom environment variables, you can set them here.
|
||||
|
||||
<Banner type="warning">
|
||||
Note: For security reasons, any variables you wish to provide to the Admin
|
||||
panel must be prefixed with `PAYLOAD_PUBLIC_`. Learn more
|
||||
Note: For security reasons, any variables you wish to provide to the Admin panel must be prefixed
|
||||
with `PAYLOAD_PUBLIC_`. Learn more
|
||||
[here](https://payloadcms.com/docs/admin/webpack#admin-environment-vars).
|
||||
</Banner>
|
||||
|
||||
@@ -54,9 +54,8 @@ Any of the features in Payload Cloud that require environment variables will aut
|
||||
Payment methods can be set per project and can be updated any time. You can use team’s default payment method, or add a new one. Modify your payment methods in your Project settings / Team settings.
|
||||
|
||||
<Banner type="success">
|
||||
<strong>Note:</strong> All Payload Cloud teams that deploy a project require a
|
||||
card on file. This helps us prevent fraud and abuse on our platform. If you
|
||||
select a plan with a free trial, you will not be charged until your trial
|
||||
period is over. We’ll remind you 7 days before your trial ends and you can
|
||||
cancel anytime.
|
||||
<strong>Note:</strong> All Payload Cloud teams that deploy a project require a card on file. This
|
||||
helps us prevent fraud and abuse on our platform. If you select a plan with a free trial, you will
|
||||
not be charged until your trial period is over. We’ll remind you 7 days before your trial ends and
|
||||
you can cancel anytime.
|
||||
</Banner>
|
||||
|
||||
@@ -13,9 +13,8 @@ Payload Cloud offers various plans tailored to meet your specific needs, includi
|
||||
To get started, you first need to create an account. Head over to [the login screen](https://payloadcms.com/login) and **Register for Free**.
|
||||
|
||||
<Banner type="success">
|
||||
To create your first project, you can either select [a
|
||||
template](#starting-from-a-template) or [import an existing
|
||||
project](#importing-from-an-existing-codebase) from GitHub.
|
||||
To create your first project, you can either select [a template](#starting-from-a-template) or
|
||||
[import an existing project](#importing-from-an-existing-codebase) from GitHub.
|
||||
</Banner>
|
||||
|
||||
## Starting from a Template
|
||||
@@ -32,9 +31,8 @@ Next, select your `GitHub Scope`. If you belong to multiple organizations, they
|
||||
After selecting your scope, create a unique `repository name` and select whether you want your repository to be public or private on GitHub.
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Note:</strong> Public repositories can be accessed by anyone online,
|
||||
while private repositories grant access only to you and anyone you explicitly
|
||||
authorize.
|
||||
<strong>Note:</strong> Public repositories can be accessed by anyone online, while private
|
||||
repositories grant access only to you and anyone you explicitly authorize.
|
||||
</Banner>
|
||||
|
||||
Once you are ready, click **Create Project**. This will clone the selected template to a new repository in your GitHub account, and take you to the configuration page to set up your project for deployment.
|
||||
@@ -47,7 +45,7 @@ Payload Cloud works for any Node.js + MongoDB app. From the New Project page, se
|
||||
_Creating a new project from an existing repository._
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Note:</strong> In order to make use of the features of Payload Cloud
|
||||
in your own codebase, you will need to add the [Cloud
|
||||
Plugin](https://github.com/payloadcms/plugin-cloud) to your Payload app.
|
||||
<strong>Note:</strong> In order to make use of the features of Payload Cloud in your own codebase,
|
||||
you will need to add the [Cloud Plugin](https://github.com/payloadcms/plugin-cloud) to your
|
||||
Payload app.
|
||||
</Banner>
|
||||
|
||||
@@ -9,11 +9,10 @@ keywords: cloud, payload cloud, projects, project, overview, database, file stor
|
||||
### Overview
|
||||
|
||||
<Banner>
|
||||
The overview tab shows your most recent deployment, along with build and
|
||||
deployment logs. From here, you can see your live URL, deployment details like
|
||||
timestamps and commit hash, as well as the status of your deployment. You can
|
||||
also trigger a redeployment manually, which will rebuild your project using
|
||||
the current configuration.
|
||||
The overview tab shows your most recent deployment, along with build and deployment logs. From
|
||||
here, you can see your live URL, deployment details like timestamps and commit hash, as well as
|
||||
the status of your deployment. You can also trigger a redeployment manually, which will rebuild
|
||||
your project using the current configuration.
|
||||
</Banner>
|
||||
|
||||

|
||||
@@ -40,18 +39,18 @@ You can update settings from your Project’s Settings tab. Changes to your buil
|
||||
From the Environment Variables page of the Settings tab, you can add, update and delete variables for use in your project. Like build settings, these changes will trigger a redeployment of your project.
|
||||
|
||||
<Banner>
|
||||
Note: For security reasons, any variables you wish to provide to the Admin
|
||||
panel must be prefixed with `PAYLOAD_PUBLIC_`. Learn more
|
||||
Note: For security reasons, any variables you wish to provide to the Admin panel must be prefixed
|
||||
with `PAYLOAD_PUBLIC_`. Learn more
|
||||
[here](https://payloadcms.com/docs/admin/webpack#admin-environment-vars).
|
||||
</Banner>
|
||||
|
||||
### Custom Domains
|
||||
|
||||
With Payload Cloud, you can add custom domain names to your project. To do so, first go to the Domains page of the Settings tab of your project. Here you can see your default domain. To add a new domain, type in the domain name you wish to use.
|
||||
|
||||
<Banner>
|
||||
Note: do not include the protocol (http:// or https://) or any routes (/page).
|
||||
Only include the domain name and extension, and optionally a subdomain. -
|
||||
your-domain.com - backend.your-domain.com
|
||||
Note: do not include the protocol (http:// or https://) or any paths (/page). Only include the
|
||||
domain name and extension, and optionally a subdomain. - your-domain.com - backend.your-domain.com
|
||||
</Banner>
|
||||
|
||||
Once you click save, a DNS record will be generated for your domain name to point to your live project. Add this record into your DNS provider’s records, and once the records are resolving properly (this can take 1hr to 48hrs in some cases), your domain will now to point to your live project.
|
||||
@@ -60,9 +59,9 @@ You will also need to configure your Payload project to use your specified domai
|
||||
|
||||
```ts
|
||||
export default buildConfig({
|
||||
serverURL: "https://example.com",
|
||||
serverURL: 'https://example.com',
|
||||
// the rest of your config,
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
### Email
|
||||
@@ -84,18 +83,18 @@ Projects generated from a template will come pre-configured with the official Cl
|
||||
`yarn add @payloadcms/plugin-cloud`
|
||||
|
||||
```js
|
||||
import { payloadCloud } from "@payloadcms/plugin-cloud";
|
||||
import { buildConfig } from "payload/config";
|
||||
import { payloadCloud } from '@payloadcms/plugin-cloud'
|
||||
import { buildConfig } from 'payload/config'
|
||||
|
||||
export default buildConfig({
|
||||
plugins: [payloadCloud()],
|
||||
// rest of config
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
<Banner type="warning">
|
||||
**Note:** If your Payload config already has an email with transport, this
|
||||
will take precedence over Payload Cloud's email service.
|
||||
**Note:** If your Payload config already has an email with transport, this will take precedence
|
||||
over Payload Cloud's email service.
|
||||
</Banner>
|
||||
|
||||
##### **Optional configuration**
|
||||
@@ -106,5 +105,5 @@ If you wish to opt-out of any Payload cloud features, the plugin also accepts op
|
||||
payloadCloud({
|
||||
storage: false, // Disable file storage
|
||||
email: false, // Disable email delivery
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
@@ -7,8 +7,8 @@ keywords: team, teams, billing, subscription, payment, plan, plans, cloud, paylo
|
||||
---
|
||||
|
||||
<Banner>
|
||||
Within Payload Cloud, the team management feature offers you the ability to
|
||||
manage your organization, team members, billing, and subscription settings.
|
||||
Within Payload Cloud, the team management feature offers you the ability to manage your
|
||||
organization, team members, billing, and subscription settings.
|
||||
</Banner>
|
||||
|
||||

|
||||
|
||||
@@ -6,64 +6,66 @@ desc: Structure your Collections for your needs by defining fields, adding slugs
|
||||
keywords: collections, config, configuration, documentation, Content Management System, cms, headless, javascript, node, react, express
|
||||
---
|
||||
|
||||
Payload Collections are defined through configs of their own, and you can define as many as your application needs. Each Collection will scaffold a MongoDB collection automatically based on fields that you define.
|
||||
Payload Collections are defined through configs of their own, and you can define as many as your application needs. Each
|
||||
Collection will scaffold a new collection automatically in your database of choice, based on fields that you define.
|
||||
|
||||
It's often best practice to write your Collections in separate files and then import them into the main Payload config.
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Description |
|
||||
|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **`slug`** * | Unique, URL-friendly string that will act as an identifier for this Collection. |
|
||||
| **`fields`** * | Array of field types that will determine the structure and functionality of the data stored within this Collection. [Click here](/docs/fields/overview) for a full list of field types as well as how to configure them. |
|
||||
| **`indexes`** * | Array of database indexes to create, including compound indexes that have multiple fields. |
|
||||
| **`labels`** | Singular and plural labels for use in identifying this Collection throughout Payload. Auto-generated from slug if not defined. |
|
||||
| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-options). |
|
||||
| **`hooks`** | Entry points to "tie in" to Collection actions at specific points. [More](/docs/hooks/overview#collection-hooks) |
|
||||
| **`access`** | Provide access control functions to define exactly who should be able to do what with Documents in this Collection. [More](/docs/access-control/overview/#collections) |
|
||||
| **`auth`** | Specify options if you would like this Collection to feature authentication. For more, consult the [Authentication](/docs/authentication/config) documentation. |
|
||||
| **`upload`** | Specify options if you would like this Collection to support file uploads. For more, consult the [Uploads](/docs/upload/overview) documentation. |
|
||||
| **`timestamps`** | Set to false to disable documents' automatically generated `createdAt` and `updatedAt` timestamps. |
|
||||
| **`versions`** | Set to true to enable default options, or configure with object properties. [More](/docs/versions/overview#collection-config) |
|
||||
| **`endpoints`** | Add custom routes to the REST API. [More](/docs/rest-api/overview#custom-endpoints) |
|
||||
| **`graphQL`** | An object with `singularName` and `pluralName` strings used in schema generation. Auto-generated from slug if not defined. |
|
||||
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
||||
| **`defaultSort`** | Pass a top-level field to sort by default in the collection List view. Prefix the name of the field with a minus symbol ("-") to sort in descending order. |
|
||||
| **`pagination`** | Set pagination-specific options for this collection. [More](#pagination) |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| Option | Description |
|
||||
|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **`slug`** \* | Unique, URL-friendly string that will act as an identifier for this Collection. |
|
||||
| **`fields`** \* | Array of field types that will determine the structure and functionality of the data stored within this Collection. [Click here](/docs/fields/overview) for a full list of field types as well as how to configure them. |
|
||||
| **`labels`** | Singular and plural labels for use in identifying this Collection throughout Payload. Auto-generated from slug if not defined. |
|
||||
| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-options). |
|
||||
| **`hooks`** | Entry points to "tie in" to Collection actions at specific points. [More](/docs/hooks/overview#collection-hooks) |
|
||||
| **`access`** | Provide access control functions to define exactly who should be able to do what with Documents in this Collection. [More](/docs/access-control/overview/#collections) |
|
||||
| **`auth`** | Specify options if you would like this Collection to feature authentication. For more, consult the [Authentication](/docs/authentication/config) documentation. |
|
||||
| **`upload`** | Specify options if you would like this Collection to support file uploads. For more, consult the [Uploads](/docs/upload/overview) documentation. |
|
||||
| **`timestamps`** | Set to false to disable documents' automatically generated `createdAt` and `updatedAt` timestamps. |
|
||||
| **`versions`** | Set to true to enable default options, or configure with object properties. [More](/docs/versions/overview#collection-config) |
|
||||
| **`endpoints`** | Add custom routes to the REST API. Set to `false` to disable routes. [More](/docs/rest-api/overview#custom-endpoints) |
|
||||
| **`graphQL`** | An object with `singularName` and `pluralName` strings used in schema generation. Auto-generated from slug if not defined. Set to `false` to disable GraphQL. |
|
||||
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
||||
| **`defaultSort`** | Pass a top-level field to sort by default in the collection List view. Prefix the name of the field with a minus symbol ("-") to sort in descending order. |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
|
||||
*\* An asterisk denotes that a property is required.*
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
#### Simple collection example
|
||||
|
||||
```ts
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
import { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Orders: CollectionConfig = {
|
||||
slug: 'orders',
|
||||
fields: [
|
||||
{
|
||||
name: 'total',
|
||||
type: 'number',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'placedBy',
|
||||
type: 'relationship',
|
||||
relationTo: 'customers',
|
||||
required: true,
|
||||
}
|
||||
],
|
||||
};
|
||||
slug: 'orders',
|
||||
fields: [
|
||||
{
|
||||
name: 'total',
|
||||
type: 'number',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'placedBy',
|
||||
type: 'relationship',
|
||||
relationTo: 'customers',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
#### More collection config examples
|
||||
|
||||
You can find an assortment of [example collection configs](https://github.com/payloadcms/public-demo/tree/master/src/collections) in the Public Demo source code on GitHub.
|
||||
You can find an assortment
|
||||
of [example collection configs](https://github.com/payloadcms/public-demo/tree/master/src/collections) in the Public
|
||||
Demo source code on GitHub.
|
||||
|
||||
### Admin options
|
||||
|
||||
You can customize the way that the Admin panel behaves on a collection-by-collection basis by defining the `admin` property on a collection's config.
|
||||
You can customize the way that the Admin panel behaves on a collection-by-collection basis by defining the `admin`
|
||||
property on a collection's config.
|
||||
|
||||
| Option | Description |
|
||||
|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
@@ -78,14 +80,18 @@ You can customize the way that the Admin panel behaves on a collection-by-collec
|
||||
| `enableRichTextLink` | The [Rich Text](/docs/fields/rich-text) field features a `Link` element which allows for users to automatically reference related documents within their rich text. Set to `true` by default. |
|
||||
| `enableRichTextRelationship` | The [Rich Text](/docs/fields/rich-text) field features a `Relationship` element which allows for users to automatically reference related documents within their rich text. Set to `true` by default. |
|
||||
| `preview` | Function to generate preview URLS within the Admin panel that can point to your app. [More](#preview). |
|
||||
| `livePreview` | Enable real-time editing for instant visual feedback of your front-end application. [More](/docs/live-preview/overview). |
|
||||
| `components` | Swap in your own React components to be used within this collection. [More](/docs/admin/components#collections) |
|
||||
| `listSearchableFields` | Specify which fields should be searched in the List search view. [More](#list-searchable-fields) |
|
||||
| **`pagination`** | Set pagination-specific options for this collection. [More](#pagination) |
|
||||
|
||||
### Preview
|
||||
|
||||
Collection `admin` options can accept a `preview` function that will be used to generate a link pointing to the frontend of your app to preview data.
|
||||
Collection `admin` options can accept a `preview` function that will be used to generate a link pointing to the frontend
|
||||
of your app to preview data.
|
||||
|
||||
If the function is specified, a Preview button will automatically appear in the corresponding collection's Edit view. Clicking the Preview button will link to the URL that is generated by the function.
|
||||
If the function is specified, a Preview button will automatically appear in the corresponding collection's Edit view.
|
||||
Clicking the Preview button will link to the URL that is generated by the function.
|
||||
|
||||
**The preview function accepts two arguments:**
|
||||
|
||||
@@ -95,59 +101,70 @@ If the function is specified, a Preview button will automatically appear in the
|
||||
**Example collection with preview function:**
|
||||
|
||||
```ts
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
import { CollectionConfig } from 'payload/types'
|
||||
|
||||
export const Posts: CollectionConfig = {
|
||||
slug: 'posts',
|
||||
fields: [
|
||||
{
|
||||
name: 'slug',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
admin: {
|
||||
preview: (doc, { locale }) => {
|
||||
if (doc?.slug) {
|
||||
return `https://bigbird.com/preview/posts/${doc.slug}?locale=${locale}`;
|
||||
}
|
||||
slug: 'posts',
|
||||
fields: [
|
||||
{
|
||||
name: 'slug',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
admin: {
|
||||
preview: (doc, { locale }) => {
|
||||
if (doc?.slug) {
|
||||
return `https://bigbird.com/preview/posts/${doc.slug}?locale=${locale}`
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
},
|
||||
};
|
||||
return null
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Pagination
|
||||
|
||||
Here are a few options that you can specify options for pagination on a collection-by-collection basis:
|
||||
|
||||
| Option | Description |
|
||||
| --------------------------- | -------------|
|
||||
| `defaultLimit` | Integer that specifies the default per-page limit that should be used. Defaults to 10. |
|
||||
| `limits` | Provide an array of integers to use as per-page options for admins to choose from in the List view. |
|
||||
| Option | Description |
|
||||
|----------------|-----------------------------------------------------------------------------------------------------|
|
||||
| `defaultLimit` | Integer that specifies the default per-page limit that should be used. Defaults to 10. |
|
||||
| `limits` | Provide an array of integers to use as per-page options for admins to choose from in the List view. |
|
||||
|
||||
### Access control
|
||||
|
||||
You can specify extremely granular access control (what users can do with documents in a collection) on a collection by collection basis. To learn more, go to the [Access Control](/docs/access-control/overview) docs.
|
||||
You can specify extremely granular access control (what users can do with documents in a collection) on a collection by
|
||||
collection basis. To learn more, go to the [Access Control](/docs/access-control/overview) docs.
|
||||
|
||||
### Hooks
|
||||
|
||||
Hooks are a powerful way to extend collection functionality and execute your own logic, and can be defined on a collection by collection basis. To learn more, go to the [Hooks](/docs/hooks/overview) documentation.
|
||||
Hooks are a powerful way to extend collection functionality and execute your own logic, and can be defined on a
|
||||
collection by collection basis. To learn more, go to the [Hooks](/docs/hooks/overview) documentation.
|
||||
|
||||
### Field types
|
||||
|
||||
Collections support all field types that Payload has to offer—including simple fields like text and checkboxes all the way to more complicated layout-building field groups like Blocks. [Click here](/docs/fields/overview) to learn more about field types.
|
||||
Collections support all field types that Payload has to offer—including simple fields like text and checkboxes all the
|
||||
way to more complicated layout-building field groups like Blocks. [Click here](/docs/fields/overview) to learn more
|
||||
about field types.
|
||||
|
||||
### List Searchable Fields
|
||||
|
||||
In the List view, there is a "search" box that allows you to quickly find a document with a search. By default, it searches on the ID field. If you have `admin.useAsTitle` defined, the list search will use that field. However, you can define more than one field to search to make it easier on your admin editors to find the data they need.
|
||||
In the List view, there is a "search" box that allows you to quickly find a document with a search. By default, it
|
||||
searches on the ID field. If you have `admin.useAsTitle` defined, the list search will use that field. However, you can
|
||||
define more than one field to search to make it easier on your admin editors to find the data they need.
|
||||
|
||||
For example, let's say you have a Posts collection with `title`, `metaDescription`, and `tags` fields - and you want all three of those fields to be searchable in the List view. You can simply add `admin.listSearchableFields: ['title', 'metaDescription', 'tags']` - and the admin UI will automatically search on those three fields plus the ID field.
|
||||
For example, let's say you have a Posts collection with `title`, `metaDescription`, and `tags` fields - and you want all
|
||||
three of those fields to be searchable in the List view. You can simply
|
||||
add `admin.listSearchableFields: ['title', 'metaDescription', 'tags']` - and the admin UI will automatically search on
|
||||
those three fields plus the ID field.
|
||||
|
||||
<Banner type="warning">
|
||||
<strong>Note:</strong><br/>
|
||||
If you are adding <strong>listSearchableFields</strong>, make sure you index each of these fields so your admin queries can remain performant.
|
||||
<strong>Note:</strong>
|
||||
<br />
|
||||
If you are adding <strong>listSearchableFields</strong>, make sure you index each of these fields
|
||||
so your admin queries can remain performant.
|
||||
</Banner>
|
||||
|
||||
### Admin Hooks
|
||||
@@ -156,29 +173,32 @@ In addition to collection hooks themselves, Payload provides for admin UI-specif
|
||||
|
||||
**`beforeDuplicate`**
|
||||
|
||||
The `beforeDuplicate` hook is an async function that accepts an object containing the data to duplicate, as well as the locale of the doc to duplicate. Within this hook, you can modify the data to be duplicated, which is useful in cases where you have unique fields that need to be incremented or similar, as well as if you want to automatically modify a document's `title`.
|
||||
The `beforeDuplicate` hook is an async function that accepts an object containing the data to duplicate, as well as the
|
||||
locale of the doc to duplicate. Within this hook, you can modify the data to be duplicated, which is useful in cases
|
||||
where you have unique fields that need to be incremented or similar, as well as if you want to automatically modify a
|
||||
document's `title`.
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
import { BeforeDuplicate, CollectionConfig } from 'payload/types';
|
||||
import { BeforeDuplicate, CollectionConfig } from 'payload/types'
|
||||
// Your auto-generated Page type
|
||||
import { Page } from '../payload-types.ts';
|
||||
import { Page } from '../payload-types.ts'
|
||||
|
||||
const beforeDuplicate: BeforeDuplicate<Page> = ({ data }) => {
|
||||
return {
|
||||
...data,
|
||||
title: `${data.title} Copy`,
|
||||
uniqueField: data.uniqueField ? `${data.uniqueField}-copy` : '',
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const Page: CollectionConfig = {
|
||||
slug: 'pages',
|
||||
admin: {
|
||||
hooks: {
|
||||
beforeDuplicate,
|
||||
}
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
@@ -189,8 +209,8 @@ export const Page: CollectionConfig = {
|
||||
name: 'uniqueField',
|
||||
type: 'text',
|
||||
unique: true,
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
@@ -199,14 +219,14 @@ export const Page: CollectionConfig = {
|
||||
You can import collection types as follows:
|
||||
|
||||
```ts
|
||||
import { CollectionConfig } from 'payload/types';
|
||||
import { CollectionConfig } from 'payload/types'
|
||||
|
||||
// This is the type used for incoming collection configs.
|
||||
// Only the bare minimum properties are marked as required.
|
||||
```
|
||||
|
||||
```ts
|
||||
import { SanitizedCollectionConfig } from 'payload/types';
|
||||
import { SanitizedCollectionConfig } from 'payload/types'
|
||||
|
||||
// This is the type used after an incoming collection config is fully sanitized.
|
||||
// Generally, this is only used internally by Payload.
|
||||
|
||||
@@ -70,11 +70,11 @@ To customize compression options, pass an object to the Payload config's `expres
|
||||
|
||||
```js
|
||||
{
|
||||
express: {
|
||||
compression: {
|
||||
// settings go here
|
||||
}
|
||||
}
|
||||
express: {
|
||||
compression: {
|
||||
// settings go here
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user