Compare commits
25 Commits
payload/2.
...
feat/trans
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26a2f8d0d7 | ||
|
|
c7a02803a0 | ||
|
|
bcdd2d626f | ||
|
|
67682248c8 | ||
|
|
7c52d6ee28 | ||
|
|
bc65b53ce5 | ||
|
|
c8cc6ea1cc | ||
|
|
4e05e6fd85 | ||
|
|
6988a68eaf | ||
|
|
a272692726 | ||
|
|
229e4459cb | ||
|
|
056585ed31 | ||
|
|
b545433ee6 | ||
|
|
4c938b5f9e | ||
|
|
f1d8fa9999 | ||
|
|
1670a603f6 | ||
|
|
22f1fa8fc9 | ||
|
|
370e8d1938 | ||
|
|
3a3eab761e | ||
|
|
238f7e1b94 | ||
|
|
58e2083882 | ||
|
|
20cde242fb | ||
|
|
f50a392d59 | ||
|
|
fa1740d906 | ||
|
|
ebd5e6ae8f |
12
.github/ISSUE_TEMPLATE/1.bug_report.yml
vendored
12
.github/ISSUE_TEMPLATE/1.bug_report.yml
vendored
@@ -10,7 +10,12 @@ body:
|
||||
id: reproduction-link
|
||||
attributes:
|
||||
label: Link to reproduction
|
||||
description: Please add a link to a reproduction. See the fork [reproduction-guide](https://github.com/payloadcms/payload/blob/main/.github/reproduction-guide.md) for more information.
|
||||
description: Want us to look into your issue faster? Follow the [reproduction-guide](https://github.com/payloadcms/payload/blob/main/.github/reproduction-guide.md) for more information.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the Bug
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
@@ -19,11 +24,6 @@ body:
|
||||
description: Steps to reproduce the behavior, please provide a clear description of how to reproduce the issue, based on the linked minimal reproduction. Screenshots can be provided in the issue body below. If using code blocks, make sure that [syntax highlighting is correct](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlighting) and double check that the rendered preview is not broken.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the Bug
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
|
||||
15
.github/reproduction-guide.md
vendored
15
.github/reproduction-guide.md
vendored
@@ -1,10 +1,11 @@
|
||||
# Reproduction Guide
|
||||
|
||||
1. [fork](https://github.com/payloadcms/payload/fork) this repo
|
||||
2. run `yarn` to install dependencies
|
||||
3. open up the `test/_community` directory
|
||||
4. add any necessary `collections/globals/fields` in this directory to recreate the issue you are experiencing
|
||||
5. run `yarn dev _community` to start the admin panel
|
||||
1. [Fork](https://github.com/payloadcms/payload/fork) this repo
|
||||
2. Optionally, create a new branch for your reproduction
|
||||
3. Run `pnpm install` to install dependencies
|
||||
4. Open up the `test/_community` directory
|
||||
5. Add any necessary `collections/globals/fields` in this directory to recreate the issue you are experiencing
|
||||
6. Run `pnpm dev _community` to start the admin panel
|
||||
|
||||
**NOTE:** The goal is to isolate the problem by reducing the number of `collections/globals/fields` you add to the `test/_community` folder. This folder is _not_ meant for you to copy your project into, but rather recreate the issue you are experiencing with minimal config.
|
||||
|
||||
@@ -21,7 +22,7 @@
|
||||
- `config.ts` - This is the _granular_ Payload config for testing. It should be as lightweight as possible. Reference existing configs for an example
|
||||
- `int.spec.ts` [Optional] - This is the test file run by jest. Any test file must have a `*int.spec.ts` suffix.
|
||||
- `e2e.spec.ts` [Optional] - This is the end-to-end test file that will load up the admin UI using the above config and run Playwright tests.
|
||||
- `payload-types.ts` - Generated types from `config.ts`. Generate this file by running `yarn dev:generate-types _community`.
|
||||
- `payload-types.ts` - Generated types from `config.ts`. Generate this file by running `pnpm dev:generate-types _community`.
|
||||
|
||||
The directory split up in this way specifically to reduce friction when creating tests and to add the ability to boot up Payload with that specific config. You should modify the files in `test/_community` to get started.
|
||||
|
||||
@@ -44,7 +45,7 @@ There are a couple ways run integration tests:
|
||||
- **Manually** - you can run all int tests in the `/test/_community/int.spec.ts` file by running the following command:
|
||||
|
||||
```bash
|
||||
yarn test:int _community
|
||||
pnpm test:int _community
|
||||
```
|
||||
|
||||
### Running E2E tests (Admin Panel UI tests)
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
## [2.0.10](https://github.com/payloadcms/payload/compare/v2.0.9...v2.0.10) (2023-10-17)
|
||||
|
||||
### Features
|
||||
|
||||
* filesRequired is optional for uploads ([#3668](https://github.com/payloadcms/payload/pull/3668)) ([48de897](https://github.com/payloadcms/payload/commit/48de89794b2c5d94183090b0830fd355d8d6c6f3))
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Register first user verify update missing transaction id / req ([#3665](https://github.com/payloadcms/payload/pull/3665)) ([68c5a5751](https://github.com/payloadcms/payload/commit/68c5a57515ffbba37c9194a75d0f672bdb10d96b))
|
||||
|
||||
## [2.0.8](https://github.com/payloadcms/payload/compare/v2.0.7...v2.0.8) (2023-10-17)
|
||||
|
||||
|
||||
@@ -11,19 +11,23 @@ keywords: documentation, getting started, guide, Content Management System, cms,
|
||||
title="Payload Introduction - Closing the Gap Between Headless CMS and Application Frameworks"
|
||||
/>
|
||||
|
||||
Payload is a headless CMS and application framework. It's meant to provide a massive boost to your
|
||||
development process, but importantly, stay out of your way as your apps get more complex.
|
||||
|
||||
<Banner type="success">
|
||||
Payload is a headless CMS and application framework. It’s meant to provide a massive boost to your
|
||||
development process, but importantly, stay out of your way as your apps get more complex.
|
||||
<strong>Payload 2.0 has been released!</strong>
|
||||
<br />
|
||||
Includes Postgres support, Live Preview, Lexical Editor, and more. <a href="/blog/payload-2-0">Read the announcement</a>.
|
||||
</Banner>
|
||||
|
||||
Out of the box, Payload gives you a lot of the things that you often need when developing a new website, web app, or native app:
|
||||
|
||||
- A MongoDB database to store your data
|
||||
- A database to store your data (Postgres and MongoDB supported)
|
||||
- A way to store, retrieve, and manipulate data of any shape via full REST and GraphQL APIs
|
||||
- Authentication—complete with commonly required functionality like registration, email verification, login, & password reset
|
||||
- Deep access control to your data, based on document or field-level functions
|
||||
- File storage and access control
|
||||
- A beautiful admin UI that’s generated specifically to suit your data
|
||||
- A beautiful admin UI that's generated specifically to suit your data
|
||||
|
||||
## What does "headless" mean?
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Form Builder Example Front-End
|
||||
|
||||
This is a [Next.js](https://nextjs.org) app using the [Pages Router](https://nextjs.org/docs/pages). It was made explicitly for Payload's [Form Builder Example](https://github.com/payloadcms/payload/tree/master/examples/form-builder/payload).
|
||||
This is a [Next.js](https://nextjs.org) app using the [Pages Router](https://nextjs.org/docs/pages). It was made explicitly for Payload's [Form Builder Example](https://github.com/payloadcms/payload/tree/main/examples/form-builder/payload).
|
||||
|
||||
> This example uses the Pages Router, the legacy API of Next.js. If your app is using the latest [App Router](https://nextjs.org/docs/app), we will add an example for that soon.
|
||||
|
||||
@@ -8,7 +8,7 @@ This is a [Next.js](https://nextjs.org) app using the [Pages Router](https://nex
|
||||
|
||||
### Payload
|
||||
|
||||
First you'll need a running Payload app. There is one made explicitly for this example and [can be found here](https://github.com/payloadcms/payload/tree/master/examples/form-builder/payload). If you have not done so already, clone it down and follow the setup instructions there.
|
||||
First you'll need a running Payload app. There is one made explicitly for this example and [can be found here](https://github.com/payloadcms/payload/tree/main/examples/form-builder/payload). If you have not done so already, clone it down and follow the setup instructions there.
|
||||
|
||||
### Next.js App
|
||||
|
||||
@@ -18,7 +18,7 @@ First you'll need a running Payload app. There is one made explicitly for this e
|
||||
4. `yarn dev` or `npm run dev` to start the server
|
||||
5. `open http://localhost:3001` to see the result
|
||||
|
||||
Once running you will find a couple seeded pages on your local environment with some basic instructions. You can also start editing the pages by modifying the documents within Payload. See the [Form Builder Example](https://github.com/payloadcms/payload/tree/master/examples/form-builder/payload) for full details.
|
||||
Once running you will find a couple seeded pages on your local environment with some basic instructions. You can also start editing the pages by modifying the documents within Payload. See the [Form Builder Example](https://github.com/payloadcms/payload/tree/main/examples/form-builder/payload) for full details.
|
||||
|
||||
## Learn More
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Payload Live Preview Example Front-End
|
||||
|
||||
This is a [Next.js](https://nextjs.org) app using the [App Router](https://nextjs.org/docs/app). It was made explicitly for Payload's [Live Preview Example](https://github.com/payloadcms/payload/tree/master/examples/live-preview/payload).
|
||||
This is a [Next.js](https://nextjs.org) app using the [App Router](https://nextjs.org/docs/app). It was made explicitly for Payload's [Live Preview Example](https://github.com/payloadcms/payload/tree/main/examples/live-preview/payload).
|
||||
|
||||
> This example uses the App Router, the latest API of Next.js. If your app is using the legacy [Pages Router](https://nextjs.org/docs/pages), check out the official [Pages Router Example](https://github.com/payloadcms/payload/tree/master/examples/live-preview/next-pages).
|
||||
> This example uses the App Router, the latest API of Next.js. If your app is using the legacy [Pages Router](https://nextjs.org/docs/pages), check out the official [Pages Router Example](https://github.com/payloadcms/payload/tree/main/examples/live-preview/next-pages).
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Payload
|
||||
|
||||
First you'll need a running Payload app. There is one made explicitly for this example and [can be found here](https://github.com/payloadcms/payload/tree/master/examples/live-preview/payload). If you have not done so already, clone it down and follow the setup instructions there. This will provide all the necessary APIs that your Next.js app requires for authentication.
|
||||
First you'll need a running Payload app. There is one made explicitly for this example and [can be found here](https://github.com/payloadcms/payload/tree/main/examples/live-preview/payload). If you have not done so already, clone it down and follow the setup instructions there. This will provide all the necessary APIs that your Next.js app requires for authentication.
|
||||
|
||||
### Next.js
|
||||
|
||||
@@ -18,7 +18,7 @@ First you'll need a running Payload app. There is one made explicitly for this e
|
||||
4. `yarn dev` or `npm run dev` to start the server
|
||||
5. `open http://localhost:3001` to see the result
|
||||
|
||||
Once running you will find a couple seeded pages on your local environment with some basic instructions. You can also start editing the pages by modifying the documents within Payload. See the [Live Preview Example](https://github.com/payloadcms/payload/tree/master/examples/live-preview/payload) for full details.
|
||||
Once running you will find a couple seeded pages on your local environment with some basic instructions. You can also start editing the pages by modifying the documents within Payload. See the [Live Preview Example](https://github.com/payloadcms/payload/tree/main/examples/live-preview/payload) for full details.
|
||||
|
||||
## Learn More
|
||||
|
||||
@@ -32,6 +32,6 @@ You can check out [the Payload GitHub repository](https://github.com/payloadcms/
|
||||
|
||||
## Deployment
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new) from the creators of Next.js. You could also combine this app into a [single Express server](https://github.com/payloadcms/payload/tree/master/examples/custom-server) and deploy in to [Payload Cloud](https://payloadcms.com/new/import).
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new) from the creators of Next.js. You could also combine this app into a [single Express server](https://github.com/payloadcms/payload/tree/main/examples/custom-server) and deploy in to [Payload Cloud](https://payloadcms.com/new/import).
|
||||
|
||||
Check out our [Payload deployment documentation](https://payloadcms.com/docs/production/deployment) or the [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/live-preview-react": "^1.0.0-beta.3",
|
||||
"@payloadcms/live-preview-react": "latest",
|
||||
"escape-html": "^1.0.3",
|
||||
"next": "^13.4.8",
|
||||
"payload-admin-bar": "^1.0.6",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,14 @@
|
||||
# Payload Live Preview Example Front-End
|
||||
|
||||
This is a [Next.js](https://nextjs.org) app using the [Pages Router](https://nextjs.org/docs/pages). It was made explicitly for Payload's [Live Preview Example](https://github.com/payloadcms/payload/tree/master/examples/live-preview/payload).
|
||||
This is a [Next.js](https://nextjs.org) app using the [Pages Router](https://nextjs.org/docs/pages). It was made explicitly for Payload's [Live Preview Example](https://github.com/payloadcms/payload/tree/main/examples/live-preview/payload).
|
||||
|
||||
> This example uses the Pages Router, the legacy API of Next.js. If your app is using the latest [App Router](https://nextjs.org/docs/app), check out the official [App Router Example](https://github.com/payloadcms/payload/tree/master/examples/live-preview/next-app).
|
||||
> This example uses the Pages Router, the legacy API of Next.js. If your app is using the latest [App Router](https://nextjs.org/docs/app), check out the official [App Router Example](https://github.com/payloadcms/payload/tree/main/examples/live-preview/next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Payload
|
||||
|
||||
First you'll need a running Payload app. There is one made explicitly for this example and [can be found here](https://github.com/payloadcms/payload/tree/master/examples/live-preview/payload). If you have not done so already, clone it down and follow the setup instructions there. This will provide all the necessary APIs that your Next.js app requires for authentication.
|
||||
First you'll need a running Payload app. There is one made explicitly for this example and [can be found here](https://github.com/payloadcms/payload/tree/main/examples/live-preview/payload). If you have not done so already, clone it down and follow the setup instructions there. This will provide all the necessary APIs that your Next.js app requires for authentication.
|
||||
|
||||
### Next.js
|
||||
|
||||
@@ -18,7 +18,7 @@ First you'll need a running Payload app. There is one made explicitly for this e
|
||||
4. `yarn dev` or `npm run dev` to start the server
|
||||
5. `open http://localhost:3001` to see the result
|
||||
|
||||
Once running you will find a couple seeded pages on your local environment with some basic instructions. You can also start editing the pages by modifying the documents within Payload. See the [Live Preview Example](https://github.com/payloadcms/payload/tree/master/examples/live-preview/payload) for full details.
|
||||
Once running you will find a couple seeded pages on your local environment with some basic instructions. You can also start editing the pages by modifying the documents within Payload. See the [Live Preview Example](https://github.com/payloadcms/payload/tree/main/examples/live-preview/payload) for full details.
|
||||
|
||||
## Learn More
|
||||
|
||||
@@ -32,6 +32,6 @@ You can check out [the Payload GitHub repository](https://github.com/payloadcms/
|
||||
|
||||
## Deployment
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new) from the creators of Next.js. You could also combine this app into a [single Express server](https://github.com/payloadcms/payload/tree/master/examples/custom-server) and deploy in to [Payload Cloud](https://payloadcms.com/new/import).
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new) from the creators of Next.js. You could also combine this app into a [single Express server](https://github.com/payloadcms/payload/tree/main/examples/custom-server) and deploy in to [Payload Cloud](https://payloadcms.com/new/import).
|
||||
|
||||
Check out our [Payload deployment documentation](https://payloadcms.com/docs/production/deployment) or the [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/live-preview-react": "^1.0.0-beta.3",
|
||||
"@payloadcms/live-preview-react": "latest",
|
||||
"@types/escape-html": "^1.0.2",
|
||||
"escape-html": "^1.0.3",
|
||||
"next": "^13.4.8",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
# Payload Live Preview Example
|
||||
|
||||
The [Payload Live Preview Example](https://github.com/payloadcms/payload/tree/master/examples/live-preview/payload) demonstrates how to implement [Live Preview](https://payloadcms.com/docs/live-preview) in [Payload](https://github.com/payloadcms/payload). With Live Preview you can render your front-end application directly within the Admin panel. As you type, your changes take effect in real-time. No need to save a draft or publish your changes.
|
||||
The [Payload Live Preview Example](https://github.com/payloadcms/payload/tree/main/examples/live-preview/payload) demonstrates how to implement [Live Preview](https://payloadcms.com/docs/live-preview) in [Payload](https://github.com/payloadcms/payload). With Live Preview you can render your front-end application directly within the Admin panel. As you type, your changes take effect in real-time. No need to save a draft or publish your changes.
|
||||
|
||||
There are various fully working front-ends made explicitly for this example, including:
|
||||
|
||||
@@ -40,7 +40,7 @@ See the [Collections](https://payloadcms.com/docs/configuration/collections) doc
|
||||
}
|
||||
```
|
||||
|
||||
For additional help with authentication, see the [Authentication](https://payloadcms.com/docs/authentication/overview#authentication-overview) docs or the official [Auth Example](https://github.com/payloadcms/payload/tree/master/examples/auth).
|
||||
For additional help with authentication, see the [Authentication](https://payloadcms.com/docs/authentication/overview#authentication-overview) docs or the official [Auth Example](https://github.com/payloadcms/payload/tree/main/examples/auth).
|
||||
|
||||
- #### Pages
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Redirects Example Front-End
|
||||
|
||||
This is a [Next.js](https://nextjs.org) app using the [Pages Router](https://nextjs.org/docs/pages). It was made explicitly for Payload's [Redirects Example](https://github.com/payloadcms/payload/tree/master/examples/redireects/payload).
|
||||
This is a [Next.js](https://nextjs.org) app using the [Pages Router](https://nextjs.org/docs/pages). It was made explicitly for Payload's [Redirects Example](https://github.com/payloadcms/payload/tree/main/examples/redireects/payload).
|
||||
|
||||
> This example uses the Pages Router, the legacy API of Next.js. If your app is using the latest [App Router](https://nextjs.org/docs/app), we will soon add a new example for you to use soon.
|
||||
|
||||
@@ -8,7 +8,7 @@ This is a [Next.js](https://nextjs.org) app using the [Pages Router](https://nex
|
||||
|
||||
### Payload
|
||||
|
||||
First you'll need a running Payload app. There is one made explicitly for this example and [can be found here](https://github.com/payloadcms/payload/tree/master/examples/redirects/payload). If you have not done so already, clone it down and follow the setup instructions there.
|
||||
First you'll need a running Payload app. There is one made explicitly for this example and [can be found here](https://github.com/payloadcms/payload/tree/main/examples/redirects/payload). If you have not done so already, clone it down and follow the setup instructions there.
|
||||
|
||||
### Next.js App
|
||||
|
||||
|
||||
@@ -6,6 +6,12 @@ module.exports = {
|
||||
extends: ['plugin:@typescript-eslint/disable-type-checked'],
|
||||
files: ['*.js', '*.cjs', '*.json', '*.md', '*.yml', '*.yaml'],
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-redundant-type-constituents': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['package.json', 'tsconfig.json'],
|
||||
rules: {
|
||||
|
||||
@@ -29,9 +29,12 @@
|
||||
"prompts": "2.4.2",
|
||||
"uuid": "9.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"@payloadcms/eslint-config": "workspace:*",
|
||||
"@types/mongoose-aggregate-paginate-v2": "1.0.9",
|
||||
"mongodb": "^6.1.0",
|
||||
"mongodb-memory-server": "8.13.0",
|
||||
"payload": "workspace:*"
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { TransactionOptions } from 'mongodb'
|
||||
import type { ClientSession, ConnectOptions, Connection } from 'mongoose'
|
||||
import type { Payload } from 'payload'
|
||||
import type { BaseDatabaseAdapter } from 'payload/database'
|
||||
@@ -6,8 +7,6 @@ import mongoose from 'mongoose'
|
||||
import path from 'path'
|
||||
import { createDatabaseAdapter } from 'payload/database'
|
||||
|
||||
export type { MigrateDownArgs, MigrateUpArgs } from './types'
|
||||
|
||||
import type { CollectionModel, GlobalModel } from './types'
|
||||
|
||||
import { connect } from './connect'
|
||||
@@ -38,6 +37,8 @@ import { updateGlobalVersion } from './updateGlobalVersion'
|
||||
import { updateOne } from './updateOne'
|
||||
import { updateVersion } from './updateVersion'
|
||||
|
||||
export type { MigrateDownArgs, MigrateUpArgs } from './types'
|
||||
|
||||
export interface Args {
|
||||
/** Set to false to disable auto-pluralization of collection names, Defaults to true */
|
||||
autoPluralization?: boolean
|
||||
@@ -47,6 +48,10 @@ export interface Args {
|
||||
useFacet?: boolean
|
||||
}
|
||||
migrationDir?: string
|
||||
/**
|
||||
* set to false to disable using transactions
|
||||
*/
|
||||
transactions?: TransactionOptions | false
|
||||
/** The URL to connect to MongoDB or false to start payload and prevent connecting */
|
||||
url: false | string
|
||||
}
|
||||
@@ -60,6 +65,7 @@ export type MongooseAdapter = BaseDatabaseAdapter &
|
||||
globals: GlobalModel
|
||||
mongoMemoryServer: any
|
||||
sessions: Record<number | string, ClientSession>
|
||||
transactionOptions: TransactionOptions | false
|
||||
versions: {
|
||||
[slug: string]: CollectionModel
|
||||
}
|
||||
@@ -70,7 +76,7 @@ type MongooseAdapterResult = (args: { payload: Payload }) => MongooseAdapter
|
||||
declare module 'payload' {
|
||||
export interface DatabaseAdapter
|
||||
extends Omit<BaseDatabaseAdapter, 'sessions'>,
|
||||
Omit<Args, 'migrationDir'> {
|
||||
Omit<Args, 'migrationDir' | 'transactions'> {
|
||||
collections: {
|
||||
[slug: string]: CollectionModel
|
||||
}
|
||||
@@ -88,6 +94,7 @@ export function mongooseAdapter({
|
||||
autoPluralization = true,
|
||||
connectOptions,
|
||||
migrationDir: migrationDirArg,
|
||||
transactions,
|
||||
url,
|
||||
}: Args): MongooseAdapterResult {
|
||||
function adapter({ payload }: { payload: Payload }) {
|
||||
@@ -108,6 +115,12 @@ export function mongooseAdapter({
|
||||
globals: undefined,
|
||||
mongoMemoryServer: undefined,
|
||||
sessions: {},
|
||||
transactionOptions: transactions ?? {
|
||||
readConcern: { level: 'local' },
|
||||
// TODO: this needs to be dynamic based on the operation
|
||||
readPreference: 'nearest',
|
||||
// readPreference: 'primary', // primary for write
|
||||
},
|
||||
url,
|
||||
versions: {},
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-expect-error // TODO: Fix this import
|
||||
import type { TransactionOptions } from 'mongodb'
|
||||
import type { BeginTransaction } from 'payload/database'
|
||||
|
||||
@@ -7,8 +6,11 @@ import { v4 as uuid } from 'uuid'
|
||||
|
||||
let transactionsNotAvailable: boolean
|
||||
export const beginTransaction: BeginTransaction = async function beginTransaction(
|
||||
options: TransactionOptions = {},
|
||||
options?: TransactionOptions,
|
||||
) {
|
||||
if (this.transactionOptions === false) {
|
||||
return null
|
||||
}
|
||||
let id = null
|
||||
if (!this.connection) {
|
||||
throw new APIError('beginTransaction called while no connection to the database exists')
|
||||
@@ -27,7 +29,7 @@ export const beginTransaction: BeginTransaction = async function beginTransactio
|
||||
if (this.sessions[id].inTransaction()) {
|
||||
this.payload.logger.warn('beginTransaction called while transaction already exists')
|
||||
} else {
|
||||
await this.sessions[id].startTransaction(options)
|
||||
await this.sessions[id].startTransaction(options || this.transactionOptions)
|
||||
}
|
||||
}
|
||||
return id
|
||||
|
||||
@@ -128,7 +128,7 @@ export const traverseFields = ({
|
||||
with: {},
|
||||
}
|
||||
|
||||
if (adapter.tables[`${topLevelTableName}_${toSnakeCase(block.slug)}_locales`])
|
||||
if (adapter.tables[`${topLevelTableName}_blocks_${toSnakeCase(block.slug)}_locales`])
|
||||
withBlock.with._locales = _locales
|
||||
topLevelArgs.with[blockKey] = withBlock
|
||||
|
||||
|
||||
13
packages/db-postgres/src/schema/idToUUID.ts
Normal file
13
packages/db-postgres/src/schema/idToUUID.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
export const idToUUID = (fields: Field[]): Field[] =>
|
||||
fields.map((field) => {
|
||||
if ('name' in field && field.name === 'id') {
|
||||
return {
|
||||
...field,
|
||||
name: '_uuid',
|
||||
}
|
||||
}
|
||||
|
||||
return field
|
||||
})
|
||||
@@ -26,6 +26,7 @@ import type { GenericColumns, PostgresAdapter } from '../types'
|
||||
import { hasLocalesTable } from '../utilities/hasLocalesTable'
|
||||
import { buildTable } from './build'
|
||||
import { createIndex } from './createIndex'
|
||||
import { idToUUID } from './idToUUID'
|
||||
import { parentIDColumnMap } from './parentIDColumnMap'
|
||||
import { validateExistingBlockIsIdentical } from './validateExistingBlockIsIdentical'
|
||||
|
||||
@@ -281,7 +282,7 @@ export const traverseFields = ({
|
||||
baseExtraConfig,
|
||||
disableNotNull: disableNotNullFromHere,
|
||||
disableUnique,
|
||||
fields: field.fields,
|
||||
fields: disableUnique ? idToUUID(field.fields) : field.fields,
|
||||
rootRelationsToBuild,
|
||||
rootRelationships: relationships,
|
||||
rootTableIDColType,
|
||||
@@ -349,7 +350,7 @@ export const traverseFields = ({
|
||||
baseExtraConfig,
|
||||
disableNotNull: disableNotNullFromHere,
|
||||
disableUnique,
|
||||
fields: block.fields,
|
||||
fields: disableUnique ? idToUUID(block.fields) : block.fields,
|
||||
rootRelationsToBuild,
|
||||
rootRelationships: relationships,
|
||||
rootTableIDColType,
|
||||
|
||||
@@ -22,7 +22,7 @@ export const validateExistingBlockIsIdentical = ({
|
||||
const fieldNames = flattenTopLevelFields(block.fields).flatMap((field) => field.name)
|
||||
|
||||
Object.keys(table).forEach((fieldName) => {
|
||||
if (!['_locale', '_order', '_parentID', '_path'].includes(fieldName)) {
|
||||
if (!['_locale', '_order', '_parentID', '_path', '_uuid'].includes(fieldName)) {
|
||||
if (fieldNames.indexOf(fieldName) === -1) {
|
||||
throw new InvalidConfiguration(
|
||||
`The table ${rootTableName} has multiple blocks with slug ${block.slug}, but the schemas do not match. One block includes the field ${fieldName}, while the other block does not.`,
|
||||
|
||||
@@ -31,6 +31,7 @@ export const transform = <T extends TypeWithID>({ config, data, fields }: Transf
|
||||
}
|
||||
|
||||
const blocks = createBlocksMap(data)
|
||||
const deletions = []
|
||||
|
||||
const result = traverseFields<T>({
|
||||
blocks,
|
||||
@@ -38,6 +39,7 @@ export const transform = <T extends TypeWithID>({ config, data, fields }: Transf
|
||||
dataRef: {
|
||||
id: data.id,
|
||||
},
|
||||
deletions,
|
||||
fieldPrefix: '',
|
||||
fields,
|
||||
numbers,
|
||||
@@ -46,5 +48,7 @@ export const transform = <T extends TypeWithID>({ config, data, fields }: Transf
|
||||
table: data,
|
||||
})
|
||||
|
||||
deletions.forEach((deletion) => deletion())
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -22,6 +22,10 @@ type TraverseFieldsArgs = {
|
||||
* The data reference to be mutated within this recursive function
|
||||
*/
|
||||
dataRef: Record<string, unknown>
|
||||
/**
|
||||
* Data that needs to be removed from the result after all fields have populated
|
||||
*/
|
||||
deletions: (() => void)[]
|
||||
/**
|
||||
* Column prefix can be built up by group and named tab fields
|
||||
*/
|
||||
@@ -54,6 +58,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
blocks,
|
||||
config,
|
||||
dataRef,
|
||||
deletions,
|
||||
fieldPrefix,
|
||||
fields,
|
||||
numbers,
|
||||
@@ -69,6 +74,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
blocks,
|
||||
config,
|
||||
dataRef,
|
||||
deletions,
|
||||
fieldPrefix,
|
||||
fields: field.tabs.map((tab) => ({ ...tab, type: 'tab' })),
|
||||
numbers,
|
||||
@@ -87,6 +93,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
blocks,
|
||||
config,
|
||||
dataRef,
|
||||
deletions,
|
||||
fieldPrefix,
|
||||
fields: field.fields,
|
||||
numbers,
|
||||
@@ -99,7 +106,6 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
if (fieldAffectsData(field)) {
|
||||
const fieldName = `${fieldPrefix || ''}${field.name}`
|
||||
const fieldData = table[fieldName]
|
||||
|
||||
if (field.type === 'array') {
|
||||
if (Array.isArray(fieldData)) {
|
||||
if (field.localized) {
|
||||
@@ -109,11 +115,16 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
const locale = row._locale
|
||||
const data = {}
|
||||
delete row._locale
|
||||
if (row._uuid) {
|
||||
row.id = row._uuid
|
||||
delete row._uuid
|
||||
}
|
||||
|
||||
const rowResult = traverseFields<T>({
|
||||
blocks,
|
||||
config,
|
||||
dataRef: data,
|
||||
deletions,
|
||||
fieldPrefix: '',
|
||||
fields: field.fields,
|
||||
numbers,
|
||||
@@ -129,10 +140,15 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
}, {})
|
||||
} else {
|
||||
result[field.name] = fieldData.map((row, i) => {
|
||||
if (row._uuid) {
|
||||
row.id = row._uuid
|
||||
delete row._uuid
|
||||
}
|
||||
return traverseFields<T>({
|
||||
blocks,
|
||||
config,
|
||||
dataRef: row,
|
||||
deletions,
|
||||
fieldPrefix: '',
|
||||
fields: field.fields,
|
||||
numbers,
|
||||
@@ -155,6 +171,10 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
result[field.name] = {}
|
||||
|
||||
blocks[blockFieldPath].forEach((row) => {
|
||||
if (row._uuid) {
|
||||
row.id = row._uuid
|
||||
delete row._uuid
|
||||
}
|
||||
if (typeof row._locale === 'string') {
|
||||
if (!result[field.name][row._locale]) result[field.name][row._locale] = []
|
||||
result[field.name][row._locale].push(row)
|
||||
@@ -171,6 +191,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
blocks,
|
||||
config,
|
||||
dataRef: row,
|
||||
deletions,
|
||||
fieldPrefix: '',
|
||||
fields: block.fields,
|
||||
numbers,
|
||||
@@ -189,6 +210,10 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
} else {
|
||||
result[field.name] = blocks[blockFieldPath].map((row, i) => {
|
||||
delete row._order
|
||||
if (row._uuid) {
|
||||
row.id = row._uuid
|
||||
delete row._uuid
|
||||
}
|
||||
const block = field.blocks.find(({ slug }) => slug === row.blockType)
|
||||
|
||||
if (block) {
|
||||
@@ -196,6 +221,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
blocks,
|
||||
config,
|
||||
dataRef: row,
|
||||
deletions,
|
||||
fieldPrefix: '',
|
||||
fields: block.fields,
|
||||
numbers,
|
||||
@@ -345,6 +371,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
blocks,
|
||||
config,
|
||||
dataRef: groupLocaleData as Record<string, unknown>,
|
||||
deletions,
|
||||
fieldPrefix: groupFieldPrefix,
|
||||
fields: field.fields,
|
||||
numbers,
|
||||
@@ -360,6 +387,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
blocks,
|
||||
config,
|
||||
dataRef: groupData as Record<string, unknown>,
|
||||
deletions,
|
||||
fieldPrefix: groupFieldPrefix,
|
||||
fields: field.fields,
|
||||
numbers,
|
||||
@@ -425,5 +453,9 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
return result
|
||||
}, dataRef)
|
||||
|
||||
if (Array.isArray(table._locales)) {
|
||||
deletions.push(() => delete table._locales)
|
||||
}
|
||||
|
||||
return formatted as T
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { ArrayField } from 'payload/types'
|
||||
|
||||
import type { PostgresAdapter } from '../../types'
|
||||
import type { ArrayRowToInsert, BlockRowToInsert, RelationshipToDelete } from './types'
|
||||
|
||||
import { isArrayOfRows } from '../../utilities/isArrayOfRows'
|
||||
import { traverseFields } from './traverseFields'
|
||||
|
||||
type Args = {
|
||||
adapter: PostgresAdapter
|
||||
arrayTableName: string
|
||||
baseTableName: string
|
||||
blocks: {
|
||||
@@ -25,6 +27,7 @@ type Args = {
|
||||
}
|
||||
|
||||
export const transformArray = ({
|
||||
adapter,
|
||||
arrayTableName,
|
||||
baseTableName,
|
||||
blocks,
|
||||
@@ -38,6 +41,7 @@ export const transformArray = ({
|
||||
selects,
|
||||
}: Args) => {
|
||||
const newRows: ArrayRowToInsert[] = []
|
||||
const hasUUID = adapter.tables[arrayTableName]._uuid
|
||||
|
||||
if (isArrayOfRows(data)) {
|
||||
data.forEach((arrayRow, i) => {
|
||||
@@ -49,6 +53,16 @@ export const transformArray = ({
|
||||
},
|
||||
}
|
||||
|
||||
// If we have declared a _uuid field on arrays,
|
||||
// that means the ID has to be unique,
|
||||
// and our ids within arrays are not unique.
|
||||
// So move the ID to a uuid field for storage
|
||||
// and allow the database to generate a serial id automatically
|
||||
if (hasUUID) {
|
||||
newRow.row._uuid = arrayRow.id
|
||||
delete arrayRow.id
|
||||
}
|
||||
|
||||
if (locale) {
|
||||
newRow.locales[locale] = {
|
||||
_locale: locale,
|
||||
@@ -60,6 +74,7 @@ export const transformArray = ({
|
||||
}
|
||||
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays: newRow.arrays,
|
||||
baseTableName,
|
||||
blocks,
|
||||
|
||||
@@ -3,11 +3,13 @@ import type { BlockField } from 'payload/types'
|
||||
|
||||
import toSnakeCase from 'to-snake-case'
|
||||
|
||||
import type { PostgresAdapter } from '../../types'
|
||||
import type { BlockRowToInsert, RelationshipToDelete } from './types'
|
||||
|
||||
import { traverseFields } from './traverseFields'
|
||||
|
||||
type Args = {
|
||||
adapter: PostgresAdapter
|
||||
baseTableName: string
|
||||
blocks: {
|
||||
[blockType: string]: BlockRowToInsert[]
|
||||
@@ -24,6 +26,7 @@ type Args = {
|
||||
}
|
||||
}
|
||||
export const transformBlocks = ({
|
||||
adapter,
|
||||
baseTableName,
|
||||
blocks,
|
||||
data,
|
||||
@@ -56,7 +59,20 @@ export const transformBlocks = ({
|
||||
|
||||
const blockTableName = `${baseTableName}_blocks_${blockType}`
|
||||
|
||||
const hasUUID = adapter.tables[blockTableName]._uuid
|
||||
|
||||
// If we have declared a _uuid field on arrays,
|
||||
// that means the ID has to be unique,
|
||||
// and our ids within arrays are not unique.
|
||||
// So move the ID to a uuid field for storage
|
||||
// and allow the database to generate a serial id automatically
|
||||
if (hasUUID) {
|
||||
newRow.row._uuid = blockRow.id
|
||||
delete blockRow.id
|
||||
}
|
||||
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays: newRow.arrays,
|
||||
baseTableName,
|
||||
blocks,
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { Field } from 'payload/types'
|
||||
|
||||
import type { PostgresAdapter } from '../../types'
|
||||
import type { RowToInsert } from './types'
|
||||
|
||||
import { traverseFields } from './traverseFields'
|
||||
|
||||
type Args = {
|
||||
adapter: PostgresAdapter
|
||||
data: Record<string, unknown>
|
||||
fields: Field[]
|
||||
path?: string
|
||||
tableName: string
|
||||
}
|
||||
|
||||
export const transformForWrite = ({ data, fields, path = '', tableName }: Args): RowToInsert => {
|
||||
export const transformForWrite = ({
|
||||
adapter,
|
||||
data,
|
||||
fields,
|
||||
path = '',
|
||||
tableName,
|
||||
}: Args): RowToInsert => {
|
||||
// Split out the incoming data into rows to insert / delete
|
||||
const rowToInsert: RowToInsert = {
|
||||
arrays: {},
|
||||
@@ -28,6 +36,7 @@ export const transformForWrite = ({ data, fields, path = '', tableName }: Args):
|
||||
// This function is responsible for building up the
|
||||
// above rowToInsert
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays: rowToInsert.arrays,
|
||||
baseTableName: tableName,
|
||||
blocks: rowToInsert.blocks,
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { Field } from 'payload/types'
|
||||
import { fieldAffectsData } from 'payload/types'
|
||||
import toSnakeCase from 'to-snake-case'
|
||||
|
||||
import type { PostgresAdapter } from '../../types'
|
||||
import type { ArrayRowToInsert, BlockRowToInsert, RelationshipToDelete } from './types'
|
||||
|
||||
import { isArrayOfRows } from '../../utilities/isArrayOfRows'
|
||||
@@ -14,6 +15,7 @@ import { transformRelationship } from './relationships'
|
||||
import { transformSelects } from './selects'
|
||||
|
||||
type Args = {
|
||||
adapter: PostgresAdapter
|
||||
arrays: {
|
||||
[tableName: string]: ArrayRowToInsert[]
|
||||
}
|
||||
@@ -56,6 +58,7 @@ type Args = {
|
||||
}
|
||||
|
||||
export const traverseFields = ({
|
||||
adapter,
|
||||
arrays,
|
||||
baseTableName,
|
||||
blocks,
|
||||
@@ -95,6 +98,7 @@ export const traverseFields = ({
|
||||
Object.entries(data[field.name]).forEach(([localeKey, localeData]) => {
|
||||
if (Array.isArray(localeData)) {
|
||||
const newRows = transformArray({
|
||||
adapter,
|
||||
arrayTableName,
|
||||
baseTableName,
|
||||
blocks,
|
||||
@@ -114,6 +118,7 @@ export const traverseFields = ({
|
||||
}
|
||||
} else {
|
||||
const newRows = transformArray({
|
||||
adapter,
|
||||
arrayTableName,
|
||||
baseTableName,
|
||||
blocks,
|
||||
@@ -138,6 +143,7 @@ export const traverseFields = ({
|
||||
Object.entries(data[field.name]).forEach(([localeKey, localeData]) => {
|
||||
if (Array.isArray(localeData)) {
|
||||
transformBlocks({
|
||||
adapter,
|
||||
baseTableName,
|
||||
blocks,
|
||||
data: localeData,
|
||||
@@ -154,6 +160,7 @@ export const traverseFields = ({
|
||||
}
|
||||
} else if (isArrayOfRows(fieldData)) {
|
||||
transformBlocks({
|
||||
adapter,
|
||||
baseTableName,
|
||||
blocks,
|
||||
data: fieldData,
|
||||
@@ -174,6 +181,7 @@ export const traverseFields = ({
|
||||
if (field.localized) {
|
||||
Object.entries(data[field.name]).forEach(([localeKey, localeData]) => {
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays,
|
||||
baseTableName,
|
||||
blocks,
|
||||
@@ -195,6 +203,7 @@ export const traverseFields = ({
|
||||
})
|
||||
} else {
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays,
|
||||
baseTableName,
|
||||
blocks,
|
||||
@@ -225,6 +234,7 @@ export const traverseFields = ({
|
||||
if (tab.localized) {
|
||||
Object.entries(data[tab.name]).forEach(([localeKey, localeData]) => {
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays,
|
||||
baseTableName,
|
||||
blocks,
|
||||
@@ -246,6 +256,7 @@ export const traverseFields = ({
|
||||
})
|
||||
} else {
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays,
|
||||
baseTableName,
|
||||
blocks,
|
||||
@@ -267,6 +278,7 @@ export const traverseFields = ({
|
||||
}
|
||||
} else {
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays,
|
||||
baseTableName,
|
||||
blocks,
|
||||
@@ -290,6 +302,7 @@ export const traverseFields = ({
|
||||
|
||||
if (field.type === 'row' || field.type === 'collapsible') {
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays,
|
||||
baseTableName,
|
||||
blocks,
|
||||
|
||||
@@ -28,6 +28,7 @@ export const upsertRow = async <T extends TypeWithID>({
|
||||
// Split out the incoming data into the corresponding:
|
||||
// base row, locales, relationships, blocks, and arrays
|
||||
const rowToInsert = transformForWrite({
|
||||
adapter,
|
||||
data,
|
||||
fields,
|
||||
path,
|
||||
@@ -107,6 +108,9 @@ export const upsertRow = async <T extends TypeWithID>({
|
||||
rowToInsert.blocks[blockName].forEach((blockRow) => {
|
||||
blockRow.row._parentID = insertedRow.id
|
||||
if (!blocksToInsert[blockName]) blocksToInsert[blockName] = []
|
||||
if (blockRow.row.uuid) {
|
||||
delete blockRow.row.uuid
|
||||
}
|
||||
blocksToInsert[blockName].push(blockRow)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/eslint-config",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0.0",
|
||||
"description": "Payload styles for ESLint and Prettier",
|
||||
"license": "MIT",
|
||||
"author": {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { fieldSchemaToJSON } from 'payload/utilities'
|
||||
|
||||
import { traverseFields } from './traverseFields'
|
||||
|
||||
export type MergeLiveDataArgs<T> = {
|
||||
apiRoute?: string
|
||||
depth: number
|
||||
fieldSchema: Record<string, unknown>[]
|
||||
fieldSchema: ReturnType<typeof fieldSchemaToJSON>
|
||||
incomingData: T
|
||||
initialData: T
|
||||
serverURL: string
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { fieldSchemaToJSON } from 'payload/utilities'
|
||||
|
||||
import { promise } from './promise'
|
||||
|
||||
type Args<T> = {
|
||||
apiRoute?: string
|
||||
depth: number
|
||||
fieldSchema: Record<string, unknown>[]
|
||||
fieldSchema: ReturnType<typeof fieldSchemaToJSON>
|
||||
incomingData: T
|
||||
populationPromises: Promise<void>[]
|
||||
result: T
|
||||
@@ -19,12 +21,11 @@ export const traverseFields = <T>({
|
||||
result,
|
||||
serverURL,
|
||||
}: Args<T>): void => {
|
||||
fieldSchema.forEach((field) => {
|
||||
if ('name' in field && typeof field.name === 'string') {
|
||||
// TODO: type this
|
||||
const fieldName = field.name
|
||||
fieldSchema.forEach((fieldJSON) => {
|
||||
if ('name' in fieldJSON && typeof fieldJSON.name === 'string') {
|
||||
const fieldName = fieldJSON.name
|
||||
|
||||
switch (field.type) {
|
||||
switch (fieldJSON.type) {
|
||||
case 'array':
|
||||
if (Array.isArray(incomingData[fieldName])) {
|
||||
result[fieldName] = incomingData[fieldName].map((row, i) => {
|
||||
@@ -38,7 +39,7 @@ export const traverseFields = <T>({
|
||||
traverseFields({
|
||||
apiRoute,
|
||||
depth,
|
||||
fieldSchema: field.fields as Record<string, unknown>[], // TODO: type this
|
||||
fieldSchema: fieldJSON.fields,
|
||||
incomingData: row,
|
||||
populationPromises,
|
||||
result: newRow,
|
||||
@@ -53,7 +54,7 @@ export const traverseFields = <T>({
|
||||
case 'blocks':
|
||||
if (Array.isArray(incomingData[fieldName])) {
|
||||
result[fieldName] = incomingData[fieldName].map((row, i) => {
|
||||
const matchedBlock = field.blocks[row.blockType]
|
||||
const matchedBlock = fieldJSON.blocks[row.blockType]
|
||||
|
||||
const hasExistingRow =
|
||||
Array.isArray(result[fieldName]) &&
|
||||
@@ -70,7 +71,7 @@ export const traverseFields = <T>({
|
||||
traverseFields({
|
||||
apiRoute,
|
||||
depth,
|
||||
fieldSchema: matchedBlock.fields as Record<string, unknown>[], // TODO: type this
|
||||
fieldSchema: matchedBlock.fields,
|
||||
incomingData: row,
|
||||
populationPromises,
|
||||
result: newRow,
|
||||
@@ -82,7 +83,7 @@ export const traverseFields = <T>({
|
||||
}
|
||||
break
|
||||
|
||||
case 'tab':
|
||||
case 'tabs':
|
||||
case 'group':
|
||||
if (!result[fieldName]) {
|
||||
result[fieldName] = {}
|
||||
@@ -91,7 +92,7 @@ export const traverseFields = <T>({
|
||||
traverseFields({
|
||||
apiRoute,
|
||||
depth,
|
||||
fieldSchema: field.fields as Record<string, unknown>[], // TODO: type this
|
||||
fieldSchema: fieldJSON.fields,
|
||||
incomingData: incomingData[fieldName] || {},
|
||||
populationPromises,
|
||||
result: result[fieldName],
|
||||
@@ -102,7 +103,7 @@ export const traverseFields = <T>({
|
||||
|
||||
case 'upload':
|
||||
case 'relationship':
|
||||
if (field.hasMany && Array.isArray(incomingData[fieldName])) {
|
||||
if (fieldJSON.hasMany && Array.isArray(incomingData[fieldName])) {
|
||||
const existingValue = Array.isArray(result[fieldName]) ? [...result[fieldName]] : []
|
||||
result[fieldName] = Array.isArray(result[fieldName])
|
||||
? [...result[fieldName]].slice(0, incomingData[fieldName].length)
|
||||
@@ -110,7 +111,7 @@ export const traverseFields = <T>({
|
||||
|
||||
incomingData[fieldName].forEach((relation, i) => {
|
||||
// Handle `hasMany` polymorphic
|
||||
if (Array.isArray(field.relationTo)) {
|
||||
if (Array.isArray(fieldJSON.relationTo)) {
|
||||
const existingID = existingValue[i]?.value?.id
|
||||
|
||||
if (
|
||||
@@ -134,7 +135,7 @@ export const traverseFields = <T>({
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// Handle `hasMany` singular
|
||||
// Handle `hasMany` monomorphic
|
||||
const existingID = existingValue[i]?.id
|
||||
|
||||
if (existingID !== relation) {
|
||||
@@ -143,7 +144,7 @@ export const traverseFields = <T>({
|
||||
id: relation,
|
||||
accessor: i,
|
||||
apiRoute,
|
||||
collection: String(field.relationTo),
|
||||
collection: String(fieldJSON.relationTo),
|
||||
depth,
|
||||
ref: result[fieldName],
|
||||
serverURL,
|
||||
@@ -154,7 +155,7 @@ export const traverseFields = <T>({
|
||||
})
|
||||
} else {
|
||||
// Handle `hasOne` polymorphic
|
||||
if (Array.isArray(field.relationTo)) {
|
||||
if (Array.isArray(fieldJSON.relationTo)) {
|
||||
const hasNewValue =
|
||||
typeof incomingData[fieldName] === 'object' && incomingData[fieldName] !== null
|
||||
const hasOldValue =
|
||||
@@ -190,31 +191,37 @@ export const traverseFields = <T>({
|
||||
result[fieldName] = null
|
||||
}
|
||||
} else {
|
||||
const hasNewValue =
|
||||
typeof incomingData[fieldName] === 'object' && incomingData[fieldName] !== null
|
||||
const hasOldValue =
|
||||
typeof result[fieldName] === 'object' && result[fieldName] !== null
|
||||
// Handle `hasOne` monomorphic
|
||||
const newID: string =
|
||||
(typeof incomingData[fieldName] === 'string' && incomingData[fieldName]) ||
|
||||
(typeof incomingData[fieldName] === 'object' &&
|
||||
incomingData[fieldName] !== null &&
|
||||
incomingData[fieldName].id) ||
|
||||
''
|
||||
|
||||
const newValue = hasNewValue ? incomingData[fieldName].value : ''
|
||||
const oldID: string =
|
||||
(typeof result[fieldName] === 'string' && result[fieldName]) ||
|
||||
(typeof result[fieldName] === 'object' &&
|
||||
result[fieldName] !== null &&
|
||||
result[fieldName].id) ||
|
||||
''
|
||||
|
||||
const oldValue = hasOldValue ? result[fieldName].value : ''
|
||||
|
||||
if (newValue !== oldValue) {
|
||||
if (newValue) {
|
||||
if (newID !== oldID) {
|
||||
if (newID) {
|
||||
populationPromises.push(
|
||||
promise({
|
||||
id: newValue,
|
||||
id: newID,
|
||||
accessor: fieldName,
|
||||
apiRoute,
|
||||
collection: String(field.relationTo),
|
||||
collection: String(fieldJSON.relationTo),
|
||||
depth,
|
||||
ref: result as Record<string, unknown>,
|
||||
serverURL,
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
result[fieldName] = null
|
||||
}
|
||||
} else {
|
||||
result[fieldName] = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,13 +31,14 @@ const DeleteDocument: React.FC<Props> = (props) => {
|
||||
routes: { admin, api },
|
||||
serverURL,
|
||||
} = useConfig()
|
||||
|
||||
const { setModified } = useForm()
|
||||
const [deleting, setDeleting] = useState(false)
|
||||
const { toggleModal } = useModal()
|
||||
const history = useHistory()
|
||||
const { i18n, t } = useTranslation('general')
|
||||
const title = useTitle({ collection })
|
||||
const titleToRender = titleFromProps || title
|
||||
const titleToRender = titleFromProps || title || id
|
||||
|
||||
const modalSlug = `delete-${id}`
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.doc-controls {
|
||||
@include blur-bg;
|
||||
@include blur-bg-light;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
@@ -9,7 +9,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&::after {
|
||||
&__divider {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
|
||||
@@ -225,6 +225,7 @@ export const DocumentControls: React.FC<{
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${baseClass}__divider`} />
|
||||
</Gutter>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,19 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
|
||||
// Use a pseudo element for the accessability so that it doesn't take up DOM space
|
||||
// Also because the parent element has `overflow: hidden` which would clip an outline
|
||||
&:focus-visible::after {
|
||||
content: '';
|
||||
border: var(--accessibility-outline);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus:not(:focus-visible) {
|
||||
|
||||
@@ -64,6 +64,7 @@ export const DocumentTab: React.FC<DocumentTabProps & DocumentTabConfig> = (prop
|
||||
className={`${baseClass}__link`}
|
||||
to={href}
|
||||
{...(newTab && { rel: 'noopener noreferrer', target: '_blank' })}
|
||||
tabIndex={isActive ? -1 : 0}
|
||||
>
|
||||
<span className={`${baseClass}__label`}>
|
||||
{labelToRender}
|
||||
|
||||
@@ -43,7 +43,7 @@ export const tabs: DocumentTabConfig[] = [
|
||||
// API
|
||||
{
|
||||
condition: ({ collection, global }) =>
|
||||
!collection?.admin?.hideAPIURL || !global?.admin?.hideAPIURL,
|
||||
(collection && !collection?.admin?.hideAPIURL) || (global && !global?.admin?.hideAPIURL),
|
||||
href: '/api',
|
||||
label: 'API',
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
$transTime: 200ms;
|
||||
$transTime: 200;
|
||||
|
||||
.drawer {
|
||||
display: flex;
|
||||
@@ -9,7 +9,7 @@ $transTime: 200ms;
|
||||
height: 100vh;
|
||||
|
||||
&__blur-bg {
|
||||
@include blur-bg();
|
||||
@include blur-bg;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
@@ -17,7 +17,7 @@ $transTime: 200ms;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
transition: all $transTime linear;
|
||||
transition: all #{$transTime}ms linear;
|
||||
}
|
||||
|
||||
&__content {
|
||||
@@ -27,7 +27,8 @@ $transTime: 200ms;
|
||||
z-index: 2;
|
||||
width: calc(100% - var(--gutter-h));
|
||||
overflow: hidden;
|
||||
transition: all $transTime linear;
|
||||
transition: all #{$transTime}ms linear;
|
||||
background-color: var(--theme-bg);
|
||||
}
|
||||
|
||||
&__content-children {
|
||||
@@ -40,14 +41,14 @@ $transTime: 200ms;
|
||||
&--is-open {
|
||||
.drawer {
|
||||
&__content,
|
||||
&__blur-bg,
|
||||
&__close {
|
||||
&__blur-bg {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&__close {
|
||||
transition: opacity $transTime linear;
|
||||
transition-delay: $transTime;
|
||||
opacity: 0.1;
|
||||
transition: opacity #{$transTime}ms linear;
|
||||
transition-delay: #{$transTime / 2}ms;
|
||||
}
|
||||
|
||||
&__content {
|
||||
@@ -68,7 +69,7 @@ $transTime: 200ms;
|
||||
transition: none;
|
||||
transition-delay: 0ms;
|
||||
flex-grow: 1;
|
||||
background: transparent;
|
||||
background: var(--theme-elevation-800);
|
||||
|
||||
&:active,
|
||||
&:focus {
|
||||
@@ -120,7 +121,15 @@ $transTime: 200ms;
|
||||
}
|
||||
|
||||
html[data-theme='dark'] {
|
||||
.drawer__close {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
.drawer {
|
||||
&__close {
|
||||
background: var(--color-base-1000);
|
||||
}
|
||||
|
||||
&--is-open {
|
||||
.drawer__close {
|
||||
opacity: 0.25;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Modal, useModal } from '@faceless-ui/modal'
|
||||
import { useWindowInfo } from '@faceless-ui/window-info'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -52,9 +51,6 @@ export const Drawer: React.FC<Props> = ({
|
||||
}) => {
|
||||
const { t } = useTranslation('general')
|
||||
const { closeModal, modalState } = useModal()
|
||||
const {
|
||||
breakpoints: { m: midBreak },
|
||||
} = useWindowInfo()
|
||||
const drawerDepth = useEditDepth()
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [animateIn, setAnimateIn] = useState(false)
|
||||
@@ -72,7 +68,12 @@ export const Drawer: React.FC<Props> = ({
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className={[className, baseClass, animateIn && `${baseClass}--is-open`]
|
||||
className={[
|
||||
className,
|
||||
baseClass,
|
||||
animateIn && `${baseClass}--is-open`,
|
||||
drawerDepth > 1 && `${baseClass}--nested`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
slug={slug}
|
||||
@@ -80,7 +81,7 @@ export const Drawer: React.FC<Props> = ({
|
||||
zIndex: zBase + drawerDepth,
|
||||
}}
|
||||
>
|
||||
{drawerDepth === 1 && <div className={`${baseClass}__blur-bg`} />}
|
||||
{(!drawerDepth || drawerDepth === 1) && <div className={`${baseClass}__blur-bg`} />}
|
||||
<button
|
||||
aria-label={t('close')}
|
||||
className={`${baseClass}__close`}
|
||||
@@ -89,7 +90,7 @@ export const Drawer: React.FC<Props> = ({
|
||||
type="button"
|
||||
/>
|
||||
<div className={`${baseClass}__content`}>
|
||||
<div className={`${baseClass}__blur-bg`} />
|
||||
<div className={`${baseClass}__blur-bg-content`} />
|
||||
<Gutter className={`${baseClass}__content-children`} left={gutter} right={gutter}>
|
||||
<EditDepthContext.Provider value={drawerDepth + 1}>
|
||||
{header && header}
|
||||
|
||||
@@ -7,27 +7,36 @@
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
position: relative;
|
||||
@include blur-bg;
|
||||
|
||||
--hamburger-padding: 8px;
|
||||
--hamburger-size: 9px;
|
||||
--hamburger-line-gap: 3px;
|
||||
|
||||
padding: var(--hamburger-padding);
|
||||
border: 1px solid var(--theme-elevation-150);
|
||||
color: var(--theme-text);
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
border: 1px solid var(--theme-elevation-500);
|
||||
background-color: var(--theme-elevation-100);
|
||||
}
|
||||
&__wrapper {
|
||||
border: 1px solid var(--theme-elevation-150);
|
||||
padding: var(--hamburger-padding);
|
||||
border-radius: 3px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
&:hover {
|
||||
border: 1px solid var(--theme-elevation-500);
|
||||
background-color: var(--theme-elevation-100);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
height: var(--hamburger-size);
|
||||
width: var(--hamburger-size);
|
||||
display: flex;
|
||||
|
||||
@@ -14,32 +14,34 @@ export const Hamburger: React.FC<{
|
||||
const { closeIcon = 'x', isActive = false } = props
|
||||
|
||||
return (
|
||||
<div className={[baseClass].filter(Boolean).join(' ')}>
|
||||
<div className={`${baseClass}__icon`}>
|
||||
{!isActive && (
|
||||
<div className={`${baseClass}__lines`} title={t('open')}>
|
||||
<div className={`${baseClass}__line ${baseClass}__top`} />
|
||||
<div className={`${baseClass}__line ${baseClass}__middle`} />
|
||||
<div className={`${baseClass}__line ${baseClass}__bottom`} />
|
||||
</div>
|
||||
)}
|
||||
{isActive && (
|
||||
<div
|
||||
aria-label={closeIcon === 'collapse' ? t('collapse') : t('close')}
|
||||
className={`${baseClass}__close-icon`}
|
||||
title={closeIcon === 'collapse' ? t('collapse') : t('close')}
|
||||
>
|
||||
{closeIcon === 'x' && (
|
||||
<React.Fragment>
|
||||
<div className={`${baseClass}__line ${baseClass}__x-left`} />
|
||||
<div className={`${baseClass}__line ${baseClass}__x-right`} />
|
||||
</React.Fragment>
|
||||
)}
|
||||
{closeIcon === 'collapse' && (
|
||||
<Chevron className={`${baseClass}__collapse-chevron`} direction="left" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className={baseClass}>
|
||||
<div className={`${baseClass}__wrapper`}>
|
||||
<div className={`${baseClass}__icon`}>
|
||||
{!isActive && (
|
||||
<div className={`${baseClass}__lines`} title={t('open')}>
|
||||
<div className={`${baseClass}__line ${baseClass}__top`} />
|
||||
<div className={`${baseClass}__line ${baseClass}__middle`} />
|
||||
<div className={`${baseClass}__line ${baseClass}__bottom`} />
|
||||
</div>
|
||||
)}
|
||||
{isActive && (
|
||||
<div
|
||||
aria-label={closeIcon === 'collapse' ? t('collapse') : t('close')}
|
||||
className={`${baseClass}__close-icon`}
|
||||
title={closeIcon === 'collapse' ? t('collapse') : t('close')}
|
||||
>
|
||||
{closeIcon === 'x' && (
|
||||
<React.Fragment>
|
||||
<div className={`${baseClass}__line ${baseClass}__x-left`} />
|
||||
<div className={`${baseClass}__line ${baseClass}__x-right`} />
|
||||
</React.Fragment>
|
||||
)}
|
||||
{closeIcon === 'collapse' && (
|
||||
<Chevron className={`${baseClass}__collapse-chevron`} direction="left" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
}
|
||||
|
||||
&__bg {
|
||||
@include blur-bg;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
@@ -58,9 +57,28 @@
|
||||
}
|
||||
|
||||
&__account {
|
||||
position: relative;
|
||||
|
||||
&:focus:not(:focus-visible) {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
// Use a pseudo element for the accessability so that it doesn't take up DOM space
|
||||
// Also because the parent element has `overflow: hidden` which would clip an outline
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
border: var(--accessibility-outline);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__controls-wrapper {
|
||||
|
||||
@@ -14,7 +14,7 @@ import './index.scss'
|
||||
|
||||
const baseClass = 'app-header'
|
||||
|
||||
export const AppHeader: React.FC = (props) => {
|
||||
export const AppHeader: React.FC = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const {
|
||||
@@ -29,7 +29,7 @@ export const AppHeader: React.FC = (props) => {
|
||||
<div className={`${baseClass}__bg`} />
|
||||
<div className={`${baseClass}__content`}>
|
||||
<div className={`${baseClass}__wrapper`}>
|
||||
<NavToggler className={`${baseClass}__mobile-nav-toggler`}>
|
||||
<NavToggler className={`${baseClass}__mobile-nav-toggler`} tabIndex={-1}>
|
||||
<Hamburger />
|
||||
</NavToggler>
|
||||
<div className={`${baseClass}__controls-wrapper`}>
|
||||
@@ -46,6 +46,7 @@ export const AppHeader: React.FC = (props) => {
|
||||
<Link
|
||||
aria-label={t('authentication:account')}
|
||||
className={`${baseClass}__account`}
|
||||
tabIndex={0}
|
||||
to={`${adminRoute}/account`}
|
||||
>
|
||||
<Account />
|
||||
|
||||
@@ -8,20 +8,22 @@ import RenderCustomComponent from '../../utilities/RenderCustomComponent'
|
||||
|
||||
const baseClass = 'nav'
|
||||
|
||||
const DefaultLogout = () => {
|
||||
const DefaultLogout: React.FC<{
|
||||
tabIndex?: number
|
||||
}> = ({ tabIndex }) => {
|
||||
const { t } = useTranslation('authentication')
|
||||
const config = useConfig()
|
||||
|
||||
const {
|
||||
admin: {
|
||||
components: { logout },
|
||||
logoutRoute,
|
||||
},
|
||||
admin: { logoutRoute },
|
||||
routes: { admin },
|
||||
} = config
|
||||
|
||||
return (
|
||||
<Link
|
||||
aria-label={t('logOut')}
|
||||
className={`${baseClass}__log-out`}
|
||||
tabIndex={tabIndex}
|
||||
to={`${admin}${logoutRoute}`}
|
||||
>
|
||||
<LogOut />
|
||||
@@ -29,7 +31,9 @@ const DefaultLogout = () => {
|
||||
)
|
||||
}
|
||||
|
||||
const Logout: React.FC = () => {
|
||||
const Logout: React.FC<{
|
||||
tabIndex?: number
|
||||
}> = ({ tabIndex = 0 }) => {
|
||||
const {
|
||||
admin: {
|
||||
components: {
|
||||
@@ -40,7 +44,15 @@ const Logout: React.FC = () => {
|
||||
} = {},
|
||||
} = useConfig()
|
||||
|
||||
return <RenderCustomComponent CustomComponent={CustomLogout} DefaultComponent={DefaultLogout} />
|
||||
return (
|
||||
<RenderCustomComponent
|
||||
CustomComponent={CustomLogout}
|
||||
DefaultComponent={DefaultLogout}
|
||||
componentProps={{
|
||||
tabIndex,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Logout
|
||||
|
||||
@@ -12,8 +12,9 @@ export const NavToggler: React.FC<{
|
||||
children?: React.ReactNode
|
||||
className?: string
|
||||
id?: string
|
||||
tabIndex?: number
|
||||
}> = (props) => {
|
||||
const { id, children, className } = props
|
||||
const { id, children, className, tabIndex = 0 } = props
|
||||
|
||||
const { t } = useTranslation('general')
|
||||
|
||||
@@ -43,6 +44,7 @@ export const NavToggler: React.FC<{
|
||||
})
|
||||
}
|
||||
}}
|
||||
tabIndex={tabIndex}
|
||||
type="button"
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
}
|
||||
|
||||
&__header {
|
||||
@include blur-bg;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
|
||||
@@ -102,6 +102,7 @@ const DefaultNav: React.FC = () => {
|
||||
className={`${baseClass}__link`}
|
||||
id={id}
|
||||
key={i}
|
||||
tabIndex={!navOpen ? -1 : undefined}
|
||||
to={href}
|
||||
>
|
||||
<span className={`${baseClass}__link-icon`}>
|
||||
@@ -117,7 +118,7 @@ const DefaultNav: React.FC = () => {
|
||||
{Array.isArray(afterNavLinks) &&
|
||||
afterNavLinks.map((Component, i) => <Component key={i} />)}
|
||||
<div className={`${baseClass}__controls`}>
|
||||
<Logout />
|
||||
<Logout tabIndex={!navOpen ? -1 : undefined} />
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
@@ -128,6 +129,7 @@ const DefaultNav: React.FC = () => {
|
||||
onClick={() => {
|
||||
setNavOpen(false)
|
||||
}}
|
||||
tabIndex={!navOpen ? -1 : undefined}
|
||||
type="button"
|
||||
>
|
||||
<Hamburger isActive />
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import AnimateHeight from 'react-animate-height'
|
||||
|
||||
import Chevron from '../../icons/Chevron'
|
||||
import { usePreferences } from '../../utilities/Preferences'
|
||||
|
||||
import { useNav } from '../Nav/context'
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'nav-group'
|
||||
@@ -16,6 +17,7 @@ const NavGroup: React.FC<Props> = ({ children, label }) => {
|
||||
const [collapsed, setCollapsed] = useState(true)
|
||||
const [animate, setAnimate] = useState(false)
|
||||
const { getPreference, setPreference } = usePreferences()
|
||||
const { navOpen } = useNav()
|
||||
|
||||
const preferencesKey = `collapsed-${label}-groups`
|
||||
|
||||
@@ -44,13 +46,12 @@ const NavGroup: React.FC<Props> = ({ children, label }) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
id={`nav-group-${label}`}
|
||||
className={[`${baseClass}`, `${label}`, collapsed && `${baseClass}--collapsed`]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
id={`nav-group-${label}`}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className={[
|
||||
`${baseClass}__toggle`,
|
||||
`${baseClass}__toggle--${collapsed ? 'collapsed' : 'open'}`,
|
||||
@@ -58,6 +59,8 @@ const NavGroup: React.FC<Props> = ({ children, label }) => {
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
onClick={toggleCollapsed}
|
||||
tabIndex={!navOpen ? -1 : 0}
|
||||
type="button"
|
||||
>
|
||||
<div className={`${baseClass}__label`}>{label}</div>
|
||||
<div className={`${baseClass}__indicator`}>
|
||||
@@ -67,7 +70,7 @@ const NavGroup: React.FC<Props> = ({ children, label }) => {
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
<AnimateHeight height={collapsed ? 0 : 'auto'} duration={animate ? 200 : 0}>
|
||||
<AnimateHeight duration={animate ? 200 : 0} height={collapsed ? 0 : 'auto'}>
|
||||
<div className={`${baseClass}__content`}>{children}</div>
|
||||
</AnimateHeight>
|
||||
</div>
|
||||
|
||||
@@ -36,7 +36,7 @@ export const PopupTrigger: React.FC<Props> = (props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<button className={classes} onClick={() => setActive(!active)} type="button">
|
||||
<button className={classes} onClick={() => setActive(!active)} tabIndex={0} type="button">
|
||||
{button}
|
||||
</button>
|
||||
)
|
||||
|
||||
@@ -13,6 +13,27 @@
|
||||
background: linear-gradient(to right, transparent, var(--theme-bg));
|
||||
}
|
||||
|
||||
// Use a pseudo element for the accessability so that it doesn't take up DOM space
|
||||
// Also because the parent element has `overflow: hidden` which would clip an outline
|
||||
&__home {
|
||||
position: relative;
|
||||
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
border: var(--accessibility-outline);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import { getTranslation } from '../../../../utilities/getTranslation'
|
||||
import { useConfig } from '../../utilities/Config'
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'step-nav'
|
||||
|
||||
const Context = createContext({} as ContextType)
|
||||
|
||||
const StepNavProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) => {
|
||||
@@ -41,32 +43,34 @@ const StepNav: React.FC<{
|
||||
} = config
|
||||
|
||||
return (
|
||||
<nav className={['step-nav', className].filter(Boolean).join(' ')}>
|
||||
<Fragment>
|
||||
{stepNav.length > 0 ? (
|
||||
<Fragment>
|
||||
<Link to={admin}>
|
||||
<nav className={[baseClass, className].filter(Boolean).join(' ')}>
|
||||
<Link className={`${baseClass}__home`} tabIndex={0} to={admin}>
|
||||
<IconGraphic />
|
||||
</Link>
|
||||
<span>/</span>
|
||||
</Fragment>
|
||||
) : (
|
||||
<IconGraphic />
|
||||
)}
|
||||
{stepNav.map((item, i) => {
|
||||
const StepLabel = <span key={i}>{getTranslation(item.label, i18n)}</span>
|
||||
const Step =
|
||||
stepNav.length === i + 1 ? (
|
||||
StepLabel
|
||||
) : (
|
||||
<Fragment key={i}>
|
||||
{item.url ? <Link to={item.url}>{StepLabel}</Link> : StepLabel}
|
||||
<span>/</span>
|
||||
</Fragment>
|
||||
)
|
||||
{stepNav.map((item, i) => {
|
||||
const StepLabel = <span key={i}>{getTranslation(item.label, i18n)}</span>
|
||||
const Step =
|
||||
stepNav.length === i + 1 ? (
|
||||
StepLabel
|
||||
) : (
|
||||
<Fragment key={i}>
|
||||
{item.url ? <Link to={item.url}>{StepLabel}</Link> : StepLabel}
|
||||
<span>/</span>
|
||||
</Fragment>
|
||||
)
|
||||
|
||||
return Step
|
||||
})}
|
||||
</nav>
|
||||
return Step
|
||||
})}
|
||||
</nav>
|
||||
) : (
|
||||
<div className={[baseClass, className].filter(Boolean).join(' ')}>
|
||||
<IconGraphic />
|
||||
</div>
|
||||
)}
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.graphic-account {
|
||||
vector-effect: non-scaling-stroke;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
|
||||
&__bg {
|
||||
fill: var(--theme-elevation-50);
|
||||
|
||||
@@ -9,11 +9,11 @@ const css = `
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.graphic-icon path {
|
||||
fill: var(--theme-elevation-1000);
|
||||
}
|
||||
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.graphic-icon {
|
||||
width: 16px;
|
||||
|
||||
@@ -26,7 +26,7 @@ const Default: React.FC<Props> = ({ children, className }) => {
|
||||
|
||||
const { t } = useTranslation('general')
|
||||
|
||||
const { navOpen, setNavOpen } = useNav()
|
||||
const { navOpen } = useNav()
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
@@ -35,6 +35,11 @@ const Default: React.FC<Props> = ({ children, className }) => {
|
||||
keywords={`${t('dashboard')}, Payload`}
|
||||
title={t('dashboard')}
|
||||
/>
|
||||
<div className={`${baseClass}__nav-toggler-wrapper`} id="nav-toggler">
|
||||
<NavToggler className={`${baseClass}__nav-toggler`}>
|
||||
<Hamburger closeIcon="collapse" isActive={navOpen} />
|
||||
</NavToggler>
|
||||
</div>
|
||||
<div
|
||||
className={[baseClass, className, navOpen && `${baseClass}--nav-open`]
|
||||
.filter(Boolean)
|
||||
@@ -46,11 +51,6 @@ const Default: React.FC<Props> = ({ children, className }) => {
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`${baseClass}__nav-toggler-wrapper`} id="nav-toggler">
|
||||
<NavToggler className={`${baseClass}__nav-toggler`}>
|
||||
<Hamburger closeIcon="collapse" isActive={navOpen} />
|
||||
</NavToggler>
|
||||
</div>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -41,9 +41,11 @@ export const GlobalRoutes: React.FC<GlobalEditViewProps> = (props) => {
|
||||
<Unauthorized />
|
||||
)}
|
||||
</Route>
|
||||
<Route exact key={`${global.slug}-api`} path={`${adminRoute}/globals/${global.slug}/api`}>
|
||||
{permissions?.read ? <CustomGlobalComponent view="API" {...props} /> : <Unauthorized />}
|
||||
</Route>
|
||||
{global?.admin?.hideAPIURL !== true && (
|
||||
<Route exact key={`${global.slug}-api`} path={`${adminRoute}/globals/${global.slug}/api`}>
|
||||
{permissions?.read ? <CustomGlobalComponent view="API" {...props} /> : <Unauthorized />}
|
||||
</Route>
|
||||
)}
|
||||
<Route
|
||||
exact
|
||||
key={`${global.slug}-view-version`}
|
||||
|
||||
@@ -41,13 +41,19 @@ export const CollectionRoutes: React.FC<CollectionEditViewProps> = (props) => {
|
||||
<Unauthorized />
|
||||
)}
|
||||
</Route>
|
||||
<Route
|
||||
exact
|
||||
key={`${collection.slug}-api`}
|
||||
path={`${adminRoute}/collections/${collection.slug}/:id/api`}
|
||||
>
|
||||
{permissions?.read ? <CustomCollectionComponent view="API" {...props} /> : <Unauthorized />}
|
||||
</Route>
|
||||
{collection?.admin?.hideAPIURL !== true && (
|
||||
<Route
|
||||
exact
|
||||
key={`${collection.slug}-api`}
|
||||
path={`${adminRoute}/collections/${collection.slug}/:id/api`}
|
||||
>
|
||||
{permissions?.read ? (
|
||||
<CustomCollectionComponent view="API" {...props} />
|
||||
) : (
|
||||
<Unauthorized />
|
||||
)}
|
||||
</Route>
|
||||
)}
|
||||
<Route
|
||||
exact
|
||||
key={`${collection.slug}-view-version`}
|
||||
|
||||
@@ -129,7 +129,7 @@ $focus-box-shadow: 0 0 0 $style-stroke-width-m var(--theme-success-500);
|
||||
// STYLE MIXINS
|
||||
//////////////////////////////
|
||||
|
||||
@mixin blur-bg($color: var(--theme-bg)) {
|
||||
@mixin blur-bg($color: var(--theme-bg), $opacity: 0.75) {
|
||||
&:before,
|
||||
&:after {
|
||||
content: ' ';
|
||||
@@ -142,14 +142,18 @@ $focus-box-shadow: 0 0 0 $style-stroke-width-m var(--theme-success-500);
|
||||
|
||||
&:before {
|
||||
background: $color;
|
||||
opacity: 0.85;
|
||||
opacity: $opacity;
|
||||
}
|
||||
|
||||
&:after {
|
||||
backdrop-filter: blur(5px);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin blur-bg-light {
|
||||
@include blur-bg(var(--theme-bg), 0.3);
|
||||
}
|
||||
|
||||
@mixin formInput() {
|
||||
@include inputShadow;
|
||||
font-family: var(--font-body);
|
||||
|
||||
@@ -162,8 +162,8 @@ const collectionSchema = joi.object().keys({
|
||||
adminThumbnail: joi.alternatives().try(joi.string(), joi.func()),
|
||||
crop: joi.bool(),
|
||||
disableLocalStorage: joi.bool(),
|
||||
focalPoint: joi.bool(),
|
||||
filesRequiredOnCreate: joi.bool(),
|
||||
focalPoint: joi.bool(),
|
||||
formatOptions: joi.object().keys({
|
||||
format: joi.string(),
|
||||
options: joi.object(),
|
||||
|
||||
@@ -7,7 +7,9 @@ export { configToJSONSchema, entityToJSONSchema } from '../utilities/configToJSO
|
||||
|
||||
export { createArrayFromCommaDelineated } from '../utilities/createArrayFromCommaDelineated'
|
||||
export { deepCopyObject } from '../utilities/deepCopyObject'
|
||||
|
||||
export { deepMerge } from '../utilities/deepMerge'
|
||||
export { fieldSchemaToJSON } from '../utilities/fieldSchemaToJSON'
|
||||
export { default as flattenTopLevelFields } from '../utilities/flattenTopLevelFields'
|
||||
export { formatLabels, formatNames, toWords } from '../utilities/formatLabels'
|
||||
export { getIDType } from '../utilities/getIDType'
|
||||
|
||||
@@ -3,7 +3,6 @@ import type { EditorProps } from '@monaco-editor/react'
|
||||
import type { TFunction } from 'i18next'
|
||||
import type { CSSProperties } from 'react'
|
||||
|
||||
import monacoeditor from 'monaco-editor' // IMPORTANT - DO NOT REMOVE: This is required for pnpm's default isolated mode to work - even though the import is not used. This is due to a typescript bug: https://github.com/microsoft/TypeScript/issues/47663#issuecomment-1519138189. (tsbugisolatedmode)
|
||||
import type { ConditionalDateProps } from '../../admin/components/elements/DatePicker/types'
|
||||
import type { Description } from '../../admin/components/forms/FieldDescription/types'
|
||||
import type { RowLabel } from '../../admin/components/forms/RowLabel/types'
|
||||
|
||||
@@ -217,6 +217,9 @@ export default function buildPoliciesType(payload: Payload): GraphQLObjectType {
|
||||
})
|
||||
|
||||
Object.values(payload.config.globals).forEach((global: SanitizedGlobalConfig) => {
|
||||
if (global.graphQL === false) {
|
||||
return
|
||||
}
|
||||
const globalPolicyType = buildPolicyType({
|
||||
entity: global,
|
||||
type: 'global',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { UploadedFile } from 'express-fileupload'
|
||||
import type { Sharp } from 'sharp'
|
||||
import type { Sharp, SharpOptions } from 'sharp'
|
||||
|
||||
import { fromBuffer } from 'file-type'
|
||||
import mkdirp from 'mkdirp'
|
||||
@@ -98,12 +98,13 @@ export const generateFileData = async <T>({
|
||||
let fileBuffer
|
||||
let ext
|
||||
let mime: string
|
||||
const isSharpRequired = fileSupportsResize && (resizeOptions || formatOptions || trimOptions)
|
||||
|
||||
const sharpOptions: sharp.SharpOptions = {}
|
||||
const sharpOptions: SharpOptions = {}
|
||||
|
||||
if (fileIsAnimated) sharpOptions.animated = true
|
||||
|
||||
if (fileSupportsResize && (resizeOptions || formatOptions || trimOptions)) {
|
||||
if (isSharpRequired) {
|
||||
if (file.tempFilePath) {
|
||||
sharpFile = sharp(file.tempFilePath, sharpOptions).rotate() // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081
|
||||
} else {
|
||||
@@ -170,7 +171,7 @@ export const generateFileData = async <T>({
|
||||
fileData.filename = fsSafeName
|
||||
let fileForResize = file
|
||||
|
||||
if (cropData) {
|
||||
if (isSharpRequired && cropData) {
|
||||
const { data: croppedImage, info } = await cropImage({ cropData, dimensions, file })
|
||||
|
||||
filesToSave.push({
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { UploadedFile } from 'express-fileupload'
|
||||
import type { OutputInfo } from 'sharp'
|
||||
|
||||
import { fromBuffer } from 'file-type'
|
||||
import fs from 'fs'
|
||||
@@ -65,7 +66,7 @@ const getSanitizedImageData = (sourceImage: string): SanitizedImageData => {
|
||||
*/
|
||||
const createImageName = (
|
||||
outputImageName: string,
|
||||
{ height, width }: sharp.OutputInfo,
|
||||
{ height, width }: OutputInfo,
|
||||
extension: string,
|
||||
) => `${outputImageName}-${width}x${height}.${extension}`
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ export type IncomingUploadType = {
|
||||
adminThumbnail?: GetAdminThumbnail | string
|
||||
crop?: boolean
|
||||
disableLocalStorage?: boolean
|
||||
filesRequiredOnCreate?: boolean
|
||||
focalPoint?: boolean
|
||||
/** Options for original upload file only. For sizes, set each formatOptions individually. */
|
||||
formatOptions?: ImageUploadFormatOptions
|
||||
@@ -80,6 +81,7 @@ export type Upload = {
|
||||
adminThumbnail?: GetAdminThumbnail | string
|
||||
crop?: boolean
|
||||
disableLocalStorage?: boolean
|
||||
filesRequiredOnCreate?: boolean
|
||||
focalPoint?: boolean
|
||||
formatOptions?: ImageUploadFormatOptions
|
||||
handlers?: any[]
|
||||
@@ -90,7 +92,6 @@ export type Upload = {
|
||||
staticOptions?: serveStatic.ServeStaticOptions<express.Response<any, Record<string, any>>>
|
||||
staticURL: string
|
||||
trimOptions?: ImageUploadTrimOptions
|
||||
filesRequiredOnCreate?: boolean
|
||||
}
|
||||
|
||||
export type File = {
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
import type { FieldTypes } from '../exports/config'
|
||||
import type { Field } from '../fields/config/types'
|
||||
|
||||
export const fieldSchemaToJSON = (fields: Field[]): Record<string, unknown>[] => {
|
||||
export type FieldSchemaJSON = {
|
||||
blocks?: FieldSchemaJSON // TODO: conditionally add based on `type`
|
||||
fields?: FieldSchemaJSON // TODO: conditionally add based on `type`
|
||||
hasMany?: boolean // TODO: conditionally add based on `type`
|
||||
name: string
|
||||
relationTo?: string // TODO: conditionally add based on `type`
|
||||
slug?: string // TODO: conditionally add based on `type`
|
||||
type: keyof FieldTypes
|
||||
}[]
|
||||
|
||||
export const fieldSchemaToJSON = (fields: Field[]): FieldSchemaJSON => {
|
||||
return fields.reduce((acc, field) => {
|
||||
let result = acc
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { PayloadRequest } from '../express/types'
|
||||
import type { SanitizedGlobalConfig } from '../globals/config/types'
|
||||
import type { Payload } from '../payload'
|
||||
|
||||
import { deepCopyObject } from '../utilities/deepCopyObject'
|
||||
import sanitizeInternalFields from '../utilities/sanitizeInternalFields'
|
||||
import { enforceMaxVersions } from './enforceMaxVersions'
|
||||
|
||||
@@ -30,7 +31,7 @@ export const saveVersion = async ({
|
||||
let result
|
||||
let createNewVersion = true
|
||||
const now = new Date().toISOString()
|
||||
const versionData = { ...doc }
|
||||
const versionData = deepCopyObject(doc)
|
||||
if (draft) versionData._status = 'draft'
|
||||
if (versionData._id) delete versionData._id
|
||||
|
||||
|
||||
@@ -28,6 +28,12 @@ module.exports = {
|
||||
'perfectionist/sort-vue-attributes': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts'],
|
||||
rules: {
|
||||
'perfectionist/sort-objects': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
extends: ['@payloadcms'],
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RelationshipField } from 'payload/types'
|
||||
import type { RelationshipField } from 'payload/types'
|
||||
|
||||
const createParentField = (
|
||||
relationTo: string,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { CollectionAfterChangeHook, CollectionConfig } from 'payload/types'
|
||||
|
||||
import type { PluginConfig } from '../types'
|
||||
|
||||
import populateBreadcrumbs from '../utilities/populateBreadcrumbs'
|
||||
|
||||
const resaveChildren =
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { Plugin } from 'payload/config'
|
||||
|
||||
import type { PluginConfig } from './types'
|
||||
|
||||
import createBreadcrumbsField from './fields/breadcrumbs'
|
||||
import createParentField from './fields/parent'
|
||||
import resaveChildren from './hooks/resaveChildren'
|
||||
import resaveSelfAfterCreate from './hooks/resaveSelfAfterCreate'
|
||||
import type { PluginConfig } from './types'
|
||||
import populateBreadcrumbs from './utilities/populateBreadcrumbs'
|
||||
|
||||
const nestedDocs =
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export interface Breadcrumb {
|
||||
url?: string
|
||||
label: string
|
||||
doc: string
|
||||
label: string
|
||||
url?: string
|
||||
}
|
||||
|
||||
export type GenerateURL = (
|
||||
@@ -15,9 +15,9 @@ export type GenerateLabel = (
|
||||
) => string
|
||||
|
||||
export interface PluginConfig {
|
||||
collections: string[]
|
||||
generateURL?: GenerateURL
|
||||
generateLabel?: GenerateLabel
|
||||
parentFieldSlug?: string
|
||||
breadcrumbsFieldSlug?: string
|
||||
collections: string[]
|
||||
generateLabel?: GenerateLabel
|
||||
generateURL?: GenerateURL
|
||||
parentFieldSlug?: string
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { CollectionConfig } from 'payload/types'
|
||||
|
||||
import type { PluginConfig } from '../types'
|
||||
|
||||
import formatBreadcrumb from './formatBreadcrumb'
|
||||
import getParents from './getParents'
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ const git = simpleGit()
|
||||
const packagesDir = path.resolve(__dirname, '../../packages')
|
||||
|
||||
export type PackageDetails = {
|
||||
commitMessage: string
|
||||
name: string
|
||||
newCommits: number
|
||||
shortName: string
|
||||
@@ -33,7 +34,8 @@ export const getPackageDetails = async (): Promise<PackageDetails[]> => {
|
||||
const publishedVersion = json?.['dist-tags']?.latest
|
||||
const publishDate = json?.time?.[publishedVersion]
|
||||
|
||||
const prevGitTag = `${dirName}/${packageJson.version}`
|
||||
const prevGitTag =
|
||||
dirName === 'payload' ? `v${packageJson.version}` : `${dirName}/${packageJson.version}`
|
||||
const prevGitTagHash = await git.revparse(prevGitTag)
|
||||
|
||||
const newCommits = await git.log({
|
||||
@@ -42,6 +44,7 @@ export const getPackageDetails = async (): Promise<PackageDetails[]> => {
|
||||
})
|
||||
|
||||
return {
|
||||
commitMessage: newCommits.latest?.message ?? '',
|
||||
name: packageJson.name as string,
|
||||
newCommits: newCommits.total,
|
||||
shortName: dirName,
|
||||
@@ -63,15 +66,20 @@ export const showPackageDetails = (details: PackageDetails[]) => {
|
||||
|
||||
${details
|
||||
.map((p) => {
|
||||
const name = p?.newCommits ? chalk.bold.green(p?.shortName.padEnd(28)) : p?.shortName.padEnd(28)
|
||||
const publishData = `${p?.publishedVersion} at ${p?.publishDate
|
||||
.split(':')
|
||||
.slice(0, 2)
|
||||
.join(':')
|
||||
.replace('T', ' ')}`
|
||||
const newCommits = `${p?.newCommits ? `${chalk.bold.green(p?.newCommits)} new commits` : ''}`
|
||||
const name = p?.newCommits
|
||||
? chalk.bold.green(p?.shortName.padEnd(28))
|
||||
: chalk.dim(p?.shortName.padEnd(28))
|
||||
const publishData = `${p?.publishedVersion.padEnd(8)}${p?.publishDate.split('T')[0]}`
|
||||
const newCommits = p?.newCommits ? chalk.bold.green(`⇡${p?.newCommits} `) : ' '
|
||||
const commitMessage = p?.commitMessage
|
||||
? chalk.dim(
|
||||
p.commitMessage.length < 57
|
||||
? p.commitMessage
|
||||
: p.commitMessage.substring(0, 60).concat('...'),
|
||||
)
|
||||
: ''
|
||||
|
||||
return ` ${name}${publishData} ${newCommits}`
|
||||
return ` ${name}${newCommits}${publishData} ${commitMessage}`
|
||||
})
|
||||
.join('\n')}
|
||||
|
||||
|
||||
@@ -17,6 +17,10 @@ async function main() {
|
||||
abort(`Invalid bump type: ${bump}.\n\nMust be one of: ${semver.RELEASE_TYPES.join(', ')}`)
|
||||
}
|
||||
|
||||
if (bump.startsWith('pre') && tag === 'latest') {
|
||||
abort(`Prerelease bumps must have tag: beta or canary`)
|
||||
}
|
||||
|
||||
const packageDetails = await getPackageDetails()
|
||||
showPackageDetails(packageDetails)
|
||||
|
||||
@@ -63,7 +67,7 @@ async function main() {
|
||||
${packagesToRelease
|
||||
.map((p) => {
|
||||
const { shortName, version } = packageMap[p]
|
||||
return ` ${shortName.padEnd(24)} ${version} -> ${semver.inc(version, bump)}`
|
||||
return ` ${shortName.padEnd(24)} ${version} -> ${semver.inc(version, bump, tag)}`
|
||||
})
|
||||
.join('\n')}
|
||||
`)
|
||||
@@ -77,29 +81,43 @@ ${packagesToRelease
|
||||
const results: { name: string; success: boolean }[] = []
|
||||
|
||||
for (const pkg of packagesToRelease) {
|
||||
const { packagePath, shortName } = packageMap[pkg]
|
||||
const { packagePath, shortName, name: registryName } = packageMap[pkg]
|
||||
|
||||
try {
|
||||
console.log(chalk.bold(`\n\nPublishing ${shortName}...\n\n`))
|
||||
console.log(chalk.bold(`\n\n🚀 Publishing ${shortName}...\n\n`))
|
||||
let npmVersionCmd = `npm --no-git-tag-version --prefix ${packagePath} version ${bump}`
|
||||
if (tag !== 'latest') {
|
||||
npmVersionCmd += ` --preid ${tag}`
|
||||
}
|
||||
execSync(npmVersionCmd, execOpts)
|
||||
execSync(`git add ${packagePath}/package.json`, execOpts)
|
||||
|
||||
const packageObj = await fse.readJson(`${packagePath}/package.json`)
|
||||
const newVersion = packageObj.version
|
||||
|
||||
const tagName = `${shortName}/${newVersion}`
|
||||
execSync(`git commit -m "chore(release): ${tagName}"`, execOpts)
|
||||
execSync(`git tag -a ${tagName} -m "${tagName}"`, execOpts)
|
||||
const shouldCommit = await confirm(`🧑💻 Commit Release?`)
|
||||
if (shouldCommit) {
|
||||
execSync(`git add ${packagePath}/package.json`, execOpts)
|
||||
execSync(`git commit -m "chore(release): ${tagName} [skip ci]" `, execOpts)
|
||||
}
|
||||
|
||||
const shouldTag = await confirm(`🏷️ Tag ${tagName}?`)
|
||||
if (shouldTag) {
|
||||
execSync(`git tag -a ${tagName} -m "${tagName}"`, execOpts)
|
||||
|
||||
if (pkg === 'payload') {
|
||||
execSync(`git tag -a v${newVersion} -m "v${newVersion}"`, execOpts)
|
||||
}
|
||||
}
|
||||
|
||||
let publishCmd = `pnpm publish -C ${packagePath} --no-git-checks`
|
||||
if (tag !== 'latest') {
|
||||
publishCmd += ` --tag ${tag}`
|
||||
}
|
||||
execSync(publishCmd, execOpts)
|
||||
const shouldPublish = await confirm(`🚢 Publish ${registryName}${chalk.yellow('@' + tag)}?`)
|
||||
if (shouldPublish) {
|
||||
execSync(publishCmd, execOpts)
|
||||
}
|
||||
|
||||
results.push({ name: shortName, success: true })
|
||||
} catch (error) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
A blank template for [Payload](https://github.com/payloadcms/payload) to help you get up and running quickly. This repo may have been created by running `npx create-payload-app` and selecting the "blank" template or by cloning this template on [Payload Cloud](https://payloadcms.com/new/clone/blank).
|
||||
|
||||
See the official [Examples Directory](https://github.com/payloadcms/payload/tree/master/examples) for details on how to use Payload in a variety of different ways.
|
||||
See the official [Examples Directory](https://github.com/payloadcms/payload/tree/main/examples) for details on how to use Payload in a variety of different ways.
|
||||
|
||||
## Development
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
"serve": "cross-env PAYLOAD_CONFIG_PATH=dist/payload.config.js NODE_ENV=production node dist/server.js",
|
||||
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png}\" dist/",
|
||||
"generate:types": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:types",
|
||||
"generate:graphQLSchema": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:graphQLSchema"
|
||||
"generate:graphQLSchema": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:graphQLSchema",
|
||||
"payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/bundler-webpack": "^1.0.0",
|
||||
|
||||
@@ -18,12 +18,13 @@
|
||||
"generate:types": "cross-env PAYLOAD_CONFIG_PATH=src/payload/payload.config.ts payload generate:types",
|
||||
"generate:graphQLSchema": "PAYLOAD_CONFIG_PATH=src/payload/payload.config.ts payload generate:graphQLSchema",
|
||||
"lint": "eslint src",
|
||||
"lint:fix": "eslint --fix --ext .ts,.tsx src"
|
||||
"lint:fix": "eslint --fix --ext .ts,.tsx src",
|
||||
"payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload/payload.config.ts payload"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/bundler-webpack": "^1.0.0",
|
||||
"@payloadcms/db-mongodb": "^1.0.0",
|
||||
"@payloadcms/plugin-cloud": "^2.0.0",
|
||||
"@payloadcms/plugin-cloud": "^2.0.0",
|
||||
"@payloadcms/plugin-nested-docs": "^1.0.8",
|
||||
"@payloadcms/plugin-redirects": "^1.0.0",
|
||||
"@payloadcms/plugin-seo": "^1.0.10",
|
||||
|
||||
@@ -1004,6 +1004,11 @@
|
||||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@drizzle-team/studio@^0.0.5":
|
||||
version "0.0.5"
|
||||
resolved "https://registry.npmjs.org/@drizzle-team/studio/-/studio-0.0.5.tgz#d2488ab4e8e755cc69287e2267cc4033a0e6ca35"
|
||||
integrity sha512-ps5qF0tMxWRVu+V5gvCRrQNqlY92aTnIKdq27gm9LZMSdaKYZt6AVvSK1dlUMzs6Rt0Jm80b+eWct6xShBKhIw==
|
||||
|
||||
"@emotion/babel-plugin@^11.11.0":
|
||||
version "11.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c"
|
||||
@@ -1103,6 +1108,132 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6"
|
||||
integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==
|
||||
|
||||
"@esbuild-kit/core-utils@^3.3.2":
|
||||
version "3.3.2"
|
||||
resolved "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.3.2.tgz#186b6598a5066f0413471d7c4d45828e399ba96c"
|
||||
integrity sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==
|
||||
dependencies:
|
||||
esbuild "~0.18.20"
|
||||
source-map-support "^0.5.21"
|
||||
|
||||
"@esbuild-kit/esm-loader@^2.5.5":
|
||||
version "2.6.5"
|
||||
resolved "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz#6eedee46095d7d13b1efc381e2211ed1c60e64ea"
|
||||
integrity sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==
|
||||
dependencies:
|
||||
"@esbuild-kit/core-utils" "^3.3.2"
|
||||
get-tsconfig "^4.7.0"
|
||||
|
||||
"@esbuild/android-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622"
|
||||
integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==
|
||||
|
||||
"@esbuild/android-arm@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682"
|
||||
integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==
|
||||
|
||||
"@esbuild/android-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2"
|
||||
integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==
|
||||
|
||||
"@esbuild/darwin-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1"
|
||||
integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==
|
||||
|
||||
"@esbuild/darwin-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d"
|
||||
integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54"
|
||||
integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==
|
||||
|
||||
"@esbuild/freebsd-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e"
|
||||
integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==
|
||||
|
||||
"@esbuild/linux-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0"
|
||||
integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==
|
||||
|
||||
"@esbuild/linux-arm@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0"
|
||||
integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==
|
||||
|
||||
"@esbuild/linux-ia32@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7"
|
||||
integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==
|
||||
|
||||
"@esbuild/linux-loong64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d"
|
||||
integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==
|
||||
|
||||
"@esbuild/linux-mips64el@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231"
|
||||
integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==
|
||||
|
||||
"@esbuild/linux-ppc64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb"
|
||||
integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==
|
||||
|
||||
"@esbuild/linux-riscv64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6"
|
||||
integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==
|
||||
|
||||
"@esbuild/linux-s390x@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071"
|
||||
integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==
|
||||
|
||||
"@esbuild/linux-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338"
|
||||
integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==
|
||||
|
||||
"@esbuild/netbsd-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1"
|
||||
integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==
|
||||
|
||||
"@esbuild/openbsd-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae"
|
||||
integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==
|
||||
|
||||
"@esbuild/sunos-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d"
|
||||
integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==
|
||||
|
||||
"@esbuild/win32-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9"
|
||||
integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==
|
||||
|
||||
"@esbuild/win32-ia32@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102"
|
||||
integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==
|
||||
|
||||
"@esbuild/win32-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d"
|
||||
integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0":
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
|
||||
@@ -1283,6 +1414,71 @@
|
||||
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
|
||||
integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
|
||||
|
||||
"@libsql/client@^0.3.1":
|
||||
version "0.3.5"
|
||||
resolved "https://registry.npmjs.org/@libsql/client/-/client-0.3.5.tgz#dfb80f4bd1969faeec7b550aabc68ba0653aa212"
|
||||
integrity sha512-4fZxGh0qKW5dtp1yuQLRvRAtbt02V4jzjM9sHSmz5k25xZTLg7/GlNudKdqKZrjJXEV5PvDNsczupBtedZZovw==
|
||||
dependencies:
|
||||
"@libsql/hrana-client" "^0.5.5"
|
||||
js-base64 "^3.7.5"
|
||||
libsql "^0.1.22"
|
||||
|
||||
"@libsql/darwin-arm64@0.1.29":
|
||||
version "0.1.29"
|
||||
resolved "https://registry.npmjs.org/@libsql/darwin-arm64/-/darwin-arm64-0.1.29.tgz#0772d8054ec8187efaa717d46fb1900845beb0d6"
|
||||
integrity sha512-lYSQaJV6Jsjuh/zms7i6QCL2GLQT17zeFVUZBNQxje0GyUtpvvfkz10S32n5+cY1TRbsbBCKzYhYxnTaTdD7Eg==
|
||||
|
||||
"@libsql/darwin-x64@0.1.29":
|
||||
version "0.1.29"
|
||||
resolved "https://registry.npmjs.org/@libsql/darwin-x64/-/darwin-x64-0.1.29.tgz#4f6e1a2b47606203048de283f1fee437a8db4ce7"
|
||||
integrity sha512-LFf6oSiBCQ0jJmh4WrQQKpa99qZVdY6KPNHU621hPV6LarEA/59YErMfAZOQY5A0iAhAzJ9ml0npt0Z63MU9dA==
|
||||
|
||||
"@libsql/hrana-client@^0.5.5":
|
||||
version "0.5.5"
|
||||
resolved "https://registry.npmjs.org/@libsql/hrana-client/-/hrana-client-0.5.5.tgz#5861aba59a593588283f9c33573ec5f571c35735"
|
||||
integrity sha512-i+hDBpiV719poqEiHupUUZYKJ9YSbCRFe5Q2PQ0v3mHIftePH6gayLjp2u6TXbqbO/Dv6y8yyvYlBXf/kFfRZA==
|
||||
dependencies:
|
||||
"@libsql/isomorphic-fetch" "^0.1.10"
|
||||
"@libsql/isomorphic-ws" "^0.1.5"
|
||||
js-base64 "^3.7.5"
|
||||
node-fetch "^3.3.2"
|
||||
|
||||
"@libsql/isomorphic-fetch@^0.1.10":
|
||||
version "0.1.10"
|
||||
resolved "https://registry.npmjs.org/@libsql/isomorphic-fetch/-/isomorphic-fetch-0.1.10.tgz#55f3e092a85e05babbd46b01521cbd6d43e38963"
|
||||
integrity sha512-dH0lMk50gKSvEKD78xWMu60SY1sjp1sY//iFLO0XMmBwfVfG136P9KOk06R4maBdlb8KMXOzJ1D28FR5ZKnHTA==
|
||||
dependencies:
|
||||
"@types/node-fetch" "^2.2.6"
|
||||
node-fetch "^2.6.12"
|
||||
|
||||
"@libsql/isomorphic-ws@^0.1.5":
|
||||
version "0.1.5"
|
||||
resolved "https://registry.npmjs.org/@libsql/isomorphic-ws/-/isomorphic-ws-0.1.5.tgz#e2d1faf965ba0f3be9301fbf5640164d03c4e606"
|
||||
integrity sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==
|
||||
dependencies:
|
||||
"@types/ws" "^8.5.4"
|
||||
ws "^8.13.0"
|
||||
|
||||
"@libsql/linux-arm64-gnu@0.1.29":
|
||||
version "0.1.29"
|
||||
resolved "https://registry.npmjs.org/@libsql/linux-arm64-gnu/-/linux-arm64-gnu-0.1.29.tgz#022466bd610d53c94411a43e2b82c553bde85eb9"
|
||||
integrity sha512-9Mtz3xRUpj1gRMFqi0+R/e2hAq711u0ogTvvlNWKjA9OZZfPgk0vLlT1Pqm0Pf1gyVc393RafZcCGP3FZMkjmg==
|
||||
|
||||
"@libsql/linux-x64-gnu@0.1.29":
|
||||
version "0.1.29"
|
||||
resolved "https://registry.npmjs.org/@libsql/linux-x64-gnu/-/linux-x64-gnu-0.1.29.tgz#b3919986f76a9710f47de6827d774dcf0289d70b"
|
||||
integrity sha512-EE3YpxqSRXnvxwPq38A9j1/poqzEJrDXnGEKcVcWqC2FB/qPJHxnAITBUNYicovdrrZYWRE5EM0LdSO6CMWi6A==
|
||||
|
||||
"@libsql/linux-x64-musl@0.1.29":
|
||||
version "0.1.29"
|
||||
resolved "https://registry.npmjs.org/@libsql/linux-x64-musl/-/linux-x64-musl-0.1.29.tgz#08cc1ab41be18387f2b786853f2a5e9466b86c74"
|
||||
integrity sha512-CJc+hKbUzF0JpAqQHT7P3SPb/NLCWsPzBD6j8fvHH34JLRYaIu9H8WrXsxAcVF65B7Jvat/CXnSe+iOctonBow==
|
||||
|
||||
"@libsql/win32-x64-msvc@0.1.29":
|
||||
version "0.1.29"
|
||||
resolved "https://registry.npmjs.org/@libsql/win32-x64-msvc/-/win32-x64-msvc-0.1.29.tgz#c1c004a732694ca0db3aa1134e2e304fef988e0b"
|
||||
integrity sha512-pIdMzY+NOKHDHiTUGLwMd3TICUiHbcxPedPRYJAI6ofTSu77JEmkmfkXcCOL8L8B9gio4ZuNeok+1i/ZPf6oeQ==
|
||||
|
||||
"@monaco-editor/loader@^1.3.3":
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.3.3.tgz#7f1742bd3cc21c0362a46a4056317f6e5215cfca"
|
||||
@@ -1297,6 +1493,11 @@
|
||||
dependencies:
|
||||
"@monaco-editor/loader" "^1.3.3"
|
||||
|
||||
"@neon-rs/load@^0.0.4":
|
||||
version "0.0.4"
|
||||
resolved "https://registry.npmjs.org/@neon-rs/load/-/load-0.0.4.tgz#2a2a3292c6f1fef043f49886712d3c96a547532e"
|
||||
integrity sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==
|
||||
|
||||
"@next/env@13.4.19":
|
||||
version "13.4.19"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.19.tgz#46905b4e6f62da825b040343cbc233144e9578d3"
|
||||
@@ -1425,6 +1626,19 @@
|
||||
prompts "2.4.2"
|
||||
uuid "9.0.0"
|
||||
|
||||
"@payloadcms/db-postgres@^0.1.9":
|
||||
version "0.1.9"
|
||||
resolved "https://registry.npmjs.org/@payloadcms/db-postgres/-/db-postgres-0.1.9.tgz#17f3bbd6cd39ba3c9b0cf939953d1e11dac2cca8"
|
||||
integrity sha512-PWtA1otpyCQasRZzA9U17BQNFaPjXRBFQOjx+CU6FiFjLkNkSEO4iK5Pdwsz23UrTlUbwNvgWd1u1+Xm4PHp9A==
|
||||
dependencies:
|
||||
"@libsql/client" "^0.3.1"
|
||||
console-table-printer "2.11.2"
|
||||
drizzle-kit "0.19.13-e99bac1"
|
||||
drizzle-orm "0.28.5"
|
||||
pg "8.11.3"
|
||||
prompts "2.4.2"
|
||||
to-snake-case "1.0.0"
|
||||
|
||||
"@payloadcms/eslint-config@^0.0.1":
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@payloadcms/eslint-config/-/eslint-config-0.0.1.tgz#4324702ddef6c773b3f3033795a13e6b50c95a92"
|
||||
@@ -2221,6 +2435,14 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
|
||||
integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==
|
||||
|
||||
"@types/node-fetch@^2.2.6":
|
||||
version "2.6.6"
|
||||
resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.6.tgz#b72f3f4bc0c0afee1c0bc9cff68e041d01e3e779"
|
||||
integrity sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
form-data "^4.0.0"
|
||||
|
||||
"@types/node@*", "@types/node@>=8.1.0":
|
||||
version "20.5.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.9.tgz#a70ec9d8fa0180a314c3ede0e20ea56ff71aed9a"
|
||||
@@ -2326,6 +2548,13 @@
|
||||
"@types/node" "*"
|
||||
"@types/webidl-conversions" "*"
|
||||
|
||||
"@types/ws@^8.5.4":
|
||||
version "8.5.7"
|
||||
resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz#1ca585074fe5d2c81dec7a3d451f244a2a6d83cb"
|
||||
integrity sha512-6UrLjiDUvn40CMrAubXuIVtj2PEfKDffJS7ychvnPU44j+KVeXmdHHTgqcM/dxLUTHxlXHiFM8Skmb8ozGdTnQ==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/yargs-parser@*":
|
||||
version "21.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.1.tgz#07773d7160494d56aa882d7531aac7319ea67c3b"
|
||||
@@ -2948,6 +3177,11 @@ buffer-from@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
||||
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
||||
|
||||
buffer-writer@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04"
|
||||
integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==
|
||||
|
||||
buffer@4.9.2:
|
||||
version "4.9.2"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8"
|
||||
@@ -3024,6 +3258,11 @@ camel-case@^4.1.2:
|
||||
pascal-case "^3.1.2"
|
||||
tslib "^2.0.3"
|
||||
|
||||
camelcase@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz#f02e50af9fd7782bc8b88a3558c32fd3a388f048"
|
||||
integrity sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==
|
||||
|
||||
caniuse-api@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
|
||||
@@ -3061,6 +3300,11 @@ chalk@^4.0.0:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chalk@^5.2.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385"
|
||||
integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==
|
||||
|
||||
charenc@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||
@@ -3108,7 +3352,7 @@ clean-css@^5.2.2:
|
||||
dependencies:
|
||||
source-map "~0.6.0"
|
||||
|
||||
cli-color@^2.0.2:
|
||||
cli-color@^2.0.0, cli-color@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-2.0.3.tgz#73769ba969080629670f3f2ef69a4bf4e7cc1879"
|
||||
integrity sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==
|
||||
@@ -3224,6 +3468,11 @@ commander@^8.3.0:
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
|
||||
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
|
||||
|
||||
commander@^9.4.1:
|
||||
version "9.5.0"
|
||||
resolved "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30"
|
||||
integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==
|
||||
|
||||
compressible@~2.0.16:
|
||||
version "2.0.18"
|
||||
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
|
||||
@@ -3561,6 +3810,11 @@ d@1, d@^1.0.1:
|
||||
es5-ext "^0.10.50"
|
||||
type "^1.0.1"
|
||||
|
||||
data-uri-to-buffer@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e"
|
||||
integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==
|
||||
|
||||
dataloader@2.2.2:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.2.2.tgz#216dc509b5abe39d43a9b9d97e6e5e473dfbe3e0"
|
||||
@@ -3687,7 +3941,7 @@ detect-file@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
|
||||
integrity sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==
|
||||
|
||||
detect-libc@^2.0.0, detect-libc@^2.0.1:
|
||||
detect-libc@2.0.2, detect-libc@^2.0.0, detect-libc@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.2.tgz#8ccf2ba9315350e1241b88d0ac3b0e1fbd99605d"
|
||||
integrity sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==
|
||||
@@ -3702,6 +3956,13 @@ diff@^5.1.0:
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40"
|
||||
integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==
|
||||
|
||||
difflib@~0.2.1:
|
||||
version "0.2.4"
|
||||
resolved "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz#b5e30361a6db023176d562892db85940a718f47e"
|
||||
integrity sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==
|
||||
dependencies:
|
||||
heap ">= 0.2.0"
|
||||
|
||||
dir-glob@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
||||
@@ -3818,6 +4079,36 @@ dotenv@8.6.0, dotenv@^8.2.0:
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
|
||||
integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==
|
||||
|
||||
dreamopt@~0.8.0:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.npmjs.org/dreamopt/-/dreamopt-0.8.0.tgz#5bcc80be7097e45fc489c342405ab68140a8c1d9"
|
||||
integrity sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==
|
||||
dependencies:
|
||||
wordwrap ">=0.0.2"
|
||||
|
||||
drizzle-kit@0.19.13-e99bac1:
|
||||
version "0.19.13-e99bac1"
|
||||
resolved "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.19.13-e99bac1.tgz#150e37b3b28d1e614eb63cd623367183902167b3"
|
||||
integrity sha512-25Ahwm7CoaXCcrSuDjNqNH7vwrjt1s+I4O1yXVDBwYnyRe4RY8ZD57s5iA9PE5C+IJwBJtxBSXYWkat+efb3ug==
|
||||
dependencies:
|
||||
"@drizzle-team/studio" "^0.0.5"
|
||||
"@esbuild-kit/esm-loader" "^2.5.5"
|
||||
camelcase "^7.0.1"
|
||||
chalk "^5.2.0"
|
||||
commander "^9.4.1"
|
||||
esbuild "^0.18.6"
|
||||
esbuild-register "^3.4.2"
|
||||
glob "^8.1.0"
|
||||
hanji "^0.0.5"
|
||||
json-diff "0.9.0"
|
||||
minimatch "^7.4.3"
|
||||
zod "^3.20.2"
|
||||
|
||||
drizzle-orm@0.28.5:
|
||||
version "0.28.5"
|
||||
resolved "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.28.5.tgz#67aa2a0fbe7d7a2066856188c2ac48106e14046f"
|
||||
integrity sha512-6r6Iw4c38NAmW6TiKH3TUpGUQ1YdlEoLJOQptn8XPx3Z63+vFNKfAiANqrIiYZiMjKR9+NYAL219nFrmo1duXA==
|
||||
|
||||
duplexer@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
|
||||
@@ -4033,6 +4324,41 @@ es6-weak-map@^2.0.3:
|
||||
es6-iterator "^2.0.3"
|
||||
es6-symbol "^3.1.1"
|
||||
|
||||
esbuild-register@^3.4.2:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.5.0.tgz#449613fb29ab94325c722f560f800dd946dc8ea8"
|
||||
integrity sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==
|
||||
dependencies:
|
||||
debug "^4.3.4"
|
||||
|
||||
esbuild@^0.18.6, esbuild@~0.18.20:
|
||||
version "0.18.20"
|
||||
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz#4709f5a34801b43b799ab7d6d82f7284a9b7a7a6"
|
||||
integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==
|
||||
optionalDependencies:
|
||||
"@esbuild/android-arm" "0.18.20"
|
||||
"@esbuild/android-arm64" "0.18.20"
|
||||
"@esbuild/android-x64" "0.18.20"
|
||||
"@esbuild/darwin-arm64" "0.18.20"
|
||||
"@esbuild/darwin-x64" "0.18.20"
|
||||
"@esbuild/freebsd-arm64" "0.18.20"
|
||||
"@esbuild/freebsd-x64" "0.18.20"
|
||||
"@esbuild/linux-arm" "0.18.20"
|
||||
"@esbuild/linux-arm64" "0.18.20"
|
||||
"@esbuild/linux-ia32" "0.18.20"
|
||||
"@esbuild/linux-loong64" "0.18.20"
|
||||
"@esbuild/linux-mips64el" "0.18.20"
|
||||
"@esbuild/linux-ppc64" "0.18.20"
|
||||
"@esbuild/linux-riscv64" "0.18.20"
|
||||
"@esbuild/linux-s390x" "0.18.20"
|
||||
"@esbuild/linux-x64" "0.18.20"
|
||||
"@esbuild/netbsd-x64" "0.18.20"
|
||||
"@esbuild/openbsd-x64" "0.18.20"
|
||||
"@esbuild/sunos-x64" "0.18.20"
|
||||
"@esbuild/win32-arm64" "0.18.20"
|
||||
"@esbuild/win32-ia32" "0.18.20"
|
||||
"@esbuild/win32-x64" "0.18.20"
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
@@ -4395,6 +4721,14 @@ fastq@^1.6.0:
|
||||
dependencies:
|
||||
reusify "^1.0.4"
|
||||
|
||||
fetch-blob@^3.1.2, fetch-blob@^3.1.4:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
|
||||
integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
|
||||
dependencies:
|
||||
node-domexception "^1.0.0"
|
||||
web-streams-polyfill "^3.0.3"
|
||||
|
||||
file-entry-cache@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
|
||||
@@ -4534,6 +4868,13 @@ form-data@^4.0.0:
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
formdata-polyfill@^4.0.10:
|
||||
version "4.0.10"
|
||||
resolved "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
|
||||
integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
|
||||
dependencies:
|
||||
fetch-blob "^3.1.2"
|
||||
|
||||
forwarded@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||
@@ -4638,6 +4979,13 @@ get-tsconfig@4.6.2:
|
||||
dependencies:
|
||||
resolve-pkg-maps "^1.0.0"
|
||||
|
||||
get-tsconfig@^4.7.0:
|
||||
version "4.7.2"
|
||||
resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz#0dcd6fb330391d46332f4c6c1bf89a6514c2ddce"
|
||||
integrity sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==
|
||||
dependencies:
|
||||
resolve-pkg-maps "^1.0.0"
|
||||
|
||||
github-from-package@0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
|
||||
@@ -4817,6 +5165,14 @@ gzip-size@^6.0.0:
|
||||
dependencies:
|
||||
duplexer "^0.1.2"
|
||||
|
||||
hanji@^0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.npmjs.org/hanji/-/hanji-0.0.5.tgz#22a5092e53b2a83ed6172c488ae0d68eb3119213"
|
||||
integrity sha512-Abxw1Lq+TnYiL4BueXqMau222fPSPMFtya8HdpWsz/xVAhifXou71mPh/kY2+08RgFcVccjG3uZHs6K5HAe3zw==
|
||||
dependencies:
|
||||
lodash.throttle "^4.1.1"
|
||||
sisteransi "^1.0.5"
|
||||
|
||||
has-bigints@^1.0.1, has-bigints@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
|
||||
@@ -4868,6 +5224,11 @@ he@^1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||
|
||||
"heap@>= 0.2.0":
|
||||
version "0.2.7"
|
||||
resolved "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc"
|
||||
integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==
|
||||
|
||||
help-me@^4.0.1:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/help-me/-/help-me-4.2.0.tgz#50712bfd799ff1854ae1d312c36eafcea85b0563"
|
||||
@@ -5417,6 +5778,11 @@ joycon@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03"
|
||||
integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==
|
||||
|
||||
js-base64@^3.7.5:
|
||||
version "3.7.5"
|
||||
resolved "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz#21e24cf6b886f76d6f5f165bfcd69cc55b9e3fca"
|
||||
integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==
|
||||
|
||||
js-beautify@^1.6.12:
|
||||
version "1.14.9"
|
||||
resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.14.9.tgz#a5db728bc5a0d84d3b1a597c376b29bd4d39c8e5"
|
||||
@@ -5449,6 +5815,15 @@ json-buffer@3.0.1:
|
||||
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
|
||||
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
|
||||
|
||||
json-diff@0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.npmjs.org/json-diff/-/json-diff-0.9.0.tgz#e7c536798053cb409113d7403c774849e8a0d7ff"
|
||||
integrity sha512-cVnggDrVkAAA3OvFfHpFEhOnmcsUpleEKq4d4O8sQWWSH40MBrWstKigVB1kGrgLWzuom+7rRdaCsnBD6VyObQ==
|
||||
dependencies:
|
||||
cli-color "^2.0.0"
|
||||
difflib "~0.2.1"
|
||||
dreamopt "~0.8.0"
|
||||
|
||||
json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||
@@ -5610,6 +5985,21 @@ levn@^0.4.1:
|
||||
prelude-ls "^1.2.1"
|
||||
type-check "~0.4.0"
|
||||
|
||||
libsql@^0.1.22:
|
||||
version "0.1.29"
|
||||
resolved "https://registry.npmjs.org/libsql/-/libsql-0.1.29.tgz#d3b929890d1a03ddb0a9dc054d069b041c1bdf28"
|
||||
integrity sha512-m81nXwDjz7WIwAblmhGJ68f6wJPtClG2N9kNxYG92vB7sALUGU3THza2J2+Mfg0YC+cy+hehorb7zHETj8doKw==
|
||||
dependencies:
|
||||
"@neon-rs/load" "^0.0.4"
|
||||
detect-libc "2.0.2"
|
||||
optionalDependencies:
|
||||
"@libsql/darwin-arm64" "0.1.29"
|
||||
"@libsql/darwin-x64" "0.1.29"
|
||||
"@libsql/linux-arm64-gnu" "0.1.29"
|
||||
"@libsql/linux-x64-gnu" "0.1.29"
|
||||
"@libsql/linux-x64-musl" "0.1.29"
|
||||
"@libsql/win32-x64-msvc" "0.1.29"
|
||||
|
||||
lilconfig@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
|
||||
@@ -5751,6 +6141,11 @@ lodash.snakecase@4.1.1:
|
||||
resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
|
||||
integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==
|
||||
|
||||
lodash.throttle@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||
integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==
|
||||
|
||||
lodash.uniq@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
@@ -5969,6 +6364,13 @@ minimatch@^5.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^7.4.3:
|
||||
version "7.4.6"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz#845d6f254d8f4a5e4fd6baf44d5f10c8448365fb"
|
||||
integrity sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimist@1.2.8, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.6:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||
@@ -6161,13 +6563,27 @@ node-addon-api@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762"
|
||||
integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==
|
||||
|
||||
node-fetch@^2.6.1:
|
||||
node-domexception@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
|
||||
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
|
||||
|
||||
node-fetch@^2.6.1, node-fetch@^2.6.12:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
node-fetch@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b"
|
||||
integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==
|
||||
dependencies:
|
||||
data-uri-to-buffer "^4.0.0"
|
||||
fetch-blob "^3.1.4"
|
||||
formdata-polyfill "^4.0.10"
|
||||
|
||||
node-releases@^2.0.13:
|
||||
version "2.0.13"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d"
|
||||
@@ -6368,6 +6784,11 @@ p-try@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||
|
||||
packet-reader@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74"
|
||||
integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==
|
||||
|
||||
param-case@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5"
|
||||
@@ -6625,6 +7046,64 @@ peek-readable@^4.1.0:
|
||||
resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.1.0.tgz#4ece1111bf5c2ad8867c314c81356847e8a62e72"
|
||||
integrity sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==
|
||||
|
||||
pg-cloudflare@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98"
|
||||
integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==
|
||||
|
||||
pg-connection-string@^2.6.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz#713d82053de4e2bd166fab70cd4f26ad36aab475"
|
||||
integrity sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==
|
||||
|
||||
pg-int8@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
|
||||
integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==
|
||||
|
||||
pg-pool@^3.6.1:
|
||||
version "3.6.1"
|
||||
resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz#5a902eda79a8d7e3c928b77abf776b3cb7d351f7"
|
||||
integrity sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==
|
||||
|
||||
pg-protocol@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz#4c91613c0315349363af2084608db843502f8833"
|
||||
integrity sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==
|
||||
|
||||
pg-types@^2.1.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3"
|
||||
integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==
|
||||
dependencies:
|
||||
pg-int8 "1.0.1"
|
||||
postgres-array "~2.0.0"
|
||||
postgres-bytea "~1.0.0"
|
||||
postgres-date "~1.0.4"
|
||||
postgres-interval "^1.1.0"
|
||||
|
||||
pg@8.11.3:
|
||||
version "8.11.3"
|
||||
resolved "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz#d7db6e3fe268fcedd65b8e4599cda0b8b4bf76cb"
|
||||
integrity sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==
|
||||
dependencies:
|
||||
buffer-writer "2.0.0"
|
||||
packet-reader "1.0.0"
|
||||
pg-connection-string "^2.6.2"
|
||||
pg-pool "^3.6.1"
|
||||
pg-protocol "^1.6.0"
|
||||
pg-types "^2.1.0"
|
||||
pgpass "1.x"
|
||||
optionalDependencies:
|
||||
pg-cloudflare "^1.1.1"
|
||||
|
||||
pgpass@1.x:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d"
|
||||
integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==
|
||||
dependencies:
|
||||
split2 "^4.1.0"
|
||||
|
||||
picocolors@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
@@ -7228,6 +7707,28 @@ postcss@8.4.31, postcss@^8.2.15, postcss@^8.4.24:
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
postgres-array@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e"
|
||||
integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==
|
||||
|
||||
postgres-bytea@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35"
|
||||
integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==
|
||||
|
||||
postgres-date@~1.0.4:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8"
|
||||
integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==
|
||||
|
||||
postgres-interval@^1.1.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695"
|
||||
integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==
|
||||
dependencies:
|
||||
xtend "^4.0.0"
|
||||
|
||||
prebuild-install@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45"
|
||||
@@ -8149,7 +8650,7 @@ source-list-map@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
|
||||
source-map-support@^0.5.13, source-map-support@~0.5.20:
|
||||
source-map-support@^0.5.13, source-map-support@^0.5.21, source-map-support@~0.5.20:
|
||||
version "0.5.21"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
|
||||
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
|
||||
@@ -8174,7 +8675,7 @@ sparse-bitfield@^3.0.3:
|
||||
dependencies:
|
||||
memory-pager "^1.0.2"
|
||||
|
||||
split2@^4.0.0:
|
||||
split2@^4.0.0, split2@^4.1.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
|
||||
integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
|
||||
@@ -8504,6 +9005,11 @@ to-fast-properties@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||
integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
|
||||
|
||||
to-no-case@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz#c722907164ef6b178132c8e69930212d1b4aa16a"
|
||||
integrity sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg==
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
@@ -8511,6 +9017,20 @@ to-regex-range@^5.0.1:
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
to-snake-case@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/to-snake-case/-/to-snake-case-1.0.0.tgz#ce746913897946019a87e62edfaeaea4c608ab8c"
|
||||
integrity sha512-joRpzBAk1Bhi2eGEYBjukEWHOe/IvclOkiJl3DtA91jV6NwQ3MwXA4FHYeqk8BNp/D8bmi9tcNbRu/SozP0jbQ==
|
||||
dependencies:
|
||||
to-space-case "^1.0.0"
|
||||
|
||||
to-space-case@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz#b052daafb1b2b29dc770cea0163e5ec0ebc9fc17"
|
||||
integrity sha512-rLdvwXZ39VOn1IxGL3V6ZstoTbwLRckQmn/U8ZDLuWwIXNpuZDhQ3AiRUlhTbOXFVE9C+dR51wM0CBDhk31VcA==
|
||||
dependencies:
|
||||
to-no-case "^1.0.0"
|
||||
|
||||
toidentifier@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
|
||||
@@ -8826,6 +9346,11 @@ watchpack@2.4.0, watchpack@^2.4.0:
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.1.2"
|
||||
|
||||
web-streams-polyfill@^3.0.3:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"
|
||||
integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==
|
||||
|
||||
webidl-conversions@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||
@@ -9020,6 +9545,11 @@ wildcard@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67"
|
||||
integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==
|
||||
|
||||
wordwrap@>=0.0.2:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
|
||||
integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
|
||||
|
||||
wrap-ansi@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
@@ -9039,6 +9569,11 @@ ws@^7.3.1:
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
|
||||
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
|
||||
|
||||
ws@^8.13.0:
|
||||
version "8.14.2"
|
||||
resolved "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f"
|
||||
integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==
|
||||
|
||||
xss@^1.0.6:
|
||||
version "1.0.14"
|
||||
resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.14.tgz#4f3efbde75ad0d82e9921cc3c95e6590dd336694"
|
||||
@@ -9047,7 +9582,7 @@ xss@^1.0.6:
|
||||
commander "^2.20.3"
|
||||
cssfilter "0.0.10"
|
||||
|
||||
xtend@~4.0.1:
|
||||
xtend@^4.0.0, xtend@~4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
@@ -9099,3 +9634,8 @@ zod@3.21.4:
|
||||
version "3.21.4"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db"
|
||||
integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==
|
||||
|
||||
zod@^3.20.2:
|
||||
version "3.22.4"
|
||||
resolved "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"
|
||||
integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
"generate:types": "cross-env PAYLOAD_CONFIG_PATH=src/payload/payload.config.ts payload generate:types",
|
||||
"generate:graphQLSchema": "PAYLOAD_CONFIG_PATH=src/payload/payload.config.ts payload generate:graphQLSchema",
|
||||
"lint": "eslint src",
|
||||
"lint:fix": "eslint --fix --ext .ts,.tsx src"
|
||||
"lint:fix": "eslint --fix --ext .ts,.tsx src",
|
||||
"payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload/payload.config.ts payload"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/bundler-webpack": "^1.0.0",
|
||||
"@payloadcms/db-mongodb": "^1.0.0",
|
||||
"@payloadcms/plugin-cloud": "^2.0.0",
|
||||
"@payloadcms/db-postgres": "^0.1.9",
|
||||
"@payloadcms/plugin-cloud": "^2.0.0",
|
||||
"@payloadcms/plugin-form-builder": "^1.0.13",
|
||||
"@payloadcms/plugin-nested-docs": "^1.0.8",
|
||||
"@payloadcms/plugin-redirects": "^1.0.0",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { webpackBundler } from '@payloadcms/bundler-webpack' // bundler-import
|
||||
import { mongooseAdapter } from '@payloadcms/db-mongodb' // database-adapter-import
|
||||
// import { mongooseAdapter } from '@payloadcms/db-mongodb' // database-adapter-import
|
||||
import { postgresAdapter } from '@payloadcms/db-postgres'
|
||||
import { payloadCloud } from '@payloadcms/plugin-cloud'
|
||||
import nestedDocs from '@payloadcms/plugin-nested-docs'
|
||||
import redirects from '@payloadcms/plugin-redirects'
|
||||
@@ -61,8 +62,13 @@ export default buildConfig({
|
||||
},
|
||||
editor: slateEditor({}), // editor-config
|
||||
// database-adapter-config-start
|
||||
db: mongooseAdapter({
|
||||
url: process.env.DATABASE_URI,
|
||||
// db: mongooseAdapter({
|
||||
// url: process.env.DATABASE_URI,
|
||||
// }),
|
||||
db: postgresAdapter({
|
||||
pool: {
|
||||
connectionString: process.env.DATABASE_URI,
|
||||
},
|
||||
}),
|
||||
// database-adapter-config-end
|
||||
serverURL: process.env.PAYLOAD_PUBLIC_SERVER_URL,
|
||||
|
||||
@@ -1677,10 +1677,10 @@
|
||||
prompts "2.4.2"
|
||||
uuid "9.0.0"
|
||||
|
||||
"@payloadcms/db-postgres@^0.1.8":
|
||||
version "0.1.8"
|
||||
resolved "https://registry.npmjs.org/@payloadcms/db-postgres/-/db-postgres-0.1.8.tgz#8603056a8e5de115af59aaa2715abfcf9a6d7ece"
|
||||
integrity sha512-3fXUVZeH1GT5oU/92MglREiQ5gU3IhF9lgLQR9W8GcGF9vlTY7k5I1qUzGALmIRu6FTCOXwDWTDMZxmmmt198w==
|
||||
"@payloadcms/db-postgres@^0.1.9":
|
||||
version "0.1.9"
|
||||
resolved "https://registry.npmjs.org/@payloadcms/db-postgres/-/db-postgres-0.1.9.tgz#17f3bbd6cd39ba3c9b0cf939953d1e11dac2cca8"
|
||||
integrity sha512-PWtA1otpyCQasRZzA9U17BQNFaPjXRBFQOjx+CU6FiFjLkNkSEO4iK5Pdwsz23UrTlUbwNvgWd1u1+Xm4PHp9A==
|
||||
dependencies:
|
||||
"@libsql/client" "^0.3.1"
|
||||
console-table-printer "2.11.2"
|
||||
|
||||
11
test/admin/collections/NoApiView.ts
Normal file
11
test/admin/collections/NoApiView.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { CollectionConfig } from '../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { noApiViewCollection } from '../shared'
|
||||
|
||||
export const CollectionNoApiView: CollectionConfig = {
|
||||
slug: noApiViewCollection,
|
||||
admin: {
|
||||
hideAPIURL: true,
|
||||
},
|
||||
fields: [],
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { CollectionGroup1B } from './collections/Group1B'
|
||||
import { CollectionGroup2A } from './collections/Group2A'
|
||||
import { CollectionGroup2B } from './collections/Group2B'
|
||||
import { CollectionHidden } from './collections/Hidden'
|
||||
import { CollectionNoApiView } from './collections/NoApiView'
|
||||
import { Posts } from './collections/Posts'
|
||||
import { Users } from './collections/Users'
|
||||
import AfterDashboard from './components/AfterDashboard'
|
||||
@@ -25,7 +26,8 @@ import { Global } from './globals/Global'
|
||||
import { GlobalGroup1A } from './globals/Group1A'
|
||||
import { GlobalGroup1B } from './globals/Group1B'
|
||||
import { GlobalHidden } from './globals/Hidden'
|
||||
import { postsSlug } from './shared'
|
||||
import { GlobalNoApiView } from './globals/NoApiView'
|
||||
import { noApiViewCollection, postsSlug } from './shared'
|
||||
|
||||
export interface Post {
|
||||
createdAt: Date
|
||||
@@ -77,6 +79,7 @@ export default buildConfigWithDefaults({
|
||||
Posts,
|
||||
Users,
|
||||
CollectionHidden,
|
||||
CollectionNoApiView,
|
||||
CustomViews1,
|
||||
CustomViews2,
|
||||
CollectionGroup1A,
|
||||
@@ -87,6 +90,7 @@ export default buildConfigWithDefaults({
|
||||
],
|
||||
globals: [
|
||||
GlobalHidden,
|
||||
GlobalNoApiView,
|
||||
Global,
|
||||
CustomGlobalViews1,
|
||||
CustomGlobalViews2,
|
||||
@@ -139,5 +143,10 @@ export default buildConfigWithDefaults({
|
||||
point: [5, -5],
|
||||
},
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: noApiViewCollection,
|
||||
data: {},
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
@@ -21,6 +21,8 @@ import {
|
||||
globalSlug,
|
||||
group1Collection1Slug,
|
||||
group1GlobalSlug,
|
||||
noApiViewCollection,
|
||||
noApiViewGlobal,
|
||||
postsSlug,
|
||||
slugPluralLabel,
|
||||
} from './shared'
|
||||
@@ -153,6 +155,32 @@ describe('admin', () => {
|
||||
await page.goto(url.global('hidden-global'))
|
||||
await expect(page.locator('.not-found')).toContainText('Nothing found')
|
||||
})
|
||||
|
||||
test('should not show API tab on collection when disabled in config', async () => {
|
||||
await page.goto(url.collection(noApiViewCollection))
|
||||
await page.locator('.collection-list .table a').click()
|
||||
await expect(page.locator('.doc-tabs__tabs-container')).not.toContainText('API')
|
||||
})
|
||||
|
||||
test('should not enable API route on collection when disabled in config', async () => {
|
||||
const collectionItems = await payload.find({
|
||||
collection: noApiViewCollection,
|
||||
limit: 1,
|
||||
})
|
||||
expect(collectionItems.docs.length).toBe(1)
|
||||
await page.goto(`${url.collection(noApiViewCollection)}/${collectionItems.docs[0].id}/api`)
|
||||
await expect(page.locator('.not-found')).toHaveCount(1)
|
||||
})
|
||||
|
||||
test('should not show API tab on global when disabled in config', async () => {
|
||||
await page.goto(url.global(noApiViewGlobal))
|
||||
await expect(page.locator('.doc-tabs__tabs-container')).not.toContainText('API')
|
||||
})
|
||||
|
||||
test('should not enable API route on global when disabled in config', async () => {
|
||||
await page.goto(`${url.global(noApiViewGlobal)}/api`)
|
||||
await expect(page.locator('.not-found')).toHaveCount(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('ui', () => {
|
||||
|
||||
10
test/admin/globals/NoApiView.ts
Normal file
10
test/admin/globals/NoApiView.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import type { GlobalConfig } from '../../../packages/payload/src/globals/config/types'
|
||||
import { noApiViewGlobal } from '../shared'
|
||||
|
||||
export const GlobalNoApiView: GlobalConfig = {
|
||||
slug: noApiViewGlobal,
|
||||
admin: {
|
||||
hideAPIURL: true,
|
||||
},
|
||||
fields: [],
|
||||
}
|
||||
@@ -11,3 +11,7 @@ export const slugPluralLabel = 'Posts'
|
||||
export const globalSlug = 'global'
|
||||
|
||||
export const group1GlobalSlug = 'group-globals-one'
|
||||
|
||||
export const noApiViewCollection = 'collection-no-api-view'
|
||||
|
||||
export const noApiViewGlobal = 'global-no-api-view'
|
||||
|
||||
@@ -12,14 +12,13 @@ export interface Relation {
|
||||
|
||||
const openAccess = {
|
||||
create: () => true,
|
||||
delete: () => true,
|
||||
read: () => true,
|
||||
update: () => true,
|
||||
delete: () => true,
|
||||
}
|
||||
|
||||
const collectionWithName = (collectionSlug: string): CollectionConfig => {
|
||||
return {
|
||||
slug: collectionSlug,
|
||||
access: openAccess,
|
||||
fields: [
|
||||
{
|
||||
@@ -27,55 +26,36 @@ const collectionWithName = (collectionSlug: string): CollectionConfig => {
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
slug: collectionSlug,
|
||||
}
|
||||
}
|
||||
|
||||
export const slug = 'posts'
|
||||
export const relationSlug = 'relation'
|
||||
|
||||
export const transactionSlug = 'transactions'
|
||||
|
||||
export const pointSlug = 'point'
|
||||
|
||||
export default buildConfigWithDefaults({
|
||||
graphQL: {
|
||||
schemaOutputFile: path.resolve(__dirname, 'schema.graphql'),
|
||||
queries: (GraphQL) => {
|
||||
return {
|
||||
QueryWithInternalError: {
|
||||
type: new GraphQL.GraphQLObjectType({
|
||||
name: 'QueryWithInternalError',
|
||||
fields: {
|
||||
text: {
|
||||
type: GraphQL.GraphQLString,
|
||||
},
|
||||
},
|
||||
}),
|
||||
resolve: () => {
|
||||
// Throwing an internal error with potentially sensitive data
|
||||
throw new Error('Lost connection to the Pentagon. Secret data: ******')
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
collections: [
|
||||
{
|
||||
slug: 'users',
|
||||
auth: true,
|
||||
access: openAccess,
|
||||
auth: true,
|
||||
fields: [],
|
||||
slug: 'users',
|
||||
},
|
||||
{
|
||||
slug: pointSlug,
|
||||
access: openAccess,
|
||||
fields: [
|
||||
{
|
||||
type: 'point',
|
||||
name: 'point',
|
||||
type: 'point',
|
||||
},
|
||||
],
|
||||
slug: pointSlug,
|
||||
},
|
||||
{
|
||||
slug,
|
||||
access: openAccess,
|
||||
fields: [
|
||||
{
|
||||
@@ -92,173 +72,173 @@ export default buildConfigWithDefaults({
|
||||
},
|
||||
{
|
||||
name: 'min',
|
||||
type: 'number',
|
||||
min: 10,
|
||||
type: 'number',
|
||||
},
|
||||
// Relationship
|
||||
{
|
||||
name: 'relationField',
|
||||
type: 'relationship',
|
||||
relationTo: relationSlug,
|
||||
type: 'relationship',
|
||||
},
|
||||
{
|
||||
name: 'relationToCustomID',
|
||||
type: 'relationship',
|
||||
relationTo: 'custom-ids',
|
||||
type: 'relationship',
|
||||
},
|
||||
// Relation hasMany
|
||||
{
|
||||
name: 'relationHasManyField',
|
||||
type: 'relationship',
|
||||
relationTo: relationSlug,
|
||||
hasMany: true,
|
||||
relationTo: relationSlug,
|
||||
type: 'relationship',
|
||||
},
|
||||
// Relation multiple relationTo
|
||||
{
|
||||
name: 'relationMultiRelationTo',
|
||||
type: 'relationship',
|
||||
relationTo: [relationSlug, 'dummy'],
|
||||
type: 'relationship',
|
||||
},
|
||||
// Relation multiple relationTo hasMany
|
||||
{
|
||||
name: 'relationMultiRelationToHasMany',
|
||||
type: 'relationship',
|
||||
relationTo: [relationSlug, 'dummy'],
|
||||
hasMany: true,
|
||||
relationTo: [relationSlug, 'dummy'],
|
||||
type: 'relationship',
|
||||
},
|
||||
{
|
||||
name: 'A1',
|
||||
type: 'group',
|
||||
fields: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'A2',
|
||||
defaultValue: 'textInRowInGroup',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
type: 'group',
|
||||
},
|
||||
{
|
||||
name: 'B1',
|
||||
type: 'group',
|
||||
fields: [
|
||||
{
|
||||
type: 'collapsible',
|
||||
label: 'Collapsible',
|
||||
fields: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'B2',
|
||||
defaultValue: 'textInRowInGroup',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
label: 'Collapsible',
|
||||
type: 'collapsible',
|
||||
},
|
||||
],
|
||||
type: 'group',
|
||||
},
|
||||
{
|
||||
name: 'C1',
|
||||
type: 'group',
|
||||
fields: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'C2Text',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
type: 'row',
|
||||
fields: [
|
||||
{
|
||||
type: 'collapsible',
|
||||
label: 'Collapsible2',
|
||||
fields: [
|
||||
{
|
||||
name: 'C2',
|
||||
type: 'group',
|
||||
fields: [
|
||||
{
|
||||
type: 'row',
|
||||
fields: [
|
||||
{
|
||||
type: 'collapsible',
|
||||
label: 'Collapsible2',
|
||||
fields: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'C3',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
label: 'Collapsible2',
|
||||
type: 'collapsible',
|
||||
},
|
||||
],
|
||||
type: 'row',
|
||||
},
|
||||
],
|
||||
type: 'group',
|
||||
},
|
||||
],
|
||||
label: 'Collapsible2',
|
||||
type: 'collapsible',
|
||||
},
|
||||
],
|
||||
type: 'row',
|
||||
},
|
||||
],
|
||||
type: 'group',
|
||||
},
|
||||
{
|
||||
type: 'tabs',
|
||||
tabs: [
|
||||
{
|
||||
label: 'Tab1',
|
||||
name: 'D1',
|
||||
fields: [
|
||||
{
|
||||
name: 'D2',
|
||||
type: 'group',
|
||||
fields: [
|
||||
{
|
||||
type: 'row',
|
||||
fields: [
|
||||
{
|
||||
type: 'collapsible',
|
||||
label: 'Collapsible2',
|
||||
fields: [
|
||||
{
|
||||
type: 'tabs',
|
||||
tabs: [
|
||||
{
|
||||
label: 'Tab1',
|
||||
fields: [
|
||||
{
|
||||
name: 'D3',
|
||||
type: 'group',
|
||||
fields: [
|
||||
{
|
||||
type: 'row',
|
||||
fields: [
|
||||
{
|
||||
type: 'collapsible',
|
||||
label: 'Collapsible2',
|
||||
fields: [
|
||||
{
|
||||
type: 'text',
|
||||
name: 'D4',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
label: 'Collapsible2',
|
||||
type: 'collapsible',
|
||||
},
|
||||
],
|
||||
type: 'row',
|
||||
},
|
||||
],
|
||||
type: 'group',
|
||||
},
|
||||
],
|
||||
label: 'Tab1',
|
||||
},
|
||||
],
|
||||
type: 'tabs',
|
||||
},
|
||||
],
|
||||
label: 'Collapsible2',
|
||||
type: 'collapsible',
|
||||
},
|
||||
],
|
||||
type: 'row',
|
||||
},
|
||||
],
|
||||
type: 'group',
|
||||
},
|
||||
],
|
||||
label: 'Tab1',
|
||||
},
|
||||
],
|
||||
type: 'tabs',
|
||||
},
|
||||
],
|
||||
slug,
|
||||
},
|
||||
{
|
||||
slug: 'custom-ids',
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
@@ -272,45 +252,87 @@ export default buildConfigWithDefaults({
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
slug: 'custom-ids',
|
||||
},
|
||||
collectionWithName(relationSlug),
|
||||
collectionWithName('dummy'),
|
||||
{
|
||||
slug: 'payload-api-test-ones',
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'payloadAPI',
|
||||
type: 'text',
|
||||
hooks: {
|
||||
afterRead: [({ req }) => req.payloadAPI],
|
||||
},
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
slug: 'payload-api-test-ones',
|
||||
},
|
||||
{
|
||||
slug: 'payload-api-test-twos',
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'payloadAPI',
|
||||
type: 'text',
|
||||
hooks: {
|
||||
afterRead: [({ req }) => req.payloadAPI],
|
||||
},
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'relation',
|
||||
type: 'relationship',
|
||||
relationTo: 'payload-api-test-ones',
|
||||
type: 'relationship',
|
||||
},
|
||||
],
|
||||
slug: 'payload-api-test-twos',
|
||||
},
|
||||
{
|
||||
access: openAccess,
|
||||
fields: [
|
||||
{
|
||||
name: 'transactionID',
|
||||
hooks: {
|
||||
beforeChange: [({ req }) => req.transactionID],
|
||||
},
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'sessions',
|
||||
hooks: {
|
||||
beforeChange: [({ req }) => Object.keys(req.payload.db.sessions)],
|
||||
},
|
||||
type: 'json',
|
||||
},
|
||||
],
|
||||
slug: transactionSlug,
|
||||
},
|
||||
],
|
||||
graphQL: {
|
||||
queries: (GraphQL) => {
|
||||
return {
|
||||
QueryWithInternalError: {
|
||||
resolve: () => {
|
||||
// Throwing an internal error with potentially sensitive data
|
||||
throw new Error('Lost connection to the Pentagon. Secret data: ******')
|
||||
},
|
||||
type: new GraphQL.GraphQLObjectType({
|
||||
name: 'QueryWithInternalError',
|
||||
fields: {
|
||||
text: {
|
||||
type: GraphQL.GraphQLString,
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
},
|
||||
schemaOutputFile: path.resolve(__dirname, 'schema.graphql'),
|
||||
},
|
||||
onInit: async (payload) => {
|
||||
const user = await payload.create({
|
||||
collection: 'users',
|
||||
@@ -331,8 +353,8 @@ export default buildConfigWithDefaults({
|
||||
await payload.create({
|
||||
collection: slug,
|
||||
data: {
|
||||
title: 'has custom ID relation',
|
||||
relationToCustomID: 1,
|
||||
title: 'has custom ID relation',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -353,23 +375,23 @@ export default buildConfigWithDefaults({
|
||||
await payload.create({
|
||||
collection: slug,
|
||||
data: {
|
||||
title: 'with-description',
|
||||
description: 'description',
|
||||
title: 'with-description',
|
||||
},
|
||||
})
|
||||
|
||||
await payload.create({
|
||||
collection: slug,
|
||||
data: {
|
||||
title: 'numPost1',
|
||||
number: 1,
|
||||
title: 'numPost1',
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: slug,
|
||||
data: {
|
||||
title: 'numPost2',
|
||||
number: 2,
|
||||
title: 'numPost2',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -390,15 +412,15 @@ export default buildConfigWithDefaults({
|
||||
await payload.create({
|
||||
collection: slug,
|
||||
data: {
|
||||
title: 'rel to hasMany',
|
||||
relationHasManyField: rel1.id,
|
||||
title: 'rel to hasMany',
|
||||
},
|
||||
})
|
||||
await payload.create({
|
||||
collection: slug,
|
||||
data: {
|
||||
title: 'rel to hasMany 2',
|
||||
relationHasManyField: rel2.id,
|
||||
title: 'rel to hasMany 2',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -406,11 +428,11 @@ export default buildConfigWithDefaults({
|
||||
await payload.create({
|
||||
collection: slug,
|
||||
data: {
|
||||
title: 'rel to multi',
|
||||
relationMultiRelationTo: {
|
||||
relationTo: relationSlug,
|
||||
value: rel2.id,
|
||||
},
|
||||
title: 'rel to multi',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -418,7 +440,6 @@ export default buildConfigWithDefaults({
|
||||
await payload.create({
|
||||
collection: slug,
|
||||
data: {
|
||||
title: 'rel to multi hasMany',
|
||||
relationMultiRelationToHasMany: [
|
||||
{
|
||||
relationTo: relationSlug,
|
||||
@@ -429,6 +450,7 @@ export default buildConfigWithDefaults({
|
||||
value: rel2.id,
|
||||
},
|
||||
],
|
||||
title: 'rel to multi hasMany',
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { Post } from './payload-types'
|
||||
|
||||
import payload from '../../packages/payload/src'
|
||||
import { mapAsync } from '../../packages/payload/src/utilities/mapAsync'
|
||||
import { devUser } from '../credentials'
|
||||
import { initPayloadTest } from '../helpers/configHelpers'
|
||||
import configPromise, { pointSlug, slug } from './config'
|
||||
|
||||
@@ -685,11 +686,11 @@ describe('collections-graphql', () => {
|
||||
|
||||
// language=graphQL
|
||||
const query = `query {
|
||||
Posts(where: { title: { exists: true }}) {
|
||||
docs {
|
||||
badFieldName
|
||||
Posts(where: { title: { exists: true }}) {
|
||||
docs {
|
||||
badFieldName
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
await client.request(query).catch((err) => {
|
||||
error = err
|
||||
@@ -702,12 +703,12 @@ describe('collections-graphql', () => {
|
||||
let error
|
||||
// language=graphQL
|
||||
const query = `mutation {
|
||||
createPost(data: {min: 1}) {
|
||||
id
|
||||
min
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
createPost(data: {min: 1}) {
|
||||
id
|
||||
min
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}`
|
||||
|
||||
await client.request(query).catch((err) => {
|
||||
@@ -722,21 +723,21 @@ describe('collections-graphql', () => {
|
||||
let error
|
||||
// language=graphQL
|
||||
const query = `mutation createTest {
|
||||
test1:createUser(data: { email: "test@test.com", password: "test" }) {
|
||||
email
|
||||
}
|
||||
test1:createUser(data: { email: "test@test.com", password: "test" }) {
|
||||
email
|
||||
}
|
||||
|
||||
test2:createUser(data: { email: "test2@test.com", password: "" }) {
|
||||
email
|
||||
}
|
||||
test2:createUser(data: { email: "test2@test.com", password: "" }) {
|
||||
email
|
||||
}
|
||||
|
||||
test3:createUser(data: { email: "test@test.com", password: "test" }) {
|
||||
email
|
||||
}
|
||||
test3:createUser(data: { email: "test@test.com", password: "test" }) {
|
||||
email
|
||||
}
|
||||
|
||||
test4:createUser(data: { email: "", password: "test" }) {
|
||||
email
|
||||
}
|
||||
test4:createUser(data: { email: "", password: "test" }) {
|
||||
email
|
||||
}
|
||||
}`
|
||||
|
||||
await client.request(query).catch((err) => {
|
||||
@@ -775,9 +776,9 @@ describe('collections-graphql', () => {
|
||||
let error
|
||||
// language=graphQL
|
||||
const query = `query {
|
||||
QueryWithInternalError {
|
||||
text
|
||||
}
|
||||
QueryWithInternalError {
|
||||
text
|
||||
}
|
||||
}`
|
||||
|
||||
await client.request(query).catch((err) => {
|
||||
@@ -792,6 +793,46 @@ describe('collections-graphql', () => {
|
||||
expect(error.response.errors[0].extensions.name).toEqual('Error')
|
||||
})
|
||||
})
|
||||
|
||||
if (['postgres'].includes(process.env.PAYLOAD_DATABASE)) {
|
||||
describe('Transactions', () => {
|
||||
let token
|
||||
let user
|
||||
|
||||
beforeAll(async () => {
|
||||
// language=graphQL
|
||||
const query = `mutation {
|
||||
loginUser(email: "${devUser.email}", password: "${devUser.password}") {
|
||||
token
|
||||
user {
|
||||
id
|
||||
email
|
||||
}
|
||||
}
|
||||
}`
|
||||
const response = await client.request(query)
|
||||
user = response.loginUser.user
|
||||
token = response.loginUser.token
|
||||
client.setHeaders({ Authorization: `JWT ${token}` })
|
||||
})
|
||||
|
||||
it('should use transaction', async () => {
|
||||
const query = `mutation {
|
||||
createTransaction(data: {}) {
|
||||
id
|
||||
transactionID
|
||||
sessions
|
||||
}
|
||||
}`
|
||||
const response = await client.request(query)
|
||||
const doc = response.createTransaction
|
||||
|
||||
expect(doc.transactionID).toBeDefined()
|
||||
expect(doc.sessions).toBeDefined()
|
||||
expect(doc.sessions).toContain(doc.transactionID)
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
async function createPost(overrides?: Partial<Post>) {
|
||||
|
||||
@@ -80,6 +80,12 @@ export default buildConfigWithDefaults({
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: 'without-graphql',
|
||||
access,
|
||||
graphQL: false,
|
||||
fields: [],
|
||||
},
|
||||
],
|
||||
onInit: async (payload) => {
|
||||
await payload.create({
|
||||
|
||||
@@ -224,5 +224,13 @@ describe('globals', () => {
|
||||
|
||||
expect(doc).toMatchObject(data)
|
||||
})
|
||||
|
||||
it('should not show globals with disabled graphql', async () => {
|
||||
const query = `query {
|
||||
WithoutGraphql { __typename }
|
||||
}`
|
||||
|
||||
await expect(client.request(query)).rejects.toHaveProperty('message')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -5,6 +5,7 @@ export const Media: CollectionConfig = {
|
||||
upload: true,
|
||||
access: {
|
||||
read: () => true,
|
||||
create: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
|
||||
@@ -401,6 +401,24 @@ export default buildConfigWithDefaults({
|
||||
Uploads1,
|
||||
Uploads2,
|
||||
AdminThumbnailCol,
|
||||
{
|
||||
slug: 'optional-file',
|
||||
upload: {
|
||||
staticURL: '/optional',
|
||||
staticDir: './optional',
|
||||
filesRequiredOnCreate: false,
|
||||
},
|
||||
fields: [],
|
||||
},
|
||||
{
|
||||
slug: 'required-file',
|
||||
upload: {
|
||||
staticURL: '/required',
|
||||
staticDir: './required',
|
||||
filesRequiredOnCreate: true,
|
||||
},
|
||||
fields: [],
|
||||
},
|
||||
],
|
||||
onInit: async (payload) => {
|
||||
const uploadsDir = path.resolve(__dirname, './media')
|
||||
|
||||
@@ -540,6 +540,48 @@ describe('Collections - Uploads', () => {
|
||||
|
||||
expect(await fileExists(path.join(__dirname, doc.filename))).toBe(false)
|
||||
})
|
||||
|
||||
describe('filesRequiredOnCreate', () => {
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
it('should allow file to be optional if filesRequiredOnCreate is false', async () => {
|
||||
expect(
|
||||
async () =>
|
||||
await payload.create({
|
||||
// @ts-ignore
|
||||
collection: 'optional-file',
|
||||
data: {},
|
||||
}),
|
||||
).not.toThrow()
|
||||
})
|
||||
|
||||
it('should throw an error if no file and filesRequiredOnCreate is true', async () => {
|
||||
await expect(async () =>
|
||||
payload.create({
|
||||
// @ts-ignore
|
||||
collection: 'required-file',
|
||||
data: {},
|
||||
}),
|
||||
).rejects.toThrow(
|
||||
expect.objectContaining({
|
||||
name: 'MissingFile',
|
||||
message: 'No files were uploaded.',
|
||||
}),
|
||||
)
|
||||
})
|
||||
it('should throw an error if no file and filesRequiredOnCreate is not defined', async () => {
|
||||
await expect(async () =>
|
||||
payload.create({
|
||||
collection: mediaSlug,
|
||||
data: {},
|
||||
}),
|
||||
).rejects.toThrow(
|
||||
expect.objectContaining({
|
||||
name: 'MissingFile',
|
||||
message: 'No files were uploaded.',
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
async function fileExists(fileName: string): Promise<boolean> {
|
||||
|
||||
@@ -11,13 +11,23 @@ export interface Config {
|
||||
relation: Relation
|
||||
audio: Audio
|
||||
'gif-resize': GifResize
|
||||
'no-image-sizes': NoImageSize
|
||||
'crop-only': CropOnly
|
||||
'focal-only': FocalOnly
|
||||
media: Media
|
||||
enlarge: Enlarge
|
||||
reduce: Reduce
|
||||
'media-trim': MediaTrim
|
||||
'unstored-media': UnstoredMedia
|
||||
'externally-served-media': ExternallyServedMedia
|
||||
'uploads-1': Uploads1
|
||||
'uploads-2': Uploads2
|
||||
'admin-thumbnail': AdminThumbnail
|
||||
'optional-file': OptionalFile
|
||||
'required-file': RequiredFile
|
||||
users: User
|
||||
'payload-preferences': PayloadPreference
|
||||
'payload-migrations': PayloadMigration
|
||||
}
|
||||
globals: {}
|
||||
}
|
||||
@@ -70,6 +80,14 @@ export interface Media {
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
accidentalSameSize?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
tablet?: {
|
||||
url?: string
|
||||
width?: number
|
||||
@@ -94,6 +112,62 @@ export interface Media {
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
focalTest?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
focalTest2?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
focalTest3?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
focalTest4?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
focalTest5?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
focalTest6?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
focalTest7?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
export interface Audio {
|
||||
@@ -131,6 +205,189 @@ export interface GifResize {
|
||||
}
|
||||
}
|
||||
}
|
||||
export interface NoImageSize {
|
||||
id: string
|
||||
updatedAt: string
|
||||
createdAt: string
|
||||
url?: string
|
||||
filename?: string
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
width?: number
|
||||
height?: number
|
||||
}
|
||||
export interface CropOnly {
|
||||
id: string
|
||||
updatedAt: string
|
||||
createdAt: string
|
||||
url?: string
|
||||
filename?: string
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
width?: number
|
||||
height?: number
|
||||
sizes?: {
|
||||
focalTest?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
focalTest2?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
focalTest3?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
export interface FocalOnly {
|
||||
id: string
|
||||
updatedAt: string
|
||||
createdAt: string
|
||||
url?: string
|
||||
filename?: string
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
width?: number
|
||||
height?: number
|
||||
sizes?: {
|
||||
focalTest?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
focalTest2?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
focalTest3?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
export interface Enlarge {
|
||||
id: string
|
||||
updatedAt: string
|
||||
createdAt: string
|
||||
url?: string
|
||||
filename?: string
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
width?: number
|
||||
height?: number
|
||||
sizes?: {
|
||||
accidentalSameSize?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
sameSizeWithNewFormat?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
resizedLarger?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
resizedSmaller?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
widthLowerHeightLarger?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
export interface Reduce {
|
||||
id: string
|
||||
updatedAt: string
|
||||
createdAt: string
|
||||
url?: string
|
||||
filename?: string
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
width?: number
|
||||
height?: number
|
||||
sizes?: {
|
||||
accidentalSameSize?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
sameSizeWithNewFormat?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
resizedLarger?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
resizedSmaller?: {
|
||||
url?: string
|
||||
width?: number
|
||||
height?: number
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
filename?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
export interface MediaTrim {
|
||||
id: string
|
||||
updatedAt: string
|
||||
@@ -217,6 +474,39 @@ export interface Uploads2 {
|
||||
width?: number
|
||||
height?: number
|
||||
}
|
||||
export interface AdminThumbnail {
|
||||
id: string
|
||||
updatedAt: string
|
||||
createdAt: string
|
||||
url?: string
|
||||
filename?: string
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
width?: number
|
||||
height?: number
|
||||
}
|
||||
export interface OptionalFile {
|
||||
id: string
|
||||
updatedAt: string
|
||||
createdAt: string
|
||||
url?: string
|
||||
filename?: string
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
width?: number
|
||||
height?: number
|
||||
}
|
||||
export interface RequiredFile {
|
||||
id: string
|
||||
updatedAt: string
|
||||
createdAt: string
|
||||
url?: string
|
||||
filename?: string
|
||||
mimeType?: string
|
||||
filesize?: number
|
||||
width?: number
|
||||
height?: number
|
||||
}
|
||||
export interface User {
|
||||
id: string
|
||||
updatedAt: string
|
||||
@@ -228,5 +518,58 @@ export interface User {
|
||||
hash?: string
|
||||
loginAttempts?: number
|
||||
lockUntil?: string
|
||||
password?: string
|
||||
password: string
|
||||
}
|
||||
export interface PayloadPreference {
|
||||
id: string
|
||||
user: {
|
||||
relationTo: 'users'
|
||||
value: string | User
|
||||
}
|
||||
key?: string
|
||||
value?:
|
||||
| {
|
||||
[k: string]: unknown
|
||||
}
|
||||
| unknown[]
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null
|
||||
updatedAt: string
|
||||
createdAt: string
|
||||
}
|
||||
export interface PayloadMigration {
|
||||
id: string
|
||||
name?: string
|
||||
batch?: number
|
||||
updatedAt: string
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
declare module 'payload' {
|
||||
export interface GeneratedTypes {
|
||||
collections: {
|
||||
relation: Relation
|
||||
audio: Audio
|
||||
'gif-resize': GifResize
|
||||
'no-image-sizes': NoImageSize
|
||||
'crop-only': CropOnly
|
||||
'focal-only': FocalOnly
|
||||
media: Media
|
||||
enlarge: Enlarge
|
||||
reduce: Reduce
|
||||
'media-trim': MediaTrim
|
||||
'unstored-media': UnstoredMedia
|
||||
'externally-served-media': ExternallyServedMedia
|
||||
'uploads-1': Uploads1
|
||||
'uploads-2': Uploads2
|
||||
'admin-thumbnail': AdminThumbnail
|
||||
'optional-file': OptionalFile
|
||||
'required-file': RequiredFile
|
||||
users: User
|
||||
'payload-preferences': PayloadPreference
|
||||
'payload-migrations': PayloadMigration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,21 +4,6 @@ import { CustomPublishButton } from '../elements/CustomSaveButton'
|
||||
import { draftSlug } from '../shared'
|
||||
|
||||
const DraftPosts: CollectionConfig = {
|
||||
slug: draftSlug,
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
defaultColumns: ['title', 'description', 'createdAt', '_status'],
|
||||
preview: () => 'https://payloadcms.com',
|
||||
components: {
|
||||
edit: {
|
||||
PublishButton: CustomPublishButton,
|
||||
},
|
||||
},
|
||||
},
|
||||
versions: {
|
||||
maxPerDoc: 35,
|
||||
drafts: true,
|
||||
},
|
||||
access: {
|
||||
read: ({ req: { user } }) => {
|
||||
if (user) {
|
||||
@@ -42,74 +27,82 @@ const DraftPosts: CollectionConfig = {
|
||||
},
|
||||
readVersions: ({ req: { user } }) => Boolean(user),
|
||||
},
|
||||
admin: {
|
||||
components: {
|
||||
edit: {
|
||||
PublishButton: CustomPublishButton,
|
||||
},
|
||||
},
|
||||
defaultColumns: ['title', 'description', 'createdAt', '_status'],
|
||||
preview: () => 'https://payloadcms.com',
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
label: 'Title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
unique: true,
|
||||
localized: true,
|
||||
required: true,
|
||||
type: 'text',
|
||||
unique: true,
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
label: 'Description',
|
||||
type: 'textarea',
|
||||
required: true,
|
||||
type: 'textarea',
|
||||
},
|
||||
{
|
||||
name: 'radio',
|
||||
type: 'radio',
|
||||
options: [
|
||||
{
|
||||
value: 'test',
|
||||
label: { en: 'Test en', es: 'Test es' },
|
||||
value: 'test',
|
||||
},
|
||||
],
|
||||
type: 'radio',
|
||||
},
|
||||
{
|
||||
name: 'select',
|
||||
type: 'select',
|
||||
hasMany: true,
|
||||
options: [
|
||||
{
|
||||
value: 'test1',
|
||||
label: { en: 'Test1 en', es: 'Test1 es' },
|
||||
value: 'test1',
|
||||
},
|
||||
{
|
||||
value: 'test2',
|
||||
label: { en: 'Test2 en', es: 'Test2 es' },
|
||||
value: 'test2',
|
||||
},
|
||||
],
|
||||
type: 'select',
|
||||
},
|
||||
{
|
||||
name: 'layout',
|
||||
type: 'blocks',
|
||||
name: 'blocksField',
|
||||
blocks: [
|
||||
{
|
||||
slug: 'cta',
|
||||
fields: [
|
||||
{
|
||||
name: 'linkGroup',
|
||||
type: 'group',
|
||||
fields: [
|
||||
{
|
||||
name: 'links',
|
||||
type: 'array',
|
||||
fields: [
|
||||
{
|
||||
name: 'url',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
name: 'text',
|
||||
type: 'text',
|
||||
},
|
||||
{
|
||||
name: 'localized',
|
||||
localized: true,
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
slug: 'block',
|
||||
},
|
||||
],
|
||||
type: 'blocks',
|
||||
},
|
||||
],
|
||||
slug: draftSlug,
|
||||
versions: {
|
||||
drafts: true,
|
||||
maxPerDoc: 35,
|
||||
},
|
||||
}
|
||||
|
||||
export default DraftPosts
|
||||
|
||||
@@ -25,10 +25,19 @@ export default buildConfigWithDefaults({
|
||||
},
|
||||
})
|
||||
|
||||
const blocksField = [
|
||||
{
|
||||
blockType: 'block',
|
||||
localized: 'text',
|
||||
text: 'text',
|
||||
},
|
||||
]
|
||||
|
||||
const { id: draftID } = await payload.create({
|
||||
collection: draftSlug,
|
||||
data: {
|
||||
id: 1,
|
||||
blocksField,
|
||||
description: 'draft description',
|
||||
radio: 'test',
|
||||
title: 'draft title',
|
||||
@@ -41,6 +50,7 @@ export default buildConfigWithDefaults({
|
||||
data: {
|
||||
id: 2,
|
||||
_status: 'published',
|
||||
blocksField,
|
||||
description: 'published description',
|
||||
radio: 'test',
|
||||
title: 'published title',
|
||||
@@ -51,6 +61,7 @@ export default buildConfigWithDefaults({
|
||||
await payload.create({
|
||||
collection: draftSlug,
|
||||
data: {
|
||||
blocksField,
|
||||
description: 'published description',
|
||||
title: titleToDelete,
|
||||
},
|
||||
|
||||
@@ -241,9 +241,9 @@ describe('Versions', () => {
|
||||
})
|
||||
|
||||
describe('Restore', () => {
|
||||
it('should versions be in correct order', async () => {
|
||||
it('should return findVersions in correct order', async () => {
|
||||
const somePost = await payload.create({
|
||||
collection,
|
||||
collection: draftSlug,
|
||||
data: {
|
||||
description: 'description 1',
|
||||
title: 'first post',
|
||||
@@ -251,59 +251,116 @@ describe('Versions', () => {
|
||||
})
|
||||
|
||||
const updatedPost = await payload.update({
|
||||
id: collectionLocalPostID,
|
||||
collection,
|
||||
id: somePost.id,
|
||||
collection: draftSlug,
|
||||
data: {
|
||||
title: 'This should be the latest version',
|
||||
},
|
||||
})
|
||||
|
||||
const versions = await payload.findVersions({
|
||||
collection,
|
||||
collection: draftSlug,
|
||||
where: {
|
||||
parent: { equals: somePost.id },
|
||||
},
|
||||
})
|
||||
|
||||
expect(versions.docs[0].version.title).toBe(updatedPost.title)
|
||||
})
|
||||
it('should allow a version to be restored', async () => {
|
||||
const title2 = 'Another updated post title in EN'
|
||||
const updated = 'updated'
|
||||
|
||||
const updatedPost = await payload.update({
|
||||
id: collectionLocalPostID,
|
||||
collection,
|
||||
const versionedPost = await payload.create({
|
||||
collection: draftSlug,
|
||||
data: {
|
||||
description: 'version description',
|
||||
title: 'version title',
|
||||
},
|
||||
draft: true,
|
||||
})
|
||||
|
||||
// @ts-ignore
|
||||
let updatedPost = await payload.update({
|
||||
id: versionedPost.id,
|
||||
collection: draftSlug,
|
||||
data: {
|
||||
blocksField: [
|
||||
{
|
||||
blockType: 'block',
|
||||
localized: 'text',
|
||||
text: 'text',
|
||||
},
|
||||
],
|
||||
title: title2,
|
||||
},
|
||||
draft: true,
|
||||
})
|
||||
// @ts-ignore
|
||||
updatedPost = await payload.update({
|
||||
id: versionedPost.id,
|
||||
collection: draftSlug,
|
||||
data: {
|
||||
blocksField: [
|
||||
{
|
||||
id: updatedPost.blocksField[0].id,
|
||||
blockName: 'breakpoint',
|
||||
blockType: 'block',
|
||||
localized: updated,
|
||||
text: updated,
|
||||
},
|
||||
],
|
||||
title: title2,
|
||||
},
|
||||
draft: true,
|
||||
})
|
||||
|
||||
expect(updatedPost.title).toBe(title2)
|
||||
expect(updatedPost.blocksField[0].text).toBe(updated)
|
||||
expect(updatedPost.blocksField[0].localized).toBe(updated)
|
||||
|
||||
// Make sure it was updated correctly
|
||||
const draftFromUpdatedPost = await payload.findByID({
|
||||
id: collectionLocalPostID,
|
||||
collection,
|
||||
id: versionedPost.id,
|
||||
collection: draftSlug,
|
||||
draft: true,
|
||||
})
|
||||
expect(draftFromUpdatedPost.title).toBe(title2)
|
||||
expect(draftFromUpdatedPost.blocksField).toHaveLength(1)
|
||||
expect(draftFromUpdatedPost.blocksField[0].localized).toStrictEqual(updated)
|
||||
|
||||
const versions = await payload.findVersions({
|
||||
collection,
|
||||
collection: draftSlug,
|
||||
where: {
|
||||
parent: {
|
||||
equals: versionedPost.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// restore to latest version
|
||||
const versionToRestore = versions.docs[versions.docs.length - 1]
|
||||
// restore to previous version
|
||||
const restoredVersion = await payload.restoreVersion({
|
||||
id: versions.docs[1].id,
|
||||
collection,
|
||||
id: versionToRestore.id,
|
||||
collection: draftSlug,
|
||||
})
|
||||
|
||||
expect(restoredVersion.title).toBeDefined()
|
||||
expect({ ...restoredVersion }).toMatchObject({
|
||||
...versionToRestore.version,
|
||||
updatedAt: restoredVersion.updatedAt,
|
||||
})
|
||||
|
||||
const latestDraft = await payload.findByID({
|
||||
id: collectionLocalPostID,
|
||||
collection,
|
||||
id: versionedPost.id,
|
||||
collection: draftSlug,
|
||||
draft: true,
|
||||
})
|
||||
|
||||
expect(latestDraft.title).toBe(versions.docs[1].version.title)
|
||||
expect(latestDraft).toMatchObject({
|
||||
...versionToRestore.version,
|
||||
updatedAt: latestDraft.updatedAt,
|
||||
})
|
||||
expect(latestDraft.blocksField).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user