fix(cpa): updates CPAs w/ vercel-postgres db types to use POSTGRES_URL & updates .env.example to use generic env var strings (#10027)

CPA projects generated with the `vercel-postgres` db type were not
receiving the proper DB env vars in the .env.example & .env files

With the `vercel-postgres` db type, the DB env var needs to be
`POSTGRES_URL` not `DATABASE_URI`.

Additionally, updates the generated .env.example file to show generic
env var strings.

#### Blank w/ MongoDB:
- `.env.example`:
```
DATABASE_URI=mongodb://127.0.0.1/your-database-name
PAYLOAD_SECRET=YOUR_SECRET_HERE
```
- `.env`:
```
# Added by Payload
DATABASE_URI=mongodb://127.0.0.1/test-cpa-blank-mongodb
PAYLOAD_SECRET=aef857429edc7f42a90bb374
```

#### Blank w/ Postgres:
- `.env.example`:
```
DATABASE_URI=postgres://postgres:<password>@127.0.0.1:5432/your-database-name
PAYLOAD_SECRET=YOUR_SECRET_HERE
```
- `.env`:
```
# Added by Payload
DATABASE_URI=postgres://postgres:<password>@127.0.0.1:5432/test-cpa-blank-postgres
PAYLOAD_SECRET=241bfe11fbe0a56dd9757019
```

#### Blank w/ SQLite:
- `.env.example`:
```
DATABASE_URI=file:./your-database-name.db
PAYLOAD_SECRET=YOUR_SECRET_HERE
```
- `.env`:
```
# Added by Payload
DATABASE_URI=file:./test-cpa-blank-sqlite.db
PAYLOAD_SECRET=a7808731b93240a73a11930c
```

#### Blank w/ vercel-postgres:
- `.env.example`:
```
POSTGRES_URL=postgres://postgres:<password>@127.0.0.1:5432/your-database-name
PAYLOAD_SECRET=YOUR_SECRET_HERE
```
- `.env`:
```
# Added by Payload
POSTGRES_URL=postgres://postgres:<password>@127.0.0.1:5432/test-cpa-blank-vercel-postgres
PAYLOAD_SECRET=af3951e923e8e4662c9c3d9e
```

Fixes #9996
This commit is contained in:
Patrik
2024-12-17 14:13:00 -05:00
committed by GitHub
parent b0b2fc6c47
commit 70666a0f7b
2 changed files with 68 additions and 43 deletions

View File

@@ -4,42 +4,66 @@ import path from 'path'
import type { CliArgs, DbType, ProjectTemplate } from '../types.js'
import { debug, error } from '../utils/log.js'
import { dbChoiceRecord } from './select-db.js'
const updateEnvVariables = (
contents: string,
const updateEnvExampleVariables = (contents: string, databaseType: DbType | undefined): string => {
return contents
.split('\n')
.map((line) => {
if (line.startsWith('#') || !line.includes('=')) {
return line // Preserve comments and unrelated lines
}
const [key] = line.split('=')
if (key === 'DATABASE_URI' || key === 'POSTGRES_URL' || key === 'MONGODB_URI') {
const dbChoice = databaseType ? dbChoiceRecord[databaseType] : null
if (dbChoice) {
const placeholderUri = `${dbChoice.dbConnectionPrefix}your-database-name${
dbChoice.dbConnectionSuffix || ''
}`
return databaseType === 'vercel-postgres'
? `POSTGRES_URL=${placeholderUri}`
: `DATABASE_URI=${placeholderUri}`
}
return `DATABASE_URI=your-database-connection-here` // Fallback
}
if (key === 'PAYLOAD_SECRET' || key === 'PAYLOAD_SECRET_KEY') {
return `PAYLOAD_SECRET=YOUR_SECRET_HERE`
}
return line
})
.join('\n')
}
const generateEnvContent = (
existingEnv: string,
databaseType: DbType | undefined,
databaseUri: string,
payloadSecret: string,
): string => {
return contents
const dbKey = databaseType === 'vercel-postgres' ? 'POSTGRES_URL' : 'DATABASE_URI'
const envVars: Record<string, string> = {}
existingEnv
.split('\n')
.filter((e) => e)
.map((line) => {
if (line.startsWith('#') || !line.includes('=')) {
return line
}
const [key, ...valueParts] = line.split('=')
let value = valueParts.join('=')
if (
key === 'MONGODB_URI' ||
key === 'MONGO_URL' ||
key === 'DATABASE_URI' ||
key === 'POSTGRES_URL'
) {
value = databaseUri
if (databaseType === 'vercel-postgres') {
value = databaseUri
}
}
if (key === 'PAYLOAD_SECRET' || key === 'PAYLOAD_SECRET_KEY') {
value = payloadSecret
}
return `${key}=${value}`
.filter((line) => line.includes('=') && !line.startsWith('#'))
.forEach((line) => {
const [key, value] = line.split('=')
envVars[key] = value
})
// Override specific keys
envVars[dbKey] = databaseUri
envVars['PAYLOAD_SECRET'] = payloadSecret
// Rebuild content
return Object.entries(envVars)
.map(([key, value]) => `${key}=${value}`)
.join('\n')
}
@@ -65,6 +89,7 @@ export async function manageEnvFiles(args: {
try {
let updatedExampleContents: string
// Update .env.example
if (template?.type === 'starter') {
if (!fs.existsSync(envExamplePath)) {
error(`.env.example file not found at ${envExamplePath}`)
@@ -72,25 +97,25 @@ export async function manageEnvFiles(args: {
}
const envExampleContents = await fs.readFile(envExamplePath, 'utf8')
updatedExampleContents = updateEnvVariables(
envExampleContents,
databaseType,
databaseUri,
payloadSecret,
)
updatedExampleContents = updateEnvExampleVariables(envExampleContents, databaseType)
await fs.writeFile(envExamplePath, updatedExampleContents)
await fs.writeFile(envExamplePath, updatedExampleContents.trimEnd() + '\n')
debug(`.env.example file successfully updated`)
} else {
updatedExampleContents = `# Added by Payload\nDATABASE_URI=${databaseUri}\nPAYLOAD_SECRET=${payloadSecret}\n`
updatedExampleContents = `# Added by Payload\nDATABASE_URI=your-connection-string-here\nPAYLOAD_SECRET=YOUR_SECRET_HERE\n`
await fs.writeFile(envExamplePath, updatedExampleContents.trimEnd() + '\n')
}
const existingEnvContents = fs.existsSync(envPath) ? await fs.readFile(envPath, 'utf8') : ''
const updatedEnvContents = existingEnvContents
? `${existingEnvContents}\n# Added by Payload\n${updatedExampleContents}`
: `# Added by Payload\n${updatedExampleContents}`
// Merge existing variables and create or update .env
const envExampleContents = await fs.readFile(envExamplePath, 'utf8')
const envContent = generateEnvContent(
envExampleContents,
databaseType,
databaseUri,
payloadSecret,
)
await fs.writeFile(envPath, `# Added by Payload\n${envContent.trimEnd()}\n`)
await fs.writeFile(envPath, updatedEnvContents)
debug(`.env file successfully created or updated`)
} catch (err: unknown) {
error('Unable to manage environment files')

View File

@@ -10,7 +10,7 @@ type DbChoice = {
value: DbType
}
const dbChoiceRecord: Record<DbType, DbChoice> = {
export const dbChoiceRecord: Record<DbType, DbChoice> = {
mongodb: {
dbConnectionPrefix: 'mongodb://127.0.0.1/',
title: 'MongoDB',