Compare commits

..

382 Commits

Author SHA1 Message Date
James
1b49c18767 0.1.140 2021-01-07 16:48:14 -05:00
James
423df3f83a fix: admin field error messages 2021-01-07 16:46:49 -05:00
James
149781af9e docs: adds some excitement to quickstart 2021-01-06 12:08:26 -05:00
James
51539e6d44 docs: spelling error 2021-01-06 10:14:49 -05:00
James
ce6e8b7412 0.1.139 2021-01-06 09:21:27 -05:00
James
d22a5ad840 docs: adds callout to license in installation 2021-01-06 09:21:14 -05:00
James
e3385e1243 docs: licensing additions 2021-01-06 09:13:44 -05:00
James
d329d9f282 chore: updates webpack-cli 2021-01-06 08:57:43 -05:00
James
644519c539 fix: improves typing in delete op 2021-01-06 08:57:35 -05:00
James
2aab4dfb9d Merge branch 'master' of github.com:payloadcms/payload 2021-01-06 08:37:42 -05:00
James
2b37bfd93e docs: lowercases dir names 2021-01-06 08:37:29 -05:00
Elliot DeNolf
4d6871abc8 fix: use FileSize and ImageSize types 2021-01-06 00:07:47 -05:00
Elliot DeNolf
f059d5b59a docs: small create-payload-app functionality correction 2021-01-05 22:57:42 -05:00
Elliot DeNolf
82d8d28b2c chore: add badges to readme and rename workflow 2021-01-05 22:28:21 -05:00
James
2624b0c34b 0.1.138 2021-01-05 19:29:51 -05:00
James
8f568411de docs: licensing and preventing abuse revisions 2021-01-05 19:29:13 -05:00
James
6066f2896a fix: removes old css 2021-01-05 18:44:10 -05:00
Dan Ribbens
c6bc387a88 Merge branch 'master' of github.com:payloadcms/payload 2021-01-05 17:23:41 -05:00
Dan Ribbens
5e0ee919d7 docs: production preventing abuse 2021-01-05 17:22:47 -05:00
James
9fd545070b 0.1.137 2021-01-05 14:51:25 -05:00
James
680863702e fix: removes prod devtool 2021-01-05 14:51:19 -05:00
James
f20f6d70a0 0.1.136 2021-01-05 14:31:31 -05:00
James
983a939952 chore: bumps config-provider 2021-01-05 14:30:58 -05:00
Dan Ribbens
b579ec7bbd Merge branch 'master' of github.com:trouble/payload 2021-01-05 14:26:17 -05:00
Dan Ribbens
9703c34f4d docs: payload license documentation 2021-01-05 14:26:08 -05:00
James
d3dd1844dc 0.1.135 2021-01-05 14:21:13 -05:00
James
54405732c9 0.1.134 2021-01-05 14:18:56 -05:00
James
6bf141c6d4 fix: updates payload-config path within webpack 2021-01-05 14:18:50 -05:00
James
3be1cf16ef 0.1.133 2021-01-05 14:11:53 -05:00
James
0cd585d09b 0.1.132 2021-01-05 14:10:21 -05:00
James
c0636dfe22 fix: renames webpack config alias 2021-01-05 14:10:12 -05:00
James
0367ce5d5a 0.1.131 2021-01-05 13:47:20 -05:00
James
38bc2e68fe 0.1.130 2021-01-05 13:46:28 -05:00
James
b71483f557 chore: bumps config provider 2021-01-05 13:46:23 -05:00
James
3557480838 0.1.129 2021-01-05 13:44:12 -05:00
James
13cd1bd060 chore: adds default values for descructured props 2021-01-05 13:44:05 -05:00
James
ed24292f55 chore: references license 2021-01-05 13:38:45 -05:00
James
b58a441109 0.1.128 2021-01-05 13:28:17 -05:00
James
eb8b9e2542 references license 2021-01-05 13:28:08 -05:00
James
587a71c1b6 Merge branch 'master' of github.com:keen-studio/payload 2021-01-05 13:18:02 -05:00
James
06a722ffdb chore: updates all references from @payloadcms/payload to payload 2021-01-05 13:17:59 -05:00
Elliot DeNolf
e8ba315b20 chore: update readme 2021-01-05 13:09:30 -05:00
James
95180f4737 docs: uses live URLs 2021-01-05 12:38:26 -05:00
James
558e6839bc docs: readme 2021-01-05 12:38:20 -05:00
James
f52eb88b70 docs: adds access control args clarity 2021-01-04 21:24:34 -05:00
James
cab10e2028 docs: adds examples and descriptions to access control 2021-01-04 21:19:19 -05:00
James
6ee2a762e8 docs: deployment improvements 2021-01-04 18:55:57 -05:00
James
4d092ab9cb Merge branch 'master' of github.com:keen-studio/payload 2021-01-04 18:45:29 -05:00
James
da6e6c4441 docs: deployment 2021-01-04 18:45:26 -05:00
Elliot DeNolf
2f9b9931e4 docs: add globals access control 2021-01-04 17:00:55 -05:00
James
43af9146d8 docs: adds max login attempts stub to preventing-abuse 2021-01-04 16:54:00 -05:00
James
99b3499044 docs: renames security to preventing-abuse, misc updates 2021-01-04 16:10:47 -05:00
Elliot DeNolf
cef864a80e docs: add field access control and collection admin access control 2021-01-03 23:56:42 -05:00
James
44a4a99b92 docs: adds adminThumbnail to upload example 2021-01-03 12:41:41 -05:00
James
34c785557d docs: improves Admin 2021-01-03 12:40:13 -05:00
James
b83abf944b docs: finishes upload 2021-01-03 12:37:40 -05:00
James
85658c7017 docs: spelling, REST auth ops, Upload progress 2021-01-03 12:00:35 -05:00
James
a0bf503f88 fix: issues with select hasMany 2021-01-03 11:45:09 -05:00
James
87aaccac94 docs: Local API 2021-01-03 10:46:23 -05:00
James
d43ff8b4a7 feat: types this within crreate op 2021-01-03 09:57:54 -05:00
James
e093e06926 fix: removes old reliance on config.email 2021-01-03 09:53:32 -05:00
James
baecb27712 Merge branch 'feature/email-docs' of github.com:keen-studio/payload 2021-01-03 09:38:59 -05:00
Dan Ribbens
faec969752 fix: payload config remove types for email 2021-01-03 03:20:29 -05:00
Dan Ribbens
cf89d4cb56 fix: default config value for email removed as the property was moved out of config 2021-01-03 03:17:18 -05:00
Dan Ribbens
57d2c8602f fix: demo email start on payload init 2021-01-03 03:15:54 -05:00
Dan Ribbens
3233e903d9 docs: adds email documentation 2021-01-03 03:15:13 -05:00
Dan Ribbens
5d6a3bc833 refactor: email build changed to be more readable and work according to docs 2021-01-03 03:13:23 -05:00
Elliot DeNolf
5eca243af9 docs: rough collection access control 2021-01-03 00:14:41 -05:00
James
2683bec738 Merge branch 'master' of github.com:keen-studio/payload 2021-01-02 22:19:55 -05:00
James
0838b6837b docs: scaffolds access control 2021-01-02 22:19:51 -05:00
Elliot DeNolf
885c73c838 fix: reinstate explicit labels for AllFields collection 2021-01-02 22:07:30 -05:00
James
730d472008 docs: rest, pagination 2021-01-02 21:18:40 -05:00
James
7b11dd053b docs: adds rich text serialization 2021-01-02 20:31:51 -05:00
James
c85d72317c docs: queries 2021-01-02 20:31:43 -05:00
James
d76c1f862c docs: graphql 2021-01-02 19:25:00 -05:00
James
f1c5cfe1a5 docs: adapts hooks docs to new formatting 2021-01-02 18:28:11 -05:00
James
68e0e5cbdd Merge branch 'master' of github.com:keen-studio/payload 2021-01-02 16:28:11 -05:00
James
97ff9eeb1b docs: finishes authentication 2021-01-02 16:28:08 -05:00
Dan Ribbens
e8eabde889 chore: add license.md 2021-01-02 15:28:26 -05:00
James
7d05069f36 feat: allows for refresh operation to accept a deliberately specified token 2021-01-02 14:50:40 -05:00
James
4d871c27f6 fix: graphQL access 2021-01-02 14:21:21 -05:00
James
709cc9c294 fix: graphQL logout 2021-01-02 14:21:06 -05:00
James
cd9b360292 docs: removes unused files 2021-01-02 13:29:46 -05:00
James
1f6666785e docs: finishes auth config 2021-01-02 13:24:33 -05:00
James
53f8570a53 docs: auth config 2021-01-02 12:58:09 -05:00
James
094b0399cb docs: auth overview 2021-01-02 11:23:50 -05:00
James
fd917e6bae docs: Admin 2021-01-02 10:38:17 -05:00
James
b3c254e34f docs: fields overview, small fields adjustments 2020-12-31 14:01:28 -05:00
James
22a7ddfd28 docs: rich text 2020-12-31 13:18:34 -05:00
James
0eda6b5c47 docs: finishes individual field docs 2020-12-31 11:55:41 -05:00
James
cd0becb7ba docs: field types 2020-12-31 11:19:59 -05:00
James
19b92c4748 docs: orders fields 2020-12-31 09:58:08 -05:00
James
c572057706 fix: config validation of block imageURL 2020-12-31 09:53:19 -05:00
James
c86731aaf7 docs: array and blocks 2020-12-31 09:30:50 -05:00
James
ffa0ea4756 chore: better names block image types 2020-12-31 09:30:25 -05:00
James
0f7046b98e fix: improves edit view layout constraints 2020-12-30 19:44:55 -05:00
James
f582a254cd fix: adds default thumbnail size 2020-12-30 19:44:28 -05:00
James
e067fa12b2 fix: Edit view main / sidebar widths 2020-12-30 19:35:30 -05:00
James
a5310ac1b3 Merge branch 'master' of github.com:keen-studio/payload 2020-12-30 19:13:21 -05:00
James
fa4c9ba796 0.1.127 2020-12-30 19:13:03 -05:00
James
662839fb06 fix: converts class methods to arrow functions 2020-12-30 19:12:55 -05:00
Jarrod Flesch
d07259d0dc Merge branch 'master' of github.com:trouble/payload 2020-12-30 17:49:03 -05:00
Jarrod Flesch
4fa942f3a0 fix: removes delete and unlock from baseField type and schema 2020-12-30 17:48:52 -05:00
Jarrod Flesch
e2d0fc3e10 Merge branch 'master' of github.com:trouble/payload 2020-12-30 17:40:19 -05:00
Jarrod Flesch
5e0ece5d72 removes delete and unlock from baseField type and schema 2020-12-30 17:40:06 -05:00
James
6b5ab50f71 0.1.126 2020-12-30 15:50:50 -05:00
James
d7d906bc86 Merge branch 'master' of github.com:keen-studio/payload 2020-12-30 15:50:38 -05:00
James
8cb80cecf8 chore: bumps payload config provider 2020-12-30 15:50:32 -05:00
Jarrod Flesch
5823a864f9 fix: lowecases joi like everywhere else in payload 2020-12-30 15:30:34 -05:00
Jarrod Flesch
36d51de201 fix: adds delete and unlock to joi baseField schema 2020-12-30 14:59:54 -05:00
Jarrod Flesch
60c1d1d3d9 doc: stubs out all fields so docs are not broken 2020-12-30 13:47:28 -05:00
Jarrod Flesch
f0a45281b5 merges with master 2020-12-30 13:29:51 -05:00
Jarrod Flesch
86584900b2 doc: text fine tuning 2020-12-30 13:29:36 -05:00
James
a7603bcc6b 0.1.125 2020-12-30 12:19:41 -05:00
James
eeea06d6aa fix: removes prod source maps 2020-12-30 12:19:23 -05:00
Jarrod Flesch
e3c3516283 doc: adjusts concepts/depth 2020-12-30 12:12:19 -05:00
James
5a45e60a73 0.1.124 2020-12-30 12:08:49 -05:00
James
e2413baf10 docs: stubs fields 2020-12-30 12:08:39 -05:00
James
0c6a08da76 chore: bumps config-provider 2020-12-30 12:08:18 -05:00
Jarrod Flesch
8401400129 fix: webpack config override 2020-12-30 10:10:43 -05:00
James
e614a6fc70 docs: few fixes 2020-12-30 10:09:29 -05:00
Jarrod Flesch
5f302dd046 Merge branch 'master' of github.com:trouble/payload into fix/datePickerTypes 2020-12-30 09:51:04 -05:00
James
480bc0ad9d chore: moves webpack customization to admin config 2020-12-29 13:28:48 -05:00
James
7274b1692d docs: adds customizing css and webpack 2020-12-29 13:17:02 -05:00
Jarrod Flesch
e263a9c9d4 chore: removes blank line 2020-12-29 12:52:58 -05:00
Jarrod Flesch
34153dc85b Merge branch 'master' of github.com:trouble/payload into typescript/datePicker 2020-12-29 12:48:24 -05:00
Jarrod Flesch
5100fd35dc fix: updates typing on DatePicker component and joi schema 2020-12-29 12:41:15 -05:00
James
d10954b788 docs: customizing scss, express, localization 2020-12-29 11:37:47 -05:00
James
544a4dbd3a feat: allows for adding custom CSS in addition to SCSS overrides 2020-12-29 11:37:36 -05:00
James
c84bcde0a1 docs: localization 2020-12-29 09:12:12 -05:00
James
85a765959b docs: collection and global configs 2020-12-29 08:09:14 -05:00
James
3ce6a45121 chore: removes unknown key on date field schema 2020-12-28 17:40:42 -05:00
James
3248740f04 docs: progress to collection config 2020-12-28 17:40:21 -05:00
James
30e28603a7 Merge branch 'master' of github.com:keen-studio/payload 2020-12-28 17:36:55 -05:00
James
0c03c2e3af fix: type issues that arose from reorganizing certain config props 2020-12-28 17:36:43 -05:00
Jarrod Flesch
4e48a4ffc5 Merge pull request #472 from trouble/refactor/sectionTitle
simplifies SectionTitle, addresses #471
2020-12-28 17:23:12 -05:00
James
f65e91dc74 docs: further stubs out access control 2020-12-28 17:20:40 -05:00
James
6df3b381ef chore: better organizes collection preview 2020-12-28 17:20:29 -05:00
Jarrod Flesch
d849367a12 fixes fieldGutter #473 2020-12-28 17:17:32 -05:00
Jarrod Flesch
af4c6fb15a simplifies SectionTitle, addresses #471 2020-12-28 16:24:25 -05:00
James
2856e0213f docs: config, getting started, collections 2020-12-28 16:05:26 -05:00
James
4fbf8aa0bf chore: continues docs 2020-12-28 13:32:12 -05:00
James
24788b8282 chore: centralizes express config options 2020-12-28 13:32:05 -05:00
James
8090b2a23b fix: disables inline sourcemaps for admin dist 2020-12-28 13:31:37 -05:00
James
64cf32146a fix: disable requiring default props in eslint 2020-12-28 13:31:15 -05:00
James
15e6ee7dac 0.1.123 2020-12-27 21:53:03 -05:00
James
8bda6eaa76 fix: prod webpack publicPath 2020-12-27 21:52:55 -05:00
James
b8ad84c525 fix: allows config validation to accept esmodules as components 2020-12-27 21:47:09 -05:00
James
72b5817276 0.1.122 2020-12-27 21:24:07 -05:00
James
1fff7374d4 fix: safely accesses field permissions 2020-12-27 21:24:01 -05:00
James
fec718e9e5 feat: sends config through babel/register 2020-12-27 21:23:41 -05:00
James
efe0b40aca feat: splits tsconfig between admin and server 2020-12-27 21:02:20 -05:00
James
db135129d8 fix: improves field schema validation 2020-12-27 21:01:39 -05:00
James
b1a15f6e33 0.1.121 2020-12-27 15:22:52 -05:00
James
9037e6c64b 0.1.20 2020-12-27 15:22:02 -05:00
James
604922a26e feat: improves edit scroll UX in Account and Globals 2020-12-27 15:21:53 -05:00
James
0117f18eb1 fix: removes unnecessary meta defaults in admin config 2020-12-27 15:21:33 -05:00
James
a715a4206e feat: improves scrolling UX in Edit views 2020-12-27 15:16:14 -05:00
James
6e83edc988 fix: production webpack css 2020-12-27 15:15:46 -05:00
James
9f1ebaf850 0.1.19 2020-12-27 14:38:40 -05:00
James
8571dc3965 feat: flattens build into one command 2020-12-27 14:38:32 -05:00
James
5b8c721292 fix: copyfiles, autocomplete transition 2020-12-27 14:34:36 -05:00
James
e2248a066d 0.1.18 2020-12-27 14:03:41 -05:00
James
62dea6d52a exposes additional types 2020-12-27 14:03:29 -05:00
James
fe380bd943 0.1.17 2020-12-27 13:45:02 -05:00
James
b266ae1356 remedies ts error in me collection 2020-12-27 13:42:57 -05:00
James
4abcad67b7 0.1.16 2020-12-27 13:38:34 -05:00
James Mikrut
0243371c71 Merge pull request #469 from trouble/ts-final
Migrates to Typescript
2020-12-27 13:36:55 -05:00
James
15323a6b6d removes location state clear on route change 2020-12-27 13:31:39 -05:00
James
f5b9d32317 restricts ActionPanel to only show add button when max rows not met 2020-12-27 13:13:37 -05:00
James
71ed0ad0ca migrates object-to-formdata 2020-12-27 13:07:01 -05:00
James
b4fd2b1976 adds default value to block field schema validation 2020-12-27 13:06:53 -05:00
James
b6d2c95ee7 disables hover on read only DraggableSections 2020-12-27 13:06:34 -05:00
James
238232cf51 fixes hover states in read-only radio group 2020-12-27 12:38:05 -05:00
James
04cf39749b upgrades dependencies 2020-12-27 12:28:37 -05:00
James
c9616b01ac removes old code 2020-12-27 12:19:43 -05:00
James
dede06ad76 removes serverModules, removes publicENV and better structures webpack configs 2020-12-27 12:15:57 -05:00
James
843d65f494 removes PropTypes 2020-12-27 11:45:08 -05:00
James
58788c327f mobile improvements 2020-12-27 11:02:53 -05:00
James
0124ae8812 ensures returned documents from create / update do not include fallbacks 2020-12-26 21:13:07 -05:00
James
3d08222c29 resolves remaining type errors 2020-12-26 21:04:41 -05:00
James
f6c0251a6c types operations, GraphQL 2020-12-26 20:24:28 -05:00
James
cf32ee460c lays operation type pattern 2020-12-26 16:25:58 -05:00
James
569ce08174 further types to admin 2020-12-26 14:51:07 -05:00
James
e2d370a415 field typing changes due to useFieldType updates 2020-12-26 13:12:29 -05:00
James
152799ecc7 finishes admin field typing 2020-12-26 12:23:08 -05:00
James
087ac31533 removes _id from relationships 2020-12-24 12:24:58 -05:00
James
b184b26a4e types RichText 2020-12-24 12:15:00 -05:00
James
f86e90b072 revises Config type 2020-12-24 10:47:14 -05:00
James
be04310810 flattens dist folder 2020-12-24 10:28:41 -05:00
James
d510961f6c ensures relationship fields can be cleared 2020-12-24 09:57:41 -05:00
James
d29f6775a8 streamlines Select, ReactSelect, Relationship 2020-12-20 17:19:38 -05:00
James
7be836cced Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-12-20 15:17:36 -05:00
James
4528586849 typing progress, refactor Relationship 2020-12-20 15:17:33 -05:00
Elliot DeNolf
47e82cb069 lots of operation typing 2020-12-20 15:09:12 -05:00
Elliot DeNolf
d38c6f8118 buildSchema types and exclude tests from tsconfig 2020-12-20 11:42:36 -05:00
James
757c8647bf adds option type 2020-12-20 11:36:24 -05:00
James
ba6c1b9439 progress to field typing 2020-12-20 11:11:35 -05:00
James
ac92e1289b further typing 2020-12-20 09:13:25 -05:00
James
6a49bffa9a Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-12-18 07:56:52 -05:00
Elliot DeNolf
a95aada35a misc gql types 2020-12-12 22:50:43 -05:00
Elliot DeNolf
8fd430819b add more graphql schema typing 2020-12-09 11:02:37 -05:00
Elliot DeNolf
396760d523 More graphql typing 2020-12-09 09:35:08 -05:00
Elliot DeNolf
6ab15fce1c ci: use registry-url 2020-12-08 13:33:40 -05:00
Elliot DeNolf
81ca30c9d4 ci: try always-auth 2020-12-08 11:59:06 -05:00
Elliot DeNolf
a5085b6e56 ci: auth against npm 2020-12-08 11:52:36 -05:00
Elliot DeNolf
4cb8bbd2f4 type traverseFields and other misc 2020-12-08 11:36:00 -05:00
Elliot DeNolf
b9c597af92 add global request handler types 2020-12-03 15:00:40 -05:00
Elliot DeNolf
47b6bb683b docs(access): stub out access control configuration 2020-12-03 12:00:46 -05:00
Elliot DeNolf
d3df6c606c chore: add build:watch script 2020-12-03 11:50:39 -05:00
Elliot DeNolf
1cd578ef44 fix: handle access result gracefully 2020-12-03 11:50:08 -05:00
James
55dd4768b9 Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-12-03 10:32:32 -05:00
Elliot DeNolf
66946c8697 fix: undo property fix, field exists - bad typing 2020-12-02 21:50:54 -05:00
Elliot DeNolf
1e4e6e9619 more typing in src/fields 2020-12-02 21:36:40 -05:00
Elliot DeNolf
c97fb62228 fix basefield types 2020-12-02 17:03:20 -05:00
James
cd5a24e308 0.1.15 2020-12-02 16:33:43 -05:00
James
c17a03ef60 fixes schema validation for custom graphics 2020-12-02 16:33:38 -05:00
James
abfad8c088 0.1.14 2020-12-02 15:28:00 -05:00
James
82b4042b26 0.1.13 2020-12-02 15:24:26 -05:00
James
1129711f75 adds sort to local find operation 2020-12-02 15:24:14 -05:00
James
69582b2e8c 0.1.12 2020-12-02 10:35:47 -05:00
James
00821bf0a2 stubs dotenv for webpack 2020-12-02 10:35:38 -05:00
James
4a313ee7c3 Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-12-02 10:35:03 -05:00
Elliot DeNolf
85f3a8b038 test: ignore dist 2020-12-01 23:04:57 -05:00
Elliot DeNolf
5fe4cb9eee add missing operation typings 2020-12-01 23:04:31 -05:00
James
0e120093cf Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-12-01 17:35:13 -05:00
James
064ab8846d 0.1.11 2020-12-01 17:34:43 -05:00
James
1d5338a8dc fixes bugs with local payload 2020-12-01 17:34:38 -05:00
Elliot DeNolf
4ac08dac65 type some collection operations 2020-12-01 16:38:27 -05:00
James
41df1c447f 0.1.10 2020-12-01 16:17:52 -05:00
James
808a283f74 exports PayloadCollectionConfig type 2020-12-01 16:15:17 -05:00
Dan Ribbens
be69ff5849 Merge branch 'ts-final' of github.com:trouble/payload into ts-final 2020-12-01 11:47:24 -05:00
Dan Ribbens
9d94c509e7 bring back collection after error hook for restful calls 2020-12-01 11:47:07 -05:00
James
282f575cab further types to Elements 2020-12-01 10:48:08 -05:00
Dan Ribbens
6b61714d7e types for error handler 2020-12-01 09:46:57 -05:00
James
dc8ffa34e4 type progress to Elements 2020-12-01 08:04:31 -05:00
James
8c8c49c66d builds a type guard for determining if field has subfields 2020-12-01 08:04:25 -05:00
James
bb7c829c5e progress to typing Blocks and Arrays 2020-11-30 20:12:15 -05:00
James
6bf60ff5d6 Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-11-30 17:31:29 -05:00
James
100d1e7220 further types 2020-11-30 17:31:05 -05:00
Elliot DeNolf
c97732cef3 add some collection/graphql types 2020-11-30 15:11:38 -05:00
James
c398c8b2a2 further types 2020-11-30 14:41:53 -05:00
James
cee40169f3 renames tests to js 2020-11-30 14:36:08 -05:00
James
7d3b6d12e3 further types 2020-11-30 14:29:14 -05:00
James
98b62df792 further types 2020-11-30 14:16:55 -05:00
James
e2d9cd1eed Merge branch 'ts-final' of github.com:keen-studio/payload into admin-types 2020-11-30 11:40:15 -05:00
James
f873a84f08 begins form typing 2020-11-30 10:59:57 -05:00
Elliot DeNolf
c1b1b81774 add requesthandlers to bindings 2020-11-30 10:56:40 -05:00
Elliot DeNolf
7333cc25d8 fix CollectionConfig type, boolean unions will have been sanitized 2020-11-30 10:56:03 -05:00
Elliot DeNolf
32957833f3 add requestHandler types 2020-11-30 10:55:26 -05:00
James
20fabb81e8 further types 2020-11-30 08:47:58 -05:00
James
7644b031c1 further typing 2020-11-30 08:42:06 -05:00
James
dbc403319d instantiates auth forgot password 2020-11-29 20:46:10 -05:00
James
c1d025e241 better sanitization pattern 2020-11-29 20:38:10 -05:00
James
c3c3f3fc88 replaces sanitization 2020-11-29 20:08:06 -05:00
James
6f1d61aabc ensures loadConfig returns a full config 2020-11-29 17:55:45 -05:00
James
3d282d2523 revises payload.authenticate type 2020-11-29 17:52:17 -05:00
James
ba66a0e801 merge 2020-11-29 15:41:03 -05:00
James
0fcd3d8f28 further types 2020-11-29 15:40:11 -05:00
Dan Ribbens
ddda183090 merge ts-final 2020-11-29 15:39:54 -05:00
Dan Ribbens
f19fc9057d replace payloadconfig with config in places 2020-11-29 15:33:03 -05:00
James
17e4d78bdc further typing 2020-11-29 14:27:56 -05:00
James
9ef954f430 defines pattern for request handler types 2020-11-29 14:18:23 -05:00
James
767b68b0bd fixes tests 2020-11-29 12:41:13 -05:00
James
53d78e995b few type fixes 2020-11-29 11:42:34 -05:00
James
0119965287 fixes build script 2020-11-29 11:36:01 -05:00
James
45dc3cab11 sets defaults for auth and upload 2020-11-29 11:35:52 -05:00
James
73d27be947 fixes bug in RenderFields 2020-11-29 11:35:37 -05:00
James
a5bbb338b9 resets ts error truncation 2020-11-29 11:35:28 -05:00
James
fd7cd0324d validates field types 2020-11-28 17:34:32 -05:00
James
aa795d19d5 converts demo to ts 2020-11-28 16:07:54 -05:00
James
9019cc9101 merges and WIP - field types 2020-11-27 14:40:16 -05:00
James
cd64238a51 progress to joi validation 2020-11-27 13:05:22 -05:00
James
5ffa0ed6ee swaps out ajv for joi 2020-11-26 15:22:34 -05:00
Elliot DeNolf
1889f00f8f more field type adjustments 2020-11-26 11:44:14 -05:00
James
0e2fbe0e8f enables build w/ typescript, refines the way configs are found 2020-11-25 18:57:17 -05:00
Dan Ribbens
70a84d90ad cleanup in payload init 2020-11-25 17:36:51 -05:00
James
56072e952d 0.1.9 2020-11-25 15:14:18 -05:00
James
f88f482837 properly formats bin 2020-11-25 15:14:12 -05:00
James
ca55c4e55f 0.1.8 2020-11-25 15:11:07 -05:00
James
a00809db8e further types frontend 2020-11-25 15:10:59 -05:00
James
e930abe741 0.1.7 2020-11-25 13:43:05 -05:00
James
b584d22b3a adds bin executable 2020-11-25 13:43:01 -05:00
James
254524ab1b updates webpack 5 dependencies 2020-11-25 11:31:36 -05:00
James
472a6cb232 13639$ types 13639$ 2020-11-25 11:23:03 -05:00
James
ed8d7f2106 adds paths to local ts declarations 2020-11-25 10:50:35 -05:00
James
4239f8e592 Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-11-25 08:09:53 -05:00
James
55deb3f01b types hooks 2020-11-25 08:09:51 -05:00
Dan Ribbens
d09fba47f1 webpack config windows safe path names 2020-11-25 06:33:49 -05:00
James
2420969375 Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-11-24 21:04:29 -05:00
James
055ff455fe builds unlicensed route 2020-11-24 21:04:19 -05:00
James
f3be1fcc62 0.1.6 2020-11-24 20:05:37 -05:00
James
ec00edcdad merges admin-types and adds asset types 2020-11-24 20:05:29 -05:00
Elliot DeNolf
e36be704a5 add types for most of graphql 2020-11-24 20:03:41 -05:00
James
75e557b894 0.1.5 2020-11-24 19:40:30 -05:00
James
41a26289b3 0.1.4 2020-11-24 19:34:38 -05:00
James
c9cb1ea05c adds unlicensed view 2020-11-24 19:34:02 -05:00
James
b3f326fead 0.1.3 2020-11-24 18:38:37 -05:00
James
a1f4168d50 adds babel config to package 2020-11-24 18:38:31 -05:00
James
8d946f225e 0.1.2 2020-11-24 18:34:03 -05:00
James
26a01afa1a fixes access bug 2020-11-24 18:33:24 -05:00
James
35686a7dca adds more files to package 2020-11-24 18:33:03 -05:00
Jessica Boezwinkle
34942daf94 element typescript updates 2020-11-24 17:58:25 -05:00
James
0bdd159fb9 0.1.1 2020-11-24 14:03:50 -05:00
James
d6e7211539 0.1.0 2020-11-24 14:03:03 -05:00
James
713673bc42 bumps payload config provider 2020-11-24 14:02:56 -05:00
James
d75da16fef Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-11-24 12:53:11 -05:00
James
cfdacea210 changes access permissions structure to be more typescript-friendly 2020-11-24 12:53:09 -05:00
Elliot DeNolf
924eb1d0b5 fix(webpack): more require.resolves needed 2020-11-24 10:40:08 -05:00
Elliot DeNolf
6fcf4ebc48 add types for errors 2020-11-23 22:43:35 -05:00
Elliot DeNolf
badd59ac38 fix(webpack): use require.resolve for modules 2020-11-23 21:36:00 -05:00
Elliot DeNolf
5b6392009d add types for buildQuery 2020-11-23 20:56:36 -05:00
James
777a2292dc fixes bug in rate limit definitions 2020-11-23 20:36:41 -05:00
James
352f70a9e4 supports typescript configs 2020-11-23 20:36:28 -05:00
James
09f267c378 merges 2020-11-23 19:37:44 -05:00
James
c2d2702a59 - abstracts AuthProvider and ConfigProvider
- updates Webpack and React
- adds further typing
2020-11-23 19:29:11 -05:00
Elliot DeNolf
062771e0a7 type field validations 2020-11-23 19:25:05 -05:00
Jessica Boezwinkle
d2571fa798 elements to TS 2020-11-23 17:44:57 -05:00
Elliot DeNolf
eafc0876a1 type uploads and images 2020-11-23 13:55:39 -05:00
Jessica Boezwinkle
56ce92e012 Icons to TS 2020-11-23 13:32:12 -05:00
Elliot DeNolf
51958c25ac ci: use tsc-silent for pretest 2020-11-23 11:21:36 -05:00
Elliot DeNolf
8789dae155 fix: add missing webpack dep path-browserify 2020-11-23 10:32:09 -05:00
Elliot DeNolf
d10f3f140f add hook types 2020-11-23 10:23:04 -05:00
Elliot DeNolf
7670a23611 more types and intellisense comments 2020-11-22 18:29:27 -05:00
James
53811b2324 re-implements custom view in CustomComponents, types a few files 2020-11-22 13:41:44 -05:00
James
3344656e6a updates to webpack 5 2020-11-22 13:41:26 -05:00
Elliot DeNolf
e4eece0352 handle singular and plural slugs for auto-label 2020-11-22 08:24:42 -05:00
Dan Ribbens
2a4b821c34 merge ts-final 2020-11-22 01:35:16 -05:00
Dan Ribbens
4a4c4223e6 more typescript types 2020-11-22 01:30:38 -05:00
Elliot DeNolf
314ea43e6d revise field types and type buildSchema 2020-11-22 01:22:28 -05:00
Elliot DeNolf
fdbdf93250 add types for all field-types, and other type tweaks 2020-11-22 00:46:19 -05:00
Dan Ribbens
cb33417924 more typescript errors resolved 2020-11-22 00:01:47 -05:00
Dan Ribbens
cbf12524fe added types to basefields and collection sanitize 2020-11-21 23:07:26 -05:00
James
8b34cab19a Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-11-21 21:00:54 -05:00
James
05a99b5798 revises build script 2020-11-21 21:00:51 -05:00
Elliot DeNolf
f1a83de772 type out the majority of auth 2020-11-21 20:47:22 -05:00
Elliot DeNolf
eb3d299521 more typing 2020-11-21 20:46:02 -05:00
James
60afdd239c revises admin source maps 2020-11-21 20:38:27 -05:00
James
307840edd1 fixes webpack bugs 2020-11-21 20:12:45 -05:00
James
95b8df6d70 adds copyfiles 2020-11-21 18:52:15 -05:00
James
700f28c3ac adds copyfiles 2020-11-21 18:43:39 -05:00
James
1487c3ff16 updates main entrypoint, fixes bad path in /errrors 2020-11-21 18:35:33 -05:00
James
b94772bfcd begins typing admin, fixes editorconfig 2020-11-21 16:11:40 -05:00
James
44d79d2153 removes unused dependencies 2020-11-21 15:12:03 -05:00
James
09f3008569 passing tests 2020-11-21 14:56:49 -05:00
James
e5043e73e3 bumps secret to payload context 2020-11-21 14:34:38 -05:00
James
16d308f452 adds yarn build:tsc 2020-11-21 14:27:43 -05:00
James
3e9ad427ec enables typescript intellisense in buildConfig 2020-11-21 13:53:54 -05:00
James
16d0289c36 progress to buildConfig, splitting out type organization 2020-11-21 12:22:38 -05:00
James
894a400b86 client tests pass 2020-11-21 10:05:10 -05:00
James
9134b51985 merge 2020-11-21 10:03:18 -05:00
James
e00321a101 int tests pass 2020-11-21 10:02:46 -05:00
Elliot DeNolf
75d0b5bb50 add email typing and others 2020-11-21 06:28:07 -05:00
Elliot DeNolf
b774d09b4b type payload logger and format 2020-11-21 03:45:14 -05:00
Elliot DeNolf
a91451e946 chore(nodemon): watch ts files 2020-11-21 03:31:06 -05:00
Elliot DeNolf
983bf713b3 feat: add initial types 2020-11-21 03:30:47 -05:00
Elliot DeNolf
f0ac9d6935 fix conflicts 2020-11-21 02:11:20 -05:00
James
d2572ba4e4 everything works? 2020-11-20 17:12:39 -05:00
James
51307f29c5 fixes bugs with gql 2020-11-20 15:38:01 -05:00
Dan Ribbens
a608a799aa merge ts-final 2020-11-20 15:37:19 -05:00
Dan Ribbens
e7822f7a51 refactor ts graphql index 2020-11-20 15:36:04 -05:00
James
e3277cf120 Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-11-20 15:24:27 -05:00
James
2ffb2b5200 adds jest types 2020-11-20 15:24:14 -05:00
Dan Ribbens
18698a9f18 refactor graphql and utilities 2020-11-20 15:23:32 -05:00
James
95c96247d9 Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-11-20 15:15:26 -05:00
James
f2f65952b2 Merge branch 'ts-final' of github.com:keen-studio/payload into ts-final 2020-11-20 15:15:14 -05:00
Elliot DeNolf
afe5f16af0 convert some errors 2020-11-20 15:15:13 -05:00
James
6a7da1e603 converts auth and email 2020-11-20 15:15:10 -05:00
Elliot DeNolf
bc9adb9fe5 convert src/uploads 2020-11-20 15:10:11 -05:00
Elliot DeNolf
9e1153639e convert src/express and src/fields 2020-11-20 15:05:51 -05:00
Elliot DeNolf
59e5a73e49 convert src/collections 2020-11-20 14:54:47 -05:00
James
8d1856ae2d merges 2020-11-20 14:54:22 -05:00
James
1eeee4854a converts auth and email 2020-11-20 14:53:45 -05:00
Elliot DeNolf
3bea32883d more module conversion 2020-11-20 14:42:36 -05:00
Elliot DeNolf
4f2891836e fix conflicts 2020-11-20 14:42:05 -05:00
James
63e86c4147 further module conversion 2020-11-20 14:39:35 -05:00
James
dfc77f0a3f further module conversion 2020-11-20 14:34:32 -05:00
James
1aaed161eb converts modules 2020-11-20 14:29:49 -05:00
James
7d411622c6 progress to build 2020-11-20 14:21:48 -05:00
Elliot DeNolf
a106fa62fe reinstate all collections in config 2020-11-20 13:41:54 -05:00
Elliot DeNolf
551c249e39 refactor: migrate to typescript 2020-11-20 13:39:18 -05:00
Elliot DeNolf
38028dd36b fix conflicts 2020-11-20 12:02:31 -05:00
844 changed files with 18473 additions and 13845 deletions

View File

@@ -4,7 +4,7 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.{js,ts}]
[*.{js,ts,tsx}]
indent_style = space
indent_size = 2
@@ -15,3 +15,7 @@ indent_size = 2
[*.scss]
indent_style = space
indent_size = 2
[*.mdx]
indent_style = space
indent_size = 2

View File

@@ -1,19 +1,63 @@
module.exports = {
parser: 'babel-eslint',
extends: '@trbl',
ignorePatterns: [
'/**/*.d.ts'
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
},
plugins: [
'@typescript-eslint',
],
extends: [
'@trbl',
],
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
},
overrides: [
{
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',
],
},
],
}
},
],
rules: {
'import/no-unresolved': [
2,
"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-underscore-dangle': 'off',
'import/extensions': [
'error',
'ignorePackages',
{
ignore: [
'payload/config',
'payload/unsanitizedConfig',
],
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
},
],
'no-underscore-dangle': 'off',
},
};

View File

@@ -1,4 +1,4 @@
name: Node.js CI
name: build
on: [push]
@@ -15,6 +15,9 @@ jobs:
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:
@@ -25,6 +28,8 @@ jobs:
${{ runner.os }}-build-
${{ runner.os }}-
- run: yarn
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- run: yarn test:client
- run: yarn test:int # In-memory db + api tests
env:

49
.vscode/launch.json vendored
View File

@@ -23,37 +23,40 @@
"<node_internals>/**"
]
},
{
"name": "Debug Jest Test - Current File",
"type": "node",
"request": "launch",
"runtimeArgs": [
"--inspect-brk",
"${workspaceRoot}/node_modules/.bin/jest",
"${fileBasename}",
"--runInBand"
],
"env": {
"PAYLOAD_CONFIG_PATH": "demo/payload.config.js"
},
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"port": 9229,
"skipFiles": [
"<node_internals>/**"
]
},
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"env": {
"PAYLOAD_CONFIG_PATH": "demo/payload.config.js"
"PAYLOAD_CONFIG_PATH": "demo/payload.config.ts",
"BABEL_ENV": "development"
},
"program": "${workspaceFolder}/demo/server.js",
"program": "${workspaceFolder}/demo/index.js",
"skipFiles": [
"<node_internals>/**"
]
],
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/babel-node",
"runtimeArgs": [
"--nolazy"
],
},
{
"type": "node",
"request": "launch",
"name": "Launch Program - Production",
"env": {
"PAYLOAD_CONFIG_PATH": "demo/payload.config.ts",
"NODE_ENV": "production",
"BABEL_ENV": "development"
},
"program": "${workspaceFolder}/demo/index.js",
"skipFiles": [
"<node_internals>/**"
],
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/babel-node",
"runtimeArgs": [
"--nolazy"
],
},
{
"type": "chrome",

View File

@@ -1,21 +1,73 @@
# Payload
<h1 align="center">Payload</h1>
<p align="center">A self-hosted, JavaScript headless CMS & application framework built with Express, MongoDB and React.</p>
<p align="center">
<a href="https://github.com/payloadcms/payload/actions">
<img src="https://github.com/payloadcms/payload/workflows/build/badge.svg">
</a>
<a href="https://www.npmjs.com/package/payload">
<img alt="npm" src="https://img.shields.io/npm/v/payload">
</a>
</p>
Headless CMS and application framework
<a href="https://payloadcms.com">
<img src="https://payloadcms.com/images/admin.jpg" alt="Payload headless CMS Admin panel built with React" />
</a>
*TODO: More on why to use it and some features*
### Quick Start
```
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).
### Documentation
Check out the [Payload website](https://payloadcms.com/docs/getting-started/what-is-payload) to find in-depth documentation for everything that Payload offers.
### Features
- [GraphQL](https://payloadcms.com/docs/graphql/overview), [REST](https://payloadcms.com/docs/rest-api/overview), and [Local](https://payloadcms.com/docs/local-api/overview) APIs
- [Easily customizable ReactJS Admin](https://payloadcms.com/docs/admin/overview)
- [Fully self-hosted](https://payloadcms.com/docs/production/deployment)
- [Extensible Authentication](https://payloadcms.com/docs/authentication/overview)
- [Local file storage & upload](https://payloadcms.com/docs/upload/overview)
- [Field-based Localization](https://payloadcms.com/docs/configuration/localization)
- [Block-based Layout Builder](https://payloadcms.com/docs/fields/blocks)
- [Extensible SlateJS rich text editor](https://payloadcms.com/docs/fields/rich-text)
- [Array field type](https://payloadcms.com/docs/fields/array)
- [Field conditional logic](https://payloadcms.com/docs/fields/overview#conditional-logic)
- Extremely granular [Access Control](https://payloadcms.com/docs/access-control/overview)
- [Document and field-level hooks](https://payloadcms.com/docs/hooks/overview) for every action Payload provides
- Built with Typescript & very Typescript-friendly
- Intensely fast API
- Highly secure thanks to HTTP-only cookies, CSRF protection, and more
### Code-first
If you know JavaScript, you know Payload. Payload is a _code-first_ CMS, which allows us to do a lot of things right:
- Payload gives you everything you need, but then steps back and lets you build what you want in JavaScript or TypeScript - with no unnecessary complexity brought by GUIs. You'll understand how your CMS works, because you will have wrote it exactly how you want it.
- Bring your own Express server and do whatever you need on top of Payload. Payload doesn't impose anything on you or your app.
- Completely control the Admin panel by using your own React components. Swap out fields or even entire views with ease.
- Use your data however and wherever you need thanks to auto-generated, yet fully extensible REST, GraphQL and Local Node APIs.
### Free for development use
Payload is 100% free for use on local environments such as `localhost` and staging sites such as `staging.mycoolsite.com`. When it's time to go to production, Payload charges a low and flat fee that doesn't change whatsoever based on your usage.
## Installation
`yarn add @payloadcms/payload` or `npm install @payloadcms/payload`
Before beginning to work with Payload, make sure you have all of the [required software](https://payloadcms.com/docs/getting-started/installation).
## Usage
From there, the easiest way to get started with Payload is to use the `create-payload-app` package:
*TODO: Show basic usage and link to docs*
```
npx create-payload-app
```
## Contributing
*TODO: Create Contributing.md*
Alternatively, it only takes about five minutes to [write out your own app from scratch](https://payloadcms.com/docs/getting-started/installation#from-scratch).
## License
*TODO: Create License.md*
Find the Payload license [here](https://github.com/payloadcms/payload/blob/master/license.md).

1
auth.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export * from './dist/auth';

1
auth.js Normal file
View File

@@ -0,0 +1 @@
module.exports = require('./dist/auth');

View File

@@ -1,20 +1,3 @@
module.exports = {
presets: [
[
require.resolve('@babel/preset-env'),
{
targets: [
'defaults',
'not IE 11',
'not IE_Mob 11',
],
},
],
require.resolve('@babel/preset-react'),
],
plugins: [
require.resolve('@babel/plugin-transform-runtime'),
require.resolve('@babel/plugin-proposal-class-properties'),
require.resolve('@babel/plugin-proposal-optional-chaining'),
],
};
const config = require('./src/babel.config');
module.exports = config;

2
bin.js Executable file
View File

@@ -0,0 +1,2 @@
#!/usr/bin/env node
require('./dist/bin');

View File

@@ -1,6 +1,6 @@
export {
useForm,
useFormFields,
useWatchForm,
useFormSubmitted,
useFormProcessing,
useFormModified,

2
config.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
export { buildConfig } from './dist/config/build';
export * from './dist/config/types';

1
config.js Normal file
View File

@@ -0,0 +1 @@
exports.buildConfig = require('./dist/config/build').buildConfig;

View File

@@ -6,11 +6,7 @@
*/
const checkRole = (allRoles, user) => {
if (user) {
if (allRoles.some((role) => {
return user.roles && user.roles.some((individualRole) => {
return individualRole === role;
});
})) {
if (allRoles.some((role) => user.roles && user.roles.some((individualRole) => individualRole === role))) {
return true;
}
}
@@ -18,4 +14,4 @@ const checkRole = (allRoles, user) => {
return false;
};
module.exports = checkRole;
export default checkRole;

View File

@@ -1,4 +1,4 @@
module.exports = [
export default [
'admin',
'editor',
'moderator',

View File

@@ -1,4 +1,6 @@
module.exports = {
import { Block } from '../../src/fields/config/types';
const CTA: Block = {
slug: 'cta',
labels: {
singular: 'Call to Action',
@@ -16,8 +18,9 @@ module.exports = {
name: 'url',
label: 'URL',
type: 'text',
height: 100,
required: true,
},
],
};
export default CTA;

View File

@@ -1,4 +1,6 @@
module.exports = {
import { Block } from '../../src/fields/config/types';
const Email: Block = {
slug: 'email',
labels: {
singular: 'Email',
@@ -9,8 +11,9 @@ module.exports = {
name: 'testEmail',
label: 'Test Email Field',
type: 'email',
maxLength: 100,
required: true,
},
],
};
export default Email;

View File

@@ -1,4 +1,6 @@
module.exports = {
import { Block } from '../../src/fields/config/types';
const NumberBlock: Block = {
slug: 'number',
labels: {
singular: 'Number',
@@ -9,8 +11,10 @@ module.exports = {
name: 'testNumber',
label: 'Test Number Field',
type: 'number',
maxLength: 100,
max: 100,
required: true,
},
],
};
export default NumberBlock;

View File

@@ -1,5 +1,7 @@
module.exports = {
blockImage: '/static/assets/images/generic-block-image.svg',
import { Block } from '../../src/fields/config/types';
const Quote: Block = {
imageURL: '/static/assets/images/generic-block-image.svg',
slug: 'quote',
labels: {
singular: 'Quote',
@@ -17,7 +19,6 @@ module.exports = {
name: 'quote',
label: 'Quote',
type: 'textarea',
height: 100,
required: true,
},
{
@@ -29,3 +30,5 @@ module.exports = {
},
],
};
export default Quote;

View File

@@ -1,5 +0,0 @@
import React from 'react';
const Sidebar = () => <div className="sidebar">fake sidebar</div>
export default Sidebar;

View File

@@ -35,7 +35,7 @@ const insertButton = (editor, { href, label, style, newTab = false }) => {
Transforms.insertNodes(editor, nodes);
};
const ToolbarButton = ({ path }) => {
const ToolbarButton: React.FC = ({ path }) => {
const { open, closeAll } = useModal();
const editor = useSlate();

View File

@@ -5,7 +5,7 @@ import './index.scss';
const baseClass = 'rich-text-button';
const ButtonElement = ({ attributes, children, element }) => {
const ButtonElement: React.FC = ({ attributes, children, element }) => {
const { style = 'primary', label } = element;
return (

View File

@@ -1,4 +1,6 @@
const withButton = (incomingEditor) => {
import { Editor } from 'slate';
const withButton = (incomingEditor: Editor): Editor => {
const editor = incomingEditor;
const { isVoid } = editor;

View File

@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
const PurpleBackground = ({ attributes, children }) => (
const PurpleBackground: React.FC<any> = ({ attributes, children }) => (
<span
{...attributes}
style={{ backgroundColor: 'purple' }}

View File

@@ -1,8 +0,0 @@
import button from './Button';
import leaf from './Leaf';
export default {
name: 'purple-background',
button,
leaf,
};

View File

@@ -0,0 +1,8 @@
import Button from './Button';
import Leaf from './Leaf';
export default {
name: 'purple-background',
Button,
Leaf,
};

14
demo/client/index.html Normal file
View File

@@ -0,0 +1,14 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div id="app"></div>
<div id="portal"></div>
</body>
</html>

View File

@@ -1,12 +1,13 @@
const roles = require('../access/roles');
const checkRole = require('../access/checkRole');
import { PayloadCollectionConfig } from '../../src/collections/config/types';
import roles from '../access/roles';
import checkRole from '../access/checkRole';
const access = ({ req: { user } }) => {
const result = checkRole(['admin'], user);
return result;
};
module.exports = {
const Admin: PayloadCollectionConfig = {
slug: 'admins',
labels: {
singular: 'Admin',
@@ -28,7 +29,7 @@ module.exports = {
depth: 0,
cookies: {
secure: false,
sameSite: 'Lax',
sameSite: 'lax',
domain: undefined,
},
},
@@ -45,6 +46,7 @@ module.exports = {
},
{
name: 'apiKey',
type: 'text',
access: {
read: ({ req: { user } }) => {
if (checkRole(['admin'], user)) {
@@ -67,3 +69,5 @@ module.exports = {
useAsTitle: 'email',
},
};
export default Admin;

View File

@@ -1,10 +1,11 @@
const checkRole = require('../access/checkRole');
const Email = require('../blocks/Email');
const Quote = require('../blocks/Quote');
const NumberBlock = require('../blocks/Number');
const CallToAction = require('../blocks/CallToAction');
import { PayloadCollectionConfig } from '../../src/collections/config/types';
import checkRole from '../access/checkRole';
import Email from '../blocks/Email';
import Quote from '../blocks/Quote';
import NumberBlock from '../blocks/Number';
import CallToAction from '../blocks/CallToAction';
const AllFields = {
const AllFields: PayloadCollectionConfig = {
slug: 'all-fields',
labels: {
singular: 'All Fields',
@@ -12,14 +13,13 @@ const AllFields = {
},
admin: {
useAsTitle: 'text',
disableScrollOnSuccess: true,
},
preview: (doc, token) => {
if (doc && doc.text) {
return `http://localhost:3000/previewable-posts/${doc.text.value}?preview=true&token=${token}`;
}
preview: (doc, token) => {
if (doc && doc.text) {
return `http://localhost:3000/previewable-posts/${doc.text.value}?preview=true&token=${token}`;
}
return null;
return null;
},
},
access: {
read: () => true,
@@ -85,6 +85,37 @@ const AllFields = {
required: true,
hasMany: true,
},
{
name: 'dateFieldExample',
label: 'Day and Time',
type: 'date',
admin: {
date: {
timeIntervals: 30,
},
},
},
{
name: 'dayOnlyDateFieldExample',
label: 'Day Only',
type: 'date',
admin: {
date: {
pickerAppearance: 'dayOnly',
monthsToShow: 2,
},
},
},
{
name: 'timeOnlyDateFieldExample',
label: 'Time Only',
type: 'date',
admin: {
date: {
pickerAppearance: 'timeOnly',
},
},
},
{
name: 'radioGroupExample',
label: 'Radio Group Example',
@@ -101,6 +132,9 @@ const AllFields = {
}],
defaultValue: 'option-2',
required: true,
admin: {
readOnly: true,
},
},
{
type: 'row',
@@ -189,10 +223,6 @@ const AllFields = {
{
type: 'blocks',
label: 'Blocks Content',
labels: {
singular: 'Block',
plural: 'Blocks',
},
name: 'blocks',
minRows: 2,
blocks: [Email, NumberBlock, Quote, CallToAction],
@@ -272,4 +302,4 @@ const AllFields = {
timestamps: true,
};
module.exports = AllFields;
export default AllFields;

View File

@@ -0,0 +1,12 @@
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const AutoLabel: PayloadCollectionConfig = {
slug: 'auto-label',
fields: [{
name: 'text',
type: 'text',
label: 'Text',
}],
};
export default AutoLabel;

View File

@@ -1,9 +1,10 @@
const Email = require('../blocks/Email');
const Quote = require('../blocks/Quote');
const NumberBlock = require('../blocks/Number');
const CallToAction = require('../blocks/CallToAction');
import { PayloadCollectionConfig } from '../../src/collections/config/types';
import Email from '../blocks/Email';
import Quote from '../blocks/Quote';
import NumberBlock from '../blocks/Number';
import CallToAction from '../blocks/CallToAction';
module.exports = {
const Blocks: PayloadCollectionConfig = {
slug: 'blocks',
labels: {
singular: 'Blocks',
@@ -38,3 +39,5 @@ module.exports = {
},
],
};
export default Blocks;

View File

@@ -1,4 +1,6 @@
const Code = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const Code: PayloadCollectionConfig = {
slug: 'code',
labels: {
singular: 'Code',
@@ -17,4 +19,4 @@ const Code = {
],
};
module.exports = Code;
export default Code;

View File

@@ -1,4 +1,6 @@
const Conditions = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const Conditions: PayloadCollectionConfig = {
slug: 'conditions',
labels: {
singular: 'Conditions',
@@ -50,4 +52,4 @@ const Conditions = {
],
};
module.exports = Conditions;
export default Conditions;

View File

@@ -1,5 +0,0 @@
import React from 'react';
const Cell = () => <div className="description">fake description cell</div>;
export default Cell;

View File

@@ -0,0 +1,5 @@
import React from 'react';
const Cell: React.FC = () => <div className="description">fake description cell</div>;
export default Cell;

View File

@@ -1,5 +0,0 @@
import React from 'react';
const Description = () => <div className="description">fake description field</div>;
export default Description;

View File

@@ -0,0 +1,5 @@
import React from 'react';
const Description: React.FC = () => <div className="description">fake description field</div>;
export default Description;

View File

@@ -1,9 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Props } from './types';
import './index.scss';
const Filter = ({ onChange, value }) => (
const Filter: React.FC<Props> = ({ onChange, value }) => (
<input
className="custom-description-filter"
type="text"
@@ -12,13 +12,4 @@ const Filter = ({ onChange, value }) => (
/>
);
Filter.defaultProps = {
value: '',
};
Filter.propTypes = {
onChange: PropTypes.func.isRequired,
value: PropTypes.string,
};
export default Filter;

View File

@@ -0,0 +1,4 @@
export type Props = {
value?: string
onChange?: (value: string) => void
}

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Group } from '../../../../../../../components/forms';
const CustomGroup = (props) => (
const CustomGroup: React.FC = (props) => (
<div className="custom-group">
<Group {...props} />
</div>

View File

@@ -1,10 +1,9 @@
import React from 'react';
import PropTypes from 'prop-types';
import DefaultList from '../../../../../../src/admin/components/views/collections/List/Default';
import './index.scss';
const CustomListView = (props) => (
const CustomListView: React.FC = (props) => (
<div className="custom-list">
<p>This is a custom Pages list view</p>
<p>Sup</p>
@@ -12,12 +11,4 @@ const CustomListView = (props) => (
</div>
);
CustomListView.propTypes = {
collection: PropTypes.shape({
labels: PropTypes.shape({
plural: PropTypes.string,
}),
}).isRequired,
};
export default CustomListView;

View File

@@ -1,13 +1,14 @@
const DescriptionField = require('./components/fields/Description/Field').default;
const DescriptionCell = require('./components/fields/Description/Cell').default;
const DescriptionFilter = require('./components/fields/Description/Filter').default;
const NestedArrayField = require('./components/fields/NestedArrayCustomField/Field').default;
const GroupField = require('./components/fields/Group/Field').default;
const NestedGroupField = require('./components/fields/NestedGroupCustomField/Field').default;
const NestedText1Field = require('./components/fields/NestedText1/Field').default;
const ListView = require('./components/views/List').default;
import { PayloadCollectionConfig } from '../../../src/collections/config/types';
import DescriptionField from './components/fields/Description/Field';
import DescriptionCell from './components/fields/Description/Cell';
import DescriptionFilter from './components/fields/Description/Filter';
import NestedArrayField from './components/fields/NestedArrayCustomField/Field';
import GroupField from './components/fields/Group/Field';
import NestedGroupField from './components/fields/NestedGroupCustomField/Field';
import NestedText1Field from './components/fields/NestedText1/Field';
import ListView from './components/views/List';
module.exports = {
const CustomComponents: PayloadCollectionConfig = {
slug: 'custom-components',
labels: {
singular: 'Custom Component',
@@ -27,7 +28,6 @@ module.exports = {
name: 'description',
label: 'Description',
type: 'textarea',
height: 100,
required: true,
localized: true,
admin: {
@@ -107,3 +107,5 @@ module.exports = {
},
},
};
export default CustomComponents;

View File

@@ -1,272 +0,0 @@
const checkRole = require('../access/checkRole');
const Email = require('../blocks/Email');
const Quote = require('../blocks/Quote');
const NumberBlock = require('../blocks/Number');
const CallToAction = require('../blocks/CallToAction');
const DefaultValueTest = {
slug: 'default-value-test',
labels: {
singular: 'Default Value Test',
plural: 'Default Value Tests',
},
admin: {
useAsTitle: 'text',
},
preview: (doc, token) => {
if (doc && doc.text) {
return `http://localhost:3000/previewable-posts/${doc.text.value}?preview=true&token=${token}`;
}
return null;
},
access: {
read: () => true,
},
fields: [
{
name: 'text',
type: 'text',
label: 'Text',
defaultValue: 'Default Value',
unique: true,
access: {
create: ({ req: { user } }) => checkRole(['admin'], user),
update: ({ req: { user } }) => checkRole(['admin'], user),
read: ({ req: { user } }) => Boolean(user),
},
},
{
name: 'image',
type: 'upload',
label: 'Image',
relationTo: 'media',
},
{
name: 'select',
label: 'Select',
type: 'select',
options: [{
value: 'option-1',
label: 'Option 1 Label',
}, {
value: 'option-2',
label: 'Option 2 Label',
}, {
value: 'option-3',
label: 'Option 3 Label',
}, {
value: 'option-4',
label: 'Option 4 Label',
}],
defaultValue: 'option-1',
},
{
name: 'selectMany',
label: 'Select w/ hasMany',
type: 'select',
options: [{
value: 'option-1',
label: 'Option 1 Label',
}, {
value: 'option-2',
label: 'Option 2 Label',
}, {
value: 'option-3',
label: 'Option 3 Label',
}, {
value: 'option-4',
label: 'Option 4 Label',
}],
defaultValue: ['option-1', 'option-4'],
hasMany: true,
},
{
name: 'radioGroupExample',
label: 'Radio Group Example',
type: 'radio',
options: [{
value: 'option-1',
label: 'Options 1 Label',
}, {
value: 'option-2',
label: 'Option 2 Label',
}, {
value: 'option-3',
label: 'Option 3 Label',
}],
defaultValue: 'option-2',
},
{
type: 'row',
fields: [
{
name: 'email',
label: 'Email',
type: 'email',
defaultValue: 'some@email.com',
}, {
name: 'number',
label: 'Number',
type: 'number',
defaultValue: 5,
},
],
},
{
type: 'group',
label: 'Group',
name: 'group',
fields: [
{
type: 'row',
fields: [
{
name: 'nestedText1',
label: 'Nested Text 1',
type: 'text',
defaultValue: 'nested default text 1',
}, {
name: 'nestedText2',
label: 'Nested Text 2',
type: 'text',
defaultValue: 'nested default text 2',
},
],
},
],
},
{
type: 'array',
label: 'Array',
name: 'array',
fields: [
{
type: 'row',
fields: [
{
name: 'arrayText1',
label: 'Array Text 1',
type: 'text',
admin: {
width: '50%',
},
defaultValue: 'default array text',
},
{
name: 'arrayText2',
label: 'Array Text 2',
type: 'text',
admin: {
width: '50%',
},
access: {
read: ({ req: { user } }) => Boolean(user),
update: ({ req: { user } }) => checkRole(['admin'], user),
},
},
],
},
{
type: 'text',
name: 'arrayText3',
label: 'Array Text 3',
admin: {
readOnly: true,
},
},
{
name: 'checkbox',
label: 'Checkbox',
type: 'checkbox',
default: true,
},
],
},
{
type: 'blocks',
label: 'Blocks Content',
name: 'blocks',
labels: {
singular: 'Block',
plural: 'Blocks',
},
blocks: [Email, NumberBlock, Quote, CallToAction],
localized: true,
},
{
type: 'relationship',
label: 'Relationship to One Collection',
name: 'relationship',
relationTo: 'conditions',
},
{
type: 'relationship',
label: 'Relationship hasMany',
name: 'relationshipHasMany',
relationTo: 'localized-posts',
hasMany: true,
},
{
type: 'relationship',
label: 'Relationship to Multiple Collections',
name: 'relationshipMultipleCollections',
relationTo: ['localized-posts', 'conditions'],
},
{
type: 'textarea',
label: 'Textarea',
name: 'textarea',
defaultValue: 'my textarea text',
},
{
name: 'slug',
type: 'text',
label: 'Slug',
admin: {
position: 'sidebar',
},
localized: true,
unique: true,
defaultValue: 'my-slug',
},
{
name: 'checkbox',
type: 'checkbox',
label: 'Checkbox',
admin: {
position: 'sidebar',
},
defaultValue: true,
},
{
name: 'richText',
type: 'richText',
label: 'Rich Text',
admin: {
elements: [
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'blockquote',
'ul',
'ol',
'link',
],
leaves: [
'bold',
'italic',
'underline',
'strikethrough',
],
},
// defaultValue: 'sooo riiiiiiiich',
},
],
timestamps: true,
};
module.exports = DefaultValueTest;

View File

@@ -1,10 +1,11 @@
const checkRole = require('../access/checkRole');
const Email = require('../blocks/Email');
const Quote = require('../blocks/Quote');
const NumberBlock = require('../blocks/Number');
const CallToAction = require('../blocks/CallToAction');
import { PayloadCollectionConfig } from '../../src/collections/config/types';
import checkRole from '../access/checkRole';
import Email from '../blocks/Email';
import Quote from '../blocks/Quote';
import NumberBlock from '../blocks/Number';
import CallToAction from '../blocks/CallToAction';
const DefaultValues = {
const DefaultValues: PayloadCollectionConfig = {
slug: 'default-values',
labels: {
singular: 'Default Value Test',
@@ -13,12 +14,6 @@ const DefaultValues = {
admin: {
useAsTitle: 'text',
},
preview: (doc, token) => {
if (doc && doc.text) {
return `http://localhost:3000/previewable-posts/${doc.text.value}?preview=true&token=${token}`;
}
return null;
},
access: {
read: () => true,
},
@@ -189,7 +184,7 @@ const DefaultValues = {
name: 'checkbox',
label: 'Checkbox',
type: 'checkbox',
default: true,
defaultValue: true,
},
],
},
@@ -203,6 +198,15 @@ const DefaultValues = {
},
blocks: [Email, NumberBlock, Quote, CallToAction],
localized: true,
admin: {
readOnly: true,
},
defaultValue: [
{
blockType: 'email',
testEmail: 'dev@payloadcms.com',
},
],
},
{
type: 'relationship',
@@ -280,4 +284,4 @@ const DefaultValues = {
],
timestamps: true,
};
module.exports = DefaultValues;
export default DefaultValues;

View File

@@ -1,4 +1,5 @@
const checkRole = require('../access/checkRole');
import { PayloadCollectionConfig } from '../../src/collections/config/types';
import checkRole from '../access/checkRole';
const access = ({ req: { user } }) => {
const isAdmin = checkRole(['admin'], user);
@@ -18,7 +19,7 @@ const access = ({ req: { user } }) => {
return false;
};
module.exports = {
const Files: PayloadCollectionConfig = {
slug: 'files',
labels: {
singular: 'File',
@@ -65,3 +66,5 @@ module.exports = {
useAsTitle: 'filename',
},
};
export default Files;

View File

@@ -1,4 +1,6 @@
const HiddenFields = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const HiddenFields: PayloadCollectionConfig = {
slug: 'hidden-fields',
labels: {
singular: 'Hidden Fields',
@@ -15,7 +17,9 @@ const HiddenFields = {
name: 'hiddenAdmin',
type: 'text',
label: 'Hidden on Admin',
hidden: 'admin',
admin: {
hidden: true,
},
required: true,
},
{
@@ -28,4 +32,4 @@ const HiddenFields = {
],
};
module.exports = HiddenFields;
export default HiddenFields;

View File

@@ -1,5 +1,8 @@
/* eslint-disable no-param-reassign */
module.exports = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const Hooks: PayloadCollectionConfig = {
slug: 'hooks',
labels: {
singular: 'Hook',
@@ -82,10 +85,11 @@ module.exports = {
name: 'description',
label: 'Description',
type: 'textarea',
height: 100,
required: true,
localized: true,
},
],
timestamps: true,
};
export default Hooks;

View File

@@ -1,4 +1,6 @@
const LocalOperations = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const LocalOperations: PayloadCollectionConfig = {
slug: 'local-operations',
labels: {
singular: 'Local Operation',
@@ -33,4 +35,4 @@ const LocalOperations = {
],
};
module.exports = LocalOperations;
export default LocalOperations;

View File

@@ -1,4 +1,6 @@
module.exports = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const LocalizedPosts: PayloadCollectionConfig = {
slug: 'localized-posts',
labels: {
singular: 'Localized Post',
@@ -16,13 +18,6 @@ module.exports = {
access: {
read: () => true,
},
preview: (doc, token) => {
if (doc && doc.title) {
return `http://localhost:3000/posts/${doc.title.value}?preview=true&token=${token}`;
}
return null;
},
fields: [
{
name: 'title',
@@ -43,7 +38,6 @@ module.exports = {
name: 'description',
label: 'Description',
type: 'textarea',
height: 100,
required: true,
localized: true,
},
@@ -57,3 +51,5 @@ module.exports = {
],
timestamps: true,
};
export default LocalizedPosts;

View File

@@ -1,4 +1,6 @@
const LocalizedArrays = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const LocalizedArrays: PayloadCollectionConfig = {
slug: 'localized-arrays',
labels: {
singular: 'Localized Array',
@@ -47,4 +49,4 @@ const LocalizedArrays = {
timestamps: true,
};
module.exports = LocalizedArrays;
export default LocalizedArrays;

View File

@@ -1,6 +1,6 @@
const checkRole = require('../access/checkRole');
import { PayloadCollectionConfig } from '../../src/collections/config/types';
module.exports = {
const Media: PayloadCollectionConfig = {
slug: 'media',
labels: {
singular: 'Media',
@@ -44,20 +44,8 @@ module.exports = {
required: true,
localized: true,
},
{
name: 'sizes',
fields: [
{
name: 'icon',
access: {
read: ({ req: { user } }) => {
const result = checkRole(['admin'], user);
return result;
},
},
},
],
},
],
timestamps: true,
};
export default Media;

View File

@@ -1,4 +1,6 @@
const NestedArray = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const NestedArray: PayloadCollectionConfig = {
slug: 'nested-arrays',
labels: {
singular: 'Nested Array',
@@ -23,7 +25,7 @@ const NestedArray = {
{
name: 'parentIdentifier',
label: 'Parent Identifier',
defaultValue: '',
defaultValue: ' ',
type: 'text',
required: true,
},
@@ -67,4 +69,4 @@ const NestedArray = {
timestamps: true,
};
module.exports = NestedArray;
export default NestedArray;

View File

@@ -1,4 +1,6 @@
module.exports = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const Preview: PayloadCollectionConfig = {
slug: 'previewable-post',
labels: {
singular: 'Previewable Post',
@@ -6,13 +8,13 @@ module.exports = {
},
admin: {
useAsTitle: 'title',
},
preview: (doc, token) => {
if (doc.title) {
return `http://localhost:3000/previewable-posts/${doc.title.value}?preview=true&token=${token}`;
}
preview: (doc, token) => {
if (doc.title) {
return `http://localhost:3000/previewable-posts/${doc.title.value}?preview=true&token=${token}`;
}
return null;
return null;
},
},
fields: [
{
@@ -27,3 +29,5 @@ module.exports = {
],
timestamps: true,
};
export default Preview;

View File

@@ -1,8 +1,9 @@
const checkRole = require('../access/checkRole');
import checkRole from '../access/checkRole';
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const access = ({ req: { user } }) => checkRole(['admin'], user);
module.exports = {
const PublicUsers: PayloadCollectionConfig = {
slug: 'public-users',
labels: {
singular: 'Public User',
@@ -35,10 +36,9 @@ module.exports = {
verify: true,
maxLoginAttempts: 5,
lockTime: 600 * 1000, // lock time in ms
generateVerificationUrl: (req, token) => `http://localhost:3000/api/verify?token=${token}`,
cookies: {
secure: process.env.NODE_ENV === 'production',
sameSite: 'Lax',
sameSite: 'lax',
domain: undefined,
},
},
@@ -57,3 +57,5 @@ module.exports = {
],
timestamps: true,
};
export default PublicUsers;

View File

@@ -1,20 +0,0 @@
module.exports = {
slug: 'relationship-a',
access: {
read: () => true,
},
labels: {
singular: 'Relationship A',
plural: 'Relationship A',
},
fields: [
{
name: 'post',
label: 'Post',
type: 'relationship',
relationTo: 'relationship-b',
localized: false,
},
],
timestamps: true,
};

View File

@@ -0,0 +1,40 @@
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const RelationshipA: PayloadCollectionConfig = {
slug: 'relationship-a',
access: {
read: () => true,
},
labels: {
singular: 'Relationship A',
plural: 'Relationship A',
},
fields: [
{
name: 'post',
label: 'Post',
type: 'relationship',
relationTo: 'relationship-b',
localized: true,
},
// {
// name: 'LocalizedPost',
// label: 'Localized Post',
// type: 'relationship',
// relationTo: 'localized-posts',
// hasMany: true,
// localized: true,
// },
{
name: 'postLocalizedMultiple',
label: 'Localized Post Multiple',
type: 'relationship',
relationTo: ['localized-posts', 'all-fields'],
hasMany: true,
localized: true,
},
],
timestamps: true,
};
export default RelationshipA;

View File

@@ -1,4 +1,6 @@
module.exports = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const RelationshipB: PayloadCollectionConfig = {
slug: 'relationship-b',
access: {
read: () => true,
@@ -19,3 +21,5 @@ module.exports = {
],
timestamps: true,
};
export default RelationshipB;

View File

@@ -1,7 +1,8 @@
const Button = require('../client/components/richText/elements/Button').default;
const PurpleBackground = require('../client/components/richText/leaves/PurpleBackground').default;
import Button from '../client/components/richText/elements/Button';
import PurpleBackground from '../client/components/richText/leaves/PurpleBackground';
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const RichText = {
const RichText: PayloadCollectionConfig = {
slug: 'rich-text',
labels: {
singular: 'Rich Text',
@@ -34,4 +35,4 @@ const RichText = {
],
};
module.exports = RichText;
export default RichText;

View File

@@ -1,4 +1,6 @@
const Select = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const Select: PayloadCollectionConfig = {
slug: 'select',
labels: {
singular: 'Select',
@@ -40,4 +42,4 @@ const Select = {
],
};
module.exports = Select;
export default Select;

View File

@@ -1,6 +1,7 @@
const checkRole = require('../access/checkRole');
import { PayloadCollectionConfig } from '../../src/collections/config/types';
import checkRole from '../access/checkRole';
module.exports = {
const StrictAccess: PayloadCollectionConfig = {
slug: 'strict-access',
labels: {
singular: 'Strict Access',
@@ -71,3 +72,5 @@ module.exports = {
],
timestamps: true,
};
export default StrictAccess;

View File

@@ -1,4 +1,6 @@
module.exports = {
import { PayloadCollectionConfig } from '../../src/collections/config/types';
const Validations: PayloadCollectionConfig = {
slug: 'validations',
labels: {
singular: 'Validation',
@@ -106,5 +108,6 @@ module.exports = {
],
},
],
timestamps: true,
};
export default Validations;

View File

@@ -1,8 +1,9 @@
const checkRole = require('../access/checkRole');
const Quote = require('../blocks/Quote');
const CallToAction = require('../blocks/CallToAction');
import checkRole from '../access/checkRole';
import Quote from '../blocks/Quote';
import CallToAction from '../blocks/CallToAction';
import { PayloadGlobalConfig } from '../../src/globals/config/types';
module.exports = {
export default {
slug: 'blocks-global',
label: 'Blocks Global',
access: {
@@ -18,4 +19,4 @@ module.exports = {
localized: true,
},
],
};
} as PayloadGlobalConfig;

View File

@@ -1,6 +1,7 @@
const checkRole = require('../access/checkRole');
import { PayloadGlobalConfig } from '../../src/globals/config/types';
import checkRole from '../access/checkRole';
module.exports = {
export default {
slug: 'global-with-access',
label: 'Global with Strict Access',
access: {
@@ -31,4 +32,4 @@ module.exports = {
required: true,
},
],
};
} as PayloadGlobalConfig;

View File

@@ -1,6 +1,7 @@
const checkRole = require('../access/checkRole');
import { PayloadGlobalConfig } from '../../src/globals/config/types';
import checkRole from '../access/checkRole';
module.exports = {
export default {
slug: 'navigation-array',
label: 'Navigation Array',
access: {
@@ -24,4 +25,4 @@ module.exports = {
}],
},
],
};
} as PayloadGlobalConfig;

14
demo/index.js Normal file
View File

@@ -0,0 +1,14 @@
const babelConfig = require('../babel.config');
require('@babel/register')({
...babelConfig,
extensions: ['.ts', '.tsx', '.js', '.jsx'],
env: {
development: {
sourceMaps: 'inline',
retainLines: true,
},
},
});
require('./server.ts');

View File

@@ -1,135 +0,0 @@
const Admin = require('./collections/Admin');
const AllFields = require('./collections/AllFields');
const Code = require('./collections/Code');
const Conditions = require('./collections/Conditions');
const CustomComponents = require('./collections/CustomComponents');
const File = require('./collections/File');
const Blocks = require('./collections/Blocks');
const DefaultValues = require('./collections/DefaultValues');
const HiddenFields = require('./collections/HiddenFields');
const Hooks = require('./collections/Hooks');
const Localized = require('./collections/Localized');
const LocalizedArray = require('./collections/LocalizedArray');
const LocalOperations = require('./collections/LocalOperations');
const Media = require('./collections/Media');
const NestedArrays = require('./collections/NestedArrays');
const Preview = require('./collections/Preview');
const PublicUsers = require('./collections/PublicUsers');
const RelationshipA = require('./collections/RelationshipA');
const RelationshipB = require('./collections/RelationshipB');
const RichText = require('./collections/RichText');
const Select = require('./collections/Select');
const StrictPolicies = require('./collections/StrictPolicies');
const Validations = require('./collections/Validations');
const BlocksGlobal = require('./globals/BlocksGlobal');
const NavigationArray = require('./globals/NavigationArray');
const GlobalWithStrictAccess = require('./globals/GlobalWithStrictAccess');
module.exports = {
admin: {
user: 'admins',
// indexHTML: 'custom-index.html',
meta: {
titleSuffix: '- Payload Demo',
// ogImage: '/static/find-image-here.jpg',
// favicon: '/img/whatever.png',
},
disable: false,
components: {
// Nav: () => (
// <div>Hello</div>
// ),
},
},
email: {
transport: 'mock',
fromName: 'Payload',
fromAddress: 'hello@payloadcms.com',
},
collections: [
Admin,
AllFields,
Code,
Conditions,
CustomComponents,
File,
DefaultValues,
Blocks,
HiddenFields,
Hooks,
Localized,
LocalizedArray,
LocalOperations,
Media,
NestedArrays,
Preview,
PublicUsers,
RelationshipA,
RelationshipB,
RichText,
Select,
StrictPolicies,
Validations,
],
globals: [
NavigationArray,
GlobalWithStrictAccess,
BlocksGlobal,
],
cookiePrefix: 'payload',
serverURL: 'http://localhost:3000',
cors: [
'http://localhost',
'http://localhost:3000',
'http://localhost:8080',
'http://localhost:8081',
],
csrf: [
'http://localhost:3000',
'https://other-app-here.com',
],
routes: {
api: '/api',
admin: '/admin',
graphQL: '/graphql',
graphQLPlayground: '/graphql-playground',
},
defaultDepth: 2,
compression: {},
paths: {
scss: 'client/scss/overrides.scss',
},
graphQL: {
maxComplexity: 1000,
mutations: {},
queries: {},
disablePlaygroundInProduction: true,
},
rateLimit: {
window: 15 * 60 * 100,
max: 100,
trustProxy: true,
skip: (req) => req.ip === '127.0.0.1',
},
maxDepth: 10,
localization: {
locales: [
'en',
'es',
],
defaultLocale: 'en',
fallback: true,
},
hooks: {
afterError: (err) => {
console.error('global error config handler', err);
},
},
upload: {
limits: {
fileSize: 10000000, // 10MB
},
},
webpack: (config) => config,
};

132
demo/payload.config.ts Normal file
View File

@@ -0,0 +1,132 @@
import path from 'path';
import { buildConfig } from '../src/config/build';
import Admin from './collections/Admin';
import AllFields from './collections/AllFields';
import AutoLabel from './collections/AutoLabel';
import Code from './collections/Code';
import Conditions from './collections/Conditions';
import CustomComponents from './collections/CustomComponents';
import File from './collections/File';
import Blocks from './collections/Blocks';
import DefaultValues from './collections/DefaultValues';
import HiddenFields from './collections/HiddenFields';
import Hooks from './collections/Hooks';
import Localized from './collections/Localized';
import LocalizedArray from './collections/LocalizedArray';
import LocalOperations from './collections/LocalOperations';
import Media from './collections/Media';
import NestedArrays from './collections/NestedArrays';
import Preview from './collections/Preview';
import PublicUsers from './collections/PublicUsers';
import RelationshipA from './collections/RelationshipA';
import RelationshipB from './collections/RelationshipB';
import RichText from './collections/RichText';
import Select from './collections/Select';
import StrictPolicies from './collections/StrictPolicies';
import Validations from './collections/Validations';
import BlocksGlobal from './globals/BlocksGlobal';
import NavigationArray from './globals/NavigationArray';
import GlobalWithStrictAccess from './globals/GlobalWithStrictAccess';
export default buildConfig({
cookiePrefix: 'payload',
serverURL: 'http://localhost:3000',
admin: {
user: 'admins',
indexHTML: path.resolve(__dirname, './client/index.html'),
// meta: {
// titleSuffix: '- Payload Demo',
// // ogImage: '/static/find-image-here.jpg',
// // favicon: '/img/whatever.png',
// },
disable: false,
scss: path.resolve(__dirname, './client/scss/overrides.scss'),
components: {
// Nav: () => (
// <div>Hello</div>
// ),
},
webpack: (config) => config,
},
collections: [
Admin,
AllFields,
AutoLabel,
Code,
Conditions,
CustomComponents,
File,
DefaultValues,
Blocks,
HiddenFields,
Hooks,
Localized,
LocalizedArray,
LocalOperations,
Media,
NestedArrays,
Preview,
PublicUsers,
RelationshipA,
RelationshipB,
RichText,
Select,
StrictPolicies,
Validations,
],
globals: [
NavigationArray,
GlobalWithStrictAccess,
BlocksGlobal,
],
cors: [
'http://localhost',
'http://localhost:3000',
'http://localhost:8080',
'http://localhost:8081',
],
csrf: [
'http://localhost:3000',
'https://other-app-here.com',
],
routes: {
api: '/api',
admin: '/admin',
graphQL: '/graphql',
graphQLPlayground: '/graphql-playground',
},
defaultDepth: 2,
graphQL: {
maxComplexity: 1000,
mutations: {}, // TODO: needs typing
queries: {}, // TODO: needs typing
disablePlaygroundInProduction: true,
},
// rateLimit: {
// window: 15 * 60 * 100,
// max: 100,
// trustProxy: true,
// skip: (req) => req.ip === '127.0.0.1',
// },
maxDepth: 10,
localization: {
locales: [
'en',
'es',
],
defaultLocale: 'en',
fallback: true,
},
hooks: {
afterError: (err) => {
console.error('global error config handler', err);
},
},
upload: {
limits: {
fileSize: 10000000, // 10MB
},
},
});

View File

@@ -1,8 +1,7 @@
/* eslint-disable no-console */
const express = require('express');
const path = require('path');
const payload = require('../src');
const logger = require('../src/utilities/logger')();
import express from 'express';
import path from 'path';
import payload from '../src';
const expressApp = express();
@@ -12,9 +11,12 @@ payload.init({
secret: 'SECRET_KEY',
mongoURL: 'mongodb://localhost/payload',
express: expressApp,
onInit: () => {
logger.info('Payload is initialized');
// console.log('Payload is initialized');
email: {
fromName: 'Payload',
fromAddress: 'hello@payloadcms.com',
},
onInit: (app) => {
app.logger.info('Payload Demo Initialized');
},
});
@@ -32,17 +34,6 @@ externalRouter.get('/', (req, res) => {
expressApp.use('/external-route', externalRouter);
exports.start = (cb) => {
const server = expressApp.listen(3000, async () => {
logger.info(`listening on ${3000}...`);
if (cb) cb();
});
return server;
};
// when server.js is launched directly
if (module.id === require.main.id) {
exports.start();
}
expressApp.listen(3000, async () => {
payload.logger.info(`listening on ${3000}...`);
});

View File

@@ -1,7 +0,0 @@
---
title: Access Control Config
label: Config
order: 10
---
Talk about how to write access control.

View File

@@ -1,7 +0,0 @@
---
title: Access Control Examples
label: Examples
order: 20
---
Show examples of how to write access control functions.

106
docs/Admin/components.mdx Normal file
View File

@@ -0,0 +1,106 @@
---
title: Swap in your own React components
label: Custom Components
order: 20
---
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.
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.
</Banner>
### Base Component Overrides
You can override a set of admin panel-wide components by providing a component to your base Payload config's `admin.components` property. The following options are available:
| Path | Description |
| --------------------- | -------------|
| **`Nav`** | Contains the sidebar and mobile Nav in its entirety. |
| **`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. |
| **`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. |
#### Full example:
`payload.config.js`
```js
import { buildConfig } from 'payload/config';
import { MyCustomNav, MyCustomLogo, MyCustomIcon, MyCustomAccount, MyCustomDashboard } from './customComponents.js';
export default buildConfig({
serverURL: 'http://localhost:3000',
admin: {
components: {
Nav: MyCustomNav,
graphics: {
Icon: MyCustomIcon,
Logo: MyCustomLogo,
},
views: {
Account: MyCustomAccount,
Dashboard: MyCustomDashboard,
}
}
}
})
```
*For more examples regarding how to customize components, look at the [demo app](https://github.com/payloadcms/payload/tree/master/demo).*
### Collections
You can override components on a Collection-by-Collection basis via each Collection's `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. |
### Globals
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. |
### Fields
All Payload fields support the ability to swap in your own React components. So, for example, instead of rendering a default Text input, you might need to render a color picker that provides the editor with a custom color picker interface to restrict the data entered to colors only.
<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.
</Banner>
**Fields support the following custom components:**
| Component | Description |
| --------------- | -------------|
| **`Filter`** | Override the text input that is presented in the `List` view when a user is filtering documents by the customized field. |
| **`Cell`** | Used in the `List` view's table to represent a table-based preview of the data stored in the field. |
| **`Field`** | Swap out the field itself within all `Edit` views. |
#### Sending and receiving values from the form
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 `useFieldType` hook as follows:
```js
import { useFieldType } from 'payload/components/forms';
const CustomTextField = ({ path }) => {
const { value, setValue } = useFieldType({ path });
return (
<input
onChange={(e) => setValue(e.target.value)}
value={value}
/>
)
}
```

View File

@@ -0,0 +1,67 @@
---
title: Customizing CSS & SCSS
label: Customizing CSS
order: 30
---
### Adding your own CSS / SCSS
You can add your own CSS by providing your base Payload config with a path to your own CSS or SCSS. Customize the styling of any part of the Payload dashboard as necessary.
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:**
```js
import { buildConfig } from 'payload/config';
import path from 'path';
const config = buildConfig({
serverURL: 'http://localhost:3000',
admin: {
css: path.resolve(__dirname, 'relative/path/to/stylesheet.scss'),
},
})
```
### Overriding SCSS variables
You can specify your own SCSS variable stylesheet that will allow for the override of Payload's base theme. This unlocks a ton of powerful theming and design options such as:
- Changing dashboard font families
- Modifying color palette
- Creating a dark theme
- Etc.
To do so, provide your base Payload config with a path to your own SCSS variable sheet.
**Example in payload.config.js:**
```js
import { buildConfig } from 'payload/config';
import path from 'path';
const config = buildConfig({
serverURL: 'http://localhost:3000',
admin: {
scss: path.resolve(__dirname, 'relative/path/to/vars.scss'),
},
})
```
**Example stylesheet override:**
```scss
$font-body: 'Papyrus';
$style-radius-m: 10px;
```
To reference all Sass variables that you can override, look at the default [SCSS variable stylesheet](https://github.com/payloadcms/payload/blob/master/src/admin/scss/vars.scss) within the Payload source code.
<Banner type="error">
<strong>Warning:</strong><br />
Only SCSS variables, mixins, functions, and extends are allowed in <strong>your SCSS overrides</strong>. Do not attempt to add any CSS declarations to this file, as this variable stylesheet is imported by many components throughout the Payload Admin panel and will result in your CSS definition(s) being duplicated many times. If you need to add real CSS definitions, see "Adding your own CSS / SCSS" the top of this page.
</Banner>

73
docs/Admin/overview.mdx Normal file
View File

@@ -0,0 +1,73 @@
---
title: The Admin Panel
label: Overview
order: 10
---
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.
<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.
</Banner>
![Payload's Admin panel built in React](https://payloadcms.com/images/admin.jpg)
*Screenshot of the Admin panel while editing a document from an example `AllFields` collection*
## 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) |
| `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). |
| `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) |
### The Admin User Collection
<Banner type="warning">
<strong>Important:</strong><br />
The Payload Admin panel can only be used by one Collection that supports <a href="/docs/authentication/">Authentication</a>.
</Banner>
To specify which Collection to use to log in to the Admin panel, pass the `admin` options a `user` key equal to the slug of the Collection that you'd like to use.
`payload.config.js`:
```js
import { buildConfig } from 'payload/config';
const config = buildConfig({
serverURL: 'http://localhost:3000',
admin: {
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.
**Note: you can use whatever Collection you'd like to access the Admin panel as long as the Collection supports Authentication. It doesn't need to be called `users`!**
For example, you may wish to have two Collections that both support `Authentication`:
- `admins` - meant to have a higher level of permissions to manage your data and access the Admin panel
- `customers` - meant for end users of your app that should not be allowed to log into the Admin panel
This is totally possible. For the above scenario, by specifying `admin: { user: 'admins' }`, your Payload Admin panel will use `admins`. Any users logged in as `customers` will not be able to log in via the Admin panel.
### Restricting user access
If you would like to restrict which users from a single Collection can access the Admin panel, you can use the `admin` access control function. [Click here](/docs/access-control/overview#admin) to learn more.
### License enforcement
Payload requires a valid license key to be used on production domains. You can use it as much as you'd like locally and on staging / UAT domains, but when you deploy to production, you'll need a license key to activate Payload's Admin panel. For more information, [click here](/docs/production/licensing).

173
docs/Admin/webpack.mdx Normal file
View File

@@ -0,0 +1,173 @@
---
title: Webpack
label: Webpack
order: 40
---
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.
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:
`payload.config.js`
```js
import { buildConfig } from 'payload/config';
export default buildConfig({
serverURL: 'http://localhost:3000',
admin: {
// highlight-start
webpack: (config) => {
// Do something with the config here
return config;
}
// highlight-end
}
})
```
### Aliasing server-only modules
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.
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`
```js
import createStripeSubscription from './hooks/createStripeSubscription';
const Subscription = {
slug: 'subscriptions',
hooks: {
beforeChange: [
createStripeSubscription,
]
}
fields: [
{
name: 'stripeSubscriptionID',
type: 'text',
required: true,
}
]
}
export default Subscription;
```
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');
export default buildConfig({
serverURL: 'http://localhost:3000',
collections: [
Subscription
],
admin: {
webpack: (config) => ({
...config,
resolve: {
...config.resolve,
alias: {
...config.resolve.alias,
[createStripeSubscriptionPath]: mockModulePath,
}
}
})
}
});
```
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.
## 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`.

View File

@@ -1,9 +0,0 @@
---
title: Accessing the User
label: Accessing the User
order: 40
---
Talk about how to access the User in custom code like hooks and access control. The User is on the req.
Show code examples.

View File

@@ -1,18 +0,0 @@
---
title: Authentication Config
label: Config
order: 10
---
Talk about how to configure authentication here.
Need to cover:
1. What collection to use for Admin panel and how there can only be one
1. Can have multiple auth collections
1. Token expiration
1. Email verification
1. Security (max login, lock time)
1. API keys
1. Depth to populate (performance impact)
1. Cookie settings (HTTP only discussion)

View File

@@ -1,43 +0,0 @@
---
title: Authentication Operations
label: Operations
order: 30
---
Talk about Auth operations here.
#### Me
Returns null or logged in user with token (useful for HTTP only)
#### Create operation modifications
Discuss if verification is required, etc etc
#### Init
Checks if there have been users created, checks Admin access
#### Login
HTTP-only cookies, token response. Discuss max login attempts
#### Logout
Removes HTTP-only cookie
#### Refresh
Refreshes token (requires valid token)
#### Register First User
Allows for anyone to register first user through UI
#### Forgot Password
Takes an email, sends email to that address. Discuss how to customize email
#### Access
Shows what the user can and cant do.

View File

@@ -1,7 +0,0 @@
---
title: Authentication Security
label: Security
order: 20
---
Talk about how Payload securely authenticates here.

View File

@@ -1,7 +0,0 @@
---
title: Using the Payload Auth Middleware
label: Using the Middleware
order: 50
---
Talk about how to use `payload.authenticate()` outside of Payload - show examples

View File

@@ -1,7 +0,0 @@
---
title: Custom Components
label: Overview
order: 10
---
Talk about how to build custom components. Show a list of all components that can be swapped out.

View File

@@ -1,7 +0,0 @@
---
title: Block Configs
label: Blocks
order: 40
---
Talk about how to write block configs here.

View File

@@ -1,7 +0,0 @@
---
title: Collection Configs
label: Collections
order: 20
---
Talk about how to write collection configs here.

View File

@@ -1,7 +0,0 @@
---
title: Global Configs
label: Globals
order: 30
---
Talk about how to write Globals configs here.

View File

@@ -1,7 +0,0 @@
---
title: The Main Config
label: Main
order: 10
---
Talk about how to write the main config here.

View File

@@ -1,298 +0,0 @@
---
title: Fields Overview
label: Overview
order: 10
---
<Banner type="info">
Fields are the building blocks of Payload. Collections and Globals both use Fields to define the shape of the data that they store. Payload offers a wide-array of field-types - both simple and complex.
</Banner>
## Field types
The `type` property on a field determines how the input will be rendered in the admin interface, what values it can accept, and how it is presented in the API.
```js
// Collection config
{
fields: [
{
name: 'my-field',
type: 'text', // highlight-line
label: 'Text',
}
]
}
```
### Simple Types
#### `text`
Plain text
#### `textarea`
Large blocks of text. No formatting.
#### `number`
Simple number input
#### `checkbox`
Boolean value that renders a checkbox
#### `date`
Renders date-picker
#### `email`
Email. Includes validation.
#### `code`
Monospaced code block
#### `richText`
Large formatted text. Includes rich text editor in the admin interface.
#### `select`
Renders a select box with any number of options
Options:
- `hasMany` - Allows for multiple options to be selected
```js
{
name: 'select',
label: 'Select',
type: 'select',
hasMany: true // Optional
options: [
{
value: 'option-1',
label: 'Option 1 Label',
}, {
value: 'option-2',
label: 'Option 2 Label',
},
],
},
```
#### `radio`
```js
{
name: 'radioGroup',
label: 'Radio Group Example',
type: 'radio',
options: [
{
value: 'option-1',
label: 'Options 1 Label',
},
{
value: 'option-2',
label: 'Option 2 Label',
},
],
},
```
### Complex Types
More powerful types but require more complex configuration
#### `upload`
Allows file and image upload. Useful for uploaded assets that can be referenced and re-used.
_TODO: Link to Upload configuration docs_
```js
{
name: 'image',
type: 'upload',
label: 'Image',
relationTo: 'media', // A collection with the `upload` properties configured
}
```
#### `row`
Rows allow for deeper nesting of values. They have their own set of fields.
```js
{
type: 'row',
fields: [
{
name: 'text',
label: 'Text',
type: 'text',
},
{
name: 'number',
label: 'Number',
type: 'number',
},
],
}
```
#### `array`
An array of the specified fields
Options:
- `minRows` - Minimum number of items required
- `maxRows` - Maximum number of items allowed
```js
{
name: 'array',
label: 'Array',
type: 'array',
minRows: 2, // Optional
maxRows: 4, // Optional
fields: [
{
name: 'textField',
label: 'Text Field',
type: 'text'
},
{
name: 'checkbox',
label: 'Checkbox',
type: 'checkbox'
}
]
}
```
#### `group`
A way to group related fields together. They will be rendered as a group in the admin interface.
```js
{
type: 'group',
label: 'Group',
name: 'group',
fields: [
{
type: 'row',
fields: [
{
name: 'nestedText1',
label: 'Nested Text 1',
type: 'text',
}, {
name: 'nestedText2',
label: 'Nested Text 2',
type: 'text',
},
],
},
],
},
```
#### `blocks`
Repeat any type of content any number of times
The `blocks` property takes an array of the allowed fields
_TODO: Link to more powerful and complex examples_
Options:
- `minRows` - Minimum number of items required
- `maxRows` - Maximum number of items allowed
```js
{
name: 'page',
type: 'blocks',
label: 'Page',
labels: {
singular: 'Page',
plural: 'Pages',
},
minRows: 2, // Optional
maxRows: 4, // Optional
blocks: [
{
slug: 'quote'
label: 'Quote',
type: 'text'
},
{
slug: 'testimonial',
label: 'Testimonial',
type: 'textarea'
},
{
slug: 'cta',
label: 'Call To Action',
type: 'text'
}
],
}
```
## Common Options
Most fields have the ability to use the following options
#### `defaultValue`
Initial value for the field
#### `required`
`true/false` value if the field is required to be populated
#### `localized`
`true/false` value to enable localization on the field
#### `admin`
The `admin` is an optional object with properties that specify how the field should be represented in the admin interface.
Properties:
- `position` - If specified as `sidebar`, the field will show in the admin interface's sidebar
- `width` - A percentage value ie. `50%` that will control the max-width of the field
- `readOnly` - `true/false` to set the field to read-only after it is saved
### Common Options Example
```js
// Collection config
{
fields: [
{
name: 'my-field',
type: 'text',
label: 'Text'
// highlight-start
admin: {
position: 'sidebar',
width: '50%',
readOnly: true,
}
// highlight-end
}
]
}
```

View File

@@ -1,11 +0,0 @@
---
title: GraphQL Overview
label: Overview
order: 10
---
Go over GraphQL configuration options.
- Naming conventions
- List of all queries and mutations w/ examples
- Context

View File

@@ -1,7 +0,0 @@
---
title: Adding your own Queries and Mutations
label: Custom Queries and Mutations
order: 20
---
Talk about how to add your own queries and mutations.

View File

@@ -1,253 +0,0 @@
---
title: Blog API From Scratch
label: Blog API
order: 20
---
In this guide, we will be creating a Blog API from scratch.
Prerequisites:
- Node
- npm or yarn
- MongoDB server
## Initial Setup
Let's get started by creating a project in a blank directory
```sh
yarn init -y
```
We then will install Payload and Express
```sh
yarn add payload express
```
### Server
Create a file named `server.js` in the root folder with the following contents
```js
const express = require('express');
const app = express();
app.listen(3000, async () => {
console.log('Express is now listening for incoming connections on port 3000.');
});
```
This is a basic Express application. Now let's pull in Payload and fill in the `init` parameters. `secret` and `mongoURL` can be changed as needed.
```js
const express = require('express');
const payload = require('payload'); // highlight-line
const app = express();
// highlight-start
payload.init({
secret: 'SECRET_KEY',
mongoURL: 'mongodb://localhost/payload-blog',
express: app,
})
// highlight-end
app.listen(3000, async () => {
console.log('Express is now listening for incoming connections on port 3000.');
});
```
### Payload Configuration
Next, let's get some basics put into our `payload.config.js` file
```js
module.exports = {
serverURL: 'http://localhost:3000',
collections: [],
}
```
#### Collections
We'll need a few different collections for our blog:
- Posts
- Categories
- Tags
The Posts will have the ability to have a single category and multiple tags
Let's create a `collections` directory and create a `.js` file for each
```js:title=Posts.js
module.exports = {
slug: 'posts',
labels: {
singular: 'Post',
plural: 'Posts',
},
admin: {
useAsTitle: 'title',
},
fields: [
{
name: 'title',
label: 'Title',
type: 'text'
},
{
name: 'content',
label: 'Content',
type: 'textarea',
},
{
name: 'category',
label: 'Category',
type: 'relationship',
relationTo: 'categories', // Categories Slug // highlight-line
},
{
name: 'tags',
label: 'Tags',
type: 'relationship',
relationTo: 'tags', // Tags Slug // highlight-line
hasMany: true, // Allow multiple tags per post
},
]
};
```
```js:title=Categories.js
module.exports = {
slug: 'categories',
labels: {
singular: 'Category',
plural: 'Categories',
},
admin: {
useAsTitle: 'name',
},
fields: [
{
name: 'name',
label: 'Name',
type: 'text',
},
],
};
```
```js:title=Tags.js
module.exports = {
slug: 'tags',
labels: {
singular: 'Tag',
plural: 'Tags',
},
admin: {
useAsTitle: 'name',
},
fields: [
{
name: 'name',
label: 'Name',
type: 'text',
},
],
};
```
Once these are created, we can pull them into the `collections` array in our `payload.config.js`
```js:title=payload.config.js
const Admins = require('./collections/Admins');
// highlight-start
const Posts = require('./collections/Posts');
const Categories = require('./collections/Categories');
const Tags = require('./collections/Tags');
// highlight-end
module.exports = {
serverURL: 'http://localhost:3000',
admin: {
user: 'admins',
},
collections: [
Admins,
// highlight-start
Posts,
Categories,
Tags
// highlight-end
],
}
```
### Create Content
**TODO: Should a guide like this use the Admin interface or `curl`?**
Navigate to the admin interface at `http://localhost:3000/admin` and create your first user.
Then create some Categories, Tags, and a Post.
Let's use `curl` to quickly create some data. The following commands will create 2 tags and 1 category.
```sh
curl -H "Content-Type: application/json" -X POST -d '{"name": "JavaScript"}' http://localhost:3000/api/tags
curl -H "Content-Type: application/json" -X POST -d '{"name": "TypeScript"}' http://localhost:3000/api/tags
curl -H "Content-Type: application/json" -X POST -d '{"name": "Code"}' http://localhost:3000/api/categories
```
We'll then make a request to create a Post, this will inclue a relationship to the category and tags created previously.
TODO: Somehow retrieve tag and category IDs then include them in a request to create a Post
Once complete, navigate to `http://localhost:3000/api/posts`, and you should see something similar to the following:
```js
{
"docs": [
{
"tags": [
{
"name": "TypeScript",
"createdAt": "2020-11-13T11:48:05.993Z",
"updatedAt": "2020-11-13T11:48:05.993Z",
"id": "5fae72758315da656fb3a8f0"
},
{
"name": "JavaScript",
"createdAt": "2020-11-13T11:48:00.064Z",
"updatedAt": "2020-11-13T11:48:00.064Z",
"id": "5fae72708315da656fb3a8ef"
}
],
"title": "My Title",
"content": "This is some content",
"category": {
"name": "Code",
"createdAt": "2020-11-13T11:48:10.351Z",
"updatedAt": "2020-11-13T11:48:36.358Z",
"id": "5fae727a8315da656fb3a8f1"
},
"createdAt": "2020-11-13T11:50:14.312Z",
"updatedAt": "2020-11-13T11:50:14.312Z",
"id": "5fae72f68e314b67609e05d1"
}
],
"totalDocs": 1,
"limit": 10,
"totalPages": 1,
"page": 1,
"pagingCounter": 1,
"hasPrevPage": false,
"hasNextPage": false,
"prevPage": null,
"nextPage": null
}
```

View File

@@ -1,7 +0,0 @@
---
title: Configure Email
label: Configure Email
order: 30
---
TODO: Configure SendGrid or similar

View File

@@ -1,320 +0,0 @@
---
title: Hooks Config
label: Config
order: 10
---
<Banner type="info">
Hooks allow intervention before or after any internal operation.
Payload has extensive support for hooks, at both the document-level and field-level.
</Banner>
## Hook Types
- [Collection Hooks](#collection-hooks)
- [Field Hooks](#field-hooks)
- [Error Hook](#error-hook)
## Collection Hooks
Collection can be executed at any point in the modification or retrieval of a collection.
Collection Hooks available:
_TODO: Fix anchor links_
- [beforeOperation](#beforeOperation)
- [beforeValidate](#beforeValidate)
- [beforeChange](#beforeChange)
- [afterChange](#afterChange)
- [beforeRead](#beforeRead)
- [afterRead](#afterRead)
- [beforeDelete](#beforeDelete)
- [afterDelete](#afterDelete)
### Usage
Configuration of collection hooks is done under a collection config in `payload.config.js`. They can either be created in-line or required from a separate file. Each hook is an array of functions to be run.
_TODO: Talk about async vs synchronous and concurrency_
```js
// Collection config
module.exports = {
slug: 'public-user',
fields: [
{ name: 'name', label: 'Name', type: 'text'},
]
hooks: {
// Before All Operations
beforeOperation: [(args) => {...}],
// Create and Update Operations
beforeValidate: [(args) => {...}],
beforeChange: [(args) => {...}],
afterChange: [(args) => {...}],
// Read Operations
beforeRead: [(args) => {...}],
afterRead: [(args) => {...}],
// Delete Operations
beforeDelete: [(args) => {...}],
afterDelete: [(args) => {...}],
// Login Operations
beforeLogin: [(args) => {...}],
afterLogin: [(args) => {...}],
// After error
afterError: [(args) => {...}],
}
}
```
Each hook is an array of functions allowing for multiple to be combined as desired.
Configuration of hooks should be done in your `payload.config.js`
#### beforeOperation
Runs before any operation
```js
const beforeOperationHook = ({
args, // Original arguments passed into the operation
operation, // name of the operation
}) => {...}
```
Available Operations: `create`, `read`, `update`, `delete`, `refresh`, `forgotPassword`
#### beforeValidate
Runs before the `create` and `update` operations.
```js
const beforeValidateHook = ({
data, // incoming document data
req, // full express request
operation, // name of the operation ie. 'create', 'update'
originalDoc, // original document
}) => {...}
```
#### beforeChange
Runs before `create` and `update` operations, after validation.
```js
const beforeChangeHook = ({
data, // incoming document data
req, // full express request
operation, // name of the operation ie. 'create', 'update'
originalDoc, // original document
}) => {...}
```
#### afterChange
Runs after `create` and `update` operations.
```js
const afterChangeHook = ({
doc, // full document data
req, // full express request
operation, // name of the operation ie. 'create', 'update'
}) => {...}
```
#### beforeRead
Runs before `find` and `findByID` operations.
```js
const beforeReadHook = ({
doc, // full document data
req, // full express request
query, // JSON formatted query
}) => {...}
```
#### afterRead
Runs after `find` and `findByID` operations.
```js
const afterReadHook = ({
doc, // full document data
req, // full express request
query, // JSON formatted query
}) => {...}
```
#### beforeDelete
Runs before `delete` operation
```js
const beforeDeleteHook = ({
req, // full express request
id, // id of document to delete
}) => {...}
```
#### afterDelete
Runs after `delete` operation
```js
const afterDeleteHook = ({
req, // full express request
id, // id of document to delete
doc, // deleted document
}) => {...}
```
#### beforeLogin
Runs before `login` operation
```js
const beforeLoginHook = ({
req, // full express request
}) => {...}
```
#### afterLogin
Runs after `login` operation
```js
const afterLoginHook = ({
req, // full express request
user, // user being logged in
token, // user token
}) => {...}
```
#### afterError
Runs after an error occurs
_TODO: example usage_
## Field Hooks
Field can be executed at any point in the modification or retrieval of a collection field.
Field Hooks available:
- `beforeValidate`
- `beforeChange`
- `afterChange`
- `afterRead`
### Usage
```js
// Collection config
module.exports = {
slug: 'public-user',
fields: [
{
name: 'name',
label: 'Name',
type: 'text',
hooks: {
// Create and Update Operations
beforeValidate: [(args) => {...}],
beforeChange: [(args) => {...}],
afterChange: [(args) => {...}],
// Read Operations
afterRead: [(args) => {...}],
}
},
],
}
```
#### beforeValidate
Runs before the `create` and `update` operations.
```js
const beforeValidateHook = ({
value, // field value
originalDoc, // original document
data, // incoming document data
operation, // name of the operation ie. 'create', 'update'
req, // full express request
}) => {...}
```
#### beforeChange
Runs before the `create` and `update` operations, after validation.
```js
const beforeChangeHook = ({
value, // field value
originalDoc, // original document
data, // incoming document data
operation, // name of the operation ie. 'create', 'update'
req, // full express request
}) => {...}
```
#### afterChange
Runs after `create` and `update` operations
```js
const afterChangeHook = ({
value, // field value
originalDoc, // original document
data, // incoming document data
operation, // name of the operation ie. 'create', 'update'
req, // full express request
}) => {...}
```
#### afterRead
Runs after result as been retrieved from database
```js
const beforeChangeHook = ({
value, // field value
originalDoc, // original document
data, // incoming document data
operation, // name of the operation ie. 'create', 'update'
req, // full express request
}) => {...}
```
## Hook Lifecycle
Hooks execute in the following order in relation to operations
`beforeOperation` is a special hook that runs _before all operations_.
### Create/Update Lifecycle
1. `beforeValidate` Field Hooks
2. `beforeValidate` Collection Hooks
3. Validate operation
4. `beforeChange` Field Hooks
5. `beforeChange` Collection Hooks
6. Create/Update against database
7. `afterChange` Field Hooks
8. `afterChange` Collection Hooks
### Find Lifecycle
1. `beforeRead` Collection Hooks
2. Find against database
3. `afterRead` Field Hooks
4. `afterRead` Collection Hooks

View File

@@ -1,64 +0,0 @@
---
title: Hooks Examples
label: Examples
order: 20
---
### Collection Hooks
#### Set createdBy and lastModifiedBy
```js
beforeChange: [
({ req, operation }) => {
if (req.user && req.body) {
if (operation === 'create') {
req.body.createdBy = req.user.id;
}
req.body.lastModifiedBy = req.user.id;
}
}
]
```
_NOTE: createdBy and lastModifiedBy must be fields on the collection_
#### Use Local Payload API
Queries a separate collection and appends to returned result
```js
afterRead: [
async ({ req, doc }) => {
const formattedData = { ...doc };
const posts = await req.payload.find({
collection: 'posts',
});
formattedData.posts = posts;
return formattedData;
},
],
```
#### Read Request Header
```js
beforeRead: [
({ req }) => {
if (req.headers.specialheader === 'special') {
// Do something...
}
},
],
```
### Field Hooks
#### Kebab-case Formatter
```js
beforeValidate: [
({ value }) => val.replace(/ /g, '-').toLowerCase();
]
```

View File

@@ -1,11 +0,0 @@
---
title: Server-Side Operations
label: Overview
order: 10
---
Talk about how to run server-side operations.
- Access control
- Providing a user

View File

@@ -1,11 +0,0 @@
---
title: Production Deployment
label: Deployment
order: 10
---
Talk about how to deploy Payload here.
- DigitalOcean
- If no file storage, Heroku
- If file storage, need Heroku extensions

View File

@@ -1,10 +0,0 @@
---
title: Production Security Measures
label: Security
order: 20
---
- Rate limiting
- GraphQL Complexity
- Limits
- Max Depth

View File

@@ -1,119 +0,0 @@
---
title: REST API Overview
label: Overview
order: 10
---
_TODO: Middleware_
<Banner type="info">
The Payload REST API is created using properties in each collection's config
</Banner>
Access to each collection is mounted on the API route using the collection's `slug` value. For example if a collection's slug is `users`, access to that collection will be mounted on `/api/users`.
Basic CRUD operations are automatically made available:
## Endpoints
### Collections
| Method | Path | Description |
| :------- | :---------------------- | :----------------------------------- |
| `GET` | `/api/{collection}` | Get all {collection} documents |
| `GET` | `/api/{collection}/:id` | Get a specific {collection} document |
| `POST` | `/api/{collection}` | Create a {collection} document |
| `DELETE` | `/api/{collection}/:id` | Delete a {collection} document |
| `PUT` | `/api/{collection}/:id` | Update a {collection} document |
### Globals
| Method | Path | Description |
| :------- | :---------------------- | :--------------------- |
| `GET` | `/api/globals/{global}` | Get {global} |
| `POST` | `/api/globals/{global}` | Create/Update {global} |
| `DELETE` | `/api/globals/{global}` | Delete a {global} |
NOTE: The `/api` prefix can be customized in the [main Payload configuration](../Configuration/main)
## Responses
### Collections
All collection queries return metadata
#### Example Response
Collection Query
```js
{
// Document Array // highlight-line
"docs": [
{
"title": "Page Title",
"description": "Some description text",
"priority": 1,
"createdAt": "2020-10-17T01:19:29.858Z",
"updatedAt": "2020-10-17T01:19:29.858Z",
"id": "5f8a46a1dd05db75c3c64760"
}
],
// Metadata // highlight-line
"totalDocs": 6,
"limit": 1,
"totalPages": 6,
"page": 1,
"pagingCounter": 1,
"hasPrevPage": false,
"hasNextPage": true,
"prevPage": null,
"nextPage": 2
}
```
Documents queried by id and globals will return a single JSON document, no metadata
| Property | Description |
| :------------ | :--------------------------------------------------------- |
| docs | Array of documents in the {collection} |
| totalDocs | Total available documents of {collection} |
| limit | Limit query parameter. Defaults to `10`, can be configured |
| totalPages | Total pages available, based upon the `limit` queried for |
| page | Current page |
| pagingCounter | `number` for the first doc on the current page |
| hasPrevPage | `true/false` if previous page exists |
| hasNextPage | `true/false` if next page exists |
| prevPage | `number` of previous page. `null` if doesn't exist. |
| nextPage | `number` of next page. `null` if doesn't exist. |
## Query Parameters
| param | description | example |
| :------ | :---------------------------------------------------------------------------------------- | :------------------------------- |
| `limit` | Limits the number of documents returned | `?limit=3` |
| `page` | Get specific page number | `?page=2` |
| `sort` | Sort on a specific field. Use field name for ascending. Prefix with `-` for descending | `?sort=age`, `?sort=-age` |
| `depth` | Controls how deep in JSON structure to return in the query. _Follows relationship fields_ | `?depth=3` |
| `where` | Exposes many logical operators. _In-depth documentation below_ | `?where[property][equals]=value` |
### Where
Query on specific collection field values
| operator | description | example |
| :------------------- | :-------------------------------------------------- | :------------------------------------------- |
| `equals` | | `?where[property][equals]=value` |
| `not_equals` | | `?where[property][not_equals]=value` |
| `greater_than` | | `?where[property][greater_than]=value` |
| `greater_than_equal` | | `?where[property][greater_than_equal]=value` |
| `less_than` | | `?where[property][less_than]=value` |
| `less_than_equal` | | `?where[property][less_than_equal]=value` |
| `like` | Partial match against property | `?where[property][like]=value` |
| `in` | Query for values in a comma-delimited list | `?where[property][in]=value1,value2` |
| `not_in` | Query for values _not in_ in a comma-delimited list | `?where[property][not_in]=value1,value2` |
| `exists` | Query for existence of a property | `?where[property][exists]=true` |
#### Complex Examples
_TODO: Complex Examples_

View File

@@ -1,16 +0,0 @@
---
title: Upload Config
label: Config
order: 10
---
Talk about how to configure uploads here.
Need to cover:
1. Can have multiple collections
1. Static directory
1. How to upload (multipart/form-data)
1. Uploading is REST-only
1. Access control
1. Image sizes

Some files were not shown because too many files have changed in this diff Show More