feat: add database migration CLI and entrypoint script

- Introduced a new entrypoint script to handle database migrations before starting the application.
- Implemented CLI commands for database migration, including argument parsing and execution logic.
- Updated Dockerfile to copy the entrypoint script and set it as the container's entrypoint.

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei
2025-11-11 17:53:23 +08:00
parent f4f66810c1
commit 7eebdb6083
4 changed files with 74 additions and 0 deletions

View File

@@ -32,6 +32,9 @@ WORKDIR /app
RUN apk add --no-cache perl
COPY --from=builder /workspace/be/apps/core/dist ./dist
COPY --from=builder /workspace/be/packages/db/migrations ./migrations
COPY --from=builder /workspace/be/apps/core/docker-entrypoint.sh ./docker-entrypoint.sh
RUN chmod +x ./docker-entrypoint.sh
RUN if [ -f dist/package.json ]; then \
cd dist && \
@@ -40,4 +43,5 @@ RUN if [ -f dist/package.json ]; then \
EXPOSE 1841
ENTRYPOINT ["./docker-entrypoint.sh"]
CMD ["node", "./dist/main.js"]

View File

@@ -0,0 +1,10 @@
#!/bin/sh
set -eu
echo "[entrypoint] Running database migrations..."
node ./dist/main.js db:migrate
echo "[entrypoint] Starting application..."
exec "$@"

View File

@@ -1,3 +1,5 @@
import type { MigrationCliOptions } from './migrate'
import { handleMigrationCli, parseMigrationCliArgs } from './migrate'
import type { ResetCliOptions } from './reset-superadmin'
import { handleResetSuperAdminPassword, parseResetCliArgs } from './reset-superadmin'
@@ -9,6 +11,14 @@ type CliCommand<TOptions> = {
}
const cliCommands: Array<CliCommand<unknown>> = [
{
name: 'db:migrate',
parse: parseMigrationCliArgs,
execute: (options) => handleMigrationCli(options as MigrationCliOptions),
onError: (error) => {
console.error('Database migration failed', error)
},
},
{
name: 'reset-superadmin-password',
parse: parseResetCliArgs,

View File

@@ -0,0 +1,50 @@
import path from 'node:path'
import { createLogger } from '@afilmory/framework'
import { drizzle } from 'drizzle-orm/node-postgres'
import { migrate } from 'drizzle-orm/node-postgres/migrator'
import { Pool } from 'pg'
import { DatabaseConfig } from '../database/database.config'
const logger = createLogger('CLI:DB_MIGRATE')
export interface MigrationCliOptions {
readonly command: 'db:migrate'
}
export function parseMigrationCliArgs(argv: readonly string[]): MigrationCliOptions | null {
if (argv.length === 0) {
return null
}
if (argv[0] !== 'db:migrate') {
return null
}
return { command: 'db:migrate' }
}
export async function handleMigrationCli(_: MigrationCliOptions): Promise<void> {
const databaseConfig = new DatabaseConfig()
const options = databaseConfig.getOptions()
const pool = new Pool({
connectionString: options.url,
max: options.max,
idleTimeoutMillis: options.idleTimeoutMillis,
connectionTimeoutMillis: options.connectionTimeoutMillis,
})
try {
const db = drizzle(pool)
logger.info('Applying database migrations...')
await migrate(db, {
migrationsFolder: path.resolve(process.cwd(), 'migrations'),
})
logger.info('Database migrations applied successfully')
} finally {
await pool.end()
}
}