added packages into dockploy
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import { createHash, randomUUID } from 'node:crypto'
|
||||
import { existsSync, readdirSync, readFileSync } from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
function migrationsDir(): string {
|
||||
return path.join(process.cwd(), 'runtime', 'migrations')
|
||||
}
|
||||
|
||||
function splitStatements(sql: string): string[] {
|
||||
return sql
|
||||
.split(/;\s*(?:\r?\n|$)/)
|
||||
.map((part) => part.trim())
|
||||
.filter((part) => part.length > 0 && !part.startsWith('--'))
|
||||
}
|
||||
|
||||
async function waitForDb(prisma: PrismaClient): Promise<void> {
|
||||
let lastError: unknown
|
||||
for (let i = 1; i <= 30; i++) {
|
||||
try {
|
||||
await prisma.$connect()
|
||||
await prisma.$queryRaw`SELECT 1`
|
||||
return
|
||||
} catch (err) {
|
||||
lastError = err
|
||||
console.log(`Waiting for database (${i}/30)...`)
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000))
|
||||
}
|
||||
}
|
||||
throw lastError
|
||||
}
|
||||
|
||||
export async function applyPendingMigrations(): Promise<void> {
|
||||
const dir = migrationsDir()
|
||||
if (!existsSync(dir)) {
|
||||
console.log('No runtime/migrations; skipping migrate')
|
||||
return
|
||||
}
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
try {
|
||||
await waitForDb(prisma)
|
||||
await prisma.$executeRawUnsafe(`
|
||||
CREATE TABLE IF NOT EXISTS "_prisma_migrations" (
|
||||
"id" VARCHAR(36) PRIMARY KEY NOT NULL,
|
||||
"checksum" VARCHAR(64) NOT NULL,
|
||||
"finished_at" TIMESTAMPTZ,
|
||||
"migration_name" VARCHAR(255) NOT NULL,
|
||||
"logs" TEXT,
|
||||
"rolled_back_at" TIMESTAMPTZ,
|
||||
"started_at" TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
"applied_steps_count" INTEGER NOT NULL DEFAULT 0
|
||||
)
|
||||
`)
|
||||
|
||||
const applied = await prisma.$queryRaw<Array<{ migration_name: string }>>`
|
||||
SELECT "migration_name" FROM "_prisma_migrations" WHERE "finished_at" IS NOT NULL
|
||||
`
|
||||
const done = new Set(applied.map((row) => row.migration_name))
|
||||
|
||||
const folders = readdirSync(dir, { withFileTypes: true })
|
||||
.filter((entry) => entry.isDirectory())
|
||||
.map((entry) => entry.name)
|
||||
.sort()
|
||||
|
||||
for (const name of folders) {
|
||||
if (done.has(name)) continue
|
||||
const file = path.join(dir, name, 'migration.sql')
|
||||
if (!existsSync(file)) continue
|
||||
|
||||
const sql = readFileSync(file, 'utf8')
|
||||
const checksum = createHash('sha256').update(sql).digest('hex')
|
||||
const id = randomUUID()
|
||||
console.log(`Applying migration ${name}`)
|
||||
|
||||
await prisma.$executeRaw`
|
||||
INSERT INTO "_prisma_migrations" ("id", "checksum", "migration_name", "started_at", "applied_steps_count")
|
||||
VALUES (${id}, ${checksum}, ${name}, now(), 0)
|
||||
`
|
||||
|
||||
for (const statement of splitStatements(sql)) {
|
||||
await prisma.$executeRawUnsafe(statement)
|
||||
}
|
||||
|
||||
await prisma.$executeRaw`
|
||||
UPDATE "_prisma_migrations"
|
||||
SET "finished_at" = now(), "applied_steps_count" = 1
|
||||
WHERE "id" = ${id}
|
||||
`
|
||||
}
|
||||
console.log('Migrations up to date')
|
||||
} finally {
|
||||
await prisma.$disconnect()
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,13 @@ import { ValidationPipe } from '@nestjs/common';
|
||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||
import { json, urlencoded } from 'express';
|
||||
import { AppModule } from './app.module';
|
||||
import { applyPendingMigrations } from './apply-migrations';
|
||||
|
||||
async function bootstrap() {
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
await applyPendingMigrations();
|
||||
}
|
||||
|
||||
const app = await NestFactory.create(AppModule);
|
||||
|
||||
// تصاویر چک و رسید بهصورت base64 داخل JSON میآیند و از سقف پیشفرض ۱۰۰KB رد میشوند
|
||||
|
||||
Reference in New Issue
Block a user