Skip to content

Use tsx watch mode and inject DB URL into .env.example#5

Merged
dmitriyeff merged 4 commits into
masterfrom
AINATIVEM-watch-mode
May 12, 2026
Merged

Use tsx watch mode and inject DB URL into .env.example#5
dmitriyeff merged 4 commits into
masterfrom
AINATIVEM-watch-mode

Conversation

@dmitriyeff
Copy link
Copy Markdown
Contributor

@dmitriyeff dmitriyeff commented May 11, 2026

Summary

  • Switch dev script from tsx src/index.ts to tsx watch --env-file=.env src/index.ts for hot reload and automatic env loading
  • Inject database-specific DATABASE_URL examples into generated .env.example using options.projectName and the selected database dialect
  • Add generated startup retry logic so npm run dev waits up to 60 seconds for the database and migrations before starting Express
  • Improve generated MySQL connectivity by setting Drizzle MySQL mode: default, moving local MySQL host access to 127.0.0.1:3307, and aligning .env.example with that port
  • Split generated Docker volumes into postgres_data and mysql_data so switching database choices does not reuse incompatible local data directories
  • Suppress benign Postgres duplicate schema/table NOTICE logs from Drizzle migration startup while preserving other Postgres notices

Database startup behavior

  • Postgres keeps localhost:5432 and uses a postgres_data Docker volume
  • MySQL uses localhost:3307 on the host, maps to container port 3306, and uses a mysql_data Docker volume
  • Generated src/index.ts retries runMigrations() once per second for up to 60 attempts, then starts the server only after migrations succeed
  • Generated Postgres clients filter migration NOTICE codes 42P06 and 42P07, so repeated npm run dev starts do not print noisy “already exists, skipping” objects

Test plan

  • npx vitest run src/generators/node/projectBuilder.test.ts src/generators/node/database.test.ts
  • npm run typecheck
  • npm run lint
  • npm run build
  • Verified generated app startup retry by starting npm run dev with the DB stopped, then starting the DB and confirming the same process reached Server running on port 3000
  • Verified generated Postgres and MySQL containers can start cleanly with separate volumes and apply migrations
  • Verified repeated Postgres npm run dev startup no longer prints duplicate Drizzle migration NOTICE objects

Copilot AI review requested due to automatic review settings May 11, 2026 13:56
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.json dev script to tsx watch --env-file=.env src/index.ts.
  • Generate a database-dialect-specific DATABASE_URL example in .env.example using options.projectName and options.database.
Comments suppressed due to low confidence (1)

src/generators/node/projectBuilder.ts:95

  • The generated package.json dev script was changed to use tsx watch --env-file=.env ..., but there’s no test coverage asserting the generated scripts. Consider extending an existing generator test to parse package.json and verify the dev script 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 thread src/generators/node/projectBuilder.ts Outdated
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}`,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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}\`,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need \ if we're using backticks ` ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needed in the generator

@dmitriyeff dmitriyeff merged commit 7851306 into master May 12, 2026
1 check passed
@dmitriyeff dmitriyeff deleted the AINATIVEM-watch-mode branch May 12, 2026 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants