Files
payload/test/config/config.ts
Sasha f779e48a58 fix: working bin configuration for custom scripts (#11294)
Previously, the `bin` configuration wasn't working at all.
Possibly because in an ESM environment this cannot work, because
`import` always returns an object with a default export under the
`module` key.
```ts
const script: BinScript = await import(pathToFileURL(userBinScript.scriptPath).toString())
await script(config)
```
Now, this works, but you must define a `script` export from your file.
Attached an integration test that asserts that it actually works. Added
documentation on how to use it, as previously it was missing.
This can be also helpful for plugins.

### Documentation

Using the `bin` configuration property, you can inject your own scripts
to `npx payload`.
Example for `pnpm payload seed`:

Step 1: create `seed.ts` file in the same folder with
`payload.config.ts` with:

```ts
import type { SanitizedConfig } from 'payload'

import payload from 'payload'

// Script must define a "script" function export that accepts the sanitized config
export const script = async (config: SanitizedConfig) => {
  await payload.init({ config })
  await payload.create({ collection: 'pages', data: { title: 'my title' } })
  payload.logger.info('Succesffully seeded!')
  process.exit(0)
}
```

Step 2: add the `seed` script to `bin`:
```ts
export default buildConfig({
  bin: [
    {
      scriptPath: path.resolve(dirname, 'seed.ts'),
      key: 'seed',
    },
  ],
})
```

Now you can run the script using:
```sh
pnpm payload seed
```
2025-02-21 18:15:27 +02:00

136 lines
3.1 KiB
TypeScript

import { fileURLToPath } from 'node:url'
import path from 'path'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
import { devUser } from '../credentials.js'
export default buildConfigWithDefaults({
admin: {
importMap: {
baseDir: path.resolve(dirname),
},
},
collections: [
{
slug: 'pages',
access: {
create: () => true,
delete: () => true,
read: () => true,
update: () => true,
},
custom: {
externalLink: 'https://foo.bar',
},
endpoints: [
{
custom: { examples: [{ type: 'response', value: { message: 'hi' } }] },
handler: () => {
return Response.json({ message: 'hi' })
},
method: 'get',
path: '/hello',
},
],
fields: [
{
name: 'title',
type: 'text',
custom: {
description: 'The title of this page',
},
},
{
name: 'myBlocks',
type: 'blocks',
blocks: [
{
slug: 'blockOne',
custom: {
description: 'The blockOne of this page',
},
fields: [
{
name: 'blockOneField',
type: 'text',
},
{
name: 'blockTwoField',
type: 'text',
},
],
},
],
custom: {
description: 'The blocks of this page',
},
},
],
},
],
custom: { name: 'Customer portal' },
endpoints: [
{
custom: { description: 'Get the sanitized payload config' },
handler: (req) => {
return Response.json(req.payload.config)
},
method: 'get',
path: '/config',
},
],
bin: [
{
scriptPath: path.resolve(dirname, 'customScript.ts'),
key: 'start-server',
},
],
globals: [
{
slug: 'my-global',
custom: { foo: 'bar' },
endpoints: [
{
custom: { params: [{ name: 'name', type: 'string', in: 'query' }] },
handler: (req) => {
const sp = new URL(req.url).searchParams
return Response.json({ message: `Hi ${sp.get('name')}!` })
},
method: 'get',
path: '/greet',
},
],
fields: [
{
name: 'title',
type: 'text',
custom: {
description: 'The title of my global',
},
},
],
},
],
onInit: async (payload) => {
const { totalDocs } = await payload.count({ collection: 'users' })
if (totalDocs === 0) {
await payload.create({
collection: 'users',
data: {
email: devUser.email,
password: devUser.password,
},
})
}
},
typescript: {
outputFile: path.resolve(dirname, 'payload-types.ts'),
},
cors: {
origins: '*',
headers: ['x-custom-header'],
},
})