Skip to content

Commit 1cb1e5e

Browse files
authored
feat(db-*): allows for running migrations in production automatically (#7563)
## Description Introduces a pattern for running migrations upon Payload init in production.
1 parent e069983 commit 1cb1e5e

File tree

19 files changed

+143
-21
lines changed

19 files changed

+143
-21
lines changed

packages/db-mongodb/src/connect.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ export const connect: Connect = async function connect(
5454
this.payload.logger.info('---- DROPPED DATABASE ----')
5555
}
5656
}
57+
58+
if (process.env.NODE_ENV === 'production' && this.prodMigrations) {
59+
await this.migrate({ migrations: this.prodMigrations })
60+
}
5761
} catch (err) {
5862
console.log(err)
5963
this.payload.logger.error(`Error: cannot connect to MongoDB. Details: ${err.message}`, err)

packages/db-mongodb/src/index.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import mongoose from 'mongoose'
88
import path from 'path'
99
import { createDatabaseAdapter } from 'payload'
1010

11-
import type { CollectionModel, GlobalModel } from './types.js'
11+
import type { CollectionModel, GlobalModel, MigrateDownArgs, MigrateUpArgs } from './types.js'
1212

1313
import { connect } from './connect.js'
1414
import { count } from './count.js'
@@ -78,6 +78,11 @@ export interface Args {
7878
* typed as any to avoid dependency
7979
*/
8080
mongoMemoryServer?: MongoMemoryReplSet
81+
prodMigrations?: {
82+
down: (args: MigrateDownArgs) => Promise<void>
83+
name: string
84+
up: (args: MigrateUpArgs) => Promise<void>
85+
}[]
8186
transactionOptions?: TransactionOptions | false
8287
/** The URL to connect to MongoDB or false to start payload and prevent connecting */
8388
url: false | string
@@ -90,6 +95,11 @@ export type MongooseAdapter = {
9095
connection: Connection
9196
globals: GlobalModel
9297
mongoMemoryServer: MongoMemoryReplSet
98+
prodMigrations?: {
99+
down: (args: MigrateDownArgs) => Promise<void>
100+
name: string
101+
up: (args: MigrateUpArgs) => Promise<void>
102+
}[]
93103
sessions: Record<number | string, ClientSession>
94104
versions: {
95105
[slug: string]: CollectionModel
@@ -107,6 +117,11 @@ declare module 'payload' {
107117
connection: Connection
108118
globals: GlobalModel
109119
mongoMemoryServer: MongoMemoryReplSet
120+
prodMigrations?: {
121+
down: (args: MigrateDownArgs) => Promise<void>
122+
name: string
123+
up: (args: MigrateUpArgs) => Promise<void>
124+
}[]
110125
sessions: Record<number | string, ClientSession>
111126
transactionOptions: TransactionOptions
112127
versions: {
@@ -121,6 +136,7 @@ export function mongooseAdapter({
121136
disableIndexHints = false,
122137
migrationDir: migrationDirArg,
123138
mongoMemoryServer,
139+
prodMigrations,
124140
transactionOptions = {},
125141
url,
126142
}: Args): DatabaseAdapterObj {
@@ -167,6 +183,7 @@ export function mongooseAdapter({
167183
migrateFresh,
168184
migrationDir,
169185
payload,
186+
prodMigrations,
170187
queryDrafts,
171188
rollbackTransaction,
172189
updateGlobal,

packages/db-postgres/src/connect.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,8 @@ export const connect: Connect = async function connect(
9191
}
9292

9393
if (typeof this.resolveInitializing === 'function') this.resolveInitializing()
94+
95+
if (process.env.NODE_ENV === 'production' && this.prodMigrations) {
96+
await this.migrate({ migrations: this.prodMigrations })
97+
}
9498
}

packages/db-postgres/src/createMigration.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { CreateMigration } from 'payload'
44
import fs from 'fs'
55
import { createRequire } from 'module'
66
import path from 'path'
7-
import { getPredefinedMigration } from 'payload'
7+
import { getPredefinedMigration, writeMigrationIndex } from 'payload'
88
import prompts from 'prompts'
99
import { fileURLToPath } from 'url'
1010

@@ -115,5 +115,8 @@ export const createMigration: CreateMigration = async function createMigration(
115115
upSQL: upSQL || ` // Migration code`,
116116
}),
117117
)
118+
119+
writeMigrationIndex({ migrationsDir: payload.db.migrationDir })
120+
118121
payload.logger.info({ msg: `Migration created at ${filePath}.ts` })
119122
}

packages/db-postgres/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import {
3232
updateOne,
3333
updateVersion,
3434
} from '@payloadcms/drizzle'
35-
import { type PgSchema, pgEnum, pgSchema, pgTable } from 'drizzle-orm/pg-core'
35+
import { pgEnum, pgSchema, pgTable } from 'drizzle-orm/pg-core'
3636
import { createDatabaseAdapter } from 'payload'
3737

3838
import type { Args, PostgresAdapter } from './types.js'
@@ -94,6 +94,7 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter>
9494
pgSchema: adapterSchema,
9595
pool: undefined,
9696
poolOptions: args.pool,
97+
prodMigrations: args.prodMigrations,
9798
push: args.push,
9899
relations: {},
99100
relationshipsSuffix: args.relationshipsSuffix || '_rels',

packages/db-postgres/src/types.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ export type Args = {
3333
logger?: DrizzleConfig['logger']
3434
migrationDir?: string
3535
pool: PoolConfig
36+
prodMigrations?: {
37+
down: (args: MigrateDownArgs) => Promise<void>
38+
name: string
39+
up: (args: MigrateUpArgs) => Promise<void>
40+
}[]
3641
push?: boolean
3742
relationshipsSuffix?: string
3843
/**
@@ -136,6 +141,11 @@ export type PostgresAdapter = {
136141
pgSchema?: Schema
137142
pool: Pool
138143
poolOptions: Args['pool']
144+
prodMigrations?: {
145+
down: (args: MigrateDownArgs) => Promise<void>
146+
name: string
147+
up: (args: MigrateUpArgs) => Promise<void>
148+
}[]
139149
push: boolean
140150
rejectInitializing: () => void
141151
relations: Record<string, GenericRelation>
@@ -178,6 +188,11 @@ declare module 'payload' {
178188
pgSchema?: { table: PgTableFn } | PgSchema
179189
pool: Pool
180190
poolOptions: Args['pool']
191+
prodMigrations?: {
192+
down: (args: MigrateDownArgs) => Promise<void>
193+
name: string
194+
up: (args: MigrateUpArgs) => Promise<void>
195+
}[]
181196
push: boolean
182197
rejectInitializing: () => void
183198
relationshipsSuffix?: string

packages/db-sqlite/src/connect.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,8 @@ export const connect: Connect = async function connect(
5252
}
5353

5454
if (typeof this.resolveInitializing === 'function') this.resolveInitializing()
55+
56+
if (process.env.NODE_ENV === 'production' && this.prodMigrations) {
57+
await this.migrate({ migrations: this.prodMigrations })
58+
}
5559
}

packages/db-sqlite/src/createMigration.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { CreateMigration } from 'payload'
44
import fs from 'fs'
55
import { createRequire } from 'module'
66
import path from 'path'
7-
import { getPredefinedMigration } from 'payload'
7+
import { getPredefinedMigration, writeMigrationIndex } from 'payload'
88
import prompts from 'prompts'
99
import { fileURLToPath } from 'url'
1010

@@ -112,5 +112,8 @@ export const createMigration: CreateMigration = async function createMigration(
112112
upSQL: upSQL || ` // Migration code`,
113113
}),
114114
)
115+
116+
writeMigrationIndex({ migrationsDir: payload.db.migrationDir })
117+
115118
payload.logger.info({ msg: `Migration created at ${filePath}.ts` })
116119
}

packages/db-sqlite/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export function sqliteAdapter(args: Args): DatabaseAdapterObj<SQLiteAdapter> {
9393
localesSuffix: args.localesSuffix || '_locales',
9494
logger: args.logger,
9595
operators,
96+
prodMigrations: args.prodMigrations,
9697
push: args.push,
9798
relations: {},
9899
relationshipsSuffix: args.relationshipsSuffix || '_rels',

packages/db-sqlite/src/types.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ export type Args = {
1818
localesSuffix?: string
1919
logger?: DrizzleConfig['logger']
2020
migrationDir?: string
21+
prodMigrations?: {
22+
down: (args: MigrateDownArgs) => Promise<void>
23+
name: string
24+
up: (args: MigrateUpArgs) => Promise<void>
25+
}[]
2126
push?: boolean
2227
relationshipsSuffix?: string
2328
schemaName?: string
@@ -100,6 +105,11 @@ export type SQLiteAdapter = {
100105
localesSuffix?: string
101106
logger: DrizzleConfig['logger']
102107
operators: Operators
108+
prodMigrations?: {
109+
down: (args: MigrateDownArgs) => Promise<void>
110+
name: string
111+
up: (args: MigrateUpArgs) => Promise<void>
112+
}[]
103113
push: boolean
104114
rejectInitializing: () => void
105115
relations: Record<string, GenericRelation>
@@ -139,6 +149,11 @@ declare module 'payload' {
139149
initializing: Promise<void>
140150
localesSuffix?: string
141151
logger: DrizzleConfig['logger']
152+
prodMigrations?: {
153+
down: (args: MigrateDownArgs) => Promise<void>
154+
name: string
155+
up: (args: MigrateUpArgs) => Promise<void>
156+
}[]
142157
push: boolean
143158
rejectInitializing: () => void
144159
relationshipsSuffix?: string

0 commit comments

Comments
 (0)