chore(cpa): updates .env.example env vars along side .env vars based on selected DB (#9757)

### What?

Previously, the create-payload-app install would properly update the env
vars in the new created `.env` file but kept outdated env vars in the
`.env.example` file.

I.e

If selecting a `postgres` DB for the blank or website template:

`.env` --> `DATABASE_URI` -->
`postgres://postgres:<password>@127.0.0.1:5432/test-cpa`

`.env.example` --> `DATABASE_URI` -->
`mongodb://127.0.0.1/payload-template-blank-3-0`

### Now

`.env` --> `DATABASE_URI` -->
`postgres://postgres:<password>@127.0.0.1:5432/test-cpa`

`.env.example` --> `DATABASE_URI` -->
`postgres://postgres:<password>@127.0.0.1:5432/test-cpa`
This commit is contained in:
Patrik
2024-12-06 14:52:11 -05:00
committed by GitHub
parent a1a0a07ff0
commit 1aa23d3ea3
3 changed files with 108 additions and 87 deletions

View File

@@ -0,0 +1,102 @@
import fs from 'fs-extra'
import path from 'path'
import type { CliArgs, DbType, ProjectTemplate } from '../types.js'
import { debug, error } from '../utils/log.js'
const updateEnvVariables = (
contents: string,
databaseType: DbType | undefined,
databaseUri: string,
payloadSecret: string,
): string => {
return contents
.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}`
})
.join('\n')
}
/** Parse and swap .env.example values and write .env */
export async function manageEnvFiles(args: {
cliArgs: CliArgs
databaseType?: DbType
databaseUri: string
payloadSecret: string
projectDir: string
template?: ProjectTemplate
}): Promise<void> {
const { cliArgs, databaseType, databaseUri, payloadSecret, projectDir, template } = args
if (cliArgs['--dry-run']) {
debug(`DRY RUN: Environment files managed`)
return
}
const envExamplePath = path.join(projectDir, '.env.example')
const envPath = path.join(projectDir, '.env')
try {
let updatedExampleContents: string
if (template?.type === 'starter') {
if (!fs.existsSync(envExamplePath)) {
error(`.env.example file not found at ${envExamplePath}`)
process.exit(1)
}
const envExampleContents = await fs.readFile(envExamplePath, 'utf8')
updatedExampleContents = updateEnvVariables(
envExampleContents,
databaseType,
databaseUri,
payloadSecret,
)
await fs.writeFile(envExamplePath, updatedExampleContents)
debug(`.env.example file successfully updated`)
} else {
updatedExampleContents = `# Added by Payload\nDATABASE_URI=${databaseUri}\nPAYLOAD_SECRET=${payloadSecret}\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}`
await fs.writeFile(envPath, updatedEnvContents)
debug(`.env file successfully created or updated`)
} catch (err: unknown) {
error('Unable to manage environment files')
if (err instanceof Error) {
error(err.message)
}
process.exit(1)
}
}

View File

@@ -1,84 +0,0 @@
import fs from 'fs-extra'
import path from 'path'
import type { CliArgs, DbType, ProjectTemplate } from '../types.js'
import { debug, error } from '../utils/log.js'
/** Parse and swap .env.example values and write .env */
export async function writeEnvFile(args: {
cliArgs: CliArgs
databaseType?: DbType
databaseUri: string
payloadSecret: string
projectDir: string
template?: ProjectTemplate
}): Promise<void> {
const { cliArgs, databaseType, databaseUri, payloadSecret, projectDir, template } = args
if (cliArgs['--dry-run']) {
debug(`DRY RUN: .env file created`)
return
}
const envOutputPath = path.join(projectDir, '.env')
try {
let fileContents: string
if (template?.type === 'starter') {
// Parse .env file into key/value pairs
const envExample = path.join(projectDir, '.env.example')
const envFile = await fs.readFile(envExample, 'utf8')
fileContents =
`# Added by Payload\n` +
envFile
.split('\n')
.filter((e) => e)
.map((line) => {
if (line.startsWith('#') || !line.includes('=')) {
return line
}
const split = line.split('=')
let key = split[0]
let value = split[1]
if (
key === 'MONGODB_URI' ||
key === 'MONGO_URL' ||
key === 'DATABASE_URI' ||
key === 'POSTGRES_URL'
) {
if (databaseType === 'vercel-postgres') {
key = 'POSTGRES_URL'
}
value = databaseUri
}
if (key === 'PAYLOAD_SECRET' || key === 'PAYLOAD_SECRET_KEY') {
value = payloadSecret
}
return `${key}=${value}`
})
.join('\n')
} else {
fileContents = `# Added by Payload\nDATABASE_URI=${databaseUri}\nPAYLOAD_SECRET=${payloadSecret}\n`
}
if (fs.existsSync(envOutputPath)) {
const existingEnv = await fs.readFile(envOutputPath, 'utf8')
const newEnv = existingEnv + '\n# Added by Payload' + fileContents
await fs.writeFile(envOutputPath, newEnv)
} else {
await fs.writeFile(envOutputPath, fileContents)
}
} catch (err: unknown) {
error('Unable to write .env file')
if (err instanceof Error) {
error(err.message)
}
process.exit(1)
}
}

View File

@@ -13,12 +13,12 @@ import { createProject } from './lib/create-project.js'
import { generateSecret } from './lib/generate-secret.js'
import { getPackageManager } from './lib/get-package-manager.js'
import { getNextAppDetails, initNext } from './lib/init-next.js'
import { manageEnvFiles } from './lib/manage-env-files.js'
import { parseProjectName } from './lib/parse-project-name.js'
import { parseTemplate } from './lib/parse-template.js'
import { selectDb } from './lib/select-db.js'
import { getValidTemplates, validateTemplate } from './lib/templates.js'
import { updatePayloadInProject } from './lib/update-payload-in-project.js'
import { writeEnvFile } from './lib/write-env-file.js'
import { debug, error, info } from './utils/log.js'
import {
feedbackOutro,
@@ -181,7 +181,7 @@ export class Main {
},
})
await writeEnvFile({
await manageEnvFiles({
cliArgs: this.args,
databaseType: dbDetails.type,
databaseUri: dbDetails.dbUri,
@@ -230,6 +230,7 @@ export class Main {
case 'starter': {
const dbDetails = await selectDb(this.args, projectName)
const payloadSecret = generateSecret()
await createProject({
cliArgs: this.args,
dbDetails,
@@ -238,7 +239,8 @@ export class Main {
projectName,
template,
})
await writeEnvFile({
await manageEnvFiles({
cliArgs: this.args,
databaseType: dbDetails.type,
databaseUri: dbDetails.dbUri,
@@ -246,6 +248,7 @@ export class Main {
projectDir,
template,
})
break
}
}