create-payload-app
Advanced tools
Comparing version
@@ -10,3 +10,2 @@ import { jest } from '@jest/globals'; | ||
import { getValidTemplates } from './templates.js'; | ||
import { manageEnvFiles } from './manage-env-files.js'; | ||
describe('createProject', ()=>{ | ||
@@ -134,57 +133,2 @@ let projectDir; | ||
}); | ||
describe('managing env files', ()=>{ | ||
it('updates .env files without overwriting existing data', async ()=>{ | ||
const envFilePath = path.join(projectDir, '.env'); | ||
const envExampleFilePath = path.join(projectDir, '.env.example'); | ||
fse.ensureDirSync(projectDir); | ||
fse.ensureFileSync(envFilePath); | ||
fse.ensureFileSync(envExampleFilePath); | ||
const initialEnvContent = `CUSTOM_VAR=custom-value\nDATABASE_URI=old-connection\n`; | ||
const initialEnvExampleContent = `CUSTOM_VAR=custom-value\nDATABASE_URI=old-connection\nPAYLOAD_SECRET=YOUR_SECRET_HERE\n`; | ||
fse.writeFileSync(envFilePath, initialEnvContent); | ||
fse.writeFileSync(envExampleFilePath, initialEnvExampleContent); | ||
await manageEnvFiles({ | ||
cliArgs: { | ||
'--debug': true | ||
}, | ||
databaseType: 'mongodb', | ||
databaseUri: 'mongodb://localhost:27017/test', | ||
payloadSecret: 'test-secret', | ||
projectDir, | ||
template: undefined | ||
}); | ||
const updatedEnvContent = fse.readFileSync(envFilePath, 'utf-8'); | ||
expect(updatedEnvContent).toContain('CUSTOM_VAR=custom-value'); | ||
expect(updatedEnvContent).toContain('DATABASE_URI=mongodb://localhost:27017/test'); | ||
expect(updatedEnvContent).toContain('PAYLOAD_SECRET=test-secret'); | ||
const updatedEnvExampleContent = fse.readFileSync(envExampleFilePath, 'utf-8'); | ||
expect(updatedEnvExampleContent).toContain('CUSTOM_VAR=custom-value'); | ||
expect(updatedEnvContent).toContain('DATABASE_URI=mongodb://localhost:27017/test'); | ||
expect(updatedEnvContent).toContain('PAYLOAD_SECRET=test-secret'); | ||
}); | ||
it('creates .env and .env.example if they do not exist', async ()=>{ | ||
const envFilePath = path.join(projectDir, '.env'); | ||
const envExampleFilePath = path.join(projectDir, '.env.example'); | ||
fse.ensureDirSync(projectDir); | ||
if (fse.existsSync(envFilePath)) fse.removeSync(envFilePath); | ||
if (fse.existsSync(envExampleFilePath)) fse.removeSync(envExampleFilePath); | ||
await manageEnvFiles({ | ||
cliArgs: { | ||
'--debug': true | ||
}, | ||
databaseUri: '', | ||
payloadSecret: '', | ||
projectDir, | ||
template: undefined | ||
}); | ||
expect(fse.existsSync(envFilePath)).toBe(true); | ||
expect(fse.existsSync(envExampleFilePath)).toBe(true); | ||
const updatedEnvContent = fse.readFileSync(envFilePath, 'utf-8'); | ||
expect(updatedEnvContent).toContain('DATABASE_URI=your-connection-string-here'); | ||
expect(updatedEnvContent).toContain('PAYLOAD_SECRET=YOUR_SECRET_HERE'); | ||
const updatedEnvExampleContent = fse.readFileSync(envExampleFilePath, 'utf-8'); | ||
expect(updatedEnvExampleContent).toContain('DATABASE_URI=your-connection-string-here'); | ||
expect(updatedEnvExampleContent).toContain('PAYLOAD_SECRET=YOUR_SECRET_HERE'); | ||
}); | ||
}); | ||
}); | ||
@@ -191,0 +135,0 @@ }); |
@@ -5,31 +5,38 @@ import fs from 'fs-extra'; | ||
import { dbChoiceRecord } from './select-db.js'; | ||
const updateEnvExampleVariables = (contents, databaseType, payloadSecret, databaseUri)=>{ | ||
const seenKeys = new Set(); | ||
const updatedEnv = contents.split('\n').map((line)=>{ | ||
const updateEnvExampleVariables = (contents, databaseType)=>{ | ||
return contents.split('\n').map((line)=>{ | ||
if (line.startsWith('#') || !line.includes('=')) { | ||
return line; | ||
return line // Preserve comments and unrelated lines | ||
; | ||
} | ||
const [key] = line.split('='); | ||
if (!key) { | ||
return; | ||
} | ||
if (key === 'DATABASE_URI' || key === 'POSTGRES_URL' || key === 'MONGODB_URI') { | ||
const dbChoice = databaseType ? dbChoiceRecord[databaseType] : null; | ||
if (dbChoice) { | ||
const placeholderUri = databaseUri ? databaseUri : `${dbChoice.dbConnectionPrefix}your-database-name${dbChoice.dbConnectionSuffix || ''}`; | ||
line = databaseType === 'vercel-postgres' ? `POSTGRES_URL=${placeholderUri}` : `DATABASE_URI=${placeholderUri}`; | ||
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') { | ||
line = `PAYLOAD_SECRET=${payloadSecret || 'YOUR_SECRET_HERE'}`; | ||
return `PAYLOAD_SECRET=YOUR_SECRET_HERE`; | ||
} | ||
// handles dupes | ||
if (seenKeys.has(key)) { | ||
return null; | ||
} | ||
seenKeys.add(key); | ||
return line; | ||
}).filter(Boolean).reverse().join('\n'); | ||
return updatedEnv; | ||
}).join('\n'); | ||
}; | ||
const generateEnvContent = (existingEnv, databaseType, databaseUri, payloadSecret)=>{ | ||
const dbKey = databaseType === 'vercel-postgres' ? 'POSTGRES_URL' : 'DATABASE_URI'; | ||
const envVars = {}; | ||
existingEnv.split('\n').filter((line)=>line.includes('=') && !line.startsWith('#')).forEach((line)=>{ | ||
const [key, value] = line.split('='); | ||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve | ||
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'); | ||
}; | ||
/** Parse and swap .env.example values and write .env */ export async function manageEnvFiles(args) { | ||
@@ -44,41 +51,27 @@ const { cliArgs, databaseType, databaseUri, payloadSecret, projectDir, template } = args; | ||
const envPath = path.join(projectDir, '.env'); | ||
const emptyEnvContent = `# Added by Payload\nDATABASE_URI=your-connection-string-here\nPAYLOAD_SECRET=YOUR_SECRET_HERE\n`; | ||
try { | ||
let updatedExampleContents; | ||
if (template?.type === 'plugin') { | ||
if (debugFlag) { | ||
debug(`plugin template detected - no .env added .env.example added`); | ||
// Update .env.example | ||
if (template?.type === 'starter') { | ||
if (!fs.existsSync(envExamplePath)) { | ||
error(`.env.example file not found at ${envExamplePath}`); | ||
process.exit(1); | ||
} | ||
return; | ||
} | ||
if (!fs.existsSync(envExamplePath)) { | ||
updatedExampleContents = updateEnvExampleVariables(emptyEnvContent, databaseType, payloadSecret, databaseUri); | ||
await fs.writeFile(envExamplePath, updatedExampleContents); | ||
if (debugFlag) { | ||
debug(`.env.example file successfully created`); | ||
} | ||
} else { | ||
const envExampleContents = await fs.readFile(envExamplePath, 'utf8'); | ||
const mergedEnvs = envExampleContents + '\n' + emptyEnvContent; | ||
updatedExampleContents = updateEnvExampleVariables(mergedEnvs, databaseType, payloadSecret, databaseUri); | ||
await fs.writeFile(envExamplePath, updatedExampleContents); | ||
updatedExampleContents = updateEnvExampleVariables(envExampleContents, databaseType); | ||
await fs.writeFile(envExamplePath, updatedExampleContents.trimEnd() + '\n'); | ||
if (debugFlag) { | ||
debug(`.env.example file successfully updated`); | ||
} | ||
} | ||
if (!fs.existsSync(envPath)) { | ||
const envContent = updateEnvExampleVariables(emptyEnvContent, databaseType, payloadSecret, databaseUri); | ||
await fs.writeFile(envPath, envContent); | ||
if (debugFlag) { | ||
debug(`.env file successfully created`); | ||
} | ||
} else { | ||
const envContents = await fs.readFile(envPath, 'utf8'); | ||
const mergedEnvs = envContents + '\n' + emptyEnvContent; | ||
const updatedEnvContents = updateEnvExampleVariables(mergedEnvs, databaseType, payloadSecret, databaseUri); | ||
await fs.writeFile(envPath, updatedEnvContents); | ||
if (debugFlag) { | ||
debug(`.env file successfully updated`); | ||
} | ||
updatedExampleContents = `# Added by Payload\nDATABASE_URI=your-connection-string-here\nPAYLOAD_SECRET=YOUR_SECRET_HERE\n`; | ||
await fs.writeFile(envExamplePath, updatedExampleContents.trimEnd() + '\n'); | ||
} | ||
// 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`); | ||
if (debugFlag) { | ||
debug(`.env file successfully created or updated`); | ||
} | ||
} catch (err) { | ||
@@ -85,0 +78,0 @@ error('Unable to manage environment files'); |
{ | ||
"name": "create-payload-app", | ||
"version": "3.37.0-canary.2", | ||
"version": "3.37.0-internal.5fa0226", | ||
"homepage": "https://payloadcms.com", | ||
@@ -5,0 +5,0 @@ "repository": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
272641
-2.99%2857
-2.16%