feat: solidifies bundler adapter pattern (#3044)

This commit is contained in:
Jarrod Flesch
2023-07-21 17:20:51 -04:00
committed by GitHub
parent 9f06253321
commit 641c765fb9
54 changed files with 2265 additions and 2030 deletions

View File

@@ -12,7 +12,7 @@ module.exports = {
'dist',
],
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/webpack/mocks/fileMock.js',
'\\.(css|scss)$': '<rootDir>/src/webpack/mocks/emptyModule.js',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/bundlers/mocks/fileMock.js',
'\\.(css|scss)$': '<rootDir>/src/bundlers/mocks/emptyModule.js',
},
};

View File

@@ -11,7 +11,7 @@ module.exports = {
globalSetup: './test/jest.setup.ts',
testTimeout: 90000,
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/webpack/mocks/fileMock.js',
'\\.(css|scss)$': '<rootDir>/src/webpack/mocks/emptyModule.js',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/src/bundlers/mocks/fileMock.js',
'\\.(css|scss)$': '<rootDir>/src/bundlers/mocks/emptyModule.js',
},
};

View File

@@ -33,7 +33,7 @@
"scripts": {
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png}\" dist/",
"build:tsc": "tsc",
"build:components": "webpack --config dist/webpack/components.config.js",
"build:components": "webpack --config dist/bundlers/webpack/components.config.js",
"build": "yarn copyfiles && yarn build:tsc && yarn build:components",
"build:watch": "nodemon --watch 'src/**' --ext 'ts,tsx' --exec \"yarn build:tsc\"",
"dev": "nodemon",

View File

@@ -4,7 +4,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="icon" href="data:," data-placeholder-favicon/>
<link rel="icon" href="data:," data-placeholder-favicon />
</head>
<body>

View File

@@ -3,7 +3,7 @@ import { extractTranslations } from '../translations/extractTranslations';
const labels = extractTranslations(['general:user', 'general:users']);
const defaultUser: CollectionConfig = {
export const defaultUserCollection: CollectionConfig = {
slug: 'users',
labels: {
singular: labels['general:user'],
@@ -17,5 +17,3 @@ const defaultUser: CollectionConfig = {
},
fields: [],
};
export default defaultUser;

View File

@@ -1,33 +1,9 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable global-require */
import webpack from 'webpack';
import getWebpackProdConfig from '../webpack/getProdConfig';
import loadConfig from '../config/load';
export const build = async (): Promise<void> => {
const config = await loadConfig(); // Will throw its own error if it fails
try {
const webpackProdConfig = getWebpackProdConfig(config);
webpack(webpackProdConfig, (err, stats) => { // Stats Object
if (err || stats.hasErrors()) {
// Handle errors here
if (stats) {
console.error(stats.toString({
chunks: false,
colors: true,
}));
} else {
console.error(err.message);
}
}
});
} catch (err) {
console.error(err);
throw new Error('Error: there was an error building the webpack config.');
}
await config.admin.bundler.build(config);
};
// when build.js is launched directly

View File

@@ -26,10 +26,10 @@ const swcOptions = {
};
if (tsConfig?.config?.compilerOptions?.paths) {
swcOptions.jsc.paths = tsConfig?.config?.compilerOptions?.paths;
swcOptions.jsc.paths = tsConfig.config.compilerOptions.paths;
if (tsConfig?.config?.compilerOptions?.baseUrl) {
swcOptions.jsc.baseUrl = tsConfig?.config?.compilerOptions?.baseUrl;
swcOptions.jsc.baseUrl = tsConfig.config.compilerOptions.baseUrl;
}
}

View File

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

8
src/bundlers/types.ts Normal file
View File

@@ -0,0 +1,8 @@
import type { PayloadHandler, SanitizedConfig } from 'payload/config';
import type { Payload } from '../payload';
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`
serve: (payload: Payload) => Promise<PayloadHandler> // serve built files in production
}

View File

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

View File

@@ -5,13 +5,13 @@ import OptimizeCSSAssetsPlugin from 'css-minimizer-webpack-plugin';
export default {
entry: {
main: [path.resolve(__dirname, '../admin/components/index.js')],
main: [path.resolve(__dirname, '../../admin/components/index.js')],
},
externals: {
react: 'react',
},
output: {
path: path.resolve(__dirname, '../../components'),
path: path.resolve(__dirname, '../../../components'),
publicPath: '/',
filename: 'index.js',
libraryTarget: 'commonjs2',
@@ -82,8 +82,8 @@ export default {
],
resolve: {
alias: {
'payload-scss-overrides': path.resolve(__dirname, '../admin/scss/overrides.scss'),
'payload-scss-overrides': path.resolve(__dirname, '../../admin/scss/overrides.scss'),
},
modules: ['node_modules', path.resolve(__dirname, '../../node_modules')],
modules: ['node_modules', path.resolve(__dirname, '../../../node_modules')],
},
};

View File

@@ -1,19 +1,23 @@
import path from 'path';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import webpack, { Configuration } from 'webpack';
import { SanitizedConfig } from '../config/types';
import type { SanitizedConfig } from '../../../config/types';
const mockModulePath = path.resolve(__dirname, './mocks/emptyModule.js');
const mockDotENVPath = path.resolve(__dirname, './mocks/dotENV.js');
const mockModulePath = path.resolve(__dirname, '../../mocks/emptyModule.js');
const mockDotENVPath = path.resolve(__dirname, '../../mocks/dotENV.js');
export default (config: SanitizedConfig): Configuration => ({
const nodeModulesPath = path.resolve(__dirname, '../../../../node_modules');
const adminFolderPath = path.resolve(__dirname, '../../../admin');
const bundlerPath = path.resolve(__dirname, '../bundler');
export const getBaseConfig = (payloadConfig: SanitizedConfig): Configuration => ({
entry: {
main: [
path.resolve(__dirname, '../admin'),
adminFolderPath,
],
},
resolveLoader: {
modules: ['node_modules', path.join(__dirname, '../../node_modules')],
modules: ['node_modules', path.join(__dirname, nodeModulesPath)],
},
module: {
rules: [
@@ -51,12 +55,13 @@ export default (config: SanitizedConfig): Configuration => ({
https: false,
http: false,
},
modules: ['node_modules', path.resolve(__dirname, '../../node_modules')],
modules: ['node_modules', path.resolve(__dirname, nodeModulesPath)],
alias: {
'payload-config': config.paths.rawConfig,
'payload-config': payloadConfig.paths.rawConfig,
payload$: mockModulePath,
'payload-user-css': config.admin.css,
'payload-user-css': payloadConfig.admin.css,
dotenv: mockDotENVPath,
[bundlerPath]: mockModulePath,
},
extensions: ['.ts', '.tsx', '.js', '.json'],
},
@@ -80,7 +85,7 @@ export default (config: SanitizedConfig): Configuration => ({
),
),
new HtmlWebpackPlugin({
template: config.admin.indexHTML,
template: payloadConfig.admin.indexHTML,
filename: path.normalize('./index.html'),
}),
new webpack.HotModuleReplacementPlugin(),

View File

@@ -1,12 +1,12 @@
import webpack, { Configuration } from 'webpack';
import md5 from 'md5';
import { SanitizedConfig } from '../config/types';
import getBaseConfig from './getBaseConfig';
import { getBaseConfig } from './base';
import { SanitizedConfig } from '../../../config/types';
export default (payloadConfig: SanitizedConfig): Configuration => {
export const getDevConfig = (payloadConfig: SanitizedConfig): Configuration => {
const baseConfig = getBaseConfig(payloadConfig) as any;
let config: Configuration = {
let webpackConfig: Configuration = {
...baseConfig,
cache: {
type: 'filesystem',
@@ -37,7 +37,7 @@ export default (payloadConfig: SanitizedConfig): Configuration => {
],
};
config.module.rules.push({
webpackConfig.module.rules.push({
test: /\.(scss|css)$/,
sideEffects: true,
use: [
@@ -61,8 +61,8 @@ export default (payloadConfig: SanitizedConfig): Configuration => {
});
if (payloadConfig.admin.webpack && typeof payloadConfig.admin.webpack === 'function') {
config = payloadConfig.admin.webpack(config);
webpackConfig = payloadConfig.admin.webpack(webpackConfig);
}
return config;
return webpackConfig;
};

View File

@@ -1,14 +1,14 @@
import { Configuration, WebpackPluginInstance } from 'webpack';
import MiniCSSExtractPlugin from 'mini-css-extract-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import { Configuration, WebpackPluginInstance } from 'webpack';
import { SwcMinifyWebpackPlugin } from 'swc-minify-webpack-plugin';
import { SanitizedConfig } from '../config/types';
import getBaseConfig from './getBaseConfig';
import { getBaseConfig } from './base';
import { SanitizedConfig } from '../../../config/types';
export default (payloadConfig: SanitizedConfig): Configuration => {
export const getProdConfig = (payloadConfig: SanitizedConfig): Configuration => {
const baseConfig = getBaseConfig(payloadConfig) as any;
let config: Configuration = {
let webpackConfig: Configuration = {
...baseConfig,
output: {
publicPath: `${payloadConfig.routes.admin}/`,
@@ -40,7 +40,7 @@ export default (payloadConfig: SanitizedConfig): Configuration => {
],
};
config.module.rules.push({
webpackConfig.module.rules.push({
test: /\.(scss|css)$/,
sideEffects: true,
use: [
@@ -64,12 +64,12 @@ export default (payloadConfig: SanitizedConfig): Configuration => {
});
if (process.env.PAYLOAD_ANALYZE_BUNDLE) {
config.plugins.push(new BundleAnalyzerPlugin() as unknown as WebpackPluginInstance);
webpackConfig.plugins.push(new BundleAnalyzerPlugin() as unknown as WebpackPluginInstance);
}
if (payloadConfig.admin.webpack && typeof payloadConfig.admin.webpack === 'function') {
config = payloadConfig.admin.webpack(config);
webpackConfig = payloadConfig.admin.webpack(webpackConfig);
}
return config;
return webpackConfig;
};

View File

@@ -0,0 +1,27 @@
import webpack from 'webpack';
import { getProdConfig } from '../configs/prod';
import { SanitizedConfig } from '../../../config/types';
type BuildAdminType = (options: { payloadConfig: SanitizedConfig }) => Promise<void>;
export const buildAdmin: BuildAdminType = async ({ payloadConfig }) => {
try {
const webpackConfig = getProdConfig(payloadConfig);
webpack(webpackConfig, (err, stats) => {
if (err || stats.hasErrors()) {
// Handle errors here
if (stats) {
console.error(stats.toString({
chunks: false,
colors: true,
}));
} else {
console.error(err.message);
}
}
});
} catch (err) {
console.error(err);
throw new Error('Error: there was an error building the webpack prod config.');
}
};

View File

@@ -0,0 +1,31 @@
import webpack from 'webpack';
import express from 'express';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import history from 'connect-history-api-fallback';
import type { PayloadHandler } from '../../../config/types';
import { Payload } from '../../../payload';
import { getDevConfig } from '../configs/dev';
const router = express.Router();
type DevAdminType = (options: { payload: Payload }) => Promise<PayloadHandler>;
export const devAdmin: DevAdminType = async ({ payload }) => {
payload.express.use(payload.config.routes.admin, history());
try {
const webpackConfig = getDevConfig(payload.config);
const compiler = webpack(webpackConfig);
router.use(webpackDevMiddleware(compiler, {
publicPath: webpackConfig.output.publicPath as string,
}));
router.use(webpackHotMiddleware(compiler));
} catch (err) {
console.error(err);
throw new Error('Error: there was an error creating the webpack dev server.');
}
return router;
};

View File

@@ -0,0 +1,27 @@
import express from 'express';
import compression from 'compression';
import history from 'connect-history-api-fallback';
import type { PayloadHandler } from '../../../config/types';
import { Payload } from '../../../payload';
const router = express.Router();
type ServeAdminType = (options: { payload: Payload }) => Promise<PayloadHandler>;
export const serveAdmin: ServeAdminType = async ({ payload }) => {
router.use(payload.config.routes.admin, history());
router.get('*', (req, res, next) => {
if (req.path.substr(-1) === '/' && req.path.length > 1) {
const query = req.url.slice(req.path.length);
res.redirect(301, req.path.slice(0, -1) + query);
} else {
next();
}
});
router.use(compression(payload.config.express.compression));
router.use(express.static(payload.config.admin.buildPath, { redirect: false }));
return router;
};

View File

@@ -1,7 +1,7 @@
/* eslint-disable no-use-before-define */
/* eslint-disable no-nested-ternary */
import { Config, SanitizedConfig } from './types';
import sanitize from './sanitize';
import { sanitizeConfig } from './sanitize';
/**
* @description Builds and validates Payload configuration
@@ -18,10 +18,10 @@ export async function buildConfig(config: Config): Promise<SanitizedConfig> {
Promise.resolve(config),
);
const sanitizedConfig = sanitize(configAfterPlugins);
const sanitizedConfig = sanitizeConfig(configAfterPlugins);
return sanitizedConfig;
}
return sanitize(config);
return sanitizeConfig(config);
}

View File

@@ -1,30 +1,47 @@
import merge from 'deepmerge';
import { isPlainObject } from 'is-plain-object';
import { Config, SanitizedConfig } from './types';
import defaultUser from '../auth/defaultUser';
import { defaultUserCollection } from '../auth/defaultUser';
import sanitizeCollection from '../collections/config/sanitize';
import { InvalidConfiguration } from '../errors';
import sanitizeGlobals from '../globals/config/sanitize';
import checkDuplicateCollections from '../utilities/checkDuplicateCollections';
import { defaults } from './defaults';
import getDefaultBundler from '../bundlers/webpack/bundler';
const sanitizeConfig = (config: Config): SanitizedConfig => {
const sanitizedConfig = merge(defaults, config, {
const sanitizeAdmin = (config: SanitizedConfig): SanitizedConfig['admin'] => {
const adminConfig = config.admin;
// add default user collection if none provided
if (!adminConfig?.user) {
const firstCollectionWithAuth = config.collections.find(({ auth }) => Boolean(auth));
if (firstCollectionWithAuth) {
adminConfig.user = firstCollectionWithAuth.slug;
} else {
adminConfig.user = 'users';
const sanitizedDefaultUser = sanitizeCollection(config, defaultUserCollection);
config.collections.push(sanitizedDefaultUser);
}
}
if (!config.collections.find(({ slug }) => slug === adminConfig.user)) {
throw new InvalidConfiguration(`${config.admin.user} is not a valid admin user collection`);
}
// add default bundler if none provided
if (!adminConfig.bundler) {
adminConfig.bundler = getDefaultBundler();
}
return adminConfig;
};
export const sanitizeConfig = (config: Config): SanitizedConfig => {
const sanitizedConfig: Config = merge(defaults, config, {
isMergeableObject: isPlainObject,
}) as Config;
if (!sanitizedConfig.admin.user) {
const firstCollectionWithAuth = sanitizedConfig.collections.find((c) => c.auth);
if (firstCollectionWithAuth) {
sanitizedConfig.admin.user = firstCollectionWithAuth.slug;
} else {
sanitizedConfig.admin.user = 'users';
const sanitizedDefaultUser = sanitizeCollection(sanitizedConfig, defaultUser);
sanitizedConfig.collections.push(sanitizedDefaultUser);
}
} else if (!sanitizedConfig.collections.find((c) => c.slug === sanitizedConfig.admin.user)) {
throw new InvalidConfiguration(`${sanitizedConfig.admin.user} is not a valid admin user collection`);
}
sanitizedConfig.admin = sanitizeAdmin(sanitizedConfig as SanitizedConfig);
sanitizedConfig.collections = sanitizedConfig.collections.map((collection) => sanitizeCollection(sanitizedConfig, collection));
checkDuplicateCollections(sanitizedConfig.collections);
@@ -43,5 +60,3 @@ const sanitizeConfig = (config: Config): SanitizedConfig => {
return sanitizedConfig as SanitizedConfig;
};
export default sanitizeConfig;

View File

@@ -107,6 +107,11 @@ export default joi.object({
}),
}),
webpack: joi.func(),
bundler: {
dev: joi.func(),
build: joi.func(),
serve: joi.func(),
},
}),
email: joi.object(),
i18n: joi.object(),

View File

@@ -2,7 +2,7 @@ import { Express, NextFunction, Response } from 'express';
import { DeepRequired } from 'ts-essentials';
import { Transporter } from 'nodemailer';
import { Options as ExpressFileUploadOptions } from 'express-fileupload';
import { Configuration } from 'webpack';
import type { Configuration } from 'webpack';
import SMTPConnection from 'nodemailer/lib/smtp-connection';
import GraphQL from 'graphql';
import { ConnectOptions } from 'mongoose';
@@ -19,6 +19,7 @@ import { GlobalConfig, SanitizedGlobalConfig } from '../globals/config/types';
import { PayloadRequest } from '../express/types';
import { Where } from '../types';
import { User } from '../auth/types';
import type { PayloadBundler } from '../bundlers/types';
type Email = {
fromName: string;
@@ -266,7 +267,11 @@ export type Config = {
*/
favicon?: string;
};
/** Specify an absolute path for where to store the built Admin panel bundle used in production. */
/**
* Specify an absolute path for where to store the built Admin panel bundle used in production.
*
* @default "/build"
* */
buildPath?: string
/** If set to true, the entire Admin panel will be disabled. */
disable?: boolean;
@@ -353,6 +358,8 @@ export type Config = {
};
/** Customize the Webpack config that's used to generate the Admin panel. */
webpack?: (config: Configuration) => Configuration;
/** Customize the bundler used to run your admin panel. */
bundler?: PayloadBundler;
};
/**
* Manage the datamodel of your application
@@ -407,13 +414,13 @@ export type Config = {
cors?: string[] | '*';
/** Control the routing structure that Payload binds itself to. */
routes?: {
/** Defaults to /api */
/** @default "/api" */
api?: string;
/** Defaults to /admin */
/** @default "/admin" */
admin?: string;
/** Defaults to /graphql */
/** @default "/graphql" */
graphQL?: string;
/** Defaults to /playground */
/** @default "/playground" */
graphQLPlayground?: string;
};
/** Control how typescript interfaces are generated from your collections. */

View File

@@ -1,32 +1,11 @@
import express from 'express';
import compression from 'compression';
import history from 'connect-history-api-fallback';
import initWebpack from '../webpack/init';
import { Payload } from '../payload';
const router = express.Router();
function initAdmin(ctx: Payload): void {
async function initAdmin(ctx: Payload): Promise<void> {
if (!ctx.config.admin.disable) {
router.use(history());
if (process.env.NODE_ENV === 'production') {
router.get('*', (req, res, next) => {
if (req.path.substr(-1) === '/' && req.path.length > 1) {
const query = req.url.slice(req.path.length);
res.redirect(301, req.path.slice(0, -1) + query);
ctx.express.use(await ctx.config.admin.bundler.serve(ctx));
} else {
next();
}
});
router.use(compression(ctx.config.express.compression));
router.use(express.static(ctx.config.admin.buildPath, { redirect: false }));
ctx.express.use(ctx.config.routes.admin, router);
} else {
ctx.express.use(ctx.config.routes.admin, history());
ctx.express.use(initWebpack(ctx.config));
ctx.express.use(await ctx.config.admin.bundler.dev(ctx));
}
}
}

View File

@@ -48,7 +48,7 @@ export const initHTTP = async (options: InitOptions): Promise<Payload> => {
payload.express.set('trust proxy', 1);
}
initAdmin(payload);
await initAdmin(payload);
initPreferences(payload);
payload.router.get('/access', access);

View File

@@ -1,4 +1,4 @@
import sanitizeConfig from '../config/sanitize';
import { sanitizeConfig } from '../config/sanitize';
import { Config } from '../config/types';
import { configToJSONSchema } from './configToJSONSchema';

View File

@@ -1,23 +0,0 @@
import webpack, { Compiler } from 'webpack';
import express, { Router } from 'express';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import getWebpackDevConfig from './getDevConfig';
import { SanitizedConfig } from '../config/types';
const router = express.Router();
function initWebpack(config: SanitizedConfig): Router {
const webpackDevConfig = getWebpackDevConfig(config);
const compiler = webpack(webpackDevConfig);
router.use(webpackDevMiddleware(compiler, {
publicPath: webpackDevConfig.output.publicPath as string,
}));
router.use(webpackHotMiddleware(compiler as any));
return router;
}
export default initWebpack;

View File

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

View File

@@ -1,10 +1,10 @@
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { PostsCollection, postsSlug } from './collections/Posts';
import { MenuGlobal } from './globals/Menu';
import { devUser } from '../credentials';
import { MediaCollection } from './collections/Media';
export default buildConfig({
export default buildConfigWithDefaults({
// ...extend config here
collections: [
PostsCollection,

View File

@@ -1,5 +1,5 @@
import { devUser } from '../credentials';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { FieldAccess } from '../../src/fields/config/types';
import { firstArrayText, secondArrayText } from './shared';
@@ -36,7 +36,7 @@ const UseRequestHeadersAccess: FieldAccess = ({ req: { headers } }) => {
return !!headers && headers.authorization === requestHeaders.authorization;
};
export default buildConfig({
export default buildConfigWithDefaults({
admin: {
user: 'users',
},

View File

@@ -1,7 +1,7 @@
import path from 'path';
import { mapAsync } from '../../src/utilities/mapAsync';
import { devUser } from '../credentials';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import AfterDashboard from './components/AfterDashboard';
import CustomMinimalRoute from './components/views/CustomMinimal';
import CustomDefaultRoute from './components/views/CustomDefault';
@@ -20,7 +20,7 @@ export interface Post {
updatedAt: Date;
}
export default buildConfig({
export default buildConfigWithDefaults({
admin: {
css: path.resolve(__dirname, 'styles.scss'),
components: {

View File

@@ -1,6 +1,6 @@
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
export default buildConfig({
export default buildConfigWithDefaults({
collections: [
{
slug: 'arrays',

View File

@@ -1,12 +1,12 @@
import { v4 as uuid } from 'uuid';
import { mapAsync } from '../../src/utilities/mapAsync';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { devUser } from '../credentials';
import { AuthDebug } from './AuthDebug';
export const slug = 'users';
export default buildConfig({
export default buildConfigWithDefaults({
admin: {
user: 'users',
autoLogin: false,

View File

@@ -1,7 +1,7 @@
import { Request } from 'express';
import { Strategy } from 'passport-strategy';
import { Payload } from '../../../src/payload';
import { buildConfig } from '../../buildConfig';
import { buildConfigWithDefaults } from '../../buildConfigWithDefaults';
export const slug = 'users';
export const strategyName = 'test-local';
@@ -41,7 +41,7 @@ export class CustomStrategy extends Strategy {
}
}
export default buildConfig({
export default buildConfigWithDefaults({
admin: {
user: 'users',
},

View File

@@ -1,40 +1,41 @@
import { Config, SanitizedConfig } from '../src/config/types';
import { buildConfig as buildPayloadConfig } from '../src/config/build';
export function buildConfig(config?: Partial<Config>): Promise<SanitizedConfig> {
export function buildConfigWithDefaults(testConfig?: Partial<Config>): Promise<SanitizedConfig> {
const [name] = process.argv.slice(2);
const baseConfig: Config = {
const config: Config = {
telemetry: false,
rateLimit: {
window: 15 * 60 * 100, // 15min default,
max: 9999999999,
},
...config,
...testConfig,
};
baseConfig.admin = {
config.admin = {
autoLogin: process.env.PAYLOAD_PUBLIC_DISABLE_AUTO_LOGIN === 'true' ? false : {
email: 'dev@payloadcms.com',
password: 'test',
},
...(baseConfig.admin || {}),
...(config.admin || {}),
webpack: (webpackConfig) => {
const existingConfig = typeof config?.admin?.webpack === 'function'
? config.admin.webpack(webpackConfig)
const existingConfig = typeof testConfig?.admin?.webpack === 'function'
? testConfig.admin.webpack(webpackConfig)
: webpackConfig;
return {
...existingConfig,
name,
cache: process.env.NODE_ENV === 'test' ? {
type: 'memory',
} : existingConfig.cache,
cache: process.env.NODE_ENV === 'test'
? { type: 'memory' }
: existingConfig.cache,
};
},
};
if (process.env.PAYLOAD_DISABLE_ADMIN === 'true') {
if (typeof baseConfig.admin !== 'object') baseConfig.admin = {};
baseConfig.admin.disable = true;
if (typeof config.admin !== 'object') config.admin = {};
config.admin.disable = true;
}
return buildPayloadConfig(baseConfig);
return buildPayloadConfig(config);
}

View File

@@ -1,7 +1,7 @@
import path from 'path';
import type { CollectionConfig } from '../../src/collections/config/types';
import { devUser } from '../credentials';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
export interface Relation {
id: string;
@@ -30,7 +30,7 @@ const collectionWithName = (collectionSlug: string): CollectionConfig => {
export const slug = 'posts';
export const relationSlug = 'relation';
export default buildConfig({
export default buildConfigWithDefaults({
graphQL: {
schemaOutputFile: path.resolve(__dirname, 'schema.graphql'),
},

View File

@@ -1,6 +1,6 @@
import type { CollectionConfig } from '../../src/collections/config/types';
import { devUser } from '../credentials';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
export interface Relation {
id: string;
@@ -34,7 +34,7 @@ export const customIdSlug = 'custom-id';
export const customIdNumberSlug = 'custom-id-number';
export const errorOnHookSlug = 'error-on-hooks';
export default buildConfig({
export default buildConfigWithDefaults({
endpoints: [
{
path: '/send-test-email',

View File

@@ -1,4 +1,4 @@
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { openAccess } from '../helpers/configHelpers';
import { Config } from '../../src/config/types';
@@ -62,4 +62,4 @@ const config: Config = {
custom: { name: 'Customer portal' },
};
export default buildConfig(config);
export default buildConfigWithDefaults(config);

View File

@@ -1,7 +1,7 @@
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { devUser } from '../credentials';
export default buildConfig({
export default buildConfigWithDefaults({
collections: [
{
slug: 'posts',

View File

@@ -1,6 +1,6 @@
import express, { Response } from 'express';
import { devUser } from '../credentials';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { openAccess } from '../helpers/configHelpers';
import { PayloadRequest } from '../../src/express/types';
import { Config } from '../../src/config/types';
@@ -124,4 +124,4 @@ const MyConfig: Config = {
},
};
export default buildConfig(MyConfig);
export default buildConfigWithDefaults(MyConfig);

View File

@@ -1,9 +1,9 @@
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { ErrorFieldsCollection } from './collections/ErrorFields';
import { devUser } from '../credentials';
import Uploads from './collections/Upload';
export default buildConfig({
export default buildConfigWithDefaults({
collections: [
ErrorFieldsCollection,
Uploads,

View File

@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { devUser } from '../credentials';
export default buildConfig({
export default buildConfigWithDefaults({
collections: [
{
slug: 'blocks-collection',

View File

@@ -1,5 +1,5 @@
import type { CollectionConfig } from '../../src/collections/config/types';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { devUser } from '../credentials';
import { mapAsync } from '../../src/utilities/mapAsync';
import { FilterOptionsProps } from '../../src/fields/config/types';
@@ -33,7 +33,7 @@ const baseRelationshipFields: CollectionConfig['fields'] = [
},
];
export default buildConfig({
export default buildConfigWithDefaults({
collections: [
{
slug,

View File

@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
import path from 'path';
import fs from 'fs';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { devUser } from '../credentials';
import ArrayFields, { arrayDoc } from './collections/Array';
import BlockFields, { blocksDoc } from './collections/Blocks';
@@ -26,7 +26,7 @@ import Uploads2 from './collections/Upload2';
import Uploads3 from './collections/Uploads3';
import RowFields from './collections/Row';
export default buildConfig({
export default buildConfigWithDefaults({
admin: {
webpack: (config) => ({
...config,

View File

@@ -1,5 +1,5 @@
import { devUser } from '../credentials';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
export const slug = 'global';
export const arraySlug = 'array';
@@ -16,7 +16,7 @@ const access = {
update: () => true,
};
export default buildConfig({
export default buildConfigWithDefaults({
localization: {
locales: [englishLocale, spanishLocale],
defaultLocale: englishLocale,

View File

@@ -1,7 +1,7 @@
import path from 'path';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
export default buildConfig({
export default buildConfigWithDefaults({
graphQL: {
schemaOutputFile: path.resolve(__dirname, 'schema.graphql'),
},

View File

@@ -1,4 +1,4 @@
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import TransformHooks from './collections/Transform';
import Hooks, { hooksSlug } from './collections/Hook';
import NestedAfterReadHooks from './collections/NestedAfterReadHooks';
@@ -6,7 +6,7 @@ import ChainingHooks from './collections/ChainingHooks';
import Relations from './collections/Relations';
import Users, { seedHooksUsers } from './collections/Users';
export default buildConfig({
export default buildConfigWithDefaults({
collections: [
TransformHooks,
Hooks,

View File

@@ -1,4 +1,4 @@
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { devUser } from '../credentials';
import { ArrayCollection } from './collections/Array';
import { LocalizedPost, RelationshipLocalized } from './payload-types';
@@ -32,7 +32,7 @@ const openAccess = {
update: () => true,
};
export default buildConfig({
export default buildConfigWithDefaults({
localization: {
locales: [defaultLocale, spanishLocale],
defaultLocale,

View File

@@ -1,9 +1,9 @@
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { devUser } from '../credentials';
export const pagesSlug = 'pages';
export default buildConfig({
export default buildConfigWithDefaults({
collections: [
{
slug: 'users',

View File

@@ -1,10 +1,10 @@
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { devUser } from '../credentials';
import GlobalViewWithRefresh from './GlobalViewWithRefresh';
export const pagesSlug = 'pages';
export default buildConfig({
export default buildConfigWithDefaults({
globals: [
{
slug: 'settings',

View File

@@ -1,6 +1,6 @@
import type { CollectionConfig } from '../../src/collections/config/types';
import { devUser } from '../credentials';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
const openAccess = {
create: () => true,
@@ -41,7 +41,7 @@ export const defaultAccessRelSlug = 'strict-access';
export const chainedRelSlug = 'chained-relation';
export const customIdSlug = 'custom-id-relation';
export const customIdNumberSlug = 'custom-id-number-relation';
export default buildConfig({
export default buildConfigWithDefaults({
collections: [
{
slug,

View File

@@ -1,5 +1,5 @@
import path from 'path';
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import { devUser } from '../credentials';
import getFileByPath from '../../src/uploads/getFileByPath';
import removeFiles from '../helpers/removeFiles';
@@ -14,7 +14,7 @@ export const audioSlug = 'audio';
const mockModulePath = path.resolve(__dirname, './mocks/mockFSModule.js');
export default buildConfig({
export default buildConfigWithDefaults({
admin: {
webpack: (config) => ({
...config,

View File

@@ -1,4 +1,4 @@
import { buildConfig } from '../buildConfig';
import { buildConfigWithDefaults } from '../buildConfigWithDefaults';
import AutosavePosts from './collections/Autosave';
import DraftPosts from './collections/Drafts';
import AutosaveGlobal from './globals/Autosave';
@@ -7,7 +7,7 @@ import DraftGlobal from './globals/Draft';
import VersionPosts from './collections/Versions';
import { draftSlug } from './shared';
export default buildConfig({
export default buildConfigWithDefaults({
collections: [
AutosavePosts,
DraftPosts,

3820
yarn.lock

File diff suppressed because it is too large Load Diff