diff --git a/docs/migration-guide/overview.mdx b/docs/migration-guide/overview.mdx index d60626ef5..2dead9ab4 100644 --- a/docs/migration-guide/overview.mdx +++ b/docs/migration-guide/overview.mdx @@ -684,7 +684,7 @@ import { s3Adapter } from '@payloadcms/plugin-cloud-storage/s3' plugins: [ cloudStorage({ collections: { - [mediaSlug]: { + media: { adapter: s3Adapter({ bucket: process.env.S3_BUCKET, config: { @@ -707,7 +707,7 @@ plugins: [ plugins: [ s3Storage({ collections: { - [mediaSlug]: true, + media: true, }, bucket: process.env.S3_BUCKET, config: { diff --git a/docs/upload/storage-adapters.mdx b/docs/upload/storage-adapters.mdx index d3f22118b..94e68deaf 100644 --- a/docs/upload/storage-adapters.mdx +++ b/docs/upload/storage-adapters.mdx @@ -43,8 +43,8 @@ export default buildConfig({ enabled: true, // Optional, defaults to true // Specify which collections should use Vercel Blob collections: { - [Media.slug]: true, - [MediaWithPrefix.slug]: { + media: true, + 'media-with-prefix': { prefix: 'my-prefix', }, }, @@ -90,8 +90,8 @@ export default buildConfig({ plugins: [ s3Storage({ collections: { - [mediaSlug]: true, - [mediaWithPrefixSlug]: { + media: true, + 'media-with-prefix': { prefix, }, }, @@ -137,8 +137,8 @@ export default buildConfig({ plugins: [ azureStorage({ collections: { - [mediaSlug]: true, - [mediaWithPrefixSlug]: { + media: true, + 'media-with-prefix': { prefix, }, }, @@ -186,8 +186,8 @@ export default buildConfig({ plugins: [ gcsStorage({ collections: { - [mediaSlug]: true, - [mediaWithPrefixSlug]: { + media: true, + 'media-with-prefix': { prefix, }, }, @@ -233,7 +233,7 @@ export default buildConfig({ plugins: [ uploadthingStorage({ collections: { - [mediaSlug]: true, + media: true, }, options: { token: process.env.UPLOADTHING_TOKEN, diff --git a/packages/create-payload-app/src/lib/replacements.ts b/packages/create-payload-app/src/lib/replacements.ts index cc109e63c..64e715d1e 100644 --- a/packages/create-payload-app/src/lib/replacements.ts +++ b/packages/create-payload-app/src/lib/replacements.ts @@ -71,7 +71,7 @@ const vercelBlobStorageReplacement: StorageAdapterReplacement = { configReplacement: [ ' vercelBlobStorage({', ' collections: {', - ' [Media.slug]: true,', + ' media: true,', ' },', " token: process.env.BLOB_READ_WRITE_TOKEN || '',", ' }),', diff --git a/packages/payload-cloud/src/types.ts b/packages/payload-cloud/src/types.ts index 7665a7556..642440fbd 100644 --- a/packages/payload-cloud/src/types.ts +++ b/packages/payload-cloud/src/types.ts @@ -1,4 +1,11 @@ -import type { CollectionConfig, Config, FileData, PayloadRequest, TypeWithID } from 'payload' +import type { + CollectionConfig, + Config, + FileData, + PayloadRequest, + TypeWithID, + UploadCollectionSlug, +} from 'payload' export interface File { buffer: Buffer @@ -94,7 +101,7 @@ export interface PluginOptions { /** * Caching configuration per-collection */ - collections?: Record + collections?: Partial> /** Caching in seconds override for all collections * @default 86400 (24 hours) */ diff --git a/packages/payload/src/auth/types.ts b/packages/payload/src/auth/types.ts index 82bda087b..987370778 100644 --- a/packages/payload/src/auth/types.ts +++ b/packages/payload/src/auth/types.ts @@ -1,6 +1,6 @@ import type { DeepRequired } from 'ts-essentials' -import type { Payload } from '../index.js' +import type { CollectionSlug, GlobalSlug, Payload } from '../index.js' import type { PayloadRequest, Where } from '../types/index.js' export type Permission = { @@ -54,10 +54,10 @@ export type DocumentPermissions = CollectionPermission | GlobalPermission export type Permissions = { canAccessAdmin: boolean collections: { - [collectionSlug: string]: CollectionPermission + [collectionSlug: CollectionSlug]: CollectionPermission } globals?: { - [globalSlug: string]: GlobalPermission + [globalSlug: GlobalSlug]: GlobalPermission } } diff --git a/packages/payload/src/collections/config/types.ts b/packages/payload/src/collections/config/types.ts index 1b5d4cf3a..957c8b698 100644 --- a/packages/payload/src/collections/config/types.ts +++ b/packages/payload/src/collections/config/types.ts @@ -520,11 +520,12 @@ export type SanitizedJoins = { export interface SanitizedCollectionConfig extends Omit< DeepRequired, - 'auth' | 'endpoints' | 'fields' | 'upload' | 'versions' + 'auth' | 'endpoints' | 'fields' | 'slug' | 'upload' | 'versions' > { auth: Auth endpoints: Endpoint[] | false fields: Field[] + slug: CollectionSlug /** * Object of collections to join 'Join Fields object keyed by collection */ diff --git a/packages/payload/src/database/types.ts b/packages/payload/src/database/types.ts index bb7d2273d..f138db9d6 100644 --- a/packages/payload/src/database/types.ts +++ b/packages/payload/src/database/types.ts @@ -1,4 +1,5 @@ import type { TypeWithID } from '../collections/config/types.js' +import type { CollectionSlug, GlobalSlug } from '../index.js' import type { Document, JoinQuery, @@ -185,7 +186,7 @@ export type RollbackTransaction = (id: number | Promise | strin export type CommitTransaction = (id: number | Promise | string) => Promise export type QueryDraftsArgs = { - collection: string + collection: CollectionSlug joins?: JoinQuery limit?: number locale?: string @@ -200,7 +201,7 @@ export type QueryDraftsArgs = { export type QueryDrafts = (args: QueryDraftsArgs) => Promise> export type FindOneArgs = { - collection: string + collection: CollectionSlug joins?: JoinQuery locale?: string req: PayloadRequest @@ -211,7 +212,7 @@ export type FindOneArgs = { export type FindOne = (args: FindOneArgs) => Promise export type FindArgs = { - collection: string + collection: CollectionSlug joins?: JoinQuery /** Setting limit to 1 is equal to the previous Model.findOne(). Setting limit to 0 disables the limit */ limit?: number @@ -230,7 +231,7 @@ export type FindArgs = { export type Find = (args: FindArgs) => Promise> export type CountArgs = { - collection: string + collection: CollectionSlug locale?: string req: PayloadRequest where?: Where @@ -263,7 +264,7 @@ type BaseVersionArgs = { } export type FindVersionsArgs = { - collection: string + collection: CollectionSlug } & BaseVersionArgs export type FindVersions = ( @@ -271,7 +272,7 @@ export type FindVersions = ( ) => Promise>> export type FindGlobalVersionsArgs = { - global: string + global: GlobalSlug } & BaseVersionArgs export type FindGlobalArgs = { @@ -283,7 +284,7 @@ export type FindGlobalArgs = { } export type UpdateGlobalVersionArgs = { - global: string + global: GlobalSlug locale?: string /** * Additional database adapter specific options to pass to the query @@ -340,7 +341,7 @@ export type FindGlobalVersions = ( ) => Promise>> export type DeleteVersionsArgs = { - collection: string + collection: CollectionSlug locale?: string req: PayloadRequest sort?: { @@ -351,7 +352,7 @@ export type DeleteVersionsArgs = { export type CreateVersionArgs = { autosave: boolean - collectionSlug: string + collectionSlug: CollectionSlug createdAt: string /** ID of the parent document for which the version should be created for */ parent: number | string @@ -370,7 +371,7 @@ export type CreateVersion = ( export type CreateGlobalVersionArgs = { autosave: boolean createdAt: string - globalSlug: string + globalSlug: GlobalSlug /** ID of the parent document for which the version should be created for */ parent: number | string publishedLocale?: string @@ -388,7 +389,7 @@ export type CreateGlobalVersion = ( export type DeleteVersions = (args: DeleteVersionsArgs) => Promise export type UpdateVersionArgs = { - collection: string + collection: CollectionSlug locale?: string /** * Additional database adapter specific options to pass to the query @@ -413,7 +414,7 @@ export type UpdateVersion = ( ) => Promise> export type CreateArgs = { - collection: string + collection: CollectionSlug data: Record draft?: boolean locale?: string @@ -424,7 +425,7 @@ export type CreateArgs = { export type Create = (args: CreateArgs) => Promise export type UpdateOneArgs = { - collection: string + collection: CollectionSlug data: Record draft?: boolean joins?: JoinQuery @@ -449,7 +450,7 @@ export type UpdateOneArgs = { export type UpdateOne = (args: UpdateOneArgs) => Promise export type UpsertArgs = { - collection: string + collection: CollectionSlug data: Record joins?: JoinQuery locale?: string @@ -461,7 +462,7 @@ export type UpsertArgs = { export type Upsert = (args: UpsertArgs) => Promise export type DeleteOneArgs = { - collection: string + collection: CollectionSlug joins?: JoinQuery req: PayloadRequest select?: SelectType @@ -471,7 +472,7 @@ export type DeleteOneArgs = { export type DeleteOne = (args: DeleteOneArgs) => Promise export type DeleteManyArgs = { - collection: string + collection: CollectionSlug joins?: JoinQuery req: PayloadRequest where: Where diff --git a/packages/payload/src/globals/config/types.ts b/packages/payload/src/globals/config/types.ts index 47fe2bb31..ac2fb3c43 100644 --- a/packages/payload/src/globals/config/types.ts +++ b/packages/payload/src/globals/config/types.ts @@ -189,9 +189,10 @@ export type GlobalConfig = { } export interface SanitizedGlobalConfig - extends Omit, 'endpoints' | 'fields' | 'versions'> { + extends Omit, 'endpoints' | 'fields' | 'slug' | 'versions'> { endpoints: Endpoint[] | false fields: Field[] + slug: GlobalSlug versions: SanitizedGlobalVersions } diff --git a/packages/payload/src/index.ts b/packages/payload/src/index.ts index 908e04013..2be723410 100644 --- a/packages/payload/src/index.ts +++ b/packages/payload/src/index.ts @@ -27,6 +27,8 @@ import type { } from './collections/config/types.js' export type { FieldState } from './admin/forms/Form.js' export type * from './admin/types.js' +import type { NonNever } from 'ts-essentials' + import type { Options as CountOptions } from './collections/operations/local/count.js' import type { Options as CreateOptions } from './collections/operations/local/create.js' import type { @@ -166,6 +168,16 @@ type ResolveGlobalSelectType = 'globalsSelect' extends keyof T // Applying helper types to GeneratedTypes export type TypedCollection = ResolveCollectionType +export type TypedUploadCollection = NonNever<{ + [K in keyof TypedCollection]: + | 'filename' + | 'filesize' + | 'mimeType' + | 'url' extends keyof TypedCollection[K] + ? TypedCollection[K] + : never +}> + export type TypedCollectionSelect = ResolveCollectionSelectType export type TypedCollectionJoins = ResolveCollectionJoinsType @@ -180,6 +192,8 @@ export type StringKeyOf = Extract // Define the types for slugs using the appropriate collections and globals export type CollectionSlug = StringKeyOf +export type UploadCollectionSlug = StringKeyOf + type ResolveDbType = 'db' extends keyof T ? T['db'] : // @ts-expect-error @@ -228,7 +242,7 @@ export class BasePayload { authStrategies: AuthStrategy[] collections: { - [slug: string]: Collection + [slug: CollectionSlug]: Collection } = {} config: SanitizedConfig diff --git a/packages/plugin-cloud-storage/src/types.ts b/packages/plugin-cloud-storage/src/types.ts index c9019a0e3..38ea00a98 100644 --- a/packages/plugin-cloud-storage/src/types.ts +++ b/packages/plugin-cloud-storage/src/types.ts @@ -5,6 +5,7 @@ import type { ImageSize, PayloadRequest, TypeWithID, + UploadCollectionSlug, } from 'payload' export interface File { @@ -79,7 +80,7 @@ export interface CollectionOptions { } export interface PluginOptions { - collections: Record + collections: Partial> /** * Whether or not to enable the plugin * diff --git a/packages/plugin-nested-docs/src/types.ts b/packages/plugin-nested-docs/src/types.ts index fa8e5eea4..c91676ca3 100644 --- a/packages/plugin-nested-docs/src/types.ts +++ b/packages/plugin-nested-docs/src/types.ts @@ -1,3 +1,5 @@ +import type { CollectionSlug } from 'payload' + export type Breadcrumb = { doc: string label: string @@ -22,7 +24,7 @@ export type NestedDocsPluginConfig = { /** * The slugs of the collections this plugin should extend. If you need different configs for different collections, this plugin can be added to your config more than once having different collections. */ - collections: string[] + collections: CollectionSlug[] generateLabel?: GenerateLabel generateURL?: GenerateURL /** diff --git a/packages/plugin-stripe/src/types.ts b/packages/plugin-stripe/src/types.ts index 142229cf2..69cff6751 100644 --- a/packages/plugin-stripe/src/types.ts +++ b/packages/plugin-stripe/src/types.ts @@ -1,4 +1,4 @@ -import type { Payload, Config as PayloadConfig, PayloadRequest } from 'payload' +import type { CollectionSlug, Payload, Config as PayloadConfig, PayloadRequest } from 'payload' import type Stripe from 'stripe' export type StripeWebhookHandler = (args: { @@ -20,7 +20,7 @@ export type FieldSyncConfig = { } export type SyncConfig = { - collection: string + collection: CollectionSlug fields: FieldSyncConfig[] stripeResourceType: 'customers' | 'products' // TODO: get this from Stripe types stripeResourceTypeSingular: 'customer' | 'product' // TODO: there must be a better way to do this diff --git a/packages/storage-azure/README.md b/packages/storage-azure/README.md index 4822fd1bf..0a3e31911 100644 --- a/packages/storage-azure/README.md +++ b/packages/storage-azure/README.md @@ -25,8 +25,8 @@ export default buildConfig({ plugins: [ azureStorage({ collections: { - [mediaSlug]: true, - [mediaWithPrefixSlug]: { + media: true, + 'media-with-prefix': { prefix, }, }, diff --git a/packages/storage-azure/src/index.ts b/packages/storage-azure/src/index.ts index 105d0a260..4f9994b34 100644 --- a/packages/storage-azure/src/index.ts +++ b/packages/storage-azure/src/index.ts @@ -4,7 +4,7 @@ import type { CollectionOptions, GeneratedAdapter, } from '@payloadcms/plugin-cloud-storage/types' -import type { Config, Plugin } from 'payload' +import type { Config, Plugin, UploadCollectionSlug } from 'payload' import { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage' @@ -30,7 +30,7 @@ export type AzureStorageOptions = { /** * Collection options to apply the Azure Blob adapter to. */ - collections: Record | true> + collections: Partial | true>> /** * Azure Blob storage connection string diff --git a/packages/storage-gcs/README.md b/packages/storage-gcs/README.md index 1b4a29af7..fc82b2fb2 100644 --- a/packages/storage-gcs/README.md +++ b/packages/storage-gcs/README.md @@ -25,8 +25,8 @@ export default buildConfig({ plugins: [ gcsStorage({ collections: { - [mediaSlug]: true, - [mediaWithPrefixSlug]: { + media: true, + 'media-with-prefix': { prefix, }, }, diff --git a/packages/storage-gcs/src/index.ts b/packages/storage-gcs/src/index.ts index a7b9139d7..ebd101766 100644 --- a/packages/storage-gcs/src/index.ts +++ b/packages/storage-gcs/src/index.ts @@ -5,7 +5,7 @@ import type { CollectionOptions, GeneratedAdapter, } from '@payloadcms/plugin-cloud-storage/types' -import type { Config, Plugin } from 'payload' +import type { Config, Plugin, UploadCollectionSlug } from 'payload' import { Storage } from '@google-cloud/storage' import { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage' @@ -25,7 +25,7 @@ export interface GcsStorageOptions { /** * Collection options to apply the S3 adapter to. */ - collections: Record | true> + collections: Partial | true>> /** * Whether or not to enable the plugin * diff --git a/packages/storage-s3/README.md b/packages/storage-s3/README.md index 5d0ac0b9c..b187b56fe 100644 --- a/packages/storage-s3/README.md +++ b/packages/storage-s3/README.md @@ -26,8 +26,8 @@ export default buildConfig({ plugins: [ s3Storage({ collections: { - [mediaSlug]: true, - [mediaWithPrefixSlug]: { + media: true, + 'media-with-prefix': { prefix, }, }, diff --git a/packages/storage-s3/src/index.ts b/packages/storage-s3/src/index.ts index afde5e491..d2a2efbe7 100644 --- a/packages/storage-s3/src/index.ts +++ b/packages/storage-s3/src/index.ts @@ -4,7 +4,7 @@ import type { CollectionOptions, GeneratedAdapter, } from '@payloadcms/plugin-cloud-storage/types' -import type { Config, Plugin } from 'payload' +import type { Config, Plugin, UploadCollectionSlug } from 'payload' import * as AWS from '@aws-sdk/client-s3' import { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage' @@ -31,7 +31,7 @@ export type S3StorageOptions = { /** * Collection options to apply the S3 adapter to. */ - collections: Record | true> + collections: Partial | true>> /** * AWS S3 client configuration. Highly dependent on your AWS setup. * diff --git a/packages/storage-uploadthing/README.md b/packages/storage-uploadthing/README.md index 07f9d3250..730b64e1c 100644 --- a/packages/storage-uploadthing/README.md +++ b/packages/storage-uploadthing/README.md @@ -20,7 +20,7 @@ export default buildConfig({ plugins: [ uploadthingStorage({ collections: { - [mediaSlug]: true, + media: true, }, options: { token: process.env.UPLOADTHING_TOKEN, diff --git a/packages/storage-uploadthing/src/index.ts b/packages/storage-uploadthing/src/index.ts index 3a91b8bcd..4c472c6f7 100644 --- a/packages/storage-uploadthing/src/index.ts +++ b/packages/storage-uploadthing/src/index.ts @@ -4,7 +4,7 @@ import type { CollectionOptions, GeneratedAdapter, } from '@payloadcms/plugin-cloud-storage/types' -import type { Config, Field, Plugin } from 'payload' +import type { Config, Field, Plugin, UploadCollectionSlug } from 'payload' import type { UTApiOptions } from 'uploadthing/types' import { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage' @@ -19,7 +19,7 @@ export type UploadthingStorageOptions = { /** * Collection options to apply the adapter to. */ - collections: Record | true> + collections: Partial | true>> /** * Whether or not to enable the plugin diff --git a/packages/storage-vercel-blob/README.md b/packages/storage-vercel-blob/README.md index a4472dca1..09be8dfd9 100644 --- a/packages/storage-vercel-blob/README.md +++ b/packages/storage-vercel-blob/README.md @@ -28,8 +28,8 @@ export default buildConfig({ enabled: true, // Optional, defaults to true // Specify which collections should use Vercel Blob collections: { - [Media.slug]: true, - [MediaWithPrefix.slug]: { + media: true, + 'media-with-prefix': { prefix: 'my-prefix', }, }, diff --git a/packages/storage-vercel-blob/src/index.ts b/packages/storage-vercel-blob/src/index.ts index 2afc82b75..47d51a87f 100644 --- a/packages/storage-vercel-blob/src/index.ts +++ b/packages/storage-vercel-blob/src/index.ts @@ -4,7 +4,7 @@ import type { CollectionOptions, GeneratedAdapter, } from '@payloadcms/plugin-cloud-storage/types' -import type { Config, Plugin } from 'payload' +import type { Config, Plugin, UploadCollectionSlug } from 'payload' import { cloudStoragePlugin } from '@payloadcms/plugin-cloud-storage' @@ -39,7 +39,7 @@ export type VercelBlobStorageOptions = { /** * Collections to apply the Vercel Blob adapter to */ - collections: Record | true> + collections: Partial | true>> /** * Whether or not to enable the plugin diff --git a/packages/ui/src/elements/ListDrawer/types.ts b/packages/ui/src/elements/ListDrawer/types.ts index c61ffeeb8..68de71b2a 100644 --- a/packages/ui/src/elements/ListDrawer/types.ts +++ b/packages/ui/src/elements/ListDrawer/types.ts @@ -6,7 +6,7 @@ import type { ListDrawerContextProps } from './Provider.js' export type ListDrawerProps = { readonly allowCreate?: boolean - readonly collectionSlugs: string[] + readonly collectionSlugs: SanitizedCollectionConfig['slug'][] readonly drawerSlug?: string readonly enableRowSelections?: boolean readonly filterOptions?: FilterOptionsResult @@ -21,9 +21,9 @@ export type ListTogglerProps = { } & HTMLAttributes export type UseListDrawer = (args: { - collectionSlugs?: string[] + collectionSlugs?: SanitizedCollectionConfig['slug'][] filterOptions?: FilterOptionsResult - selectedCollection?: string + selectedCollection?: SanitizedCollectionConfig['slug'] uploads?: boolean // finds all collections with upload: true }) => [ React.FC< diff --git a/templates/vercel-postgres/src/payload.config.ts b/templates/vercel-postgres/src/payload.config.ts index 50d264fcf..959340e86 100644 --- a/templates/vercel-postgres/src/payload.config.ts +++ b/templates/vercel-postgres/src/payload.config.ts @@ -26,7 +26,7 @@ export default buildConfig({ plugins: [ vercelBlobStorage({ collections: { - [Media.slug]: true, + media: true, }, token: process.env.BLOB_READ_WRITE_TOKEN || '', }), diff --git a/templates/with-vercel-mongodb/src/payload.config.ts b/templates/with-vercel-mongodb/src/payload.config.ts index ac41374c4..990546d2a 100644 --- a/templates/with-vercel-mongodb/src/payload.config.ts +++ b/templates/with-vercel-mongodb/src/payload.config.ts @@ -30,7 +30,7 @@ export default buildConfig({ plugins: [ vercelBlobStorage({ collections: { - [Media.slug]: true, + media: true, }, token: process.env.BLOB_READ_WRITE_TOKEN || '', }), diff --git a/templates/with-vercel-postgres/src/payload.config.ts b/templates/with-vercel-postgres/src/payload.config.ts index cb394a626..5d8f4eb42 100644 --- a/templates/with-vercel-postgres/src/payload.config.ts +++ b/templates/with-vercel-postgres/src/payload.config.ts @@ -32,7 +32,7 @@ export default buildConfig({ plugins: [ vercelBlobStorage({ collections: { - [Media.slug]: true, + slug: true, }, token: process.env.BLOB_READ_WRITE_TOKEN || '', }),