Compare commits

..

1 Commits

Author SHA1 Message Date
Dan Ribbens
8a77320841 chore: add localized to version field 2023-07-25 15:21:21 -04:00
197 changed files with 15615 additions and 49198 deletions

View File

@@ -1,29 +1,5 @@
## [1.11.8](https://github.com/payloadcms/payload/compare/v1.11.7...v1.11.8) (2023-07-31)
## [1.11.7](https://github.com/payloadcms/payload/compare/v1.11.6...v1.11.7) (2023-07-27)
### Bug Fixes
* [#3062](https://github.com/payloadcms/payload/issues/3062) ([0280953](https://github.com/payloadcms/payload/commit/02809532b484d9018c6528cfbbbb43abfd55a540))
* array row deletion ([#3062](https://github.com/payloadcms/payload/issues/3062)) ([cf9795b](https://github.com/payloadcms/payload/commit/cf9795b8d8b53c48335ff4c32c6c51b3de4f7bc9))
* incorrect image rotation after being processed by sharp ([#3081](https://github.com/payloadcms/payload/issues/3081)) ([0a91950](https://github.com/payloadcms/payload/commit/0a91950f052ce40427801e6561a0f676354a2ca4))
### Features
* ability to add context to payload's request object ([#2796](https://github.com/payloadcms/payload/issues/2796)) ([67ba131](https://github.com/payloadcms/payload/commit/67ba131cc61f3d3b30ef9ef7fc150344ca82da2f))
## [1.11.6](https://github.com/payloadcms/payload/compare/v1.11.5...v1.11.6) (2023-07-25)
### Bug Fixes
* **collections:admin:** Enable adminThumbnail fn execution on all types ([2c74e93](https://github.com/payloadcms/payload/commit/2c74e9396a216a033e2bacdf189b7f28a0f97505))
* threads hasMaxRows into ArrayAction components within blocks and arrays ([#3066](https://github.com/payloadcms/payload/issues/3066)) ([d43c83d](https://github.com/payloadcms/payload/commit/d43c83dad1bab5b05f4fcbae7d41de369905797c))
## [1.11.5](https://github.com/payloadcms/payload/compare/v1.11.4...v1.11.5) (2023-07-25)

View File

@@ -1,127 +0,0 @@
---
title: Context
label: Context
order: 50
desc: Context allows you to pass in extra data that can be shared between hooks
keywords: hooks, context, payload context, payloadcontext, data, extra data, shared data, shared, extra
---
The `context` object in hooks is used to share data across different hooks. The persists throughout the entire lifecycle of a request and is available within every hook. This allows you to add logic to your hooks based on the request state by setting properties to `req.context` and using them elsewhere.
## When to use Context
Context gives you a way forward on otherwise difficult problems such as:
1. **Passing data between hooks**: Needing data in multiple hooks from a 3rd party API, it could be retrieved and used in `beforeChange` and later used again in an `afterChange` hook without having to fetch it twice.
2. **Preventing infinite loops**: Calling `payload.update()` on the same document that triggered an `afterChange` hook will create an infinite loop, control the flow by assigning a no-op condition to context
3. **Passing data to local API**: Setting values on the `req.context` and pass it to `payload.create()` you can provide additional data to hooks without adding extraneous fields.
4. **Passing data between hooks and middleware or custom endpoints**: Hooks could set context across multiple collections and then be used in a final `postMiddleware`.
## How to Use Context
Let's see examples on how context can be used in the first two scenarios mentioned above:
### Passing data between hooks
To pass data between hooks, you can assign values to context in an earlier hook in the lifecycle of a request and expect it the context in a later hook.
For example:
```ts
const Customer: CollectionConfig = {
slug: 'customers',
hooks: {
beforeChange: [async ({ context, data }) => {
// assign the customerData to context for use later
context.customerData = await fetchCustomerData(data.customerID);
return {
...data,
// some data we use here
name: context.customerData.name
};
}],
afterChange: [async ({ context, doc, req }) => {
// use context.customerData without needing to fetch it again
if (context.customerData.contacted === false) {
createTodo('Call Customer', context.customerData)
}
}],
},
fields: [ /* ... */ ],
};
```
### Preventing infinite loops
Let's say you have an `afterChange` hook, and you want to do a calculation inside the hook (as the document ID needed for the calculation is available in the `afterChange` hook, but not in the `beforeChange` hook). Once that's done, you want to update the document with the result of the calculation.
Bad example:
```ts
const Customer: CollectionConfig = {
slug: 'customers',
hooks: {
afterChange: [async ({ doc }) => {
await payload.update({
// DANGER: updating the same slug as the collection in an afterChange will create an infinite loop!
collection: 'customers',
id: doc.id,
data: {
...(await fetchCustomerData(data.customerID))
},
});
}],
},
fields: [ /* ... */ ],
};
```
Instead of the above, we need to tell the `afterChange` hook to not run again if it performs the update (and thus not update itself again). We can solve that with context.
Fixed example:
```ts
const MyCollection: CollectionConfig = {
slug: 'slug',
hooks: {
afterChange: [async ({ context, doc }) => {
// return if flag was previously set
if (context.triggerAfterChange === false) {
return;
}
await payload.update({
collection: contextHooksSlug,
id: doc.id,
data: {
...(await fetchCustomerData(data.customerID))
},
context: {
// set a flag to prevent from running again
triggerAfterChange: false,
},
});
}],
},
fields: [ /* ... */ ],
};
```
## Typing context
The default typescript interface for `context` is `{ [key: string]: unknown }`. If you prefer a more strict typing in your project or when authoring plugins for others, you can override this using the `declare` syntax.
This is known as "type augmentation" - a TypeScript feature which allows us to add types to existing objects. Simply put this in any .ts or .d.ts file:
```ts
import { RequestContext as OriginalRequestContext } from 'payload';
declare module 'payload' {
// Create a new interface that merges your additional fields with the original one
export interface RequestContext extends OriginalRequestContext {
myObject?: string;
// ...
}
}
```
This will add a the property `myObject` with a type of string to every context object. Make sure to follow this example correctly, as type augmentation can mess up your types if you do it wrong.

View File

@@ -77,7 +77,6 @@ You can specify more options within the Local API vs. REST or GraphQL due to the
| `user` | If you set `overrideAccess` to `false`, you can pass a user to use against the access control checks. |
| `showHiddenFields` | Opt-in to receiving hidden fields. By default, they are hidden from returned documents in accordance to your config. |
| `pagination` | Set to false to return all documents and avoid querying for document counts. |
| `context` | [Context](/docs/hooks/context), which will then be passed to `context` and `req.context`, which can be read by hooks. Useful if you want to pass additional information to the hooks which shouldn't be necessarily part of the document, for example a `triggerBeforeChange` option which can be read by the BeforeChange hook to determine if it should run or not. |
_There are more options available on an operation by operation basis outlined below._

View File

@@ -190,7 +190,9 @@ export const Media: CollectionConfig = {
<Banner>
<strong>Note:</strong>
<br />
This function runs in the browser. If your function returns `null` or `false` Payload will show the default generic file thumbnail instead.
If you specify a function to return an admin thumbnail, but your upload is not
an image file type (for example, PDF or TXT) your function will not be used.
Instead, Payload will display its generic file upload graphic.
</Banner>
### MimeTypes

View File

@@ -19,7 +19,7 @@
"dependencies": {
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest"
"payload": "^1.11.0"
},
"devDependencies": {
"@payloadcms/eslint-config": "^0.0.1",
@@ -42,4 +42,4 @@
"ts-node": "^9.1.1",
"typescript": "^4.8.4"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
{
"name": "payload-nextjs-auth-example-app",
"name": "payload-nextjs-auth-example",
"version": "0.1.0",
"private": true,
"scripts": {

View File

@@ -1,5 +1,5 @@
{
"name": "payload-nextjs-auth-example-pages",
"name": "payload-nextjs-auth-example",
"version": "1.0.0",
"scripts": {
"dev": "next dev -p 3001",

View File

@@ -24,7 +24,7 @@
"escape-html": "^1.0.3",
"express": "^4.17.1",
"next": "^13.4.8",
"payload": "latest",
"payload": "^1.8.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
@@ -52,4 +52,4 @@
"ts-node": "^10.9.1",
"typescript": "^4.8.4"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@
"dependencies": {
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest",
"payload": "1.6.29",
"handlebars": "^4.7.7",
"inline-css": "^4.0.2"
},
@@ -32,4 +32,4 @@
"ts-node": "^9.1.1",
"typescript": "^4.8.4"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
{
"name": "payload-example-form-builder-cms",
"name": "form-builder-example-cms",
"description": "The CMS that utilizes Payload's form builder plugin.",
"version": "1.0.0",
"main": "dist/server.js",
@@ -20,7 +20,7 @@
"@payloadcms/plugin-seo": "^1.0.8",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest"
"payload": "^1.7.5"
},
"devDependencies": {
"@types/express": "^4.17.9",
@@ -30,4 +30,4 @@
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
{
"name": "payload-example-form-builder-website",
"name": "form-builder-example-website",
"version": "0.1.0",
"private": true,
"scripts": {

View File

@@ -20,7 +20,7 @@
"dependencies": {
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest"
"payload": "^1.8.2"
},
"devDependencies": {
"@payloadcms/eslint-config": "^0.0.1",
@@ -43,4 +43,4 @@
"ts-node": "^9.1.1",
"typescript": "^4.8.4"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
"dependencies": {
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest"
"payload": "^1.11.0"
},
"devDependencies": {
"@payloadcms/eslint-config": "^0.0.2",
@@ -43,4 +43,4 @@
"ts-node": "^9.1.1",
"typescript": "^4.8.4"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
{
"name": "payload-example-nextjs-preview-app",
"name": "payload-nextjs-preview-example",
"version": "0.1.0",
"private": true,
"scripts": {

View File

@@ -1,5 +1,5 @@
{
"name": "payload-example-nextjs-preview-pages",
"name": "payload-nextjs-preview-example",
"version": "0.1.0",
"private": true,
"scripts": {

View File

@@ -1,5 +1,5 @@
{
"name": "payload-example-redirects-cms",
"name": "redirects-example-cms",
"description": "The CMS is used to demonstrate the redirects feature.",
"version": "1.0.0",
"main": "dist/server.js",
@@ -20,7 +20,7 @@
"@payloadcms/plugin-redirects": "^1.0.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest"
"payload": "^1.7.5"
},
"devDependencies": {
"@payloadcms/eslint-config": "^0.0.1",
@@ -43,4 +43,4 @@
"ts-node": "^9.1.1",
"typescript": "^4.8.4"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
{
"name": "payload-example-nextjs-redirects-pages",
"name": "nextjs-redirects-example",
"version": "0.1.0",
"private": true,
"scripts": {

View File

@@ -1,5 +1,5 @@
{
"name": "payload-example-virtual-fields-cms",
"name": "virtual-fields",
"version": "1.0.0",
"main": "dist/server.js",
"license": "MIT",
@@ -16,7 +16,7 @@
"dependencies": {
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest"
"payload": "^1.7.5"
},
"devDependencies": {
"@types/express": "^4.17.9",
@@ -26,4 +26,4 @@
"ts-node": "^9.1.1",
"typescript": "^4.8.4"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
{
"name": "payload-example-whitelabel-cms",
"name": "whitelabel-example-cms",
"version": "1.0.0",
"main": "dist/server.js",
"license": "MIT",
@@ -16,7 +16,7 @@
"dependencies": {
"dotenv": "^8.2.0",
"express": "^4.17.1",
"payload": "latest"
"payload": "^1.7.5"
},
"devDependencies": {
"@types/express": "^4.17.9",

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "payload",
"version": "1.11.8",
"version": "1.11.5",
"description": "Node, React and MongoDB Headless CMS and Application Framework",
"license": "MIT",
"engines": {
@@ -96,7 +96,6 @@
"compression": "^1.7.4",
"conf": "^10.2.0",
"connect-history-api-fallback": "^1.6.0",
"console-table-printer": "^2.11.2",
"css-loader": "^5.2.7",
"css-minimizer-webpack-plugin": "^5.0.0",
"dataloader": "^2.1.0",

View File

@@ -19,7 +19,6 @@ export const ArrayAction: React.FC<Props> = ({
addRow,
duplicateRow,
removeRow,
hasMaxRows,
}) => {
const { t } = useTranslation('general');
return (
@@ -57,32 +56,28 @@ export const ArrayAction: React.FC<Props> = ({
{t('moveDown')}
</button>
)}
{!hasMaxRows && (
<React.Fragment>
<button
className={`${baseClass}__action ${baseClass}__add`}
type="button"
onClick={() => {
addRow(index);
close();
}}
>
<Plus />
{t('addBelow')}
</button>
<button
className={`${baseClass}__action ${baseClass}__duplicate`}
type="button"
onClick={() => {
duplicateRow(index);
close();
}}
>
<Copy />
{t('duplicate')}
</button>
</React.Fragment>
)}
<button
className={`${baseClass}__action ${baseClass}__add`}
type="button"
onClick={() => {
addRow(index);
close();
}}
>
<Plus />
{t('addBelow')}
</button>
<button
className={`${baseClass}__action ${baseClass}__duplicate`}
type="button"
onClick={() => {
duplicateRow(index);
close();
}}
>
<Copy />
{t('duplicate')}
</button>
<button
className={`${baseClass}__action ${baseClass}__remove`}
type="button"

View File

@@ -5,5 +5,4 @@ export type Props = {
moveRow: (from: number, to: number) => void
index: number
rowCount: number
hasMaxRows: boolean
}

View File

@@ -6,6 +6,11 @@ import { FormField, FieldAction, Fields } from './types';
import deepCopyObject from '../../../../utilities/deepCopyObject';
import { flattenRows, separateRows } from './rows';
function splitPathByArrayFields(str) {
const regex = /\.(\d+)\./g;
return str.split(regex).filter(Boolean);
}
export function fieldReducer(state: Fields, action: FieldAction): Fields {
switch (action.type) {
case 'REPLACE_STATE': {

View File

@@ -29,7 +29,6 @@ type ArrayRowProps = UseDraggableSortableReturn & Pick<Props, 'fields' | 'path'
row: Row
CustomRowLabel?: RowLabelType
readOnly?: boolean
hasMaxRows?: boolean
}
export const ArrayRow: React.FC<ArrayRowProps> = ({
path: parentPath,
@@ -52,7 +51,6 @@ export const ArrayRow: React.FC<ArrayRowProps> = ({
permissions,
CustomRowLabel,
fields,
hasMaxRows,
}) => {
const path = `${parentPath}.${rowIndex}`;
const { i18n } = useTranslation();
@@ -110,7 +108,6 @@ export const ArrayRow: React.FC<ArrayRowProps> = ({
duplicateRow={duplicateRow}
rowCount={rowCount}
index={rowIndex}
hasMaxRows={hasMaxRows}
/>
) : undefined}
>

View File

@@ -95,7 +95,7 @@ const ArrayFieldType: React.FC<Props> = (props) => {
showError,
errorMessage,
value,
rows = [],
rows,
valid,
} = useField<number>({
path,
@@ -142,8 +142,8 @@ const ArrayFieldType: React.FC<Props> = (props) => {
dispatchFields({ type: 'SET_ROW_COLLAPSED', path, collapsed, rowID, setDocFieldPreferences });
}, [dispatchFields, path, setDocFieldPreferences]);
const hasMaxRows = maxRows && rows.length >= maxRows;
const fieldErrorCount = rows.reduce((total, row) => total + (row?.childErrorPaths?.size || 0), 0) + (valid ? 0 : 1);
const hasMaxRows = maxRows && rows?.length >= maxRows;
const fieldErrorCount = (rows || []).reduce((total, row) => total + (row?.childErrorPaths?.size || 0), 0) + (valid ? 0 : 1);
const fieldHasErrors = submitted && fieldErrorCount > 0;
const classes = [
@@ -153,6 +153,8 @@ const ArrayFieldType: React.FC<Props> = (props) => {
fieldHasErrors ? `${baseClass}--has-error` : `${baseClass}--has-no-error`,
].filter(Boolean).join(' ');
if (!rows) return null;
return (
<div
id={`field-${path.replace(/\./gi, '__')}`}
@@ -216,7 +218,6 @@ const ArrayFieldType: React.FC<Props> = (props) => {
<DraggableSortable
ids={rows.map((row) => row.id)}
onDragEnd={({ moveFromIndex, moveToIndex }) => moveRow(moveFromIndex, moveToIndex)}
className={`${baseClass}__draggable-rows`}
>
{rows.length > 0 && rows.map((row, i) => (
<DraggableSortableItem
@@ -243,7 +244,6 @@ const ArrayFieldType: React.FC<Props> = (props) => {
rowIndex={i}
indexPath={indexPath}
labels={labels}
hasMaxRows={hasMaxRows}
/>
)}
</DraggableSortableItem>

View File

@@ -28,7 +28,6 @@ type BlockFieldProps = UseDraggableSortableReturn & Pick<Props, 'path' | 'labels
readOnly: boolean
rowCount: number
blockToRender: Block
hasMaxRows?: boolean
}
export const BlockRow: React.FC<BlockFieldProps> = ({
path: parentPath,
@@ -51,7 +50,6 @@ export const BlockRow: React.FC<BlockFieldProps> = ({
permissions,
blocks,
blockToRender,
hasMaxRows,
}) => {
const path = `${parentPath}.${rowIndex}`;
const { i18n } = useTranslation();
@@ -119,7 +117,6 @@ export const BlockRow: React.FC<BlockFieldProps> = ({
blockType={row.blockType}
blocks={blocks}
labels={labels}
hasMaxRows={hasMaxRows}
/>
) : undefined}
>

View File

@@ -15,7 +15,6 @@ export const RowActions: React.FC<{
rowIndex: number
rowCount: number
blockType: string
hasMaxRows?: boolean
}> = (props) => {
const {
addRow,
@@ -27,7 +26,6 @@ export const RowActions: React.FC<{
rowIndex,
rowCount,
blockType,
hasMaxRows,
} = props;
const { openModal, closeModal } = useModal();
@@ -56,7 +54,6 @@ export const RowActions: React.FC<{
moveRow={moveRow}
removeRow={removeRow}
index={rowIndex}
hasMaxRows={hasMaxRows}
/>
</React.Fragment>
);

View File

@@ -80,7 +80,6 @@ const BlocksField: React.FC<Props> = (props) => {
return true;
})();
const memoizedValidate = useCallback((value, options) => {
// alternative locales can be null
if (!editingDefaultLocale && value === null) {
@@ -89,11 +88,12 @@ const BlocksField: React.FC<Props> = (props) => {
return validate(value, { ...options, minRows, maxRows, required });
}, [maxRows, minRows, required, validate, editingDefaultLocale]);
const {
showError,
errorMessage,
value,
rows = [],
rows,
valid,
} = useField<number>({
path,
@@ -141,7 +141,7 @@ const BlocksField: React.FC<Props> = (props) => {
dispatchFields({ type: 'SET_ROW_COLLAPSED', path, collapsed, rowID, setDocFieldPreferences });
}, [dispatchFields, path, setDocFieldPreferences]);
const hasMaxRows = maxRows && rows.length >= maxRows;
const hasMaxRows = maxRows && rows?.length >= maxRows;
const fieldErrorCount = rows.reduce((total, row) => total + (row?.childErrorPaths?.size || 0), 0);
const fieldHasErrors = submitted && fieldErrorCount + (valid ? 0 : 1) > 0;
@@ -153,6 +153,8 @@ const BlocksField: React.FC<Props> = (props) => {
fieldHasErrors ? `${baseClass}--has-error` : `${baseClass}--has-no-error`,
].filter(Boolean).join(' ');
if (!rows) return null;
return (
<div
id={`field-${path.replace(/\./gi, '__')}`}
@@ -245,7 +247,6 @@ const BlocksField: React.FC<Props> = (props) => {
rowCount={rows.length}
labels={labels}
path={path}
hasMaxRows={hasMaxRows}
/>
)}
</DraggableSortableItem>

View File

@@ -1,12 +1,12 @@
import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useAuth } from '../../utilities/Auth';
import { useFormProcessing, useFormSubmitted, useForm, useFormFields } from '../Form/context';
import { useFormProcessing, useFormSubmitted, useFormModified, useForm, useFormFields } from '../Form/context';
import { Options, FieldType } from './types';
import { useDocumentInfo } from '../../utilities/DocumentInfo';
import { useOperation } from '../../utilities/OperationProvider';
import useThrottledEffect from '../../../hooks/useThrottledEffect';
import type { UPDATE } from '../Form/types';
import { UPDATE } from '../Form/types';
/**
* Get and set the value of a form field.
@@ -24,6 +24,7 @@ const useField = <T, >(options: Options): FieldType<T> => {
const submitted = useFormSubmitted();
const processing = useFormProcessing();
const modified = useFormModified();
const { user } = useAuth();
const { id } = useDocumentInfo();
const operation = useOperation();
@@ -43,7 +44,7 @@ const useField = <T, >(options: Options): FieldType<T> => {
const setValue = useCallback((e, disableModifyingForm = false) => {
const val = (e && e.target) ? e.target.value : e;
if (!disableModifyingForm) {
if (!modified && !disableModifyingForm) {
if (typeof setModified === 'function') {
// Update modified state after field value comes back
// to avoid cursor jump caused by state value / DOM mismatch
@@ -61,6 +62,7 @@ const useField = <T, >(options: Options): FieldType<T> => {
});
}, [
setModified,
modified,
path,
dispatchField,
disableFormData,

View File

@@ -22,23 +22,21 @@ const useThumbnail = (collection: SanitizedCollectionConfig, doc: Record<string,
const { serverURL } = useConfig();
if (typeof adminThumbnail === 'function') {
const thumbnailURL = adminThumbnail({ doc });
if (!thumbnailURL) return false;
if (absoluteURLPattern.test(thumbnailURL) || base64Pattern.test(thumbnailURL)) {
return thumbnailURL;
}
return `${serverURL}${thumbnailURL}`;
}
if (isImage(mimeType as string)) {
if (typeof adminThumbnail === 'undefined' && url) {
return url as string;
}
if (typeof adminThumbnail === 'function') {
const thumbnailURL = adminThumbnail({ doc });
if (absoluteURLPattern.test(thumbnailURL) || base64Pattern.test(thumbnailURL)) {
return thumbnailURL;
}
return `${serverURL}${thumbnailURL}`;
}
if (sizes?.[adminThumbnail]?.url) {
return sizes[adminThumbnail].url;
}

View File

@@ -34,7 +34,6 @@ async function forgotPassword(incomingArgs: Arguments): Promise<string | null> {
args = (await hook({
args,
operation: 'forgotPassword',
context: args.req.context,
})) || args;
}, Promise.resolve());
@@ -123,7 +122,7 @@ async function forgotPassword(incomingArgs: Arguments): Promise<string | null> {
await collectionConfig.hooks.afterForgotPassword.reduce(async (priorHook, hook) => {
await priorHook;
await hook({ args, context: req.context });
await hook({ args });
}, Promise.resolve());
return token;

View File

@@ -5,7 +5,6 @@ import { Payload } from '../../../payload';
import { getDataLoader } from '../../../collections/dataloader';
import i18n from '../../../translations/init';
import { APIError } from '../../../errors';
import { setRequestContext } from '../../../express/setRequestContext';
export type Options<T extends keyof GeneratedTypes['collections']> = {
collection: T
@@ -28,7 +27,6 @@ async function localForgotPassword<T extends keyof GeneratedTypes['collections']
disableEmail,
req = {} as PayloadRequest,
} = options;
setRequestContext(options.req);
const collection = payload.collections[collectionSlug];

View File

@@ -6,7 +6,6 @@ import { Payload } from '../../../payload';
import { getDataLoader } from '../../../collections/dataloader';
import i18n from '../../../translations/init';
import { APIError } from '../../../errors';
import { setRequestContext } from '../../../express/setRequestContext';
export type Options<TSlug extends keyof GeneratedTypes['collections']> = {
collection: TSlug
@@ -38,8 +37,6 @@ async function localLogin<TSlug extends keyof GeneratedTypes['collections']>(
overrideAccess = true,
showHiddenFields,
} = options;
setRequestContext(options.req);
const collection = payload.collections[collectionSlug];

View File

@@ -5,7 +5,6 @@ import { PayloadRequest } from '../../../express/types';
import { getDataLoader } from '../../../collections/dataloader';
import i18n from '../../../translations/init';
import { APIError } from '../../../errors';
import { setRequestContext } from '../../../express/setRequestContext';
export type Options<T extends keyof GeneratedTypes['collections']> = {
collection: T
@@ -27,7 +26,6 @@ async function localResetPassword<T extends keyof GeneratedTypes['collections']>
overrideAccess,
req = {} as PayloadRequest,
} = options;
setRequestContext(options.req);
const collection = payload.collections[collectionSlug];

View File

@@ -5,7 +5,6 @@ import unlock from '../unlock';
import { getDataLoader } from '../../../collections/dataloader';
import i18n from '../../../translations/init';
import { APIError } from '../../../errors';
import { setRequestContext } from '../../../express/setRequestContext';
export type Options<T extends keyof GeneratedTypes['collections']> = {
collection: T
@@ -26,7 +25,6 @@ async function localUnlock<T extends keyof GeneratedTypes['collections']>(
overrideAccess = true,
req = {} as PayloadRequest,
} = options;
setRequestContext(options.req);
const collection = payload.collections[collectionSlug];

View File

@@ -48,7 +48,6 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
args = (await hook({
args,
operation: 'login',
context: args.req.context,
})) || args;
}, Promise.resolve());
@@ -134,7 +133,6 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
user = (await hook({
user,
req: args.req,
context: req.context,
})) || user;
}, Promise.resolve());
@@ -174,7 +172,6 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
user,
req: args.req,
token,
context: req.context,
}) || user;
}, Promise.resolve());
@@ -189,7 +186,6 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
overrideAccess,
req,
showHiddenFields,
context: req.context,
});
// /////////////////////////////////////
@@ -202,7 +198,6 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
user = await hook({
req,
doc: user,
context: req.context,
}) || user;
}, Promise.resolve());

View File

@@ -46,7 +46,6 @@ async function logout(incomingArgs: Arguments): Promise<string> {
args = (await hook({
req,
res,
context: req.context,
})) || args;
}, Promise.resolve());

View File

@@ -60,7 +60,6 @@ async function me({
response = await hook({
req,
response,
context: req.context,
}) || response;
}, Promise.resolve());

View File

@@ -34,7 +34,6 @@ async function refresh(incomingArgs: Arguments): Promise<Result> {
args = (await hook({
args,
operation: 'refresh',
context: args.req.context,
})) || args;
}, Promise.resolve());
@@ -115,7 +114,6 @@ async function refresh(incomingArgs: Arguments): Promise<Result> {
res: args.res,
exp,
token: refreshedToken,
context: args.req.context,
})) || response;
}, Promise.resolve());

View File

@@ -19,12 +19,12 @@ export const getDevConfig = (payloadConfig: SanitizedConfig): Configuration => {
entry: {
...baseConfig.entry,
main: [
`webpack-hot-middleware/client?path=${payloadConfig.routes.admin}/__webpack_hmr`,
require.resolve('webpack-hot-middleware/client'),
...(baseConfig.entry.main as string[]),
],
},
output: {
publicPath: `${payloadConfig.routes.admin}/`,
publicPath: payloadConfig.routes.admin,
path: '/',
filename: '[name].js',
},

View File

@@ -11,14 +11,14 @@ const router = express.Router();
type DevAdminType = (options: { payload: Payload }) => Promise<PayloadHandler>;
export const devAdmin: DevAdminType = async ({ payload }) => {
router.use(history());
payload.express.use(payload.config.routes.admin, history());
try {
const webpackConfig = getDevConfig(payload.config);
const compiler = webpack(webpackConfig);
router.use(webpackDevMiddleware(compiler, {
publicPath: '/',
publicPath: webpackConfig.output.publicPath as string,
}));
router.use(webpackHotMiddleware(compiler));

View File

@@ -10,7 +10,7 @@ import getBaseUploadFields from '../../uploads/getBaseFields';
import { formatLabels } from '../../utilities/formatLabels';
import { authDefaults, defaults } from './defaults';
import { Config } from '../../config/types';
import baseVersionFields from '../../versions/baseFields';
import getBaseVersionFields from '../../versions/baseFields';
import TimestampsRequired from '../../errors/TimestampsRequired';
import mergeBaseFields from '../../fields/mergeBaseFields';
import { extractTranslations } from '../../translations/extractTranslations';
@@ -87,7 +87,7 @@ const sanitizeCollection = (config: Config, collection: CollectionConfig): Sanit
};
}
sanitized.fields = mergeBaseFields(sanitized.fields, baseVersionFields);
sanitized.fields = mergeBaseFields(sanitized.fields, getBaseVersionFields(config));
}
}

View File

@@ -6,7 +6,7 @@ import { Response } from 'express';
import { Config as GeneratedTypes } from 'payload/generated-types';
import { Access, Endpoint, EntityDescription, GeneratePreviewURL } from '../../config/types';
import { Field } from '../../fields/config/types';
import { PayloadRequest, RequestContext } from '../../express/types';
import { PayloadRequest } from '../../express/types';
import { Auth, IncomingAuthType, User } from '../../auth/types';
import { IncomingUploadType, Upload } from '../../uploads/types';
import { IncomingCollectionVersions, SanitizedCollectionVersions } from '../../versions/types';
@@ -49,7 +49,6 @@ export type BeforeOperationHook = (args: {
* Hook operation being performed
*/
operation: HookOperationType;
context: RequestContext;
}) => any;
export type BeforeValidateHook<T extends TypeWithID = any> = (args: {
@@ -65,7 +64,6 @@ export type BeforeValidateHook<T extends TypeWithID = any> = (args: {
* `undefined` on 'create' operation
*/
originalDoc?: T;
context: RequestContext;
}) => any;
export type BeforeChangeHook<T extends TypeWithID = any> = (args: {
@@ -81,7 +79,6 @@ export type BeforeChangeHook<T extends TypeWithID = any> = (args: {
* `undefined` on 'create' operation
*/
originalDoc?: T;
context: RequestContext;
}) => any;
export type AfterChangeHook<T extends TypeWithID = any> = (args: {
@@ -92,62 +89,53 @@ export type AfterChangeHook<T extends TypeWithID = any> = (args: {
* Hook operation being performed
*/
operation: CreateOrUpdateOperation;
context: RequestContext;
}) => any;
export type BeforeReadHook<T extends TypeWithID = any> = (args: {
doc: T;
req: PayloadRequest;
query: { [key: string]: any };
context: RequestContext;
}) => any;
export type AfterReadHook<T extends TypeWithID = any> = (args: {
doc: T;
req: PayloadRequest;
query?: { [key: string]: any };
findMany?: boolean;
context: RequestContext;
findMany?: boolean
}) => any;
export type BeforeDeleteHook = (args: {
req: PayloadRequest;
id: string | number;
context: RequestContext;
}) => any;
export type AfterDeleteHook<T extends TypeWithID = any> = (args: {
doc: T;
req: PayloadRequest;
id: string | number;
context: RequestContext;
}) => any;
export type AfterErrorHook = (err: Error, res: unknown, context: RequestContext) => { response: any, status: number } | void;
export type AfterErrorHook = (err: Error, res: unknown) => { response: any, status: number } | void;
export type BeforeLoginHook<T extends TypeWithID = any> = (args: {
req: PayloadRequest;
user: T;
context: RequestContext;
user: T
}) => any;
export type AfterLoginHook<T extends TypeWithID = any> = (args: {
req: PayloadRequest;
user: T;
token: string;
context: RequestContext;
}) => any;
export type AfterLogoutHook<T extends TypeWithID = any> = (args: {
req: PayloadRequest;
res: Response;
context: RequestContext;
}) => any;
export type AfterMeHook<T extends TypeWithID = any> = (args: {
req: PayloadRequest;
response: unknown;
context: RequestContext;
}) => any;
export type AfterRefreshHook<T extends TypeWithID = any> = (args: {
@@ -155,12 +143,10 @@ export type AfterRefreshHook<T extends TypeWithID = any> = (args: {
res: Response;
token: string;
exp: number;
context: RequestContext;
}) => any;
export type AfterForgotPasswordHook = (args: {
args?: any;
context: RequestContext;
}) => any;
type BeforeDuplicateArgs<T> = {
@@ -276,7 +262,7 @@ export type CollectionConfig = {
graphQL?: {
singularName?: string
pluralName?: string
} | false
}
/**
* Options used in typescript generation
*/

View File

@@ -41,9 +41,6 @@ function initCollectionsGraphQL(payload: Payload): void {
versions,
},
} = collection;
if (!graphQL) return;
const { fields } = config;
let singularName;

View File

@@ -54,7 +54,6 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
args = (await hook({
args,
operation: 'create',
context: args.req.context,
})) || args;
}, Promise.resolve());
@@ -131,7 +130,6 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
operation: 'create',
overrideAccess,
req,
context: req.context,
});
// /////////////////////////////////////
@@ -145,7 +143,6 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
data,
req,
operation: 'create',
context: req.context,
})) || data;
}, Promise.resolve());
@@ -168,7 +165,6 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
data,
req,
operation: 'create',
context: req.context,
})) || data;
}, Promise.resolve());
@@ -184,7 +180,6 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
operation: 'create',
req,
skipValidation: shouldSaveDraft,
context: req.context,
});
// /////////////////////////////////////
@@ -208,7 +203,7 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
doc: resultWithLocales,
payload: req.payload,
password: data.password as string,
});
})
} else {
try {
doc = await Model.create(resultWithLocales);
@@ -271,7 +266,6 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
overrideAccess,
req,
showHiddenFields,
context: req.context,
});
// /////////////////////////////////////
@@ -284,7 +278,6 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
result = await hook({
req,
doc: result,
context: req.context,
}) || result;
}, Promise.resolve());
@@ -299,7 +292,6 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
entityConfig: collectionConfig,
operation: 'create',
req,
context: req.context,
});
// /////////////////////////////////////
@@ -314,7 +306,6 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
previousDoc: {},
req: args.req,
operation: 'create',
context: req.context,
}) || result;
}, Promise.resolve());

View File

@@ -41,7 +41,6 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
args = (await hook({
args,
operation: 'delete',
context: args.req.context,
})) || args;
}, Promise.resolve());
@@ -117,7 +116,6 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
return hook({
req,
id,
context: req.context,
});
}, Promise.resolve());
@@ -152,7 +150,6 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
overrideAccess,
req,
showHiddenFields,
context: req.context,
});
// /////////////////////////////////////
@@ -165,7 +162,6 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
result = await hook({
req,
doc: result || doc,
context: req.context,
}) || result;
}, Promise.resolve());
@@ -180,7 +176,6 @@ async function deleteOperation<TSlug extends keyof GeneratedTypes['collections']
req,
id,
doc: result,
context: req.context,
}) || result;
}, Promise.resolve());

View File

@@ -32,7 +32,6 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(inc
args = (await hook({
args,
operation: 'delete',
context: args.req.context,
})) || args;
}, Promise.resolve());
@@ -73,7 +72,6 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(inc
return hook({
req,
id,
context: req.context,
});
}, Promise.resolve());
@@ -147,7 +145,6 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(inc
overrideAccess,
req,
showHiddenFields,
context: req.context,
});
// /////////////////////////////////////
@@ -160,7 +157,6 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(inc
result = await hook({
req,
doc: result,
context: req.context,
}) || result;
}, Promise.resolve());
@@ -171,7 +167,7 @@ async function deleteByID<TSlug extends keyof GeneratedTypes['collections']>(inc
await collectionConfig.hooks.afterDelete.reduce(async (priorHook, hook) => {
await priorHook;
result = await hook({ req, id, doc: result, context: req.context }) || result;
result = await hook({ req, id, doc: result }) || result;
}, Promise.resolve());
// /////////////////////////////////////

View File

@@ -41,7 +41,6 @@ async function find<T extends TypeWithID & Record<string, unknown>>(
args = (await hook({
args,
operation: 'read',
context: args.req.context,
})) || args;
}, Promise.resolve());
@@ -181,7 +180,7 @@ async function find<T extends TypeWithID & Record<string, unknown>>(
await collectionConfig.hooks.beforeRead.reduce(async (priorHook, hook) => {
await priorHook;
docRef = await hook({ req, query, doc: docRef, context: req.context }) || docRef;
docRef = await hook({ req, query, doc: docRef }) || docRef;
}, Promise.resolve());
return docRef;
@@ -203,7 +202,6 @@ async function find<T extends TypeWithID & Record<string, unknown>>(
req,
showHiddenFields,
findMany: true,
context: req.context,
}))),
};
@@ -219,7 +217,7 @@ async function find<T extends TypeWithID & Record<string, unknown>>(
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
await priorHook;
docRef = await hook({ req, query, doc: docRef, findMany: true, context: req.context }) || doc;
docRef = await hook({ req, query, doc: docRef, findMany: true }) || doc;
}, Promise.resolve());
return docRef;

View File

@@ -35,7 +35,6 @@ async function findByID<T extends TypeWithID>(
args = (await hook({
args,
operation: 'read',
context: args.req.context,
})) || args;
}, Promise.resolve());
@@ -139,7 +138,6 @@ async function findByID<T extends TypeWithID>(
req,
query,
doc: result,
context: req.context,
}) || result;
}, Promise.resolve());
@@ -155,7 +153,6 @@ async function findByID<T extends TypeWithID>(
overrideAccess,
req,
showHiddenFields,
context: req.context,
});
// /////////////////////////////////////
@@ -169,7 +166,6 @@ async function findByID<T extends TypeWithID>(
req,
query,
doc: result,
context: req.context,
}) || result;
}, Promise.resolve());

View File

@@ -98,7 +98,6 @@ async function findVersionByID<T extends TypeWithVersion<T> = any>(args: Argumen
req,
query,
doc: result.version,
context: req.context,
}) || result.version;
}, Promise.resolve());
@@ -114,7 +113,6 @@ async function findVersionByID<T extends TypeWithVersion<T> = any>(args: Argumen
overrideAccess,
req,
showHiddenFields,
context: req.context,
});
// /////////////////////////////////////
@@ -128,7 +126,6 @@ async function findVersionByID<T extends TypeWithVersion<T> = any>(args: Argumen
req,
query,
doc: result.version,
context: req.context,
}) || result.version;
}, Promise.resolve());

View File

@@ -110,7 +110,7 @@ async function findVersions<T extends TypeWithVersion<T>>(
await collectionConfig.hooks.beforeRead.reduce(async (priorHook, hook) => {
await priorHook;
docRef.version = await hook({ req, query, doc: docRef.version, context: req.context }) || docRef.version;
docRef.version = await hook({ req, query, doc: docRef.version }) || docRef.version;
}, Promise.resolve());
return docRef;
@@ -133,7 +133,6 @@ async function findVersions<T extends TypeWithVersion<T>>(
req,
showHiddenFields,
findMany: true,
context: req.context,
}),
}))),
};
@@ -150,7 +149,7 @@ async function findVersions<T extends TypeWithVersion<T>>(
await collectionConfig.hooks.afterRead.reduce(async (priorHook, hook) => {
await priorHook;
docRef.version = await hook({ req, query, doc: doc.version, findMany: true, context: req.context }) || doc.version;
docRef.version = await hook({ req, query, doc: doc.version, findMany: true }) || doc.version;
}, Promise.resolve());
return docRef;

View File

@@ -2,7 +2,7 @@ import { Config as GeneratedTypes } from 'payload/generated-types';
import { UploadedFile } from 'express-fileupload';
import { MarkOptional } from 'ts-essentials';
import { Payload } from '../../../payload';
import { PayloadRequest, RequestContext } from '../../../express/types';
import { PayloadRequest } from '../../../express/types';
import { Document } from '../../../types';
import getFileByPath from '../../../uploads/getFileByPath';
import create from '../create';
@@ -10,7 +10,6 @@ import { getDataLoader } from '../../dataloader';
import { File } from '../../../uploads/types';
import i18n from '../../../translations/init';
import { APIError } from '../../../errors';
import { setRequestContext } from '../../../express/setRequestContext';
export type Options<TSlug extends keyof GeneratedTypes['collections']> = {
collection: TSlug
@@ -27,10 +26,6 @@ export type Options<TSlug extends keyof GeneratedTypes['collections']> = {
overwriteExistingFiles?: boolean
req?: PayloadRequest
draft?: boolean
/**
* context, which will then be passed to req.context, which can be read by hooks
*/
context?: RequestContext
}
export default async function createLocal<TSlug extends keyof GeneratedTypes['collections']>(
@@ -52,9 +47,7 @@ export default async function createLocal<TSlug extends keyof GeneratedTypes['co
overwriteExistingFiles = false,
req = {} as PayloadRequest,
draft,
context,
} = options;
setRequestContext(req, context);
const collection = payload.collections[collectionSlug];
const defaultLocale = payload?.config?.localization ? payload?.config?.localization?.defaultLocale : null;

View File

@@ -1,6 +1,6 @@
import { Config as GeneratedTypes } from '../../../generated-types';
import { Document, Where } from '../../../types';
import { PayloadRequest, RequestContext } from '../../../express/types';
import { PayloadRequest } from '../../../express/types';
import { Payload } from '../../../payload';
import deleteOperation from '../delete';
import deleteByID from '../deleteByID';
@@ -8,10 +8,8 @@ import { getDataLoader } from '../../dataloader';
import i18n from '../../../translations/init';
import { APIError } from '../../../errors';
import { BulkOperationResult } from '../../config/types';
import { setRequestContext } from '../../../express/setRequestContext';
export type BaseOptions<T extends keyof GeneratedTypes['collections']> = {
req?: PayloadRequest,
collection: T
depth?: number
locale?: string
@@ -19,10 +17,6 @@ export type BaseOptions<T extends keyof GeneratedTypes['collections']> = {
user?: Document
overrideAccess?: boolean
showHiddenFields?: boolean
/**
* context, which will then be passed to req.context, which can be read by hooks
*/
context?: RequestContext
}
export type ByIDOptions<T extends keyof GeneratedTypes['collections']> = BaseOptions<T> & {
@@ -51,7 +45,6 @@ async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(pa
user,
overrideAccess = true,
showHiddenFields,
context,
} = options;
const collection = payload.collections[collectionSlug];
@@ -70,7 +63,6 @@ async function deleteLocal<TSlug extends keyof GeneratedTypes['collections']>(pa
payload,
i18n: i18n(payload.config.i18n),
} as PayloadRequest;
setRequestContext(req, context);
if (!req.t) req.t = req.i18n.t;
if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req);

View File

@@ -2,12 +2,11 @@ import { Config as GeneratedTypes } from 'payload/generated-types';
import { PaginatedDocs } from '../../../mongoose/types';
import { Document, Where } from '../../../types';
import { Payload } from '../../../payload';
import { PayloadRequest, RequestContext } from '../../../express/types';
import { PayloadRequest } from '../../../express/types';
import find from '../find';
import { getDataLoader } from '../../dataloader';
import i18n from '../../../translations/init';
import { APIError } from '../../../errors';
import { setRequestContext } from '../../../express/setRequestContext';
export type Options<T extends keyof GeneratedTypes['collections']> = {
collection: T
@@ -26,10 +25,6 @@ export type Options<T extends keyof GeneratedTypes['collections']> = {
where?: Where
draft?: boolean
req?: PayloadRequest
/**
* context, which will then be passed to req.context, which can be read by hooks
*/
context?: RequestContext
}
export default async function findLocal<T extends keyof GeneratedTypes['collections']>(
@@ -53,9 +48,7 @@ export default async function findLocal<T extends keyof GeneratedTypes['collecti
draft = false,
pagination = true,
req = {} as PayloadRequest,
context,
} = options;
setRequestContext(options.req, context);
const collection = payload.collections[collectionSlug];
const defaultLocale = payload?.config?.localization ? payload?.config?.localization?.defaultLocale : null;

View File

@@ -1,12 +1,11 @@
import { Config as GeneratedTypes } from 'payload/generated-types';
import { PayloadRequest, RequestContext } from '../../../express/types';
import { PayloadRequest } from '../../../express/types';
import { Document } from '../../../types';
import findByID from '../findByID';
import { Payload } from '../../../payload';
import { getDataLoader } from '../../dataloader';
import i18n from '../../../translations/init';
import { APIError } from '../../../errors';
import { setRequestContext } from '../../../express/setRequestContext';
export type Options<T extends keyof GeneratedTypes['collections']> = {
collection: T
@@ -21,10 +20,6 @@ export type Options<T extends keyof GeneratedTypes['collections']> = {
disableErrors?: boolean
req?: PayloadRequest
draft?: boolean
/**
* context, which will then be passed to req.context, which can be read by hooks
*/
context?: RequestContext,
}
export default async function findByIDLocal<T extends keyof GeneratedTypes['collections']>(
@@ -44,9 +39,7 @@ export default async function findByIDLocal<T extends keyof GeneratedTypes['coll
showHiddenFields,
req = {} as PayloadRequest,
draft = false,
context,
} = options;
setRequestContext(options.req, context);
const collection = payload.collections[collectionSlug];
const defaultLocale = payload?.config?.localization ? payload?.config?.localization?.defaultLocale : null;

View File

@@ -1,13 +1,12 @@
import { Config as GeneratedTypes } from 'payload/generated-types';
import { Payload } from '../../../payload';
import { Document } from '../../../types';
import { PayloadRequest, RequestContext } from '../../../express/types';
import { PayloadRequest } from '../../../express/types';
import { TypeWithVersion } from '../../../versions/types';
import findVersionByID from '../findVersionByID';
import { getDataLoader } from '../../dataloader';
import i18n from '../../../translations/init';
import { APIError } from '../../../errors';
import { setRequestContext } from '../../../express/setRequestContext';
export type Options<T extends keyof GeneratedTypes['collections']> = {
collection: T
@@ -20,11 +19,6 @@ export type Options<T extends keyof GeneratedTypes['collections']> = {
showHiddenFields?: boolean
disableErrors?: boolean
req?: PayloadRequest
draft?: boolean
/**
* context, which will then be passed to req.context, which can be read by hooks
*/
context?: RequestContext,
}
export default async function findVersionByIDLocal<T extends keyof GeneratedTypes['collections']>(
@@ -41,9 +35,7 @@ export default async function findVersionByIDLocal<T extends keyof GeneratedType
disableErrors = false,
showHiddenFields,
req = {} as PayloadRequest,
context,
} = options;
setRequestContext(options.req, context);
const collection = payload.collections[collectionSlug];
const defaultLocale = payload?.config?.localization ? payload?.config?.localization?.defaultLocale : null;

View File

@@ -3,12 +3,11 @@ import { Payload } from '../../../payload';
import { Document, Where } from '../../../types';
import { PaginatedDocs } from '../../../mongoose/types';
import { TypeWithVersion } from '../../../versions/types';
import { PayloadRequest, RequestContext } from '../../../express/types';
import { PayloadRequest } from '../../../express/types';
import findVersions from '../findVersions';
import { getDataLoader } from '../../dataloader';
import i18nInit from '../../../translations/init';
import { APIError } from '../../../errors';
import { setRequestContext } from '../../../express/setRequestContext';
export type Options<T extends keyof GeneratedTypes['collections']> = {
collection: T
@@ -22,11 +21,6 @@ export type Options<T extends keyof GeneratedTypes['collections']> = {
showHiddenFields?: boolean
sort?: string
where?: Where
draft?: boolean
/**
* context, which will then be passed to req.context, which can be read by hooks
*/
context?: RequestContext,
}
export default async function findVersionsLocal<T extends keyof GeneratedTypes['collections']>(
@@ -45,7 +39,6 @@ export default async function findVersionsLocal<T extends keyof GeneratedTypes['
overrideAccess = true,
showHiddenFields,
sort,
context,
} = options;
const collection = payload.collections[collectionSlug];
@@ -64,7 +57,6 @@ export default async function findVersionsLocal<T extends keyof GeneratedTypes['
payload,
i18n,
} as PayloadRequest;
setRequestContext(req, context);
if (!req.t) req.t = req.i18n.t;
if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req);

View File

@@ -1,12 +1,11 @@
import { Config as GeneratedTypes } from 'payload/generated-types';
import { Payload } from '../../../payload';
import { PayloadRequest, RequestContext } from '../../../express/types';
import { PayloadRequest } from '../../../express/types';
import { Document } from '../../../types';
import { getDataLoader } from '../../dataloader';
import restoreVersion from '../restoreVersion';
import i18nInit from '../../../translations/init';
import { APIError } from '../../../errors';
import { setRequestContext } from '../../../express/setRequestContext';
export type Options<T extends keyof GeneratedTypes['collections']> = {
collection: T
@@ -17,11 +16,6 @@ export type Options<T extends keyof GeneratedTypes['collections']> = {
user?: Document
overrideAccess?: boolean
showHiddenFields?: boolean
draft?: boolean
/**
* context, which will then be passed to req.context, which can be read by hooks
*/
context?: RequestContext,
}
export default async function restoreVersionLocal<T extends keyof GeneratedTypes['collections']>(
@@ -37,7 +31,6 @@ export default async function restoreVersionLocal<T extends keyof GeneratedTypes
user,
overrideAccess = true,
showHiddenFields,
context,
} = options;
const collection = payload.collections[collectionSlug];
@@ -56,7 +49,6 @@ export default async function restoreVersionLocal<T extends keyof GeneratedTypes
i18n,
t: i18n.t,
} as PayloadRequest;
setRequestContext(req, context);
if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req);

View File

@@ -4,14 +4,13 @@ import { Payload } from '../../../payload';
import { Document, Where } from '../../../types';
import getFileByPath from '../../../uploads/getFileByPath';
import update from '../update';
import { PayloadRequest, RequestContext } from '../../../express/types';
import { PayloadRequest } from '../../../express/types';
import { getDataLoader } from '../../dataloader';
import { File } from '../../../uploads/types';
import i18nInit from '../../../translations/init';
import { APIError } from '../../../errors';
import updateByID from '../updateByID';
import { BulkOperationResult } from '../../config/types';
import { setRequestContext } from '../../../express/setRequestContext';
export type BaseOptions<TSlug extends keyof GeneratedTypes['collections']> = {
collection: TSlug
@@ -27,10 +26,6 @@ export type BaseOptions<TSlug extends keyof GeneratedTypes['collections']> = {
overwriteExistingFiles?: boolean
draft?: boolean
autosave?: boolean
/**
* context, which will then be passed to req.context, which can be read by hooks
*/
context?: RequestContext
}
export type ByIDOptions<TSlug extends keyof GeneratedTypes['collections']> = BaseOptions<TSlug> & {
@@ -65,7 +60,6 @@ async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(pa
autosave,
id,
where,
context,
} = options;
const collection = payload.collections[collectionSlug];
@@ -88,7 +82,6 @@ async function updateLocal<TSlug extends keyof GeneratedTypes['collections']>(pa
file: file ?? await getFileByPath(filePath),
},
} as PayloadRequest;
setRequestContext(req, context);
if (!req.t) req.t = req.i18n.t;
if (!req.payloadDataLoader) req.payloadDataLoader = getDataLoader(req);

View File

@@ -143,7 +143,6 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
req,
overrideAccess,
showHiddenFields,
context: req.context,
});
// /////////////////////////////////////
@@ -156,7 +155,6 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
result = await hook({
req,
doc: result,
context: req.context,
}) || result;
}, Promise.resolve());
@@ -170,7 +168,6 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
previousDoc: prevDocWithLocales,
entityConfig: collectionConfig,
operation: 'update',
context: req.context,
req,
});
@@ -186,7 +183,6 @@ async function restoreVersion<T extends TypeWithID = any>(args: Arguments): Prom
req,
previousDoc: prevDocWithLocales,
operation: 'update',
context: req.context,
}) || result;
}, Promise.resolve());

View File

@@ -46,7 +46,6 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
args = (await hook({
args,
operation: 'update',
context: args.req.context,
})) || args;
}, Promise.resolve());
@@ -150,7 +149,6 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
req,
overrideAccess: true,
showHiddenFields: true,
context: req.context,
});
await deleteAssociatedFiles({ config, collectionConfig, files: filesToUpload, doc: docWithLocales, t, overrideDelete: false });
@@ -167,7 +165,6 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
operation: 'update',
overrideAccess,
req,
context: req.context,
});
// /////////////////////////////////////
@@ -182,7 +179,6 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
req,
operation: 'update',
originalDoc,
context: req.context,
})) || data;
}, Promise.resolve());
@@ -206,7 +202,6 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
req,
originalDoc,
operation: 'update',
context: req.context,
})) || data;
}, Promise.resolve());
@@ -223,7 +218,6 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
operation: 'update',
req,
skipValidation: shouldSaveDraft || data._status === 'draft',
context: req.context,
});
// /////////////////////////////////////
@@ -281,7 +275,6 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
req,
overrideAccess,
showHiddenFields,
context: req.context,
});
// /////////////////////////////////////
@@ -294,7 +287,6 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
result = await hook({
req,
doc: result,
context: req.context,
}) || result;
}, Promise.resolve());
@@ -309,7 +301,6 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
entityConfig: collectionConfig,
operation: 'update',
req,
context: req.context,
});
// /////////////////////////////////////
@@ -324,7 +315,6 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
previousDoc: originalDoc,
req,
operation: 'update',
context: req.context,
}) || result;
}, Promise.resolve());

View File

@@ -49,7 +49,6 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
args = (await hook({
args,
operation: 'update',
context: args.req.context,
})) || args;
}, Promise.resolve());
@@ -131,7 +130,6 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
req,
overrideAccess: true,
showHiddenFields: true,
context: req.context,
});
// /////////////////////////////////////
@@ -167,7 +165,6 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
operation: 'update',
overrideAccess,
req,
context: req.context,
});
// /////////////////////////////////////
@@ -182,7 +179,6 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
req,
operation: 'update',
originalDoc,
context: req.context,
})) || data;
}, Promise.resolve());
@@ -206,7 +202,6 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
req,
originalDoc,
operation: 'update',
context: req.context,
})) || data;
}, Promise.resolve());
@@ -223,19 +218,18 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
operation: 'update',
req,
skipValidation: shouldSaveDraft || data._status === 'draft',
context: req.context,
});
// /////////////////////////////////////
// Handle potential password update
// /////////////////////////////////////
const dataToUpdate: Record<string, unknown> = { ...result };
const dataToUpdate: Record<string, unknown> = { ...result }
if (shouldSavePassword && typeof password === 'string') {
const { hash, salt } = await generatePasswordSaltHash({ password });
dataToUpdate.salt = salt;
dataToUpdate.hash = hash;
const { hash, salt } = await generatePasswordSaltHash({ password })
dataToUpdate.salt = salt
dataToUpdate.hash = hash
delete data.password;
delete result.password;
}
@@ -293,7 +287,6 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
req,
overrideAccess,
showHiddenFields,
context: req.context,
});
// /////////////////////////////////////
@@ -306,7 +299,6 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
result = await hook({
req,
doc: result,
context: req.context,
}) || result;
}, Promise.resolve());
@@ -321,7 +313,6 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
entityConfig: collectionConfig,
operation: 'update',
req,
context: req.context,
});
// /////////////////////////////////////
@@ -336,7 +327,6 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
previousDoc: originalDoc,
req,
operation: 'update',
context: req.context,
}) || result;
}, Promise.resolve());

View File

@@ -47,7 +47,7 @@ export const sanitizeConfig = (config: Config): SanitizedConfig => {
checkDuplicateCollections(sanitizedConfig.collections);
if (sanitizedConfig.globals.length > 0) {
sanitizedConfig.globals = sanitizeGlobals(sanitizedConfig.collections, sanitizedConfig.globals);
sanitizedConfig.globals = sanitizeGlobals(config, sanitizedConfig.collections, sanitizedConfig.globals);
}
if (typeof sanitizedConfig.serverURL === 'undefined') {

View File

@@ -1,15 +0,0 @@
import { hasWhereAccessResult } from '../auth';
import { Where } from '../types';
export const combineQueries = (where: Where, access: Where | boolean): Where => {
if (!where && !access) return {};
const result: Where = {
and: [],
};
if (where) result.and.push(where);
if (hasWhereAccessResult(access)) result.and.push(access);
return result;
};

View File

@@ -1,44 +0,0 @@
/* eslint-disable no-param-reassign */
import { Configuration } from 'webpack';
import { MarkOptional } from 'ts-essentials';
import { transaction } from './transaction';
import { migrate } from './migrations/migrate';
import { migrateStatus } from './migrations/migrateStatus';
import { migrateDown } from './migrations/migrateDown';
import { migrateRefresh } from './migrations/migrateRefresh';
import { migrateReset } from './migrations/migrateReset';
import { DatabaseAdapter } from './types';
import { createMigration } from './migrations/createMigration';
export function createDatabaseAdapter<T extends DatabaseAdapter>(args: MarkOptional<T,
| 'transaction'
| 'migrate'
| 'createMigration'
| 'migrateStatus'
| 'migrateDown'
| 'migrateRefresh'
| 'migrateReset'
| 'migrateFresh'
| 'migrationDir'>): T {
// Need to implement DB Webpack config extensions here
if (args.webpack) {
const existingWebpackConfig = args.payload.config.admin.webpack ? args.payload.config.admin.webpack : (webpackConfig) => webpackConfig;
args.payload.config.admin.webpack = (webpackConfig: Configuration) => {
return args.webpack(
existingWebpackConfig(webpackConfig),
);
};
}
return {
transaction,
migrate,
createMigration,
migrateStatus,
migrateDown,
migrateRefresh,
migrateReset,
migrateFresh: async () => null,
...args,
} as T;
}

View File

@@ -1,23 +0,0 @@
import { Where, WhereField } from '../types';
// Take a where query and flatten it to all top-level operators
const flattenWhereToOperators = (query: Where): WhereField[] => Object.entries(query).reduce((flattenedConstraints, [key, val]) => {
if ((key === 'and' || key === 'or') && Array.isArray(val)) {
return [
...flattenedConstraints,
...val.reduce((subVals, subVal) => {
return [
...subVals,
...flattenWhereToOperators(subVal),
];
}, []),
];
}
return [
...flattenedConstraints,
val,
];
}, []);
export default flattenWhereToOperators;

View File

@@ -1,150 +0,0 @@
import { Field, fieldAffectsData } from '../fields/config/types';
import flattenFields from '../utilities/flattenTopLevelFields';
import { PathToQuery } from './queryValidation/types';
import { Payload } from '..';
export async function getLocalizedPaths({
payload,
locale,
collectionSlug,
globalSlug,
fields,
incomingPath,
overrideAccess = false,
}: {
payload: Payload
locale?: string
collectionSlug?: string
globalSlug?: string
fields: Field[]
incomingPath: string
overrideAccess?: boolean,
}): Promise<PathToQuery[]> {
const pathSegments = incomingPath.split('.');
const localizationConfig = payload.config.localization;
let paths: PathToQuery[] = [
{
path: '',
complete: false,
field: undefined,
fields: flattenFields(fields, false),
collectionSlug,
globalSlug,
invalid: false,
},
];
for (let i = 0; i < pathSegments.length; i += 1) {
const segment = pathSegments[i];
const lastIncompletePath = paths.find(({ complete }) => !complete);
if (lastIncompletePath) {
const { path } = lastIncompletePath;
let currentPath = path ? `${path}.${segment}` : segment;
const matchedField = lastIncompletePath.fields.find((field) => fieldAffectsData(field) && field.name === segment);
lastIncompletePath.field = matchedField;
if (currentPath === 'globalType' && globalSlug) {
lastIncompletePath.path = currentPath;
lastIncompletePath.complete = true;
lastIncompletePath.field = {
name: 'globalType',
type: 'text',
};
return paths;
}
if (matchedField) {
if ('hidden' in matchedField && matchedField.hidden && !overrideAccess) {
lastIncompletePath.invalid = true;
}
const nextSegment = pathSegments[i + 1];
const nextSegmentIsLocale = localizationConfig && localizationConfig.locales.includes(nextSegment);
if (nextSegmentIsLocale) {
// Skip the next iteration, because it's a locale
i += 1;
currentPath = `${currentPath}.${nextSegment}`;
} else if (localizationConfig && 'localized' in matchedField && matchedField.localized) {
currentPath = `${currentPath}.${locale}`;
}
switch (matchedField.type) {
case 'blocks':
case 'richText':
case 'json': {
const upcomingSegments = pathSegments.slice(i + 1).join('.');
lastIncompletePath.complete = true;
lastIncompletePath.path = upcomingSegments ? `${currentPath}.${upcomingSegments}` : currentPath;
return paths;
}
case 'relationship':
case 'upload': {
// If this is a polymorphic relation,
// We only support querying directly (no nested querying)
if (typeof matchedField.relationTo !== 'string') {
const lastSegmentIsValid = ['value', 'relationTo'].includes(pathSegments[pathSegments.length - 1]);
if (lastSegmentIsValid) {
lastIncompletePath.complete = true;
lastIncompletePath.path = pathSegments.join('.');
} else {
lastIncompletePath.invalid = true;
return paths;
}
} else {
lastIncompletePath.complete = true;
lastIncompletePath.path = currentPath;
const nestedPathToQuery = pathSegments.slice(nextSegmentIsLocale ? i + 2 : i + 1).join('.');
if (nestedPathToQuery) {
const relatedCollection = payload.collections[matchedField.relationTo as string].config;
// eslint-disable-next-line no-await-in-loop
const remainingPaths = await getLocalizedPaths({
payload,
locale,
globalSlug,
collectionSlug: relatedCollection.slug,
fields: relatedCollection.fields,
incomingPath: nestedPathToQuery,
});
paths = [
...paths,
...remainingPaths,
];
}
return paths;
}
break;
}
default: {
if ('fields' in lastIncompletePath.field) {
lastIncompletePath.fields = flattenFields(lastIncompletePath.field.fields, false);
}
if (i + 1 === pathSegments.length) lastIncompletePath.complete = true;
lastIncompletePath.path = currentPath;
}
}
} else {
lastIncompletePath.invalid = true;
lastIncompletePath.path = currentPath;
return paths;
}
}
}
return paths;
}

View File

@@ -1,27 +0,0 @@
/* eslint-disable no-restricted-syntax, no-await-in-loop */
import fs from 'fs';
import { migrationTemplate } from './migrationTemplate';
import { CreateMigration } from '../types';
export const createMigration: CreateMigration = async function createMigration({
payload,
migrationDir,
migrationName,
}) {
const dir = migrationDir || '.migrations'; // TODO: Verify path after linking
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
const [yyymmdd, hhmmss] = new Date().toISOString().split('T');
const formattedDate = yyymmdd.replace(/\D/g, '');
const formattedTime = hhmmss.split('.')[0].replace(/\D/g, '');
const timestamp = `${formattedDate}_${formattedTime}`;
const formattedName = migrationName.replace(/\W/g, '_');
const fileName = `${timestamp}_${formattedName}.ts`;
const filePath = `${dir}/${fileName}`;
fs.writeFileSync(filePath, migrationTemplate);
payload.logger.info({ msg: `Migration created at ${filePath}` });
};

View File

@@ -1,23 +0,0 @@
import { Payload } from '../..';
import { MigrationData } from '../types';
export async function getMigrations({
payload,
}: {
payload: Payload;
}): Promise<{ existingMigrations: MigrationData[], latestBatch: number }> {
const migrationQuery = await payload.find({
collection: 'payload-migrations',
sort: '-name',
});
const existingMigrations = migrationQuery.docs as unknown as MigrationData[];
// Get the highest batch number from existing migrations
const latestBatch = existingMigrations?.[0]?.batch || 0;
return {
existingMigrations,
latestBatch,
};
}

View File

@@ -1,48 +0,0 @@
/* eslint-disable no-restricted-syntax, no-await-in-loop */
import { DatabaseAdapter } from '../types';
import { getMigrations } from './getMigrations';
import { readMigrationFiles } from './readMigrationFiles';
import { PayloadRequest } from '../../express/types';
export async function migrate(this: DatabaseAdapter): Promise<void> {
const { payload } = this;
const migrationFiles = await readMigrationFiles({ payload });
const { existingMigrations, latestBatch } = await getMigrations({ payload });
const newBatch = latestBatch + 1;
// Execute 'up' function for each migration sequentially
for (const migration of migrationFiles) {
const existingMigration = existingMigrations.find((existing) => existing.name === migration.name);
// Run migration if not found in database
if (existingMigration) {
continue; // eslint-disable-line no-continue
}
const start = Date.now();
let transactionID;
try {
payload.logger.info({ msg: `Migrating: ${migration.name}` });
transactionID = await this.beginTransaction();
await migration.up({ payload });
payload.logger.info({ msg: `Migrated: ${migration.name} (${Date.now() - start}ms)` });
await payload.create({
collection: 'payload-migrations',
data: {
name: migration.name,
batch: newBatch,
},
req: {
transactionID,
} as PayloadRequest,
});
await this.commitTransaction(transactionID);
} catch (err: unknown) {
await this.rollbackTransaction(transactionID);
payload.logger.error({ msg: `Error running migration ${migration.name}`, err });
throw err;
}
}
}

View File

@@ -1,57 +0,0 @@
/* eslint-disable no-restricted-syntax, no-await-in-loop */
import { DatabaseAdapter } from '../types';
import { getMigrations } from './getMigrations';
import { readMigrationFiles } from './readMigrationFiles';
import { PayloadRequest } from '../../express/types';
export async function migrateDown(this: DatabaseAdapter): Promise<void> {
const { payload } = this;
const migrationFiles = await readMigrationFiles({ payload });
const {
existingMigrations,
latestBatch,
} = await getMigrations({
payload,
});
const migrationsToRollback = existingMigrations.filter((migration) => migration.batch === latestBatch);
if (!migrationsToRollback?.length) {
payload.logger.info({ msg: 'No migrations to rollback.' });
return;
}
payload.logger.info({ msg: `Rolling back batch ${latestBatch} consisting of ${migrationsToRollback.length} migrations.` });
for (const migration of migrationsToRollback) {
const migrationFile = migrationFiles.find((m) => m.name === migration.name);
if (!migrationFile) {
throw new Error(`Migration ${migration.name} not found locally.`);
}
const start = Date.now();
let transactionID;
try {
payload.logger.info({ msg: `Migrating: ${migrationFile.name}` });
transactionID = await this.beginTransaction();
await migrationFile.down({ payload });
payload.logger.info({ msg: `Migrated: ${migrationFile.name} (${Date.now() - start}ms)` });
await payload.delete({
collection: 'payload-migrations',
id: migration.id,
req: {
transactionID,
} as PayloadRequest,
});
await this.commitTransaction(transactionID);
} catch (err: unknown) {
await this.rollbackTransaction(transactionID);
payload.logger.error({
msg: `Error running migration ${migrationFile.name}`,
err,
});
throw err;
}
}
}

View File

@@ -1,48 +0,0 @@
/* eslint-disable no-restricted-syntax, no-await-in-loop */
import { DatabaseAdapter } from '../types';
import { readMigrationFiles } from './readMigrationFiles';
import { PayloadRequest } from '../../express/types';
/**
* Reset and re-run all migrations.
*/
export async function migrateRefresh(this: DatabaseAdapter) {
const { payload } = this;
const migrationFiles = await readMigrationFiles({ payload });
// Clear all migrations
await payload.delete({
collection: 'payload-migrations',
where: {}, // All migrations
});
let transactionID;
// Run all migrations
for (const migration of migrationFiles) {
payload.logger.info({ msg: `Migrating: ${migration.name}` });
try {
const start = Date.now();
transactionID = await this.beginTransaction();
await migration.up({ payload });
await payload.create({
collection: 'payload-migrations',
data: {
name: migration.name,
executed: true,
},
req: {
transactionID,
} as PayloadRequest,
});
await this.commitTransaction(transactionID);
payload.logger.info({ msg: `Migrated: ${migration.name} (${Date.now() - start}ms)` });
} catch (err: unknown) {
await this.rollbackTransaction(transactionID);
payload.logger.error({
msg: `Error running migration ${migration.name}`,
err,
});
throw err;
}
}
}

View File

@@ -1,48 +0,0 @@
/* eslint-disable no-restricted-syntax, no-await-in-loop */
import { DatabaseAdapter } from '../types';
import { getMigrations } from './getMigrations';
import { readMigrationFiles } from './readMigrationFiles';
import { PayloadRequest } from '../../express/types';
export async function migrateReset(this: DatabaseAdapter): Promise<void> {
const { payload } = this;
const migrationFiles = await readMigrationFiles({ payload });
const { existingMigrations } = await getMigrations({ payload });
if (!existingMigrations?.length) {
payload.logger.info({ msg: 'No migrations to reset.' });
return;
}
let transactionID;
// Rollback all migrations in order
for (const migration of migrationFiles) {
// Create or update migration in database
const existingMigration = existingMigrations.find((existing) => existing.name === migration.name);
if (existingMigration) {
payload.logger.info({ msg: `Migrating: ${migration.name}` });
try {
const start = Date.now();
transactionID = await this.beginTransaction();
await migration.down({ payload });
await payload.delete({
collection: 'payload-migrations',
where: {
id: {
equals: existingMigration.id,
},
},
req: { transactionID } as PayloadRequest,
});
await this.commitTransaction(transactionID);
payload.logger.info({ msg: `Migrated: ${migration.name} (${Date.now() - start}ms)` });
} catch (err: unknown) {
await this.rollbackTransaction(transactionID);
payload.logger.error({ msg: `Error running migration ${migration.name}`, err });
throw err;
}
}
}
}

View File

@@ -1,36 +0,0 @@
import { Table } from 'console-table-printer';
import { DatabaseAdapter } from '../types';
import { readMigrationFiles } from './readMigrationFiles';
import { getMigrations } from './getMigrations';
export async function migrateStatus(this: DatabaseAdapter): Promise<void> {
const { payload } = this;
const migrationFiles = await readMigrationFiles({ payload });
const { existingMigrations } = await getMigrations({ payload });
if (!migrationFiles.length) {
payload.logger.info({ msg: 'No migrations found.' });
return;
}
// Compare migration files to existing migrations
const statuses = migrationFiles.map((migration) => {
const existingMigration = existingMigrations.find(
(m) => m.name === migration.name,
);
return {
Ran: existingMigration ? 'Yes' : 'No',
Name: migration.name,
Batch: existingMigration?.batch,
};
});
const p = new Table();
statuses.forEach((s) => {
p.addRow(s, {
color: s.Ran === 'Yes' ? 'green' : 'red',
});
});
p.printTable();
}

View File

@@ -1,11 +0,0 @@
export const migrationTemplate = `
import payload, { Payload } from 'payload';
export async function up(payload: Payload): Promise<void> {
// Migration code
};
export async function down(payload: Payload): Promise<void> {
// Migration code
};
`;

View File

@@ -1,39 +0,0 @@
import type { CollectionConfig } from '../../collections/config/types';
export const migrationsCollection: CollectionConfig = {
slug: 'payload-migrations',
admin: {
hidden: true,
},
graphQL: false,
fields: [
{
name: 'name',
type: 'text',
},
{
name: 'batch',
type: 'number',
},
// TODO: determine how schema will impact migration workflow
{
name: 'schema',
type: 'json',
},
// TODO: do we need to persist the indexes separate from the schema?
// {
// name: 'indexes',
// type: 'array',
// fields: [
// {
// name: 'index',
// type: 'text',
// },
// {
// name: 'value',
// type: 'json',
// },
// ],
// },
],
};

View File

@@ -1,28 +0,0 @@
import fs from 'fs';
import path from 'path';
import { Migration } from '../types';
import { Payload } from '../../index';
/**
* Read the migration files from disk
*/
export const readMigrationFiles = async ({
payload,
}: {
payload: Payload;
}): Promise<Migration[]> => {
if (!fs.existsSync(payload.db.migrationDir)) return [];
const files = fs
.readdirSync(payload.db.migrationDir)
.sort()
.map((file) => {
return path.resolve(payload.db.migrationDir, file);
});
return files.map((filePath) => {
// eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-dynamic-require
const migration = require(filePath) as Migration;
migration.name = path.basename(filePath).split('.')?.[0];
return migration;
});
};

View File

@@ -1,23 +0,0 @@
import { CollectionPermission, GlobalPermission } from '../../auth';
import { Field, FieldAffectingData, TabAsField, UIField } from '../../fields/config/types';
export const validOperators = ['like', 'contains', 'in', 'all', 'not_in', 'greater_than_equal', 'greater_than', 'less_than_equal', 'less_than', 'not_equals', 'equals', 'exists', 'near'];
export type EntityPolicies = {
collections?: {
[collectionSlug: string]: CollectionPermission;
};
globals?: {
[globalSlug: string]: GlobalPermission;
};
};
export type PathToQuery = {
complete: boolean
collectionSlug?: string
globalSlug?: string
path: string
field: Field | TabAsField
fields?: (FieldAffectingData | UIField | TabAsField)[]
invalid?: boolean
}

View File

@@ -1,86 +0,0 @@
/* eslint-disable no-restricted-syntax */
/* eslint-disable no-await-in-loop */
import { PayloadRequest, Where, WhereField } from '../../types';
import QueryError from '../../errors/QueryError';
import { SanitizedCollectionConfig } from '../../collections/config/types';
import { SanitizedGlobalConfig } from '../../globals/config/types';
import flattenFields from '../../utilities/flattenTopLevelFields';
import { Field, FieldAffectingData } from '../../fields/config/types';
import { validateSearchParam } from './validateSearchParams';
import deepCopyObject from '../../utilities/deepCopyObject';
import { EntityPolicies, validOperators } from './types';
const flattenWhere = (query: Where): WhereField[] => Object.entries(query).reduce((flattenedConstraints, [key, val]) => {
if ((key === 'and' || key === 'or') && Array.isArray(val)) {
return [
...flattenedConstraints,
...val.map((subVal) => flattenWhere(subVal)),
];
}
return [
...flattenedConstraints,
{ [key]: val },
];
}, []);
type Args = {
where: Where
errors?: { path: string }[]
policies?: EntityPolicies
req: PayloadRequest
versionFields?: Field[]
overrideAccess: boolean
} & ({
collectionConfig: SanitizedCollectionConfig
globalConfig?: never | undefined
} | {
globalConfig: SanitizedGlobalConfig
collectionConfig?: never | undefined
})
export async function validateQueryPaths({
where,
collectionConfig,
globalConfig,
errors = [],
policies = {
collections: {},
globals: {},
},
versionFields,
req,
overrideAccess,
}: Args): Promise<void> {
const fields = flattenFields(versionFields || (globalConfig || collectionConfig).fields) as FieldAffectingData[];
if (typeof where === 'object') {
// const flattenedWhere = flattenWhere(where);
const whereFields = flattenWhere(where);
// We need to determine if the whereKey is an AND, OR, or a schema path
const promises = [];
whereFields.map(async (constraint) => {
Object.keys(constraint).map(async (path) => {
Object.entries(constraint[path]).map(async ([operator, val]) => {
if (validOperators.includes(operator)) {
promises.push(validateSearchParam({
collectionConfig: deepCopyObject(collectionConfig),
globalConfig: deepCopyObject(globalConfig),
fields: (fields as Field[]),
versionFields,
errors,
policies,
req,
path,
val,
operator,
overrideAccess,
}));
}
});
});
});
await Promise.all(promises);
if (errors.length > 0) {
throw new QueryError(errors);
}
}
}

View File

@@ -1,165 +0,0 @@
import { Field, fieldAffectsData } from '../../fields/config/types';
import { PayloadRequest } from '../../express/types';
import { getEntityPolicies } from '../../utilities/getEntityPolicies';
import { SanitizedCollectionConfig } from '../../collections/config/types';
import { SanitizedGlobalConfig } from '../../globals/config/types';
import { validateQueryPaths } from './validateQueryPaths';
import { EntityPolicies, PathToQuery } from './types';
import { getLocalizedPaths } from '../getLocalizedPaths';
type Args = {
fields: Field[]
path: string
val: unknown
operator: string
req: PayloadRequest
errors: { path: string }[]
policies: EntityPolicies
collectionConfig?: SanitizedCollectionConfig
globalConfig?: SanitizedGlobalConfig
versionFields?: Field[]
overrideAccess: boolean
}
/**
* Validate the Payload key / value / operator
*/
export async function validateSearchParam({
fields,
path: incomingPath,
versionFields,
val,
operator,
collectionConfig,
globalConfig,
errors,
req,
policies,
overrideAccess,
}: Args): Promise<void> {
// Replace GraphQL nested field double underscore formatting
let sanitizedPath;
if (incomingPath === '_id') {
sanitizedPath = 'id';
} else {
sanitizedPath = incomingPath.replace(/__/gi, '.');
}
let paths: PathToQuery[] = [];
const { slug } = (collectionConfig || globalConfig);
if (globalConfig && !policies.globals[slug]) {
// eslint-disable-next-line no-param-reassign
globalConfig.fields = fields;
// eslint-disable-next-line no-param-reassign
policies.globals[slug] = await getEntityPolicies({
req,
entity: globalConfig,
operations: ['read'],
type: 'global',
});
}
if (sanitizedPath !== 'id') {
paths = await getLocalizedPaths({
payload: req.payload,
locale: req.locale,
collectionSlug: collectionConfig?.slug,
globalSlug: globalConfig?.slug,
fields,
incomingPath: sanitizedPath,
overrideAccess,
});
}
const promises = [];
promises.push(...paths.map(async ({ path, field, invalid, collectionSlug }, i) => {
if (invalid) {
errors.push({ path });
return;
}
if (!overrideAccess && fieldAffectsData(field)) {
if (collectionSlug) {
if (!policies.collections[collectionSlug]) {
// eslint-disable-next-line no-param-reassign
policies.collections[collectionSlug] = await getEntityPolicies({
req,
entity: req.payload.collections[collectionSlug].config,
operations: ['read'],
type: 'collection',
});
}
if (['salt', 'hash'].includes(incomingPath) && collectionConfig.auth && !collectionConfig.auth?.disableLocalStrategy) {
errors.push({ path: incomingPath });
}
}
let fieldAccess;
let fieldPath = path;
// remove locale from end of path
if (path.endsWith(req.locale)) {
fieldPath = path.slice(0, -(req.locale.length + 1));
}
// remove ".value" from ends of polymorphic relationship paths
if (field.type === 'relationship' && Array.isArray(field.relationTo)) {
fieldPath = fieldPath.replace('.value', '');
}
const entityType: 'collections' | 'globals' = globalConfig ? 'globals' : 'collections';
const entitySlug = collectionSlug || globalConfig.slug;
const segments = fieldPath.split('.');
if (versionFields) {
if (fieldPath === 'parent' || fieldPath === 'version') {
fieldAccess = policies[entityType][entitySlug].read.permission;
} else if (segments[0] === 'parent' || segments[0] === 'version') {
fieldAccess = policies[entityType][entitySlug].read.permission;
segments.shift();
}
} else {
fieldAccess = policies[entityType][entitySlug].fields;
segments.forEach((segment, pathIndex) => {
if (pathIndex === segments.length - 1) {
fieldAccess = fieldAccess[segment];
} else {
fieldAccess = fieldAccess[segment].fields;
}
});
fieldAccess = fieldAccess.read.permission;
}
if (!fieldAccess) {
errors.push({ path: fieldPath });
}
}
if (i > 1) {
// Remove top collection and reverse array
// to work backwards from top
const pathsToQuery = paths.slice(1)
.reverse();
pathsToQuery.forEach(({
path: subPath,
collectionSlug: pathCollectionSlug,
}, pathToQueryIndex) => {
// On the "deepest" collection,
// validate query of the relationship
if (pathToQueryIndex === 0) {
promises.push(validateQueryPaths({
collectionConfig: req.payload.collections[pathCollectionSlug].config,
globalConfig: undefined,
where: {
[subPath]: {
[operator]: val,
},
},
errors,
policies,
req,
overrideAccess,
}));
}
});
}
}));
await Promise.all(promises);
}

View File

@@ -1,14 +0,0 @@
import { Transaction } from './types';
export const transaction: Transaction = async function transaction(
callback: () => Promise<unknown>,
options,
) {
const id = await this.beginTransaction(options);
try {
await callback();
await this.commitTransaction(id);
} catch (err: unknown) {
await this.rollbackTransaction(id);
}
};

View File

@@ -1,354 +0,0 @@
import type { Configuration } from 'webpack';
import type { TypeWithID } from '../collections/config/types';
import type { TypeWithID as GlobalsTypeWithID } from '../globals/config/types';
import type { Payload } from '../payload';
import type { Document, PayloadRequest, Where } from '../types';
import type { TypeWithVersion } from '../versions/types';
export interface DatabaseAdapter {
/**
* reference to the instance of payload
*/
payload: Payload;
/**
* Open the connection to the database
*/
connect?: Connect;
/**
* Perform startup tasks required to interact with the database such as building Schema and models
*/
init?: Init;
/**
* Terminate the connection with the database
*/
destroy?: Destroy;
/**
* Used to alias server only modules or make other changes to webpack configuration
*/
webpack?: Webpack;
// migrations
/**
* Path to read and write migration files from
*/
migrationDir?: string;
/**
* Output a migration file
*/
createMigration: (CreateMigrationArgs) => Promise<void>;
/**
* Run any migration up functions that have not yet been performed and update the status
*/
migrate: () => Promise<void>;
/**
* Read the current state of migrations and output the result to show which have been run
*/
migrateStatus: () => Promise<void>;
/**
* Run any migration down functions that have been performed
*/
migrateDown: () => Promise<void>;
/**
* Run all migration down functions before running up
*/
migrateRefresh: () => Promise<void>;
/**
* Run all migrate down functions
*/
migrateReset: () => Promise<void>;
/**
* Drop the current database and run all migrate up functions
*/
migrateFresh: () => Promise<void>;
// transactions
/**
* assign the transaction to use when making queries, defaults to the last started transaction
*/
useTransaction?: (id: string | number) => void;
/**
* Perform many database interactions in a single, all-or-nothing operation.
*/
transaction?: Transaction;
/**
* Start a transaction, requiring commitTransaction() to be called for any changes to be made.
* @returns an identifier for the transaction or null if one cannot be established
*/
beginTransaction?: BeginTransaction;
/**
* Abort any changes since the start of the transaction.
*/
rollbackTransaction?: RollbackTransaction;
/**
* Persist the changes made since the start of the transaction.
*/
commitTransaction?: CommitTransaction;
queryDrafts: QueryDrafts;
// operations
find: <T = TypeWithID>(args: FindArgs) => Promise<PaginatedDocs<T>>;
findOne: FindOne;
create: Create;
updateOne: UpdateOne;
deleteOne: DeleteOne;
deleteMany: DeleteMany;
// operations - globals
findGlobal: FindGlobal;
createGlobal: CreateGlobal;
updateGlobal: UpdateGlobal;
// versions
findVersions: FindVersions;
findGlobalVersions: FindGlobalVersions;
createVersion: CreateVersion;
updateVersion: UpdateVersion;
deleteVersions: DeleteVersions;
}
export type Init = (payload: Payload) => Promise<void>;
export type Connect = (payload: Payload) => Promise<void>
export type Destroy = (payload: Payload) => Promise<void>
export type Webpack = (config: Configuration) => Configuration;
export type CreateMigrationArgs = {
payload: Payload
migrationDir: string
migrationName: string
}
export type CreateMigration = (args: CreateMigrationArgs) => Promise<void>
export type Transaction = (callback: () => Promise<void>, options?: Record<string, unknown>) => Promise<void>
export type BeginTransaction = (options?: Record<string, unknown>) => Promise<number | string | null>
export type RollbackTransaction = (id: string | number) => Promise<void>
export type CommitTransaction = (id: string | number) => Promise<void>
export type QueryDraftsArgs = {
collection: string
where?: Where
page?: number
limit?: number
pagination?: boolean
sort?: string
locale?: string
req?: PayloadRequest
}
export type QueryDrafts = <T = TypeWithID>(args: QueryDraftsArgs) => Promise<PaginatedDocs<T>>;
export type FindOneArgs = {
collection: string
where?: Where
locale?: string
req?: PayloadRequest
}
export type FindOne = <T = TypeWithID>(args: FindOneArgs) => Promise<T | null>
export type FindArgs = {
collection: string
where?: Where
page?: number
skip?: number
versions?: boolean
/** Setting limit to 1 is equal to the previous Model.findOne(). Setting limit to 0 disables the limit */
limit?: number
pagination?: boolean
sort?: string
locale?: string
req?: PayloadRequest
}
export type Find = <T = TypeWithID>(args: FindArgs) => Promise<PaginatedDocs<T>>;
export type FindVersionsArgs = {
collection: string
where?: Where
page?: number
skip?: number
versions?: boolean
limit?: number
pagination?: boolean
sort?: string
locale?: string
req?: PayloadRequest
}
export type FindVersions = <T = TypeWithID>(args: FindVersionsArgs) => Promise<PaginatedDocs<TypeWithVersion<T>>>;
export type FindGlobalVersionsArgs = {
global: string
where?: Where
page?: number
skip?: number
versions?: boolean
limit?: number
pagination?: boolean
sort?: string
locale?: string
req?: PayloadRequest
}
export type FindGlobalArgs = {
slug: string
locale?: string
where?: Where
req?: PayloadRequest
}
export type FindGlobal = <T extends GlobalsTypeWithID = any>(args: FindGlobalArgs) => Promise<T>
export type CreateGlobalArgs<T extends GlobalsTypeWithID = any> = {
slug: string
data: T
req?: PayloadRequest
}
export type CreateGlobal = <T extends GlobalsTypeWithID = any>(args: CreateGlobalArgs<T>) => Promise<T>
export type UpdateGlobalArgs<T extends GlobalsTypeWithID = any> = {
slug: string
data: T
req?: PayloadRequest
}
export type UpdateGlobal = <T extends GlobalsTypeWithID = any>(args: UpdateGlobalArgs<T>) => Promise<T>
// export type UpdateOne = (args: UpdateOneArgs) => Promise<Document>
export type FindGlobalVersions = <T = TypeWithID>(args: FindGlobalVersionsArgs) => Promise<PaginatedDocs<TypeWithVersion<T>>>;
export type DeleteVersionsArgs = {
collection: string
where: Where
locale?: string
sort?: {
[key: string]: string
}
req?: PayloadRequest
};
export type CreateVersionArgs<T = TypeWithID> = {
collectionSlug: string
/** ID of the parent document for which the version should be created for */
parent: string | number
versionData: T
autosave: boolean
createdAt: string
updatedAt: string
req?: PayloadRequest
}
export type CreateVersion = <T = TypeWithID>(args: CreateVersionArgs<T>) => Promise<TypeWithVersion<T>>;
export type DeleteVersions = (args: DeleteVersionsArgs) => Promise<void>;
export type UpdateVersionArgs<T = TypeWithID> = {
collectionSlug: string
where: Where
locale?: string
versionData: T
req?: PayloadRequest
}
export type UpdateVersion = <T = TypeWithID>(args: UpdateVersionArgs<T>) => Promise<TypeWithVersion<T>>
export type CreateArgs = {
collection: string
data: Record<string, unknown>
draft?: boolean
locale?: string
req?: PayloadRequest
}
export type Create = (args: CreateArgs) => Promise<Document>
export type UpdateArgs = {
collection: string
data: Record<string, unknown>
where: Where
draft?: boolean
locale?: string
req?: PayloadRequest
}
export type Update = (args: UpdateArgs) => Promise<Document>
export type UpdateOneArgs = {
collection: string
data: Record<string, unknown>
where: Where
draft?: boolean
locale?: string
req?: PayloadRequest
}
export type UpdateOne = (args: UpdateOneArgs) => Promise<Document>
export type DeleteOneArgs = {
collection: string
where: Where
req?: PayloadRequest
}
export type DeleteOne = (args: DeleteOneArgs) => Promise<Document>
export type DeleteManyArgs = {
collection: string
where: Where
req?: PayloadRequest
}
export type DeleteMany = (args: DeleteManyArgs) => Promise<void>
export type Migration = MigrationData & {
up: ({ payload }: { payload }) => Promise<boolean>
down: ({ payload }: { payload }) => Promise<boolean>
};
export type MigrationData = {
id: string
name: string
batch: number
}
export type PaginatedDocs<T = any> = {
docs: T[]
totalDocs: number
limit: number
totalPages: number
page?: number
pagingCounter: number
hasPrevPage: boolean
hasNextPage: boolean
prevPage?: number | null | undefined
nextPage?: number | null | undefined
}

View File

@@ -5,7 +5,7 @@ async function initAdmin(ctx: Payload): Promise<void> {
if (process.env.NODE_ENV === 'production') {
ctx.express.use(ctx.config.routes.admin, await ctx.config.admin.bundler.serve(ctx));
} else {
ctx.express.use(ctx.config.routes.admin, await ctx.config.admin.bundler.dev(ctx));
ctx.express.use(await ctx.config.admin.bundler.dev(ctx));
}
}
}

View File

@@ -1,10 +0,0 @@
import type { Response, NextFunction } from 'express';
import type { PayloadRequest } from '../types';
import { setRequestContext } from '../setRequestContext';
function defaultPayload(req: PayloadRequest, res: Response, next: NextFunction) {
setRequestContext(req);
next();
}
export default defaultPayload;

View File

@@ -21,11 +21,11 @@ const errorHandler = (config: SanitizedConfig, logger: Logger) => async (err: AP
}
if (req.collection && typeof req.collection.config.hooks.afterError === 'function') {
({ response, status } = await req.collection.config.hooks.afterError(err, response, req.context) || { response, status });
({ response, status } = await req.collection.config.hooks.afterError(err, response) || { response, status });
}
if (typeof config.hooks.afterError === 'function') {
({ response, status } = await config.hooks.afterError(err, response, req.context) || { response, status });
({ response, status } = await config.hooks.afterError(err, response) || { response, status });
}
res.status(status).send(response);

View File

@@ -14,7 +14,6 @@ import { PayloadRequest } from '../types';
import corsHeaders from './corsHeaders';
import convertPayload from './convertPayload';
import { i18nMiddleware } from './i18n';
import defaultPayload from './defaultPayload';
const middleware = (payload: Payload): any => {
const rateLimitOptions: {
@@ -33,7 +32,6 @@ const middleware = (payload: Payload): any => {
}
return [
defaultPayload,
...(payload.config.express.preMiddleware || []),
rateLimit(rateLimitOptions),
passport.initialize(),

View File

@@ -1,18 +0,0 @@
/* eslint-disable no-param-reassign */
import type { PayloadRequest, RequestContext } from './types';
/**
* This makes sure that req.context always exists (is {}) and populates it with an optional default context.
* This function mutates directly to avoid copying memory. As payloadRequest is not a primitive, the scope of the mutation is not limited to this function but should also be reflected in the calling function.
*/
export function setRequestContext(req: PayloadRequest = { context: null } as PayloadRequest, context: RequestContext = {}) {
if (req.context) {
if (Object.keys(req.context).length === 0 && req.context.constructor === Object) { // check if req.context is just {}
req.context = context; // Faster - ... is bad for performance
} else {
req.context = { ...req.context, ...context }; // Merge together
}
} else {
req.context = context;
}
}

View File

@@ -24,20 +24,10 @@ export declare type PayloadRequest<U = any> = Request & {
* - Configuration from payload-config.ts
* - MongoDB model for this collection
* - GraphQL type metadata
*/
* */
collection?: Collection;
/** What triggered this request */
payloadAPI?: 'REST' | 'local' | 'GraphQL';
/**
* Identifier for the database transaction for interactions in a single, all-or-nothing operation.
*/
transactionID?: string | number;
/** context allows you to pass your own data to the request object as context
* This is useful for, for example, passing data from a beforeChange hook to an afterChange hook.
* payoadContext can also be fully typed using declare module
* {@link https://payloadcms.com/docs/hooks/context More info in the Payload Documentation}.
*/
context: RequestContext;
/** Uploaded files */
files?: {
/**
@@ -59,7 +49,3 @@ export declare type PayloadRequest<U = any> = Request & {
[slug: string]: (q: unknown) => Document;
};
};
export interface RequestContext {
[key: string]: unknown;
}

View File

@@ -6,7 +6,7 @@ import type { EditorProps } from '@monaco-editor/react';
import { Operation, Where } from '../../types';
import { SanitizedConfig } from '../../config/types';
import { TypeWithID } from '../../collections/config/types';
import { PayloadRequest, RequestContext } from '../../express/types';
import { PayloadRequest } from '../../express/types';
import { ConditionalDateProps } from '../../admin/components/elements/DatePicker/types';
import { Description } from '../../admin/components/forms/FieldDescription/types';
import { User } from '../../auth';
@@ -33,7 +33,6 @@ export type FieldHookArgs<T extends TypeWithID = any, P = any, S = any> = {
/** The value of the field. */
value?: P,
previousValue?: P,
context: RequestContext
}
export type FieldHook<T extends TypeWithID = any, P = any, S = any> = (args: FieldHookArgs<T, P, S>) => Promise<P> | P;

View File

@@ -1,6 +1,6 @@
import { SanitizedCollectionConfig } from '../../../collections/config/types';
import { SanitizedGlobalConfig } from '../../../globals/config/types';
import { PayloadRequest, RequestContext } from '../../../express/types';
import { PayloadRequest } from '../../../express/types';
import { traverseFields } from './traverseFields';
import deepCopyObject from '../../../utilities/deepCopyObject';
@@ -11,7 +11,6 @@ type Args<T> = {
entityConfig: SanitizedCollectionConfig | SanitizedGlobalConfig
operation: 'create' | 'update'
req: PayloadRequest
context: RequestContext
}
export const afterChange = async <T extends Record<string, unknown>>({
@@ -21,7 +20,6 @@ export const afterChange = async <T extends Record<string, unknown>>({
entityConfig,
operation,
req,
context,
}: Args<T>): Promise<T> => {
const doc = deepCopyObject(incomingDoc);
@@ -35,7 +33,6 @@ export const afterChange = async <T extends Record<string, unknown>>({
previousSiblingDoc: previousDoc,
siblingDoc: doc,
siblingData: data,
context,
});
return doc;

View File

@@ -1,5 +1,5 @@
/* eslint-disable no-param-reassign */
import { PayloadRequest, RequestContext } from '../../../express/types';
import { PayloadRequest } from '../../../express/types';
import { Field, fieldAffectsData, TabAsField, tabHasName } from '../../config/types';
import { traverseFields } from './traverseFields';
@@ -13,7 +13,6 @@ type Args = {
req: PayloadRequest
siblingData: Record<string, unknown>
siblingDoc: Record<string, unknown>
context: RequestContext
}
// This function is responsible for the following actions, in order:
@@ -29,7 +28,6 @@ export const promise = async ({
req,
siblingData,
siblingDoc,
context,
}: Args): Promise<void> => {
if (fieldAffectsData(field)) {
// Execute hooks
@@ -47,7 +45,6 @@ export const promise = async ({
siblingData,
operation,
req,
context,
});
if (hookedValue !== undefined) {
@@ -70,7 +67,6 @@ export const promise = async ({
req,
siblingData: siblingData?.[field.name] as Record<string, unknown> || {},
siblingDoc: siblingDoc[field.name] as Record<string, unknown>,
context,
});
break;
@@ -92,7 +88,6 @@ export const promise = async ({
req,
siblingData: siblingData?.[field.name]?.[i] || {},
siblingDoc: { ...row } || {},
context,
}));
});
await Promise.all(promises);
@@ -119,7 +114,6 @@ export const promise = async ({
req,
siblingData: siblingData?.[field.name]?.[i] || {},
siblingDoc: { ...row } || {},
context,
}));
}
});
@@ -141,7 +135,6 @@ export const promise = async ({
req,
siblingData: siblingData || {},
siblingDoc: { ...siblingDoc },
context,
});
break;
@@ -168,7 +161,6 @@ export const promise = async ({
previousDoc,
siblingData: tabSiblingData,
siblingDoc: tabSiblingDoc,
context,
});
break;
@@ -185,7 +177,6 @@ export const promise = async ({
req,
siblingData: siblingData || {},
siblingDoc: { ...siblingDoc },
context,
});
break;
}

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