fix: get auto type-gen to work on turbo, by running type gen in a child process outside turbo/webpack (#6714)
Before on turbo: https://github.com/vercel/next.js/issues/66723
This commit is contained in:
@@ -2,7 +2,6 @@ import type { GeneratedTypes, Payload } from 'payload'
|
||||
import type { InitOptions, SanitizedConfig } from 'payload/config'
|
||||
|
||||
import { BasePayload } from 'payload'
|
||||
import { generateTypes } from 'payload/bin'
|
||||
import WebSocket from 'ws'
|
||||
|
||||
let cached: {
|
||||
@@ -39,7 +38,12 @@ export const reload = async (config: SanitizedConfig, payload: Payload): Promise
|
||||
|
||||
// Generate types
|
||||
if (config.typescript.autoGenerate !== false) {
|
||||
void generateTypes(config, { log: false })
|
||||
// We cannot run it directly here, as generate-types imports json-schema-to-typescript, which breaks on turbopack.
|
||||
// see: https://github.com/vercel/next.js/issues/66723
|
||||
void payload.bin({
|
||||
args: ['generate:types'],
|
||||
log: false,
|
||||
})
|
||||
}
|
||||
|
||||
await payload.db.init()
|
||||
|
||||
@@ -68,7 +68,6 @@ export const withPayload = (nextConfig = {}) => {
|
||||
'pino',
|
||||
'pino-pretty',
|
||||
'graphql',
|
||||
'json-schema-to-typescript',
|
||||
],
|
||||
webpack: (webpackConfig, webpackOptions) => {
|
||||
const incomingWebpackConfig =
|
||||
@@ -84,7 +83,6 @@ export const withPayload = (nextConfig = {}) => {
|
||||
'drizzle-kit/payload',
|
||||
'sharp',
|
||||
'libsql',
|
||||
'json-schema-to-typescript',
|
||||
],
|
||||
ignoreWarnings: [
|
||||
...(incomingWebpackConfig?.ignoreWarnings || []),
|
||||
|
||||
@@ -18,7 +18,6 @@ const componentWebpackConfig = {
|
||||
'payload/config',
|
||||
'react-image-crop',
|
||||
'payload/operations',
|
||||
'payload/bin',
|
||||
],
|
||||
mode: 'production',
|
||||
module: {
|
||||
|
||||
@@ -4,8 +4,6 @@ import { register } from 'node:module'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath, pathToFileURL } from 'node:url'
|
||||
|
||||
import { bin } from './dist/bin/index.js'
|
||||
|
||||
// Allow disabling SWC for debugging
|
||||
if (process.env.DISABLE_SWC !== 'true') {
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
@@ -15,4 +13,9 @@ if (process.env.DISABLE_SWC !== 'true') {
|
||||
register('./dist/bin/loader/index.js', url)
|
||||
}
|
||||
|
||||
bin()
|
||||
const start = async () => {
|
||||
const { bin } = await import('./dist/bin/index.js')
|
||||
bin()
|
||||
}
|
||||
|
||||
void start()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { findUpSync, pathExistsSync } from 'find-up'
|
||||
import fs from 'fs'
|
||||
import { getTsconfig } from 'get-tsconfig'
|
||||
import path from 'path'
|
||||
|
||||
/**
|
||||
@@ -12,37 +12,30 @@ const getTSConfigPaths = (): {
|
||||
outPath?: string
|
||||
rootPath?: string
|
||||
srcPath?: string
|
||||
tsConfigPath?: string
|
||||
} => {
|
||||
const tsConfigPath = findUpSync('tsconfig.json')
|
||||
|
||||
if (!tsConfigPath) {
|
||||
return {
|
||||
rootPath: process.cwd(),
|
||||
}
|
||||
}
|
||||
const tsConfigResult = getTsconfig()
|
||||
const tsConfig = tsConfigResult.config
|
||||
const tsConfigDir = path.dirname(tsConfigResult.path)
|
||||
|
||||
try {
|
||||
// Read the file as a string and remove trailing commas
|
||||
const rawTsConfig = fs
|
||||
.readFileSync(tsConfigPath, 'utf-8')
|
||||
.replace(/,\s*\]/g, ']')
|
||||
.replace(/,\s*\}/g, '}')
|
||||
|
||||
const tsConfig = JSON.parse(rawTsConfig)
|
||||
|
||||
const rootPath = process.cwd()
|
||||
const rootConfigDir = path.resolve(tsConfigDir, tsConfig.compilerOptions.baseUrl || '')
|
||||
const srcPath = tsConfig.compilerOptions?.rootDir || path.resolve(process.cwd(), 'src')
|
||||
const outPath = tsConfig.compilerOptions?.outDir || path.resolve(process.cwd(), 'dist')
|
||||
const tsConfigDir = path.dirname(tsConfigPath)
|
||||
let configPath = tsConfig.compilerOptions?.paths?.['@payload-config']?.[0]
|
||||
let configPath = path.resolve(
|
||||
rootConfigDir,
|
||||
tsConfig.compilerOptions?.paths?.['@payload-config']?.[0],
|
||||
)
|
||||
|
||||
if (configPath) {
|
||||
configPath = path.resolve(tsConfigDir, configPath)
|
||||
configPath = path.resolve(rootConfigDir, configPath)
|
||||
}
|
||||
return {
|
||||
configPath,
|
||||
outPath,
|
||||
rootPath,
|
||||
rootPath: rootConfigDir,
|
||||
srcPath,
|
||||
tsConfigPath: tsConfigResult.path,
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error parsing tsconfig.json: ${error}`) // Do not throw the error, as we can still continue with the other config path finding methods
|
||||
@@ -70,6 +63,11 @@ export const findConfig = (): string => {
|
||||
|
||||
const { configPath, outPath, rootPath, srcPath } = getTSConfigPaths()
|
||||
|
||||
// if configPath is absolute file, not folder, return it
|
||||
if (path.extname(configPath) === '.js' || path.extname(configPath) === '.ts') {
|
||||
return configPath
|
||||
}
|
||||
|
||||
const searchPaths =
|
||||
process.env.NODE_ENV === 'production'
|
||||
? [configPath, outPath, srcPath, rootPath]
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* WARNING: This file contains exports that can only be safely used on the server.
|
||||
*/
|
||||
|
||||
export { generateTypes } from '../bin/generateTypes.js'
|
||||
@@ -2,7 +2,10 @@ import type { ExecutionResult, GraphQLSchema, ValidationRule } from 'graphql'
|
||||
import type { OperationArgs, Request as graphQLRequest } from 'graphql-http'
|
||||
import type pino from 'pino'
|
||||
|
||||
import { spawn } from 'child_process'
|
||||
import crypto from 'crypto'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import path from 'path'
|
||||
|
||||
import type { AuthArgs } from './auth/operations/auth.js'
|
||||
import type { Result as ForgotPasswordResult } from './auth/operations/forgotPassword.js'
|
||||
@@ -47,7 +50,6 @@ 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 { generateTypes } from './bin/generateTypes.js'
|
||||
import localOperations from './collections/operations/local/index.js'
|
||||
import { validateSchema } from './config/validate.js'
|
||||
import { consoleEmailAdapter } from './email/consoleEmailAdapter.js'
|
||||
@@ -57,6 +59,9 @@ import flattenFields from './utilities/flattenTopLevelFields.js'
|
||||
import Logger from './utilities/logger.js'
|
||||
import { serverInit as serverInitTelemetry } from './utilities/telemetry/events/serverInit.js'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
/**
|
||||
* @description Payload
|
||||
*/
|
||||
@@ -302,6 +307,31 @@ export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
|
||||
[slug: string]: any // TODO: Type this
|
||||
} = {}
|
||||
|
||||
async bin({
|
||||
args,
|
||||
cwd,
|
||||
log,
|
||||
}: {
|
||||
args: string[]
|
||||
cwd?: string
|
||||
log?: boolean
|
||||
}): Promise<{ code: number }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const spawned = spawn('node', [path.resolve(dirname, '../bin.js'), ...args], {
|
||||
cwd,
|
||||
stdio: log || log === undefined ? 'inherit' : 'ignore',
|
||||
})
|
||||
|
||||
spawned.on('exit', (code) => {
|
||||
resolve({ code })
|
||||
})
|
||||
|
||||
spawned.on('error', (error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description delete one or more documents
|
||||
* @param options
|
||||
@@ -366,7 +396,12 @@ export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
|
||||
|
||||
// Generate types on startup
|
||||
if (process.env.NODE_ENV !== 'production' && this.config.typescript.autoGenerate !== false) {
|
||||
void generateTypes(this.config, { log: false })
|
||||
// We cannot run it directly here, as generate-types imports json-schema-to-typescript, which breaks on turbopack.
|
||||
// see: https://github.com/vercel/next.js/issues/66723
|
||||
void this.bin({
|
||||
args: ['generate:types'],
|
||||
log: false,
|
||||
})
|
||||
}
|
||||
|
||||
this.db = this.config.db.init({ payload: this })
|
||||
|
||||
@@ -32,7 +32,7 @@ export const createTestHooks = async (testSuiteName = '_community') => {
|
||||
tsConfig.compilerOptions.paths['@payload-config'] = [`./test/${testSuiteName}/config.ts`]
|
||||
await writeFile(tsConfigPath, stringify(tsConfig, null, 2) + '\n')
|
||||
|
||||
process.env.PAYLOAD_CONFIG_PATH = path.resolve(testSuiteName, 'config')
|
||||
process.env.PAYLOAD_CONFIG_PATH = path.resolve(dirname, testSuiteName, 'config.ts')
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user