chore: merge

This commit is contained in:
James
2023-09-19 10:53:44 -04:00
654 changed files with 21410 additions and 6947 deletions

View File

@@ -11,6 +11,28 @@ module.exports = {
'perfectionist/sort-objects': 'off',
},
},
{
files: ['package.json', 'tsconfig.json'],
rules: {
'perfectionist/sort-array-includes': 'off',
'perfectionist/sort-astro-attributes': 'off',
'perfectionist/sort-classes': 'off',
'perfectionist/sort-enums': 'off',
'perfectionist/sort-exports': 'off',
'perfectionist/sort-imports': 'off',
'perfectionist/sort-interfaces': 'off',
'perfectionist/sort-jsx-props': 'off',
'perfectionist/sort-keys': 'off',
'perfectionist/sort-maps': 'off',
'perfectionist/sort-named-exports': 'off',
'perfectionist/sort-named-imports': 'off',
'perfectionist/sort-object-types': 'off',
'perfectionist/sort-objects': 'off',
'perfectionist/sort-svelte-attributes': 'off',
'perfectionist/sort-union-types': 'off',
'perfectionist/sort-vue-attributes': 'off',
},
},
],
root: true,
}

View File

@@ -1,3 +1,9 @@
# lint and format
ae7d6f97d205491390f15850e5104c7abded1550
1fbda85cd04a774cb978778b0f813001664c53dd
# prettier all templates
75a428ddc4672903455998eaba7ae9f9d710bf85
# re-run prettier and eslint everywhere again
cdaa0acd61d3001407609915bd573b78565d5571

View File

@@ -26,6 +26,7 @@ Payload is a _config-based_, code-first CMS and application framework. The Paylo
| `cors` | Either a whitelist array of URLS to allow CORS requests from, or a wildcard string (`'*'`) to accept incoming requests from any domain. |
| `globals` | An array of all Globals that Payload will manage. For more on Globals and their configs, [click here](/docs/configuration/globals). |
| `admin` | Base Payload admin configuration. Specify custom components, control metadata, set the Admin user collection, and [more](/docs/admin/overview#admin-options). |
| `editor` | Default richText editor which will be used by richText fields. |
| `localization` | Opt-in and control how Payload handles the translation of your content into multiple locales. [More](/docs/configuration/localization) |
| `graphQL` | Manage GraphQL-specific functionality here. Define your own queries and mutations, manage query complexity limits, and [more](/docs/graphql/overview#graphql-options). |
| `cookiePrefix` | A string that will be prefixed to all cookies that Payload sets. |

View File

@@ -21,13 +21,7 @@ keywords: rich text, fields, config, configuration, documentation, Content Manag
The Admin component is built on the powerful [`slatejs`](https://docs.slatejs.org/) editor and is meant to be as extensible and customizable as possible.
<Banner type="success">
<strong>
Consistent with Payload's goal of making you learn as little of Payload as possible, customizing
and using the Rich Text Editor does not involve learning how to develop for a <em>Payload</em>{' '}
rich text editor.
</strong>{' '}
Instead, you can invest your time and effort into learning Slate, an open-source tool that will
allow you to apply your learnings elsewhere as well.
<strong>Consistent with Payload's goal of making you learn as little of Payload as possible, customizing and using the Rich Text Editor does not involve learning how to develop for a <em>Payload</em> rich text editor.</strong> Instead, you can invest your time and effort into learning Slate, an open-source tool that will allow you to apply your learnings elsewhere as well.
</Banner>
### Config
@@ -45,6 +39,7 @@ The Admin component is built on the powerful [`slatejs`](https://docs.slatejs.or
| **`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. |
| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-config). |
| **`editor`** | RichText editor which will be used by this field. |
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
_\* An asterisk denotes that a property is required._

View File

@@ -36,10 +36,7 @@ When you initialize Payload, you provide it with a `secret` property. This prope
Because _**you**_ are in complete control of who can do what with your data, you should double and triple-check that you wield that power responsibly before deploying to Production.
<Banner type="error">
<strong>
By default, all Access Control functions require that a user is successfully logged in to
Payload to create, read, update, or delete data.
</strong>{' '}
<strong>By default, all Access Control functions require that a user is successfully logged in to Payload to create, read, update, or delete data.</strong>{' '}
But, if you allow public user registration, for example, you will want to make sure that your
access control functions are more strict - permitting <strong>only appropriate users</strong> to
perform appropriate actions.

View File

@@ -9,9 +9,7 @@ keywords: query, documents, overview, documentation, Content Management System,
Payload provides an extremely granular querying language through all APIs. Each API takes the same syntax and fully supports all options.
<Banner>
<strong>
Here, "querying" relates to filtering or searching through documents within a Collection.
</strong>{' '}
<strong>Here, "querying" relates to filtering or searching through documents within a Collection.</strong>{' '}
You can build queries to pass to Find operations as well as to [restrict which documents certain
users can access](/docs/access-control/overview) via access control functions.
</Banner>

View File

@@ -13,7 +13,6 @@
"clean:unix": "find . \\( -type d \\( -name node_modules -o -name dist -o -name .cache \\) -o -type f -name tsconfig.tsbuildinfo \\) -exec rm -rf {} +",
"dev": "pnpm --filter payload run dev",
"dev:generate-graphql-schema": "ts-node -T ./test/generateGraphQLSchema.ts",
"test:int:postgres": "cross-env PAYLOAD_DATABASE=postgres yarn test:int",
"dev:generate-types": "pnpm --filter payload run dev:generate-types",
"dev:postgres": "pnpm --filter payload run dev:postgres",
"fix": "eslint \"src/**/*.ts\" --fix",
@@ -51,7 +50,6 @@
"express": "4.18.2",
"form-data": "3.0.1",
"get-port": "5.1.1",
"graphql-request": "3.7.0",
"isomorphic-fetch": "3.0.0",
"jest": "29.6.4",
"jest-environment-jsdom": "29.6.4",

View File

@@ -0,0 +1,10 @@
.tmp
**/.git
**/.hg
**/.pnp.*
**/.svn
**/.yarn/**
**/build
**/dist/**
**/node_modules
**/temp

View File

@@ -0,0 +1,43 @@
/** @type {import('prettier').Config} */
module.exports = {
extends: ['@payloadcms'],
overrides: [
{
extends: ['plugin:@typescript-eslint/disable-type-checked'],
files: ['*.js', '*.cjs', '*.json', '*.md', '*.yml', '*.yaml'],
},
{
files: ['**/*.ts'],
rules: {
'@typescript-eslint/no-redundant-type-constituents': 'off',
},
},
{
files: ['package.json', 'tsconfig.json'],
rules: {
'perfectionist/sort-array-includes': 'off',
'perfectionist/sort-astro-attributes': 'off',
'perfectionist/sort-classes': 'off',
'perfectionist/sort-enums': 'off',
'perfectionist/sort-exports': 'off',
'perfectionist/sort-imports': 'off',
'perfectionist/sort-interfaces': 'off',
'perfectionist/sort-jsx-props': 'off',
'perfectionist/sort-keys': 'off',
'perfectionist/sort-maps': 'off',
'perfectionist/sort-named-exports': 'off',
'perfectionist/sort-named-imports': 'off',
'perfectionist/sort-object-types': 'off',
'perfectionist/sort-objects': 'off',
'perfectionist/sort-svelte-attributes': 'off',
'perfectionist/sort-union-types': 'off',
'perfectionist/sort-vue-attributes': 'off',
},
},
],
parserOptions: {
project: ['./tsconfig.json'],
tsconfigRootDir: __dirname,
},
root: true,
}

View File

@@ -0,0 +1,10 @@
.tmp
**/.git
**/.hg
**/.pnp.*
**/.svn
**/.yarn/**
**/build
**/dist/**
**/node_modules
**/temp

View File

@@ -4,6 +4,7 @@
"description": "The officially supported Vite bundler adapter for Payload",
"repository": "https://github.com/payloadcms/payload",
"license": "MIT",
"homepage": "https://payloadcms.com",
"author": {
"email": "info@payloadcms.com",
"name": "Payload",
@@ -12,9 +13,9 @@
"main": "./src/index.ts",
"types": "./src/index.ts",
"scripts": {
"build": "pnpm build:swc && pnpm build:types",
"build:swc": "swc ./src -d ./dist --config-file .swcrc",
"build:types": "tsc --emitDeclarationOnly --outDir dist",
"build": "pnpm build:swc && pnpm build:types"
"build:types": "tsc --emitDeclarationOnly --outDir dist"
},
"dependencies": {
"@rollup/plugin-commonjs": "^25.0.4",

View File

@@ -1,15 +1,16 @@
/* eslint-disable no-param-reassign */
import path from 'path'
import type { SanitizedConfig } from 'payload/config'
// @ts-expect-error
import type { InlineConfig } from 'vite'
import viteCommonJS from 'vite-plugin-commonjs'
import virtual from 'vite-plugin-virtual'
import scss from 'rollup-plugin-scss'
import image from '@rollup/plugin-image'
import rollupCommonJS from '@rollup/plugin-commonjs'
import image from '@rollup/plugin-image'
import react from '@vitejs/plugin-react'
import getPort from 'get-port'
import type { SanitizedConfig } from 'payload/config'
import path from 'path'
import scss from 'rollup-plugin-scss'
import viteCommonJS from 'vite-plugin-commonjs'
import virtual from 'vite-plugin-virtual'
const bundlerPath = path.resolve(__dirname, '../')
const mockModulePath = path.resolve(__dirname, '../mocks/emptyModule.js')
@@ -18,7 +19,7 @@ const mockDotENVPath = path.resolve(__dirname, '../mocks/dotENV.js')
export const getViteConfig = async (payloadConfig: SanitizedConfig): Promise<InlineConfig> => {
const { createLogger } = await import('vite')
const logger = createLogger('warn', { prefix: '[VITE-WARNING]', allowClearScreen: false })
const logger = createLogger('warn', { allowClearScreen: false, prefix: '[VITE-WARNING]' })
const originalWarning = logger.warn
logger.warn = (msg, options) => {
// TODO: fix this? removed these warnings to make debugging easier
@@ -60,9 +61,46 @@ export const getViteConfig = async (payloadConfig: SanitizedConfig): Promise<Inl
}
return {
root: path.resolve(__dirname, '../'),
base: payloadConfig.routes.admin,
build: {
commonjsOptions: {
include: [/payload/],
transformMixedEsModules: true,
},
outDir: payloadConfig.admin.buildPath,
rollupOptions: {
// output: {
// manualChunks: {
// jsonWorker: ['monaco-editor/esm/vs/language/json/json.worker'],
// cssWorker: ['monaco-editor/esm/vs/language/css/css.worker'],
// htmlWorker: ['monaco-editor/esm/vs/language/html/html.worker'],
// tsWorker: ['monaco-editor/esm/vs/language/typescript/ts.worker'],
// editorWorker: ['monaco-editor/esm/vs/editor/editor.worker'],
// },
// },
input: {
main: path.resolve(__dirname, '../index.html'),
},
plugins: [
image(),
rollupCommonJS(),
scss({
output: path.resolve(payloadConfig.admin.buildPath, 'styles.css'),
outputStyle: 'compressed',
// include: [`${relativeAdminPath}/**/*.scss`],
}),
],
treeshake: true,
},
},
customLogger: logger,
define: {
__dirname: '""',
'module.hot': 'undefined',
'process.argv': '[]',
'process.cwd': '() => ""',
'process.env': '{}',
},
optimizeDeps: {
exclude: [
// Dependencies that need aliases should be excluded
@@ -79,22 +117,6 @@ export const getViteConfig = async (payloadConfig: SanitizedConfig): Promise<Inl
// '@monaco-editor/react',
],
},
server: {
middlewareMode: true,
hmr: {
port: hmrPort,
},
},
resolve: {
alias,
},
define: {
__dirname: '""',
'module.hot': 'undefined',
'process.env': '{}',
'process.cwd': '() => ""',
'process.argv': '[]',
},
plugins: [
{
name: 'absolute-aliases',
@@ -119,8 +141,8 @@ export const getViteConfig = async (payloadConfig: SanitizedConfig): Promise<Inl
},
virtual({
crypto: 'export default {}',
https: 'export default {}',
http: 'export default {}',
https: 'export default {}',
}),
react(),
// viteCommonJS(),
@@ -138,36 +160,15 @@ export const getViteConfig = async (payloadConfig: SanitizedConfig): Promise<Inl
// },
// },
],
build: {
outDir: payloadConfig.admin.buildPath,
commonjsOptions: {
transformMixedEsModules: true,
include: [/payload/],
},
rollupOptions: {
// output: {
// manualChunks: {
// jsonWorker: ['monaco-editor/esm/vs/language/json/json.worker'],
// cssWorker: ['monaco-editor/esm/vs/language/css/css.worker'],
// htmlWorker: ['monaco-editor/esm/vs/language/html/html.worker'],
// tsWorker: ['monaco-editor/esm/vs/language/typescript/ts.worker'],
// editorWorker: ['monaco-editor/esm/vs/editor/editor.worker'],
// },
// },
plugins: [
image(),
rollupCommonJS(),
scss({
output: path.resolve(payloadConfig.admin.buildPath, 'styles.css'),
outputStyle: 'compressed',
// include: [`${relativeAdminPath}/**/*.scss`],
}),
],
treeshake: true,
input: {
main: path.resolve(__dirname, '../index.html'),
resolve: {
alias,
},
root: path.resolve(__dirname, '../'),
server: {
hmr: {
port: hmrPort,
},
middlewareMode: true,
},
}
}

View File

@@ -1,8 +1,8 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
import { Root } from 'payload/components/root'
// @ts-ignore - need to do this because this file doesn't actually exist
import React from 'react'
import { createRoot } from 'react-dom/client'
import { Root } from 'payload/components/root'
const container = document.getElementById('app')
const root = createRoot(container) // createRoot(container!) if you use TypeScript

View File

@@ -1,12 +1,14 @@
// @ts-expect-error
import type { InlineConfig } from 'vite'
import { PayloadBundler } from './types'
import { devAdmin } from './scripts/dev'
import type { PayloadBundler } from './types'
import { buildAdmin } from './scripts/build'
import { devAdmin } from './scripts/dev'
import { serveAdmin } from './scripts/serve'
export default (viteConfig?: InlineConfig): PayloadBundler => ({
dev: async (payload) => devAdmin({ payload, viteConfig }),
export const viteBundler: (viteConfig?: InlineConfig) => PayloadBundler = (viteConfig) => ({
build: async (payloadConfig) => buildAdmin({ payloadConfig, viteConfig }),
dev: async (payload) => devAdmin({ payload, viteConfig }),
serve: async (payload) => serveAdmin({ payload }),
})

View File

@@ -1 +1 @@
export default () => {};
export default () => {}

View File

@@ -1,3 +1,3 @@
export default {
config: () => null,
};
}

View File

@@ -1 +1 @@
export default () => { };
export default () => {}

View File

@@ -1 +1 @@
export default 'file-stub';
export default 'file-stub'

View File

@@ -1,6 +1,6 @@
// @ts-expect-error
import type { SanitizedConfig } from 'payload/config'
import type { InlineConfig } from 'vite'
import { SanitizedConfig } from 'payload/config'
import { getViteConfig } from '../configs/vite'
type BuildAdminType = (options: {

View File

@@ -1,8 +1,10 @@
// @ts-expect-error
import type { InlineConfig } from 'vite'
import express from 'express'
import type { PayloadHandler } from 'payload/config'
import { Payload } from '../../../payload'
import type { InlineConfig } from 'vite'
import express from 'express'
import type { Payload } from '../../../payload'
import { getViteConfig } from '../configs/vite'
const router = express.Router()

View File

@@ -1,8 +1,9 @@
import express from 'express'
import type { Payload } from 'payload'
import type { PayloadHandler } from 'payload/config'
import compression from 'compression'
import history from 'connect-history-api-fallback'
import type { PayloadHandler } from 'payload/config'
import type { Payload } from 'payload'
import express from 'express'
const router = express.Router()

View File

@@ -1,8 +1,8 @@
import type { PayloadHandler, SanitizedConfig } from 'payload/config'
import type { Payload } from 'payload'
import type { PayloadHandler, SanitizedConfig } from 'payload/config'
export interface PayloadBundler {
dev: (payload: Payload) => Promise<PayloadHandler> // this would be a typical Express middleware handler
build: (payloadConfig: SanitizedConfig) => Promise<void> // used in `payload build`
dev: (payload: Payload) => Promise<PayloadHandler> // this would be a typical Express middleware handler
serve: (payload: Payload) => Promise<PayloadHandler> // serve built files in production
}

View File

@@ -0,0 +1,10 @@
.tmp
**/.git
**/.hg
**/.pnp.*
**/.svn
**/.yarn/**
**/build
**/dist/**
**/node_modules
**/temp

View File

@@ -0,0 +1,43 @@
/** @type {import('prettier').Config} */
module.exports = {
extends: ['@payloadcms'],
overrides: [
{
extends: ['plugin:@typescript-eslint/disable-type-checked'],
files: ['*.js', '*.cjs', '*.json', '*.md', '*.yml', '*.yaml'],
},
{
files: ['**/*.ts'],
rules: {
'@typescript-eslint/no-redundant-type-constituents': 'off',
},
},
{
files: ['package.json', 'tsconfig.json'],
rules: {
'perfectionist/sort-array-includes': 'off',
'perfectionist/sort-astro-attributes': 'off',
'perfectionist/sort-classes': 'off',
'perfectionist/sort-enums': 'off',
'perfectionist/sort-exports': 'off',
'perfectionist/sort-imports': 'off',
'perfectionist/sort-interfaces': 'off',
'perfectionist/sort-jsx-props': 'off',
'perfectionist/sort-keys': 'off',
'perfectionist/sort-maps': 'off',
'perfectionist/sort-named-exports': 'off',
'perfectionist/sort-named-imports': 'off',
'perfectionist/sort-object-types': 'off',
'perfectionist/sort-objects': 'off',
'perfectionist/sort-svelte-attributes': 'off',
'perfectionist/sort-union-types': 'off',
'perfectionist/sort-vue-attributes': 'off',
},
},
],
parserOptions: {
project: ['./tsconfig.json'],
tsconfigRootDir: __dirname,
},
root: true,
}

View File

@@ -0,0 +1,10 @@
.tmp
**/.git
**/.hg
**/.pnp.*
**/.svn
**/.yarn/**
**/build
**/dist/**
**/node_modules
**/temp

View File

@@ -4,6 +4,7 @@
"description": "The officially supported Webpack bundler adapter for Payload",
"repository": "https://github.com/payloadcms/payload",
"license": "MIT",
"homepage": "https://payloadcms.com",
"author": {
"email": "info@payloadcms.com",
"name": "Payload",

View File

@@ -1,7 +1,9 @@
import path from 'path'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import webpack, { Configuration } from 'webpack'
import type { SanitizedConfig } from 'payload/config'
import type { Configuration } from 'webpack'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import path from 'path'
import webpack from 'webpack'
const mockModulePath = path.resolve(__dirname, '../mocks/emptyModule.js')
const mockDotENVPath = path.resolve(__dirname, '../mocks/dotENV.js')
@@ -17,8 +19,8 @@ export const getBaseConfig = (payloadConfig: SanitizedConfig): Configuration =>
module: {
rules: [
{
test: /\.(t|j)sx?$/,
exclude: /\/node_modules\/(?!.+\.tsx?$).*$/,
test: /\.(t|j)sx?$/,
use: [
{
loader: require.resolve('swc-loader'),
@@ -43,23 +45,6 @@ export const getBaseConfig = (payloadConfig: SanitizedConfig): Configuration =>
},
],
},
resolve: {
fallback: {
crypto: false,
https: false,
http: false,
},
modules: ['node_modules', nodeModulesPath],
alias: {
path: require.resolve('path-browserify'),
'payload-config': payloadConfig.paths.rawConfig,
payload$: mockModulePath,
'payload-user-css': payloadConfig.admin.css,
dotenv: mockDotENVPath,
[bundlerPath]: mockModulePath,
},
extensions: ['.ts', '.tsx', '.js', '.json'],
},
plugins: [
new webpack.ProvidePlugin({ process: require.resolve('process/browser') }),
new webpack.DefinePlugin(
@@ -75,9 +60,26 @@ export const getBaseConfig = (payloadConfig: SanitizedConfig): Configuration =>
}, {}),
),
new HtmlWebpackPlugin({
template: payloadConfig.admin.indexHTML,
filename: path.normalize('./index.html'),
template: payloadConfig.admin.indexHTML,
}),
new webpack.HotModuleReplacementPlugin(),
],
resolve: {
alias: {
[bundlerPath]: mockModulePath,
dotenv: mockDotENVPath,
path: require.resolve('path-browserify'),
payload$: mockModulePath,
'payload-config': payloadConfig.paths.rawConfig,
'payload-user-css': payloadConfig.admin.css,
},
extensions: ['.ts', '.tsx', '.js', '.json'],
fallback: {
crypto: false,
http: false,
https: false,
},
modules: ['node_modules', nodeModulesPath],
},
})

View File

@@ -1,20 +1,40 @@
import webpack, { Configuration } from 'webpack'
import type { SanitizedConfig } from 'payload/config'
import type { Configuration } from 'webpack'
import md5 from 'md5'
import webpack from 'webpack'
import { getBaseConfig } from './base'
import { SanitizedConfig } from 'payload/config'
export const getDevConfig = (payloadConfig: SanitizedConfig): Configuration => {
const baseConfig = getBaseConfig(payloadConfig) as any
let webpackConfig: Configuration = {
...baseConfig,
cache: {
type: 'filesystem',
// version cache when there are changes to aliases
buildDependencies: {
config: [__filename],
},
version: md5(Object.entries(baseConfig.resolve.alias).join()),
},
devtool: 'inline-source-map',
entry: {
...baseConfig.entry,
main: [
`webpack-hot-middleware/client?path=${payloadConfig.routes.admin}/__webpack_hmr`,
...(baseConfig.entry.main as string[]),
],
},
mode: 'development',
module: {
...baseConfig.module,
rules: [
...baseConfig.module.rules,
{
test: /\.(scss|css)$/,
sideEffects: true,
test: /\.(scss|css)$/,
/*
* The loaders here are run in reverse order. Here is how your loaders are being processed:
* 1. sass-loader: This loader compiles your SCSS into CSS.
@@ -43,30 +63,13 @@ export const getDevConfig = (payloadConfig: SanitizedConfig): Configuration => {
},
],
},
cache: {
type: 'filesystem',
// version cache when there are changes to aliases
version: md5(Object.entries(baseConfig.resolve.alias).join()),
buildDependencies: {
config: [__filename],
},
},
entry: {
...baseConfig.entry,
main: [
`webpack-hot-middleware/client?path=${payloadConfig.routes.admin}/__webpack_hmr`,
...(baseConfig.entry.main as string[]),
],
},
output: {
publicPath: `${payloadConfig.routes.admin}/`,
path: '/',
filename: '[name].js',
path: '/',
publicPath: `${payloadConfig.routes.admin}/`,
},
devtool: 'inline-source-map',
mode: 'development',
stats: 'errors-warnings',
plugins: [...baseConfig.plugins, new webpack.HotModuleReplacementPlugin()],
stats: 'errors-warnings',
}
if (payloadConfig.admin.webpack && typeof payloadConfig.admin.webpack === 'function') {

View File

@@ -1,22 +1,26 @@
import { Configuration, WebpackPluginInstance } from 'webpack'
import type { SanitizedConfig } from 'payload/config'
import type { Configuration } from 'webpack'
import MiniCSSExtractPlugin from 'mini-css-extract-plugin'
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
import { SwcMinifyWebpackPlugin } from 'swc-minify-webpack-plugin'
import { WebpackPluginInstance } from 'webpack'
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
import { getBaseConfig } from './base'
import { SanitizedConfig } from 'payload/config'
export const getProdConfig = (payloadConfig: SanitizedConfig): Configuration => {
const baseConfig = getBaseConfig(payloadConfig) as any
let webpackConfig: Configuration = {
...baseConfig,
mode: 'production',
module: {
...baseConfig.module,
rules: [
...baseConfig.module.rules,
{
test: /\.(scss|css)$/,
sideEffects: true,
test: /\.(scss|css)$/,
use: [
MiniCSSExtractPlugin.loader,
{
@@ -38,27 +42,25 @@ export const getProdConfig = (payloadConfig: SanitizedConfig): Configuration =>
},
],
},
output: {
publicPath: `${payloadConfig.routes.admin}/`,
path: payloadConfig.admin.buildPath,
filename: '[name].[chunkhash].js',
chunkFilename: '[name].[chunkhash].js',
},
mode: 'production',
stats: 'errors-only',
optimization: {
minimizer: [new SwcMinifyWebpackPlugin()],
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.(sa|sc|c)ss$/,
chunks: 'all',
enforce: true,
test: /\.(sa|sc|c)ss$/,
},
},
},
},
output: {
chunkFilename: '[name].[chunkhash].js',
filename: '[name].[chunkhash].js',
path: payloadConfig.admin.buildPath,
publicPath: `${payloadConfig.routes.admin}/`,
},
plugins: [
...baseConfig.plugins,
new MiniCSSExtractPlugin({
@@ -67,6 +69,7 @@ export const getProdConfig = (payloadConfig: SanitizedConfig): Configuration =>
}),
...(process.env.PAYLOAD_ANALYZE_BUNDLE ? [new BundleAnalyzerPlugin()] : []),
],
stats: 'errors-only',
}
if (payloadConfig.admin.webpack && typeof payloadConfig.admin.webpack === 'function') {

View File

@@ -1,11 +1,12 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import { PayloadBundler } from '../../payload/dist/bundlers/types'
import { devAdmin } from './scripts/dev'
import type { PayloadBundler } from '../../payload/dist/bundlers/types'
import { buildAdmin } from './scripts/build'
import { devAdmin } from './scripts/dev'
import { serveAdmin } from './scripts/serve'
export default (): PayloadBundler => ({
dev: async (payload) => devAdmin({ payload }),
export const webpackBundler: () => PayloadBundler = () => ({
build: async (payloadConfig) => buildAdmin({ payloadConfig }),
dev: async (payload) => devAdmin({ payload }),
serve: async (payload) => serveAdmin({ payload }),
})

View File

@@ -1 +1 @@
export default () => {}
export const webpackBundler = () => {}

View File

@@ -1,6 +1,8 @@
import type { SanitizedConfig } from 'payload/config'
import webpack from 'webpack'
import { getProdConfig } from '../configs/prod'
import { SanitizedConfig } from 'payload/config'
type BuildAdminType = (options: { payloadConfig: SanitizedConfig }) => Promise<void>
export const buildAdmin: BuildAdminType = async ({ payloadConfig }) => {

View File

@@ -1,10 +1,12 @@
import webpack from 'webpack'
import type { Payload } from 'payload'
import type { PayloadHandler } from 'payload/config'
import history from 'connect-history-api-fallback'
import express from 'express'
import webpack from 'webpack'
import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import history from 'connect-history-api-fallback'
import type { PayloadHandler } from 'payload/config'
import { Payload } from 'payload'
import { getDevConfig } from '../configs/dev'
const router = express.Router()

View File

@@ -1,8 +1,9 @@
import express from 'express'
import type { Payload } from 'payload'
import type { PayloadHandler } from 'payload/config'
import compression from 'compression'
import history from 'connect-history-api-fallback'
import type { PayloadHandler } from 'payload/config'
import { Payload } from 'payload'
import express from 'express'
const router = express.Router()

View File

@@ -6,6 +6,28 @@ module.exports = {
extends: ['plugin:@typescript-eslint/disable-type-checked'],
files: ['*.js', '*.cjs', '*.json', '*.md', '*.yml', '*.yaml'],
},
{
files: ['package.json', 'tsconfig.json'],
rules: {
'perfectionist/sort-array-includes': 'off',
'perfectionist/sort-astro-attributes': 'off',
'perfectionist/sort-classes': 'off',
'perfectionist/sort-enums': 'off',
'perfectionist/sort-exports': 'off',
'perfectionist/sort-imports': 'off',
'perfectionist/sort-interfaces': 'off',
'perfectionist/sort-jsx-props': 'off',
'perfectionist/sort-keys': 'off',
'perfectionist/sort-maps': 'off',
'perfectionist/sort-named-exports': 'off',
'perfectionist/sort-named-imports': 'off',
'perfectionist/sort-object-types': 'off',
'perfectionist/sort-objects': 'off',
'perfectionist/sort-svelte-attributes': 'off',
'perfectionist/sort-union-types': 'off',
'perfectionist/sort-vue-attributes': 'off',
},
},
],
parserOptions: {
project: ['./tsconfig.json'],

View File

@@ -24,9 +24,9 @@ export const createVersion: CreateVersion = async function createVersion(
const [doc] = await VersionModel.create(
[
{
latest: true,
autosave,
createdAt,
latest: true,
parent,
updatedAt,
version: versionData,
@@ -36,7 +36,8 @@ export const createVersion: CreateVersion = async function createVersion(
req,
)
await VersionModel.updateMany({
await VersionModel.updateMany(
{
$and: [
{
_id: {
@@ -54,10 +55,12 @@ export const createVersion: CreateVersion = async function createVersion(
},
},
],
}, { $unset: { latest: 1 } });
},
{ $unset: { latest: 1 } },
)
const result: Document = JSON.parse(JSON.stringify(doc));
const verificationToken = doc._verificationToken;
const result: Document = JSON.parse(JSON.stringify(doc))
const verificationToken = doc._verificationToken
// custom id type reset
result.id = result._id

View File

@@ -1,8 +1,7 @@
import type { Field, TabAsField } from 'payload/types';
import mongoose from 'mongoose';
import { createArrayFromCommaDelineated } from 'payload/utilities';
import type { Field, TabAsField } from 'payload/types'
import mongoose from 'mongoose'
import { createArrayFromCommaDelineated } from 'payload/utilities'
type SanitizeQueryValueArgs = {
field: Field | TabAsField

View File

@@ -2,7 +2,7 @@ import type { PaginateOptions } from 'mongoose'
import type { QueryDrafts } from 'payload/database'
import type { PayloadRequest } from 'payload/types'
import { flattenWhereToOperators, combineQueries } from 'payload/database'
import { combineQueries, flattenWhereToOperators } from 'payload/database'
import type { MongooseAdapter } from '.'
@@ -18,8 +18,8 @@ export const queryDrafts: QueryDrafts = async function queryDrafts<T>(
const collectionConfig = this.payload.collections[collection].config
const options = withSession(this, req.transactionID)
let hasNearConstraint;
let sort;
let hasNearConstraint
let sort
if (where) {
const constraints = flattenWhereToOperators(where)
@@ -36,33 +36,33 @@ export const queryDrafts: QueryDrafts = async function queryDrafts<T>(
})
}
const combinedWhere = combineQueries({ latest: { equals: true } }, where);
const combinedWhere = combineQueries({ latest: { equals: true } }, where)
const versionQuery = await VersionModel.buildQuery({
where: combinedWhere,
locale,
payload: this.payload,
});
where: combinedWhere,
})
const paginationOptions: PaginateOptions = {
page,
sort,
forceCountFn: hasNearConstraint,
lean: true,
leanWithId: true,
useEstimatedCount: hasNearConstraint,
forceCountFn: hasNearConstraint,
pagination,
options,
};
if (limit > 0) {
paginationOptions.limit = limit;
// limit must also be set here, it's ignored when pagination is false
paginationOptions.options.limit = limit;
page,
pagination,
sort,
useEstimatedCount: hasNearConstraint,
}
const result = await VersionModel.paginate(versionQuery, paginationOptions);
const docs = JSON.parse(JSON.stringify(result.docs));
if (limit > 0) {
paginationOptions.limit = limit
// limit must also be set here, it's ignored when pagination is false
paginationOptions.options.limit = limit
}
const result = await VersionModel.paginate(versionQuery, paginationOptions)
const docs = JSON.parse(JSON.stringify(result.docs))
return {
...result,

View File

@@ -11,7 +11,7 @@ import { withSession } from './withSession'
export const updateOne: UpdateOne = async function updateOne(
this: MongooseAdapter,
{ collection, data, id, locale, req = {} as PayloadRequest, where: whereArg },
{ id, collection, data, locale, req = {} as PayloadRequest, where: whereArg },
) {
const where = id ? { id: { equals: id } } : whereArg
const Model = this.collections[collection]

View File

@@ -12,6 +12,28 @@ module.exports = {
'@typescript-eslint/no-redundant-type-constituents': 'off',
},
},
{
files: ['package.json', 'tsconfig.json'],
rules: {
'perfectionist/sort-array-includes': 'off',
'perfectionist/sort-astro-attributes': 'off',
'perfectionist/sort-classes': 'off',
'perfectionist/sort-enums': 'off',
'perfectionist/sort-exports': 'off',
'perfectionist/sort-imports': 'off',
'perfectionist/sort-interfaces': 'off',
'perfectionist/sort-jsx-props': 'off',
'perfectionist/sort-keys': 'off',
'perfectionist/sort-maps': 'off',
'perfectionist/sort-named-exports': 'off',
'perfectionist/sort-named-imports': 'off',
'perfectionist/sort-object-types': 'off',
'perfectionist/sort-objects': 'off',
'perfectionist/sort-svelte-attributes': 'off',
'perfectionist/sort-union-types': 'off',
'perfectionist/sort-vue-attributes': 'off',
},
},
],
parserOptions: {
project: ['./tsconfig.json'],

View File

@@ -4,6 +4,7 @@
"description": "The officially supported Postgres database adapter for Payload",
"repository": "https://github.com/payloadcms/payload",
"license": "MIT",
"homepage": "https://payloadcms.com",
"author": {
"email": "info@payloadcms.com",
"name": "Payload",
@@ -14,8 +15,7 @@
"scripts": {
"build": "pnpm build:swc && pnpm build:types",
"build:swc": "swc ./src -d ./dist --config-file .swcrc",
"build:types": "tsc --emitDeclarationOnly --outDir dist",
"builddisabled": "pnpm build:swc && pnpm build:types"
"build:types": "tsc --emitDeclarationOnly --outDir dist"
},
"dependencies": {
"@libsql/client": "^0.3.1",

View File

@@ -1,149 +1,149 @@
import type { Connect } from 'payload/database';
import type { Connect } from 'payload/database'
import { generateDrizzleJson, pushSchema } from 'drizzle-kit/utils';
import { eq, sql } from 'drizzle-orm';
import { drizzle } from 'drizzle-orm/node-postgres';
import { jsonb, numeric, pgTable, varchar } from 'drizzle-orm/pg-core';
import fs from 'fs';
import { configToJSONSchema } from 'payload/utilities';
import { Client, Pool } from 'pg';
import prompts from 'prompts';
import { v4 as uuid } from 'uuid';
import { generateDrizzleJson, pushSchema } from 'drizzle-kit/utils'
import { eq, sql } from 'drizzle-orm'
import { drizzle } from 'drizzle-orm/node-postgres'
import { jsonb, numeric, pgTable, varchar } from 'drizzle-orm/pg-core'
import fs from 'fs'
import { configToJSONSchema } from 'payload/utilities'
import { Client, Pool } from 'pg'
import prompts from 'prompts'
import { v4 as uuid } from 'uuid'
import type { DrizzleDB, PostgresAdapter } from './types';
import type { DrizzleDB, PostgresAdapter } from './types'
// Migration table def in order to use query using drizzle
const migrationsSchema = pgTable('payload_migrations', {
batch: numeric('batch'),
name: varchar('name'),
batch: numeric('batch'),
schema: jsonb('schema'),
});
})
export const connect: Connect = async function connect(
this: PostgresAdapter,
payload,
) {
let db: DrizzleDB;
export const connect: Connect = async function connect(this: PostgresAdapter, payload) {
let db: DrizzleDB
this.schema = {
...this.tables,
...this.relations,
...this.enums,
};
}
try {
const sessionID = uuid();
const sessionID = uuid()
if ('pool' in this && this.pool !== false) {
const pool = new Pool(this.pool);
db = drizzle(pool, { schema: this.schema });
await pool.connect();
const pool = new Pool(this.pool)
db = drizzle(pool, { schema: this.schema })
await pool.connect()
}
if ('client' in this && this.client !== false) {
const client = new Client(this.client);
db = drizzle(client, { schema: this.schema });
await client.connect();
const client = new Client(this.client)
db = drizzle(client, { schema: this.schema })
await client.connect()
}
this.sessions[sessionID] = db;
this.sessions[sessionID] = db
if (process.env.PAYLOAD_DROP_DATABASE === 'true') {
this.payload.logger.info('---- DROPPING TABLES ----');
await db.execute(sql`drop schema public cascade;\ncreate schema public;`);
this.payload.logger.info('---- DROPPED TABLES ----');
this.payload.logger.info('---- DROPPING TABLES ----')
await db.execute(sql`drop schema public cascade;\ncreate schema public;`)
this.payload.logger.info('---- DROPPED TABLES ----')
}
} catch (err) {
payload.logger.error(
`Error: cannot connect to Postgres. Details: ${err.message}`,
err,
);
process.exit(1);
payload.logger.error(`Error: cannot connect to Postgres. Details: ${err.message}`, err)
process.exit(1)
}
this.payload.logger.info('Connected to Postgres successfully');
this.db = db;
this.payload.logger.info('Connected to Postgres successfully')
this.db = db
// Only push schema if not in production
if (process.env.NODE_ENV === 'production') return;
if (process.env.NODE_ENV === 'production') return
// This will prompt if clarifications are needed for Drizzle to push new schema
const { apply, hasDataLoss, statementsToExecute, warnings } = await pushSchema(this.schema, this.db);
const { apply, hasDataLoss, statementsToExecute, warnings } = await pushSchema(
this.schema,
this.db,
)
this.payload.logger.debug({
hasDataLoss,
msg: 'Schema push results',
statementsToExecute,
warnings,
});
})
if (warnings.length) {
this.payload.logger.warn({
msg: `Warnings detected during schema push: ${warnings.join('\n')}`,
warnings,
});
})
if (hasDataLoss) {
this.payload.logger.warn({
msg: 'DATA LOSS WARNING: Possible data loss detected if schema is pushed.',
});
})
}
const { confirm: acceptWarnings } = await prompts(
{
name: 'confirm',
initial: false,
message: 'Accept warnings and push schema to database?',
name: 'confirm',
type: 'confirm',
},
{
onCancel: () => {
process.exit(0);
process.exit(0)
},
},
);
)
// Exit if user does not accept warnings.
// Q: Is this the right type of exit for this interaction?
if (!acceptWarnings) {
process.exit(0);
process.exit(0)
}
}
this.migrationDir = '.migrations';
this.migrationDir = '.migrations'
// Create drizzle snapshot if it doesn't exist
if (!fs.existsSync(`${this.migrationDir}/drizzle-snapshot.json`)) {
// Ensure migration dir exists
if (!fs.existsSync(this.migrationDir)) {
fs.mkdirSync(this.migrationDir);
fs.mkdirSync(this.migrationDir)
}
const drizzleJSON = generateDrizzleJson(this.schema);
const drizzleJSON = generateDrizzleJson(this.schema)
fs.writeFileSync(`${this.migrationDir}/drizzle-snapshot.json`, JSON.stringify(drizzleJSON, null, 2));
fs.writeFileSync(
`${this.migrationDir}/drizzle-snapshot.json`,
JSON.stringify(drizzleJSON, null, 2),
)
}
const jsonSchema = configToJSONSchema(this.payload.config);
const jsonSchema = configToJSONSchema(this.payload.config)
await apply();
await apply()
const devPush = await this.db
.select()
.from(migrationsSchema)
.where(eq(migrationsSchema.batch, '-1'));
.where(eq(migrationsSchema.batch, '-1'))
if (!devPush.length) {
await this.db.insert(migrationsSchema).values({
batch: '-1',
name: 'dev',
batch: '-1',
schema: JSON.stringify(jsonSchema),
});
})
} else {
await this.db
.update(migrationsSchema)
.set({
schema: JSON.stringify(jsonSchema),
})
.where(eq(migrationsSchema.batch, '-1'));
.where(eq(migrationsSchema.batch, '-1'))
}
};
}

View File

@@ -1,16 +1,12 @@
import type { Create } from 'payload/database';
import type { Create } from 'payload/database'
import toSnakeCase from 'to-snake-case';
import toSnakeCase from 'to-snake-case'
import { upsertRow } from '../upsertRow';
import { upsertRow } from '../upsertRow'
export const create: Create = async function create({
collection: collectionSlug,
data,
req,
}) {
const db = req.transactionID ? this.sessions[req.transactionID] : this.db;
const collection = this.payload.collections[collectionSlug].config;
export const create: Create = async function create({ collection: collectionSlug, data, req }) {
const db = req.transactionID ? this.sessions[req.transactionID] : this.db
const collection = this.payload.collections[collectionSlug].config
const result = await upsertRow({
adapter: this,
@@ -19,7 +15,7 @@ export const create: Create = async function create({
fields: collection.fields,
operation: 'create',
tableName: toSnakeCase(collectionSlug),
});
})
return result;
};
return result
}

View File

@@ -1,18 +1,18 @@
import type { CreateGlobal } from 'payload/database';
import type { PayloadRequest } from 'payload/types';
import type { CreateGlobal } from 'payload/database'
import type { PayloadRequest } from 'payload/types'
import toSnakeCase from 'to-snake-case';
import toSnakeCase from 'to-snake-case'
import type { PostgresAdapter } from './types';
import type { PostgresAdapter } from './types'
import { upsertRow } from './upsertRow';
import { upsertRow } from './upsertRow'
export const createGlobal: CreateGlobal = async function createGlobal(
this: PostgresAdapter,
{ data, req = {} as PayloadRequest, slug },
) {
const db = req.transactionID ? this.sessions[req.transactionID] : this.db;
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug);
const db = req.transactionID ? this.sessions[req.transactionID] : this.db
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug)
const result = await upsertRow({
adapter: this,
@@ -21,7 +21,7 @@ export const createGlobal: CreateGlobal = async function createGlobal(
fields: globalConfig.fields,
operation: 'create',
tableName: toSnakeCase(slug),
});
})
return result;
};
return result
}

View File

@@ -1,16 +1,10 @@
/* eslint-disable no-restricted-syntax, no-await-in-loop */
import fs from 'fs';
import { CreateMigration } from 'payload/dist/database/types';
import type { CreateMigration } from 'payload/database'
import { generateDrizzleJson, generateMigration } from 'drizzle-kit/utils';
import { eq } from 'drizzle-orm';
import { jsonb, numeric, pgEnum, pgTable, varchar } from 'drizzle-orm/pg-core';
import { SanitizedCollectionConfig } from 'payload/dist/collections/config/types';
import type { DatabaseAdapter, Init } from 'payload/dist/database/types';
import { configToJSONSchema } from 'payload/dist/utilities/configToJSONSchema';
import prompts from 'prompts';
import { buildTable } from './schema/build';
import type { GenericEnum, GenericRelation, GenericTable, PostgresAdapter } from './types';
import { generateDrizzleJson, generateMigration } from 'drizzle-kit/utils'
import fs from 'fs'
import type { PostgresAdapter } from './types'
const migrationTemplate = (upSQL?: string) => `
import payload, { Payload } from 'payload';
@@ -22,7 +16,7 @@ export async function up(payload: Payload): Promise<void> {
export async function down(payload: Payload): Promise<void> {
// Migration code
};
`;
`
export const createMigration: CreateMigration = async function createMigration(
this: PostgresAdapter,
@@ -30,27 +24,30 @@ export const createMigration: CreateMigration = async function createMigration(
migrationDir,
migrationName,
) {
payload.logger.info({ msg: 'Creating migration from postgres adapter...' });
const dir = migrationDir || '.migrations'; // TODO: Verify path after linking
payload.logger.info({ msg: 'Creating migration from postgres adapter...' })
const dir = migrationDir || '.migrations' // TODO: Verify path after linking
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
fs.mkdirSync(dir)
}
const [yyymmdd, hhmmss] = new Date().toISOString().split('T');
const formattedDate = yyymmdd.replace(/\D/g, '');
const formattedTime = hhmmss.split('.')[0].replace(/\D/g, '');
const [yyymmdd, hhmmss] = new Date().toISOString().split('T')
const formattedDate = yyymmdd.replace(/\D/g, '')
const formattedTime = hhmmss.split('.')[0].replace(/\D/g, '')
const timestamp = `${formattedDate}_${formattedTime}`;
const timestamp = `${formattedDate}_${formattedTime}`
const formattedName = migrationName.replace(/\W/g, '_');
const fileName = `${timestamp}_${formattedName}.ts`;
const filePath = `${dir}/${fileName}`;
const formattedName = migrationName.replace(/\W/g, '_')
const fileName = `${timestamp}_${formattedName}.ts`
const filePath = `${dir}/${fileName}`
const snapshotJSON = fs.readFileSync(`${dir}/drizzle-snapshot.json`, 'utf8');
const drizzleJsonBefore = generateDrizzleJson(JSON.parse(snapshotJSON));
const drizzleJsonAfter = generateDrizzleJson(this.schema, drizzleJsonBefore.id);
const sqlStatements = await generateMigration(drizzleJsonBefore, drizzleJsonAfter);
fs.writeFileSync(filePath, migrationTemplate(sqlStatements.length ? sqlStatements?.join('\n') : undefined));
const snapshotJSON = fs.readFileSync(`${dir}/drizzle-snapshot.json`, 'utf8')
const drizzleJsonBefore = generateDrizzleJson(JSON.parse(snapshotJSON))
const drizzleJsonAfter = generateDrizzleJson(this.schema, drizzleJsonBefore.id)
const sqlStatements = await generateMigration(drizzleJsonBefore, drizzleJsonAfter)
fs.writeFileSync(
filePath,
migrationTemplate(sqlStatements.length ? sqlStatements?.join('\n') : undefined),
)
// TODO:
// Get the most recent migration schema from the file system
@@ -61,4 +58,4 @@ export const createMigration: CreateMigration = async function createMigration(
// and then inject them each into the `migrationTemplate` above,
// outputting the file into the migrations folder accordingly
// also make sure to output the JSON schema snapshot into a `./migrationsDir/meta` folder like Drizzle does
};
}

View File

@@ -1,25 +1,18 @@
import type { CreateVersion } from 'payload/database';
import type { CreateVersion } from 'payload/database'
import { buildVersionCollectionFields } from 'payload/versions';
import toSnakeCase from 'to-snake-case';
import { buildVersionCollectionFields } from 'payload/versions'
import toSnakeCase from 'to-snake-case'
import type { PostgresAdapter } from './types';
import type { PostgresAdapter } from './types'
import { upsertRow } from './upsertRow';
import { upsertRow } from './upsertRow'
export const createVersion: CreateVersion = async function createVersion(
this: PostgresAdapter,
{
autosave,
collectionSlug,
createdAt,
parent,
updatedAt,
versionData,
},
{ autosave, collectionSlug, createdAt, parent, updatedAt, versionData },
) {
const collection = this.payload.collections[collectionSlug].config;
const tableName = toSnakeCase(collectionSlug);
const collection = this.payload.collections[collectionSlug].config
const tableName = toSnakeCase(collectionSlug)
const result = await upsertRow({
adapter: this,
@@ -31,10 +24,11 @@ export const createVersion: CreateVersion = async function createVersion(
updatedAt,
version: versionData,
},
db: this.db,
fields: buildVersionCollectionFields(collection),
operation: 'create',
tableName: `_${tableName}_versions`,
});
})
// const [doc] = await VersionModel.create(
// [
@@ -71,5 +65,5 @@ export const createVersion: CreateVersion = async function createVersion(
// ],
// }, { $unset: { latest: 1 } });
return result;
};
return result
}

View File

@@ -1,51 +1,48 @@
import type { DeleteMany } from 'payload/database';
import type { PayloadRequest } from 'payload/types';
import type { DeleteMany } from 'payload/database'
import type { PayloadRequest } from 'payload/types'
import toSnakeCase from 'to-snake-case';
import toSnakeCase from 'to-snake-case'
import type { PostgresAdapter } from './types';
import type { PostgresAdapter } from './types'
import { buildFindManyArgs } from './find/buildFindManyArgs';
import buildQuery from './queries/buildQuery';
import { transform } from './transform/read';
import { buildFindManyArgs } from './find/buildFindManyArgs'
import buildQuery from './queries/buildQuery'
import { transform } from './transform/read'
export const deleteMany: DeleteMany = async function deleteMany(this: PostgresAdapter,
{
collection,
req = {} as PayloadRequest,
where: incomingWhere,
}) {
const collectionConfig = this.payload.collections[collection].config;
const tableName = toSnakeCase(collection);
export const deleteMany: DeleteMany = async function deleteMany(
this: PostgresAdapter,
{ collection, req = {} as PayloadRequest, where: incomingWhere },
) {
const collectionConfig = this.payload.collections[collection].config
const tableName = toSnakeCase(collection)
const { where } = await buildQuery({
adapter: this,
fields: collectionConfig.fields,
tableName,
where: incomingWhere,
});
})
const findManyArgs = buildFindManyArgs({
adapter: this,
depth: 0,
fields: collectionConfig.fields,
tableName,
});
})
findManyArgs.where = where;
findManyArgs.where = where
const docsToDelete = await this.db.query[tableName].findMany(findManyArgs);
const docsToDelete = await this.db.query[tableName].findMany(findManyArgs)
const result = docsToDelete.map((data) => {
return transform({
config: this.payload.config,
data,
fields: collectionConfig.fields,
});
});
})
})
await this.db.delete(this.tables[tableName])
.where(where);
await this.db.delete(this.tables[tableName]).where(where)
return result;
};
return result
}

View File

@@ -1,51 +1,46 @@
import type { DeleteOne } from 'payload/database';
import type { PayloadRequest } from 'payload/types';
import type { DeleteOne } from 'payload/database'
import type { PayloadRequest } from 'payload/types'
import toSnakeCase from 'to-snake-case';
import toSnakeCase from 'to-snake-case'
import type { PostgresAdapter } from './types';
import type { PostgresAdapter } from './types'
import { buildFindManyArgs } from './find/buildFindManyArgs';
import buildQuery from './queries/buildQuery';
import { transform } from './transform/read';
import { buildFindManyArgs } from './find/buildFindManyArgs'
import buildQuery from './queries/buildQuery'
import { transform } from './transform/read'
export const deleteOne: DeleteOne = async function deleteOne(
this: PostgresAdapter,
{
collection,
req = {} as PayloadRequest,
where: incomingWhere,
},
{ collection, req = {} as PayloadRequest, where: incomingWhere },
) {
const collectionConfig = this.payload.collections[collection].config;
const tableName = toSnakeCase(collection);
const collectionConfig = this.payload.collections[collection].config
const tableName = toSnakeCase(collection)
const { where } = await buildQuery({
adapter: this,
fields: collectionConfig.fields,
tableName,
where: incomingWhere,
});
})
const findManyArgs = buildFindManyArgs({
adapter: this,
depth: 0,
fields: collectionConfig.fields,
tableName,
});
})
findManyArgs.where = where;
findManyArgs.where = where
const docToDelete = await this.db.query[tableName].findFirst(findManyArgs);
const docToDelete = await this.db.query[tableName].findFirst(findManyArgs)
const result = transform({
config: this.payload.config,
data: docToDelete,
fields: collectionConfig.fields,
});
})
await this.db.delete(this.tables[tableName])
.where(where);
await this.db.delete(this.tables[tableName]).where(where)
return result;
};
return result
}

View File

@@ -1,14 +1,14 @@
import type { SQL } from 'drizzle-orm'
import type { PgSelect } from 'drizzle-orm/pg-core'
import type { Find } from 'payload/database'
import type { PayloadRequest, SanitizedCollectionConfig, TypeWithID } from 'payload/types'
import { asc, desc, inArray, sql } from 'drizzle-orm'
import toSnakeCase from 'to-snake-case'
import type { GenericColumn, PostgresAdapter } from './types'
import type { ChainedMethods } from './find/chainMethods'
import type { PostgresAdapter } from './types'
import { buildFindManyArgs } from './find/buildFindManyArgs'
import { chainMethods } from './find/chainMethods'
import buildQuery from './queries/buildQuery'
import { transform } from './transform/read'
@@ -47,15 +47,11 @@ export const find: Find = async function find(
})
const db = this.sessions?.[req.transactionID] || this.db
const orderedIDMap: Record<number | string, number> = {}
let selectCount: PgSelect<string, { count: SQL<number> }, 'partial', Record<string, 'not-null'>>
const methodsToCall: {
args: unknown[]
method: string
}[] = []
const selectDistinctMethods: ChainedMethods = []
if (orderBy?.order && orderBy?.column) {
methodsToCall.push({
selectDistinctMethods.push({
args: [orderBy.order(orderBy.column)],
method: 'orderBy',
})
@@ -71,23 +67,24 @@ export const find: Find = async function find(
// only fetch IDs when a sort or where query is used that needs to be done on join tables, otherwise these can be done directly on the table in findMany
if (Object.keys(joins).length > 0) {
if (where) {
methodsToCall.push({ args: [where], method: 'where' })
selectDistinctMethods.push({ args: [where], method: 'where' })
}
Object.entries(joins).forEach(([joinTable, condition]) => {
if (joinTable) {
methodsToCall.push({
selectDistinctMethods.push({
args: [this.tables[joinTable], condition],
method: 'leftJoin',
})
}
})
methodsToCall.push({ args: [(page - 1) * limit], method: 'offset' })
methodsToCall.push({ args: [limit === 0 ? undefined : limit], method: 'limit' })
selectDistinctMethods.push({ args: [(page - 1) * limit], method: 'offset' })
selectDistinctMethods.push({ args: [limit === 0 ? undefined : limit], method: 'limit' })
selectDistinctResult = await methodsToCall.reduce((query, { args, method }) => {
return query[method](...args)
}, db.selectDistinct(selectFields).from(table))
selectDistinctResult = await chainMethods({
methods: selectDistinctMethods,
query: db.selectDistinct(selectFields).from(table),
})
if (selectDistinctResult.length === 0) {
return {
@@ -120,16 +117,22 @@ export const find: Find = async function find(
const findPromise = db.query[tableName].findMany(findManyArgs)
if (pagination !== false || selectDistinctResult?.length > limit) {
selectCount = db
.select({ count: sql<number>`count(*)` })
.from(table)
.where(where)
const selectCountMethods: ChainedMethods = []
Object.entries(joins).forEach(([joinTable, condition]) => {
if (joinTable) {
selectCount.leftJoin(this.tables[joinTable], condition)
selectCountMethods.push({
args: [this.tables[joinTable], condition],
method: 'leftJoin',
})
}
})
const countResult = await selectCount
const countResult = await chainMethods({
methods: selectCountMethods,
query: db
.select({ count: sql<number>`count(*)` })
.from(table)
.where(where),
})
totalDocs = Number(countResult[0].count)
totalPages = typeof limit === 'number' ? Math.ceil(totalDocs / limit) : 1
hasPrevPage = page > 1

View File

@@ -1,9 +1,9 @@
import type { DBQueryConfig } from 'drizzle-orm';
import type { ArrayField, Block, Field } from 'payload/types';
import type { DBQueryConfig } from 'drizzle-orm'
import type { ArrayField, Block, Field } from 'payload/types'
import type { PostgresAdapter } from '../types';
import type { PostgresAdapter } from '../types'
import { traverseFields } from './traverseFields';
import { traverseFields } from './traverseFields'
type BuildFindQueryArgs = {
adapter: PostgresAdapter
@@ -24,14 +24,14 @@ export const buildFindManyArgs = ({
}: BuildFindQueryArgs): Record<string, unknown> => {
const result: Result = {
with: {},
};
}
const _locales: Result = {
columns: {
_parentID: false,
id: false,
_parentID: false,
},
};
}
if (adapter.tables[`${tableName}_relationships`]) {
result.with._relationships = {
@@ -40,15 +40,15 @@ export const buildFindManyArgs = ({
parent: false,
},
orderBy: ({ order }, { asc: ASC }) => [ASC(order)],
};
}
}
if (adapter.tables[`${tableName}_locales`]) {
result.with._locales = _locales;
result.with._locales = _locales
}
const locatedBlocks: Block[] = [];
const locatedArrays: { [path: string]: ArrayField } = {};
const locatedBlocks: Block[] = []
const locatedArrays: { [path: string]: ArrayField } = {}
traverseFields({
_locales,
@@ -62,7 +62,7 @@ export const buildFindManyArgs = ({
path: '',
topLevelArgs: result,
topLevelTableName: tableName,
});
})
return result;
};
return result
}

View File

@@ -0,0 +1,17 @@
export type ChainedMethods = {
args: unknown[]
method: string
}[]
/**
* Call and returning methods that would normally be chained together but cannot be because of control logic
* @param methods
* @param query
*/
const chainMethods = ({ methods, query }): Promise<unknown> => {
return methods.reduce((query, { args, method }) => {
return query[method](...args)
}, query)
}
export { chainMethods }

View File

@@ -1,23 +1,23 @@
/* eslint-disable no-param-reassign */
import type { ArrayField, Block, Field } from 'payload/types';
import type { ArrayField, Block, Field } from 'payload/types'
import { fieldAffectsData } from 'payload/types';
import toSnakeCase from 'to-snake-case';
import { fieldAffectsData } from 'payload/types'
import toSnakeCase from 'to-snake-case'
import type { PostgresAdapter } from '../tyfpes';
import type { Result } from './buildFindManyArgs';
import type { PostgresAdapter } from '../types'
import type { Result } from './buildFindManyArgs'
type TraverseFieldArgs = {
_locales: Record<string, unknown>
adapter: PostgresAdapter
currentArgs: Record<string, unknown>,
currentArgs: Record<string, unknown>
currentTableName: string
depth?: number,
depth?: number
fields: Field[]
locatedArrays: { [path: string]: ArrayField },
locatedBlocks: Block[],
path: string,
topLevelArgs: Record<string, unknown>,
locatedArrays: { [path: string]: ArrayField }
locatedBlocks: Block[]
path: string
topLevelArgs: Record<string, unknown>
topLevelTableName: string
}
@@ -45,12 +45,12 @@ export const traverseFields = ({
},
orderBy: ({ _order }, { asc }) => [asc(_order)],
with: {},
};
}
const arrayTableName = `${currentTableName}_${toSnakeCase(field.name)}`;
const arrayTableName = `${currentTableName}_${toSnakeCase(field.name)}`
if (adapter.tables[`${arrayTableName}_locales`]) withArray.with._locales = _locales;
currentArgs.with[`${path}${field.name}`] = withArray;
if (adapter.tables[`${arrayTableName}_locales`]) withArray.with._locales = _locales
currentArgs.with[`${path}${field.name}`] = withArray
traverseFields({
_locales,
@@ -64,14 +64,14 @@ export const traverseFields = ({
path: '',
topLevelArgs,
topLevelTableName,
});
})
break;
break
}
case 'blocks':
field.blocks.forEach((block) => {
const blockKey = `_blocks_${block.slug}`;
const blockKey = `_blocks_${block.slug}`
if (!topLevelArgs[blockKey]) {
const withBlock: Result = {
@@ -80,10 +80,11 @@ export const traverseFields = ({
},
orderBy: ({ _order }, { asc }) => [asc(_order)],
with: {},
};
}
if (adapter.tables[`${topLevelTableName}_${toSnakeCase(block.slug)}_locales`]) withBlock.with._locales = _locales;
topLevelArgs.with[blockKey] = withBlock;
if (adapter.tables[`${topLevelTableName}_${toSnakeCase(block.slug)}_locales`])
withBlock.with._locales = _locales
topLevelArgs.with[blockKey] = withBlock
traverseFields({
_locales,
@@ -97,11 +98,11 @@ export const traverseFields = ({
path,
topLevelArgs,
topLevelTableName,
});
})
}
});
})
break;
break
case 'group':
traverseFields({
@@ -116,16 +117,16 @@ export const traverseFields = ({
path: `${path}${field.name}_`,
topLevelArgs,
topLevelTableName,
});
})
break;
break
default: {
break;
break
}
}
}
});
})
return topLevelArgs;
};
return topLevelArgs
}

View File

@@ -1,20 +1,20 @@
import type { FindGlobal } from 'payload/database';
import type { FindGlobal } from 'payload/database'
import toSnakeCase from 'to-snake-case';
import toSnakeCase from 'to-snake-case'
import type { PostgresAdapter } from './types';
import type { PostgresAdapter } from './types'
import { buildFindManyArgs } from './find/buildFindManyArgs';
import buildQuery from './queries/buildQuery';
import { transform } from './transform/read';
import { buildFindManyArgs } from './find/buildFindManyArgs'
import buildQuery from './queries/buildQuery'
import { transform } from './transform/read'
export const findGlobal: FindGlobal = async function findGlobal(
this: PostgresAdapter,
{ locale, req, slug, where },
) {
const db = req.transactionID ? this.sessions[req.transactionID] : this.db;
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug);
const tableName = toSnakeCase(slug);
const db = req.transactionID ? this.sessions[req.transactionID] : this.db
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug)
const tableName = toSnakeCase(slug)
const query = await buildQuery({
adapter: this,
@@ -22,28 +22,28 @@ export const findGlobal: FindGlobal = async function findGlobal(
locale,
tableName,
where,
});
})
const findManyArgs = buildFindManyArgs({
adapter: this,
depth: 0,
fields: globalConfig.fields,
tableName,
});
})
findManyArgs.where = query;
findManyArgs.where = query
const doc = await db.query[tableName].findFirst(findManyArgs);
const doc = await db.query[tableName].findFirst(findManyArgs)
if (doc) {
const result = transform({
config: this.payload.config,
data: doc,
fields: globalConfig.fields,
});
})
return result;
return result
}
return null;
};
return null
}

View File

@@ -1,11 +1,11 @@
import type { FindOne } from 'payload/database';
import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types';
import type { FindOne } from 'payload/database'
import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types'
import toSnakeCase from 'to-snake-case';
import toSnakeCase from 'to-snake-case'
import { buildFindManyArgs } from './find/buildFindManyArgs';
import buildQuery from './queries/buildQuery';
import { transform } from './transform/read';
import { buildFindManyArgs } from './find/buildFindManyArgs'
import buildQuery from './queries/buildQuery'
import { transform } from './transform/read'
export const findOne: FindOne = async function findOne({
collection,
@@ -13,9 +13,9 @@ export const findOne: FindOne = async function findOne({
req = {} as PayloadRequest,
where: incomingWhere,
}) {
const db = req.transactionID ? this.sessions[req.transactionID] : this.db;
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config;
const tableName = toSnakeCase(collection);
const db = req.transactionID ? this.sessions[req.transactionID] : this.db
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
const tableName = toSnakeCase(collection)
const { where } = await buildQuery({
adapter: this,
@@ -23,22 +23,22 @@ export const findOne: FindOne = async function findOne({
locale,
tableName,
where: incomingWhere,
});
})
const findManyArgs = buildFindManyArgs({
adapter: this,
depth: 0,
fields: collectionConfig.fields,
tableName,
});
})
findManyArgs.where = where;
findManyArgs.where = where
const doc = await db.query[tableName].findFirst(findManyArgs);
const doc = await db.query[tableName].findFirst(findManyArgs)
return transform({
config: this.payload.config,
data: doc,
fields: collectionConfig.fields,
});
};
})
}

View File

@@ -1,14 +1,14 @@
/* eslint-disable no-param-reassign */
import type { Init } from 'payload/database';
import type { SanitizedCollectionConfig } from 'payload/types';
import type { Init } from 'payload/database'
import type { SanitizedCollectionConfig } from 'payload/types'
import { pgEnum } from 'drizzle-orm/pg-core';
import { buildVersionCollectionFields, buildVersionGlobalFields } from 'payload/versions';
import toSnakeCase from 'to-snake-case';
import { pgEnum } from 'drizzle-orm/pg-core'
import { buildVersionCollectionFields, buildVersionGlobalFields } from 'payload/versions'
import toSnakeCase from 'to-snake-case'
import type { PostgresAdapter } from './types';
import type { PostgresAdapter } from './types'
import { buildTable } from './schema/build';
import { buildTable } from './schema/build'
export const init: Init = async function init(this: PostgresAdapter) {
if (this.payload.config.localization) {
@@ -16,12 +16,14 @@ export const init: Init = async function init(this: PostgresAdapter) {
'_locales',
// TODO: types out of sync with core, monorepo please
// this.payload.config.localization.localeCodes,
(this.payload.config.localization.locales as unknown as { code: string }[]).map(({ code }) => code) as [string, ...string[]],
);
(this.payload.config.localization.locales as unknown as { code: string }[]).map(
({ code }) => code,
) as [string, ...string[]],
)
}
this.payload.config.collections.forEach((collection: SanitizedCollectionConfig) => {
const tableName = toSnakeCase(collection.slug);
const tableName = toSnakeCase(collection.slug)
buildTable({
adapter: this,
@@ -29,11 +31,11 @@ export const init: Init = async function init(this: PostgresAdapter) {
fields: collection.fields,
tableName,
timestamps: collection.timestamps,
});
})
if (collection.versions) {
const versionsTableName = `_${tableName}_versions`;
const versionFields = buildVersionCollectionFields(collection);
const versionsTableName = `_${tableName}_versions`
const versionFields = buildVersionCollectionFields(collection)
buildTable({
adapter: this,
@@ -41,12 +43,12 @@ export const init: Init = async function init(this: PostgresAdapter) {
fields: versionFields,
tableName: versionsTableName,
timestamps: true,
});
})
}
});
})
this.payload.config.globals.forEach((global) => {
const tableName = toSnakeCase(global.slug);
const tableName = toSnakeCase(global.slug)
buildTable({
adapter: this,
@@ -54,11 +56,11 @@ export const init: Init = async function init(this: PostgresAdapter) {
fields: global.fields,
tableName,
timestamps: false,
});
})
if (global.versions) {
const versionsTableName = `_${tableName}_versions`;
const versionFields = buildVersionGlobalFields(global);
const versionsTableName = `_${tableName}_versions`
const versionFields = buildVersionGlobalFields(global)
buildTable({
adapter: this,
@@ -66,7 +68,7 @@ export const init: Init = async function init(this: PostgresAdapter) {
fields: versionFields,
tableName: versionsTableName,
timestamps: true,
});
})
}
});
};
})
}

View File

@@ -1,10 +1,10 @@
import type { SQL } from 'drizzle-orm';
import type { Field, Where } from 'payload/types';
import type { SQL } from 'drizzle-orm'
import type { Field, Where } from 'payload/types'
import type { GenericColumn, PostgresAdapter } from '../types';
import type { BuildQueryJoins } from './buildQuery';
import type { GenericColumn, PostgresAdapter } from '../types'
import type { BuildQueryJoins } from './buildQuery'
import { parseParams } from './parseParams';
import { parseParams } from './parseParams'
export async function buildAndOrConditions({
adapter,
@@ -16,16 +16,16 @@ export async function buildAndOrConditions({
where,
}: {
adapter: PostgresAdapter
collectionSlug?: string,
fields: Field[],
globalSlug?: string,
joins: BuildQueryJoins,
locale?: string,
collectionSlug?: string
fields: Field[]
globalSlug?: string
joins: BuildQueryJoins
locale?: string
selectFields: Record<string, GenericColumn>
tableName: string,
where: Where[],
tableName: string
where: Where[]
}): Promise<SQL[]> {
const completedConditions = [];
const completedConditions = []
// Loop over all AND / OR operations and add them to the AND / OR query param
// Operations should come through as an array
// eslint-disable-next-line no-restricted-syntax
@@ -41,11 +41,11 @@ export async function buildAndOrConditions({
selectFields,
tableName,
where: condition,
});
})
if (result && Object.keys(result).length > 0) {
completedConditions.push(result);
completedConditions.push(result)
}
}
}
return completedConditions;
return completedConditions
}

View File

@@ -62,7 +62,7 @@ const buildQuery = async function buildQuery({
fields,
joins,
locale,
pathSegments: sortPath.split('.'),
pathSegments: sortPath.replace(/__/g, '.').split('.'),
selectFields,
tableName,
})

View File

@@ -1,15 +1,15 @@
/* eslint-disable no-param-reassign */
import type { SQL } from 'drizzle-orm';
import type { Field, FieldAffectingData, TabAsField } from 'payload/types';
import type { SQL } from 'drizzle-orm'
import type { Field, FieldAffectingData, TabAsField } from 'payload/types'
import { and, eq, sql } from 'drizzle-orm';
import { APIError } from 'payload/errors';
import { fieldAffectsData, tabHasName } from 'payload/types';
import { flattenTopLevelFields } from 'payload/utilities';
import toSnakeCase from 'to-snake-case';
import { and, eq, sql } from 'drizzle-orm'
import { APIError } from 'payload/errors'
import { fieldAffectsData, tabHasName } from 'payload/types'
import { flattenTopLevelFields } from 'payload/utilities'
import toSnakeCase from 'to-snake-case'
import type { GenericColumn, GenericTable, PostgresAdapter } from '../types';
import type { BuildQueryJoins } from './buildQuery';
import type { GenericColumn, GenericTable, PostgresAdapter } from '../types'
import type { BuildQueryJoins } from './buildQuery'
type Constraint = {
columnName: string
@@ -26,7 +26,7 @@ type TableColumn = {
}
type Args = {
adapter: PostgresAdapter,
adapter: PostgresAdapter
collectionPath: string
columnPrefix?: string
constraints?: Constraint[]
@@ -54,13 +54,14 @@ export const getTableColumnFromPath = ({
selectFields,
tableName,
}: Args): TableColumn => {
const fieldPath = pathSegments[0];
const field = flattenTopLevelFields(fields as Field[])
.find((fieldToFind) => fieldAffectsData(fieldToFind) && fieldToFind.name === fieldPath) as Field | TabAsField;
let newTableName = tableName;
const fieldPath = pathSegments[0]
const field = flattenTopLevelFields(fields as Field[]).find(
(fieldToFind) => fieldAffectsData(fieldToFind) && fieldToFind.name === fieldPath,
) as Field | TabAsField
let newTableName = tableName
if (!field && fieldPath === 'id') {
selectFields.id = adapter.tables[newTableName].id;
selectFields.id = adapter.tables[newTableName].id
return {
columnName: 'id',
constraints,
@@ -69,7 +70,7 @@ export const getTableColumnFromPath = ({
type: 'number',
},
table: adapter.tables[newTableName],
};
}
}
if (field) {
@@ -89,7 +90,7 @@ export const getTableColumnFromPath = ({
pathSegments: pathSegments.slice(1),
selectFields,
tableName: newTableName,
});
})
}
case 'tab': {
if (tabHasName(field)) {
@@ -98,38 +99,41 @@ export const getTableColumnFromPath = ({
collectionPath,
columnPrefix: `${columnPrefix}${field.name}_`,
constraints,
fields: field.fields ,
fields: field.fields,
joins,
locale,
pathSegments: pathSegments.slice(1),
selectFields,
tableName: newTableName,
});
})
}
return getTableColumnFromPath({
adapter,
collectionPath,
columnPrefix,
constraints,
fields: field.fields ,
fields: field.fields,
joins,
locale,
pathSegments: pathSegments.slice(1),
selectFields,
tableName: newTableName,
});
})
}
case 'group': {
if (locale && field.localized && adapter.payload.config.localization) {
newTableName = `${tableName}_locales`;
joins[tableName] = eq(adapter.tables[tableName].id, adapter.tables[newTableName]._parentID);
newTableName = `${tableName}_locales`
joins[tableName] = eq(
adapter.tables[tableName].id,
adapter.tables[newTableName]._parentID,
)
if (locale !== 'all') {
constraints.push({
columnName: '_locale',
table: adapter.tables[newTableName],
value: locale,
});
})
}
}
return getTableColumnFromPath({
@@ -137,31 +141,34 @@ export const getTableColumnFromPath = ({
collectionPath,
columnPrefix: `${columnPrefix}${field.name}_`,
constraints,
fields: field.fields ,
fields: field.fields,
joins,
locale,
pathSegments: pathSegments.slice(1),
selectFields,
tableName: newTableName,
});
})
}
case 'array': {
newTableName = `${tableName}_${toSnakeCase(field.name)}`;
newTableName = `${tableName}_${toSnakeCase(field.name)}`
if (locale && field.localized && adapter.payload.config.localization) {
joins[newTableName] = and(
eq(adapter.tables[tableName].id, adapter.tables[newTableName]._parentID),
eq(adapter.tables[newTableName]._locale, locale),
);
)
if (locale !== 'all') {
constraints.push({
columnName: '_locale',
table: adapter.tables[newTableName],
value: locale,
});
})
}
} else {
joins[newTableName] = eq(adapter.tables[tableName].id, adapter.tables[newTableName]._parentID);
joins[newTableName] = eq(
adapter.tables[tableName].id,
adapter.tables[newTableName]._parentID,
)
}
return getTableColumnFromPath({
adapter,
@@ -173,17 +180,17 @@ export const getTableColumnFromPath = ({
pathSegments: pathSegments.slice(1),
selectFields,
tableName: newTableName,
});
})
}
case 'blocks': {
let blockTableColumn: TableColumn;
let newTableName: string;
let blockTableColumn: TableColumn
let newTableName: string
const hasBlockField = field.blocks.some((block) => {
newTableName = `${tableName}_${toSnakeCase(block.slug)}`;
let result;
const blockConstraints = [];
const blockSelectFields = {};
newTableName = `${tableName}_${toSnakeCase(block.slug)}`
let result
const blockConstraints = []
const blockSelectFields = {}
try {
result = getTableColumnFromPath({
adapter,
@@ -195,33 +202,36 @@ export const getTableColumnFromPath = ({
pathSegments: pathSegments.slice(1),
selectFields: blockSelectFields,
tableName: newTableName,
});
})
} catch (error) {
// this is fine, not every block will have the field
}
if (!result) {
return;
return
}
blockTableColumn = result;
constraints = constraints.concat(blockConstraints);
selectFields = {...selectFields, ...blockSelectFields};
blockTableColumn = result
constraints = constraints.concat(blockConstraints)
selectFields = { ...selectFields, ...blockSelectFields }
if (field.localized && adapter.payload.config.localization) {
joins[newTableName] = and(
eq(adapter.tables[tableName].id, adapter.tables[newTableName]._parentID),
eq(adapter.tables[newTableName]._locale, locale),
);
)
if (locale) {
constraints.push({
columnName: '_locale',
table: adapter.tables[newTableName],
value: locale,
});
})
}
} else {
joins[newTableName] = eq(adapter.tables[tableName].id, adapter.tables[newTableName]._parentID);
joins[newTableName] = eq(
adapter.tables[tableName].id,
adapter.tables[newTableName]._parentID,
)
}
return result;
});
return result
})
if (hasBlockField) {
return {
columnName: blockTableColumn.columnName,
@@ -229,49 +239,57 @@ export const getTableColumnFromPath = ({
field: blockTableColumn.field,
rawColumn: blockTableColumn.rawColumn,
table: adapter.tables[newTableName],
};
}
break;
}
break
}
case 'relationship':
case 'upload': {
let relationshipFields;
const relationTableName = `${tableName}_relationships`;
const newCollectionPath = pathSegments.slice(1).join('.');
let relationshipFields
const relationTableName = `${tableName}_relationships`
const newCollectionPath = pathSegments.slice(1).join('.')
// Join in the relationships table
joins[relationTableName] = eq(adapter.tables[tableName].id, adapter.tables[relationTableName].parent);
selectFields[`${relationTableName}.path`] = adapter.tables[relationTableName].path;
joins[relationTableName] = eq(
adapter.tables[tableName].id,
adapter.tables[relationTableName].parent,
)
selectFields[`${relationTableName}.path`] = adapter.tables[relationTableName].path
constraints.push({
columnName: 'path',
table: adapter.tables[relationTableName],
value: field.name,
});
})
if (typeof field.relationTo === 'string') {
newTableName = `${toSnakeCase(field.relationTo)}`;
newTableName = `${toSnakeCase(field.relationTo)}`
// parent to relationship join table
relationshipFields = adapter.payload.collections[field.relationTo].config.fields;
joins[newTableName] = eq(adapter.tables[newTableName].id, adapter.tables[`${tableName}_relationships`][`${field.relationTo}ID`]);
relationshipFields = adapter.payload.collections[field.relationTo].config.fields
joins[newTableName] = eq(
adapter.tables[newTableName].id,
adapter.tables[`${tableName}_relationships`][`${field.relationTo}ID`],
)
if (newCollectionPath === '') {
return {
columnName: `${field.relationTo}ID`,
constraints,
field,
table: adapter.tables[relationTableName],
};
}
}
} else if (newCollectionPath === 'value') {
const tableColumnsNames = field.relationTo.map((relationTo) => `"${relationTableName}"."${toSnakeCase(relationTo)}_id"`);
const tableColumnsNames = field.relationTo.map(
(relationTo) => `"${relationTableName}"."${toSnakeCase(relationTo)}_id"`,
)
return {
constraints,
field,
rawColumn: sql.raw(`COALESCE(${tableColumnsNames.join(', ')})`),
table: adapter.tables[relationTableName],
};
}
} else {
throw new APIError('Not supported');
throw new APIError('Not supported')
}
return getTableColumnFromPath({
@@ -284,7 +302,7 @@ export const getTableColumnFromPath = ({
pathSegments: pathSegments.slice(1),
selectFields,
tableName: newTableName,
});
})
}
default: {
@@ -302,28 +320,31 @@ export const getTableColumnFromPath = ({
// case 'point':
if (fieldAffectsData(field)) {
if (field.localized && adapter.payload.config.localization) {
newTableName = `${tableName}_locales`;
joins[newTableName] = eq(adapter.tables[tableName].id, adapter.tables[newTableName]._parentID);
newTableName = `${tableName}_locales`
joins[newTableName] = eq(
adapter.tables[tableName].id,
adapter.tables[newTableName]._parentID,
)
if (locale !== 'all') {
constraints.push({
columnName: '_locale',
table: adapter.tables[newTableName],
value: locale,
});
})
}
}
selectFields[`${newTableName}.${field.name}`] = adapter.tables[newTableName][field.name];
selectFields[`${newTableName}.${field.name}`] = adapter.tables[newTableName][field.name]
return {
columnName: `${columnPrefix}${field.name}`,
constraints,
field,
table: adapter.tables[newTableName],
};
}
}
}
}
}
throw new APIError(`Cannot find field for path at ${fieldPath}`);
};
throw new APIError(`Cannot find field for path at ${fieldPath}`)
}

View File

@@ -83,7 +83,7 @@ export async function parseParams({
fields,
joins,
locale,
pathSegments: relationOrPath.split('.'),
pathSegments: relationOrPath.replace(/__/g, '.').split('.'),
selectFields,
tableName,
})
@@ -97,9 +97,6 @@ export async function parseParams({
queryConstraints.forEach(({ columnName: col, table: constraintTable, value }) => {
constraints.push(operatorMap.equals(constraintTable[col], value))
})
if (!operatorMap[queryOperator]) {
console.log('found it')
}
constraints.push(
operatorMap[queryOperator](rawColumn || table[columnName], queryValue),
)

View File

@@ -1,13 +1,13 @@
import type { QueryDrafts } from 'payload/database';
import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types';
import type { QueryDrafts } from 'payload/database'
import type { PayloadRequest, SanitizedCollectionConfig } from 'payload/types'
import { sql } from 'drizzle-orm';
import { buildVersionCollectionFields } from 'payload/versions';
import toSnakeCase from 'to-snake-case';
import { sql } from 'drizzle-orm'
import { buildVersionCollectionFields } from 'payload/versions'
import toSnakeCase from 'to-snake-case'
import { buildFindManyArgs } from './find/buildFindManyArgs';
import buildQuery from './queries/buildQuery';
import { transform } from './transform/read';
import { buildFindManyArgs } from './find/buildFindManyArgs'
import buildQuery from './queries/buildQuery'
import { transform } from './transform/read'
export const queryDrafts: QueryDrafts = async function queryDrafts({
collection,
@@ -19,20 +19,21 @@ export const queryDrafts: QueryDrafts = async function queryDrafts({
sort: sortArg,
where: whereArg,
}) {
const db = req.transactionID ? this.sessions[req.transactionID] : this.db;
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config;
const tableName = toSnakeCase(collection);
const versionsTableName = `_${tableName}_versions`;
const table = this.tables[versionsTableName];
const limit = typeof limitArg === 'number' ? limitArg : collectionConfig.admin.pagination.defaultLimit;
const db = req.transactionID ? this.sessions[req.transactionID] : this.db
const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config
const tableName = toSnakeCase(collection)
const versionsTableName = `_${tableName}_versions`
const table = this.tables[versionsTableName]
const limit =
typeof limitArg === 'number' ? limitArg : collectionConfig.admin.pagination.defaultLimit
// TODO: use sort
const sort = typeof sortArg === 'string' ? sortArg : collectionConfig.defaultSort;
const sort = typeof sortArg === 'string' ? sortArg : collectionConfig.defaultSort
let totalDocs;
let totalPages;
let hasPrevPage;
let hasNextPage;
let pagingCounter;
let totalDocs
let totalPages
let hasPrevPage
let hasNextPage
let pagingCounter
const { where } = await buildQuery({
adapter: this,
@@ -40,16 +41,19 @@ export const queryDrafts: QueryDrafts = async function queryDrafts({
locale,
sort,
tableName: versionsTableName,
where: whereArg
});
where: whereArg,
})
if (pagination !== false) {
const countResult = await db.select({ count: sql<number>`count(*)` }).from(table).where(where);
totalDocs = Number(countResult[0].count);
totalPages = Math.ceil(totalDocs / limit);
hasPrevPage = page > 1;
hasNextPage = totalPages > page;
pagingCounter = ((page - 1) * limit) + 1;
const countResult = await db
.select({ count: sql<number>`count(*)` })
.from(table)
.where(where)
totalDocs = Number(countResult[0].count)
totalPages = Math.ceil(totalDocs / limit)
hasPrevPage = page > 1
hasNextPage = totalPages > page
pagingCounter = (page - 1) * limit + 1
}
const findManyArgs = buildFindManyArgs({
@@ -57,21 +61,21 @@ export const queryDrafts: QueryDrafts = async function queryDrafts({
depth: 0,
fields: collectionConfig.fields,
tableName,
});
})
findManyArgs.limit = limit === 0 ? undefined : limit;
findManyArgs.offset = (page - 1) * limit;
findManyArgs.where = where;
findManyArgs.limit = limit === 0 ? undefined : limit
findManyArgs.offset = (page - 1) * limit
findManyArgs.where = where
const rawDocs = await db.query[tableName].findMany(findManyArgs);
const rawDocs = await db.query[tableName].findMany(findManyArgs)
const docs = rawDocs.map((data) => {
return transform({
config: this.payload.config,
data,
fields: collectionConfig.fields,
});
});
})
})
return {
docs, // : T[]
@@ -84,5 +88,5 @@ export const queryDrafts: QueryDrafts = async function queryDrafts({
prevPage: hasPrevPage ? page - 1 : null, // ?: number | null | undefined
totalDocs, // : number
totalPages, // : number
};
};
}
}

View File

@@ -4,40 +4,40 @@
// type PushDiff = (schema: DrizzleSchemaExports) => Promise<{ warnings: string[], apply: () => Promise<void> }>
// drizzle-kit@utils
import { generateDrizzleJson, generateMigration, pushSchema } from 'drizzle-kit/utils';
import { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';
import { generateDrizzleJson, generateMigration, pushSchema } from 'drizzle-kit/utils'
import { drizzle } from 'drizzle-orm/node-postgres'
import { Pool } from 'pg'
async function generateUsage() {
const schema = await import('./data/users');
const schemaAfter = await import('./data/users-after');
// @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue
const schema = await import('./data/users')
// @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue
const schemaAfter = await import('./data/users-after')
const drizzleJsonBefore = generateDrizzleJson(schema);
const drizzleJsonAfter = generateDrizzleJson(schemaAfter);
const drizzleJsonBefore = generateDrizzleJson(schema)
const drizzleJsonAfter = generateDrizzleJson(schemaAfter)
const sqlStatements = await generateMigration(drizzleJsonBefore, drizzleJsonAfter);
const sqlStatements = await generateMigration(drizzleJsonBefore, drizzleJsonAfter)
console.log(sqlStatements);
console.log(sqlStatements)
}
async function pushUsage() {
const schemaAfter = await import('./data/users-after');
// @ts-expect-error Just TypeScript being broken // TODO: Open TypeScript issue
const schemaAfter = await import('./data/users-after')
const db = drizzle(
new Pool({ connectionString: '' }),
);
const db = drizzle(new Pool({ connectionString: '' }))
const response = await pushSchema(schemaAfter, db);
const response = await pushSchema(schemaAfter, db)
console.log('\n');
console.log('hasDataLoss: ', response.hasDataLoss);
console.log('warnings: ', response.warnings);
console.log('statements: ', response.statementsToExecute);
console.log('\n')
console.log('hasDataLoss: ', response.hasDataLoss)
console.log('warnings: ', response.warnings)
console.log('statements: ', response.statementsToExecute)
await response.apply();
await response.apply()
process.exit(0);
process.exit(0)
}

View File

@@ -1,21 +1,30 @@
/* eslint-disable no-param-reassign */
import type { Relation } from 'drizzle-orm';
import type { IndexBuilder, PgColumnBuilder, UniqueConstraintBuilder } from 'drizzle-orm/pg-core';
import type { Field } from 'payload/types';
import type { Relation } from 'drizzle-orm'
import type { IndexBuilder, PgColumnBuilder, UniqueConstraintBuilder } from 'drizzle-orm/pg-core'
import type { Field } from 'payload/types'
import { relations } from 'drizzle-orm';
import { index, integer, numeric, pgTable, serial, timestamp, unique, varchar, } from 'drizzle-orm/pg-core';
import { fieldAffectsData } from 'payload/types';
import toSnakeCase from 'to-snake-case';
import { relations } from 'drizzle-orm'
import {
index,
integer,
numeric,
pgTable,
serial,
timestamp,
unique,
varchar,
} from 'drizzle-orm/pg-core'
import { fieldAffectsData } from 'payload/types'
import toSnakeCase from 'to-snake-case'
import type { GenericColumns, GenericTable, PostgresAdapter } from '../types';
import type { GenericColumns, GenericTable, PostgresAdapter } from '../types'
import { parentIDColumnMap } from './parentIDColumnMap';
import { traverseFields } from './traverseFields';
import { parentIDColumnMap } from './parentIDColumnMap'
import { traverseFields } from './traverseFields'
type Args = {
adapter: PostgresAdapter
baseColumns?: Record<string, PgColumnBuilder>,
baseColumns?: Record<string, PgColumnBuilder>
baseExtraConfig?: Record<string, (cols: GenericColumns) => IndexBuilder | UniqueConstraintBuilder>
buildRelationships?: boolean
fields: Field[]
@@ -36,38 +45,38 @@ export const buildTable = ({
tableName,
timestamps,
}: Args): Result => {
const columns: Record<string, PgColumnBuilder> = baseColumns;
const indexes: Record<string, (cols: GenericColumns) => IndexBuilder> = {};
const columns: Record<string, PgColumnBuilder> = baseColumns
const indexes: Record<string, (cols: GenericColumns) => IndexBuilder> = {}
let hasLocalizedField = false;
let hasLocalizedRelationshipField = false;
const localesColumns: Record<string, PgColumnBuilder> = {};
const localesIndexes: Record<string, (cols: GenericColumns) => IndexBuilder> = {};
let localesTable: GenericTable;
let hasLocalizedField = false
let hasLocalizedRelationshipField = false
const localesColumns: Record<string, PgColumnBuilder> = {}
const localesIndexes: Record<string, (cols: GenericColumns) => IndexBuilder> = {}
let localesTable: GenericTable
const relationships: Set<string> = new Set();
let relationshipsTable: GenericTable;
const relationships: Set<string> = new Set()
let relationshipsTable: GenericTable
const arrayBlockRelations: Map<string, string> = new Map();
const arrayBlockRelations: Map<string, string> = new Map()
const idField = fields.find((field) => fieldAffectsData(field) && field.name === 'id');
let idColType = 'integer';
const idField = fields.find((field) => fieldAffectsData(field) && field.name === 'id')
let idColType = 'integer'
if (idField) {
if (idField.type === 'number') {
idColType = 'numeric';
columns.id = numeric('id').primaryKey();
idColType = 'numeric'
columns.id = numeric('id').primaryKey()
}
if (idField.type === 'text') {
idColType = 'varchar';
columns.id = varchar('id').primaryKey();
idColType = 'varchar'
columns.id = varchar('id').primaryKey()
}
} else {
columns.id = serial('id').primaryKey();
columns.id = serial('id').primaryKey()
}
({ hasLocalizedField, hasLocalizedRelationshipField } = traverseFields({
;({ hasLocalizedField, hasLocalizedRelationshipField } = traverseFields({
adapter,
arrayBlockRelations,
buildRelationships,
@@ -79,52 +88,57 @@ export const buildTable = ({
newTableName: tableName,
parentTableName: tableName,
relationships,
}));
}))
if (timestamps) {
columns.createdAt = timestamp('created_at').defaultNow().notNull();
columns.updatedAt = timestamp('updated_at').defaultNow().notNull();
columns.createdAt = timestamp('created_at').defaultNow().notNull()
columns.updatedAt = timestamp('updated_at').defaultNow().notNull()
}
const table = pgTable(tableName, columns, (cols) => {
const extraConfig = Object.entries(baseExtraConfig).reduce((config, [key, func]) => {
config[key] = func(cols);
return config;
}, {});
config[key] = func(cols)
return config
}, {})
return Object.entries(indexes).reduce((acc, [colName, func]) => {
acc[colName] = func(cols);
return acc;
}, extraConfig);
});
acc[colName] = func(cols)
return acc
}, extraConfig)
})
adapter.tables[tableName] = table;
adapter.tables[tableName] = table
if (hasLocalizedField) {
const localeTableName = `${tableName}_locales`;
localesColumns.id = serial('id').primaryKey();
localesColumns._locale = adapter.enums._locales('_locale').notNull();
localesColumns._parentID = parentIDColumnMap[idColType]('_parent_id').references(() => table.id, { onDelete: 'cascade' }).notNull();
const localeTableName = `${tableName}_locales`
localesColumns.id = serial('id').primaryKey()
localesColumns._locale = adapter.enums._locales('_locale').notNull()
localesColumns._parentID = parentIDColumnMap[idColType]('_parent_id')
.references(() => table.id, { onDelete: 'cascade' })
.notNull()
localesTable = pgTable(localeTableName, localesColumns, (cols) => {
return Object.entries(localesIndexes).reduce((acc, [colName, func]) => {
acc[colName] = func(cols);
return acc;
}, {
return Object.entries(localesIndexes).reduce(
(acc, [colName, func]) => {
acc[colName] = func(cols)
return acc
},
{
_localeParent: unique().on(cols._locale, cols._parentID),
});
});
},
)
})
adapter.tables[localeTableName] = localesTable;
adapter.tables[localeTableName] = localesTable
const localesTableRelations = relations(localesTable, ({ one }) => ({
_parentID: one(table, {
fields: [localesTable._parentID],
references: [table.id],
}),
}));
}))
adapter.relations[`relations_${localeTableName}`] = localesTableRelations;
adapter.relations[`relations_${localeTableName}`] = localesTableRelations
}
if (buildRelationships) {
@@ -132,40 +146,51 @@ export const buildTable = ({
const relationshipColumns: Record<string, PgColumnBuilder> = {
id: serial('id').primaryKey(),
order: integer('order'),
parent: parentIDColumnMap[idColType]('parent_id').references(() => table.id, { onDelete: 'cascade' }).notNull(),
parent: parentIDColumnMap[idColType]('parent_id')
.references(() => table.id, { onDelete: 'cascade' })
.notNull(),
path: varchar('path').notNull(),
};
}
if (hasLocalizedRelationshipField) {
relationshipColumns.locale = adapter.enums._locales('locale');
relationshipColumns.locale = adapter.enums._locales('locale')
}
relationships.forEach((relationTo) => {
const formattedRelationTo = toSnakeCase(relationTo);
let colType = 'integer';
const relatedCollectionCustomID = adapter.payload.collections[relationTo].config.fields.find((field) => fieldAffectsData(field) && field.name === 'id');
if (relatedCollectionCustomID?.type === 'number') colType = 'numeric';
if (relatedCollectionCustomID?.type === 'text') colType = 'varchar';
const formattedRelationTo = toSnakeCase(relationTo)
let colType = 'integer'
const relatedCollectionCustomID = adapter.payload.collections[
relationTo
].config.fields.find((field) => fieldAffectsData(field) && field.name === 'id')
if (relatedCollectionCustomID?.type === 'number') colType = 'numeric'
if (relatedCollectionCustomID?.type === 'text') colType = 'varchar'
relationshipColumns[`${relationTo}ID`] = parentIDColumnMap[colType](`${formattedRelationTo}_id`).references(() => adapter.tables[formattedRelationTo].id);
});
relationshipColumns[`${relationTo}ID`] = parentIDColumnMap[colType](
`${formattedRelationTo}_id`,
).references(() => adapter.tables[formattedRelationTo].id)
})
const relationshipsTableName = `${tableName}_relationships`;
const relationshipsTableName = `${tableName}_relationships`
relationshipsTable = pgTable(relationshipsTableName, relationshipColumns, (cols) => {
const result: Record<string, unknown> = {};
const result: Record<string, unknown> = {}
if (hasLocalizedRelationshipField) {
result.localeIdx = index('locale_idx').on(cols.locale);
result.parentPathOrderLocale = unique().on(cols.parent, cols.path, cols.order, cols.locale);
result.localeIdx = index('locale_idx').on(cols.locale)
result.parentPathOrderLocale = unique().on(
cols.parent,
cols.path,
cols.order,
cols.locale,
)
} else {
result.parentPathOrder = unique().on(cols.parent, cols.path, cols.order);
result.parentPathOrder = unique().on(cols.parent, cols.path, cols.order)
}
return result;
});
return result
})
adapter.tables[relationshipsTableName] = relationshipsTable;
adapter.tables[relationshipsTableName] = relationshipsTable
const relationshipsTableRelations = relations(relationshipsTable, ({ one }) => {
const result: Record<string, Relation<string>> = {
@@ -174,45 +199,45 @@ export const buildTable = ({
references: [table.id],
relationName: '_relationships',
}),
};
}
relationships.forEach((relationTo) => {
const relatedTableName = toSnakeCase(relationTo);
const idColumnName = `${relationTo}ID`;
const relatedTableName = toSnakeCase(relationTo)
const idColumnName = `${relationTo}ID`
result[idColumnName] = one(adapter.tables[relatedTableName], {
fields: [relationshipsTable[idColumnName]],
references: [adapter.tables[relatedTableName].id],
});
});
})
})
return result;
});
return result
})
adapter.relations[`relations_${relationshipsTableName}`] = relationshipsTableRelations;
adapter.relations[`relations_${relationshipsTableName}`] = relationshipsTableRelations
}
}
const tableRelations = relations(table, ({ many }) => {
const result: Record<string, Relation<string>> = {};
const result: Record<string, Relation<string>> = {}
arrayBlockRelations.forEach((val, key) => {
result[key] = many(adapter.tables[val]);
});
result[key] = many(adapter.tables[val])
})
if (hasLocalizedField) {
result._locales = many(localesTable);
result._locales = many(localesTable)
}
if (relationships.size && relationshipsTable) {
result._relationships = many(relationshipsTable, {
relationName: '_relationships',
});
})
}
return result;
});
return result
})
adapter.relations[`relations_${tableName}`] = tableRelations;
adapter.relations[`relations_${tableName}`] = tableRelations
return { arrayBlockRelations };
};
return { arrayBlockRelations }
}

View File

@@ -1,7 +1,7 @@
/* eslint-disable no-param-reassign */
import { index, uniqueIndex } from 'drizzle-orm/pg-core';
import { index, uniqueIndex } from 'drizzle-orm/pg-core'
import type { GenericColumn } from '../types';
import type { GenericColumn } from '../types'
type CreateIndexArgs = {
columnName: string
@@ -9,9 +9,9 @@ type CreateIndexArgs = {
unique?: boolean
}
export const createIndex = ({ columnName, name, unique }: CreateIndexArgs) => {
export const createIndex = ({ name, columnName, unique }: CreateIndexArgs) => {
return (table: { [x: string]: GenericColumn }) => {
if (unique) return uniqueIndex(`${columnName}_idx`).on(table[name]);
return index(`${columnName}_idx`).on(table[name]);
};
};
if (unique) return uniqueIndex(`${columnName}_idx`).on(table[name])
return index(`${columnName}_idx`).on(table[name])
}
}

View File

@@ -1,7 +1,7 @@
import { integer, numeric, varchar } from 'drizzle-orm/pg-core';
import { integer, numeric, varchar } from 'drizzle-orm/pg-core'
export const parentIDColumnMap = {
integer,
numeric,
varchar,
};
}

View File

@@ -1,19 +1,18 @@
import type { CommitTransaction } from 'payload/database';
import { sql } from 'drizzle-orm';
import type { CommitTransaction } from 'payload/database'
import { sql } from 'drizzle-orm'
export const commitTransaction: CommitTransaction = async function commitTransaction(id) {
if (!this.sessions[id]) {
this.payload.logger.warn('commitTransaction called when no transaction exists');
return;
this.payload.logger.warn('commitTransaction called when no transaction exists')
return
}
try {
await this.sessions[id].execute(sql`COMMIT;`);
await this.sessions[id].execute(sql`COMMIT;`)
} catch (err: unknown) {
await this.sessions[id].execute(sql`ROLLBACK;`);
await this.sessions[id].execute(sql`ROLLBACK;`)
}
delete this.sessions[id];
};
delete this.sessions[id]
}

View File

@@ -1,13 +1,14 @@
import type { RollbackTransaction } from 'payload/database';
import type { RollbackTransaction } from 'payload/database'
import { sql } from 'drizzle-orm';
import { sql } from 'drizzle-orm'
export const rollbackTransaction: RollbackTransaction = async function rollbackTransaction(id = '') {
export const rollbackTransaction: RollbackTransaction = async function rollbackTransaction(
id = '',
) {
if (!this.sessions[id]) {
this.payload.logger.warn('rollbackTransaction called when no transaction exists');
return;
this.payload.logger.warn('rollbackTransaction called when no transaction exists')
return
}
await this.sessions[id].execute(sql`ROLLBACK;`);
delete this.sessions[id];
};
await this.sessions[id].execute(sql`ROLLBACK;`)
delete this.sessions[id]
}

View File

@@ -1,5 +1,5 @@
/* eslint-disable no-param-reassign */
import { RelationshipField } from 'payload/types';
import type { RelationshipField } from 'payload/types'
type Args = {
field: RelationshipField
@@ -8,68 +8,67 @@ type Args = {
relations: Record<string, unknown>[]
}
export const transformRelationship = ({
field,
locale,
ref,
relations,
}: Args) => {
let result: unknown;
export const transformRelationship = ({ field, locale, ref, relations }: Args) => {
let result: unknown
if (!field.hasMany) {
const relation = relations[0];
const relation = relations[0]
if (relation) {
// Handle hasOne Poly
if (Array.isArray(field.relationTo)) {
const matchedRelation = Object.entries(relation).find(([key, val]) => val !== null && !['order', 'id', 'parent', 'locale'].includes(key));
const matchedRelation = Object.entries(relation).find(
([key, val]) => val !== null && !['id', 'locale', 'order', 'parent'].includes(key),
)
if (matchedRelation) {
const relationTo = matchedRelation[0].replace('ID', '');
const relationTo = matchedRelation[0].replace('ID', '')
result = {
relationTo,
value: matchedRelation[1],
};
}
}
} else {
// Handle hasOne
const relatedData = relation[`${field.relationTo}ID`];
result = relatedData;
const relatedData = relation[`${field.relationTo}ID`]
result = relatedData
}
}
} else {
const transformedRelations = [];
const transformedRelations = []
relations.forEach((relation) => {
// Handle hasMany
if (!Array.isArray(field.relationTo)) {
const relatedData = relation[`${field.relationTo}ID`];
const relatedData = relation[`${field.relationTo}ID`]
if (relatedData) {
transformedRelations.push(relatedData);
transformedRelations.push(relatedData)
}
} else {
// Handle hasMany Poly
const matchedRelation = Object.entries(relation).find(([key, val]) => val !== null && !['order', 'parent', 'id', 'locale'].includes(key));
const matchedRelation = Object.entries(relation).find(
([key, val]) => val !== null && !['id', 'locale', 'order', 'parent'].includes(key),
)
if (matchedRelation) {
const relationTo = matchedRelation[0].replace('ID', '');
const relationTo = matchedRelation[0].replace('ID', '')
transformedRelations.push({
relationTo,
value: matchedRelation[1],
});
})
}
}
});
})
result = transformedRelations;
result = transformedRelations
}
if (locale) {
ref[field.name][locale] = result;
ref[field.name][locale] = result
} else {
ref[field.name] = result;
ref[field.name] = result
}
};
}

View File

@@ -1,9 +1,15 @@
/* eslint-disable no-param-reassign */
import type { SanitizedConfig } from 'payload/config'
<<<<<<< HEAD
import type { Field, TabAsField } from 'payload/types'
import { fieldAffectsData, tabHasName } from 'payload/types'
import toSnakeCase from 'to-snake-case'
=======
import type { Field } from 'payload/types'
import { fieldAffectsData } from 'payload/types'
>>>>>>> 463a39e8223464012ef67564d46eae5a4cf83280
import type { BlocksMap } from '../../utilities/createBlocksMap'
@@ -205,12 +211,18 @@ export const traverseFields = <T extends Record<string, unknown>>({
const localizedFieldData = {}
const valuesToTransform: {
<<<<<<< HEAD
ref: Record<string, unknown>
table: Record<string, unknown>
=======
localeRow: Record<string, unknown>
ref: Record<string, unknown>
>>>>>>> 463a39e8223464012ef67564d46eae5a4cf83280
}[] = []
if (field.localized && Array.isArray(table._locales)) {
table._locales.forEach((localeRow) => {
<<<<<<< HEAD
valuesToTransform.push({ ref: localizedFieldData, table: localeRow })
})
} else {
@@ -220,10 +232,22 @@ export const traverseFields = <T extends Record<string, unknown>>({
valuesToTransform.forEach(({ ref, table }) => {
const fieldData = table[field.name]
const locale = table?._locale
=======
valuesToTransform.push({ localeRow, ref: localizedFieldData })
})
} else {
valuesToTransform.push({ localeRow: undefined, ref: result })
}
valuesToTransform.forEach(({ localeRow, ref }) => {
const fieldData = localeRow?.[field.name] || ref[field.name]
const locale = localeRow?._locale
>>>>>>> 463a39e8223464012ef67564d46eae5a4cf83280
switch (field.type) {
case 'tab':
case 'group': {
<<<<<<< HEAD
// if (field.type === 'tab') {
// console.log('got one')
// }
@@ -245,6 +269,25 @@ export const traverseFields = <T extends Record<string, unknown>>({
const groupColumnPrefix = `${columnPrefix || ''}${toSnakeCase(field.name)}_`
const groupData = {}
=======
const groupData = {}
field.fields.forEach((subField) => {
if (fieldAffectsData(subField)) {
const subFieldKey = `${sanitizedPath.replace(/\./g, '_')}${field.name}_${
subField.name
}`
if (typeof locale === 'string') {
if (!ref[locale]) ref[locale] = {}
ref[locale][subField.name] = localeRow[subFieldKey]
} else {
groupData[subField.name] = table[subFieldKey]
delete table[subFieldKey]
}
}
})
>>>>>>> 463a39e8223464012ef67564d46eae5a4cf83280
if (field.localized) {
if (typeof locale === 'string' && !ref[locale]) ref[locale] = {}
@@ -326,6 +369,7 @@ export const traverseFields = <T extends Record<string, unknown>>({
return result
}
<<<<<<< HEAD
if (field.type === 'tabs') {
traverseFields({
blocks,
@@ -355,5 +399,10 @@ export const traverseFields = <T extends Record<string, unknown>>({
return dataRef
}, dataRef)
=======
return siblingData
}, siblingData)
>>>>>>> 463a39e8223464012ef67564d46eae5a4cf83280
return formatted as T
}

View File

@@ -1,10 +1,10 @@
/* eslint-disable no-param-reassign */
import type { ArrayField } from 'payload/types';
import type { ArrayField } from 'payload/types'
import type { ArrayRowToInsert, BlockRowToInsert } from './types';
import type { ArrayRowToInsert, BlockRowToInsert } from './types'
import { isArrayOfRows } from '../../utilities/isArrayOfRows';
import { traverseFields } from './traverseFields';
import { isArrayOfRows } from '../../utilities/isArrayOfRows'
import { traverseFields } from './traverseFields'
type Args = {
arrayTableName: string
@@ -29,7 +29,7 @@ export const transformArray = ({
path,
relationships,
}: Args) => {
const newRows: ArrayRowToInsert[] = [];
const newRows: ArrayRowToInsert[] = []
if (isArrayOfRows(data)) {
data.forEach((arrayRow, i) => {
@@ -40,16 +40,16 @@ export const transformArray = ({
row: {
_order: i + 1,
},
};
}
if (locale) {
newRow.locales[locale] = {
_locale: locale,
};
}
}
if (field.localized) {
newRow.row._locale = locale;
newRow.row._locale = locale
}
traverseFields({
@@ -64,11 +64,11 @@ export const transformArray = ({
path: `${path || ''}${field.name}.${i}.`,
relationships,
row: newRow.row,
});
})
newRows.push(newRow);
});
newRows.push(newRow)
})
}
return newRows;
};
return newRows
}

View File

@@ -1,11 +1,11 @@
/* eslint-disable no-param-reassign */
import type { BlockField } from 'payload/types';
import type { BlockField } from 'payload/types'
import toSnakeCase from 'to-snake-case';
import toSnakeCase from 'to-snake-case'
import type { BlockRowToInsert } from './types';
import type { BlockRowToInsert } from './types'
import { traverseFields } from './traverseFields';
import { traverseFields } from './traverseFields'
type Args = {
blocks: {
@@ -28,11 +28,11 @@ export const transformBlocks = ({
tableName,
}: Args) => {
data.forEach((blockRow, i) => {
if (typeof blockRow.blockType !== 'string') return;
const matchedBlock = field.blocks.find(({ slug }) => slug === blockRow.blockType);
if (!matchedBlock) return;
if (typeof blockRow.blockType !== 'string') return
const matchedBlock = field.blocks.find(({ slug }) => slug === blockRow.blockType)
if (!matchedBlock) return
if (!blocks[blockRow.blockType]) blocks[blockRow.blockType] = [];
if (!blocks[blockRow.blockType]) blocks[blockRow.blockType] = []
const newRow: BlockRowToInsert = {
arrays: {},
@@ -41,11 +41,11 @@ export const transformBlocks = ({
_order: i + 1,
_path: `${path}${field.name}`,
},
};
}
if (field.localized && locale) newRow.row._locale = locale;
if (field.localized && locale) newRow.row._locale = locale
const blockTableName = `${tableName}_${toSnakeCase(blockRow.blockType)}`;
const blockTableName = `${tableName}_${toSnakeCase(blockRow.blockType)}`
traverseFields({
arrays: newRow.arrays,
@@ -59,8 +59,8 @@ export const transformBlocks = ({
path: `${path || ''}${field.name}.${i}.`,
relationships,
row: newRow.row,
});
})
blocks[blockRow.blockType].push(newRow);
});
};
blocks[blockRow.blockType].push(newRow)
})
}

View File

@@ -1,10 +1,9 @@
/* eslint-disable no-param-reassign */
import type { Field } from 'payload/types';
import type { Field } from 'payload/types'
import type { RowToInsert } from './types';
import { traverseFields } from './traverseFields';
import type { RowToInsert } from './types'
import { traverseFields } from './traverseFields'
type Args = {
data: Record<string, unknown>
@@ -13,12 +12,7 @@ type Args = {
tableName: string
}
export const transformForWrite = ({
data,
fields,
path = '',
tableName,
}: Args): RowToInsert => {
export const transformForWrite = ({ data, fields, path = '', tableName }: Args): RowToInsert => {
// Split out the incoming data into the corresponding:
// base row, locales, relationships, blocks, and arrays
const rowToInsert: RowToInsert = {
@@ -27,7 +21,7 @@ export const transformForWrite = ({
locales: {},
relationships: [],
row: {},
};
}
// This function is responsible for building up the
// above rowToInsert
@@ -43,7 +37,7 @@ export const transformForWrite = ({
path,
relationships: rowToInsert.relationships,
row: rowToInsert.row,
});
})
return rowToInsert;
};
return rowToInsert
}

View File

@@ -1,6 +1,6 @@
import type { RelationshipField, UploadField } from 'payload/types';
import type { RelationshipField, UploadField } from 'payload/types'
import { valueIsValueWithRelation } from 'payload/types';
import { valueIsValueWithRelation } from 'payload/types'
type Args = {
baseRow: Record<string, unknown>
@@ -9,26 +9,21 @@ type Args = {
relationships: Record<string, unknown>[]
}
export const transformRelationship = ({
baseRow,
data,
field,
relationships,
}: Args) => {
const relations = Array.isArray(data) ? data : [data];
export const transformRelationship = ({ baseRow, data, field, relationships }: Args) => {
const relations = Array.isArray(data) ? data : [data]
relations.forEach((relation, i) => {
if (relation) {
const relationRow = { ...baseRow };
if ('hasMany' in field && field.hasMany) relationRow.order = i + 1;
const relationRow = { ...baseRow }
if ('hasMany' in field && field.hasMany) relationRow.order = i + 1
if (Array.isArray(field.relationTo) && valueIsValueWithRelation(relation)) {
relationRow[`${relation.relationTo}ID`] = relation.value;
relationships.push(relationRow);
relationRow[`${relation.relationTo}ID`] = relation.value
relationships.push(relationRow)
} else {
relationRow[`${field.relationTo}ID`] = relation;
if (relation) relationships.push(relationRow);
relationRow[`${field.relationTo}ID`] = relation
if (relation) relationships.push(relationRow)
}
}
});
};
})
}

View File

@@ -324,26 +324,6 @@ export const traverseFields = ({
break
}
case 'row':
case 'collapsible': {
traverseFields({
adapter,
arrayRowPromises,
blockRows,
columnPrefix,
data,
fields: field.fields,
locale,
localeRow,
operation,
path,
relationshipRows,
row,
tableName,
})
break
}
default: {
break
}

View File

@@ -6,7 +6,7 @@ export type ArrayRowToInsert = {
locales: {
[locale: string]: Record<string, unknown>
}
row: Record<string, unknown>,
row: Record<string, unknown>
}
export type BlockRowToInsert = {
@@ -16,7 +16,7 @@ export type BlockRowToInsert = {
locales: {
[locale: string]: Record<string, unknown>
}
row: Record<string, unknown>,
row: Record<string, unknown>
}
export type RowToInsert = {
@@ -29,6 +29,6 @@ export type RowToInsert = {
locales: {
[locale: string]: Record<string, unknown>
}
relationships: Record<string, unknown>[],
row: Record<string, unknown>,
relationships: Record<string, unknown>[]
row: Record<string, unknown>
}

View File

@@ -1,14 +1,14 @@
import type { ColumnBaseConfig, ColumnDataType, Relation, Relations } from 'drizzle-orm';
import type { NodePgDatabase } from 'drizzle-orm/node-postgres';
import type { PgColumn, PgEnum, PgTableWithColumns } from 'drizzle-orm/pg-core';
import type { DatabaseAdapter, Payload } from 'payload';
import type { ClientConfig, PoolConfig } from 'pg';
import type { ColumnBaseConfig, ColumnDataType, Relation, Relations } from 'drizzle-orm'
import type { NodePgDatabase } from 'drizzle-orm/node-postgres'
import type { PgColumn, PgEnum, PgTableWithColumns } from 'drizzle-orm/pg-core'
import type { DatabaseAdapter, Payload } from 'payload'
import type { ClientConfig, PoolConfig } from 'pg'
export type DrizzleDB = NodePgDatabase<Record<string, never>>
type BaseArgs = {
migrationDir?: string;
migrationName?: string;
migrationDir?: string
migrationName?: string
}
type ClientArgs = {
@@ -23,27 +23,34 @@ type PoolArgs = {
export type Args = ClientArgs | PoolArgs
export type GenericColumn = PgColumn<ColumnBaseConfig<ColumnDataType, string>, Record<string, unknown>>
export type GenericColumn = PgColumn<
ColumnBaseConfig<ColumnDataType, string>,
Record<string, unknown>
>
export type GenericColumns = {
[x: string]: GenericColumn
}
export type GenericTable = PgTableWithColumns<{
columns: GenericColumns, dialect: string, name: string, schema: undefined
columns: GenericColumns
dialect: string
name: string
schema: undefined
}>
export type GenericEnum = PgEnum<[string, ...string[]]>
export type GenericRelation = Relations<string, Record<string, Relation<string>>>
export type PostgresAdapter = DatabaseAdapter & Args & {
export type PostgresAdapter = DatabaseAdapter &
Args & {
db: DrizzleDB
enums: Record<string, GenericEnum>
relations: Record<string, GenericRelation>
schema: Record<string, GenericEnum | GenericRelation | GenericTable>
sessions: Record<string, DrizzleDB>
tables: Record<string, GenericTable>
}
}
export type PostgresAdapterResult = (args: { payload: Payload }) => PostgresAdapter

View File

@@ -1,31 +1,31 @@
import type { UpdateGlobal } from 'payload/database';
import type { PayloadRequest } from 'payload/types';
import type { UpdateGlobal } from 'payload/database'
import type { PayloadRequest } from 'payload/types'
import toSnakeCase from 'to-snake-case';
import toSnakeCase from 'to-snake-case'
import type { PostgresAdapter } from './types';
import type { PostgresAdapter } from './types'
import { upsertRow } from './upsertRow';
import { upsertRow } from './upsertRow'
export const updateGlobal: UpdateGlobal = async function updateGlobal(
this: PostgresAdapter,
{ data, req = {} as PayloadRequest, slug },
) {
const db = req.transactionID ? this.sessions[req.transactionID] : this.db;
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug);
const tableName = toSnakeCase(slug);
const db = req.transactionID ? this.sessions[req.transactionID] : this.db
const globalConfig = this.payload.globals.config.find((config) => config.slug === slug)
const tableName = toSnakeCase(slug)
const existingGlobal = await this.db.query[tableName].findFirst({});
const existingGlobal = await this.db.query[tableName].findFirst({})
const result = await upsertRow({
id: existingGlobal.id,
adapter: this,
data,
db,
fields: globalConfig.fields,
id: existingGlobal.id,
operation: 'update',
tableName: toSnakeCase(slug),
});
})
return result;
};
return result
}

View File

@@ -1,5 +1,6 @@
import { and, eq } from 'drizzle-orm';
import { PostgresAdapter } from '../types';
import { and, eq } from 'drizzle-orm'
import type { PostgresAdapter } from '../types'
type Args = {
adapter: PostgresAdapter
@@ -13,14 +14,9 @@ export const deleteExistingArrayRows = async ({
parentID,
tableName,
}: Args): Promise<void> => {
const table = adapter.tables[tableName];
const table = adapter.tables[tableName]
const whereConstraints = [
eq(table._parentID, parentID),
];
const whereConstraints = [eq(table._parentID, parentID)]
await adapter.db.delete(table)
.where(
and(...whereConstraints),
);
};
await adapter.db.delete(table).where(and(...whereConstraints))
}

View File

@@ -1,64 +1,57 @@
import { and, eq, inArray } from 'drizzle-orm';
import { PostgresAdapter } from '../types';
import { and, eq, inArray } from 'drizzle-orm'
import type { PostgresAdapter } from '../types'
type Args = {
adapter: PostgresAdapter
localeColumnName?: string
newRows: Record<string, unknown>[]
parentColumnName?: string
parentID: unknown
pathColumnName?: string
newRows: Record<string, unknown>[]
tableName: string
}
export const deleteExistingRowsByPath = async ({
adapter,
localeColumnName = '_locale',
newRows,
parentColumnName = '_parentID',
parentID,
pathColumnName = '_path',
newRows,
tableName,
}: Args): Promise<void> => {
const localizedPathsToDelete = new Set<string>();
const pathsToDelete = new Set<string>();
const table = adapter.tables[tableName];
const localizedPathsToDelete = new Set<string>()
const pathsToDelete = new Set<string>()
const table = adapter.tables[tableName]
newRows.forEach((row) => {
const path = row[pathColumnName];
const localeData = row[localeColumnName];
const path = row[pathColumnName]
const localeData = row[localeColumnName]
if (typeof path === 'string') {
if (typeof localeData === 'string') {
localizedPathsToDelete.add(path);
localizedPathsToDelete.add(path)
} else {
pathsToDelete.add(path);
pathsToDelete.add(path)
}
}
});
})
if (localizedPathsToDelete.size > 0) {
const whereConstraints = [
eq(table[parentColumnName], parentID),
];
const whereConstraints = [eq(table[parentColumnName], parentID)]
if (pathColumnName) whereConstraints.push(inArray(table[pathColumnName], Array.from(localizedPathsToDelete)));
if (pathColumnName)
whereConstraints.push(inArray(table[pathColumnName], Array.from(localizedPathsToDelete)))
await adapter.db.delete(table)
.where(
and(...whereConstraints),
);
await adapter.db.delete(table).where(and(...whereConstraints))
}
if (pathsToDelete.size > 0) {
const whereConstraints = [
eq(table[parentColumnName], parentID),
];
const whereConstraints = [eq(table[parentColumnName], parentID)]
if (pathColumnName) whereConstraints.push(inArray(table[pathColumnName], Array.from(pathsToDelete)));
if (pathColumnName)
whereConstraints.push(inArray(table[pathColumnName], Array.from(pathsToDelete)))
await adapter.db.delete(table)
.where(
and(...whereConstraints),
);
await adapter.db.delete(table).where(and(...whereConstraints))
}
};
}

View File

@@ -1,22 +1,22 @@
/* eslint-disable no-param-reassign */
import { eq } from 'drizzle-orm';
import { eq } from 'drizzle-orm'
import type { BlockRowToInsert } from '../transform/write/types';
import type { Args } from './types';
import type { BlockRowToInsert } from '../transform/write/types'
import type { Args } from './types'
import { buildFindManyArgs } from '../find/buildFindManyArgs';
import { transform } from '../transform/read';
import { transformForWrite } from '../transform/write';
import { deleteExistingArrayRows } from './deleteExistingArrayRows';
import { deleteExistingRowsByPath } from './deleteExistingRowsByPath';
import { insertArrays } from './insertArrays';
import { buildFindManyArgs } from '../find/buildFindManyArgs'
import { transform } from '../transform/read'
import { transformForWrite } from '../transform/write'
import { deleteExistingArrayRows } from './deleteExistingArrayRows'
import { deleteExistingRowsByPath } from './deleteExistingRowsByPath'
import { insertArrays } from './insertArrays'
export const upsertRow = async ({
id,
adapter,
data,
db,
fields,
id,
operation,
path = '',
tableName,
@@ -30,80 +30,81 @@ export const upsertRow = async ({
fields,
path,
tableName,
});
})
// First, we insert the main row
let insertedRow: Record<string, unknown>;
let insertedRow: Record<string, unknown>
if (operation === 'update') {
const target = upsertTarget || adapter.tables[tableName].id;
const target = upsertTarget || adapter.tables[tableName].id
if (id) {
rowToInsert.row.id = id;
[insertedRow] = await db.insert(adapter.tables[tableName])
rowToInsert.row.id = id
;[insertedRow] = await db
.insert(adapter.tables[tableName])
.values(rowToInsert.row)
.onConflictDoUpdate({ set: rowToInsert.row, target })
.returning();
.returning()
} else {
[insertedRow] = await db.insert(adapter.tables[tableName])
;[insertedRow] = await db
.insert(adapter.tables[tableName])
.values(rowToInsert.row)
.onConflictDoUpdate({ set: rowToInsert.row, target, where })
.returning();
.returning()
}
} else {
[insertedRow] = await db.insert(adapter.tables[tableName])
.values(rowToInsert.row).returning();
;[insertedRow] = await db.insert(adapter.tables[tableName]).values(rowToInsert.row).returning()
}
const localesToInsert: Record<string, unknown>[] = [];
const relationsToInsert: Record<string, unknown>[] = [];
const blocksToInsert: { [blockType: string]: BlockRowToInsert[] } = {};
const localesToInsert: Record<string, unknown>[] = []
const relationsToInsert: Record<string, unknown>[] = []
const blocksToInsert: { [blockType: string]: BlockRowToInsert[] } = {}
// Maintain a list of promises to run locale, blocks, and relationships
// all in parallel
const promises = [];
const promises = []
// If there are locale rows with data, add the parent and locale to each
if (Object.keys(rowToInsert.locales).length > 0) {
Object.entries(rowToInsert.locales).forEach(([locale, localeRow]) => {
localeRow._parentID = insertedRow.id;
localeRow._locale = locale;
localesToInsert.push(localeRow);
});
localeRow._parentID = insertedRow.id
localeRow._locale = locale
localesToInsert.push(localeRow)
})
}
// If there are relationships, add parent to each
if (rowToInsert.relationships.length > 0) {
rowToInsert.relationships.forEach((relation) => {
relation.parent = insertedRow.id;
relationsToInsert.push(relation);
});
relation.parent = insertedRow.id
relationsToInsert.push(relation)
})
}
// If there are blocks, add parent to each, and then
// store by table name and rows
Object.keys(rowToInsert.blocks).forEach((blockName) => {
rowToInsert.blocks[blockName].forEach((blockRow) => {
blockRow.row._parentID = insertedRow.id;
if (!blocksToInsert[blockName]) blocksToInsert[blockName] = [];
blocksToInsert[blockName].push(blockRow);
});
});
blockRow.row._parentID = insertedRow.id
if (!blocksToInsert[blockName]) blocksToInsert[blockName] = []
blocksToInsert[blockName].push(blockRow)
})
})
// //////////////////////////////////
// INSERT LOCALES
// //////////////////////////////////
if (localesToInsert.length > 0) {
const localeTable = adapter.tables[`${tableName}_locales`];
const localeTable = adapter.tables[`${tableName}_locales`]
promises.push(async () => {
if (operation === 'update') {
await db.delete(localeTable).where(eq(localeTable._parentID, insertedRow.id));
await db.delete(localeTable).where(eq(localeTable._parentID, insertedRow.id))
}
await db.insert(localeTable).values(localesToInsert);
});
await db.insert(localeTable).values(localesToInsert)
})
}
// //////////////////////////////////
@@ -112,7 +113,7 @@ export const upsertRow = async ({
if (relationsToInsert.length > 0) {
promises.push(async () => {
const relationshipsTableName = `${tableName}_relationships`;
const relationshipsTableName = `${tableName}_relationships`
if (operation === 'update') {
await deleteExistingRowsByPath({
adapter,
@@ -122,19 +123,18 @@ export const upsertRow = async ({
parentID: insertedRow.id,
pathColumnName: 'path',
tableName: relationshipsTableName,
});
})
}
await db.insert(adapter.tables[relationshipsTableName])
.values(relationsToInsert).returning();
});
await db.insert(adapter.tables[relationshipsTableName]).values(relationsToInsert).returning()
})
}
// //////////////////////////////////
// INSERT BLOCKS
// //////////////////////////////////
const insertedBlockRows: Record<string, Record<string, unknown>[]> = {};
const insertedBlockRows: Record<string, Record<string, unknown>[]> = {}
Object.entries(blocksToInsert).forEach(([blockName, blockRows]) => {
// For each block, push insert into promises to run parallel
@@ -146,45 +146,49 @@ export const upsertRow = async ({
parentID: insertedRow.id,
pathColumnName: '_path',
tableName: `${tableName}_${blockName}`,
});
})
}
insertedBlockRows[blockName] = await db.insert(adapter.tables[`${tableName}_${blockName}`])
.values(blockRows.map(({ row }) => row)).returning();
insertedBlockRows[blockName] = await db
.insert(adapter.tables[`${tableName}_${blockName}`])
.values(blockRows.map(({ row }) => row))
.returning()
insertedBlockRows[blockName].forEach((row, i) => {
blockRows[i].row = row;
});
blockRows[i].row = row
})
const blockLocaleIndexMap: number[] = [];
const blockLocaleIndexMap: number[] = []
const blockLocaleRowsToInsert = blockRows.reduce((acc, blockRow, i) => {
if (Object.entries(blockRow.locales).length > 0) {
Object.entries(blockRow.locales).forEach(([blockLocale, blockLocaleData]) => {
if (Object.keys(blockLocaleData).length > 0) {
blockLocaleData._parentID = blockRow.row.id;
blockLocaleData._locale = blockLocale;
acc.push(blockLocaleData);
blockLocaleIndexMap.push(i);
blockLocaleData._parentID = blockRow.row.id
blockLocaleData._locale = blockLocale
acc.push(blockLocaleData)
blockLocaleIndexMap.push(i)
}
});
})
}
return acc;
}, []);
return acc
}, [])
if (blockLocaleRowsToInsert.length > 0) {
await db.insert(adapter.tables[`${tableName}_${blockName}_locales`])
.values(blockLocaleRowsToInsert).returning();
await db
.insert(adapter.tables[`${tableName}_${blockName}_locales`])
.values(blockLocaleRowsToInsert)
.returning()
}
await insertArrays({
adapter,
arrays: blockRows.map(({ arrays }) => arrays),
parentRows: insertedBlockRows[blockName],
});
});
});
})
})
})
// //////////////////////////////////
// INSERT ARRAYS RECURSIVELY
@@ -192,23 +196,25 @@ export const upsertRow = async ({
promises.push(async () => {
if (operation === 'update') {
await Promise.all(Object.entries(rowToInsert.arrays).map(async ([arrayTableName, tableRows]) => {
await Promise.all(
Object.entries(rowToInsert.arrays).map(async ([arrayTableName, tableRows]) => {
await deleteExistingArrayRows({
adapter,
parentID: insertedRow.id,
tableName: arrayTableName,
});
}));
})
}),
)
}
await insertArrays({
adapter,
arrays: [rowToInsert.arrays],
parentRows: [insertedRow],
});
});
})
})
await Promise.all(promises.map((promise) => promise()));
await Promise.all(promises.map((promise) => promise()))
// //////////////////////////////////
// RETRIEVE NEWLY UPDATED ROW
@@ -219,11 +225,11 @@ export const upsertRow = async ({
depth: 0,
fields,
tableName,
});
})
findManyArgs.where = eq(adapter.tables[tableName].id, insertedRow.id);
findManyArgs.where = eq(adapter.tables[tableName].id, insertedRow.id)
const doc = await db.query[tableName].findFirst(findManyArgs);
const doc = await db.query[tableName].findFirst(findManyArgs)
// //////////////////////////////////
// TRANSFORM DATA
@@ -233,7 +239,7 @@ export const upsertRow = async ({
config: adapter.payload.config,
data: doc,
fields,
});
})
return result;
};
return result
}

View File

@@ -1,6 +1,6 @@
/* eslint-disable no-param-reassign */
import { PostgresAdapter } from '../types';
import { ArrayRowToInsert } from '../transform/write/types';
import type { ArrayRowToInsert } from '../transform/write/types'
import type { PostgresAdapter } from '../types'
type Args = {
adapter: PostgresAdapter
@@ -20,13 +20,9 @@ type RowsByTable = {
}
}
export const insertArrays = async ({
adapter,
arrays,
parentRows,
}: Args): Promise<void> => {
export const insertArrays = async ({ adapter, arrays, parentRows }: Args): Promise<void> => {
// Maintain a map of flattened rows by table
const rowsByTable: RowsByTable = {};
const rowsByTable: RowsByTable = {}
arrays.forEach((arraysByTable, parentRowIndex) => {
Object.entries(arraysByTable).forEach(([tableName, arrayRows]) => {
@@ -36,43 +32,43 @@ export const insertArrays = async ({
arrays: [],
locales: [],
rows: [],
};
}
}
const parentID = parentRows[parentRowIndex].id;
const parentID = parentRows[parentRowIndex].id
// Add any sub arrays that need to be created
// We will call this recursively below
arrayRows.forEach((arrayRow) => {
if (Object.keys(arrayRow.arrays).length > 0) {
rowsByTable[tableName].arrays.push(arrayRow.arrays);
rowsByTable[tableName].arrays.push(arrayRow.arrays)
}
// Set up parent IDs for both row and locale row
arrayRow.row._parentID = parentID;
rowsByTable[tableName].rows.push(arrayRow.row);
arrayRow.row._parentID = parentID
rowsByTable[tableName].rows.push(arrayRow.row)
Object.entries(arrayRow.locales).forEach(([arrayRowLocale, arrayRowLocaleData]) => {
arrayRowLocaleData._parentID = arrayRow.row.id;
arrayRowLocaleData._locale = arrayRowLocale;
rowsByTable[tableName].locales.push(arrayRowLocaleData);
});
});
});
});
arrayRowLocaleData._parentID = arrayRow.row.id
arrayRowLocaleData._locale = arrayRowLocale
rowsByTable[tableName].locales.push(arrayRowLocaleData)
})
})
})
})
// Insert all corresponding arrays in parallel
// (one insert per array table)
await Promise.all(Object.entries(rowsByTable).map(async (
[tableName, row],
) => {
await adapter.db.insert(adapter.tables[tableName])
.values(row.rows).returning();
await Promise.all(
Object.entries(rowsByTable).map(async ([tableName, row]) => {
await adapter.db.insert(adapter.tables[tableName]).values(row.rows).returning()
// Insert locale rows
if (adapter.tables[`${tableName}_locales`]) {
await adapter.db.insert(adapter.tables[`${tableName}_locales`])
.values(row.locales).returning();
await adapter.db
.insert(adapter.tables[`${tableName}_locales`])
.values(row.locales)
.returning()
}
// If there are sub arrays, call this function recursively
@@ -81,7 +77,8 @@ export const insertArrays = async ({
adapter,
arrays: row.arrays,
parentRows: row.rows,
});
})
}
}));
};
}),
)
}

View File

@@ -1,8 +1,8 @@
import type { SQL } from 'drizzle-orm';
import type { Field } from 'payload/types';
import type { SQL } from 'drizzle-orm'
import type { Field } from 'payload/types'
import type { GenericColumn, PostgresAdapter } from '../types';
import type { DrizzleDB } from '../types';
import type { GenericColumn, PostgresAdapter } from '../types'
import type { DrizzleDB } from '../types'
type BaseArgs = {
adapter: PostgresAdapter

View File

@@ -4,38 +4,38 @@ export type BlocksMap = {
}
export const createBlocksMap = (data: Record<string, unknown>): BlocksMap => {
const blocksMap: BlocksMap = {};
const blocksMap: BlocksMap = {}
Object.entries(data).forEach(([key, rows]) => {
if (key.startsWith('_blocks_') && Array.isArray(rows)) {
const blockType = key.replace('_blocks_', '');
const blockType = key.replace('_blocks_', '')
rows.forEach((row) => {
if ('_path' in row) {
if (!(row._path in blocksMap)) blocksMap[row._path] = [];
if (!(row._path in blocksMap)) blocksMap[row._path] = []
row.blockType = blockType;
blocksMap[row._path].push(row);
row.blockType = blockType
blocksMap[row._path].push(row)
delete row._path;
delete row._path
}
});
})
delete data[key];
delete data[key]
}
});
})
Object.entries(blocksMap).reduce((sortedBlocksMap, [path, blocks]) => {
sortedBlocksMap[path] = blocks.sort((a, b) => {
if (typeof a._order === 'number' && typeof b._order === 'number') {
return a._order - b._order;
return a._order - b._order
}
return 0;
});
return 0
})
return sortedBlocksMap;
}, {});
return sortedBlocksMap
}, {})
return blocksMap;
};
return blocksMap
}

View File

@@ -1,22 +1,24 @@
// Flatten relationships to object with path keys
// for easier retrieval
export const createRelationshipMap = (rawRelationships: unknown): Record<string, Record<string, unknown>[]> => {
let relationships = {};
export const createRelationshipMap = (
rawRelationships: unknown,
): Record<string, Record<string, unknown>[]> => {
let relationships = {}
if (Array.isArray(rawRelationships)) {
relationships = rawRelationships.reduce((res, relation) => {
const formattedRelation = {
...relation,
};
delete formattedRelation.path;
if (!res[relation.path]) res[relation.path] = [];
res[relation.path].push(formattedRelation);
return res;
}, {});
}
return relationships;
};
delete formattedRelation.path
if (!res[relation.path]) res[relation.path] = []
res[relation.path].push(formattedRelation)
return res
}, {})
}
return relationships
}

View File

@@ -1,12 +1,12 @@
import type { Field} from 'payload/types';
import type { Field } from 'payload/types'
import { fieldAffectsData, fieldHasSubFields } from 'payload/types';
import { fieldAffectsData, fieldHasSubFields } from 'payload/types'
export const hasLocalesTable = (fields: Field[]): boolean => {
return fields.some((field) => {
if (fieldAffectsData(field) && field.localized) return true;
if (fieldHasSubFields(field) && field.type !== 'array') return hasLocalesTable(field.fields);
if (field.type === 'tabs') return field.tabs.some((tab) => hasLocalesTable(tab.fields));
return false;
});
};
if (fieldAffectsData(field) && field.localized) return true
if (fieldHasSubFields(field) && field.type !== 'array') return hasLocalesTable(field.fields)
if (field.type === 'tabs') return field.tabs.some((tab) => hasLocalesTable(tab.fields))
return false
})
}

View File

@@ -1,3 +1,3 @@
export function isArrayOfRows(data: unknown): data is Record<string, unknown>[] {
return Array.isArray(data);
return Array.isArray(data)
}

View File

@@ -3,6 +3,12 @@
"version": "0.0.1",
"private": true,
"description": "Payload styles for ESLint and Prettier",
"license": "MIT",
"author": {
"email": "info@payloadcms.com",
"name": "Payload",
"url": "https://payloadcms.com"
},
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
@@ -24,7 +30,5 @@
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-regexp": "1.15.0"
},
"keywords": [],
"author": "",
"license": "MIT"
"keywords": []
}

View File

@@ -27,6 +27,28 @@ module.exports = {
'jest/expect-expect': 'off',
},
},
{
files: ['package.json', 'tsconfig.json'],
rules: {
'perfectionist/sort-array-includes': 'off',
'perfectionist/sort-astro-attributes': 'off',
'perfectionist/sort-classes': 'off',
'perfectionist/sort-enums': 'off',
'perfectionist/sort-exports': 'off',
'perfectionist/sort-imports': 'off',
'perfectionist/sort-interfaces': 'off',
'perfectionist/sort-jsx-props': 'off',
'perfectionist/sort-keys': 'off',
'perfectionist/sort-maps': 'off',
'perfectionist/sort-named-exports': 'off',
'perfectionist/sort-named-imports': 'off',
'perfectionist/sort-object-types': 'off',
'perfectionist/sort-objects': 'off',
'perfectionist/sort-svelte-attributes': 'off',
'perfectionist/sort-union-types': 'off',
'perfectionist/sort-vue-attributes': 'off',
},
},
],
parserOptions: {
project: ['./tsconfig.json'],

View File

@@ -1,2 +1,2 @@
export * from './dist/auth';
export * from './dist/auth'
//# sourceMappingURL=auth.d.ts.map

View File

@@ -1,20 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
_export_star(require("./dist/auth"), exports);
'use strict'
Object.defineProperty(exports, '__esModule', {
value: true,
})
_export_star(require('./dist/auth'), exports)
function _export_star(from, to) {
Object.keys(from).forEach(function(k) {
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
Object.keys(from).forEach(function (k) {
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(to, k)) {
Object.defineProperty(to, k, {
enumerable: true,
get: function() {
return from[k];
get: function () {
return from[k]
},
})
}
});
}
});
return from;
})
return from
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9leHBvcnRzL2F1dGgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi4vYXV0aCdcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O3FCQUFjIn0=

View File

@@ -1,11 +1,13 @@
export { default as Banner } from './dist/admin/components/elements/Banner';
export { default as Button } from './dist/admin/components/elements/Button';
export { default as Pill } from './dist/admin/components/elements/Pill';
export { default as Popup } from './dist/admin/components/elements/Popup';
export { default as Check } from './dist/admin/components/icons/Check';
export { default as Chevron } from './dist/admin/components/icons/Chevron';
export { default as Menu } from './dist/admin/components/icons/Menu';
export { default as Search } from './dist/admin/components/icons/Search';
export { default as X } from './dist/admin/components/icons/X';
export { default as MinimalTemplate } from './dist/admin/components/templates/Minimal';
export { default as Banner } from './dist/admin/components/elements/Banner'
export { default as Button } from './dist/admin/components/elements/Button'
export { default as Pill } from './dist/admin/components/elements/Pill'
export { default as Popup } from './dist/admin/components/elements/Popup'
export { ShimmerEffect } from './dist/admin/components/elements/ShimmerEffect'
export { default as Tooltip } from './dist/admin/components/elements/Tooltip'
export { default as Check } from './dist/admin/components/icons/Check'
export { default as Chevron } from './dist/admin/components/icons/Chevron'
export { default as Menu } from './dist/admin/components/icons/Menu'
export { default as Search } from './dist/admin/components/icons/Search'
export { default as X } from './dist/admin/components/icons/X'
export { default as MinimalTemplate } from './dist/admin/components/templates/Minimal'
//# sourceMappingURL=components.d.ts.map

View File

@@ -1,59 +1,88 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
'use strict'
Object.defineProperty(exports, '__esModule', {
value: true,
})
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
for (var name in all)
Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
get: all[name],
})
}
_export(exports, {
Banner: function() {
return _Banner.default;
Banner: function () {
return _Banner.default
},
Button: function() {
return _Button.default;
Button: function () {
return _Button.default
},
Pill: function() {
return _Pill.default;
Check: function () {
return _Check.default
},
Popup: function() {
return _Popup.default;
Chevron: function () {
return _Chevron.default
},
Check: function() {
return _Check.default;
Menu: function () {
return _Menu.default
},
Chevron: function() {
return _Chevron.default;
MinimalTemplate: function () {
return _Minimal.default
},
Menu: function() {
return _Menu.default;
Pill: function () {
return _Pill.default
},
Search: function() {
return _Search.default;
Popup: function () {
return _Popup.default
},
X: function() {
return _X.default;
Search: function () {
return _Search.default
},
MinimalTemplate: function() {
return _Minimal.default;
}
});
const _Banner = /*#__PURE__*/ _interop_require_default(require("./dist/admin/components/elements/Banner"));
const _Button = /*#__PURE__*/ _interop_require_default(require("./dist/admin/components/elements/Button"));
const _Pill = /*#__PURE__*/ _interop_require_default(require("./dist/admin/components/elements/Pill"));
const _Popup = /*#__PURE__*/ _interop_require_default(require("./dist/admin/components/elements/Popup"));
const _Check = /*#__PURE__*/ _interop_require_default(require("./dist/admin/components/icons/Check"));
const _Chevron = /*#__PURE__*/ _interop_require_default(require("./dist/admin/components/icons/Chevron"));
const _Menu = /*#__PURE__*/ _interop_require_default(require("./dist/admin/components/icons/Menu"));
const _Search = /*#__PURE__*/ _interop_require_default(require("./dist/admin/components/icons/Search"));
const _X = /*#__PURE__*/ _interop_require_default(require("./dist/admin/components/icons/X"));
const _Minimal = /*#__PURE__*/ _interop_require_default(require("./dist/admin/components/templates/Minimal"));
ShimmerEffect: function () {
return _ShimmerEffect.ShimmerEffect
},
Tooltip: function () {
return _Tooltip.default
},
X: function () {
return _X.default
},
})
const _Banner = /*#__PURE__*/ _interop_require_default(
require('./dist/admin/components/elements/Banner'),
)
const _Button = /*#__PURE__*/ _interop_require_default(
require('./dist/admin/components/elements/Button'),
)
const _Pill = /*#__PURE__*/ _interop_require_default(
require('./dist/admin/components/elements/Pill'),
)
const _Popup = /*#__PURE__*/ _interop_require_default(
require('./dist/admin/components/elements/Popup'),
)
const _ShimmerEffect = require('./dist/admin/components/elements/ShimmerEffect')
const _Tooltip = /*#__PURE__*/ _interop_require_default(
require('./dist/admin/components/elements/Tooltip'),
)
const _Check = /*#__PURE__*/ _interop_require_default(
require('./dist/admin/components/icons/Check'),
)
const _Chevron = /*#__PURE__*/ _interop_require_default(
require('./dist/admin/components/icons/Chevron'),
)
const _Menu = /*#__PURE__*/ _interop_require_default(require('./dist/admin/components/icons/Menu'))
const _Search = /*#__PURE__*/ _interop_require_default(
require('./dist/admin/components/icons/Search'),
)
const _X = /*#__PURE__*/ _interop_require_default(require('./dist/admin/components/icons/X'))
const _Minimal = /*#__PURE__*/ _interop_require_default(
require('./dist/admin/components/templates/Minimal'),
)
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
return obj && obj.__esModule
? obj
: {
default: obj,
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9leHBvcnRzL2NvbXBvbmVudHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgZGVmYXVsdCBhcyBCYW5uZXIgfSBmcm9tICcuLi9hZG1pbi9jb21wb25lbnRzL2VsZW1lbnRzL0Jhbm5lcidcbmV4cG9ydCB7IGRlZmF1bHQgYXMgQnV0dG9uIH0gZnJvbSAnLi4vYWRtaW4vY29tcG9uZW50cy9lbGVtZW50cy9CdXR0b24nXG5cbmV4cG9ydCB7IGRlZmF1bHQgYXMgUGlsbCB9IGZyb20gJy4uL2FkbWluL2NvbXBvbmVudHMvZWxlbWVudHMvUGlsbCdcblxuZXhwb3J0IHsgZGVmYXVsdCBhcyBQb3B1cCB9IGZyb20gJy4uL2FkbWluL2NvbXBvbmVudHMvZWxlbWVudHMvUG9wdXAnXG5leHBvcnQgeyBkZWZhdWx0IGFzIENoZWNrIH0gZnJvbSAnLi4vYWRtaW4vY29tcG9uZW50cy9pY29ucy9DaGVjaydcbmV4cG9ydCB7IGRlZmF1bHQgYXMgQ2hldnJvbiB9IGZyb20gJy4uL2FkbWluL2NvbXBvbmVudHMvaWNvbnMvQ2hldnJvbidcbmV4cG9ydCB7IGRlZmF1bHQgYXMgTWVudSB9IGZyb20gJy4uL2FkbWluL2NvbXBvbmVudHMvaWNvbnMvTWVudSdcbmV4cG9ydCB7IGRlZmF1bHQgYXMgU2VhcmNoIH0gZnJvbSAnLi4vYWRtaW4vY29tcG9uZW50cy9pY29ucy9TZWFyY2gnXG5leHBvcnQgeyBkZWZhdWx0IGFzIFggfSBmcm9tICcuLi9hZG1pbi9jb21wb25lbnRzL2ljb25zL1gnXG5leHBvcnQgeyBkZWZhdWx0IGFzIE1pbmltYWxUZW1wbGF0ZSB9IGZyb20gJy4uL2FkbWluL2NvbXBvbmVudHMvdGVtcGxhdGVzL01pbmltYWwnXG4iXSwibmFtZXMiOlsiQmFubmVyIiwiQnV0dG9uIiwiUGlsbCIsIlBvcHVwIiwiQ2hlY2siLCJDaGV2cm9uIiwiTWVudSIsIlNlYXJjaCIsIlgiLCJNaW5pbWFsVGVtcGxhdGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0lBQW9CQSxNQUFNO2VBQU5BLGVBQU07O0lBQ05DLE1BQU07ZUFBTkEsZUFBTTs7SUFFTkMsSUFBSTtlQUFKQSxhQUFJOztJQUVKQyxLQUFLO2VBQUxBLGNBQUs7O0lBQ0xDLEtBQUs7ZUFBTEEsY0FBSzs7SUFDTEMsT0FBTztlQUFQQSxnQkFBTzs7SUFDUEMsSUFBSTtlQUFKQSxhQUFJOztJQUNKQyxNQUFNO2VBQU5BLGVBQU07O0lBQ05DLENBQUM7ZUFBREEsVUFBQzs7SUFDREMsZUFBZTtlQUFmQSxnQkFBZTs7OytEQVhEOytEQUNBOzZEQUVGOzhEQUVDOzhEQUNBO2dFQUNFOzZEQUNIOytEQUNFOzBEQUNMO2dFQUNjIn0=
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9leHBvcnRzL2NvbXBvbmVudHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgZGVmYXVsdCBhcyBCYW5uZXIgfSBmcm9tICcuLi9hZG1pbi9jb21wb25lbnRzL2VsZW1lbnRzL0Jhbm5lcidcbmV4cG9ydCB7IGRlZmF1bHQgYXMgQnV0dG9uIH0gZnJvbSAnLi4vYWRtaW4vY29tcG9uZW50cy9lbGVtZW50cy9CdXR0b24nXG5cbmV4cG9ydCB7IGRlZmF1bHQgYXMgUGlsbCB9IGZyb20gJy4uL2FkbWluL2NvbXBvbmVudHMvZWxlbWVudHMvUGlsbCdcblxuZXhwb3J0IHsgZGVmYXVsdCBhcyBQb3B1cCB9IGZyb20gJy4uL2FkbWluL2NvbXBvbmVudHMvZWxlbWVudHMvUG9wdXAnXG5cbmV4cG9ydCB7IFNoaW1tZXJFZmZlY3QgfSBmcm9tICcuLi9hZG1pbi9jb21wb25lbnRzL2VsZW1lbnRzL1NoaW1tZXJFZmZlY3QnXG5leHBvcnQgeyBkZWZhdWx0IGFzIFRvb2x0aXAgfSBmcm9tICcuLi9hZG1pbi9jb21wb25lbnRzL2VsZW1lbnRzL1Rvb2x0aXAnXG5leHBvcnQgeyBkZWZhdWx0IGFzIENoZWNrIH0gZnJvbSAnLi4vYWRtaW4vY29tcG9uZW50cy9pY29ucy9DaGVjaydcbmV4cG9ydCB7IGRlZmF1bHQgYXMgQ2hldnJvbiB9IGZyb20gJy4uL2FkbWluL2NvbXBvbmVudHMvaWNvbnMvQ2hldnJvbidcbmV4cG9ydCB7IGRlZmF1bHQgYXMgTWVudSB9IGZyb20gJy4uL2FkbWluL2NvbXBvbmVudHMvaWNvbnMvTWVudSdcbmV4cG9ydCB7IGRlZmF1bHQgYXMgU2VhcmNoIH0gZnJvbSAnLi4vYWRtaW4vY29tcG9uZW50cy9pY29ucy9TZWFyY2gnXG5leHBvcnQgeyBkZWZhdWx0IGFzIFggfSBmcm9tICcuLi9hZG1pbi9jb21wb25lbnRzL2ljb25zL1gnXG5leHBvcnQgeyBkZWZhdWx0IGFzIE1pbmltYWxUZW1wbGF0ZSB9IGZyb20gJy4uL2FkbWluL2NvbXBvbmVudHMvdGVtcGxhdGVzL01pbmltYWwnXG4iXSwibmFtZXMiOlsiQmFubmVyIiwiQnV0dG9uIiwiUGlsbCIsIlBvcHVwIiwiU2hpbW1lckVmZmVjdCIsIlRvb2x0aXAiLCJDaGVjayIsIkNoZXZyb24iLCJNZW51IiwiU2VhcmNoIiwiWCIsIk1pbmltYWxUZW1wbGF0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7SUFBb0JBLE1BQU07ZUFBTkEsZUFBTTs7SUFDTkMsTUFBTTtlQUFOQSxlQUFNOztJQUVOQyxJQUFJO2VBQUpBLGFBQUk7O0lBRUpDLEtBQUs7ZUFBTEEsY0FBSzs7SUFFaEJDLGFBQWE7ZUFBYkEsNEJBQWE7O0lBQ0ZDLE9BQU87ZUFBUEEsZ0JBQU87O0lBQ1BDLEtBQUs7ZUFBTEEsY0FBSzs7SUFDTEMsT0FBTztlQUFQQSxnQkFBTzs7SUFDUEMsSUFBSTtlQUFKQSxhQUFJOztJQUNKQyxNQUFNO2VBQU5BLGVBQU07O0lBQ05DLENBQUM7ZUFBREEsVUFBQzs7SUFDREMsZUFBZTtlQUFmQSxnQkFBZTs7OytEQWREOytEQUNBOzZEQUVGOzhEQUVDOytCQUVIO2dFQUNLOzhEQUNGO2dFQUNFOzZEQUNIOytEQUNFOzBEQUNMO2dFQUNjIn0=

View File

@@ -1,6 +1,21 @@
export { default as Button } from '../dist/admin/components/elements/Button';
export { default as Card } from '../dist/admin/components/elements/Card';
export { default as Eyebrow } from '../dist/admin/components/elements/Eyebrow';
export { Gutter } from '../dist/admin/components/elements/Gutter';
export { default as Nav } from '../dist/admin/components/elements/Nav';
export { default as Button } from '../dist/admin/components/elements/Button'
export { default as Card } from '../dist/admin/components/elements/Card'
export {
DocumentDrawer,
DocumentDrawerToggler,
baseClass as DocumentDrawerBaseClass,
useDocumentDrawer,
} from '../dist/admin/components/elements/DocumentDrawer'
export { Drawer, DrawerToggler, formatDrawerSlug } from '../dist/admin/components/elements/Drawer'
export { useDrawerSlug } from '../dist/admin/components/elements/Drawer/useDrawerSlug'
export { default as Eyebrow } from '../dist/admin/components/elements/Eyebrow'
export { Gutter } from '../dist/admin/components/elements/Gutter'
export {
ListDrawer,
ListDrawerToggler,
baseClass as ListDrawerBaseClass,
formatListDrawerSlug,
useListDrawer,
} from '../dist/admin/components/elements/ListDrawer'
export { default as Nav } from '../dist/admin/components/elements/Nav'
//# sourceMappingURL=elements.d.ts.map

View File

@@ -1,39 +1,93 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
'use strict'
Object.defineProperty(exports, '__esModule', {
value: true,
})
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
for (var name in all)
Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
get: all[name],
})
}
_export(exports, {
Button: function() {
return _Button.default;
Button: function () {
return _Button.default
},
Card: function() {
return _Card.default;
Card: function () {
return _Card.default
},
Eyebrow: function() {
return _Eyebrow.default;
DocumentDrawer: function () {
return _DocumentDrawer.DocumentDrawer
},
Gutter: function() {
return _Gutter.Gutter;
DocumentDrawerBaseClass: function () {
return _DocumentDrawer.baseClass
},
Nav: function() {
return _Nav.default;
}
});
const _Button = /*#__PURE__*/ _interop_require_default(require("../dist/admin/components/elements/Button"));
const _Card = /*#__PURE__*/ _interop_require_default(require("../dist/admin/components/elements/Card"));
const _Eyebrow = /*#__PURE__*/ _interop_require_default(require("../dist/admin/components/elements/Eyebrow"));
const _Gutter = require("../dist/admin/components/elements/Gutter");
const _Nav = /*#__PURE__*/ _interop_require_default(require("../dist/admin/components/elements/Nav"));
DocumentDrawerToggler: function () {
return _DocumentDrawer.DocumentDrawerToggler
},
Drawer: function () {
return _Drawer.Drawer
},
DrawerToggler: function () {
return _Drawer.DrawerToggler
},
Eyebrow: function () {
return _Eyebrow.default
},
Gutter: function () {
return _Gutter.Gutter
},
ListDrawer: function () {
return _ListDrawer.ListDrawer
},
ListDrawerBaseClass: function () {
return _ListDrawer.baseClass
},
ListDrawerToggler: function () {
return _ListDrawer.ListDrawerToggler
},
Nav: function () {
return _Nav.default
},
formatDrawerSlug: function () {
return _Drawer.formatDrawerSlug
},
formatListDrawerSlug: function () {
return _ListDrawer.formatListDrawerSlug
},
useDocumentDrawer: function () {
return _DocumentDrawer.useDocumentDrawer
},
useDrawerSlug: function () {
return _useDrawerSlug.useDrawerSlug
},
useListDrawer: function () {
return _ListDrawer.useListDrawer
},
})
const _Button = /*#__PURE__*/ _interop_require_default(
require('../dist/admin/components/elements/Button'),
)
const _Card = /*#__PURE__*/ _interop_require_default(
require('../dist/admin/components/elements/Card'),
)
const _DocumentDrawer = require('../dist/admin/components/elements/DocumentDrawer')
const _Drawer = require('../dist/admin/components/elements/Drawer')
const _useDrawerSlug = require('../dist/admin/components/elements/Drawer/useDrawerSlug')
const _Eyebrow = /*#__PURE__*/ _interop_require_default(
require('../dist/admin/components/elements/Eyebrow'),
)
const _Gutter = require('../dist/admin/components/elements/Gutter')
const _ListDrawer = require('../dist/admin/components/elements/ListDrawer')
const _Nav = /*#__PURE__*/ _interop_require_default(
require('../dist/admin/components/elements/Nav'),
)
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
return obj && obj.__esModule
? obj
: {
default: obj,
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9leHBvcnRzL2NvbXBvbmVudHMvZWxlbWVudHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgZGVmYXVsdCBhcyBCdXR0b24gfSBmcm9tICcuLi8uLi9hZG1pbi9jb21wb25lbnRzL2VsZW1lbnRzL0J1dHRvbidcbmV4cG9ydCB7IGRlZmF1bHQgYXMgQ2FyZCB9IGZyb20gJy4uLy4uL2FkbWluL2NvbXBvbmVudHMvZWxlbWVudHMvQ2FyZCdcbmV4cG9ydCB7IGRlZmF1bHQgYXMgRXllYnJvdyB9IGZyb20gJy4uLy4uL2FkbWluL2NvbXBvbmVudHMvZWxlbWVudHMvRXllYnJvdydcbmV4cG9ydCB7IEd1dHRlciB9IGZyb20gJy4uLy4uL2FkbWluL2NvbXBvbmVudHMvZWxlbWVudHMvR3V0dGVyJ1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBOYXYgfSBmcm9tICcuLi8uLi9hZG1pbi9jb21wb25lbnRzL2VsZW1lbnRzL05hdidcbiJdLCJuYW1lcyI6WyJCdXR0b24iLCJDYXJkIiwiRXllYnJvdyIsIkd1dHRlciIsIk5hdiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7SUFBb0JBLE1BQU07ZUFBTkEsZUFBTTs7SUFDTkMsSUFBSTtlQUFKQSxhQUFJOztJQUNKQyxPQUFPO2VBQVBBLGdCQUFPOztJQUNsQkMsTUFBTTtlQUFOQSxjQUFNOztJQUNLQyxHQUFHO2VBQUhBLFlBQUc7OzsrREFKVzs2REFDRjtnRUFDRzt3QkFDWjs0REFDUSJ9
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9leHBvcnRzL2NvbXBvbmVudHMvZWxlbWVudHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgZGVmYXVsdCBhcyBCdXR0b24gfSBmcm9tICcuLi8uLi9hZG1pbi9jb21wb25lbnRzL2VsZW1lbnRzL0J1dHRvbidcbmV4cG9ydCB7IGRlZmF1bHQgYXMgQ2FyZCB9IGZyb20gJy4uLy4uL2FkbWluL2NvbXBvbmVudHMvZWxlbWVudHMvQ2FyZCdcbmV4cG9ydCB7XG4gIERvY3VtZW50RHJhd2VyLFxuICBEb2N1bWVudERyYXdlclRvZ2dsZXIsXG4gIGJhc2VDbGFzcyBhcyBEb2N1bWVudERyYXdlckJhc2VDbGFzcyxcbiAgdXNlRG9jdW1lbnREcmF3ZXIsXG59IGZyb20gJy4uLy4uL2FkbWluL2NvbXBvbmVudHMvZWxlbWVudHMvRG9jdW1lbnREcmF3ZXInXG5leHBvcnQgeyBEcmF3ZXIsIERyYXdlclRvZ2dsZXIsIGZvcm1hdERyYXdlclNsdWcgfSBmcm9tICcuLi8uLi9hZG1pbi9jb21wb25lbnRzL2VsZW1lbnRzL0RyYXdlcidcbmV4cG9ydCB7IHVzZURyYXdlclNsdWcgfSBmcm9tICcuLi8uLi9hZG1pbi9jb21wb25lbnRzL2VsZW1lbnRzL0RyYXdlci91c2VEcmF3ZXJTbHVnJ1xuXG5leHBvcnQgeyBkZWZhdWx0IGFzIEV5ZWJyb3cgfSBmcm9tICcuLi8uLi9hZG1pbi9jb21wb25lbnRzL2VsZW1lbnRzL0V5ZWJyb3cnXG5cbmV4cG9ydCB7IEd1dHRlciB9IGZyb20gJy4uLy4uL2FkbWluL2NvbXBvbmVudHMvZWxlbWVudHMvR3V0dGVyJ1xuZXhwb3J0IHtcbiAgTGlzdERyYXdlcixcbiAgTGlzdERyYXdlclRvZ2dsZXIsXG4gIGJhc2VDbGFzcyBhcyBMaXN0RHJhd2VyQmFzZUNsYXNzLFxuICBmb3JtYXRMaXN0RHJhd2VyU2x1ZyxcbiAgdXNlTGlzdERyYXdlcixcbn0gZnJvbSAnLi4vLi4vYWRtaW4vY29tcG9uZW50cy9lbGVtZW50cy9MaXN0RHJhd2VyJ1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBOYXYgfSBmcm9tICcuLi8uLi9hZG1pbi9jb21wb25lbnRzL2VsZW1lbnRzL05hdidcbiJdLCJuYW1lcyI6WyJCdXR0b24iLCJDYXJkIiwiRG9jdW1lbnREcmF3ZXIiLCJEb2N1bWVudERyYXdlclRvZ2dsZXIiLCJEb2N1bWVudERyYXdlckJhc2VDbGFzcyIsImJhc2VDbGFzcyIsInVzZURvY3VtZW50RHJhd2VyIiwiRHJhd2VyIiwiRHJhd2VyVG9nZ2xlciIsImZvcm1hdERyYXdlclNsdWciLCJ1c2VEcmF3ZXJTbHVnIiwiRXllYnJvdyIsIkd1dHRlciIsIkxpc3REcmF3ZXIiLCJMaXN0RHJhd2VyVG9nZ2xlciIsIkxpc3REcmF3ZXJCYXNlQ2xhc3MiLCJmb3JtYXRMaXN0RHJhd2VyU2x1ZyIsInVzZUxpc3REcmF3ZXIiLCJOYXYiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0lBQW9CQSxNQUFNO2VBQU5BLGVBQU07O0lBQ05DLElBQUk7ZUFBSkEsYUFBSTs7SUFFdEJDLGNBQWM7ZUFBZEEsOEJBQWM7O0lBQ2RDLHFCQUFxQjtlQUFyQkEscUNBQXFCOztJQUNSQyx1QkFBdUI7ZUFBcENDLHlCQUFTOztJQUNUQyxpQkFBaUI7ZUFBakJBLGlDQUFpQjs7SUFFVkMsTUFBTTtlQUFOQSxjQUFNOztJQUFFQyxhQUFhO2VBQWJBLHFCQUFhOztJQUFFQyxnQkFBZ0I7ZUFBaEJBLHdCQUFnQjs7SUFDdkNDLGFBQWE7ZUFBYkEsNEJBQWE7O0lBRUZDLE9BQU87ZUFBUEEsZ0JBQU87O0lBRWxCQyxNQUFNO2VBQU5BLGNBQU07O0lBRWJDLFVBQVU7ZUFBVkEsc0JBQVU7O0lBQ1ZDLGlCQUFpQjtlQUFqQkEsNkJBQWlCOztJQUNKQyxtQkFBbUI7ZUFBaENWLHFCQUFTOztJQUNUVyxvQkFBb0I7ZUFBcEJBLGdDQUFvQjs7SUFDcEJDLGFBQWE7ZUFBYkEseUJBQWE7O0lBRUtDLEdBQUc7ZUFBSEEsWUFBRzs7OytEQXJCVzs2REFDRjtnQ0FNekI7d0JBQ2lEOytCQUMxQjtnRUFFSzt3QkFFWjs0QkFPaEI7NERBQ3dCIn0=

View File

@@ -1,2 +1,2 @@
export type { Props } from '../../dist/admin/components/forms/field-types/Array/types';
export type { Props } from '../../dist/admin/components/forms/field-types/Array/types'
//# sourceMappingURL=Array.d.ts.map

View File

@@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
'use strict'
Object.defineProperty(exports, '__esModule', {
value: true,
})
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9

View File

@@ -1,2 +1,2 @@
export type { Props } from '../../dist/admin/components/forms/field-types/Blocks/types';
export type { Props } from '../../dist/admin/components/forms/field-types/Blocks/types'
//# sourceMappingURL=Blocks.d.ts.map

View File

@@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
'use strict'
Object.defineProperty(exports, '__esModule', {
value: true,
})
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9

View File

@@ -1,2 +1,2 @@
export type { Props } from '../../dist/admin/components/views/collections/List/Cell/types';
export type { Props } from '../../dist/admin/components/views/collections/List/Cell/types'
//# sourceMappingURL=Cell.d.ts.map

View File

@@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
'use strict'
Object.defineProperty(exports, '__esModule', {
value: true,
})
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9

View File

@@ -1,2 +1,2 @@
export type { Props } from '../../dist/admin/components/forms/field-types/Checkbox/types';
export type { Props } from '../../dist/admin/components/forms/field-types/Checkbox/types'
//# sourceMappingURL=Checkbox.d.ts.map

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