Compare commits

...

1 Commits

Author SHA1 Message Date
Dan Ribbens
9f64534213 feat!: make graphql an optional dependency 2024-11-17 16:19:55 -05:00
8 changed files with 66 additions and 51 deletions

View File

@@ -88,8 +88,6 @@
"@payloadcms/ui": "workspace:*",
"busboy": "^1.6.0",
"file-type": "19.3.0",
"graphql-http": "^1.22.0",
"graphql-playground-html": "1.6.30",
"http-status": "1.6.2",
"path-to-regexp": "^6.2.1",
"qs-esm": "7.0.2",
@@ -114,11 +112,12 @@
"esbuild": "0.23.1",
"esbuild-sass-plugin": "3.3.1",
"eslint-plugin-react-compiler": "19.0.0-beta-a7bf2bd-20241110",
"graphql": "^16.8.1",
"graphql-http": "^1.22.0",
"payload": "workspace:*",
"swc-plugin-transform-remove-imports": "1.15.0"
},
"peerDependencies": {
"graphql": "^16.8.1",
"next": "^15.0.0",
"payload": "workspace:*"
},

View File

@@ -1,9 +1,8 @@
import type { GraphQLError, GraphQLFormattedError } from 'graphql'
import type { APIError, Payload, PayloadRequest, SanitizedConfig } from 'payload'
import { configToSchema } from '@payloadcms/graphql'
import { createHandler } from 'graphql-http/lib/use/fetch'
import httpStatus from 'http-status'
import { createRequire } from 'module'
import { addDataAndFileToRequest } from '../../utilities/addDataAndFileToRequest.js'
import { addLocalesToRequestFromData } from '../../utilities/addLocalesToRequest.js'
@@ -11,6 +10,20 @@ import { createPayloadRequest } from '../../utilities/createPayloadRequest.js'
import { headersWithCors } from '../../utilities/headersWithCors.js'
import { mergeHeaders } from '../../utilities/mergeHeaders.js'
const require = createRequire(import.meta.url)
let createHandler
let configToSchema
const getDynamicImports = () => {
if (createHandler) {
return createHandler
} else {
createHandler = require('graphql-http/lib/use/fetch').createHandler
configToSchema = require('@payloadcms/graphql').configToSchema
return { configToSchema, createHandler }
}
}
const handleError = async ({
err,
payload,
@@ -78,6 +91,11 @@ export const getGraphql = async (config: Promise<SanitizedConfig> | SanitizedCon
if (!cached.promise) {
const resolvedConfig = await config
cached.promise = new Promise((resolve) => {
if (resolvedConfig.graphQL.disable) {
resolve(null)
return
}
const { configToSchema } = getDynamicImports()
const schema = configToSchema(resolvedConfig)
resolve(cached.graphql || schema)
})
@@ -95,6 +113,13 @@ export const getGraphql = async (config: Promise<SanitizedConfig> | SanitizedCon
export const POST =
(config: Promise<SanitizedConfig> | SanitizedConfig) => async (request: Request) => {
if ((await config).graphQL.disable) {
return new Response('GraphQL is disabled', {
status: httpStatus.NOT_FOUND,
})
}
const { createHandler } = getDynamicImports()
const originalRequest = request.clone()
const req = await createPayloadRequest({
config,

View File

@@ -1,15 +1,28 @@
import type { SanitizedConfig } from 'payload'
import { renderPlaygroundPage } from 'graphql-playground-html'
import { createRequire } from 'module'
import { createPayloadRequest } from '../../utilities/createPayloadRequest.js'
const require = createRequire(import.meta.url)
let renderPlaygroundPage
const getRenderPlaygroundPage = () => {
if (renderPlaygroundPage) {
return renderPlaygroundPage
} else {
renderPlaygroundPage = require('graphql-playground-html').renderPlaygroundPage
return renderPlaygroundPage
}
}
export const GET = (config: Promise<SanitizedConfig>) => async (request: Request) => {
const req = await createPayloadRequest({
config,
request,
})
const renderPlaygroundPage = getRenderPlaygroundPage()
if (
(!req.payload.config.graphQL.disable &&
!req.payload.config.graphQL.disablePlaygroundInProduction &&

View File

@@ -125,13 +125,11 @@
"copyfiles": "2.4.1",
"cross-env": "7.0.3",
"esbuild": "0.23.1",
"graphql": "^16.8.1",
"graphql-http": "^1.22.0",
"rimraf": "3.0.2",
"sharp": "0.32.6"
},
"peerDependencies": {
"graphql": "^16.8.1"
},
"engines": {
"node": "^18.20.2 || >=20.9.0"
},

View File

@@ -525,11 +525,11 @@ export interface SanitizedCollectionConfig
auth: Auth
endpoints: Endpoint[] | false
fields: Field[]
slug: CollectionSlug
/**
* Object of collections to join 'Join Fields object keyed by collection
*/
joins: SanitizedJoins
slug: CollectionSlug
upload: SanitizedUploadConfig
versions: SanitizedCollectionVersions
}

View File

@@ -97,6 +97,12 @@ export const sanitizeConfig = async (incomingConfig: Config): Promise<SanitizedC
},
}
if (configWithDefaults.graphQL.disable) {
configWithDefaults.graphQL = { disable: true }
delete configWithDefaults.routes.graphQL
delete configWithDefaults.routes.graphQLPlayground
}
if (!configWithDefaults?.serverURL) {
configWithDefaults.serverURL = ''
}

View File

@@ -1,6 +1,7 @@
import type { ExecutionResult, GraphQLSchema, ValidationRule } from 'graphql'
import type { Request as graphQLRequest, OperationArgs } from 'graphql-http'
import type { Logger } from 'pino'
import type { NonNever } from 'ts-essentials'
import { spawn } from 'child_process'
import crypto from 'crypto'
@@ -25,12 +26,6 @@ import type {
SelectFromCollectionSlug,
TypeWithID,
} from './collections/config/types.js'
import { generateImportMap, type ImportMap } from './bin/generateImportMap/index.js'
export type { FieldState } from './admin/forms/Form.js'
export type * from './admin/types.js'
import type { NonNever } from 'ts-essentials'
import type { Options as CountOptions } from './collections/operations/local/count.js'
import type { Options as CreateOptions } from './collections/operations/local/create.js'
import type {
@@ -72,6 +67,7 @@ import type { TypeWithVersion } from './versions/types.js'
import { decrypt, encrypt } from './auth/crypto.js'
import { APIKeyAuthentication } from './auth/strategies/apiKey.js'
import { JWTAuthentication } from './auth/strategies/jwt.js'
import { generateImportMap, type ImportMap } from './bin/generateImportMap/index.js'
import { checkPayloadDependencies } from './checkPayloadDependencies.js'
import localOperations from './collections/operations/local/index.js'
import { consoleEmailAdapter } from './email/consoleEmailAdapter.js'
@@ -82,6 +78,9 @@ import { getLogger } from './utilities/logger.js'
import { serverInit as serverInitTelemetry } from './utilities/telemetry/events/serverInit.js'
import { traverseFields } from './utilities/traverseFields.js'
export type { FieldState } from './admin/forms/Form.js'
export type * from './admin/types.js'
export interface GeneratedTypes {
authUntyped: {
[slug: string]: {
@@ -459,7 +458,7 @@ export class BasePayload {
return restoreVersion<TSlug>(this, options)
}
schema: GraphQLSchema
schema?: GraphQLSchema
secret: string

43
pnpm-lock.yaml generated
View File

@@ -706,15 +706,6 @@ importers:
file-type:
specifier: 19.3.0
version: 19.3.0
graphql:
specifier: ^16.8.1
version: 16.9.0
graphql-http:
specifier: ^1.22.0
version: 1.22.2(graphql@16.9.0)
graphql-playground-html:
specifier: 1.6.30
version: 1.6.30
http-status:
specifier: 1.6.2
version: 1.6.2
@@ -785,6 +776,12 @@ importers:
eslint-plugin-react-compiler:
specifier: 19.0.0-beta-a7bf2bd-20241110
version: 19.0.0-beta-a7bf2bd-20241110(eslint@9.14.0(jiti@1.21.6))
graphql:
specifier: ^16.8.1
version: 16.9.0
graphql-http:
specifier: ^1.22.0
version: 1.22.2(graphql@16.9.0)
payload:
specifier: workspace:*
version: link:../payload
@@ -833,9 +830,6 @@ importers:
get-tsconfig:
specifier: 4.8.1
version: 4.8.1
graphql:
specifier: ^16.8.1
version: 16.9.0
http-status:
specifier: 1.6.2
version: 1.6.2
@@ -915,6 +909,9 @@ importers:
esbuild:
specifier: 0.23.1
version: 0.23.1
graphql:
specifier: ^16.8.1
version: 16.9.0
graphql-http:
specifier: ^1.22.0
version: 1.22.2(graphql@16.9.0)
@@ -5749,9 +5746,6 @@ packages:
resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
engines: {node: '>=8'}
cssfilter@0.0.10:
resolution: {integrity: sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==}
cssom@0.3.8:
resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==}
@@ -6820,9 +6814,6 @@ packages:
peerDependencies:
graphql: ^16.8.1
graphql-playground-html@1.6.30:
resolution: {integrity: sha512-tpCujhsJMva4aqE8ULnF7/l3xw4sNRZcSHu+R00VV+W0mfp+Q20Plvcrp+5UXD+2yS6oyCXncA+zoQJQqhGCEw==}
graphql-scalars@1.22.2:
resolution: {integrity: sha512-my9FB4GtghqXqi/lWSVAOPiTzTnnEzdOXCsAC2bb5V7EFNQjVjwy3cSSbUvgYOtDuDibd+ZsCDhz+4eykYOlhQ==}
engines: {node: '>=10'}
@@ -9831,11 +9822,6 @@ packages:
xmlchars@2.2.0:
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
xss@1.0.15:
resolution: {integrity: sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==}
engines: {node: '>= 0.10.0'}
hasBin: true
xtend@4.0.2:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
@@ -15103,8 +15089,6 @@ snapshots:
crypto-random-string@2.0.0: {}
cssfilter@0.0.10: {}
cssom@0.3.8: {}
cssom@0.5.0: {}
@@ -16350,10 +16334,6 @@ snapshots:
dependencies:
graphql: 16.9.0
graphql-playground-html@1.6.30:
dependencies:
xss: 1.0.15
graphql-scalars@1.22.2(graphql@16.9.0):
dependencies:
graphql: 16.9.0
@@ -19593,11 +19573,6 @@ snapshots:
xmlchars@2.2.0: {}
xss@1.0.15:
dependencies:
commander: 2.20.3
cssfilter: 0.0.10
xtend@4.0.2: {}
y18n@5.0.8: {}