chore: initial next poc
This commit is contained in:
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -27,7 +27,7 @@
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm run dev:postgres fields",
|
||||
"command": "pnpm run dev:postgres versions",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Postgres",
|
||||
"request": "launch",
|
||||
|
||||
@@ -11,6 +11,13 @@
|
||||
"url": "https://payloadcms.com"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./src/index.ts",
|
||||
"require": "./src/index.ts",
|
||||
"types": "./src/index.ts"
|
||||
}
|
||||
},
|
||||
"types": "./dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "pnpm build:swc && pnpm build:types",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import type { CreateMigration } from 'payload/database'
|
||||
// import type { CreateMigration } from 'payload/database'
|
||||
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
@@ -18,11 +18,7 @@ ${downSQL ?? ` // Migration code`}
|
||||
};
|
||||
`
|
||||
|
||||
export const createMigration: CreateMigration = async function createMigration({
|
||||
file,
|
||||
migrationName,
|
||||
payload,
|
||||
}) {
|
||||
export const createMigration = async function createMigration({ file, migrationName, payload }) {
|
||||
const dir = payload.db.migrationDir
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir)
|
||||
@@ -38,8 +34,8 @@ export const createMigration: CreateMigration = async function createMigration({
|
||||
|
||||
// Check if predefined migration exists
|
||||
if (fs.existsSync(cleanPath)) {
|
||||
const { down, up } = require(cleanPath)
|
||||
migrationFileContent = migrationTemplate(up, down)
|
||||
// const { down, up } = require(cleanPath)
|
||||
// migrationFileContent = migrationTemplate(up, down)
|
||||
} else {
|
||||
payload.logger.error({
|
||||
msg: `Canned migration ${predefinedMigrationName} not found.`,
|
||||
|
||||
5
packages/dev/next-env.d.ts
vendored
Normal file
5
packages/dev/next-env.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
15
packages/dev/next.config.js
Normal file
15
packages/dev/next.config.js
Normal file
@@ -0,0 +1,15 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// experimental: {
|
||||
// serverComponentsExternalPackages: ['@payloadcms/db-mongodb'],
|
||||
// },
|
||||
// transpilePackages: ['@payloadcms/db-mongodb'],
|
||||
webpack: (config) => {
|
||||
return {
|
||||
...config,
|
||||
externals: [...config.externals, 'mongoose'],
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = nextConfig
|
||||
25
packages/dev/package.json
Normal file
25
packages/dev/package.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "dev",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "14.0.2-canary.18",
|
||||
"react": "^18",
|
||||
"react-dom": "^18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@payloadcms/db-mongodb": "workspace:*",
|
||||
"@payloadcms/richtext-lexical": "workspace:*",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"payload": "workspace:*",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
4
packages/dev/src/app/(payload)/admin/page.tsx
Normal file
4
packages/dev/src/app/(payload)/admin/page.tsx
Normal file
@@ -0,0 +1,4 @@
|
||||
import { dashboard } from 'payload/pages'
|
||||
import config from '../../../payload.config'
|
||||
|
||||
export default dashboard({ config })
|
||||
@@ -0,0 +1,4 @@
|
||||
import { initHandler } from 'payload/handlers'
|
||||
import config from 'payload-config'
|
||||
|
||||
export const GET = initHandler({ config })
|
||||
12
packages/dev/src/app/(payload)/layout.tsx
Normal file
12
packages/dev/src/app/(payload)/layout.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
export const metadata = {
|
||||
title: 'Next.js',
|
||||
description: 'Generated by Next.js',
|
||||
}
|
||||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
5
packages/dev/src/app/my-route/route.ts
Normal file
5
packages/dev/src/app/my-route/route.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export const GET = (request) => {
|
||||
return Response.json({
|
||||
hello: 'elliot',
|
||||
})
|
||||
}
|
||||
11
packages/dev/src/payload.config.ts
Normal file
11
packages/dev/src/payload.config.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { mongooseAdapter } from '@payloadcms/db-mongodb'
|
||||
// import { lexicalEditor } from '@payloadcms/richtext-lexical'
|
||||
import { buildConfig } from 'payload/config'
|
||||
|
||||
export default buildConfig({
|
||||
db: mongooseAdapter({
|
||||
url: process.env.DATABASE_URI,
|
||||
}),
|
||||
// editor: lexicalEditor({}),
|
||||
secret: process.env.PAYLOAD_SECRET,
|
||||
})
|
||||
27
packages/dev/tsconfig.json
Normal file
27
packages/dev/tsconfig.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"payload-config": ["./src/payload.config.ts"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"],
|
||||
"references": [{ "path": "../payload" }]
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/nodemon.json",
|
||||
"exec": "ts-node ../../test/dev.ts -- -I",
|
||||
"ext": "ts,js,json",
|
||||
"ignore": [
|
||||
".git",
|
||||
"node_modules",
|
||||
"node_modules/**/node_modules",
|
||||
"src/admin",
|
||||
"src/**/*.spec.ts",
|
||||
"test/**/payload-types.ts"
|
||||
],
|
||||
"watch": ["src/**/*.ts", "../../test/", "../../packages/**/*.ts"],
|
||||
"stdin": false
|
||||
}
|
||||
@@ -54,59 +54,38 @@
|
||||
"@faceless-ui/scroll-info": "1.3.0",
|
||||
"@faceless-ui/window-info": "2.1.1",
|
||||
"@monaco-editor/react": "4.5.1",
|
||||
"@swc/core": "1.3.76",
|
||||
"@swc/register": "0.1.10",
|
||||
"body-parser": "1.20.2",
|
||||
"body-scroll-lock": "4.0.0-beta.0",
|
||||
"bson-objectid": "2.0.4",
|
||||
"compression": "1.7.4",
|
||||
"conf": "10.2.0",
|
||||
"connect-history-api-fallback": "1.6.0",
|
||||
"console-table-printer": "2.11.2",
|
||||
"dataloader": "2.2.2",
|
||||
"date-fns": "2.30.0",
|
||||
"deep-equal": "2.2.2",
|
||||
"deepmerge": "4.3.1",
|
||||
"dotenv": "8.6.0",
|
||||
"express": "4.18.2",
|
||||
"express-fileupload": "1.4.0",
|
||||
"express-rate-limit": "5.5.1",
|
||||
"file-type": "16.5.4",
|
||||
"find-up": "4.1.0",
|
||||
"flatley": "5.2.0",
|
||||
"fs-extra": "10.1.0",
|
||||
"get-tsconfig": "4.6.2",
|
||||
"graphql": "16.8.1",
|
||||
"graphql-http": "1.21.0",
|
||||
"graphql-playground-middleware-express": "1.7.23",
|
||||
"graphql-query-complexity": "0.12.0",
|
||||
"graphql-scalars": "1.22.2",
|
||||
"graphql-type-json": "0.3.2",
|
||||
"html-webpack-plugin": "5.5.3",
|
||||
"http-status": "1.6.2",
|
||||
"i18next": "22.5.1",
|
||||
"i18next-browser-languagedetector": "6.1.8",
|
||||
"i18next-http-middleware": "3.3.2",
|
||||
"is-hotkey": "0.2.0",
|
||||
"is-plain-object": "5.0.0",
|
||||
"isomorphic-fetch": "3.0.0",
|
||||
"joi": "17.9.2",
|
||||
"json-schema-to-typescript": "11.0.3",
|
||||
"jsonwebtoken": "9.0.1",
|
||||
"jwt-decode": "3.1.2",
|
||||
"md5": "2.3.0",
|
||||
"method-override": "3.0.0",
|
||||
"micro-memoize": "4.1.2",
|
||||
"minimist": "1.2.8",
|
||||
"mkdirp": "1.0.4",
|
||||
"monaco-editor": "0.38.0",
|
||||
"nodemailer": "6.9.4",
|
||||
"object-to-formdata": "4.5.1",
|
||||
"passport": "0.6.0",
|
||||
"passport-anonymous": "1.0.1",
|
||||
"passport-headerapikey": "1.2.2",
|
||||
"passport-jwt": "4.0.1",
|
||||
"passport-local": "1.0.0",
|
||||
"pino": "8.15.0",
|
||||
"pino-pretty": "10.2.0",
|
||||
"pluralize": "8.0.0",
|
||||
@@ -114,25 +93,17 @@
|
||||
"process": "0.11.10",
|
||||
"qs": "6.11.2",
|
||||
"qs-middleware": "1.0.3",
|
||||
"react": "18.2.0",
|
||||
"react-animate-height": "2.1.2",
|
||||
"react-datepicker": "4.16.0",
|
||||
"react-diff-viewer-continued": "3.2.6",
|
||||
"react-dom": "18.2.0",
|
||||
"react-helmet": "6.1.0",
|
||||
"react-i18next": "11.18.6",
|
||||
"react-image-crop": "10.1.8",
|
||||
"react-router-dom": "5.3.4",
|
||||
"react-router-navigation-prompt": "1.9.6",
|
||||
"react-select": "5.7.4",
|
||||
"react-toastify": "8.2.0",
|
||||
"sanitize-filename": "1.6.3",
|
||||
"sass": "1.69.4",
|
||||
"scheduler": "0.23.0",
|
||||
"scmp": "2.1.0",
|
||||
"sharp": "0.32.6",
|
||||
"swc-loader": "0.2.3",
|
||||
"terser-webpack-plugin": "5.3.9",
|
||||
"ts-essentials": "7.0.3",
|
||||
"use-context-selector": "1.4.1",
|
||||
"uuid": "8.3.2"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
import type { ClientConfig } from '../../../exports/config'
|
||||
|
||||
export const ClientComponent: React.FC<{ config: ClientConfig }> = ({ config }) => {
|
||||
return (
|
||||
<p>
|
||||
This is a test client component and I have received the Payload config via props. No Webpack
|
||||
aliases required!
|
||||
</p>
|
||||
)
|
||||
}
|
||||
18
packages/payload/src/admin/pages/dashboard/index.tsx
Normal file
18
packages/payload/src/admin/pages/dashboard/index.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from 'react'
|
||||
|
||||
import type { SanitizedConfig } from '../../../config/types'
|
||||
|
||||
import { createClientConfig } from '../../../config/createClientConfig'
|
||||
import { ClientComponent } from './TestClientComponent'
|
||||
|
||||
export const dashboard = ({ config: configPromise }: { config: Promise<SanitizedConfig> }) =>
|
||||
async function () {
|
||||
const config = await createClientConfig(configPromise)
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<h1>Dashboard (rendered on server)</h1>
|
||||
<ClientComponent config={config} />
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
17
packages/payload/src/auth/handlers/init.ts
Normal file
17
packages/payload/src/auth/handlers/init.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { SanitizedConfig } from '../../exports/config'
|
||||
|
||||
import { getPayload } from '../..'
|
||||
import init from '../operations/init'
|
||||
|
||||
export const initHandler = ({ config }: { config: Promise<SanitizedConfig> }) =>
|
||||
async function (request: Request, { params }: { params: { collection: string } }) {
|
||||
const payload = await getPayload({ config })
|
||||
request.payload = payload
|
||||
|
||||
const initialized = await init({
|
||||
collection: params.collection,
|
||||
req: request,
|
||||
})
|
||||
|
||||
return Response.json({ initialized })
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import type { PayloadRequest } from '../../express/types'
|
||||
|
||||
import init from '../operations/init'
|
||||
|
||||
export default async function initHandler(
|
||||
req: PayloadRequest,
|
||||
res: Response,
|
||||
next: NextFunction,
|
||||
): Promise<any> {
|
||||
try {
|
||||
const initialized = await init({
|
||||
collection: req.collection.config.slug,
|
||||
req,
|
||||
})
|
||||
return res.status(200).json({ initialized })
|
||||
} catch (error) {
|
||||
return next(error)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { MarkOptional } from 'ts-essentials'
|
||||
|
||||
import crypto from 'crypto'
|
||||
import fs from 'fs'
|
||||
import { promisify } from 'util'
|
||||
// import fs from 'fs'
|
||||
// import { promisify } from 'util'
|
||||
|
||||
import type { GeneratedTypes } from '../../'
|
||||
import type { PayloadRequest } from '../../express/types'
|
||||
@@ -22,9 +22,9 @@ import { afterChange } from '../../fields/hooks/afterChange'
|
||||
import { afterRead } from '../../fields/hooks/afterRead'
|
||||
import { beforeChange } from '../../fields/hooks/beforeChange'
|
||||
import { beforeValidate } from '../../fields/hooks/beforeValidate'
|
||||
import { generateFileData } from '../../uploads/generateFileData'
|
||||
// import { generateFileData } from '../../uploads/generateFileData'
|
||||
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles'
|
||||
import { uploadFiles } from '../../uploads/uploadFiles'
|
||||
// import { uploadFiles } from '../../uploads/uploadFiles'
|
||||
import { commitTransaction } from '../../utilities/commitTransaction'
|
||||
import { initTransaction } from '../../utilities/initTransaction'
|
||||
import { killTransaction } from '../../utilities/killTransaction'
|
||||
@@ -32,7 +32,7 @@ import sanitizeInternalFields from '../../utilities/sanitizeInternalFields'
|
||||
import { saveVersion } from '../../versions/saveVersion'
|
||||
import { buildAfterOperation } from './utils'
|
||||
|
||||
const unlinkFile = promisify(fs.unlink)
|
||||
// const unlinkFile = promisify(fs.unlink)
|
||||
|
||||
export type CreateUpdateType = { [field: number | string | symbol]: unknown }
|
||||
|
||||
@@ -123,17 +123,17 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
// Generate data for all files and sizes
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { data: newFileData, files: filesToUpload } = await generateFileData({
|
||||
collection,
|
||||
config,
|
||||
data,
|
||||
overwriteExistingFiles,
|
||||
req,
|
||||
throwOnMissingFile:
|
||||
!shouldSaveDraft && collection.config.upload.filesRequiredOnCreate !== false,
|
||||
})
|
||||
// const { data: newFileData, files: filesToUpload } = await generateFileData({
|
||||
// collection,
|
||||
// config,
|
||||
// data,
|
||||
// overwriteExistingFiles,
|
||||
// req,
|
||||
// throwOnMissingFile:
|
||||
// !shouldSaveDraft && collection.config.upload.filesRequiredOnCreate !== false,
|
||||
// })
|
||||
|
||||
data = newFileData
|
||||
// data = newFileData
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeValidate - Fields
|
||||
@@ -174,9 +174,9 @@ async function create<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
// Write files to local storage
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!collectionConfig.upload.disableLocalStorage) {
|
||||
await uploadFiles(payload, filesToUpload, req.t)
|
||||
}
|
||||
// if (!collectionConfig.upload.disableLocalStorage) {
|
||||
// await uploadFiles(payload, filesToUpload, req.t)
|
||||
// }
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeChange - Collection
|
||||
|
||||
@@ -17,10 +17,10 @@ import { afterChange } from '../../fields/hooks/afterChange'
|
||||
import { afterRead } from '../../fields/hooks/afterRead'
|
||||
import { beforeChange } from '../../fields/hooks/beforeChange'
|
||||
import { beforeValidate } from '../../fields/hooks/beforeValidate'
|
||||
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles'
|
||||
import { generateFileData } from '../../uploads/generateFileData'
|
||||
// import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles'
|
||||
// import { generateFileData } from '../../uploads/generateFileData'
|
||||
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles'
|
||||
import { uploadFiles } from '../../uploads/uploadFiles'
|
||||
// import { uploadFiles } from '../../uploads/uploadFiles'
|
||||
import { commitTransaction } from '../../utilities/commitTransaction'
|
||||
import { initTransaction } from '../../utilities/initTransaction'
|
||||
import { killTransaction } from '../../utilities/killTransaction'
|
||||
@@ -151,21 +151,20 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
// Generate data for all files and sizes
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { data: newFileData, files: filesToUpload } = await generateFileData({
|
||||
collection,
|
||||
config,
|
||||
data: bulkUpdateData,
|
||||
overwriteExistingFiles,
|
||||
req,
|
||||
throwOnMissingFile: false,
|
||||
})
|
||||
// const { data: newFileData, files: filesToUpload } = await generateFileData({
|
||||
// collection,
|
||||
// config,
|
||||
// data: bulkUpdateData,
|
||||
// overwriteExistingFiles,
|
||||
// req,
|
||||
// throwOnMissingFile: false,
|
||||
// })
|
||||
|
||||
const errors = []
|
||||
|
||||
const promises = docs.map(async (doc) => {
|
||||
const { id } = doc
|
||||
let data = {
|
||||
...newFileData,
|
||||
...bulkUpdateData,
|
||||
}
|
||||
|
||||
@@ -181,14 +180,14 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
showHiddenFields: true,
|
||||
})
|
||||
|
||||
await deleteAssociatedFiles({
|
||||
collectionConfig,
|
||||
config,
|
||||
doc,
|
||||
files: filesToUpload,
|
||||
overrideDelete: false,
|
||||
t,
|
||||
})
|
||||
// await deleteAssociatedFiles({
|
||||
// collectionConfig,
|
||||
// config,
|
||||
// doc,
|
||||
// // files: filesToUpload,
|
||||
// overrideDelete: false,
|
||||
// t,
|
||||
// })
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeValidate - Fields
|
||||
@@ -228,9 +227,9 @@ async function update<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
// Write files to local storage
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!collectionConfig.upload.disableLocalStorage) {
|
||||
await uploadFiles(payload, filesToUpload, t)
|
||||
}
|
||||
// if (!collectionConfig.upload.disableLocalStorage) {
|
||||
// await uploadFiles(payload, filesToUpload, t)
|
||||
// }
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeChange - Collection
|
||||
|
||||
@@ -16,10 +16,10 @@ import { afterChange } from '../../fields/hooks/afterChange'
|
||||
import { afterRead } from '../../fields/hooks/afterRead'
|
||||
import { beforeChange } from '../../fields/hooks/beforeChange'
|
||||
import { beforeValidate } from '../../fields/hooks/beforeValidate'
|
||||
import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles'
|
||||
import { generateFileData } from '../../uploads/generateFileData'
|
||||
// import { deleteAssociatedFiles } from '../../uploads/deleteAssociatedFiles'
|
||||
// import { generateFileData } from '../../uploads/generateFileData'
|
||||
import { unlinkTempFiles } from '../../uploads/unlinkTempFiles'
|
||||
import { uploadFiles } from '../../uploads/uploadFiles'
|
||||
// import { uploadFiles } from '../../uploads/uploadFiles'
|
||||
import { commitTransaction } from '../../utilities/commitTransaction'
|
||||
import { initTransaction } from '../../utilities/initTransaction'
|
||||
import { killTransaction } from '../../utilities/killTransaction'
|
||||
@@ -139,29 +139,29 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
// Generate data for all files and sizes
|
||||
// /////////////////////////////////////
|
||||
|
||||
const { data: newFileData, files: filesToUpload } = await generateFileData({
|
||||
collection,
|
||||
config,
|
||||
data,
|
||||
overwriteExistingFiles,
|
||||
req,
|
||||
throwOnMissingFile: false,
|
||||
})
|
||||
// const { data: newFileData, files: filesToUpload } = await generateFileData({
|
||||
// collection,
|
||||
// config,
|
||||
// data,
|
||||
// overwriteExistingFiles,
|
||||
// req,
|
||||
// throwOnMissingFile: false,
|
||||
// })
|
||||
|
||||
data = newFileData
|
||||
// data = newFileData
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Delete any associated files
|
||||
// /////////////////////////////////////
|
||||
|
||||
await deleteAssociatedFiles({
|
||||
collectionConfig,
|
||||
config,
|
||||
doc: docWithLocales,
|
||||
files: filesToUpload,
|
||||
overrideDelete: false,
|
||||
t,
|
||||
})
|
||||
// await deleteAssociatedFiles({
|
||||
// collectionConfig,
|
||||
// config,
|
||||
// doc: docWithLocales,
|
||||
// files: filesToUpload,
|
||||
// overrideDelete: false,
|
||||
// t,
|
||||
// })
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeValidate - Fields
|
||||
@@ -201,9 +201,9 @@ async function updateByID<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
// Write files to local storage
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (!collectionConfig.upload.disableLocalStorage) {
|
||||
await uploadFiles(payload, filesToUpload, t)
|
||||
}
|
||||
// if (!collectionConfig.upload.disableLocalStorage) {
|
||||
// await uploadFiles(payload, filesToUpload, t)
|
||||
// }
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeChange - Collection
|
||||
|
||||
54
packages/payload/src/config/createClientConfig.ts
Normal file
54
packages/payload/src/config/createClientConfig.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import type { Field } from '../fields/config/types'
|
||||
import type { ClientConfig, SanitizedConfig } from './types'
|
||||
|
||||
const sanitizeFields = (fields: Field[]): Field[] =>
|
||||
fields.map((field) => {
|
||||
const sanitized = { ...field }
|
||||
|
||||
if ('access' in field) delete field.access
|
||||
if ('hooks' in field) delete field.hooks
|
||||
if ('validate' in field) delete field.validate
|
||||
if ('defaultValue' in field) delete field.defaultValue
|
||||
|
||||
if ('fields' in field) {
|
||||
field.fields = sanitizeFields(field.fields)
|
||||
}
|
||||
|
||||
if ('admin' in field) {
|
||||
if ('components' in field.admin) {
|
||||
delete field.admin.components
|
||||
}
|
||||
}
|
||||
|
||||
return sanitized
|
||||
})
|
||||
|
||||
export const createClientConfig = async (
|
||||
configPromise: Promise<SanitizedConfig>,
|
||||
): Promise<ClientConfig> => {
|
||||
const config = await configPromise
|
||||
const clientConfig = { ...config }
|
||||
|
||||
delete clientConfig.endpoints
|
||||
delete clientConfig.db
|
||||
|
||||
clientConfig.collections = config.collections.map((collection) => {
|
||||
const sanitized = { ...collection }
|
||||
sanitized.fields = sanitizeFields(sanitized.fields)
|
||||
delete sanitized.hooks
|
||||
delete sanitized.access
|
||||
delete sanitized.endpoints
|
||||
return sanitized
|
||||
})
|
||||
|
||||
clientConfig.globals = config.globals.map((global) => {
|
||||
const sanitized = { ...global }
|
||||
sanitized.fields = sanitizeFields(sanitized.fields)
|
||||
delete sanitized.hooks
|
||||
delete sanitized.access
|
||||
delete sanitized.endpoints
|
||||
return sanitized
|
||||
})
|
||||
|
||||
return clientConfig
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import type {
|
||||
} from '../collections/config/types'
|
||||
import type { BaseDatabaseAdapter } from '../database/types'
|
||||
import type { PayloadRequest } from '../express/types'
|
||||
import type { ClientConfigField, Field } from '../fields/config/types'
|
||||
import type { GlobalConfig, SanitizedGlobalConfig } from '../globals/config/types'
|
||||
import type { Payload } from '../payload'
|
||||
import type { Where } from '../types'
|
||||
@@ -118,8 +119,7 @@ export type InitOptions = {
|
||||
* The passed config should match the config file, and if it doesn't, there could be mismatches between the admin UI
|
||||
* and the backend functionality
|
||||
*/
|
||||
config?: Promise<SanitizedConfig>
|
||||
|
||||
config: Promise<SanitizedConfig>
|
||||
/**
|
||||
* Disable connect to the database on init
|
||||
*/
|
||||
@@ -149,20 +149,17 @@ export type InitOptions = {
|
||||
local?: boolean
|
||||
|
||||
loggerDestination?: DestinationStream
|
||||
|
||||
/**
|
||||
* Specify options for the built-in Pino logger that Payload uses for internal logging.
|
||||
*
|
||||
* See Pino Docs for options: https://getpino.io/#/docs/api?id=options
|
||||
*/
|
||||
loggerOptions?: LoggerOptions
|
||||
|
||||
/**
|
||||
* A function that is called immediately following startup that receives the Payload instance as it's only argument.
|
||||
*/
|
||||
onInit?: (payload: Payload) => Promise<void> | void
|
||||
|
||||
/** Secure string that Payload will use for any encryption workflows */
|
||||
secret: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,12 +506,12 @@ export type Config = {
|
||||
cookiePrefix?: string
|
||||
/** Either a whitelist array of URLS to allow CORS requests from, or a wildcard string ('*') to accept incoming requests from any domain. */
|
||||
cors?: '*' | string[]
|
||||
|
||||
/** A whitelist array of URLs to allow Payload cookies to be accepted from as a form of CSRF protection. */
|
||||
csrf?: string[]
|
||||
|
||||
/** Extension point to add your custom data. */
|
||||
custom?: Record<string, any>
|
||||
|
||||
/** Pass in a database adapter for use on this project. */
|
||||
db: (args: { payload: Payload }) => BaseDatabaseAdapter
|
||||
/** Enable to expose more detailed error information. */
|
||||
@@ -666,6 +663,8 @@ export type Config = {
|
||||
/** @default "/playground" */
|
||||
graphQLPlayground?: string
|
||||
}
|
||||
/** Secure string that Payload will use for any encryption workflows */
|
||||
secret: string
|
||||
/**
|
||||
* Define the absolute URL of your app including the protocol, for example `https://example.org`.
|
||||
* No paths allowed, only protocol, domain and (optionally) port.
|
||||
@@ -703,6 +702,15 @@ export type SanitizedConfig = Omit<
|
||||
}
|
||||
}
|
||||
|
||||
export type ClientConfig = Omit<SanitizedConfig, 'db' | 'endpoints' | 'webpack'> & {
|
||||
collections: (Omit<SanitizedCollectionConfig, 'access' | 'endpoints' | 'fields' | 'hooks'> & {
|
||||
fields: ClientConfigField[]
|
||||
})[]
|
||||
globals: (Omit<SanitizedGlobalConfig, 'access' | 'endpoints' | 'fields' | 'hooks'> & {
|
||||
fields: ClientConfigField[]
|
||||
})[]
|
||||
}
|
||||
|
||||
export type EntityDescription =
|
||||
| (() => string)
|
||||
| React.ComponentType<any>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import type { Payload } from '../../'
|
||||
import type { Migration } from '../types'
|
||||
// import type { Payload } from '../../'
|
||||
// import type { Migration } from '../types'
|
||||
|
||||
/**
|
||||
* Read the migration files from disk
|
||||
@@ -27,10 +27,12 @@ export const readMigrationFiles = async ({
|
||||
return path.resolve(payload.db.migrationDir, file)
|
||||
})
|
||||
|
||||
return files.map((filePath) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-dynamic-require
|
||||
const migration = require(filePath) as Migration
|
||||
migration.name = path.basename(filePath).split('.')?.[0]
|
||||
return migration
|
||||
})
|
||||
return files
|
||||
|
||||
// return files.map((filePath) => {
|
||||
// // eslint-disable-next-line @typescript-eslint/no-var-requires,import/no-dynamic-require
|
||||
// const migration = require(filePath) as Migration
|
||||
// migration.name = path.basename(filePath).split('.')?.[0]
|
||||
// return migration
|
||||
// })
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export {
|
||||
export type {
|
||||
BaseDatabaseAdapter,
|
||||
BeginTransaction,
|
||||
CommitTransaction,
|
||||
@@ -78,7 +78,7 @@ export { migrationsCollection } from '../database/migrations/migrationsCollectio
|
||||
|
||||
export { readMigrationFiles } from '../database/migrations/readMigrationFiles'
|
||||
|
||||
export { EntityPolicies, PathToQuery } from '../database/queryValidation/types'
|
||||
export type { EntityPolicies, PathToQuery } from '../database/queryValidation/types'
|
||||
|
||||
export { validateQueryPaths } from '../database/queryValidation/validateQueryPaths'
|
||||
|
||||
|
||||
1
packages/payload/src/exports/handlers.ts
Normal file
1
packages/payload/src/exports/handlers.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { initHandler } from '../auth/handlers/init'
|
||||
1
packages/payload/src/exports/pages.ts
Normal file
1
packages/payload/src/exports/pages.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { dashboard } from '../admin/pages/dashboard'
|
||||
@@ -15,7 +15,7 @@ export type {
|
||||
|
||||
export type { CellComponentProps } from '../admin/components/views/collections/List/Cell/types'
|
||||
|
||||
export { FileData, ImageSize, IncomingUploadType } from '../uploads/types'
|
||||
export type { FileData, ImageSize, IncomingUploadType } from '../uploads/types'
|
||||
|
||||
export type {
|
||||
CustomPublishButtonProps,
|
||||
|
||||
@@ -503,6 +503,8 @@ export type Field =
|
||||
| UIField
|
||||
| UploadField
|
||||
|
||||
export type ClientConfigField = Omit<Field, 'access' | 'defaultValue' | 'hooks' | 'validate'>
|
||||
|
||||
export type FieldAffectingData =
|
||||
| ArrayField
|
||||
| BlockField
|
||||
|
||||
@@ -1,35 +1,421 @@
|
||||
import type { TypeWithID } from './collections/config/types'
|
||||
import type { InitOptions } from './config/types'
|
||||
import type { BaseDatabaseAdapter } from './database/types'
|
||||
import type { Express, Router } from 'express'
|
||||
import type { ExecutionResult, GraphQLSchema, ValidationRule } from 'graphql'
|
||||
import type { OperationArgs, Request as graphQLRequest } from 'graphql-http/lib/handler'
|
||||
import type { SendMailOptions } from 'nodemailer'
|
||||
import type pino from 'pino'
|
||||
|
||||
import crypto from 'crypto'
|
||||
|
||||
import type { Result as ForgotPasswordResult } from './auth/operations/forgotPassword'
|
||||
import type { Options as ForgotPasswordOptions } from './auth/operations/local/forgotPassword'
|
||||
import type { Options as LoginOptions } from './auth/operations/local/login'
|
||||
import type { Options as ResetPasswordOptions } from './auth/operations/local/resetPassword'
|
||||
import type { Options as UnlockOptions } from './auth/operations/local/unlock'
|
||||
import type { Options as VerifyEmailOptions } from './auth/operations/local/verifyEmail'
|
||||
import type { Result as LoginResult } from './auth/operations/login'
|
||||
import type { Result as ResetPasswordResult } from './auth/operations/resetPassword'
|
||||
import type { BulkOperationResult, Collection, TypeWithID } from './collections/config/types'
|
||||
import type { Options as CreateOptions } from './collections/operations/local/create'
|
||||
import type {
|
||||
ByIDOptions as DeleteByIDOptions,
|
||||
ManyOptions as DeleteManyOptions,
|
||||
Options as DeleteOptions,
|
||||
} from './collections/operations/local/delete'
|
||||
import type { Options as FindOptions } from './collections/operations/local/find'
|
||||
import type { Options as FindByIDOptions } from './collections/operations/local/findByID'
|
||||
import type { Options as FindVersionByIDOptions } from './collections/operations/local/findVersionByID'
|
||||
import type { Options as FindVersionsOptions } from './collections/operations/local/findVersions'
|
||||
import type { Options as RestoreVersionOptions } from './collections/operations/local/restoreVersion'
|
||||
import type {
|
||||
ByIDOptions as UpdateByIDOptions,
|
||||
ManyOptions as UpdateManyOptions,
|
||||
Options as UpdateOptions,
|
||||
} from './collections/operations/local/update'
|
||||
import type { EmailOptions, InitOptions, SanitizedConfig } from './config/types'
|
||||
import type { PaginatedDocs } from './database/types'
|
||||
import type { BuildEmailResult } from './email/types'
|
||||
import type { ErrorHandler } from './express/middleware/errorHandler'
|
||||
import type { RequestContext } from './express/types'
|
||||
import type { TypeWithID as GlobalTypeWithID } from './globals/config/types'
|
||||
import type { Payload as LocalPayload } from './payload'
|
||||
import type { TypeWithID as GlobalTypeWithID, Globals } from './globals/config/types'
|
||||
import type { Options as FindGlobalOptions } from './globals/operations/local/findOne'
|
||||
import type { Options as FindGlobalVersionByIDOptions } from './globals/operations/local/findVersionByID'
|
||||
import type { Options as FindGlobalVersionsOptions } from './globals/operations/local/findVersions'
|
||||
import type { Options as RestoreGlobalVersionOptions } from './globals/operations/local/restoreVersion'
|
||||
import type { Options as UpdateGlobalOptions } from './globals/operations/local/update'
|
||||
import type { TypeWithVersion } from './versions/types'
|
||||
|
||||
import { initHTTP } from './initHTTP'
|
||||
import { BasePayload } from './payload'
|
||||
import { decrypt, encrypt } from './auth/crypto'
|
||||
import localOperations from './collections/operations/local'
|
||||
import buildEmail from './email/build'
|
||||
import { defaults as emailDefaults } from './email/defaults'
|
||||
import sendEmail from './email/sendEmail'
|
||||
import localGlobalOperations from './globals/operations/local'
|
||||
import registerGraphQLSchema from './graphql/registerSchema'
|
||||
import Logger from './utilities/logger'
|
||||
import { serverInit as serverInitTelemetry } from './utilities/telemetry/events/serverInit'
|
||||
|
||||
export { getPayload } from './payload'
|
||||
/**
|
||||
* @description Payload
|
||||
*/
|
||||
export class Payload<TGeneratedTypes extends GeneratedTypes> {
|
||||
Mutation: { fields: { [key: string]: any }; name: string } = { name: 'Mutation', fields: {} }
|
||||
|
||||
require('isomorphic-fetch')
|
||||
Query: { fields: { [key: string]: any }; name: string } = { name: 'Query', fields: {} }
|
||||
|
||||
export class Payload extends BasePayload<GeneratedTypes> {
|
||||
async init(options: InitOptions): Promise<LocalPayload> {
|
||||
const payload = await initHTTP(options)
|
||||
Object.assign(this, payload)
|
||||
collections: {
|
||||
[slug: number | string | symbol]: Collection
|
||||
} = {}
|
||||
|
||||
config: SanitizedConfig
|
||||
|
||||
/**
|
||||
* @description Performs create operation
|
||||
* @param options
|
||||
* @returns created document
|
||||
*/
|
||||
create = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: CreateOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]> => {
|
||||
const { create } = localOperations
|
||||
return create<T>(this, options)
|
||||
}
|
||||
|
||||
db: DatabaseAdapter
|
||||
|
||||
decrypt = decrypt
|
||||
|
||||
email: BuildEmailResult
|
||||
|
||||
emailOptions: EmailOptions
|
||||
|
||||
encrypt = encrypt
|
||||
|
||||
errorHandler: ErrorHandler
|
||||
|
||||
express?: Express
|
||||
|
||||
extensions: (args: {
|
||||
args: OperationArgs<any>
|
||||
req: graphQLRequest<unknown, unknown>
|
||||
result: ExecutionResult
|
||||
}) => Promise<any>
|
||||
|
||||
/**
|
||||
* @description Find documents with criteria
|
||||
* @param options
|
||||
* @returns documents satisfying query
|
||||
*/
|
||||
find = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: FindOptions<T>,
|
||||
): Promise<PaginatedDocs<TGeneratedTypes['collections'][T]>> => {
|
||||
const { find } = localOperations
|
||||
return find<T>(this, options)
|
||||
}
|
||||
|
||||
findByID = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: FindByIDOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]> => {
|
||||
const { findByID } = localOperations
|
||||
return findByID<T>(this, options)
|
||||
}
|
||||
|
||||
findGlobal = async <T extends keyof TGeneratedTypes['globals']>(
|
||||
options: FindGlobalOptions<T>,
|
||||
): Promise<TGeneratedTypes['globals'][T]> => {
|
||||
const { findOne } = localGlobalOperations
|
||||
return findOne<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Find global version by ID
|
||||
* @param options
|
||||
* @returns global version with specified ID
|
||||
*/
|
||||
findGlobalVersionByID = async <T extends keyof TGeneratedTypes['globals']>(
|
||||
options: FindGlobalVersionByIDOptions<T>,
|
||||
): Promise<TypeWithVersion<TGeneratedTypes['globals'][T]>> => {
|
||||
const { findVersionByID } = localGlobalOperations
|
||||
return findVersionByID<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Find global versions with criteria
|
||||
* @param options
|
||||
* @returns versions satisfying query
|
||||
*/
|
||||
findGlobalVersions = async <T extends keyof TGeneratedTypes['globals']>(
|
||||
options: FindGlobalVersionsOptions<T>,
|
||||
): Promise<PaginatedDocs<TypeWithVersion<TGeneratedTypes['globals'][T]>>> => {
|
||||
const { findVersions } = localGlobalOperations
|
||||
return findVersions<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Find version by ID
|
||||
* @param options
|
||||
* @returns version with specified ID
|
||||
*/
|
||||
findVersionByID = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: FindVersionByIDOptions<T>,
|
||||
): Promise<TypeWithVersion<TGeneratedTypes['collections'][T]>> => {
|
||||
const { findVersionByID } = localOperations
|
||||
return findVersionByID<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Find versions with criteria
|
||||
* @param options
|
||||
* @returns versions satisfying query
|
||||
*/
|
||||
findVersions = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: FindVersionsOptions<T>,
|
||||
): Promise<PaginatedDocs<TypeWithVersion<TGeneratedTypes['collections'][T]>>> => {
|
||||
const { findVersions } = localOperations
|
||||
return findVersions<T>(this, options)
|
||||
}
|
||||
|
||||
forgotPassword = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: ForgotPasswordOptions<T>,
|
||||
): Promise<ForgotPasswordResult> => {
|
||||
const { forgotPassword } = localOperations.auth
|
||||
return forgotPassword<T>(this, options)
|
||||
}
|
||||
|
||||
getAPIURL = (): string => `${this.config.serverURL}${this.config.routes.api}`
|
||||
|
||||
getAdminURL = (): string => `${this.config.serverURL}${this.config.routes.admin}`
|
||||
|
||||
globals: Globals
|
||||
|
||||
local: boolean
|
||||
|
||||
logger: pino.Logger
|
||||
|
||||
login = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: LoginOptions<T>,
|
||||
): Promise<LoginResult & { user: TGeneratedTypes['collections'][T] }> => {
|
||||
const { login } = localOperations.auth
|
||||
return login<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Find document by ID
|
||||
* @param options
|
||||
* @returns document with specified ID
|
||||
*/
|
||||
|
||||
resetPassword = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: ResetPasswordOptions<T>,
|
||||
): Promise<ResetPasswordResult> => {
|
||||
const { resetPassword } = localOperations.auth
|
||||
return resetPassword<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Restore global version by ID
|
||||
* @param options
|
||||
* @returns version with specified ID
|
||||
*/
|
||||
restoreGlobalVersion = async <T extends keyof TGeneratedTypes['globals']>(
|
||||
options: RestoreGlobalVersionOptions<T>,
|
||||
): Promise<TGeneratedTypes['globals'][T]> => {
|
||||
const { restoreVersion } = localGlobalOperations
|
||||
return restoreVersion<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Restore version by ID
|
||||
* @param options
|
||||
* @returns version with specified ID
|
||||
*/
|
||||
restoreVersion = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: RestoreVersionOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]> => {
|
||||
const { restoreVersion } = localOperations
|
||||
return restoreVersion<T>(this, options)
|
||||
}
|
||||
|
||||
router?: Router
|
||||
|
||||
schema: GraphQLSchema
|
||||
|
||||
secret: string
|
||||
|
||||
sendEmail: (message: SendMailOptions) => Promise<unknown>
|
||||
|
||||
types: {
|
||||
arrayTypes: any
|
||||
blockInputTypes: any
|
||||
blockTypes: any
|
||||
fallbackLocaleInputType?: any
|
||||
groupTypes: any
|
||||
localeInputType?: any
|
||||
tabTypes: any
|
||||
}
|
||||
|
||||
unlock = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: UnlockOptions<T>,
|
||||
): Promise<boolean> => {
|
||||
const { unlock } = localOperations.auth
|
||||
return unlock(this, options)
|
||||
}
|
||||
|
||||
updateGlobal = async <T extends keyof TGeneratedTypes['globals']>(
|
||||
options: UpdateGlobalOptions<T>,
|
||||
): Promise<TGeneratedTypes['globals'][T]> => {
|
||||
const { update } = localGlobalOperations
|
||||
return update<T>(this, options)
|
||||
}
|
||||
|
||||
validationRules: (args: OperationArgs<any>) => ValidationRule[]
|
||||
|
||||
verifyEmail = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: VerifyEmailOptions<T>,
|
||||
): Promise<boolean> => {
|
||||
const { verifyEmail } = localOperations.auth
|
||||
return verifyEmail(this, options)
|
||||
}
|
||||
|
||||
versions: {
|
||||
[slug: string]: any // TODO: Type this
|
||||
} = {}
|
||||
|
||||
delete<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: DeleteOptions<T>,
|
||||
): Promise<BulkOperationResult<T> | TGeneratedTypes['collections'][T]> {
|
||||
const { deleteLocal } = localOperations
|
||||
return deleteLocal<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description delete one or more documents
|
||||
* @param options
|
||||
* @returns Updated document(s)
|
||||
*/
|
||||
delete<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: DeleteByIDOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]>
|
||||
|
||||
delete<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: DeleteManyOptions<T>,
|
||||
): Promise<BulkOperationResult<T>>
|
||||
|
||||
/**
|
||||
* @description Initializes Payload
|
||||
* @param options
|
||||
*/
|
||||
// @ts-expect-error // TODO: TypeScript hallucinating again. fix later
|
||||
async init(options: InitOptions): Promise<Payload> {
|
||||
this.logger = Logger('payload', options.loggerOptions, options.loggerDestination)
|
||||
|
||||
this.config = await options.config
|
||||
|
||||
if (!this.config.secret) {
|
||||
throw new Error('Error: missing secret key. A secret key is needed to secure Payload.')
|
||||
}
|
||||
|
||||
this.secret = crypto.createHash('sha256').update(this.config.secret).digest('hex').slice(0, 32)
|
||||
|
||||
this.local = options.local
|
||||
|
||||
this.globals = {
|
||||
config: this.config.globals,
|
||||
}
|
||||
this.config.collections.forEach((collection) => {
|
||||
this.collections[collection.slug] = {
|
||||
config: collection,
|
||||
}
|
||||
})
|
||||
|
||||
this.db = this.config.db({ payload: this })
|
||||
this.db.payload = this
|
||||
|
||||
if (this.db?.init) {
|
||||
await this.db.init(this)
|
||||
}
|
||||
|
||||
if (!options.disableDBConnect && this.db.connect) {
|
||||
await this.db.connect(this)
|
||||
}
|
||||
|
||||
this.logger.info('Starting Payload...')
|
||||
|
||||
// Configure email service
|
||||
const emailOptions = options.email ? { ...options.email } : this.config.email
|
||||
if (options.email && this.config.email) {
|
||||
this.logger.warn(
|
||||
'Email options provided in both init options and config. Using init options.',
|
||||
)
|
||||
}
|
||||
|
||||
this.emailOptions = emailOptions ?? emailDefaults
|
||||
this.email = buildEmail(this.emailOptions, this.logger)
|
||||
this.sendEmail = sendEmail.bind(this)
|
||||
|
||||
if (!this.config.graphQL.disable) {
|
||||
registerGraphQLSchema(this)
|
||||
}
|
||||
|
||||
serverInitTelemetry(this)
|
||||
|
||||
if (!options.disableOnInit) {
|
||||
if (typeof options.onInit === 'function') await options.onInit(this)
|
||||
if (typeof this.config.onInit === 'function') await this.config.onInit(this)
|
||||
}
|
||||
|
||||
return payload
|
||||
return this
|
||||
}
|
||||
|
||||
update<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: UpdateManyOptions<T>,
|
||||
): Promise<BulkOperationResult<T>>
|
||||
|
||||
/**
|
||||
* @description Update one or more documents
|
||||
* @param options
|
||||
* @returns Updated document(s)
|
||||
*/
|
||||
update<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: UpdateByIDOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]>
|
||||
|
||||
update<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: UpdateOptions<T>,
|
||||
): Promise<BulkOperationResult<T> | TGeneratedTypes['collections'][T]> {
|
||||
const { update } = localOperations
|
||||
return update<T>(this, options)
|
||||
}
|
||||
}
|
||||
|
||||
const payload = new Payload()
|
||||
const initialized = new Payload()
|
||||
|
||||
export default payload
|
||||
module.exports = payload
|
||||
export default initialized
|
||||
|
||||
let cached = global._payload
|
||||
|
||||
if (!cached) {
|
||||
// eslint-disable-next-line no-multi-assign
|
||||
cached = global._payload = { payload: null, promise: null }
|
||||
}
|
||||
|
||||
export const getPayload = async (options?: InitOptions): Promise<Payload<GeneratedTypes>> => {
|
||||
if (cached.payload) {
|
||||
return cached.payload
|
||||
}
|
||||
|
||||
if (!cached.promise) {
|
||||
cached.promise = new Payload<GeneratedTypes>().init(options)
|
||||
}
|
||||
|
||||
try {
|
||||
cached.payload = await cached.promise
|
||||
} catch (e) {
|
||||
cached.promise = null
|
||||
throw e
|
||||
}
|
||||
|
||||
return cached.payload
|
||||
}
|
||||
|
||||
type GeneratedTypes = {
|
||||
collections: {
|
||||
@@ -40,6 +426,6 @@ type GeneratedTypes = {
|
||||
}
|
||||
}
|
||||
|
||||
type DatabaseAdapter = BaseDatabaseAdapter
|
||||
// type DatabaseAdapter = BaseDatabaseAdapter
|
||||
|
||||
export type { DatabaseAdapter, GeneratedTypes, RequestContext }
|
||||
export type { GeneratedTypes, RequestContext }
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { NextFunction, Response } from 'express'
|
||||
|
||||
import express from 'express'
|
||||
|
||||
import type { InitOptions } from './config/types'
|
||||
import type { PayloadRequest } from './express/types'
|
||||
import type { Payload } from './payload'
|
||||
|
||||
import initAuth from './auth/init'
|
||||
import access from './auth/requestHandlers/access'
|
||||
import { getDataLoader } from './collections/dataloader'
|
||||
import initCollectionsHTTP from './collections/initHTTP'
|
||||
import initAdmin from './express/admin'
|
||||
import expressMiddleware from './express/middleware'
|
||||
import authenticate from './express/middleware/authenticate'
|
||||
import errorHandler from './express/middleware/errorHandler'
|
||||
import identifyAPI from './express/middleware/identifyAPI'
|
||||
import mountEndpoints from './express/mountEndpoints'
|
||||
import initStatic from './express/static'
|
||||
import initGlobalsHTTP from './globals/initHTTP'
|
||||
import graphQLHandler from './graphql/graphQLHandler'
|
||||
import initGraphQLPlayground from './graphql/initPlayground'
|
||||
import { getPayload } from './payload'
|
||||
|
||||
export const initHTTP = async (incomingOptions: InitOptions): Promise<Payload> => {
|
||||
const options = { ...incomingOptions }
|
||||
if (typeof options.local === 'undefined') options.local = false
|
||||
|
||||
// Disable onInit because it will be called in top-level Payload
|
||||
options.disableOnInit = true
|
||||
|
||||
const payload = await getPayload(options)
|
||||
|
||||
if (!options.local) {
|
||||
payload.router = express.Router()
|
||||
payload.router.use(...expressMiddleware(payload))
|
||||
initAuth(payload)
|
||||
|
||||
initCollectionsHTTP(payload)
|
||||
initGlobalsHTTP(payload)
|
||||
|
||||
options.express.use((req: PayloadRequest, res, next) => {
|
||||
req.payload = payload
|
||||
next()
|
||||
})
|
||||
|
||||
options.express.use((req: PayloadRequest, res: Response, next: NextFunction): void => {
|
||||
req.payloadDataLoader = getDataLoader(req)
|
||||
return next()
|
||||
})
|
||||
|
||||
payload.express = options.express
|
||||
|
||||
if (payload.config.rateLimit.trustProxy) {
|
||||
payload.express.set('trust proxy', 1)
|
||||
}
|
||||
|
||||
await initAdmin(payload)
|
||||
|
||||
payload.router.get('/access', access)
|
||||
|
||||
if (!payload.config.graphQL.disable) {
|
||||
payload.router.use(
|
||||
payload.config.routes.graphQL,
|
||||
(req, res, next): void => {
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.sendStatus(204)
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
},
|
||||
identifyAPI('GraphQL'),
|
||||
(req: PayloadRequest, res: Response, next) => graphQLHandler(req, res)(req, res, next),
|
||||
)
|
||||
initGraphQLPlayground(payload)
|
||||
}
|
||||
|
||||
mountEndpoints(options.express, payload.router, payload.config.endpoints)
|
||||
|
||||
// Bind router to API
|
||||
payload.express.use(payload.config.routes.api, payload.router)
|
||||
|
||||
// Enable static routes for all collections permitting upload
|
||||
initStatic(payload)
|
||||
|
||||
payload.errorHandler = errorHandler(payload.config, payload.logger)
|
||||
payload.router.use(payload.errorHandler)
|
||||
|
||||
payload.authenticate = authenticate(payload.config)
|
||||
}
|
||||
|
||||
return payload
|
||||
}
|
||||
@@ -1,438 +0,0 @@
|
||||
import type { Express, Router } from 'express'
|
||||
import type { ExecutionResult, GraphQLSchema, ValidationRule } from 'graphql'
|
||||
// @ts-expect-error // TODO Fix this - moduleResolution 16 breaks this import
|
||||
import type { OperationArgs, Request as graphQLRequest } from 'graphql-http/lib/handler'
|
||||
import type { SendMailOptions } from 'nodemailer'
|
||||
import type pino from 'pino'
|
||||
|
||||
import crypto from 'crypto'
|
||||
import path from 'path'
|
||||
|
||||
import type { DatabaseAdapter, GeneratedTypes } from './' // Must import from Payload to support declare module
|
||||
import type { Result as ForgotPasswordResult } from './auth/operations/forgotPassword'
|
||||
import type { Options as ForgotPasswordOptions } from './auth/operations/local/forgotPassword'
|
||||
import type { Options as LoginOptions } from './auth/operations/local/login'
|
||||
import type { Options as ResetPasswordOptions } from './auth/operations/local/resetPassword'
|
||||
import type { Options as UnlockOptions } from './auth/operations/local/unlock'
|
||||
import type { Options as VerifyEmailOptions } from './auth/operations/local/verifyEmail'
|
||||
import type { Result as LoginResult } from './auth/operations/login'
|
||||
import type { Result as ResetPasswordResult } from './auth/operations/resetPassword'
|
||||
import type { BulkOperationResult, Collection } from './collections/config/types'
|
||||
import type { Options as CreateOptions } from './collections/operations/local/create'
|
||||
import type {
|
||||
ByIDOptions as DeleteByIDOptions,
|
||||
ManyOptions as DeleteManyOptions,
|
||||
Options as DeleteOptions,
|
||||
} from './collections/operations/local/delete'
|
||||
import type { Options as FindOptions } from './collections/operations/local/find'
|
||||
import type { Options as FindByIDOptions } from './collections/operations/local/findByID'
|
||||
import type { Options as FindVersionByIDOptions } from './collections/operations/local/findVersionByID'
|
||||
import type { Options as FindVersionsOptions } from './collections/operations/local/findVersions'
|
||||
import type { Options as RestoreVersionOptions } from './collections/operations/local/restoreVersion'
|
||||
import type {
|
||||
ByIDOptions as UpdateByIDOptions,
|
||||
ManyOptions as UpdateManyOptions,
|
||||
Options as UpdateOptions,
|
||||
} from './collections/operations/local/update'
|
||||
import type { EmailOptions, InitOptions, SanitizedConfig } from './config/types'
|
||||
import type { PaginatedDocs } from './database/types'
|
||||
import type { BuildEmailResult } from './email/types'
|
||||
import type { PayloadAuthenticate } from './express/middleware/authenticate'
|
||||
import type { ErrorHandler } from './express/middleware/errorHandler'
|
||||
import type { Globals } from './globals/config/types'
|
||||
import type { Options as FindGlobalOptions } from './globals/operations/local/findOne'
|
||||
import type { Options as FindGlobalVersionByIDOptions } from './globals/operations/local/findVersionByID'
|
||||
import type { Options as FindGlobalVersionsOptions } from './globals/operations/local/findVersions'
|
||||
import type { Options as RestoreGlobalVersionOptions } from './globals/operations/local/restoreVersion'
|
||||
import type { Options as UpdateGlobalOptions } from './globals/operations/local/update'
|
||||
import type { TypeWithVersion } from './versions/types'
|
||||
|
||||
import { decrypt, encrypt } from './auth/crypto'
|
||||
import localOperations from './collections/operations/local'
|
||||
import findConfig from './config/find'
|
||||
import buildEmail from './email/build'
|
||||
import { defaults as emailDefaults } from './email/defaults'
|
||||
import sendEmail from './email/sendEmail'
|
||||
import localGlobalOperations from './globals/operations/local'
|
||||
import registerGraphQLSchema from './graphql/registerSchema'
|
||||
import Logger from './utilities/logger'
|
||||
import { serverInit as serverInitTelemetry } from './utilities/telemetry/events/serverInit'
|
||||
|
||||
/**
|
||||
* @description Payload
|
||||
*/
|
||||
export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
|
||||
Mutation: { fields: { [key: string]: any }; name: string } = { name: 'Mutation', fields: {} }
|
||||
|
||||
Query: { fields: { [key: string]: any }; name: string } = { name: 'Query', fields: {} }
|
||||
|
||||
authenticate: PayloadAuthenticate
|
||||
|
||||
collections: {
|
||||
[slug: number | string | symbol]: Collection
|
||||
} = {}
|
||||
|
||||
config: SanitizedConfig
|
||||
|
||||
/**
|
||||
* @description Performs create operation
|
||||
* @param options
|
||||
* @returns created document
|
||||
*/
|
||||
create = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: CreateOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]> => {
|
||||
const { create } = localOperations
|
||||
return create<T>(this, options)
|
||||
}
|
||||
|
||||
db: DatabaseAdapter
|
||||
|
||||
decrypt = decrypt
|
||||
|
||||
email: BuildEmailResult
|
||||
|
||||
emailOptions: EmailOptions
|
||||
|
||||
encrypt = encrypt
|
||||
|
||||
errorHandler: ErrorHandler
|
||||
|
||||
express?: Express
|
||||
|
||||
extensions: (args: {
|
||||
args: OperationArgs<any>
|
||||
req: graphQLRequest<unknown, unknown>
|
||||
result: ExecutionResult
|
||||
}) => Promise<any>
|
||||
|
||||
/**
|
||||
* @description Find documents with criteria
|
||||
* @param options
|
||||
* @returns documents satisfying query
|
||||
*/
|
||||
find = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: FindOptions<T>,
|
||||
): Promise<PaginatedDocs<TGeneratedTypes['collections'][T]>> => {
|
||||
const { find } = localOperations
|
||||
return find<T>(this, options)
|
||||
}
|
||||
|
||||
findByID = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: FindByIDOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]> => {
|
||||
const { findByID } = localOperations
|
||||
return findByID<T>(this, options)
|
||||
}
|
||||
|
||||
findGlobal = async <T extends keyof TGeneratedTypes['globals']>(
|
||||
options: FindGlobalOptions<T>,
|
||||
): Promise<TGeneratedTypes['globals'][T]> => {
|
||||
const { findOne } = localGlobalOperations
|
||||
return findOne<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Find global version by ID
|
||||
* @param options
|
||||
* @returns global version with specified ID
|
||||
*/
|
||||
findGlobalVersionByID = async <T extends keyof TGeneratedTypes['globals']>(
|
||||
options: FindGlobalVersionByIDOptions<T>,
|
||||
): Promise<TypeWithVersion<TGeneratedTypes['globals'][T]>> => {
|
||||
const { findVersionByID } = localGlobalOperations
|
||||
return findVersionByID<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Find global versions with criteria
|
||||
* @param options
|
||||
* @returns versions satisfying query
|
||||
*/
|
||||
findGlobalVersions = async <T extends keyof TGeneratedTypes['globals']>(
|
||||
options: FindGlobalVersionsOptions<T>,
|
||||
): Promise<PaginatedDocs<TypeWithVersion<TGeneratedTypes['globals'][T]>>> => {
|
||||
const { findVersions } = localGlobalOperations
|
||||
return findVersions<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Find version by ID
|
||||
* @param options
|
||||
* @returns version with specified ID
|
||||
*/
|
||||
findVersionByID = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: FindVersionByIDOptions<T>,
|
||||
): Promise<TypeWithVersion<TGeneratedTypes['collections'][T]>> => {
|
||||
const { findVersionByID } = localOperations
|
||||
return findVersionByID<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Find versions with criteria
|
||||
* @param options
|
||||
* @returns versions satisfying query
|
||||
*/
|
||||
findVersions = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: FindVersionsOptions<T>,
|
||||
): Promise<PaginatedDocs<TypeWithVersion<TGeneratedTypes['collections'][T]>>> => {
|
||||
const { findVersions } = localOperations
|
||||
return findVersions<T>(this, options)
|
||||
}
|
||||
|
||||
forgotPassword = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: ForgotPasswordOptions<T>,
|
||||
): Promise<ForgotPasswordResult> => {
|
||||
const { forgotPassword } = localOperations.auth
|
||||
return forgotPassword<T>(this, options)
|
||||
}
|
||||
|
||||
getAPIURL = (): string => `${this.config.serverURL}${this.config.routes.api}`
|
||||
|
||||
getAdminURL = (): string => `${this.config.serverURL}${this.config.routes.admin}`
|
||||
|
||||
globals: Globals
|
||||
|
||||
local: boolean
|
||||
|
||||
logger: pino.Logger
|
||||
|
||||
login = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: LoginOptions<T>,
|
||||
): Promise<LoginResult & { user: TGeneratedTypes['collections'][T] }> => {
|
||||
const { login } = localOperations.auth
|
||||
return login<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Find document by ID
|
||||
* @param options
|
||||
* @returns document with specified ID
|
||||
*/
|
||||
|
||||
resetPassword = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: ResetPasswordOptions<T>,
|
||||
): Promise<ResetPasswordResult> => {
|
||||
const { resetPassword } = localOperations.auth
|
||||
return resetPassword<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Restore global version by ID
|
||||
* @param options
|
||||
* @returns version with specified ID
|
||||
*/
|
||||
restoreGlobalVersion = async <T extends keyof TGeneratedTypes['globals']>(
|
||||
options: RestoreGlobalVersionOptions<T>,
|
||||
): Promise<TGeneratedTypes['globals'][T]> => {
|
||||
const { restoreVersion } = localGlobalOperations
|
||||
return restoreVersion<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Restore version by ID
|
||||
* @param options
|
||||
* @returns version with specified ID
|
||||
*/
|
||||
restoreVersion = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: RestoreVersionOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]> => {
|
||||
const { restoreVersion } = localOperations
|
||||
return restoreVersion<T>(this, options)
|
||||
}
|
||||
|
||||
router?: Router
|
||||
|
||||
schema: GraphQLSchema
|
||||
|
||||
secret: string
|
||||
|
||||
sendEmail: (message: SendMailOptions) => Promise<unknown>
|
||||
|
||||
types: {
|
||||
arrayTypes: any
|
||||
blockInputTypes: any
|
||||
blockTypes: any
|
||||
fallbackLocaleInputType?: any
|
||||
groupTypes: any
|
||||
localeInputType?: any
|
||||
tabTypes: any
|
||||
}
|
||||
|
||||
unlock = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: UnlockOptions<T>,
|
||||
): Promise<boolean> => {
|
||||
const { unlock } = localOperations.auth
|
||||
return unlock(this, options)
|
||||
}
|
||||
|
||||
updateGlobal = async <T extends keyof TGeneratedTypes['globals']>(
|
||||
options: UpdateGlobalOptions<T>,
|
||||
): Promise<TGeneratedTypes['globals'][T]> => {
|
||||
const { update } = localGlobalOperations
|
||||
return update<T>(this, options)
|
||||
}
|
||||
|
||||
validationRules: (args: OperationArgs<any>) => ValidationRule[]
|
||||
|
||||
verifyEmail = async <T extends keyof TGeneratedTypes['collections']>(
|
||||
options: VerifyEmailOptions<T>,
|
||||
): Promise<boolean> => {
|
||||
const { verifyEmail } = localOperations.auth
|
||||
return verifyEmail(this, options)
|
||||
}
|
||||
|
||||
versions: {
|
||||
[slug: string]: any // TODO: Type this
|
||||
} = {}
|
||||
|
||||
delete<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: DeleteOptions<T>,
|
||||
): Promise<BulkOperationResult<T> | TGeneratedTypes['collections'][T]> {
|
||||
const { deleteLocal } = localOperations
|
||||
return deleteLocal<T>(this, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description delete one or more documents
|
||||
* @param options
|
||||
* @returns Updated document(s)
|
||||
*/
|
||||
delete<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: DeleteByIDOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]>
|
||||
|
||||
delete<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: DeleteManyOptions<T>,
|
||||
): Promise<BulkOperationResult<T>>
|
||||
|
||||
/**
|
||||
* @description Initializes Payload
|
||||
* @param options
|
||||
*/
|
||||
// @ts-expect-error // TODO: TypeScript hallucinating again. fix later
|
||||
async init(options: InitOptions): Promise<Payload> {
|
||||
this.logger = Logger('payload', options.loggerOptions, options.loggerDestination)
|
||||
|
||||
if (!options.secret) {
|
||||
throw new Error('Error: missing secret key. A secret key is needed to secure Payload.')
|
||||
}
|
||||
|
||||
this.secret = crypto.createHash('sha256').update(options.secret).digest('hex').slice(0, 32)
|
||||
|
||||
this.local = options.local
|
||||
|
||||
if (options.config) {
|
||||
this.config = await options.config
|
||||
const configPath = findConfig()
|
||||
|
||||
this.config = {
|
||||
...this.config,
|
||||
paths: {
|
||||
config: configPath,
|
||||
configDir: path.dirname(configPath),
|
||||
rawConfig: configPath,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
|
||||
const loadConfig = require('./config/load').default
|
||||
this.config = await loadConfig(this.logger)
|
||||
}
|
||||
|
||||
this.globals = {
|
||||
config: this.config.globals,
|
||||
}
|
||||
this.config.collections.forEach((collection) => {
|
||||
this.collections[collection.slug] = {
|
||||
config: collection,
|
||||
}
|
||||
})
|
||||
|
||||
this.db = this.config.db({ payload: this })
|
||||
this.db.payload = this
|
||||
|
||||
if (this.db?.init) {
|
||||
await this.db.init(this)
|
||||
}
|
||||
|
||||
if (!options.disableDBConnect && this.db.connect) {
|
||||
await this.db.connect(this)
|
||||
}
|
||||
|
||||
this.logger.info('Starting Payload...')
|
||||
|
||||
// Configure email service
|
||||
const emailOptions = options.email ? { ...options.email } : this.config.email
|
||||
if (options.email && this.config.email) {
|
||||
this.logger.warn(
|
||||
'Email options provided in both init options and config. Using init options.',
|
||||
)
|
||||
}
|
||||
|
||||
this.emailOptions = emailOptions ?? emailDefaults
|
||||
this.email = buildEmail(this.emailOptions, this.logger)
|
||||
this.sendEmail = sendEmail.bind(this)
|
||||
|
||||
if (!this.config.graphQL.disable) {
|
||||
registerGraphQLSchema(this)
|
||||
}
|
||||
|
||||
serverInitTelemetry(this)
|
||||
|
||||
if (!options.disableOnInit) {
|
||||
if (typeof options.onInit === 'function') await options.onInit(this)
|
||||
if (typeof this.config.onInit === 'function') await this.config.onInit(this)
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
update<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: UpdateManyOptions<T>,
|
||||
): Promise<BulkOperationResult<T>>
|
||||
|
||||
/**
|
||||
* @description Update one or more documents
|
||||
* @param options
|
||||
* @returns Updated document(s)
|
||||
*/
|
||||
update<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: UpdateByIDOptions<T>,
|
||||
): Promise<TGeneratedTypes['collections'][T]>
|
||||
|
||||
update<T extends keyof TGeneratedTypes['collections']>(
|
||||
options: UpdateOptions<T>,
|
||||
): Promise<BulkOperationResult<T> | TGeneratedTypes['collections'][T]> {
|
||||
const { update } = localOperations
|
||||
return update<T>(this, options)
|
||||
}
|
||||
}
|
||||
|
||||
export type Payload = BasePayload<GeneratedTypes>
|
||||
|
||||
let cached = global._payload
|
||||
|
||||
if (!cached) {
|
||||
// eslint-disable-next-line no-multi-assign
|
||||
cached = global._payload = { payload: null, promise: null }
|
||||
}
|
||||
|
||||
export const getPayload = async (options: InitOptions): Promise<Payload> => {
|
||||
if (cached.payload) {
|
||||
return cached.payload
|
||||
}
|
||||
|
||||
if (!cached.promise) {
|
||||
cached.promise = new BasePayload<GeneratedTypes>().init(options)
|
||||
}
|
||||
|
||||
try {
|
||||
cached.payload = await cached.promise
|
||||
} catch (e) {
|
||||
cached.promise = null
|
||||
throw e
|
||||
}
|
||||
|
||||
return cached.payload
|
||||
}
|
||||
777
pnpm-lock.yaml
generated
777
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user