Compare commits
38 Commits
db-postgre
...
mongodb/nu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
501022991f | ||
|
|
53600c7352 | ||
|
|
76c1b23729 | ||
|
|
8104fac5ed | ||
|
|
59ef1263a5 | ||
|
|
813e3dbc98 | ||
|
|
12a23092e1 | ||
|
|
4a49beb552 | ||
|
|
80530c666e | ||
|
|
f53e2df951 | ||
|
|
db58e2bab2 | ||
|
|
d88e97e123 | ||
|
|
bb72e506e6 | ||
|
|
b1f727fd6a | ||
|
|
72af18229b | ||
|
|
af52b526c8 | ||
|
|
60525623bf | ||
|
|
0fba582926 | ||
|
|
5d1cad3adb | ||
|
|
e31f72da8e | ||
|
|
7aa058d604 | ||
|
|
64e80d242e | ||
|
|
e8f2ca484e | ||
|
|
ceca5c4e97 | ||
|
|
ee13736288 | ||
|
|
815bdfac0b | ||
|
|
7a7f0ed7e8 | ||
|
|
ad42d541b3 | ||
|
|
32ed95e1ee | ||
|
|
70e57fef18 | ||
|
|
0a07f607b9 | ||
|
|
3918fc7c21 | ||
|
|
13f71ac475 | ||
|
|
07720e777a | ||
|
|
efff47e400 | ||
|
|
453ac218ea | ||
|
|
d4b09bd9cd | ||
|
|
dd67e03fc1 |
13
.github/workflows/main.yml
vendored
13
.github/workflows/main.yml
vendored
@@ -85,7 +85,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
database: [ mongoose, postgres, postgres-uuid, supabase ]
|
||||
database: [mongoose, postgres, postgres-custom-schema, postgres-uuid, supabase]
|
||||
env:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
@@ -123,7 +123,7 @@ jobs:
|
||||
postgresql db: ${{ env.POSTGRES_DB }}
|
||||
postgresql user: ${{ env.POSTGRES_USER }}
|
||||
postgresql password: ${{ env.POSTGRES_PASSWORD }}
|
||||
if: matrix.database == 'postgres' || matrix.database == 'postgres-uuid'
|
||||
if: startsWith(matrix.database, 'postgres')
|
||||
|
||||
- name: Install Supabase CLI
|
||||
uses: supabase/setup-cli@v1
|
||||
@@ -139,14 +139,19 @@ jobs:
|
||||
|
||||
- name: Wait for PostgreSQL
|
||||
run: sleep 30
|
||||
if: matrix.database == 'postgres' || matrix.database == 'postgres-uuid'
|
||||
if: startsWith(matrix.database, 'postgres')
|
||||
|
||||
- name: Configure PostgreSQL
|
||||
run: |
|
||||
psql "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" -c "CREATE ROLE runner SUPERUSER LOGIN;"
|
||||
psql "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" -c "SELECT version();"
|
||||
echo "POSTGRES_URL=postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" >> $GITHUB_ENV
|
||||
if: matrix.database == 'postgres' || matrix.database == 'postgres-uuid'
|
||||
if: startsWith(matrix.database, 'postgres')
|
||||
|
||||
- name: Configure PostgreSQL with custom schema
|
||||
run: |
|
||||
psql "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost:5432/$POSTGRES_DB" -c "CREATE SCHEMA custom;"
|
||||
if: matrix.database == 'postgres-custom-schema'
|
||||
|
||||
- name: Configure Supabase
|
||||
run: |
|
||||
|
||||
30
CHANGELOG.md
30
CHANGELOG.md
@@ -1,10 +1,24 @@
|
||||
## [2.11.2](https://github.com/payloadcms/payload/compare/v2.11.1...v2.11.2) (2024-02-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **db-postgres:** configurable custom schema to use ([#5047](https://github.com/payloadcms/payload/issues/5047)) ([e8f2ca4](https://github.com/payloadcms/payload/commit/e8f2ca484ee56cd7767d5111e46ebd24752ff8de))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add Context Provider in EditMany Component ([#5005](https://github.com/payloadcms/payload/issues/5005)) ([70e57fe](https://github.com/payloadcms/payload/commit/70e57fef184f7fcf56344ea755465f246f2253a5))
|
||||
* **db-mongodb:** unique sparse for not required fields ([#5114](https://github.com/payloadcms/payload/issues/5114)) ([815bdfa](https://github.com/payloadcms/payload/commit/815bdfac0b0afbff2a20e54d5aee64b90f6b3a77))
|
||||
* **db-postgres:** set _parentID for array nested localized fields ([#5117](https://github.com/payloadcms/payload/issues/5117)) ([ceca5c4](https://github.com/payloadcms/payload/commit/ceca5c4e97f53f1346797a31b6abfc0375e98215))
|
||||
* disabling API Key does not remove the key ([#5145](https://github.com/payloadcms/payload/issues/5145)) ([7a7f0ed](https://github.com/payloadcms/payload/commit/7a7f0ed7e8132253be607c111c160163b84bd770))
|
||||
* handle thrown errors in config-level afterError hook ([#5147](https://github.com/payloadcms/payload/issues/5147)) ([32ed95e](https://github.com/payloadcms/payload/commit/32ed95e1ee87409db234f1b7bd6d2e462fd9ed5d))
|
||||
* only replace the drawer content with full edit component if it exists ([#5144](https://github.com/payloadcms/payload/issues/5144)) ([0a07f60](https://github.com/payloadcms/payload/commit/0a07f607b9fb1217ad956cd05b2a84a4042a19ca))
|
||||
* transaction error from access endpoint ([#5156](https://github.com/payloadcms/payload/issues/5156)) ([ad42d54](https://github.com/payloadcms/payload/commit/ad42d541b342ed56463b81cee6d6307df6f06d7f))
|
||||
|
||||
## [2.11.1](https://github.com/payloadcms/payload/compare/v2.11.0...v2.11.1) (2024-02-16)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **richtext-lexical:** Update lexical from 0.12.6 to 0.13.1, port over all useful changes from playground (#5066)
|
||||
|
||||
### Features
|
||||
|
||||
* **db-postgres:** adds idType to use uuid or serial id columns ([#3864](https://github.com/payloadcms/payload/issues/3864)) ([d6c2578](https://github.com/payloadcms/payload/commit/d6c25783cfa97983bf9db27ceb5ccd39a62c62f1))
|
||||
@@ -25,6 +39,14 @@
|
||||
* **richtext-lexical:** do not remove adjacent paragraph node when inserting certain nodes in empty editor ([#5061](https://github.com/payloadcms/payload/issues/5061)) ([6323965](https://github.com/payloadcms/payload/commit/6323965c652ea68dffeb716957b124d165b9ce96))
|
||||
* **uploads:** account for serverURL when retrieving external file ([#5102](https://github.com/payloadcms/payload/issues/5102)) ([25cee8b](https://github.com/payloadcms/payload/commit/25cee8bb102bf80b3a4bfb4b4e46712722cc7f0d))
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES: @payloadcms/richtext-lexical
|
||||
|
||||
* **richtext-lexical:** Update lexical from 0.12.6 to 0.13.1, port over all useful changes from playground (#5066)
|
||||
|
||||
- You HAVE to make sure that any versions of the lexical packages (IF you have any installed) match the lexical version which richtext-lexical uses: v0.13.1. If you do not do this, you may be plagued by React useContext / "cannot find active editor state" errors
|
||||
- Updates to lexical's API, e.g. the removal of INTERNAL_isPointSelection, could be breaking depending on your code. Please consult the [lexical changelog](https://github.com/facebook/lexical/blob/main/CHANGELOG.md).
|
||||
|
||||
## [2.11.0](https://github.com/payloadcms/payload/compare/v2.10.1...v2.11.0) (2024-02-09)
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Postgres
|
||||
label: Postgres
|
||||
order: 50
|
||||
desc: Payload supports Postgres through an officially supported Drizzle database adapter.
|
||||
desc: Payload supports Postgres through an officially supported Drizzle database adapter.
|
||||
keywords: Postgres, documentation, typescript, Content Management System, cms, headless, javascript, node, react, express
|
||||
---
|
||||
|
||||
@@ -37,11 +37,12 @@ export default buildConfig({
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Description |
|
||||
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `pool` | [Pool connection options](https://orm.drizzle.team/docs/quick-postgresql/node-postgres) that will be passed to Drizzle and `node-postgres`. |
|
||||
| `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. |
|
||||
| `migrationDir` | Customize the directory that migrations are stored. |
|
||||
| Option | Description |
|
||||
|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `pool` | [Pool connection options](https://orm.drizzle.team/docs/quick-postgresql/node-postgres) that will be passed to Drizzle and `node-postgres`. |
|
||||
| `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. |
|
||||
| `migrationDir` | Customize the directory that migrations are stored. |
|
||||
| `schemaName` | A string for the postgres schema to use, defaults to 'public'. |
|
||||
|
||||
### Access to Drizzle
|
||||
|
||||
@@ -65,7 +66,7 @@ In addition to exposing Drizzle directly, all of the tables, Drizzle relations,
|
||||
|
||||
Drizzle exposes two ways to work locally in development mode.
|
||||
|
||||
The first is [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push), which automatically pushes changes you make to your Payload config (and therefore, Drizzle schema) to your database so you don't have to manually migrate every time you change your Payload config. This only works in development mode, and should not be mixed with manually running [`migrate`](/docs/database/migrations) commands.
|
||||
The first is [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push), which automatically pushes changes you make to your Payload config (and therefore, Drizzle schema) to your database so you don't have to manually migrate every time you change your Payload config. This only works in development mode, and should not be mixed with manually running [`migrate`](/docs/database/migrations) commands.
|
||||
|
||||
You will be warned if any changes that you make will entail data loss while in development mode. Push is enabled by default, but you can opt out if you'd like.
|
||||
|
||||
@@ -77,11 +78,11 @@ Migrations are extremely powerful thanks to the seamless way that Payload and Dr
|
||||
|
||||
1. You are building your Payload config locally, with a local database used for testing.
|
||||
1. You have left the default setting of `push` enabled, so every time you change your Payload config (add or remove fields, collections, etc.), Drizzle will automatically push changes to your local DB.
|
||||
1. Once you're done with your changes, or have completed a feature, you can run `npm run payload migrate:create`.
|
||||
1. Once you're done with your changes, or have completed a feature, you can run `npm run payload migrate:create`.
|
||||
1. Payload and Drizzle will look for any existing migrations, and automatically generate all SQL changes necessary to convert your schema from its prior state into the state of your current Payload config, and store the resulting DDL in a newly created migration.
|
||||
1. Once you're ready to go to production, you will be able to run `npm run payload migrate` against your production database, which will apply any new migrations that have not yet run.
|
||||
1. Now your production database is in sync with your Payload config!
|
||||
|
||||
<Banner type="warning">
|
||||
Warning: do not mix "push" and migrations with your local development database. If you use "push" locally, and then try to migrate, Payload will throw a warning, telling you that these two methods are not meant to be used interchangeably.
|
||||
</Banner>
|
||||
</Banner>
|
||||
|
||||
@@ -36,7 +36,7 @@ If your Hook simply performs a side-effect, such as updating a CRM, it might be
|
||||
|
||||
#### Server-only execution
|
||||
|
||||
Payload Hooks do not have any effect within the Payload Admin panel. You can safely [remove your hooks](/docs/admin/webpack#aliasing-server-only-modules) from your Admin panel's code by customizing the Webpack config, which not only keeps your Admin bundles' filesize small but also ensures that any server-side only code does not cause problems within browser environments.
|
||||
Payload Hooks are only triggered on the server. You can safely [remove your hooks](/docs/admin/webpack#aliasing-server-only-modules) from your Admin panel's client-side code by customizing the Webpack config, which not only keeps your Admin bundles' filesize small but also ensures that any server-side only code does not cause problems within browser environments.
|
||||
|
||||
## Hook Types
|
||||
|
||||
|
||||
@@ -4508,9 +4508,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -4701,9 +4701,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -4508,9 +4508,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -4258,14 +4258,14 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^1.1.5:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48"
|
||||
integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==
|
||||
version "1.1.9"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396"
|
||||
integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -3924,9 +3924,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -4347,9 +4347,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -4508,9 +4508,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -4625,9 +4625,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -4599,9 +4599,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -4513,9 +4513,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -4835,9 +4835,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -3748,9 +3748,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-mongodb",
|
||||
"version": "1.4.2",
|
||||
"version": "1.4.3",
|
||||
"description": "The officially supported MongoDB database adapter for Payload",
|
||||
"repository": "https://github.com/payloadcms/payload",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -49,6 +49,8 @@ export interface Args {
|
||||
/** Set to true to disable hinting to MongoDB to use 'id' as index. This is currently done when counting documents for pagination. Disabling this optimization might fix some problems with AWS DocumentDB. Defaults to false */
|
||||
disableIndexHints?: boolean
|
||||
migrationDir?: string
|
||||
/** Set to true to evaluate null field values as existing */
|
||||
nullFieldValuesNotExist?: boolean
|
||||
transactionOptions?: TransactionOptions | false
|
||||
/** The URL to connect to MongoDB or false to start payload and prevent connecting */
|
||||
url: false | string
|
||||
@@ -93,6 +95,7 @@ export function mongooseAdapter({
|
||||
connectOptions,
|
||||
disableIndexHints = false,
|
||||
migrationDir: migrationDirArg,
|
||||
nullFieldValuesNotExist = true,
|
||||
transactionOptions = {},
|
||||
url,
|
||||
}: Args): MongooseAdapterResult {
|
||||
@@ -103,6 +106,8 @@ export function mongooseAdapter({
|
||||
return createDatabaseAdapter<MongooseAdapter>({
|
||||
name: 'mongoose',
|
||||
|
||||
nullFieldValuesNotExist,
|
||||
|
||||
// Mongoose-specific
|
||||
autoPluralization,
|
||||
collections: {},
|
||||
|
||||
@@ -14,8 +14,10 @@ import type {
|
||||
DateField,
|
||||
EmailField,
|
||||
Field,
|
||||
FieldAffectingData,
|
||||
GroupField,
|
||||
JSONField,
|
||||
NonPresentationalField,
|
||||
NumberField,
|
||||
PointField,
|
||||
RadioField,
|
||||
@@ -23,12 +25,12 @@ import type {
|
||||
RichTextField,
|
||||
RowField,
|
||||
SelectField,
|
||||
Tab,
|
||||
TabsField,
|
||||
TextField,
|
||||
TextareaField,
|
||||
UploadField,
|
||||
} from 'payload/types'
|
||||
import type { FieldAffectingData, NonPresentationalField, Tab, UnnamedTab } from 'payload/types'
|
||||
|
||||
import { Schema } from 'mongoose'
|
||||
import {
|
||||
@@ -61,7 +63,15 @@ const formatBaseSchema = (field: FieldAffectingData, buildSchemaOptions: BuildSc
|
||||
unique: (!disableUnique && field.unique) || false,
|
||||
}
|
||||
|
||||
if (schema.unique && (field.localized || draftsEnabled)) {
|
||||
if (
|
||||
schema.unique &&
|
||||
(field.localized ||
|
||||
draftsEnabled ||
|
||||
(fieldAffectsData(field) &&
|
||||
field.type !== 'group' &&
|
||||
field.type !== 'tab' &&
|
||||
field.required !== true))
|
||||
) {
|
||||
schema.sparse = true
|
||||
}
|
||||
|
||||
@@ -79,7 +89,6 @@ const localizeSchema = (
|
||||
) => {
|
||||
if (fieldIsLocalized(entity) && localization && Array.isArray(localization.locales)) {
|
||||
return {
|
||||
localized: true,
|
||||
type: localization.localeCodes.reduce(
|
||||
(localeSchema, locale) => ({
|
||||
...localeSchema,
|
||||
@@ -89,6 +98,7 @@ const localizeSchema = (
|
||||
_id: false,
|
||||
},
|
||||
),
|
||||
localized: true,
|
||||
}
|
||||
}
|
||||
return schema
|
||||
@@ -140,7 +150,6 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
) => {
|
||||
const baseSchema = {
|
||||
...formatBaseSchema(field, buildSchemaOptions),
|
||||
default: undefined,
|
||||
type: [
|
||||
buildSchema(config, field.fields, {
|
||||
allowIDField: true,
|
||||
@@ -153,6 +162,7 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
},
|
||||
}),
|
||||
],
|
||||
default: undefined,
|
||||
}
|
||||
|
||||
schema.add({
|
||||
@@ -166,8 +176,8 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
buildSchemaOptions: BuildSchemaOptions,
|
||||
): void => {
|
||||
const fieldSchema = {
|
||||
default: undefined,
|
||||
type: [new Schema({}, { _id: false, discriminatorKey: 'blockType' })],
|
||||
default: undefined,
|
||||
}
|
||||
|
||||
schema.add({
|
||||
@@ -187,12 +197,12 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
if (field.localized && config.localization) {
|
||||
config.localization.localeCodes.forEach((localeCode) => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore Possible incorrect typing in mongoose types, this works
|
||||
// @ts-expect-error Possible incorrect typing in mongoose types, this works
|
||||
schema.path(`${field.name}.${localeCode}`).discriminator(blockItem.slug, blockSchema)
|
||||
})
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore Possible incorrect typing in mongoose types, this works
|
||||
// @ts-expect-error Possible incorrect typing in mongoose types, this works
|
||||
schema.path(field.name).discriminator(blockItem.slug, blockSchema)
|
||||
}
|
||||
})
|
||||
@@ -325,14 +335,14 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
buildSchemaOptions: BuildSchemaOptions,
|
||||
): void => {
|
||||
const baseSchema: SchemaTypeOptions<unknown> = {
|
||||
type: {
|
||||
type: String,
|
||||
enum: ['Point'],
|
||||
},
|
||||
coordinates: {
|
||||
type: [Number],
|
||||
default: field.defaultValue || undefined,
|
||||
required: false,
|
||||
type: [Number],
|
||||
},
|
||||
type: {
|
||||
enum: ['Point'],
|
||||
type: String,
|
||||
},
|
||||
}
|
||||
if (buildSchemaOptions.disableUnique && field.unique && field.localized) {
|
||||
@@ -366,11 +376,11 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
): void => {
|
||||
const baseSchema = {
|
||||
...formatBaseSchema(field, buildSchemaOptions),
|
||||
type: String,
|
||||
enum: field.options.map((option) => {
|
||||
if (typeof option === 'object') return option.value
|
||||
return option
|
||||
}),
|
||||
type: String,
|
||||
}
|
||||
|
||||
schema.add({
|
||||
@@ -388,7 +398,6 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
|
||||
if (field.localized && config.localization) {
|
||||
schemaToReturn = {
|
||||
localized: true,
|
||||
type: config.localization.localeCodes.reduce((locales, locale) => {
|
||||
let localeSchema: { [key: string]: any } = {}
|
||||
|
||||
@@ -396,56 +405,57 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
localeSchema = {
|
||||
...formatBaseSchema(field, buildSchemaOptions),
|
||||
_id: false,
|
||||
relationTo: { enum: field.relationTo, type: String },
|
||||
type: Schema.Types.Mixed,
|
||||
relationTo: { type: String, enum: field.relationTo },
|
||||
value: {
|
||||
refPath: `${field.name}.${locale}.relationTo`,
|
||||
type: Schema.Types.Mixed,
|
||||
refPath: `${field.name}.${locale}.relationTo`,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
localeSchema = {
|
||||
...formatBaseSchema(field, buildSchemaOptions),
|
||||
ref: field.relationTo,
|
||||
type: Schema.Types.Mixed,
|
||||
ref: field.relationTo,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...locales,
|
||||
[locale]: field.hasMany ? { default: undefined, type: [localeSchema] } : localeSchema,
|
||||
[locale]: field.hasMany ? { type: [localeSchema], default: undefined } : localeSchema,
|
||||
}
|
||||
}, {}),
|
||||
localized: true,
|
||||
}
|
||||
} else if (hasManyRelations) {
|
||||
schemaToReturn = {
|
||||
...formatBaseSchema(field, buildSchemaOptions),
|
||||
_id: false,
|
||||
relationTo: { enum: field.relationTo, type: String },
|
||||
type: Schema.Types.Mixed,
|
||||
relationTo: { type: String, enum: field.relationTo },
|
||||
value: {
|
||||
refPath: `${field.name}.relationTo`,
|
||||
type: Schema.Types.Mixed,
|
||||
refPath: `${field.name}.relationTo`,
|
||||
},
|
||||
}
|
||||
|
||||
if (field.hasMany) {
|
||||
schemaToReturn = {
|
||||
default: undefined,
|
||||
type: [schemaToReturn],
|
||||
default: undefined,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
schemaToReturn = {
|
||||
...formatBaseSchema(field, buildSchemaOptions),
|
||||
ref: field.relationTo,
|
||||
type: Schema.Types.Mixed,
|
||||
ref: field.relationTo,
|
||||
}
|
||||
|
||||
if (field.hasMany) {
|
||||
schemaToReturn = {
|
||||
default: undefined,
|
||||
type: [schemaToReturn],
|
||||
default: undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -488,11 +498,11 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
): void => {
|
||||
const baseSchema = {
|
||||
...formatBaseSchema(field, buildSchemaOptions),
|
||||
type: String,
|
||||
enum: field.options.map((option) => {
|
||||
if (typeof option === 'object') return option.value
|
||||
return option
|
||||
}),
|
||||
type: String,
|
||||
}
|
||||
|
||||
if (buildSchemaOptions.draftsEnabled || !field.required) {
|
||||
@@ -576,8 +586,8 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
): void => {
|
||||
const baseSchema = {
|
||||
...formatBaseSchema(field, buildSchemaOptions),
|
||||
ref: field.relationTo,
|
||||
type: Schema.Types.Mixed,
|
||||
ref: field.relationTo,
|
||||
}
|
||||
|
||||
schema.add({
|
||||
|
||||
@@ -102,6 +102,7 @@ export async function buildSearchParam({
|
||||
hasCustomID,
|
||||
operator,
|
||||
path,
|
||||
payload,
|
||||
val,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Payload } from 'payload'
|
||||
import type { Field, TabAsField } from 'payload/types'
|
||||
|
||||
import mongoose from 'mongoose'
|
||||
@@ -8,6 +9,7 @@ type SanitizeQueryValueArgs = {
|
||||
hasCustomID: boolean
|
||||
operator: string
|
||||
path: string
|
||||
payload: Payload
|
||||
val: any
|
||||
}
|
||||
|
||||
@@ -16,6 +18,7 @@ export const sanitizeQueryValue = ({
|
||||
hasCustomID,
|
||||
operator,
|
||||
path,
|
||||
payload,
|
||||
val,
|
||||
}: SanitizeQueryValueArgs): {
|
||||
operator?: string
|
||||
@@ -174,6 +177,14 @@ export const sanitizeQueryValue = ({
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!payload.db.nullFieldValuesNotExist) {
|
||||
return {
|
||||
rawQuery: {
|
||||
$or: [{ [path]: { $exists: true } }, { [path]: { $eq: null } }],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { operator: formattedOperator, val: formattedValue }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-postgres",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0",
|
||||
"description": "The officially supported Postgres database adapter for Payload",
|
||||
"repository": "https://github.com/payloadcms/payload",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { Connect } from 'payload/database'
|
||||
|
||||
import { eq, sql } from 'drizzle-orm'
|
||||
import { drizzle } from 'drizzle-orm/node-postgres'
|
||||
import { numeric, pgTable, timestamp, varchar } from 'drizzle-orm/pg-core'
|
||||
import { numeric, timestamp, varchar } from 'drizzle-orm/pg-core'
|
||||
import { Pool } from 'pg'
|
||||
import prompts from 'prompts'
|
||||
|
||||
@@ -61,9 +61,13 @@ export const connect: Connect = async function connect(this: PostgresAdapter, pa
|
||||
|
||||
this.drizzle = drizzle(this.pool, { logger, schema: this.schema })
|
||||
if (process.env.PAYLOAD_DROP_DATABASE === 'true') {
|
||||
this.payload.logger.info('---- DROPPING TABLES ----')
|
||||
await this.drizzle.execute(sql`drop schema public cascade;
|
||||
create schema public;`)
|
||||
this.payload.logger.info(`---- DROPPING TABLES SCHEMA(${this.schemaName || 'public'}) ----`)
|
||||
await this.drizzle.execute(
|
||||
sql.raw(`
|
||||
drop schema if exists ${this.schemaName || 'public'} cascade;
|
||||
create schema ${this.schemaName || 'public'};
|
||||
`),
|
||||
)
|
||||
this.payload.logger.info('---- DROPPED TABLES ----')
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -120,7 +124,7 @@ export const connect: Connect = async function connect(this: PostgresAdapter, pa
|
||||
await apply()
|
||||
|
||||
// Migration table def in order to use query using drizzle
|
||||
const migrationsSchema = pgTable('payload_migrations', {
|
||||
const migrationsSchema = this.pgSchema.table('payload_migrations', {
|
||||
name: varchar('name'),
|
||||
batch: numeric('batch'),
|
||||
created_at: timestamp('created_at'),
|
||||
|
||||
@@ -78,7 +78,7 @@ export const traverseFields = ({
|
||||
with: {},
|
||||
}
|
||||
|
||||
const arrayTableName = `${currentTableName}_${toSnakeCase(field.name)}`
|
||||
const arrayTableName = `${currentTableName}_${path}${toSnakeCase(field.name)}`
|
||||
|
||||
if (adapter.tables[`${arrayTableName}_locales`]) withArray.with._locales = _locales
|
||||
currentArgs.with[`${path}${field.name}`] = withArray
|
||||
|
||||
@@ -52,11 +52,13 @@ export function postgresAdapter(args: Args): PostgresAdapterResult {
|
||||
fieldConstraints: {},
|
||||
idType,
|
||||
logger: args.logger,
|
||||
pgSchema: undefined,
|
||||
pool: undefined,
|
||||
poolOptions: args.pool,
|
||||
push: args.push,
|
||||
relations: {},
|
||||
schema: {},
|
||||
schemaName: args.schemaName,
|
||||
sessions: {},
|
||||
tables: {},
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import type { Init } from 'payload/database'
|
||||
import type { SanitizedCollectionConfig } from 'payload/types'
|
||||
|
||||
import { pgEnum } from 'drizzle-orm/pg-core'
|
||||
import { pgEnum, pgSchema, pgTable } from 'drizzle-orm/pg-core'
|
||||
import { buildVersionCollectionFields, buildVersionGlobalFields } from 'payload/versions'
|
||||
import toSnakeCase from 'to-snake-case'
|
||||
|
||||
@@ -11,6 +11,12 @@ import type { PostgresAdapter } from './types'
|
||||
import { buildTable } from './schema/build'
|
||||
|
||||
export const init: Init = async function init(this: PostgresAdapter) {
|
||||
if (this.schemaName) {
|
||||
this.pgSchema = pgSchema(this.schemaName)
|
||||
} else {
|
||||
this.pgSchema = { table: pgTable }
|
||||
}
|
||||
|
||||
if (this.payload.config.localization) {
|
||||
this.enums.enum__locales = pgEnum(
|
||||
'_locales',
|
||||
|
||||
@@ -39,7 +39,7 @@ export async function migrate(this: PostgresAdapter): Promise<void> {
|
||||
latestBatch = Number(migrationsInDB[0]?.batch)
|
||||
}
|
||||
} else {
|
||||
await createMigrationTable(this.drizzle)
|
||||
await createMigrationTable(this)
|
||||
}
|
||||
|
||||
if (migrationsInDB.find((m) => m.batch === -1)) {
|
||||
|
||||
@@ -44,8 +44,10 @@ export async function migrateFresh(
|
||||
msg: `Dropping database.`,
|
||||
})
|
||||
|
||||
await this.drizzle.execute(sql`drop schema public cascade;
|
||||
create schema public;`)
|
||||
await this.drizzle.execute(
|
||||
sql.raw(`drop schema ${this.schemaName || 'public'} cascade;
|
||||
create schema ${this.schemaName || 'public'};`),
|
||||
)
|
||||
|
||||
const migrationFiles = await readMigrationFiles({ payload })
|
||||
payload.logger.debug({
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { SQL } from 'drizzle-orm'
|
||||
import type { PgTableWithColumns } from 'drizzle-orm/pg-core'
|
||||
import type { Field, Where } from 'payload/types'
|
||||
|
||||
import { asc, desc } from 'drizzle-orm'
|
||||
@@ -12,7 +13,7 @@ export type BuildQueryJoins = Record<string, SQL>
|
||||
|
||||
export type BuildQueryJoinAliases = {
|
||||
condition: SQL
|
||||
table: GenericTable
|
||||
table: GenericTable | PgTableWithColumns<any>
|
||||
}[]
|
||||
|
||||
type BuildQueryArgs = {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { SQL } from 'drizzle-orm'
|
||||
import type { Field, FieldAffectingData, NumberField, TabAsField, TextField } from 'payload/types'
|
||||
import type { PgTableWithColumns } from 'drizzle-orm/pg-core'
|
||||
import type { Field, FieldAffectingData, NumberField, TabAsField, TextField } from 'payload/types'
|
||||
|
||||
import { and, eq, like, sql } from 'drizzle-orm'
|
||||
import { alias } from 'drizzle-orm/pg-core'
|
||||
@@ -15,7 +16,7 @@ import type { BuildQueryJoinAliases, BuildQueryJoins } from './buildQuery'
|
||||
|
||||
type Constraint = {
|
||||
columnName: string
|
||||
table: GenericTable
|
||||
table: GenericTable | PgTableWithColumns<any>
|
||||
value: unknown
|
||||
}
|
||||
|
||||
@@ -26,12 +27,12 @@ type TableColumn = {
|
||||
getNotNullColumnByValue?: (val: unknown) => string
|
||||
pathSegments?: string[]
|
||||
rawColumn?: SQL
|
||||
table: GenericTable
|
||||
table: GenericTable | PgTableWithColumns<any>
|
||||
}
|
||||
|
||||
type Args = {
|
||||
adapter: PostgresAdapter
|
||||
aliasTable?: GenericTable
|
||||
aliasTable?: GenericTable | PgTableWithColumns<any>
|
||||
collectionPath: string
|
||||
columnPrefix?: string
|
||||
constraintPath?: string
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { Relation } from 'drizzle-orm'
|
||||
import type { IndexBuilder, PgColumnBuilder, UniqueConstraintBuilder } from 'drizzle-orm/pg-core'
|
||||
import type {
|
||||
IndexBuilder,
|
||||
PgColumnBuilder,
|
||||
PgTableWithColumns,
|
||||
UniqueConstraintBuilder,
|
||||
} from 'drizzle-orm/pg-core'
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
import { relations } from 'drizzle-orm'
|
||||
import {
|
||||
index,
|
||||
integer,
|
||||
numeric,
|
||||
pgTable,
|
||||
serial,
|
||||
timestamp,
|
||||
unique,
|
||||
varchar,
|
||||
} from 'drizzle-orm/pg-core'
|
||||
import { index, integer, numeric, serial, timestamp, unique, varchar } from 'drizzle-orm/pg-core'
|
||||
import { fieldAffectsData } from 'payload/types'
|
||||
import toSnakeCase from 'to-snake-case'
|
||||
|
||||
@@ -77,14 +73,14 @@ export const buildTable = ({
|
||||
|
||||
const localesColumns: Record<string, PgColumnBuilder> = {}
|
||||
const localesIndexes: Record<string, (cols: GenericColumns) => IndexBuilder> = {}
|
||||
let localesTable: GenericTable
|
||||
let textsTable: GenericTable
|
||||
let numbersTable: GenericTable
|
||||
let localesTable: GenericTable | PgTableWithColumns<any>
|
||||
let textsTable: GenericTable | PgTableWithColumns<any>
|
||||
let numbersTable: GenericTable | PgTableWithColumns<any>
|
||||
|
||||
// Relationships to the base collection
|
||||
const relationships: Set<string> = rootRelationships || new Set()
|
||||
|
||||
let relationshipsTable: GenericTable
|
||||
let relationshipsTable: GenericTable | PgTableWithColumns<any>
|
||||
|
||||
// Drizzle relations
|
||||
const relationsToBuild: Map<string, string> = new Map()
|
||||
@@ -136,7 +132,7 @@ export const buildTable = ({
|
||||
.notNull()
|
||||
}
|
||||
|
||||
const table = pgTable(tableName, columns, (cols) => {
|
||||
const table = adapter.pgSchema.table(tableName, columns, (cols) => {
|
||||
const extraConfig = Object.entries(baseExtraConfig).reduce((config, [key, func]) => {
|
||||
config[key] = func(cols)
|
||||
return config
|
||||
@@ -158,7 +154,7 @@ export const buildTable = ({
|
||||
.references(() => table.id, { onDelete: 'cascade' })
|
||||
.notNull()
|
||||
|
||||
localesTable = pgTable(localeTableName, localesColumns, (cols) => {
|
||||
localesTable = adapter.pgSchema.table(localeTableName, localesColumns, (cols) => {
|
||||
return Object.entries(localesIndexes).reduce(
|
||||
(acc, [colName, func]) => {
|
||||
acc[colName] = func(cols)
|
||||
@@ -201,7 +197,7 @@ export const buildTable = ({
|
||||
columns.locale = adapter.enums.enum__locales('locale')
|
||||
}
|
||||
|
||||
textsTable = pgTable(textsTableName, columns, (cols) => {
|
||||
textsTable = adapter.pgSchema.table(textsTableName, columns, (cols) => {
|
||||
const indexes: Record<string, IndexBuilder> = {
|
||||
orderParentIdx: index(`${textsTableName}_order_parent_idx`).on(cols.order, cols.parent),
|
||||
}
|
||||
@@ -245,7 +241,7 @@ export const buildTable = ({
|
||||
columns.locale = adapter.enums.enum__locales('locale')
|
||||
}
|
||||
|
||||
numbersTable = pgTable(numbersTableName, columns, (cols) => {
|
||||
numbersTable = adapter.pgSchema.table(numbersTableName, columns, (cols) => {
|
||||
const indexes: Record<string, IndexBuilder> = {
|
||||
orderParentIdx: index(`${numbersTableName}_order_parent_idx`).on(cols.order, cols.parent),
|
||||
}
|
||||
@@ -307,19 +303,23 @@ export const buildTable = ({
|
||||
|
||||
const relationshipsTableName = `${tableName}_rels`
|
||||
|
||||
relationshipsTable = pgTable(relationshipsTableName, relationshipColumns, (cols) => {
|
||||
const result: Record<string, unknown> = {
|
||||
order: index(`${relationshipsTableName}_order_idx`).on(cols.order),
|
||||
parentIdx: index(`${relationshipsTableName}_parent_idx`).on(cols.parent),
|
||||
pathIdx: index(`${relationshipsTableName}_path_idx`).on(cols.path),
|
||||
}
|
||||
relationshipsTable = adapter.pgSchema.table(
|
||||
relationshipsTableName,
|
||||
relationshipColumns,
|
||||
(cols) => {
|
||||
const result: Record<string, unknown> = {
|
||||
order: index(`${relationshipsTableName}_order_idx`).on(cols.order),
|
||||
parentIdx: index(`${relationshipsTableName}_parent_idx`).on(cols.parent),
|
||||
pathIdx: index(`${relationshipsTableName}_path_idx`).on(cols.path),
|
||||
}
|
||||
|
||||
if (hasLocalizedRelationshipField) {
|
||||
result.localeIdx = index(`${relationshipsTableName}_locale_idx`).on(cols.locale)
|
||||
}
|
||||
if (hasLocalizedRelationshipField) {
|
||||
result.localeIdx = index(`${relationshipsTableName}_locale_idx`).on(cols.locale)
|
||||
}
|
||||
|
||||
return result
|
||||
})
|
||||
return result
|
||||
},
|
||||
)
|
||||
|
||||
adapter.tables[relationshipsTableName] = relationshipsTable
|
||||
|
||||
|
||||
@@ -7,7 +7,14 @@ import type {
|
||||
Relations,
|
||||
} from 'drizzle-orm'
|
||||
import type { NodePgDatabase, NodePgQueryResultHKT } from 'drizzle-orm/node-postgres'
|
||||
import type { PgColumn, PgEnum, PgTableWithColumns, PgTransaction } from 'drizzle-orm/pg-core'
|
||||
import type {
|
||||
PgColumn,
|
||||
PgEnum,
|
||||
PgSchema,
|
||||
PgTableWithColumns,
|
||||
PgTransaction,
|
||||
} from 'drizzle-orm/pg-core'
|
||||
import type { PgTableFn } from 'drizzle-orm/pg-core/table'
|
||||
import type { Payload } from 'payload'
|
||||
import type { BaseDatabaseAdapter } from 'payload/database'
|
||||
import type { PayloadRequest } from 'payload/types'
|
||||
@@ -21,6 +28,7 @@ export type Args = {
|
||||
migrationDir?: string
|
||||
pool: PoolConfig
|
||||
push?: boolean
|
||||
schemaName?: string
|
||||
}
|
||||
|
||||
export type GenericColumn = PgColumn<
|
||||
@@ -59,11 +67,13 @@ export type PostgresAdapter = BaseDatabaseAdapter & {
|
||||
fieldConstraints: Record<string, Record<string, string>>
|
||||
idType: Args['idType']
|
||||
logger: DrizzleConfig['logger']
|
||||
pgSchema?: { table: PgTableFn } | PgSchema
|
||||
pool: Pool
|
||||
poolOptions: Args['pool']
|
||||
push: boolean
|
||||
relations: Record<string, GenericRelation>
|
||||
schema: Record<string, GenericEnum | GenericRelation | GenericTable>
|
||||
schemaName?: Args['schemaName']
|
||||
sessions: {
|
||||
[id: string]: {
|
||||
db: DrizzleTransaction
|
||||
@@ -71,7 +81,7 @@ export type PostgresAdapter = BaseDatabaseAdapter & {
|
||||
resolve: () => Promise<void>
|
||||
}
|
||||
}
|
||||
tables: Record<string, GenericTable>
|
||||
tables: Record<string, GenericTable | PgTableWithColumns<any>>
|
||||
}
|
||||
|
||||
export type IDType = 'integer' | 'numeric' | 'uuid' | 'varchar'
|
||||
|
||||
@@ -40,7 +40,7 @@ export const insertArrays = async ({ adapter, arrays, db, parentRows }: Args): P
|
||||
|
||||
// Add any sub arrays that need to be created
|
||||
// We will call this recursively below
|
||||
arrayRows.forEach((arrayRow) => {
|
||||
arrayRows.forEach((arrayRow, i) => {
|
||||
if (Object.keys(arrayRow.arrays).length > 0) {
|
||||
rowsByTable[tableName].arrays.push(arrayRow.arrays)
|
||||
}
|
||||
@@ -53,6 +53,9 @@ export const insertArrays = async ({ adapter, arrays, db, parentRows }: Args): P
|
||||
arrayRowLocaleData._parentID = arrayRow.row.id
|
||||
arrayRowLocaleData._locale = arrayRowLocale
|
||||
rowsByTable[tableName].locales.push(arrayRowLocaleData)
|
||||
if (!arrayRow.row.id) {
|
||||
arrayRowLocaleData._getParentID = (rows) => rows[i].id
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -69,6 +72,15 @@ export const insertArrays = async ({ adapter, arrays, db, parentRows }: Args): P
|
||||
|
||||
// Insert locale rows
|
||||
if (adapter.tables[`${tableName}_locales`] && row.locales.length > 0) {
|
||||
if (!row.locales[0]._parentID) {
|
||||
row.locales = row.locales.map((localeRow, i) => {
|
||||
if (typeof localeRow._getParentID === 'function') {
|
||||
localeRow._parentID = localeRow._getParentID(insertedRows)
|
||||
delete localeRow._getParentID
|
||||
}
|
||||
return localeRow
|
||||
})
|
||||
}
|
||||
await db.insert(adapter.tables[`${tableName}_locales`]).values(row.locales).returning()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { sql } from 'drizzle-orm'
|
||||
|
||||
import type { DrizzleDB } from '../types'
|
||||
import type { PostgresAdapter } from '../types'
|
||||
|
||||
export const createMigrationTable = async (db: DrizzleDB): Promise<void> => {
|
||||
await db.execute(sql`CREATE TABLE IF NOT EXISTS "payload_migrations" (
|
||||
export const createMigrationTable = async (adapter: PostgresAdapter): Promise<void> => {
|
||||
const prependSchema = adapter.schemaName ? `"${adapter.schemaName}".` : ''
|
||||
|
||||
await adapter.drizzle.execute(
|
||||
sql.raw(`CREATE TABLE IF NOT EXISTS ${prependSchema}"payload_migrations" (
|
||||
"id" serial PRIMARY KEY NOT NULL,
|
||||
"name" varchar,
|
||||
"batch" numeric,
|
||||
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
|
||||
);`)
|
||||
);`),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload",
|
||||
"version": "2.11.1",
|
||||
"version": "2.11.2",
|
||||
"description": "Node, React and MongoDB Headless CMS and Application Framework",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
|
||||
@@ -52,21 +52,9 @@ const Content: React.FC<DocumentDrawerProps> = ({
|
||||
|
||||
const { id, docPermissions, getDocPreferences } = useDocumentInfo()
|
||||
|
||||
// The component definition could come from multiple places in the config
|
||||
// we need to cascade into the proper component from the top-down
|
||||
// 1. "components.Edit"
|
||||
// 2. "components.Edit.Default"
|
||||
// 3. "components.Edit.Default.Component"
|
||||
const CustomEditView =
|
||||
typeof Edit === 'function'
|
||||
? Edit
|
||||
: typeof Edit === 'object' && typeof Edit.Default === 'function'
|
||||
? Edit.Default
|
||||
: typeof Edit?.Default === 'object' &&
|
||||
'Component' in Edit.Default &&
|
||||
typeof Edit.Default.Component === 'function'
|
||||
? Edit.Default.Component
|
||||
: undefined
|
||||
// If they are replacing the entire edit view, use that.
|
||||
// Else let the DefaultEdit determine what to render.
|
||||
const CustomEditView = typeof Edit === 'function' ? Edit : undefined
|
||||
|
||||
const [fields, setFields] = useState(() => formatFields(collectionConfig, true))
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import { fieldTypes } from '../../forms/field-types'
|
||||
import X from '../../icons/X'
|
||||
import { useAuth } from '../../utilities/Auth'
|
||||
import { useConfig } from '../../utilities/Config'
|
||||
import { DocumentInfoProvider } from '../../utilities/DocumentInfo'
|
||||
import { OperationContext } from '../../utilities/OperationProvider'
|
||||
import { SelectAllStatus, useSelection } from '../../views/collections/List/SelectionProvider'
|
||||
import { Drawer, DrawerToggler } from '../Drawer'
|
||||
@@ -120,53 +121,55 @@ const EditMany: React.FC<Props> = (props) => {
|
||||
{t('edit')}
|
||||
</DrawerToggler>
|
||||
<Drawer header={null} slug={drawerSlug}>
|
||||
<OperationContext.Provider value="update">
|
||||
<Form className={`${baseClass}__form`} onSuccess={onSuccess}>
|
||||
<div className={`${baseClass}__main`}>
|
||||
<div className={`${baseClass}__header`}>
|
||||
<h2 className={`${baseClass}__header__title`}>
|
||||
{t('editingLabel', { count, label: getTranslation(plural, i18n) })}
|
||||
</h2>
|
||||
<button
|
||||
aria-label={t('close')}
|
||||
className={`${baseClass}__header__close`}
|
||||
id={`close-drawer__${drawerSlug}`}
|
||||
onClick={() => closeModal(drawerSlug)}
|
||||
type="button"
|
||||
>
|
||||
<X />
|
||||
</button>
|
||||
</div>
|
||||
<FieldSelect fields={fields} setSelected={setSelected} />
|
||||
<RenderFields fieldSchema={selected} fieldTypes={fieldTypes} />
|
||||
<div className={`${baseClass}__sidebar-wrap`}>
|
||||
<div className={`${baseClass}__sidebar`}>
|
||||
<div className={`${baseClass}__sidebar-sticky-wrap`}>
|
||||
<div className={`${baseClass}__document-actions`}>
|
||||
{collection.versions ? (
|
||||
<React.Fragment>
|
||||
<Publish
|
||||
<DocumentInfoProvider collection={collection}>
|
||||
<OperationContext.Provider value="update">
|
||||
<Form className={`${baseClass}__form`} onSuccess={onSuccess}>
|
||||
<div className={`${baseClass}__main`}>
|
||||
<div className={`${baseClass}__header`}>
|
||||
<h2 className={`${baseClass}__header__title`}>
|
||||
{t('editingLabel', { count, label: getTranslation(plural, i18n) })}
|
||||
</h2>
|
||||
<button
|
||||
aria-label={t('close')}
|
||||
className={`${baseClass}__header__close`}
|
||||
id={`close-drawer__${drawerSlug}`}
|
||||
onClick={() => closeModal(drawerSlug)}
|
||||
type="button"
|
||||
>
|
||||
<X />
|
||||
</button>
|
||||
</div>
|
||||
<FieldSelect fields={fields} setSelected={setSelected} />
|
||||
<RenderFields fieldSchema={selected} fieldTypes={fieldTypes} />
|
||||
<div className={`${baseClass}__sidebar-wrap`}>
|
||||
<div className={`${baseClass}__sidebar`}>
|
||||
<div className={`${baseClass}__sidebar-sticky-wrap`}>
|
||||
<div className={`${baseClass}__document-actions`}>
|
||||
{collection.versions ? (
|
||||
<React.Fragment>
|
||||
<Publish
|
||||
action={`${serverURL}${api}/${slug}${getQueryParams()}`}
|
||||
disabled={selected.length === 0}
|
||||
/>
|
||||
<SaveDraft
|
||||
action={`${serverURL}${api}/${slug}${getQueryParams()}`}
|
||||
disabled={selected.length === 0}
|
||||
/>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<Submit
|
||||
action={`${serverURL}${api}/${slug}${getQueryParams()}`}
|
||||
disabled={selected.length === 0}
|
||||
/>
|
||||
<SaveDraft
|
||||
action={`${serverURL}${api}/${slug}${getQueryParams()}`}
|
||||
disabled={selected.length === 0}
|
||||
/>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<Submit
|
||||
action={`${serverURL}${api}/${slug}${getQueryParams()}`}
|
||||
disabled={selected.length === 0}
|
||||
/>
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</OperationContext.Provider>
|
||||
</Form>
|
||||
</OperationContext.Provider>
|
||||
</DocumentInfoProvider>
|
||||
</Drawer>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -7,13 +7,14 @@ import { extractTranslations } from '../../translations/extractTranslations'
|
||||
const labels = extractTranslations(['authentication:enableAPIKey', 'authentication:apiKey'])
|
||||
|
||||
const encryptKey: FieldHook = ({ req, value }) =>
|
||||
value ? req.payload.encrypt(value as string) : undefined
|
||||
value ? req.payload.encrypt(value as string) : null
|
||||
const decryptKey: FieldHook = ({ req, value }) =>
|
||||
value ? req.payload.decrypt(value as string) : undefined
|
||||
|
||||
export default [
|
||||
{
|
||||
name: 'enableAPIKey',
|
||||
type: 'checkbox',
|
||||
admin: {
|
||||
components: {
|
||||
Field: () => null,
|
||||
@@ -21,10 +22,10 @@ export default [
|
||||
},
|
||||
defaultValue: false,
|
||||
label: labels['authentication:enableAPIKey'],
|
||||
type: 'checkbox',
|
||||
},
|
||||
{
|
||||
name: 'apiKey',
|
||||
type: 'text',
|
||||
admin: {
|
||||
components: {
|
||||
Field: () => null,
|
||||
@@ -35,10 +36,10 @@ export default [
|
||||
beforeChange: [encryptKey],
|
||||
},
|
||||
label: labels['authentication:apiKey'],
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'apiKeyIndex',
|
||||
type: 'text',
|
||||
admin: {
|
||||
disabled: true,
|
||||
},
|
||||
@@ -59,6 +60,5 @@ export default [
|
||||
},
|
||||
],
|
||||
},
|
||||
type: 'text',
|
||||
},
|
||||
] as Field[]
|
||||
|
||||
@@ -72,6 +72,8 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
overrideAccess,
|
||||
req,
|
||||
req: {
|
||||
fallbackLocale,
|
||||
locale,
|
||||
payload,
|
||||
payload: { config, secret },
|
||||
},
|
||||
@@ -196,7 +198,9 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
context: req.context,
|
||||
depth,
|
||||
doc: user,
|
||||
fallbackLocale,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -56,30 +56,33 @@ const args = minimist(process.argv.slice(2))
|
||||
const scriptIndex = args._.findIndex((x) => x === 'build')
|
||||
|
||||
const script = scriptIndex === -1 ? args._[0] : args._[scriptIndex]
|
||||
if (script) {
|
||||
if (script.startsWith('migrate')) {
|
||||
migrate(args).then(() => process.exit(0))
|
||||
} else {
|
||||
switch (script.toLowerCase()) {
|
||||
case 'build': {
|
||||
build()
|
||||
break
|
||||
}
|
||||
|
||||
if (script.startsWith('migrate')) {
|
||||
migrate(args).then(() => process.exit(0))
|
||||
} else {
|
||||
switch (script.toLowerCase()) {
|
||||
case 'build': {
|
||||
build()
|
||||
break
|
||||
case 'generate:types': {
|
||||
generateTypes()
|
||||
break
|
||||
}
|
||||
|
||||
case 'generate:graphqlschema': {
|
||||
generateGraphQLSchema()
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
console.log(`Unknown script "${script}".`)
|
||||
break
|
||||
}
|
||||
|
||||
case 'generate:types': {
|
||||
generateTypes()
|
||||
break
|
||||
}
|
||||
|
||||
case 'generate:graphqlschema': {
|
||||
generateGraphQLSchema()
|
||||
break
|
||||
}
|
||||
|
||||
default:
|
||||
console.log(`Unknown script "${script}".`)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
console.error('No payload script specified. Did you mean to run `payload migrate`?')
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,6 @@ import type {
|
||||
import executeAccess from '../../auth/executeAccess'
|
||||
import sendVerificationEmail from '../../auth/sendVerificationEmail'
|
||||
import { registerLocalStrategy } from '../../auth/strategies/local/register'
|
||||
import { fieldAffectsData } from '../../fields/config/types'
|
||||
import { afterChange } from '../../fields/hooks/afterChange'
|
||||
import { afterRead } from '../../fields/hooks/afterRead'
|
||||
import { beforeChange } from '../../fields/hooks/beforeChange'
|
||||
@@ -26,12 +25,12 @@ import { generateFileData } from '../../uploads/generateFileData'
|
||||
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles'
|
||||
import { uploadFiles } from '../../uploads/uploadFiles'
|
||||
import { commitTransaction } from '../../utilities/commitTransaction'
|
||||
import flattenFields from '../../utilities/flattenTopLevelFields'
|
||||
import { initTransaction } from '../../utilities/initTransaction'
|
||||
import { killTransaction } from '../../utilities/killTransaction'
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields'
|
||||
import { saveVersion } from '../../versions/saveVersion'
|
||||
import { buildAfterOperation } from './utils'
|
||||
import flattenFields from '../../utilities/flattenTopLevelFields'
|
||||
|
||||
const unlinkFile = promisify(fs.unlink)
|
||||
|
||||
@@ -88,6 +87,8 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
overrideAccess,
|
||||
overwriteExistingFiles = false,
|
||||
req: {
|
||||
fallbackLocale,
|
||||
locale,
|
||||
payload,
|
||||
payload: { config, emailOptions },
|
||||
},
|
||||
@@ -289,7 +290,9 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
context: req.context,
|
||||
depth,
|
||||
doc: result,
|
||||
fallbackLocale,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -66,6 +66,7 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
|
||||
depth,
|
||||
overrideAccess,
|
||||
req: {
|
||||
fallbackLocale,
|
||||
locale,
|
||||
payload: { config },
|
||||
payload,
|
||||
@@ -149,9 +150,9 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
|
||||
if (collectionConfig.versions) {
|
||||
await deleteCollectionVersions({
|
||||
id,
|
||||
slug: collectionConfig.slug,
|
||||
payload,
|
||||
req,
|
||||
slug: collectionConfig.slug,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -178,7 +179,9 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
|
||||
context: req.context,
|
||||
depth,
|
||||
doc: result || doc,
|
||||
fallbackLocale,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -59,6 +59,8 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
depth,
|
||||
overrideAccess,
|
||||
req: {
|
||||
fallbackLocale,
|
||||
locale,
|
||||
payload: { config },
|
||||
payload,
|
||||
t,
|
||||
@@ -120,9 +122,9 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
if (collectionConfig.versions) {
|
||||
await deleteCollectionVersions({
|
||||
id,
|
||||
slug: collectionConfig.slug,
|
||||
payload,
|
||||
req,
|
||||
slug: collectionConfig.slug,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -156,7 +158,9 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
context: req.context,
|
||||
depth,
|
||||
doc: result,
|
||||
fallbackLocale,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -68,7 +68,7 @@ async function find<T extends TypeWithID & Record<string, unknown>>(
|
||||
overrideAccess,
|
||||
page,
|
||||
pagination = true,
|
||||
req: { locale, payload },
|
||||
req: { fallbackLocale, locale, payload },
|
||||
req,
|
||||
showHiddenFields,
|
||||
sort,
|
||||
@@ -196,8 +196,10 @@ async function find<T extends TypeWithID & Record<string, unknown>>(
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
findMany: true,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -56,7 +56,7 @@ async function findByID<T extends TypeWithID>(incomingArgs: Arguments): Promise<
|
||||
disableErrors,
|
||||
draft: draftEnabled = false,
|
||||
overrideAccess = false,
|
||||
req: { locale, t },
|
||||
req: { fallbackLocale, locale, t },
|
||||
req,
|
||||
showHiddenFields,
|
||||
} = args
|
||||
@@ -139,7 +139,9 @@ async function findByID<T extends TypeWithID>(incomingArgs: Arguments): Promise<
|
||||
currentDepth,
|
||||
depth,
|
||||
doc: result,
|
||||
fallbackLocale,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -34,7 +34,7 @@ async function findVersionByID<T extends TypeWithID = any>(
|
||||
depth,
|
||||
disableErrors,
|
||||
overrideAccess,
|
||||
req: { locale, payload, t },
|
||||
req: { fallbackLocale, locale, payload, t },
|
||||
req,
|
||||
showHiddenFields,
|
||||
} = args
|
||||
@@ -112,7 +112,9 @@ async function findVersionByID<T extends TypeWithID = any>(
|
||||
currentDepth,
|
||||
depth,
|
||||
doc: result.version,
|
||||
fallbackLocale,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -37,7 +37,7 @@ async function findVersions<T extends TypeWithVersion<T>>(
|
||||
overrideAccess,
|
||||
page,
|
||||
pagination = true,
|
||||
req: { locale, payload },
|
||||
req: { fallbackLocale, locale, payload },
|
||||
req,
|
||||
showHiddenFields,
|
||||
sort,
|
||||
@@ -125,8 +125,10 @@ async function findVersions<T extends TypeWithVersion<T>>(
|
||||
context: req.context,
|
||||
depth,
|
||||
doc: data.version,
|
||||
fallbackLocale,
|
||||
findMany: true,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -34,7 +34,7 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
|
||||
depth,
|
||||
overrideAccess = false,
|
||||
req,
|
||||
req: { locale, payload, t },
|
||||
req: { fallbackLocale, locale, payload, t },
|
||||
showHiddenFields,
|
||||
} = args
|
||||
|
||||
@@ -140,7 +140,9 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
|
||||
context: req.context,
|
||||
depth,
|
||||
doc: result,
|
||||
fallbackLocale,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -75,6 +75,7 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
overrideAccess,
|
||||
overwriteExistingFiles = false,
|
||||
req: {
|
||||
fallbackLocale,
|
||||
locale,
|
||||
payload: { config },
|
||||
payload,
|
||||
@@ -176,7 +177,9 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
context: req.context,
|
||||
depth: 0,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess: true,
|
||||
req,
|
||||
showHiddenFields: true,
|
||||
@@ -309,7 +312,9 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
context: req.context,
|
||||
depth,
|
||||
doc: result,
|
||||
fallbackLocale: null,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -76,6 +76,7 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
overrideAccess,
|
||||
overwriteExistingFiles = false,
|
||||
req: {
|
||||
fallbackLocale,
|
||||
locale,
|
||||
payload: { config },
|
||||
payload,
|
||||
@@ -130,7 +131,9 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
context: req.context,
|
||||
depth: 0,
|
||||
doc: docWithLocales,
|
||||
fallbackLocale: null,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess: true,
|
||||
req,
|
||||
showHiddenFields: true,
|
||||
@@ -297,7 +300,9 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
context: req.context,
|
||||
depth,
|
||||
doc: result,
|
||||
fallbackLocale,
|
||||
global: null,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -56,7 +56,7 @@ const errorHandler =
|
||||
err,
|
||||
response,
|
||||
req.context,
|
||||
req.collection.config,
|
||||
null,
|
||||
)) || {
|
||||
response,
|
||||
status,
|
||||
|
||||
@@ -11,9 +11,11 @@ type Args = {
|
||||
currentDepth?: number
|
||||
depth: number
|
||||
doc: Record<string, unknown>
|
||||
fallbackLocale: null | string
|
||||
findMany?: boolean
|
||||
flattenLocales?: boolean
|
||||
global: SanitizedGlobalConfig | null
|
||||
locale: string
|
||||
overrideAccess: boolean
|
||||
req: PayloadRequest
|
||||
showHiddenFields: boolean
|
||||
@@ -26,9 +28,11 @@ export async function afterRead<T = any>(args: Args): Promise<T> {
|
||||
currentDepth: incomingCurrentDepth,
|
||||
depth: incomingDepth,
|
||||
doc: incomingDoc,
|
||||
fallbackLocale,
|
||||
findMany,
|
||||
flattenLocales = true,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
@@ -52,11 +56,13 @@ export async function afterRead<T = any>(args: Args): Promise<T> {
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
fieldPromises,
|
||||
fields: collection?.fields || global?.fields,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
|
||||
@@ -16,11 +16,13 @@ type Args = {
|
||||
currentDepth: number
|
||||
depth: number
|
||||
doc: Record<string, unknown>
|
||||
fallbackLocale: null | string
|
||||
field: Field | TabAsField
|
||||
fieldPromises: Promise<void>[]
|
||||
findMany: boolean
|
||||
flattenLocales: boolean
|
||||
global: SanitizedGlobalConfig | null
|
||||
locale: null | string
|
||||
overrideAccess: boolean
|
||||
populationPromises: Promise<void>[]
|
||||
req: PayloadRequest
|
||||
@@ -44,11 +46,13 @@ export const promise = async ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
field,
|
||||
fieldPromises,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
@@ -72,18 +76,13 @@ export const promise = async ({
|
||||
typeof siblingDoc[field.name] === 'object' &&
|
||||
siblingDoc[field.name] !== null &&
|
||||
field.localized &&
|
||||
req.locale !== 'all' &&
|
||||
locale !== 'all' &&
|
||||
req.payload.config.localization
|
||||
|
||||
if (shouldHoistLocalizedValue) {
|
||||
// replace actual value with localized value before sanitizing
|
||||
// { [locale]: fields } -> fields
|
||||
const { locale } = req
|
||||
const value = siblingDoc[field.name][locale]
|
||||
const fallbackLocale =
|
||||
req.payload.config.localization &&
|
||||
req.payload.config.localization?.fallback &&
|
||||
req.fallbackLocale
|
||||
|
||||
let hoistedValue = value
|
||||
|
||||
@@ -201,7 +200,7 @@ export const promise = async ({
|
||||
|
||||
const shouldRunHookOnAllLocales =
|
||||
field.localized &&
|
||||
(req.locale === 'all' || !flattenLocales) &&
|
||||
(locale === 'all' || !flattenLocales) &&
|
||||
typeof siblingDoc[field.name] === 'object'
|
||||
|
||||
if (shouldRunHookOnAllLocales) {
|
||||
@@ -277,7 +276,7 @@ export const promise = async ({
|
||||
) {
|
||||
siblingDoc[field.name] = await getValueWithDefault({
|
||||
defaultValue: field.defaultValue,
|
||||
locale: req.locale,
|
||||
locale,
|
||||
user: req.user,
|
||||
value: siblingDoc[field.name],
|
||||
})
|
||||
@@ -288,7 +287,9 @@ export const promise = async ({
|
||||
relationshipPopulationPromise({
|
||||
currentDepth,
|
||||
depth,
|
||||
fallbackLocale,
|
||||
field,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
@@ -309,11 +310,13 @@ export const promise = async ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
fieldPromises,
|
||||
fields: field.fields,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
@@ -337,11 +340,13 @@ export const promise = async ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
fieldPromises,
|
||||
fields: field.fields,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
@@ -361,11 +366,13 @@ export const promise = async ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
fieldPromises,
|
||||
fields: field.fields,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
@@ -397,11 +404,13 @@ export const promise = async ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
fieldPromises,
|
||||
fields: block.fields,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
@@ -425,11 +434,13 @@ export const promise = async ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
fieldPromises,
|
||||
fields: block.fields,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
@@ -457,11 +468,13 @@ export const promise = async ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
fieldPromises,
|
||||
fields: field.fields,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
@@ -487,11 +500,13 @@ export const promise = async ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
fieldPromises,
|
||||
fields: field.fields,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
@@ -511,11 +526,13 @@ export const promise = async ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
fieldPromises,
|
||||
fields: field.tabs.map((tab) => ({ ...tab, type: 'tab' })),
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
|
||||
@@ -8,9 +8,11 @@ type PopulateArgs = {
|
||||
data: Record<string, unknown>
|
||||
dataReference: Record<string, any>
|
||||
depth: number
|
||||
fallbackLocale: null | string
|
||||
field: RelationshipField | UploadField
|
||||
index?: number
|
||||
key?: string
|
||||
locale: null | string
|
||||
overrideAccess: boolean
|
||||
req: PayloadRequest
|
||||
showHiddenFields: boolean
|
||||
@@ -21,9 +23,11 @@ const populate = async ({
|
||||
data,
|
||||
dataReference,
|
||||
depth,
|
||||
fallbackLocale,
|
||||
field,
|
||||
index,
|
||||
key,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
@@ -54,8 +58,8 @@ const populate = async ({
|
||||
id,
|
||||
depth,
|
||||
currentDepth + 1,
|
||||
req.locale,
|
||||
req.fallbackLocale,
|
||||
locale,
|
||||
fallbackLocale,
|
||||
overrideAccess,
|
||||
showHiddenFields,
|
||||
]),
|
||||
@@ -90,7 +94,9 @@ const populate = async ({
|
||||
type PromiseArgs = {
|
||||
currentDepth: number
|
||||
depth: number
|
||||
fallbackLocale: null | string
|
||||
field: RelationshipField | UploadField
|
||||
locale: null | string
|
||||
overrideAccess: boolean
|
||||
req: PayloadRequest
|
||||
showHiddenFields: boolean
|
||||
@@ -100,7 +106,9 @@ type PromiseArgs = {
|
||||
const relationshipPopulationPromise = async ({
|
||||
currentDepth,
|
||||
depth,
|
||||
fallbackLocale,
|
||||
field,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
@@ -112,7 +120,7 @@ const relationshipPopulationPromise = async ({
|
||||
|
||||
if (fieldSupportsMany(field) && field.hasMany) {
|
||||
if (
|
||||
req.locale === 'all' &&
|
||||
locale === 'all' &&
|
||||
typeof siblingDoc[field.name] === 'object' &&
|
||||
siblingDoc[field.name] !== null
|
||||
) {
|
||||
@@ -125,9 +133,11 @@ const relationshipPopulationPromise = async ({
|
||||
data: siblingDoc[field.name][key][index],
|
||||
dataReference: resultingDoc,
|
||||
depth: populateDepth,
|
||||
fallbackLocale,
|
||||
field,
|
||||
index,
|
||||
key,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
@@ -146,8 +156,10 @@ const relationshipPopulationPromise = async ({
|
||||
data: relatedDoc,
|
||||
dataReference: resultingDoc,
|
||||
depth: populateDepth,
|
||||
fallbackLocale,
|
||||
field,
|
||||
index,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
@@ -161,7 +173,7 @@ const relationshipPopulationPromise = async ({
|
||||
} else if (
|
||||
typeof siblingDoc[field.name] === 'object' &&
|
||||
siblingDoc[field.name] !== null &&
|
||||
req.locale === 'all'
|
||||
locale === 'all'
|
||||
) {
|
||||
Object.keys(siblingDoc[field.name]).forEach((key) => {
|
||||
const rowPromise = async () => {
|
||||
@@ -170,8 +182,10 @@ const relationshipPopulationPromise = async ({
|
||||
data: siblingDoc[field.name][key],
|
||||
dataReference: resultingDoc,
|
||||
depth: populateDepth,
|
||||
fallbackLocale,
|
||||
field,
|
||||
key,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
@@ -187,7 +201,9 @@ const relationshipPopulationPromise = async ({
|
||||
data: siblingDoc[field.name],
|
||||
dataReference: resultingDoc,
|
||||
depth: populateDepth,
|
||||
fallbackLocale,
|
||||
field,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -11,11 +11,13 @@ type Args = {
|
||||
currentDepth: number
|
||||
depth: number
|
||||
doc: Record<string, unknown>
|
||||
fallbackLocale: null | string
|
||||
fieldPromises: Promise<void>[]
|
||||
fields: (Field | TabAsField)[]
|
||||
findMany: boolean
|
||||
flattenLocales: boolean
|
||||
global: SanitizedGlobalConfig | null
|
||||
locale: null | string
|
||||
overrideAccess: boolean
|
||||
populationPromises: Promise<void>[]
|
||||
req: PayloadRequest
|
||||
@@ -31,11 +33,13 @@ export const traverseFields = ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
fieldPromises,
|
||||
fields,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
@@ -52,11 +56,13 @@ export const traverseFields = ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
field,
|
||||
fieldPromises,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global,
|
||||
locale,
|
||||
overrideAccess,
|
||||
populationPromises,
|
||||
req,
|
||||
|
||||
@@ -23,14 +23,14 @@ type Args = {
|
||||
|
||||
async function findOne<T extends Record<string, unknown>>(args: Args): Promise<T> {
|
||||
const {
|
||||
slug,
|
||||
depth,
|
||||
draft: draftEnabled = false,
|
||||
globalConfig,
|
||||
overrideAccess = false,
|
||||
req: { locale, payload },
|
||||
req: { fallbackLocale, locale, payload },
|
||||
req,
|
||||
showHiddenFields,
|
||||
slug,
|
||||
} = args
|
||||
|
||||
try {
|
||||
@@ -51,9 +51,9 @@ async function findOne<T extends Record<string, unknown>>(args: Args): Promise<T
|
||||
// /////////////////////////////////////
|
||||
|
||||
let doc = await req.payload.db.findGlobal({
|
||||
slug,
|
||||
locale,
|
||||
req,
|
||||
slug,
|
||||
where: overrideAccess ? undefined : (accessResult as Where),
|
||||
})
|
||||
if (!doc) {
|
||||
@@ -100,7 +100,9 @@ async function findOne<T extends Record<string, unknown>>(args: Args): Promise<T
|
||||
context: req.context,
|
||||
depth,
|
||||
doc,
|
||||
fallbackLocale,
|
||||
global: globalConfig,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -31,7 +31,7 @@ async function findVersionByID<T extends TypeWithVersion<T> = any>(args: Argumen
|
||||
disableErrors,
|
||||
globalConfig,
|
||||
overrideAccess,
|
||||
req: { locale, payload, t },
|
||||
req: { fallbackLocale, locale, payload, t },
|
||||
req,
|
||||
showHiddenFields,
|
||||
} = args
|
||||
@@ -108,7 +108,9 @@ async function findVersionByID<T extends TypeWithVersion<T> = any>(args: Argumen
|
||||
currentDepth,
|
||||
depth,
|
||||
doc: result.version,
|
||||
fallbackLocale,
|
||||
global: globalConfig,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -35,7 +35,7 @@ async function findVersions<T extends TypeWithVersion<T>>(
|
||||
limit,
|
||||
overrideAccess,
|
||||
page,
|
||||
req: { locale, payload },
|
||||
req: { fallbackLocale, locale, payload },
|
||||
req,
|
||||
showHiddenFields,
|
||||
sort,
|
||||
@@ -97,8 +97,10 @@ async function findVersions<T extends TypeWithVersion<T>>(
|
||||
// Patch globalType onto version doc
|
||||
globalType: globalConfig.slug,
|
||||
},
|
||||
fallbackLocale,
|
||||
findMany: true,
|
||||
global: globalConfig,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -25,7 +25,7 @@ async function restoreVersion<T extends TypeWithVersion<T> = any>(args: Argument
|
||||
depth,
|
||||
globalConfig,
|
||||
overrideAccess,
|
||||
req: { payload, t },
|
||||
req: { fallbackLocale, locale, payload, t },
|
||||
req,
|
||||
showHiddenFields,
|
||||
} = args
|
||||
@@ -66,9 +66,9 @@ async function restoreVersion<T extends TypeWithVersion<T> = any>(args: Argument
|
||||
// /////////////////////////////////////
|
||||
|
||||
const previousDoc = await payload.findGlobal({
|
||||
slug: globalConfig.slug,
|
||||
depth,
|
||||
req,
|
||||
slug: globalConfig.slug,
|
||||
})
|
||||
|
||||
// /////////////////////////////////////
|
||||
@@ -76,23 +76,23 @@ async function restoreVersion<T extends TypeWithVersion<T> = any>(args: Argument
|
||||
// /////////////////////////////////////
|
||||
|
||||
const global = await payload.db.findGlobal({
|
||||
req,
|
||||
slug: globalConfig.slug,
|
||||
req,
|
||||
})
|
||||
|
||||
let result = rawVersion.version
|
||||
|
||||
if (global) {
|
||||
result = await payload.db.updateGlobal({
|
||||
slug: globalConfig.slug,
|
||||
data: result,
|
||||
req,
|
||||
slug: globalConfig.slug,
|
||||
})
|
||||
} else {
|
||||
result = await payload.db.createGlobal({
|
||||
slug: globalConfig.slug,
|
||||
data: result,
|
||||
req,
|
||||
slug: globalConfig.slug,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -105,7 +105,9 @@ async function restoreVersion<T extends TypeWithVersion<T> = any>(args: Argument
|
||||
context: req.context,
|
||||
depth,
|
||||
doc: result,
|
||||
fallbackLocale,
|
||||
global: globalConfig,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -32,15 +32,15 @@ async function update<TSlug extends keyof GeneratedTypes['globals']>(
|
||||
args: Args<GeneratedTypes['globals'][TSlug]>,
|
||||
): Promise<GeneratedTypes['globals'][TSlug]> {
|
||||
const {
|
||||
slug,
|
||||
autosave,
|
||||
depth,
|
||||
draft: draftArg,
|
||||
globalConfig,
|
||||
overrideAccess,
|
||||
req: { locale, payload },
|
||||
req: { fallbackLocale, locale, payload },
|
||||
req,
|
||||
showHiddenFields,
|
||||
slug,
|
||||
} = args
|
||||
|
||||
try {
|
||||
@@ -74,11 +74,11 @@ async function update<TSlug extends keyof GeneratedTypes['globals']>(
|
||||
// 2. Retrieve document
|
||||
// /////////////////////////////////////
|
||||
const { global, globalExists } = await getLatestGlobalVersion({
|
||||
slug,
|
||||
config: globalConfig,
|
||||
locale,
|
||||
payload,
|
||||
req,
|
||||
slug,
|
||||
where: query,
|
||||
})
|
||||
|
||||
@@ -97,7 +97,9 @@ async function update<TSlug extends keyof GeneratedTypes['globals']>(
|
||||
context: req.context,
|
||||
depth: 0,
|
||||
doc: globalJSON,
|
||||
fallbackLocale,
|
||||
global: globalConfig,
|
||||
locale,
|
||||
overrideAccess: true,
|
||||
req,
|
||||
showHiddenFields,
|
||||
@@ -175,15 +177,15 @@ async function update<TSlug extends keyof GeneratedTypes['globals']>(
|
||||
if (!shouldSaveDraft) {
|
||||
if (globalExists) {
|
||||
result = await payload.db.updateGlobal({
|
||||
slug,
|
||||
data: result,
|
||||
req,
|
||||
slug,
|
||||
})
|
||||
} else {
|
||||
result = await payload.db.createGlobal({
|
||||
slug,
|
||||
data: result,
|
||||
req,
|
||||
slug,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -218,7 +220,9 @@ async function update<TSlug extends keyof GeneratedTypes['globals']>(
|
||||
context: req.context,
|
||||
depth,
|
||||
doc: result,
|
||||
fallbackLocale: null,
|
||||
global: globalConfig,
|
||||
locale,
|
||||
overrideAccess,
|
||||
req,
|
||||
showHiddenFields,
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
"near": "nær"
|
||||
},
|
||||
"upload": {
|
||||
"crop": "Avling",
|
||||
"crop": "Beskjær",
|
||||
"cropToolDescription": "Dra hjørnene av det valgte området, tegn et nytt område eller juster verdiene nedenfor.",
|
||||
"dragAndDrop": "Dra og slipp en fil",
|
||||
"dragAndDropHere": "eller dra og slipp en fil her",
|
||||
|
||||
@@ -57,8 +57,10 @@ export async function getEntityPolicies<T extends Args>(args: T): Promise<Return
|
||||
if (typeof where === 'object') {
|
||||
const paginatedRes = await req.payload.find({
|
||||
collection: entity.slug,
|
||||
depth: 0,
|
||||
limit: 1,
|
||||
overrideAccess: true,
|
||||
pagination: false,
|
||||
req,
|
||||
where: {
|
||||
...where,
|
||||
@@ -79,6 +81,7 @@ export async function getEntityPolicies<T extends Args>(args: T): Promise<Return
|
||||
return req.payload.findByID({
|
||||
id,
|
||||
collection: entity.slug,
|
||||
depth: 0,
|
||||
overrideAccess: true,
|
||||
req,
|
||||
})
|
||||
@@ -98,8 +101,13 @@ export async function getEntityPolicies<T extends Args>(args: T): Promise<Return
|
||||
const mutablePolicies = policiesObj
|
||||
|
||||
if (accessLevel === 'field' && docBeingAccessed === undefined) {
|
||||
docBeingAccessed = await getEntityDoc()
|
||||
// assign docBeingAccessed first as the promise to avoid multiple calls to getEntityDoc
|
||||
docBeingAccessed = getEntityDoc().then((doc) => {
|
||||
docBeingAccessed = doc
|
||||
})
|
||||
}
|
||||
// awaiting the promise to ensure docBeingAccessed is assigned before it is used
|
||||
await docBeingAccessed
|
||||
|
||||
const data = req?.body
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-nested-docs",
|
||||
"version": "1.0.11",
|
||||
"version": "1.0.12",
|
||||
"description": "The official Nested Docs plugin for Payload",
|
||||
"repository": "https://github.com/payloadcms/payload",
|
||||
"license": "MIT",
|
||||
@@ -20,6 +20,9 @@
|
||||
"@payloadcms/eslint-config": "workspace:*",
|
||||
"payload": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"payload": "^0.18.5 || ^1.0.0 || ^2.0.0"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./src/index.ts",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-search",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"homepage:": "https://payloadcms.com",
|
||||
"repository": "git@github.com:payloadcms/plugin-search.git",
|
||||
"description": "Search plugin for Payload",
|
||||
|
||||
@@ -2,10 +2,12 @@ import en from './en.json'
|
||||
import es from './es.json'
|
||||
import fa from './fa.json'
|
||||
import fr from './fr.json'
|
||||
import pl from './pl.json'
|
||||
|
||||
export default {
|
||||
en,
|
||||
es,
|
||||
fa,
|
||||
fr,
|
||||
pl,
|
||||
}
|
||||
|
||||
22
packages/plugin-seo/src/translations/pl.json
Normal file
22
packages/plugin-seo/src/translations/pl.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"$schema": "./translation-schema.json",
|
||||
"plugin-seo": {
|
||||
"autoGenerate": "Wygeneruj automatycznie",
|
||||
"imageAutoGenerationTip": "Automatyczne generowanie pobierze wybrany główny obraz.",
|
||||
"bestPractices": "najlepsze praktyki",
|
||||
"lengthTipTitle": "Długość powinna wynosić od {{minLength}} do {{maxLength}} znaków. Po porady dotyczące pisania wysokiej jakości meta tytułów zobacz ",
|
||||
"lengthTipDescription": "Długość powinna wynosić od {{minLength}} do {{maxLength}} znaków. Po porady dotyczące pisania wysokiej jakości meta opisów zobacz ",
|
||||
"good": "Dobrze",
|
||||
"tooLong": "Zbyt długie",
|
||||
"tooShort": "Zbyt krótkie",
|
||||
"almostThere": "Prawie gotowe",
|
||||
"characterCount": "{{current}}/{{minLength}}-{{maxLength}} znaków, ",
|
||||
"charactersToGo": "pozostało {{characters}} znaków",
|
||||
"charactersLeftOver": "zostało {{characters}} znaków",
|
||||
"charactersTooMany": "{{characters}} znaków za dużo",
|
||||
"noImage": "Brak obrazu",
|
||||
"checksPassing": "{{current}}/{{max}} testów zakończonych pomyślnie",
|
||||
"preview": "Podgląd",
|
||||
"previewDescription": "Dokładne wyniki listowania mogą się różnić w zależności od treści i zgodności z kryteriami wyszukiwania."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/richtext-lexical",
|
||||
"version": "0.6.1",
|
||||
"version": "0.7.0",
|
||||
"description": "The officially supported Lexical richtext adapter for Payload",
|
||||
"repository": "https://github.com/payloadcms/payload",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -46,11 +46,13 @@ export const recurseNestedFields = ({
|
||||
currentDepth,
|
||||
depth,
|
||||
doc: data as any, // Looks like it's only needed for hooks and access control, so doesn't matter what we pass here right now
|
||||
fallbackLocale: req.fallbackLocale,
|
||||
fieldPromises: promises, // Not sure if what I pass in here makes sense. But it doesn't seem like it's used at all anyways
|
||||
fields,
|
||||
findMany,
|
||||
flattenLocales,
|
||||
global: null, // Pass from core? This is only needed for hooks, so we can leave this null for now
|
||||
locale: req.locale,
|
||||
overrideAccess,
|
||||
populationPromises, // This is not the same as populationPromises passed into this recurseNestedFields. These are just promises resolved at the very end.
|
||||
req,
|
||||
|
||||
@@ -1332,11 +1332,6 @@
|
||||
slate-hyperscript "0.81.3"
|
||||
slate-react "0.92.0"
|
||||
|
||||
"@pkgjs/parseargs@^0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@polka/url@^1.0.0-next.20":
|
||||
version "1.0.0-next.23"
|
||||
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.23.tgz#498e41218ab3b6a1419c735e5c6ae2c5ed609b6c"
|
||||
@@ -2750,15 +2745,6 @@ cliui@^7.0.2:
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
cliui@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
|
||||
integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.1"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
clone-deep@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
|
||||
@@ -4260,9 +4246,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
@@ -4515,15 +4501,6 @@ isomorphic-unfetch@^3.0.0:
|
||||
node-fetch "^2.6.1"
|
||||
unfetch "^4.2.0"
|
||||
|
||||
jackspeak@2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.1.1.tgz#2a42db4cfbb7e55433c28b6f75d8b796af9669cd"
|
||||
integrity sha512-juf9stUEwUaILepraGOWIJTLwg48bUnBmRqd2ln2Os1sW987zeoj/hzhbvRB95oMuS2ZTpjULmdwHNX4rzZIZw==
|
||||
dependencies:
|
||||
cliui "^8.0.1"
|
||||
optionalDependencies:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
jest-util@^29.7.0:
|
||||
version "29.7.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
|
||||
|
||||
@@ -1540,11 +1540,6 @@
|
||||
slate-hyperscript "0.81.3"
|
||||
slate-react "0.92.0"
|
||||
|
||||
"@pkgjs/parseargs@^0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@polka/url@^1.0.0-next.20":
|
||||
version "1.0.0-next.24"
|
||||
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.24.tgz#58601079e11784d20f82d0585865bb42305c4df3"
|
||||
@@ -3188,15 +3183,6 @@ cliui@^7.0.2:
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
cliui@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
|
||||
integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.1"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
clone-deep@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
|
||||
@@ -5120,9 +5106,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
@@ -5385,15 +5371,6 @@ isomorphic-unfetch@^3.0.0:
|
||||
node-fetch "^2.6.1"
|
||||
unfetch "^4.2.0"
|
||||
|
||||
jackspeak@2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.1.1.tgz#2a42db4cfbb7e55433c28b6f75d8b796af9669cd"
|
||||
integrity sha512-juf9stUEwUaILepraGOWIJTLwg48bUnBmRqd2ln2Os1sW987zeoj/hzhbvRB95oMuS2ZTpjULmdwHNX4rzZIZw==
|
||||
dependencies:
|
||||
cliui "^8.0.1"
|
||||
optionalDependencies:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
jest-util@^29.7.0:
|
||||
version "29.7.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
|
||||
|
||||
@@ -1749,11 +1749,6 @@
|
||||
slate-hyperscript "0.81.3"
|
||||
slate-react "0.92.0"
|
||||
|
||||
"@pkgjs/parseargs@^0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@polka/url@^1.0.0-next.20":
|
||||
version "1.0.0-next.24"
|
||||
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.24.tgz#58601079e11784d20f82d0585865bb42305c4df3"
|
||||
@@ -3415,15 +3410,6 @@ cliui@^7.0.2:
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
cliui@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
|
||||
integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.1"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
clone-deep@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
|
||||
@@ -5485,9 +5471,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
@@ -5750,15 +5736,6 @@ isomorphic-unfetch@^3.0.0:
|
||||
node-fetch "^2.6.1"
|
||||
unfetch "^4.2.0"
|
||||
|
||||
jackspeak@2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.1.1.tgz#2a42db4cfbb7e55433c28b6f75d8b796af9669cd"
|
||||
integrity sha512-juf9stUEwUaILepraGOWIJTLwg48bUnBmRqd2ln2Os1sW987zeoj/hzhbvRB95oMuS2ZTpjULmdwHNX4rzZIZw==
|
||||
dependencies:
|
||||
cliui "^8.0.1"
|
||||
optionalDependencies:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
jest-util@^29.7.0:
|
||||
version "29.7.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
|
||||
|
||||
@@ -4,7 +4,7 @@ import { mapAsync } from '../../packages/payload/src/utilities/mapAsync'
|
||||
import { buildConfigWithDefaults } from '../buildConfigWithDefaults'
|
||||
import { devUser } from '../credentials'
|
||||
import { AuthDebug } from './AuthDebug'
|
||||
import { namedSaveToJWTValue, saveToJWTKey, slug } from './shared'
|
||||
import { apiKeysSlug, namedSaveToJWTValue, saveToJWTKey, slug } from './shared'
|
||||
|
||||
export default buildConfigWithDefaults({
|
||||
admin: {
|
||||
@@ -171,11 +171,7 @@ export default buildConfigWithDefaults({
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: 'api-keys',
|
||||
labels: {
|
||||
singular: 'API Key',
|
||||
plural: 'API Keys',
|
||||
},
|
||||
slug: apiKeysSlug,
|
||||
access: {
|
||||
read: ({ req: { user } }) => {
|
||||
if (user.collection === 'api-keys') {
|
||||
@@ -193,6 +189,10 @@ export default buildConfigWithDefaults({
|
||||
useAPIKey: true,
|
||||
},
|
||||
fields: [],
|
||||
labels: {
|
||||
plural: 'API Keys',
|
||||
singular: 'API Key',
|
||||
},
|
||||
},
|
||||
{
|
||||
slug: 'public-users',
|
||||
|
||||
@@ -2,28 +2,34 @@ import type { Page } from '@playwright/test'
|
||||
|
||||
import { expect, test } from '@playwright/test'
|
||||
|
||||
import payload from '../../packages/payload/src'
|
||||
import { initPageConsoleErrorCatch, login, saveDocAndAssert } from '../helpers'
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil'
|
||||
import { initPayloadE2E } from '../helpers/configHelpers'
|
||||
import { slug } from './shared'
|
||||
import { apiKeysSlug, slug } from './shared'
|
||||
|
||||
/**
|
||||
* TODO: Auth
|
||||
* create first user
|
||||
* unlock
|
||||
* generate api key
|
||||
* log out
|
||||
*/
|
||||
|
||||
const { beforeAll, describe } = test
|
||||
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
describe('auth', () => {
|
||||
let page: Page
|
||||
let url: AdminUrlUtil
|
||||
let serverURL: string
|
||||
let apiURL: string
|
||||
|
||||
beforeAll(async ({ browser }) => {
|
||||
const { serverURL } = await initPayloadE2E(__dirname)
|
||||
url = new AdminUrlUtil(serverURL, slug)
|
||||
serverURL = (await initPayloadE2E(__dirname)).serverURL
|
||||
apiURL = `${serverURL}/api`
|
||||
|
||||
const context = await browser.newContext()
|
||||
page = await context.newPage()
|
||||
@@ -36,6 +42,10 @@ describe('auth', () => {
|
||||
})
|
||||
|
||||
describe('authenticated users', () => {
|
||||
beforeAll(async ({ browser }) => {
|
||||
url = new AdminUrlUtil(serverURL, slug)
|
||||
})
|
||||
|
||||
test('should allow change password', async () => {
|
||||
await page.goto(url.account)
|
||||
const emailBeforeSave = await page.locator('#field-email').inputValue()
|
||||
@@ -62,4 +72,56 @@ describe('auth', () => {
|
||||
await expect(page.locator('#use-auth-result')).toHaveText('Goodbye, world!')
|
||||
})
|
||||
})
|
||||
|
||||
describe('api-keys', () => {
|
||||
let user
|
||||
|
||||
beforeAll(async () => {
|
||||
url = new AdminUrlUtil(serverURL, apiKeysSlug)
|
||||
|
||||
user = await payload.create({
|
||||
collection: apiKeysSlug,
|
||||
data: {
|
||||
enableAPIKey: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('should enable api key', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
// click enable api key checkbox
|
||||
await page.locator('#field-enableAPIKey').click()
|
||||
|
||||
// assert that the value is set
|
||||
const apiKey = await page.locator('#apiKey').inputValue()
|
||||
expect(apiKey).toBeDefined()
|
||||
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
expect(await page.locator('#apiKey').inputValue()).toStrictEqual(apiKey)
|
||||
})
|
||||
|
||||
test('should disable api key', async () => {
|
||||
await page.goto(url.edit(user.id))
|
||||
|
||||
// click enable api key checkbox
|
||||
await page.locator('#field-enableAPIKey').click()
|
||||
|
||||
// assert that the apiKey field is hidden
|
||||
await expect(page.locator('#apiKey')).toBeHidden()
|
||||
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
// use the api key in a fetch to assert that it is disabled
|
||||
const response = await fetch(`${apiURL}/${apiKeysSlug}/me`, {
|
||||
headers: {
|
||||
...headers,
|
||||
Authorization: `${slug} API-Key ${user.apiKey}`,
|
||||
},
|
||||
}).then((res) => res.json())
|
||||
|
||||
expect(response.user).toBeNull()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export const slug = 'users'
|
||||
export const apiKeysSlug = 'api-keys'
|
||||
|
||||
export const namedSaveToJWTValue = 'namedSaveToJWT value'
|
||||
|
||||
|
||||
@@ -35,6 +35,13 @@ const databaseAdapters = {
|
||||
connectionString: process.env.POSTGRES_URL || 'postgres://127.0.0.1:5432/payloadtests',
|
||||
},
|
||||
}),
|
||||
'postgres-custom-schema': postgresAdapter({
|
||||
migrationDir,
|
||||
pool: {
|
||||
connectionString: process.env.POSTGRES_URL || 'postgres://127.0.0.1:5432/payloadtests',
|
||||
},
|
||||
schemaName: 'custom',
|
||||
}),
|
||||
'postgres-uuid': postgresAdapter({
|
||||
idType: 'uuid',
|
||||
migrationDir,
|
||||
|
||||
@@ -3,7 +3,7 @@ import fs from 'fs'
|
||||
import { GraphQLClient } from 'graphql-request'
|
||||
import path from 'path'
|
||||
|
||||
import type { DrizzleDB } from '../../packages/db-postgres/src/types'
|
||||
import type { PostgresAdapter } from '../../packages/db-postgres/src/types'
|
||||
import type { TypeWithID } from '../../packages/payload/src/collections/config/types'
|
||||
import type { PayloadRequest } from '../../packages/payload/src/express/types'
|
||||
|
||||
@@ -44,10 +44,14 @@ describe('database', () => {
|
||||
describe('migrations', () => {
|
||||
beforeAll(async () => {
|
||||
if (process.env.PAYLOAD_DROP_DATABASE === 'true' && 'drizzle' in payload.db) {
|
||||
const drizzle = payload.db.drizzle as DrizzleDB
|
||||
// @ts-expect-error drizzle raw sql typing
|
||||
await drizzle.execute(sql`drop schema public cascade;
|
||||
create schema public;`)
|
||||
const db = payload.db as unknown as PostgresAdapter
|
||||
const drizzle = db.drizzle
|
||||
const schemaName = db.schemaName || 'public'
|
||||
|
||||
await drizzle.execute(
|
||||
sql.raw(`drop schema ${schemaName} cascade;
|
||||
create schema ${schemaName};`),
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -21,8 +21,13 @@ const ArrayFields: CollectionConfig = {
|
||||
fields: [
|
||||
{
|
||||
name: 'text',
|
||||
required: true,
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'localizedText',
|
||||
type: 'text',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'subArray',
|
||||
|
||||
@@ -32,26 +32,34 @@ const IndexedFields: CollectionConfig = {
|
||||
fields: [
|
||||
{
|
||||
name: 'text',
|
||||
type: 'text',
|
||||
index: true,
|
||||
required: true,
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'uniqueText',
|
||||
type: 'text',
|
||||
unique: true,
|
||||
},
|
||||
{
|
||||
name: 'uniqueRequiredText',
|
||||
type: 'text',
|
||||
defaultValue: 'uniqueRequired',
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
{
|
||||
name: 'point',
|
||||
type: 'point',
|
||||
},
|
||||
{
|
||||
name: 'group',
|
||||
type: 'group',
|
||||
fields: [
|
||||
{
|
||||
name: 'localizedUnique',
|
||||
localized: true,
|
||||
type: 'text',
|
||||
localized: true,
|
||||
unique: true,
|
||||
},
|
||||
{
|
||||
@@ -64,25 +72,24 @@ const IndexedFields: CollectionConfig = {
|
||||
type: 'point',
|
||||
},
|
||||
],
|
||||
type: 'group',
|
||||
},
|
||||
{
|
||||
type: 'collapsible',
|
||||
fields: [
|
||||
{
|
||||
name: 'collapsibleLocalizedUnique',
|
||||
localized: true,
|
||||
type: 'text',
|
||||
localized: true,
|
||||
unique: true,
|
||||
},
|
||||
{
|
||||
name: 'collapsibleTextUnique',
|
||||
label: 'collapsibleTextUnique',
|
||||
type: 'text',
|
||||
label: 'collapsibleTextUnique',
|
||||
unique: true,
|
||||
},
|
||||
],
|
||||
label: 'Collapsible',
|
||||
type: 'collapsible',
|
||||
},
|
||||
],
|
||||
versions: true,
|
||||
|
||||
@@ -249,6 +249,7 @@ describe('fields', () => {
|
||||
unique: uniqueText,
|
||||
},
|
||||
text: 'text',
|
||||
uniqueRequiredText: 'text',
|
||||
uniqueText,
|
||||
},
|
||||
})
|
||||
@@ -814,6 +815,95 @@ describe('fields', () => {
|
||||
).toHaveValue(`${assertGroupText3} duplicate`)
|
||||
})
|
||||
})
|
||||
test('should bulk update', async () => {
|
||||
await Promise.all([
|
||||
payload.create({
|
||||
collection: 'array-fields',
|
||||
data: {
|
||||
title: 'for test 1',
|
||||
items: [
|
||||
{
|
||||
text: 'test 1',
|
||||
},
|
||||
{
|
||||
text: 'test 2',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
payload.create({
|
||||
collection: 'array-fields',
|
||||
data: {
|
||||
title: 'for test 2',
|
||||
items: [
|
||||
{
|
||||
text: 'test 3',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
payload.create({
|
||||
collection: 'array-fields',
|
||||
data: {
|
||||
title: 'for test 3',
|
||||
items: [
|
||||
{
|
||||
text: 'test 4',
|
||||
},
|
||||
{
|
||||
text: 'test 5',
|
||||
},
|
||||
{
|
||||
text: 'test 6',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
])
|
||||
|
||||
const bulkText = 'Bulk update text'
|
||||
await page.goto(url.list)
|
||||
await page.waitForSelector('.table > table > tbody > tr td.cell-title')
|
||||
const rows = page.locator('.table > table > tbody > tr', {
|
||||
has: page.locator('td.cell-title span', {
|
||||
hasText: 'for test',
|
||||
}),
|
||||
})
|
||||
const count = await rows.count()
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
await rows
|
||||
.nth(i)
|
||||
.locator('td.cell-_select .checkbox-input__input > input[type="checkbox"]')
|
||||
.check()
|
||||
}
|
||||
await page.locator('.edit-many__toggle').click()
|
||||
await page.locator('.field-select .rs__control').click()
|
||||
|
||||
const arrayOption = page.locator('.rs__option', {
|
||||
hasText: exactText('Items'),
|
||||
})
|
||||
|
||||
await expect(arrayOption).toBeVisible()
|
||||
|
||||
await arrayOption.click()
|
||||
const addRowButton = page.locator('#field-items > .btn.array-field__add-row')
|
||||
|
||||
await expect(addRowButton).toBeVisible()
|
||||
|
||||
await addRowButton.click()
|
||||
|
||||
const targetInput = page.locator('#field-items__0__text')
|
||||
|
||||
await expect(targetInput).toBeVisible()
|
||||
|
||||
await targetInput.fill(bulkText)
|
||||
|
||||
await page.locator('.form-submit button[type="submit"].edit-many__publish').click()
|
||||
await expect(page.locator('.Toastify__toast--success')).toContainText(
|
||||
'Updated 3 Array Fields successfully.',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('tabs', () => {
|
||||
|
||||
@@ -424,7 +424,7 @@ describe('Fields', () => {
|
||||
const definitions: Record<string, IndexDirection> = {}
|
||||
const options: Record<string, IndexOptions> = {}
|
||||
|
||||
beforeEach(() => {
|
||||
beforeAll(() => {
|
||||
indexes = (payload.db as MongooseAdapter).collections[
|
||||
'indexed-fields'
|
||||
].schema.indexes() as [Record<string, IndexDirection>, IndexOptions]
|
||||
@@ -441,8 +441,13 @@ describe('Fields', () => {
|
||||
expect(definitions.text).toEqual(1)
|
||||
})
|
||||
|
||||
it('should have unique indexes', () => {
|
||||
it('should have unique sparse indexes when field is not required', () => {
|
||||
expect(definitions.uniqueText).toEqual(1)
|
||||
expect(options.uniqueText).toMatchObject({ sparse: true, unique: true })
|
||||
})
|
||||
|
||||
it('should have unique indexes that are not sparse when field is required', () => {
|
||||
expect(definitions.uniqueRequiredText).toEqual(1)
|
||||
expect(options.uniqueText).toMatchObject({ unique: true })
|
||||
})
|
||||
|
||||
@@ -594,6 +599,25 @@ describe('Fields', () => {
|
||||
return result.error
|
||||
}).toBeDefined()
|
||||
})
|
||||
|
||||
it('should not throw validation error saving multiple null values for unique fields', async () => {
|
||||
const data = {
|
||||
text: 'a',
|
||||
uniqueRequiredText: 'a',
|
||||
// uniqueText omitted on purpose
|
||||
}
|
||||
await payload.create({
|
||||
collection: 'indexed-fields',
|
||||
data,
|
||||
})
|
||||
data.uniqueRequiredText = 'b'
|
||||
const result = await payload.create({
|
||||
collection: 'indexed-fields',
|
||||
data,
|
||||
})
|
||||
|
||||
expect(result.id).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('array', () => {
|
||||
@@ -620,6 +644,51 @@ describe('Fields', () => {
|
||||
expect(doc.localized).toMatchObject(arrayDefaultValue)
|
||||
})
|
||||
|
||||
it('should create and update localized subfields with versions', async () => {
|
||||
const doc = await payload.create({
|
||||
collection,
|
||||
data: {
|
||||
items: [
|
||||
{
|
||||
localizedText: 'test',
|
||||
text: 'required',
|
||||
},
|
||||
],
|
||||
localized: [
|
||||
{
|
||||
text: 'english',
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
const spanish = await payload.update({
|
||||
id: doc.id,
|
||||
collection,
|
||||
data: {
|
||||
items: [
|
||||
{
|
||||
id: doc.items[0].id,
|
||||
localizedText: 'spanish',
|
||||
text: 'required',
|
||||
},
|
||||
],
|
||||
},
|
||||
locale: 'es',
|
||||
})
|
||||
|
||||
const result = await payload.findByID({
|
||||
id: doc.id,
|
||||
collection,
|
||||
locale: 'all',
|
||||
})
|
||||
|
||||
expect(doc.items[0].localizedText).toStrictEqual('test')
|
||||
expect(spanish.items[0].localizedText).toStrictEqual('spanish')
|
||||
expect(result.items[0].localizedText.en).toStrictEqual('test')
|
||||
expect(result.items[0].localizedText.es).toStrictEqual('spanish')
|
||||
})
|
||||
|
||||
it('should create with nested array', async () => {
|
||||
const subArrayText = 'something expected'
|
||||
const doc = await payload.create({
|
||||
|
||||
@@ -20,7 +20,7 @@ export async function resetDB(_payload: Payload, collectionSlugs: string[]) {
|
||||
return
|
||||
}
|
||||
const queries = Object.values(schema).map((table: any) => {
|
||||
return sql.raw(`DELETE FROM ${table.dbName}`)
|
||||
return sql.raw(`DELETE FROM ${db.schemaName ? db.schemaName + '.' : ''}${table.dbName}`)
|
||||
})
|
||||
|
||||
await db.drizzle.transaction(async (trx) => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { SanitizedConfig } from '../../packages/payload/src/config/types'
|
||||
|
||||
import { APIError } from '../../packages/payload/errors'
|
||||
import { buildConfigWithDefaults } from '../buildConfigWithDefaults'
|
||||
import AfterOperation from './collections/AfterOperation'
|
||||
import ChainingHooks from './collections/ChainingHooks'
|
||||
@@ -24,6 +25,18 @@ export const HooksConfig: Promise<SanitizedConfig> = buildConfigWithDefaults({
|
||||
DataHooks,
|
||||
],
|
||||
globals: [DataHooksGlobal],
|
||||
endpoints: [
|
||||
{
|
||||
path: '/throw-to-after-error',
|
||||
method: 'get',
|
||||
handler: () => {
|
||||
throw new APIError("I'm a teapot", 418)
|
||||
},
|
||||
},
|
||||
],
|
||||
hooks: {
|
||||
afterError: () => console.log('Running afterError hook'),
|
||||
},
|
||||
onInit: async (payload) => {
|
||||
await seedHooksUsers(payload)
|
||||
await payload.create({
|
||||
|
||||
@@ -462,4 +462,13 @@ describe('Hooks', () => {
|
||||
expect(doc.field_globalAndField).toStrictEqual(globalAndFieldString + globalAndFieldString)
|
||||
})
|
||||
})
|
||||
|
||||
describe('config level after error hook', () => {
|
||||
it('should handle error', async () => {
|
||||
const response = await fetch(`${apiUrl}/throw-to-after-error`)
|
||||
const body = await response.json()
|
||||
expect(response.status).toEqual(418)
|
||||
expect(body).toEqual({ errors: [{ message: "I'm a teapot" }] })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -157,6 +157,7 @@ describe('Localization', () => {
|
||||
id,
|
||||
collection: localizedPostsSlug,
|
||||
data: {
|
||||
localizedCheckbox: false,
|
||||
title: spanishTitle,
|
||||
},
|
||||
locale: spanishLocale,
|
||||
@@ -174,8 +175,6 @@ describe('Localization', () => {
|
||||
await changeLocale(page, spanishLocale)
|
||||
await expect(page.locator('#field-title')).toHaveValue(spanishTitle)
|
||||
|
||||
// click checkbox manually
|
||||
await page.locator('#field-localizedCheckbox').click()
|
||||
await expect(page.locator('#field-localizedCheckbox')).not.toBeChecked()
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user