Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
213 lines
8.4 KiB
Plaintext
213 lines
8.4 KiB
Plaintext
import { hasLocalizeStatusEnabled } from '../../../../utilities/getVersionsConfig.js';
|
|
import { toSnakeCase } from '../shared.js';
|
|
export async function down(args) {
|
|
const { collectionSlug, db, globalSlug, payload, sql } = args;
|
|
if (!collectionSlug && !globalSlug) {
|
|
throw new Error('Either collectionSlug or globalSlug must be provided');
|
|
}
|
|
if (collectionSlug && globalSlug) {
|
|
throw new Error('Cannot provide both collectionSlug and globalSlug');
|
|
}
|
|
const entitySlug = collectionSlug || globalSlug;
|
|
// Convert camelCase slugs to snake_case and add version prefix/suffix
|
|
const versionsTable = collectionSlug ? `_${toSnakeCase(collectionSlug)}_v` : `_${toSnakeCase(globalSlug)}_v`;
|
|
const localesTable = `${versionsTable}_locales`;
|
|
if (!payload.config.localization) {
|
|
throw new Error('Localization is not enabled in payload config');
|
|
}
|
|
const entityConfig = collectionSlug ? payload.config.collections.find((c)=>c.slug === collectionSlug) : payload.config.globals.find((g)=>g.slug === globalSlug);
|
|
if (!entityConfig) {
|
|
throw new Error(`${collectionSlug ? 'Collection' : 'Global'} not found: ${collectionSlug || globalSlug}`);
|
|
}
|
|
if (hasLocalizeStatusEnabled(entityConfig)) {
|
|
throw new Error(`${entitySlug} has localizeStatus enabled, cannot run down migration. ` + `Please disable localizeStatus in your config before rolling back this migration.`);
|
|
}
|
|
const defaultLocale = payload.config.localization.defaultLocale;
|
|
payload.logger.info({
|
|
msg: `Rolling back _status localization migration for ${collectionSlug ? 'collection' : 'global'}: ${entitySlug}`
|
|
});
|
|
// 1. Restore version__status column to main table
|
|
payload.logger.info({
|
|
msg: `Restoring version__status column to ${versionsTable}`
|
|
});
|
|
await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
ALTER TABLE ${sql.identifier(versionsTable)} ADD COLUMN version__status VARCHAR
|
|
`
|
|
});
|
|
// 2. Copy status from default locale back to main table
|
|
payload.logger.info({
|
|
msg: `Copying status from default locale (${defaultLocale}) back to main table`
|
|
});
|
|
await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
UPDATE ${sql.identifier(versionsTable)} pv
|
|
SET version__status = pl.version__status
|
|
FROM ${sql.identifier(localesTable)} pl
|
|
WHERE pv.id = pl._parent_id
|
|
AND pl._locale = ${defaultLocale}
|
|
`
|
|
});
|
|
// 3. Check if there are other localized fields besides version__status
|
|
const columnCheckResult = await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
SELECT COUNT(*) as count
|
|
FROM information_schema.columns
|
|
WHERE table_schema = 'public'
|
|
AND table_name = ${localesTable}
|
|
AND column_name NOT IN ('id', '_locale', '_parent_id', 'version__status')
|
|
`
|
|
});
|
|
const hasOtherLocalizedFields = Number(columnCheckResult.rows[0]?.count) > 0;
|
|
if (!hasOtherLocalizedFields) {
|
|
// SCENARIO 1 ROLLBACK: No other localized fields, drop entire table
|
|
payload.logger.info({
|
|
msg: `Dropping entire locales table: ${localesTable}`
|
|
});
|
|
await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`DROP TABLE ${sql.identifier(localesTable)} CASCADE`
|
|
});
|
|
} else {
|
|
// SCENARIO 2 ROLLBACK: Other localized fields exist, just drop version__status column
|
|
payload.logger.info({
|
|
msg: `Dropping version__status column from ${localesTable}`
|
|
});
|
|
await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
ALTER TABLE ${sql.identifier(localesTable)} DROP COLUMN version__status
|
|
`
|
|
});
|
|
}
|
|
// 4. Restore _status to main collection/global table if it was dropped
|
|
const mainTable = collectionSlug ? toSnakeCase(collectionSlug) : toSnakeCase(globalSlug);
|
|
const mainLocalesTable = `${mainTable}_locales`;
|
|
// Check if _status exists in the main table
|
|
const statusInMainTableCheck = await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
SELECT EXISTS (
|
|
SELECT FROM information_schema.columns
|
|
WHERE table_schema = 'public'
|
|
AND table_name = ${mainTable}
|
|
AND column_name = '_status'
|
|
) as exists
|
|
`
|
|
});
|
|
if (!statusInMainTableCheck.rows[0]?.exists) {
|
|
// _status column doesn't exist in main table, need to restore it
|
|
// Check if main collection/global has a locales table
|
|
const mainLocalesTableCheck = await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
SELECT EXISTS (
|
|
SELECT FROM information_schema.tables
|
|
WHERE table_schema = 'public'
|
|
AND table_name = ${mainLocalesTable}
|
|
) as exists
|
|
`
|
|
});
|
|
if (mainLocalesTableCheck.rows[0]?.exists) {
|
|
// Locales table exists - check if _status is there
|
|
const statusInLocalesCheck = await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
SELECT EXISTS (
|
|
SELECT FROM information_schema.columns
|
|
WHERE table_schema = 'public'
|
|
AND table_name = ${mainLocalesTable}
|
|
AND column_name = '_status'
|
|
) as exists
|
|
`
|
|
});
|
|
if (statusInLocalesCheck.rows[0]?.exists) {
|
|
// Add _status back to main table
|
|
payload.logger.info({
|
|
msg: `Restoring _status column to ${mainTable}`
|
|
});
|
|
await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
ALTER TABLE ${sql.identifier(mainTable)} ADD COLUMN _status VARCHAR
|
|
`
|
|
});
|
|
// Copy status from default locale back to main table
|
|
await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
UPDATE ${sql.identifier(mainTable)} m
|
|
SET _status = l._status
|
|
FROM ${sql.identifier(mainLocalesTable)} l
|
|
WHERE m.id = l._parent_id
|
|
AND l._locale = ${defaultLocale}
|
|
`
|
|
});
|
|
// Drop _status from locales table
|
|
payload.logger.info({
|
|
msg: `Dropping _status column from ${mainLocalesTable}`
|
|
});
|
|
await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
ALTER TABLE ${sql.identifier(mainLocalesTable)} DROP COLUMN _status
|
|
`
|
|
});
|
|
}
|
|
} else {
|
|
// No locales table exists - this means collection/global has no localized fields
|
|
// Just add _status back to main table with default values
|
|
payload.logger.info({
|
|
msg: `Restoring _status column to ${mainTable} (no locales table exists)`
|
|
});
|
|
await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
ALTER TABLE ${sql.identifier(mainTable)} ADD COLUMN _status VARCHAR
|
|
`
|
|
});
|
|
// Set default status based on latest version status for each document
|
|
// Get all documents in the collection
|
|
const documents = await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
SELECT DISTINCT id
|
|
FROM ${sql.identifier(mainTable)}
|
|
`
|
|
});
|
|
for (const doc of documents.rows){
|
|
// Get latest version status for this document
|
|
const latestVersionStatus = await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
SELECT version__status
|
|
FROM ${sql.identifier(versionsTable)}
|
|
WHERE parent_id = ${doc.id}
|
|
ORDER BY created_at DESC
|
|
LIMIT 1
|
|
`
|
|
});
|
|
const status = latestVersionStatus.rows[0]?.version__status || 'draft';
|
|
await db.execute({
|
|
drizzle: db.drizzle,
|
|
sql: sql`
|
|
UPDATE ${sql.identifier(mainTable)}
|
|
SET _status = ${status}
|
|
WHERE id = ${doc.id}
|
|
`
|
|
});
|
|
}
|
|
payload.logger.info({
|
|
msg: `Restored _status for ${documents.rows.length} documents`
|
|
});
|
|
}
|
|
}
|
|
payload.logger.info({
|
|
msg: 'Rollback completed successfully'
|
|
});
|
|
}
|
|
|
|
//# sourceMappingURL=down.js.map |