Compare commits
51 Commits
v3.0.0-bet
...
v3.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a8bd4c775 | ||
|
|
ac10bad723 | ||
|
|
142616e6ad | ||
|
|
dd3d985091 | ||
|
|
de3d7c95e7 | ||
|
|
570422ff9a | ||
|
|
53c41bdfd8 | ||
|
|
e5c34ead16 | ||
|
|
6e561b11ca | ||
|
|
f7146362df | ||
|
|
ec9d1cda2d | ||
|
|
657326b528 | ||
|
|
538b7ee616 | ||
|
|
828f5d866d | ||
|
|
e375f6e727 | ||
|
|
cc9b877e88 | ||
|
|
dc12047723 | ||
|
|
12fb691e4f | ||
|
|
0962850086 | ||
|
|
78c8bb81a1 | ||
|
|
419b274bb1 | ||
|
|
ef818fd5c8 | ||
|
|
0aaf3af1ea | ||
|
|
18b0806b5b | ||
|
|
3d9051ad34 | ||
|
|
e4ef47b938 | ||
|
|
c7e7dc71d3 | ||
|
|
375671c162 | ||
|
|
23b495b145 | ||
|
|
27d743e2a8 | ||
|
|
8c9ff3d54b | ||
|
|
5c447252e7 | ||
|
|
a76be81368 | ||
|
|
5d97d57e70 | ||
|
|
de7ff1f8c6 | ||
|
|
3d714d3e72 | ||
|
|
2bbb02b9c0 | ||
|
|
0533e7f5db | ||
|
|
23c5ef428d | ||
|
|
f046a04510 | ||
|
|
4cda7d2363 | ||
|
|
ea48cfbfe9 | ||
|
|
1aeb912762 | ||
|
|
ce2cb35d71 | ||
|
|
d3ec68ac2f | ||
|
|
05bf52aac3 | ||
|
|
fed7f2fa5b | ||
|
|
686b0865b2 | ||
|
|
dfb4c8eb4c | ||
|
|
ad7a387e19 | ||
|
|
d05be016ce |
@@ -196,6 +196,48 @@ import { MyFieldComponent } from 'my-external-package/client'
|
||||
|
||||
which is a valid way to access MyFieldComponent that can be resolved by the consuming project.
|
||||
|
||||
### Custom Components from unknown locations
|
||||
|
||||
By default, any component paths from known locations are added to the import map. However, if you need to add any components from unknown locations to the import map, you can do so by adding them to the `admin.dependencies` array in your Payload Config. This is mostly only relevant for plugin authors and not for regular Payload users.
|
||||
|
||||
Example:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
// ...
|
||||
admin: {
|
||||
// ...
|
||||
dependencies: {
|
||||
myTestComponent: { // myTestComponent is the key - can be anything
|
||||
path: '/components/TestComponent.js#TestComponent',
|
||||
type: 'component',
|
||||
clientProps: {
|
||||
test: 'hello',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This way, `TestComponent` is added to the import map, no matter if it's referenced in a known location or not. On the client, you can then use the component like this:
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
|
||||
import { RenderComponent, useConfig } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
export const CustomView = () => {
|
||||
const { config } = useConfig()
|
||||
return (
|
||||
<div>
|
||||
<RenderComponent mappedComponent={config.admin.dependencies?.myTestComponent} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Root Components
|
||||
|
||||
Root Components are those that effect the [Admin Panel](./overview) generally, such as the logo or the main nav.
|
||||
|
||||
@@ -71,6 +71,7 @@ The following options are available:
|
||||
| **`db`** \* | The Database Adapter which will be used by Payload. [More details](../database/overview). |
|
||||
| **`serverURL`** | A string used to define the absolute URL of your app. This includes the protocol, for example `https://example.com`. No paths allowed, only protocol, domain and (optionally) port. |
|
||||
| **`collections`** | An array of Collections for Payload to manage. [More details](./collections). |
|
||||
| **`compatibility`** | Compatibility flags for earlier versions of Payload. [More details](#compatibility-flags). |
|
||||
| **`globals`** | An array of Globals for Payload to manage. [More details](./globals). |
|
||||
| **`cors`** | Cross-origin resource sharing (CORS) is a mechanism that accept incoming requests from given domains. You can also customize the `Access-Control-Allow-Headers` header. [More details](#cors). |
|
||||
| **`localization`** | Opt-in to translate your content into multiple locales. [More details](./localization). |
|
||||
@@ -253,3 +254,13 @@ import type { Config, SanitizedConfig } from 'payload'
|
||||
The Payload Config only lives on the server and is not allowed to contain any client-side code. That way, you can load up the Payload Config in any server environment or standalone script, without having to use Bundlers or Node.js loaders to handle importing client-only modules (e.g. scss files or React Components) without any errors.
|
||||
|
||||
Behind the curtains, the Next.js-based Admin Panel generates a ClientConfig, which strips away any server-only code and enriches the config with React Components.
|
||||
|
||||
## Compatibility flags
|
||||
|
||||
The Payload Config can accept compatibility flags for running the newest versions but with older databases. You should only use these flags if you need to, and should confirm that you need to prior to enabling these flags.
|
||||
|
||||
`allowLocalizedWithinLocalized`
|
||||
|
||||
Payload localization works on a field-by-field basis. As you can nest fields within other fields, you could potentially nest a localized field within a localized field—but this would be redundant and unnecessary. There would be no reason to define a localized field within a localized parent field, given that the entire data structure from the parent field onward would be localized.
|
||||
|
||||
By default, Payload will remove the `localized: true` property from sub-fields if a parent field is localized. Set this compatibility flag to `true` only if you have an existing Payload MongoDB database from pre-3.0, and you have nested localized fields that you would like to maintain without migrating.
|
||||
|
||||
@@ -40,6 +40,7 @@ export const rootEslintConfig = [
|
||||
{
|
||||
ignores: [
|
||||
...defaultESLintIgnores,
|
||||
'packages/eslint-*/**',
|
||||
'test/live-preview/next-app',
|
||||
'packages/**/*.spec.ts',
|
||||
'templates/**',
|
||||
|
||||
@@ -5,6 +5,8 @@ import config from '@payload-config'
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views'
|
||||
|
||||
import { importMap } from '../importMap.js'
|
||||
|
||||
type Args = {
|
||||
params: {
|
||||
segments: string[]
|
||||
@@ -17,6 +19,7 @@ type Args = {
|
||||
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
|
||||
generatePageMetadata({ config, params, searchParams })
|
||||
|
||||
const NotFound = ({ params, searchParams }: Args) => NotFoundPage({ config, params, searchParams })
|
||||
const NotFound = ({ params, searchParams }: Args) =>
|
||||
NotFoundPage({ config, importMap, params, searchParams })
|
||||
|
||||
export default NotFound
|
||||
|
||||
@@ -5,6 +5,8 @@ import config from '@payload-config'
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import { RootPage, generatePageMetadata } from '@payloadcms/next/views'
|
||||
|
||||
import { importMap } from '../importMap.js'
|
||||
|
||||
type Args = {
|
||||
params: {
|
||||
segments: string[]
|
||||
@@ -17,6 +19,7 @@ type Args = {
|
||||
export const generateMetadata = ({ params, searchParams }: Args): Promise<Metadata> =>
|
||||
generatePageMetadata({ config, params, searchParams })
|
||||
|
||||
const Page = ({ params, searchParams }: Args) => RootPage({ config, params, searchParams })
|
||||
const Page = ({ params, searchParams }: Args) =>
|
||||
RootPage({ config, importMap, params, searchParams })
|
||||
|
||||
export default Page
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { TenantFieldComponent as TenantFieldComponent_0 } from '@/fields/TenantField/components/Field'
|
||||
import { TenantSelectorRSC as TenantSelectorRSC_1 } from '@/components/TenantSelector'
|
||||
|
||||
export const importMap = {
|
||||
'@/fields/TenantField/components/Field#TenantFieldComponent': TenantFieldComponent_0,
|
||||
'@/components/TenantSelector#TenantSelectorRSC': TenantSelectorRSC_1,
|
||||
}
|
||||
@@ -1,18 +1,21 @@
|
||||
/* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
|
||||
import configPromise from "@payload-config";
|
||||
import "@payloadcms/next/css";
|
||||
import { RootLayout } from "@payloadcms/next/layouts";
|
||||
import configPromise from '@payload-config'
|
||||
import '@payloadcms/next/css'
|
||||
import { RootLayout } from '@payloadcms/next/layouts'
|
||||
/* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
|
||||
import React from "react";
|
||||
import React from 'react'
|
||||
|
||||
import "./custom.scss";
|
||||
import { importMap } from './admin/importMap.js'
|
||||
import './custom.scss'
|
||||
|
||||
type Args = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
const Layout = ({ children }: Args) => (
|
||||
<RootLayout config={configPromise}>{children}</RootLayout>
|
||||
);
|
||||
<RootLayout config={configPromise} importMap={importMap}>
|
||||
{children}
|
||||
</RootLayout>
|
||||
)
|
||||
|
||||
export default Layout;
|
||||
export default Layout
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Access } from 'payload'
|
||||
|
||||
import type { User } from '../../../../payload-types'
|
||||
import type { User } from '../../../payload-types'
|
||||
|
||||
import { isSuperAdmin } from '../../../access/isSuperAdmin'
|
||||
import { getTenantAdminTenantAccessIDs } from '../../../utilities/getTenantAccessIDs'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
import type { User } from '../../../payload-types'
|
||||
import type { User } from '../../payload-types'
|
||||
|
||||
import { getTenantAdminTenantAccessIDs } from '../../utilities/getTenantAccessIDs'
|
||||
import { createAccess } from './access/create'
|
||||
@@ -37,32 +37,6 @@ const Users: CollectionConfig = {
|
||||
{
|
||||
name: 'tenant',
|
||||
type: 'relationship',
|
||||
filterOptions: ({ user }) => {
|
||||
if (!user) {
|
||||
// Would like to query where exists true on id
|
||||
// but that is not working
|
||||
return {
|
||||
id: {
|
||||
like: '',
|
||||
},
|
||||
}
|
||||
}
|
||||
if (user?.roles?.includes('super-admin')) {
|
||||
// Would like to query where exists true on id
|
||||
// but that is not working
|
||||
return {
|
||||
id: {
|
||||
like: '',
|
||||
},
|
||||
}
|
||||
}
|
||||
const adminTenantAccessIDs = getTenantAdminTenantAccessIDs(user as User)
|
||||
return {
|
||||
id: {
|
||||
in: adminTenantAccessIDs,
|
||||
},
|
||||
}
|
||||
},
|
||||
index: true,
|
||||
relationTo: 'tenants',
|
||||
required: true,
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
import type { Option } from '@payloadcms/ui/elements/ReactSelect'
|
||||
import type { OptionObject } from 'payload'
|
||||
|
||||
import { getTenantAdminTenantAccessIDs } from '@/utilities/getTenantAccessIDs'
|
||||
import { SelectInput, useAuth } from '@payloadcms/ui'
|
||||
import * as qs from 'qs-esm'
|
||||
import React from 'react'
|
||||
|
||||
import type { Tenant, User } from '../../../payload-types.js'
|
||||
import type { Tenant, User } from '../../payload-types'
|
||||
|
||||
import './index.scss'
|
||||
|
||||
export const TenantSelector = ({ initialCookie }: { initialCookie?: string }) => {
|
||||
const { user } = useAuth<User>()
|
||||
const [options, setOptions] = React.useState<OptionObject[]>([])
|
||||
const [value, setValue] = React.useState<string | undefined>(initialCookie)
|
||||
|
||||
const isSuperAdmin = user?.roles?.includes('super-admin')
|
||||
const tenantIDs =
|
||||
@@ -28,18 +29,6 @@ export const TenantSelector = ({ initialCookie }: { initialCookie?: string }) =>
|
||||
document.cookie = name + '=' + (value || '') + expires + '; path=/'
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
const fetchTenants = async () => {
|
||||
const res = await fetch(`/api/tenants?depth=0&limit=100&sort=name`, {
|
||||
credentials: 'include',
|
||||
}).then((res) => res.json())
|
||||
|
||||
setOptions(res.docs.map((doc: Tenant) => ({ label: doc.name, value: doc.id })))
|
||||
}
|
||||
|
||||
void fetchTenants()
|
||||
}, [])
|
||||
|
||||
const handleChange = React.useCallback((option: Option | Option[]) => {
|
||||
if (!option) {
|
||||
setCookie('payload-tenant', undefined)
|
||||
@@ -50,7 +39,44 @@ export const TenantSelector = ({ initialCookie }: { initialCookie?: string }) =>
|
||||
}
|
||||
}, [])
|
||||
|
||||
if (isSuperAdmin || tenantIDs.length > 1) {
|
||||
React.useEffect(() => {
|
||||
const fetchTenants = async () => {
|
||||
const adminOfTenants = getTenantAdminTenantAccessIDs(user ?? null)
|
||||
|
||||
const queryString = qs.stringify(
|
||||
{
|
||||
depth: 0,
|
||||
limit: 100,
|
||||
sort: 'name',
|
||||
where: {
|
||||
id: {
|
||||
in: adminOfTenants,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
addQueryPrefix: true,
|
||||
},
|
||||
)
|
||||
|
||||
const res = await fetch(`/api/tenants${queryString}`, {
|
||||
credentials: 'include',
|
||||
}).then((res) => res.json())
|
||||
|
||||
const optionsToSet = res.docs.map((doc: Tenant) => ({ label: doc.name, value: doc.id }))
|
||||
|
||||
if (optionsToSet.length === 1) {
|
||||
setCookie('payload-tenant', optionsToSet[0].value)
|
||||
}
|
||||
setOptions(optionsToSet)
|
||||
}
|
||||
|
||||
if (user) {
|
||||
void fetchTenants()
|
||||
}
|
||||
}, [user])
|
||||
|
||||
if ((isSuperAdmin || tenantIDs.length > 1) && options.length > 1) {
|
||||
return (
|
||||
<div className="tenant-selector">
|
||||
<SelectInput
|
||||
@@ -59,7 +85,7 @@ export const TenantSelector = ({ initialCookie }: { initialCookie?: string }) =>
|
||||
onChange={handleChange}
|
||||
options={options}
|
||||
path="setTenant"
|
||||
value={value}
|
||||
value={options.find((opt) => opt.value === initialCookie)?.value}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
'use client'
|
||||
import { RelationshipField, useField } from '@payloadcms/ui'
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
initialValue?: string
|
||||
path: string
|
||||
readOnly: boolean
|
||||
}
|
||||
export function TenantFieldComponentClient({ initialValue, path, readOnly }: Props) {
|
||||
const { formInitializing, setValue } = useField({ path })
|
||||
const hasSetInitialValue = React.useRef(false)
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!hasSetInitialValue.current && !formInitializing && initialValue) {
|
||||
setValue(initialValue)
|
||||
hasSetInitialValue.current = true
|
||||
}
|
||||
}, [initialValue, setValue, formInitializing])
|
||||
|
||||
return (
|
||||
<RelationshipField
|
||||
field={{
|
||||
name: path,
|
||||
type: 'relationship',
|
||||
_path: path,
|
||||
label: 'Tenant',
|
||||
relationTo: 'tenants',
|
||||
required: true,
|
||||
}}
|
||||
readOnly={readOnly}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -1,26 +1,32 @@
|
||||
'use client'
|
||||
import { RelationshipField, useAuth, useFieldProps } from '@payloadcms/ui'
|
||||
import type { Payload } from 'payload'
|
||||
|
||||
import { cookies as getCookies, headers as getHeaders } from 'next/headers'
|
||||
import React from 'react'
|
||||
|
||||
import type { User } from '../../../../payload-types.js'
|
||||
import { TenantFieldComponentClient } from './Field.client'
|
||||
|
||||
export const TenantFieldComponent = () => {
|
||||
const { user } = useAuth<User>()
|
||||
const { path, readOnly } = useFieldProps()
|
||||
export const TenantFieldComponent: React.FC<{
|
||||
path: string
|
||||
payload: Payload
|
||||
readOnly: boolean
|
||||
}> = async (args) => {
|
||||
const cookies = getCookies()
|
||||
const headers = getHeaders()
|
||||
const { user } = await args.payload.auth({ headers })
|
||||
|
||||
if (user) {
|
||||
if ((user.tenants && user.tenants.length > 1) || user?.roles?.includes('super-admin')) {
|
||||
return (
|
||||
<RelationshipField
|
||||
label="Tenant"
|
||||
name={path}
|
||||
path={path}
|
||||
readOnly={readOnly}
|
||||
relationTo="tenants"
|
||||
required
|
||||
/>
|
||||
)
|
||||
}
|
||||
if (
|
||||
user &&
|
||||
((Array.isArray(user.tenants) && user.tenants.length > 1) ||
|
||||
user?.roles?.includes('super-admin'))
|
||||
) {
|
||||
return (
|
||||
<TenantFieldComponentClient
|
||||
initialValue={cookies.get('payload-tenant')?.value || undefined}
|
||||
path={args.path}
|
||||
readOnly={args.readOnly}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { Field } from 'payload'
|
||||
|
||||
import { isSuperAdmin } from '../../access/isSuperAdmin'
|
||||
import { tenantFieldUpdate } from './access/update'
|
||||
import { TenantFieldComponent } from './components/Field'
|
||||
import { autofillTenant } from './hooks/autofillTenant'
|
||||
|
||||
export const tenantField: Field = {
|
||||
@@ -17,7 +16,7 @@ export const tenantField: Field = {
|
||||
},
|
||||
admin: {
|
||||
components: {
|
||||
Field: TenantFieldComponent,
|
||||
Field: '@/fields/TenantField/components/Field#TenantFieldComponent',
|
||||
},
|
||||
position: 'sidebar',
|
||||
},
|
||||
|
||||
@@ -17,6 +17,9 @@ export interface Config {
|
||||
'payload-preferences': PayloadPreference;
|
||||
'payload-migrations': PayloadMigration;
|
||||
};
|
||||
db: {
|
||||
defaultIDType: string;
|
||||
};
|
||||
globals: {};
|
||||
locale: null;
|
||||
user: User & {
|
||||
@@ -26,15 +29,20 @@ export interface Config {
|
||||
export interface UserAuthOperations {
|
||||
forgotPassword: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
login: {
|
||||
password: string;
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
registerFirstUser: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
unlock: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
|
||||
@@ -7,7 +7,6 @@ import { fileURLToPath } from 'url'
|
||||
import { Pages } from './collections/Pages'
|
||||
import { Tenants } from './collections/Tenants'
|
||||
import Users from './collections/Users'
|
||||
import { TenantSelectorRSC } from './components/TenantSelector'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
@@ -15,7 +14,7 @@ const dirname = path.dirname(filename)
|
||||
export default buildConfig({
|
||||
admin: {
|
||||
components: {
|
||||
afterNavLinks: [TenantSelectorRSC],
|
||||
afterNavLinks: ['@/components/TenantSelector#TenantSelectorRSC'],
|
||||
},
|
||||
user: 'users',
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { User } from '../../payload-types'
|
||||
import type { User } from '../payload-types'
|
||||
|
||||
export const getTenantAccessIDs = (user: User | null): string[] => {
|
||||
if (!user) return []
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@ export default withBundleAnalyzer(
|
||||
env: {
|
||||
PAYLOAD_CORE_DEV: 'true',
|
||||
ROOT_DIR: path.resolve(dirname),
|
||||
PAYLOAD_DISABLE_DEPENDENCY_CHECKER: 'true',
|
||||
PAYLOAD_CI_DEPENDENCY_CHECKER: 'true',
|
||||
},
|
||||
async redirects() {
|
||||
return [
|
||||
|
||||
74
package.json
74
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload-monorepo",
|
||||
"version": "3.0.0-beta.91",
|
||||
"version": "3.0.0-beta.96",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
@@ -10,46 +10,46 @@
|
||||
"build:app": "next build",
|
||||
"build:app:analyze": "cross-env ANALYZE=true next build",
|
||||
"build:clean": "pnpm clean:build",
|
||||
"build:core": "turbo build --filter \"!@payloadcms/plugin-*\"",
|
||||
"build:core:force": "pnpm clean:build && turbo build --filter \"!@payloadcms/plugin-*\" --no-cache --force",
|
||||
"build:core": "turbo build --filter \"!@payloadcms/plugin-*\" --filter \"!@payloadcms/storage-*\"",
|
||||
"build:core:force": "pnpm clean:build && pnpm build:core --no-cache --force",
|
||||
"build:create-payload-app": "turbo build --filter create-payload-app",
|
||||
"build:db-mongodb": "turbo build --filter db-mongodb",
|
||||
"build:db-postgres": "turbo build --filter db-postgres",
|
||||
"build:db-sqlite": "turbo build --filter db-sqlite",
|
||||
"build:db-vercel-postgres": "turbo build --filter db-vercel-postgres",
|
||||
"build:drizzle": "turbo build --filter drizzle",
|
||||
"build:email-nodemailer": "turbo build --filter email-nodemailer",
|
||||
"build:email-resend": "turbo build --filter email-resend",
|
||||
"build:eslint-config": "turbo build --filter eslint-config",
|
||||
"build:db-mongodb": "turbo build --filter \"@payloadcms/db-mongodb\"",
|
||||
"build:db-postgres": "turbo build --filter \"@payloadcms/db-postgres\"",
|
||||
"build:db-sqlite": "turbo build --filter \"@payloadcms/db-sqlite\"",
|
||||
"build:db-vercel-postgres": "turbo build --filter \"@payloadcms/db-vercel-postgres\"",
|
||||
"build:drizzle": "turbo build --filter \"@payloadcms/drizzle\"",
|
||||
"build:email-nodemailer": "turbo build --filter \"@payloadcms/email-nodemailer\"",
|
||||
"build:email-resend": "turbo build --filter \"@payloadcms/email-resend\"",
|
||||
"build:eslint-config": "turbo build --filter \"@payloadcms/eslint-config\"",
|
||||
"build:essentials:force": "pnpm clean:build && turbo build --filter=\"payload...\" --filter=\"@payloadcms/ui\" --filter=\"@payloadcms/next\" --filter=\"@payloadcms/db-mongodb\" --filter=\"@payloadcms/db-postgres\" --filter=\"@payloadcms/richtext-lexical\" --filter=\"@payloadcms/translations\" --filter=\"@payloadcms/plugin-cloud\" --filter=\"@payloadcms/graphql\" --no-cache --force",
|
||||
"build:force": "pnpm run build:core:force",
|
||||
"build:graphql": "turbo build --filter graphql",
|
||||
"build:live-preview": "turbo build --filter live-preview",
|
||||
"build:live-preview-react": "turbo build --filter live-preview-react",
|
||||
"build:live-preview-vue": "turbo build --filter live-preview-vue",
|
||||
"build:graphql": "turbo build --filter \"@payloadcms/graphql\"",
|
||||
"build:live-preview": "turbo build --filter \"@payloadcms/live-preview\"",
|
||||
"build:live-preview-react": "turbo build --filter \"@payloadcms/live-preview-react\"",
|
||||
"build:live-preview-vue": "turbo build --filter \"@payloadcms/live-preview-vue\"",
|
||||
"build:next": "turbo build --filter \"@payloadcms/next\"",
|
||||
"build:payload": "turbo build --filter payload",
|
||||
"build:plugin-cloud": "turbo build --filter plugin-cloud",
|
||||
"build:plugin-cloud-storage": "turbo build --filter plugin-cloud-storage",
|
||||
"build:plugin-form-builder": "turbo build --filter plugin-form-builder",
|
||||
"build:plugin-nested-docs": "turbo build --filter plugin-nested-docs",
|
||||
"build:plugin-redirects": "turbo build --filter plugin-redirects",
|
||||
"build:plugin-relationship-object-ids": "turbo build --filter plugin-relationship-object-ids",
|
||||
"build:plugin-search": "turbo build --filter plugin-search",
|
||||
"build:plugin-sentry": "turbo build --filter plugin-sentry",
|
||||
"build:plugin-seo": "turbo build --filter plugin-seo",
|
||||
"build:plugin-stripe": "turbo build --filter plugin-stripe",
|
||||
"build:plugin-cloud": "turbo build --filter \"@payloadcms/plugin-cloud\"",
|
||||
"build:plugin-cloud-storage": "turbo build --filter \"@payloadcms/plugin-cloud-storage\"",
|
||||
"build:plugin-form-builder": "turbo build --filter \"@payloadcms/plugin-form-builder\"",
|
||||
"build:plugin-nested-docs": "turbo build --filter \"@payloadcms/plugin-nested-docs\"",
|
||||
"build:plugin-redirects": "turbo build --filter \"@payloadcms/plugin-redirects\"",
|
||||
"build:plugin-relationship-object-ids": "turbo build --filter \"@payloadcms/plugin-relationship-object-ids\"",
|
||||
"build:plugin-search": "turbo build --filter \"@payloadcms/plugin-search\"",
|
||||
"build:plugin-sentry": "turbo build --filter \"@payloadcms/plugin-sentry\"",
|
||||
"build:plugin-seo": "turbo build --filter \"@payloadcms/plugin-seo\"",
|
||||
"build:plugin-stripe": "turbo build --filter \"@payloadcms/plugin-stripe\"",
|
||||
"build:plugins": "turbo build --filter \"@payloadcms/plugin-*\"",
|
||||
"build:richtext-lexical": "turbo build --filter richtext-lexical",
|
||||
"build:richtext-slate": "turbo build --filter richtext-slate",
|
||||
"build:storage-azure": "turbo build --filter storage-azure",
|
||||
"build:storage-gcs": "turbo build --filter storage-gcs",
|
||||
"build:storage-s3": "turbo build --filter storage-s3",
|
||||
"build:storage-uploadthing": "turbo build --filter storage-uploadthing",
|
||||
"build:storage-vercel-blob": "turbo build --filter storage-vercel-blob",
|
||||
"build:richtext-lexical": "turbo build --filter \"@payloadcms/richtext-lexical\"",
|
||||
"build:richtext-slate": "turbo build --filter \"@payloadcms/richtext-slate\"",
|
||||
"build:storage-azure": "turbo build --filter \"@payloadcms/storage-azure\"",
|
||||
"build:storage-gcs": "turbo build --filter \"@payloadcms/storage-gcs\"",
|
||||
"build:storage-s3": "turbo build --filter \"@payloadcms/storage-s3\"",
|
||||
"build:storage-uploadthing": "turbo build --filter \"@payloadcms/storage-uploadthing\"",
|
||||
"build:storage-vercel-blob": "turbo build --filter \"@payloadcms/storage-vercel-blob\"",
|
||||
"build:tests": "pnpm --filter payload-test-suite run typecheck",
|
||||
"build:translations": "turbo build --filter translations",
|
||||
"build:ui": "turbo build --filter ui",
|
||||
"build:translations": "turbo build --filter \"@payloadcms/translations\"",
|
||||
"build:ui": "turbo build --filter \"@payloadcms/ui\"",
|
||||
"clean": "turbo clean",
|
||||
"clean:all": "node ./scripts/delete-recursively.js '@node_modules' 'media/*' '**/dist/' '**/.cache/*' '**/.next/*' '**/.turbo/*' '**/tsconfig.tsbuildinfo' '**/payload*.tgz' '**/meta_*.json'",
|
||||
"clean:build": "node ./scripts/delete-recursively.js 'media/' '**/dist/' '**/.cache/' '**/.next/' '**/.turbo/' '**/tsconfig.tsbuildinfo' '**/payload*.tgz' '**/meta_*.json'",
|
||||
@@ -64,10 +64,10 @@
|
||||
"docker:restart": "pnpm docker:stop --remove-orphans && pnpm docker:start",
|
||||
"docker:start": "docker compose -f packages/plugin-cloud-storage/docker-compose.yml up -d",
|
||||
"docker:stop": "docker compose -f packages/plugin-cloud-storage/docker-compose.yml down",
|
||||
"fix": "eslint \"packages/**/*.ts\" --fix",
|
||||
"force:build": "pnpm run build:core:force",
|
||||
"lint": "eslint \"packages/**/*.ts\"",
|
||||
"lint": "turbo run lint --concurrency 1 --continue",
|
||||
"lint-staged": "lint-staged",
|
||||
"lint:fix": "turbo run lint:fix --concurrency 1 --continue",
|
||||
"obliterate-playwright-cache-macos": "rm -rf ~/Library/Caches/ms-playwright && find /System/Volumes/Data/private/var/folders -type d -name 'playwright*' -exec rm -rf {} +",
|
||||
"prepare": "husky",
|
||||
"reinstall": "pnpm clean:all && pnpm install",
|
||||
@@ -159,7 +159,7 @@
|
||||
"swc-plugin-transform-remove-imports": "1.15.0",
|
||||
"tempy": "1.0.1",
|
||||
"tsx": "4.17.0",
|
||||
"turbo": "^2.0.14",
|
||||
"turbo": "^2.1.0",
|
||||
"typescript": "5.5.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-payload-app",
|
||||
"version": "3.0.0-beta.91",
|
||||
"version": "3.0.0-beta.96",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -42,6 +42,8 @@
|
||||
"build": "pnpm pack-template-files && pnpm typecheck && pnpm build:swc",
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"pack-template-files": "node --no-deprecation --import @swc-node/register/esm-register src/scripts/pack-template-files.ts",
|
||||
"prepublishOnly": "pnpm clean && pnpm build",
|
||||
"test": "jest",
|
||||
|
||||
@@ -14,6 +14,7 @@ import { getValidTemplates } from './templates.js'
|
||||
describe('createProject', () => {
|
||||
let projectDir: string
|
||||
beforeAll(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log = jest.fn()
|
||||
})
|
||||
|
||||
@@ -57,7 +58,7 @@ describe('createProject', () => {
|
||||
const packageJson = fse.readJsonSync(packageJsonPath)
|
||||
|
||||
// Check package name and description
|
||||
expect(packageJson.name).toEqual(projectName)
|
||||
expect(packageJson.name).toStrictEqual(projectName)
|
||||
})
|
||||
|
||||
describe('creates project from template', () => {
|
||||
@@ -115,10 +116,6 @@ describe('createProject', () => {
|
||||
})
|
||||
)?.[0]
|
||||
|
||||
if (!payloadConfigPath) {
|
||||
throw new Error(`Could not find payload.config.ts inside ${projectDir}`)
|
||||
}
|
||||
|
||||
const content = fse.readFileSync(payloadConfigPath, 'utf-8')
|
||||
|
||||
// Check payload.config.ts
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { CompilerOptions } from 'typescript'
|
||||
|
||||
import * as p from '@clack/prompts'
|
||||
import { parse, stringify } from 'comment-json'
|
||||
import execa from 'execa'
|
||||
import fs from 'fs'
|
||||
import fse from 'fs-extra'
|
||||
import globby from 'globby'
|
||||
@@ -53,8 +52,7 @@ export async function initNext(args: InitNextArgs): Promise<InitNextResult> {
|
||||
nextAppDetails.nextAppDir = createdAppDir
|
||||
}
|
||||
|
||||
const { hasTopLevelLayout, isPayloadInstalled, isSrcDir, nextAppDir, nextConfigType } =
|
||||
nextAppDetails
|
||||
const { hasTopLevelLayout, isSrcDir, nextAppDir, nextConfigType } = nextAppDetails
|
||||
|
||||
if (!nextConfigType) {
|
||||
return {
|
||||
@@ -169,7 +167,9 @@ async function installAndConfigurePayload(
|
||||
}
|
||||
|
||||
const logDebug = (message: string) => {
|
||||
if (debug) origDebug(message)
|
||||
if (debug) {
|
||||
origDebug(message)
|
||||
}
|
||||
}
|
||||
|
||||
if (!fs.existsSync(projectDir)) {
|
||||
@@ -210,7 +210,7 @@ async function installAndConfigurePayload(
|
||||
)
|
||||
|
||||
// This is a little clunky and needs to account for isSrcDir
|
||||
copyRecursiveSync(templateSrcDir, path.dirname(nextConfigPath), debug)
|
||||
copyRecursiveSync(templateSrcDir, path.dirname(nextConfigPath))
|
||||
|
||||
// Wrap next.config.js with withPayload
|
||||
await wrapNextConfig({ nextConfigPath, nextConfigType })
|
||||
|
||||
@@ -4,13 +4,19 @@ import slugify from '@sindresorhus/slugify'
|
||||
import type { CliArgs } from '../types.js'
|
||||
|
||||
export async function parseProjectName(args: CliArgs): Promise<string> {
|
||||
if (args['--name']) return slugify(args['--name'])
|
||||
if (args._[0]) return slugify(args._[0])
|
||||
if (args['--name']) {
|
||||
return slugify(args['--name'])
|
||||
}
|
||||
if (args._[0]) {
|
||||
return slugify(args._[0])
|
||||
}
|
||||
|
||||
const projectName = await p.text({
|
||||
message: 'Project name?',
|
||||
validate: (value) => {
|
||||
if (!value) return 'Please enter a project name.'
|
||||
if (!value) {
|
||||
return 'Please enter a project name.'
|
||||
}
|
||||
},
|
||||
})
|
||||
if (p.isCancel(projectName)) {
|
||||
|
||||
@@ -9,7 +9,9 @@ export async function parseTemplate(
|
||||
if (args['--template']) {
|
||||
const templateName = args['--template']
|
||||
const template = validTemplates.find((t) => t.name === templateName)
|
||||
if (!template) throw new Error('Invalid template given')
|
||||
if (!template) {
|
||||
throw new Error('Invalid template given')
|
||||
}
|
||||
return template
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,9 @@ export async function selectDb(args: CliArgs, projectName: string): Promise<DbDe
|
||||
value: dbChoice.value,
|
||||
})),
|
||||
})
|
||||
if (p.isCancel(dbType)) process.exit(0)
|
||||
if (p.isCancel(dbType)) {
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
const dbChoice = dbChoiceRecord[dbType]
|
||||
@@ -73,7 +75,9 @@ export async function selectDb(args: CliArgs, projectName: string): Promise<DbDe
|
||||
initialValue: initialDbUri,
|
||||
message: `Enter ${dbChoice.title.split(' ')[0]} connection string`, // strip beta from title
|
||||
})
|
||||
if (p.isCancel(dbUri)) process.exit(0)
|
||||
if (p.isCancel(dbUri)) {
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -16,7 +16,9 @@ import { installPackages } from './install-packages.js'
|
||||
export async function updatePayloadInProject(
|
||||
appDetails: NextAppDetails,
|
||||
): Promise<{ message: string; success: boolean }> {
|
||||
if (!appDetails.nextConfigPath) return { message: 'No Next.js config found', success: false }
|
||||
if (!appDetails.nextConfigPath) {
|
||||
return { message: 'No Next.js config found', success: false }
|
||||
}
|
||||
|
||||
const projectDir = path.dirname(appDetails.nextConfigPath)
|
||||
|
||||
|
||||
@@ -42,8 +42,6 @@ export async function parseAndModifyConfigContent(
|
||||
): Promise<{ modifiedConfigContent: string; success: boolean }> {
|
||||
content = withPayloadStatement[configType] + '\n' + content
|
||||
|
||||
console.log({ configType, content })
|
||||
|
||||
if (configType === 'cjs' || configType === 'esm') {
|
||||
try {
|
||||
const ast = parseModule(content, { loc: true })
|
||||
|
||||
@@ -36,7 +36,9 @@ export async function writeEnvFile(args: {
|
||||
.split('\n')
|
||||
.filter((e) => e)
|
||||
.map((line) => {
|
||||
if (line.startsWith('#') || !line.includes('=')) return line
|
||||
if (line.startsWith('#') || !line.includes('=')) {
|
||||
return line
|
||||
}
|
||||
|
||||
const split = line.split('=')
|
||||
const key = split[0]
|
||||
|
||||
@@ -6,7 +6,7 @@ import path from 'path'
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function copyRecursiveSync(src: string, dest: string, debug?: boolean) {
|
||||
export function copyRecursiveSync(src: string, dest: string) {
|
||||
const exists = fs.existsSync(src)
|
||||
const stats = exists && fs.statSync(src)
|
||||
const isDirectory = exists && stats !== false && stats.isDirectory()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-mongodb",
|
||||
"version": "3.0.0-beta.91",
|
||||
"version": "3.0.0-beta.96",
|
||||
"description": "The officially supported MongoDB database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
@@ -30,6 +30,8 @@
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc-build --strip-leading-paths",
|
||||
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"prepublishOnly": "pnpm clean && pnpm turbo build"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -59,8 +59,10 @@ export const connect: Connect = async function connect(
|
||||
await this.migrate({ migrations: this.prodMigrations })
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
this.payload.logger.error(`Error: cannot connect to MongoDB. Details: ${err.message}`, err)
|
||||
this.payload.logger.error({
|
||||
err,
|
||||
msg: `Error: cannot connect to MongoDB. Details: ${err.message}`,
|
||||
})
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { CreateGlobal, PayloadRequest } from 'payload'
|
||||
|
||||
import type { MongooseAdapter } from './index.js'
|
||||
|
||||
import sanitizeInternalFields from './utilities/sanitizeInternalFields.js'
|
||||
import { sanitizeInternalFields } from './utilities/sanitizeInternalFields.js'
|
||||
import { withSession } from './withSession.js'
|
||||
|
||||
export const createGlobal: CreateGlobal = async function createGlobal(
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { DeleteOne, Document, PayloadRequest } from 'payload'
|
||||
|
||||
import type { MongooseAdapter } from './index.js'
|
||||
|
||||
import sanitizeInternalFields from './utilities/sanitizeInternalFields.js'
|
||||
import { sanitizeInternalFields } from './utilities/sanitizeInternalFields.js'
|
||||
import { withSession } from './withSession.js'
|
||||
|
||||
export const deleteOne: DeleteOne = async function deleteOne(
|
||||
|
||||
@@ -6,7 +6,7 @@ import { flattenWhereToOperators } from 'payload'
|
||||
import type { MongooseAdapter } from './index.js'
|
||||
|
||||
import { buildSortParam } from './queries/buildSortParam.js'
|
||||
import sanitizeInternalFields from './utilities/sanitizeInternalFields.js'
|
||||
import { sanitizeInternalFields } from './utilities/sanitizeInternalFields.js'
|
||||
import { withSession } from './withSession.js'
|
||||
|
||||
export const find: Find = async function find(
|
||||
|
||||
@@ -4,7 +4,7 @@ import { combineQueries } from 'payload'
|
||||
|
||||
import type { MongooseAdapter } from './index.js'
|
||||
|
||||
import sanitizeInternalFields from './utilities/sanitizeInternalFields.js'
|
||||
import { sanitizeInternalFields } from './utilities/sanitizeInternalFields.js'
|
||||
import { withSession } from './withSession.js'
|
||||
|
||||
export const findGlobal: FindGlobal = async function findGlobal(
|
||||
|
||||
@@ -6,7 +6,7 @@ import { buildVersionGlobalFields, flattenWhereToOperators } from 'payload'
|
||||
import type { MongooseAdapter } from './index.js'
|
||||
|
||||
import { buildSortParam } from './queries/buildSortParam.js'
|
||||
import sanitizeInternalFields from './utilities/sanitizeInternalFields.js'
|
||||
import { sanitizeInternalFields } from './utilities/sanitizeInternalFields.js'
|
||||
import { withSession } from './withSession.js'
|
||||
|
||||
export const findGlobalVersions: FindGlobalVersions = async function findGlobalVersions(
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { Document, FindOne, PayloadRequest } from 'payload'
|
||||
|
||||
import type { MongooseAdapter } from './index.js'
|
||||
|
||||
import sanitizeInternalFields from './utilities/sanitizeInternalFields.js'
|
||||
import { sanitizeInternalFields } from './utilities/sanitizeInternalFields.js'
|
||||
import { withSession } from './withSession.js'
|
||||
|
||||
export const findOne: FindOne = async function findOne(
|
||||
|
||||
@@ -6,7 +6,7 @@ import { flattenWhereToOperators } from 'payload'
|
||||
import type { MongooseAdapter } from './index.js'
|
||||
|
||||
import { buildSortParam } from './queries/buildSortParam.js'
|
||||
import sanitizeInternalFields from './utilities/sanitizeInternalFields.js'
|
||||
import { sanitizeInternalFields } from './utilities/sanitizeInternalFields.js'
|
||||
import { withSession } from './withSession.js'
|
||||
|
||||
export const findVersions: FindVersions = async function findVersions(
|
||||
|
||||
@@ -8,10 +8,10 @@ import { buildVersionCollectionFields, buildVersionGlobalFields } from 'payload'
|
||||
import type { MongooseAdapter } from './index.js'
|
||||
import type { CollectionModel } from './types.js'
|
||||
|
||||
import buildCollectionSchema from './models/buildCollectionSchema.js'
|
||||
import { buildCollectionSchema } from './models/buildCollectionSchema.js'
|
||||
import { buildGlobalModel } from './models/buildGlobalModel.js'
|
||||
import buildSchema from './models/buildSchema.js'
|
||||
import getBuildQueryPlugin from './queries/buildQuery.js'
|
||||
import { buildSchema } from './models/buildSchema.js'
|
||||
import { getBuildQueryPlugin } from './queries/buildQuery.js'
|
||||
import { getDBName } from './utilities/getDBName.js'
|
||||
|
||||
export const init: Init = function init(this: MongooseAdapter) {
|
||||
|
||||
@@ -3,10 +3,10 @@ import type { SanitizedCollectionConfig, SanitizedConfig } from 'payload'
|
||||
|
||||
import paginate from 'mongoose-paginate-v2'
|
||||
|
||||
import getBuildQueryPlugin from '../queries/buildQuery.js'
|
||||
import buildSchema from './buildSchema.js'
|
||||
import { getBuildQueryPlugin } from '../queries/buildQuery.js'
|
||||
import { buildSchema } from './buildSchema.js'
|
||||
|
||||
const buildCollectionSchema = (
|
||||
export const buildCollectionSchema = (
|
||||
collection: SanitizedCollectionConfig,
|
||||
config: SanitizedConfig,
|
||||
schemaOptions = {},
|
||||
@@ -44,5 +44,3 @@ const buildCollectionSchema = (
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
export default buildCollectionSchema
|
||||
|
||||
@@ -4,8 +4,8 @@ import mongoose from 'mongoose'
|
||||
|
||||
import type { GlobalModel } from '../types.js'
|
||||
|
||||
import getBuildQueryPlugin from '../queries/buildQuery.js'
|
||||
import buildSchema from './buildSchema.js'
|
||||
import { getBuildQueryPlugin } from '../queries/buildQuery.js'
|
||||
import { buildSchema } from './buildSchema.js'
|
||||
|
||||
export const buildGlobalModel = (config: SanitizedConfig): GlobalModel | null => {
|
||||
if (config.globals && config.globals.length > 0) {
|
||||
|
||||
@@ -111,7 +111,7 @@ const localizeSchema = (
|
||||
return schema
|
||||
}
|
||||
|
||||
const buildSchema = (
|
||||
export const buildSchema = (
|
||||
config: SanitizedConfig,
|
||||
configFields: Field[],
|
||||
buildSchemaOptions: BuildSchemaOptions = {},
|
||||
@@ -669,5 +669,3 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
export default buildSchema
|
||||
|
||||
@@ -18,7 +18,10 @@ export type BuildQueryArgs = {
|
||||
|
||||
// This plugin asynchronously builds a list of Mongoose query constraints
|
||||
// which can then be used in subsequent Mongoose queries.
|
||||
const getBuildQueryPlugin = ({ collectionSlug, versionsFields }: GetBuildQueryPluginArgs = {}) => {
|
||||
export const getBuildQueryPlugin = ({
|
||||
collectionSlug,
|
||||
versionsFields,
|
||||
}: GetBuildQueryPluginArgs = {}) => {
|
||||
return function buildQueryPlugin(schema) {
|
||||
const modifiedSchema = schema
|
||||
async function buildQuery({
|
||||
@@ -57,5 +60,3 @@ const getBuildQueryPlugin = ({ collectionSlug, versionsFields }: GetBuildQueryPl
|
||||
modifiedSchema.statics.buildQuery = buildQuery
|
||||
}
|
||||
}
|
||||
|
||||
export default getBuildQueryPlugin
|
||||
|
||||
@@ -16,7 +16,7 @@ describe('get localized sort property', () => {
|
||||
},
|
||||
} as Config)
|
||||
})
|
||||
it('passes through a non-localized sort property', async () => {
|
||||
it('passes through a non-localized sort property', () => {
|
||||
const result = getLocalizedSortProperty({
|
||||
config,
|
||||
fields: [
|
||||
|
||||
@@ -6,7 +6,7 @@ import { combineQueries, flattenWhereToOperators } from 'payload'
|
||||
import type { MongooseAdapter } from './index.js'
|
||||
|
||||
import { buildSortParam } from './queries/buildSortParam.js'
|
||||
import sanitizeInternalFields from './utilities/sanitizeInternalFields.js'
|
||||
import { sanitizeInternalFields } from './utilities/sanitizeInternalFields.js'
|
||||
import { withSession } from './withSession.js'
|
||||
|
||||
export const queryDrafts: QueryDrafts = async function queryDrafts(
|
||||
|
||||
@@ -6,6 +6,8 @@ import { v4 as uuid } from 'uuid'
|
||||
|
||||
import type { MongooseAdapter } from '../index.js'
|
||||
|
||||
// Needs await to fulfill the interface
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
export const beginTransaction: BeginTransaction = async function beginTransaction(
|
||||
this: MongooseAdapter,
|
||||
options: TransactionOptions,
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { PayloadRequest, UpdateGlobal } from 'payload'
|
||||
|
||||
import type { MongooseAdapter } from './index.js'
|
||||
|
||||
import sanitizeInternalFields from './utilities/sanitizeInternalFields.js'
|
||||
import { sanitizeInternalFields } from './utilities/sanitizeInternalFields.js'
|
||||
import { withSession } from './withSession.js'
|
||||
|
||||
export const updateGlobal: UpdateGlobal = async function updateGlobal(
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { PayloadRequest, UpdateOne } from 'payload'
|
||||
import type { MongooseAdapter } from './index.js'
|
||||
|
||||
import { handleError } from './utilities/handleError.js'
|
||||
import sanitizeInternalFields from './utilities/sanitizeInternalFields.js'
|
||||
import { sanitizeInternalFields } from './utilities/sanitizeInternalFields.js'
|
||||
import { withSession } from './withSession.js'
|
||||
|
||||
export const updateOne: UpdateOne = async function updateOne(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const internalFields = ['__v']
|
||||
|
||||
const sanitizeInternalFields = <T extends Record<string, unknown>>(incomingDoc: T): T =>
|
||||
export const sanitizeInternalFields = <T extends Record<string, unknown>>(incomingDoc: T): T =>
|
||||
Object.entries(incomingDoc).reduce((newDoc, [key, val]): T => {
|
||||
if (key === '_id') {
|
||||
return {
|
||||
@@ -18,5 +18,3 @@ const sanitizeInternalFields = <T extends Record<string, unknown>>(incomingDoc:
|
||||
[key]: val,
|
||||
}
|
||||
}, {} as T)
|
||||
|
||||
export default sanitizeInternalFields
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-postgres",
|
||||
"version": "3.0.0-beta.91",
|
||||
"version": "3.0.0-beta.96",
|
||||
"description": "The officially supported Postgres database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
@@ -40,6 +40,8 @@
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
||||
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"prepack": "pnpm clean && pnpm turbo build",
|
||||
"prepublishOnly": "pnpm clean && pnpm turbo build",
|
||||
"renamePredefinedMigrations": "node --no-deprecation --import @swc-node/register/esm-register ./scripts/renamePredefinedMigrations.ts"
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
.tmp
|
||||
**/.git
|
||||
**/.hg
|
||||
**/.pnp.*
|
||||
**/.svn
|
||||
**/.yarn/**
|
||||
**/build
|
||||
**/dist/**
|
||||
**/node_modules
|
||||
**/temp
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-sqlite",
|
||||
"version": "3.0.0-beta.91",
|
||||
"version": "3.0.0-beta.96",
|
||||
"description": "The officially supported SQLite database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
@@ -39,6 +39,8 @@
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
||||
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"prepack": "pnpm clean && pnpm turbo build",
|
||||
"prepublishOnly": "pnpm clean && pnpm turbo build"
|
||||
},
|
||||
|
||||
@@ -58,9 +58,17 @@ type Args = {
|
||||
tableName: string
|
||||
timestamps?: boolean
|
||||
versions: boolean
|
||||
/**
|
||||
* Tracks whether or not this table is built
|
||||
* from the result of a localized array or block field at some point
|
||||
*/
|
||||
withinLocalizedArrayOrBlock?: boolean
|
||||
}
|
||||
|
||||
type Result = {
|
||||
hasLocalizedManyNumberField: boolean
|
||||
hasLocalizedManyTextField: boolean
|
||||
hasLocalizedRelationshipField: boolean
|
||||
hasManyNumberField: 'index' | boolean
|
||||
hasManyTextField: 'index' | boolean
|
||||
relationsToBuild: RelationMap
|
||||
@@ -81,6 +89,7 @@ export const buildTable = ({
|
||||
tableName,
|
||||
timestamps,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
}: Args): Result => {
|
||||
const isRoot = !incomingRootTableName
|
||||
const rootTableName = incomingRootTableName || tableName
|
||||
@@ -128,6 +137,7 @@ export const buildTable = ({
|
||||
rootTableIDColType: rootTableIDColType || idColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
})
|
||||
|
||||
// split the relationsToBuild by localized and non-localized
|
||||
@@ -478,5 +488,12 @@ export const buildTable = ({
|
||||
return result
|
||||
})
|
||||
|
||||
return { hasManyNumberField, hasManyTextField, relationsToBuild }
|
||||
return {
|
||||
hasLocalizedManyNumberField,
|
||||
hasLocalizedManyTextField,
|
||||
hasLocalizedRelationshipField,
|
||||
hasManyNumberField,
|
||||
hasManyTextField,
|
||||
relationsToBuild,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,11 @@ type Args = {
|
||||
rootTableIDColType: IDType
|
||||
rootTableName: string
|
||||
versions: boolean
|
||||
/**
|
||||
* Tracks whether or not this table is built
|
||||
* from the result of a localized array or block field at some point
|
||||
*/
|
||||
withinLocalizedArrayOrBlock?: boolean
|
||||
}
|
||||
|
||||
type Result = {
|
||||
@@ -84,6 +89,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
}: Args): Result => {
|
||||
let hasLocalizedField = false
|
||||
let hasLocalizedRelationshipField = false
|
||||
@@ -150,7 +156,11 @@ export const traverseFields = ({
|
||||
switch (field.type) {
|
||||
case 'text': {
|
||||
if (field.hasMany) {
|
||||
if (field.localized) {
|
||||
const isLocalized =
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
|
||||
if (isLocalized) {
|
||||
hasLocalizedManyTextField = true
|
||||
}
|
||||
|
||||
@@ -179,7 +189,11 @@ export const traverseFields = ({
|
||||
|
||||
case 'number': {
|
||||
if (field.hasMany) {
|
||||
if (field.localized) {
|
||||
const isLocalized =
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
|
||||
if (isLocalized) {
|
||||
hasLocalizedManyNumberField = true
|
||||
}
|
||||
|
||||
@@ -255,7 +269,11 @@ export const traverseFields = ({
|
||||
parentIdx: (cols) => index(`${selectTableName}_parent_idx`).on(cols.parent),
|
||||
}
|
||||
|
||||
if (field.localized) {
|
||||
const isLocalized =
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
|
||||
if (isLocalized) {
|
||||
baseColumns.locale = text('locale', { enum: locales }).notNull()
|
||||
baseExtraConfig.localeIdx = (cols) =>
|
||||
index(`${selectTableName}_locale_idx`).on(cols.locale)
|
||||
@@ -337,13 +355,20 @@ export const traverseFields = ({
|
||||
_parentIDIdx: (cols) => index(`${arrayTableName}_parent_id_idx`).on(cols._parentID),
|
||||
}
|
||||
|
||||
if (field.localized && adapter.payload.config.localization) {
|
||||
const isLocalized =
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
|
||||
if (isLocalized) {
|
||||
baseColumns._locale = text('_locale', { enum: locales }).notNull()
|
||||
baseExtraConfig._localeIdx = (cols) =>
|
||||
index(`${arrayTableName}_locale_idx`).on(cols._locale)
|
||||
}
|
||||
|
||||
const {
|
||||
hasLocalizedManyNumberField: subHasLocalizedManyNumberField,
|
||||
hasLocalizedManyTextField: subHasLocalizedManyTextField,
|
||||
hasLocalizedRelationshipField: subHasLocalizedRelationshipField,
|
||||
hasManyNumberField: subHasManyNumberField,
|
||||
hasManyTextField: subHasManyTextField,
|
||||
relationsToBuild: subRelationsToBuild,
|
||||
@@ -360,8 +385,21 @@ export const traverseFields = ({
|
||||
rootTableName,
|
||||
tableName: arrayTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock: isLocalized,
|
||||
})
|
||||
|
||||
if (subHasLocalizedManyNumberField) {
|
||||
hasLocalizedManyNumberField = subHasLocalizedManyNumberField
|
||||
}
|
||||
|
||||
if (subHasLocalizedRelationshipField) {
|
||||
hasLocalizedRelationshipField = subHasLocalizedRelationshipField
|
||||
}
|
||||
|
||||
if (subHasLocalizedManyTextField) {
|
||||
hasLocalizedManyTextField = subHasLocalizedManyTextField
|
||||
}
|
||||
|
||||
if (subHasManyTextField) {
|
||||
if (!hasManyTextField || subHasManyTextField === 'index')
|
||||
hasManyTextField = subHasManyTextField
|
||||
@@ -453,13 +491,20 @@ export const traverseFields = ({
|
||||
_pathIdx: (cols) => index(`${blockTableName}_path_idx`).on(cols._path),
|
||||
}
|
||||
|
||||
if (field.localized && adapter.payload.config.localization) {
|
||||
const isLocalized =
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
|
||||
if (isLocalized) {
|
||||
baseColumns._locale = text('_locale', { enum: locales }).notNull()
|
||||
baseExtraConfig._localeIdx = (cols) =>
|
||||
index(`${blockTableName}_locale_idx`).on(cols._locale)
|
||||
}
|
||||
|
||||
const {
|
||||
hasLocalizedManyNumberField: subHasLocalizedManyNumberField,
|
||||
hasLocalizedManyTextField: subHasLocalizedManyTextField,
|
||||
hasLocalizedRelationshipField: subHasLocalizedRelationshipField,
|
||||
hasManyNumberField: subHasManyNumberField,
|
||||
hasManyTextField: subHasManyTextField,
|
||||
relationsToBuild: subRelationsToBuild,
|
||||
@@ -476,8 +521,21 @@ export const traverseFields = ({
|
||||
rootTableName,
|
||||
tableName: blockTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock: isLocalized,
|
||||
})
|
||||
|
||||
if (subHasLocalizedManyNumberField) {
|
||||
hasLocalizedManyNumberField = subHasLocalizedManyNumberField
|
||||
}
|
||||
|
||||
if (subHasLocalizedRelationshipField) {
|
||||
hasLocalizedRelationshipField = subHasLocalizedRelationshipField
|
||||
}
|
||||
|
||||
if (subHasLocalizedManyTextField) {
|
||||
hasLocalizedManyTextField = subHasLocalizedManyTextField
|
||||
}
|
||||
|
||||
if (subHasManyTextField) {
|
||||
if (!hasManyTextField || subHasManyTextField === 'index')
|
||||
hasManyTextField = subHasManyTextField
|
||||
@@ -577,6 +635,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
})
|
||||
|
||||
if (groupHasLocalizedField) hasLocalizedField = true
|
||||
@@ -618,6 +677,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
})
|
||||
|
||||
if (groupHasLocalizedField) hasLocalizedField = true
|
||||
@@ -660,6 +720,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
})
|
||||
|
||||
if (tabHasLocalizedField) hasLocalizedField = true
|
||||
@@ -702,6 +763,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
})
|
||||
|
||||
if (rowHasLocalizedField) hasLocalizedField = true
|
||||
@@ -753,7 +815,10 @@ export const traverseFields = ({
|
||||
}
|
||||
break
|
||||
}
|
||||
if (adapter.payload.config.localization && field.localized) {
|
||||
if (
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
) {
|
||||
hasLocalizedRelationshipField = true
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-vercel-postgres",
|
||||
"version": "3.0.0-beta.91",
|
||||
"version": "3.0.0-beta.96",
|
||||
"description": "Vercel Postgres adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
@@ -40,6 +40,8 @@
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
||||
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"prepack": "pnpm clean && pnpm turbo build",
|
||||
"prepublishOnly": "pnpm clean && pnpm turbo build",
|
||||
"renamePredefinedMigrations": "node --no-deprecation --import @swc-node/register/esm-register ./scripts/renamePredefinedMigrations.ts"
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
.tmp
|
||||
**/.git
|
||||
**/.hg
|
||||
**/.pnp.*
|
||||
**/.svn
|
||||
**/.yarn/**
|
||||
**/build
|
||||
**/dist/**
|
||||
**/node_modules
|
||||
**/temp
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/drizzle",
|
||||
"version": "3.0.0-beta.91",
|
||||
"version": "3.0.0-beta.96",
|
||||
"description": "A library of shared functions used by different payload database adapters",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
@@ -39,6 +39,8 @@
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
||||
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"prepack": "pnpm clean && pnpm turbo build",
|
||||
"prepublishOnly": "pnpm clean && pnpm turbo build"
|
||||
},
|
||||
|
||||
@@ -12,11 +12,11 @@ type BuildFindQueryArgs = {
|
||||
tableName: string
|
||||
}
|
||||
|
||||
export type Result = DBQueryConfig<'many', true, any, any> & {
|
||||
with?: DBQueryConfig<'many', true, any, any> & {
|
||||
export type Result = {
|
||||
with?: {
|
||||
_locales?: DBQueryConfig<'many', true, any, any>
|
||||
}
|
||||
}
|
||||
} & DBQueryConfig<'many', true, any, any>
|
||||
} & DBQueryConfig<'many', true, any, any>
|
||||
|
||||
// Generate the Drizzle query for findMany based on
|
||||
// a collection field structure
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import type { PayloadRequest } from 'payload'
|
||||
|
||||
import {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import type { PayloadRequest } from 'payload'
|
||||
|
||||
import {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import type { PayloadRequest } from 'payload'
|
||||
|
||||
import {
|
||||
|
||||
@@ -30,7 +30,7 @@ export async function migrateStatus(this: DrizzleAdapter): Promise<void> {
|
||||
const existingMigration = existingMigrations.find((m) => m.name === migration.name)
|
||||
return {
|
||||
Name: migration.name,
|
||||
// eslint-disable-next-line perfectionist/sort-objects
|
||||
|
||||
Batch: existingMigration?.batch,
|
||||
Ran: existingMigration ? 'Yes' : 'No',
|
||||
}
|
||||
|
||||
@@ -54,9 +54,17 @@ type Args = {
|
||||
tableName: string
|
||||
timestamps?: boolean
|
||||
versions: boolean
|
||||
/**
|
||||
* Tracks whether or not this table is built
|
||||
* from the result of a localized array or block field at some point
|
||||
*/
|
||||
withinLocalizedArrayOrBlock?: boolean
|
||||
}
|
||||
|
||||
type Result = {
|
||||
hasLocalizedManyNumberField: boolean
|
||||
hasLocalizedManyTextField: boolean
|
||||
hasLocalizedRelationshipField: boolean
|
||||
hasManyNumberField: 'index' | boolean
|
||||
hasManyTextField: 'index' | boolean
|
||||
relationsToBuild: RelationMap
|
||||
@@ -76,6 +84,7 @@ export const buildTable = ({
|
||||
tableName,
|
||||
timestamps,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
}: Args): Result => {
|
||||
const isRoot = !incomingRootTableName
|
||||
const rootTableName = incomingRootTableName || tableName
|
||||
@@ -122,6 +131,7 @@ export const buildTable = ({
|
||||
rootTableIDColType: rootTableIDColType || idColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
})
|
||||
|
||||
// split the relationsToBuild by localized and non-localized
|
||||
@@ -464,5 +474,12 @@ export const buildTable = ({
|
||||
return result
|
||||
})
|
||||
|
||||
return { hasManyNumberField, hasManyTextField, relationsToBuild }
|
||||
return {
|
||||
hasLocalizedManyNumberField,
|
||||
hasLocalizedManyTextField,
|
||||
hasLocalizedRelationshipField,
|
||||
hasManyNumberField,
|
||||
hasManyTextField,
|
||||
relationsToBuild,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,11 @@ type Args = {
|
||||
rootTableIDColType: string
|
||||
rootTableName: string
|
||||
versions: boolean
|
||||
/**
|
||||
* Tracks whether or not this table is built
|
||||
* from the result of a localized array or block field at some point
|
||||
*/
|
||||
withinLocalizedArrayOrBlock?: boolean
|
||||
}
|
||||
|
||||
type Result = {
|
||||
@@ -89,6 +94,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
}: Args): Result => {
|
||||
const throwValidationError = true
|
||||
let hasLocalizedField = false
|
||||
@@ -156,7 +162,11 @@ export const traverseFields = ({
|
||||
switch (field.type) {
|
||||
case 'text': {
|
||||
if (field.hasMany) {
|
||||
if (field.localized) {
|
||||
const isLocalized =
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
|
||||
if (isLocalized) {
|
||||
hasLocalizedManyTextField = true
|
||||
}
|
||||
|
||||
@@ -185,7 +195,11 @@ export const traverseFields = ({
|
||||
|
||||
case 'number': {
|
||||
if (field.hasMany) {
|
||||
if (field.localized) {
|
||||
const isLocalized =
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
|
||||
if (isLocalized) {
|
||||
hasLocalizedManyNumberField = true
|
||||
}
|
||||
|
||||
@@ -276,7 +290,11 @@ export const traverseFields = ({
|
||||
parentIdx: (cols) => index(`${selectTableName}_parent_idx`).on(cols.parent),
|
||||
}
|
||||
|
||||
if (field.localized) {
|
||||
const isLocalized =
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
|
||||
if (isLocalized) {
|
||||
baseColumns.locale = adapter.enums.enum__locales('locale').notNull()
|
||||
baseExtraConfig.localeIdx = (cols) =>
|
||||
index(`${selectTableName}_locale_idx`).on(cols.locale)
|
||||
@@ -354,13 +372,20 @@ export const traverseFields = ({
|
||||
_parentIDIdx: (cols) => index(`${arrayTableName}_parent_id_idx`).on(cols._parentID),
|
||||
}
|
||||
|
||||
if (field.localized && adapter.payload.config.localization) {
|
||||
const isLocalized =
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
|
||||
if (isLocalized) {
|
||||
baseColumns._locale = adapter.enums.enum__locales('_locale').notNull()
|
||||
baseExtraConfig._localeIdx = (cols) =>
|
||||
index(`${arrayTableName}_locale_idx`).on(cols._locale)
|
||||
}
|
||||
|
||||
const {
|
||||
hasLocalizedManyNumberField: subHasLocalizedManyNumberField,
|
||||
hasLocalizedManyTextField: subHasLocalizedManyTextField,
|
||||
hasLocalizedRelationshipField: subHasLocalizedRelationshipField,
|
||||
hasManyNumberField: subHasManyNumberField,
|
||||
hasManyTextField: subHasManyTextField,
|
||||
relationsToBuild: subRelationsToBuild,
|
||||
@@ -377,8 +402,21 @@ export const traverseFields = ({
|
||||
rootTableName,
|
||||
tableName: arrayTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock: isLocalized,
|
||||
})
|
||||
|
||||
if (subHasLocalizedManyNumberField) {
|
||||
hasLocalizedManyNumberField = subHasLocalizedManyNumberField
|
||||
}
|
||||
|
||||
if (subHasLocalizedRelationshipField) {
|
||||
hasLocalizedRelationshipField = subHasLocalizedRelationshipField
|
||||
}
|
||||
|
||||
if (subHasLocalizedManyTextField) {
|
||||
hasLocalizedManyTextField = subHasLocalizedManyTextField
|
||||
}
|
||||
|
||||
if (subHasManyTextField) {
|
||||
if (!hasManyTextField || subHasManyTextField === 'index')
|
||||
hasManyTextField = subHasManyTextField
|
||||
@@ -466,13 +504,20 @@ export const traverseFields = ({
|
||||
_pathIdx: (cols) => index(`${blockTableName}_path_idx`).on(cols._path),
|
||||
}
|
||||
|
||||
if (field.localized && adapter.payload.config.localization) {
|
||||
const isLocalized =
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
|
||||
if (isLocalized) {
|
||||
baseColumns._locale = adapter.enums.enum__locales('_locale').notNull()
|
||||
baseExtraConfig._localeIdx = (cols) =>
|
||||
index(`${blockTableName}_locale_idx`).on(cols._locale)
|
||||
}
|
||||
|
||||
const {
|
||||
hasLocalizedManyNumberField: subHasLocalizedManyNumberField,
|
||||
hasLocalizedManyTextField: subHasLocalizedManyTextField,
|
||||
hasLocalizedRelationshipField: subHasLocalizedRelationshipField,
|
||||
hasManyNumberField: subHasManyNumberField,
|
||||
hasManyTextField: subHasManyTextField,
|
||||
relationsToBuild: subRelationsToBuild,
|
||||
@@ -489,8 +534,21 @@ export const traverseFields = ({
|
||||
rootTableName,
|
||||
tableName: blockTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock: isLocalized,
|
||||
})
|
||||
|
||||
if (subHasLocalizedManyNumberField) {
|
||||
hasLocalizedManyNumberField = subHasLocalizedManyNumberField
|
||||
}
|
||||
|
||||
if (subHasLocalizedRelationshipField) {
|
||||
hasLocalizedRelationshipField = subHasLocalizedRelationshipField
|
||||
}
|
||||
|
||||
if (subHasLocalizedManyTextField) {
|
||||
hasLocalizedManyTextField = subHasLocalizedManyTextField
|
||||
}
|
||||
|
||||
if (subHasManyTextField) {
|
||||
if (!hasManyTextField || subHasManyTextField === 'index')
|
||||
hasManyTextField = subHasManyTextField
|
||||
@@ -589,6 +647,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
})
|
||||
|
||||
if (groupHasLocalizedField) hasLocalizedField = true
|
||||
@@ -629,6 +688,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
})
|
||||
|
||||
if (groupHasLocalizedField) hasLocalizedField = true
|
||||
@@ -670,6 +730,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
})
|
||||
|
||||
if (tabHasLocalizedField) hasLocalizedField = true
|
||||
@@ -711,6 +772,7 @@ export const traverseFields = ({
|
||||
rootTableIDColType,
|
||||
rootTableName,
|
||||
versions,
|
||||
withinLocalizedArrayOrBlock,
|
||||
})
|
||||
|
||||
if (rowHasLocalizedField) hasLocalizedField = true
|
||||
@@ -761,7 +823,11 @@ export const traverseFields = ({
|
||||
}
|
||||
break
|
||||
}
|
||||
if (adapter.payload.config.localization && field.localized) {
|
||||
|
||||
if (
|
||||
Boolean(field.localized && adapter.payload.config.localization) ||
|
||||
withinLocalizedArrayOrBlock
|
||||
) {
|
||||
hasLocalizedRelationshipField = true
|
||||
}
|
||||
|
||||
|
||||
@@ -28,11 +28,10 @@ export async function buildAndOrConditions({
|
||||
const completedConditions = []
|
||||
// Loop over all AND / OR operations and add them to the AND / OR query param
|
||||
// Operations should come through as an array
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
|
||||
for (const condition of where) {
|
||||
// If the operation is properly formatted as an object
|
||||
if (typeof condition === 'object') {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const result = await parseParams({
|
||||
adapter,
|
||||
fields,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import type { SQL } from 'drizzle-orm'
|
||||
import type { Field, Operator, Where } from 'payload'
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { ChainedMethods } from '../find/chainMethods.js'
|
||||
import type {
|
||||
DrizzleAdapter,
|
||||
DrizzleTransaction,
|
||||
GenericColumn,
|
||||
GenericPgColumn,
|
||||
TransactionPg,
|
||||
TransactionSQLite,
|
||||
@@ -12,7 +13,6 @@ import type {
|
||||
import type { BuildQueryJoinAliases } from './buildQuery.js'
|
||||
|
||||
import { chainMethods } from '../find/chainMethods.js'
|
||||
import { type GenericColumn } from '../types.js'
|
||||
|
||||
type Args = {
|
||||
adapter: DrizzleAdapter
|
||||
@@ -35,7 +35,7 @@ export const selectDistinct = ({
|
||||
selectFields,
|
||||
tableName,
|
||||
where,
|
||||
}: Args): QueryPromise<Record<string, GenericColumn> & { id: number | string }[]> => {
|
||||
}: Args): QueryPromise<{ id: number | string }[] & Record<string, GenericColumn>> => {
|
||||
if (Object.keys(joins).length > 0) {
|
||||
if (where) {
|
||||
chainedMethods.push({ args: [where], method: 'where' })
|
||||
|
||||
@@ -35,7 +35,6 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(
|
||||
return {
|
||||
...result,
|
||||
docs: result.docs.map((doc) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
doc = {
|
||||
id: doc.parent,
|
||||
...doc.version,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { NumberField } from 'payload'
|
||||
|
||||
type Args = {
|
||||
@@ -6,10 +5,29 @@ type Args = {
|
||||
locale?: string
|
||||
numberRows: Record<string, unknown>[]
|
||||
ref: Record<string, unknown>
|
||||
withinArrayOrBlockLocale?: string
|
||||
}
|
||||
|
||||
export const transformHasManyNumber = ({ field, locale, numberRows, ref }: Args) => {
|
||||
const result = numberRows.map(({ number }) => number)
|
||||
export const transformHasManyNumber = ({
|
||||
field,
|
||||
locale,
|
||||
numberRows,
|
||||
ref,
|
||||
withinArrayOrBlockLocale,
|
||||
}: Args) => {
|
||||
let result: unknown[]
|
||||
|
||||
if (withinArrayOrBlockLocale) {
|
||||
result = numberRows.reduce((acc, { locale, number }) => {
|
||||
if (locale === withinArrayOrBlockLocale) {
|
||||
acc.push(number)
|
||||
}
|
||||
|
||||
return acc
|
||||
}, [])
|
||||
} else {
|
||||
result = numberRows.map(({ number }) => number)
|
||||
}
|
||||
|
||||
if (locale) {
|
||||
ref[field.name][locale] = result
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { TextField } from 'payload'
|
||||
|
||||
type Args = {
|
||||
@@ -6,10 +5,29 @@ type Args = {
|
||||
locale?: string
|
||||
ref: Record<string, unknown>
|
||||
textRows: Record<string, unknown>[]
|
||||
withinArrayOrBlockLocale?: string
|
||||
}
|
||||
|
||||
export const transformHasManyText = ({ field, locale, ref, textRows }: Args) => {
|
||||
const result = textRows.map(({ text }) => text)
|
||||
export const transformHasManyText = ({
|
||||
field,
|
||||
locale,
|
||||
ref,
|
||||
textRows,
|
||||
withinArrayOrBlockLocale,
|
||||
}: Args) => {
|
||||
let result: unknown[]
|
||||
|
||||
if (withinArrayOrBlockLocale) {
|
||||
result = textRows.reduce((acc, { locale, text }) => {
|
||||
if (locale === withinArrayOrBlockLocale) {
|
||||
acc.push(text)
|
||||
}
|
||||
|
||||
return acc
|
||||
}, [])
|
||||
} else {
|
||||
result = textRows.map(({ text }) => text)
|
||||
}
|
||||
|
||||
if (locale) {
|
||||
ref[field.name][locale] = result
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { Field, SanitizedConfig, TypeWithID } from 'payload'
|
||||
|
||||
import type { DrizzleAdapter } from '../../types.js'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { RelationshipField, UploadField } from 'payload'
|
||||
|
||||
type Args = {
|
||||
@@ -6,21 +5,31 @@ type Args = {
|
||||
locale?: string
|
||||
ref: Record<string, unknown>
|
||||
relations: Record<string, unknown>[]
|
||||
withinArrayOrBlockLocale?: string
|
||||
}
|
||||
|
||||
export const transformRelationship = ({ field, locale, ref, relations }: Args) => {
|
||||
export const transformRelationship = ({
|
||||
field,
|
||||
locale,
|
||||
ref,
|
||||
relations,
|
||||
withinArrayOrBlockLocale,
|
||||
}: Args) => {
|
||||
let result: unknown
|
||||
|
||||
if (!('hasMany' in field) || field.hasMany === false) {
|
||||
const relation = relations[0]
|
||||
let relation = relations[0]
|
||||
|
||||
if (withinArrayOrBlockLocale) {
|
||||
relation = relations.find((rel) => rel.locale === withinArrayOrBlockLocale)
|
||||
}
|
||||
|
||||
if (relation) {
|
||||
// Handle hasOne Poly
|
||||
if (Array.isArray(field.relationTo)) {
|
||||
const matchedRelation = Object.entries(relation).find(
|
||||
([key, val]) =>
|
||||
val !== null && !['id', 'locale', 'order', 'parent', 'path'].includes(key),
|
||||
)
|
||||
const matchedRelation = Object.entries(relation).find(([key, val]) => {
|
||||
return val !== null && !['id', 'locale', 'order', 'parent', 'path'].includes(key)
|
||||
})
|
||||
|
||||
if (matchedRelation) {
|
||||
const relationTo = matchedRelation[0].replace('ID', '')
|
||||
@@ -36,18 +45,26 @@ export const transformRelationship = ({ field, locale, ref, relations }: Args) =
|
||||
const transformedRelations = []
|
||||
|
||||
relations.forEach((relation) => {
|
||||
let matchedLocale = true
|
||||
|
||||
if (withinArrayOrBlockLocale) {
|
||||
matchedLocale = relation.locale === withinArrayOrBlockLocale
|
||||
}
|
||||
|
||||
// Handle hasMany
|
||||
if (!Array.isArray(field.relationTo)) {
|
||||
const relatedData = relation[`${field.relationTo}ID`]
|
||||
|
||||
if (relatedData) {
|
||||
if (relatedData && matchedLocale) {
|
||||
transformedRelations.push(relatedData)
|
||||
}
|
||||
} else {
|
||||
// Handle hasMany Poly
|
||||
const matchedRelation = Object.entries(relation).find(
|
||||
([key, val]) =>
|
||||
val !== null && !['id', 'locale', 'order', 'parent', 'path'].includes(key),
|
||||
val !== null &&
|
||||
!['id', 'locale', 'order', 'parent', 'path'].includes(key) &&
|
||||
matchedLocale,
|
||||
)
|
||||
|
||||
if (matchedRelation) {
|
||||
|
||||
@@ -58,6 +58,10 @@ type TraverseFieldsArgs = {
|
||||
* All hasMany text fields, as returned by Drizzle, keyed on an object by field path
|
||||
*/
|
||||
texts: Record<string, Record<string, unknown>[]>
|
||||
/**
|
||||
* Set to a locale if this group of fields is within a localized array or block.
|
||||
*/
|
||||
withinArrayOrBlockLocale?: string
|
||||
}
|
||||
|
||||
// Traverse fields recursively, transforming data
|
||||
@@ -75,6 +79,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
relationships,
|
||||
table,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
}: TraverseFieldsArgs): T => {
|
||||
const sanitizedPath = path ? `${path}.` : path
|
||||
|
||||
@@ -93,6 +98,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
relationships,
|
||||
table,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -114,6 +120,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
relationships,
|
||||
table,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -157,6 +164,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
relationships,
|
||||
table: row,
|
||||
texts,
|
||||
withinArrayOrBlockLocale: locale,
|
||||
})
|
||||
|
||||
if ('_order' in rowResult) {
|
||||
@@ -169,7 +177,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
return arrayResult
|
||||
}, {})
|
||||
} else {
|
||||
result[field.name] = fieldData.map((row, i) => {
|
||||
result[field.name] = fieldData.reduce((acc, row, i) => {
|
||||
if (row._uuid) {
|
||||
row.id = row._uuid
|
||||
delete row._uuid
|
||||
@@ -179,21 +187,35 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
delete row._order
|
||||
}
|
||||
|
||||
return traverseFields<T>({
|
||||
adapter,
|
||||
blocks,
|
||||
config,
|
||||
dataRef: row,
|
||||
deletions,
|
||||
fieldPrefix: '',
|
||||
fields: field.fields,
|
||||
numbers,
|
||||
path: `${sanitizedPath}${field.name}.${i}`,
|
||||
relationships,
|
||||
table: row,
|
||||
texts,
|
||||
})
|
||||
})
|
||||
if (
|
||||
!withinArrayOrBlockLocale ||
|
||||
(withinArrayOrBlockLocale && withinArrayOrBlockLocale === row._locale)
|
||||
) {
|
||||
if (row._locale) {
|
||||
delete row._locale
|
||||
}
|
||||
|
||||
acc.push(
|
||||
traverseFields<T>({
|
||||
adapter,
|
||||
blocks,
|
||||
config,
|
||||
dataRef: row,
|
||||
deletions,
|
||||
fieldPrefix: '',
|
||||
fields: field.fields,
|
||||
numbers,
|
||||
path: `${sanitizedPath}${field.name}.${i}`,
|
||||
relationships,
|
||||
table: row,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
return acc
|
||||
}, [])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +259,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
relationships,
|
||||
table: row,
|
||||
texts,
|
||||
withinArrayOrBlockLocale: locale,
|
||||
})
|
||||
|
||||
delete blockResult._order
|
||||
@@ -247,7 +270,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
})
|
||||
})
|
||||
} else {
|
||||
result[field.name] = blocks[blockFieldPath].map((row, i) => {
|
||||
result[field.name] = blocks[blockFieldPath].reduce((acc, row, i) => {
|
||||
delete row._order
|
||||
if (row._uuid) {
|
||||
row.id = row._uuid
|
||||
@@ -256,24 +279,40 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
const block = field.blocks.find(({ slug }) => slug === row.blockType)
|
||||
|
||||
if (block) {
|
||||
return traverseFields<T>({
|
||||
adapter,
|
||||
blocks,
|
||||
config,
|
||||
dataRef: row,
|
||||
deletions,
|
||||
fieldPrefix: '',
|
||||
fields: block.fields,
|
||||
numbers,
|
||||
path: `${blockFieldPath}.${i}`,
|
||||
relationships,
|
||||
table: row,
|
||||
texts,
|
||||
})
|
||||
if (
|
||||
!withinArrayOrBlockLocale ||
|
||||
(withinArrayOrBlockLocale && withinArrayOrBlockLocale === row._locale)
|
||||
) {
|
||||
if (row._locale) {
|
||||
delete row._locale
|
||||
}
|
||||
|
||||
acc.push(
|
||||
traverseFields<T>({
|
||||
adapter,
|
||||
blocks,
|
||||
config,
|
||||
dataRef: row,
|
||||
deletions,
|
||||
fieldPrefix: '',
|
||||
fields: block.fields,
|
||||
numbers,
|
||||
path: `${blockFieldPath}.${i}`,
|
||||
relationships,
|
||||
table: row,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
}),
|
||||
)
|
||||
|
||||
return acc
|
||||
}
|
||||
} else {
|
||||
acc.push({})
|
||||
}
|
||||
|
||||
return {}
|
||||
})
|
||||
return acc
|
||||
}, [])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,6 +373,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
field,
|
||||
ref: result,
|
||||
relations: relationPathMatch,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
}
|
||||
return result
|
||||
@@ -368,6 +408,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
field,
|
||||
ref: result,
|
||||
textRows: textPathMatch,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -402,6 +443,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
field,
|
||||
numberRows: numberPathMatch,
|
||||
ref: result,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -466,6 +508,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
|
||||
relationships,
|
||||
table,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
|
||||
if ('_order' in ref) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { ArrayField } from 'payload'
|
||||
|
||||
import type { DrizzleAdapter } from '../../types.js'
|
||||
@@ -26,6 +25,11 @@ type Args = {
|
||||
[tableName: string]: Record<string, unknown>[]
|
||||
}
|
||||
texts: Record<string, unknown>[]
|
||||
/**
|
||||
* Set to a locale code if this set of fields is traversed within a
|
||||
* localized array or block field
|
||||
*/
|
||||
withinArrayOrBlockLocale?: string
|
||||
}
|
||||
|
||||
export const transformArray = ({
|
||||
@@ -43,6 +47,7 @@ export const transformArray = ({
|
||||
relationshipsToDelete,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
}: Args) => {
|
||||
const newRows: ArrayRowToInsert[] = []
|
||||
|
||||
@@ -78,6 +83,10 @@ export const transformArray = ({
|
||||
newRow.row._locale = locale
|
||||
}
|
||||
|
||||
if (withinArrayOrBlockLocale) {
|
||||
newRow.row._locale = withinArrayOrBlockLocale
|
||||
}
|
||||
|
||||
traverseFields({
|
||||
adapter,
|
||||
arrays: newRow.arrays,
|
||||
@@ -97,6 +106,7 @@ export const transformArray = ({
|
||||
row: newRow.row,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
|
||||
newRows.push(newRow)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { BlockField } from 'payload'
|
||||
|
||||
import toSnakeCase from 'to-snake-case'
|
||||
@@ -26,6 +25,11 @@ type Args = {
|
||||
[tableName: string]: Record<string, unknown>[]
|
||||
}
|
||||
texts: Record<string, unknown>[]
|
||||
/**
|
||||
* Set to a locale code if this set of fields is traversed within a
|
||||
* localized array or block field
|
||||
*/
|
||||
withinArrayOrBlockLocale?: string
|
||||
}
|
||||
export const transformBlocks = ({
|
||||
adapter,
|
||||
@@ -41,6 +45,7 @@ export const transformBlocks = ({
|
||||
relationshipsToDelete,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
}: Args) => {
|
||||
data.forEach((blockRow, i) => {
|
||||
if (typeof blockRow.blockType !== 'string') return
|
||||
@@ -60,6 +65,7 @@ export const transformBlocks = ({
|
||||
}
|
||||
|
||||
if (field.localized && locale) newRow.row._locale = locale
|
||||
if (withinArrayOrBlockLocale) newRow.row._locale = withinArrayOrBlockLocale
|
||||
|
||||
const blockTableName = adapter.tableNameMap.get(`${baseTableName}_blocks_${blockType}`)
|
||||
|
||||
@@ -94,6 +100,7 @@ export const transformBlocks = ({
|
||||
row: newRow.row,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
|
||||
blocks[blockType].push(newRow)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { Field } from 'payload'
|
||||
|
||||
import type { DrizzleAdapter } from '../../types.js'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import { isArrayOfRows } from '../../utilities/isArrayOfRows.js'
|
||||
|
||||
type Args = {
|
||||
|
||||
@@ -57,6 +57,11 @@ type Args = {
|
||||
[tableName: string]: Record<string, unknown>[]
|
||||
}
|
||||
texts: Record<string, unknown>[]
|
||||
/**
|
||||
* Set to a locale code if this set of fields is traversed within a
|
||||
* localized array or block field
|
||||
*/
|
||||
withinArrayOrBlockLocale?: string
|
||||
}
|
||||
|
||||
export const traverseFields = ({
|
||||
@@ -80,6 +85,7 @@ export const traverseFields = ({
|
||||
row,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
}: Args) => {
|
||||
fields.forEach((field) => {
|
||||
let columnName = ''
|
||||
@@ -116,6 +122,7 @@ export const traverseFields = ({
|
||||
relationshipsToDelete,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale: localeKey,
|
||||
})
|
||||
|
||||
arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)
|
||||
@@ -137,6 +144,7 @@ export const traverseFields = ({
|
||||
relationshipsToDelete,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
|
||||
arrays[arrayTableName] = arrays[arrayTableName].concat(newRows)
|
||||
@@ -168,6 +176,7 @@ export const traverseFields = ({
|
||||
relationshipsToDelete,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale: localeKey,
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -186,6 +195,7 @@ export const traverseFields = ({
|
||||
relationshipsToDelete,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -217,6 +227,7 @@ export const traverseFields = ({
|
||||
row,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale: localeKey,
|
||||
})
|
||||
})
|
||||
} else {
|
||||
@@ -240,6 +251,7 @@ export const traverseFields = ({
|
||||
row,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -274,6 +286,7 @@ export const traverseFields = ({
|
||||
row,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale: localeKey,
|
||||
})
|
||||
})
|
||||
} else {
|
||||
@@ -297,6 +310,7 @@ export const traverseFields = ({
|
||||
row,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -321,6 +335,7 @@ export const traverseFields = ({
|
||||
row,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -347,6 +362,7 @@ export const traverseFields = ({
|
||||
row,
|
||||
selects,
|
||||
texts,
|
||||
withinArrayOrBlockLocale,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -387,6 +403,7 @@ export const traverseFields = ({
|
||||
|
||||
transformRelationship({
|
||||
baseRow: {
|
||||
locale: withinArrayOrBlockLocale,
|
||||
path: relationshipPath,
|
||||
},
|
||||
data: fieldData,
|
||||
@@ -440,6 +457,7 @@ export const traverseFields = ({
|
||||
} else if (Array.isArray(fieldData)) {
|
||||
transformTexts({
|
||||
baseRow: {
|
||||
locale: withinArrayOrBlockLocale,
|
||||
path: textPath,
|
||||
},
|
||||
data: fieldData,
|
||||
@@ -471,6 +489,7 @@ export const traverseFields = ({
|
||||
} else if (Array.isArray(fieldData)) {
|
||||
transformNumbers({
|
||||
baseRow: {
|
||||
locale: withinArrayOrBlockLocale,
|
||||
path: numberPath,
|
||||
},
|
||||
data: fieldData,
|
||||
@@ -503,6 +522,7 @@ export const traverseFields = ({
|
||||
const newRows = transformSelects({
|
||||
id: data._uuid || data.id,
|
||||
data: data[field.name],
|
||||
locale: withinArrayOrBlockLocale,
|
||||
})
|
||||
|
||||
selects[selectTableName] = selects[selectTableName].concat(newRows)
|
||||
|
||||
@@ -348,20 +348,52 @@ export const upsertRow = async <T extends Record<string, unknown> | TypeWithID>(
|
||||
// Error Handling
|
||||
// //////////////////////////////////
|
||||
} catch (error) {
|
||||
throw error.code === '23505'
|
||||
? new ValidationError(
|
||||
{
|
||||
id,
|
||||
errors: [
|
||||
{
|
||||
field: adapter.fieldConstraints[tableName][error.constraint],
|
||||
message: req.t('error:valueMustBeUnique'),
|
||||
},
|
||||
],
|
||||
},
|
||||
req.t,
|
||||
)
|
||||
: error
|
||||
if (error.code === '23505') {
|
||||
let fieldName: null | string = null
|
||||
// We need to try and find the right constraint for the field but if we can't we fallback to a generic message
|
||||
if (adapter.fieldConstraints?.[tableName]) {
|
||||
if (adapter.fieldConstraints[tableName]?.[error.constraint]) {
|
||||
fieldName = adapter.fieldConstraints[tableName]?.[error.constraint]
|
||||
} else {
|
||||
const replacement = `${tableName}_`
|
||||
|
||||
if (error.constraint.includes(replacement)) {
|
||||
const replacedConstraint = error.constraint.replace(replacement, '')
|
||||
|
||||
if (replacedConstraint && adapter.fieldConstraints[tableName]?.[replacedConstraint])
|
||||
fieldName = adapter.fieldConstraints[tableName][replacedConstraint]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!fieldName) {
|
||||
// Last case scenario we extract the key and value from the detail on the error
|
||||
const detail = error.detail
|
||||
const regex = /Key \(([^)]+)\)=\(([^)]+)\)/
|
||||
const match = detail.match(regex)
|
||||
|
||||
if (match) {
|
||||
const key = match[1]
|
||||
|
||||
fieldName = key
|
||||
}
|
||||
}
|
||||
|
||||
throw new ValidationError(
|
||||
{
|
||||
id,
|
||||
errors: [
|
||||
{
|
||||
field: fieldName,
|
||||
message: req.t('error:valueMustBeUnique'),
|
||||
},
|
||||
],
|
||||
},
|
||||
req.t,
|
||||
)
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
if (ignoreResult) return data as T
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { ArrayRowToInsert } from '../transform/write/types.js'
|
||||
import type { DrizzleAdapter, DrizzleTransaction } from '../types.js'
|
||||
|
||||
|
||||
@@ -18,18 +18,18 @@ type BaseArgs = {
|
||||
tableName: string
|
||||
}
|
||||
|
||||
type CreateArgs = BaseArgs & {
|
||||
type CreateArgs = {
|
||||
id?: never
|
||||
operation: 'create'
|
||||
upsertTarget?: never
|
||||
where?: never
|
||||
}
|
||||
} & BaseArgs
|
||||
|
||||
type UpdateArgs = BaseArgs & {
|
||||
type UpdateArgs = {
|
||||
id?: number | string
|
||||
operation: 'update'
|
||||
upsertTarget?: GenericColumn
|
||||
where?: SQL<unknown>
|
||||
}
|
||||
} & BaseArgs
|
||||
|
||||
export type Args = CreateArgs | UpdateArgs
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
export type BlocksMap = {
|
||||
[path: string]: Record<string, unknown>[]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-nodemailer",
|
||||
"version": "3.0.0-beta.91",
|
||||
"version": "3.0.0-beta.96",
|
||||
"description": "Payload Nodemailer Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
@@ -29,6 +29,8 @@
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
||||
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"prepublishOnly": "pnpm clean && pnpm turbo build"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -47,7 +47,9 @@ async function buildEmail(emailConfig?: NodemailerAdapterArgs): Promise<{
|
||||
}> {
|
||||
if (!emailConfig) {
|
||||
const transport = await createMockAccount(emailConfig)
|
||||
if (!transport) throw new InvalidConfiguration('Unable to create Nodemailer test account.')
|
||||
if (!transport) {
|
||||
throw new InvalidConfiguration('Unable to create Nodemailer test account.')
|
||||
}
|
||||
|
||||
return {
|
||||
defaultFromAddress: 'info@payloadcms.com',
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { jest } from '@jest/globals'
|
||||
import type { Transporter } from 'nodemailer'
|
||||
|
||||
import nodemailer, { Transporter } from 'nodemailer'
|
||||
import { nodemailerAdapter, NodemailerAdapterArgs } from './index.js'
|
||||
import { jest } from '@jest/globals'
|
||||
import nodemailer from 'nodemailer'
|
||||
|
||||
import type { NodemailerAdapterArgs } from './index.js'
|
||||
|
||||
import { nodemailerAdapter } from './index.js'
|
||||
|
||||
const defaultArgs: NodemailerAdapterArgs = {
|
||||
defaultFromAddress: 'test@test.com',
|
||||
@@ -9,7 +13,6 @@ const defaultArgs: NodemailerAdapterArgs = {
|
||||
}
|
||||
|
||||
describe('email-nodemailer', () => {
|
||||
|
||||
describe('transport verification', () => {
|
||||
let mockedVerify: jest.Mock<Transporter['verify']>
|
||||
let mockTransport: Transporter
|
||||
@@ -18,20 +21,21 @@ describe('email-nodemailer', () => {
|
||||
mockedVerify = jest.fn<Transporter['verify']>()
|
||||
mockTransport = nodemailer.createTransport({
|
||||
name: 'existing-transport',
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
// eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-misused-promises
|
||||
send: async (mail) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('mock send', mail)
|
||||
},
|
||||
version: '0.0.1',
|
||||
verify: mockedVerify,
|
||||
version: '0.0.1',
|
||||
})
|
||||
})
|
||||
|
||||
it('should be invoked when skipVerify = false', async () => {
|
||||
await nodemailerAdapter({
|
||||
...defaultArgs,
|
||||
transport: mockTransport,
|
||||
skipVerify: false,
|
||||
transport: mockTransport,
|
||||
})
|
||||
|
||||
expect(mockedVerify.mock.calls).toHaveLength(1)
|
||||
@@ -40,8 +44,8 @@ describe('email-nodemailer', () => {
|
||||
it('should be invoked when skipVerify is undefined', async () => {
|
||||
await nodemailerAdapter({
|
||||
...defaultArgs,
|
||||
transport: mockTransport,
|
||||
skipVerify: false,
|
||||
transport: mockTransport,
|
||||
})
|
||||
|
||||
expect(mockedVerify.mock.calls).toHaveLength(1)
|
||||
@@ -50,8 +54,8 @@ describe('email-nodemailer', () => {
|
||||
it('should not be invoked when skipVerify = true', async () => {
|
||||
await nodemailerAdapter({
|
||||
...defaultArgs,
|
||||
transport: mockTransport,
|
||||
skipVerify: true,
|
||||
transport: mockTransport,
|
||||
})
|
||||
|
||||
expect(mockedVerify.mock.calls).toHaveLength(0)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-resend",
|
||||
"version": "3.0.0-beta.91",
|
||||
"version": "3.0.0-beta.96",
|
||||
"description": "Payload Resend Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
@@ -28,6 +28,8 @@
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc-build --strip-leading-paths",
|
||||
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"prepublishOnly": "pnpm clean && pnpm turbo build",
|
||||
"test": "jest"
|
||||
},
|
||||
|
||||
@@ -14,6 +14,7 @@ import { deepMerge } from './deepMerge.js'
|
||||
const baseRules = {
|
||||
// This rule makes no sense when overriding class methods. This is used a lot in richtext-lexical.
|
||||
'class-methods-use-this': 'off',
|
||||
curly: ['warn', 'all'],
|
||||
'arrow-body-style': 0,
|
||||
'import-x/prefer-default-export': 'off',
|
||||
'no-restricted-exports': ['warn', { restrictDefaultExports: { direct: true } }],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/graphql",
|
||||
"version": "3.0.0-beta.91",
|
||||
"version": "3.0.0-beta.96",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -38,6 +38,8 @@
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
||||
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"prepublishOnly": "pnpm clean && pnpm turbo build"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -8,12 +8,12 @@ import {
|
||||
fieldExtensionsEstimator,
|
||||
simpleEstimator,
|
||||
} from './packages/graphql-query-complexity/index.js'
|
||||
import accessResolver from './resolvers/auth/access.js'
|
||||
import buildFallbackLocaleInputType from './schema/buildFallbackLocaleInputType.js'
|
||||
import buildLocaleInputType from './schema/buildLocaleInputType.js'
|
||||
import buildPoliciesType from './schema/buildPoliciesType.js'
|
||||
import initCollections from './schema/initCollections.js'
|
||||
import initGlobals from './schema/initGlobals.js'
|
||||
import { accessResolver } from './resolvers/auth/access.js'
|
||||
import { buildFallbackLocaleInputType } from './schema/buildFallbackLocaleInputType.js'
|
||||
import { buildLocaleInputType } from './schema/buildLocaleInputType.js'
|
||||
import { buildPoliciesType } from './schema/buildPoliciesType.js'
|
||||
import { initCollections } from './schema/initCollections.js'
|
||||
import { initGlobals } from './schema/initGlobals.js'
|
||||
import { wrapCustomFields } from './utilities/wrapCustomResolver.js'
|
||||
|
||||
export function configToSchema(config: SanitizedConfig): {
|
||||
|
||||
@@ -122,7 +122,7 @@ export function getComplexity(options: {
|
||||
return visitor.complexity
|
||||
}
|
||||
|
||||
export default class QueryComplexity {
|
||||
export class QueryComplexity {
|
||||
OperationDefinition: Record<string, any>
|
||||
complexity: number
|
||||
context: ValidationContext
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { ValidationContext } from 'graphql'
|
||||
|
||||
import type { QueryComplexityOptions } from './QueryComplexity.js'
|
||||
|
||||
import QueryComplexity from './QueryComplexity.js'
|
||||
import { QueryComplexity } from './QueryComplexity.js'
|
||||
|
||||
export function createComplexityRule(
|
||||
options: QueryComplexityOptions,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { accessOperation, isolateObjectProperty } from 'payload'
|
||||
|
||||
import type { Context } from '../types.js'
|
||||
|
||||
import formatName from '../../utilities/formatName.js'
|
||||
import { formatName } from '../../utilities/formatName.js'
|
||||
const formatConfigNames = (results, configs) => {
|
||||
const formattedResults = { ...results }
|
||||
|
||||
@@ -17,7 +17,7 @@ const formatConfigNames = (results, configs) => {
|
||||
return formattedResults
|
||||
}
|
||||
|
||||
function accessResolver(config: SanitizedConfig) {
|
||||
export function accessResolver(config: SanitizedConfig) {
|
||||
async function resolver(_, args, context: Context) {
|
||||
const options = {
|
||||
req: isolateObjectProperty<any>(context.req, 'transactionID'),
|
||||
@@ -34,5 +34,3 @@ function accessResolver(config: SanitizedConfig) {
|
||||
|
||||
return resolver
|
||||
}
|
||||
|
||||
export default accessResolver
|
||||
|
||||
@@ -4,7 +4,7 @@ import { forgotPasswordOperation, isolateObjectProperty } from 'payload'
|
||||
|
||||
import type { Context } from '../types.js'
|
||||
|
||||
function forgotPasswordResolver(collection: Collection): any {
|
||||
export function forgotPassword(collection: Collection): any {
|
||||
async function resolver(_, args, context: Context) {
|
||||
const options = {
|
||||
collection,
|
||||
@@ -23,5 +23,3 @@ function forgotPasswordResolver(collection: Collection): any {
|
||||
|
||||
return resolver
|
||||
}
|
||||
|
||||
export default forgotPasswordResolver
|
||||
|
||||
@@ -2,7 +2,7 @@ import { initOperation, isolateObjectProperty } from 'payload'
|
||||
|
||||
import type { Context } from '../types.js'
|
||||
|
||||
function initResolver(collection: string) {
|
||||
export function init(collection: string) {
|
||||
async function resolver(_, args, context: Context) {
|
||||
const options = {
|
||||
collection,
|
||||
@@ -14,5 +14,3 @@ function initResolver(collection: string) {
|
||||
|
||||
return resolver
|
||||
}
|
||||
|
||||
export default initResolver
|
||||
|
||||
@@ -4,7 +4,7 @@ import { generatePayloadCookie, isolateObjectProperty, loginOperation } from 'pa
|
||||
|
||||
import type { Context } from '../types.js'
|
||||
|
||||
function loginResolver(collection: Collection): any {
|
||||
export function login(collection: Collection): any {
|
||||
async function resolver(_, args, context: Context) {
|
||||
const options = {
|
||||
collection,
|
||||
@@ -35,5 +35,3 @@ function loginResolver(collection: Collection): any {
|
||||
|
||||
return resolver
|
||||
}
|
||||
|
||||
export default loginResolver
|
||||
|
||||
@@ -4,7 +4,7 @@ import { generateExpiredPayloadCookie, isolateObjectProperty, logoutOperation }
|
||||
|
||||
import type { Context } from '../types.js'
|
||||
|
||||
function logoutResolver(collection: Collection): any {
|
||||
export function logout(collection: Collection): any {
|
||||
async function resolver(_, args, context: Context) {
|
||||
const options = {
|
||||
collection,
|
||||
@@ -22,5 +22,3 @@ function logoutResolver(collection: Collection): any {
|
||||
|
||||
return resolver
|
||||
}
|
||||
|
||||
export default logoutResolver
|
||||
|
||||
@@ -4,7 +4,7 @@ import { extractJWT, isolateObjectProperty, meOperation } from 'payload'
|
||||
|
||||
import type { Context } from '../types.js'
|
||||
|
||||
function meResolver(collection: Collection): any {
|
||||
export function me(collection: Collection): any {
|
||||
async function resolver(_, args, context: Context) {
|
||||
const currentToken = extractJWT(context.req)
|
||||
|
||||
@@ -26,5 +26,3 @@ function meResolver(collection: Collection): any {
|
||||
|
||||
return resolver
|
||||
}
|
||||
|
||||
export default meResolver
|
||||
|
||||
@@ -4,7 +4,7 @@ import { generatePayloadCookie, isolateObjectProperty, refreshOperation } from '
|
||||
|
||||
import type { Context } from '../types.js'
|
||||
|
||||
function refreshResolver(collection: Collection): any {
|
||||
export function refresh(collection: Collection): any {
|
||||
async function resolver(_, __, context: Context) {
|
||||
const options = {
|
||||
collection,
|
||||
@@ -29,5 +29,3 @@ function refreshResolver(collection: Collection): any {
|
||||
|
||||
return resolver
|
||||
}
|
||||
|
||||
export default refreshResolver
|
||||
|
||||
@@ -4,10 +4,14 @@ import { generatePayloadCookie, isolateObjectProperty, resetPasswordOperation }
|
||||
|
||||
import type { Context } from '../types.js'
|
||||
|
||||
function resetPasswordResolver(collection: Collection): any {
|
||||
export function resetPassword(collection: Collection): any {
|
||||
async function resolver(_, args, context: Context) {
|
||||
if (args.locale) context.req.locale = args.locale
|
||||
if (args.fallbackLocale) context.req.fallbackLocale = args.fallbackLocale
|
||||
if (args.locale) {
|
||||
context.req.locale = args.locale
|
||||
}
|
||||
if (args.fallbackLocale) {
|
||||
context.req.fallbackLocale = args.fallbackLocale
|
||||
}
|
||||
|
||||
const options = {
|
||||
api: 'GraphQL',
|
||||
@@ -34,5 +38,3 @@ function resetPasswordResolver(collection: Collection): any {
|
||||
|
||||
return resolver
|
||||
}
|
||||
|
||||
export default resetPasswordResolver
|
||||
|
||||
@@ -4,7 +4,7 @@ import { isolateObjectProperty, unlockOperation } from 'payload'
|
||||
|
||||
import type { Context } from '../types.js'
|
||||
|
||||
function unlockResolver(collection: Collection) {
|
||||
export function unlock(collection: Collection) {
|
||||
async function resolver(_, args, context: Context) {
|
||||
const options = {
|
||||
collection,
|
||||
@@ -18,5 +18,3 @@ function unlockResolver(collection: Collection) {
|
||||
|
||||
return resolver
|
||||
}
|
||||
|
||||
export default unlockResolver
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user