Use tsx watch mode and inject DB URL into .env.example#5
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Updates the Node project scaffolding to improve local development ergonomics by enabling tsx hot-reload watch mode (with env loading) and by generating a dialect-specific DATABASE_URL example in .env.example based on the selected database and project name.
Changes:
- Switch generated
package.jsondev script totsx watch --env-file=.env src/index.ts. - Generate a database-dialect-specific
DATABASE_URLexample in.env.exampleusingoptions.projectNameandoptions.database.
Comments suppressed due to low confidence (1)
src/generators/node/projectBuilder.ts:95
- The generated
package.jsondevscript was changed to usetsx watch --env-file=.env ..., but there’s no test coverage asserting the generated scripts. Consider extending an existing generator test to parsepackage.jsonand verify thedevscript value so changes to the CLI invocation don’t silently break scaffolds.
const pkg = {
name: options.projectName,
version: '0.1.0',
type: 'module',
scripts: {
'dev': 'tsx watch --env-file=.env src/index.ts',
'build': 'tsc',
'typecheck': 'tsc --noEmit',
'db:migrate': 'drizzle-kit migrate',
},
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+136
to
+138
| const databaseUrlExample: Record<GeneratorOptions['database'], string> = { | ||
| postgres: `postgresql://app:app@localhost:5432/${options.projectName}`, | ||
| mysql: `mysql://app:app@localhost:3306/${options.projectName}`, |
Contributor
Author
There was a problem hiding this comment.
It is validated and trimmed:
export async function promptProjectName(initial?: string): Promise<string> {
const value = await clack.text({
message: 'Project name or path?',
initialValue: initial,
validate: (v) => {
const trimmed = v.trim();
if (!trimmed) return 'Project name is required';
if (!basename(trimmed)) return 'Path must include a directory name';
},
});
if (clack.isCancel(value)) {
clack.cancel('Operation cancelled');
process.exit(0);
}
return (value as string).trim();
}
Comment on lines
+135
to
148
| async execute(outputDir: string, options: GeneratorOptions): Promise<void> { | ||
| const databaseUrlExample: Record<GeneratorOptions['database'], string> = { | ||
| postgres: `postgresql://app:app@localhost:5432/${options.projectName}`, | ||
| mysql: `mysql://app:app@localhost:3306/${options.projectName}`, | ||
| sqlite: 'file:./data.db', | ||
| }; | ||
| await writeFile( | ||
| join(outputDir, '.env.example'), | ||
| dedent` | ||
| PIPEDRIVE_CLIENT_ID= | ||
| PIPEDRIVE_CLIENT_SECRET= | ||
| PIPEDRIVE_REDIRECT_URI=http://localhost:3000/oauth/callback | ||
| DATABASE_URL= | ||
| DATABASE_URL=${databaseUrlExample[options.database]} | ||
| PORT=3000 |
|
|
||
| const message = error instanceof Error ? error.message : String(error); | ||
| console.warn( | ||
| \`Database is not ready yet (\${attempt}/\${STARTUP_RETRY_ATTEMPTS}): \${message}\`, |
Contributor
There was a problem hiding this comment.
do we need \ if we're using backticks ` ?
Contributor
Author
There was a problem hiding this comment.
needed in the generator
youssef-saber-3
approved these changes
May 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
tsx src/index.tstotsx watch --env-file=.env src/index.tsfor hot reload and automatic env loadingDATABASE_URLexamples into generated.env.exampleusingoptions.projectNameand the selected database dialectnpm run devwaits up to 60 seconds for the database and migrations before starting Expressmode: default, moving local MySQL host access to127.0.0.1:3307, and aligning.env.examplewith that portpostgres_dataandmysql_dataso switching database choices does not reuse incompatible local data directoriesDatabase startup behavior
localhost:5432and uses apostgres_dataDocker volumelocalhost:3307on the host, maps to container port3306, and uses amysql_dataDocker volumesrc/index.tsretriesrunMigrations()once per second for up to 60 attempts, then starts the server only after migrations succeed42P06and42P07, so repeatednpm run devstarts do not print noisy “already exists, skipping” objectsTest plan
npx vitest run src/generators/node/projectBuilder.test.ts src/generators/node/database.test.tsnpm run typechecknpm run lintnpm run buildnpm run devwith the DB stopped, then starting the DB and confirming the same process reachedServer running on port 3000npm run devstartup no longer prints duplicate Drizzle migration NOTICE objects