feat: custom db naming for postgres and mongodb (#5697)
This commit is contained in:
@@ -30,6 +30,7 @@ It's often best practice to write your Collections in separate files and then im
|
|||||||
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
||||||
| **`disableDuplicate`** | When true, do not show the "Duplicate" button while editing documents within this collection and prevent `duplicate` from all APIs. |
|
| **`disableDuplicate`** | When true, do not show the "Duplicate" button while editing documents within this collection and prevent `duplicate` from all APIs. |
|
||||||
| **`defaultSort`** | Pass a top-level field to sort by default in the collection List view. Prefix the name of the field with a minus symbol ("-") to sort in descending order. |
|
| **`defaultSort`** | Pass a top-level field to sort by default in the collection List view. Prefix the name of the field with a minus symbol ("-") to sort in descending order. |
|
||||||
|
| **`dbName`** | Custom table or collection name depending on the database adapter. Auto-generated from slug if not defined.
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
|
|
||||||
_\* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ As with Collection configs, it's often best practice to write your Globals in se
|
|||||||
| **`graphQL.name`** | Text used in schema generation. Auto-generated from slug if not defined. |
|
| **`graphQL.name`** | Text used in schema generation. Auto-generated from slug if not defined. |
|
||||||
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
| **`typescript`** | An object with property `interface` as the text used in schema generation. Auto-generated from slug if not defined. |
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
|
| **`dbName`** | Custom table or collection name for this global depending on the database adapter. Auto-generated from slug if not defined.
|
||||||
|
|
||||||
_\* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
|
|||||||
@@ -38,12 +38,18 @@ export default buildConfig({
|
|||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `pool` | [Pool connection options](https://orm.drizzle.team/docs/quick-postgresql/node-postgres) that will be passed to Drizzle and `node-postgres`. |
|
| `pool` \* | [Pool connection options](https://orm.drizzle.team/docs/quick-postgresql/node-postgres) that will be passed to Drizzle and `node-postgres`. |
|
||||||
| `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. |
|
| `push` | Disable Drizzle's [`db push`](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push) in development mode. By default, `push` is enabled for development mode only. |
|
||||||
| `migrationDir` | Customize the directory that migrations are stored. |
|
| `migrationDir` | Customize the directory that migrations are stored. |
|
||||||
|
| `logger` | The instance of the logger to be passed to drizzle. By default Payload's will be used. |
|
||||||
| `schemaName` | A string for the postgres schema to use, defaults to 'public'. |
|
| `schemaName` | A string for the postgres schema to use, defaults to 'public'. |
|
||||||
|
| `localesSuffix` | A string appended to the end of table names for storing localized fields. Default is '_locales'. |
|
||||||
|
| `relationshipsSuffix` | A string appended to the end of table names for storing relationships. Default is '_rels'. |
|
||||||
|
| `versionsSuffix` | A string appended to the end of table names for storing versions. Defaults to '_v'. |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Access to Drizzle
|
### Access to Drizzle
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ keywords: array, fields, config, configuration, documentation, Content Managemen
|
|||||||
| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
|
| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
|
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
|
||||||
|
| **`dbName`** | Custom table name for the field when using SQL database adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
|
||||||
|
|
||||||
_\* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ Blocks are defined as separate configs of their own.
|
|||||||
| **`imageAltText`** | Customize this block's image thumbnail alt text. |
|
| **`imageAltText`** | Customize this block's image thumbnail alt text. |
|
||||||
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
|
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
|
||||||
| **`graphQL.singularName`** | Text to use for the GraphQL schema name. Auto-generated from slug if not defined. NOTE: this is set for deprecation, prefer `interfaceName`. |
|
| **`graphQL.singularName`** | Text to use for the GraphQL schema name. Auto-generated from slug if not defined. NOTE: this is set for deprecation, prefer `interfaceName`. |
|
||||||
|
| **`dbName`** | Custom table name for this block type when using SQL database adapter ([Postgres](/docs/database/postgres)). Auto-generated from slug if not defined.
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
|
|
||||||
#### Auto-generated data per block
|
#### Auto-generated data per block
|
||||||
|
|||||||
@@ -20,27 +20,27 @@ keywords: number, fields, config, configuration, documentation, Content Manageme
|
|||||||
|
|
||||||
### Config
|
### Config
|
||||||
|
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||||
| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
|
| **`label`** | Text used as a field label in the Admin panel or an object with keys for each language. |
|
||||||
| **`min`** | Minimum value accepted. Used in the default `validation` function. |
|
| **`min`** | Minimum value accepted. Used in the default `validation` function. |
|
||||||
| **`max`** | Maximum value accepted. Used in the default `validation` function. |
|
| **`max`** | Maximum value accepted. Used in the default `validation` function. |
|
||||||
| **`hasMany`** | Makes this field an ordered array of numbers instead of just a single number. |
|
| **`hasMany`** | Makes this field an ordered array of numbers instead of just a single number. |
|
||||||
| **`minRows`** | Minimum number of numbers in the numbers array, if `hasMany` is set to true. |
|
| **`minRows`** | Minimum number of numbers in the numbers array, if `hasMany` is set to true. |
|
||||||
| **`maxRows`** | Maximum number of numbers in the numbers array, if `hasMany` is set to true. |
|
| **`maxRows`** | Maximum number of numbers in the numbers array, if `hasMany` is set to true. |
|
||||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
|
| **`validate`** | Provide a custom validation function that will be executed on both the Admin panel and the backend. [More](/docs/fields/overview#validation) |
|
||||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
|
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/config), include its data in the user JWT. |
|
||||||
| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
|
| **`hooks`** | Provide field-based hooks to control logic for this field. [More](/docs/fields/overview#field-level-hooks) |
|
||||||
| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
|
| **`access`** | Provide field-based access control to denote what users can see and do with this field's data. [More](/docs/fields/overview#field-level-access-control) |
|
||||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
|
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin panel. |
|
||||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||||
| **`required`** | Require this field to have a value. |
|
| **`required`** | Require this field to have a value. |
|
||||||
| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
|
| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
|
|
||||||
_\* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ keywords: radio, fields, config, configuration, documentation, Content Managemen
|
|||||||
| **`required`** | Require this field to have a value. |
|
| **`required`** | Require this field to have a value. |
|
||||||
| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
|
| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
|
| **`enumName`** | Custom enum name for this field when using SQL database adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined.
|
||||||
|
|
||||||
_\* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ keywords: select, multi-select, fields, config, configuration, documentation, Co
|
|||||||
| **`required`** | Require this field to have a value. |
|
| **`required`** | Require this field to have a value. |
|
||||||
| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-config) for more details. |
|
| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-config) for more details. |
|
||||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||||
|
| **`enumName`** | Custom enum name for this field when using SQL database adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
|
||||||
|
| **`dbName`** | Custom table name (if `hasMany` set to `true`) for this field when using SQL database adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
|
||||||
|
|
||||||
_\* An asterisk denotes that a property is required._
|
_\* An asterisk denotes that a property is required._
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
"get-port": "5.1.1",
|
"get-port": "5.1.1",
|
||||||
"http-status": "1.6.2",
|
"http-status": "1.6.2",
|
||||||
"mongoose": "6.12.3",
|
"mongoose": "6.12.3",
|
||||||
"mongoose-aggregate-paginate-v2": "1.0.6",
|
|
||||||
"mongoose-paginate-v2": "1.7.22",
|
"mongoose-paginate-v2": "1.7.22",
|
||||||
"prompts": "2.4.2",
|
"prompts": "2.4.2",
|
||||||
"uuid": "9.0.0"
|
"uuid": "9.0.0"
|
||||||
|
|||||||
@@ -5,11 +5,7 @@ import type { SanitizedCollectionConfig } from 'payload/types'
|
|||||||
|
|
||||||
import mongoose from 'mongoose'
|
import mongoose from 'mongoose'
|
||||||
import paginate from 'mongoose-paginate-v2'
|
import paginate from 'mongoose-paginate-v2'
|
||||||
import {
|
import { buildVersionCollectionFields, buildVersionGlobalFields } from 'payload/versions'
|
||||||
buildVersionCollectionFields,
|
|
||||||
buildVersionGlobalFields,
|
|
||||||
getVersionsModelName,
|
|
||||||
} from 'payload/versions'
|
|
||||||
|
|
||||||
import type { MongooseAdapter } from './index.js'
|
import type { MongooseAdapter } from './index.js'
|
||||||
import type { CollectionModel } from './types.js'
|
import type { CollectionModel } from './types.js'
|
||||||
@@ -18,13 +14,14 @@ import buildCollectionSchema from './models/buildCollectionSchema.js'
|
|||||||
import { buildGlobalModel } from './models/buildGlobalModel.js'
|
import { buildGlobalModel } from './models/buildGlobalModel.js'
|
||||||
import buildSchema from './models/buildSchema.js'
|
import buildSchema from './models/buildSchema.js'
|
||||||
import getBuildQueryPlugin from './queries/buildQuery.js'
|
import getBuildQueryPlugin from './queries/buildQuery.js'
|
||||||
|
import { getDBName } from './utilities/getDBName.js'
|
||||||
|
|
||||||
export const init: Init = function init(this: MongooseAdapter) {
|
export const init: Init = function init(this: MongooseAdapter) {
|
||||||
this.payload.config.collections.forEach((collection: SanitizedCollectionConfig) => {
|
this.payload.config.collections.forEach((collection: SanitizedCollectionConfig) => {
|
||||||
const schema = buildCollectionSchema(collection, this.payload.config)
|
const schema = buildCollectionSchema(collection, this.payload.config)
|
||||||
|
|
||||||
if (collection.versions) {
|
if (collection.versions) {
|
||||||
const versionModelName = getVersionsModelName(collection)
|
const versionModelName = getDBName({ config: collection, versions: true })
|
||||||
|
|
||||||
const versionCollectionFields = buildVersionCollectionFields(collection)
|
const versionCollectionFields = buildVersionCollectionFields(collection)
|
||||||
|
|
||||||
@@ -54,7 +51,7 @@ export const init: Init = function init(this: MongooseAdapter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const model = mongoose.model(
|
const model = mongoose.model(
|
||||||
collection.slug,
|
getDBName({ config: collection }),
|
||||||
schema,
|
schema,
|
||||||
this.autoPluralization === true ? undefined : collection.slug,
|
this.autoPluralization === true ? undefined : collection.slug,
|
||||||
) as CollectionModel
|
) as CollectionModel
|
||||||
@@ -72,7 +69,7 @@ export const init: Init = function init(this: MongooseAdapter) {
|
|||||||
|
|
||||||
this.payload.config.globals.forEach((global) => {
|
this.payload.config.globals.forEach((global) => {
|
||||||
if (global.versions) {
|
if (global.versions) {
|
||||||
const versionModelName = getVersionsModelName(global)
|
const versionModelName = getDBName({ config: global, versions: true })
|
||||||
|
|
||||||
const versionGlobalFields = buildVersionGlobalFields(global)
|
const versionGlobalFields = buildVersionGlobalFields(global)
|
||||||
|
|
||||||
|
|||||||
@@ -363,7 +363,7 @@ const fieldToSchemaMap: Record<string, FieldSchemaGenerator> = {
|
|||||||
}
|
}
|
||||||
if (field.localized && config.localization) {
|
if (field.localized && config.localization) {
|
||||||
config.localization.locales.forEach((locale) => {
|
config.localization.locales.forEach((locale) => {
|
||||||
schema.index({ [`${field.name}.${locale}`]: '2dsphere' }, indexOptions)
|
schema.index({ [`${field.name}.${locale.code}`]: '2dsphere' }, indexOptions)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
schema.index({ [field.name]: '2dsphere' }, indexOptions)
|
schema.index({ [field.name]: '2dsphere' }, indexOptions)
|
||||||
|
|||||||
41
packages/db-mongodb/src/utilities/getDBName.ts
Normal file
41
packages/db-mongodb/src/utilities/getDBName.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import type { DBIdentifierName } from 'payload/database'
|
||||||
|
|
||||||
|
type Args = {
|
||||||
|
config: {
|
||||||
|
dbName?: DBIdentifierName
|
||||||
|
enumName?: DBIdentifierName
|
||||||
|
name?: string
|
||||||
|
slug?: string
|
||||||
|
}
|
||||||
|
locales?: boolean
|
||||||
|
target?: 'dbName' | 'enumName'
|
||||||
|
versions?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to name database enums and collections
|
||||||
|
* Returns the collection or enum name for a given entity
|
||||||
|
*/
|
||||||
|
export const getDBName = ({
|
||||||
|
config: { name, slug },
|
||||||
|
config,
|
||||||
|
target = 'dbName',
|
||||||
|
versions = false,
|
||||||
|
}: Args): string => {
|
||||||
|
let result: string
|
||||||
|
let custom = config[target]
|
||||||
|
|
||||||
|
if (!custom && target === 'enumName') {
|
||||||
|
custom = config['dbName']
|
||||||
|
}
|
||||||
|
|
||||||
|
if (custom) {
|
||||||
|
result = typeof custom === 'function' ? custom({}) : custom
|
||||||
|
} else {
|
||||||
|
result = name ?? slug
|
||||||
|
}
|
||||||
|
|
||||||
|
if (versions) result = `_${result}_versions`
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
import type { Create } from 'payload/database'
|
import type { Create } from 'payload/database'
|
||||||
|
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
import { upsertRow } from './upsertRow/index.js'
|
import { upsertRow } from './upsertRow/index.js'
|
||||||
|
|
||||||
export const create: Create = async function create(
|
export const create: Create = async function create(
|
||||||
@@ -20,7 +19,10 @@ export const create: Create = async function create(
|
|||||||
fields: collection.fields,
|
fields: collection.fields,
|
||||||
operation: 'create',
|
operation: 'create',
|
||||||
req,
|
req,
|
||||||
tableName: toSnakeCase(collectionSlug),
|
tableName: getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collection,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import type { CreateGlobalArgs } from 'payload/database'
|
import type { CreateGlobalArgs } from 'payload/database'
|
||||||
import type { PayloadRequest, TypeWithID } from 'payload/types'
|
import type { PayloadRequest, TypeWithID } from 'payload/types'
|
||||||
|
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
import { upsertRow } from './upsertRow/index.js'
|
import { upsertRow } from './upsertRow/index.js'
|
||||||
|
|
||||||
export async function createGlobal<T extends TypeWithID>(
|
export async function createGlobal<T extends TypeWithID>(
|
||||||
@@ -21,7 +20,10 @@ export async function createGlobal<T extends TypeWithID>(
|
|||||||
fields: globalConfig.fields,
|
fields: globalConfig.fields,
|
||||||
operation: 'create',
|
operation: 'create',
|
||||||
req,
|
req,
|
||||||
tableName: toSnakeCase(slug),
|
tableName: getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: globalConfig,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import type { PayloadRequest, TypeWithID } from 'payload/types'
|
|||||||
import { sql } from 'drizzle-orm'
|
import { sql } from 'drizzle-orm'
|
||||||
import { type CreateGlobalVersionArgs } from 'payload/database'
|
import { type CreateGlobalVersionArgs } from 'payload/database'
|
||||||
import { buildVersionGlobalFields } from 'payload/versions'
|
import { buildVersionGlobalFields } from 'payload/versions'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
import { upsertRow } from './upsertRow/index.js'
|
import { upsertRow } from './upsertRow/index.js'
|
||||||
|
|
||||||
export async function createGlobalVersion<T extends TypeWithID>(
|
export async function createGlobalVersion<T extends TypeWithID>(
|
||||||
@@ -16,8 +16,11 @@ export async function createGlobalVersion<T extends TypeWithID>(
|
|||||||
) {
|
) {
|
||||||
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
||||||
const global = this.payload.globals.config.find(({ slug }) => slug === globalSlug)
|
const global = this.payload.globals.config.find(({ slug }) => slug === globalSlug)
|
||||||
const globalTableName = toSnakeCase(globalSlug)
|
const tableName = getTableName({
|
||||||
const tableName = `_${globalTableName}_v`
|
adapter: this,
|
||||||
|
config: global,
|
||||||
|
versions: true,
|
||||||
|
})
|
||||||
|
|
||||||
const result = await upsertRow<TypeWithVersion<T>>({
|
const result = await upsertRow<TypeWithVersion<T>>({
|
||||||
adapter: this,
|
adapter: this,
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import type { PayloadRequest, TypeWithID } from 'payload/types'
|
|||||||
|
|
||||||
import { sql } from 'drizzle-orm'
|
import { sql } from 'drizzle-orm'
|
||||||
import { buildVersionCollectionFields } from 'payload/versions'
|
import { buildVersionCollectionFields } from 'payload/versions'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
import { upsertRow } from './upsertRow/index.js'
|
import { upsertRow } from './upsertRow/index.js'
|
||||||
|
|
||||||
export async function createVersion<T extends TypeWithID>(
|
export async function createVersion<T extends TypeWithID>(
|
||||||
@@ -21,8 +21,11 @@ export async function createVersion<T extends TypeWithID>(
|
|||||||
) {
|
) {
|
||||||
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
||||||
const collection = this.payload.collections[collectionSlug].config
|
const collection = this.payload.collections[collectionSlug].config
|
||||||
const collectionTableName = toSnakeCase(collectionSlug)
|
const tableName = getTableName({
|
||||||
const tableName = `_${collectionTableName}_v`
|
adapter: this,
|
||||||
|
config: collection,
|
||||||
|
versions: true,
|
||||||
|
})
|
||||||
|
|
||||||
const result = await upsertRow<TypeWithVersion<T>>({
|
const result = await upsertRow<TypeWithVersion<T>>({
|
||||||
adapter: this,
|
adapter: this,
|
||||||
@@ -40,7 +43,15 @@ export async function createVersion<T extends TypeWithID>(
|
|||||||
})
|
})
|
||||||
|
|
||||||
const table = this.tables[tableName]
|
const table = this.tables[tableName]
|
||||||
const relationshipsTable = this.tables[`${tableName}_rels`]
|
const relationshipsTable =
|
||||||
|
this.tables[
|
||||||
|
getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collection,
|
||||||
|
relationships: true,
|
||||||
|
versions: true,
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
||||||
if (collection.versions.drafts) {
|
if (collection.versions.drafts) {
|
||||||
await db.execute(sql`
|
await db.execute(sql`
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import type { DeleteMany } from 'payload/database'
|
|||||||
import type { PayloadRequest } from 'payload/types'
|
import type { PayloadRequest } from 'payload/types'
|
||||||
|
|
||||||
import { inArray } from 'drizzle-orm'
|
import { inArray } from 'drizzle-orm'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import { findMany } from './find/findMany.js'
|
import { findMany } from './find/findMany.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
|
|
||||||
export const deleteMany: DeleteMany = async function deleteMany(
|
export const deleteMany: DeleteMany = async function deleteMany(
|
||||||
this: PostgresAdapter,
|
this: PostgresAdapter,
|
||||||
@@ -14,7 +14,7 @@ export const deleteMany: DeleteMany = async function deleteMany(
|
|||||||
) {
|
) {
|
||||||
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
||||||
const collectionConfig = this.payload.collections[collection].config
|
const collectionConfig = this.payload.collections[collection].config
|
||||||
const tableName = toSnakeCase(collection)
|
const tableName = getTableName({ adapter: this, config: collectionConfig })
|
||||||
|
|
||||||
const result = await findMany({
|
const result = await findMany({
|
||||||
adapter: this,
|
adapter: this,
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ import type { DeleteOne } from 'payload/database'
|
|||||||
import type { PayloadRequest } from 'payload/types'
|
import type { PayloadRequest } from 'payload/types'
|
||||||
|
|
||||||
import { eq } from 'drizzle-orm'
|
import { eq } from 'drizzle-orm'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import { buildFindManyArgs } from './find/buildFindManyArgs.js'
|
import { buildFindManyArgs } from './find/buildFindManyArgs.js'
|
||||||
import buildQuery from './queries/buildQuery.js'
|
import buildQuery from './queries/buildQuery.js'
|
||||||
import { selectDistinct } from './queries/selectDistinct.js'
|
import { selectDistinct } from './queries/selectDistinct.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
import { transform } from './transform/read/index.js'
|
import { transform } from './transform/read/index.js'
|
||||||
|
|
||||||
export const deleteOne: DeleteOne = async function deleteOne(
|
export const deleteOne: DeleteOne = async function deleteOne(
|
||||||
@@ -17,7 +17,10 @@ export const deleteOne: DeleteOne = async function deleteOne(
|
|||||||
) {
|
) {
|
||||||
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
||||||
const collection = this.payload.collections[collectionSlug].config
|
const collection = this.payload.collections[collectionSlug].config
|
||||||
const tableName = toSnakeCase(collectionSlug)
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collection,
|
||||||
|
})
|
||||||
let docToDelete: Record<string, unknown>
|
let docToDelete: Record<string, unknown>
|
||||||
|
|
||||||
const { joinAliases, joins, selectFields, where } = await buildQuery({
|
const { joinAliases, joins, selectFields, where } = await buildQuery({
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types'
|
|||||||
|
|
||||||
import { inArray } from 'drizzle-orm'
|
import { inArray } from 'drizzle-orm'
|
||||||
import { buildVersionCollectionFields } from 'payload/versions'
|
import { buildVersionCollectionFields } from 'payload/versions'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import { findMany } from './find/findMany.js'
|
import { findMany } from './find/findMany.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
|
|
||||||
export const deleteVersions: DeleteVersions = async function deleteVersion(
|
export const deleteVersions: DeleteVersions = async function deleteVersion(
|
||||||
this: PostgresAdapter,
|
this: PostgresAdapter,
|
||||||
@@ -16,7 +16,11 @@ export const deleteVersions: DeleteVersions = async function deleteVersion(
|
|||||||
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
||||||
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
||||||
|
|
||||||
const tableName = `_${toSnakeCase(collection)}_v`
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collectionConfig,
|
||||||
|
versions: true,
|
||||||
|
})
|
||||||
const fields = buildVersionCollectionFields(collectionConfig)
|
const fields = buildVersionCollectionFields(collectionConfig)
|
||||||
|
|
||||||
const { docs } = await findMany({
|
const { docs } = await findMany({
|
||||||
|
|||||||
@@ -1,38 +1,41 @@
|
|||||||
import type { Find } from 'payload/database'
|
import type { Find } from 'payload/database'
|
||||||
import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types'
|
import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types'
|
||||||
|
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import { findMany } from './find/findMany.js'
|
import { findMany } from './find/findMany.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
|
|
||||||
export const find: Find = async function find(
|
export const find: Find = async function find(
|
||||||
this: PostgresAdapter,
|
this: PostgresAdapter,
|
||||||
{
|
{
|
||||||
collection,
|
collection,
|
||||||
limit: limitArg,
|
limit,
|
||||||
locale,
|
locale,
|
||||||
page = 1,
|
page = 1,
|
||||||
pagination,
|
pagination,
|
||||||
req = {} as PayloadRequest,
|
req = {} as PayloadRequest,
|
||||||
sort: sortArg,
|
sort: sortArg,
|
||||||
where: whereArg,
|
where,
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
||||||
const sort = typeof sortArg === 'string' ? sortArg : collectionConfig.defaultSort
|
const sort = typeof sortArg === 'string' ? sortArg : collectionConfig.defaultSort
|
||||||
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collectionConfig,
|
||||||
|
})
|
||||||
|
|
||||||
return findMany({
|
return findMany({
|
||||||
adapter: this,
|
adapter: this,
|
||||||
fields: collectionConfig.fields,
|
fields: collectionConfig.fields,
|
||||||
limit: limitArg,
|
limit,
|
||||||
locale,
|
locale,
|
||||||
page,
|
page,
|
||||||
pagination,
|
pagination,
|
||||||
req,
|
req,
|
||||||
sort,
|
sort,
|
||||||
tableName: toSnakeCase(collection),
|
tableName,
|
||||||
where: whereArg,
|
where,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
import type { Field } from 'payload/types'
|
import type { Field } from 'payload/types'
|
||||||
|
|
||||||
import { fieldAffectsData, tabHasName } from 'payload/types'
|
import { fieldAffectsData, tabHasName } from 'payload/types'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from '../types.js'
|
import type { PostgresAdapter } from '../types.js'
|
||||||
import type { Result } from './buildFindManyArgs.js'
|
import type { Result } from './buildFindManyArgs.js'
|
||||||
|
|
||||||
|
import { getTableName } from '../schema/getTableName.js'
|
||||||
|
|
||||||
type TraverseFieldArgs = {
|
type TraverseFieldArgs = {
|
||||||
_locales: Record<string, unknown>
|
_locales: Record<string, unknown>
|
||||||
adapter: PostgresAdapter
|
adapter: PostgresAdapter
|
||||||
@@ -78,9 +79,22 @@ export const traverseFields = ({
|
|||||||
with: {},
|
with: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
const arrayTableName = `${currentTableName}_${path}${toSnakeCase(field.name)}`
|
const arrayTableName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: field,
|
||||||
|
parentTableName: currentTableName,
|
||||||
|
prefix: `${currentTableName}_${path}`,
|
||||||
|
})
|
||||||
|
|
||||||
if (adapter.tables[`${arrayTableName}_locales`]) withArray.with._locales = _locales
|
const arrayTableNameWithLocales = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: field,
|
||||||
|
locales: true,
|
||||||
|
parentTableName: currentTableName,
|
||||||
|
prefix: `${currentTableName}_${path}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (adapter.tables[arrayTableNameWithLocales]) withArray.with._locales = _locales
|
||||||
currentArgs.with[`${path}${field.name}`] = withArray
|
currentArgs.with[`${path}${field.name}`] = withArray
|
||||||
|
|
||||||
traverseFields({
|
traverseFields({
|
||||||
@@ -128,9 +142,16 @@ export const traverseFields = ({
|
|||||||
with: {},
|
with: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
const tableName = `${topLevelTableName}_blocks_${toSnakeCase(block.slug)}`
|
const tableName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: block,
|
||||||
|
parentTableName: topLevelTableName,
|
||||||
|
prefix: `${topLevelTableName}_blocks_`,
|
||||||
|
})
|
||||||
|
|
||||||
if (adapter.tables[`${tableName}_locales`]) withBlock.with._locales = _locales
|
if (adapter.tables[`${tableName}${adapter.localesSuffix}`]) {
|
||||||
|
withBlock.with._locales = _locales
|
||||||
|
}
|
||||||
topLevelArgs.with[blockKey] = withBlock
|
topLevelArgs.with[blockKey] = withBlock
|
||||||
|
|
||||||
traverseFields({
|
traverseFields({
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
import type { FindGlobal } from 'payload/database'
|
import type { FindGlobal } from 'payload/database'
|
||||||
|
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import { findMany } from './find/findMany.js'
|
import { findMany } from './find/findMany.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
|
|
||||||
export const findGlobal: FindGlobal = async function findGlobal(
|
export const findGlobal: FindGlobal = async function findGlobal(
|
||||||
this: PostgresAdapter,
|
this: PostgresAdapter,
|
||||||
{ slug, locale, req, where },
|
{ slug, locale, req, where },
|
||||||
) {
|
) {
|
||||||
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug)
|
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug)
|
||||||
const tableName = toSnakeCase(slug)
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: globalConfig,
|
||||||
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
docs: [doc],
|
docs: [doc],
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import type { FindGlobalVersions } from 'payload/database'
|
|||||||
import type { PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
|
import type { PayloadRequest, SanitizedGlobalConfig } from 'payload/types'
|
||||||
|
|
||||||
import { buildVersionGlobalFields } from 'payload/versions'
|
import { buildVersionGlobalFields } from 'payload/versions'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import { findMany } from './find/findMany.js'
|
import { findMany } from './find/findMany.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
|
|
||||||
export const findGlobalVersions: FindGlobalVersions = async function findGlobalVersions(
|
export const findGlobalVersions: FindGlobalVersions = async function findGlobalVersions(
|
||||||
this: PostgresAdapter,
|
this: PostgresAdapter,
|
||||||
@@ -27,7 +27,11 @@ export const findGlobalVersions: FindGlobalVersions = async function findGlobalV
|
|||||||
)
|
)
|
||||||
const sort = typeof sortArg === 'string' ? sortArg : '-createdAt'
|
const sort = typeof sortArg === 'string' ? sortArg : '-createdAt'
|
||||||
|
|
||||||
const tableName = `_${toSnakeCase(global)}_v`
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: globalConfig,
|
||||||
|
versions: true,
|
||||||
|
})
|
||||||
const fields = buildVersionGlobalFields(globalConfig)
|
const fields = buildVersionGlobalFields(globalConfig)
|
||||||
|
|
||||||
return findMany({
|
return findMany({
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
import type { FindOneArgs } from 'payload/database'
|
import type { FindOneArgs } from 'payload/database'
|
||||||
import type { PayloadRequest, SanitizedCollectionConfig, TypeWithID } from 'payload/types'
|
import type { PayloadRequest, SanitizedCollectionConfig, TypeWithID } from 'payload/types'
|
||||||
|
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import { findMany } from './find/findMany.js'
|
import { findMany } from './find/findMany.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
|
|
||||||
export async function findOne<T extends TypeWithID>(
|
export async function findOne<T extends TypeWithID>(
|
||||||
this: PostgresAdapter,
|
this: PostgresAdapter,
|
||||||
{ collection, locale, req = {} as PayloadRequest, where: incomingWhere }: FindOneArgs,
|
{ collection, locale, req = {} as PayloadRequest, where }: FindOneArgs,
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
||||||
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collectionConfig,
|
||||||
|
})
|
||||||
|
|
||||||
const { docs } = await findMany({
|
const { docs } = await findMany({
|
||||||
adapter: this,
|
adapter: this,
|
||||||
@@ -22,8 +25,8 @@ export async function findOne<T extends TypeWithID>(
|
|||||||
pagination: false,
|
pagination: false,
|
||||||
req,
|
req,
|
||||||
sort: undefined,
|
sort: undefined,
|
||||||
tableName: toSnakeCase(collection),
|
tableName,
|
||||||
where: incomingWhere,
|
where,
|
||||||
})
|
})
|
||||||
|
|
||||||
return docs?.[0] || null
|
return docs?.[0] || null
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import type { FindVersions } from 'payload/database'
|
|||||||
import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types'
|
import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types'
|
||||||
|
|
||||||
import { buildVersionCollectionFields } from 'payload/versions'
|
import { buildVersionCollectionFields } from 'payload/versions'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import { findMany } from './find/findMany.js'
|
import { findMany } from './find/findMany.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
|
|
||||||
export const findVersions: FindVersions = async function findVersions(
|
export const findVersions: FindVersions = async function findVersions(
|
||||||
this: PostgresAdapter,
|
this: PostgresAdapter,
|
||||||
@@ -25,7 +25,11 @@ export const findVersions: FindVersions = async function findVersions(
|
|||||||
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
||||||
const sort = typeof sortArg === 'string' ? sortArg : collectionConfig.defaultSort
|
const sort = typeof sortArg === 'string' ? sortArg : collectionConfig.defaultSort
|
||||||
|
|
||||||
const tableName = `_${toSnakeCase(collection)}_v`
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collectionConfig,
|
||||||
|
versions: true,
|
||||||
|
})
|
||||||
const fields = buildVersionCollectionFields(collectionConfig)
|
const fields = buildVersionCollectionFields(collectionConfig)
|
||||||
|
|
||||||
return findMany({
|
return findMany({
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import type { Payload } from 'payload'
|
import type { Payload } from 'payload'
|
||||||
import type { DatabaseAdapterObj } from 'payload/database'
|
import type { DatabaseAdapterObj } from 'payload/database'
|
||||||
export type { MigrateDownArgs, MigrateUpArgs } from './types.js'
|
|
||||||
|
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
@@ -39,6 +38,8 @@ import { updateGlobal } from './updateGlobal.js'
|
|||||||
import { updateGlobalVersion } from './updateGlobalVersion.js'
|
import { updateGlobalVersion } from './updateGlobalVersion.js'
|
||||||
import { updateVersion } from './updateVersion.js'
|
import { updateVersion } from './updateVersion.js'
|
||||||
|
|
||||||
|
export type { MigrateDownArgs, MigrateUpArgs } from './types.js'
|
||||||
|
|
||||||
export { sql } from 'drizzle-orm'
|
export { sql } from 'drizzle-orm'
|
||||||
|
|
||||||
export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter> {
|
export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter> {
|
||||||
@@ -50,20 +51,24 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter>
|
|||||||
name: 'postgres',
|
name: 'postgres',
|
||||||
|
|
||||||
// Postgres-specific
|
// Postgres-specific
|
||||||
|
blockTableNames: {},
|
||||||
drizzle: undefined,
|
drizzle: undefined,
|
||||||
enums: {},
|
enums: {},
|
||||||
fieldConstraints: {},
|
fieldConstraints: {},
|
||||||
idType,
|
idType,
|
||||||
|
localesSuffix: args.localesSuffix || '_locales',
|
||||||
logger: args.logger,
|
logger: args.logger,
|
||||||
pgSchema: undefined,
|
pgSchema: undefined,
|
||||||
pool: undefined,
|
pool: undefined,
|
||||||
poolOptions: args.pool,
|
poolOptions: args.pool,
|
||||||
push: args.push,
|
push: args.push,
|
||||||
relations: {},
|
relations: {},
|
||||||
|
relationshipsSuffix: args.relationshipsSuffix || '_rels',
|
||||||
schema: {},
|
schema: {},
|
||||||
schemaName: args.schemaName,
|
schemaName: args.schemaName,
|
||||||
sessions: {},
|
sessions: {},
|
||||||
tables: {},
|
tables: {},
|
||||||
|
versionsSuffix: args.versionsSuffix || '_v',
|
||||||
|
|
||||||
// DatabaseAdapter
|
// DatabaseAdapter
|
||||||
beginTransaction,
|
beginTransaction,
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import type { SanitizedCollectionConfig } from 'payload/types'
|
|||||||
|
|
||||||
import { pgEnum, pgSchema, pgTable } from 'drizzle-orm/pg-core'
|
import { pgEnum, pgSchema, pgTable } from 'drizzle-orm/pg-core'
|
||||||
import { buildVersionCollectionFields, buildVersionGlobalFields } from 'payload/versions'
|
import { buildVersionCollectionFields, buildVersionGlobalFields } from 'payload/versions'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import { buildTable } from './schema/build.js'
|
import { buildTable } from './schema/build.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
|
|
||||||
export const init: Init = function init(this: PostgresAdapter) {
|
export const init: Init = function init(this: PostgresAdapter) {
|
||||||
if (this.schemaName) {
|
if (this.schemaName) {
|
||||||
@@ -25,7 +25,10 @@ export const init: Init = function init(this: PostgresAdapter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.payload.config.collections.forEach((collection: SanitizedCollectionConfig) => {
|
this.payload.config.collections.forEach((collection: SanitizedCollectionConfig) => {
|
||||||
const tableName = toSnakeCase(collection.slug)
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collection,
|
||||||
|
})
|
||||||
|
|
||||||
buildTable({
|
buildTable({
|
||||||
adapter: this,
|
adapter: this,
|
||||||
@@ -37,10 +40,15 @@ export const init: Init = function init(this: PostgresAdapter) {
|
|||||||
fields: collection.fields,
|
fields: collection.fields,
|
||||||
tableName,
|
tableName,
|
||||||
timestamps: collection.timestamps,
|
timestamps: collection.timestamps,
|
||||||
|
versions: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (collection.versions) {
|
if (collection.versions) {
|
||||||
const versionsTableName = `_${tableName}_v`
|
const versionsTableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collection,
|
||||||
|
versions: true,
|
||||||
|
})
|
||||||
const versionFields = buildVersionCollectionFields(collection)
|
const versionFields = buildVersionCollectionFields(collection)
|
||||||
|
|
||||||
buildTable({
|
buildTable({
|
||||||
@@ -53,12 +61,13 @@ export const init: Init = function init(this: PostgresAdapter) {
|
|||||||
fields: versionFields,
|
fields: versionFields,
|
||||||
tableName: versionsTableName,
|
tableName: versionsTableName,
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
|
versions: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.payload.config.globals.forEach((global) => {
|
this.payload.config.globals.forEach((global) => {
|
||||||
const tableName = toSnakeCase(global.slug)
|
const tableName = getTableName({ adapter: this, config: global })
|
||||||
|
|
||||||
buildTable({
|
buildTable({
|
||||||
adapter: this,
|
adapter: this,
|
||||||
@@ -70,10 +79,11 @@ export const init: Init = function init(this: PostgresAdapter) {
|
|||||||
fields: global.fields,
|
fields: global.fields,
|
||||||
tableName,
|
tableName,
|
||||||
timestamps: false,
|
timestamps: false,
|
||||||
|
versions: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (global.versions) {
|
if (global.versions) {
|
||||||
const versionsTableName = `_${tableName}_v`
|
const versionsTableName = getTableName({ adapter: this, config: global, versions: true })
|
||||||
const versionFields = buildVersionGlobalFields(global)
|
const versionFields = buildVersionGlobalFields(global)
|
||||||
|
|
||||||
buildTable({
|
buildTable({
|
||||||
@@ -86,6 +96,7 @@ export const init: Init = function init(this: PostgresAdapter) {
|
|||||||
fields: versionFields,
|
fields: versionFields,
|
||||||
tableName: versionsTableName,
|
tableName: versionsTableName,
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
|
versions: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ async function runMigrationFile(payload: Payload, migration: Migration, batch: n
|
|||||||
|
|
||||||
payload.logger.info({ msg: `Migrating: ${migration.name}` })
|
payload.logger.info({ msg: `Migrating: ${migration.name}` })
|
||||||
|
|
||||||
const pgAdapter = payload.db as PostgresAdapter
|
const pgAdapter = payload.db
|
||||||
const drizzleJSON = generateDrizzleJson(pgAdapter.schema)
|
const drizzleJSON = generateDrizzleJson(pgAdapter.schema)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import { v4 as uuid } from 'uuid'
|
|||||||
import type { GenericColumn, GenericTable, PostgresAdapter } from '../types.js'
|
import type { GenericColumn, GenericTable, PostgresAdapter } from '../types.js'
|
||||||
import type { BuildQueryJoinAliases, BuildQueryJoins } from './buildQuery.js'
|
import type { BuildQueryJoinAliases, BuildQueryJoins } from './buildQuery.js'
|
||||||
|
|
||||||
|
import { getTableName } from '../schema/getTableName.js'
|
||||||
|
|
||||||
type Constraint = {
|
type Constraint = {
|
||||||
columnName: string
|
columnName: string
|
||||||
table: GenericTable | PgTableWithColumns<any>
|
table: GenericTable | PgTableWithColumns<any>
|
||||||
@@ -183,7 +185,13 @@ export const getTableColumnFromPath = ({
|
|||||||
|
|
||||||
case 'group': {
|
case 'group': {
|
||||||
if (locale && field.localized && adapter.payload.config.localization) {
|
if (locale && field.localized && adapter.payload.config.localization) {
|
||||||
newTableName = `${tableName}_locales`
|
newTableName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: field,
|
||||||
|
locales: true,
|
||||||
|
parentTableName: tableName,
|
||||||
|
prefix: `${tableName}_`,
|
||||||
|
})
|
||||||
|
|
||||||
joins[tableName] = eq(
|
joins[tableName] = eq(
|
||||||
adapter.tables[tableName].id,
|
adapter.tables[tableName].id,
|
||||||
@@ -218,7 +226,12 @@ export const getTableColumnFromPath = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'array': {
|
case 'array': {
|
||||||
newTableName = `${tableName}_${tableNameSuffix}${toSnakeCase(field.name)}`
|
newTableName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: field,
|
||||||
|
parentTableName: `${tableName}_${tableNameSuffix}`,
|
||||||
|
prefix: `${tableName}_${tableNameSuffix}`,
|
||||||
|
})
|
||||||
constraintPath = `${constraintPath}${field.name}.%.`
|
constraintPath = `${constraintPath}${field.name}.%.`
|
||||||
if (locale && field.localized && adapter.payload.config.localization) {
|
if (locale && field.localized && adapter.payload.config.localization) {
|
||||||
joins[newTableName] = and(
|
joins[newTableName] = and(
|
||||||
@@ -265,7 +278,12 @@ export const getTableColumnFromPath = ({
|
|||||||
const blockTypes = Array.isArray(value) ? value : [value]
|
const blockTypes = Array.isArray(value) ? value : [value]
|
||||||
blockTypes.forEach((blockType) => {
|
blockTypes.forEach((blockType) => {
|
||||||
const block = field.blocks.find((block) => block.slug === blockType)
|
const block = field.blocks.find((block) => block.slug === blockType)
|
||||||
newTableName = `${tableName}_blocks_${toSnakeCase(block.slug)}`
|
newTableName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: block,
|
||||||
|
parentTableName: tableName,
|
||||||
|
prefix: `${tableName}_blocks_`,
|
||||||
|
})
|
||||||
joins[newTableName] = eq(
|
joins[newTableName] = eq(
|
||||||
adapter.tables[tableName].id,
|
adapter.tables[tableName].id,
|
||||||
adapter.tables[newTableName]._parentID,
|
adapter.tables[newTableName]._parentID,
|
||||||
@@ -285,7 +303,12 @@ export const getTableColumnFromPath = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hasBlockField = field.blocks.some((block) => {
|
const hasBlockField = field.blocks.some((block) => {
|
||||||
newTableName = `${tableName}_blocks_${toSnakeCase(block.slug)}`
|
newTableName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: block,
|
||||||
|
parentTableName: tableName,
|
||||||
|
prefix: `${tableName}_blocks_`,
|
||||||
|
})
|
||||||
constraintPath = `${constraintPath}${field.name}.%.`
|
constraintPath = `${constraintPath}${field.name}.%.`
|
||||||
let result
|
let result
|
||||||
const blockConstraints = []
|
const blockConstraints = []
|
||||||
@@ -351,7 +374,7 @@ export const getTableColumnFromPath = ({
|
|||||||
case 'relationship':
|
case 'relationship':
|
||||||
case 'upload': {
|
case 'upload': {
|
||||||
let relationshipFields
|
let relationshipFields
|
||||||
const relationTableName = `${rootTableName}_rels`
|
const relationTableName = `${rootTableName}${adapter.relationshipsSuffix}`
|
||||||
const newCollectionPath = pathSegments.slice(1).join('.')
|
const newCollectionPath = pathSegments.slice(1).join('.')
|
||||||
const aliasRelationshipTableName = uuid()
|
const aliasRelationshipTableName = uuid()
|
||||||
const aliasRelationshipTable = alias(
|
const aliasRelationshipTable = alias(
|
||||||
@@ -392,9 +415,13 @@ export const getTableColumnFromPath = ({
|
|||||||
let newAliasTable
|
let newAliasTable
|
||||||
|
|
||||||
if (typeof field.relationTo === 'string') {
|
if (typeof field.relationTo === 'string') {
|
||||||
newTableName = `${toSnakeCase(field.relationTo)}`
|
const relationshipConfig = adapter.payload.collections[field.relationTo].config
|
||||||
|
newTableName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: relationshipConfig,
|
||||||
|
})
|
||||||
// parent to relationship join table
|
// parent to relationship join table
|
||||||
relationshipFields = adapter.payload.collections[field.relationTo].config.fields
|
relationshipFields = relationshipConfig.fields
|
||||||
|
|
||||||
newAliasTable = alias(adapter.tables[newTableName], toSnakeCase(uuid()))
|
newAliasTable = alias(adapter.tables[newTableName], toSnakeCase(uuid()))
|
||||||
|
|
||||||
@@ -413,7 +440,11 @@ export const getTableColumnFromPath = ({
|
|||||||
}
|
}
|
||||||
} else if (newCollectionPath === 'value') {
|
} else if (newCollectionPath === 'value') {
|
||||||
const tableColumnsNames = field.relationTo.map(
|
const tableColumnsNames = field.relationTo.map(
|
||||||
(relationTo) => `"${aliasRelationshipTableName}"."${toSnakeCase(relationTo)}_id"`,
|
(relationTo) =>
|
||||||
|
`"${aliasRelationshipTableName}"."${getTableName({
|
||||||
|
adapter,
|
||||||
|
config: adapter.payload.collections[relationTo].config,
|
||||||
|
})}_id"`,
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
constraints,
|
constraints,
|
||||||
@@ -460,7 +491,7 @@ export const getTableColumnFromPath = ({
|
|||||||
if (field.localized && adapter.payload.config.localization) {
|
if (field.localized && adapter.payload.config.localization) {
|
||||||
// If localized, we go to localized table and set aliasTable to undefined
|
// If localized, we go to localized table and set aliasTable to undefined
|
||||||
// so it is not picked up below to be used as targetTable
|
// so it is not picked up below to be used as targetTable
|
||||||
newTableName = `${tableName}_locales`
|
newTableName = `${tableName}${adapter.localesSuffix}`
|
||||||
|
|
||||||
const parentTable = aliasTable || adapter.tables[tableName]
|
const parentTable = aliasTable || adapter.tables[tableName]
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types'
|
|||||||
|
|
||||||
import { type QueryDrafts, combineQueries } from 'payload/database'
|
import { type QueryDrafts, combineQueries } from 'payload/database'
|
||||||
import { buildVersionCollectionFields } from 'payload/versions'
|
import { buildVersionCollectionFields } from 'payload/versions'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import { findMany } from './find/findMany.js'
|
import { findMany } from './find/findMany.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
|
|
||||||
export const queryDrafts: QueryDrafts = async function queryDrafts({
|
export const queryDrafts: QueryDrafts = async function queryDrafts({
|
||||||
collection,
|
collection,
|
||||||
@@ -17,7 +17,11 @@ export const queryDrafts: QueryDrafts = async function queryDrafts({
|
|||||||
where,
|
where,
|
||||||
}) {
|
}) {
|
||||||
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
||||||
const tableName = `_${toSnakeCase(collection)}_v`
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collectionConfig,
|
||||||
|
versions: true,
|
||||||
|
})
|
||||||
const fields = buildVersionCollectionFields(collectionConfig)
|
const fields = buildVersionCollectionFields(collectionConfig)
|
||||||
|
|
||||||
const combinedWhere = combineQueries({ latest: { equals: true } }, where)
|
const combinedWhere = combineQueries({ latest: { equals: true } }, where)
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ import type { Field } from 'payload/types'
|
|||||||
import { relations } from 'drizzle-orm'
|
import { relations } from 'drizzle-orm'
|
||||||
import { index, integer, numeric, serial, timestamp, unique, varchar } from 'drizzle-orm/pg-core'
|
import { index, integer, numeric, serial, timestamp, unique, varchar } from 'drizzle-orm/pg-core'
|
||||||
import { fieldAffectsData } from 'payload/types'
|
import { fieldAffectsData } from 'payload/types'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { GenericColumns, GenericTable, IDType, PostgresAdapter } from '../types.js'
|
import type { GenericColumns, GenericTable, IDType, PostgresAdapter } from '../types.js'
|
||||||
|
|
||||||
|
import { getTableName } from './getTableName.js'
|
||||||
import { parentIDColumnMap } from './parentIDColumnMap.js'
|
import { parentIDColumnMap } from './parentIDColumnMap.js'
|
||||||
import { setColumnID } from './setColumnID.js'
|
import { setColumnID } from './setColumnID.js'
|
||||||
import { traverseFields } from './traverseFields.js'
|
import { traverseFields } from './traverseFields.js'
|
||||||
@@ -35,6 +35,7 @@ type Args = {
|
|||||||
rootTableName?: string
|
rootTableName?: string
|
||||||
tableName: string
|
tableName: string
|
||||||
timestamps?: boolean
|
timestamps?: boolean
|
||||||
|
versions: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type Result = {
|
type Result = {
|
||||||
@@ -59,6 +60,7 @@ export const buildTable = ({
|
|||||||
rootTableName: incomingRootTableName,
|
rootTableName: incomingRootTableName,
|
||||||
tableName,
|
tableName,
|
||||||
timestamps,
|
timestamps,
|
||||||
|
versions,
|
||||||
}: Args): Result => {
|
}: Args): Result => {
|
||||||
const rootTableName = incomingRootTableName || tableName
|
const rootTableName = incomingRootTableName || tableName
|
||||||
const columns: Record<string, PgColumnBuilder> = baseColumns
|
const columns: Record<string, PgColumnBuilder> = baseColumns
|
||||||
@@ -113,6 +115,7 @@ export const buildTable = ({
|
|||||||
rootRelationsToBuild: rootRelationsToBuild || relationsToBuild,
|
rootRelationsToBuild: rootRelationsToBuild || relationsToBuild,
|
||||||
rootTableIDColType: rootTableIDColType || idColType,
|
rootTableIDColType: rootTableIDColType || idColType,
|
||||||
rootTableName,
|
rootTableName,
|
||||||
|
versions,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if (timestamps) {
|
if (timestamps) {
|
||||||
@@ -147,7 +150,7 @@ export const buildTable = ({
|
|||||||
adapter.tables[tableName] = table
|
adapter.tables[tableName] = table
|
||||||
|
|
||||||
if (hasLocalizedField) {
|
if (hasLocalizedField) {
|
||||||
const localeTableName = `${tableName}_locales`
|
const localeTableName = `${tableName}${adapter.localesSuffix}`
|
||||||
localesColumns.id = serial('id').primaryKey()
|
localesColumns.id = serial('id').primaryKey()
|
||||||
localesColumns._locale = adapter.enums.enum__locales('_locale').notNull()
|
localesColumns._locale = adapter.enums.enum__locales('_locale').notNull()
|
||||||
localesColumns._parentID = parentIDColumnMap[idColType]('_parent_id')
|
localesColumns._parentID = parentIDColumnMap[idColType]('_parent_id')
|
||||||
@@ -288,11 +291,16 @@ export const buildTable = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
relationships.forEach((relationTo) => {
|
relationships.forEach((relationTo) => {
|
||||||
const formattedRelationTo = toSnakeCase(relationTo)
|
const relationshipConfig = adapter.payload.collections[relationTo].config
|
||||||
|
const formattedRelationTo = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: relationshipConfig,
|
||||||
|
throwValidationError: true,
|
||||||
|
})
|
||||||
let colType = adapter.idType === 'uuid' ? 'uuid' : 'integer'
|
let colType = adapter.idType === 'uuid' ? 'uuid' : 'integer'
|
||||||
const relatedCollectionCustomID = adapter.payload.collections[
|
const relatedCollectionCustomID = relationshipConfig.fields.find(
|
||||||
relationTo
|
(field) => fieldAffectsData(field) && field.name === 'id',
|
||||||
].config.fields.find((field) => fieldAffectsData(field) && field.name === 'id')
|
)
|
||||||
if (relatedCollectionCustomID?.type === 'number') colType = 'numeric'
|
if (relatedCollectionCustomID?.type === 'number') colType = 'numeric'
|
||||||
if (relatedCollectionCustomID?.type === 'text') colType = 'varchar'
|
if (relatedCollectionCustomID?.type === 'text') colType = 'varchar'
|
||||||
|
|
||||||
@@ -301,7 +309,7 @@ export const buildTable = ({
|
|||||||
).references(() => adapter.tables[formattedRelationTo].id, { onDelete: 'cascade' })
|
).references(() => adapter.tables[formattedRelationTo].id, { onDelete: 'cascade' })
|
||||||
})
|
})
|
||||||
|
|
||||||
const relationshipsTableName = `${tableName}_rels`
|
const relationshipsTableName = `${tableName}${adapter.relationshipsSuffix}`
|
||||||
|
|
||||||
relationshipsTable = adapter.pgSchema.table(
|
relationshipsTable = adapter.pgSchema.table(
|
||||||
relationshipsTableName,
|
relationshipsTableName,
|
||||||
@@ -333,7 +341,11 @@ export const buildTable = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
relationships.forEach((relationTo) => {
|
relationships.forEach((relationTo) => {
|
||||||
const relatedTableName = toSnakeCase(relationTo)
|
const relatedTableName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: adapter.payload.collections[relationTo].config,
|
||||||
|
throwValidationError: true,
|
||||||
|
})
|
||||||
const idColumnName = `${relationTo}ID`
|
const idColumnName = `${relationTo}ID`
|
||||||
result[idColumnName] = one(adapter.tables[relatedTableName], {
|
result[idColumnName] = one(adapter.tables[relatedTableName], {
|
||||||
fields: [relationshipsTable[idColumnName]],
|
fields: [relationshipsTable[idColumnName]],
|
||||||
|
|||||||
75
packages/db-postgres/src/schema/getTableName.ts
Normal file
75
packages/db-postgres/src/schema/getTableName.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import type { DBIdentifierName } from 'payload/database'
|
||||||
|
|
||||||
|
import { APIError } from 'payload/errors'
|
||||||
|
import toSnakeCase from 'to-snake-case'
|
||||||
|
|
||||||
|
import type { PostgresAdapter } from '../types.js'
|
||||||
|
|
||||||
|
type Args = {
|
||||||
|
adapter: PostgresAdapter
|
||||||
|
/** The collection, global or field config **/
|
||||||
|
config: {
|
||||||
|
dbName?: DBIdentifierName
|
||||||
|
enumName?: DBIdentifierName
|
||||||
|
name?: string
|
||||||
|
slug?: string
|
||||||
|
}
|
||||||
|
/** Localized tables need to be given the locales suffix */
|
||||||
|
locales?: boolean
|
||||||
|
/** For nested tables passed for the user custom dbName functions to handle their own iterations */
|
||||||
|
parentTableName?: string
|
||||||
|
/** For sub tables (array for example) this needs to include the parentTableName */
|
||||||
|
prefix?: string
|
||||||
|
/** Adds the relationships suffix */
|
||||||
|
relationships?: boolean
|
||||||
|
/** For tables based on fields that could have both enumName and dbName (ie: select with hasMany), default: 'dbName' */
|
||||||
|
target?: 'dbName' | 'enumName'
|
||||||
|
throwValidationError?: boolean
|
||||||
|
/** Adds the versions suffix, should only be used on the base collection to duplicate suffixing */
|
||||||
|
versions?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to name database enums and tables
|
||||||
|
* Returns the table or enum name for a given entity
|
||||||
|
*/
|
||||||
|
export const getTableName = ({
|
||||||
|
adapter,
|
||||||
|
config: { name, slug },
|
||||||
|
config,
|
||||||
|
locales = false,
|
||||||
|
parentTableName,
|
||||||
|
prefix = '',
|
||||||
|
relationships = false,
|
||||||
|
target = 'dbName',
|
||||||
|
throwValidationError = false,
|
||||||
|
versions = false,
|
||||||
|
}: Args): string => {
|
||||||
|
let result: string
|
||||||
|
let custom = config[target]
|
||||||
|
|
||||||
|
if (!custom && target === 'enumName') {
|
||||||
|
custom = config['dbName']
|
||||||
|
}
|
||||||
|
|
||||||
|
if (custom) {
|
||||||
|
result = typeof custom === 'function' ? custom({ tableName: parentTableName }) : custom
|
||||||
|
} else {
|
||||||
|
result = `${prefix}${toSnakeCase(name ?? slug)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locales) result = `${result}${adapter.localesSuffix}`
|
||||||
|
if (versions) result = `_${result}${adapter.versionsSuffix}`
|
||||||
|
if (relationships) result = `${result}${adapter.relationshipsSuffix}`
|
||||||
|
|
||||||
|
if (!throwValidationError) {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.length > 63) {
|
||||||
|
throw new APIError(
|
||||||
|
`Exceeded max identifier length for table or enum name of 63 characters. Invalid name: ${result}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ import type { GenericColumns, IDType, PostgresAdapter } from '../types.js'
|
|||||||
import { hasLocalesTable } from '../utilities/hasLocalesTable.js'
|
import { hasLocalesTable } from '../utilities/hasLocalesTable.js'
|
||||||
import { buildTable } from './build.js'
|
import { buildTable } from './build.js'
|
||||||
import { createIndex } from './createIndex.js'
|
import { createIndex } from './createIndex.js'
|
||||||
|
import { getTableName } from './getTableName.js'
|
||||||
import { idToUUID } from './idToUUID.js'
|
import { idToUUID } from './idToUUID.js'
|
||||||
import { parentIDColumnMap } from './parentIDColumnMap.js'
|
import { parentIDColumnMap } from './parentIDColumnMap.js'
|
||||||
import { validateExistingBlockIsIdentical } from './validateExistingBlockIsIdentical.js'
|
import { validateExistingBlockIsIdentical } from './validateExistingBlockIsIdentical.js'
|
||||||
@@ -53,6 +54,7 @@ type Args = {
|
|||||||
rootRelationsToBuild?: Map<string, string>
|
rootRelationsToBuild?: Map<string, string>
|
||||||
rootTableIDColType: string
|
rootTableIDColType: string
|
||||||
rootTableName: string
|
rootTableName: string
|
||||||
|
versions: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type Result = {
|
type Result = {
|
||||||
@@ -86,7 +88,9 @@ export const traverseFields = ({
|
|||||||
rootRelationsToBuild,
|
rootRelationsToBuild,
|
||||||
rootTableIDColType,
|
rootTableIDColType,
|
||||||
rootTableName,
|
rootTableName,
|
||||||
|
versions,
|
||||||
}: Args): Result => {
|
}: Args): Result => {
|
||||||
|
const throwValidationError = true
|
||||||
let hasLocalizedField = false
|
let hasLocalizedField = false
|
||||||
let hasLocalizedRelationshipField = false
|
let hasLocalizedRelationshipField = false
|
||||||
let hasManyTextField: 'index' | boolean = false
|
let hasManyTextField: 'index' | boolean = false
|
||||||
@@ -217,7 +221,15 @@ export const traverseFields = ({
|
|||||||
|
|
||||||
case 'radio':
|
case 'radio':
|
||||||
case 'select': {
|
case 'select': {
|
||||||
const enumName = `enum_${newTableName}_${toSnakeCase(field.name)}`
|
const enumName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: field,
|
||||||
|
parentTableName: newTableName,
|
||||||
|
prefix: `enum_${newTableName}_`,
|
||||||
|
target: 'enumName',
|
||||||
|
throwValidationError,
|
||||||
|
versions,
|
||||||
|
})
|
||||||
|
|
||||||
adapter.enums[enumName] = pgEnum(
|
adapter.enums[enumName] = pgEnum(
|
||||||
enumName,
|
enumName,
|
||||||
@@ -231,7 +243,14 @@ export const traverseFields = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (field.type === 'select' && field.hasMany) {
|
if (field.type === 'select' && field.hasMany) {
|
||||||
const selectTableName = `${newTableName}_${toSnakeCase(field.name)}`
|
const selectTableName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: field,
|
||||||
|
parentTableName: newTableName,
|
||||||
|
prefix: `${newTableName}_`,
|
||||||
|
throwValidationError,
|
||||||
|
versions,
|
||||||
|
})
|
||||||
const baseColumns: Record<string, PgColumnBuilder> = {
|
const baseColumns: Record<string, PgColumnBuilder> = {
|
||||||
order: integer('order').notNull(),
|
order: integer('order').notNull(),
|
||||||
parent: parentIDColumnMap[parentIDColType]('parent_id')
|
parent: parentIDColumnMap[parentIDColType]('parent_id')
|
||||||
@@ -266,6 +285,7 @@ export const traverseFields = ({
|
|||||||
disableUnique,
|
disableUnique,
|
||||||
fields: [],
|
fields: [],
|
||||||
tableName: selectTableName,
|
tableName: selectTableName,
|
||||||
|
versions,
|
||||||
})
|
})
|
||||||
|
|
||||||
relationsToBuild.set(fieldName, selectTableName)
|
relationsToBuild.set(fieldName, selectTableName)
|
||||||
@@ -296,7 +316,13 @@ export const traverseFields = ({
|
|||||||
case 'array': {
|
case 'array': {
|
||||||
const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull
|
const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull
|
||||||
|
|
||||||
const arrayTableName = `${newTableName}_${toSnakeCase(field.name)}`
|
const arrayTableName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: field,
|
||||||
|
parentTableName: newTableName,
|
||||||
|
prefix: `${newTableName}_`,
|
||||||
|
throwValidationError,
|
||||||
|
})
|
||||||
const baseColumns: Record<string, PgColumnBuilder> = {
|
const baseColumns: Record<string, PgColumnBuilder> = {
|
||||||
_order: integer('_order').notNull(),
|
_order: integer('_order').notNull(),
|
||||||
_parentID: parentIDColumnMap[parentIDColType]('_parent_id')
|
_parentID: parentIDColumnMap[parentIDColType]('_parent_id')
|
||||||
@@ -334,6 +360,7 @@ export const traverseFields = ({
|
|||||||
rootTableIDColType,
|
rootTableIDColType,
|
||||||
rootTableName,
|
rootTableName,
|
||||||
tableName: arrayTableName,
|
tableName: arrayTableName,
|
||||||
|
versions,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (subHasManyTextField) {
|
if (subHasManyTextField) {
|
||||||
@@ -356,7 +383,7 @@ export const traverseFields = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasLocalesTable(field.fields)) {
|
if (hasLocalesTable(field.fields)) {
|
||||||
result._locales = many(adapter.tables[`${arrayTableName}_locales`])
|
result._locales = many(adapter.tables[`${arrayTableName}${adapter.localesSuffix}`])
|
||||||
}
|
}
|
||||||
|
|
||||||
subRelationsToBuild.forEach((val, key) => {
|
subRelationsToBuild.forEach((val, key) => {
|
||||||
@@ -375,7 +402,13 @@ export const traverseFields = ({
|
|||||||
const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull
|
const disableNotNullFromHere = Boolean(field.admin?.condition) || disableNotNull
|
||||||
|
|
||||||
field.blocks.forEach((block) => {
|
field.blocks.forEach((block) => {
|
||||||
const blockTableName = `${rootTableName}_blocks_${toSnakeCase(block.slug)}`
|
const blockTableName = getTableName({
|
||||||
|
adapter,
|
||||||
|
config: block,
|
||||||
|
parentTableName: rootTableName,
|
||||||
|
prefix: `${rootTableName}_blocks_`,
|
||||||
|
throwValidationError,
|
||||||
|
})
|
||||||
if (!adapter.tables[blockTableName]) {
|
if (!adapter.tables[blockTableName]) {
|
||||||
const baseColumns: Record<string, PgColumnBuilder> = {
|
const baseColumns: Record<string, PgColumnBuilder> = {
|
||||||
_order: integer('_order').notNull(),
|
_order: integer('_order').notNull(),
|
||||||
@@ -416,6 +449,7 @@ export const traverseFields = ({
|
|||||||
rootTableIDColType,
|
rootTableIDColType,
|
||||||
rootTableName,
|
rootTableName,
|
||||||
tableName: blockTableName,
|
tableName: blockTableName,
|
||||||
|
versions,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (subHasManyTextField) {
|
if (subHasManyTextField) {
|
||||||
@@ -439,7 +473,9 @@ export const traverseFields = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasLocalesTable(block.fields)) {
|
if (hasLocalesTable(block.fields)) {
|
||||||
result._locales = many(adapter.tables[`${blockTableName}_locales`])
|
result._locales = many(
|
||||||
|
adapter.tables[`${blockTableName}${adapter.localesSuffix}`],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
subRelationsToBuild.forEach((val, key) => {
|
subRelationsToBuild.forEach((val, key) => {
|
||||||
@@ -451,7 +487,7 @@ export const traverseFields = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
adapter.relations[`relations_${blockTableName}`] = blockTableRelations
|
adapter.relations[`relations_${blockTableName}`] = blockTableRelations
|
||||||
} else if (process.env.NODE_ENV !== 'production') {
|
} else if (process.env.NODE_ENV !== 'production' && !versions) {
|
||||||
validateExistingBlockIsIdentical({
|
validateExistingBlockIsIdentical({
|
||||||
block,
|
block,
|
||||||
localized: field.localized,
|
localized: field.localized,
|
||||||
@@ -459,7 +495,7 @@ export const traverseFields = ({
|
|||||||
table: adapter.tables[blockTableName],
|
table: adapter.tables[blockTableName],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
adapter.blockTableNames[`${rootTableName}.${toSnakeCase(block.slug)}`] = blockTableName
|
||||||
rootRelationsToBuild.set(`_blocks_${block.slug}`, blockTableName)
|
rootRelationsToBuild.set(`_blocks_${block.slug}`, blockTableName)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -498,6 +534,7 @@ export const traverseFields = ({
|
|||||||
rootRelationsToBuild,
|
rootRelationsToBuild,
|
||||||
rootTableIDColType,
|
rootTableIDColType,
|
||||||
rootTableName,
|
rootTableName,
|
||||||
|
versions,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (groupHasLocalizedField) hasLocalizedField = true
|
if (groupHasLocalizedField) hasLocalizedField = true
|
||||||
@@ -540,6 +577,7 @@ export const traverseFields = ({
|
|||||||
rootRelationsToBuild,
|
rootRelationsToBuild,
|
||||||
rootTableIDColType,
|
rootTableIDColType,
|
||||||
rootTableName,
|
rootTableName,
|
||||||
|
versions,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (groupHasLocalizedField) hasLocalizedField = true
|
if (groupHasLocalizedField) hasLocalizedField = true
|
||||||
@@ -583,6 +621,7 @@ export const traverseFields = ({
|
|||||||
rootRelationsToBuild,
|
rootRelationsToBuild,
|
||||||
rootTableIDColType,
|
rootTableIDColType,
|
||||||
rootTableName,
|
rootTableName,
|
||||||
|
versions,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (tabHasLocalizedField) hasLocalizedField = true
|
if (tabHasLocalizedField) hasLocalizedField = true
|
||||||
@@ -626,6 +665,7 @@ export const traverseFields = ({
|
|||||||
rootRelationsToBuild,
|
rootRelationsToBuild,
|
||||||
rootTableIDColType,
|
rootTableIDColType,
|
||||||
rootTableName,
|
rootTableName,
|
||||||
|
versions,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (rowHasLocalizedField) hasLocalizedField = true
|
if (rowHasLocalizedField) hasLocalizedField = true
|
||||||
|
|||||||
@@ -24,11 +24,14 @@ export type DrizzleDB = NodePgDatabase<Record<string, unknown>>
|
|||||||
|
|
||||||
export type Args = {
|
export type Args = {
|
||||||
idType?: 'serial' | 'uuid'
|
idType?: 'serial' | 'uuid'
|
||||||
|
localesSuffix?: string
|
||||||
logger?: DrizzleConfig['logger']
|
logger?: DrizzleConfig['logger']
|
||||||
migrationDir?: string
|
migrationDir?: string
|
||||||
pool: PoolConfig
|
pool: PoolConfig
|
||||||
push?: boolean
|
push?: boolean
|
||||||
|
relationshipsSuffix?: string
|
||||||
schemaName?: string
|
schemaName?: string
|
||||||
|
versionsSuffix?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GenericColumn = PgColumn<
|
export type GenericColumn = PgColumn<
|
||||||
@@ -58,6 +61,10 @@ export type DrizzleTransaction = PgTransaction<
|
|||||||
>
|
>
|
||||||
|
|
||||||
export type PostgresAdapter = BaseDatabaseAdapter & {
|
export type PostgresAdapter = BaseDatabaseAdapter & {
|
||||||
|
/**
|
||||||
|
* Used internally to map the block name to the table name
|
||||||
|
*/
|
||||||
|
blockTableNames: Record<string, string>
|
||||||
drizzle: DrizzleDB
|
drizzle: DrizzleDB
|
||||||
enums: Record<string, GenericEnum>
|
enums: Record<string, GenericEnum>
|
||||||
/**
|
/**
|
||||||
@@ -66,12 +73,14 @@ export type PostgresAdapter = BaseDatabaseAdapter & {
|
|||||||
*/
|
*/
|
||||||
fieldConstraints: Record<string, Record<string, string>>
|
fieldConstraints: Record<string, Record<string, string>>
|
||||||
idType: Args['idType']
|
idType: Args['idType']
|
||||||
|
localesSuffix?: string
|
||||||
logger: DrizzleConfig['logger']
|
logger: DrizzleConfig['logger']
|
||||||
pgSchema?: { table: PgTableFn } | PgSchema
|
pgSchema?: { table: PgTableFn } | PgSchema
|
||||||
pool: Pool
|
pool: Pool
|
||||||
poolOptions: Args['pool']
|
poolOptions: Args['pool']
|
||||||
push: boolean
|
push: boolean
|
||||||
relations: Record<string, GenericRelation>
|
relations: Record<string, GenericRelation>
|
||||||
|
relationshipsSuffix?: string
|
||||||
schema: Record<string, GenericEnum | GenericRelation | GenericTable>
|
schema: Record<string, GenericEnum | GenericRelation | GenericTable>
|
||||||
schemaName?: Args['schemaName']
|
schemaName?: Args['schemaName']
|
||||||
sessions: {
|
sessions: {
|
||||||
@@ -82,6 +91,7 @@ export type PostgresAdapter = BaseDatabaseAdapter & {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tables: Record<string, GenericTable | PgTableWithColumns<any>>
|
tables: Record<string, GenericTable | PgTableWithColumns<any>>
|
||||||
|
versionsSuffix?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IDType = 'integer' | 'numeric' | 'uuid' | 'varchar'
|
export type IDType = 'integer' | 'numeric' | 'uuid' | 'varchar'
|
||||||
@@ -98,9 +108,11 @@ declare module 'payload' {
|
|||||||
drizzle: DrizzleDB
|
drizzle: DrizzleDB
|
||||||
enums: Record<string, GenericEnum>
|
enums: Record<string, GenericEnum>
|
||||||
fieldConstraints: Record<string, Record<string, string>>
|
fieldConstraints: Record<string, Record<string, string>>
|
||||||
|
localeSuffix?: string
|
||||||
pool: Pool
|
pool: Pool
|
||||||
push: boolean
|
push: boolean
|
||||||
relations: Record<string, GenericRelation>
|
relations: Record<string, GenericRelation>
|
||||||
|
relationshipsSuffix?: string
|
||||||
schema: Record<string, GenericEnum | GenericRelation | GenericTable>
|
schema: Record<string, GenericEnum | GenericRelation | GenericTable>
|
||||||
sessions: {
|
sessions: {
|
||||||
[id: string]: {
|
[id: string]: {
|
||||||
@@ -110,5 +122,6 @@ declare module 'payload' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tables: Record<string, GenericTable>
|
tables: Record<string, GenericTable>
|
||||||
|
versionsSuffix?: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import type { UpdateOne } from 'payload/database'
|
import type { UpdateOne } from 'payload/database'
|
||||||
|
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import buildQuery from './queries/buildQuery.js'
|
import buildQuery from './queries/buildQuery.js'
|
||||||
import { selectDistinct } from './queries/selectDistinct.js'
|
import { selectDistinct } from './queries/selectDistinct.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
import { upsertRow } from './upsertRow/index.js'
|
import { upsertRow } from './upsertRow/index.js'
|
||||||
|
|
||||||
export const updateOne: UpdateOne = async function updateOne(
|
export const updateOne: UpdateOne = async function updateOne(
|
||||||
@@ -14,7 +13,10 @@ export const updateOne: UpdateOne = async function updateOne(
|
|||||||
) {
|
) {
|
||||||
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
||||||
const collection = this.payload.collections[collectionSlug].config
|
const collection = this.payload.collections[collectionSlug].config
|
||||||
const tableName = toSnakeCase(collectionSlug)
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collection,
|
||||||
|
})
|
||||||
const whereToUse = whereArg || { id: { equals: id } }
|
const whereToUse = whereArg || { id: { equals: id } }
|
||||||
let idToUpdate = id
|
let idToUpdate = id
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ export const updateOne: UpdateOne = async function updateOne(
|
|||||||
fields: collection.fields,
|
fields: collection.fields,
|
||||||
operation: 'update',
|
operation: 'update',
|
||||||
req,
|
req,
|
||||||
tableName: toSnakeCase(collectionSlug),
|
tableName,
|
||||||
})
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import type { UpdateGlobalArgs } from 'payload/database'
|
import type { UpdateGlobalArgs } from 'payload/database'
|
||||||
import type { PayloadRequest, TypeWithID } from 'payload/types'
|
import type { PayloadRequest, TypeWithID } from 'payload/types'
|
||||||
|
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
import { upsertRow } from './upsertRow/index.js'
|
import { upsertRow } from './upsertRow/index.js'
|
||||||
|
|
||||||
export async function updateGlobal<T extends TypeWithID>(
|
export async function updateGlobal<T extends TypeWithID>(
|
||||||
@@ -13,7 +12,10 @@ export async function updateGlobal<T extends TypeWithID>(
|
|||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
||||||
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug)
|
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug)
|
||||||
const tableName = toSnakeCase(slug)
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: globalConfig,
|
||||||
|
})
|
||||||
|
|
||||||
const existingGlobal = await db.query[tableName].findFirst({})
|
const existingGlobal = await db.query[tableName].findFirst({})
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import type { TypeWithVersion, UpdateGlobalVersionArgs } from 'payload/database'
|
|||||||
import type { PayloadRequest, SanitizedGlobalConfig, TypeWithID } from 'payload/types'
|
import type { PayloadRequest, SanitizedGlobalConfig, TypeWithID } from 'payload/types'
|
||||||
|
|
||||||
import { buildVersionGlobalFields } from 'payload/versions'
|
import { buildVersionGlobalFields } from 'payload/versions'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import buildQuery from './queries/buildQuery.js'
|
import buildQuery from './queries/buildQuery.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
import { upsertRow } from './upsertRow/index.js'
|
import { upsertRow } from './upsertRow/index.js'
|
||||||
|
|
||||||
export async function updateGlobalVersion<T extends TypeWithID>(
|
export async function updateGlobalVersion<T extends TypeWithID>(
|
||||||
@@ -25,7 +25,11 @@ export async function updateGlobalVersion<T extends TypeWithID>(
|
|||||||
({ slug }) => slug === global,
|
({ slug }) => slug === global,
|
||||||
)
|
)
|
||||||
const whereToUse = whereArg || { id: { equals: id } }
|
const whereToUse = whereArg || { id: { equals: id } }
|
||||||
const tableName = `_${toSnakeCase(global)}_v`
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: globalConfig,
|
||||||
|
versions: true,
|
||||||
|
})
|
||||||
const fields = buildVersionGlobalFields(globalConfig)
|
const fields = buildVersionGlobalFields(globalConfig)
|
||||||
|
|
||||||
const { where } = await buildQuery({
|
const { where } = await buildQuery({
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import type { TypeWithVersion, UpdateVersionArgs } from 'payload/database'
|
|||||||
import type { PayloadRequest, SanitizedCollectionConfig, TypeWithID } from 'payload/types'
|
import type { PayloadRequest, SanitizedCollectionConfig, TypeWithID } from 'payload/types'
|
||||||
|
|
||||||
import { buildVersionCollectionFields } from 'payload/versions'
|
import { buildVersionCollectionFields } from 'payload/versions'
|
||||||
import toSnakeCase from 'to-snake-case'
|
|
||||||
|
|
||||||
import type { PostgresAdapter } from './types.js'
|
import type { PostgresAdapter } from './types.js'
|
||||||
|
|
||||||
import buildQuery from './queries/buildQuery.js'
|
import buildQuery from './queries/buildQuery.js'
|
||||||
|
import { getTableName } from './schema/getTableName.js'
|
||||||
import { upsertRow } from './upsertRow/index.js'
|
import { upsertRow } from './upsertRow/index.js'
|
||||||
|
|
||||||
export async function updateVersion<T extends TypeWithID>(
|
export async function updateVersion<T extends TypeWithID>(
|
||||||
@@ -23,7 +23,11 @@ export async function updateVersion<T extends TypeWithID>(
|
|||||||
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
const db = this.sessions[req.transactionID]?.db || this.drizzle
|
||||||
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
|
||||||
const whereToUse = whereArg || { id: { equals: id } }
|
const whereToUse = whereArg || { id: { equals: id } }
|
||||||
const tableName = `_${toSnakeCase(collection)}_v`
|
const tableName = getTableName({
|
||||||
|
adapter: this,
|
||||||
|
config: collectionConfig,
|
||||||
|
versions: true,
|
||||||
|
})
|
||||||
const fields = buildVersionCollectionFields(collectionConfig)
|
const fields = buildVersionCollectionFields(collectionConfig)
|
||||||
|
|
||||||
const { where } = await buildQuery({
|
const { where } = await buildQuery({
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ const collectionSchema = joi.object().keys({
|
|||||||
joi.boolean(),
|
joi.boolean(),
|
||||||
),
|
),
|
||||||
custom: joi.object().pattern(joi.string(), joi.any()),
|
custom: joi.object().pattern(joi.string(), joi.any()),
|
||||||
|
dbName: joi.alternatives().try(joi.string(), joi.func()),
|
||||||
defaultSort: joi.string(),
|
defaultSort: joi.string(),
|
||||||
disableDuplicate: joi.bool(),
|
disableDuplicate: joi.bool(),
|
||||||
endpoints: endpointsSchema,
|
endpoints: endpointsSchema,
|
||||||
|
|||||||
@@ -411,3 +411,10 @@ export type DatabaseAdapterResult<T = BaseDatabaseAdapter> = {
|
|||||||
defaultIDType: 'number' | 'text'
|
defaultIDType: 'number' | 'text'
|
||||||
init: (args: { payload: Payload }) => T
|
init: (args: { payload: Payload }) => T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DBIdentifierName =
|
||||||
|
| ((Args: {
|
||||||
|
/** The name of the parent table when using relational DBs */
|
||||||
|
tableName?: string
|
||||||
|
}) => string)
|
||||||
|
| string
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type {
|
|||||||
CreateMigration,
|
CreateMigration,
|
||||||
CreateVersion,
|
CreateVersion,
|
||||||
CreateVersionArgs,
|
CreateVersionArgs,
|
||||||
|
DBIdentifierName,
|
||||||
DatabaseAdapterResult as DatabaseAdapterObj,
|
DatabaseAdapterResult as DatabaseAdapterObj,
|
||||||
DeleteMany,
|
DeleteMany,
|
||||||
DeleteManyArgs,
|
DeleteManyArgs,
|
||||||
|
|||||||
@@ -4,6 +4,5 @@ export { deleteCollectionVersions } from '../versions/deleteCollectionVersions.j
|
|||||||
export { enforceMaxVersions } from '../versions/enforceMaxVersions.js'
|
export { enforceMaxVersions } from '../versions/enforceMaxVersions.js'
|
||||||
export { getLatestCollectionVersion } from '../versions/getLatestCollectionVersion.js'
|
export { getLatestCollectionVersion } from '../versions/getLatestCollectionVersion.js'
|
||||||
export { getLatestGlobalVersion } from '../versions/getLatestGlobalVersion.js'
|
export { getLatestGlobalVersion } from '../versions/getLatestGlobalVersion.js'
|
||||||
export { getVersionsModelName } from '../versions/getVersionsModelName.js'
|
|
||||||
export { saveVersion } from '../versions/saveVersion.js'
|
export { saveVersion } from '../versions/saveVersion.js'
|
||||||
export type { TypeWithVersion } from '../versions/types.js'
|
export type { TypeWithVersion } from '../versions/types.js'
|
||||||
|
|||||||
@@ -201,9 +201,11 @@ export const select = baseField.keys({
|
|||||||
isClearable: joi.boolean().default(false),
|
isClearable: joi.boolean().default(false),
|
||||||
isSortable: joi.boolean().default(false),
|
isSortable: joi.boolean().default(false),
|
||||||
}),
|
}),
|
||||||
|
dbName: joi.alternatives().try(joi.string(), joi.func()),
|
||||||
defaultValue: joi
|
defaultValue: joi
|
||||||
.alternatives()
|
.alternatives()
|
||||||
.try(joi.string().allow(''), joi.array().items(joi.string().allow('')), joi.func()),
|
.try(joi.string().allow(''), joi.array().items(joi.string().allow('')), joi.func()),
|
||||||
|
enumName: joi.alternatives().try(joi.string(), joi.func()),
|
||||||
hasMany: joi.boolean().default(false),
|
hasMany: joi.boolean().default(false),
|
||||||
options: joi
|
options: joi
|
||||||
.array()
|
.array()
|
||||||
@@ -233,6 +235,7 @@ export const radio = baseField.keys({
|
|||||||
layout: joi.string().valid('vertical', 'horizontal'),
|
layout: joi.string().valid('vertical', 'horizontal'),
|
||||||
}),
|
}),
|
||||||
defaultValue: joi.alternatives().try(joi.string().allow(''), joi.func()),
|
defaultValue: joi.alternatives().try(joi.string().allow(''), joi.func()),
|
||||||
|
enumName: joi.alternatives().try(joi.string(), joi.func()),
|
||||||
options: joi
|
options: joi
|
||||||
.array()
|
.array()
|
||||||
.min(1)
|
.min(1)
|
||||||
@@ -310,6 +313,7 @@ export const array = baseField.keys({
|
|||||||
.default({}),
|
.default({}),
|
||||||
})
|
})
|
||||||
.default({}),
|
.default({}),
|
||||||
|
dbName: joi.alternatives().try(joi.string(), joi.func()),
|
||||||
defaultValue: joi.alternatives().try(joi.array().items(joi.object()), joi.func()),
|
defaultValue: joi.alternatives().try(joi.array().items(joi.object()), joi.func()),
|
||||||
fields: joi.array().items(joi.link('#field')).required(),
|
fields: joi.array().items(joi.link('#field')).required(),
|
||||||
interfaceName: joi.string(),
|
interfaceName: joi.string(),
|
||||||
@@ -410,6 +414,7 @@ export const blocks = baseField.keys({
|
|||||||
joi.object({
|
joi.object({
|
||||||
slug: joi.string().required(),
|
slug: joi.string().required(),
|
||||||
custom: joi.object().pattern(joi.string(), joi.any()),
|
custom: joi.object().pattern(joi.string(), joi.any()),
|
||||||
|
dbName: joi.alternatives().try(joi.string(), joi.func()),
|
||||||
fields: joi.array().items(joi.link('#field')),
|
fields: joi.array().items(joi.link('#field')),
|
||||||
graphQL: joi.object().keys({
|
graphQL: joi.object().keys({
|
||||||
singularName: joi.string(),
|
singularName: joi.string(),
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import type {
|
|||||||
} from '../../admin/types.js'
|
} from '../../admin/types.js'
|
||||||
import type { User } from '../../auth/index.js'
|
import type { User } from '../../auth/index.js'
|
||||||
import type { SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types.js'
|
import type { SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types.js'
|
||||||
|
import type { DBIdentifierName } from '../../database/types.js'
|
||||||
import type { SanitizedGlobalConfig } from '../../globals/config/types.js'
|
import type { SanitizedGlobalConfig } from '../../globals/config/types.js'
|
||||||
import type { Operation, PayloadRequest, RequestContext, Where } from '../../types/index.js'
|
import type { Operation, PayloadRequest, RequestContext, Where } from '../../types/index.js'
|
||||||
import type { ClientFieldConfig } from './client.js'
|
import type { ClientFieldConfig } from './client.js'
|
||||||
@@ -68,9 +69,11 @@ export type FieldAccess<T extends TypeWithID = any, P = any, U = any> = (args: {
|
|||||||
* The `id` of the current document being read or updated. `id` is undefined during the `create` operation.
|
* The `id` of the current document being read or updated. `id` is undefined during the `create` operation.
|
||||||
*/
|
*/
|
||||||
id?: number | string
|
id?: number | string
|
||||||
/** The `Express` request object containing the currently authenticated `user` */
|
|
||||||
req: PayloadRequest<U>
|
|
||||||
/** The `payload` object to interface with the payload API */
|
/** The `payload` object to interface with the payload API */
|
||||||
|
req: PayloadRequest<U>
|
||||||
|
/**
|
||||||
|
* Immediately adjacent data to this field. For example, if this is a `group` field, then `siblingData` will be the other fields within the group.
|
||||||
|
*/
|
||||||
siblingData?: Partial<P>
|
siblingData?: Partial<P>
|
||||||
}) => Promise<boolean> | boolean
|
}) => Promise<boolean> | boolean
|
||||||
|
|
||||||
@@ -478,6 +481,14 @@ export type SelectField = FieldBase & {
|
|||||||
isClearable?: boolean
|
isClearable?: boolean
|
||||||
isSortable?: boolean
|
isSortable?: boolean
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Customize the SQL table name
|
||||||
|
*/
|
||||||
|
dbName?: DBIdentifierName
|
||||||
|
/**
|
||||||
|
* Customize the DB enum name
|
||||||
|
*/
|
||||||
|
enumName?: DBIdentifierName
|
||||||
hasMany?: boolean
|
hasMany?: boolean
|
||||||
options: Option[]
|
options: Option[]
|
||||||
type: 'select'
|
type: 'select'
|
||||||
@@ -584,6 +595,10 @@ export type ArrayField = FieldBase & {
|
|||||||
} & Admin['components']
|
} & Admin['components']
|
||||||
initCollapsed?: boolean
|
initCollapsed?: boolean
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Customize the SQL table name
|
||||||
|
*/
|
||||||
|
dbName?: DBIdentifierName
|
||||||
fields: Field[]
|
fields: Field[]
|
||||||
/** Customize generated GraphQL and Typescript schema names.
|
/** Customize generated GraphQL and Typescript schema names.
|
||||||
* By default it is bound to the collection.
|
* By default it is bound to the collection.
|
||||||
@@ -606,6 +621,14 @@ export type RadioField = FieldBase & {
|
|||||||
}
|
}
|
||||||
layout?: 'horizontal' | 'vertical'
|
layout?: 'horizontal' | 'vertical'
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Customize the SQL table name
|
||||||
|
*/
|
||||||
|
dbName?: DBIdentifierName
|
||||||
|
/**
|
||||||
|
* Customize the DB enum name
|
||||||
|
*/
|
||||||
|
enumName?: DBIdentifierName
|
||||||
options: Option[]
|
options: Option[]
|
||||||
type: 'radio'
|
type: 'radio'
|
||||||
}
|
}
|
||||||
@@ -613,6 +636,10 @@ export type RadioField = FieldBase & {
|
|||||||
export type Block = {
|
export type Block = {
|
||||||
/** Extension point to add your custom data. */
|
/** Extension point to add your custom data. */
|
||||||
custom?: Record<string, any>
|
custom?: Record<string, any>
|
||||||
|
/**
|
||||||
|
* Customize the SQL table name
|
||||||
|
*/
|
||||||
|
dbName?: DBIdentifierName
|
||||||
fields: Field[]
|
fields: Field[]
|
||||||
/** @deprecated - please migrate to the interfaceName property instead. */
|
/** @deprecated - please migrate to the interfaceName property instead. */
|
||||||
graphQL?: {
|
graphQL?: {
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ const globalSchema = joi
|
|||||||
preview: joi.func(),
|
preview: joi.func(),
|
||||||
}),
|
}),
|
||||||
custom: joi.object().pattern(joi.string(), joi.any()),
|
custom: joi.object().pattern(joi.string(), joi.any()),
|
||||||
|
dbName: joi.alternatives().try(joi.string(), joi.func()),
|
||||||
endpoints: endpointsSchema,
|
endpoints: endpointsSchema,
|
||||||
fields: joi.array(),
|
fields: joi.array(),
|
||||||
graphQL: joi.alternatives().try(
|
graphQL: joi.alternatives().try(
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import type {
|
|||||||
GeneratePreviewURL,
|
GeneratePreviewURL,
|
||||||
LivePreviewConfig,
|
LivePreviewConfig,
|
||||||
} from '../../config/types.js'
|
} from '../../config/types.js'
|
||||||
|
import type { DBIdentifierName } from '../../database/types.js'
|
||||||
import type { Field } from '../../fields/config/types.js'
|
import type { Field } from '../../fields/config/types.js'
|
||||||
import type { PayloadRequest, RequestContext } from '../../types/index.js'
|
import type { PayloadRequest, RequestContext } from '../../types/index.js'
|
||||||
import type { Where } from '../../types/index.js'
|
import type { Where } from '../../types/index.js'
|
||||||
@@ -141,6 +142,10 @@ export type GlobalConfig = {
|
|||||||
admin?: GlobalAdminOptions
|
admin?: GlobalAdminOptions
|
||||||
/** Extension point to add your custom data. */
|
/** Extension point to add your custom data. */
|
||||||
custom?: Record<string, any>
|
custom?: Record<string, any>
|
||||||
|
/**
|
||||||
|
* Customize the SQL table name
|
||||||
|
*/
|
||||||
|
dbName?: DBIdentifierName
|
||||||
endpoints?: Omit<Endpoint, 'root'>[] | false
|
endpoints?: Omit<Endpoint, 'root'>[] | false
|
||||||
fields: Field[]
|
fields: Field[]
|
||||||
graphQL?:
|
graphQL?:
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
import type { SanitizedCollectionConfig } from '../collections/config/types.ts'
|
|
||||||
import type { SanitizedGlobalConfig } from '../globals/config/types.js'
|
|
||||||
|
|
||||||
export const getVersionsModelName = (
|
|
||||||
entity: SanitizedCollectionConfig | SanitizedGlobalConfig,
|
|
||||||
): string => `_${entity.slug}_versions`
|
|
||||||
77
pnpm-lock.yaml
generated
77
pnpm-lock.yaml
generated
@@ -374,9 +374,6 @@ importers:
|
|||||||
mongoose:
|
mongoose:
|
||||||
specifier: 6.12.3
|
specifier: 6.12.3
|
||||||
version: 6.12.3
|
version: 6.12.3
|
||||||
mongoose-aggregate-paginate-v2:
|
|
||||||
specifier: 1.0.6
|
|
||||||
version: 1.0.6
|
|
||||||
mongoose-paginate-v2:
|
mongoose-paginate-v2:
|
||||||
specifier: 1.7.22
|
specifier: 1.7.22
|
||||||
version: 1.7.22
|
version: 1.7.22
|
||||||
@@ -9774,7 +9771,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
loader-utils: 2.0.4
|
loader-utils: 2.0.4
|
||||||
schema-utils: 3.3.0
|
schema-utils: 3.3.0
|
||||||
webpack: 5.90.3(@swc/core@1.4.2)
|
webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.19.12)(webpack-cli@5.1.4)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/file-type@16.5.4:
|
/file-type@16.5.4:
|
||||||
@@ -12275,7 +12272,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
loader-utils: 2.0.4
|
loader-utils: 2.0.4
|
||||||
schema-utils: 3.3.0
|
schema-utils: 3.3.0
|
||||||
webpack: 5.90.3(@swc/core@1.4.2)
|
webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.19.12)(webpack-cli@5.1.4)
|
||||||
webpack-sources: 1.4.3
|
webpack-sources: 1.4.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -12416,11 +12413,6 @@ packages:
|
|||||||
'@mongodb-js/saslprep': 1.1.4
|
'@mongodb-js/saslprep': 1.1.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/mongoose-aggregate-paginate-v2@1.0.6:
|
|
||||||
resolution: {integrity: sha512-UuALu+mjhQa1K9lMQvjLL3vm3iALvNw8PQNIh2gp1b+tO5hUa0NC0Wf6/8QrT9PSJVTihXaD8hQVy3J4e0jO0Q==}
|
|
||||||
engines: {node: '>=4.0.0'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/mongoose-paginate-v2@1.7.22:
|
/mongoose-paginate-v2@1.7.22:
|
||||||
resolution: {integrity: sha512-xW5GugkE21DJiu9e13EOxKt4ejEKQkRP/S1PkkXRjnk2rRZVKBcld1nPV+VJ/YCPfm8hb3sz9OvI7O38RmixkA==}
|
resolution: {integrity: sha512-xW5GugkE21DJiu9e13EOxKt4ejEKQkRP/S1PkkXRjnk2rRZVKBcld1nPV+VJ/YCPfm8hb3sz9OvI7O38RmixkA==}
|
||||||
engines: {node: '>=4.0.0'}
|
engines: {node: '>=4.0.0'}
|
||||||
@@ -15656,31 +15648,6 @@ packages:
|
|||||||
webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.19.12)(webpack-cli@5.1.4)
|
webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.19.12)(webpack-cli@5.1.4)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/terser-webpack-plugin@5.3.10(@swc/core@1.4.2)(webpack@5.90.3):
|
|
||||||
resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==}
|
|
||||||
engines: {node: '>= 10.13.0'}
|
|
||||||
peerDependencies:
|
|
||||||
'@swc/core': '*'
|
|
||||||
esbuild: '*'
|
|
||||||
uglify-js: '*'
|
|
||||||
webpack: ^5.1.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@swc/core':
|
|
||||||
optional: true
|
|
||||||
esbuild:
|
|
||||||
optional: true
|
|
||||||
uglify-js:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
'@jridgewell/trace-mapping': 0.3.23
|
|
||||||
'@swc/core': 1.4.2
|
|
||||||
jest-worker: 27.5.1
|
|
||||||
schema-utils: 3.3.0
|
|
||||||
serialize-javascript: 6.0.2
|
|
||||||
terser: 5.28.1
|
|
||||||
webpack: 5.90.3(@swc/core@1.4.2)
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/terser@5.28.1:
|
/terser@5.28.1:
|
||||||
resolution: {integrity: sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==}
|
resolution: {integrity: sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -16440,46 +16407,6 @@ packages:
|
|||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/webpack@5.90.3(@swc/core@1.4.2):
|
|
||||||
resolution: {integrity: sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==}
|
|
||||||
engines: {node: '>=10.13.0'}
|
|
||||||
hasBin: true
|
|
||||||
peerDependencies:
|
|
||||||
webpack-cli: '*'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
webpack-cli:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
'@types/eslint-scope': 3.7.7
|
|
||||||
'@types/estree': 1.0.5
|
|
||||||
'@webassemblyjs/ast': 1.11.6
|
|
||||||
'@webassemblyjs/wasm-edit': 1.11.6
|
|
||||||
'@webassemblyjs/wasm-parser': 1.11.6
|
|
||||||
acorn: 8.11.3
|
|
||||||
acorn-import-assertions: 1.9.0(acorn@8.11.3)
|
|
||||||
browserslist: 4.23.0
|
|
||||||
chrome-trace-event: 1.0.3
|
|
||||||
enhanced-resolve: 5.15.1
|
|
||||||
es-module-lexer: 1.4.1
|
|
||||||
eslint-scope: 5.1.1
|
|
||||||
events: 3.3.0
|
|
||||||
glob-to-regexp: 0.4.1
|
|
||||||
graceful-fs: 4.2.11
|
|
||||||
json-parse-even-better-errors: 2.3.1
|
|
||||||
loader-runner: 4.3.0
|
|
||||||
mime-types: 2.1.35
|
|
||||||
neo-async: 2.6.2
|
|
||||||
schema-utils: 3.3.0
|
|
||||||
tapable: 2.2.1
|
|
||||||
terser-webpack-plugin: 5.3.10(@swc/core@1.4.2)(webpack@5.90.3)
|
|
||||||
watchpack: 2.4.0
|
|
||||||
webpack-sources: 3.2.3
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- '@swc/core'
|
|
||||||
- esbuild
|
|
||||||
- uglify-js
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.19.12)(webpack-cli@5.1.4):
|
/webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.19.12)(webpack-cli@5.1.4):
|
||||||
resolution: {integrity: sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==}
|
resolution: {integrity: sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==}
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
|
|||||||
@@ -63,7 +63,98 @@ export default buildConfigWithDefaults({
|
|||||||
singular: 'Relation B',
|
singular: 'Relation B',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
slug: 'custom-schema',
|
||||||
|
dbName: 'customs',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'text',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'localizedText',
|
||||||
|
type: 'text',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'relationship',
|
||||||
|
type: 'relationship',
|
||||||
|
hasMany: true,
|
||||||
|
relationTo: 'relation-a',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'select',
|
||||||
|
type: 'select',
|
||||||
|
dbName: ({ tableName }) => `${tableName}_customSelect`,
|
||||||
|
enumName: 'selectEnum',
|
||||||
|
hasMany: true,
|
||||||
|
options: ['a', 'b', 'c'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'radio',
|
||||||
|
type: 'select',
|
||||||
|
enumName: 'radioEnum',
|
||||||
|
options: ['a', 'b', 'c'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'array',
|
||||||
|
type: 'array',
|
||||||
|
dbName: 'customArrays',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'text',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'localizedText',
|
||||||
|
type: 'text',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'blocks',
|
||||||
|
type: 'blocks',
|
||||||
|
blocks: [
|
||||||
|
{
|
||||||
|
slug: 'block',
|
||||||
|
dbName: 'customBlocks',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'text',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'localizedText',
|
||||||
|
type: 'text',
|
||||||
|
localized: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
versions: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
|
globals: [
|
||||||
|
{
|
||||||
|
slug: 'global',
|
||||||
|
// @ts-expect-error
|
||||||
|
dbName: 'customGlobal',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'text',
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
versions: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
localization: {
|
||||||
|
defaultLocale: 'en',
|
||||||
|
locales: ['en', 'es'],
|
||||||
|
},
|
||||||
onInit: async (payload) => {
|
onInit: async (payload) => {
|
||||||
await payload.create({
|
await payload.create({
|
||||||
collection: 'users',
|
collection: 'users',
|
||||||
|
|||||||
@@ -131,6 +131,59 @@ describe('database', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('schema', () => {
|
||||||
|
it('should use custom dbNames', () => {
|
||||||
|
expect(payload.db).toBeDefined()
|
||||||
|
|
||||||
|
if (payload.db.name === 'mongoose') {
|
||||||
|
// @ts-expect-error
|
||||||
|
const db: MongooseAdapter = payload.db
|
||||||
|
|
||||||
|
expect(db.collections['custom-schema'].modelName).toStrictEqual('customs')
|
||||||
|
expect(db.versions['custom-schema'].modelName).toStrictEqual('_customs_versions')
|
||||||
|
expect(db.versions.global.modelName).toStrictEqual('_customGlobal_versions')
|
||||||
|
} else {
|
||||||
|
// @ts-expect-error
|
||||||
|
const db: PostgresAdapter = payload.db
|
||||||
|
|
||||||
|
// collection
|
||||||
|
expect(db.tables.customs).toBeDefined()
|
||||||
|
|
||||||
|
// collection versions
|
||||||
|
expect(db.tables._customs_v).toBeDefined()
|
||||||
|
|
||||||
|
// collection relationships
|
||||||
|
expect(db.tables.customs_rels).toBeDefined()
|
||||||
|
|
||||||
|
// collection localized
|
||||||
|
expect(db.tables.customs_locales).toBeDefined()
|
||||||
|
|
||||||
|
// global
|
||||||
|
expect(db.tables.customGlobal).toBeDefined()
|
||||||
|
expect(db.tables._customGlobal_v).toBeDefined()
|
||||||
|
|
||||||
|
// select
|
||||||
|
expect(db.tables.customs_customSelect).toBeDefined()
|
||||||
|
|
||||||
|
// array
|
||||||
|
expect(db.tables.customArrays).toBeDefined()
|
||||||
|
|
||||||
|
// array localized
|
||||||
|
expect(db.tables.customArrays_locales).toBeDefined()
|
||||||
|
|
||||||
|
// blocks
|
||||||
|
expect(db.tables.customBlocks).toBeDefined()
|
||||||
|
|
||||||
|
// localized blocks
|
||||||
|
expect(db.tables.customBlocks_locales).toBeDefined()
|
||||||
|
|
||||||
|
// enum names
|
||||||
|
expect(db.enums.selectEnum).toBeDefined()
|
||||||
|
expect(db.enums.radioEnum).toBeDefined()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('transactions', () => {
|
describe('transactions', () => {
|
||||||
describe('local api', () => {
|
describe('local api', () => {
|
||||||
it('should commit multiple operations in isolation', async () => {
|
it('should commit multiple operations in isolation', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user