feat: make PAYLOAD_CONFIG_PATH optional (#2839)

* feat: make PAYLOAD_CONFIG_PATH optional

* hardcode common search paths

* docs: update docs regarding PAYLOAD_CONFIG_PATH

* make the tsConfig parser less prone to errors
This commit is contained in:
Alessio Gravili
2023-08-14 16:46:10 +02:00
committed by GitHub
parent 8a6cbf8a4d
commit 5744de7ec6
2 changed files with 89 additions and 17 deletions

View File

@@ -126,15 +126,23 @@ project-name
here](/docs/admin/webpack#admin-environment-vars) for more info.
</Banner>
### Customizing & overriding the config location
### Customizing & Automating Config Location Detection
By default, the Payload config must be in the root of your current working directory and named either `payload.config.js` or `payload.config.ts` if you're using TypeScript.
Payload is designed to automatically locate your configuration file. By default, it will first look in the root of your current working directory for a file named `payload.config.js` or `payload.config.ts` if you're using TypeScript.
But, you can specify where your Payload config is located as well as what it's named by using the environment variable `PAYLOAD_CONFIG_PATH`. The path you provide via this environment variable can either be absolute or relative to your current working directory.
In development mode, if the configuration file is not found at the root, Payload will attempt to read your `tsconfig.json`, and search in the directory specified in `compilerOptions.rootDir` (typically "src").
In production mode, Payload will first attempt to find the config file in the output directory specified in `compilerOptions.outDir` of your `tsconfig.json`, then fallback to the source directory (`compilerOptions.rootDir`), and finally will check the 'dist' directory.
Please ensure your `tsconfig.json` is properly configured if you want Payload to accurately auto-detect your configuration file location. If `tsconfig.json` does not exist or doesn't specify `rootDir` or `outDir`, Payload will default to the current working directory.
#### Overriding the Config Location
In addition to the above automated detection, you can specify your own location for the Payload config file. This is done by using the environment variable `PAYLOAD_CONFIG_PATH`. The path you provide via this environment variable can either be absolute or relative to your current working directory. This can be useful in situations where your Payload config is not in a standard location, or you wish to switch between multiple configurations.
**Example in package.json:**
```
```json
{
"scripts": {
"dev": "PAYLOAD_CONFIG_PATH=path/to/custom-config.js node server.js",
@@ -142,6 +150,8 @@ But, you can specify where your Payload config is located as well as what it's n
}
```
When `PAYLOAD_CONFIG_PATH` is set, Payload will use this path to load the configuration, bypassing all automated detection.
### Developing within the Config
Payload comes with `isomorphic-fetch` installed which means that even in Node, you can use the `fetch` API just as you would within the browser. No need to import `axios` or similar, unless you want to!

View File

@@ -1,6 +1,43 @@
import path from 'path';
import findUp from 'find-up';
import fs from 'fs';
/**
* Returns the source and output paths from the nearest tsconfig.json file.
* If no tsconfig.json file is found, returns the current working directory.
* @returns An object containing the source and output paths.
*/
const getTSConfigPaths = (): { srcPath: string, outPath: string } => {
const tsConfigPath = findUp.sync('tsconfig.json');
if (!tsConfigPath) {
return { srcPath: process.cwd(), outPath: process.cwd() };
}
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 srcPath = tsConfig.compilerOptions?.rootDir || process.cwd();
const outPath = tsConfig.compilerOptions?.outDir || process.cwd();
return { srcPath, outPath };
} 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
return { srcPath: process.cwd(), outPath: process.cwd() };
}
};
/**
* Searches for a Payload configuration file.
* @returns The absolute path to the Payload configuration file.
* @throws An error if no configuration file is found.
*/
const findConfig = (): string => {
// If the developer has specified a config path,
// format it if relative and use it directly if absolute
@@ -12,21 +49,46 @@ const findConfig = (): string => {
return path.resolve(process.cwd(), process.env.PAYLOAD_CONFIG_PATH);
}
const { srcPath, outPath } = getTSConfigPaths();
const searchPaths = process.env.NODE_ENV === 'production' ? [outPath, srcPath] : [srcPath];
// eslint-disable-next-line no-restricted-syntax
for (const searchPath of searchPaths) {
const configPath = findUp.sync((dir) => {
const tsPath = path.join(dir, 'payload.config.ts');
const hasTS = findUp.sync.exists(tsPath);
if (hasTS) return tsPath;
if (hasTS) {
return tsPath;
}
const jsPath = path.join(dir, 'payload.config.js');
const hasJS = findUp.sync.exists(jsPath);
if (hasJS) return jsPath;
if (hasJS) {
return jsPath;
}
return undefined;
});
}, { cwd: searchPath });
if (configPath) return configPath;
if (configPath) {
return configPath;
}
}
// If no config file is found in the directories defined by tsconfig.json,
// try searching in the 'src' and 'dist' directory as a last resort, as they are most commonly used
if (process.env.NODE_ENV === 'production') {
const distConfigPath = findUp.sync(['payload.config.js', 'payload.config.ts'], { cwd: path.resolve(process.cwd(), 'dist') });
if (distConfigPath) return distConfigPath;
} else {
const srcConfigPath = findUp.sync(['payload.config.js', 'payload.config.ts'], { cwd: path.resolve(process.cwd(), 'src') });
if (srcConfigPath) return srcConfigPath;
}
throw new Error('Error: cannot find Payload config. Please create a configuration file located at the root of your current working directory called "payload.config.js" or "payload.config.ts".');
};